summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_ecommunity.c22
-rw-r--r--bgpd/bgp_fsm.c4
-rw-r--r--bgpd/bgp_fsm.h1
-rw-r--r--bgpd/bgp_mplsvpn.c68
-rw-r--r--bgpd/bgp_nb_config.c7
-rw-r--r--bgpd/bgp_network.c1
-rw-r--r--bgpd/bgp_nht.c37
-rw-r--r--bgpd/bgp_nht.h2
-rw-r--r--bgpd/bgp_route.c14
-rw-r--r--bgpd/bgp_zebra.c3
-rw-r--r--bgpd/bgpd.c2
-rw-r--r--bgpd/bgpd.h1
-rw-r--r--doc/user/ospfd.rst12
-rw-r--r--docker/alpine/Dockerfile2
-rw-r--r--docker/centos-7/Dockerfile2
-rw-r--r--docker/centos-8/Dockerfile2
-rw-r--r--docker/debian/Dockerfile2
-rwxr-xr-xdocker/debian/docker-start4
-rw-r--r--docker/ubuntu18-ci/Dockerfile2
-rw-r--r--docker/ubuntu20-ci/Dockerfile2
-rw-r--r--lib/sigevent.c14
-rw-r--r--lib/zlog.c10
-rw-r--r--ospfd/ospf_abr.c1
-rw-r--r--ospfd/ospf_asbr.c22
-rw-r--r--ospfd/ospf_asbr.h3
-rw-r--r--ospfd/ospf_dump.c17
-rw-r--r--ospfd/ospf_vty.c1
-rw-r--r--ospfd/ospfd.c1
-rw-r--r--ospfd/ospfd.h2
-rw-r--r--zebra/redistribute.c17
30 files changed, 186 insertions, 92 deletions
diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c
index 7f6f61e141..923c9b0d7e 100644
--- a/bgpd/bgp_ecommunity.c
+++ b/bgpd/bgp_ecommunity.c
@@ -1294,15 +1294,19 @@ bool ecommunity_del_val(struct ecommunity *ecom, struct ecommunity_val *eval)
/* Delete the selected value */
ecom->size--;
- p = XMALLOC(MTYPE_ECOMMUNITY_VAL, ecom->size * ecom->unit_size);
- if (c != 0)
- memcpy(p, ecom->val, c * ecom->unit_size);
- if ((ecom->size - c) != 0)
- memcpy(p + (c)*ecom->unit_size,
- ecom->val + (c + 1) * ecom->unit_size,
- (ecom->size - c) * ecom->unit_size);
- XFREE(MTYPE_ECOMMUNITY_VAL, ecom->val);
- ecom->val = p;
+ if (ecom->size) {
+ p = XMALLOC(MTYPE_ECOMMUNITY_VAL, ecom->size * ecom->unit_size);
+ if (c != 0)
+ memcpy(p, ecom->val, c * ecom->unit_size);
+ if ((ecom->size - c) != 0)
+ memcpy(p + (c)*ecom->unit_size,
+ ecom->val + (c + 1) * ecom->unit_size,
+ (ecom->size - c) * ecom->unit_size);
+ XFREE(MTYPE_ECOMMUNITY_VAL, ecom->val);
+ ecom->val = p;
+ } else
+ ecom->val = NULL;
+
return true;
}
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
index 45a856a459..88c44fc984 100644
--- a/bgpd/bgp_fsm.c
+++ b/bgpd/bgp_fsm.c
@@ -101,7 +101,7 @@ static int bgp_delayopen_timer(struct thread *);
static int bgp_start(struct peer *);
/* Register peer with NHT */
-static int bgp_peer_reg_with_nht(struct peer *peer)
+int bgp_peer_reg_with_nht(struct peer *peer)
{
int connected = 0;
@@ -340,6 +340,8 @@ static struct peer *peer_xfer_conn(struct peer *from_peer)
* needed, even on a passive connection.
*/
bgp_peer_reg_with_nht(peer);
+ if (from_peer)
+ bgp_replace_nexthop_by_peer(from_peer, peer);
bgp_reads_on(peer);
bgp_writes_on(peer);
diff --git a/bgpd/bgp_fsm.h b/bgpd/bgp_fsm.h
index bcf697e153..12cbad3eb8 100644
--- a/bgpd/bgp_fsm.h
+++ b/bgpd/bgp_fsm.h
@@ -179,4 +179,5 @@ const char *print_peer_gr_mode(enum peer_mode pr_mode);
const char *print_peer_gr_cmd(enum peer_gr_command pr_gr_cmd);
const char *print_global_gr_mode(enum global_mode gl_mode);
const char *print_global_gr_cmd(enum global_gr_command gl_gr_cmd);
+int bgp_peer_reg_with_nht(struct peer *peer);
#endif /* _QUAGGA_BGP_FSM_H */
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index 62fed931f9..eb68d84c06 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -540,6 +540,17 @@ leak_update(struct bgp *bgp, /* destination bgp instance */
if (bpi) {
bool labelssame = labels_same(bpi, label, num_labels);
+ if (CHECK_FLAG(source_bpi->flags, BGP_PATH_REMOVED)
+ && CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
+ if (debug) {
+ zlog_debug(
+ "%s: ->%s(s_flags: 0x%x b_flags: 0x%x): %pFX: Found route, being removed, not leaking",
+ __func__, bgp->name_pretty,
+ source_bpi->flags, bpi->flags, p);
+ }
+ return NULL;
+ }
+
if (attrhash_cmp(bpi->attr, new_attr) && labelssame
&& !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
@@ -613,6 +624,16 @@ leak_update(struct bgp *bgp, /* destination bgp instance */
return bpi;
}
+ if (CHECK_FLAG(source_bpi->flags, BGP_PATH_REMOVED)) {
+ if (debug) {
+ zlog_debug(
+ "%s: ->%s(s_flags: 0x%x): %pFX: New route, being removed, not leaking",
+ __func__, bgp->name_pretty,
+ source_bpi->flags, p);
+ }
+ return NULL;
+ }
+
new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_IMPORTED, 0,
bgp->peer_self, new_attr, bn);
@@ -1027,6 +1048,8 @@ void vpn_leak_from_vrf_withdraw_all(struct bgp *bgp_vpn, /* to */
if (debug)
zlog_debug("%s: deleting it",
__func__);
+ /* withdraw from leak-to vrfs as well */
+ vpn_leak_to_vrf_withdraw(bgp_vpn, bpi);
bgp_aggregate_decrement(
bgp_vpn,
bgp_dest_get_prefix(bn), bpi,
@@ -1101,7 +1124,10 @@ vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */
if (!ecom_intersect(
bgp_vrf->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_FROMVPN],
path_vpn->attr->ecommunity)) {
-
+ if (debug)
+ zlog_debug(
+ "from vpn to vrf %s, skipping after no intersection of route targets",
+ bgp_vrf->name_pretty);
return;
}
@@ -1532,7 +1558,8 @@ void vpn_handle_router_id_update(struct bgp *bgp, bool withdraw,
bool is_config)
{
afi_t afi;
- int debug;
+ int debug = (BGP_DEBUG(vpn, VPN_LEAK_TO_VRF)
+ | BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF));
char *vname;
const char *export_name;
char buf[RD_ADDRSTRLEN];
@@ -1541,14 +1568,23 @@ void vpn_handle_router_id_update(struct bgp *bgp, bool withdraw,
struct ecommunity *ecom;
vpn_policy_direction_t idir, edir;
+ /*
+ * Router-id change that is not explicitly configured
+ * (a change from zebra, frr restart for example)
+ * should not replace a configured vpn RD/RT.
+ */
+ if (!is_config) {
+ if (debug)
+ zlog_debug("%s: skipping non explicit router-id change",
+ __func__);
+ return;
+ }
+
if (bgp->inst_type != BGP_INSTANCE_TYPE_DEFAULT
&& bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
return;
export_name = bgp->name ? bgp->name : VRF_DEFAULT_NAME;
- debug = (BGP_DEBUG(vpn, VPN_LEAK_TO_VRF) |
- BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF));
-
idir = BGP_VPN_POLICY_DIR_FROMVPN;
edir = BGP_VPN_POLICY_DIR_TOVPN;
@@ -1574,26 +1610,12 @@ void vpn_handle_router_id_update(struct bgp *bgp, bool withdraw,
if (!bgp_import)
continue;
- ecommunity_del_val(bgp_import->vpn_policy[afi].
- rtlist[idir],
+ ecommunity_del_val(
+ bgp_import->vpn_policy[afi]
+ .rtlist[idir],
(struct ecommunity_val *)ecom->val);
-
}
} else {
- /*
- * Router-id changes that are not explicit config
- * changes should not replace configured RD/RT.
- */
- if (!is_config) {
- if (CHECK_FLAG(bgp->vpn_policy[afi].flags,
- BGP_VPN_POLICY_TOVPN_RD_SET)) {
- if (debug)
- zlog_debug("%s: auto router-id change skipped",
- __func__);
- goto postchange;
- }
- }
-
/* New router-id derive auto RD and RT and export
* to VPN
*/
@@ -1624,10 +1646,8 @@ void vpn_handle_router_id_update(struct bgp *bgp, bool withdraw,
else
bgp_import->vpn_policy[afi].rtlist[idir]
= ecommunity_dup(ecom);
-
}
-postchange:
/* Update routes to VPN */
vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN,
afi, bgp_get_default(),
diff --git a/bgpd/bgp_nb_config.c b/bgpd/bgp_nb_config.c
index 5a88bd08d9..94ff362d1a 100644
--- a/bgpd/bgp_nb_config.c
+++ b/bgpd/bgp_nb_config.c
@@ -123,7 +123,12 @@ int bgp_router_create(struct nb_cb_create_args *args)
if (is_new_bgp && inst_type == BGP_INSTANCE_TYPE_DEFAULT)
vpn_leak_postchange_all();
- if (inst_type == BGP_INSTANCE_TYPE_VRF)
+ /*
+ * Check if we need to export to other VRF(s).
+ * Leak the routes to importing bgp vrf instances,
+ * only when new bgp vrf instance is configured.
+ */
+ if (ret != BGP_INSTANCE_EXISTS)
bgp_vpn_leak_export(bgp);
UNSET_FLAG(bgp->vrf_flags, BGP_VRF_AUTO);
diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c
index 4821ce8ddb..8d9024e07c 100644
--- a/bgpd/bgp_network.c
+++ b/bgpd/bgp_network.c
@@ -569,6 +569,7 @@ static int bgp_accept(struct thread *thread)
peer1->doppelganger = peer;
peer->fd = bgp_sock;
vrf_bind(peer->bgp->vrf_id, bgp_sock, bgp_get_bound_name(peer));
+ bgp_peer_reg_with_nht(peer);
bgp_fsm_change_status(peer, Active);
BGP_TIMER_OFF(peer->t_start); /* created in peer_create() */
diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c
index 9c8d7878c5..7ccfae4ba4 100644
--- a/bgpd/bgp_nht.c
+++ b/bgpd/bgp_nht.c
@@ -98,6 +98,31 @@ void bgp_unlink_nexthop(struct bgp_path_info *path)
bgp_unlink_nexthop_check(bnc);
}
+void bgp_replace_nexthop_by_peer(struct peer *from, struct peer *to)
+{
+ struct prefix pp;
+ struct prefix pt;
+ struct bgp_nexthop_cache *bncp, *bnct;
+ afi_t afi;
+
+ if (!sockunion2hostprefix(&from->su, &pp))
+ return;
+
+ afi = family2afi(pp.family);
+ bncp = bnc_find(&from->bgp->nexthop_cache_table[afi], &pp, 0);
+
+ if (!sockunion2hostprefix(&to->su, &pt))
+ return;
+
+ bnct = bnc_find(&to->bgp->nexthop_cache_table[afi], &pt, 0);
+
+ if (bnct != bncp)
+ return;
+
+ if (bnct)
+ bnct->nht_info = to;
+}
+
void bgp_unlink_nexthop_by_peer(struct peer *peer)
{
struct prefix p;
@@ -273,8 +298,16 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
(bgp_path_info_extra_get(pi))->igpmetric = bnc->metric;
else if (pi->extra)
pi->extra->igpmetric = 0;
- } else if (peer)
- bnc->nht_info = (void *)peer; /* NHT peer reference */
+ } else if (peer) {
+ /*
+ * Let's not accidently save the peer data for a peer
+ * we are going to throw away in a second or so.
+ * When we come back around we'll fix up this
+ * data properly in replace_nexthop_by_peer
+ */
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
+ bnc->nht_info = (void *)peer; /* NHT peer reference */
+ }
/*
* We are cheating here. Views have no associated underlying
diff --git a/bgpd/bgp_nht.h b/bgpd/bgp_nht.h
index a1683e1511..9268b225ca 100644
--- a/bgpd/bgp_nht.h
+++ b/bgpd/bgp_nht.h
@@ -51,7 +51,7 @@ extern int bgp_find_or_add_nexthop(struct bgp *bgp_route,
*/
extern void bgp_unlink_nexthop(struct bgp_path_info *p);
void bgp_unlink_nexthop_by_peer(struct peer *peer);
-
+void bgp_replace_nexthop_by_peer(struct peer *from, struct peer *to);
/**
* bgp_delete_connected_nexthop() - Reset the 'peer' pointer for a connected
* nexthop entry. If no paths reference the nexthop, it will be unregistered
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index f56c866de5..49b94e6d7c 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -10260,7 +10260,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
vty_out(vty, "\n");
/* Line 4 display Community */
- if (attr->community) {
+ if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
if (json_paths) {
if (!attr->community->json)
community_str(attr->community, true);
@@ -11620,13 +11620,13 @@ DEFUN (show_ip_bgp_large_community_list,
struct bgp *bgp = NULL;
bool uj = use_json(argc, argv);
- if (uj)
- argc--;
+ if (uj)
+ argc--;
- bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
- &bgp, uj);
- if (!idx)
- return CMD_WARNING;
+ bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
+ &bgp, uj);
+ if (!idx)
+ return CMD_WARNING;
argv_find(argv, argc, "large-community-list", &idx);
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index d1912db01f..ae0bf7fe92 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -1700,9 +1700,6 @@ int bgp_redistribute_set(struct bgp *bgp, afi_t afi, int type,
redist_add_instance(&zclient->mi_redist[afi][type], instance);
} else {
- if (vrf_bitmap_check(zclient->redist[afi][type], bgp->vrf_id))
- return CMD_WARNING;
-
#ifdef ENABLE_BGP_VNC
if (EVPN_ENABLED(bgp) && type == ZEBRA_ROUTE_VNC_DIRECT) {
vnc_export_bgp_enable(
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index d37b9fa48c..bad62f9946 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -3402,7 +3402,7 @@ int bgp_get(struct bgp **bgp_val, as_t *as, const char *name,
return ret;
case BGP_SUCCESS:
if (*bgp_val)
- return ret;
+ return BGP_INSTANCE_EXISTS;
}
bgp = bgp_create(as, name, inst_type);
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 51134dc8c5..f9aa62c682 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -1844,6 +1844,7 @@ enum bgp_clear_type {
/* BGP error codes. */
#define BGP_SUCCESS 0
#define BGP_CREATED 1
+#define BGP_INSTANCE_EXISTS 2
#define BGP_ERR_INVALID_VALUE -1
#define BGP_ERR_INVALID_FLAG -2
#define BGP_ERR_INVALID_AS -3
diff --git a/doc/user/ospfd.rst b/doc/user/ospfd.rst
index 7d1e91dc41..ba9917f72f 100644
--- a/doc/user/ospfd.rst
+++ b/doc/user/ospfd.rst
@@ -299,15 +299,11 @@ To start OSPF process you have to specify the OSPF router.
command can be used when the neighbor state get stuck at some state and
this can be used to recover it from that state.
-.. index:: maximum-paths " CMD_RANGE_STR(1, MULTIPATH_NUM)
-.. clicmd:: maximum-paths " CMD_RANGE_STR(1, MULTIPATH_NUM)
+.. clicmd:: maximum-paths (1-64)
-.. index:: maximum-paths " CMD_RANGE_STR(1, MULTIPATH_NUM)
-.. clicmd:: no maximum-paths
-
- CLI to control maximum number of equal cost paths to reach a specific
- destination.(ECMP)
- Reset CLI, resets the maximum supported multi path to the default value.
+ Use this command to control the maximum number of equal cost paths to reach
+ a specific destination. The upper limit may differ if you change the value
+ of MULTIPATH_NUM during compilation. The default is MULTIPATH_NUM (64).
.. _ospf-area:
diff --git a/docker/alpine/Dockerfile b/docker/alpine/Dockerfile
index 56ac1c0d00..cb2b3eb69e 100644
--- a/docker/alpine/Dockerfile
+++ b/docker/alpine/Dockerfile
@@ -56,4 +56,4 @@ RUN apk add \
--allow-untrusted /pkgs/apk/*/*.apk \
&& rm -rf /pkgs
COPY docker/alpine/docker-start /usr/lib/frr/docker-start
-ENTRYPOINT [ "/sbin/tini", "--", "/usr/lib/frr/docker-start" ]
+CMD [ "/sbin/tini", "--", "/usr/lib/frr/docker-start" ]
diff --git a/docker/centos-7/Dockerfile b/docker/centos-7/Dockerfile
index a92326fcf3..d2ec9f974b 100644
--- a/docker/centos-7/Dockerfile
+++ b/docker/centos-7/Dockerfile
@@ -40,4 +40,4 @@ COPY --from=centos-7-builder /rpmbuild/RPMS/ /pkgs/rpm/
RUN yum install -y /pkgs/rpm/*/*.rpm \
&& rm -rf /pkgs
COPY docker/centos-7/docker-start /usr/lib/frr/docker-start
-ENTRYPOINT [ "/usr/lib/frr/docker-start" ]
+CMD [ "/usr/lib/frr/docker-start" ]
diff --git a/docker/centos-8/Dockerfile b/docker/centos-8/Dockerfile
index 7ed7948927..104501aabc 100644
--- a/docker/centos-8/Dockerfile
+++ b/docker/centos-8/Dockerfile
@@ -41,4 +41,4 @@ COPY --from=centos-8-builder /rpmbuild/RPMS/ /pkgs/rpm/
RUN yum install -y /pkgs/rpm/*/*.rpm \
&& rm -rf /pkgs
COPY docker/centos-8/docker-start /usr/lib/frr/docker-start
-ENTRYPOINT [ "/usr/lib/frr/docker-start" ]
+CMD [ "/usr/lib/frr/docker-start" ]
diff --git a/docker/debian/Dockerfile b/docker/debian/Dockerfile
index 3f830348bc..cc9217f103 100644
--- a/docker/debian/Dockerfile
+++ b/docker/debian/Dockerfile
@@ -17,4 +17,4 @@ RUN apt-get update && \
rm -rf /var/lib/apt/lists/*
ADD docker-start /usr/sbin/docker-start
-ENTRYPOINT ["/usr/sbin/docker-start"]
+CMD ["/usr/sbin/docker-start"]
diff --git a/docker/debian/docker-start b/docker/debian/docker-start
index 43854ab142..a0f31f5ac5 100755
--- a/docker/debian/docker-start
+++ b/docker/debian/docker-start
@@ -7,4 +7,6 @@ set -e
##
chown -R frr:frr /etc/frr
/etc/init.d/frr start
-exec sleep 10000d
+
+# Sleep forever
+exec tail -f /dev/null
diff --git a/docker/ubuntu18-ci/Dockerfile b/docker/ubuntu18-ci/Dockerfile
index ac745c60a8..f6fa910381 100644
--- a/docker/ubuntu18-ci/Dockerfile
+++ b/docker/ubuntu18-ci/Dockerfile
@@ -68,4 +68,4 @@ RUN cd ~/frr && \
RUN cd ~/frr && make check || true
COPY docker/ubuntu18-ci/docker-start /usr/sbin/docker-start
-ENTRYPOINT ["/usr/sbin/docker-start"]
+CMD ["/usr/sbin/docker-start"]
diff --git a/docker/ubuntu20-ci/Dockerfile b/docker/ubuntu20-ci/Dockerfile
index 56657789ee..0b08c2f278 100644
--- a/docker/ubuntu20-ci/Dockerfile
+++ b/docker/ubuntu20-ci/Dockerfile
@@ -71,4 +71,4 @@ RUN cd ~/frr && \
RUN cd ~/frr && make check || true
COPY docker/ubuntu20-ci/docker-start /usr/sbin/docker-start
-ENTRYPOINT ["/usr/sbin/docker-start"]
+CMD ["/usr/sbin/docker-start"]
diff --git a/lib/sigevent.c b/lib/sigevent.c
index 64cec1385d..be7297f264 100644
--- a/lib/sigevent.c
+++ b/lib/sigevent.c
@@ -237,9 +237,12 @@ core_handler(int signo, siginfo_t *siginfo, void *context)
/* make sure we don't hang in here. default for SIGALRM is terminate.
* - if we're in backtrace for more than a second, abort. */
struct sigaction sa_default = {.sa_handler = SIG_DFL};
+
sigaction(SIGALRM, &sa_default, NULL);
+ sigaction(signo, &sa_default, NULL);
sigset_t sigset;
+
sigemptyset(&sigset);
sigaddset(&sigset, SIGALRM);
sigprocmask(SIG_UNBLOCK, &sigset, NULL);
@@ -252,7 +255,16 @@ core_handler(int signo, siginfo_t *siginfo, void *context)
log_memstats(stderr, "core_handler");
zlog_tls_buffer_fini();
- abort();
+
+ /* give the kernel a chance to generate a coredump */
+ sigaddset(&sigset, signo);
+ sigprocmask(SIG_UNBLOCK, &sigset, NULL);
+ raise(signo);
+
+ /* only chance to end up here is if the default action for signo is
+ * something other than kill or coredump the process
+ */
+ _exit(128 + signo);
}
static void trap_default_signals(void)
diff --git a/lib/zlog.c b/lib/zlog.c
index f546709328..24800c6e64 100644
--- a/lib/zlog.c
+++ b/lib/zlog.c
@@ -142,6 +142,7 @@ struct zlog_msg {
struct zlog_tls {
char *mmbuf;
size_t bufpos;
+ bool do_unlink;
size_t nmsgs;
struct zlog_msg msgs[TLS_LOG_MAXMSG];
@@ -266,13 +267,14 @@ void zlog_tls_buffer_init(void)
mmpath, strerror(errno));
goto out_anon_unlink;
}
+ zlog_tls->do_unlink = true;
close(mmfd);
zlog_tls_set(zlog_tls);
return;
out_anon_unlink:
- unlink(mmpath);
+ unlinkat(zlog_tmpdirfd, mmpath, 0);
close(mmfd);
out_anon:
@@ -296,14 +298,16 @@ out_anon:
void zlog_tls_buffer_fini(void)
{
char mmpath[MAXPATHLEN];
+ struct zlog_tls *zlog_tls = zlog_tls_get();
+ bool do_unlink = zlog_tls ? zlog_tls->do_unlink : false;
zlog_tls_buffer_flush();
- zlog_tls_free(zlog_tls_get());
+ zlog_tls_free(zlog_tls);
zlog_tls_set(NULL);
snprintfrr(mmpath, sizeof(mmpath), "logbuf.%ld", zlog_gettid());
- if (unlinkat(zlog_tmpdirfd, mmpath, 0))
+ if (do_unlink && unlinkat(zlog_tmpdirfd, mmpath, 0))
zlog_err("unlink logbuf: %s (%d)", strerror(errno), errno);
}
diff --git a/ospfd/ospf_abr.c b/ospfd/ospf_abr.c
index b5c97eda3c..a6027ee9d1 100644
--- a/ospfd/ospf_abr.c
+++ b/ospfd/ospf_abr.c
@@ -1818,7 +1818,6 @@ static int ospf_abr_task_timer(struct thread *thread)
ospf_abr_task(ospf);
ospf_abr_nssa_task(ospf); /* if nssa-abr, then scan Type-7 LSDB */
- ospf_asbr_nssa_redist_task(ospf);
return 0;
}
diff --git a/ospfd/ospf_asbr.c b/ospfd/ospf_asbr.c
index 0b4e5d7762..6d80725ae6 100644
--- a/ospfd/ospf_asbr.c
+++ b/ospfd/ospf_asbr.c
@@ -277,10 +277,16 @@ void ospf_asbr_status_update(struct ospf *ospf, uint8_t status)
/* If there's redistribution configured, we need to refresh external
* LSAs in order to install Type-7 and flood to all NSSA Areas
*/
-void ospf_asbr_nssa_redist_task(struct ospf *ospf)
+static int ospf_asbr_nssa_redist_update_timer(struct thread *thread)
{
+ struct ospf *ospf = THREAD_ARG(thread);
int type;
+ ospf->t_asbr_nssa_redist_update = NULL;
+
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug("Running ASBR NSSA redistribution update on timer");
+
for (type = 0; type < ZEBRA_ROUTE_MAX; type++) {
struct list *red_list;
struct listnode *node;
@@ -293,10 +299,22 @@ void ospf_asbr_nssa_redist_task(struct ospf *ospf)
for (ALL_LIST_ELEMENTS_RO(red_list, node, red))
ospf_external_lsa_refresh_type(ospf, type,
red->instance,
- LSA_REFRESH_IF_CHANGED);
+ LSA_REFRESH_FORCE);
}
ospf_external_lsa_refresh_default(ospf);
+
+ return 0;
+}
+
+void ospf_schedule_asbr_nssa_redist_update(struct ospf *ospf)
+{
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug("Scheduling ASBR NSSA redistribution update");
+
+ thread_add_timer(master, ospf_asbr_nssa_redist_update_timer, ospf,
+ OSPF_ASBR_NSSA_REDIST_UPDATE_DELAY,
+ &ospf->t_asbr_nssa_redist_update);
}
void ospf_redistribute_withdraw(struct ospf *ospf, uint8_t type,
diff --git a/ospfd/ospf_asbr.h b/ospfd/ospf_asbr.h
index 7759d45455..d3e50903ef 100644
--- a/ospfd/ospf_asbr.h
+++ b/ospfd/ospf_asbr.h
@@ -104,6 +104,7 @@ struct ospf_external_aggr_rt {
};
#define OSPF_ASBR_CHECK_DELAY 30
+#define OSPF_ASBR_NSSA_REDIST_UPDATE_DELAY 9
extern void ospf_external_route_remove(struct ospf *, struct prefix_ipv4 *);
extern struct external_info *ospf_external_info_new(uint8_t, unsigned short);
@@ -121,7 +122,7 @@ extern struct external_info *ospf_external_info_lookup(struct ospf *, uint8_t,
unsigned short,
struct prefix_ipv4 *);
extern void ospf_asbr_status_update(struct ospf *, uint8_t);
-extern void ospf_asbr_nssa_redist_task(struct ospf *ospf);
+extern void ospf_schedule_asbr_nssa_redist_update(struct ospf *ospf);
extern void ospf_redistribute_withdraw(struct ospf *, uint8_t, unsigned short);
extern void ospf_asbr_check(void);
diff --git a/ospfd/ospf_dump.c b/ospfd/ospf_dump.c
index 2442f2e781..8f31f90346 100644
--- a/ospfd/ospf_dump.c
+++ b/ospfd/ospf_dump.c
@@ -169,8 +169,7 @@ const char *ospf_timeval_dump(struct timeval *t, char *buf, size_t size)
/* Making formatted timer strings. */
#define MINUTE_IN_SECONDS 60
#define HOUR_IN_SECONDS (60*MINUTE_IN_SECONDS)
-#define DAY_IN_SECONDS (24*HOUR_IN_SECONDS)
-#define WEEK_IN_SECONDS (7*DAY_IN_SECONDS)
+
unsigned long w, d, h, m, ms, us;
if (!t)
@@ -191,14 +190,14 @@ const char *ospf_timeval_dump(struct timeval *t, char *buf, size_t size)
ms %= 1000;
}
- if (t->tv_sec > WEEK_IN_SECONDS) {
- w = t->tv_sec / WEEK_IN_SECONDS;
- t->tv_sec -= w * WEEK_IN_SECONDS;
+ if (t->tv_sec > ONE_WEEK_SECOND) {
+ w = t->tv_sec / ONE_WEEK_SECOND;
+ t->tv_sec -= w * ONE_WEEK_SECOND;
}
- if (t->tv_sec > DAY_IN_SECONDS) {
- d = t->tv_sec / DAY_IN_SECONDS;
- t->tv_sec -= d * DAY_IN_SECONDS;
+ if (t->tv_sec > ONE_DAY_SECOND) {
+ d = t->tv_sec / ONE_DAY_SECOND;
+ t->tv_sec -= d * ONE_DAY_SECOND;
}
if (t->tv_sec >= HOUR_IN_SECONDS) {
@@ -221,7 +220,7 @@ const char *ospf_timeval_dump(struct timeval *t, char *buf, size_t size)
snprintf(buf, size, "%luh%02lum%02lds", h, m, (long)t->tv_sec);
else if (m)
snprintf(buf, size, "%lum%02lds", m, (long)t->tv_sec);
- else if (ms)
+ else if (t->tv_sec > 0 || ms > 0)
snprintf(buf, size, "%ld.%03lus", (long)t->tv_sec, ms);
else
snprintf(buf, size, "%ld usecs", (long)t->tv_usec);
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index be446705ea..69a3e45878 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -1546,6 +1546,7 @@ static int ospf_area_nssa_cmd_handler(struct vty *vty, int argc,
/* Flush the external LSA for the specified area */
ospf_flush_lsa_from_area(ospf, area_id, OSPF_AS_EXTERNAL_LSA);
ospf_schedule_abr_task(ospf);
+ ospf_schedule_asbr_nssa_redist_update(ospf);
return CMD_SUCCESS;
}
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index 9949a78336..faec868b2a 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -791,6 +791,7 @@ static void ospf_finish_final(struct ospf *ospf)
OSPF_TIMER_OFF(ospf->t_maxage_walker);
OSPF_TIMER_OFF(ospf->t_abr_task);
OSPF_TIMER_OFF(ospf->t_asbr_check);
+ OSPF_TIMER_OFF(ospf->t_asbr_nssa_redist_update);
OSPF_TIMER_OFF(ospf->t_distribute_update);
OSPF_TIMER_OFF(ospf->t_lsa_refresher);
OSPF_TIMER_OFF(ospf->t_opaque_lsa_self);
diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h
index 2093eb2e42..318400e968 100644
--- a/ospfd/ospfd.h
+++ b/ospfd/ospfd.h
@@ -242,6 +242,8 @@ struct ospf {
/* Threads. */
struct thread *t_abr_task; /* ABR task timer. */
struct thread *t_asbr_check; /* ASBR check timer. */
+ struct thread *t_asbr_nssa_redist_update; /* ASBR NSSA redistribution
+ update timer. */
struct thread *t_distribute_update; /* Distirbute list update timer. */
struct thread *t_spf_calc; /* SPF calculation timer. */
struct thread *t_ase_calc; /* ASE calculation timer. */
diff --git a/zebra/redistribute.c b/zebra/redistribute.c
index 9e675011ee..104f952b3b 100644
--- a/zebra/redistribute.c
+++ b/zebra/redistribute.c
@@ -347,17 +347,12 @@ void zebra_redistribute_add(ZAPI_HANDLER_ARGS)
zvrf_id(zvrf), afi);
}
} else {
- if (!vrf_bitmap_check(client->redist[afi][type],
- zvrf_id(zvrf))) {
- if (IS_ZEBRA_DEBUG_EVENT)
- zlog_debug(
- "%s: setting vrf %s(%u) redist bitmap",
- __func__, VRF_LOGNAME(zvrf->vrf),
- zvrf_id(zvrf));
- vrf_bitmap_set(client->redist[afi][type],
- zvrf_id(zvrf));
- zebra_redistribute(client, type, 0, zvrf_id(zvrf), afi);
- }
+ if (IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug("%s: setting vrf %s(%u) redist bitmap",
+ __func__, VRF_LOGNAME(zvrf->vrf),
+ zvrf_id(zvrf));
+ vrf_bitmap_set(client->redist[afi][type], zvrf_id(zvrf));
+ zebra_redistribute(client, type, 0, zvrf_id(zvrf), afi);
}
stream_failure: