int olsr_process_hysteresis(struct link_entry *entry) { //printf("PROCESSING QUALITY: %f\n", entry->L_link_quality); if (entry->L_link_quality > hhigh) { if (entry->L_link_pending == 1) { struct ipaddr_str buf; OLSR_PRINTF(1, "HYST[%s] link set to NOT pending!\n", olsr_ip_to_string(&buf, &entry->neighbor_iface_addr)); changes_neighborhood = true; } /* Pending = false */ entry->L_link_pending = 0; if (!TIMED_OUT(entry->L_LOST_LINK_time)) changes_neighborhood = true; /* time = now -1 */ entry->L_LOST_LINK_time = now_times - 1; return 1; } if (entry->L_link_quality < hlow) { if (entry->L_link_pending == 0) { struct ipaddr_str buf; OLSR_PRINTF(1, "HYST[%s] link set to pending!\n", olsr_ip_to_string(&buf, &entry->neighbor_iface_addr)); changes_neighborhood = true; } /* Pending = true */ entry->L_link_pending = 1; if (TIMED_OUT(entry->L_LOST_LINK_time)) changes_neighborhood = true; /* Timer = min (L_time, current time + NEIGHB_HOLD_TIME) */ entry->L_LOST_LINK_time = MIN(GET_TIMESTAMP(NEIGHB_HOLD_TIME * MSEC_PER_SEC), entry->link_timer->timer_clock); /* (the link is then considered as lost according to section 8.5 and this may produce a neighbor loss). WTF? */ return -1; } /* *If we get here then: *(HYST_THRESHOLD_LOW <= entry->L_link_quality <= HYST_THRESHOLD_HIGH) */ /* L_link_pending and L_LOST_LINK_time remain unchanged. */ return 0; }
static bool serialize_tc6(struct tc_message *message, struct interface *ifp) { #ifdef DEBUG struct ipaddr_str buf; #endif uint16_t remainsize, curr_size; struct tc_mpr_addr *mprs; union olsr_message *m; struct olsr_tcmsg6 *tc6; struct neigh_info6 *mprsaddr6; bool found = false, partial_sent = false; if ((!message) || (!ifp) || (olsr_cnf->ip_version != AF_INET6)) return false; remainsize = net_outbuffer_bytes_left(ifp); m = (union olsr_message *)msg_buffer; tc6 = &m->v6.message.tc; mprsaddr6 = tc6->neigh; curr_size = OLSR_TC_IPV6_HDRSIZE; /* Send pending packet if not room in buffer */ if (curr_size > remainsize) { net_output(ifp); remainsize = net_outbuffer_bytes_left(ifp); } check_buffspace(curr_size, remainsize, "TC"); /* Fill header */ m->v6.olsr_vtime = ifp->valtimes.tc; m->v6.olsr_msgtype = TC_MESSAGE; m->v6.hopcnt = message->hop_count; m->v6.ttl = message->ttl; m->v6.originator = message->originator.v6; /* Fill TC header */ tc6->ansn = htons(message->ansn); tc6->reserved = 0; /*Looping trough MPR selectors */ for (mprs = message->multipoint_relay_selector_address; mprs != NULL; mprs = mprs->next) { /*If packet is to be chomped */ if ((curr_size + olsr_cnf->ipsize) > remainsize) { /* Only add TC message if it contains data */ if (curr_size > OLSR_TC_IPV6_HDRSIZE) { #ifdef DEBUG OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize); #endif m->v6.olsr_msgsize = htons(curr_size); m->v6.seqno = htons(get_msg_seqno()); net_outbuffer_push(ifp, msg_buffer, curr_size); mprsaddr6 = tc6->neigh; curr_size = OLSR_TC_IPV6_HDRSIZE; found = false; partial_sent = true; } net_output(ifp); remainsize = net_outbuffer_bytes_left(ifp); check_buffspace(curr_size + olsr_cnf->ipsize, remainsize, "TC2"); } found = true; #ifdef DEBUG OLSR_PRINTF(BMSG_DBGLVL, "\t%s\n", olsr_ip_to_string(&buf, &mprs->address)); #endif mprsaddr6->addr = mprs->address.v6; curr_size += olsr_cnf->ipsize; mprsaddr6++; } if (found) { m->v6.olsr_msgsize = htons(curr_size); m->v6.seqno = htons(get_msg_seqno()); net_outbuffer_push(ifp, msg_buffer, curr_size); } else { if ((!partial_sent) && (!TIMED_OUT(send_empty_tc))) { OLSR_PRINTF(1, "TC: Sending empty package\n"); m->v6.olsr_msgsize = htons(curr_size); m->v6.seqno = htons(get_msg_seqno()); net_outbuffer_push(ifp, msg_buffer, curr_size); found = true; } } return found; }
/** * Walk through the timer list and check if any timer is ready to fire. * Callback the provided function with the context pointer. */ static void walk_timers(uint32_t * last_run) { unsigned int total_timers_walked = 0, total_timers_fired = 0; unsigned int wheel_slot_walks = 0; /* * Check the required wheel slots since the last time a timer walk was invoked, * or check *all* the wheel slots, whatever is less work. * The latter is meant as a safety belt if the scheduler falls behind. */ while ((*last_run <= now_times) && (wheel_slot_walks < TIMER_WHEEL_SLOTS)) { struct list_node tmp_head_node; /* keep some statistics */ unsigned int timers_walked = 0, timers_fired = 0; /* Get the hash slot for this clocktick */ struct list_node *const timer_head_node = &timer_wheel[*last_run & TIMER_WHEEL_MASK]; /* Walk all entries hanging off this hash bucket. We treat this basically as a stack * so that we always know if and where the next element is. */ list_head_init(&tmp_head_node); while (!list_is_empty(timer_head_node)) { /* the top element */ struct list_node *const timer_node = timer_head_node->next; struct timer_entry *const timer = list2timer(timer_node); /* * Dequeue and insert to a temporary list. * We do this to avoid loosing our walking context when * multiple timers fire. */ list_remove(timer_node); list_add_after(&tmp_head_node, timer_node); timers_walked++; /* Ready to fire ? */ if (TIMED_OUT(timer->timer_clock)) { OLSR_PRINTF(7, "TIMER: fire %s timer %p, ctx %p, " "at clocktick %u (%s)\n", timer->timer_cookie->ci_name, timer, timer->timer_cb_context, (unsigned int)*last_run, olsr_wallclock_string()); /* This timer is expired, call into the provided callback function */ timer->timer_cb(timer->timer_cb_context); /* Only act on actually running timers */ if (timer->timer_flags & OLSR_TIMER_RUNNING) { /* * Don't restart the periodic timer if the callback function has * stopped the timer. */ if (timer->timer_period) { /* For periodical timers, rehash the random number and restart */ timer->timer_random = random(); olsr_change_timer(timer, timer->timer_period, timer->timer_jitter_pct, OLSR_TIMER_PERIODIC); } else { /* Singleshot timers are stopped */ olsr_stop_timer(timer); } } timers_fired++; } } /* * Now merge the temporary list back to the old bucket. */ list_merge(timer_head_node, &tmp_head_node); /* keep some statistics */ total_timers_walked += timers_walked; total_timers_fired += timers_fired; /* Increment the time slot and wheel slot walk iteration */ (*last_run)++; wheel_slot_walks++; } OLSR_PRINTF(7, "TIMER: processed %4u/%d clockwheel slots, " "timers walked %4u/%u, timers fired %u\n", wheel_slot_walks, TIMER_WHEEL_SLOTS, total_timers_walked, timer_mem_cookie->ci_usage, total_timers_fired); /* * If the scheduler has slipped and we have walked all wheel slots, * reset the last timer run. */ *last_run = now_times; }