summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/freeze.yml17
-rw-r--r--babeld/babel_interface.c18
-rw-r--r--babeld/babeld.c2
-rw-r--r--bfdd/bfd_packet.c3
-rw-r--r--bfdd/ptm_adapter.c1
-rw-r--r--bgpd/bgp_aspath.c10
-rw-r--r--bgpd/bgp_aspath.h3
-rw-r--r--bgpd/bgp_dump.c4
-rw-r--r--bgpd/bgp_evpn.c80
-rw-r--r--bgpd/bgp_evpn_mh.c30
-rw-r--r--bgpd/bgp_evpn_vty.c11
-rw-r--r--bgpd/bgp_flowspec.c21
-rw-r--r--bgpd/bgp_fsm.c18
-rw-r--r--bgpd/bgp_mac.c14
-rw-r--r--bgpd/bgp_nexthop.c19
-rw-r--r--bgpd/bgp_nexthop.h2
-rw-r--r--bgpd/bgp_route.c106
-rw-r--r--bgpd/bgp_route.h22
-rw-r--r--bgpd/bgp_vty.c4
-rw-r--r--bgpd/bgpd.c1
-rw-r--r--bgpd/rfapi/rfapi_vty.c1
-rw-r--r--configure.ac2
-rw-r--r--isisd/isis_cli.c4
-rw-r--r--ldpd/log.c4
-rw-r--r--lib/bfd.c95
-rw-r--r--lib/bfd.h7
-rw-r--r--lib/clippy.c1
-rw-r--r--lib/command.h3
-rw-r--r--lib/ferr.c1
-rw-r--r--lib/ferr.h9
-rw-r--r--lib/filter_cli.c24
-rw-r--r--lib/filter_nb.c19
-rw-r--r--lib/frrscript.h2
-rw-r--r--lib/grammar_sandbox_main.c4
-rw-r--r--lib/if.c4
-rw-r--r--lib/northbound_cli.h5
-rw-r--r--lib/printf/glue.c4
-rw-r--r--lib/printf/vfprintf.c6
-rw-r--r--lib/termtable.c10
-rw-r--r--lib/vrf.c2
-rw-r--r--lib/vty.c14
-rw-r--r--lib/wheel.c15
-rw-r--r--lib/wheel.h10
-rw-r--r--lib/yang.h15
-rw-r--r--lib/yang_translator.c8
-rw-r--r--lib/yang_wrappers.c2
-rw-r--r--lib/yang_wrappers.h96
-rw-r--r--lib/zlog.c8
-rw-r--r--pathd/path_nb.c2
-rw-r--r--pathd/path_pcep_lib.c3
-rw-r--r--pceplib/pcep_utils_logging.c4
-rw-r--r--pimd/pim_cmd.c14
-rw-r--r--pimd/pim_cmd_common.c4
-rw-r--r--staticd/static_vty.c4
-rw-r--r--staticd/static_zebra.c3
-rw-r--r--tests/topotests/all_protocol_startup/r1/ip_nht.ref24
-rw-r--r--tests/topotests/all_protocol_startup/r1/ipv6_nht.ref8
-rw-r--r--tests/topotests/babel_topo1/r1/babeld.conf21
-rw-r--r--tests/topotests/babel_topo1/r1/show_ip_route.json_ref80
-rw-r--r--tests/topotests/babel_topo1/r1/zebra.conf22
-rw-r--r--tests/topotests/babel_topo1/r2/babeld.conf18
-rw-r--r--tests/topotests/babel_topo1/r2/show_ip_route.json_ref80
-rw-r--r--tests/topotests/babel_topo1/r2/zebra.conf23
-rw-r--r--tests/topotests/babel_topo1/r3/babeld.conf18
-rw-r--r--tests/topotests/babel_topo1/r3/show_ip_route.json_ref81
-rw-r--r--tests/topotests/babel_topo1/r3/zebra.conf25
-rw-r--r--tests/topotests/babel_topo1/test_babel_topo1.py171
-rw-r--r--tests/topotests/bgp_dont_capability_negotiate/r1/bgpd.conf6
-rw-r--r--tests/topotests/bgp_dont_capability_negotiate/r2/bgpd.conf2
-rw-r--r--tests/topotests/bgp_dont_capability_negotiate/test_bgp_dont_capability_negotiate.py97
-rw-r--r--tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vpn_routes.json5
-rw-r--r--tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vpn_routes_unfiltered.json7
-rw-r--r--tests/topotests/bgp_vpnv4_noretain/test_bgp_vpnv4_noretain.py49
-rw-r--r--tests/topotests/lib/topotest.py11
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_lan.py2
-rw-r--r--tests/topotests/ospf_gr_helper/test_ospf_gr_helper1.py2
-rw-r--r--tests/topotests/ospf_gr_helper/test_ospf_gr_helper2.py2
-rw-r--r--tests/topotests/ospf_gr_helper/test_ospf_gr_helper3.py2
-rw-r--r--vtysh/vtysh.c14
-rw-r--r--watchfrr/watchfrr.c15
-rw-r--r--zebra/dplane_fpm_nl.c4
-rw-r--r--zebra/kernel_netlink.c17
-rw-r--r--zebra/kernel_socket.c8
-rw-r--r--zebra/rt.h2
-rw-r--r--zebra/zebra_dplane.c237
-rw-r--r--zebra/zebra_dplane.h25
-rw-r--r--zebra/zebra_nhg.c9
-rw-r--r--zebra/zebra_rib.c45
-rw-r--r--zebra/zebra_rnh.c319
-rw-r--r--zebra/zebra_rnh.h6
-rw-r--r--zebra/zebra_vty.c342
91 files changed, 1539 insertions, 1055 deletions
diff --git a/.github/workflows/freeze.yml b/.github/workflows/freeze.yml
new file mode 100644
index 0000000000..f3506d0061
--- /dev/null
+++ b/.github/workflows/freeze.yml
@@ -0,0 +1,17 @@
+name: Warn before merging if a "freeze" label exists
+
+on:
+ pull_request_target:
+ types: [synchronize, opened, reopened, labeled, unlabeled]
+
+jobs:
+ freeze_warning:
+ if: ${{ contains(github.event.*.labels.*.name, 'freeze') }}
+ name: Warn before merging if a "freeze" label exists
+ runs-on: ubuntu-latest
+ steps:
+ - name: Check for "freeze" label
+ run: |
+ echo "Pull request is labeled as 'freeze'"
+ echo "This workflow fails so that the pull request cannot be merged."
+ exit 1
diff --git a/babeld/babel_interface.c b/babeld/babel_interface.c
index cc50898017..4ca875206f 100644
--- a/babeld/babel_interface.c
+++ b/babeld/babel_interface.c
@@ -632,15 +632,15 @@ interface_recalculate(struct interface *ifp)
rc = setsockopt(protocol_socket, IPPROTO_IPV6, IPV6_JOIN_GROUP,
(char*)&mreq, sizeof(mreq));
- if(rc < 0) {
- flog_err_sys(EC_LIB_SOCKET,
- "setsockopt(IPV6_JOIN_GROUP) on interface '%s': %s",
- ifp->name, safe_strerror(errno));
- /* This is probably due to a missing link-local address,
- so down this interface, and wait until the main loop
- tries to up it again. */
- interface_reset(ifp);
- return -1;
+ if (rc < 0 && errno != EADDRINUSE) {
+ flog_err_sys(EC_LIB_SOCKET,
+ "setsockopt(IPV6_JOIN_GROUP) on interface '%s': %s",
+ ifp->name, safe_strerror(errno));
+ /* This is probably due to a missing link-local address,
+ so down this interface, and wait until the main loop
+ tries to up it again. */
+ interface_reset(ifp);
+ return -1;
}
set_timeout(&babel_ifp->hello_timeout, babel_ifp->hello_interval);
diff --git a/babeld/babeld.c b/babeld/babeld.c
index 34e1a4318b..972d52819b 100644
--- a/babeld/babeld.c
+++ b/babeld/babeld.c
@@ -165,7 +165,7 @@ babel_create_routing_process (void)
}
/* Threads. */
- thread_add_read(master, &babel_read_protocol, NULL, protocol_socket, &babel_routing_process->t_read);
+ thread_add_read(master, babel_read_protocol, NULL, protocol_socket, &babel_routing_process->t_read);
/* wait a little: zebra will announce interfaces, addresses, routes... */
thread_add_timer_msec(master, babel_init_routing_process, NULL, 200L, &babel_routing_process->t_update);
diff --git a/bfdd/bfd_packet.c b/bfdd/bfd_packet.c
index 6397aa5747..30f54f130f 100644
--- a/bfdd/bfd_packet.c
+++ b/bfdd/bfd_packet.c
@@ -746,6 +746,7 @@ static void bfd_sd_reschedule(struct bfd_vrf_global *bvrf, int sd)
}
}
+PRINTFRR(6, 7)
static void cp_debug(bool mhop, struct sockaddr_any *peer,
struct sockaddr_any *local, ifindex_t ifindex,
vrf_id_t vrfid, const char *fmt, ...)
@@ -844,7 +845,7 @@ void bfd_recv_cb(struct thread *t)
/* Implement RFC 5880 6.8.6 */
if (mlen < BFD_PKT_LEN) {
cp_debug(is_mhop, &peer, &local, ifindex, vrfid,
- "too small (%ld bytes)", mlen);
+ "too small (%zd bytes)", mlen);
return;
}
diff --git a/bfdd/ptm_adapter.c b/bfdd/ptm_adapter.c
index f6259b9c3b..8a27fced5f 100644
--- a/bfdd/ptm_adapter.c
+++ b/bfdd/ptm_adapter.c
@@ -81,6 +81,7 @@ static void bfdd_client_deregister(struct stream *msg);
/*
* Functions
*/
+PRINTFRR(2, 3)
static void debug_printbpc(const struct bfd_peer_cfg *bpc, const char *fmt, ...)
{
char timers[3][128] = {};
diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c
index 85f09ccf0b..2ae693cd30 100644
--- a/bgpd/bgp_aspath.c
+++ b/bgpd/bgp_aspath.c
@@ -2122,16 +2122,12 @@ const char *aspath_print(struct aspath *as)
}
/* Printing functions */
-/* Feed the AS_PATH to the vty; the suffix string follows it only in case
+/* Feed the AS_PATH to the vty; the space suffix follows it only in case
* AS_PATH wasn't empty.
*/
-void aspath_print_vty(struct vty *vty, const char *format, struct aspath *as,
- const char *suffix)
+void aspath_print_vty(struct vty *vty, struct aspath *as)
{
- assert(format);
- vty_out(vty, format, as->str);
- if (as->str_len && strlen(suffix))
- vty_out(vty, "%s", suffix);
+ vty_out(vty, "%s%s", as->str, as->str_len ? " " : "");
}
static void aspath_show_all_iterator(struct hash_bucket *bucket,
diff --git a/bgpd/bgp_aspath.h b/bgpd/bgp_aspath.h
index 97bc7c0aca..a814d73ddd 100644
--- a/bgpd/bgp_aspath.h
+++ b/bgpd/bgp_aspath.h
@@ -104,8 +104,7 @@ extern void aspath_free(struct aspath *aspath);
extern struct aspath *aspath_intern(struct aspath *aspath);
extern void aspath_unintern(struct aspath **aspath);
extern const char *aspath_print(struct aspath *aspath);
-extern void aspath_print_vty(struct vty *vty, const char *format,
- struct aspath *aspath, const char *suffix);
+extern void aspath_print_vty(struct vty *vty, struct aspath *aspath);
extern void aspath_print_all_vty(struct vty *vty);
extern unsigned int aspath_key_make(const void *p);
extern unsigned int aspath_get_first_as(struct aspath *aspath);
diff --git a/bgpd/bgp_dump.c b/bgpd/bgp_dump.c
index 254996edad..98a2f95ead 100644
--- a/bgpd/bgp_dump.c
+++ b/bgpd/bgp_dump.c
@@ -117,9 +117,13 @@ static FILE *bgp_dump_open_file(struct bgp_dump *bgp_dump)
if (bgp_dump->filename[0] != DIRECTORY_SEP) {
snprintf(fullpath, sizeof(fullpath), "%s/%s", vty_get_cwd(),
bgp_dump->filename);
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+ /* user supplied date/time format string */
ret = strftime(realpath, MAXPATHLEN, fullpath, &tm);
} else
ret = strftime(realpath, MAXPATHLEN, bgp_dump->filename, &tm);
+#pragma GCC diagnostic pop
if (ret == 0) {
flog_warn(EC_BGP_DUMP, "%s: strftime error", __func__);
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index c9e935668e..c993707206 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -2736,23 +2736,29 @@ static int bgp_evpn_mcast_grp_change(struct bgp *bgp, struct bgpevpn *vpn,
* Note: Route re-advertisement happens elsewhere after other processing
* other changes.
*/
-static int handle_tunnel_ip_change(struct bgp *bgp, struct bgpevpn *vpn,
- struct in_addr originator_ip)
+static void handle_tunnel_ip_change(struct bgp *bgp, struct bgpevpn *vpn,
+ struct in_addr originator_ip)
{
struct prefix_evpn p;
+ if (IPV4_ADDR_SAME(&vpn->originator_ip, &originator_ip))
+ return;
+
/* If VNI is not live, we only need to update the originator ip */
if (!is_vni_live(vpn)) {
vpn->originator_ip = originator_ip;
- return 0;
+ return;
}
/* Update the tunnel-ip hash */
bgp_tip_del(bgp, &vpn->originator_ip);
- bgp_tip_add(bgp, &originator_ip);
-
- /* filter routes as martian nexthop db has changed */
- bgp_filter_evpn_routes_upon_martian_nh_change(bgp);
+ if (bgp_tip_add(bgp, &originator_ip))
+ /* The originator_ip was not already present in the
+ * bgp martian next-hop table as a tunnel-ip, so we
+ * need to go back and filter routes matching the new
+ * martian next-hop.
+ */
+ bgp_filter_evpn_routes_upon_martian_nh_change(bgp);
/* Need to withdraw type-3 route as the originator IP is part
* of the key.
@@ -2762,7 +2768,7 @@ static int handle_tunnel_ip_change(struct bgp *bgp, struct bgpevpn *vpn,
/* Update the tunnel IP and re-advertise all routes for this VNI. */
vpn->originator_ip = originator_ip;
- return 0;
+ return;
}
static struct bgp_path_info *
@@ -4423,7 +4429,7 @@ static int process_type2_route(struct peer *peer, afi_t afi, safi_t safi,
mpls_label_t label[BGP_MAX_LABELS] = {};
uint32_t num_labels = 0;
uint32_t eth_tag;
- int ret;
+ int ret = 0;
/* Type-2 route should be either 33, 37 or 49 bytes or an
* additional 3 bytes if there is a second label (VNI):
@@ -4516,13 +4522,13 @@ static int process_type2_route(struct peer *peer, afi_t afi, safi_t safi,
/* Process the route. */
if (attr)
- ret = bgp_update(peer, (struct prefix *)&p, addpath_id, attr,
- afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
- &prd, &label[0], num_labels, 0, &evpn);
+ bgp_update(peer, (struct prefix *)&p, addpath_id, attr, afi,
+ safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd,
+ &label[0], num_labels, 0, &evpn);
else
- ret = bgp_withdraw(peer, (struct prefix *)&p, addpath_id, attr,
- afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
- &prd, &label[0], num_labels, &evpn);
+ bgp_withdraw(peer, (struct prefix *)&p, addpath_id, attr, afi,
+ safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd,
+ &label[0], num_labels, &evpn);
goto done;
fail:
@@ -4547,7 +4553,6 @@ static int process_type3_route(struct peer *peer, afi_t afi, safi_t safi,
struct prefix_evpn p;
uint8_t ipaddr_len;
uint32_t eth_tag;
- int ret;
/* Type-3 route should be either 17 or 29 bytes: RD (8), Eth Tag (4),
* IP len (1) and IP (4 or 16).
@@ -4608,14 +4613,14 @@ static int process_type3_route(struct peer *peer, afi_t afi, safi_t safi,
/* Process the route. */
if (attr)
- ret = bgp_update(peer, (struct prefix *)&p, addpath_id, attr,
- afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
- &prd, NULL, 0, 0, NULL);
+ bgp_update(peer, (struct prefix *)&p, addpath_id, attr, afi,
+ safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, NULL,
+ 0, 0, NULL);
else
- ret = bgp_withdraw(peer, (struct prefix *)&p, addpath_id, attr,
- afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
- &prd, NULL, 0, NULL);
- return ret;
+ bgp_withdraw(peer, (struct prefix *)&p, addpath_id, attr, afi,
+ safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd,
+ NULL, 0, NULL);
+ return 0;
}
/*
@@ -4631,7 +4636,6 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi,
uint8_t ippfx_len;
uint32_t eth_tag;
mpls_label_t label; /* holds the VNI as in the packet */
- int ret;
bool is_valid_update = true;
/* Type-5 route should be 34 or 58 bytes:
@@ -4743,9 +4747,9 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi,
/* Process the route. */
if (attr && is_valid_update)
- ret = bgp_update(peer, (struct prefix *)&p, addpath_id, attr,
- afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
- &prd, &label, 1, 0, &evpn);
+ bgp_update(peer, (struct prefix *)&p, addpath_id, attr, afi,
+ safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd,
+ &label, 1, 0, &evpn);
else {
if (!is_valid_update) {
char attr_str[BUFSIZ] = {0};
@@ -4756,12 +4760,12 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi,
peer->hostname, peer->bgp->vrf_id, &p,
attr_str);
}
- ret = bgp_withdraw(peer, (struct prefix *)&p, addpath_id, attr,
- afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
- &prd, &label, 1, &evpn);
+ bgp_withdraw(peer, (struct prefix *)&p, addpath_id, attr, afi,
+ safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd,
+ &label, 1, &evpn);
}
- return ret;
+ return 0;
}
static void evpn_mpattr_encode_type5(struct stream *s, const struct prefix *p,
@@ -6545,8 +6549,7 @@ int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni,
/* If tunnel endpoint IP has changed, update (and delete prior
* type-3 route, if needed.)
*/
- if (!IPV4_ADDR_SAME(&vpn->originator_ip, &originator_ip))
- handle_tunnel_ip_change(bgp, vpn, originator_ip);
+ handle_tunnel_ip_change(bgp, vpn, originator_ip);
/* Update all routes with new endpoint IP and/or export RT
* for VRFs
@@ -6567,10 +6570,13 @@ int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni,
SET_FLAG(vpn->flags, VNI_FLAG_LIVE);
/* tunnel is now active, add tunnel-ip to db */
- bgp_tip_add(bgp, &originator_ip);
-
- /* filter routes as nexthop database has changed */
- bgp_filter_evpn_routes_upon_martian_nh_change(bgp);
+ if (bgp_tip_add(bgp, &originator_ip))
+ /* The originator_ip was not already present in the
+ * bgp martian next-hop table as a tunnel-ip, so we
+ * need to go back and filter routes matching the new
+ * martian next-hop.
+ */
+ bgp_filter_evpn_routes_upon_martian_nh_change(bgp);
/*
* Create EVPN type-3 route and schedule for processing.
diff --git a/bgpd/bgp_evpn_mh.c b/bgpd/bgp_evpn_mh.c
index 7b1c7cf471..7ad0816631 100644
--- a/bgpd/bgp_evpn_mh.c
+++ b/bgpd/bgp_evpn_mh.c
@@ -706,7 +706,6 @@ int bgp_evpn_type4_route_process(struct peer *peer, afi_t afi, safi_t safi,
struct attr *attr, uint8_t *pfx, int psize,
uint32_t addpath_id)
{
- int ret;
esi_t esi;
uint8_t ipaddr_len;
struct in_addr vtep_ip;
@@ -750,15 +749,15 @@ int bgp_evpn_type4_route_process(struct peer *peer, afi_t afi, safi_t safi,
build_evpn_type4_prefix(&p, &esi, vtep_ip);
/* Process the route. */
if (attr) {
- ret = bgp_update(peer, (struct prefix *)&p, addpath_id, attr,
- afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
- &prd, NULL, 0, 0, NULL);
+ bgp_update(peer, (struct prefix *)&p, addpath_id, attr, afi,
+ safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, NULL,
+ 0, 0, NULL);
} else {
- ret = bgp_withdraw(peer, (struct prefix *)&p, addpath_id, attr,
- afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
- &prd, NULL, 0, NULL);
+ bgp_withdraw(peer, (struct prefix *)&p, addpath_id, attr, afi,
+ safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd,
+ NULL, 0, NULL);
}
- return ret;
+ return 0;
}
/* Check if a prefix belongs to the local ES */
@@ -1180,7 +1179,6 @@ int bgp_evpn_type1_route_process(struct peer *peer, afi_t afi, safi_t safi,
struct attr *attr, uint8_t *pfx, int psize,
uint32_t addpath_id)
{
- int ret;
struct prefix_rd prd;
esi_t esi;
uint32_t eth_tag;
@@ -1219,15 +1217,15 @@ int bgp_evpn_type1_route_process(struct peer *peer, afi_t afi, safi_t safi,
build_evpn_type1_prefix(&p, eth_tag, &esi, vtep_ip);
/* Process the route. */
if (attr) {
- ret = bgp_update(peer, (struct prefix *)&p, addpath_id, attr,
- afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
- &prd, NULL, 0, 0, NULL);
+ bgp_update(peer, (struct prefix *)&p, addpath_id, attr, afi,
+ safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, NULL,
+ 0, 0, NULL);
} else {
- ret = bgp_withdraw(peer, (struct prefix *)&p, addpath_id, attr,
- afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
- &prd, NULL, 0, NULL);
+ bgp_withdraw(peer, (struct prefix *)&p, addpath_id, attr, afi,
+ safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd,
+ NULL, 0, NULL);
}
- return ret;
+ return 0;
}
void bgp_evpn_mh_config_ead_export_rt(struct bgp *bgp,
diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c
index ca6f079401..3c7fb4cb17 100644
--- a/bgpd/bgp_evpn_vty.c
+++ b/bgpd/bgp_evpn_vty.c
@@ -4807,8 +4807,15 @@ DEFUN(show_bgp_l2vpn_evpn_route,
evpn_show_all_routes(vty, bgp, type, json, detail);
- if (uj)
- vty_json(vty, json);
+ if (uj) {
+ if (detail) {
+ vty_out(vty, "%s\n", json_object_to_json_string(json));
+ json_object_free(json);
+ } else {
+ vty_json(vty, json);
+ }
+ }
+
return CMD_SUCCESS;
}
diff --git a/bgpd/bgp_flowspec.c b/bgpd/bgp_flowspec.c
index 39c0cfe514..b07625c49e 100644
--- a/bgpd/bgp_flowspec.c
+++ b/bgpd/bgp_flowspec.c
@@ -103,7 +103,6 @@ int bgp_nlri_parse_flowspec(struct peer *peer, struct attr *attr,
safi_t safi;
int psize = 0;
struct prefix p;
- int ret;
void *temp;
/* Start processing the NLRI - there may be multiple in the MP_REACH */
@@ -190,21 +189,13 @@ int bgp_nlri_parse_flowspec(struct peer *peer, struct attr *attr,
}
/* Process the route. */
if (!withdraw)
- ret = bgp_update(peer, &p, 0, attr,
- afi, safi,
- ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
- NULL, NULL, 0, 0, NULL);
+ bgp_update(peer, &p, 0, attr, afi, safi,
+ ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL,
+ NULL, 0, 0, NULL);
else
- ret = bgp_withdraw(peer, &p, 0, attr,
- afi, safi,
- ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
- NULL, NULL, 0, NULL);
- if (ret) {
- flog_err(EC_BGP_FLOWSPEC_INSTALLATION,
- "Flowspec NLRI failed to be %s.",
- attr ? "added" : "withdrawn");
- return BGP_NLRI_PARSE_ERROR;
- }
+ bgp_withdraw(peer, &p, 0, attr, afi, safi,
+ ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL,
+ NULL, 0, NULL);
}
return BGP_NLRI_PARSE_OK;
}
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
index c57e148ef8..9624adfbe2 100644
--- a/bgpd/bgp_fsm.c
+++ b/bgpd/bgp_fsm.c
@@ -279,22 +279,20 @@ static struct peer *peer_xfer_conn(struct peer *from_peer)
}
}
+ if (peer->hostname) {
+ XFREE(MTYPE_BGP_PEER_HOST, peer->hostname);
+ peer->hostname = NULL;
+ }
if (from_peer->hostname != NULL) {
- if (peer->hostname) {
- XFREE(MTYPE_BGP_PEER_HOST, peer->hostname);
- peer->hostname = NULL;
- }
-
peer->hostname = from_peer->hostname;
from_peer->hostname = NULL;
}
+ if (peer->domainname) {
+ XFREE(MTYPE_BGP_PEER_HOST, peer->domainname);
+ peer->domainname = NULL;
+ }
if (from_peer->domainname != NULL) {
- if (peer->domainname) {
- XFREE(MTYPE_BGP_PEER_HOST, peer->domainname);
- peer->domainname = NULL;
- }
-
peer->domainname = from_peer->domainname;
from_peer->domainname = NULL;
}
diff --git a/bgpd/bgp_mac.c b/bgpd/bgp_mac.c
index b9649ac4da..52ffb10334 100644
--- a/bgpd/bgp_mac.c
+++ b/bgpd/bgp_mac.c
@@ -211,16 +211,10 @@ static void bgp_process_mac_rescan_table(struct bgp *bgp, struct peer *peer,
memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr),
sizeof(evpn));
- int32_t ret = bgp_update(peer, p,
- pi->addpath_rx_id,
- pi->attr, AFI_L2VPN, SAFI_EVPN,
- ZEBRA_ROUTE_BGP,
- BGP_ROUTE_NORMAL, &prd,
- label_pnt, num_labels,
- 1, evpn);
-
- if (ret < 0)
- bgp_dest_unlock_node(dest);
+ bgp_update(peer, p, pi->addpath_rx_id, pi->attr,
+ AFI_L2VPN, SAFI_EVPN, ZEBRA_ROUTE_BGP,
+ BGP_ROUTE_NORMAL, &prd, label_pnt,
+ num_labels, 1, evpn);
}
}
}
diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c
index d9822ee974..77e26037c0 100644
--- a/bgpd/bgp_nexthop.c
+++ b/bgpd/bgp_nexthop.c
@@ -188,15 +188,30 @@ void bgp_tip_hash_destroy(struct bgp *bgp)
bgp->tip_hash = NULL;
}
-void bgp_tip_add(struct bgp *bgp, struct in_addr *tip)
+/* Add/Update Tunnel-IP entry of bgp martian next-hop table.
+ *
+ * Returns true only if we add a _new_ TIP so the caller knows that an
+ * actionable change has occurred. If we find an existing TIP then we
+ * only need to update the refcnt, since the collection of known TIPs
+ * has not changed.
+ */
+bool bgp_tip_add(struct bgp *bgp, struct in_addr *tip)
{
struct tip_addr tmp;
struct tip_addr *addr;
+ bool tip_added = false;
tmp.addr = *tip;
- addr = hash_get(bgp->tip_hash, &tmp, bgp_tip_hash_alloc);
+ addr = hash_lookup(bgp->tip_hash, &tmp);
+ if (!addr) {
+ addr = hash_get(bgp->tip_hash, &tmp, bgp_tip_hash_alloc);
+ tip_added = true;
+ }
+
addr->refcnt++;
+
+ return tip_added;
}
void bgp_tip_del(struct bgp *bgp, struct in_addr *tip)
diff --git a/bgpd/bgp_nexthop.h b/bgpd/bgp_nexthop.h
index efad906d0a..d765bdd261 100644
--- a/bgpd/bgp_nexthop.h
+++ b/bgpd/bgp_nexthop.h
@@ -166,7 +166,7 @@ extern void bgp_scan_finish(struct bgp *bgp);
extern void bgp_scan_vty_init(void);
extern void bgp_address_init(struct bgp *bgp);
extern void bgp_address_destroy(struct bgp *bgp);
-extern void bgp_tip_add(struct bgp *bgp, struct in_addr *tip);
+extern bool bgp_tip_add(struct bgp *bgp, struct in_addr *tip);
extern void bgp_tip_del(struct bgp *bgp, struct in_addr *tip);
extern void bgp_tip_hash_init(struct bgp *bgp);
extern void bgp_tip_hash_destroy(struct bgp *bgp);
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 3f07e53bb6..c9cfc44da0 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -3957,11 +3957,11 @@ static bool bgp_accept_own(struct peer *peer, afi_t afi, safi_t safi,
return false;
}
-int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
- struct attr *attr, afi_t afi, safi_t safi, int type,
- int sub_type, struct prefix_rd *prd, mpls_label_t *label,
- uint32_t num_labels, int soft_reconfig,
- struct bgp_route_evpn *evpn)
+void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
+ struct attr *attr, afi_t afi, safi_t safi, int type,
+ int sub_type, struct prefix_rd *prd, mpls_label_t *label,
+ uint32_t num_labels, int soft_reconfig,
+ struct bgp_route_evpn *evpn)
{
int ret;
int aspath_loop_count = 0;
@@ -4337,7 +4337,7 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
bgp_dest_unlock_node(dest);
bgp_attr_unintern(&attr_new);
- return 0;
+ return;
}
/* Withdraw/Announce before we fully processed the withdraw */
@@ -4551,7 +4551,7 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
ret = bgp_damp_update(pi, dest, afi, safi);
if (ret == BGP_DAMP_SUPPRESSED) {
bgp_dest_unlock_node(dest);
- return 0;
+ return;
}
}
@@ -4671,7 +4671,7 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
bgp_unlink_nexthop(pi);
bgp_path_info_delete(dest, pi);
}
- return 0;
+ return;
} // End of implicit withdraw
/* Received Logging. */
@@ -4834,7 +4834,7 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
bgp_path_info_delete(dest, new);
}
- return 0;
+ return;
/* This BGP update is filtered. Log the reason then update BGP
entry. */
@@ -4897,13 +4897,14 @@ filtered:
}
#endif
- return 0;
+ return;
}
-int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
- struct attr *attr, afi_t afi, safi_t safi, int type,
- int sub_type, struct prefix_rd *prd, mpls_label_t *label,
- uint32_t num_labels, struct bgp_route_evpn *evpn)
+void bgp_withdraw(struct peer *peer, const struct prefix *p,
+ uint32_t addpath_id, struct attr *attr, afi_t afi,
+ safi_t safi, int type, int sub_type, struct prefix_rd *prd,
+ mpls_label_t *label, uint32_t num_labels,
+ struct bgp_route_evpn *evpn)
{
struct bgp *bgp;
char pfx_buf[BGP_PRD_PATH_STRLEN];
@@ -4948,7 +4949,7 @@ int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
peer->host, pfx_buf);
}
bgp_dest_unlock_node(dest);
- return 0;
+ return;
}
/* Lookup withdrawn route. */
@@ -4990,7 +4991,7 @@ int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
/* Unlock bgp_node_get() lock. */
bgp_dest_unlock_node(dest);
- return 0;
+ return;
}
void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
@@ -5122,10 +5123,10 @@ static void bgp_soft_reconfig_table_flag(struct bgp_table *table, bool flag)
}
}
-static int bgp_soft_reconfig_table_update(struct peer *peer,
- struct bgp_dest *dest,
- struct bgp_adj_in *ain, afi_t afi,
- safi_t safi, struct prefix_rd *prd)
+static void bgp_soft_reconfig_table_update(struct peer *peer,
+ struct bgp_dest *dest,
+ struct bgp_adj_in *ain, afi_t afi,
+ safi_t safi, struct prefix_rd *prd)
{
struct bgp_path_info *pi;
uint32_t num_labels = 0;
@@ -5146,17 +5147,15 @@ static int bgp_soft_reconfig_table_update(struct peer *peer,
else
memset(&evpn, 0, sizeof(evpn));
- return bgp_update(peer, bgp_dest_get_prefix(dest), ain->addpath_rx_id,
- ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
- BGP_ROUTE_NORMAL, prd, label_pnt, num_labels, 1,
- &evpn);
+ bgp_update(peer, bgp_dest_get_prefix(dest), ain->addpath_rx_id,
+ ain->attr, afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, prd,
+ label_pnt, num_labels, 1, &evpn);
}
static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
struct bgp_table *table,
struct prefix_rd *prd)
{
- int ret;
struct bgp_dest *dest;
struct bgp_adj_in *ain;
@@ -5168,13 +5167,8 @@ static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
if (ain->peer != peer)
continue;
- ret = bgp_soft_reconfig_table_update(peer, dest, ain,
- afi, safi, prd);
-
- if (ret < 0) {
- bgp_dest_unlock_node(dest);
- return;
- }
+ bgp_soft_reconfig_table_update(peer, dest, ain, afi,
+ safi, prd);
}
}
@@ -5189,7 +5183,6 @@ static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
static void bgp_soft_reconfig_table_task(struct thread *thread)
{
uint32_t iter, max_iter;
- int ret;
struct bgp_dest *dest;
struct bgp_adj_in *ain;
struct peer *peer;
@@ -5222,27 +5215,10 @@ static void bgp_soft_reconfig_table_task(struct thread *thread)
if (ain->peer != peer)
continue;
- ret = bgp_soft_reconfig_table_update(
+ bgp_soft_reconfig_table_update(
peer, dest, ain, table->afi,
table->safi, prd);
iter++;
-
- if (ret < 0) {
- bgp_dest_unlock_node(dest);
- listnode_delete(
- table->soft_reconfig_peers,
- peer);
- bgp_announce_route(peer, table->afi,
- table->safi, false);
- if (list_isempty(
- table->soft_reconfig_peers)) {
- list_delete(
- &table->soft_reconfig_peers);
- bgp_soft_reconfig_table_flag(
- table, false);
- return;
- }
- }
}
}
}
@@ -5959,7 +5935,6 @@ int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
uint8_t *lim;
struct prefix p;
int psize;
- int ret;
afi_t afi;
safi_t safi;
bool addpath_capable;
@@ -6072,23 +6047,18 @@ int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
/* Normal process. */
if (attr)
- ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
- ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
- NULL, NULL, 0, 0, NULL);
+ bgp_update(peer, &p, addpath_id, attr, afi, safi,
+ ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL,
+ NULL, 0, 0, NULL);
else
- ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
- safi, ZEBRA_ROUTE_BGP,
- BGP_ROUTE_NORMAL, NULL, NULL, 0,
- NULL);
+ bgp_withdraw(peer, &p, addpath_id, attr, afi, safi,
+ ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL,
+ NULL, 0, NULL);
/* Do not send BGP notification twice when maximum-prefix count
* overflow. */
if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
-
- /* Address family configuration mismatch. */
- if (ret < 0)
- return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
}
/* Packet length consistency check. */
@@ -9483,7 +9453,7 @@ void route_vty_out(struct vty *vty, const struct prefix *p,
json_object_string_add(json_path, "path",
attr->aspath->str);
else
- aspath_print_vty(vty, "%s", attr->aspath, " ");
+ aspath_print_vty(vty, attr->aspath);
}
/* Print origin */
@@ -9701,7 +9671,7 @@ CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
/* Print aspath */
if (attr->aspath)
- aspath_print_vty(vty, "%s", attr->aspath, " ");
+ aspath_print_vty(vty, attr->aspath);
/* Print origin */
vty_out(vty, "%s", bgp_origin_str[attr->origin]);
@@ -9968,7 +9938,7 @@ static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
use_json, NULL));
if (attr->aspath)
- aspath_print_vty(vty, "%s", attr->aspath, " ");
+ aspath_print_vty(vty, attr->aspath);
vty_out(vty, "%s", bgp_origin_str[attr->origin]);
@@ -10045,7 +10015,7 @@ static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
vty_out(vty, "%*s ", 8, " ");
if (attr->aspath)
- aspath_print_vty(vty, "%s", attr->aspath, " ");
+ aspath_print_vty(vty, attr->aspath);
vty_out(vty, "%s", bgp_origin_str[attr->origin]);
@@ -10329,7 +10299,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
attr->aspath->json);
} else {
if (attr->aspath->segments)
- aspath_print_vty(vty, " %s", attr->aspath, "");
+ vty_out(vty, " %s", attr->aspath->str);
else
vty_out(vty, " Local");
}
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index e16e077029..452282926f 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -750,17 +750,17 @@ extern int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *,
const char *, const char *, const char *);
/* this is primarily for MPLS-VPN */
-extern int bgp_update(struct peer *peer, const struct prefix *p,
- uint32_t addpath_id, struct attr *attr,
- afi_t afi, safi_t safi, int type, int sub_type,
- struct prefix_rd *prd, mpls_label_t *label,
- uint32_t num_labels, int soft_reconfig,
- struct bgp_route_evpn *evpn);
-extern int bgp_withdraw(struct peer *peer, const struct prefix *p,
- uint32_t addpath_id, struct attr *attr, afi_t afi,
- safi_t safi, int type, int sub_type,
- struct prefix_rd *prd, mpls_label_t *label,
- uint32_t num_labels, struct bgp_route_evpn *evpn);
+extern void bgp_update(struct peer *peer, const struct prefix *p,
+ uint32_t addpath_id, struct attr *attr, afi_t afi,
+ safi_t safi, int type, int sub_type,
+ struct prefix_rd *prd, mpls_label_t *label,
+ uint32_t num_labels, int soft_reconfig,
+ struct bgp_route_evpn *evpn);
+extern void bgp_withdraw(struct peer *peer, const struct prefix *p,
+ uint32_t addpath_id, struct attr *attr, afi_t afi,
+ safi_t safi, int type, int sub_type,
+ struct prefix_rd *prd, mpls_label_t *label,
+ uint32_t num_labels, struct bgp_route_evpn *evpn);
/* for bgp_nexthop and bgp_damp */
extern void bgp_process(struct bgp *, struct bgp_dest *, afi_t, safi_t);
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 5738d9ef68..d837601f32 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -12002,7 +12002,7 @@ static void bgp_show_neighbor_graceful_restart_remote_mode(struct vty *vty,
if (json)
json_object_string_add(json, "remoteGrMode", mode);
else
- vty_out(vty, mode, "\n");
+ vty_out(vty, "%s\n", mode);
}
static void bgp_show_neighbor_graceful_restart_local_mode(struct vty *vty,
@@ -12034,7 +12034,7 @@ static void bgp_show_neighbor_graceful_restart_local_mode(struct vty *vty,
if (json)
json_object_string_add(json, "localGrMode", mode);
else
- vty_out(vty, mode, "\n");
+ vty_out(vty, "%s\n", mode);
}
static void bgp_show_neighbor_graceful_restart_capability_per_afi_safi(
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 1fd394a849..39010e76f9 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -1156,6 +1156,7 @@ static void peer_free(struct peer *peer)
XFREE(MTYPE_PEER_DESC, peer->desc);
XFREE(MTYPE_BGP_PEER_HOST, peer->host);
+ XFREE(MTYPE_BGP_PEER_HOST, peer->hostname);
XFREE(MTYPE_BGP_PEER_HOST, peer->domainname);
XFREE(MTYPE_BGP_PEER_IFNAME, peer->ifname);
diff --git a/bgpd/rfapi/rfapi_vty.c b/bgpd/rfapi/rfapi_vty.c
index 719d898e3c..d04d1ee750 100644
--- a/bgpd/rfapi/rfapi_vty.c
+++ b/bgpd/rfapi/rfapi_vty.c
@@ -322,6 +322,7 @@ int rfapiDebugPrintf(void *dummy, const char *format, ...)
return 0;
}
+PRINTFRR(2, 3)
static int rfapiStdioPrintf(void *stream, const char *format, ...)
{
FILE *file = NULL;
diff --git a/configure.ac b/configure.ac
index 2d9d4f66b1..48ac4873b8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -349,6 +349,8 @@ AC_C_FLAG([-fno-omit-frame-pointer])
AC_C_FLAG([-funwind-tables])
AC_C_FLAG([-Wall])
AC_C_FLAG([-Wextra])
+AC_C_FLAG([-Wformat-nonliteral])
+AC_C_FLAG([-Wformat-security])
AC_C_FLAG([-Wstrict-prototypes])
AC_C_FLAG([-Wmissing-prototypes])
AC_C_FLAG([-Wmissing-declarations])
diff --git a/isisd/isis_cli.c b/isisd/isis_cli.c
index 3650984f1b..cb607deb23 100644
--- a/isisd/isis_cli.c
+++ b/isisd/isis_cli.c
@@ -61,7 +61,7 @@ DEFPY_YANG_NOSH(router_isis, router_isis_cmd,
vrf_name);
nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
- ret = nb_cli_apply_changes(vty, base_xpath);
+ ret = nb_cli_apply_changes(vty, "%s", base_xpath);
if (ret == CMD_SUCCESS)
VTY_PUSH_XPATH(ISIS_NODE, base_xpath);
@@ -1427,7 +1427,7 @@ DEFPY_YANG(
overload ? "true" : "false");
}
- return nb_cli_apply_changes(vty, base_xpath);
+ return nb_cli_apply_changes(vty, "%s", base_xpath);
}
void cli_show_isis_mt_ipv4_multicast(struct vty *vty,
diff --git a/ldpd/log.c b/ldpd/log.c
index 1aaad41a10..88ce03095a 100644
--- a/ldpd/log.c
+++ b/ldpd/log.c
@@ -77,7 +77,11 @@ log_warn(const char *emsg, ...)
vlog(LOG_ERR, emsg, ap);
logit(LOG_ERR, "%s", strerror(errno));
} else {
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+ /* format extended above */
vlog(LOG_ERR, nfmt, ap);
+#pragma GCC diagnostic pop
free(nfmt);
}
va_end(ap);
diff --git a/lib/bfd.c b/lib/bfd.c
index ae402ec5cb..9078e3559f 100644
--- a/lib/bfd.c
+++ b/lib/bfd.c
@@ -129,8 +129,6 @@ struct bfd_sessions_global {
struct thread_master *tm;
/** Pointer to zebra client data structure. */
struct zclient *zc;
- /** Zebra next hop tracking (NHT) client. */
- struct zclient *nht_zclient;
/** Debugging state. */
bool debugging;
@@ -147,31 +145,10 @@ static const struct in6_addr i6a_zero;
/*
* Prototypes
*/
-static void bfd_nht_zclient_connect(struct thread *thread);
-
-static void bfd_nht_zclient_connected(struct zclient *zclient);
-static int bfd_nht_update(ZAPI_CALLBACK_ARGS);
static void bfd_source_cache_get(struct bfd_session_params *session);
static void bfd_source_cache_put(struct bfd_session_params *session);
-static inline void
-bfd_source_cache_register(const struct bfd_source_cache *source)
-{
- zclient_send_rnh(bsglobal.nht_zclient, ZEBRA_NEXTHOP_REGISTER,
- &source->address, SAFI_UNICAST, false, false,
- source->vrf_id);
-}
-
-static inline void
-bfd_source_cache_unregister(const struct bfd_source_cache *source)
-{
- zclient_send_rnh(bsglobal.nht_zclient, ZEBRA_NEXTHOP_UNREGISTER,
- &source->address, SAFI_UNICAST, false, false,
- source->vrf_id);
-}
-
-
/*
* bfd_get_peer_info - Extract the Peer information for which the BFD session
* went down from the message sent from Zebra to clients.
@@ -1074,20 +1051,11 @@ static int bfd_protocol_integration_finish(void)
if (!SLIST_EMPTY(&bsglobal.source_list))
zlog_warn("BFD integration source cache not empty");
- zclient_stop(bsglobal.nht_zclient);
- zclient_free(bsglobal.nht_zclient);
-
return 0;
}
-static zclient_handler *const bfd_nht_handlers[] = {
- [ZEBRA_NEXTHOP_UPDATE] = bfd_nht_update,
-};
-
void bfd_protocol_integration_init(struct zclient *zc, struct thread_master *tm)
{
- struct zclient_options bfd_nht_options = zclient_options_default;
-
/* Initialize data structure. */
TAILQ_INIT(&bsglobal.bsplist);
SLIST_INIT(&bsglobal.source_list);
@@ -1102,16 +1070,6 @@ void bfd_protocol_integration_init(struct zclient *zc, struct thread_master *tm)
/* Send the client registration */
bfd_client_sendmsg(zc, ZEBRA_BFD_CLIENT_REGISTER, VRF_DEFAULT);
- /* Start NHT client (for automatic source decisions). */
- bsglobal.nht_zclient =
- zclient_new(tm, &bfd_nht_options, bfd_nht_handlers,
- array_size(bfd_nht_handlers));
- bsglobal.nht_zclient->sock = -1;
- bsglobal.nht_zclient->privs = zc->privs;
- bsglobal.nht_zclient->zebra_connected = bfd_nht_zclient_connected;
- thread_add_timer(tm, bfd_nht_zclient_connect, bsglobal.nht_zclient, 1,
- &bsglobal.nht_zclient->t_connect);
-
hook_register(frr_fini, bfd_protocol_integration_finish);
}
@@ -1252,8 +1210,6 @@ static void bfd_source_cache_get(struct bfd_session_params *session)
session->source_cache = source;
source->refcount = 1;
- bfd_source_cache_register(source);
-
return;
}
@@ -1268,7 +1224,6 @@ static void bfd_source_cache_put(struct bfd_session_params *session)
return;
}
- bfd_source_cache_unregister(session->source_cache);
SLIST_REMOVE(&bsglobal.source_list, session->source_cache,
bfd_source_cache, entry);
XFREE(MTYPE_BFD_SOURCE, session->source_cache);
@@ -1378,59 +1333,19 @@ static bool bfd_source_cache_update(struct bfd_source_cache *source,
return false;
}
-static void bfd_nht_zclient_connect(struct thread *thread)
-{
- struct zclient *zclient = THREAD_ARG(thread);
-
- if (bsglobal.debugging)
- zlog_debug("BFD NHT zclient connection attempt");
-
- if (zclient_start(zclient) == -1) {
- if (bsglobal.debugging)
- zlog_debug("BFD NHT zclient connection failed");
-
- thread_add_timer(bsglobal.tm, bfd_nht_zclient_connect, zclient,
- 3, &zclient->t_connect);
- return;
- }
-
- if (bsglobal.debugging)
- zlog_debug("BFD NHT zclient connection succeeded");
-}
-
-static void bfd_nht_zclient_connected(struct zclient *zclient)
-{
- struct bfd_source_cache *source;
-
- if (bsglobal.debugging)
- zlog_debug("BFD NHT zclient connected");
-
- SLIST_FOREACH (source, &bsglobal.source_list, entry)
- bfd_source_cache_register(source);
-}
-
-static int bfd_nht_update(ZAPI_CALLBACK_ARGS)
+int bfd_nht_update(const struct prefix *match, const struct zapi_route *route)
{
struct bfd_source_cache *source;
- struct zapi_route route;
- struct prefix match;
-
- if (!zapi_nexthop_update_decode(zclient->ibuf, &match, &route)) {
- zlog_warn("BFD NHT update decode failure");
- return 0;
- }
- if (cmd != ZEBRA_NEXTHOP_UPDATE)
- return 0;
if (bsglobal.debugging)
- zlog_debug("BFD NHT update for %pFX", &route.prefix);
+ zlog_debug("BFD NHT update for %pFX", &route->prefix);
SLIST_FOREACH (source, &bsglobal.source_list, entry) {
- if (source->vrf_id != route.vrf_id)
+ if (source->vrf_id != route->vrf_id)
continue;
- if (!prefix_same(&match, &source->address))
+ if (!prefix_same(match, &source->address))
continue;
- if (bfd_source_cache_update(source, &route))
+ if (bfd_source_cache_update(source, route))
bfd_source_cache_update_sessions(source);
}
diff --git a/lib/bfd.h b/lib/bfd.h
index b7e4eea5f3..51e831785a 100644
--- a/lib/bfd.h
+++ b/lib/bfd.h
@@ -473,6 +473,13 @@ extern bool bfd_protocol_integration_debug(void);
*/
extern bool bfd_protocol_integration_shutting_down(void);
+/* Update nexthop-tracking (nht) information for BFD auto source selection.
+ * The function must be called from the daemon callback function
+ * that deals with the ZEBRA_NEXTHOP_UPDATE zclient command
+ */
+extern int bfd_nht_update(const struct prefix *match,
+ const struct zapi_route *route);
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/clippy.c b/lib/clippy.c
index 7ca99c9a94..1c27f857ba 100644
--- a/lib/clippy.c
+++ b/lib/clippy.c
@@ -108,6 +108,7 @@ int main(int argc, char **argv)
#include "log.h"
+PRINTFRR(3, 0)
void vzlogx(const struct xref_logmsg *xref, int prio,
const char *format, va_list args)
{
diff --git a/lib/command.h b/lib/command.h
index bce4fb9e1c..8f5d96053c 100644
--- a/lib/command.h
+++ b/lib/command.h
@@ -619,9 +619,6 @@ extern void print_version(const char *);
extern int cmd_banner_motd_file(const char *);
extern void cmd_banner_motd_line(const char *line);
-/* struct host global, ick */
-extern struct host host;
-
struct cmd_variable_handler {
const char *tokenname, *varname;
void (*completions)(vector out, struct cmd_token *token);
diff --git a/lib/ferr.c b/lib/ferr.c
index bef7f3b209..4e41526211 100644
--- a/lib/ferr.c
+++ b/lib/ferr.c
@@ -219,6 +219,7 @@ ferr_r ferr_clear(void)
return ferr_ok();
}
+PRINTFRR(7, 0)
static ferr_r ferr_set_va(const char *file, int line, const char *func,
enum ferr_kind kind, const char *pathname,
int errno_val, const char *text, va_list va)
diff --git a/lib/ferr.h b/lib/ferr.h
index c27601f66c..9accde1697 100644
--- a/lib/ferr.h
+++ b/lib/ferr.h
@@ -178,10 +178,12 @@ ferr_r ferr_clear(void);
/* do NOT call these functions directly. only for macro use! */
ferr_r ferr_set_internal(const char *file, int line, const char *func,
- enum ferr_kind kind, const char *text, ...);
+ enum ferr_kind kind, const char *text, ...)
+ PRINTFRR(5, 6);
ferr_r ferr_set_internal_ext(const char *file, int line, const char *func,
enum ferr_kind kind, const char *pathname,
- int errno_val, const char *text, ...);
+ int errno_val, const char *text, ...)
+ PRINTFRR(7, 8);
#define ferr_ok() 0
@@ -221,7 +223,8 @@ ferr_r ferr_set_internal_ext(const char *file, int line, const char *func,
#include "vty.h"
/* print error message to vty; $ERR is replaced by the error's message */
-void vty_print_error(struct vty *vty, ferr_r err, const char *msg, ...);
+void vty_print_error(struct vty *vty, ferr_r err, const char *msg, ...)
+ PRINTFRR(3, 4);
#define CMD_FERR_DO(func, action, ...) \
do { \
diff --git a/lib/filter_cli.c b/lib/filter_cli.c
index 296c05b9f4..5accea3f02 100644
--- a/lib/filter_cli.c
+++ b/lib/filter_cli.c
@@ -206,7 +206,7 @@ DEFPY_YANG(
nb_cli_enqueue_change(vty, "./source-any", NB_OP_CREATE, NULL);
}
- return nb_cli_apply_changes(vty, xpath_entry);
+ return nb_cli_apply_changes(vty, "%s", xpath_entry);
}
DEFPY_YANG(
@@ -369,7 +369,7 @@ DEFPY_YANG(
NULL);
}
- return nb_cli_apply_changes(vty, xpath_entry);
+ return nb_cli_apply_changes(vty, "%s", xpath_entry);
}
DEFPY_YANG(
@@ -519,7 +519,7 @@ DEFPY_YANG(
nb_cli_enqueue_change(vty, "./any", NB_OP_CREATE, NULL);
}
- return nb_cli_apply_changes(vty, xpath_entry);
+ return nb_cli_apply_changes(vty, "%s", xpath_entry);
}
DEFPY_YANG(
@@ -600,7 +600,7 @@ DEFPY_YANG(
remark = argv_concat(argv, argc, 3);
nb_cli_enqueue_change(vty, "./remark", NB_OP_CREATE, remark);
- rv = nb_cli_apply_changes(vty, xpath);
+ rv = nb_cli_apply_changes(vty, "%s", xpath);
XFREE(MTYPE_TMP, remark);
return rv;
@@ -709,7 +709,7 @@ DEFPY_YANG(
nb_cli_enqueue_change(vty, "./any", NB_OP_CREATE, NULL);
}
- return nb_cli_apply_changes(vty, xpath_entry);
+ return nb_cli_apply_changes(vty, "%s", xpath_entry);
}
DEFPY_YANG(
@@ -793,7 +793,7 @@ DEFPY_YANG(
remark = argv_concat(argv, argc, 4);
nb_cli_enqueue_change(vty, "./remark", NB_OP_CREATE, remark);
- rv = nb_cli_apply_changes(vty, xpath);
+ rv = nb_cli_apply_changes(vty, "%s", xpath);
XFREE(MTYPE_TMP, remark);
return rv;
@@ -896,7 +896,7 @@ DEFPY_YANG(
nb_cli_enqueue_change(vty, "./any", NB_OP_CREATE, NULL);
}
- return nb_cli_apply_changes(vty, xpath_entry);
+ return nb_cli_apply_changes(vty, "%s", xpath_entry);
}
DEFPY_YANG(
@@ -975,7 +975,7 @@ DEFPY_YANG(
remark = argv_concat(argv, argc, 4);
nb_cli_enqueue_change(vty, "./remark", NB_OP_CREATE, remark);
- rv = nb_cli_apply_changes(vty, xpath);
+ rv = nb_cli_apply_changes(vty, "%s", xpath);
XFREE(MTYPE_TMP, remark);
return rv;
@@ -1344,7 +1344,7 @@ DEFPY_YANG(
nb_cli_enqueue_change(vty, "./any", NB_OP_CREATE, NULL);
}
- return nb_cli_apply_changes(vty, xpath_entry);
+ return nb_cli_apply_changes(vty, "%s", xpath_entry);
}
DEFPY_YANG(
@@ -1415,7 +1415,7 @@ DEFPY_YANG(
remark = argv_concat(argv, argc, 4);
nb_cli_enqueue_change(vty, "./remark", NB_OP_CREATE, remark);
- rv = nb_cli_apply_changes(vty, xpath);
+ rv = nb_cli_apply_changes(vty, "%s", xpath);
XFREE(MTYPE_TMP, remark);
return rv;
@@ -1548,7 +1548,7 @@ DEFPY_YANG(
nb_cli_enqueue_change(vty, "./any", NB_OP_CREATE, NULL);
}
- return nb_cli_apply_changes(vty, xpath_entry);
+ return nb_cli_apply_changes(vty, "%s", xpath_entry);
}
DEFPY_YANG(
@@ -1619,7 +1619,7 @@ DEFPY_YANG(
remark = argv_concat(argv, argc, 4);
nb_cli_enqueue_change(vty, "./remark", NB_OP_CREATE, remark);
- rv = nb_cli_apply_changes(vty, xpath);
+ rv = nb_cli_apply_changes(vty, "%s", xpath);
XFREE(MTYPE_TMP, remark);
return rv;
diff --git a/lib/filter_nb.c b/lib/filter_nb.c
index 3ed1f3e03e..cfe3105380 100644
--- a/lib/filter_nb.c
+++ b/lib/filter_nb.c
@@ -70,7 +70,7 @@ static enum nb_error prefix_list_length_validate(struct nb_cb_modify_args *args)
* prefix length <= le.
*/
if (yang_dnode_exists(args->dnode, xpath_le)) {
- le = yang_dnode_get_uint8(args->dnode, xpath_le);
+ le = yang_dnode_get_uint8(args->dnode, "%s", xpath_le);
if (p.prefixlen > le)
goto log_and_fail;
}
@@ -80,7 +80,7 @@ static enum nb_error prefix_list_length_validate(struct nb_cb_modify_args *args)
* prefix length <= ge.
*/
if (yang_dnode_exists(args->dnode, xpath_ge)) {
- ge = yang_dnode_get_uint8(args->dnode, xpath_ge);
+ ge = yang_dnode_get_uint8(args->dnode, "%s", xpath_ge);
if (p.prefixlen > ge)
goto log_and_fail;
}
@@ -91,8 +91,8 @@ static enum nb_error prefix_list_length_validate(struct nb_cb_modify_args *args)
*/
if (yang_dnode_exists(args->dnode, xpath_le)
&& yang_dnode_exists(args->dnode, xpath_ge)) {
- le = yang_dnode_get_uint8(args->dnode, xpath_le);
- ge = yang_dnode_get_uint8(args->dnode, xpath_ge);
+ le = yang_dnode_get_uint8(args->dnode, "%s", xpath_le);
+ ge = yang_dnode_get_uint8(args->dnode, "%s", xpath_ge);
if (ge > le)
goto log_and_fail;
}
@@ -273,7 +273,8 @@ static int _acl_is_dup(const struct lyd_node *dnode, void *arg)
return YANG_ITER_CONTINUE;
/* Check if different value. */
- if (strcmp(yang_dnode_get_string(dnode, ada->ada_xpath[idx]),
+ if (strcmp(yang_dnode_get_string(dnode, "%s",
+ ada->ada_xpath[idx]),
ada->ada_value[idx]))
return YANG_ITER_CONTINUE;
}
@@ -328,8 +329,8 @@ static bool acl_cisco_is_dup(const struct lyd_node *dnode)
}
ada.ada_xpath[arg_idx] = cisco_entries[idx];
- ada.ada_value[arg_idx] =
- yang_dnode_get_string(entry_dnode, cisco_entries[idx]);
+ ada.ada_value[arg_idx] = yang_dnode_get_string(
+ entry_dnode, "%s", cisco_entries[idx]);
arg_idx++;
idx++;
}
@@ -378,8 +379,8 @@ static bool acl_zebra_is_dup(const struct lyd_node *dnode,
}
ada.ada_xpath[arg_idx] = zebra_entries[idx];
- ada.ada_value[arg_idx] =
- yang_dnode_get_string(entry_dnode, zebra_entries[idx]);
+ ada.ada_value[arg_idx] = yang_dnode_get_string(
+ entry_dnode, "%s", zebra_entries[idx]);
arg_idx++;
idx++;
}
diff --git a/lib/frrscript.h b/lib/frrscript.h
index 7fa01f70d1..afaab66f1b 100644
--- a/lib/frrscript.h
+++ b/lib/frrscript.h
@@ -34,7 +34,7 @@ extern "C" {
#endif
/* Forward declarations */
-extern struct zebra_dplane_ctx ctx;
+struct zebra_dplane_ctx;
extern void lua_pushzebra_dplane_ctx(lua_State *L,
const struct zebra_dplane_ctx *ctx);
extern void lua_decode_zebra_dplane_ctx(lua_State *L, int idx,
diff --git a/lib/grammar_sandbox_main.c b/lib/grammar_sandbox_main.c
index 6469b49262..a7d6c51376 100644
--- a/lib/grammar_sandbox_main.c
+++ b/lib/grammar_sandbox_main.c
@@ -49,8 +49,8 @@ int main(int argc, char **argv)
/* Library inits. */
cmd_init(1);
- host.name = strdup("test");
- host.domainname = strdup("testdomainname");
+ cmd_hostname_set("test");
+ cmd_domainname_set("testdomainname");
vty_init(master, true);
lib_cmd_init();
diff --git a/lib/if.c b/lib/if.c
index db73210036..b75c2a4dbe 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -1220,7 +1220,7 @@ DEFPY_YANG_NOSH (interface,
}
nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
- ret = nb_cli_apply_changes_clear_pending(vty, xpath_list);
+ ret = nb_cli_apply_changes_clear_pending(vty, "%s", xpath_list);
if (ret == CMD_SUCCESS) {
VTY_PUSH_XPATH(INTERFACE_NODE, xpath_list);
@@ -1279,7 +1279,7 @@ DEFPY_YANG (no_interface,
nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
- return nb_cli_apply_changes(vty, xpath_list);
+ return nb_cli_apply_changes(vty, "%s", xpath_list);
}
static void netns_ifname_split(const char *xpath, char *ifname, char *vrfname)
diff --git a/lib/northbound_cli.h b/lib/northbound_cli.h
index e472425447..d848507e01 100644
--- a/lib/northbound_cli.h
+++ b/lib/northbound_cli.h
@@ -71,7 +71,8 @@ extern void nb_cli_enqueue_change(struct vty *vty, const char *xpath,
* CMD_SUCCESS on success, CMD_WARNING_CONFIG_FAILED otherwise.
*/
extern int nb_cli_apply_changes_clear_pending(struct vty *vty,
- const char *xpath_base_fmt, ...);
+ const char *xpath_base_fmt, ...)
+ PRINTFRR(2, 3);
/*
* Apply enqueued changes to the candidate configuration, this function
@@ -89,7 +90,7 @@ extern int nb_cli_apply_changes_clear_pending(struct vty *vty,
* CMD_SUCCESS on success, CMD_WARNING_CONFIG_FAILED otherwise.
*/
extern int nb_cli_apply_changes(struct vty *vty, const char *xpath_base_fmt,
- ...);
+ ...) PRINTFRR(2, 3);
/*
* Execute a YANG RPC or Action.
diff --git a/lib/printf/glue.c b/lib/printf/glue.c
index 6e39c2d9cf..3ac6e2c0ae 100644
--- a/lib/printf/glue.c
+++ b/lib/printf/glue.c
@@ -293,5 +293,9 @@ static ssize_t printfrr_va(struct fbuf *buf, struct printfrr_eargs *ea,
* when allocating a larger buffer in asnprintfrr()
*/
va_copy(ap, *vaf->va);
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+ /* can't format check this */
return vbprintfrr(buf, vaf->fmt, ap);
+#pragma GCC diagnostic pop
}
diff --git a/lib/printf/vfprintf.c b/lib/printf/vfprintf.c
index 49fa2b718f..cc886834fa 100644
--- a/lib/printf/vfprintf.c
+++ b/lib/printf/vfprintf.c
@@ -504,14 +504,20 @@ reswitch: switch (ch) {
fmt[4] = ch;
fmt[5] = '\0';
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
snprintf(buf, sizeof(buf), fmt, prec, arg);
+#pragma GCC diagnostic pop
} else {
double arg = GETARG(double);
char fmt[5] = "%.*";
fmt[3] = ch;
fmt[4] = '\0';
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
snprintf(buf, sizeof(buf), fmt, prec, arg);
+#pragma GCC diagnostic pop
}
cp = buf;
/* for proper padding */
diff --git a/lib/termtable.c b/lib/termtable.c
index ddf8822853..14362e1443 100644
--- a/lib/termtable.c
+++ b/lib/termtable.c
@@ -130,6 +130,7 @@ struct ttable *ttable_new(const struct ttable_style *style)
*
* @return pointer to the first cell of allocated row
*/
+PRINTFRR(3, 0)
static struct ttable_cell *ttable_insert_row_va(struct ttable *tt, int i,
const char *format, va_list ap)
{
@@ -435,13 +436,12 @@ char *ttable_dump(struct ttable *tt, const char *newline)
abspad -= row[j].style.border.right_on ? 1 : 0;
/* print text */
- const char *fmt;
if (row[j].style.align == LEFT)
- fmt = "%-*s";
+ pos += sprintf(&buf[pos], "%-*s", abspad,
+ row[j].text);
else
- fmt = "%*s";
-
- pos += sprintf(&buf[pos], fmt, abspad, row[j].text);
+ pos += sprintf(&buf[pos], "%*s", abspad,
+ row[j].text);
/* print right padding */
for (int k = 0; k < row[j].style.rpad; k++)
diff --git a/lib/vrf.c b/lib/vrf.c
index 2ac7ef7a97..7d2ca6f1e1 100644
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -652,7 +652,7 @@ DEFUN_YANG_NOSH (vrf,
snprintf(xpath_list, sizeof(xpath_list), FRR_VRF_KEY_XPATH, vrfname);
nb_cli_enqueue_change(vty, xpath_list, NB_OP_CREATE, NULL);
- ret = nb_cli_apply_changes_clear_pending(vty, xpath_list);
+ ret = nb_cli_apply_changes_clear_pending(vty, "%s", xpath_list);
if (ret == CMD_SUCCESS) {
VTY_PUSH_XPATH(VRF_NODE, xpath_list);
vrf = vrf_lookup_by_name(vrfname);
diff --git a/lib/vty.c b/lib/vty.c
index 352080e580..76d907408c 100644
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -343,6 +343,15 @@ void vty_hello(struct vty *vty)
vty_out(vty, "%s", host.motd);
}
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+/* prompt formatting has a %s in the cmd_node prompt string.
+ *
+ * Also for some reason GCC emits the warning on the end of the function
+ * (optimization maybe?) rather than on the vty_out line, so this pragma
+ * wraps the entire function rather than just the vty_out line.
+ */
+
/* Put out prompt and wait input from user. */
static void vty_prompt(struct vty *vty)
{
@@ -350,6 +359,7 @@ static void vty_prompt(struct vty *vty)
vty_out(vty, cmd_prompt(vty->node), cmd_hostname_get());
}
}
+#pragma GCC diagnostic pop
/* Send WILL TELOPT_ECHO to remote server. */
static void vty_will_echo(struct vty *vty)
@@ -464,8 +474,12 @@ static int vty_command(struct vty *vty, char *buf)
vty->address);
/* format the prompt */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+ /* prompt formatting has a %s in the cmd_node prompt string */
snprintf(prompt_str, sizeof(prompt_str), cmd_prompt(vty->node),
vty_str);
+#pragma GCC diagnostic pop
/* now log the command */
zlog_notice("%s%s", prompt_str, buf);
diff --git a/lib/wheel.c b/lib/wheel.c
index 6e9c88de9d..f2776d6091 100644
--- a/lib/wheel.c
+++ b/lib/wheel.c
@@ -118,21 +118,6 @@ void wheel_delete(struct timer_wheel *wheel)
XFREE(MTYPE_TIMER_WHEEL, wheel);
}
-int wheel_stop(struct timer_wheel *wheel)
-{
- THREAD_OFF(wheel->timer);
- return 0;
-}
-
-int wheel_start(struct timer_wheel *wheel)
-{
- if (!wheel->timer)
- thread_add_timer_msec(wheel->master, wheel_timer_thread, wheel,
- wheel->nexttime, &wheel->timer);
-
- return 0;
-}
-
int wheel_add_item(struct timer_wheel *wheel, void *item)
{
long long slot;
diff --git a/lib/wheel.h b/lib/wheel.h
index 401789e1a0..1e5a31b9a6 100644
--- a/lib/wheel.h
+++ b/lib/wheel.h
@@ -90,16 +90,6 @@ struct timer_wheel *wheel_init(struct thread_master *master, int period,
void wheel_delete(struct timer_wheel *);
/*
- * Pause the Wheel from running
- */
-int wheel_stop(struct timer_wheel *wheel);
-
-/*
- * Start the wheel running again
- */
-int wheel_start(struct timer_wheel *wheel);
-
-/*
* wheel - The Timer wheel being modified
* item - The generic data structure that will be handed
* to the slot_run function.
diff --git a/lib/yang.h b/lib/yang.h
index d625b24f6a..8b49df5e91 100644
--- a/lib/yang.h
+++ b/lib/yang.h
@@ -331,7 +331,8 @@ extern void yang_dnode_get_path(const struct lyd_node *dnode, char *xpath,
* Schema name of the libyang data node.
*/
extern const char *yang_dnode_get_schema_name(const struct lyd_node *dnode,
- const char *xpath_fmt, ...);
+ const char *xpath_fmt, ...)
+ PRINTFRR(2, 3);
/*
* Find a libyang data node by its YANG data path.
@@ -366,7 +367,8 @@ extern struct lyd_node *yang_dnode_get(const struct lyd_node *dnode,
* The libyang data node if found, or NULL if not found.
*/
extern struct lyd_node *yang_dnode_getf(const struct lyd_node *dnode,
- const char *path_fmt, ...);
+ const char *path_fmt, ...)
+ PRINTFRR(2, 3);
/*
* Check if a libyang data node exists.
@@ -400,7 +402,7 @@ extern bool yang_dnode_exists(const struct lyd_node *dnode, const char *xpath);
* true if a libyang data node was found, false otherwise.
*/
extern bool yang_dnode_existsf(const struct lyd_node *dnode,
- const char *xpath_fmt, ...);
+ const char *xpath_fmt, ...) PRINTFRR(2, 3);
/*
* Iterate over all libyang data nodes that satisfy an XPath query.
@@ -422,7 +424,7 @@ extern bool yang_dnode_existsf(const struct lyd_node *dnode,
*/
void yang_dnode_iterate(yang_dnode_iter_cb cb, void *arg,
const struct lyd_node *dnode, const char *xpath_fmt,
- ...);
+ ...) PRINTFRR(4, 5);
/*
* Check if the libyang data node contains a default value. Non-presence
@@ -459,7 +461,7 @@ extern bool yang_dnode_is_default(const struct lyd_node *dnode,
* true if the data node contains the default value, false otherwise.
*/
extern bool yang_dnode_is_defaultf(const struct lyd_node *dnode,
- const char *xpath_fmt, ...);
+ const char *xpath_fmt, ...) PRINTFRR(2, 3);
/*
* Check if the libyang data node and all of its children contain default
@@ -566,7 +568,8 @@ extern struct list *yang_data_list_new(void);
* Pointer to yang_data if found, NULL otherwise.
*/
extern struct yang_data *yang_data_list_find(const struct list *list,
- const char *xpath_fmt, ...);
+ const char *xpath_fmt, ...)
+ PRINTFRR(2, 3);
/*
* Create and set up a libyang context (for use by the translator)
diff --git a/lib/yang_translator.c b/lib/yang_translator.c
index d562e4d29e..67b7f9aa70 100644
--- a/lib/yang_translator.c
+++ b/lib/yang_translator.c
@@ -339,8 +339,12 @@ yang_translate_xpath(const struct yang_translator *translator, int dir,
if (!mapping)
return YANG_TRANSLATE_NOTFOUND;
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+ /* processing format strings from mapping node... */
n = sscanf(xpath, mapping->xpath_from_fmt, keys[0], keys[1], keys[2],
keys[3]);
+#pragma GCC diagnostic pop
if (n < 0) {
flog_warn(EC_LIB_YANG_TRANSLATION_ERROR,
"%s: sscanf() failed: %s", __func__,
@@ -348,8 +352,12 @@ yang_translate_xpath(const struct yang_translator *translator, int dir,
return YANG_TRANSLATE_FAILURE;
}
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+ /* processing format strings from mapping node... */
snprintf(xpath, xpath_len, mapping->xpath_to_fmt, keys[0], keys[1],
keys[2], keys[3]);
+#pragma GCC diagnostic pop
return YANG_TRANSLATE_SUCCESS;
}
diff --git a/lib/yang_wrappers.c b/lib/yang_wrappers.c
index ea21d1324b..d22379dd23 100644
--- a/lib/yang_wrappers.c
+++ b/lib/yang_wrappers.c
@@ -58,6 +58,7 @@
} \
} while (0)
+PRINTFRR(2, 0)
static inline const char *
yang_dnode_xpath_get_canon(const struct lyd_node *dnode, const char *xpath_fmt,
va_list ap)
@@ -75,6 +76,7 @@ yang_dnode_xpath_get_canon(const struct lyd_node *dnode, const char *xpath_fmt,
return lyd_get_value(&__dleaf->node);
}
+PRINTFRR(2, 0)
static inline const struct lyd_value *
yang_dnode_xpath_get_value(const struct lyd_node *dnode, const char *xpath_fmt,
va_list ap)
diff --git a/lib/yang_wrappers.h b/lib/yang_wrappers.h
index 56b314876f..c27e1e5372 100644
--- a/lib/yang_wrappers.h
+++ b/lib/yang_wrappers.h
@@ -30,105 +30,120 @@ extern "C" {
extern bool yang_str2bool(const char *value);
extern struct yang_data *yang_data_new_bool(const char *xpath, bool value);
extern bool yang_dnode_get_bool(const struct lyd_node *dnode,
- const char *xpath_fmt, ...);
-extern bool yang_get_default_bool(const char *xpath_fmt, ...);
+ const char *xpath_fmt, ...) PRINTFRR(2, 3);
+extern bool yang_get_default_bool(const char *xpath_fmt, ...) PRINTFRR(1, 2);
/* dec64 */
extern double yang_str2dec64(const char *xpath, const char *value);
extern struct yang_data *yang_data_new_dec64(const char *xpath, double value);
extern double yang_dnode_get_dec64(const struct lyd_node *dnode,
- const char *xpath_fmt, ...);
-extern double yang_get_default_dec64(const char *xpath_fmt, ...);
+ const char *xpath_fmt, ...) PRINTFRR(2, 3);
+extern double yang_get_default_dec64(const char *xpath_fmt, ...) PRINTFRR(1, 2);
/* enum */
extern int yang_str2enum(const char *xpath, const char *value);
extern struct yang_data *yang_data_new_enum(const char *xpath, int value);
extern int yang_dnode_get_enum(const struct lyd_node *dnode,
- const char *xpath_fmt, ...);
-extern int yang_get_default_enum(const char *xpath_fmt, ...);
+ const char *xpath_fmt, ...) PRINTFRR(2, 3);
+extern int yang_get_default_enum(const char *xpath_fmt, ...) PRINTFRR(1, 2);
/* int8 */
extern int8_t yang_str2int8(const char *value);
extern struct yang_data *yang_data_new_int8(const char *xpath, int8_t value);
extern int8_t yang_dnode_get_int8(const struct lyd_node *dnode,
- const char *xpath_fmt, ...);
-extern int8_t yang_get_default_int8(const char *xpath_fmt, ...);
+ const char *xpath_fmt, ...) PRINTFRR(2, 3);
+extern int8_t yang_get_default_int8(const char *xpath_fmt, ...) PRINTFRR(1, 2);
/* int16 */
extern int16_t yang_str2int16(const char *value);
extern struct yang_data *yang_data_new_int16(const char *xpath, int16_t value);
extern int16_t yang_dnode_get_int16(const struct lyd_node *dnode,
- const char *xpath_fmt, ...);
-extern int16_t yang_get_default_int16(const char *xpath_fmt, ...);
+ const char *xpath_fmt, ...) PRINTFRR(2, 3);
+extern int16_t yang_get_default_int16(const char *xpath_fmt, ...)
+ PRINTFRR(1, 2);
/* int32 */
extern int32_t yang_str2int32(const char *value);
extern struct yang_data *yang_data_new_int32(const char *xpath, int32_t value);
extern int32_t yang_dnode_get_int32(const struct lyd_node *dnode,
- const char *xpath_fmt, ...);
-extern int32_t yang_get_default_int32(const char *xpath_fmt, ...);
+ const char *xpath_fmt, ...) PRINTFRR(2, 3);
+extern int32_t yang_get_default_int32(const char *xpath_fmt, ...)
+ PRINTFRR(1, 2);
/* int64 */
extern int64_t yang_str2int64(const char *value);
extern struct yang_data *yang_data_new_int64(const char *xpath, int64_t value);
extern int64_t yang_dnode_get_int64(const struct lyd_node *dnode,
- const char *xpath_fmt, ...);
-extern int64_t yang_get_default_int64(const char *xpath_fmt, ...);
+ const char *xpath_fmt, ...) PRINTFRR(2, 3);
+extern int64_t yang_get_default_int64(const char *xpath_fmt, ...)
+ PRINTFRR(1, 2);
/* uint8 */
extern uint8_t yang_str2uint8(const char *value);
extern struct yang_data *yang_data_new_uint8(const char *xpath, uint8_t value);
extern uint8_t yang_dnode_get_uint8(const struct lyd_node *dnode,
- const char *xpath_fmt, ...);
-extern uint8_t yang_get_default_uint8(const char *xpath_fmt, ...);
+ const char *xpath_fmt, ...) PRINTFRR(2, 3);
+extern uint8_t yang_get_default_uint8(const char *xpath_fmt, ...)
+ PRINTFRR(1, 2);
/* uint16 */
extern uint16_t yang_str2uint16(const char *value);
extern struct yang_data *yang_data_new_uint16(const char *xpath,
uint16_t value);
extern uint16_t yang_dnode_get_uint16(const struct lyd_node *dnode,
- const char *xpath_fmt, ...);
-extern uint16_t yang_get_default_uint16(const char *xpath_fmt, ...);
+ const char *xpath_fmt, ...)
+ PRINTFRR(2, 3);
+extern uint16_t yang_get_default_uint16(const char *xpath_fmt, ...)
+ PRINTFRR(1, 2);
/* uint32 */
extern uint32_t yang_str2uint32(const char *value);
extern struct yang_data *yang_data_new_uint32(const char *xpath,
uint32_t value);
extern uint32_t yang_dnode_get_uint32(const struct lyd_node *dnode,
- const char *xpath_fmt, ...);
-extern uint32_t yang_get_default_uint32(const char *xpath_fmt, ...);
+ const char *xpath_fmt, ...)
+ PRINTFRR(2, 3);
+extern uint32_t yang_get_default_uint32(const char *xpath_fmt, ...)
+ PRINTFRR(1, 2);
/* uint64 */
extern uint64_t yang_str2uint64(const char *value);
extern struct yang_data *yang_data_new_uint64(const char *xpath,
uint64_t value);
extern uint64_t yang_dnode_get_uint64(const struct lyd_node *dnode,
- const char *xpath_fmt, ...);
-extern uint64_t yang_get_default_uint64(const char *xpath_fmt, ...);
+ const char *xpath_fmt, ...)
+ PRINTFRR(2, 3);
+extern uint64_t yang_get_default_uint64(const char *xpath_fmt, ...)
+ PRINTFRR(1, 2);
/* string */
extern struct yang_data *yang_data_new_string(const char *xpath,
const char *value);
extern const char *yang_dnode_get_string(const struct lyd_node *dnode,
- const char *xpath_fmt, ...);
+ const char *xpath_fmt, ...)
+ PRINTFRR(2, 3);
extern void yang_dnode_get_string_buf(char *buf, size_t size,
const struct lyd_node *dnode,
- const char *xpath_fmt, ...);
-extern const char *yang_get_default_string(const char *xpath_fmt, ...);
+ const char *xpath_fmt, ...)
+ PRINTFRR(4, 5);
+extern const char *yang_get_default_string(const char *xpath_fmt, ...)
+ PRINTFRR(1, 2);
extern void yang_get_default_string_buf(char *buf, size_t size,
- const char *xpath_fmt, ...);
+ const char *xpath_fmt, ...)
+ PRINTFRR(3, 4);
/* binary */
extern struct yang_data *yang_data_new_binary(const char *xpath,
const char *value, size_t len);
extern size_t yang_dnode_get_binary_buf(char *buf, size_t size,
const struct lyd_node *dnode,
- const char *xpath_fmt, ...);
+ const char *xpath_fmt, ...)
+ PRINTFRR(4, 5);
/* empty */
extern struct yang_data *yang_data_new_empty(const char *xpath);
extern bool yang_dnode_get_empty(const struct lyd_node *dnode,
- const char *xpath_fmt, ...);
+ const char *xpath_fmt, ...) PRINTFRR(2, 3);
/* ip prefix */
extern void yang_str2prefix(const char *value, union prefixptr prefix);
@@ -136,9 +151,9 @@ extern struct yang_data *yang_data_new_prefix(const char *xpath,
union prefixconstptr prefix);
extern void yang_dnode_get_prefix(struct prefix *prefix,
const struct lyd_node *dnode,
- const char *xpath_fmt, ...);
+ const char *xpath_fmt, ...) PRINTFRR(3, 4);
extern void yang_get_default_prefix(union prefixptr var, const char *xpath_fmt,
- ...);
+ ...) PRINTFRR(2, 3);
/* ipv4 */
extern void yang_str2ipv4(const char *value, struct in_addr *addr);
@@ -146,9 +161,9 @@ extern struct yang_data *yang_data_new_ipv4(const char *xpath,
const struct in_addr *addr);
extern void yang_dnode_get_ipv4(struct in_addr *addr,
const struct lyd_node *dnode,
- const char *xpath_fmt, ...);
+ const char *xpath_fmt, ...) PRINTFRR(3, 4);
extern void yang_get_default_ipv4(struct in_addr *var, const char *xpath_fmt,
- ...);
+ ...) PRINTFRR(2, 3);
/* ipv4p */
extern void yang_str2ipv4p(const char *value, union prefixptr prefix);
@@ -156,9 +171,9 @@ extern struct yang_data *yang_data_new_ipv4p(const char *xpath,
union prefixconstptr prefix);
extern void yang_dnode_get_ipv4p(union prefixptr prefix,
const struct lyd_node *dnode,
- const char *xpath_fmt, ...);
+ const char *xpath_fmt, ...) PRINTFRR(3, 4);
extern void yang_get_default_ipv4p(union prefixptr var, const char *xpath_fmt,
- ...);
+ ...) PRINTFRR(2, 3);
/* ipv6 */
extern void yang_str2ipv6(const char *value, struct in6_addr *addr);
@@ -166,9 +181,9 @@ extern struct yang_data *yang_data_new_ipv6(const char *xpath,
const struct in6_addr *addr);
extern void yang_dnode_get_ipv6(struct in6_addr *addr,
const struct lyd_node *dnode,
- const char *xpath_fmt, ...);
+ const char *xpath_fmt, ...) PRINTFRR(3, 4);
extern void yang_get_default_ipv6(struct in6_addr *var, const char *xpath_fmt,
- ...);
+ ...) PRINTFRR(2, 3);
/* ipv6p */
extern void yang_str2ipv6p(const char *value, union prefixptr prefix);
@@ -176,17 +191,18 @@ extern struct yang_data *yang_data_new_ipv6p(const char *xpath,
union prefixconstptr prefix);
extern void yang_dnode_get_ipv6p(union prefixptr prefix,
const struct lyd_node *dnode,
- const char *xpath_fmt, ...);
+ const char *xpath_fmt, ...) PRINTFRR(3, 4);
extern void yang_get_default_ipv6p(union prefixptr var, const char *xpath_fmt,
- ...);
+ ...) PRINTFRR(2, 3);
/* ip */
extern void yang_str2ip(const char *value, struct ipaddr *addr);
extern struct yang_data *yang_data_new_ip(const char *xpath,
const struct ipaddr *addr);
extern void yang_dnode_get_ip(struct ipaddr *addr, const struct lyd_node *dnode,
- const char *xpath_fmt, ...);
-extern void yang_get_default_ip(struct ipaddr *var, const char *xpath_fmt, ...);
+ const char *xpath_fmt, ...) PRINTFRR(3, 4);
+extern void yang_get_default_ip(struct ipaddr *var, const char *xpath_fmt, ...)
+ PRINTFRR(2, 3);
/* mac */
extern struct yang_data *yang_data_new_mac(const char *xpath,
diff --git a/lib/zlog.c b/lib/zlog.c
index 6a36a0b123..e08d22b2b9 100644
--- a/lib/zlog.c
+++ b/lib/zlog.c
@@ -743,7 +743,11 @@ const char *zlog_msg_text(struct zlog_msg *msg, size_t *textlen)
fb.outpos_i = 0;
va_copy(args, msg->args);
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+ /* format-string checking is done further up the chain */
need += vbprintfrr(&fb, msg->fmt, args);
+#pragma GCC diagnostic pop
va_end(args);
msg->textlen = need;
@@ -762,7 +766,11 @@ const char *zlog_msg_text(struct zlog_msg *msg, size_t *textlen)
fb.outpos_i = 0;
va_copy(args, msg->args);
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+ /* same as above */
vbprintfrr(&fb, msg->fmt, args);
+#pragma GCC diagnostic pop
va_end(args);
bputch(&fb, '\n');
diff --git a/pathd/path_nb.c b/pathd/path_nb.c
index 1ab8b7f39b..137e64d12c 100644
--- a/pathd/path_nb.c
+++ b/pathd/path_nb.c
@@ -310,7 +310,7 @@ void iter_objfun_prefs(const struct lyd_node *dnode, const char* path,
struct of_cb_args args = {0};
struct of_cb_pref *p;
- yang_dnode_iterate(iter_objfun_cb, &args, dnode, path);
+ yang_dnode_iterate(iter_objfun_cb, &args, dnode, "%s", path);
for (p = args.first; p != NULL; p = p->next)
fun(p->type, arg);
}
diff --git a/pathd/path_pcep_lib.c b/pathd/path_pcep_lib.c
index 8e3565d72d..6b247b705f 100644
--- a/pathd/path_pcep_lib.c
+++ b/pathd/path_pcep_lib.c
@@ -38,7 +38,8 @@ DEFINE_MTYPE_STATIC(PATHD, PCEPLIB_MESSAGES, "PCEPlib PCEP Messages");
#define MAX_PATH_NAME_SIZE 255
/* pceplib logging callback */
-static int pceplib_logging_cb(int level, const char *fmt, va_list args);
+static int pceplib_logging_cb(int level, const char *fmt, va_list args)
+ PRINTFRR(2, 0);
/* Socket callbacks */
static int pcep_lib_pceplib_socket_read_cb(void *fpt, void **thread, int fd,
diff --git a/pceplib/pcep_utils_logging.c b/pceplib/pcep_utils_logging.c
index c9b2588b4b..7afe55f125 100644
--- a/pceplib/pcep_utils_logging.c
+++ b/pceplib/pcep_utils_logging.c
@@ -27,10 +27,12 @@
#include <stdarg.h>
#include <stdio.h>
+#include "compiler.h"
#include "pcep_utils_logging.h"
/* Forward declaration */
-int pcep_stdout_logger(int priority, const char *format, va_list args);
+int pcep_stdout_logger(int priority, const char *format, va_list args)
+ PRINTFRR(2, 0);
static pcep_logger_func logger_func = pcep_stdout_logger;
static int logging_level_ = LOG_INFO;
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c
index 306891c0e0..d73ec2990d 100644
--- a/pimd/pim_cmd.c
+++ b/pimd/pim_cmd.c
@@ -4777,14 +4777,11 @@ DEFPY(ip_msdp_timers, ip_msdp_timers_cmd,
"Connection retry period (in seconds)\n")
{
const char *vrfname;
- char xpath[XPATH_MAXLEN];
vrfname = pim_cli_get_vrf_name(vty);
if (vrfname == NULL)
return CMD_WARNING_CONFIG_FAILED;
- snprintf(xpath, sizeof(xpath), FRR_PIM_MSDP_XPATH, "frr-pim:pimd",
- "pim", vrfname, "frr-routing:ipv4");
nb_cli_enqueue_change(vty, "./hold-time", NB_OP_MODIFY, holdtime_str);
nb_cli_enqueue_change(vty, "./keep-alive", NB_OP_MODIFY, keepalive_str);
if (connretry_str)
@@ -4794,8 +4791,8 @@ DEFPY(ip_msdp_timers, ip_msdp_timers_cmd,
nb_cli_enqueue_change(vty, "./connection-retry", NB_OP_DESTROY,
NULL);
- nb_cli_apply_changes(vty, xpath);
-
+ nb_cli_apply_changes(vty, FRR_PIM_MSDP_XPATH, "frr-pim:pimd", "pim",
+ vrfname, "frr-routing:ipv4");
return CMD_SUCCESS;
}
@@ -4810,20 +4807,17 @@ DEFPY(no_ip_msdp_timers, no_ip_msdp_timers_cmd,
IGNORED_IN_NO_STR)
{
const char *vrfname;
- char xpath[XPATH_MAXLEN];
vrfname = pim_cli_get_vrf_name(vty);
if (vrfname == NULL)
return CMD_WARNING_CONFIG_FAILED;
- snprintf(xpath, sizeof(xpath), FRR_PIM_MSDP_XPATH, "frr-pim:pimd",
- "pim", vrfname, "frr-routing:ipv4");
-
nb_cli_enqueue_change(vty, "./hold-time", NB_OP_DESTROY, NULL);
nb_cli_enqueue_change(vty, "./keep-alive", NB_OP_DESTROY, NULL);
nb_cli_enqueue_change(vty, "./connection-retry", NB_OP_DESTROY, NULL);
- nb_cli_apply_changes(vty, xpath);
+ nb_cli_apply_changes(vty, FRR_PIM_MSDP_XPATH, "frr-pim:pimd", "pim",
+ vrfname, "frr-routing:ipv4");
return CMD_SUCCESS;
}
diff --git a/pimd/pim_cmd_common.c b/pimd/pim_cmd_common.c
index 28e4c488f3..d220ae082f 100644
--- a/pimd/pim_cmd_common.c
+++ b/pimd/pim_cmd_common.c
@@ -299,7 +299,7 @@ int pim_process_no_rp_kat_cmd(struct vty *vty)
sizeof(rs_timer_xpath));
/* RFC4601 */
- v = yang_dnode_get_uint16(vty->candidate_config->dnode,
+ v = yang_dnode_get_uint16(vty->candidate_config->dnode, "%s",
rs_timer_xpath);
v = 3 * v + PIM_REGISTER_PROBE_TIME_DEFAULT;
if (v > UINT16_MAX)
@@ -688,7 +688,7 @@ int pim_process_no_rp_plist_cmd(struct vty *vty, const char *rp_str,
return NB_OK;
}
- plist = yang_dnode_get_string(plist_dnode, plist_xpath);
+ plist = yang_dnode_get_string(plist_dnode, "%s", plist_xpath);
if (strcmp(prefix_list, plist)) {
vty_out(vty, "%% Unable to find specified RP\n");
return NB_OK;
diff --git a/staticd/static_vty.c b/staticd/static_vty.c
index ff79622038..c5bea755ec 100644
--- a/staticd/static_vty.c
+++ b/staticd/static_vty.c
@@ -377,7 +377,7 @@ static int static_route_nb_run(struct vty *vty, struct static_route_args *args)
}
}
- ret = nb_cli_apply_changes(vty, xpath_prefix);
+ ret = nb_cli_apply_changes(vty, "%s", xpath_prefix);
} else {
if (args->source)
snprintf(ab_xpath, sizeof(ab_xpath),
@@ -411,7 +411,7 @@ static int static_route_nb_run(struct vty *vty, struct static_route_args *args)
yang_dnode_get_path(dnode, ab_xpath, XPATH_MAXLEN);
nb_cli_enqueue_change(vty, ab_xpath, NB_OP_DESTROY, NULL);
- ret = nb_cli_apply_changes(vty, ab_xpath);
+ ret = nb_cli_apply_changes(vty, "%s", ab_xpath);
}
return ret;
diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c
index 316247adb3..85e4b1c033 100644
--- a/staticd/static_zebra.c
+++ b/staticd/static_zebra.c
@@ -211,6 +211,9 @@ static int static_zebra_nexthop_update(ZAPI_CALLBACK_ARGS)
return 1;
}
+ if (zclient->bfd_integration)
+ bfd_nht_update(&matched, &nhr);
+
if (matched.family == AF_INET6)
afi = AFI_IP6;
diff --git a/tests/topotests/all_protocol_startup/r1/ip_nht.ref b/tests/topotests/all_protocol_startup/r1/ip_nht.ref
index 1da4da4df5..0ef3f4b675 100644
--- a/tests/topotests/all_protocol_startup/r1/ip_nht.ref
+++ b/tests/topotests/all_protocol_startup/r1/ip_nht.ref
@@ -1,34 +1,34 @@
1.1.1.1
resolved via static
- is directly connected, r1-eth1
+ is directly connected, r1-eth1 (vrf default), weight 1
Client list: pbr(fd XX)
1.1.1.2
resolved via static
- is directly connected, r1-eth2
+ is directly connected, r1-eth2 (vrf default), weight 1
Client list: pbr(fd XX)
1.1.1.3
resolved via static
- is directly connected, r1-eth3
+ is directly connected, r1-eth3 (vrf default), weight 1
Client list: pbr(fd XX)
1.1.1.4
resolved via static
- is directly connected, r1-eth4
+ is directly connected, r1-eth4 (vrf default), weight 1
Client list: pbr(fd XX)
1.1.1.5
resolved via static
- is directly connected, r1-eth5
+ is directly connected, r1-eth5 (vrf default), weight 1
Client list: pbr(fd XX)
1.1.1.6
resolved via static
- is directly connected, r1-eth6
+ is directly connected, r1-eth6 (vrf default), weight 1
Client list: pbr(fd XX)
1.1.1.7
resolved via static
- is directly connected, r1-eth7
+ is directly connected, r1-eth7 (vrf default), weight 1
Client list: pbr(fd XX)
1.1.1.8
resolved via static
- is directly connected, r1-eth8
+ is directly connected, r1-eth8 (vrf default), weight 1
Client list: pbr(fd XX)
2.2.2.1
unresolved
@@ -53,19 +53,19 @@
Client list: pbr(fd XX)
192.168.0.2
resolved via connected
- is directly connected, r1-eth0
+ is directly connected, r1-eth0 (vrf default)
Client list: static(fd XX)
192.168.0.4
resolved via connected
- is directly connected, r1-eth0
+ is directly connected, r1-eth0 (vrf default)
Client list: static(fd XX)
192.168.7.10
resolved via connected
- is directly connected, r1-eth7
+ is directly connected, r1-eth7 (vrf default)
Client list: bgp(fd XX)
192.168.7.20(Connected)
resolved via connected
- is directly connected, r1-eth7
+ is directly connected, r1-eth7 (vrf default)
Client list: bgp(fd XX)
192.168.161.4
unresolved
diff --git a/tests/topotests/all_protocol_startup/r1/ipv6_nht.ref b/tests/topotests/all_protocol_startup/r1/ipv6_nht.ref
index 0255ecdee8..8c93728007 100644
--- a/tests/topotests/all_protocol_startup/r1/ipv6_nht.ref
+++ b/tests/topotests/all_protocol_startup/r1/ipv6_nht.ref
@@ -1,13 +1,13 @@
fc00::2
resolved via connected
- is directly connected, r1-eth0
+ is directly connected, r1-eth0 (vrf default)
Client list: static(fd XX)
fc00:0:0:8::1000
resolved via connected
- is directly connected, r1-eth8
+ is directly connected, r1-eth8 (vrf default)
Client list: bgp(fd XX)
fc00:0:0:8::2000(Connected)
resolved via connected
- is directly connected, r1-eth8
+ is directly connected, r1-eth8 (vrf default)
Client list: bgp(fd XX)
- \ No newline at end of file
+
diff --git a/tests/topotests/babel_topo1/r1/babeld.conf b/tests/topotests/babel_topo1/r1/babeld.conf
new file mode 100644
index 0000000000..372d2edff1
--- /dev/null
+++ b/tests/topotests/babel_topo1/r1/babeld.conf
@@ -0,0 +1,21 @@
+log file eigrpd.log
+
+interface r1-eth0
+ babel hello-interval 1000
+ babel wired
+ babel update-interval 50
+!
+interface r1-eth1
+ babel hello-interval 1000
+ babel wired
+ babel update-interval 50
+!
+router babel
+ network r1-eth0
+ network r1-eth1
+ redistribute ipv4 connected
+ redistribute ipv6 connected
+!
+line vty
+!
+
diff --git a/tests/topotests/babel_topo1/r1/show_ip_route.json_ref b/tests/topotests/babel_topo1/r1/show_ip_route.json_ref
new file mode 100644
index 0000000000..0d52b67df5
--- /dev/null
+++ b/tests/topotests/babel_topo1/r1/show_ip_route.json_ref
@@ -0,0 +1,80 @@
+{
+ "192.168.1.0/24":[
+ {
+ "prefix":"192.168.1.0/24",
+ "protocol":"connected",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"r1-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "192.168.2.0/24":[
+ {
+ "prefix":"192.168.2.0/24",
+ "prefixLen":24,
+ "protocol":"babel",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"193.1.1.2",
+ "afi":"ipv4",
+ "interfaceName":"r1-eth1"
+ }
+ ]
+ }
+ ],
+ "192.168.3.0/24":[
+ {
+ "prefix":"192.168.3.0/24",
+ "protocol":"babel",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"193.1.1.2",
+ "afi":"ipv4",
+ "interfaceName":"r1-eth1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "193.1.1.0/26":[
+ {
+ "prefix":"193.1.1.0/26",
+ "protocol":"connected",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"r1-eth1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "193.1.2.0/24":[
+ {
+ "prefix":"193.1.2.0/24",
+ "protocol":"babel",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"193.1.1.2",
+ "afi":"ipv4",
+ "interfaceName":"r1-eth1",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/babel_topo1/r1/zebra.conf b/tests/topotests/babel_topo1/r1/zebra.conf
new file mode 100644
index 0000000000..5eda3e24fc
--- /dev/null
+++ b/tests/topotests/babel_topo1/r1/zebra.conf
@@ -0,0 +1,22 @@
+log file zebra.log
+! debug zebra rib detail
+!
+hostname r1
+!
+interface r1-eth0
+ ip address 192.168.1.1/24
+ ipv6 address 192:168:1::1/64
+!
+interface r1-eth1
+ description to sw2 - babel interface
+ ip address 193.1.1.1/26
+ ipv6 address 193:1:1::1/64
+ no link-detect
+!
+ip forwarding
+ipv6 forwarding
+!
+!
+line vty
+!
+
diff --git a/tests/topotests/babel_topo1/r2/babeld.conf b/tests/topotests/babel_topo1/r2/babeld.conf
new file mode 100644
index 0000000000..8a36dda5f8
--- /dev/null
+++ b/tests/topotests/babel_topo1/r2/babeld.conf
@@ -0,0 +1,18 @@
+log file eigrpd.log
+!
+interface r2-eth0
+ babel hello-interval 1000
+ babel wired
+ babel update-interval 50
+!
+interface r2-eth1
+ babel hello-interval 1000
+ babel wired
+ babel update-interval 50
+!
+router babel
+ network r2-eth0
+ network r2-eth1
+ redistribute ipv4 connected
+ redistribute ipv6 connected
+!
diff --git a/tests/topotests/babel_topo1/r2/show_ip_route.json_ref b/tests/topotests/babel_topo1/r2/show_ip_route.json_ref
new file mode 100644
index 0000000000..ff3f6ab874
--- /dev/null
+++ b/tests/topotests/babel_topo1/r2/show_ip_route.json_ref
@@ -0,0 +1,80 @@
+{
+ "192.168.1.0/24":[
+ {
+ "prefix":"192.168.1.0/24",
+ "protocol":"babel",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"193.1.1.1",
+ "afi":"ipv4",
+ "interfaceName":"r2-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "192.168.2.0/24":[
+ {
+ "prefix":"192.168.2.0/24",
+ "protocol":"babel",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"193.1.2.2",
+ "afi":"ipv4",
+ "interfaceName":"r2-eth1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "192.168.3.0/24":[
+ {
+ "prefix":"192.168.3.0/24",
+ "protocol":"babel",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"193.1.2.2",
+ "afi":"ipv4",
+ "interfaceName":"r2-eth1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "193.1.1.0/26":[
+ {
+ "prefix":"193.1.1.0/26",
+ "protocol":"connected",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"r2-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "193.1.2.0/24":[
+ {
+ "prefix":"193.1.2.0/24",
+ "protocol":"connected",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"r2-eth1",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/babel_topo1/r2/zebra.conf b/tests/topotests/babel_topo1/r2/zebra.conf
new file mode 100644
index 0000000000..301a8b2e34
--- /dev/null
+++ b/tests/topotests/babel_topo1/r2/zebra.conf
@@ -0,0 +1,23 @@
+log file zebra.log
+!
+hostname r2
+!
+interface r2-eth0
+ description to sw2 - babel interface
+ ip address 193.1.1.2/26
+ ipv6 address 193:1:1::2/64
+ no link-detect
+!
+interface r2-eth1
+ description to sw3 - babel interface
+ ip address 193.1.2.1/24
+ ipv6 address 193:1:2::1/64
+ no link-detect
+!
+ip forwarding
+ipv6 forwarding
+!
+!
+line vty
+!
+
diff --git a/tests/topotests/babel_topo1/r3/babeld.conf b/tests/topotests/babel_topo1/r3/babeld.conf
new file mode 100644
index 0000000000..1e9dc261f5
--- /dev/null
+++ b/tests/topotests/babel_topo1/r3/babeld.conf
@@ -0,0 +1,18 @@
+log file eigrpd.log
+!
+interface r3-eth0
+ babel hello-interval 1000
+ babel wired
+ babel update-interval 50
+!
+interface r3-eth1
+ babel hello-interval 1000
+ babel wired
+ babel update-interval 50
+!
+router babel
+ network r3-eth0
+ network r3-eth1
+ redistribute ipv4 connected
+ redistribute ipv4 static
+ redistirbute ipv6 connected
diff --git a/tests/topotests/babel_topo1/r3/show_ip_route.json_ref b/tests/topotests/babel_topo1/r3/show_ip_route.json_ref
new file mode 100644
index 0000000000..7fe66fa66d
--- /dev/null
+++ b/tests/topotests/babel_topo1/r3/show_ip_route.json_ref
@@ -0,0 +1,81 @@
+{
+ "192.168.1.0/24":[
+ {
+ "prefix":"192.168.1.0/24",
+ "protocol":"babel",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"193.1.2.1",
+ "afi":"ipv4",
+ "interfaceName":"r3-eth1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "192.168.2.0/24":[
+ {
+ "prefix":"192.168.2.0/24",
+ "protocol":"static",
+ "selected":true,
+ "distance":1,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"192.168.3.10",
+ "afi":"ipv4",
+ "interfaceName":"r3-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "192.168.3.0/24":[
+ {
+ "prefix":"192.168.3.0/24",
+ "protocol":"connected",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"r3-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "193.1.1.0/26":[
+ {
+ "prefix":"193.1.1.0/26",
+ "protocol":"babel",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"193.1.2.1",
+ "afi":"ipv4",
+ "interfaceName":"r3-eth1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "193.1.2.0/24":[
+ {
+ "prefix":"193.1.2.0/24",
+ "protocol":"connected",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"r3-eth1",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/babel_topo1/r3/zebra.conf b/tests/topotests/babel_topo1/r3/zebra.conf
new file mode 100644
index 0000000000..34e8c626f2
--- /dev/null
+++ b/tests/topotests/babel_topo1/r3/zebra.conf
@@ -0,0 +1,25 @@
+log file zebra.log
+!
+hostname r3
+!
+interface r3-eth0
+ description to sw4 - Stub interface
+ ip address 192.168.3.1/24
+ ipv6 address 192:168:3::1/64
+ no link-detect
+!
+interface r3-eth1
+ description to sw3 - RIPv2 interface
+ ip address 193.1.2.2/24
+ ipv6 address 193:1:2::2/64
+ no link-detect
+!
+ip route 192.168.2.0/24 192.168.3.10
+ipv6 route 192:168:2::0/64 192:168:3::10
+!
+ip forwarding
+ipv6 forwarding
+!
+!
+line vty
+!
diff --git a/tests/topotests/babel_topo1/test_babel_topo1.py b/tests/topotests/babel_topo1/test_babel_topo1.py
new file mode 100644
index 0000000000..12f81042e6
--- /dev/null
+++ b/tests/topotests/babel_topo1/test_babel_topo1.py
@@ -0,0 +1,171 @@
+#!/usr/bin/env python
+
+#
+# test_babel_topo1.py
+#
+# Copyright (c) 2017 by
+# Cumulus Networks, 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_babel_topo1.py: Testing BABEL
+
+"""
+
+import os
+import re
+import sys
+import pytest
+import json
+
+pytestmark = [pytest.mark.babeld]
+
+# 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
+
+# Required to instantiate the topology builder class.
+
+#####################################################
+##
+## Network Topology Definition
+##
+#####################################################
+
+
+def build_topo(tgen):
+ for routern in range(1, 4):
+ tgen.add_router("r{}".format(routern))
+
+ # On main router
+ # First switch is for a dummy interface (for local network)
+ switch = tgen.add_switch("sw1")
+ switch.add_link(tgen.gears["r1"])
+
+ # Switches for BABEL
+ # switch 2 switch is for connection to BABEL router
+ switch = tgen.add_switch("sw2")
+ switch.add_link(tgen.gears["r1"])
+ switch.add_link(tgen.gears["r2"])
+
+ # switch 4 is stub on remote BABEL router
+ switch = tgen.add_switch("sw4")
+ switch.add_link(tgen.gears["r3"])
+
+ # switch 3 is between BABEL routers
+ switch = tgen.add_switch("sw3")
+ switch.add_link(tgen.gears["r2"])
+ switch.add_link(tgen.gears["r3"])
+
+
+#####################################################
+##
+## Tests starting
+##
+#####################################################
+
+
+def setup_module(module):
+ "Setup topology"
+ tgen = Topogen(build_topo, module.__name__)
+ tgen.start_topology()
+
+ # This is a sample of configuration loading.
+ router_list = tgen.routers()
+ for rname, router in router_list.items():
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_BABEL, os.path.join(CWD, "{}/babeld.conf".format(rname))
+ )
+
+ 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_converge_protocols():
+ "Wait for protocol convergence"
+
+ tgen = get_topogen()
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ topotest.sleep(10, "Waiting for BABEL convergence")
+
+
+def test_zebra_ipv4_routingTable():
+ "Test 'show ip route'"
+
+ tgen = get_topogen()
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ failures = 0
+ router_list = tgen.routers().values()
+ for router in router_list:
+ output = router.vtysh_cmd("show ip route json", isjson=True)
+ refTableFile = "{}/{}/show_ip_route.json_ref".format(CWD, router.name)
+ expected = json.loads(open(refTableFile).read())
+
+ assertmsg = "Zebra IPv4 Routing Table verification failed for router {}".format(
+ router.name
+ )
+ assert topotest.json_cmp(output, expected) is None, assertmsg
+
+def test_shutdown_check_stderr():
+ if os.environ.get("TOPOTESTS_CHECK_STDERR") is None:
+ pytest.skip("Skipping test for Stderr output and memory leaks")
+
+ tgen = get_topogen()
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Verifying unexpected STDERR output from daemons")
+
+ router_list = tgen.routers().values()
+ for router in router_list:
+ router.stop()
+
+ log = tgen.net[router.name].getStdErr("babeld")
+ if log:
+ logger.error("BABELd StdErr Log:" + log)
+ log = tgen.net[router.name].getStdErr("zebra")
+ if log:
+ logger.error("Zebra StdErr Log:" + log)
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_dont_capability_negotiate/r1/bgpd.conf b/tests/topotests/bgp_dont_capability_negotiate/r1/bgpd.conf
index b429efe076..e2ff1df965 100644
--- a/tests/topotests/bgp_dont_capability_negotiate/r1/bgpd.conf
+++ b/tests/topotests/bgp_dont_capability_negotiate/r1/bgpd.conf
@@ -1,6 +1,12 @@
!
+debug bgp neighbor
+!
router bgp 65001
no bgp ebgp-requires-policy
+ bgp default show-hostname
+ bgp default show-nexthop-hostname
neighbor 192.168.1.2 remote-as external
+ neighbor 192.168.1.2 timers 1 3
+ neighbor 192.168.1.2 timers connect 1
neighbor 192.168.1.2 dont-capability-negotiate
!
diff --git a/tests/topotests/bgp_dont_capability_negotiate/r2/bgpd.conf b/tests/topotests/bgp_dont_capability_negotiate/r2/bgpd.conf
index 4af2cd6a80..06e1e54b6f 100644
--- a/tests/topotests/bgp_dont_capability_negotiate/r2/bgpd.conf
+++ b/tests/topotests/bgp_dont_capability_negotiate/r2/bgpd.conf
@@ -1,6 +1,8 @@
router bgp 65002
no bgp ebgp-requires-policy
neighbor 192.168.1.1 remote-as external
+ neighbor 192.168.1.1 timers 1 3
+ neighbor 192.168.1.1 timers connect 1
address-family ipv4 unicast
redistribute connected
exit-address-family
diff --git a/tests/topotests/bgp_dont_capability_negotiate/test_bgp_dont_capability_negotiate.py b/tests/topotests/bgp_dont_capability_negotiate/test_bgp_dont_capability_negotiate.py
index 272fdd334a..211472e57d 100644
--- a/tests/topotests/bgp_dont_capability_negotiate/test_bgp_dont_capability_negotiate.py
+++ b/tests/topotests/bgp_dont_capability_negotiate/test_bgp_dont_capability_negotiate.py
@@ -37,6 +37,7 @@ sys.path.append(os.path.join(CWD, "../"))
# pylint: disable=C0413
from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.common_config import step
pytestmark = [pytest.mark.bgpd]
@@ -64,32 +65,104 @@ def teardown_module(mod):
tgen.stop_topology()
+def bgp_converge(router):
+ output = json.loads(router.vtysh_cmd("show bgp ipv4 unicast summary json"))
+ expected = {
+ "peers": {
+ "192.168.1.2": {
+ "pfxRcd": 2,
+ "pfxSnt": 2,
+ "state": "Established",
+ "peerState": "OK",
+ }
+ }
+ }
+ return topotest.json_cmp(output, expected)
+
+
def test_bgp_dont_capability_negotiate():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
- router = tgen.gears["r1"]
+ r1 = tgen.gears["r1"]
+
+ test_func = functools.partial(bgp_converge, r1)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "Can't converge with dont-capability-negotiate"
+
+
+def test_bgp_check_fqdn():
+ tgen = get_topogen()
- def _bgp_converge(router):
- output = json.loads(router.vtysh_cmd("show bgp ipv4 unicast summary json"))
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r1 = tgen.gears["r1"]
+ r2 = tgen.gears["r2"]
+
+ def _bgp_check_fqdn(fqdn=None):
+ output = json.loads(r1.vtysh_cmd("show bgp ipv4 unicast 172.16.16.1/32 json"))
expected = {
- "peers": {
- "192.168.1.2": {
- "pfxRcd": 2,
- "pfxSnt": 2,
- "state": "Established",
- "peerState": "OK",
+ "paths": [
+ {
+ "nexthops": [
+ {
+ "hostname": fqdn,
+ }
+ ],
+ "peer": {
+ "hostname": fqdn,
+ },
}
- }
+ ]
}
return topotest.json_cmp(output, expected)
- test_func = functools.partial(_bgp_converge, router)
- success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ step("Enable all capabilities")
+ r1.vtysh_cmd(
+ """
+ configure terminal
+ router bgp
+ address-family ipv4 unicast
+ no neighbor 192.168.1.2 dont-capability-negotiate
+ end
+ clear bgp 192.168.1.2
+ """
+ )
+
+ step("Wait to converge")
+ test_func = functools.partial(bgp_converge, r1)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "Can't converge with dont-capability-negotiate"
+
+ test_func = functools.partial(_bgp_check_fqdn, "r2")
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "FQDN capability enabled, but r1 can't see it"
+
+ step("Disable sending any capabilities from r2")
+ r2.vtysh_cmd(
+ """
+ configure terminal
+ router bgp
+ address-family ipv4 unicast
+ neighbor 192.168.1.1 dont-capability-negotiate
+ end
+ clear bgp 192.168.1.1
+ """
+ )
+
+ step("Wait to converge")
+ test_func = functools.partial(bgp_converge, r1)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
assert result is None, "Can't converge with dont-capability-negotiate"
+ step("Make sure FQDN capability is reset")
+ test_func = functools.partial(_bgp_check_fqdn)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "FQDN capability disabled, but we still have a hostname"
+
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
diff --git a/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vpn_routes.json b/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vpn_routes.json
index 903c4603c5..28e153e3de 100644
--- a/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vpn_routes.json
+++ b/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vpn_routes.json
@@ -1,7 +1,6 @@
{
"vrfId":0,
"vrfName":"default",
- "tableVersion":1,
"routerId":"1.1.1.1",
"defaultLocPrf":100,
"localAS":65500,
@@ -17,7 +16,6 @@
"prefix":"10.201.0.0",
"prefixLen":24,
"network":"10.201.0.0\/24",
- "version":1,
"metric":0,
"weight":32768,
"peerId":"(unspec)",
@@ -28,6 +26,7 @@
"nexthops":[
{
"ip":"0.0.0.0",
+ "hostname":"r1",
"afi":"ipv4",
"used":true
}
@@ -45,7 +44,6 @@
"prefix":"10.200.0.0",
"prefixLen":24,
"network":"10.200.0.0\/24",
- "version":1,
"metric":0,
"locPrf":100,
"weight":0,
@@ -55,6 +53,7 @@
"nexthops":[
{
"ip":"10.125.0.2",
+ "hostname":"r2",
"afi":"ipv4",
"used":true
}
diff --git a/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vpn_routes_unfiltered.json b/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vpn_routes_unfiltered.json
index 3cc0b4a5f5..45f4acce6f 100644
--- a/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vpn_routes_unfiltered.json
+++ b/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vpn_routes_unfiltered.json
@@ -1,7 +1,6 @@
{
"vrfId":0,
"vrfName":"default",
- "tableVersion":1,
"routerId":"1.1.1.1",
"defaultLocPrf":100,
"localAS":65500,
@@ -17,7 +16,6 @@
"prefix":"10.201.0.0",
"prefixLen":24,
"network":"10.201.0.0\/24",
- "version":1,
"metric":0,
"weight":32768,
"peerId":"(unspec)",
@@ -28,6 +26,7 @@
"nexthops":[
{
"ip":"0.0.0.0",
+ "hostname":"r1",
"afi":"ipv4",
"used":true
}
@@ -45,7 +44,6 @@
"prefix":"10.200.0.0",
"prefixLen":24,
"network":"10.200.0.0\/24",
- "version":1,
"metric":0,
"locPrf":100,
"weight":0,
@@ -55,6 +53,7 @@
"nexthops":[
{
"ip":"10.125.0.2",
+ "hostname":"r2",
"afi":"ipv4",
"used":true
}
@@ -72,7 +71,6 @@
"prefix":"10.210.0.0",
"prefixLen":24,
"network":"10.210.0.0\/24",
- "version":1,
"metric":0,
"locPrf":100,
"weight":0,
@@ -82,6 +80,7 @@
"nexthops":[
{
"ip":"10.125.0.2",
+ "hostname":"r2",
"afi":"ipv4",
"used":true
}
diff --git a/tests/topotests/bgp_vpnv4_noretain/test_bgp_vpnv4_noretain.py b/tests/topotests/bgp_vpnv4_noretain/test_bgp_vpnv4_noretain.py
index b4a841d9cf..ed5cc3faf6 100644
--- a/tests/topotests/bgp_vpnv4_noretain/test_bgp_vpnv4_noretain.py
+++ b/tests/topotests/bgp_vpnv4_noretain/test_bgp_vpnv4_noretain.py
@@ -133,27 +133,37 @@ def teardown_module(_mod):
tgen.stop_topology()
-def test_protocols_convergence():
+def router_json_cmp_exact_filter(router, cmd, expected):
+ # filter out tableVersion, version and nhVrfID
+ output = router.cmd('vtysh -c "{}" | grep -v ersion | grep -v nhVrfId'.format(cmd))
+ logger.info("{}: {}\n{}".format(router.name, cmd, output))
+
+ json_output = json.loads(output)
+
+ return topotest.json_cmp(json_output, expected, exact=True)
+
+
+def test_bgp_no_retain():
"""
- Assert that all protocols have converged
- statuses as they depend on it.
+ Check bgp no retain route-target all on r1
"""
+
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
# Check IPv4 VPN routing tables on r1
- logger.info("Checking IPv4 routes for convergence on r1")
- router = tgen.gears['r1']
+ logger.info("Checking VPNv4 routes for convergence on r1")
+ router = tgen.gears["r1"]
json_file = "{}/{}/ipv4_vpn_routes.json".format(CWD, router.name)
if not os.path.isfile(json_file):
logger.info("skipping file {}".format(json_file))
- assert 0, 'ipv4_vpn_routes.json file not found'
+ assert 0, "{} file not found".format(json_file)
return
expected = json.loads(open(json_file).read())
test_func = partial(
- topotest.router_json_cmp,
+ router_json_cmp_exact_filter,
router,
"show bgp ipv4 vpn json",
expected,
@@ -162,23 +172,31 @@ def test_protocols_convergence():
assertmsg = '"{}" JSON output mismatches'.format(router.name)
assert result is None, assertmsg
- # Check BGP IPv4 routing tables after unsetting no retain flag
- logger.info("Checking BGP IPv4 routes for convergence on r2")
- router = tgen.gears['r1']
- router.vtysh_cmd("configure\nrouter bgp 65500\naddress-family ipv4 vpn\nbgp retain route-target all\n")
+
+def test_bgp_retain():
+ """
+ Apply and check bgp retain route-target all on r1
+ """
+
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
# Check IPv4 VPN routing tables on r1
- logger.info("Checking IPv4 routes for convergence on r1")
- router = tgen.gears['r1']
+ logger.info("Checking VPNv4 routes on r1 after bgp no retain")
+ router = tgen.gears["r1"]
+ router.vtysh_cmd(
+ "configure\nrouter bgp 65500\naddress-family ipv4 vpn\nbgp retain route-target all\n"
+ )
json_file = "{}/{}/ipv4_vpn_routes_unfiltered.json".format(CWD, router.name)
if not os.path.isfile(json_file):
logger.info("skipping file {}".format(json_file))
- assert 0, 'ipv4_vpn_routes_unfiltered.json file not found'
+ assert 0, "{} file not found".format(json_file)
return
expected = json.loads(open(json_file).read())
test_func = partial(
- topotest.router_json_cmp,
+ router_json_cmp_exact_filter,
router,
"show bgp ipv4 vpn json",
expected,
@@ -187,6 +205,7 @@ def test_protocols_convergence():
assertmsg = '"{}" JSON output mismatches'.format(router.name)
assert result is None, assertmsg
+
def test_memory_leak():
"Run the memory leak test and report results."
tgen = get_topogen()
diff --git a/tests/topotests/lib/topotest.py b/tests/topotests/lib/topotest.py
index 61cf16944f..7f68b4ccf3 100644
--- a/tests/topotests/lib/topotest.py
+++ b/tests/topotests/lib/topotest.py
@@ -1888,15 +1888,16 @@ class Router(Node):
# Exclude empty string at end of list
for d in dmns[:-1]:
if re.search(r"%s" % daemon, d):
- daemonpid = self.cmd("cat %s" % d.rstrip()).rstrip()
+ daemonpidfile = d.rstrip()
+ daemonpid = self.cmd("cat %s" % daemonpidfile).rstrip()
if daemonpid.isdigit() and pid_exists(int(daemonpid)):
logger.info(
"{}: killing {}".format(
self.name,
- os.path.basename(d.rstrip().rsplit(".", 1)[0]),
+ os.path.basename(daemonpidfile.rsplit(".", 1)[0]),
)
)
- self.cmd("kill -9 %s" % daemonpid)
+ os.kill(int(daemonpid), signal.SIGKILL)
if pid_exists(int(daemonpid)):
numRunning += 1
while wait and numRunning > 0:
@@ -1922,12 +1923,12 @@ class Router(Node):
),
)
)
- self.cmd("kill -9 %s" % daemonpid)
+ os.kill(int(daemonpid), signal.SIGKILL)
if daemonpid.isdigit() and not pid_exists(
int(daemonpid)
):
numRunning -= 1
- self.cmd("rm -- {}".format(d.rstrip()))
+ self.cmd("rm -- {}".format(daemonpidfile))
if wait:
errors = self.checkRouterCores(reportOnce=True)
if self.checkRouterVersion("<", minErrorVersion):
diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_lan.py b/tests/topotests/ospf_basic_functionality/test_ospf_lan.py
index 80ca0c8b04..773e83bd95 100644
--- a/tests/topotests/ospf_basic_functionality/test_ospf_lan.py
+++ b/tests/topotests/ospf_basic_functionality/test_ospf_lan.py
@@ -143,7 +143,7 @@ def teardown_module():
try:
# Stop toplogy and Remove tmp files
- tgen.stop_topology
+ tgen.stop_topology()
except OSError:
# OSError exception is raised when mininet tries to stop switch
diff --git a/tests/topotests/ospf_gr_helper/test_ospf_gr_helper1.py b/tests/topotests/ospf_gr_helper/test_ospf_gr_helper1.py
index a7ab29d791..f72cac4f1f 100644
--- a/tests/topotests/ospf_gr_helper/test_ospf_gr_helper1.py
+++ b/tests/topotests/ospf_gr_helper/test_ospf_gr_helper1.py
@@ -153,7 +153,7 @@ def teardown_module():
try:
# Stop toplogy and Remove tmp files
- tgen.stop_topology
+ tgen.stop_topology()
except OSError:
# OSError exception is raised when mininet tries to stop switch
diff --git a/tests/topotests/ospf_gr_helper/test_ospf_gr_helper2.py b/tests/topotests/ospf_gr_helper/test_ospf_gr_helper2.py
index b78fd235d7..a6b993d147 100644
--- a/tests/topotests/ospf_gr_helper/test_ospf_gr_helper2.py
+++ b/tests/topotests/ospf_gr_helper/test_ospf_gr_helper2.py
@@ -153,7 +153,7 @@ def teardown_module():
try:
# Stop toplogy and Remove tmp files
- tgen.stop_topology
+ tgen.stop_topology()
except OSError:
# OSError exception is raised when mininet tries to stop switch
diff --git a/tests/topotests/ospf_gr_helper/test_ospf_gr_helper3.py b/tests/topotests/ospf_gr_helper/test_ospf_gr_helper3.py
index f4e366031f..0d3baeb15d 100644
--- a/tests/topotests/ospf_gr_helper/test_ospf_gr_helper3.py
+++ b/tests/topotests/ospf_gr_helper/test_ospf_gr_helper3.py
@@ -153,7 +153,7 @@ def teardown_module():
try:
# Stop toplogy and Remove tmp files
- tgen.stop_topology
+ tgen.stop_topology()
except OSError:
# OSError exception is raised when mininet tries to stop switch
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c
index dea09fa151..7885188483 100644
--- a/vtysh/vtysh.c
+++ b/vtysh/vtysh.c
@@ -2759,6 +2759,15 @@ static char *do_prepend(struct vty *vty, struct cmd_token **argv, int argc)
return frrstr_join(argstr, argc + off, " ");
}
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+/* 'headline' is a format string with a %s for the daemon name
+ *
+ * Also for some reason GCC emits the warning on the end of the function
+ * (optimization maybe?) rather than on the vty_out line, so this pragma
+ * wraps the entire function rather than just the vty_out line.
+ */
+
static int show_per_daemon(struct vty *vty, struct cmd_token **argv, int argc,
const char *headline)
{
@@ -2777,6 +2786,7 @@ static int show_per_daemon(struct vty *vty, struct cmd_token **argv, int argc,
return ret;
}
+#pragma GCC diagnostic pop
static int show_one_daemon(struct vty *vty, struct cmd_token **argv, int argc,
const char *name)
@@ -4353,7 +4363,11 @@ char *vtysh_prompt(void)
{
static char buf[512];
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+ /* prompt formatting has a %s in the cmd_node prompt string. */
snprintf(buf, sizeof(buf), cmd_prompt(vty->node), cmd_hostname_get());
+#pragma GCC diagnostic pop
return buf;
}
diff --git a/watchfrr/watchfrr.c b/watchfrr/watchfrr.c
index 4a3575ae75..c37626ccc6 100644
--- a/watchfrr/watchfrr.c
+++ b/watchfrr/watchfrr.c
@@ -512,7 +512,11 @@ static int run_job(struct restart_info *restart, const char *cmdtype,
restart->kills = 0;
{
char cmd[strlen(command) + strlen(restart->name) + 1];
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+ /* user supplied command string has a %s for the daemon name */
snprintf(cmd, sizeof(cmd), command, restart->name);
+#pragma GCC diagnostic pop
if ((restart->pid = run_background(cmd)) > 0) {
thread_add_timer(master, restart_kill, restart,
gs.restart_timeout, &restart->t_kill);
@@ -941,13 +945,10 @@ static void phase_check(void)
if (!IS_UP(gs.special))
break;
zlog_info("Phased restart: %s is now up.", gs.special->name);
- {
- struct daemon *dmn;
- for (dmn = gs.daemons; dmn; dmn = dmn->next) {
- if (dmn != gs.special)
- run_job(&dmn->restart, "start",
- gs.start_command, 1, 0);
- }
+ for (dmn = gs.daemons; dmn; dmn = dmn->next) {
+ if (dmn != gs.special)
+ run_job(&dmn->restart, "start",
+ gs.start_command, 1, 0);
}
gs.phase = PHASE_NONE;
THREAD_OFF(gs.t_phase_hanging);
diff --git a/zebra/dplane_fpm_nl.c b/zebra/dplane_fpm_nl.c
index af75ddf742..0a9fecc9df 100644
--- a/zebra/dplane_fpm_nl.c
+++ b/zebra/dplane_fpm_nl.c
@@ -89,7 +89,7 @@ struct fpm_nl_ctx {
* When a FPM server connection becomes a bottleneck, we must keep the
* data plane contexts until we get a chance to process them.
*/
- struct dplane_ctx_q ctxqueue;
+ struct dplane_ctx_list_head ctxqueue;
pthread_mutex_t ctxqueue_mutex;
/* data plane events. */
@@ -1473,7 +1473,7 @@ static int fpm_nl_start(struct zebra_dplane_provider *prov)
fnc->socket = -1;
fnc->disabled = true;
fnc->prov = prov;
- TAILQ_INIT(&fnc->ctxqueue);
+ dplane_ctx_q_init(&fnc->ctxqueue);
pthread_mutex_init(&fnc->ctxqueue_mutex, NULL);
/* Set default values. */
diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c
index 54d9561e2b..42afe61469 100644
--- a/zebra/kernel_netlink.c
+++ b/zebra/kernel_netlink.c
@@ -202,13 +202,13 @@ struct nl_batch {
const struct zebra_dplane_info *zns;
- struct dplane_ctx_q ctx_list;
+ struct dplane_ctx_list_head ctx_list;
/*
* Pointer to the queue of completed contexts outbound back
* towards the dataplane module.
*/
- struct dplane_ctx_q *ctx_out_q;
+ struct dplane_ctx_list_head *ctx_out_q;
};
int netlink_config_write_helper(struct vty *vty)
@@ -1446,10 +1446,11 @@ static void nl_batch_reset(struct nl_batch *bth)
bth->msgcnt = 0;
bth->zns = NULL;
- TAILQ_INIT(&(bth->ctx_list));
+ dplane_ctx_q_init(&(bth->ctx_list));
}
-static void nl_batch_init(struct nl_batch *bth, struct dplane_ctx_q *ctx_out_q)
+static void nl_batch_init(struct nl_batch *bth,
+ struct dplane_ctx_list_head *ctx_out_q)
{
/*
* If the size of the buffer has changed, free and then allocate a new
@@ -1665,14 +1666,14 @@ static enum netlink_msg_status nl_put_msg(struct nl_batch *bth,
return FRR_NETLINK_ERROR;
}
-void kernel_update_multi(struct dplane_ctx_q *ctx_list)
+void kernel_update_multi(struct dplane_ctx_list_head *ctx_list)
{
struct nl_batch batch;
struct zebra_dplane_ctx *ctx;
- struct dplane_ctx_q handled_list;
+ struct dplane_ctx_list_head handled_list;
enum netlink_msg_status res;
- TAILQ_INIT(&handled_list);
+ dplane_ctx_q_init(&handled_list);
nl_batch_init(&batch, &handled_list);
while (true) {
@@ -1703,7 +1704,7 @@ void kernel_update_multi(struct dplane_ctx_q *ctx_list)
nl_batch_send(&batch);
- TAILQ_INIT(ctx_list);
+ dplane_ctx_q_init(ctx_list);
dplane_ctx_list_append(ctx_list, &handled_list);
}
diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c
index f84d31cc44..684ccc3ed5 100644
--- a/zebra/kernel_socket.c
+++ b/zebra/kernel_socket.c
@@ -1516,13 +1516,13 @@ int kernel_dplane_read(struct zebra_dplane_info *info)
return 0;
}
-void kernel_update_multi(struct dplane_ctx_q *ctx_list)
+void kernel_update_multi(struct dplane_ctx_list_head *ctx_list)
{
struct zebra_dplane_ctx *ctx;
- struct dplane_ctx_q handled_list;
+ struct dplane_ctx_list_head handled_list;
enum zebra_dplane_result res = ZEBRA_DPLANE_REQUEST_SUCCESS;
- TAILQ_INIT(&handled_list);
+ dplane_ctx_q_init(&handled_list);
while (true) {
ctx = dplane_ctx_dequeue(ctx_list);
@@ -1642,7 +1642,7 @@ void kernel_update_multi(struct dplane_ctx_q *ctx_list)
dplane_ctx_enqueue_tail(&handled_list, ctx);
}
- TAILQ_INIT(ctx_list);
+ dplane_ctx_q_init(ctx_list);
dplane_ctx_list_append(ctx_list, &handled_list);
}
diff --git a/zebra/rt.h b/zebra/rt.h
index 4cf4c9d780..6f4dd48a54 100644
--- a/zebra/rt.h
+++ b/zebra/rt.h
@@ -121,7 +121,7 @@ extern int kernel_del_mac_nhg(uint32_t nhg_id);
/*
* Message batching interface.
*/
-extern void kernel_update_multi(struct dplane_ctx_q *ctx_list);
+extern void kernel_update_multi(struct dplane_ctx_list_head *ctx_list);
/*
* Called by the dplane pthread to read incoming OS messages and dispatch them.
diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c
index 739f6adce9..ef4cef65ca 100644
--- a/zebra/zebra_dplane.c
+++ b/zebra/zebra_dplane.c
@@ -26,7 +26,6 @@
#include "lib/frratomic.h"
#include "lib/frr_pthread.h"
#include "lib/memory.h"
-#include "lib/queue.h"
#include "lib/zebra.h"
#include "zebra/netconf_netlink.h"
#include "zebra/zebra_router.h"
@@ -103,7 +102,7 @@ struct dplane_intf_extra {
uint32_t flags;
uint32_t status;
- TAILQ_ENTRY(dplane_intf_extra) link;
+ struct dplane_intf_extra_list_item dlink;
};
/*
@@ -152,7 +151,7 @@ struct dplane_route_info {
struct nexthop_group old_backup_ng;
/* Optional list of extra interface info */
- TAILQ_HEAD(dp_intf_extra_q, dplane_intf_extra) intf_extra_q;
+ struct dplane_intf_extra_list_head intf_extra_list;
};
/*
@@ -415,7 +414,7 @@ struct zebra_dplane_ctx {
struct zebra_dplane_info zd_ns_info;
/* Embedded list linkage */
- TAILQ_ENTRY(zebra_dplane_ctx) zd_q_entries;
+ struct dplane_ctx_list_item zd_entries;
};
/* Flag that can be set by a pre-kernel provider as a signal that an update
@@ -423,6 +422,12 @@ struct zebra_dplane_ctx {
*/
#define DPLANE_CTX_FLAG_NO_KERNEL 0x01
+/* List types declared now that the structs involved are defined. */
+DECLARE_DLIST(dplane_ctx_list, struct zebra_dplane_ctx, zd_entries);
+DECLARE_DLIST(dplane_intf_extra_list, struct dplane_intf_extra, dlink);
+
+/* List for dplane plugins/providers */
+PREDECL_DLIST(dplane_prov_list);
/*
* Registration block for one dataplane provider.
@@ -461,17 +466,20 @@ struct zebra_dplane_provider {
_Atomic uint32_t dp_error_counter;
/* Queue of contexts inbound to the provider */
- struct dplane_ctx_q dp_ctx_in_q;
+ struct dplane_ctx_list_head dp_ctx_in_list;
/* Queue of completed contexts outbound from the provider back
* towards the dataplane module.
*/
- struct dplane_ctx_q dp_ctx_out_q;
+ struct dplane_ctx_list_head dp_ctx_out_list;
/* Embedded list linkage for provider objects */
- TAILQ_ENTRY(zebra_dplane_provider) dp_prov_link;
+ struct dplane_prov_list_item dp_link;
};
+/* Declare list of providers/plugins */
+DECLARE_DLIST(dplane_prov_list, struct zebra_dplane_provider, dp_link);
+
/* Declare types for list of zns info objects */
PREDECL_DLIST(zns_info_list);
@@ -496,7 +504,7 @@ static struct zebra_dplane_globals {
pthread_mutex_t dg_mutex;
/* Results callback registered by zebra 'core' */
- int (*dg_results_cb)(struct dplane_ctx_q *ctxlist);
+ int (*dg_results_cb)(struct dplane_ctx_list_head *ctxlist);
/* Sentinel for beginning of shutdown */
volatile bool dg_is_shutdown;
@@ -505,10 +513,10 @@ static struct zebra_dplane_globals {
volatile bool dg_run;
/* Update context queue inbound to the dataplane */
- TAILQ_HEAD(zdg_ctx_q, zebra_dplane_ctx) dg_update_ctx_q;
+ struct dplane_ctx_list_head dg_update_list;
/* Ordered list of providers */
- TAILQ_HEAD(zdg_prov_q, zebra_dplane_provider) dg_providers_q;
+ struct dplane_prov_list_head dg_providers;
/* List of info about each zns */
struct zns_info_list_head dg_zns_list;
@@ -668,7 +676,7 @@ void dplane_enable_sys_route_notifs(void)
*/
static void dplane_ctx_free_internal(struct zebra_dplane_ctx *ctx)
{
- struct dplane_intf_extra *if_extra, *if_tmp;
+ struct dplane_intf_extra *if_extra;
/*
* Some internal allocations may need to be freed, depending on
@@ -713,12 +721,9 @@ static void dplane_ctx_free_internal(struct zebra_dplane_ctx *ctx)
}
/* Optional extra interface info */
- TAILQ_FOREACH_SAFE(if_extra, &ctx->u.rinfo.intf_extra_q,
- link, if_tmp) {
- TAILQ_REMOVE(&ctx->u.rinfo.intf_extra_q, if_extra,
- link);
+ while ((if_extra = dplane_intf_extra_list_pop(
+ &ctx->u.rinfo.intf_extra_list)))
XFREE(MTYPE_DP_INTF, if_extra);
- }
break;
@@ -885,39 +890,40 @@ void dplane_ctx_fini(struct zebra_dplane_ctx **pctx)
dplane_ctx_free(pctx);
}
+/* Init a list of contexts */
+void dplane_ctx_q_init(struct dplane_ctx_list_head *q)
+{
+ dplane_ctx_list_init(q);
+}
+
/* Enqueue a context block */
-void dplane_ctx_enqueue_tail(struct dplane_ctx_q *q,
+void dplane_ctx_enqueue_tail(struct dplane_ctx_list_head *list,
const struct zebra_dplane_ctx *ctx)
{
- TAILQ_INSERT_TAIL(q, (struct zebra_dplane_ctx *)ctx, zd_q_entries);
+ dplane_ctx_list_add_tail(list, (struct zebra_dplane_ctx *)ctx);
}
/* Append a list of context blocks to another list */
-void dplane_ctx_list_append(struct dplane_ctx_q *to_list,
- struct dplane_ctx_q *from_list)
+void dplane_ctx_list_append(struct dplane_ctx_list_head *to_list,
+ struct dplane_ctx_list_head *from_list)
{
- if (TAILQ_FIRST(from_list)) {
- TAILQ_CONCAT(to_list, from_list, zd_q_entries);
+ struct zebra_dplane_ctx *ctx;
- /* And clear 'from' list */
- TAILQ_INIT(from_list);
- }
+ while ((ctx = dplane_ctx_list_pop(from_list)) != NULL)
+ dplane_ctx_list_add_tail(to_list, ctx);
}
-struct zebra_dplane_ctx *dplane_ctx_get_head(struct dplane_ctx_q *q)
+struct zebra_dplane_ctx *dplane_ctx_get_head(struct dplane_ctx_list_head *q)
{
- struct zebra_dplane_ctx *ctx = TAILQ_FIRST(q);
+ struct zebra_dplane_ctx *ctx = dplane_ctx_list_first(q);
return ctx;
}
/* Dequeue a context block from the head of a list */
-struct zebra_dplane_ctx *dplane_ctx_dequeue(struct dplane_ctx_q *q)
+struct zebra_dplane_ctx *dplane_ctx_dequeue(struct dplane_ctx_list_head *q)
{
- struct zebra_dplane_ctx *ctx = TAILQ_FIRST(q);
-
- if (ctx)
- TAILQ_REMOVE(q, ctx, zd_q_entries);
+ struct zebra_dplane_ctx *ctx = dplane_ctx_list_pop(q);
return ctx;
}
@@ -2597,14 +2603,16 @@ void dplane_ctx_rule_set_dp_flow_ptr(struct zebra_dplane_ctx *ctx,
const struct dplane_intf_extra *
dplane_ctx_get_intf_extra(const struct zebra_dplane_ctx *ctx)
{
- return TAILQ_FIRST(&ctx->u.rinfo.intf_extra_q);
+ return dplane_intf_extra_list_const_first(
+ &ctx->u.rinfo.intf_extra_list);
}
const struct dplane_intf_extra *
dplane_ctx_intf_extra_next(const struct zebra_dplane_ctx *ctx,
const struct dplane_intf_extra *ptr)
{
- return TAILQ_NEXT(ptr, link);
+ return dplane_intf_extra_list_const_next(&ctx->u.rinfo.intf_extra_list,
+ ptr);
}
vrf_id_t dplane_intf_extra_get_vrfid(const struct dplane_intf_extra *ptr)
@@ -2793,7 +2801,7 @@ int dplane_ctx_route_init_basic(struct zebra_dplane_ctx *ctx,
if (!ctx || !re)
return ret;
- TAILQ_INIT(&ctx->u.rinfo.intf_extra_q);
+ dplane_intf_extra_list_init(&ctx->u.rinfo.intf_extra_list);
ctx->zd_op = op;
ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS;
@@ -2896,8 +2904,9 @@ int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op,
if_extra->flags = ifp->flags;
if_extra->status = ifp->status;
- TAILQ_INSERT_TAIL(&ctx->u.rinfo.intf_extra_q,
- if_extra, link);
+ dplane_intf_extra_list_add_tail(
+ &ctx->u.rinfo.intf_extra_list,
+ if_extra);
}
}
@@ -3622,8 +3631,7 @@ static int dplane_update_enqueue(struct zebra_dplane_ctx *ctx)
/* Enqueue for processing by the dataplane pthread */
DPLANE_LOCK();
{
- TAILQ_INSERT_TAIL(&zdplane_info.dg_update_ctx_q, ctx,
- zd_q_entries);
+ dplane_ctx_list_add_tail(&zdplane_info.dg_update_list, ctx);
}
DPLANE_UNLOCK();
@@ -5520,7 +5528,7 @@ int dplane_show_provs_helper(struct vty *vty, bool detailed)
vty_out(vty, "Zebra dataplane providers:\n");
DPLANE_LOCK();
- prov = TAILQ_FIRST(&zdplane_info.dg_providers_q);
+ prov = dplane_prov_list_first(&zdplane_info.dg_providers);
DPLANE_UNLOCK();
/* Show counters, useful info from each registered provider */
@@ -5543,9 +5551,7 @@ int dplane_show_provs_helper(struct vty *vty, bool detailed)
prov->dp_name, prov->dp_id, in, in_q, in_max,
out, out_q, out_max);
- DPLANE_LOCK();
- prov = TAILQ_NEXT(prov, dp_prov_link);
- DPLANE_UNLOCK();
+ prov = dplane_prov_list_next(&zdplane_info.dg_providers, prov);
}
return CMD_SUCCESS;
@@ -5595,8 +5601,8 @@ int dplane_provider_register(const char *name,
p = XCALLOC(MTYPE_DP_PROV, sizeof(struct zebra_dplane_provider));
pthread_mutex_init(&(p->dp_mutex), NULL);
- TAILQ_INIT(&(p->dp_ctx_in_q));
- TAILQ_INIT(&(p->dp_ctx_out_q));
+ dplane_ctx_list_init(&p->dp_ctx_in_list);
+ dplane_ctx_list_init(&p->dp_ctx_out_list);
p->dp_flags = flags;
p->dp_priority = prio;
@@ -5617,16 +5623,15 @@ int dplane_provider_register(const char *name,
"provider-%u", p->dp_id);
/* Insert into list ordered by priority */
- TAILQ_FOREACH(last, &zdplane_info.dg_providers_q, dp_prov_link) {
+ frr_each (dplane_prov_list, &zdplane_info.dg_providers, last) {
if (last->dp_priority > p->dp_priority)
break;
}
if (last)
- TAILQ_INSERT_BEFORE(last, p, dp_prov_link);
+ dplane_prov_list_add_after(&zdplane_info.dg_providers, last, p);
else
- TAILQ_INSERT_TAIL(&zdplane_info.dg_providers_q, p,
- dp_prov_link);
+ dplane_prov_list_add_tail(&zdplane_info.dg_providers, p);
/* And unlock */
DPLANE_UNLOCK();
@@ -5688,10 +5693,8 @@ struct zebra_dplane_ctx *dplane_provider_dequeue_in_ctx(
dplane_provider_lock(prov);
- ctx = TAILQ_FIRST(&(prov->dp_ctx_in_q));
+ ctx = dplane_ctx_list_pop(&(prov->dp_ctx_in_list));
if (ctx) {
- TAILQ_REMOVE(&(prov->dp_ctx_in_q), ctx, zd_q_entries);
-
atomic_fetch_sub_explicit(&prov->dp_in_queued, 1,
memory_order_relaxed);
}
@@ -5705,7 +5708,7 @@ struct zebra_dplane_ctx *dplane_provider_dequeue_in_ctx(
* Dequeue work to a list, return count
*/
int dplane_provider_dequeue_in_list(struct zebra_dplane_provider *prov,
- struct dplane_ctx_q *listp)
+ struct dplane_ctx_list_head *listp)
{
int limit, ret;
struct zebra_dplane_ctx *ctx;
@@ -5715,14 +5718,11 @@ int dplane_provider_dequeue_in_list(struct zebra_dplane_provider *prov,
dplane_provider_lock(prov);
for (ret = 0; ret < limit; ret++) {
- ctx = TAILQ_FIRST(&(prov->dp_ctx_in_q));
- if (ctx) {
- TAILQ_REMOVE(&(prov->dp_ctx_in_q), ctx, zd_q_entries);
-
- TAILQ_INSERT_TAIL(listp, ctx, zd_q_entries);
- } else {
+ ctx = dplane_ctx_list_pop(&(prov->dp_ctx_in_list));
+ if (ctx)
+ dplane_ctx_list_add_tail(listp, ctx);
+ else
break;
- }
}
if (ret > 0)
@@ -5750,8 +5750,7 @@ void dplane_provider_enqueue_out_ctx(struct zebra_dplane_provider *prov,
dplane_provider_lock(prov);
- TAILQ_INSERT_TAIL(&(prov->dp_ctx_out_q), ctx,
- zd_q_entries);
+ dplane_ctx_list_add_tail(&(prov->dp_ctx_out_list), ctx);
/* Maintain out-queue counters */
atomic_fetch_add_explicit(&(prov->dp_out_queued), 1,
@@ -5921,12 +5920,12 @@ int dplane_provider_work_ready(void)
*/
void dplane_provider_enqueue_to_zebra(struct zebra_dplane_ctx *ctx)
{
- struct dplane_ctx_q temp_list;
+ struct dplane_ctx_list_head temp_list;
/* Zebra's api takes a list, so we need to use a temporary list */
- TAILQ_INIT(&temp_list);
+ dplane_ctx_list_init(&temp_list);
- TAILQ_INSERT_TAIL(&temp_list, ctx, zd_q_entries);
+ dplane_ctx_list_add_tail(&temp_list, ctx);
(zdplane_info.dg_results_cb)(&temp_list);
}
@@ -6321,11 +6320,11 @@ void dplane_rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p,
*/
static int kernel_dplane_process_func(struct zebra_dplane_provider *prov)
{
- struct zebra_dplane_ctx *ctx, *tctx;
- struct dplane_ctx_q work_list;
+ struct zebra_dplane_ctx *ctx;
+ struct dplane_ctx_list_head work_list;
int counter, limit;
- TAILQ_INIT(&work_list);
+ dplane_ctx_list_init(&work_list);
limit = dplane_provider_get_work_limit(prov);
@@ -6351,15 +6350,14 @@ static int kernel_dplane_process_func(struct zebra_dplane_provider *prov)
== DPLANE_OP_IPSET_ENTRY_DELETE))
kernel_dplane_process_ipset_entry(prov, ctx);
else
- TAILQ_INSERT_TAIL(&work_list, ctx, zd_q_entries);
+ dplane_ctx_list_add_tail(&work_list, ctx);
}
kernel_update_multi(&work_list);
- TAILQ_FOREACH_SAFE (ctx, &work_list, zd_q_entries, tctx) {
+ while ((ctx = dplane_ctx_list_pop(&work_list)) != NULL) {
kernel_dplane_handle_result(ctx);
- TAILQ_REMOVE(&work_list, ctx, zd_q_entries);
dplane_provider_enqueue_out_ctx(prov, ctx);
}
@@ -6486,10 +6484,10 @@ static void dplane_provider_init(void)
int dplane_clean_ctx_queue(bool (*context_cb)(struct zebra_dplane_ctx *ctx,
void *arg), void *val)
{
- struct zebra_dplane_ctx *ctx, *temp;
- struct dplane_ctx_q work_list;
+ struct zebra_dplane_ctx *ctx;
+ struct dplane_ctx_list_head work_list;
- TAILQ_INIT(&work_list);
+ dplane_ctx_list_init(&work_list);
if (context_cb == NULL)
return AOK;
@@ -6497,12 +6495,10 @@ int dplane_clean_ctx_queue(bool (*context_cb)(struct zebra_dplane_ctx *ctx,
/* Walk the pending context queue under the dplane lock. */
DPLANE_LOCK();
- TAILQ_FOREACH_SAFE(ctx, &zdplane_info.dg_update_ctx_q, zd_q_entries,
- temp) {
+ frr_each_safe (dplane_ctx_list, &zdplane_info.dg_update_list, ctx) {
if (context_cb(ctx, val)) {
- TAILQ_REMOVE(&zdplane_info.dg_update_ctx_q, ctx,
- zd_q_entries);
- TAILQ_INSERT_TAIL(&work_list, ctx, zd_q_entries);
+ dplane_ctx_list_del(&zdplane_info.dg_update_list, ctx);
+ dplane_ctx_list_add_tail(&work_list, ctx);
}
}
@@ -6511,10 +6507,8 @@ int dplane_clean_ctx_queue(bool (*context_cb)(struct zebra_dplane_ctx *ctx,
/* Now free any contexts selected by the caller, without holding
* the lock.
*/
- TAILQ_FOREACH_SAFE(ctx, &work_list, zd_q_entries, temp) {
- TAILQ_REMOVE(&work_list, ctx, zd_q_entries);
+ while ((ctx = dplane_ctx_list_pop(&work_list)) != NULL)
dplane_ctx_fini(&ctx);
- }
return AOK;
}
@@ -6552,7 +6546,7 @@ void zebra_dplane_pre_finish(void)
zdplane_info.dg_is_shutdown = true;
/* Notify provider(s) of pending shutdown. */
- TAILQ_FOREACH(prov, &zdplane_info.dg_providers_q, dp_prov_link) {
+ frr_each (dplane_prov_list, &zdplane_info.dg_providers, prov) {
if (prov->dp_fini == NULL)
continue;
@@ -6575,8 +6569,8 @@ static bool dplane_work_pending(void)
*/
DPLANE_LOCK();
{
- ctx = TAILQ_FIRST(&zdplane_info.dg_update_ctx_q);
- prov = TAILQ_FIRST(&zdplane_info.dg_providers_q);
+ ctx = dplane_ctx_list_first(&zdplane_info.dg_update_list);
+ prov = dplane_prov_list_first(&zdplane_info.dg_providers);
}
DPLANE_UNLOCK();
@@ -6587,18 +6581,16 @@ static bool dplane_work_pending(void)
dplane_provider_lock(prov);
- ctx = TAILQ_FIRST(&(prov->dp_ctx_in_q));
+ ctx = dplane_ctx_list_first(&(prov->dp_ctx_in_list));
if (ctx == NULL)
- ctx = TAILQ_FIRST(&(prov->dp_ctx_out_q));
+ ctx = dplane_ctx_list_first(&(prov->dp_ctx_out_list));
dplane_provider_unlock(prov);
if (ctx != NULL)
break;
- DPLANE_LOCK();
- prov = TAILQ_NEXT(prov, dp_prov_link);
- DPLANE_UNLOCK();
+ prov = dplane_prov_list_next(&zdplane_info.dg_providers, prov);
}
if (ctx != NULL)
@@ -6683,10 +6675,10 @@ void zebra_dplane_finish(void)
*/
static void dplane_thread_loop(struct thread *event)
{
- struct dplane_ctx_q work_list;
- struct dplane_ctx_q error_list;
+ struct dplane_ctx_list_head work_list;
+ struct dplane_ctx_list_head error_list;
struct zebra_dplane_provider *prov;
- struct zebra_dplane_ctx *ctx, *tctx;
+ struct zebra_dplane_ctx *ctx;
int limit, counter, error_counter;
uint64_t curr, high;
bool reschedule = false;
@@ -6695,8 +6687,9 @@ static void dplane_thread_loop(struct thread *event)
limit = zdplane_info.dg_updates_per_cycle;
/* Init temporary lists used to move contexts among providers */
- TAILQ_INIT(&work_list);
- TAILQ_INIT(&error_list);
+ dplane_ctx_list_init(&work_list);
+ dplane_ctx_list_init(&error_list);
+
error_counter = 0;
/* Check for zebra shutdown */
@@ -6709,18 +6702,15 @@ static void dplane_thread_loop(struct thread *event)
DPLANE_LOCK();
/* Locate initial registered provider */
- prov = TAILQ_FIRST(&zdplane_info.dg_providers_q);
+ prov = dplane_prov_list_first(&zdplane_info.dg_providers);
/* Move new work from incoming list to temp list */
for (counter = 0; counter < limit; counter++) {
- ctx = TAILQ_FIRST(&zdplane_info.dg_update_ctx_q);
+ ctx = dplane_ctx_list_pop(&zdplane_info.dg_update_list);
if (ctx) {
- TAILQ_REMOVE(&zdplane_info.dg_update_ctx_q, ctx,
- zd_q_entries);
-
ctx->zd_provider = prov->dp_id;
- TAILQ_INSERT_TAIL(&work_list, ctx, zd_q_entries);
+ dplane_ctx_list_add_tail(&work_list, ctx);
} else {
break;
}
@@ -6750,7 +6740,7 @@ static void dplane_thread_loop(struct thread *event)
/* Capture current provider id in each context; check for
* error status.
*/
- TAILQ_FOREACH_SAFE(ctx, &work_list, zd_q_entries, tctx) {
+ frr_each_safe (dplane_ctx_list, &work_list, ctx) {
if (dplane_ctx_get_status(ctx) ==
ZEBRA_DPLANE_REQUEST_SUCCESS) {
ctx->zd_provider = prov->dp_id;
@@ -6764,9 +6754,8 @@ static void dplane_thread_loop(struct thread *event)
/* Move to error list; will be returned
* zebra main.
*/
- TAILQ_REMOVE(&work_list, ctx, zd_q_entries);
- TAILQ_INSERT_TAIL(&error_list,
- ctx, zd_q_entries);
+ dplane_ctx_list_del(&work_list, ctx);
+ dplane_ctx_list_add_tail(&error_list, ctx);
error_counter++;
}
}
@@ -6774,9 +6763,8 @@ static void dplane_thread_loop(struct thread *event)
/* Enqueue new work to the provider */
dplane_provider_lock(prov);
- if (TAILQ_FIRST(&work_list))
- TAILQ_CONCAT(&(prov->dp_ctx_in_q), &work_list,
- zd_q_entries);
+ while ((ctx = dplane_ctx_list_pop(&work_list)) != NULL)
+ dplane_ctx_list_add_tail(&(prov->dp_ctx_in_list), ctx);
atomic_fetch_add_explicit(&prov->dp_in_counter, counter,
memory_order_relaxed);
@@ -6795,7 +6783,7 @@ static void dplane_thread_loop(struct thread *event)
/* Reset the temp list (though the 'concat' may have done this
* already), and the counter
*/
- TAILQ_INIT(&work_list);
+ dplane_ctx_list_init(&work_list);
counter = 0;
/* Call into the provider code. Note that this is
@@ -6812,13 +6800,9 @@ static void dplane_thread_loop(struct thread *event)
dplane_provider_lock(prov);
while (counter < limit) {
- ctx = TAILQ_FIRST(&(prov->dp_ctx_out_q));
+ ctx = dplane_ctx_list_pop(&(prov->dp_ctx_out_list));
if (ctx) {
- TAILQ_REMOVE(&(prov->dp_ctx_out_q), ctx,
- zd_q_entries);
-
- TAILQ_INSERT_TAIL(&work_list,
- ctx, zd_q_entries);
+ dplane_ctx_list_add_tail(&work_list, ctx);
counter++;
} else
break;
@@ -6834,9 +6818,7 @@ static void dplane_thread_loop(struct thread *event)
counter, dplane_provider_get_name(prov));
/* Locate next provider */
- DPLANE_LOCK();
- prov = TAILQ_NEXT(prov, dp_prov_link);
- DPLANE_UNLOCK();
+ prov = dplane_prov_list_next(&zdplane_info.dg_providers, prov);
}
/*
@@ -6861,12 +6843,12 @@ static void dplane_thread_loop(struct thread *event)
/* Call through to zebra main */
(zdplane_info.dg_results_cb)(&error_list);
- TAILQ_INIT(&error_list);
+ dplane_ctx_list_init(&error_list);
/* Call through to zebra main */
(zdplane_info.dg_results_cb)(&work_list);
- TAILQ_INIT(&work_list);
+ dplane_ctx_list_init(&work_list);
}
/*
@@ -6899,7 +6881,7 @@ void zebra_dplane_shutdown(void)
* Note that this call is in the main pthread, so providers must
* be prepared for that.
*/
- TAILQ_FOREACH(dp, &zdplane_info.dg_providers_q, dp_prov_link) {
+ frr_each (dplane_prov_list, &zdplane_info.dg_providers, dp) {
if (dp->dp_fini == NULL)
continue;
@@ -6920,8 +6902,9 @@ static void zebra_dplane_init_internal(void)
pthread_mutex_init(&zdplane_info.dg_mutex, NULL);
- TAILQ_INIT(&zdplane_info.dg_update_ctx_q);
- TAILQ_INIT(&zdplane_info.dg_providers_q);
+ dplane_prov_list_init(&zdplane_info.dg_providers);
+
+ dplane_ctx_list_init(&zdplane_info.dg_update_list);
zns_info_list_init(&zdplane_info.dg_zns_list);
zdplane_info.dg_updates_per_cycle = DPLANE_DEFAULT_NEW_WORK;
@@ -6970,7 +6953,7 @@ void zebra_dplane_start(void)
/* Call start callbacks for registered providers */
DPLANE_LOCK();
- prov = TAILQ_FIRST(&zdplane_info.dg_providers_q);
+ prov = dplane_prov_list_first(&zdplane_info.dg_providers);
DPLANE_UNLOCK();
while (prov) {
@@ -6979,9 +6962,7 @@ void zebra_dplane_start(void)
(prov->dp_start)(prov);
/* Locate next provider */
- DPLANE_LOCK();
- prov = TAILQ_NEXT(prov, dp_prov_link);
- DPLANE_UNLOCK();
+ prov = dplane_prov_list_next(&zdplane_info.dg_providers, prov);
}
frr_pthread_run(zdplane_info.dg_pthread, NULL);
@@ -6990,7 +6971,7 @@ void zebra_dplane_start(void)
/*
* Initialize the dataplane module at startup; called by zebra rib_init()
*/
-void zebra_dplane_init(int (*results_fp)(struct dplane_ctx_q *))
+void zebra_dplane_init(int (*results_fp)(struct dplane_ctx_list_head *))
{
zebra_dplane_init_internal();
zdplane_info.dg_results_cb = results_fp;
diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h
index 51f6f3d897..ae13243a16 100644
--- a/zebra/zebra_dplane.h
+++ b/zebra/zebra_dplane.h
@@ -24,7 +24,6 @@
#include "lib/prefix.h"
#include "lib/nexthop.h"
#include "lib/nexthop_group.h"
-#include "lib/queue.h"
#include "lib/vlan.h"
#include "zebra/zebra_ns.h"
#include "zebra/rib.h"
@@ -265,14 +264,15 @@ void dplane_enable_sys_route_notifs(void);
* they cannot share existing global data structures safely.
*/
-/* Define a tailq list type for context blocks. The list is exposed/public,
+/* Define a list type for context blocks. The list is exposed/public,
* but the internal linkage in the context struct is private, so there
* are accessor apis that support enqueue and dequeue.
*/
-TAILQ_HEAD(dplane_ctx_q, zebra_dplane_ctx);
+
+PREDECL_DLIST(dplane_ctx_list);
/* Declare a type for (optional) extended interface info objects. */
-TAILQ_HEAD(dplane_intf_extra_q, dplane_intf_extra);
+PREDECL_DLIST(dplane_intf_extra_list);
/* Allocate a context object */
struct zebra_dplane_ctx *dplane_ctx_alloc(void);
@@ -300,18 +300,21 @@ void dplane_ctx_fini(struct zebra_dplane_ctx **pctx);
/* Enqueue a context block to caller's tailq. This exists so that the
* context struct can remain opaque.
*/
-void dplane_ctx_enqueue_tail(struct dplane_ctx_q *q,
+void dplane_ctx_enqueue_tail(struct dplane_ctx_list_head *q,
const struct zebra_dplane_ctx *ctx);
/* Append a list of context blocks to another list - again, just keeping
* the context struct opaque.
*/
-void dplane_ctx_list_append(struct dplane_ctx_q *to_list,
- struct dplane_ctx_q *from_list);
+void dplane_ctx_list_append(struct dplane_ctx_list_head *to_list,
+ struct dplane_ctx_list_head *from_list);
/* Dequeue a context block from the head of caller's tailq */
-struct zebra_dplane_ctx *dplane_ctx_dequeue(struct dplane_ctx_q *q);
-struct zebra_dplane_ctx *dplane_ctx_get_head(struct dplane_ctx_q *q);
+struct zebra_dplane_ctx *dplane_ctx_dequeue(struct dplane_ctx_list_head *q);
+struct zebra_dplane_ctx *dplane_ctx_get_head(struct dplane_ctx_list_head *q);
+
+/* Init a list of contexts */
+void dplane_ctx_q_init(struct dplane_ctx_list_head *q);
/*
* Accessors for information from the context object
@@ -1036,7 +1039,7 @@ struct zebra_dplane_ctx *dplane_provider_dequeue_in_ctx(
/* Dequeue work to a list, maintain counter and locking, return count */
int dplane_provider_dequeue_in_list(struct zebra_dplane_provider *prov,
- struct dplane_ctx_q *listp);
+ struct dplane_ctx_list_head *listp);
/* Current completed work queue length */
uint32_t dplane_provider_out_ctx_queue_len(struct zebra_dplane_provider *prov);
@@ -1061,7 +1064,7 @@ void dplane_enable_intf_extra_info(void);
* so the expectation is that the contexts are queued for the zebra
* main pthread.
*/
-void zebra_dplane_init(int (*) (struct dplane_ctx_q *));
+void zebra_dplane_init(int (*)(struct dplane_ctx_list_head *));
/*
* Start the dataplane pthread. This step needs to be run later than the
diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c
index 286cc0292d..758fed7280 100644
--- a/zebra/zebra_nhg.c
+++ b/zebra/zebra_nhg.c
@@ -1820,7 +1820,7 @@ static struct nexthop *nexthop_set_resolved(afi_t afi,
/* Copy labels of the resolved route and the parent resolving to it */
if (policy) {
- int i = 0;
+ int label_num = 0;
/*
* Don't push the first SID if the corresponding action in the
@@ -1828,10 +1828,11 @@ static struct nexthop *nexthop_set_resolved(afi_t afi,
*/
if (!newhop->nh_label || !newhop->nh_label->num_labels
|| newhop->nh_label->label[0] == MPLS_LABEL_IMPLICIT_NULL)
- i = 1;
+ label_num = 1;
- for (; i < policy->segment_list.label_num; i++)
- labels[num_labels++] = policy->segment_list.labels[i];
+ for (; label_num < policy->segment_list.label_num; label_num++)
+ labels[num_labels++] =
+ policy->segment_list.labels[label_num];
label_type = policy->segment_list.type;
} else if (newhop->nh_label) {
for (i = 0; i < newhop->nh_label->num_labels; i++) {
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 81910f68b7..2f71a10d3d 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -72,7 +72,7 @@ DEFINE_MTYPE_STATIC(ZEBRA, WQ_WRAPPER, "WQ wrapper");
*/
static pthread_mutex_t dplane_mutex;
static struct thread *t_dplane;
-static struct dplane_ctx_q rib_dplane_q;
+static struct dplane_ctx_list_head rib_dplane_q;
DEFINE_HOOK(rib_update, (struct route_node * rn, const char *reason),
(rn, reason));
@@ -1788,9 +1788,12 @@ no_nexthops:
ctxnhg->nexthop != NULL ? "" : " (empty)");
/* Set the flag about the dedicated fib list */
- SET_FLAG(re->status, ROUTE_ENTRY_USE_FIB_NHG);
- if (ctxnhg->nexthop)
- copy_nexthops(&(re->fib_ng.nexthop), ctxnhg->nexthop, NULL);
+ if (zrouter.asic_notification_nexthop_control) {
+ SET_FLAG(re->status, ROUTE_ENTRY_USE_FIB_NHG);
+ if (ctxnhg->nexthop)
+ copy_nexthops(&(re->fib_ng.nexthop), ctxnhg->nexthop,
+ NULL);
+ }
check_backups:
@@ -4337,25 +4340,6 @@ void rib_update_table(struct route_table *table, enum rib_update_event event,
}
}
-static void rib_update_handle_vrf(vrf_id_t vrf_id, enum rib_update_event event,
- int rtype)
-{
- struct route_table *table;
-
- if (IS_ZEBRA_DEBUG_EVENT)
- zlog_debug("%s: Handling VRF %s event %s", __func__,
- vrf_id_to_name(vrf_id), rib_update_event2str(event));
-
- /* Process routes of interested address-families. */
- table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id);
- if (table)
- rib_update_table(table, event, rtype);
-
- table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST, vrf_id);
- if (table)
- rib_update_table(table, event, rtype);
-}
-
static void rib_update_handle_vrf_all(enum rib_update_event event, int rtype)
{
struct zebra_router_table *zrt;
@@ -4371,7 +4355,6 @@ static void rib_update_handle_vrf_all(enum rib_update_event event, int rtype)
struct rib_update_ctx {
enum rib_update_event event;
- bool vrf_all;
vrf_id_t vrf_id;
};
@@ -4399,10 +4382,7 @@ static void rib_update_handler(struct thread *thread)
ctx = THREAD_ARG(thread);
- if (ctx->vrf_all)
- rib_update_handle_vrf_all(ctx->event, ZEBRA_ROUTE_ALL);
- else
- rib_update_handle_vrf(ctx->vrf_id, ctx->event, ZEBRA_ROUTE_ALL);
+ rib_update_handle_vrf_all(ctx->event, ZEBRA_ROUTE_ALL);
rib_update_ctx_fini(&ctx);
}
@@ -4422,7 +4402,6 @@ void rib_update(enum rib_update_event event)
return;
ctx = rib_update_ctx_init(0, event);
- ctx->vrf_all = true;
thread_add_event(zrouter.master, rib_update_handler, ctx, 0,
&t_rib_update_threads[event]);
@@ -4613,13 +4592,13 @@ static void handle_pw_result(struct zebra_dplane_ctx *ctx)
static void rib_process_dplane_results(struct thread *thread)
{
struct zebra_dplane_ctx *ctx;
- struct dplane_ctx_q ctxlist;
+ struct dplane_ctx_list_head ctxlist;
bool shut_p = false;
/* Dequeue a list of completed updates with one lock/unlock cycle */
do {
- TAILQ_INIT(&ctxlist);
+ dplane_ctx_q_init(&ctxlist);
/* Take lock controlling queue of results */
frr_with_mutex (&dplane_mutex) {
@@ -4788,7 +4767,7 @@ static void rib_process_dplane_results(struct thread *thread)
* the dataplane pthread. We enqueue the results here for processing by
* the main thread later.
*/
-static int rib_dplane_results(struct dplane_ctx_q *ctxlist)
+static int rib_dplane_results(struct dplane_ctx_list_head *ctxlist)
{
/* Take lock controlling queue of results */
frr_with_mutex (&dplane_mutex) {
@@ -4833,7 +4812,7 @@ void rib_init(void)
/* Init dataplane, and register for results */
pthread_mutex_init(&dplane_mutex, NULL);
- TAILQ_INIT(&rib_dplane_q);
+ dplane_ctx_q_init(&rib_dplane_q);
zebra_dplane_init(rib_dplane_results);
}
diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c
index 599c679864..e24556122b 100644
--- a/zebra/zebra_rnh.c
+++ b/zebra/zebra_rnh.c
@@ -1270,73 +1270,291 @@ failure:
return -1;
}
-static void print_nh(struct nexthop *nexthop, struct vty *vty,
- json_object *json)
+
+/*
+ * Render a nexthop into a json object; the caller allocates and owns
+ * the json object memory.
+ */
+void show_nexthop_json_helper(json_object *json_nexthop,
+ const struct nexthop *nexthop,
+ const struct route_entry *re)
{
- struct zebra_ns *zns = zebra_ns_lookup(nexthop->vrf_id);
+ json_object *json_labels = NULL;
+ json_object *json_backups = NULL;
+ json_object *json_seg6local = NULL;
+ json_object *json_seg6 = NULL;
+ int i;
+
+ json_object_int_add(json_nexthop, "flags", nexthop->flags);
+
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE))
+ json_object_boolean_true_add(json_nexthop, "duplicate");
+
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))
+ json_object_boolean_true_add(json_nexthop, "fib");
switch (nexthop->type) {
case NEXTHOP_TYPE_IPV4:
case NEXTHOP_TYPE_IPV4_IFINDEX:
- if (json) {
- json_object_string_addf(json, "ip", "%pI4",
- &nexthop->gate.ipv4);
- if (nexthop->ifindex)
- json_object_string_add(
- json, "interface",
- ifindex2ifname_per_ns(
- zns, nexthop->ifindex));
- } else {
- vty_out(vty, " via %pI4", &nexthop->gate.ipv4);
- if (nexthop->ifindex)
- vty_out(vty, ", %s",
- ifindex2ifname_per_ns(
- zns, nexthop->ifindex));
+ json_object_string_addf(json_nexthop, "ip", "%pI4",
+ &nexthop->gate.ipv4);
+ json_object_string_add(json_nexthop, "afi", "ipv4");
+
+ if (nexthop->ifindex) {
+ json_object_int_add(json_nexthop, "interfaceIndex",
+ nexthop->ifindex);
+ json_object_string_add(json_nexthop, "interfaceName",
+ ifindex2ifname(nexthop->ifindex,
+ nexthop->vrf_id));
}
break;
case NEXTHOP_TYPE_IPV6:
case NEXTHOP_TYPE_IPV6_IFINDEX:
- if (json) {
- json_object_string_addf(json, "ip", "%pI6",
- &nexthop->gate.ipv6);
- if (nexthop->ifindex)
- json_object_string_add(
- json, "interface",
- ifindex2ifname_per_ns(
- zns, nexthop->ifindex));
- } else {
- vty_out(vty, " %pI6", &nexthop->gate.ipv6);
- if (nexthop->ifindex)
- vty_out(vty, ", via %s",
- ifindex2ifname_per_ns(
- zns, nexthop->ifindex));
+ json_object_string_addf(json_nexthop, "ip", "%pI6",
+ &nexthop->gate.ipv6);
+ json_object_string_add(json_nexthop, "afi", "ipv6");
+
+ if (nexthop->ifindex) {
+ json_object_int_add(json_nexthop, "interfaceIndex",
+ nexthop->ifindex);
+ json_object_string_add(json_nexthop, "interfaceName",
+ ifindex2ifname(nexthop->ifindex,
+ nexthop->vrf_id));
}
break;
+
case NEXTHOP_TYPE_IFINDEX:
- if (json) {
- json_object_string_add(
- json, "interface",
- ifindex2ifname_per_ns(zns, nexthop->ifindex));
- json_object_boolean_true_add(json, "directlyConnected");
- } else {
- vty_out(vty, " is directly connected, %s",
- ifindex2ifname_per_ns(zns, nexthop->ifindex));
+ json_object_boolean_true_add(json_nexthop, "directlyConnected");
+ json_object_int_add(json_nexthop, "interfaceIndex",
+ nexthop->ifindex);
+ json_object_string_add(
+ json_nexthop, "interfaceName",
+ ifindex2ifname(nexthop->ifindex, nexthop->vrf_id));
+ break;
+ case NEXTHOP_TYPE_BLACKHOLE:
+ json_object_boolean_true_add(json_nexthop, "unreachable");
+ switch (nexthop->bh_type) {
+ case BLACKHOLE_REJECT:
+ json_object_boolean_true_add(json_nexthop, "reject");
+ break;
+ case BLACKHOLE_ADMINPROHIB:
+ json_object_boolean_true_add(json_nexthop,
+ "adminProhibited");
+ break;
+ case BLACKHOLE_NULL:
+ json_object_boolean_true_add(json_nexthop, "blackhole");
+ break;
+ case BLACKHOLE_UNSPEC:
+ break;
+ }
+ break;
+ }
+
+ /* This nexthop is a resolver for the parent nexthop.
+ * Set resolver flag for better clarity and delimiter
+ * in flat list of nexthops in json.
+ */
+ if (nexthop->rparent)
+ json_object_boolean_true_add(json_nexthop, "resolver");
+
+ if ((re == NULL || (nexthop->vrf_id != re->vrf_id)))
+ json_object_string_add(json_nexthop, "vrf",
+ vrf_id_to_name(nexthop->vrf_id));
+
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE))
+ json_object_boolean_true_add(json_nexthop, "duplicate");
+
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
+ json_object_boolean_true_add(json_nexthop, "active");
+
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
+ json_object_boolean_true_add(json_nexthop, "onLink");
+
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_LINKDOWN))
+ json_object_boolean_true_add(json_nexthop, "linkDown");
+
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
+ json_object_boolean_true_add(json_nexthop, "recursive");
+
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) {
+ json_backups = json_object_new_array();
+ for (i = 0; i < nexthop->backup_num; i++) {
+ json_object_array_add(
+ json_backups,
+ json_object_new_int(nexthop->backup_idx[i]));
}
+
+ json_object_object_add(json_nexthop, "backupIndex",
+ json_backups);
+ }
+
+ switch (nexthop->type) {
+ case NEXTHOP_TYPE_IPV4:
+ case NEXTHOP_TYPE_IPV4_IFINDEX:
+ if (nexthop->src.ipv4.s_addr)
+ json_object_string_addf(json_nexthop, "source", "%pI4",
+ &nexthop->src.ipv4);
+ break;
+ case NEXTHOP_TYPE_IPV6:
+ case NEXTHOP_TYPE_IPV6_IFINDEX:
+ if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any))
+ json_object_string_addf(json_nexthop, "source", "%pI6",
+ &nexthop->src.ipv6);
+ break;
+ default:
+ break;
+ }
+
+ if (nexthop->nh_label && nexthop->nh_label->num_labels) {
+ json_labels = json_object_new_array();
+
+ for (int label_index = 0;
+ label_index < nexthop->nh_label->num_labels; label_index++)
+ json_object_array_add(
+ json_labels,
+ json_object_new_int(
+ nexthop->nh_label->label[label_index]));
+
+ json_object_object_add(json_nexthop, "labels", json_labels);
+ }
+
+ if (nexthop->weight)
+ json_object_int_add(json_nexthop, "weight", nexthop->weight);
+
+ if (nexthop->srte_color)
+ json_object_int_add(json_nexthop, "srteColor",
+ nexthop->srte_color);
+
+ if (nexthop->nh_srv6) {
+ json_seg6local = json_object_new_object();
+ json_object_string_add(
+ json_seg6local, "action",
+ seg6local_action2str(
+ nexthop->nh_srv6->seg6local_action));
+ json_object_object_add(json_nexthop, "seg6local",
+ json_seg6local);
+
+ json_seg6 = json_object_new_object();
+ json_object_string_addf(json_seg6, "segs", "%pI6",
+ &nexthop->nh_srv6->seg6_segs);
+ json_object_object_add(json_nexthop, "seg6", json_seg6);
+ }
+}
+
+/*
+ * Helper for nexthop output, used in the 'show ip route' path
+ */
+void show_route_nexthop_helper(struct vty *vty, const struct route_entry *re,
+ const struct nexthop *nexthop)
+{
+ char buf[MPLS_LABEL_STRLEN];
+ int i;
+
+ switch (nexthop->type) {
+ case NEXTHOP_TYPE_IPV4:
+ case NEXTHOP_TYPE_IPV4_IFINDEX:
+ vty_out(vty, " via %pI4", &nexthop->gate.ipv4);
+ if (nexthop->ifindex)
+ vty_out(vty, ", %s",
+ ifindex2ifname(nexthop->ifindex,
+ nexthop->vrf_id));
+ break;
+ case NEXTHOP_TYPE_IPV6:
+ case NEXTHOP_TYPE_IPV6_IFINDEX:
+ vty_out(vty, " via %s",
+ inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
+ sizeof(buf)));
+ if (nexthop->ifindex)
+ vty_out(vty, ", %s",
+ ifindex2ifname(nexthop->ifindex,
+ nexthop->vrf_id));
+ break;
+
+ case NEXTHOP_TYPE_IFINDEX:
+ vty_out(vty, " is directly connected, %s",
+ ifindex2ifname(nexthop->ifindex, nexthop->vrf_id));
break;
case NEXTHOP_TYPE_BLACKHOLE:
- if (json) {
- json_object_string_add(json, "interface", "Null0");
- json_object_boolean_true_add(json, "directlyConnected");
- } else {
- vty_out(vty, " is directly connected, Null0");
+ vty_out(vty, " unreachable");
+ switch (nexthop->bh_type) {
+ case BLACKHOLE_REJECT:
+ vty_out(vty, " (ICMP unreachable)");
+ break;
+ case BLACKHOLE_ADMINPROHIB:
+ vty_out(vty, " (ICMP admin-prohibited)");
+ break;
+ case BLACKHOLE_NULL:
+ vty_out(vty, " (blackhole)");
+ break;
+ case BLACKHOLE_UNSPEC:
+ break;
}
break;
+ }
+
+ if ((re == NULL || (nexthop->vrf_id != re->vrf_id)))
+ vty_out(vty, " (vrf %s)", vrf_id_to_name(nexthop->vrf_id));
+
+ if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
+ vty_out(vty, " inactive");
+
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
+ vty_out(vty, " onlink");
+
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_LINKDOWN))
+ vty_out(vty, " linkdown");
+
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
+ vty_out(vty, " (recursive)");
+
+ switch (nexthop->type) {
+ case NEXTHOP_TYPE_IPV4:
+ case NEXTHOP_TYPE_IPV4_IFINDEX:
+ if (nexthop->src.ipv4.s_addr) {
+ vty_out(vty, ", src %pI4", &nexthop->src.ipv4);
+ /* SR-TE information */
+ if (nexthop->srte_color)
+ vty_out(vty, ", SR-TE color %u",
+ nexthop->srte_color);
+ }
+ break;
+ case NEXTHOP_TYPE_IPV6:
+ case NEXTHOP_TYPE_IPV6_IFINDEX:
+ if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any))
+ vty_out(vty, ", src %pI6", &nexthop->src.ipv6);
+ break;
default:
break;
}
- if (!json)
- vty_out(vty, "\n");
+ /* Label information */
+ if (nexthop->nh_label && nexthop->nh_label->num_labels) {
+ vty_out(vty, ", label %s",
+ mpls_label2str(nexthop->nh_label->num_labels,
+ nexthop->nh_label->label, buf,
+ sizeof(buf), 1));
+ }
+
+ if (nexthop->nh_srv6) {
+ seg6local_context2str(buf, sizeof(buf),
+ &nexthop->nh_srv6->seg6local_ctx,
+ nexthop->nh_srv6->seg6local_action);
+ vty_out(vty, ", seg6local %s %s",
+ seg6local_action2str(
+ nexthop->nh_srv6->seg6local_action),
+ buf);
+ vty_out(vty, ", seg6 %pI6", &nexthop->nh_srv6->seg6_segs);
+ }
+
+ if (nexthop->weight)
+ vty_out(vty, ", weight %u", nexthop->weight);
+
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) {
+ vty_out(vty, ", backup %d", nexthop->backup_idx[0]);
+
+ for (i = 1; i < nexthop->backup_num; i++)
+ vty_out(vty, ",%d", nexthop->backup_idx[i]);
+ }
}
static void print_rnh(struct route_node *rn, struct vty *vty, json_object *json)
@@ -1368,7 +1586,8 @@ static void print_rnh(struct route_node *rn, struct vty *vty, json_object *json)
CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED));
json_object_object_add(json_nht, "clientList",
json_client_array);
- json_object_object_add(json_nht, "gates", json_nexthop_array);
+ json_object_object_add(json_nht, "nexthops",
+ json_nexthop_array);
} else {
vty_out(vty, "%s%s\n",
inet_ntop(rn->p.family, &rn->p.u.prefix, buf, BUFSIZ),
@@ -1392,8 +1611,12 @@ static void print_rnh(struct route_node *rn, struct vty *vty, json_object *json)
json_nexthop = json_object_new_object();
json_object_array_add(json_nexthop_array,
json_nexthop);
+ show_nexthop_json_helper(json_nexthop, nexthop,
+ NULL);
+ } else {
+ show_route_nexthop_helper(vty, NULL, nexthop);
+ vty_out(vty, "\n");
}
- print_nh(nexthop, vty, json_nexthop);
}
} else {
if (json)
diff --git a/zebra/zebra_rnh.h b/zebra/zebra_rnh.h
index 44ce65b4b6..88be69a81d 100644
--- a/zebra/zebra_rnh.h
+++ b/zebra/zebra_rnh.h
@@ -58,6 +58,12 @@ extern bool rnh_nexthop_valid(const struct route_entry *re,
void rnh_set_hide_backups(bool hide_p);
bool rnh_get_hide_backups(void);
+void show_nexthop_json_helper(json_object *json_nexthop,
+ const struct nexthop *nexthop,
+ const struct route_entry *re);
+void show_route_nexthop_helper(struct vty *vty, const struct route_entry *re,
+ const struct nexthop *nexthop);
+
#ifdef __cplusplus
}
#endif
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index ccd6eb2631..8a73ae3d28 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -598,340 +598,6 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
}
}
-/*
- * Helper for nexthop output, used in the 'show ip route' path
- */
-static void show_route_nexthop_helper(struct vty *vty,
- const struct route_entry *re,
- const struct nexthop *nexthop)
-{
- char buf[MPLS_LABEL_STRLEN];
- int i;
-
- switch (nexthop->type) {
- case NEXTHOP_TYPE_IPV4:
- case NEXTHOP_TYPE_IPV4_IFINDEX:
- vty_out(vty, " via %pI4", &nexthop->gate.ipv4);
- if (nexthop->ifindex)
- vty_out(vty, ", %s",
- ifindex2ifname(nexthop->ifindex,
- nexthop->vrf_id));
- break;
- case NEXTHOP_TYPE_IPV6:
- case NEXTHOP_TYPE_IPV6_IFINDEX:
- vty_out(vty, " via %s",
- inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
- sizeof(buf)));
- if (nexthop->ifindex)
- vty_out(vty, ", %s",
- ifindex2ifname(nexthop->ifindex,
- nexthop->vrf_id));
- break;
-
- case NEXTHOP_TYPE_IFINDEX:
- vty_out(vty, " is directly connected, %s",
- ifindex2ifname(nexthop->ifindex, nexthop->vrf_id));
- break;
- case NEXTHOP_TYPE_BLACKHOLE:
- vty_out(vty, " unreachable");
- switch (nexthop->bh_type) {
- case BLACKHOLE_REJECT:
- vty_out(vty, " (ICMP unreachable)");
- break;
- case BLACKHOLE_ADMINPROHIB:
- vty_out(vty, " (ICMP admin-prohibited)");
- break;
- case BLACKHOLE_NULL:
- vty_out(vty, " (blackhole)");
- break;
- case BLACKHOLE_UNSPEC:
- break;
- }
- break;
- }
-
- if ((re == NULL || (nexthop->vrf_id != re->vrf_id)))
- vty_out(vty, " (vrf %s)", vrf_id_to_name(nexthop->vrf_id));
-
- if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
- vty_out(vty, " inactive");
-
- if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
- vty_out(vty, " onlink");
-
- if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_LINKDOWN))
- vty_out(vty, " linkdown");
-
- if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
- vty_out(vty, " (recursive)");
-
- switch (nexthop->type) {
- case NEXTHOP_TYPE_IPV4:
- case NEXTHOP_TYPE_IPV4_IFINDEX:
- if (nexthop->src.ipv4.s_addr) {
- if (inet_ntop(AF_INET, &nexthop->src.ipv4, buf,
- sizeof(buf)))
- vty_out(vty, ", src %s", buf);
- /* SR-TE information */
- if (nexthop->srte_color)
- vty_out(vty, ", SR-TE color %u",
- nexthop->srte_color);
- }
- break;
- case NEXTHOP_TYPE_IPV6:
- case NEXTHOP_TYPE_IPV6_IFINDEX:
- if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any)) {
- if (inet_ntop(AF_INET6, &nexthop->src.ipv6, buf,
- sizeof(buf)))
- vty_out(vty, ", src %s", buf);
- }
- break;
- default:
- break;
- }
-
- /* Label information */
- if (nexthop->nh_label && nexthop->nh_label->num_labels) {
- vty_out(vty, ", label %s",
- mpls_label2str(nexthop->nh_label->num_labels,
- nexthop->nh_label->label, buf,
- sizeof(buf), 1));
- }
-
- if (nexthop->nh_srv6) {
- seg6local_context2str(buf, sizeof(buf),
- &nexthop->nh_srv6->seg6local_ctx,
- nexthop->nh_srv6->seg6local_action);
- vty_out(vty, ", seg6local %s %s",
- seg6local_action2str(
- nexthop->nh_srv6->seg6local_action),
- buf);
-
- inet_ntop(AF_INET6, &nexthop->nh_srv6->seg6_segs, buf,
- sizeof(buf));
- vty_out(vty, ", seg6 %s", buf);
- }
-
- if (nexthop->weight)
- vty_out(vty, ", weight %u", nexthop->weight);
-
- if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) {
- vty_out(vty, ", backup %d", nexthop->backup_idx[0]);
-
- for (i = 1; i < nexthop->backup_num; i++)
- vty_out(vty, ",%d", nexthop->backup_idx[i]);
- }
-}
-
-
-/*
- * Render a nexthop into a json object; the caller allocates and owns
- * the json object memory.
- */
-static void show_nexthop_json_helper(json_object *json_nexthop,
- const struct nexthop *nexthop,
- const struct route_entry *re)
-{
- char buf[SRCDEST2STR_BUFFER];
- json_object *json_labels = NULL;
- json_object *json_backups = NULL;
- json_object *json_seg6local = NULL;
- json_object *json_seg6 = NULL;
- int i;
-
- json_object_int_add(json_nexthop, "flags",
- nexthop->flags);
-
- if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE))
- json_object_boolean_true_add(json_nexthop,
- "duplicate");
-
- if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))
- json_object_boolean_true_add(json_nexthop,
- "fib");
-
- switch (nexthop->type) {
- case NEXTHOP_TYPE_IPV4:
- case NEXTHOP_TYPE_IPV4_IFINDEX:
- json_object_string_addf(json_nexthop, "ip", "%pI4",
- &nexthop->gate.ipv4);
- json_object_string_add(json_nexthop, "afi",
- "ipv4");
-
- if (nexthop->ifindex) {
- json_object_int_add(json_nexthop,
- "interfaceIndex",
- nexthop->ifindex);
- json_object_string_add(
- json_nexthop, "interfaceName",
- ifindex2ifname(
- nexthop->ifindex,
- nexthop->vrf_id));
- }
- break;
- case NEXTHOP_TYPE_IPV6:
- case NEXTHOP_TYPE_IPV6_IFINDEX:
- json_object_string_addf(json_nexthop, "ip", "%pI6",
- &nexthop->gate.ipv6);
- json_object_string_add(json_nexthop, "afi",
- "ipv6");
-
- if (nexthop->ifindex) {
- json_object_int_add(json_nexthop,
- "interfaceIndex",
- nexthop->ifindex);
- json_object_string_add(
- json_nexthop, "interfaceName",
- ifindex2ifname(
- nexthop->ifindex,
- nexthop->vrf_id));
- }
- break;
-
- case NEXTHOP_TYPE_IFINDEX:
- json_object_boolean_true_add(
- json_nexthop, "directlyConnected");
- json_object_int_add(json_nexthop,
- "interfaceIndex",
- nexthop->ifindex);
- json_object_string_add(
- json_nexthop, "interfaceName",
- ifindex2ifname(nexthop->ifindex,
- nexthop->vrf_id));
- break;
- case NEXTHOP_TYPE_BLACKHOLE:
- json_object_boolean_true_add(json_nexthop,
- "unreachable");
- switch (nexthop->bh_type) {
- case BLACKHOLE_REJECT:
- json_object_boolean_true_add(
- json_nexthop, "reject");
- break;
- case BLACKHOLE_ADMINPROHIB:
- json_object_boolean_true_add(json_nexthop,
- "adminProhibited");
- break;
- case BLACKHOLE_NULL:
- json_object_boolean_true_add(
- json_nexthop, "blackhole");
- break;
- case BLACKHOLE_UNSPEC:
- break;
- }
- break;
- }
-
- /* This nexthop is a resolver for the parent nexthop.
- * Set resolver flag for better clarity and delimiter
- * in flat list of nexthops in json.
- */
- if (nexthop->rparent)
- json_object_boolean_true_add(json_nexthop, "resolver");
-
- if ((re == NULL || (nexthop->vrf_id != re->vrf_id)))
- json_object_string_add(json_nexthop, "vrf",
- vrf_id_to_name(nexthop->vrf_id));
-
- if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE))
- json_object_boolean_true_add(json_nexthop,
- "duplicate");
-
- if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
- json_object_boolean_true_add(json_nexthop,
- "active");
-
- if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
- json_object_boolean_true_add(json_nexthop, "onLink");
-
- if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_LINKDOWN))
- json_object_boolean_true_add(json_nexthop, "linkDown");
-
- if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
- json_object_boolean_true_add(json_nexthop,
- "recursive");
-
- if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) {
- json_backups = json_object_new_array();
- for (i = 0; i < nexthop->backup_num; i++) {
- json_object_array_add(
- json_backups,
- json_object_new_int(nexthop->backup_idx[i]));
- }
-
- json_object_object_add(json_nexthop, "backupIndex",
- json_backups);
- }
-
- switch (nexthop->type) {
- case NEXTHOP_TYPE_IPV4:
- case NEXTHOP_TYPE_IPV4_IFINDEX:
- if (nexthop->src.ipv4.s_addr) {
- if (inet_ntop(AF_INET,
- &nexthop->src.ipv4, buf,
- sizeof(buf)))
- json_object_string_add(
- json_nexthop, "source",
- buf);
- }
- break;
- case NEXTHOP_TYPE_IPV6:
- case NEXTHOP_TYPE_IPV6_IFINDEX:
- if (!IPV6_ADDR_SAME(&nexthop->src.ipv6,
- &in6addr_any)) {
- if (inet_ntop(AF_INET6,
- &nexthop->src.ipv6, buf,
- sizeof(buf)))
- json_object_string_add(
- json_nexthop, "source",
- buf);
- }
- break;
- default:
- break;
- }
-
- if (nexthop->nh_label
- && nexthop->nh_label->num_labels) {
- json_labels = json_object_new_array();
-
- for (int label_index = 0;
- label_index
- < nexthop->nh_label->num_labels;
- label_index++)
- json_object_array_add(
- json_labels,
- json_object_new_int(
- nexthop->nh_label->label
- [label_index]));
-
- json_object_object_add(json_nexthop, "labels",
- json_labels);
- }
-
- if (nexthop->weight)
- json_object_int_add(json_nexthop, "weight",
- nexthop->weight);
-
- if (nexthop->srte_color)
- json_object_int_add(json_nexthop, "srteColor",
- nexthop->srte_color);
-
- if (nexthop->nh_srv6) {
- json_seg6local = json_object_new_object();
- json_object_string_add(
- json_seg6local, "action", seg6local_action2str(
- nexthop->nh_srv6->seg6local_action));
- json_object_object_add(json_nexthop, "seg6local",
- json_seg6local);
-
- json_seg6 = json_object_new_object();
- inet_ntop(AF_INET6, &nexthop->nh_srv6->seg6_segs, buf,
- sizeof(buf));
- json_object_string_add(json_seg6, "segs", buf);
- json_object_object_add(json_nexthop, "seg6", json_seg6);
- }
-}
-
static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
struct route_entry *re, json_object *json,
bool is_fib, bool show_ng)
@@ -1410,7 +1076,9 @@ DEFPY (show_ip_nht,
zvrf_name(zvrf),
json_vrf);
json_object_object_add(json_vrf,
- "nexthops",
+ (afi == AFI_IP)
+ ? "ipv4"
+ : "ipv6",
json_nexthop);
} else {
vty_out(vty, "\nVRF %s:\n",
@@ -1447,7 +1115,9 @@ DEFPY (show_ip_nht,
else
json_object_object_add(json, "default", json_vrf);
- json_object_object_add(json_vrf, "nexthops", json_nexthop);
+ json_object_object_add(json_vrf,
+ (afi == AFI_IP) ? "ipv4" : "ipv6",
+ json_nexthop);
}
zebra_print_rnh_table(vrf_id, afi, safi, vty, p, json_nexthop);