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); 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; } } } diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c index 3158da6bfa..34fcf8f8c6 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; @@ -703,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); } @@ -786,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); } @@ -1348,7 +1346,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 +1396,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 +1427,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",