diff options
| -rw-r--r-- | bgpd/bgp_updgrp_adv.c | 62 | ||||
| -rw-r--r-- | bgpd/bgp_updgrp_packet.c | 2 | ||||
| -rw-r--r-- | isisd/isis_lsp.c | 95 | ||||
| -rw-r--r-- | isisd/isis_lsp.h | 7 | ||||
| -rw-r--r-- | isisd/isis_spf.c | 11 | ||||
| -rw-r--r-- | isisd/isis_spf.h | 6 | ||||
| -rw-r--r-- | isisd/isisd.c | 7 | ||||
| -rw-r--r-- | isisd/isisd.h | 8 |
8 files changed, 103 insertions, 95 deletions
diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c index 1f81dad649..81b782c2b0 100644 --- a/bgpd/bgp_updgrp_adv.c +++ b/bgpd/bgp_updgrp_adv.c @@ -664,7 +664,8 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw) { struct bgp *bgp; struct attr attr; - struct bgp_path_info *info, init_info, tmp_info; + struct aspath *aspath; + struct bgp_path_info tmp_info; struct prefix p; struct peer *from; struct bgp_node *rn; @@ -688,59 +689,46 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw) from = bgp->peer_self; bgp_attr_default_set(&attr, BGP_ORIGIN_IGP); + aspath = attr.aspath; + attr.local_pref = bgp->default_local_pref; + memset(&p, 0, sizeof(p)); + p.family = afi2family(afi); + p.prefixlen = 0; + if ((afi == AFI_IP6) || peer_cap_enhe(peer, afi, safi)) { - /* IPv6 global nexthop must be included. - */ + /* IPv6 global nexthop must be included. */ attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL; - /* If the peer is on shared nextwork and - * we have link-local nexthop set it. */ + /* If the peer is on shared nextwork and we have link-local + nexthop set it. */ if (peer->shared_network && !IN6_IS_ADDR_UNSPECIFIED(&peer->nexthop.v6_local)) attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL; } - init_info.attr = &attr; - info = &init_info; - bgp_attr_intern(info->attr); - - memset(&p, 0, sizeof(p)); - p.family = afi2family(afi); - p.prefixlen = 0; if (peer->default_rmap[afi][safi].name) { SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_DEFAULT); for (rn = bgp_table_top(bgp->rib[afi][safi]); rn; rn = bgp_route_next(rn)) { for (ri = rn->info; ri; ri = ri->next) { + struct attr dummy_attr; + + /* Provide dummy so the route-map can't modify + * the attributes */ + bgp_attr_dup(&dummy_attr, ri->attr); tmp_info.peer = ri->peer; - tmp_info.attr = ri->attr; - - /* Reset attributes every time to avoid \ - * unexpected as-path prepends */ - bgp_attr_default_set(tmp_info.attr, - BGP_ORIGIN_IGP); - - if ((afi == AFI_IP6) - || peer_cap_enhe(peer, afi, safi)) { - tmp_info.attr->mp_nexthop_len = - BGP_ATTR_NHLEN_IPV6_GLOBAL; - - if (peer->shared_network - && !IN6_IS_ADDR_UNSPECIFIED( - &peer->nexthop.v6_local)) - tmp_info.attr->mp_nexthop_len = - BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL; - } + tmp_info.attr = &dummy_attr; ret = route_map_apply( peer->default_rmap[afi][safi].map, &rn->p, RMAP_BGP, &tmp_info); - info = &tmp_info; - bgp_attr_intern(info->attr); - + /* The route map might have set attributes. If + * we don't flush them + * here, they will be leaked. */ + bgp_attr_flush(&dummy_attr); if (ret != RMAP_DENYMATCH) break; } @@ -762,13 +750,12 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw) SUBGRP_STATUS_DEFAULT_ORIGINATE)) { if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN)) { - bgp_attr_add_gshut_community(info->attr); + bgp_attr_add_gshut_community(&attr); } SET_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE); - subgroup_default_update_packet(subgrp, info->attr, - from); + subgroup_default_update_packet(subgrp, &attr, from); /* The 'neighbor x.x.x.x default-originate' default will * act as an @@ -788,7 +775,8 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw) BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE); } } - aspath_unintern(&info->attr->aspath); + + aspath_unintern(&aspath); } /* diff --git a/bgpd/bgp_updgrp_packet.c b/bgpd/bgp_updgrp_packet.c index 3950e2f18f..c4fcea948f 100644 --- a/bgpd/bgp_updgrp_packet.c +++ b/bgpd/bgp_updgrp_packet.c @@ -1123,6 +1123,8 @@ void subgroup_default_update_packet(struct update_subgroup *subgrp, snprintf(tx_id_buf, sizeof(tx_id_buf), " with addpath ID %u", BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE); + else + tx_id_buf[0] = '\0'; zlog_debug("u%" PRIu64 ":s%" PRIu64 " send UPDATE %s%s %s", (SUBGRP_UPDGRP(subgrp))->id, subgrp->id, diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c index 558bc4276b..bb090f42ed 100644 --- a/isisd/isis_lsp.c +++ b/isisd/isis_lsp.c @@ -59,8 +59,7 @@ #include "isisd/fabricd.h" #include "isisd/isis_tx_queue.h" -static int lsp_l1_refresh(struct thread *thread); -static int lsp_l2_refresh(struct thread *thread); +static int lsp_refresh(struct thread *thread); static int lsp_l1_refresh_pseudo(struct thread *thread); static int lsp_l2_refresh_pseudo(struct thread *thread); @@ -1251,12 +1250,9 @@ int lsp_generate(struct isis_area *area, int level) THREAD_TIMER_OFF(area->t_lsp_refresh[level - 1]); area->lsp_regenerate_pending[level - 1] = 0; - if (level == IS_LEVEL_1) - thread_add_timer(master, lsp_l1_refresh, area, refresh_time, - &area->t_lsp_refresh[level - 1]); - else if (level == IS_LEVEL_2) - thread_add_timer(master, lsp_l2_refresh, area, refresh_time, - &area->t_lsp_refresh[level - 1]); + thread_add_timer(master, lsp_refresh, + &area->lsp_refresh_arg[level - 1], refresh_time, + &area->t_lsp_refresh[level - 1]); if (isis->debugs & DEBUG_UPDATE_PACKETS) { zlog_debug("ISIS-Upd (%s): Building L%d LSP %s, len %" PRIu16 @@ -1323,12 +1319,9 @@ static int lsp_regenerate(struct isis_area *area, int level) lsp_seqno_update(lsp); refresh_time = lsp_refresh_time(lsp, rem_lifetime); - if (level == IS_LEVEL_1) - thread_add_timer(master, lsp_l1_refresh, area, refresh_time, - &area->t_lsp_refresh[level - 1]); - else if (level == IS_LEVEL_2) - thread_add_timer(master, lsp_l2_refresh, area, refresh_time, - &area->t_lsp_refresh[level - 1]); + thread_add_timer(master, lsp_refresh, + &area->lsp_refresh_arg[level - 1], refresh_time, + &area->t_lsp_refresh[level - 1]); area->lsp_regenerate_pending[level - 1] = 0; if (isis->debugs & DEBUG_UPDATE_PACKETS) { @@ -1350,45 +1343,42 @@ static int lsp_regenerate(struct isis_area *area, int level) /* * Something has changed or periodic refresh -> regenerate LSP */ -static int lsp_l1_refresh(struct thread *thread) +static int lsp_refresh(struct thread *thread) { - struct isis_area *area; + struct lsp_refresh_arg *arg = THREAD_ARG(thread); - area = THREAD_ARG(thread); - assert(area); - - area->t_lsp_refresh[0] = NULL; - area->lsp_regenerate_pending[0] = 0; - - if ((area->is_type & IS_LEVEL_1) == 0) - return ISIS_ERROR; - - sched_debug( - "ISIS (%s): LSP L1 refresh timer expired. Refreshing LSP...", - area->area_tag); - return lsp_regenerate(area, IS_LEVEL_1); -} + assert(arg); -static int lsp_l2_refresh(struct thread *thread) -{ - struct isis_area *area; + struct isis_area *area = arg->area; - area = THREAD_ARG(thread); assert(area); - area->t_lsp_refresh[1] = NULL; - area->lsp_regenerate_pending[1] = 0; + int level = arg->level; - if ((area->is_type & IS_LEVEL_2) == 0) + area->t_lsp_refresh[level - 1] = NULL; + area->lsp_regenerate_pending[level - 1] = 0; + + if ((area->is_type & level) == 0) return ISIS_ERROR; + if (monotime_since(&area->last_lsp_refresh_event[level - 1], NULL) < 50000L) { + sched_debug("ISIS (%s): Still unstable, postpone LSP L%d refresh", + area->area_tag, level); + _lsp_regenerate_schedule(area, level, 0, false, + __func__, __FILE__, __LINE__); + return 0; + } + sched_debug( - "ISIS (%s): LSP L2 refresh timer expired. Refreshing LSP...", - area->area_tag); - return lsp_regenerate(area, IS_LEVEL_2); + "ISIS (%s): LSP L%d refresh timer expired. Refreshing LSP...", + area->area_tag, level); + return lsp_regenerate(area, level); } -int lsp_regenerate_schedule(struct isis_area *area, int level, int all_pseudo) +int _lsp_regenerate_schedule(struct isis_area *area, int level, + int all_pseudo, bool postpone, + const char *func, const char *file, + int line) { struct isis_lsp *lsp; uint8_t id[ISIS_SYS_ID_LEN + 2]; @@ -1402,9 +1392,11 @@ int lsp_regenerate_schedule(struct isis_area *area, int level, int all_pseudo) return ISIS_ERROR; sched_debug( - "ISIS (%s): Scheduling regeneration of %s LSPs, %sincluding PSNs", + "ISIS (%s): Scheduling regeneration of %s LSPs, %sincluding PSNs" + " Caller: %s %s:%d", area->area_tag, circuit_t2string(level), - all_pseudo ? "" : "not "); + all_pseudo ? "" : "not ", + func, file, line); memcpy(id, isis->sysid, ISIS_SYS_ID_LEN); LSP_PSEUDO_ID(id) = LSP_FRAGMENT(id) = 0; @@ -1414,6 +1406,10 @@ int lsp_regenerate_schedule(struct isis_area *area, int level, int all_pseudo) if (!((level & lvl) && (area->is_type & lvl))) continue; + if (postpone) { + monotime(&area->last_lsp_refresh_event[lvl - 1]); + } + sched_debug( "ISIS (%s): Checking whether L%d needs to be scheduled", area->area_tag, lvl); @@ -1468,15 +1464,10 @@ int lsp_regenerate_schedule(struct isis_area *area, int level, int all_pseudo) } area->lsp_regenerate_pending[lvl - 1] = 1; - if (lvl == IS_LEVEL_1) { - thread_add_timer_msec(master, lsp_l1_refresh, area, - timeout, - &area->t_lsp_refresh[lvl - 1]); - } else if (lvl == IS_LEVEL_2) { - thread_add_timer_msec(master, lsp_l2_refresh, area, - timeout, - &area->t_lsp_refresh[lvl - 1]); - } + thread_add_timer_msec(master, lsp_refresh, + &area->lsp_refresh_arg[lvl - 1], + timeout, + &area->t_lsp_refresh[lvl - 1]); } if (all_pseudo) { diff --git a/isisd/isis_lsp.h b/isisd/isis_lsp.h index 4beee10081..2b45e6994c 100644 --- a/isisd/isis_lsp.h +++ b/isisd/isis_lsp.h @@ -54,7 +54,12 @@ void lsp_db_destroy(dict_t *lspdb); int lsp_tick(struct thread *thread); int lsp_generate(struct isis_area *area, int level); -int lsp_regenerate_schedule(struct isis_area *area, int level, int all_pseudo); +#define lsp_regenerate_schedule(area, level, all_pseudo) \ + _lsp_regenerate_schedule((area), (level), (all_pseudo), true, \ + __func__, __FILE__, __LINE__) +int _lsp_regenerate_schedule(struct isis_area *area, int level, + int all_pseudo, bool postpone, + const char *func, const char *file, int line); int lsp_generate_pseudo(struct isis_circuit *circuit, int level); int lsp_regenerate_schedule_pseudo(struct isis_circuit *circuit, int level); diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c index 1440a3becf..1c4ca249ee 100644 --- a/isisd/isis_spf.c +++ b/isisd/isis_spf.c @@ -1248,7 +1248,8 @@ static struct isis_spf_run *isis_run_spf_arg(struct isis_area *area, int level) return run; } -int isis_spf_schedule(struct isis_area *area, int level) +int _isis_spf_schedule(struct isis_area *area, int level, + const char *func, const char *file, int line) { struct isis_spftree *spftree = area->spftree[SPFTREE_IPV4][level - 1]; time_t now = monotime(NULL); @@ -1257,10 +1258,12 @@ int isis_spf_schedule(struct isis_area *area, int level) assert(diff >= 0); assert(area->is_type & level); - if (isis->debugs & DEBUG_SPF_EVENTS) + if (isis->debugs & DEBUG_SPF_EVENTS) { zlog_debug( - "ISIS-Spf (%s) L%d SPF schedule called, lastrun %d sec ago", - area->area_tag, level, diff); + "ISIS-Spf (%s) L%d SPF schedule called, lastrun %d sec ago" + " Caller: %s %s:%d", + area->area_tag, level, diff, func, file, line); + } if (area->spf_delay_ietf[level - 1]) { /* Need to call schedule function also if spf delay is running diff --git a/isisd/isis_spf.h b/isisd/isis_spf.h index f4db98cfed..8bf9c9978a 100644 --- a/isisd/isis_spf.h +++ b/isisd/isis_spf.h @@ -34,7 +34,11 @@ void isis_spftree_del(struct isis_spftree *spftree); void spftree_area_init(struct isis_area *area); void spftree_area_del(struct isis_area *area); void spftree_area_adj_del(struct isis_area *area, struct isis_adjacency *adj); -int isis_spf_schedule(struct isis_area *area, int level); +#define isis_spf_schedule(area, level) \ + _isis_spf_schedule((area), (level), __func__, \ + __FILE__, __LINE__) +int _isis_spf_schedule(struct isis_area *area, int level, + const char *func, const char *file, int line); void isis_spf_cmds_init(void); void isis_spf_print(struct isis_spftree *spftree, struct vty *vty); struct isis_spftree *isis_run_hopcount_spf(struct isis_area *area, diff --git a/isisd/isisd.c b/isisd/isisd.c index 94e6a63855..54bdbf3eb3 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -160,6 +160,13 @@ struct isis_area *isis_area_create(const char *area_tag) if (fabricd) area->fabricd = fabricd_new(area); + + area->lsp_refresh_arg[0].area = area; + area->lsp_refresh_arg[0].level = IS_LEVEL_1; + area->lsp_refresh_arg[1].area = area; + area->lsp_refresh_arg[1].level = IS_LEVEL_2; + + QOBJ_REG(area, isis_area); return area; diff --git a/isisd/isisd.h b/isisd/isisd.h index 7572f55174..51b359aad4 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -90,6 +90,11 @@ enum spf_tree_id { SPFTREE_COUNT }; +struct lsp_refresh_arg { + struct isis_area *area; + int level; +}; + struct isis_area { struct isis *isis; /* back pointer */ dict_t *lspdb[ISIS_LEVELS]; /* link-state dbs */ @@ -100,6 +105,7 @@ struct isis_area { struct flags flags; struct thread *t_tick; /* LSP walker */ struct thread *t_lsp_refresh[ISIS_LEVELS]; + struct timeval last_lsp_refresh_event[ISIS_LEVELS]; /* t_lsp_refresh is used in two ways: * a) regular refresh of LSPs * b) (possibly throttled) updates to LSPs @@ -160,6 +166,8 @@ struct isis_area { parameters*/ struct thread *spf_timer[ISIS_LEVELS]; + struct lsp_refresh_arg lsp_refresh_arg[ISIS_LEVELS]; + QOBJ_FIELDS }; DECLARE_QOBJ_TYPE(isis_area) |
