struct timeval * ccnl_run_events(void) { static struct timeval now; long usec; ccnl_get_timeval(&now); //DEBUGMSG(1, "ccnl_run_events now: %ld:%ld\n", now.tv_sec, now.tv_usec); while (eventqueue) { struct ccnl_timer_s *t = eventqueue; usec = timevaldelta(&(t->timeout), &now); if (usec >= 0) { //DEBUGMSG(1, "ccnl_run_events nothing to do: %ld:%ld\n", now.tv_sec, now.tv_usec); now.tv_sec = usec / 1000000; now.tv_usec = usec % 1000000; return &now; } //DEBUGMSG(1, "ccnl_run_events run event handler: %ld:%ld\n", now.tv_sec, now.tv_usec); if (t->fct) { (t->fct)(t->node, t->intarg); } else if (t->fct2) { (t->fct2)(t->aux1, t->aux2); } eventqueue = t->next; ccnl_free(t); } return NULL; }
/** * @brief initializing routing system * @param pointer to count transceiver pids * */ void *ccnl_riot_relay_start(void *arg) { (void) arg; theRelay = calloc(1, sizeof(struct ccnl_relay_s)); ccnl_get_timeval(&theRelay->startup_time); theRelay->riot_pid = sched_active_pid; mutex_init(&theRelay->global_lock); DEBUGMSG(1, "This is ccn-lite-relay, starting at %lu:%lu\n", theRelay->startup_time.tv_sec, theRelay->startup_time.tv_usec); DEBUGMSG(1, " compile time: %s %s\n", __DATE__, __TIME__); DEBUGMSG(1, " max_cache_entries: %d\n", CCNL_DEFAULT_MAX_CACHE_ENTRIES); DEBUGMSG(1, " threshold_prefix: %d\n", CCNL_DEFAULT_THRESHOLD_PREFIX); DEBUGMSG(1, " threshold_aggregate: %d\n", CCNL_DEFAULT_THRESHOLD_AGGREGATE); ccnl_relay_config(theRelay, CCNL_DEFAULT_MAX_CACHE_ENTRIES, CCNL_DEFAULT_THRESHOLD_PREFIX, CCNL_DEFAULT_THRESHOLD_AGGREGATE); theRelay->riot_helper_pid = riot_start_helper_thread(); ccnl_io_loop(theRelay); DEBUGMSG(1, "ioloop stopped\n"); while (eventqueue) { ccnl_rem_timer(eventqueue); } ccnl_core_cleanup(theRelay); mutex_lock(&theRelay->stop_lock); ccnl_free(theRelay); return NULL; }
struct ccnl_interest_s * ccnl_interest_new(struct ccnl_relay_s *ccnl, struct ccnl_face_s *from, struct ccnl_buf_s **pkt, struct ccnl_prefix_s **prefix, int minsuffix, int maxsuffix, struct ccnl_buf_s **ppkd) { struct ccnl_interest_s *i = (struct ccnl_interest_s *) ccnl_calloc(1, sizeof(struct ccnl_interest_s)); DEBUGMSG(99, "ccnl_new_interest\n"); if (!i) { puts("can't get more memory from malloc, dropping ccn msg..."); return NULL; } i->from = from; i->prefix = *prefix; *prefix = 0; i->pkt = *pkt; *pkt = 0; i->ppkd = *ppkd; *ppkd = 0; i->minsuffix = minsuffix; i->maxsuffix = maxsuffix; ccnl_get_timeval(&i->last_used); DBL_LINKED_LIST_ADD(ccnl->pit, i); return i; }
static cf_time ccnl_cf_now() { struct timeval now; ccnl_get_timeval(&now); return ((cf_time)now.tv_sec) * 1000000000 + now.tv_usec * 1000; }
struct ccnl_sched_s* ccnl_sched_pktrate_new(void (cts)(void *aux1, void *aux2), struct ccnl_relay_s *ccnl, int inter_packet_interval) { struct ccnl_sched_s *s; DEBUGMSG(TRACE, "ccnl_sched_pktrate_new()\n"); s = (struct ccnl_sched_s*) ccnl_calloc(1, sizeof(struct ccnl_sched_s)); if (!s) return NULL; s->mode = 1; s->cts = cts; s->ccnl = ccnl; #ifdef USE_CHEMFLOW if (cfnl_sched_create_default_rnet(s, inter_packet_interval)) { ccnl_free(s); return NULL; } #else ccnl_get_timeval(&(s->nextTX)); s->ipi = inter_packet_interval; #endif return s; }
void * ccnl_set_timer(int usec, void (*fct)(void *aux1, void *aux2), void *aux1, void *aux2) { struct ccnl_timer_s *t, **pp; static int handlercnt; t = (struct ccnl_timer_s *) ccnl_calloc(1, sizeof(*t)); if (!t) { return 0; } t->fct2 = fct; ccnl_get_timeval(&t->timeout); usec += t->timeout.tv_usec; t->timeout.tv_sec += usec / 1000000; t->timeout.tv_usec = usec % 1000000; t->aux1 = aux1; t->aux2 = aux2; for (pp = &eventqueue; ; pp = &((*pp)->next)) { if (!*pp || (*pp)->timeout.tv_sec > t->timeout.tv_sec || ((*pp)->timeout.tv_sec == t->timeout.tv_sec && (*pp)->timeout.tv_usec > t->timeout.tv_usec)) { t->next = *pp; t->handler = handlercnt++; *pp = t; return t; } } return NULL; // ? }
void ccnl_do_ageing(void *ptr, void *dummy) { (void) dummy; /* unused */ struct ccnl_relay_s *relay = (struct ccnl_relay_s *) ptr; struct ccnl_interest_s *i = relay->pit; struct ccnl_content_s *c = relay->contents; struct ccnl_face_s *f = relay->faces; struct timeval now; ccnl_get_timeval(&now); //DEBUGMSG(999, "ccnl_do_ageing %ld:%ld\n", now.tv_sec, now.tv_usec); while (i) { if (ccnl_is_timed_out(&now, &i->last_used, CCNL_INTEREST_TIMEOUT_SEC, CCNL_INTEREST_TIMEOUT_USEC)) { if (i->from->ifndx == RIOT_MSG_IDX) { /* this interest was requested by an app from this node */ /* inform this app about this problem */ riot_send_nack(i->from->faceid); } i = ccnl_interest_remove(relay, i); } else { i = i->next; } } while (c) { if (ccnl_is_timed_out(&now, &c->last_used, CCNL_CONTENT_TIMEOUT_SEC, CCNL_CONTENT_TIMEOUT_USEC) && !(c->flags & CCNL_CONTENT_FLAGS_STATIC)) { c = ccnl_content_remove(relay, c); } else { c = c->next; } } while (f) { if (!(f->flags & CCNL_FACE_FLAGS_STATIC) && ccnl_is_timed_out(&now, &f->last_used, CCNL_FACE_TIMEOUT_SEC, CCNL_FACE_TIMEOUT_USEC)) { f = ccnl_face_remove(relay, f); } else { f = f->next; } } struct ccnl_forward_s *fwd = relay->fib; while (fwd) { if (!(fwd->flags & CCNL_FORWARD_FLAGS_STATIC) && ccnl_is_timed_out(&now, &fwd->last_used, CCNL_FWD_TIMEOUT_SEC, CCNL_FWD_TIMEOUT_USEC)) { fwd = ccnl_forward_remove(relay, fwd); } else { fwd = fwd->next; } } }
struct ccnl_content_s * ccnl_content_new(struct ccnl_relay_s *ccnl, struct ccnl_buf_s **pkt, struct ccnl_prefix_s **prefix, struct ccnl_buf_s **ppkd, unsigned char *content, int contlen) { (void) ccnl; /* unused */ struct ccnl_content_s *c; // DEBUGMSG(99, "ccnl_content_new <%s>\n", // prefix == NULL ? NULL : ccnl_prefix_to_path(*prefix)); c = (struct ccnl_content_s *) ccnl_calloc(1, sizeof(struct ccnl_content_s)); if (!c) { return NULL; } ccnl_get_timeval(&c->last_used); c->content = content; c->contentlen = contlen; c->pkt = *pkt; *pkt = NULL; c->name = *prefix; *prefix = NULL; if (ppkd) { c->ppkd = *ppkd; *ppkd = NULL; } return c; }
static int current_time(void) { struct timeval tv; ccnl_get_timeval(&tv); return tv.tv_sec; }
void ccnl_interest_propagate(struct ccnl_relay_s *ccnl, struct ccnl_interest_s *i) { struct ccnl_forward_s *fwd; DEBUGMSG(99, "ccnl_interest_propagate\n"); // CONFORM: "A node MUST implement some strategy rule, even if it is only to // transmit an Interest Message on all listed dest faces in sequence." // CCNL strategy: we forward on all FWD entries with a prefix match int forward_cnt = 0; for (fwd = ccnl->fib; fwd; fwd = fwd->next) { int rc = ccnl_prefix_cmp(fwd->prefix, NULL, i->prefix, CMP_LONGEST); DEBUGMSG(40, " ccnl_interest_propagate, rc=%d/%d\n", rc, fwd->prefix->compcnt); if (rc < fwd->prefix->compcnt) { continue; } DEBUGMSG(40, " ccnl_interest_propagate, fwd==%p\n", (void *) fwd); // suppress forwarding to origin of interest, except wireless if (!i->from || fwd->face != i->from || (i->from->flags & CCNL_FACE_FLAGS_REFLECT)) { i->forwarded_over = fwd; fwd->face->stat.send_interest[i->retries]++; ccnl_get_timeval(&i->last_used); ccnl_face_enqueue(ccnl, fwd->face, buf_dup(i->pkt)); ccnl_get_timeval(&fwd->last_used); forward_cnt++; } } if (forward_cnt == 0) { DEBUGMSG(40, " ccnl_interest_propagate: using broadcast face!\n"); ccnl->ifs[RIOT_TRANS_IDX].broadcast_face->stat.send_interest[i->retries]++; ccnl_get_timeval(&i->last_used); ccnl_face_enqueue(ccnl, ccnl->ifs[RIOT_TRANS_IDX].broadcast_face, buf_dup(i->pkt)); } return; }
void ccnl_sched_CTS_done(struct ccnl_sched_s *s, int cnt, int len) { #ifdef USE_CHEMFLOW cf_time now = ccnl_cf_now(); #else struct timeval now; long since; #endif if (!s) { DEBUGMSG(VERBOSE, "ccnl_sched_CTS_done sched=%p cnt=%d len=%d\n", (void*)s, cnt, len); return; } DEBUGMSG(VERBOSE, "ccnl_sched_CTS_done sched=%p/%d cnt=%d len=%d (mycnt=%d)\n", (void*)s, s->mode, cnt, len, s->cnt); s->cnt -= cnt; if (s->cnt <= 0) return; if (s->mode == 0) { s->cts(s->aux1, s->aux2); return; } #ifdef USE_CHEMFLOW if (CF_OK == cf_queue_dequeue_packet(s->q, 1)) { DEBUGMSG(VERBOSE, " cf_dequeue successful; CTS\n"); cf_queue_update_concentrations(s->q, now); cf_engine_reschedule_and_set_timer(engine, now); s->cts(s->aux1, s->aux2); } #else ccnl_get_timeval(&now); since = timevaldelta(&(s->nextTX), &now); if (since <= 0) { now.tv_sec += s->ipi / 1000000; now.tv_usec += s->ipi % 1000000; memcpy(&(s->nextTX), &now, sizeof(now)); s->cts(s->aux1, s->aux2); return; } DEBUGMSG(VERBOSE, "since=%ld\n", since); // ccnl_set_timer(since, (void(*)(void*,int))signal_cts, ccnl, ifndx); s->pendingTimer = ccnl_set_timer(since, s->cts, s->aux1, s->aux2); s->nextTX.tv_sec += s->ipi / 1000000;; s->nextTX.tv_usec += s->ipi % 1000000;; // s->cts(); #endif }
struct ccnl_nonce_s *ccnl_nonce_new(struct ccnl_buf_s *that) { struct ccnl_nonce_s *n = (struct ccnl_nonce_s *) ccnl_malloc(sizeof(struct ccnl_nonce_s)); n->buf = buf_dup(that); ccnl_get_timeval(&n->created); n->next = NULL; n->prev = NULL; return n; }
// deliver new content c to all clients with (loosely) matching interest, // but only one copy per face // returns: number of forwards int ccnl_content_serve_pending(struct ccnl_relay_s *ccnl, struct ccnl_content_s *c, struct ccnl_face_s *from) { struct ccnl_interest_s *i; struct ccnl_face_s *f; int cnt = 0; DEBUGMSG(99, "ccnl_content_serve_pending\n"); for (f = ccnl->faces; f; f = f->next) { f->flags &= ~CCNL_FACE_FLAGS_SERVED; // reply on a face only once } for (i = ccnl->pit; i;) { struct ccnl_pendint_s *pi; if (!ccnl_i_prefixof_c(i->prefix, i->ppkd, i->minsuffix, i->maxsuffix, c)) { i = i->next; continue; } // CONFORM: "Data MUST only be transmitted in response to // an Interest that matches the Data." for (pi = i->pending; pi; pi = pi->next) { if (pi->face->flags & CCNL_FACE_FLAGS_SERVED) { continue; } if (pi->face == from) { // the existing pending interest is from the same face // as the newly arrived content is...no need to send content back DEBUGMSG(1, " detected looping content, before loop could happen\n"); continue; } pi->face->flags |= CCNL_FACE_FLAGS_SERVED; DEBUGMSG(6, " forwarding content <%s>\n", ccnl_prefix_to_path(c->name)); pi->face->stat.send_content[c->served_cnt % CCNL_MAX_CONTENT_SERVED_STAT]++; ccnl_face_enqueue(ccnl, pi->face, buf_dup(c->pkt)); c->served_cnt++; ccnl_get_timeval(&c->last_used); cnt++; } i = ccnl_interest_remove(ccnl, i); } return cnt; }
void ccnl_sched_RTS(struct ccnl_sched_s *s, int cnt, int len, void *aux1, void *aux2) { #ifdef USE_CHEMFLOW cf_time now = ccnl_cf_now(); #else struct timeval now; long since; #endif if (!s) { DEBUGMSG(VERBOSE, "ccnl_sched_RTS sched=%p len=%d aux1=%p aux2=%p\n", (void*)s, len, (void*)aux1, (void*)aux2); return; } DEBUGMSG(VERBOSE, "ccnl_sched_RTS sched=%p/%d len=%d aux1=%p aux2=%p\n", (void*)s, s->mode, len, (void*)aux1, (void*)aux2); s->cnt += cnt; s->aux1 = aux1; s->aux2 = aux2; if (s->mode == 0) { s->cts(aux1, aux2); return; } #ifdef USE_CHEMFLOW for (; cnt; --cnt) { DEBUGMSG(VERBOSE, " cf_enqueuen"); if (CF_OK == cf_queue_enqueue_packet(s->q, 1)) { cf_queue_update_concentrations(s->q, now); cf_engine_reschedule_and_set_timer(engine, now); } } #else ccnl_get_timeval(&now); since = timevaldelta(&(s->nextTX), &now); if (since <= 0) { now.tv_sec += s->ipi / 1000000; now.tv_usec += s->ipi % 1000000; memcpy(&(s->nextTX), &now, sizeof(now)); s->cts(aux1, aux2); return; } DEBUGMSG(VERBOSE, "since=%ld\n", since); // ccnl_set_timer(since, (void(*)(void*,int))signal_cts, ccnl, ifndx); s->pendingTimer = ccnl_set_timer(since, s->cts, aux1, aux2); s->nextTX.tv_sec += s->ipi / 1000000;; s->nextTX.tv_usec += s->ipi % 1000000;; #endif }
int ccnl_interest_append_pending(struct ccnl_interest_s *i, struct ccnl_face_s *from) { struct ccnl_pendint_s *pi, *last = NULL; DEBUGMSG(99, "ccnl_append_pending\n"); for (pi = i->pending; pi; pi = pi->next) { // check whether already listed if (pi->face == from) { DEBUGMSG(40, " we found a matching interest, updating time\n"); ccnl_get_timeval(&pi->last_used); return 0; } last = pi; } pi = (struct ccnl_pendint_s *) ccnl_calloc(1, sizeof(struct ccnl_pendint_s)); DEBUGMSG(40, " appending a new pendint entry %p\n", (void *) pi); if (!pi) { return -1; } pi->face = from; ccnl_get_timeval(&pi->last_used); if (last) { last->next = pi; } else { i->pending = pi; } return 0; }
double current_time() { struct timeval tv; static time_t start; static time_t start_usec; ccnl_get_timeval(&tv); if (!start) { start = tv.tv_sec; start_usec = tv.tv_usec; } return (double)(tv.tv_sec) - start + ((double)(tv.tv_usec) - start_usec) / 1000000; }
void ccnl_do_nonce_timeout(void *ptr, void *dummy) { (void) dummy; /* unused */ struct ccnl_relay_s *relay = (struct ccnl_relay_s *) ptr; struct timeval now; ccnl_get_timeval(&now); //DEBUGMSG(99, "ccnl_do_nonce_timeout: %lu:%lu\n", now.tv_sec, now.tv_usec); for (struct ccnl_nonce_s *n = relay->nonces; n;) { if (ccnl_is_timed_out(&now, &n->created, CCNL_NONCE_TIMEOUT_SEC, CCNL_NONCE_TIMEOUT_USEC)) { n = ccnl_nonce_remove(relay, n); } else { n = n->next; } } }
struct ccnl_sched_s* ccnl_sched_packetratelimiter_new(int inter_packet_interval, void (*cts)(void *aux1, void *aux2), void *aux1, void *aux2) { struct ccnl_sched_s *s; DEBUGMSG(TRACE, "ccnl_rate:limiter_new()\n"); s = (struct ccnl_sched_s*) ccnl_calloc(1, sizeof(struct ccnl_sched_s)); if (s) { s->cts = cts; s->aux1 = aux1; s->aux2 = aux2; #ifndef USE_CHEMFLOW ccnl_get_timeval(&s->nextTX); s->ipi = inter_packet_interval; #endif } return s; }
char * timestamp(void) { static char ts[30], *cp; struct timeval now; ccnl_get_timeval(&now); sprintf(ts, "%.4lu", (time_t) 100000 * now.tv_sec + now.tv_usec); cp = strchr(ts, '.'); if (!cp) { strcat(ts, ".0000"); } else if (strlen(cp) > 5) { cp[5] = '\0'; } else while (strlen(cp) < 5) { strcat(cp, "0"); } return ts; }
void ccnl_content_learn_name_route(struct ccnl_relay_s *ccnl, struct ccnl_prefix_s *p, struct ccnl_face_s *f, int threshold_prefix, int flags) { /* * we want to insert a new dynamic route in the fib, let's try to aggregate! * for aggregation we ask the fib for a prefix match */ int match_len; struct ccnl_forward_s *fwd = ccn_forward_find_common_prefix_to_aggregate(ccnl, p, &match_len); if (!fwd) { /* there was no prefix match with the user defined creteria. */ /* create a new fib entry */ fwd = ccnl_forward_new(p, f, threshold_prefix, flags); DBL_LINKED_LIST_ADD(ccnl->fib, fwd); DEBUGMSG(999, "ccnl_content_learn_name_route: new route '%s' on face %d learned\n", ccnl_prefix_to_path(fwd->prefix), f->faceid); } else { /* there was a prefix match with the user defined creteria. */ /* if the new entry has shorter prefix */ if (p->compcnt < fwd->prefix->compcnt) { /* we need to aggregate! */ DBL_LINKED_LIST_REMOVE(ccnl->fib, fwd); /* create a new fib entry */ fwd = ccnl_forward_new(p, f, (p->compcnt - match_len), flags); DBL_LINKED_LIST_ADD(ccnl->fib, fwd); DEBUGMSG(999, "ccnl_content_learn_name_route: route '%s' on face %d replaced\n", ccnl_prefix_to_path(fwd->prefix), f->faceid); } else { /* we don't need to do an update, because we know a shorter prefix already */ } } /* refresh fwd entry */ DEBUGMSG(999, "ccnl_content_learn_name_route refresh route '%s' on face %d\n", ccnl_prefix_to_path(fwd->prefix), f->faceid); ccnl_get_timeval(&fwd->last_used); }
struct ccnl_face_s * ccnl_get_face_or_create(struct ccnl_relay_s *ccnl, int ifndx, uint16_t sender_id) { struct ccnl_face_s *f; for (f = ccnl->faces; f; f = f->next) { if (ifndx == f->ifndx && (f->faceid == sender_id)) { DEBUGMSG(1, "face found! ifidx=%d sender_id=%d faceid=%d\n", ifndx, sender_id, f->faceid); ccnl_get_timeval(&f->last_used); return f; } } f = (struct ccnl_face_s *) ccnl_calloc(1, sizeof(struct ccnl_face_s)); if (!f) { return NULL; } f->faceid = sender_id; f->ifndx = ifndx; if (sender_id == RIOT_BROADCAST) { f->flags |= CCNL_FACE_FLAGS_BROADCAST; } if (ifndx >= 0) { if (ccnl->defaultFaceScheduler) f->sched = ccnl->defaultFaceScheduler(ccnl, (void ( *)(void *, void *)) ccnl_face_CTS); if (ccnl->ifs[ifndx].reflect) { f->flags |= CCNL_FACE_FLAGS_REFLECT; } if (ccnl->ifs[ifndx].fwdalli) { f->flags |= CCNL_FACE_FLAGS_FWDALLI; } } f->peer.id = sender_id; #ifdef USE_FRAG if (ifndx == RIOT_TRANS_IDX) { // if newly created face, no fragment policy is defined yet // turning on fragmentation for riot trans dev based faces int flagval = CCNL_FACE_FLAGS_STATIC; f->flags = flagval & (CCNL_FACE_FLAGS_STATIC | CCNL_FACE_FLAGS_REFLECT); if (f->frag) { ccnl_frag_destroy(f->frag); f->frag = NULL; } int mtu = ccnl->ifs[f->ifndx].mtu; f->frag = ccnl_frag_new(CCNL_FRAG_CCNx2013, mtu); //TODO } #endif ccnl_get_timeval(&f->last_used); DBL_LINKED_LIST_ADD(ccnl->faces, f); return f; }