summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_updgrp_adv.c62
-rw-r--r--bgpd/bgp_updgrp_packet.c2
-rw-r--r--isisd/isis_lsp.c95
-rw-r--r--isisd/isis_lsp.h7
-rw-r--r--isisd/isis_spf.c11
-rw-r--r--isisd/isis_spf.h6
-rw-r--r--isisd/isisd.c7
-rw-r--r--isisd/isisd.h8
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)