From 74361f41d9bbceedc511d8a086ad274a456d6b49 Mon Sep 17 00:00:00 2001 From: Christian Franke Date: Sat, 23 Sep 2017 19:27:29 +0200 Subject: [PATCH 1/4] isisd: use only one IP of neighbor as nexthop There is no point in building a multipath route via one neighbor if there is only one link to the neighbor, but the neighbor has multiple IPs on that link. So only create one nexthop per link. Signed-off-by: Christian Franke --- isisd/isis_route.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/isisd/isis_route.c b/isisd/isis_route.c index 267e72002f..ff17572ef9 100644 --- a/isisd/isis_route.c +++ b/isisd/isis_route.c @@ -208,9 +208,6 @@ static void adjinfo2nexthop(struct list *nexthops, struct isis_adjacency *adj) { struct isis_nexthop *nh; - if (!adj->ipv4_address_count) - return; - for (unsigned int i = 0; i < adj->ipv4_address_count; i++) { struct in_addr *ipv4_addr = &adj->ipv4_addresses[i]; if (!nexthoplookup(nexthops, ipv4_addr, @@ -219,6 +216,7 @@ static void adjinfo2nexthop(struct list *nexthops, struct isis_adjacency *adj) ipv4_addr, adj->circuit->interface->ifindex); nh->router_address = adj->router_address; listnode_add(nexthops, nh); + return; } } } @@ -227,9 +225,6 @@ static void adjinfo2nexthop6(struct list *nexthops6, struct isis_adjacency *adj) { struct isis_nexthop6 *nh6; - if (!adj->ipv6_address_count) - return; - for (unsigned int i = 0; i < adj->ipv6_address_count; i++) { struct in6_addr *ipv6_addr = &adj->ipv6_addresses[i]; if (!nexthop6lookup(nexthops6, ipv6_addr, @@ -238,6 +233,7 @@ static void adjinfo2nexthop6(struct list *nexthops6, struct isis_adjacency *adj) ipv6_addr, adj->circuit->interface->ifindex); nh6->router_address6 = adj->router_address6; listnode_add(nexthops6, nh6); + return; } } } From 3dca3c8c483e0da21193141e0d6f00f5ec530b62 Mon Sep 17 00:00:00 2001 From: Christian Franke Date: Sat, 23 Sep 2017 19:28:48 +0200 Subject: [PATCH 2/4] isisd: always trigger spf run asynchronously isis_spf_schedule gets called in states where an immediate spf run will lead to crashes, e.g. from lsp_destroy. Delay the spf execution until the event calling isis_spf_schedule has run to completion to avoid this. Signed-off-by: Christian Franke --- isisd/isis_spf.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c index 3158da6bfa..9c51457e35 100644 --- a/isisd/isis_spf.c +++ b/isisd/isis_spf.c @@ -278,7 +278,8 @@ struct isis_spftree { struct isis_vertex_queue tents; /* TENT */ struct isis_area *area; /* back pointer to area */ unsigned int runcount; /* number of runs since uptime */ - time_t last_run_timestamp; /* last run timestamp for scheduling */ + time_t last_run_timestamp; /* last run timestamp as wall time for display */ + time_t last_run_monotime; /* last run as monotime for scheduling */ time_t last_run_duration; /* last run duration in msec */ uint16_t mtid; @@ -475,6 +476,7 @@ struct isis_spftree *isis_spftree_new(struct isis_area *area) isis_vertex_queue_init(&tree->paths, "IS-IS SPF paths", false); tree->area = area; tree->last_run_timestamp = 0; + tree->last_run_monotime = 0; tree->last_run_duration = 0; tree->runcount = 0; return tree; @@ -1348,7 +1350,7 @@ out: isis_route_validate(area); spftree->runcount++; spftree->last_run_timestamp = time(NULL); - monotime(&time_now); + spftree->last_run_monotime = monotime(&time_now); end_time = time_now.tv_sec; end_time = (end_time * 1000000) + time_now.tv_usec; spftree->last_run_duration = end_time - start_time; @@ -1398,8 +1400,8 @@ static struct isis_spf_run *isis_run_spf_arg(struct isis_area *area, int level) int isis_spf_schedule(struct isis_area *area, int level) { struct isis_spftree *spftree = area->spftree[level - 1]; - time_t now = time(NULL); - int diff = now - spftree->last_run_timestamp; + time_t now = monotime(NULL); + int diff = now - spftree->last_run_monotime; assert(diff >= 0); assert(area->is_type & level); @@ -1429,22 +1431,16 @@ int isis_spf_schedule(struct isis_area *area, int level) return ISIS_OK; /* wait configured min_spf_interval before doing the SPF */ + long timer; if (diff >= area->min_spf_interval[level - 1]) { - int retval = ISIS_OK; - - if (area->ip_circuits) - retval = - isis_run_spf(area, level, AF_INET, isis->sysid); - if (area->ipv6_circuits) - retval = isis_run_spf(area, level, AF_INET6, - isis->sysid); - - return retval; + /* Last run is more than min interval ago, schedule immediate run */ + timer = 0; + } else { + timer = area->min_spf_interval[level - 1] - diff; } thread_add_timer(master, isis_run_spf_cb, isis_run_spf_arg(area, level), - area->min_spf_interval[level - 1] - diff, - &area->spf_timer[level - 1]); + timer, &area->spf_timer[level - 1]); if (isis->debugs & DEBUG_SPF_EVENTS) zlog_debug("ISIS-Spf (%s) L%d SPF scheduled %d sec from now", From 05278b9378e172ac2757da71302e3481c562797b Mon Sep 17 00:00:00 2001 From: Christian Franke Date: Sat, 23 Sep 2017 19:32:12 +0200 Subject: [PATCH 3/4] isisd: cleanup unused variables Signed-off-by: Christian Franke --- isisd/isis_spf.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c index 9c51457e35..34fcf8f8c6 100644 --- a/isisd/isis_spf.c +++ b/isisd/isis_spf.c @@ -705,8 +705,6 @@ static void isis_spf_add_local(struct isis_spftree *spftree, return; } else { /* vertex->d_N > cost */ /* f) */ - struct listnode *pnode, *pnextnode; - struct isis_vertex *pvertex; isis_vertex_queue_delete(&spftree->tents, vertex); isis_vertex_del(vertex); } @@ -788,8 +786,6 @@ static void process_N(struct isis_spftree *spftree, enum vertextype vtype, return; /* 4) */ } else { - struct listnode *pnode, *pnextnode; - struct isis_vertex *pvertex; isis_vertex_queue_delete(&spftree->tents, vertex); isis_vertex_del(vertex); } From 0b8b6cab5791865b8e2746a99ce8eae3e5402dc4 Mon Sep 17 00:00:00 2001 From: Christian Franke Date: Sat, 23 Sep 2017 20:01:43 +0200 Subject: [PATCH 4/4] isisd: ensure fragments get always linked When we receive or generate new versions of fragments which are curently pending for age out, we need to ensure that they are correctly linked to their lsp0. Signed-off-by: Christian Franke --- isisd/isis_lsp.c | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c index 8e916d8fe0..33c52804e4 100644 --- a/isisd/isis_lsp.c +++ b/isisd/isis_lsp.c @@ -447,6 +447,19 @@ static void lsp_update_data(struct isis_lsp *lsp, struct isis_lsp_hdr *hdr, return; } +static void lsp_link_fragment(struct isis_lsp *lsp, struct isis_lsp *lsp0) +{ + if (!LSP_FRAGMENT(lsp->hdr.lsp_id)) { + /* zero lsp -> create list to store fragments */ + lsp->lspu.frags = list_new(); + } else { + /* fragment -> set backpointer and add to zero lsps list */ + assert(lsp0); + lsp->lspu.zero_lsp = lsp0; + listnode_add(lsp0->lspu.frags, lsp); + } +} + void lsp_update(struct isis_lsp *lsp, struct isis_lsp_hdr *hdr, struct isis_tlvs *tlvs, struct stream *stream, struct isis_area *area, int level, bool confusion) @@ -476,23 +489,21 @@ void lsp_update(struct isis_lsp *lsp, struct isis_lsp_hdr *hdr, put_lsp_hdr(lsp, NULL, true); } + if (LSP_FRAGMENT(lsp->hdr.lsp_id) && !lsp->lspu.zero_lsp) { + uint8_t lspid[ISIS_SYS_ID_LEN + 2]; + struct isis_lsp *lsp0; + + memcpy(lspid, lsp->hdr.lsp_id, ISIS_SYS_ID_LEN + 1); + LSP_FRAGMENT(lspid) = 0; + lsp0 = lsp_search(lspid, area->lspdb[level - 1]); + if (lsp0) + lsp_link_fragment(lsp, lsp0); + } + /* insert the lsp back into the database */ lsp_insert(lsp, area->lspdb[level - 1]); } -static void lsp_link_fragment(struct isis_lsp *lsp, struct isis_lsp *lsp0) -{ - if (!LSP_FRAGMENT(lsp->hdr.lsp_id)) { - /* zero lsp -> create list to store fragments */ - lsp->lspu.frags = list_new(); - } else { - /* fragment -> set backpointer and add to zero lsps list */ - assert(lsp0); - lsp->lspu.zero_lsp = lsp0; - listnode_add(lsp0->lspu.frags, lsp); - } -} - /* creation of LSP directly from what we received */ struct isis_lsp *lsp_new_from_recv(struct isis_lsp_hdr *hdr, struct isis_tlvs *tlvs, @@ -809,6 +820,8 @@ static struct isis_lsp *lsp_next_frag(uint8_t frag_num, struct isis_lsp *lsp0, lsp = lsp_search(frag_id, area->lspdb[level - 1]); if (lsp) { lsp_clear_data(lsp); + if (!lsp->lspu.zero_lsp) + lsp_link_fragment(lsp, lsp0); return lsp; } @@ -1255,6 +1268,7 @@ static int lsp_regenerate(struct isis_area *area, int level) * so that no fragment expires before the lsp is refreshed. */ frag->hdr.rem_lifetime = rem_lifetime; + frag->age_out = ZERO_AGE_LIFETIME; lsp_set_all_srmflags(frag); } lsp_seqno_update(lsp);