From 6c3d76ce9a00804139ae11f4c8ffeaaf67236bc6 Mon Sep 17 00:00:00 2001 From: Jennifer Richards Date: Thu, 14 Jul 2016 15:54:50 -0400 Subject: [PATCH] Sweep for expired routes. Sweeps every two seconds for now, not yet configurable. --- common/tr_config.c | 9 +++++++++ include/tr_config.h | 1 + include/tr_trp.h | 1 + include/trp_internal.h | 1 + include/trp_rtable.h | 3 +++ tr/tr_trp.c | 17 ++++++++++++++++ trp/trp_rtable.c | 11 ++++++++++ trp/trps.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++- 8 files changed, 96 insertions(+), 1 deletion(-) diff --git a/common/tr_config.c b/common/tr_config.c index 0625790..59fd409 100644 --- a/common/tr_config.c +++ b/common/tr_config.c @@ -96,6 +96,7 @@ static TR_CFG_RC tr_cfg_parse_internal (TR_CFG *trc, json_t *jcfg) { json_t *jlogthres = NULL; json_t *jcfgpoll = NULL; json_t *jcfgsettle = NULL; + json_t *jroutesweep = NULL; if ((!trc) || (!jcfg)) return TR_CFG_BAD_PARAMS; @@ -163,6 +164,14 @@ static TR_CFG_RC tr_cfg_parse_internal (TR_CFG *trc, json_t *jcfg) { return TR_CFG_NOPARSE; } } + if (NULL != (jroutesweep = json_object_get(jint, "route_sweep_interval"))) { + if (json_is_number(jroutesweep)) { + trc->internal->route_sweep_interval = json_integer_value(jroutesweep); + } else { + tr_debug("tr_cfg_parse_internal: Parsing error, route_sweep_interval is not a number."); + return TR_CFG_NOPARSE; + } + } if (NULL != (jlog = json_object_get(jint, "logging"))) { if (NULL != (jlogthres = json_object_get(jlog, "log_threshold"))) { diff --git a/include/tr_config.h b/include/tr_config.h index af58db9..737da4b 100644 --- a/include/tr_config.h +++ b/include/tr_config.h @@ -69,6 +69,7 @@ typedef struct tr_cfg_internal { int console_threshold; unsigned int cfg_poll_interval; unsigned int cfg_settle_count; + unsigned int route_sweep_interval; } TR_CFG_INTERNAL; typedef struct tr_cfg { diff --git a/include/tr_trp.h b/include/tr_trp.h index 66222d3..7b12672 100644 --- a/include/tr_trp.h +++ b/include/tr_trp.h @@ -12,6 +12,7 @@ typedef struct tr_trps_events { struct tr_socket_event *listen_ev; struct event *mq_ev; + struct event *sweep_ev; } TR_TRPS_EVENTS; /* prototypes */ diff --git a/include/trp_internal.h b/include/trp_internal.h index 5289980..fb2eaef 100644 --- a/include/trp_internal.h +++ b/include/trp_internal.h @@ -162,5 +162,6 @@ TRP_RC trps_handle_tr_msg(TRPS_INSTANCE *trps, TR_MSG *tr_msg); TRP_RENTRY *trps_get_route(TRPS_INSTANCE *trps, TR_NAME *comm, TR_NAME *realm, TR_NAME *peer); TRP_RENTRY *trps_get_selected_route(TRPS_INSTANCE *trps, TR_NAME *comm, TR_NAME *realm); TR_NAME *trps_get_next_hop(TRPS_INSTANCE *trps, TR_NAME *comm, TR_NAME *realm); +TRP_RC trps_sweep_routes(TRPS_INSTANCE *trps); #endif /* TRP_INTERNAL_H */ diff --git a/include/trp_rtable.h b/include/trp_rtable.h index ec3d778..0f6966e 100644 --- a/include/trp_rtable.h +++ b/include/trp_rtable.h @@ -15,6 +15,7 @@ typedef struct trp_rentry { TR_NAME *trust_router; TR_NAME *next_hop; int selected; + unsigned int interval; /* interval from route update */ struct timespec *expiry; } TRP_RENTRY; @@ -52,6 +53,8 @@ void trp_rentry_set_next_hop(TRP_RENTRY *entry, TR_NAME *next_hop); TR_NAME *trp_rentry_get_next_hop(TRP_RENTRY *entry); void trp_rentry_set_selected(TRP_RENTRY *entry, int sel); int trp_rentry_get_selected(TRP_RENTRY *entry); +void trp_rentry_set_interval(TRP_RENTRY *entry, int interval); +int trp_rentry_get_interval(TRP_RENTRY *entry); void trp_rentry_set_expiry(TRP_RENTRY *entry, struct timespec *exp); TRP_RENTRY *trp_rtable_get_selected_entry(TRP_RTABLE *rtbl, TR_NAME *apc, TR_NAME *realm); struct timespec *trp_rentry_get_expiry(TRP_RENTRY *entry); diff --git a/tr/tr_trp.c b/tr/tr_trp.c index ac9f905..492fc5d 100644 --- a/tr/tr_trp.c +++ b/tr/tr_trp.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -195,11 +196,20 @@ static void tr_trps_process_mq(int socket, short event, void *arg) } } +static void tr_trps_sweep(int listener, short event, void *arg) +{ + TRPS_INSTANCE *trps=talloc_get_type_abort(arg, TRPS_INSTANCE); + tr_debug("tr_trps_sweep: sweeping routes"); + trps_sweep_routes(trps); +} + static int tr_trps_events_destructor(void *obj) { TR_TRPS_EVENTS *ev=talloc_get_type_abort(obj, TR_TRPS_EVENTS); if (ev->mq_ev!=NULL) event_free(ev->mq_ev); + if (ev->sweep_ev!=NULL) + event_free(ev->sweep_ev); return 0; } TR_TRPS_EVENTS *tr_trps_events_new(TALLOC_CTX *mem_ctx) @@ -208,6 +218,7 @@ TR_TRPS_EVENTS *tr_trps_events_new(TALLOC_CTX *mem_ctx) if (ev!=NULL) { ev->listen_ev=talloc(ev, struct tr_socket_event); ev->mq_ev=NULL; + ev->sweep_ev=NULL; if (ev->listen_ev==NULL) { talloc_free(ev); ev=NULL; @@ -227,6 +238,7 @@ TRP_RC tr_trps_event_init(struct event_base *base, TALLOC_CTX *tmp_ctx=talloc_new(NULL); struct tr_socket_event *listen_ev=NULL; struct tr_trps_event_cookie *cookie; + struct timeval two_secs={2, 0}; TRP_RC retval=TRP_ERROR; if (trps_ev == NULL) { @@ -280,6 +292,11 @@ TRP_RC tr_trps_event_init(struct event_base *base, (void *)trps); tr_mq_set_notify_cb(trps->mq, tr_trps_mq_cb, trps_ev->mq_ev); + /* now set up the route table sweep timer event */ + trps_ev->sweep_ev=event_new(base, -1, EV_TIMEOUT|EV_PERSIST, tr_trps_sweep, (void *)trps); + /* todo: event_add(trps_ev->sweep_ev, &(cfg_mgr->active->internal->route_sweep_interval)); */ + event_add(trps_ev->sweep_ev, &two_secs); + retval=TRP_SUCCESS; cleanup: diff --git a/trp/trp_rtable.c b/trp/trp_rtable.c index 6cc8e18..20caef7 100644 --- a/trp/trp_rtable.c +++ b/trp/trp_rtable.c @@ -37,6 +37,7 @@ TRP_RENTRY *trp_rentry_new(TALLOC_CTX *mem_ctx) entry->peer=NULL; entry->next_hop=NULL; entry->selected=0; + entry->interval=0; entry->expiry=talloc(entry, struct timespec); if (entry->expiry==NULL) { talloc_free(entry); @@ -123,6 +124,16 @@ int trp_rentry_get_selected(TRP_RENTRY *entry) return entry->selected; } +void trp_rentry_set_interval(TRP_RENTRY *entry, int interval) +{ + entry->interval=interval; +} + +int trp_rentry_get_interval(TRP_RENTRY *entry) +{ + return entry->interval; +} + /* copies incoming value, does not assume responsibility for freeing */ void trp_rentry_set_expiry(TRP_RENTRY *entry, struct timespec *exp) { diff --git a/trp/trps.c b/trp/trps.c index aa6a834..5134645 100644 --- a/trp/trps.c +++ b/trp/trps.c @@ -488,10 +488,11 @@ static TRP_RC trps_accept_update(TRPS_INSTANCE *trps, TRP_INFOREC *rec) * time unset on a new route entry. */ tr_debug("trps_accept_update: accepting route update."); trp_rentry_set_metric(entry, trp_inforec_get_metric(rec)); + trp_rentry_set_interval(entry, trp_inforec_get_interval(rec)); if (!trps_route_retracted(trps, entry)) { tr_debug("trps_accept_update: route not retracted, setting expiry timer."); trp_rentry_set_expiry(entry, trps_compute_expiry(trps, - trp_inforec_get_interval(rec), + trp_rentry_get_interval(entry), trp_rentry_get_expiry(entry))); } return TRP_SUCCESS; @@ -613,3 +614,54 @@ TRP_RC trps_handle_tr_msg(TRPS_INSTANCE *trps, TR_MSG *tr_msg) return TRP_ERROR; } } + +/* true if curtime >= expiry */ +static int trps_expired(struct timespec *expiry, struct timespec *curtime) +{ + return ((curtime->tv_sec > expiry->tv_sec) + || ((curtime->tv_sec == expiry->tv_sec) + &&(curtime->tv_nsec > expiry->tv_nsec))); +} + +/* Sweep for expired routes. For each expired route, if its metric is infinite, the route is flushed. + * If its metric is finite, the metric is set to infinite and the route's expiration time is updated. */ +TRP_RC trps_sweep_routes(TRPS_INSTANCE *trps) +{ + struct timespec sweep_time={0,0}; + TRP_RENTRY **entry=NULL; + size_t n_entry=0; + size_t ii=0; + + /* use a single time for the entire sweep */ + if (0!=clock_gettime(CLOCK_REALTIME, &sweep_time)) { + tr_err("trps_sweep_routes: could not read realtime clock."); + sweep_time.tv_sec=0; + sweep_time.tv_nsec=0; + return TRP_ERROR; + } + + entry=trp_rtable_get_entries(trps->rtable, &n_entry); /* must talloc_free *entry */ + + /* loop over the entries */ + for (ii=0; iirtable, entry[ii]); /* entry[ii] is no longer valid */ + entry[ii]=NULL; + } else { + /* set metric to infinity and reset timer */ + tr_debug("trps_sweep_routes: setting metric to infinity and resetting expiry."); + trp_rentry_set_metric(entry[ii], TRP_METRIC_INFINITY); + trp_rentry_set_expiry(entry[ii], trps_compute_expiry(trps, + trp_rentry_get_interval(entry[ii]), + trp_rentry_get_expiry(entry[ii]))); + } + } + } + + talloc_free(entry); + return TRP_SUCCESS; +} -- 2.1.4