diff options
| -rw-r--r-- | bfdd/ptm_adapter.c | 63 | ||||
| -rw-r--r-- | bgpd/bgp_fsm.c | 20 | ||||
| -rw-r--r-- | lib/prefix.h | 2 | ||||
| -rwxr-xr-x | tests/topotests/pbr-topo1/test_pbr_topo1.py | 25 | ||||
| -rw-r--r-- | zebra/zebra_dplane.c | 11 |
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); |
