summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--babeld/babel_zebra.c14
-rw-r--r--bfdd/bfd.c31
-rw-r--r--bfdd/bfdd_cli.c48
-rw-r--r--bfdd/bfdd_nb.h35
-rw-r--r--bfdd/ptm_adapter.c31
-rw-r--r--bgpd/bgp_open.c129
-rw-r--r--bgpd/bgp_route.c30
-rw-r--r--bgpd/bgp_route.h5
-rw-r--r--bgpd/bgp_routemap.c4
-rw-r--r--bgpd/bgp_vty.c1
-rw-r--r--bgpd/bgp_zebra.c105
-rw-r--r--bgpd/bgpd.c10
-rw-r--r--bgpd/rfapi/vnc_zebra.c11
-rw-r--r--doc/user/bgp.rst9
-rw-r--r--doc/user/pbr.rst25
-rw-r--r--doc/user/scripting.rst79
-rw-r--r--doc/user/zebra.rst196
-rw-r--r--eigrpd/eigrp_cli.c79
-rw-r--r--eigrpd/eigrp_cli.h47
-rw-r--r--eigrpd/eigrp_zebra.c18
-rw-r--r--include/linux/nexthop.h59
-rw-r--r--isisd/isis_circuit.c28
-rw-r--r--isisd/isis_cli.c178
-rw-r--r--isisd/isis_nb.h167
-rw-r--r--isisd/isis_zebra.c28
-rw-r--r--isisd/isisd.c55
-rw-r--r--ldpd/lde.c2
-rw-r--r--ldpd/ldp_zebra.c20
-rw-r--r--lib/bfd.c15
-rw-r--r--lib/filter.h16
-rw-r--r--lib/filter_cli.c14
-rw-r--r--lib/frrlua.c67
-rw-r--r--lib/frrlua.h8
-rw-r--r--lib/frrscript.c86
-rw-r--r--lib/frrscript.h53
-rw-r--r--lib/if.c33
-rw-r--r--lib/if.h2
-rw-r--r--lib/nexthop_group.c7
-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.c63
-rw-r--r--lib/thread.h44
-rw-r--r--lib/vrf.c157
-rw-r--r--lib/vrf.h15
-rw-r--r--lib/vty.c22
-rw-r--r--lib/vxlan.h2
-rw-r--r--lib/yang.h2
-rw-r--r--lib/zclient.c377
-rw-r--r--lib/zclient.h86
-rw-r--r--lib/zebra.h3
-rw-r--r--nhrpd/netlink_arp.c9
-rw-r--r--nhrpd/nhrp_main.c2
-rw-r--r--nhrpd/nhrp_route.c30
-rw-r--r--nhrpd/nhrpd.h4
-rw-r--r--ospf6d/ospf6_asbr.c6
-rw-r--r--ospf6d/ospf6_zebra.c19
-rw-r--r--ospfd/ospf_asbr.c5
-rw-r--r--ospfd/ospf_asbr.h5
-rw-r--r--ospfd/ospf_lsa.c4
-rw-r--r--ospfd/ospf_lsa.h4
-rw-r--r--ospfd/ospf_routemap.c2
-rw-r--r--ospfd/ospf_zebra.c32
-rw-r--r--pathd/path_cli.c23
-rw-r--r--pathd/path_nb.h21
-rw-r--r--pathd/path_zebra.c14
-rw-r--r--pbrd/pbr_map.c35
-rw-r--r--pbrd/pbr_map.h12
-rw-r--r--pbrd/pbr_vty.c132
-rw-r--r--pbrd/pbr_zebra.c24
-rw-r--r--pimd/pim_ifchannel.c1
-rw-r--r--pimd/pim_mlag.c8
-rw-r--r--pimd/pim_mlag.h7
-rw-r--r--pimd/pim_zebra.c28
-rw-r--r--pimd/pim_zlookup.c2
-rw-r--r--ripd/rip_cli.c53
-rw-r--r--ripd/rip_interface.c29
-rw-r--r--ripd/rip_nb.h53
-rw-r--r--ripd/rip_zebra.c16
-rw-r--r--ripngd/ripng_cli.c34
-rw-r--r--ripngd/ripng_interface.c29
-rw-r--r--ripngd/ripng_nb.h32
-rw-r--r--ripngd/ripng_zebra.c16
-rw-r--r--sharpd/sharp_zebra.c44
-rw-r--r--staticd/static_vty.c20
-rw-r--r--staticd/static_vty.h20
-rw-r--r--staticd/static_zebra.c14
-rw-r--r--tests/bgpd/test_mpath.c2
-rw-r--r--tests/topotests/all_protocol_startup/test_all_protocol_startup.py86
-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
-rwxr-xr-xtests/topotests/conftest.py58
-rw-r--r--tests/topotests/ldp_topo1/test_ldp_topo1.py13
-rw-r--r--tests/topotests/lib/lutil.py21
-rw-r--r--tests/topotests/lib/topotest.py2
-rwxr-xr-xtests/topotests/ospf_gr_topo1/test_ospf_gr_topo1.py2
-rw-r--r--tests/topotests/pytest.ini1
-rw-r--r--vrrpd/vrrp_vty.c45
-rw-r--r--vrrpd/vrrp_vty.h18
-rw-r--r--vrrpd/vrrp_zebra.c12
-rw-r--r--zebra/debug_nl.c1
-rw-r--r--zebra/interface.c27
-rw-r--r--zebra/kernel_netlink.h4
-rw-r--r--zebra/subdir.am2
-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_netns_notify.c30
-rw-r--r--zebra/zebra_ptm.c18
-rw-r--r--zebra/zebra_rib.c26
-rw-r--r--zebra/zebra_router.c9
-rw-r--r--zebra/zebra_script.c420
-rw-r--r--zebra/zebra_script.h41
-rw-r--r--zebra/zebra_vrf.c100
-rw-r--r--zebra/zebra_vrf.h8
-rw-r--r--zebra/zebra_vty.c34
126 files changed, 2889 insertions, 1623 deletions
diff --git a/babeld/babel_zebra.c b/babeld/babel_zebra.c
index d10d41857..d0da93e50 100644
--- a/babeld/babel_zebra.c
+++ b/babeld/babel_zebra.c
@@ -234,16 +234,20 @@ babel_zebra_connected (struct zclient *zclient)
zclient_send_reg_requests (zclient, VRF_DEFAULT);
}
+static zclient_handler *const babel_handlers[] = {
+ [ZEBRA_INTERFACE_ADDRESS_ADD] = babel_interface_address_add,
+ [ZEBRA_INTERFACE_ADDRESS_DELETE] = babel_interface_address_delete,
+ [ZEBRA_REDISTRIBUTE_ROUTE_ADD] = babel_zebra_read_route,
+ [ZEBRA_REDISTRIBUTE_ROUTE_DEL] = babel_zebra_read_route,
+};
+
void babelz_zebra_init(void)
{
- zclient = zclient_new(master, &zclient_options_default);
+ zclient = zclient_new(master, &zclient_options_default, babel_handlers,
+ array_size(babel_handlers));
zclient_init(zclient, ZEBRA_ROUTE_BABEL, 0, &babeld_privs);
zclient->zebra_connected = babel_zebra_connected;
- zclient->interface_address_add = babel_interface_address_add;
- zclient->interface_address_delete = babel_interface_address_delete;
- zclient->redistribute_route_add = babel_zebra_read_route;
- zclient->redistribute_route_del = babel_zebra_read_route;
install_element(BABEL_NODE, &babel_redistribute_type_cmd);
install_element(ENABLE_NODE, &debug_babel_cmd);
diff --git a/bfdd/bfd.c b/bfdd/bfd.c
index c66fccb85..a4091534f 100644
--- a/bfdd/bfd.c
+++ b/bfdd/bfd.c
@@ -315,45 +315,28 @@ int bfd_session_enable(struct bfd_session *bs)
vrf = vrf_lookup_by_name(bs->key.vrfname);
if (vrf == NULL) {
zlog_err(
- "session-enable: specified VRF doesn't exists.");
+ "session-enable: specified VRF %s doesn't exists.",
+ bs->key.vrfname);
return 0;
}
+ } else {
+ vrf = vrf_lookup_by_id(VRF_DEFAULT);
}
- if (!vrf_is_backend_netns() && vrf && vrf->vrf_id != VRF_DEFAULT
- && !if_lookup_by_name(vrf->name, vrf->vrf_id)) {
- zlog_err("session-enable: vrf interface %s not available yet",
- vrf->name);
- return 0;
- }
+ assert(vrf);
if (bs->key.ifname[0]) {
- if (vrf)
- ifp = if_lookup_by_name(bs->key.ifname, vrf->vrf_id);
- else
- ifp = if_lookup_by_name_all_vrf(bs->key.ifname);
+ ifp = if_lookup_by_name(bs->key.ifname, vrf->vrf_id);
if (ifp == NULL) {
zlog_err(
"session-enable: specified interface %s (VRF %s) doesn't exist.",
- bs->key.ifname, vrf ? vrf->name : "<all>");
+ bs->key.ifname, vrf->name);
return 0;
}
- if (bs->key.ifname[0] && !vrf) {
- vrf = vrf_lookup_by_id(ifp->vrf_id);
- if (vrf == NULL) {
- zlog_err(
- "session-enable: specified VRF %u doesn't exist.",
- ifp->vrf_id);
- return 0;
- }
- }
}
/* Assign interface/VRF pointers. */
bs->vrf = vrf;
- if (bs->vrf == NULL)
- bs->vrf = vrf_lookup_by_id(VRF_DEFAULT);
- assert(bs->vrf);
/* Assign interface pointer (if any). */
bs->ifp = ifp;
diff --git a/bfdd/bfdd_cli.c b/bfdd/bfdd_cli.c
index 384bb26fd..d4e12e4f1 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 874e98691..d7ac32063 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/bfdd/ptm_adapter.c b/bfdd/ptm_adapter.c
index 838acf450..434d79c8f 100644
--- a/bfdd/ptm_adapter.c
+++ b/bfdd/ptm_adapter.c
@@ -844,29 +844,32 @@ static int bfd_ifp_create(struct interface *ifp)
return 0;
}
-void bfdd_zclient_init(struct zebra_privs_t *bfdd_priv)
-{
- if_zapi_callbacks(bfd_ifp_create, NULL, NULL, bfd_ifp_destroy);
- zclient = zclient_new(master, &zclient_options_default);
- assert(zclient != NULL);
- zclient_init(zclient, ZEBRA_ROUTE_BFD, 0, bfdd_priv);
-
+static zclient_handler *const bfd_handlers[] = {
/*
* We'll receive all messages through replay, however it will
* contain a special field with the real command inside so we
* avoid having to create too many handlers.
*/
- zclient->bfd_dest_replay = bfdd_replay;
-
- /* Send replay request on zebra connect. */
- zclient->zebra_connected = bfdd_zebra_connected;
+ [ZEBRA_BFD_DEST_REPLAY] = bfdd_replay,
/* Learn about interface VRF. */
- zclient->interface_vrf_update = bfdd_interface_vrf_update;
+ [ZEBRA_INTERFACE_VRF_UPDATE] = bfdd_interface_vrf_update,
/* Learn about new addresses being registered. */
- zclient->interface_address_add = bfdd_interface_address_update;
- zclient->interface_address_delete = bfdd_interface_address_update;
+ [ZEBRA_INTERFACE_ADDRESS_ADD] = bfdd_interface_address_update,
+ [ZEBRA_INTERFACE_ADDRESS_DELETE] = bfdd_interface_address_update,
+};
+
+void bfdd_zclient_init(struct zebra_privs_t *bfdd_priv)
+{
+ if_zapi_callbacks(bfd_ifp_create, NULL, NULL, bfd_ifp_destroy);
+ zclient = zclient_new(master, &zclient_options_default, bfd_handlers,
+ array_size(bfd_handlers));
+ assert(zclient != NULL);
+ zclient_init(zclient, ZEBRA_ROUTE_BFD, 0, bfdd_priv);
+
+ /* Send replay request on zebra connect. */
+ zclient->zebra_connected = bfdd_zebra_connected;
}
void bfdd_zclient_register(vrf_id_t vrf_id)
diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c
index f1dfebdc1..ca8b1e398 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 2a84f548f..4b798cc26 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -8433,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:
@@ -13451,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
@@ -13701,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");
@@ -13717,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");
@@ -13785,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 37bf675b6..46802d0d1 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 72a620aa6..d7c56dd83 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -1688,10 +1688,10 @@ route_match_interface(void *rule, const struct prefix *prefix, void *object)
path = object;
- if (!path)
+ if (!path || !path->peer || !path->peer->bgp)
return RMAP_NOMATCH;
- ifp = if_lookup_by_name_all_vrf((char *)rule);
+ ifp = if_lookup_by_name((char *)rule, path->peer->bgp->vrf_id);
if (ifp == NULL || ifp->ifindex != path->attr->nh_ifindex)
return RMAP_NOMATCH;
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 158a5f30b..772e20dc8 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;
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 6161f56fe..a98168d46 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -136,8 +136,7 @@ static void bgp_update_interface_nbrs(struct bgp *bgp, struct interface *ifp,
}
}
-static int bgp_read_fec_update(int command, struct zclient *zclient,
- zebra_size_t length)
+static int bgp_read_fec_update(ZAPI_CALLBACK_ARGS)
{
bgp_parse_fec_update();
return 0;
@@ -1490,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));
@@ -1503,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);
@@ -3005,7 +3009,7 @@ static int bgp_zebra_process_local_macip(ZAPI_CALLBACK_ARGS)
}
}
-static void bgp_zebra_process_local_ip_prefix(ZAPI_CALLBACK_ARGS)
+static int bgp_zebra_process_local_ip_prefix(ZAPI_CALLBACK_ARGS)
{
struct stream *s = NULL;
struct bgp *bgp_vrf = NULL;
@@ -3017,7 +3021,7 @@ static void bgp_zebra_process_local_ip_prefix(ZAPI_CALLBACK_ARGS)
bgp_vrf = bgp_lookup_by_vrf_id(vrf_id);
if (!bgp_vrf)
- return;
+ return 0;
if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug("Recv prefix %pFX %s on vrf %s", &p,
@@ -3041,9 +3045,10 @@ static void bgp_zebra_process_local_ip_prefix(ZAPI_CALLBACK_ARGS)
bgp_evpn_withdraw_type5_route(bgp_vrf, &p, AFI_IP6,
SAFI_UNICAST);
}
+ return 0;
}
-static void bgp_zebra_process_label_chunk(ZAPI_CALLBACK_ARGS)
+static int bgp_zebra_process_label_chunk(ZAPI_CALLBACK_ARGS)
{
struct stream *s = NULL;
uint8_t response_keep;
@@ -3062,12 +3067,12 @@ static void bgp_zebra_process_label_chunk(ZAPI_CALLBACK_ARGS)
if (zclient->redist_default != proto) {
flog_err(EC_BGP_LM_ERROR, "Got LM msg with wrong proto %u",
proto);
- return;
+ return 0;
}
if (zclient->instance != instance) {
flog_err(EC_BGP_LM_ERROR, "Got LM msg with wrong instance %u",
proto);
- return;
+ return 0;
}
if (first > last ||
@@ -3076,7 +3081,7 @@ static void bgp_zebra_process_label_chunk(ZAPI_CALLBACK_ARGS)
flog_err(EC_BGP_LM_ERROR, "%s: Invalid Label chunk: %u - %u",
__func__, first, last);
- return;
+ return 0;
}
if (BGP_DEBUG(zebra, ZEBRA)) {
zlog_debug("Label Chunk assign: %u - %u (%u) ",
@@ -3085,8 +3090,10 @@ static void bgp_zebra_process_label_chunk(ZAPI_CALLBACK_ARGS)
bgp_lp_event_chunk(response_keep, first, last);
+ return 0;
+
stream_failure: /* for STREAM_GETX */
- return;
+ return -1;
}
extern struct zebra_privs_t bgpd_privs;
@@ -3109,7 +3116,7 @@ static int bgp_ifp_create(struct interface *ifp)
return 0;
}
-static void bgp_zebra_process_srv6_locator_chunk(ZAPI_CALLBACK_ARGS)
+static int bgp_zebra_process_srv6_locator_chunk(ZAPI_CALLBACK_ARGS)
{
struct stream *s = NULL;
struct bgp *bgp = bgp_get_default();
@@ -3124,18 +3131,19 @@ static void bgp_zebra_process_srv6_locator_chunk(ZAPI_CALLBACK_ARGS)
if (strcmp(bgp->srv6_locator_name, s6c.locator_name) != 0) {
zlog_err("%s: Locator name unmatch %s:%s", __func__,
bgp->srv6_locator_name, s6c.locator_name);
- return;
+ return 0;
}
for (ALL_LIST_ELEMENTS_RO(bgp->srv6_locator_chunks, node, c)) {
if (!prefix_cmp(c, &s6c.prefix))
- return;
+ return 0;
}
chunk = prefix_ipv6_new();
*chunk = s6c.prefix;
listnode_add(bgp->srv6_locator_chunks, chunk);
vpn_leak_postchange_all();
+ return 0;
}
static int bgp_zebra_process_srv6_locator_add(ZAPI_CALLBACK_ARGS)
@@ -3220,6 +3228,41 @@ static int bgp_zebra_process_srv6_locator_delete(ZAPI_CALLBACK_ARGS)
return 0;
}
+static zclient_handler *const bgp_handlers[] = {
+ [ZEBRA_ROUTER_ID_UPDATE] = bgp_router_id_update,
+ [ZEBRA_INTERFACE_ADDRESS_ADD] = bgp_interface_address_add,
+ [ZEBRA_INTERFACE_ADDRESS_DELETE] = bgp_interface_address_delete,
+ [ZEBRA_INTERFACE_NBR_ADDRESS_ADD] = bgp_interface_nbr_address_add,
+ [ZEBRA_INTERFACE_NBR_ADDRESS_DELETE] = bgp_interface_nbr_address_delete,
+ [ZEBRA_INTERFACE_VRF_UPDATE] = bgp_interface_vrf_update,
+ [ZEBRA_REDISTRIBUTE_ROUTE_ADD] = zebra_read_route,
+ [ZEBRA_REDISTRIBUTE_ROUTE_DEL] = zebra_read_route,
+ [ZEBRA_NEXTHOP_UPDATE] = bgp_read_nexthop_update,
+ [ZEBRA_FEC_UPDATE] = bgp_read_fec_update,
+ [ZEBRA_LOCAL_ES_ADD] = bgp_zebra_process_local_es_add,
+ [ZEBRA_LOCAL_ES_DEL] = bgp_zebra_process_local_es_del,
+ [ZEBRA_VNI_ADD] = bgp_zebra_process_local_vni,
+ [ZEBRA_LOCAL_ES_EVI_ADD] = bgp_zebra_process_local_es_evi,
+ [ZEBRA_LOCAL_ES_EVI_DEL] = bgp_zebra_process_local_es_evi,
+ [ZEBRA_VNI_DEL] = bgp_zebra_process_local_vni,
+ [ZEBRA_MACIP_ADD] = bgp_zebra_process_local_macip,
+ [ZEBRA_MACIP_DEL] = bgp_zebra_process_local_macip,
+ [ZEBRA_L3VNI_ADD] = bgp_zebra_process_local_l3vni,
+ [ZEBRA_L3VNI_DEL] = bgp_zebra_process_local_l3vni,
+ [ZEBRA_IP_PREFIX_ROUTE_ADD] = bgp_zebra_process_local_ip_prefix,
+ [ZEBRA_IP_PREFIX_ROUTE_DEL] = bgp_zebra_process_local_ip_prefix,
+ [ZEBRA_GET_LABEL_CHUNK] = bgp_zebra_process_label_chunk,
+ [ZEBRA_RULE_NOTIFY_OWNER] = rule_notify_owner,
+ [ZEBRA_IPSET_NOTIFY_OWNER] = ipset_notify_owner,
+ [ZEBRA_IPSET_ENTRY_NOTIFY_OWNER] = ipset_entry_notify_owner,
+ [ZEBRA_IPTABLE_NOTIFY_OWNER] = iptable_notify_owner,
+ [ZEBRA_ROUTE_NOTIFY_OWNER] = bgp_zebra_route_notify_owner,
+ [ZEBRA_SRV6_LOCATOR_ADD] = bgp_zebra_process_srv6_locator_add,
+ [ZEBRA_SRV6_LOCATOR_DELETE] = bgp_zebra_process_srv6_locator_delete,
+ [ZEBRA_SRV6_MANAGER_GET_LOCATOR_CHUNK] =
+ bgp_zebra_process_srv6_locator_chunk,
+};
+
void bgp_zebra_init(struct thread_master *master, unsigned short instance)
{
zclient_num_connects = 0;
@@ -3228,43 +3271,11 @@ void bgp_zebra_init(struct thread_master *master, unsigned short instance)
bgp_ifp_down, bgp_ifp_destroy);
/* Set default values. */
- zclient = zclient_new(master, &zclient_options_default);
+ zclient = zclient_new(master, &zclient_options_default, bgp_handlers,
+ array_size(bgp_handlers));
zclient_init(zclient, ZEBRA_ROUTE_BGP, 0, &bgpd_privs);
zclient->zebra_connected = bgp_zebra_connected;
- zclient->router_id_update = bgp_router_id_update;
- zclient->interface_address_add = bgp_interface_address_add;
- zclient->interface_address_delete = bgp_interface_address_delete;
- zclient->interface_nbr_address_add = bgp_interface_nbr_address_add;
- zclient->interface_nbr_address_delete =
- bgp_interface_nbr_address_delete;
- zclient->interface_vrf_update = bgp_interface_vrf_update;
- zclient->redistribute_route_add = zebra_read_route;
- zclient->redistribute_route_del = zebra_read_route;
- zclient->nexthop_update = bgp_read_nexthop_update;
- zclient->fec_update = bgp_read_fec_update;
- zclient->local_es_add = bgp_zebra_process_local_es_add;
- zclient->local_es_del = bgp_zebra_process_local_es_del;
- zclient->local_vni_add = bgp_zebra_process_local_vni;
- zclient->local_es_evi_add = bgp_zebra_process_local_es_evi;
- zclient->local_es_evi_del = bgp_zebra_process_local_es_evi;
- zclient->local_vni_del = bgp_zebra_process_local_vni;
- zclient->local_macip_add = bgp_zebra_process_local_macip;
- zclient->local_macip_del = bgp_zebra_process_local_macip;
- zclient->local_l3vni_add = bgp_zebra_process_local_l3vni;
- zclient->local_l3vni_del = bgp_zebra_process_local_l3vni;
- zclient->local_ip_prefix_add = bgp_zebra_process_local_ip_prefix;
- zclient->local_ip_prefix_del = bgp_zebra_process_local_ip_prefix;
- zclient->label_chunk = bgp_zebra_process_label_chunk;
- zclient->rule_notify_owner = rule_notify_owner;
- zclient->ipset_notify_owner = ipset_notify_owner;
- zclient->ipset_entry_notify_owner = ipset_entry_notify_owner;
- zclient->iptable_notify_owner = iptable_notify_owner;
- zclient->route_notify_owner = bgp_zebra_route_notify_owner;
zclient->instance = instance;
- zclient->srv6_locator_add = bgp_zebra_process_srv6_locator_add;
- zclient->srv6_locator_delete = bgp_zebra_process_srv6_locator_delete;
- zclient->process_srv6_locator_chunk =
- bgp_zebra_process_srv6_locator_chunk;
}
void bgp_zebra_destroy(void)
@@ -3536,7 +3547,7 @@ void bgp_zebra_announce_default(struct bgp *bgp, struct nexthop *nh,
/* create default route with interface <VRF>
* with nexthop-vrf <VRF>
*/
- ifp = if_lookup_by_name_all_vrf(vrf->name);
+ ifp = if_lookup_by_name_vrf(vrf->name, vrf);
if (!ifp)
return;
api_nh->vrf_id = nh->vrf_id;
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index b191029d2..c5a5e49a4 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/bgpd/rfapi/vnc_zebra.c b/bgpd/rfapi/vnc_zebra.c
index ba849e4e0..672a0e978 100644
--- a/bgpd/rfapi/vnc_zebra.c
+++ b/bgpd/rfapi/vnc_zebra.c
@@ -895,6 +895,11 @@ int vnc_redistribute_unset(struct bgp *bgp, afi_t afi, int type)
extern struct zebra_privs_t bgpd_privs;
+static zclient_handler *const vnc_handlers[] = {
+ [ZEBRA_REDISTRIBUTE_ROUTE_ADD] = vnc_zebra_read_route,
+ [ZEBRA_REDISTRIBUTE_ROUTE_DEL] = vnc_zebra_read_route,
+};
+
/*
* Modeled after bgp_zebra.c'bgp_zebra_init()
* Charriere asks, "Is it possible to carry two?"
@@ -902,11 +907,9 @@ extern struct zebra_privs_t bgpd_privs;
void vnc_zebra_init(struct thread_master *master)
{
/* Set default values. */
- zclient_vnc = zclient_new(master, &zclient_options_default);
+ zclient_vnc = zclient_new(master, &zclient_options_default,
+ vnc_handlers, array_size(vnc_handlers));
zclient_init(zclient_vnc, ZEBRA_ROUTE_VNC, 0, &bgpd_privs);
-
- zclient_vnc->redistribute_route_add = vnc_zebra_read_route;
- zclient_vnc->redistribute_route_del = vnc_zebra_read_route;
}
void vnc_zebra_destroy(void)
diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst
index 5fcddafaa..1793ae3d2 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 e59ed1089..29567bb70 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/doc/user/scripting.rst b/doc/user/scripting.rst
index b0295e570..badc82c50 100644
--- a/doc/user/scripting.rst
+++ b/doc/user/scripting.rst
@@ -1,22 +1,31 @@
-.. _scripting:
+.. _scripting-user:
*********
Scripting
*********
The behavior of FRR may be extended or customized using its built-in scripting
-capabilities.
+capabilities. The scripting language is Lua 5.3. This guide assumes Lua
+knowledge. For more information on Lua, consult the Lua 5.3 reference manual, or
+*Programming in Lua* (note that the free version covers only Lua 5.0).
-Some configuration commands accept the name of a Lua script to call to perform
-some task or make some decision. These scripts have their environments
-populated with some set of inputs, and are expected to populate some set of
-output variables, which are read by FRR after the script completes. The names
-and expected contents of these scripts are documented alongside the commands
-that support them.
+https://www.lua.org/manual/5.3/
-These scripts live in :file:`/etc/frr/scripts/` by default. This is
-configurable at compile time via ``--with-scriptdir``. It may be
-overriden at runtime with the ``--scriptdir`` daemon option.
+http://www.lua.org/pil/contents.html
+
+Scripting
+=========
+
+.. seealso:: Developer docs for scripting
+
+How to use
+----------
+
+1. Identify the Lua function name. See :ref:`lua-hook-calls`.
+
+2. Write the Lua script
+
+3. Configure FRR to use the Lua script
In order to use scripting, FRR must be built with ``--enable-scripting``.
@@ -26,3 +35,51 @@ In order to use scripting, FRR must be built with ``--enable-scripting``.
contents of a script that is in use without restarting FRR. Not all
scripting locations may behave this way; refer to the documentation for the
particular location.
+
+
+Example: on_rib_process_dplane_results
+--------------------------------------
+
+This example shows how to write a Lua script that logs changes when a route is
+added.
+
+First, identify the Lua hook call to attach a Lua function to: this will be the
+name of the Lua function. In this case, since the hook call is
+`on_rib_process_dplane_results`:
+
+.. code-block:: lua
+
+ function on_rib_process_dplane_results(ctx)
+ log.info(ctx.rinfo.zd_dest.network)
+ return {}
+
+
+The documentation for :ref:`on-rib-process-dplane-results` tells us its
+arguments. Here, the destination prefix for a route is being logged out.
+
+Scripts live in :file:`/etc/frr/scripts/` by default. This is configurable at
+compile time via ``--with-scriptdir``. It may be overriden at runtime with the
+``--scriptdir`` daemon option.
+
+The documentation for :ref:`on-rib-process-dplane-results` indicates that the
+``script`` command should be used to set the script. Assuming that the above
+function was created in :file:`/etc/frr/scripts/my_dplane_script.lua`, the
+following vtysh command sets the script for the hook call:
+
+.. code-block:: console
+
+ script on_rib_process_dplane_results my_dplane_script
+
+
+After the script is set, when the hook call is hit, FRR will look for a
+*on_rib_process_dplane_results* function in
+:file:`/etc/frr/scripts/my_dplane_script.lua` and run it with the ``ctx`` object
+as its argument.
+
+
+.. _lua-hook-calls:
+
+Available Lua hook calls
+========================
+
+:ref:`on-rib-process-dplane-results`
diff --git a/doc/user/zebra.rst b/doc/user/zebra.rst
index 5eb97ff06..de327dfe2 100644
--- a/doc/user/zebra.rst
+++ b/doc/user/zebra.rst
@@ -1416,3 +1416,199 @@ Debugging
Nexthop and nexthop-group events.
+Scripting
+=========
+
+.. clicmd:: zebra on-rib-process script SCRIPT
+
+ Set a Lua script for :ref:`on-rib-process-dplane-results` hook call.
+ SCRIPT is the basename of the script, without `.lua`.
+
+Data structures
+---------------
+
+.. _const-struct-zebra-dplane-ctx:
+
+const struct zebra_dplane_ctx
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: console
+
+ * integer zd_op
+ * integer zd_status
+ * integer zd_provider
+ * integer zd_vrf_id
+ * integer zd_table_id
+ * integer zd_ifname
+ * integer zd_ifindex
+ * table rinfo (if zd_op is DPLANE_OP_ROUTE*, DPLANE_NH_*)
+
+ * prefix zd_dest
+ * prefix zd_src
+ * integer zd_afi
+ * integer zd_safi
+ * integer zd_type
+ * integer zd_old_type
+ * integer zd_tag
+ * integer zd_old_tag
+ * integer zd_metric
+ * integer zd_old_metric
+ * integer zd_instance
+ * integer zd_old_instance
+ * integer zd_distance
+ * integer zd_old_distance
+ * integer zd_mtu
+ * integer zd_nexthop_mtu
+ * table nhe
+
+ * integer id
+ * integer old_id
+ * integer afi
+ * integer vrf_id
+ * integer type
+ * nexthop_group ng
+ * nh_grp
+ * integer nh_grp_count
+
+ * integer zd_nhg_id
+ * nexthop_group zd_ng
+ * nexthop_group backup_ng
+ * nexthop_group zd_old_ng
+ * nexthop_group old_backup_ng
+
+ * integer label (if zd_op is DPLANE_OP_LSP_*)
+ * table pw (if zd_op is DPLANE_OP_PW_*)
+
+ * integer type
+ * integer af
+ * integer status
+ * integer flags
+ * integer local_label
+ * integer remote_label
+
+ * table macinfo (if zd_op is DPLANE_OP_MAC_*)
+
+ * integer vid
+ * integer br_ifindex
+ * ethaddr mac
+ * integer vtep_ip
+ * integer is_sticky
+ * integer nhg_id
+ * integer update_flags
+
+ * table rule (if zd_op is DPLANE_OP_RULE_*)
+
+ * integer sock
+ * integer unique
+ * integer seq
+ * string ifname
+ * integer priority
+ * integer old_priority
+ * integer table
+ * integer old_table
+ * integer filter_bm
+ * integer old_filter_bm
+ * integer fwmark
+ * integer old_fwmark
+ * integer dsfield
+ * integer old_dsfield
+ * integer ip_proto
+ * integer old_ip_proto
+ * prefix src_ip
+ * prefix old_src_ip
+ * prefix dst_ip
+ * prefix old_dst_ip
+
+ * table iptable (if zd_op is DPLANE_OP_IPTABLE_*)
+
+ * integer sock
+ * integer vrf_id
+ * integer unique
+ * integer type
+ * integer filter_bm
+ * integer fwmark
+ * integer action
+ * integer pkt_len_min
+ * integer pkt_len_max
+ * integer tcp_flags
+ * integer dscp_value
+ * integer fragment
+ * integer protocol
+ * integer nb_interface
+ * integer flow_label
+ * integer family
+ * string ipset_name
+
+ * table ipset (if zd_op is DPLANE_OP_IPSET_*)
+ * integer sock
+ * integer vrf_id
+ * integer unique
+ * integer type
+ * integer family
+ * string ipset_name
+
+ * table neigh (if zd_op is DPLANE_OP_NEIGH_*)
+
+ * ipaddr ip_addr
+ * table link
+
+ * ethaddr mac
+ * ipaddr ip_addr
+
+ * integer flags
+ * integer state
+ * integer update_flags
+
+ * table br_port (if zd_op is DPLANE_OP_BR_PORT_UPDATE)
+
+ * integer sph_filter_cnt
+ * integer flags
+ * integer backup_nhg_id
+
+ * table neightable (if zd_op is DPLANE_OP_NEIGH_TABLE_UPDATE)
+
+ * integer family
+ * integer app_probes
+ * integer ucast_probes
+ * integer mcast_probes
+
+ * table gre (if zd_op is DPLANE_OP_GRE_SET)**
+
+ * integer link_ifindex
+ * integer mtu
+
+
+.. _const-struct-nh-grp:
+
+const struct nh_grp
+^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: console
+
+ * integer id
+ * integer weight
+
+
+.. _zebra-hook-calls:
+
+Zebra Hook calls
+----------------
+
+.. _on-rib-process-dplane-results:
+
+on_rib_process_dplane_results
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Called when RIB processes dataplane events.
+Set script location with the ``zebra on-rib-process script SCRIPT`` command.
+
+**Arguments**
+
+* :ref:`const struct zebra_dplane_ctx<const-struct-zebra-dplane-ctx>` ctx
+
+
+.. code-block:: lua
+
+ function on_rib_process_dplane_results(ctx)
+ log.info(ctx.rinfo.zd_dest.network)
+ return {}
diff --git a/eigrpd/eigrp_cli.c b/eigrpd/eigrp_cli.c
index 533d7de2c..744f5f9c7 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");
@@ -862,30 +869,6 @@ static int eigrp_config_write(struct vty *vty)
return written;
}
-static int eigrp_write_interface(struct vty *vty)
-{
- struct lyd_node *dnode;
- struct interface *ifp;
- struct vrf *vrf;
- int written = 0;
-
- RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) {
- FOR_ALL_INTERFACES(vrf, ifp) {
- dnode = yang_dnode_getf(
- running_config->dnode,
- "/frr-interface:lib/interface[name='%s'][vrf='%s']",
- ifp->name, vrf->name);
- if (dnode == NULL)
- continue;
-
- written = 1;
- nb_cli_show_dnode_cmds(vty, dnode, false);
- }
- }
-
- return written;
-}
-
void
eigrp_cli_init(void)
{
@@ -912,7 +895,7 @@ eigrp_cli_init(void)
vrf_cmd_init(NULL);
- if_cmd_init(eigrp_write_interface);
+ if_cmd_init_default();
install_element(INTERFACE_NODE, &eigrp_if_delay_cmd);
install_element(INTERFACE_NODE, &no_eigrp_if_delay_cmd);
diff --git a/eigrpd/eigrp_cli.h b/eigrpd/eigrp_cli.h
index c5f2fd800..8b16dea39 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/eigrpd/eigrp_zebra.c b/eigrpd/eigrp_zebra.c
index 7c765248c..89dd5be27 100644
--- a/eigrpd/eigrp_zebra.c
+++ b/eigrpd/eigrp_zebra.c
@@ -102,20 +102,24 @@ static void eigrp_zebra_connected(struct zclient *zclient)
zclient_send_reg_requests(zclient, VRF_DEFAULT);
}
+static zclient_handler *const eigrp_handlers[] = {
+ [ZEBRA_ROUTER_ID_UPDATE] = eigrp_router_id_update_zebra,
+ [ZEBRA_INTERFACE_ADDRESS_ADD] = eigrp_interface_address_add,
+ [ZEBRA_INTERFACE_ADDRESS_DELETE] = eigrp_interface_address_delete,
+ [ZEBRA_REDISTRIBUTE_ROUTE_ADD] = eigrp_zebra_read_route,
+ [ZEBRA_REDISTRIBUTE_ROUTE_DEL] = eigrp_zebra_read_route,
+ [ZEBRA_ROUTE_NOTIFY_OWNER] = eigrp_zebra_route_notify_owner,
+};
+
void eigrp_zebra_init(void)
{
struct zclient_options opt = {.receive_notify = false};
- zclient = zclient_new(master, &opt);
+ zclient = zclient_new(master, &opt, eigrp_handlers,
+ array_size(eigrp_handlers));
zclient_init(zclient, ZEBRA_ROUTE_EIGRP, 0, &eigrpd_privs);
zclient->zebra_connected = eigrp_zebra_connected;
- zclient->router_id_update = eigrp_router_id_update_zebra;
- zclient->interface_address_add = eigrp_interface_address_add;
- zclient->interface_address_delete = eigrp_interface_address_delete;
- zclient->redistribute_route_add = eigrp_zebra_read_route;
- zclient->redistribute_route_del = eigrp_zebra_read_route;
- zclient->route_notify_owner = eigrp_zebra_route_notify_owner;
}
diff --git a/include/linux/nexthop.h b/include/linux/nexthop.h
index ee2a15b9c..d8ffa8c9c 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_circuit.c b/isisd/isis_circuit.c
index 6f4a91be6..c09bdf4f4 100644
--- a/isisd/isis_circuit.c
+++ b/isisd/isis_circuit.c
@@ -1295,30 +1295,6 @@ static int isis_interface_config_write(struct vty *vty)
return write;
}
-#else
-static int isis_interface_config_write(struct vty *vty)
-{
- struct vrf *vrf = NULL;
- int write = 0;
-
- RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
- struct interface *ifp;
-
- FOR_ALL_INTERFACES (vrf, ifp) {
- struct lyd_node *dnode;
- dnode = yang_dnode_getf(
- running_config->dnode,
- "/frr-interface:lib/interface[name='%s'][vrf='%s']",
- ifp->name, vrf->name);
- if (dnode == NULL)
- continue;
-
- write++;
- nb_cli_show_dnode_cmds(vty, dnode, false);
- }
- }
- return write;
-}
#endif /* ifdef FABRICD */
void isis_circuit_af_set(struct isis_circuit *circuit, bool ip_router,
@@ -1529,7 +1505,11 @@ void isis_circuit_init(void)
hook_register_prio(if_del, 0, isis_if_delete_hook);
/* Install interface node */
+#ifdef FABRICD
if_cmd_init(isis_interface_config_write);
+#else
+ if_cmd_init_default();
+#endif
if_zapi_callbacks(isis_ifp_create, isis_ifp_up,
isis_ifp_down, isis_ifp_destroy);
}
diff --git a/isisd/isis_cli.c b/isisd/isis_cli.c
index f48b142b1..195a3fcd2 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 4680dd5de..ee7904163 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/isisd/isis_zebra.c b/isisd/isis_zebra.c
index 2c05cb827..27e80e250 100644
--- a/isisd/isis_zebra.c
+++ b/isisd/isis_zebra.c
@@ -800,23 +800,31 @@ static int isis_zebra_client_close_notify(ZAPI_CALLBACK_ARGS)
return ret;
}
+static zclient_handler *const isis_handlers[] = {
+ [ZEBRA_ROUTER_ID_UPDATE] = isis_router_id_update_zebra,
+ [ZEBRA_INTERFACE_ADDRESS_ADD] = isis_zebra_if_address_add,
+ [ZEBRA_INTERFACE_ADDRESS_DELETE] = isis_zebra_if_address_del,
+ [ZEBRA_INTERFACE_LINK_PARAMS] = isis_zebra_link_params,
+ [ZEBRA_REDISTRIBUTE_ROUTE_ADD] = isis_zebra_read,
+ [ZEBRA_REDISTRIBUTE_ROUTE_DEL] = isis_zebra_read,
+
+ [ZEBRA_OPAQUE_MESSAGE] = isis_opaque_msg_handler,
+
+ [ZEBRA_CLIENT_CLOSE_NOTIFY] = isis_zebra_client_close_notify,
+};
+
void isis_zebra_init(struct thread_master *master, int instance)
{
/* Initialize asynchronous zclient. */
- zclient = zclient_new(master, &zclient_options_default);
+ zclient = zclient_new(master, &zclient_options_default, isis_handlers,
+ array_size(isis_handlers));
zclient_init(zclient, PROTO_TYPE, 0, &isisd_privs);
zclient->zebra_connected = isis_zebra_connected;
- zclient->router_id_update = isis_router_id_update_zebra;
- zclient->interface_address_add = isis_zebra_if_address_add;
- zclient->interface_address_delete = isis_zebra_if_address_del;
- zclient->interface_link_params = isis_zebra_link_params;
- zclient->redistribute_route_add = isis_zebra_read;
- zclient->redistribute_route_del = isis_zebra_read;
/* Initialize special zclient for synchronous message exchanges. */
struct zclient_options options = zclient_options_default;
options.synchronous = true;
- zclient_sync = zclient_new(master, &options);
+ zclient_sync = zclient_new(master, &options, NULL, 0);
zclient_sync->sock = -1;
zclient_sync->redist_default = ZEBRA_ROUTE_ISIS;
zclient_sync->instance = instance;
@@ -826,10 +834,6 @@ void isis_zebra_init(struct thread_master *master, int instance)
*/
zclient_sync->session_id = 1;
zclient_sync->privs = &isisd_privs;
-
- zclient->opaque_msg_handler = isis_opaque_msg_handler;
-
- zclient->zebra_client_close_notify = isis_zebra_client_close_notify;
}
void isis_zebra_stop(void)
diff --git a/isisd/isisd.c b/isisd/isisd.c
index 65764654e..8c26a57be 100644
--- a/isisd/isisd.c
+++ b/isisd/isisd.c
@@ -646,7 +646,52 @@ static int isis_vrf_enable(struct vrf *vrf)
vrf->vrf_id);
isis = isis_lookup_by_vrfname(vrf->name);
- if (isis) {
+ if (!isis) {
+ char *old_vrf_name = NULL;
+
+ isis = (struct isis *)vrf->info;
+ if (!isis)
+ return 0;
+ /* update vrf name */
+ if (isis->name)
+ old_vrf_name = isis->name;
+ isis->name = XSTRDUP(MTYPE_ISIS_NAME, vrf->name);
+ /*
+ * HACK: Change the ISIS VRF in the running configuration
+ * directly, bypassing the northbound layer. This is necessary
+ * to avoid deleting the ISIS and readding it in the new VRF,
+ * which would have several implications.
+ */
+ if (yang_module_find("frr-isisd") && old_vrf_name) {
+ struct lyd_node *isis_dnode;
+ struct isis_area *area;
+ char oldpath[XPATH_MAXLEN];
+ char newpath[XPATH_MAXLEN];
+ struct listnode *node, *nnode;
+
+ for (ALL_LIST_ELEMENTS(isis->area_list, node, nnode,
+ area)) {
+ isis_dnode = yang_dnode_getf(
+ running_config->dnode,
+ "/frr-isisd:isis/instance[area-tag='%s'][vrf='%s']/vrf",
+ area->area_tag, old_vrf_name);
+ if (isis_dnode) {
+ yang_dnode_get_path(
+ lyd_parent(isis_dnode), oldpath,
+ sizeof(oldpath));
+ yang_dnode_change_leaf(isis_dnode,
+ vrf->name);
+ yang_dnode_get_path(
+ lyd_parent(isis_dnode), newpath,
+ sizeof(newpath));
+ nb_running_move_tree(oldpath, newpath);
+ running_config->version++;
+ }
+ }
+ }
+ XFREE(MTYPE_ISIS_NAME, old_vrf_name);
+ }
+ if (isis && isis->vrf_id != vrf->vrf_id) {
old_vrf_id = isis->vrf_id;
/* We have instance configured, link to VRF and make it "up". */
isis_vrf_link(isis, vrf);
@@ -654,12 +699,10 @@ static int isis_vrf_enable(struct vrf *vrf)
zlog_debug(
"%s: isis linked to vrf %s vrf_id %u (old id %u)",
__func__, vrf->name, isis->vrf_id, old_vrf_id);
- if (old_vrf_id != isis->vrf_id) {
- /* start zebra redist to us for new vrf */
- isis_set_redist_vrf_bitmaps(isis, true);
+ /* start zebra redist to us for new vrf */
+ isis_set_redist_vrf_bitmaps(isis, true);
- isis_zebra_vrf_register(isis);
- }
+ isis_zebra_vrf_register(isis);
}
return 0;
diff --git a/ldpd/lde.c b/ldpd/lde.c
index babadc461..095631036 100644
--- a/ldpd/lde.c
+++ b/ldpd/lde.c
@@ -2192,7 +2192,7 @@ static void zclient_sync_init(void)
options.synchronous = true;
/* Initialize special zclient for synchronous message exchanges. */
- zclient_sync = zclient_new(master, &options);
+ zclient_sync = zclient_new(master, &options, NULL, 0);
zclient_sync->sock = -1;
zclient_sync->redist_default = ZEBRA_ROUTE_LDP;
zclient_sync->session_id = 1; /* Distinguish from main session */
diff --git a/ldpd/ldp_zebra.c b/ldpd/ldp_zebra.c
index 2d90412d1..059115915 100644
--- a/ldpd/ldp_zebra.c
+++ b/ldpd/ldp_zebra.c
@@ -694,6 +694,16 @@ ldp_zebra_filter_update(struct access_list *access)
extern struct zebra_privs_t ldpd_privs;
+static zclient_handler *const ldp_handlers[] = {
+ [ZEBRA_ROUTER_ID_UPDATE] = ldp_router_id_update,
+ [ZEBRA_INTERFACE_ADDRESS_ADD] = ldp_interface_address_add,
+ [ZEBRA_INTERFACE_ADDRESS_DELETE] = ldp_interface_address_delete,
+ [ZEBRA_REDISTRIBUTE_ROUTE_ADD] = ldp_zebra_read_route,
+ [ZEBRA_REDISTRIBUTE_ROUTE_DEL] = ldp_zebra_read_route,
+ [ZEBRA_PW_STATUS_UPDATE] = ldp_zebra_read_pw_status_update,
+ [ZEBRA_OPAQUE_MESSAGE] = ldp_zebra_opaque_msg_handler,
+};
+
void
ldp_zebra_init(struct thread_master *master)
{
@@ -701,18 +711,12 @@ ldp_zebra_init(struct thread_master *master)
ldp_ifp_down, ldp_ifp_destroy);
/* Set default values. */
- zclient = zclient_new(master, &zclient_options_default);
+ zclient = zclient_new(master, &zclient_options_default, ldp_handlers,
+ array_size(ldp_handlers));
zclient_init(zclient, ZEBRA_ROUTE_LDP, 0, &ldpd_privs);
/* set callbacks */
zclient->zebra_connected = ldp_zebra_connected;
- zclient->router_id_update = ldp_router_id_update;
- zclient->interface_address_add = ldp_interface_address_add;
- zclient->interface_address_delete = ldp_interface_address_delete;
- zclient->redistribute_route_add = ldp_zebra_read_route;
- zclient->redistribute_route_del = ldp_zebra_read_route;
- zclient->pw_status_update = ldp_zebra_read_pw_status_update;
- zclient->opaque_msg_handler = ldp_zebra_opaque_msg_handler;
/* Access list initialize. */
access_list_add_hook(ldp_zebra_filter_update);
diff --git a/lib/bfd.c b/lib/bfd.c
index 5a8a46b67..70cbe0f2a 100644
--- a/lib/bfd.c
+++ b/lib/bfd.c
@@ -821,10 +821,13 @@ void bfd_sess_show(struct vty *vty, struct json_object *json,
*
* Use this as `zclient` `bfd_dest_replay` callback.
*/
-static int zclient_bfd_session_reply(ZAPI_CALLBACK_ARGS)
+int zclient_bfd_session_reply(ZAPI_CALLBACK_ARGS)
{
struct bfd_session_params *bsp;
+ if (!zclient->bfd_integration)
+ return 0;
+
/* Do nothing when shutting down. */
if (bsglobal.shutting_down)
return 0;
@@ -855,7 +858,7 @@ static int zclient_bfd_session_reply(ZAPI_CALLBACK_ARGS)
return 0;
}
-static int zclient_bfd_session_update(ZAPI_CALLBACK_ARGS)
+int zclient_bfd_session_update(ZAPI_CALLBACK_ARGS)
{
struct bfd_session_params *bsp, *bspn;
size_t sessions_updated = 0;
@@ -868,6 +871,9 @@ static int zclient_bfd_session_update(ZAPI_CALLBACK_ARGS)
struct prefix sp;
char ifstr[128], cbitstr[32];
+ if (!zclient->bfd_integration)
+ return 0;
+
/* Do nothing when shutting down. */
if (bsglobal.shutting_down)
return 0;
@@ -969,9 +975,8 @@ void bfd_protocol_integration_init(struct zclient *zc, struct thread_master *tm)
bsglobal.zc = zc;
bsglobal.tm = tm;
- /* Install our callbacks. */
- zc->interface_bfd_dest_update = zclient_bfd_session_update;
- zc->bfd_dest_replay = zclient_bfd_session_reply;
+ /* Enable BFD callbacks. */
+ zc->bfd_integration = true;
/* Send the client registration */
bfd_client_sendmsg(zc, ZEBRA_BFD_CLIENT_REGISTER, VRF_DEFAULT);
diff --git a/lib/filter.h b/lib/filter.h
index d1956ec01..b378288c5 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 e424fcf87..43618094a 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/frrlua.c b/lib/frrlua.c
index 00491568f..535649eff 100644
--- a/lib/frrlua.c
+++ b/lib/frrlua.c
@@ -223,6 +223,21 @@ void *lua_toin6addr(lua_State *L, int idx)
return in6addr;
}
+void lua_pushipaddr(lua_State *L, const struct ipaddr *addr)
+{
+ if (IS_IPADDR_V4(addr))
+ lua_pushinaddr(L, &addr->ipaddr_v4);
+ else
+ lua_pushin6addr(L, &addr->ipaddr_v6);
+}
+
+void lua_pushethaddr(lua_State *L, const struct ethaddr *addr)
+{
+ lua_newtable(L);
+ lua_pushinteger(L, *(addr->octet));
+ lua_setfield(L, -2, "octet");
+}
+
void lua_pushsockunion(lua_State *L, const union sockunion *su)
{
char buf[SU_ADDRSTRLEN];
@@ -297,6 +312,58 @@ void *lua_tointegerp(lua_State *L, int idx)
return num;
}
+void lua_pushnexthop(lua_State *L, const struct nexthop *nexthop)
+{
+ lua_newtable(L);
+ lua_pushinteger(L, nexthop->vrf_id);
+ lua_setfield(L, -2, "vrf_id");
+ lua_pushinteger(L, nexthop->ifindex);
+ lua_setfield(L, -2, "ifindex");
+ lua_pushinteger(L, nexthop->type);
+ lua_setfield(L, -2, "type");
+ lua_pushinteger(L, nexthop->flags);
+ lua_setfield(L, -2, "flags");
+ if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE) {
+ lua_pushinteger(L, nexthop->bh_type);
+ lua_setfield(L, -2, "bh_type");
+ } else if (nexthop->type == NEXTHOP_TYPE_IPV4) {
+ lua_pushinaddr(L, &nexthop->gate.ipv4);
+ lua_setfield(L, -2, "gate");
+ } else if (nexthop->type == NEXTHOP_TYPE_IPV6) {
+ lua_pushin6addr(L, &nexthop->gate.ipv6);
+ lua_setfield(L, -2, "gate");
+ }
+ lua_pushinteger(L, nexthop->nh_label_type);
+ lua_setfield(L, -2, "nh_label_type");
+ lua_pushinteger(L, nexthop->weight);
+ lua_setfield(L, -2, "weight");
+ lua_pushinteger(L, nexthop->backup_num);
+ lua_setfield(L, -2, "backup_num");
+ lua_pushinteger(L, *(nexthop->backup_idx));
+ lua_setfield(L, -2, "backup_idx");
+ if (nexthop->nh_encap_type == NET_VXLAN) {
+ lua_pushinteger(L, nexthop->nh_encap.vni);
+ lua_setfield(L, -2, "vni");
+ }
+ lua_pushinteger(L, nexthop->nh_encap_type);
+ lua_setfield(L, -2, "nh_encap_type");
+ lua_pushinteger(L, nexthop->srte_color);
+ lua_setfield(L, -2, "srte_color");
+}
+
+void lua_pushnexthop_group(lua_State *L, const struct nexthop_group *ng)
+{
+ lua_newtable(L);
+ struct nexthop *nexthop;
+ int i = 0;
+
+ for (ALL_NEXTHOPS_PTR(ng, nexthop)) {
+ lua_pushnexthop(L, nexthop);
+ lua_seti(L, -2, i);
+ i++;
+ }
+}
+
void lua_decode_stringp(lua_State *L, int idx, char *str)
{
strlcpy(str, lua_tostring(L, idx), strlen(str) + 1);
diff --git a/lib/frrlua.h b/lib/frrlua.h
index 3e16c82e2..a82009a77 100644
--- a/lib/frrlua.h
+++ b/lib/frrlua.h
@@ -100,6 +100,10 @@ void lua_pushin6addr(lua_State *L, const struct in6_addr *addr);
void lua_decode_in6addr(lua_State *L, int idx, struct in6_addr *addr);
+void lua_pushipaddr(lua_State *L, const struct ipaddr *addr);
+
+void lua_pushethaddr(lua_State *L, const struct ethaddr *addr);
+
/*
* Converts the Lua value at idx to an in6_addr.
*
@@ -138,6 +142,10 @@ void lua_decode_sockunion(lua_State *L, int idx, union sockunion *su);
*/
void *lua_tosockunion(lua_State *L, int idx);
+void lua_pushnexthop_group(lua_State *L, const struct nexthop_group *ng);
+
+void lua_pushnexthop(lua_State *L, const struct nexthop *nexthop);
+
/*
* Converts an int to a Lua value and pushes it on the stack.
*/
diff --git a/lib/frrscript.c b/lib/frrscript.c
index b935b30cc..ccb790dc4 100644
--- a/lib/frrscript.c
+++ b/lib/frrscript.c
@@ -32,6 +32,92 @@
DEFINE_MTYPE_STATIC(LIB, SCRIPT, "Scripting");
+/*
+ * Script name hash utilities
+ */
+
+struct frrscript_names_head frrscript_names_hash;
+
+/*
+ * Wrapper for frrscript_names_add
+ * Use this to register hook calls when a daemon starts up
+ */
+int frrscript_names_add_function_name(const char *function_name)
+{
+ struct frrscript_names_entry *insert =
+ XCALLOC(MTYPE_SCRIPT, sizeof(*insert));
+ strlcpy(insert->function_name, function_name,
+ sizeof(insert->function_name));
+
+ if (frrscript_names_add(&frrscript_names_hash, insert)) {
+ zlog_warn(
+ "Failed to add hook call function name to script_names");
+ return 1;
+ }
+ return 0;
+}
+
+void frrscript_names_destroy(void)
+{
+ struct frrscript_names_entry *ne;
+
+ while ((ne = frrscript_names_pop(&frrscript_names_hash)))
+ XFREE(MTYPE_SCRIPT, ne);
+}
+
+/*
+ * Given a function_name, set its script_name. function_names and script_names
+ * are one-to-one. Each set will wipe the previous script_name.
+ * Return 0 if set was successful, else 1.
+ *
+ * script_name is the base name of the file, without .lua.
+ */
+int frrscript_names_set_script_name(const char *function_name,
+ const char *script_name)
+{
+ struct frrscript_names_entry lookup;
+
+ strlcpy(lookup.function_name, function_name,
+ sizeof(lookup.function_name));
+ struct frrscript_names_entry *snhe =
+ frrscript_names_find(&frrscript_names_hash, &lookup);
+ if (!snhe)
+ return 1;
+ strlcpy(snhe->script_name, script_name, sizeof(snhe->script_name));
+ return 0;
+}
+
+/*
+ * Given a function_name, get its script_name.
+ * Return NULL if function_name not found.
+ *
+ * script_name is the base name of the file, without .lua.
+ */
+char *frrscript_names_get_script_name(const char *function_name)
+{
+ struct frrscript_names_entry lookup;
+
+ strlcpy(lookup.function_name, function_name,
+ sizeof(lookup.function_name));
+ struct frrscript_names_entry *snhe =
+ frrscript_names_find(&frrscript_names_hash, &lookup);
+ if (!snhe)
+ return NULL;
+ return snhe->script_name;
+}
+
+uint32_t frrscript_names_hash_key(const struct frrscript_names_entry *snhe)
+{
+ return string_hash_make(snhe->function_name);
+}
+
+int frrscript_names_hash_cmp(const struct frrscript_names_entry *snhe1,
+ const struct frrscript_names_entry *snhe2)
+{
+ return strncmp(snhe1->function_name, snhe2->function_name,
+ sizeof(snhe1->function_name));
+}
+
/* Codecs */
struct frrscript_codec frrscript_codecs_lib[] = {
diff --git a/lib/frrscript.h b/lib/frrscript.h
index c089df61f..4db3e6f1b 100644
--- a/lib/frrscript.h
+++ b/lib/frrscript.h
@@ -24,6 +24,8 @@
#ifdef HAVE_SCRIPTING
#include <lua.h>
+#include <nexthop.h>
+#include <nexthop_group.h>
#include "frrlua.h"
#include "bgpd/bgp_script.h" // for peer and attr encoders/decoders
@@ -31,6 +33,43 @@
extern "C" {
#endif
+/* Forward declarations */
+extern struct zebra_dplane_ctx ctx;
+extern void lua_pushzebra_dplane_ctx(lua_State *L,
+ const struct zebra_dplane_ctx *ctx);
+extern void lua_decode_zebra_dplane_ctx(lua_State *L, int idx,
+ struct zebra_dplane_ctx *ctx);
+
+/*
+ * Script name hash
+ */
+PREDECL_HASH(frrscript_names);
+
+struct frrscript_names_entry {
+ /* Name of a Lua hook call */
+ char function_name[MAXPATHLEN];
+
+ /* Lua script in which to look for it */
+ char script_name[MAXPATHLEN];
+
+ struct frrscript_names_item item;
+};
+
+extern struct frrscript_names_head frrscript_names_hash;
+
+int frrscript_names_hash_cmp(const struct frrscript_names_entry *snhe1,
+ const struct frrscript_names_entry *snhe2);
+uint32_t frrscript_names_hash_key(const struct frrscript_names_entry *snhe);
+
+DECLARE_HASH(frrscript_names, struct frrscript_names_entry, item,
+ frrscript_names_hash_cmp, frrscript_names_hash_key);
+
+int frrscript_names_add_function_name(const char *function_name);
+void frrscript_names_destroy(void);
+int frrscript_names_set_script_name(const char *function_name,
+ const char *script_name);
+char *frrscript_names_get_script_name(const char *function_name);
+
typedef void (*encoder_func)(lua_State *, const void *);
typedef void *(*decoder_func)(lua_State *, int);
@@ -171,7 +210,12 @@ time_t * : lua_pushtimet, \
char * : lua_pushstring_wrapper, \
struct attr * : lua_pushattr, \
struct peer * : lua_pushpeer, \
-const struct prefix * : lua_pushprefix \
+const struct prefix * : lua_pushprefix, \
+const struct ipaddr * : lua_pushipaddr, \
+const struct ethaddr * : lua_pushethaddr, \
+const struct nexthop_group * : lua_pushnexthop_group, \
+const struct nexthop * : lua_pushnexthop, \
+struct zebra_dplane_ctx * : lua_pushzebra_dplane_ctx \
)((L), (value))
#define DECODE_ARGS_WITH_STATE(L, value) \
@@ -187,7 +231,12 @@ time_t * : lua_decode_timet, \
char * : lua_decode_stringp, \
struct attr * : lua_decode_attr, \
struct peer * : lua_decode_noop, \
-const struct prefix * : lua_decode_noop \
+const struct prefix * : lua_decode_noop, \
+const struct ipaddr * : lua_decode_noop, \
+const struct ethaddr * : lua_decode_noop, \
+const struct nexthop_group * : lua_decode_noop, \
+const struct nexthop * : lua_decode_noop, \
+struct zebra_dplane_ctx * : lua_decode_noop \
)((L), -1, (value))
/*
diff --git a/lib/if.c b/lib/if.c
index cb6270f5e..4ccb36d09 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -423,7 +423,7 @@ struct interface *if_lookup_by_name_vrf(const char *name, struct vrf *vrf)
return RB_FIND(if_name_head, &vrf->ifaces_by_name, &if_tmp);
}
-struct interface *if_lookup_by_name_all_vrf(const char *name)
+static struct interface *if_lookup_by_name_all_vrf(const char *name)
{
struct vrf *vrf;
struct interface *ifp;
@@ -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));
}
@@ -1339,6 +1341,20 @@ static struct cmd_node interface_node = {
.prompt = "%s(config-if)# ",
};
+static int if_config_write_single(const struct lyd_node *dnode, void *arg)
+{
+ nb_cli_show_dnode_cmds(arg, dnode, false);
+
+ return YANG_ITER_CONTINUE;
+}
+
+static int if_nb_config_write(struct vty *vty)
+{
+ yang_dnode_iterate(if_config_write_single, vty, running_config->dnode,
+ "/frr-interface:lib/interface");
+ return 1;
+}
+
void if_cmd_init(int (*config_write)(struct vty *))
{
cmd_variable_handler_register(if_var_handlers);
@@ -1354,6 +1370,11 @@ void if_cmd_init(int (*config_write)(struct vty *))
install_element(INTERFACE_NODE, &no_interface_desc_cmd);
}
+void if_cmd_init_default(void)
+{
+ if_cmd_init(if_nb_config_write);
+}
+
void if_zapi_callbacks(int (*create)(struct interface *ifp),
int (*up)(struct interface *ifp),
int (*down)(struct interface *ifp),
diff --git a/lib/if.h b/lib/if.h
index 1125acd20..1d32c2b08 100644
--- a/lib/if.h
+++ b/lib/if.h
@@ -526,7 +526,6 @@ size_t if_lookup_by_hwaddr(const uint8_t *hw_addr, size_t addrsz,
struct interface ***result, vrf_id_t vrf_id);
struct vrf;
-extern struct interface *if_lookup_by_name_all_vrf(const char *ifname);
extern struct interface *if_lookup_by_name_vrf(const char *name, struct vrf *vrf);
extern struct interface *if_lookup_by_name(const char *ifname, vrf_id_t vrf_id);
extern struct interface *if_get_by_name(const char *ifname, vrf_id_t vrf_id,
@@ -594,6 +593,7 @@ void if_link_params_free(struct interface *);
/* Northbound. */
struct vty;
extern void if_cmd_init(int (*config_write)(struct vty *));
+extern void if_cmd_init_default(void);
extern void if_zapi_callbacks(int (*create)(struct interface *ifp),
int (*up)(struct interface *ifp),
int (*down)(struct interface *ifp),
diff --git a/lib/nexthop_group.c b/lib/nexthop_group.c
index 97d70189f..af9cd2d79 100644
--- a/lib/nexthop_group.c
+++ b/lib/nexthop_group.c
@@ -953,12 +953,6 @@ DEFPY(ecmp_nexthops, ecmp_nexthops_cmd,
nhg_hooks.add_nexthop(nhgc, nh);
}
- if (intf) {
- struct interface *ifp = if_lookup_by_name_all_vrf(intf);
-
- if (ifp)
- ifp->configured = true;
- }
return CMD_SUCCESS;
}
@@ -1265,7 +1259,6 @@ void nexthop_group_interface_state_change(struct interface *ifp,
if (ifp->ifindex != nhop.ifindex)
continue;
- ifp->configured = true;
nh = nexthop_new();
memcpy(nh, &nhop, sizeof(nhop));
diff --git a/lib/northbound.h b/lib/northbound.h
index bf04dbda1..a330bd1a3 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 6676c0b07..70c71b18c 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 28f81f8b3..e47242544 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 cef1d9d38..b14ba0750 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 7c4e9a16e..c5e7d6a32 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 2c8eb2453..f8fdc67d5 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 e2db511fc..9360c7f52 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 150736e00..45f3c2333 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 e6030ca4c..523183bef 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 71d7798af..5dbba6363 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 ------------------------------------------------------ */
diff --git a/lib/thread.h b/lib/thread.h
index c5f0ffbf7..39f21da11 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,
diff --git a/lib/vrf.c b/lib/vrf.c
index 6bc10b8cf..847899f0b 100644
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -21,9 +21,6 @@
#include <zebra.h>
-/* for basename */
-#include <libgen.h>
-
#include "if.h"
#include "vrf.h"
#include "vrf_int.h"
@@ -97,28 +94,6 @@ static int vrf_name_compare(const struct vrf *a, const struct vrf *b)
return strcmp(a->name, b->name);
}
-/* if ns_id is different and not VRF_UNKNOWN,
- * then update vrf identifier, and enable VRF
- */
-static void vrf_update_vrf_id(ns_id_t ns_id, void *opaqueptr)
-{
- ns_id_t vrf_id = (vrf_id_t)ns_id;
- vrf_id_t old_vrf_id;
- struct vrf *vrf = (struct vrf *)opaqueptr;
-
- if (!vrf)
- return;
- old_vrf_id = vrf->vrf_id;
- if (vrf_id == vrf->vrf_id)
- return;
- if (vrf->vrf_id != VRF_UNKNOWN)
- RB_REMOVE(vrf_id_head, &vrfs_by_id, vrf);
- vrf->vrf_id = vrf_id;
- RB_INSERT(vrf_id_head, &vrfs_by_id, vrf);
- if (old_vrf_id == VRF_UNKNOWN)
- vrf_enable(vrf);
-}
-
int vrf_switch_to_netns(vrf_id_t vrf_id)
{
char *name;
@@ -657,115 +632,6 @@ int vrf_configure_backend(enum vrf_backend_type backend)
return 0;
}
-int vrf_handler_create(struct vty *vty, const char *vrfname,
- struct vrf **vrf)
-{
- struct vrf *vrfp;
- char xpath_list[XPATH_MAXLEN];
- int ret;
-
- if (strlen(vrfname) > VRF_NAMSIZ) {
- if (vty)
- vty_out(vty,
- "%% VRF name %s invalid: length exceeds %d bytes\n",
- vrfname, VRF_NAMSIZ);
- else
- flog_warn(
- EC_LIB_VRF_LENGTH,
- "%% VRF name %s invalid: length exceeds %d bytes",
- vrfname, VRF_NAMSIZ);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- if (vty) {
- snprintf(xpath_list, sizeof(xpath_list), FRR_VRF_KEY_XPATH,
- vrfname);
-
- nb_cli_enqueue_change(vty, xpath_list, NB_OP_CREATE, NULL);
- ret = nb_cli_apply_changes_clear_pending(vty, xpath_list);
- if (ret == CMD_SUCCESS) {
- VTY_PUSH_XPATH(VRF_NODE, xpath_list);
- vrfp = vrf_lookup_by_name(vrfname);
- if (vrfp)
- VTY_PUSH_CONTEXT(VRF_NODE, vrfp);
- }
- } else {
- vrfp = vrf_get(VRF_UNKNOWN, vrfname);
-
- if (vrf)
- *vrf = vrfp;
- }
- return CMD_SUCCESS;
-}
-
-int vrf_netns_handler_create(struct vty *vty, struct vrf *vrf, char *pathname,
- ns_id_t ns_id, ns_id_t internal_ns_id,
- ns_id_t rel_def_ns_id)
-{
- struct ns *ns = NULL;
-
- if (!vrf)
- return CMD_WARNING_CONFIG_FAILED;
- if (vrf->vrf_id != VRF_UNKNOWN && vrf->ns_ctxt == NULL) {
- if (vty)
- vty_out(vty,
- "VRF %u is already configured with VRF %s\n",
- vrf->vrf_id, vrf->name);
- else
- zlog_info("VRF %u is already configured with VRF %s",
- vrf->vrf_id, vrf->name);
- return CMD_WARNING_CONFIG_FAILED;
- }
- if (vrf->ns_ctxt != NULL) {
- ns = (struct ns *)vrf->ns_ctxt;
- if (!strcmp(ns->name, pathname)) {
- if (vty)
- vty_out(vty,
- "VRF %u already configured with NETNS %s\n",
- vrf->vrf_id, ns->name);
- else
- zlog_info(
- "VRF %u already configured with NETNS %s",
- vrf->vrf_id, ns->name);
- return CMD_WARNING_CONFIG_FAILED;
- }
- }
- ns = ns_lookup_name(pathname);
- if (ns && ns->vrf_ctxt) {
- struct vrf *vrf2 = (struct vrf *)ns->vrf_ctxt;
-
- if (vrf2 == vrf)
- return CMD_SUCCESS;
- if (vty)
- vty_out(vty,
- "NS %s is already configured with VRF %u(%s)\n",
- ns->name, vrf2->vrf_id, vrf2->name);
- else
- zlog_info("NS %s is already configured with VRF %u(%s)",
- ns->name, vrf2->vrf_id, vrf2->name);
- return CMD_WARNING_CONFIG_FAILED;
- }
- ns = ns_get_created(ns, pathname, ns_id);
- ns->internal_ns_id = internal_ns_id;
- ns->relative_default_ns = rel_def_ns_id;
- ns->vrf_ctxt = (void *)vrf;
- vrf->ns_ctxt = (void *)ns;
- /* update VRF netns NAME */
- strlcpy(vrf->data.l.netns_name, basename(pathname), NS_NAMSIZ);
-
- if (!ns_enable(ns, vrf_update_vrf_id)) {
- if (vty)
- vty_out(vty, "Can not associate NS %u with NETNS %s\n",
- ns->ns_id, ns->name);
- else
- zlog_info("Can not associate NS %u with NETNS %s",
- ns->ns_id, ns->name);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- return CMD_SUCCESS;
-}
-
/* vrf CLI commands */
DEFUN_NOSH(vrf_exit,
vrf_exit_cmd,
@@ -784,8 +650,29 @@ DEFUN_YANG_NOSH (vrf,
{
int idx_name = 1;
const char *vrfname = argv[idx_name]->arg;
+ char xpath_list[XPATH_MAXLEN];
+ struct vrf *vrf;
+ int ret;
+
+ if (strlen(vrfname) > VRF_NAMSIZ) {
+ vty_out(vty,
+ "%% VRF name %s invalid: length exceeds %d bytes\n",
+ vrfname, VRF_NAMSIZ);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
- return vrf_handler_create(vty, vrfname, NULL);
+ snprintf(xpath_list, sizeof(xpath_list), FRR_VRF_KEY_XPATH, vrfname);
+
+ nb_cli_enqueue_change(vty, xpath_list, NB_OP_CREATE, NULL);
+ ret = nb_cli_apply_changes_clear_pending(vty, xpath_list);
+ if (ret == CMD_SUCCESS) {
+ VTY_PUSH_XPATH(VRF_NODE, xpath_list);
+ vrf = vrf_lookup_by_name(vrfname);
+ if (vrf)
+ VTY_PUSH_CONTEXT(VRF_NODE, vrf);
+ }
+
+ return ret;
}
DEFUN_YANG (no_vrf,
diff --git a/lib/vrf.h b/lib/vrf.h
index dab83d42d..0e2e601a7 100644
--- a/lib/vrf.h
+++ b/lib/vrf.h
@@ -301,21 +301,6 @@ extern int vrf_configure_backend(enum vrf_backend_type backend);
extern int vrf_get_backend(void);
extern int vrf_is_backend_netns(void);
-
-/* API to create a VRF. either from vty
- * or through discovery
- */
-extern int vrf_handler_create(struct vty *vty, const char *name,
- struct vrf **vrf);
-
-/* API to associate a VRF with a NETNS.
- * called either from vty or through discovery
- * should be called from zebra only
- */
-extern int vrf_netns_handler_create(struct vty *vty, struct vrf *vrf,
- char *pathname, ns_id_t ext_ns_id,
- ns_id_t ns_id, ns_id_t rel_def_ns_id);
-
/* used internally to enable or disable VRF.
* Notify a change in the VRF ID of the VRF
*/
diff --git a/lib/vty.c b/lib/vty.c
index fef16f1ee..5a03514be 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 62963a609..220fd8d23 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 d4517f969..d625b24f6 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 eea118738..24546f3c4 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -66,7 +66,8 @@ static int zclient_debug;
/* Allocate zclient structure. */
struct zclient *zclient_new(struct thread_master *master,
- struct zclient_options *opt)
+ struct zclient_options *opt,
+ zclient_handler *const *handlers, size_t n_handlers)
{
struct zclient *zclient;
size_t stream_size =
@@ -79,6 +80,9 @@ struct zclient *zclient_new(struct thread_master *master,
zclient->wb = buffer_new(0);
zclient->master = master;
+ zclient->handlers = handlers;
+ zclient->n_handlers = n_handlers;
+
zclient->receive_notify = opt->receive_notify;
zclient->synchronous = opt->synchronous;
@@ -450,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));
@@ -2099,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.
@@ -2109,7 +2113,7 @@ stream_failure:
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
-static int zclient_vrf_add(struct zclient *zclient, vrf_id_t vrf_id)
+static int zclient_vrf_add(ZAPI_CALLBACK_ARGS)
{
struct vrf *vrf;
char vrfname_tmp[VRF_NAMSIZ + 1] = {};
@@ -2141,7 +2145,7 @@ stream_failure:
return -1;
}
-static void zclient_vrf_delete(struct zclient *zclient, vrf_id_t vrf_id)
+static int zclient_vrf_delete(ZAPI_CALLBACK_ARGS)
{
struct vrf *vrf;
@@ -2154,12 +2158,13 @@ static void zclient_vrf_delete(struct zclient *zclient, vrf_id_t vrf_id)
* no point in attempting to delete it.
*/
if (!vrf)
- return;
+ return 0;
vrf_delete(vrf);
+ return 0;
}
-static int zclient_interface_add(struct zclient *zclient, vrf_id_t vrf_id)
+static int zclient_interface_add(ZAPI_CALLBACK_ARGS)
{
struct interface *ifp;
char ifname_tmp[INTERFACE_NAMSIZ + 1] = {};
@@ -2219,7 +2224,7 @@ stream_failure:
return NULL;
}
-static void zclient_interface_delete(struct zclient *zclient, vrf_id_t vrf_id)
+static int zclient_interface_delete(ZAPI_CALLBACK_ARGS)
{
struct interface *ifp;
struct stream *s = zclient->ibuf;
@@ -2227,13 +2232,13 @@ static void zclient_interface_delete(struct zclient *zclient, vrf_id_t vrf_id)
ifp = zebra_interface_state_read(s, vrf_id);
if (ifp == NULL)
- return;
+ return 0;
if_destroy_via_zapi(ifp);
- return;
+ return 0;
}
-static void zclient_interface_up(struct zclient *zclient, vrf_id_t vrf_id)
+static int zclient_interface_up(ZAPI_CALLBACK_ARGS)
{
struct interface *ifp;
struct stream *s = zclient->ibuf;
@@ -2241,12 +2246,13 @@ static void zclient_interface_up(struct zclient *zclient, vrf_id_t vrf_id)
ifp = zebra_interface_state_read(s, vrf_id);
if (!ifp)
- return;
+ return 0;
if_up_via_zapi(ifp);
+ return 0;
}
-static void zclient_interface_down(struct zclient *zclient, vrf_id_t vrf_id)
+static int zclient_interface_down(ZAPI_CALLBACK_ARGS)
{
struct interface *ifp;
struct stream *s = zclient->ibuf;
@@ -2254,12 +2260,13 @@ static void zclient_interface_down(struct zclient *zclient, vrf_id_t vrf_id)
ifp = zebra_interface_state_read(s, vrf_id);
if (!ifp)
- return;
+ return 0;
if_down_via_zapi(ifp);
+ return 0;
}
-static void zclient_handle_error(ZAPI_CALLBACK_ARGS)
+static int zclient_handle_error(ZAPI_CALLBACK_ARGS)
{
enum zebra_error_types error;
struct stream *s = zclient->ibuf;
@@ -2268,6 +2275,7 @@ static void zclient_handle_error(ZAPI_CALLBACK_ARGS)
if (zclient->handle_error)
(*zclient->handle_error)(error);
+ return 0;
}
static int link_params_set_value(struct stream *s, struct if_link_params *iflp)
@@ -2440,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
* +-+-+-+-+-+-+-+-+
@@ -2705,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)
@@ -2800,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
@@ -2910,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)
@@ -3087,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)
@@ -3146,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.
@@ -3585,7 +3593,7 @@ stream_failure:
return -1;
}
-static void zclient_capability_decode(ZAPI_CALLBACK_ARGS)
+static int zclient_capability_decode(ZAPI_CALLBACK_ARGS)
{
struct zclient_capabilities cap;
struct stream *s = zclient->ibuf;
@@ -3612,7 +3620,7 @@ static void zclient_capability_decode(ZAPI_CALLBACK_ARGS)
(*zclient->zebra_capabilities)(&cap);
stream_failure:
- return;
+ return 0;
}
enum zclient_send_status zclient_send_mlag_register(struct zclient *client,
@@ -3651,24 +3659,6 @@ enum zclient_send_status zclient_send_mlag_data(struct zclient *client,
return zclient_send_message(client);
}
-static void zclient_mlag_process_up(ZAPI_CALLBACK_ARGS)
-{
- if (zclient->mlag_process_up)
- (*zclient->mlag_process_up)();
-}
-
-static void zclient_mlag_process_down(ZAPI_CALLBACK_ARGS)
-{
- if (zclient->mlag_process_down)
- (*zclient->mlag_process_down)();
-}
-
-static void zclient_mlag_handle_msg(ZAPI_CALLBACK_ARGS)
-{
- if (zclient->mlag_handle_msg)
- (*zclient->mlag_handle_msg)(zclient->ibuf, length);
-}
-
/*
* Send an OPAQUE message, contents opaque to zebra. The message header
* is a message subtype.
@@ -3858,6 +3848,24 @@ stream_failure:
return -1;
}
+static zclient_handler *const lib_handlers[] = {
+ /* fundamentals */
+ [ZEBRA_CAPABILITIES] = zclient_capability_decode,
+ [ZEBRA_ERROR] = zclient_handle_error,
+
+ /* VRF & interface code is shared in lib */
+ [ZEBRA_VRF_ADD] = zclient_vrf_add,
+ [ZEBRA_VRF_DELETE] = zclient_vrf_delete,
+ [ZEBRA_INTERFACE_ADD] = zclient_interface_add,
+ [ZEBRA_INTERFACE_DELETE] = zclient_interface_delete,
+ [ZEBRA_INTERFACE_UP] = zclient_interface_up,
+ [ZEBRA_INTERFACE_DOWN] = zclient_interface_down,
+
+ /* BFD */
+ [ZEBRA_BFD_DEST_REPLAY] = zclient_bfd_session_reply,
+ [ZEBRA_INTERFACE_BFD_DEST_UPDATE] = zclient_bfd_session_update,
+};
+
/* Zebra client message read function. */
static int zclient_read(struct thread *thread)
{
@@ -3957,283 +3965,10 @@ static int zclient_read(struct thread *thread)
zlog_debug("zclient %p command %s VRF %u", zclient,
zserv_command_string(command), vrf_id);
- switch (command) {
- case ZEBRA_CAPABILITIES:
- zclient_capability_decode(command, zclient, length, vrf_id);
- break;
- case ZEBRA_ROUTER_ID_UPDATE:
- if (zclient->router_id_update)
- (*zclient->router_id_update)(command, zclient, length,
- vrf_id);
- break;
- case ZEBRA_VRF_ADD:
- zclient_vrf_add(zclient, vrf_id);
- break;
- case ZEBRA_VRF_DELETE:
- zclient_vrf_delete(zclient, vrf_id);
- break;
- case ZEBRA_INTERFACE_ADD:
- zclient_interface_add(zclient, vrf_id);
- break;
- case ZEBRA_INTERFACE_DELETE:
- zclient_interface_delete(zclient, vrf_id);
- break;
- case ZEBRA_INTERFACE_ADDRESS_ADD:
- if (zclient->interface_address_add)
- (*zclient->interface_address_add)(command, zclient,
- length, vrf_id);
- break;
- case ZEBRA_INTERFACE_ADDRESS_DELETE:
- if (zclient->interface_address_delete)
- (*zclient->interface_address_delete)(command, zclient,
- length, vrf_id);
- break;
- case ZEBRA_INTERFACE_BFD_DEST_UPDATE:
- if (zclient->interface_bfd_dest_update)
- (*zclient->interface_bfd_dest_update)(command, zclient,
- length, vrf_id);
- break;
- case ZEBRA_INTERFACE_NBR_ADDRESS_ADD:
- if (zclient->interface_nbr_address_add)
- (*zclient->interface_nbr_address_add)(command, zclient,
- length, vrf_id);
- break;
- case ZEBRA_INTERFACE_NBR_ADDRESS_DELETE:
- if (zclient->interface_nbr_address_delete)
- (*zclient->interface_nbr_address_delete)(
- command, zclient, length, vrf_id);
- break;
- case ZEBRA_INTERFACE_UP:
- zclient_interface_up(zclient, vrf_id);
- break;
- case ZEBRA_INTERFACE_DOWN:
- zclient_interface_down(zclient, vrf_id);
- break;
- case ZEBRA_INTERFACE_VRF_UPDATE:
- if (zclient->interface_vrf_update)
- (*zclient->interface_vrf_update)(command, zclient,
- length, vrf_id);
- break;
- case ZEBRA_NEXTHOP_UPDATE:
- if (zclient_debug)
- zlog_debug("zclient rcvd nexthop update");
- if (zclient->nexthop_update)
- (*zclient->nexthop_update)(command, zclient, length,
- vrf_id);
- break;
- case ZEBRA_BFD_DEST_REPLAY:
- if (zclient->bfd_dest_replay)
- (*zclient->bfd_dest_replay)(command, zclient, length,
- vrf_id);
- break;
- case ZEBRA_REDISTRIBUTE_ROUTE_ADD:
- if (zclient->redistribute_route_add)
- (*zclient->redistribute_route_add)(command, zclient,
- length, vrf_id);
- break;
- case ZEBRA_REDISTRIBUTE_ROUTE_DEL:
- if (zclient->redistribute_route_del)
- (*zclient->redistribute_route_del)(command, zclient,
- length, vrf_id);
- break;
- case ZEBRA_INTERFACE_LINK_PARAMS:
- if (zclient->interface_link_params)
- (*zclient->interface_link_params)(command, zclient,
- length, vrf_id);
- break;
- case ZEBRA_FEC_UPDATE:
- if (zclient_debug)
- zlog_debug("zclient rcvd fec update");
- if (zclient->fec_update)
- (*zclient->fec_update)(command, zclient, length);
- break;
- case ZEBRA_LOCAL_ES_ADD:
- if (zclient->local_es_add)
- (*zclient->local_es_add)(command, zclient, length,
- vrf_id);
- break;
- case ZEBRA_LOCAL_ES_DEL:
- if (zclient->local_es_del)
- (*zclient->local_es_del)(command, zclient, length,
- vrf_id);
- break;
- case ZEBRA_LOCAL_ES_EVI_ADD:
- if (zclient->local_es_evi_add)
- (*zclient->local_es_evi_add)(command, zclient, length,
- vrf_id);
- break;
- case ZEBRA_LOCAL_ES_EVI_DEL:
- if (zclient->local_es_evi_del)
- (*zclient->local_es_evi_del)(command, zclient, length,
- vrf_id);
- break;
- case ZEBRA_VNI_ADD:
- if (zclient->local_vni_add)
- (*zclient->local_vni_add)(command, zclient, length,
- vrf_id);
- break;
- case ZEBRA_VNI_DEL:
- if (zclient->local_vni_del)
- (*zclient->local_vni_del)(command, zclient, length,
- vrf_id);
- break;
- case ZEBRA_L3VNI_ADD:
- if (zclient->local_l3vni_add)
- (*zclient->local_l3vni_add)(command, zclient, length,
- vrf_id);
- break;
- case ZEBRA_L3VNI_DEL:
- if (zclient->local_l3vni_del)
- (*zclient->local_l3vni_del)(command, zclient, length,
- vrf_id);
- break;
- case ZEBRA_MACIP_ADD:
- if (zclient->local_macip_add)
- (*zclient->local_macip_add)(command, zclient, length,
- vrf_id);
- break;
- case ZEBRA_MACIP_DEL:
- if (zclient->local_macip_del)
- (*zclient->local_macip_del)(command, zclient, length,
- vrf_id);
- break;
- case ZEBRA_IP_PREFIX_ROUTE_ADD:
- if (zclient->local_ip_prefix_add)
- (*zclient->local_ip_prefix_add)(command, zclient,
- length, vrf_id);
- break;
- case ZEBRA_IP_PREFIX_ROUTE_DEL:
- if (zclient->local_ip_prefix_del)
- (*zclient->local_ip_prefix_del)(command, zclient,
- length, vrf_id);
- break;
- case ZEBRA_PW_STATUS_UPDATE:
- if (zclient->pw_status_update)
- (*zclient->pw_status_update)(command, zclient, length,
- vrf_id);
- break;
- case ZEBRA_ROUTE_NOTIFY_OWNER:
- if (zclient->route_notify_owner)
- (*zclient->route_notify_owner)(command, zclient, length,
- vrf_id);
- break;
- case ZEBRA_RULE_NOTIFY_OWNER:
- if (zclient->rule_notify_owner)
- (*zclient->rule_notify_owner)(command, zclient, length,
- vrf_id);
- break;
- case ZEBRA_NHG_NOTIFY_OWNER:
- if (zclient->nhg_notify_owner)
- (*zclient->nhg_notify_owner)(command, zclient, length,
- vrf_id);
- break;
- case ZEBRA_GET_LABEL_CHUNK:
- if (zclient->label_chunk)
- (*zclient->label_chunk)(command, zclient, length,
- vrf_id);
- break;
- case ZEBRA_IPSET_NOTIFY_OWNER:
- if (zclient->ipset_notify_owner)
- (*zclient->ipset_notify_owner)(command, zclient, length,
- vrf_id);
- break;
- case ZEBRA_IPSET_ENTRY_NOTIFY_OWNER:
- if (zclient->ipset_entry_notify_owner)
- (*zclient->ipset_entry_notify_owner)(command,
- zclient, length,
- vrf_id);
- break;
- case ZEBRA_IPTABLE_NOTIFY_OWNER:
- if (zclient->iptable_notify_owner)
- (*zclient->iptable_notify_owner)(command,
- zclient, length,
- vrf_id);
- break;
- case ZEBRA_VXLAN_SG_ADD:
- if (zclient->vxlan_sg_add)
- (*zclient->vxlan_sg_add)(command, zclient, length,
- vrf_id);
- break;
- case ZEBRA_VXLAN_SG_DEL:
- if (zclient->vxlan_sg_del)
- (*zclient->vxlan_sg_del)(command, zclient, length,
- vrf_id);
- break;
- case ZEBRA_MLAG_PROCESS_UP:
- zclient_mlag_process_up(command, zclient, length, vrf_id);
- break;
- case ZEBRA_MLAG_PROCESS_DOWN:
- zclient_mlag_process_down(command, zclient, length, vrf_id);
- break;
- case ZEBRA_MLAG_FORWARD_MSG:
- zclient_mlag_handle_msg(command, zclient, length, vrf_id);
- break;
- case ZEBRA_SRV6_LOCATOR_ADD:
- if (zclient->srv6_locator_add)
- (*zclient->srv6_locator_add)(command, zclient, length,
- vrf_id);
- break;
- case ZEBRA_SRV6_LOCATOR_DELETE:
- if (zclient->srv6_locator_delete)
- (*zclient->srv6_locator_delete)(command, zclient,
- length, vrf_id);
- break;
- case ZEBRA_SRV6_MANAGER_GET_LOCATOR_CHUNK:
- if (zclient->process_srv6_locator_chunk)
- (*zclient->process_srv6_locator_chunk)(command, zclient,
- length, vrf_id);
- break;
- case ZEBRA_ERROR:
- zclient_handle_error(command, zclient, length, vrf_id);
- break;
- case ZEBRA_OPAQUE_MESSAGE:
- if (zclient->opaque_msg_handler)
- (*zclient->opaque_msg_handler)(command, zclient, length,
- vrf_id);
- break;
- case ZEBRA_OPAQUE_REGISTER:
- if (zclient->opaque_register_handler)
- (*zclient->opaque_register_handler)(command, zclient,
- length, vrf_id);
- break;
- case ZEBRA_OPAQUE_UNREGISTER:
- if (zclient->opaque_unregister_handler)
- (*zclient->opaque_unregister_handler)(command, zclient,
- length, vrf_id);
- break;
- case ZEBRA_SR_POLICY_NOTIFY_STATUS:
- if (zclient->sr_policy_notify_status)
- (*zclient->sr_policy_notify_status)(command, zclient,
- length, vrf_id);
- break;
- case ZEBRA_CLIENT_CLOSE_NOTIFY:
- if (zclient->zebra_client_close_notify)
- (*zclient->zebra_client_close_notify)(command, zclient,
- length, vrf_id);
- break;
- case ZEBRA_NHRP_NEIGH_ADDED:
- if (zclient->neighbor_added)
- (*zclient->neighbor_added)(command, zclient, length,
- vrf_id);
- break;
- case ZEBRA_NHRP_NEIGH_REMOVED:
- if (zclient->neighbor_removed)
- (*zclient->neighbor_removed)(command, zclient, length,
- vrf_id);
- break;
- case ZEBRA_NHRP_NEIGH_GET:
- if (zclient->neighbor_get)
- (*zclient->neighbor_get)(command, zclient, length,
- vrf_id);
- break;
- case ZEBRA_GRE_UPDATE:
- if (zclient->gre_update)
- (*zclient->gre_update)(command, zclient,
- length, vrf_id);
- break;
- default:
- break;
- }
+ if (command < array_size(lib_handlers) && lib_handlers[command])
+ lib_handlers[command](command, zclient, length, vrf_id);
+ if (command < zclient->n_handlers && zclient->handlers[command])
+ zclient->handlers[command](command, zclient, length, vrf_id);
if (zclient->sock < 0)
/* Connection was closed during packet processing. */
diff --git a/lib/zclient.h b/lib/zclient.h
index c35753ca8..82eaefda4 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -21,6 +21,8 @@
#ifndef _ZEBRA_ZCLIENT_H
#define _ZEBRA_ZCLIENT_H
+struct zclient;
+
/* For struct zapi_route. */
#include "prefix.h"
#include "ipaddr.h"
@@ -284,12 +286,20 @@ struct zapi_cap {
vrf_id_t vrf_id;
};
+/* clang-format off */
+#define ZAPI_CALLBACK_ARGS \
+ int cmd, struct zclient *zclient, uint16_t length, vrf_id_t vrf_id
+
+/* function-type typedef (pointer not included) */
+typedef int (zclient_handler)(ZAPI_CALLBACK_ARGS);
+/* clang-format on */
+
/* Structure for the zebra client. */
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? */
@@ -298,6 +308,9 @@ struct zclient {
/* Is this a synchronous client? */
bool synchronous;
+ /* BFD enabled with bfd_protocol_integration_init() */
+ bool bfd_integration;
+
/* Session id (optional) to support clients with multiple sessions */
uint32_t session_id;
@@ -329,16 +342,15 @@ 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];
-#define ZAPI_CALLBACK_ARGS \
- int cmd, struct zclient *zclient, uint16_t length, vrf_id_t vrf_id
-
/* Pointer to the callback functions. */
void (*zebra_connected)(struct zclient *);
void (*zebra_capabilities)(struct zclient_capabilities *cap);
+ int (*handle_error)(enum zebra_error_types error);
+
/*
* When the zclient attempts to write the stream data to
* it's named pipe to/from zebra, we may have a situation
@@ -350,61 +362,15 @@ struct zclient {
* more data.
*/
void (*zebra_buffer_write_ready)(void);
- int (*router_id_update)(ZAPI_CALLBACK_ARGS);
- int (*interface_address_add)(ZAPI_CALLBACK_ARGS);
- int (*interface_address_delete)(ZAPI_CALLBACK_ARGS);
- int (*interface_link_params)(ZAPI_CALLBACK_ARGS);
- int (*interface_bfd_dest_update)(ZAPI_CALLBACK_ARGS);
- int (*interface_nbr_address_add)(ZAPI_CALLBACK_ARGS);
- int (*interface_nbr_address_delete)(ZAPI_CALLBACK_ARGS);
- int (*interface_vrf_update)(ZAPI_CALLBACK_ARGS);
- int (*nexthop_update)(ZAPI_CALLBACK_ARGS);
- int (*bfd_dest_replay)(ZAPI_CALLBACK_ARGS);
- int (*redistribute_route_add)(ZAPI_CALLBACK_ARGS);
- int (*redistribute_route_del)(ZAPI_CALLBACK_ARGS);
- int (*fec_update)(int, struct zclient *, uint16_t);
- int (*local_es_add)(ZAPI_CALLBACK_ARGS);
- int (*local_es_del)(ZAPI_CALLBACK_ARGS);
- int (*local_es_evi_add)(ZAPI_CALLBACK_ARGS);
- int (*local_es_evi_del)(ZAPI_CALLBACK_ARGS);
- int (*local_vni_add)(ZAPI_CALLBACK_ARGS);
- int (*local_vni_del)(ZAPI_CALLBACK_ARGS);
- int (*local_l3vni_add)(ZAPI_CALLBACK_ARGS);
- int (*local_l3vni_del)(ZAPI_CALLBACK_ARGS);
- void (*local_ip_prefix_add)(ZAPI_CALLBACK_ARGS);
- void (*local_ip_prefix_del)(ZAPI_CALLBACK_ARGS);
- int (*local_macip_add)(ZAPI_CALLBACK_ARGS);
- int (*local_macip_del)(ZAPI_CALLBACK_ARGS);
- int (*pw_status_update)(ZAPI_CALLBACK_ARGS);
- int (*route_notify_owner)(ZAPI_CALLBACK_ARGS);
- int (*rule_notify_owner)(ZAPI_CALLBACK_ARGS);
- void (*label_chunk)(ZAPI_CALLBACK_ARGS);
- int (*ipset_notify_owner)(ZAPI_CALLBACK_ARGS);
- int (*ipset_entry_notify_owner)(ZAPI_CALLBACK_ARGS);
- int (*iptable_notify_owner)(ZAPI_CALLBACK_ARGS);
- int (*vxlan_sg_add)(ZAPI_CALLBACK_ARGS);
- int (*vxlan_sg_del)(ZAPI_CALLBACK_ARGS);
- int (*mlag_process_up)(void);
- int (*mlag_process_down)(void);
- int (*mlag_handle_msg)(struct stream *msg, int len);
- int (*nhg_notify_owner)(ZAPI_CALLBACK_ARGS);
- int (*srv6_locator_add)(ZAPI_CALLBACK_ARGS);
- int (*srv6_locator_delete)(ZAPI_CALLBACK_ARGS);
- int (*srv6_function_add)(ZAPI_CALLBACK_ARGS);
- int (*srv6_function_delete)(ZAPI_CALLBACK_ARGS);
- void (*process_srv6_locator_chunk)(ZAPI_CALLBACK_ARGS);
- int (*handle_error)(enum zebra_error_types error);
- int (*opaque_msg_handler)(ZAPI_CALLBACK_ARGS);
- int (*opaque_register_handler)(ZAPI_CALLBACK_ARGS);
- int (*opaque_unregister_handler)(ZAPI_CALLBACK_ARGS);
- int (*sr_policy_notify_status)(ZAPI_CALLBACK_ARGS);
- int (*zebra_client_close_notify)(ZAPI_CALLBACK_ARGS);
- void (*neighbor_added)(ZAPI_CALLBACK_ARGS);
- void (*neighbor_removed)(ZAPI_CALLBACK_ARGS);
- void (*neighbor_get)(ZAPI_CALLBACK_ARGS);
- void (*gre_update)(ZAPI_CALLBACK_ARGS);
+
+ zclient_handler *const *handlers;
+ size_t n_handlers;
};
+/* lib handlers added in bfd.c */
+extern int zclient_bfd_session_reply(ZAPI_CALLBACK_ARGS);
+extern int zclient_bfd_session_update(ZAPI_CALLBACK_ARGS);
+
/* Zebra API message flag. */
#define ZAPI_MESSAGE_NEXTHOP 0x01
#define ZAPI_MESSAGE_DISTANCE 0x02
@@ -893,7 +859,9 @@ int zclient_neigh_ip_encode(struct stream *s, uint16_t cmd, union sockunion *in,
extern uint32_t zclient_get_nhg_start(uint32_t proto);
extern struct zclient *zclient_new(struct thread_master *m,
- struct zclient_options *opt);
+ struct zclient_options *opt,
+ zclient_handler *const *handlers,
+ size_t n_handlers);
extern void zclient_init(struct zclient *, int, unsigned short,
struct zebra_privs_t *privs);
diff --git a/lib/zebra.h b/lib/zebra.h
index 6a02dcb92..c9794352c 100644
--- a/lib/zebra.h
+++ b/lib/zebra.h
@@ -383,6 +383,9 @@ typedef uint32_t route_tag_t;
#define ROUTE_TAG_MAX UINT32_MAX
#define ROUTE_TAG_PRI PRIu32
+/* Name of hook calls */
+#define ZEBRA_ON_RIB_PROCESS_HOOK_CALL "on_rib_process_dplane_results"
+
#ifdef __cplusplus
}
#endif
diff --git a/nhrpd/netlink_arp.c b/nhrpd/netlink_arp.c
index 0a618056d..3658cb16b 100644
--- a/nhrpd/netlink_arp.c
+++ b/nhrpd/netlink_arp.c
@@ -147,7 +147,7 @@ void netlink_set_nflog_group(int nlgroup)
}
}
-void nhrp_neighbor_operation(ZAPI_CALLBACK_ARGS)
+int nhrp_neighbor_operation(ZAPI_CALLBACK_ARGS)
{
union sockunion addr = {}, lladdr = {};
struct interface *ifp;
@@ -157,7 +157,7 @@ void nhrp_neighbor_operation(ZAPI_CALLBACK_ARGS)
zclient_neigh_ip_decode(zclient->ibuf, &api);
if (api.ip_in.ipa_type == AF_UNSPEC)
- return;
+ return 0;
sockunion_family(&addr) = api.ip_in.ipa_type;
memcpy((uint8_t *)sockunion_get_addr(&addr), &api.ip_in.ip.addr,
family2addrsize(api.ip_in.ipa_type));
@@ -172,10 +172,10 @@ void nhrp_neighbor_operation(ZAPI_CALLBACK_ARGS)
ndm_state = api.ndm_state;
if (!ifp)
- return;
+ return 0;
c = nhrp_cache_get(ifp, &addr, 0);
if (!c)
- return;
+ return 0;
debugf(NHRP_DEBUG_KERNEL,
"Netlink: %s %pSU dev %s lladdr %pSU nud 0x%x cache used %u type %u",
(cmd == ZEBRA_NHRP_NEIGH_GET)
@@ -200,4 +200,5 @@ void nhrp_neighbor_operation(ZAPI_CALLBACK_ARGS)
: ZEBRA_NEIGH_STATE_FAILED;
nhrp_cache_set_used(c, state == ZEBRA_NEIGH_STATE_REACHABLE);
}
+ return 0;
}
diff --git a/nhrpd/nhrp_main.c b/nhrpd/nhrp_main.c
index 73684046a..4c98f02e1 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_route.c b/nhrpd/nhrp_route.c
index 12a2fc2fa..76e0978cb 100644
--- a/nhrpd/nhrp_route.c
+++ b/nhrpd/nhrp_route.c
@@ -366,21 +366,25 @@ static void nhrp_zebra_connected(struct zclient *zclient)
nhrp_zebra_register_neigh(VRF_DEFAULT, AFI_IP6, true);
}
+static zclient_handler *const nhrp_handlers[] = {
+ [ZEBRA_INTERFACE_ADDRESS_ADD] = nhrp_interface_address_add,
+ [ZEBRA_INTERFACE_ADDRESS_DELETE] = nhrp_interface_address_delete,
+ [ZEBRA_REDISTRIBUTE_ROUTE_ADD] = nhrp_route_read,
+ [ZEBRA_REDISTRIBUTE_ROUTE_DEL] = nhrp_route_read,
+ [ZEBRA_NHRP_NEIGH_ADDED] = nhrp_neighbor_operation,
+ [ZEBRA_NHRP_NEIGH_REMOVED] = nhrp_neighbor_operation,
+ [ZEBRA_NHRP_NEIGH_GET] = nhrp_neighbor_operation,
+ [ZEBRA_GRE_UPDATE] = nhrp_gre_update,
+};
+
void nhrp_zebra_init(void)
{
zebra_rib[AFI_IP] = route_table_init();
zebra_rib[AFI_IP6] = route_table_init();
- zclient = zclient_new(master, &zclient_options_default);
+ zclient = zclient_new(master, &zclient_options_default, nhrp_handlers,
+ array_size(nhrp_handlers));
zclient->zebra_connected = nhrp_zebra_connected;
- zclient->interface_address_add = nhrp_interface_address_add;
- zclient->interface_address_delete = nhrp_interface_address_delete;
- zclient->redistribute_route_add = nhrp_route_read;
- zclient->redistribute_route_del = nhrp_route_read;
- zclient->neighbor_added = nhrp_neighbor_operation;
- zclient->neighbor_removed = nhrp_neighbor_operation;
- zclient->neighbor_get = nhrp_neighbor_operation;
- zclient->gre_update = nhrp_gre_update;
zclient_init(zclient, ZEBRA_ROUTE_NHRP, 0, &nhrpd_privs);
}
@@ -476,7 +480,7 @@ void nhrp_zebra_terminate(void)
route_table_finish(zebra_rib[AFI_IP6]);
}
-void nhrp_gre_update(ZAPI_CALLBACK_ARGS)
+int nhrp_gre_update(ZAPI_CALLBACK_ARGS)
{
struct stream *s;
struct nhrp_gre_info gre_info, *val;
@@ -485,7 +489,7 @@ void nhrp_gre_update(ZAPI_CALLBACK_ARGS)
/* result */
s = zclient->ibuf;
if (vrf_id != VRF_DEFAULT)
- return;
+ return 0;
/* read GRE information */
STREAM_GETL(s, gre_info.ifindex);
@@ -516,7 +520,9 @@ void nhrp_gre_update(ZAPI_CALLBACK_ARGS)
ifp ? ifp->name : "<none>", gre_info.ifindex, vrf_id);
if (ifp)
nhrp_interface_update_nbma(ifp, val);
- return;
+ return 0;
+
stream_failure:
zlog_err("%s(): error reading response ..", __func__);
+ return -1;
}
diff --git a/nhrpd/nhrpd.h b/nhrpd/nhrpd.h
index 63f1cb97e..753c6e9b2 100644
--- a/nhrpd/nhrpd.h
+++ b/nhrpd/nhrpd.h
@@ -376,8 +376,8 @@ int nhrp_interface_up(ZAPI_CALLBACK_ARGS);
int nhrp_interface_down(ZAPI_CALLBACK_ARGS);
int nhrp_interface_address_add(ZAPI_CALLBACK_ARGS);
int nhrp_interface_address_delete(ZAPI_CALLBACK_ARGS);
-void nhrp_neighbor_operation(ZAPI_CALLBACK_ARGS);
-void nhrp_gre_update(ZAPI_CALLBACK_ARGS);
+int nhrp_neighbor_operation(ZAPI_CALLBACK_ARGS);
+int nhrp_gre_update(ZAPI_CALLBACK_ARGS);
void nhrp_interface_notify_add(struct interface *ifp, struct notifier_block *n,
notifier_fn_t fn);
diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c
index 1eb53411c..cf9b327e9 100644
--- a/ospf6d/ospf6_asbr.c
+++ b/ospf6d/ospf6_asbr.c
@@ -2041,10 +2041,12 @@ ospf6_routemap_rule_match_interface(void *rule, const struct prefix *prefix,
void *object)
{
struct interface *ifp;
+ struct ospf6_route *route;
struct ospf6_external_info *ei;
- ei = ((struct ospf6_route *)object)->route_option;
- ifp = if_lookup_by_name_all_vrf((char *)rule);
+ route = object;
+ ei = route->route_option;
+ ifp = if_lookup_by_name((char *)rule, route->ospf6->vrf_id);
if (ifp != NULL && ei->ifindex == ifp->ifindex)
return RMAP_MATCH;
diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c
index 81573da3a..5e50a6cc5 100644
--- a/ospf6d/ospf6_zebra.c
+++ b/ospf6d/ospf6_zebra.c
@@ -709,19 +709,22 @@ static void ospf6_zebra_connected(struct zclient *zclient)
zclient_send_reg_requests(zclient, VRF_DEFAULT);
}
+static zclient_handler *const ospf6_handlers[] = {
+ [ZEBRA_ROUTER_ID_UPDATE] = ospf6_router_id_update_zebra,
+ [ZEBRA_INTERFACE_ADDRESS_ADD] = ospf6_zebra_if_address_update_add,
+ [ZEBRA_INTERFACE_ADDRESS_DELETE] = ospf6_zebra_if_address_update_delete,
+ [ZEBRA_REDISTRIBUTE_ROUTE_ADD] = ospf6_zebra_read_route,
+ [ZEBRA_REDISTRIBUTE_ROUTE_DEL] = ospf6_zebra_read_route,
+ [ZEBRA_NEXTHOP_UPDATE] = ospf6_zebra_import_check_update,
+};
+
void ospf6_zebra_init(struct thread_master *master)
{
/* Allocate zebra structure. */
- zclient = zclient_new(master, &zclient_options_default);
+ zclient = zclient_new(master, &zclient_options_default, ospf6_handlers,
+ array_size(ospf6_handlers));
zclient_init(zclient, ZEBRA_ROUTE_OSPF6, 0, &ospf6d_privs);
zclient->zebra_connected = ospf6_zebra_connected;
- zclient->router_id_update = ospf6_router_id_update_zebra;
- zclient->interface_address_add = ospf6_zebra_if_address_update_add;
- zclient->interface_address_delete =
- ospf6_zebra_if_address_update_delete;
- zclient->redistribute_route_add = ospf6_zebra_read_route;
- zclient->redistribute_route_del = ospf6_zebra_read_route;
- zclient->nexthop_update = ospf6_zebra_import_check_update;
/* Install command element for zebra node. */
install_element(VIEW_NODE, &show_ospf6_zebra_cmd);
diff --git a/ospfd/ospf_asbr.c b/ospfd/ospf_asbr.c
index 53d2ec538..982fad63e 100644
--- a/ospfd/ospf_asbr.c
+++ b/ospfd/ospf_asbr.c
@@ -72,12 +72,13 @@ void ospf_external_route_remove(struct ospf *ospf, struct prefix_ipv4 *p)
}
/* Add an External info for AS-external-LSA. */
-struct external_info *ospf_external_info_new(uint8_t type,
+struct external_info *ospf_external_info_new(struct ospf *ospf, uint8_t type,
unsigned short instance)
{
struct external_info *new;
new = XCALLOC(MTYPE_OSPF_EXTERNAL_INFO, sizeof(struct external_info));
+ new->ospf = ospf;
new->type = type;
new->instance = instance;
new->to_be_processed = 0;
@@ -138,7 +139,7 @@ ospf_external_info_add(struct ospf *ospf, uint8_t type, unsigned short instance,
}
/* Create new External info instance. */
- new = ospf_external_info_new(type, instance);
+ new = ospf_external_info_new(ospf, type, instance);
new->p = p;
new->ifindex = ifindex;
new->nexthop = nexthop;
diff --git a/ospfd/ospf_asbr.h b/ospfd/ospf_asbr.h
index d3e50903e..160883144 100644
--- a/ospfd/ospf_asbr.h
+++ b/ospfd/ospf_asbr.h
@@ -29,6 +29,8 @@ struct route_map_set_values {
/* Redistributed external information. */
struct external_info {
+ struct ospf *ospf;
+
/* Type of source protocol. */
uint8_t type;
@@ -107,7 +109,8 @@ struct ospf_external_aggr_rt {
#define OSPF_ASBR_NSSA_REDIST_UPDATE_DELAY 9
extern void ospf_external_route_remove(struct ospf *, struct prefix_ipv4 *);
-extern struct external_info *ospf_external_info_new(uint8_t, unsigned short);
+extern struct external_info *ospf_external_info_new(struct ospf *, uint8_t,
+ unsigned short);
extern void ospf_reset_route_map_set_values(struct route_map_set_values *);
extern int ospf_route_map_set_compare(struct route_map_set_values *,
struct route_map_set_values *);
diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c
index cc1b2919c..10541b09b 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 5dcd07277..2e648b335 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/ospf_routemap.c b/ospfd/ospf_routemap.c
index 2525c1cf3..b1216626c 100644
--- a/ospfd/ospf_routemap.c
+++ b/ospfd/ospf_routemap.c
@@ -320,7 +320,7 @@ route_match_interface(void *rule, const struct prefix *prefix, void *object)
struct external_info *ei;
ei = object;
- ifp = if_lookup_by_name_all_vrf((char *)rule);
+ ifp = if_lookup_by_name((char *)rule, ei->ospf->vrf_id);
if (ifp == NULL || ifp->ifindex != ei->ifindex)
return RMAP_NOMATCH;
diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c
index 2ba976af5..b0ed66da5 100644
--- a/ospfd/ospf_zebra.c
+++ b/ospfd/ospf_zebra.c
@@ -2102,25 +2102,33 @@ static int ospf_zebra_client_close_notify(ZAPI_CALLBACK_ARGS)
return ret;
}
+static zclient_handler *const ospf_handlers[] = {
+ [ZEBRA_ROUTER_ID_UPDATE] = ospf_router_id_update_zebra,
+ [ZEBRA_INTERFACE_ADDRESS_ADD] = ospf_interface_address_add,
+ [ZEBRA_INTERFACE_ADDRESS_DELETE] = ospf_interface_address_delete,
+ [ZEBRA_INTERFACE_LINK_PARAMS] = ospf_interface_link_params,
+ [ZEBRA_INTERFACE_VRF_UPDATE] = ospf_interface_vrf_update,
+
+ [ZEBRA_REDISTRIBUTE_ROUTE_ADD] = ospf_zebra_read_route,
+ [ZEBRA_REDISTRIBUTE_ROUTE_DEL] = ospf_zebra_read_route,
+
+ [ZEBRA_OPAQUE_MESSAGE] = ospf_opaque_msg_handler,
+
+ [ZEBRA_CLIENT_CLOSE_NOTIFY] = ospf_zebra_client_close_notify,
+};
+
void ospf_zebra_init(struct thread_master *master, unsigned short instance)
{
/* Allocate zebra structure. */
- zclient = zclient_new(master, &zclient_options_default);
+ zclient = zclient_new(master, &zclient_options_default, ospf_handlers,
+ array_size(ospf_handlers));
zclient_init(zclient, ZEBRA_ROUTE_OSPF, instance, &ospfd_privs);
zclient->zebra_connected = ospf_zebra_connected;
- zclient->router_id_update = ospf_router_id_update_zebra;
- zclient->interface_address_add = ospf_interface_address_add;
- zclient->interface_address_delete = ospf_interface_address_delete;
- zclient->interface_link_params = ospf_interface_link_params;
- zclient->interface_vrf_update = ospf_interface_vrf_update;
-
- zclient->redistribute_route_add = ospf_zebra_read_route;
- zclient->redistribute_route_del = ospf_zebra_read_route;
/* Initialize special zclient for synchronous message exchanges. */
struct zclient_options options = zclient_options_default;
options.synchronous = true;
- zclient_sync = zclient_new(master, &options);
+ zclient_sync = zclient_new(master, &options, NULL, 0);
zclient_sync->sock = -1;
zclient_sync->redist_default = ZEBRA_ROUTE_OSPF;
zclient_sync->instance = instance;
@@ -2135,10 +2143,6 @@ void ospf_zebra_init(struct thread_master *master, unsigned short instance)
access_list_delete_hook(ospf_filter_update);
prefix_list_add_hook(ospf_prefix_list_update);
prefix_list_delete_hook(ospf_prefix_list_update);
-
- zclient->opaque_msg_handler = ospf_opaque_msg_handler;
-
- zclient->zebra_client_close_notify = ospf_zebra_client_close_notify;
}
void ospf_zebra_send_arp(const struct interface *ifp, const struct prefix *p)
diff --git a/pathd/path_cli.c b/pathd/path_cli.c
index 46242fd05..bfeea8c3d 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 6a918b8b8..dacc5eb0d 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/path_zebra.c b/pathd/path_zebra.c
index 53d834f36..156267a39 100644
--- a/pathd/path_zebra.c
+++ b/pathd/path_zebra.c
@@ -320,6 +320,12 @@ static int path_zebra_opaque_msg_handler(ZAPI_CALLBACK_ARGS)
return ret;
}
+static zclient_handler *const path_handlers[] = {
+ [ZEBRA_SR_POLICY_NOTIFY_STATUS] = path_zebra_sr_policy_notify_status,
+ [ZEBRA_ROUTER_ID_UPDATE] = path_zebra_router_id_update,
+ [ZEBRA_OPAQUE_MESSAGE] = path_zebra_opaque_msg_handler,
+};
+
/**
* Initializes Zebra asynchronous connection.
*
@@ -331,15 +337,13 @@ void path_zebra_init(struct thread_master *master)
options.synchronous = true;
/* Initialize asynchronous zclient. */
- zclient = zclient_new(master, &zclient_options_default);
+ zclient = zclient_new(master, &zclient_options_default, path_handlers,
+ array_size(path_handlers));
zclient_init(zclient, ZEBRA_ROUTE_SRTE, 0, &pathd_privs);
zclient->zebra_connected = path_zebra_connected;
- zclient->sr_policy_notify_status = path_zebra_sr_policy_notify_status;
- zclient->router_id_update = path_zebra_router_id_update;
- zclient->opaque_msg_handler = path_zebra_opaque_msg_handler;
/* Initialize special zclient for synchronous message exchanges. */
- zclient_sync = zclient_new(master, &options);
+ zclient_sync = zclient_new(master, &options, NULL, 0);
zclient_sync->sock = -1;
zclient_sync->redist_default = ZEBRA_ROUTE_SRTE;
zclient_sync->instance = 1;
diff --git a/pbrd/pbr_map.c b/pbrd/pbr_map.c
index 053b7363a..03e6bacf1 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 694b915f4..3527523fc 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 9436f4430..cac056abd 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"
@@ -485,14 +561,37 @@ DEFPY(pbr_map_nexthop, pbr_map_nexthop_cmd,
nhop.vrf_id = vrf->vrf_id;
if (intf) {
- struct interface *ifp;
+ struct interface *ifp = NULL;
+ struct interface *ifptmp;
+ struct vrf *vrftmp;
+ int count = 0;
+
+ if (vrf_is_backend_netns() && vrf_name) {
+ ifp = if_lookup_by_name_vrf(intf, vrf);
+ } else {
+ RB_FOREACH (vrftmp, vrf_name_head, &vrfs_by_name) {
+ ifptmp = if_lookup_by_name_vrf(intf, vrftmp);
+ if (ifptmp) {
+ ifp = ifptmp;
+ count++;
+ if (!vrf_is_backend_netns())
+ break;
+ }
+ }
+ }
- ifp = if_lookup_by_name_all_vrf(intf);
if (!ifp) {
vty_out(vty, "Specified Intf %s does not exist\n",
intf);
return CMD_WARNING_CONFIG_FAILED;
}
+ if (count > 1) {
+ vty_out(vty,
+ "Specified Intf %s exists in multiple VRFs\n",
+ intf);
+ vty_out(vty, "You must specify the nexthop-vrf\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
if (ifp->vrf_id != vrf->vrf_id) {
struct vrf *actual;
@@ -764,6 +863,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 +1281,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 +1381,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 643269e34..8a9bb0201 100644
--- a/pbrd/pbr_zebra.c
+++ b/pbrd/pbr_zebra.c
@@ -429,20 +429,24 @@ static int pbr_zebra_nexthop_update(ZAPI_CALLBACK_ARGS)
extern struct zebra_privs_t pbr_privs;
+static zclient_handler *const pbr_handlers[] = {
+ [ZEBRA_INTERFACE_ADDRESS_ADD] = interface_address_add,
+ [ZEBRA_INTERFACE_ADDRESS_DELETE] = interface_address_delete,
+ [ZEBRA_INTERFACE_VRF_UPDATE] = interface_vrf_update,
+ [ZEBRA_ROUTE_NOTIFY_OWNER] = route_notify_owner,
+ [ZEBRA_RULE_NOTIFY_OWNER] = rule_notify_owner,
+ [ZEBRA_NEXTHOP_UPDATE] = pbr_zebra_nexthop_update,
+};
+
void pbr_zebra_init(void)
{
struct zclient_options opt = { .receive_notify = true };
- zclient = zclient_new(master, &opt);
+ zclient = zclient_new(master, &opt, pbr_handlers,
+ array_size(pbr_handlers));
zclient_init(zclient, ZEBRA_ROUTE_PBR, 0, &pbr_privs);
zclient->zebra_connected = zebra_connected;
- zclient->interface_address_add = interface_address_add;
- zclient->interface_address_delete = interface_address_delete;
- zclient->interface_vrf_update = interface_vrf_update;
- zclient->route_notify_owner = route_notify_owner;
- zclient->rule_notify_owner = rule_notify_owner;
- zclient->nexthop_update = pbr_zebra_nexthop_update;
}
void pbr_send_rnh(struct nexthop *nhop, bool reg)
@@ -542,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/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c
index 3f985e64b..86f897aed 100644
--- a/pimd/pim_ifchannel.c
+++ b/pimd/pim_ifchannel.c
@@ -1021,6 +1021,7 @@ void pim_ifchannel_join_add(struct interface *ifp, struct in_addr neigh_addr,
if (remain > holdtime)
return;
}
+ THREAD_OFF(ch->t_ifjoin_expiry_timer);
break;
case PIM_IFJOIN_PRUNE_TMP:
diff --git a/pimd/pim_mlag.c b/pimd/pim_mlag.c
index a06c0a6f4..55d6e7e0f 100644
--- a/pimd/pim_mlag.c
+++ b/pimd/pim_mlag.c
@@ -791,8 +791,10 @@ static void pim_mlag_process_mroute_del(struct mlag_mroute_del msg)
pim_mlag_up_peer_del(&msg);
}
-int pim_zebra_mlag_handle_msg(struct stream *s, int len)
+int pim_zebra_mlag_handle_msg(int cmd, struct zclient *zclient,
+ uint16_t zapi_length, vrf_id_t vrf_id)
{
+ struct stream *s = zclient->ibuf;
struct mlag_msg mlag_msg;
char buf[80];
int rc = 0;
@@ -880,7 +882,7 @@ int pim_zebra_mlag_handle_msg(struct stream *s, int len)
/****************End of PIM Mesasge processing handler********************/
-int pim_zebra_mlag_process_up(void)
+int pim_zebra_mlag_process_up(ZAPI_CALLBACK_ARGS)
{
if (PIM_DEBUG_MLAG)
zlog_debug("%s: Received Process-Up from Mlag", __func__);
@@ -908,7 +910,7 @@ static void pim_mlag_param_reset(void)
router->peerlink_rif[0] = '\0';
}
-int pim_zebra_mlag_process_down(void)
+int pim_zebra_mlag_process_down(ZAPI_CALLBACK_ARGS)
{
if (PIM_DEBUG_MLAG)
zlog_debug("%s: Received Process-Down from Mlag", __func__);
diff --git a/pimd/pim_mlag.h b/pimd/pim_mlag.h
index b044c31c4..996e4d473 100644
--- a/pimd/pim_mlag.h
+++ b/pimd/pim_mlag.h
@@ -24,6 +24,7 @@
#ifndef __PIM_MLAG_H__
#define __PIM_MLAG_H__
+#include "zclient.h"
#include "mlag.h"
#include "pim_iface.h"
@@ -33,9 +34,9 @@ extern void pim_instance_mlag_init(struct pim_instance *pim);
extern void pim_instance_mlag_terminate(struct pim_instance *pim);
extern void pim_if_configure_mlag_dualactive(struct pim_interface *pim_ifp);
extern void pim_if_unconfigure_mlag_dualactive(struct pim_interface *pim_ifp);
-extern int pim_zebra_mlag_process_up(void);
-extern int pim_zebra_mlag_process_down(void);
-extern int pim_zebra_mlag_handle_msg(struct stream *msg, int len);
+extern int pim_zebra_mlag_process_up(ZAPI_CALLBACK_ARGS);
+extern int pim_zebra_mlag_process_down(ZAPI_CALLBACK_ARGS);
+extern int pim_zebra_mlag_handle_msg(ZAPI_CALLBACK_ARGS);
/* pm_zpthread.c */
extern int pim_mlag_signal_zpthread(void);
diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c
index aa041df85..1da33af00 100644
--- a/pimd/pim_zebra.c
+++ b/pimd/pim_zebra.c
@@ -439,23 +439,29 @@ static void pim_zebra_capabilities(struct zclient_capabilities *cap)
router->mlag_role = cap->role;
}
+static zclient_handler *const pim_handlers[] = {
+ [ZEBRA_ROUTER_ID_UPDATE] = pim_router_id_update_zebra,
+ [ZEBRA_INTERFACE_ADDRESS_ADD] = pim_zebra_if_address_add,
+ [ZEBRA_INTERFACE_ADDRESS_DELETE] = pim_zebra_if_address_del,
+ [ZEBRA_INTERFACE_VRF_UPDATE] = pim_zebra_interface_vrf_update,
+ [ZEBRA_NEXTHOP_UPDATE] = pim_parse_nexthop_update,
+
+ [ZEBRA_VXLAN_SG_ADD] = pim_zebra_vxlan_sg_proc,
+ [ZEBRA_VXLAN_SG_DEL] = pim_zebra_vxlan_sg_proc,
+
+ [ZEBRA_MLAG_PROCESS_UP] = pim_zebra_mlag_process_up,
+ [ZEBRA_MLAG_PROCESS_DOWN] = pim_zebra_mlag_process_down,
+ [ZEBRA_MLAG_FORWARD_MSG] = pim_zebra_mlag_handle_msg,
+};
+
void pim_zebra_init(void)
{
/* Socket for receiving updates from Zebra daemon */
- zclient = zclient_new(router->master, &zclient_options_default);
+ zclient = zclient_new(router->master, &zclient_options_default,
+ pim_handlers, array_size(pim_handlers));
zclient->zebra_capabilities = pim_zebra_capabilities;
zclient->zebra_connected = pim_zebra_connected;
- zclient->router_id_update = pim_router_id_update_zebra;
- zclient->interface_address_add = pim_zebra_if_address_add;
- zclient->interface_address_delete = pim_zebra_if_address_del;
- zclient->interface_vrf_update = pim_zebra_interface_vrf_update;
- zclient->nexthop_update = pim_parse_nexthop_update;
- zclient->vxlan_sg_add = pim_zebra_vxlan_sg_proc;
- zclient->vxlan_sg_del = pim_zebra_vxlan_sg_proc;
- zclient->mlag_process_up = pim_zebra_mlag_process_up;
- zclient->mlag_process_down = pim_zebra_mlag_process_down;
- zclient->mlag_handle_msg = pim_zebra_mlag_handle_msg;
zclient_init(zclient, ZEBRA_ROUTE_PIM, 0, &pimd_privs);
if (PIM_DEBUG_PIM_TRACE) {
diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c
index abf9577bd..abf1119ac 100644
--- a/pimd/pim_zlookup.c
+++ b/pimd/pim_zlookup.c
@@ -137,7 +137,7 @@ void zclient_lookup_new(void)
struct zclient_options options = zclient_options_default;
options.synchronous = true;
- zlookup = zclient_new(router->master, &options);
+ zlookup = zclient_new(router->master, &options, NULL, 0);
if (!zlookup) {
flog_err(EC_LIB_ZAPI_SOCKET, "%s: zclient_new() failure",
__func__);
diff --git a/ripd/rip_cli.c b/ripd/rip_cli.c
index 8a3ce24f5..5590b1833 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_interface.c b/ripd/rip_interface.c
index 2eb7bb6da..3d128ee72 100644
--- a/ripd/rip_interface.c
+++ b/ripd/rip_interface.c
@@ -1103,33 +1103,6 @@ void rip_passive_nondefault_clean(struct rip *rip)
rip_passive_interface_apply_all(rip);
}
-/* Write rip configuration of each interface. */
-static int rip_interface_config_write(struct vty *vty)
-{
- struct vrf *vrf;
- int write = 0;
-
- RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
- struct interface *ifp;
-
- FOR_ALL_INTERFACES (vrf, ifp) {
- struct lyd_node *dnode;
-
- dnode = yang_dnode_getf(
- running_config->dnode,
- "/frr-interface:lib/interface[name='%s'][vrf='%s']",
- ifp->name, vrf->name);
- if (dnode == NULL)
- continue;
-
- write = 1;
- nb_cli_show_dnode_cmds(vty, dnode, false);
- }
- }
-
- return write;
-}
-
int rip_show_network_config(struct vty *vty, struct rip *rip)
{
unsigned int i;
@@ -1194,7 +1167,7 @@ void rip_if_init(void)
hook_register_prio(if_del, 0, rip_interface_delete_hook);
/* Install interface node. */
- if_cmd_init(rip_interface_config_write);
+ if_cmd_init_default();
if_zapi_callbacks(rip_ifp_create, rip_ifp_up,
rip_ifp_down, rip_ifp_destroy);
}
diff --git a/ripd/rip_nb.h b/ripd/rip_nb.h
index 26bb3cb3b..1e29f3b77 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/ripd/rip_zebra.c b/ripd/rip_zebra.c
index 074370dc2..1f1566863 100644
--- a/ripd/rip_zebra.c
+++ b/ripd/rip_zebra.c
@@ -230,17 +230,21 @@ static void rip_zebra_connected(struct zclient *zclient)
zclient_send_reg_requests(zclient, VRF_DEFAULT);
}
+zclient_handler *const rip_handlers[] = {
+ [ZEBRA_INTERFACE_ADDRESS_ADD] = rip_interface_address_add,
+ [ZEBRA_INTERFACE_ADDRESS_DELETE] = rip_interface_address_delete,
+ [ZEBRA_INTERFACE_VRF_UPDATE] = rip_interface_vrf_update,
+ [ZEBRA_REDISTRIBUTE_ROUTE_ADD] = rip_zebra_read_route,
+ [ZEBRA_REDISTRIBUTE_ROUTE_DEL] = rip_zebra_read_route,
+};
+
void rip_zclient_init(struct thread_master *master)
{
/* Set default value to the zebra client structure. */
- zclient = zclient_new(master, &zclient_options_default);
+ zclient = zclient_new(master, &zclient_options_default, rip_handlers,
+ array_size(rip_handlers));
zclient_init(zclient, ZEBRA_ROUTE_RIP, 0, &ripd_privs);
zclient->zebra_connected = rip_zebra_connected;
- zclient->interface_address_add = rip_interface_address_add;
- zclient->interface_address_delete = rip_interface_address_delete;
- zclient->interface_vrf_update = rip_interface_vrf_update;
- zclient->redistribute_route_add = rip_zebra_read_route;
- zclient->redistribute_route_del = rip_zebra_read_route;
}
void rip_zclient_stop(void)
diff --git a/ripngd/ripng_cli.c b/ripngd/ripng_cli.c
index 722c0c7dd..63b75e723 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_interface.c b/ripngd/ripng_interface.c
index 7b5e7604d..dc577facc 100644
--- a/ripngd/ripng_interface.c
+++ b/ripngd/ripng_interface.c
@@ -923,33 +923,6 @@ static int ripng_if_delete_hook(struct interface *ifp)
return 0;
}
-/* Configuration write function for ripngd. */
-static int interface_config_write(struct vty *vty)
-{
- struct vrf *vrf;
- int write = 0;
-
- RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
- struct interface *ifp;
-
- FOR_ALL_INTERFACES (vrf, ifp) {
- struct lyd_node *dnode;
-
- dnode = yang_dnode_getf(
- running_config->dnode,
- "/frr-interface:lib/interface[name='%s'][vrf='%s']",
- ifp->name, vrf->name);
- if (dnode == NULL)
- continue;
-
- write = 1;
- nb_cli_show_dnode_cmds(vty, dnode, false);
- }
- }
-
- return write;
-}
-
/* Initialization of interface. */
void ripng_if_init(void)
{
@@ -958,7 +931,7 @@ void ripng_if_init(void)
hook_register_prio(if_del, 0, ripng_if_delete_hook);
/* Install interface node. */
- if_cmd_init(interface_config_write);
+ if_cmd_init_default();
if_zapi_callbacks(ripng_ifp_create, ripng_ifp_up,
ripng_ifp_down, ripng_ifp_destroy);
}
diff --git a/ripngd/ripng_nb.h b/ripngd/ripng_nb.h
index d6aecbf6b..cf0424248 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/ripngd/ripng_zebra.c b/ripngd/ripng_zebra.c
index baf7f0096..4108aa506 100644
--- a/ripngd/ripng_zebra.c
+++ b/ripngd/ripng_zebra.c
@@ -234,19 +234,23 @@ static void ripng_zebra_connected(struct zclient *zclient)
zclient_send_reg_requests(zclient, VRF_DEFAULT);
}
+static zclient_handler *const ripng_handlers[] = {
+ [ZEBRA_INTERFACE_ADDRESS_ADD] = ripng_interface_address_add,
+ [ZEBRA_INTERFACE_ADDRESS_DELETE] = ripng_interface_address_delete,
+ [ZEBRA_INTERFACE_VRF_UPDATE] = ripng_interface_vrf_update,
+ [ZEBRA_REDISTRIBUTE_ROUTE_ADD] = ripng_zebra_read_route,
+ [ZEBRA_REDISTRIBUTE_ROUTE_DEL] = ripng_zebra_read_route,
+};
+
/* Initialize zebra structure and it's commands. */
void zebra_init(struct thread_master *master)
{
/* Allocate zebra structure. */
- zclient = zclient_new(master, &zclient_options_default);
+ zclient = zclient_new(master, &zclient_options_default, ripng_handlers,
+ array_size(ripng_handlers));
zclient_init(zclient, ZEBRA_ROUTE_RIPNG, 0, &ripngd_privs);
zclient->zebra_connected = ripng_zebra_connected;
- zclient->interface_address_add = ripng_interface_address_add;
- zclient->interface_address_delete = ripng_interface_address_delete;
- zclient->interface_vrf_update = ripng_interface_vrf_update;
- zclient->redistribute_route_add = ripng_zebra_read_route;
- zclient->redistribute_route_del = ripng_zebra_read_route;
}
void ripng_zebra_stop(void)
diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c
index 67cff378e..8c9f0c278 100644
--- a/sharpd/sharp_zebra.c
+++ b/sharpd/sharp_zebra.c
@@ -720,6 +720,10 @@ void sharp_redistribute_vrf(struct vrf *vrf, int type)
0, vrf->vrf_id);
}
+static zclient_handler *const sharp_opaque_handlers[] = {
+ [ZEBRA_OPAQUE_MESSAGE] = sharp_opaque_handler,
+};
+
/* Add a zclient with a specified session id, for testing. */
int sharp_zclient_create(uint32_t session_id)
{
@@ -732,15 +736,14 @@ int sharp_zclient_create(uint32_t session_id)
return -1;
}
- client = zclient_new(master, &zclient_options_default);
+ client = zclient_new(master, &zclient_options_default,
+ sharp_opaque_handlers,
+ array_size(sharp_opaque_handlers));
client->sock = -1;
client->session_id = session_id;
zclient_init(client, ZEBRA_ROUTE_SHARP, 0, &sharp_privs);
- /* Register handlers for messages we expect this session to see */
- client->opaque_msg_handler = sharp_opaque_handler;
-
/* Enqueue on the list of test clients */
add_zclient(client);
@@ -928,7 +931,7 @@ int sharp_zebra_srv6_manager_release_locator_chunk(const char *locator_name)
return srv6_manager_release_locator_chunk(zclient, locator_name);
}
-static void sharp_zebra_process_srv6_locator_chunk(ZAPI_CALLBACK_ARGS)
+static int sharp_zebra_process_srv6_locator_chunk(ZAPI_CALLBACK_ARGS)
{
struct stream *s = NULL;
struct srv6_locator_chunk s6c = {};
@@ -951,17 +954,31 @@ static void sharp_zebra_process_srv6_locator_chunk(ZAPI_CALLBACK_ARGS)
for (ALL_LIST_ELEMENTS_RO(loc->chunks, chunk_node, c))
if (!prefix_cmp(c, &s6c.prefix))
- return;
+ return 0;
chunk = prefix_ipv6_new();
*chunk = s6c.prefix;
listnode_add(loc->chunks, chunk);
- return;
+ return 0;
}
zlog_err("%s: can't get locator_chunk!!", __func__);
+ return 0;
}
+static zclient_handler *const sharp_handlers[] = {
+ [ZEBRA_INTERFACE_ADDRESS_ADD] = interface_address_add,
+ [ZEBRA_INTERFACE_ADDRESS_DELETE] = interface_address_delete,
+ [ZEBRA_ROUTE_NOTIFY_OWNER] = route_notify_owner,
+ [ZEBRA_NEXTHOP_UPDATE] = sharp_nexthop_update,
+ [ZEBRA_NHG_NOTIFY_OWNER] = nhg_notify_owner,
+ [ZEBRA_REDISTRIBUTE_ROUTE_ADD] = sharp_redistribute_route,
+ [ZEBRA_REDISTRIBUTE_ROUTE_DEL] = sharp_redistribute_route,
+ [ZEBRA_OPAQUE_MESSAGE] = sharp_opaque_handler,
+ [ZEBRA_SRV6_MANAGER_GET_LOCATOR_CHUNK] =
+ sharp_zebra_process_srv6_locator_chunk,
+};
+
void sharp_zebra_init(void)
{
struct zclient_options opt = {.receive_notify = true};
@@ -969,19 +986,10 @@ void sharp_zebra_init(void)
if_zapi_callbacks(sharp_ifp_create, sharp_ifp_up,
sharp_ifp_down, sharp_ifp_destroy);
- zclient = zclient_new(master, &opt);
+ zclient = zclient_new(master, &opt, sharp_handlers,
+ array_size(sharp_handlers));
zclient_init(zclient, ZEBRA_ROUTE_SHARP, 0, &sharp_privs);
zclient->zebra_connected = zebra_connected;
- zclient->interface_address_add = interface_address_add;
- zclient->interface_address_delete = interface_address_delete;
- zclient->route_notify_owner = route_notify_owner;
- zclient->nexthop_update = sharp_nexthop_update;
- zclient->nhg_notify_owner = nhg_notify_owner;
zclient->zebra_buffer_write_ready = sharp_zclient_buffer_ready;
- zclient->redistribute_route_add = sharp_redistribute_route;
- zclient->redistribute_route_del = sharp_redistribute_route;
- zclient->opaque_msg_handler = sharp_opaque_handler;
- zclient->process_srv6_locator_chunk =
- sharp_zebra_process_srv6_locator_chunk;
}
diff --git a/staticd/static_vty.c b/staticd/static_vty.c
index 751a26277..95d1386a6 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 8861afa46..84a359593 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/staticd/static_zebra.c b/staticd/static_zebra.c
index a01ecad81..538fae28a 100644
--- a/staticd/static_zebra.c
+++ b/staticd/static_zebra.c
@@ -508,6 +508,13 @@ extern void static_zebra_route_add(struct static_path *pn, bool install)
zclient, &api);
}
+static zclient_handler *const static_handlers[] = {
+ [ZEBRA_INTERFACE_ADDRESS_ADD] = interface_address_add,
+ [ZEBRA_INTERFACE_ADDRESS_DELETE] = interface_address_delete,
+ [ZEBRA_ROUTE_NOTIFY_OWNER] = route_notify_owner,
+ [ZEBRA_NEXTHOP_UPDATE] = static_zebra_nexthop_update,
+};
+
void static_zebra_init(void)
{
struct zclient_options opt = { .receive_notify = true };
@@ -515,15 +522,12 @@ void static_zebra_init(void)
if_zapi_callbacks(static_ifp_create, static_ifp_up,
static_ifp_down, static_ifp_destroy);
- zclient = zclient_new(master, &opt);
+ zclient = zclient_new(master, &opt, static_handlers,
+ array_size(static_handlers));
zclient_init(zclient, ZEBRA_ROUTE_STATIC, 0, &static_privs);
zclient->zebra_capabilities = static_zebra_capabilities;
zclient->zebra_connected = zebra_connected;
- zclient->interface_address_add = interface_address_add;
- zclient->interface_address_delete = interface_address_delete;
- zclient->route_notify_owner = route_notify_owner;
- zclient->nexthop_update = static_zebra_nexthop_update;
static_nht_hash = hash_create(static_nht_hash_key,
static_nht_hash_cmp,
diff --git a/tests/bgpd/test_mpath.c b/tests/bgpd/test_mpath.c
index 77fd87659..d1ca356b9 100644
--- a/tests/bgpd/test_mpath.c
+++ b/tests/bgpd/test_mpath.c
@@ -392,7 +392,7 @@ static int global_test_init(void)
{
qobj_init();
master = thread_master_create(NULL);
- zclient = zclient_new(master, &zclient_options_default);
+ zclient = zclient_new(master, &zclient_options_default, NULL, 0);
bgp_master_init(master, BGP_SOCKET_SNDBUF_SIZE, list_new());
vrf_init(NULL, NULL, NULL, NULL, NULL);
bgp_option_set(BGP_OPT_NO_LISTEN);
diff --git a/tests/topotests/all_protocol_startup/test_all_protocol_startup.py b/tests/topotests/all_protocol_startup/test_all_protocol_startup.py
index e8a793cfe..34752b0bd 100644
--- a/tests/topotests/all_protocol_startup/test_all_protocol_startup.py
+++ b/tests/topotests/all_protocol_startup/test_all_protocol_startup.py
@@ -34,7 +34,6 @@ import pytest
import glob
from time import sleep
-
pytestmark = [
pytest.mark.babeld,
pytest.mark.bgpd,
@@ -389,34 +388,71 @@ def route_get_nhg_id(route_str):
def verify_nexthop_group(nhg_id, recursive=False, ecmp=0):
net = get_topogen().net
- # Verify NHG is valid/installed
- output = net["r1"].cmd('vtysh -c "show nexthop-group rib %d"' % nhg_id)
-
- match = re.search(r"Valid", output)
- assert match is not None, "Nexthop Group ID=%d not marked Valid" % nhg_id
-
+ count = 0
+ valid = None
+ ecmpcount = None
+ depends = None
+ resolved_id = None
+ installed = None
+ found = False
+
+ while not found and count < 10:
+ count += 1
+ # Verify NHG is valid/installed
+ output = net["r1"].cmd('vtysh -c "show nexthop-group rib %d"' % nhg_id)
+ valid = re.search(r"Valid", output)
+ if valid is None:
+ found = False
+ sleep(1)
+ continue
+
+ if ecmp or recursive:
+ ecmpcount = re.search(r"Depends:.*\n", output)
+ if ecmpcount is None:
+ found = False
+ sleep(1)
+ continue
+
+ # list of IDs in group
+ depends = re.findall(r"\((\d+)\)", ecmpcount.group(0))
+
+ if ecmp:
+ if len(depends) != ecmp:
+ found = False
+ sleep(1)
+ continue
+ else:
+ # If recursive, we need to look at its resolved group
+ if len(depends) != 1:
+ found = False
+ sleep(1)
+ continue
+
+ resolved_id = int(depends[0])
+ verify_nexthop_group(resolved_id, False)
+ else:
+ installed = re.search(r"Installed", output)
+ if installed is None:
+ found = False
+ sleep(1)
+ continue
+ found = True
+
+ assert valid is not None, "Nexthop Group ID=%d not marked Valid" % nhg_id
if ecmp or recursive:
- match = re.search(r"Depends:.*\n", output)
- assert match is not None, "Nexthop Group ID=%d has no depends" % nhg_id
-
- # list of IDs in group
- depends = re.findall(r"\((\d+)\)", match.group(0))
-
+ assert ecmpcount is not None, "Nexthop Group ID=%d has no depends" % nhg_id
if ecmp:
assert len(depends) == ecmp, (
"Nexthop Group ID=%d doesn't match ecmp size" % nhg_id
)
else:
- # If recursive, we need to look at its resolved group
assert len(depends) == 1, (
"Nexthop Group ID=%d should only have one recursive depend" % nhg_id
)
- resolved_id = int(depends[0])
- verify_nexthop_group(resolved_id, False)
-
else:
- match = re.search(r"Installed", output)
- assert match is not None, "Nexthop Group ID=%d not marked Installed" % nhg_id
+ assert installed is not None, (
+ "Nexthop Group ID=%d not marked Installed" % nhg_id
+ )
def verify_route_nexthop_group(route_str, recursive=False, ecmp=0):
@@ -447,7 +483,6 @@ def test_nexthop_groups():
# Create with sharpd using nexthop-group
net["r1"].cmd('vtysh -c "sharp install routes 2.2.2.1 nexthop-group basic 1"')
-
verify_route_nexthop_group("2.2.2.1/32")
## Connected
@@ -457,7 +492,6 @@ def test_nexthop_groups():
)
net["r1"].cmd('vtysh -c "sharp install routes 2.2.2.2 nexthop-group connected 1"')
-
verify_route_nexthop_group("2.2.2.2/32")
## Recursive
@@ -548,10 +582,16 @@ def test_nexthop_groups():
)
# Get routes and test if has too many (duplicate) nexthops
+ count = 0
+ dups = []
nhg_id = route_get_nhg_id("6.6.6.1/32")
- output = net["r1"].cmd('vtysh -c "show nexthop-group rib %d"' % nhg_id)
+ while (len(dups) != 3) and count < 10:
+ output = net["r1"].cmd('vtysh -c "show nexthop-group rib %d"' % nhg_id)
- dups = re.findall(r"(via 1\.1\.1\.1)", output)
+ dups = re.findall(r"(via 1\.1\.1\.1)", output)
+ if len(dups) != 3:
+ count += 1
+ sleep(1)
# Should find 3, itself is inactive
assert len(dups) == 3, (
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 3c176f25a..27a441932 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 54b3e80da..2a51dc83e 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 789f93b83..6cd92e293 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/conftest.py b/tests/topotests/conftest.py
index 7fe6a5aea..ce7878c24 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 834205f65..4a33edb9d 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/lutil.py b/tests/topotests/lib/lutil.py
index c17c7f14e..5c1fa24a7 100644
--- a/tests/topotests/lib/lutil.py
+++ b/tests/topotests/lib/lutil.py
@@ -189,11 +189,8 @@ Total %-4d %-4d %d\n\
self.log("unable to read: " + tstFile)
sys.exit(1)
- def command(self, target, command, regexp, op, result, returnJson):
+ def command(self, target, command, regexp, op, result, returnJson, startt=None):
global net
- if op != "wait":
- self.l_line += 1
-
if op == "jsoncmp_pass" or op == "jsoncmp_fail":
returnJson = True
@@ -294,7 +291,11 @@ Total %-4d %-4d %d\n\
% (group_nl_converted, ret),
9,
)
- if op == "pass" or op == "fail":
+ if startt != None:
+ if js != None or ret is not False:
+ delta = time.time() - startt
+ self.result(target, success, "%s +%4.2f secs" % (result, delta))
+ elif op == "pass" or op == "fail":
self.result(target, success, result)
if js != None:
return js
@@ -326,7 +327,7 @@ Total %-4d %-4d %d\n\
while wait_count > 0:
n += 1
- found = self.command(target, command, regexp, op, result, returnJson)
+ found = self.command(target, command, regexp, op, result, returnJson, startt)
if found is not False:
break
@@ -336,14 +337,6 @@ Total %-4d %-4d %d\n\
delta = time.time() - startt
self.log("Done after %d loops, time=%s, Found=%s" % (n, delta, found))
- found = self.command(
- target,
- command,
- regexp,
- "pass",
- "%s +%4.2f secs" % (result, delta),
- returnJson,
- )
return found
diff --git a/tests/topotests/lib/topotest.py b/tests/topotests/lib/topotest.py
index 947ea196b..6ee000b0f 100644
--- a/tests/topotests/lib/topotest.py
+++ b/tests/topotests/lib/topotest.py
@@ -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 3e3bf5cb8..debf7ad76 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 33c5635eb..7dd13935b 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/vrrpd/vrrp_vty.c b/vrrpd/vrrp_vty.c
index 91ff6fe28..c11254c71 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");
@@ -715,35 +715,6 @@ DEFUN_NOSH (show_debugging_vrrp,
/* clang-format on */
-/*
- * Write per interface VRRP config.
- */
-static int vrrp_config_write_interface(struct vty *vty)
-{
- struct vrf *vrf;
- int write = 0;
-
- RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
- struct interface *ifp;
-
- FOR_ALL_INTERFACES (vrf, ifp) {
- struct lyd_node *dnode;
-
- dnode = yang_dnode_getf(
- running_config->dnode,
- "/frr-interface:lib/interface[name='%s'][vrf='%s']",
- ifp->name, vrf->name);
- if (dnode == NULL)
- continue;
-
- write = 1;
- nb_cli_show_dnode_cmds(vty, dnode, false);
- }
- }
-
- return write;
-}
-
static struct cmd_node debug_node = {
.name = "debug",
.node = DEBUG_NODE,
@@ -763,7 +734,7 @@ void vrrp_vty_init(void)
install_node(&debug_node);
install_node(&vrrp_node);
vrf_cmd_init(NULL);
- if_cmd_init(vrrp_config_write_interface);
+ if_cmd_init_default();
install_element(VIEW_NODE, &vrrp_vrid_show_cmd);
install_element(VIEW_NODE, &vrrp_vrid_show_summary_cmd);
diff --git a/vrrpd/vrrp_vty.h b/vrrpd/vrrp_vty.h
index 6c6eef032..587537a6f 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/vrrpd/vrrp_zebra.c b/vrrpd/vrrp_zebra.c
index 385d44357..d7d37f1f3 100644
--- a/vrrpd/vrrp_zebra.c
+++ b/vrrpd/vrrp_zebra.c
@@ -188,18 +188,22 @@ void vrrp_zclient_send_interface_protodown(struct interface *ifp, bool down)
zclient_send_interface_protodown(zclient, ifp->vrf_id, ifp, down);
}
+static zclient_handler *const vrrp_handlers[] = {
+ [ZEBRA_ROUTER_ID_UPDATE] = vrrp_router_id_update_zebra,
+ [ZEBRA_INTERFACE_ADDRESS_ADD] = vrrp_zebra_if_address_add,
+ [ZEBRA_INTERFACE_ADDRESS_DELETE] = vrrp_zebra_if_address_del,
+};
+
void vrrp_zebra_init(void)
{
if_zapi_callbacks(vrrp_ifp_create, vrrp_ifp_up,
vrrp_ifp_down, vrrp_ifp_destroy);
/* Socket for receiving updates from Zebra daemon */
- zclient = zclient_new(master, &zclient_options_default);
+ zclient = zclient_new(master, &zclient_options_default, vrrp_handlers,
+ array_size(vrrp_handlers));
zclient->zebra_connected = vrrp_zebra_connected;
- zclient->router_id_update = vrrp_router_id_update_zebra;
- zclient->interface_address_add = vrrp_zebra_if_address_add;
- zclient->interface_address_delete = vrrp_zebra_if_address_del;
zclient_init(zclient, ZEBRA_ROUTE_VRRP, 0, &vrrp_privs);
diff --git a/zebra/debug_nl.c b/zebra/debug_nl.c
index 842579f89..2175aaff6 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/interface.c b/zebra/interface.c
index 595862a6c..6479dbb58 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -2481,12 +2481,24 @@ DEFPY (show_interface_name_vrf_all,
VRF_ALL_CMD_HELP_STR
JSON_STR)
{
- struct interface *ifp;
+ struct interface *ifp = NULL;
+ struct interface *ifptmp;
+ struct vrf *vrf;
json_object *json = NULL;
+ int count = 0;
interface_update_stats();
- ifp = if_lookup_by_name_all_vrf(ifname);
+ RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
+ ifptmp = if_lookup_by_name_vrf(ifname, vrf);
+ if (ifptmp) {
+ ifp = ifptmp;
+ count++;
+ if (!vrf_is_backend_netns())
+ break;
+ }
+ }
+
if (ifp == NULL) {
if (uj)
vty_out(vty, "{}\n");
@@ -2494,6 +2506,17 @@ DEFPY (show_interface_name_vrf_all,
vty_out(vty, "%% Can't find interface %s\n", ifname);
return CMD_WARNING;
}
+ if (count > 1) {
+ if (uj) {
+ vty_out(vty, "{}\n");
+ } else {
+ vty_out(vty,
+ "%% There are multiple interfaces with name %s\n",
+ ifname);
+ vty_out(vty, "%% You must specify the VRF name\n");
+ }
+ return CMD_WARNING;
+ }
if (uj)
json = json_object_new_object();
diff --git a/zebra/kernel_netlink.h b/zebra/kernel_netlink.h
index 37c76b9e5..cf8b8c785 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/subdir.am b/zebra/subdir.am
index c3d8a73aa..f0cc6ce71 100644
--- a/zebra/subdir.am
+++ b/zebra/subdir.am
@@ -116,6 +116,7 @@ zebra_zebra_SOURCES = \
zebra/zebra_routemap.c \
zebra/zebra_routemap_nb.c \
zebra/zebra_routemap_nb_config.c \
+ zebra/zebra_script.c \
zebra/zebra_srte.c \
zebra/zebra_vrf.c \
zebra/zebra_vty.c \
@@ -185,6 +186,7 @@ noinst_HEADERS += \
zebra/zebra_routemap.h \
zebra/zebra_routemap_nb.h \
zebra/zebra_router.h \
+ zebra/zebra_script.h \
zebra/zebra_srte.h \
zebra/zebra_vrf.h \
zebra/zebra_vxlan.h \
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index 2e9b0b6ea..61bd1417d 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 ab06ea643..9e9844390 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 d5e043eea..4006e1fed 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 472e53b73..c1bb19d4e 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 e03cf9db0..3f7e6256f 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 853af7c4b..af6832092 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_netns_notify.c b/zebra/zebra_netns_notify.c
index 61f97ce6a..0d260ad63 100644
--- a/zebra/zebra_netns_notify.c
+++ b/zebra/zebra_netns_notify.c
@@ -66,6 +66,18 @@ static int zebra_ns_continue_read(struct zebra_netns_info *zns_info,
int stop_retry);
static int zebra_ns_notify_read(struct thread *t);
+static struct vrf *vrf_handler_create(struct vty *vty, const char *vrfname)
+{
+ if (strlen(vrfname) > VRF_NAMSIZ) {
+ flog_warn(EC_LIB_VRF_LENGTH,
+ "%% VRF name %s invalid: length exceeds %d bytes",
+ vrfname, VRF_NAMSIZ);
+ return NULL;
+ }
+
+ return vrf_get(VRF_UNKNOWN, vrfname);
+}
+
static void zebra_ns_notify_create_context_from_entry_name(const char *name)
{
char *netnspath = ns_netns_pathname(NULL, name);
@@ -91,7 +103,8 @@ static void zebra_ns_notify_create_context_from_entry_name(const char *name)
vrf->name, netnspath);
return;
}
- if (vrf_handler_create(NULL, name, &vrf) != CMD_SUCCESS) {
+ vrf = vrf_handler_create(NULL, name);
+ if (!vrf) {
flog_warn(EC_ZEBRA_NS_VRF_CREATION_FAILED,
"NS notify : failed to create VRF %s", name);
ns_map_nsid_with_external(ns_id, false);
@@ -108,10 +121,9 @@ static void zebra_ns_notify_create_context_from_entry_name(const char *name)
}
frr_with_privs(&zserv_privs) {
- ret = vrf_netns_handler_create(NULL, vrf, netnspath,
- ns_id_external,
- ns_id,
- ns_id_relative);
+ ret = zebra_vrf_netns_handler_create(NULL, vrf, netnspath,
+ ns_id_external, ns_id,
+ ns_id_relative);
}
if (ret != CMD_SUCCESS) {
flog_warn(EC_ZEBRA_NS_VRF_CREATION_FAILED,
@@ -249,8 +261,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 +371,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_ptm.c b/zebra/zebra_ptm.c
index e17465b11..ec68f585e 100644
--- a/zebra/zebra_ptm.c
+++ b/zebra/zebra_ptm.c
@@ -609,7 +609,17 @@ static int zebra_ptm_handle_msg_cb(void *arg, void *in_ctxt)
}
if (strcmp(ZEBRA_PTM_INVALID_PORT_NAME, port_str)) {
- ifp = if_lookup_by_name_all_vrf(port_str);
+ struct vrf *vrf;
+ int count = 0;
+
+ RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
+ ifp = if_lookup_by_name_vrf(ifname, vrf);
+ if (ifp) {
+ count++;
+ if (!vrf_is_backend_netns())
+ break;
+ }
+ }
if (!ifp) {
flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE,
@@ -617,6 +627,12 @@ static int zebra_ptm_handle_msg_cb(void *arg, void *in_ctxt)
__func__, port_str);
return -1;
}
+ if (count > 1) {
+ flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE,
+ "%s: multiple interface with name %s",
+ __func__, port_str);
+ return -1;
+ }
}
ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_CBL_STR, cbl_str);
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 84c78a369..42fa927d9 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -39,6 +39,7 @@
#include "nexthop_group_private.h"
#include "frr_pthread.h"
#include "printfrr.h"
+#include "frrscript.h"
#include "zebra/zebra_router.h"
#include "zebra/connected.h"
@@ -57,6 +58,7 @@
#include "zebra/zapi_msg.h"
#include "zebra/zebra_dplane.h"
#include "zebra/zebra_evpn_mh.h"
+#include "zebra/zebra_script.h"
DEFINE_MGROUP(ZEBRA, "zebra");
@@ -4135,7 +4137,31 @@ static int rib_process_dplane_results(struct thread *thread)
continue;
}
+#ifdef HAVE_SCRIPTING
+ char *script_name = frrscript_names_get_script_name(
+ ZEBRA_ON_RIB_PROCESS_HOOK_CALL);
+
+ int ret = 1;
+ struct frrscript *fs;
+
+ if (script_name) {
+ fs = frrscript_new(script_name);
+ if (fs)
+ ret = frrscript_load(
+ fs, ZEBRA_ON_RIB_PROCESS_HOOK_CALL,
+ NULL);
+ }
+#endif /* HAVE_SCRIPTING */
+
while (ctx) {
+
+#ifdef HAVE_SCRIPTING
+ if (ret == 0)
+ frrscript_call(fs,
+ ZEBRA_ON_RIB_PROCESS_HOOK_CALL,
+ ("ctx", ctx));
+#endif /* HAVE_SCRIPTING */
+
switch (dplane_ctx_get_op(ctx)) {
case DPLANE_OP_ROUTE_INSTALL:
case DPLANE_OP_ROUTE_UPDATE:
diff --git a/zebra/zebra_router.c b/zebra/zebra_router.c
index d930f5986..a80c57385 100644
--- a/zebra/zebra_router.c
+++ b/zebra/zebra_router.c
@@ -30,6 +30,7 @@
#include "zebra_mlag.h"
#include "zebra_nhg.h"
#include "debug.h"
+#include "zebra_script.h"
DEFINE_MTYPE_STATIC(ZEBRA, RIB_TABLE_INFO, "RIB table info");
DEFINE_MTYPE_STATIC(ZEBRA, ZEBRA_RT_TABLE, "Zebra VRF table");
@@ -255,6 +256,10 @@ void zebra_router_terminate(void)
hash_free(zrouter.ipset_entry_hash);
hash_clean(zrouter.iptable_hash, zebra_pbr_iptable_free);
hash_free(zrouter.iptable_hash);
+
+#ifdef HAVE_SCRIPTING
+ zebra_script_destroy();
+#endif
}
bool zebra_router_notify_on_ack(void)
@@ -296,4 +301,8 @@ void zebra_router_init(bool asic_offload, bool notify_on_ack)
zrouter.asic_offloaded = asic_offload;
zrouter.notify_on_ack = notify_on_ack;
+
+#ifdef HAVE_SCRIPTING
+ zebra_script_init();
+#endif
}
diff --git a/zebra/zebra_script.c b/zebra/zebra_script.c
new file mode 100644
index 000000000..0e19376ab
--- /dev/null
+++ b/zebra/zebra_script.c
@@ -0,0 +1,420 @@
+/*
+ * frrscript encoders and decoders for data structures in Zebra
+ * Copyright (C) 2021 Donald Lee
+ *
+ * This program is free software; you can redistribute it 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "zebra_script.h"
+
+#ifdef HAVE_SCRIPTING
+
+void zebra_script_init(void)
+{
+ frrscript_names_add_function_name(ZEBRA_ON_RIB_PROCESS_HOOK_CALL);
+}
+
+void zebra_script_destroy(void)
+{
+ frrscript_names_destroy();
+}
+
+void lua_pushnh_grp(lua_State *L, const struct nh_grp *nh_grp)
+{
+ lua_newtable(L);
+ lua_pushinteger(L, nh_grp->id);
+ lua_setfield(L, -2, "id");
+ lua_pushinteger(L, nh_grp->weight);
+ lua_setfield(L, -2, "weight");
+}
+
+void lua_pushzebra_dplane_ctx(lua_State *L, const struct zebra_dplane_ctx *ctx)
+{
+
+ lua_newtable(L);
+ lua_pushinteger(L, dplane_ctx_get_op(ctx));
+ lua_setfield(L, -2, "zd_op");
+ lua_pushinteger(L, dplane_ctx_get_status(ctx));
+ lua_setfield(L, -2, "zd_status");
+ lua_pushinteger(L, dplane_ctx_get_provider(ctx));
+ lua_setfield(L, -2, "zd_provider");
+ lua_pushinteger(L, dplane_ctx_get_vrf(ctx));
+ lua_setfield(L, -2, "zd_vrf_id");
+ lua_pushinteger(L, dplane_ctx_get_table(ctx));
+ lua_setfield(L, -2, "zd_table_id");
+ lua_pushstring(L, dplane_ctx_get_ifname(ctx));
+ lua_setfield(L, -2, "zd_ifname");
+ lua_pushinteger(L, dplane_ctx_get_ifindex(ctx));
+ lua_setfield(L, -2, "zd_ifindex");
+
+ switch (dplane_ctx_get_op(ctx)) {
+ case DPLANE_OP_ROUTE_INSTALL:
+ case DPLANE_OP_ROUTE_UPDATE:
+ case DPLANE_OP_ROUTE_DELETE:
+ case DPLANE_OP_ROUTE_NOTIFY:
+ case DPLANE_OP_NH_INSTALL:
+ case DPLANE_OP_NH_UPDATE:
+ case DPLANE_OP_NH_DELETE:
+ /* rinfo */
+ lua_newtable(L);
+ {
+ lua_pushprefix(L, dplane_ctx_get_dest(ctx));
+ lua_setfield(L, -2, "zd_dest");
+ const struct prefix *src_pfx = dplane_ctx_get_src(ctx);
+
+ if (src_pfx) {
+ lua_pushprefix(L, src_pfx);
+ lua_setfield(L, -2, "zd_src");
+ }
+ lua_pushinteger(L, dplane_ctx_get_afi(ctx));
+ lua_setfield(L, -2, "zd_afi");
+ lua_pushinteger(L, dplane_ctx_get_safi(ctx));
+ lua_setfield(L, -2, "zd_safi");
+ lua_pushinteger(L, dplane_ctx_get_type(ctx));
+ lua_setfield(L, -2, "zd_type");
+ lua_pushinteger(L, dplane_ctx_get_old_type(ctx));
+ lua_setfield(L, -2, "zd_old_type");
+ lua_pushinteger(L, dplane_ctx_get_tag(ctx));
+ lua_setfield(L, -2, "zd_tag");
+ lua_pushinteger(L, dplane_ctx_get_old_tag(ctx));
+ lua_setfield(L, -2, "zd_old_tag");
+ lua_pushinteger(L, dplane_ctx_get_metric(ctx));
+ lua_setfield(L, -2, "zd_metric");
+ lua_pushinteger(L, dplane_ctx_get_old_metric(ctx));
+ lua_setfield(L, -2, "zd_old_metric");
+ lua_pushinteger(L, dplane_ctx_get_instance(ctx));
+ lua_setfield(L, -2, "zd_instance");
+ lua_pushinteger(L, dplane_ctx_get_old_instance(ctx));
+ lua_setfield(L, -2, "zd_old_instance");
+ lua_pushinteger(L, dplane_ctx_get_distance(ctx));
+ lua_setfield(L, -2, "zd_distance");
+ lua_pushinteger(L, dplane_ctx_get_old_distance(ctx));
+ lua_setfield(L, -2, "zd_old_distance");
+ lua_pushinteger(L, dplane_ctx_get_mtu(ctx));
+ lua_setfield(L, -2, "zd_mtu");
+ lua_pushinteger(L, dplane_ctx_get_nh_mtu(ctx));
+ lua_setfield(L, -2, "zd_nexthop_mtu");
+ /* nhe */
+ lua_newtable(L);
+ {
+ lua_pushinteger(L, dplane_ctx_get_nhe_id(ctx));
+ lua_setfield(L, -2, "id");
+ lua_pushinteger(L,
+ dplane_ctx_get_old_nhe_id(ctx));
+ lua_setfield(L, -2, "old_id");
+ lua_pushinteger(L, dplane_ctx_get_nhe_afi(ctx));
+ lua_setfield(L, -2, "afi");
+ lua_pushinteger(L,
+ dplane_ctx_get_nhe_vrf_id(ctx));
+ lua_setfield(L, -2, "vrf_id");
+ lua_pushinteger(L,
+ dplane_ctx_get_nhe_type(ctx));
+ lua_setfield(L, -2, "type");
+ lua_pushnexthop_group(
+ L, dplane_ctx_get_nhe_ng(ctx));
+ lua_setfield(L, -2, "ng");
+ lua_pushnh_grp(L,
+ dplane_ctx_get_nhe_nh_grp(ctx));
+ lua_setfield(L, -2, "nh_grp");
+ lua_pushinteger(
+ L,
+ dplane_ctx_get_nhe_nh_grp_count(ctx));
+ lua_setfield(L, -2, "nh_grp_count");
+ }
+ lua_setfield(L, -2, "nhe");
+ lua_pushinteger(L, dplane_ctx_get_nhg_id(ctx));
+ lua_setfield(L, -2, "zd_nhg_id");
+ lua_pushnexthop_group(L, dplane_ctx_get_ng(ctx));
+ lua_setfield(L, -2, "zd_ng");
+ lua_pushnexthop_group(L, dplane_ctx_get_backup_ng(ctx));
+ lua_setfield(L, -2, "backup_ng");
+ lua_pushnexthop_group(L, dplane_ctx_get_old_ng(ctx));
+ lua_setfield(L, -2, "zd_old_ng");
+ lua_pushnexthop_group(
+ L, dplane_ctx_get_old_backup_ng(ctx));
+ lua_setfield(L, -2, "old_backup_ng");
+ }
+ lua_setfield(L, -2, "rinfo");
+ break;
+ case DPLANE_OP_LSP_INSTALL:
+ case DPLANE_OP_LSP_UPDATE:
+ case DPLANE_OP_LSP_DELETE:
+ case DPLANE_OP_LSP_NOTIFY:
+ lua_pushinteger(L, (int)dplane_ctx_get_in_label(ctx));
+ lua_setfield(L, -2, "label");
+ break;
+ case DPLANE_OP_PW_INSTALL:
+ case DPLANE_OP_PW_UNINSTALL:
+ /* pw*/
+ lua_newtable(L);
+ {
+ lua_pushinteger(L, dplane_ctx_get_pw_type(ctx));
+ lua_setfield(L, -2, "type");
+ lua_pushinteger(L, dplane_ctx_get_pw_af(ctx));
+ lua_setfield(L, -2, "af");
+ lua_pushinteger(L, dplane_ctx_get_pw_status(ctx));
+ lua_setfield(L, -2, "status");
+ lua_pushinteger(L, dplane_ctx_get_pw_flags(ctx));
+ lua_setfield(L, -2, "flags");
+ lua_pushinteger(L, dplane_ctx_get_pw_local_label(ctx));
+ lua_setfield(L, -2, "local_label");
+ lua_pushinteger(L, dplane_ctx_get_pw_remote_label(ctx));
+ lua_setfield(L, -2, "remote_label");
+ }
+ lua_setfield(L, -2, "pw");
+ break;
+ case DPLANE_OP_SYS_ROUTE_ADD:
+ case DPLANE_OP_SYS_ROUTE_DELETE:
+ /* nothing to encode */
+ break;
+ case DPLANE_OP_MAC_INSTALL:
+ case DPLANE_OP_MAC_DELETE:
+ /* macinfo */
+ lua_newtable(L);
+ {
+ lua_pushinteger(L, dplane_ctx_mac_get_vlan(ctx));
+ lua_setfield(L, -2, "vid");
+ lua_pushinteger(L, dplane_ctx_mac_get_br_ifindex(ctx));
+ lua_setfield(L, -2, "br_ifindex");
+ lua_pushethaddr(L, dplane_ctx_mac_get_addr(ctx));
+ lua_setfield(L, -2, "mac");
+ lua_pushinaddr(L, dplane_ctx_mac_get_vtep_ip(ctx));
+ lua_setfield(L, -2, "vtep_ip");
+ lua_pushinteger(L, dplane_ctx_mac_is_sticky(ctx));
+ lua_setfield(L, -2, "is_sticky");
+ lua_pushinteger(L, dplane_ctx_mac_get_nhg_id(ctx));
+ lua_setfield(L, -2, "nhg_id");
+ lua_pushinteger(L,
+ dplane_ctx_mac_get_update_flags(ctx));
+ lua_setfield(L, -2, "update_flags");
+ }
+ lua_setfield(L, -2, "macinfo");
+ break;
+ case DPLANE_OP_RULE_ADD:
+ case DPLANE_OP_RULE_DELETE:
+ case DPLANE_OP_RULE_UPDATE:
+ /* rule */
+ lua_newtable(L);
+ {
+ lua_pushinteger(L, dplane_ctx_rule_get_sock(ctx));
+ lua_setfield(L, -2, "sock");
+ lua_pushinteger(L, dplane_ctx_rule_get_unique(ctx));
+ lua_setfield(L, -2, "unique");
+ lua_pushinteger(L, dplane_ctx_rule_get_seq(ctx));
+ lua_setfield(L, -2, "seq");
+ lua_pushstring(L, dplane_ctx_rule_get_ifname(ctx));
+ lua_setfield(L, -2, "ifname");
+ lua_pushinteger(L, dplane_ctx_rule_get_priority(ctx));
+ lua_setfield(L, -2, "priority");
+ lua_pushinteger(L,
+ dplane_ctx_rule_get_old_priority(ctx));
+ lua_setfield(L, -2, "old_priority");
+ lua_pushinteger(L, dplane_ctx_rule_get_table(ctx));
+ lua_setfield(L, -2, "table");
+ lua_pushinteger(L, dplane_ctx_rule_get_old_table(ctx));
+ lua_setfield(L, -2, "old_table");
+ lua_pushinteger(L, dplane_ctx_rule_get_filter_bm(ctx));
+ lua_setfield(L, -2, "filter_bm");
+ lua_pushinteger(L,
+ dplane_ctx_rule_get_old_filter_bm(ctx));
+ lua_setfield(L, -2, "old_filter_bm");
+ lua_pushinteger(L, dplane_ctx_rule_get_fwmark(ctx));
+ lua_setfield(L, -2, "fwmark");
+ lua_pushinteger(L, dplane_ctx_rule_get_old_fwmark(ctx));
+ lua_setfield(L, -2, "old_fwmark");
+ lua_pushinteger(L, dplane_ctx_rule_get_dsfield(ctx));
+ lua_setfield(L, -2, "dsfield");
+ lua_pushinteger(L,
+ dplane_ctx_rule_get_old_dsfield(ctx));
+ lua_setfield(L, -2, "old_dsfield");
+ lua_pushinteger(L, dplane_ctx_rule_get_ipproto(ctx));
+ lua_setfield(L, -2, "ip_proto");
+ lua_pushinteger(L,
+ dplane_ctx_rule_get_old_ipproto(ctx));
+ lua_setfield(L, -2, "old_ip_proto");
+ lua_pushprefix(L, dplane_ctx_rule_get_src_ip(ctx));
+ lua_setfield(L, -2, "src_ip");
+ lua_pushprefix(L, dplane_ctx_rule_get_old_src_ip(ctx));
+ lua_setfield(L, -2, "old_src_ip");
+ lua_pushprefix(L, dplane_ctx_rule_get_dst_ip(ctx));
+ lua_setfield(L, -2, "dst_ip");
+ lua_pushprefix(L, dplane_ctx_rule_get_old_dst_ip(ctx));
+ lua_setfield(L, -2, "old_dst_ip");
+ }
+ lua_setfield(L, -2, "rule");
+ break;
+ case DPLANE_OP_IPTABLE_ADD:
+ case DPLANE_OP_IPTABLE_DELETE: {
+ struct zebra_pbr_iptable iptable;
+
+ dplane_ctx_get_pbr_iptable(ctx, &iptable);
+ /* iptable */
+ lua_newtable(L);
+ {
+ lua_pushinteger(L, iptable.sock);
+ lua_setfield(L, -2, "sock");
+ lua_pushinteger(L, iptable.vrf_id);
+ lua_setfield(L, -2, "vrf_id");
+ lua_pushinteger(L, iptable.unique);
+ lua_setfield(L, -2, "unique");
+ lua_pushinteger(L, iptable.type);
+ lua_setfield(L, -2, "type");
+ lua_pushinteger(L, iptable.filter_bm);
+ lua_setfield(L, -2, "filter_bm");
+ lua_pushinteger(L, iptable.fwmark);
+ lua_setfield(L, -2, "fwmark");
+ lua_pushinteger(L, iptable.action);
+ lua_setfield(L, -2, "action");
+ lua_pushinteger(L, iptable.pkt_len_min);
+ lua_setfield(L, -2, "pkt_len_min");
+ lua_pushinteger(L, iptable.pkt_len_max);
+ lua_setfield(L, -2, "pkt_len_max");
+ lua_pushinteger(L, iptable.tcp_flags);
+ lua_setfield(L, -2, "tcp_flags");
+ lua_pushinteger(L, iptable.dscp_value);
+ lua_setfield(L, -2, "dscp_value");
+ lua_pushinteger(L, iptable.fragment);
+ lua_setfield(L, -2, "fragment");
+ lua_pushinteger(L, iptable.protocol);
+ lua_setfield(L, -2, "protocol");
+ lua_pushinteger(L, iptable.nb_interface);
+ lua_setfield(L, -2, "nb_interface");
+ lua_pushinteger(L, iptable.flow_label);
+ lua_setfield(L, -2, "flow_label");
+ lua_pushinteger(L, iptable.family);
+ lua_setfield(L, -2, "family");
+ lua_pushstring(L, iptable.ipset_name);
+ lua_setfield(L, -2, "ipset_name");
+ }
+ lua_setfield(L, -2, "iptable");
+ break;
+ }
+ case DPLANE_OP_IPSET_ADD:
+ case DPLANE_OP_IPSET_DELETE:
+ case DPLANE_OP_IPSET_ENTRY_ADD:
+ case DPLANE_OP_IPSET_ENTRY_DELETE: {
+ struct zebra_pbr_ipset ipset;
+
+ dplane_ctx_get_pbr_ipset(ctx, &ipset);
+ /* ipset */
+ lua_newtable(L);
+ {
+ lua_pushinteger(L, ipset.sock);
+ lua_setfield(L, -2, "sock");
+ lua_pushinteger(L, ipset.vrf_id);
+ lua_setfield(L, -2, "vrf_id");
+ lua_pushinteger(L, ipset.unique);
+ lua_setfield(L, -2, "unique");
+ lua_pushinteger(L, ipset.type);
+ lua_setfield(L, -2, "type");
+ lua_pushinteger(L, ipset.family);
+ lua_setfield(L, -2, "family");
+ lua_pushstring(L, ipset.ipset_name);
+ lua_setfield(L, -2, "ipset_name");
+ }
+ lua_setfield(L, -2, "ipset");
+ break;
+ }
+ case DPLANE_OP_ADDR_INSTALL:
+ case DPLANE_OP_ADDR_UNINSTALL:
+ case DPLANE_OP_INTF_ADDR_ADD:
+ case DPLANE_OP_INTF_ADDR_DEL:
+ break;
+ case DPLANE_OP_NEIGH_INSTALL:
+ case DPLANE_OP_NEIGH_UPDATE:
+ case DPLANE_OP_NEIGH_DELETE:
+ case DPLANE_OP_NEIGH_DISCOVER:
+ case DPLANE_OP_NEIGH_IP_INSTALL:
+ case DPLANE_OP_NEIGH_IP_DELETE:
+ /* neigh */
+ lua_newtable(L);
+ {
+ lua_pushipaddr(L, dplane_ctx_neigh_get_ipaddr(ctx));
+ lua_setfield(L, -2, "ip_addr");
+ /* link */
+ lua_newtable(L);
+ {
+ lua_pushethaddr(L,
+ dplane_ctx_neigh_get_mac(ctx));
+ lua_setfield(L, -2, "mac");
+ lua_pushipaddr(
+ L, dplane_ctx_neigh_get_link_ip(ctx));
+ lua_setfield(L, -2, "ip_addr");
+ }
+ lua_setfield(L, -2, "link");
+ lua_pushinteger(L, dplane_ctx_neigh_get_flags(ctx));
+ lua_setfield(L, -2, "flags");
+ lua_pushinteger(L, dplane_ctx_neigh_get_state(ctx));
+ lua_setfield(L, -2, "state");
+ lua_pushinteger(L,
+ dplane_ctx_neigh_get_update_flags(ctx));
+ lua_setfield(L, -2, "update_flags");
+ }
+ lua_setfield(L, -2, "neigh");
+ break;
+ case DPLANE_OP_VTEP_ADD:
+ case DPLANE_OP_VTEP_DELETE:
+ break;
+ case DPLANE_OP_BR_PORT_UPDATE:
+ /* br_port */
+ lua_newtable(L);
+ {
+ lua_pushinteger(
+ L, dplane_ctx_get_br_port_sph_filter_cnt(ctx));
+ lua_setfield(L, -2, "sph_filter_cnt");
+ lua_pushinteger(L, dplane_ctx_get_br_port_flags(ctx));
+ lua_setfield(L, -2, "flags");
+ lua_pushinteger(
+ L, dplane_ctx_get_br_port_backup_nhg_id(ctx));
+ lua_setfield(L, -2, "backup_nhg_id");
+ }
+ lua_setfield(L, -2, "br_port");
+ break;
+ case DPLANE_OP_NEIGH_TABLE_UPDATE:
+ /* neightable */
+ lua_newtable(L);
+ {
+ lua_pushinteger(L,
+ dplane_ctx_neightable_get_family(ctx));
+ lua_setfield(L, -2, "family");
+ lua_pushinteger(
+ L, dplane_ctx_neightable_get_app_probes(ctx));
+ lua_setfield(L, -2, "app_probes");
+ lua_pushinteger(
+ L, dplane_ctx_neightable_get_mcast_probes(ctx));
+ lua_setfield(L, -2, "ucast_probes");
+ lua_pushinteger(
+ L, dplane_ctx_neightable_get_ucast_probes(ctx));
+ lua_setfield(L, -2, "mcast_probes");
+ }
+ lua_setfield(L, -2, "neightable");
+ break;
+ case DPLANE_OP_GRE_SET:
+ /* gre */
+ lua_newtable(L);
+ {
+ lua_pushinteger(L,
+ dplane_ctx_gre_get_link_ifindex(ctx));
+ lua_setfield(L, -2, "link_ifindex");
+ lua_pushinteger(L, dplane_ctx_gre_get_mtu(ctx));
+ lua_setfield(L, -2, "mtu");
+ }
+ lua_setfield(L, -2, "gre");
+ case DPLANE_OP_NONE:
+ break;
+ } /* Dispatch by op code */
+}
+
+#endif /* HAVE_SCRIPTING */
diff --git a/zebra/zebra_script.h b/zebra/zebra_script.h
new file mode 100644
index 000000000..5eb59753c
--- /dev/null
+++ b/zebra/zebra_script.h
@@ -0,0 +1,41 @@
+/*
+ * frrscript encoders and decoders for data structures in Zebra
+ * Copyright (C) 2021 Donald Lee
+ *
+ * This program is free software; you can redistribute it 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _ZEBRA_SCRIPT_H
+#define _ZEBRA_SCRIPT_H
+
+#include "zebra.h"
+#include "zebra/zebra_dplane.h"
+#include "zebra/zebra_pbr.h"
+
+#ifdef HAVE_SCRIPTING
+
+#include "frrlua.h"
+
+void zebra_script_init(void);
+
+void zebra_script_destroy(void);
+
+void lua_pushnh_grp(lua_State *L, const struct nh_grp *nh_grp);
+
+void lua_pushzebra_dplane_ctx(lua_State *L, const struct zebra_dplane_ctx *ctx);
+
+#endif /* HAVE_SCRIPTING */
+
+#endif /* _ZEBRA_SCRIPT_H */
diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c
index 4b00f3415..d051ed67a 100644
--- a/zebra/zebra_vrf.c
+++ b/zebra/zebra_vrf.c
@@ -20,6 +20,9 @@
*/
#include <zebra.h>
+/* for basename */
+#include <libgen.h>
+
#include "log.h"
#include "linklist.h"
#include "command.h"
@@ -565,10 +568,8 @@ DEFPY (vrf_netns,
return CMD_WARNING_CONFIG_FAILED;
frr_with_privs(&zserv_privs) {
- ret = vrf_netns_handler_create(vty, vrf, pathname,
- NS_UNKNOWN,
- NS_UNKNOWN,
- NS_UNKNOWN);
+ ret = zebra_vrf_netns_handler_create(
+ vty, vrf, pathname, NS_UNKNOWN, NS_UNKNOWN, NS_UNKNOWN);
}
return ret;
@@ -607,6 +608,97 @@ DEFUN (no_vrf_netns,
return CMD_SUCCESS;
}
+/* if ns_id is different and not VRF_UNKNOWN,
+ * then update vrf identifier, and enable VRF
+ */
+static void vrf_update_vrf_id(ns_id_t ns_id, void *opaqueptr)
+{
+ ns_id_t vrf_id = (vrf_id_t)ns_id;
+ vrf_id_t old_vrf_id;
+ struct vrf *vrf = (struct vrf *)opaqueptr;
+
+ if (!vrf)
+ return;
+ old_vrf_id = vrf->vrf_id;
+ if (vrf_id == vrf->vrf_id)
+ return;
+ if (vrf->vrf_id != VRF_UNKNOWN)
+ RB_REMOVE(vrf_id_head, &vrfs_by_id, vrf);
+ vrf->vrf_id = vrf_id;
+ RB_INSERT(vrf_id_head, &vrfs_by_id, vrf);
+ if (old_vrf_id == VRF_UNKNOWN)
+ vrf_enable(vrf);
+}
+
+int zebra_vrf_netns_handler_create(struct vty *vty, struct vrf *vrf,
+ char *pathname, ns_id_t ns_id,
+ ns_id_t internal_ns_id,
+ ns_id_t rel_def_ns_id)
+{
+ struct ns *ns = NULL;
+
+ if (!vrf)
+ return CMD_WARNING_CONFIG_FAILED;
+ if (vrf->vrf_id != VRF_UNKNOWN && vrf->ns_ctxt == NULL) {
+ if (vty)
+ vty_out(vty,
+ "VRF %u is already configured with VRF %s\n",
+ vrf->vrf_id, vrf->name);
+ else
+ zlog_info("VRF %u is already configured with VRF %s",
+ vrf->vrf_id, vrf->name);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ if (vrf->ns_ctxt != NULL) {
+ ns = (struct ns *)vrf->ns_ctxt;
+ if (!strcmp(ns->name, pathname)) {
+ if (vty)
+ vty_out(vty,
+ "VRF %u already configured with NETNS %s\n",
+ vrf->vrf_id, ns->name);
+ else
+ zlog_info(
+ "VRF %u already configured with NETNS %s",
+ vrf->vrf_id, ns->name);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ }
+ ns = ns_lookup_name(pathname);
+ if (ns && ns->vrf_ctxt) {
+ struct vrf *vrf2 = (struct vrf *)ns->vrf_ctxt;
+
+ if (vrf2 == vrf)
+ return CMD_SUCCESS;
+ if (vty)
+ vty_out(vty,
+ "NS %s is already configured with VRF %u(%s)\n",
+ ns->name, vrf2->vrf_id, vrf2->name);
+ else
+ zlog_info("NS %s is already configured with VRF %u(%s)",
+ ns->name, vrf2->vrf_id, vrf2->name);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ ns = ns_get_created(ns, pathname, ns_id);
+ ns->internal_ns_id = internal_ns_id;
+ ns->relative_default_ns = rel_def_ns_id;
+ ns->vrf_ctxt = (void *)vrf;
+ vrf->ns_ctxt = (void *)ns;
+ /* update VRF netns NAME */
+ strlcpy(vrf->data.l.netns_name, basename(pathname), NS_NAMSIZ);
+
+ if (!ns_enable(ns, vrf_update_vrf_id)) {
+ if (vty)
+ vty_out(vty, "Can not associate NS %u with NETNS %s\n",
+ ns->ns_id, ns->name);
+ else
+ zlog_info("Can not associate NS %u with NETNS %s",
+ ns->ns_id, ns->name);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ return CMD_SUCCESS;
+}
+
/* Zebra VRF initialization. */
void zebra_vrf_init(void)
{
diff --git a/zebra/zebra_vrf.h b/zebra/zebra_vrf.h
index 3def27b79..a24a008b7 100644
--- a/zebra/zebra_vrf.h
+++ b/zebra/zebra_vrf.h
@@ -260,6 +260,14 @@ extern struct zebra_vrf *zebra_vrf_lookup_by_name(const char *);
extern struct zebra_vrf *zebra_vrf_alloc(struct vrf *vrf);
extern struct route_table *zebra_vrf_table(afi_t, safi_t, vrf_id_t);
+/*
+ * API to associate a VRF with a NETNS.
+ * Called either from vty or through discovery.
+ */
+extern int zebra_vrf_netns_handler_create(struct vty *vty, struct vrf *vrf,
+ char *pathname, ns_id_t ext_ns_id,
+ ns_id_t ns_id, ns_id_t rel_def_ns_id);
+
extern void zebra_vrf_init(void);
extern void zebra_rtable_node_cleanup(struct route_table *table,
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index 5b79de969..85e1a4b2b 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -60,6 +60,7 @@
#include "zebra/zebra_nb.h"
#include "zebra/kernel_netlink.h"
#include "zebra/table_manager.h"
+#include "zebra/zebra_script.h"
extern int allow_delete;
@@ -449,6 +450,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 +462,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:
@@ -4318,6 +4324,30 @@ DEFUN(ip_table_range, ip_table_range_cmd,
return table_manager_range(vty, true, zvrf, argv[3]->arg, argv[4]->arg);
}
+#ifdef HAVE_SCRIPTING
+
+DEFUN(zebra_on_rib_process_script, zebra_on_rib_process_script_cmd,
+ "zebra on-rib-process script SCRIPT",
+ ZEBRA_STR
+ "on_rib_process_dplane_results hook call\n"
+ "Set a script\n"
+ "Script name (same as filename in /etc/frr/scripts/, without .lua)\n")
+{
+
+ if (frrscript_names_set_script_name(ZEBRA_ON_RIB_PROCESS_HOOK_CALL,
+ argv[3]->arg)
+ == 0) {
+ vty_out(vty, "Successfully added script %s for hook call %s\n",
+ argv[3]->arg, ZEBRA_ON_RIB_PROCESS_HOOK_CALL);
+ } else {
+ vty_out(vty, "Failed to add script %s for hook call %s\n",
+ argv[3]->arg, ZEBRA_ON_RIB_PROCESS_HOOK_CALL);
+ }
+ return CMD_SUCCESS;
+}
+
+#endif /* HAVE_SCRIPTING */
+
/* IP node for static routes. */
static int zebra_ip_config(struct vty *vty);
static struct cmd_node ip_node = {
@@ -4474,5 +4504,9 @@ void zebra_vty_init(void)
install_element(CONFIG_NODE, &no_zebra_kernel_netlink_batch_tx_buf_cmd);
#endif /* HAVE_NETLINK */
+#ifdef HAVE_SCRIPTING
+ install_element(CONFIG_NODE, &zebra_on_rib_process_script_cmd);
+#endif /* HAVE_SCRIPTING */
+
install_element(VIEW_NODE, &zebra_show_routing_tables_summary_cmd);
}