summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfdd/ptm_adapter.c63
-rw-r--r--bgpd/bgp_fsm.c20
-rw-r--r--lib/prefix.h2
-rwxr-xr-xtests/topotests/pbr-topo1/test_pbr_topo1.py25
-rw-r--r--zebra/zebra_dplane.c11
5 files changed, 89 insertions, 32 deletions
diff --git a/bfdd/ptm_adapter.c b/bfdd/ptm_adapter.c
index 25938dd9f5..ed6db24115 100644
--- a/bfdd/ptm_adapter.c
+++ b/bfdd/ptm_adapter.c
@@ -128,6 +128,35 @@ static void debug_printbpc(const struct bfd_peer_cfg *bpc, const char *fmt, ...)
timers[0], timers[1], timers[2], cbit_str);
}
+static void _ptm_bfd_session_del(struct bfd_session *bs, uint8_t diag)
+{
+ if (bglobal.debug_peer_event)
+ zlog_debug("session-delete: %s", bs_to_string(bs));
+
+ /* Change state and notify peer. */
+ bs->ses_state = PTM_BFD_DOWN;
+ bs->local_diag = diag;
+ ptm_bfd_snd(bs, 0);
+
+ /* Session reached refcount == 0, lets delete it. */
+ if (bs->refcount == 0) {
+ /*
+ * Sanity check: if there is a refcount bug, we can't delete
+ * the session a user configured manually. Lets leave a
+ * message here so we can catch the bug if it exists.
+ */
+ if (CHECK_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG)) {
+ zlog_err(
+ "ptm-del-session: [%s] session refcount is "
+ "zero but it was configured by CLI",
+ bs_to_string(bs));
+ } else {
+ control_notify_config(BCM_NOTIFY_CONFIG_DELETE, bs);
+ bfd_session_free(bs);
+ }
+ }
+}
+
static int _ptm_msg_address(struct stream *msg, int family, const void *addr)
{
stream_putc(msg, family);
@@ -456,15 +485,20 @@ static void bfdd_dest_deregister(struct stream *msg, vrf_id_t vrf_id)
/* Unregister client peer notification. */
pcn = pcn_lookup(pc, bs);
- pcn_free(pcn);
- if (bs->refcount ||
- CHECK_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG))
+ if (pcn != NULL) {
+ pcn_free(pcn);
return;
+ }
- bs->ses_state = PTM_BFD_ADM_DOWN;
- ptm_bfd_snd(bs, 0);
+ if (bglobal.debug_zebra)
+ zlog_debug("ptm-del-dest: failed to find BFD session");
- ptm_bfd_sess_del(&bpc);
+ /*
+ * XXX: We either got a double deregistration or the daemon who
+ * created this is no longer around. Lets try to delete it anyway
+ * and the worst case is the refcount will detain us.
+ */
+ _ptm_bfd_session_del(bs, BD_NEIGHBOR_DOWN);
}
/*
@@ -506,6 +540,9 @@ static void bfdd_client_deregister(struct stream *msg)
return;
}
+ if (bglobal.debug_zebra)
+ zlog_debug("ptm-del-client: client pid %u", pid);
+
pc_free(pc);
return;
@@ -827,9 +864,6 @@ static void pc_free(struct ptm_client *pc)
{
struct ptm_client_notification *pcn;
- if (pc == NULL)
- return;
-
TAILQ_REMOVE(&pcqueue, pc, pc_entry);
while (!TAILQ_EMPTY(&pc->pc_pcnqueue)) {
@@ -891,14 +925,19 @@ static void pcn_free(struct ptm_client_notification *pcn)
struct ptm_client *pc;
struct bfd_session *bs;
- if (pcn == NULL)
- return;
-
/* Handle session de-registration. */
bs = pcn->pcn_bs;
pcn->pcn_bs = NULL;
bs->refcount--;
+ /* Log modification to users. */
+ if (bglobal.debug_zebra)
+ zlog_debug("ptm-del-session: [%s] refcount=%" PRIu64,
+ bs_to_string(bs), bs->refcount);
+
+ /* Set session down. */
+ _ptm_bfd_session_del(bs, BD_NEIGHBOR_DOWN);
+
/* Handle ptm_client deregistration. */
pc = pcn->pcn_pc;
pcn->pcn_pc = NULL;
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
index ce5747dc2b..e78682a3bb 100644
--- a/bgpd/bgp_fsm.c
+++ b/bgpd/bgp_fsm.c
@@ -512,6 +512,7 @@ static int bgp_connect_timer(struct thread *thread)
/* BGP holdtime timer. */
static int bgp_holdtime_timer(struct thread *thread)
{
+ atomic_size_t inq_count;
struct peer *peer;
peer = THREAD_ARG(thread);
@@ -521,6 +522,25 @@ static int bgp_holdtime_timer(struct thread *thread)
zlog_debug("%s [FSM] Timer (holdtime timer expire)",
peer->host);
+ /*
+ * Given that we do not have any expectation of ordering
+ * for handling packets from a peer -vs- handling
+ * the hold timer for a peer as that they are both
+ * events on the peer. If we have incoming
+ * data on the peers inq, let's give the system a chance
+ * to handle that data. This can be especially true
+ * for systems where we are heavily loaded for one
+ * reason or another.
+ */
+ inq_count = atomic_load_explicit(&peer->ibuf->count,
+ memory_order_relaxed);
+ if (inq_count) {
+ BGP_TIMER_ON(peer->t_holdtime, bgp_holdtime_timer,
+ peer->v_holdtime);
+
+ return 0;
+ }
+
THREAD_VAL(thread) = Hold_Timer_expired;
bgp_event(thread); /* bgp_event unlocks peer */
diff --git a/lib/prefix.h b/lib/prefix.h
index 4b2d90d63a..506efffb94 100644
--- a/lib/prefix.h
+++ b/lib/prefix.h
@@ -295,6 +295,7 @@ union prefixptr {
prefixtype(prefixptr, struct prefix_ipv6, p6)
prefixtype(prefixptr, struct prefix_evpn, evp)
prefixtype(prefixptr, struct prefix_fs, fs)
+ prefixtype(prefixptr, struct prefix_rd, rd)
} __attribute__((transparent_union));
union prefixconstptr {
@@ -303,6 +304,7 @@ union prefixconstptr {
prefixtype(prefixconstptr, const struct prefix_ipv6, p6)
prefixtype(prefixconstptr, const struct prefix_evpn, evp)
prefixtype(prefixconstptr, const struct prefix_fs, fs)
+ prefixtype(prefixconstptr, const struct prefix_rd, rd)
} __attribute__((transparent_union));
#ifndef INET_ADDRSTRLEN
diff --git a/tests/topotests/pbr-topo1/test_pbr_topo1.py b/tests/topotests/pbr-topo1/test_pbr_topo1.py
index 7de1cfa519..63d1f26d1c 100755
--- a/tests/topotests/pbr-topo1/test_pbr_topo1.py
+++ b/tests/topotests/pbr-topo1/test_pbr_topo1.py
@@ -32,6 +32,7 @@ import re
import sys
import pytest
import json
+from functools import partial
# Save the Current Working Directory to find configuration files.
CWD = os.path.dirname(os.path.realpath(__file__))
@@ -140,9 +141,10 @@ def test_pbr_data():
expected = json.loads(open(intf_file).read())
# Actual output from router
- actual = router.vtysh_cmd("show pbr interface json", isjson=True)
+ test_func = partial(topotest.router_json_cmp, router, "show pbr interface json", expected)
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
assertmsg = '"show pbr interface" mismatches on {}'.format(router.name)
- assert topotest.json_cmp(actual, expected) is None, assertmsg
+ assert result is None, assertmsg
map_file = "{}/{}/pbr-map.json".format(CWD, router.name)
logger.info(map_file)
@@ -151,10 +153,10 @@ def test_pbr_data():
expected = json.loads(open(map_file).read())
# Actual output from router
- actual = router.vtysh_cmd("show pbr map json", isjson=True)
-
+ test_func = partial(topotest.router_json_cmp, router, "show pbr map json", expected)
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
assertmsg = '"show pbr map" mismatches on {}'.format(router.name)
- assert topotest.json_cmp(actual, expected) is None, assertmsg
+ assert result is None, assertmsg
nexthop_file = "{}/{}/pbr-nexthop-groups.json".format(CWD, router.name)
logger.info(nexthop_file)
@@ -163,11 +165,10 @@ def test_pbr_data():
expected = json.loads(open(nexthop_file).read())
# Actual output from router
- actual = router.vtysh_cmd("show pbr nexthop-groups json", isjson=True)
-
+ test_func = partial(topotest.router_json_cmp, router, "show pbr nexthop-groups json", expected)
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
assertmsg = '"show pbr nexthop-groups" mismatches on {}'.format(router.name)
- assert topotest.json_cmp(actual, expected) is None, assertmsg
-
+ assert result is None, assertmsg
def test_pbr_flap():
"Test PBR interface flapping"
@@ -199,10 +200,10 @@ def test_pbr_flap():
expected = json.loads(open(intf_file).read())
# Actual output from router
- actual = router.vtysh_cmd("show pbr interface json", isjson=True)
+ test_func = partial(topotest.router_json_cmp, router, "show pbr interface json", expected)
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
assertmsg = '"show pbr interface" mismatches on {}'.format(router.name)
-
- assert topotest.json_cmp(actual, expected) is None, assertmsg
+ assert result is None, assertmsg
def test_rule_linux_installation():
diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c
index eb3d48d784..b9163cfaab 100644
--- a/zebra/zebra_dplane.c
+++ b/zebra/zebra_dplane.c
@@ -2158,17 +2158,12 @@ static int dplane_update_enqueue(struct zebra_dplane_ctx *ctx)
}
DPLANE_UNLOCK();
- curr = atomic_add_fetch_explicit(
-#ifdef __clang__
- /* TODO -- issue with the clang atomic/intrinsics currently;
- * casting away the 'Atomic'-ness of the variable works.
- */
- (uint32_t *)&(zdplane_info.dg_routes_queued),
-#else
+ curr = atomic_fetch_add_explicit(
&(zdplane_info.dg_routes_queued),
-#endif
1, memory_order_seq_cst);
+ curr++; /* We got the pre-incremented value */
+
/* Maybe update high-water counter also */
high = atomic_load_explicit(&zdplane_info.dg_routes_queued_max,
memory_order_seq_cst);