static int babel_create_routing_process (void) { assert (babel_routing_process == NULL); /* Allocaste Babel instance. */ babel_routing_process = XCALLOC (MTYPE_BABEL, sizeof (struct babel)); /* Initialize timeouts */ gettime(&babel_now); expiry_time = babel_now.tv_sec + roughly(30); source_expiry_time = babel_now.tv_sec + roughly(300); /* Make socket for Babel protocol. */ protocol_socket = babel_socket(protocol_port); if (protocol_socket < 0) { zlog_err("Couldn't create link local socket: %s", safe_strerror(errno)); goto fail; } /* Threads. */ babel_routing_process->t_read = thread_add_read(master, &babel_read_protocol, NULL, protocol_socket); /* wait a little: zebra will announce interfaces, addresses, routes... */ babel_routing_process->t_update = thread_add_timer_msec(master, babel_init_routing_process, NULL, 200L); schedule_auth_housekeeping(); return 0; fail: XFREE(MTYPE_BABEL, babel_routing_process); babel_routing_process = NULL; return -1; }
/** * @fn eigrp_update_send_GR_thread * * @param[in] thread contains neighbor who would receive Graceful restart * * @return int always 0 * * @par * Function used for sending Graceful restart Update packet * in thread, it is prepared for multiple chunks of packet. * * Uses nbr_gr_packet_type and t_nbr_send_gr from neighbor. */ int eigrp_update_send_GR_thread(struct thread *thread) { struct eigrp_neighbor *nbr; /* get argument from thread */ nbr = THREAD_ARG(thread); /* remove this thread pointer */ nbr->t_nbr_send_gr = NULL; /* if there is packet waiting in queue, * schedule this thread again with small delay */ if(nbr->retrans_queue->count > 0) { nbr->t_nbr_send_gr = thread_add_timer_msec(master, eigrp_update_send_GR_thread, nbr, 10); return 0; } /* send GR EIGRP packet chunk */ eigrp_update_send_GR_part(nbr); /* if it wasn't last chunk, schedule this thread again */ if(nbr->nbr_gr_packet_type != EIGRP_PACKET_PART_LAST) nbr->t_nbr_send_gr = thread_execute(master, eigrp_update_send_GR_thread, nbr, 0); return 0; }
long spf_backoff_schedule(struct spf_backoff *backoff) { long rv = 0; struct timeval now; gettimeofday(&now, NULL); backoff_debug("SPF Back-off(%s) schedule called in state %s", backoff->name, spf_backoff_state2str(backoff->state)); backoff->last_event_time = now; switch (backoff->state) { case SPF_BACKOFF_QUIET: backoff->state = SPF_BACKOFF_SHORT_WAIT; thread_add_timer_msec( backoff->m, spf_backoff_timetolearn_elapsed, backoff, backoff->timetolearn, &backoff->t_timetolearn); thread_add_timer_msec(backoff->m, spf_backoff_holddown_elapsed, backoff, backoff->holddown, &backoff->t_holddown); backoff->first_event_time = now; rv = backoff->init_delay; break; case SPF_BACKOFF_SHORT_WAIT: case SPF_BACKOFF_LONG_WAIT: THREAD_TIMER_OFF(backoff->t_holddown); thread_add_timer_msec(backoff->m, spf_backoff_holddown_elapsed, backoff, backoff->holddown, &backoff->t_holddown); if (backoff->state == SPF_BACKOFF_SHORT_WAIT) rv = backoff->short_delay; else rv = backoff->long_delay; break; } backoff_debug( "SPF Back-off(%s) changed state to %s and returned %ld delay", backoff->name, spf_backoff_state2str(backoff->state), rv); return rv; }
int main(int argc, char **argv) { int i, j; struct thread t; struct timeval **alarms; master = thread_master_create(); log_buf_len = SCHEDULE_TIMERS * (TIMESTR_LEN + 1) + 1; log_buf_pos = 0; log_buf = XMALLOC(MTYPE_TMP, log_buf_len); expected_buf_len = SCHEDULE_TIMERS * (TIMESTR_LEN + 1) + 1; expected_buf_pos = 0; expected_buf = XMALLOC(MTYPE_TMP, expected_buf_len); prng = prng_new(0); timers = XMALLOC(MTYPE_TMP, SCHEDULE_TIMERS * sizeof(*timers)); for (i = 0; i < SCHEDULE_TIMERS; i++) { long interval_msec; int ret; char *arg; /* Schedule timers to expire in 0..5 seconds */ interval_msec = prng_rand(prng) % 5000; arg = XMALLOC(MTYPE_TMP, TIMESTR_LEN + 1); timers[i] = thread_add_timer_msec(master, timer_func, arg, interval_msec); ret = snprintf(arg, TIMESTR_LEN + 1, "%ld.%06ld", timers[i]->u.sands.tv_sec, timers[i]->u.sands.tv_usec); assert(ret > 0); assert((size_t)ret < TIMESTR_LEN + 1); timers_pending++; } for (i = 0; i < REMOVE_TIMERS; i++) { int index; index = prng_rand(prng) % SCHEDULE_TIMERS; if (!timers[index]) continue; XFREE(MTYPE_TMP, timers[index]->arg); thread_cancel(timers[index]); timers[index] = NULL; timers_pending--; } /* We create an array of pointers to the alarm times and sort * that array. That sorted array is used to generate a string * representing the expected "output" of the timers when they * are run. */ j = 0; alarms = XMALLOC(MTYPE_TMP, timers_pending * sizeof(*alarms)); for (i = 0; i < SCHEDULE_TIMERS; i++) { if (!timers[i]) continue; alarms[j++] = &timers[i]->u.sands; } qsort(alarms, j, sizeof(*alarms), cmp_timeval); for (i = 0; i < j; i++) { int ret; ret = snprintf(expected_buf + expected_buf_pos, expected_buf_len - expected_buf_pos, "%ld.%06ld\n", alarms[i]->tv_sec, alarms[i]->tv_usec); assert(ret > 0); expected_buf_pos += ret; assert(expected_buf_pos < expected_buf_len); } XFREE(MTYPE_TMP, alarms); while (thread_fetch(master, &t)) thread_call(&t); return 0; }
int main(int argc, char **argv) { struct prng *prng; int i; struct thread **timers; struct timeval tv_start, tv_lap, tv_stop; unsigned long t_schedule, t_remove; master = thread_master_create(); prng = prng_new(0); timers = calloc(SCHEDULE_TIMERS, sizeof(*timers)); /* create thread structures so they won't be allocated during the * time measurement */ for (i = 0; i < SCHEDULE_TIMERS; i++) timers[i] = thread_add_timer_msec(master, dummy_func, NULL, 0); for (i = 0; i < SCHEDULE_TIMERS; i++) thread_cancel(timers[i]); quagga_gettime(QUAGGA_CLK_MONOTONIC, &tv_start); for (i = 0; i < SCHEDULE_TIMERS; i++) { long interval_msec; interval_msec = prng_rand(prng) % (100 * SCHEDULE_TIMERS); timers[i] = thread_add_timer_msec(master, dummy_func, NULL, interval_msec); } quagga_gettime(QUAGGA_CLK_MONOTONIC, &tv_lap); for (i = 0; i < REMOVE_TIMERS; i++) { int index; index = prng_rand(prng) % SCHEDULE_TIMERS; if (timers[index]) thread_cancel(timers[index]); timers[index] = NULL; } quagga_gettime(QUAGGA_CLK_MONOTONIC, &tv_stop); t_schedule = 1000 * (tv_lap.tv_sec - tv_start.tv_sec); t_schedule += (tv_lap.tv_usec - tv_start.tv_usec) / 1000; t_remove = 1000 * (tv_stop.tv_sec - tv_lap.tv_sec); t_remove += (tv_stop.tv_usec - tv_lap.tv_usec) / 1000; printf("Scheduling %d random timers took %ld.%03ld seconds.\n", SCHEDULE_TIMERS, t_schedule/1000, t_schedule%1000); printf("Removing %d random timers took %ld.%03ld seconds.\n", REMOVE_TIMERS, t_remove/1000, t_remove%1000); fflush(stdout); free(timers); thread_master_free(master); prng_free(prng); return 0; }
/* Add schedule for SPF calculation. To avoid frequenst SPF calc, we set timer for SPF calc. */ void ospf6_spf_schedule (struct ospf6 *ospf6, unsigned int reason) { unsigned long delay, elapsed, ht; struct timeval now, result; ospf6_set_spf_reason(ospf6, reason); if (IS_OSPF6_DEBUG_SPF(PROCESS) || IS_OSPF6_DEBUG_SPF (TIME)) { char rbuf[32]; ospf6_spf_reason_string(reason, rbuf, sizeof(rbuf)); zlog_debug ("SPF: calculation timer scheduled (reason %s)", rbuf); } /* OSPF instance does not exist. */ if (ospf6 == NULL) return; /* SPF calculation timer is already scheduled. */ if (ospf6->t_spf_calc) { if (IS_OSPF6_DEBUG_SPF(PROCESS) || IS_OSPF6_DEBUG_SPF (TIME)) zlog_debug ("SPF: calculation timer is already scheduled: %p", (void *)ospf6->t_spf_calc); return; } /* XXX Monotic timers: we only care about relative time here. */ now = recent_relative_time (); timersub (&now, &ospf6->ts_spf, &result); elapsed = (result.tv_sec * 1000) + (result.tv_usec / 1000); ht = ospf6->spf_holdtime * ospf6->spf_hold_multiplier; if (ht > ospf6->spf_max_holdtime) ht = ospf6->spf_max_holdtime; /* Get SPF calculation delay time. */ if (elapsed < ht) { /* Got an event within the hold time of last SPF. We need to * increase the hold_multiplier, if it's not already at/past * maximum value, and wasn't already increased.. */ if (ht < ospf6->spf_max_holdtime) ospf6->spf_hold_multiplier++; /* always honour the SPF initial delay */ if ( (ht - elapsed) < ospf6->spf_delay) delay = ospf6->spf_delay; else delay = ht - elapsed; } else { /* Event is past required hold-time of last SPF */ delay = ospf6->spf_delay; ospf6->spf_hold_multiplier = 1; } if (IS_OSPF6_DEBUG_SPF(PROCESS) || IS_OSPF6_DEBUG_SPF (TIME)) zlog_debug ("SPF: calculation timer delay = %ld", delay); zlog_info ("SPF: Scheduled in %ld msec", delay); ospf6->t_spf_calc = thread_add_timer_msec (master, ospf6_spf_calculation_thread, ospf6, delay); }
int shim_sisis_read(struct thread * thread) { struct sisis_listener *listener; int sisis_sock; uint16_t length, checksum; int already; u_int ifindex; struct shim_interface * si; struct in6_addr src; char src_buf[INET6_ADDRSTRLEN]; struct in6_addr dst; char dst_buf[INET6_ADDRSTRLEN]; zlog_notice("Reading packet from SISIS connection!"); /* first of all get listener pointer. */ listener = THREAD_ARG (thread); sisis_sock = THREAD_FD (thread); stream_reset(listener->ibuf); if ((already = stream_get_endp(listener->ibuf)) < SVZ_OUT_HEADER_SIZE) { ssize_t nbytes; if (((nbytes = stream_read_try (listener->ibuf, sisis_sock, SVZ_OUT_HEADER_SIZE-already)) == 0) || (nbytes == -1)) { return -1; } if(nbytes != (SVZ_OUT_HEADER_SIZE - already)) { listener->read_thread = thread_add_read (master, shim_sisis_read, listener, sisis_sock); return 0; } already = SVZ_OUT_HEADER_SIZE; } stream_set_getp(listener->ibuf, 0); length = stream_getw(listener->ibuf); checksum = stream_getw(listener->ibuf); if(length > STREAM_SIZE(listener->ibuf)) { struct stream * ns; zlog_warn("message size exceeds buffer size"); ns = stream_new(length); stream_copy(ns, listener->ibuf); stream_free(listener->ibuf); listener->ibuf = ns; } if(already < length) { ssize_t nbytes; if(((nbytes = stream_read_try(listener->ibuf, sisis_sock, length-already)) == 0) || nbytes == -1) { return -1; } if(nbytes != (length-already)) { listener->read_thread = thread_add_read (master, shim_sisis_read, listener, sisis_sock); return 0; } } unsigned int num_of_addrs = number_of_sisis_addrs_for_process_type(SISIS_PTYPE_RIBCOMP_OSPF6); unsigned int num_of_listeners = number_of_listeners(); zlog_notice("Number of addr: %d", num_of_addrs); zlog_notice("Number of listeners: %d", num_of_listeners); pthread_mutex_lock(&bmap_mutex); struct bmap * bmap = bmap_set(checksum); // if we added initially // set timer at which to recycle bmap // if there are no more processes sending data if(bmap->count == 0) { uint16_t * chcksum_ptr = malloc(sizeof(uint16_t)); *chcksum_ptr = checksum; listener->bmap_thread = thread_add_timer_msec (master, svz_sisis_clean_bmap, chcksum_ptr, 100); } bmap->count++; zlog_notice("# of streams %d for checksum %d with length %d", bmap->count, checksum, length); float received_ratio = (float)bmap->count/(float)num_of_addrs; stream_putw(listener->chksum_stream, checksum); if((received_ratio > 1.0/2.0) && !bmap->sent) { if(are_checksums_same()) { zlog_notice("Checksums are all the same"); if(primary_listener == NULL) primary_listener = listener; reset_checksum_streams(); svz_send(listener->ibuf); bmap->sent = 1; } else { zlog_notice("Checksums are not all the same"); stream_fifo_push(listener->dif, listener->ibuf); listener->dif_size++; } } else if(!bmap->sent) { zlog_notice("Not enough processes have sent their data; buffering..."); } else { zlog_notice("Data has already been sent..."); } if((bmap->count == num_of_addrs) && (bmap->sent)) { zlog_notice("Bmap no longer needed, freeing..."); bmap->count = 0; bmap->sent = 0; clear_checksum_streams(checksum); bmap_unset(checksum); } pthread_mutex_unlock(&bmap_mutex); if (sisis_sock < 0) /* Connection was closed during packet processing. */ return -1; /* Register read thread. */ // stream_reset(listener->ibuf); /* prepare for next packet. */ listener->read_thread = thread_add_read (master, shim_sisis_read, listener, sisis_sock); return 0; }