summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfdd/bfdd_cli.c48
-rw-r--r--bfdd/bfdd_nb.h35
-rw-r--r--bgpd/bgp_label.c4
-rw-r--r--bgpd/bgp_open.c129
-rw-r--r--bgpd/bgp_route.c58
-rw-r--r--bgpd/bgp_route.h5
-rw-r--r--bgpd/bgp_routemap.c20
-rw-r--r--bgpd/bgp_vty.c65
-rw-r--r--bgpd/bgp_zebra.c5
-rw-r--r--bgpd/bgpd.c10
-rw-r--r--doc/developer/lists.rst27
-rw-r--r--doc/user/bgp.rst9
-rw-r--r--doc/user/pbr.rst25
-rw-r--r--eigrpd/eigrp_cli.c55
-rw-r--r--eigrpd/eigrp_cli.h47
-rw-r--r--include/linux/nexthop.h59
-rw-r--r--isisd/isis_cli.c178
-rw-r--r--isisd/isis_nb.h167
-rw-r--r--lib/command.c75
-rw-r--r--lib/command.h9
-rw-r--r--lib/command_graph.c157
-rw-r--r--lib/command_graph.h11
-rw-r--r--lib/command_parse.y14
-rw-r--r--lib/filter.h16
-rw-r--r--lib/filter_cli.c14
-rw-r--r--lib/grammar_sandbox.c2
-rw-r--r--lib/if.c12
-rw-r--r--lib/northbound.h7
-rw-r--r--lib/northbound_cli.c8
-rw-r--r--lib/northbound_cli.h3
-rw-r--r--lib/pbr.h9
-rw-r--r--lib/route_opaque.h6
-rw-r--r--lib/routemap.h23
-rw-r--r--lib/routemap_cli.c25
-rw-r--r--lib/sockopt.c4
-rw-r--r--lib/table.c2
-rw-r--r--lib/thread.c71
-rw-r--r--lib/thread.h45
-rw-r--r--lib/typerb.c10
-rw-r--r--lib/typerb.h7
-rw-r--r--lib/typesafe.c40
-rw-r--r--lib/typesafe.h109
-rw-r--r--lib/vector.c33
-rw-r--r--lib/vector.h7
-rw-r--r--lib/vty.c22
-rw-r--r--lib/vxlan.h2
-rw-r--r--lib/yang.h2
-rw-r--r--lib/zclient.c22
-rw-r--r--lib/zclient.h4
-rw-r--r--nhrpd/list.h209
-rw-r--r--nhrpd/nhrp_cache.c4
-rw-r--r--nhrpd/nhrp_interface.c17
-rw-r--r--nhrpd/nhrp_main.c2
-rw-r--r--nhrpd/nhrp_multicast.c30
-rw-r--r--nhrpd/nhrp_nhs.c96
-rw-r--r--nhrpd/nhrp_peer.c2
-rw-r--r--nhrpd/nhrp_vc.c27
-rw-r--r--nhrpd/nhrp_vty.c8
-rw-r--r--nhrpd/nhrpd.h53
-rw-r--r--nhrpd/subdir.am1
-rw-r--r--nhrpd/zbuf.c21
-rw-r--r--nhrpd/zbuf.h10
-rw-r--r--ospfd/ospf_lsa.c4
-rw-r--r--ospfd/ospf_lsa.h4
-rw-r--r--ospfd/ospfd.c1
-rw-r--r--pathd/path_cli.c23
-rw-r--r--pathd/path_nb.h21
-rw-r--r--pathd/pathd.c2
-rw-r--r--pbrd/pbr_map.c35
-rw-r--r--pbrd/pbr_map.h12
-rw-r--r--pbrd/pbr_vty.c105
-rw-r--r--pbrd/pbr_zebra.c6
-rw-r--r--ripd/rip_cli.c53
-rw-r--r--ripd/rip_nb.h53
-rw-r--r--ripngd/ripng_cli.c34
-rw-r--r--ripngd/ripng_nb.h32
-rw-r--r--staticd/static_vty.c20
-rw-r--r--staticd/static_vty.h20
-rw-r--r--tests/.gitignore2
-rw-r--r--tests/lib/test_typelist.h82
-rw-r--r--tests/topotests/bfd_isis_topo1/test_bfd_isis_topo1.py15
-rw-r--r--tests/topotests/bgp_ecmp_topo3/test_ibgp_ecmp_topo3.py11
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_direct/scripts/adjacencies.py7
-rw-r--r--tests/topotests/bgp_lu_topo1/R2/labelpool.summ.json6
-rw-r--r--tests/topotests/bgp_lu_topo2/R1/bgpd.conf29
-rw-r--r--tests/topotests/bgp_lu_topo2/R1/labelpool.summ.json8
-rw-r--r--tests/topotests/bgp_lu_topo2/R1/zebra.conf13
-rw-r--r--tests/topotests/bgp_lu_topo2/R2/bgpd.conf27
-rw-r--r--tests/topotests/bgp_lu_topo2/R2/labelpool.summ.json8
-rw-r--r--tests/topotests/bgp_lu_topo2/R2/zebra.conf14
-rw-r--r--tests/topotests/bgp_lu_topo2/R3/bgpd.conf70
-rw-r--r--tests/topotests/bgp_lu_topo2/R3/staticd.conf5
-rw-r--r--tests/topotests/bgp_lu_topo2/R3/zebra.conf11
-rw-r--r--tests/topotests/bgp_lu_topo2/R4/bgpd.conf23
-rw-r--r--tests/topotests/bgp_lu_topo2/R4/zebra.conf9
-rw-r--r--tests/topotests/bgp_lu_topo2/test_bgp_lu2.py221
-rwxr-xr-xtests/topotests/conftest.py58
-rw-r--r--tests/topotests/ldp_topo1/test_ldp_topo1.py13
-rw-r--r--tests/topotests/lib/topotest.py4
-rwxr-xr-xtests/topotests/ospf_gr_topo1/test_ospf_gr_topo1.py2
-rw-r--r--tests/topotests/pytest.ini1
-rwxr-xr-xtools/checkpatch.pl32
-rw-r--r--vrrpd/vrrp_vty.c16
-rw-r--r--vrrpd/vrrp_vty.h18
-rw-r--r--vtysh/vtysh.c2
-rw-r--r--zebra/debug_nl.c1
-rw-r--r--zebra/kernel_netlink.h4
-rw-r--r--zebra/zapi_msg.c7
-rw-r--r--zebra/zebra_dplane.c13
-rw-r--r--zebra/zebra_evpn.c20
-rw-r--r--zebra/zebra_evpn_mac.c19
-rw-r--r--zebra/zebra_evpn_mh.c46
-rw-r--r--zebra/zebra_evpn_mh.h2
-rw-r--r--zebra/zebra_l2.c4
-rw-r--r--zebra/zebra_netns_notify.c8
-rw-r--r--zebra/zebra_rib.c12
-rw-r--r--zebra/zebra_vty.c5
117 files changed, 2290 insertions, 1180 deletions
diff --git a/bfdd/bfdd_cli.c b/bfdd/bfdd_cli.c
index 384bb26fd7..d4e12e4f1a 100644
--- a/bfdd/bfdd_cli.c
+++ b/bfdd/bfdd_cli.c
@@ -92,14 +92,15 @@ DEFUN_YANG(
}
void bfd_cli_show_header(struct vty *vty,
- struct lyd_node *dnode __attribute__((__unused__)),
+ const struct lyd_node *dnode
+ __attribute__((__unused__)),
bool show_defaults __attribute__((__unused__)))
{
vty_out(vty, "!\nbfd\n");
}
-void bfd_cli_show_header_end(struct vty *vty,
- struct lyd_node *dnode __attribute__((__unused__)))
+void bfd_cli_show_header_end(struct vty *vty, const struct lyd_node *dnode
+ __attribute__((__unused__)))
{
vty_out(vty, "exit\n");
vty_out(vty, "!\n");
@@ -230,7 +231,7 @@ DEFPY_YANG(
return nb_cli_apply_changes(vty, NULL);
}
-static void _bfd_cli_show_peer(struct vty *vty, struct lyd_node *dnode,
+static void _bfd_cli_show_peer(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults __attribute__((__unused__)),
bool mhop)
{
@@ -259,22 +260,20 @@ static void _bfd_cli_show_peer(struct vty *vty, struct lyd_node *dnode,
vty_out(vty, "\n");
}
-void bfd_cli_show_single_hop_peer(struct vty *vty,
- struct lyd_node *dnode,
+void bfd_cli_show_single_hop_peer(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
_bfd_cli_show_peer(vty, dnode, show_defaults, false);
}
-void bfd_cli_show_multi_hop_peer(struct vty *vty,
- struct lyd_node *dnode,
- bool show_defaults)
+void bfd_cli_show_multi_hop_peer(struct vty *vty, const struct lyd_node *dnode,
+ bool show_defaults)
{
_bfd_cli_show_peer(vty, dnode, show_defaults, true);
}
-void bfd_cli_show_peer_end(struct vty *vty,
- struct lyd_node *dnode __attribute__((__unused__)))
+void bfd_cli_show_peer_end(struct vty *vty, const struct lyd_node *dnode
+ __attribute__((__unused__)))
{
vty_out(vty, " exit\n");
vty_out(vty, " !\n");
@@ -291,7 +290,7 @@ DEFPY_YANG(
return nb_cli_apply_changes(vty, NULL);
}
-void bfd_cli_show_shutdown(struct vty *vty, struct lyd_node *dnode,
+void bfd_cli_show_shutdown(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " %sshutdown\n",
@@ -309,7 +308,7 @@ DEFPY_YANG(
return nb_cli_apply_changes(vty, NULL);
}
-void bfd_cli_show_passive(struct vty *vty, struct lyd_node *dnode,
+void bfd_cli_show_passive(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " %spassive-mode\n",
@@ -347,7 +346,7 @@ DEFPY_YANG(
return nb_cli_apply_changes(vty, NULL);
}
-void bfd_cli_show_minimum_ttl(struct vty *vty, struct lyd_node *dnode,
+void bfd_cli_show_minimum_ttl(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " minimum-ttl %s\n", yang_dnode_get_string(dnode, NULL));
@@ -364,7 +363,7 @@ DEFPY_YANG(
return nb_cli_apply_changes(vty, NULL);
}
-void bfd_cli_show_mult(struct vty *vty, struct lyd_node *dnode,
+void bfd_cli_show_mult(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " detect-multiplier %s\n",
@@ -386,7 +385,7 @@ DEFPY_YANG(
return nb_cli_apply_changes(vty, NULL);
}
-void bfd_cli_show_rx(struct vty *vty, struct lyd_node *dnode,
+void bfd_cli_show_rx(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
uint32_t value = yang_dnode_get_uint32(dnode, NULL);
@@ -409,7 +408,7 @@ DEFPY_YANG(
return nb_cli_apply_changes(vty, NULL);
}
-void bfd_cli_show_tx(struct vty *vty, struct lyd_node *dnode,
+void bfd_cli_show_tx(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
uint32_t value = yang_dnode_get_uint32(dnode, NULL);
@@ -437,8 +436,8 @@ DEFPY_YANG(
return nb_cli_apply_changes(vty, NULL);
}
-void bfd_cli_show_echo(struct vty *vty, struct lyd_node *dnode,
- bool show_defaults)
+void bfd_cli_show_echo(struct vty *vty, const struct lyd_node *dnode,
+ bool show_defaults)
{
vty_out(vty, " %secho-mode\n",
yang_dnode_get_bool(dnode, NULL) ? "" : "no ");
@@ -487,8 +486,8 @@ DEFPY_YANG(
return nb_cli_apply_changes(vty, NULL);
}
-void bfd_cli_show_desired_echo_transmission_interval(struct vty *vty,
- struct lyd_node *dnode, bool show_defaults)
+void bfd_cli_show_desired_echo_transmission_interval(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
{
uint32_t value = yang_dnode_get_uint32(dnode, NULL);
@@ -522,7 +521,8 @@ DEFPY_YANG(
}
void bfd_cli_show_required_echo_receive_interval(struct vty *vty,
- struct lyd_node *dnode, bool show_defaults)
+ const struct lyd_node *dnode,
+ bool show_defaults)
{
uint32_t value = yang_dnode_get_uint32(dnode, NULL);
@@ -573,7 +573,7 @@ DEFPY_YANG(no_bfd_profile, no_bfd_profile_cmd,
return nb_cli_apply_changes(vty, NULL);
}
-void bfd_cli_show_profile(struct vty *vty, struct lyd_node *dnode,
+void bfd_cli_show_profile(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " profile %s\n", yang_dnode_get_string(dnode, "./name"));
@@ -654,7 +654,7 @@ DEFPY_YANG(bfd_peer_profile, bfd_peer_profile_cmd,
return nb_cli_apply_changes(vty, NULL);
}
-void bfd_cli_peer_profile_show(struct vty *vty, struct lyd_node *dnode,
+void bfd_cli_peer_profile_show(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " profile %s\n", yang_dnode_get_string(dnode, NULL));
diff --git a/bfdd/bfdd_nb.h b/bfdd/bfdd_nb.h
index 874e98691f..d7ac320638 100644
--- a/bfdd/bfdd_nb.h
+++ b/bfdd/bfdd_nb.h
@@ -195,35 +195,36 @@ bfdd_bfd_sessions_multi_hop_stats_echo_packet_output_count_get_elem(
struct nb_cb_get_elem_args *args);
/* Optional 'cli_show' callbacks. */
-void bfd_cli_show_header(struct vty *vty, struct lyd_node *dnode,
+void bfd_cli_show_header(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void bfd_cli_show_header_end(struct vty *vty, struct lyd_node *dnode);
-void bfd_cli_show_single_hop_peer(struct vty *vty, struct lyd_node *dnode,
+void bfd_cli_show_header_end(struct vty *vty, const struct lyd_node *dnode);
+void bfd_cli_show_single_hop_peer(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void bfd_cli_show_multi_hop_peer(struct vty *vty, struct lyd_node *dnode,
+void bfd_cli_show_multi_hop_peer(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void bfd_cli_show_peer_end(struct vty *vty, struct lyd_node *dnode);
-void bfd_cli_show_mult(struct vty *vty, struct lyd_node *dnode,
+void bfd_cli_show_peer_end(struct vty *vty, const struct lyd_node *dnode);
+void bfd_cli_show_mult(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void bfd_cli_show_tx(struct vty *vty, struct lyd_node *dnode,
+void bfd_cli_show_tx(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void bfd_cli_show_rx(struct vty *vty, struct lyd_node *dnode,
+void bfd_cli_show_rx(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void bfd_cli_show_shutdown(struct vty *vty, struct lyd_node *dnode,
+void bfd_cli_show_shutdown(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void bfd_cli_show_echo(struct vty *vty, struct lyd_node *dnode,
+void bfd_cli_show_echo(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
void bfd_cli_show_desired_echo_transmission_interval(
- struct vty *vty, struct lyd_node *dnode, bool show_defaults);
-void bfd_cli_show_required_echo_receive_interval(
- struct vty *vty, struct lyd_node *dnode, bool show_defaults);
-void bfd_cli_show_profile(struct vty *vty, struct lyd_node *dnode,
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults);
+void bfd_cli_show_required_echo_receive_interval(struct vty *vty,
+ const struct lyd_node *dnode,
+ bool show_defaults);
+void bfd_cli_show_profile(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void bfd_cli_peer_profile_show(struct vty *vty, struct lyd_node *dnode,
+void bfd_cli_peer_profile_show(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void bfd_cli_show_passive(struct vty *vty, struct lyd_node *dnode,
+void bfd_cli_show_passive(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void bfd_cli_show_minimum_ttl(struct vty *vty, struct lyd_node *dnode,
+void bfd_cli_show_minimum_ttl(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
#endif /* _FRR_BFDD_NB_H_ */
diff --git a/bgpd/bgp_label.c b/bgpd/bgp_label.c
index 3c8f2f3668..fa2a445165 100644
--- a/bgpd/bgp_label.c
+++ b/bgpd/bgp_label.c
@@ -244,6 +244,10 @@ void bgp_reg_dereg_for_label(struct bgp_dest *dest, struct bgp_path_info *pi,
p = bgp_dest_get_prefix(dest);
+ if (BGP_DEBUG(labelpool, LABELPOOL))
+ zlog_debug("%s: %pFX: %s ", __func__, p,
+ (reg ? "reg" : "dereg"));
+
if (reg) {
assert(pi);
/*
diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c
index f1dfebdc1b..ca8b1e398b 100644
--- a/bgpd/bgp_open.c
+++ b/bgpd/bgp_open.c
@@ -42,6 +42,63 @@
#include "bgpd/bgp_vty.h"
#include "bgpd/bgp_memory.h"
+static const struct message capcode_str[] = {
+ {CAPABILITY_CODE_MP, "MultiProtocol Extensions"},
+ {CAPABILITY_CODE_REFRESH, "Route Refresh"},
+ {CAPABILITY_CODE_ORF, "Cooperative Route Filtering"},
+ {CAPABILITY_CODE_RESTART, "Graceful Restart"},
+ {CAPABILITY_CODE_AS4, "4-octet AS number"},
+ {CAPABILITY_CODE_ADDPATH, "AddPath"},
+ {CAPABILITY_CODE_DYNAMIC, "Dynamic"},
+ {CAPABILITY_CODE_ENHE, "Extended Next Hop Encoding"},
+ {CAPABILITY_CODE_DYNAMIC_OLD, "Dynamic (Old)"},
+ {CAPABILITY_CODE_REFRESH_OLD, "Route Refresh (Old)"},
+ {CAPABILITY_CODE_ORF_OLD, "ORF (Old)"},
+ {CAPABILITY_CODE_FQDN, "FQDN"},
+ {CAPABILITY_CODE_ENHANCED_RR, "Enhanced Route Refresh"},
+ {CAPABILITY_CODE_EXT_MESSAGE, "BGP Extended Message"},
+ {0}};
+
+/* Minimum sizes for length field of each cap (so not inc. the header) */
+static const size_t cap_minsizes[] = {
+ [CAPABILITY_CODE_MP] = CAPABILITY_CODE_MP_LEN,
+ [CAPABILITY_CODE_REFRESH] = CAPABILITY_CODE_REFRESH_LEN,
+ [CAPABILITY_CODE_ORF] = CAPABILITY_CODE_ORF_LEN,
+ [CAPABILITY_CODE_RESTART] = CAPABILITY_CODE_RESTART_LEN,
+ [CAPABILITY_CODE_AS4] = CAPABILITY_CODE_AS4_LEN,
+ [CAPABILITY_CODE_ADDPATH] = CAPABILITY_CODE_ADDPATH_LEN,
+ [CAPABILITY_CODE_DYNAMIC] = CAPABILITY_CODE_DYNAMIC_LEN,
+ [CAPABILITY_CODE_DYNAMIC_OLD] = CAPABILITY_CODE_DYNAMIC_LEN,
+ [CAPABILITY_CODE_ENHE] = CAPABILITY_CODE_ENHE_LEN,
+ [CAPABILITY_CODE_REFRESH_OLD] = CAPABILITY_CODE_REFRESH_LEN,
+ [CAPABILITY_CODE_ORF_OLD] = CAPABILITY_CODE_ORF_LEN,
+ [CAPABILITY_CODE_FQDN] = CAPABILITY_CODE_MIN_FQDN_LEN,
+ [CAPABILITY_CODE_ENHANCED_RR] = CAPABILITY_CODE_ENHANCED_LEN,
+ [CAPABILITY_CODE_EXT_MESSAGE] = CAPABILITY_CODE_EXT_MESSAGE_LEN,
+};
+
+/* value the capability must be a multiple of.
+ * 0-data capabilities won't be checked against this.
+ * Other capabilities whose data doesn't fall on convenient boundaries for this
+ * table should be set to 1.
+ */
+static const size_t cap_modsizes[] = {
+ [CAPABILITY_CODE_MP] = 4,
+ [CAPABILITY_CODE_REFRESH] = 1,
+ [CAPABILITY_CODE_ORF] = 1,
+ [CAPABILITY_CODE_RESTART] = 1,
+ [CAPABILITY_CODE_AS4] = 4,
+ [CAPABILITY_CODE_ADDPATH] = 4,
+ [CAPABILITY_CODE_DYNAMIC] = 1,
+ [CAPABILITY_CODE_DYNAMIC_OLD] = 1,
+ [CAPABILITY_CODE_ENHE] = 6,
+ [CAPABILITY_CODE_REFRESH_OLD] = 1,
+ [CAPABILITY_CODE_ORF_OLD] = 1,
+ [CAPABILITY_CODE_FQDN] = 1,
+ [CAPABILITY_CODE_ENHANCED_RR] = 1,
+ [CAPABILITY_CODE_EXT_MESSAGE] = 1,
+};
+
/* BGP-4 Multiprotocol Extentions lead us to the complex world. We can
negotiate remote peer supports extentions or not. But if
remote-peer doesn't supports negotiation process itself. We would
@@ -264,9 +321,9 @@ static int bgp_capability_mp(struct peer *peer, struct capability_header *hdr)
bgp_capability_mp_data(s, &mpc);
if (bgp_debug_neighbor_events(peer))
- zlog_debug("%s OPEN has MP_EXT CAP for afi/safi: %s/%s",
- peer->host, iana_afi2str(mpc.afi),
- iana_safi2str(mpc.safi));
+ zlog_debug("%s OPEN has %s capability for afi/safi: %s/%s",
+ peer->host, lookup_msg(capcode_str, hdr->code, NULL),
+ iana_afi2str(mpc.afi), iana_safi2str(mpc.safi));
/* Convert AFI, SAFI to internal values, check. */
if (bgp_map_afi_safi_iana2int(mpc.afi, mpc.safi, &afi, &safi))
@@ -466,8 +523,6 @@ static int bgp_capability_restart(struct peer *peer,
peer->v_gr_restart = restart_flag_time;
if (bgp_debug_neighbor_events(peer)) {
- zlog_debug("%s OPEN has Graceful Restart capability",
- peer->host);
zlog_debug("%s Peer has%srestarted. Restart Time : %d",
peer->host,
CHECK_FLAG(peer->cap, PEER_CAP_RESTART_BIT_RCV)
@@ -580,9 +635,10 @@ static int bgp_capability_addpath(struct peer *peer,
if (bgp_debug_neighbor_events(peer))
zlog_debug(
- "%s OPEN has AddPath CAP for afi/safi: %s/%s%s%s",
- peer->host, iana_afi2str(pkt_afi),
- iana_safi2str(pkt_safi),
+ "%s OPEN has %s capability for afi/safi: %s/%s%s%s",
+ peer->host,
+ lookup_msg(capcode_str, hdr->code, NULL),
+ iana_afi2str(pkt_afi), iana_safi2str(pkt_safi),
(send_receive & BGP_ADDPATH_RX) ? ", receive"
: "",
(send_receive & BGP_ADDPATH_TX) ? ", transmit"
@@ -763,63 +819,6 @@ static int bgp_capability_hostname(struct peer *peer,
return 0;
}
-static const struct message capcode_str[] = {
- {CAPABILITY_CODE_MP, "MultiProtocol Extensions"},
- {CAPABILITY_CODE_REFRESH, "Route Refresh"},
- {CAPABILITY_CODE_ORF, "Cooperative Route Filtering"},
- {CAPABILITY_CODE_RESTART, "Graceful Restart"},
- {CAPABILITY_CODE_AS4, "4-octet AS number"},
- {CAPABILITY_CODE_ADDPATH, "AddPath"},
- {CAPABILITY_CODE_DYNAMIC, "Dynamic"},
- {CAPABILITY_CODE_ENHE, "Extended Next Hop Encoding"},
- {CAPABILITY_CODE_DYNAMIC_OLD, "Dynamic (Old)"},
- {CAPABILITY_CODE_REFRESH_OLD, "Route Refresh (Old)"},
- {CAPABILITY_CODE_ORF_OLD, "ORF (Old)"},
- {CAPABILITY_CODE_FQDN, "FQDN"},
- {CAPABILITY_CODE_ENHANCED_RR, "Enhanced Route Refresh"},
- {CAPABILITY_CODE_EXT_MESSAGE, "BGP Extended Message"},
- {0}};
-
-/* Minimum sizes for length field of each cap (so not inc. the header) */
-static const size_t cap_minsizes[] = {
- [CAPABILITY_CODE_MP] = CAPABILITY_CODE_MP_LEN,
- [CAPABILITY_CODE_REFRESH] = CAPABILITY_CODE_REFRESH_LEN,
- [CAPABILITY_CODE_ORF] = CAPABILITY_CODE_ORF_LEN,
- [CAPABILITY_CODE_RESTART] = CAPABILITY_CODE_RESTART_LEN,
- [CAPABILITY_CODE_AS4] = CAPABILITY_CODE_AS4_LEN,
- [CAPABILITY_CODE_ADDPATH] = CAPABILITY_CODE_ADDPATH_LEN,
- [CAPABILITY_CODE_DYNAMIC] = CAPABILITY_CODE_DYNAMIC_LEN,
- [CAPABILITY_CODE_DYNAMIC_OLD] = CAPABILITY_CODE_DYNAMIC_LEN,
- [CAPABILITY_CODE_ENHE] = CAPABILITY_CODE_ENHE_LEN,
- [CAPABILITY_CODE_REFRESH_OLD] = CAPABILITY_CODE_REFRESH_LEN,
- [CAPABILITY_CODE_ORF_OLD] = CAPABILITY_CODE_ORF_LEN,
- [CAPABILITY_CODE_FQDN] = CAPABILITY_CODE_MIN_FQDN_LEN,
- [CAPABILITY_CODE_ENHANCED_RR] = CAPABILITY_CODE_ENHANCED_LEN,
- [CAPABILITY_CODE_EXT_MESSAGE] = CAPABILITY_CODE_EXT_MESSAGE_LEN,
-};
-
-/* value the capability must be a multiple of.
- * 0-data capabilities won't be checked against this.
- * Other capabilities whose data doesn't fall on convenient boundaries for this
- * table should be set to 1.
- */
-static const size_t cap_modsizes[] = {
- [CAPABILITY_CODE_MP] = 4,
- [CAPABILITY_CODE_REFRESH] = 1,
- [CAPABILITY_CODE_ORF] = 1,
- [CAPABILITY_CODE_RESTART] = 1,
- [CAPABILITY_CODE_AS4] = 4,
- [CAPABILITY_CODE_ADDPATH] = 4,
- [CAPABILITY_CODE_DYNAMIC] = 1,
- [CAPABILITY_CODE_DYNAMIC_OLD] = 1,
- [CAPABILITY_CODE_ENHE] = 6,
- [CAPABILITY_CODE_REFRESH_OLD] = 1,
- [CAPABILITY_CODE_ORF_OLD] = 1,
- [CAPABILITY_CODE_FQDN] = 1,
- [CAPABILITY_CODE_ENHANCED_RR] = 1,
- [CAPABILITY_CODE_EXT_MESSAGE] = 1,
-};
-
/**
* Parse given capability.
* XXX: This is reading into a stream, but not using stream API
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index e1d4d22b7e..4b798cc264 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -2712,6 +2712,28 @@ static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
}
/*
+ * Utility to determine whether a particular path_info should use
+ * the IMPLICIT_NULL label. This is pretty specialized: it's only called
+ * in a path where we basically _know_ this is a BGP-LU route.
+ */
+static bool bgp_lu_need_imp_null(const struct bgp_path_info *new_select)
+{
+ /* Certain types get imp null; so do paths where the nexthop is
+ * not labeled.
+ */
+ if (new_select->sub_type == BGP_ROUTE_STATIC
+ || new_select->sub_type == BGP_ROUTE_AGGREGATE
+ || new_select->sub_type == BGP_ROUTE_REDISTRIBUTE)
+ return true;
+ else if (new_select->extra == NULL ||
+ !bgp_is_valid_label(&new_select->extra->label[0]))
+ /* TODO -- should be configurable? */
+ return true;
+ else
+ return false;
+}
+
+/*
* old_select = The old best path
* new_select = the new best path
*
@@ -2802,11 +2824,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
* implicit-null for local routes, aggregate
* and redistributed routes
*/
- if (new_select->sub_type == BGP_ROUTE_STATIC
- || new_select->sub_type
- == BGP_ROUTE_AGGREGATE
- || new_select->sub_type
- == BGP_ROUTE_REDISTRIBUTE) {
+ if (bgp_lu_need_imp_null(new_select)) {
if (CHECK_FLAG(
dest->flags,
BGP_NODE_REGISTERED_FOR_LABEL)
@@ -8415,8 +8433,7 @@ enum bgp_display_type {
normal_list,
};
-static const char *
-bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
+const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
{
switch (reason) {
case bgp_path_selection_none:
@@ -13433,16 +13450,6 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
bgp = peer->bgp;
- if (!bgp) {
- if (use_json) {
- json_object_string_add(json, "alert", "no BGP");
- vty_out(vty, "%s\n", json_object_to_json_string(json));
- json_object_free(json);
- } else
- vty_out(vty, "%% No bgp\n");
- return;
- }
-
subgrp = peer_subgroup(peer, afi, safi);
if (type == bgp_show_adj_route_advertised && subgrp
@@ -13683,6 +13690,9 @@ static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
"No such neighbor or address family");
vty_out(vty, "%s\n", json_object_to_json_string(json));
json_object_free(json);
+ json_object_free(json_ar);
+ json_object_free(json_scode);
+ json_object_free(json_ocode);
} else
vty_out(vty, "%% No such neighbor or address family\n");
@@ -13699,6 +13709,9 @@ static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
"Inbound soft reconfiguration not enabled");
vty_out(vty, "%s\n", json_object_to_json_string(json));
json_object_free(json);
+ json_object_free(json_ar);
+ json_object_free(json_scode);
+ json_object_free(json_ocode);
} else
vty_out(vty,
"%% Inbound soft reconfiguration not enabled\n");
@@ -13767,14 +13780,17 @@ static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
json_object_to_json_string_ext(
json, JSON_C_TO_STRING_PRETTY));
- if (!output_count && !filtered_count) {
+ /*
+ * These fields only give up ownership to `json` when `header1`
+ * is used (set to zero). See code in `show_adj_route` and
+ * `show_adj_route_header`.
+ */
+ if (header1 == 1) {
json_object_free(json_scode);
json_object_free(json_ocode);
}
- if (json)
- json_object_free(json);
-
+ json_object_free(json);
} else if (output_count > 0) {
if (filtered_count > 0)
vty_out(vty,
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index 37bf675b67..46802d0d14 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -90,6 +90,9 @@ enum bgp_show_adj_route_type {
/* Maximum number of sids we can process or send with a prefix. */
#define BGP_MAX_SIDS 6
+/* Maximum buffer length for storing BGP best path selection reason */
+#define BGP_MAX_SELECTION_REASON_STR_BUF 32
+
/* Error codes for handling NLRI */
#define BGP_NLRI_PARSE_OK 0
#define BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW -1
@@ -803,4 +806,6 @@ extern void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
const struct prefix *p, afi_t afi,
safi_t safi, bool suppress);
extern void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr);
+const char *
+bgp_path_selection_reason2str(enum bgp_path_selection_reason reason);
#endif /* _QUAGGA_BGP_ROUTE_H */
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index 75dbc7f3e3..72a620aa6c 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -4761,7 +4761,7 @@ DEFUN_YANG(no_match_alias, no_match_alias_cmd, "no match alias [ALIAS_NAME]",
DEFPY_YANG (match_community,
match_community_cmd,
- "match community <(1-99)|(100-500)|WORD> [exact-match]",
+ "match community <(1-99)|(100-500)|COMMUNITY_LIST_NAME> [exact-match]",
MATCH_STR
"Match BGP community list\n"
"Community-list number (standard)\n"
@@ -4804,7 +4804,7 @@ DEFPY_YANG (match_community,
DEFUN_YANG (no_match_community,
no_match_community_cmd,
- "no match community [<(1-99)|(100-500)|WORD> [exact-match]]",
+ "no match community [<(1-99)|(100-500)|COMMUNITY_LIST_NAME> [exact-match]]",
NO_STR
MATCH_STR
"Match BGP community list\n"
@@ -4822,7 +4822,7 @@ DEFUN_YANG (no_match_community,
DEFPY_YANG (match_lcommunity,
match_lcommunity_cmd,
- "match large-community <(1-99)|(100-500)|WORD> [exact-match]",
+ "match large-community <(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> [exact-match]",
MATCH_STR
"Match BGP large community list\n"
"Large Community-list number (standard)\n"
@@ -4865,7 +4865,7 @@ DEFPY_YANG (match_lcommunity,
DEFUN_YANG (no_match_lcommunity,
no_match_lcommunity_cmd,
- "no match large-community [<(1-99)|(100-500)|WORD> [exact-match]]",
+ "no match large-community [<(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> [exact-match]]",
NO_STR
MATCH_STR
"Match BGP large community list\n"
@@ -4883,7 +4883,7 @@ DEFUN_YANG (no_match_lcommunity,
DEFPY_YANG (match_ecommunity,
match_ecommunity_cmd,
- "match extcommunity <(1-99)|(100-500)|WORD>",
+ "match extcommunity <(1-99)|(100-500)|EXTCOMMUNITY_LIST_NAME>",
MATCH_STR
"Match BGP/VPN extended community list\n"
"Extended community-list number (standard)\n"
@@ -4909,7 +4909,7 @@ DEFPY_YANG (match_ecommunity,
DEFUN_YANG (no_match_ecommunity,
no_match_ecommunity_cmd,
- "no match extcommunity [<(1-99)|(100-500)|WORD>]",
+ "no match extcommunity [<(1-99)|(100-500)|EXTCOMMUNITY_LIST_NAME>]",
NO_STR
MATCH_STR
"Match BGP/VPN extended community list\n"
@@ -5522,7 +5522,7 @@ ALIAS_YANG (no_set_community,
DEFPY_YANG (set_community_delete,
set_community_delete_cmd,
- "set comm-list <(1-99)|(100-500)|WORD> delete",
+ "set comm-list <(1-99)|(100-500)|COMMUNITY_LIST_NAME> delete",
SET_STR
"set BGP community list (for deletion)\n"
"Community-list number (standard)\n"
@@ -5549,7 +5549,7 @@ DEFPY_YANG (set_community_delete,
DEFUN_YANG (no_set_community_delete,
no_set_community_delete_cmd,
- "no set comm-list [<(1-99)|(100-500)|WORD> delete]",
+ "no set comm-list [<(1-99)|(100-500)|COMMUNITY_LIST_NAME> delete]",
NO_STR
SET_STR
"set BGP community list (for deletion)\n"
@@ -5649,7 +5649,7 @@ ALIAS_YANG (no_set_lcommunity1,
DEFPY_YANG (set_lcommunity_delete,
set_lcommunity_delete_cmd,
- "set large-comm-list <(1-99)|(100-500)|WORD> delete",
+ "set large-comm-list <(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> delete",
SET_STR
"set BGP large community list (for deletion)\n"
"Large Community-list number (standard)\n"
@@ -5675,7 +5675,7 @@ DEFPY_YANG (set_lcommunity_delete,
DEFUN_YANG (no_set_lcommunity_delete,
no_set_lcommunity_delete_cmd,
- "no set large-comm-list <(1-99)|(100-500)|WORD> [delete]",
+ "no set large-comm-list <(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> [delete]",
NO_STR
SET_STR
"set BGP large community list (for deletion)\n"
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 8e2044fd8a..772e20dc85 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -10241,6 +10241,7 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
count = 0; /* Reset the value as its used again */
filtered_count = 0;
+ dn_count = 0;
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
continue;
@@ -19061,7 +19062,7 @@ static void community_list_perror(struct vty *vty, int ret)
/*community-list standard */
DEFUN (community_list_standard,
bgp_community_list_standard_cmd,
- "bgp community-list <(1-99)|standard WORD> [seq (0-4294967295)] <deny|permit> AA:NN...",
+ "bgp community-list <(1-99)|standard COMMUNITY_LIST_NAME> [seq (0-4294967295)] <deny|permit> AA:NN...",
BGP_STR
COMMUNITY_LIST_STR
"Community list number (standard)\n"
@@ -19085,7 +19086,7 @@ DEFUN (community_list_standard,
idx = 0;
argv_find(argv, argc, "(1-99)", &idx);
- argv_find(argv, argc, "WORD", &idx);
+ argv_find(argv, argc, "COMMUNITY_LIST_NAME", &idx);
cl_name_or_number = argv[idx]->arg;
direct = argv_find(argv, argc, "permit", &idx) ? COMMUNITY_PERMIT
: COMMUNITY_DENY;
@@ -19108,7 +19109,7 @@ DEFUN (community_list_standard,
DEFUN (no_community_list_standard_all,
no_bgp_community_list_standard_all_cmd,
- "no bgp community-list <(1-99)|standard WORD> [seq (0-4294967295)] <deny|permit> AA:NN...",
+ "no bgp community-list <(1-99)|standard COMMUNITY_LIST_NAME> [seq (0-4294967295)] <deny|permit> AA:NN...",
NO_STR
BGP_STR
COMMUNITY_LIST_STR
@@ -19148,7 +19149,7 @@ DEFUN (no_community_list_standard_all,
idx = 0;
argv_find(argv, argc, "(1-99)", &idx);
- argv_find(argv, argc, "WORD", &idx);
+ argv_find(argv, argc, "COMMUNITY_LIST_NAME", &idx);
cl_name_or_number = argv[idx]->arg;
int ret = community_list_unset(bgp_clist, cl_name_or_number, str, seq,
@@ -19165,7 +19166,7 @@ DEFUN (no_community_list_standard_all,
}
ALIAS(no_community_list_standard_all, no_bgp_community_list_standard_all_list_cmd,
- "no bgp community-list <(1-99)|standard WORD>",
+ "no bgp community-list <(1-99)|standard COMMUNITY_LIST_NAME>",
NO_STR BGP_STR COMMUNITY_LIST_STR
"Community list number (standard)\n"
"Add an standard community-list entry\n"
@@ -19174,7 +19175,7 @@ ALIAS(no_community_list_standard_all, no_bgp_community_list_standard_all_list_cm
/*community-list expanded */
DEFUN (community_list_expanded_all,
bgp_community_list_expanded_all_cmd,
- "bgp community-list <(100-500)|expanded WORD> [seq (0-4294967295)] <deny|permit> AA:NN...",
+ "bgp community-list <(100-500)|expanded COMMUNITY_LIST_NAME> [seq (0-4294967295)] <deny|permit> AA:NN...",
BGP_STR
COMMUNITY_LIST_STR
"Community list number (expanded)\n"
@@ -19199,7 +19200,7 @@ DEFUN (community_list_expanded_all,
idx = 0;
argv_find(argv, argc, "(100-500)", &idx);
- argv_find(argv, argc, "WORD", &idx);
+ argv_find(argv, argc, "COMMUNITY_LIST_NAME", &idx);
cl_name_or_number = argv[idx]->arg;
direct = argv_find(argv, argc, "permit", &idx) ? COMMUNITY_PERMIT
: COMMUNITY_DENY;
@@ -19222,7 +19223,7 @@ DEFUN (community_list_expanded_all,
DEFUN (no_community_list_expanded_all,
no_bgp_community_list_expanded_all_cmd,
- "no bgp community-list <(100-500)|expanded WORD> [seq (0-4294967295)] <deny|permit> AA:NN...",
+ "no bgp community-list <(100-500)|expanded COMMUNITY_LIST_NAME> [seq (0-4294967295)] <deny|permit> AA:NN...",
NO_STR
BGP_STR
COMMUNITY_LIST_STR
@@ -19262,7 +19263,7 @@ DEFUN (no_community_list_expanded_all,
idx = 0;
argv_find(argv, argc, "(100-500)", &idx);
- argv_find(argv, argc, "WORD", &idx);
+ argv_find(argv, argc, "COMMUNITY_LIST_NAME", &idx);
cl_name_or_number = argv[idx]->arg;
int ret = community_list_unset(bgp_clist, cl_name_or_number, str, seq,
@@ -19280,7 +19281,7 @@ DEFUN (no_community_list_expanded_all,
ALIAS(no_community_list_expanded_all,
no_bgp_community_list_expanded_all_list_cmd,
- "no bgp community-list <(100-500)|expanded WORD>",
+ "no bgp community-list <(100-500)|expanded COMMUNITY_LIST_NAME>",
NO_STR BGP_STR COMMUNITY_LIST_STR
"Community list number (expanded)\n"
"Add an expanded community-list entry\n"
@@ -19358,7 +19359,7 @@ DEFUN (show_community_list,
DEFUN (show_community_list_arg,
show_bgp_community_list_arg_cmd,
- "show bgp community-list <(1-500)|WORD> detail",
+ "show bgp community-list <(1-500)|COMMUNITY_LIST_NAME> detail",
SHOW_STR
BGP_STR
"List community-list\n"
@@ -19404,7 +19405,7 @@ static int lcommunity_list_set_vty(struct vty *vty, int argc,
/* All digit name check. */
idx = 0;
- argv_find(argv, argc, "WORD", &idx);
+ argv_find(argv, argc, "LCOMMUNITY_LIST_NAME", &idx);
argv_find(argv, argc, "(1-99)", &idx);
argv_find(argv, argc, "(100-500)", &idx);
cl_name = argv[idx]->arg;
@@ -19468,7 +19469,7 @@ static int lcommunity_list_unset_vty(struct vty *vty, int argc,
idx = 0;
argv_find(argv, argc, "(1-99)", &idx);
argv_find(argv, argc, "(100-500)", &idx);
- argv_find(argv, argc, "WORD", &idx);
+ argv_find(argv, argc, "LCOMMUNITY_LIST_NAME", &idx);
/* Unset community list. */
ret = lcommunity_list_unset(bgp_clist, argv[idx]->arg, str, seq, direct,
@@ -19524,7 +19525,7 @@ DEFUN (lcommunity_list_expanded,
DEFUN (lcommunity_list_name_standard,
bgp_lcommunity_list_name_standard_cmd,
- "bgp large-community-list standard WORD [seq (0-4294967295)] <deny|permit> AA:BB:CC...",
+ "bgp large-community-list standard LCOMMUNITY_LIST_NAME [seq (0-4294967295)] <deny|permit> AA:BB:CC...",
BGP_STR
LCOMMUNITY_LIST_STR
"Specify standard large-community-list\n"
@@ -19541,7 +19542,7 @@ DEFUN (lcommunity_list_name_standard,
DEFUN (lcommunity_list_name_expanded,
bgp_lcommunity_list_name_expanded_cmd,
- "bgp large-community-list expanded WORD [seq (0-4294967295)] <deny|permit> LINE...",
+ "bgp large-community-list expanded LCOMMUNITY_LIST_NAME [seq (0-4294967295)] <deny|permit> LINE...",
BGP_STR
LCOMMUNITY_LIST_STR
"Specify expanded large-community-list\n"
@@ -19558,7 +19559,7 @@ DEFUN (lcommunity_list_name_expanded,
DEFUN (no_lcommunity_list_all,
no_bgp_lcommunity_list_all_cmd,
- "no bgp large-community-list <(1-99)|(100-500)|WORD>",
+ "no bgp large-community-list <(1-99)|(100-500)|LCOMMUNITY_LIST_NAME>",
NO_STR
BGP_STR
LCOMMUNITY_LIST_STR
@@ -19572,7 +19573,7 @@ DEFUN (no_lcommunity_list_all,
DEFUN (no_lcommunity_list_name_standard_all,
no_bgp_lcommunity_list_name_standard_all_cmd,
- "no bgp large-community-list standard WORD",
+ "no bgp large-community-list standard LCOMMUNITY_LIST_NAME",
NO_STR
BGP_STR
LCOMMUNITY_LIST_STR
@@ -19585,7 +19586,7 @@ DEFUN (no_lcommunity_list_name_standard_all,
DEFUN (no_lcommunity_list_name_expanded_all,
no_bgp_lcommunity_list_name_expanded_all_cmd,
- "no bgp large-community-list expanded WORD",
+ "no bgp large-community-list expanded LCOMMUNITY_LIST_NAME",
NO_STR
BGP_STR
LCOMMUNITY_LIST_STR
@@ -19632,7 +19633,7 @@ DEFUN (no_lcommunity_list_expanded,
DEFUN (no_lcommunity_list_name_standard,
no_bgp_lcommunity_list_name_standard_cmd,
- "no bgp large-community-list standard WORD [seq (0-4294967295)] <deny|permit> AA:AA:NN...",
+ "no bgp large-community-list standard LCOMMUNITY_LIST_NAME [seq (0-4294967295)] <deny|permit> AA:AA:NN...",
NO_STR
BGP_STR
LCOMMUNITY_LIST_STR
@@ -19650,7 +19651,7 @@ DEFUN (no_lcommunity_list_name_standard,
DEFUN (no_lcommunity_list_name_expanded,
no_bgp_lcommunity_list_name_expanded_cmd,
- "no bgp large-community-list expanded WORD [seq (0-4294967295)] <deny|permit> LINE...",
+ "no bgp large-community-list expanded LCOMMUNITY_LIST_NAME [seq (0-4294967295)] <deny|permit> LINE...",
NO_STR
BGP_STR
LCOMMUNITY_LIST_STR
@@ -19724,7 +19725,7 @@ DEFUN (show_lcommunity_list,
DEFUN (show_lcommunity_list_arg,
show_bgp_lcommunity_list_arg_cmd,
- "show bgp large-community-list <(1-500)|WORD> detail",
+ "show bgp large-community-list <(1-500)|LCOMMUNITY_LIST_NAME> detail",
SHOW_STR
BGP_STR
"List large-community list\n"
@@ -19752,7 +19753,7 @@ DEFUN (show_lcommunity_list_arg,
DEFUN (extcommunity_list_standard,
bgp_extcommunity_list_standard_cmd,
- "bgp extcommunity-list <(1-99)|standard WORD> [seq (0-4294967295)] <deny|permit> AA:NN...",
+ "bgp extcommunity-list <(1-99)|standard EXTCOMMUNITY_LIST_NAME> [seq (0-4294967295)] <deny|permit> AA:NN...",
BGP_STR
EXTCOMMUNITY_LIST_STR
"Extended Community list number (standard)\n"
@@ -19772,7 +19773,7 @@ DEFUN (extcommunity_list_standard,
int idx = 0;
argv_find(argv, argc, "(1-99)", &idx);
- argv_find(argv, argc, "WORD", &idx);
+ argv_find(argv, argc, "EXTCOMMUNITY_LIST_NAME", &idx);
cl_number_or_name = argv[idx]->arg;
if (argv_find(argv, argc, "(0-4294967295)", &idx))
@@ -19798,7 +19799,7 @@ DEFUN (extcommunity_list_standard,
DEFUN (extcommunity_list_name_expanded,
bgp_extcommunity_list_name_expanded_cmd,
- "bgp extcommunity-list <(100-500)|expanded WORD> [seq (0-4294967295)] <deny|permit> LINE...",
+ "bgp extcommunity-list <(100-500)|expanded EXTCOMMUNITY_LIST_NAME> [seq (0-4294967295)] <deny|permit> LINE...",
BGP_STR
EXTCOMMUNITY_LIST_STR
"Extended Community list number (expanded)\n"
@@ -19817,7 +19818,7 @@ DEFUN (extcommunity_list_name_expanded,
int idx = 0;
argv_find(argv, argc, "(100-500)", &idx);
- argv_find(argv, argc, "WORD", &idx);
+ argv_find(argv, argc, "EXTCOMMUNITY_LIST_NAME", &idx);
cl_number_or_name = argv[idx]->arg;
if (argv_find(argv, argc, "(0-4294967295)", &idx))
@@ -19843,7 +19844,7 @@ DEFUN (extcommunity_list_name_expanded,
DEFUN (no_extcommunity_list_standard_all,
no_bgp_extcommunity_list_standard_all_cmd,
- "no bgp extcommunity-list <(1-99)|standard WORD> [seq (0-4294967295)] <deny|permit> AA:NN...",
+ "no bgp extcommunity-list <(1-99)|standard EXTCOMMUNITY_LIST_NAME> [seq (0-4294967295)] <deny|permit> AA:NN...",
NO_STR
BGP_STR
EXTCOMMUNITY_LIST_STR
@@ -19881,7 +19882,7 @@ DEFUN (no_extcommunity_list_standard_all,
idx = 0;
argv_find(argv, argc, "(1-99)", &idx);
- argv_find(argv, argc, "WORD", &idx);
+ argv_find(argv, argc, "EXTCOMMUNITY_LIST_NAME", &idx);
cl_number_or_name = argv[idx]->arg;
int ret = extcommunity_list_unset(bgp_clist, cl_number_or_name, str,
@@ -19899,7 +19900,7 @@ DEFUN (no_extcommunity_list_standard_all,
ALIAS(no_extcommunity_list_standard_all,
no_bgp_extcommunity_list_standard_all_list_cmd,
- "no bgp extcommunity-list <(1-99)|standard WORD>",
+ "no bgp extcommunity-list <(1-99)|standard EXTCOMMUNITY_LIST_NAME>",
NO_STR BGP_STR EXTCOMMUNITY_LIST_STR
"Extended Community list number (standard)\n"
"Specify standard extcommunity-list\n"
@@ -19907,7 +19908,7 @@ ALIAS(no_extcommunity_list_standard_all,
DEFUN (no_extcommunity_list_expanded_all,
no_bgp_extcommunity_list_expanded_all_cmd,
- "no bgp extcommunity-list <(100-500)|expanded WORD> [seq (0-4294967295)] <deny|permit> LINE...",
+ "no bgp extcommunity-list <(100-500)|expanded EXTCOMMUNITY_LIST_NAME> [seq (0-4294967295)] <deny|permit> LINE...",
NO_STR
BGP_STR
EXTCOMMUNITY_LIST_STR
@@ -19946,7 +19947,7 @@ DEFUN (no_extcommunity_list_expanded_all,
idx = 0;
argv_find(argv, argc, "(100-500)", &idx);
- argv_find(argv, argc, "WORD", &idx);
+ argv_find(argv, argc, "EXTCOMMUNITY_LIST_NAME", &idx);
cl_number_or_name = argv[idx]->arg;
int ret = extcommunity_list_unset(bgp_clist, cl_number_or_name, str,
@@ -19964,7 +19965,7 @@ DEFUN (no_extcommunity_list_expanded_all,
ALIAS(no_extcommunity_list_expanded_all,
no_bgp_extcommunity_list_expanded_all_list_cmd,
- "no bgp extcommunity-list <(100-500)|expanded WORD>",
+ "no bgp extcommunity-list <(100-500)|expanded EXTCOMMUNITY_LIST_NAME>",
NO_STR BGP_STR EXTCOMMUNITY_LIST_STR
"Extended Community list number (expanded)\n"
"Specify expanded extcommunity-list\n"
@@ -20025,7 +20026,7 @@ DEFUN (show_extcommunity_list,
DEFUN (show_extcommunity_list_arg,
show_bgp_extcommunity_list_arg_cmd,
- "show bgp extcommunity-list <(1-500)|WORD> detail",
+ "show bgp extcommunity-list <(1-500)|EXTCOMMUNITY_LIST_NAME> detail",
SHOW_STR
BGP_STR
"List extended-community list\n"
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 4f0501f4b9..6c9eb2972c 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -1489,6 +1489,8 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
if (is_add && CHECK_FLAG(bm->flags, BM_FLAG_SEND_EXTRA_DATA_TO_ZEBRA)) {
struct bgp_zebra_opaque bzo = {};
+ const char *reason =
+ bgp_path_selection_reason2str(dest->reason);
strlcpy(bzo.aspath, info->attr->aspath->str,
sizeof(bzo.aspath));
@@ -1502,6 +1504,9 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
strlcpy(bzo.lcommunity, info->attr->lcommunity->str,
sizeof(bzo.lcommunity));
+ strlcpy(bzo.selection_reason, reason,
+ sizeof(bzo.selection_reason));
+
SET_FLAG(api.message, ZAPI_MESSAGE_OPAQUE);
api.opaque.length = MIN(sizeof(struct bgp_zebra_opaque),
ZAPI_MESSAGE_OPAQUE_LENGTH);
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index b191029d2f..c5a5e49a48 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -4775,6 +4775,7 @@ int peer_ebgp_multihop_unset(struct peer *peer)
{
struct peer_group *group;
struct listnode *node, *nnode;
+ int ttl;
if (peer->sort == BGP_PEER_IBGP)
return 0;
@@ -4783,9 +4784,14 @@ int peer_ebgp_multihop_unset(struct peer *peer)
return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
if (peer_group_active(peer))
- peer->ttl = peer->group->conf->ttl;
+ ttl = peer->group->conf->ttl;
else
- peer->ttl = BGP_DEFAULT_TTL;
+ ttl = BGP_DEFAULT_TTL;
+
+ if (ttl == peer->ttl)
+ return 0;
+
+ peer->ttl = ttl;
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
diff --git a/doc/developer/lists.rst b/doc/developer/lists.rst
index 718e404764..dc8f236927 100644
--- a/doc/developer/lists.rst
+++ b/doc/developer/lists.rst
@@ -106,19 +106,25 @@ Functions provided:
| _init, _fini | yes | yes | yes | yes | yes |
+------------------------------------+------+------+------+---------+------------+
| _first, _next, _next_safe, | yes | yes | yes | yes | yes |
+| | | | | | |
| _const_first, _const_next | | | | | |
+------------------------------------+------+------+------+---------+------------+
| _swap_all | yes | yes | yes | yes | yes |
+------------------------------------+------+------+------+---------+------------+
+| _anywhere | yes | -- | -- | -- | -- |
++------------------------------------+------+------+------+---------+------------+
| _add_head, _add_tail, _add_after | yes | -- | -- | -- | -- |
+------------------------------------+------+------+------+---------+------------+
| _add | -- | yes | yes | yes | yes |
+------------------------------------+------+------+------+---------+------------+
+| _member | yes | yes | yes | yes | yes |
++------------------------------------+------+------+------+---------+------------+
| _del, _pop | yes | yes | yes | yes | yes |
+------------------------------------+------+------+------+---------+------------+
| _find, _const_find | -- | -- | yes | yes | -- |
+------------------------------------+------+------+------+---------+------------+
| _find_lt, _find_gteq, | -- | -- | -- | yes | yes |
+| | | | | | |
| _const_find_lt, _const_find_gteq | | | | | |
+------------------------------------+------+------+------+---------+------------+
| use with frr_each() macros | yes | yes | yes | yes | yes |
@@ -268,6 +274,16 @@ The following documentation assumes that a list has been defined using
outdated by the time this function returns and can therefore only be
used as an estimate.
+.. c:function:: bool Z_member(const struct Z_head *, const itemtype *)
+
+ Determines whether some item is a member of the given container. The
+ item must either be valid on some container, or set to all zeroes.
+
+ On some containers, if no faster way to determine membership is possible,
+ this is simply ``item == Z_find(head, item)``.
+
+ Not currently available for atomic containers.
+
.. c:function:: const itemtype *Z_const_first(const struct Z_head *)
.. c:function:: itemtype *Z_first(struct Z_head *)
@@ -396,6 +412,17 @@ are several functions exposed to insert data:
maybe flip the order of ``item`` & ``after``?
``Z_add_after(head, item, after)``
+.. c:function:: bool Z_anywhere(const itemtype *)
+
+ Returns whether an item is a member of *any* container of this type.
+ The item must either be valid on some container, or set to all zeroes.
+
+ Guaranteed to be fast (pointer compare or similar.)
+
+ Not currently available for sorted and atomic containers. Might be added
+ for sorted containers at some point (when needed.)
+
+
API for sorted structures
-------------------------
diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst
index 5fcddafaaa..1793ae3d27 100644
--- a/doc/user/bgp.rst
+++ b/doc/user/bgp.rst
@@ -1425,15 +1425,6 @@ Configuring Peers
Set description of the peer.
-.. clicmd:: neighbor PEER version VERSION
-
- Set up the neighbor's BGP version. `version` can be `4`, `4+` or `4-`. BGP
- version `4` is the default value used for BGP peering. BGP version `4+`
- means that the neighbor supports Multiprotocol Extensions for BGP-4. BGP
- version `4-` is similar but the neighbor speaks the old Internet-Draft
- revision 00's Multiprotocol Extensions for BGP-4. Some routing software is
- still using this version.
-
.. clicmd:: neighbor PEER interface IFNAME
When you connect to a BGP peer over an IPv6 link-local address, you have to
diff --git a/doc/user/pbr.rst b/doc/user/pbr.rst
index e59ed10896..29567bb709 100644
--- a/doc/user/pbr.rst
+++ b/doc/user/pbr.rst
@@ -154,6 +154,31 @@ end destination.
(ECN) field in the IP header; if this value matches then forward the packet
according to the nexthop(s) specified.
+
+.. clicmd:: set queue-id (1-65535)
+
+ Set the egress port queue identifier for matched packets. The Linux Kernel
+ provider does not currently support packet mangling, so this field will be
+ ignored unless another provider is used.
+
+.. clicmd:: set pcp (0-7)
+
+ Set the 802.1Q priority code point (PCP) for matched packets. A PCP of zero
+ is the defaul (nominally, "best effort"). The Linux Kernel provider does not
+ currently support packet mangling, so this field will be ignored unless
+ another provider is used.
+
+.. clicmd:: set vlan (1-4094)
+
+ Set the VLAN tag for matched packets. Identifiers 0 and 4095 are reserved.
+ The Linux Kernel provider does not currently support packet mangling, so
+ this field will be ignored unless another provider is used.
+
+.. clicmd:: strip vlan
+
+ Strip inner vlan tags from matched packets. The Linux Kernel provider does not currently support packet mangling, so this field will be ignored unless another provider is used. It is invalid to specify both a `strip` and `set
+ vlan` action.
+
.. clicmd:: set nexthop-group NAME
Use the nexthop-group NAME as the place to forward packets when the match
diff --git a/eigrpd/eigrp_cli.c b/eigrpd/eigrp_cli.c
index 533d7de2c2..329332f695 100644
--- a/eigrpd/eigrp_cli.c
+++ b/eigrpd/eigrp_cli.c
@@ -82,7 +82,7 @@ DEFPY_YANG(
return nb_cli_apply_changes_clear_pending(vty, NULL);
}
-void eigrp_cli_show_header(struct vty *vty, struct lyd_node *dnode,
+void eigrp_cli_show_header(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
const char *asn = yang_dnode_get_string(dnode, "./asn");
@@ -94,7 +94,7 @@ void eigrp_cli_show_header(struct vty *vty, struct lyd_node *dnode,
vty_out(vty, "\n");
}
-void eigrp_cli_show_end_header(struct vty *vty, struct lyd_node *dnode)
+void eigrp_cli_show_end_header(struct vty *vty, const struct lyd_node *dnode)
{
vty_out(vty, "exit\n");
vty_out(vty, "!\n");
@@ -128,7 +128,7 @@ DEFPY_YANG(
return nb_cli_apply_changes(vty, NULL);
}
-void eigrp_cli_show_router_id(struct vty *vty, struct lyd_node *dnode,
+void eigrp_cli_show_router_id(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
const char *router_id = yang_dnode_get_string(dnode, NULL);
@@ -157,7 +157,8 @@ DEFPY_YANG(
return nb_cli_apply_changes(vty, NULL);
}
-void eigrp_cli_show_passive_interface(struct vty *vty, struct lyd_node *dnode,
+void eigrp_cli_show_passive_interface(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
const char *ifname = yang_dnode_get_string(dnode, NULL);
@@ -200,7 +201,7 @@ DEFPY_YANG(
return nb_cli_apply_changes(vty, NULL);
}
-void eigrp_cli_show_active_time(struct vty *vty, struct lyd_node *dnode,
+void eigrp_cli_show_active_time(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
const char *timer = yang_dnode_get_string(dnode, NULL);
@@ -234,7 +235,7 @@ DEFPY_YANG(
return nb_cli_apply_changes(vty, NULL);
}
-void eigrp_cli_show_variance(struct vty *vty, struct lyd_node *dnode,
+void eigrp_cli_show_variance(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
const char *variance = yang_dnode_get_string(dnode, NULL);
@@ -269,7 +270,7 @@ DEFPY_YANG(
return nb_cli_apply_changes(vty, NULL);
}
-void eigrp_cli_show_maximum_paths(struct vty *vty, struct lyd_node *dnode,
+void eigrp_cli_show_maximum_paths(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
const char *maximum_paths = yang_dnode_get_string(dnode, NULL);
@@ -333,7 +334,7 @@ DEFPY_YANG(
return nb_cli_apply_changes(vty, NULL);
}
-void eigrp_cli_show_metrics(struct vty *vty, struct lyd_node *dnode,
+void eigrp_cli_show_metrics(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
const char *k1, *k2, *k3, *k4, *k5, *k6;
@@ -379,7 +380,7 @@ DEFPY_YANG(
return nb_cli_apply_changes(vty, NULL);
}
-void eigrp_cli_show_network(struct vty *vty, struct lyd_node *dnode,
+void eigrp_cli_show_network(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
const char *prefix = yang_dnode_get_string(dnode, NULL);
@@ -408,8 +409,8 @@ DEFPY_YANG(
return nb_cli_apply_changes(vty, NULL);
}
-void eigrp_cli_show_neighbor(struct vty *vty, struct lyd_node *dnode,
- bool show_defaults)
+void eigrp_cli_show_neighbor(struct vty *vty, const struct lyd_node *dnode,
+ bool show_defaults)
{
const char *prefix = yang_dnode_get_string(dnode, NULL);
@@ -468,7 +469,7 @@ DEFPY_YANG(
return nb_cli_apply_changes(vty, NULL);
}
-void eigrp_cli_show_redistribute(struct vty *vty, struct lyd_node *dnode,
+void eigrp_cli_show_redistribute(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
const char *proto = yang_dnode_get_string(dnode, "./protocol");
@@ -520,7 +521,7 @@ DEFPY_YANG(
return nb_cli_apply_changes(vty, NULL);
}
-void eigrp_cli_show_delay(struct vty *vty, struct lyd_node *dnode,
+void eigrp_cli_show_delay(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
const char *delay = yang_dnode_get_string(dnode, NULL);
@@ -558,7 +559,7 @@ DEFPY_YANG(
return nb_cli_apply_changes(vty, NULL);
}
-void eigrp_cli_show_bandwidth(struct vty *vty, struct lyd_node *dnode,
+void eigrp_cli_show_bandwidth(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
const char *bandwidth = yang_dnode_get_string(dnode, NULL);
@@ -599,7 +600,8 @@ DEFPY_YANG(
}
-void eigrp_cli_show_hello_interval(struct vty *vty, struct lyd_node *dnode,
+void eigrp_cli_show_hello_interval(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
const char *hello = yang_dnode_get_string(dnode, NULL);
@@ -639,7 +641,7 @@ DEFPY_YANG(
return nb_cli_apply_changes(vty, NULL);
}
-void eigrp_cli_show_hold_time(struct vty *vty, struct lyd_node *dnode,
+void eigrp_cli_show_hold_time(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
const char *holdtime = yang_dnode_get_string(dnode, NULL);
@@ -701,10 +703,12 @@ DEFPY_YANG(
return nb_cli_apply_changes(vty, NULL);
}
-void eigrp_cli_show_summarize_address(struct vty *vty, struct lyd_node *dnode,
+void eigrp_cli_show_summarize_address(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
- const struct lyd_node *instance = yang_dnode_get_parent(dnode, "instance");
+ const struct lyd_node *instance =
+ yang_dnode_get_parent(dnode, "instance");
uint16_t asn = yang_dnode_get_uint16(instance, "./asn");
const char *summarize_address = yang_dnode_get_string(dnode, NULL);
@@ -765,10 +769,12 @@ DEFPY_YANG(
return nb_cli_apply_changes(vty, NULL);
}
-void eigrp_cli_show_authentication(struct vty *vty, struct lyd_node *dnode,
+void eigrp_cli_show_authentication(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
- const struct lyd_node *instance = yang_dnode_get_parent(dnode, "instance");
+ const struct lyd_node *instance =
+ yang_dnode_get_parent(dnode, "instance");
uint16_t asn = yang_dnode_get_uint16(instance, "./asn");
const char *crypt = yang_dnode_get_string(dnode, NULL);
@@ -824,10 +830,11 @@ DEFPY_YANG(
return nb_cli_apply_changes(vty, NULL);
}
-void eigrp_cli_show_keychain(struct vty *vty, struct lyd_node *dnode,
+void eigrp_cli_show_keychain(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
- const struct lyd_node *instance = yang_dnode_get_parent(dnode, "instance");
+ const struct lyd_node *instance =
+ yang_dnode_get_parent(dnode, "instance");
uint16_t asn = yang_dnode_get_uint16(instance, "./asn");
const char *keychain = yang_dnode_get_string(dnode, NULL);
@@ -850,7 +857,7 @@ static struct cmd_node eigrp_node = {
static int eigrp_config_write(struct vty *vty)
{
- struct lyd_node *dnode;
+ const struct lyd_node *dnode;
int written = 0;
dnode = yang_dnode_get(running_config->dnode, "/frr-eigrpd:eigrpd");
@@ -864,7 +871,7 @@ static int eigrp_config_write(struct vty *vty)
static int eigrp_write_interface(struct vty *vty)
{
- struct lyd_node *dnode;
+ const struct lyd_node *dnode;
struct interface *ifp;
struct vrf *vrf;
int written = 0;
diff --git a/eigrpd/eigrp_cli.h b/eigrpd/eigrp_cli.h
index c5f2fd8009..8b16dea39a 100644
--- a/eigrpd/eigrp_cli.h
+++ b/eigrpd/eigrp_cli.h
@@ -25,45 +25,56 @@
#define _EIGRP_CLI_H_
/*Prototypes*/
-extern void eigrp_cli_show_header(struct vty *vty, struct lyd_node *dnode,
+extern void eigrp_cli_show_header(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-extern void eigrp_cli_show_end_header(struct vty *vty, struct lyd_node *dnode);
-extern void eigrp_cli_show_router_id(struct vty *vty, struct lyd_node *dnode,
+extern void eigrp_cli_show_end_header(struct vty *vty,
+ const struct lyd_node *dnode);
+extern void eigrp_cli_show_router_id(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
extern void eigrp_cli_show_passive_interface(struct vty *vty,
- struct lyd_node *dnode,
+ const struct lyd_node *dnode,
bool show_defaults);
-extern void eigrp_cli_show_active_time(struct vty *vty, struct lyd_node *dnode,
+extern void eigrp_cli_show_active_time(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-extern void eigrp_cli_show_variance(struct vty *vty, struct lyd_node *dnode,
+extern void eigrp_cli_show_variance(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
extern void eigrp_cli_show_maximum_paths(struct vty *vty,
- struct lyd_node *dnode,
+ const struct lyd_node *dnode,
bool show_defaults);
-extern void eigrp_cli_show_metrics(struct vty *vty, struct lyd_node *dnode,
+extern void eigrp_cli_show_metrics(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-extern void eigrp_cli_show_network(struct vty *vty, struct lyd_node *dnode,
+extern void eigrp_cli_show_network(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-extern void eigrp_cli_show_neighbor(struct vty *vty, struct lyd_node *dnode,
+extern void eigrp_cli_show_neighbor(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-extern void eigrp_cli_show_redistribute(struct vty *vty, struct lyd_node *dnode,
+extern void eigrp_cli_show_redistribute(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-extern void eigrp_cli_show_delay(struct vty *vty, struct lyd_node *dnode,
+extern void eigrp_cli_show_delay(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-extern void eigrp_cli_show_bandwidth(struct vty *vty, struct lyd_node *dnode,
+extern void eigrp_cli_show_bandwidth(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
extern void eigrp_cli_show_hello_interval(struct vty *vty,
- struct lyd_node *dnode,
+ const struct lyd_node *dnode,
bool show_defaults);
-extern void eigrp_cli_show_hold_time(struct vty *vty, struct lyd_node *dnode,
+extern void eigrp_cli_show_hold_time(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
extern void eigrp_cli_show_summarize_address(struct vty *vty,
- struct lyd_node *dnode,
+ const struct lyd_node *dnode,
bool show_defaults);
extern void eigrp_cli_show_authentication(struct vty *vty,
- struct lyd_node *dnode,
+ const struct lyd_node *dnode,
bool show_defaults);
-extern void eigrp_cli_show_keychain(struct vty *vty, struct lyd_node *dnode,
+extern void eigrp_cli_show_keychain(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
extern void eigrp_cli_init(void);
diff --git a/include/linux/nexthop.h b/include/linux/nexthop.h
index ee2a15b9c7..d8ffa8c9ca 100644
--- a/include/linux/nexthop.h
+++ b/include/linux/nexthop.h
@@ -1,12 +1,9 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-#ifndef _LINUX_NEXTHOP_H
-#define _LINUX_NEXTHOP_H
+#ifndef _UAPI_LINUX_NEXTHOP_H
+#define _UAPI_LINUX_NEXTHOP_H
#include <linux/types.h>
-#define RTM_NHA(h) ((struct rtattr *)(((char *)(h)) + \
- NLMSG_ALIGN(sizeof(struct nhmsg))))
-
struct nhmsg {
unsigned char nh_family;
unsigned char nh_scope; /* return only */
@@ -15,6 +12,7 @@ struct nhmsg {
unsigned int nh_flags; /* RTNH_F flags */
};
+/* entry in a nexthop group */
struct nexthop_grp {
__u32 id; /* nexthop id - must exist */
__u8 weight; /* weight of this nexthop */
@@ -23,7 +21,10 @@ struct nexthop_grp {
};
enum {
- NEXTHOP_GRP_TYPE_MPATH, /* default type if not specified */
+ NEXTHOP_GRP_TYPE_MPATH, /* hash-threshold nexthop group
+ * default type if not specified
+ */
+ NEXTHOP_GRP_TYPE_RES, /* resilient nexthop group */
__NEXTHOP_GRP_TYPE_MAX,
};
@@ -50,10 +51,54 @@ enum {
*/
NHA_GROUPS, /* flag; only return nexthop groups in dump */
NHA_MASTER, /* u32; only return nexthops with given master dev */
- NHA_FDB, /* nexthop belongs to a bridge fdb */
+
+ NHA_FDB, /* flag; nexthop belongs to a bridge fdb */
+ /* if NHA_FDB is added, OIF, BLACKHOLE, ENCAP cannot be set */
+
+ /* nested; resilient nexthop group attributes */
+ NHA_RES_GROUP,
+ /* nested; nexthop bucket attributes */
+ NHA_RES_BUCKET,
__NHA_MAX,
};
#define NHA_MAX (__NHA_MAX - 1)
+
+enum {
+ NHA_RES_GROUP_UNSPEC,
+ /* Pad attribute for 64-bit alignment. */
+ NHA_RES_GROUP_PAD = NHA_RES_GROUP_UNSPEC,
+
+ /* u16; number of nexthop buckets in a resilient nexthop group */
+ NHA_RES_GROUP_BUCKETS,
+ /* clock_t as u32; nexthop bucket idle timer (per-group) */
+ NHA_RES_GROUP_IDLE_TIMER,
+ /* clock_t as u32; nexthop unbalanced timer */
+ NHA_RES_GROUP_UNBALANCED_TIMER,
+ /* clock_t as u64; nexthop unbalanced time */
+ NHA_RES_GROUP_UNBALANCED_TIME,
+
+ __NHA_RES_GROUP_MAX,
+};
+
+#define NHA_RES_GROUP_MAX (__NHA_RES_GROUP_MAX - 1)
+
+enum {
+ NHA_RES_BUCKET_UNSPEC,
+ /* Pad attribute for 64-bit alignment. */
+ NHA_RES_BUCKET_PAD = NHA_RES_BUCKET_UNSPEC,
+
+ /* u16; nexthop bucket index */
+ NHA_RES_BUCKET_INDEX,
+ /* clock_t as u64; nexthop bucket idle time */
+ NHA_RES_BUCKET_IDLE_TIME,
+ /* u32; nexthop id assigned to the nexthop bucket */
+ NHA_RES_BUCKET_NH_ID,
+
+ __NHA_RES_BUCKET_MAX,
+};
+
+#define NHA_RES_BUCKET_MAX (__NHA_RES_BUCKET_MAX - 1)
+
#endif
diff --git a/isisd/isis_cli.c b/isisd/isis_cli.c
index f48b142b1a..195a3fcd2f 100644
--- a/isisd/isis_cli.c
+++ b/isisd/isis_cli.c
@@ -131,7 +131,7 @@ DEFPY_YANG(no_router_isis, no_router_isis_cmd,
vrf_name);
}
-void cli_show_router_isis(struct vty *vty, struct lyd_node *dnode,
+void cli_show_router_isis(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
const char *vrf = NULL;
@@ -146,7 +146,7 @@ void cli_show_router_isis(struct vty *vty, struct lyd_node *dnode,
vty_out(vty, "\n");
}
-void cli_show_router_isis_end(struct vty *vty, struct lyd_node *dnode)
+void cli_show_router_isis_end(struct vty *vty, const struct lyd_node *dnode)
{
vty_out(vty, "exit\n");
}
@@ -165,7 +165,7 @@ DEFPY_YANG(ip_router_isis, ip_router_isis_cmd,
"Routing process tag\n")
{
char inst_xpath[XPATH_MAXLEN];
- struct lyd_node *if_dnode, *inst_dnode;
+ const struct lyd_node *if_dnode, *inst_dnode;
const char *circ_type = NULL;
const char *vrf_name;
struct interface *ifp;
@@ -222,7 +222,7 @@ DEFPY_YANG(ip6_router_isis, ip6_router_isis_cmd,
"Routing process tag\n")
{
char inst_xpath[XPATH_MAXLEN];
- struct lyd_node *if_dnode, *inst_dnode;
+ const struct lyd_node *if_dnode, *inst_dnode;
const char *circ_type = NULL;
const char *vrf_name;
struct interface *ifp;
@@ -321,7 +321,7 @@ ALIAS_HIDDEN(no_ip_router_isis, no_ip_router_isis_vrf_cmd,
"Routing process tag\n"
VRF_CMD_HELP_STR)
-void cli_show_ip_isis_ipv4(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_ipv4(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
if (!yang_dnode_get_bool(dnode, NULL))
@@ -330,7 +330,7 @@ void cli_show_ip_isis_ipv4(struct vty *vty, struct lyd_node *dnode,
yang_dnode_get_string(dnode, "../area-tag"));
}
-void cli_show_ip_isis_ipv6(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_ipv6(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
if (!yang_dnode_get_bool(dnode, NULL))
@@ -395,7 +395,8 @@ DEFPY_YANG(isis_bfd_profile,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_ip_isis_bfd_monitoring(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_bfd_monitoring(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
if (!yang_dnode_get_bool(dnode, "./enabled")) {
@@ -424,7 +425,7 @@ DEFPY_YANG(net, net_cmd, "[no] net WORD",
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_isis_area_address(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_area_address(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " net %s\n", yang_dnode_get_string(dnode, NULL));
@@ -459,7 +460,7 @@ DEFPY_YANG(no_is_type, no_is_type_cmd,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_isis_is_type(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_is_type(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
int is_type = yang_dnode_get_enum(dnode, NULL);
@@ -491,7 +492,8 @@ DEFPY_YANG(dynamic_hostname, dynamic_hostname_cmd, "[no] hostname dynamic",
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_isis_dynamic_hostname(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_dynamic_hostname(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
if (!yang_dnode_get_bool(dnode, NULL))
@@ -513,7 +515,7 @@ DEFPY_YANG(set_overload_bit, set_overload_bit_cmd, "[no] set-overload-bit",
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_isis_overload(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_overload(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
if (!yang_dnode_get_bool(dnode, NULL))
@@ -552,7 +554,7 @@ DEFPY_YANG(attached_bit_send, attached_bit_send_cmd, "[no] attached-bit send",
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_isis_attached_send(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_attached_send(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
if (!yang_dnode_get_bool(dnode, NULL))
@@ -577,7 +579,8 @@ DEFPY_YANG(
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_isis_attached_receive(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_attached_receive(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
if (!yang_dnode_get_bool(dnode, NULL))
@@ -613,7 +616,7 @@ DEFPY_YANG(no_metric_style, no_metric_style_cmd,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_isis_metric_style(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_metric_style(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
int metric = yang_dnode_get_enum(dnode, NULL);
@@ -656,7 +659,7 @@ DEFPY_YANG(area_passwd, area_passwd_cmd,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_isis_area_pwd(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_area_pwd(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
const char *snp;
@@ -706,7 +709,7 @@ DEFPY_YANG(no_area_passwd, no_area_passwd_cmd,
return nb_cli_apply_changes(vty, "./%s", cmd);
}
-void cli_show_isis_domain_pwd(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_domain_pwd(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
const char *snp;
@@ -931,7 +934,7 @@ DEFPY_YANG(no_lsp_timers, no_lsp_timers_cmd,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_isis_lsp_timers(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_lsp_timers(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
const char *l1_refresh =
@@ -983,7 +986,7 @@ DEFPY_YANG(no_area_lsp_mtu, no_area_lsp_mtu_cmd, "no lsp-mtu [(128-4352)]",
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_isis_lsp_mtu(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_lsp_mtu(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " lsp-mtu %s\n", yang_dnode_get_string(dnode, NULL));
@@ -1027,7 +1030,8 @@ DEFPY_YANG(no_spf_interval, no_spf_interval_cmd,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_isis_spf_min_interval(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_spf_min_interval(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
const char *l1 = yang_dnode_get_string(dnode, "./level-1");
@@ -1095,7 +1099,8 @@ DEFPY_YANG(no_spf_delay_ietf, no_spf_delay_ietf_cmd,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_isis_spf_ietf_backoff(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_spf_ietf_backoff(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty,
@@ -1147,7 +1152,8 @@ DEFPY_YANG(no_spf_prefix_priority, no_spf_prefix_priority_cmd,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_isis_spf_prefix_priority(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_spf_prefix_priority(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " spf prefix-priority %s %s\n",
@@ -1167,7 +1173,7 @@ DEFPY_YANG(area_purge_originator, area_purge_originator_cmd, "[no] purge-origina
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_isis_purge_origin(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_purge_origin(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
if (!yang_dnode_get_bool(dnode, NULL))
@@ -1198,7 +1204,7 @@ DEFPY_YANG(no_isis_mpls_te_on, no_isis_mpls_te_on_cmd, "no mpls-te [on]",
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_isis_mpls_te(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_mpls_te(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " mpls-te on\n");
@@ -1231,7 +1237,8 @@ DEFPY_YANG(no_isis_mpls_te_router_addr, no_isis_mpls_te_router_addr_cmd,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_isis_mpls_te_router_addr(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_mpls_te_router_addr(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " mpls-te router-address %s\n",
@@ -1292,7 +1299,7 @@ DEFPY_YANG(isis_default_originate, isis_default_originate_cmd,
level);
}
-static void vty_print_def_origin(struct vty *vty, struct lyd_node *dnode,
+static void vty_print_def_origin(struct vty *vty, const struct lyd_node *dnode,
const char *family, const char *level,
bool show_defaults)
{
@@ -1310,7 +1317,8 @@ static void vty_print_def_origin(struct vty *vty, struct lyd_node *dnode,
vty_out(vty, "\n");
}
-void cli_show_isis_def_origin_ipv4(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_def_origin_ipv4(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
const char *level = yang_dnode_get_string(dnode, "./level");
@@ -1318,7 +1326,8 @@ void cli_show_isis_def_origin_ipv4(struct vty *vty, struct lyd_node *dnode,
vty_print_def_origin(vty, dnode, "ipv4", level, show_defaults);
}
-void cli_show_isis_def_origin_ipv6(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_def_origin_ipv6(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
const char *level = yang_dnode_get_string(dnode, "./level");
@@ -1361,7 +1370,8 @@ DEFPY_YANG(isis_redistribute, isis_redistribute_cmd,
level);
}
-static void vty_print_redistribute(struct vty *vty, struct lyd_node *dnode,
+static void vty_print_redistribute(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults, const char *family)
{
const char *level = yang_dnode_get_string(dnode, "./level");
@@ -1377,12 +1387,14 @@ static void vty_print_redistribute(struct vty *vty, struct lyd_node *dnode,
vty_out(vty, "\n");
}
-void cli_show_isis_redistribute_ipv4(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_redistribute_ipv4(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
vty_print_redistribute(vty, dnode, show_defaults, "ipv4");
}
-void cli_show_isis_redistribute_ipv6(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_redistribute_ipv6(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
vty_print_redistribute(vty, dnode, show_defaults, "ipv6");
@@ -1435,7 +1447,8 @@ DEFPY_YANG(isis_topology, isis_topology_cmd,
return nb_cli_apply_changes(vty, base_xpath);
}
-void cli_show_isis_mt_ipv4_multicast(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_mt_ipv4_multicast(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " topology ipv4-multicast");
@@ -1444,7 +1457,7 @@ void cli_show_isis_mt_ipv4_multicast(struct vty *vty, struct lyd_node *dnode,
vty_out(vty, "\n");
}
-void cli_show_isis_mt_ipv4_mgmt(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_mt_ipv4_mgmt(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " topology ipv4-mgmt");
@@ -1453,7 +1466,8 @@ void cli_show_isis_mt_ipv4_mgmt(struct vty *vty, struct lyd_node *dnode,
vty_out(vty, "\n");
}
-void cli_show_isis_mt_ipv6_unicast(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_mt_ipv6_unicast(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " topology ipv6-unicast");
@@ -1462,7 +1476,8 @@ void cli_show_isis_mt_ipv6_unicast(struct vty *vty, struct lyd_node *dnode,
vty_out(vty, "\n");
}
-void cli_show_isis_mt_ipv6_multicast(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_mt_ipv6_multicast(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " topology ipv6-multicast");
@@ -1471,7 +1486,7 @@ void cli_show_isis_mt_ipv6_multicast(struct vty *vty, struct lyd_node *dnode,
vty_out(vty, "\n");
}
-void cli_show_isis_mt_ipv6_mgmt(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_mt_ipv6_mgmt(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " topology ipv6-mgmt");
@@ -1480,7 +1495,7 @@ void cli_show_isis_mt_ipv6_mgmt(struct vty *vty, struct lyd_node *dnode,
vty_out(vty, "\n");
}
-void cli_show_isis_mt_ipv6_dstsrc(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_mt_ipv6_dstsrc(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " topology ipv6-dstsrc");
@@ -1517,7 +1532,7 @@ DEFPY_YANG (no_isis_sr_enable,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_isis_sr_enabled(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_sr_enabled(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
if (!yang_dnode_get_bool(dnode, NULL))
@@ -1585,7 +1600,7 @@ DEFPY_YANG(no_isis_sr_global_block_label_range,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_isis_label_blocks(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_label_blocks(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " segment-routing global-block %s %s",
@@ -1671,7 +1686,7 @@ DEFPY_YANG (no_isis_sr_node_msd,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_isis_node_msd(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_node_msd(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " segment-routing node-msd %s\n",
@@ -1748,7 +1763,7 @@ DEFPY_YANG (no_isis_sr_prefix_sid,
prefix_str);
}
-void cli_show_isis_prefix_sid(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_prefix_sid(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
const char *prefix;
@@ -1825,7 +1840,7 @@ DEFPY_YANG (isis_frr_lfa_priority_limit,
}
void cli_show_isis_frr_lfa_priority_limit(struct vty *vty,
- struct lyd_node *dnode,
+ const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " fast-reroute priority-limit %s %s\n",
@@ -1890,7 +1905,8 @@ DEFPY_YANG (isis_frr_lfa_tiebreaker,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_isis_frr_lfa_tiebreaker(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_frr_lfa_tiebreaker(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " fast-reroute lfa tiebreaker %s index %s %s\n",
@@ -1938,7 +1954,8 @@ DEFPY_YANG (isis_frr_lfa_load_sharing,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_isis_frr_lfa_load_sharing(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_frr_lfa_load_sharing(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
if (!yang_dnode_get_bool(dnode, NULL))
@@ -1996,7 +2013,8 @@ DEFPY_YANG (no_isis_frr_remote_lfa_plist,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_isis_frr_remote_lfa_plist(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_frr_remote_lfa_plist(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " fast-reroute remote-lfa prefix-list %s %s\n",
@@ -2018,7 +2036,7 @@ DEFPY_YANG(isis_passive, isis_passive_cmd, "[no] isis passive",
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_ip_isis_passive(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_passive(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
if (!yang_dnode_get_bool(dnode, NULL))
@@ -2061,7 +2079,7 @@ DEFPY_YANG(no_isis_passwd, no_isis_passwd_cmd, "no isis password [<md5|clear> WO
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_ip_isis_password(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_password(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " isis password %s %s\n",
@@ -2109,7 +2127,7 @@ DEFPY_YANG(no_isis_metric, no_isis_metric_cmd,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_ip_isis_metric(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_metric(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
const char *l1 = yang_dnode_get_string(dnode, "./level-1");
@@ -2167,7 +2185,8 @@ DEFPY_YANG(no_isis_hello_interval, no_isis_hello_interval_cmd,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_ip_isis_hello_interval(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_hello_interval(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
const char *l1 = yang_dnode_get_string(dnode, "./level-1");
@@ -2225,7 +2244,7 @@ DEFPY_YANG(no_isis_hello_multiplier, no_isis_hello_multiplier_cmd,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_ip_isis_hello_multi(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_hello_multi(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
const char *l1 = yang_dnode_get_string(dnode, "./level-1");
@@ -2255,7 +2274,8 @@ DEFPY_YANG(isis_threeway_adj, isis_threeway_adj_cmd, "[no] isis three-way-handsh
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_ip_isis_threeway_shake(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_threeway_shake(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
if (yang_dnode_get_bool(dnode, NULL))
@@ -2278,7 +2298,8 @@ DEFPY_YANG(isis_hello_padding, isis_hello_padding_cmd, "[no] isis hello padding"
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_ip_isis_hello_padding(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_hello_padding(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
if (!yang_dnode_get_bool(dnode, NULL))
@@ -2331,7 +2352,8 @@ DEFPY_YANG(no_csnp_interval, no_csnp_interval_cmd,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_ip_isis_csnp_interval(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_csnp_interval(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
const char *l1 = yang_dnode_get_string(dnode, "./level-1");
@@ -2389,7 +2411,8 @@ DEFPY_YANG(no_psnp_interval, no_psnp_interval_cmd,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_ip_isis_psnp_interval(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_psnp_interval(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
const char *l1 = yang_dnode_get_string(dnode, "./level-1");
@@ -2432,7 +2455,8 @@ DEFPY_YANG(circuit_topology, circuit_topology_cmd,
vty, "./frr-isisd:isis/multi-topology/%s", topology);
}
-void cli_show_ip_isis_mt_ipv4_unicast(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_mt_ipv4_unicast(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
if (!yang_dnode_get_bool(dnode, NULL))
@@ -2440,7 +2464,8 @@ void cli_show_ip_isis_mt_ipv4_unicast(struct vty *vty, struct lyd_node *dnode,
vty_out(vty, " isis topology ipv4-unicast\n");
}
-void cli_show_ip_isis_mt_ipv4_multicast(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_mt_ipv4_multicast(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
if (!yang_dnode_get_bool(dnode, NULL))
@@ -2448,7 +2473,8 @@ void cli_show_ip_isis_mt_ipv4_multicast(struct vty *vty, struct lyd_node *dnode,
vty_out(vty, " isis topology ipv4-multicast\n");
}
-void cli_show_ip_isis_mt_ipv4_mgmt(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_mt_ipv4_mgmt(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
if (!yang_dnode_get_bool(dnode, NULL))
@@ -2456,7 +2482,8 @@ void cli_show_ip_isis_mt_ipv4_mgmt(struct vty *vty, struct lyd_node *dnode,
vty_out(vty, " isis topology ipv4-mgmt\n");
}
-void cli_show_ip_isis_mt_ipv6_unicast(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_mt_ipv6_unicast(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
if (!yang_dnode_get_bool(dnode, NULL))
@@ -2464,7 +2491,8 @@ void cli_show_ip_isis_mt_ipv6_unicast(struct vty *vty, struct lyd_node *dnode,
vty_out(vty, " isis topology ipv6-unicast\n");
}
-void cli_show_ip_isis_mt_ipv6_multicast(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_mt_ipv6_multicast(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
if (!yang_dnode_get_bool(dnode, NULL))
@@ -2472,7 +2500,8 @@ void cli_show_ip_isis_mt_ipv6_multicast(struct vty *vty, struct lyd_node *dnode,
vty_out(vty, " isis topology ipv6-multicast\n");
}
-void cli_show_ip_isis_mt_ipv6_mgmt(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_mt_ipv6_mgmt(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
if (!yang_dnode_get_bool(dnode, NULL))
@@ -2480,7 +2509,8 @@ void cli_show_ip_isis_mt_ipv6_mgmt(struct vty *vty, struct lyd_node *dnode,
vty_out(vty, " isis topology ipv6-mgmt\n");
}
-void cli_show_ip_isis_mt_ipv6_dstsrc(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_mt_ipv6_dstsrc(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
if (!yang_dnode_get_bool(dnode, NULL))
@@ -2516,7 +2546,7 @@ DEFPY_YANG(no_isis_circuit_type, no_isis_circuit_type_cmd,
"Level-2 only adjacencies are formed\n")
{
char inst_xpath[XPATH_MAXLEN];
- struct lyd_node *if_dnode, *inst_dnode;
+ const struct lyd_node *if_dnode, *inst_dnode;
const char *vrf_name;
const char *tag;
const char *circ_type = NULL;
@@ -2554,7 +2584,7 @@ DEFPY_YANG(no_isis_circuit_type, no_isis_circuit_type_cmd,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_ip_isis_circ_type(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_circ_type(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
int level = yang_dnode_get_enum(dnode, NULL);
@@ -2588,7 +2618,8 @@ DEFPY_YANG(isis_network, isis_network_cmd, "[no] isis network point-to-point",
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_ip_isis_network_type(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_network_type(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
if (yang_dnode_get_enum(dnode, NULL) != CIRCUIT_T_P2P)
@@ -2637,7 +2668,7 @@ DEFPY_YANG(no_isis_priority, no_isis_priority_cmd,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_ip_isis_priority(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_priority(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
const char *l1 = yang_dnode_get_string(dnode, "./level-1");
@@ -2654,7 +2685,7 @@ void cli_show_ip_isis_priority(struct vty *vty, struct lyd_node *dnode,
/*
* XPath: /frr-interface:lib/interface/frr-isisd:isis/fast-reroute
*/
-void cli_show_ip_isis_frr(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_frr(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
bool l1_enabled, l2_enabled;
@@ -2832,7 +2863,8 @@ DEFPY(isis_lfa_exclude_interface, isis_lfa_exclude_interface_cmd,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_frr_lfa_exclude_interface(struct vty *vty, struct lyd_node *dnode,
+void cli_show_frr_lfa_exclude_interface(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " isis fast-reroute lfa %s exclude interface %s\n",
@@ -2930,7 +2962,8 @@ DEFPY(isis_remote_lfa_max_metric, isis_remote_lfa_max_metric_cmd,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_frr_remote_lfa_max_metric(struct vty *vty, struct lyd_node *dnode,
+void cli_show_frr_remote_lfa_max_metric(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " isis fast-reroute remote-lfa maximum-metric %s %s\n",
@@ -3028,7 +3061,7 @@ DEFPY_YANG(log_adj_changes, log_adj_changes_cmd, "[no] log-adjacency-changes",
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_isis_log_adjacency(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_log_adjacency(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
if (!yang_dnode_get_bool(dnode, NULL))
@@ -3055,7 +3088,7 @@ DEFPY(no_isis_mpls_ldp_sync, no_isis_mpls_ldp_sync_cmd, "no mpls ldp-sync",
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_isis_mpls_ldp_sync(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_mpls_ldp_sync(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " mpls ldp-sync\n");
@@ -3084,7 +3117,7 @@ DEFPY(no_isis_mpls_ldp_sync_holddown, no_isis_mpls_ldp_sync_holddown_cmd,
}
void cli_show_isis_mpls_ldp_sync_holddown(struct vty *vty,
- struct lyd_node *dnode,
+ const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " mpls ldp-sync holddown %s\n",
@@ -3114,7 +3147,8 @@ DEFPY(isis_mpls_if_ldp_sync, isis_mpls_if_ldp_sync_cmd,
}
-void cli_show_isis_mpls_if_ldp_sync(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_mpls_if_ldp_sync(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
if (!yang_dnode_get_bool(dnode, NULL))
@@ -3165,7 +3199,7 @@ DEFPY(no_isis_mpls_if_ldp_sync_holddown, no_isis_mpls_if_ldp_sync_holddown_cmd,
}
void cli_show_isis_mpls_if_ldp_sync_holddown(struct vty *vty,
- struct lyd_node *dnode,
+ const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " isis mpls ldp-sync holddown %s\n",
diff --git a/isisd/isis_nb.h b/isisd/isis_nb.h
index 4680dd5ded..ee7904163c 100644
--- a/isisd/isis_nb.h
+++ b/isisd/isis_nb.h
@@ -413,141 +413,174 @@ void isis_instance_segment_routing_prefix_sid_map_prefix_sid_apply_finish(
struct nb_cb_apply_finish_args *args);
/* Optional 'cli_show' callbacks. */
-void cli_show_router_isis(struct vty *vty, struct lyd_node *dnode,
+void cli_show_router_isis(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_router_isis_end(struct vty *vty, struct lyd_node *dnode);
-void cli_show_ip_isis_ipv4(struct vty *vty, struct lyd_node *dnode,
+void cli_show_router_isis_end(struct vty *vty, const struct lyd_node *dnode);
+void cli_show_ip_isis_ipv4(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_ip_isis_ipv6(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_ipv6(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_ip_isis_bfd_monitoring(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_bfd_monitoring(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_isis_area_address(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_area_address(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_isis_is_type(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_is_type(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_isis_dynamic_hostname(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_dynamic_hostname(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_isis_attached_send(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_attached_send(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_isis_attached_receive(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_attached_receive(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_isis_overload(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_overload(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_isis_metric_style(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_metric_style(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_isis_area_pwd(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_area_pwd(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_isis_domain_pwd(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_domain_pwd(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_isis_lsp_timers(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_lsp_timers(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_isis_lsp_mtu(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_lsp_mtu(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_isis_spf_min_interval(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_spf_min_interval(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_isis_spf_ietf_backoff(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_spf_ietf_backoff(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_isis_spf_prefix_priority(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_spf_prefix_priority(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_isis_purge_origin(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_purge_origin(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_isis_mpls_te(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_mpls_te(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_isis_mpls_te_router_addr(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_mpls_te_router_addr(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_isis_def_origin_ipv4(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_def_origin_ipv4(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_isis_def_origin_ipv6(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_def_origin_ipv6(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_isis_redistribute_ipv4(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_redistribute_ipv4(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_isis_redistribute_ipv6(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_redistribute_ipv6(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_isis_mt_ipv4_multicast(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_mt_ipv4_multicast(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_isis_mt_ipv4_mgmt(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_mt_ipv4_mgmt(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_isis_mt_ipv6_unicast(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_mt_ipv6_unicast(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_isis_mt_ipv6_multicast(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_mt_ipv6_multicast(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_isis_mt_ipv6_mgmt(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_mt_ipv6_mgmt(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_isis_mt_ipv6_dstsrc(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_mt_ipv6_dstsrc(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_isis_sr_enabled(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_sr_enabled(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_isis_label_blocks(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_label_blocks(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_isis_node_msd(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_node_msd(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_isis_prefix_sid(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_prefix_sid(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
void cli_show_isis_frr_lfa_priority_limit(struct vty *vty,
- struct lyd_node *dnode,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_isis_frr_lfa_tiebreaker(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_frr_lfa_tiebreaker(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_isis_frr_lfa_load_sharing(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_frr_lfa_load_sharing(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_isis_frr_remote_lfa_plist(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_frr_remote_lfa_plist(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_ip_isis_passive(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_passive(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_ip_isis_password(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_password(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_ip_isis_metric(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_metric(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_ip_isis_hello_interval(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_hello_interval(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_ip_isis_hello_multi(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_hello_multi(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_ip_isis_threeway_shake(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_threeway_shake(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_ip_isis_hello_padding(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_hello_padding(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_ip_isis_csnp_interval(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_csnp_interval(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_ip_isis_psnp_interval(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_psnp_interval(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_ip_isis_mt_ipv4_unicast(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_mt_ipv4_unicast(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_ip_isis_mt_ipv4_multicast(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_mt_ipv4_multicast(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_ip_isis_mt_ipv4_mgmt(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_mt_ipv4_mgmt(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_ip_isis_mt_ipv6_unicast(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_mt_ipv6_unicast(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_ip_isis_mt_ipv6_multicast(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_mt_ipv6_multicast(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_ip_isis_mt_ipv6_mgmt(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_mt_ipv6_mgmt(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_ip_isis_mt_ipv6_dstsrc(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_mt_ipv6_dstsrc(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_ip_isis_frr(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_frr(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_frr_lfa_exclude_interface(struct vty *vty, struct lyd_node *dnode,
+void cli_show_frr_lfa_exclude_interface(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_frr_remote_lfa_max_metric(struct vty *vty, struct lyd_node *dnode,
+void cli_show_frr_remote_lfa_max_metric(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_ip_isis_circ_type(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_circ_type(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_ip_isis_network_type(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_network_type(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_ip_isis_priority(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_isis_priority(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_isis_log_adjacency(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_log_adjacency(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_isis_mpls_ldp_sync(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_mpls_ldp_sync(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
void cli_show_isis_mpls_ldp_sync_holddown(struct vty *vty,
- struct lyd_node *dnode,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_isis_mpls_if_ldp_sync(struct vty *vty, struct lyd_node *dnode,
+void cli_show_isis_mpls_if_ldp_sync(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
void cli_show_isis_mpls_if_ldp_sync_holddown(struct vty *vty,
- struct lyd_node *dnode,
+ const struct lyd_node *dnode,
bool show_defaults);
/* Notifications. */
diff --git a/lib/command.c b/lib/command.c
index 53aa064705..ea66a17bb0 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -86,6 +86,9 @@ vector cmdvec = NULL;
/* Host information structure. */
struct host host;
+/* for vtysh, put together CLI trees only when switching into node */
+static bool defer_cli_tree;
+
/*
* Returns host.name if any, otherwise
* it returns the system hostname.
@@ -285,6 +288,11 @@ const char *cmd_prompt(enum node_type node)
return cnode->prompt;
}
+void cmd_defer_tree(bool val)
+{
+ defer_cli_tree = val;
+}
+
/* Install a command into a node. */
void _install_element(enum node_type ntype, const struct cmd_element *cmd)
{
@@ -319,20 +327,50 @@ void _install_element(enum node_type ntype, const struct cmd_element *cmd)
assert(hash_get(cnode->cmd_hash, (void *)cmd, hash_alloc_intern));
+ if (cnode->graph_built || !defer_cli_tree) {
+ struct graph *graph = graph_new();
+ struct cmd_token *token =
+ cmd_token_new(START_TKN, CMD_ATTR_NORMAL, NULL, NULL);
+ graph_new_node(graph, token,
+ (void (*)(void *)) & cmd_token_del);
+
+ cmd_graph_parse(graph, cmd);
+ cmd_graph_names(graph);
+ cmd_graph_merge(cnode->cmdgraph, graph, +1);
+ graph_delete_graph(graph);
+
+ cnode->graph_built = true;
+ }
+
+ vector_set(cnode->cmd_vector, (void *)cmd);
+
+ if (ntype == VIEW_NODE)
+ _install_element(ENABLE_NODE, cmd);
+}
+
+static void cmd_finalize_iter(struct hash_bucket *hb, void *arg)
+{
+ struct cmd_node *cnode = arg;
+ const struct cmd_element *cmd = hb->data;
struct graph *graph = graph_new();
struct cmd_token *token =
cmd_token_new(START_TKN, CMD_ATTR_NORMAL, NULL, NULL);
+
graph_new_node(graph, token, (void (*)(void *)) & cmd_token_del);
cmd_graph_parse(graph, cmd);
cmd_graph_names(graph);
cmd_graph_merge(cnode->cmdgraph, graph, +1);
graph_delete_graph(graph);
+}
- vector_set(cnode->cmd_vector, (void *)cmd);
+void cmd_finalize_node(struct cmd_node *cnode)
+{
+ if (cnode->graph_built)
+ return;
- if (ntype == VIEW_NODE)
- _install_element(ENABLE_NODE, cmd);
+ hash_iterate(cnode->cmd_hash, cmd_finalize_iter, cnode);
+ cnode->graph_built = true;
}
void uninstall_element(enum node_type ntype, const struct cmd_element *cmd)
@@ -368,15 +406,18 @@ void uninstall_element(enum node_type ntype, const struct cmd_element *cmd)
vector_unset_value(cnode->cmd_vector, (void *)cmd);
- struct graph *graph = graph_new();
- struct cmd_token *token =
- cmd_token_new(START_TKN, CMD_ATTR_NORMAL, NULL, NULL);
- graph_new_node(graph, token, (void (*)(void *)) & cmd_token_del);
+ if (cnode->graph_built) {
+ struct graph *graph = graph_new();
+ struct cmd_token *token =
+ cmd_token_new(START_TKN, CMD_ATTR_NORMAL, NULL, NULL);
+ graph_new_node(graph, token,
+ (void (*)(void *)) & cmd_token_del);
- cmd_graph_parse(graph, cmd);
- cmd_graph_names(graph);
- cmd_graph_merge(cnode->cmdgraph, graph, -1);
- graph_delete_graph(graph);
+ cmd_graph_parse(graph, cmd);
+ cmd_graph_names(graph);
+ cmd_graph_merge(cnode->cmdgraph, graph, -1);
+ graph_delete_graph(graph);
+ }
if (ntype == VIEW_NODE)
uninstall_element(ENABLE_NODE, cmd);
@@ -503,6 +544,8 @@ static int config_write_host(struct vty *vty)
static struct graph *cmd_node_graph(vector v, enum node_type ntype)
{
struct cmd_node *cnode = vector_slot(v, ntype);
+
+ cmd_finalize_node(cnode);
return cnode->cmdgraph;
}
@@ -1506,9 +1549,10 @@ int cmd_list_cmds(struct vty *vty, int do_permute)
{
struct cmd_node *node = vector_slot(cmdvec, vty->node);
- if (do_permute)
+ if (do_permute) {
+ cmd_finalize_node(node);
permute(vector_slot(node->cmdgraph->nodes, 0), vty);
- else {
+ } else {
/* loop over all commands at this node */
const struct cmd_element *element = NULL;
for (unsigned int i = 0; i < vector_active(node->cmd_vector);
@@ -1551,7 +1595,10 @@ DEFUN_HIDDEN(show_cli_graph,
"Dump current command space as DOT graph\n")
{
struct cmd_node *cn = vector_slot(cmdvec, vty->node);
- char *dot = cmd_graph_dump_dot(cn->cmdgraph);
+ char *dot;
+
+ cmd_finalize_node(cn);
+ dot = cmd_graph_dump_dot(cn->cmdgraph);
vty_out(vty, "%s\n", dot);
XFREE(MTYPE_TMP, dot);
diff --git a/lib/command.h b/lib/command.h
index e2eec1aac6..e2086701ad 100644
--- a/lib/command.h
+++ b/lib/command.h
@@ -210,6 +210,9 @@ struct cmd_node {
/* Hashed index of command node list, for de-dupping primarily */
struct hash *cmd_hash;
+
+ /* set as soon as any command is in cmdgraph */
+ bool graph_built;
};
/* Return value of the commands. */
@@ -526,6 +529,12 @@ extern void _install_element(enum node_type, const struct cmd_element *);
* deprecated/hidden) are not reversed. */
extern void uninstall_element(enum node_type, const struct cmd_element *);
+/* construct CLI tree only when entering nodes */
+extern void cmd_defer_tree(bool val);
+
+/* finish CLI tree for node when above is true (noop otherwise) */
+extern void cmd_finalize_node(struct cmd_node *node);
+
/* Concatenates argv[shift] through argv[argc-1] into a single NUL-terminated
string with a space between each element (allocated using
XMALLOC(MTYPE_TMP)). Returns NULL if shift >= argc. */
diff --git a/lib/command_graph.c b/lib/command_graph.c
index 15c8302e63..09d802e796 100644
--- a/lib/command_graph.c
+++ b/lib/command_graph.c
@@ -77,16 +77,17 @@ struct cmd_token *cmd_token_dup(struct cmd_token *token)
return copy;
}
-void cmd_token_varname_set(struct cmd_token *token, const char *varname)
+static void cmd_token_varname_do(struct cmd_token *token, const char *varname,
+ uint8_t varname_src)
{
- XFREE(MTYPE_CMD_VAR, token->varname);
- if (!varname) {
- token->varname = NULL;
+ if (token->varname_src >= varname_src)
return;
- }
+
+ XFREE(MTYPE_CMD_VAR, token->varname);
size_t len = strlen(varname), i;
token->varname = XMALLOC(MTYPE_CMD_VAR, len + 1);
+ token->varname_src = varname_src;
for (i = 0; i < len; i++)
switch (varname[i]) {
@@ -102,6 +103,80 @@ void cmd_token_varname_set(struct cmd_token *token, const char *varname)
token->varname[len] = '\0';
}
+void cmd_token_varname_set(struct cmd_token *token, const char *varname)
+{
+ if (varname) {
+ cmd_token_varname_do(token, varname, VARNAME_EXPLICIT);
+ return;
+ }
+ if (token->type == VARIABLE_TKN) {
+ if (strcmp(token->text, "WORD") && strcmp(token->text, "NAME"))
+ cmd_token_varname_do(token, token->text, VARNAME_TEXT);
+ }
+}
+
+static void cmd_token_varname_fork(struct graph_node *node,
+ struct cmd_token *prevtoken)
+{
+ for (size_t i = 0; i < vector_active(node->to); i++) {
+ struct graph_node *next = vector_slot(node->to, i);
+ struct cmd_token *nexttoken = next->data;
+
+ if (nexttoken->type == FORK_TKN) {
+ cmd_token_varname_fork(next, prevtoken);
+ continue;
+ }
+ if (nexttoken->varname)
+ continue;
+ if (!IS_VARYING_TOKEN(nexttoken->type))
+ continue;
+
+ cmd_token_varname_do(nexttoken, prevtoken->text, VARNAME_TEXT);
+ }
+}
+
+void cmd_token_varname_join(struct graph_node *join, const char *varname)
+{
+ if (!varname)
+ return;
+
+ for (size_t i = 0; i < vector_active(join->from); i++) {
+ struct graph_node *prev = vector_slot(join->from, i);
+ struct cmd_token *token = prev->data;
+
+ if (token->type == JOIN_TKN)
+ cmd_token_varname_join(prev, varname);
+ else if (token->type < SPECIAL_TKN)
+ cmd_token_varname_do(token, varname, VARNAME_EXPLICIT);
+ }
+}
+
+void cmd_token_varname_seqappend(struct graph_node *node)
+{
+ struct graph_node *prevnode = node;
+ struct cmd_token *token = node->data;
+ struct cmd_token *prevtoken;
+
+ if (token->type == WORD_TKN)
+ return;
+
+ do {
+ if (vector_active(prevnode->from) != 1)
+ return;
+
+ prevnode = vector_slot(prevnode->from, 0);
+ prevtoken = prevnode->data;
+ } while (prevtoken->type == FORK_TKN);
+
+ if (prevtoken->type != WORD_TKN)
+ return;
+
+ if (token->type == FORK_TKN)
+ cmd_token_varname_fork(node, prevtoken);
+ else
+ cmd_token_varname_do(token, prevtoken->text, VARNAME_TEXT);
+}
+
static bool cmd_nodes_link(struct graph_node *from, struct graph_node *to)
{
for (size_t i = 0; i < vector_active(from->to); i++)
@@ -357,72 +432,6 @@ void cmd_graph_merge(struct graph *old, struct graph *new, int direction)
vector_slot(new->nodes, 0), direction);
}
-static void cmd_node_names(struct graph_node *gn, struct graph_node *join,
- const char *prevname)
-{
- size_t i;
- struct cmd_token *tok = gn->data, *jointok;
- struct graph_node *stop = cmd_loopstop(gn);
-
- switch (tok->type) {
- case WORD_TKN:
- prevname = tok->text;
- break;
-
- case VARIABLE_TKN:
- if (!tok->varname && strcmp(tok->text, "WORD")
- && strcmp(tok->text, "NAME"))
- cmd_token_varname_set(tok, tok->text);
- /* fallthrough */
- case RANGE_TKN:
- case IPV4_TKN:
- case IPV4_PREFIX_TKN:
- case IPV6_TKN:
- case IPV6_PREFIX_TKN:
- case MAC_TKN:
- case MAC_PREFIX_TKN:
- if (!tok->varname && prevname)
- cmd_token_varname_set(tok, prevname);
- prevname = NULL;
- break;
-
- case START_TKN:
- case JOIN_TKN:
- case NEG_ONLY_TKN:
- /* "<foo|bar> WORD" -> word is not "bar" or "foo" */
- prevname = NULL;
- break;
-
- case FORK_TKN:
- /* apply "<A.B.C.D|X:X::X:X>$name" */
- jointok = tok->forkjoin->data;
- if (!jointok->varname)
- break;
- for (i = 0; i < vector_active(tok->forkjoin->from); i++) {
- struct graph_node *tail =
- vector_slot(tok->forkjoin->from, i);
- struct cmd_token *tailtok = tail->data;
- if (tail == gn || tailtok->varname)
- continue;
- cmd_token_varname_set(tailtok, jointok->varname);
- }
- break;
-
- case END_TKN:
- return;
- }
-
- for (i = 0; i < vector_active(gn->to); i++) {
- struct graph_node *next = vector_slot(gn->to, i);
- if (next == stop || next == join)
- continue;
- cmd_node_names(next, join, prevname);
- }
-
- if (tok->type == FORK_TKN && tok->forkjoin != join)
- cmd_node_names(tok->forkjoin, join, NULL);
-}
-
void cmd_graph_names(struct graph *graph)
{
struct graph_node *start;
@@ -451,12 +460,10 @@ void cmd_graph_names(struct graph *graph)
struct cmd_token *tok1 = next1->data;
/* the other one needs to be "no" (only one will match here) */
if ((tok0->type == WORD_TKN && !strcmp(tok0->text, "no")))
- cmd_token_varname_set(tok0, "no");
+ cmd_token_varname_do(tok0, "no", VARNAME_AUTO);
if ((tok1->type == WORD_TKN && !strcmp(tok1->text, "no")))
- cmd_token_varname_set(tok1, "no");
+ cmd_token_varname_do(tok1, "no", VARNAME_AUTO);
} while (0);
-
- cmd_node_names(start, NULL, NULL);
}
#ifndef BUILDING_CLIPPY
diff --git a/lib/command_graph.h b/lib/command_graph.h
index 86157f872e..ed4da6aa4c 100644
--- a/lib/command_graph.h
+++ b/lib/command_graph.h
@@ -79,11 +79,20 @@ enum { CMD_ATTR_NORMAL,
CMD_ATTR_YANG,
};
+enum varname_src {
+ VARNAME_NONE = 0,
+ VARNAME_AUTO,
+ VARNAME_VAR,
+ VARNAME_TEXT,
+ VARNAME_EXPLICIT,
+};
+
/* Command token struct. */
struct cmd_token {
enum cmd_token_type type; // token type
uint8_t attr; // token attributes
bool allowrepeat; // matcher allowed to match token repetitively?
+ uint8_t varname_src;
uint32_t refcnt;
char *text; // token text
@@ -119,6 +128,8 @@ extern struct cmd_token *cmd_token_new(enum cmd_token_type, uint8_t attr,
extern struct cmd_token *cmd_token_dup(struct cmd_token *);
extern void cmd_token_del(struct cmd_token *);
extern void cmd_token_varname_set(struct cmd_token *token, const char *varname);
+extern void cmd_token_varname_seqappend(struct graph_node *n);
+extern void cmd_token_varname_join(struct graph_node *n, const char *varname);
extern void cmd_graph_parse(struct graph *graph, const struct cmd_element *cmd);
extern void cmd_graph_names(struct graph *graph);
diff --git a/lib/command_parse.y b/lib/command_parse.y
index dccd738f31..35c119691b 100644
--- a/lib/command_parse.y
+++ b/lib/command_parse.y
@@ -217,10 +217,12 @@ cmd_token:
{
if ((ctx->currnode = graph_add_edge (ctx->currnode, $1)) != $1)
graph_delete_node (ctx->graph, $1);
+ cmd_token_varname_seqappend($1);
}
| selector
{
graph_add_edge (ctx->currnode, $1.start);
+ cmd_token_varname_seqappend($1.start);
ctx->currnode = $1.end;
}
;
@@ -295,9 +297,8 @@ placeholder_token_real:
placeholder_token:
placeholder_token_real varname_token
{
- struct cmd_token *token = $$->data;
$$ = $1;
- cmd_token_varname_set (token, $2);
+ cmd_token_varname_set ($$->data, $2);
XFREE (MTYPE_LEX, $2);
};
@@ -306,7 +307,7 @@ placeholder_token:
selector: '<' selector_seq_seq '>' varname_token
{
$$ = $2;
- cmd_token_varname_set ($2.end->data, $4);
+ cmd_token_varname_join ($2.end, $4);
XFREE (MTYPE_LEX, $4);
};
@@ -342,7 +343,7 @@ selector: '{' selector_seq_seq '}' varname_token
* #1 is good enough to keep it this way. */
loopcheck(ctx, &$$);
- cmd_token_varname_set ($2.end->data, $4);
+ cmd_token_varname_join ($2.end, $4);
XFREE (MTYPE_LEX, $4);
};
@@ -359,6 +360,7 @@ selector_token_seq:
selector_token_seq selector_token
{
graph_add_edge ($1.end, $2.start);
+ cmd_token_varname_seqappend($2.start);
$$.start = $1.start;
$$.end = $2.end;
}
@@ -370,7 +372,7 @@ selector: '[' selector_seq_seq ']' varname_token
{
$$ = $2;
graph_add_edge ($$.start, $$.end);
- cmd_token_varname_set ($2.end->data, $4);
+ cmd_token_varname_join ($2.end, $4);
XFREE (MTYPE_LEX, $4);
}
;
@@ -383,7 +385,7 @@ selector: EXCL_BRACKET selector_seq_seq ']' varname_token
$$ = $2;
graph_add_edge ($$.start, neg_only);
graph_add_edge (neg_only, $$.end);
- cmd_token_varname_set ($2.end->data, $4);
+ cmd_token_varname_join ($2.end, $4);
XFREE (MTYPE_LEX, $4);
}
;
diff --git a/lib/filter.h b/lib/filter.h
index d1956ec019..b378288c58 100644
--- a/lib/filter.h
+++ b/lib/filter.h
@@ -234,15 +234,19 @@ bool plist_is_dup(const struct lyd_node *dnode, struct plist_dup_args *pda);
struct lyd_node;
struct vty;
-extern int access_list_cmp(struct lyd_node *dnode1, struct lyd_node *dnode2);
-extern void access_list_show(struct vty *vty, struct lyd_node *dnode,
+extern int access_list_cmp(const struct lyd_node *dnode1,
+ const struct lyd_node *dnode2);
+extern void access_list_show(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-extern void access_list_remark_show(struct vty *vty, struct lyd_node *dnode,
+extern void access_list_remark_show(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-extern int prefix_list_cmp(struct lyd_node *dnode1, struct lyd_node *dnode2);
-extern void prefix_list_show(struct vty *vty, struct lyd_node *dnode,
+extern int prefix_list_cmp(const struct lyd_node *dnode1,
+ const struct lyd_node *dnode2);
+extern void prefix_list_show(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-extern void prefix_list_remark_show(struct vty *vty, struct lyd_node *dnode,
+extern void prefix_list_remark_show(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
void filter_cli_init(void);
diff --git a/lib/filter_cli.c b/lib/filter_cli.c
index e424fcf878..43618094ac 100644
--- a/lib/filter_cli.c
+++ b/lib/filter_cli.c
@@ -1012,7 +1012,8 @@ ALIAS(
ACCESS_LIST_REMARK_STR
ACCESS_LIST_REMARK_LINE_STR)
-int access_list_cmp(struct lyd_node *dnode1, struct lyd_node *dnode2)
+int access_list_cmp(const struct lyd_node *dnode1,
+ const struct lyd_node *dnode2)
{
uint32_t seq1 = yang_dnode_get_uint32(dnode1, "./sequence");
uint32_t seq2 = yang_dnode_get_uint32(dnode2, "./sequence");
@@ -1020,7 +1021,7 @@ int access_list_cmp(struct lyd_node *dnode1, struct lyd_node *dnode2)
return seq1 - seq2;
}
-void access_list_show(struct vty *vty, struct lyd_node *dnode,
+void access_list_show(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
int type = yang_dnode_get_enum(dnode, "../type");
@@ -1134,7 +1135,7 @@ void access_list_show(struct vty *vty, struct lyd_node *dnode,
vty_out(vty, "\n");
}
-void access_list_remark_show(struct vty *vty, struct lyd_node *dnode,
+void access_list_remark_show(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
int type = yang_dnode_get_enum(dnode, "../type");
@@ -1655,7 +1656,8 @@ ALIAS(
ACCESS_LIST_REMARK_STR
ACCESS_LIST_REMARK_LINE_STR)
-int prefix_list_cmp(struct lyd_node *dnode1, struct lyd_node *dnode2)
+int prefix_list_cmp(const struct lyd_node *dnode1,
+ const struct lyd_node *dnode2)
{
uint32_t seq1 = yang_dnode_get_uint32(dnode1, "./sequence");
uint32_t seq2 = yang_dnode_get_uint32(dnode2, "./sequence");
@@ -1663,7 +1665,7 @@ int prefix_list_cmp(struct lyd_node *dnode1, struct lyd_node *dnode2)
return seq1 - seq2;
}
-void prefix_list_show(struct vty *vty, struct lyd_node *dnode,
+void prefix_list_show(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
int type = yang_dnode_get_enum(dnode, "../type");
@@ -1722,7 +1724,7 @@ void prefix_list_show(struct vty *vty, struct lyd_node *dnode,
vty_out(vty, "\n");
}
-void prefix_list_remark_show(struct vty *vty, struct lyd_node *dnode,
+void prefix_list_remark_show(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
int type = yang_dnode_get_enum(dnode, "../type");
diff --git a/lib/grammar_sandbox.c b/lib/grammar_sandbox.c
index 209765bd6f..f9778c5d4c 100644
--- a/lib/grammar_sandbox.c
+++ b/lib/grammar_sandbox.c
@@ -395,6 +395,7 @@ DEFUN (grammar_findambig,
vector_slot(cmdvec, scannode++);
if (!cnode)
continue;
+ cmd_finalize_node(cnode);
nodegraph = cnode->cmdgraph;
if (!nodegraph)
continue;
@@ -466,6 +467,7 @@ DEFUN (grammar_access,
}
vty_out(vty, "node %d\n", (int)cnode->node);
+ cmd_finalize_node(cnode);
nodegraph = cnode->cmdgraph;
return CMD_SUCCESS;
}
diff --git a/lib/if.c b/lib/if.c
index cb6270f5ec..41dc91a475 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -1255,8 +1255,8 @@ DEFPY_YANG (no_interface,
ifname, vrf_name);
}
-static void cli_show_interface(struct vty *vty, struct lyd_node *dnode,
- bool show_defaults)
+static void cli_show_interface(struct vty *vty, const struct lyd_node *dnode,
+ bool show_defaults)
{
const char *vrf;
@@ -1269,7 +1269,8 @@ static void cli_show_interface(struct vty *vty, struct lyd_node *dnode,
vty_out(vty, "\n");
}
-static void cli_show_interface_end(struct vty *vty, struct lyd_node *dnode)
+static void cli_show_interface_end(struct vty *vty,
+ const struct lyd_node *dnode)
{
vty_out(vty, "exit\n");
}
@@ -1305,8 +1306,9 @@ DEFPY_YANG (no_interface_desc,
return nb_cli_apply_changes(vty, NULL);
}
-static void cli_show_interface_desc(struct vty *vty, struct lyd_node *dnode,
- bool show_defaults)
+static void cli_show_interface_desc(struct vty *vty,
+ const struct lyd_node *dnode,
+ bool show_defaults)
{
vty_out(vty, " description %s\n", yang_dnode_get_string(dnode, NULL));
}
diff --git a/lib/northbound.h b/lib/northbound.h
index bf04dbda17..a330bd1a30 100644
--- a/lib/northbound.h
+++ b/lib/northbound.h
@@ -488,7 +488,8 @@ struct nb_callbacks {
* >0 when the CLI command for the dnode2 should be printed first
* 0 when there is no difference
*/
- int (*cli_cmp)(struct lyd_node *dnode1, struct lyd_node *dnode2);
+ int (*cli_cmp)(const struct lyd_node *dnode1,
+ const struct lyd_node *dnode2);
/*
* Optional callback to show the CLI command associated to the given
@@ -510,7 +511,7 @@ struct nb_callbacks {
* nodes, in which case it might be desirable to hide one or more
* parts of the command when this parameter is set to false.
*/
- void (*cli_show)(struct vty *vty, struct lyd_node *dnode,
+ void (*cli_show)(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
/*
@@ -523,7 +524,7 @@ struct nb_callbacks {
* libyang data node that should be shown in the form of a CLI
* command.
*/
- void (*cli_show_end)(struct vty *vty, struct lyd_node *dnode);
+ void (*cli_show_end)(struct vty *vty, const struct lyd_node *dnode);
};
struct nb_dependency_callbacks {
diff --git a/lib/northbound_cli.c b/lib/northbound_cli.c
index 6676c0b072..70c71b18c4 100644
--- a/lib/northbound_cli.c
+++ b/lib/northbound_cli.c
@@ -550,14 +550,16 @@ void nb_cli_show_config_prepare(struct nb_config *config, bool with_defaults)
LYD_VALIDATE_NO_STATE, NULL);
}
-static int lyd_node_cmp(struct lyd_node **dnode1, struct lyd_node **dnode2)
+static int lyd_node_cmp(const struct lyd_node **dnode1,
+ const struct lyd_node **dnode2)
{
struct nb_node *nb_node = (*dnode1)->schema->priv;
return nb_node->cbs.cli_cmp(*dnode1, *dnode2);
}
-static void show_dnode_children_cmds(struct vty *vty, struct lyd_node *root,
+static void show_dnode_children_cmds(struct vty *vty,
+ const struct lyd_node *root,
bool with_defaults)
{
struct nb_node *nb_node, *sort_node = NULL;
@@ -616,7 +618,7 @@ static void show_dnode_children_cmds(struct vty *vty, struct lyd_node *root,
}
}
-void nb_cli_show_dnode_cmds(struct vty *vty, struct lyd_node *root,
+void nb_cli_show_dnode_cmds(struct vty *vty, const struct lyd_node *root,
bool with_defaults)
{
struct nb_node *nb_node;
diff --git a/lib/northbound_cli.h b/lib/northbound_cli.h
index 28f81f8b39..e472425447 100644
--- a/lib/northbound_cli.h
+++ b/lib/northbound_cli.h
@@ -127,7 +127,8 @@ extern int nb_cli_rpc(struct vty *vty, const char *xpath, struct list *input,
* show_defaults
* Specify whether to display default configuration values or not.
*/
-extern void nb_cli_show_dnode_cmds(struct vty *vty, struct lyd_node *dnode,
+extern void nb_cli_show_dnode_cmds(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
/*
diff --git a/lib/pbr.h b/lib/pbr.h
index cef1d9d380..b14ba07503 100644
--- a/lib/pbr.h
+++ b/lib/pbr.h
@@ -50,7 +50,7 @@ struct pbr_filter {
#define PBR_FILTER_SRC_PORT_RANGE (1 << 6)
#define PBR_FILTER_DST_PORT_RANGE (1 << 7)
#define PBR_FILTER_DSFIELD (1 << 8)
-#define PBR_FILTER_IP_PROTOCOL (1 << 9)
+#define PBR_FILTER_IP_PROTOCOL (1 << 9)
#define PBR_DSFIELD_DSCP (0xfc) /* Upper 6 bits of DS field: DSCP */
#define PBR_DSFIELD_ECN (0x03) /* Lower 2 bits of DS field: BCN */
@@ -83,6 +83,13 @@ struct pbr_filter {
* the user criteria may directly point to a table too.
*/
struct pbr_action {
+ /* VLAN */
+ uint8_t pcp;
+ uint16_t vlan_id;
+ uint16_t vlan_flags;
+
+ uint32_t queue_id;
+
uint32_t table;
};
diff --git a/lib/route_opaque.h b/lib/route_opaque.h
index 7c4e9a16e1..c5e7d6a327 100644
--- a/lib/route_opaque.h
+++ b/lib/route_opaque.h
@@ -36,6 +36,12 @@ struct bgp_zebra_opaque {
/* Show at least 10 large-communities AA:BB:CC */
char lcommunity[LCOMMUNITY_SIZE * 30];
+
+ /* 32 bytes seems enough because of
+ * bgp_path_selection_confed_as_path which is
+ * `Confederation based AS Path`.
+ */
+ char selection_reason[BGP_MAX_SELECTION_REASON_STR_BUF];
};
static_assert(sizeof(struct bgp_zebra_opaque) <= ZAPI_MESSAGE_OPAQUE_LENGTH,
diff --git a/lib/routemap.h b/lib/routemap.h
index 2c8eb24537..f8fdc67d57 100644
--- a/lib/routemap.h
+++ b/lib/routemap.h
@@ -908,25 +908,28 @@ void routemap_hook_context_free(struct routemap_hook_context *rhc);
extern const struct frr_yang_module_info frr_route_map_info;
/* routemap_cli.c */
-extern int route_map_instance_cmp(struct lyd_node *dnode1,
- struct lyd_node *dnode2);
-extern void route_map_instance_show(struct vty *vty, struct lyd_node *dnode,
+extern int route_map_instance_cmp(const struct lyd_node *dnode1,
+ const struct lyd_node *dnode2);
+extern void route_map_instance_show(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
extern void route_map_instance_show_end(struct vty *vty,
- struct lyd_node *dnode);
-extern void route_map_condition_show(struct vty *vty, struct lyd_node *dnode,
+ const struct lyd_node *dnode);
+extern void route_map_condition_show(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-extern void route_map_action_show(struct vty *vty, struct lyd_node *dnode,
+extern void route_map_action_show(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-extern void route_map_exit_policy_show(struct vty *vty, struct lyd_node *dnode,
+extern void route_map_exit_policy_show(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-extern void route_map_call_show(struct vty *vty, struct lyd_node *dnode,
+extern void route_map_call_show(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
extern void route_map_description_show(struct vty *vty,
- struct lyd_node *dnode,
+ const struct lyd_node *dnode,
bool show_defaults);
extern void route_map_optimization_disabled_show(struct vty *vty,
- struct lyd_node *dnode,
+ const struct lyd_node *dnode,
bool show_defaults);
extern void route_map_cli_init(void);
diff --git a/lib/routemap_cli.c b/lib/routemap_cli.c
index e2db511fc0..9360c7f529 100644
--- a/lib/routemap_cli.c
+++ b/lib/routemap_cli.c
@@ -103,7 +103,8 @@ DEFPY_YANG(
return nb_cli_apply_changes(vty, NULL);
}
-int route_map_instance_cmp(struct lyd_node *dnode1, struct lyd_node *dnode2)
+int route_map_instance_cmp(const struct lyd_node *dnode1,
+ const struct lyd_node *dnode2)
{
uint16_t seq1 = yang_dnode_get_uint16(dnode1, "./sequence");
uint16_t seq2 = yang_dnode_get_uint16(dnode2, "./sequence");
@@ -111,7 +112,7 @@ int route_map_instance_cmp(struct lyd_node *dnode1, struct lyd_node *dnode2)
return seq1 - seq2;
}
-void route_map_instance_show(struct vty *vty, struct lyd_node *dnode,
+void route_map_instance_show(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
const char *name = yang_dnode_get_string(dnode, "../name");
@@ -122,7 +123,7 @@ void route_map_instance_show(struct vty *vty, struct lyd_node *dnode,
}
-void route_map_instance_show_end(struct vty *vty, struct lyd_node *dnode)
+void route_map_instance_show_end(struct vty *vty, const struct lyd_node *dnode)
{
vty_out(vty, "exit\n");
vty_out(vty, "!\n");
@@ -538,11 +539,11 @@ DEFPY_YANG(
return nb_cli_apply_changes(vty, NULL);
}
-void route_map_condition_show(struct vty *vty, struct lyd_node *dnode,
+void route_map_condition_show(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
const char *condition = yang_dnode_get_string(dnode, "./condition");
- struct lyd_node *ln;
+ const struct lyd_node *ln;
const char *acl;
if (IS_MATCH_INTERFACE(condition)) {
@@ -1013,11 +1014,11 @@ DEFUN_YANG (no_set_srte_color,
}
-void route_map_action_show(struct vty *vty, struct lyd_node *dnode,
+void route_map_action_show(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
const char *action = yang_dnode_get_string(dnode, "./action");
- struct lyd_node *ln;
+ const struct lyd_node *ln;
const char *acl;
if (IS_SET_IPv4_NH(action)) {
@@ -1355,7 +1356,7 @@ ALIAS_YANG(
"Continue on a different entry within the route-map\n"
"Route-map entry sequence number\n")
-void route_map_exit_policy_show(struct vty *vty, struct lyd_node *dnode,
+void route_map_exit_policy_show(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
int exit_policy = yang_dnode_get_enum(dnode, NULL);
@@ -1397,7 +1398,7 @@ DEFPY_YANG(
return nb_cli_apply_changes(vty, NULL);
}
-void route_map_call_show(struct vty *vty, struct lyd_node *dnode,
+void route_map_call_show(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " call %s\n", yang_dnode_get_string(dnode, NULL));
@@ -1431,7 +1432,7 @@ DEFUN_YANG (no_rmap_description,
return nb_cli_apply_changes(vty, NULL);
}
-void route_map_description_show(struct vty *vty, struct lyd_node *dnode,
+void route_map_description_show(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " description %s\n", yang_dnode_get_string(dnode, NULL));
@@ -1460,7 +1461,7 @@ DEFPY_YANG(
}
void route_map_optimization_disabled_show(struct vty *vty,
- struct lyd_node *dnode,
+ const struct lyd_node *dnode,
bool show_defaults)
{
const char *name = yang_dnode_get_string(dnode, "../name");
@@ -1507,7 +1508,7 @@ DEFPY_HIDDEN(
static int route_map_config_write(struct vty *vty)
{
- struct lyd_node *dnode;
+ const struct lyd_node *dnode;
int written = 0;
dnode = yang_dnode_get(running_config->dnode,
diff --git a/lib/sockopt.c b/lib/sockopt.c
index 150736e00c..45f3c23330 100644
--- a/lib/sockopt.c
+++ b/lib/sockopt.c
@@ -122,7 +122,7 @@ int setsockopt_ipv6_pktinfo(int sock, int val)
if (ret < 0)
flog_err(EC_LIB_SOCKET, "can't setsockopt IPV6_PKTINFO : %s",
safe_strerror(errno));
-#endif /* INIA_IPV6 */
+#endif /* IANA_IPV6 */
return ret;
}
@@ -595,7 +595,7 @@ int sockopt_tcp_signature_ext(int sock, union sockunion *su, uint16_t prefixlen,
/* If this does not work, then all users of this sockopt will
* need to
- * differentiate between IPv4 and IPv6, and keep seperate
+ * differentiate between IPv4 and IPv6, and keep separate
* sockets for
* each.
*
diff --git a/lib/table.c b/lib/table.c
index e6030ca4ca..523183bef2 100644
--- a/lib/table.c
+++ b/lib/table.c
@@ -393,7 +393,7 @@ void route_node_delete(struct route_node *node)
route_node_delete(parent);
}
-/* Get fist node and lock it. This function is useful when one want
+/* Get first node and lock it. This function is useful when one wants
to lookup all the node exist in the routing table. */
struct route_node *route_top(struct route_table *table)
{
diff --git a/lib/thread.c b/lib/thread.c
index 835aa38115..5dbba6363d 100644
--- a/lib/thread.c
+++ b/lib/thread.c
@@ -922,10 +922,10 @@ done:
}
/* Add new read thread. */
-struct thread *_thread_add_read_write(const struct xref_threadsched *xref,
- struct thread_master *m,
- int (*func)(struct thread *),
- void *arg, int fd, struct thread **t_ptr)
+void _thread_add_read_write(const struct xref_threadsched *xref,
+ struct thread_master *m,
+ int (*func)(struct thread *), void *arg, int fd,
+ struct thread **t_ptr)
{
int dir = xref->thread_type;
struct thread *thread = NULL;
@@ -1000,15 +1000,13 @@ struct thread *_thread_add_read_write(const struct xref_threadsched *xref,
AWAKEN(m);
}
-
- return thread;
}
-static struct thread *
-_thread_add_timer_timeval(const struct xref_threadsched *xref,
- struct thread_master *m, int (*func)(struct thread *),
- void *arg, struct timeval *time_relative,
- struct thread **t_ptr)
+static void _thread_add_timer_timeval(const struct xref_threadsched *xref,
+ struct thread_master *m,
+ int (*func)(struct thread *), void *arg,
+ struct timeval *time_relative,
+ struct thread **t_ptr)
{
struct thread *thread;
struct timeval t;
@@ -1028,7 +1026,7 @@ _thread_add_timer_timeval(const struct xref_threadsched *xref,
frr_with_mutex(&m->mtx) {
if (t_ptr && *t_ptr)
/* thread is already scheduled; don't reschedule */
- return NULL;
+ return;
thread = thread_get(m, THREAD_TIMER, func, arg, xref);
@@ -1048,16 +1046,13 @@ _thread_add_timer_timeval(const struct xref_threadsched *xref,
if (thread_timer_list_first(&m->timer) == thread)
AWAKEN(m);
}
-
- return thread;
}
/* Add timer event thread. */
-struct thread *_thread_add_timer(const struct xref_threadsched *xref,
- struct thread_master *m,
- int (*func)(struct thread *),
- void *arg, long timer, struct thread **t_ptr)
+void _thread_add_timer(const struct xref_threadsched *xref,
+ struct thread_master *m, int (*func)(struct thread *),
+ void *arg, long timer, struct thread **t_ptr)
{
struct timeval trel;
@@ -1066,15 +1061,14 @@ struct thread *_thread_add_timer(const struct xref_threadsched *xref,
trel.tv_sec = timer;
trel.tv_usec = 0;
- return _thread_add_timer_timeval(xref, m, func, arg, &trel, t_ptr);
+ _thread_add_timer_timeval(xref, m, func, arg, &trel, t_ptr);
}
/* Add timer event thread with "millisecond" resolution */
-struct thread *_thread_add_timer_msec(const struct xref_threadsched *xref,
- struct thread_master *m,
- int (*func)(struct thread *),
- void *arg, long timer,
- struct thread **t_ptr)
+void _thread_add_timer_msec(const struct xref_threadsched *xref,
+ struct thread_master *m,
+ int (*func)(struct thread *), void *arg, long timer,
+ struct thread **t_ptr)
{
struct timeval trel;
@@ -1083,24 +1077,21 @@ struct thread *_thread_add_timer_msec(const struct xref_threadsched *xref,
trel.tv_sec = timer / 1000;
trel.tv_usec = 1000 * (timer % 1000);
- return _thread_add_timer_timeval(xref, m, func, arg, &trel, t_ptr);
+ _thread_add_timer_timeval(xref, m, func, arg, &trel, t_ptr);
}
/* Add timer event thread with "timeval" resolution */
-struct thread *_thread_add_timer_tv(const struct xref_threadsched *xref,
- struct thread_master *m,
- int (*func)(struct thread *),
- void *arg, struct timeval *tv,
- struct thread **t_ptr)
+void _thread_add_timer_tv(const struct xref_threadsched *xref,
+ struct thread_master *m, int (*func)(struct thread *),
+ void *arg, struct timeval *tv, struct thread **t_ptr)
{
- return _thread_add_timer_timeval(xref, m, func, arg, tv, t_ptr);
+ _thread_add_timer_timeval(xref, m, func, arg, tv, t_ptr);
}
/* Add simple event thread. */
-struct thread *_thread_add_event(const struct xref_threadsched *xref,
- struct thread_master *m,
- int (*func)(struct thread *),
- void *arg, int val, struct thread **t_ptr)
+void _thread_add_event(const struct xref_threadsched *xref,
+ struct thread_master *m, int (*func)(struct thread *),
+ void *arg, int val, struct thread **t_ptr)
{
struct thread *thread = NULL;
@@ -1128,8 +1119,6 @@ struct thread *_thread_add_event(const struct xref_threadsched *xref,
AWAKEN(m);
}
-
- return thread;
}
/* Thread cancellation ------------------------------------------------------ */
@@ -2059,3 +2048,11 @@ void debug_signals(const sigset_t *sigs)
zlog_debug("%s: %s", __func__, buf);
}
+
+bool thread_is_scheduled(struct thread *thread)
+{
+ if (thread == NULL)
+ return false;
+
+ return true;
+}
diff --git a/lib/thread.h b/lib/thread.h
index abd94ff4f0..39f21da11d 100644
--- a/lib/thread.h
+++ b/lib/thread.h
@@ -219,26 +219,30 @@ void thread_master_set_name(struct thread_master *master, const char *name);
extern void thread_master_free(struct thread_master *);
extern void thread_master_free_unused(struct thread_master *);
-extern struct thread *_thread_add_read_write(
- const struct xref_threadsched *xref, struct thread_master *master,
- int (*fn)(struct thread *), void *arg, int fd, struct thread **tref);
-
-extern struct thread *_thread_add_timer(
- const struct xref_threadsched *xref, struct thread_master *master,
- int (*fn)(struct thread *), void *arg, long t, struct thread **tref);
-
-extern struct thread *_thread_add_timer_msec(
- const struct xref_threadsched *xref, struct thread_master *master,
- int (*fn)(struct thread *), void *arg, long t, struct thread **tref);
-
-extern struct thread *_thread_add_timer_tv(
- const struct xref_threadsched *xref, struct thread_master *master,
- int (*fn)(struct thread *), void *arg, struct timeval *tv,
- struct thread **tref);
-
-extern struct thread *_thread_add_event(
- const struct xref_threadsched *xref, struct thread_master *master,
- int (*fn)(struct thread *), void *arg, int val, struct thread **tref);
+extern void _thread_add_read_write(const struct xref_threadsched *xref,
+ struct thread_master *master,
+ int (*fn)(struct thread *), void *arg,
+ int fd, struct thread **tref);
+
+extern void _thread_add_timer(const struct xref_threadsched *xref,
+ struct thread_master *master,
+ int (*fn)(struct thread *), void *arg, long t,
+ struct thread **tref);
+
+extern void _thread_add_timer_msec(const struct xref_threadsched *xref,
+ struct thread_master *master,
+ int (*fn)(struct thread *), void *arg,
+ long t, struct thread **tref);
+
+extern void _thread_add_timer_tv(const struct xref_threadsched *xref,
+ struct thread_master *master,
+ int (*fn)(struct thread *), void *arg,
+ struct timeval *tv, struct thread **tref);
+
+extern void _thread_add_event(const struct xref_threadsched *xref,
+ struct thread_master *master,
+ int (*fn)(struct thread *), void *arg, int val,
+ struct thread **tref);
extern void _thread_execute(const struct xref_threadsched *xref,
struct thread_master *master,
@@ -273,6 +277,7 @@ extern pthread_key_t thread_current;
extern char *thread_timer_to_hhmmss(char *buf, int buf_size,
struct thread *t_timer);
+extern bool thread_is_scheduled(struct thread *thread);
/* Debug signal mask */
void debug_signals(const sigset_t *sigs);
diff --git a/lib/typerb.c b/lib/typerb.c
index 092faa4cc9..e1346df191 100644
--- a/lib/typerb.c
+++ b/lib/typerb.c
@@ -45,6 +45,7 @@
#include "config.h"
#endif
+#include <string.h>
#include "typerb.h"
#define RB_BLACK 0
@@ -330,6 +331,7 @@ color:
rbe_remove_color(rbt, parent, child);
rbt->count--;
+ memset(old, 0, sizeof(*old));
return (old);
}
@@ -478,3 +480,11 @@ struct rb_entry *typed_rb_min(const struct rbt_tree *rbt)
return parent;
}
+
+bool typed_rb_member(const struct typed_rb_root *rbt,
+ const struct typed_rb_entry *rbe)
+{
+ while (rbe->rbt_parent)
+ rbe = rbe->rbt_parent;
+ return rbe == rbt->rbt_root;
+}
diff --git a/lib/typerb.h b/lib/typerb.h
index cbed8d4893..d22d864aae 100644
--- a/lib/typerb.h
+++ b/lib/typerb.h
@@ -62,6 +62,8 @@ const struct typed_rb_entry *typed_rb_find_lt(const struct typed_rb_root *rbt,
const struct typed_rb_entry *b));
struct typed_rb_entry *typed_rb_min(const struct typed_rb_root *rbt);
struct typed_rb_entry *typed_rb_next(const struct typed_rb_entry *rbe);
+bool typed_rb_member(const struct typed_rb_root *rbt,
+ const struct typed_rb_entry *rbe);
#define _PREDECL_RBTREE(prefix) \
struct prefix ## _head { struct typed_rb_root rr; }; \
@@ -142,6 +144,11 @@ macro_pure size_t prefix ## _count(const struct prefix##_head *h) \
{ \
return h->rr.count; \
} \
+macro_pure bool prefix ## _member(const struct prefix##_head *h, \
+ const type *item) \
+{ \
+ return typed_rb_member(&h->rr, &item->field.re); \
+} \
MACRO_REQUIRE_SEMICOLON() /* end */
#define PREDECL_RBTREE_UNIQ(prefix) \
diff --git a/lib/typesafe.c b/lib/typesafe.c
index 76705fad0d..f90b59daf0 100644
--- a/lib/typesafe.c
+++ b/lib/typesafe.c
@@ -29,6 +29,46 @@ DEFINE_MTYPE_STATIC(LIB, TYPEDHASH_BUCKET, "Typed-hash bucket");
DEFINE_MTYPE_STATIC(LIB, SKIPLIST_OFLOW, "Skiplist overflow");
DEFINE_MTYPE_STATIC(LIB, HEAP_ARRAY, "Typed-heap array");
+struct slist_item typesafe_slist_sentinel = { NULL };
+
+bool typesafe_list_member(const struct slist_head *head,
+ const struct slist_item *item)
+{
+ struct slist_item *fromhead = head->first;
+ struct slist_item **fromnext = (struct slist_item **)&item->next;
+
+ while (fromhead != _SLIST_LAST) {
+ if (fromhead == item || fromnext == head->last_next)
+ return true;
+
+ fromhead = fromhead->next;
+ if (!*fromnext || *fromnext == _SLIST_LAST)
+ break;
+ fromnext = &(*fromnext)->next;
+ }
+
+ return false;
+}
+
+bool typesafe_dlist_member(const struct dlist_head *head,
+ const struct dlist_item *item)
+{
+ const struct dlist_item *fromhead = head->hitem.next;
+ const struct dlist_item *fromitem = item->next;
+
+ if (!item->prev || !item->next)
+ return false;
+
+ while (fromhead != &head->hitem && fromitem != item) {
+ if (fromitem == &head->hitem || fromhead == item)
+ return true;
+ fromhead = fromhead->next;
+ fromitem = fromitem->next;
+ }
+
+ return false;
+}
+
#if 0
static void hash_consistency_check(struct thash_head *head)
{
diff --git a/lib/typesafe.h b/lib/typesafe.h
index ecac1a4381..44c42ffbca 100644
--- a/lib/typesafe.h
+++ b/lib/typesafe.h
@@ -78,8 +78,34 @@ macro_inline type *prefix ## _find_gteq(struct prefix##_head *h, \
} \
/* ... */
+/* *_member via find - when there is no better membership check than find() */
+#define TYPESAFE_MEMBER_VIA_FIND(prefix, type) \
+macro_inline bool prefix ## _member(struct prefix##_head *h, \
+ const type *item) \
+{ \
+ return item == prefix ## _const_find(h, item); \
+} \
+/* ... */
+
+/* *_member via find_gteq - same for non-unique containers */
+#define TYPESAFE_MEMBER_VIA_FIND_GTEQ(prefix, type, cmpfn) \
+macro_inline bool prefix ## _member(struct prefix##_head *h, \
+ const type *item) \
+{ \
+ const type *iter; \
+ for (iter = prefix ## _const_find_gteq(h, item); iter; \
+ iter = prefix ## _const_next(h, iter)) { \
+ if (iter == item) \
+ return true; \
+ if (cmpfn(iter, item) > 0) \
+ break; \
+ } \
+ return false; \
+} \
+/* ... */
+
/* SWAP_ALL_SIMPLE = for containers where the items don't point back to the
- * head *AND* the head doesn'T points to itself (= everything except LIST,
+ * head *AND* the head doesn't point to itself (= everything except LIST,
* DLIST and SKIPLIST), just switch out the entire head
*/
#define TYPESAFE_SWAP_ALL_SIMPLE(prefix) \
@@ -106,6 +132,10 @@ struct slist_head {
size_t count;
};
+/* this replaces NULL as the value for ->next on the last item. */
+extern struct slist_item typesafe_slist_sentinel;
+#define _SLIST_LAST &typesafe_slist_sentinel
+
static inline void typesafe_list_add(struct slist_head *head,
struct slist_item **pos, struct slist_item *item)
{
@@ -116,6 +146,9 @@ static inline void typesafe_list_add(struct slist_head *head,
head->count++;
}
+extern bool typesafe_list_member(const struct slist_head *head,
+ const struct slist_item *item);
+
/* use as:
*
* PREDECL_LIST(namelist);
@@ -136,6 +169,7 @@ MACRO_REQUIRE_SEMICOLON() /* end */
macro_inline void prefix ## _init(struct prefix##_head *h) \
{ \
memset(h, 0, sizeof(*h)); \
+ h->sh.first = _SLIST_LAST; \
h->sh.last_next = &h->sh.first; \
} \
macro_inline void prefix ## _fini(struct prefix##_head *h) \
@@ -161,25 +195,27 @@ macro_inline void prefix ## _add_after(struct prefix##_head *h, \
macro_inline type *prefix ## _del(struct prefix##_head *h, type *item) \
{ \
struct slist_item **iter = &h->sh.first; \
- while (*iter && *iter != &item->field.si) \
+ while (*iter != _SLIST_LAST && *iter != &item->field.si) \
iter = &(*iter)->next; \
- if (!*iter) \
+ if (*iter == _SLIST_LAST) \
return NULL; \
h->sh.count--; \
*iter = item->field.si.next; \
- if (!item->field.si.next) \
+ if (item->field.si.next == _SLIST_LAST) \
h->sh.last_next = iter; \
+ item->field.si.next = NULL; \
return item; \
} \
macro_inline type *prefix ## _pop(struct prefix##_head *h) \
{ \
struct slist_item *sitem = h->sh.first; \
- if (!sitem) \
+ if (sitem == _SLIST_LAST) \
return NULL; \
h->sh.count--; \
h->sh.first = sitem->next; \
- if (h->sh.first == NULL) \
+ if (h->sh.first == _SLIST_LAST) \
h->sh.last_next = &h->sh.first; \
+ sitem->next = NULL; \
return container_of(sitem, type, field.si); \
} \
macro_inline void prefix ## _swap_all(struct prefix##_head *a, \
@@ -195,13 +231,17 @@ macro_inline void prefix ## _swap_all(struct prefix##_head *a, \
} \
macro_pure const type *prefix ## _const_first(const struct prefix##_head *h) \
{ \
- return container_of_null(h->sh.first, type, field.si); \
+ if (h->sh.first != _SLIST_LAST) \
+ return container_of(h->sh.first, type, field.si); \
+ return NULL; \
} \
macro_pure const type *prefix ## _const_next(const struct prefix##_head *h, \
const type *item) \
{ \
const struct slist_item *sitem = &item->field.si; \
- return container_of_null(sitem->next, type, field.si); \
+ if (sitem->next != _SLIST_LAST) \
+ return container_of(sitem->next, type, field.si); \
+ return NULL; \
} \
TYPESAFE_FIRST_NEXT(prefix, type) \
macro_pure type *prefix ## _next_safe(struct prefix##_head *h, type *item) \
@@ -210,12 +250,23 @@ macro_pure type *prefix ## _next_safe(struct prefix##_head *h, type *item) \
if (!item) \
return NULL; \
sitem = &item->field.si; \
- return container_of_null(sitem->next, type, field.si); \
+ if (sitem->next != _SLIST_LAST) \
+ return container_of(sitem->next, type, field.si); \
+ return NULL; \
} \
macro_pure size_t prefix ## _count(const struct prefix##_head *h) \
{ \
return h->sh.count; \
} \
+macro_pure bool prefix ## _anywhere(const type *item) \
+{ \
+ return item->field.si.next != NULL; \
+} \
+macro_pure bool prefix ## _member(const struct prefix##_head *h, \
+ const type *item) \
+{ \
+ return typesafe_list_member(&h->sh, &item->field.si); \
+} \
MACRO_REQUIRE_SEMICOLON() /* end */
/* don't use these structs directly */
@@ -267,6 +318,9 @@ static inline void typesafe_dlist_swap_all(struct dlist_head *a,
}
}
+extern bool typesafe_dlist_member(const struct dlist_head *head,
+ const struct dlist_item *item);
+
/* double-linked list, for fast item deletion
*/
#define PREDECL_DLIST(prefix) \
@@ -321,6 +375,7 @@ macro_inline type *prefix ## _pop(struct prefix##_head *h) \
ditem->prev->next = ditem->next; \
ditem->next->prev = ditem->prev; \
h->dh.count--; \
+ ditem->prev = ditem->next = NULL; \
return container_of(ditem, type, field.di); \
} \
macro_inline void prefix ## _swap_all(struct prefix##_head *a, \
@@ -354,6 +409,16 @@ macro_pure size_t prefix ## _count(const struct prefix##_head *h) \
{ \
return h->dh.count; \
} \
+macro_pure bool prefix ## _anywhere(const type *item) \
+{ \
+ const struct dlist_item *ditem = &item->field.di; \
+ return ditem->next && ditem->prev; \
+} \
+macro_pure bool prefix ## _member(const struct prefix##_head *h, \
+ const type *item) \
+{ \
+ return typesafe_dlist_member(&h->dh, &item->field.di); \
+} \
MACRO_REQUIRE_SEMICOLON() /* end */
/* note: heap currently caps out at 4G items */
@@ -463,6 +528,14 @@ macro_pure size_t prefix ## _count(const struct prefix##_head *h) \
{ \
return h->hh.count; \
} \
+macro_pure bool prefix ## _member(const struct prefix##_head *h, \
+ const type *item) \
+{ \
+ uint32_t idx = item->field.hi.index; \
+ if (idx >= h->hh.count) \
+ return false; \
+ return h->hh.array[idx] == &item->field.hi; \
+} \
MACRO_REQUIRE_SEMICOLON() /* end */
extern void typesafe_heap_resize(struct heap_head *head, bool grow);
@@ -565,6 +638,7 @@ macro_inline type *prefix ## _del(struct prefix##_head *h, type *item) \
return NULL; \
h->sh.count--; \
*iter = item->field.si.next; \
+ item->field.si.next = NULL; \
return item; \
} \
macro_inline type *prefix ## _pop(struct prefix##_head *h) \
@@ -618,6 +692,7 @@ macro_inline const type *prefix ## _const_find(const struct prefix##_head *h, \
return container_of(sitem, type, field.si); \
} \
TYPESAFE_FIND(prefix, type) \
+TYPESAFE_MEMBER_VIA_FIND(prefix, type) \
MACRO_REQUIRE_SEMICOLON() /* end */
#define DECLARE_SORTLIST_NONUNIQ(prefix, type, field, cmpfn) \
@@ -633,6 +708,7 @@ macro_inline int _ ## prefix ## _cmp(const type *a, const type *b) \
return 0; \
} \
_DECLARE_SORTLIST(prefix, type, field, cmpfn, _ ## prefix ## _cmp); \
+TYPESAFE_MEMBER_VIA_FIND_GTEQ(prefix, type, cmpfn) \
MACRO_REQUIRE_SEMICOLON() /* end */
@@ -799,6 +875,19 @@ macro_pure size_t prefix ## _count(const struct prefix##_head *h) \
{ \
return h->hh.count; \
} \
+macro_pure bool prefix ## _member(const struct prefix##_head *h, \
+ const type *item) \
+{ \
+ uint32_t hval = item->field.hi.hashval, hbits = HASH_KEY(h->hh, hval); \
+ const struct thash_item *hitem = h->hh.entries[hbits]; \
+ while (hitem && hitem->hashval < hval) \
+ hitem = hitem->next; \
+ for (hitem = h->hh.entries[hbits]; hitem && hitem->hashval <= hval; \
+ hitem = hitem->next) \
+ if (hitem == &item->field.hi) \
+ return true; \
+ return false; \
+} \
MACRO_REQUIRE_SEMICOLON() /* end */
/* skiplist, sorted.
@@ -937,6 +1026,7 @@ macro_inline const type *prefix ## _const_find(const struct prefix##_head *h, \
return container_of_null(sitem, type, field.si); \
} \
TYPESAFE_FIND(prefix, type) \
+TYPESAFE_MEMBER_VIA_FIND(prefix, type) \
\
_DECLARE_SKIPLIST(prefix, type, field, \
prefix ## __cmp, prefix ## __cmp); \
@@ -968,6 +1058,7 @@ macro_inline int prefix ## __cmp_uq(const struct sskip_item *a, \
\
_DECLARE_SKIPLIST(prefix, type, field, \
prefix ## __cmp, prefix ## __cmp_uq); \
+TYPESAFE_MEMBER_VIA_FIND_GTEQ(prefix, type, cmpfn) \
MACRO_REQUIRE_SEMICOLON() /* end */
diff --git a/lib/vector.c b/lib/vector.c
index 4af564a82f..38f9b1b85f 100644
--- a/lib/vector.c
+++ b/lib/vector.c
@@ -37,6 +37,7 @@ vector vector_init(unsigned int size)
v->alloced = size;
v->active = 0;
+ v->count = 0;
v->index = XCALLOC(MTYPE_VECTOR_INDEX, sizeof(void *) * size);
return v;
}
@@ -54,6 +55,7 @@ vector vector_copy(vector v)
new->active = v->active;
new->alloced = v->alloced;
+ new->count = v->count;
size = sizeof(void *) * (v->alloced);
new->index = XCALLOC(MTYPE_VECTOR_INDEX, size);
@@ -84,6 +86,9 @@ int vector_empty_slot(vector v)
{
unsigned int i;
+ if (v->active == v->count)
+ return v->active;
+
if (v->active == 0)
return 0;
@@ -102,6 +107,10 @@ int vector_set(vector v, void *val)
i = vector_empty_slot(v);
vector_ensure(v, i);
+ if (v->index[i])
+ v->count--;
+ if (val)
+ v->count++;
v->index[i] = val;
if (v->active <= i)
@@ -115,6 +124,10 @@ int vector_set_index(vector v, unsigned int i, void *val)
{
vector_ensure(v, i);
+ if (v->index[i])
+ v->count--;
+ if (val)
+ v->count++;
v->index[i] = val;
if (v->active <= i)
@@ -155,6 +168,9 @@ void vector_unset(vector v, unsigned int i)
if (i >= v->alloced)
return;
+ if (v->index[i])
+ v->count--;
+
v->index[i] = NULL;
if (i + 1 == v->active) {
@@ -169,6 +185,9 @@ void vector_remove(vector v, unsigned int ix)
if (ix >= v->active)
return;
+ if (v->index[ix])
+ v->count--;
+
int n = (--v->active) - ix;
memmove(&v->index[ix], &v->index[ix + 1], n * sizeof(void *));
@@ -192,6 +211,7 @@ void vector_unset_value(vector v, void *val)
for (i = 0; i < v->active; i++)
if (v->index[i] == val) {
v->index[i] = NULL;
+ v->count--;
break;
}
@@ -201,19 +221,6 @@ void vector_unset_value(vector v, void *val)
while (i && v->index[--i] == NULL);
}
-/* Count the number of not emplty slot. */
-unsigned int vector_count(vector v)
-{
- unsigned int i;
- unsigned count = 0;
-
- for (i = 0; i < v->active; i++)
- if (v->index[i] != NULL)
- count++;
-
- return count;
-}
-
void vector_to_array(vector v, void ***dest, int *argc)
{
*dest = XCALLOC(MTYPE_TMP, sizeof(void *) * v->active);
diff --git a/lib/vector.h b/lib/vector.h
index 845c8d8b04..6208be1cc7 100644
--- a/lib/vector.h
+++ b/lib/vector.h
@@ -32,6 +32,7 @@ extern "C" {
struct _vector {
unsigned int active; /* number of active slots */
unsigned int alloced; /* number of allocated slot */
+ unsigned int count;
void **index; /* index to data */
};
typedef struct _vector *vector;
@@ -60,7 +61,11 @@ extern void vector_unset_value(vector v, void *val);
extern void vector_remove(vector v, unsigned int ix);
extern void vector_compact(vector v);
-extern unsigned int vector_count(vector v);
+static inline unsigned int vector_count(vector v)
+{
+ return v->count;
+}
+
extern void vector_free(vector v);
extern vector vector_copy(vector v);
diff --git a/lib/vty.c b/lib/vty.c
index fef16f1ee7..5a03514be4 100644
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -776,7 +776,7 @@ static void vty_end_config(struct vty *vty)
vty->cp = 0;
}
-/* Delete a charcter at the current point. */
+/* Delete a character at the current point. */
static void vty_delete_char(struct vty *vty)
{
int i;
@@ -2282,7 +2282,7 @@ static void vty_read_file(struct nb_config *config, FILE *confp)
vty = vty_new();
/* vty_close won't close stderr; if some config command prints
- * something it'll end up there. (not ideal; it'd be beter if output
+ * something it'll end up there. (not ideal; it'd be better if output
* from a file-load went to logging instead. Also note that if this
* function is called after daemonizing, stderr will be /dev/null.)
*
@@ -2697,19 +2697,21 @@ static struct thread_master *vty_master;
static void vty_event_serv(enum event event, int sock)
{
- struct thread *vty_serv_thread = NULL;
+ struct thread **vty_serv_thread_ptr = NULL;
switch (event) {
case VTY_SERV:
- vty_serv_thread = thread_add_read(vty_master, vty_accept,
- NULL, sock, NULL);
- vector_set_index(Vvty_serv_thread, sock, vty_serv_thread);
+ vty_serv_thread_ptr = (struct thread **)vector_get_index(
+ Vvty_serv_thread, sock);
+ thread_add_read(vty_master, vty_accept, NULL, sock,
+ vty_serv_thread_ptr);
break;
#ifdef VTYSH
case VTYSH_SERV:
- vty_serv_thread = thread_add_read(vty_master, vtysh_accept,
- NULL, sock, NULL);
- vector_set_index(Vvty_serv_thread, sock, vty_serv_thread);
+ vty_serv_thread_ptr = (struct thread **)vector_get_index(
+ Vvty_serv_thread, sock);
+ thread_add_read(vty_master, vtysh_accept, NULL, sock,
+ vty_serv_thread_ptr);
break;
#endif /* VTYSH */
default:
@@ -3165,7 +3167,7 @@ void vty_init(struct thread_master *master_thread, bool do_command_logging)
atexit(vty_stdio_atexit);
- /* Initilize server thread vector. */
+ /* Initialize server thread vector. */
Vvty_serv_thread = vector_init(VECTOR_MIN_SIZE);
/* Install bgp top node. */
diff --git a/lib/vxlan.h b/lib/vxlan.h
index 62963a6097..220fd8d232 100644
--- a/lib/vxlan.h
+++ b/lib/vxlan.h
@@ -26,7 +26,7 @@
extern "C" {
#endif
-/* EVPN MH DF election alogorithm */
+/* EVPN MH DF election algorithm */
#define EVPN_MH_DF_ALG_SERVICE_CARVING 0
#define EVPN_MH_DF_ALG_HRW 1
#define EVPN_MH_DF_ALG_PREF 2
diff --git a/lib/yang.h b/lib/yang.h
index d4517f969a..d625b24f6a 100644
--- a/lib/yang.h
+++ b/lib/yang.h
@@ -183,7 +183,7 @@ extern int yang_snodes_iterate_subtree(const struct lysc_node *snode,
void *arg);
/*
- * Iterate over all libyang schema nodes from all loeaded modules of from the
+ * Iterate over all libyang schema nodes from all loaded modules of the
* given YANG module.
*
* module
diff --git a/lib/zclient.c b/lib/zclient.c
index 844e7ac404..24546f3c45 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -454,7 +454,7 @@ enum zclient_send_status zclient_send_localsid(struct zclient *zclient,
p.prefix = *sid;
api.vrf_id = VRF_DEFAULT;
- api.type = ZEBRA_ROUTE_BGP;
+ api.type = zclient->redist_default;
api.instance = 0;
api.safi = SAFI_UNICAST;
memcpy(&api.prefix, &p, sizeof(p));
@@ -2103,7 +2103,7 @@ stream_failure:
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Harware Address Length |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Hardware Address if HW lenght different from 0 |
+ * | Hardware Address if HW length different from 0 |
* | ... max INTERFACE_HWADDR_MAX |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Link_params? | Whether a link-params follows: 1 or 0.
@@ -2448,7 +2448,7 @@ size_t zebra_interface_link_params_write(struct stream *s,
}
/*
- * format of message for address additon is:
+ * format of message for address addition is:
* 0
* 0 1 2 3 4 5 6 7
* +-+-+-+-+-+-+-+-+
@@ -2713,9 +2713,9 @@ static int zclient_read_sync_response(struct zclient *zclient,
return 0;
}
/**
- * Connect to label manager in a syncronous way
+ * Connect to label manager in a synchronous way
*
- * It first writes the request to zcient output buffer and then
+ * It first writes the request to zclient output buffer and then
* immediately reads the answer from the input buffer.
*
* @param zclient Zclient used to connect to label manager (zebra)
@@ -2808,7 +2808,7 @@ stream_failure:
}
/**
- * Function to request a srv6-locator chunk in an Asyncronous way
+ * Function to request a srv6-locator chunk in an asynchronous way
*
* @param zclient Zclient used to connect to table manager (zebra)
* @param locator_name Name of SRv6-locator
@@ -2918,9 +2918,9 @@ enum zclient_send_status zclient_send_get_label_chunk(struct zclient *zclient,
}
/**
- * Function to request a label chunk in a syncronous way
+ * Function to request a label chunk in a synchronous way
*
- * It first writes the request to zlcient output buffer and then
+ * It first writes the request to zclient output buffer and then
* immediately reads the answer from the input buffer.
*
* @param zclient Zclient used to connect to label manager (zebra)
@@ -3095,9 +3095,9 @@ int lm_release_label_chunk(struct zclient *zclient, uint32_t start,
}
/**
- * Connect to table manager in a syncronous way
+ * Connect to table manager in a synchronous way
*
- * It first writes the request to zcient output buffer and then
+ * It first writes the request to zclient output buffer and then
* immediately reads the answer from the input buffer.
*
* @param zclient Zclient used to connect to table manager (zebra)
@@ -3154,7 +3154,7 @@ stream_failure:
}
/**
- * Function to request a table chunk in a syncronous way
+ * Function to request a table chunk in a synchronous way
*
* It first writes the request to zclient output buffer and then
* immediately reads the answer from the input buffer.
diff --git a/lib/zclient.h b/lib/zclient.h
index 3c4df9e249..82eaefda42 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -299,7 +299,7 @@ struct zclient {
/* The thread master we schedule ourselves on */
struct thread_master *master;
- /* Priviledges to change socket values */
+ /* Privileges to change socket values */
struct zebra_privs_t *privs;
/* Do we care about failure events for route install? */
@@ -342,7 +342,7 @@ struct zclient {
struct redist_proto mi_redist[AFI_MAX][ZEBRA_ROUTE_MAX];
vrf_bitmap_t redist[AFI_MAX][ZEBRA_ROUTE_MAX];
- /* Redistribute defauilt. */
+ /* Redistribute default. */
vrf_bitmap_t default_information[AFI_MAX];
/* Pointer to the callback functions. */
diff --git a/nhrpd/list.h b/nhrpd/list.h
deleted file mode 100644
index a43687ac08..0000000000
--- a/nhrpd/list.h
+++ /dev/null
@@ -1,209 +0,0 @@
-/* Linux kernel style list handling function
- *
- * Written from scratch by Timo Teräs <timo.teras@iki.fi>, but modeled
- * after the linux kernel code.
- *
- * This file is free software: you may copy, redistribute and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef LIST_H
-#define LIST_H
-
-#ifndef NULL
-#define NULL 0L
-#endif
-
-#ifndef offsetof
-#ifdef __compiler_offsetof
-#define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)
-#else
-#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
-#endif
-#endif
-
-#ifndef container_of
-#define container_of(ptr, type, member) \
- ({ \
- const typeof(((type *)0)->member) *__mptr = (ptr); \
- (type *)((char *)__mptr - offsetof(type, member)); \
- })
-#endif
-
-struct hlist_head {
- struct hlist_node *first;
-};
-
-struct hlist_node {
- struct hlist_node *next;
- struct hlist_node **pprev;
-};
-
-static inline int hlist_empty(const struct hlist_head *h)
-{
- return !h->first;
-}
-
-static inline int hlist_hashed(const struct hlist_node *n)
-{
- return n->pprev != NULL;
-}
-
-static inline void hlist_del(struct hlist_node *n)
-{
- struct hlist_node *next = n->next;
- struct hlist_node **pprev = n->pprev;
-
- *pprev = next;
- if (next)
- next->pprev = pprev;
-
- n->next = NULL;
- n->pprev = NULL;
-}
-
-static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
-{
- struct hlist_node *first = h->first;
-
- n->next = first;
- if (first)
- first->pprev = &n->next;
- n->pprev = &h->first;
- h->first = n;
-}
-
-static inline void hlist_add_after(struct hlist_node *n,
- struct hlist_node *prev)
-{
- n->next = prev->next;
- n->pprev = &prev->next;
- prev->next = n;
-}
-
-static inline struct hlist_node **hlist_tail_ptr(struct hlist_head *h)
-{
- struct hlist_node *n = h->first;
- if (n == NULL)
- return &h->first;
- while (n->next != NULL)
- n = n->next;
- return &n->next;
-}
-
-#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
-
-#define hlist_for_each(pos, head) \
- for (pos = (head)->first; pos; pos = pos->next)
-
-#define hlist_for_each_safe(pos, n, head) \
- for (pos = (head)->first; pos && ({ \
- n = pos->next; \
- 1; \
- }); \
- pos = n)
-
-#define hlist_for_each_entry(tpos, pos, head, member) \
- for (pos = (head)->first; \
- pos && ({ \
- tpos = hlist_entry(pos, typeof(*tpos), member); \
- 1; \
- }); \
- pos = pos->next)
-
-#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \
- for (pos = (head)->first; \
- pos && ({ \
- n = pos->next; \
- 1; \
- }) \
- && ({ \
- tpos = hlist_entry(pos, typeof(*tpos), member); \
- 1; \
- }); \
- pos = n)
-
-
-struct list_head {
- struct list_head *next, *prev;
-};
-
-#define LIST_INITIALIZER(l) { .next = &l, .prev = &l }
-
-static inline void list_init(struct list_head *list)
-{
- list->next = list;
- list->prev = list;
-}
-
-static inline void __list_add(struct list_head *new, struct list_head *prev,
- struct list_head *next)
-{
- next->prev = new;
- new->next = next;
- new->prev = prev;
- prev->next = new;
-}
-
-static inline void list_add(struct list_head *new, struct list_head *head)
-{
- __list_add(new, head, head->next);
-}
-
-static inline void list_add_tail(struct list_head *new, struct list_head *head)
-{
- __list_add(new, head->prev, head);
-}
-
-static inline void __list_del(struct list_head *prev, struct list_head *next)
-{
- next->prev = prev;
- prev->next = next;
-}
-
-static inline void list_del(struct list_head *entry)
-{
- __list_del(entry->prev, entry->next);
- entry->next = NULL;
- entry->prev = NULL;
-}
-
-static inline int list_hashed(const struct list_head *n)
-{
- return n->next != n && n->next != NULL;
-}
-
-static inline int list_empty(const struct list_head *n)
-{
- return !list_hashed(n);
-}
-
-#define list_next(ptr, type, member) \
- (list_hashed(ptr) ? container_of((ptr)->next, type, member) : NULL)
-
-#define list_entry(ptr, type, member) container_of(ptr,type,member)
-
-#define list_for_each(pos, head) \
- for (pos = (head)->next; pos != (head); pos = pos->next)
-
-#define list_for_each_safe(pos, n, head) \
- for (pos = (head)->next, n = pos->next; pos != (head); \
- pos = n, n = pos->next)
-
-#define list_for_each_entry(pos, head, member) \
- for (pos = list_entry((head)->next, typeof(*pos), member); \
- &pos->member != (head); \
- pos = list_entry(pos->member.next, typeof(*pos), member))
-
-#define list_for_each_entry_safe(pos, n, head, member) \
- for (pos = ((head)->next != head ? \
- list_entry((head)->next, typeof(*pos), member) : \
- NULL), \
- n = (pos ? \
- list_entry(pos->member.next, typeof(*pos), member) : NULL); \
- pos && (&pos->member != (head)); \
- pos = n, n = list_entry(n->member.next, typeof(*n), member))
-
-#endif
diff --git a/nhrpd/nhrp_cache.c b/nhrpd/nhrp_cache.c
index c358baecb2..3823464a73 100644
--- a/nhrpd/nhrp_cache.c
+++ b/nhrpd/nhrp_cache.c
@@ -315,7 +315,7 @@ static void nhrp_cache_peer_notifier(struct notifier_block *n,
static void nhrp_cache_reset_new(struct nhrp_cache *c)
{
THREAD_OFF(c->t_auth);
- if (list_hashed(&c->newpeer_notifier.notifier_entry))
+ if (notifier_list_anywhere(&c->newpeer_notifier))
nhrp_peer_notify_del(c->new.peer, &c->newpeer_notifier);
nhrp_peer_unref(c->new.peer);
memset(&c->new, 0, sizeof(c->new));
@@ -574,5 +574,5 @@ void nhrp_cache_notify_add(struct nhrp_cache *c, struct notifier_block *n,
void nhrp_cache_notify_del(struct nhrp_cache *c, struct notifier_block *n)
{
- notifier_del(n);
+ notifier_del(n, &c->notifier_list);
}
diff --git a/nhrpd/nhrp_interface.c b/nhrpd/nhrp_interface.c
index 2db8997bad..94cec0281f 100644
--- a/nhrpd/nhrp_interface.c
+++ b/nhrpd/nhrp_interface.c
@@ -79,8 +79,8 @@ static int nhrp_if_new_hook(struct interface *ifp)
for (afi = 0; afi < AFI_MAX; afi++) {
struct nhrp_afi_data *ad = &nifp->afi[afi];
ad->holdtime = NHRPD_DEFAULT_HOLDTIME;
- list_init(&ad->nhslist_head);
- list_init(&ad->mcastlist_head);
+ nhrp_nhslist_init(&ad->nhslist_head);
+ nhrp_mcastlist_init(&ad->mcastlist_head);
}
return 0;
@@ -224,8 +224,12 @@ void nhrp_interface_update_nbma(struct interface *ifp,
nbmanifp = nbmaifp->info;
if (nbmaifp != nifp->nbmaifp) {
- if (nifp->nbmaifp)
- notifier_del(&nifp->nbmanifp_notifier);
+ if (nifp->nbmaifp) {
+ struct nhrp_interface *prev_nifp = nifp->nbmaifp->info;
+
+ notifier_del(&nifp->nbmanifp_notifier,
+ &prev_nifp->notifier_list);
+ }
nifp->nbmaifp = nbmaifp;
if (nbmaifp) {
notifier_add(&nifp->nbmanifp_notifier,
@@ -509,12 +513,15 @@ void nhrp_interface_notify_add(struct interface *ifp, struct notifier_block *n,
notifier_fn_t fn)
{
struct nhrp_interface *nifp = ifp->info;
+
notifier_add(n, &nifp->notifier_list, fn);
}
void nhrp_interface_notify_del(struct interface *ifp, struct notifier_block *n)
{
- notifier_del(n);
+ struct nhrp_interface *nifp = ifp->info;
+
+ notifier_del(n, &nifp->notifier_list);
}
void nhrp_interface_set_protection(struct interface *ifp, const char *profile,
diff --git a/nhrpd/nhrp_main.c b/nhrpd/nhrp_main.c
index 73684046a8..4c98f02e1d 100644
--- a/nhrpd/nhrp_main.c
+++ b/nhrpd/nhrp_main.c
@@ -55,8 +55,10 @@ struct zebra_privs_t nhrpd_privs = {
#endif
.caps_p = _caps_p,
.cap_num_p = array_size(_caps_p),
+ .cap_num_i = 0
};
+
static void parse_arguments(int argc, char **argv)
{
int opt;
diff --git a/nhrpd/nhrp_multicast.c b/nhrpd/nhrp_multicast.c
index 339b6dfabe..d8372ae8a8 100644
--- a/nhrpd/nhrp_multicast.c
+++ b/nhrpd/nhrp_multicast.c
@@ -219,7 +219,9 @@ void netlink_mcast_set_nflog_group(int nlgroup)
static int nhrp_multicast_free(struct interface *ifp,
struct nhrp_multicast *mcast)
{
- list_del(&mcast->list_entry);
+ struct nhrp_interface *nifp = ifp->info;
+
+ nhrp_mcastlist_del(&nifp->afi[mcast->afi].mcastlist_head, mcast);
XFREE(MTYPE_NHRP_MULTICAST, mcast);
return 0;
}
@@ -230,8 +232,7 @@ int nhrp_multicast_add(struct interface *ifp, afi_t afi,
struct nhrp_interface *nifp = ifp->info;
struct nhrp_multicast *mcast;
- list_for_each_entry(mcast, &nifp->afi[afi].mcastlist_head, list_entry)
- {
+ frr_each (nhrp_mcastlist, &nifp->afi[afi].mcastlist_head, mcast) {
if (sockunion_same(&mcast->nbma_addr, nbma_addr))
return NHRP_ERR_ENTRY_EXISTS;
}
@@ -241,7 +242,7 @@ int nhrp_multicast_add(struct interface *ifp, afi_t afi,
*mcast = (struct nhrp_multicast){
.afi = afi, .ifp = ifp, .nbma_addr = *nbma_addr,
};
- list_add_tail(&mcast->list_entry, &nifp->afi[afi].mcastlist_head);
+ nhrp_mcastlist_add_tail(&nifp->afi[afi].mcastlist_head, mcast);
debugf(NHRP_DEBUG_COMMON, "Adding multicast entry (%pSU)", nbma_addr);
@@ -252,11 +253,9 @@ int nhrp_multicast_del(struct interface *ifp, afi_t afi,
union sockunion *nbma_addr)
{
struct nhrp_interface *nifp = ifp->info;
- struct nhrp_multicast *mcast, *tmp;
+ struct nhrp_multicast *mcast;
- list_for_each_entry_safe(mcast, tmp, &nifp->afi[afi].mcastlist_head,
- list_entry)
- {
+ frr_each_safe (nhrp_mcastlist, &nifp->afi[afi].mcastlist_head, mcast) {
if (!sockunion_same(&mcast->nbma_addr, nbma_addr))
continue;
@@ -274,17 +273,15 @@ int nhrp_multicast_del(struct interface *ifp, afi_t afi,
void nhrp_multicast_interface_del(struct interface *ifp)
{
struct nhrp_interface *nifp = ifp->info;
- struct nhrp_multicast *mcast, *tmp;
+ struct nhrp_multicast *mcast;
afi_t afi;
for (afi = 0; afi < AFI_MAX; afi++) {
- debugf(NHRP_DEBUG_COMMON,
- "Cleaning up multicast entries (%d)",
- !list_empty(&nifp->afi[afi].mcastlist_head));
+ debugf(NHRP_DEBUG_COMMON, "Cleaning up multicast entries (%zu)",
+ nhrp_mcastlist_count(&nifp->afi[afi].mcastlist_head));
- list_for_each_entry_safe(
- mcast, tmp, &nifp->afi[afi].mcastlist_head, list_entry)
- {
+ frr_each_safe (nhrp_mcastlist, &nifp->afi[afi].mcastlist_head,
+ mcast) {
nhrp_multicast_free(ifp, mcast);
}
}
@@ -297,8 +294,7 @@ void nhrp_multicast_foreach(struct interface *ifp, afi_t afi,
struct nhrp_interface *nifp = ifp->info;
struct nhrp_multicast *mcast;
- list_for_each_entry(mcast, &nifp->afi[afi].mcastlist_head, list_entry)
- {
+ frr_each (nhrp_mcastlist, &nifp->afi[afi].mcastlist_head, mcast) {
cb(mcast, ctx);
}
}
diff --git a/nhrpd/nhrp_nhs.c b/nhrpd/nhrp_nhs.c
index 5179f15ebf..597c125e17 100644
--- a/nhrpd/nhrp_nhs.c
+++ b/nhrpd/nhrp_nhs.c
@@ -254,7 +254,7 @@ static void nhrp_reg_delete(struct nhrp_registration *r)
{
nhrp_peer_notify_del(r->peer, &r->peer_notifier);
nhrp_peer_unref(r->peer);
- list_del(&r->reglist_entry);
+ nhrp_reglist_del(&r->nhs->reglist_head, r);
THREAD_OFF(r->t_register);
XFREE(MTYPE_NHRP_REGISTRATION, r);
}
@@ -264,10 +264,9 @@ nhrp_reg_by_nbma(struct nhrp_nhs *nhs, const union sockunion *nbma_addr)
{
struct nhrp_registration *r;
- list_for_each_entry(
- r, &nhs->reglist_head,
- reglist_entry) if (sockunion_same(&r->peer->vc->remote.nbma,
- nbma_addr)) return r;
+ frr_each (nhrp_reglist, &nhs->reglist_head, r)
+ if (sockunion_same(&r->peer->vc->remote.nbma, nbma_addr))
+ return r;
return NULL;
}
@@ -276,7 +275,7 @@ static void nhrp_nhs_resolve_cb(struct resolver_query *q, const char *errstr,
{
struct nhrp_nhs *nhs = container_of(q, struct nhrp_nhs, dns_resolve);
struct nhrp_interface *nifp = nhs->ifp->info;
- struct nhrp_registration *reg, *regn;
+ struct nhrp_registration *reg;
int i;
if (n < 0) {
@@ -289,8 +288,8 @@ static void nhrp_nhs_resolve_cb(struct resolver_query *q, const char *errstr,
thread_add_timer(master, nhrp_nhs_resolve, nhs, 2 * 60 * 60,
&nhs->t_resolve);
- list_for_each_entry(reg, &nhs->reglist_head, reglist_entry) reg->mark =
- 1;
+ frr_each (nhrp_reglist, &nhs->reglist_head, reg)
+ reg->mark = 1;
nhs->hub = 0;
for (i = 0; i < n; i++) {
@@ -309,19 +308,16 @@ static void nhrp_nhs_resolve_cb(struct resolver_query *q, const char *errstr,
reg->peer = nhrp_peer_get(nhs->ifp, &addrs[i]);
reg->nhs = nhs;
reg->timeout = 1;
- list_init(&reg->reglist_entry);
- list_add_tail(&reg->reglist_entry, &nhs->reglist_head);
+ nhrp_reglist_add_tail(&nhs->reglist_head, reg);
nhrp_peer_notify_add(reg->peer, &reg->peer_notifier,
nhrp_reg_peer_notify);
thread_add_timer_msec(master, nhrp_reg_send_req, reg, 50,
&reg->t_register);
}
- list_for_each_entry_safe(reg, regn, &nhs->reglist_head, reglist_entry)
- {
+ frr_each_safe (nhrp_reglist, &nhs->reglist_head, reg)
if (reg->mark)
nhrp_reg_delete(reg);
- }
}
static int nhrp_nhs_resolve(struct thread *t)
@@ -344,8 +340,7 @@ int nhrp_nhs_add(struct interface *ifp, afi_t afi, union sockunion *proto_addr,
&& sockunion_family(proto_addr) != afi2family(afi))
return NHRP_ERR_PROTOCOL_ADDRESS_MISMATCH;
- list_for_each_entry(nhs, &nifp->afi[afi].nhslist_head, nhslist_entry)
- {
+ frr_each (nhrp_nhslist, &nifp->afi[afi].nhslist_head, nhs) {
if (sockunion_family(&nhs->proto_addr) != AF_UNSPEC
&& sockunion_family(proto_addr) != AF_UNSPEC
&& sockunion_same(&nhs->proto_addr, proto_addr))
@@ -362,9 +357,9 @@ int nhrp_nhs_add(struct interface *ifp, afi_t afi, union sockunion *proto_addr,
.ifp = ifp,
.proto_addr = *proto_addr,
.nbma_fqdn = strdup(nbma_fqdn),
- .reglist_head = LIST_INITIALIZER(nhs->reglist_head),
+ .reglist_head = INIT_DLIST(nhs->reglist_head),
};
- list_add_tail(&nhs->nhslist_entry, &nifp->afi[afi].nhslist_head);
+ nhrp_nhslist_add_tail(&nifp->afi[afi].nhslist_head, nhs);
thread_add_timer_msec(master, nhrp_nhs_resolve, nhs, 1000,
&nhs->t_resolve);
@@ -375,36 +370,34 @@ int nhrp_nhs_del(struct interface *ifp, afi_t afi, union sockunion *proto_addr,
const char *nbma_fqdn)
{
struct nhrp_interface *nifp = ifp->info;
- struct nhrp_nhs *nhs, *nnhs;
+ struct nhrp_nhs *nhs;
int ret = NHRP_ERR_ENTRY_NOT_FOUND;
if (sockunion_family(proto_addr) != AF_UNSPEC
&& sockunion_family(proto_addr) != afi2family(afi))
return NHRP_ERR_PROTOCOL_ADDRESS_MISMATCH;
- list_for_each_entry_safe(nhs, nnhs, &nifp->afi[afi].nhslist_head,
- nhslist_entry)
- {
+ frr_each_safe (nhrp_nhslist, &nifp->afi[afi].nhslist_head, nhs) {
if (!sockunion_same(&nhs->proto_addr, proto_addr))
continue;
if (strcmp(nhs->nbma_fqdn, nbma_fqdn) != 0)
continue;
- nhrp_nhs_free(nhs);
+ nhrp_nhs_free(nifp, afi, nhs);
ret = NHRP_OK;
}
return ret;
}
-int nhrp_nhs_free(struct nhrp_nhs *nhs)
+int nhrp_nhs_free(struct nhrp_interface *nifp, afi_t afi, struct nhrp_nhs *nhs)
{
- struct nhrp_registration *r, *rn;
+ struct nhrp_registration *r;
- list_for_each_entry_safe(r, rn, &nhs->reglist_head, reglist_entry)
+ frr_each_safe (nhrp_reglist, &nhs->reglist_head, r)
nhrp_reg_delete(r);
THREAD_OFF(nhs->t_resolve);
- list_del(&nhs->nhslist_entry);
+ nhrp_nhslist_del(&nifp->afi[afi].nhslist_head, nhs);
free((void *)nhs->nbma_fqdn);
XFREE(MTYPE_NHRP_NHS, nhs);
return 0;
@@ -413,18 +406,15 @@ int nhrp_nhs_free(struct nhrp_nhs *nhs)
void nhrp_nhs_interface_del(struct interface *ifp)
{
struct nhrp_interface *nifp = ifp->info;
- struct nhrp_nhs *nhs, *tmp;
+ struct nhrp_nhs *nhs;
afi_t afi;
for (afi = 0; afi < AFI_MAX; afi++) {
- debugf(NHRP_DEBUG_COMMON, "Cleaning up nhs entries (%d)",
- !list_empty(&nifp->afi[afi].nhslist_head));
+ debugf(NHRP_DEBUG_COMMON, "Cleaning up nhs entries (%zu)",
+ nhrp_nhslist_count(&nifp->afi[afi].nhslist_head));
- list_for_each_entry_safe(nhs, tmp, &nifp->afi[afi].nhslist_head,
- nhslist_entry)
- {
- nhrp_nhs_free(nhs);
- }
+ frr_each_safe (nhrp_nhslist, &nifp->afi[afi].nhslist_head, nhs)
+ nhrp_nhs_free(nifp, afi, nhs);
}
}
@@ -433,15 +423,15 @@ void nhrp_nhs_terminate(void)
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
struct interface *ifp;
struct nhrp_interface *nifp;
- struct nhrp_nhs *nhs, *tmp;
+ struct nhrp_nhs *nhs;
afi_t afi;
FOR_ALL_INTERFACES (vrf, ifp) {
nifp = ifp->info;
for (afi = 0; afi < AFI_MAX; afi++) {
- list_for_each_entry_safe(
- nhs, tmp, &nifp->afi[afi].nhslist_head,
- nhslist_entry) nhrp_nhs_free(nhs);
+ frr_each_safe (nhrp_nhslist,
+ &nifp->afi[afi].nhslist_head, nhs)
+ nhrp_nhs_free(nifp, afi, nhs);
}
}
}
@@ -455,11 +445,10 @@ void nhrp_nhs_foreach(struct interface *ifp, afi_t afi,
struct nhrp_nhs *nhs;
struct nhrp_registration *reg;
- list_for_each_entry(nhs, &nifp->afi[afi].nhslist_head, nhslist_entry)
- {
- if (!list_empty(&nhs->reglist_head)) {
- list_for_each_entry(reg, &nhs->reglist_head,
- reglist_entry) cb(nhs, reg, ctx);
+ frr_each (nhrp_nhslist, &nifp->afi[afi].nhslist_head, nhs) {
+ if (nhrp_reglist_count(&nhs->reglist_head)) {
+ frr_each (nhrp_reglist, &nhs->reglist_head, reg)
+ cb(nhs, reg, ctx);
} else
cb(nhs, 0, ctx);
}
@@ -472,19 +461,14 @@ int nhrp_nhs_match_ip(union sockunion *in_ip, struct nhrp_interface *nifp)
struct nhrp_registration *reg;
for (i = 0; i < AFI_MAX; i++) {
- list_for_each_entry(nhs, &nifp->afi[i].nhslist_head,
- nhslist_entry)
- {
- if (!list_empty(&nhs->reglist_head)) {
- list_for_each_entry(reg, &nhs->reglist_head,
- reglist_entry)
- {
- if (!sockunion_cmp(
- in_ip,
- &reg->peer->vc->remote
- .nbma))
- return 1;
- }
+ frr_each (nhrp_nhslist, &nifp->afi[i].nhslist_head, nhs) {
+ if (!nhrp_reglist_count(&nhs->reglist_head))
+ continue;
+
+ frr_each (nhrp_reglist, &nhs->reglist_head, reg) {
+ if (!sockunion_cmp(in_ip,
+ &reg->peer->vc->remote.nbma))
+ return 1;
}
}
}
diff --git a/nhrpd/nhrp_peer.c b/nhrpd/nhrp_peer.c
index 030f4c0ff3..51cae44bd1 100644
--- a/nhrpd/nhrp_peer.c
+++ b/nhrpd/nhrp_peer.c
@@ -359,7 +359,7 @@ void nhrp_peer_notify_add(struct nhrp_peer *p, struct notifier_block *n,
void nhrp_peer_notify_del(struct nhrp_peer *p, struct notifier_block *n)
{
- notifier_del(n);
+ notifier_del(n, &p->notifier_list);
nhrp_peer_check_delete(p);
}
diff --git a/nhrpd/nhrp_vc.c b/nhrpd/nhrp_vc.c
index b3b657f3fa..4b45389dad 100644
--- a/nhrpd/nhrp_vc.c
+++ b/nhrpd/nhrp_vc.c
@@ -19,14 +19,18 @@
DEFINE_MTYPE_STATIC(NHRPD, NHRP_VC, "NHRP virtual connection");
+PREDECL_DLIST(childlist);
+
struct child_sa {
uint32_t id;
struct nhrp_vc *vc;
- struct list_head childlist_entry;
+ struct childlist_item childlist_entry;
};
+DECLARE_DLIST(childlist, struct child_sa, childlist_entry);
+
static struct hash *nhrp_vc_hash;
-static struct list_head childlist_head[512];
+static struct childlist_head childlist_head[512];
static unsigned int nhrp_vc_key(const void *peer_data)
{
@@ -104,8 +108,7 @@ int nhrp_vc_ipsec_updown(uint32_t child_id, struct nhrp_vc *vc)
uint32_t child_hash = child_id % array_size(childlist_head);
int abort_migration = 0;
- list_for_each_entry(lsa, &childlist_head[child_hash], childlist_entry)
- {
+ frr_each (childlist, &childlist_head[child_hash], lsa) {
if (lsa->id == child_id) {
sa = lsa;
break;
@@ -120,12 +123,9 @@ int nhrp_vc_ipsec_updown(uint32_t child_id, struct nhrp_vc *vc)
*sa = (struct child_sa){
.id = child_id,
- .childlist_entry =
- LIST_INITIALIZER(sa->childlist_entry),
.vc = NULL,
};
- list_add_tail(&sa->childlist_entry,
- &childlist_head[child_hash]);
+ childlist_add_tail(&childlist_head[child_hash], sa);
}
if (sa->vc == vc)
@@ -155,7 +155,7 @@ int nhrp_vc_ipsec_updown(uint32_t child_id, struct nhrp_vc *vc)
/* Update */
sa->vc = vc;
if (!vc) {
- list_del(&sa->childlist_entry);
+ childlist_del(&childlist_head[child_hash], sa);
XFREE(MTYPE_NHRP_VC, sa);
}
@@ -170,7 +170,7 @@ void nhrp_vc_notify_add(struct nhrp_vc *vc, struct notifier_block *n,
void nhrp_vc_notify_del(struct nhrp_vc *vc, struct notifier_block *n)
{
- notifier_del(n);
+ notifier_del(n, &vc->notifier_list);
nhrp_vc_check_delete(vc);
}
@@ -200,17 +200,16 @@ void nhrp_vc_init(void)
nhrp_vc_hash = hash_create(nhrp_vc_key, nhrp_vc_cmp, "NHRP VC hash");
for (i = 0; i < array_size(childlist_head); i++)
- list_init(&childlist_head[i]);
+ childlist_init(&childlist_head[i]);
}
void nhrp_vc_reset(void)
{
- struct child_sa *sa, *n;
+ struct child_sa *sa;
size_t i;
for (i = 0; i < array_size(childlist_head); i++) {
- list_for_each_entry_safe(sa, n, &childlist_head[i],
- childlist_entry)
+ frr_each_safe (childlist, &childlist_head[i], sa)
nhrp_vc_ipsec_updown(sa->id, 0);
}
}
diff --git a/nhrpd/nhrp_vty.c b/nhrpd/nhrp_vty.c
index 50161dae2f..0dfabcf6ae 100644
--- a/nhrpd/nhrp_vty.c
+++ b/nhrpd/nhrp_vty.c
@@ -1200,9 +1200,7 @@ static int interface_config_write(struct vty *vty)
nhrp_cache_config_foreach(
ifp, interface_config_write_nhrp_map, &mapctx);
- list_for_each_entry(nhs, &ad->nhslist_head,
- nhslist_entry)
- {
+ frr_each (nhrp_nhslist, &ad->nhslist_head, nhs) {
vty_out(vty, " %s nhrp nhs ", aficmd);
if (sockunion_family(&nhs->proto_addr)
== AF_UNSPEC)
@@ -1212,9 +1210,7 @@ static int interface_config_write(struct vty *vty)
vty_out(vty, " nbma %s\n", nhs->nbma_fqdn);
}
- list_for_each_entry(mcast, &ad->mcastlist_head,
- list_entry)
- {
+ frr_each (nhrp_mcastlist, &ad->mcastlist_head, mcast) {
vty_out(vty, " %s nhrp map multicast ", aficmd);
if (sockunion_family(&mcast->nbma_addr)
== AF_UNSPEC)
diff --git a/nhrpd/nhrpd.h b/nhrpd/nhrpd.h
index 96caa39040..753c6e9b22 100644
--- a/nhrpd/nhrpd.h
+++ b/nhrpd/nhrpd.h
@@ -10,8 +10,6 @@
#ifndef NHRPD_H
#define NHRPD_H
-#include "list.h"
-
#include "zbuf.h"
#include "zclient.h"
#include "debug.h"
@@ -42,48 +40,53 @@ struct notifier_block;
typedef void (*notifier_fn_t)(struct notifier_block *, unsigned long);
+PREDECL_DLIST(notifier_list);
+
struct notifier_block {
- struct list_head notifier_entry;
+ struct notifier_list_item notifier_entry;
notifier_fn_t action;
};
+DECLARE_DLIST(notifier_list, struct notifier_block, notifier_entry);
+
struct notifier_list {
- struct list_head notifier_head;
+ struct notifier_list_head head;
};
#define NOTIFIER_LIST_INITIALIZER(l) \
{ \
- .notifier_head = LIST_INITIALIZER((l)->notifier_head) \
+ .head = INIT_DLIST((l)->head) \
}
static inline void notifier_init(struct notifier_list *l)
{
- list_init(&l->notifier_head);
+ notifier_list_init(&l->head);
}
static inline void notifier_add(struct notifier_block *n,
struct notifier_list *l, notifier_fn_t action)
{
n->action = action;
- list_add_tail(&n->notifier_entry, &l->notifier_head);
+ notifier_list_add_tail(&l->head, n);
}
-static inline void notifier_del(struct notifier_block *n)
+static inline void notifier_del(struct notifier_block *n,
+ struct notifier_list *l)
{
- list_del(&n->notifier_entry);
+ notifier_list_del(&l->head, n);
}
static inline void notifier_call(struct notifier_list *l, int cmd)
{
- struct notifier_block *n, *nn;
- list_for_each_entry_safe(n, nn, &l->notifier_head, notifier_entry) {
+ struct notifier_block *n;
+
+ frr_each_safe (notifier_list, &l->head, n)
n->action(n, cmd);
- }
}
static inline int notifier_active(struct notifier_list *l)
{
- return !list_empty(&l->notifier_head);
+ return notifier_list_count(&l->head) > 0;
}
extern struct hash *nhrp_gre_list;
@@ -263,9 +266,13 @@ struct nhrp_shortcut {
struct notifier_block cache_notifier;
};
+PREDECL_DLIST(nhrp_nhslist);
+PREDECL_DLIST(nhrp_mcastlist);
+PREDECL_DLIST(nhrp_reglist);
+
struct nhrp_nhs {
struct interface *ifp;
- struct list_head nhslist_entry;
+ struct nhrp_nhslist_item nhslist_entry;
unsigned hub : 1;
afi_t afi;
@@ -274,18 +281,22 @@ struct nhrp_nhs {
struct thread *t_resolve;
struct resolver_query dns_resolve;
- struct list_head reglist_head;
+ struct nhrp_reglist_head reglist_head;
};
+DECLARE_DLIST(nhrp_nhslist, struct nhrp_nhs, nhslist_entry);
+
struct nhrp_multicast {
struct interface *ifp;
- struct list_head list_entry;
+ struct nhrp_mcastlist_item mcastlist_entry;
afi_t afi;
union sockunion nbma_addr; /* IP-address */
};
+DECLARE_DLIST(nhrp_mcastlist, struct nhrp_multicast, mcastlist_entry);
+
struct nhrp_registration {
- struct list_head reglist_entry;
+ struct nhrp_reglist_item reglist_entry;
struct thread *t_register;
struct nhrp_nhs *nhs;
struct nhrp_reqid reqid;
@@ -296,6 +307,8 @@ struct nhrp_registration {
struct notifier_block peer_notifier;
};
+DECLARE_DLIST(nhrp_reglist, struct nhrp_registration, reglist_entry);
+
#define NHRP_IFF_SHORTCUT 0x0001
#define NHRP_IFF_REDIRECT 0x0002
#define NHRP_IFF_REG_NO_UNIQUE 0x0100
@@ -330,8 +343,8 @@ struct nhrp_interface {
short configured_mtu;
unsigned short mtu;
unsigned int holdtime;
- struct list_head nhslist_head;
- struct list_head mcastlist_head;
+ struct nhrp_nhslist_head nhslist_head;
+ struct nhrp_mcastlist_head mcastlist_head;
} afi[AFI_MAX];
};
@@ -381,7 +394,7 @@ int nhrp_nhs_add(struct interface *ifp, afi_t afi, union sockunion *proto_addr,
const char *nbma_fqdn);
int nhrp_nhs_del(struct interface *ifp, afi_t afi, union sockunion *proto_addr,
const char *nbma_fqdn);
-int nhrp_nhs_free(struct nhrp_nhs *nhs);
+int nhrp_nhs_free(struct nhrp_interface *nifp, afi_t afi, struct nhrp_nhs *nhs);
void nhrp_nhs_terminate(void);
void nhrp_nhs_foreach(struct interface *ifp, afi_t afi,
void (*cb)(struct nhrp_nhs *, struct nhrp_registration *,
diff --git a/nhrpd/subdir.am b/nhrpd/subdir.am
index 9a186d6ed8..dc0c162c83 100644
--- a/nhrpd/subdir.am
+++ b/nhrpd/subdir.am
@@ -34,7 +34,6 @@ nhrpd_nhrpd_SOURCES = \
noinst_HEADERS += \
nhrpd/debug.h \
- nhrpd/list.h \
nhrpd/netlink.h \
nhrpd/nhrp_errors.h \
nhrpd/nhrp_protocol.h \
diff --git a/nhrpd/zbuf.c b/nhrpd/zbuf.c
index e191a90f2d..9cc2b56245 100644
--- a/nhrpd/zbuf.c
+++ b/nhrpd/zbuf.c
@@ -164,35 +164,33 @@ void *zbuf_may_pull_until(struct zbuf *zb, const char *sep, struct zbuf *msg)
void zbufq_init(struct zbuf_queue *zbq)
{
*zbq = (struct zbuf_queue){
- .queue_head = LIST_INITIALIZER(zbq->queue_head),
+ .queue_head = INIT_DLIST(zbq->queue_head),
};
}
void zbufq_reset(struct zbuf_queue *zbq)
{
- struct zbuf *buf, *bufn;
+ struct zbuf *buf;
- list_for_each_entry_safe(buf, bufn, &zbq->queue_head, queue_list)
- {
- list_del(&buf->queue_list);
+ frr_each_safe (zbuf_queue, &zbq->queue_head, buf) {
+ zbuf_queue_del(&zbq->queue_head, buf);
zbuf_free(buf);
}
}
void zbufq_queue(struct zbuf_queue *zbq, struct zbuf *zb)
{
- list_add_tail(&zb->queue_list, &zbq->queue_head);
+ zbuf_queue_add_tail(&zbq->queue_head, zb);
}
int zbufq_write(struct zbuf_queue *zbq, int fd)
{
struct iovec iov[16];
- struct zbuf *zb, *zbn;
+ struct zbuf *zb;
ssize_t r;
size_t iovcnt = 0;
- list_for_each_entry_safe(zb, zbn, &zbq->queue_head, queue_list)
- {
+ frr_each_safe (zbuf_queue, &zbq->queue_head, zb) {
iov[iovcnt++] = (struct iovec){
.iov_base = zb->head, .iov_len = zbuf_used(zb),
};
@@ -204,15 +202,14 @@ int zbufq_write(struct zbuf_queue *zbq, int fd)
if (r < 0)
return r;
- list_for_each_entry_safe(zb, zbn, &zbq->queue_head, queue_list)
- {
+ frr_each_safe (zbuf_queue, &zbq->queue_head, zb) {
if (r < (ssize_t)zbuf_used(zb)) {
zb->head += r;
return 1;
}
r -= zbuf_used(zb);
- list_del(&zb->queue_list);
+ zbuf_queue_del(&zbq->queue_head, zb);
zbuf_free(zb);
}
diff --git a/nhrpd/zbuf.h b/nhrpd/zbuf.h
index 2741860bfd..d036b10460 100644
--- a/nhrpd/zbuf.h
+++ b/nhrpd/zbuf.h
@@ -15,18 +15,22 @@
#include <endian.h>
#include <sys/types.h>
-#include "list.h"
+#include "typesafe.h"
+
+PREDECL_DLIST(zbuf_queue);
struct zbuf {
- struct list_head queue_list;
+ struct zbuf_queue_item queue_entry;
unsigned allocated : 1;
unsigned error : 1;
uint8_t *buf, *end;
uint8_t *head, *tail;
};
+DECLARE_DLIST(zbuf_queue, struct zbuf, queue_entry);
+
struct zbuf_queue {
- struct list_head queue_head;
+ struct zbuf_queue_head queue_head;
};
struct zbuf *zbuf_alloc(size_t size);
diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c
index cc1b2919c0..10541b09bb 100644
--- a/ospfd/ospf_lsa.c
+++ b/ospfd/ospf_lsa.c
@@ -2480,10 +2480,6 @@ ospf_router_lsa_install(struct ospf *ospf, struct ospf_lsa *new, int rt_recalc)
return new;
}
-#define OSPF_INTERFACE_TIMER_ON(T, F, V) \
- if (!(T)) \
- (T) = thread_add_timer(master, (F), oi, (V))
-
/* Install network-LSA to an area. */
static struct ospf_lsa *ospf_network_lsa_install(struct ospf *ospf,
struct ospf_interface *oi,
diff --git a/ospfd/ospf_lsa.h b/ospfd/ospf_lsa.h
index 5dcd072774..2e648b3354 100644
--- a/ospfd/ospf_lsa.h
+++ b/ospfd/ospf_lsa.h
@@ -223,10 +223,6 @@ struct as_external_lsa {
#define OSPF_LSA_UPDATE_DELAY 2
-#define OSPF_LSA_UPDATE_TIMER_ON(T, F) \
- if (!(T)) \
- (T) = thread_add_timer(master, (F), 0, 2)
-
#define CHECK_LSA_TYPE_1_TO_5_OR_7(type) \
((type == OSPF_ROUTER_LSA) || (type == OSPF_NETWORK_LSA) \
|| (type == OSPF_SUMMARY_LSA) || (type == OSPF_ASBR_SUMMARY_LSA) \
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index 766be60778..1e1057dc39 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -582,6 +582,7 @@ static void ospf_deferred_shutdown_finish(struct ospf *ospf)
/* ospfd being shut-down? If so, was this the last ospf instance? */
if (CHECK_FLAG(om->options, OSPF_MASTER_SHUTDOWN)
&& (listcount(om->ospf) == 0)) {
+ frr_fini();
exit(0);
}
diff --git a/pathd/path_cli.c b/pathd/path_cli.c
index 46242fd05a..bfeea8c3db 100644
--- a/pathd/path_cli.c
+++ b/pathd/path_cli.c
@@ -298,14 +298,15 @@ DEFPY(srte_no_segment_list,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_srte_segment_list(struct vty *vty, struct lyd_node *dnode,
+void cli_show_srte_segment_list(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " segment-list %s\n",
yang_dnode_get_string(dnode, "./name"));
}
-void cli_show_srte_segment_list_end(struct vty *vty, struct lyd_node *dnode)
+void cli_show_srte_segment_list_end(struct vty *vty,
+ const struct lyd_node *dnode)
{
vty_out(vty, " exit\n");
}
@@ -557,7 +558,7 @@ DEFPY(srte_segment_list_no_segment,
}
void cli_show_srte_segment_list_segment(struct vty *vty,
- struct lyd_node *dnode,
+ const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " index %s", yang_dnode_get_string(dnode, "./index"));
@@ -668,7 +669,7 @@ DEFPY(srte_no_policy,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_srte_policy(struct vty *vty, struct lyd_node *dnode,
+void cli_show_srte_policy(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " policy color %s endpoint %s\n",
@@ -676,7 +677,7 @@ void cli_show_srte_policy(struct vty *vty, struct lyd_node *dnode,
yang_dnode_get_string(dnode, "./endpoint"));
}
-void cli_show_srte_policy_end(struct vty *vty, struct lyd_node *dnode)
+void cli_show_srte_policy_end(struct vty *vty, const struct lyd_node *dnode)
{
vty_out(vty, " exit\n");
}
@@ -708,8 +709,8 @@ DEFPY(srte_policy_no_name,
}
-void cli_show_srte_policy_name(struct vty *vty, struct lyd_node *dnode,
- bool show_defaults)
+void cli_show_srte_policy_name(struct vty *vty, const struct lyd_node *dnode,
+ bool show_defaults)
{
vty_out(vty, " name %s\n", yang_dnode_get_string(dnode, NULL));
}
@@ -741,7 +742,7 @@ DEFPY(srte_policy_no_binding_sid,
}
void cli_show_srte_policy_binding_sid(struct vty *vty,
- struct lyd_node *dnode,
+ const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " binding-sid %s\n", yang_dnode_get_string(dnode, NULL));
@@ -1187,7 +1188,7 @@ static int config_write_metric_cb(const struct lyd_node *dnode, void *arg)
}
void cli_show_srte_policy_candidate_path(struct vty *vty,
- struct lyd_node *dnode,
+ const struct lyd_node *dnode,
bool show_defaults)
{
float bandwidth;
@@ -1253,7 +1254,7 @@ void cli_show_srte_policy_candidate_path(struct vty *vty,
}
void cli_show_srte_policy_candidate_path_end(struct vty *vty,
- struct lyd_node *dnode)
+ const struct lyd_node *dnode)
{
const char *type = yang_dnode_get_string(dnode, "./type");
@@ -1265,7 +1266,7 @@ static int config_write_dnode(const struct lyd_node *dnode, void *arg)
{
struct vty *vty = arg;
- nb_cli_show_dnode_cmds(vty, (struct lyd_node *)dnode, false);
+ nb_cli_show_dnode_cmds(vty, dnode, false);
return YANG_ITER_CONTINUE;
}
diff --git a/pathd/path_nb.h b/pathd/path_nb.h
index 6a918b8b82..dacc5eb0d8 100644
--- a/pathd/path_nb.h
+++ b/pathd/path_nb.h
@@ -110,23 +110,26 @@ int pathd_srte_policy_candidate_path_segment_list_name_destroy(
void pathd_apply_finish(struct nb_cb_apply_finish_args *args);
/* Optional 'cli_show' callbacks. */
-void cli_show_srte_segment_list(struct vty *vty, struct lyd_node *dnode,
+void cli_show_srte_segment_list(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_srte_segment_list_end(struct vty *vty, struct lyd_node *dnode);
-void cli_show_srte_segment_list_segment(struct vty *vty, struct lyd_node *dnode,
+void cli_show_srte_segment_list_end(struct vty *vty,
+ const struct lyd_node *dnode);
+void cli_show_srte_segment_list_segment(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_srte_policy(struct vty *vty, struct lyd_node *dnode,
+void cli_show_srte_policy(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_srte_policy_end(struct vty *vty, struct lyd_node *dnode);
-void cli_show_srte_policy_name(struct vty *vty, struct lyd_node *dnode,
+void cli_show_srte_policy_end(struct vty *vty, const struct lyd_node *dnode);
+void cli_show_srte_policy_name(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_srte_policy_binding_sid(struct vty *vty, struct lyd_node *dnode,
+void cli_show_srte_policy_binding_sid(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
void cli_show_srte_policy_candidate_path(struct vty *vty,
- struct lyd_node *dnode,
+ const struct lyd_node *dnode,
bool show_defaults);
void cli_show_srte_policy_candidate_path_end(struct vty *vty,
- struct lyd_node *dnode);
+ const struct lyd_node *dnode);
/* Utility functions */
typedef void (*of_pref_cp_t)(enum objfun_type type, void *arg);
diff --git a/pathd/pathd.c b/pathd/pathd.c
index 90b8727284..7f6d34f752 100644
--- a/pathd/pathd.c
+++ b/pathd/pathd.c
@@ -22,6 +22,7 @@
#include "log.h"
#include "lib_errors.h"
#include "network.h"
+#include "libfrr.h"
#include "pathd/pathd.h"
#include "pathd/path_zebra.h"
@@ -1223,6 +1224,7 @@ void pathd_shutdown(void)
{
path_ted_teardown();
srte_clean_zebra();
+ frr_fini();
}
void trigger_pathd_candidate_created(struct srte_candidate *candidate)
diff --git a/pbrd/pbr_map.c b/pbrd/pbr_map.c
index 053b7363a3..03e6bacf1e 100644
--- a/pbrd/pbr_map.c
+++ b/pbrd/pbr_map.c
@@ -178,9 +178,9 @@ static void pbr_map_pbrms_uninstall(struct pbr_map_sequence *pbrms)
}
static const char *const pbr_map_reason_str[] = {
- "Invalid NH-group", "Invalid NH", "No Nexthops",
- "Both NH and NH-Group", "Invalid Src or Dst", "Invalid VRF",
- "Deleting Sequence",
+ "Invalid NH-group", "Invalid NH", "No Nexthops",
+ "Both NH and NH-Group", "Invalid Src or Dst", "Invalid VRF",
+ "Both VLAN Set and Strip", "Deleting Sequence",
};
void pbr_map_reason_string(unsigned int reason, char *buf, int size)
@@ -539,6 +539,13 @@ struct pbr_map_sequence *pbrms_get(const char *name, uint32_t seqno)
pbrms->seqno = seqno;
pbrms->ruleno = pbr_nht_get_next_rule(seqno);
pbrms->parent = pbrm;
+
+ pbrms->action_vlan_id = 0;
+ pbrms->action_vlan_flags = 0;
+ pbrms->action_pcp = 0;
+
+ pbrms->action_queue_id = PBR_MAP_UNDEFINED_QUEUE_ID;
+
pbrms->reason =
PBR_MAP_INVALID_EMPTY |
PBR_MAP_INVALID_NO_NEXTHOPS;
@@ -601,10 +608,28 @@ pbr_map_sequence_check_nexthops_valid(struct pbr_map_sequence *pbrms)
static void pbr_map_sequence_check_not_empty(struct pbr_map_sequence *pbrms)
{
- if (!pbrms->src && !pbrms->dst && !pbrms->mark && !pbrms->dsfield)
+ if (!pbrms->src && !pbrms->dst && !pbrms->mark && !pbrms->dsfield
+ && !pbrms->action_vlan_id && !pbrms->action_vlan_flags
+ && !pbrms->action_pcp
+ && pbrms->action_queue_id == PBR_MAP_UNDEFINED_QUEUE_ID)
pbrms->reason |= PBR_MAP_INVALID_EMPTY;
}
+static void pbr_map_sequence_check_vlan_actions(struct pbr_map_sequence *pbrms)
+{
+ /* The set vlan tag action does the following:
+ * 1. If the frame is untagged, it tags the frame with the
+ * configured VLAN ID.
+ * 2. If the frame is tagged, if replaces the tag.
+ *
+ * The strip vlan action removes any inner tag, so it is invalid to
+ * specify both a set and strip action.
+ */
+ if ((pbrms->action_vlan_id != 0) && (pbrms->action_vlan_flags != 0))
+ pbrms->reason |= PBR_MAP_INVALID_SET_STRIP_VLAN;
+}
+
+
/*
* Checks to see if we think that the pbmrs is valid. If we think
* the config is valid return true.
@@ -612,7 +637,7 @@ static void pbr_map_sequence_check_not_empty(struct pbr_map_sequence *pbrms)
static void pbr_map_sequence_check_valid(struct pbr_map_sequence *pbrms)
{
pbr_map_sequence_check_nexthops_valid(pbrms);
-
+ pbr_map_sequence_check_vlan_actions(pbrms);
pbr_map_sequence_check_not_empty(pbrms);
}
diff --git a/pbrd/pbr_map.h b/pbrd/pbr_map.h
index 694b915f48..3527523fc1 100644
--- a/pbrd/pbr_map.h
+++ b/pbrd/pbr_map.h
@@ -104,6 +104,17 @@ struct pbr_map_sequence {
uint32_t mark;
/*
+ * Actions
+ */
+ uint8_t action_pcp;
+ uint8_t action_vlan_id;
+#define PBR_MAP_STRIP_INNER_ANY (1 << 0)
+ uint8_t action_vlan_flags;
+
+#define PBR_MAP_UNDEFINED_QUEUE_ID 0
+ uint32_t action_queue_id;
+
+ /*
* Family of the src/dst. Needed when deleting since we clear them
*/
unsigned char family;
@@ -158,6 +169,7 @@ struct pbr_map_sequence {
#define PBR_MAP_INVALID_BOTH_NHANDGRP (1 << 3)
#define PBR_MAP_INVALID_EMPTY (1 << 4)
#define PBR_MAP_INVALID_VRF (1 << 5)
+#define PBR_MAP_INVALID_SET_STRIP_VLAN (1 << 6)
uint64_t reason;
QOBJ_FIELDS;
diff --git a/pbrd/pbr_vty.c b/pbrd/pbr_vty.c
index 9436f4430b..a16d00c472 100644
--- a/pbrd/pbr_vty.c
+++ b/pbrd/pbr_vty.c
@@ -407,6 +407,82 @@ static void pbrms_clear_set_config(struct pbr_map_sequence *pbrms)
pbrms->nhs_installed = false;
}
+
+DEFPY(pbr_map_action_queue_id, pbr_map_action_queue_id_cmd,
+ "[no] set queue-id <(1-65535)$queue_id>",
+ NO_STR
+ "Set the rest of the command\n"
+ "Set based on egress port queue id\n"
+ "A valid value in range 1..65535 \n")
+{
+ struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
+
+ if (!no)
+ pbrms->action_queue_id = queue_id;
+ else if ((uint32_t)queue_id == pbrms->action_queue_id)
+ pbrms->action_queue_id = PBR_MAP_UNDEFINED_QUEUE_ID;
+
+ pbr_map_check(pbrms, true);
+
+ return CMD_SUCCESS;
+}
+
+DEFPY(pbr_map_action_pcp, pbr_map_action_pcp_cmd, "[no] set pcp <(0-7)$pcp>",
+ NO_STR
+ "Set the rest of the command\n"
+ "Set based on 802.1p Priority Code Point (PCP) value\n"
+ "A valid value in range 0..7\n")
+{
+ struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
+
+ if (!no)
+ pbrms->action_pcp = pcp;
+ else if (pcp == pbrms->action_pcp)
+ pbrms->action_pcp = 0;
+
+ pbr_map_check(pbrms, true);
+
+ return CMD_SUCCESS;
+}
+
+DEFPY(pbr_map_action_vlan_id, pbr_map_action_vlan_id_cmd,
+ "[no] set vlan <(1-4094)$vlan_id>",
+ NO_STR
+ "Set the rest of the command\n"
+ "Set action for VLAN tagging\n"
+ "A valid value in range 1..4094\n")
+{
+ struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
+
+ if (!no)
+ pbrms->action_vlan_id = vlan_id;
+ else if (pbrms->action_vlan_id == vlan_id)
+ pbrms->action_vlan_id = 0;
+
+ pbr_map_check(pbrms, true);
+
+ return CMD_SUCCESS;
+}
+
+DEFPY(pbr_map_action_strip_vlan, pbr_map_action_strip_vlan_cmd,
+ "[no] strip vlan",
+ NO_STR
+ "Strip the vlan tags from frame\n"
+ "Strip any inner vlan tag \n")
+{
+ struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
+
+ if (!no)
+ pbrms->action_vlan_flags = PBR_MAP_STRIP_INNER_ANY;
+ else
+ pbrms->action_vlan_flags = 0;
+
+ pbr_map_check(pbrms, true);
+
+ return CMD_SUCCESS;
+}
+
+
DEFPY(pbr_map_nexthop_group, pbr_map_nexthop_group_cmd,
"set nexthop-group NHGNAME$name",
"Set for the PBR-MAP\n"
@@ -764,6 +840,18 @@ static void vty_show_pbrms(struct vty *vty,
if (pbrms->mark)
vty_out(vty, " MARK Match: %u\n", pbrms->mark);
+ if (pbrms->action_queue_id != PBR_MAP_UNDEFINED_QUEUE_ID)
+ vty_out(vty, " Set Queue ID %u\n",
+ pbrms->action_queue_id);
+
+ if (pbrms->action_vlan_id != 0)
+ vty_out(vty, " Set VLAN ID %u\n", pbrms->action_vlan_id);
+ if (pbrms->action_vlan_flags == PBR_MAP_STRIP_INNER_ANY)
+ vty_out(vty, " Strip VLAN ID\n");
+ if (pbrms->action_pcp)
+ vty_out(vty, " Set PCP %u\n", pbrms->action_pcp);
+
+
if (pbrms->nhgrp_name) {
vty_out(vty, " Nexthop-Group: %s\n", pbrms->nhgrp_name);
@@ -1170,6 +1258,19 @@ static int pbr_vty_map_config_write_sequence(struct vty *vty,
if (pbrms->mark)
vty_out(vty, " match mark %u\n", pbrms->mark);
+
+ if (pbrms->action_queue_id != PBR_MAP_UNDEFINED_QUEUE_ID)
+ vty_out(vty, " set queue-id %d\n", pbrms->action_queue_id);
+
+ if (pbrms->action_pcp)
+ vty_out(vty, " set pcp %d\n", pbrms->action_pcp);
+
+ if (pbrms->action_vlan_id)
+ vty_out(vty, " set vlan %u\n", pbrms->action_vlan_id);
+
+ if (pbrms->action_vlan_flags == PBR_MAP_STRIP_INNER_ANY)
+ vty_out(vty, " strip vlan any\n");
+
if (pbrms->vrf_unchanged)
vty_out(vty, " set vrf unchanged\n");
@@ -1257,6 +1358,10 @@ void pbr_vty_init(void)
install_element(PBRMAP_NODE, &pbr_map_match_dscp_cmd);
install_element(PBRMAP_NODE, &pbr_map_match_ecn_cmd);
install_element(PBRMAP_NODE, &pbr_map_match_mark_cmd);
+ install_element(PBRMAP_NODE, &pbr_map_action_queue_id_cmd);
+ install_element(PBRMAP_NODE, &pbr_map_action_strip_vlan_cmd);
+ install_element(PBRMAP_NODE, &pbr_map_action_vlan_id_cmd);
+ install_element(PBRMAP_NODE, &pbr_map_action_pcp_cmd);
install_element(PBRMAP_NODE, &pbr_map_nexthop_group_cmd);
install_element(PBRMAP_NODE, &no_pbr_map_nexthop_group_cmd);
install_element(PBRMAP_NODE, &pbr_map_nexthop_cmd);
diff --git a/pbrd/pbr_zebra.c b/pbrd/pbr_zebra.c
index 4df01043a9..8a9bb0201e 100644
--- a/pbrd/pbr_zebra.c
+++ b/pbrd/pbr_zebra.c
@@ -546,6 +546,12 @@ static void pbr_encode_pbr_map_sequence(struct stream *s,
stream_putc(s, pbrms->dsfield);
stream_putl(s, pbrms->mark);
+ stream_putl(s, pbrms->action_queue_id);
+
+ stream_putw(s, pbrms->action_vlan_id);
+ stream_putw(s, pbrms->action_vlan_flags);
+ stream_putw(s, pbrms->action_pcp);
+
if (pbrms->vrf_unchanged || pbrms->vrf_lookup)
pbr_encode_pbr_map_sequence_vrf(s, pbrms, ifp);
else if (pbrms->nhgrp_name)
diff --git a/ripd/rip_cli.c b/ripd/rip_cli.c
index 8a3ce24f5e..5590b1833d 100644
--- a/ripd/rip_cli.c
+++ b/ripd/rip_cli.c
@@ -83,7 +83,7 @@ DEFPY_YANG (no_router_rip,
return nb_cli_apply_changes_clear_pending(vty, NULL);
}
-void cli_show_router_rip(struct vty *vty, struct lyd_node *dnode,
+void cli_show_router_rip(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
const char *vrf_name;
@@ -112,7 +112,7 @@ DEFPY_YANG (rip_allow_ecmp,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_rip_allow_ecmp(struct vty *vty, struct lyd_node *dnode,
+void cli_show_rip_allow_ecmp(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
if (!yang_dnode_get_bool(dnode, NULL))
@@ -138,7 +138,7 @@ DEFPY_YANG (rip_default_information_originate,
}
void cli_show_rip_default_information_originate(struct vty *vty,
- struct lyd_node *dnode,
+ const struct lyd_node *dnode,
bool show_defaults)
{
if (!yang_dnode_get_bool(dnode, NULL))
@@ -174,7 +174,7 @@ DEFPY_YANG (no_rip_default_metric,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_rip_default_metric(struct vty *vty, struct lyd_node *dnode,
+void cli_show_rip_default_metric(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " default-metric %s\n",
@@ -208,7 +208,7 @@ DEFPY_YANG (no_rip_distance,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_rip_distance(struct vty *vty, struct lyd_node *dnode,
+void cli_show_rip_distance(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
if (yang_dnode_is_default(dnode, NULL))
@@ -243,7 +243,7 @@ DEFPY_YANG (rip_distance_source,
prefix_str);
}
-void cli_show_rip_distance_source(struct vty *vty, struct lyd_node *dnode,
+void cli_show_rip_distance_source(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " distance %s %s",
@@ -271,7 +271,7 @@ DEFPY_YANG (rip_neighbor,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_rip_neighbor(struct vty *vty, struct lyd_node *dnode,
+void cli_show_rip_neighbor(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " neighbor %s\n", yang_dnode_get_string(dnode, NULL));
@@ -293,7 +293,7 @@ DEFPY_YANG (rip_network_prefix,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_rip_network_prefix(struct vty *vty, struct lyd_node *dnode,
+void cli_show_rip_network_prefix(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " network %s\n", yang_dnode_get_string(dnode, NULL));
@@ -315,7 +315,8 @@ DEFPY_YANG (rip_network_if,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_rip_network_interface(struct vty *vty, struct lyd_node *dnode,
+void cli_show_rip_network_interface(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " network %s\n", yang_dnode_get_string(dnode, NULL));
@@ -348,7 +349,7 @@ DEFPY_YANG (rip_offset_list,
ifname ? ifname : "*", direction);
}
-void cli_show_rip_offset_list(struct vty *vty, struct lyd_node *dnode,
+void cli_show_rip_offset_list(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
const char *interface;
@@ -380,7 +381,7 @@ DEFPY_YANG (rip_passive_default,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_rip_passive_default(struct vty *vty, struct lyd_node *dnode,
+void cli_show_rip_passive_default(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
if (!yang_dnode_get_bool(dnode, NULL))
@@ -417,14 +418,16 @@ DEFPY_YANG (rip_passive_interface,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_rip_passive_interface(struct vty *vty, struct lyd_node *dnode,
+void cli_show_rip_passive_interface(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " passive-interface %s\n",
yang_dnode_get_string(dnode, NULL));
}
-void cli_show_rip_non_passive_interface(struct vty *vty, struct lyd_node *dnode,
+void cli_show_rip_non_passive_interface(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " no passive-interface %s\n",
@@ -460,7 +463,7 @@ DEFPY_YANG (rip_redistribute,
protocol);
}
-void cli_show_rip_redistribute(struct vty *vty, struct lyd_node *dnode,
+void cli_show_rip_redistribute(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " redistribute %s",
@@ -490,7 +493,7 @@ DEFPY_YANG (rip_route,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_rip_route(struct vty *vty, struct lyd_node *dnode,
+void cli_show_rip_route(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " route %s\n", yang_dnode_get_string(dnode, NULL));
@@ -535,7 +538,7 @@ DEFPY_YANG (no_rip_timers,
return nb_cli_apply_changes(vty, "./timers");
}
-void cli_show_rip_timers(struct vty *vty, struct lyd_node *dnode,
+void cli_show_rip_timers(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " timers basic %s %s %s\n",
@@ -573,7 +576,7 @@ DEFPY_YANG (no_rip_version,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_rip_version(struct vty *vty, struct lyd_node *dnode,
+void cli_show_rip_version(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
/*
@@ -619,7 +622,8 @@ DEFPY_YANG (ip_rip_split_horizon,
return nb_cli_apply_changes(vty, "./frr-ripd:rip");
}
-void cli_show_ip_rip_split_horizon(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_rip_split_horizon(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
int value;
@@ -655,7 +659,7 @@ DEFPY_YANG (ip_rip_v2_broadcast,
return nb_cli_apply_changes(vty, "./frr-ripd:rip");
}
-void cli_show_ip_rip_v2_broadcast(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_rip_v2_broadcast(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
if (!yang_dnode_get_bool(dnode, NULL))
@@ -711,7 +715,8 @@ DEFPY_YANG (no_ip_rip_receive_version,
return nb_cli_apply_changes(vty, "./frr-ripd:rip");
}
-void cli_show_ip_rip_receive_version(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_rip_receive_version(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
switch (yang_dnode_get_enum(dnode, NULL)) {
@@ -780,7 +785,7 @@ DEFPY_YANG (no_ip_rip_send_version,
return nb_cli_apply_changes(vty, "./frr-ripd:rip");
}
-void cli_show_ip_rip_send_version(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_rip_send_version(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
switch (yang_dnode_get_enum(dnode, NULL)) {
@@ -860,7 +865,7 @@ DEFPY_YANG (no_ip_rip_authentication_mode,
}
void cli_show_ip_rip_authentication_scheme(struct vty *vty,
- struct lyd_node *dnode,
+ const struct lyd_node *dnode,
bool show_defaults)
{
switch (yang_dnode_get_enum(dnode, "./mode")) {
@@ -933,7 +938,7 @@ DEFPY_YANG (no_ip_rip_authentication_string,
}
void cli_show_ip_rip_authentication_string(struct vty *vty,
- struct lyd_node *dnode,
+ const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " ip rip authentication string %s\n",
@@ -982,7 +987,7 @@ DEFPY_YANG (no_ip_rip_authentication_key_chain,
}
void cli_show_ip_rip_authentication_key_chain(struct vty *vty,
- struct lyd_node *dnode,
+ const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " ip rip authentication key-chain %s\n",
diff --git a/ripd/rip_nb.h b/ripd/rip_nb.h
index 26bb3cb3bd..1e29f3b771 100644
--- a/ripd/rip_nb.h
+++ b/ripd/rip_nb.h
@@ -128,57 +128,62 @@ void ripd_instance_redistribute_apply_finish(
void ripd_instance_timers_apply_finish(struct nb_cb_apply_finish_args *args);
/* Optional 'cli_show' callbacks. */
-void cli_show_router_rip(struct vty *vty, struct lyd_node *dnode,
+void cli_show_router_rip(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_rip_allow_ecmp(struct vty *vty, struct lyd_node *dnode,
+void cli_show_rip_allow_ecmp(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
void cli_show_rip_default_information_originate(struct vty *vty,
- struct lyd_node *dnode,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_rip_default_metric(struct vty *vty, struct lyd_node *dnode,
+void cli_show_rip_default_metric(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_rip_distance(struct vty *vty, struct lyd_node *dnode,
+void cli_show_rip_distance(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_rip_distance_source(struct vty *vty, struct lyd_node *dnode,
+void cli_show_rip_distance_source(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_rip_neighbor(struct vty *vty, struct lyd_node *dnode,
+void cli_show_rip_neighbor(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_rip_network_prefix(struct vty *vty, struct lyd_node *dnode,
+void cli_show_rip_network_prefix(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_rip_network_interface(struct vty *vty, struct lyd_node *dnode,
+void cli_show_rip_network_interface(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_rip_offset_list(struct vty *vty, struct lyd_node *dnode,
+void cli_show_rip_offset_list(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_rip_passive_default(struct vty *vty, struct lyd_node *dnode,
+void cli_show_rip_passive_default(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_rip_passive_interface(struct vty *vty, struct lyd_node *dnode,
+void cli_show_rip_passive_interface(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_rip_non_passive_interface(struct vty *vty, struct lyd_node *dnode,
+void cli_show_rip_non_passive_interface(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_rip_redistribute(struct vty *vty, struct lyd_node *dnode,
+void cli_show_rip_redistribute(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_rip_route(struct vty *vty, struct lyd_node *dnode,
+void cli_show_rip_route(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_rip_timers(struct vty *vty, struct lyd_node *dnode,
+void cli_show_rip_timers(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_rip_version(struct vty *vty, struct lyd_node *dnode,
+void cli_show_rip_version(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_ip_rip_split_horizon(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_rip_split_horizon(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_ip_rip_v2_broadcast(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_rip_v2_broadcast(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_ip_rip_receive_version(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_rip_receive_version(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_ip_rip_send_version(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip_rip_send_version(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
void cli_show_ip_rip_authentication_scheme(struct vty *vty,
- struct lyd_node *dnode,
+ const struct lyd_node *dnode,
bool show_defaults);
void cli_show_ip_rip_authentication_string(struct vty *vty,
- struct lyd_node *dnode,
+ const struct lyd_node *dnode,
bool show_defaults);
void cli_show_ip_rip_authentication_key_chain(struct vty *vty,
- struct lyd_node *dnode,
+ const struct lyd_node *dnode,
bool show_defaults);
/* Notifications. */
diff --git a/ripngd/ripng_cli.c b/ripngd/ripng_cli.c
index 722c0c7dd6..63b75e723d 100644
--- a/ripngd/ripng_cli.c
+++ b/ripngd/ripng_cli.c
@@ -83,8 +83,8 @@ DEFPY_YANG (no_router_ripng,
return nb_cli_apply_changes_clear_pending(vty, NULL);
}
-void cli_show_router_ripng(struct vty *vty, struct lyd_node *dnode,
- bool show_defaults)
+void cli_show_router_ripng(struct vty *vty, const struct lyd_node *dnode,
+ bool show_defaults)
{
const char *vrf_name;
@@ -112,7 +112,7 @@ DEFPY_YANG (ripng_allow_ecmp,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_ripng_allow_ecmp(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ripng_allow_ecmp(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
if (!yang_dnode_get_bool(dnode, NULL))
@@ -138,7 +138,7 @@ DEFPY_YANG (ripng_default_information_originate,
}
void cli_show_ripng_default_information_originate(struct vty *vty,
- struct lyd_node *dnode,
+ const struct lyd_node *dnode,
bool show_defaults)
{
if (!yang_dnode_get_bool(dnode, NULL))
@@ -174,7 +174,8 @@ DEFPY_YANG (no_ripng_default_metric,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_ripng_default_metric(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ripng_default_metric(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " default-metric %s\n",
@@ -197,7 +198,8 @@ DEFPY_YANG (ripng_network_prefix,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_ripng_network_prefix(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ripng_network_prefix(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " network %s\n", yang_dnode_get_string(dnode, NULL));
@@ -219,7 +221,8 @@ DEFPY_YANG (ripng_network_if,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_ripng_network_interface(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ripng_network_interface(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " network %s\n", yang_dnode_get_string(dnode, NULL));
@@ -252,7 +255,7 @@ DEFPY_YANG (ripng_offset_list,
ifname ? ifname : "*", direction);
}
-void cli_show_ripng_offset_list(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ripng_offset_list(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
const char *interface;
@@ -284,7 +287,8 @@ DEFPY_YANG (ripng_passive_interface,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_ripng_passive_interface(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ripng_passive_interface(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " passive-interface %s\n",
@@ -320,7 +324,7 @@ DEFPY_YANG (ripng_redistribute,
protocol);
}
-void cli_show_ripng_redistribute(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ripng_redistribute(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " redistribute %s",
@@ -350,7 +354,7 @@ DEFPY_YANG (ripng_route,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_ripng_route(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ripng_route(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " route %s\n", yang_dnode_get_string(dnode, NULL));
@@ -373,7 +377,8 @@ DEFPY_YANG (ripng_aggregate_address,
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_ripng_aggregate_address(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ripng_aggregate_address(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " aggregate-address %s\n",
@@ -419,7 +424,7 @@ DEFPY_YANG (no_ripng_timers,
return nb_cli_apply_changes(vty, "./timers");
}
-void cli_show_ripng_timers(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ripng_timers(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " timers basic %s %s %s\n",
@@ -454,7 +459,8 @@ DEFPY_YANG (ipv6_ripng_split_horizon,
return nb_cli_apply_changes(vty, "./frr-ripngd:ripng");
}
-void cli_show_ipv6_ripng_split_horizon(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ipv6_ripng_split_horizon(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults)
{
int value;
diff --git a/ripngd/ripng_nb.h b/ripngd/ripng_nb.h
index d6aecbf6b0..cf04242480 100644
--- a/ripngd/ripng_nb.h
+++ b/ripngd/ripng_nb.h
@@ -101,32 +101,38 @@ void ripngd_instance_redistribute_apply_finish(
void ripngd_instance_timers_apply_finish(struct nb_cb_apply_finish_args *args);
/* Optional 'cli_show' callbacks. */
-void cli_show_router_ripng(struct vty *vty, struct lyd_node *dnode,
+void cli_show_router_ripng(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_ripng_allow_ecmp(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ripng_allow_ecmp(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
void cli_show_ripng_default_information_originate(struct vty *vty,
- struct lyd_node *dnode,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_ripng_default_metric(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ripng_default_metric(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_ripng_network_prefix(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ripng_network_prefix(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_ripng_network_interface(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ripng_network_interface(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_ripng_offset_list(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ripng_offset_list(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_ripng_passive_interface(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ripng_passive_interface(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_ripng_redistribute(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ripng_redistribute(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_ripng_route(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ripng_route(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_ripng_aggregate_address(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ripng_aggregate_address(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_ripng_timers(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ripng_timers(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_ipv6_ripng_split_horizon(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ipv6_ripng_split_horizon(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
#endif /* _FRR_RIPNG_NB_H_ */
diff --git a/staticd/static_vty.c b/staticd/static_vty.c
index 751a262775..95d1386a67 100644
--- a/staticd/static_vty.c
+++ b/staticd/static_vty.c
@@ -1002,7 +1002,7 @@ DEFPY_YANG(ipv6_route_vrf,
table_str, false, color_str);
}
-void static_cli_show(struct vty *vty, struct lyd_node *dnode,
+void static_cli_show(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
const char *vrf;
@@ -1012,7 +1012,7 @@ void static_cli_show(struct vty *vty, struct lyd_node *dnode,
vty_out(vty, "vrf %s\n", vrf);
}
-void static_cli_show_end(struct vty *vty, struct lyd_node *dnode)
+void static_cli_show_end(struct vty *vty, const struct lyd_node *dnode)
{
const char *vrf;
@@ -1154,7 +1154,7 @@ static void nexthop_cli_show(struct vty *vty, const struct lyd_node *route,
vty_out(vty, "\n");
}
-void static_nexthop_cli_show(struct vty *vty, struct lyd_node *dnode,
+void static_nexthop_cli_show(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
const struct lyd_node *path = yang_dnode_get_parent(dnode, "path-list");
@@ -1164,7 +1164,7 @@ void static_nexthop_cli_show(struct vty *vty, struct lyd_node *dnode,
nexthop_cli_show(vty, route, NULL, path, dnode, show_defaults);
}
-void static_src_nexthop_cli_show(struct vty *vty, struct lyd_node *dnode,
+void static_src_nexthop_cli_show(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
const struct lyd_node *path = yang_dnode_get_parent(dnode, "path-list");
@@ -1174,7 +1174,8 @@ void static_src_nexthop_cli_show(struct vty *vty, struct lyd_node *dnode,
nexthop_cli_show(vty, route, src, path, dnode, show_defaults);
}
-int static_nexthop_cli_cmp(struct lyd_node *dnode1, struct lyd_node *dnode2)
+int static_nexthop_cli_cmp(const struct lyd_node *dnode1,
+ const struct lyd_node *dnode2)
{
enum static_nh_type nh_type1, nh_type2;
struct prefix prefix1, prefix2;
@@ -1221,7 +1222,8 @@ int static_nexthop_cli_cmp(struct lyd_node *dnode1, struct lyd_node *dnode2)
yang_dnode_get_string(dnode2, "./vrf"));
}
-int static_route_list_cli_cmp(struct lyd_node *dnode1, struct lyd_node *dnode2)
+int static_route_list_cli_cmp(const struct lyd_node *dnode1,
+ const struct lyd_node *dnode2)
{
const char *afi_safi1, *afi_safi2;
afi_t afi1, afi2;
@@ -1246,7 +1248,8 @@ int static_route_list_cli_cmp(struct lyd_node *dnode1, struct lyd_node *dnode2)
return prefix_cmp(&prefix1, &prefix2);
}
-int static_src_list_cli_cmp(struct lyd_node *dnode1, struct lyd_node *dnode2)
+int static_src_list_cli_cmp(const struct lyd_node *dnode1,
+ const struct lyd_node *dnode2)
{
struct prefix prefix1, prefix2;
@@ -1256,7 +1259,8 @@ int static_src_list_cli_cmp(struct lyd_node *dnode1, struct lyd_node *dnode2)
return prefix_cmp(&prefix1, &prefix2);
}
-int static_path_list_cli_cmp(struct lyd_node *dnode1, struct lyd_node *dnode2)
+int static_path_list_cli_cmp(const struct lyd_node *dnode1,
+ const struct lyd_node *dnode2)
{
uint32_t table_id1, table_id2;
uint8_t distance1, distance2;
diff --git a/staticd/static_vty.h b/staticd/static_vty.h
index 8861afa468..84a359593f 100644
--- a/staticd/static_vty.h
+++ b/staticd/static_vty.h
@@ -23,17 +23,21 @@
extern "C" {
#endif
-void static_cli_show(struct vty *vty, struct lyd_node *dnode,
+void static_cli_show(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void static_cli_show_end(struct vty *vty, struct lyd_node *dnode);
-void static_nexthop_cli_show(struct vty *vty, struct lyd_node *dnode,
+void static_cli_show_end(struct vty *vty, const struct lyd_node *dnode);
+void static_nexthop_cli_show(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void static_src_nexthop_cli_show(struct vty *vty, struct lyd_node *dnode,
+void static_src_nexthop_cli_show(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-int static_nexthop_cli_cmp(struct lyd_node *dnode1, struct lyd_node *dnode2);
-int static_route_list_cli_cmp(struct lyd_node *dnode1, struct lyd_node *dnode2);
-int static_src_list_cli_cmp(struct lyd_node *dnode1, struct lyd_node *dnode2);
-int static_path_list_cli_cmp(struct lyd_node *dnode1, struct lyd_node *dnode2);
+int static_nexthop_cli_cmp(const struct lyd_node *dnode1,
+ const struct lyd_node *dnode2);
+int static_route_list_cli_cmp(const struct lyd_node *dnode1,
+ const struct lyd_node *dnode2);
+int static_src_list_cli_cmp(const struct lyd_node *dnode1,
+ const struct lyd_node *dnode2);
+int static_path_list_cli_cmp(const struct lyd_node *dnode1,
+ const struct lyd_node *dnode2);
void static_vty_init(void);
diff --git a/tests/.gitignore b/tests/.gitignore
index 498d7dd0b7..8cc2aa98f9 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -28,6 +28,7 @@
/lib/test_frrscript
/lib/test_frrlua
/lib/test_graph
+/lib/test_grpc
/lib/test_heavy
/lib/test_heavy_thread
/lib/test_heavy_wq
@@ -44,6 +45,7 @@
/lib/test_segv
/lib/test_seqlock
/lib/test_sig
+/lib/test_skiplist
/lib/test_srcdest_table
/lib/test_stream
/lib/test_table
diff --git a/tests/lib/test_typelist.h b/tests/lib/test_typelist.h
index 379a2396b4..8261616ed2 100644
--- a/tests/lib/test_typelist.h
+++ b/tests/lib/test_typelist.h
@@ -39,6 +39,8 @@
#define list_find concat(TYPE, _find)
#define list_find_lt concat(TYPE, _find_lt)
#define list_find_gteq concat(TYPE, _find_gteq)
+#define list_member concat(TYPE, _member)
+#define list_anywhere concat(TYPE, _anywhere)
#define list_del concat(TYPE, _del)
#define list_pop concat(TYPE, _pop)
#define list_swap_all concat(TYPE, _swap_all)
@@ -239,6 +241,13 @@ static void concat(test_, TYPE)(void)
ts_hash_headx(
&head, "swap2b",
"a538546a6e6ab0484e925940aa8dd02fd934408bbaed8cb66a0721841584d838");
+
+ while (list_pop(&other))
+ ;
+ list_fini(&other);
+ prng_free(prng_swap);
+
+ ts_ref("swap-cleanup");
#endif /* !IS_ATOMIC */
k = 0;
@@ -294,7 +303,7 @@ static void concat(test_, TYPE)(void)
#elif IS_HEAP(REALTYPE)
/* heap - partially sorted. */
prev = NULL;
- l = k / 2;
+ l = k / 4;
for (i = 0; i < l; i++) {
item = list_pop(&head);
if (prev)
@@ -303,7 +312,24 @@ static void concat(test_, TYPE)(void)
k--;
prev = item;
}
- ts_hash("pop", NULL);
+ ts_hash("pop#1", NULL);
+
+ for (i = 0; i < NITEM; i++)
+ assertf(list_member(&head, &itm[i]) == itm[i].scratchpad,
+ "%zu should:%d is:%d", i, itm[i].scratchpad,
+ list_member(&head, &itm[i]));
+ ts_hash("member", NULL);
+
+ l = k / 2;
+ for (; i < l; i++) {
+ item = list_pop(&head);
+ if (prev)
+ assert(prev->val < item->val);
+ item->scratchpad = 0;
+ k--;
+ prev = item;
+ }
+ ts_hash("pop#2", NULL);
#else /* !IS_UNIQ(REALTYPE) && !IS_HEAP(REALTYPE) */
for (i = 0; i < NITEM; i++) {
@@ -380,6 +406,14 @@ static void concat(test_, TYPE)(void)
assert(l + list_count(&head) == k);
ts_hashx("del", "cb2e5d80f08a803ef7b56c15e981b681adcea214bebc2f55e12e0bfb242b07ca");
+#if !IS_ATOMIC(REALTYPE)
+ for (i = 0; i < NITEM; i++)
+ assertf(list_member(&head, &itm[i]) == itm[i].scratchpad,
+ "%zu should:%d is:%d", i, itm[i].scratchpad,
+ list_member(&head, &itm[i]));
+ ts_hashx("member", "cb2e5d80f08a803ef7b56c15e981b681adcea214bebc2f55e12e0bfb242b07ca");
+#endif
+
frr_each_safe(list, &head, item) {
assert(item->scratchpad != 0);
@@ -449,6 +483,13 @@ static void concat(test_, TYPE)(void)
ts_hash_head(
&head, "swap2b",
"eabfcf1413936daaf20965abced95762f45110a6619b84aac7d38481bce4ea19");
+
+ while (list_pop(&other))
+ ;
+ list_fini(&other);
+ prng_free(prng_swap);
+
+ ts_ref("swap-cleanup");
#endif
for (i = 0; i < NITEM / 2; i++) {
@@ -461,7 +502,39 @@ static void concat(test_, TYPE)(void)
}
ts_hash("del-prng", "86d568a95eb429dab3162976c5a5f3f75aabc835932cd682aa280b6923549564");
+#if !IS_ATOMIC(REALTYPE)
+ for (i = 0; i < NITEM; i++) {
+ assertf(list_member(&head, &itm[i]) == itm[i].scratchpad,
+ "%zu should:%d is:%d", i, itm[i].scratchpad,
+ list_member(&head, &itm[i]));
+ assertf(list_anywhere(&itm[i]) == itm[i].scratchpad,
+ "%zu should:%d is:%d", i, itm[i].scratchpad,
+ list_anywhere(&itm[i]));
+ }
+ ts_hash("member", "86d568a95eb429dab3162976c5a5f3f75aabc835932cd682aa280b6923549564");
+#endif
+
l = 0;
+ while (l < (k / 4) && (prev = list_pop(&head))) {
+ assert(prev->scratchpad != 0);
+
+ prev->scratchpad = 0;
+ l++;
+ }
+ ts_hash("pop#1", "42b8950c880535b2d2e0c980f9845f7841ecf675c0fb9801aec4170d2036349d");
+
+#if !IS_ATOMIC(REALTYPE)
+ for (i = 0; i < NITEM; i++) {
+ assertf(list_member(&head, &itm[i]) == itm[i].scratchpad,
+ "%zu should:%d is:%d", i, itm[i].scratchpad,
+ list_member(&head, &itm[i]));
+ assertf(list_anywhere(&itm[i]) == itm[i].scratchpad,
+ "%zu should:%d is:%d", i, itm[i].scratchpad,
+ list_anywhere(&itm[i]));
+ }
+ ts_hash("member", "42b8950c880535b2d2e0c980f9845f7841ecf675c0fb9801aec4170d2036349d");
+#endif
+
while ((item = list_pop(&head))) {
assert(item->scratchpad != 0);
@@ -471,7 +544,7 @@ static void concat(test_, TYPE)(void)
assert(l == k);
assert(list_count(&head) == 0);
assert(list_first(&head) == NULL);
- ts_hash("pop", "df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119");
+ ts_hash("pop#2", "df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119");
prng_free(prng);
prng = prng_new(0x1e5a2d69);
@@ -650,6 +723,7 @@ static void concat(test_, TYPE)(void)
list_fini(&head);
ts_ref("fini");
ts_end();
+ prng_free(prng);
printfrr("%s end\n", str(TYPE));
}
@@ -680,6 +754,8 @@ static void concat(test_, TYPE)(void)
#undef list_find
#undef list_find_lt
#undef list_find_gteq
+#undef list_member
+#undef list_anywhere
#undef list_del
#undef list_pop
#undef list_swap_all
diff --git a/tests/topotests/bfd_isis_topo1/test_bfd_isis_topo1.py b/tests/topotests/bfd_isis_topo1/test_bfd_isis_topo1.py
index 3c176f25a3..27a4419329 100644
--- a/tests/topotests/bfd_isis_topo1/test_bfd_isis_topo1.py
+++ b/tests/topotests/bfd_isis_topo1/test_bfd_isis_topo1.py
@@ -72,7 +72,6 @@ import os
import sys
import pytest
import json
-from time import sleep
from functools import partial
# Save the Current Working Directory to find configuration files.
@@ -193,15 +192,14 @@ def test_bfd_isis_interface_failure_rt2_step3():
# By default BFD provides a recovery time of 900ms plus jitter, so let's wait
# initial 2 seconds to let the CI not suffer.
# TODO: add check for array size
- sleep(2)
router_compare_json_output(
- "rt1", "show ip route isis json", "step3/show_ip_route_rt2_down.ref", 1, 0
+ "rt1", "show ip route isis json", "step3/show_ip_route_rt2_down.ref", 20, 1
)
router_compare_json_output(
- "rt1", "show ipv6 route isis json", "step3/show_ipv6_route_rt2_down.ref", 1, 0
+ "rt1", "show ipv6 route isis json", "step3/show_ipv6_route_rt2_down.ref", 20, 1
)
router_compare_json_output(
- "rt1", "show bfd peers json", "step3/show_bfd_peers_rt2_down.ref", 1, 0
+ "rt1", "show bfd peers json", "step3/show_bfd_peers_rt2_down.ref", 20, 1
)
# Check recovery, this can take some time
@@ -232,15 +230,14 @@ def test_bfd_isis_interface_failure_rt3_step3():
# By default BFD provides a recovery time of 900ms plus jitter, so let's wait
# initial 2 seconds to let the CI not suffer.
# TODO: add check for array size
- sleep(2)
router_compare_json_output(
- "rt1", "show ip route isis json", "step3/show_ip_route_rt3_down.ref", 1, 0
+ "rt1", "show ip route isis json", "step3/show_ip_route_rt3_down.ref", 20, 1
)
router_compare_json_output(
- "rt1", "show ipv6 route isis json", "step3/show_ipv6_route_rt3_down.ref", 1, 0
+ "rt1", "show ipv6 route isis json", "step3/show_ipv6_route_rt3_down.ref", 20, 1
)
router_compare_json_output(
- "rt1", "show bfd peers json", "step3/show_bfd_peers_rt3_down.ref", 1, 0
+ "rt1", "show bfd peers json", "step3/show_bfd_peers_rt3_down.ref", 20, 1
)
# Check recovery, this can take some time
diff --git a/tests/topotests/bgp_ecmp_topo3/test_ibgp_ecmp_topo3.py b/tests/topotests/bgp_ecmp_topo3/test_ibgp_ecmp_topo3.py
index 54b3e80da5..2a51dc83ef 100644
--- a/tests/topotests/bgp_ecmp_topo3/test_ibgp_ecmp_topo3.py
+++ b/tests/topotests/bgp_ecmp_topo3/test_ibgp_ecmp_topo3.py
@@ -29,6 +29,7 @@ import os
import sys
import time
import pytest
+import re
from time import sleep
# Save the Current Working Directory to find configuration files.
@@ -221,6 +222,9 @@ def test_ecmp_fast_convergence(request, test_type, tgen, topo):
shutdown_bringup_interface(tgen, "r2", intf1, True)
shutdown_bringup_interface(tgen, "r2", intf2, True)
+ logger.info("Ensure that the links are still up")
+ result = verify_bgp_convergence(tgen, topo)
+
logger.info("Enable bgp fast-convergence cli")
raw_config = {
"r2": {
@@ -233,6 +237,13 @@ def test_ecmp_fast_convergence(request, test_type, tgen, topo):
result = apply_raw_config(tgen, raw_config)
assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+ logger.info("Ensure BGP has processed the cli")
+ r2 = tgen.gears["r2"]
+ output = r2.vtysh_cmd("show run")
+ verify = re.search(r"fast-convergence", output )
+ assert verify is not None, (
+ "r2 does not have the fast convergence command yet")
+
logger.info("Shutdown one link b/w r2 and r3")
shutdown_bringup_interface(tgen, "r2", intf1, False)
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_direct/scripts/adjacencies.py b/tests/topotests/bgp_l3vpn_to_bgp_direct/scripts/adjacencies.py
index 789f93b837..6cd92e293d 100644
--- a/tests/topotests/bgp_l3vpn_to_bgp_direct/scripts/adjacencies.py
+++ b/tests/topotests/bgp_l3vpn_to_bgp_direct/scripts/adjacencies.py
@@ -7,11 +7,18 @@ luCommand("ce1", 'vtysh -c "show bgp summary"', " 00:0", "wait", "Adjacencies up
luCommand("ce2", 'vtysh -c "show bgp summary"', " 00:0", "wait", "Adjacencies up", 180)
luCommand("ce3", 'vtysh -c "show bgp summary"', " 00:0", "wait", "Adjacencies up", 180)
luCommand(
+ "r1", 'vtysh -c "show ip route ospf"', "2.2.2.2", "wait", "OSPF Route has Arrived", 60)
+luCommand(
"r1", "ping 2.2.2.2 -c 1", " 0. packet loss", "wait", "PE->P2 (loopback) ping", 60
)
luCommand(
+ "r3", 'vtysh -c "show ip route ospf"', "2.2.2.2", "wait", "OSPF Route has Arrived", 60)
+luCommand(
"r3", "ping 2.2.2.2 -c 1", " 0. packet loss", "wait", "PE->P2 (loopback) ping", 60
)
+
+luCommand(
+ "r4", 'vtysh -c "show ip route ospf"', "2.2.2.2", "wait", "OSPF Route has Arrived", 60)
luCommand(
"r4", "ping 2.2.2.2 -c 1", " 0. packet loss", "wait", "PE->P2 (loopback) ping", 60
)
diff --git a/tests/topotests/bgp_lu_topo1/R2/labelpool.summ.json b/tests/topotests/bgp_lu_topo1/R2/labelpool.summ.json
index 29e6c2cbf7..9c817e8075 100644
--- a/tests/topotests/bgp_lu_topo1/R2/labelpool.summ.json
+++ b/tests/topotests/bgp_lu_topo1/R2/labelpool.summ.json
@@ -1,8 +1,8 @@
{
- "Ledger":506,
- "InUse":506,
+ "Ledger":0,
+ "InUse":0,
"Requests":0,
- "LabelChunks":11,
+ "LabelChunks":0,
"Pending":0,
"Reconnects":0
}
diff --git a/tests/topotests/bgp_lu_topo2/R1/bgpd.conf b/tests/topotests/bgp_lu_topo2/R1/bgpd.conf
new file mode 100644
index 0000000000..13383e20b6
--- /dev/null
+++ b/tests/topotests/bgp_lu_topo2/R1/bgpd.conf
@@ -0,0 +1,29 @@
+!
+no log unique-id
+!
+debug bgp labelpool
+debug bgp zebra
+!
+router bgp 1
+ bgp router-id 10.0.0.1
+ timers bgp 3 9
+ no bgp ebgp-requires-policy
+ no bgp network import-check
+ neighbor 10.0.0.2 remote-as 2
+! neighbor 10.0.0.2 solo
+ neighbor 10.0.0.2 timers connect 10
+ neighbor 10.0.4.4 remote-as 4
+! neighbor 10.0.4.4 solo
+ neighbor 10.0.4.4 timers connect 10
+!
+ address-family ipv4 unicast
+ no neighbor 10.0.0.2 activate
+ no neighbor 10.0.4.4 activate
+ redistribute connected
+ exit-address-family
+ !
+ address-family ipv4 labeled-unicast
+ neighbor 10.0.0.2 activate
+ neighbor 10.0.4.4 activate
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_lu_topo2/R1/labelpool.summ.json b/tests/topotests/bgp_lu_topo2/R1/labelpool.summ.json
new file mode 100644
index 0000000000..77705e8d35
--- /dev/null
+++ b/tests/topotests/bgp_lu_topo2/R1/labelpool.summ.json
@@ -0,0 +1,8 @@
+{
+ "Ledger":51,
+ "InUse":51,
+ "Requests":0,
+ "LabelChunks":2,
+ "Pending":0,
+ "Reconnects":0
+}
diff --git a/tests/topotests/bgp_lu_topo2/R1/zebra.conf b/tests/topotests/bgp_lu_topo2/R1/zebra.conf
new file mode 100644
index 0000000000..c782481860
--- /dev/null
+++ b/tests/topotests/bgp_lu_topo2/R1/zebra.conf
@@ -0,0 +1,13 @@
+!
+no log unique-id
+!
+debug zebra events
+debug zebra rib det
+debug zebra dplane
+debug zebra mpls
+!
+interface R1-eth0
+ ip address 10.0.0.1/24
+!
+interface R1-eth1
+ ip address 10.0.4.1/24
diff --git a/tests/topotests/bgp_lu_topo2/R2/bgpd.conf b/tests/topotests/bgp_lu_topo2/R2/bgpd.conf
new file mode 100644
index 0000000000..bab3b8dd78
--- /dev/null
+++ b/tests/topotests/bgp_lu_topo2/R2/bgpd.conf
@@ -0,0 +1,27 @@
+!
+no log unique-id
+!
+debug bgp labelpool
+debug bgp zebra
+!
+router bgp 2
+ bgp router-id 10.0.0.2
+ no bgp ebgp-requires-policy
+ no bgp network import-check
+ timers bgp 3 9
+ neighbor 10.0.0.1 remote-as 1
+ neighbor 10.0.0.1 timers connect 10
+ neighbor 10.0.1.3 remote-as 2
+ neighbor 10.0.1.3 update-source 10.0.1.2
+ neighbor 10.0.1.3 timers connect 10
+!
+ address-family ipv4 unicast
+ network 10.0.0.0/24
+ neighbor 10.0.1.3 activate
+ no neighbor 10.0.0.1 activate
+ exit-address-family
+ !
+ address-family ipv4 labeled-unicast
+ neighbor 10.0.0.1 activate
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_lu_topo2/R2/labelpool.summ.json b/tests/topotests/bgp_lu_topo2/R2/labelpool.summ.json
new file mode 100644
index 0000000000..eb1ae93b6c
--- /dev/null
+++ b/tests/topotests/bgp_lu_topo2/R2/labelpool.summ.json
@@ -0,0 +1,8 @@
+{
+ "Ledger":1,
+ "InUse":1,
+ "Requests":0,
+ "LabelChunks":1,
+ "Pending":0,
+ "Reconnects":0
+}
diff --git a/tests/topotests/bgp_lu_topo2/R2/zebra.conf b/tests/topotests/bgp_lu_topo2/R2/zebra.conf
new file mode 100644
index 0000000000..b8a03e4fcb
--- /dev/null
+++ b/tests/topotests/bgp_lu_topo2/R2/zebra.conf
@@ -0,0 +1,14 @@
+!
+no log unique-id
+!
+debug zebra events
+debug zebra dplane
+debug zebra mpls
+debug zebra rib det
+!
+interface R2-eth0
+ ip address 10.0.0.2/24
+!
+interface R2-eth1
+ ip address 10.0.1.2/24
+! \ No newline at end of file
diff --git a/tests/topotests/bgp_lu_topo2/R3/bgpd.conf b/tests/topotests/bgp_lu_topo2/R3/bgpd.conf
new file mode 100644
index 0000000000..2dfeaa3274
--- /dev/null
+++ b/tests/topotests/bgp_lu_topo2/R3/bgpd.conf
@@ -0,0 +1,70 @@
+log file /tmp/bgpd.log
+no log unique-id
+!
+!
+debug bgp updates
+!
+router bgp 2
+ bgp router-id 10.0.1.3
+ no bgp ebgp-requires-policy
+ no bgp network import-check
+ timers bgp 3 9
+ neighbor 10.0.1.2 remote-as 2
+ neighbor 10.0.1.2 timers connect 10
+ !
+ address-family ipv4 unicast
+ neighbor 10.0.1.2 activate
+ network 10.0.1.0/24
+ network 11.0.0.1/32
+ network 11.0.0.2/32
+ network 11.0.0.3/32
+ network 11.0.0.4/32
+ network 11.0.0.5/32
+ network 11.0.0.6/32
+ network 11.0.0.7/32
+ network 11.0.0.8/32
+ network 11.0.0.9/32
+ network 11.0.0.10/32
+ network 11.0.0.11/32
+ network 11.0.0.12/32
+ network 11.0.0.13/32
+ network 11.0.0.14/32
+ network 11.0.0.15/32
+ network 11.0.0.16/32
+ network 11.0.0.17/32
+ network 11.0.0.18/32
+ network 11.0.0.19/32
+ network 11.0.0.20/32
+ network 11.0.0.21/32
+ network 11.0.0.22/32
+ network 11.0.0.23/32
+ network 11.0.0.24/32
+ network 11.0.0.25/32
+ network 11.0.0.26/32
+ network 11.0.0.27/32
+ network 11.0.0.28/32
+ network 11.0.0.29/32
+ network 11.0.0.30/32
+ network 11.0.0.31/32
+ network 11.0.0.32/32
+ network 11.0.0.33/32
+ network 11.0.0.34/32
+ network 11.0.0.35/32
+ network 11.0.0.36/32
+ network 11.0.0.37/32
+ network 11.0.0.38/32
+ network 11.0.0.39/32
+ network 11.0.0.40/32
+ network 11.0.0.41/32
+ network 11.0.0.42/32
+ network 11.0.0.43/32
+ network 11.0.0.44/32
+ network 11.0.0.45/32
+ network 11.0.0.46/32
+ network 11.0.0.47/32
+ network 11.0.0.48/32
+ network 11.0.0.49/32
+ network 11.0.0.50/32
+ exit-address-family
+ !
+!
diff --git a/tests/topotests/bgp_lu_topo2/R3/staticd.conf b/tests/topotests/bgp_lu_topo2/R3/staticd.conf
new file mode 100644
index 0000000000..867fc5a837
--- /dev/null
+++ b/tests/topotests/bgp_lu_topo2/R3/staticd.conf
@@ -0,0 +1,5 @@
+log file /tmp/staticd.log
+no log unique-id
+!
+!
+ip route 10.0.4.0/24 10.0.1.2
diff --git a/tests/topotests/bgp_lu_topo2/R3/zebra.conf b/tests/topotests/bgp_lu_topo2/R3/zebra.conf
new file mode 100644
index 0000000000..e4234de48c
--- /dev/null
+++ b/tests/topotests/bgp_lu_topo2/R3/zebra.conf
@@ -0,0 +1,11 @@
+log file /tmp/zebra.log
+no log unique-id
+!
+!
+debug zebra events
+debug zebra packet detail
+debug zebra mpls
+!
+interface R3-eth0
+ ip address 10.0.1.3/24
+!
diff --git a/tests/topotests/bgp_lu_topo2/R4/bgpd.conf b/tests/topotests/bgp_lu_topo2/R4/bgpd.conf
new file mode 100644
index 0000000000..3cef827b86
--- /dev/null
+++ b/tests/topotests/bgp_lu_topo2/R4/bgpd.conf
@@ -0,0 +1,23 @@
+!
+no log unique-id
+!
+debug bgp labelpool
+debug bgp zebra
+!
+router bgp 4
+ bgp router-id 10.0.4.4
+ timers bgp 3 9
+ no bgp ebgp-requires-policy
+ no bgp network import-check
+ neighbor 10.0.4.1 remote-as 1
+ neighbor 10.0.4.1 solo
+ neighbor 10.0.4.1 timers connect 10
+!
+ address-family ipv4 unicast
+ no neighbor 10.0.4.1 activate
+ exit-address-family
+ !
+ address-family ipv4 labeled-unicast
+ neighbor 10.0.4.1 activate
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_lu_topo2/R4/zebra.conf b/tests/topotests/bgp_lu_topo2/R4/zebra.conf
new file mode 100644
index 0000000000..ba1b2bba6e
--- /dev/null
+++ b/tests/topotests/bgp_lu_topo2/R4/zebra.conf
@@ -0,0 +1,9 @@
+no log unique-id
+!
+debug zebra events
+debug zebra dplane
+debug zebra mpls
+debug zebra rib det
+!
+interface R4-eth0
+ ip address 10.0.4.4/24
diff --git a/tests/topotests/bgp_lu_topo2/test_bgp_lu2.py b/tests/topotests/bgp_lu_topo2/test_bgp_lu2.py
new file mode 100644
index 0000000000..fc9d2c433a
--- /dev/null
+++ b/tests/topotests/bgp_lu_topo2/test_bgp_lu2.py
@@ -0,0 +1,221 @@
+#!/usr/bin/env python
+#
+# test_bgp_lu2.py
+#
+# Part of FRR/NetDEF Topology Tests
+#
+# Copyright (c) 2020 by Volta Networks
+# Copyright (c) 2021 by Nvidia, Inc.
+#
+# 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_bgp_lu2.py: Test BGP LU label allocation
+"""
+
+import os
+import sys
+import json
+from functools import partial
+import pytest
+
+# 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.
+
+pytestmark = [pytest.mark.bgpd]
+
+#
+# Basic scenario for BGP-LU. Nodes are directly connected.
+# Node 3 is advertising routes to 2, which advertises them
+# as BGP-LU to 1; this way we get routes with actual labels, as
+# opposed to implicit-null routes in the 2-node case.
+#
+# R2 is an LER, with MPLS towards R1, and IP towards R3. R1 is an LSR, with
+# MPLS on both sides.
+#
+#
+# AS4 BGP-LU AS1 BGP-LU AS2 iBGP AS2
+# +-----+ +-----+ +-----+ +-----+
+# | |.4 .1| |.1 .2| |.2 .3| |
+# | 4 +-------------+ 1 +----------------+ 2 +-----------------+ 3 |
+# | | 10.0.4.0/24 | | 10.0.0.0/24 | | 10.0.1.0/24 | |
+# +-----+ +-----+ +-----+ +-----+
+#
+#
+
+
+def build_topo(tgen):
+ "Build function"
+
+ # This function's only purpose is to define allocation and relationship
+ # between routers, switches and hosts.
+ #
+ #
+ # Create routers
+ tgen.add_router("R1")
+ tgen.add_router("R2")
+ tgen.add_router("R3")
+ tgen.add_router("R4")
+
+ # R1-R2
+ switch = tgen.add_switch("s1")
+ switch.add_link(tgen.gears["R1"])
+ switch.add_link(tgen.gears["R2"])
+
+ # R2-R3
+ switch = tgen.add_switch("s2")
+ switch.add_link(tgen.gears["R2"])
+ switch.add_link(tgen.gears["R3"])
+
+ # R1-R4
+ switch = tgen.add_switch("s3")
+ switch.add_link(tgen.gears["R1"])
+ switch.add_link(tgen.gears["R4"])
+
+
+def setup_module(mod):
+ "Sets up the pytest environment"
+ # This function initiates the topology build with Topogen...
+ tgen = Topogen(build_topo, mod.__name__)
+
+ # Skip if no mpls support
+ if not tgen.hasmpls:
+ logger.info("MPLS is not available, skipping test")
+ pytest.skip("MPLS is not available, skipping")
+ return
+
+ # ... and here it calls Mininet initialization functions.
+ tgen.start_topology()
+
+ # This is a sample of configuration loading.
+ router_list = tgen.routers()
+
+ # Enable mpls input for routers, so we can ping
+ sval = "net.mpls.conf.{}.input"
+ topotest.sysctl_assure(router_list["R2"], sval.format("R2-eth0"), 1)
+ topotest.sysctl_assure(router_list["R1"], sval.format("R1-eth0"), 1)
+ topotest.sysctl_assure(router_list["R1"], sval.format("R1-eth1"), 1)
+ topotest.sysctl_assure(router_list["R4"], sval.format("R4-eth0"), 1)
+
+ # For all registered routers, load the zebra configuration file
+ 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_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
+ )
+
+ # Have static config for R3 too
+ if router == router_list["R3"]:
+ router.load_config(
+ TopoRouter.RD_STATIC, os.path.join(CWD, "{}/staticd.conf".format(rname))
+ )
+
+ # After loading the configurations, this function loads configured daemons.
+ 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 check_labelpool(router):
+ json_file = "{}/{}/labelpool.summ.json".format(CWD, router.name)
+ expected = json.loads(open(json_file).read())
+
+ test_func = partial(
+ topotest.router_json_cmp, router, "show bgp labelpool summary json", expected
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=20, wait=1)
+ assertmsg = '"{}" JSON output mismatches - Did not converge'.format(router.name)
+ assert result is None, assertmsg
+
+
+def test_converge_bgplu():
+ "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)
+
+ # TODO -- enable for debugging
+ # tgen.mininet_cli()
+
+ r1 = tgen.gears["R1"]
+ r2 = tgen.gears["R2"]
+
+ check_labelpool(r1)
+ check_labelpool(r2)
+
+
+def test_ping():
+ "Simple ping tests"
+
+ tgen = get_topogen()
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ #
+ logger.info("Ping from R2 to R3")
+ router = tgen.gears["R2"]
+ output = router.run("ping -c 4 -w 4 {}".format("10.0.1.3"))
+ assert " 0% packet loss" in output, "Ping R2->R3 FAILED"
+ logger.info("Ping from R2 to R3 ... success")
+
+ #
+ logger.info("Ping from R4 to R2")
+ router = tgen.gears["R4"]
+ output = router.run("ping -c 4 -w 4 {}".format("10.0.0.2"))
+ assert " 0% packet loss" in output, "Ping R4->R2 FAILED"
+ logger.info("Ping from R4 to R2 ... success")
+
+ #
+ logger.info("Ping from R4 to R3")
+ router = tgen.gears["R4"]
+ output = router.run("ping -c 4 -w 4 {}".format("10.0.1.3"))
+ assert " 0% packet loss" in output, "Ping R4->R3 FAILED"
+ logger.info("Ping from R4 to R3 ... success")
+
+
+def test_memory_leak():
+ "Run the memory leak test and report results."
+ tgen = get_topogen()
+ if not tgen.is_memleak_enabled():
+ pytest.skip("Memory leak test/report is disabled")
+
+ tgen.report_memory_leaks()
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/conftest.py b/tests/topotests/conftest.py
index 7fe6a5aea1..ce7878c240 100755
--- a/tests/topotests/conftest.py
+++ b/tests/topotests/conftest.py
@@ -21,13 +21,6 @@ from lib.topolog import logger
from lib.topotest import g_extra_config as topotest_extra_config
from lib.topotest import json_cmp_result
-try:
- from _pytest._code.code import ExceptionInfo
-
- leak_check_ok = True
-except ImportError:
- leak_check_ok = False
-
def pytest_addoption(parser):
"""
@@ -138,8 +131,7 @@ def pytest_addoption(parser):
def check_for_memleaks():
- if not topotest_extra_config["valgrind_memleaks"]:
- return
+ assert topotest_extra_config["valgrind_memleaks"]
leaks = []
tgen = get_topogen()
@@ -151,21 +143,25 @@ def check_for_memleaks():
existing = tgen.valgrind_existing_files
latest = glob.glob(os.path.join(logdir, "*.valgrind.*"))
+ daemons = set()
for vfile in latest:
if vfile in existing:
continue
- with open(vfile) as vf:
+ existing.append(vfile)
+ with open(vfile, encoding="ascii") as vf:
vfcontent = vf.read()
match = re.search(r"ERROR SUMMARY: (\d+) errors", vfcontent)
if match and match.group(1) != "0":
emsg = "{} in {}".format(match.group(1), vfile)
leaks.append(emsg)
+ daemons.add(re.match(r".*\.valgrind\.(.*)\.\d+", vfile).group(1))
+
+ if tgen is not None:
+ tgen.valgrind_existing_files = existing
if leaks:
- if leak_check_ok:
- pytest.fail("Memleaks found:\n\t" + "\n\t".join(leaks))
- else:
- logger.error("Memleaks found:\n\t" + "\n\t".join(leaks))
+ logger.error("valgrind memleaks found:\n\t%s", "\n\t".join(leaks))
+ pytest.fail("valgrind memleaks found for daemons: " + " ".join(daemons))
def pytest_runtest_logstart(nodeid, location):
@@ -178,18 +174,21 @@ def pytest_runtest_logfinish(nodeid, location):
topolog.logfinish(nodeid, location)
-def pytest_runtest_call():
- """
- This function must be run after setup_module(), it does standarized post
- setup routines. It is only being used for the 'topology-only' option.
- """
+@pytest.hookimpl(hookwrapper=True)
+def pytest_runtest_call(item: pytest.Item) -> None:
+ "Hook the function that is called to execute the test."
+
+ # For topology only run the CLI then exit
if topotest_extra_config["topology_only"]:
- tgen = get_topogen()
- if tgen is not None:
- # Allow user to play with the setup.
- tgen.cli()
+ get_topogen().cli()
+ pytest.exit("exiting after --topology-only")
+
+ # Let the default pytest_runtest_call execute the test function
+ yield
- pytest.exit("the topology executed successfully")
+ # Check for leaks if requested
+ if topotest_extra_config["valgrind_memleaks"]:
+ check_for_memleaks()
def pytest_assertrepr_compare(op, left, right):
@@ -333,7 +332,10 @@ def pytest_configure(config):
topotest_extra_config["pause"] = pause
assert_feature_windows(pause, "--pause")
- topotest_extra_config["topology_only"] = config.getoption("--topology-only")
+ topology_only = config.getoption("--topology-only")
+ if topology_only and is_xdist:
+ pytest.exit("Cannot use --topology-only with distributed test mode")
+ topotest_extra_config["topology_only"] = topology_only
# Check environment now that we have config
if not diagnose_env(rundir):
@@ -373,12 +375,6 @@ def pytest_runtest_makereport(item, call):
else:
pause = False
- if call.excinfo is None and call.when == "call":
- try:
- check_for_memleaks()
- except:
- call.excinfo = ExceptionInfo()
-
title = "unset"
if call.excinfo is None:
diff --git a/tests/topotests/ldp_topo1/test_ldp_topo1.py b/tests/topotests/ldp_topo1/test_ldp_topo1.py
index 834205f653..4a33edb9d1 100644
--- a/tests/topotests/ldp_topo1/test_ldp_topo1.py
+++ b/tests/topotests/ldp_topo1/test_ldp_topo1.py
@@ -64,6 +64,7 @@ import re
import sys
import pytest
from time import sleep
+from lib.topolog import logger
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from lib import topotest
@@ -225,6 +226,13 @@ def test_mpls_ldp_neighbor_establish():
if fatal_error != "":
pytest.skip(fatal_error)
+ neighbors_operational = {
+ 1: 1,
+ 2: 3,
+ 3: 2,
+ 4: 2,
+ }
+
# Wait for MPLS LDP neighbors to establish.
print("\n\n** Verify MPLS LDP neighbors to establish")
print("******************************************\n")
@@ -254,9 +262,14 @@ def test_mpls_ldp_neighbor_establish():
established = "" # Empty string shows NOT established
if re.search(operational, lines[j]):
found_operational += 1
+
+ logger.info("Found operational %d" % found_operational)
if found_operational < 1:
# Need at least one operational neighbor
established = "" # Empty string shows NOT established
+ else:
+ if found_operational != neighbors_operational[i]:
+ established = ""
if not established:
print("Waiting for r%s" % i)
sys.stdout.flush()
diff --git a/tests/topotests/lib/topotest.py b/tests/topotests/lib/topotest.py
index b98698185c..6ee000b0f4 100644
--- a/tests/topotests/lib/topotest.py
+++ b/tests/topotests/lib/topotest.py
@@ -1445,7 +1445,7 @@ class Router(Node):
running = self.listDaemons()
if running:
- for _ in range(0, 5):
+ for _ in range(0, 30):
sleep(
0.5,
"{}: waiting for daemons stopping: {}".format(
@@ -1725,7 +1725,7 @@ class Router(Node):
)
if valgrind_extra:
cmdenv += (
- "--gen-suppressions=all --expensive-definedness-checks=yes"
+ " --gen-suppressions=all --expensive-definedness-checks=yes"
)
elif daemon in strace_daemons or "all" in strace_daemons:
cmdenv = "strace -f -D -o {1}/{2}.strace.{0} ".format(
diff --git a/tests/topotests/ospf_gr_topo1/test_ospf_gr_topo1.py b/tests/topotests/ospf_gr_topo1/test_ospf_gr_topo1.py
index 3e3bf5cb8c..debf7ad766 100755
--- a/tests/topotests/ospf_gr_topo1/test_ospf_gr_topo1.py
+++ b/tests/topotests/ospf_gr_topo1/test_ospf_gr_topo1.py
@@ -231,7 +231,7 @@ def check_routers(initial_convergence=False, exiting=None, restarting=None):
tries = 240
else:
if restarting != None:
- tries = 40
+ tries = 60
else:
tries = 1
router_compare_json_output(
diff --git a/tests/topotests/pytest.ini b/tests/topotests/pytest.ini
index 33c5635eb2..7dd13935b1 100644
--- a/tests/topotests/pytest.ini
+++ b/tests/topotests/pytest.ini
@@ -81,4 +81,3 @@ markers =
# memleak_path = /tmp/memleak_
# Output files will be named after the testname:
# /tmp/memleak_test_ospf_topo1.txt
-memleak_path = /tmp/memleak_
diff --git a/tools/checkpatch.pl b/tools/checkpatch.pl
index cf15d00796..d2eb20ce5b 100755
--- a/tools/checkpatch.pl
+++ b/tools/checkpatch.pl
@@ -409,6 +409,25 @@ our $Operators = qr{
}x;
our $c90_Keywords = qr{do|for|while|if|else|return|goto|continue|switch|default|case|break}x;
+our $Iterators = qr{
+ frr_each|frr_each_safe|frr_each_from|
+ frr_with_mutex|frr_with_privs|
+ LIST_FOREACH|LIST_FOREACH_SAFE|
+ SLIST_FOREACH|SLIST_FOREACH_SAFE|SLIST_FOREACH_PREVPTR|
+ STAILQ_FOREACH|STAILQ_FOREACH_SAFE|
+ TAILQ_FOREACH|TAILQ_FOREACH_SAFE|TAILQ_FOREACH_REVERSE|TAILQ_FOREACH_REVERSE_SAFE|
+ RB_FOREACH|RB_FOREACH_SAFE|RB_FOREACH_REVERSE|RB_FOREACH_REVERSE_SAFE|
+ SPLAY_FOREACH|
+ FOR_ALL_INTERFACES|FOR_ALL_INTERFACES_ADDRESSES|JSON_FOREACH|
+ LY_FOR_KEYS|LY_LIST_FOR|LY_TREE_FOR|LY_TREE_DFS_BEGIN|LYD_TREE_DFS_BEGIN|
+ RE_DEST_FOREACH_ROUTE|RE_DEST_FOREACH_ROUTE_SAFE|
+ RNODE_FOREACH_RE|RNODE_FOREACH_RE_SAFE|
+ UPDGRP_FOREACH_SUBGRP|UPDGRP_FOREACH_SUBGRP_SAFE|
+ SUBGRP_FOREACH_PEER|SUBGRP_FOREACH_PEER_SAFE|
+ SUBGRP_FOREACH_ADJ|SUBGRP_FOREACH_ADJ_SAFE|
+ AF_FOREACH|FOREACH_AFI_SAFI|FOREACH_SAFI|
+ LSDB_LOOP
+ }x;
our $BasicType;
our $NonptrType;
@@ -1009,9 +1028,9 @@ sub top_of_kernel_tree {
my ($root) = @_;
my @tree_check = (
- "COPYING", "CREDITS", "Kbuild", "MAINTAINERS", "Makefile",
- "README", "Documentation", "arch", "include", "drivers",
- "fs", "init", "ipc", "kernel", "lib", "scripts",
+ "COPYING", "configure.ac", "Makefile.am",
+ "README.md", "doc", "lib", "vtysh", "watchfrr", "tests",
+ "zebra", "bgpd", "ospfd", "ospf6d", "isisd", "staticd",
);
foreach my $check (@tree_check) {
@@ -2655,8 +2674,8 @@ sub process {
(defined($1) || defined($2))))) {
$is_patch = 1;
$reported_maintainer_file = 1;
- WARN("FILE_PATH_CHANGES",
- "added, moved or deleted file(s), does MAINTAINERS need updating?\n" . $herecurr);
+ #WARN("FILE_PATH_CHANGES",
+ # "added, moved or deleted file(s), does MAINTAINERS need updating?\n" . $herecurr);
}
# Check for wrappage within a valid hunk of the file
@@ -4028,7 +4047,8 @@ sub process {
if|for|while|switch|return|case|
volatile|__volatile__|
__attribute__|format|__extension__|
- asm|__asm__)$/x)
+ asm|__asm__|
+ $Iterators)$/x)
{
# cpp #define statements have non-optional spaces, ie
# if there is a space between the name and the open
diff --git a/vrrpd/vrrp_vty.c b/vrrpd/vrrp_vty.c
index 91ff6fe28e..a612b0205a 100644
--- a/vrrpd/vrrp_vty.c
+++ b/vrrpd/vrrp_vty.c
@@ -75,7 +75,7 @@ DEFPY_YANG(vrrp_vrid,
return nb_cli_apply_changes(vty, VRRP_XPATH_ENTRY, vrid);
}
-void cli_show_vrrp(struct vty *vty, struct lyd_node *dnode, bool show_defaults)
+void cli_show_vrrp(struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
{
const char *vrid = yang_dnode_get_string(dnode, "./virtual-router-id");
const char *ver = yang_dnode_get_string(dnode, "./version");
@@ -103,7 +103,7 @@ DEFPY_YANG(vrrp_shutdown,
return nb_cli_apply_changes(vty, VRRP_XPATH_ENTRY, vrid);
}
-void cli_show_shutdown(struct vty *vty, struct lyd_node *dnode,
+void cli_show_shutdown(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
const char *vrid = yang_dnode_get_string(dnode, "../virtual-router-id");
@@ -145,7 +145,7 @@ DEFPY_YANG(no_vrrp_priority,
return nb_cli_apply_changes(vty, VRRP_XPATH_ENTRY, vrid);
}
-void cli_show_priority(struct vty *vty, struct lyd_node *dnode,
+void cli_show_priority(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
const char *vrid = yang_dnode_get_string(dnode, "../virtual-router-id");
@@ -191,7 +191,7 @@ DEFPY_YANG(no_vrrp_advertisement_interval,
return nb_cli_apply_changes(vty, VRRP_XPATH_ENTRY, vrid);
}
-void cli_show_advertisement_interval(struct vty *vty, struct lyd_node *dnode,
+void cli_show_advertisement_interval(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
const char *vrid = yang_dnode_get_string(dnode, "../virtual-router-id");
@@ -220,7 +220,7 @@ DEFPY_YANG(vrrp_ip,
return nb_cli_apply_changes(vty, VRRP_XPATH_ENTRY, vrid);
}
-void cli_show_ip(struct vty *vty, struct lyd_node *dnode, bool show_defaults)
+void cli_show_ip(struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
{
const char *vrid =
yang_dnode_get_string(dnode, "../../virtual-router-id");
@@ -248,7 +248,7 @@ DEFPY_YANG(vrrp_ip6,
return nb_cli_apply_changes(vty, VRRP_XPATH_ENTRY, vrid);
}
-void cli_show_ipv6(struct vty *vty, struct lyd_node *dnode, bool show_defaults)
+void cli_show_ipv6(struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
{
const char *vrid =
yang_dnode_get_string(dnode, "../../virtual-router-id");
@@ -274,7 +274,7 @@ DEFPY_YANG(vrrp_preempt,
return nb_cli_apply_changes(vty, VRRP_XPATH_ENTRY, vrid);
}
-void cli_show_preempt(struct vty *vty, struct lyd_node *dnode,
+void cli_show_preempt(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
const char *vrid = yang_dnode_get_string(dnode, "../virtual-router-id");
@@ -727,7 +727,7 @@ static int vrrp_config_write_interface(struct vty *vty)
struct interface *ifp;
FOR_ALL_INTERFACES (vrf, ifp) {
- struct lyd_node *dnode;
+ const struct lyd_node *dnode;
dnode = yang_dnode_getf(
running_config->dnode,
diff --git a/vrrpd/vrrp_vty.h b/vrrpd/vrrp_vty.h
index 6c6eef0327..587537a6f3 100644
--- a/vrrpd/vrrp_vty.h
+++ b/vrrpd/vrrp_vty.h
@@ -25,16 +25,20 @@
void vrrp_vty_init(void);
/* Northbound callbacks */
-void cli_show_vrrp(struct vty *vty, struct lyd_node *dnode, bool show_defaults);
-void cli_show_shutdown(struct vty *vty, struct lyd_node *dnode,
+void cli_show_vrrp(struct vty *vty, const struct lyd_node *dnode,
+ bool show_defaults);
+void cli_show_shutdown(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_priority(struct vty *vty, struct lyd_node *dnode,
+void cli_show_priority(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_advertisement_interval(struct vty *vty, struct lyd_node *dnode,
+void cli_show_advertisement_interval(struct vty *vty,
+ const struct lyd_node *dnode,
bool show_defaults);
-void cli_show_ip(struct vty *vty, struct lyd_node *dnode, bool show_defaults);
-void cli_show_ipv6(struct vty *vty, struct lyd_node *dnode, bool show_defaults);
-void cli_show_preempt(struct vty *vty, struct lyd_node *dnode,
+void cli_show_ip(struct vty *vty, const struct lyd_node *dnode,
+ bool show_defaults);
+void cli_show_ipv6(struct vty *vty, const struct lyd_node *dnode,
+ bool show_defaults);
+void cli_show_preempt(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
#endif /* __VRRP_VTY_H__ */
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c
index beb7045a7d..53349452e6 100644
--- a/vtysh/vtysh.c
+++ b/vtysh/vtysh.c
@@ -3923,6 +3923,8 @@ void vtysh_uninit(void)
void vtysh_init_vty(void)
{
+ cmd_defer_tree(true);
+
/* Make vty structure. */
vty = vty_new();
vty->type = VTY_SHELL;
diff --git a/zebra/debug_nl.c b/zebra/debug_nl.c
index 842579f89e..2175aaff60 100644
--- a/zebra/debug_nl.c
+++ b/zebra/debug_nl.c
@@ -29,6 +29,7 @@
#include <stdint.h>
#include "zebra/rt_netlink.h"
+#include "zebra/kernel_netlink.h"
const char *nlmsg_type2str(uint16_t type)
{
diff --git a/zebra/kernel_netlink.h b/zebra/kernel_netlink.h
index 37c76b9e59..cf8b8c785e 100644
--- a/zebra/kernel_netlink.h
+++ b/zebra/kernel_netlink.h
@@ -27,6 +27,10 @@ extern "C" {
#ifdef HAVE_NETLINK
+#define RTM_NHA(h) \
+ ((struct rtattr *)(((char *)(h)) + NLMSG_ALIGN(sizeof(struct nhmsg))))
+
+
#define NL_RCV_PKT_BUF_SIZE 32768
#define NL_PKT_BUF_SIZE 8192
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index 2e9b0b6ea2..61bd1417d1 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -3190,6 +3190,12 @@ static inline void zread_rule(ZAPI_HANDLER_ARGS)
STREAM_GETW(s, zpr.rule.filter.dst_port);
STREAM_GETC(s, zpr.rule.filter.dsfield);
STREAM_GETL(s, zpr.rule.filter.fwmark);
+
+ STREAM_GETL(s, zpr.rule.action.queue_id);
+ STREAM_GETW(s, zpr.rule.action.vlan_id);
+ STREAM_GETW(s, zpr.rule.action.vlan_flags);
+ STREAM_GETW(s, zpr.rule.action.pcp);
+
STREAM_GETL(s, zpr.rule.action.table);
STREAM_GET(ifname, s, INTERFACE_NAMSIZ);
@@ -3434,6 +3440,7 @@ static inline void zebra_gre_get(ZAPI_HANDLER_ARGS)
stream_putl(s, IFINDEX_INTERNAL);
stream_putl(s, VRF_UNKNOWN);
stream_putl(s, 0);
+ stream_putl(s, 0);
}
/* Write packet size. */
stream_putw_at(s, 0, stream_get_endp(s));
diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c
index ab06ea6438..9e9844390d 100644
--- a/zebra/zebra_dplane.c
+++ b/zebra/zebra_dplane.c
@@ -261,6 +261,13 @@ struct dplane_ctx_rule {
struct prefix src_ip;
struct prefix dst_ip;
uint8_t ip_proto;
+
+ uint8_t action_pcp;
+ uint16_t action_vlan_id;
+ uint16_t action_vlan_flags;
+
+ uint32_t action_queue_id;
+
char ifname[INTERFACE_NAMSIZ + 1];
};
@@ -2770,6 +2777,12 @@ static void dplane_ctx_rule_init_single(struct dplane_ctx_rule *dplane_rule,
dplane_rule->ip_proto = rule->rule.filter.ip_proto;
prefix_copy(&(dplane_rule->dst_ip), &rule->rule.filter.dst_ip);
prefix_copy(&(dplane_rule->src_ip), &rule->rule.filter.src_ip);
+
+ dplane_rule->action_pcp = rule->rule.action.pcp;
+ dplane_rule->action_vlan_flags = rule->rule.action.vlan_flags;
+ dplane_rule->action_vlan_id = rule->rule.action.vlan_id;
+ dplane_rule->action_queue_id = rule->rule.action.queue_id;
+
strlcpy(dplane_rule->ifname, rule->ifname, INTERFACE_NAMSIZ);
}
diff --git a/zebra/zebra_evpn.c b/zebra/zebra_evpn.c
index d5e043eea8..4006e1fed5 100644
--- a/zebra/zebra_evpn.c
+++ b/zebra/zebra_evpn.c
@@ -1423,8 +1423,24 @@ void zebra_evpn_rem_macip_add(vni_t vni, const struct ethaddr *macaddr,
* REMOTE - if ES is not local
*/
if (flags & ZEBRA_MACIP_TYPE_SYNC_PATH) {
- zebra_evpn_process_sync_macip_add(zevpn, macaddr, ipa_len,
- ipaddr, flags, seq, esi);
+ struct zebra_evpn_es *es;
+
+ es = zebra_evpn_es_find(esi);
+ if (es && (es->flags & ZEBRA_EVPNES_READY_FOR_BGP)) {
+ zebra_evpn_process_sync_macip_add(zevpn, macaddr,
+ ipa_len, ipaddr,
+ flags, seq, esi);
+ } else {
+ if (IS_ZEBRA_DEBUG_EVPN_MH_ES) {
+ char esi_str[ESI_STR_LEN];
+
+ esi_to_str(esi, esi_str, sizeof(esi_str));
+ zlog_debug(
+ "Ignore sync-macip add; ES %s is not ready",
+ esi_str);
+ }
+ }
+
return;
}
diff --git a/zebra/zebra_evpn_mac.c b/zebra/zebra_evpn_mac.c
index 472e53b730..c1bb19d4e5 100644
--- a/zebra/zebra_evpn_mac.c
+++ b/zebra/zebra_evpn_mac.c
@@ -1342,6 +1342,25 @@ int zebra_evpn_sync_mac_dp_install(struct zebra_mac *mac, bool set_inactive,
struct zebra_if *zif;
struct interface *br_ifp;
+ /* If the ES-EVI doesn't exist defer install. When the ES-EVI is
+ * created we will attempt to install the mac entry again
+ */
+ if (mac->es) {
+ struct zebra_evpn_es_evi *es_evi;
+
+ es_evi = zebra_evpn_es_evi_find(mac->es, mac->zevpn);
+ if (!es_evi) {
+ if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
+ zlog_debug(
+ "%s: dp-install sync-mac vni %u mac %pEA es %s 0x%x %sskipped, no es-evi",
+ caller, zevpn->vni, &mac->macaddr,
+ mac->es ? mac->es->esi_str : "-",
+ mac->flags,
+ set_inactive ? "inactive " : "");
+ return -1;
+ }
+ }
+
/* get the access vlan from the vxlan_device */
zebra_evpn_mac_get_access_info(mac, &ifp, &vid);
diff --git a/zebra/zebra_evpn_mh.c b/zebra/zebra_evpn_mh.c
index e03cf9db06..3f7e6256fc 100644
--- a/zebra/zebra_evpn_mh.c
+++ b/zebra/zebra_evpn_mh.c
@@ -186,8 +186,8 @@ static void zebra_evpn_es_evi_free(struct zebra_evpn_es_evi *es_evi)
}
/* find the ES-EVI in the per-L2-VNI RB tree */
-static struct zebra_evpn_es_evi *
-zebra_evpn_es_evi_find(struct zebra_evpn_es *es, struct zebra_evpn *zevpn)
+struct zebra_evpn_es_evi *zebra_evpn_es_evi_find(struct zebra_evpn_es *es,
+ struct zebra_evpn *zevpn)
{
struct zebra_evpn_es_evi es_evi;
@@ -229,6 +229,34 @@ static void zebra_evpn_local_es_evi_del(struct zebra_evpn_es *es,
zebra_evpn_local_es_evi_do_del(es_evi);
}
+/* If there are any existing MAC entries for this es/zevpn we need
+ * to install it in the dataplane.
+ *
+ * Note: primary purpose of this is to handle es del/re-add windows where
+ * sync MAC entries may be added by bgpd before the es-evi membership is
+ * created in the dataplane and in zebra
+ */
+static void zebra_evpn_es_evi_mac_install(struct zebra_evpn_es_evi *es_evi)
+{
+ struct zebra_mac *mac;
+ struct listnode *node;
+ struct zebra_evpn_es *es = es_evi->es;
+
+ if (listcount(es->mac_list) && IS_ZEBRA_DEBUG_EVPN_MH_ES)
+ zlog_debug("dp-mac install on es %s evi %d add", es->esi_str,
+ es_evi->zevpn->vni);
+
+ for (ALL_LIST_ELEMENTS_RO(es->mac_list, node, mac)) {
+ if (mac->zevpn != es_evi->zevpn)
+ continue;
+
+ if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
+ continue;
+
+ zebra_evpn_sync_mac_dp_install(mac, false, false, __func__);
+ }
+}
+
/* Create an ES-EVI if it doesn't already exist and tell BGP */
static void zebra_evpn_local_es_evi_add(struct zebra_evpn_es *es,
struct zebra_evpn *zevpn)
@@ -250,6 +278,8 @@ static void zebra_evpn_local_es_evi_add(struct zebra_evpn_es *es,
listnode_add(zevpn->local_es_evi_list, &es_evi->l2vni_listnode);
zebra_evpn_es_evi_re_eval_send_to_client(es_evi);
+
+ zebra_evpn_es_evi_mac_install(es_evi);
}
}
@@ -1050,15 +1080,15 @@ void zebra_evpn_if_cleanup(struct zebra_if *zif)
vlanid_t vid;
struct zebra_evpn_es *es;
- if (!bf_is_inited(zif->vlan_bitmap))
- return;
+ if (bf_is_inited(zif->vlan_bitmap)) {
+ bf_for_each_set_bit(zif->vlan_bitmap, vid, IF_VLAN_BITMAP_MAX)
+ {
+ zebra_evpn_vl_mbr_deref(vid, zif);
+ }
- bf_for_each_set_bit(zif->vlan_bitmap, vid, IF_VLAN_BITMAP_MAX) {
- zebra_evpn_vl_mbr_deref(vid, zif);
+ bf_free(zif->vlan_bitmap);
}
- bf_free(zif->vlan_bitmap);
-
/* Delete associated Ethernet Segment */
es = zif->es_info.es;
if (es)
diff --git a/zebra/zebra_evpn_mh.h b/zebra/zebra_evpn_mh.h
index 853af7c4bc..af6832092b 100644
--- a/zebra/zebra_evpn_mh.h
+++ b/zebra/zebra_evpn_mh.h
@@ -387,5 +387,7 @@ extern void zebra_evpn_acc_bd_svi_mac_add(struct interface *vlan_if);
extern void zebra_evpn_es_bypass_update(struct zebra_evpn_es *es,
struct interface *ifp, bool bypass);
extern void zebra_evpn_proc_remote_nh(ZAPI_HANDLER_ARGS);
+extern struct zebra_evpn_es_evi *
+zebra_evpn_es_evi_find(struct zebra_evpn_es *es, struct zebra_evpn *zevpn);
#endif /* _ZEBRA_EVPN_MH_H */
diff --git a/zebra/zebra_l2.c b/zebra/zebra_l2.c
index 5a02149611..30e74902aa 100644
--- a/zebra/zebra_l2.c
+++ b/zebra/zebra_l2.c
@@ -431,10 +431,10 @@ void zebra_l2if_update_bridge_slave(struct interface *ifp,
if (zif->zif_type == ZEBRA_IF_VXLAN
&& chgflags != ZEBRA_BRIDGE_NO_ACTION) {
- if (ZEBRA_BRIDGE_MASTER_MAC_CHANGE)
+ if (chgflags & ZEBRA_BRIDGE_MASTER_MAC_CHANGE)
zebra_vxlan_if_update(ifp,
ZEBRA_VXLIF_MASTER_MAC_CHANGE);
- if (ZEBRA_BRIDGE_MASTER_UP)
+ if (chgflags & ZEBRA_BRIDGE_MASTER_UP)
zebra_vxlan_if_update(ifp, ZEBRA_VXLIF_MASTER_CHANGE);
}
old_bridge_ifindex = zif->brslave_info.bridge_ifindex;
diff --git a/zebra/zebra_netns_notify.c b/zebra/zebra_netns_notify.c
index 61f97ce6a9..2d25801590 100644
--- a/zebra/zebra_netns_notify.c
+++ b/zebra/zebra_netns_notify.c
@@ -249,8 +249,8 @@ static int zebra_ns_notify_read(struct thread *t)
char buf[BUFSIZ];
ssize_t len;
- zebra_netns_notify_current = thread_add_read(
- zrouter.master, zebra_ns_notify_read, NULL, fd_monitor, NULL);
+ thread_add_read(zrouter.master, zebra_ns_notify_read, NULL, fd_monitor,
+ &zebra_netns_notify_current);
len = read(fd_monitor, buf, sizeof(buf));
if (len < 0) {
flog_err_sys(EC_ZEBRA_NS_NOTIFY_READ,
@@ -359,8 +359,8 @@ void zebra_ns_notify_init(void)
"NS notify watch: failed to add watch (%s)",
safe_strerror(errno));
}
- zebra_netns_notify_current = thread_add_read(
- zrouter.master, zebra_ns_notify_read, NULL, fd_monitor, NULL);
+ thread_add_read(zrouter.master, zebra_ns_notify_read, NULL, fd_monitor,
+ &zebra_netns_notify_current);
}
void zebra_ns_notify_close(void)
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 12e82dde94..fcac3328c9 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -3890,14 +3890,16 @@ void rib_update(enum rib_update_event event)
{
struct rib_update_ctx *ctx;
- ctx = rib_update_ctx_init(0, event);
+ if (thread_is_scheduled(t_rib_update_threads[event]))
+ return;
+ ctx = rib_update_ctx_init(0, event);
ctx->vrf_all = true;
- if (!thread_add_event(zrouter.master, rib_update_handler, ctx, 0,
- &t_rib_update_threads[event]))
- rib_update_ctx_fini(&ctx); /* Already scheduled */
- else if (IS_ZEBRA_DEBUG_EVENT)
+ thread_add_event(zrouter.master, rib_update_handler, ctx, 0,
+ &t_rib_update_threads[event]);
+
+ if (IS_ZEBRA_DEBUG_EVENT)
zlog_debug("%s: Scheduled VRF (ALL), event %s", __func__,
rib_update_event2str(event));
}
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index 5b79de9697..2cb2b5118b 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -449,6 +449,8 @@ static void zebra_show_ip_route_opaque(struct vty *vty, struct route_entry *re,
bzo.community);
json_object_string_add(json, "largeCommunities",
bzo.lcommunity);
+ json_object_string_add(json, "selectionReason",
+ bzo.selection_reason);
} else {
vty_out(vty, " AS-Path : %s\n", bzo.aspath);
@@ -459,6 +461,9 @@ static void zebra_show_ip_route_opaque(struct vty *vty, struct route_entry *re,
if (bzo.lcommunity[0] != '\0')
vty_out(vty, " Large-Communities: %s\n",
bzo.lcommunity);
+
+ vty_out(vty, " Selection reason : %s\n",
+ bzo.selection_reason);
}
}
default: