diff options
26 files changed, 596 insertions, 215 deletions
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index 45e9aad1ba..672fa4512a 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -662,6 +662,15 @@ static void bgp_graceful_restart_timer_off(struct peer *peer) UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT); BGP_TIMER_OFF(peer->t_gr_stale); + + if (peer_dynamic_neighbor(peer) && + !(CHECK_FLAG(peer->flags, PEER_FLAG_DELETE))) { + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s (dynamic neighbor) deleted (%s)", + peer->host, __func__); + peer_delete(peer); + } + bgp_timer_set(peer); } @@ -1380,10 +1389,11 @@ int bgp_stop(struct peer *peer) && peer->last_reset == PEER_DOWN_UPDATE_SOURCE_CHANGE) bfd_sess_uninstall(peer->bfd_config->session); - if (peer_dynamic_neighbor(peer) - && !(CHECK_FLAG(peer->flags, PEER_FLAG_DELETE))) { + if (peer_dynamic_neighbor_no_nsf(peer) && + !(CHECK_FLAG(peer->flags, PEER_FLAG_DELETE))) { if (bgp_debug_neighbor_events(peer)) - zlog_debug("%s (dynamic neighbor) deleted", peer->host); + zlog_debug("%s (dynamic neighbor) deleted (%s)", + peer->host, __func__); peer_delete(peer); return -1; } @@ -1602,9 +1612,10 @@ static int bgp_stop_with_error(struct peer *peer) if (peer->v_start >= (60 * 2)) peer->v_start = (60 * 2); - if (peer_dynamic_neighbor(peer)) { + if (peer_dynamic_neighbor_no_nsf(peer)) { if (bgp_debug_neighbor_events(peer)) - zlog_debug("%s (dynamic neighbor) deleted", peer->host); + zlog_debug("%s (dynamic neighbor) deleted (%s)", + peer->host, __func__); peer_delete(peer); return -1; } @@ -1620,9 +1631,10 @@ static int bgp_stop_with_notify(struct peer *peer, uint8_t code, /* Send notify to remote peer */ bgp_notify_send(peer, code, sub_code); - if (peer_dynamic_neighbor(peer)) { + if (peer_dynamic_neighbor_no_nsf(peer)) { if (bgp_debug_neighbor_events(peer)) - zlog_debug("%s (dynamic neighbor) deleted", peer->host); + zlog_debug("%s (dynamic neighbor) deleted (%s)", + peer->host, __func__); peer_delete(peer); return -1; } @@ -1781,9 +1793,10 @@ static int bgp_connect_success_w_delayopen(struct peer *peer) /* TCP connect fail */ static int bgp_connect_fail(struct peer *peer) { - if (peer_dynamic_neighbor(peer)) { + if (peer_dynamic_neighbor_no_nsf(peer)) { if (bgp_debug_neighbor_events(peer)) - zlog_debug("%s (dynamic neighbor) deleted", peer->host); + zlog_debug("%s (dynamic neighbor) deleted (%s)", + peer->host, __func__); peer_delete(peer); return -1; } diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index e07883865a..69f4d66b46 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -17495,7 +17495,20 @@ static struct cmd_node bgp_srv6_node = { static void community_list_vty(void); -static void bgp_ac_neighbor(vector comps, struct cmd_token *token) +static void bgp_ac_peergroup(vector comps, struct cmd_token *token) +{ + struct bgp *bgp; + struct peer_group *group; + struct listnode *lnbgp, *lnpeer; + + for (ALL_LIST_ELEMENTS_RO(bm->bgp, lnbgp, bgp)) { + for (ALL_LIST_ELEMENTS_RO(bgp->group, lnpeer, group)) + vector_set(comps, + XSTRDUP(MTYPE_COMPLETION, group->name)); + } +} + +static void bgp_ac_peer(vector comps, struct cmd_token *token) { struct bgp *bgp; struct peer *peer; @@ -17525,25 +17538,20 @@ static void bgp_ac_neighbor(vector comps, struct cmd_token *token) } } +static void bgp_ac_neighbor(vector comps, struct cmd_token *token) +{ + bgp_ac_peer(comps, token); + + if (token->type == VARIABLE_TKN) + bgp_ac_peergroup(comps, token); +} + static const struct cmd_variable_handler bgp_var_neighbor[] = { {.varname = "neighbor", .completions = bgp_ac_neighbor}, {.varname = "neighbors", .completions = bgp_ac_neighbor}, {.varname = "peer", .completions = bgp_ac_neighbor}, {.completions = NULL}}; -static void bgp_ac_peergroup(vector comps, struct cmd_token *token) -{ - struct bgp *bgp; - struct peer_group *group; - struct listnode *lnbgp, *lnpeer; - - for (ALL_LIST_ELEMENTS_RO(bm->bgp, lnbgp, bgp)) { - for (ALL_LIST_ELEMENTS_RO(bgp->group, lnpeer, group)) - vector_set(comps, XSTRDUP(MTYPE_COMPLETION, - group->name)); - } -} - static const struct cmd_variable_handler bgp_var_peergroup[] = { {.tokenname = "PGNAME", .completions = bgp_ac_peergroup}, {.completions = NULL} }; diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 747c185e39..57d135e781 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -2380,9 +2380,15 @@ static inline bool peer_established(struct peer *peer) return peer->status == Established; } -static inline int peer_dynamic_neighbor(struct peer *peer) +static inline bool peer_dynamic_neighbor(struct peer *peer) { - return (CHECK_FLAG(peer->flags, PEER_FLAG_DYNAMIC_NEIGHBOR)) ? 1 : 0; + return CHECK_FLAG(peer->flags, PEER_FLAG_DYNAMIC_NEIGHBOR); +} + +static inline bool peer_dynamic_neighbor_no_nsf(struct peer *peer) +{ + return (peer_dynamic_neighbor(peer) && + !CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)); } static inline int peer_cap_enhe(struct peer *peer, afi_t afi, safi_t safi) diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index 6588d70208..c169996e01 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -2090,8 +2090,7 @@ static struct external_info *ospf_default_external_info(struct ospf *ospf) p.prefix.s_addr = 0; p.prefixlen = 0; - default_ei = ospf_external_info_lookup(ospf, DEFAULT_ROUTE, - ospf->instance, &p); + default_ei = ospf_external_info_lookup(ospf, DEFAULT_ROUTE, 0, &p); if (!default_ei) return NULL; diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 3d0804b018..8aa5545920 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -5939,7 +5939,7 @@ static int show_lsa_summary(struct vty *vty, struct ospf_lsa *lsa, int self, struct as_external_lsa *asel; struct prefix_ipv4 p; - if (lsa != NULL) + if (lsa != NULL) { /* If self option is set, check LSA self flag. */ if (self == 0 || IS_LSA_SELF(lsa)) { @@ -6047,6 +6047,9 @@ static int show_lsa_summary(struct vty *vty, struct ospf_lsa *lsa, int self, vty_out(vty, "\n"); } + return 1; + } + return 0; } @@ -6080,6 +6083,21 @@ static const char * const show_database_desc_json[] = { "asExternalOpaqueLsa", }; +static const char *const show_database_desc_count_json[] = { + "unknownCount", + "routerLinkStatesCount", + "networkLinkStatesCount", + "summaryLinkStatesCount", + "asbrSummaryLinkStatesCount", + "asExternalLinkStatesCount", + "groupMembershipLsaCount", + "nssaExternalLinkStatesCount", + "type8LsaCount", + "linkLocalOpaqueLsaCount", + "areaLocalOpaqueLsaCount", + "asExternalOpaqueLsaCount", +}; + static const char *const show_database_header[] = { "", "Link ID ADV Router Age Seq# CkSum Link count", @@ -6752,6 +6770,7 @@ void show_ip_ospf_database_summary(struct vty *vty, struct ospf *ospf, int self, json_object *json_lsa = NULL; int type; json_object *json_lsa_array = NULL; + uint32_t count; if (json) json_areas = json_object_new_object(); @@ -6761,6 +6780,7 @@ void show_ip_ospf_database_summary(struct vty *vty, struct ospf *ospf, int self, json_area = json_object_new_object(); for (type = OSPF_MIN_LSA; type < OSPF_MAX_LSA; type++) { + count = 0; switch (type) { case OSPF_AS_EXTERNAL_LSA: case OSPF_OPAQUE_AS_LSA: @@ -6797,12 +6817,19 @@ void show_ip_ospf_database_summary(struct vty *vty, struct ospf *ospf, int self, json_lsa); } - show_lsa_summary(vty, lsa, self, - json_lsa); + count += show_lsa_summary( + vty, lsa, self, json_lsa); } if (!json) vty_out(vty, "\n"); + else + json_object_int_add( + json_area, + + show_database_desc_count_json + [type], + count); } } if (json) @@ -6817,6 +6844,7 @@ void show_ip_ospf_database_summary(struct vty *vty, struct ospf *ospf, int self, json_object_object_add(json, "areas", json_areas); for (type = OSPF_MIN_LSA; type < OSPF_MAX_LSA; type++) { + count = 0; switch (type) { case OSPF_AS_EXTERNAL_LSA: case OSPF_OPAQUE_AS_LSA: @@ -6845,11 +6873,17 @@ void show_ip_ospf_database_summary(struct vty *vty, struct ospf *ospf, int self, json_lsa); } - show_lsa_summary(vty, lsa, self, json_lsa); + count += show_lsa_summary(vty, lsa, self, + json_lsa); } if (!json) vty_out(vty, "\n"); + else + json_object_int_add( + json, + show_database_desc_count_json[type], + count); } } diff --git a/tests/topotests/bgp_llgr/r0/bgpd.conf b/tests/topotests/bgp_llgr/r0/bgpd.conf index d93ee193bc..a20e64fa42 100644 --- a/tests/topotests/bgp_llgr/r0/bgpd.conf +++ b/tests/topotests/bgp_llgr/r0/bgpd.conf @@ -4,6 +4,8 @@ router bgp 65000 bgp graceful-restart restart-time 0 bgp long-lived-graceful-restart stale-time 20 neighbor 192.168.0.2 remote-as external + neighbor 192.168.0.2 timers 3 10 + neighbor 192.168.0.2 timers connect 1 address-family ipv4 unicast redistribute connected exit-address-family diff --git a/tests/topotests/bgp_llgr/r1/bgpd.conf b/tests/topotests/bgp_llgr/r1/bgpd.conf index f8c9877730..bf33eebc51 100644 --- a/tests/topotests/bgp_llgr/r1/bgpd.conf +++ b/tests/topotests/bgp_llgr/r1/bgpd.conf @@ -4,6 +4,8 @@ router bgp 65001 bgp graceful-restart restart-time 0 bgp long-lived-graceful-restart stale-time 20 neighbor 192.168.1.2 remote-as external + neighbor 192.168.1.2 timers 3 10 + neighbor 192.168.1.2 timers connect 1 address-family ipv4 unicast redistribute connected exit-address-family diff --git a/tests/topotests/bgp_llgr/r2/bgpd.conf b/tests/topotests/bgp_llgr/r2/bgpd.conf index ea8e6beef1..6515ef83a0 100644 --- a/tests/topotests/bgp_llgr/r2/bgpd.conf +++ b/tests/topotests/bgp_llgr/r2/bgpd.conf @@ -3,7 +3,16 @@ router bgp 65002 bgp graceful-restart bgp long-lived-graceful-restart stale-time 20 neighbor 192.168.0.1 remote-as external + neighbor 192.168.0.1 timers 3 10 + neighbor 192.168.0.1 timers connect 1 neighbor 192.168.1.1 remote-as external + neighbor 192.168.1.1 timers 3 10 + neighbor 192.168.1.1 timers connect 1 neighbor 192.168.2.1 remote-as external + neighbor 192.168.2.1 timers 3 10 + neighbor 192.168.2.1 timers connect 1 + neighbor PG peer-group + neighbor PG remote-as external + bgp listen range 192.168.3.0/24 peer-group PG address-family ipv4 unicast neighbor 192.168.1.1 weight 100 diff --git a/tests/topotests/bgp_llgr/r2/zebra.conf b/tests/topotests/bgp_llgr/r2/zebra.conf index 0fa589f3a9..e5e88d4773 100644 --- a/tests/topotests/bgp_llgr/r2/zebra.conf +++ b/tests/topotests/bgp_llgr/r2/zebra.conf @@ -8,3 +8,6 @@ int r2-eth1 int r2-eth2 ip address 192.168.2.2/24 ! +int r2-eth3 + ip address 192.168.3.2/24 +! diff --git a/tests/topotests/bgp_llgr/r3/bgpd.conf b/tests/topotests/bgp_llgr/r3/bgpd.conf index d73fdccb1d..dfe20c1069 100644 --- a/tests/topotests/bgp_llgr/r3/bgpd.conf +++ b/tests/topotests/bgp_llgr/r3/bgpd.conf @@ -4,3 +4,5 @@ router bgp 65003 bgp graceful-restart bgp long-lived-graceful-restart stale-time 20 neighbor 192.168.2.2 remote-as external + neighbor 192.168.2.2 timers 3 10 + neighbor 192.168.2.2 timers connect 1 diff --git a/tests/topotests/bgp_llgr/r4/bgpd.conf b/tests/topotests/bgp_llgr/r4/bgpd.conf new file mode 100644 index 0000000000..49ce387392 --- /dev/null +++ b/tests/topotests/bgp_llgr/r4/bgpd.conf @@ -0,0 +1,13 @@ +router bgp 65004 + bgp router-id 192.168.3.1 + no bgp ebgp-requires-policy + bgp graceful-restart + bgp graceful-restart restart-time 0 + bgp long-lived-graceful-restart stale-time 30 + neighbor 192.168.3.2 remote-as external + neighbor 192.168.3.2 timers 3 10 + neighbor 192.168.3.2 timers connect 1 + address-family ipv4 unicast + redistribute connected + exit-address-family +! diff --git a/tests/topotests/bgp_llgr/r4/zebra.conf b/tests/topotests/bgp_llgr/r4/zebra.conf new file mode 100644 index 0000000000..7ec20be8bb --- /dev/null +++ b/tests/topotests/bgp_llgr/r4/zebra.conf @@ -0,0 +1,7 @@ +! +int lo + ip address 172.16.1.2/32 +! +int r4-eth0 + ip address 192.168.3.1/24 +! diff --git a/tests/topotests/bgp_llgr/test_bgp_llgr.py b/tests/topotests/bgp_llgr/test_bgp_llgr.py index df4f401d02..fa57f66400 100644 --- a/tests/topotests/bgp_llgr/test_bgp_llgr.py +++ b/tests/topotests/bgp_llgr/test_bgp_llgr.py @@ -53,7 +53,7 @@ pytestmark = [pytest.mark.bgpd] def build_topo(tgen): - for routern in range(0, 5): + for routern in range(0, 6): tgen.add_router("r{}".format(routern)) switch = tgen.add_switch("s0") @@ -68,6 +68,11 @@ def build_topo(tgen): switch.add_link(tgen.gears["r2"]) switch.add_link(tgen.gears["r3"]) + # Dynamic neighbor + switch = tgen.add_switch("s3") + switch.add_link(tgen.gears["r2"]) + switch.add_link(tgen.gears["r4"]) + def setup_module(mod): tgen = Topogen(build_topo, mod.__name__) @@ -104,14 +109,15 @@ def test_bgp_llgr(): output = json.loads(router.vtysh_cmd("show ip bgp json")) expected = { "routes": { - "172.16.1.1/32": [{"nexthops": [{"ip": "192.168.2.2", "used": True}]}] + "172.16.1.1/32": [{"nexthops": [{"ip": "192.168.2.2", "used": True}]}], + "172.16.1.2/32": [{"nexthops": [{"ip": "192.168.2.2", "used": True}]}], } } return topotest.json_cmp(output, expected) step("Check if we can see 172.16.1.1/32 after initial converge in R3") test_func = functools.partial(_bgp_converge, r3) - success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5) assert result is None, "Cannot see 172.16.1.1/32 in r3" def _bgp_weight_prefered_route(router): @@ -134,7 +140,7 @@ def test_bgp_llgr(): "Check if we can see 172.16.1.1/32 as best selected due to higher weigth in R2" ) test_func = functools.partial(_bgp_weight_prefered_route, r2) - success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5) assert ( result is None ), "Prefix 172.16.1.1/32 is not selected as bests path due to weight" @@ -142,14 +148,14 @@ def test_bgp_llgr(): step("Kill bgpd in R1") kill_router_daemons(tgen, "r1", ["bgpd"]) - def _bgp_stale_route(router): - output = json.loads(router.vtysh_cmd("show ip bgp 172.16.1.1/32 json")) + def _bgp_stale_route(router, prefix): + output = json.loads(router.vtysh_cmd("show ip bgp {} json".format(prefix))) expected = {"paths": [{"community": {"string": "llgr-stale"}, "stale": True}]} return topotest.json_cmp(output, expected) step("Check if we can see 172.16.1.1/32 as stale in R2") - test_func = functools.partial(_bgp_stale_route, r2) - success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5) + test_func = functools.partial(_bgp_stale_route, r2, "172.16.1.1/32") + _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5) assert result is None, "Prefix 172.16.1.1/32 is not stale" def _bgp_llgr_depreference_route(router): @@ -170,14 +176,22 @@ def test_bgp_llgr(): step("Check if we can see 172.16.1.1/32 depreferenced due to LLGR_STALE in R2") test_func = functools.partial(_bgp_llgr_depreference_route, r2) - success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5) assert result is None, "Prefix 172.16.1.1/32 is not depreferenced due to LLGR_STALE" step("Check if we can see 172.16.1.1/32 after R1 was killed in R3") test_func = functools.partial(_bgp_converge, r3) - success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5) assert result is None, "Cannot see 172.16.1.1/32 in r3" + step("Kill bgpd in R4 (dynamic peer)") + kill_router_daemons(tgen, "r4", ["bgpd"]) + + step("Check if we can see 172.16.1.2/32 after R4 (dynamic peer) was killed") + test_func = functools.partial(_bgp_stale_route, r2, "172.16.1.2/32") + _, result = topotest.run_and_expect(test_func, None, count=120, wait=0.5) + assert result is None, "Cannot see 172.16.1.2/32 in r2" + if __name__ == "__main__": args = ["-s"] + sys.argv[1:] diff --git a/tests/topotests/ospf_instance_redistribute/r1/ospf_default_information.json b/tests/topotests/ospf_instance_redistribute/r1/ospf_default_information.json new file mode 100644 index 0000000000..c0f71bb05d --- /dev/null +++ b/tests/topotests/ospf_instance_redistribute/r1/ospf_default_information.json @@ -0,0 +1,33 @@ +{ + "ospfInstance":3, + "routerId":"192.168.100.1", + "areas":{ + }, + "asExternalLinkStates":[ + { + "lsId":"0.0.0.0", + "advertisedRouter":"192.168.100.1", + "sequenceNumber":"80000001", + "metricType":"E2", + "route":"0.0.0.0/0", + "tag":0 + }, + { + "lsId":"4.5.6.7", + "advertisedRouter":"192.168.100.1", + "sequenceNumber":"80000001", + "metricType":"E2", + "route":"4.5.6.7/32", + "tag":0 + }, + { + "lsId":"4.5.6.10", + "advertisedRouter":"192.168.100.1", + "sequenceNumber":"80000001", + "metricType":"E2", + "route":"4.5.6.10/32", + "tag":0 + } + ], + "asExternalLinkStatesCount":3 +} diff --git a/tests/topotests/ospf_instance_redistribute/r1/ospf_instance_lsa.json b/tests/topotests/ospf_instance_redistribute/r1/ospf_instance_lsa.json new file mode 100644 index 0000000000..fc8e349d2e --- /dev/null +++ b/tests/topotests/ospf_instance_redistribute/r1/ospf_instance_lsa.json @@ -0,0 +1,17 @@ +{ + "ospfInstance":3, + "routerId":"192.168.100.1", + "areas":{ + }, + "asExternalLinkStates":[ + { + "lsId":"4.5.6.7", + "advertisedRouter":"192.168.100.1", + "sequenceNumber":"80000001", + "metricType":"E2", + "route":"4.5.6.7/32", + "tag":0 + } + ], + "asExternalLinkStatesCount":1 +} diff --git a/tests/topotests/ospf_instance_redistribute/r1/ospf_instance_lsa2.json b/tests/topotests/ospf_instance_redistribute/r1/ospf_instance_lsa2.json new file mode 100644 index 0000000000..b7d6f7c0c4 --- /dev/null +++ b/tests/topotests/ospf_instance_redistribute/r1/ospf_instance_lsa2.json @@ -0,0 +1,25 @@ +{ + "ospfInstance":3, + "routerId":"192.168.100.1", + "areas":{ + }, + "asExternalLinkStates":[ + { + "lsId":"4.5.6.7", + "advertisedRouter":"192.168.100.1", + "sequenceNumber":"80000001", + "metricType":"E2", + "route":"4.5.6.7/32", + "tag":0 + }, + { + "lsId":"4.5.6.10", + "advertisedRouter":"192.168.100.1", + "sequenceNumber":"80000001", + "metricType":"E2", + "route":"4.5.6.10/32", + "tag":0 + } + ], + "asExternalLinkStatesCount":2 +} diff --git a/tests/topotests/ospf_instance_redistribute/r1/ospfd-3.conf b/tests/topotests/ospf_instance_redistribute/r1/ospfd-3.conf new file mode 100644 index 0000000000..88432fed63 --- /dev/null +++ b/tests/topotests/ospf_instance_redistribute/r1/ospfd-3.conf @@ -0,0 +1,2 @@ +router ospf 3 + redistribute sharp diff --git a/tests/topotests/ospf_instance_redistribute/r1/sharp_installed.json b/tests/topotests/ospf_instance_redistribute/r1/sharp_installed.json new file mode 100644 index 0000000000..c0a1f6ac00 --- /dev/null +++ b/tests/topotests/ospf_instance_redistribute/r1/sharp_installed.json @@ -0,0 +1,13 @@ +{ + "routes":[ + { + "fib":3, + "rib":3, + "fibOffLoaded":0, + "fibTrapped":0, + "type":"sharp" + } + ], + "routesTotal":4, + "routesTotalFib":4 +} diff --git a/tests/topotests/ospf_instance_redistribute/r1/zebra.conf b/tests/topotests/ospf_instance_redistribute/r1/zebra.conf new file mode 100644 index 0000000000..6bb2a65eaf --- /dev/null +++ b/tests/topotests/ospf_instance_redistribute/r1/zebra.conf @@ -0,0 +1,2 @@ +interface lo + ip address 192.168.100.1/24 diff --git a/tests/topotests/ospf_instance_redistribute/test_ospf_instance_redistribute.py b/tests/topotests/ospf_instance_redistribute/test_ospf_instance_redistribute.py new file mode 100644 index 0000000000..88c236d7a0 --- /dev/null +++ b/tests/topotests/ospf_instance_redistribute/test_ospf_instance_redistribute.py @@ -0,0 +1,188 @@ +#!/usr/bin/env python + +# +# test_ospf_instance_redistribute.py +# +# Copyright (c) 2022 by +# Nvidia, Inc. +# Donald Sharp +# +# Permission to use, copy, modify, and/or distribute this software +# for any purpose with or without fee is hereby granted, provided +# that the above copyright notice and this permission notice appear +# in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY +# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +# OF THIS SOFTWARE. +# + +""" +test_ospf_instance_redistribute + +""" + +import os +import re +import sys +import pytest +import json + +pytestmark = [pytest.mark.ospfd, pytest.mark.sharpd] + +# Save the Current Working Directory to find configuration files. +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) + +# pylint: disable=C0413 +# Import topogen and topotest helpers +from lib import topotest +from lib.topogen import Topogen, TopoRouter, get_topogen +from lib.topolog import logger +from functools import partial + +# Required to instantiate the topology builder class. + +##################################################### +## +## Network Topology Definition +## +##################################################### + + +def build_topo(tgen): + tgen.add_router("r1") + + # Connect r1 and r2 through the eth0 interface + switch = tgen.add_switch("sw1") + switch.add_link(tgen.gears["r1"]) + + +##################################################### +## +## Tests starting +## +##################################################### + + +def setup_module(module): + "Setup topology" + tgen = Topogen(build_topo, module.__name__) + tgen.start_topology() + + # This is a sample of configuration loading. + r1 = tgen.gears["r1"] + r1.load_config( + TopoRouter.RD_ZEBRA, os.path.join(CWD, "r1/zebra.conf") + ) + r1.load_config( + TopoRouter.RD_OSPF, os.path.join(CWD, "r1/ospfd-3.conf"), + "-n 3" + ) + r1.load_config( + TopoRouter.RD_SHARP, os.path.join(CWD, "r1/sharpd.conf") + ) + + tgen.start_router() + + +def teardown_module(_mod): + "Teardown the pytest environment" + tgen = get_topogen() + + # This function tears down the whole topology. + tgen.stop_topology() + + +def test_install_sharp_instance_routes(): + tgen = get_topogen() + + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + logger.info("Installing sharp routes") + r1 = tgen.gears["r1"] + r1.vtysh_cmd("sharp install route 4.5.6.7 nexthop 192.168.100.2 1") + r1.vtysh_cmd("sharp install route 4.5.6.8 nexthop 192.168.100.2 1 instance 3") + r1.vtysh_cmd("sharp install route 4.5.6.9 nexthop 192.168.100.3 1 instance 4") + r1.vtysh_cmd("conf\nrouter ospf 3\nredistribute sharp") + + json_file = "{}/r1/sharp_installed.json".format(CWD) + expected = json.loads(open(json_file).read()) + + test_func = partial( + topotest.router_json_cmp, r1, "show ip route summ json", expected) + + logger.info("Ensuring that they exist in the rib/fib") + _, result = topotest.run_and_expect(test_func, None, count=10, wait=1) + assertmsg = '"r1" sharp routes are not installed' + assert result is None, assertmsg + +def test_ospf_instance_redistribute(): + tgen = get_topogen() + + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + logger.info("Testing that ospf instance 3 has the redistributed sharp route") + r1 = tgen.gears["r1"] + r1.vtysh_cmd("conf\nrouter ospf 3\nredistribute sharp") + + json_file = "{}/r1/ospf_instance_lsa.json".format(CWD) + expected = json.loads(open(json_file).read()) + + test_func = partial( + topotest.router_json_cmp, r1, "show ip ospf 3 data json", expected) + + _, result = topotest.run_and_expect(test_func, None, count=10, wait=1) + assertmsg = '"r1" ospf instance 3 does not have the proper redistributed routes' + assert result is None, assertmsg + + r1.vtysh_cmd("sharp install route 4.5.6.10 nexthop 192.168.100.2 1") + r1.vtysh_cmd("sharp install route 4.5.6.11 nexthop 192.168.100.2 1 instance 3") + r1.vtysh_cmd("sharp install route 4.5.6.12 nexthop 192.168.100.2 1 instance 4") + + logger.info("Added new sharp routes let's see if we pick up only the .10") + json_file = "{}/r1/ospf_instance_lsa2.json".format(CWD) + expected = json.loads(open(json_file).read()) + + test_func = partial( + topotest.router_json_cmp, r1, "show ip ospf 3 data json", expected) + + _, result = topotest.run_and_expect(test_func, None, count=10, wait=1) + assertmsg = '"r1" ospf instance 3 does not have the proper redistributed routes' + assert result is None, assertmsg + + +def test_ospf_instance_default_information(): + tgen = get_topogen() + + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + logger.info("Testing the using default information originate") + r1 = tgen.gears["r1"] + r1.vtysh_cmd("conf\nrouter ospf 3\ndefault-information originate") + + r1.vtysh_cmd("conf\nip route 0.0.0.0/0 192.168.100.2") + json_file = "{}/r1/ospf_default_information.json".format(CWD) + expected = json.loads(open(json_file).read()) + + test_func = partial( + topotest.router_json_cmp, r1, "show ip ospf 3 data json", expected) + + _, result = topotest.run_and_expect(test_func, None, count=10, wait=1) + assertmsg = '"r1" ospf instance 3 does not properly redistribute the default route' + assert result is None, assertmsg + + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) + diff --git a/zebra/redistribute.c b/zebra/redistribute.c index c59ff1bbec..fdd2c8405f 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -94,7 +94,7 @@ static void zebra_redistribute_default(struct zserv *client, vrf_id_t vrf_id) if (CHECK_FLAG(newre->flags, ZEBRA_FLAG_SELECTED)) zsend_redistribute_route( ZEBRA_REDISTRIBUTE_ROUTE_ADD, client, - &rn->p, NULL, newre); + rn, newre); } route_unlock_node(rn); @@ -116,20 +116,17 @@ static void zebra_redistribute(struct zserv *client, int type, for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) RNODE_FOREACH_RE (rn, newre) { - const struct prefix *dst_p, *src_p; - - srcdest_rnode_prefixes(rn, &dst_p, &src_p); - if (IS_ZEBRA_DEBUG_RIB) zlog_debug( - "%s: client %s %pFX(%u) checking: selected=%d, type=%d, distance=%d, metric=%d zebra_check_addr=%d", + "%s: client %s %pRN(%u:%u) checking: selected=%d, type=%d, distance=%d, metric=%d zebra_check_addr=%d", __func__, - zebra_route_string(client->proto), - dst_p, vrf_id, - CHECK_FLAG(newre->flags, - ZEBRA_FLAG_SELECTED), + zebra_route_string(client->proto), rn, + vrf_id, newre->instance, + !!CHECK_FLAG(newre->flags, + ZEBRA_FLAG_SELECTED), newre->type, newre->distance, - newre->metric, zebra_check_addr(dst_p)); + newre->metric, + zebra_check_addr(&rn->p)); if (!CHECK_FLAG(newre->flags, ZEBRA_FLAG_SELECTED)) continue; @@ -137,11 +134,11 @@ static void zebra_redistribute(struct zserv *client, int type, && (newre->type != type || newre->instance != instance))) continue; - if (!zebra_check_addr(dst_p)) + if (!zebra_check_addr(&rn->p)) continue; zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_ADD, - client, dst_p, src_p, newre); + client, rn, newre); } } @@ -149,23 +146,25 @@ static void zebra_redistribute(struct zserv *client, int type, * Function to check if prefix is candidate for * redistribute. */ -static bool zebra_redistribute_check(const struct route_entry *re, - struct zserv *client, - const struct prefix *p, int afi) +static bool zebra_redistribute_check(const struct route_node *rn, + const struct route_entry *re, + struct zserv *client) { struct zebra_vrf *zvrf; + afi_t afi; /* Process only if there is valid re */ if (!re) return false; + afi = family2afi(rn->p.family); zvrf = vrf_info_lookup(re->vrf_id); if (re->vrf_id == VRF_DEFAULT && zvrf->table_id != re->table) return false; /* If default route and redistributed */ - if (is_default_prefix(p) - && vrf_bitmap_check(client->redist_default[afi], re->vrf_id)) + if (is_default_prefix(&rn->p) && + vrf_bitmap_check(client->redist_default[afi], re->vrf_id)) return true; /* If redistribute in enabled for zebra route all */ @@ -176,10 +175,13 @@ static bool zebra_redistribute_check(const struct route_entry *re, * If multi-instance then check for route * redistribution for given instance. */ - if (re->instance - && redist_check_instance(&client->mi_redist[afi][re->type], - re->instance)) - return true; + if (re->instance) { + if (redist_check_instance(&client->mi_redist[afi][re->type], + re->instance)) + return true; + else + return false; + } /* If redistribution is enabled for give route type. */ if (vrf_bitmap_check(client->redist[afi][re->type], re->vrf_id)) @@ -190,49 +192,42 @@ static bool zebra_redistribute_check(const struct route_entry *re, /* Either advertise a route for redistribution to registered clients or */ /* withdraw redistribution if add cannot be done for client */ -void redistribute_update(const struct prefix *p, const struct prefix *src_p, +void redistribute_update(const struct route_node *rn, const struct route_entry *re, const struct route_entry *prev_re) { struct listnode *node, *nnode; struct zserv *client; - int afi; if (IS_ZEBRA_DEBUG_RIB) zlog_debug( - "(%u:%u):%pFX: Redist update re %p (%s), old %p (%s)", - re->vrf_id, re->table, p, re, + "(%u:%u):%pRN(%u): Redist update re %p (%s), old %p (%s)", + re->vrf_id, re->table, rn, re->instance, re, zebra_route_string(re->type), prev_re, prev_re ? zebra_route_string(prev_re->type) : "None"); - afi = family2afi(p->family); - if (!afi) { - flog_warn(EC_ZEBRA_REDISTRIBUTE_UNKNOWN_AF, - "%s: Unknown AFI/SAFI prefix received", __func__); - return; - } - if (!zebra_check_addr(p)) { + if (!zebra_check_addr(&rn->p)) { if (IS_ZEBRA_DEBUG_RIB) - zlog_debug("Redist update filter prefix %pFX", p); + zlog_debug("Redist update filter prefix %pRN", rn); return; } for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) { - if (zebra_redistribute_check(re, client, p, afi)) { + if (zebra_redistribute_check(rn, re, client)) { if (IS_ZEBRA_DEBUG_RIB) { zlog_debug( - "%s: client %s %pFX(%u:%u), type=%d, distance=%d, metric=%d", + "%s: client %s %pRN(%u:%u), type=%d, distance=%d, metric=%d", __func__, - zebra_route_string(client->proto), p, + zebra_route_string(client->proto), rn, re->vrf_id, re->table, re->type, re->distance, re->metric); } zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_ADD, - client, p, src_p, re); - } else if (zebra_redistribute_check(prev_re, client, p, afi)) + client, rn, re); + } else if (zebra_redistribute_check(rn, prev_re, client)) zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_DEL, - client, p, src_p, prev_re); + client, rn, prev_re); } } @@ -244,13 +239,12 @@ void redistribute_update(const struct prefix *p, const struct prefix *src_p, * may have seen a redist for 'old_re', but will not see * the redist for 'new_re'. */ -void redistribute_delete(const struct prefix *p, const struct prefix *src_p, +void redistribute_delete(const struct route_node *rn, const struct route_entry *old_re, const struct route_entry *new_re) { struct listnode *node, *nnode; struct zserv *client; - int afi; vrf_id_t vrfid; if (old_re) @@ -261,27 +255,34 @@ void redistribute_delete(const struct prefix *p, const struct prefix *src_p, return; if (IS_ZEBRA_DEBUG_RIB) { - zlog_debug("%u:%pFX: Redist del: re %p (%s), new re %p (%s)", - vrfid, p, old_re, - old_re ? zebra_route_string(old_re->type) : "None", - new_re, - new_re ? zebra_route_string(new_re->type) : "None"); - } + uint8_t old_inst, new_inst; + uint32_t table = 0; - afi = family2afi(p->family); - if (!afi) { - flog_warn(EC_ZEBRA_REDISTRIBUTE_UNKNOWN_AF, - "%s: Unknown AFI/SAFI prefix received", - __func__); - return; + old_inst = new_inst = 0; + + if (old_re) { + old_inst = old_re->instance; + table = old_re->table; + } + if (new_re) { + new_inst = new_re->instance; + table = new_re->table; + } + + zlog_debug( + "%u:%u%pRN: Redist del: re %p (%u:%s), new re %p (%u:%s)", + vrfid, table, rn, old_re, old_inst, + old_re ? zebra_route_string(old_re->type) : "None", + new_re, new_inst, + new_re ? zebra_route_string(new_re->type) : "None"); } /* Skip invalid (e.g. linklocal) prefix */ - if (!zebra_check_addr(p)) { + if (!zebra_check_addr(&rn->p)) { if (IS_ZEBRA_DEBUG_RIB) { zlog_debug( - "%u:%pFX: Redist del old: skipping invalid prefix", - vrfid, p); + "%u:%pRN: Redist del old: skipping invalid prefix", + vrfid, rn); } return; } @@ -294,13 +295,13 @@ void redistribute_delete(const struct prefix *p, const struct prefix *src_p, * Skip this client if it will receive an update for the * 'new' re */ - if (zebra_redistribute_check(new_re, client, p, afi)) + if (zebra_redistribute_check(rn, new_re, client)) continue; /* Send a delete for the 'old' re to any subscribed client. */ - if (zebra_redistribute_check(old_re, client, p, afi)) + if (zebra_redistribute_check(rn, old_re, client)) zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_DEL, - client, p, src_p, old_re); + client, rn, old_re); } } @@ -533,14 +534,12 @@ void zebra_interface_address_add_update(struct interface *ifp, { struct listnode *node, *nnode; struct zserv *client; - struct prefix *p; - if (IS_ZEBRA_DEBUG_EVENT) { - p = ifc->address; + if (IS_ZEBRA_DEBUG_EVENT) zlog_debug( "MESSAGE: ZEBRA_INTERFACE_ADDRESS_ADD %pFX on %s vrf %s(%u)", - p, ifp->name, ifp->vrf->name, ifp->vrf->vrf_id); - } + ifc->address, ifp->name, ifp->vrf->name, + ifp->vrf->vrf_id); if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) flog_warn( @@ -570,14 +569,12 @@ void zebra_interface_address_delete_update(struct interface *ifp, { struct listnode *node, *nnode; struct zserv *client; - struct prefix *p; - if (IS_ZEBRA_DEBUG_EVENT) { - p = ifc->address; + if (IS_ZEBRA_DEBUG_EVENT) zlog_debug( "MESSAGE: ZEBRA_INTERFACE_ADDRESS_DELETE %pFX on %s vrf %s(%u)", - p, ifp->name, ifp->vrf->name, ifp->vrf->vrf_id); - } + ifc->address, ifp->name, ifp->vrf->name, + ifp->vrf->vrf_id); zebra_vxlan_add_del_gw_macip(ifp, ifc->address, 0); diff --git a/zebra/redistribute.h b/zebra/redistribute.h index 2685458f96..ac257d6389 100644 --- a/zebra/redistribute.h +++ b/zebra/redistribute.h @@ -40,8 +40,7 @@ extern void zebra_redistribute_default_add(ZAPI_HANDLER_ARGS); extern void zebra_redistribute_default_delete(ZAPI_HANDLER_ARGS); /* ----------------- */ -extern void redistribute_update(const struct prefix *p, - const struct prefix *src_p, +extern void redistribute_update(const struct route_node *rn, const struct route_entry *re, const struct route_entry *prev_re); /* @@ -52,24 +51,24 @@ extern void redistribute_update(const struct prefix *p, * may have seen a redist for 'old_re', but will not see * the redist for 'new_re'. */ -void redistribute_delete(const struct prefix *p, const struct prefix *src_p, +void redistribute_delete(const struct route_node *rn, const struct route_entry *old_re, const struct route_entry *new_re); -extern void zebra_interface_up_update(struct interface *); -extern void zebra_interface_down_update(struct interface *); +extern void zebra_interface_up_update(struct interface *ifp); +extern void zebra_interface_down_update(struct interface *ifp); -extern void zebra_interface_add_update(struct interface *); -extern void zebra_interface_delete_update(struct interface *); +extern void zebra_interface_add_update(struct interface *ifp); +extern void zebra_interface_delete_update(struct interface *ifp); -extern void zebra_interface_address_add_update(struct interface *, - struct connected *); -extern void zebra_interface_address_delete_update(struct interface *, +extern void zebra_interface_address_add_update(struct interface *ifp, + struct connected *c); +extern void zebra_interface_address_delete_update(struct interface *ifp, struct connected *c); -extern void zebra_interface_parameters_update(struct interface *); -extern void zebra_interface_vrf_update_del(struct interface *, +extern void zebra_interface_parameters_update(struct interface *ifp); +extern void zebra_interface_vrf_update_del(struct interface *ifp, vrf_id_t new_vrf_id); -extern void zebra_interface_vrf_update_add(struct interface *, +extern void zebra_interface_vrf_update_add(struct interface *ifp, vrf_id_t old_vrf_id); extern int zebra_import_table(afi_t afi, vrf_id_t vrf_id, diff --git a/zebra/rib.h b/zebra/rib.h index b7416322f9..a0ec1f0e4f 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -493,6 +493,9 @@ extern uint8_t route_distance(int type); extern void zebra_rib_evaluate_rn_nexthops(struct route_node *rn, uint32_t seq, bool rt_delete); +extern struct route_node * +rib_find_rn_from_ctx(const struct zebra_dplane_ctx *ctx); + /* * Inline functions. */ diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 421438a051..c3d7bcd909 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -546,18 +546,19 @@ int zsend_interface_update(int cmd, struct zserv *client, struct interface *ifp) } int zsend_redistribute_route(int cmd, struct zserv *client, - const struct prefix *p, - const struct prefix *src_p, + const struct route_node *rn, const struct route_entry *re) { struct zapi_route api; struct zapi_nexthop *api_nh; struct nexthop *nexthop; + const struct prefix *p, *src_p; uint8_t count = 0; afi_t afi; size_t stream_size = MAX(ZEBRA_MAX_PACKET_SIZ, sizeof(struct zapi_route)); + srcdest_rnode_prefixes(rn, &p, &src_p); memset(&api, 0, sizeof(api)); api.vrf_id = re->vrf_id; api.type = re->type; @@ -742,11 +743,11 @@ int zsend_nhg_notify(uint16_t type, uint16_t instance, uint32_t session_id, * Common utility send route notification, called from a path using a * route_entry and from a path using a dataplane context. */ -static int route_notify_internal(const struct prefix *p, int type, +static int route_notify_internal(const struct route_node *rn, int type, uint16_t instance, vrf_id_t vrf_id, uint32_t table_id, - enum zapi_route_notify_owner note, - afi_t afi, safi_t safi) + enum zapi_route_notify_owner note, afi_t afi, + safi_t safi) { struct zserv *client; struct stream *s; @@ -756,16 +757,16 @@ static int route_notify_internal(const struct prefix *p, int type, if (!client || !client->notify_owner) { if (IS_ZEBRA_DEBUG_PACKET) zlog_debug( - "Not Notifying Owner: %s about prefix %pFX(%u) %d vrf: %u", - zebra_route_string(type), p, table_id, note, + "Not Notifying Owner: %s about prefix %pRN(%u) %d vrf: %u", + zebra_route_string(type), rn, table_id, note, vrf_id); return 0; } if (IS_ZEBRA_DEBUG_PACKET) zlog_debug( - "Notifying Owner: %s about prefix %pFX(%u) %d vrf: %u", - zebra_route_string(type), p, table_id, note, vrf_id); + "Notifying Owner: %s about prefix %pRN(%u) %d vrf: %u", + zebra_route_string(type), rn, table_id, note, vrf_id); /* We're just allocating a small-ish buffer here, since we only * encode a small amount of data. @@ -778,11 +779,11 @@ static int route_notify_internal(const struct prefix *p, int type, stream_put(s, ¬e, sizeof(note)); - stream_putc(s, p->family); + stream_putc(s, rn->p.family); - blen = prefix_blen(p); - stream_putc(s, p->prefixlen); - stream_put(s, &p->u.prefix, blen); + blen = prefix_blen(&rn->p); + stream_putc(s, rn->p.prefixlen); + stream_put(s, &rn->p.u.prefix, blen); stream_putl(s, table_id); @@ -795,11 +796,12 @@ static int route_notify_internal(const struct prefix *p, int type, return zserv_send_message(client, s); } -int zsend_route_notify_owner(struct route_entry *re, const struct prefix *p, - enum zapi_route_notify_owner note, - afi_t afi, safi_t safi) +int zsend_route_notify_owner(const struct route_node *rn, + struct route_entry *re, + enum zapi_route_notify_owner note, afi_t afi, + safi_t safi) { - return (route_notify_internal(p, re->type, re->instance, re->vrf_id, + return (route_notify_internal(rn, re->type, re->instance, re->vrf_id, re->table, note, afi, safi)); } @@ -809,14 +811,11 @@ int zsend_route_notify_owner(struct route_entry *re, const struct prefix *p, int zsend_route_notify_owner_ctx(const struct zebra_dplane_ctx *ctx, enum zapi_route_notify_owner note) { - return (route_notify_internal(dplane_ctx_get_dest(ctx), - dplane_ctx_get_type(ctx), - dplane_ctx_get_instance(ctx), - dplane_ctx_get_vrf(ctx), - dplane_ctx_get_table(ctx), - note, - dplane_ctx_get_afi(ctx), - dplane_ctx_get_safi(ctx))); + return (route_notify_internal( + rib_find_rn_from_ctx(ctx), dplane_ctx_get_type(ctx), + dplane_ctx_get_instance(ctx), dplane_ctx_get_vrf(ctx), + dplane_ctx_get_table(ctx), note, dplane_ctx_get_afi(ctx), + dplane_ctx_get_safi(ctx))); } static void zread_route_notify_request(ZAPI_HANDLER_ARGS) @@ -2093,6 +2092,7 @@ static void zread_route_add(ZAPI_HANDLER_ARGS) __func__); nexthop_group_delete(&ng); zebra_nhg_backup_free(&bnhg); + XFREE(MTYPE_OPAQUE, re->opaque); XFREE(MTYPE_RE, re); return; } @@ -2105,6 +2105,7 @@ static void zread_route_add(ZAPI_HANDLER_ARGS) __func__, api.safi); nexthop_group_delete(&ng); zebra_nhg_backup_free(&bnhg); + XFREE(MTYPE_OPAQUE, re->opaque); XFREE(MTYPE_RE, re); return; } @@ -2133,6 +2134,7 @@ static void zread_route_add(ZAPI_HANDLER_ARGS) */ if (ret == -1) { client->error_cnt++; + XFREE(MTYPE_OPAQUE, re->opaque); XFREE(MTYPE_RE, re); } diff --git a/zebra/zapi_msg.h b/zebra/zapi_msg.h index dad40c200d..b3fe7318f9 100644 --- a/zebra/zapi_msg.h +++ b/zebra/zapi_msg.h @@ -65,8 +65,7 @@ extern void nbr_connected_delete_ipv6(struct interface *ifp, extern int zsend_interface_update(int cmd, struct zserv *client, struct interface *ifp); extern int zsend_redistribute_route(int cmd, struct zserv *zclient, - const struct prefix *p, - const struct prefix *src_p, + const struct route_node *rn, const struct route_entry *re); extern int zsend_router_id_update(struct zserv *zclient, afi_t afi, @@ -76,8 +75,8 @@ extern int zsend_interface_vrf_update(struct zserv *zclient, extern int zsend_interface_link_params(struct zserv *zclient, struct interface *ifp); extern int zsend_pw_update(struct zserv *client, struct zebra_pw *pw); -extern int zsend_route_notify_owner(struct route_entry *re, - const struct prefix *p, +extern int zsend_route_notify_owner(const struct route_node *rn, + struct route_entry *re, enum zapi_route_notify_owner note, afi_t afi, safi_t safi); extern int zsend_route_notify_owner_ctx(const struct zebra_dplane_ctx *ctx, diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 1279c7c9a9..1374b932ae 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -575,7 +575,7 @@ void rib_install_kernel(struct route_node *rn, struct route_entry *re, * know that they've lost */ if (old && (old != re) && (old->type != re->type)) - zsend_route_notify_owner(old, p, ZAPI_ROUTE_BETTER_ADMIN_WON, + zsend_route_notify_owner(rn, old, ZAPI_ROUTE_BETTER_ADMIN_WON, info->afi, info->safi); /* Update fib selection */ @@ -745,9 +745,9 @@ void zebra_rib_evaluate_rn_nexthops(struct route_node *rn, uint32_t seq, if (IS_ZEBRA_DEBUG_NHT_DETAILED) zlog_debug( - "%s(%u):%pRN has Nexthop(%pFX) depending on it, evaluating %u:%u", - zvrf_name(zvrf), zvrf_id(zvrf), rn, p, - seq, rnh->seqno); + "%s(%u):%pRN has Nexthop(%pRN) depending on it, evaluating %u:%u", + zvrf_name(zvrf), zvrf_id(zvrf), rn, + rnh->node, seq, rnh->seqno); /* * If we have evaluated this node on this pass @@ -1088,9 +1088,7 @@ static void rib_process(struct route_node *rn) rib_dest_t *dest; struct zebra_vrf *zvrf = NULL; struct vrf *vrf; - const struct prefix *p, *src_p; - srcdest_rnode_prefixes(rn, &p, &src_p); vrf_id_t vrf_id = VRF_UNKNOWN; assert(rn); @@ -1194,9 +1192,9 @@ static void rib_process(struct route_node *rn) info = srcdest_rnode_table_info(rn); srcdest_rnode_prefixes(rn, &p, NULL); - zsend_route_notify_owner(re, p, - ZAPI_ROUTE_FAIL_INSTALL, - info->afi, info->safi); + zsend_route_notify_owner( + rn, re, ZAPI_ROUTE_FAIL_INSTALL, + info->afi, info->safi); continue; } } else { @@ -1288,8 +1286,7 @@ static void rib_process(struct route_node *rn) */ if (!new_selected || CHECK_FLAG(old_selected->status, ROUTE_ENTRY_REMOVED)) - redistribute_delete(p, src_p, - old_selected, + redistribute_delete(rn, old_selected, new_selected); if (old_selected != new_selected) @@ -1758,8 +1755,7 @@ done: * when processing dplane results, e.g. Note well: the route-node is returned * with a ref held - route_unlock_node() must be called eventually. */ -static struct route_node * -rib_find_rn_from_ctx(const struct zebra_dplane_ctx *ctx) +struct route_node *rib_find_rn_from_ctx(const struct zebra_dplane_ctx *ctx) { struct route_table *table = NULL; struct route_node *rn = NULL; @@ -1806,7 +1802,6 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx) bool is_update = false; enum dplane_op_e op; enum zebra_dplane_result status; - const struct prefix *dest_pfx, *src_pfx; uint32_t seq; rib_dest_t *dest; bool fib_changed = false; @@ -1815,22 +1810,19 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx) zvrf = vrf_info_lookup(dplane_ctx_get_vrf(ctx)); vrf = vrf_lookup_by_id(dplane_ctx_get_vrf(ctx)); - dest_pfx = dplane_ctx_get_dest(ctx); /* Locate rn and re(s) from ctx */ rn = rib_find_rn_from_ctx(ctx); if (rn == NULL) { if (IS_ZEBRA_DEBUG_DPLANE) { zlog_debug( - "Failed to process dplane results: no route for %s(%u):%pFX", - VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx), - dest_pfx); + "Failed to process dplane results: no route for %s(%u):%pRN", + VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx), rn); } goto done; } dest = rib_dest_from_rnode(rn); - srcdest_rnode_prefixes(rn, &dest_pfx, &src_pfx); info = srcdest_rnode_table_info(rn); op = dplane_ctx_get_op(ctx); @@ -1838,10 +1830,10 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx) if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) zlog_debug( - "%s(%u:%u):%pFX Processing dplane result ctx %p, op %s result %s", + "%s(%u:%u):%pRN Processing dplane result ctx %p, op %s result %s", VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx), - dplane_ctx_get_table(ctx), dest_pfx, ctx, - dplane_op2str(op), dplane_res2str(status)); + dplane_ctx_get_table(ctx), rn, ctx, dplane_op2str(op), + dplane_res2str(status)); /* * Update is a bit of a special case, where we may have both old and new @@ -1880,9 +1872,9 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx) if (re->dplane_sequence != seq) { if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) zlog_debug( - "%s(%u):%pFX Stale dplane result for re %p", + "%s(%u):%pRN Stale dplane result for re %p", VRF_LOGNAME(vrf), - dplane_ctx_get_vrf(ctx), dest_pfx, re); + dplane_ctx_get_vrf(ctx), rn, re); } else { if (!zrouter.asic_offloaded || (CHECK_FLAG(re->flags, ZEBRA_FLAG_OFFLOADED) || @@ -1895,10 +1887,10 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx) if (old_re->dplane_sequence != dplane_ctx_get_old_seq(ctx)) { if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) zlog_debug( - "%s(%u:%u):%pFX Stale dplane result for old_re %p", + "%s(%u:%u):%pRN Stale dplane result for old_re %p", VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx), old_re->table, - dest_pfx, old_re); + rn, old_re); } else UNSET_FLAG(old_re->status, ROUTE_ENTRY_QUEUED); } @@ -1936,18 +1928,17 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx) if (!fib_changed) { if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) zlog_debug( - "%s(%u:%u):%pFX no fib change for re", + "%s(%u:%u):%pRN no fib change for re", VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx), dplane_ctx_get_table( ctx), - dest_pfx); + rn); } /* Redistribute if this is the selected re */ if (dest && re == dest->selected_fib) - redistribute_update(dest_pfx, src_pfx, - re, old_re); + redistribute_update(rn, re, old_re); } /* @@ -1989,13 +1980,13 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx) } if (old_re) SET_FLAG(old_re->status, ROUTE_ENTRY_FAILED); if (re) - zsend_route_notify_owner(re, dest_pfx, - ZAPI_ROUTE_FAIL_INSTALL, - info->afi, info->safi); + zsend_route_notify_owner( + rn, re, ZAPI_ROUTE_FAIL_INSTALL, + info->afi, info->safi); - zlog_warn("%s(%u:%u):%pFX: Route install failed", + zlog_warn("%s(%u:%u):%pRN: Route install failed", VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx), - dplane_ctx_get_table(ctx), dest_pfx); + dplane_ctx_get_table(ctx), rn); } break; case DPLANE_OP_ROUTE_DELETE: @@ -2022,9 +2013,9 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx) zsend_route_notify_owner_ctx(ctx, ZAPI_ROUTE_REMOVE_FAIL); - zlog_warn("%s(%u:%u):%pFX: Route Deletion failure", + zlog_warn("%s(%u:%u):%pRN: Route Deletion failure", VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx), - dplane_ctx_get_table(ctx), dest_pfx); + dplane_ctx_get_table(ctx), rn); } /* @@ -2099,12 +2090,11 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx) struct route_entry *re = NULL; struct vrf *vrf; struct nexthop *nexthop; - const struct prefix *dest_pfx, *src_pfx; rib_dest_t *dest; bool fib_changed = false; bool debug_p = IS_ZEBRA_DEBUG_DPLANE | IS_ZEBRA_DEBUG_RIB; int start_count, end_count; - dest_pfx = dplane_ctx_get_dest(ctx); + vrf = vrf_lookup_by_id(dplane_ctx_get_vrf(ctx)); /* Locate rn and re(s) from ctx */ @@ -2112,20 +2102,19 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx) if (rn == NULL) { if (debug_p) { zlog_debug( - "Failed to process dplane notification: no routes for %s(%u:%u):%pFX", + "Failed to process dplane notification: no routes for %s(%u:%u):%pRN", VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx), - dplane_ctx_get_table(ctx), dest_pfx); + dplane_ctx_get_table(ctx), rn); } goto done; } dest = rib_dest_from_rnode(rn); - srcdest_rnode_prefixes(rn, &dest_pfx, &src_pfx); if (debug_p) - zlog_debug("%s(%u:%u):%pFX Processing dplane notif ctx %p", + zlog_debug("%s(%u:%u):%pRN Processing dplane notif ctx %p", VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx), - dplane_ctx_get_table(ctx), dest_pfx, ctx); + dplane_ctx_get_table(ctx), rn, ctx); /* * Take a pass through the routes, look for matches with the context @@ -2140,9 +2129,9 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx) if (re == NULL) { if (debug_p) zlog_debug( - "%s(%u:%u):%pFX Unable to process dplane notification: no entry for type %s", + "%s(%u:%u):%pRN Unable to process dplane notification: no entry for type %s", VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx), - dplane_ctx_get_table(ctx), dest_pfx, + dplane_ctx_get_table(ctx), rn, zebra_route_string(dplane_ctx_get_type(ctx))); goto done; @@ -2175,20 +2164,20 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx) UNSET_FLAG(re->status, ROUTE_ENTRY_INSTALLED); if (debug_p) zlog_debug( - "%s(%u:%u):%pFX dplane notif, uninstalled type %s route", + "%s(%u:%u):%pRN dplane notif, uninstalled type %s route", VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx), - dplane_ctx_get_table(ctx), dest_pfx, + dplane_ctx_get_table(ctx), rn, zebra_route_string( dplane_ctx_get_type(ctx))); } else { /* At least report on the event. */ if (debug_p) zlog_debug( - "%s(%u:%u):%pFX dplane notif, but type %s not selected_fib", + "%s(%u:%u):%pRN dplane notif, but type %s not selected_fib", VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx), - dplane_ctx_get_table(ctx), dest_pfx, + dplane_ctx_get_table(ctx), rn, zebra_route_string( dplane_ctx_get_type(ctx))); } @@ -2212,9 +2201,9 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx) if (!fib_changed) { if (debug_p) zlog_debug( - "%s(%u:%u):%pFX dplane notification: rib_update returns FALSE", + "%s(%u:%u):%pRN dplane notification: rib_update returns FALSE", VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx), - dplane_ctx_get_table(ctx), dest_pfx); + dplane_ctx_get_table(ctx), rn); } /* @@ -2229,9 +2218,9 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx) if (start_count > 0 && end_count > 0) { if (debug_p) zlog_debug( - "%s(%u:%u):%pFX applied nexthop changes from dplane notification", + "%s(%u:%u):%pRN applied nexthop changes from dplane notification", VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx), - dplane_ctx_get_table(ctx), dest_pfx); + dplane_ctx_get_table(ctx), rn); /* Changed nexthops - update kernel/others */ dplane_route_notif_update(rn, re, @@ -2240,9 +2229,9 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx) } else if (start_count == 0 && end_count > 0) { if (debug_p) zlog_debug( - "%s(%u:%u):%pFX installed transition from dplane notification", + "%s(%u:%u):%pRN installed transition from dplane notification", VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx), - dplane_ctx_get_table(ctx), dest_pfx); + dplane_ctx_get_table(ctx), rn); /* We expect this to be the selected route, so we want * to tell others about this transition. @@ -2253,14 +2242,14 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx) dplane_route_notif_update(rn, re, DPLANE_OP_ROUTE_UPDATE, ctx); /* Redistribute, lsp, and nht update */ - redistribute_update(dest_pfx, src_pfx, re, NULL); + redistribute_update(rn, re, NULL); } else if (start_count > 0 && end_count == 0) { if (debug_p) zlog_debug( - "%s(%u:%u):%pFX un-installed transition from dplane notification", + "%s(%u:%u):%pRN un-installed transition from dplane notification", VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx), - dplane_ctx_get_table(ctx), dest_pfx); + dplane_ctx_get_table(ctx), rn); /* Transition from _something_ installed to _nothing_ * installed. @@ -2274,7 +2263,7 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx) dplane_route_notif_update(rn, re, DPLANE_OP_ROUTE_DELETE, ctx); /* Redistribute, lsp, and nht update */ - redistribute_delete(dest_pfx, src_pfx, re, NULL); + redistribute_delete(rn, re, NULL); } /* Make any changes visible for lsp and nexthop-tracking processing */ @@ -3522,8 +3511,8 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, else src_buf[0] = '\0'; - zlog_debug("%s[%d]:%pFX%s%s doesn't exist in rib", - vrf->name, table_id, p, + zlog_debug("%s[%d]:%pRN%s%s doesn't exist in rib", + vrf->name, table_id, rn, (src_buf[0] != '\0') ? " from " : "", src_buf); } |
