summaryrefslogtreecommitdiff
path: root/zebra
diff options
context:
space:
mode:
Diffstat (limited to 'zebra')
-rw-r--r--zebra/.gitignore1
-rw-r--r--zebra/connected.c87
-rw-r--r--zebra/debug.c4
-rw-r--r--zebra/debug_nl.c1
-rw-r--r--zebra/dpdk/zebra_dplane_dpdk.c51
-rw-r--r--zebra/dplane_fpm_nl.c175
-rw-r--r--zebra/fpm_listener.c703
-rw-r--r--zebra/ge_netlink.c369
-rw-r--r--zebra/ge_netlink.h49
-rw-r--r--zebra/if_ioctl.c1
-rw-r--r--zebra/if_netlink.c1153
-rw-r--r--zebra/if_netlink.h11
-rw-r--r--zebra/if_sysctl.c2
-rw-r--r--zebra/interface.c2918
-rw-r--r--zebra/interface.h35
-rw-r--r--zebra/ioctl.c2
-rw-r--r--zebra/irdp_interface.c13
-rw-r--r--zebra/irdp_main.c39
-rw-r--r--zebra/kernel_netlink.c257
-rw-r--r--zebra/kernel_netlink.h32
-rw-r--r--zebra/kernel_socket.c30
-rw-r--r--zebra/label_manager.c256
-rw-r--r--zebra/label_manager.h17
-rw-r--r--zebra/main.c132
-rw-r--r--zebra/netconf_netlink.c3
-rw-r--r--zebra/redistribute.c147
-rw-r--r--zebra/rib.h53
-rw-r--r--zebra/router-id.c270
-rw-r--r--zebra/router-id.h2
-rw-r--r--zebra/rt.h5
-rw-r--r--zebra/rt_netlink.c405
-rw-r--r--zebra/rt_netlink.h4
-rw-r--r--zebra/rt_socket.c2
-rw-r--r--zebra/rtadv.c1291
-rw-r--r--zebra/rtadv.h25
-rw-r--r--zebra/rtread_sysctl.c2
-rw-r--r--zebra/rule_netlink.c34
-rw-r--r--zebra/subdir.am14
-rw-r--r--zebra/table_manager.c67
-rw-r--r--zebra/table_manager.h20
-rw-r--r--zebra/tc_netlink.c15
-rw-r--r--zebra/zapi_msg.c318
-rw-r--r--zebra/zapi_msg.h11
-rw-r--r--zebra/zebra_affinitymap.c90
-rw-r--r--zebra/zebra_cli.c2984
-rw-r--r--zebra/zebra_cli.h10
-rw-r--r--zebra/zebra_dplane.c1024
-rw-r--r--zebra/zebra_dplane.h162
-rw-r--r--zebra/zebra_evpn.c155
-rw-r--r--zebra/zebra_evpn_mac.c528
-rw-r--r--zebra/zebra_evpn_mh.c390
-rw-r--r--zebra/zebra_evpn_mh.h21
-rw-r--r--zebra/zebra_evpn_neigh.c19
-rw-r--r--zebra/zebra_fpm.c17
-rw-r--r--zebra/zebra_fpm_dt.c4
-rw-r--r--zebra/zebra_fpm_netlink.c22
-rw-r--r--zebra/zebra_gr.c15
-rw-r--r--zebra/zebra_l2.c44
-rw-r--r--zebra/zebra_l2.h23
-rw-r--r--zebra/zebra_mlag.c37
-rw-r--r--zebra/zebra_mpls.c278
-rw-r--r--zebra/zebra_mpls.h8
-rw-r--r--zebra/zebra_mpls_netlink.c4
-rw-r--r--zebra/zebra_mpls_openbsd.c160
-rw-r--r--zebra/zebra_mpls_vty.c21
-rw-r--r--zebra/zebra_nb.c524
-rw-r--r--zebra/zebra_nb.h228
-rw-r--r--zebra/zebra_nb_config.c2807
-rw-r--r--zebra/zebra_nb_state.c166
-rw-r--r--zebra/zebra_neigh.c13
-rw-r--r--zebra/zebra_neigh.h1
-rw-r--r--zebra/zebra_netns_id.c6
-rw-r--r--zebra/zebra_netns_notify.c1
-rw-r--r--zebra/zebra_nhg.c478
-rw-r--r--zebra/zebra_nhg.h13
-rw-r--r--zebra/zebra_ns.c52
-rw-r--r--zebra/zebra_ns.h7
-rw-r--r--zebra/zebra_opaque.c383
-rw-r--r--zebra/zebra_pbr.c79
-rw-r--r--zebra/zebra_pbr.h4
-rw-r--r--zebra/zebra_ptm.c77
-rw-r--r--zebra/zebra_ptm.h11
-rw-r--r--zebra/zebra_pw.c30
-rw-r--r--zebra/zebra_pw.h7
-rw-r--r--zebra/zebra_rib.c408
-rw-r--r--zebra/zebra_rnh.c67
-rw-r--r--zebra/zebra_routemap.c832
-rw-r--r--zebra/zebra_routemap.h38
-rw-r--r--zebra/zebra_routemap_nb_config.c2
-rw-r--r--zebra/zebra_router.c37
-rw-r--r--zebra/zebra_router.h39
-rw-r--r--zebra/zebra_script.c3
-rw-r--r--zebra/zebra_snmp.c11
-rw-r--r--zebra/zebra_srv6.c38
-rw-r--r--zebra/zebra_srv6.h7
-rw-r--r--zebra/zebra_srv6_vty.c89
-rw-r--r--zebra/zebra_tc.c23
-rw-r--r--zebra/zebra_tc.h3
-rw-r--r--zebra/zebra_trace.c2
-rw-r--r--zebra/zebra_vrf.c171
-rw-r--r--zebra/zebra_vrf.h7
-rw-r--r--zebra/zebra_vty.c503
-rw-r--r--zebra/zebra_vxlan.c260
-rw-r--r--zebra/zebra_vxlan.h6
-rw-r--r--zebra/zserv.c108
-rw-r--r--zebra/zserv.h12
106 files changed, 13764 insertions, 8831 deletions
diff --git a/zebra/.gitignore b/zebra/.gitignore
index 41a86e7d75..f10240db43 100644
--- a/zebra/.gitignore
+++ b/zebra/.gitignore
@@ -1,3 +1,4 @@
zebra
zebra.conf
client
+fpm_listener
diff --git a/zebra/connected.c b/zebra/connected.c
index ee0823f56f..404f892f6e 100644
--- a/zebra/connected.c
+++ b/zebra/connected.c
@@ -48,7 +48,7 @@ static void connected_withdraw(struct connected *ifc)
UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED)) {
- listnode_delete(ifc->ifp->connected, ifc);
+ if_connected_del(ifc->ifp->connected, ifc);
connected_free(&ifc);
}
}
@@ -65,7 +65,7 @@ static void connected_announce(struct interface *ifp, struct connected *ifc)
UNSET_FLAG(ifc->flags, ZEBRA_IFA_UNNUMBERED);
}
- listnode_add(ifp->connected, ifc);
+ if_connected_add_tail(ifp->connected, ifc);
/* Update interface address information to protocol daemon. */
if (ifc->address->family == AF_INET)
@@ -84,9 +84,8 @@ struct connected *connected_check(struct interface *ifp,
{
const struct prefix *p = pu.p;
struct connected *ifc;
- struct listnode *node;
- for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc))
+ frr_each (if_connected, ifp->connected, ifc)
if (prefix_same(ifc->address, p))
return ifc;
@@ -101,9 +100,8 @@ struct connected *connected_check_ptp(struct interface *ifp,
const struct prefix *p = pu.p;
const struct prefix *d = du.p;
struct connected *ifc;
- struct listnode *node;
- for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
+ frr_each (if_connected, ifp->connected, ifc) {
if (!prefix_same(ifc->address, p))
continue;
if (!CONNECTED_PEER(ifc) && !d)
@@ -182,7 +180,7 @@ static void connected_update(struct interface *ifp, struct connected *ifc)
void connected_up(struct interface *ifp, struct connected *ifc)
{
afi_t afi;
- struct prefix p;
+ struct prefix p, plocal;
struct nexthop nh = {
.type = NEXTHOP_TYPE_IFINDEX,
.ifindex = ifp->ifindex,
@@ -192,8 +190,8 @@ void connected_up(struct interface *ifp, struct connected *ifc)
uint32_t metric;
uint32_t flags = 0;
uint32_t count = 0;
- struct listnode *cnode;
struct connected *c;
+ bool install_local = true;
zvrf = ifp->vrf->info;
if (!zvrf) {
@@ -210,6 +208,7 @@ void connected_up(struct interface *ifp, struct connected *ifc)
UNSET_FLAG(ifc->conf, ZEBRA_IFC_DOWN);
prefix_copy(&p, CONNECTED_PREFIX(ifc));
+ prefix_copy(&plocal, ifc->address);
/* Apply mask to the network. */
apply_mask(&p);
@@ -224,6 +223,8 @@ void connected_up(struct interface *ifp, struct connected *ifc)
*/
if (prefix_ipv4_any((struct prefix_ipv4 *)&p))
return;
+
+ plocal.prefixlen = IPV4_MAX_BITLEN;
break;
case AFI_IP6:
#ifndef GNU_LINUX
@@ -231,6 +232,11 @@ void connected_up(struct interface *ifp, struct connected *ifc)
if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
return;
#endif
+
+ if (IN6_IS_ADDR_LINKLOCAL(&plocal.u.prefix6))
+ install_local = false;
+
+ plocal.prefixlen = IPV6_MAX_BITLEN;
break;
case AFI_UNSPEC:
case AFI_L2VPN:
@@ -262,7 +268,7 @@ void connected_up(struct interface *ifp, struct connected *ifc)
* for all the addresses on an interface that
* resolve to the same network and mask
*/
- for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) {
+ frr_each (if_connected, ifp->connected, c) {
struct prefix cp;
prefix_copy(&cp, CONNECTED_PREFIX(c));
@@ -276,13 +282,24 @@ void connected_up(struct interface *ifp, struct connected *ifc)
return;
}
- rib_add(afi, SAFI_UNICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT, 0,
- flags, &p, NULL, &nh, 0, zvrf->table_id, metric, 0, 0, 0,
- false);
+ if (!CHECK_FLAG(ifc->flags, ZEBRA_IFA_NOPREFIXROUTE)) {
+ rib_add(afi, SAFI_UNICAST, zvrf->vrf->vrf_id,
+ ZEBRA_ROUTE_CONNECT, 0, flags, &p, NULL, &nh, 0,
+ zvrf->table_id, metric, 0, 0, 0, false);
- rib_add(afi, SAFI_MULTICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT, 0,
- flags, &p, NULL, &nh, 0, zvrf->table_id, metric, 0, 0, 0,
- false);
+ rib_add(afi, SAFI_MULTICAST, zvrf->vrf->vrf_id,
+ ZEBRA_ROUTE_CONNECT, 0, flags, &p, NULL, &nh, 0,
+ zvrf->table_id, metric, 0, 0, 0, false);
+ }
+
+ if (install_local) {
+ rib_add(afi, SAFI_UNICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_LOCAL,
+ 0, flags, &plocal, NULL, &nh, 0, zvrf->table_id, 0, 0,
+ 0, 0, false);
+ rib_add(afi, SAFI_MULTICAST, zvrf->vrf->vrf_id,
+ ZEBRA_ROUTE_LOCAL, 0, flags, &plocal, NULL, &nh, 0,
+ zvrf->table_id, 0, 0, 0, 0, false);
+ }
/* Schedule LSP forwarding entries for processing, if appropriate. */
if (zvrf->vrf->vrf_id == VRF_DEFAULT) {
@@ -368,7 +385,7 @@ void connected_add_ipv4(struct interface *ifp, int flags,
void connected_down(struct interface *ifp, struct connected *ifc)
{
afi_t afi;
- struct prefix p;
+ struct prefix p, plocal;
struct nexthop nh = {
.type = NEXTHOP_TYPE_IFINDEX,
.ifindex = ifp->ifindex,
@@ -376,8 +393,8 @@ void connected_down(struct interface *ifp, struct connected *ifc)
};
struct zebra_vrf *zvrf;
uint32_t count = 0;
- struct listnode *cnode;
struct connected *c;
+ bool remove_local = true;
zvrf = ifp->vrf->info;
if (!zvrf) {
@@ -403,6 +420,7 @@ void connected_down(struct interface *ifp, struct connected *ifc)
}
prefix_copy(&p, CONNECTED_PREFIX(ifc));
+ prefix_copy(&plocal, ifc->address);
/* Apply mask to the network. */
apply_mask(&p);
@@ -417,10 +435,18 @@ void connected_down(struct interface *ifp, struct connected *ifc)
*/
if (prefix_ipv4_any((struct prefix_ipv4 *)&p))
return;
+
+ plocal.prefixlen = IPV4_MAX_BITLEN;
break;
case AFI_IP6:
if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
return;
+
+ plocal.prefixlen = IPV6_MAX_BITLEN;
+
+ if (IN6_IS_ADDR_LINKLOCAL(&plocal.u.prefix6))
+ remove_local = false;
+
break;
case AFI_UNSPEC:
case AFI_L2VPN:
@@ -439,7 +465,7 @@ void connected_down(struct interface *ifp, struct connected *ifc)
* allow the deletion when are removing the last
* one.
*/
- for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) {
+ frr_each (if_connected, ifp->connected, c) {
struct prefix cp;
prefix_copy(&cp, CONNECTED_PREFIX(c));
@@ -457,11 +483,25 @@ void connected_down(struct interface *ifp, struct connected *ifc)
* Same logic as for connected_up(): push the changes into the
* head.
*/
- rib_delete(afi, SAFI_UNICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT, 0,
- 0, &p, NULL, &nh, 0, zvrf->table_id, 0, 0, false);
+ if (!CHECK_FLAG(ifc->flags, ZEBRA_IFA_NOPREFIXROUTE)) {
+ rib_delete(afi, SAFI_UNICAST, zvrf->vrf->vrf_id,
+ ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, &nh, 0,
+ zvrf->table_id, 0, 0, false);
+
+ rib_delete(afi, SAFI_MULTICAST, zvrf->vrf->vrf_id,
+ ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, &nh, 0,
+ zvrf->table_id, 0, 0, false);
+ }
+
+ if (remove_local) {
+ rib_delete(afi, SAFI_UNICAST, zvrf->vrf->vrf_id,
+ ZEBRA_ROUTE_LOCAL, 0, 0, &plocal, NULL, &nh, 0,
+ zvrf->table_id, 0, 0, false);
- rib_delete(afi, SAFI_MULTICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT,
- 0, 0, &p, NULL, &nh, 0, zvrf->table_id, 0, 0, false);
+ rib_delete(afi, SAFI_MULTICAST, zvrf->vrf->vrf_id,
+ ZEBRA_ROUTE_LOCAL, 0, 0, &plocal, NULL, &nh, 0,
+ zvrf->table_id, 0, 0, false);
+ }
/* Schedule LSP forwarding entries for processing, if appropriate. */
if (zvrf->vrf->vrf_id == VRF_DEFAULT) {
@@ -616,9 +656,8 @@ void connected_delete_ipv6(struct interface *ifp,
int connected_is_unnumbered(struct interface *ifp)
{
struct connected *connected;
- struct listnode *node;
- for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) {
+ frr_each (if_connected, ifp->connected, connected) {
if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL)
&& connected->address->family == AF_INET)
return CHECK_FLAG(connected->flags,
diff --git a/zebra/debug.c b/zebra/debug.c
index 68bedaf057..cf1701be19 100644
--- a/zebra/debug.c
+++ b/zebra/debug.c
@@ -7,6 +7,7 @@
#include <zebra.h>
#include "command.h"
#include "debug.h"
+#include "mgmt_be_client.h"
#include "zebra/debug_clippy.c"
@@ -846,4 +847,7 @@ void zebra_debug_init(void)
install_element(CONFIG_NODE, &no_debug_zebra_pbr_cmd);
install_element(CONFIG_NODE, &debug_zebra_mlag_cmd);
install_element(CONFIG_NODE, &debug_zebra_evpn_mh_cmd);
+
+ /* Init mgmtd backend client debug commands. */
+ mgmt_be_client_lib_vty_init();
}
diff --git a/zebra/debug_nl.c b/zebra/debug_nl.c
index df0b5aae7b..a7cccdb98f 100644
--- a/zebra/debug_nl.c
+++ b/zebra/debug_nl.c
@@ -983,6 +983,7 @@ next_rta:
zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta->rta_len,
plen, rta_type, rta_type2str(rta_type));
switch (rta_type) {
+ case IFLA_IFNAME:
case IFLA_IFALIAS:
if (plen == 0) {
zlog_debug(" invalid length");
diff --git a/zebra/dpdk/zebra_dplane_dpdk.c b/zebra/dpdk/zebra_dplane_dpdk.c
index fc140b07a3..7a5388c57b 100644
--- a/zebra/dpdk/zebra_dplane_dpdk.c
+++ b/zebra/dpdk/zebra_dplane_dpdk.c
@@ -105,8 +105,7 @@ static int zd_dpdk_pbr_show_rules_walkcb(struct hash_bucket *bucket, void *arg)
ifp = if_lookup_by_name_vrf(rule->ifname, vrf);
if (ifp)
- zd_dpdk_flow_stat_show(vty, ifp->ifindex,
- zaction->dp_flow_ptr);
+ zd_dpdk_flow_stat_show(vty, ifp->ifindex, zaction->dp_flow_ptr);
}
return HASHWALK_CONTINUE;
}
@@ -153,8 +152,7 @@ static void zd_dpdk_rule_add(struct zebra_dplane_ctx *ctx)
if (IS_ZEBRA_DEBUG_DPLANE_DPDK_DETAIL)
zlog_debug(
"PBR dpdk flow create ifname %s seq %d pri %u unique %d failed; in_port %d missing\n",
- dplane_ctx_rule_get_ifname(ctx), seq, pri,
- unique, in_ifindex);
+ dplane_ctx_rule_get_ifname(ctx), seq, pri, unique, in_ifindex);
return;
}
@@ -163,8 +161,7 @@ static void zd_dpdk_rule_add(struct zebra_dplane_ctx *ctx)
if (IS_ZEBRA_DEBUG_DPLANE_DPDK_DETAIL)
zlog_debug(
"PBR dpdk flow create ifname %s seq %d pri %u unique %d failed; out_port %d missing\n",
- dplane_ctx_rule_get_ifname(ctx), seq, pri,
- unique, out_ifindex);
+ dplane_ctx_rule_get_ifname(ctx), seq, pri, unique, out_ifindex);
return;
}
@@ -180,7 +177,7 @@ static void zd_dpdk_rule_add(struct zebra_dplane_ctx *ctx)
memset(&ip, 0, sizeof(ip));
memset(&ip_mask, 0, sizeof(ip_mask));
- if (filter_bm & PBR_FILTER_SRC_IP) {
+ if (CHECK_FLAG(filter_bm, PBR_FILTER_SRC_IP)) {
const struct prefix *src_ip;
src_ip = dplane_ctx_rule_get_src_ip(ctx);
@@ -188,7 +185,7 @@ static void zd_dpdk_rule_add(struct zebra_dplane_ctx *ctx)
masklen2ip(src_ip->prefixlen, &tmp_mask);
ip_mask.hdr.src_addr = tmp_mask.s_addr;
}
- if (filter_bm & PBR_FILTER_DST_IP) {
+ if (CHECK_FLAG(filter_bm, PBR_FILTER_DST_IP)) {
const struct prefix *dst_ip;
dst_ip = dplane_ctx_rule_get_dst_ip(ctx);
@@ -196,7 +193,7 @@ static void zd_dpdk_rule_add(struct zebra_dplane_ctx *ctx)
masklen2ip(dst_ip->prefixlen, &tmp_mask);
ip_mask.hdr.dst_addr = tmp_mask.s_addr;
}
- if (filter_bm & PBR_FILTER_IP_PROTOCOL) {
+ if (CHECK_FLAG(filter_bm, PBR_FILTER_IP_PROTOCOL)) {
ip.hdr.next_proto_id = dplane_ctx_rule_get_ipproto(ctx);
ip_mask.hdr.next_proto_id = UINT8_MAX;
}
@@ -206,17 +203,15 @@ static void zd_dpdk_rule_add(struct zebra_dplane_ctx *ctx)
items[item_cnt].last = NULL;
++item_cnt;
- if ((filter_bm & (PBR_FILTER_SRC_PORT | PBR_FILTER_DST_PORT))) {
+ if (CHECK_FLAG(filter_bm, (PBR_FILTER_SRC_PORT | PBR_FILTER_DST_PORT))) {
memset(&udp, 0, sizeof(udp));
memset(&udp_mask, 0, sizeof(udp_mask));
- if (filter_bm & PBR_FILTER_SRC_PORT) {
- udp.hdr.src_port =
- RTE_BE16(dplane_ctx_rule_get_src_port(ctx));
+ if (CHECK_FLAG(filter_bm, PBR_FILTER_SRC_PORT)) {
+ udp.hdr.src_port = RTE_BE16(dplane_ctx_rule_get_src_port(ctx));
udp_mask.hdr.src_port = UINT16_MAX;
}
- if (filter_bm & PBR_FILTER_DST_PORT) {
- udp.hdr.dst_port =
- RTE_BE16(dplane_ctx_rule_get_dst_port(ctx));
+ if (CHECK_FLAG(filter_bm, PBR_FILTER_DST_PORT)) {
+ udp.hdr.dst_port = RTE_BE16(dplane_ctx_rule_get_dst_port(ctx));
udp_mask.hdr.dst_port = UINT16_MAX;
}
items[item_cnt].type = RTE_FLOW_ITEM_TYPE_UDP;
@@ -273,8 +268,7 @@ static void zd_dpdk_rule_add(struct zebra_dplane_ctx *ctx)
} else {
zlog_warn(
"PBR dpdk flow create failed ifname %s seq %d pri %u unique %d; rc %d\n",
- dplane_ctx_rule_get_ifname(ctx), seq, pri, unique,
- error.type);
+ dplane_ctx_rule_get_ifname(ctx), seq, pri, unique, error.type);
}
}
@@ -562,7 +556,7 @@ void zd_dpdk_port_show(struct vty *vty, uint16_t port_id, bool uj, int detail)
for (count = 0; count < RTE_MAX_ETHPORTS; ++count) {
dport = &dpdk_ctx->dpdk_ports[count];
- if (dport->flags & ZD_DPDK_PORT_FLAG_INITED)
+ if (CHECK_FLAG(dport->flags, ZD_DPDK_PORT_FLAG_INITED))
zd_dpdk_port_show_entry(dport, vty, detail);
}
}
@@ -592,14 +586,14 @@ static void zd_dpdk_port_init(void)
dport = &dpdk_ctx->dpdk_ports[count];
count++;
dport->port_id = port_id;
- dport->flags |= ZD_DPDK_PORT_FLAG_PROBED;
+ SET_FLAG(dport->flags, ZD_DPDK_PORT_FLAG_PROBED);
dev_info = &dport->dev_info;
if (rte_eth_dev_info_get(port_id, dev_info) < 0) {
zlog_warn("failed to get dev info for %u, %s", port_id,
rte_strerror(rte_errno));
continue;
}
- dport->flags |= ZD_DPDK_PORT_FLAG_INITED;
+ SET_FLAG(dport->flags, ZD_DPDK_PORT_FLAG_INITED);
if (IS_ZEBRA_DEBUG_DPLANE_DPDK)
zlog_debug(
"port %u, dev %s, ifI %d, sw_name %s, sw_domain %u, sw_port %u",
@@ -611,12 +605,10 @@ static void zd_dpdk_port_init(void)
if (rte_flow_isolate(port_id, 1, &error)) {
if (IS_ZEBRA_DEBUG_DPLANE_DPDK)
zlog_debug(
- "Flow isolate on port %u failed %d\n",
- port_id, error.type);
+ "Flow isolate on port %u failed %d", port_id, error.type);
} else {
if (IS_ZEBRA_DEBUG_DPLANE_DPDK)
- zlog_debug("Flow isolate on port %u\n",
- port_id);
+ zlog_debug("Flow isolate on port %u", port_id);
}
rc = rte_eth_dev_start(port_id);
if (rc) {
@@ -625,8 +617,7 @@ static void zd_dpdk_port_init(void)
continue;
}
if (IS_ZEBRA_DEBUG_DPLANE_DPDK)
- zlog_debug("DPDK port %d started in promiscuous mode ",
- port_id);
+ zlog_debug("DPDK port %d started in promiscuous mode ", port_id);
}
if (!count) {
@@ -639,8 +630,7 @@ static void zd_dpdk_port_init(void)
static int zd_dpdk_init(void)
{
int rc;
- static const char *argv[] = {(char *)"/usr/lib/frr/zebra",
- (char *)"--"};
+ static const char *argv[] = {(char *)"/usr/lib/frr/zebra", (char *)"--"};
zd_dpdk_vty_init();
@@ -674,8 +664,7 @@ static int zd_dpdk_finish(struct zebra_dplane_provider *prov, bool early)
if (early) {
if (IS_ZEBRA_DEBUG_DPLANE_DPDK)
- zlog_debug("%s early finish",
- dplane_provider_get_name(prov));
+ zlog_debug("%s early finish", dplane_provider_get_name(prov));
return 0;
}
diff --git a/zebra/dplane_fpm_nl.c b/zebra/dplane_fpm_nl.c
index be2f55120c..245b799a91 100644
--- a/zebra/dplane_fpm_nl.c
+++ b/zebra/dplane_fpm_nl.c
@@ -19,6 +19,9 @@
#include <string.h>
#include "lib/zebra.h"
+
+#include <linux/rtnetlink.h>
+
#include "lib/json.h"
#include "lib/libfrr.h"
#include "lib/frratomic.h"
@@ -27,6 +30,7 @@
#include "lib/network.h"
#include "lib/ns.h"
#include "lib/frr_pthread.h"
+#include "lib/termtable.h"
#include "zebra/debug.h"
#include "zebra/interface.h"
#include "zebra/zebra_dplane.h"
@@ -41,8 +45,15 @@
#include "zebra/debug.h"
#include "fpm/fpm.h"
+#include "zebra/dplane_fpm_nl_clippy.c"
+
#define SOUTHBOUND_DEFAULT_ADDR INADDR_LOOPBACK
-#define SOUTHBOUND_DEFAULT_PORT 2620
+
+/*
+ * Time in seconds that if the other end is not responding
+ * something terrible has gone wrong. Let's fix that.
+ */
+#define DPLANE_FPM_NL_WEDGIE_TIME 15
/**
* FPM header:
@@ -65,6 +76,7 @@ struct fpm_nl_ctx {
bool disabled;
bool connecting;
bool use_nhg;
+ bool use_route_replace;
struct sockaddr_storage addr;
/* data plane buffers. */
@@ -89,6 +101,7 @@ struct fpm_nl_ctx {
struct event *t_event;
struct event *t_nhg;
struct event *t_dequeue;
+ struct event *t_wedged;
/* zebra events. */
struct event *t_lspreset;
@@ -206,7 +219,7 @@ DEFUN(fpm_set_address, fpm_set_address_cmd,
memset(sin, 0, sizeof(*sin));
sin->sin_family = AF_INET;
sin->sin_port =
- port ? htons(port) : htons(SOUTHBOUND_DEFAULT_PORT);
+ port ? htons(port) : htons(FPM_DEFAULT_PORT);
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
sin->sin_len = sizeof(*sin);
#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
@@ -224,7 +237,7 @@ DEFUN(fpm_set_address, fpm_set_address_cmd,
sin6 = (struct sockaddr_in6 *)&gfnc->addr;
memset(sin6, 0, sizeof(*sin6));
sin6->sin6_family = AF_INET6;
- sin6->sin6_port = port ? htons(port) : htons(SOUTHBOUND_DEFAULT_PORT);
+ sin6->sin6_port = port ? htons(port) : htons(FPM_DEFAULT_PORT);
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
sin6->sin6_len = sizeof(*sin6);
#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
@@ -282,6 +295,25 @@ DEFUN(no_fpm_use_nhg, no_fpm_use_nhg_cmd,
return CMD_SUCCESS;
}
+DEFUN(fpm_use_route_replace, fpm_use_route_replace_cmd,
+ "fpm use-route-replace",
+ FPM_STR
+ "Use netlink route replace semantics\n")
+{
+ gfnc->use_route_replace = true;
+ return CMD_SUCCESS;
+}
+
+DEFUN(no_fpm_use_route_replace, no_fpm_use_route_replace_cmd,
+ "no fpm use-route-replace",
+ NO_STR
+ FPM_STR
+ "Use netlink route replace semantics\n")
+{
+ gfnc->use_route_replace = false;
+ return CMD_SUCCESS;
+}
+
DEFUN(fpm_reset_counters, fpm_reset_counters_cmd,
"clear fpm counters",
CLEAR_STR
@@ -293,6 +325,74 @@ DEFUN(fpm_reset_counters, fpm_reset_counters_cmd,
return CMD_SUCCESS;
}
+DEFPY(fpm_show_status,
+ fpm_show_status_cmd,
+ "show fpm status [json]$json",
+ SHOW_STR FPM_STR "FPM status\n" JSON_STR)
+{
+ struct json_object *j;
+ bool connected;
+ uint16_t port;
+ struct sockaddr_in *sin;
+ struct sockaddr_in6 *sin6;
+ char buf[BUFSIZ];
+
+ connected = gfnc->socket > 0 ? true : false;
+
+ switch (gfnc->addr.ss_family) {
+ case AF_INET:
+ sin = (struct sockaddr_in *)&gfnc->addr;
+ snprintfrr(buf, sizeof(buf), "%pI4", &sin->sin_addr);
+ port = ntohs(sin->sin_port);
+ break;
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *)&gfnc->addr;
+ snprintfrr(buf, sizeof(buf), "%pI6", &sin6->sin6_addr);
+ port = ntohs(sin6->sin6_port);
+ break;
+ default:
+ strlcpy(buf, "Unknown", sizeof(buf));
+ port = FPM_DEFAULT_PORT;
+ break;
+ }
+
+ if (json) {
+ j = json_object_new_object();
+
+ json_object_boolean_add(j, "connected", connected);
+ json_object_boolean_add(j, "useNHG", gfnc->use_nhg);
+ json_object_boolean_add(j, "useRouteReplace",
+ gfnc->use_route_replace);
+ json_object_boolean_add(j, "disabled", gfnc->disabled);
+ json_object_string_add(j, "address", buf);
+ json_object_int_add(j, "port", port);
+
+ vty_json(vty, j);
+ } else {
+ struct ttable *table = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
+ char *out;
+
+ ttable_rowseps(table, 0, BOTTOM, true, '-');
+ ttable_add_row(table, "Address to connect to|%s", buf);
+ ttable_add_row(table, "Port|%u", port);
+ ttable_add_row(table, "Connected|%s", connected ? "Yes" : "No");
+ ttable_add_row(table, "Use Nexthop Groups|%s",
+ gfnc->use_nhg ? "Yes" : "No");
+ ttable_add_row(table, "Use Route Replace Semantics|%s",
+ gfnc->use_route_replace ? "Yes" : "No");
+ ttable_add_row(table, "Disabled|%s",
+ gfnc->disabled ? "Yes" : "No");
+
+ out = ttable_dump(table, "\n");
+ vty_out(vty, "%s\n", out);
+ XFREE(MTYPE_TMP, out);
+
+ ttable_del(table);
+ }
+
+ return CMD_SUCCESS;
+}
+
DEFUN(fpm_show_counters, fpm_show_counters_cmd,
"show fpm counters",
SHOW_STR
@@ -372,7 +472,7 @@ static int fpm_write_config(struct vty *vty)
written = 1;
sin = (struct sockaddr_in *)&gfnc->addr;
vty_out(vty, "fpm address %pI4", &sin->sin_addr);
- if (sin->sin_port != htons(SOUTHBOUND_DEFAULT_PORT))
+ if (sin->sin_port != htons(FPM_DEFAULT_PORT))
vty_out(vty, " port %d", ntohs(sin->sin_port));
vty_out(vty, "\n");
@@ -381,7 +481,7 @@ static int fpm_write_config(struct vty *vty)
written = 1;
sin6 = (struct sockaddr_in6 *)&gfnc->addr;
vty_out(vty, "fpm address %pI6", &sin6->sin6_addr);
- if (sin6->sin6_port != htons(SOUTHBOUND_DEFAULT_PORT))
+ if (sin6->sin6_port != htons(FPM_DEFAULT_PORT))
vty_out(vty, " port %d", ntohs(sin6->sin6_port));
vty_out(vty, "\n");
@@ -396,6 +496,11 @@ static int fpm_write_config(struct vty *vty)
written = 1;
}
+ if (!gfnc->use_route_replace) {
+ vty_out(vty, "no fpm use-route-replace\n");
+ written = 1;
+ }
+
return written;
}
@@ -587,7 +692,8 @@ static void fpm_read(struct event *t)
switch (hdr->nlmsg_type) {
case RTM_NEWROUTE:
ctx = dplane_ctx_alloc();
- dplane_ctx_set_op(ctx, DPLANE_OP_ROUTE_NOTIFY);
+ dplane_ctx_route_init(ctx, DPLANE_OP_ROUTE_NOTIFY, NULL,
+ NULL);
if (netlink_route_change_read_unicast_internal(
hdr, 0, false, ctx) != 1) {
dplane_ctx_fini(&ctx);
@@ -806,12 +912,20 @@ static int fpm_nl_enqueue(struct fpm_nl_ctx *fnc, struct zebra_dplane_ctx *ctx)
frr_mutex_lock_autounlock(&fnc->obuf_mutex);
+ /*
+ * If route replace is enabled then directly encode the install which
+ * is going to use `NLM_F_REPLACE` (instead of delete/add operations).
+ */
+ if (fnc->use_route_replace && op == DPLANE_OP_ROUTE_UPDATE)
+ op = DPLANE_OP_ROUTE_INSTALL;
+
switch (op) {
case DPLANE_OP_ROUTE_UPDATE:
case DPLANE_OP_ROUTE_DELETE:
rv = netlink_route_multipath_msg_encode(RTM_DELROUTE, ctx,
nl_buf, sizeof(nl_buf),
- true, fnc->use_nhg);
+ true, fnc->use_nhg,
+ false);
if (rv <= 0) {
zlog_err(
"%s: netlink_route_multipath_msg_encode failed",
@@ -825,11 +939,14 @@ static int fpm_nl_enqueue(struct fpm_nl_ctx *fnc, struct zebra_dplane_ctx *ctx)
if (op == DPLANE_OP_ROUTE_DELETE)
break;
- /* FALL THROUGH */
+ fallthrough;
case DPLANE_OP_ROUTE_INSTALL:
- rv = netlink_route_multipath_msg_encode(
- RTM_NEWROUTE, ctx, &nl_buf[nl_buf_len],
- sizeof(nl_buf) - nl_buf_len, true, fnc->use_nhg);
+ rv = netlink_route_multipath_msg_encode(RTM_NEWROUTE, ctx,
+ &nl_buf[nl_buf_len],
+ sizeof(nl_buf) -
+ nl_buf_len,
+ true, fnc->use_nhg,
+ fnc->use_route_replace);
if (rv <= 0) {
zlog_err(
"%s: netlink_route_multipath_msg_encode failed",
@@ -932,7 +1049,9 @@ static int fpm_nl_enqueue(struct fpm_nl_ctx *fnc, struct zebra_dplane_ctx *ctx)
case DPLANE_OP_TC_FILTER_ADD:
case DPLANE_OP_TC_FILTER_DELETE:
case DPLANE_OP_TC_FILTER_UPDATE:
+ case DPLANE_OP_SRV6_ENCAP_SRCADDR_SET:
case DPLANE_OP_NONE:
+ case DPLANE_OP_STARTUP_STAGE:
break;
}
@@ -1326,6 +1445,18 @@ static void fpm_rmac_reset(struct event *t)
&fnc->t_rmacwalk);
}
+static void fpm_process_wedged(struct event *t)
+{
+ struct fpm_nl_ctx *fnc = EVENT_ARG(t);
+
+ zlog_warn("%s: Connection unable to write to peer for over %u seconds, resetting",
+ __func__, DPLANE_FPM_NL_WEDGIE_TIME);
+
+ atomic_fetch_add_explicit(&fnc->counters.connection_errors, 1,
+ memory_order_relaxed);
+ FPM_RECONNECT(fnc);
+}
+
static void fpm_process_queue(struct event *t)
{
struct fpm_nl_ctx *fnc = EVENT_ARG(t);
@@ -1334,8 +1465,14 @@ static void fpm_process_queue(struct event *t)
uint64_t processed_contexts = 0;
while (true) {
+ size_t writeable_amount;
+
+ frr_with_mutex (&fnc->obuf_mutex) {
+ writeable_amount = STREAM_WRITEABLE(fnc->obuf);
+ }
+
/* No space available yet. */
- if (STREAM_WRITEABLE(fnc->obuf) < NL_PKT_BUF_SIZE) {
+ if (writeable_amount < NL_PKT_BUF_SIZE) {
no_bufs = true;
break;
}
@@ -1370,9 +1507,13 @@ static void fpm_process_queue(struct event *t)
processed_contexts, memory_order_relaxed);
/* Re-schedule if we ran out of buffer space */
- if (no_bufs)
- event_add_timer(fnc->fthread->master, fpm_process_queue, fnc, 0,
+ if (no_bufs) {
+ event_add_event(fnc->fthread->master, fpm_process_queue, fnc, 0,
&fnc->t_dequeue);
+ event_add_timer(fnc->fthread->master, fpm_process_wedged, fnc,
+ DPLANE_FPM_NL_WEDGIE_TIME, &fnc->t_wedged);
+ } else
+ EVENT_OFF(fnc->t_wedged);
/*
* Let the dataplane thread know if there are items in the
@@ -1467,6 +1608,7 @@ static int fpm_nl_start(struct zebra_dplane_provider *prov)
/* Set default values. */
fnc->use_nhg = true;
+ fnc->use_route_replace = true;
return 0;
}
@@ -1575,7 +1717,7 @@ static int fpm_nl_process(struct zebra_dplane_provider *prov)
if (atomic_load_explicit(&fnc->counters.ctxqueue_len,
memory_order_relaxed)
> 0)
- event_add_timer(fnc->fthread->master, fpm_process_queue, fnc, 0,
+ event_add_event(fnc->fthread->master, fpm_process_queue, fnc, 0,
&fnc->t_dequeue);
/* Ensure dataplane thread is rescheduled if we hit the work limit */
@@ -1600,6 +1742,7 @@ static int fpm_nl_new(struct event_loop *tm)
zlog_debug("%s register status: %d", prov_name, rv);
install_node(&fpm_node);
+ install_element(ENABLE_NODE, &fpm_show_status_cmd);
install_element(ENABLE_NODE, &fpm_show_counters_cmd);
install_element(ENABLE_NODE, &fpm_show_counters_json_cmd);
install_element(ENABLE_NODE, &fpm_reset_counters_cmd);
@@ -1607,6 +1750,8 @@ static int fpm_nl_new(struct event_loop *tm)
install_element(CONFIG_NODE, &no_fpm_set_address_cmd);
install_element(CONFIG_NODE, &fpm_use_nhg_cmd);
install_element(CONFIG_NODE, &no_fpm_use_nhg_cmd);
+ install_element(CONFIG_NODE, &fpm_use_route_replace_cmd);
+ install_element(CONFIG_NODE, &no_fpm_use_route_replace_cmd);
return 0;
}
diff --git a/zebra/fpm_listener.c b/zebra/fpm_listener.c
new file mode 100644
index 0000000000..5ffc0561bb
--- /dev/null
+++ b/zebra/fpm_listener.c
@@ -0,0 +1,703 @@
+// SPDX-License-Identifier: ISC
+/*
+ * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#ifdef GNU_LINUX
+#include <stdint.h>
+#include <memory.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <assert.h>
+#include <err.h>
+#include <sys/types.h>
+
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+
+#include "rt_netlink.h"
+#include "fpm/fpm.h"
+#include "lib/libfrr.h"
+
+struct glob {
+ int server_sock;
+ int sock;
+ bool reflect;
+};
+
+struct glob glob_space;
+struct glob *glob = &glob_space;
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
+
+/*
+ * get_print_buf
+ */
+static char *
+get_print_buf(size_t *buf_len)
+{
+ static char print_bufs[16][128];
+ static int counter;
+
+ counter++;
+ if (counter >= 16)
+ counter = 0;
+
+ *buf_len = 128;
+ return &print_bufs[counter][0];
+}
+
+/*
+ * create_listen_sock
+ */
+static int create_listen_sock(int port, int *sock_p)
+{
+ int sock;
+ struct sockaddr_in addr;
+ int reuse;
+
+ sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (sock < 0) {
+ fprintf(stderr, "Failed to create socket: %s\n", strerror(errno));
+ return 0;
+ }
+
+ reuse = 1;
+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) <
+ 0) {
+ fprintf(stderr, "Failed to set reuse addr option: %s\n",
+ strerror(errno));
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ addr.sin_port = htons(port);
+
+ if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ fprintf(stderr, "Failed to bind to port %d: %s\n", port, strerror(errno));
+ close(sock);
+ return 0;
+ }
+
+ if (listen(sock, 5)) {
+ fprintf(stderr, "Failed to listen on socket: %s\n", strerror(errno));
+ close(sock);
+ return 0;
+ }
+
+ *sock_p = sock;
+ return 1;
+}
+
+/*
+ * accept_conn
+ */
+static int accept_conn(int listen_sock)
+{
+ int sock;
+ struct sockaddr_in client_addr = { 0 };
+ unsigned int client_len;
+
+ while (1) {
+ char buf[120];
+
+ fprintf(stdout, "Waiting for client connection...\n");
+ client_len = sizeof(client_addr);
+ sock = accept(listen_sock, (struct sockaddr *)&client_addr,
+ &client_len);
+
+ if (sock >= 0) {
+ fprintf(stdout, "Accepted client %s\n",
+ inet_ntop(AF_INET, &client_addr.sin_addr, buf, sizeof(buf)));
+ return sock;
+ }
+ fprintf(stderr, "Failed to accept socket: %s\n", strerror(errno));
+ }
+}
+
+/*
+ * read_fpm_msg
+ */
+static fpm_msg_hdr_t *
+read_fpm_msg(char *buf, size_t buf_len)
+{
+ char *cur, *end;
+ long need_len, bytes_read, have_len;
+ fpm_msg_hdr_t *hdr;
+ int reading_full_msg;
+
+ end = buf + buf_len;
+ cur = buf;
+ hdr = (fpm_msg_hdr_t *)buf;
+
+ while (1) {
+ reading_full_msg = 0;
+
+ have_len = cur - buf;
+
+ if (have_len < (long)FPM_MSG_HDR_LEN) {
+ need_len = FPM_MSG_HDR_LEN - have_len;
+ } else {
+ need_len = fpm_msg_len(hdr) - have_len;
+ assert(need_len >= 0 && need_len <= (end - cur));
+
+ if (!need_len)
+ return hdr;
+
+ reading_full_msg = 1;
+ }
+
+ bytes_read = read(glob->sock, cur, need_len);
+
+ if (bytes_read == 0) {
+ fprintf(stdout,
+ "Socket closed as that read returned 0\n");
+ return NULL;
+ }
+
+ if (bytes_read < 0) {
+ fprintf(stderr, "Error reading from socket: %s\n",
+ strerror(errno));
+ return NULL;
+ }
+
+ cur += bytes_read;
+
+ if (bytes_read < need_len) {
+ fprintf(stderr,
+ "Read %lu bytes but expected to read %lu bytes instead\n",
+ bytes_read, need_len);
+ return NULL;
+ }
+
+ if (reading_full_msg)
+ return hdr;
+
+ if (!fpm_msg_ok(hdr, buf_len)) {
+ assert(0);
+ fprintf(stderr, "Malformed fpm message\n");
+ return NULL;
+ }
+ }
+}
+
+/*
+ * netlink_msg_type_to_s
+ */
+static const char *
+netlink_msg_type_to_s(uint16_t type)
+{
+ switch (type) {
+
+ case RTM_NEWROUTE:
+ return "New route";
+
+ case RTM_DELROUTE:
+ return "Del route";
+
+ case RTM_NEWNEXTHOP:
+ return "New Nexthop Group";
+
+ case RTM_DELNEXTHOP:
+ return "Del Nexthop Group";
+
+ default:
+ return "Unknown";
+ }
+}
+
+/*
+ * netlink_prot_to_s
+ */
+static const char *
+netlink_prot_to_s(unsigned char prot)
+{
+ switch (prot) {
+
+ case RTPROT_KERNEL:
+ return "Kernel";
+
+ case RTPROT_BOOT:
+ return "Boot";
+
+ case RTPROT_STATIC:
+ return "Static";
+
+ case RTPROT_ZEBRA:
+ return "Zebra";
+
+ case RTPROT_DHCP:
+ return "Dhcp";
+
+ case RTPROT_BGP:
+ return "BGP";
+
+ case RTPROT_ISIS:
+ return "ISIS";
+
+ case RTPROT_OSPF:
+ return "OSPF";
+
+ case RTPROT_RIP:
+ return "RIP";
+
+ case RTPROT_RIPNG:
+ return "RIPNG";
+
+ case RTPROT_BABEL:
+ return "BABEL";
+
+ case RTPROT_NHRP:
+ return "NHRP";
+
+ case RTPROT_EIGRP:
+ return "EIGRP";
+
+ case RTPROT_SHARP:
+ return "SHARP";
+
+ case RTPROT_PBR:
+ return "PBR";
+
+ case RTPROT_ZSTATIC:
+ return "Static";
+
+ default:
+ return "Unknown";
+ }
+}
+
+#define MAX_NHS 16
+
+struct netlink_nh {
+ struct rtattr *gateway;
+ int if_index;
+};
+
+struct netlink_msg_ctx {
+ struct nlmsghdr *hdr;
+
+ /*
+ * Stuff pertaining to route messages.
+ */
+ struct rtmsg *rtmsg;
+ struct rtattr *rtattrs[RTA_MAX + 1];
+
+ /*
+ * Nexthops.
+ */
+ struct netlink_nh nhs[MAX_NHS];
+ unsigned long num_nhs;
+
+ struct rtattr *dest;
+ struct rtattr *src;
+ int *metric;
+ unsigned int *nhgid;
+
+ const char *err_msg;
+};
+
+/*
+ * netlink_msg_ctx_init
+ */
+static inline void netlink_msg_ctx_init(struct netlink_msg_ctx *ctx)
+{
+ memset(ctx, 0, sizeof(*ctx));
+}
+
+/*
+ * netlink_msg_ctx_set_err
+ */
+static inline void netlink_msg_ctx_set_err(struct netlink_msg_ctx *ctx,
+ const char *err_msg)
+{
+ if (ctx->err_msg)
+ return;
+
+ ctx->err_msg = err_msg;
+}
+
+/*
+ * parse_rtattrs_
+ */
+static int parse_rtattrs_(struct rtattr *rta, size_t len, struct rtattr **rtas,
+ int num_rtas, const char **err_msg)
+{
+ memset(rtas, 0, num_rtas * sizeof(rtas[0]));
+
+ for (; len > 0; rta = RTA_NEXT(rta, len)) {
+ if (!RTA_OK(rta, len)) {
+ *err_msg = "Malformed rta";
+ return 0;
+ }
+
+ if (rta->rta_type >= num_rtas) {
+ warn("Unknown rtattr type %d", rta->rta_type);
+ continue;
+ }
+
+ rtas[rta->rta_type] = rta;
+ }
+
+ return 1;
+}
+
+/*
+ * parse_rtattrs
+ */
+static int parse_rtattrs(struct netlink_msg_ctx *ctx, struct rtattr *rta,
+ size_t len)
+{
+ const char *err_msg;
+
+ err_msg = NULL;
+
+ if (!parse_rtattrs_(rta, len, ctx->rtattrs, ARRAY_SIZE(ctx->rtattrs),
+ &err_msg)) {
+ netlink_msg_ctx_set_err(ctx, err_msg);
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * netlink_msg_ctx_add_nh
+ */
+static int netlink_msg_ctx_add_nh(struct netlink_msg_ctx *ctx, int if_index,
+ struct rtattr *gateway)
+{
+ struct netlink_nh *nh;
+
+ if (ctx->num_nhs + 1 >= ARRAY_SIZE(ctx->nhs)) {
+ warn("Too many next hops");
+ return 0;
+ }
+ nh = &ctx->nhs[ctx->num_nhs];
+ ctx->num_nhs++;
+
+ nh->gateway = gateway;
+ nh->if_index = if_index;
+ return 1;
+}
+
+/*
+ * parse_multipath_attr
+ */
+static int parse_multipath_attr(struct netlink_msg_ctx *ctx,
+ struct rtattr *mpath_rtattr)
+{
+ size_t len;
+ struct rtnexthop *rtnh;
+ struct rtattr *rtattrs[RTA_MAX + 1];
+ struct rtattr *gateway;
+ const char *err_msg;
+
+ rtnh = RTA_DATA(mpath_rtattr);
+ len = RTA_PAYLOAD(mpath_rtattr);
+
+ for (; len > 0;
+ len -= NLMSG_ALIGN(rtnh->rtnh_len), rtnh = RTNH_NEXT(rtnh)) {
+
+ if (!RTNH_OK(rtnh, len)) {
+ netlink_msg_ctx_set_err(ctx, "Malformed nh");
+ return 0;
+ }
+
+ if (rtnh->rtnh_len <= sizeof(*rtnh)) {
+ netlink_msg_ctx_set_err(ctx, "NH len too small");
+ return 0;
+ }
+
+ /*
+ * Parse attributes included in the nexthop.
+ */
+ err_msg = NULL;
+ if (!parse_rtattrs_(RTNH_DATA(rtnh),
+ rtnh->rtnh_len - sizeof(*rtnh), rtattrs,
+ ARRAY_SIZE(rtattrs), &err_msg)) {
+ netlink_msg_ctx_set_err(ctx, err_msg);
+ return 0;
+ }
+
+ gateway = rtattrs[RTA_GATEWAY];
+ netlink_msg_ctx_add_nh(ctx, rtnh->rtnh_ifindex, gateway);
+ }
+
+ return 1;
+}
+
+/*
+ * parse_route_msg
+ */
+static int parse_route_msg(struct netlink_msg_ctx *ctx)
+{
+ int len;
+ struct rtattr **rtattrs, *rtattr, *gateway, *oif;
+ int if_index;
+
+ ctx->rtmsg = NLMSG_DATA(ctx->hdr);
+
+ len = ctx->hdr->nlmsg_len - NLMSG_LENGTH(sizeof(struct rtmsg));
+ if (len < 0) {
+ netlink_msg_ctx_set_err(ctx, "Bad message length");
+ return 0;
+ }
+
+ if (!parse_rtattrs(ctx, RTM_RTA(ctx->rtmsg), len))
+ return 0;
+
+ rtattrs = ctx->rtattrs;
+
+ ctx->dest = rtattrs[RTA_DST];
+ ctx->src = rtattrs[RTA_PREFSRC];
+
+ rtattr = rtattrs[RTA_PRIORITY];
+ if (rtattr)
+ ctx->metric = (int *)RTA_DATA(rtattr);
+
+ rtattr = rtattrs[RTA_NH_ID];
+ if (rtattr)
+ ctx->nhgid = (unsigned int *)RTA_DATA(rtattr);
+
+ gateway = rtattrs[RTA_GATEWAY];
+ oif = rtattrs[RTA_OIF];
+ if (gateway || oif) {
+ if_index = 0;
+ if (oif)
+ if_index = *((int *)RTA_DATA(oif));
+
+ netlink_msg_ctx_add_nh(ctx, if_index, gateway);
+ }
+
+ rtattr = rtattrs[RTA_MULTIPATH];
+ if (rtattr)
+ parse_multipath_attr(ctx, rtattr);
+
+ return 1;
+}
+
+/*
+ * addr_to_s
+ */
+static const char *
+addr_to_s(unsigned char family, void *addr)
+{
+ size_t buf_len;
+ char *buf;
+
+ buf = get_print_buf(&buf_len);
+
+ return inet_ntop(family, addr, buf, buf_len);
+}
+
+/*
+ * netlink_msg_ctx_print
+ */
+static int netlink_msg_ctx_snprint(struct netlink_msg_ctx *ctx, char *buf,
+ size_t buf_len)
+{
+ struct nlmsghdr *hdr;
+ struct rtmsg *rtmsg;
+ struct netlink_nh *nh;
+ char *cur, *end;
+ unsigned long i;
+
+ hdr = ctx->hdr;
+ rtmsg = ctx->rtmsg;
+
+ cur = buf;
+ end = buf + buf_len;
+
+ cur += snprintf(cur, end - cur, "%s %s/%d, Prot: %s(%u)",
+ netlink_msg_type_to_s(hdr->nlmsg_type),
+ addr_to_s(rtmsg->rtm_family, RTA_DATA(ctx->dest)),
+ rtmsg->rtm_dst_len,
+ netlink_prot_to_s(rtmsg->rtm_protocol),
+ rtmsg->rtm_protocol);
+
+ if (ctx->metric)
+ cur += snprintf(cur, end - cur, ", Metric: %d", *ctx->metric);
+
+ if (ctx->nhgid)
+ cur += snprintf(cur, end - cur, ", nhgid: %u", *ctx->nhgid);
+ for (i = 0; i < ctx->num_nhs; i++) {
+ cur += snprintf(cur, end - cur, "\n ");
+ nh = &ctx->nhs[i];
+
+ if (nh->gateway) {
+ cur += snprintf(cur, end - cur, " %s",
+ addr_to_s(rtmsg->rtm_family,
+ RTA_DATA(nh->gateway)));
+ }
+
+ if (nh->if_index) {
+ cur += snprintf(cur, end - cur, " via interface %d",
+ nh->if_index);
+ }
+ }
+
+ return cur - buf;
+}
+
+/*
+ * print_netlink_msg_ctx
+ */
+static void print_netlink_msg_ctx(struct netlink_msg_ctx *ctx)
+{
+ char buf[1024];
+
+ netlink_msg_ctx_snprint(ctx, buf, sizeof(buf));
+ printf("%s\n", buf);
+}
+
+/*
+ * parse_netlink_msg
+ */
+static void parse_netlink_msg(char *buf, size_t buf_len, fpm_msg_hdr_t *fpm)
+{
+ struct netlink_msg_ctx ctx_space, *ctx;
+ struct nlmsghdr *hdr;
+ unsigned int len;
+
+ ctx = &ctx_space;
+
+ hdr = (struct nlmsghdr *)buf;
+ len = buf_len;
+ for (; NLMSG_OK(hdr, len); hdr = NLMSG_NEXT(hdr, len)) {
+
+ netlink_msg_ctx_init(ctx);
+ ctx->hdr = (struct nlmsghdr *)buf;
+
+ switch (hdr->nlmsg_type) {
+
+ case RTM_DELROUTE:
+ case RTM_NEWROUTE:
+
+ parse_route_msg(ctx);
+ if (ctx->err_msg) {
+ fprintf(stderr,
+ "Error parsing route message: %s\n",
+ ctx->err_msg);
+ }
+
+ print_netlink_msg_ctx(ctx);
+
+ if (glob->reflect && hdr->nlmsg_type == RTM_NEWROUTE &&
+ ctx->rtmsg->rtm_protocol > RTPROT_STATIC) {
+ printf(" Route %s(%u) reflecting back\n",
+ netlink_prot_to_s(
+ ctx->rtmsg->rtm_protocol),
+ ctx->rtmsg->rtm_protocol);
+ ctx->rtmsg->rtm_flags |= RTM_F_OFFLOAD;
+ write(glob->sock, fpm, fpm_msg_len(fpm));
+ }
+ break;
+
+ default:
+ fprintf(stdout,
+ "Ignoring netlink message - Type: %s(%d)\n",
+ netlink_msg_type_to_s(hdr->nlmsg_type),
+ hdr->nlmsg_type);
+ }
+ }
+}
+
+/*
+ * process_fpm_msg
+ */
+static void process_fpm_msg(fpm_msg_hdr_t *hdr)
+{
+ fprintf(stdout, "FPM message - Type: %d, Length %d\n", hdr->msg_type,
+ ntohs(hdr->msg_len));
+
+ if (hdr->msg_type != FPM_MSG_TYPE_NETLINK) {
+ fprintf(stderr, "Unknown fpm message type %u\n", hdr->msg_type);
+ return;
+ }
+
+ parse_netlink_msg(fpm_msg_data(hdr), fpm_msg_data_len(hdr), hdr);
+}
+
+/*
+ * fpm_serve
+ */
+static void fpm_serve(void)
+{
+ char buf[FPM_MAX_MSG_LEN * 4];
+ fpm_msg_hdr_t *hdr;
+
+ while (1) {
+
+ hdr = read_fpm_msg(buf, sizeof(buf));
+ if (!hdr)
+ return;
+
+ process_fpm_msg(hdr);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ pid_t daemon;
+ int r;
+ bool fork_daemon = false;
+
+ memset(glob, 0, sizeof(*glob));
+
+ while ((r = getopt(argc, argv, "rd")) != -1) {
+ switch (r) {
+ case 'r':
+ glob->reflect = true;
+ break;
+ case 'd':
+ fork_daemon = true;
+ break;
+ }
+ }
+
+ if (fork_daemon) {
+ daemon = fork();
+
+ if (daemon)
+ exit(0);
+ }
+
+ if (!create_listen_sock(FPM_DEFAULT_PORT, &glob->server_sock))
+ exit(1);
+
+ /*
+ * Server forever.
+ */
+ while (1) {
+ glob->sock = accept_conn(glob->server_sock);
+ fpm_serve();
+ fprintf(stdout, "Done serving client");
+ }
+}
+#else
+
+int main(int argc, char **argv)
+{
+ fprintf(stderr, "This program only works on linux");
+ exit(-1);
+}
+#endif
diff --git a/zebra/ge_netlink.c b/zebra/ge_netlink.c
new file mode 100644
index 0000000000..e7d2e6b12a
--- /dev/null
+++ b/zebra/ge_netlink.c
@@ -0,0 +1,369 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Generic Netlink functions.
+ * Copyright (C) 2022, Carmine Scarpitta
+ */
+
+#include <zebra.h>
+
+#ifdef HAVE_NETLINK
+
+/* The following definition is to workaround an issue in the Linux kernel
+ * header files with redefinition of 'struct in6_addr' in both
+ * netinet/in.h and linux/in6.h.
+ * Reference - https://sourceware.org/ml/libc-alpha/2013-01/msg00599.html
+ */
+#define _LINUX_IN6_H
+
+#include <linux/genetlink.h>
+#include <linux/rtnetlink.h>
+#include <linux/seg6_genl.h>
+
+#include "lib/ns.h"
+#include "zebra/ge_netlink.h"
+#include "zebra/debug.h"
+#include "zebra/kernel_netlink.h"
+#include "zebra/zebra_router.h"
+#include "zebra/zebra_srv6.h"
+
+
+/**
+ * This file provides an implementation of the functionality exposed by the
+ * kernel through the Generic Netlink mechanism.
+ *
+ * Supported features include the ability to configure the source address used
+ * for SRv6 encapsulation ('sr tunsrc' in kernel terminology).
+ *
+ * At the time of writing this code, the kernel does not send us any asynchronous
+ * notifications when someone changes the 'sr tunsrc' under us. As a result, we
+ * are currently unable to detect when the source address changes and update the
+ * SRv6 encapsulation source address configured in zebra.
+ *
+ * In the future, when the kernel supports async notifications, the implementation
+ * can be improved by listening on the Generic Netlink socket and adding a handler
+ * to process/parse incoming 'sr tunsrc' change messages and update the SRv6 zebra
+ * configuration with the new encap source address.
+ */
+
+
+/*
+ * Numeric family identifier used to configure SRv6 internal parameters through Generic Netlink.
+ */
+static int16_t seg6_genl_family = -1;
+
+static int genl_parse_getfamily(struct nlmsghdr *h, ns_id_t ns_id, int startup)
+{
+ int len;
+ struct rtattr *tb[CTRL_ATTR_MAX + 1];
+ struct genlmsghdr *ghdr = NLMSG_DATA(h);
+ struct rtattr *attrs;
+ const char *family;
+
+ if (h->nlmsg_type != GENL_ID_CTRL) {
+ zlog_err(
+ "Not a controller message, nlmsg_len=%d nlmsg_type=0x%x",
+ h->nlmsg_len, h->nlmsg_type);
+ return 0;
+ }
+
+ len = h->nlmsg_len - NLMSG_LENGTH(GENL_HDRLEN);
+ if (len < 0) {
+ zlog_err(
+ "Message received from netlink is of a broken size %d %zu",
+ h->nlmsg_len, (size_t)NLMSG_LENGTH(GENL_HDRLEN));
+ return -1;
+ }
+
+ if (ghdr->cmd != CTRL_CMD_NEWFAMILY) {
+ zlog_err("Unknown controller command %d", ghdr->cmd);
+ return -1;
+ }
+
+ attrs = (struct rtattr *)((char *)ghdr + GENL_HDRLEN);
+ netlink_parse_rtattr(tb, CTRL_ATTR_MAX, attrs, len);
+
+ if (tb[CTRL_ATTR_FAMILY_ID] == NULL) {
+ zlog_err("Missing family id TLV");
+ return -1;
+ }
+
+ if (tb[CTRL_ATTR_FAMILY_NAME] == NULL) {
+ zlog_err("Missing family name TLV");
+ return -1;
+ }
+
+ family = (char *)RTA_DATA(tb[CTRL_ATTR_FAMILY_NAME]);
+
+ if (strmatch(family, "SEG6"))
+ seg6_genl_family =
+ *(int16_t *)RTA_DATA(tb[CTRL_ATTR_FAMILY_ID]);
+ else {
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_err("Unsupported Generic Netlink family '%s'",
+ family);
+ return -1;
+ }
+
+ return 0;
+}
+
+int genl_resolve_family(const char *family)
+{
+ struct zebra_ns *zns;
+ struct genl_request req;
+
+ memset(&req, 0, sizeof(req));
+
+ zns = zebra_ns_lookup(NS_DEFAULT);
+
+ req.n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
+ req.n.nlmsg_flags = NLM_F_REQUEST;
+ req.n.nlmsg_type = GENL_ID_CTRL;
+
+ req.n.nlmsg_pid = zns->ge_netlink_cmd.snl.nl_pid;
+
+ req.g.cmd = CTRL_CMD_GETFAMILY;
+ req.g.version = 0;
+
+ if (!nl_attr_put(&req.n, sizeof(req), CTRL_ATTR_FAMILY_NAME, family,
+ strlen(family) + 1))
+ return -1;
+
+ return ge_netlink_talk(genl_parse_getfamily, &req.n, zns, false);
+}
+
+/*
+ * sr tunsrc change via netlink interface, using a dataplane context object
+ *
+ * Returns -1 on failure, 0 when the msg doesn't fit entirely in the buffer
+ * otherwise the number of bytes written to buf.
+ */
+ssize_t netlink_sr_tunsrc_set_msg_encode(int cmd, struct zebra_dplane_ctx *ctx,
+ void *buf, size_t buflen)
+{
+ struct nlsock *nl;
+ const struct in6_addr *tunsrc_addr;
+ struct genl_request *req = buf;
+
+ if (seg6_genl_family < 0) {
+ zlog_err(
+ "Failed to set SRv6 source address: kernel does not support 'SEG6' Generic Netlink family.");
+ return -1;
+ }
+
+ tunsrc_addr = dplane_ctx_get_srv6_encap_srcaddr(ctx);
+ if (!tunsrc_addr)
+ return -1;
+
+ if (buflen < sizeof(*req))
+ return 0;
+
+ nl = kernel_netlink_nlsock_lookup(dplane_ctx_get_ns_sock(ctx));
+
+ memset(req, 0, sizeof(*req));
+
+ req->n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
+ req->n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+
+ /* Prepare Netlink request to set tunsrc addr */
+ req->n.nlmsg_type = seg6_genl_family;
+ req->n.nlmsg_pid = nl->snl.nl_pid;
+
+ req->g.cmd = cmd;
+ req->g.version = SEG6_GENL_VERSION;
+
+ switch (cmd) {
+ case SEG6_CMD_SET_TUNSRC:
+ if (!nl_attr_put(&req->n, buflen, SEG6_ATTR_DST, tunsrc_addr,
+ sizeof(struct in6_addr)))
+ return 0;
+ break;
+ default:
+ zlog_err("Unsupported command (%u)", cmd);
+ return -1;
+ }
+
+ return NLMSG_ALIGN(req->n.nlmsg_len);
+}
+
+ssize_t netlink_sr_tunsrc_set_msg_encoder(struct zebra_dplane_ctx *ctx,
+ void *buf, size_t buflen)
+{
+ enum dplane_op_e op;
+ int cmd = 0;
+
+ op = dplane_ctx_get_op(ctx);
+
+ /* Call to netlink layer based on type of operation */
+ if (op == DPLANE_OP_SRV6_ENCAP_SRCADDR_SET) {
+ /* Validate */
+ if (dplane_ctx_get_srv6_encap_srcaddr(ctx) == NULL) {
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(
+ "sr tunsrc set failed: SRv6 encap source address not set");
+ return -1;
+ }
+
+ cmd = SEG6_CMD_SET_TUNSRC;
+ } else {
+ /* Invalid op */
+ zlog_err("Context received for kernel sr tunsrc update with incorrect OP code (%u)",
+ op);
+ return -1;
+ }
+
+ return netlink_sr_tunsrc_set_msg_encode(cmd, ctx, buf, buflen);
+}
+
+enum netlink_msg_status
+netlink_put_sr_tunsrc_set_msg(struct nl_batch *bth, struct zebra_dplane_ctx *ctx)
+{
+ enum dplane_op_e op;
+ struct zebra_ns *zns;
+ struct genl_request req;
+
+ op = dplane_ctx_get_op(ctx);
+ assert(op == DPLANE_OP_SRV6_ENCAP_SRCADDR_SET);
+
+ netlink_sr_tunsrc_set_msg_encoder(ctx, &req, sizeof(req));
+
+ zns = zebra_ns_lookup(dplane_ctx_get_ns_sock(ctx));
+
+ return ge_netlink_talk(netlink_talk_filter, &req.n, zns, false);
+}
+
+/**
+ * netlink_sr_tunsrc_reply_read() - Read in SR tunsrc reply from the kernel
+ *
+ * @h: Netlink message header
+ * @ns_id: Namspace id
+ * @startup: Are we reading under startup conditions?
+ *
+ * Return: Result status
+ */
+int netlink_sr_tunsrc_reply_read(struct nlmsghdr *h, ns_id_t ns_id, int startup)
+{
+ int len;
+ struct genlmsghdr *ghdr;
+ struct rtattr *tb[SEG6_ATTR_MAX + 1] = {};
+ struct rtattr *attrs;
+
+ if (h->nlmsg_type != seg6_genl_family)
+ return 0;
+
+ len = h->nlmsg_len - NLMSG_LENGTH(GENL_HDRLEN);
+ if (len < 0) {
+ zlog_warn("%s: Message received from netlink is of a broken size %d %zu",
+ __func__, h->nlmsg_len,
+ (size_t)NLMSG_LENGTH(GENL_HDRLEN));
+ return -1;
+ }
+
+ ghdr = NLMSG_DATA(h);
+
+ if (ghdr->cmd != SEG6_CMD_GET_TUNSRC)
+ return 0;
+
+ attrs = (struct rtattr *)((char *)ghdr + GENL_HDRLEN);
+ netlink_parse_rtattr(tb, SEG6_ATTR_MAX, attrs, len);
+
+ if (tb[SEG6_ATTR_DST] == NULL) {
+ zlog_err("Missing tunsrc addr");
+ return -1;
+ }
+
+ zebra_srv6_encap_src_addr_set(
+ (struct in6_addr *)RTA_DATA(tb[SEG6_ATTR_DST]));
+
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("%s: SRv6 encap source address received from kernel: '%pI6'",
+ __func__,
+ (struct in6_addr *)RTA_DATA(tb[SEG6_ATTR_DST]));
+
+ return 0;
+}
+
+/**
+ * netlink_request_sr_tunsrc() - Request SR tunsrc from the kernel
+ * @zns: Zebra namespace
+ *
+ * Return: Result status
+ */
+static int netlink_request_sr_tunsrc(struct zebra_ns *zns)
+{
+ struct genl_request req;
+
+ if (zns->ge_netlink_cmd.sock < 0)
+ return -1;
+
+ if (seg6_genl_family < 0) {
+ zlog_err(
+ "Failed to get SRv6 encap source address: kernel does not support 'SEG6' Generic Netlink family.");
+ return -1;
+ }
+
+ /* Form the request, specifying filter (rtattr) if needed. */
+ memset(&req, 0, sizeof(req));
+ req.n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
+ req.n.nlmsg_flags = NLM_F_REQUEST;
+ req.n.nlmsg_type = seg6_genl_family;
+ req.g.cmd = SEG6_CMD_GET_TUNSRC;
+ req.g.version = SEG6_GENL_VERSION;
+
+ return netlink_request(&zns->ge_netlink_cmd, &req);
+}
+
+/**
+ * SR tunsrc read function using netlink interface. Only called
+ * on bootstrap time.
+ */
+int netlink_sr_tunsrc_read(struct zebra_ns *zns)
+{
+ int ret;
+ struct zebra_dplane_info dp_info;
+
+ if (zns->ge_netlink_cmd.sock < 0)
+ return -1;
+
+ /* Capture info in intermediate info struct */
+ dp_info.ns_id = zns->ns_id;
+ dp_info.is_cmd = true;
+ dp_info.sock = zns->ge_netlink_cmd.sock;
+ dp_info.seq = zns->ge_netlink_cmd.seq;
+
+ /* Get SR tunsrc. */
+ ret = netlink_request_sr_tunsrc(zns);
+ if (ret < 0)
+ return ret;
+ ret = netlink_parse_info(netlink_sr_tunsrc_reply_read,
+ &zns->ge_netlink_cmd, &dp_info, 0, true);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+void ge_netlink_init(struct zebra_ns *zns)
+{
+ if (zns->ge_netlink_cmd.sock < 0)
+ return;
+
+ /*
+ * Resolves the 'seg6' Generic Netlink family name to the corresponding numeric family identifier.
+ * This will give us the numeric family identifier required to send 'seg6' commands to the kernel
+ * over the Generic Netlink socket. 'seg6' commands are used to configure SRv6 internal parameters
+ * such as the address to use as source for encapsulated packets.
+ */
+ if (genl_resolve_family("SEG6"))
+ zlog_warn(
+ "Kernel does not support 'SEG6' Generic Netlink family. Any attempt to set the encapsulation parameters under the SRv6 configuration will fail");
+
+ /**
+ * Retrieve the actual SRv6 encap source address from the kernel
+ * (default namespace) and save it to zebra SRv6 config
+ */
+ if (zns->ns_id == NS_DEFAULT)
+ netlink_sr_tunsrc_read(zns);
+}
+
+#endif /* HAVE_NETLINK */
diff --git a/zebra/ge_netlink.h b/zebra/ge_netlink.h
new file mode 100644
index 0000000000..20d09116c0
--- /dev/null
+++ b/zebra/ge_netlink.h
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Header file exported by ge_netlink.c to zebra.
+ * Copyright (C) 2022, Carmine Scarpitta
+ */
+
+#ifndef _ZEBRA_GE_NETLINK_H
+#define _ZEBRA_GE_NETLINK_H
+
+#include "zebra_dplane.h"
+
+#ifdef HAVE_NETLINK
+
+#include <linux/genetlink.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Generic Netlink request message */
+struct genl_request {
+ struct nlmsghdr n;
+ struct genlmsghdr g;
+ char buf[1024];
+};
+
+extern int genl_resolve_family(const char *family);
+extern ssize_t netlink_sr_tunsrc_set_msg_encode(int cmd,
+ struct zebra_dplane_ctx *ctx,
+ void *buf, size_t buflen);
+extern ssize_t netlink_sr_tunsrc_set_msg_encoder(struct zebra_dplane_ctx *ctx,
+ void *buf, size_t buflen);
+struct nl_batch;
+extern enum netlink_msg_status
+netlink_put_sr_tunsrc_set_msg(struct nl_batch *bth,
+ struct zebra_dplane_ctx *ctx);
+
+int netlink_sr_tunsrc_reply_read(struct nlmsghdr *h, ns_id_t ns_id, int startup);
+int netlink_sr_tunsrc_read(struct zebra_ns *zns);
+
+extern void ge_netlink_init(struct zebra_ns *zns);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAVE_NETLINK */
+
+#endif /* _ZEBRA_GE_NETLINK_H */
diff --git a/zebra/if_ioctl.c b/zebra/if_ioctl.c
index b3cf865122..d0aa2167fe 100644
--- a/zebra/if_ioctl.c
+++ b/zebra/if_ioctl.c
@@ -5,6 +5,7 @@
*/
#include <zebra.h>
+#include <sys/ioctl.h>
#ifdef OPEN_BSD
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index 3a325df06c..5f096e3039 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -17,6 +17,8 @@
#define _LINUX_IF_H
#define _LINUX_IP_H
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
#include <netinet/if_ether.h>
#include <linux/if_bridge.h>
#include <linux/if_link.h>
@@ -63,66 +65,22 @@
#include "zebra/zebra_trace.h"
extern struct zebra_privs_t zserv_privs;
-uint8_t frr_protodown_r_bit = FRR_PROTODOWN_REASON_DEFAULT_BIT;
-
-/* Note: on netlink systems, there should be a 1-to-1 mapping between interface
- names and ifindex values. */
-static void set_ifindex(struct interface *ifp, ifindex_t ifi_index,
- struct zebra_ns *zns)
-{
- struct interface *oifp;
-
- if (((oifp = if_lookup_by_index_per_ns(zns, ifi_index)) != NULL)
- && (oifp != ifp)) {
- if (ifi_index == IFINDEX_INTERNAL)
- flog_err(
- EC_LIB_INTERFACE,
- "Netlink is setting interface %s ifindex to reserved internal value %u",
- ifp->name, ifi_index);
- else {
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug(
- "interface index %d was renamed from %s to %s",
- ifi_index, oifp->name, ifp->name);
- if (if_is_up(oifp))
- flog_err(
- EC_LIB_INTERFACE,
- "interface rename detected on up interface: index %d was renamed from %s to %s, results are uncertain!",
- ifi_index, oifp->name, ifp->name);
- if_delete_update(&oifp);
- }
- }
- if_set_index(ifp, ifi_index);
-}
/* Utility function to parse hardware link-layer address and update ifp */
static void netlink_interface_update_hw_addr(struct rtattr **tb,
- struct interface *ifp)
+ struct zebra_dplane_ctx *ctx)
{
- int i;
-
if (tb[IFLA_ADDRESS]) {
int hw_addr_len;
hw_addr_len = RTA_PAYLOAD(tb[IFLA_ADDRESS]);
if (hw_addr_len > INTERFACE_HWADDR_MAX)
- zlog_debug("Hardware address is too large: %d",
- hw_addr_len);
- else {
- ifp->hw_addr_len = hw_addr_len;
- memcpy(ifp->hw_addr, RTA_DATA(tb[IFLA_ADDRESS]),
- hw_addr_len);
-
- for (i = 0; i < hw_addr_len; i++)
- if (ifp->hw_addr[i] != 0)
- break;
-
- if (i == hw_addr_len)
- ifp->hw_addr_len = 0;
- else
- ifp->hw_addr_len = hw_addr_len;
- }
+ zlog_warn("Hardware address is too large: %d",
+ hw_addr_len);
+ else
+ dplane_ctx_set_ifp_hw_addr(ctx, hw_addr_len,
+ RTA_DATA(tb[IFLA_ADDRESS]));
}
}
@@ -237,26 +195,6 @@ static enum zebra_link_type netlink_to_zebra_link_type(unsigned int hwt)
}
}
-static inline void zebra_if_set_ziftype(struct interface *ifp,
- enum zebra_iftype zif_type,
- enum zebra_slave_iftype zif_slave_type)
-{
- struct zebra_if *zif;
-
- zif = (struct zebra_if *)ifp->info;
- zif->zif_slave_type = zif_slave_type;
-
- if (zif->zif_type != zif_type) {
- zif->zif_type = zif_type;
- /* If the if_type has been set to bond initialize ES info
- * against it. XXX - note that we don't handle the case where
- * a zif changes from bond to non-bond; it is really
- * an unexpected/error condition.
- */
- zebra_evpn_if_init(zif);
- }
-}
-
static void netlink_determine_zebra_iftype(const char *kind,
enum zebra_iftype *zif_type)
{
@@ -279,23 +217,18 @@ static void netlink_determine_zebra_iftype(const char *kind,
*zif_type = ZEBRA_IF_VETH;
else if (strcmp(kind, "bond") == 0)
*zif_type = ZEBRA_IF_BOND;
- else if (strcmp(kind, "bond_slave") == 0)
- *zif_type = ZEBRA_IF_BOND_SLAVE;
+ else if (strcmp(kind, "team") == 0)
+ *zif_type = ZEBRA_IF_BOND;
else if (strcmp(kind, "gre") == 0)
*zif_type = ZEBRA_IF_GRE;
}
static void netlink_vrf_change(struct nlmsghdr *h, struct rtattr *tb,
- uint32_t ns_id, const char *name)
+ uint32_t ns_id, const char *name,
+ struct zebra_dplane_ctx *ctx)
{
- struct ifinfomsg *ifi;
struct rtattr *linkinfo[IFLA_INFO_MAX + 1];
struct rtattr *attr[IFLA_VRF_MAX + 1];
- struct vrf *vrf = NULL;
- struct zebra_vrf *zvrf;
- uint32_t nl_table_id;
-
- ifi = NLMSG_DATA(h);
netlink_parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb);
@@ -317,74 +250,8 @@ static void netlink_vrf_change(struct nlmsghdr *h, struct rtattr *tb,
return;
}
- nl_table_id = *(uint32_t *)RTA_DATA(attr[IFLA_VRF_TABLE]);
-
- if (h->nlmsg_type == RTM_NEWLINK) {
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("RTM_NEWLINK for VRF %s(%u) table %u", name,
- ifi->ifi_index, nl_table_id);
-
- if (!vrf_lookup_by_id((vrf_id_t)ifi->ifi_index)) {
- vrf_id_t exist_id;
-
- exist_id = vrf_lookup_by_table(nl_table_id, ns_id);
- if (exist_id != VRF_DEFAULT) {
- vrf = vrf_lookup_by_id(exist_id);
-
- flog_err(
- EC_ZEBRA_VRF_MISCONFIGURED,
- "VRF %s id %u table id overlaps existing vrf %s, misconfiguration exiting",
- name, ifi->ifi_index, vrf->name);
- exit(-1);
- }
- }
-
- vrf = vrf_update((vrf_id_t)ifi->ifi_index, name);
- if (!vrf) {
- flog_err(EC_LIB_INTERFACE, "VRF %s id %u not created",
- name, ifi->ifi_index);
- return;
- }
-
- /*
- * This is the only place that we get the actual kernel table_id
- * being used. We need it to set the table_id of the routes
- * we are passing to the kernel.... And to throw some totally
- * awesome parties. that too.
- *
- * At this point we *must* have a zvrf because the vrf_create
- * callback creates one. We *must* set the table id
- * before the vrf_enable because of( at the very least )
- * static routes being delayed for installation until
- * during the vrf_enable callbacks.
- */
- zvrf = (struct zebra_vrf *)vrf->info;
- zvrf->table_id = nl_table_id;
-
- /* Enable the created VRF. */
- if (!vrf_enable(vrf)) {
- flog_err(EC_LIB_INTERFACE,
- "Failed to enable VRF %s id %u", name,
- ifi->ifi_index);
- return;
- }
-
- } else // h->nlmsg_type == RTM_DELLINK
- {
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("RTM_DELLINK for VRF %s(%u)", name,
- ifi->ifi_index);
-
- vrf = vrf_lookup_by_id((vrf_id_t)ifi->ifi_index);
-
- if (!vrf) {
- flog_warn(EC_ZEBRA_VRF_NOT_FOUND, "%s: vrf not found",
- __func__);
- return;
- }
-
- vrf_delete(vrf);
- }
+ dplane_ctx_set_ifp_table_id(
+ ctx, *(uint32_t *)RTA_DATA(attr[IFLA_VRF_TABLE]));
}
static uint32_t get_iflink_speed(struct interface *interface, int *error)
@@ -394,6 +261,7 @@ static uint32_t get_iflink_speed(struct interface *interface, int *error)
int sd;
int rc;
const char *ifname = interface->name;
+ uint32_t ret;
if (error)
*error = 0;
@@ -418,7 +286,7 @@ static uint32_t get_iflink_speed(struct interface *interface, int *error)
ifname, errno, safe_strerror(errno));
/* no vrf socket creation may probably mean vrf issue */
if (error)
- *error = -1;
+ *error = INTERFACE_SPEED_ERROR_READ;
return 0;
}
/* Get the current link state for the interface */
@@ -432,14 +300,20 @@ static uint32_t get_iflink_speed(struct interface *interface, int *error)
ifname, errno, safe_strerror(errno));
/* no device means interface unreachable */
if (errno == ENODEV && error)
- *error = -1;
+ *error = INTERFACE_SPEED_ERROR_READ;
ecmd.speed_hi = 0;
ecmd.speed = 0;
}
close(sd);
- return ((uint32_t)ecmd.speed_hi << 16) | ecmd.speed;
+ ret = ((uint32_t)ecmd.speed_hi << 16) | ecmd.speed;
+ if (ret == UINT32_MAX) {
+ if (error)
+ *error = INTERFACE_SPEED_ERROR_UNKNOWN;
+ ret = 0;
+ }
+ return ret;
}
uint32_t kernel_get_speed(struct interface *ifp, int *error)
@@ -665,62 +539,59 @@ static int netlink_extract_vxlan_info(struct rtattr *link_data,
* bridge interface is added or updated, take further actions to map
* its members. Likewise, for VxLAN interface.
*/
-static void netlink_interface_update_l2info(struct interface *ifp,
+static void netlink_interface_update_l2info(struct zebra_dplane_ctx *ctx,
+ enum zebra_iftype zif_type,
struct rtattr *link_data, int add,
ns_id_t link_nsid)
{
+ struct zebra_l2info_bridge bridge_info;
+ struct zebra_l2info_vlan vlan_info;
+ struct zebra_l2info_vxlan vxlan_info;
+ struct zebra_l2info_gre gre_info;
+
if (!link_data)
return;
- if (IS_ZEBRA_IF_BRIDGE(ifp)) {
- struct zebra_l2info_bridge bridge_info;
-
+ switch (zif_type) {
+ case ZEBRA_IF_BRIDGE:
netlink_extract_bridge_info(link_data, &bridge_info);
- zebra_l2_bridge_add_update(ifp, &bridge_info, add);
- } else if (IS_ZEBRA_IF_VLAN(ifp)) {
- struct zebra_l2info_vlan vlan_info;
-
+ dplane_ctx_set_ifp_bridge_info(ctx, &bridge_info);
+ break;
+ case ZEBRA_IF_VLAN:
netlink_extract_vlan_info(link_data, &vlan_info);
- zebra_l2_vlanif_update(ifp, &vlan_info);
- zebra_evpn_acc_bd_svi_set(ifp->info, NULL,
- !!if_is_operative(ifp));
- } else if (IS_ZEBRA_IF_VXLAN(ifp)) {
- struct zebra_l2info_vxlan vxlan_info;
-
+ dplane_ctx_set_ifp_vlan_info(ctx, &vlan_info);
+ break;
+ case ZEBRA_IF_VXLAN:
netlink_extract_vxlan_info(link_data, &vxlan_info);
vxlan_info.link_nsid = link_nsid;
- zebra_l2_vxlanif_add_update(ifp, &vxlan_info, add);
- if (link_nsid != NS_UNKNOWN &&
- vxlan_info.ifindex_link)
- zebra_if_update_link(ifp, vxlan_info.ifindex_link,
- link_nsid);
- } else if (IS_ZEBRA_IF_GRE(ifp)) {
- struct zebra_l2info_gre gre_info;
-
+ dplane_ctx_set_ifp_vxlan_info(ctx, &vxlan_info);
+ break;
+ case ZEBRA_IF_GRE:
netlink_extract_gre_info(link_data, &gre_info);
gre_info.link_nsid = link_nsid;
- zebra_l2_greif_add_update(ifp, &gre_info, add);
- if (link_nsid != NS_UNKNOWN &&
- gre_info.ifindex_link)
- zebra_if_update_link(ifp, gre_info.ifindex_link,
- link_nsid);
+ dplane_ctx_set_ifp_gre_info(ctx, &gre_info);
+ break;
+ case ZEBRA_IF_OTHER:
+ case ZEBRA_IF_VRF:
+ case ZEBRA_IF_MACVLAN:
+ case ZEBRA_IF_VETH:
+ case ZEBRA_IF_BOND:
+ break;
}
}
-static int netlink_bridge_vxlan_vlan_vni_map_update(struct interface *ifp,
- struct rtattr *af_spec)
+static int
+netlink_bridge_vxlan_vlan_vni_map_update(struct zebra_dplane_ctx *ctx,
+ struct rtattr *af_spec)
{
int rem;
- vni_t vni_id;
- vlanid_t vid;
uint16_t flags;
struct rtattr *i;
- struct zebra_vxlan_vni vni;
- struct zebra_vxlan_vni *vnip;
- struct hash *vni_table = NULL;
+ struct zebra_vxlan_vni_array *vniarray = NULL;
struct zebra_vxlan_vni vni_end;
struct zebra_vxlan_vni vni_start;
struct rtattr *aftb[IFLA_BRIDGE_VLAN_TUNNEL_MAX + 1];
+ int32_t count = 0;
memset(&vni_start, 0, sizeof(vni_start));
memset(&vni_end, 0, sizeof(vni_end));
@@ -739,204 +610,126 @@ static int netlink_bridge_vxlan_vlan_vni_map_update(struct interface *ifp,
/* vlan-vni info missing */
return 0;
+ count++;
flags = 0;
- memset(&vni, 0, sizeof(vni));
+ vniarray = XREALLOC(
+ MTYPE_TMP, vniarray,
+ sizeof(struct zebra_vxlan_vni_array) +
+ count * sizeof(struct zebra_vxlan_vni));
- vni.vni = *(vni_t *)RTA_DATA(aftb[IFLA_BRIDGE_VLAN_TUNNEL_ID]);
- vni.access_vlan = *(vlanid_t *)RTA_DATA(
+ memset(&vniarray->vnis[count - 1], 0,
+ sizeof(struct zebra_vxlan_vni));
+
+ vniarray->vnis[count - 1].vni =
+ *(vni_t *)RTA_DATA(aftb[IFLA_BRIDGE_VLAN_TUNNEL_ID]);
+ vniarray->vnis[count - 1].access_vlan = *(vlanid_t *)RTA_DATA(
aftb[IFLA_BRIDGE_VLAN_TUNNEL_VID]);
if (aftb[IFLA_BRIDGE_VLAN_TUNNEL_FLAGS])
flags = *(uint16_t *)RTA_DATA(
aftb[IFLA_BRIDGE_VLAN_TUNNEL_FLAGS]);
- if (flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) {
- vni_start = vni;
- continue;
- }
-
- if (flags & BRIDGE_VLAN_INFO_RANGE_END)
- vni_end = vni;
-
- if (!(flags & BRIDGE_VLAN_INFO_RANGE_END)) {
- vni_start = vni;
- vni_end = vni;
- }
-
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug(
- "Vlan-Vni(%d:%d-%d:%d) update for VxLAN IF %s(%u)",
- vni_start.access_vlan, vni_end.access_vlan,
- vni_start.vni, vni_end.vni, ifp->name,
- ifp->ifindex);
-
- if (!vni_table) {
- vni_table = zebra_vxlan_vni_table_create();
- if (!vni_table)
- return 0;
- }
-
- for (vid = vni_start.access_vlan, vni_id = vni_start.vni;
- vid <= vni_end.access_vlan; vid++, vni_id++) {
-
- memset(&vni, 0, sizeof(vni));
- vni.vni = vni_id;
- vni.access_vlan = vid;
- vnip = hash_get(vni_table, &vni, zebra_vxlan_vni_alloc);
- if (!vnip)
- return 0;
- }
-
- memset(&vni_start, 0, sizeof(vni_start));
- memset(&vni_end, 0, sizeof(vni_end));
+ vniarray->vnis[count - 1].flags = flags;
}
- if (vni_table)
- zebra_vxlan_if_vni_table_add_update(ifp, vni_table);
-
+ if (count) {
+ vniarray->count = count;
+ dplane_ctx_set_ifp_vxlan_vni_array(ctx, vniarray);
+ }
return 0;
}
-static int netlink_bridge_vxlan_update(struct interface *ifp,
- struct rtattr *af_spec)
+static int netlink_bridge_vxlan_update(struct zebra_dplane_ctx *ctx,
+ struct rtattr *af_spec)
{
struct rtattr *aftb[IFLA_BRIDGE_MAX + 1];
struct bridge_vlan_info *vinfo;
- struct zebra_if *zif;
- vlanid_t access_vlan;
+ struct zebra_dplane_bridge_vlan_info bvinfo;
- if (!af_spec)
+ if (!af_spec) {
+ dplane_ctx_set_ifp_no_afspec(ctx);
return 0;
+ }
- zif = (struct zebra_if *)ifp->info;
-
- /* Single vxlan devices has vni-vlan range to update */
- if (IS_ZEBRA_VXLAN_IF_SVD(zif))
- return netlink_bridge_vxlan_vlan_vni_map_update(ifp, af_spec);
+ netlink_bridge_vxlan_vlan_vni_map_update(ctx, af_spec);
/* There is a 1-to-1 mapping of VLAN to VxLAN - hence
* only 1 access VLAN is accepted.
*/
netlink_parse_rtattr_nested(aftb, IFLA_BRIDGE_MAX, af_spec);
- if (!aftb[IFLA_BRIDGE_VLAN_INFO])
+ if (!aftb[IFLA_BRIDGE_VLAN_INFO]) {
+ dplane_ctx_set_ifp_no_bridge_vlan_info(ctx);
return 0;
+ }
vinfo = RTA_DATA(aftb[IFLA_BRIDGE_VLAN_INFO]);
- if (!(vinfo->flags & BRIDGE_VLAN_INFO_PVID))
- return 0;
+ bvinfo.flags = vinfo->flags;
+ bvinfo.vid = vinfo->vid;
- access_vlan = (vlanid_t)vinfo->vid;
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("Access VLAN %u for VxLAN IF %s(%u)", access_vlan,
- ifp->name, ifp->ifindex);
- zebra_l2_vxlanif_update_access_vlan(ifp, access_vlan);
+ dplane_ctx_set_ifp_bridge_vlan_info(ctx, &bvinfo);
return 0;
}
-static void netlink_bridge_vlan_update(struct interface *ifp,
- struct rtattr *af_spec)
+static void netlink_bridge_vlan_update(struct zebra_dplane_ctx *ctx,
+ struct rtattr *af_spec)
{
struct rtattr *i;
int rem;
- uint16_t vid_range_start = 0;
- struct zebra_if *zif;
- bitfield_t old_vlan_bitmap;
struct bridge_vlan_info *vinfo;
-
- zif = (struct zebra_if *)ifp->info;
-
- /* cache the old bitmap addrs */
- old_vlan_bitmap = zif->vlan_bitmap;
- /* create a new bitmap space for re-eval */
- bf_init(zif->vlan_bitmap, IF_VLAN_BITMAP_MAX);
+ struct zebra_dplane_bridge_vlan_info_array *bvarray = NULL;
+ int32_t count = 0;
if (af_spec) {
for (i = RTA_DATA(af_spec), rem = RTA_PAYLOAD(af_spec);
RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
-
if (i->rta_type != IFLA_BRIDGE_VLAN_INFO)
continue;
- vinfo = RTA_DATA(i);
-
- if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) {
- vid_range_start = vinfo->vid;
- continue;
- }
-
- if (!(vinfo->flags & BRIDGE_VLAN_INFO_RANGE_END))
- vid_range_start = vinfo->vid;
+ count++;
+ bvarray = XREALLOC(
+ MTYPE_TMP, bvarray,
+ sizeof(struct
+ zebra_dplane_bridge_vlan_info_array) +
+ count * sizeof(struct
+ zebra_dplane_bridge_vlan_info));
- zebra_vlan_bitmap_compute(ifp, vid_range_start,
- vinfo->vid);
+ vinfo = RTA_DATA(i);
+ bvarray->array[count - 1].flags = vinfo->flags;
+ bvarray->array[count - 1].vid = vinfo->vid;
}
}
- zebra_vlan_mbr_re_eval(ifp, old_vlan_bitmap);
-
- bf_free(old_vlan_bitmap);
+ if (count) {
+ bvarray->count = count;
+ dplane_ctx_set_ifp_bridge_vlan_info_array(ctx, bvarray);
+ }
}
-static int netlink_bridge_interface(struct nlmsghdr *h, int len, ns_id_t ns_id,
- int startup)
+static int netlink_bridge_interface(struct zebra_dplane_ctx *ctx,
+ struct rtattr *af_spec, int startup)
{
- char *name = NULL;
- struct ifinfomsg *ifi;
- struct rtattr *tb[IFLA_MAX + 1];
- struct interface *ifp;
- struct zebra_if *zif;
- struct rtattr *af_spec;
-
- /* Fetch name and ifindex */
- ifi = NLMSG_DATA(h);
- netlink_parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
-
- if (tb[IFLA_IFNAME] == NULL)
- return -1;
- name = (char *)RTA_DATA(tb[IFLA_IFNAME]);
-
- /* The interface should already be known, if not discard. */
- ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id), ifi->ifi_index);
- if (!ifp) {
- zlog_debug("Cannot find bridge IF %s(%u)", name,
- ifi->ifi_index);
- return 0;
- }
- /* We are only interested in the access VLAN i.e., AF_SPEC */
- af_spec = tb[IFLA_AF_SPEC];
-
- if (IS_ZEBRA_IF_VXLAN(ifp))
- return netlink_bridge_vxlan_update(ifp, af_spec);
+ netlink_bridge_vxlan_update(ctx, af_spec);
/* build vlan bitmap associated with this interface if that
* device type is interested in the vlans
*/
- zif = (struct zebra_if *)ifp->info;
- if (bf_is_inited(zif->vlan_bitmap))
- netlink_bridge_vlan_update(ifp, af_spec);
+ netlink_bridge_vlan_update(ctx, af_spec);
+ dplane_provider_enqueue_to_zebra(ctx);
return 0;
}
-static bool is_if_protodown_reason_only_frr(uint32_t rc_bitfield)
-{
- /* This shouldn't be possible */
- assert(frr_protodown_r_bit < 32);
- return (rc_bitfield == (((uint32_t)1) << frr_protodown_r_bit));
-}
-
/*
* Process interface protodown dplane update.
*
* If the interface is an es bond member then it must follow EVPN's
* protodown setting.
*/
-static void netlink_proc_dplane_if_protodown(struct zebra_if *zif,
+static void netlink_proc_dplane_if_protodown(struct zebra_dplane_ctx *ctx,
struct rtattr **tb)
{
bool protodown;
- bool old_protodown;
uint32_t rc_bitfield = 0;
struct rtattr *pd_reason_info[IFLA_MAX + 1];
@@ -951,59 +744,9 @@ static void netlink_proc_dplane_if_protodown(struct zebra_if *zif,
pd_reason_info[IFLA_PROTO_DOWN_REASON_VALUE]);
}
- /*
- * Set our reason code to note it wasn't us.
- * If the reason we got from the kernel is ONLY frr though, don't
- * set it.
- */
- COND_FLAG(zif->protodown_rc, ZEBRA_PROTODOWN_EXTERNAL,
- protodown && rc_bitfield &&
- !is_if_protodown_reason_only_frr(rc_bitfield));
-
-
- old_protodown = !!ZEBRA_IF_IS_PROTODOWN(zif);
- if (protodown == old_protodown)
- return;
-
- if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("interface %s dplane change, protdown %s",
- zif->ifp->name, protodown ? "on" : "off");
-
- /* Set protodown, respectively */
- COND_FLAG(zif->flags, ZIF_FLAG_PROTODOWN, protodown);
-
- if (zebra_evpn_is_es_bond_member(zif->ifp)) {
- /* Check it's not already being sent to the dplane first */
- if (protodown &&
- CHECK_FLAG(zif->flags, ZIF_FLAG_SET_PROTODOWN)) {
- if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug(
- "bond mbr %s protodown on recv'd but already sent protodown on to the dplane",
- zif->ifp->name);
- return;
- }
-
- if (!protodown &&
- CHECK_FLAG(zif->flags, ZIF_FLAG_UNSET_PROTODOWN)) {
- if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug(
- "bond mbr %s protodown off recv'd but already sent protodown off to the dplane",
- zif->ifp->name);
- return;
- }
-
- if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug(
- "bond mbr %s reinstate protodown %s in the dplane",
- zif->ifp->name, old_protodown ? "on" : "off");
-
- if (old_protodown)
- SET_FLAG(zif->flags, ZIF_FLAG_SET_PROTODOWN);
- else
- SET_FLAG(zif->flags, ZIF_FLAG_UNSET_PROTODOWN);
-
- dplane_intf_update(zif->ifp);
- }
+ dplane_ctx_set_ifp_rc_bitfield(ctx, rc_bitfield);
+ dplane_ctx_set_ifp_protodown(ctx, protodown);
+ dplane_ctx_set_ifp_protodown_set(ctx, true);
}
static uint8_t netlink_parse_lacp_bypass(struct rtattr **linkinfo)
@@ -1020,201 +763,6 @@ static uint8_t netlink_parse_lacp_bypass(struct rtattr **linkinfo)
return bypass;
}
-/*
- * Only called at startup to cleanup leftover protodown reasons we may
- * have not cleaned up. We leave protodown set though.
- */
-static void if_sweep_protodown(struct zebra_if *zif)
-{
- bool protodown;
-
- protodown = !!ZEBRA_IF_IS_PROTODOWN(zif);
-
- if (!protodown)
- return;
-
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("interface %s sweeping protodown %s reason 0x%x",
- zif->ifp->name, protodown ? "on" : "off",
- zif->protodown_rc);
-
- /* Only clear our reason codes, leave external if it was set */
- UNSET_FLAG(zif->protodown_rc, ZEBRA_PROTODOWN_ALL);
- dplane_intf_update(zif->ifp);
-}
-
-/*
- * Called from interface_lookup_netlink(). This function is only used
- * during bootstrap.
- */
-static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup)
-{
- int len;
- struct ifinfomsg *ifi;
- struct rtattr *tb[IFLA_MAX + 1];
- struct rtattr *linkinfo[IFLA_MAX + 1];
- struct interface *ifp;
- char *name = NULL;
- char *kind = NULL;
- char *desc = NULL;
- char *slave_kind = NULL;
- struct zebra_ns *zns = NULL;
- vrf_id_t vrf_id = VRF_DEFAULT;
- enum zebra_iftype zif_type = ZEBRA_IF_OTHER;
- enum zebra_slave_iftype zif_slave_type = ZEBRA_IF_SLAVE_NONE;
- ifindex_t bridge_ifindex = IFINDEX_INTERNAL;
- ifindex_t link_ifindex = IFINDEX_INTERNAL;
- ifindex_t bond_ifindex = IFINDEX_INTERNAL;
- struct zebra_if *zif;
- ns_id_t link_nsid = ns_id;
- uint8_t bypass = 0;
-
- frrtrace(3, frr_zebra, netlink_interface, h, ns_id, startup);
-
- zns = zebra_ns_lookup(ns_id);
- ifi = NLMSG_DATA(h);
-
- if (h->nlmsg_type != RTM_NEWLINK)
- return 0;
-
- len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifinfomsg));
- if (len < 0) {
- zlog_err(
- "%s: Message received from netlink is of a broken size: %d %zu",
- __func__, h->nlmsg_len,
- (size_t)NLMSG_LENGTH(sizeof(struct ifinfomsg)));
- return -1;
- }
-
- /* We are interested in some AF_BRIDGE notifications. */
- if (ifi->ifi_family == AF_BRIDGE)
- return netlink_bridge_interface(h, len, ns_id, startup);
-
- /* Looking up interface name. */
- memset(linkinfo, 0, sizeof(linkinfo));
- netlink_parse_rtattr_flags(tb, IFLA_MAX, IFLA_RTA(ifi), len,
- NLA_F_NESTED);
-
- /* check for wireless messages to ignore */
- if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0)) {
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("%s: ignoring IFLA_WIRELESS message",
- __func__);
- return 0;
- }
-
- if (tb[IFLA_IFNAME] == NULL)
- return -1;
- name = (char *)RTA_DATA(tb[IFLA_IFNAME]);
-
- if (tb[IFLA_IFALIAS])
- desc = (char *)RTA_DATA(tb[IFLA_IFALIAS]);
-
- if (tb[IFLA_LINKINFO]) {
- netlink_parse_rtattr_nested(linkinfo, IFLA_INFO_MAX,
- tb[IFLA_LINKINFO]);
-
- if (linkinfo[IFLA_INFO_KIND])
- kind = RTA_DATA(linkinfo[IFLA_INFO_KIND]);
-
- if (linkinfo[IFLA_INFO_SLAVE_KIND])
- slave_kind = RTA_DATA(linkinfo[IFLA_INFO_SLAVE_KIND]);
-
- if ((slave_kind != NULL) && strcmp(slave_kind, "bond") == 0)
- netlink_determine_zebra_iftype("bond_slave", &zif_type);
- else
- netlink_determine_zebra_iftype(kind, &zif_type);
- }
-
- /* If VRF, create the VRF structure itself. */
- if (zif_type == ZEBRA_IF_VRF && !vrf_is_backend_netns()) {
- netlink_vrf_change(h, tb[IFLA_LINKINFO], ns_id, name);
- vrf_id = (vrf_id_t)ifi->ifi_index;
- }
-
- if (tb[IFLA_MASTER]) {
- if (slave_kind && (strcmp(slave_kind, "vrf") == 0)
- && !vrf_is_backend_netns()) {
- zif_slave_type = ZEBRA_IF_SLAVE_VRF;
- vrf_id = *(uint32_t *)RTA_DATA(tb[IFLA_MASTER]);
- } else if (slave_kind && (strcmp(slave_kind, "bridge") == 0)) {
- zif_slave_type = ZEBRA_IF_SLAVE_BRIDGE;
- bridge_ifindex =
- *(ifindex_t *)RTA_DATA(tb[IFLA_MASTER]);
- } else if (slave_kind && (strcmp(slave_kind, "bond") == 0)) {
- zif_slave_type = ZEBRA_IF_SLAVE_BOND;
- bond_ifindex = *(ifindex_t *)RTA_DATA(tb[IFLA_MASTER]);
- bypass = netlink_parse_lacp_bypass(linkinfo);
- } else
- zif_slave_type = ZEBRA_IF_SLAVE_OTHER;
- }
- if (vrf_is_backend_netns())
- vrf_id = (vrf_id_t)ns_id;
-
- /* If linking to another interface, note it. */
- if (tb[IFLA_LINK])
- link_ifindex = *(ifindex_t *)RTA_DATA(tb[IFLA_LINK]);
-
- if (tb[IFLA_LINK_NETNSID]) {
- link_nsid = *(ns_id_t *)RTA_DATA(tb[IFLA_LINK_NETNSID]);
- link_nsid = ns_id_get_absolute(ns_id, link_nsid);
- }
-
- ifp = if_get_by_name(name, vrf_id, NULL);
- set_ifindex(ifp, ifi->ifi_index, zns); /* add it to ns struct */
-
- ifp->flags = ifi->ifi_flags & 0x0000fffff;
- ifp->mtu6 = ifp->mtu = *(uint32_t *)RTA_DATA(tb[IFLA_MTU]);
- ifp->metric = 0;
- ifp->speed = get_iflink_speed(ifp, NULL);
- ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN;
-
- /* Set zebra interface type */
- zebra_if_set_ziftype(ifp, zif_type, zif_slave_type);
- if (IS_ZEBRA_IF_VRF(ifp))
- SET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK);
-
- /*
- * Just set the @link/lower-device ifindex. During nldump interfaces are
- * not ordered in any fashion so we may end up getting upper devices
- * before lower devices. We will setup the real linkage once the dump
- * is complete.
- */
- zif = (struct zebra_if *)ifp->info;
- zif->link_ifindex = link_ifindex;
-
- if (desc) {
- XFREE(MTYPE_ZIF_DESC, zif->desc);
- zif->desc = XSTRDUP(MTYPE_ZIF_DESC, desc);
- }
-
- /* Hardware type and address. */
- ifp->ll_type = netlink_to_zebra_link_type(ifi->ifi_type);
-
- netlink_interface_update_hw_addr(tb, ifp);
-
- if_add_update(ifp);
-
- /* Extract and save L2 interface information, take additional actions.
- */
- netlink_interface_update_l2info(ifp, linkinfo[IFLA_INFO_DATA],
- 1, link_nsid);
- if (IS_ZEBRA_IF_BOND(ifp))
- zebra_l2if_update_bond(ifp, true);
- if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp))
- zebra_l2if_update_bridge_slave(ifp, bridge_ifindex, ns_id,
- ZEBRA_BRIDGE_NO_ACTION);
- else if (IS_ZEBRA_IF_BOND_SLAVE(ifp))
- zebra_l2if_update_bond_slave(ifp, bond_ifindex, !!bypass);
-
- if (tb[IFLA_PROTO_DOWN]) {
- netlink_proc_dplane_if_protodown(zif, tb);
- if_sweep_protodown(zif);
- }
-
- return 0;
-}
-
/* Request for specific interface or address information from the kernel */
static int netlink_request_intf_addr(struct nlsock *netlink_cmd, int family,
int type, uint32_t filter_mask)
@@ -1261,7 +809,7 @@ int interface_lookup_netlink(struct zebra_ns *zns)
{
int ret;
struct zebra_dplane_info dp_info;
- struct nlsock *netlink_cmd = &zns->netlink_cmd;
+ struct nlsock *netlink_cmd = &zns->netlink_dplane_out;
/* Capture key info from ns struct */
zebra_dplane_info_from_zns(&dp_info, zns, true /*is_cmd*/);
@@ -1270,7 +818,7 @@ int interface_lookup_netlink(struct zebra_ns *zns)
ret = netlink_request_intf_addr(netlink_cmd, AF_PACKET, RTM_GETLINK, 0);
if (ret < 0)
return ret;
- ret = netlink_parse_info(netlink_interface, netlink_cmd, &dp_info, 0,
+ ret = netlink_parse_info(netlink_link_change, netlink_cmd, &dp_info, 0,
true);
if (ret < 0)
return ret;
@@ -1280,11 +828,18 @@ int interface_lookup_netlink(struct zebra_ns *zns)
RTEXT_FILTER_BRVLAN);
if (ret < 0)
return ret;
- ret = netlink_parse_info(netlink_interface, netlink_cmd, &dp_info, 0,
+ ret = netlink_parse_info(netlink_link_change, netlink_cmd, &dp_info, 0,
true);
if (ret < 0)
return ret;
+ return ret;
+}
+
+void interface_list_tunneldump(struct zebra_ns *zns)
+{
+ int ret;
+
/*
* So netlink_tunneldump_read will initiate a request
* per tunnel to get data. If we are on a kernel that
@@ -1297,13 +852,12 @@ int interface_lookup_netlink(struct zebra_ns *zns)
*/
ret = netlink_tunneldump_read(zns);
if (ret < 0)
- return ret;
+ return;
- /* fixup linkages */
- zebra_if_update_all_links(zns);
- return 0;
+ zebra_dplane_startup_stage(zns, ZEBRA_DPLANE_TUNNELS_READ);
}
+
/**
* interface_addr_lookup_netlink() - Look up interface addresses
*
@@ -1323,8 +877,8 @@ static int interface_addr_lookup_netlink(struct zebra_ns *zns)
ret = netlink_request_intf_addr(netlink_cmd, AF_INET, RTM_GETADDR, 0);
if (ret < 0)
return ret;
- ret = netlink_parse_info(netlink_interface_addr, netlink_cmd, &dp_info,
- 0, true);
+ ret = netlink_parse_info(netlink_interface_addr_dplane, netlink_cmd,
+ &dp_info, 0, true);
if (ret < 0)
return ret;
@@ -1332,8 +886,8 @@ static int interface_addr_lookup_netlink(struct zebra_ns *zns)
ret = netlink_request_intf_addr(netlink_cmd, AF_INET6, RTM_GETADDR, 0);
if (ret < 0)
return ret;
- ret = netlink_parse_info(netlink_interface_addr, netlink_cmd, &dp_info,
- 0, true);
+ ret = netlink_parse_info(netlink_interface_addr_dplane, netlink_cmd,
+ &dp_info, 0, true);
if (ret < 0)
return ret;
@@ -1455,67 +1009,13 @@ static ssize_t netlink_intf_msg_encoder(struct zebra_dplane_ctx *ctx, void *buf,
op = dplane_ctx_get_op(ctx);
- switch (op) {
- case DPLANE_OP_INTF_UPDATE:
+ if (op == DPLANE_OP_INTF_UPDATE)
cmd = RTM_SETLINK;
- break;
- case DPLANE_OP_INTF_INSTALL:
+ else if (op == DPLANE_OP_INTF_INSTALL)
cmd = RTM_NEWLINK;
- break;
- case DPLANE_OP_INTF_DELETE:
+ else if (op == DPLANE_OP_INTF_DELETE)
cmd = RTM_DELLINK;
- break;
- case DPLANE_OP_NONE:
- 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:
- case DPLANE_OP_LSP_INSTALL:
- case DPLANE_OP_LSP_DELETE:
- case DPLANE_OP_LSP_NOTIFY:
- case DPLANE_OP_LSP_UPDATE:
- case DPLANE_OP_PW_INSTALL:
- case DPLANE_OP_PW_UNINSTALL:
- case DPLANE_OP_SYS_ROUTE_ADD:
- case DPLANE_OP_SYS_ROUTE_DELETE:
- case DPLANE_OP_ADDR_INSTALL:
- case DPLANE_OP_ADDR_UNINSTALL:
- case DPLANE_OP_MAC_INSTALL:
- case DPLANE_OP_MAC_DELETE:
- case DPLANE_OP_NEIGH_INSTALL:
- case DPLANE_OP_NEIGH_UPDATE:
- case DPLANE_OP_NEIGH_DELETE:
- case DPLANE_OP_NEIGH_DISCOVER:
- case DPLANE_OP_VTEP_ADD:
- case DPLANE_OP_VTEP_DELETE:
- case DPLANE_OP_RULE_ADD:
- case DPLANE_OP_RULE_DELETE:
- case DPLANE_OP_RULE_UPDATE:
- case DPLANE_OP_BR_PORT_UPDATE:
- case DPLANE_OP_IPTABLE_ADD:
- case DPLANE_OP_IPTABLE_DELETE:
- case DPLANE_OP_IPSET_ADD:
- case DPLANE_OP_IPSET_ENTRY_ADD:
- case DPLANE_OP_IPSET_ENTRY_DELETE:
- case DPLANE_OP_IPSET_DELETE:
- case DPLANE_OP_NEIGH_IP_INSTALL:
- case DPLANE_OP_NEIGH_IP_DELETE:
- case DPLANE_OP_NEIGH_TABLE_UPDATE:
- case DPLANE_OP_GRE_SET:
- case DPLANE_OP_INTF_ADDR_ADD:
- case DPLANE_OP_INTF_ADDR_DEL:
- case DPLANE_OP_INTF_NETCONFIG:
- case DPLANE_OP_TC_QDISC_INSTALL:
- case DPLANE_OP_TC_QDISC_UNINSTALL:
- case DPLANE_OP_TC_CLASS_ADD:
- case DPLANE_OP_TC_CLASS_DELETE:
- case DPLANE_OP_TC_CLASS_UPDATE:
- case DPLANE_OP_TC_FILTER_ADD:
- case DPLANE_OP_TC_FILTER_DELETE:
- case DPLANE_OP_TC_FILTER_UPDATE:
+ else {
flog_err(
EC_ZEBRA_NHG_FIB_UPDATE,
"Context received for kernel interface update with incorrect OP code (%u)",
@@ -1930,6 +1430,9 @@ int netlink_interface_addr_dplane(struct nlmsghdr *h, ns_id_t ns_id,
if (kernel_flags & IFA_F_SECONDARY)
dplane_ctx_intf_set_secondary(ctx);
+ if (kernel_flags & IFA_F_NOPREFIXROUTE)
+ dplane_ctx_intf_set_noprefixroute(ctx);
+
/* Label */
if (tb[IFA_LABEL]) {
label = (char *)RTA_DATA(tb[IFA_LABEL]);
@@ -1943,7 +1446,6 @@ int netlink_interface_addr_dplane(struct nlmsghdr *h, ns_id_t ns_id,
/* Enqueue ctx for main pthread to process */
dplane_provider_enqueue_to_zebra(ctx);
-
return 0;
}
@@ -1953,25 +1455,22 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
struct ifinfomsg *ifi;
struct rtattr *tb[IFLA_MAX + 1];
struct rtattr *linkinfo[IFLA_MAX + 1];
- struct interface *ifp;
char *name = NULL;
char *kind = NULL;
- char *desc = NULL;
char *slave_kind = NULL;
- struct zebra_ns *zns;
vrf_id_t vrf_id = VRF_DEFAULT;
enum zebra_iftype zif_type = ZEBRA_IF_OTHER;
enum zebra_slave_iftype zif_slave_type = ZEBRA_IF_SLAVE_NONE;
ifindex_t bridge_ifindex = IFINDEX_INTERNAL;
ifindex_t bond_ifindex = IFINDEX_INTERNAL;
ifindex_t link_ifindex = IFINDEX_INTERNAL;
- uint8_t old_hw_addr[INTERFACE_HWADDR_MAX];
- struct zebra_if *zif;
ns_id_t link_nsid = ns_id;
ifindex_t master_infindex = IFINDEX_INTERNAL;
uint8_t bypass = 0;
+ uint32_t txqlen = 0;
+
+ frrtrace(3, frr_zebra, netlink_interface, h, ns_id, startup);
- zns = zebra_ns_lookup(ns_id);
ifi = NLMSG_DATA(h);
/* assume if not default zns, then new VRF */
@@ -2000,10 +1499,6 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
return -1;
}
- /* We are interested in some AF_BRIDGE notifications. */
- if (ifi->ifi_family == AF_BRIDGE)
- return netlink_bridge_interface(h, len, ns_id, startup);
-
/* Looking up interface name. */
memset(linkinfo, 0, sizeof(linkinfo));
netlink_parse_rtattr_flags(tb, IFLA_MAX, IFLA_RTA(ifi), len,
@@ -2050,18 +1545,52 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
link_nsid = *(ns_id_t *)RTA_DATA(tb[IFLA_LINK_NETNSID]);
link_nsid = ns_id_get_absolute(ns_id, link_nsid);
}
- if (tb[IFLA_IFALIAS]) {
- desc = (char *)RTA_DATA(tb[IFLA_IFALIAS]);
- }
- /* See if interface is present. */
- ifp = if_lookup_by_name_per_ns(zns, name);
+ if (tb[IFLA_TXQLEN])
+ txqlen = *(uint32_t *)RTA_DATA(tb[IFLA_TXQLEN]);
+
+ struct zebra_dplane_ctx *ctx = dplane_ctx_alloc();
+ dplane_ctx_set_ns_id(ctx, ns_id);
+ dplane_ctx_set_ifp_link_nsid(ctx, link_nsid);
+ dplane_ctx_set_ifp_zif_type(ctx, zif_type);
+ dplane_ctx_set_ifindex(ctx, ifi->ifi_index);
+ dplane_ctx_set_ifname(ctx, name);
+ dplane_ctx_set_ifp_startup(ctx, startup);
+ dplane_ctx_set_ifp_family(ctx, ifi->ifi_family);
+ dplane_ctx_set_intf_txqlen(ctx, txqlen);
+
+ /* We are interested in some AF_BRIDGE notifications. */
+#ifndef AF_BRIDGE
+#define AF_BRIDGE 7
+#endif
+ if (ifi->ifi_family == AF_BRIDGE) {
+ dplane_ctx_set_op(ctx, DPLANE_OP_INTF_INSTALL);
+ return netlink_bridge_interface(ctx, tb[IFLA_AF_SPEC], startup);
+ }
if (h->nlmsg_type == RTM_NEWLINK) {
+ dplane_ctx_set_ifp_link_ifindex(ctx, link_ifindex);
+ dplane_ctx_set_op(ctx, DPLANE_OP_INTF_INSTALL);
+ dplane_ctx_set_status(ctx, ZEBRA_DPLANE_REQUEST_QUEUED);
+ if (tb[IFLA_IFALIAS]) {
+ dplane_ctx_set_ifp_desc(ctx,
+ RTA_DATA(tb[IFLA_IFALIAS]));
+ }
+ if (!tb[IFLA_MTU]) {
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(
+ "RTM_NEWLINK for interface %s(%u) without MTU set",
+ name, ifi->ifi_index);
+ dplane_ctx_fini(&ctx);
+ return 0;
+ }
+ dplane_ctx_set_ifp_mtu(ctx, *(int *)RTA_DATA(tb[IFLA_MTU]));
+
/* If VRF, create or update the VRF structure itself. */
if (zif_type == ZEBRA_IF_VRF && !vrf_is_backend_netns()) {
- netlink_vrf_change(h, tb[IFLA_LINKINFO], ns_id, name);
- vrf_id = (vrf_id_t)ifi->ifi_index;
+ netlink_vrf_change(h, tb[IFLA_LINKINFO], ns_id, name,
+ ctx);
+ vrf_id = ifi->ifi_index;
}
if (tb[IFLA_MASTER]) {
@@ -2084,264 +1613,45 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
} else
zif_slave_type = ZEBRA_IF_SLAVE_OTHER;
}
+ dplane_ctx_set_ifp_zif_slave_type(ctx, zif_slave_type);
+ dplane_ctx_set_ifp_vrf_id(ctx, vrf_id);
+ dplane_ctx_set_ifp_master_ifindex(ctx, master_infindex);
+ dplane_ctx_set_ifp_bridge_ifindex(ctx, bridge_ifindex);
+ dplane_ctx_set_ifp_bond_ifindex(ctx, bond_ifindex);
+ dplane_ctx_set_ifp_bypass(ctx, bypass);
+ dplane_ctx_set_ifp_zltype(
+ ctx, netlink_to_zebra_link_type(ifi->ifi_type));
+
if (vrf_is_backend_netns())
- vrf_id = (vrf_id_t)ns_id;
- if (ifp == NULL
- || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
- /* Add interface notification from kernel */
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug(
- "RTM_NEWLINK ADD for %s(%u) vrf_id %u type %d sl_type %d master %u flags 0x%x",
- name, ifi->ifi_index, vrf_id, zif_type,
- zif_slave_type, master_infindex,
- ifi->ifi_flags);
-
- if (ifp == NULL) {
- /* unknown interface */
- ifp = if_get_by_name(name, vrf_id, NULL);
- } else {
- /* pre-configured interface, learnt now */
- if (ifp->vrf->vrf_id != vrf_id)
- if_update_to_new_vrf(ifp, vrf_id);
- }
-
- /* Update interface information. */
- set_ifindex(ifp, ifi->ifi_index, zns);
- ifp->flags = ifi->ifi_flags & 0x0000fffff;
- if (!tb[IFLA_MTU]) {
- zlog_debug(
- "RTM_NEWLINK for interface %s(%u) without MTU set",
- name, ifi->ifi_index);
- return 0;
- }
- ifp->mtu6 = ifp->mtu = *(int *)RTA_DATA(tb[IFLA_MTU]);
- ifp->metric = 0;
- ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN;
-
- /* Set interface type */
- zebra_if_set_ziftype(ifp, zif_type, zif_slave_type);
- if (IS_ZEBRA_IF_VRF(ifp))
- SET_FLAG(ifp->status,
- ZEBRA_INTERFACE_VRF_LOOPBACK);
-
- /* Update link. */
- zebra_if_update_link(ifp, link_ifindex, link_nsid);
-
- ifp->ll_type =
- netlink_to_zebra_link_type(ifi->ifi_type);
- netlink_interface_update_hw_addr(tb, ifp);
-
- /* Inform clients, install any configured addresses. */
- if_add_update(ifp);
-
- /* Extract and save L2 interface information, take
- * additional actions. */
- netlink_interface_update_l2info(
- ifp, linkinfo[IFLA_INFO_DATA],
- 1, link_nsid);
- if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp))
- zebra_l2if_update_bridge_slave(
- ifp, bridge_ifindex, ns_id,
- ZEBRA_BRIDGE_NO_ACTION);
- else if (IS_ZEBRA_IF_BOND_SLAVE(ifp))
- zebra_l2if_update_bond_slave(ifp, bond_ifindex,
- !!bypass);
-
- if (tb[IFLA_PROTO_DOWN])
- netlink_proc_dplane_if_protodown(ifp->info, tb);
- if (IS_ZEBRA_IF_BRIDGE(ifp)) {
- zif = ifp->info;
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug(
- "RTM_NEWLINK ADD for %s(%u), vlan-aware %d",
- name, ifp->ifindex,
- IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(
- zif));
- }
- } else if (ifp->vrf->vrf_id != vrf_id) {
- /* VRF change for an interface. */
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug(
- "RTM_NEWLINK vrf-change for %s(%u) vrf_id %u -> %u flags 0x%x",
- name, ifp->ifindex, ifp->vrf->vrf_id,
- vrf_id, ifi->ifi_flags);
+ dplane_ctx_set_ifp_vrf_id(ctx, ns_id);
- if_handle_vrf_change(ifp, vrf_id);
- } else {
- bool was_bridge_slave, was_bond_slave;
- uint8_t chgflags = ZEBRA_BRIDGE_NO_ACTION;
- zif = ifp->info;
+ dplane_ctx_set_ifp_flags(ctx, ifi->ifi_flags & 0x0000fffff);
- /* Interface update. */
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug(
- "RTM_NEWLINK update for %s(%u) sl_type %d master %u flags 0x%x",
- name, ifp->ifindex, zif_slave_type,
- master_infindex, ifi->ifi_flags);
+ if (tb[IFLA_PROTO_DOWN]) {
+ dplane_ctx_set_ifp_protodown_set(ctx, true);
+ netlink_proc_dplane_if_protodown(ctx, tb);
+ } else
+ dplane_ctx_set_ifp_protodown_set(ctx, false);
- set_ifindex(ifp, ifi->ifi_index, zns);
- if (!tb[IFLA_MTU]) {
- zlog_debug(
- "RTM_NEWLINK for interface %s(%u) without MTU set",
- name, ifi->ifi_index);
- return 0;
- }
- ifp->mtu6 = ifp->mtu = *(int *)RTA_DATA(tb[IFLA_MTU]);
- ifp->metric = 0;
-
- /* Update interface type - NOTE: Only slave_type can
- * change. */
- was_bridge_slave = IS_ZEBRA_IF_BRIDGE_SLAVE(ifp);
- was_bond_slave = IS_ZEBRA_IF_BOND_SLAVE(ifp);
- zebra_if_set_ziftype(ifp, zif_type, zif_slave_type);
-
- memcpy(old_hw_addr, ifp->hw_addr, INTERFACE_HWADDR_MAX);
-
- /* Update link. */
- zebra_if_update_link(ifp, link_ifindex, link_nsid);
-
- ifp->ll_type =
- netlink_to_zebra_link_type(ifi->ifi_type);
- netlink_interface_update_hw_addr(tb, ifp);
-
- if (tb[IFLA_PROTO_DOWN])
- netlink_proc_dplane_if_protodown(ifp->info, tb);
-
- if (if_is_no_ptm_operative(ifp)) {
- bool is_up = if_is_operative(ifp);
- ifp->flags = ifi->ifi_flags & 0x0000fffff;
- if (!if_is_no_ptm_operative(ifp) ||
- CHECK_FLAG(zif->flags,
- ZIF_FLAG_PROTODOWN)) {
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug(
- "Intf %s(%u) has gone DOWN",
- name, ifp->ifindex);
- if_down(ifp);
- rib_update(RIB_UPDATE_KERNEL);
- } else if (if_is_operative(ifp)) {
- bool mac_updated = false;
-
- /* Must notify client daemons of new
- * interface status. */
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug(
- "Intf %s(%u) PTM up, notifying clients",
- name, ifp->ifindex);
- if_up(ifp, !is_up);
-
- /* Update EVPN VNI when SVI MAC change
- */
- if (memcmp(old_hw_addr, ifp->hw_addr,
- INTERFACE_HWADDR_MAX))
- mac_updated = true;
- if (IS_ZEBRA_IF_VLAN(ifp)
- && mac_updated) {
- struct interface *link_if;
-
- link_if =
- if_lookup_by_index_per_ns(
- zebra_ns_lookup(NS_DEFAULT),
- link_ifindex);
- if (link_if)
- zebra_vxlan_svi_up(ifp,
- link_if);
- } else if (mac_updated
- && IS_ZEBRA_IF_BRIDGE(ifp)) {
- zlog_debug(
- "Intf %s(%u) bridge changed MAC address",
- name, ifp->ifindex);
- chgflags =
- ZEBRA_BRIDGE_MASTER_MAC_CHANGE;
- }
- }
- } else {
- ifp->flags = ifi->ifi_flags & 0x0000fffff;
- if (if_is_operative(ifp) &&
- !CHECK_FLAG(zif->flags,
- ZIF_FLAG_PROTODOWN)) {
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug(
- "Intf %s(%u) has come UP",
- name, ifp->ifindex);
- if_up(ifp, true);
- if (IS_ZEBRA_IF_BRIDGE(ifp))
- chgflags =
- ZEBRA_BRIDGE_MASTER_UP;
- } else {
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug(
- "Intf %s(%u) has gone DOWN",
- name, ifp->ifindex);
- if_down(ifp);
- rib_update(RIB_UPDATE_KERNEL);
- }
- }
-
- /* Extract and save L2 interface information, take
- * additional actions. */
- netlink_interface_update_l2info(
- ifp, linkinfo[IFLA_INFO_DATA],
- 0, link_nsid);
- if (IS_ZEBRA_IF_BRIDGE(ifp))
- zebra_l2if_update_bridge(ifp, chgflags);
- if (IS_ZEBRA_IF_BOND(ifp))
- zebra_l2if_update_bond(ifp, true);
- if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp) || was_bridge_slave)
- zebra_l2if_update_bridge_slave(
- ifp, bridge_ifindex, ns_id, chgflags);
- else if (IS_ZEBRA_IF_BOND_SLAVE(ifp) || was_bond_slave)
- zebra_l2if_update_bond_slave(ifp, bond_ifindex,
- !!bypass);
- if (IS_ZEBRA_IF_BRIDGE(ifp)) {
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug(
- "RTM_NEWLINK update for %s(%u), vlan-aware %d",
- name, ifp->ifindex,
- IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(
- zif));
- }
- }
+ netlink_interface_update_hw_addr(tb, ctx);
- zif = ifp->info;
- if (zif) {
- XFREE(MTYPE_ZIF_DESC, zif->desc);
- if (desc)
- zif->desc = XSTRDUP(MTYPE_ZIF_DESC, desc);
- }
+ /* Extract and save L2 interface information, take
+ * additional actions. */
+ netlink_interface_update_l2info(
+ ctx, zif_type, linkinfo[IFLA_INFO_DATA], 1, link_nsid);
} else {
- /* Delete interface notification from kernel */
- if (ifp == NULL) {
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug(
- "RTM_DELLINK for unknown interface %s(%u)",
- name, ifi->ifi_index);
- return 0;
- }
-
if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("RTM_DELLINK for %s(%u)", name,
- ifp->ifindex);
-
- UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK);
-
- if (IS_ZEBRA_IF_BOND(ifp))
- zebra_l2if_update_bond(ifp, false);
- if (IS_ZEBRA_IF_BOND_SLAVE(ifp))
- zebra_l2if_update_bond_slave(ifp, bond_ifindex, false);
- /* Special handling for bridge or VxLAN interfaces. */
- if (IS_ZEBRA_IF_BRIDGE(ifp))
- zebra_l2_bridge_del(ifp);
- else if (IS_ZEBRA_IF_VXLAN(ifp))
- zebra_l2_vxlanif_del(ifp);
-
- if_delete_update(&ifp);
-
- /* If VRF, delete the VRF structure itself. */
- if (zif_type == ZEBRA_IF_VRF && !vrf_is_backend_netns())
- netlink_vrf_change(h, tb[IFLA_LINKINFO], ns_id, name);
+ zlog_debug("RTM_DELLINK for %s(%u), enqueuing to zebra",
+ name, ifi->ifi_index);
+
+ dplane_ctx_set_op(ctx, DPLANE_OP_INTF_DELETE);
+ dplane_ctx_set_status(ctx, ZEBRA_DPLANE_REQUEST_QUEUED);
+
+ dplane_ctx_set_ifp_bond_ifindex(ctx, bond_ifindex);
}
+ dplane_provider_enqueue_to_zebra(ctx);
+
return 0;
}
@@ -2399,9 +1709,10 @@ ssize_t netlink_intf_msg_encode(uint16_t cmd,
return -1;
nl_attr_put32(&req->n, buflen, IFLA_PROTO_DOWN_REASON_MASK,
- (1 << frr_protodown_r_bit));
+ (1 << if_netlink_get_frr_protodown_r_bit()));
nl_attr_put32(&req->n, buflen, IFLA_PROTO_DOWN_REASON_VALUE,
- ((int)pd_reason_val) << frr_protodown_r_bit);
+ ((int)pd_reason_val)
+ << if_netlink_get_frr_protodown_r_bit());
nl_attr_nest_end(&req->n, nest_protodown_reason);
@@ -2417,6 +1728,13 @@ ssize_t netlink_intf_msg_encode(uint16_t cmd,
void interface_list(struct zebra_ns *zns)
{
interface_lookup_netlink(zns);
+
+ zebra_dplane_startup_stage(zns, ZEBRA_DPLANE_INTERFACES_READ);
+}
+
+void interface_list_second(struct zebra_ns *zns)
+{
+ zebra_if_update_all_links(zns);
/* We add routes for interface address,
* so we need to get the nexthop info
* from the kernel before we can do that
@@ -2424,37 +1742,8 @@ void interface_list(struct zebra_ns *zns)
netlink_nexthop_read(zns);
interface_addr_lookup_netlink(zns);
-}
-
-void if_netlink_set_frr_protodown_r_bit(uint8_t bit)
-{
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug(
- "Protodown reason bit index changed: bit-index %u -> bit-index %u",
- frr_protodown_r_bit, bit);
-
- frr_protodown_r_bit = bit;
-}
-void if_netlink_unset_frr_protodown_r_bit(void)
-{
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug(
- "Protodown reason bit index changed: bit-index %u -> bit-index %u",
- frr_protodown_r_bit, FRR_PROTODOWN_REASON_DEFAULT_BIT);
-
- frr_protodown_r_bit = FRR_PROTODOWN_REASON_DEFAULT_BIT;
-}
-
-
-bool if_netlink_frr_protodown_r_bit_is_set(void)
-{
- return (frr_protodown_r_bit != FRR_PROTODOWN_REASON_DEFAULT_BIT);
-}
-
-uint8_t if_netlink_get_frr_protodown_r_bit(void)
-{
- return frr_protodown_r_bit;
+ zebra_dplane_startup_stage(zns, ZEBRA_DPLANE_ADDRESSES_READ);
}
/**
@@ -2514,7 +1803,7 @@ int netlink_tunneldump_read(struct zebra_ns *zns)
if (ret < 0)
return ret;
- ret = netlink_parse_info(netlink_interface, netlink_cmd,
+ ret = netlink_parse_info(netlink_link_change, netlink_cmd,
&dp_info, 0, true);
if (ret < 0)
diff --git a/zebra/if_netlink.h b/zebra/if_netlink.h
index ede6224188..9b31906a17 100644
--- a/zebra/if_netlink.h
+++ b/zebra/if_netlink.h
@@ -42,17 +42,6 @@ extern int netlink_tunneldump_read(struct zebra_ns *zns);
extern enum netlink_msg_status
netlink_put_intf_update_msg(struct nl_batch *bth, struct zebra_dplane_ctx *ctx);
-#define FRR_PROTODOWN_REASON_DEFAULT_BIT 7
-/* Protodown bit setter/getter
- *
- * Allow users to change the bit if it conflicts with another
- * on their system.
- */
-extern void if_netlink_set_frr_protodown_r_bit(uint8_t bit);
-extern void if_netlink_unset_frr_protodown_r_bit(void);
-extern bool if_netlink_frr_protodown_r_bit_is_set(void);
-extern uint8_t if_netlink_get_frr_protodown_r_bit(void);
-
#ifdef __cplusplus
}
#endif
diff --git a/zebra/if_sysctl.c b/zebra/if_sysctl.c
index ae292689ed..9db959896e 100644
--- a/zebra/if_sysctl.c
+++ b/zebra/if_sysctl.c
@@ -6,6 +6,8 @@
#include <zebra.h>
+#include <net/route.h>
+
#if !defined(GNU_LINUX) && !defined(OPEN_BSD)
#include "if.h"
diff --git a/zebra/interface.c b/zebra/interface.c
index 496a85e676..b824977f9e 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -18,7 +18,6 @@
#include "log.h"
#include "zclient.h"
#include "vrf.h"
-#include "lib/northbound_cli.h"
#include "zebra/rtadv.h"
#include "zebra_ns.h"
@@ -44,8 +43,6 @@ DEFINE_MTYPE_STATIC(ZEBRA, ZINFO, "Zebra Interface Information");
DEFINE_HOOK(zebra_if_extra_info, (struct vty * vty, struct interface *ifp),
(vty, ifp));
-DEFINE_HOOK(zebra_if_config_wr, (struct vty * vty, struct interface *ifp),
- (vty, ifp));
DEFINE_MTYPE(ZEBRA, ZIF_DESC, "Intf desc");
@@ -65,7 +62,7 @@ static void if_zebra_speed_update(struct event *thread)
* interfaces not available.
* note that loopback & virtual interfaces can return 0 as speed
*/
- if (error < 0)
+ if (error == INTERFACE_SPEED_ERROR_READ)
return;
if (new_speed != ifp->speed) {
@@ -76,7 +73,7 @@ static void if_zebra_speed_update(struct event *thread)
changed = true;
}
- if (changed || new_speed == UINT32_MAX) {
+ if (changed || error == INTERFACE_SPEED_ERROR_UNKNOWN) {
#define SPEED_UPDATE_SLEEP_TIME 5
#define SPEED_UPDATE_COUNT_MAX (4 * 60 / SPEED_UPDATE_SLEEP_TIME)
/*
@@ -91,7 +88,7 @@ static void if_zebra_speed_update(struct event *thread)
* to not update the system to keep track of that. This
* is far simpler to just stop trying after 4 minutes
*/
- if (new_speed == UINT32_MAX &&
+ if (error == INTERFACE_SPEED_ERROR_UNKNOWN &&
zif->speed_update_count == SPEED_UPDATE_COUNT_MAX)
return;
@@ -111,17 +108,6 @@ static void zebra_if_node_destroy(route_table_delegate_t *delegate,
route_node_destroy(delegate, table, node);
}
-static void zebra_if_nhg_dependents_free(struct zebra_if *zebra_if)
-{
- nhg_connected_tree_free(&zebra_if->nhg_dependents);
-}
-
-static void zebra_if_nhg_dependents_init(struct zebra_if *zebra_if)
-{
- nhg_connected_tree_init(&zebra_if->nhg_dependents);
-}
-
-
route_table_delegate_t zebra_if_table_delegate = {
.create_node = route_node_create,
.destroy_node = zebra_if_node_destroy};
@@ -135,11 +121,12 @@ static int if_zebra_new_hook(struct interface *ifp)
zebra_if->ifp = ifp;
zebra_if->multicast = IF_ZEBRA_DATA_UNSPEC;
- zebra_if->shutdown = IF_ZEBRA_DATA_OFF;
+ zebra_if->mpls_config = IF_ZEBRA_DATA_UNSPEC;
+ zebra_if->shutdown = IF_ZEBRA_DATA_UNSPEC;
zebra_if->link_nsid = NS_UNKNOWN;
- zebra_if_nhg_dependents_init(zebra_if);
+ nhg_connected_tree_init(&zebra_if->nhg_dependents);
zebra_ptm_if_init(zebra_if);
@@ -147,6 +134,8 @@ static int if_zebra_new_hook(struct interface *ifp)
rtadv_if_init(zebra_if);
+ zebra_evpn_mh_if_init(zebra_if);
+
memset(&zebra_if->neigh_mac[0], 0, 6);
/* Initialize installed address chains tree. */
@@ -170,18 +159,13 @@ static int if_zebra_new_hook(struct interface *ifp)
return 0;
}
-static void if_nhg_dependents_check_valid(struct nhg_hash_entry *nhe)
-{
- zebra_nhg_check_valid(nhe);
-}
-
static void if_down_nhg_dependents(const struct interface *ifp)
{
struct nhg_connected *rb_node_dep = NULL;
struct zebra_if *zif = (struct zebra_if *)ifp->info;
frr_each(nhg_connected_tree, &zif->nhg_dependents, rb_node_dep)
- if_nhg_dependents_check_valid(rb_node_dep->nhe);
+ zebra_nhg_check_valid(rb_node_dep->nhe);
}
static void if_nhg_dependents_release(const struct interface *ifp)
@@ -191,7 +175,11 @@ static void if_nhg_dependents_release(const struct interface *ifp)
frr_each(nhg_connected_tree, &zif->nhg_dependents, rb_node_dep) {
rb_node_dep->nhe->ifp = NULL; /* Null it out */
- if_nhg_dependents_check_valid(rb_node_dep->nhe);
+ zebra_nhg_check_valid(rb_node_dep->nhe);
+ if (CHECK_FLAG(rb_node_dep->nhe->flags,
+ NEXTHOP_GROUP_KEEP_AROUND) &&
+ rb_node_dep->nhe->refcnt == 1)
+ zebra_nhg_decrement_ref(rb_node_dep->nhe);
}
}
@@ -199,6 +187,7 @@ static void if_nhg_dependents_release(const struct interface *ifp)
static int if_zebra_delete_hook(struct interface *ifp)
{
struct zebra_if *zebra_if;
+ struct zebra_l2info_bond *bond;
if (ifp->info) {
zebra_if = ifp->info;
@@ -216,12 +205,16 @@ static int if_zebra_delete_hook(struct interface *ifp)
rtadv_if_fini(zebra_if);
+ bond = &zebra_if->bond_info;
+ if (bond && bond->mbr_zifs)
+ list_delete(&bond->mbr_zifs);
+
zebra_l2_bridge_if_cleanup(ifp);
zebra_evpn_if_cleanup(zebra_if);
zebra_evpn_mac_ifp_del(ifp);
if_nhg_dependents_release(ifp);
- zebra_if_nhg_dependents_free(zebra_if);
+ nhg_connected_tree_free(&zebra_if->nhg_dependents);
XFREE(MTYPE_ZIF_DESC, zebra_if->desc);
@@ -267,6 +260,9 @@ struct interface *if_link_per_ns(struct zebra_ns *ns, struct interface *ifp)
/* Delete a VRF. This is called in vrf_terminate(). */
void if_unlink_per_ns(struct interface *ifp)
{
+ if (!ifp->node)
+ return;
+
ifp->node->info = NULL;
route_unlock_node(ifp->node);
ifp->node = NULL;
@@ -480,12 +476,11 @@ void if_flags_update(struct interface *ifp, uint64_t newflags)
address. */
void if_addr_wakeup(struct interface *ifp)
{
- struct listnode *node, *nnode;
struct connected *ifc;
struct prefix *p;
enum zebra_dplane_result dplane_res;
- for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, ifc)) {
+ frr_each_safe (if_connected, ifp->connected, ifc) {
p = ifc->address;
if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED)
@@ -606,6 +601,11 @@ void if_add_update(struct interface *ifp)
if_addr_wakeup(ifp);
+ if (if_data->mpls_config == IF_ZEBRA_DATA_ON)
+ dplane_intf_mpls_modify_state(ifp, true);
+ else if (if_data->mpls_config == IF_ZEBRA_DATA_OFF)
+ dplane_intf_mpls_modify_state(ifp, false);
+
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
"interface %s vrf %s(%u) index %d becomes active.",
@@ -623,32 +623,24 @@ void if_add_update(struct interface *ifp)
/* Install connected routes corresponding to an interface. */
static void if_install_connected(struct interface *ifp)
{
- struct listnode *node;
- struct listnode *next;
struct connected *ifc;
- if (ifp->connected) {
- for (ALL_LIST_ELEMENTS(ifp->connected, node, next, ifc)) {
- if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
- zebra_interface_address_add_update(ifp, ifc);
+ frr_each (if_connected, ifp->connected, ifc) {
+ if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
+ zebra_interface_address_add_update(ifp, ifc);
- connected_up(ifp, ifc);
- }
+ connected_up(ifp, ifc);
}
}
/* Uninstall connected routes corresponding to an interface. */
static void if_uninstall_connected(struct interface *ifp)
{
- struct listnode *node;
- struct listnode *next;
struct connected *ifc;
- if (ifp->connected) {
- for (ALL_LIST_ELEMENTS(ifp->connected, node, next, ifc)) {
- zebra_interface_address_delete_update(ifp, ifc);
- connected_down(ifp, ifc);
- }
+ frr_each_safe (if_connected, ifp->connected, ifc) {
+ zebra_interface_address_delete_update(ifp, ifc);
+ connected_down(ifp, ifc);
}
}
@@ -656,20 +648,15 @@ static void if_uninstall_connected(struct interface *ifp)
/* TODO - Check why IPv4 handling here is different from install or if_down */
static void if_delete_connected(struct interface *ifp)
{
- struct connected *ifc;
+ struct connected *ifc, *ifc_next;
struct prefix cp;
struct route_node *rn;
struct zebra_if *zebra_if;
- struct listnode *node;
- struct listnode *last = NULL;
zebra_if = ifp->info;
- if (!ifp->connected)
- return;
-
- while ((node = (last ? last->next : listhead(ifp->connected)))) {
- ifc = listgetdata(node);
+ for (ifc = if_connected_first(ifp->connected); ifc; ifc = ifc_next) {
+ ifc_next = if_connected_next(ifp->connected, ifc);
cp = *CONNECTED_PREFIX(ifc);
apply_mask(&cp);
@@ -718,11 +705,15 @@ static void if_delete_connected(struct interface *ifp)
* (unconditionally). */
if (!CHECK_FLAG(ifc->conf,
ZEBRA_IFC_CONFIGURED)) {
- listnode_delete(ifp->connected,
+ if (ifc == ifc_next)
+ ifc_next = if_connected_next(
+ ifp->connected,
ifc);
+
+ if_connected_del(ifp->connected,
+ ifc);
connected_free(&ifc);
- } else
- last = node;
+ }
}
/* Free chain list and respective route node. */
@@ -737,14 +728,10 @@ static void if_delete_connected(struct interface *ifp)
UNSET_FLAG(ifc->conf, ZEBRA_IFC_REAL);
UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
- if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
- last = node;
- else {
- listnode_delete(ifp->connected, ifc);
+ if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED)) {
+ if_connected_del(ifp->connected, ifc);
connected_free(&ifc);
}
- } else {
- last = node;
}
}
}
@@ -778,6 +765,15 @@ void if_delete_update(struct interface **pifp)
/* Delete connected routes from the kernel. */
if_delete_connected(ifp);
+ /* if the ifp is in a vrf, move it to default so vrf can be deleted if
+ * desired. This operation is not done for netns implementation to avoid
+ * collision with interface with the same name in the default vrf (can
+ * occur with this implementation whereas it is not possible with
+ * vrf-lite).
+ */
+ if (ifp->vrf->vrf_id && !vrf_is_backend_netns())
+ if_handle_vrf_change(ifp, VRF_DEFAULT);
+
/* Send out notification on interface delete. */
zebra_interface_delete_update(ifp);
@@ -791,14 +787,7 @@ void if_delete_update(struct interface **pifp)
if_set_index(ifp, IFINDEX_INTERNAL);
ifp->node = NULL;
- /* if the ifp is in a vrf, move it to default so vrf can be deleted if
- * desired. This operation is not done for netns implementation to avoid
- * collision with interface with the same name in the default vrf (can
- * occur with this implementation whereas it is not possible with
- * vrf-lite).
- */
- if (ifp->vrf->vrf_id && !vrf_is_backend_netns())
- if_handle_vrf_change(ifp, VRF_DEFAULT);
+ UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK);
/* Reset some zebra interface params to default values. */
zif = ifp->info;
@@ -837,9 +826,12 @@ void if_handle_vrf_change(struct interface *ifp, vrf_id_t vrf_id)
if_down_del_nbr_connected(ifp);
/* Send out notification on interface VRF change. */
- /* This is to issue an UPDATE or a DELETE, as appropriate. */
+ /* This is to issue a DELETE, as appropriate. */
zebra_interface_vrf_update_del(ifp, vrf_id);
+ if (if_is_vrf(ifp))
+ return;
+
/* update VRF */
if_update_to_new_vrf(ifp, vrf_id);
@@ -955,47 +947,6 @@ static void if_down_del_nbr_connected(struct interface *ifp)
}
}
-void if_nhg_dependents_add(struct interface *ifp, struct nhg_hash_entry *nhe)
-{
- if (ifp->info) {
- struct zebra_if *zif = (struct zebra_if *)ifp->info;
-
- nhg_connected_tree_add_nhe(&zif->nhg_dependents, nhe);
- }
-}
-
-void if_nhg_dependents_del(struct interface *ifp, struct nhg_hash_entry *nhe)
-{
- if (ifp->info) {
- struct zebra_if *zif = (struct zebra_if *)ifp->info;
-
- nhg_connected_tree_del_nhe(&zif->nhg_dependents, nhe);
- }
-}
-
-unsigned int if_nhg_dependents_count(const struct interface *ifp)
-{
- if (ifp->info) {
- struct zebra_if *zif = (struct zebra_if *)ifp->info;
-
- return nhg_connected_tree_count(&zif->nhg_dependents);
- }
-
- return 0;
-}
-
-
-bool if_nhg_dependents_is_empty(const struct interface *ifp)
-{
- if (ifp->info) {
- struct zebra_if *zif = (struct zebra_if *)ifp->info;
-
- return nhg_connected_tree_is_empty(&zif->nhg_dependents);
- }
-
- return false;
-}
-
/* Interface is up. */
void if_up(struct interface *ifp, bool install_connected)
{
@@ -1023,6 +974,14 @@ void if_up(struct interface *ifp, bool install_connected)
if (install_connected)
if_install_connected(ifp);
+ /*
+ * Interface associated NHG's have been deleted on
+ * interface down events, now that this interface
+ * is coming back up, let's resync the zebra -> dplane
+ * nhg's so that they can be continued to be used.
+ */
+ zebra_interface_nhg_reinstall(ifp);
+
/* Handle interface up for specific types for EVPN. Non-VxLAN interfaces
* are checked to see if (remote) neighbor entries need to be installed
* on them for ARP suppression.
@@ -1049,6 +1008,8 @@ void if_up(struct interface *ifp, bool install_connected)
event_add_timer(zrouter.master, if_zebra_speed_update, ifp, 0,
&zif->speed_update);
event_ignore_late_timer(zif->speed_update);
+
+ if_addr_wakeup(ifp);
}
/* Interface goes down. We have to manage different behavior of based
@@ -1112,8 +1073,6 @@ void zebra_if_update_link(struct interface *ifp, ifindex_t link_ifindex,
{
struct zebra_if *zif;
- if (IS_ZEBRA_IF_VETH(ifp))
- return;
zif = (struct zebra_if *)ifp->info;
zif->link_nsid = ns_id;
zif->link_ifindex = link_ifindex;
@@ -1176,6 +1135,12 @@ static bool if_ignore_set_protodown(const struct interface *ifp, bool new_down,
zif = ifp->info;
+ /*
+ * FRR does not have enough data to make this request
+ */
+ if (ifp->ifindex == IFINDEX_INTERNAL)
+ return true;
+
/* Current state as we know it */
old_down = !!(ZEBRA_IF_IS_PROTODOWN(zif));
old_set_down = !!CHECK_FLAG(zif->flags, ZIF_FLAG_SET_PROTODOWN);
@@ -1285,6 +1250,9 @@ static void zebra_if_addr_update_ctx(struct zebra_dplane_ctx *ctx,
const struct prefix *addr, *dest = NULL;
enum dplane_op_e op;
+ if (!ifp)
+ return;
+
op = dplane_ctx_get_op(ctx);
addr = dplane_ctx_get_intf_addr(ctx);
@@ -1305,6 +1273,9 @@ static void zebra_if_addr_update_ctx(struct zebra_dplane_ctx *ctx,
if (dplane_ctx_intf_is_secondary(ctx))
SET_FLAG(flags, ZEBRA_IFA_SECONDARY);
+ if (dplane_ctx_intf_is_noprefixroute(ctx))
+ SET_FLAG(flags, ZEBRA_IFA_NOPREFIXROUTE);
+
/* Label? */
if (dplane_ctx_intf_has_label(ctx))
label = dplane_ctx_get_intf_label(ctx);
@@ -1356,6 +1327,13 @@ static void zebra_if_update_ctx(struct zebra_dplane_ctx *ctx,
bool pd_reason_val;
bool down;
+ if (!ifp) {
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("%s: Can't find ifp", __func__);
+
+ return;
+ }
+
dp_res = dplane_ctx_get_status(ctx);
pd_reason_val = dplane_ctx_get_intf_pd_reason_val(ctx);
down = dplane_ctx_intf_is_protodown(ctx);
@@ -1403,6 +1381,13 @@ static void zebra_if_netconf_update_ctx(struct zebra_dplane_ctx *ctx,
enum dplane_netconf_status_e mpls, mcast_on, linkdown;
bool *mcast_set, *linkdown_set;
+ if (!ifp && ifindex != -1 && ifindex != -2) {
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("%s: Can't find ifp(%u)", __func__, ifindex);
+
+ return;
+ }
+
afi = dplane_ctx_get_afi(ctx);
mpls = dplane_ctx_get_netconf_mpls(ctx);
linkdown = dplane_ctx_get_netconf_linkdown(ctx);
@@ -1425,7 +1410,7 @@ static void zebra_if_netconf_update_ctx(struct zebra_dplane_ctx *ctx,
linkdown_set = &zrouter.default_linkdownv6;
}
} else {
- zif = ifp ? ifp->info : NULL;
+ zif = ifp->info;
if (!zif) {
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
@@ -1472,6 +1457,762 @@ static void zebra_if_netconf_update_ctx(struct zebra_dplane_ctx *ctx,
(*linkdown_set ? "ON" : "OFF"));
}
+static void interface_vrf_change(enum dplane_op_e op, ifindex_t ifindex,
+ const char *name, uint32_t tableid,
+ ns_id_t ns_id)
+{
+ struct vrf *vrf;
+ struct zebra_vrf *zvrf = NULL;
+
+ if (op == DPLANE_OP_INTF_DELETE) {
+ if (IS_ZEBRA_DEBUG_DPLANE)
+ zlog_debug("DPLANE_OP_INTF_DELETE for VRF %s(%u)", name,
+ ifindex);
+
+ vrf = vrf_lookup_by_id((vrf_id_t)ifindex);
+ if (!vrf) {
+ flog_warn(EC_ZEBRA_VRF_NOT_FOUND,
+ "%s(%u): vrf not found", name, ifindex);
+ return;
+ }
+
+ vrf_delete(vrf);
+ } else {
+ if (IS_ZEBRA_DEBUG_DPLANE)
+ zlog_debug(
+ "DPLANE_OP_INTF_UPDATE for VRF %s(%u) table %u",
+ name, ifindex, tableid);
+
+ if (!vrf_lookup_by_id((vrf_id_t)ifindex)) {
+ vrf_id_t exist_id;
+
+ exist_id = zebra_vrf_lookup_by_table(tableid, ns_id);
+ if (exist_id != VRF_DEFAULT) {
+ vrf = vrf_lookup_by_id(exist_id);
+
+ if (vrf)
+ flog_err(EC_ZEBRA_VRF_MISCONFIGURED,
+ "VRF %s id %u table id overlaps existing vrf %s(%d), misconfiguration exiting",
+ name, ifindex, vrf->name,
+ vrf->vrf_id);
+ else
+ flog_err(EC_ZEBRA_VRF_NOT_FOUND,
+ "VRF %s id %u does not exist",
+ name, ifindex);
+
+ exit(-1);
+ }
+ }
+
+ vrf = vrf_update((vrf_id_t)ifindex, name);
+ if (!vrf) {
+ flog_err(EC_LIB_INTERFACE, "VRF %s id %u not created",
+ name, ifindex);
+ return;
+ }
+
+ /*
+ * This is the only place that we get the actual kernel table_id
+ * being used. We need it to set the table_id of the routes
+ * we are passing to the kernel.... And to throw some totally
+ * awesome parties. that too.
+ *
+ * At this point we *must* have a zvrf because the vrf_create
+ * callback creates one. We *must* set the table id
+ * before the vrf_enable because of( at the very least )
+ * static routes being delayed for installation until
+ * during the vrf_enable callbacks.
+ */
+ zvrf = (struct zebra_vrf *)vrf->info;
+ zvrf->table_id = tableid;
+
+ /* Enable the created VRF. */
+ if (!vrf_enable(vrf)) {
+ flog_err(EC_LIB_INTERFACE,
+ "Failed to enable VRF %s id %u", name,
+ ifindex);
+ return;
+ }
+ }
+}
+
+/*
+ * Note: on netlink systems, there should be a 1-to-1 mapping
+ * between interface names and ifindex values.
+ */
+static void set_ifindex(struct interface *ifp, ifindex_t ifi_index,
+ struct zebra_ns *zns)
+{
+ struct interface *oifp;
+
+ oifp = if_lookup_by_index_per_ns(zns, ifi_index);
+ if ((oifp != NULL) && (oifp != ifp)) {
+ if (ifi_index == IFINDEX_INTERNAL)
+ flog_err(
+ EC_LIB_INTERFACE,
+ "Netlink is setting interface %s ifindex to reserved internal value %u",
+ ifp->name, ifi_index);
+ else {
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(
+ "interface index %d was renamed from %s to %s",
+ ifi_index, oifp->name, ifp->name);
+ if (if_is_up(oifp))
+ flog_err(
+ EC_LIB_INTERFACE,
+ "interface rename detected on up interface: index %d was renamed from %s to %s, results are uncertain!",
+ ifi_index, oifp->name, ifp->name);
+ if_delete_update(&oifp);
+ }
+ }
+ if_set_index(ifp, ifi_index);
+}
+
+static inline void zebra_if_set_ziftype(struct interface *ifp,
+ enum zebra_iftype zif_type,
+ enum zebra_slave_iftype zif_slave_type)
+{
+ struct zebra_if *zif;
+
+ zif = (struct zebra_if *)ifp->info;
+ zif->zif_slave_type = zif_slave_type;
+
+ if (zif->zif_type != zif_type) {
+ zif->zif_type = zif_type;
+ /* If the if_type has been set to bond initialize ES info
+ * against it. XXX - note that we don't handle the case where
+ * a zif changes from bond to non-bond; it is really
+ * an unexpected/error condition.
+ */
+ zebra_evpn_if_init(zif);
+ }
+}
+
+static void interface_update_hw_addr(struct zebra_dplane_ctx *ctx,
+ struct interface *ifp)
+{
+ int i;
+
+ ifp->hw_addr_len = dplane_ctx_get_ifp_hw_addr_len(ctx);
+ memcpy(ifp->hw_addr, dplane_ctx_get_ifp_hw_addr(ctx), ifp->hw_addr_len);
+
+ for (i = 0; i < ifp->hw_addr_len; i++)
+ if (ifp->hw_addr[i] != 0)
+ break;
+
+ if (i == ifp->hw_addr_len)
+ ifp->hw_addr_len = 0;
+}
+
+static void interface_update_l2info(struct zebra_dplane_ctx *ctx,
+ struct interface *ifp,
+ enum zebra_iftype zif_type, int add,
+ ns_id_t link_nsid)
+{
+ const struct zebra_l2info_vxlan *vxlan_info;
+ const struct zebra_l2info_gre *gre_info;
+
+ switch (zif_type) {
+ case ZEBRA_IF_BRIDGE:
+ zebra_l2_bridge_add_update(ifp,
+ dplane_ctx_get_ifp_bridge_info(ctx));
+ break;
+ case ZEBRA_IF_VLAN:
+ zebra_l2_vlanif_update(ifp, dplane_ctx_get_ifp_vlan_info(ctx));
+ zebra_evpn_acc_bd_svi_set(ifp->info, NULL,
+ !!if_is_operative(ifp));
+ break;
+ case ZEBRA_IF_VXLAN:
+ vxlan_info = dplane_ctx_get_ifp_vxlan_info(ctx);
+ zebra_l2_vxlanif_add_update(ifp, vxlan_info, add);
+ if (link_nsid != NS_UNKNOWN && vxlan_info->ifindex_link)
+ zebra_if_update_link(ifp, vxlan_info->ifindex_link,
+ link_nsid);
+ break;
+ case ZEBRA_IF_GRE:
+ gre_info = dplane_ctx_get_ifp_gre_info(ctx);
+ zebra_l2_greif_add_update(ifp, gre_info, add);
+ if (link_nsid != NS_UNKNOWN && gre_info->ifindex_link)
+ zebra_if_update_link(ifp, gre_info->ifindex_link,
+ link_nsid);
+ break;
+ case ZEBRA_IF_OTHER:
+ case ZEBRA_IF_VRF:
+ case ZEBRA_IF_MACVLAN:
+ case ZEBRA_IF_VETH:
+ case ZEBRA_IF_BOND:
+ break;
+ }
+}
+
+static bool is_if_protodown_reason_only_frr(uint32_t rc_bitfield)
+{
+ uint8_t frr_protodown_r_bit = if_netlink_get_frr_protodown_r_bit();
+
+ return (rc_bitfield == (((uint32_t)1) << frr_protodown_r_bit));
+}
+
+static void interface_if_protodown(struct interface *ifp, bool protodown,
+ uint32_t rc_bitfield)
+{
+ struct zebra_if *zif = ifp->info;
+ bool old_protodown;
+
+ /*
+ * Set our reason code to note it wasn't us.
+ * If the reason we got from the kernel is ONLY frr though, don't
+ * set it.
+ */
+ COND_FLAG(zif->protodown_rc, ZEBRA_PROTODOWN_EXTERNAL,
+ protodown && rc_bitfield &&
+ !is_if_protodown_reason_only_frr(rc_bitfield));
+
+
+ old_protodown = !!ZEBRA_IF_IS_PROTODOWN(zif);
+ if (protodown == old_protodown)
+ return;
+
+ if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_DPLANE)
+ zlog_debug("interface %s dplane change, protodown %s",
+ ifp->name, protodown ? "on" : "off");
+
+ /* Set protodown, respectively */
+ COND_FLAG(zif->flags, ZIF_FLAG_PROTODOWN, protodown);
+
+ if (zebra_evpn_is_es_bond_member(ifp)) {
+ /* Check it's not already being sent to the dplane first */
+ if (protodown &&
+ CHECK_FLAG(zif->flags, ZIF_FLAG_SET_PROTODOWN)) {
+ if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(
+ "bond mbr %s protodown on recv'd but already sent protodown on to the dplane",
+ ifp->name);
+ return;
+ }
+
+ if (!protodown &&
+ CHECK_FLAG(zif->flags, ZIF_FLAG_UNSET_PROTODOWN)) {
+ if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(
+ "bond mbr %s protodown off recv'd but already sent protodown off to the dplane",
+ ifp->name);
+ return;
+ }
+
+ if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(
+ "bond mbr %s reinstate protodown %s in the dplane",
+ ifp->name, old_protodown ? "on" : "off");
+
+ if (old_protodown)
+ SET_FLAG(zif->flags, ZIF_FLAG_SET_PROTODOWN);
+ else
+ SET_FLAG(zif->flags, ZIF_FLAG_UNSET_PROTODOWN);
+
+ dplane_intf_update(zif->ifp);
+ }
+}
+
+static void if_sweep_protodown(struct zebra_if *zif)
+{
+ bool protodown;
+
+ protodown = !!ZEBRA_IF_IS_PROTODOWN(zif);
+
+ if (!protodown)
+ return;
+
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("interface %s sweeping protodown %s reason 0x%x",
+ zif->ifp->name, protodown ? "on" : "off",
+ zif->protodown_rc);
+
+ /* Only clear our reason codes, leave external if it was set */
+ UNSET_FLAG(zif->protodown_rc, ZEBRA_PROTODOWN_ALL);
+ dplane_intf_update(zif->ifp);
+}
+
+static void
+interface_bridge_vxlan_vlan_vni_map_update(struct zebra_dplane_ctx *ctx,
+ struct interface *ifp)
+{
+ const struct zebra_vxlan_vni_array *vniarray =
+ dplane_ctx_get_ifp_vxlan_vni_array(ctx);
+ struct zebra_vxlan_vni vni_start, vni_end;
+ struct hash *vni_table = NULL;
+ struct zebra_vxlan_vni vni, *vnip;
+ vni_t vni_id;
+ vlanid_t vid;
+ int i;
+
+ if (vniarray == NULL)
+ return;
+
+ memset(&vni_start, 0, sizeof(vni_start));
+ memset(&vni_end, 0, sizeof(vni_end));
+
+ for (i = 0; i < vniarray->count; i++) {
+ uint16_t flags = vniarray->vnis[i].flags;
+
+ if (flags & DPLANE_BRIDGE_VLAN_INFO_RANGE_BEGIN) {
+ vni_start = vniarray->vnis[i];
+ continue;
+ }
+
+ if (flags & DPLANE_BRIDGE_VLAN_INFO_RANGE_END)
+ vni_end = vniarray->vnis[i];
+
+ if (!(flags & DPLANE_BRIDGE_VLAN_INFO_RANGE_END)) {
+ vni_start = vniarray->vnis[i];
+ vni_end = vniarray->vnis[i];
+ }
+
+ if (IS_ZEBRA_DEBUG_DPLANE)
+ zlog_debug(
+ "Vlan-Vni(%d:%d-%d:%d) update for VxLAN IF %s(%u)",
+ vni_start.access_vlan, vni_end.access_vlan,
+ vni_start.vni, vni_end.vni, ifp->name,
+ ifp->ifindex);
+
+ if (!vni_table) {
+ vni_table = zebra_vxlan_vni_table_create();
+ if (!vni_table)
+ return;
+ }
+
+ for (vid = vni_start.access_vlan, vni_id = vni_start.vni;
+ vid <= vni_end.access_vlan; vid++, vni_id++) {
+
+ memset(&vni, 0, sizeof(vni));
+ vni.vni = vni_id;
+ vni.access_vlan = vid;
+ vnip = hash_get(vni_table, &vni, zebra_vxlan_vni_alloc);
+ if (!vnip)
+ return;
+ }
+
+ memset(&vni_start, 0, sizeof(vni_start));
+ memset(&vni_end, 0, sizeof(vni_end));
+ }
+
+ if (vni_table)
+ zebra_vxlan_if_vni_table_add_update(ifp, vni_table);
+}
+
+static void interface_bridge_vxlan_update(struct zebra_dplane_ctx *ctx,
+ struct interface *ifp)
+{
+ struct zebra_if *zif = ifp->info;
+ const struct zebra_dplane_bridge_vlan_info *bvinfo;
+
+ if (dplane_ctx_get_ifp_no_afspec(ctx))
+ return;
+
+ if (IS_ZEBRA_VXLAN_IF_SVD(zif))
+ interface_bridge_vxlan_vlan_vni_map_update(ctx, ifp);
+
+ if (dplane_ctx_get_ifp_no_bridge_vlan_info(ctx))
+ return;
+
+ bvinfo = dplane_ctx_get_ifp_bridge_vlan_info(ctx);
+
+ if (!(bvinfo->flags & DPLANE_BRIDGE_VLAN_INFO_PVID))
+ return;
+
+ if (IS_ZEBRA_DEBUG_DPLANE)
+ zlog_debug("Access VLAN %u for VxLAN IF %s(%u)", bvinfo->vid,
+ ifp->name, ifp->ifindex);
+
+ zebra_l2_vxlanif_update_access_vlan(ifp, bvinfo->vid);
+}
+
+static void interface_bridge_vlan_update(struct zebra_dplane_ctx *ctx,
+ struct interface *ifp)
+{
+ struct zebra_if *zif = ifp->info;
+ const struct zebra_dplane_bridge_vlan_info_array *bvarray;
+ struct zebra_dplane_bridge_vlan_info bvinfo;
+ bitfield_t old_vlan_bitmap;
+ uint16_t vid_range_start = 0;
+ int32_t i;
+
+ /* cache the old bitmap addrs */
+ old_vlan_bitmap = zif->vlan_bitmap;
+ /* create a new bitmap space for re-eval */
+ bf_init(zif->vlan_bitmap, IF_VLAN_BITMAP_MAX);
+
+ /* Could we have multiple bridge vlan infos? */
+ bvarray = dplane_ctx_get_ifp_bridge_vlan_info_array(ctx);
+ if (!bvarray)
+ return;
+
+ for (i = 0; i < bvarray->count; i++) {
+ bvinfo = bvarray->array[i];
+
+ if (bvinfo.flags & DPLANE_BRIDGE_VLAN_INFO_RANGE_BEGIN) {
+ vid_range_start = bvinfo.vid;
+ continue;
+ }
+
+ if (!(bvinfo.flags & DPLANE_BRIDGE_VLAN_INFO_RANGE_END))
+ vid_range_start = bvinfo.vid;
+
+ zebra_vlan_bitmap_compute(ifp, vid_range_start, bvinfo.vid);
+ }
+
+ zebra_vlan_mbr_re_eval(ifp, old_vlan_bitmap);
+ bf_free(old_vlan_bitmap);
+}
+
+static void interface_bridge_handling(struct zebra_dplane_ctx *ctx,
+ struct interface *ifp,
+ enum zebra_iftype zif_type)
+{
+ struct zebra_if *zif;
+
+ if (!ifp) {
+ zlog_warn("Cannot find bridge if %s(%u)",
+ dplane_ctx_get_ifname(ctx),
+ dplane_ctx_get_ifindex(ctx));
+ return;
+ }
+
+ if (IS_ZEBRA_IF_VXLAN(ifp))
+ return interface_bridge_vxlan_update(ctx, ifp);
+
+ /*
+ * build vlan bitmap associated with this interface if that
+ * device type is interested in the vlans
+ */
+ zif = ifp->info;
+ if (bf_is_inited(zif->vlan_bitmap))
+ interface_bridge_vlan_update(ctx, ifp);
+}
+
+static void zebra_if_dplane_ifp_handling(struct zebra_dplane_ctx *ctx)
+{
+ enum dplane_op_e op = dplane_ctx_get_op(ctx);
+ const char *name = dplane_ctx_get_ifname(ctx);
+ ns_id_t ns_id = dplane_ctx_get_ns_id(ctx);
+ ifindex_t ifindex = dplane_ctx_get_ifindex(ctx);
+ ifindex_t bond_ifindex = dplane_ctx_get_ifp_bond_ifindex(ctx);
+ uint32_t tableid = dplane_ctx_get_ifp_table_id(ctx);
+ enum zebra_iftype zif_type = dplane_ctx_get_ifp_zif_type(ctx);
+ struct interface *ifp;
+ struct zebra_ns *zns;
+
+ zns = zebra_ns_lookup(ns_id);
+ if (!zns) {
+ zlog_err("Where is our namespace?");
+ return;
+ }
+
+ if (IS_ZEBRA_DEBUG_DPLANE)
+ zlog_debug("%s for %s(%u)", dplane_op2str(op), name, ifindex);
+
+ ifp = if_lookup_by_name_per_ns(zns, name);
+ if (op == DPLANE_OP_INTF_DELETE) {
+ /* Delete interface notification from kernel */
+ if (ifp == NULL) {
+ if (IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug(
+ "Delete LINK received for unknown interface %s(%u)",
+ name, ifindex);
+ return;
+ }
+
+ if (IS_ZEBRA_IF_BOND(ifp))
+ zebra_l2if_update_bond(ifp, false);
+ if (IS_ZEBRA_IF_BOND_SLAVE(ifp))
+ zebra_l2if_update_bond_slave(ifp, bond_ifindex, false);
+ /* Special handling for bridge or VxLAN interfaces. */
+ if (IS_ZEBRA_IF_BRIDGE(ifp))
+ zebra_l2_bridge_del(ifp);
+ else if (IS_ZEBRA_IF_VXLAN(ifp))
+ zebra_l2_vxlanif_del(ifp);
+
+ if_delete_update(&ifp);
+
+ if (zif_type == ZEBRA_IF_VRF && !vrf_is_backend_netns())
+ interface_vrf_change(op, ifindex, name, tableid, ns_id);
+ } else {
+ ifindex_t master_ifindex, bridge_ifindex, bond_ifindex,
+ link_ifindex;
+ enum zebra_slave_iftype zif_slave_type;
+ uint8_t bypass;
+ uint64_t flags;
+ vrf_id_t vrf_id;
+ uint32_t mtu;
+ ns_id_t link_nsid;
+ struct zebra_if *zif;
+ bool protodown, protodown_set, startup;
+ uint32_t rc_bitfield;
+ uint8_t old_hw_addr[INTERFACE_HWADDR_MAX];
+ char *desc;
+ uint8_t family;
+
+ /* If VRF, create or update the VRF structure itself. */
+ if (zif_type == ZEBRA_IF_VRF && !vrf_is_backend_netns())
+ interface_vrf_change(op, ifindex, name, tableid, ns_id);
+
+ master_ifindex = dplane_ctx_get_ifp_master_ifindex(ctx);
+ zif_slave_type = dplane_ctx_get_ifp_zif_slave_type(ctx);
+ bridge_ifindex = dplane_ctx_get_ifp_bridge_ifindex(ctx);
+ bond_ifindex = dplane_ctx_get_ifp_bond_ifindex(ctx);
+ bypass = dplane_ctx_get_ifp_bypass(ctx);
+ flags = dplane_ctx_get_ifp_flags(ctx);
+ vrf_id = dplane_ctx_get_ifp_vrf_id(ctx);
+ mtu = dplane_ctx_get_ifp_mtu(ctx);
+ link_ifindex = dplane_ctx_get_ifp_link_ifindex(ctx);
+ link_nsid = dplane_ctx_get_ifp_link_nsid(ctx);
+ protodown_set = dplane_ctx_get_ifp_protodown_set(ctx);
+ protodown = dplane_ctx_get_ifp_protodown(ctx);
+ rc_bitfield = dplane_ctx_get_ifp_rc_bitfield(ctx);
+ startup = dplane_ctx_get_ifp_startup(ctx);
+ desc = dplane_ctx_get_ifp_desc(ctx);
+ family = dplane_ctx_get_ifp_family(ctx);
+
+#ifndef AF_BRIDGE
+ /*
+ * Work around to make free bsd happy at the moment
+ */
+#define AF_BRIDGE 7
+#endif
+ if (family == AF_BRIDGE)
+ return interface_bridge_handling(ctx, ifp, zif_type);
+
+ if (ifp == NULL ||
+ !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
+ /* Add interface notification from kernel */
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(
+ "RTM_NEWLINK ADD for %s(%u) vrf_id %u type %d sl_type %d master %u",
+ name, ifindex, vrf_id, zif_type,
+ zif_slave_type, master_ifindex);
+
+ if (ifp == NULL) {
+ /* unknown interface */
+ ifp = if_get_by_name(name, vrf_id, NULL);
+ } else {
+ /* pre-configured interface, learnt now */
+ if (ifp->vrf->vrf_id != vrf_id)
+ if_update_to_new_vrf(ifp, vrf_id);
+ }
+
+ zif = ifp->info;
+
+ /* Update interface information. */
+ set_ifindex(ifp, ifindex, zns);
+ ifp->flags = flags;
+ ifp->mtu6 = ifp->mtu = mtu;
+ ifp->metric = 0;
+ ifp->speed = kernel_get_speed(ifp, NULL);
+ ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN;
+ ifp->txqlen = dplane_ctx_get_intf_txqlen(ctx);
+
+ /* Set interface type */
+ zebra_if_set_ziftype(ifp, zif_type, zif_slave_type);
+ if (IS_ZEBRA_IF_VRF(ifp))
+ SET_FLAG(ifp->status,
+ ZEBRA_INTERFACE_VRF_LOOPBACK);
+
+ /* Update link. */
+ zebra_if_update_link(ifp, link_ifindex, link_nsid);
+
+ ifp->ll_type = dplane_ctx_get_ifp_zltype(ctx);
+ interface_update_hw_addr(ctx, ifp);
+
+ /* Inform clients, install any configured addresses. */
+ if_add_update(ifp);
+
+ /*
+ * Extract and save L2 interface information, take
+ * additional actions.
+ */
+ interface_update_l2info(ctx, ifp, zif_type, 1,
+ link_nsid);
+ if (IS_ZEBRA_IF_BOND(ifp))
+ zebra_l2if_update_bond(ifp, true);
+ if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp))
+ zebra_l2if_update_bridge_slave(
+ ifp, bridge_ifindex, ns_id,
+ ZEBRA_BRIDGE_NO_ACTION);
+ else if (IS_ZEBRA_IF_BOND_SLAVE(ifp))
+ zebra_l2if_update_bond_slave(ifp, bond_ifindex,
+ !!bypass);
+
+ if (protodown_set) {
+ interface_if_protodown(ifp, protodown,
+ rc_bitfield);
+ if (startup)
+ if_sweep_protodown(zif);
+ }
+
+ if (IS_ZEBRA_IF_BRIDGE(ifp)) {
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(
+ "RTM_NEWLINK ADD for %s(%u), vlan-aware %d",
+ name, ifp->ifindex,
+ IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(
+ zif));
+ }
+ } else if (ifp->vrf->vrf_id != vrf_id) {
+ /* VRF change for an interface. */
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(
+ "RTM_NEWLINK vrf-change for %s(%u) vrf_id %u -> %u",
+ name, ifp->ifindex, ifp->vrf->vrf_id,
+ vrf_id);
+
+ if_handle_vrf_change(ifp, vrf_id);
+ } else {
+ bool was_bridge_slave, was_bond_slave;
+ uint8_t chgflags = ZEBRA_BRIDGE_NO_ACTION;
+
+ zif = ifp->info;
+
+ /* Interface update. */
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(
+ "RTM_NEWLINK update for %s(%u) sl_type %d master %u",
+ name, ifp->ifindex, zif_slave_type,
+ master_ifindex);
+
+ set_ifindex(ifp, ifindex, zns);
+ ifp->mtu6 = ifp->mtu = mtu;
+ ifp->metric = 0;
+ ifp->txqlen = dplane_ctx_get_intf_txqlen(ctx);
+
+ /*
+ * Update interface type - NOTE: Only slave_type can
+ * change.
+ */
+ was_bridge_slave = IS_ZEBRA_IF_BRIDGE_SLAVE(ifp);
+ was_bond_slave = IS_ZEBRA_IF_BOND_SLAVE(ifp);
+ zebra_if_set_ziftype(ifp, zif_type, zif_slave_type);
+
+ memcpy(old_hw_addr, ifp->hw_addr, INTERFACE_HWADDR_MAX);
+
+ /* Update link. */
+ zebra_if_update_link(ifp, link_ifindex, link_nsid);
+
+ ifp->ll_type = dplane_ctx_get_ifp_zltype(ctx);
+ interface_update_hw_addr(ctx, ifp);
+
+ if (protodown_set)
+ interface_if_protodown(ifp, protodown,
+ rc_bitfield);
+
+ if (if_is_no_ptm_operative(ifp)) {
+ bool is_up = if_is_operative(ifp);
+
+ ifp->flags = flags;
+ if (!if_is_no_ptm_operative(ifp) ||
+ CHECK_FLAG(zif->flags,
+ ZIF_FLAG_PROTODOWN)) {
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(
+ "Intf %s(%u) has gone DOWN",
+ name, ifp->ifindex);
+ if_down(ifp);
+ rib_update(RIB_UPDATE_KERNEL);
+ } else if (if_is_operative(ifp)) {
+ bool mac_updated = false;
+
+ /*
+ * Must notify client daemons of new
+ * interface status.
+ */
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(
+ "Intf %s(%u) PTM up, notifying clients",
+ name, ifp->ifindex);
+ if_up(ifp, !is_up);
+
+ /*
+ * Update EVPN VNI when SVI MAC change
+ */
+ if (memcmp(old_hw_addr, ifp->hw_addr,
+ INTERFACE_HWADDR_MAX))
+ mac_updated = true;
+ if (IS_ZEBRA_IF_VLAN(ifp) &&
+ mac_updated) {
+ struct interface *link_if;
+
+ link_if = if_lookup_by_index_per_ns(
+ zebra_ns_lookup(
+ NS_DEFAULT),
+ link_ifindex);
+ if (link_if)
+ zebra_vxlan_svi_up(
+ ifp, link_if);
+ } else if (mac_updated &&
+ IS_ZEBRA_IF_BRIDGE(ifp)) {
+ zlog_debug(
+ "Intf %s(%u) bridge changed MAC address",
+ name, ifp->ifindex);
+ chgflags =
+ ZEBRA_BRIDGE_MASTER_MAC_CHANGE;
+ }
+ }
+ } else {
+ ifp->flags = flags;
+ if (if_is_operative(ifp) &&
+ !CHECK_FLAG(zif->flags,
+ ZIF_FLAG_PROTODOWN)) {
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(
+ "Intf %s(%u) has come UP",
+ name, ifp->ifindex);
+ if_up(ifp, true);
+ if (IS_ZEBRA_IF_BRIDGE(ifp))
+ chgflags =
+ ZEBRA_BRIDGE_MASTER_UP;
+ } else {
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(
+ "Intf %s(%u) has gone DOWN",
+ name, ifp->ifindex);
+ if_down(ifp);
+ rib_update(RIB_UPDATE_KERNEL);
+ }
+ }
+
+ /*
+ * Extract and save L2 interface information, take
+ * additional actions.
+ */
+ interface_update_l2info(ctx, ifp, zif_type, 0,
+ link_nsid);
+ if (IS_ZEBRA_IF_BRIDGE(ifp))
+ zebra_l2if_update_bridge(ifp, chgflags);
+ if (IS_ZEBRA_IF_BOND(ifp))
+ zebra_l2if_update_bond(ifp, true);
+ if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp) || was_bridge_slave)
+ zebra_l2if_update_bridge_slave(
+ ifp, bridge_ifindex, ns_id, chgflags);
+ else if (IS_ZEBRA_IF_BOND_SLAVE(ifp) || was_bond_slave)
+ zebra_l2if_update_bond_slave(ifp, bond_ifindex,
+ !!bypass);
+ if (IS_ZEBRA_IF_BRIDGE(ifp)) {
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(
+ "RTM_NEWLINK update for %s(%u), vlan-aware %d",
+ name, ifp->ifindex,
+ IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(
+ zif));
+ }
+ }
+
+ zif = ifp->info;
+ if (zif) {
+ XFREE(MTYPE_ZIF_DESC, zif->desc);
+ if (desc[0])
+ zif->desc = XSTRDUP(MTYPE_ZIF_DESC, desc);
+ }
+ }
+}
+
void zebra_if_dplane_result(struct zebra_dplane_ctx *ctx)
{
struct zebra_ns *zns;
@@ -1501,83 +2242,22 @@ void zebra_if_dplane_result(struct zebra_dplane_ctx *ctx)
}
ifp = if_lookup_by_index_per_ns(zns, ifindex);
- if (ifp == NULL) {
- if (op != DPLANE_OP_INTF_NETCONFIG ||
- (ifindex != -1 && ifindex != -2)) {
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug(
- "%s: can't find ifp at nsid %u index %d",
- __func__, ns_id, ifindex);
-
- return;
- }
- }
- switch (op) {
- case DPLANE_OP_INTF_ADDR_ADD:
- case DPLANE_OP_INTF_ADDR_DEL:
+ if (op == DPLANE_OP_INTF_ADDR_ADD || op == DPLANE_OP_INTF_ADDR_DEL) {
zebra_if_addr_update_ctx(ctx, ifp);
- break;
-
- case DPLANE_OP_INTF_INSTALL:
- case DPLANE_OP_INTF_UPDATE:
- case DPLANE_OP_INTF_DELETE:
- zebra_if_update_ctx(ctx, ifp);
- break;
-
- case DPLANE_OP_INTF_NETCONFIG:
+ } else if (op == DPLANE_OP_INTF_INSTALL ||
+ op == DPLANE_OP_INTF_UPDATE || op == DPLANE_OP_INTF_DELETE) {
+ /*
+ * Queued from the dplane means it is something
+ * that we need to handle( create/delete the
+ * interface as needed )
+ */
+ if (dp_res == ZEBRA_DPLANE_REQUEST_QUEUED)
+ zebra_if_dplane_ifp_handling(ctx);
+ else
+ zebra_if_update_ctx(ctx, ifp);
+ } else if (op == DPLANE_OP_INTF_NETCONFIG) {
zebra_if_netconf_update_ctx(ctx, ifp, ifindex);
- break;
-
- case DPLANE_OP_ROUTE_INSTALL:
- case DPLANE_OP_ROUTE_UPDATE:
- case DPLANE_OP_ROUTE_DELETE:
- case DPLANE_OP_NH_DELETE:
- case DPLANE_OP_NH_INSTALL:
- case DPLANE_OP_NH_UPDATE:
- case DPLANE_OP_ROUTE_NOTIFY:
- case DPLANE_OP_LSP_INSTALL:
- case DPLANE_OP_LSP_UPDATE:
- case DPLANE_OP_LSP_DELETE:
- case DPLANE_OP_LSP_NOTIFY:
- case DPLANE_OP_PW_INSTALL:
- case DPLANE_OP_PW_UNINSTALL:
- case DPLANE_OP_SYS_ROUTE_ADD:
- case DPLANE_OP_SYS_ROUTE_DELETE:
- case DPLANE_OP_ADDR_INSTALL:
- case DPLANE_OP_ADDR_UNINSTALL:
- case DPLANE_OP_MAC_INSTALL:
- case DPLANE_OP_MAC_DELETE:
- case DPLANE_OP_NEIGH_INSTALL:
- case DPLANE_OP_NEIGH_UPDATE:
- case DPLANE_OP_NEIGH_DELETE:
- case DPLANE_OP_NEIGH_IP_INSTALL:
- case DPLANE_OP_NEIGH_IP_DELETE:
- case DPLANE_OP_VTEP_ADD:
- case DPLANE_OP_VTEP_DELETE:
- case DPLANE_OP_RULE_ADD:
- case DPLANE_OP_RULE_DELETE:
- case DPLANE_OP_RULE_UPDATE:
- case DPLANE_OP_NEIGH_DISCOVER:
- case DPLANE_OP_BR_PORT_UPDATE:
- case DPLANE_OP_NONE:
- case DPLANE_OP_IPTABLE_ADD:
- case DPLANE_OP_IPTABLE_DELETE:
- case DPLANE_OP_IPSET_ADD:
- case DPLANE_OP_IPSET_DELETE:
- case DPLANE_OP_IPSET_ENTRY_ADD:
- case DPLANE_OP_IPSET_ENTRY_DELETE:
- case DPLANE_OP_NEIGH_TABLE_UPDATE:
- case DPLANE_OP_GRE_SET:
- case DPLANE_OP_TC_QDISC_INSTALL:
- case DPLANE_OP_TC_QDISC_UNINSTALL:
- case DPLANE_OP_TC_CLASS_ADD:
- case DPLANE_OP_TC_CLASS_DELETE:
- case DPLANE_OP_TC_CLASS_UPDATE:
- case DPLANE_OP_TC_FILTER_ADD:
- case DPLANE_OP_TC_FILTER_DELETE:
- case DPLANE_OP_TC_FILTER_UPDATE:
- break; /* should never hit here */
}
}
@@ -1617,6 +2297,12 @@ static void connected_dump_vty(struct vty *vty, json_object *json,
vty_out(vty, " secondary");
if (json)
+ json_object_boolean_add(json_addr, "noPrefixRoute",
+ CHECK_FLAG(connected->flags, ZEBRA_IFA_NOPREFIXROUTE));
+ else if (CHECK_FLAG(connected->flags, ZEBRA_IFA_NOPREFIXROUTE))
+ vty_out(vty, " noprefixroute");
+
+ if (json)
json_object_boolean_add(
json_addr, "unnumbered",
CHECK_FLAG(connected->flags, ZEBRA_IFA_UNNUMBERED));
@@ -1692,9 +2378,6 @@ static const char *zebra_ziftype_2str(enum zebra_iftype zif_type)
case ZEBRA_IF_BOND:
return "bond";
- case ZEBRA_IF_BOND_SLAVE:
- return "bond_slave";
-
case ZEBRA_IF_MACVLAN:
return "macvlan";
@@ -1768,34 +2451,27 @@ static void ifs_dump_brief_vty(struct vty *vty, struct vrf *vrf)
}
uint32_t v6_list_size = 0;
- for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) {
+ frr_each (if_connected, ifp->connected, connected) {
if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL)
&& (connected->address->family == AF_INET6))
v6_list_size++;
}
- for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) {
- if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL)
- && !CHECK_FLAG(connected->flags,
- ZEBRA_IFA_SECONDARY)
- && (connected->address->family == AF_INET6)) {
+ frr_each (if_connected, ifp->connected, connected) {
+ if (!CHECK_FLAG(connected->flags, ZEBRA_IFA_SECONDARY) &&
+ (connected->address->family == AF_INET6)) {
p = connected->address;
- /* Don't print link local pfx */
- if (!IN6_IS_ADDR_LINKLOCAL(&p->u.prefix6)) {
- if (first_pfx_printed) {
- /* padding to prepare row only
- * for ip addr */
- vty_out(vty, "%-40s", "");
- if (v6_list_size > 1)
- vty_out(vty, "+ ");
- vty_out(vty, "%pFX\n", p);
- } else {
- if (v6_list_size > 1)
- vty_out(vty, "+ ");
- vty_out(vty, "%pFX\n", p);
- }
- first_pfx_printed = true;
- break;
+ if (first_pfx_printed) {
+ vty_out(vty, "%-40s", "");
+ if (v6_list_size > 1)
+ vty_out(vty, "+ ");
+ vty_out(vty, "%pFX\n", p);
+ } else {
+ if (v6_list_size > 1)
+ vty_out(vty, "+ ");
+ vty_out(vty, "%pFX\n", p);
}
+ first_pfx_printed = true;
+ break;
}
}
if (!first_pfx_printed)
@@ -1807,7 +2483,6 @@ static void ifs_dump_brief_vty(struct vty *vty, struct vrf *vrf)
static void ifs_dump_brief_vty_json(json_object *json, struct vrf *vrf)
{
struct connected *connected;
- struct listnode *node;
struct interface *ifp;
FOR_ALL_INTERFACES (vrf, ifp) {
@@ -1823,13 +2498,8 @@ static void ifs_dump_brief_vty_json(json_object *json, struct vrf *vrf)
json_addrs = json_object_new_array();
json_object_object_add(json_if, "addresses", json_addrs);
- for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) {
- if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL)
- && !CHECK_FLAG(connected->flags,
- ZEBRA_IFA_SECONDARY)
- && !(connected->address->family == AF_INET6
- && IN6_IS_ADDR_LINKLOCAL(
- &connected->address->u.prefix6))) {
+ frr_each (if_connected, ifp->connected, connected) {
+ if (!CHECK_FLAG(connected->flags, ZEBRA_IFA_SECONDARY)) {
char buf[PREFIX2STR_BUFFER];
json_array_string_add(
@@ -1990,8 +2660,8 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp)
return;
}
- vty_out(vty, " index %d metric %d mtu %d speed %u ", ifp->ifindex,
- ifp->metric, ifp->mtu, ifp->speed);
+ vty_out(vty, " index %d metric %d mtu %d speed %u txqlen %u",
+ ifp->ifindex, ifp->metric, ifp->mtu, ifp->speed, ifp->txqlen);
if (ifp->mtu6 != ifp->mtu)
vty_out(vty, "mtu6 %d ", ifp->mtu6);
vty_out(vty, "\n flags: %s\n", if_flag_dump(ifp->flags));
@@ -2036,9 +2706,8 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp)
connected_dump_vty(vty, NULL, connected);
}
- for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) {
- if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL)
- && (connected->address->family == AF_INET6))
+ frr_each (if_connected, ifp->connected, connected) {
+ if (connected->address->family == AF_INET6)
connected_dump_vty(vty, NULL, connected);
}
@@ -2170,8 +2839,8 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp)
" Link Delay Variation %u (micro-sec.)\n",
iflp->delay_var);
if (IS_PARAM_SET(iflp, LP_PKT_LOSS))
- vty_out(vty, " Link Packet Loss %g (in %%)\n",
- iflp->pkt_loss);
+ vty_out(vty, " Link Packet Loss %f (in %%)\n",
+ (double)iflp->pkt_loss * LOSS_PRECISION);
if (IS_PARAM_SET(iflp, LP_AVA_BW))
vty_out(vty, " Available Bandwidth %g (Byte/s)\n",
iflp->ava_bw);
@@ -2345,7 +3014,7 @@ static void if_dump_vty_json(struct vty *vty, struct interface *ifp,
json_object_string_add(json_if, "lastLinkDown",
zebra_if->down_last);
- zebra_ptm_show_status(vty, json, ifp);
+ zebra_ptm_show_status(vty, json_if, ifp);
json_object_string_add(json_if, "vrfName", ifp->vrf->name);
@@ -2378,6 +3047,7 @@ static void if_dump_vty_json(struct vty *vty, struct interface *ifp,
if (ifp->mtu6 != ifp->mtu)
json_object_int_add(json_if, "mtu6", ifp->mtu6);
json_object_int_add(json_if, "speed", ifp->speed);
+ json_object_int_add(json_if, "txqlen", ifp->txqlen);
json_object_string_add(json_if, "flags", if_flag_dump(ifp->flags));
/* Hardware address. */
@@ -2412,9 +3082,8 @@ static void if_dump_vty_json(struct vty *vty, struct interface *ifp,
connected_dump_vty(vty, json_addrs, connected);
}
- for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) {
- if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL)
- && (connected->address->family == AF_INET6))
+ frr_each (if_connected, ifp->connected, connected) {
+ if (connected->address->family == AF_INET6)
connected_dump_vty(vty, json_addrs, connected);
}
@@ -2571,7 +3240,8 @@ static void if_dump_vty_json(struct vty *vty, struct interface *ifp,
iflp->delay_var);
if (IS_PARAM_SET(iflp, LP_PKT_LOSS))
json_object_double_add(json_te, "linkPacketLoss",
- iflp->pkt_loss);
+ (double)iflp->pkt_loss *
+ LOSS_PRECISION);
if (IS_PARAM_SET(iflp, LP_AVA_BW))
json_object_double_add(json_te, "availableBandwidth",
iflp->ava_bw);
@@ -2955,66 +3625,43 @@ DEFUN (show_interface_desc_vrf_all,
return CMD_SUCCESS;
}
-int if_multicast_set(struct interface *ifp)
+void if_arp(struct interface *ifp, bool enable)
{
- struct zebra_if *if_data;
+ int ret;
- if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
- if (if_set_flags(ifp, IFF_MULTICAST) < 0) {
- zlog_debug("Can't set multicast flag on interface %s",
- ifp->name);
- return -1;
- }
- if_refresh(ifp);
+ if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE))
+ return;
+
+ if (enable)
+ ret = if_unset_flags(ifp, IFF_NOARP);
+ else
+ ret = if_set_flags(ifp, IFF_NOARP);
+
+ if (ret < 0) {
+ zlog_debug("Can't %sset noarp flag on interface %s",
+ enable ? "" : "un", ifp->name);
+ return;
}
- if_data = ifp->info;
- if_data->multicast = IF_ZEBRA_DATA_ON;
- return 0;
+ if_refresh(ifp);
}
-DEFUN (multicast,
- multicast_cmd,
- "multicast",
- "Set multicast flag to interface\n")
+int if_multicast_set(struct interface *ifp)
{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- int ret;
struct zebra_if *if_data;
if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
- ret = if_set_flags(ifp, IFF_MULTICAST);
- if (ret < 0) {
- vty_out(vty, "Can't set multicast flag\n");
- return CMD_WARNING_CONFIG_FAILED;
+ if (if_set_flags(ifp, IFF_MULTICAST) < 0) {
+ zlog_debug("Can't set multicast flag on interface %s",
+ ifp->name);
+ return -1;
}
if_refresh(ifp);
}
if_data = ifp->info;
if_data->multicast = IF_ZEBRA_DATA_ON;
- return CMD_SUCCESS;
-}
-
-DEFPY (mpls,
- mpls_cmd,
- "[no] mpls enable",
- NO_STR
- MPLS_STR
- "Set mpls to be on for the interface\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *if_data = ifp->info;
-
- if (no) {
- dplane_intf_mpls_modify_state(ifp, false);
- if_data->mpls = IF_ZEBRA_DATA_UNSPEC;
- } else {
- dplane_intf_mpls_modify_state(ifp, true);
- if_data->mpls = IF_ZEBRA_DATA_ON;
- }
-
- return CMD_SUCCESS;
+ return 0;
}
int if_multicast_unset(struct interface *ifp)
@@ -3035,30 +3682,6 @@ int if_multicast_unset(struct interface *ifp)
return 0;
}
-DEFUN (no_multicast,
- no_multicast_cmd,
- "no multicast",
- NO_STR
- "Unset multicast flag to interface\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- int ret;
- struct zebra_if *if_data;
-
- if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
- ret = if_unset_flags(ifp, IFF_MULTICAST);
- if (ret < 0) {
- vty_out(vty, "Can't unset multicast flag\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
- if_refresh(ifp);
- }
- if_data = ifp->info;
- if_data->multicast = IF_ZEBRA_DATA_OFF;
-
- return CMD_SUCCESS;
-}
-
int if_linkdetect(struct interface *ifp, bool detect)
{
int if_was_operative;
@@ -3082,30 +3705,6 @@ int if_linkdetect(struct interface *ifp, bool detect)
return 0;
}
-DEFUN(linkdetect, linkdetect_cmd, "link-detect",
- "Enable link detection on interface\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
-
- if_linkdetect(ifp, true);
-
- return CMD_SUCCESS;
-}
-
-
-DEFUN (no_linkdetect,
- no_linkdetect_cmd,
- "no link-detect",
- NO_STR
- "Disable link detection on interface\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
-
- if_linkdetect(ifp, false);
-
- return CMD_SUCCESS;
-}
-
int if_shutdown(struct interface *ifp)
{
struct zebra_if *if_data;
@@ -3125,31 +3724,6 @@ int if_shutdown(struct interface *ifp)
return 0;
}
-DEFUN (shutdown_if,
- shutdown_if_cmd,
- "shutdown",
- "Shutdown the selected interface\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- int ret;
- struct zebra_if *if_data;
-
- if (ifp->ifindex != IFINDEX_INTERNAL) {
- /* send RA lifetime of 0 before stopping. rfc4861/6.2.5 */
- rtadv_stop_ra(ifp);
- ret = if_unset_flags(ifp, IFF_UP);
- if (ret < 0) {
- vty_out(vty, "Can't shutdown interface\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
- if_refresh(ifp);
- }
- if_data = ifp->info;
- if_data->shutdown = IF_ZEBRA_DATA_ON;
-
- return CMD_SUCCESS;
-}
-
int if_no_shutdown(struct interface *ifp)
{
struct zebra_if *if_data;
@@ -3174,984 +3748,56 @@ int if_no_shutdown(struct interface *ifp)
return 0;
}
-DEFUN (no_shutdown_if,
- no_shutdown_if_cmd,
- "no shutdown",
- NO_STR
- "Shutdown the selected interface\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- int ret;
- struct zebra_if *if_data;
-
- if (ifp->ifindex != IFINDEX_INTERNAL) {
- ret = if_set_flags(ifp, IFF_UP | IFF_RUNNING);
- if (ret < 0) {
- vty_out(vty, "Can't up interface\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
- if_refresh(ifp);
-
- /* Some addresses (in particular, IPv6 addresses on Linux) get
- * removed when the interface goes down. They need to be
- * readded.
- */
- if_addr_wakeup(ifp);
- }
-
- if_data = ifp->info;
- if_data->shutdown = IF_ZEBRA_DATA_OFF;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (bandwidth_if,
- bandwidth_if_cmd,
- "bandwidth (1-100000)",
- "Set bandwidth informational parameter\n"
- "Bandwidth in megabits\n")
-{
- int idx_number = 1;
- VTY_DECLVAR_CONTEXT(interface, ifp);
- unsigned int bandwidth;
-
- bandwidth = strtol(argv[idx_number]->arg, NULL, 10);
-
- /* bandwidth range is <1-100000> */
- if (bandwidth < 1 || bandwidth > 100000) {
- vty_out(vty, "Bandwidth is invalid\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- ifp->bandwidth = bandwidth;
-
- /* force protocols to recalculate routes due to cost change */
- if (if_is_operative(ifp))
- zebra_interface_up_update(ifp);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_bandwidth_if,
- no_bandwidth_if_cmd,
- "no bandwidth [(1-100000)]",
- NO_STR
- "Set bandwidth informational parameter\n"
- "Bandwidth in megabits\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
-
- ifp->bandwidth = 0;
-
- /* force protocols to recalculate routes due to cost change */
- if (if_is_operative(ifp))
- zebra_interface_up_update(ifp);
-
- return CMD_SUCCESS;
-}
-
-
-struct cmd_node link_params_node = {
- .name = "link-params",
- .node = LINK_PARAMS_NODE,
- .parent_node = INTERFACE_NODE,
- .prompt = "%s(config-link-params)# ",
- .no_xpath = true,
-};
-
-static void link_param_cmd_set_uint32(struct interface *ifp, uint32_t *field,
- uint32_t type, uint32_t value)
+void link_param_cmd_set_uint32(struct interface *ifp, uint32_t *field,
+ uint32_t type, uint32_t value)
{
/* Update field as needed */
if (IS_PARAM_UNSET(ifp->link_params, type) || *field != value) {
*field = value;
SET_PARAM(ifp->link_params, type);
-
- /* force protocols to update LINK STATE due to parameters change
- */
- if (if_is_operative(ifp))
- zebra_interface_parameters_update(ifp);
}
}
-static void link_param_cmd_set_float(struct interface *ifp, float *field,
- uint32_t type, float value)
-{
+void link_param_cmd_set_float(struct interface *ifp, float *field,
+ uint32_t type, float value)
+{
/* Update field as needed */
if (IS_PARAM_UNSET(ifp->link_params, type) || *field != value) {
*field = value;
SET_PARAM(ifp->link_params, type);
-
- /* force protocols to update LINK STATE due to parameters change
- */
- if (if_is_operative(ifp))
- zebra_interface_parameters_update(ifp);
}
}
-static void link_param_cmd_unset(struct interface *ifp, uint32_t type)
+void link_param_cmd_unset(struct interface *ifp, uint32_t type)
{
if (ifp->link_params == NULL)
return;
/* Unset field */
UNSET_PARAM(ifp->link_params, type);
-
- /* force protocols to update LINK STATE due to parameters change */
- if (if_is_operative(ifp))
- zebra_interface_parameters_update(ifp);
-}
-
-DEFUN_NOSH (link_params,
- link_params_cmd,
- "link-params",
- LINK_PARAMS_STR)
-{
- /* vty->qobj_index stays the same @ interface pointer */
- vty->node = LINK_PARAMS_NODE;
-
- return CMD_SUCCESS;
-}
-
-DEFUN_NOSH (exit_link_params,
- exit_link_params_cmd,
- "exit-link-params",
- "Exit from Link Params configuration mode\n")
-{
- if (vty->node == LINK_PARAMS_NODE)
- vty->node = INTERFACE_NODE;
- return CMD_SUCCESS;
-}
-
-/* Specific Traffic Engineering parameters commands */
-DEFUN (link_params_enable,
- link_params_enable_cmd,
- "enable",
- "Activate link parameters on this interface\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
-
- /* This command could be issue at startup, when activate MPLS TE */
- /* on a new interface or after a ON / OFF / ON toggle */
- /* In all case, TE parameters are reset to their default factory */
- if (IS_ZEBRA_DEBUG_EVENT || IS_ZEBRA_DEBUG_MPLS)
- zlog_debug(
- "Link-params: enable TE link parameters on interface %s",
- ifp->name);
-
- if (!if_link_params_get(ifp))
- if_link_params_enable(ifp);
-
- /* force protocols to update LINK STATE due to parameters change */
- if (if_is_operative(ifp))
- zebra_interface_parameters_update(ifp);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_link_params_enable,
- no_link_params_enable_cmd,
- "no enable",
- NO_STR
- "Disable link parameters on this interface\n")
-{
- char xpath[XPATH_MAXLEN];
- int ret;
- VTY_DECLVAR_CONTEXT(interface, ifp);
-
- if (IS_ZEBRA_DEBUG_EVENT || IS_ZEBRA_DEBUG_MPLS)
- zlog_debug("MPLS-TE: disable TE link parameters on interface %s",
- ifp->name);
-
- if_link_params_free(ifp);
-
- snprintf(
- xpath, sizeof(xpath),
- "/frr-interface:lib/interface[name='%s']/frr-zebra:zebra/link-params/affinities",
- ifp->name);
- if (yang_dnode_exists(running_config->dnode, xpath))
- nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
-
- ret = nb_cli_apply_changes(vty, NULL);
-
- if (ret != CMD_SUCCESS)
- return ret;
-
- /* force protocols to update LINK STATE due to parameters change */
- if (if_is_operative(ifp))
- zebra_interface_parameters_update(ifp);
-
- return CMD_SUCCESS;
}
-/* STANDARD TE metrics */
-DEFUN (link_params_metric,
- link_params_metric_cmd,
- "metric (0-4294967295)",
- "Link metric for MPLS-TE purpose\n"
- "Metric value in decimal\n")
-{
- int idx_number = 1;
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct if_link_params *iflp = if_link_params_get(ifp);
- uint32_t metric;
-
- metric = strtoul(argv[idx_number]->arg, NULL, 10);
-
- if (!iflp)
- iflp = if_link_params_enable(ifp);
-
- /* Update TE metric if needed */
- link_param_cmd_set_uint32(ifp, &iflp->te_metric, LP_TE_METRIC, metric);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_link_params_metric,
- no_link_params_metric_cmd,
- "no metric",
- NO_STR
- "Disable Link Metric on this interface\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
-
- /* Unset TE Metric */
- link_param_cmd_unset(ifp, LP_TE_METRIC);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (link_params_maxbw,
- link_params_maxbw_cmd,
- "max-bw BANDWIDTH",
- "Maximum bandwidth that can be used\n"
- "Bytes/second (IEEE floating point format)\n")
-{
- int idx_bandwidth = 1;
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct if_link_params *iflp = if_link_params_get(ifp);
-
- float bw;
-
- if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) {
- vty_out(vty, "link_params_maxbw: fscanf: %s\n",
- safe_strerror(errno));
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- /* Check that Maximum bandwidth is not lower than other bandwidth
- * parameters */
- if (iflp && ((bw <= iflp->max_rsv_bw) || (bw <= iflp->unrsv_bw[0]) ||
- (bw <= iflp->unrsv_bw[1]) || (bw <= iflp->unrsv_bw[2]) ||
- (bw <= iflp->unrsv_bw[3]) || (bw <= iflp->unrsv_bw[4]) ||
- (bw <= iflp->unrsv_bw[5]) || (bw <= iflp->unrsv_bw[6]) ||
- (bw <= iflp->unrsv_bw[7]) || (bw <= iflp->ava_bw) ||
- (bw <= iflp->res_bw) || (bw <= iflp->use_bw))) {
- vty_out(vty,
- "Maximum Bandwidth could not be lower than others bandwidth\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- if (!iflp)
- iflp = if_link_params_enable(ifp);
-
- /* Update Maximum Bandwidth if needed */
- link_param_cmd_set_float(ifp, &iflp->max_bw, LP_MAX_BW, bw);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (link_params_max_rsv_bw,
- link_params_max_rsv_bw_cmd,
- "max-rsv-bw BANDWIDTH",
- "Maximum bandwidth that may be reserved\n"
- "Bytes/second (IEEE floating point format)\n")
-{
- int idx_bandwidth = 1;
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct if_link_params *iflp = if_link_params_get(ifp);
- float bw;
-
- if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) {
- vty_out(vty, "link_params_max_rsv_bw: fscanf: %s\n",
- safe_strerror(errno));
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- /* Check that bandwidth is not greater than maximum bandwidth parameter
- */
- if (iflp && bw > iflp->max_bw) {
- vty_out(vty,
- "Maximum Reservable Bandwidth could not be greater than Maximum Bandwidth (%g)\n",
- iflp->max_bw);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- if (!iflp)
- iflp = if_link_params_enable(ifp);
-
- /* Update Maximum Reservable Bandwidth if needed */
- link_param_cmd_set_float(ifp, &iflp->max_rsv_bw, LP_MAX_RSV_BW, bw);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (link_params_unrsv_bw,
- link_params_unrsv_bw_cmd,
- "unrsv-bw (0-7) BANDWIDTH",
- "Unreserved bandwidth at each priority level\n"
- "Priority\n"
- "Bytes/second (IEEE floating point format)\n")
-{
- int idx_number = 1;
- int idx_bandwidth = 2;
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct if_link_params *iflp = if_link_params_get(ifp);
- int priority;
- float bw;
-
- /* We don't have to consider about range check here. */
- if (sscanf(argv[idx_number]->arg, "%d", &priority) != 1) {
- vty_out(vty, "link_params_unrsv_bw: fscanf: %s\n",
- safe_strerror(errno));
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) {
- vty_out(vty, "link_params_unrsv_bw: fscanf: %s\n",
- safe_strerror(errno));
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- /* Check that bandwidth is not greater than maximum bandwidth parameter
- */
- if (iflp && bw > iflp->max_bw) {
- vty_out(vty,
- "UnReserved Bandwidth could not be greater than Maximum Bandwidth (%g)\n",
- iflp->max_bw);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- if (!iflp)
- iflp = if_link_params_enable(ifp);
-
- /* Update Unreserved Bandwidth if needed */
- link_param_cmd_set_float(ifp, &iflp->unrsv_bw[priority], LP_UNRSV_BW,
- bw);
-
- return CMD_SUCCESS;
-}
-
-DEFPY_YANG(link_params_admin_grp, link_params_admin_grp_cmd,
- "admin-grp BITPATTERN",
- "Administrative group membership\n"
- "32-bit Hexadecimal value (e.g. 0xa1)\n")
-{
- char xpath[XPATH_MAXLEN];
- int idx_bitpattern = 1;
- unsigned long value;
- char value_str[11];
-
- VTY_DECLVAR_CONTEXT(interface, ifp);
-
- snprintf(
- xpath, sizeof(xpath),
- "/frr-interface:lib/interface[name='%s']/frr-zebra:zebra/link-params/affinities",
- ifp->name);
- if (yang_dnode_exists(running_config->dnode, xpath)) {
- vty_out(vty,
- "cannot use the admin-grp command when affinity is set\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- if (sscanf(argv[idx_bitpattern]->arg, "0x%lx", &value) != 1) {
- vty_out(vty, "link_params_admin_grp: fscanf: %s\n",
- safe_strerror(errno));
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- if (value > 0xFFFFFFFF) {
- vty_out(vty, "value must be not be superior to 0xFFFFFFFF\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- snprintf(value_str, sizeof(value_str), "%ld", value);
-
- nb_cli_enqueue_change(
- vty, "./frr-zebra:zebra/link-params/legacy-admin-group",
- NB_OP_MODIFY, value_str);
-
- return nb_cli_apply_changes(vty, NULL);
-}
-
-DEFPY_YANG(no_link_params_admin_grp, no_link_params_admin_grp_cmd,
- "no admin-grp",
- NO_STR "Disable Administrative group membership on this interface\n")
-{
- nb_cli_enqueue_change(
- vty, "./frr-zebra:zebra/link-params/legacy-admin-group",
- NB_OP_DESTROY, NULL);
-
- return nb_cli_apply_changes(vty, NULL);
-}
-
-/* RFC5392 & RFC5316: INTER-AS */
-DEFUN (link_params_inter_as,
- link_params_inter_as_cmd,
- "neighbor A.B.C.D as (1-4294967295)",
- "Configure remote ASBR information (Neighbor IP address and AS number)\n"
- "Remote IP address in dot decimal A.B.C.D\n"
- "Remote AS number\n"
- "AS number in the range <1-4294967295>\n")
-{
- int idx_ipv4 = 1;
- int idx_number = 3;
-
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct if_link_params *iflp = if_link_params_get(ifp);
- struct in_addr addr;
- uint32_t as;
-
- if (!inet_aton(argv[idx_ipv4]->arg, &addr)) {
- vty_out(vty, "Please specify Router-Addr by A.B.C.D\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- if (!iflp)
- iflp = if_link_params_enable(ifp);
-
- as = strtoul(argv[idx_number]->arg, NULL, 10);
-
- /* Update Remote IP and Remote AS fields if needed */
- if (IS_PARAM_UNSET(iflp, LP_RMT_AS) || iflp->rmt_as != as
- || iflp->rmt_ip.s_addr != addr.s_addr) {
-
- iflp->rmt_as = as;
- iflp->rmt_ip.s_addr = addr.s_addr;
- SET_PARAM(iflp, LP_RMT_AS);
-
- /* force protocols to update LINK STATE due to parameters change
- */
- if (if_is_operative(ifp))
- zebra_interface_parameters_update(ifp);
- }
- return CMD_SUCCESS;
-}
-
-DEFUN (no_link_params_inter_as,
- no_link_params_inter_as_cmd,
- "no neighbor",
- NO_STR
- "Remove Neighbor IP address and AS number for Inter-AS TE\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct if_link_params *iflp = if_link_params_get(ifp);
-
- if (!iflp)
- return CMD_SUCCESS;
-
- /* Reset Remote IP and AS neighbor */
- iflp->rmt_as = 0;
- iflp->rmt_ip.s_addr = 0;
- UNSET_PARAM(iflp, LP_RMT_AS);
-
- /* force protocols to update LINK STATE due to parameters change */
- if (if_is_operative(ifp))
- zebra_interface_parameters_update(ifp);
-
- return CMD_SUCCESS;
-}
-
-/* RFC7471: OSPF Traffic Engineering (TE) Metric extensions &
- * draft-ietf-isis-metric-extensions-07.txt */
-DEFUN (link_params_delay,
- link_params_delay_cmd,
- "delay (0-16777215) [min (0-16777215) max (0-16777215)]",
- "Unidirectional Average Link Delay\n"
- "Average delay in micro-second as decimal (0...16777215)\n"
- "Minimum delay\n"
- "Minimum delay in micro-second as decimal (0...16777215)\n"
- "Maximum delay\n"
- "Maximum delay in micro-second as decimal (0...16777215)\n")
-{
- /* Get and Check new delay values */
- uint32_t delay = 0, low = 0, high = 0;
- delay = strtoul(argv[1]->arg, NULL, 10);
- if (argc == 6) {
- low = strtoul(argv[3]->arg, NULL, 10);
- high = strtoul(argv[5]->arg, NULL, 10);
- }
-
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct if_link_params *iflp = if_link_params_get(ifp);
- uint8_t update = 0;
-
- if (argc == 2) {
- /*
- * Check new delay value against old Min and Max delays if set
- *
- * RFC 7471 Section 4.2.7:
- * It is possible for min delay and max delay to be
- * the same value.
- *
- * Therefore, it is also allowed that the average
- * delay be equal to the min delay or max delay.
- */
- if (iflp && IS_PARAM_SET(iflp, LP_MM_DELAY) &&
- (delay < iflp->min_delay || delay > iflp->max_delay)) {
- vty_out(vty,
- "Average delay should be in range Min (%d) - Max (%d) delay\n",
- iflp->min_delay, iflp->max_delay);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- if (!iflp)
- iflp = if_link_params_enable(ifp);
-
- /* Update delay if value is not set or change */
- if (IS_PARAM_UNSET(iflp, LP_DELAY) || iflp->av_delay != delay) {
- iflp->av_delay = delay;
- SET_PARAM(iflp, LP_DELAY);
- update = 1;
- }
- /* Unset Min and Max delays if already set */
- if (IS_PARAM_SET(iflp, LP_MM_DELAY)) {
- iflp->min_delay = 0;
- iflp->max_delay = 0;
- UNSET_PARAM(iflp, LP_MM_DELAY);
- update = 1;
- }
- } else {
- /*
- * Check new delays value coherency. See above note
- * regarding average delay equal to min/max allowed
- */
- if (delay < low || delay > high) {
- vty_out(vty,
- "Average delay should be in range Min (%d) - Max (%d) delay\n",
- low, high);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- if (!iflp)
- iflp = if_link_params_enable(ifp);
-
- /* Update Delays if needed */
- if (IS_PARAM_UNSET(iflp, LP_DELAY)
- || IS_PARAM_UNSET(iflp, LP_MM_DELAY)
- || iflp->av_delay != delay || iflp->min_delay != low
- || iflp->max_delay != high) {
- iflp->av_delay = delay;
- SET_PARAM(iflp, LP_DELAY);
- iflp->min_delay = low;
- iflp->max_delay = high;
- SET_PARAM(iflp, LP_MM_DELAY);
- update = 1;
- }
- }
-
- /* force protocols to update LINK STATE due to parameters change */
- if (update == 1 && if_is_operative(ifp))
- zebra_interface_parameters_update(ifp);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_link_params_delay,
- no_link_params_delay_cmd,
- "no delay",
- NO_STR
- "Disable Unidirectional Average, Min & Max Link Delay on this interface\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct if_link_params *iflp = if_link_params_get(ifp);
-
- if (!iflp)
- return CMD_SUCCESS;
-
- /* Unset Delays */
- iflp->av_delay = 0;
- UNSET_PARAM(iflp, LP_DELAY);
- iflp->min_delay = 0;
- iflp->max_delay = 0;
- UNSET_PARAM(iflp, LP_MM_DELAY);
-
- /* force protocols to update LINK STATE due to parameters change */
- if (if_is_operative(ifp))
- zebra_interface_parameters_update(ifp);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (link_params_delay_var,
- link_params_delay_var_cmd,
- "delay-variation (0-16777215)",
- "Unidirectional Link Delay Variation\n"
- "delay variation in micro-second as decimal (0...16777215)\n")
-{
- int idx_number = 1;
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct if_link_params *iflp = if_link_params_get(ifp);
- uint32_t value;
-
- value = strtoul(argv[idx_number]->arg, NULL, 10);
-
- if (!iflp)
- iflp = if_link_params_enable(ifp);
-
- /* Update Delay Variation if needed */
- link_param_cmd_set_uint32(ifp, &iflp->delay_var, LP_DELAY_VAR, value);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_link_params_delay_var,
- no_link_params_delay_var_cmd,
- "no delay-variation",
- NO_STR
- "Disable Unidirectional Delay Variation on this interface\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
-
- /* Unset Delay Variation */
- link_param_cmd_unset(ifp, LP_DELAY_VAR);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (link_params_pkt_loss,
- link_params_pkt_loss_cmd,
- "packet-loss PERCENTAGE",
- "Unidirectional Link Packet Loss\n"
- "percentage of total traffic by 0.000003% step and less than 50.331642%\n")
-{
- int idx_percentage = 1;
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct if_link_params *iflp = if_link_params_get(ifp);
- float fval;
-
- if (sscanf(argv[idx_percentage]->arg, "%g", &fval) != 1) {
- vty_out(vty, "link_params_pkt_loss: fscanf: %s\n",
- safe_strerror(errno));
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- if (fval > MAX_PKT_LOSS)
- fval = MAX_PKT_LOSS;
-
- if (!iflp)
- iflp = if_link_params_enable(ifp);
-
- /* Update Packet Loss if needed */
- link_param_cmd_set_float(ifp, &iflp->pkt_loss, LP_PKT_LOSS, fval);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_link_params_pkt_loss,
- no_link_params_pkt_loss_cmd,
- "no packet-loss",
- NO_STR
- "Disable Unidirectional Link Packet Loss on this interface\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
-
- /* Unset Packet Loss */
- link_param_cmd_unset(ifp, LP_PKT_LOSS);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (link_params_res_bw,
- link_params_res_bw_cmd,
- "res-bw BANDWIDTH",
- "Unidirectional Residual Bandwidth\n"
- "Bytes/second (IEEE floating point format)\n")
-{
- int idx_bandwidth = 1;
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct if_link_params *iflp = if_link_params_get(ifp);
- float bw;
-
- if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) {
- vty_out(vty, "link_params_res_bw: fscanf: %s\n",
- safe_strerror(errno));
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- /* Check that bandwidth is not greater than maximum bandwidth parameter
- */
- if (iflp && bw > iflp->max_bw) {
- vty_out(vty,
- "Residual Bandwidth could not be greater than Maximum Bandwidth (%g)\n",
- iflp->max_bw);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- if (!iflp)
- iflp = if_link_params_enable(ifp);
-
- /* Update Residual Bandwidth if needed */
- link_param_cmd_set_float(ifp, &iflp->res_bw, LP_RES_BW, bw);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_link_params_res_bw,
- no_link_params_res_bw_cmd,
- "no res-bw",
- NO_STR
- "Disable Unidirectional Residual Bandwidth on this interface\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
-
- /* Unset Residual Bandwidth */
- link_param_cmd_unset(ifp, LP_RES_BW);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (link_params_ava_bw,
- link_params_ava_bw_cmd,
- "ava-bw BANDWIDTH",
- "Unidirectional Available Bandwidth\n"
- "Bytes/second (IEEE floating point format)\n")
-{
- int idx_bandwidth = 1;
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct if_link_params *iflp = if_link_params_get(ifp);
- float bw;
-
- if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) {
- vty_out(vty, "link_params_ava_bw: fscanf: %s\n",
- safe_strerror(errno));
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- /* Check that bandwidth is not greater than maximum bandwidth parameter
- */
- if (iflp && bw > iflp->max_bw) {
- vty_out(vty,
- "Available Bandwidth could not be greater than Maximum Bandwidth (%g)\n",
- iflp->max_bw);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- if (!iflp)
- iflp = if_link_params_enable(ifp);
-
- /* Update Residual Bandwidth if needed */
- link_param_cmd_set_float(ifp, &iflp->ava_bw, LP_AVA_BW, bw);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_link_params_ava_bw,
- no_link_params_ava_bw_cmd,
- "no ava-bw",
- NO_STR
- "Disable Unidirectional Available Bandwidth on this interface\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
-
- /* Unset Available Bandwidth */
- link_param_cmd_unset(ifp, LP_AVA_BW);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (link_params_use_bw,
- link_params_use_bw_cmd,
- "use-bw BANDWIDTH",
- "Unidirectional Utilised Bandwidth\n"
- "Bytes/second (IEEE floating point format)\n")
-{
- int idx_bandwidth = 1;
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct if_link_params *iflp = if_link_params_get(ifp);
- float bw;
-
- if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) {
- vty_out(vty, "link_params_use_bw: fscanf: %s\n",
- safe_strerror(errno));
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- /* Check that bandwidth is not greater than maximum bandwidth parameter
- */
- if (iflp && bw > iflp->max_bw) {
- vty_out(vty,
- "Utilised Bandwidth could not be greater than Maximum Bandwidth (%g)\n",
- iflp->max_bw);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- if (!iflp)
- iflp = if_link_params_enable(ifp);
-
- /* Update Utilized Bandwidth if needed */
- link_param_cmd_set_float(ifp, &iflp->use_bw, LP_USE_BW, bw);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_link_params_use_bw,
- no_link_params_use_bw_cmd,
- "no use-bw",
- NO_STR
- "Disable Unidirectional Utilised Bandwidth on this interface\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
-
- /* Unset Utilised Bandwidth */
- link_param_cmd_unset(ifp, LP_USE_BW);
-
- return CMD_SUCCESS;
-}
-
-static int ag_change(struct vty *vty, int argc, struct cmd_token **argv,
- const char *xpath, bool no, int start_idx)
-{
- for (int i = start_idx; i < argc; i++)
- nb_cli_enqueue_change(vty, xpath,
- no ? NB_OP_DESTROY : NB_OP_CREATE,
- argv[i]->arg);
- return nb_cli_apply_changes(vty, NULL);
-}
-
-/*
- * XPath:
- * /frr-interface:lib/interface/frr-zebra:zebra/link-params/affinities/affinity
- */
-DEFPY_YANG(link_params_affinity, link_params_affinity_cmd,
- "[no] affinity NAME...",
- NO_STR
- "Interface affinities\n"
- "Affinity names\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- char xpath[XPATH_MAXLEN];
-
- snprintf(
- xpath, sizeof(xpath),
- "/frr-interface:lib/interface[name='%s']/frr-zebra:zebra/link-params/legacy-admin-group",
- ifp->name);
- if (yang_dnode_exists(running_config->dnode, xpath)) {
- vty_out(vty,
- "cannot use the affinity command when admin-grp is set\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- return ag_change(vty, argc, argv,
- "./frr-zebra:zebra/link-params/affinities/affinity",
- no, no ? 2 : 1);
-}
-
-
-/*
- * XPath:
- * /frr-interface:lib/interface/frr-zebra:zebra/link-params/affinities/affinity-mode
- */
-DEFPY_YANG(link_params_affinity_mode, link_params_affinity_mode_cmd,
- "affinity-mode <standard|extended|both>$affmode",
- "Interface affinity mode\n"
- "Standard Admin-Group only RFC3630,5305,5329 (default)\n"
- "Extended Admin-Group only RFC7308\n"
- "Standard and extended Admin-Group format\n")
-{
- const char *xpath = "./frr-zebra:zebra/link-params/affinity-mode";
-
- nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, affmode);
-
- return nb_cli_apply_changes(vty, NULL);
-}
-
-DEFPY_YANG(no_link_params_affinity_mode, no_link_params_affinity_mode_cmd,
- "no affinity-mode [<standard|extended|both>]",
- NO_STR
- "Interface affinity mode\n"
- "Standard Admin-Group only RFC3630,5305,5329 (default)\n"
- "Extended Admin-Group only RFC7308\n"
- "Standard and extended Admin-Group format\n")
-{
- const char *xpath = "./frr-zebra:zebra/link-params/affinity-mode";
-
- nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, "standard");
-
- return nb_cli_apply_changes(vty, NULL);
-}
-
-static int ag_iter_cb(const struct lyd_node *dnode, void *arg)
-{
- struct vty *vty = (struct vty *)arg;
-
- vty_out(vty, " %s", yang_dnode_get_string(dnode, "."));
- return YANG_ITER_CONTINUE;
-}
-
-void cli_show_legacy_admin_group(struct vty *vty, const struct lyd_node *dnode,
- bool show_defaults)
-{
- if (!yang_dnode_exists(dnode, "./legacy-admin-group"))
- return;
-
- vty_out(vty, " admin-group 0x%x\n",
- yang_dnode_get_uint32(dnode, "./legacy-admin-group"));
-}
-
-void cli_show_affinity_mode(struct vty *vty, const struct lyd_node *dnode,
- bool show_defaults)
-{
- enum affinity_mode affinity_mode = yang_dnode_get_enum(dnode, ".");
-
- if (affinity_mode == AFFINITY_MODE_STANDARD)
- vty_out(vty, " affinity-mode standard\n");
- else if (affinity_mode == AFFINITY_MODE_BOTH)
- vty_out(vty, " affinity-mode both\n");
-}
-
-void cli_show_affinity(struct vty *vty, const struct lyd_node *dnode,
- bool show_defaults)
-{
- if (!yang_dnode_exists(dnode, "./affinity"))
- return;
-
- vty_out(vty, " affinity");
- yang_dnode_iterate(ag_iter_cb, vty, dnode, "./affinity");
- vty_out(vty, "\n");
-}
-
-int if_ip_address_install(struct interface *ifp, struct prefix *prefix,
- const char *label, struct prefix *pp)
+void if_ip_address_install(struct interface *ifp, struct prefix *prefix,
+ const char *label, struct prefix *pp)
{
struct zebra_if *if_data;
- struct prefix_ipv4 lp;
- struct prefix_ipv4 *p;
struct connected *ifc;
- enum zebra_dplane_result dplane_res;
if_data = ifp->info;
- lp.family = prefix->family;
- lp.prefix = prefix->u.prefix4;
- lp.prefixlen = prefix->prefixlen;
- apply_mask_ipv4(&lp);
-
- ifc = connected_check_ptp(ifp, &lp, pp ? pp : NULL);
+ ifc = connected_check_ptp(ifp, prefix, pp);
if (!ifc) {
ifc = connected_new();
ifc->ifp = ifp;
/* Address. */
- p = prefix_ipv4_new();
- *p = lp;
- ifc->address = (struct prefix *)p;
+ ifc->address = prefix_new();
+ prefix_copy(ifc->address, prefix);
if (pp) {
SET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
- p = prefix_ipv4_new();
- *p = *(struct prefix_ipv4 *)pp;
- ifc->destination = (struct prefix *)p;
+ ifc->destination = prefix_new();
+ prefix_copy(ifc->destination, pp);
}
/* Label. */
@@ -4159,7 +3805,7 @@ int if_ip_address_install(struct interface *ifp, struct prefix *prefix,
ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);
/* Add to linked list. */
- listnode_add(ifp->connected, ifc);
+ if_connected_add_tail(ifp->connected, ifc);
}
/* This address is configured from zebra. */
@@ -4176,13 +3822,7 @@ int if_ip_address_install(struct interface *ifp, struct prefix *prefix,
if_refresh(ifp);
}
- dplane_res = dplane_intf_addr_set(ifp, ifc);
- if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) {
- zlog_debug(
- "dplane can't set interface IP address: %s.",
- dplane_res2str(dplane_res));
- return NB_ERR;
- }
+ dplane_intf_addr_set(ifp, ifc);
SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
/* The address will be advertised to zebra clients when the
@@ -4190,407 +3830,50 @@ int if_ip_address_install(struct interface *ifp, struct prefix *prefix,
* from the kernel has been received.
* It will also be added to the subnet chain list, then. */
}
-
- return 0;
}
-static int ip_address_install(struct vty *vty, struct interface *ifp,
- const char *addr_str, const char *peer_str,
- const char *label)
+void if_ip_address_uninstall(struct interface *ifp, struct prefix *prefix,
+ struct prefix *pp)
{
- struct zebra_if *if_data;
- struct prefix_ipv4 lp, pp;
struct connected *ifc;
- struct prefix_ipv4 *p;
- int ret;
- enum zebra_dplane_result dplane_res;
-
- if_data = ifp->info;
-
- ret = str2prefix_ipv4(addr_str, &lp);
- if (ret <= 0) {
- vty_out(vty, "%% Malformed address \n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- if (ipv4_martian(&lp.prefix)) {
- vty_out(vty, "%% Invalid address\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- if (peer_str) {
- if (lp.prefixlen != IPV4_MAX_BITLEN) {
- vty_out(vty,
- "%% Local prefix length for P-t-P address must be /32\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- ret = str2prefix_ipv4(peer_str, &pp);
- if (ret <= 0) {
- vty_out(vty, "%% Malformed peer address\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
- }
-
- ifc = connected_check_ptp(ifp, &lp, peer_str ? &pp : NULL);
- if (!ifc) {
- ifc = connected_new();
- ifc->ifp = ifp;
-
- /* Address. */
- p = prefix_ipv4_new();
- *p = lp;
- ifc->address = (struct prefix *)p;
-
- if (peer_str) {
- SET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
- p = prefix_ipv4_new();
- *p = pp;
- ifc->destination = (struct prefix *)p;
- }
-
- /* Label. */
- if (label)
- ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);
-
- /* Add to linked list. */
- listnode_add(ifp->connected, ifc);
- }
-
- /* This address is configured from zebra. */
- if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
- SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
-
- /* In case of this route need to install kernel. */
- if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) &&
- CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE) &&
- !(if_data && if_data->shutdown == IF_ZEBRA_DATA_ON)) {
- /* Some system need to up the interface to set IP address. */
- if (!if_is_up(ifp)) {
- if_set_flags(ifp, IFF_UP | IFF_RUNNING);
- if_refresh(ifp);
- }
-
- dplane_res = dplane_intf_addr_set(ifp, ifc);
- if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) {
- vty_out(vty, "%% Can't set interface IP address: %s.\n",
- dplane_res2str(dplane_res));
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
- /* The address will be advertised to zebra clients when the
- * notification
- * from the kernel has been received.
- * It will also be added to the subnet chain list, then. */
- }
-
- return CMD_SUCCESS;
-}
-
-int if_ip_address_uinstall(struct interface *ifp, struct prefix *prefix)
-{
- struct connected *ifc = NULL;
- enum zebra_dplane_result dplane_res;
-
- if (prefix->family == AF_INET) {
- /* Check current interface address. */
- ifc = connected_check_ptp(ifp, prefix, NULL);
- if (!ifc) {
- zlog_debug("interface %s Can't find address",
- ifp->name);
- return -1;
- }
- } else if (prefix->family == AF_INET6) {
- /* Check current interface address. */
- ifc = connected_check(ifp, prefix);
- }
+ ifc = connected_check_ptp(ifp, prefix, pp);
+ assert(ifc);
- if (!ifc) {
- zlog_debug("interface %s Can't find address", ifp->name);
- return -1;
- }
UNSET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
/* This is not real address or interface is not active. */
if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)
|| !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
- listnode_delete(ifp->connected, ifc);
+ if_connected_del(ifp->connected, ifc);
connected_free(&ifc);
- return CMD_WARNING_CONFIG_FAILED;
+ return;
}
/* This is real route. */
- dplane_res = dplane_intf_addr_unset(ifp, ifc);
- if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) {
- zlog_debug("Can't unset interface IP address: %s.",
- dplane_res2str(dplane_res));
- return -1;
- }
- UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
-
- return 0;
-}
-
-static int ip_address_uninstall(struct vty *vty, struct interface *ifp,
- const char *addr_str, const char *peer_str,
- const char *label)
-{
- struct prefix_ipv4 lp, pp;
- struct connected *ifc;
- int ret;
- enum zebra_dplane_result dplane_res;
-
- /* Convert to prefix structure. */
- ret = str2prefix_ipv4(addr_str, &lp);
- if (ret <= 0) {
- vty_out(vty, "%% Malformed address \n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- if (peer_str) {
- if (lp.prefixlen != IPV4_MAX_BITLEN) {
- vty_out(vty,
- "%% Local prefix length for P-t-P address must be /32\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- ret = str2prefix_ipv4(peer_str, &pp);
- if (ret <= 0) {
- vty_out(vty, "%% Malformed peer address\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
- }
-
- /* Check current interface address. */
- ifc = connected_check_ptp(ifp, &lp, peer_str ? &pp : NULL);
- if (!ifc) {
- vty_out(vty, "%% Can't find address\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
+ dplane_intf_addr_unset(ifp, ifc);
- /* This is not configured address. */
- if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
- return CMD_WARNING_CONFIG_FAILED;
-
- UNSET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
-
- /* This is not real address or interface is not active. */
- if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)
- || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
- listnode_delete(ifp->connected, ifc);
- connected_free(&ifc);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- /* This is real route. */
- dplane_res = dplane_intf_addr_unset(ifp, ifc);
- if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) {
- vty_out(vty, "%% Can't unset interface IP address: %s.\n",
- dplane_res2str(dplane_res));
- return CMD_WARNING_CONFIG_FAILED;
- }
UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
- /* we will receive a kernel notification about this route being removed.
- * this will trigger its removal from the connected list. */
- return CMD_SUCCESS;
-}
-
-DEFUN (ip_address,
- ip_address_cmd,
- "ip address A.B.C.D/M",
- "Interface Internet Protocol config commands\n"
- "Set the IP address of an interface\n"
- "IP address (e.g. 10.0.0.1/8)\n")
-{
- int idx_ipv4_prefixlen = 2;
- VTY_DECLVAR_CONTEXT(interface, ifp);
- return ip_address_install(vty, ifp, argv[idx_ipv4_prefixlen]->arg, NULL,
- NULL);
-}
-
-DEFUN (no_ip_address,
- no_ip_address_cmd,
- "no ip address A.B.C.D/M",
- NO_STR
- "Interface Internet Protocol config commands\n"
- "Set the IP address of an interface\n"
- "IP Address (e.g. 10.0.0.1/8)\n")
-{
- int idx_ipv4_prefixlen = 3;
- VTY_DECLVAR_CONTEXT(interface, ifp);
- return ip_address_uninstall(vty, ifp, argv[idx_ipv4_prefixlen]->arg,
- NULL, NULL);
-}
-
-DEFUN(ip_address_peer,
- ip_address_peer_cmd,
- "ip address A.B.C.D peer A.B.C.D/M",
- "Interface Internet Protocol config commands\n"
- "Set the IP address of an interface\n"
- "Local IP (e.g. 10.0.0.1) for P-t-P address\n"
- "Specify P-t-P address\n"
- "Peer IP address (e.g. 10.0.0.1/8)\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- return ip_address_install(vty, ifp, argv[2]->arg, argv[4]->arg, NULL);
-}
-
-DEFUN(no_ip_address_peer,
- no_ip_address_peer_cmd,
- "no ip address A.B.C.D peer A.B.C.D/M",
- NO_STR
- "Interface Internet Protocol config commands\n"
- "Set the IP address of an interface\n"
- "Local IP (e.g. 10.0.0.1) for P-t-P address\n"
- "Specify P-t-P address\n"
- "Peer IP address (e.g. 10.0.0.1/8)\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- return ip_address_uninstall(vty, ifp, argv[3]->arg, argv[5]->arg, NULL);
-}
-
-#ifdef HAVE_NETLINK
-DEFUN (ip_address_label,
- ip_address_label_cmd,
- "ip address A.B.C.D/M label LINE",
- "Interface Internet Protocol config commands\n"
- "Set the IP address of an interface\n"
- "IP address (e.g. 10.0.0.1/8)\n"
- "Label of this address\n"
- "Label\n")
-{
- int idx_ipv4_prefixlen = 2;
- int idx_line = 4;
- VTY_DECLVAR_CONTEXT(interface, ifp);
- return ip_address_install(vty, ifp, argv[idx_ipv4_prefixlen]->arg, NULL,
- argv[idx_line]->arg);
-}
-
-DEFUN (no_ip_address_label,
- no_ip_address_label_cmd,
- "no ip address A.B.C.D/M label LINE",
- NO_STR
- "Interface Internet Protocol config commands\n"
- "Set the IP address of an interface\n"
- "IP address (e.g. 10.0.0.1/8)\n"
- "Label of this address\n"
- "Label\n")
-{
- int idx_ipv4_prefixlen = 3;
- int idx_line = 5;
- VTY_DECLVAR_CONTEXT(interface, ifp);
- return ip_address_uninstall(vty, ifp, argv[idx_ipv4_prefixlen]->arg,
- NULL, argv[idx_line]->arg);
}
-#endif /* HAVE_NETLINK */
-int if_ipv6_address_install(struct interface *ifp, struct prefix *prefix,
- const char *label)
+void if_ipv6_address_install(struct interface *ifp, struct prefix *prefix)
{
struct zebra_if *if_data;
- struct prefix_ipv6 cp;
struct connected *ifc;
- struct prefix_ipv6 *p;
- enum zebra_dplane_result dplane_res;
-
- if_data = ifp->info;
-
- cp.family = prefix->family;
- cp.prefixlen = prefix->prefixlen;
- cp.prefix = prefix->u.prefix6;
- apply_mask_ipv6(&cp);
-
- ifc = connected_check(ifp, (struct prefix *)&cp);
- if (!ifc) {
- ifc = connected_new();
- ifc->ifp = ifp;
-
- /* Address. */
- p = prefix_ipv6_new();
- *p = cp;
- ifc->address = (struct prefix *)p;
-
- /* Label. */
- if (label)
- ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);
-
- /* Add to linked list. */
- listnode_add(ifp->connected, ifc);
- }
-
- /* This address is configured from zebra. */
- if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
- SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
-
- /* In case of this route need to install kernel. */
- if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) &&
- CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE) &&
- !(if_data && if_data->shutdown == IF_ZEBRA_DATA_ON)) {
- /* Some system need to up the interface to set IP address. */
- if (!if_is_up(ifp)) {
- if_set_flags(ifp, IFF_UP | IFF_RUNNING);
- if_refresh(ifp);
- }
-
- dplane_res = dplane_intf_addr_set(ifp, ifc);
- if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) {
- zlog_debug(
- "dplane can't set interface IP address: %s.",
- dplane_res2str(dplane_res));
- return NB_ERR;
- }
-
- SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
- /* The address will be advertised to zebra clients when the
- * notification
- * from the kernel has been received. */
- }
-
- return 0;
-}
-
-static int ipv6_address_install(struct vty *vty, struct interface *ifp,
- const char *addr_str, const char *peer_str,
- const char *label)
-{
- struct zebra_if *if_data;
- struct prefix_ipv6 cp;
- struct connected *ifc;
- struct prefix_ipv6 *p;
- int ret;
- enum zebra_dplane_result dplane_res;
if_data = ifp->info;
- ret = str2prefix_ipv6(addr_str, &cp);
- if (ret <= 0) {
- vty_out(vty, "%% Malformed address \n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- if (ipv6_martian(&cp.prefix)) {
- vty_out(vty, "%% Invalid address\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- ifc = connected_check(ifp, (struct prefix *)&cp);
+ ifc = connected_check(ifp, prefix);
if (!ifc) {
ifc = connected_new();
ifc->ifp = ifp;
/* Address. */
- p = prefix_ipv6_new();
- *p = cp;
- ifc->address = (struct prefix *)p;
-
- /* Label. */
- if (label)
- ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);
+ ifc->address = prefix_new();
+ prefix_copy(ifc->address, prefix);
/* Add to linked list. */
- listnode_add(ifp->connected, ifc);
+ if_connected_add_tail(ifp->connected, ifc);
}
/* This address is configured from zebra. */
@@ -4607,261 +3890,36 @@ static int ipv6_address_install(struct vty *vty, struct interface *ifp,
if_refresh(ifp);
}
- dplane_res = dplane_intf_addr_set(ifp, ifc);
- if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) {
- vty_out(vty, "%% Can't set interface IP address: %s.\n",
- dplane_res2str(dplane_res));
- return CMD_WARNING_CONFIG_FAILED;
- }
+ dplane_intf_addr_set(ifp, ifc);
SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
/* The address will be advertised to zebra clients when the
* notification
* from the kernel has been received. */
}
-
- return CMD_SUCCESS;
-}
-
-/* Return true if an ipv6 address is configured on ifp */
-int ipv6_address_configured(struct interface *ifp)
-{
- struct connected *connected;
- struct listnode *node;
-
- for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected))
- if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL)
- && (connected->address->family == AF_INET6))
- return 1;
-
- return 0;
}
-static int ipv6_address_uninstall(struct vty *vty, struct interface *ifp,
- const char *addr_str, const char *peer_str,
- const char *label)
+void if_ipv6_address_uninstall(struct interface *ifp, struct prefix *prefix)
{
- struct prefix_ipv6 cp;
struct connected *ifc;
- int ret;
- enum zebra_dplane_result dplane_res;
-
- /* Convert to prefix structure. */
- ret = str2prefix_ipv6(addr_str, &cp);
- if (ret <= 0) {
- vty_out(vty, "%% Malformed address \n");
- return CMD_WARNING_CONFIG_FAILED;
- }
- /* Check current interface address. */
- ifc = connected_check(ifp, (struct prefix *)&cp);
- if (!ifc) {
- vty_out(vty, "%% Can't find address\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- /* This is not configured address. */
- if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
- return CMD_WARNING_CONFIG_FAILED;
+ ifc = connected_check(ifp, prefix);
+ assert(ifc);
UNSET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
/* This is not real address or interface is not active. */
if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)
|| !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
- listnode_delete(ifp->connected, ifc);
+ if_connected_del(ifp->connected, ifc);
connected_free(&ifc);
- return CMD_WARNING_CONFIG_FAILED;
+ return;
}
/* This is real route. */
- dplane_res = dplane_intf_addr_unset(ifp, ifc);
- if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) {
- vty_out(vty, "%% Can't unset interface IP address: %s.\n",
- dplane_res2str(dplane_res));
- return CMD_WARNING_CONFIG_FAILED;
- }
+ dplane_intf_addr_unset(ifp, ifc);
UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
- /* This information will be propagated to the zclients when the
- * kernel notification is received. */
- return CMD_SUCCESS;
-}
-
-DEFUN (ipv6_address,
- ipv6_address_cmd,
- "ipv6 address X:X::X:X/M",
- "Interface IPv6 config commands\n"
- "Set the IP address of an interface\n"
- "IPv6 address (e.g. 3ffe:506::1/48)\n")
-{
- int idx_ipv6_prefixlen = 2;
- VTY_DECLVAR_CONTEXT(interface, ifp);
- return ipv6_address_install(vty, ifp, argv[idx_ipv6_prefixlen]->arg,
- NULL, NULL);
-}
-
-DEFUN (no_ipv6_address,
- no_ipv6_address_cmd,
- "no ipv6 address X:X::X:X/M",
- NO_STR
- "Interface IPv6 config commands\n"
- "Set the IP address of an interface\n"
- "IPv6 address (e.g. 3ffe:506::1/48)\n")
-{
- int idx_ipv6_prefixlen = 3;
- VTY_DECLVAR_CONTEXT(interface, ifp);
- return ipv6_address_uninstall(vty, ifp, argv[idx_ipv6_prefixlen]->arg,
- NULL, NULL);
-}
-
-static int link_params_config_write(struct vty *vty, struct interface *ifp)
-{
- const struct lyd_node *dnode;
- char xpath[XPATH_MAXLEN];
- int i;
-
- if ((ifp == NULL) || !HAS_LINK_PARAMS(ifp))
- return -1;
-
- struct if_link_params *iflp = ifp->link_params;
-
- vty_out(vty, " link-params\n");
- vty_out(vty, " enable\n");
- if (IS_PARAM_SET(iflp, LP_TE_METRIC) && iflp->te_metric != ifp->metric)
- vty_out(vty, " metric %u\n", iflp->te_metric);
- if (IS_PARAM_SET(iflp, LP_MAX_BW) && iflp->max_bw != iflp->default_bw)
- vty_out(vty, " max-bw %g\n", iflp->max_bw);
- if (IS_PARAM_SET(iflp, LP_MAX_RSV_BW)
- && iflp->max_rsv_bw != iflp->default_bw)
- vty_out(vty, " max-rsv-bw %g\n", iflp->max_rsv_bw);
- if (IS_PARAM_SET(iflp, LP_UNRSV_BW)) {
- for (i = 0; i < 8; i++)
- if (iflp->unrsv_bw[i] != iflp->default_bw)
- vty_out(vty, " unrsv-bw %d %g\n", i,
- iflp->unrsv_bw[i]);
- }
-
- snprintf(
- xpath, sizeof(xpath),
- "/frr-interface:lib/interface[name='%s']/frr-zebra:zebra/link-params",
- ifp->name);
- dnode = yang_dnode_get(running_config->dnode, xpath);
- if (dnode)
- nb_cli_show_dnode_cmds(vty, dnode, false);
-
- if (IS_PARAM_SET(iflp, LP_DELAY)) {
- vty_out(vty, " delay %u", iflp->av_delay);
- if (IS_PARAM_SET(iflp, LP_MM_DELAY)) {
- vty_out(vty, " min %u", iflp->min_delay);
- vty_out(vty, " max %u", iflp->max_delay);
- }
- vty_out(vty, "\n");
- }
- if (IS_PARAM_SET(iflp, LP_DELAY_VAR))
- vty_out(vty, " delay-variation %u\n", iflp->delay_var);
- if (IS_PARAM_SET(iflp, LP_PKT_LOSS))
- vty_out(vty, " packet-loss %g\n", iflp->pkt_loss);
- if (IS_PARAM_SET(iflp, LP_AVA_BW))
- vty_out(vty, " ava-bw %g\n", iflp->ava_bw);
- if (IS_PARAM_SET(iflp, LP_RES_BW))
- vty_out(vty, " res-bw %g\n", iflp->res_bw);
- if (IS_PARAM_SET(iflp, LP_USE_BW))
- vty_out(vty, " use-bw %g\n", iflp->use_bw);
- if (IS_PARAM_SET(iflp, LP_RMT_AS))
- vty_out(vty, " neighbor %pI4 as %u\n", &iflp->rmt_ip,
- iflp->rmt_as);
-
- vty_out(vty, " exit-link-params\n");
- return 0;
-}
-
-static int if_config_write(struct vty *vty)
-{
- struct vrf *vrf;
- struct interface *ifp;
-
- zebra_ptm_write(vty);
-
- RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
- FOR_ALL_INTERFACES (vrf, ifp) {
- struct zebra_if *if_data;
- struct listnode *addrnode;
- struct connected *ifc;
- struct prefix *p;
-
- if_data = ifp->info;
-
- if_vty_config_start(vty, ifp);
-
- if (if_data) {
- if (if_data->shutdown == IF_ZEBRA_DATA_ON)
- vty_out(vty, " shutdown\n");
-
- zebra_ptm_if_write(vty, if_data);
- }
-
- if (ifp->desc)
- vty_out(vty, " description %s\n", ifp->desc);
-
- /* Assign bandwidth here to avoid unnecessary interface
- flap
- while processing config script */
- if (ifp->bandwidth != 0)
- vty_out(vty, " bandwidth %u\n", ifp->bandwidth);
-
- if (!CHECK_FLAG(ifp->status,
- ZEBRA_INTERFACE_LINKDETECTION))
- vty_out(vty, " no link-detect\n");
-
- for (ALL_LIST_ELEMENTS_RO(ifp->connected, addrnode,
- ifc)) {
- if (CHECK_FLAG(ifc->conf,
- ZEBRA_IFC_CONFIGURED)) {
- char buf[INET6_ADDRSTRLEN];
- p = ifc->address;
- vty_out(vty, " ip%s address %s",
- p->family == AF_INET ? ""
- : "v6",
- inet_ntop(p->family,
- &p->u.prefix, buf,
- sizeof(buf)));
- if (CONNECTED_PEER(ifc)) {
- p = ifc->destination;
- vty_out(vty, " peer %s",
- inet_ntop(p->family,
- &p->u.prefix,
- buf,
- sizeof(buf)));
- }
- vty_out(vty, "/%d", p->prefixlen);
-
- if (ifc->label)
- vty_out(vty, " label %s",
- ifc->label);
-
- vty_out(vty, "\n");
- }
- }
-
- if (if_data) {
- if (if_data->multicast != IF_ZEBRA_DATA_UNSPEC)
- vty_out(vty, " %smulticast\n",
- if_data->multicast ==
- IF_ZEBRA_DATA_ON
- ? ""
- : "no ");
- if (if_data->mpls == IF_ZEBRA_DATA_ON)
- vty_out(vty, " mpls enable\n");
- }
-
- hook_call(zebra_if_config_wr, vty, ifp);
- zebra_evpn_mh_if_write(vty, ifp);
- link_params_config_write(vty, ifp);
-
- if_vty_config_end(vty);
- }
- return 0;
}
/* Allocate and initialize interface vector. */
@@ -4871,15 +3929,6 @@ void zebra_if_init(void)
hook_register_prio(if_add, 0, if_zebra_new_hook);
hook_register_prio(if_del, 0, if_zebra_delete_hook);
- /* Install configuration write function. */
- if_cmd_init(if_config_write);
- install_node(&link_params_node);
- /*
- * This is *intentionally* setting this to NULL, signaling
- * that interface creation for zebra acts differently
- */
- if_zapi_callbacks(NULL, NULL, NULL, NULL);
-
install_element(VIEW_NODE, &show_interface_cmd);
install_element(VIEW_NODE, &show_interface_vrf_all_cmd);
install_element(VIEW_NODE, &show_interface_name_vrf_cmd);
@@ -4887,55 +3936,4 @@ void zebra_if_init(void)
install_element(ENABLE_NODE, &show_interface_desc_cmd);
install_element(ENABLE_NODE, &show_interface_desc_vrf_all_cmd);
- install_element(INTERFACE_NODE, &multicast_cmd);
- install_element(INTERFACE_NODE, &no_multicast_cmd);
- install_element(INTERFACE_NODE, &mpls_cmd);
- install_element(INTERFACE_NODE, &linkdetect_cmd);
- install_element(INTERFACE_NODE, &no_linkdetect_cmd);
- install_element(INTERFACE_NODE, &shutdown_if_cmd);
- install_element(INTERFACE_NODE, &no_shutdown_if_cmd);
- install_element(INTERFACE_NODE, &bandwidth_if_cmd);
- install_element(INTERFACE_NODE, &no_bandwidth_if_cmd);
- install_element(INTERFACE_NODE, &ip_address_cmd);
- install_element(INTERFACE_NODE, &no_ip_address_cmd);
- install_element(INTERFACE_NODE, &ip_address_peer_cmd);
- install_element(INTERFACE_NODE, &no_ip_address_peer_cmd);
- install_element(INTERFACE_NODE, &ipv6_address_cmd);
- install_element(INTERFACE_NODE, &no_ipv6_address_cmd);
-#ifdef HAVE_NETLINK
- install_element(INTERFACE_NODE, &ip_address_label_cmd);
- install_element(INTERFACE_NODE, &no_ip_address_label_cmd);
-#endif /* HAVE_NETLINK */
- install_element(INTERFACE_NODE, &link_params_cmd);
- install_default(LINK_PARAMS_NODE);
- install_element(LINK_PARAMS_NODE, &link_params_enable_cmd);
- install_element(LINK_PARAMS_NODE, &no_link_params_enable_cmd);
- install_element(LINK_PARAMS_NODE, &link_params_metric_cmd);
- install_element(LINK_PARAMS_NODE, &no_link_params_metric_cmd);
- install_element(LINK_PARAMS_NODE, &link_params_maxbw_cmd);
- install_element(LINK_PARAMS_NODE, &link_params_max_rsv_bw_cmd);
- install_element(LINK_PARAMS_NODE, &link_params_unrsv_bw_cmd);
- install_element(LINK_PARAMS_NODE, &link_params_admin_grp_cmd);
- install_element(LINK_PARAMS_NODE, &no_link_params_admin_grp_cmd);
- install_element(LINK_PARAMS_NODE, &link_params_inter_as_cmd);
- install_element(LINK_PARAMS_NODE, &no_link_params_inter_as_cmd);
- install_element(LINK_PARAMS_NODE, &link_params_delay_cmd);
- install_element(LINK_PARAMS_NODE, &no_link_params_delay_cmd);
- install_element(LINK_PARAMS_NODE, &link_params_delay_var_cmd);
- install_element(LINK_PARAMS_NODE, &no_link_params_delay_var_cmd);
- install_element(LINK_PARAMS_NODE, &link_params_pkt_loss_cmd);
- install_element(LINK_PARAMS_NODE, &no_link_params_pkt_loss_cmd);
- install_element(LINK_PARAMS_NODE, &link_params_ava_bw_cmd);
- install_element(LINK_PARAMS_NODE, &no_link_params_ava_bw_cmd);
- install_element(LINK_PARAMS_NODE, &link_params_res_bw_cmd);
- install_element(LINK_PARAMS_NODE, &no_link_params_res_bw_cmd);
- install_element(LINK_PARAMS_NODE, &link_params_use_bw_cmd);
- install_element(LINK_PARAMS_NODE, &no_link_params_use_bw_cmd);
- install_element(LINK_PARAMS_NODE, &link_params_affinity_cmd);
- install_element(LINK_PARAMS_NODE, &link_params_affinity_mode_cmd);
- install_element(LINK_PARAMS_NODE, &no_link_params_affinity_mode_cmd);
- install_element(LINK_PARAMS_NODE, &exit_link_params_cmd);
-
- /* setup EVPN MH elements */
- zebra_evpn_interface_init();
}
diff --git a/zebra/interface.h b/zebra/interface.h
index e5545d6ba0..8d19c1838f 100644
--- a/zebra/interface.h
+++ b/zebra/interface.h
@@ -39,7 +39,6 @@ enum zebra_iftype {
ZEBRA_IF_MACVLAN, /* MAC VLAN interface*/
ZEBRA_IF_VETH, /* VETH interface*/
ZEBRA_IF_BOND, /* Bond */
- ZEBRA_IF_BOND_SLAVE, /* Bond */
ZEBRA_IF_GRE, /* GRE interface */
};
@@ -114,6 +113,9 @@ struct zebra_if {
/* MPLS status. */
bool mpls;
+ /* MPLS configuration */
+ uint8_t mpls_config;
+
/* Linkdown status */
bool linkdown, linkdownv6;
@@ -199,6 +201,9 @@ struct zebra_if {
ifindex_t link_ifindex;
struct interface *link;
+#define INTERFACE_SPEED_ERROR_READ -1
+#define INTERFACE_SPEED_ERROR_UNKNOWN -2
+
uint8_t speed_update_count;
struct event *speed_update;
@@ -216,8 +221,6 @@ struct zebra_if {
DECLARE_HOOK(zebra_if_extra_info, (struct vty * vty, struct interface *ifp),
(vty, ifp));
-DECLARE_HOOK(zebra_if_config_wr, (struct vty * vty, struct interface *ifp),
- (vty, ifp));
#define IS_ZEBRA_IF_VRF(ifp) \
(((struct zebra_if *)(ifp->info))->zif_type == ZEBRA_IF_VRF)
@@ -281,7 +284,6 @@ extern void if_refresh(struct interface *);
extern void if_flags_update(struct interface *, uint64_t);
extern int if_subnet_add(struct interface *, struct connected *);
extern int if_subnet_delete(struct interface *, struct connected *);
-extern int ipv6_address_configured(struct interface *ifp);
extern void if_handle_vrf_change(struct interface *ifp, vrf_id_t vrf_id);
extern void zebra_if_update_link(struct interface *ifp, ifindex_t link_ifindex,
ns_id_t ns_id);
@@ -306,24 +308,29 @@ extern void cli_show_affinity(struct vty *vty, const struct lyd_node *dnode,
*/
extern int zebra_if_set_protodown(struct interface *ifp, bool down,
enum protodown_reasons new_reason);
-extern int if_ip_address_install(struct interface *ifp, struct prefix *prefix,
- const char *label, struct prefix *pp);
-extern int if_ipv6_address_install(struct interface *ifp, struct prefix *prefix,
- const char *label);
-extern int if_ip_address_uinstall(struct interface *ifp, struct prefix *prefix);
+extern void if_ip_address_install(struct interface *ifp, struct prefix *prefix,
+ const char *label, struct prefix *pp);
+extern void if_ip_address_uninstall(struct interface *ifp,
+ struct prefix *prefix, struct prefix *pp);
+extern void if_ipv6_address_install(struct interface *ifp,
+ struct prefix *prefix);
+extern void if_ipv6_address_uninstall(struct interface *ifp,
+ struct prefix *prefix);
extern int if_shutdown(struct interface *ifp);
extern int if_no_shutdown(struct interface *ifp);
+extern void if_arp(struct interface *ifp, bool enable);
extern int if_multicast_set(struct interface *ifp);
extern int if_multicast_unset(struct interface *ifp);
extern int if_linkdetect(struct interface *ifp, bool detect);
extern void if_addr_wakeup(struct interface *ifp);
+void link_param_cmd_set_uint32(struct interface *ifp, uint32_t *field,
+ uint32_t type, uint32_t value);
+void link_param_cmd_set_float(struct interface *ifp, float *field,
+ uint32_t type, float value);
+void link_param_cmd_unset(struct interface *ifp, uint32_t type);
+
/* Nexthop group connected functions */
-extern void if_nhg_dependents_add(struct interface *ifp,
- struct nhg_hash_entry *nhe);
-extern void if_nhg_dependents_del(struct interface *ifp,
- struct nhg_hash_entry *nhe);
-extern unsigned int if_nhg_dependents_count(const struct interface *ifp);
extern bool if_nhg_dependents_is_empty(const struct interface *ifp);
extern void vrf_add_update(struct vrf *vrfp);
diff --git a/zebra/ioctl.c b/zebra/ioctl.c
index 8da1ae37c6..a35784cd36 100644
--- a/zebra/ioctl.c
+++ b/zebra/ioctl.c
@@ -6,6 +6,8 @@
#include <zebra.h>
+#include <sys/ioctl.h>
+
#include "linklist.h"
#include "if.h"
#include "prefix.h"
diff --git a/zebra/irdp_interface.c b/zebra/irdp_interface.c
index 253e6a8dd6..70f3f57ae0 100644
--- a/zebra/irdp_interface.c
+++ b/zebra/irdp_interface.c
@@ -87,12 +87,12 @@ static const char *inet_2a(uint32_t a, char *b, size_t b_len)
static struct prefix *irdp_get_prefix(struct interface *ifp)
{
- struct listnode *node;
struct connected *ifc;
- if (ifp->connected)
- for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc))
+ frr_each (if_connected, ifp->connected, ifc) {
+ if (ifc->address->family == AF_INET)
return ifc->address;
+ }
return NULL;
}
@@ -198,7 +198,6 @@ static void irdp_if_start(struct interface *ifp, int multicast,
{
struct zebra_if *zi = ifp->info;
struct irdp_interface *irdp = zi->irdp;
- struct listnode *node;
struct connected *ifc;
uint32_t timer, seed;
@@ -247,11 +246,12 @@ static void irdp_if_start(struct interface *ifp, int multicast,
/* The spec suggests this for randomness */
seed = 0;
- if (ifp->connected)
- for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
+ frr_each (if_connected, ifp->connected, ifc) {
+ if (ifc->address->family == AF_INET) {
seed = ifc->address->u.prefix4.s_addr;
break;
}
+ }
srandom(seed);
timer = (frr_weak_random() % IRDP_DEFAULT_INTERVAL) + 1;
@@ -694,7 +694,6 @@ DEFUN (ip_irdp_debug_disable,
void irdp_if_init(void)
{
- hook_register(zebra_if_config_wr, irdp_config_write);
hook_register(if_del, irdp_if_delete);
install_element(INTERFACE_NODE, &ip_irdp_broadcast_cmd);
diff --git a/zebra/irdp_main.c b/zebra/irdp_main.c
index 6548790e9a..349ae1a191 100644
--- a/zebra/irdp_main.c
+++ b/zebra/irdp_main.c
@@ -197,7 +197,6 @@ void irdp_send_thread(struct event *t_advert)
struct zebra_if *zi = ifp->info;
struct irdp_interface *irdp = zi->irdp;
struct prefix *p;
- struct listnode *node, *nnode;
struct connected *ifc;
if (!irdp)
@@ -205,16 +204,15 @@ void irdp_send_thread(struct event *t_advert)
irdp->flags &= ~IF_SOLICIT;
- if (ifp->connected)
- for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, ifc)) {
- p = ifc->address;
+ frr_each (if_connected, ifp->connected, ifc) {
+ p = ifc->address;
- if (p->family != AF_INET)
- continue;
+ if (p->family != AF_INET)
+ continue;
- irdp_advertisement(ifp, p);
- irdp->irdp_sent++;
- }
+ irdp_advertisement(ifp, p);
+ irdp->irdp_sent++;
+ }
tmp = irdp->MaxAdvertInterval - irdp->MinAdvertInterval;
timer = frr_weak_random() % (tmp + 1);
@@ -237,7 +235,6 @@ void irdp_advert_off(struct interface *ifp)
{
struct zebra_if *zi = ifp->info;
struct irdp_interface *irdp = zi->irdp;
- struct listnode *node, *nnode;
int i;
struct connected *ifc;
struct prefix *p;
@@ -247,19 +244,21 @@ void irdp_advert_off(struct interface *ifp)
EVENT_OFF(irdp->t_advertise);
- if (ifp->connected)
- for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, ifc)) {
- p = ifc->address;
+ frr_each (if_connected, ifp->connected, ifc) {
+ p = ifc->address;
- /* Output some packets with Lifetime 0
- we should add a wait...
- */
+ if (p->family != AF_INET)
+ continue;
- for (i = 0; i < IRDP_LAST_ADVERT_MESSAGES; i++) {
- irdp->irdp_sent++;
- irdp_advertisement(ifp, p);
- }
+ /* Output some packets with Lifetime 0
+ we should add a wait...
+ */
+
+ for (i = 0; i < IRDP_LAST_ADVERT_MESSAGES; i++) {
+ irdp->irdp_sent++;
+ irdp_advertisement(ifp, p);
}
+ }
}
diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c
index 78b1dfe276..8a64a1ea48 100644
--- a/zebra/kernel_netlink.c
+++ b/zebra/kernel_netlink.c
@@ -4,8 +4,12 @@
*/
#include <zebra.h>
+#include <fcntl.h>
#ifdef HAVE_NETLINK
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <linux/filter.h>
#include "linklist.h"
#include "if.h"
@@ -35,6 +39,7 @@
#include "zebra/tc_netlink.h"
#include "zebra/netconf_netlink.h"
#include "zebra/zebra_errors.h"
+#include "zebra/ge_netlink.h"
#ifndef SO_RCVBUFFORCE
#define SO_RCVBUFFORCE (33)
@@ -76,43 +81,48 @@
*/
#define NL_DEFAULT_BATCH_SEND_THRESHOLD (15 * NL_PKT_BUF_SIZE)
-static const struct message nlmsg_str[] = {{RTM_NEWROUTE, "RTM_NEWROUTE"},
- {RTM_DELROUTE, "RTM_DELROUTE"},
- {RTM_GETROUTE, "RTM_GETROUTE"},
- {RTM_NEWLINK, "RTM_NEWLINK"},
- {RTM_SETLINK, "RTM_SETLINK"},
- {RTM_DELLINK, "RTM_DELLINK"},
- {RTM_GETLINK, "RTM_GETLINK"},
- {RTM_NEWADDR, "RTM_NEWADDR"},
- {RTM_DELADDR, "RTM_DELADDR"},
- {RTM_GETADDR, "RTM_GETADDR"},
- {RTM_NEWNEIGH, "RTM_NEWNEIGH"},
- {RTM_DELNEIGH, "RTM_DELNEIGH"},
- {RTM_GETNEIGH, "RTM_GETNEIGH"},
- {RTM_NEWRULE, "RTM_NEWRULE"},
- {RTM_DELRULE, "RTM_DELRULE"},
- {RTM_GETRULE, "RTM_GETRULE"},
- {RTM_NEWNEXTHOP, "RTM_NEWNEXTHOP"},
- {RTM_DELNEXTHOP, "RTM_DELNEXTHOP"},
- {RTM_GETNEXTHOP, "RTM_GETNEXTHOP"},
- {RTM_NEWNETCONF, "RTM_NEWNETCONF"},
- {RTM_DELNETCONF, "RTM_DELNETCONF"},
- {RTM_NEWTUNNEL, "RTM_NEWTUNNEL"},
- {RTM_DELTUNNEL, "RTM_DELTUNNEL"},
- {RTM_GETTUNNEL, "RTM_GETTUNNEL"},
- {RTM_NEWQDISC, "RTM_NEWQDISC"},
- {RTM_DELQDISC, "RTM_DELQDISC"},
- {RTM_GETQDISC, "RTM_GETQDISC"},
- {RTM_NEWTCLASS, "RTM_NEWTCLASS"},
- {RTM_DELTCLASS, "RTM_DELTCLASS"},
- {RTM_GETTCLASS, "RTM_GETTCLASS"},
- {RTM_NEWTFILTER, "RTM_NEWTFILTER"},
- {RTM_DELTFILTER, "RTM_DELTFILTER"},
- {RTM_GETTFILTER, "RTM_GETTFILTER"},
- {RTM_NEWVLAN, "RTM_NEWVLAN"},
- {RTM_DELVLAN, "RTM_DELVLAN"},
- {RTM_GETVLAN, "RTM_GETVLAN"},
- {0}};
+static const struct message nlmsg_str[] = {
+ { RTM_NEWROUTE, "RTM_NEWROUTE" },
+ { RTM_DELROUTE, "RTM_DELROUTE" },
+ { RTM_GETROUTE, "RTM_GETROUTE" },
+ { RTM_NEWLINK, "RTM_NEWLINK" },
+ { RTM_SETLINK, "RTM_SETLINK" },
+ { RTM_DELLINK, "RTM_DELLINK" },
+ { RTM_GETLINK, "RTM_GETLINK" },
+ { RTM_NEWADDR, "RTM_NEWADDR" },
+ { RTM_DELADDR, "RTM_DELADDR" },
+ { RTM_GETADDR, "RTM_GETADDR" },
+ { RTM_NEWNEIGH, "RTM_NEWNEIGH" },
+ { RTM_DELNEIGH, "RTM_DELNEIGH" },
+ { RTM_GETNEIGH, "RTM_GETNEIGH" },
+ { RTM_NEWRULE, "RTM_NEWRULE" },
+ { RTM_DELRULE, "RTM_DELRULE" },
+ { RTM_GETRULE, "RTM_GETRULE" },
+ { RTM_NEWNEXTHOP, "RTM_NEWNEXTHOP" },
+ { RTM_DELNEXTHOP, "RTM_DELNEXTHOP" },
+ { RTM_GETNEXTHOP, "RTM_GETNEXTHOP" },
+ { RTM_NEWNETCONF, "RTM_NEWNETCONF" },
+ { RTM_DELNETCONF, "RTM_DELNETCONF" },
+ { RTM_NEWTUNNEL, "RTM_NEWTUNNEL" },
+ { RTM_DELTUNNEL, "RTM_DELTUNNEL" },
+ { RTM_GETTUNNEL, "RTM_GETTUNNEL" },
+ { RTM_NEWQDISC, "RTM_NEWQDISC" },
+ { RTM_DELQDISC, "RTM_DELQDISC" },
+ { RTM_GETQDISC, "RTM_GETQDISC" },
+ { RTM_NEWTCLASS, "RTM_NEWTCLASS" },
+ { RTM_DELTCLASS, "RTM_DELTCLASS" },
+ { RTM_GETTCLASS, "RTM_GETTCLASS" },
+ { RTM_NEWTFILTER, "RTM_NEWTFILTER" },
+ { RTM_DELTFILTER, "RTM_DELTFILTER" },
+ { RTM_GETTFILTER, "RTM_GETTFILTER" },
+ { RTM_NEWVLAN, "RTM_NEWVLAN" },
+ { RTM_DELVLAN, "RTM_DELVLAN" },
+ { RTM_GETVLAN, "RTM_GETVLAN" },
+ { RTM_NEWCHAIN, "RTM_NEWCHAIN" },
+ { RTM_DELCHAIN, "RTM_DELCHAIN" },
+ { RTM_GETCHAIN, "RTM_GETCHAIN" },
+ { 0 }
+};
static const struct message rtproto_str[] = {
{RTPROT_REDIRECT, "redirect"},
@@ -301,7 +311,7 @@ static const char *group2str(uint32_t group)
/* Make socket for Linux netlink interface. */
static int netlink_socket(struct nlsock *nl, unsigned long groups,
uint32_t ext_groups[], uint8_t ext_group_size,
- ns_id_t ns_id)
+ ns_id_t ns_id, int nl_family)
{
int ret;
struct sockaddr_nl snl;
@@ -309,7 +319,7 @@ static int netlink_socket(struct nlsock *nl, unsigned long groups,
int namelen;
frr_with_privs(&zserv_privs) {
- sock = ns_socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE, ns_id);
+ sock = ns_socket(AF_NETLINK, SOCK_RAW, nl_family, ns_id);
if (sock < 0) {
zlog_err("Can't open %s socket: %s", nl->name,
safe_strerror(errno));
@@ -398,7 +408,7 @@ static int netlink_information_fetch(struct nlmsghdr *h, ns_id_t ns_id,
case RTM_NEWLINK:
return netlink_link_change(h, ns_id, startup);
case RTM_DELLINK:
- return netlink_link_change(h, ns_id, startup);
+ return 0;
case RTM_NEWNEIGH:
case RTM_DELNEIGH:
case RTM_GETNEIGH:
@@ -425,6 +435,12 @@ static int netlink_information_fetch(struct nlmsghdr *h, ns_id_t ns_id,
case RTM_DELVLAN:
return netlink_vlan_change(h, ns_id, startup);
+ /* Messages we may receive, but ignore */
+ case RTM_NEWCHAIN:
+ case RTM_DELCHAIN:
+ case RTM_GETCHAIN:
+ return 0;
+
/* Messages handled in the dplane thread */
case RTM_NEWADDR:
case RTM_DELADDR:
@@ -474,6 +490,7 @@ static int dplane_netlink_information_fetch(struct nlmsghdr *h, ns_id_t ns_id,
case RTM_NEWLINK:
case RTM_DELLINK:
+ return netlink_link_change(h, ns_id, startup);
default:
break;
@@ -740,58 +757,6 @@ void nl_attr_rtnh_end(struct nlmsghdr *n, struct rtnexthop *rtnh)
rtnh->rtnh_len = (uint8_t *)NLMSG_TAIL(n) - (uint8_t *)rtnh;
}
-bool nl_rta_put(struct rtattr *rta, unsigned int maxlen, int type,
- const void *data, int alen)
-{
- struct rtattr *subrta;
- int len = RTA_LENGTH(alen);
-
- if (RTA_ALIGN(rta->rta_len) + RTA_ALIGN(len) > maxlen) {
- zlog_err("ERROR max allowed bound %d exceeded for rtattr",
- maxlen);
- return false;
- }
- subrta = (struct rtattr *)(((char *)rta) + RTA_ALIGN(rta->rta_len));
- subrta->rta_type = type;
- subrta->rta_len = len;
- if (alen)
- memcpy(RTA_DATA(subrta), data, alen);
- rta->rta_len = NLMSG_ALIGN(rta->rta_len) + RTA_ALIGN(len);
-
- return true;
-}
-
-bool nl_rta_put16(struct rtattr *rta, unsigned int maxlen, int type,
- uint16_t data)
-{
- return nl_rta_put(rta, maxlen, type, &data, sizeof(uint16_t));
-}
-
-bool nl_rta_put64(struct rtattr *rta, unsigned int maxlen, int type,
- uint64_t data)
-{
- return nl_rta_put(rta, maxlen, type, &data, sizeof(uint64_t));
-}
-
-struct rtattr *nl_rta_nest(struct rtattr *rta, unsigned int maxlen, int type)
-{
- struct rtattr *nest = RTA_TAIL(rta);
-
- if (nl_rta_put(rta, maxlen, type, NULL, 0))
- return NULL;
-
- nest->rta_type |= NLA_F_NESTED;
-
- return nest;
-}
-
-int nl_rta_nest_end(struct rtattr *rta, struct rtattr *nest)
-{
- nest->rta_len = (uint8_t *)RTA_TAIL(rta) - (uint8_t *)nest;
-
- return rta->rta_len;
-}
-
const char *nl_msg_type_to_str(uint16_t msg_type)
{
return lookup_msg(nlmsg_str, msg_type, "");
@@ -1169,7 +1134,6 @@ int netlink_parse_info(int (*filter)(struct nlmsghdr *, ns_id_t, int),
h->nlmsg_type, h->nlmsg_len,
h->nlmsg_seq, h->nlmsg_pid);
-
/*
* Ignore messages that maybe sent from
* other actors besides the kernel
@@ -1265,6 +1229,33 @@ int netlink_talk(int (*filter)(struct nlmsghdr *, ns_id_t, int startup),
return netlink_talk_info(filter, n, &dp_info, startup);
}
+/*
+ * Synchronous version of netlink_talk_info. Converts args to suit the
+ * common version, which is suitable for both sync and async use.
+ */
+int ge_netlink_talk(int (*filter)(struct nlmsghdr *, ns_id_t, int startup),
+ struct nlmsghdr *n, struct zebra_ns *zns, bool startup)
+{
+ struct zebra_dplane_info dp_info;
+
+ if (zns->ge_netlink_cmd.sock < 0)
+ return -1;
+
+ /* Increment sequence number before capturing snapshot of ns socket
+ * info.
+ */
+ zns->ge_netlink_cmd.seq = zebra_router_get_next_sequence();
+
+ /* Capture info in intermediate info struct */
+ dp_info.ns_id = zns->ns_id;
+
+ dp_info.is_cmd = true;
+ dp_info.sock = zns->ge_netlink_cmd.sock;
+ dp_info.seq = zns->ge_netlink_cmd.seq;
+
+ return netlink_talk_info(filter, n, &dp_info, startup);
+}
+
/* Issue request message to kernel via netlink socket. GET messages
* are issued through this interface.
*/
@@ -1289,18 +1280,15 @@ int netlink_request(struct nlsock *nl, void *req)
return 0;
}
-static int nl_batch_read_resp(struct nl_batch *bth)
+static int nl_batch_read_resp(struct nl_batch *bth, struct nlsock *nl)
{
struct nlmsghdr *h;
struct sockaddr_nl snl;
struct msghdr msg = {};
int status, seq;
- struct nlsock *nl;
struct zebra_dplane_ctx *ctx;
bool ignore_msg;
- nl = kernel_netlink_nlsock_lookup(bth->zns->sock);
-
msg.msg_name = (void *)&snl;
msg.msg_namelen = sizeof(snl);
@@ -1493,7 +1481,7 @@ static void nl_batch_send(struct nl_batch *bth)
err = true;
if (!err) {
- if (nl_batch_read_resp(bth) == -1)
+ if (nl_batch_read_resp(bth, nl) == -1)
err = true;
}
}
@@ -1631,6 +1619,7 @@ static enum netlink_msg_status nl_put_msg(struct nl_batch *bth,
case DPLANE_OP_IPSET_DELETE:
case DPLANE_OP_IPSET_ENTRY_ADD:
case DPLANE_OP_IPSET_ENTRY_DELETE:
+ case DPLANE_OP_STARTUP_STAGE:
return FRR_NETLINK_ERROR;
case DPLANE_OP_GRE_SET:
@@ -1660,6 +1649,9 @@ static enum netlink_msg_status nl_put_msg(struct nl_batch *bth,
case DPLANE_OP_TC_FILTER_DELETE:
case DPLANE_OP_TC_FILTER_UPDATE:
return netlink_put_tc_filter_update_msg(bth, ctx);
+
+ case DPLANE_OP_SRV6_ENCAP_SRCADDR_SET:
+ return netlink_put_sr_tunsrc_set_msg(bth, ctx);
}
return FRR_NETLINK_ERROR;
@@ -1777,17 +1769,11 @@ void kernel_init(struct zebra_ns *zns)
* groups are added further below after SOL_NETLINK is verified to
* exist.
*/
- groups = RTMGRP_LINK |
- RTMGRP_IPV4_ROUTE |
- RTMGRP_IPV4_IFADDR |
- RTMGRP_IPV6_ROUTE |
- RTMGRP_IPV6_IFADDR |
- RTMGRP_IPV4_MROUTE |
- RTMGRP_NEIGH |
- ((uint32_t) 1 << (RTNLGRP_IPV4_RULE - 1)) |
- ((uint32_t) 1 << (RTNLGRP_IPV6_RULE - 1)) |
- ((uint32_t) 1 << (RTNLGRP_NEXTHOP - 1)) |
- ((uint32_t) 1 << (RTNLGRP_TC - 1));
+ groups = RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE | RTMGRP_IPV4_MROUTE |
+ RTMGRP_NEIGH | ((uint32_t)1 << (RTNLGRP_IPV4_RULE - 1)) |
+ ((uint32_t)1 << (RTNLGRP_IPV6_RULE - 1)) |
+ ((uint32_t)1 << (RTNLGRP_NEXTHOP - 1)) |
+ ((uint32_t)1 << (RTNLGRP_TC - 1));
dplane_groups = (RTMGRP_LINK |
RTMGRP_IPV4_IFADDR |
@@ -1802,8 +1788,8 @@ void kernel_init(struct zebra_ns *zns)
snprintf(zns->netlink.name, sizeof(zns->netlink.name),
"netlink-listen (NS %u)", zns->ns_id);
zns->netlink.sock = -1;
- if (netlink_socket(&zns->netlink, groups, &ext_groups, 1, zns->ns_id) <
- 0) {
+ if (netlink_socket(&zns->netlink, groups, &ext_groups, 1, zns->ns_id,
+ NETLINK_ROUTE) < 0) {
zlog_err("Failure to create %s socket",
zns->netlink.name);
exit(-1);
@@ -1814,7 +1800,8 @@ void kernel_init(struct zebra_ns *zns)
snprintf(zns->netlink_cmd.name, sizeof(zns->netlink_cmd.name),
"netlink-cmd (NS %u)", zns->ns_id);
zns->netlink_cmd.sock = -1;
- if (netlink_socket(&zns->netlink_cmd, 0, 0, 0, zns->ns_id) < 0) {
+ if (netlink_socket(&zns->netlink_cmd, 0, 0, 0, zns->ns_id,
+ NETLINK_ROUTE) < 0) {
zlog_err("Failure to create %s socket",
zns->netlink_cmd.name);
exit(-1);
@@ -1827,7 +1814,8 @@ void kernel_init(struct zebra_ns *zns)
sizeof(zns->netlink_dplane_out.name), "netlink-dp (NS %u)",
zns->ns_id);
zns->netlink_dplane_out.sock = -1;
- if (netlink_socket(&zns->netlink_dplane_out, 0, 0, 0, zns->ns_id) < 0) {
+ if (netlink_socket(&zns->netlink_dplane_out, 0, 0, 0, zns->ns_id,
+ NETLINK_ROUTE) < 0) {
zlog_err("Failure to create %s socket",
zns->netlink_dplane_out.name);
exit(-1);
@@ -1841,7 +1829,7 @@ void kernel_init(struct zebra_ns *zns)
zns->ns_id);
zns->netlink_dplane_in.sock = -1;
if (netlink_socket(&zns->netlink_dplane_in, dplane_groups, 0, 0,
- zns->ns_id) < 0) {
+ zns->ns_id, NETLINK_ROUTE) < 0) {
zlog_err("Failure to create %s socket",
zns->netlink_dplane_in.name);
exit(-1);
@@ -1849,6 +1837,19 @@ void kernel_init(struct zebra_ns *zns)
kernel_netlink_nlsock_insert(&zns->netlink_dplane_in);
+ /* Generic Netlink socket. */
+ snprintf(zns->ge_netlink_cmd.name, sizeof(zns->ge_netlink_cmd.name),
+ "generic-netlink-cmd (NS %u)", zns->ns_id);
+ zns->ge_netlink_cmd.sock = -1;
+ if (netlink_socket(&zns->ge_netlink_cmd, 0, 0, 0, zns->ns_id,
+ NETLINK_GENERIC) < 0) {
+ zlog_warn("Failure to create %s socket",
+ zns->ge_netlink_cmd.name);
+ }
+
+ if (zns->ge_netlink_cmd.sock >= 0)
+ kernel_netlink_nlsock_insert(&zns->ge_netlink_cmd);
+
/*
* SOL_NETLINK is not available on all platforms yet
* apparently. It's in bits/socket.h which I am not
@@ -1887,6 +1888,15 @@ void kernel_init(struct zebra_ns *zns)
zlog_notice("Registration for extended dp ACK failed : %d %s",
errno, safe_strerror(errno));
+ if (zns->ge_netlink_cmd.sock >= 0) {
+ one = 1;
+ ret = setsockopt(zns->ge_netlink_cmd.sock, SOL_NETLINK,
+ NETLINK_EXT_ACK, &one, sizeof(one));
+ if (ret < 0)
+ zlog_err("Registration for extended generic netlink cmd ACK failed : %d %s",
+ errno, safe_strerror(errno));
+ }
+
/*
* Trim off the payload of the original netlink message in the
* acknowledgment. This option is available since Linux 4.2, so if
@@ -1919,12 +1929,22 @@ void kernel_init(struct zebra_ns *zns)
zns->netlink_dplane_in.name, safe_strerror(errno),
errno);
+ if (zns->ge_netlink_cmd.sock >= 0) {
+ if (fcntl(zns->ge_netlink_cmd.sock, F_SETFL, O_NONBLOCK) < 0)
+ zlog_err("Can't set %s socket error: %s(%d)",
+ zns->ge_netlink_cmd.name, safe_strerror(errno),
+ errno);
+ }
+
/* Set receive buffer size if it's set from command line */
if (rcvbufsize) {
netlink_recvbuf(&zns->netlink, rcvbufsize);
netlink_recvbuf(&zns->netlink_cmd, rcvbufsize);
netlink_recvbuf(&zns->netlink_dplane_out, rcvbufsize);
netlink_recvbuf(&zns->netlink_dplane_in, rcvbufsize);
+
+ if (zns->ge_netlink_cmd.sock >= 0)
+ netlink_recvbuf(&zns->ge_netlink_cmd, rcvbufsize);
}
/* Set filter for inbound sockets, to exclude events we've generated
@@ -1943,6 +1963,8 @@ void kernel_init(struct zebra_ns *zns)
&zns->t_netlink);
rt_netlink_init();
+
+ ge_netlink_init(zns);
}
/* Helper to clean up an nlsock */
@@ -1967,11 +1989,16 @@ void kernel_terminate(struct zebra_ns *zns, bool complete)
kernel_nlsock_fini(&zns->netlink_dplane_in);
+ kernel_nlsock_fini(&zns->ge_netlink_cmd);
+
/* During zebra shutdown, we need to leave the dataplane socket
* around until all work is done.
*/
- if (complete)
+ if (complete) {
kernel_nlsock_fini(&zns->netlink_dplane_out);
+
+ XFREE(MTYPE_NL_BUF, nl_batch_tx_buf);
+ }
}
/*
diff --git a/zebra/kernel_netlink.h b/zebra/kernel_netlink.h
index 446c860327..e37bba0cf6 100644
--- a/zebra/kernel_netlink.h
+++ b/zebra/kernel_netlink.h
@@ -85,35 +85,6 @@ extern void netlink_parse_rtattr_nested(struct rtattr **tb, int max,
*/
extern bool nl_addraw_l(struct nlmsghdr *n, unsigned int maxlen,
const void *data, unsigned int len);
-/*
- * nl_rta_put - add an additional optional attribute(rtattr) to the
- * Netlink message buffer.
- *
- * Returns true if the attribute could be added to the message (fits into the
- * buffer), otherwise false is returned.
- */
-extern bool nl_rta_put(struct rtattr *rta, unsigned int maxlen, int type,
- const void *data, int alen);
-extern bool nl_rta_put16(struct rtattr *rta, unsigned int maxlen, int type,
- uint16_t data);
-extern bool nl_rta_put64(struct rtattr *rta, unsigned int maxlen, int type,
- uint64_t data);
-/*
- * nl_rta_nest - start an additional optional attribute (rtattr) nest.
- *
- * Returns a valid pointer to the beginning of the nest if the attribute
- * describing the nest could be added to the message (fits into the buffer),
- * otherwise NULL is returned.
- */
-extern struct rtattr *nl_rta_nest(struct rtattr *rta, unsigned int maxlen,
- int type);
-/*
- * nl_rta_nest_end - finalize nesting of an aditionl optionl attributes.
- *
- * Updates the length field of the attribute header to include the appeneded
- * attributes. Returns a total length of the Netlink message.
- */
-extern int nl_rta_nest_end(struct rtattr *rta, struct rtattr *nest);
extern const char *nl_msg_type_to_str(uint16_t msg_type);
extern const char *nl_rtproto_to_str(uint8_t rtproto);
extern const char *nl_family_to_str(uint8_t family);
@@ -127,6 +98,9 @@ extern int netlink_talk_filter(struct nlmsghdr *h, ns_id_t ns, int startup);
extern int netlink_talk(int (*filter)(struct nlmsghdr *, ns_id_t, int startup),
struct nlmsghdr *n, struct nlsock *nl,
struct zebra_ns *zns, bool startup);
+extern int
+ge_netlink_talk(int (*filter)(struct nlmsghdr *, ns_id_t, int startup),
+ struct nlmsghdr *n, struct zebra_ns *zns, bool startup);
extern int netlink_request(struct nlsock *nl, void *req);
enum netlink_msg_status {
diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c
index b8dc92b2e9..d50e7de229 100644
--- a/zebra/kernel_socket.c
+++ b/zebra/kernel_socket.c
@@ -5,6 +5,8 @@
#include <zebra.h>
+#include <net/route.h>
+
#ifndef HAVE_NETLINK
#include <net/if_types.h>
@@ -48,11 +50,7 @@ extern struct zebra_privs_t zserv_privs;
* 0). We follow this practice without questioning it, but it is a
* bug if frr calls ROUNDUP with 0.
*/
-#ifdef __APPLE__
-#define ROUNDUP_TYPE int
-#else
-#define ROUNDUP_TYPE long
-#endif
+#define ROUNDUP_TYPE long
/*
* Because of these varying conventions, the only sane approach is for
@@ -834,12 +832,12 @@ int ifam_read(struct ifa_msghdr *ifam)
struct interface *ifp = NULL;
union sockunion addr, mask, brd;
bool dest_same = false;
- char ifname[INTERFACE_NAMSIZ];
+ char ifname[IFNAMSIZ];
short ifnlen = 0;
bool isalias = false;
uint32_t flags = 0;
- ifname[0] = ifname[INTERFACE_NAMSIZ - 1] = '\0';
+ ifname[0] = ifname[IFNAMSIZ - 1] = '\0';
/* Allocate and read address information. */
ifam_read_mesg(ifam, &addr, &mask, &brd, ifname, &ifnlen);
@@ -851,7 +849,7 @@ int ifam_read(struct ifa_msghdr *ifam)
return -1;
}
- if (ifnlen && strncmp(ifp->name, ifname, INTERFACE_NAMSIZ))
+ if (ifnlen && strncmp(ifp->name, ifname, IFNAMSIZ))
isalias = true;
/*
@@ -995,7 +993,7 @@ void rtm_read(struct rt_msghdr *rtm)
int flags;
uint32_t zebra_flags;
union sockunion dest, mask, gate;
- char ifname[INTERFACE_NAMSIZ + 1];
+ char ifname[IFNAMSIZ + 1];
short ifnlen = 0;
struct nexthop nh;
struct prefix p;
@@ -1100,11 +1098,11 @@ void rtm_read(struct rt_msghdr *rtm)
if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD
|| rtm->rtm_type == RTM_CHANGE)
rib_add(afi, SAFI_UNICAST, VRF_DEFAULT, proto, 0, zebra_flags,
- &p, NULL, &nh, 0, RT_TABLE_MAIN, 0, 0, distance, 0,
+ &p, NULL, &nh, 0, rt_table_main_id, 0, 0, distance, 0,
false);
else
rib_delete(afi, SAFI_UNICAST, VRF_DEFAULT, proto, 0,
- zebra_flags, &p, NULL, &nh, 0, RT_TABLE_MAIN, 0,
+ zebra_flags, &p, NULL, &nh, 0, rt_table_main_id, 0,
distance, true);
}
@@ -1468,6 +1466,14 @@ static void routing_socket(struct zebra_ns *zns)
event_add_read(zrouter.master, kernel_read, NULL, routing_sock, NULL);
}
+void interface_list_second(struct zebra_ns *zns)
+{
+}
+
+void interface_list_tunneldump(struct zebra_ns *zns)
+{
+}
+
/* Exported interface function. This function simply calls
routing_socket (). */
void kernel_init(struct zebra_ns *zns)
@@ -1617,6 +1623,8 @@ void kernel_update_multi(struct dplane_ctx_list_head *ctx_list)
case DPLANE_OP_GRE_SET:
case DPLANE_OP_INTF_ADDR_ADD:
case DPLANE_OP_INTF_ADDR_DEL:
+ case DPLANE_OP_STARTUP_STAGE:
+ case DPLANE_OP_SRV6_ENCAP_SRCADDR_SET:
zlog_err("Unhandled dplane data for %s",
dplane_op2str(dplane_ctx_get_op(ctx)));
res = ZEBRA_DPLANE_REQUEST_FAILURE;
diff --git a/zebra/label_manager.c b/zebra/label_manager.c
index c77470a701..c97beb6af8 100644
--- a/zebra/label_manager.c
+++ b/zebra/label_manager.c
@@ -28,6 +28,8 @@
#include "zebra/zapi_msg.h"
#include "zebra/debug.h"
+#include "zebra/label_manager_clippy.c"
+
#define CONNECTION_DELAY 5
struct label_manager lbl_mgr;
@@ -49,10 +51,14 @@ DEFINE_HOOK(lm_get_chunk,
DEFINE_HOOK(lm_release_chunk,
(struct zserv *client, uint32_t start, uint32_t end),
(client, start, end));
+/* show running-config needs an API for dynamic-block */
+DEFINE_HOOK(lm_write_label_block_config,
+ (struct vty *vty, struct zebra_vrf *zvrf),
+ (vty, zvrf));
DEFINE_HOOK(lm_cbs_inited, (), ());
-/* define wrappers to be called in zapi_msg.c (as hooks must be called in
- * source file where they were defined)
+/* define wrappers to be called in zapi_msg.c or zebra_mpls_vty.c (as hooks
+ * must be called in source file where they were defined)
*/
void lm_client_connect_call(struct zserv *client, vrf_id_t vrf_id)
{
@@ -69,6 +75,11 @@ void lm_release_chunk_call(struct zserv *client, uint32_t start, uint32_t end)
hook_call(lm_release_chunk, client, start, end);
}
+int lm_write_label_block_config_call(struct vty *vty, struct zebra_vrf *zvrf)
+{
+ return hook_call(lm_write_label_block_config, vty, zvrf);
+}
+
/* forward declarations of the static functions to be used for some hooks */
static int label_manager_connect(struct zserv *client, vrf_id_t vrf_id);
static int label_manager_disconnect(struct zserv *client);
@@ -78,6 +89,8 @@ static int label_manager_get_chunk(struct label_manager_chunk **lmc,
vrf_id_t vrf_id);
static int label_manager_release_label_chunk(struct zserv *client,
uint32_t start, uint32_t end);
+static int label_manager_write_label_block_config(struct vty *vty,
+ struct zebra_vrf *zvrf);
void delete_label_chunk(void *val)
{
@@ -96,7 +109,7 @@ void delete_label_chunk(void *val)
*/
int release_daemon_label_chunks(struct zserv *client)
{
- struct listnode *node;
+ struct listnode *node, *nnode;
struct label_manager_chunk *lmc;
int count = 0;
int ret;
@@ -106,7 +119,7 @@ int release_daemon_label_chunks(struct zserv *client)
__func__, zebra_route_string(client->proto),
client->instance, client->session_id);
- for (ALL_LIST_ELEMENTS_RO(lbl_mgr.lc_list, node, lmc)) {
+ for (ALL_LIST_ELEMENTS(lbl_mgr.lc_list, node, nnode, lmc)) {
if (lmc->proto == client->proto &&
lmc->instance == client->instance &&
lmc->session_id == client->session_id && lmc->keep == 0) {
@@ -136,6 +149,8 @@ void lm_hooks_register(void)
hook_register(lm_client_disconnect, label_manager_disconnect);
hook_register(lm_get_chunk, label_manager_get_chunk);
hook_register(lm_release_chunk, label_manager_release_label_chunk);
+ hook_register(lm_write_label_block_config,
+ label_manager_write_label_block_config);
}
void lm_hooks_unregister(void)
{
@@ -143,6 +158,127 @@ void lm_hooks_unregister(void)
hook_unregister(lm_client_disconnect, label_manager_disconnect);
hook_unregister(lm_get_chunk, label_manager_get_chunk);
hook_unregister(lm_release_chunk, label_manager_release_label_chunk);
+ hook_unregister(lm_write_label_block_config,
+ label_manager_write_label_block_config);
+}
+
+static json_object *lmc_json(struct label_manager_chunk *lmc)
+{
+ json_object *json = json_object_new_object();
+
+ json_object_string_add(json, "protocol", zebra_route_string(lmc->proto));
+ json_object_int_add(json, "instance", lmc->instance);
+ json_object_int_add(json, "sessionId", lmc->session_id);
+ json_object_int_add(json, "start", lmc->start);
+ json_object_int_add(json, "end", lmc->end);
+ json_object_boolean_add(json, "dynamic", lmc->is_dynamic);
+ return json;
+}
+
+DEFPY(show_label_table, show_label_table_cmd, "show debugging label-table [json$uj]",
+ SHOW_STR
+ DEBUG_STR
+ "Display allocated label chunks\n"
+ JSON_STR)
+{
+ struct label_manager_chunk *lmc;
+ struct listnode *node;
+ json_object *json_array = NULL, *json_global = NULL, *json_dyn_block;
+
+ if (uj) {
+ json_array = json_object_new_array();
+ json_global = json_object_new_object();
+ json_dyn_block = json_object_new_object();
+ json_object_int_add(json_dyn_block, "lowerBound",
+ lbl_mgr.dynamic_block_start);
+ json_object_int_add(json_dyn_block, "upperBound",
+ lbl_mgr.dynamic_block_end);
+ json_object_object_add(json_global, "dynamicBlock",
+ json_dyn_block);
+ } else
+ vty_out(vty, "Dynamic block: lower-bound %u, upper-bound %u\n",
+ lbl_mgr.dynamic_block_start, lbl_mgr.dynamic_block_end);
+
+ for (ALL_LIST_ELEMENTS_RO(lbl_mgr.lc_list, node, lmc)) {
+ if (uj) {
+ json_object_array_add(json_array, lmc_json(lmc));
+ continue;
+ }
+ vty_out(vty, "Proto %s: [%u/%u]\n",
+ zebra_route_string(lmc->proto), lmc->start, lmc->end);
+ }
+ if (uj) {
+ json_object_object_add(json_global, "chunks", json_array);
+ vty_json(vty, json_global);
+ }
+ return CMD_SUCCESS;
+}
+
+DEFPY(mpls_label_dynamic_block, mpls_label_dynamic_block_cmd,
+ "[no$no] mpls label dynamic-block [(16-1048575)$start (16-1048575)$end]",
+ NO_STR
+ MPLS_STR
+ "Label configuration\n"
+ "Configure dynamic label block\n"
+ "Start label\n"
+ "End label\n")
+{
+ struct listnode *node;
+ struct label_manager_chunk *lmc;
+
+ /* unset dynamic range */
+ if (no ||
+ (start == MPLS_LABEL_UNRESERVED_MIN && end == MPLS_LABEL_MAX)) {
+ lbl_mgr.dynamic_block_start = MPLS_LABEL_UNRESERVED_MIN;
+ lbl_mgr.dynamic_block_end = MPLS_LABEL_MAX;
+ return CMD_SUCCESS;
+ }
+ if (!start || !end) {
+ vty_out(vty,
+ "%% label dynamic-block, range missing, aborting\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ if (start > end) {
+ vty_out(vty,
+ "%% label dynamic-block, wrong range (%ld > %ld), aborting\n",
+ start, end);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ for (ALL_LIST_ELEMENTS_RO(lbl_mgr.lc_list, node, lmc)) {
+ if (lmc->proto == NO_PROTO)
+ continue;
+ if (!lmc->is_dynamic && lmc->start >= (uint32_t)start &&
+ lmc->end <= (uint32_t)end) {
+ vty_out(vty,
+ "%% Found a static label chunk [%u-%u] for %s in conflict with the dynamic label block\n",
+ lmc->start, lmc->end,
+ zebra_route_string(lmc->proto));
+ return CMD_WARNING_CONFIG_FAILED;
+ } else if (lmc->is_dynamic && (lmc->end > (uint32_t)end ||
+ lmc->start < (uint32_t)start)) {
+ vty_out(vty,
+ "%% Found a dynamic label chunk [%u-%u] for %s outside the new dynamic label block, consider restart the service\n",
+ lmc->start, lmc->end,
+ zebra_route_string(lmc->proto));
+ }
+ }
+ lbl_mgr.dynamic_block_start = start;
+ lbl_mgr.dynamic_block_end = end;
+ return CMD_SUCCESS;
+}
+
+static int label_manager_write_label_block_config(struct vty *vty,
+ struct zebra_vrf *zvrf)
+{
+ if (zvrf_id(zvrf) != VRF_DEFAULT)
+ return 0;
+ if (lbl_mgr.dynamic_block_start == MPLS_LABEL_UNRESERVED_MIN &&
+ lbl_mgr.dynamic_block_end == MPLS_LABEL_MAX)
+ return 0;
+ vty_out(vty, "mpls label dynamic-block %u %u\n",
+ lbl_mgr.dynamic_block_start, lbl_mgr.dynamic_block_end);
+ return 1;
}
/**
@@ -152,6 +288,8 @@ void label_manager_init(void)
{
lbl_mgr.lc_list = list_new();
lbl_mgr.lc_list->del = delete_label_chunk;
+ lbl_mgr.dynamic_block_start = MPLS_LABEL_UNRESERVED_MIN;
+ lbl_mgr.dynamic_block_end = MPLS_LABEL_MAX;
hook_register(zserv_client_close, lm_client_disconnect_cb);
/* register default hooks for the label manager actions */
@@ -159,12 +297,20 @@ void label_manager_init(void)
/* notify any external module that we are done */
hook_call(lm_cbs_inited);
+
+ install_element(VIEW_NODE, &show_label_table_cmd);
+ install_element(CONFIG_NODE, &mpls_label_dynamic_block_cmd);
+}
+
+void label_manager_terminate(void)
+{
+ list_delete(&lbl_mgr.lc_list);
}
/* alloc and fill a label chunk */
struct label_manager_chunk *
create_label_chunk(uint8_t proto, unsigned short instance, uint32_t session_id,
- uint8_t keep, uint32_t start, uint32_t end)
+ uint8_t keep, uint32_t start, uint32_t end, bool is_dynamic)
{
/* alloc chunk, fill it and return it */
struct label_manager_chunk *lmc =
@@ -176,6 +322,7 @@ create_label_chunk(uint8_t proto, unsigned short instance, uint32_t session_id,
lmc->instance = instance;
lmc->session_id = session_id;
lmc->keep = keep;
+ lmc->is_dynamic = is_dynamic;
return lmc;
}
@@ -203,6 +350,15 @@ assign_specific_label_chunk(uint8_t proto, unsigned short instance,
return NULL;
}
+ if ((lbl_mgr.dynamic_block_start != MPLS_LABEL_UNRESERVED_MIN ||
+ lbl_mgr.dynamic_block_end != MPLS_LABEL_MAX) &&
+ base >= lbl_mgr.dynamic_block_start &&
+ end <= lbl_mgr.dynamic_block_end) {
+ zlog_warn("Invalid LM request arguments: base: %u, size: %u for %s in conflict with the dynamic label block",
+ base, size, zebra_route_string(proto));
+ return NULL;
+ }
+
/* Scan the existing chunks to see if the requested range of labels
* falls inside any of such chunks */
for (ALL_LIST_ELEMENTS_RO(lbl_mgr.lc_list, node, lmc)) {
@@ -234,7 +390,7 @@ assign_specific_label_chunk(uint8_t proto, unsigned short instance,
/* insert chunk between existing chunks */
if (insert_node) {
lmc = create_label_chunk(proto, instance, session_id, keep,
- base, end);
+ base, end, false);
listnode_add_before(lbl_mgr.lc_list, insert_node, lmc);
return lmc;
}
@@ -257,7 +413,7 @@ assign_specific_label_chunk(uint8_t proto, unsigned short instance,
}
lmc = create_label_chunk(proto, instance, session_id, keep,
- base, end);
+ base, end, false);
if (last_node)
listnode_add_before(lbl_mgr.lc_list, last_node, lmc);
else
@@ -268,7 +424,7 @@ assign_specific_label_chunk(uint8_t proto, unsigned short instance,
/* create a new chunk past all the existing ones and link at
* tail */
lmc = create_label_chunk(proto, instance, session_id, keep,
- base, end);
+ base, end, false);
listnode_add(lbl_mgr.lc_list, lmc);
return lmc;
}
@@ -293,9 +449,13 @@ assign_label_chunk(uint8_t proto, unsigned short instance, uint32_t session_id,
{
struct label_manager_chunk *lmc;
struct listnode *node;
- uint32_t prev_end = MPLS_LABEL_UNRESERVED_MIN;
+ uint32_t prev_end = lbl_mgr.dynamic_block_start - 1;
+ struct label_manager_chunk *lmc_block_last = NULL;
- /* handle chunks request with a specific base label */
+ /* handle chunks request with a specific base label
+ * - static label requests: BGP hardset value, Pathd
+ * - segment routing label requests
+ */
if (base != MPLS_LABEL_BASE_ANY)
return assign_specific_label_chunk(proto, instance, session_id,
keep, size, base);
@@ -305,37 +465,44 @@ assign_label_chunk(uint8_t proto, unsigned short instance, uint32_t session_id,
/* first check if there's one available */
for (ALL_LIST_ELEMENTS_RO(lbl_mgr.lc_list, node, lmc)) {
- if (lmc->proto == NO_PROTO
- && lmc->end - lmc->start + 1 == size) {
+ if (lmc->start <= prev_end)
+ continue;
+ if (lmc->proto == NO_PROTO &&
+ lmc->end - lmc->start + 1 == size &&
+ lmc->end <= lbl_mgr.dynamic_block_end) {
lmc->proto = proto;
lmc->instance = instance;
lmc->session_id = session_id;
lmc->keep = keep;
+ lmc->is_dynamic = true;
return lmc;
}
/* check if we hadve a "hole" behind us that we can squeeze into
*/
- if ((lmc->start > prev_end) && (lmc->start - prev_end > size)) {
+ if (lmc->start - prev_end > size &&
+ prev_end + 1 + size <= lbl_mgr.dynamic_block_end) {
lmc = create_label_chunk(proto, instance, session_id,
keep, prev_end + 1,
- prev_end + size);
+ prev_end + size, true);
listnode_add_before(lbl_mgr.lc_list, node, lmc);
return lmc;
}
prev_end = lmc->end;
+
+ /* check if we have a chunk that goes over the end block */
+ if (lmc->end > lbl_mgr.dynamic_block_end)
+ continue;
+ lmc_block_last = lmc;
}
/* otherwise create a new one */
uint32_t start_free;
- if (list_isempty(lbl_mgr.lc_list))
- start_free = MPLS_LABEL_UNRESERVED_MIN;
+ if (lmc_block_last == NULL)
+ start_free = lbl_mgr.dynamic_block_start;
else
- start_free = ((struct label_manager_chunk *)listgetdata(
- listtail(lbl_mgr.lc_list)))
- ->end
- + 1;
+ start_free = lmc_block_last->end + 1;
- if (start_free > MPLS_LABEL_UNRESERVED_MAX - size + 1) {
+ if (start_free > lbl_mgr.dynamic_block_end - size + 1) {
flog_err(EC_ZEBRA_LM_EXHAUSTED_LABELS,
"Reached max labels. Start: %u, size: %u", start_free,
size);
@@ -344,7 +511,7 @@ assign_label_chunk(uint8_t proto, unsigned short instance, uint32_t session_id,
/* create chunk and link at tail */
lmc = create_label_chunk(proto, instance, session_id, keep, start_free,
- start_free + size - 1);
+ start_free + size - 1, true);
listnode_add(lbl_mgr.lc_list, lmc);
return lmc;
}
@@ -399,13 +566,14 @@ int release_label_chunk(uint8_t proto, unsigned short instance,
"%s: Daemon mismatch!!", __func__);
continue;
}
- lmc->proto = NO_PROTO;
- lmc->instance = 0;
- lmc->session_id = 0;
- lmc->keep = 0;
ret = 0;
break;
}
+ if (lmc) {
+ list_delete_node(lbl_mgr.lc_list, node);
+ delete_label_chunk(lmc);
+ }
+
if (ret != 0)
flog_err(EC_ZEBRA_LM_UNRELEASED_CHUNK,
"%s: Label chunk not released!!", __func__);
@@ -435,7 +603,25 @@ static int label_manager_get_chunk(struct label_manager_chunk **lmc,
{
*lmc = assign_label_chunk(client->proto, client->instance,
client->session_id, keep, size, base);
- return lm_get_chunk_response(*lmc, client, vrf_id);
+ /* Respond to a get_chunk request */
+ if (!*lmc) {
+ if (base == MPLS_LABEL_BASE_ANY)
+ flog_err(EC_ZEBRA_LM_CANNOT_ASSIGN_CHUNK,
+ "Unable to assign Label Chunk size %u to %s instance %u",
+ size, zebra_route_string(client->proto),
+ client->instance);
+ else
+ flog_err(EC_ZEBRA_LM_CANNOT_ASSIGN_CHUNK,
+ "Unable to assign Label Chunk %u - %u to %s instance %u",
+ base, base + size - 1,
+ zebra_route_string(client->proto),
+ client->instance);
+ } else if (IS_ZEBRA_DEBUG_PACKET)
+ zlog_debug("Assigned Label Chunk %u - %u to %s instance %u",
+ (*lmc)->start, (*lmc)->end,
+ zebra_route_string(client->proto), client->instance);
+
+ return zsend_assign_label_chunk_response(client, vrf_id, *lmc);
}
/* Respond to a connect request */
@@ -454,22 +640,6 @@ int lm_client_connect_response(uint8_t proto, uint16_t instance,
return zsend_label_manager_connect_response(client, vrf_id, result);
}
-/* Respond to a get_chunk request */
-int lm_get_chunk_response(struct label_manager_chunk *lmc, struct zserv *client,
- vrf_id_t vrf_id)
-{
- if (!lmc)
- flog_err(EC_ZEBRA_LM_CANNOT_ASSIGN_CHUNK,
- "Unable to assign Label Chunk to %s instance %u",
- zebra_route_string(client->proto), client->instance);
- else if (IS_ZEBRA_DEBUG_PACKET)
- zlog_debug("Assigned Label Chunk %u - %u to %s instance %u",
- lmc->start, lmc->end,
- zebra_route_string(client->proto), client->instance);
-
- return zsend_assign_label_chunk_response(client, vrf_id, lmc);
-}
-
void label_manager_close(void)
{
list_delete(&lbl_mgr.lc_list);
diff --git a/zebra/label_manager.h b/zebra/label_manager.h
index cfbb4bd169..03cf6a6813 100644
--- a/zebra/label_manager.h
+++ b/zebra/label_manager.h
@@ -42,6 +42,7 @@ struct label_manager_chunk {
unsigned short instance;
uint32_t session_id;
uint8_t keep;
+ uint8_t is_dynamic; /* Tell if chunk is dynamic or static */
uint32_t start; /* First label of the chunk */
uint32_t end; /* Last label of the chunk */
};
@@ -61,11 +62,14 @@ DECLARE_HOOK(lm_get_chunk,
DECLARE_HOOK(lm_release_chunk,
(struct zserv *client, uint32_t start, uint32_t end),
(client, start, end));
+DECLARE_HOOK(lm_write_label_block_config,
+ (struct vty *vty, struct zebra_vrf *zvrf),
+ (vty, zvrf));
DECLARE_HOOK(lm_cbs_inited, (), ());
-/* declare wrappers to be called in zapi_msg.c (as hooks must be called in
- * source file where they were defined)
+/* declare wrappers to be called in zapi_msg.c or zebra_mpls_vty.c (as hooks
+ * must be called in source file where they were defined)
*/
void lm_client_connect_call(struct zserv *client, vrf_id_t vrf_id);
void lm_get_chunk_call(struct label_manager_chunk **lmc, struct zserv *client,
@@ -73,18 +77,17 @@ void lm_get_chunk_call(struct label_manager_chunk **lmc, struct zserv *client,
vrf_id_t vrf_id);
void lm_release_chunk_call(struct zserv *client, uint32_t start,
uint32_t end);
+int lm_write_label_block_config_call(struct vty *vty, struct zebra_vrf *zvrf);
/* API for an external LM to return responses for requests */
int lm_client_connect_response(uint8_t proto, uint16_t instance,
uint32_t session_id, vrf_id_t vrf_id,
uint8_t result);
-int lm_get_chunk_response(struct label_manager_chunk *lmc, struct zserv *client,
- vrf_id_t vrf_id);
/* convenience function to allocate an lmc to be consumed by the above API */
struct label_manager_chunk *
create_label_chunk(uint8_t proto, unsigned short instance, uint32_t session_id,
- uint8_t keep, uint32_t start, uint32_t end);
+ uint8_t keep, uint32_t start, uint32_t end, bool is_dynamic);
void delete_label_chunk(void *val);
/* register/unregister callbacks for hooks */
@@ -97,9 +100,13 @@ void lm_hooks_unregister(void);
*/
struct label_manager {
struct list *lc_list;
+ uint32_t dynamic_block_start;
+ uint32_t dynamic_block_end;
};
void label_manager_init(void);
+void label_manager_terminate(void);
+
struct label_manager_chunk *
assign_label_chunk(uint8_t proto, unsigned short instance, uint32_t session_id,
uint8_t keep, uint32_t size, uint32_t base);
diff --git a/zebra/main.c b/zebra/main.c
index 81a3066445..d83f1d0491 100644
--- a/zebra/main.c
+++ b/zebra/main.c
@@ -5,6 +5,10 @@
#include <zebra.h>
+#ifdef GNU_LINUX
+#include <linux/rtnetlink.h>
+#endif
+
#include <lib/version.h>
#include "getopt.h"
#include "command.h"
@@ -21,6 +25,7 @@
#include "affinitymap.h"
#include "routemap.h"
#include "routing_nb.h"
+#include "mgmt_be_client.h"
#include "zebra/zebra_router.h"
#include "zebra/zebra_errors.h"
@@ -54,13 +59,13 @@ pid_t pid;
/* Pacify zclient.o in libfrr, which expects this variable. */
struct event_loop *master;
+struct mgmt_be_client *mgmt_be_client;
+
/* Route retain mode flag. */
int retain_mode = 0;
int graceful_restart;
-bool v6_rr_semantics = false;
-
/* Receive buffer size for kernel control sockets */
#define RCVBUFSIZE_MIN 4194304
#ifdef HAVE_NETLINK
@@ -69,24 +74,30 @@ uint32_t rcvbufsize = RCVBUFSIZE_MIN;
uint32_t rcvbufsize = 128 * 1024;
#endif
+uint32_t rt_table_main_id = RT_TABLE_MAIN;
+
#define OPTION_V6_RR_SEMANTICS 2000
#define OPTION_ASIC_OFFLOAD 2001
+#define OPTION_V6_WITH_V4_NEXTHOP 2002
/* Command line options. */
const struct option longopts[] = {
- {"batch", no_argument, NULL, 'b'},
- {"allow_delete", no_argument, NULL, 'a'},
- {"socket", required_argument, NULL, 'z'},
- {"ecmp", required_argument, NULL, 'e'},
- {"retain", no_argument, NULL, 'r'},
- {"graceful_restart", required_argument, NULL, 'K'},
- {"asic-offload", optional_argument, NULL, OPTION_ASIC_OFFLOAD},
+ { "batch", no_argument, NULL, 'b' },
+ { "allow_delete", no_argument, NULL, 'a' },
+ { "socket", required_argument, NULL, 'z' },
+ { "ecmp", required_argument, NULL, 'e' },
+ { "retain", no_argument, NULL, 'r' },
+ { "graceful_restart", required_argument, NULL, 'K' },
+ { "asic-offload", optional_argument, NULL, OPTION_ASIC_OFFLOAD },
+ { "v6-with-v4-nexthops", no_argument, NULL, OPTION_V6_WITH_V4_NEXTHOP },
#ifdef HAVE_NETLINK
- {"vrfwnetns", no_argument, NULL, 'n'},
- {"nl-bufsize", required_argument, NULL, 's'},
- {"v6-rr-semantics", no_argument, NULL, OPTION_V6_RR_SEMANTICS},
+ { "vrfwnetns", no_argument, NULL, 'n' },
+ { "nl-bufsize", required_argument, NULL, 's' },
+ { "v6-rr-semantics", no_argument, NULL, OPTION_V6_RR_SEMANTICS },
#endif /* HAVE_NETLINK */
- {0}};
+ {"routing-table", optional_argument, NULL, 'R'},
+ { 0 }
+};
zebra_capabilities_t _caps_p[] = {ZCAP_NET_ADMIN, ZCAP_SYS_ADMIN,
ZCAP_NET_RAW,
@@ -134,6 +145,10 @@ static void sigint(void)
zlog_notice("Terminating on signal");
+ nb_oper_cancel_all_walks();
+ mgmt_be_client_destroy(mgmt_be_client);
+ mgmt_be_client = NULL;
+
atomic_store_explicit(&zrouter.in_shutdown, true,
memory_order_relaxed);
@@ -188,6 +203,13 @@ static void sigint(void)
rib_update_finish();
list_delete(&zrouter.client_list);
+ list_delete(&zrouter.stale_client_list);
+
+ /*
+ * Besides other clean-ups zebra's vrf_disable() also enqueues installed
+ * routes for removal from the kernel, unless ZEBRA_VRF_RETAIN is set.
+ */
+ vrf_iterate(vrf_disable);
/* Indicate that all new dplane work has been enqueued. When that
* work is complete, the dataplane will enqueue an event
@@ -206,17 +228,31 @@ void zebra_finalize(struct event *dummy)
vrf_terminate();
+ /*
+ * Stop dplane thread and finish any cleanup
+ * This is before the zebra_ns_early_shutdown call
+ * because sockets that the dplane depends on are closed
+ * in those functions
+ */
+ zebra_dplane_shutdown();
+
ns_walk_func(zebra_ns_early_shutdown, NULL, NULL);
zebra_ns_notify_close();
- /* Stop dplane thread and finish any cleanup */
- zebra_dplane_shutdown();
-
/* Final shutdown of ns resources */
ns_walk_func(zebra_ns_final_shutdown, NULL, NULL);
+ zebra_rib_terminate();
zebra_router_terminate();
+ zebra_mpls_terminate();
+
+ zebra_pw_terminate();
+
+ zebra_srv6_terminate();
+
+ label_manager_terminate();
+
ns_terminate();
frr_fini();
exit(0);
@@ -260,19 +296,23 @@ static const struct frr_yang_module_info *const zebra_yang_modules[] = {
};
/* clang-format on */
-FRR_DAEMON_INFO(
- zebra, ZEBRA, .vty_port = ZEBRA_VTY_PORT, .flags = FRR_NO_ZCLIENT,
-
+/* clang-format off */
+FRR_DAEMON_INFO(zebra, ZEBRA,
+ .vty_port = ZEBRA_VTY_PORT,
.proghelp =
"Daemon which manages kernel routing table management and\nredistribution between different routing protocols.",
- .signals = zebra_signals, .n_signals = array_size(zebra_signals),
+ .flags = FRR_NO_ZCLIENT,
+
+ .signals = zebra_signals,
+ .n_signals = array_size(zebra_signals),
.privs = &zserv_privs,
.yang_modules = zebra_yang_modules,
.n_yang_modules = array_size(zebra_yang_modules),
);
+/* clang-format on */
/* Main startup routine. */
int main(int argc, char **argv)
@@ -282,6 +322,7 @@ int main(int argc, char **argv)
struct sockaddr_storage dummy;
socklen_t dummylen;
bool asic_offload = false;
+ bool v6_with_v4_nexthop = false;
bool notify_on_ack = true;
graceful_restart = 0;
@@ -289,27 +330,28 @@ int main(int argc, char **argv)
frr_preinit(&zebra_di, argc, argv);
- frr_opt_add(
- "baz:e:rK:s:"
+ frr_opt_add("baz:e:rK:s:R:"
#ifdef HAVE_NETLINK
- "n"
+ "n"
#endif
- ,
- longopts,
- " -b, --batch Runs in batch mode\n"
- " -a, --allow_delete Allow other processes to delete zebra routes\n"
- " -z, --socket Set path of zebra socket\n"
- " -e, --ecmp Specify ECMP to use.\n"
- " -r, --retain When program terminates, retain added route by zebra.\n"
- " -K, --graceful_restart Graceful restart at the kernel level, timer in seconds for expiration\n"
- " -A, --asic-offload FRR is interacting with an asic underneath the linux kernel\n"
+ ,
+ longopts,
+ " -b, --batch Runs in batch mode\n"
+ " -a, --allow_delete Allow other processes to delete zebra routes\n"
+ " -z, --socket Set path of zebra socket\n"
+ " -e, --ecmp Specify ECMP to use.\n"
+ " -r, --retain When program terminates, retain added route by zebra.\n"
+ " -K, --graceful_restart Graceful restart at the kernel level, timer in seconds for expiration\n"
+ " -A, --asic-offload FRR is interacting with an asic underneath the linux kernel\n"
+ " --v6-with-v4-nexthops Underlying dataplane supports v6 routes with v4 nexthops"
#ifdef HAVE_NETLINK
- " -s, --nl-bufsize Set netlink receive buffer size\n"
- " -n, --vrfwnetns Use NetNS as VRF backend\n"
- " --v6-rr-semantics Use v6 RR semantics\n"
+ " -s, --nl-bufsize Set netlink receive buffer size\n"
+ " -n, --vrfwnetns Use NetNS as VRF backend\n"
+ " --v6-rr-semantics Use v6 RR semantics\n"
#else
- " -s, Set kernel socket receive buffer size\n"
+ " -s, Set kernel socket receive buffer size\n"
#endif /* HAVE_NETLINK */
+ " -R, --routing-table Set kernel routing table\n"
);
while (1) {
@@ -364,12 +406,15 @@ int main(int argc, char **argv)
"Rcvbufsize is smaller than recommended value: %d\n",
RCVBUFSIZE_MIN);
break;
+ case 'R':
+ rt_table_main_id = atoi(optarg);
+ break;
#ifdef HAVE_NETLINK
case 'n':
vrf_configure_backend(VRF_BACKEND_NETNS);
break;
case OPTION_V6_RR_SEMANTICS:
- v6_rr_semantics = true;
+ zrouter.v6_rr_semantics = true;
break;
case OPTION_ASIC_OFFLOAD:
if (!strcmp(optarg, "notify_on_offload"))
@@ -378,6 +423,9 @@ int main(int argc, char **argv)
notify_on_ack = true;
asic_offload = true;
break;
+ case OPTION_V6_WITH_V4_NEXTHOP:
+ v6_with_v4_nexthop = true;
+ break;
#endif /* HAVE_NETLINK */
default:
frr_help_exit(1);
@@ -387,9 +435,9 @@ int main(int argc, char **argv)
zrouter.master = frr_init();
/* Zebra related initialize. */
- zebra_router_init(asic_offload, notify_on_ack);
+ zebra_router_init(asic_offload, notify_on_ack, v6_with_v4_nexthop);
zserv_init();
- rib_init();
+ zebra_rib_init();
zebra_if_init();
zebra_debug_init();
@@ -399,8 +447,12 @@ int main(int argc, char **argv)
zebra_ns_init();
router_id_cmd_init();
zebra_vty_init();
- access_list_init();
+ mgmt_be_client = mgmt_be_client_create("zebra", NULL, 0,
+ zrouter.master);
+ access_list_init_new(true);
prefix_list_init();
+
+ rtadv_init();
rtadv_cmd_init();
/* PTM socket */
#ifdef ZEBRA_PTM_SUPPORT
diff --git a/zebra/netconf_netlink.c b/zebra/netconf_netlink.c
index 7352dfb2ee..002d2c7bf6 100644
--- a/zebra/netconf_netlink.c
+++ b/zebra/netconf_netlink.c
@@ -6,11 +6,14 @@
* Donald Sharp
*/
#include <zebra.h>
+#include <fcntl.h>
#ifdef HAVE_NETLINK /* Netlink OSes only */
#include <ns.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
#include "linux/netconf.h"
#include "lib/lib_errors.h"
diff --git a/zebra/redistribute.c b/zebra/redistribute.c
index d2fa85eb64..11c1330398 100644
--- a/zebra/redistribute.c
+++ b/zebra/redistribute.c
@@ -16,6 +16,7 @@
#include "log.h"
#include "vrf.h"
#include "srcdest_table.h"
+#include "frrdistance.h"
#include "zebra/rib.h"
#include "zebra/zebra_router.h"
@@ -28,6 +29,7 @@
#include "zebra/zapi_msg.h"
#include "zebra/zebra_vxlan.h"
#include "zebra/zebra_errors.h"
+#include "zebra/zebra_neigh.h"
#define ZEBRA_PTM_SUPPORT
@@ -60,7 +62,7 @@ static void zebra_redistribute_default(struct zserv *client, vrf_id_t vrf_id)
for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
- if (!vrf_bitmap_check(client->redist_default[afi], vrf_id))
+ if (!vrf_bitmap_check(&client->redist_default[afi], vrf_id))
continue;
/* Lookup table. */
@@ -77,9 +79,8 @@ static void zebra_redistribute_default(struct zserv *client, vrf_id_t vrf_id)
RNODE_FOREACH_RE (rn, newre) {
if (CHECK_FLAG(newre->flags, ZEBRA_FLAG_SELECTED))
- zsend_redistribute_route(
- ZEBRA_REDISTRIBUTE_ROUTE_ADD, client,
- rn, newre);
+ zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_ADD,
+ client, rn, newre, false);
}
route_unlock_node(rn);
@@ -88,14 +89,26 @@ static void zebra_redistribute_default(struct zserv *client, vrf_id_t vrf_id)
/* Redistribute routes. */
static void zebra_redistribute(struct zserv *client, int type,
- unsigned short instance, vrf_id_t vrf_id,
+ unsigned short instance, struct zebra_vrf *zvrf,
int afi)
{
struct route_entry *newre;
struct route_table *table;
struct route_node *rn;
+ bool is_table_direct = false;
+ vrf_id_t vrf_id = zvrf_id(zvrf);
+
+ if (type == ZEBRA_ROUTE_TABLE_DIRECT) {
+ if (vrf_id == VRF_DEFAULT) {
+ table = zebra_router_find_table(zvrf, instance, afi,
+ SAFI_UNICAST);
+ type = ZEBRA_ROUTE_ALL;
+ is_table_direct = true;
+ } else
+ return;
+ } else
+ table = zebra_vrf_table(afi, SAFI_UNICAST, vrf_id);
- table = zebra_vrf_table(afi, SAFI_UNICAST, vrf_id);
if (!table)
return;
@@ -125,11 +138,26 @@ static void zebra_redistribute(struct zserv *client, int type,
continue;
zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_ADD,
- client, rn, newre);
+ client, rn, newre, is_table_direct);
}
}
/*
+ * Function to return a valid table id value if table-direct is used
+ * return 0 otherwise
+ * This function can be called only if zebra_redistribute_check returns TRUE
+ */
+static bool zebra_redistribute_is_table_direct(const struct route_entry *re)
+{
+ struct zebra_vrf *zvrf;
+
+ zvrf = zebra_vrf_lookup_by_id(re->vrf_id);
+ if (re->vrf_id == VRF_DEFAULT && zvrf->table_id != re->table)
+ return true;
+ return false;
+}
+
+/*
* Function to check if prefix is candidate for
* redistribute.
*/
@@ -146,16 +174,27 @@ static bool zebra_redistribute_check(const struct route_node *rn,
afi = family2afi(rn->p.family);
zvrf = zebra_vrf_lookup_by_id(re->vrf_id);
- if (re->vrf_id == VRF_DEFAULT && zvrf->table_id != re->table)
+ if (re->vrf_id == VRF_DEFAULT && zvrf->table_id != re->table) {
+ if (re->table &&
+ redist_check_instance(&client->mi_redist
+ [afi][ZEBRA_ROUTE_TABLE_DIRECT],
+ re->table)) {
+ /* table-direct redistribution only for route entries which
+ * are on the default vrf, and that have table id different
+ * from the default table.
+ */
+ return true;
+ }
return false;
+ }
/* If default route and redistributed */
if (is_default_prefix(&rn->p) &&
- vrf_bitmap_check(client->redist_default[afi], re->vrf_id))
+ vrf_bitmap_check(&client->redist_default[afi], re->vrf_id))
return true;
/* If redistribute in enabled for zebra route all */
- if (vrf_bitmap_check(client->redist[afi][ZEBRA_ROUTE_ALL], re->vrf_id))
+ if (vrf_bitmap_check(&client->redist[afi][ZEBRA_ROUTE_ALL], re->vrf_id))
return true;
/*
@@ -171,7 +210,7 @@ static bool zebra_redistribute_check(const struct route_node *rn,
}
/* If redistribution is enabled for give route type. */
- if (vrf_bitmap_check(client->redist[afi][re->type], re->vrf_id))
+ if (vrf_bitmap_check(&client->redist[afi][re->type], re->vrf_id))
return true;
return false;
@@ -185,6 +224,7 @@ void redistribute_update(const struct route_node *rn,
{
struct listnode *node, *nnode;
struct zserv *client;
+ bool is_table_direct;
if (IS_ZEBRA_DEBUG_RIB)
zlog_debug(
@@ -210,11 +250,16 @@ void redistribute_update(const struct route_node *rn,
re->vrf_id, re->table, re->type,
re->distance, re->metric);
}
+ is_table_direct = zebra_redistribute_is_table_direct(re);
zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_ADD,
- client, rn, re);
- } else if (zebra_redistribute_check(rn, prev_re, client))
+ client, rn, re,
+ is_table_direct);
+ } else if (zebra_redistribute_check(rn, prev_re, client)) {
+ is_table_direct = zebra_redistribute_is_table_direct(prev_re);
zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_DEL,
- client, rn, prev_re);
+ client, rn, prev_re,
+ is_table_direct);
+ }
}
}
@@ -233,6 +278,7 @@ void redistribute_delete(const struct route_node *rn,
struct listnode *node, *nnode;
struct zserv *client;
vrf_id_t vrfid;
+ bool is_table_direct;
if (old_re)
vrfid = old_re->vrf_id;
@@ -256,12 +302,11 @@ void redistribute_delete(const struct route_node *rn,
table = new_re->table;
}
- zlog_debug(
- "%u:%u%pRN: Redist del: re %p (%u:%s), new re %p (%u:%s)",
- vrfid, table, rn, old_re, old_inst,
- old_re ? zebra_route_string(old_re->type) : "None",
- new_re, new_inst,
- new_re ? zebra_route_string(new_re->type) : "None");
+ zlog_debug("(%u:%u):%pRN: Redist del: re %p (%u:%s), new re %p (%u:%s)",
+ vrfid, table, rn, old_re, old_inst,
+ old_re ? zebra_route_string(old_re->type) : "None",
+ new_re, new_inst,
+ new_re ? zebra_route_string(new_re->type) : "None");
}
/* Skip invalid (e.g. linklocal) prefix */
@@ -286,9 +331,20 @@ void redistribute_delete(const struct route_node *rn,
continue;
/* Send a delete for the 'old' re to any subscribed client. */
- if (zebra_redistribute_check(rn, old_re, client))
+ if (zebra_redistribute_check(rn, old_re, client)) {
+ /*
+ * SA is complaining that old_re could be false
+ * SA is wrong because old_re is checked for NULL
+ * in zebra_redistribute_check and false is
+ * returned in that case. Let's just make SA
+ * happy.
+ */
+ assert(old_re);
+ is_table_direct = zebra_redistribute_is_table_direct(old_re);
zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_DEL,
- client, rn, old_re);
+ client, rn, old_re,
+ is_table_direct);
+ }
}
}
@@ -327,20 +383,19 @@ void zebra_redistribute_add(ZAPI_HANDLER_ARGS)
instance)) {
redist_add_instance(&client->mi_redist[afi][type],
instance);
- zebra_redistribute(client, type, instance,
- zvrf_id(zvrf), afi);
+ zebra_redistribute(client, type, instance, zvrf, afi);
}
} else {
- if (!vrf_bitmap_check(client->redist[afi][type],
+ if (!vrf_bitmap_check(&client->redist[afi][type],
zvrf_id(zvrf))) {
if (IS_ZEBRA_DEBUG_EVENT)
zlog_debug(
"%s: setting vrf %s(%u) redist bitmap",
__func__, VRF_LOGNAME(zvrf->vrf),
zvrf_id(zvrf));
- vrf_bitmap_set(client->redist[afi][type],
+ vrf_bitmap_set(&client->redist[afi][type],
zvrf_id(zvrf));
- zebra_redistribute(client, type, 0, zvrf_id(zvrf), afi);
+ zebra_redistribute(client, type, 0, zvrf, afi);
}
}
@@ -387,7 +442,7 @@ void zebra_redistribute_delete(ZAPI_HANDLER_ARGS)
if (instance)
redist_del_instance(&client->mi_redist[afi][type], instance);
else
- vrf_bitmap_unset(client->redist[afi][type], zvrf_id(zvrf));
+ vrf_bitmap_unset(&client->redist[afi][type], zvrf_id(zvrf));
stream_failure:
return;
@@ -405,7 +460,7 @@ void zebra_redistribute_default_add(ZAPI_HANDLER_ARGS)
return;
}
- vrf_bitmap_set(client->redist_default[afi], zvrf_id(zvrf));
+ vrf_bitmap_set(&client->redist_default[afi], zvrf_id(zvrf));
zebra_redistribute_default(client, zvrf_id(zvrf));
stream_failure:
@@ -424,7 +479,7 @@ void zebra_redistribute_default_delete(ZAPI_HANDLER_ARGS)
return;
}
- vrf_bitmap_unset(client->redist_default[afi], zvrf_id(zvrf));
+ vrf_bitmap_unset(&client->redist_default[afi], zvrf_id(zvrf));
stream_failure:
return;
@@ -473,6 +528,8 @@ void zebra_interface_down_update(struct interface *ifp)
zsend_interface_update(ZEBRA_INTERFACE_DOWN, client, ifp);
}
+
+ zebra_neigh_del_all(ifp);
}
/* Interface information update. */
@@ -589,9 +646,8 @@ void zebra_interface_vrf_update_del(struct interface *ifp, vrf_id_t new_vrf_id)
struct zserv *client;
if (IS_ZEBRA_DEBUG_EVENT)
- zlog_debug(
- "MESSAGE: ZEBRA_INTERFACE_VRF_UPDATE/DEL %s VRF Id %u -> %u",
- ifp->name, ifp->vrf->vrf_id, new_vrf_id);
+ zlog_debug("MESSAGE: ZEBRA_INTERFACE_DELETE %s VRF Id %u -> %u",
+ ifp->name, ifp->vrf->vrf_id, new_vrf_id);
for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
/* Do not send unsolicited messages to synchronous clients. */
@@ -603,7 +659,6 @@ void zebra_interface_vrf_update_del(struct interface *ifp, vrf_id_t new_vrf_id)
zsend_interface_update(ZEBRA_INTERFACE_DOWN, client, ifp);
client->ifdel_cnt++;
zsend_interface_delete(client, ifp);
- zsend_interface_vrf_update(client, ifp, new_vrf_id);
}
}
@@ -616,9 +671,8 @@ void zebra_interface_vrf_update_add(struct interface *ifp, vrf_id_t old_vrf_id)
struct zserv *client;
if (IS_ZEBRA_DEBUG_EVENT)
- zlog_debug(
- "MESSAGE: ZEBRA_INTERFACE_VRF_UPDATE/ADD %s VRF Id %u -> %u",
- ifp->name, old_vrf_id, ifp->vrf->vrf_id);
+ zlog_debug("MESSAGE: ZEBRA_INTERFACE_ADD %s VRF Id %u -> %u",
+ ifp->name, old_vrf_id, ifp->vrf->vrf_id);
for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
/* Do not send unsolicited messages to synchronous clients. */
@@ -644,10 +698,9 @@ int zebra_add_import_table_entry(struct zebra_vrf *zvrf, struct route_node *rn,
afi = family2afi(rn->p.family);
if (rmap_name)
- ret = zebra_import_table_route_map_check(
- afi, re->type, re->instance, &rn->p,
- re->nhe->nhg.nexthop,
- zvrf->vrf->vrf_id, re->tag, rmap_name);
+ ret = zebra_import_table_route_map_check(afi, re, &rn->p,
+ re->nhe->nhg.nexthop,
+ rmap_name);
if (ret != RMAP_PERMITMATCH) {
UNSET_FLAG(re->flags, ZEBRA_FLAG_SELECTED);
@@ -661,9 +714,10 @@ int zebra_add_import_table_entry(struct zebra_vrf *zvrf, struct route_node *rn,
if (CHECK_FLAG(same->status, ROUTE_ENTRY_REMOVED))
continue;
- if (same->type == re->type && same->instance == re->instance
- && same->table == re->table
- && same->type != ZEBRA_ROUTE_CONNECT)
+ if (same->type == re->type && same->instance == re->instance &&
+ same->table == re->table &&
+ (same->type != ZEBRA_ROUTE_CONNECT &&
+ same->type != ZEBRA_ROUTE_LOCAL))
break;
}
@@ -672,6 +726,8 @@ int zebra_add_import_table_entry(struct zebra_vrf *zvrf, struct route_node *rn,
zebra_del_import_table_entry(zvrf, rn, same);
}
+ UNSET_FLAG(re->flags, ZEBRA_FLAG_RR_USE_DISTANCE);
+
newre = zebra_rib_route_entry_new(
0, ZEBRA_ROUTE_TABLE, re->table, re->flags, re->nhe_id,
zvrf->table_id, re->metric, re->mtu,
@@ -681,6 +737,7 @@ int zebra_add_import_table_entry(struct zebra_vrf *zvrf, struct route_node *rn,
copy_nexthops(&ng->nexthop, re->nhe->nhg.nexthop, NULL);
rib_add_multipath(afi, SAFI_UNICAST, &p, NULL, newre, ng, false);
+ nexthop_group_delete(&ng);
return 0;
}
@@ -712,7 +769,7 @@ int zebra_import_table(afi_t afi, vrf_id_t vrf_id, uint32_t table_id,
struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(vrf_id);
if (!is_zebra_valid_kernel_table(table_id)
- || (table_id == RT_TABLE_MAIN))
+ || (table_id == rt_table_main_id))
return -1;
if (afi >= AFI_MAX)
diff --git a/zebra/rib.h b/zebra/rib.h
index a56bb05d68..a721f4bac4 100644
--- a/zebra/rib.h
+++ b/zebra/rib.h
@@ -85,25 +85,12 @@ struct route_entry {
*/
struct nhg_hash_entry *nhe;
- /* Nexthop group from FIB (optional), reflecting what is actually
- * installed in the FIB if that differs. The 'backup' group is used
- * when backup nexthops are present in the route's nhg.
- */
- struct nexthop_group fib_ng;
- struct nexthop_group fib_backup_ng;
-
/* Nexthop group hash entry IDs. The "installed" id is the id
* used in linux/netlink, if available.
*/
uint32_t nhe_id;
uint32_t nhe_installed_id;
- /* Tag */
- route_tag_t tag;
-
- /* Uptime. */
- time_t uptime;
-
/* Type of this route. */
int type;
@@ -160,13 +147,30 @@ struct route_entry {
/* Distance. */
uint8_t distance;
+ /* Tag */
+ route_tag_t tag;
+
+ /* Uptime. */
+ time_t uptime;
+
struct re_opaque *opaque;
+
+ /* Nexthop group from FIB (optional), reflecting what is actually
+ * installed in the FIB if that differs. The 'backup' group is used
+ * when backup nexthops are present in the route's nhg.
+ */
+ struct nexthop_group fib_ng;
+ struct nexthop_group fib_backup_ng;
};
#define RIB_SYSTEM_ROUTE(R) RSYSTEM_ROUTE((R)->type)
#define RIB_KERNEL_ROUTE(R) RKERNEL_ROUTE((R)->type)
+/* Define route types that are equivalent to "connected". */
+#define RIB_CONNECTED_ROUTE(R) \
+ ((R)->type == ZEBRA_ROUTE_CONNECT || (R)->type == ZEBRA_ROUTE_LOCAL || (R)->type == ZEBRA_ROUTE_NHRP)
+
/* meta-queue structure:
* sub-queue 0: nexthop group objects
* sub-queue 1: EVPN/VxLAN objects
@@ -181,6 +185,10 @@ struct route_entry {
* don't generate routes
*/
#define MQ_SIZE 11
+
+/* For checking that an object has already queued in some sub-queue */
+#define MQ_BIT_MASK ((1 << MQ_SIZE) - 1)
+
struct meta_queue {
struct list *subq[MQ_SIZE];
uint32_t size; /* sum of lengths of all subqueues */
@@ -329,14 +337,16 @@ int route_entry_update_nhe(struct route_entry *re,
struct nhg_hash_entry *new_nhghe);
/* NHG replace has happend, we have to update route_entry pointers to new one */
-void rib_handle_nhg_replace(struct nhg_hash_entry *old_entry,
- struct nhg_hash_entry *new_entry);
+int rib_handle_nhg_replace(struct nhg_hash_entry *old_entry,
+ struct nhg_hash_entry *new_entry);
#define route_entry_dump(prefix, src, re) _route_entry_dump(__func__, prefix, src, re)
extern void _route_entry_dump(const char *func, union prefixconstptr pp,
union prefixconstptr src_pp,
const struct route_entry *re);
+void zebra_rib_route_entry_free(struct route_entry *re);
+
struct route_entry *
zebra_rib_route_entry_new(vrf_id_t vrf_id, int type, uint8_t instance,
uint32_t flags, uint32_t nhe_id, uint32_t table_id,
@@ -406,7 +416,8 @@ extern void rib_update_table(struct route_table *table,
extern void rib_sweep_route(struct event *t);
extern void rib_sweep_table(struct route_table *table);
extern void rib_close_table(struct route_table *table);
-extern void rib_init(void);
+extern void zebra_rib_init(void);
+extern void zebra_rib_terminate(void);
extern unsigned long rib_score_proto(uint8_t proto, unsigned short instance);
extern unsigned long rib_score_proto_table(uint8_t proto,
unsigned short instance,
@@ -421,6 +432,7 @@ extern int rib_queue_nhg_ctx_add(struct nhg_ctx *ctx);
/* Enqueue incoming nhg from proto daemon for processing */
extern int rib_queue_nhe_add(struct nhg_hash_entry *nhe);
+extern int rib_queue_nhe_del(struct nhg_hash_entry *nhe);
/* Enqueue evpn route for processing */
int zebra_rib_queue_evpn_route_add(vrf_id_t vrf_id, const struct ethaddr *rmac,
@@ -465,6 +477,13 @@ extern uint8_t route_distance(int type);
extern void zebra_rib_evaluate_rn_nexthops(struct route_node *rn, uint32_t seq,
bool rt_delete);
+/*
+ * rib_find_rn_from_ctx
+ *
+ * Returns a lock increased route_node for the appropriate
+ * table and prefix specified by the context. Developer
+ * should unlock the node when done.
+ */
extern struct route_node *
rib_find_rn_from_ctx(const struct zebra_dplane_ctx *ctx);
@@ -612,7 +631,7 @@ extern void zebra_vty_init(void);
extern pid_t pid;
-extern bool v6_rr_semantics;
+extern uint32_t rt_table_main_id;
/* Name of hook calls */
#define ZEBRA_ON_RIB_PROCESS_HOOK_CALL "on_rib_process_dplane_results"
diff --git a/zebra/router-id.c b/zebra/router-id.c
index ef87d924fe..2f251a79e5 100644
--- a/zebra/router-id.c
+++ b/zebra/router-id.c
@@ -109,7 +109,7 @@ int router_id_get(afi_t afi, struct prefix *p, struct zebra_vrf *zvrf)
assert(!"Reached end of function we should never hit");
}
-static int router_id_set(afi_t afi, struct prefix *p, struct zebra_vrf *zvrf)
+int router_id_set(afi_t afi, struct prefix *p, struct zebra_vrf *zvrf)
{
struct prefix after, before;
struct listnode *node;
@@ -241,256 +241,6 @@ void router_id_del_address(struct connected *ifc)
zsend_router_id_update(client, afi, &after, zvrf_id(zvrf));
}
-void router_id_write(struct vty *vty, struct zebra_vrf *zvrf)
-{
- char space[2];
-
- memset(space, 0, sizeof(space));
-
- if (zvrf_id(zvrf) != VRF_DEFAULT)
- snprintf(space, sizeof(space), "%s", " ");
-
- if (zvrf->rid_user_assigned.u.prefix4.s_addr != INADDR_ANY) {
- vty_out(vty, "%sip router-id %pI4\n", space,
- &zvrf->rid_user_assigned.u.prefix4);
- }
- if (!router_id_v6_is_any(&zvrf->rid6_user_assigned)) {
- vty_out(vty, "%sipv6 router-id %pI6\n", space,
- &zvrf->rid_user_assigned.u.prefix6);
- }
-}
-
-DEFUN (ip_router_id,
- ip_router_id_cmd,
- "ip router-id A.B.C.D vrf NAME",
- IP_STR
- "Manually set the router-id\n"
- "IP address to use for router-id\n"
- VRF_CMD_HELP_STR)
-{
- int idx = 0;
- struct prefix rid;
- vrf_id_t vrf_id;
- struct zebra_vrf *zvrf;
-
- argv_find(argv, argc, "A.B.C.D", &idx);
-
- if (!inet_pton(AF_INET, argv[idx]->arg, &rid.u.prefix4))
- return CMD_WARNING_CONFIG_FAILED;
-
- rid.prefixlen = IPV4_MAX_BITLEN;
- rid.family = AF_INET;
-
- argv_find(argv, argc, "NAME", &idx);
- VRF_GET_ID(vrf_id, argv[idx]->arg, false);
-
- zvrf = zebra_vrf_lookup_by_id(vrf_id);
- router_id_set(AFI_IP, &rid, zvrf);
-
- return CMD_SUCCESS;
-}
-
-ALIAS (ip_router_id,
- router_id_cmd,
- "router-id A.B.C.D vrf NAME",
- "Manually set the router-id\n"
- "IP address to use for router-id\n"
- VRF_CMD_HELP_STR);
-
-DEFUN (ipv6_router_id,
- ipv6_router_id_cmd,
- "ipv6 router-id X:X::X:X vrf NAME",
- IPV6_STR
- "Manually set the router-id\n"
- "IPv6 address to use for router-id\n"
- VRF_CMD_HELP_STR)
-{
- int idx = 0;
- struct prefix rid;
- vrf_id_t vrf_id;
- struct zebra_vrf *zvrf;
-
- argv_find(argv, argc, "X:X::X:X", &idx);
-
- if (!inet_pton(AF_INET6, argv[idx]->arg, &rid.u.prefix6))
- return CMD_WARNING_CONFIG_FAILED;
-
- rid.prefixlen = IPV6_MAX_BITLEN;
- rid.family = AF_INET6;
-
- argv_find(argv, argc, "NAME", &idx);
- VRF_GET_ID(vrf_id, argv[idx]->arg, false);
-
- zvrf = zebra_vrf_lookup_by_id(vrf_id);
- router_id_set(AFI_IP6, &rid, zvrf);
-
- return CMD_SUCCESS;
-}
-
-
-DEFUN (ip_router_id_in_vrf,
- ip_router_id_in_vrf_cmd,
- "ip router-id A.B.C.D",
- IP_STR
- "Manually set the router-id\n"
- "IP address to use for router-id\n")
-{
- ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
- int idx = 0;
- struct prefix rid;
-
- argv_find(argv, argc, "A.B.C.D", &idx);
-
- if (!inet_pton(AF_INET, argv[idx]->arg, &rid.u.prefix4))
- return CMD_WARNING_CONFIG_FAILED;
-
- rid.prefixlen = IPV4_MAX_BITLEN;
- rid.family = AF_INET;
-
- router_id_set(AFI_IP, &rid, zvrf);
-
- return CMD_SUCCESS;
-}
-
-ALIAS (ip_router_id_in_vrf,
- router_id_in_vrf_cmd,
- "router-id A.B.C.D",
- "Manually set the router-id\n"
- "IP address to use for router-id\n");
-
-DEFUN (ipv6_router_id_in_vrf,
- ipv6_router_id_in_vrf_cmd,
- "ipv6 router-id X:X::X:X",
- IP6_STR
- "Manually set the IPv6 router-id\n"
- "IPV6 address to use for router-id\n")
-{
- ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
- int idx = 0;
- struct prefix rid;
-
- argv_find(argv, argc, "X:X::X:X", &idx);
-
- if (!inet_pton(AF_INET6, argv[idx]->arg, &rid.u.prefix6))
- return CMD_WARNING_CONFIG_FAILED;
-
- rid.prefixlen = IPV6_MAX_BITLEN;
- rid.family = AF_INET6;
-
- router_id_set(AFI_IP6, &rid, zvrf);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_ip_router_id,
- no_ip_router_id_cmd,
- "no ip router-id [A.B.C.D vrf NAME]",
- NO_STR
- IP_STR
- "Remove the manually configured router-id\n"
- "IP address to use for router-id\n"
- VRF_CMD_HELP_STR)
-{
- int idx = 0;
- struct prefix rid;
- vrf_id_t vrf_id = VRF_DEFAULT;
- struct zebra_vrf *zvrf;
-
- rid.u.prefix4.s_addr = 0;
- rid.prefixlen = 0;
- rid.family = AF_INET;
-
- if (argv_find(argv, argc, "NAME", &idx))
- VRF_GET_ID(vrf_id, argv[idx]->arg, false);
-
- zvrf = zebra_vrf_lookup_by_id(vrf_id);
- router_id_set(AFI_IP, &rid, zvrf);
-
- return CMD_SUCCESS;
-}
-
-ALIAS (no_ip_router_id,
- no_router_id_cmd,
- "no router-id [A.B.C.D vrf NAME]",
- NO_STR
- "Remove the manually configured router-id\n"
- "IP address to use for router-id\n"
- VRF_CMD_HELP_STR);
-
-DEFUN (no_ipv6_router_id,
- no_ipv6_router_id_cmd,
- "no ipv6 router-id [X:X::X:X vrf NAME]",
- NO_STR
- IPV6_STR
- "Remove the manually configured IPv6 router-id\n"
- "IPv6 address to use for router-id\n"
- VRF_CMD_HELP_STR)
-{
- int idx = 0;
- struct prefix rid;
- vrf_id_t vrf_id = VRF_DEFAULT;
- struct zebra_vrf *zvrf;
-
- memset(&rid, 0, sizeof(rid));
- rid.family = AF_INET;
-
- if (argv_find(argv, argc, "NAME", &idx))
- VRF_GET_ID(vrf_id, argv[idx]->arg, false);
-
- zvrf = zebra_vrf_lookup_by_id(vrf_id);
- router_id_set(AFI_IP6, &rid, zvrf);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_ip_router_id_in_vrf,
- no_ip_router_id_in_vrf_cmd,
- "no ip router-id [A.B.C.D]",
- NO_STR
- IP_STR
- "Remove the manually configured router-id\n"
- "IP address to use for router-id\n")
-{
- ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
-
- struct prefix rid;
-
- rid.u.prefix4.s_addr = 0;
- rid.prefixlen = 0;
- rid.family = AF_INET;
-
- router_id_set(AFI_IP, &rid, zvrf);
-
- return CMD_SUCCESS;
-}
-
-ALIAS (no_ip_router_id_in_vrf,
- no_router_id_in_vrf_cmd,
- "no router-id [A.B.C.D]",
- NO_STR
- "Remove the manually configured router-id\n"
- "IP address to use for router-id\n");
-
-DEFUN (no_ipv6_router_id_in_vrf,
- no_ipv6_router_id_in_vrf_cmd,
- "no ipv6 router-id [X:X::X:X]",
- NO_STR
- IP6_STR
- "Remove the manually configured IPv6 router-id\n"
- "IPv6 address to use for router-id\n")
-{
- ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
-
- struct prefix rid;
-
- memset(&rid, 0, sizeof(rid));
- rid.family = AF_INET;
-
- router_id_set(AFI_IP6, &rid, zvrf);
-
- return CMD_SUCCESS;
-}
-
DEFUN (show_ip_router_id,
show_ip_router_id_cmd,
"show [ip|ipv6] router-id [vrf NAME]",
@@ -557,24 +307,6 @@ static int router_id_v6_cmp(void *a, void *b)
void router_id_cmd_init(void)
{
- install_element(CONFIG_NODE, &ip_router_id_cmd);
- install_element(CONFIG_NODE, &router_id_cmd);
- install_element(CONFIG_NODE, &ipv6_router_id_cmd);
- install_element(CONFIG_NODE, &no_ip_router_id_cmd);
- install_element(CONFIG_NODE, &no_router_id_cmd);
- install_element(CONFIG_NODE, &ip_router_id_in_vrf_cmd);
- install_element(VRF_NODE, &ip_router_id_in_vrf_cmd);
- install_element(CONFIG_NODE, &router_id_in_vrf_cmd);
- install_element(VRF_NODE, &router_id_in_vrf_cmd);
- install_element(CONFIG_NODE, &ipv6_router_id_in_vrf_cmd);
- install_element(VRF_NODE, &ipv6_router_id_in_vrf_cmd);
- install_element(CONFIG_NODE, &no_ipv6_router_id_cmd);
- install_element(CONFIG_NODE, &no_ip_router_id_in_vrf_cmd);
- install_element(VRF_NODE, &no_ip_router_id_in_vrf_cmd);
- install_element(CONFIG_NODE, &no_router_id_in_vrf_cmd);
- install_element(VRF_NODE, &no_router_id_in_vrf_cmd);
- install_element(CONFIG_NODE, &no_ipv6_router_id_in_vrf_cmd);
- install_element(VRF_NODE, &no_ipv6_router_id_in_vrf_cmd);
install_element(VIEW_NODE, &show_ip_router_id_cmd);
}
diff --git a/zebra/router-id.h b/zebra/router-id.h
index 45860d8b7b..09ad4ec65e 100644
--- a/zebra/router-id.h
+++ b/zebra/router-id.h
@@ -25,8 +25,8 @@ extern void router_id_add_address(struct connected *c);
extern void router_id_del_address(struct connected *c);
extern void router_id_init(struct zebra_vrf *zvrf);
extern void router_id_cmd_init(void);
-extern void router_id_write(struct vty *vty, struct zebra_vrf *zvrf);
extern int router_id_get(afi_t afi, struct prefix *p, struct zebra_vrf *zvrf);
+extern int router_id_set(afi_t afi, struct prefix *p, struct zebra_vrf *zvrf);
#ifdef __cplusplus
}
diff --git a/zebra/rt.h b/zebra/rt.h
index 2e3495a037..e5dc26150a 100644
--- a/zebra/rt.h
+++ b/zebra/rt.h
@@ -25,7 +25,8 @@ extern "C" {
#define RKERNEL_ROUTE(type) ((type) == ZEBRA_ROUTE_KERNEL)
#define RSYSTEM_ROUTE(type) \
- ((RKERNEL_ROUTE(type)) || (type) == ZEBRA_ROUTE_CONNECT)
+ ((RKERNEL_ROUTE(type)) || (type) == ZEBRA_ROUTE_CONNECT || \
+ (type) == ZEBRA_ROUTE_LOCAL)
#ifndef HAVE_NETLINK
/*
@@ -84,6 +85,8 @@ extern int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *mroute);
* state.
*/
extern void interface_list(struct zebra_ns *zns);
+extern void interface_list_tunneldump(struct zebra_ns *zns);
+extern void interface_list_second(struct zebra_ns *zns);
extern void kernel_init(struct zebra_ns *zns);
extern void kernel_terminate(struct zebra_ns *zns, bool complete);
extern void macfdb_read(struct zebra_ns *zns);
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index de01ced411..f092fc5c85 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -66,6 +66,7 @@
#include "zebra/zebra_evpn_mh.h"
#include "zebra/zebra_trace.h"
#include "zebra/zebra_neigh.h"
+#include "lib/srv6.h"
#ifndef AF_MPLS
#define AF_MPLS 28
@@ -77,6 +78,8 @@
#define BR_SPH_LIST_SIZE 10
#endif
+DEFINE_MTYPE_STATIC(LIB, NH_SRV6, "Nexthop srv6");
+
static vlanid_t filter_vlan = 0;
/* We capture whether the current kernel supports nexthop ids; by
@@ -275,6 +278,7 @@ int zebra2proto(int proto)
proto = RTPROT_ZEBRA;
break;
case ZEBRA_ROUTE_CONNECT:
+ case ZEBRA_ROUTE_LOCAL:
case ZEBRA_ROUTE_KERNEL:
proto = RTPROT_KERNEL;
break;
@@ -363,7 +367,8 @@ static inline int proto2zebra(int proto, int family, bool is_nexthop)
proto = ZEBRA_ROUTE_NHG;
break;
}
- /* Intentional fall thru */
+ proto = ZEBRA_ROUTE_KERNEL;
+ break;
default:
/*
* When a user adds a new protocol this will show up
@@ -380,33 +385,6 @@ static inline int proto2zebra(int proto, int family, bool is_nexthop)
return proto;
}
-/*
-Pending: create an efficient table_id (in a tree/hash) based lookup)
- */
-vrf_id_t vrf_lookup_by_table(uint32_t table_id, ns_id_t ns_id)
-{
- struct vrf *vrf;
- struct zebra_vrf *zvrf;
-
- RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
- zvrf = vrf->info;
- if (zvrf == NULL)
- continue;
- /* case vrf with netns : match the netnsid */
- if (vrf_is_backend_netns()) {
- if (ns_id == zvrf_id(zvrf))
- return zvrf_id(zvrf);
- } else {
- /* VRF is VRF_BACKEND_VRF_LITE */
- if (zvrf->table_id != table_id)
- continue;
- return zvrf_id(zvrf);
- }
- }
-
- return VRF_DEFAULT;
-}
-
/**
* @parse_encap_mpls() - Parses encapsulated mpls attributes
* @tb: Pointer to rtattr to look for nested items in.
@@ -434,6 +412,36 @@ static int parse_encap_mpls(struct rtattr *tb, mpls_label_t *labels)
return num_labels;
}
+/**
+ * @parse_encap_seg6local_flavors() - Parses encapsulated SRv6 flavors
+ * attributes
+ * @tb: Pointer to rtattr to look for nested items in.
+ * @flv: Pointer to store SRv6 flavors info in.
+ *
+ * Return: 0 on success, non-zero on error
+ */
+static int parse_encap_seg6local_flavors(struct rtattr *tb,
+ struct seg6local_flavors_info *flv)
+{
+ struct rtattr *tb_encap[SEG6_LOCAL_FLV_MAX + 1] = {};
+
+ netlink_parse_rtattr_nested(tb_encap, SEG6_LOCAL_FLV_MAX, tb);
+
+ if (tb_encap[SEG6_LOCAL_FLV_OPERATION])
+ flv->flv_ops = *(uint32_t *)RTA_DATA(
+ tb_encap[SEG6_LOCAL_FLV_OPERATION]);
+
+ if (tb_encap[SEG6_LOCAL_FLV_LCBLOCK_BITS])
+ flv->lcblock_len = *(uint8_t *)RTA_DATA(
+ tb_encap[SEG6_LOCAL_FLV_LCBLOCK_BITS]);
+
+ if (tb_encap[SEG6_LOCAL_FLV_LCNODE_FN_BITS])
+ flv->lcnode_func_len = *(uint8_t *)RTA_DATA(
+ tb_encap[SEG6_LOCAL_FLV_LCNODE_FN_BITS]);
+
+ return 0;
+}
+
static enum seg6local_action_t
parse_encap_seg6local(struct rtattr *tb,
struct seg6local_context *ctx)
@@ -461,6 +469,11 @@ parse_encap_seg6local(struct rtattr *tb,
ctx->table =
*(uint32_t *)RTA_DATA(tb_encap[SEG6_LOCAL_VRFTABLE]);
+ if (tb_encap[SEG6_LOCAL_FLAVORS]) {
+ parse_encap_seg6local_flavors(tb_encap[SEG6_LOCAL_FLAVORS],
+ &ctx->flv);
+ }
+
return act;
}
@@ -468,19 +481,19 @@ static int parse_encap_seg6(struct rtattr *tb, struct in6_addr *segs)
{
struct rtattr *tb_encap[SEG6_IPTUNNEL_MAX + 1] = {};
struct seg6_iptunnel_encap *ipt = NULL;
- struct in6_addr *segments = NULL;
+ int i;
netlink_parse_rtattr_nested(tb_encap, SEG6_IPTUNNEL_MAX, tb);
- /*
- * TODO: It's not support multiple SID list.
- */
if (tb_encap[SEG6_IPTUNNEL_SRH]) {
ipt = (struct seg6_iptunnel_encap *)
RTA_DATA(tb_encap[SEG6_IPTUNNEL_SRH]);
- segments = ipt->srh[0].segments;
- *segs = segments[0];
- return 1;
+
+ for (i = ipt->srh[0].first_segment; i >= 0; i--)
+ memcpy(&segs[i], &ipt->srh[0].segments[i],
+ sizeof(struct in6_addr));
+
+ return ipt->srh[0].first_segment + 1;
}
return 0;
@@ -498,7 +511,7 @@ parse_nexthop_unicast(ns_id_t ns_id, struct rtmsg *rtm, struct rtattr **tb,
int num_labels = 0;
enum seg6local_action_t seg6l_act = ZEBRA_SEG6_LOCAL_ACTION_UNSPEC;
struct seg6local_context seg6l_ctx = {};
- struct in6_addr seg6_segs = {};
+ struct in6_addr segs[SRV6_MAX_SIDS] = {};
int num_segs = 0;
vrf_id_t nh_vrf_id = vrf_id;
@@ -547,7 +560,7 @@ parse_nexthop_unicast(ns_id_t ns_id, struct rtmsg *rtm, struct rtattr **tb,
if (tb[RTA_ENCAP] && tb[RTA_ENCAP_TYPE]
&& *(uint16_t *)RTA_DATA(tb[RTA_ENCAP_TYPE])
== LWTUNNEL_ENCAP_SEG6) {
- num_segs = parse_encap_seg6(tb[RTA_ENCAP], &seg6_segs);
+ num_segs = parse_encap_seg6(tb[RTA_ENCAP], segs);
}
if (rtm->rtm_flags & RTNH_F_ONLINK)
@@ -559,11 +572,21 @@ parse_nexthop_unicast(ns_id_t ns_id, struct rtmsg *rtm, struct rtattr **tb,
if (num_labels)
nexthop_add_labels(&nh, ZEBRA_LSP_STATIC, num_labels, labels);
+ /* Resolve default values for SRv6 flavors */
+ if (seg6l_ctx.flv.flv_ops != ZEBRA_SEG6_LOCAL_FLV_OP_UNSPEC) {
+ if (seg6l_ctx.flv.lcblock_len == 0)
+ seg6l_ctx.flv.lcblock_len =
+ ZEBRA_DEFAULT_SEG6_LOCAL_FLV_LCBLOCK_LEN;
+ if (seg6l_ctx.flv.lcnode_func_len == 0)
+ seg6l_ctx.flv.lcnode_func_len =
+ ZEBRA_DEFAULT_SEG6_LOCAL_FLV_LCNODE_FN_LEN;
+ }
+
if (seg6l_act != ZEBRA_SEG6_LOCAL_ACTION_UNSPEC)
nexthop_add_srv6_seg6local(&nh, seg6l_act, &seg6l_ctx);
if (num_segs)
- nexthop_add_srv6_seg6(&nh, &seg6_segs);
+ nexthop_add_srv6_seg6(&nh, segs, num_segs);
return nh;
}
@@ -583,7 +606,7 @@ static uint8_t parse_multipath_nexthops_unicast(ns_id_t ns_id,
int num_labels = 0;
enum seg6local_action_t seg6l_act = ZEBRA_SEG6_LOCAL_ACTION_UNSPEC;
struct seg6local_context seg6l_ctx = {};
- struct in6_addr seg6_segs = {};
+ struct in6_addr segs[SRV6_MAX_SIDS] = {};
int num_segs = 0;
struct rtattr *rtnh_tb[RTA_MAX + 1] = {};
@@ -639,7 +662,7 @@ static uint8_t parse_multipath_nexthops_unicast(ns_id_t ns_id,
&& *(uint16_t *)RTA_DATA(rtnh_tb[RTA_ENCAP_TYPE])
== LWTUNNEL_ENCAP_SEG6) {
num_segs = parse_encap_seg6(rtnh_tb[RTA_ENCAP],
- &seg6_segs);
+ segs);
}
}
@@ -666,12 +689,23 @@ static uint8_t parse_multipath_nexthops_unicast(ns_id_t ns_id,
nexthop_add_labels(nh, ZEBRA_LSP_STATIC,
num_labels, labels);
+ /* Resolve default values for SRv6 flavors */
+ if (seg6l_ctx.flv.flv_ops !=
+ ZEBRA_SEG6_LOCAL_FLV_OP_UNSPEC) {
+ if (seg6l_ctx.flv.lcblock_len == 0)
+ seg6l_ctx.flv.lcblock_len =
+ ZEBRA_DEFAULT_SEG6_LOCAL_FLV_LCBLOCK_LEN;
+ if (seg6l_ctx.flv.lcnode_func_len == 0)
+ seg6l_ctx.flv.lcnode_func_len =
+ ZEBRA_DEFAULT_SEG6_LOCAL_FLV_LCNODE_FN_LEN;
+ }
+
if (seg6l_act != ZEBRA_SEG6_LOCAL_ACTION_UNSPEC)
nexthop_add_srv6_seg6local(nh, seg6l_act,
&seg6l_ctx);
if (num_segs)
- nexthop_add_srv6_seg6(nh, &seg6_segs);
+ nexthop_add_srv6_seg6(nh, segs, num_segs);
if (rtnh->rtnh_flags & RTNH_F_ONLINK)
SET_FLAG(nh->flags, NEXTHOP_FLAG_ONLINK);
@@ -790,7 +824,7 @@ int netlink_route_change_read_unicast_internal(struct nlmsghdr *h,
table = rtm->rtm_table;
/* Map to VRF */
- vrf_id = vrf_lookup_by_table(table, ns_id);
+ vrf_id = zebra_vrf_lookup_by_table(table, ns_id);
if (vrf_id == VRF_DEFAULT) {
if (!is_zebra_valid_kernel_table(table)
&& !is_zebra_main_routing_table(table))
@@ -993,6 +1027,8 @@ int netlink_route_change_read_unicast_internal(struct nlmsghdr *h,
re, ng, startup, ctx);
if (ng)
nexthop_group_delete(&ng);
+ if (ctx)
+ zebra_rib_route_entry_free(re);
} else {
/*
* I really don't see how this is possible
@@ -1079,7 +1115,7 @@ static int netlink_route_change_read_multicast(struct nlmsghdr *h,
else
table = rtm->rtm_table;
- vrf = vrf_lookup_by_table(table, ns_id);
+ vrf = zebra_vrf_lookup_by_table(table, ns_id);
if (tb[RTA_IIF])
iif = *(int *)RTA_DATA(tb[RTA_IIF]);
@@ -1485,37 +1521,80 @@ static bool _netlink_route_encode_nexthop_src(const struct nexthop *nexthop,
}
static ssize_t fill_seg6ipt_encap(char *buffer, size_t buflen,
- const struct in6_addr *seg)
+ struct seg6_seg_stack *segs)
{
struct seg6_iptunnel_encap *ipt;
struct ipv6_sr_hdr *srh;
- const size_t srhlen = 24;
+ size_t srhlen;
+ int i;
- /*
- * Caution: Support only SINGLE-SID, not MULTI-SID
- * This function only supports the case where segs represents
- * a single SID. If you want to extend the SRv6 functionality,
- * you should improve the Boundary Check.
- * Ex. In case of set a SID-List include multiple-SIDs as an
- * argument of the Transit Behavior, we must support variable
- * boundary check for buflen.
- */
- if (buflen < (sizeof(struct seg6_iptunnel_encap) +
- sizeof(struct ipv6_sr_hdr) + 16))
+ if (segs->num_segs > SRV6_MAX_SEGS) {
+ /* Exceeding maximum supported SIDs */
+ return -1;
+ }
+
+ srhlen = SRH_BASE_HEADER_LENGTH + SRH_SEGMENT_LENGTH * segs->num_segs;
+
+ if (buflen < (sizeof(struct seg6_iptunnel_encap) + srhlen))
return -1;
memset(buffer, 0, buflen);
ipt = (struct seg6_iptunnel_encap *)buffer;
ipt->mode = SEG6_IPTUN_MODE_ENCAP;
- srh = ipt->srh;
+
+ srh = (struct ipv6_sr_hdr *)&ipt->srh;
srh->hdrlen = (srhlen >> 3) - 1;
srh->type = 4;
- srh->segments_left = 0;
- srh->first_segment = 0;
- memcpy(&srh->segments[0], seg, sizeof(struct in6_addr));
+ srh->segments_left = segs->num_segs - 1;
+ srh->first_segment = segs->num_segs - 1;
+
+ for (i = 0; i < segs->num_segs; i++) {
+ memcpy(&srh->segments[i], &segs->seg[i],
+ sizeof(struct in6_addr));
+ }
+
+ return sizeof(struct seg6_iptunnel_encap) + srhlen;
+}
+
+static bool
+_netlink_nexthop_encode_seg6local_flavor(const struct nexthop *nexthop,
+ struct nlmsghdr *nlmsg, size_t buflen)
+{
+ struct rtattr *nest;
+ struct seg6local_flavors_info *flv;
+
+ assert(nexthop);
+
+ if (!nexthop->nh_srv6)
+ return false;
+
+ flv = &nexthop->nh_srv6->seg6local_ctx.flv;
+
+ if (flv->flv_ops == ZEBRA_SEG6_LOCAL_FLV_OP_UNSPEC)
+ return true;
+
+ nest = nl_attr_nest(nlmsg, buflen, SEG6_LOCAL_FLAVORS);
+ if (!nest)
+ return false;
+
+ if (!nl_attr_put32(nlmsg, buflen, SEG6_LOCAL_FLV_OPERATION,
+ flv->flv_ops))
+ return false;
- return srhlen + 4;
+ if (flv->lcblock_len)
+ if (!nl_attr_put8(nlmsg, buflen, SEG6_LOCAL_FLV_LCBLOCK_BITS,
+ flv->lcblock_len))
+ return false;
+
+ if (flv->lcnode_func_len)
+ if (!nl_attr_put8(nlmsg, buflen, SEG6_LOCAL_FLV_LCNODE_FN_BITS,
+ flv->lcnode_func_len))
+ return false;
+
+ nl_attr_nest_end(nlmsg, nest);
+
+ return true;
}
/* This function takes a nexthop as argument and adds
@@ -1649,10 +1728,17 @@ static bool _netlink_route_build_singlepath(const struct prefix *p,
nexthop->nh_srv6->seg6local_action);
return false;
}
+
+ if (!_netlink_nexthop_encode_seg6local_flavor(
+ nexthop, nlmsg, req_size))
+ return false;
+
nl_attr_nest_end(nlmsg, nest);
}
- if (!sid_zero(&nexthop->nh_srv6->seg6_segs)) {
+ if (nexthop->nh_srv6->seg6_segs &&
+ nexthop->nh_srv6->seg6_segs->num_segs &&
+ !sid_zero(nexthop->nh_srv6->seg6_segs)) {
char tun_buf[4096];
ssize_t tun_len;
struct rtattr *nest;
@@ -1663,8 +1749,9 @@ static bool _netlink_route_build_singlepath(const struct prefix *p,
nest = nl_attr_nest(nlmsg, req_size, RTA_ENCAP);
if (!nest)
return false;
- tun_len = fill_seg6ipt_encap(tun_buf, sizeof(tun_buf),
- &nexthop->nh_srv6->seg6_segs);
+ tun_len =
+ fill_seg6ipt_encap(tun_buf, sizeof(tun_buf),
+ nexthop->nh_srv6->seg6_segs);
if (tun_len < 0)
return false;
if (!nl_attr_put(nlmsg, req_size, SEG6_IPTUNNEL_SRH,
@@ -2087,10 +2174,10 @@ static int netlink_route_nexthop_encap(struct nlmsghdr *n, size_t nlen,
* Returns -1 on failure, 0 when the msg doesn't fit entirely in the buffer
* otherwise the number of bytes written to buf.
*/
-ssize_t netlink_route_multipath_msg_encode(int cmd,
- struct zebra_dplane_ctx *ctx,
+ssize_t netlink_route_multipath_msg_encode(int cmd, struct zebra_dplane_ctx *ctx,
uint8_t *data, size_t datalen,
- bool fpm, bool force_nhg)
+ bool fpm, bool force_nhg,
+ bool force_rr)
{
int bytelen;
struct nexthop *nexthop = NULL;
@@ -2124,8 +2211,10 @@ ssize_t netlink_route_multipath_msg_encode(int cmd,
req->n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
req->n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
- if ((cmd == RTM_NEWROUTE) &&
- ((p->family == AF_INET) || v6_rr_semantics))
+ if (((cmd == RTM_NEWROUTE) &&
+ ((p->family == AF_INET) || kernel_nexthops_supported() ||
+ zrouter.v6_rr_semantics)) ||
+ force_rr)
req->n.nlmsg_flags |= NLM_F_REPLACE;
req->n.nlmsg_type = cmd;
@@ -2328,19 +2417,21 @@ ssize_t netlink_route_multipath_msg_encode(int cmd,
p, routedesc, bytelen, nexthop,
&req->n, &req->r, datalen, cmd))
return 0;
+
+ /*
+ * Add encapsulation information when
+ * installing via FPM.
+ */
+ if (fpm) {
+ if (!netlink_route_nexthop_encap(&req->n,
+ datalen,
+ nexthop))
+ return 0;
+ }
+
nexthop_num++;
break;
}
-
- /*
- * Add encapsulation information when installing via
- * FPM.
- */
- if (fpm) {
- if (!netlink_route_nexthop_encap(
- &req->n, datalen, nexthop))
- return 0;
- }
}
if (setsrc) {
@@ -2387,6 +2478,16 @@ ssize_t netlink_route_multipath_msg_encode(int cmd,
tag))
return 0;
+ /*
+ * Add encapsulation information when installing via
+ * FPM.
+ */
+ if (fpm) {
+ if (!netlink_route_nexthop_encap(
+ &req->n, datalen, nexthop))
+ return 0;
+ }
+
if (!setsrc && src1) {
if (p->family == AF_INET)
src.ipv4 = src1->ipv4;
@@ -2400,23 +2501,6 @@ ssize_t netlink_route_multipath_msg_encode(int cmd,
nl_attr_nest_end(&req->n, nest);
- /*
- * Add encapsulation information when installing via
- * FPM.
- */
- if (fpm) {
- for (ALL_NEXTHOPS_PTR(dplane_ctx_get_ng(ctx),
- nexthop)) {
- if (CHECK_FLAG(nexthop->flags,
- NEXTHOP_FLAG_RECURSIVE))
- continue;
- if (!netlink_route_nexthop_encap(
- &req->n, datalen, nexthop))
- return 0;
- }
- }
-
-
if (setsrc) {
if (p->family == AF_INET) {
if (!nl_attr_put(&req->n, datalen, RTA_PREFSRC,
@@ -2503,7 +2587,7 @@ int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *in)
* are trying to give me. So now we have this little hack.
*/
if (mroute->family == AF_INET)
- actual_table = (zvrf->table_id == RT_TABLE_MAIN)
+ actual_table = (zvrf->table_id == rt_table_main_id)
? RT_TABLE_DEFAULT
: zvrf->table_id;
else
@@ -2543,7 +2627,7 @@ static bool _netlink_nexthop_build_group(struct nlmsghdr *n, size_t req_size,
if (IS_ZEBRA_DEBUG_KERNEL) {
if (i == 0)
- snprintf(buf, sizeof(buf1), "group %u",
+ snprintf(buf, sizeof(buf), "group %u",
grp[i].id);
else {
snprintf(buf1, sizeof(buf1), "/%u",
@@ -2888,10 +2972,17 @@ ssize_t netlink_nexthop_msg_encode(uint16_t cmd,
__func__, action);
return 0;
}
+
+ if (!_netlink_nexthop_encode_seg6local_flavor(
+ nh, &req->n, buflen))
+ return false;
+
nl_attr_nest_end(&req->n, nest);
}
- if (!sid_zero(&nh->nh_srv6->seg6_segs)) {
+ if (nh->nh_srv6->seg6_segs &&
+ nh->nh_srv6->seg6_segs->num_segs &&
+ !sid_zero(nh->nh_srv6->seg6_segs)) {
char tun_buf[4096];
ssize_t tun_len;
struct rtattr *nest;
@@ -2904,9 +2995,9 @@ ssize_t netlink_nexthop_msg_encode(uint16_t cmd,
NHA_ENCAP | NLA_F_NESTED);
if (!nest)
return 0;
- tun_len = fill_seg6ipt_encap(tun_buf,
- sizeof(tun_buf),
- &nh->nh_srv6->seg6_segs);
+ tun_len = fill_seg6ipt_encap(
+ tun_buf, sizeof(tun_buf),
+ nh->nh_srv6->seg6_segs);
if (tun_len < 0)
return 0;
if (!nl_attr_put(&req->n, buflen,
@@ -2980,14 +3071,14 @@ static ssize_t netlink_newroute_msg_encoder(struct zebra_dplane_ctx *ctx,
void *buf, size_t buflen)
{
return netlink_route_multipath_msg_encode(RTM_NEWROUTE, ctx, buf,
- buflen, false, false);
+ buflen, false, false, false);
}
static ssize_t netlink_delroute_msg_encoder(struct zebra_dplane_ctx *ctx,
void *buf, size_t buflen)
{
return netlink_route_multipath_msg_encode(RTM_DELROUTE, ctx, buf,
- buflen, false, false);
+ buflen, false, false, false);
}
enum netlink_msg_status
@@ -3001,8 +3092,8 @@ netlink_put_route_update_msg(struct nl_batch *bth, struct zebra_dplane_ctx *ctx)
} else if (dplane_ctx_get_op(ctx) == DPLANE_OP_ROUTE_INSTALL) {
cmd = RTM_NEWROUTE;
} else if (dplane_ctx_get_op(ctx) == DPLANE_OP_ROUTE_UPDATE) {
-
- if (p->family == AF_INET || v6_rr_semantics) {
+ if (p->family == AF_INET || kernel_nexthops_supported() ||
+ zrouter.v6_rr_semantics) {
/* Single 'replace' operation */
/*
@@ -4151,11 +4242,11 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
* - struct ethaddr mac; (for NEW)
*/
if (h->nlmsg_type == RTM_NEWNEIGH)
- cmd = ZEBRA_NHRP_NEIGH_ADDED;
+ cmd = ZEBRA_NEIGH_ADDED;
else if (h->nlmsg_type == RTM_GETNEIGH)
- cmd = ZEBRA_NHRP_NEIGH_GET;
+ cmd = ZEBRA_NEIGH_GET;
else if (h->nlmsg_type == RTM_DELNEIGH)
- cmd = ZEBRA_NHRP_NEIGH_REMOVED;
+ cmd = ZEBRA_NEIGH_REMOVED;
else {
zlog_debug("%s(): unknown nlmsg type %u", __func__,
h->nlmsg_type);
@@ -4165,20 +4256,18 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
/* copy LLADDR information */
l2_len = RTA_PAYLOAD(tb[NDA_LLADDR]);
}
- if (l2_len == IPV4_MAX_BYTELEN || l2_len == 0) {
- union sockunion link_layer_ipv4;
- if (l2_len) {
- sockunion_family(&link_layer_ipv4) = AF_INET;
- memcpy((void *)sockunion_get_addr(&link_layer_ipv4),
- RTA_DATA(tb[NDA_LLADDR]), l2_len);
- } else
- sockunion_family(&link_layer_ipv4) = AF_UNSPEC;
- zsend_nhrp_neighbor_notify(
- cmd, ifp, &ip,
- netlink_nbr_entry_state_to_zclient(ndm->ndm_state),
- &link_layer_ipv4);
- }
+ union sockunion link_layer_ipv4;
+
+ if (l2_len) {
+ sockunion_family(&link_layer_ipv4) = AF_INET;
+ memcpy((void *)sockunion_get_addr(&link_layer_ipv4),
+ RTA_DATA(tb[NDA_LLADDR]), l2_len);
+ } else
+ sockunion_family(&link_layer_ipv4) = AF_UNSPEC;
+ zsend_neighbor_notify(cmd, ifp, &ip,
+ netlink_nbr_entry_state_to_zclient(ndm->ndm_state),
+ &link_layer_ipv4, l2_len);
if (h->nlmsg_type == RTM_GETNEIGH)
return 0;
@@ -4631,76 +4720,24 @@ static ssize_t netlink_neigh_msg_encoder(struct zebra_dplane_ctx *ctx,
void *buf, size_t buflen)
{
ssize_t ret = 0;
+ enum dplane_op_e op;
- switch (dplane_ctx_get_op(ctx)) {
- case DPLANE_OP_NEIGH_INSTALL:
- case DPLANE_OP_NEIGH_UPDATE:
- case DPLANE_OP_NEIGH_DISCOVER:
- case DPLANE_OP_NEIGH_IP_INSTALL:
+ op = dplane_ctx_get_op(ctx);
+ if (op == DPLANE_OP_NEIGH_INSTALL || op == DPLANE_OP_NEIGH_UPDATE ||
+ op == DPLANE_OP_NEIGH_DISCOVER || op == DPLANE_OP_NEIGH_IP_INSTALL)
ret = netlink_neigh_update_ctx(ctx, RTM_NEWNEIGH, buf, buflen);
- break;
- case DPLANE_OP_NEIGH_DELETE:
- case DPLANE_OP_NEIGH_IP_DELETE:
+ else if (op == DPLANE_OP_NEIGH_DELETE || op == DPLANE_OP_NEIGH_IP_DELETE)
ret = netlink_neigh_update_ctx(ctx, RTM_DELNEIGH, buf, buflen);
- break;
- case DPLANE_OP_VTEP_ADD:
+ else if (op == DPLANE_OP_VTEP_ADD)
ret = netlink_vxlan_flood_update_ctx(ctx, RTM_NEWNEIGH, buf,
buflen);
- break;
- case DPLANE_OP_VTEP_DELETE:
+ else if (op == DPLANE_OP_VTEP_DELETE)
ret = netlink_vxlan_flood_update_ctx(ctx, RTM_DELNEIGH, buf,
buflen);
- break;
- case DPLANE_OP_NEIGH_TABLE_UPDATE:
+ else if (op == DPLANE_OP_NEIGH_TABLE_UPDATE)
ret = netlink_neigh_table_update_ctx(ctx, buf, buflen);
- break;
- 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:
- case DPLANE_OP_LSP_INSTALL:
- case DPLANE_OP_LSP_UPDATE:
- case DPLANE_OP_LSP_DELETE:
- case DPLANE_OP_LSP_NOTIFY:
- case DPLANE_OP_PW_INSTALL:
- case DPLANE_OP_PW_UNINSTALL:
- case DPLANE_OP_SYS_ROUTE_ADD:
- case DPLANE_OP_SYS_ROUTE_DELETE:
- case DPLANE_OP_ADDR_INSTALL:
- case DPLANE_OP_ADDR_UNINSTALL:
- case DPLANE_OP_MAC_INSTALL:
- case DPLANE_OP_MAC_DELETE:
- case DPLANE_OP_RULE_ADD:
- case DPLANE_OP_RULE_DELETE:
- case DPLANE_OP_RULE_UPDATE:
- case DPLANE_OP_BR_PORT_UPDATE:
- case DPLANE_OP_IPTABLE_ADD:
- case DPLANE_OP_IPTABLE_DELETE:
- case DPLANE_OP_IPSET_ADD:
- case DPLANE_OP_IPSET_DELETE:
- case DPLANE_OP_IPSET_ENTRY_ADD:
- case DPLANE_OP_IPSET_ENTRY_DELETE:
- case DPLANE_OP_GRE_SET:
- case DPLANE_OP_INTF_ADDR_ADD:
- case DPLANE_OP_INTF_ADDR_DEL:
- case DPLANE_OP_INTF_NETCONFIG:
- case DPLANE_OP_INTF_INSTALL:
- case DPLANE_OP_INTF_UPDATE:
- case DPLANE_OP_INTF_DELETE:
- case DPLANE_OP_TC_QDISC_INSTALL:
- case DPLANE_OP_TC_QDISC_UNINSTALL:
- case DPLANE_OP_TC_CLASS_ADD:
- case DPLANE_OP_TC_CLASS_DELETE:
- case DPLANE_OP_TC_CLASS_UPDATE:
- case DPLANE_OP_TC_FILTER_ADD:
- case DPLANE_OP_TC_FILTER_DELETE:
- case DPLANE_OP_TC_FILTER_UPDATE:
- case DPLANE_OP_NONE:
+ else
ret = -1;
- }
return ret;
}
@@ -4785,7 +4822,7 @@ ssize_t netlink_mpls_multipath_msg_encode(int cmd, struct zebra_dplane_ctx *ctx,
req->n.nlmsg_pid = nl->snl.nl_pid;
req->r.rtm_family = AF_MPLS;
- req->r.rtm_table = RT_TABLE_MAIN;
+ req->r.rtm_table = rt_table_main_id;
req->r.rtm_dst_len = MPLS_LABEL_LEN_BITS;
req->r.rtm_scope = RT_SCOPE_UNIVERSE;
req->r.rtm_type = RTN_UNICAST;
diff --git a/zebra/rt_netlink.h b/zebra/rt_netlink.h
index 3ca59ce676..d51944f1a4 100644
--- a/zebra/rt_netlink.h
+++ b/zebra/rt_netlink.h
@@ -56,7 +56,8 @@ extern ssize_t netlink_mpls_multipath_msg_encode(int cmd,
extern ssize_t netlink_route_multipath_msg_encode(int cmd,
struct zebra_dplane_ctx *ctx,
uint8_t *data, size_t datalen,
- bool fpm, bool force_nhg);
+ bool fpm, bool force_nhg,
+ bool force_rr);
extern ssize_t netlink_macfdb_update_ctx(struct zebra_dplane_ctx *ctx,
void *data, size_t datalen);
@@ -90,7 +91,6 @@ extern int netlink_macfdb_read_specific_mac(struct zebra_ns *zns,
uint16_t vid);
extern int netlink_neigh_read_specific_ip(const struct ipaddr *ip,
struct interface *vlan_if);
-extern vrf_id_t vrf_lookup_by_table(uint32_t table_id, ns_id_t ns_id);
struct nl_batch;
extern enum netlink_msg_status
diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c
index f9888b12d4..0bfcd518ca 100644
--- a/zebra/rt_socket.c
+++ b/zebra/rt_socket.c
@@ -6,6 +6,8 @@
#include <zebra.h>
+#include <net/route.h>
+
#ifndef HAVE_NETLINK
#ifdef __OpenBSD__
diff --git a/zebra/rtadv.c b/zebra/rtadv.c
index 9af41cbc39..470391de9b 100644
--- a/zebra/rtadv.c
+++ b/zebra/rtadv.c
@@ -6,6 +6,7 @@
*/
#include <zebra.h>
+#include <netinet/icmp6.h>
#include "memory.h"
#include "sockopt.h"
@@ -33,6 +34,7 @@
extern struct zebra_privs_t zserv_privs;
static uint32_t interfaces_configured_for_ra_from_bgp;
+#define RTADV_ADATA_SIZE 1024
#if defined(HAVE_RTADV)
@@ -58,7 +60,7 @@ DEFINE_MTYPE_STATIC(ZEBRA, ADV_IF, "Advertised Interface");
/* adv list node */
struct adv_if {
- char name[INTERFACE_NAMSIZ];
+ char name[IFNAMSIZ];
struct adv_if_list_item list_item;
};
@@ -182,13 +184,14 @@ static int rtadv_recv_packet(struct zebra_vrf *zvrf, int sock, uint8_t *buf,
static void rtadv_send_packet(int sock, struct interface *ifp,
enum ipv6_nd_suppress_ra_status stop)
{
- struct msghdr msg;
- struct iovec iov;
+ struct msghdr msg = { 0 };
+ struct iovec iov = { 0 };
struct cmsghdr *cmsgptr;
struct in6_pktinfo *pkt;
- struct sockaddr_in6 addr;
- static void *adata = NULL;
- unsigned char buf[RTADV_MSG_SIZE];
+ struct sockaddr_in6 addr = { 0 };
+ unsigned char buf[RTADV_MSG_SIZE] = { 0 };
+ char adata[RTADV_ADATA_SIZE] = { 0 };
+
struct nd_router_advert *rtadv;
int ret;
int len = 0;
@@ -199,22 +202,6 @@ static void rtadv_send_packet(int sock, struct interface *ifp,
struct listnode *node;
uint16_t pkt_RouterLifetime;
- /*
- * Allocate control message bufffer. This is dynamic because
- * CMSG_SPACE is not guaranteed not to call a function. Note that
- * the size will be different on different architectures due to
- * differing alignment rules.
- */
- if (adata == NULL) {
- /* XXX Free on shutdown. */
- adata = calloc(1, CMSG_SPACE(sizeof(struct in6_pktinfo)));
-
- if (adata == NULL) {
- zlog_debug("%s: can't malloc control data", __func__);
- exit(-1);
- }
- }
-
/* Logging of packet. */
if (IS_ZEBRA_DEBUG_PACKET)
zlog_debug("%s(%s:%u): Tx RA, socket %u", ifp->name,
@@ -1147,7 +1134,8 @@ static void rtadv_prefix_set_defaults(struct rtadv_prefix *rp)
rp->AdvValidLifetime = RTADV_VALID_LIFETIME;
}
-static void rtadv_prefix_set(struct zebra_if *zif, struct rtadv_prefix *rp)
+static struct rtadv_prefix *rtadv_prefix_set(struct zebra_if *zif,
+ struct rtadv_prefix *rp)
{
struct rtadv_prefix *rprefix;
@@ -1180,13 +1168,16 @@ static void rtadv_prefix_set(struct zebra_if *zif, struct rtadv_prefix *rp)
rtadv_prefix_set_defaults(rprefix);
}
}
+
+ return rprefix;
}
-static int rtadv_prefix_reset(struct zebra_if *zif, struct rtadv_prefix *rp)
+static void rtadv_prefix_reset(struct zebra_if *zif, struct rtadv_prefix *rp,
+ struct rtadv_prefix *rprefix)
{
- struct rtadv_prefix *rprefix;
+ if (!rprefix)
+ rprefix = rtadv_prefixes_find(zif->rtadv.prefixes, rp);
- rprefix = rtadv_prefixes_find(zif->rtadv.prefixes, rp);
if (rprefix != NULL) {
/*
@@ -1200,20 +1191,35 @@ static int rtadv_prefix_reset(struct zebra_if *zif, struct rtadv_prefix *rp)
if (rprefix->AdvPrefixCreate == PREFIX_SRC_BOTH) {
rprefix->AdvPrefixCreate = PREFIX_SRC_AUTO;
rtadv_prefix_set_defaults(rprefix);
- return 1;
+ return;
}
} else if (rp->AdvPrefixCreate == PREFIX_SRC_AUTO) {
if (rprefix->AdvPrefixCreate == PREFIX_SRC_BOTH) {
rprefix->AdvPrefixCreate = PREFIX_SRC_MANUAL;
- return 1;
+ return;
}
}
rtadv_prefixes_del(zif->rtadv.prefixes, rprefix);
rtadv_prefix_free(rprefix);
- return 1;
- } else
- return 0;
+ }
+}
+
+struct rtadv_prefix *rtadv_add_prefix_manual(struct zebra_if *zif,
+ struct rtadv_prefix *rp)
+{
+ rp->AdvPrefixCreate = PREFIX_SRC_MANUAL;
+ return rtadv_prefix_set(zif, rp);
+}
+
+void rtadv_delete_prefix_manual(struct zebra_if *zif,
+ struct rtadv_prefix *rprefix)
+{
+ struct rtadv_prefix rp;
+
+ rp.AdvPrefixCreate = PREFIX_SRC_MANUAL;
+
+ rtadv_prefix_reset(zif, &rp, rprefix);
}
/* Add IPv6 prefixes learned from the kernel to the RA prefix list */
@@ -1235,7 +1241,7 @@ void rtadv_delete_prefix(struct zebra_if *zif, const struct prefix *p)
rp.prefix = *((struct prefix_ipv6 *)p);
apply_mask_ipv6(&rp.prefix);
rp.AdvPrefixCreate = PREFIX_SRC_AUTO;
- rtadv_prefix_reset(zif, &rp);
+ rtadv_prefix_reset(zif, &rp, NULL);
}
static void rtadv_start_interface_events(struct zebra_vrf *zvrf,
@@ -1261,8 +1267,8 @@ static void rtadv_start_interface_events(struct zebra_vrf *zvrf,
rtadv_event(zvrf, RTADV_START, 0);
}
-static void ipv6_nd_suppress_ra_set(struct interface *ifp,
- enum ipv6_nd_suppress_ra_status status)
+void ipv6_nd_suppress_ra_set(struct interface *ifp,
+ enum ipv6_nd_suppress_ra_status status)
{
struct zebra_if *zif;
struct zebra_vrf *zvrf;
@@ -1310,6 +1316,36 @@ static void ipv6_nd_suppress_ra_set(struct interface *ifp,
}
}
+void ipv6_nd_interval_set(struct interface *ifp, uint32_t interval)
+{
+ struct zebra_if *zif = ifp->info;
+ struct zebra_vrf *zvrf = rtadv_interface_get_zvrf(ifp);
+ struct adv_if *adv_if;
+
+ if (zif->rtadv.MaxRtrAdvInterval % 1000) {
+ adv_if = adv_msec_if_del(zvrf, ifp->name);
+ if (adv_if != NULL)
+ adv_if_free(adv_if);
+ }
+
+ if (interval % 1000)
+ (void)adv_msec_if_add(zvrf, ifp->name);
+
+ zif->rtadv.MaxRtrAdvInterval = interval;
+ zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
+
+ if (interval != RTADV_MAX_RTR_ADV_INTERVAL) {
+ SET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
+ zif->rtadv.AdvIntervalTimer = 0;
+ } else {
+ if (CHECK_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED))
+ zif->rtadv.MaxRtrAdvInterval = 10000;
+
+ UNSET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
+ zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
+ }
+}
+
/*
* Handle client (BGP) message to enable or disable IPv6 RA on an interface.
* Note that while the client could request RA on an interface on which the
@@ -1427,7 +1463,7 @@ void rtadv_stop_ra_all(void)
frr_each_safe (rtadv_prefixes, zif->rtadv.prefixes,
rprefix)
- rtadv_prefix_reset(zif, rprefix);
+ rtadv_prefix_reset(zif, rprefix, rprefix);
rtadv_stop_ra(ifp);
}
@@ -1512,777 +1548,6 @@ DEFPY(show_ipv6_nd_ra_if, show_ipv6_nd_ra_if_cmd,
return CMD_SUCCESS;
}
-DEFUN (ipv6_nd_ra_fast_retrans,
- ipv6_nd_ra_fast_retrans_cmd,
- "ipv6 nd ra-fast-retrans",
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Fast retransmit of RA packets\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *zif = ifp->info;
-
- if (if_is_loopback(ifp)) {
- vty_out(vty,
- "Cannot configure IPv6 Router Advertisements on this interface\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- zif->rtadv.UseFastRexmit = true;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_ipv6_nd_ra_fast_retrans,
- no_ipv6_nd_ra_fast_retrans_cmd,
- "no ipv6 nd ra-fast-retrans",
- NO_STR
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Fast retransmit of RA packets\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *zif = ifp->info;
-
- if (if_is_loopback(ifp)) {
- vty_out(vty,
- "Cannot configure IPv6 Router Advertisements on this interface\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- zif->rtadv.UseFastRexmit = false;
-
- return CMD_SUCCESS;
-}
-
-DEFPY (ipv6_nd_ra_hop_limit,
- ipv6_nd_ra_hop_limit_cmd,
- "ipv6 nd ra-hop-limit (0-255)$hopcount",
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Advertisement Hop Limit\n"
- "Advertisement Hop Limit in hops (default:64)\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *zif = ifp->info;
-
- if (if_is_loopback(ifp)) {
- vty_out(vty,
- "Cannot configure IPv6 Router Advertisements on this interface\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- zif->rtadv.AdvCurHopLimit = hopcount;
-
- return CMD_SUCCESS;
-}
-
-DEFPY (no_ipv6_nd_ra_hop_limit,
- no_ipv6_nd_ra_hop_limit_cmd,
- "no ipv6 nd ra-hop-limit [(0-255)]",
- NO_STR
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Advertisement Hop Limit\n"
- "Advertisement Hop Limit in hops\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *zif = ifp->info;
-
- if (if_is_loopback(ifp)) {
- vty_out(vty,
- "Cannot configure IPv6 Router Advertisements on this interface\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- zif->rtadv.AdvCurHopLimit = RTADV_DEFAULT_HOPLIMIT;
-
- return CMD_SUCCESS;
-}
-
-DEFPY (ipv6_nd_ra_retrans_interval,
- ipv6_nd_ra_retrans_interval_cmd,
- "ipv6 nd ra-retrans-interval (0-4294967295)$interval",
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Advertisement Retransmit Interval\n"
- "Advertisement Retransmit Interval in msec\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *zif = ifp->info;
-
- if (if_is_loopback(ifp)) {
- vty_out(vty,
- "Cannot configure IPv6 Router Advertisements on loopback interface\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- zif->rtadv.AdvRetransTimer = interval;
-
- return CMD_SUCCESS;
-}
-
-DEFPY (no_ipv6_nd_ra_retrans_interval,
- no_ipv6_nd_ra_retrans_interval_cmd,
- "no ipv6 nd ra-retrans-interval [(0-4294967295)]",
- NO_STR
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Advertisement Retransmit Interval\n"
- "Advertisement Retransmit Interval in msec\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *zif = ifp->info;
-
- if (if_is_loopback(ifp)) {
- vty_out(vty,
- "Cannot remove IPv6 Router Advertisements on loopback interface\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- zif->rtadv.AdvRetransTimer = 0;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (ipv6_nd_suppress_ra,
- ipv6_nd_suppress_ra_cmd,
- "ipv6 nd suppress-ra",
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Suppress Router Advertisement\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *zif = ifp->info;
-
- if (if_is_loopback(ifp)) {
- vty_out(vty,
- "Cannot configure IPv6 Router Advertisements on this interface\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- if (!CHECK_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED))
- ipv6_nd_suppress_ra_set(ifp, RA_SUPPRESS);
-
- UNSET_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED);
- return CMD_SUCCESS;
-}
-
-DEFUN (no_ipv6_nd_suppress_ra,
- no_ipv6_nd_suppress_ra_cmd,
- "no ipv6 nd suppress-ra",
- NO_STR
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Suppress Router Advertisement\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *zif = ifp->info;
-
- if (if_is_loopback(ifp)) {
- vty_out(vty,
- "Cannot configure IPv6 Router Advertisements on this interface\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- ipv6_nd_suppress_ra_set(ifp, RA_ENABLE);
- SET_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED);
- return CMD_SUCCESS;
-}
-
-DEFUN (ipv6_nd_ra_interval_msec,
- ipv6_nd_ra_interval_msec_cmd,
- "ipv6 nd ra-interval msec (70-1800000)",
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Router Advertisement interval\n"
- "Router Advertisement interval in milliseconds\n"
- "Router Advertisement interval in milliseconds\n")
-{
- int idx_number = 4;
- VTY_DECLVAR_CONTEXT(interface, ifp);
- unsigned interval;
- struct zebra_if *zif = ifp->info;
- struct zebra_vrf *zvrf;
- struct adv_if *adv_if;
-
- zvrf = rtadv_interface_get_zvrf(ifp);
-
- interval = strtoul(argv[idx_number]->arg, NULL, 10);
- if ((zif->rtadv.AdvDefaultLifetime != -1
- && interval > (unsigned)zif->rtadv.AdvDefaultLifetime * 1000)) {
- vty_out(vty,
- "This ra-interval would conflict with configured ra-lifetime!\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- if (zif->rtadv.MaxRtrAdvInterval % 1000) {
- adv_if = adv_msec_if_del(zvrf, ifp->name);
- if (adv_if != NULL)
- adv_if_free(adv_if);
- }
-
- if (interval % 1000)
- (void)adv_msec_if_add(zvrf, ifp->name);
-
- SET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
- zif->rtadv.MaxRtrAdvInterval = interval;
- zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
- zif->rtadv.AdvIntervalTimer = 0;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (ipv6_nd_ra_interval,
- ipv6_nd_ra_interval_cmd,
- "ipv6 nd ra-interval (1-1800)",
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Router Advertisement interval\n"
- "Router Advertisement interval in seconds\n")
-{
- int idx_number = 3;
- VTY_DECLVAR_CONTEXT(interface, ifp);
- unsigned interval;
- struct zebra_if *zif = ifp->info;
- struct zebra_vrf *zvrf;
- struct adv_if *adv_if;
-
- zvrf = rtadv_interface_get_zvrf(ifp);
-
- interval = strtoul(argv[idx_number]->arg, NULL, 10);
- if ((zif->rtadv.AdvDefaultLifetime != -1
- && interval > (unsigned)zif->rtadv.AdvDefaultLifetime)) {
- vty_out(vty,
- "This ra-interval would conflict with configured ra-lifetime!\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- if (zif->rtadv.MaxRtrAdvInterval % 1000) {
- adv_if = adv_msec_if_del(zvrf, ifp->name);
- if (adv_if != NULL)
- adv_if_free(adv_if);
- }
-
- /* convert to milliseconds */
- interval = interval * 1000;
-
- SET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
- zif->rtadv.MaxRtrAdvInterval = interval;
- zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
- zif->rtadv.AdvIntervalTimer = 0;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_ipv6_nd_ra_interval,
- no_ipv6_nd_ra_interval_cmd,
- "no ipv6 nd ra-interval [<(1-1800)|msec (1-1800000)>]",
- NO_STR
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Router Advertisement interval\n"
- "Router Advertisement interval in seconds\n"
- "Specify millisecond router advertisement interval\n"
- "Router Advertisement interval in milliseconds\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *zif = ifp->info;
- struct zebra_vrf *zvrf = NULL;
- struct adv_if *adv_if;
-
- zvrf = rtadv_interface_get_zvrf(ifp);
-
- if (zif->rtadv.MaxRtrAdvInterval % 1000) {
- adv_if = adv_msec_if_del(zvrf, ifp->name);
- if (adv_if != NULL)
- adv_if_free(adv_if);
- }
-
- UNSET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
-
- if (CHECK_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED))
- zif->rtadv.MaxRtrAdvInterval = 10000;
- else
- zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
-
- zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
- zif->rtadv.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (ipv6_nd_ra_lifetime,
- ipv6_nd_ra_lifetime_cmd,
- "ipv6 nd ra-lifetime (0-9000)",
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Router lifetime\n"
- "Router lifetime in seconds (0 stands for a non-default gw)\n")
-{
- int idx_number = 3;
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *zif = ifp->info;
- int lifetime;
-
- lifetime = strtoul(argv[idx_number]->arg, NULL, 10);
-
- /* The value to be placed in the Router Lifetime field
- * of Router Advertisements sent from the interface,
- * in seconds. MUST be either zero or between
- * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
- if ((lifetime != 0 && lifetime * 1000 < zif->rtadv.MaxRtrAdvInterval)) {
- vty_out(vty,
- "This ra-lifetime would conflict with configured ra-interval\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- zif->rtadv.AdvDefaultLifetime = lifetime;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_ipv6_nd_ra_lifetime,
- no_ipv6_nd_ra_lifetime_cmd,
- "no ipv6 nd ra-lifetime [(0-9000)]",
- NO_STR
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Router lifetime\n"
- "Router lifetime in seconds (0 stands for a non-default gw)\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *zif = ifp->info;
-
- zif->rtadv.AdvDefaultLifetime = -1;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (ipv6_nd_reachable_time,
- ipv6_nd_reachable_time_cmd,
- "ipv6 nd reachable-time (1-3600000)",
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Reachable time\n"
- "Reachable time in milliseconds\n")
-{
- int idx_number = 3;
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *zif = ifp->info;
- zif->rtadv.AdvReachableTime = strtoul(argv[idx_number]->arg, NULL, 10);
- return CMD_SUCCESS;
-}
-
-DEFUN (no_ipv6_nd_reachable_time,
- no_ipv6_nd_reachable_time_cmd,
- "no ipv6 nd reachable-time [(1-3600000)]",
- NO_STR
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Reachable time\n"
- "Reachable time in milliseconds\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *zif = ifp->info;
-
- zif->rtadv.AdvReachableTime = 0;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (ipv6_nd_homeagent_preference,
- ipv6_nd_homeagent_preference_cmd,
- "ipv6 nd home-agent-preference (0-65535)",
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Home Agent preference\n"
- "preference value (default is 0, least preferred)\n")
-{
- int idx_number = 3;
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *zif = ifp->info;
- zif->rtadv.HomeAgentPreference =
- strtoul(argv[idx_number]->arg, NULL, 10);
- return CMD_SUCCESS;
-}
-
-DEFUN (no_ipv6_nd_homeagent_preference,
- no_ipv6_nd_homeagent_preference_cmd,
- "no ipv6 nd home-agent-preference [(0-65535)]",
- NO_STR
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Home Agent preference\n"
- "preference value (default is 0, least preferred)\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *zif = ifp->info;
-
- zif->rtadv.HomeAgentPreference = 0;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (ipv6_nd_homeagent_lifetime,
- ipv6_nd_homeagent_lifetime_cmd,
- "ipv6 nd home-agent-lifetime (0-65520)",
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Home Agent lifetime\n"
- "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
-{
- int idx_number = 3;
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *zif = ifp->info;
- zif->rtadv.HomeAgentLifetime = strtoul(argv[idx_number]->arg, NULL, 10);
- return CMD_SUCCESS;
-}
-
-DEFUN (no_ipv6_nd_homeagent_lifetime,
- no_ipv6_nd_homeagent_lifetime_cmd,
- "no ipv6 nd home-agent-lifetime [(0-65520)]",
- NO_STR
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Home Agent lifetime\n"
- "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *zif = ifp->info;
-
- zif->rtadv.HomeAgentLifetime = -1;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (ipv6_nd_managed_config_flag,
- ipv6_nd_managed_config_flag_cmd,
- "ipv6 nd managed-config-flag",
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Managed address configuration flag\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *zif = ifp->info;
-
- zif->rtadv.AdvManagedFlag = 1;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_ipv6_nd_managed_config_flag,
- no_ipv6_nd_managed_config_flag_cmd,
- "no ipv6 nd managed-config-flag",
- NO_STR
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Managed address configuration flag\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *zif = ifp->info;
-
- zif->rtadv.AdvManagedFlag = 0;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (ipv6_nd_homeagent_config_flag,
- ipv6_nd_homeagent_config_flag_cmd,
- "ipv6 nd home-agent-config-flag",
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Home Agent configuration flag\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *zif = ifp->info;
-
- zif->rtadv.AdvHomeAgentFlag = 1;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_ipv6_nd_homeagent_config_flag,
- no_ipv6_nd_homeagent_config_flag_cmd,
- "no ipv6 nd home-agent-config-flag",
- NO_STR
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Home Agent configuration flag\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *zif = ifp->info;
-
- zif->rtadv.AdvHomeAgentFlag = 0;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (ipv6_nd_adv_interval_config_option,
- ipv6_nd_adv_interval_config_option_cmd,
- "ipv6 nd adv-interval-option",
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Advertisement Interval Option\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *zif = ifp->info;
-
- zif->rtadv.AdvIntervalOption = 1;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_ipv6_nd_adv_interval_config_option,
- no_ipv6_nd_adv_interval_config_option_cmd,
- "no ipv6 nd adv-interval-option",
- NO_STR
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Advertisement Interval Option\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *zif = ifp->info;
-
- zif->rtadv.AdvIntervalOption = 0;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (ipv6_nd_other_config_flag,
- ipv6_nd_other_config_flag_cmd,
- "ipv6 nd other-config-flag",
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Other statefull configuration flag\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *zif = ifp->info;
-
- zif->rtadv.AdvOtherConfigFlag = 1;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_ipv6_nd_other_config_flag,
- no_ipv6_nd_other_config_flag_cmd,
- "no ipv6 nd other-config-flag",
- NO_STR
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Other statefull configuration flag\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *zif = ifp->info;
-
- zif->rtadv.AdvOtherConfigFlag = 0;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (ipv6_nd_prefix,
- ipv6_nd_prefix_cmd,
- "ipv6 nd prefix X:X::X:X/M [<(0-4294967295)|infinite> <(0-4294967295)|infinite>] [<router-address|off-link [no-autoconfig]|no-autoconfig [off-link]>]",
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Prefix information\n"
- "IPv6 prefix\n"
- "Valid lifetime in seconds\n"
- "Infinite valid lifetime\n"
- "Preferred lifetime in seconds\n"
- "Infinite preferred lifetime\n"
- "Set Router Address flag\n"
- "Do not use prefix for onlink determination\n"
- "Do not use prefix for autoconfiguration\n"
- "Do not use prefix for autoconfiguration\n"
- "Do not use prefix for onlink determination\n")
-{
- /* prelude */
- char *prefix = argv[3]->arg;
- int lifetimes = (argc > 4) && (argv[4]->type == RANGE_TKN
- || strmatch(argv[4]->text, "infinite"));
- int routeropts = lifetimes ? argc > 6 : argc > 4;
-
- int idx_routeropts = routeropts ? (lifetimes ? 6 : 4) : 0;
-
- char *lifetime = NULL, *preflifetime = NULL;
- int routeraddr = 0, offlink = 0, noautoconf = 0;
- if (lifetimes) {
- lifetime = argv[4]->type == RANGE_TKN ? argv[4]->arg
- : argv[4]->text;
- preflifetime = argv[5]->type == RANGE_TKN ? argv[5]->arg
- : argv[5]->text;
- }
- if (routeropts) {
- routeraddr =
- strmatch(argv[idx_routeropts]->text, "router-address");
- if (!routeraddr) {
- offlink = (argc > idx_routeropts + 1
- || strmatch(argv[idx_routeropts]->text,
- "off-link"));
- noautoconf = (argc > idx_routeropts + 1
- || strmatch(argv[idx_routeropts]->text,
- "no-autoconfig"));
- }
- }
-
- /* business */
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *zebra_if = ifp->info;
- int ret;
- struct rtadv_prefix rp;
-
- ret = str2prefix_ipv6(prefix, &rp.prefix);
- if (!ret) {
- vty_out(vty, "Malformed IPv6 prefix\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
- apply_mask_ipv6(&rp.prefix); /* RFC4861 4.6.2 */
- rp.AdvOnLinkFlag = !offlink;
- rp.AdvAutonomousFlag = !noautoconf;
- rp.AdvRouterAddressFlag = routeraddr;
- rp.AdvValidLifetime = RTADV_VALID_LIFETIME;
- rp.AdvPreferredLifetime = RTADV_PREFERRED_LIFETIME;
- rp.AdvPrefixCreate = PREFIX_SRC_MANUAL;
-
- if (lifetimes) {
- rp.AdvValidLifetime = strmatch(lifetime, "infinite")
- ? UINT32_MAX
- : strtoll(lifetime, NULL, 10);
- rp.AdvPreferredLifetime =
- strmatch(preflifetime, "infinite")
- ? UINT32_MAX
- : strtoll(preflifetime, NULL, 10);
- if (rp.AdvPreferredLifetime > rp.AdvValidLifetime) {
- vty_out(vty, "Invalid preferred lifetime\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
- }
-
- rtadv_prefix_set(zebra_if, &rp);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_ipv6_nd_prefix,
- no_ipv6_nd_prefix_cmd,
- "no ipv6 nd prefix X:X::X:X/M [<(0-4294967295)|infinite> <(0-4294967295)|infinite>] [<router-address|off-link [no-autoconfig]|no-autoconfig [off-link]>]",
- NO_STR
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Prefix information\n"
- "IPv6 prefix\n"
- "Valid lifetime in seconds\n"
- "Infinite valid lifetime\n"
- "Preferred lifetime in seconds\n"
- "Infinite preferred lifetime\n"
- "Set Router Address flag\n"
- "Do not use prefix for onlink determination\n"
- "Do not use prefix for autoconfiguration\n"
- "Do not use prefix for autoconfiguration\n"
- "Do not use prefix for onlink determination\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *zebra_if = ifp->info;
- int ret;
- struct rtadv_prefix rp;
- char *prefix = argv[4]->arg;
-
- ret = str2prefix_ipv6(prefix, &rp.prefix);
- if (!ret) {
- vty_out(vty, "Malformed IPv6 prefix\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
- apply_mask_ipv6(&rp.prefix); /* RFC4861 4.6.2 */
- rp.AdvPrefixCreate = PREFIX_SRC_MANUAL;
-
- ret = rtadv_prefix_reset(zebra_if, &rp);
- if (!ret) {
- vty_out(vty, "Non-existant IPv6 prefix\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- return CMD_SUCCESS;
-}
-
-DEFUN (ipv6_nd_router_preference,
- ipv6_nd_router_preference_cmd,
- "ipv6 nd router-preference <high|medium|low>",
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Default router preference\n"
- "High default router preference\n"
- "Medium default router preference (default)\n"
- "Low default router preference\n")
-{
- int idx_high_medium_low = 3;
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *zif = ifp->info;
- int i = 0;
-
- while (0 != rtadv_pref_strs[i]) {
- if (strncmp(argv[idx_high_medium_low]->arg, rtadv_pref_strs[i],
- 1)
- == 0) {
- zif->rtadv.DefaultPreference = i;
- return CMD_SUCCESS;
- }
- i++;
- }
-
- return CMD_ERR_NO_MATCH;
-}
-
-DEFUN (no_ipv6_nd_router_preference,
- no_ipv6_nd_router_preference_cmd,
- "no ipv6 nd router-preference [<high|medium|low>]",
- NO_STR
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Default router preference\n"
- "High default router preference\n"
- "Medium default router preference (default)\n"
- "Low default router preference\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *zif = ifp->info;
-
- zif->rtadv.DefaultPreference =
- RTADV_PREF_MEDIUM; /* Default per RFC4191. */
-
- return CMD_SUCCESS;
-}
-
-DEFUN (ipv6_nd_mtu,
- ipv6_nd_mtu_cmd,
- "ipv6 nd mtu (1-65535)",
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Advertised MTU\n"
- "MTU in bytes\n")
-{
- int idx_number = 3;
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *zif = ifp->info;
- zif->rtadv.AdvLinkMTU = strtoul(argv[idx_number]->arg, NULL, 10);
- return CMD_SUCCESS;
-}
-
-DEFUN (no_ipv6_nd_mtu,
- no_ipv6_nd_mtu_cmd,
- "no ipv6 nd mtu [(1-65535)]",
- NO_STR
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Advertised MTU\n"
- "MTU in bytes\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *zif = ifp->info;
- zif->rtadv.AdvLinkMTU = 0;
- return CMD_SUCCESS;
-}
-
static struct rtadv_rdnss *rtadv_rdnss_new(void)
{
return XCALLOC(MTYPE_RTADV_RDNSS, sizeof(struct rtadv_rdnss));
@@ -2293,55 +1558,22 @@ static void rtadv_rdnss_free(struct rtadv_rdnss *rdnss)
XFREE(MTYPE_RTADV_RDNSS, rdnss);
}
-static struct rtadv_rdnss *rtadv_rdnss_lookup(struct list *list,
- struct rtadv_rdnss *rdnss)
+struct rtadv_rdnss *rtadv_rdnss_set(struct zebra_if *zif,
+ struct rtadv_rdnss *rdnss)
{
- struct listnode *node;
struct rtadv_rdnss *p;
- for (ALL_LIST_ELEMENTS_RO(list, node, p))
- if (IPV6_ADDR_SAME(&p->addr, &rdnss->addr))
- return p;
- return NULL;
-}
-
-static struct rtadv_rdnss *rtadv_rdnss_get(struct list *list,
- struct rtadv_rdnss *rdnss)
-{
- struct rtadv_rdnss *p;
-
- p = rtadv_rdnss_lookup(list, rdnss);
- if (p)
- return p;
-
p = rtadv_rdnss_new();
memcpy(p, rdnss, sizeof(struct rtadv_rdnss));
- listnode_add(list, p);
+ listnode_add(zif->rtadv.AdvRDNSSList, p);
return p;
}
-static void rtadv_rdnss_set(struct zebra_if *zif, struct rtadv_rdnss *rdnss)
+void rtadv_rdnss_reset(struct zebra_if *zif, struct rtadv_rdnss *p)
{
- struct rtadv_rdnss *p;
-
- p = rtadv_rdnss_get(zif->rtadv.AdvRDNSSList, rdnss);
- p->lifetime = rdnss->lifetime;
- p->lifetime_set = rdnss->lifetime_set;
-}
-
-static int rtadv_rdnss_reset(struct zebra_if *zif, struct rtadv_rdnss *rdnss)
-{
- struct rtadv_rdnss *p;
-
- p = rtadv_rdnss_lookup(zif->rtadv.AdvRDNSSList, rdnss);
- if (p) {
- listnode_delete(zif->rtadv.AdvRDNSSList, p);
- rtadv_rdnss_free(p);
- return 1;
- }
-
- return 0;
+ listnode_delete(zif->rtadv.AdvRDNSSList, p);
+ rtadv_rdnss_free(p);
}
static struct rtadv_dnssl *rtadv_dnssl_new(void)
@@ -2354,54 +1586,22 @@ static void rtadv_dnssl_free(struct rtadv_dnssl *dnssl)
XFREE(MTYPE_RTADV_DNSSL, dnssl);
}
-static struct rtadv_dnssl *rtadv_dnssl_lookup(struct list *list,
- struct rtadv_dnssl *dnssl)
+struct rtadv_dnssl *rtadv_dnssl_set(struct zebra_if *zif,
+ struct rtadv_dnssl *dnssl)
{
- struct listnode *node;
struct rtadv_dnssl *p;
- for (ALL_LIST_ELEMENTS_RO(list, node, p))
- if (!strcasecmp(p->name, dnssl->name))
- return p;
- return NULL;
-}
-
-static struct rtadv_dnssl *rtadv_dnssl_get(struct list *list,
- struct rtadv_dnssl *dnssl)
-{
- struct rtadv_dnssl *p;
-
- p = rtadv_dnssl_lookup(list, dnssl);
- if (p)
- return p;
-
p = rtadv_dnssl_new();
memcpy(p, dnssl, sizeof(struct rtadv_dnssl));
- listnode_add(list, p);
+ listnode_add(zif->rtadv.AdvDNSSLList, p);
return p;
}
-static void rtadv_dnssl_set(struct zebra_if *zif, struct rtadv_dnssl *dnssl)
-{
- struct rtadv_dnssl *p;
-
- p = rtadv_dnssl_get(zif->rtadv.AdvDNSSLList, dnssl);
- memcpy(p, dnssl, sizeof(struct rtadv_dnssl));
-}
-
-static int rtadv_dnssl_reset(struct zebra_if *zif, struct rtadv_dnssl *dnssl)
+void rtadv_dnssl_reset(struct zebra_if *zif, struct rtadv_dnssl *p)
{
- struct rtadv_dnssl *p;
-
- p = rtadv_dnssl_lookup(zif->rtadv.AdvDNSSLList, dnssl);
- if (p) {
- listnode_delete(zif->rtadv.AdvDNSSLList, p);
- rtadv_dnssl_free(p);
- return 1;
- }
-
- return 0;
+ listnode_delete(zif->rtadv.AdvDNSSLList, p);
+ rtadv_dnssl_free(p);
}
/*
@@ -2412,7 +1612,7 @@ static int rtadv_dnssl_reset(struct zebra_if *zif, struct rtadv_dnssl *dnssl)
* Returns the number of octets written to out or -1 if in does not constitute
* a valid domain name.
*/
-static int rtadv_dnssl_encode(uint8_t *out, const char *in)
+int rtadv_dnssl_encode(uint8_t *out, const char *in)
{
const char *label_start, *label_end;
size_t outp;
@@ -2443,148 +1643,6 @@ static int rtadv_dnssl_encode(uint8_t *out, const char *in)
return outp;
}
-DEFUN(ipv6_nd_rdnss,
- ipv6_nd_rdnss_cmd,
- "ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Recursive DNS server information\n"
- "IPv6 address\n"
- "Valid lifetime in seconds\n"
- "Infinite valid lifetime\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *zif = ifp->info;
- struct rtadv_rdnss rdnss = {};
-
- if (inet_pton(AF_INET6, argv[3]->arg, &rdnss.addr) != 1) {
- vty_out(vty, "Malformed IPv6 address\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
- if (argc > 4) {
- char *lifetime = argv[4]->type == RANGE_TKN ? argv[4]->arg
- : argv[4]->text;
- rdnss.lifetime = strmatch(lifetime, "infinite")
- ? UINT32_MAX
- : strtoll(lifetime, NULL, 10);
- rdnss.lifetime_set = 1;
- }
-
- rtadv_rdnss_set(zif, &rdnss);
-
- return CMD_SUCCESS;
-}
-
-DEFUN(no_ipv6_nd_rdnss,
- no_ipv6_nd_rdnss_cmd,
- "no ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
- NO_STR
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Recursive DNS server information\n"
- "IPv6 address\n"
- "Valid lifetime in seconds\n"
- "Infinite valid lifetime\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *zif = ifp->info;
- struct rtadv_rdnss rdnss = {};
-
- if (inet_pton(AF_INET6, argv[4]->arg, &rdnss.addr) != 1) {
- vty_out(vty, "Malformed IPv6 address\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
- if (rtadv_rdnss_reset(zif, &rdnss) != 1) {
- vty_out(vty, "Non-existant RDNSS address\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- return CMD_SUCCESS;
-}
-
-DEFUN(ipv6_nd_dnssl,
- ipv6_nd_dnssl_cmd,
- "ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "DNS search list information\n"
- "Domain name suffix\n"
- "Valid lifetime in seconds\n"
- "Infinite valid lifetime\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *zif = ifp->info;
- struct rtadv_dnssl dnssl = {};
- size_t len;
- int ret;
-
- len = strlcpy(dnssl.name, argv[3]->arg, sizeof(dnssl.name));
- if (len == 0 || len >= sizeof(dnssl.name)) {
- vty_out(vty, "Malformed DNS search domain\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
- if (dnssl.name[len - 1] == '.') {
- /*
- * Allow, but don't require, a trailing dot signifying the root
- * zone. Canonicalize by cutting it off if present.
- */
- dnssl.name[len - 1] = '\0';
- len--;
- }
- if (argc > 4) {
- char *lifetime = argv[4]->type == RANGE_TKN ? argv[4]->arg
- : argv[4]->text;
- dnssl.lifetime = strmatch(lifetime, "infinite")
- ? UINT32_MAX
- : strtoll(lifetime, NULL, 10);
- dnssl.lifetime_set = 1;
- }
-
- ret = rtadv_dnssl_encode(dnssl.encoded_name, dnssl.name);
- if (ret < 0) {
- vty_out(vty, "Malformed DNS search domain\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
- dnssl.encoded_len = ret;
- rtadv_dnssl_set(zif, &dnssl);
-
- return CMD_SUCCESS;
-}
-
-DEFUN(no_ipv6_nd_dnssl,
- no_ipv6_nd_dnssl_cmd,
- "no ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
- NO_STR
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "DNS search list information\n"
- "Domain name suffix\n"
- "Valid lifetime in seconds\n"
- "Infinite valid lifetime\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *zif = ifp->info;
- struct rtadv_dnssl dnssl = {};
- size_t len;
-
- len = strlcpy(dnssl.name, argv[4]->arg, sizeof(dnssl.name));
- if (len == 0 || len >= sizeof(dnssl.name)) {
- vty_out(vty, "Malformed DNS search domain\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
- if (dnssl.name[len - 1] == '.') {
- dnssl.name[len - 1] = '\0';
- len--;
- }
- if (rtadv_dnssl_reset(zif, &dnssl) != 1) {
- vty_out(vty, "Non-existant DNS search domain\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- return CMD_SUCCESS;
-}
-
-
/* Dump interface ND information to vty. */
static int nd_dump_vty(struct vty *vty, struct interface *ifp)
{
@@ -2655,136 +1713,6 @@ static int nd_dump_vty(struct vty *vty, struct interface *ifp)
return 0;
}
-
-/* Write configuration about router advertisement. */
-static int rtadv_config_write(struct vty *vty, struct interface *ifp)
-{
- struct zebra_if *zif;
- struct listnode *node;
- struct rtadv_prefix *rprefix;
- struct rtadv_rdnss *rdnss;
- struct rtadv_dnssl *dnssl;
- int interval;
-
- zif = ifp->info;
-
- if (!if_is_loopback(ifp)) {
- if (zif->rtadv.AdvSendAdvertisements
- && CHECK_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED))
- vty_out(vty, " no ipv6 nd suppress-ra\n");
- }
-
- interval = zif->rtadv.MaxRtrAdvInterval;
- if (CHECK_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED)) {
- if (interval % 1000)
- vty_out(vty, " ipv6 nd ra-interval msec %d\n",
- interval);
- else if (interval != RTADV_MAX_RTR_ADV_INTERVAL)
- vty_out(vty, " ipv6 nd ra-interval %d\n",
- interval / 1000);
- }
-
- if (zif->rtadv.AdvIntervalOption)
- vty_out(vty, " ipv6 nd adv-interval-option\n");
-
- if (!zif->rtadv.UseFastRexmit)
- vty_out(vty, " no ipv6 nd ra-fast-retrans\n");
-
- if (zif->rtadv.AdvRetransTimer != 0)
- vty_out(vty, " ipv6 nd ra-retrans-interval %u\n",
- zif->rtadv.AdvRetransTimer);
-
- if (zif->rtadv.AdvCurHopLimit != RTADV_DEFAULT_HOPLIMIT)
- vty_out(vty, " ipv6 nd ra-hop-limit %d\n",
- zif->rtadv.AdvCurHopLimit);
-
- if (zif->rtadv.AdvDefaultLifetime != -1)
- vty_out(vty, " ipv6 nd ra-lifetime %d\n",
- zif->rtadv.AdvDefaultLifetime);
-
- if (zif->rtadv.HomeAgentPreference)
- vty_out(vty, " ipv6 nd home-agent-preference %u\n",
- zif->rtadv.HomeAgentPreference);
-
- if (zif->rtadv.HomeAgentLifetime != -1)
- vty_out(vty, " ipv6 nd home-agent-lifetime %u\n",
- zif->rtadv.HomeAgentLifetime);
-
- if (zif->rtadv.AdvHomeAgentFlag)
- vty_out(vty, " ipv6 nd home-agent-config-flag\n");
-
- if (zif->rtadv.AdvReachableTime)
- vty_out(vty, " ipv6 nd reachable-time %d\n",
- zif->rtadv.AdvReachableTime);
-
- if (zif->rtadv.AdvManagedFlag)
- vty_out(vty, " ipv6 nd managed-config-flag\n");
-
- if (zif->rtadv.AdvOtherConfigFlag)
- vty_out(vty, " ipv6 nd other-config-flag\n");
-
- if (zif->rtadv.DefaultPreference != RTADV_PREF_MEDIUM)
- vty_out(vty, " ipv6 nd router-preference %s\n",
- rtadv_pref_strs[zif->rtadv.DefaultPreference]);
-
- if (zif->rtadv.AdvLinkMTU)
- vty_out(vty, " ipv6 nd mtu %d\n", zif->rtadv.AdvLinkMTU);
-
- frr_each (rtadv_prefixes, zif->rtadv.prefixes, rprefix) {
- if ((rprefix->AdvPrefixCreate == PREFIX_SRC_MANUAL)
- || (rprefix->AdvPrefixCreate == PREFIX_SRC_BOTH)) {
- vty_out(vty, " ipv6 nd prefix %pFX", &rprefix->prefix);
- if ((rprefix->AdvValidLifetime != RTADV_VALID_LIFETIME)
- || (rprefix->AdvPreferredLifetime
- != RTADV_PREFERRED_LIFETIME)) {
- if (rprefix->AdvValidLifetime == UINT32_MAX)
- vty_out(vty, " infinite");
- else
- vty_out(vty, " %u",
- rprefix->AdvValidLifetime);
- if (rprefix->AdvPreferredLifetime == UINT32_MAX)
- vty_out(vty, " infinite");
- else
- vty_out(vty, " %u",
- rprefix->AdvPreferredLifetime);
- }
- if (!rprefix->AdvOnLinkFlag)
- vty_out(vty, " off-link");
- if (!rprefix->AdvAutonomousFlag)
- vty_out(vty, " no-autoconfig");
- if (rprefix->AdvRouterAddressFlag)
- vty_out(vty, " router-address");
- vty_out(vty, "\n");
- }
- }
-
- for (ALL_LIST_ELEMENTS_RO(zif->rtadv.AdvRDNSSList, node, rdnss)) {
- char buf[INET6_ADDRSTRLEN];
-
- vty_out(vty, " ipv6 nd rdnss %s",
- inet_ntop(AF_INET6, &rdnss->addr, buf, sizeof(buf)));
- if (rdnss->lifetime_set) {
- if (rdnss->lifetime == UINT32_MAX)
- vty_out(vty, " infinite");
- else
- vty_out(vty, " %u", rdnss->lifetime);
- }
- vty_out(vty, "\n");
- }
- for (ALL_LIST_ELEMENTS_RO(zif->rtadv.AdvDNSSLList, node, dnssl)) {
- vty_out(vty, " ipv6 nd dnssl %s", dnssl->name);
- if (dnssl->lifetime_set) {
- if (dnssl->lifetime == UINT32_MAX)
- vty_out(vty, " infinite");
- else
- vty_out(vty, " %u", dnssl->lifetime);
- }
- vty_out(vty, "\n");
- }
- return 0;
-}
-
-
static void rtadv_event(struct zebra_vrf *zvrf, enum rtadv_event event, int val)
{
struct rtadv *rtadv;
@@ -2930,49 +1858,8 @@ void rtadv_cmd_init(void)
interfaces_configured_for_ra_from_bgp = 0;
hook_register(zebra_if_extra_info, nd_dump_vty);
- hook_register(zebra_if_config_wr, rtadv_config_write);
install_element(VIEW_NODE, &show_ipv6_nd_ra_if_cmd);
-
- install_element(INTERFACE_NODE, &ipv6_nd_ra_fast_retrans_cmd);
- install_element(INTERFACE_NODE, &no_ipv6_nd_ra_fast_retrans_cmd);
- install_element(INTERFACE_NODE, &ipv6_nd_ra_retrans_interval_cmd);
- install_element(INTERFACE_NODE, &no_ipv6_nd_ra_retrans_interval_cmd);
- install_element(INTERFACE_NODE, &ipv6_nd_ra_hop_limit_cmd);
- install_element(INTERFACE_NODE, &no_ipv6_nd_ra_hop_limit_cmd);
- install_element(INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd);
- install_element(INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd);
- install_element(INTERFACE_NODE, &ipv6_nd_ra_interval_cmd);
- install_element(INTERFACE_NODE, &ipv6_nd_ra_interval_msec_cmd);
- install_element(INTERFACE_NODE, &no_ipv6_nd_ra_interval_cmd);
- install_element(INTERFACE_NODE, &ipv6_nd_ra_lifetime_cmd);
- install_element(INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_cmd);
- install_element(INTERFACE_NODE, &ipv6_nd_reachable_time_cmd);
- install_element(INTERFACE_NODE, &no_ipv6_nd_reachable_time_cmd);
- install_element(INTERFACE_NODE, &ipv6_nd_managed_config_flag_cmd);
- install_element(INTERFACE_NODE, &no_ipv6_nd_managed_config_flag_cmd);
- install_element(INTERFACE_NODE, &ipv6_nd_other_config_flag_cmd);
- install_element(INTERFACE_NODE, &no_ipv6_nd_other_config_flag_cmd);
- install_element(INTERFACE_NODE, &ipv6_nd_homeagent_config_flag_cmd);
- install_element(INTERFACE_NODE, &no_ipv6_nd_homeagent_config_flag_cmd);
- install_element(INTERFACE_NODE, &ipv6_nd_homeagent_preference_cmd);
- install_element(INTERFACE_NODE, &no_ipv6_nd_homeagent_preference_cmd);
- install_element(INTERFACE_NODE, &ipv6_nd_homeagent_lifetime_cmd);
- install_element(INTERFACE_NODE, &no_ipv6_nd_homeagent_lifetime_cmd);
- install_element(INTERFACE_NODE,
- &ipv6_nd_adv_interval_config_option_cmd);
- install_element(INTERFACE_NODE,
- &no_ipv6_nd_adv_interval_config_option_cmd);
- install_element(INTERFACE_NODE, &ipv6_nd_prefix_cmd);
- install_element(INTERFACE_NODE, &no_ipv6_nd_prefix_cmd);
- install_element(INTERFACE_NODE, &ipv6_nd_router_preference_cmd);
- install_element(INTERFACE_NODE, &no_ipv6_nd_router_preference_cmd);
- install_element(INTERFACE_NODE, &ipv6_nd_mtu_cmd);
- install_element(INTERFACE_NODE, &no_ipv6_nd_mtu_cmd);
- install_element(INTERFACE_NODE, &ipv6_nd_rdnss_cmd);
- install_element(INTERFACE_NODE, &no_ipv6_nd_rdnss_cmd);
- install_element(INTERFACE_NODE, &ipv6_nd_dnssl_cmd);
- install_element(INTERFACE_NODE, &no_ipv6_nd_dnssl_cmd);
}
static int if_join_all_router(int sock, struct interface *ifp)
@@ -3069,3 +1956,13 @@ uint32_t rtadv_get_interfaces_configured_from_bgp(void)
{
return interfaces_configured_for_ra_from_bgp;
}
+
+void rtadv_init(void)
+{
+ if (CMSG_SPACE(sizeof(struct in6_pktinfo)) > RTADV_ADATA_SIZE) {
+ zlog_debug("%s: RTADV_ADATA_SIZE choosen will not work on this platform, please use a larger size",
+ __func__);
+
+ exit(-1);
+ }
+}
diff --git a/zebra/rtadv.h b/zebra/rtadv.h
index 1ec376a106..0983ea578f 100644
--- a/zebra/rtadv.h
+++ b/zebra/rtadv.h
@@ -385,6 +385,30 @@ extern void rtadv_if_fini(struct zebra_if *zif);
extern void rtadv_add_prefix(struct zebra_if *zif, const struct prefix_ipv6 *p);
extern void rtadv_delete_prefix(struct zebra_if *zif, const struct prefix *p);
+/* returns created prefix */
+struct rtadv_prefix *rtadv_add_prefix_manual(struct zebra_if *zif,
+ struct rtadv_prefix *rp);
+/* rprefix must be the one returned by rtadv_add_prefix_manual */
+void rtadv_delete_prefix_manual(struct zebra_if *zif,
+ struct rtadv_prefix *rprefix);
+
+/* returns created address */
+struct rtadv_rdnss *rtadv_rdnss_set(struct zebra_if *zif,
+ struct rtadv_rdnss *rdnss);
+/* p must be the one returned by rtadv_rdnss_set */
+void rtadv_rdnss_reset(struct zebra_if *zif, struct rtadv_rdnss *p);
+
+/* returns created domain */
+struct rtadv_dnssl *rtadv_dnssl_set(struct zebra_if *zif,
+ struct rtadv_dnssl *dnssl);
+/* p must be the one returned by rtadv_dnssl_set */
+void rtadv_dnssl_reset(struct zebra_if *zif, struct rtadv_dnssl *p);
+int rtadv_dnssl_encode(uint8_t *out, const char *in);
+
+void ipv6_nd_suppress_ra_set(struct interface *ifp,
+ enum ipv6_nd_suppress_ra_status status);
+void ipv6_nd_interval_set(struct interface *ifp, uint32_t interval);
+
#else /* !HAVE_RTADV */
struct rtadv {
/* empty structs aren't valid ISO C */
@@ -435,6 +459,7 @@ extern void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS);
extern uint32_t rtadv_get_interfaces_configured_from_bgp(void);
extern bool rtadv_compiled_in(void);
+extern void rtadv_init(void);
#ifdef __cplusplus
}
diff --git a/zebra/rtread_sysctl.c b/zebra/rtread_sysctl.c
index ef1e21b4f7..8e2d13faff 100644
--- a/zebra/rtread_sysctl.c
+++ b/zebra/rtread_sysctl.c
@@ -6,6 +6,8 @@
#include <zebra.h>
+#include <net/route.h>
+
#if !defined(GNU_LINUX)
#include "memory.h"
diff --git a/zebra/rule_netlink.c b/zebra/rule_netlink.c
index c7832992ea..05282793d7 100644
--- a/zebra/rule_netlink.c
+++ b/zebra/rule_netlink.c
@@ -9,6 +9,9 @@
#ifdef HAVE_NETLINK
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+
#include "if.h"
#include "prefix.h"
#include "vrf.h"
@@ -116,9 +119,9 @@ static ssize_t netlink_rule_msg_encode(
return 0;
}
- /* dsfield, if specified */
- if (filter_bm & PBR_FILTER_DSFIELD)
- req->frh.tos = dsfield;
+ /* dsfield, if specified; mask off the ECN bits */
+ if (filter_bm & PBR_FILTER_DSCP)
+ req->frh.tos = dsfield & PBR_DSFIELD_DSCP;
/* protocol to match on */
if (filter_bm & PBR_FILTER_IP_PROTOCOL)
@@ -174,6 +177,17 @@ static ssize_t netlink_oldrule_msg_encoder(struct zebra_dplane_ctx *ctx,
dplane_ctx_rule_get_old_ipproto(ctx), buf, buflen);
}
+/*
+ * Identify valid rule actions for netlink - other actions can't be installed
+ */
+static bool nl_rule_valid_action(uint32_t action)
+{
+ if (action == PBR_ACTION_TABLE)
+ return true;
+ else
+ return false;
+}
+
/* Public functions */
enum netlink_msg_status
@@ -181,6 +195,7 @@ netlink_put_rule_update_msg(struct nl_batch *bth, struct zebra_dplane_ctx *ctx)
{
enum dplane_op_e op;
enum netlink_msg_status ret;
+ struct pbr_rule rule = {};
op = dplane_ctx_get_op(ctx);
if (!(op == DPLANE_OP_RULE_ADD || op == DPLANE_OP_RULE_UPDATE
@@ -192,6 +207,18 @@ netlink_put_rule_update_msg(struct nl_batch *bth, struct zebra_dplane_ctx *ctx)
return FRR_NETLINK_ERROR;
}
+ /* TODO -- special handling for rules that include actions that
+ * netlink cannot install. Some of the rule attributes are not
+ * available in netlink: only try to install valid actions.
+ */
+ dplane_ctx_rule_get(ctx, &rule, NULL);
+ if (!nl_rule_valid_action(rule.action.flags)) {
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("%s: skip invalid action %#x", __func__,
+ rule.action.flags);
+ return 0;
+ }
+
ret = netlink_batch_add_msg(bth, ctx, netlink_rule_msg_encoder, false);
/**
@@ -400,6 +427,7 @@ int netlink_rules_read(struct zebra_ns *zns)
ret = netlink_parse_info(netlink_rule_change, &zns->netlink_cmd,
&dp_info, 0, true);
+
return ret;
}
diff --git a/zebra/subdir.am b/zebra/subdir.am
index 1060e38785..f767447366 100644
--- a/zebra/subdir.am
+++ b/zebra/subdir.am
@@ -19,6 +19,12 @@ if LINUX
module_LTLIBRARIES += zebra/zebra_cumulus_mlag.la
endif
+#if FPM_LISTENER
+sbin_PROGRAMS += zebra/fpm_listener
+zebra_fpm_listener_SOURCES = zebra/fpm_listener.c
+zebra_fpm_listener_LDADD = lib/libfrr.la
+#endf
+
# Dataplane sample plugin
if DEV_BUILD
module_LTLIBRARIES += zebra/dplane_sample_plugin.la
@@ -28,7 +34,7 @@ man8 += $(MANBUILD)/frr-zebra.8
## endif ZEBRA
endif
-zebra_zebra_LDADD = lib/libfrr.la $(LIBCAP) $(UST_LIBS)
+zebra_zebra_LDADD = lib/libfrr.la $(LIBCAP) $(LIBYANG_LIBS) $(UST_LIBS)
if HAVE_PROTOBUF3
zebra_zebra_LDADD += mlag/libmlag_pb.la $(PROTOBUF_C_LIBS)
zebra/zebra_mlag.$(OBJEXT): mlag/mlag.pb-c.h
@@ -52,6 +58,7 @@ zebra_zebra_SOURCES = \
zebra/redistribute.c \
zebra/router-id.c \
zebra/rt_netlink.c \
+ zebra/ge_netlink.c \
zebra/rt_socket.c \
zebra/rtadv.c \
zebra/rtread_netlink.c \
@@ -115,15 +122,17 @@ zebra_zebra_SOURCES = \
clippy_scan += \
zebra/debug.c \
+ zebra/dplane_fpm_nl.c \
zebra/interface.c \
zebra/rtadv.c \
- zebra/zebra_evpn_mh.c \
zebra/zebra_mlag_vty.c \
zebra/zebra_routemap.c \
zebra/zebra_vty.c \
zebra/zebra_srv6_vty.c \
zebra/zebra_vrf.c \
zebra/dpdk/zebra_dplane_dpdk_vty.c \
+ zebra/label_manager.c \
+ zebra/zebra_cli.c \
# end
noinst_HEADERS += \
@@ -143,6 +152,7 @@ noinst_HEADERS += \
zebra/router-id.h \
zebra/rt.h \
zebra/rt_netlink.h \
+ zebra/ge_netlink.h \
zebra/rtadv.h \
zebra/rule_netlink.h \
zebra/table_manager.h \
diff --git a/zebra/table_manager.c b/zebra/table_manager.c
index 77ec42e64b..8417a22114 100644
--- a/zebra/table_manager.c
+++ b/zebra/table_manager.c
@@ -24,21 +24,6 @@
#include "zebra/table_manager.h"
#include "zebra/zebra_errors.h"
-/* routing table identifiers
- *
- */
-#if !defined(GNU_LINUX)
-/* BSD systems
- */
-#else
-/* Linux Systems
- */
-#define RT_TABLE_ID_LOCAL 255
-#define RT_TABLE_ID_MAIN 254
-#define RT_TABLE_ID_DEFAULT 253
-#define RT_TABLE_ID_COMPAT 252
-#define RT_TABLE_ID_UNSPEC 0
-#endif /* !def(GNU_LINUX) */
#define RT_TABLE_ID_UNRESERVED_MIN 1
#define RT_TABLE_ID_UNRESERVED_MAX 0xffffffff
@@ -63,8 +48,7 @@ void table_manager_enable(struct zebra_vrf *zvrf)
&& strcmp(zvrf_name(zvrf), VRF_DEFAULT_NAME)) {
struct zebra_vrf *def = zebra_vrf_lookup_by_id(VRF_DEFAULT);
- if (def)
- zvrf->tbl_mgr = def->tbl_mgr;
+ zvrf->tbl_mgr = def->tbl_mgr;
return;
}
zvrf->tbl_mgr = XCALLOC(MTYPE_TM_TABLE, sizeof(struct table_manager));
@@ -280,52 +264,11 @@ void table_manager_disable(struct zebra_vrf *zvrf)
zvrf->tbl_mgr = NULL;
}
-int table_manager_range(struct vty *vty, bool add, struct zebra_vrf *zvrf,
- const char *start_table_str, const char *end_table_str)
+void table_manager_range(bool add, struct zebra_vrf *zvrf, uint32_t start,
+ uint32_t end)
{
- uint32_t start;
- uint32_t end;
-
- if (add) {
- if (!start_table_str || !end_table_str) {
- vty_out(vty, "%% Labels not specified\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
- start = atoi(start_table_str);
- end = atoi(end_table_str);
- if (end < start) {
- vty_out(vty, "%% End table is less than Start table\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
-#if !defined(GNU_LINUX)
-/* BSD systems
- */
-#else
- /* Linux Systems
- */
- if ((start >= RT_TABLE_ID_COMPAT && start <= RT_TABLE_ID_LOCAL)
- || (end >= RT_TABLE_ID_COMPAT
- && end <= RT_TABLE_ID_LOCAL)) {
- vty_out(vty, "%% Values forbidden in range [%u;%u]\n",
- RT_TABLE_ID_COMPAT, RT_TABLE_ID_LOCAL);
- return CMD_WARNING_CONFIG_FAILED;
- }
- if (start < RT_TABLE_ID_COMPAT && end > RT_TABLE_ID_LOCAL) {
- vty_out(vty,
- "%% Range overlaps range [%u;%u] forbidden\n",
- RT_TABLE_ID_COMPAT, RT_TABLE_ID_LOCAL);
- return CMD_WARNING_CONFIG_FAILED;
- }
-#endif
- if (zvrf->tbl_mgr
- && ((zvrf->tbl_mgr->start && zvrf->tbl_mgr->start != start)
- || (zvrf->tbl_mgr->end && zvrf->tbl_mgr->end != end))) {
- vty_out(vty,
- "%% New range will be taken into account at restart\n");
- }
+ if (add)
table_range_add(zvrf, start, end);
- } else
+ else
table_range_add(zvrf, 0, 0);
- return CMD_SUCCESS;
}
diff --git a/zebra/table_manager.h b/zebra/table_manager.h
index f8e99a357d..21691994cb 100644
--- a/zebra/table_manager.h
+++ b/zebra/table_manager.h
@@ -18,6 +18,22 @@
extern "C" {
#endif
+/* routing table identifiers
+ *
+ */
+#if !defined(GNU_LINUX)
+/* BSD systems
+ */
+#else
+/* Linux Systems
+ */
+#define RT_TABLE_ID_LOCAL 255
+#define RT_TABLE_ID_MAIN 254
+#define RT_TABLE_ID_DEFAULT 253
+#define RT_TABLE_ID_COMPAT 252
+#define RT_TABLE_ID_UNSPEC 0
+#endif /* !def(GNU_LINUX) */
+
/*
* Table chunk struct
* Client daemon which the chunk belongs to can be identified by either
@@ -56,8 +72,8 @@ int release_table_chunk(uint8_t proto, uint16_t instance, uint32_t start,
uint32_t end, struct zebra_vrf *zvrf);
int release_daemon_table_chunks(struct zserv *client);
void table_manager_disable(struct zebra_vrf *zvrf);
-int table_manager_range(struct vty *vty, bool add, struct zebra_vrf *zvrf,
- const char *min, const char *max);
+void table_manager_range(bool add, struct zebra_vrf *zvrf, uint32_t start,
+ uint32_t end);
#ifdef __cplusplus
}
diff --git a/zebra/tc_netlink.c b/zebra/tc_netlink.c
index 679dc80a58..19667e66ac 100644
--- a/zebra/tc_netlink.c
+++ b/zebra/tc_netlink.c
@@ -9,6 +9,7 @@
#ifdef HAVE_NETLINK
+#include <linux/rtnetlink.h>
#include <linux/pkt_cls.h>
#include <linux/pkt_sched.h>
#include <netinet/if_ether.h>
@@ -160,7 +161,7 @@ static ssize_t netlink_qdisc_msg_encode(int cmd, struct zebra_dplane_ctx *ctx,
struct nlmsghdr n;
struct tcmsg t;
char buf[0];
- } *req = (void *)data;
+ } *req = data;
if (datalen < sizeof(*req))
return 0;
@@ -236,7 +237,7 @@ static ssize_t netlink_tclass_msg_encode(int cmd, struct zebra_dplane_ctx *ctx,
struct nlmsghdr n;
struct tcmsg t;
char buf[0];
- } *req = (void *)data;
+ } *req = data;
if (datalen < sizeof(*req))
return 0;
@@ -486,7 +487,7 @@ static ssize_t netlink_tfilter_msg_encode(int cmd, struct zebra_dplane_ctx *ctx,
struct nlmsghdr n;
struct tcmsg t;
char buf[0];
- } *req = (void *)data;
+ } *req = data;
if (datalen < sizeof(*req))
return 0;
@@ -703,6 +704,8 @@ int netlink_qdisc_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
{
struct tcmsg *tcm;
struct zebra_tc_qdisc qdisc = {};
+ enum tc_qdisc_kind kind = TC_QDISC_UNSPEC;
+ const char *kind_str = "Unknown";
int len;
struct rtattr *tb[TCA_MAX + 1];
@@ -722,9 +725,11 @@ int netlink_qdisc_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
tcm = NLMSG_DATA(h);
netlink_parse_rtattr(tb, TCA_MAX, TCA_RTA(tcm), len);
- const char *kind_str = (const char *)RTA_DATA(tb[TCA_KIND]);
+ if (RTA_DATA(tb[TCA_KIND])) {
+ kind_str = (const char *)RTA_DATA(tb[TCA_KIND]);
- enum tc_qdisc_kind kind = tc_qdisc_str2kind(kind_str);
+ kind = tc_qdisc_str2kind(kind_str);
+ }
qdisc.qdisc.ifindex = tcm->tcm_ifindex;
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index 4c6c336d41..76cabd1bf0 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -5,6 +5,8 @@
* Copyright (C) 1997-1999 Kunihiro Ishiguro
* Copyright (C) 2015-2018 Cumulus Networks, Inc.
* et al.
+ * Copyright (c) 2021 The MITRE Corporation.
+ * Copyright (c) 2023 LabN Consulting, L.L.C.
*/
#include <zebra.h>
@@ -22,6 +24,7 @@
#include "lib/vrf.h"
#include "lib/libfrr.h"
#include "lib/lib_errors.h"
+#include "lib/frrdistance.h"
#include "zebra/zebra_router.h"
#include "zebra/rib.h"
@@ -61,7 +64,7 @@ static void zserv_encode_interface(struct stream *s, struct interface *ifp)
/* Interface information. */
struct zebra_if *zif = ifp->info;
- stream_put(s, ifp->name, INTERFACE_NAMSIZ);
+ stream_put(s, ifp->name, IFNAMSIZ);
stream_putl(s, ifp->ifindex);
stream_putc(s, ifp->status);
stream_putq(s, ifp->flags);
@@ -69,6 +72,7 @@ static void zserv_encode_interface(struct stream *s, struct interface *ifp)
stream_putc(s, ifp->ptm_status);
stream_putl(s, ifp->metric);
stream_putl(s, ifp->speed);
+ stream_putl(s, ifp->txqlen);
stream_putl(s, ifp->mtu);
stream_putl(s, ifp->mtu6);
stream_putl(s, ifp->bandwidth);
@@ -411,7 +415,7 @@ int zsend_interface_addresses(struct zserv *client, struct interface *ifp)
struct nbr_connected *nc;
/* Send interface addresses. */
- for (ALL_LIST_ELEMENTS(ifp->connected, cnode, cnnode, c)) {
+ frr_each (if_connected, ifp->connected, c) {
if (!CHECK_FLAG(c->conf, ZEBRA_IFC_REAL))
continue;
@@ -432,27 +436,6 @@ int zsend_interface_addresses(struct zserv *client, struct interface *ifp)
return 0;
}
-/* Notify client about interface moving from one VRF to another.
- * Whether client is interested in old and new VRF is checked by caller.
- */
-int zsend_interface_vrf_update(struct zserv *client, struct interface *ifp,
- vrf_id_t vrf_id)
-{
- struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
-
- zclient_create_header(s, ZEBRA_INTERFACE_VRF_UPDATE, ifp->vrf->vrf_id);
-
- /* Fill in the name of the interface and its new VRF (id) */
- stream_put(s, ifp->name, INTERFACE_NAMSIZ);
- stream_putl(s, vrf_id);
-
- /* Write packet size. */
- stream_putw_at(s, 0, stream_get_endp(s));
-
- client->if_vrfchg_cnt++;
- return zserv_send_message(client, s);
-}
-
/* Add new nbr connected IPv6 address */
void nbr_connected_add_ipv6(struct interface *ifp, struct in6_addr *address)
{
@@ -528,7 +511,7 @@ int zsend_interface_update(int cmd, struct zserv *client, struct interface *ifp)
int zsend_redistribute_route(int cmd, struct zserv *client,
const struct route_node *rn,
- const struct route_entry *re)
+ const struct route_entry *re, bool is_table_direct)
{
struct zapi_route api;
struct zapi_nexthop *api_nh;
@@ -544,7 +527,11 @@ int zsend_redistribute_route(int cmd, struct zserv *client,
api.vrf_id = re->vrf_id;
api.type = re->type;
api.safi = SAFI_UNICAST;
- api.instance = re->instance;
+ if (is_table_direct) {
+ api.instance = re->table;
+ api.type = ZEBRA_ROUTE_TABLE_DIRECT;
+ } else
+ api.instance = re->instance;
api.flags = re->flags;
afi = family2afi(p->family);
@@ -611,7 +598,10 @@ int zsend_redistribute_route(int cmd, struct zserv *client,
/* Attributes. */
SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
- api.distance = re->distance;
+ if (is_table_direct)
+ api.distance = ZEBRA_TABLEDIRECT_DISTANCE_DEFAULT;
+ else
+ api.distance = re->distance;
SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
api.metric = re->metric;
if (re->tag) {
@@ -801,11 +791,17 @@ int zsend_route_notify_owner(const struct route_node *rn,
int zsend_route_notify_owner_ctx(const struct zebra_dplane_ctx *ctx,
enum zapi_route_notify_owner note)
{
- return (route_notify_internal(
- rib_find_rn_from_ctx(ctx), dplane_ctx_get_type(ctx),
- dplane_ctx_get_instance(ctx), dplane_ctx_get_vrf(ctx),
- dplane_ctx_get_table(ctx), note, dplane_ctx_get_afi(ctx),
- dplane_ctx_get_safi(ctx)));
+ int result;
+ struct route_node *rn = rib_find_rn_from_ctx(ctx);
+
+ result = route_notify_internal(
+ rn, dplane_ctx_get_type(ctx), dplane_ctx_get_instance(ctx),
+ dplane_ctx_get_vrf(ctx), dplane_ctx_get_table(ctx), note,
+ dplane_ctx_get_afi(ctx), dplane_ctx_get_safi(ctx));
+
+ route_unlock_node(rn);
+
+ return result;
}
static void zread_route_notify_request(ZAPI_HANDLER_ARGS)
@@ -839,12 +835,14 @@ void zsend_rule_notify_owner(const struct zebra_dplane_ctx *ctx,
s = stream_new(ZEBRA_MAX_PACKET_SIZ);
- zclient_create_header(s, ZEBRA_RULE_NOTIFY_OWNER, VRF_DEFAULT);
+ zclient_create_header(s, ZEBRA_RULE_NOTIFY_OWNER,
+ dplane_ctx_rule_get_vrfid(ctx));
+
stream_put(s, &note, sizeof(note));
stream_putl(s, dplane_ctx_rule_get_seq(ctx));
stream_putl(s, dplane_ctx_rule_get_priority(ctx));
stream_putl(s, dplane_ctx_rule_get_unique(ctx));
- stream_put(s, dplane_ctx_rule_get_ifname(ctx), INTERFACE_NAMSIZ);
+ stream_put(s, dplane_ctx_rule_get_ifname(ctx), IFNAMSIZ);
stream_putw_at(s, 0, stream_get_endp(s));
@@ -970,9 +968,9 @@ void zsend_ipset_entry_notify_owner(const struct zebra_dplane_ctx *ctx,
zserv_send_message(client, s);
}
-void zsend_nhrp_neighbor_notify(int cmd, struct interface *ifp,
- struct ipaddr *ipaddr, int ndm_state,
- union sockunion *link_layer_ipv4)
+void zsend_neighbor_notify(int cmd, struct interface *ifp,
+ struct ipaddr *ipaddr, int ndm_state,
+ union sockunion *link_layer_ipv4, int ip_len)
{
struct stream *s;
struct listnode *node, *nnode;
@@ -989,13 +987,13 @@ void zsend_nhrp_neighbor_notify(int cmd, struct interface *ifp,
family2addrsize(sockunion_family(&ip)));
for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
- if (!vrf_bitmap_check(client->nhrp_neighinfo[afi],
+ if (!vrf_bitmap_check(&client->neighinfo[afi],
ifp->vrf->vrf_id))
continue;
s = stream_new(ZEBRA_MAX_PACKET_SIZ);
zclient_neigh_ip_encode(s, cmd, &ip, link_layer_ipv4, ifp,
- ndm_state);
+ ndm_state, ip_len);
stream_putw_at(s, 0, stream_get_endp(s));
zserv_send_message(client, s);
}
@@ -1010,7 +1008,7 @@ int zsend_router_id_update(struct zserv *client, afi_t afi, struct prefix *p,
struct stream *s;
/* Check this client need interface information. */
- if (!vrf_bitmap_check(client->ridinfo[afi], vrf_id))
+ if (!vrf_bitmap_check(&client->ridinfo[afi], vrf_id))
return 0;
s = stream_new(ZEBRA_MAX_PACKET_SIZ);
@@ -1038,7 +1036,7 @@ int zsend_pw_update(struct zserv *client, struct zebra_pw *pw)
struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
zclient_create_header(s, ZEBRA_PW_STATUS_UPDATE, pw->vrf_id);
- stream_write(s, pw->ifname, INTERFACE_NAMSIZ);
+ stream_write(s, pw->ifname, IFNAMSIZ);
stream_putl(s, pw->ifindex);
stream_putl(s, pw->status);
@@ -1331,8 +1329,6 @@ static void zread_fec_register(ZAPI_HANDLER_ARGS)
s = msg;
zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
- if (!zvrf)
- return;
/*
* The minimum amount of data that can be sent for one fec
@@ -1394,8 +1390,6 @@ static void zread_fec_unregister(ZAPI_HANDLER_ARGS)
s = msg;
zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
- if (!zvrf)
- return;
/*
* The minimum amount of data that can be sent for one
@@ -1554,7 +1548,6 @@ static struct nexthop *nexthop_from_zapi(const struct zapi_nexthop *api_nh,
uint16_t backup_nexthop_num)
{
struct nexthop *nexthop = NULL;
- struct ipaddr vtep_ip;
struct interface *ifp;
int i;
char nhbuf[INET6_ADDRSTRLEN] = "";
@@ -1590,13 +1583,8 @@ static struct nexthop *nexthop_from_zapi(const struct zapi_nexthop *api_nh,
* the nexthop and associated MAC need to be installed.
*/
if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_EVPN)) {
- memset(&vtep_ip, 0, sizeof(vtep_ip));
- vtep_ip.ipa_type = IPADDR_V4;
- memcpy(&(vtep_ip.ipaddr_v4), &(api_nh->gate.ipv4),
- sizeof(struct in_addr));
- zebra_rib_queue_evpn_route_add(
- api_nh->vrf_id, &api_nh->rmac, &vtep_ip, p);
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_EVPN);
+ nexthop->rmac = api_nh->rmac;
}
break;
case NEXTHOP_TYPE_IPV6:
@@ -1624,13 +1612,8 @@ static struct nexthop *nexthop_from_zapi(const struct zapi_nexthop *api_nh,
* the nexthop and associated MAC need to be installed.
*/
if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_EVPN)) {
- memset(&vtep_ip, 0, sizeof(vtep_ip));
- vtep_ip.ipa_type = IPADDR_V6;
- memcpy(&vtep_ip.ipaddr_v6, &(api_nh->gate.ipv6),
- sizeof(struct in6_addr));
- zebra_rib_queue_evpn_route_add(
- api_nh->vrf_id, &api_nh->rmac, &vtep_ip, p);
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_EVPN);
+ nexthop->rmac = api_nh->rmac;
}
break;
case NEXTHOP_TYPE_BLACKHOLE:
@@ -1704,10 +1687,14 @@ static bool zapi_read_nexthops(struct zserv *client, struct prefix *p,
struct nexthop_group **png,
struct nhg_backup_info **pbnhg)
{
+ struct zapi_nexthop *znh;
struct nexthop_group *ng = NULL;
struct nhg_backup_info *bnhg = NULL;
uint16_t i;
struct nexthop *last_nh = NULL;
+ bool same_weight = true;
+ uint64_t max_weight = 0;
+ uint64_t tmp;
assert(!(png && pbnhg));
@@ -1722,6 +1709,41 @@ static bool zapi_read_nexthops(struct zserv *client, struct prefix *p,
bnhg = zebra_nhg_backup_alloc();
}
+ for (i = 0; i < nexthop_num; i++) {
+ znh = &nhops[i];
+
+ if (max_weight < znh->weight) {
+ if (i != 0 || znh->weight != 1)
+ same_weight = false;
+
+ max_weight = znh->weight;
+ }
+ }
+
+ /*
+ * Let's convert the weights to a scaled value
+ * between 1 and zrouter.nexthop_weight_scale_value
+ * This is a simple application of a ratio:
+ * scaled_weight/zrouter.nexthop_weight_scale_value =
+ * weight/max_weight
+ * This translates to:
+ * scaled_weight = weight * zrouter.nexthop_weight_scale_value
+ * -------------------------------------------
+ * max_weight
+ *
+ * This same formula is applied to both the nexthops
+ * and the backup nexthops
+ */
+ if (!same_weight) {
+ for (i = 0; i < nexthop_num; i++) {
+ znh = &nhops[i];
+
+ tmp = (uint64_t)znh->weight *
+ zrouter.nexthop_weight_scale_value;
+ znh->weight = MAX(1, ((uint32_t)(tmp / max_weight)));
+ }
+ }
+
/*
* TBD should _all_ of the nexthop add operations use
* api_nh->vrf_id instead of re->vrf_id ? I only changed
@@ -1800,7 +1822,8 @@ static bool zapi_read_nexthops(struct zserv *client, struct prefix *p,
if (IS_ZEBRA_DEBUG_RECV)
zlog_debug("%s: adding seg6", __func__);
- nexthop_add_srv6_seg6(nexthop, &api_nh->seg6_segs);
+ nexthop_add_srv6_seg6(nexthop, &api_nh->seg6_segs[0],
+ api_nh->seg_num);
}
if (IS_ZEBRA_DEBUG_RECV) {
@@ -1936,20 +1959,21 @@ static void zread_nhg_del(ZAPI_HANDLER_ARGS)
return;
}
- /*
- * Delete the received nhg id
- */
- nhe = zebra_nhg_proto_del(api_nhg.id, api_nhg.proto);
+ /* Create a temporary nhe */
+ nhe = zebra_nhg_alloc();
+ nhe->id = api_nhg.id;
+ nhe->type = api_nhg.proto;
+ nhe->zapi_instance = client->instance;
+ nhe->zapi_session = client->session_id;
- if (nhe) {
- zebra_nhg_decrement_ref(nhe);
- zsend_nhg_notify(api_nhg.proto, client->instance,
- client->session_id, api_nhg.id,
- ZAPI_NHG_REMOVED);
- } else
- zsend_nhg_notify(api_nhg.proto, client->instance,
- client->session_id, api_nhg.id,
- ZAPI_NHG_REMOVE_FAIL);
+ /* Sanity check - Empty nexthop and group */
+ nhe->nhg.nexthop = NULL;
+
+ /* Enqueue to workqueue for processing */
+ rib_queue_nhe_del(nhe);
+
+ /* Stats */
+ client->nhg_del_cnt++;
}
static void zread_nhg_add(ZAPI_HANDLER_ARGS)
@@ -1958,7 +1982,7 @@ static void zread_nhg_add(ZAPI_HANDLER_ARGS)
struct zapi_nhg api_nhg = {};
struct nexthop_group *nhg = NULL;
struct nhg_backup_info *bnhg = NULL;
- struct nhg_hash_entry *nhe;
+ struct nhg_hash_entry *nhe, *nhe_tmp;
s = msg;
if (zapi_nhg_decode(s, hdr->command, &api_nhg) < 0) {
@@ -2016,6 +2040,12 @@ static void zread_nhg_add(ZAPI_HANDLER_ARGS)
nexthop_group_delete(&nhg);
zebra_nhg_backup_free(&bnhg);
+ /* Stats */
+ nhe_tmp = zebra_nhg_lookup_id(api_nhg.id);
+ if (nhe_tmp)
+ client->nhg_upd8_cnt++;
+ else
+ client->nhg_add_cnt++;
}
static void zread_route_add(ZAPI_HANDLER_ARGS)
@@ -2275,7 +2305,7 @@ static void zread_router_id_add(ZAPI_HANDLER_ARGS)
}
/* Router-id information is needed. */
- vrf_bitmap_set(client->ridinfo[afi], zvrf_id(zvrf));
+ vrf_bitmap_set(&client->ridinfo[afi], zvrf_id(zvrf));
router_id_get(afi, &p, zvrf);
@@ -2311,7 +2341,7 @@ static void zread_router_id_delete(ZAPI_HANDLER_ARGS)
goto stream_failure;
}
- vrf_bitmap_unset(client->ridinfo[afi], zvrf_id(zvrf));
+ vrf_bitmap_unset(&client->ridinfo[afi], zvrf_id(zvrf));
stream_failure:
return;
@@ -2326,7 +2356,7 @@ static void zsend_capabilities(struct zserv *client, struct zebra_vrf *zvrf)
stream_putc(s, mpls_enabled);
stream_putl(s, zrouter.multipath_num);
stream_putc(s, zebra_mlag_get_role());
-
+ stream_putc(s, zrouter.v6_with_v4_nexthop);
stream_putw_at(s, 0, stream_get_endp(s));
zserv_send_message(client, s);
}
@@ -2353,23 +2383,19 @@ static void zread_hello(ZAPI_HANDLER_ARGS)
/* type of protocol (lib/zebra.h) */
uint8_t proto;
unsigned short instance;
- uint8_t notify;
uint8_t synchronous;
uint32_t session_id;
STREAM_GETC(msg, proto);
STREAM_GETW(msg, instance);
STREAM_GETL(msg, session_id);
- STREAM_GETC(msg, notify);
STREAM_GETC(msg, synchronous);
- if (notify)
- client->notify_owner = true;
if (synchronous)
client->synchronous = true;
/* accept only dynamic routing protocols */
- if ((proto < ZEBRA_ROUTE_MAX) && (proto > ZEBRA_ROUTE_CONNECT)) {
+ if ((proto < ZEBRA_ROUTE_MAX) && (proto > ZEBRA_ROUTE_LOCAL)) {
zlog_notice(
"client %d says hello and bids fair to announce only %s routes vrf=%u",
client->sock, zebra_route_string(proto),
@@ -2401,10 +2427,11 @@ static void zread_vrf_unregister(ZAPI_HANDLER_ARGS)
for (afi = AFI_IP; afi < AFI_MAX; afi++) {
for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
- vrf_bitmap_unset(client->redist[afi][i], zvrf_id(zvrf));
- vrf_bitmap_unset(client->redist_default[afi], zvrf_id(zvrf));
- vrf_bitmap_unset(client->ridinfo[afi], zvrf_id(zvrf));
- vrf_bitmap_unset(client->nhrp_neighinfo[afi], zvrf_id(zvrf));
+ vrf_bitmap_unset(&client->redist[afi][i],
+ zvrf_id(zvrf));
+ vrf_bitmap_unset(&client->redist_default[afi], zvrf_id(zvrf));
+ vrf_bitmap_unset(&client->ridinfo[afi], zvrf_id(zvrf));
+ vrf_bitmap_unset(&client->neighinfo[afi], zvrf_id(zvrf));
}
}
@@ -2984,7 +3011,7 @@ static void zread_srv6_manager_request(ZAPI_HANDLER_ARGS)
static void zread_pseudowire(ZAPI_HANDLER_ARGS)
{
struct stream *s;
- char ifname[INTERFACE_NAMSIZ];
+ char ifname[IFNAMSIZ];
ifindex_t ifindex;
int type;
int af;
@@ -3000,8 +3027,8 @@ static void zread_pseudowire(ZAPI_HANDLER_ARGS)
s = msg;
/* Get data. */
- STREAM_GET(ifname, s, INTERFACE_NAMSIZ);
- ifname[INTERFACE_NAMSIZ - 1] = '\0';
+ STREAM_GET(ifname, s, IFNAMSIZ);
+ ifname[IFNAMSIZ - 1] = '\0';
STREAM_GETL(s, ifindex);
STREAM_GETL(s, type);
STREAM_GETL(s, af);
@@ -3097,6 +3124,28 @@ stream_failure:
}
+static void zread_interface_set_arp(ZAPI_HANDLER_ARGS)
+{
+ struct stream *s = msg;
+ struct interface *ifp;
+ bool arp_enable;
+ vrf_id_t vrf_id = zvrf->vrf->vrf_id;
+ int ifindex;
+
+ STREAM_GETL(s, ifindex);
+ STREAM_GETC(s, arp_enable);
+ ifp = if_lookup_by_index(ifindex, vrf_id);
+
+ if (!ifp)
+ return;
+
+ if_arp(ifp, arp_enable);
+
+stream_failure:
+ return;
+}
+
+
static void zread_vrf_label(ZAPI_HANDLER_ARGS)
{
struct interface *ifp;
@@ -3179,7 +3228,6 @@ static inline void zread_rule(ZAPI_HANDLER_ARGS)
struct zebra_pbr_rule zpr;
struct stream *s;
uint32_t total, i;
- char ifname[INTERFACE_NAMSIZ + 1] = {};
s = msg;
STREAM_GETL(s, total);
@@ -3189,59 +3237,38 @@ static inline void zread_rule(ZAPI_HANDLER_ARGS)
zpr.sock = client->sock;
zpr.rule.vrf_id = hdr->vrf_id;
- STREAM_GETL(s, zpr.rule.seq);
- STREAM_GETL(s, zpr.rule.priority);
- STREAM_GETL(s, zpr.rule.unique);
- STREAM_GETC(s, zpr.rule.filter.ip_proto);
- STREAM_GETC(s, zpr.rule.filter.src_ip.family);
- STREAM_GETC(s, zpr.rule.filter.src_ip.prefixlen);
- STREAM_GET(&zpr.rule.filter.src_ip.u.prefix, s,
- prefix_blen(&zpr.rule.filter.src_ip));
- STREAM_GETW(s, zpr.rule.filter.src_port);
- STREAM_GETC(s, zpr.rule.filter.dst_ip.family);
- STREAM_GETC(s, zpr.rule.filter.dst_ip.prefixlen);
- STREAM_GET(&zpr.rule.filter.dst_ip.u.prefix, s,
- prefix_blen(&zpr.rule.filter.dst_ip));
- 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);
-
- strlcpy(zpr.ifname, ifname, sizeof(zpr.ifname));
- strlcpy(zpr.rule.ifname, ifname, sizeof(zpr.rule.ifname));
-
- if (!is_default_prefix(&zpr.rule.filter.src_ip))
- zpr.rule.filter.filter_bm |= PBR_FILTER_SRC_IP;
-
- if (!is_default_prefix(&zpr.rule.filter.dst_ip))
- zpr.rule.filter.filter_bm |= PBR_FILTER_DST_IP;
-
- if (zpr.rule.filter.src_port)
- zpr.rule.filter.filter_bm |= PBR_FILTER_SRC_PORT;
-
- if (zpr.rule.filter.dst_port)
- zpr.rule.filter.filter_bm |= PBR_FILTER_DST_PORT;
-
- if (zpr.rule.filter.dsfield)
- zpr.rule.filter.filter_bm |= PBR_FILTER_DSFIELD;
-
- if (zpr.rule.filter.ip_proto)
- zpr.rule.filter.filter_bm |= PBR_FILTER_IP_PROTOCOL;
-
- if (zpr.rule.filter.fwmark)
- zpr.rule.filter.filter_bm |= PBR_FILTER_FWMARK;
+ if (!zapi_pbr_rule_decode(s, &zpr.rule))
+ goto stream_failure;
+
+ strlcpy(zpr.ifname, zpr.rule.ifname, sizeof(zpr.ifname));
+
+ if ((zpr.rule.family != AF_INET) &&
+ (zpr.rule.family != AF_INET6)) {
+ zlog_warn("Unsupported PBR source IP family: %s (%hhu)",
+ family2str(zpr.rule.family), zpr.rule.family);
+ return;
+ }
+
+ /*
+ * Fixup filter src/dst IP addresses if they are unset
+ * because the netlink code currently obtains address family
+ * from them. Address family is used to specify which
+ * kernel database to use when adding/deleting rule.
+ *
+ * TBD: propagate zpr.rule.family into dataplane and
+ * netlink code so they can stop using filter src/dst addrs.
+ */
+ if (!CHECK_FLAG(zpr.rule.filter.filter_bm, PBR_FILTER_SRC_IP))
+ zpr.rule.filter.src_ip.family = zpr.rule.family;
+ if (!CHECK_FLAG(zpr.rule.filter.filter_bm, PBR_FILTER_DST_IP))
+ zpr.rule.filter.dst_ip.family = zpr.rule.family;
+
+ /* TBD delete below block when netlink code gets family from zpr.rule.family */
if (!(zpr.rule.filter.src_ip.family == AF_INET
|| zpr.rule.filter.src_ip.family == AF_INET6)) {
zlog_warn(
- "Unsupported PBR source IP family: %s (%hhu)",
+ "Unsupported PBR source IP family: %s (%u)",
family2str(zpr.rule.filter.src_ip.family),
zpr.rule.filter.src_ip.family);
return;
@@ -3249,11 +3276,12 @@ static inline void zread_rule(ZAPI_HANDLER_ARGS)
if (!(zpr.rule.filter.dst_ip.family == AF_INET
|| zpr.rule.filter.dst_ip.family == AF_INET6)) {
zlog_warn(
- "Unsupported PBR destination IP family: %s (%hhu)",
+ "Unsupported PBR destination IP family: %s (%u)",
family2str(zpr.rule.filter.dst_ip.family),
zpr.rule.filter.dst_ip.family);
return;
}
+ /* TBD delete above block when netlink code gets family from zpr.rule.family */
zpr.vrf_id = zvrf->vrf->vrf_id;
@@ -3508,7 +3536,7 @@ static inline void zread_ipset_entry(ZAPI_HANDLER_ARGS)
if (zpi.src_port_max != 0)
zpi.filter_bm |= PBR_FILTER_SRC_PORT_RANGE;
if (zpi.proto != 0)
- zpi.filter_bm |= PBR_FILTER_PROTO;
+ zpi.filter_bm |= PBR_FILTER_IP_PROTOCOL;
if (!(zpi.dst.family == AF_INET
|| zpi.dst.family == AF_INET6)) {
@@ -3557,7 +3585,7 @@ static inline void zebra_neigh_register(ZAPI_HANDLER_ARGS)
afi);
goto stream_failure;
}
- vrf_bitmap_set(client->nhrp_neighinfo[afi], zvrf_id(zvrf));
+ vrf_bitmap_set(&client->neighinfo[afi], zvrf_id(zvrf));
stream_failure:
return;
}
@@ -3573,7 +3601,7 @@ static inline void zebra_neigh_unregister(ZAPI_HANDLER_ARGS)
afi);
goto stream_failure;
}
- vrf_bitmap_unset(client->nhrp_neighinfo[afi], zvrf_id(zvrf));
+ vrf_bitmap_unset(&client->neighinfo[afi], zvrf_id(zvrf));
stream_failure:
return;
}
@@ -3899,6 +3927,7 @@ void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
[ZEBRA_REMOTE_MACIP_DEL] = zebra_vxlan_remote_macip_del,
[ZEBRA_DUPLICATE_ADDR_DETECTION] = zebra_vxlan_dup_addr_detection,
[ZEBRA_INTERFACE_SET_MASTER] = zread_interface_set_master,
+ [ZEBRA_INTERFACE_SET_ARP] = zread_interface_set_arp,
[ZEBRA_PW_ADD] = zread_pseudowire,
[ZEBRA_PW_DELETE] = zread_pseudowire,
[ZEBRA_PW_SET] = zread_pseudowire,
@@ -3930,8 +3959,8 @@ void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
[ZEBRA_EVPN_REMOTE_NH_DEL] = zebra_evpn_proc_remote_nh,
[ZEBRA_NEIGH_IP_ADD] = zebra_neigh_ip_add,
[ZEBRA_NEIGH_IP_DEL] = zebra_neigh_ip_del,
- [ZEBRA_NHRP_NEIGH_REGISTER] = zebra_neigh_register,
- [ZEBRA_NHRP_NEIGH_UNREGISTER] = zebra_neigh_unregister,
+ [ZEBRA_NEIGH_REGISTER] = zebra_neigh_register,
+ [ZEBRA_NEIGH_UNREGISTER] = zebra_neigh_unregister,
[ZEBRA_CONFIGURE_ARP] = zebra_configure_arp,
[ZEBRA_GRE_GET] = zebra_gre_get,
[ZEBRA_GRE_SOURCE_SET] = zebra_gre_source_set,
@@ -3976,8 +4005,7 @@ void zserv_handle_commands(struct zserv *client, struct stream_fifo *fifo)
hdr.length -= ZEBRA_HEADER_SIZE;
/* Before checking for a handler function, check for
- * special messages that are handled in another module;
- * we'll treat these as opaque.
+ * special messages that are handled the 'opaque zapi' module.
*/
if (zebra_opaque_handles_msgid(hdr.command)) {
/* Reset message buffer */
diff --git a/zebra/zapi_msg.h b/zebra/zapi_msg.h
index ce8e154465..43f734d26e 100644
--- a/zebra/zapi_msg.h
+++ b/zebra/zapi_msg.h
@@ -53,12 +53,11 @@ extern int zsend_interface_update(int cmd, struct zserv *client,
struct interface *ifp);
extern int zsend_redistribute_route(int cmd, struct zserv *zclient,
const struct route_node *rn,
- const struct route_entry *re);
+ const struct route_entry *re,
+ bool is_table_direct);
extern int zsend_router_id_update(struct zserv *zclient, afi_t afi,
struct prefix *p, vrf_id_t vrf_id);
-extern int zsend_interface_vrf_update(struct zserv *zclient,
- struct interface *ifp, vrf_id_t vrf_id);
extern int zsend_interface_link_params(struct zserv *zclient,
struct interface *ifp);
extern int zsend_pw_update(struct zserv *client, struct zebra_pw *pw);
@@ -92,9 +91,9 @@ extern int zsend_label_manager_connect_response(struct zserv *client,
extern int zsend_sr_policy_notify_status(uint32_t color,
struct ipaddr *endpoint, char *name,
int status);
-extern void zsend_nhrp_neighbor_notify(int cmd, struct interface *ifp,
- struct ipaddr *ipaddr, int ndm_state,
- union sockunion *link_layer_ipv4);
+extern void zsend_neighbor_notify(int cmd, struct interface *ifp,
+ struct ipaddr *ipaddr, int ndm_state,
+ union sockunion *link_layer_ipv4, int ip_len);
extern int zsend_client_close_notify(struct zserv *client,
struct zserv *closed_client);
diff --git a/zebra/zebra_affinitymap.c b/zebra/zebra_affinitymap.c
index ae0f9a8a35..79bc78a7dc 100644
--- a/zebra/zebra_affinitymap.c
+++ b/zebra/zebra_affinitymap.c
@@ -26,102 +26,26 @@
#include "zebra/redistribute.h"
#include "zebra/zebra_affinitymap.h"
-static bool zebra_affinity_map_check_use(const char *affmap_name)
-{
- char xpath[XPATH_MAXLEN];
- struct interface *ifp;
- struct vrf *vrf;
-
- RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
- FOR_ALL_INTERFACES (vrf, ifp) {
- snprintf(xpath, sizeof(xpath),
- "/frr-interface:lib/interface[name='%s']",
- ifp->name);
- if (!yang_dnode_exists(running_config->dnode, xpath))
- continue;
- snprintf(
- xpath, sizeof(xpath),
- "/frr-interface:lib/interface[name='%s']/frr-zebra:zebra/link-params/affinities[affinity='%s']",
- ifp->name, affmap_name);
- if (yang_dnode_exists(running_config->dnode, xpath))
- return true;
- }
- }
- return false;
-}
-
-static bool zebra_affinity_map_check_update(const char *affmap_name,
- uint16_t new_pos)
-{
- char xpath[XPATH_MAXLEN];
- struct interface *ifp;
- struct vrf *vrf;
-
- /* check whether the affinity-map new bit position is upper than 31
- * but is used on an interface on which affinity-mode is standard.
- * Return false if the change is not possible.
- */
- if (new_pos < 32)
- return true;
-
- RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
- FOR_ALL_INTERFACES (vrf, ifp) {
- snprintf(xpath, sizeof(xpath),
- "/frr-interface:lib/interface[name='%s']",
- ifp->name);
- if (!yang_dnode_exists(running_config->dnode, xpath))
- continue;
- snprintf(
- xpath, sizeof(xpath),
- "/frr-interface:lib/interface[name='%s']/frr-zebra:zebra/link-params/affinities[affinity='%s']",
- ifp->name, affmap_name);
- if (!yang_dnode_exists(running_config->dnode, xpath))
- continue;
- if (yang_dnode_get_enum(
- running_config->dnode,
- "/frr-interface:lib/interface[name='%s']/frr-zebra:zebra/link-params/affinity-mode",
- ifp->name) == AFFINITY_MODE_STANDARD)
- return false;
- }
- }
- return true;
-}
-
static void zebra_affinity_map_update(const char *affmap_name, uint16_t old_pos,
uint16_t new_pos)
{
struct if_link_params *iflp;
- enum affinity_mode aff_mode;
- char xpath[XPATH_MAXLEN];
struct interface *ifp;
struct vrf *vrf;
RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
FOR_ALL_INTERFACES (vrf, ifp) {
- snprintf(xpath, sizeof(xpath),
- "/frr-interface:lib/interface[name='%s']",
- ifp->name);
- if (!yang_dnode_exists(running_config->dnode, xpath))
- continue;
- snprintf(
- xpath, sizeof(xpath),
- "/frr-interface:lib/interface[name='%s']/frr-zebra:zebra/link-params/affinities[affinity='%s']",
- ifp->name, affmap_name);
- if (!yang_dnode_exists(running_config->dnode, xpath))
- continue;
- aff_mode = yang_dnode_get_enum(
- running_config->dnode,
- "/frr-interface:lib/interface[name='%s']/frr-zebra:zebra/link-params/affinity-mode",
- ifp->name);
iflp = if_link_params_get(ifp);
- if (aff_mode == AFFINITY_MODE_EXTENDED ||
- aff_mode == AFFINITY_MODE_BOTH) {
+ if (!iflp)
+ continue;
+ if (IS_PARAM_SET(iflp, LP_EXTEND_ADM_GRP) &&
+ admin_group_get(&iflp->ext_admin_grp, old_pos)) {
admin_group_unset(&iflp->ext_admin_grp,
old_pos);
admin_group_set(&iflp->ext_admin_grp, new_pos);
}
- if (aff_mode == AFFINITY_MODE_STANDARD ||
- aff_mode == AFFINITY_MODE_BOTH) {
+ if (IS_PARAM_SET(iflp, LP_ADM_GRP) &&
+ (iflp->admin_grp & (1 << old_pos))) {
iflp->admin_grp &= ~(1 << old_pos);
if (new_pos < 32)
iflp->admin_grp |= 1 << new_pos;
@@ -138,7 +62,5 @@ void zebra_affinity_map_init(void)
{
affinity_map_init();
- affinity_map_set_check_use_hook(zebra_affinity_map_check_use);
- affinity_map_set_check_update_hook(zebra_affinity_map_check_update);
affinity_map_set_update_hook(zebra_affinity_map_update);
}
diff --git a/zebra/zebra_cli.c b/zebra/zebra_cli.c
new file mode 100644
index 0000000000..00e0a49cb8
--- /dev/null
+++ b/zebra/zebra_cli.c
@@ -0,0 +1,2984 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "command.h"
+#include "defaults.h"
+#include "northbound_cli.h"
+#include "vrf.h"
+
+#include "zebra_cli.h"
+#include "zebra/zebra_cli_clippy.c"
+
+#define EVPN_MH_VTY_STR "Multihoming\n"
+
+FRR_CFG_DEFAULT_BOOL(ZEBRA_IP_NHT_RESOLVE_VIA_DEFAULT,
+ { .val_bool = true, .match_profile = "traditional", },
+ { .val_bool = false },
+);
+
+#if HAVE_BFDD == 0
+DEFPY_YANG (zebra_ptm_enable,
+ zebra_ptm_enable_cmd,
+ "[no] ptm-enable",
+ NO_STR
+ "Enable neighbor check with specified topology\n")
+{
+ nb_cli_enqueue_change(vty, "/frr-zebra:zebra/ptm-enable", NB_OP_MODIFY,
+ no ? "false" : "true");
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void zebra_ptm_enable_cli_write(struct vty *vty,
+ const struct lyd_node *dnode,
+ bool show_defaults)
+{
+ bool enable = yang_dnode_get_bool(dnode, NULL);
+
+ if (enable)
+ vty_out(vty, "ptm-enable\n");
+ else if (show_defaults)
+ vty_out(vty, "no ptm-enable\n");
+}
+#endif
+
+DEFPY_YANG (zebra_route_map_timer,
+ zebra_route_map_timer_cmd,
+ "[no] zebra route-map delay-timer ![(0-600)$delay]",
+ NO_STR
+ ZEBRA_STR
+ "Set route-map parameters\n"
+ "Time to wait before route-map updates are processed\n"
+ "0 means route-map changes are run immediately instead of delaying\n")
+{
+ if (!no)
+ nb_cli_enqueue_change(vty, "/frr-zebra:zebra/route-map-delay",
+ NB_OP_MODIFY, delay_str);
+ else
+ nb_cli_enqueue_change(vty, "/frr-zebra:zebra/route-map-delay",
+ NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void zebra_route_map_delay_cli_write(struct vty *vty,
+ const struct lyd_node *dnode,
+ bool show_defaults)
+{
+ uint32_t delay = yang_dnode_get_uint32(dnode, NULL);
+
+ vty_out(vty, "zebra route-map delay-timer %u\n", delay);
+}
+
+DEFPY_YANG (multicast_new,
+ multicast_new_cmd,
+ "[no] multicast <enable$on|disable$off>",
+ NO_STR
+ "Control multicast flag on interface\n"
+ "Set multicast flag on interface\n"
+ "Unset multicast flag on interface\n")
+{
+ if (!no)
+ nb_cli_enqueue_change(vty, "./frr-zebra:zebra/multicast",
+ NB_OP_CREATE, on ? "true" : "false");
+ else
+ nb_cli_enqueue_change(vty, "./frr-zebra:zebra/multicast",
+ NB_OP_DESTROY, NULL);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void lib_interface_zebra_multicast_cli_write(struct vty *vty,
+ const struct lyd_node *dnode,
+ bool show_defaults)
+{
+ bool multicast = yang_dnode_get_bool(dnode, NULL);
+
+ if (multicast)
+ vty_out(vty, " multicast enable\n");
+ else
+ vty_out(vty, " multicast disable\n");
+}
+
+/* Deprecated multicast commands */
+
+DEFPY_YANG_HIDDEN (multicast,
+ multicast_cmd,
+ "[no] multicast",
+ NO_STR
+ "Set multicast flag to interface\n")
+{
+ nb_cli_enqueue_change(vty, "./frr-zebra:zebra/multicast",
+ NB_OP_CREATE, no ? "false" : "true");
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFPY_YANG (mpls,
+ mpls_cmd,
+ "[no] mpls <enable$on|disable$off>",
+ NO_STR
+ MPLS_STR
+ "Set mpls to be on for the interface\n"
+ "Set mpls to be off for the interface\n")
+{
+ if (!no)
+ nb_cli_enqueue_change(vty, "./frr-zebra:zebra/mpls",
+ NB_OP_CREATE, on ? "true" : "false");
+ else
+ nb_cli_enqueue_change(vty, "./frr-zebra:zebra/mpls",
+ NB_OP_DESTROY, NULL);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void lib_interface_zebra_mpls_cli_write(struct vty *vty,
+ const struct lyd_node *dnode,
+ bool show_defaults)
+{
+ bool mpls = yang_dnode_get_bool(dnode, NULL);
+
+ if (mpls)
+ vty_out(vty, " mpls enable\n");
+ else
+ vty_out(vty, " mpls disable\n");
+}
+
+DEFPY_YANG (linkdetect,
+ linkdetect_cmd,
+ "[no] link-detect",
+ NO_STR
+ "Enable link detection on interface\n")
+{
+ nb_cli_enqueue_change(vty, "./frr-zebra:zebra/link-detect",
+ NB_OP_CREATE, no ? "false" : "true");
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void lib_interface_zebra_link_detect_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ bool link_detect = yang_dnode_get_bool(dnode, NULL);
+
+ if (!link_detect)
+ vty_out(vty, " no link-detect\n");
+ else if (show_defaults)
+ vty_out(vty, " link-detect\n");
+}
+
+DEFPY_YANG (shutdown_if,
+ shutdown_if_cmd,
+ "[no] shutdown",
+ NO_STR
+ "Shutdown the selected interface\n")
+{
+ nb_cli_enqueue_change(vty, "./frr-zebra:zebra/enabled", NB_OP_CREATE,
+ no ? "true" : "false");
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void lib_interface_zebra_enabled_cli_write(struct vty *vty,
+ const struct lyd_node *dnode,
+ bool show_defaults)
+{
+ bool enabled = yang_dnode_get_bool(dnode, NULL);
+
+ if (!enabled)
+ vty_out(vty, " shutdown\n");
+ else if (show_defaults)
+ vty_out(vty, " no shutdown\n");
+}
+
+DEFPY_YANG (bandwidth_if,
+ bandwidth_if_cmd,
+ "[no] bandwidth ![(1-1000000)]$bw",
+ NO_STR
+ "Set bandwidth informational parameter\n"
+ "Bandwidth in megabits\n")
+{
+ if (!no)
+ nb_cli_enqueue_change(vty, "./frr-zebra:zebra/bandwidth",
+ NB_OP_CREATE, bw_str);
+ else
+ nb_cli_enqueue_change(vty, "./frr-zebra:zebra/bandwidth",
+ NB_OP_DESTROY, NULL);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void lib_interface_zebra_bandwidth_cli_write(struct vty *vty,
+ const struct lyd_node *dnode,
+ bool show_defaults)
+{
+ uint32_t bandwidth = yang_dnode_get_uint32(dnode, NULL);
+
+ vty_out(vty, " bandwidth %u\n", bandwidth);
+}
+
+DEFUN_YANG_NOSH (link_params,
+ link_params_cmd,
+ "link-params",
+ LINK_PARAMS_STR)
+{
+ int ret;
+
+ nb_cli_enqueue_change(vty, "./frr-zebra:zebra/link-params",
+ NB_OP_CREATE, NULL);
+
+ ret = nb_cli_apply_changes(vty, NULL);
+ if (ret == CMD_SUCCESS) {
+ char *xpath;
+
+ xpath = asprintfrr(MTYPE_TMP, "%s/frr-zebra:zebra/link-params",
+ VTY_CURR_XPATH);
+ VTY_PUSH_XPATH(LINK_PARAMS_NODE, xpath);
+ XFREE(MTYPE_TMP, xpath);
+ }
+
+ return ret;
+}
+
+DEFUN_NOSH (exit_link_params,
+ exit_link_params_cmd,
+ "exit-link-params",
+ "Exit from Link Params configuration mode\n")
+{
+ cmd_exit(vty);
+ return CMD_SUCCESS;
+}
+
+static void lib_interface_zebra_link_params_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ vty_out(vty, " link-params\n");
+}
+
+static void
+lib_interface_zebra_link_params_cli_write_end(struct vty *vty,
+ const struct lyd_node *dnode)
+{
+ vty_out(vty, " exit-link-params\n");
+}
+
+DEFUN_YANG (no_link_params,
+ no_link_params_cmd,
+ "no link-params",
+ NO_STR
+ LINK_PARAMS_STR)
+{
+ nb_cli_enqueue_change(vty, "./frr-zebra:zebra/link-params", NB_OP_DESTROY, NULL);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+/* [no] enable is deprecated, link-params is enabled when entering the node. */
+
+DEFUN_YANG_HIDDEN (link_params_enable,
+ link_params_enable_cmd,
+ "enable",
+ "Activate link parameters on this interface\n")
+{
+ vty_out(vty, "This command is deprecated. Link parameters are activated when \"link-params\" node is entered.\n");
+
+ return CMD_SUCCESS;
+}
+
+DEFUN_YANG_NOSH (no_link_params_enable,
+ no_link_params_enable_cmd,
+ "no enable",
+ NO_STR
+ "Disable link parameters on this interface\n")
+{
+ int ret;
+
+ vty_out(vty, "This command is deprecated. To disable link parameters use \"no link-params\" in the interface node.\n");
+
+ nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
+
+ ret = nb_cli_apply_changes(vty, NULL);
+ if (ret == CMD_SUCCESS)
+ cmd_exit(vty);
+
+ return ret;
+}
+
+DEFPY_YANG (link_params_metric,
+ link_params_metric_cmd,
+ "[no] metric ![(0-4294967295)]$metric",
+ NO_STR
+ "Link metric for MPLS-TE purpose\n"
+ "Metric value in decimal\n")
+{
+ if (!no)
+ nb_cli_enqueue_change(vty, "./metric", NB_OP_MODIFY, metric_str);
+ else
+ nb_cli_enqueue_change(vty, "./metric", NB_OP_DESTROY, NULL);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void lib_interface_zebra_link_params_metric_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ uint32_t metric = yang_dnode_get_uint32(dnode, NULL);
+
+ vty_out(vty, " metric %u\n", metric);
+}
+
+DEFPY_YANG (link_params_maxbw,
+ link_params_maxbw_cmd,
+ "max-bw BANDWIDTH",
+ "Maximum bandwidth that can be used\n"
+ "Bytes/second (IEEE floating point format)\n")
+{
+ char value[YANG_VALUE_MAXLEN];
+ float bw;
+
+ if (sscanf(bandwidth, "%g", &bw) != 1) {
+ vty_out(vty, "Invalid bandwidth value\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ snprintf(value, sizeof(value), "%a", bw);
+
+ nb_cli_enqueue_change(vty, "./max-bandwidth", NB_OP_MODIFY, value);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void lib_interface_zebra_link_params_max_bandwidth_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ float max_bandwidth = yang_dnode_get_bandwidth_ieee_float32(dnode, NULL);
+
+ vty_out(vty, " max-bw %g\n", max_bandwidth);
+}
+
+DEFPY_YANG (link_params_max_rsv_bw,
+ link_params_max_rsv_bw_cmd,
+ "max-rsv-bw BANDWIDTH",
+ "Maximum bandwidth that may be reserved\n"
+ "Bytes/second (IEEE floating point format)\n")
+{
+ char value[YANG_VALUE_MAXLEN];
+ float bw;
+
+ if (sscanf(bandwidth, "%g", &bw) != 1) {
+ vty_out(vty, "Invalid bandwidth value\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ snprintf(value, sizeof(value), "%a", bw);
+
+ nb_cli_enqueue_change(vty, "./max-reservable-bandwidth", NB_OP_MODIFY,
+ value);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void lib_interface_zebra_link_params_max_reservable_bandwidth_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ float max_reservable_bandwidth =
+ yang_dnode_get_bandwidth_ieee_float32(dnode, NULL);
+
+ vty_out(vty, " max-rsv-bw %g\n", max_reservable_bandwidth);
+}
+
+DEFPY_YANG (link_params_unrsv_bw,
+ link_params_unrsv_bw_cmd,
+ "unrsv-bw (0-7)$priority BANDWIDTH",
+ "Unreserved bandwidth at each priority level\n"
+ "Priority\n"
+ "Bytes/second (IEEE floating point format)\n")
+{
+ char xpath[XPATH_MAXLEN];
+ char value[YANG_VALUE_MAXLEN];
+ float bw;
+
+ if (sscanf(bandwidth, "%g", &bw) != 1) {
+ vty_out(vty, "Invalid bandwidth value\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ snprintf(xpath, sizeof(xpath),
+ "./unreserved-bandwidths/unreserved-bandwidth[priority='%s']/unreserved-bandwidth",
+ priority_str);
+ snprintf(value, sizeof(value), "%a", bw);
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, value);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void
+lib_interface_zebra_link_params_unreserved_bandwidths_unreserved_bandwidth_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ uint8_t priority = yang_dnode_get_uint8(dnode, "priority");
+ float unreserved_bandwidth =
+ yang_dnode_get_bandwidth_ieee_float32(dnode,
+ "unreserved-bandwidth");
+
+ vty_out(vty, " unrsv-bw %u %g\n", priority, unreserved_bandwidth);
+}
+
+DEFPY_YANG (link_params_admin_grp,
+ link_params_admin_grp_cmd,
+ "[no] admin-grp ![BITPATTERN]",
+ NO_STR
+ "Administrative group membership\n"
+ "32-bit Hexadecimal value (e.g. 0xa1)\n")
+{
+ uint32_t value;
+ char value_str[YANG_VALUE_MAXLEN];
+
+ if (!no) {
+ assert(bitpattern);
+
+ if (bitpattern[0] != '0' || bitpattern[1] != 'x' ||
+ strlen(bitpattern) > 10) {
+ vty_out(vty, "Invalid bitpattern value\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ if (sscanf(bitpattern, "%x", &value) != 1) {
+ vty_out(vty, "Invalid bitpattern value\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ snprintf(value_str, sizeof(value_str), "%u", value);
+
+ nb_cli_enqueue_change(vty, "./legacy-admin-group", NB_OP_MODIFY,
+ value_str);
+ } else {
+ nb_cli_enqueue_change(vty, "./legacy-admin-group",
+ NB_OP_DESTROY, NULL);
+ }
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void lib_interface_zebra_link_params_legacy_admin_group_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ vty_out(vty, " admin-grp %#x\n", yang_dnode_get_uint32(dnode, NULL));
+}
+
+/* RFC5392 & RFC5316: INTER-AS */
+DEFPY_YANG (link_params_inter_as,
+ link_params_inter_as_cmd,
+ "[no] neighbor ![A.B.C.D$ip as (1-4294967295)$as]",
+ NO_STR
+ "Configure remote ASBR information (Neighbor IP address and AS number)\n"
+ "Remote IP address in dot decimal A.B.C.D\n"
+ "Remote AS number\n"
+ "AS number in the range <1-4294967295>\n")
+{
+ if (!no) {
+ nb_cli_enqueue_change(vty, "./neighbor", NB_OP_CREATE, NULL);
+ nb_cli_enqueue_change(vty, "./neighbor/remote-as", NB_OP_MODIFY,
+ as_str);
+ nb_cli_enqueue_change(vty, "./neighbor/ipv4-remote-id",
+ NB_OP_MODIFY, ip_str);
+ } else {
+ nb_cli_enqueue_change(vty, "./neighbor", NB_OP_DESTROY, NULL);
+ }
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void lib_interface_zebra_link_params_neighbor_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ uint32_t remote_as = yang_dnode_get_uint32(dnode, "remote-as");
+ const char *ipv4_remote_id = yang_dnode_get_string(dnode,
+ "ipv4-remote-id");
+
+ vty_out(vty, " neighbor %s as %u\n", ipv4_remote_id, remote_as);
+}
+
+/* RFC7471 & RFC8570 */
+DEFPY_YANG (link_params_delay,
+ link_params_delay_cmd,
+ "[no] delay ![(0-16777215)$delay [min (0-16777215)$min max (0-16777215)$max]]",
+ NO_STR
+ "Unidirectional Average Link Delay\n"
+ "Average delay in micro-second as decimal (0...16777215)\n"
+ "Minimum delay\n"
+ "Minimum delay in micro-second as decimal (0...16777215)\n"
+ "Maximum delay\n"
+ "Maximum delay in micro-second as decimal (0...16777215)\n")
+{
+ if (!no) {
+ nb_cli_enqueue_change(vty, "./delay", NB_OP_MODIFY, delay_str);
+ if (min_str && max_str) {
+ nb_cli_enqueue_change(vty, "./min-max-delay",
+ NB_OP_CREATE, NULL);
+ nb_cli_enqueue_change(vty, "./min-max-delay/delay-min",
+ NB_OP_MODIFY, min_str);
+ nb_cli_enqueue_change(vty, "./min-max-delay/delay-max",
+ NB_OP_MODIFY, max_str);
+ } else {
+ nb_cli_enqueue_change(vty, "./min-max-delay",
+ NB_OP_DESTROY, NULL);
+ }
+ } else {
+ nb_cli_enqueue_change(vty, "./delay", NB_OP_DESTROY, NULL);
+ nb_cli_enqueue_change(vty, "./min-max-delay", NB_OP_DESTROY,
+ NULL);
+ }
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void lib_interface_zebra_link_params_delay_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ uint32_t delay = yang_dnode_get_uint32(dnode, NULL);
+
+ vty_out(vty, " delay %u", delay);
+
+ if (yang_dnode_exists(dnode, "../min-max-delay")) {
+ uint32_t delay_min =
+ yang_dnode_get_uint32(dnode,
+ "../min-max-delay/delay-min");
+ uint32_t delay_max =
+ yang_dnode_get_uint32(dnode,
+ "../min-max-delay/delay-max");
+
+ vty_out(vty, " min %u max %u", delay_min, delay_max);
+ }
+
+ vty_out(vty, "\n");
+}
+
+DEFPY_YANG (link_params_delay_var,
+ link_params_delay_var_cmd,
+ "[no] delay-variation ![(0-16777215)$delay_var]",
+ NO_STR
+ "Unidirectional Link Delay Variation\n"
+ "delay variation in micro-second as decimal (0...16777215)\n")
+{
+ if (!no)
+ nb_cli_enqueue_change(vty, "./delay-variation", NB_OP_MODIFY,
+ delay_var_str);
+ else
+ nb_cli_enqueue_change(vty, "./delay-variation", NB_OP_DESTROY,
+ NULL);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void lib_interface_zebra_link_params_delay_variation_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ uint32_t delay_variation = yang_dnode_get_uint32(dnode, NULL);
+
+ vty_out(vty, " delay-variation %u\n", delay_variation);
+}
+
+DEFPY_YANG(
+ link_params_pkt_loss, link_params_pkt_loss_cmd,
+ "[no] packet-loss ![PERCENTAGE]",
+ NO_STR
+ "Unidirectional Link Packet Loss\n"
+ "percentage of total traffic by 0.000003% step and less than 50.331642%\n")
+{
+ if (!no)
+ nb_cli_enqueue_change(vty, "./packet-loss", NB_OP_MODIFY,
+ percentage);
+ else
+ nb_cli_enqueue_change(vty, "./packet-loss", NB_OP_DESTROY, NULL);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void lib_interface_zebra_link_params_packet_loss_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ double packet_loss = yang_dnode_get_dec64(dnode, NULL);
+
+ vty_out(vty, " packet-loss %lf\n", packet_loss);
+}
+
+DEFPY_YANG (link_params_res_bw,
+ link_params_res_bw_cmd,
+ "[no] res-bw ![BANDWIDTH]",
+ NO_STR
+ "Unidirectional Residual Bandwidth\n"
+ "Bytes/second (IEEE floating point format)\n")
+{
+ char value[YANG_VALUE_MAXLEN];
+ float bw;
+
+ if (!no) {
+ assert(bandwidth);
+
+ if (sscanf(bandwidth, "%g", &bw) != 1) {
+ vty_out(vty, "Invalid bandwidth value\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ snprintf(value, sizeof(value), "%a", bw);
+
+ nb_cli_enqueue_change(vty, "./residual-bandwidth", NB_OP_MODIFY,
+ value);
+ } else {
+ nb_cli_enqueue_change(vty, "./residual-bandwidth",
+ NB_OP_DESTROY, NULL);
+ }
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void lib_interface_zebra_link_params_residual_bandwidth_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ float residual_bandwidth = yang_dnode_get_bandwidth_ieee_float32(dnode,
+ NULL);
+
+ vty_out(vty, " res-bw %g\n", residual_bandwidth);
+}
+
+DEFPY_YANG (link_params_ava_bw,
+ link_params_ava_bw_cmd,
+ "[no] ava-bw ![BANDWIDTH]",
+ NO_STR
+ "Unidirectional Available Bandwidth\n"
+ "Bytes/second (IEEE floating point format)\n")
+{
+ char value[YANG_VALUE_MAXLEN];
+ float bw;
+
+ if (!no) {
+ assert(bandwidth);
+
+ if (sscanf(bandwidth, "%g", &bw) != 1) {
+ vty_out(vty, "Invalid bandwidth value\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ snprintf(value, sizeof(value), "%a", bw);
+
+ nb_cli_enqueue_change(vty, "./available-bandwidth",
+ NB_OP_MODIFY, value);
+ } else {
+ nb_cli_enqueue_change(vty, "./available-bandwidth",
+ NB_OP_DESTROY, NULL);
+ }
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void lib_interface_zebra_link_params_available_bandwidth_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ float available_bandwidth = yang_dnode_get_bandwidth_ieee_float32(dnode,
+ NULL);
+
+ vty_out(vty, " ava-bw %g\n", available_bandwidth);
+}
+
+DEFPY_YANG (link_params_use_bw,
+ link_params_use_bw_cmd,
+ "[no] use-bw ![BANDWIDTH]",
+ NO_STR
+ "Unidirectional Utilised Bandwidth\n"
+ "Bytes/second (IEEE floating point format)\n")
+{
+ char value[YANG_VALUE_MAXLEN];
+ float bw;
+
+ if (!no) {
+ assert(bandwidth);
+
+ if (sscanf(bandwidth, "%g", &bw) != 1) {
+ vty_out(vty, "Invalid bandwidth value\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ snprintf(value, sizeof(value), "%a", bw);
+
+ nb_cli_enqueue_change(vty, "./utilized-bandwidth", NB_OP_MODIFY,
+ value);
+ } else {
+ nb_cli_enqueue_change(vty, "./utilized-bandwidth",
+ NB_OP_DESTROY, NULL);
+ }
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void lib_interface_zebra_link_params_utilized_bandwidth_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ float utilized_bandwidth = yang_dnode_get_bandwidth_ieee_float32(dnode,
+ NULL);
+
+ vty_out(vty, " use-bw %g\n", utilized_bandwidth);
+}
+
+DEFPY_YANG (link_params_affinity,
+ link_params_affinity_cmd,
+ "[no] affinity NAME...",
+ NO_STR
+ "Interface affinities\n"
+ "Affinity names\n")
+{
+ char xpath[XPATH_MAXLEN];
+ int i;
+
+ for (i = no ? 2 : 1; i < argc; i++) {
+ snprintf(xpath, XPATH_MAXLEN, "./affinities/affinity[.='%s']",
+ argv[i]->arg);
+ nb_cli_enqueue_change(vty, xpath,
+ no ? NB_OP_DESTROY : NB_OP_CREATE, NULL);
+ }
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static int ag_iter_cb(const struct lyd_node *dnode, void *arg)
+{
+ struct vty *vty = arg;
+
+ vty_out(vty, " %s", yang_dnode_get_string(dnode, NULL));
+ return YANG_ITER_CONTINUE;
+}
+
+static void lib_interface_zebra_link_params_affinities_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ vty_out(vty, " affinity");
+ yang_dnode_iterate(ag_iter_cb, vty, dnode, "affinity");
+ vty_out(vty, "\n");
+}
+
+DEFPY_YANG (link_params_affinity_mode,
+ link_params_affinity_mode_cmd,
+ "[no] affinity-mode ![<standard|extended|both>$mode]",
+ NO_STR
+ "Interface affinity mode\n"
+ "Standard Admin-Group only RFC3630,5305,5329\n"
+ "Extended Admin-Group only RFC7308 (default)\n"
+ "Standard and extended Admin-Group format\n")
+{
+ if (!no)
+ nb_cli_enqueue_change(vty, "./affinity-mode", NB_OP_MODIFY,
+ mode);
+ else
+ nb_cli_enqueue_change(vty, "./affinity-mode", NB_OP_DESTROY,
+ NULL);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void lib_interface_zebra_link_params_affinity_mode_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ enum affinity_mode affinity_mode = yang_dnode_get_enum(dnode, NULL);
+
+ if (affinity_mode == AFFINITY_MODE_STANDARD)
+ vty_out(vty, " affinity-mode standard\n");
+ else if (affinity_mode == AFFINITY_MODE_BOTH)
+ vty_out(vty, " affinity-mode both\n");
+ else if (affinity_mode == AFFINITY_MODE_EXTENDED && show_defaults)
+ vty_out(vty, " affinity-mode extended\n");
+}
+
+#ifdef HAVE_NETLINK
+DEFPY_YANG (ip_address,
+ ip_address_cmd,
+ "[no] ip address A.B.C.D/M [label LINE$label]",
+ NO_STR
+ "Interface Internet Protocol config commands\n"
+ "Set the IP address of an interface\n"
+ "IP address (e.g. 10.0.0.1/8)\n"
+ "Label of this address\n"
+ "Label\n")
+#else
+DEFPY_YANG (ip_address,
+ ip_address_cmd,
+ "[no] ip address A.B.C.D/M",
+ NO_STR
+ "Interface Internet Protocol config commands\n"
+ "Set the IP address of an interface\n"
+ "IP address (e.g. 10.0.0.1/8)\n")
+#endif
+{
+ char ip[INET_ADDRSTRLEN + 3];
+ char *mask;
+
+ if (no) {
+ nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
+ } else {
+ nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
+#ifdef HAVE_NETLINK
+ if (label)
+ nb_cli_enqueue_change(vty, "./label", NB_OP_MODIFY,
+ label);
+ else
+ nb_cli_enqueue_change(vty, "./label", NB_OP_DESTROY,
+ NULL);
+#endif
+ }
+
+ strlcpy(ip, address_str, sizeof(ip));
+
+ mask = strchr(ip, '/');
+ assert(mask);
+ *mask = 0;
+ mask++;
+
+ return nb_cli_apply_changes(vty,
+ "./frr-zebra:zebra/ipv4-addrs[ip='%s'][prefix-length='%s']",
+ ip, mask);
+}
+
+static void lib_interface_zebra_ipv4_addrs_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ const char *ip = yang_dnode_get_string(dnode, "ip");
+ uint8_t prefix_length = yang_dnode_get_uint8(dnode, "prefix-length");
+
+ vty_out(vty, " ip address %s/%u", ip, prefix_length);
+
+ if (yang_dnode_exists(dnode, "label")) {
+ const char *label = yang_dnode_get_string(dnode, "label");
+
+ vty_out(vty, " label %s", label);
+ }
+
+ vty_out(vty, "\n");
+}
+
+#ifdef HAVE_NETLINK
+DEFPY_YANG (ip_address_peer,
+ ip_address_peer_cmd,
+ "[no] ip address A.B.C.D peer A.B.C.D/M [label LINE$label]",
+ NO_STR
+ "Interface Internet Protocol config commands\n"
+ "Set the IP address of an interface\n"
+ "Local IP (e.g. 10.0.0.1) for P-t-P address\n"
+ "Specify P-t-P address\n"
+ "Peer IP address (e.g. 10.0.0.1/8)\n"
+ "Label of this address\n"
+ "Label\n")
+#else
+DEFPY_YANG (ip_address_peer,
+ ip_address_peer_cmd,
+ "[no] ip address A.B.C.D peer A.B.C.D/M",
+ NO_STR
+ "Interface Internet Protocol config commands\n"
+ "Set the IP address of an interface\n"
+ "Local IP (e.g. 10.0.0.1) for P-t-P address\n"
+ "Specify P-t-P address\n"
+ "Peer IP address (e.g. 10.0.0.1/8)\n")
+#endif
+{
+ char peer_ip[INET_ADDRSTRLEN + 3];
+ char *peer_mask;
+
+ if (no) {
+ nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
+ } else {
+ nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
+#ifdef HAVE_NETLINK
+ if (label)
+ nb_cli_enqueue_change(vty, "./label", NB_OP_MODIFY,
+ label);
+ else
+ nb_cli_enqueue_change(vty, "./label", NB_OP_DESTROY,
+ NULL);
+#endif
+ }
+
+ strlcpy(peer_ip, peer_str, sizeof(peer_ip));
+
+ peer_mask = strchr(peer_ip, '/');
+ assert(peer_mask);
+ *peer_mask = 0;
+ peer_mask++;
+
+ return nb_cli_apply_changes(
+ vty,
+ "./frr-zebra:zebra/ipv4-p2p-addrs[ip='%s'][peer-ip='%s'][peer-prefix-length='%s']",
+ address_str, peer_ip, peer_mask);
+}
+
+static void lib_interface_zebra_ipv4_p2p_addrs_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ const char *ip = yang_dnode_get_string(dnode, "ip");
+ const char *peer_ip = yang_dnode_get_string(dnode, "peer-ip");
+ uint8_t peer_prefix_length = yang_dnode_get_uint8(dnode,
+ "peer-prefix-length");
+
+ vty_out(vty, " ip address %s peer %s/%u", ip, peer_ip,
+ peer_prefix_length);
+
+ if (yang_dnode_exists(dnode, "label")) {
+ const char *label = yang_dnode_get_string(dnode, "label");
+
+ vty_out(vty, " label %s", label);
+ }
+
+ vty_out(vty, "\n");
+}
+
+DEFPY_YANG (ipv6_address,
+ ipv6_address_cmd,
+ "[no] ipv6 address X:X::X:X/M",
+ NO_STR
+ "Interface IPv6 config commands\n"
+ "Set the IP address of an interface\n"
+ "IPv6 address (e.g. 3ffe:506::1/48)\n")
+{
+ char ip[INET6_ADDRSTRLEN + 4];
+ char *mask;
+
+ if (no)
+ nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
+ else
+ nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
+
+ strlcpy(ip, address_str, sizeof(ip));
+
+ mask = strchr(ip, '/');
+ assert(mask);
+ *mask = 0;
+ mask++;
+
+ return nb_cli_apply_changes(vty,
+ "./frr-zebra:zebra/ipv6-addrs[ip='%s'][prefix-length='%s']",
+ ip, mask);
+}
+
+static void lib_interface_zebra_ipv6_addrs_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ const char *ip = yang_dnode_get_string(dnode, "ip");
+ uint8_t prefix_length = yang_dnode_get_uint8(dnode, "prefix-length");
+
+ vty_out(vty, " ipv6 address %s/%u\n", ip, prefix_length);
+}
+
+/* CLI for setting an ES in bypass mode */
+DEFPY_YANG_HIDDEN (zebra_evpn_es_bypass,
+ zebra_evpn_es_bypass_cmd,
+ "[no] evpn mh bypass",
+ NO_STR
+ "EVPN\n"
+ EVPN_MH_VTY_STR
+ "Set bypass mode\n")
+{
+ if (!no)
+ nb_cli_enqueue_change(vty, "./frr-zebra:zebra/evpn-mh/bypass",
+ NB_OP_MODIFY, "true");
+ else
+ nb_cli_enqueue_change(vty, "./frr-zebra:zebra/evpn-mh/bypass",
+ NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void lib_interface_zebra_evpn_mh_bypass_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ bool bypass = yang_dnode_get_bool(dnode, NULL);
+
+ if (bypass)
+ vty_out(vty, " evpn mh bypass\n");
+ else if (show_defaults)
+ vty_out(vty, " no evpn mh bypass\n");
+}
+
+/* CLI for configuring DF preference part for an ES */
+DEFPY_YANG (zebra_evpn_es_pref,
+ zebra_evpn_es_pref_cmd,
+ "[no$no] evpn mh es-df-pref ![(1-65535)$df_pref]",
+ NO_STR
+ "EVPN\n"
+ EVPN_MH_VTY_STR
+ "Preference value used for DF election\n"
+ "Preference\n")
+{
+ if (!no)
+ nb_cli_enqueue_change(vty,
+ "./frr-zebra:zebra/evpn-mh/df-preference",
+ NB_OP_MODIFY, df_pref_str);
+ else
+ nb_cli_enqueue_change(vty,
+ "./frr-zebra:zebra/evpn-mh/df-preference",
+ NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void lib_interface_zebra_evpn_mh_df_preference_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ uint16_t df_pref = yang_dnode_get_uint16(dnode, NULL);
+
+ vty_out(vty, " evpn mh es-df-pref %u\n", df_pref);
+}
+
+/* CLI for setting up sysmac part of ESI on an access port */
+DEFPY_YANG (zebra_evpn_es_sys_mac,
+ zebra_evpn_es_sys_mac_cmd,
+ "[no$no] evpn mh es-sys-mac ![X:X:X:X:X:X$mac]",
+ NO_STR
+ "EVPN\n"
+ EVPN_MH_VTY_STR
+ "Ethernet segment system MAC\n"
+ MAC_STR)
+{
+ if (!no)
+ nb_cli_enqueue_change(vty,
+ "./frr-zebra:zebra/evpn-mh/type-3/system-mac",
+ NB_OP_MODIFY, mac_str);
+ else
+ nb_cli_enqueue_change(vty,
+ "./frr-zebra:zebra/evpn-mh/type-3/system-mac",
+ NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void lib_interface_zebra_evpn_mh_type_3_system_mac_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ char buf[ETHER_ADDR_STRLEN];
+ struct ethaddr mac;
+
+ yang_dnode_get_mac(&mac, dnode, NULL);
+
+ vty_out(vty, " evpn mh es-sys-mac %s\n",
+ prefix_mac2str(&mac, buf, sizeof(buf)));
+}
+
+/* CLI for setting up local-ID part of ESI on an access port */
+DEFPY_YANG (zebra_evpn_es_id,
+ zebra_evpn_es_id_cmd,
+ "[no$no] evpn mh es-id ![(1-16777215)$es_lid | NAME$esi_str]",
+ NO_STR
+ "EVPN\n"
+ EVPN_MH_VTY_STR
+ "Ethernet segment identifier\n"
+ "local discriminator\n"
+ "10-byte ID - 00:AA:BB:CC:DD:EE:FF:GG:HH:II\n")
+{
+ if (no) {
+ /* We don't know which one is configured, so detroy both types. */
+ nb_cli_enqueue_change(vty,
+ "./frr-zebra:zebra/evpn-mh/type-0/esi",
+ NB_OP_DESTROY, NULL);
+ nb_cli_enqueue_change(vty,
+ "./frr-zebra:zebra/evpn-mh/type-3/local-discriminator",
+ NB_OP_DESTROY, NULL);
+ } else {
+ if (esi_str)
+ nb_cli_enqueue_change(vty,
+ "./frr-zebra:zebra/evpn-mh/type-0/esi",
+ NB_OP_MODIFY, esi_str);
+ else
+ nb_cli_enqueue_change(vty,
+ "./frr-zebra:zebra/evpn-mh/type-3/local-discriminator",
+ NB_OP_MODIFY, es_lid_str);
+ }
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void lib_interface_zebra_evpn_mh_type_0_esi_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ const char *esi_str = yang_dnode_get_string(dnode, NULL);
+
+ vty_out(vty, " evpn mh es-id %s\n", esi_str);
+}
+
+static void lib_interface_zebra_evpn_mh_type_3_local_discriminator_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ uint32_t es_lid = yang_dnode_get_uint32(dnode, NULL);
+
+ vty_out(vty, " evpn mh es-id %u\n", es_lid);
+}
+
+/* CLI for tagging an interface as an uplink */
+DEFPY_YANG (zebra_evpn_mh_uplink,
+ zebra_evpn_mh_uplink_cmd,
+ "[no] evpn mh uplink",
+ NO_STR
+ "EVPN\n"
+ EVPN_MH_VTY_STR
+ "Uplink to the VxLAN core\n")
+{
+ if (!no)
+ nb_cli_enqueue_change(vty, "./frr-zebra:zebra/evpn-mh/uplink",
+ NB_OP_MODIFY, "true");
+ else
+ nb_cli_enqueue_change(vty, "./frr-zebra:zebra/evpn-mh/uplink",
+ NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void lib_interface_zebra_evpn_mh_uplink_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ bool uplink = yang_dnode_get_bool(dnode, NULL);
+
+ if (uplink)
+ vty_out(vty, " evpn mh uplink\n");
+ else if (show_defaults)
+ vty_out(vty, " no evpn mh uplink\n");
+}
+
+#if defined(HAVE_RTADV)
+DEFPY_YANG (ipv6_nd_ra_fast_retrans,
+ ipv6_nd_ra_fast_retrans_cmd,
+ "[no] ipv6 nd ra-fast-retrans",
+ NO_STR
+ "Interface IPv6 config commands\n"
+ "Neighbor discovery\n"
+ "Fast retransmit of RA packets\n")
+{
+ if (no)
+ nb_cli_enqueue_change(vty,
+ "./frr-zebra:zebra/ipv6-router-advertisements/fast-retransmit",
+ NB_OP_MODIFY, "false");
+ else
+ nb_cli_enqueue_change(vty,
+ "./frr-zebra:zebra/ipv6-router-advertisements/fast-retransmit",
+ NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void
+lib_interface_zebra_ipv6_router_advertisements_fast_retransmit_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ bool fast_retransmit = yang_dnode_get_bool(dnode, NULL);
+
+ if (!fast_retransmit)
+ vty_out(vty, " no ipv6 nd ra-fast-retrans\n");
+ else if (show_defaults)
+ vty_out(vty, " ipv6 nd ra-fast-retrans\n");
+}
+
+DEFPY_YANG (ipv6_nd_ra_hop_limit,
+ ipv6_nd_ra_hop_limit_cmd,
+ "[no] ipv6 nd ra-hop-limit ![(0-255)$hopcount]",
+ NO_STR
+ "Interface IPv6 config commands\n"
+ "Neighbor discovery\n"
+ "Advertisement Hop Limit\n"
+ "Advertisement Hop Limit in hops (default:64)\n")
+{
+ if (!no)
+ nb_cli_enqueue_change(vty,
+ "./frr-zebra:zebra/ipv6-router-advertisements/cur-hop-limit",
+ NB_OP_MODIFY, hopcount_str);
+ else
+ nb_cli_enqueue_change(vty,
+ "./frr-zebra:zebra/ipv6-router-advertisements/cur-hop-limit",
+ NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void
+lib_interface_zebra_ipv6_router_advertisements_cur_hop_limit_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ uint8_t hop_limit = yang_dnode_get_uint8(dnode, NULL);
+
+ vty_out(vty, " ipv6 nd ra-hop-limit %u\n", hop_limit);
+}
+
+DEFPY_YANG (ipv6_nd_ra_retrans_interval,
+ ipv6_nd_ra_retrans_interval_cmd,
+ "[no] ipv6 nd ra-retrans-interval ![(0-4294967295)$interval]",
+ NO_STR
+ "Interface IPv6 config commands\n"
+ "Neighbor discovery\n"
+ "Advertisement Retransmit Interval\n"
+ "Advertisement Retransmit Interval in msec\n")
+{
+ if (!no)
+ nb_cli_enqueue_change(vty,
+ "./frr-zebra:zebra/ipv6-router-advertisements/retrans-timer",
+ NB_OP_MODIFY, interval_str);
+ else
+ nb_cli_enqueue_change(vty,
+ "./frr-zebra:zebra/ipv6-router-advertisements/retrans-timer",
+ NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void
+lib_interface_zebra_ipv6_router_advertisements_retrans_timer_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ uint32_t retrans_timer = yang_dnode_get_uint32(dnode, NULL);
+
+ vty_out(vty, " ipv6 nd ra-retrans-interval %u\n", retrans_timer);
+}
+
+DEFPY_YANG (ipv6_nd_suppress_ra,
+ ipv6_nd_suppress_ra_cmd,
+ "[no] ipv6 nd suppress-ra",
+ NO_STR
+ "Interface IPv6 config commands\n"
+ "Neighbor discovery\n"
+ "Suppress Router Advertisement\n")
+{
+ if (no)
+ nb_cli_enqueue_change(vty,
+ "./frr-zebra:zebra/ipv6-router-advertisements/send-advertisements",
+ NB_OP_MODIFY, "true");
+ else
+ nb_cli_enqueue_change(vty,
+ "./frr-zebra:zebra/ipv6-router-advertisements/send-advertisements",
+ NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void
+lib_interface_zebra_ipv6_router_advertisements_send_advertisements_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ bool send_advertisements = yang_dnode_get_bool(dnode, NULL);
+
+ if (send_advertisements)
+ vty_out(vty, " no ipv6 nd suppress-ra\n");
+ else if (show_defaults)
+ vty_out(vty, " ipv6 nd suppress-ra\n");
+}
+
+DEFPY_YANG (ipv6_nd_ra_interval,
+ ipv6_nd_ra_interval_cmd,
+ "[no] ipv6 nd ra-interval ![<(1-1800)$sec|msec (70-1800000)$msec>]",
+ NO_STR
+ "Interface IPv6 config commands\n"
+ "Neighbor discovery\n"
+ "Router Advertisement interval\n"
+ "Router Advertisement interval in seconds\n"
+ "Router Advertisement interval in milliseconds\n"
+ "Router Advertisement interval in milliseconds\n")
+{
+ char value[YANG_VALUE_MAXLEN];
+
+ if (!no) {
+ if (sec)
+ snprintf(value, sizeof(value), "%lu", sec * 1000);
+ else
+ snprintf(value, sizeof(value), "%lu", msec);
+
+ nb_cli_enqueue_change(vty,
+ "./frr-zebra:zebra/ipv6-router-advertisements/max-rtr-adv-interval",
+ NB_OP_MODIFY, value);
+ } else {
+ nb_cli_enqueue_change(vty,
+ "./frr-zebra:zebra/ipv6-router-advertisements/max-rtr-adv-interval",
+ NB_OP_DESTROY, NULL);
+ }
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void
+lib_interface_zebra_ipv6_router_advertisements_max_rtr_adv_interval_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ uint32_t max_rtr_adv_interval = yang_dnode_get_uint32(dnode, NULL);
+
+ if (max_rtr_adv_interval % 1000)
+ vty_out(vty, " ipv6 nd ra-interval msec %u\n",
+ max_rtr_adv_interval);
+ else
+ vty_out(vty, " ipv6 nd ra-interval %u\n",
+ max_rtr_adv_interval / 1000);
+}
+
+DEFPY_YANG (ipv6_nd_ra_lifetime,
+ ipv6_nd_ra_lifetime_cmd,
+ "[no] ipv6 nd ra-lifetime ![(0-9000)$lifetime]",
+ NO_STR
+ "Interface IPv6 config commands\n"
+ "Neighbor discovery\n"
+ "Router lifetime\n"
+ "Router lifetime in seconds (0 stands for a non-default gw)\n")
+{
+ if (!no)
+ nb_cli_enqueue_change(vty,
+ "./frr-zebra:zebra/ipv6-router-advertisements/default-lifetime",
+ NB_OP_MODIFY, lifetime_str);
+ else
+ nb_cli_enqueue_change(vty,
+ "./frr-zebra:zebra/ipv6-router-advertisements/default-lifetime",
+ NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void
+lib_interface_zebra_ipv6_router_advertisements_default_lifetime_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ uint16_t default_lifetime = yang_dnode_get_uint16(dnode, NULL);
+
+ vty_out(vty, " ipv6 nd ra-lifetime %u\n", default_lifetime);
+}
+
+DEFPY_YANG (ipv6_nd_reachable_time,
+ ipv6_nd_reachable_time_cmd,
+ "[no] ipv6 nd reachable-time ![(1-3600000)$msec]",
+ NO_STR
+ "Interface IPv6 config commands\n"
+ "Neighbor discovery\n"
+ "Reachable time\n"
+ "Reachable time in milliseconds\n")
+{
+ if (!no)
+ nb_cli_enqueue_change(vty,
+ "./frr-zebra:zebra/ipv6-router-advertisements/reachable-time",
+ NB_OP_MODIFY, msec_str);
+ else
+ nb_cli_enqueue_change(vty,
+ "./frr-zebra:zebra/ipv6-router-advertisements/reachable-time",
+ NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void
+lib_interface_zebra_ipv6_router_advertisements_reachable_time_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ uint32_t reachable_time = yang_dnode_get_uint32(dnode, NULL);
+
+ vty_out(vty, " ipv6 nd reachable-time %u\n", reachable_time);
+}
+
+DEFPY_YANG (ipv6_nd_homeagent_preference,
+ ipv6_nd_homeagent_preference_cmd,
+ "[no] ipv6 nd home-agent-preference ![(0-65535)$pref]",
+ NO_STR
+ "Interface IPv6 config commands\n"
+ "Neighbor discovery\n"
+ "Home Agent preference\n"
+ "preference value (default is 0, least preferred)\n")
+{
+ if (!no)
+ nb_cli_enqueue_change(vty,
+ "./frr-zebra:zebra/ipv6-router-advertisements/home-agent-preference",
+ NB_OP_MODIFY, pref_str);
+ else
+ nb_cli_enqueue_change(vty,
+ "./frr-zebra:zebra/ipv6-router-advertisements/home-agent-preference",
+ NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void
+lib_interface_zebra_ipv6_router_advertisements_home_agent_preference_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ uint16_t home_agent_preference = yang_dnode_get_uint16(dnode, NULL);
+
+ vty_out(vty, " ipv6 nd home-agent-preference %u\n",
+ home_agent_preference);
+}
+
+DEFPY_YANG (ipv6_nd_homeagent_lifetime,
+ ipv6_nd_homeagent_lifetime_cmd,
+ "[no] ipv6 nd home-agent-lifetime ![(1-65520)$lifetime]",
+ NO_STR
+ "Interface IPv6 config commands\n"
+ "Neighbor discovery\n"
+ "Home Agent lifetime\n"
+ "Home Agent lifetime in seconds\n")
+{
+ if (!no)
+ nb_cli_enqueue_change(vty,
+ "./frr-zebra:zebra/ipv6-router-advertisements/home-agent-lifetime",
+ NB_OP_MODIFY, lifetime_str);
+ else
+ nb_cli_enqueue_change(vty,
+ "./frr-zebra:zebra/ipv6-router-advertisements/home-agent-lifetime",
+ NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void
+lib_interface_zebra_ipv6_router_advertisements_home_agent_lifetime_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ uint16_t home_agent_lifetime = yang_dnode_get_uint16(dnode, NULL);
+
+ vty_out(vty, " ipv6 nd home-agent-lifetime %u\n", home_agent_lifetime);
+}
+
+DEFPY_YANG (ipv6_nd_managed_config_flag,
+ ipv6_nd_managed_config_flag_cmd,
+ "[no] ipv6 nd managed-config-flag",
+ NO_STR
+ "Interface IPv6 config commands\n"
+ "Neighbor discovery\n"
+ "Managed address configuration flag\n")
+{
+ if (!no)
+ nb_cli_enqueue_change(vty,
+ "./frr-zebra:zebra/ipv6-router-advertisements/managed-flag",
+ NB_OP_MODIFY, "true");
+ else
+ nb_cli_enqueue_change(vty,
+ "./frr-zebra:zebra/ipv6-router-advertisements/managed-flag",
+ NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void lib_interface_zebra_ipv6_router_advertisements_managed_flag_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ bool managed_flag = yang_dnode_get_bool(dnode, NULL);
+
+ if (managed_flag)
+ vty_out(vty, " ipv6 nd managed-config-flag\n");
+ else if (show_defaults)
+ vty_out(vty, " no ipv6 nd managed-config-flag\n");
+}
+
+DEFPY_YANG (ipv6_nd_homeagent_config_flag,
+ ipv6_nd_homeagent_config_flag_cmd,
+ "[no] ipv6 nd home-agent-config-flag",
+ NO_STR
+ "Interface IPv6 config commands\n"
+ "Neighbor discovery\n"
+ "Home Agent configuration flag\n")
+{
+ if (!no)
+ nb_cli_enqueue_change(vty,
+ "./frr-zebra:zebra/ipv6-router-advertisements/home-agent-flag",
+ NB_OP_MODIFY, "true");
+ else
+ nb_cli_enqueue_change(vty,
+ "./frr-zebra:zebra/ipv6-router-advertisements/home-agent-flag",
+ NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void
+lib_interface_zebra_ipv6_router_advertisements_home_agent_flag_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ bool home_agent_flag = yang_dnode_get_bool(dnode, NULL);
+
+ if (home_agent_flag)
+ vty_out(vty, " ipv6 nd home-agent-config-flag\n");
+ else if (show_defaults)
+ vty_out(vty, " no ipv6 nd home-agent-config-flag\n");
+}
+
+DEFPY_YANG (ipv6_nd_adv_interval_config_option,
+ ipv6_nd_adv_interval_config_option_cmd,
+ "[no] ipv6 nd adv-interval-option",
+ NO_STR
+ "Interface IPv6 config commands\n"
+ "Neighbor discovery\n"
+ "Advertisement Interval Option\n")
+{
+ if (!no)
+ nb_cli_enqueue_change(vty,
+ "./frr-zebra:zebra/ipv6-router-advertisements/advertisement-interval-option",
+ NB_OP_MODIFY, "true");
+ else
+ nb_cli_enqueue_change(vty,
+ "./frr-zebra:zebra/ipv6-router-advertisements/advertisement-interval-option",
+ NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void
+lib_interface_zebra_ipv6_router_advertisements_advertisement_interval_option_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ bool advertisement_interval_option = yang_dnode_get_bool(dnode, NULL);
+
+ if (advertisement_interval_option)
+ vty_out(vty, " ipv6 nd adv-interval-option\n");
+ else if (show_defaults)
+ vty_out(vty, " no ipv6 nd adv-interval-option\n");
+}
+
+DEFPY_YANG (ipv6_nd_other_config_flag,
+ ipv6_nd_other_config_flag_cmd,
+ "[no] ipv6 nd other-config-flag",
+ NO_STR
+ "Interface IPv6 config commands\n"
+ "Neighbor discovery\n"
+ "Other statefull configuration flag\n")
+{
+ if (!no)
+ nb_cli_enqueue_change(vty,
+ "./frr-zebra:zebra/ipv6-router-advertisements/other-config-flag",
+ NB_OP_MODIFY, "true");
+ else
+ nb_cli_enqueue_change(vty,
+ "./frr-zebra:zebra/ipv6-router-advertisements/other-config-flag",
+ NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void
+lib_interface_zebra_ipv6_router_advertisements_other_config_flag_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ bool other_config_flag = yang_dnode_get_bool(dnode, NULL);
+
+ if (other_config_flag)
+ vty_out(vty, " ipv6 nd other-config-flag\n");
+ else if (show_defaults)
+ vty_out(vty, " no ipv6 nd other-config-flag\n");
+}
+
+DEFPY_YANG (ipv6_nd_prefix,
+ ipv6_nd_prefix_cmd,
+ "[no] ipv6 nd prefix X:X::X:X/M$prefix [<(0-4294967295)|infinite>$valid <(0-4294967295)|infinite>$preferred] [{router-address$routeraddr|off-link$offlink|no-autoconfig$noautoconf}]",
+ NO_STR
+ "Interface IPv6 config commands\n"
+ "Neighbor discovery\n"
+ "Prefix information\n"
+ "IPv6 prefix\n"
+ "Valid lifetime in seconds\n"
+ "Infinite valid lifetime\n"
+ "Preferred lifetime in seconds\n"
+ "Infinite preferred lifetime\n"
+ "Set Router Address flag\n"
+ "Do not use prefix for onlink determination\n"
+ "Do not use prefix for autoconfiguration\n")
+{
+ if (!no) {
+ nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
+ if (valid) {
+ if (strmatch(valid, "infinite"))
+ valid = "4294967295";
+ nb_cli_enqueue_change(vty, "./valid-lifetime",
+ NB_OP_MODIFY, valid);
+ } else {
+ nb_cli_enqueue_change(vty, "./valid-lifetime",
+ NB_OP_DESTROY, NULL);
+ }
+ if (preferred) {
+ if (strmatch(preferred, "infinite"))
+ preferred = "4294967295";
+ nb_cli_enqueue_change(vty, "./preferred-lifetime",
+ NB_OP_MODIFY, preferred);
+ } else {
+ nb_cli_enqueue_change(vty, "./preferred-lifetime",
+ NB_OP_DESTROY, NULL);
+ }
+ if (routeraddr)
+ nb_cli_enqueue_change(vty, "./router-address-flag",
+ NB_OP_MODIFY, "true");
+ else
+ nb_cli_enqueue_change(vty, "./router-address-flag",
+ NB_OP_DESTROY, NULL);
+ if (offlink)
+ nb_cli_enqueue_change(vty, "./on-link-flag",
+ NB_OP_MODIFY, "false");
+ else
+ nb_cli_enqueue_change(vty, "./on-link-flag",
+ NB_OP_DESTROY, NULL);
+ if (noautoconf)
+ nb_cli_enqueue_change(vty, "./autonomous-flag",
+ NB_OP_MODIFY, "false");
+ else
+ nb_cli_enqueue_change(vty, "./autonomous-flag",
+ NB_OP_DESTROY, NULL);
+ } else {
+ nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
+ }
+ return nb_cli_apply_changes(
+ vty,
+ "./frr-zebra:zebra/ipv6-router-advertisements/prefix-list/prefix[prefix-spec='%s']",
+ prefix_str);
+}
+
+static void
+lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ const char *prefix = yang_dnode_get_string(dnode, "prefix-spec");
+ struct lyd_node *valid = yang_dnode_get(dnode, "valid-lifetime");
+ struct lyd_node *preferred = yang_dnode_get(dnode, "preferred-lifetime");
+ bool router_address_flag = yang_dnode_get_bool(dnode,
+ "router-address-flag");
+ bool on_link_flag = yang_dnode_get_bool(dnode, "on-link-flag");
+ bool autonomous_flag = yang_dnode_get_bool(dnode, "autonomous-flag");
+
+ vty_out(vty, " ipv6 nd prefix %s", prefix);
+
+ if (!yang_dnode_is_default(valid, NULL) ||
+ !yang_dnode_is_default(preferred, NULL) || show_defaults) {
+ uint32_t valid_lifetime = yang_dnode_get_uint32(valid, NULL);
+ uint32_t preferred_lifetime = yang_dnode_get_uint32(preferred,
+ NULL);
+
+ if (valid_lifetime == UINT32_MAX)
+ vty_out(vty, " infinite");
+ else
+ vty_out(vty, " %u", valid_lifetime);
+ if (preferred_lifetime == UINT32_MAX)
+ vty_out(vty, " infinite");
+ else
+ vty_out(vty, " %u", preferred_lifetime);
+ }
+
+ if (!on_link_flag)
+ vty_out(vty, " off-link");
+
+ if (!autonomous_flag)
+ vty_out(vty, " no-autoconfig");
+
+ if (router_address_flag)
+ vty_out(vty, " router-address");
+
+ vty_out(vty, "\n");
+}
+
+DEFPY_YANG (ipv6_nd_router_preference,
+ ipv6_nd_router_preference_cmd,
+ "[no] ipv6 nd router-preference ![<high|medium|low>$pref]",
+ NO_STR
+ "Interface IPv6 config commands\n"
+ "Neighbor discovery\n"
+ "Default router preference\n"
+ "High default router preference\n"
+ "Medium default router preference (default)\n"
+ "Low default router preference\n")
+{
+ if (!no)
+ nb_cli_enqueue_change(vty,
+ "./frr-zebra:zebra/ipv6-router-advertisements/default-router-preference",
+ NB_OP_MODIFY, pref);
+ else
+ nb_cli_enqueue_change(vty,
+ "./frr-zebra:zebra/ipv6-router-advertisements/default-router-preference",
+ NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void
+lib_interface_zebra_ipv6_router_advertisements_default_router_preference_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ const char *default_router_preference = yang_dnode_get_string(dnode,
+ NULL);
+
+ vty_out(vty, " ipv6 nd router-preference %s\n",
+ default_router_preference);
+}
+
+DEFPY_YANG (ipv6_nd_mtu,
+ ipv6_nd_mtu_cmd,
+ "[no] ipv6 nd mtu ![(1-65535)]",
+ NO_STR
+ "Interface IPv6 config commands\n"
+ "Neighbor discovery\n"
+ "Advertised MTU\n"
+ "MTU in bytes\n")
+{
+ if (!no)
+ nb_cli_enqueue_change(vty,
+ "./frr-zebra:zebra/ipv6-router-advertisements/link-mtu",
+ NB_OP_MODIFY, mtu_str);
+ else
+ nb_cli_enqueue_change(vty,
+ "./frr-zebra:zebra/ipv6-router-advertisements/link-mtu",
+ NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void lib_interface_zebra_ipv6_router_advertisements_link_mtu_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ uint16_t link_mtu = yang_dnode_get_uint32(dnode, NULL);
+
+ vty_out(vty, " ipv6 nd mtu %u\n", link_mtu);
+}
+
+DEFPY_YANG (ipv6_nd_rdnss,
+ ipv6_nd_rdnss_cmd,
+ "[no] ipv6 nd rdnss X:X::X:X$addr [<(0-4294967295)|infinite>]$lifetime",
+ NO_STR
+ "Interface IPv6 config commands\n"
+ "Neighbor discovery\n"
+ "Recursive DNS server information\n"
+ "IPv6 address\n"
+ "Valid lifetime in seconds\n"
+ "Infinite valid lifetime\n")
+{
+ if (!no) {
+ nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
+ if (lifetime) {
+ if (strmatch(lifetime, "infinite"))
+ lifetime = "4294967295";
+ nb_cli_enqueue_change(vty, "./lifetime", NB_OP_MODIFY,
+ lifetime);
+ } else {
+ nb_cli_enqueue_change(vty, "./lifetime", NB_OP_DESTROY,
+ NULL);
+ }
+ } else {
+ nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
+ }
+ return nb_cli_apply_changes(
+ vty,
+ "./frr-zebra:zebra/ipv6-router-advertisements/rdnss/rdnss-address[address='%s']",
+ addr_str);
+}
+
+static void
+lib_interface_zebra_ipv6_router_advertisements_rdnss_rdnss_address_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ const char *address = yang_dnode_get_string(dnode, "address");
+
+ vty_out(vty, " ipv6 nd rdnss %s", address);
+
+ if (yang_dnode_exists(dnode, "lifetime")) {
+ uint32_t lifetime = yang_dnode_get_uint32(dnode, "lifetime");
+
+ if (lifetime == UINT32_MAX)
+ vty_out(vty, " infinite");
+ else
+ vty_out(vty, " %u", lifetime);
+ }
+
+ vty_out(vty, "\n");
+}
+
+DEFPY_YANG (ipv6_nd_dnssl,
+ ipv6_nd_dnssl_cmd,
+ "[no] ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]$lifetime",
+ NO_STR
+ "Interface IPv6 config commands\n"
+ "Neighbor discovery\n"
+ "DNS search list information\n"
+ "Domain name suffix\n"
+ "Valid lifetime in seconds\n"
+ "Infinite valid lifetime\n")
+{
+ char domain[254];
+ size_t len;
+
+ len = strlcpy(domain, suffix, sizeof(domain));
+ if (len == 0 || len >= sizeof(domain)) {
+ vty_out(vty, "Malformed DNS search domain\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ if (domain[len - 1] == '.') {
+ /*
+ * Allow, but don't require, a trailing dot signifying the root
+ * zone. Canonicalize by cutting it off if present.
+ */
+ domain[len - 1] = '\0';
+ len--;
+ }
+
+ if (!no) {
+ nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
+ if (lifetime) {
+ if (strmatch(lifetime, "infinite"))
+ lifetime = "4294967295";
+ nb_cli_enqueue_change(vty, "./lifetime", NB_OP_MODIFY,
+ lifetime);
+ } else {
+ nb_cli_enqueue_change(vty, "./lifetime", NB_OP_DESTROY,
+ NULL);
+ }
+ } else {
+ nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
+ }
+ return nb_cli_apply_changes(
+ vty,
+ "./frr-zebra:zebra/ipv6-router-advertisements/dnssl/dnssl-domain[domain='%s']",
+ domain);
+}
+
+static void
+lib_interface_zebra_ipv6_router_advertisements_dnssl_dnssl_domain_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ const char *domain = yang_dnode_get_string(dnode, "domain");
+
+ vty_out(vty, " ipv6 nd dnssl %s", domain);
+
+ if (yang_dnode_exists(dnode, "lifetime")) {
+ uint32_t lifetime = yang_dnode_get_uint32(dnode, "lifetime");
+
+ if (lifetime == UINT32_MAX)
+ vty_out(vty, " infinite");
+ else
+ vty_out(vty, " %u", lifetime);
+ }
+
+ vty_out(vty, "\n");
+}
+#endif /* HAVE_RTADV */
+
+#if HAVE_BFDD == 0
+DEFPY_YANG (zebra_ptm_enable_if,
+ zebra_ptm_enable_if_cmd,
+ "[no] ptm-enable",
+ NO_STR
+ "Enable neighbor check with specified topology\n")
+{
+ if (no)
+ nb_cli_enqueue_change(vty, "./frr-zebra:zebra/ptm-enable",
+ NB_OP_MODIFY, "false");
+ else
+ nb_cli_enqueue_change(vty, "./frr-zebra:zebra/ptm-enable",
+ NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void lib_interface_zebra_ptm_enable_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ bool enable = yang_dnode_get_bool(dnode, NULL);
+
+ if (!enable)
+ vty_out(vty, " no ptm-enable\n");
+ else if (show_defaults)
+ vty_out(vty, " ptm-enable\n");
+}
+#endif /* HAVE_BFDD == 0 */
+
+/*
+ * VRF commands
+ */
+
+static void zebra_vrf_indent_cli_write(struct vty *vty,
+ const struct lyd_node *dnode)
+{
+ const struct lyd_node *vrf = yang_dnode_get_parent(dnode, "vrf");
+
+ if (vrf && strcmp(yang_dnode_get_string(vrf, "name"), VRF_DEFAULT_NAME))
+ vty_out(vty, " ");
+}
+
+DEFPY_YANG (ip_router_id,
+ ip_router_id_cmd,
+ "[no] ip router-id A.B.C.D$id vrf NAME",
+ NO_STR
+ IP_STR
+ "Manually set the router-id\n"
+ "IP address to use for router-id\n"
+ VRF_CMD_HELP_STR)
+{
+ if (!no)
+ nb_cli_enqueue_change(vty, "./frr-zebra:zebra/router-id", NB_OP_MODIFY,
+ id_str);
+ else
+ nb_cli_enqueue_change(vty, "./frr-zebra:zebra/router-id", NB_OP_DESTROY,
+ NULL);
+ return nb_cli_apply_changes(vty, "/frr-vrf:lib/vrf[name='%s']", vrf);
+}
+
+ALIAS_YANG (ip_router_id,
+ router_id_cmd,
+ "[no] router-id A.B.C.D$id vrf NAME",
+ NO_STR
+ "Manually set the router-id\n"
+ "IP address to use for router-id\n"
+ VRF_CMD_HELP_STR);
+
+DEFPY_YANG (ipv6_router_id,
+ ipv6_router_id_cmd,
+ "[no] ipv6 router-id X:X::X:X$id vrf NAME",
+ NO_STR
+ IPV6_STR
+ "Manually set the router-id\n"
+ "IPv6 address to use for router-id\n"
+ VRF_CMD_HELP_STR)
+{
+ if (!no)
+ nb_cli_enqueue_change(vty, "./frr-zebra:zebra/ipv6-router-id",
+ NB_OP_MODIFY, id_str);
+ else
+ nb_cli_enqueue_change(vty, "./frr-zebra:zebra/ipv6-router-id",
+ NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, "/frr-vrf:lib/vrf[name='%s']", vrf);
+}
+
+DEFPY_YANG (ip_router_id_in_vrf,
+ ip_router_id_in_vrf_cmd,
+ "[no] ip router-id ![A.B.C.D$id]",
+ NO_STR
+ IP_STR
+ "Manually set the router-id\n"
+ "IP address to use for router-id\n")
+{
+ if (!no)
+ nb_cli_enqueue_change(vty, "./frr-zebra:zebra/router-id", NB_OP_MODIFY,
+ id_str);
+ else
+ nb_cli_enqueue_change(vty, "./frr-zebra:zebra/router-id", NB_OP_DESTROY,
+ NULL);
+
+ if (vty->node == CONFIG_NODE)
+ return nb_cli_apply_changes(vty, "/frr-vrf:lib/vrf[name='%s']",
+ VRF_DEFAULT_NAME);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+ALIAS_YANG (ip_router_id_in_vrf,
+ router_id_in_vrf_cmd,
+ "[no] router-id ![A.B.C.D$id]",
+ NO_STR
+ "Manually set the router-id\n"
+ "IP address to use for router-id\n");
+
+DEFPY_YANG (ipv6_router_id_in_vrf,
+ ipv6_router_id_in_vrf_cmd,
+ "[no] ipv6 router-id ![X:X::X:X$id]",
+ NO_STR
+ IP6_STR
+ "Manually set the IPv6 router-id\n"
+ "IPV6 address to use for router-id\n")
+{
+ if (!no)
+ nb_cli_enqueue_change(vty, "./frr-zebra:zebra/ipv6-router-id",
+ NB_OP_MODIFY, id_str);
+ else
+ nb_cli_enqueue_change(vty, "./frr-zebra:zebra/ipv6-router-id",
+ NB_OP_DESTROY, NULL);
+
+ if (vty->node == CONFIG_NODE)
+ return nb_cli_apply_changes(vty, "/frr-vrf:lib/vrf[name='%s']",
+ VRF_DEFAULT_NAME);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void lib_vrf_zebra_router_id_cli_write(struct vty *vty,
+ const struct lyd_node *dnode,
+ bool show_defaults)
+{
+ const char *id = yang_dnode_get_string(dnode, NULL);
+
+ zebra_vrf_indent_cli_write(vty, dnode);
+
+ vty_out(vty, "ip router-id %s\n", id);
+}
+
+static void lib_vrf_zebra_ipv6_router_id_cli_write(struct vty *vty,
+ const struct lyd_node *dnode,
+ bool show_defaults)
+{
+ const char *id = yang_dnode_get_string(dnode, NULL);
+
+ zebra_vrf_indent_cli_write(vty, dnode);
+
+ vty_out(vty, "ipv6 router-id %s\n", id);
+}
+
+DEFPY_YANG (ip_protocol,
+ ip_protocol_cmd,
+ "[no] ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
+ " $proto ![route-map ROUTE-MAP$rmap]",
+ NO_STR
+ IP_STR
+ "Filter routing info exchanged between zebra and protocol\n"
+ FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
+ "Specify route-map\n"
+ "Route map name\n")
+{
+ if (!no) {
+ nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
+ nb_cli_enqueue_change(vty, "./route-map", NB_OP_MODIFY, rmap);
+ } else {
+ nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
+ }
+
+ if (vty->node == CONFIG_NODE)
+ return nb_cli_apply_changes(
+ vty,
+ "/frr-vrf:lib/vrf[name='%s']/frr-zebra:zebra/filter-protocol[afi-safi='%s'][protocol='%s']",
+ VRF_DEFAULT_NAME,
+ yang_afi_safi_value2identity(AFI_IP, SAFI_UNICAST),
+ proto);
+
+ return nb_cli_apply_changes(
+ vty,
+ "./frr-zebra:zebra/filter-protocol[afi-safi='%s'][protocol='%s']",
+ yang_afi_safi_value2identity(AFI_IP, SAFI_UNICAST), proto);
+}
+
+DEFPY_YANG (ipv6_protocol,
+ ipv6_protocol_cmd,
+ "[no] ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
+ " $proto ![route-map ROUTE-MAP$rmap]",
+ NO_STR
+ IP6_STR
+ "Filter IPv6 routing info exchanged between zebra and protocol\n"
+ FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
+ "Specify route-map\n"
+ "Route map name\n")
+{
+ if (!no) {
+ nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
+ nb_cli_enqueue_change(vty, "./route-map", NB_OP_MODIFY, rmap);
+ } else {
+ nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
+ }
+
+ if (vty->node == CONFIG_NODE)
+ return nb_cli_apply_changes(
+ vty,
+ "/frr-vrf:lib/vrf[name='%s']/frr-zebra:zebra/filter-protocol[afi-safi='%s'][protocol='%s']",
+ VRF_DEFAULT_NAME,
+ yang_afi_safi_value2identity(AFI_IP6, SAFI_UNICAST),
+ proto);
+
+ return nb_cli_apply_changes(
+ vty,
+ "./frr-zebra:zebra/filter-protocol[afi-safi='%s'][protocol='%s']",
+ yang_afi_safi_value2identity(AFI_IP6, SAFI_UNICAST), proto);
+}
+
+static void lib_vrf_zebra_filter_protocol_cli_write(struct vty *vty,
+ const struct lyd_node *dnode,
+ bool show_defaults)
+{
+ const char *afi_safi = yang_dnode_get_string(dnode, "afi-safi");
+ const char *proto = yang_dnode_get_string(dnode, "protocol");
+ const char *rmap = yang_dnode_get_string(dnode, "route-map");
+ afi_t afi;
+ safi_t safi;
+
+ yang_afi_safi_identity2value(afi_safi, &afi, &safi);
+
+ if (safi != SAFI_UNICAST)
+ return;
+
+ zebra_vrf_indent_cli_write(vty, dnode);
+
+ if (afi == AFI_IP)
+ vty_out(vty, "ip protocol %s route-map %s\n", proto, rmap);
+ else
+ vty_out(vty, "ipv6 protocol %s route-map %s\n", proto, rmap);
+}
+
+DEFPY_YANG (ip_protocol_nht_rmap,
+ ip_protocol_nht_rmap_cmd,
+ "[no] ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
+ " $proto ![route-map ROUTE-MAP$rmap]",
+ NO_STR
+ IP_STR
+ "Filter Next Hop tracking route resolution\n"
+ FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
+ "Specify route map\n"
+ "Route map name\n")
+{
+ if (!no) {
+ nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
+ nb_cli_enqueue_change(vty, "./route-map", NB_OP_MODIFY, rmap);
+ } else {
+ nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
+ }
+
+ if (vty->node == CONFIG_NODE)
+ return nb_cli_apply_changes(
+ vty,
+ "/frr-vrf:lib/vrf[name='%s']/frr-zebra:zebra/filter-nht[afi-safi='%s'][protocol='%s']",
+ VRF_DEFAULT_NAME,
+ yang_afi_safi_value2identity(AFI_IP, SAFI_UNICAST),
+ proto);
+
+ return nb_cli_apply_changes(
+ vty,
+ "./frr-zebra:zebra/filter-nht[afi-safi='%s'][protocol='%s']",
+ yang_afi_safi_value2identity(AFI_IP, SAFI_UNICAST), proto);
+}
+
+DEFPY_YANG (ipv6_protocol_nht_rmap,
+ ipv6_protocol_nht_rmap_cmd,
+ "[no] ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
+ " $proto ![route-map ROUTE-MAP$rmap]",
+ NO_STR
+ IP6_STR
+ "Filter Next Hop tracking route resolution\n"
+ FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
+ "Specify route map\n"
+ "Route map name\n")
+{
+ if (!no) {
+ nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
+ nb_cli_enqueue_change(vty, "./route-map", NB_OP_MODIFY, rmap);
+ } else {
+ nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
+ }
+
+ if (vty->node == CONFIG_NODE)
+ return nb_cli_apply_changes(
+ vty,
+ "/frr-vrf:lib/vrf[name='%s']/frr-zebra:zebra/filter-nht[afi-safi='%s'][protocol='%s']",
+ VRF_DEFAULT_NAME,
+ yang_afi_safi_value2identity(AFI_IP6, SAFI_UNICAST),
+ proto);
+
+ return nb_cli_apply_changes(
+ vty,
+ "./frr-zebra:zebra/filter-nht[afi-safi='%s'][protocol='%s']",
+ yang_afi_safi_value2identity(AFI_IP6, SAFI_UNICAST), proto);
+}
+
+static void lib_vrf_zebra_filter_nht_cli_write(struct vty *vty,
+ const struct lyd_node *dnode,
+ bool show_defaults)
+{
+ const char *afi_safi = yang_dnode_get_string(dnode, "afi-safi");
+ const char *proto = yang_dnode_get_string(dnode, "protocol");
+ const char *rmap = yang_dnode_get_string(dnode, "route-map");
+ afi_t afi;
+ safi_t safi;
+
+ yang_afi_safi_identity2value(afi_safi, &afi, &safi);
+
+ if (safi != SAFI_UNICAST)
+ return;
+
+ zebra_vrf_indent_cli_write(vty, dnode);
+
+ if (afi == AFI_IP)
+ vty_out(vty, "ip nht %s route-map %s\n", proto, rmap);
+ else
+ vty_out(vty, "ipv6 nht %s route-map %s\n", proto, rmap);
+}
+
+DEFPY_YANG (ip_nht_default_route,
+ ip_nht_default_route_cmd,
+ "[no] ip nht resolve-via-default",
+ NO_STR
+ IP_STR
+ "Filter Next Hop tracking route resolution\n"
+ "Resolve via default route\n")
+{
+ nb_cli_enqueue_change(vty, "./frr-zebra:zebra/resolve-via-default",
+ NB_OP_MODIFY, no ? "false" : "true");
+
+ if (vty->node == CONFIG_NODE)
+ return nb_cli_apply_changes(vty, "/frr-vrf:lib/vrf[name='%s']",
+ VRF_DEFAULT_NAME);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void lib_vrf_zebra_resolve_via_default_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ bool resolve_via_default = yang_dnode_get_bool(dnode, NULL);
+
+ if (resolve_via_default != SAVE_ZEBRA_IP_NHT_RESOLVE_VIA_DEFAULT ||
+ show_defaults) {
+ zebra_vrf_indent_cli_write(vty, dnode);
+
+ vty_out(vty, "%sip nht resolve-via-default\n",
+ resolve_via_default ? "" : "no ");
+ }
+}
+
+DEFPY_YANG (ipv6_nht_default_route,
+ ipv6_nht_default_route_cmd,
+ "[no] ipv6 nht resolve-via-default",
+ NO_STR
+ IP6_STR
+ "Filter Next Hop tracking route resolution\n"
+ "Resolve via default route\n")
+{
+ nb_cli_enqueue_change(vty, "./frr-zebra:zebra/ipv6-resolve-via-default",
+ NB_OP_MODIFY, no ? "false" : "true");
+
+ if (vty->node == CONFIG_NODE)
+ return nb_cli_apply_changes(vty, "/frr-vrf:lib/vrf[name='%s']",
+ VRF_DEFAULT_NAME);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void lib_vrf_zebra_ipv6_resolve_via_default_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ bool resolve_via_default = yang_dnode_get_bool(dnode, NULL);
+
+ if (resolve_via_default != SAVE_ZEBRA_IP_NHT_RESOLVE_VIA_DEFAULT ||
+ show_defaults) {
+ zebra_vrf_indent_cli_write(vty, dnode);
+
+ vty_out(vty, "%sipv6 nht resolve-via-default\n",
+ resolve_via_default ? "" : "no ");
+ }
+}
+
+DEFPY_YANG (vrf_netns,
+ vrf_netns_cmd,
+ "[no] netns ![NAME$netns_name]",
+ NO_STR
+ "Attach VRF to a Namespace\n"
+ "The file name in " NS_RUN_DIR ", or a full pathname\n")
+{
+ vty_out(vty, "%% This command doesn't do anything.\n");
+ vty_out(vty,
+ "%% VRF is linked to a netns automatically based on its name.\n");
+ return CMD_WARNING;
+}
+
+DEFPY_YANG (ip_table_range, ip_table_range_cmd,
+ "[no] ip table range ![(1-4294967295)$start (1-4294967295)$end]",
+ NO_STR IP_STR
+ "table configuration\n"
+ "Configure table range\n"
+ "Start Routing Table\n"
+ "End Routing Table\n")
+{
+ if (!no) {
+ const struct lyd_node *start_node;
+ const struct lyd_node *end_node;
+
+ if (vty->node == CONFIG_NODE) {
+ start_node =
+ yang_dnode_getf(vty->candidate_config->dnode,
+ "/frr-vrf:lib/vrf[name='%s']/frr-zebra:zebra/netns/table-range/start",
+ VRF_DEFAULT_NAME);
+ end_node =
+ yang_dnode_getf(vty->candidate_config->dnode,
+ "/frr-vrf:lib/vrf[name='%s']/frr-zebra:zebra/netns/table-range/end",
+ VRF_DEFAULT_NAME);
+ } else {
+ start_node =
+ yang_dnode_getf(vty->candidate_config->dnode,
+ "%s/frr-zebra:zebra/netns/table-range/start",
+ VTY_CURR_XPATH);
+ end_node =
+ yang_dnode_getf(vty->candidate_config->dnode,
+ "%s/frr-zebra:zebra/netns/table-range/end",
+ VTY_CURR_XPATH);
+ }
+
+ if (start_node && end_node) {
+ if (yang_dnode_get_uint32(start_node, NULL) !=
+ (uint32_t)start ||
+ yang_dnode_get_uint32(end_node, NULL) !=
+ (uint32_t)end) {
+ vty_out(vty,
+ "%% New range will be taken into account at restart.\n");
+ vty_out(vty,
+ "%% Don't forget to save your configuration.\n");
+ }
+ }
+
+ nb_cli_enqueue_change(vty, "./frr-zebra:zebra/netns/table-range",
+ NB_OP_CREATE, NULL);
+ nb_cli_enqueue_change(vty,
+ "./frr-zebra:zebra/netns/table-range/start",
+ NB_OP_MODIFY, start_str);
+ nb_cli_enqueue_change(vty,
+ "./frr-zebra:zebra/netns/table-range/end",
+ NB_OP_MODIFY, end_str);
+ } else {
+ nb_cli_enqueue_change(vty, "./frr-zebra:zebra/netns/table-range",
+ NB_OP_DESTROY, NULL);
+ }
+
+ if (vty->node == CONFIG_NODE)
+ return nb_cli_apply_changes(vty, "/frr-vrf:lib/vrf[name='%s']",
+ VRF_DEFAULT_NAME);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void lib_vrf_zebra_netns_table_range_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ uint32_t start = yang_dnode_get_uint32(dnode, "start");
+ uint32_t end = yang_dnode_get_uint32(dnode, "end");
+
+ zebra_vrf_indent_cli_write(vty, dnode);
+
+ vty_out(vty, "ip table range %u %u\n", start, end);
+}
+
+DEFPY_YANG (vni_mapping,
+ vni_mapping_cmd,
+ "[no] vni ![" CMD_VNI_RANGE "[prefix-routes-only$filter]]",
+ NO_STR
+ "VNI corresponding to tenant VRF\n"
+ "VNI-ID\n"
+ "prefix-routes-only\n")
+{
+ if (!no)
+ nb_cli_enqueue_change(vty, "./frr-zebra:zebra/l3vni-id", NB_OP_MODIFY,
+ vni_str);
+ else
+ nb_cli_enqueue_change(vty, "./frr-zebra:zebra/l3vni-id", NB_OP_DESTROY,
+ NULL);
+
+ if (filter)
+ nb_cli_enqueue_change(vty, "./frr-zebra:zebra/prefix-only",
+ NB_OP_MODIFY, "true");
+ else
+ nb_cli_enqueue_change(vty, "./frr-zebra:zebra/prefix-only",
+ NB_OP_DESTROY, NULL);
+
+ if (vty->node == CONFIG_NODE)
+ return nb_cli_apply_changes(vty, "/frr-vrf:lib/vrf[name='%s']",
+ VRF_DEFAULT_NAME);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void lib_vrf_zebra_l3vni_id_cli_write(struct vty *vty,
+ const struct lyd_node *dnode,
+ bool show_defaults)
+{
+ vni_t vni = yang_dnode_get_uint32(dnode, NULL);
+ bool prefix_only = yang_dnode_get_bool(dnode, "../prefix-only");
+
+ zebra_vrf_indent_cli_write(vty, dnode);
+
+ vty_out(vty, "vni %u", vni);
+
+ if (prefix_only)
+ vty_out(vty, " prefix-routes-only");
+
+ vty_out(vty, "\n");
+}
+
+DEFPY_YANG(
+ match_ip_address_prefix_len, match_ip_address_prefix_len_cmd,
+ "match ip address prefix-len (0-32)$length",
+ MATCH_STR
+ IP_STR
+ "Match prefix length of IP address\n"
+ "Match prefix length of IP address\n"
+ "Prefix length\n")
+{
+ const char *xpath =
+ "./match-condition[condition='frr-zebra-route-map:ipv4-prefix-length']";
+ char xpath_value[XPATH_MAXLEN];
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
+ snprintf(
+ xpath_value, sizeof(xpath_value),
+ "%s/rmap-match-condition/frr-zebra-route-map:ipv4-prefix-length",
+ xpath);
+ nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, length_str);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFPY_YANG(
+ no_match_ip_address_prefix_len, no_match_ip_address_prefix_len_cmd,
+ "no match ip address prefix-len [(0-32)]",
+ NO_STR
+ MATCH_STR
+ IP_STR
+ "Match prefix length of IP address\n"
+ "Match prefix length of IP address\n"
+ "Prefix length\n")
+{
+ const char *xpath =
+ "./match-condition[condition='frr-zebra-route-map:ipv4-prefix-length']";
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFPY_YANG(
+ match_ipv6_address_prefix_len, match_ipv6_address_prefix_len_cmd,
+ "match ipv6 address prefix-len (0-128)$length",
+ MATCH_STR
+ IPV6_STR
+ "Match prefix length of IPv6 address\n"
+ "Match prefix length of IPv6 address\n"
+ "Prefix length\n")
+{
+ const char *xpath =
+ "./match-condition[condition='frr-zebra-route-map:ipv6-prefix-length']";
+ char xpath_value[XPATH_MAXLEN];
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
+ snprintf(
+ xpath_value, sizeof(xpath_value),
+ "%s/rmap-match-condition/frr-zebra-route-map:ipv6-prefix-length",
+ xpath);
+ nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, length_str);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFPY_YANG(
+ no_match_ipv6_address_prefix_len, no_match_ipv6_address_prefix_len_cmd,
+ "no match ipv6 address prefix-len [(0-128)]",
+ NO_STR
+ MATCH_STR
+ IPV6_STR
+ "Match prefix length of IPv6 address\n"
+ "Match prefix length of IPv6 address\n"
+ "Prefix length\n")
+{
+ const char *xpath =
+ "./match-condition[condition='frr-zebra-route-map:ipv6-prefix-length']";
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFPY_YANG(
+ match_ip_nexthop_prefix_len, match_ip_nexthop_prefix_len_cmd,
+ "match ip next-hop prefix-len (0-32)$length",
+ MATCH_STR
+ IP_STR
+ "Match prefixlen of nexthop IP address\n"
+ "Match prefixlen of given nexthop\n"
+ "Prefix length\n")
+{
+ const char *xpath =
+ "./match-condition[condition='frr-zebra-route-map:ipv4-next-hop-prefix-length']";
+ char xpath_value[XPATH_MAXLEN];
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
+ snprintf(
+ xpath_value, sizeof(xpath_value),
+ "%s/rmap-match-condition/frr-zebra-route-map:ipv4-prefix-length",
+ xpath);
+ nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, length_str);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFPY_YANG(
+ no_match_ip_nexthop_prefix_len, no_match_ip_nexthop_prefix_len_cmd,
+ "no match ip next-hop prefix-len [(0-32)]",
+ NO_STR
+ MATCH_STR
+ IP_STR
+ "Match prefixlen of nexthop IP address\n"
+ "Match prefix length of nexthop\n"
+ "Prefix length\n")
+{
+ const char *xpath =
+ "./match-condition[condition='frr-zebra-route-map:ipv4-next-hop-prefix-length']";
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFPY_YANG(
+ match_source_protocol, match_source_protocol_cmd,
+ "match source-protocol " FRR_REDIST_STR_ZEBRA "$proto",
+ MATCH_STR
+ "Match protocol via which the route was learnt\n"
+ FRR_REDIST_HELP_STR_ZEBRA)
+{
+ const char *xpath =
+ "./match-condition[condition='frr-zebra-route-map:source-protocol']";
+ char xpath_value[XPATH_MAXLEN];
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
+ snprintf(xpath_value, sizeof(xpath_value),
+ "%s/rmap-match-condition/frr-zebra-route-map:source-protocol",
+ xpath);
+ nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, proto);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFPY_YANG(
+ no_match_source_protocol, no_match_source_protocol_cmd,
+ "no match source-protocol [" FRR_REDIST_STR_ZEBRA "]",
+ NO_STR
+ MATCH_STR
+ "Match protocol via which the route was learnt\n"
+ FRR_REDIST_HELP_STR_ZEBRA)
+{
+ const char *xpath =
+ "./match-condition[condition='frr-zebra-route-map:source-protocol']";
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFPY_YANG(
+ match_source_instance, match_source_instance_cmd,
+ "match source-instance (0-255)$instance",
+ MATCH_STR
+ "Match the protocol's instance number\n"
+ "The instance number\n")
+{
+ const char *xpath =
+ "./match-condition[condition='frr-zebra-route-map:source-instance']";
+ char xpath_value[XPATH_MAXLEN];
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
+ snprintf(xpath_value, sizeof(xpath_value),
+ "%s/rmap-match-condition/frr-zebra-route-map:source-instance",
+ xpath);
+ nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, instance_str);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFPY_YANG(
+ no_match_source_instance, no_match_source_instance_cmd,
+ "no match source-instance [(0-255)]",
+ NO_STR MATCH_STR
+ "Match the protocol's instance number\n"
+ "The instance number\n")
+{
+ const char *xpath =
+ "./match-condition[condition='frr-zebra-route-map:source-instance']";
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+/* set functions */
+
+DEFPY_YANG(
+ set_src, set_src_cmd,
+ "set src <A.B.C.D$addrv4|X:X::X:X$addrv6>",
+ SET_STR
+ "src address for route\n"
+ "IPv4 src address\n"
+ "IPv6 src address\n")
+{
+ const char *xpath =
+ "./set-action[action='frr-zebra-route-map:src-address']";
+ char xpath_value[XPATH_MAXLEN];
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
+ if (addrv4_str) {
+ snprintf(
+ xpath_value, sizeof(xpath_value),
+ "%s/rmap-set-action/frr-zebra-route-map:ipv4-src-address",
+ xpath);
+ nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
+ addrv4_str);
+ } else {
+ snprintf(
+ xpath_value, sizeof(xpath_value),
+ "%s/rmap-set-action/frr-zebra-route-map:ipv6-src-address",
+ xpath);
+ nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
+ addrv6_str);
+ }
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFPY_YANG(
+ no_set_src, no_set_src_cmd,
+ "no set src [<A.B.C.D|X:X::X:X>]",
+ NO_STR
+ SET_STR
+ "Source address for route\n"
+ "IPv4 address\n"
+ "IPv6 address\n")
+{
+ const char *xpath =
+ "./set-action[action='frr-zebra-route-map:src-address']";
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+const char *features[] = {
+#if HAVE_BFDD == 0
+ "ptm-bfd",
+#endif
+#if defined(HAVE_RTADV)
+ "ipv6-router-advertisements",
+#endif
+ NULL
+};
+
+/* clang-format off */
+const struct frr_yang_module_info frr_zebra_cli_info = {
+ .name = "frr-zebra",
+ .ignore_cfg_cbs = true,
+ .features = features,
+ .nodes = {
+#if HAVE_BFDD == 0
+ {
+ .xpath = "/frr-zebra:zebra/ptm-enable",
+ .cbs.cli_show = zebra_ptm_enable_cli_write,
+ },
+#endif
+ {
+ .xpath = "/frr-zebra:zebra/route-map-delay",
+ .cbs.cli_show = zebra_route_map_delay_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv4-addrs",
+ .cbs.cli_show = lib_interface_zebra_ipv4_addrs_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv4-p2p-addrs",
+ .cbs.cli_show = lib_interface_zebra_ipv4_p2p_addrs_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-addrs",
+ .cbs.cli_show = lib_interface_zebra_ipv6_addrs_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/multicast",
+ .cbs.cli_show = lib_interface_zebra_multicast_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/link-detect",
+ .cbs.cli_show = lib_interface_zebra_link_detect_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/enabled",
+ .cbs.cli_show = lib_interface_zebra_enabled_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/bandwidth",
+ .cbs.cli_show = lib_interface_zebra_bandwidth_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/mpls",
+ .cbs.cli_show = lib_interface_zebra_mpls_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/link-params",
+ .cbs.cli_show = lib_interface_zebra_link_params_cli_write,
+ .cbs.cli_show_end = lib_interface_zebra_link_params_cli_write_end,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/link-params/metric",
+ .cbs.cli_show = lib_interface_zebra_link_params_metric_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/link-params/max-bandwidth",
+ .cbs.cli_show = lib_interface_zebra_link_params_max_bandwidth_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/link-params/max-reservable-bandwidth",
+ .cbs.cli_show = lib_interface_zebra_link_params_max_reservable_bandwidth_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/link-params/unreserved-bandwidths/unreserved-bandwidth",
+ .cbs.cli_show = lib_interface_zebra_link_params_unreserved_bandwidths_unreserved_bandwidth_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/link-params/residual-bandwidth",
+ .cbs.cli_show = lib_interface_zebra_link_params_residual_bandwidth_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/link-params/available-bandwidth",
+ .cbs.cli_show = lib_interface_zebra_link_params_available_bandwidth_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/link-params/utilized-bandwidth",
+ .cbs.cli_show = lib_interface_zebra_link_params_utilized_bandwidth_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/link-params/legacy-admin-group",
+ .cbs.cli_show = lib_interface_zebra_link_params_legacy_admin_group_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/link-params/affinities",
+ .cbs.cli_show = lib_interface_zebra_link_params_affinities_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/link-params/affinity-mode",
+ .cbs.cli_show = lib_interface_zebra_link_params_affinity_mode_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/link-params/neighbor",
+ .cbs.cli_show = lib_interface_zebra_link_params_neighbor_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/link-params/delay",
+ .cbs.cli_show = lib_interface_zebra_link_params_delay_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/link-params/delay-variation",
+ .cbs.cli_show = lib_interface_zebra_link_params_delay_variation_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/link-params/packet-loss",
+ .cbs.cli_show = lib_interface_zebra_link_params_packet_loss_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/evpn-mh/type-0/esi",
+ .cbs.cli_show = lib_interface_zebra_evpn_mh_type_0_esi_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/evpn-mh/type-3/system-mac",
+ .cbs.cli_show = lib_interface_zebra_evpn_mh_type_3_system_mac_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/evpn-mh/type-3/local-discriminator",
+ .cbs.cli_show = lib_interface_zebra_evpn_mh_type_3_local_discriminator_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/evpn-mh/df-preference",
+ .cbs.cli_show = lib_interface_zebra_evpn_mh_df_preference_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/evpn-mh/bypass",
+ .cbs.cli_show = lib_interface_zebra_evpn_mh_bypass_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/evpn-mh/uplink",
+ .cbs.cli_show = lib_interface_zebra_evpn_mh_uplink_cli_write,
+ },
+#if defined(HAVE_RTADV)
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/send-advertisements",
+ .cbs.cli_show = lib_interface_zebra_ipv6_router_advertisements_send_advertisements_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/max-rtr-adv-interval",
+ .cbs.cli_show = lib_interface_zebra_ipv6_router_advertisements_max_rtr_adv_interval_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/managed-flag",
+ .cbs.cli_show = lib_interface_zebra_ipv6_router_advertisements_managed_flag_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/other-config-flag",
+ .cbs.cli_show = lib_interface_zebra_ipv6_router_advertisements_other_config_flag_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/home-agent-flag",
+ .cbs.cli_show = lib_interface_zebra_ipv6_router_advertisements_home_agent_flag_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/link-mtu",
+ .cbs.cli_show = lib_interface_zebra_ipv6_router_advertisements_link_mtu_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/reachable-time",
+ .cbs.cli_show = lib_interface_zebra_ipv6_router_advertisements_reachable_time_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/retrans-timer",
+ .cbs.cli_show = lib_interface_zebra_ipv6_router_advertisements_retrans_timer_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/cur-hop-limit",
+ .cbs.cli_show = lib_interface_zebra_ipv6_router_advertisements_cur_hop_limit_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/default-lifetime",
+ .cbs.cli_show = lib_interface_zebra_ipv6_router_advertisements_default_lifetime_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/fast-retransmit",
+ .cbs.cli_show = lib_interface_zebra_ipv6_router_advertisements_fast_retransmit_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/advertisement-interval-option",
+ .cbs.cli_show = lib_interface_zebra_ipv6_router_advertisements_advertisement_interval_option_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/home-agent-preference",
+ .cbs.cli_show = lib_interface_zebra_ipv6_router_advertisements_home_agent_preference_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/home-agent-lifetime",
+ .cbs.cli_show = lib_interface_zebra_ipv6_router_advertisements_home_agent_lifetime_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/default-router-preference",
+ .cbs.cli_show = lib_interface_zebra_ipv6_router_advertisements_default_router_preference_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/prefix-list/prefix",
+ .cbs.cli_show = lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/dnssl/dnssl-domain",
+ .cbs.cli_show = lib_interface_zebra_ipv6_router_advertisements_dnssl_dnssl_domain_cli_write,
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/rdnss/rdnss-address",
+ .cbs.cli_show = lib_interface_zebra_ipv6_router_advertisements_rdnss_rdnss_address_cli_write,
+ },
+#endif /* defined(HAVE_RTADV) */
+#if HAVE_BFDD == 0
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ptm-enable",
+ .cbs.cli_show = lib_interface_zebra_ptm_enable_cli_write,
+ },
+#endif
+ {
+ .xpath = "/frr-vrf:lib/vrf/frr-zebra:zebra/router-id",
+ .cbs.cli_show = lib_vrf_zebra_router_id_cli_write,
+ },
+ {
+ .xpath = "/frr-vrf:lib/vrf/frr-zebra:zebra/ipv6-router-id",
+ .cbs.cli_show = lib_vrf_zebra_ipv6_router_id_cli_write,
+ },
+ {
+ .xpath = "/frr-vrf:lib/vrf/frr-zebra:zebra/filter-protocol",
+ .cbs.cli_show = lib_vrf_zebra_filter_protocol_cli_write,
+ },
+ {
+ .xpath = "/frr-vrf:lib/vrf/frr-zebra:zebra/filter-nht",
+ .cbs.cli_show = lib_vrf_zebra_filter_nht_cli_write,
+ },
+ {
+ .xpath = "/frr-vrf:lib/vrf/frr-zebra:zebra/resolve-via-default",
+ .cbs.cli_show = lib_vrf_zebra_resolve_via_default_cli_write,
+ },
+ {
+ .xpath = "/frr-vrf:lib/vrf/frr-zebra:zebra/ipv6-resolve-via-default",
+ .cbs.cli_show = lib_vrf_zebra_ipv6_resolve_via_default_cli_write,
+ },
+ {
+ .xpath = "/frr-vrf:lib/vrf/frr-zebra:zebra/netns/table-range",
+ .cbs.cli_show = lib_vrf_zebra_netns_table_range_cli_write,
+ },
+ {
+ .xpath = "/frr-vrf:lib/vrf/frr-zebra:zebra/l3vni-id",
+ .cbs.cli_show = lib_vrf_zebra_l3vni_id_cli_write,
+ },
+ {
+ .xpath = NULL,
+ },
+ }
+};
+
+struct cmd_node link_params_node = {
+ .name = "link-params",
+ .node = LINK_PARAMS_NODE,
+ .parent_node = INTERFACE_NODE,
+ .prompt = "%s(config-link-params)# ",
+};
+
+void zebra_cli_init(void)
+{
+ install_node(&link_params_node);
+
+ install_element(INTERFACE_NODE, &multicast_new_cmd);
+ install_element(INTERFACE_NODE, &multicast_cmd);
+ install_element(INTERFACE_NODE, &mpls_cmd);
+ install_element(INTERFACE_NODE, &linkdetect_cmd);
+ install_element(INTERFACE_NODE, &shutdown_if_cmd);
+ install_element(INTERFACE_NODE, &bandwidth_if_cmd);
+ install_element(INTERFACE_NODE, &ip_address_cmd);
+ install_element(INTERFACE_NODE, &ip_address_peer_cmd);
+ install_element(INTERFACE_NODE, &ipv6_address_cmd);
+ install_element(INTERFACE_NODE, &link_params_cmd);
+ install_element(INTERFACE_NODE, &no_link_params_cmd);
+ install_default(LINK_PARAMS_NODE);
+ install_element(LINK_PARAMS_NODE, &link_params_enable_cmd);
+ install_element(LINK_PARAMS_NODE, &no_link_params_enable_cmd);
+ install_element(LINK_PARAMS_NODE, &link_params_metric_cmd);
+ install_element(LINK_PARAMS_NODE, &link_params_maxbw_cmd);
+ install_element(LINK_PARAMS_NODE, &link_params_max_rsv_bw_cmd);
+ install_element(LINK_PARAMS_NODE, &link_params_unrsv_bw_cmd);
+ install_element(LINK_PARAMS_NODE, &link_params_admin_grp_cmd);
+ install_element(LINK_PARAMS_NODE, &link_params_inter_as_cmd);
+ install_element(LINK_PARAMS_NODE, &link_params_delay_cmd);
+ install_element(LINK_PARAMS_NODE, &link_params_delay_var_cmd);
+ install_element(LINK_PARAMS_NODE, &link_params_pkt_loss_cmd);
+ install_element(LINK_PARAMS_NODE, &link_params_ava_bw_cmd);
+ install_element(LINK_PARAMS_NODE, &link_params_res_bw_cmd);
+ install_element(LINK_PARAMS_NODE, &link_params_use_bw_cmd);
+ install_element(LINK_PARAMS_NODE, &link_params_affinity_cmd);
+ install_element(LINK_PARAMS_NODE, &link_params_affinity_mode_cmd);
+ install_element(LINK_PARAMS_NODE, &exit_link_params_cmd);
+
+ install_element(INTERFACE_NODE, &zebra_evpn_es_id_cmd);
+ install_element(INTERFACE_NODE, &zebra_evpn_es_sys_mac_cmd);
+ install_element(INTERFACE_NODE, &zebra_evpn_es_pref_cmd);
+ install_element(INTERFACE_NODE, &zebra_evpn_es_bypass_cmd);
+ install_element(INTERFACE_NODE, &zebra_evpn_mh_uplink_cmd);
+
+#if defined(HAVE_RTADV)
+ install_element(INTERFACE_NODE, &ipv6_nd_ra_fast_retrans_cmd);
+ install_element(INTERFACE_NODE, &ipv6_nd_ra_retrans_interval_cmd);
+ install_element(INTERFACE_NODE, &ipv6_nd_ra_hop_limit_cmd);
+ install_element(INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd);
+ install_element(INTERFACE_NODE, &ipv6_nd_ra_interval_cmd);
+ install_element(INTERFACE_NODE, &ipv6_nd_ra_lifetime_cmd);
+ install_element(INTERFACE_NODE, &ipv6_nd_reachable_time_cmd);
+ install_element(INTERFACE_NODE, &ipv6_nd_managed_config_flag_cmd);
+ install_element(INTERFACE_NODE, &ipv6_nd_other_config_flag_cmd);
+ install_element(INTERFACE_NODE, &ipv6_nd_homeagent_config_flag_cmd);
+ install_element(INTERFACE_NODE, &ipv6_nd_homeagent_preference_cmd);
+ install_element(INTERFACE_NODE, &ipv6_nd_homeagent_lifetime_cmd);
+ install_element(INTERFACE_NODE, &ipv6_nd_adv_interval_config_option_cmd);
+ install_element(INTERFACE_NODE, &ipv6_nd_prefix_cmd);
+ install_element(INTERFACE_NODE, &ipv6_nd_router_preference_cmd);
+ install_element(INTERFACE_NODE, &ipv6_nd_mtu_cmd);
+ install_element(INTERFACE_NODE, &ipv6_nd_rdnss_cmd);
+ install_element(INTERFACE_NODE, &ipv6_nd_dnssl_cmd);
+#endif
+#if HAVE_BFDD == 0
+ install_element(INTERFACE_NODE, &zebra_ptm_enable_if_cmd);
+#endif
+
+ install_element(CONFIG_NODE, &ip_router_id_cmd);
+ install_element(CONFIG_NODE, &router_id_cmd);
+ install_element(CONFIG_NODE, &ipv6_router_id_cmd);
+ install_element(CONFIG_NODE, &ip_router_id_in_vrf_cmd);
+ install_element(CONFIG_NODE, &router_id_in_vrf_cmd);
+ install_element(CONFIG_NODE, &ipv6_router_id_in_vrf_cmd);
+ install_element(VRF_NODE, &ip_router_id_in_vrf_cmd);
+ install_element(VRF_NODE, &router_id_in_vrf_cmd);
+ install_element(VRF_NODE, &ipv6_router_id_in_vrf_cmd);
+
+ install_element(CONFIG_NODE, &ip_protocol_cmd);
+ install_element(VRF_NODE, &ip_protocol_cmd);
+ install_element(CONFIG_NODE, &ipv6_protocol_cmd);
+ install_element(VRF_NODE, &ipv6_protocol_cmd);
+ install_element(CONFIG_NODE, &ip_protocol_nht_rmap_cmd);
+ install_element(VRF_NODE, &ip_protocol_nht_rmap_cmd);
+ install_element(CONFIG_NODE, &ipv6_protocol_nht_rmap_cmd);
+ install_element(VRF_NODE, &ipv6_protocol_nht_rmap_cmd);
+ install_element(CONFIG_NODE, &zebra_route_map_timer_cmd);
+
+ install_element(CONFIG_NODE, &ip_nht_default_route_cmd);
+ install_element(CONFIG_NODE, &ipv6_nht_default_route_cmd);
+ install_element(VRF_NODE, &ip_nht_default_route_cmd);
+ install_element(VRF_NODE, &ipv6_nht_default_route_cmd);
+
+ install_element(CONFIG_NODE, &vni_mapping_cmd);
+ install_element(VRF_NODE, &vni_mapping_cmd);
+
+ if (vrf_is_backend_netns())
+ install_element(VRF_NODE, &vrf_netns_cmd);
+
+ install_element(CONFIG_NODE, &ip_table_range_cmd);
+ install_element(VRF_NODE, &ip_table_range_cmd);
+#if HAVE_BFDD == 0
+ install_element(CONFIG_NODE, &zebra_ptm_enable_cmd);
+#endif
+ install_element(RMAP_NODE, &match_ip_nexthop_prefix_len_cmd);
+ install_element(RMAP_NODE, &no_match_ip_nexthop_prefix_len_cmd);
+ install_element(RMAP_NODE, &match_ip_address_prefix_len_cmd);
+ install_element(RMAP_NODE, &match_ipv6_address_prefix_len_cmd);
+ install_element(RMAP_NODE, &no_match_ipv6_address_prefix_len_cmd);
+ install_element(RMAP_NODE, &no_match_ip_address_prefix_len_cmd);
+ install_element(RMAP_NODE, &match_source_protocol_cmd);
+ install_element(RMAP_NODE, &no_match_source_protocol_cmd);
+ install_element(RMAP_NODE, &match_source_instance_cmd);
+ install_element(RMAP_NODE, &no_match_source_instance_cmd);
+
+ install_element(RMAP_NODE, &set_src_cmd);
+ install_element(RMAP_NODE, &no_set_src_cmd);
+}
diff --git a/zebra/zebra_cli.h b/zebra/zebra_cli.h
new file mode 100644
index 0000000000..01931a47ab
--- /dev/null
+++ b/zebra/zebra_cli.h
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#ifndef _ZEBRA_CLI_H
+#define _ZEBRA_CLI_H 1
+
+extern const struct frr_yang_module_info frr_zebra_cli_info;
+
+void zebra_cli_init(void);
+
+#endif
diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c
index f6c1fdd78e..06b34da209 100644
--- a/zebra/zebra_dplane.c
+++ b/zebra/zebra_dplane.c
@@ -2,6 +2,8 @@
/*
* Zebra dataplane layer.
* Copyright (c) 2018 Volta Networks, Inc.
+ * Portions:
+ * Copyright (c) 2021 The MITRE Corporation.
*/
#ifdef HAVE_CONFIG_H
@@ -37,6 +39,13 @@ DEFINE_MTYPE_STATIC(ZEBRA, DP_NS, "DPlane NSes");
# define AOK 0
#endif
+/*
+ * Dataplane API version. This must be updated when any incompatible changes
+ * are made. The minor version (at least) should be updated when new APIs
+ * are introduced.
+ */
+static uint32_t zdplane_version = MAKE_FRRVERSION(2, 0, 0);
+
/* Control for collection of extra interface info with route updates; a plugin
* can enable the extra info via a dplane api.
*/
@@ -180,10 +189,47 @@ struct dplane_br_port_info {
*/
struct dplane_intf_info {
+ enum zebra_iftype zif_type;
+ ifindex_t bond_ifindex;
+ ifindex_t link_ifindex;
+ int32_t mtu;
+ vrf_id_t vrf_id;
+ enum zebra_slave_iftype zif_slave_type;
+ ifindex_t master_ifindex;
+ ifindex_t bridge_ifindex;
+ ns_id_t link_nsid;
+ enum zebra_slave_iftype zslave_type;
+ uint8_t bypass;
+ enum zebra_link_type zltype;
+ bool startup;
+ uint8_t family;
+ struct zebra_vxlan_vni_array *vniarray;
+ bool no_bvinfo_avail;
+ bool no_afspec_avail;
+ struct zebra_dplane_bridge_vlan_info bvinfo;
+ struct zebra_dplane_bridge_vlan_info_array *bvarray;
+
+ char desc[128];
+
+ int32_t hw_addr_len;
+ uint8_t hw_addr[INTERFACE_HWADDR_MAX];
+
+ uint32_t table_id;
+
+ struct zebra_l2info_bridge binfo;
+ struct zebra_l2info_vlan vinfo;
+ struct zebra_l2info_vxlan vxinfo;
+ struct zebra_l2info_gre grinfo;
+
+ uint32_t rc_bitfield;
+
+ uint32_t txqlen;
+
uint32_t metric;
uint32_t flags;
bool protodown;
+ bool protodown_set;
bool pd_reason_val;
#define DPLANE_INTF_CONNECTED (1 << 0) /* Connected peer, p2p */
@@ -191,6 +237,7 @@ struct dplane_intf_info {
#define DPLANE_INTF_BROADCAST (1 << 2)
#define DPLANE_INTF_HAS_DEST DPLANE_INTF_CONNECTED
#define DPLANE_INTF_HAS_LABEL (1 << 4)
+#define DPLANE_INTF_NOPREFIXROUTE (1 << 5)
/* Interface address/prefix */
struct prefix prefix;
@@ -245,28 +292,8 @@ struct dplane_neigh_table {
* Policy based routing rule info for the dataplane
*/
struct dplane_ctx_rule {
- uint32_t priority;
-
- /* The route table pointed by this rule */
- uint32_t table;
-
- /* Filter criteria */
- uint32_t filter_bm;
- uint32_t fwmark;
- uint8_t dsfield;
- struct prefix src_ip;
- struct prefix dst_ip;
- uint8_t ip_proto;
- uint16_t src_port;
- uint16_t dst_port;
-
- uint8_t action_pcp;
- uint16_t action_vlan_id;
- uint16_t action_vlan_flags;
+ struct pbr_rule prule;
- uint32_t action_queue_id;
-
- char ifname[INTERFACE_NAMSIZ + 1];
struct ethaddr smac;
struct ethaddr dmac;
int out_ifindex;
@@ -337,6 +364,13 @@ struct dplane_tc_filter_info {
};
/*
+ * SRv6 encapsulation params context for the dataplane
+ */
+struct dplane_srv6_encap_ctx {
+ struct in6_addr srcaddr;
+};
+
+/*
* The context block used to exchange info about route updates across
* the boundary between the zebra main context (and pthread) and the
* dataplane layer (and pthread).
@@ -372,7 +406,7 @@ struct zebra_dplane_ctx {
vrf_id_t zd_vrf_id;
uint32_t zd_table_id;
- char zd_ifname[INTERFACE_NAMSIZ];
+ char zd_ifname[IFNAMSIZ];
ifindex_t zd_ifindex;
/* Support info for different kinds of updates */
@@ -397,6 +431,8 @@ struct zebra_dplane_ctx {
struct dplane_neigh_table neightable;
struct dplane_gre_ctx gre;
struct dplane_netconf_info netconf;
+ enum zebra_dplane_startup_notifications spot;
+ struct dplane_srv6_encap_ctx srv6_encap;
} u;
/* Namespace info, used especially for netlink kernel communication */
@@ -578,6 +614,9 @@ static struct zebra_dplane_globals {
_Atomic uint32_t dg_tcs_in;
_Atomic uint32_t dg_tcs_errors;
+ _Atomic uint32_t dg_srv6_encap_srcaddr_set_in;
+ _Atomic uint32_t dg_srv6_encap_srcaddr_set_errors;
+
/* Dataplane pthread */
struct frr_pthread *dg_pthread;
@@ -632,6 +671,12 @@ neigh_update_internal(enum dplane_op_e op, const struct interface *ifp,
* Public APIs
*/
+/* Access the dplane API version */
+uint32_t zebra_dplane_get_version(void)
+{
+ return zdplane_version;
+}
+
/* Obtain thread_master for dataplane thread */
struct event_loop *dplane_get_thread_master(void)
{
@@ -808,8 +853,14 @@ static void dplane_ctx_free_internal(struct zebra_dplane_ctx *ctx)
case DPLANE_OP_NONE:
case DPLANE_OP_IPSET_ADD:
case DPLANE_OP_IPSET_DELETE:
+ break;
case DPLANE_OP_INTF_INSTALL:
case DPLANE_OP_INTF_UPDATE:
+ if (ctx->u.intf.vniarray)
+ XFREE(MTYPE_TMP, ctx->u.intf.vniarray);
+ if (ctx->u.intf.bvarray)
+ XFREE(MTYPE_TMP, ctx->u.intf.bvarray);
+ break;
case DPLANE_OP_INTF_DELETE:
case DPLANE_OP_TC_QDISC_INSTALL:
case DPLANE_OP_TC_QDISC_UNINSTALL:
@@ -833,6 +884,8 @@ static void dplane_ctx_free_internal(struct zebra_dplane_ctx *ctx)
break;
case DPLANE_OP_GRE_SET:
case DPLANE_OP_INTF_NETCONFIG:
+ case DPLANE_OP_STARTUP_STAGE:
+ case DPLANE_OP_SRV6_ENCAP_SRCADDR_SET:
break;
}
}
@@ -1156,6 +1209,13 @@ const char *dplane_op2str(enum dplane_op_e op)
case DPLANE_OP_TC_FILTER_UPDATE:
ret = "TC__FILTER_UPDATE";
break;
+ case DPLANE_OP_STARTUP_STAGE:
+ ret = "STARTUP_STAGE";
+ break;
+
+ case DPLANE_OP_SRV6_ENCAP_SRCADDR_SET:
+ ret = "SRV6_ENCAP_SRCADDR_SET";
+ break;
}
return ret;
@@ -1297,6 +1357,450 @@ const char *dplane_ctx_get_ifname(const struct zebra_dplane_ctx *ctx)
return ctx->zd_ifname;
}
+void dplane_ctx_set_ifp_bridge_vlan_info_array(
+ struct zebra_dplane_ctx *ctx,
+ struct zebra_dplane_bridge_vlan_info_array *bvarray)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.intf.bvarray = bvarray;
+}
+
+const struct zebra_dplane_bridge_vlan_info_array *
+dplane_ctx_get_ifp_bridge_vlan_info_array(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.intf.bvarray;
+}
+
+void dplane_ctx_set_ifp_vxlan_vni_array(struct zebra_dplane_ctx *ctx,
+ struct zebra_vxlan_vni_array *vniarray)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.intf.vniarray = vniarray;
+}
+
+const struct zebra_vxlan_vni_array *
+dplane_ctx_get_ifp_vxlan_vni_array(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.intf.vniarray;
+}
+
+void dplane_ctx_set_ifp_no_afspec(struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.intf.no_afspec_avail = true;
+}
+
+bool dplane_ctx_get_ifp_no_afspec(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.intf.no_afspec_avail;
+}
+
+void dplane_ctx_set_ifp_no_bridge_vlan_info(struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.intf.no_bvinfo_avail = true;
+}
+
+bool dplane_ctx_get_ifp_no_bridge_vlan_info(struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.intf.no_bvinfo_avail;
+}
+
+void dplane_ctx_set_ifp_bridge_vlan_info(
+ struct zebra_dplane_ctx *ctx,
+ struct zebra_dplane_bridge_vlan_info *bvinfo)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.intf.bvinfo = *bvinfo;
+}
+
+const struct zebra_dplane_bridge_vlan_info *
+dplane_ctx_get_ifp_bridge_vlan_info(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return &ctx->u.intf.bvinfo;
+}
+
+void dplane_ctx_set_ifp_family(struct zebra_dplane_ctx *ctx, uint8_t family)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.intf.family = family;
+}
+
+uint8_t dplane_ctx_get_ifp_family(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.intf.family;
+}
+
+void dplane_ctx_set_ifp_zltype(struct zebra_dplane_ctx *ctx,
+ enum zebra_link_type zltype)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.intf.zltype = zltype;
+}
+
+enum zebra_link_type
+dplane_ctx_get_ifp_zltype(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.intf.zltype;
+}
+
+void dplane_ctx_set_ifp_link_ifindex(struct zebra_dplane_ctx *ctx,
+ ifindex_t link_ifindex)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.intf.link_ifindex = link_ifindex;
+}
+
+ifindex_t dplane_ctx_get_ifp_link_ifindex(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.intf.link_ifindex;
+}
+
+void dplane_ctx_set_ifp_desc(struct zebra_dplane_ctx *ctx, const char *desc)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ strlcpy(ctx->u.intf.desc, desc, sizeof(ctx->u.intf.desc));
+}
+
+char *dplane_ctx_get_ifp_desc(struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.intf.desc;
+}
+
+void dplane_ctx_set_ifp_flags(struct zebra_dplane_ctx *ctx, uint64_t flags)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.intf.flags = flags;
+}
+
+uint64_t dplane_ctx_get_ifp_flags(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.intf.flags;
+}
+
+void dplane_ctx_set_ifp_bypass(struct zebra_dplane_ctx *ctx, uint8_t bypass)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.intf.bypass = bypass;
+}
+
+uint8_t dplane_ctx_get_ifp_bypass(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.intf.bypass;
+}
+
+void dplane_ctx_set_ifp_bridge_ifindex(struct zebra_dplane_ctx *ctx,
+ ifindex_t bridge_ifindex)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.intf.bridge_ifindex = bridge_ifindex;
+}
+
+ifindex_t dplane_ctx_get_ifp_bridge_ifindex(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.intf.bridge_ifindex;
+}
+
+void dplane_ctx_set_ifp_zif_slave_type(struct zebra_dplane_ctx *ctx,
+ enum zebra_slave_iftype zslave_type)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.intf.zslave_type = zslave_type;
+}
+
+enum zebra_slave_iftype
+dplane_ctx_get_ifp_zif_slave_type(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.intf.zslave_type;
+}
+
+void dplane_ctx_set_ifp_master_ifindex(struct zebra_dplane_ctx *ctx,
+ ifindex_t master_ifindex)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.intf.master_ifindex = master_ifindex;
+}
+
+ifindex_t dplane_ctx_get_ifp_master_ifindex(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.intf.master_ifindex;
+}
+
+void dplane_ctx_set_ifp_mtu(struct zebra_dplane_ctx *ctx, uint32_t mtu)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.intf.mtu = mtu;
+}
+
+uint32_t dplane_ctx_get_ifp_mtu(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.intf.mtu;
+}
+
+void dplane_ctx_set_ifp_vrf_id(struct zebra_dplane_ctx *ctx, vrf_id_t vrf_id)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.intf.vrf_id = vrf_id;
+}
+
+vrf_id_t dplane_ctx_get_ifp_vrf_id(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.intf.vrf_id;
+}
+
+void dplane_ctx_set_ifp_link_nsid(struct zebra_dplane_ctx *ctx,
+ ns_id_t link_nsid)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.intf.link_nsid = link_nsid;
+}
+
+ns_id_t dplane_ctx_get_ifp_link_nsid(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.intf.link_nsid;
+}
+
+void dplane_ctx_set_ifp_startup(struct zebra_dplane_ctx *ctx, bool startup)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.intf.startup = startup;
+}
+
+bool dplane_ctx_get_ifp_startup(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.intf.startup;
+}
+
+void dplane_ctx_set_ifp_protodown_set(struct zebra_dplane_ctx *ctx, bool set)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.intf.protodown_set = set;
+}
+
+bool dplane_ctx_get_ifp_protodown_set(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.intf.protodown_set;
+}
+
+void dplane_ctx_set_ifp_protodown(struct zebra_dplane_ctx *ctx, bool protodown)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.intf.protodown = protodown;
+}
+
+bool dplane_ctx_get_ifp_protodown(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.intf.protodown;
+}
+
+ifindex_t dplane_ctx_get_ifp_bond_ifindex(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.intf.bond_ifindex;
+}
+
+void dplane_ctx_set_ifp_rc_bitfield(struct zebra_dplane_ctx *ctx,
+ uint32_t rc_bitfield)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.intf.rc_bitfield = rc_bitfield;
+}
+
+uint32_t dplane_ctx_get_ifp_rc_bitfield(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.intf.rc_bitfield;
+}
+
+void dplane_ctx_set_ifp_gre_info(struct zebra_dplane_ctx *ctx,
+ struct zebra_l2info_gre *grinfo)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.intf.grinfo = *grinfo;
+}
+
+const struct zebra_l2info_gre *
+dplane_ctx_get_ifp_gre_info(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return &ctx->u.intf.grinfo;
+}
+
+void dplane_ctx_set_ifp_vxlan_info(struct zebra_dplane_ctx *ctx,
+ struct zebra_l2info_vxlan *vxinfo)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.intf.vxinfo = *vxinfo;
+}
+
+const struct zebra_l2info_vxlan *
+dplane_ctx_get_ifp_vxlan_info(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return &ctx->u.intf.vxinfo;
+}
+
+void dplane_ctx_set_ifp_vlan_info(struct zebra_dplane_ctx *ctx,
+ struct zebra_l2info_vlan *vinfo)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.intf.vinfo = *vinfo;
+}
+
+const struct zebra_l2info_vlan *
+dplane_ctx_get_ifp_vlan_info(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return &ctx->u.intf.vinfo;
+}
+
+void dplane_ctx_set_ifp_bridge_info(struct zebra_dplane_ctx *ctx,
+ struct zebra_l2info_bridge *binfo)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.intf.binfo = *binfo;
+}
+
+const struct zebra_l2info_bridge *
+dplane_ctx_get_ifp_bridge_info(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return &ctx->u.intf.binfo;
+}
+
+void dplane_ctx_set_ifp_table_id(struct zebra_dplane_ctx *ctx,
+ uint32_t table_id)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.intf.table_id = table_id;
+}
+
+uint32_t dplane_ctx_get_ifp_table_id(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.intf.table_id;
+}
+
+void dplane_ctx_set_ifp_hw_addr(struct zebra_dplane_ctx *ctx,
+ int32_t hw_addr_len, uint8_t *hw_addr)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.intf.hw_addr_len = hw_addr_len;
+ memcpy(ctx->u.intf.hw_addr, hw_addr, hw_addr_len);
+}
+
+int32_t dplane_ctx_get_ifp_hw_addr_len(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.intf.hw_addr_len;
+}
+
+const uint8_t *dplane_ctx_get_ifp_hw_addr(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.intf.hw_addr;
+}
+
+void dplane_ctx_set_ifp_bond_ifindex(struct zebra_dplane_ctx *ctx,
+ ifindex_t bond_ifindex)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.intf.bond_ifindex = bond_ifindex;
+}
+
+enum zebra_iftype
+dplane_ctx_get_ifp_zif_type(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.intf.zif_type;
+}
+
+void dplane_ctx_set_ifp_zif_type(struct zebra_dplane_ctx *ctx,
+ enum zebra_iftype zif_type)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.intf.zif_type = zif_type;
+}
+
void dplane_ctx_set_ifname(struct zebra_dplane_ctx *ctx, const char *ifname)
{
DPLANE_CTX_VALID(ctx);
@@ -2068,6 +2572,13 @@ bool dplane_ctx_intf_is_connected(const struct zebra_dplane_ctx *ctx)
return (ctx->u.intf.flags & DPLANE_INTF_CONNECTED);
}
+bool dplane_ctx_intf_is_noprefixroute(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return (ctx->u.intf.flags & DPLANE_INTF_NOPREFIXROUTE);
+}
+
bool dplane_ctx_intf_is_secondary(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
@@ -2096,6 +2607,13 @@ void dplane_ctx_intf_set_secondary(struct zebra_dplane_ctx *ctx)
ctx->u.intf.flags |= DPLANE_INTF_SECONDARY;
}
+void dplane_ctx_intf_set_noprefixroute(struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.intf.flags |= DPLANE_INTF_NOPREFIXROUTE;
+}
+
void dplane_ctx_intf_set_broadcast(struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
@@ -2111,6 +2629,16 @@ const struct prefix *dplane_ctx_get_intf_addr(
return &(ctx->u.intf.prefix);
}
+
+/* Accessors for SRv6 encapsulation source address information */
+const struct in6_addr *
+dplane_ctx_get_srv6_encap_srcaddr(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return &(ctx->u.srv6_encap.srcaddr);
+}
+
void dplane_ctx_set_intf_addr(struct zebra_dplane_ctx *ctx,
const struct prefix *p)
{
@@ -2185,6 +2713,20 @@ void dplane_ctx_set_intf_label(struct zebra_dplane_ctx *ctx, const char *label)
}
}
+void dplane_ctx_set_intf_txqlen(struct zebra_dplane_ctx *ctx, uint32_t txqlen)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.intf.txqlen = txqlen;
+}
+
+uint32_t dplane_ctx_get_intf_txqlen(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.intf.txqlen;
+}
+
/* Accessors for MAC information */
vlanid_t dplane_ctx_mac_get_vlan(const struct zebra_dplane_ctx *ctx)
{
@@ -2307,6 +2849,25 @@ dplane_ctx_gre_get_info(const struct zebra_dplane_ctx *ctx)
return &ctx->u.gre.info;
}
+/***********************************************************************
+ * PBR RULE ACCESSORS - start
+ **********************************************************************/
+
+/*
+ * This accessor fills one or two lib/pbr structs from the PBR context.
+ * New dataplane modules should use this interface where possible instead
+ * of adding more accessors that return fields from 'struct pbr_rule'.
+ */
+void dplane_ctx_rule_get(const struct zebra_dplane_ctx *ctx,
+ struct pbr_rule *pNew, struct pbr_rule *pOld)
+{
+ DPLANE_CTX_VALID(ctx);
+ if (pNew)
+ *pNew = ctx->u.rule.new.prule;
+ if (pOld)
+ *pOld = ctx->u.rule.old.prule;
+}
+
/* Accessors for PBR rule information */
int dplane_ctx_rule_get_sock(const struct zebra_dplane_ctx *ctx)
{
@@ -2319,7 +2880,7 @@ const char *dplane_ctx_rule_get_ifname(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return ctx->u.rule.new.ifname;
+ return ctx->u.rule.new.prule.ifname;
}
int dplane_ctx_rule_get_unique(const struct zebra_dplane_ctx *ctx)
@@ -2340,112 +2901,112 @@ uint32_t dplane_ctx_rule_get_priority(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return ctx->u.rule.new.priority;
+ return ctx->u.rule.new.prule.priority;
}
uint32_t dplane_ctx_rule_get_old_priority(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return ctx->u.rule.old.priority;
+ return ctx->u.rule.old.prule.priority;
}
uint32_t dplane_ctx_rule_get_table(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return ctx->u.rule.new.table;
+ return ctx->u.rule.new.prule.action.table;
}
uint32_t dplane_ctx_rule_get_old_table(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return ctx->u.rule.old.table;
+ return ctx->u.rule.old.prule.action.table;
}
uint32_t dplane_ctx_rule_get_filter_bm(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return ctx->u.rule.new.filter_bm;
+ return ctx->u.rule.new.prule.filter.filter_bm;
}
uint32_t dplane_ctx_rule_get_old_filter_bm(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return ctx->u.rule.old.filter_bm;
+ return ctx->u.rule.old.prule.filter.filter_bm;
}
uint32_t dplane_ctx_rule_get_fwmark(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return ctx->u.rule.new.fwmark;
+ return ctx->u.rule.new.prule.filter.fwmark;
}
uint32_t dplane_ctx_rule_get_old_fwmark(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return ctx->u.rule.old.fwmark;
+ return ctx->u.rule.old.prule.filter.fwmark;
}
uint8_t dplane_ctx_rule_get_ipproto(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return ctx->u.rule.new.ip_proto;
+ return ctx->u.rule.new.prule.filter.ip_proto;
}
uint8_t dplane_ctx_rule_get_old_ipproto(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return ctx->u.rule.old.ip_proto;
+ return ctx->u.rule.old.prule.filter.ip_proto;
}
uint16_t dplane_ctx_rule_get_src_port(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return ctx->u.rule.new.src_port;
+ return ctx->u.rule.new.prule.filter.src_port;
}
uint16_t dplane_ctx_rule_get_old_src_port(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return ctx->u.rule.old.src_port;
+ return ctx->u.rule.old.prule.filter.src_port;
}
uint16_t dplane_ctx_rule_get_dst_port(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return ctx->u.rule.new.dst_port;
+ return ctx->u.rule.new.prule.filter.dst_port;
}
uint16_t dplane_ctx_rule_get_old_dst_port(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return ctx->u.rule.old.dst_port;
+ return ctx->u.rule.old.prule.filter.dst_port;
}
uint8_t dplane_ctx_rule_get_dsfield(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return ctx->u.rule.new.dsfield;
+ return ctx->u.rule.new.prule.filter.dsfield;
}
uint8_t dplane_ctx_rule_get_old_dsfield(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return ctx->u.rule.old.dsfield;
+ return ctx->u.rule.old.prule.filter.dsfield;
}
const struct prefix *
@@ -2453,7 +3014,7 @@ dplane_ctx_rule_get_src_ip(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return &(ctx->u.rule.new.src_ip);
+ return &(ctx->u.rule.new.prule.filter.src_ip);
}
const struct prefix *
@@ -2461,7 +3022,7 @@ dplane_ctx_rule_get_old_src_ip(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return &(ctx->u.rule.old.src_ip);
+ return &(ctx->u.rule.old.prule.filter.src_ip);
}
const struct prefix *
@@ -2469,7 +3030,7 @@ dplane_ctx_rule_get_dst_ip(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return &(ctx->u.rule.new.dst_ip);
+ return &(ctx->u.rule.new.prule.filter.dst_ip);
}
const struct prefix *
@@ -2477,9 +3038,65 @@ dplane_ctx_rule_get_old_dst_ip(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return &(ctx->u.rule.old.dst_ip);
+ return &(ctx->u.rule.old.prule.filter.dst_ip);
+}
+
+const struct ethaddr *
+dplane_ctx_rule_get_smac(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return &(ctx->u.rule.new.smac);
+}
+
+const struct ethaddr *
+dplane_ctx_rule_get_dmac(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return &(ctx->u.rule.new.dmac);
+}
+
+int dplane_ctx_rule_get_out_ifindex(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.rule.new.out_ifindex;
}
+intptr_t dplane_ctx_rule_get_old_dp_flow_ptr(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.rule.old.dp_flow_ptr;
+}
+
+intptr_t dplane_ctx_rule_get_dp_flow_ptr(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.rule.new.dp_flow_ptr;
+}
+
+void dplane_ctx_rule_set_dp_flow_ptr(struct zebra_dplane_ctx *ctx,
+ intptr_t dp_flow_ptr)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.rule.new.dp_flow_ptr = dp_flow_ptr;
+}
+
+vrf_id_t dplane_ctx_rule_get_vrfid(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.rule.new.prule.vrf_id;
+}
+
+/***********************************************************************
+ * PBR RULE ACCESSORS - end
+ **********************************************************************/
+
uint32_t dplane_ctx_get_br_port_flags(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
@@ -2548,55 +3165,6 @@ void dplane_ctx_get_pbr_ipset_entry(const struct zebra_dplane_ctx *ctx,
memcpy(entry, &ctx->u.ipset_entry.entry, sizeof(struct zebra_pbr_ipset_entry));
}
-const struct ethaddr *
-dplane_ctx_rule_get_smac(const struct zebra_dplane_ctx *ctx)
-{
- DPLANE_CTX_VALID(ctx);
-
- return &(ctx->u.rule.new.smac);
-}
-
-const struct ethaddr *
-dplane_ctx_rule_get_dmac(const struct zebra_dplane_ctx *ctx)
-{
- DPLANE_CTX_VALID(ctx);
-
- return &(ctx->u.rule.new.dmac);
-}
-
-int dplane_ctx_rule_get_out_ifindex(const struct zebra_dplane_ctx *ctx)
-{
- DPLANE_CTX_VALID(ctx);
-
- return ctx->u.rule.new.out_ifindex;
-}
-
-intptr_t dplane_ctx_rule_get_old_dp_flow_ptr(const struct zebra_dplane_ctx *ctx)
-{
- DPLANE_CTX_VALID(ctx);
-
- return ctx->u.rule.old.dp_flow_ptr;
-}
-
-intptr_t dplane_ctx_rule_get_dp_flow_ptr(const struct zebra_dplane_ctx *ctx)
-{
- DPLANE_CTX_VALID(ctx);
-
- return ctx->u.rule.new.dp_flow_ptr;
-}
-
-void dplane_ctx_rule_set_dp_flow_ptr(struct zebra_dplane_ctx *ctx,
- intptr_t dp_flow_ptr)
-{
- DPLANE_CTX_VALID(ctx);
-
- ctx->u.rule.new.dp_flow_ptr = dp_flow_ptr;
-}
-
-/*
- * End of dplane context accessors
- */
-
/* Optional extra info about interfaces in nexthops - a plugin must enable
* this extra info.
*/
@@ -2798,7 +3366,7 @@ int dplane_ctx_route_init_basic(struct zebra_dplane_ctx *ctx,
{
int ret = EINVAL;
- if (!ctx || !re)
+ if (!ctx)
return ret;
dplane_intf_extra_list_init(&ctx->u.rinfo.intf_extra_list);
@@ -2806,6 +3374,13 @@ int dplane_ctx_route_init_basic(struct zebra_dplane_ctx *ctx,
ctx->zd_op = op;
ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS;
+ /* This function may be called to create/init a dplane context, not
+ * necessarily to copy a route object. Let's return if there is no route
+ * object to copy.
+ */
+ if (!re)
+ return AOK;
+
ctx->u.rinfo.zd_type = re->type;
ctx->u.rinfo.zd_old_type = re->type;
@@ -2837,6 +3412,8 @@ int dplane_ctx_route_init_basic(struct zebra_dplane_ctx *ctx,
/*
* Initialize a context block for a route update from zebra data structs.
+ * If the `rn` or `re` parameters are NULL, this function only initializes the
+ * dplane context without copying a route object into it.
*/
int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op,
struct route_node *rn, struct route_entry *re)
@@ -2853,10 +3430,18 @@ int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op,
const struct interface *ifp;
struct dplane_intf_extra *if_extra;
- if (!ctx || !rn || !re)
+ if (!ctx)
return ret;
/*
+ * Initialize the dplane context and return, if there is no route
+ * object to copy
+ */
+ if (!re || !rn)
+ return dplane_ctx_route_init_basic(ctx, op, NULL, NULL, NULL,
+ AFI_UNSPEC, SAFI_UNSPEC);
+
+ /*
* Let's grab the data from the route_node
* so that we can call a helper function
*/
@@ -3414,24 +3999,8 @@ static void dplane_ctx_rule_init_single(struct dplane_ctx_rule *dplane_rule,
{
struct zebra_neigh_ent *n;
- dplane_rule->priority = rule->rule.priority;
- dplane_rule->table = rule->rule.action.table;
-
- dplane_rule->filter_bm = rule->rule.filter.filter_bm;
- dplane_rule->fwmark = rule->rule.filter.fwmark;
- dplane_rule->dsfield = rule->rule.filter.dsfield;
- dplane_rule->ip_proto = rule->rule.filter.ip_proto;
- dplane_rule->src_port = rule->rule.filter.src_port;
- dplane_rule->dst_port = rule->rule.filter.dst_port;
- prefix_copy(&(dplane_rule->dst_ip), &rule->rule.filter.dst_ip);
- prefix_copy(&(dplane_rule->src_ip), &rule->rule.filter.src_ip);
+ dplane_rule->prule = rule->rule;
- 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);
dplane_rule->dp_flow_ptr = rule->action.dp_flow_ptr;
n = rule->action.neigh;
if (n && (n->flags & ZEBRA_NEIGH_ENT_ACTIVE)) {
@@ -3533,6 +4102,7 @@ static int dplane_ctx_iptable_init(struct zebra_dplane_ctx *ctx,
ctx->zd_vrf_id = iptable->vrf_id;
memcpy(&ctx->u.iptable, iptable, sizeof(struct zebra_pbr_iptable));
+ ctx->u.iptable.interface_name_list = NULL;
if (iptable->nb_interface > 0) {
ctx->u.iptable.interface_name_list = list_new();
ctx->u.iptable.interface_name_list->del =
@@ -3785,18 +4355,12 @@ tc_qdisc_update_internal(enum dplane_op_e op,
/* Obtain context block */
ctx = dplane_ctx_alloc();
- if (!ctx) {
- ret = ENOMEM;
- goto done;
- }
-
/* Init context with info from zebra data structs */
ret = dplane_ctx_tc_qdisc_init(ctx, op, qdisc);
if (ret == AOK)
ret = dplane_update_enqueue(ctx);
-done:
/* Update counter */
atomic_fetch_add_explicit(&zdplane_info.dg_tcs_in, 1,
memory_order_relaxed);
@@ -3805,8 +4369,7 @@ done:
} else {
atomic_fetch_add_explicit(&zdplane_info.dg_tcs_errors, 1,
memory_order_relaxed);
- if (ctx)
- dplane_ctx_free(&ctx);
+ dplane_ctx_free(&ctx);
}
return result;
@@ -3822,18 +4385,12 @@ tc_class_update_internal(enum dplane_op_e op, struct zebra_tc_class *class)
/* Obtain context block */
ctx = dplane_ctx_alloc();
- if (!ctx) {
- ret = ENOMEM;
- goto done;
- }
-
/* Init context with info from zebra data structs */
ret = dplane_ctx_tc_class_init(ctx, op, class);
if (ret == AOK)
ret = dplane_update_enqueue(ctx);
-done:
/* Update counter */
atomic_fetch_add_explicit(&zdplane_info.dg_tcs_in, 1,
memory_order_relaxed);
@@ -3842,8 +4399,7 @@ done:
} else {
atomic_fetch_add_explicit(&zdplane_info.dg_tcs_errors, 1,
memory_order_relaxed);
- if (ctx)
- dplane_ctx_free(&ctx);
+ dplane_ctx_free(&ctx);
}
return result;
@@ -3859,18 +4415,12 @@ tc_filter_update_internal(enum dplane_op_e op, struct zebra_tc_filter *filter)
/* Obtain context block */
ctx = dplane_ctx_alloc();
- if (!ctx) {
- ret = ENOMEM;
- goto done;
- }
-
/* Init context with info from zebra data structs */
ret = dplane_ctx_tc_filter_init(ctx, op, filter);
if (ret == AOK)
ret = dplane_update_enqueue(ctx);
-done:
/* Update counter */
atomic_fetch_add_explicit(&zdplane_info.dg_tcs_in, 1,
memory_order_relaxed);
@@ -3879,8 +4429,7 @@ done:
} else {
atomic_fetch_add_explicit(&zdplane_info.dg_tcs_errors, 1,
memory_order_relaxed);
- if (ctx)
- dplane_ctx_free(&ctx);
+ dplane_ctx_free(&ctx);
}
return result;
@@ -3943,16 +4492,11 @@ dplane_nexthop_update_internal(struct nhg_hash_entry *nhe, enum dplane_op_e op)
/* Obtain context block */
ctx = dplane_ctx_alloc();
- if (!ctx) {
- ret = ENOMEM;
- goto done;
- }
ret = dplane_ctx_nexthop_init(ctx, op, nhe);
if (ret == AOK)
ret = dplane_update_enqueue(ctx);
-done:
/* Update counter */
atomic_fetch_add_explicit(&zdplane_info.dg_nexthops_in, 1,
memory_order_relaxed);
@@ -4083,8 +4627,6 @@ dplane_route_notif_update(struct route_node *rn,
goto done;
new_ctx = dplane_ctx_alloc();
- if (new_ctx == NULL)
- goto done;
/* Init context with info from zebra data structs */
dplane_ctx_route_init(new_ctx, op, rn, re);
@@ -4216,10 +4758,6 @@ dplane_lsp_notif_update(struct zebra_lsp *lsp, enum dplane_op_e op,
/* Obtain context block */
ctx = dplane_ctx_alloc();
- if (ctx == NULL) {
- ret = ENOMEM;
- goto done;
- }
/* Copy info from zebra LSP */
ret = dplane_ctx_lsp_init(ctx, op, lsp);
@@ -4259,8 +4797,7 @@ done:
else {
atomic_fetch_add_explicit(&zdplane_info.dg_lsp_errors, 1,
memory_order_relaxed);
- if (ctx)
- dplane_ctx_free(&ctx);
+ dplane_ctx_free(&ctx);
}
return result;
}
@@ -4589,16 +5126,11 @@ dplane_intf_update_internal(const struct interface *ifp, enum dplane_op_e op)
/* Obtain context block */
ctx = dplane_ctx_alloc();
- if (!ctx) {
- ret = ENOMEM;
- goto done;
- }
ret = dplane_ctx_intf_init(ctx, op, ifp);
if (ret == AOK)
ret = dplane_update_enqueue(ctx);
-done:
/* Update counter */
atomic_fetch_add_explicit(&zdplane_info.dg_intfs_in, 1,
memory_order_relaxed);
@@ -4640,18 +5172,6 @@ enum zebra_dplane_result dplane_intf_update(const struct interface *ifp)
}
/*
- * Enqueue a interface delete for the dataplane.
- */
-enum zebra_dplane_result dplane_intf_delete(const struct interface *ifp)
-{
- enum zebra_dplane_result ret = ZEBRA_DPLANE_REQUEST_FAILURE;
-
- if (ifp)
- ret = dplane_intf_update_internal(ifp, DPLANE_OP_INTF_DELETE);
- return ret;
-}
-
-/*
* Enqueue vxlan/evpn mac add (or update).
*/
enum zebra_dplane_result
@@ -5337,8 +5857,10 @@ dplane_gre_set(struct interface *ifp, struct interface *ifp_link,
ctx = dplane_ctx_alloc();
- if (!ifp)
- return result;
+ if (!ifp) {
+ ret = EINVAL;
+ goto done;
+ }
if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
zlog_debug("init dplane ctx %s: if %s link %s%s",
@@ -5350,8 +5872,11 @@ dplane_gre_set(struct interface *ifp, struct interface *ifp_link,
ctx->zd_op = op;
ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS;
zns = zebra_ns_lookup(ifp->vrf->vrf_id);
- if (!zns)
- return result;
+ if (!zns) {
+ ret = EINVAL;
+ goto done;
+ }
+
dplane_ctx_ns_init(ctx, zns, false);
dplane_ctx_set_ifname(ctx, ifp->name);
@@ -5370,6 +5895,7 @@ dplane_gre_set(struct interface *ifp, struct interface *ifp_link,
/* Enqueue context for processing */
ret = dplane_update_enqueue(ctx);
+done:
/* Update counter */
atomic_fetch_add_explicit(&zdplane_info.dg_gre_set_in, 1,
memory_order_relaxed);
@@ -5387,6 +5913,59 @@ dplane_gre_set(struct interface *ifp, struct interface *ifp_link,
}
/*
+ * Common helper api for SRv6 encapsulation source address set
+ */
+enum zebra_dplane_result
+dplane_srv6_encap_srcaddr_set(const struct in6_addr *addr, ns_id_t ns_id)
+{
+ enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
+ struct zebra_dplane_ctx *ctx = NULL;
+ enum dplane_op_e op = DPLANE_OP_SRV6_ENCAP_SRCADDR_SET;
+ int ret;
+ struct zebra_ns *zns;
+
+ if (!addr)
+ return result;
+
+ if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
+ zlog_debug("init dplane ctx %s: addr %pI6", dplane_op2str(op),
+ addr);
+ }
+
+ zns = zebra_ns_lookup(ns_id);
+ if (!zns)
+ return result;
+
+ ctx = dplane_ctx_alloc();
+
+ ctx->zd_op = op;
+ ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS;
+
+ dplane_ctx_ns_init(ctx, zns, false);
+
+ /* Init the SRv6 encap source address specific data area */
+ memcpy(&ctx->u.srv6_encap.srcaddr, addr,
+ sizeof(ctx->u.srv6_encap.srcaddr));
+
+ /* Update counter */
+ atomic_fetch_add_explicit(&zdplane_info.dg_srv6_encap_srcaddr_set_in, 1,
+ memory_order_relaxed);
+
+ /* Enqueue context for processing */
+ ret = dplane_update_enqueue(ctx);
+
+ if (ret == AOK)
+ result = ZEBRA_DPLANE_REQUEST_QUEUED;
+ else {
+ atomic_fetch_add_explicit(&zdplane_info
+ .dg_srv6_encap_srcaddr_set_errors,
+ 1, memory_order_relaxed);
+ dplane_ctx_free(&ctx);
+ }
+ return result;
+}
+
+/*
* Handler for 'show dplane'
*/
int dplane_show_helper(struct vty *vty, bool detailed)
@@ -5578,7 +6157,7 @@ int dplane_provider_register(const char *name,
struct zebra_dplane_provider **prov_p)
{
int ret = 0;
- struct zebra_dplane_provider *p = NULL, *last;
+ struct zebra_dplane_provider *p = NULL, *last, *prev = NULL;
/* Validate */
if (fp == NULL) {
@@ -5621,10 +6200,11 @@ int dplane_provider_register(const char *name,
frr_each (dplane_prov_list, &zdplane_info.dg_providers, last) {
if (last->dp_priority > p->dp_priority)
break;
+ prev = last;
}
if (last)
- dplane_prov_list_add_after(&zdplane_info.dg_providers, last, p);
+ dplane_prov_list_add_after(&zdplane_info.dg_providers, prev, p);
else
dplane_prov_list_add_tail(&zdplane_info.dg_providers, p);
@@ -5764,12 +6344,27 @@ void dplane_provider_enqueue_out_ctx(struct zebra_dplane_provider *prov,
memory_order_relaxed);
}
+static struct zebra_dplane_ctx *
+dplane_provider_dequeue_out_ctx(struct zebra_dplane_provider *prov)
+{
+ struct zebra_dplane_ctx *ctx;
+
+ ctx = dplane_ctx_list_pop(&(prov->dp_ctx_out_list));
+ if (!ctx)
+ return NULL;
+
+ atomic_fetch_sub_explicit(&(prov->dp_out_queued), 1,
+ memory_order_relaxed);
+
+ return ctx;
+}
+
/*
* Accessor for provider object
*/
bool dplane_provider_is_threaded(const struct zebra_dplane_provider *prov)
{
- return (prov->dp_flags & DPLANE_PROV_FLAG_THREADED);
+ return CHECK_FLAG(prov->dp_flags, DPLANE_PROV_FLAG_THREADED);
}
#ifdef HAVE_NETLINK
@@ -6093,6 +6688,13 @@ static void kernel_dplane_log_detail(struct zebra_dplane_ctx *ctx)
case DPLANE_OP_TC_FILTER_ADD:
case DPLANE_OP_TC_FILTER_DELETE:
case DPLANE_OP_TC_FILTER_UPDATE:
+ case DPLANE_OP_STARTUP_STAGE:
+ break;
+
+ case DPLANE_OP_SRV6_ENCAP_SRCADDR_SET:
+ zlog_debug("Dplane SRv6 encap source address set op %s, addr %pI6",
+ dplane_op2str(dplane_ctx_get_op(ctx)),
+ &ctx->u.srv6_encap.srcaddr);
break;
}
}
@@ -6264,7 +6866,15 @@ static void kernel_dplane_handle_result(struct zebra_dplane_ctx *ctx)
case DPLANE_OP_INTF_NETCONFIG:
break;
+ case DPLANE_OP_SRV6_ENCAP_SRCADDR_SET:
+ if (res != ZEBRA_DPLANE_REQUEST_SUCCESS)
+ atomic_fetch_add_explicit(&zdplane_info
+ .dg_srv6_encap_srcaddr_set_errors,
+ 1, memory_order_relaxed);
+ break;
+
case DPLANE_OP_NONE:
+ case DPLANE_OP_STARTUP_STAGE:
if (res != ZEBRA_DPLANE_REQUEST_SUCCESS)
atomic_fetch_add_explicit(&zdplane_info.dg_other_errors,
1, memory_order_relaxed);
@@ -6371,6 +6981,31 @@ static int kernel_dplane_process_func(struct zebra_dplane_provider *prov)
return 0;
}
+static int kernel_dplane_shutdown_func(struct zebra_dplane_provider *prov,
+ bool early)
+{
+ struct zebra_dplane_ctx *ctx;
+
+ if (early)
+ return 1;
+
+ ctx = dplane_provider_dequeue_in_ctx(prov);
+ while (ctx) {
+ dplane_ctx_free(&ctx);
+
+ ctx = dplane_provider_dequeue_in_ctx(prov);
+ }
+
+ ctx = dplane_provider_dequeue_out_ctx(prov);
+ while (ctx) {
+ dplane_ctx_free(&ctx);
+
+ ctx = dplane_provider_dequeue_out_ctx(prov);
+ }
+
+ return 1;
+}
+
#ifdef DPLANE_TEST_PROVIDER
/*
@@ -6443,12 +7078,10 @@ static void dplane_provider_init(void)
{
int ret;
- ret = dplane_provider_register("Kernel",
- DPLANE_PRIO_KERNEL,
+ ret = dplane_provider_register("Kernel", DPLANE_PRIO_KERNEL,
DPLANE_PROV_FLAGS_DEFAULT, NULL,
kernel_dplane_process_func,
- NULL,
- NULL, NULL);
+ kernel_dplane_shutdown_func, NULL, NULL);
if (ret != AOK)
zlog_err("Unable to register kernel dplane provider: %d",
@@ -6791,7 +7424,7 @@ static void dplane_thread_loop(struct event *event)
dplane_provider_lock(prov);
while (counter < limit) {
- ctx = dplane_ctx_list_pop(&(prov->dp_ctx_out_list));
+ ctx = dplane_provider_dequeue_out_ctx(prov);
if (ctx) {
dplane_ctx_list_add_tail(&work_list, ctx);
counter++;
@@ -6849,6 +7482,7 @@ static void dplane_thread_loop(struct event *event)
void zebra_dplane_shutdown(void)
{
struct zebra_dplane_provider *dp;
+ struct zebra_dplane_ctx *ctx;
if (IS_ZEBRA_DEBUG_DPLANE)
zlog_debug("Zebra dataplane shutdown called");
@@ -6876,8 +7510,25 @@ void zebra_dplane_shutdown(void)
}
/* TODO -- Clean-up provider objects */
+ dp = dplane_prov_list_first(&zdplane_info.dg_providers);
+ while (dp) {
+ dplane_prov_list_del(&zdplane_info.dg_providers, dp);
+ XFREE(MTYPE_DP_PROV, dp);
+
+ dp = dplane_prov_list_first(&zdplane_info.dg_providers);
+ }
/* TODO -- Clean queue(s), free memory */
+ DPLANE_LOCK();
+ {
+ ctx = dplane_ctx_list_pop(&zdplane_info.dg_update_list);
+ while (ctx) {
+ dplane_ctx_free(&ctx);
+
+ ctx = dplane_ctx_list_pop(&zdplane_info.dg_update_list);
+ }
+ }
+ DPLANE_UNLOCK();
}
/*
@@ -6955,6 +7606,25 @@ void zebra_dplane_start(void)
frr_pthread_run(zdplane_info.dg_pthread, NULL);
}
+enum zebra_dplane_startup_notifications
+dplane_ctx_get_startup_spot(struct zebra_dplane_ctx *ctx)
+{
+ return ctx->u.spot;
+}
+
+void zebra_dplane_startup_stage(struct zebra_ns *zns,
+ enum zebra_dplane_startup_notifications spot)
+{
+ struct zebra_dplane_ctx *ctx = dplane_ctx_alloc();
+
+ ctx->zd_op = DPLANE_OP_STARTUP_STAGE;
+ ctx->zd_status = ZEBRA_DPLANE_REQUEST_QUEUED;
+
+ ctx->u.spot = spot;
+ dplane_ctx_set_ns_id(ctx, zns->ns_id);
+
+ dplane_provider_enqueue_to_zebra(ctx);
+}
/*
* Initialize the dataplane module at startup; called by zebra rib_init()
*/
diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h
index 6716c0ffb6..060b1c8b9e 100644
--- a/zebra/zebra_dplane.h
+++ b/zebra/zebra_dplane.h
@@ -11,17 +11,26 @@
#include "lib/prefix.h"
#include "lib/nexthop.h"
#include "lib/nexthop_group.h"
+#include "lib/pbr.h"
#include "lib/vlan.h"
#include "zebra/zebra_ns.h"
#include "zebra/rib.h"
#include "zebra/zserv.h"
#include "zebra/zebra_mpls.h"
#include "zebra/zebra_nhg.h"
+#include "zebra/ge_netlink.h"
#ifdef __cplusplus
extern "C" {
#endif
+/* Retrieve the dataplane API version number; see libfrr.h to decode major,
+ * minor, sub version values.
+ * Plugins should pay attention to the major version number, at least, to
+ * be able to detect API changes that may not be backward-compatible.
+ */
+uint32_t zebra_dplane_get_version(void);
+
/* Key netlink info from zebra ns */
struct zebra_dplane_info {
ns_id_t ns_id;
@@ -87,6 +96,11 @@ enum zebra_dplane_result {
ZEBRA_DPLANE_REQUEST_FAILURE,
};
+enum zebra_dplane_startup_notifications {
+ ZEBRA_DPLANE_INTERFACES_READ,
+ ZEBRA_DPLANE_TUNNELS_READ,
+ ZEBRA_DPLANE_ADDRESSES_READ,
+};
/*
* API between the zebra dataplane system and the main zebra processing
* context.
@@ -188,7 +202,13 @@ enum dplane_op_e {
DPLANE_OP_TC_CLASS_UPDATE,
DPLANE_OP_TC_FILTER_ADD,
DPLANE_OP_TC_FILTER_DELETE,
- DPLANE_OP_TC_FILTER_UPDATE
+ DPLANE_OP_TC_FILTER_UPDATE,
+
+ /* Startup Control */
+ DPLANE_OP_STARTUP_STAGE,
+
+ /* Source address for SRv6 encapsulation */
+ DPLANE_OP_SRV6_ENCAP_SRCADDR_SET,
};
/*
@@ -323,6 +343,122 @@ const char *dplane_ctx_get_ifname(const struct zebra_dplane_ctx *ctx);
void dplane_ctx_set_ifname(struct zebra_dplane_ctx *ctx, const char *ifname);
ifindex_t dplane_ctx_get_ifindex(const struct zebra_dplane_ctx *ctx);
void dplane_ctx_set_ifindex(struct zebra_dplane_ctx *ctx, ifindex_t ifindex);
+void dplane_ctx_set_ifp_bond_ifindex(struct zebra_dplane_ctx *ctx,
+ ifindex_t ifindex);
+ifindex_t dplane_ctx_get_ifp_bond_ifindex(const struct zebra_dplane_ctx *ctx);
+enum zebra_iftype
+dplane_ctx_get_ifp_zif_type(const struct zebra_dplane_ctx *ctx);
+void dplane_ctx_set_ifp_zif_type(struct zebra_dplane_ctx *ctx,
+ enum zebra_iftype zif_type);
+void dplane_ctx_set_ifp_table_id(struct zebra_dplane_ctx *ctx,
+ uint32_t table_id);
+uint32_t dplane_ctx_get_ifp_table_id(const struct zebra_dplane_ctx *ctx);
+void dplane_ctx_set_ifp_hw_addr(struct zebra_dplane_ctx *ctx,
+ int32_t hw_addr_len, uint8_t *hw_addr);
+int32_t dplane_ctx_get_ifp_hw_addr_len(const struct zebra_dplane_ctx *ctx);
+const uint8_t *dplane_ctx_get_ifp_hw_addr(const struct zebra_dplane_ctx *ctx);
+struct zebra_l2info_bridge;
+void dplane_ctx_set_ifp_bridge_info(struct zebra_dplane_ctx *ctx,
+ struct zebra_l2info_bridge *binfo);
+const struct zebra_l2info_bridge *
+dplane_ctx_get_ifp_bridge_info(const struct zebra_dplane_ctx *ctx);
+struct zebra_l2info_vlan;
+void dplane_ctx_set_ifp_vlan_info(struct zebra_dplane_ctx *ctx,
+ struct zebra_l2info_vlan *vinfo);
+const struct zebra_l2info_vlan *
+dplane_ctx_get_ifp_vlan_info(const struct zebra_dplane_ctx *ctx);
+struct zebra_l2info_vxlan;
+void dplane_ctx_set_ifp_vxlan_info(struct zebra_dplane_ctx *ctx,
+ struct zebra_l2info_vxlan *vxinfo);
+const struct zebra_l2info_vxlan *
+dplane_ctx_get_ifp_vxlan_info(const struct zebra_dplane_ctx *ctx);
+struct zebra_l2info_gre;
+void dplane_ctx_set_ifp_gre_info(struct zebra_dplane_ctx *ctx,
+ struct zebra_l2info_gre *greinfo);
+const struct zebra_l2info_gre *
+dplane_ctx_get_ifp_gre_info(const struct zebra_dplane_ctx *ctx);
+void dplane_ctx_set_ifp_zltype(struct zebra_dplane_ctx *ctx,
+ enum zebra_link_type zlt);
+enum zebra_link_type
+dplane_ctx_get_ifp_zltype(const struct zebra_dplane_ctx *ctx);
+void dplane_ctx_set_ifp_link_nsid(struct zebra_dplane_ctx *ctx, ns_id_t ns_id);
+ns_id_t dplane_ctx_get_ifp_link_nsid(const struct zebra_dplane_ctx *ctx);
+void dplane_ctx_set_ifp_desc(struct zebra_dplane_ctx *ctx, const char *desc);
+char *dplane_ctx_get_ifp_desc(struct zebra_dplane_ctx *ctx);
+void dplane_ctx_set_ifp_mtu(struct zebra_dplane_ctx *ctx, uint32_t mtu);
+uint32_t dplane_ctx_get_ifp_mtu(const struct zebra_dplane_ctx *ctx);
+void dplane_ctx_set_ifp_vrf_id(struct zebra_dplane_ctx *ctx, vrf_id_t vrf_id);
+vrf_id_t dplane_ctx_get_ifp_vrf_id(const struct zebra_dplane_ctx *ctx);
+enum zebra_slave_iftype;
+void dplane_ctx_set_ifp_zif_slave_type(struct zebra_dplane_ctx *ctx,
+ enum zebra_slave_iftype zslave_type);
+enum zebra_slave_iftype
+dplane_ctx_get_ifp_zif_slave_type(const struct zebra_dplane_ctx *ctx);
+void dplane_ctx_set_ifp_master_ifindex(struct zebra_dplane_ctx *ctx,
+ ifindex_t master_ifindex);
+ifindex_t dplane_ctx_get_ifp_master_ifindex(const struct zebra_dplane_ctx *ctx);
+void dplane_ctx_set_ifp_bridge_ifindex(struct zebra_dplane_ctx *ctx,
+ ifindex_t bridge_ifindex);
+ifindex_t dplane_ctx_get_ifp_bridge_ifindex(const struct zebra_dplane_ctx *ctx);
+void dplane_ctx_set_ifp_bypass(struct zebra_dplane_ctx *ctx, uint8_t bypass);
+uint8_t dplane_ctx_get_ifp_bypass(const struct zebra_dplane_ctx *ctx);
+void dplane_ctx_set_ifp_flags(struct zebra_dplane_ctx *ctx, uint64_t flags);
+uint64_t dplane_ctx_get_ifp_flags(const struct zebra_dplane_ctx *ctx);
+void dplane_ctx_set_ifp_protodown(struct zebra_dplane_ctx *ctx, bool protodown);
+bool dplane_ctx_get_ifp_protodown(const struct zebra_dplane_ctx *ctx);
+void dplane_ctx_set_ifp_startup(struct zebra_dplane_ctx *ctx, bool startup);
+bool dplane_ctx_get_ifp_startup(const struct zebra_dplane_ctx *ctx);
+void dplane_ctx_set_ifp_protodown_set(struct zebra_dplane_ctx *ctx, bool set);
+bool dplane_ctx_get_ifp_protodown_set(const struct zebra_dplane_ctx *ctx);
+void dplane_ctx_set_ifp_rc_bitfield(struct zebra_dplane_ctx *ctx,
+ uint32_t rc_bitfield);
+uint32_t dplane_ctx_get_ifp_rc_bitfield(const struct zebra_dplane_ctx *ctx);
+void dplane_ctx_set_ifp_link_ifindex(struct zebra_dplane_ctx *ctx,
+ ifindex_t link_ifindex);
+ifindex_t dplane_ctx_get_ifp_link_ifindex(const struct zebra_dplane_ctx *ctx);
+void dplane_ctx_set_ifp_family(struct zebra_dplane_ctx *ctx, uint8_t family);
+uint8_t dplane_ctx_get_ifp_family(const struct zebra_dplane_ctx *ctx);
+struct zebra_vxlan_vni_array;
+void dplane_ctx_set_ifp_vxlan_vni_array(struct zebra_dplane_ctx *ctx,
+ struct zebra_vxlan_vni_array *vniarray);
+
+/*
+ * These defines mirror the values for bridge values in linux
+ * at this point since we only have a linux implementation
+ * we don't need to do any type of translation. Let's just
+ * pass these through and use them
+ */
+#define DPLANE_BRIDGE_VLAN_INFO_PVID \
+ (1 << 1) /* VLAN is PVID, ingress untagged */
+#define DPLANE_BRIDGE_VLAN_INFO_RANGE_BEGIN \
+ (1 << 3) /* VLAN is start of vlan range */
+#define DPLANE_BRIDGE_VLAN_INFO_RANGE_END \
+ (1 << 4) /* VLAN is end of vlan range */
+const struct zebra_vxlan_vni_array *
+dplane_ctx_get_ifp_vxlan_vni_array(const struct zebra_dplane_ctx *ctx);
+struct zebra_dplane_bridge_vlan_info {
+ uint16_t flags;
+ uint16_t vid;
+};
+void dplane_ctx_set_ifp_no_afspec(struct zebra_dplane_ctx *ctx);
+bool dplane_ctx_get_ifp_no_afspec(const struct zebra_dplane_ctx *ctx);
+void dplane_ctx_set_ifp_no_bridge_vlan_info(struct zebra_dplane_ctx *ctx);
+bool dplane_ctx_get_ifp_no_bridge_vlan_info(struct zebra_dplane_ctx *ctx);
+void dplane_ctx_set_ifp_bridge_vlan_info(
+ struct zebra_dplane_ctx *ctx,
+ struct zebra_dplane_bridge_vlan_info *bvinfo);
+const struct zebra_dplane_bridge_vlan_info *
+dplane_ctx_get_ifp_bridge_vlan_info(const struct zebra_dplane_ctx *ctx);
+
+struct zebra_dplane_bridge_vlan_info_array {
+ int count;
+ struct zebra_dplane_bridge_vlan_info array[0];
+};
+void dplane_ctx_set_ifp_bridge_vlan_info_array(
+ struct zebra_dplane_ctx *ctx,
+ struct zebra_dplane_bridge_vlan_info_array *bvarray);
+const struct zebra_dplane_bridge_vlan_info_array *
+dplane_ctx_get_ifp_bridge_vlan_info_array(const struct zebra_dplane_ctx *ctx);
/* Retrieve last/current provider id */
uint32_t dplane_ctx_get_provider(const struct zebra_dplane_ctx *ctx);
@@ -533,10 +669,14 @@ bool dplane_ctx_intf_is_connected(const struct zebra_dplane_ctx *ctx);
void dplane_ctx_intf_set_connected(struct zebra_dplane_ctx *ctx);
bool dplane_ctx_intf_is_secondary(const struct zebra_dplane_ctx *ctx);
void dplane_ctx_intf_set_secondary(struct zebra_dplane_ctx *ctx);
+bool dplane_ctx_intf_is_noprefixroute(const struct zebra_dplane_ctx *ctx);
+void dplane_ctx_intf_set_noprefixroute(struct zebra_dplane_ctx *ctx);
bool dplane_ctx_intf_is_broadcast(const struct zebra_dplane_ctx *ctx);
void dplane_ctx_intf_set_broadcast(struct zebra_dplane_ctx *ctx);
const struct prefix *dplane_ctx_get_intf_addr(
const struct zebra_dplane_ctx *ctx);
+const struct in6_addr *
+dplane_ctx_get_srv6_encap_srcaddr(const struct zebra_dplane_ctx *ctx);
void dplane_ctx_set_intf_addr(struct zebra_dplane_ctx *ctx,
const struct prefix *p);
bool dplane_ctx_intf_has_dest(const struct zebra_dplane_ctx *ctx);
@@ -547,6 +687,8 @@ void dplane_ctx_set_intf_dest(struct zebra_dplane_ctx *ctx,
bool dplane_ctx_intf_has_label(const struct zebra_dplane_ctx *ctx);
const char *dplane_ctx_get_intf_label(const struct zebra_dplane_ctx *ctx);
void dplane_ctx_set_intf_label(struct zebra_dplane_ctx *ctx, const char *label);
+void dplane_ctx_set_intf_txqlen(struct zebra_dplane_ctx *ctx, uint32_t txqlen);
+uint32_t dplane_ctx_get_intf_txqlen(const struct zebra_dplane_ctx *ctx);
/* Accessors for MAC information */
vlanid_t dplane_ctx_mac_get_vlan(const struct zebra_dplane_ctx *ctx);
@@ -573,6 +715,8 @@ uint16_t dplane_ctx_neigh_get_state(const struct zebra_dplane_ctx *ctx);
uint32_t dplane_ctx_neigh_get_update_flags(const struct zebra_dplane_ctx *ctx);
/* Accessors for policy based routing rule information */
+void dplane_ctx_rule_get(const struct zebra_dplane_ctx *ctx,
+ struct pbr_rule *pNew, struct pbr_rule *pOld);
int dplane_ctx_rule_get_sock(const struct zebra_dplane_ctx *ctx);
int dplane_ctx_rule_get_unique(const struct zebra_dplane_ctx *ctx);
int dplane_ctx_rule_get_seq(const struct zebra_dplane_ctx *ctx);
@@ -611,6 +755,8 @@ intptr_t
dplane_ctx_rule_get_old_dp_flow_ptr(const struct zebra_dplane_ctx *ctx);
void dplane_ctx_rule_set_dp_flow_ptr(struct zebra_dplane_ctx *ctx,
intptr_t dp_flow_ptr);
+vrf_id_t dplane_ctx_rule_get_vrfid(const struct zebra_dplane_ctx *ctx);
+
/* Accessors for policy based routing iptable information */
struct zebra_pbr_iptable;
void dplane_ctx_get_pbr_iptable(const struct zebra_dplane_ctx *ctx,
@@ -747,7 +893,6 @@ enum zebra_dplane_result dplane_intf_addr_unset(const struct interface *ifp,
*/
enum zebra_dplane_result dplane_intf_add(const struct interface *ifp);
enum zebra_dplane_result dplane_intf_update(const struct interface *ifp);
-enum zebra_dplane_result dplane_intf_delete(const struct interface *ifp);
/*
* Enqueue tc link changes for the dataplane.
@@ -860,6 +1005,13 @@ enum zebra_dplane_result
dplane_gre_set(struct interface *ifp, struct interface *ifp_link,
unsigned int mtu, const struct zebra_l2info_gre *gre_info);
+/*
+ * Enqueue an SRv6 encap source address set
+ */
+enum zebra_dplane_result
+dplane_srv6_encap_srcaddr_set(const struct in6_addr *addr, ns_id_t ns_id);
+
+
/* Forward ref of zebra_pbr_rule */
struct zebra_pbr_rule;
@@ -1067,6 +1219,9 @@ void zebra_dplane_pre_finish(void);
void zebra_dplane_finish(void);
void zebra_dplane_shutdown(void);
+void zebra_dplane_startup_stage(struct zebra_ns *zns,
+ enum zebra_dplane_startup_notifications spot);
+
/*
* decision point for sending a routing update through the old
* straight to zebra master pthread or through the dplane to
@@ -1077,6 +1232,9 @@ void dplane_rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p,
struct nexthop_group *ng, int startup,
struct zebra_dplane_ctx *ctx);
+enum zebra_dplane_startup_notifications
+dplane_ctx_get_startup_spot(struct zebra_dplane_ctx *ctx);
+
#ifdef __cplusplus
}
#endif
diff --git a/zebra/zebra_evpn.c b/zebra/zebra_evpn.c
index ce5e639928..ebb5a42298 100644
--- a/zebra/zebra_evpn.c
+++ b/zebra/zebra_evpn.c
@@ -109,21 +109,14 @@ void zebra_evpn_print(struct zebra_evpn *zevpn, void **ctxt)
} else {
json_object_int_add(json, "vni", zevpn->vni);
json_object_string_add(json, "type", "L2");
-#if CONFDATE > 20240210
-CPP_NOTICE("Drop `vrf` from JSON output")
-#endif
- json_object_string_add(json, "vrf",
- vrf_id_to_name(zevpn->vrf_id));
- json_object_string_add(json, "tenantVrf",
- vrf_id_to_name(zevpn->vrf_id));
+ json_object_string_add(json, "tenantVrf", vrf_id_to_name(zevpn->vrf_id));
}
if (!zevpn->vxlan_if) { // unexpected
if (json == NULL)
vty_out(vty, " VxLAN interface: unknown\n");
else
- json_object_string_add(json, "vxlanInterface",
- "unknown");
+ json_object_string_add(json, "vxlanInterface", "unknown");
return;
}
num_macs = num_valid_macs(zevpn);
@@ -135,35 +128,21 @@ CPP_NOTICE("Drop `vrf` from JSON output")
(zevpn->svi_if ? zevpn->svi_if->name : ""));
vty_out(vty, " SVI ifIndex: %u\n",
(zevpn->svi_if ? zevpn->svi_if->ifindex : 0));
- vty_out(vty, " Local VTEP IP: %pI4\n",
- &zevpn->local_vtep_ip);
- vty_out(vty, " Mcast group: %pI4\n",
- &zevpn->mcast_grp);
+ vty_out(vty, " Local VTEP IP: %pI4\n", &zevpn->local_vtep_ip);
+ vty_out(vty, " Mcast group: %pI4\n", &zevpn->mcast_grp);
} else {
- json_object_string_add(json, "vxlanInterface",
- zevpn->vxlan_if->name);
-#if CONFDATE > 20240210
-CPP_NOTICE("Drop `ifindex` from JSON output")
-#endif
- json_object_int_add(json, "ifindex", zevpn->vxlan_if->ifindex);
- json_object_int_add(json, "vxlanIfindex",
- zevpn->vxlan_if->ifindex);
+ json_object_string_add(json, "vxlanInterface", zevpn->vxlan_if->name);
+ json_object_int_add(json, "vxlanIfindex", zevpn->vxlan_if->ifindex);
if (zevpn->svi_if) {
- json_object_string_add(json, "sviInterface",
- zevpn->svi_if->name);
- json_object_int_add(json, "sviIfindex",
- zevpn->svi_if->ifindex);
+ json_object_string_add(json, "sviInterface", zevpn->svi_if->name);
+ json_object_int_add(json, "sviIfindex", zevpn->svi_if->ifindex);
}
- json_object_string_addf(json, "vtepIp", "%pI4",
- &zevpn->local_vtep_ip);
- json_object_string_addf(json, "mcastGroup", "%pI4",
- &zevpn->mcast_grp);
+ json_object_string_addf(json, "vtepIp", "%pI4", &zevpn->local_vtep_ip);
+ json_object_string_addf(json, "mcastGroup", "%pI4", &zevpn->mcast_grp);
json_object_string_add(json, "advertiseGatewayMacip",
- zevpn->advertise_gw_macip ? "Yes"
- : "No");
+ zevpn->advertise_gw_macip ? "Yes" : "No");
json_object_string_add(json, "advertiseSviMacip",
- zevpn->advertise_svi_macip ? "Yes"
- : "No");
+ zevpn->advertise_svi_macip ? "Yes" : "No");
json_object_int_add(json, "numMacs", num_macs);
json_object_int_add(json, "numArpNd", num_neigh);
}
@@ -179,28 +158,21 @@ CPP_NOTICE("Drop `ifindex` from JSON output")
json_vtep_list = json_object_new_array();
for (zvtep = zevpn->vteps; zvtep; zvtep = zvtep->next) {
const char *flood_str = lookup_msg(
- zvtep_flood_str, zvtep->flood_control,
- VXLAN_FLOOD_STR_DEFAULT);
+ zvtep_flood_str, zvtep->flood_control, VXLAN_FLOOD_STR_DEFAULT);
if (json == NULL) {
- vty_out(vty, " %pI4 flood: %s\n",
- &zvtep->vtep_ip,
- flood_str);
+ vty_out(vty, " %pI4 flood: %s\n", &zvtep->vtep_ip, flood_str);
} else {
json_vtep = json_object_new_object();
- json_object_string_addf(json_vtep, "ip", "%pI4",
- &zvtep->vtep_ip);
- json_object_string_add(json_vtep, "flood",
- flood_str);
- json_object_array_add(json_vtep_list,
- json_vtep);
+ json_object_string_addf(json_vtep, "ip", "%pI4", &zvtep->vtep_ip);
+ json_object_string_add(json_vtep, "flood", flood_str);
+ json_object_array_add(json_vtep_list, json_vtep);
}
num_vteps++;
}
if (json) {
json_object_int_add(json, "numRemoteVteps", num_vteps);
- json_object_object_add(json, "remoteVteps",
- json_vtep_list);
+ json_object_object_add(json, "remoteVteps", json_vtep_list);
}
}
if (json == NULL) {
@@ -261,8 +233,7 @@ void zebra_evpn_print_hash(struct hash_bucket *bucket, void *ctxt[])
json_object_int_add(json_evpn, "vni", zevpn->vni);
json_object_string_add(json_evpn, "type", "L2");
json_object_string_add(json_evpn, "vxlanIf",
- zevpn->vxlan_if ? zevpn->vxlan_if->name
- : "unknown");
+ zevpn->vxlan_if ? zevpn->vxlan_if->name : "unknown");
json_object_int_add(json_evpn, "numMacs", num_macs);
json_object_int_add(json_evpn, "numArpNd", num_neigh);
json_object_int_add(json_evpn, "numRemoteVteps", num_vteps);
@@ -272,13 +243,10 @@ void zebra_evpn_print_hash(struct hash_bucket *bucket, void *ctxt[])
json_vtep_list = json_object_new_array();
for (zvtep = zevpn->vteps; zvtep; zvtep = zvtep->next) {
json_ip_str = json_object_new_string(
- inet_ntop(AF_INET, &zvtep->vtep_ip, buf,
- sizeof(buf)));
- json_object_array_add(json_vtep_list,
- json_ip_str);
+ inet_ntop(AF_INET, &zvtep->vtep_ip, buf, sizeof(buf)));
+ json_object_array_add(json_vtep_list, json_ip_str);
}
- json_object_object_add(json_evpn, "remoteVteps",
- json_vtep_list);
+ json_object_object_add(json_evpn, "remoteVteps", json_vtep_list);
}
json_object_object_add(json, vni_str, json_evpn);
}
@@ -310,13 +278,12 @@ void zebra_evpn_print_hash_detail(struct hash_bucket *bucket, void *data)
int zebra_evpn_del_macip_for_intf(struct interface *ifp,
struct zebra_evpn *zevpn)
{
- struct listnode *cnode = NULL, *cnnode = NULL;
struct connected *c = NULL;
struct ethaddr macaddr;
memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
- for (ALL_LIST_ELEMENTS(ifp->connected, cnode, cnnode, c)) {
+ frr_each_safe (if_connected, ifp->connected, c) {
struct ipaddr ip;
memset(&ip, 0, sizeof(struct ipaddr));
@@ -344,13 +311,12 @@ int zebra_evpn_del_macip_for_intf(struct interface *ifp,
int zebra_evpn_add_macip_for_intf(struct interface *ifp,
struct zebra_evpn *zevpn)
{
- struct listnode *cnode = NULL, *cnnode = NULL;
struct connected *c = NULL;
struct ethaddr macaddr;
memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
- for (ALL_LIST_ELEMENTS(ifp->connected, cnode, cnnode, c)) {
+ frr_each_safe (if_connected, ifp->connected, c) {
struct ipaddr ip;
if (!CHECK_FLAG(c->conf, ZEBRA_IFC_REAL))
@@ -385,7 +351,7 @@ static int ip_prefix_send_to_client(vrf_id_t vrf_id, struct prefix *p,
if (!client)
return 0;
- s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+ s = stream_new(ZEBRA_SMALL_PACKET_SIZE);
zclient_create_header(s, cmd, vrf_id);
stream_put(s, p, sizeof(struct prefix));
@@ -409,13 +375,12 @@ static int ip_prefix_send_to_client(vrf_id_t vrf_id, struct prefix *p,
int zebra_evpn_advertise_subnet(struct zebra_evpn *zevpn, struct interface *ifp,
int advertise)
{
- struct listnode *cnode = NULL, *cnnode = NULL;
struct connected *c = NULL;
struct ethaddr macaddr;
memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
- for (ALL_LIST_ELEMENTS(ifp->connected, cnode, cnnode, c)) {
+ frr_each (if_connected, ifp->connected, c) {
struct prefix p;
memcpy(&p, c->address, sizeof(struct prefix));
@@ -493,8 +458,7 @@ int zebra_evpn_gw_macip_del(struct interface *ifp, struct zebra_evpn *zevpn,
/* Remove neighbor from BGP. */
zebra_evpn_neigh_send_del_to_client(zevpn->vni, &n->ip, &n->emac,
- n->flags, ZEBRA_NEIGH_ACTIVE,
- false /*force*/);
+ n->flags, ZEBRA_NEIGH_ACTIVE, false /*force*/);
/* Delete this neighbor entry. */
zebra_evpn_neigh_del(zevpn, n);
@@ -524,8 +488,7 @@ void zebra_evpn_gw_macip_del_for_evpn_hash(struct hash_bucket *bucket,
*/
if (zevpn->advertise_gw_macip) {
if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug("VNI: %u GW-MACIP enabled, retain gw-macip",
- zevpn->vni);
+ zlog_debug("VNI: %u GW-MACIP enabled, retain gw-macip", zevpn->vni);
return;
}
@@ -697,8 +660,7 @@ static int zebra_evpn_map_vlan_ns(struct ns *ns,
if (zif->brslave_info.br_if != br_if)
continue;
- vni_id =
- zebra_vxlan_if_access_vlan_vni_find(zif, br_if);
+ vni_id = zebra_vxlan_if_access_vlan_vni_find(zif, br_if);
if (vni_id) {
found = 1;
break;
@@ -735,9 +697,7 @@ struct zebra_evpn *zebra_evpn_map_vlan(struct interface *ifp,
in_param.zif = zif;
p_zevpn = &zevpn;
- ns_walk_func(zebra_evpn_map_vlan_ns,
- (void *)&in_param,
- (void **)p_zevpn);
+ ns_walk_func(zebra_evpn_map_vlan_ns, (void *)&in_param, (void **)p_zevpn);
return zevpn;
}
@@ -857,9 +817,7 @@ struct zebra_evpn *zebra_evpn_from_svi(struct interface *ifp,
return zevpn;
}
-static int zvni_map_to_macvlan_ns(struct ns *ns,
- void *_in_param,
- void **_p_ifp)
+static int zvni_map_to_macvlan_ns(struct ns *ns, void *_in_param, void **_p_ifp)
{
struct zebra_ns *zns = ns->info;
struct zebra_from_svi_param *in_param =
@@ -921,9 +879,7 @@ struct interface *zebra_evpn_map_to_macvlan(struct interface *br_if,
p_ifp = &tmp_if;
/* Identify corresponding VLAN interface. */
- ns_walk_func(zvni_map_to_macvlan_ns,
- (void *)&in_param,
- (void **)p_ifp);
+ ns_walk_func(zvni_map_to_macvlan_ns, (void *)&in_param, (void **)p_ifp);
return tmp_if;
}
@@ -1128,8 +1084,7 @@ struct zebra_evpn *zebra_evpn_add(vni_t vni)
/* Create hash table for MAC */
zevpn->mac_table = zebra_mac_db_create(buffer);
- snprintf(buffer, sizeof(buffer), "Zebra EVPN Neighbor Table vni: %u",
- vni);
+ snprintf(buffer, sizeof(buffer), "Zebra EVPN Neighbor Table vni: %u", vni);
/* Create hash table for neighbors */
zevpn->neigh_table = zebra_neigh_db_create(buffer);
@@ -1185,7 +1140,7 @@ int zebra_evpn_send_add_to_client(struct zebra_evpn *zevpn)
svi_index = zevpn->svi_if ? zevpn->svi_if->ifindex : 0;
- s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+ s = stream_new(ZEBRA_SMALL_PACKET_SIZE);
zclient_create_header(s, ZEBRA_VNI_ADD, zebra_vrf_get_evpn_id());
stream_putl(s, zevpn->vni);
@@ -1208,8 +1163,8 @@ int zebra_evpn_send_add_to_client(struct zebra_evpn *zevpn)
client->vniadd_cnt++;
rc = zserv_send_message(client, s);
- if (!(zevpn->flags & ZEVPN_READY_FOR_BGP)) {
- zevpn->flags |= ZEVPN_READY_FOR_BGP;
+ if (!CHECK_FLAG(zevpn->flags, ZEVPN_READY_FOR_BGP)) {
+ SET_FLAG(zevpn->flags, ZEVPN_READY_FOR_BGP);
/* once the EVPN is sent the ES-EVIs can also be replayed
* to BGP
*/
@@ -1231,13 +1186,13 @@ int zebra_evpn_send_del_to_client(struct zebra_evpn *zevpn)
if (!client)
return 0;
- if (zevpn->flags & ZEVPN_READY_FOR_BGP) {
- zevpn->flags &= ~ZEVPN_READY_FOR_BGP;
+ if (CHECK_FLAG(zevpn->flags, ZEVPN_READY_FOR_BGP)) {
+ UNSET_FLAG(zevpn->flags, ZEVPN_READY_FOR_BGP);
/* the ES-EVIs must be removed from BGP before the EVPN is */
zebra_evpn_update_all_es(zevpn);
}
- s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+ s = stream_new(ZEBRA_SMALL_PACKET_SIZE);
stream_reset(s);
zclient_create_header(s, ZEBRA_VNI_DEL, zebra_vrf_get_evpn_id());
@@ -1353,8 +1308,7 @@ int zebra_evpn_vtep_install(struct zebra_evpn *zevpn, struct zebra_vtep *zvtep)
if (is_vxlan_flooding_head_end() &&
(zvtep->flood_control == VXLAN_FLOOD_HEAD_END_REPL)) {
if (ZEBRA_DPLANE_REQUEST_FAILURE ==
- dplane_vtep_add(zevpn->vxlan_if,
- &zvtep->vtep_ip, zevpn->vni))
+ dplane_vtep_add(zevpn->vxlan_if, &zvtep->vtep_ip, zevpn->vni))
return -1;
}
@@ -1445,9 +1399,7 @@ static void zebra_evpn_process_sync_macip_add(struct zebra_evpn *zevpn,
zevpn->vni,
macaddr,
ipa_len ? " IP " : "",
- ipa_len ? ipaddr2str(ipaddr, ipbuf,
- sizeof(ipbuf))
- : "",
+ ipa_len ? ipaddr2str(ipaddr, ipbuf, sizeof(ipbuf)) : "",
sticky ? " sticky" : "",
remote_gw ? " remote_gw" : "");
return;
@@ -1462,16 +1414,13 @@ static void zebra_evpn_process_sync_macip_add(struct zebra_evpn *zevpn,
mac = zebra_evpn_mac_lookup(zevpn, macaddr);
if (!mac) {
mac = zebra_evpn_proc_sync_mac_update(zevpn, macaddr,
- ipa_len, ipaddr,
- flags, seq, esi);
+ ipa_len, ipaddr, flags, seq, esi);
}
if (!mac)
return;
n = zebra_evpn_neigh_lookup(zevpn, ipaddr);
- if (n
- && !zebra_evpn_neigh_is_bgp_seq_ok(zevpn, n, macaddr, seq,
- true))
+ if (n && !zebra_evpn_neigh_is_bgp_seq_ok(zevpn, n, macaddr, seq, true))
return;
zebra_evpn_proc_sync_neigh_update(zevpn, n, ipa_len, ipaddr,
@@ -1517,22 +1466,19 @@ void zebra_evpn_rem_macip_add(vni_t vni, const struct ethaddr *macaddr,
* SYNC - if ES is local
* REMOTE - if ES is not local
*/
- if (flags & ZEBRA_MACIP_TYPE_SYNC_PATH) {
+ if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_SYNC_PATH)) {
struct zebra_evpn_es *es;
es = zebra_evpn_es_find(esi);
- if (es && (es->flags & ZEBRA_EVPNES_READY_FOR_BGP)) {
+ if (es && CHECK_FLAG(es->flags, ZEBRA_EVPNES_READY_FOR_BGP)) {
zebra_evpn_process_sync_macip_add(zevpn, macaddr,
- ipa_len, ipaddr,
- flags, seq, esi);
+ 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);
+ zlog_debug("Ignore sync-macip add; ES %s is not ready", esi_str);
}
}
@@ -1546,8 +1492,7 @@ void zebra_evpn_rem_macip_add(vni_t vni, const struct ethaddr *macaddr,
if (vtep_ip.s_addr) {
zvtep = zebra_evpn_vtep_find(zevpn, &vtep_ip);
if (!zvtep) {
- zvtep = zebra_evpn_vtep_add(zevpn, &vtep_ip,
- VXLAN_FLOOD_DISABLED);
+ zvtep = zebra_evpn_vtep_add(zevpn, &vtep_ip, VXLAN_FLOOD_DISABLED);
if (!zvtep) {
flog_err(
EC_ZEBRA_VTEP_ADD_FAILED,
@@ -1624,9 +1569,7 @@ void zebra_evpn_rem_macip_del(vni_t vni, const struct ethaddr *macaddr,
vnip = zebra_vxlan_if_vni_find(zif, vni);
if (!vnip) {
if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug(
- "VNI %u not in interface upon remote MACIP DEL",
- vni);
+ zlog_debug("VNI %u not in interface upon remote MACIP DEL", vni);
return;
}
diff --git a/zebra/zebra_evpn_mac.c b/zebra/zebra_evpn_mac.c
index 6d5cd66143..bfc060db61 100644
--- a/zebra/zebra_evpn_mac.c
+++ b/zebra/zebra_evpn_mac.c
@@ -103,9 +103,7 @@ static void zebra_evpn_mac_ifp_unlink(struct zebra_mac *zmac)
if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
zlog_debug("VNI %d MAC %pEA unlinked from ifp %s (%u)",
- zmac->zevpn->vni,
- &zmac->macaddr,
- ifp->name, ifp->ifindex);
+ zmac->zevpn->vni, &zmac->macaddr, ifp->name, ifp->ifindex);
zif = ifp->info;
list_delete_node(zif->mac_list, &zmac->ifp_listnode);
@@ -122,7 +120,7 @@ void zebra_evpn_mac_ifp_del(struct interface *ifp)
if (zif->mac_list) {
if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
zlog_debug("MAC list deleted for ifp %s (%u)",
- zif->ifp->name, zif->ifp->ifindex);
+ zif->ifp->name, zif->ifp->ifindex);
for (ALL_LIST_ELEMENTS_RO(zif->mac_list, node, zmac)) {
zebra_evpn_mac_ifp_unlink(zmac);
@@ -161,9 +159,7 @@ static void zebra_evpn_mac_ifp_link(struct zebra_mac *zmac,
if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
zlog_debug("VNI %d MAC %pEA linked to ifp %s (%u)",
- zmac->zevpn->vni,
- &zmac->macaddr,
- ifp->name, ifp->ifindex);
+ zmac->zevpn->vni, &zmac->macaddr, ifp->name, ifp->ifindex);
zmac->ifp = ifp;
listnode_init(&zmac->ifp_listnode, zmac);
@@ -205,7 +201,7 @@ int zebra_evpn_rem_mac_install(struct zebra_evpn *zevpn, struct zebra_mac *mac,
return -1;
sticky = !!CHECK_FLAG(mac->flags,
- (ZEBRA_MAC_STICKY | ZEBRA_MAC_REMOTE_DEF_GW));
+ (ZEBRA_MAC_STICKY | ZEBRA_MAC_REMOTE_DEF_GW));
/* If nexthop group for the FDB entry is inactive (not programmed in
* the dataplane) the MAC entry cannot be installed
@@ -249,7 +245,7 @@ int zebra_evpn_rem_mac_uninstall(struct zebra_evpn *zevpn,
enum zebra_dplane_result res;
/* If the MAC was not installed there is no need to uninstall it */
- if (!force && mac->es && !(mac->es->flags & ZEBRA_EVPNES_NHG_ACTIVE))
+ if (!force && mac->es && !CHECK_FLAG(mac->es->flags, ZEBRA_EVPNES_NHG_ACTIVE))
return -1;
if (!zevpn->vxlan_if) {
@@ -282,8 +278,7 @@ int zebra_evpn_rem_mac_uninstall(struct zebra_evpn *zevpn,
ifp = zevpn->vxlan_if;
vtep_ip = mac->fwd_info.r_vtep_ip;
- res = dplane_rem_mac_del(ifp, br_ifp, vid, &mac->macaddr, vni->vni,
- vtep_ip);
+ res = dplane_rem_mac_del(ifp, br_ifp, vid, &mac->macaddr, vni->vni, vtep_ip);
if (res != ZEBRA_DPLANE_REQUEST_FAILURE)
return 0;
else
@@ -341,8 +336,7 @@ static void zebra_evpn_mac_get_access_info(struct zebra_mac *mac,
*vid = mac->fwd_info.local.vid;
zns = zebra_ns_lookup(mac->fwd_info.local.ns_id);
- *p_ifp = if_lookup_by_index_per_ns(zns,
- mac->fwd_info.local.ifindex);
+ *p_ifp = if_lookup_by_index_per_ns(zns, mac->fwd_info.local.ifindex);
}
}
@@ -355,26 +349,19 @@ static char *zebra_evpn_zebra_mac_flag_dump(struct zebra_mac *mac, char *buf,
return buf;
}
- snprintfrr(
- buf, len, "%s%s%s%s%s%s%s%s%s%s%s%s",
+ snprintfrr(buf, len, "%s%s%s%s%s%s%s%s%s%s%s%s",
CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL) ? "LOC " : "",
CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE) ? "REM " : "",
CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO) ? "AUTO " : "",
CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? "STICKY " : "",
- CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_RMAC) ? "REM Router "
- : "",
+ CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_RMAC) ? "REM Router " : "",
CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW) ? "Default GW " : "",
- CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW) ? "REM DEF GW "
- : "",
+ CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW) ? "REM DEF GW " : "",
CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE) ? "DUP " : "",
CHECK_FLAG(mac->flags, ZEBRA_MAC_FPM_SENT) ? "FPM " : "",
- CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_ACTIVE)
- ? "PEER Active "
- : "",
+ CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_ACTIVE) ? "PEER Active " : "",
CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_PROXY) ? "PROXY " : "",
- CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE)
- ? "LOC Inactive "
- : "");
+ CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE) ? "LOC Inactive " : "");
return buf;
}
@@ -407,8 +394,7 @@ static void zebra_evpn_dad_mac_auto_recovery_exp(struct event *t)
zlog_debug(
"%s: duplicate addr mac %pEA flags %slearn count %u host count %u auto recovery expired",
__func__, &mac->macaddr,
- zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
- sizeof(mac_buf)),
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)),
mac->dad_count, listcount(mac->neigh_list));
}
@@ -418,8 +404,7 @@ static void zebra_evpn_dad_mac_auto_recovery_exp(struct event *t)
if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL))
ZEBRA_NEIGH_SET_INACTIVE(nbr);
else if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_REMOTE))
- zebra_evpn_rem_neigh_install(
- zevpn, nbr, false /*was_static*/);
+ zebra_evpn_rem_neigh_install(zevpn, nbr, false /*was_static*/);
}
UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
@@ -438,13 +423,11 @@ static void zebra_evpn_dad_mac_auto_recovery_exp(struct event *t)
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
/* Inform to BGP */
if (zebra_evpn_mac_send_add_to_client(zevpn->vni, &mac->macaddr,
- mac->flags, mac->loc_seq,
- mac->es))
+ mac->flags, mac->loc_seq, mac->es))
return;
/* Process all neighbors associated with this MAC. */
- zebra_evpn_process_neigh_on_local_mac_change(zevpn, mac, 0,
- 0 /*es_change*/);
+ zebra_evpn_process_neigh_on_local_mac_change(zevpn, mac, 0, 0 /*es_change*/);
} else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
zebra_evpn_process_neigh_on_remote_mac_add(zevpn, mac);
@@ -479,8 +462,7 @@ static void zebra_evpn_dup_addr_detect_for_mac(struct zebra_vrf *zvrf,
zlog_debug(
"%s: duplicate addr MAC %pEA flags %sskip update to client, learn count %u recover time %u",
__func__, &mac->macaddr,
- zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
- sizeof(mac_buf)),
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)),
mac->dad_count, zvrf->dad_freeze_time);
}
/* For duplicate MAC do not update
@@ -516,8 +498,7 @@ static void zebra_evpn_dup_addr_detect_for_mac(struct zebra_vrf *zvrf,
zlog_debug(
"%s: duplicate addr MAC %pEA flags %sdetection time passed, reset learn count %u",
__func__, &mac->macaddr,
- zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
- sizeof(mac_buf)),
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)),
mac->dad_count);
}
@@ -545,10 +526,10 @@ static void zebra_evpn_dup_addr_detect_for_mac(struct zebra_vrf *zvrf,
if (mac->dad_count >= zvrf->dad_max_moves) {
flog_warn(EC_ZEBRA_DUP_MAC_DETECTED,
- "VNI %u: MAC %pEA detected as duplicate during %s VTEP %pI4",
- mac->zevpn->vni, &mac->macaddr,
- is_local ? "local update, last" :
- "remote update, from", &vtep_ip);
+ "VNI %u: MAC %pEA detected as duplicate during %s VTEP %pI4",
+ mac->zevpn->vni, &mac->macaddr,
+ is_local ? "local update, last" : "remote update, from",
+ &vtep_ip);
SET_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE);
@@ -583,15 +564,13 @@ static void zebra_evpn_dup_addr_detect_for_mac(struct zebra_vrf *zvrf,
zlog_debug(
"%s: duplicate addr MAC %pEA flags %sauto recovery time %u start",
__func__, &mac->macaddr,
- zebra_evpn_zebra_mac_flag_dump(
- mac, mac_buf, sizeof(mac_buf)),
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)),
zvrf->dad_freeze_time);
}
event_add_timer(zrouter.master,
- zebra_evpn_dad_mac_auto_recovery_exp,
- mac, zvrf->dad_freeze_time,
- &mac->dad_mac_auto_recovery_timer);
+ zebra_evpn_dad_mac_auto_recovery_exp, mac,
+ zvrf->dad_freeze_time, &mac->dad_mac_auto_recovery_timer);
}
/* In case of local update, do not inform to client (BGPd),
@@ -638,22 +617,18 @@ void zebra_evpn_print_mac(struct zebra_mac *mac, void *ctxt, json_object *json)
zebra_evpn_mac_get_access_info(mac, &ifp, &vid);
json_object_string_add(json_mac, "type", "local");
if (ifp) {
- json_object_string_add(json_mac, "intf",
- ifp->name);
- json_object_int_add(json_mac, "ifindex",
- ifp->ifindex);
+ json_object_string_add(json_mac, "intf", ifp->name);
+ json_object_int_add(json_mac, "ifindex", ifp->ifindex);
}
if (vid)
json_object_int_add(json_mac, "vlan", vid);
} else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
json_object_string_add(json_mac, "type", "remote");
if (mac->es)
- json_object_string_add(json_mac, "remoteEs",
- mac->es->esi_str);
+ json_object_string_add(json_mac, "remoteEs", mac->es->esi_str);
else
json_object_string_addf(
- json_mac, "remoteVtep", "%pI4",
- &mac->fwd_info.r_vtep_ip);
+ json_mac, "remoteVtep", "%pI4", &mac->fwd_info.r_vtep_ip);
} else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO))
json_object_string_add(json_mac, "type", "auto");
@@ -664,12 +639,10 @@ void zebra_evpn_print_mac(struct zebra_mac *mac, void *ctxt, json_object *json)
json_object_boolean_true_add(json_mac, "sviMac");
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW))
- json_object_boolean_true_add(json_mac,
- "defaultGateway");
+ json_object_boolean_true_add(json_mac, "defaultGateway");
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW))
- json_object_boolean_true_add(json_mac,
- "remoteGatewayMac");
+ json_object_boolean_true_add(json_mac, "remoteGatewayMac");
json_object_string_add(json_mac, "uptime", up_str);
json_object_int_add(json_mac, "localSequence", mac->loc_seq);
@@ -690,46 +663,31 @@ void zebra_evpn_print_mac(struct zebra_mac *mac, void *ctxt, json_object *json)
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_ACTIVE))
json_object_boolean_true_add(json_mac, "peerActive");
if (mac->hold_timer)
- json_object_string_add(
- json_mac, "peerActiveHold",
- event_timer_to_hhmmss(thread_buf,
- sizeof(thread_buf),
- mac->hold_timer));
+ json_object_string_add(json_mac, "peerActiveHold",
+ event_timer_to_hhmmss(thread_buf, sizeof(thread_buf), mac->hold_timer));
if (mac->es)
- json_object_string_add(json_mac, "esi",
- mac->es->esi_str);
+ json_object_string_add(json_mac, "esi", mac->es->esi_str);
/* print all the associated neigh */
if (!listcount(mac->neigh_list))
json_object_string_add(json_mac, "neighbors", "none");
else {
json_object *json_active_nbrs = json_object_new_array();
- json_object *json_inactive_nbrs =
- json_object_new_array();
+ json_object *json_inactive_nbrs = json_object_new_array();
json_object *json_nbrs = json_object_new_object();
for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, n)) {
if (IS_ZEBRA_NEIGH_ACTIVE(n))
- json_object_array_add(
- json_active_nbrs,
- json_object_new_string(
- ipaddr2str(
- &n->ip, buf2,
- sizeof(buf2))));
+ json_object_array_add(json_active_nbrs,
+ json_object_new_string(ipaddr2str(&n->ip, buf2, sizeof(buf2))));
else
json_object_array_add(
json_inactive_nbrs,
- json_object_new_string(
- ipaddr2str(
- &n->ip, buf2,
- sizeof(buf2))));
+ json_object_new_string(ipaddr2str(&n->ip, buf2, sizeof(buf2))));
}
- json_object_object_add(json_nbrs, "active",
- json_active_nbrs);
- json_object_object_add(json_nbrs, "inactive",
- json_inactive_nbrs);
- json_object_object_add(json_mac, "neighbors",
- json_nbrs);
+ json_object_object_add(json_nbrs, "active", json_active_nbrs);
+ json_object_object_add(json_nbrs, "inactive", json_inactive_nbrs);
+ json_object_object_add(json_mac, "neighbors", json_nbrs);
}
json_object_object_add(json, buf1, json_mac);
@@ -746,18 +704,15 @@ void zebra_evpn_print_mac(struct zebra_mac *mac, void *ctxt, json_object *json)
vty_out(vty, " ESI: %s\n", mac->es->esi_str);
if (ifp)
- vty_out(vty, " Intf: %s(%u)", ifp->name,
- ifp->ifindex);
+ vty_out(vty, " Intf: %s(%u)", ifp->name, ifp->ifindex);
else
vty_out(vty, " Intf: -");
vty_out(vty, " VLAN: %u", vid);
} else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
if (mac->es)
- vty_out(vty, " Remote ES: %s",
- mac->es->esi_str);
+ vty_out(vty, " Remote ES: %s", mac->es->esi_str);
else
- vty_out(vty, " Remote VTEP: %pI4",
- &mac->fwd_info.r_vtep_ip);
+ vty_out(vty, " Remote VTEP: %pI4", &mac->fwd_info.r_vtep_ip);
} else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO)) {
vty_out(vty, " Auto Mac ");
}
@@ -784,24 +739,18 @@ void zebra_evpn_print_mac(struct zebra_mac *mac, void *ctxt, json_object *json)
vty_out(vty, " peer-active");
if (mac->hold_timer)
vty_out(vty, " (ht: %s)",
- event_timer_to_hhmmss(thread_buf,
- sizeof(thread_buf),
- mac->hold_timer));
+ event_timer_to_hhmmss(thread_buf, sizeof(thread_buf), mac->hold_timer));
vty_out(vty, "\n");
- vty_out(vty, " Local Seq: %u Remote Seq: %u\n", mac->loc_seq,
- mac->rem_seq);
+ vty_out(vty, " Local Seq: %u Remote Seq: %u\n", mac->loc_seq, mac->rem_seq);
vty_out(vty, " Uptime: %s\n", up_str);
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) {
vty_out(vty, " Duplicate, detected at %s",
- time_to_string(mac->dad_dup_detect_time,
- timebuf));
+ time_to_string(mac->dad_dup_detect_time, timebuf));
} else if (mac->dad_count) {
- monotime_since(&mac->detect_start_time,
- &detect_start_time);
+ monotime_since(&mac->detect_start_time, &detect_start_time);
if (detect_start_time.tv_sec <= zvrf->dad_time) {
- time_to_string(mac->detect_start_time.tv_sec,
- timebuf);
+ time_to_string(mac->detect_start_time.tv_sec, timebuf);
vty_out(vty,
" Duplicate detection started at %s, detection count %u\n",
timebuf, mac->dad_count);
@@ -816,9 +765,7 @@ void zebra_evpn_print_mac(struct zebra_mac *mac, void *ctxt, json_object *json)
for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, n)) {
vty_out(vty, " %s %s\n",
ipaddr2str(&n->ip, buf2, sizeof(buf2)),
- (IS_ZEBRA_NEIGH_ACTIVE(n)
- ? "Active"
- : "Inactive"));
+ (IS_ZEBRA_NEIGH_ACTIVE(n) ? "Active" : "Inactive"));
}
}
@@ -831,9 +778,9 @@ static char *zebra_evpn_print_mac_flags(struct zebra_mac *mac, char *flags_buf,
{
snprintf(flags_buf, flags_buf_sz, "%s%s%s%s",
mac->sync_neigh_cnt ? "N" : "",
- (mac->flags & ZEBRA_MAC_ES_PEER_ACTIVE) ? "P" : "",
- (mac->flags & ZEBRA_MAC_ES_PEER_PROXY) ? "X" : "",
- (mac->flags & ZEBRA_MAC_LOCAL_INACTIVE) ? "I" : "");
+ CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_ACTIVE) ? "P" : "",
+ CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_PROXY) ? "X" : "",
+ CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE) ? "I" : "");
return flags_buf;
}
@@ -870,14 +817,12 @@ void zebra_evpn_print_mac_hash(struct hash_bucket *bucket, void *ctxt)
zebra_evpn_mac_get_access_info(mac, &ifp, &vid);
if (json_mac_hdr == NULL) {
vty_out(vty, "%-17s %-6s %-5s %-30s", buf1, "local",
- zebra_evpn_print_mac_flags(mac, flags_buf,
- sizeof(flags_buf)),
+ zebra_evpn_print_mac_flags(mac, flags_buf, sizeof(flags_buf)),
ifp ? ifp->name : "-");
} else {
json_object_string_add(json_mac, "type", "local");
if (ifp)
- json_object_string_add(json_mac, "intf",
- ifp->name);
+ json_object_string_add(json_mac, "intf", ifp->name);
}
if (vid) {
if (json_mac_hdr == NULL)
@@ -891,18 +836,13 @@ void zebra_evpn_print_mac_hash(struct hash_bucket *bucket, void *ctxt)
vty_out(vty, " %u/%u", mac->loc_seq, mac->rem_seq);
vty_out(vty, "\n");
} else {
- json_object_int_add(json_mac, "localSequence",
- mac->loc_seq);
- json_object_int_add(json_mac, "remoteSequence",
- mac->rem_seq);
- json_object_int_add(json_mac, "detectionCount",
- mac->dad_count);
+ json_object_int_add(json_mac, "localSequence", mac->loc_seq);
+ json_object_int_add(json_mac, "remoteSequence", mac->rem_seq);
+ json_object_int_add(json_mac, "detectionCount", mac->dad_count);
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
- json_object_boolean_true_add(json_mac,
- "isDuplicate");
+ json_object_boolean_true_add(json_mac, "isDuplicate");
else
- json_object_boolean_false_add(json_mac,
- "isDuplicate");
+ json_object_boolean_false_add(json_mac, "isDuplicate");
json_object_object_add(json_mac_hdr, buf1, json_mac);
}
@@ -910,19 +850,16 @@ void zebra_evpn_print_mac_hash(struct hash_bucket *bucket, void *ctxt)
} else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
- if ((wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP)
- && !IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip,
- &wctx->r_vtep_ip))
+ if (CHECK_FLAG(wctx->flags, SHOW_REMOTE_MAC_FROM_VTEP)
+ && !IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &wctx->r_vtep_ip))
return;
if (json_mac_hdr == NULL) {
- if ((wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP)
+ if (CHECK_FLAG(wctx->flags, SHOW_REMOTE_MAC_FROM_VTEP)
&& (wctx->count == 0)) {
vty_out(vty, "\nVNI %u\n\n", wctx->zevpn->vni);
vty_out(vty, "%-17s %-6s %-5s%-30s %-5s %s\n",
- "MAC", "Type", "Flags",
- "Intf/Remote ES/VTEP", "VLAN",
- "Seq #'s");
+ "MAC", "Type", "Flags", "Intf/Remote ES/VTEP", "VLAN", "Seq #'s");
}
if (mac->es == NULL)
inet_ntop(AF_INET, &mac->fwd_info.r_vtep_ip,
@@ -930,32 +867,24 @@ void zebra_evpn_print_mac_hash(struct hash_bucket *bucket, void *ctxt)
vty_out(vty, "%-17s %-6s %-5s %-30s %-5s %u/%u\n", buf1,
"remote",
- zebra_evpn_print_mac_flags(mac, flags_buf,
- sizeof(flags_buf)),
+ zebra_evpn_print_mac_flags(mac, flags_buf, sizeof(flags_buf)),
mac->es ? mac->es->esi_str : addr_buf,
"", mac->loc_seq, mac->rem_seq);
} else {
json_object_string_add(json_mac, "type", "remote");
if (mac->es)
- json_object_string_add(json_mac, "remoteEs",
- mac->es->esi_str);
+ json_object_string_add(json_mac, "remoteEs", mac->es->esi_str);
else
json_object_string_addf(
- json_mac, "remoteVtep", "%pI4",
- &mac->fwd_info.r_vtep_ip);
+ json_mac, "remoteVtep", "%pI4", &mac->fwd_info.r_vtep_ip);
json_object_object_add(json_mac_hdr, buf1, json_mac);
- json_object_int_add(json_mac, "localSequence",
- mac->loc_seq);
- json_object_int_add(json_mac, "remoteSequence",
- mac->rem_seq);
- json_object_int_add(json_mac, "detectionCount",
- mac->dad_count);
+ json_object_int_add(json_mac, "localSequence", mac->loc_seq);
+ json_object_int_add(json_mac, "remoteSequence", mac->rem_seq);
+ json_object_int_add(json_mac, "detectionCount", mac->dad_count);
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
- json_object_boolean_true_add(json_mac,
- "isDuplicate");
+ json_object_boolean_true_add(json_mac, "isDuplicate");
else
- json_object_boolean_false_add(json_mac,
- "isDuplicate");
+ json_object_boolean_false_add(json_mac, "isDuplicate");
}
wctx->count++;
@@ -1004,7 +933,7 @@ int zebra_evpn_macip_send_msg_to_client(vni_t vni,
if (!client)
return 0;
- s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+ s = stream_new(ZEBRA_SMALL_PACKET_SIZE);
zclient_create_header(s, cmd, zebra_vrf_get_evpn_id());
stream_putl(s, vni);
@@ -1040,9 +969,9 @@ int zebra_evpn_macip_send_msg_to_client(vni_t vni,
zlog_debug(
"Send MACIP %s f %s state %u MAC %pEA IP %pIA seq %u L2-VNI %u ESI %s to %s",
(cmd == ZEBRA_MACIP_ADD) ? "Add" : "Del",
- zclient_evpn_dump_macip_flags(flags, flag_buf,
- sizeof(flag_buf)),
- state, macaddr, ip, seq, vni, es ? es->esi_str : "-",
+ zclient_evpn_dump_macip_flags(flags, flag_buf, sizeof(flag_buf)),
+ state, macaddr, ip, seq, vni,
+ es ? es->esi_str : "-",
zebra_route_string(client->proto));
}
@@ -1076,8 +1005,7 @@ static bool mac_cmp(const void *p1, const void *p2)
if (pmac1 == NULL || pmac2 == NULL)
return false;
- return (memcmp(pmac1->macaddr.octet, pmac2->macaddr.octet, ETH_ALEN)
- == 0);
+ return (memcmp(pmac1->macaddr.octet, pmac2->macaddr.octet, ETH_ALEN) == 0);
}
/*
@@ -1117,10 +1045,8 @@ struct zebra_mac *zebra_evpn_mac_add(struct zebra_evpn *zevpn,
if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
char mac_buf[MAC_BUF_SIZE];
- zlog_debug("%s: MAC %pEA flags %s", __func__,
- &mac->macaddr,
- zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
- sizeof(mac_buf)));
+ zlog_debug("%s: MAC %pEA flags %s", __func__, &mac->macaddr,
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)));
}
return mac;
}
@@ -1135,10 +1061,8 @@ int zebra_evpn_mac_del(struct zebra_evpn *zevpn, struct zebra_mac *mac)
if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
char mac_buf[MAC_BUF_SIZE];
- zlog_debug("%s: MAC %pEA flags %s", __func__,
- &mac->macaddr,
- zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
- sizeof(mac_buf)));
+ zlog_debug("%s: MAC %pEA flags %s", __func__, &mac->macaddr,
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)));
}
/* force de-ref any ES entry linked to the MAC */
@@ -1165,9 +1089,8 @@ int zebra_evpn_mac_del(struct zebra_evpn *zevpn, struct zebra_mac *mac)
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
"MAC %pEA (flags 0x%x vni %u) has non-empty neigh list "
- "count %u, mark MAC as AUTO",
- &mac->macaddr, mac->flags, zevpn->vni,
- listcount(mac->neigh_list));
+ "count %u, mark MAC as AUTO", &mac->macaddr, mac->flags,
+ zevpn->vni, listcount(mac->neigh_list));
SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
return 0;
@@ -1204,25 +1127,25 @@ struct zebra_mac *zebra_evpn_mac_add_auto(struct zebra_evpn *zevpn,
static bool zebra_evpn_check_mac_del_from_db(struct mac_walk_ctx *wctx,
struct zebra_mac *mac)
{
- if ((wctx->flags & DEL_LOCAL_MAC) && (mac->flags & ZEBRA_MAC_LOCAL))
+ if (CHECK_FLAG(wctx->flags, DEL_LOCAL_MAC)
+ && CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
return true;
- else if ((wctx->flags & DEL_REMOTE_MAC)
- && (mac->flags & ZEBRA_MAC_REMOTE))
+ else if (CHECK_FLAG(wctx->flags, DEL_REMOTE_MAC)
+ && CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE))
return true;
- else if ((wctx->flags & DEL_REMOTE_MAC_FROM_VTEP)
- && (mac->flags & ZEBRA_MAC_REMOTE)
+ else if (CHECK_FLAG(wctx->flags, DEL_REMOTE_MAC_FROM_VTEP)
+ && CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)
&& IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &wctx->r_vtep_ip))
return true;
- else if ((wctx->flags & DEL_LOCAL_MAC) && (mac->flags & ZEBRA_MAC_AUTO)
+ else if (CHECK_FLAG(wctx->flags, DEL_LOCAL_MAC)
+ && CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO)
&& !listcount(mac->neigh_list)) {
if (IS_ZEBRA_DEBUG_VXLAN) {
char mac_buf[MAC_BUF_SIZE];
zlog_debug(
- "%s: Del MAC %pEA flags %s", __func__,
- &mac->macaddr,
- zebra_evpn_zebra_mac_flag_dump(
- mac, mac_buf, sizeof(mac_buf)));
+ "%s: Del MAC %pEA flags %s", __func__, &mac->macaddr,
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)));
}
wctx->uninstall = 0;
@@ -1241,21 +1164,17 @@ static void zebra_evpn_mac_del_hash_entry(struct hash_bucket *bucket, void *arg)
struct zebra_mac *mac = bucket->data;
if (zebra_evpn_check_mac_del_from_db(wctx, mac)) {
- if (wctx->upd_client && (mac->flags & ZEBRA_MAC_LOCAL)) {
+ if (wctx->upd_client && CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
zebra_evpn_mac_send_del_to_client(wctx->zevpn->vni,
- &mac->macaddr,
- mac->flags, false);
+ &mac->macaddr, mac->flags, false);
}
if (wctx->uninstall) {
if (zebra_evpn_mac_is_static(mac))
- zebra_evpn_sync_mac_dp_install(
- mac, false /* set_inactive */,
- true /* force_clear_static */,
- __func__);
+ zebra_evpn_sync_mac_dp_install(mac, false /* set_inactive */,
+ true /* force_clear_static */, __func__);
if (mac->flags & ZEBRA_MAC_REMOTE)
- zebra_evpn_rem_mac_uninstall(wctx->zevpn, mac,
- false /*force*/);
+ zebra_evpn_rem_mac_uninstall(wctx->zevpn, mac, false /*force*/);
}
zebra_evpn_mac_del(wctx->zevpn, mac);
@@ -1330,8 +1249,7 @@ int zebra_evpn_mac_send_add_to_client(vni_t vni, const struct ethaddr *macaddr,
SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
return zebra_evpn_macip_send_msg_to_client(vni, macaddr, NULL, flags,
- seq, ZEBRA_NEIGH_ACTIVE, es,
- ZEBRA_MACIP_ADD);
+ seq, ZEBRA_NEIGH_ACTIVE, es, ZEBRA_MACIP_ADD);
}
/*
@@ -1357,9 +1275,8 @@ int zebra_evpn_mac_send_del_to_client(vni_t vni, const struct ethaddr *macaddr,
state = ZEBRA_NEIGH_INACTIVE;
}
- return zebra_evpn_macip_send_msg_to_client(
- vni, macaddr, NULL, 0 /* flags */, 0 /* seq */, state, NULL,
- ZEBRA_MACIP_DEL);
+ return zebra_evpn_macip_send_msg_to_client(vni, macaddr, NULL,
+ 0 /* flags */, 0 /* seq */, state, NULL, ZEBRA_MACIP_DEL);
}
/*
@@ -1412,8 +1329,7 @@ int zebra_evpn_sync_mac_dp_install(struct zebra_mac *mac, bool set_inactive,
"%s: dp-install sync-mac vni %u mac %pEA es %s %s%sskipped, no access-port",
caller, zevpn->vni, &mac->macaddr,
mac->es ? mac->es->esi_str : "-",
- zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
- sizeof(mac_buf)),
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)),
set_inactive ? "inactive " : "");
}
return -1;
@@ -1429,8 +1345,7 @@ int zebra_evpn_sync_mac_dp_install(struct zebra_mac *mac, bool set_inactive,
"%s: dp-install sync-mac vni %u mac %pEA es %s %s%sskipped, no br",
caller, zevpn->vni, &mac->macaddr,
mac->es ? mac->es->esi_str : "-",
- zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
- sizeof(mac_buf)),
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)),
set_inactive ? "inactive " : "");
}
return -1;
@@ -1455,19 +1370,16 @@ int zebra_evpn_sync_mac_dp_install(struct zebra_mac *mac, bool set_inactive,
set_static ? "install" : "uninstall",
zevpn->vni, &mac->macaddr,
mac->es ? mac->es->esi_str : "-",
- zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
- sizeof(mac_buf)),
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)),
set_inactive ? "inactive " : "");
}
if (set_static)
/* XXX - old_static needs to be computed more
* accurately
*/
- zebra_evpn_rem_mac_install(zevpn, mac,
- true /* old_static */);
+ zebra_evpn_rem_mac_install(zevpn, mac, true /* old_static */);
else
- zebra_evpn_rem_mac_uninstall(zevpn, mac,
- false /* force */);
+ zebra_evpn_rem_mac_uninstall(zevpn, mac, false /* force */);
return 0;
}
@@ -1478,14 +1390,13 @@ int zebra_evpn_sync_mac_dp_install(struct zebra_mac *mac, bool set_inactive,
zlog_debug("dp-install sync-mac vni %u mac %pEA es %s %s%s%s",
zevpn->vni, &mac->macaddr,
mac->es ? mac->es->esi_str : "-",
- zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
- sizeof(mac_buf)),
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)),
set_static ? "static " : "",
set_inactive ? "inactive " : "");
}
dplane_local_mac_add(ifp, br_ifp, vid, &mac->macaddr, sticky,
- set_static, set_inactive);
+ set_static, set_inactive);
return 0;
}
@@ -1495,12 +1406,11 @@ void zebra_evpn_mac_send_add_del_to_client(struct zebra_mac *mac,
{
if (new_bgp_ready)
zebra_evpn_mac_send_add_to_client(mac->zevpn->vni,
- &mac->macaddr, mac->flags,
- mac->loc_seq, mac->es);
+ &mac->macaddr, mac->flags,
+ mac->loc_seq, mac->es);
else if (old_bgp_ready)
zebra_evpn_mac_send_del_to_client(mac->zevpn->vni,
- &mac->macaddr, mac->flags,
- true /* force */);
+ &mac->macaddr, mac->flags, true /* force */);
}
/* MAC hold timer is used to age out peer-active flag.
@@ -1537,8 +1447,7 @@ static void zebra_evpn_mac_hold_exp_cb(struct event *t)
"sync-mac vni %u mac %pEA es %s %shold expired",
mac->zevpn->vni, &mac->macaddr,
mac->es ? mac->es->esi_str : "-",
- zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
- sizeof(mac_buf)));
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)));
}
/* re-program the local mac in the dataplane if the mac is no
@@ -1546,13 +1455,11 @@ static void zebra_evpn_mac_hold_exp_cb(struct event *t)
*/
if (old_static != new_static)
zebra_evpn_sync_mac_dp_install(mac, false /* set_inactive */,
- false /* force_clear_static */,
- __func__);
+ false /* force_clear_static */, __func__);
/* inform bgp if needed */
if (old_bgp_ready != new_bgp_ready)
- zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready,
- new_bgp_ready);
+ zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready, new_bgp_ready);
}
static inline void zebra_evpn_mac_start_hold_timer(struct zebra_mac *mac)
@@ -1567,8 +1474,7 @@ static inline void zebra_evpn_mac_start_hold_timer(struct zebra_mac *mac)
"sync-mac vni %u mac %pEA es %s %shold started",
mac->zevpn->vni, &mac->macaddr,
mac->es ? mac->es->esi_str : "-",
- zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
- sizeof(mac_buf)));
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)));
}
event_add_timer(zrouter.master, zebra_evpn_mac_hold_exp_cb, mac,
zmh_info->mac_hold_time, &mac->hold_timer);
@@ -1586,8 +1492,7 @@ void zebra_evpn_mac_stop_hold_timer(struct zebra_mac *mac)
"sync-mac vni %u mac %pEA es %s %shold stopped",
mac->zevpn->vni, &mac->macaddr,
mac->es ? mac->es->esi_str : "-",
- zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
- sizeof(mac_buf)));
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)));
}
EVENT_OFF(mac->hold_timer);
@@ -1605,8 +1510,7 @@ void zebra_evpn_sync_mac_del(struct zebra_mac *mac)
"sync-mac del vni %u mac %pEA es %s seq %d f %s",
mac->zevpn->vni, &mac->macaddr,
mac->es ? mac->es->esi_str : "-", mac->loc_seq,
- zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
- sizeof(mac_buf)));
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)));
}
old_static = zebra_evpn_mac_is_static(mac);
@@ -1618,8 +1522,7 @@ void zebra_evpn_sync_mac_del(struct zebra_mac *mac)
if (old_static != new_static)
/* program the local mac in the kernel */
zebra_evpn_sync_mac_dp_install(mac, false /* set_inactive */,
- false /* force_clear_static */,
- __func__);
+ false /* force_clear_static */, __func__);
}
static inline bool zebra_evpn_mac_is_bgp_seq_ok(struct zebra_evpn *zevpn,
@@ -1647,8 +1550,7 @@ static inline bool zebra_evpn_mac_is_bgp_seq_ok(struct zebra_evpn *zevpn,
zlog_debug(
"%s-macip not ready vni %u %s-mac %pEA lower seq %u f 0x%x",
sync ? "sync" : "rem", zevpn->vni,
- n_type, &mac->macaddr, tmp_seq,
- mac->flags);
+ n_type, &mac->macaddr, tmp_seq, mac->flags);
return true;
}
@@ -1660,10 +1562,9 @@ static inline bool zebra_evpn_mac_is_bgp_seq_ok(struct zebra_evpn *zevpn,
IS_ZEBRA_DEBUG_VXLAN) {
zlog_debug(
"%s-macip accept vni %u %s-mac %pEA lower seq %u f %s",
- sync ? "sync" : "rem", zevpn->vni,
- n_type, &mac->macaddr, tmp_seq,
- zebra_evpn_zebra_mac_flag_dump(
- mac, mac_buf, sizeof(mac_buf)));
+ (sync ? "sync" : "rem"),
+ zevpn->vni, n_type, &mac->macaddr, tmp_seq,
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)));
}
return true;
@@ -1672,10 +1573,8 @@ static inline bool zebra_evpn_mac_is_bgp_seq_ok(struct zebra_evpn *zevpn,
if (IS_ZEBRA_DEBUG_EVPN_MH_MAC || IS_ZEBRA_DEBUG_VXLAN) {
zlog_debug(
"%s-macip ignore vni %u %s-mac %pEA as existing has higher seq %u f %s",
- sync ? "sync" : "rem", zevpn->vni, n_type,
- &mac->macaddr, tmp_seq,
- zebra_evpn_zebra_mac_flag_dump(
- mac, mac_buf, sizeof(mac_buf)));
+ (sync ? "sync" : "rem"), zevpn->vni, n_type, &mac->macaddr, tmp_seq,
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)));
}
return false;
@@ -1749,9 +1648,7 @@ struct zebra_mac *zebra_evpn_proc_sync_mac_update(struct zebra_evpn *zevpn,
"Ignore sync-macip vni %u mac %pEA%s%s%s%s",
zevpn->vni, macaddr,
ipa_len ? " IP " : "",
- ipa_len ? ipaddr2str(ipaddr, ipbuf,
- sizeof(ipbuf))
- : "",
+ ipa_len ? ipaddr2str(ipaddr, ipbuf, sizeof(ipbuf)) : "",
sticky ? " sticky" : "",
remote_gw ? " remote_gw" : "");
return NULL;
@@ -1766,16 +1663,16 @@ struct zebra_mac *zebra_evpn_proc_sync_mac_update(struct zebra_evpn *zevpn,
new_flags = 0;
SET_FLAG(new_flags, ZEBRA_MAC_LOCAL);
/* retain old local activity flag */
- if (old_flags & ZEBRA_MAC_LOCAL)
- new_flags |= (old_flags & ZEBRA_MAC_LOCAL_INACTIVE);
+ if (CHECK_FLAG(old_flags, ZEBRA_MAC_LOCAL))
+ SET_FLAG (new_flags, CHECK_FLAG(old_flags, ZEBRA_MAC_LOCAL_INACTIVE));
else
- new_flags |= ZEBRA_MAC_LOCAL_INACTIVE;
+ SET_FLAG(new_flags, ZEBRA_MAC_LOCAL_INACTIVE);
if (ipa_len) {
/* if mac-ip route do NOT update the peer flags
* i.e. retain only flags as is
*/
- new_flags |= (old_flags & ZEBRA_MAC_ALL_PEER_FLAGS);
+ SET_FLAG(new_flags, CHECK_FLAG(old_flags, ZEBRA_MAC_ALL_PEER_FLAGS));
} else {
/* if mac-only route update peer flags */
if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_PROXY_ADVERT)) {
@@ -1785,10 +1682,8 @@ struct zebra_mac *zebra_evpn_proc_sync_mac_update(struct zebra_evpn *zevpn,
* holdtimer on it. the peer-active flag is
* cleared on holdtimer expiry.
*/
- if (CHECK_FLAG(old_flags,
- ZEBRA_MAC_ES_PEER_ACTIVE)) {
- SET_FLAG(new_flags,
- ZEBRA_MAC_ES_PEER_ACTIVE);
+ if (CHECK_FLAG(old_flags, ZEBRA_MAC_ES_PEER_ACTIVE)) {
+ SET_FLAG(new_flags, ZEBRA_MAC_ES_PEER_ACTIVE);
zebra_evpn_mac_start_hold_timer(mac);
}
} else {
@@ -1811,10 +1706,8 @@ struct zebra_mac *zebra_evpn_proc_sync_mac_update(struct zebra_evpn *zevpn,
zlog_debug(
"sync-mac vni %u mac %pEA old_f %snew_f %s",
zevpn->vni, macaddr,
- zebra_evpn_zebra_mac_flag_dump(
- &omac, omac_buf, sizeof(omac_buf)),
- zebra_evpn_zebra_mac_flag_dump(
- mac, mac_buf, sizeof(mac_buf)));
+ zebra_evpn_zebra_mac_flag_dump(&omac, omac_buf, sizeof(omac_buf)),
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)));
}
/* update es */
@@ -1854,24 +1747,24 @@ struct zebra_mac *zebra_evpn_proc_sync_mac_update(struct zebra_evpn *zevpn,
char mac_buf[MAC_BUF_SIZE];
zlog_debug("sync-mac %s vni %u mac %pEA es %s seq %d f %s%s%s",
- created ? "created" : "updated", zevpn->vni, macaddr,
- mac->es ? mac->es->esi_str : "-", mac->loc_seq,
- zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
- sizeof(mac_buf)),
- inform_bgp ? "inform_bgp" : "",
- inform_dataplane ? " inform_dp" : "");
+ created ? "created" : "updated",
+ zevpn->vni, macaddr,
+ mac->es ? mac->es->esi_str : "-",
+ mac->loc_seq,
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)),
+ inform_bgp ? "inform_bgp" : "",
+ inform_dataplane ? " inform_dp" : "");
}
if (inform_bgp)
- zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready,
- new_bgp_ready);
+ zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready, new_bgp_ready);
/* neighs using the mac may need to be re-sent to
* bgp with updated info
*/
if (seq_change || es_change || !old_local)
zebra_evpn_process_neigh_on_local_mac_change(
- zevpn, mac, seq_change, es_change);
+ zevpn, mac, seq_change, es_change);
if (inform_dataplane && !ipa_len) {
/* program the local mac in the kernel. when the ES
@@ -1879,9 +1772,8 @@ struct zebra_mac *zebra_evpn_proc_sync_mac_update(struct zebra_evpn *zevpn,
* the activity as we are yet to establish activity
* locally
*/
- zebra_evpn_sync_mac_dp_install(
- mac, mac_inactive /* set_inactive */,
- false /* force_clear_static */, __func__);
+ zebra_evpn_sync_mac_dp_install(mac, mac_inactive /* set_inactive */,
+ false /* force_clear_static */, __func__);
}
return mac;
@@ -1891,8 +1783,7 @@ struct zebra_mac *zebra_evpn_proc_sync_mac_update(struct zebra_evpn *zevpn,
* is detected
*/
static bool zebra_evpn_local_mac_update_fwd_info(struct zebra_mac *mac,
- struct interface *ifp,
- vlanid_t vid)
+ struct interface *ifp, vlanid_t vid)
{
struct zebra_if *zif = ifp->info;
bool es_change;
@@ -1934,8 +1825,8 @@ static void zebra_evpn_send_mac_hash_entry_to_client(struct hash_bucket *bucket,
if (CHECK_FLAG(zmac->flags, ZEBRA_MAC_LOCAL))
zebra_evpn_mac_send_add_to_client(wctx->zevpn->vni,
- &zmac->macaddr, zmac->flags,
- zmac->loc_seq, zmac->es);
+ &zmac->macaddr, zmac->flags,
+ zmac->loc_seq, zmac->es);
}
/* Iterator to Notify Local MACs of a EVPN */
@@ -1949,8 +1840,7 @@ void zebra_evpn_send_mac_list_to_client(struct zebra_evpn *zevpn)
memset(&wctx, 0, sizeof(wctx));
wctx.zevpn = zevpn;
- hash_iterate(zevpn->mac_table, zebra_evpn_send_mac_hash_entry_to_client,
- &wctx);
+ hash_iterate(zevpn->mac_table, zebra_evpn_send_mac_hash_entry_to_client, &wctx);
}
void zebra_evpn_rem_mac_del(struct zebra_evpn *zevpn, struct zebra_mac *mac)
@@ -1992,8 +1882,7 @@ void zebra_evpn_print_dad_mac_hash(struct hash_bucket *bucket, void *ctxt)
}
/* Print Duplicate MAC in detail */
-void zebra_evpn_print_dad_mac_hash_detail(struct hash_bucket *bucket,
- void *ctxt)
+void zebra_evpn_print_dad_mac_hash_detail(struct hash_bucket *bucket, void *ctxt)
{
struct zebra_mac *mac;
@@ -2043,11 +1932,13 @@ int zebra_evpn_mac_remote_macip_add(struct zebra_evpn *zevpn,
* If so, that needs to be updated first. Note that client could
* install MAC and MACIP separately or just install the latter.
*/
- if (!mac || !CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)
- || sticky != !!CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY)
- || remote_gw != !!CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW)
- || !IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &vtep_ip)
- || memcmp(old_esi, esi, sizeof(esi_t)) || seq != mac->rem_seq)
+ if (!mac
+ || !CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)
+ || sticky != !!CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY)
+ || remote_gw != !!CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW)
+ || !IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &vtep_ip)
+ || memcmp(old_esi, esi, sizeof(esi_t))
+ || seq != mac->rem_seq)
update_mac = 1;
if (update_mac) {
@@ -2063,8 +1954,7 @@ int zebra_evpn_mac_remote_macip_add(struct zebra_evpn *zevpn,
* the sequence number and ignore this update
* if appropriate.
*/
- if (!zebra_evpn_mac_is_bgp_seq_ok(zevpn, mac, seq,
- false))
+ if (!zebra_evpn_mac_is_bgp_seq_ok(zevpn, mac, seq, false))
return -1;
old_es_present = !!mac->es;
@@ -2091,8 +1981,7 @@ int zebra_evpn_mac_remote_macip_add(struct zebra_evpn *zevpn,
* MAC is already marked duplicate set dad, then
* is_dup_detect will be set to not install the entry.
*/
- if ((!CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)
- && mac->dad_count)
+ if ((!CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE) && mac->dad_count)
|| CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
do_dad = true;
@@ -2108,14 +1997,12 @@ int zebra_evpn_mac_remote_macip_add(struct zebra_evpn *zevpn,
zevpn->vni, macaddr,
mac->es ? mac->es->esi_str : "-",
mac->loc_seq,
- zebra_evpn_zebra_mac_flag_dump(
- mac, mac_buf, sizeof(mac_buf)));
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)));
}
zebra_evpn_mac_clear_sync_info(mac);
- zebra_evpn_mac_send_del_to_client(zevpn->vni, macaddr,
- mac->flags,
- false /* force */);
+ zebra_evpn_mac_send_del_to_client(zevpn->vni, macaddr, mac->flags,
+ false /* force */);
}
/* Set "auto" and "remote" forwarding info. */
@@ -2135,8 +2022,7 @@ int zebra_evpn_mac_remote_macip_add(struct zebra_evpn *zevpn,
UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW);
zebra_evpn_dup_addr_detect_for_mac(
- zvrf, mac, mac->fwd_info.r_vtep_ip, do_dad,
- &is_dup_detect, false);
+ zvrf, mac, mac->fwd_info.r_vtep_ip, do_dad, &is_dup_detect, false);
if (!is_dup_detect) {
zebra_evpn_process_neigh_on_remote_mac_add(zevpn, mac);
@@ -2180,8 +2066,8 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf,
if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC)
zlog_debug(
"ADD %sMAC %pEA intf %s(%u) VID %u -> VNI %u%s",
- sticky ? "sticky " : "", macaddr,
- ifp->name, ifp->ifindex, vid, zevpn->vni,
+ sticky ? "sticky " : "",
+ macaddr, ifp->name, ifp->ifindex, vid, zevpn->vni,
local_inactive ? " local-inactive" : "");
mac = zebra_evpn_mac_add(zevpn, macaddr);
@@ -2196,11 +2082,10 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf,
zlog_debug(
"UPD %sMAC %pEA intf %s(%u) VID %u -> VNI %u %scurFlags %s",
- sticky ? "sticky " : "", macaddr,
- ifp->name, ifp->ifindex, vid, zevpn->vni,
+ sticky ? "sticky " : "",
+ macaddr, ifp->name, ifp->ifindex, vid, zevpn->vni,
local_inactive ? "local-inactive " : "",
- zebra_evpn_zebra_mac_flag_dump(
- mac, mac_buf, sizeof(mac_buf)));
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)));
}
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
@@ -2209,42 +2094,34 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf,
bool old_static;
zebra_evpn_mac_get_access_info(mac, &old_ifp, &old_vid);
- old_bgp_ready =
- zebra_evpn_mac_is_ready_for_bgp(mac->flags);
- old_local_inactive =
- !!(mac->flags & ZEBRA_MAC_LOCAL_INACTIVE);
+ old_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags);
+ old_local_inactive = !!(mac->flags & ZEBRA_MAC_LOCAL_INACTIVE);
old_static = zebra_evpn_mac_is_static(mac);
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY))
mac_sticky = true;
- es_change = zebra_evpn_local_mac_update_fwd_info(
- mac, ifp, vid);
+ es_change = zebra_evpn_local_mac_update_fwd_info(mac, ifp, vid);
/*
* Update any changes and if changes are relevant to
* BGP, note it.
*/
- if (mac_sticky == sticky && old_ifp == ifp
- && old_vid == vid
- && old_local_inactive == local_inactive
- && dp_static == old_static && !es_change) {
+ if (mac_sticky == sticky && old_ifp == ifp && old_vid == vid
+ && old_local_inactive == local_inactive
+ && dp_static == old_static && !es_change) {
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
" Add/Update %sMAC %pEA intf %s(%u) VID %u -> VNI %u%s, "
"entry exists and has not changed ",
sticky ? "sticky " : "",
- macaddr, ifp->name,
- ifp->ifindex, vid, zevpn->vni,
- local_inactive
- ? " local_inactive"
- : "");
+ macaddr, ifp->name, ifp->ifindex, vid, zevpn->vni,
+ local_inactive ? " local_inactive" : "");
return 0;
}
if (mac_sticky != sticky) {
if (sticky)
SET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
else
- UNSET_FLAG(mac->flags,
- ZEBRA_MAC_STICKY);
+ UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
inform_client = true;
}
@@ -2262,11 +2139,9 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf,
/* force drop the peer/sync info as it is
* simply no longer relevant
*/
- if (CHECK_FLAG(mac->flags,
- ZEBRA_MAC_ALL_PEER_FLAGS)) {
+ if (CHECK_FLAG(mac->flags, ZEBRA_MAC_ALL_PEER_FLAGS)) {
zebra_evpn_mac_clear_sync_info(mac);
- new_static =
- zebra_evpn_mac_is_static(mac);
+ new_static = zebra_evpn_mac_is_static(mac);
/* if we clear peer-flags we
* also need to notify the dataplane
* to drop the static flag
@@ -2289,16 +2164,13 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf,
flog_warn(
EC_ZEBRA_STICKY_MAC_ALREADY_LEARNT,
"MAC %pEA already learnt as remote sticky MAC behind VTEP %pI4 VNI %u",
- macaddr,
- &mac->fwd_info.r_vtep_ip,
- zevpn->vni);
+ macaddr, &mac->fwd_info.r_vtep_ip, zevpn->vni);
return 0;
}
/* If an actual move, compute MAC's seq number */
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
- mac->loc_seq =
- MAX(mac->rem_seq + 1, mac->loc_seq);
+ mac->loc_seq = MAX(mac->rem_seq + 1, mac->loc_seq);
vtep_ip = mac->fwd_info.r_vtep_ip;
/* Trigger DAD for remote MAC */
do_dad = true;
@@ -2307,8 +2179,7 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf,
UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE);
UNSET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
- es_change = zebra_evpn_local_mac_update_fwd_info(
- mac, ifp, vid);
+ es_change = zebra_evpn_local_mac_update_fwd_info(mac, ifp, vid);
if (sticky)
SET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
else
@@ -2321,8 +2192,7 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf,
upd_neigh = true;
zebra_evpn_dup_addr_detect_for_mac(
- zvrf, mac, vtep_ip, do_dad, &is_dup_detect,
- true);
+ zvrf, mac, vtep_ip, do_dad, &is_dup_detect, true);
if (is_dup_detect) {
inform_client = false;
upd_neigh = false;
@@ -2357,8 +2227,7 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf,
"local mac vni %u mac %pEA es %s seq %d f %s%s",
zevpn->vni, macaddr,
mac->es ? mac->es->esi_str : "", mac->loc_seq,
- zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
- sizeof(mac_buf)),
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)),
local_inactive ? "local-inactive" : "");
}
@@ -2374,18 +2243,15 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf,
/* Inform dataplane if required. */
if (inform_dataplane)
zebra_evpn_sync_mac_dp_install(mac, false /* set_inactive */,
- false /* force_clear_static */,
- __func__);
+ false /* force_clear_static */, __func__);
/* Inform BGP if required. */
if (inform_client)
- zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready,
- new_bgp_ready);
+ zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready, new_bgp_ready);
/* Process all neighbors associated with this MAC, if required. */
if (upd_neigh)
- zebra_evpn_process_neigh_on_local_mac_change(zevpn, mac, 0,
- es_change);
+ zebra_evpn_process_neigh_on_local_mac_change(zevpn, mac, 0, es_change);
return 0;
}
@@ -2415,23 +2281,20 @@ int zebra_evpn_del_local_mac(struct zebra_evpn *zevpn, struct zebra_mac *mac,
"re-add sync-mac vni %u mac %pEA es %s seq %d f %s",
zevpn->vni, &mac->macaddr,
mac->es ? mac->es->esi_str : "-", mac->loc_seq,
- zebra_evpn_zebra_mac_flag_dump(
- mac, mac_buf, sizeof(mac_buf)));
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)));
}
/* inform-bgp about change in local-activity if any */
if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE)) {
SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE);
- new_bgp_ready =
- zebra_evpn_mac_is_ready_for_bgp(mac->flags);
+ new_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags);
zebra_evpn_mac_send_add_del_to_client(
- mac, old_bgp_ready, new_bgp_ready);
+ mac, old_bgp_ready, new_bgp_ready);
}
/* re-install the inactive entry in the kernel */
zebra_evpn_sync_mac_dp_install(mac, true /* set_inactive */,
- false /* force_clear_static */,
- __func__);
+ false /* force_clear_static */, __func__);
return 0;
}
@@ -2519,8 +2382,7 @@ void zebra_evpn_mac_svi_del(struct interface *ifp, struct zebra_evpn *zevpn)
old_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags);
UNSET_FLAG(mac->flags, ZEBRA_MAC_SVI);
- zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready,
- false);
+ zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready, false);
zebra_evpn_deref_ip2mac(mac->zevpn, mac);
}
}
@@ -2548,13 +2410,11 @@ void zebra_evpn_mac_svi_add(struct interface *ifp, struct zebra_evpn *zevpn)
if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
zlog_debug("SVI %s mac add", zif->ifp->name);
- old_bgp_ready = (mac && zebra_evpn_mac_is_ready_for_bgp(mac->flags))
- ? true
- : false;
+ old_bgp_ready =
+ (mac && zebra_evpn_mac_is_ready_for_bgp(mac->flags)) ? true : false;
zebra_evpn_mac_gw_macip_add(ifp, zevpn, NULL, &mac, &macaddr, 0, false);
new_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags);
- zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready,
- new_bgp_ready);
+ zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready, new_bgp_ready);
}
diff --git a/zebra/zebra_evpn_mh.c b/zebra/zebra_evpn_mh.c
index bf488ca316..0d9d912f83 100644
--- a/zebra/zebra_evpn_mh.c
+++ b/zebra/zebra_evpn_mh.c
@@ -52,10 +52,9 @@ static void zebra_evpn_es_get_one_base_evpn(void);
static int zebra_evpn_es_evi_send_to_client(struct zebra_evpn_es *es,
struct zebra_evpn *zevpn, bool add);
static void zebra_evpn_local_es_del(struct zebra_evpn_es **esp);
-static int zebra_evpn_local_es_update(struct zebra_if *zif, esi_t *esi);
+static void zebra_evpn_local_es_update(struct zebra_if *zif);
static bool zebra_evpn_es_br_port_dplane_update(struct zebra_evpn_es *es,
const char *caller);
-static void zebra_evpn_mh_uplink_cfg_update(struct zebra_if *zif, bool set);
static void zebra_evpn_mh_update_protodown_es(struct zebra_evpn_es *es,
bool resync_dplane);
static void zebra_evpn_mh_clear_protodown_es(struct zebra_evpn_es *es);
@@ -535,19 +534,26 @@ static bool zebra_evpn_acc_vl_cmp(const void *p1, const void *p2)
}
/* Lookup VLAN based broadcast domain */
-struct zebra_evpn_access_bd *zebra_evpn_acc_vl_find(vlanid_t vid,
- struct interface *br_if)
+struct zebra_evpn_access_bd *
+zebra_evpn_acc_vl_find_index(vlanid_t vid, ifindex_t bridge_ifindex)
{
struct zebra_evpn_access_bd *acc_bd;
struct zebra_evpn_access_bd tmp;
tmp.vid = vid;
- tmp.bridge_ifindex = br_if->ifindex;
+ tmp.bridge_ifindex = bridge_ifindex;
acc_bd = hash_lookup(zmh_info->evpn_vlan_table, &tmp);
return acc_bd;
}
+/* Lookup VLAN based broadcast domain */
+struct zebra_evpn_access_bd *zebra_evpn_acc_vl_find(vlanid_t vid,
+ struct interface *br_if)
+{
+ return zebra_evpn_acc_vl_find_index(vid, br_if->ifindex);
+}
+
/* A new broadcast domain can be created when a VLAN member or VLAN<=>VxLAN_IF
* mapping is added.
*/
@@ -842,9 +848,9 @@ void zebra_evpn_access_bd_bridge_cleanup(vlanid_t vid, struct interface *br_if,
void zebra_evpn_vxl_evpn_set(struct zebra_if *zif, struct zebra_evpn *zevpn,
bool set)
{
- struct interface *br_if;
struct zebra_vxlan_vni *vni;
struct zebra_evpn_access_bd *acc_bd;
+ ifindex_t br_ifindex;
if (!zif)
return;
@@ -854,11 +860,12 @@ void zebra_evpn_vxl_evpn_set(struct zebra_if *zif, struct zebra_evpn *zevpn,
if (!vni)
return;
- br_if = zif->brslave_info.br_if;
- if (!br_if)
+ /* Use the index as the pointer can be stale (deleted) */
+ br_ifindex = zif->brslave_info.bridge_ifindex;
+ if (!zif->brslave_info.br_if || br_ifindex == IFINDEX_INTERNAL)
return;
- acc_bd = zebra_evpn_acc_vl_find(vni->access_vlan, br_if);
+ acc_bd = zebra_evpn_acc_vl_find_index(vni->access_vlan, br_ifindex);
if (!acc_bd)
return;
@@ -1131,7 +1138,7 @@ void zebra_evpn_if_init(struct zebra_if *zif)
/* if an es_id and sysmac are already present against the interface
* activate it
*/
- zebra_evpn_local_es_update(zif, &zif->es_info.esi);
+ zebra_evpn_local_es_update(zif);
}
/* handle deletion of an access port by removing it from all associated
@@ -1928,7 +1935,7 @@ static int zebra_evpn_es_send_add_to_client(struct zebra_evpn_es *es)
if (!client)
return 0;
- s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+ s = stream_new(ZEBRA_SMALL_PACKET_SIZE);
zclient_create_header(s, ZEBRA_LOCAL_ES_ADD, zebra_vrf_get_evpn_id());
stream_put(s, &es->esi, sizeof(esi_t));
@@ -1964,7 +1971,7 @@ static int zebra_evpn_es_send_del_to_client(struct zebra_evpn_es *es)
if (!client)
return 0;
- s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+ s = stream_new(ZEBRA_SMALL_PACKET_SIZE);
stream_reset(s);
zclient_create_header(s, ZEBRA_LOCAL_ES_DEL, zebra_vrf_get_evpn_id());
@@ -2242,8 +2249,7 @@ static void zebra_evpn_es_local_info_set(struct zebra_evpn_es *es,
/* attach es to interface */
zif->es_info.es = es;
- es->df_pref = zif->es_info.df_pref ? zif->es_info.df_pref
- : EVPN_MH_DF_PREF_DEFAULT;
+ es->df_pref = zif->es_info.df_pref;
/* attach interface to es */
es->zif = zif;
@@ -2394,73 +2400,63 @@ static void zebra_evpn_es_remote_info_re_eval(struct zebra_evpn_es **esp)
}
}
+void zebra_build_type3_esi(uint32_t lid, struct ethaddr *mac, esi_t *esi)
+{
+ int offset = 0;
+ int field_bytes = 0;
+
+ /* build 10-byte type-3-ESI -
+ * Type(1-byte), MAC(6-bytes), ES-LID (3-bytes)
+ */
+ field_bytes = 1;
+ esi->val[offset] = ESI_TYPE_MAC;
+ offset += field_bytes;
+
+ field_bytes = ETH_ALEN;
+ memcpy(&esi->val[offset], (uint8_t *)mac, field_bytes);
+ offset += field_bytes;
+
+ esi->val[offset++] = (uint8_t)(lid >> 16);
+ esi->val[offset++] = (uint8_t)(lid >> 8);
+ esi->val[offset++] = (uint8_t)lid;
+}
+
/* A new local es is created when a local-es-id and sysmac is configured
* against an interface.
*/
-static int zebra_evpn_local_es_update(struct zebra_if *zif, esi_t *esi)
+static void zebra_evpn_local_es_update(struct zebra_if *zif)
{
struct zebra_evpn_es *old_es = zif->es_info.es;
struct zebra_evpn_es *es;
+ esi_t _esi, *esi;
+
+ if (!zebra_evpn_is_if_es_capable(zif))
+ return;
+
+ if (memcmp(&zif->es_info.esi, zero_esi, sizeof(*zero_esi))) {
+ esi = &zif->es_info.esi;
+ } else if (zif->es_info.lid && !is_zero_mac(&zif->es_info.sysmac)) {
+ zebra_build_type3_esi(zif->es_info.lid, &zif->es_info.sysmac,
+ &_esi);
+ esi = &_esi;
+ } else {
+ esi = zero_esi;
+ }
if (old_es && !memcmp(&old_es->esi, esi, sizeof(*esi)))
/* dup - nothing to be done */
- return 0;
+ return;
/* release the old_es against the zif */
if (old_es)
zebra_evpn_local_es_del(&old_es);
es = zebra_evpn_es_find(esi);
- if (es) {
- /* if it exists against another interface flag an error */
- if (es->zif && es->zif != zif)
- return -1;
- } else {
- /* create new es */
+ if (!es)
es = zebra_evpn_es_new(esi);
- }
- memcpy(&zif->es_info.esi, esi, sizeof(*esi));
if (es)
zebra_evpn_es_local_info_set(es, zif);
-
- return 0;
-}
-
-static int zebra_evpn_type3_esi_update(struct zebra_if *zif, uint32_t lid,
- struct ethaddr *sysmac)
-{
- struct zebra_evpn_es *old_es = zif->es_info.es;
- esi_t esi;
- int offset = 0;
- int field_bytes = 0;
-
- /* Complete config of the ES-ID bootstraps the ES */
- if (!lid || is_zero_mac(sysmac)) {
- /* clear old esi */
- memset(&zif->es_info.esi, 0, sizeof(zif->es_info.esi));
- /* if in ES is attached to zif delete it */
- if (old_es)
- zebra_evpn_local_es_del(&old_es);
- return 0;
- }
-
- /* build 10-byte type-3-ESI -
- * Type(1-byte), MAC(6-bytes), ES-LID (3-bytes)
- */
- field_bytes = 1;
- esi.val[offset] = ESI_TYPE_MAC;
- offset += field_bytes;
-
- field_bytes = ETH_ALEN;
- memcpy(&esi.val[offset], (uint8_t *)sysmac, field_bytes);
- offset += field_bytes;
-
- esi.val[offset++] = (uint8_t)(lid >> 16);
- esi.val[offset++] = (uint8_t)(lid >> 8);
- esi.val[offset++] = (uint8_t)lid;
-
- return zebra_evpn_local_es_update(zif, &esi);
}
int zebra_evpn_remote_es_del(const esi_t *esi, struct in_addr vtep_ip)
@@ -2643,7 +2639,7 @@ static int zebra_evpn_es_evi_send_to_client(struct zebra_evpn_es *es,
if (!client)
return 0;
- s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+ s = stream_new(ZEBRA_SMALL_PACKET_SIZE);
zclient_create_header(s,
add ? ZEBRA_LOCAL_ES_EVI_ADD : ZEBRA_LOCAL_ES_EVI_DEL,
@@ -2665,44 +2661,33 @@ static int zebra_evpn_es_evi_send_to_client(struct zebra_evpn_es *es,
}
/* sysmac part of a local ESI has changed */
-static int zebra_evpn_es_sys_mac_update(struct zebra_if *zif,
- struct ethaddr *sysmac)
+void zebra_evpn_es_sys_mac_update(struct zebra_if *zif, struct ethaddr *sysmac)
{
- int rv;
-
- rv = zebra_evpn_type3_esi_update(zif, zif->es_info.lid, sysmac);
- if (!rv)
+ if (sysmac)
memcpy(&zif->es_info.sysmac, sysmac, sizeof(struct ethaddr));
+ else
+ memset(&zif->es_info.sysmac, 0, sizeof(struct ethaddr));
- return rv;
+ zebra_evpn_local_es_update(zif);
}
/* local-ID part of ESI has changed */
-static int zebra_evpn_es_lid_update(struct zebra_if *zif, uint32_t lid)
+void zebra_evpn_es_lid_update(struct zebra_if *zif, uint32_t lid)
{
- int rv;
+ zif->es_info.lid = lid;
- rv = zebra_evpn_type3_esi_update(zif, lid, &zif->es_info.sysmac);
- if (!rv)
- zif->es_info.lid = lid;
-
- return rv;
+ zebra_evpn_local_es_update(zif);
}
/* type-0 esi has changed */
-static int zebra_evpn_es_type0_esi_update(struct zebra_if *zif, esi_t *esi)
+void zebra_evpn_es_type0_esi_update(struct zebra_if *zif, esi_t *esi)
{
- int rv;
-
- rv = zebra_evpn_local_es_update(zif, esi);
-
- /* clear the old es_lid, es_sysmac - type-0 is being set so old
- * type-3 params need to be flushed
- */
- memset(&zif->es_info.sysmac, 0, sizeof(struct ethaddr));
- zif->es_info.lid = 0;
+ if (esi)
+ memcpy(&zif->es_info.esi, esi, sizeof(*esi));
+ else
+ memset(&zif->es_info.esi, 0, sizeof(*esi));
- return rv;
+ zebra_evpn_local_es_update(zif);
}
void zebra_evpn_es_cleanup(void)
@@ -2718,10 +2703,9 @@ void zebra_evpn_es_cleanup(void)
}
}
-static void zebra_evpn_es_df_pref_update(struct zebra_if *zif, uint16_t df_pref)
+void zebra_evpn_es_df_pref_update(struct zebra_if *zif, uint16_t df_pref)
{
struct zebra_evpn_es *es;
- uint16_t tmp_pref;
if (zif->es_info.df_pref == df_pref)
return;
@@ -2732,13 +2716,10 @@ static void zebra_evpn_es_df_pref_update(struct zebra_if *zif, uint16_t df_pref)
if (!es)
return;
- tmp_pref = zif->es_info.df_pref ? zif->es_info.df_pref
- : EVPN_MH_DF_PREF_DEFAULT;
-
- if (es->df_pref == tmp_pref)
+ if (es->df_pref == zif->es_info.df_pref)
return;
- es->df_pref = tmp_pref;
+ es->df_pref = zif->es_info.df_pref;
/* run df election */
zebra_evpn_es_run_df_election(es, __func__);
/* notify bgp */
@@ -2825,7 +2806,7 @@ void zebra_evpn_es_bypass_update(struct zebra_evpn_es *es,
zebra_evpn_es_br_port_dplane_update(es, __func__);
}
-static void zebra_evpn_es_bypass_cfg_update(struct zebra_if *zif, bool bypass)
+void zebra_evpn_es_bypass_cfg_update(struct zebra_if *zif, bool bypass)
{
bool old_bypass = !!(zif->es_info.flags & ZIF_CFG_ES_FLAG_BYPASS);
@@ -3157,6 +3138,9 @@ static void zebra_evpn_es_show_entry_detail(struct vty *vty,
json_array_string_add(json_flags, "local");
if (es->flags & ZEBRA_EVPNES_REMOTE)
json_array_string_add(json_flags, "remote");
+ if (es->flags & ZEBRA_EVPNES_LOCAL &&
+ !(es->flags & ZEBRA_EVPNES_NON_DF))
+ json_array_string_add(json_flags, "df");
if (es->flags & ZEBRA_EVPNES_NON_DF)
json_array_string_add(json_flags, "nonDF");
if (es->flags & ZEBRA_EVPNES_BYPASS)
@@ -3315,208 +3299,9 @@ void zebra_evpn_es_show_esi(struct vty *vty, bool uj, esi_t *esi)
vty_json(vty, json);
}
-int zebra_evpn_mh_if_write(struct vty *vty, struct interface *ifp)
-{
- struct zebra_if *zif = ifp->info;
- char buf[ETHER_ADDR_STRLEN];
- bool type_3_esi = false;
- char esi_buf[ESI_STR_LEN];
-
- if (zif->es_info.lid) {
- vty_out(vty, " evpn mh es-id %u\n", zif->es_info.lid);
- type_3_esi = true;
- }
-
- if (!is_zero_mac(&zif->es_info.sysmac)) {
- vty_out(vty, " evpn mh es-sys-mac %s\n",
- prefix_mac2str(&zif->es_info.sysmac,
- buf, sizeof(buf)));
- type_3_esi = true;
- }
-
- if (!type_3_esi
- && memcmp(&zif->es_info.esi, zero_esi, sizeof(*zero_esi)))
- vty_out(vty, " evpn mh es-id %s\n",
- esi_to_str(&zif->es_info.esi, esi_buf, sizeof(esi_buf)));
-
- if (zif->es_info.df_pref)
- vty_out(vty, " evpn mh es-df-pref %u\n", zif->es_info.df_pref);
-
- if (zif->flags & ZIF_FLAG_EVPN_MH_UPLINK)
- vty_out(vty, " evpn mh uplink\n");
-
- return 0;
-}
-
-#include "zebra/zebra_evpn_mh_clippy.c"
-/* CLI for setting an ES in bypass mode */
-DEFPY_HIDDEN(zebra_evpn_es_bypass, zebra_evpn_es_bypass_cmd,
- "[no] evpn mh bypass",
- NO_STR "EVPN\n" EVPN_MH_VTY_STR "set bypass mode\n")
+void zebra_evpn_mh_if_init(struct zebra_if *zif)
{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *zif;
-
- zif = ifp->info;
-
- if (no) {
- zebra_evpn_es_bypass_cfg_update(zif, false);
- } else {
- if (!zebra_evpn_is_if_es_capable(zif)) {
- vty_out(vty,
- "%% DF bypass cannot be associated with this interface type\n");
- return CMD_WARNING;
- }
- zebra_evpn_es_bypass_cfg_update(zif, true);
- }
- return CMD_SUCCESS;
-}
-
-/* CLI for configuring DF preference part for an ES */
-DEFPY(zebra_evpn_es_pref, zebra_evpn_es_pref_cmd,
- "[no$no] evpn mh es-df-pref [(1-65535)$df_pref]",
- NO_STR "EVPN\n" EVPN_MH_VTY_STR
- "preference value used for DF election\n"
- "pref\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *zif;
-
- zif = ifp->info;
-
- if (no) {
- zebra_evpn_es_df_pref_update(zif, 0);
- } else {
- if (!zebra_evpn_is_if_es_capable(zif)) {
- vty_out(vty,
- "%% DF preference cannot be associated with this interface type\n");
- return CMD_WARNING;
- }
- zebra_evpn_es_df_pref_update(zif, df_pref);
- }
- return CMD_SUCCESS;
-}
-
-/* CLI for setting up sysmac part of ESI on an access port */
-DEFPY(zebra_evpn_es_sys_mac,
- zebra_evpn_es_sys_mac_cmd,
- "[no$no] evpn mh es-sys-mac [X:X:X:X:X:X$mac]",
- NO_STR
- "EVPN\n"
- EVPN_MH_VTY_STR
- "Ethernet segment system MAC\n"
- MAC_STR
-)
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *zif;
- int ret = 0;
-
- zif = ifp->info;
-
- if (no) {
- static struct ethaddr zero_mac;
-
- ret = zebra_evpn_es_sys_mac_update(zif, &zero_mac);
- if (ret == -1) {
- vty_out(vty, "%% Failed to clear ES sysmac\n");
- return CMD_WARNING;
- }
- } else {
-
- if (!zebra_evpn_is_if_es_capable(zif)) {
- vty_out(vty,
- "%% ESI cannot be associated with this interface type\n");
- return CMD_WARNING;
- }
-
- if (!mac || is_zero_mac(&mac->eth_addr)) {
- vty_out(vty, "%% ES sysmac value is invalid\n");
- return CMD_WARNING;
- }
-
- ret = zebra_evpn_es_sys_mac_update(zif, &mac->eth_addr);
- if (ret == -1) {
- vty_out(vty,
- "%% ESI already exists on a different interface\n");
- return CMD_WARNING;
- }
- }
- return CMD_SUCCESS;
-}
-
-/* CLI for setting up local-ID part of ESI on an access port */
-DEFPY(zebra_evpn_es_id,
- zebra_evpn_es_id_cmd,
- "[no$no] evpn mh es-id [(1-16777215)$es_lid | NAME$esi_str]",
- NO_STR
- "EVPN\n"
- EVPN_MH_VTY_STR
- "Ethernet segment identifier\n"
- "local discriminator\n"
- "10-byte ID - 00:AA:BB:CC:DD:EE:FF:GG:HH:II\n"
-)
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *zif;
- int ret = 0;
- esi_t esi;
-
- zif = ifp->info;
-
- if (no) {
- if (zif->es_info.lid)
- ret = zebra_evpn_es_lid_update(zif, 0);
- else if (memcmp(&zif->es_info.esi, zero_esi, sizeof(*zero_esi)))
- ret = zebra_evpn_es_type0_esi_update(zif, zero_esi);
-
- if (ret == -1) {
- vty_out(vty,
- "%% Failed to clear ES local id or ESI name\n");
- return CMD_WARNING;
- }
- } else {
- if (!zebra_evpn_is_if_es_capable(zif)) {
- vty_out(vty,
- "%% ESI cannot be associated with this interface type\n");
- return CMD_WARNING;
- }
-
- if (esi_str) {
- if (!str_to_esi(esi_str, &esi)) {
- vty_out(vty, "%% Malformed ESI name\n");
- return CMD_WARNING;
- }
- ret = zebra_evpn_es_type0_esi_update(zif, &esi);
- } else {
- if (!es_lid) {
- vty_out(vty,
- "%% Specify ES local id or ESI name\n");
- return CMD_WARNING;
- }
- ret = zebra_evpn_es_lid_update(zif, es_lid);
- }
-
- if (ret == -1) {
- vty_out(vty,
- "%% ESI already exists on a different interface\n");
- return CMD_WARNING;
- }
- }
- return CMD_SUCCESS;
-}
-
-/* CLI for tagging an interface as an uplink */
-DEFPY(zebra_evpn_mh_uplink, zebra_evpn_mh_uplink_cmd, "[no] evpn mh uplink",
- NO_STR "EVPN\n" EVPN_MH_VTY_STR "uplink to the VxLAN core\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct zebra_if *zif;
-
- zif = ifp->info;
- zebra_evpn_mh_uplink_cfg_update(zif, no ? false : true);
-
- return CMD_SUCCESS;
+ zif->es_info.df_pref = EVPN_MH_DF_PREF_DEFAULT;
}
void zebra_evpn_mh_json(json_object *json)
@@ -3853,7 +3638,7 @@ static void zebra_evpn_mh_uplink_oper_flags_update(struct zebra_if *zif,
}
}
-static void zebra_evpn_mh_uplink_cfg_update(struct zebra_if *zif, bool set)
+void zebra_evpn_mh_uplink_cfg_update(struct zebra_if *zif, bool set)
{
bool old_protodown = zebra_evpn_mh_is_all_uplinks_down();
bool new_protodown;
@@ -4076,15 +3861,6 @@ int zebra_evpn_mh_redirect_off(struct vty *vty, bool redirect_off)
return 0;
}
-void zebra_evpn_interface_init(void)
-{
- install_element(INTERFACE_NODE, &zebra_evpn_es_id_cmd);
- install_element(INTERFACE_NODE, &zebra_evpn_es_sys_mac_cmd);
- install_element(INTERFACE_NODE, &zebra_evpn_es_pref_cmd);
- install_element(INTERFACE_NODE, &zebra_evpn_es_bypass_cmd);
- install_element(INTERFACE_NODE, &zebra_evpn_mh_uplink_cmd);
-}
-
void zebra_evpn_mh_init(void)
{
zrouter.mh_info = XCALLOC(MTYPE_ZMH_INFO, sizeof(*zrouter.mh_info));
diff --git a/zebra/zebra_evpn_mh.h b/zebra/zebra_evpn_mh.h
index 6dda30a57f..34ef79f155 100644
--- a/zebra/zebra_evpn_mh.h
+++ b/zebra/zebra_evpn_mh.h
@@ -17,8 +17,7 @@
#include "zebra_vxlan.h"
#include "zebra_vxlan_private.h"
#include "zebra_nhg.h"
-
-#define EVPN_MH_VTY_STR "Multihoming\n"
+#include "zebra_nb.h"
/* Ethernet Segment entry -
* - Local and remote ESs are maintained in a global RB tree,
@@ -155,7 +154,7 @@ struct zebra_evpn_es_vtep {
/* Parameters for DF election */
uint8_t df_alg;
- uint32_t df_pref;
+ uint16_t df_pref;
/* XXX - maintain a backpointer to struct zebra_vtep */
};
@@ -336,14 +335,14 @@ extern bool zebra_evpn_es_mac_ref_entry(struct zebra_mac *mac,
struct zebra_evpn_es *es);
extern bool zebra_evpn_es_mac_ref(struct zebra_mac *mac, const esi_t *esi);
extern struct zebra_evpn_es *zebra_evpn_es_find(const esi_t *esi);
-extern void zebra_evpn_interface_init(void);
-extern int zebra_evpn_mh_if_write(struct vty *vty, struct interface *ifp);
extern void zebra_evpn_acc_vl_show(struct vty *vty, bool uj);
extern void zebra_evpn_acc_vl_show_detail(struct vty *vty, bool uj);
extern void zebra_evpn_if_es_print(struct vty *vty, json_object *json,
struct zebra_if *zif);
extern struct zebra_evpn_access_bd *
zebra_evpn_acc_vl_find(vlanid_t vid, struct interface *br_if);
+struct zebra_evpn_access_bd *
+zebra_evpn_acc_vl_find_index(vlanid_t vid, ifindex_t bridge_ifindex);
extern void zebra_evpn_acc_vl_show_vid(struct vty *vty, bool uj, vlanid_t vid,
struct interface *br_if);
extern void zebra_evpn_es_cleanup(void);
@@ -380,4 +379,16 @@ 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);
+void zebra_build_type3_esi(uint32_t lid, struct ethaddr *mac, esi_t *esi);
+
+void zebra_evpn_es_sys_mac_update(struct zebra_if *zif, struct ethaddr *sysmac);
+void zebra_evpn_es_lid_update(struct zebra_if *zif, uint32_t lid);
+void zebra_evpn_es_type0_esi_update(struct zebra_if *zif, esi_t *esi);
+
+void zebra_evpn_es_df_pref_update(struct zebra_if *zif, uint16_t df_pref);
+void zebra_evpn_es_bypass_cfg_update(struct zebra_if *zif, bool bypass);
+void zebra_evpn_mh_uplink_cfg_update(struct zebra_if *zif, bool set);
+
+void zebra_evpn_mh_if_init(struct zebra_if *zif);
+
#endif /* _ZEBRA_EVPN_MH_H */
diff --git a/zebra/zebra_evpn_neigh.c b/zebra/zebra_evpn_neigh.c
index 74141e4f34..81705d4e85 100644
--- a/zebra/zebra_evpn_neigh.c
+++ b/zebra/zebra_evpn_neigh.c
@@ -6,6 +6,10 @@
#include <zebra.h>
+#ifdef GNU_LINUX
+#include <linux/neighbour.h>
+#endif
+
#include "hash.h"
#include "interface.h"
#include "jhash.h"
@@ -1038,11 +1042,10 @@ static inline void zebra_evpn_local_neigh_update_log(
* from MAC.
*/
static int zebra_evpn_ip_inherit_dad_from_mac(struct zebra_vrf *zvrf,
- struct zebra_mac *old_zmac,
+ bool is_old_mac_dup,
struct zebra_mac *new_zmac,
struct zebra_neigh *nbr)
{
- bool is_old_mac_dup = false;
bool is_new_mac_dup = false;
if (!zebra_evpn_do_dup_addr_detect(zvrf))
@@ -1050,9 +1053,6 @@ static int zebra_evpn_ip_inherit_dad_from_mac(struct zebra_vrf *zvrf,
/* Check old or new MAC is detected as duplicate
* mark this neigh as duplicate
*/
- if (old_zmac)
- is_old_mac_dup =
- CHECK_FLAG(old_zmac->flags, ZEBRA_MAC_DUPLICATE);
if (new_zmac)
is_new_mac_dup =
CHECK_FLAG(new_zmac->flags, ZEBRA_MAC_DUPLICATE);
@@ -1262,6 +1262,7 @@ int zebra_evpn_local_neigh_update(struct zebra_evpn *zevpn,
bool new_static = false;
bool old_bgp_ready = false;
bool new_bgp_ready;
+ bool is_old_mac_dup = false;
/* Check if the MAC exists. */
zmac = zebra_evpn_mac_lookup(zevpn, macaddr);
@@ -1408,6 +1409,7 @@ int zebra_evpn_local_neigh_update(struct zebra_evpn *zevpn,
old_bgp_ready = false;
}
if (old_zmac) {
+ is_old_mac_dup = CHECK_FLAG(old_zmac->flags, ZEBRA_MAC_DUPLICATE);
old_mac_seq = CHECK_FLAG(old_zmac->flags,
ZEBRA_MAC_REMOTE)
? old_zmac->rem_seq
@@ -1437,6 +1439,7 @@ int zebra_evpn_local_neigh_update(struct zebra_evpn *zevpn,
!= 0) {
old_zmac = n->mac;
if (old_zmac) {
+ is_old_mac_dup = CHECK_FLAG(old_zmac->flags, ZEBRA_MAC_DUPLICATE);
old_mac_seq =
CHECK_FLAG(old_zmac->flags,
ZEBRA_MAC_REMOTE)
@@ -1499,7 +1502,7 @@ int zebra_evpn_local_neigh_update(struct zebra_evpn *zevpn,
/* Check old and/or new MAC detected as duplicate mark
* the neigh as duplicate
*/
- if (zebra_evpn_ip_inherit_dad_from_mac(zvrf, old_zmac, zmac, n)) {
+ if (zebra_evpn_ip_inherit_dad_from_mac(zvrf, is_old_mac_dup, zmac, n)) {
flog_warn(
EC_ZEBRA_DUP_IP_INHERIT_DETECTED,
"VNI %u: MAC %pEA IP %pIA detected as duplicate during local update, inherit duplicate from MAC",
@@ -2034,6 +2037,7 @@ void zebra_evpn_neigh_remote_macip_add(struct zebra_evpn *zevpn,
bool do_dad = false;
bool is_dup_detect = false;
bool is_router;
+ bool is_old_mac_dup = false;
assert(mac);
is_router = !!CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG);
@@ -2086,6 +2090,7 @@ void zebra_evpn_neigh_remote_macip_add(struct zebra_evpn *zevpn,
old_mac =
zebra_evpn_mac_lookup(zevpn, &n->emac);
if (old_mac) {
+ is_old_mac_dup = CHECK_FLAG(old_mac->flags, ZEBRA_MAC_DUPLICATE);
listnode_delete(old_mac->neigh_list, n);
n->mac = NULL;
zebra_evpn_deref_ip2mac(zevpn, old_mac);
@@ -2128,7 +2133,7 @@ void zebra_evpn_neigh_remote_macip_add(struct zebra_evpn *zevpn,
/* Check old or new MAC detected as duplicate,
* inherit duplicate flag to this neigh.
*/
- if (zebra_evpn_ip_inherit_dad_from_mac(zvrf, old_mac, mac, n)) {
+ if (zebra_evpn_ip_inherit_dad_from_mac(zvrf, is_old_mac_dup, mac, n)) {
flog_warn(
EC_ZEBRA_DUP_IP_INHERIT_DETECTED,
"VNI %u: MAC %pEA IP %pIA detected as duplicate during remote update, inherit duplicate from MAC",
diff --git a/zebra/zebra_fpm.c b/zebra/zebra_fpm.c
index e379a5868c..92dc591d40 100644
--- a/zebra/zebra_fpm.c
+++ b/zebra/zebra_fpm.c
@@ -8,6 +8,10 @@
#include <zebra.h>
+#ifdef GNU_LINUX
+#include <linux/rtnetlink.h>
+#endif
+
#include "log.h"
#include "libfrr.h"
#include "stream.h"
@@ -497,6 +501,11 @@ static inline void zfpm_connect_off(void)
EVENT_OFF(zfpm_g->t_connect);
}
+static inline void zfpm_conn_down_off(void)
+{
+ EVENT_OFF(zfpm_g->t_conn_down);
+}
+
/*
* zfpm_conn_up_thread_cb
*
@@ -635,8 +644,6 @@ static void zfpm_conn_down_thread_cb(struct event *thread)
while ((mac = TAILQ_FIRST(&zfpm_g->mac_q)) != NULL)
zfpm_mac_info_del(mac);
- zfpm_g->t_conn_down = NULL;
-
iter = &zfpm_g->t_conn_down_state.iter;
while ((rnode = zfpm_rnodes_iter_next(iter))) {
@@ -667,7 +674,6 @@ static void zfpm_conn_down_thread_cb(struct event *thread)
zfpm_g->stats.t_conn_down_yields++;
zfpm_rnodes_iter_pause(iter);
- zfpm_g->t_conn_down = NULL;
event_add_timer_msec(zfpm_g->master, zfpm_conn_down_thread_cb,
NULL, 0, &zfpm_g->t_conn_down);
return;
@@ -712,7 +718,7 @@ static void zfpm_connection_down(const char *detail)
*/
assert(!zfpm_g->t_conn_down);
zfpm_rnodes_iter_init(&zfpm_g->t_conn_down_state.iter);
- zfpm_g->t_conn_down = NULL;
+ zfpm_conn_down_off();
event_add_timer_msec(zfpm_g->master, zfpm_conn_down_thread_cb, NULL, 0,
&zfpm_g->t_conn_down);
zfpm_g->stats.t_conn_down_starts++;
@@ -2042,10 +2048,13 @@ static int zfpm_fini(void)
zfpm_write_off();
zfpm_read_off();
zfpm_connect_off();
+ zfpm_conn_down_off();
zfpm_stop_stats_timer();
hook_unregister(rib_update, zfpm_trigger_update);
+ hook_unregister(zebra_rmac_update, zfpm_trigger_rmac_update);
+
return 0;
}
diff --git a/zebra/zebra_fpm_dt.c b/zebra/zebra_fpm_dt.c
index 94308a961b..ce5eb6fe15 100644
--- a/zebra/zebra_fpm_dt.c
+++ b/zebra/zebra_fpm_dt.c
@@ -22,6 +22,10 @@
*/
#include <zebra.h>
+
+#ifdef GNU_LINUX
+#include <linux/rtnetlink.h>
+#endif
#include "log.h"
#include "vrf.h"
diff --git a/zebra/zebra_fpm_netlink.c b/zebra/zebra_fpm_netlink.c
index 5adca14d71..95207ce75c 100644
--- a/zebra/zebra_fpm_netlink.c
+++ b/zebra/zebra_fpm_netlink.c
@@ -11,6 +11,9 @@
#ifdef HAVE_NETLINK
+#include <linux/rtnetlink.h>
+#include <linux/neighbour.h>
+
#include "log.h"
#include "rib.h"
#include "vty.h"
@@ -252,20 +255,15 @@ static int netlink_route_info_fill(struct netlink_route_info *ri, int cmd,
rib_dest_t *dest, struct route_entry *re)
{
struct nexthop *nexthop;
- struct rib_table_info *table_info =
- rib_table_info(rib_dest_table(dest));
- struct zebra_vrf *zvrf = table_info->zvrf;
memset(ri, 0, sizeof(*ri));
ri->prefix = rib_dest_prefix(dest);
ri->af = rib_dest_af(dest);
- if (zvrf && zvrf->zns)
- ri->nlmsg_pid = zvrf->zns->netlink_dplane_out.snl.nl_pid;
+ ri->nlmsg_pid = pid;
ri->nlmsg_type = cmd;
- ri->rtm_table = table_info->table_id;
ri->rtm_protocol = RTPROT_UNSPEC;
/*
@@ -280,6 +278,8 @@ static int netlink_route_info_fill(struct netlink_route_info *ri, int cmd,
return 0;
}
+ ri->rtm_table = re->table;
+
ri->rtm_protocol = netlink_proto_from_route_type(re->type);
ri->rtm_type = RTN_UNICAST;
ri->metric = &re->metric;
@@ -290,6 +290,8 @@ static int netlink_route_info_fill(struct netlink_route_info *ri, int cmd,
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
continue;
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE))
+ continue;
if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE) {
switch (nexthop->bh_type) {
@@ -590,19 +592,19 @@ int zfpm_netlink_encode_mac(struct fpm_mac_info_t *mac, char *in_buf,
RTM_DELNEIGH : RTM_NEWNEIGH;
req->hdr.nlmsg_flags = NLM_F_REQUEST;
if (req->hdr.nlmsg_type == RTM_NEWNEIGH)
- req->hdr.nlmsg_flags |= (NLM_F_CREATE | NLM_F_REPLACE);
+ SET_FLAG(req->hdr.nlmsg_flags, (NLM_F_CREATE | NLM_F_REPLACE));
/* Construct ndmsg */
req->ndm.ndm_family = AF_BRIDGE;
req->ndm.ndm_ifindex = mac->vxlan_if;
req->ndm.ndm_state = NUD_REACHABLE;
- req->ndm.ndm_flags |= NTF_SELF | NTF_MASTER;
+ SET_FLAG(req->ndm.ndm_flags, (NTF_SELF | NTF_MASTER));
if (CHECK_FLAG(mac->zebra_flags,
(ZEBRA_MAC_STICKY | ZEBRA_MAC_REMOTE_DEF_GW)))
- req->ndm.ndm_state |= NUD_NOARP;
+ SET_FLAG(req->ndm.ndm_state, NUD_NOARP);
else
- req->ndm.ndm_flags |= NTF_EXT_LEARNED;
+ SET_FLAG(req->ndm.ndm_flags, NTF_EXT_LEARNED);
/* Add attributes */
nl_attr_put(&req->hdr, in_buf_len, NDA_LLADDR, &mac->macaddr, 6);
diff --git a/zebra/zebra_gr.c b/zebra/zebra_gr.c
index cf2056b7ac..cee66cc055 100644
--- a/zebra/zebra_gr.c
+++ b/zebra/zebra_gr.c
@@ -80,13 +80,12 @@ void zebra_gr_stale_client_cleanup(struct list *client_list)
/* Cancel the stale timer */
if (info->t_stale_removal != NULL) {
EVENT_OFF(info->t_stale_removal);
- info->t_stale_removal = NULL;
info->do_delete = true;
/* Process the stale routes */
event_execute(
zrouter.master,
zebra_gr_route_stale_delete_timer_expiry,
- info, 0);
+ info, 0, NULL);
}
}
}
@@ -299,6 +298,16 @@ struct zebra_gr_afi_clean {
* Functions to deal with capabilities
*/
+void zebra_gr_client_final_shutdown(struct zserv *client)
+{
+ struct client_gr_info *info;
+
+ while (!TAILQ_EMPTY(&client->gr_info_queue)) {
+ info = TAILQ_FIRST(&client->gr_info_queue);
+ zebra_gr_client_info_delete(client, info);
+ }
+}
+
/*
* Function to decode and call appropriate functions
* to handle client capabilities.
@@ -328,7 +337,7 @@ void zread_client_capabilities(ZAPI_HANDLER_ARGS)
return;
/* GR only for dynamic clients */
- if (client->proto <= ZEBRA_ROUTE_CONNECT) {
+ if (client->proto <= ZEBRA_ROUTE_LOCAL) {
LOG_GR("%s: GR capabilities for client %s not supported",
__func__, zebra_route_string(client->proto));
return;
diff --git a/zebra/zebra_l2.c b/zebra/zebra_l2.c
index 2eea772f9f..0f591810b9 100644
--- a/zebra/zebra_l2.c
+++ b/zebra/zebra_l2.c
@@ -111,13 +111,13 @@ static void zebra_l2_bond_lacp_bypass_eval(struct zebra_if *bond_zif)
{
struct listnode *node;
struct zebra_if *bond_mbr;
- bool old_bypass = !!(bond_zif->flags & ZIF_FLAG_LACP_BYPASS);
+ bool old_bypass = !!CHECK_FLAG(bond_zif->flags, ZIF_FLAG_LACP_BYPASS);
bool new_bypass = false;
if (bond_zif->bond_info.mbr_zifs) {
for (ALL_LIST_ELEMENTS_RO(bond_zif->bond_info.mbr_zifs, node,
bond_mbr)) {
- if (bond_mbr->flags & ZIF_FLAG_LACP_BYPASS) {
+ if (CHECK_FLAG(bond_mbr->flags, ZIF_FLAG_LACP_BYPASS)) {
new_bypass = true;
break;
}
@@ -132,9 +132,9 @@ static void zebra_l2_bond_lacp_bypass_eval(struct zebra_if *bond_zif)
bond_zif->ifp->name, new_bypass ? "on" : "off");
if (new_bypass)
- bond_zif->flags |= ZIF_FLAG_LACP_BYPASS;
+ SET_FLAG(bond_zif->flags, ZIF_FLAG_LACP_BYPASS);
else
- bond_zif->flags &= ~ZIF_FLAG_LACP_BYPASS;
+ UNSET_FLAG(bond_zif->flags, ZIF_FLAG_LACP_BYPASS);
if (bond_zif->es_info.es)
zebra_evpn_es_bypass_update(bond_zif->es_info.es, bond_zif->ifp,
@@ -174,8 +174,7 @@ void zebra_l2_map_slave_to_bond(struct zebra_if *zif, vrf_id_t vrf_id)
}
} else {
if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_EVENT)
- zlog_debug("bond mbr %s link to bond skipped",
- zif->ifp->name);
+ zlog_debug("bond mbr %s link to bond skipped", zif->ifp->name);
}
}
@@ -186,8 +185,7 @@ void zebra_l2_unmap_slave_from_bond(struct zebra_if *zif)
if (!bond_slave->bond_if) {
if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_EVENT)
- zlog_debug("bond mbr %s unlink from bond skipped",
- zif->ifp->name);
+ zlog_debug("bond mbr %s unlink from bond skipped", zif->ifp->name);
return;
}
@@ -218,8 +216,7 @@ void zebra_l2if_update_bond(struct interface *ifp, bool add)
if (add) {
if (!bond->mbr_zifs) {
if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_EVENT)
- zlog_debug("bond %s mbr list create",
- ifp->name);
+ zlog_debug("bond %s mbr list create", ifp->name);
bond->mbr_zifs = list_new();
}
} else {
@@ -244,8 +241,7 @@ void zebra_l2if_update_bond(struct interface *ifp, bool add)
* map slaves (if any) to the bridge.
*/
void zebra_l2_bridge_add_update(struct interface *ifp,
- struct zebra_l2info_bridge *bridge_info,
- int add)
+ const struct zebra_l2info_bridge *bridge_info)
{
struct zebra_if *zif;
struct zebra_l2_bridge_if *br;
@@ -284,7 +280,7 @@ void zebra_l2if_update_bridge(struct interface *ifp, uint8_t chgflags)
* VLAN Id and this cannot change.
*/
void zebra_l2_vlanif_update(struct interface *ifp,
- struct zebra_l2info_vlan *vlan_info)
+ const struct zebra_l2info_vlan *vlan_info)
{
struct zebra_if *zif;
@@ -301,7 +297,7 @@ void zebra_l2_vlanif_update(struct interface *ifp,
* clients about GRE information.
*/
void zebra_l2_greif_add_update(struct interface *ifp,
- struct zebra_l2info_gre *gre_info, int add)
+ const struct zebra_l2info_gre *gre_info, int add)
{
struct zebra_if *zif;
struct in_addr old_vtep_ip;
@@ -328,7 +324,8 @@ void zebra_l2_greif_add_update(struct interface *ifp,
* IP and VLAN mapping, but the latter is handled separately.
*/
void zebra_l2_vxlanif_add_update(struct interface *ifp,
- struct zebra_l2info_vxlan *vxlan_info, int add)
+ const struct zebra_l2info_vxlan *vxlan_info,
+ int add)
{
struct zebra_if *zif;
uint16_t chgflags = 0;
@@ -347,7 +344,7 @@ void zebra_l2_vxlanif_add_update(struct interface *ifp,
ctx.old_vtep_ip = zif->l2info.vxl.vtep_ip;
if (!IPV4_ADDR_SAME(&ctx.old_vtep_ip, &vxlan_info->vtep_ip)) {
- chgflags |= ZEBRA_VXLIF_LOCAL_IP_CHANGE;
+ SET_FLAG(chgflags, ZEBRA_VXLIF_LOCAL_IP_CHANGE);
zif->l2info.vxl.vtep_ip = vxlan_info->vtep_ip;
}
@@ -355,7 +352,7 @@ void zebra_l2_vxlanif_add_update(struct interface *ifp,
ctx.old_vni = vxlan_info->vni_info.vni;
if (!IPV4_ADDR_SAME(&zif->l2info.vxl.vni_info.vni.mcast_grp,
&vxlan_info->vni_info.vni.mcast_grp)) {
- chgflags |= ZEBRA_VXLIF_MCAST_GRP_CHANGE;
+ SET_FLAG(chgflags, ZEBRA_VXLIF_MCAST_GRP_CHANGE);
zif->l2info.vxl.vni_info.vni.mcast_grp =
vxlan_info->vni_info.vni.mcast_grp;
}
@@ -383,7 +380,8 @@ void zebra_l2_vxlanif_update_access_vlan(struct interface *ifp,
assert(zif);
/* This would be called only in non svd case */
- assert(IS_ZEBRA_VXLAN_IF_VNI(zif));
+ if (!IS_ZEBRA_VXLAN_IF_VNI(zif))
+ return;
old_access_vlan = zif->l2info.vxl.vni_info.vni.access_vlan;
;
@@ -440,11 +438,11 @@ void zebra_l2if_update_bridge_slave(struct interface *ifp,
if (zif->zif_type == ZEBRA_IF_VXLAN
&& chgflags != ZEBRA_BRIDGE_NO_ACTION) {
- if (chgflags & ZEBRA_BRIDGE_MASTER_MAC_CHANGE) {
+ if (CHECK_FLAG(chgflags, ZEBRA_BRIDGE_MASTER_MAC_CHANGE)) {
ctx.chgflags = ZEBRA_VXLIF_MASTER_MAC_CHANGE;
zebra_vxlan_if_update(ifp, &ctx);
}
- if (chgflags & ZEBRA_BRIDGE_MASTER_UP) {
+ if (CHECK_FLAG(chgflags, ZEBRA_BRIDGE_MASTER_UP)) {
ctx.chgflags = ZEBRA_VXLIF_MASTER_CHANGE;
zebra_vxlan_if_update(ifp, &ctx);
}
@@ -493,16 +491,16 @@ void zebra_l2if_update_bond_slave(struct interface *ifp, ifindex_t bond_ifindex,
zif = ifp->info;
assert(zif);
- old_bypass = !!(zif->flags & ZIF_FLAG_LACP_BYPASS);
+ old_bypass = !!CHECK_FLAG(zif->flags, ZIF_FLAG_LACP_BYPASS);
if (old_bypass != new_bypass) {
if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_EVENT)
zlog_debug("bond-mbr %s lacp bypass changed to %s",
zif->ifp->name, new_bypass ? "on" : "off");
if (new_bypass)
- zif->flags |= ZIF_FLAG_LACP_BYPASS;
+ SET_FLAG(zif->flags, ZIF_FLAG_LACP_BYPASS);
else
- zif->flags &= ~ZIF_FLAG_LACP_BYPASS;
+ UNSET_FLAG(zif->flags, ZIF_FLAG_LACP_BYPASS);
bond_mbr = &zif->bondslave_info;
if (bond_mbr->bond_if) {
diff --git a/zebra/zebra_l2.h b/zebra/zebra_l2.h
index 3be002656a..588917f4c0 100644
--- a/zebra/zebra_l2.h
+++ b/zebra/zebra_l2.h
@@ -80,6 +80,12 @@ struct zebra_vxlan_vni {
vni_t vni; /* VNI */
vlanid_t access_vlan; /* Access VLAN - for VLAN-aware bridge. */
struct in_addr mcast_grp;
+ uint16_t flags;
+};
+
+struct zebra_vxlan_vni_array {
+ uint16_t count;
+ struct zebra_vxlan_vni vnis[0];
};
enum {
@@ -159,18 +165,19 @@ extern void zebra_l2_map_slave_to_bridge(struct zebra_l2info_brslave *br_slave,
struct zebra_ns *zns);
extern void
zebra_l2_unmap_slave_from_bridge(struct zebra_l2info_brslave *br_slave);
-extern void zebra_l2_bridge_add_update(struct interface *ifp,
- struct zebra_l2info_bridge *bridge_info,
- int add);
+extern void
+zebra_l2_bridge_add_update(struct interface *ifp,
+ const struct zebra_l2info_bridge *bridge_info);
extern void zebra_l2_bridge_del(struct interface *ifp);
extern void zebra_l2_vlanif_update(struct interface *ifp,
- struct zebra_l2info_vlan *vlan_info);
+ const struct zebra_l2info_vlan *vlan_info);
extern void zebra_l2_greif_add_update(struct interface *ifp,
- struct zebra_l2info_gre *vxlan_info,
+ const struct zebra_l2info_gre *vxlan_info,
int add);
-extern void zebra_l2_vxlanif_add_update(struct interface *ifp,
- struct zebra_l2info_vxlan *vxlan_info,
- int add);
+extern void
+zebra_l2_vxlanif_add_update(struct interface *ifp,
+ const struct zebra_l2info_vxlan *vxlan_info,
+ int add);
extern void zebra_l2_vxlanif_update_access_vlan(struct interface *ifp,
vlanid_t access_vlan);
extern void zebra_l2_greif_del(struct interface *ifp);
diff --git a/zebra/zebra_mlag.c b/zebra/zebra_mlag.c
index 6713dbc967..8fd373cb19 100644
--- a/zebra/zebra_mlag.c
+++ b/zebra/zebra_mlag.c
@@ -338,8 +338,6 @@ static void zebra_mlag_post_data_from_main_thread(struct event *thread)
}
}
- stream_free(s);
- return;
stream_failure:
stream_free(s);
if (zebra_s)
@@ -629,6 +627,8 @@ void zebra_mlag_init(void)
void zebra_mlag_terminate(void)
{
+ stream_fifo_free(zrouter.mlag_info.mlag_fifo);
+ zrouter.mlag_info.mlag_fifo = NULL;
}
@@ -985,8 +985,7 @@ int zebra_mlag_protobuf_decode_message(struct stream *s, uint8_t *data,
/* No Batching */
stream_putw(s, MLAG_MSG_NO_BATCH);
/* Actual Data */
- zebra_fill_protobuf_msg(s, msg->peerlink,
- INTERFACE_NAMSIZ);
+ zebra_fill_protobuf_msg(s, msg->peerlink, IFNAMSIZ);
stream_putl(s, msg->my_role);
stream_putl(s, msg->peer_state);
zebra_mlag_status_update__free_unpacked(msg, NULL);
@@ -1034,9 +1033,9 @@ int zebra_mlag_protobuf_decode_message(struct stream *s, uint8_t *data,
stream_putl(s, msg->vrf_id);
if (msg->owner_id == MLAG_OWNER_INTERFACE)
zebra_fill_protobuf_msg(s, msg->intf_name,
- INTERFACE_NAMSIZ);
+ IFNAMSIZ);
else
- stream_put(s, NULL, INTERFACE_NAMSIZ);
+ stream_put(s, NULL, IFNAMSIZ);
zebra_mlag_mroute_add__free_unpacked(msg, NULL);
} break;
case ZEBRA_MLAG__HEADER__MESSAGE_TYPE__ZEBRA_MLAG_MROUTE_DEL: {
@@ -1061,9 +1060,9 @@ int zebra_mlag_protobuf_decode_message(struct stream *s, uint8_t *data,
stream_putl(s, msg->vrf_id);
if (msg->owner_id == MLAG_OWNER_INTERFACE)
zebra_fill_protobuf_msg(s, msg->intf_name,
- INTERFACE_NAMSIZ);
+ IFNAMSIZ);
else
- stream_put(s, NULL, INTERFACE_NAMSIZ);
+ stream_put(s, NULL, IFNAMSIZ);
zebra_mlag_mroute_del__free_unpacked(msg, NULL);
} break;
case ZEBRA_MLAG__HEADER__MESSAGE_TYPE__ZEBRA_MLAG_MROUTE_ADD_BULK: {
@@ -1085,8 +1084,7 @@ int zebra_mlag_protobuf_decode_message(struct stream *s, uint8_t *data,
/* Actual Data */
for (i = 0; i < Bulk_msg->n_mroute_add; i++) {
- if (STREAM_SIZE(s)
- < VRF_NAMSIZ + 22 + INTERFACE_NAMSIZ) {
+ if (STREAM_SIZE(s) < VRF_NAMSIZ + 22 + IFNAMSIZ) {
zlog_warn(
"We have received more messages than we can parse at this point in time: %zu",
Bulk_msg->n_mroute_add);
@@ -1105,11 +1103,11 @@ int zebra_mlag_protobuf_decode_message(struct stream *s, uint8_t *data,
stream_putc(s, msg->am_i_dual_active);
stream_putl(s, msg->vrf_id);
if (msg->owner_id == MLAG_OWNER_INTERFACE)
- zebra_fill_protobuf_msg(
- s, msg->intf_name,
- INTERFACE_NAMSIZ);
+ zebra_fill_protobuf_msg(s,
+ msg->intf_name,
+ IFNAMSIZ);
else
- stream_put(s, NULL, INTERFACE_NAMSIZ);
+ stream_put(s, NULL, IFNAMSIZ);
}
stream_putw_at(s, length_spot, i + 1);
@@ -1136,8 +1134,7 @@ int zebra_mlag_protobuf_decode_message(struct stream *s, uint8_t *data,
/* Actual Data */
for (i = 0; i < Bulk_msg->n_mroute_del; i++) {
- if (STREAM_SIZE(s)
- < VRF_NAMSIZ + 16 + INTERFACE_NAMSIZ) {
+ if (STREAM_SIZE(s) < VRF_NAMSIZ + 16 + IFNAMSIZ) {
zlog_warn(
"We have received more messages than we can parse at this time");
break;
@@ -1152,11 +1149,11 @@ int zebra_mlag_protobuf_decode_message(struct stream *s, uint8_t *data,
stream_putl(s, msg->owner_id);
stream_putl(s, msg->vrf_id);
if (msg->owner_id == MLAG_OWNER_INTERFACE)
- zebra_fill_protobuf_msg(
- s, msg->intf_name,
- INTERFACE_NAMSIZ);
+ zebra_fill_protobuf_msg(s,
+ msg->intf_name,
+ IFNAMSIZ);
else
- stream_put(s, NULL, INTERFACE_NAMSIZ);
+ stream_put(s, NULL, IFNAMSIZ);
}
stream_putw_at(s, length_spot, i + 1);
diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c
index f1a99d89ce..4cc85d461f 100644
--- a/zebra/zebra_mpls.c
+++ b/zebra/zebra_mpls.c
@@ -97,8 +97,8 @@ static struct zebra_nhlfe *nhlfe_find(struct nhlfe_list_head *list,
static struct zebra_nhlfe *
nhlfe_add(struct zebra_lsp *lsp, enum lsp_types_t lsp_type,
enum nexthop_types_t gtype, const union g_addr *gate,
- ifindex_t ifindex, uint8_t num_labels, const mpls_label_t *labels,
- bool is_backup);
+ ifindex_t ifindex, vrf_id_t vrf_id, uint8_t num_labels,
+ const mpls_label_t *labels, bool is_backup);
static int nhlfe_del(struct zebra_nhlfe *nhlfe);
static void nhlfe_free(struct zebra_nhlfe *nhlfe);
static void nhlfe_out_label_update(struct zebra_nhlfe *nhlfe,
@@ -212,11 +212,11 @@ static int lsp_install(struct zebra_vrf *zvrf, mpls_label_t label,
changed++;
} else {
/* Add LSP entry to this nexthop */
- nhlfe = nhlfe_add(lsp, lsp_type, nexthop->type,
- &nexthop->gate, nexthop->ifindex,
- nexthop->nh_label->num_labels,
- nexthop->nh_label->label,
- false /*backup*/);
+ nhlfe = nhlfe_add(
+ lsp, lsp_type, nexthop->type, &nexthop->gate,
+ nexthop->ifindex, nexthop->vrf_id,
+ nexthop->nh_label->num_labels,
+ nexthop->nh_label->label, false /*backup*/);
if (!nhlfe)
return -1;
@@ -329,7 +329,7 @@ static void fec_evaluate(struct zebra_vrf *zvrf)
/* Skip configured FECs and those without a label index.
*/
- if (fec->flags & FEC_FLAG_CONFIGURED
+ if (CHECK_FLAG(fec->flags, FEC_FLAG_CONFIGURED)
|| fec->label_index == MPLS_INVALID_LABEL_INDEX)
continue;
@@ -616,8 +616,9 @@ static int nhlfe_nexthop_active_ipv4(struct zebra_nhlfe *nhlfe,
for (match_nh = match->nhe->nhg.nexthop; match_nh;
match_nh = match_nh->next) {
- if (match->type == ZEBRA_ROUTE_CONNECT
- || nexthop->ifindex == match_nh->ifindex) {
+ if ((match->type == ZEBRA_ROUTE_CONNECT ||
+ match->type == ZEBRA_ROUTE_LOCAL) ||
+ nexthop->ifindex == match_nh->ifindex) {
nexthop->ifindex = match_nh->ifindex;
return 1;
}
@@ -659,9 +660,10 @@ static int nhlfe_nexthop_active_ipv6(struct zebra_nhlfe *nhlfe,
/* Locate a valid connected route. */
RNODE_FOREACH_RE (rn, match) {
- if ((match->type == ZEBRA_ROUTE_CONNECT)
- && !CHECK_FLAG(match->status, ROUTE_ENTRY_REMOVED)
- && CHECK_FLAG(match->flags, ZEBRA_FLAG_SELECTED))
+ if (((match->type == ZEBRA_ROUTE_CONNECT ||
+ match->type == ZEBRA_ROUTE_LOCAL)) &&
+ !CHECK_FLAG(match->status, ROUTE_ENTRY_REMOVED) &&
+ CHECK_FLAG(match->flags, ZEBRA_FLAG_SELECTED))
break;
}
@@ -1029,8 +1031,6 @@ static void lsp_processq_del(struct work_queue *wq, void *data)
return;
zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
- assert(zvrf);
-
lsp_table = zvrf->lsp_table;
if (!lsp_table) // unexpected
return;
@@ -1184,6 +1184,7 @@ static char *nhlfe2str(const struct zebra_nhlfe *nhlfe, char *buf, int size)
break;
case NEXTHOP_TYPE_IFINDEX:
snprintf(buf, size, "Ifindex: %u", nexthop->ifindex);
+ break;
case NEXTHOP_TYPE_BLACKHOLE:
break;
}
@@ -1236,6 +1237,7 @@ static int nhlfe_nhop_match(struct zebra_nhlfe *nhlfe,
/*
* Locate NHLFE that matches with passed info.
+ * TODO: handle vrf_id if vrf backend is netns based
*/
static struct zebra_nhlfe *nhlfe_find(struct nhlfe_list_head *list,
enum lsp_types_t lsp_type,
@@ -1261,7 +1263,8 @@ static struct zebra_nhlfe *nhlfe_find(struct nhlfe_list_head *list,
static struct zebra_nhlfe *
nhlfe_alloc(struct zebra_lsp *lsp, enum lsp_types_t lsp_type,
enum nexthop_types_t gtype, const union g_addr *gate,
- ifindex_t ifindex, uint8_t num_labels, const mpls_label_t *labels)
+ ifindex_t ifindex, vrf_id_t vrf_id, uint8_t num_labels,
+ const mpls_label_t *labels)
{
struct zebra_nhlfe *nhlfe;
struct nexthop *nexthop;
@@ -1278,7 +1281,7 @@ nhlfe_alloc(struct zebra_lsp *lsp, enum lsp_types_t lsp_type,
nexthop_add_labels(nexthop, lsp_type, num_labels, labels);
- nexthop->vrf_id = VRF_DEFAULT;
+ nexthop->vrf_id = vrf_id;
nexthop->type = gtype;
switch (nexthop->type) {
case NEXTHOP_TYPE_IPV4:
@@ -1313,29 +1316,20 @@ nhlfe_alloc(struct zebra_lsp *lsp, enum lsp_types_t lsp_type,
* Add primary or backup NHLFE. Base entry must have been created and
* duplicate check done.
*/
-static struct zebra_nhlfe *nhlfe_add(struct zebra_lsp *lsp,
- enum lsp_types_t lsp_type,
- enum nexthop_types_t gtype,
- const union g_addr *gate,
- ifindex_t ifindex, uint8_t num_labels,
- const mpls_label_t *labels, bool is_backup)
+static struct zebra_nhlfe *
+nhlfe_add(struct zebra_lsp *lsp, enum lsp_types_t lsp_type,
+ enum nexthop_types_t gtype, const union g_addr *gate,
+ ifindex_t ifindex, vrf_id_t vrf_id, uint8_t num_labels,
+ const mpls_label_t *labels, bool is_backup)
{
struct zebra_nhlfe *nhlfe;
if (!lsp)
return NULL;
- /* Must have labels */
- if (num_labels == 0 || labels == NULL) {
- if (IS_ZEBRA_DEBUG_MPLS)
- zlog_debug("%s: invalid nexthop: no labels", __func__);
-
- return NULL;
- }
-
/* Allocate new object */
- nhlfe = nhlfe_alloc(lsp, lsp_type, gtype, gate, ifindex, num_labels,
- labels);
+ nhlfe = nhlfe_alloc(lsp, lsp_type, gtype, gate, ifindex, vrf_id,
+ num_labels, labels);
if (!nhlfe)
return NULL;
@@ -1510,16 +1504,18 @@ static json_object *nhlfe_json(struct zebra_nhlfe *nhlfe)
json_nhlfe = json_object_new_object();
json_object_string_add(json_nhlfe, "type", nhlfe_type2str(nhlfe->type));
- json_object_int_add(json_nhlfe, "outLabel",
- nexthop->nh_label->label[0]);
-
- json_label_stack = json_object_new_array();
- json_object_object_add(json_nhlfe, "outLabelStack", json_label_stack);
- for (i = 0; i < nexthop->nh_label->num_labels; i++)
- json_object_array_add(
- json_label_stack,
- json_object_new_int(nexthop->nh_label->label[i]));
-
+ if (nexthop->nh_label) {
+ json_object_int_add(json_nhlfe, "outLabel",
+ nexthop->nh_label->label[0]);
+ json_label_stack = json_object_new_array();
+ json_object_object_add(json_nhlfe, "outLabelStack",
+ json_label_stack);
+ for (i = 0; i < nexthop->nh_label->num_labels; i++)
+ json_object_array_add(
+ json_label_stack,
+ json_object_new_int(
+ nexthop->nh_label->label[i]));
+ }
json_object_int_add(json_nhlfe, "distance", nhlfe->distance);
if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED))
@@ -1530,6 +1526,10 @@ static json_object *nhlfe_json(struct zebra_nhlfe *nhlfe)
case NEXTHOP_TYPE_IPV4_IFINDEX:
json_object_string_addf(json_nhlfe, "nexthop", "%pI4",
&nexthop->gate.ipv4);
+ if (nexthop->ifindex)
+ json_object_string_add(json_nhlfe, "interface",
+ ifindex2ifname(nexthop->ifindex,
+ nexthop->vrf_id));
break;
case NEXTHOP_TYPE_IPV6:
case NEXTHOP_TYPE_IPV6_IFINDEX:
@@ -1772,14 +1772,9 @@ void zebra_mpls_lsp_dplane_result(struct zebra_dplane_ctx *ctx)
label = dplane_ctx_get_in_label(ctx);
- switch (op) {
- case DPLANE_OP_LSP_INSTALL:
- case DPLANE_OP_LSP_UPDATE:
+ if (op == DPLANE_OP_LSP_INSTALL || op == DPLANE_OP_LSP_UPDATE) {
/* Look for zebra LSP object */
zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
- if (zvrf == NULL)
- break;
-
lsp_table = zvrf->lsp_table;
tmp_ile.in_label = label;
@@ -1788,7 +1783,7 @@ void zebra_mpls_lsp_dplane_result(struct zebra_dplane_ctx *ctx)
if (IS_ZEBRA_DEBUG_DPLANE)
zlog_debug("LSP ctx %p: in-label %u not found",
ctx, dplane_ctx_get_in_label(ctx));
- break;
+ return;
}
/* TODO -- Confirm that this result is still 'current' */
@@ -1799,7 +1794,7 @@ void zebra_mpls_lsp_dplane_result(struct zebra_dplane_ctx *ctx)
flog_warn(EC_ZEBRA_LSP_INSTALL_FAILURE,
"LSP Install Failure: in-label %u",
lsp->ile.in_label);
- break;
+ return;
}
/* Update zebra object */
@@ -1820,73 +1815,16 @@ void zebra_mpls_lsp_dplane_result(struct zebra_dplane_ctx *ctx)
? ZEBRA_SR_POLICY_LABEL_CREATED
: ZEBRA_SR_POLICY_LABEL_UPDATED;
zebra_sr_policy_label_update(label, update_mode);
- break;
-
- case DPLANE_OP_LSP_DELETE:
+ } else if (op == DPLANE_OP_LSP_DELETE) {
if (status != ZEBRA_DPLANE_REQUEST_SUCCESS) {
flog_warn(EC_ZEBRA_LSP_DELETE_FAILURE,
"LSP Deletion Failure: in-label %u",
dplane_ctx_get_in_label(ctx));
- break;
+ return;
}
zebra_sr_policy_label_update(label,
ZEBRA_SR_POLICY_LABEL_REMOVED);
- break;
-
- case DPLANE_OP_LSP_NOTIFY:
- case DPLANE_OP_NONE:
- 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:
- case DPLANE_OP_PW_INSTALL:
- case DPLANE_OP_PW_UNINSTALL:
- case DPLANE_OP_SYS_ROUTE_ADD:
- case DPLANE_OP_SYS_ROUTE_DELETE:
- case DPLANE_OP_ADDR_INSTALL:
- case DPLANE_OP_ADDR_UNINSTALL:
- case DPLANE_OP_MAC_INSTALL:
- case DPLANE_OP_MAC_DELETE:
- case DPLANE_OP_NEIGH_INSTALL:
- case DPLANE_OP_NEIGH_UPDATE:
- case DPLANE_OP_NEIGH_DELETE:
- case DPLANE_OP_VTEP_ADD:
- case DPLANE_OP_VTEP_DELETE:
- case DPLANE_OP_RULE_ADD:
- case DPLANE_OP_RULE_DELETE:
- case DPLANE_OP_RULE_UPDATE:
- case DPLANE_OP_NEIGH_DISCOVER:
- case DPLANE_OP_BR_PORT_UPDATE:
- case DPLANE_OP_IPTABLE_ADD:
- case DPLANE_OP_IPTABLE_DELETE:
- case DPLANE_OP_IPSET_ADD:
- case DPLANE_OP_IPSET_DELETE:
- case DPLANE_OP_IPSET_ENTRY_ADD:
- case DPLANE_OP_IPSET_ENTRY_DELETE:
- case DPLANE_OP_NEIGH_IP_INSTALL:
- case DPLANE_OP_NEIGH_IP_DELETE:
- case DPLANE_OP_NEIGH_TABLE_UPDATE:
- case DPLANE_OP_GRE_SET:
- case DPLANE_OP_INTF_ADDR_ADD:
- case DPLANE_OP_INTF_ADDR_DEL:
- case DPLANE_OP_INTF_NETCONFIG:
- case DPLANE_OP_INTF_INSTALL:
- case DPLANE_OP_INTF_UPDATE:
- case DPLANE_OP_INTF_DELETE:
- case DPLANE_OP_TC_QDISC_INSTALL:
- case DPLANE_OP_TC_QDISC_UNINSTALL:
- case DPLANE_OP_TC_CLASS_ADD:
- case DPLANE_OP_TC_CLASS_DELETE:
- case DPLANE_OP_TC_CLASS_UPDATE:
- case DPLANE_OP_TC_FILTER_ADD:
- case DPLANE_OP_TC_FILTER_DELETE:
- case DPLANE_OP_TC_FILTER_UPDATE:
- break;
-
- } /* Switch */
+ }
}
/*
@@ -2093,9 +2031,6 @@ void zebra_mpls_process_dplane_notify(struct zebra_dplane_ctx *ctx)
/* Look for zebra LSP object */
zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
- if (zvrf == NULL)
- return;
-
lsp_table = zvrf->lsp_table;
tmp_ile.in_label = dplane_ctx_get_in_label(ctx);
@@ -2242,8 +2177,8 @@ zebra_mpls_lsp_add_nhlfe(struct zebra_lsp *lsp, enum lsp_types_t lsp_type,
const mpls_label_t *out_labels)
{
/* Just a public pass-through to the internal implementation */
- return nhlfe_add(lsp, lsp_type, gtype, gate, ifindex, num_labels,
- out_labels, false /*backup*/);
+ return nhlfe_add(lsp, lsp_type, gtype, gate, ifindex, VRF_DEFAULT,
+ num_labels, out_labels, false /*backup*/);
}
/*
@@ -2257,8 +2192,8 @@ struct zebra_nhlfe *zebra_mpls_lsp_add_backup_nhlfe(
uint8_t num_labels, const mpls_label_t *out_labels)
{
/* Just a public pass-through to the internal implementation */
- return nhlfe_add(lsp, lsp_type, gtype, gate, ifindex, num_labels,
- out_labels, true);
+ return nhlfe_add(lsp, lsp_type, gtype, gate, ifindex, VRF_DEFAULT,
+ num_labels, out_labels, true);
}
/*
@@ -2270,12 +2205,10 @@ struct zebra_nhlfe *zebra_mpls_lsp_add_nh(struct zebra_lsp *lsp,
{
struct zebra_nhlfe *nhlfe;
- if (nh->nh_label == NULL || nh->nh_label->num_labels == 0)
- return NULL;
-
- nhlfe = nhlfe_add(lsp, lsp_type, nh->type, &nh->gate, nh->ifindex,
- nh->nh_label->num_labels, nh->nh_label->label,
- false /*backup*/);
+ nhlfe = nhlfe_add(
+ lsp, lsp_type, nh->type, &nh->gate, nh->ifindex, nh->vrf_id,
+ nh->nh_label ? nh->nh_label->num_labels : 0,
+ nh->nh_label ? nh->nh_label->label : NULL, false /*backup*/);
return nhlfe;
}
@@ -2290,12 +2223,10 @@ struct zebra_nhlfe *zebra_mpls_lsp_add_backup_nh(struct zebra_lsp *lsp,
{
struct zebra_nhlfe *nhlfe;
- if (nh->nh_label == NULL || nh->nh_label->num_labels == 0)
- return NULL;
-
- nhlfe = nhlfe_add(lsp, lsp_type, nh->type, &nh->gate,
- nh->ifindex, nh->nh_label->num_labels,
- nh->nh_label->label, true);
+ nhlfe = nhlfe_add(lsp, lsp_type, nh->type, &nh->gate, nh->ifindex,
+ nh->vrf_id,
+ nh->nh_label ? nh->nh_label->num_labels : 0,
+ nh->nh_label ? nh->nh_label->label : NULL, true);
return nhlfe;
}
@@ -2360,7 +2291,7 @@ int zebra_mpls_fec_register(struct zebra_vrf *zvrf, struct prefix *p,
new_client = true;
} else {
/* Check if the FEC has been statically defined in the config */
- is_configured_fec = fec->flags & FEC_FLAG_CONFIGURED;
+ is_configured_fec = CHECK_FLAG(fec->flags, FEC_FLAG_CONFIGURED);
/* Client may register same FEC with different label index. */
new_client =
(listnode_lookup(fec->client_list, client) == NULL);
@@ -2451,8 +2382,8 @@ int zebra_mpls_fec_unregister(struct zebra_vrf *zvrf, struct prefix *p,
/* If not a configured entry, delete the FEC if no other clients. Before
* deleting, see if any LSP needs to be uninstalled.
*/
- if (!(fec->flags & FEC_FLAG_CONFIGURED)
- && list_isempty(fec->client_list)) {
+ if (!CHECK_FLAG(fec->flags, FEC_FLAG_CONFIGURED) &&
+ list_isempty(fec->client_list)) {
mpls_label_t old_label = fec->label;
fec->label = MPLS_INVALID_LABEL; /* reset */
fec_change_update_lsp(zvrf, fec, old_label);
@@ -2489,7 +2420,7 @@ static int zebra_mpls_cleanup_fecs_for_client(struct zserv *client)
if (fec_client == client) {
listnode_delete(fec->client_list,
fec_client);
- if (!(fec->flags & FEC_FLAG_CONFIGURED)
+ if (!CHECK_FLAG(fec->flags, FEC_FLAG_CONFIGURED)
&& list_isempty(fec->client_list))
fec_del(fec);
break;
@@ -2545,7 +2476,7 @@ static int zebra_mpls_cleanup_zclient_labels(struct zserv *client)
* hash..
*/
struct zebra_fec *zebra_mpls_fec_for_label(struct zebra_vrf *zvrf,
- mpls_label_t label)
+ struct prefix *p, mpls_label_t label)
{
struct route_node *rn;
struct zebra_fec *fec;
@@ -2560,8 +2491,11 @@ struct zebra_fec *zebra_mpls_fec_for_label(struct zebra_vrf *zvrf,
if (!rn->info)
continue;
fec = rn->info;
- if (fec->label == label)
+ if (fec->label == label) {
+ if (p && prefix_same(p, &rn->p))
+ return NULL;
return fec;
+ }
}
}
@@ -2571,9 +2505,10 @@ struct zebra_fec *zebra_mpls_fec_for_label(struct zebra_vrf *zvrf,
/*
* Inform if specified label is currently bound to a FEC or not.
*/
-int zebra_mpls_label_already_bound(struct zebra_vrf *zvrf, mpls_label_t label)
+int zebra_mpls_label_already_bound(struct zebra_vrf *zvrf, struct prefix *p,
+ mpls_label_t label)
{
- return (zebra_mpls_fec_for_label(zvrf, label) ? 1 : 0);
+ return (zebra_mpls_fec_for_label(zvrf, p, label) ? 1 : 0);
}
/*
@@ -2607,7 +2542,7 @@ int zebra_mpls_static_fec_add(struct zebra_vrf *zvrf, struct prefix *p,
if (IS_ZEBRA_DEBUG_MPLS)
zlog_debug("Add fec %pFX label %u", p, in_label);
} else {
- fec->flags |= FEC_FLAG_CONFIGURED;
+ SET_FLAG(fec->flags, FEC_FLAG_CONFIGURED);
if (fec->label == in_label)
/* Duplicate config */
return 0;
@@ -2656,7 +2591,7 @@ int zebra_mpls_static_fec_del(struct zebra_vrf *zvrf, struct prefix *p)
}
old_label = fec->label;
- fec->flags &= ~FEC_FLAG_CONFIGURED;
+ UNSET_FLAG(fec->flags, FEC_FLAG_CONFIGURED);
fec->label = MPLS_INVALID_LABEL;
/* If no client exists, just delete the FEC. */
@@ -2699,7 +2634,7 @@ int zebra_mpls_write_fec_config(struct vty *vty, struct zebra_vrf *zvrf)
char lstr[BUFSIZ];
fec = rn->info;
- if (!(fec->flags & FEC_FLAG_CONFIGURED))
+ if (!CHECK_FLAG(fec->flags, FEC_FLAG_CONFIGURED))
continue;
write = 1;
@@ -3113,7 +3048,7 @@ static struct zebra_nhlfe *
lsp_add_nhlfe(struct zebra_lsp *lsp, enum lsp_types_t type,
uint8_t num_out_labels, const mpls_label_t *out_labels,
enum nexthop_types_t gtype, const union g_addr *gate,
- ifindex_t ifindex, bool is_backup)
+ ifindex_t ifindex, vrf_id_t vrf_id, bool is_backup)
{
struct zebra_nhlfe *nhlfe;
char buf[MPLS_LABEL_STRLEN];
@@ -3133,13 +3068,18 @@ lsp_add_nhlfe(struct zebra_lsp *lsp, enum lsp_types_t type,
struct nexthop *nh = nhlfe->nexthop;
assert(nh);
- assert(nh->nh_label);
/* Clear deleted flag (in case it was set) */
UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_DELETED);
- if (nh->nh_label->num_labels == num_out_labels
- && !memcmp(nh->nh_label->label, out_labels,
- sizeof(mpls_label_t) * num_out_labels))
+
+ if (!nh->nh_label || num_out_labels == 0)
+ /* No change */
+ return nhlfe;
+
+ if (nh->nh_label &&
+ nh->nh_label->num_labels == num_out_labels &&
+ !memcmp(nh->nh_label->label, out_labels,
+ sizeof(mpls_label_t) * num_out_labels))
/* No change */
return nhlfe;
@@ -3160,7 +3100,7 @@ lsp_add_nhlfe(struct zebra_lsp *lsp, enum lsp_types_t type,
}
/* Update out label(s), trigger processing. */
- if (nh->nh_label->num_labels == num_out_labels)
+ if (nh->nh_label && nh->nh_label->num_labels == num_out_labels)
memcpy(nh->nh_label->label, out_labels,
sizeof(mpls_label_t) * num_out_labels);
else {
@@ -3170,7 +3110,7 @@ lsp_add_nhlfe(struct zebra_lsp *lsp, enum lsp_types_t type,
}
} else {
/* Add LSP entry to this nexthop */
- nhlfe = nhlfe_add(lsp, type, gtype, gate, ifindex,
+ nhlfe = nhlfe_add(lsp, type, gtype, gate, ifindex, vrf_id,
num_out_labels, out_labels, is_backup);
if (!nhlfe)
return NULL;
@@ -3179,8 +3119,11 @@ lsp_add_nhlfe(struct zebra_lsp *lsp, enum lsp_types_t type,
char buf2[MPLS_LABEL_STRLEN];
nhlfe2str(nhlfe, buf, sizeof(buf));
- mpls_label2str(num_out_labels, out_labels, buf2,
- sizeof(buf2), 0, 0);
+ if (num_out_labels)
+ mpls_label2str(num_out_labels, out_labels, buf2,
+ sizeof(buf2), 0, 0);
+ else
+ snprintf(buf2, sizeof(buf2), "-");
zlog_debug("Add LSP in-label %u type %d %snexthop %s out-label(s) %s",
lsp->ile.in_label, type, backup_str, buf,
@@ -3199,6 +3142,8 @@ lsp_add_nhlfe(struct zebra_lsp *lsp, enum lsp_types_t type,
/*
* Install an LSP and forwarding entry; used primarily
* from vrf zapi message processing.
+ * TODO: handle vrf_id parameter when mpls API extends to interface or SRTE
+ * changes
*/
int mpls_lsp_install(struct zebra_vrf *zvrf, enum lsp_types_t type,
mpls_label_t in_label, uint8_t num_out_labels,
@@ -3220,7 +3165,7 @@ int mpls_lsp_install(struct zebra_vrf *zvrf, enum lsp_types_t type,
lsp = hash_get(lsp_table, &tmp_ile, lsp_alloc);
nhlfe = lsp_add_nhlfe(lsp, type, num_out_labels, out_labels, gtype,
- gate, ifindex, false /*backup*/);
+ gate, ifindex, VRF_DEFAULT, false /*backup*/);
if (nhlfe == NULL)
return -1;
@@ -3239,8 +3184,8 @@ static int lsp_znh_install(struct zebra_lsp *lsp, enum lsp_types_t type,
{
struct zebra_nhlfe *nhlfe;
- nhlfe = lsp_add_nhlfe(lsp, type, znh->label_num, znh->labels,
- znh->type, &znh->gate, znh->ifindex,
+ nhlfe = lsp_add_nhlfe(lsp, type, znh->label_num, znh->labels, znh->type,
+ &znh->gate, znh->ifindex, znh->vrf_id,
false /*backup*/);
if (nhlfe == NULL)
return -1;
@@ -3277,9 +3222,9 @@ static int lsp_backup_znh_install(struct zebra_lsp *lsp, enum lsp_types_t type,
{
struct zebra_nhlfe *nhlfe;
- nhlfe = lsp_add_nhlfe(lsp, type, znh->label_num,
- znh->labels, znh->type, &znh->gate,
- znh->ifindex, true /*backup*/);
+ nhlfe = lsp_add_nhlfe(lsp, type, znh->label_num, znh->labels, znh->type,
+ &znh->gate, znh->ifindex, znh->vrf_id,
+ true /*backup*/);
if (nhlfe == NULL) {
if (IS_ZEBRA_DEBUG_MPLS)
zlog_debug("%s: unable to add backup nhlfe, label: %u",
@@ -3610,8 +3555,8 @@ int zebra_mpls_static_lsp_add(struct zebra_vrf *zvrf, mpls_label_t in_label,
} else {
/* Add static LSP entry to this nexthop */
- nhlfe = nhlfe_add(lsp, ZEBRA_LSP_STATIC, gtype, gate,
- ifindex, 1, &out_label, false /*backup*/);
+ nhlfe = nhlfe_add(lsp, ZEBRA_LSP_STATIC, gtype, gate, ifindex,
+ VRF_DEFAULT, 1, &out_label, false /*backup*/);
if (!nhlfe)
return -1;
@@ -3820,7 +3765,8 @@ void zebra_mpls_print_lsp_table(struct vty *vty, struct zebra_vrf *zvrf,
break;
}
- if (nexthop->type != NEXTHOP_TYPE_IFINDEX)
+ if (nexthop->type != NEXTHOP_TYPE_IFINDEX &&
+ nexthop->nh_label)
out_label_str = mpls_label2str(
nexthop->nh_label->num_labels,
&nexthop->nh_label->label[0],
@@ -4094,10 +4040,12 @@ void zebra_mpls_turned_on(void)
if (!mpls_enabled) {
mpls_processq_init();
mpls_enabled = true;
- }
- hook_register(zserv_client_close, zebra_mpls_cleanup_fecs_for_client);
- hook_register(zserv_client_close, zebra_mpls_cleanup_zclient_labels);
+ hook_register(zserv_client_close,
+ zebra_mpls_cleanup_fecs_for_client);
+ hook_register(zserv_client_close,
+ zebra_mpls_cleanup_zclient_labels);
+ }
}
/*
@@ -4116,3 +4064,9 @@ void zebra_mpls_init(void)
zebra_mpls_turned_on();
}
+
+void zebra_mpls_terminate(void)
+{
+ hook_unregister(zserv_client_close, zebra_mpls_cleanup_fecs_for_client);
+ hook_unregister(zserv_client_close, zebra_mpls_cleanup_zclient_labels);
+}
diff --git a/zebra/zebra_mpls.h b/zebra/zebra_mpls.h
index 7feace56b5..dd6f960146 100644
--- a/zebra/zebra_mpls.h
+++ b/zebra/zebra_mpls.h
@@ -203,12 +203,13 @@ int zebra_mpls_fec_unregister(struct zebra_vrf *zvrf, struct prefix *p,
* hash..
*/
struct zebra_fec *zebra_mpls_fec_for_label(struct zebra_vrf *zvrf,
- mpls_label_t label);
+ struct prefix *p, mpls_label_t label);
/*
* Inform if specified label is currently bound to a FEC or not.
*/
-int zebra_mpls_label_already_bound(struct zebra_vrf *zvrf, mpls_label_t label);
+int zebra_mpls_label_already_bound(struct zebra_vrf *zvrf, struct prefix *p,
+ mpls_label_t label);
/*
* Add static FEC to label binding. If there are clients registered for this
@@ -400,9 +401,10 @@ void zebra_mpls_init_tables(struct zebra_vrf *zvrf);
void zebra_mpls_turned_on(void);
/*
- * Global MPLS initialization.
+ * Global MPLS initialization/termination.
*/
void zebra_mpls_init(void);
+void zebra_mpls_terminate(void);
/*
* MPLS VTY.
diff --git a/zebra/zebra_mpls_netlink.c b/zebra/zebra_mpls_netlink.c
index 4bc676f392..f0f2c4b7a3 100644
--- a/zebra/zebra_mpls_netlink.c
+++ b/zebra/zebra_mpls_netlink.c
@@ -4,9 +4,13 @@
*/
#include <zebra.h>
+#include <sys/stat.h>
#ifdef HAVE_NETLINK
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+
#include "zebra/debug.h"
#include "zebra/rt.h"
#include "zebra/rt_netlink.h"
diff --git a/zebra/zebra_mpls_openbsd.c b/zebra/zebra_mpls_openbsd.c
index ee6f7045f5..85a53dd4c5 100644
--- a/zebra/zebra_mpls_openbsd.c
+++ b/zebra/zebra_mpls_openbsd.c
@@ -4,6 +4,8 @@
*/
#include <zebra.h>
+#include <sys/ioctl.h>
+#include <sys/uio.h>
#ifdef OPEN_BSD
@@ -62,8 +64,8 @@ static int kernel_send_rtmsg_v4(int action, mpls_label_t in_label,
sa_label_in.smpls_family = AF_MPLS;
sa_label_in.smpls_label = htonl(in_label << MPLS_LABEL_OFFSET);
/* adjust header */
- hdr.rtm_flags |= RTF_MPLS | RTF_MPATH;
- hdr.rtm_addrs |= RTA_DST;
+ SET_FLAG(hdr.rtm_flags, (RTF_MPLS | RTF_MPATH));
+ SET_FLAG(hdr.rtm_addrs, RTA_DST);
hdr.rtm_msglen += sizeof(sa_label_in);
/* adjust iovec */
iov[iovcnt].iov_base = &sa_label_in;
@@ -75,8 +77,8 @@ static int kernel_send_rtmsg_v4(int action, mpls_label_t in_label,
nexthop.sin_family = AF_INET;
nexthop.sin_addr = nhlfe->nexthop->gate.ipv4;
/* adjust header */
- hdr.rtm_flags |= RTF_GATEWAY;
- hdr.rtm_addrs |= RTA_GATEWAY;
+ SET_FLAG(hdr.rtm_flags, RTF_GATEWAY);
+ SET_FLAG(hdr.rtm_addrs, RTA_GATEWAY);
hdr.rtm_msglen += sizeof(nexthop);
/* adjust iovec */
iov[iovcnt].iov_base = &nexthop;
@@ -91,8 +93,8 @@ static int kernel_send_rtmsg_v4(int action, mpls_label_t in_label,
htonl(nhlfe->nexthop->nh_label->label[0]
<< MPLS_LABEL_OFFSET);
/* adjust header */
- hdr.rtm_addrs |= RTA_SRC;
- hdr.rtm_flags |= RTF_MPLS;
+ SET_FLAG(hdr.rtm_addrs, RTA_SRC);
+ SET_FLAG(hdr.rtm_flags, RTF_MPLS);
hdr.rtm_msglen += sizeof(sa_label_out);
/* adjust iovec */
iov[iovcnt].iov_base = &sa_label_out;
@@ -157,8 +159,8 @@ static int kernel_send_rtmsg_v6(int action, mpls_label_t in_label,
sa_label_in.smpls_family = AF_MPLS;
sa_label_in.smpls_label = htonl(in_label << MPLS_LABEL_OFFSET);
/* adjust header */
- hdr.rtm_flags |= RTF_MPLS | RTF_MPATH;
- hdr.rtm_addrs |= RTA_DST;
+ SET_FLAG(hdr.rtm_flags, (RTF_MPLS | RTF_MPATH));
+ SET_FLAG(hdr.rtm_addrs, RTA_DST);
hdr.rtm_msglen += sizeof(sa_label_in);
/* adjust iovec */
iov[iovcnt].iov_base = &sa_label_in;
@@ -182,8 +184,8 @@ static int kernel_send_rtmsg_v6(int action, mpls_label_t in_label,
}
/* adjust header */
- hdr.rtm_flags |= RTF_GATEWAY;
- hdr.rtm_addrs |= RTA_GATEWAY;
+ SET_FLAG(hdr.rtm_flags, RTF_GATEWAY);
+ SET_FLAG(hdr.rtm_addrs, RTA_GATEWAY);
hdr.rtm_msglen += ROUNDUP(sizeof(struct sockaddr_in6));
/* adjust iovec */
iov[iovcnt].iov_base = &nexthop;
@@ -198,8 +200,8 @@ static int kernel_send_rtmsg_v6(int action, mpls_label_t in_label,
htonl(nhlfe->nexthop->nh_label->label[0]
<< MPLS_LABEL_OFFSET);
/* adjust header */
- hdr.rtm_addrs |= RTA_SRC;
- hdr.rtm_flags |= RTF_MPLS;
+ SET_FLAG(hdr.rtm_addrs, RTA_SRC);
+ SET_FLAG(hdr.rtm_flags, RTF_MPLS);
hdr.rtm_msglen += sizeof(sa_label_out);
/* adjust iovec */
iov[iovcnt].iov_base = &sa_label_out;
@@ -229,70 +231,18 @@ static int kernel_lsp_cmd(struct zebra_dplane_ctx *ctx)
const struct nexthop *nexthop = NULL;
unsigned int nexthop_num = 0;
int action;
+ enum dplane_op_e op;
- switch (dplane_ctx_get_op(ctx)) {
- case DPLANE_OP_LSP_DELETE:
+ op = dplane_ctx_get_op(ctx);
+
+ if (op == DPLANE_OP_LSP_DELETE)
action = RTM_DELETE;
- break;
- case DPLANE_OP_LSP_INSTALL:
+ else if (op == DPLANE_OP_LSP_INSTALL)
action = RTM_ADD;
- break;
- case DPLANE_OP_LSP_UPDATE:
+ else if (op == DPLANE_OP_LSP_UPDATE)
action = RTM_CHANGE;
- break;
- case DPLANE_OP_NONE:
- 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:
- case DPLANE_OP_LSP_NOTIFY:
- case DPLANE_OP_PW_INSTALL:
- case DPLANE_OP_PW_UNINSTALL:
- case DPLANE_OP_SYS_ROUTE_ADD:
- case DPLANE_OP_SYS_ROUTE_DELETE:
- case DPLANE_OP_ADDR_INSTALL:
- case DPLANE_OP_ADDR_UNINSTALL:
- case DPLANE_OP_MAC_INSTALL:
- case DPLANE_OP_MAC_DELETE:
- case DPLANE_OP_NEIGH_INSTALL:
- case DPLANE_OP_NEIGH_UPDATE:
- case DPLANE_OP_NEIGH_DELETE:
- case DPLANE_OP_VTEP_ADD:
- case DPLANE_OP_VTEP_DELETE:
- case DPLANE_OP_RULE_ADD:
- case DPLANE_OP_RULE_DELETE:
- case DPLANE_OP_RULE_UPDATE:
- case DPLANE_OP_NEIGH_DISCOVER:
- case DPLANE_OP_BR_PORT_UPDATE:
- case DPLANE_OP_IPTABLE_ADD:
- case DPLANE_OP_IPTABLE_DELETE:
- case DPLANE_OP_IPSET_ADD:
- case DPLANE_OP_IPSET_DELETE:
- case DPLANE_OP_IPSET_ENTRY_ADD:
- case DPLANE_OP_IPSET_ENTRY_DELETE:
- case DPLANE_OP_NEIGH_IP_INSTALL:
- case DPLANE_OP_NEIGH_IP_DELETE:
- case DPLANE_OP_NEIGH_TABLE_UPDATE:
- case DPLANE_OP_GRE_SET:
- case DPLANE_OP_INTF_ADDR_ADD:
- case DPLANE_OP_INTF_ADDR_DEL:
- case DPLANE_OP_INTF_NETCONFIG:
- case DPLANE_OP_INTF_INSTALL:
- case DPLANE_OP_INTF_UPDATE:
- case DPLANE_OP_INTF_DELETE:
- case DPLANE_OP_TC_QDISC_INSTALL:
- case DPLANE_OP_TC_QDISC_UNINSTALL:
- case DPLANE_OP_TC_CLASS_ADD:
- case DPLANE_OP_TC_CLASS_DELETE:
- case DPLANE_OP_TC_CLASS_UPDATE:
- case DPLANE_OP_TC_FILTER_ADD:
- case DPLANE_OP_TC_FILTER_DELETE:
- case DPLANE_OP_TC_FILTER_UPDATE:
+ else
return -1;
- }
head = dplane_ctx_get_nhlfe_list(ctx);
frr_each(nhlfe_list_const, head, nhlfe) {
@@ -374,8 +324,8 @@ static enum zebra_dplane_result kmpw_install(struct zebra_dplane_ctx *ctx)
return ZEBRA_DPLANE_REQUEST_FAILURE;
}
- if (dplane_ctx_get_pw_flags(ctx) & F_PSEUDOWIRE_CWORD)
- imr.imr_flags |= IMR_FLAG_CONTROLWORD;
+ if (CHECK_FLAG(dplane_ctx_get_pw_flags(ctx), F_PSEUDOWIRE_CWORD))
+ SET_FLAG(imr.imr_flags, IMR_FLAG_CONTROLWORD);
/* pseudowire nexthop */
memset(&ss, 0, sizeof(ss));
@@ -442,68 +392,14 @@ static enum zebra_dplane_result kmpw_uninstall(struct zebra_dplane_ctx *ctx)
enum zebra_dplane_result kernel_pw_update(struct zebra_dplane_ctx *ctx)
{
enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
+ enum dplane_op_e op;
- switch (dplane_ctx_get_op(ctx)) {
- case DPLANE_OP_PW_INSTALL:
+ op = dplane_ctx_get_op(ctx);
+
+ if (op == DPLANE_OP_PW_INSTALL)
result = kmpw_install(ctx);
- break;
- case DPLANE_OP_PW_UNINSTALL:
+ else if (op == DPLANE_OP_PW_UNINSTALL)
result = kmpw_uninstall(ctx);
- break;
- case DPLANE_OP_NONE:
- 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:
- case DPLANE_OP_LSP_INSTALL:
- case DPLANE_OP_LSP_UPDATE:
- case DPLANE_OP_LSP_DELETE:
- case DPLANE_OP_LSP_NOTIFY:
- case DPLANE_OP_SYS_ROUTE_ADD:
- case DPLANE_OP_SYS_ROUTE_DELETE:
- case DPLANE_OP_ADDR_INSTALL:
- case DPLANE_OP_ADDR_UNINSTALL:
- case DPLANE_OP_MAC_INSTALL:
- case DPLANE_OP_MAC_DELETE:
- case DPLANE_OP_NEIGH_INSTALL:
- case DPLANE_OP_NEIGH_UPDATE:
- case DPLANE_OP_NEIGH_DELETE:
- case DPLANE_OP_VTEP_ADD:
- case DPLANE_OP_VTEP_DELETE:
- case DPLANE_OP_RULE_ADD:
- case DPLANE_OP_RULE_DELETE:
- case DPLANE_OP_RULE_UPDATE:
- case DPLANE_OP_NEIGH_DISCOVER:
- case DPLANE_OP_BR_PORT_UPDATE:
- case DPLANE_OP_IPTABLE_ADD:
- case DPLANE_OP_IPTABLE_DELETE:
- case DPLANE_OP_IPSET_ADD:
- case DPLANE_OP_IPSET_DELETE:
- case DPLANE_OP_IPSET_ENTRY_ADD:
- case DPLANE_OP_IPSET_ENTRY_DELETE:
- case DPLANE_OP_NEIGH_IP_INSTALL:
- case DPLANE_OP_NEIGH_IP_DELETE:
- case DPLANE_OP_NEIGH_TABLE_UPDATE:
- case DPLANE_OP_GRE_SET:
- case DPLANE_OP_INTF_ADDR_ADD:
- case DPLANE_OP_INTF_ADDR_DEL:
- case DPLANE_OP_INTF_NETCONFIG:
- case DPLANE_OP_INTF_INSTALL:
- case DPLANE_OP_INTF_UPDATE:
- case DPLANE_OP_INTF_DELETE:
- case DPLANE_OP_TC_QDISC_INSTALL:
- case DPLANE_OP_TC_QDISC_UNINSTALL:
- case DPLANE_OP_TC_CLASS_ADD:
- case DPLANE_OP_TC_CLASS_DELETE:
- case DPLANE_OP_TC_CLASS_UPDATE:
- case DPLANE_OP_TC_FILTER_ADD:
- case DPLANE_OP_TC_FILTER_DELETE:
- case DPLANE_OP_TC_FILTER_UPDATE:
- break;
- }
return result;
}
diff --git a/zebra/zebra_mpls_vty.c b/zebra/zebra_mpls_vty.c
index 6b8859e0ca..8248d4a555 100644
--- a/zebra/zebra_mpls_vty.c
+++ b/zebra/zebra_mpls_vty.c
@@ -22,6 +22,7 @@
#include "zebra/zebra_rnh.h"
#include "zebra/redistribute.h"
#include "zebra/zebra_routemap.h"
+#include "zebra/label_manager.h"
static int zebra_mpls_transit_lsp(struct vty *vty, int add_cmd,
const char *inlabel_str, const char *gate_str,
@@ -42,10 +43,6 @@ static int zebra_mpls_transit_lsp(struct vty *vty, int add_cmd,
}
zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
- if (!zvrf) {
- vty_out(vty, "%% Default VRF does not exist\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
if (!inlabel_str) {
vty_out(vty, "%% No Label Information\n");
@@ -186,10 +183,6 @@ static int zebra_mpls_bind(struct vty *vty, int add_cmd, const char *prefix,
int ret;
zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
- if (!zvrf) {
- vty_out(vty, "%% Default VRF does not exist\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
memset(&p, 0, sizeof(p));
ret = str2prefix(prefix, &p);
@@ -217,7 +210,7 @@ static int zebra_mpls_bind(struct vty *vty, int add_cmd, const char *prefix,
vty_out(vty, "%% Invalid label\n");
return CMD_WARNING_CONFIG_FAILED;
}
- if (zebra_mpls_label_already_bound(zvrf, label)) {
+ if (zebra_mpls_label_already_bound(zvrf, &p, label)) {
vty_out(vty,
"%% Label already bound to a FEC\n");
return CMD_WARNING_CONFIG_FAILED;
@@ -274,12 +267,12 @@ static int zebra_mpls_config(struct vty *vty)
struct zebra_vrf *zvrf;
zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
- if (!zvrf)
- return 0;
write += zebra_mpls_write_lsp_config(vty, zvrf);
write += zebra_mpls_write_fec_config(vty, zvrf);
write += zebra_mpls_write_label_block_config(vty, zvrf);
+ write += lm_write_label_block_config_call(vty, zvrf);
+
return write;
}
@@ -297,8 +290,6 @@ DEFUN (show_mpls_fec,
int ret;
zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
- if (!zvrf)
- return 0;
if (argc == 3)
zebra_mpls_print_fec_table(vty, zvrf);
@@ -373,10 +364,6 @@ static int zebra_mpls_global_block(struct vty *vty, int add_cmd,
struct zebra_vrf *zvrf;
zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
- if (!zvrf) {
- vty_out(vty, "%% Default VRF does not exist\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
if (add_cmd) {
if (!start_label_str || !end_label_str) {
diff --git a/zebra/zebra_nb.c b/zebra/zebra_nb.c
index d94547cffc..eee9323082 100644
--- a/zebra/zebra_nb.c
+++ b/zebra/zebra_nb.c
@@ -10,9 +10,20 @@
#include "libfrr.h"
#include "zebra_nb.h"
+const char *features[] = {
+#if HAVE_BFDD == 0
+ "ptm-bfd",
+#endif
+#if defined(HAVE_RTADV)
+ "ipv6-router-advertisements",
+#endif
+ NULL
+};
+
/* clang-format off */
const struct frr_yang_module_info frr_zebra_info = {
.name = "frr-zebra",
+ .features = features,
.nodes = {
{
.xpath = "/frr-zebra:zebra/mcast-rpf-lookup",
@@ -79,6 +90,20 @@ const struct frr_yang_module_info frr_zebra_info = {
.modify = zebra_dplane_queue_limit_modify,
}
},
+#if HAVE_BFDD == 0
+ {
+ .xpath = "/frr-zebra:zebra/ptm-enable",
+ .cbs = {
+ .modify = zebra_ptm_enable_modify,
+ }
+ },
+#endif
+ {
+ .xpath = "/frr-zebra:zebra/route-map-delay",
+ .cbs = {
+ .modify = zebra_route_map_delay_modify,
+ }
+ },
{
.xpath = "/frr-zebra:zebra/debugs/debug-events",
.cbs = {
@@ -290,24 +315,38 @@ const struct frr_yang_module_info frr_zebra_info = {
}
},
{
- .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ip-addrs",
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv4-addrs",
.cbs = {
- .create = lib_interface_zebra_ip_addrs_create,
- .destroy = lib_interface_zebra_ip_addrs_destroy,
+ .create = lib_interface_zebra_ipv4_addrs_create,
+ .destroy = lib_interface_zebra_ipv4_addrs_destroy,
}
},
{
- .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ip-addrs/label",
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv4-addrs/label",
.cbs = {
- .modify = lib_interface_zebra_ip_addrs_label_modify,
- .destroy = lib_interface_zebra_ip_addrs_label_destroy,
+ .modify = lib_interface_zebra_ipv4_addrs_label_modify,
+ .destroy = lib_interface_zebra_ipv4_addrs_label_destroy,
}
},
{
- .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ip-addrs/ip4-peer",
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv4-p2p-addrs",
.cbs = {
- .modify = lib_interface_zebra_ip_addrs_ip4_peer_modify,
- .destroy = lib_interface_zebra_ip_addrs_ip4_peer_destroy,
+ .create = lib_interface_zebra_ipv4_p2p_addrs_create,
+ .destroy = lib_interface_zebra_ipv4_p2p_addrs_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv4-p2p-addrs/label",
+ .cbs = {
+ .modify = lib_interface_zebra_ipv4_p2p_addrs_label_modify,
+ .destroy = lib_interface_zebra_ipv4_p2p_addrs_label_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-addrs",
+ .cbs = {
+ .create = lib_interface_zebra_ipv6_addrs_create,
+ .destroy = lib_interface_zebra_ipv6_addrs_destroy,
}
},
{
@@ -321,14 +360,13 @@ const struct frr_yang_module_info frr_zebra_info = {
.xpath = "/frr-interface:lib/interface/frr-zebra:zebra/link-detect",
.cbs = {
.modify = lib_interface_zebra_link_detect_modify,
- .destroy = lib_interface_zebra_link_detect_destroy,
}
},
{
- .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/shutdown",
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/enabled",
.cbs = {
- .modify = lib_interface_zebra_shutdown_modify,
- .destroy = lib_interface_zebra_shutdown_destroy,
+ .modify = lib_interface_zebra_enabled_modify,
+ .destroy = lib_interface_zebra_enabled_destroy,
}
},
{
@@ -339,10 +377,73 @@ const struct frr_yang_module_info frr_zebra_info = {
}
},
{
- .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/bandwidth",
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/mpls",
.cbs = {
- .modify = lib_interface_zebra_bandwidth_modify,
- .destroy = lib_interface_zebra_bandwidth_destroy,
+ .modify = lib_interface_zebra_mpls_modify,
+ .destroy = lib_interface_zebra_mpls_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/link-params",
+ .cbs = {
+ .create = lib_interface_zebra_link_params_create,
+ .destroy = lib_interface_zebra_link_params_destroy,
+ .apply_finish = lib_interface_zebra_link_params_apply_finish,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/link-params/metric",
+ .cbs = {
+ .modify = lib_interface_zebra_link_params_metric_modify,
+ .destroy = lib_interface_zebra_link_params_metric_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/link-params/max-bandwidth",
+ .cbs = {
+ .modify = lib_interface_zebra_link_params_max_bandwidth_modify,
+ .destroy = lib_interface_zebra_link_params_max_bandwidth_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/link-params/max-reservable-bandwidth",
+ .cbs = {
+ .modify = lib_interface_zebra_link_params_max_reservable_bandwidth_modify,
+ .destroy = lib_interface_zebra_link_params_max_reservable_bandwidth_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/link-params/unreserved-bandwidths/unreserved-bandwidth",
+ .cbs = {
+ .create = lib_interface_zebra_link_params_unreserved_bandwidths_unreserved_bandwidth_create,
+ .destroy = lib_interface_zebra_link_params_unreserved_bandwidths_unreserved_bandwidth_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/link-params/unreserved-bandwidths/unreserved-bandwidth/unreserved-bandwidth",
+ .cbs = {
+ .modify = lib_interface_zebra_link_params_unreserved_bandwidths_unreserved_bandwidth_unreserved_bandwidth_modify,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/link-params/residual-bandwidth",
+ .cbs = {
+ .modify = lib_interface_zebra_link_params_residual_bandwidth_modify,
+ .destroy = lib_interface_zebra_link_params_residual_bandwidth_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/link-params/available-bandwidth",
+ .cbs = {
+ .modify = lib_interface_zebra_link_params_available_bandwidth_modify,
+ .destroy = lib_interface_zebra_link_params_available_bandwidth_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/link-params/utilized-bandwidth",
+ .cbs = {
+ .modify = lib_interface_zebra_link_params_utilized_bandwidth_modify,
+ .destroy = lib_interface_zebra_link_params_utilized_bandwidth_destroy,
}
},
{
@@ -350,13 +451,13 @@ const struct frr_yang_module_info frr_zebra_info = {
.cbs = {
.modify = lib_interface_zebra_legacy_admin_group_modify,
.destroy = lib_interface_zebra_legacy_admin_group_destroy,
- .cli_show = cli_show_legacy_admin_group,
},
},
{
.xpath = "/frr-interface:lib/interface/frr-zebra:zebra/link-params/affinities",
.cbs = {
- .cli_show = cli_show_affinity,
+ .create = lib_interface_zebra_affinities_create,
+ .destroy = lib_interface_zebra_affinities_destroy,
},
},
{
@@ -370,10 +471,290 @@ const struct frr_yang_module_info frr_zebra_info = {
.xpath = "/frr-interface:lib/interface/frr-zebra:zebra/link-params/affinity-mode",
.cbs = {
.modify = lib_interface_zebra_affinity_mode_modify,
- .cli_show = cli_show_affinity_mode,
},
},
{
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/link-params/neighbor",
+ .cbs = {
+ .create = lib_interface_zebra_link_params_neighbor_create,
+ .destroy = lib_interface_zebra_link_params_neighbor_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/link-params/neighbor/remote-as",
+ .cbs = {
+ .modify = lib_interface_zebra_link_params_neighbor_remote_as_modify,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/link-params/neighbor/ipv4-remote-id",
+ .cbs = {
+ .modify = lib_interface_zebra_link_params_neighbor_ipv4_remote_id_modify,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/link-params/delay",
+ .cbs = {
+ .modify = lib_interface_zebra_link_params_delay_modify,
+ .destroy = lib_interface_zebra_link_params_delay_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/link-params/min-max-delay",
+ .cbs = {
+ .create = lib_interface_zebra_link_params_min_max_delay_create,
+ .destroy = lib_interface_zebra_link_params_min_max_delay_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/link-params/min-max-delay/delay-min",
+ .cbs = {
+ .modify = lib_interface_zebra_link_params_min_max_delay_delay_min_modify,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/link-params/min-max-delay/delay-max",
+ .cbs = {
+ .modify = lib_interface_zebra_link_params_min_max_delay_delay_max_modify,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/link-params/delay-variation",
+ .cbs = {
+ .modify = lib_interface_zebra_link_params_delay_variation_modify,
+ .destroy = lib_interface_zebra_link_params_delay_variation_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/link-params/packet-loss",
+ .cbs = {
+ .modify = lib_interface_zebra_link_params_packet_loss_modify,
+ .destroy = lib_interface_zebra_link_params_packet_loss_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/evpn-mh/type-0",
+ .cbs = {
+ .create = lib_interface_zebra_evpn_mh_type_0_create,
+ .destroy = lib_interface_zebra_evpn_mh_type_0_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/evpn-mh/type-0/esi",
+ .cbs = {
+ .modify = lib_interface_zebra_evpn_mh_type_0_esi_modify,
+ .destroy = lib_interface_zebra_evpn_mh_type_0_esi_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/evpn-mh/type-3",
+ .cbs = {
+ .create = lib_interface_zebra_evpn_mh_type_3_create,
+ .destroy = lib_interface_zebra_evpn_mh_type_3_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/evpn-mh/type-3/system-mac",
+ .cbs = {
+ .modify = lib_interface_zebra_evpn_mh_type_3_system_mac_modify,
+ .destroy = lib_interface_zebra_evpn_mh_type_3_system_mac_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/evpn-mh/type-3/local-discriminator",
+ .cbs = {
+ .modify = lib_interface_zebra_evpn_mh_type_3_local_discriminator_modify,
+ .destroy = lib_interface_zebra_evpn_mh_type_3_local_discriminator_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/evpn-mh/df-preference",
+ .cbs = {
+ .modify = lib_interface_zebra_evpn_mh_df_preference_modify,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/evpn-mh/bypass",
+ .cbs = {
+ .modify = lib_interface_zebra_evpn_mh_bypass_modify,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/evpn-mh/uplink",
+ .cbs = {
+ .modify = lib_interface_zebra_evpn_mh_uplink_modify,
+ }
+ },
+#if defined(HAVE_RTADV)
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/send-advertisements",
+ .cbs = {
+ .modify = lib_interface_zebra_ipv6_router_advertisements_send_advertisements_modify,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/max-rtr-adv-interval",
+ .cbs = {
+ .modify = lib_interface_zebra_ipv6_router_advertisements_max_rtr_adv_interval_modify,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/managed-flag",
+ .cbs = {
+ .modify = lib_interface_zebra_ipv6_router_advertisements_managed_flag_modify,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/other-config-flag",
+ .cbs = {
+ .modify = lib_interface_zebra_ipv6_router_advertisements_other_config_flag_modify,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/home-agent-flag",
+ .cbs = {
+ .modify = lib_interface_zebra_ipv6_router_advertisements_home_agent_flag_modify,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/link-mtu",
+ .cbs = {
+ .modify = lib_interface_zebra_ipv6_router_advertisements_link_mtu_modify,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/reachable-time",
+ .cbs = {
+ .modify = lib_interface_zebra_ipv6_router_advertisements_reachable_time_modify,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/retrans-timer",
+ .cbs = {
+ .modify = lib_interface_zebra_ipv6_router_advertisements_retrans_timer_modify,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/cur-hop-limit",
+ .cbs = {
+ .modify = lib_interface_zebra_ipv6_router_advertisements_cur_hop_limit_modify,
+ .destroy = lib_interface_zebra_ipv6_router_advertisements_cur_hop_limit_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/default-lifetime",
+ .cbs = {
+ .modify = lib_interface_zebra_ipv6_router_advertisements_default_lifetime_modify,
+ .destroy = lib_interface_zebra_ipv6_router_advertisements_default_lifetime_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/fast-retransmit",
+ .cbs = {
+ .modify = lib_interface_zebra_ipv6_router_advertisements_fast_retransmit_modify,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/advertisement-interval-option",
+ .cbs = {
+ .modify = lib_interface_zebra_ipv6_router_advertisements_advertisement_interval_option_modify,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/home-agent-preference",
+ .cbs = {
+ .modify = lib_interface_zebra_ipv6_router_advertisements_home_agent_preference_modify,
+ .destroy = lib_interface_zebra_ipv6_router_advertisements_home_agent_preference_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/home-agent-lifetime",
+ .cbs = {
+ .modify = lib_interface_zebra_ipv6_router_advertisements_home_agent_lifetime_modify,
+ .destroy = lib_interface_zebra_ipv6_router_advertisements_home_agent_lifetime_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/default-router-preference",
+ .cbs = {
+ .modify = lib_interface_zebra_ipv6_router_advertisements_default_router_preference_modify,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/prefix-list/prefix",
+ .cbs = {
+ .create = lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_create,
+ .destroy = lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/dnssl/dnssl-domain",
+ .cbs = {
+ .create = lib_interface_zebra_ipv6_router_advertisements_dnssl_dnssl_domain_create,
+ .destroy = lib_interface_zebra_ipv6_router_advertisements_dnssl_dnssl_domain_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/dnssl/dnssl-domain/lifetime",
+ .cbs = {
+ .modify = lib_interface_zebra_ipv6_router_advertisements_dnssl_dnssl_domain_lifetime_modify,
+ .destroy = lib_interface_zebra_ipv6_router_advertisements_dnssl_dnssl_domain_lifetime_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/prefix-list/prefix/valid-lifetime",
+ .cbs = {
+ .modify = lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_valid_lifetime_modify,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/prefix-list/prefix/on-link-flag",
+ .cbs = {
+ .modify = lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_on_link_flag_modify,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/prefix-list/prefix/preferred-lifetime",
+ .cbs = {
+ .modify = lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_preferred_lifetime_modify,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/prefix-list/prefix/autonomous-flag",
+ .cbs = {
+ .modify = lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_autonomous_flag_modify,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/prefix-list/prefix/router-address-flag",
+ .cbs = {
+ .modify = lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_router_address_flag_modify,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/rdnss/rdnss-address",
+ .cbs = {
+ .create = lib_interface_zebra_ipv6_router_advertisements_rdnss_rdnss_address_create,
+ .destroy = lib_interface_zebra_ipv6_router_advertisements_rdnss_rdnss_address_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/rdnss/rdnss-address/lifetime",
+ .cbs = {
+ .modify = lib_interface_zebra_ipv6_router_advertisements_rdnss_rdnss_address_lifetime_modify,
+ .destroy = lib_interface_zebra_ipv6_router_advertisements_rdnss_rdnss_address_lifetime_destroy,
+ }
+ },
+#endif /* defined(HAVE_RTADV) */
+#if HAVE_BFDD == 0
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ptm-enable",
+ .cbs = {
+ .modify = lib_interface_zebra_ptm_enable_modify,
+ }
+ },
+#endif
+ {
.xpath = "/frr-interface:lib/interface/frr-zebra:zebra/state/up-count",
.cbs = {
.get_elem = lib_interface_zebra_state_up_count_get_elem,
@@ -422,11 +803,93 @@ const struct frr_yang_module_info frr_zebra_info = {
}
},
{
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/state/bond",
+ .cbs = {
+ .get_elem = lib_interface_zebra_state_bond_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-vrf:lib/vrf/frr-zebra:zebra/router-id",
+ .cbs = {
+ .modify = lib_vrf_zebra_router_id_modify,
+ .destroy = lib_vrf_zebra_router_id_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-vrf:lib/vrf/frr-zebra:zebra/ipv6-router-id",
+ .cbs = {
+ .modify = lib_vrf_zebra_ipv6_router_id_modify,
+ .destroy = lib_vrf_zebra_ipv6_router_id_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-vrf:lib/vrf/frr-zebra:zebra/filter-protocol",
+ .cbs = {
+ .create = lib_vrf_zebra_filter_protocol_create,
+ .destroy = lib_vrf_zebra_filter_protocol_destroy,
+ .apply_finish = lib_vrf_zebra_filter_protocol_apply_finish,
+ }
+ },
+ {
+ .xpath = "/frr-vrf:lib/vrf/frr-zebra:zebra/filter-protocol/route-map",
+ .cbs = {
+ .modify = lib_vrf_zebra_filter_protocol_route_map_modify,
+ }
+ },
+ {
+ .xpath = "/frr-vrf:lib/vrf/frr-zebra:zebra/filter-nht",
+ .cbs = {
+ .create = lib_vrf_zebra_filter_nht_create,
+ .destroy = lib_vrf_zebra_filter_nht_destroy,
+ .apply_finish = lib_vrf_zebra_filter_nht_apply_finish,
+ }
+ },
+ {
+ .xpath = "/frr-vrf:lib/vrf/frr-zebra:zebra/filter-nht/route-map",
+ .cbs = {
+ .modify = lib_vrf_zebra_filter_nht_route_map_modify,
+ }
+ },
+ {
+ .xpath = "/frr-vrf:lib/vrf/frr-zebra:zebra/resolve-via-default",
+ .cbs = {
+ .modify = lib_vrf_zebra_resolve_via_default_modify,
+ .destroy = lib_vrf_zebra_resolve_via_default_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-vrf:lib/vrf/frr-zebra:zebra/ipv6-resolve-via-default",
+ .cbs = {
+ .modify = lib_vrf_zebra_ipv6_resolve_via_default_modify,
+ .destroy = lib_vrf_zebra_ipv6_resolve_via_default_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-vrf:lib/vrf/frr-zebra:zebra/netns/table-range",
+ .cbs = {
+ .create = lib_vrf_zebra_netns_table_range_create,
+ .destroy = lib_vrf_zebra_netns_table_range_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-vrf:lib/vrf/frr-zebra:zebra/netns/table-range/start",
+ .cbs = {
+ .modify = lib_vrf_zebra_netns_table_range_start_modify,
+ }
+ },
+ {
+ .xpath = "/frr-vrf:lib/vrf/frr-zebra:zebra/netns/table-range/end",
+ .cbs = {
+ .modify = lib_vrf_zebra_netns_table_range_end_modify,
+ }
+ },
+ {
.xpath = "/frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib",
.cbs = {
.get_next = lib_vrf_zebra_ribs_rib_get_next,
.get_keys = lib_vrf_zebra_ribs_rib_get_keys,
.lookup_entry = lib_vrf_zebra_ribs_rib_lookup_entry,
+ .lookup_next = lib_vrf_zebra_ribs_rib_lookup_next,
}
},
{
@@ -447,6 +910,7 @@ const struct frr_yang_module_info frr_zebra_info = {
.get_next = lib_vrf_zebra_ribs_rib_route_get_next,
.get_keys = lib_vrf_zebra_ribs_rib_route_get_keys,
.lookup_entry = lib_vrf_zebra_ribs_rib_route_lookup_entry,
+ .lookup_next = lib_vrf_zebra_ribs_rib_route_lookup_next,
}
},
{
@@ -591,6 +1055,28 @@ const struct frr_yang_module_info frr_zebra_info = {
.get_elem = lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_color_get_elem,
}
},
+
+ {
+ .xpath = "/frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route/route-entry/nexthop-group/nexthop/srv6-segs-stack/entry",
+ .cbs = {
+ .get_next = lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_srv6_segs_stack_entry_get_next,
+ .get_keys = lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_srv6_segs_stack_entry_get_keys,
+ .lookup_entry = lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_srv6_segs_stack_entry_lookup_entry,
+ }
+ },
+ {
+ .xpath = "/frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route/route-entry/nexthop-group/nexthop/srv6-segs-stack/entry/id",
+ .cbs = {
+ .get_elem = lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_srv6_segs_stack_entry_id_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route/route-entry/nexthop-group/nexthop/srv6-segs-stack/entry/seg",
+ .cbs = {
+ .get_elem = lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_srv6_segs_stack_entry_seg_get_elem,
+ }
+ },
+
{
.xpath = "/frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route/route-entry/nexthop-group/nexthop/mpls-label-stack/entry",
.cbs = {
diff --git a/zebra/zebra_nb.h b/zebra/zebra_nb.h
index fa576ec3f4..b40ed68229 100644
--- a/zebra/zebra_nb.h
+++ b/zebra/zebra_nb.h
@@ -44,6 +44,10 @@ int zebra_import_kernel_table_route_map_destroy(
int zebra_allow_external_route_update_create(struct nb_cb_create_args *args);
int zebra_allow_external_route_update_destroy(struct nb_cb_destroy_args *args);
int zebra_dplane_queue_limit_modify(struct nb_cb_modify_args *args);
+#if HAVE_BFDD == 0
+int zebra_ptm_enable_modify(struct nb_cb_modify_args *args);
+#endif
+int zebra_route_map_delay_modify(struct nb_cb_modify_args *args);
int zebra_debugs_debug_events_modify(struct nb_cb_modify_args *args);
int zebra_debugs_debug_events_destroy(struct nb_cb_destroy_args *args);
int zebra_debugs_debug_zapi_send_modify(struct nb_cb_modify_args *args);
@@ -80,29 +84,191 @@ int zebra_debugs_debug_dplane_detail_modify(struct nb_cb_modify_args *args);
int zebra_debugs_debug_dplane_detail_destroy(struct nb_cb_destroy_args *args);
int zebra_debugs_debug_mlag_modify(struct nb_cb_modify_args *args);
int zebra_debugs_debug_mlag_destroy(struct nb_cb_destroy_args *args);
-int lib_interface_zebra_ip_addrs_create(struct nb_cb_create_args *args);
-int lib_interface_zebra_ip_addrs_destroy(struct nb_cb_destroy_args *args);
-int lib_interface_zebra_ip_addrs_label_modify(struct nb_cb_modify_args *args);
-int lib_interface_zebra_ip_addrs_label_destroy(struct nb_cb_destroy_args *args);
-int lib_interface_zebra_ip_addrs_ip4_peer_modify(
+int lib_interface_zebra_ipv4_addrs_create(struct nb_cb_create_args *args);
+int lib_interface_zebra_ipv4_addrs_destroy(struct nb_cb_destroy_args *args);
+int lib_interface_zebra_ipv4_addrs_label_modify(struct nb_cb_modify_args *args);
+int lib_interface_zebra_ipv4_addrs_label_destroy(struct nb_cb_destroy_args *args);
+int lib_interface_zebra_ipv4_p2p_addrs_create(struct nb_cb_create_args *args);
+int lib_interface_zebra_ipv4_p2p_addrs_destroy(struct nb_cb_destroy_args *args);
+int lib_interface_zebra_ipv4_p2p_addrs_label_modify(
struct nb_cb_modify_args *args);
-int lib_interface_zebra_ip_addrs_ip4_peer_destroy(
+int lib_interface_zebra_ipv4_p2p_addrs_label_destroy(
struct nb_cb_destroy_args *args);
+int lib_interface_zebra_ipv6_addrs_create(struct nb_cb_create_args *args);
+int lib_interface_zebra_ipv6_addrs_destroy(struct nb_cb_destroy_args *args);
int lib_interface_zebra_multicast_modify(struct nb_cb_modify_args *args);
int lib_interface_zebra_multicast_destroy(struct nb_cb_destroy_args *args);
int lib_interface_zebra_link_detect_modify(struct nb_cb_modify_args *args);
-int lib_interface_zebra_link_detect_destroy(struct nb_cb_destroy_args *args);
-int lib_interface_zebra_shutdown_modify(struct nb_cb_modify_args *args);
-int lib_interface_zebra_shutdown_destroy(struct nb_cb_destroy_args *args);
+int lib_interface_zebra_enabled_modify(struct nb_cb_modify_args *args);
+int lib_interface_zebra_enabled_destroy(struct nb_cb_destroy_args *args);
int lib_interface_zebra_bandwidth_modify(struct nb_cb_modify_args *args);
int lib_interface_zebra_bandwidth_destroy(struct nb_cb_destroy_args *args);
-int lib_interface_zebra_legacy_admin_group_modify(
+int lib_interface_zebra_mpls_modify(struct nb_cb_modify_args *args);
+int lib_interface_zebra_mpls_destroy(struct nb_cb_destroy_args *args);
+int lib_interface_zebra_link_params_create(struct nb_cb_create_args *args);
+int lib_interface_zebra_link_params_destroy(struct nb_cb_destroy_args *args);
+void lib_interface_zebra_link_params_apply_finish(
+ struct nb_cb_apply_finish_args *args);
+int lib_interface_zebra_link_params_metric_modify(struct nb_cb_modify_args *args);
+int lib_interface_zebra_link_params_metric_destroy(
+ struct nb_cb_destroy_args *args);
+int lib_interface_zebra_link_params_max_bandwidth_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_zebra_link_params_max_bandwidth_destroy(
+ struct nb_cb_destroy_args *args);
+int lib_interface_zebra_link_params_max_reservable_bandwidth_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_zebra_link_params_max_reservable_bandwidth_destroy(
+ struct nb_cb_destroy_args *args);
+int lib_interface_zebra_link_params_unreserved_bandwidths_unreserved_bandwidth_create(
+ struct nb_cb_create_args *args);
+void lib_interface_zebra_link_params_unreserved_bandwidths_unreserved_bandwidth_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults);
+int lib_interface_zebra_link_params_unreserved_bandwidths_unreserved_bandwidth_destroy(
+ struct nb_cb_destroy_args *args);
+int lib_interface_zebra_link_params_unreserved_bandwidths_unreserved_bandwidth_unreserved_bandwidth_modify(
+ struct nb_cb_modify_args *args);
+void lib_interface_zebra_link_params_unreserved_bandwidths_unreserved_bandwidth_unreserved_bandwidth_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults);
+int lib_interface_zebra_link_params_residual_bandwidth_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_zebra_link_params_residual_bandwidth_destroy(
+ struct nb_cb_destroy_args *args);
+int lib_interface_zebra_link_params_available_bandwidth_modify(
struct nb_cb_modify_args *args);
+int lib_interface_zebra_link_params_available_bandwidth_destroy(
+ struct nb_cb_destroy_args *args);
+int lib_interface_zebra_link_params_utilized_bandwidth_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_zebra_link_params_utilized_bandwidth_destroy(
+ struct nb_cb_destroy_args *args);
+int lib_interface_zebra_legacy_admin_group_modify(struct nb_cb_modify_args *args);
int lib_interface_zebra_legacy_admin_group_destroy(
struct nb_cb_destroy_args *args);
+int lib_interface_zebra_affinities_create(struct nb_cb_create_args *args);
+int lib_interface_zebra_affinities_destroy(struct nb_cb_destroy_args *args);
int lib_interface_zebra_affinity_create(struct nb_cb_create_args *args);
int lib_interface_zebra_affinity_destroy(struct nb_cb_destroy_args *args);
int lib_interface_zebra_affinity_mode_modify(struct nb_cb_modify_args *args);
+int lib_interface_zebra_link_params_neighbor_create(
+ struct nb_cb_create_args *args);
+int lib_interface_zebra_link_params_neighbor_destroy(
+ struct nb_cb_destroy_args *args);
+int lib_interface_zebra_link_params_neighbor_remote_as_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_zebra_link_params_neighbor_ipv4_remote_id_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_zebra_link_params_delay_modify(struct nb_cb_modify_args *args);
+int lib_interface_zebra_link_params_delay_destroy(
+ struct nb_cb_destroy_args *args);
+int lib_interface_zebra_link_params_min_max_delay_create(
+ struct nb_cb_create_args *args);
+int lib_interface_zebra_link_params_min_max_delay_destroy(
+ struct nb_cb_destroy_args *args);
+int lib_interface_zebra_link_params_min_max_delay_delay_min_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_zebra_link_params_min_max_delay_delay_max_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_zebra_link_params_delay_variation_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_zebra_link_params_delay_variation_destroy(
+ struct nb_cb_destroy_args *args);
+int lib_interface_zebra_link_params_packet_loss_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_zebra_link_params_packet_loss_destroy(
+ struct nb_cb_destroy_args *args);
+int lib_interface_zebra_evpn_mh_type_0_create(struct nb_cb_create_args *args);
+int lib_interface_zebra_evpn_mh_type_0_destroy(struct nb_cb_destroy_args *args);
+int lib_interface_zebra_evpn_mh_type_0_esi_modify(struct nb_cb_modify_args *args);
+int lib_interface_zebra_evpn_mh_type_0_esi_destroy(
+ struct nb_cb_destroy_args *args);
+int lib_interface_zebra_evpn_mh_type_3_create(struct nb_cb_create_args *args);
+int lib_interface_zebra_evpn_mh_type_3_destroy(struct nb_cb_destroy_args *args);
+int lib_interface_zebra_evpn_mh_type_3_system_mac_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_zebra_evpn_mh_type_3_system_mac_destroy(
+ struct nb_cb_destroy_args *args);
+int lib_interface_zebra_evpn_mh_type_3_local_discriminator_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_zebra_evpn_mh_type_3_local_discriminator_destroy(
+ struct nb_cb_destroy_args *args);
+int lib_interface_zebra_evpn_mh_df_preference_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_zebra_evpn_mh_bypass_modify(struct nb_cb_modify_args *args);
+int lib_interface_zebra_evpn_mh_uplink_modify(struct nb_cb_modify_args *args);
+#if defined(HAVE_RTADV)
+int lib_interface_zebra_ipv6_router_advertisements_send_advertisements_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_max_rtr_adv_interval_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_managed_flag_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_other_config_flag_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_home_agent_flag_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_link_mtu_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_reachable_time_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_retrans_timer_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_cur_hop_limit_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_cur_hop_limit_destroy(
+ struct nb_cb_destroy_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_default_lifetime_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_default_lifetime_destroy(
+ struct nb_cb_destroy_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_fast_retransmit_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_advertisement_interval_option_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_home_agent_preference_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_home_agent_preference_destroy(
+ struct nb_cb_destroy_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_home_agent_lifetime_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_home_agent_lifetime_destroy(
+ struct nb_cb_destroy_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_default_router_preference_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_create(
+ struct nb_cb_create_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_destroy(
+ struct nb_cb_destroy_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_valid_lifetime_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_on_link_flag_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_preferred_lifetime_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_autonomous_flag_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_router_address_flag_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_rdnss_rdnss_address_create(
+ struct nb_cb_create_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_rdnss_rdnss_address_destroy(
+ struct nb_cb_destroy_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_rdnss_rdnss_address_lifetime_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_rdnss_rdnss_address_lifetime_destroy(
+ struct nb_cb_destroy_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_dnssl_dnssl_domain_create(
+ struct nb_cb_create_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_dnssl_dnssl_domain_destroy(
+ struct nb_cb_destroy_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_dnssl_dnssl_domain_lifetime_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_zebra_ipv6_router_advertisements_dnssl_dnssl_domain_lifetime_destroy(
+ struct nb_cb_destroy_args *args);
+#endif /* defined(HAVE_RTADV) */
+#if HAVE_BFDD == 0
+int lib_interface_zebra_ptm_enable_modify(struct nb_cb_modify_args *args);
+#endif
struct yang_data *
lib_interface_zebra_state_up_count_get_elem(struct nb_cb_get_elem_args *args);
struct yang_data *
@@ -119,10 +285,36 @@ struct yang_data *lib_interface_zebra_state_remote_vtep_get_elem(
struct nb_cb_get_elem_args *args);
struct yang_data *lib_interface_zebra_state_mcast_group_get_elem(
struct nb_cb_get_elem_args *args);
+struct yang_data *lib_interface_zebra_state_bond_get_elem(struct nb_cb_get_elem_args *args);
+int lib_vrf_zebra_router_id_modify(struct nb_cb_modify_args *args);
+int lib_vrf_zebra_router_id_destroy(struct nb_cb_destroy_args *args);
+int lib_vrf_zebra_ipv6_router_id_modify(struct nb_cb_modify_args *args);
+int lib_vrf_zebra_ipv6_router_id_destroy(struct nb_cb_destroy_args *args);
+int lib_vrf_zebra_filter_protocol_create(struct nb_cb_create_args *args);
+int lib_vrf_zebra_filter_protocol_destroy(struct nb_cb_destroy_args *args);
+void lib_vrf_zebra_filter_protocol_apply_finish(
+ struct nb_cb_apply_finish_args *args);
+int lib_vrf_zebra_filter_protocol_route_map_modify(
+ struct nb_cb_modify_args *args);
+int lib_vrf_zebra_filter_nht_create(struct nb_cb_create_args *args);
+int lib_vrf_zebra_filter_nht_destroy(struct nb_cb_destroy_args *args);
+void lib_vrf_zebra_filter_nht_apply_finish(struct nb_cb_apply_finish_args *args);
+int lib_vrf_zebra_filter_nht_route_map_modify(struct nb_cb_modify_args *args);
+int lib_vrf_zebra_resolve_via_default_modify(struct nb_cb_modify_args *args);
+int lib_vrf_zebra_resolve_via_default_destroy(struct nb_cb_destroy_args *args);
+int lib_vrf_zebra_ipv6_resolve_via_default_modify(struct nb_cb_modify_args *args);
+int lib_vrf_zebra_ipv6_resolve_via_default_destroy(
+ struct nb_cb_destroy_args *args);
+int lib_vrf_zebra_netns_table_range_create(struct nb_cb_create_args *args);
+int lib_vrf_zebra_netns_table_range_destroy(struct nb_cb_destroy_args *args);
+int lib_vrf_zebra_netns_table_range_start_modify(struct nb_cb_modify_args *args);
+int lib_vrf_zebra_netns_table_range_end_modify(struct nb_cb_modify_args *args);
const void *lib_vrf_zebra_ribs_rib_get_next(struct nb_cb_get_next_args *args);
int lib_vrf_zebra_ribs_rib_get_keys(struct nb_cb_get_keys_args *args);
const void *
lib_vrf_zebra_ribs_rib_lookup_entry(struct nb_cb_lookup_entry_args *args);
+const void *
+lib_vrf_zebra_ribs_rib_lookup_next(struct nb_cb_lookup_entry_args *args);
struct yang_data *
lib_vrf_zebra_ribs_rib_afi_safi_name_get_elem(struct nb_cb_get_elem_args *args);
struct yang_data *
@@ -132,6 +324,8 @@ lib_vrf_zebra_ribs_rib_route_get_next(struct nb_cb_get_next_args *args);
int lib_vrf_zebra_ribs_rib_route_get_keys(struct nb_cb_get_keys_args *args);
const void *
lib_vrf_zebra_ribs_rib_route_lookup_entry(struct nb_cb_lookup_entry_args *args);
+const void *
+lib_vrf_zebra_ribs_rib_route_lookup_next(struct nb_cb_lookup_entry_args *args);
struct yang_data *
lib_vrf_zebra_ribs_rib_route_prefix_get_elem(struct nb_cb_get_elem_args *args);
struct yang_data *lib_vrf_zebra_ribs_rib_route_protocol_get_elem(
@@ -238,6 +432,20 @@ struct yang_data *
lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_color_get_elem(
struct nb_cb_get_elem_args *args);
const void *
+lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_srv6_segs_stack_entry_get_next(
+ struct nb_cb_get_next_args *args);
+int lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_srv6_segs_stack_entry_get_keys(
+ struct nb_cb_get_keys_args *args);
+const void *
+lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_srv6_segs_stack_entry_lookup_entry(
+ struct nb_cb_lookup_entry_args *args);
+struct yang_data *
+lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_srv6_segs_stack_entry_id_get_elem(
+ struct nb_cb_get_elem_args *args);
+struct yang_data *
+lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_srv6_segs_stack_entry_seg_get_elem(
+ struct nb_cb_get_elem_args *args);
+const void *
lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_mpls_label_stack_entry_get_next(
struct nb_cb_get_next_args *args);
int lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_mpls_label_stack_entry_get_keys(
diff --git a/zebra/zebra_nb_config.c b/zebra/zebra_nb_config.c
index 336669a49b..04eac63d3e 100644
--- a/zebra/zebra_nb_config.c
+++ b/zebra/zebra_nb_config.c
@@ -23,6 +23,12 @@
#include "zebra/debug.h"
#include "zebra/zebra_vxlan_private.h"
#include "zebra/zebra_vxlan.h"
+#include "zebra/zebra_evpn_mh.h"
+#include "zebra/zebra_ptm.h"
+#include "zebra/router-id.h"
+#include "zebra/zebra_routemap.h"
+#include "zebra/zebra_rnh.h"
+#include "zebra/table_manager.h"
/*
* XPath: /frr-zebra:zebra/mcast-rpf-lookup
@@ -264,6 +270,43 @@ int zebra_dplane_queue_limit_modify(struct nb_cb_modify_args *args)
return NB_OK;
}
+#if HAVE_BFDD == 0
+/*
+ * XPath: /frr-zebra:zebra/ptm-enable
+ */
+int zebra_ptm_enable_modify(struct nb_cb_modify_args *args)
+{
+ bool ptm;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ptm = yang_dnode_get_bool(args->dnode, NULL);
+
+ if (ptm)
+ zebra_global_ptm_enable();
+ else
+ zebra_global_ptm_disable();
+
+ return NB_OK;
+}
+#endif
+
+/*
+ * XPath: /frr-zebra:zebra/route-map-delay
+ */
+int zebra_route_map_delay_modify(struct nb_cb_modify_args *args)
+{
+ uint32_t delay = yang_dnode_get_uint32(args->dnode, NULL);
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ zebra_route_map_set_delay_timer(delay);
+
+ return NB_OK;
+}
+
/*
* XPath: /frr-zebra:zebra/debugs/debug-events
*/
@@ -823,28 +866,26 @@ int zebra_debugs_debug_mlag_destroy(struct nb_cb_destroy_args *args)
}
/*
- * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ip-addrs
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv4-addrs
*/
-int lib_interface_zebra_ip_addrs_create(struct nb_cb_create_args *args)
+int lib_interface_zebra_ipv4_addrs_create(struct nb_cb_create_args *args)
{
struct interface *ifp;
- struct prefix prefix;
+ struct prefix p;
+ const char *label = NULL;
+
+ p.family = AF_INET;
+ yang_dnode_get_ipv4(&p.u.prefix4, args->dnode, "ip");
+ p.prefixlen = yang_dnode_get_uint8(args->dnode, "prefix-length");
- // addr_family = yang_dnode_get_enum(dnode, "./address-family");
- yang_dnode_get_prefix(&prefix, args->dnode, "./ip-prefix");
- apply_mask(&prefix);
+ if (yang_dnode_exists(args->dnode, "label"))
+ label = yang_dnode_get_string(args->dnode, "label");
switch (args->event) {
case NB_EV_VALIDATE:
- if (prefix.family == AF_INET
- && ipv4_martian(&prefix.u.prefix4)) {
+ if (ipv4_martian(&p.u.prefix4)) {
snprintfrr(args->errmsg, args->errmsg_len,
- "invalid address %pFX", &prefix);
- return NB_ERR_VALIDATION;
- } else if (prefix.family == AF_INET6
- && ipv6_martian(&prefix.u.prefix6)) {
- snprintfrr(args->errmsg, args->errmsg_len,
- "invalid address %pFX", &prefix);
+ "invalid address %pFX", &p);
return NB_ERR_VALIDATION;
}
break;
@@ -853,65 +894,105 @@ int lib_interface_zebra_ip_addrs_create(struct nb_cb_create_args *args)
break;
case NB_EV_APPLY:
ifp = nb_running_get_entry(args->dnode, NULL, true);
- if (prefix.family == AF_INET)
- if_ip_address_install(ifp, &prefix, NULL, NULL);
- else if (prefix.family == AF_INET6)
- if_ipv6_address_install(ifp, &prefix, NULL);
+ if_ip_address_install(ifp, &p, label, NULL);
+ /* set something for checking on label modify */
+ nb_running_set_entry(args->dnode, (void *)0x1);
break;
}
return NB_OK;
}
-int lib_interface_zebra_ip_addrs_destroy(struct nb_cb_destroy_args *args)
+int lib_interface_zebra_ipv4_addrs_destroy(struct nb_cb_destroy_args *args)
{
struct interface *ifp;
- struct prefix prefix;
- struct connected *ifc;
+ struct prefix p;
- yang_dnode_get_prefix(&prefix, args->dnode, "./ip-prefix");
- apply_mask(&prefix);
+ p.family = AF_INET;
+ yang_dnode_get_ipv4(&p.u.prefix4, args->dnode, "ip");
+ p.prefixlen = yang_dnode_get_uint8(args->dnode, "prefix-length");
switch (args->event) {
case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ nb_running_unset_entry(args->dnode);
+
ifp = nb_running_get_entry(args->dnode, NULL, false);
- if (!ifp)
- return NB_OK;
-
- if (prefix.family == AF_INET) {
- /* Check current interface address. */
- ifc = connected_check_ptp(ifp, &prefix, NULL);
- if (!ifc) {
- snprintf(args->errmsg, args->errmsg_len,
- "interface %s Can't find address\n",
- ifp->name);
- return NB_ERR_VALIDATION;
- }
- } else if (prefix.family == AF_INET6) {
- /* Check current interface address. */
- ifc = connected_check(ifp, &prefix);
- if (!ifc) {
- snprintf(args->errmsg, args->errmsg_len,
- "interface can't find address %s",
- ifp->name);
- return NB_ERR_VALIDATION;
- }
- } else
- return NB_ERR_VALIDATION;
+ if_ip_address_uninstall(ifp, &p, NULL);
+ break;
+ }
+
+ return NB_OK;
+}
- /* This is not configured address. */
- if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED)) {
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv4-addrs/label
+ */
+int lib_interface_zebra_ipv4_addrs_label_modify(struct nb_cb_modify_args *args)
+{
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ if (nb_running_get_entry_non_rec(lyd_parent(args->dnode), NULL,
+ false)) {
snprintf(args->errmsg, args->errmsg_len,
- "interface %s not configured", ifp->name);
+ "Changing label is not allowed");
return NB_ERR_VALIDATION;
}
+ break;
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ case NB_EV_APPLY:
+ break;
+ }
+
+ return NB_OK;
+}
+
+int lib_interface_zebra_ipv4_addrs_label_destroy(struct nb_cb_destroy_args *args)
+{
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ snprintf(args->errmsg, args->errmsg_len,
+ "Removing label is not allowed");
+ return NB_ERR_VALIDATION;
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ case NB_EV_APPLY:
+ break;
+ }
- /* This is not real address or interface is not active. */
- if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)
- || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
- listnode_delete(ifp->connected, ifc);
- connected_free(&ifc);
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv4-p2p-addrs
+ */
+int lib_interface_zebra_ipv4_p2p_addrs_create(struct nb_cb_create_args *args)
+{
+ struct interface *ifp;
+ struct prefix p, pp;
+ const char *label = NULL;
+
+ p.family = AF_INET;
+ yang_dnode_get_ipv4(&p.u.prefix4, args->dnode, "ip");
+ p.prefixlen = 32;
+
+ pp.family = AF_INET;
+ yang_dnode_get_ipv4(&pp.u.prefix4, args->dnode, "peer-ip");
+ pp.prefixlen = yang_dnode_get_uint8(args->dnode, "peer-prefix-length");
+
+ if (yang_dnode_exists(args->dnode, "label"))
+ label = yang_dnode_get_string(args->dnode, "label");
+
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ if (ipv4_martian(&p.u.prefix4)) {
+ snprintfrr(args->errmsg, args->errmsg_len,
+ "invalid address %pFX", &p);
return NB_ERR_VALIDATION;
}
break;
@@ -920,7 +1001,39 @@ int lib_interface_zebra_ip_addrs_destroy(struct nb_cb_destroy_args *args)
break;
case NB_EV_APPLY:
ifp = nb_running_get_entry(args->dnode, NULL, true);
- if_ip_address_uinstall(ifp, &prefix);
+ if_ip_address_install(ifp, &p, label, &pp);
+
+ /* set something for checking on label modify */
+ nb_running_set_entry(args->dnode, (void *)0x1);
+ break;
+ }
+
+ return NB_OK;
+}
+
+int lib_interface_zebra_ipv4_p2p_addrs_destroy(struct nb_cb_destroy_args *args)
+{
+ struct interface *ifp;
+ struct prefix p, pp;
+
+ p.family = AF_INET;
+ yang_dnode_get_ipv4(&p.u.prefix4, args->dnode, "ip");
+ p.prefixlen = 32;
+
+ pp.family = AF_INET;
+ yang_dnode_get_ipv4(&pp.u.prefix4, args->dnode, "peer-ip");
+ pp.prefixlen = yang_dnode_get_uint8(args->dnode, "peer-prefix-length");
+
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ nb_running_unset_entry(args->dnode);
+
+ ifp = nb_running_get_entry(args->dnode, NULL, false);
+ if_ip_address_uninstall(ifp, &p, &pp);
break;
}
@@ -928,30 +1041,39 @@ int lib_interface_zebra_ip_addrs_destroy(struct nb_cb_destroy_args *args)
}
/*
- * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ip-addrs/label
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv4-p2p-addrs/label
*/
-int lib_interface_zebra_ip_addrs_label_modify(struct nb_cb_modify_args *args)
+int lib_interface_zebra_ipv4_p2p_addrs_label_modify(struct nb_cb_modify_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
+ if (nb_running_get_entry_non_rec(lyd_parent(args->dnode), NULL,
+ false)) {
+ snprintf(args->errmsg, args->errmsg_len,
+ "Changing label is not allowed");
+ return NB_ERR_VALIDATION;
+ }
+ break;
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
- /* TODO: implement me. */
break;
}
return NB_OK;
}
-int lib_interface_zebra_ip_addrs_label_destroy(struct nb_cb_destroy_args *args)
+int lib_interface_zebra_ipv4_p2p_addrs_label_destroy(
+ struct nb_cb_destroy_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
+ snprintf(args->errmsg, args->errmsg_len,
+ "Removing label is not allowed");
+ return NB_ERR_VALIDATION;
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
- /* TODO: implement me. */
break;
}
@@ -959,31 +1081,54 @@ int lib_interface_zebra_ip_addrs_label_destroy(struct nb_cb_destroy_args *args)
}
/*
- * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ip-addrs/ip4-peer
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-addrs
*/
-int lib_interface_zebra_ip_addrs_ip4_peer_modify(struct nb_cb_modify_args *args)
+int lib_interface_zebra_ipv6_addrs_create(struct nb_cb_create_args *args)
{
+ struct interface *ifp;
+ struct prefix p;
+
+ p.family = AF_INET6;
+ yang_dnode_get_ipv6(&p.u.prefix6, args->dnode, "ip");
+ p.prefixlen = yang_dnode_get_uint8(args->dnode, "prefix-length");
+
switch (args->event) {
case NB_EV_VALIDATE:
+ if (ipv6_martian(&p.u.prefix6)) {
+ snprintfrr(args->errmsg, args->errmsg_len,
+ "invalid address %pFX", &p);
+ return NB_ERR_VALIDATION;
+ }
+ break;
case NB_EV_PREPARE:
case NB_EV_ABORT:
+ break;
case NB_EV_APPLY:
- /* TODO: implement me. */
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ if_ipv6_address_install(ifp, &p);
break;
}
return NB_OK;
}
-int lib_interface_zebra_ip_addrs_ip4_peer_destroy(
- struct nb_cb_destroy_args *args)
+int lib_interface_zebra_ipv6_addrs_destroy(struct nb_cb_destroy_args *args)
{
+ struct interface *ifp;
+ struct prefix p;
+
+ p.family = AF_INET6;
+ yang_dnode_get_ipv6(&p.u.prefix6, args->dnode, "ip");
+ p.prefixlen = yang_dnode_get_uint8(args->dnode, "prefix-length");
+
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
+ break;
case NB_EV_APPLY:
- /* TODO: implement me. */
+ ifp = nb_running_get_entry(args->dnode, NULL, false);
+ if_ipv6_address_uninstall(ifp, &p);
break;
}
@@ -999,10 +1144,14 @@ int lib_interface_zebra_multicast_modify(struct nb_cb_modify_args *args)
return NB_OK;
struct interface *ifp;
+ bool multicast = yang_dnode_get_bool(args->dnode, NULL);
ifp = nb_running_get_entry(args->dnode, NULL, true);
- if_multicast_set(ifp);
+ if (multicast)
+ if_multicast_set(ifp);
+ else
+ if_multicast_unset(ifp);
return NB_OK;
}
@@ -1013,10 +1162,12 @@ int lib_interface_zebra_multicast_destroy(struct nb_cb_destroy_args *args)
return NB_OK;
struct interface *ifp;
+ struct zebra_if *zif;
ifp = nb_running_get_entry(args->dnode, NULL, true);
+ zif = ifp->info;
- if_multicast_unset(ifp);
+ zif->multicast = IF_ZEBRA_DATA_UNSPEC;
return NB_OK;
}
@@ -1033,56 +1184,91 @@ int lib_interface_zebra_link_detect_modify(struct nb_cb_modify_args *args)
bool link_detect;
ifp = nb_running_get_entry(args->dnode, NULL, true);
- link_detect = yang_dnode_get_bool(args->dnode, "./link-detect");
+ link_detect = yang_dnode_get_bool(args->dnode, NULL);
if_linkdetect(ifp, link_detect);
return NB_OK;
}
-int lib_interface_zebra_link_detect_destroy(struct nb_cb_destroy_args *args)
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/enabled
+ */
+int lib_interface_zebra_enabled_modify(struct nb_cb_modify_args *args)
{
if (args->event != NB_EV_APPLY)
return NB_OK;
struct interface *ifp;
- bool link_detect;
+ bool enabled;
ifp = nb_running_get_entry(args->dnode, NULL, true);
- link_detect = yang_dnode_get_bool(args->dnode, "./link-detect");
+ enabled = yang_dnode_get_bool(args->dnode, NULL);
- if_linkdetect(ifp, link_detect);
+ if (enabled)
+ if_no_shutdown(ifp);
+ else
+ if_shutdown(ifp);
return NB_OK;
}
-/*
- * XPath: /frr-interface:lib/interface/frr-zebra:zebra/shutdown
- */
-int lib_interface_zebra_shutdown_modify(struct nb_cb_modify_args *args)
+int lib_interface_zebra_enabled_destroy(struct nb_cb_destroy_args *args)
{
if (args->event != NB_EV_APPLY)
return NB_OK;
struct interface *ifp;
+ struct zebra_if *zif;
ifp = nb_running_get_entry(args->dnode, NULL, true);
+ zif = ifp->info;
- if_shutdown(ifp);
+ zif->shutdown = IF_ZEBRA_DATA_UNSPEC;
return NB_OK;
}
-int lib_interface_zebra_shutdown_destroy(struct nb_cb_destroy_args *args)
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/mpls
+ */
+int lib_interface_zebra_mpls_modify(struct nb_cb_modify_args *args)
{
+ struct interface *ifp;
+ bool mpls;
+ struct zebra_if *zif;
+
if (args->event != NB_EV_APPLY)
return NB_OK;
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ zif = ifp->info;
+ mpls = yang_dnode_get_bool(args->dnode, NULL);
+
+ if (mpls)
+ zif->mpls_config = IF_ZEBRA_DATA_ON;
+ else
+ zif->mpls_config = IF_ZEBRA_DATA_OFF;
+
+ dplane_intf_mpls_modify_state(ifp, mpls);
+
+ return NB_OK;
+}
+
+int lib_interface_zebra_mpls_destroy(struct nb_cb_destroy_args *args)
+{
struct interface *ifp;
+ struct zebra_if *zif;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
+ zif = ifp->info;
+
+ zif->mpls_config = IF_ZEBRA_DATA_UNSPEC;
- if_no_shutdown(ifp);
+ /* keep the state as it is */
return NB_OK;
}
@@ -1099,7 +1285,7 @@ int lib_interface_zebra_bandwidth_modify(struct nb_cb_modify_args *args)
uint32_t bandwidth;
ifp = nb_running_get_entry(args->dnode, NULL, true);
- bandwidth = yang_dnode_get_uint32(args->dnode, "./bandwidth");
+ bandwidth = yang_dnode_get_uint32(args->dnode, NULL);
ifp->bandwidth = bandwidth;
@@ -1129,58 +1315,447 @@ int lib_interface_zebra_bandwidth_destroy(struct nb_cb_destroy_args *args)
}
/*
- * XPath:
- * /frr-interface:lib/interface/frr-zebra:zebra/link-params/legacy-admin-group
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/link-params
*/
-int lib_interface_zebra_legacy_admin_group_modify(
+int lib_interface_zebra_link_params_create(struct nb_cb_create_args *args)
+{
+ struct interface *ifp;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ if_link_params_enable(ifp);
+
+ /*
+ * The interface is updated in the apply_finish callback after all
+ * parameters are set in the corresponding callbacks.
+ */
+
+ return NB_OK;
+}
+
+int lib_interface_zebra_link_params_destroy(struct nb_cb_destroy_args *args)
+{
+ struct interface *ifp;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ if_link_params_free(ifp);
+ if (if_is_operative(ifp))
+ zebra_interface_parameters_update(ifp);
+
+ return NB_OK;
+}
+
+void lib_interface_zebra_link_params_apply_finish(
+ struct nb_cb_apply_finish_args *args)
+{
+ struct interface *ifp;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ if (if_is_operative(ifp))
+ zebra_interface_parameters_update(ifp);
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/link-params/metric
+ */
+int lib_interface_zebra_link_params_metric_modify(struct nb_cb_modify_args *args)
+{
+ struct interface *ifp;
+ struct if_link_params *iflp;
+ uint32_t metric;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ iflp = if_link_params_get(ifp);
+ metric = yang_dnode_get_uint32(args->dnode, NULL);
+
+ link_param_cmd_set_uint32(ifp, &iflp->te_metric, LP_TE_METRIC, metric);
+
+ return NB_OK;
+}
+
+int lib_interface_zebra_link_params_metric_destroy(struct nb_cb_destroy_args *args)
+{
+ struct interface *ifp;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+
+ link_param_cmd_unset(ifp, LP_TE_METRIC);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/link-params/max-bandwidth
+ */
+int lib_interface_zebra_link_params_max_bandwidth_modify(
struct nb_cb_modify_args *args)
{
struct interface *ifp;
struct if_link_params *iflp;
- uint32_t admin_group_value;
+ float max_bw, res_bw, ava_bw, use_bw;
+
+ max_bw = yang_dnode_get_bandwidth_ieee_float32(args->dnode, NULL);
+
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ if (yang_dnode_exists(args->dnode, "../residual-bandwidth")) {
+ res_bw = yang_dnode_get_bandwidth_ieee_float32(
+ args->dnode, "../residual-bandwidth");
+ if (max_bw < res_bw) {
+ snprintfrr(args->errmsg, args->errmsg_len,
+ "max-bandwidth %f is less than residual-bandwidth %f",
+ max_bw, res_bw);
+ return NB_ERR_VALIDATION;
+ }
+ }
+ if (yang_dnode_exists(args->dnode, "../available-bandwidth")) {
+ ava_bw = yang_dnode_get_bandwidth_ieee_float32(
+ args->dnode, "../available-bandwidth");
+ if (max_bw < ava_bw) {
+ snprintfrr(args->errmsg, args->errmsg_len,
+ "max-bandwidth %f is less than available-bandwidth %f",
+ max_bw, ava_bw);
+ return NB_ERR_VALIDATION;
+ }
+ }
+ if (yang_dnode_exists(args->dnode, "../utilized-bandwidth")) {
+ use_bw = yang_dnode_get_bandwidth_ieee_float32(
+ args->dnode, "../utilized-bandwidth");
+ if (max_bw < use_bw) {
+ snprintfrr(args->errmsg, args->errmsg_len,
+ "max-bandwidth %f is less than utilized-bandwidth %f",
+ max_bw, use_bw);
+ return NB_ERR_VALIDATION;
+ }
+ }
+ break;
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ iflp = if_link_params_get(ifp);
+ link_param_cmd_set_float(ifp, &iflp->max_bw, LP_MAX_BW, max_bw);
+ break;
+ }
+
+ return NB_OK;
+}
+
+int lib_interface_zebra_link_params_max_bandwidth_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ if (args->event == NB_EV_VALIDATE) {
+ snprintfrr(args->errmsg, args->errmsg_len,
+ "Removing max-bandwidth is not allowed");
+ return NB_ERR_VALIDATION;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/link-params/max-reservable-bandwidth
+ */
+int lib_interface_zebra_link_params_max_reservable_bandwidth_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct interface *ifp;
+ struct if_link_params *iflp;
+ float max_rsv_bw;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ max_rsv_bw = yang_dnode_get_bandwidth_ieee_float32(args->dnode, NULL);
ifp = nb_running_get_entry(args->dnode, NULL, true);
- admin_group_value = yang_dnode_get_uint32(args->dnode, ".");
+ iflp = if_link_params_get(ifp);
+ link_param_cmd_set_float(ifp, &iflp->max_rsv_bw, LP_MAX_RSV_BW,
+ max_rsv_bw);
+
+ return NB_OK;
+}
+
+int lib_interface_zebra_link_params_max_reservable_bandwidth_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ if (args->event == NB_EV_VALIDATE) {
+ snprintfrr(args->errmsg, args->errmsg_len,
+ "Removing max-reservable-bandwidth is not allowed");
+ return NB_ERR_VALIDATION;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/link-params/unreserved-bandwidths/unreserved-bandwidth
+ */
+int lib_interface_zebra_link_params_unreserved_bandwidths_unreserved_bandwidth_create(
+ struct nb_cb_create_args *args)
+{
+ struct interface *ifp;
+ struct if_link_params *iflp;
+ uint8_t priority;
+ float unrsv_bw;
- if (!ifp)
- return NB_ERR_RESOURCE;
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ priority = yang_dnode_get_uint8(args->dnode, "priority");
+ unrsv_bw = yang_dnode_get_bandwidth_ieee_float32(args->dnode,
+ "unreserved-bandwidth");
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ iflp = if_link_params_get(ifp);
+ link_param_cmd_set_float(ifp, &iflp->unrsv_bw[priority], LP_UNRSV_BW,
+ unrsv_bw);
+
+ return NB_OK;
+}
+
+int lib_interface_zebra_link_params_unreserved_bandwidths_unreserved_bandwidth_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ if (args->event == NB_EV_VALIDATE) {
+ snprintfrr(args->errmsg, args->errmsg_len,
+ "Removing unreserved-bandwidth is not allowed");
+ return NB_ERR_VALIDATION;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/link-params/unreserved-bandwidths/unreserved-bandwidth/unreserved-bandwidth
+ */
+int lib_interface_zebra_link_params_unreserved_bandwidths_unreserved_bandwidth_unreserved_bandwidth_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct interface *ifp;
+ struct if_link_params *iflp;
+ uint8_t priority;
+ float unrsv_bw;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ priority = yang_dnode_get_uint8(args->dnode, "../priority");
+ unrsv_bw = yang_dnode_get_bandwidth_ieee_float32(args->dnode, NULL);
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
iflp = if_link_params_get(ifp);
+ link_param_cmd_set_float(ifp, &iflp->unrsv_bw[priority], LP_UNRSV_BW,
+ unrsv_bw);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/link-params/residual-bandwidth
+ */
+int lib_interface_zebra_link_params_residual_bandwidth_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct interface *ifp;
+ struct if_link_params *iflp;
+ float max_bw, res_bw;
+
+ res_bw = yang_dnode_get_bandwidth_ieee_float32(args->dnode, NULL);
switch (args->event) {
case NB_EV_VALIDATE:
+ if (yang_dnode_exists(args->dnode, "../max-bandwidth")) {
+ max_bw =
+ yang_dnode_get_bandwidth_ieee_float32(args->dnode,
+ "../max-bandwidth");
+ if (max_bw < res_bw) {
+ snprintfrr(args->errmsg, args->errmsg_len,
+ "max-bandwidth %f is less than residual-bandwidth %f",
+ max_bw, res_bw);
+ return NB_ERR_VALIDATION;
+ }
+ }
+ break;
case NB_EV_PREPARE:
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
- if (!iflp)
- iflp = if_link_params_enable(ifp);
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ iflp = if_link_params_get(ifp);
+ link_param_cmd_set_float(ifp, &iflp->res_bw, LP_RES_BW, res_bw);
+ break;
+ }
- iflp->admin_grp = admin_group_value;
- SET_PARAM(iflp, LP_ADM_GRP);
+ return NB_OK;
+}
- admin_group_clear(&iflp->ext_admin_grp);
- UNSET_PARAM(iflp, LP_EXTEND_ADM_GRP);
+int lib_interface_zebra_link_params_residual_bandwidth_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ struct interface *ifp;
- if (if_is_operative(ifp))
- zebra_interface_parameters_update(ifp);
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ link_param_cmd_unset(ifp, LP_RES_BW);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/link-params/available-bandwidth
+ */
+int lib_interface_zebra_link_params_available_bandwidth_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct interface *ifp;
+ struct if_link_params *iflp;
+ float max_bw, ava_bw;
+
+ ava_bw = yang_dnode_get_bandwidth_ieee_float32(args->dnode, NULL);
+
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ if (yang_dnode_exists(args->dnode, "../max-bandwidth")) {
+ max_bw =
+ yang_dnode_get_bandwidth_ieee_float32(args->dnode,
+ "../max-bandwidth");
+ if (max_bw < ava_bw) {
+ snprintfrr(args->errmsg, args->errmsg_len,
+ "max-bandwidth %f is less than available-bandwidth %f",
+ max_bw, ava_bw);
+ return NB_ERR_VALIDATION;
+ }
+ }
+ break;
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ iflp = if_link_params_get(ifp);
+ link_param_cmd_set_float(ifp, &iflp->ava_bw, LP_AVA_BW, ava_bw);
break;
}
+
return NB_OK;
}
-int lib_interface_zebra_legacy_admin_group_destroy(
+int lib_interface_zebra_link_params_available_bandwidth_destroy(
struct nb_cb_destroy_args *args)
{
struct interface *ifp;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ link_param_cmd_unset(ifp, LP_AVA_BW);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/link-params/utilized-bandwidth
+ */
+int lib_interface_zebra_link_params_utilized_bandwidth_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct interface *ifp;
struct if_link_params *iflp;
+ float max_bw, use_bw;
+
+ use_bw = yang_dnode_get_bandwidth_ieee_float32(args->dnode, NULL);
+
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ if (yang_dnode_exists(args->dnode, "../max-bandwidth")) {
+ max_bw =
+ yang_dnode_get_bandwidth_ieee_float32(args->dnode,
+ "../max-bandwidth");
+ if (max_bw < use_bw) {
+ snprintfrr(args->errmsg, args->errmsg_len,
+ "max-bandwidth %f is less than utilized-bandwidth %f",
+ max_bw, use_bw);
+ return NB_ERR_VALIDATION;
+ }
+ }
+ break;
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ iflp = if_link_params_get(ifp);
+ link_param_cmd_set_float(ifp, &iflp->use_bw, LP_USE_BW, use_bw);
+ break;
+ }
+
+ return NB_OK;
+}
+
+int lib_interface_zebra_link_params_utilized_bandwidth_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ struct interface *ifp;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
+ link_param_cmd_unset(ifp, LP_USE_BW);
- if (!ifp)
- return NB_ERR_RESOURCE;
+ return NB_OK;
+}
- iflp = if_link_params_get(ifp);
+/*
+ * XPath:
+ * /frr-interface:lib/interface/frr-zebra:zebra/link-params/legacy-admin-group
+ */
+int lib_interface_zebra_legacy_admin_group_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct interface *ifp;
+ struct if_link_params *iflp;
+ uint32_t admin_group_value;
+
+ admin_group_value = yang_dnode_get_uint32(args->dnode, ".");
+
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ iflp = if_link_params_get(ifp);
+
+ iflp->admin_grp = admin_group_value;
+ SET_PARAM(iflp, LP_ADM_GRP);
+ break;
+ }
+ return NB_OK;
+}
+
+int lib_interface_zebra_legacy_admin_group_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ struct interface *ifp;
+ struct if_link_params *iflp;
switch (args->event) {
case NB_EV_VALIDATE:
@@ -1188,14 +1763,11 @@ int lib_interface_zebra_legacy_admin_group_destroy(
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
- if (!iflp)
- iflp = if_link_params_enable(ifp);
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ iflp = if_link_params_get(ifp);
iflp->admin_grp = 0;
UNSET_PARAM(iflp, LP_ADM_GRP);
-
- if (if_is_operative(ifp))
- zebra_interface_parameters_update(ifp);
break;
}
return NB_OK;
@@ -1203,6 +1775,35 @@ int lib_interface_zebra_legacy_admin_group_destroy(
/*
* XPath:
+ * /frr-interface:lib/interface/frr-zebra:zebra/link-params/affinities
+ */
+int lib_interface_zebra_affinities_create(struct nb_cb_create_args *args)
+{
+ return NB_OK;
+}
+
+int lib_interface_zebra_affinities_destroy(struct nb_cb_destroy_args *args)
+{
+ struct interface *ifp;
+ struct if_link_params *iflp;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ iflp = if_link_params_get(ifp);
+
+ iflp->admin_grp = 0;
+ UNSET_PARAM(iflp, LP_ADM_GRP);
+
+ admin_group_clear(&iflp->ext_admin_grp);
+ UNSET_PARAM(iflp, LP_EXTEND_ADM_GRP);
+
+ return NB_OK;
+}
+
+/*
+ * XPath:
* /frr-interface:lib/interface/frr-zebra:zebra/link-params/affinities/affinity
*/
int lib_interface_zebra_affinity_create(struct nb_cb_create_args *args)
@@ -1213,39 +1814,18 @@ int lib_interface_zebra_affinity_create(struct nb_cb_create_args *args)
struct affinity_map *affmap;
enum affinity_mode affinity_mode;
-
- ifp = nb_running_get_entry(args->dnode, NULL, true);
affname = yang_dnode_get_string(args->dnode, ".");
affinity_mode = yang_dnode_get_enum(args->dnode, "../../affinity-mode");
- if (!ifp)
- return NB_ERR_RESOURCE;
-
- affmap = affinity_map_get(affname);
- iflp = if_link_params_get(ifp);
-
switch (args->event) {
case NB_EV_VALIDATE:
- if (!affmap) {
- snprintf(args->errmsg, args->errmsg_len,
- "affinity-map %s not found.", affname);
- return NB_ERR_VALIDATION;
- }
- if (affinity_mode == AFFINITY_MODE_STANDARD &&
- affmap->bit_position > 31) {
- snprintf(
- args->errmsg, args->errmsg_len,
- "affinity %s bit-position %d is not compatible with affinity-mode standard (bit-position > 31).",
- affname, affmap->bit_position);
- return NB_ERR_VALIDATION;
- }
- break;
case NB_EV_PREPARE:
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
- if (!iflp)
- iflp = if_link_params_enable(ifp);
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ iflp = if_link_params_get(ifp);
+ affmap = affinity_map_get(affname);
if (affmap->bit_position < 32 &&
(affinity_mode == AFFINITY_MODE_STANDARD ||
@@ -1259,9 +1839,6 @@ int lib_interface_zebra_affinity_create(struct nb_cb_create_args *args)
affmap->bit_position);
SET_PARAM(iflp, LP_EXTEND_ADM_GRP);
}
-
- if (if_is_operative(ifp))
- zebra_interface_parameters_update(ifp);
break;
}
return NB_OK;
@@ -1275,30 +1852,19 @@ int lib_interface_zebra_affinity_destroy(struct nb_cb_destroy_args *args)
struct affinity_map *affmap;
enum affinity_mode affinity_mode;
- ifp = nb_running_get_entry(args->dnode, NULL, true);
affname = yang_dnode_get_string(args->dnode, ".");
affinity_mode = yang_dnode_get_enum(args->dnode, "../../affinity-mode");
- if (!ifp)
- return NB_ERR_RESOURCE;
-
- affmap = affinity_map_get(affname);
- iflp = if_link_params_get(ifp);
-
switch (args->event) {
case NB_EV_VALIDATE:
- if (!affmap) {
- snprintf(args->errmsg, args->errmsg_len,
- "affinity-map %s not found.", affname);
- return NB_ERR_VALIDATION;
- }
- break;
case NB_EV_PREPARE:
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
- if (!iflp)
- return NB_OK;
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ iflp = if_link_params_get(ifp);
+ affmap = affinity_map_get(affname);
+
if (affmap->bit_position < 32 &&
(affinity_mode == AFFINITY_MODE_STANDARD ||
affinity_mode == AFFINITY_MODE_BOTH)) {
@@ -1313,9 +1879,6 @@ int lib_interface_zebra_affinity_destroy(struct nb_cb_destroy_args *args)
if (admin_group_zero(&iflp->ext_admin_grp))
UNSET_PARAM(iflp, LP_EXTEND_ADM_GRP);
}
-
- if (if_is_operative(ifp))
- zebra_interface_parameters_update(ifp);
break;
}
return NB_OK;
@@ -1331,31 +1894,17 @@ int lib_interface_zebra_affinity_mode_modify(struct nb_cb_modify_args *args)
struct if_link_params *iflp;
enum affinity_mode affinity_mode;
-
- ifp = nb_running_get_entry(args->dnode, NULL, true);
affinity_mode = yang_dnode_get_enum(args->dnode, ".");
- if (!ifp)
- return NB_ERR_RESOURCE;
-
- iflp = if_link_params_get(ifp);
-
switch (args->event) {
case NB_EV_VALIDATE:
- if (affinity_mode == AFFINITY_MODE_STANDARD &&
- admin_group_nb_words(&iflp->ext_admin_grp) > 1) {
- snprintf(
- args->errmsg, args->errmsg_len,
- "affinity-mode standard cannot be set when a bit-position > 31 is set.");
- return NB_ERR_VALIDATION;
- }
- break;
case NB_EV_PREPARE:
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
- if (!iflp)
- iflp = if_link_params_enable(ifp);
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ iflp = if_link_params_get(ifp);
+
if (affinity_mode == AFFINITY_MODE_STANDARD) {
if (!IS_PARAM_SET(iflp, LP_ADM_GRP) &&
IS_PARAM_SET(iflp, LP_EXTEND_ADM_GRP)) {
@@ -1389,84 +1938,1880 @@ int lib_interface_zebra_affinity_mode_modify(struct nb_cb_modify_args *args)
SET_PARAM(iflp, LP_ADM_GRP);
}
}
+ break;
+ }
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/link-params/neighbor
+ */
+int lib_interface_zebra_link_params_neighbor_create(struct nb_cb_create_args *args)
+{
+ struct interface *ifp;
+ struct if_link_params *iflp;
+ struct in_addr ip;
+ uint32_t as;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ as = yang_dnode_get_uint32(args->dnode, "remote-as");
+ yang_dnode_get_ipv4(&ip, args->dnode, "ipv4-remote-id");
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ iflp = if_link_params_get(ifp);
+
+ iflp->rmt_as = as;
+ iflp->rmt_ip = ip;
+ SET_PARAM(iflp, LP_RMT_AS);
+
+ return NB_OK;
+}
+
+int lib_interface_zebra_link_params_neighbor_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ struct interface *ifp;
+ struct if_link_params *iflp;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ iflp = if_link_params_get(ifp);
+
+ iflp->rmt_as = 0;
+ iflp->rmt_ip.s_addr = 0;
+ UNSET_PARAM(iflp, LP_RMT_AS);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/link-params/neighbor/remote-as
+ */
+int lib_interface_zebra_link_params_neighbor_remote_as_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct interface *ifp;
+ struct if_link_params *iflp;
+ uint32_t as;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ as = yang_dnode_get_uint32(args->dnode, NULL);
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ iflp = if_link_params_get(ifp);
+
+ iflp->rmt_as = as;
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/link-params/neighbor/ipv4-remote-id
+ */
+int lib_interface_zebra_link_params_neighbor_ipv4_remote_id_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct interface *ifp;
+ struct if_link_params *iflp;
+ struct in_addr ip;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ yang_dnode_get_ipv4(&ip, args->dnode, NULL);
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ iflp = if_link_params_get(ifp);
+
+ iflp->rmt_ip = ip;
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/link-params/delay
+ */
+int lib_interface_zebra_link_params_delay_modify(struct nb_cb_modify_args *args)
+{
+ struct interface *ifp;
+ struct if_link_params *iflp;
+ uint32_t delay;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ delay = yang_dnode_get_uint32(args->dnode, NULL);
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ iflp = if_link_params_get(ifp);
+
+ link_param_cmd_set_uint32(ifp, &iflp->av_delay, LP_DELAY, delay);
+
+ return NB_OK;
+}
+
+int lib_interface_zebra_link_params_delay_destroy(struct nb_cb_destroy_args *args)
+{
+ struct interface *ifp;
+ struct if_link_params *iflp;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ iflp = if_link_params_get(ifp);
+
+ iflp->av_delay = 0;
+ link_param_cmd_unset(ifp, LP_DELAY);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/link-params/min-max-delay
+ */
+int lib_interface_zebra_link_params_min_max_delay_create(
+ struct nb_cb_create_args *args)
+{
+ struct interface *ifp;
+ struct if_link_params *iflp;
+ uint32_t delay_min, delay_max;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ delay_min = yang_dnode_get_uint32(args->dnode, "delay-min");
+ delay_max = yang_dnode_get_uint32(args->dnode, "delay-max");
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ iflp = if_link_params_get(ifp);
+
+ iflp->min_delay = delay_min;
+ iflp->max_delay = delay_max;
+ SET_PARAM(iflp, LP_MM_DELAY);
+
+ return NB_OK;
+}
+
+int lib_interface_zebra_link_params_min_max_delay_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ struct interface *ifp;
+ struct if_link_params *iflp;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ iflp = if_link_params_get(ifp);
+
+ iflp->min_delay = 0;
+ iflp->max_delay = 0;
+ UNSET_PARAM(iflp, LP_MM_DELAY);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/link-params/min-max-delay/delay-min
+ */
+int lib_interface_zebra_link_params_min_max_delay_delay_min_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct interface *ifp;
+ struct if_link_params *iflp;
+ uint32_t delay_min;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ delay_min = yang_dnode_get_uint32(args->dnode, NULL);
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ iflp = if_link_params_get(ifp);
+
+ iflp->min_delay = delay_min;
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/link-params/min-max-delay/delay-max
+ */
+int lib_interface_zebra_link_params_min_max_delay_delay_max_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct interface *ifp;
+ struct if_link_params *iflp;
+ uint32_t delay_max;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ delay_max = yang_dnode_get_uint32(args->dnode, NULL);
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ iflp = if_link_params_get(ifp);
+
+ iflp->max_delay = delay_max;
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/link-params/delay-variation
+ */
+int lib_interface_zebra_link_params_delay_variation_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct interface *ifp;
+ struct if_link_params *iflp;
+ uint32_t delay_var;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ delay_var = yang_dnode_get_uint32(args->dnode, NULL);
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ iflp = if_link_params_get(ifp);
+
+ link_param_cmd_set_uint32(ifp, &iflp->delay_var, LP_DELAY_VAR,
+ delay_var);
+
+ return NB_OK;
+}
+
+int lib_interface_zebra_link_params_delay_variation_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ struct interface *ifp;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+
+ link_param_cmd_unset(ifp, LP_DELAY_VAR);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/link-params/packet-loss
+ */
+int lib_interface_zebra_link_params_packet_loss_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct interface *ifp;
+ struct if_link_params *iflp;
+ double packet_loss;
+ uint32_t value;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ packet_loss = yang_dnode_get_dec64(args->dnode, NULL);
+ value = (uint32_t)(packet_loss / LOSS_PRECISION);
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ iflp = if_link_params_get(ifp);
+
+ link_param_cmd_set_uint32(ifp, &iflp->pkt_loss, LP_PKT_LOSS, value);
+
+ return NB_OK;
+}
+
+int lib_interface_zebra_link_params_packet_loss_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ struct interface *ifp;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+
+ link_param_cmd_unset(ifp, LP_PKT_LOSS);
+
+ return NB_OK;
+}
+
+static bool evpn_mh_dnode_to_esi(const struct lyd_node *dnode, esi_t *esi)
+{
+ if (yang_dnode_exists(dnode, "type-0/esi")) {
+ if (!str_to_esi(yang_dnode_get_string(dnode, "type-0/esi"), esi))
+ assert(false);
+ } else if (yang_dnode_exists(dnode, "type-3/system-mac") &&
+ yang_dnode_exists(dnode, "type-3/local-discriminator")) {
+ struct ethaddr mac;
+ uint32_t lid;
+
+ yang_dnode_get_mac(&mac, dnode, "type-3/system-mac");
+ lid = yang_dnode_get_uint32(dnode, "type-3/local-discriminator");
+
+ zebra_build_type3_esi(lid, &mac, esi);
+ } else {
+ return false;
+ }
+
+ return true;
+}
+
+struct esi_cmp_iter_arg {
+ struct lyd_node *dnode;
+ esi_t esi;
+ bool exists;
+};
+
+static int esi_cmp_iter_cb(const struct lyd_node *dnode, void *arg)
+{
+ struct esi_cmp_iter_arg *iter = arg;
+ esi_t esi;
+
+ if (dnode == iter->dnode)
+ return YANG_ITER_CONTINUE;
+
+ if (!evpn_mh_dnode_to_esi(dnode, &esi))
+ return YANG_ITER_CONTINUE;
+
+ if (!memcmp(&esi, &iter->esi, ESI_BYTES)) {
+ iter->exists = true;
+ return YANG_ITER_STOP;
+ }
+
+ return YANG_ITER_CONTINUE;
+}
+
+/* evpn-mh should be passed to this function */
+static bool esi_unique(struct lyd_node *dnode)
+{
+ struct esi_cmp_iter_arg iter;
+
+ iter.dnode = dnode;
+ evpn_mh_dnode_to_esi(dnode, &iter.esi);
+ iter.exists = false;
+
+ yang_dnode_iterate(esi_cmp_iter_cb, &iter, dnode,
+ "/frr-interface:lib/interface/frr-zebra:zebra/evpn-mh");
+
+ if (iter.exists)
+ return false;
+
+ return true;
+}
- if (if_is_operative(ifp))
- zebra_interface_parameters_update(ifp);
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/evpn-mh/type-0
+ */
+int lib_interface_zebra_evpn_mh_type_0_create(struct nb_cb_create_args *args)
+{
+ return NB_OK;
+}
+
+int lib_interface_zebra_evpn_mh_type_0_destroy(struct nb_cb_destroy_args *args)
+{
+ struct interface *ifp;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ zebra_evpn_es_type0_esi_update(ifp->info, NULL);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/evpn-mh/type-0/esi
+ */
+int lib_interface_zebra_evpn_mh_type_0_esi_modify(struct nb_cb_modify_args *args)
+{
+ struct interface *ifp;
+ esi_t esi;
+
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ if (!esi_unique(lyd_parent(lyd_parent(args->dnode)))) {
+ snprintfrr(args->errmsg, args->errmsg_len,
+ "ESI already exists on a different interface");
+ return NB_ERR_VALIDATION;
+ }
+ break;
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ if (!str_to_esi(yang_dnode_get_string(args->dnode, NULL), &esi))
+ assert(false);
+ zebra_evpn_es_type0_esi_update(ifp->info, &esi);
break;
}
+
+ return NB_OK;
+}
+
+int lib_interface_zebra_evpn_mh_type_0_esi_destroy(struct nb_cb_destroy_args *args)
+{
+ struct interface *ifp;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ zebra_evpn_es_type0_esi_update(ifp->info, NULL);
+
return NB_OK;
}
/*
- * XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/l3vni-id
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/evpn-mh/type-3
*/
-int lib_vrf_zebra_l3vni_id_modify(struct nb_cb_modify_args *args)
+int lib_interface_zebra_evpn_mh_type_3_create(struct nb_cb_create_args *args)
{
- struct vrf *vrf;
- struct zebra_vrf *zvrf;
- vni_t vni = 0;
- struct zebra_l3vni *zl3vni = NULL;
- char err[ERR_STR_SZ];
- bool pfx_only = false;
- const struct lyd_node *pn_dnode;
- const char *vrfname;
+ return NB_OK;
+}
+
+int lib_interface_zebra_evpn_mh_type_3_destroy(struct nb_cb_destroy_args *args)
+{
+ struct interface *ifp;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ zebra_evpn_es_sys_mac_update(ifp->info, NULL);
+ zebra_evpn_es_lid_update(ifp->info, 0);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/evpn-mh/type-3/system-mac
+ */
+int lib_interface_zebra_evpn_mh_type_3_system_mac_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct interface *ifp;
+ struct ethaddr mac;
+
+ yang_dnode_get_mac(&mac, args->dnode, NULL);
switch (args->event) {
+ case NB_EV_VALIDATE:
+ if (is_zero_mac(&mac)) {
+ snprintfrr(args->errmsg, args->errmsg_len,
+ "MAC cannot be all-zeroes");
+ return NB_ERR_VALIDATION;
+ }
+ if (!esi_unique(lyd_parent(lyd_parent(args->dnode)))) {
+ snprintfrr(args->errmsg, args->errmsg_len,
+ "ESI already exists on a different interface");
+ return NB_ERR_VALIDATION;
+ }
+ break;
case NB_EV_PREPARE:
case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ zebra_evpn_es_sys_mac_update(ifp->info, &mac);
+ break;
+ }
+
+ return NB_OK;
+}
+
+int lib_interface_zebra_evpn_mh_type_3_system_mac_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ struct interface *ifp;
+
+ if (args->event != NB_EV_APPLY)
return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ zebra_evpn_es_sys_mac_update(ifp->info, NULL);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/evpn-mh/type-3/local-discriminator
+ */
+int lib_interface_zebra_evpn_mh_type_3_local_discriminator_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct interface *ifp;
+ uint32_t lid;
+
+ switch (args->event) {
case NB_EV_VALIDATE:
- vni = yang_dnode_get_uint32(args->dnode, NULL);
- /* Get vrf info from parent node, reject configuration
- * if zebra vrf already mapped to different vni id.
- */
- pn_dnode = yang_dnode_get_parent(args->dnode, "vrf");
- vrfname = yang_dnode_get_string(pn_dnode, "./name");
- zvrf = zebra_vrf_lookup_by_name(vrfname);
- if (!zvrf) {
- snprintf(args->errmsg, args->errmsg_len,
- "zebra vrf info not found for vrf:%s.",
- vrfname);
+ if (!esi_unique(lyd_parent(lyd_parent(args->dnode)))) {
+ snprintfrr(args->errmsg, args->errmsg_len,
+ "ESI already exists on a different interface");
+ return NB_ERR_VALIDATION;
+ }
+ break;
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ lid = yang_dnode_get_uint32(args->dnode, NULL);
+ zebra_evpn_es_lid_update(ifp->info, lid);
+ break;
+ }
+
+ return NB_OK;
+}
+
+int lib_interface_zebra_evpn_mh_type_3_local_discriminator_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ struct interface *ifp;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ zebra_evpn_es_lid_update(ifp->info, 0);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/evpn-mh/df-preference
+ */
+int lib_interface_zebra_evpn_mh_df_preference_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct interface *ifp;
+ uint16_t df_pref;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ df_pref = yang_dnode_get_uint16(args->dnode, NULL);
+ zebra_evpn_es_df_pref_update(ifp->info, df_pref);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/evpn-mh/bypass
+ */
+int lib_interface_zebra_evpn_mh_bypass_modify(struct nb_cb_modify_args *args)
+{
+ struct interface *ifp;
+ bool bypass;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ bypass = yang_dnode_get_bool(args->dnode, NULL);
+ zebra_evpn_es_bypass_cfg_update(ifp->info, bypass);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/evpn-mh/uplink
+ */
+int lib_interface_zebra_evpn_mh_uplink_modify(struct nb_cb_modify_args *args)
+{
+ struct interface *ifp;
+ bool uplink;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ uplink = yang_dnode_get_bool(args->dnode, NULL);
+ zebra_evpn_mh_uplink_cfg_update(ifp->info, uplink);
+
+ return NB_OK;
+}
+
+#if defined(HAVE_RTADV)
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/send-advertisements
+ */
+int lib_interface_zebra_ipv6_router_advertisements_send_advertisements_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct interface *ifp;
+ struct zebra_if *zif;
+ bool send_adv;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ zif = ifp->info;
+
+ send_adv = yang_dnode_get_bool(args->dnode, NULL);
+
+ if (send_adv) {
+ ipv6_nd_suppress_ra_set(ifp, RA_ENABLE);
+ SET_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED);
+ } else {
+ if (!CHECK_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED))
+ ipv6_nd_suppress_ra_set(ifp, RA_SUPPRESS);
+ UNSET_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED);
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/max-rtr-adv-interval
+ */
+int lib_interface_zebra_ipv6_router_advertisements_max_rtr_adv_interval_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct interface *ifp;
+ uint32_t interval;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ interval = yang_dnode_get_uint32(args->dnode, NULL);
+
+ ipv6_nd_interval_set(ifp, interval);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/managed-flag
+ */
+int lib_interface_zebra_ipv6_router_advertisements_managed_flag_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct interface *ifp;
+ struct zebra_if *zif;
+ bool managed_flag;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ zif = ifp->info;
+
+ managed_flag = yang_dnode_get_bool(args->dnode, NULL);
+
+ zif->rtadv.AdvManagedFlag = managed_flag;
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/other-config-flag
+ */
+int lib_interface_zebra_ipv6_router_advertisements_other_config_flag_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct interface *ifp;
+ struct zebra_if *zif;
+ bool other_config_flag;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ zif = ifp->info;
+
+ other_config_flag = yang_dnode_get_bool(args->dnode, NULL);
+
+ zif->rtadv.AdvOtherConfigFlag = other_config_flag;
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/home-agent-flag
+ */
+int lib_interface_zebra_ipv6_router_advertisements_home_agent_flag_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct interface *ifp;
+ struct zebra_if *zif;
+ bool home_agent_flag;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ zif = ifp->info;
+
+ home_agent_flag = yang_dnode_get_bool(args->dnode, NULL);
+
+ zif->rtadv.AdvHomeAgentFlag = home_agent_flag;
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/link-mtu
+ */
+int lib_interface_zebra_ipv6_router_advertisements_link_mtu_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct interface *ifp;
+ struct zebra_if *zif;
+ uint32_t mtu;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ zif = ifp->info;
+
+ mtu = yang_dnode_get_uint32(args->dnode, NULL);
+
+ zif->rtadv.AdvLinkMTU = mtu;
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/reachable-time
+ */
+int lib_interface_zebra_ipv6_router_advertisements_reachable_time_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct interface *ifp;
+ struct zebra_if *zif;
+ uint32_t time;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ zif = ifp->info;
+ time = yang_dnode_get_uint32(args->dnode, NULL);
+
+ zif->rtadv.AdvReachableTime = time;
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/retrans-timer
+ */
+int lib_interface_zebra_ipv6_router_advertisements_retrans_timer_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct interface *ifp;
+ struct zebra_if *zif;
+ uint32_t timer;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ zif = ifp->info;
+ timer = yang_dnode_get_uint32(args->dnode, NULL);
+
+ zif->rtadv.AdvRetransTimer = timer;
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/cur-hop-limit
+ */
+int lib_interface_zebra_ipv6_router_advertisements_cur_hop_limit_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct interface *ifp;
+ struct zebra_if *zif;
+ uint8_t limit;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ zif = ifp->info;
+ limit = yang_dnode_get_uint8(args->dnode, NULL);
+
+ zif->rtadv.AdvCurHopLimit = limit;
+
+ return NB_OK;
+}
+
+int lib_interface_zebra_ipv6_router_advertisements_cur_hop_limit_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ struct interface *ifp;
+ struct zebra_if *zif;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ zif = ifp->info;
+
+ zif->rtadv.AdvCurHopLimit = RTADV_DEFAULT_HOPLIMIT;
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/default-lifetime
+ */
+int lib_interface_zebra_ipv6_router_advertisements_default_lifetime_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct interface *ifp;
+ struct zebra_if *zif;
+ uint16_t lifetime;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ zif = ifp->info;
+
+ lifetime = yang_dnode_get_uint16(args->dnode, NULL);
+
+ zif->rtadv.AdvDefaultLifetime = lifetime;
+
+ return NB_OK;
+}
+
+int lib_interface_zebra_ipv6_router_advertisements_default_lifetime_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ struct interface *ifp;
+ struct zebra_if *zif;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ zif = ifp->info;
+
+ zif->rtadv.AdvDefaultLifetime = -1;
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/fast-retransmit
+ */
+int lib_interface_zebra_ipv6_router_advertisements_fast_retransmit_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct interface *ifp;
+ struct zebra_if *zif;
+ bool fast_retransmit;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ zif = ifp->info;
+
+ fast_retransmit = yang_dnode_get_bool(args->dnode, NULL);
+
+ zif->rtadv.UseFastRexmit = fast_retransmit;
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/advertisement-interval-option
+ */
+int lib_interface_zebra_ipv6_router_advertisements_advertisement_interval_option_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct interface *ifp;
+ struct zebra_if *zif;
+ bool option;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ zif = ifp->info;
+
+ option = yang_dnode_get_bool(args->dnode, NULL);
+
+ zif->rtadv.AdvIntervalOption = option;
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/home-agent-preference
+ */
+int lib_interface_zebra_ipv6_router_advertisements_home_agent_preference_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct interface *ifp;
+ struct zebra_if *zif;
+ uint16_t preference;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ zif = ifp->info;
+
+ preference = yang_dnode_get_uint16(args->dnode, NULL);
+
+ zif->rtadv.HomeAgentPreference = preference;
+
+ return NB_OK;
+}
+
+int lib_interface_zebra_ipv6_router_advertisements_home_agent_preference_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ struct interface *ifp;
+ struct zebra_if *zif;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ zif = ifp->info;
+
+ zif->rtadv.HomeAgentPreference = 0;
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/home-agent-lifetime
+ */
+int lib_interface_zebra_ipv6_router_advertisements_home_agent_lifetime_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct interface *ifp;
+ struct zebra_if *zif;
+ uint16_t lifetime;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ zif = ifp->info;
+
+ lifetime = yang_dnode_get_uint16(args->dnode, NULL);
+
+ zif->rtadv.HomeAgentLifetime = lifetime;
+
+ return NB_OK;
+}
+
+int lib_interface_zebra_ipv6_router_advertisements_home_agent_lifetime_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ struct interface *ifp;
+ struct zebra_if *zif;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ zif = ifp->info;
+
+ zif->rtadv.HomeAgentLifetime = -1;
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/default-router-preference
+ */
+int lib_interface_zebra_ipv6_router_advertisements_default_router_preference_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct interface *ifp;
+ struct zebra_if *zif;
+ int preference;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ zif = ifp->info;
+
+ preference = yang_dnode_get_enum(args->dnode, NULL);
+
+ zif->rtadv.DefaultPreference = preference;
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/prefix-list/prefix
+ */
+int lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_create(
+ struct nb_cb_create_args *args)
+{
+ struct interface *ifp;
+ struct rtadv_prefix rp, *prefix;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+
+ yang_dnode_get_ipv6p(&rp.prefix, args->dnode, "prefix-spec");
+ rp.AdvOnLinkFlag = yang_dnode_get_bool(args->dnode, "on-link-flag");
+ rp.AdvAutonomousFlag = yang_dnode_get_bool(args->dnode,
+ "autonomous-flag");
+ rp.AdvRouterAddressFlag = yang_dnode_get_bool(args->dnode,
+ "router-address-flag");
+ rp.AdvValidLifetime = yang_dnode_get_uint32(args->dnode,
+ "valid-lifetime");
+ rp.AdvPreferredLifetime = yang_dnode_get_uint32(args->dnode,
+ "preferred-lifetime");
+
+ prefix = rtadv_add_prefix_manual(ifp->info, &rp);
+ nb_running_set_entry(args->dnode, prefix);
+
+ return NB_OK;
+}
+
+int lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ struct interface *ifp;
+ struct rtadv_prefix *prefix;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ prefix = nb_running_unset_entry(args->dnode);
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+
+ rtadv_delete_prefix_manual(ifp->info, prefix);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/prefix-list/prefix/valid-lifetime
+ */
+int lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_valid_lifetime_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct rtadv_prefix *prefix;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ prefix = nb_running_get_entry(args->dnode, NULL, true);
+
+ prefix->AdvValidLifetime = yang_dnode_get_uint32(args->dnode, NULL);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/prefix-list/prefix/on-link-flag
+ */
+int lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_on_link_flag_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct rtadv_prefix *prefix;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ prefix = nb_running_get_entry(args->dnode, NULL, true);
+
+ prefix->AdvOnLinkFlag = yang_dnode_get_bool(args->dnode, NULL);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/prefix-list/prefix/preferred-lifetime
+ */
+int lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_preferred_lifetime_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct rtadv_prefix *prefix;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ prefix = nb_running_get_entry(args->dnode, NULL, true);
+
+ prefix->AdvPreferredLifetime = yang_dnode_get_uint32(args->dnode, NULL);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/prefix-list/prefix/autonomous-flag
+ */
+int lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_autonomous_flag_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct rtadv_prefix *prefix;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ prefix = nb_running_get_entry(args->dnode, NULL, true);
+
+ prefix->AdvAutonomousFlag = yang_dnode_get_bool(args->dnode, NULL);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/prefix-list/prefix/router-address-flag
+ */
+int lib_interface_zebra_ipv6_router_advertisements_prefix_list_prefix_router_address_flag_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct rtadv_prefix *prefix;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ prefix = nb_running_get_entry(args->dnode, NULL, true);
+
+ prefix->AdvRouterAddressFlag = yang_dnode_get_bool(args->dnode, NULL);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/rdnss/rdnss-address
+ */
+int lib_interface_zebra_ipv6_router_advertisements_rdnss_rdnss_address_create(
+ struct nb_cb_create_args *args)
+{
+ struct interface *ifp;
+ struct rtadv_rdnss rdnss = {{{{0}}}}, *p;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+
+ yang_dnode_get_ipv6(&rdnss.addr, args->dnode, "address");
+ if (yang_dnode_exists(args->dnode, "lifetime")) {
+ rdnss.lifetime = yang_dnode_get_uint32(args->dnode, "lifetime");
+ rdnss.lifetime_set = 1;
+ } else {
+ rdnss.lifetime_set = 0;
+ }
+
+ p = rtadv_rdnss_set(ifp->info, &rdnss);
+ nb_running_set_entry(args->dnode, p);
+
+ return NB_OK;
+}
+
+int lib_interface_zebra_ipv6_router_advertisements_rdnss_rdnss_address_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ struct interface *ifp;
+ struct rtadv_rdnss *p;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ p = nb_running_unset_entry(args->dnode);
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+
+ rtadv_rdnss_reset(ifp->info, p);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/rdnss/rdnss-address/lifetime
+ */
+int lib_interface_zebra_ipv6_router_advertisements_rdnss_rdnss_address_lifetime_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct rtadv_rdnss *p;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ p = nb_running_get_entry(args->dnode, NULL, true);
+
+ p->lifetime = yang_dnode_get_uint32(args->dnode, NULL);
+ p->lifetime_set = 1;
+
+ return NB_OK;
+}
+
+int lib_interface_zebra_ipv6_router_advertisements_rdnss_rdnss_address_lifetime_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ struct rtadv_rdnss *p;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ p = nb_running_get_entry(args->dnode, NULL, true);
+
+ p->lifetime_set = 0;
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/dnssl/dnssl-domain
+ */
+int lib_interface_zebra_ipv6_router_advertisements_dnssl_dnssl_domain_create(
+ struct nb_cb_create_args *args)
+{
+ struct interface *ifp;
+ struct rtadv_dnssl dnssl = {{0}}, *p;
+ int ret;
+
+ strlcpy(dnssl.name, yang_dnode_get_string(args->dnode, "domain"),
+ sizeof(dnssl.name));
+ ret = rtadv_dnssl_encode(dnssl.encoded_name, dnssl.name);
+
+ if (args->event == NB_EV_VALIDATE) {
+ if (ret < 0) {
+ snprintfrr(args->errmsg, args->errmsg_len,
+ "Malformed DNS search domain");
return NB_ERR_VALIDATION;
}
- if (zvrf->l3vni && zvrf->l3vni != vni) {
- snprintf(
- args->errmsg, args->errmsg_len,
- "vni %u cannot be configured as vni %u is already configured under the vrf",
- vni, zvrf->l3vni);
+ }
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+
+ if (yang_dnode_exists(args->dnode, "lifetime")) {
+ dnssl.lifetime = yang_dnode_get_uint32(args->dnode, "lifetime");
+ dnssl.lifetime_set = 1;
+ } else {
+ dnssl.lifetime_set = 0;
+ }
+
+ p = rtadv_dnssl_set(ifp->info, &dnssl);
+ nb_running_set_entry(args->dnode, p);
+
+ return NB_OK;
+}
+
+int lib_interface_zebra_ipv6_router_advertisements_dnssl_dnssl_domain_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ struct interface *ifp;
+ struct rtadv_dnssl *p;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ p = nb_running_unset_entry(args->dnode);
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+
+ rtadv_dnssl_reset(ifp->info, p);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ipv6-router-advertisements/dnssl/dnssl-domain/lifetime
+ */
+int lib_interface_zebra_ipv6_router_advertisements_dnssl_dnssl_domain_lifetime_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct rtadv_dnssl *p;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ p = nb_running_get_entry(args->dnode, NULL, true);
+
+ p->lifetime = yang_dnode_get_uint32(args->dnode, NULL);
+ p->lifetime_set = 1;
+
+ return NB_OK;
+}
+
+int lib_interface_zebra_ipv6_router_advertisements_dnssl_dnssl_domain_lifetime_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ struct rtadv_dnssl *p;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ p = nb_running_get_entry(args->dnode, NULL, true);
+
+ p->lifetime_set = 0;
+
+ return NB_OK;
+}
+#endif /* defined(HAVE_RTADV) */
+
+#if HAVE_BFDD == 0
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/ptm-enable
+ */
+int lib_interface_zebra_ptm_enable_modify(struct nb_cb_modify_args *args)
+{
+ struct interface *ifp;
+ bool ptm;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+
+ ptm = yang_dnode_get_bool(args->dnode, NULL);
+ if (ptm)
+ zebra_if_ptm_enable(ifp);
+ else
+ zebra_if_ptm_disable(ifp);
+
+ return NB_OK;
+}
+#endif
+
+/*
+ * XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/router-id
+ */
+int lib_vrf_zebra_router_id_modify(struct nb_cb_modify_args *args)
+{
+ struct vrf *vrf;
+ struct prefix p;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ vrf = nb_running_get_entry(args->dnode, NULL, true);
+
+ yang_dnode_get_ipv4p(&p, args->dnode, NULL);
+
+ router_id_set(AFI_IP, &p, vrf->info);
+
+ return NB_OK;
+}
+
+int lib_vrf_zebra_router_id_destroy(struct nb_cb_destroy_args *args)
+{
+ struct vrf *vrf;
+ struct prefix p;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ vrf = nb_running_get_entry(args->dnode, NULL, true);
+
+ memset(&p, 0, sizeof(p));
+ p.family = AF_INET;
+
+ router_id_set(AFI_IP, &p, vrf->info);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/ipv6-router-id
+ */
+int lib_vrf_zebra_ipv6_router_id_modify(struct nb_cb_modify_args *args)
+{
+ struct vrf *vrf;
+ struct prefix p;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ vrf = nb_running_get_entry(args->dnode, NULL, true);
+
+ yang_dnode_get_ipv6p(&p, args->dnode, NULL);
+
+ router_id_set(AFI_IP6, &p, vrf->info);
+
+ return NB_OK;
+}
+
+int lib_vrf_zebra_ipv6_router_id_destroy(struct nb_cb_destroy_args *args)
+{
+ struct vrf *vrf;
+ struct prefix p;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ vrf = nb_running_get_entry(args->dnode, NULL, true);
+
+ memset(&p, 0, sizeof(p));
+ p.family = AF_INET6;
+
+ router_id_set(AFI_IP6, &p, vrf->info);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/filter-protocol
+ */
+int lib_vrf_zebra_filter_protocol_create(struct nb_cb_create_args *args)
+{
+ const char *proto = yang_dnode_get_string(args->dnode, "protocol");
+ int rtype;
+
+ if (strcasecmp(proto, "any") == 0)
+ rtype = ZEBRA_ROUTE_MAX;
+ else
+ rtype = proto_name2num(proto);
+
+ if (args->event == NB_EV_VALIDATE)
+ if (rtype < 0) {
+ snprintfrr(args->errmsg, args->errmsg_len,
+ "invalid protocol name \"%s\"", proto);
return NB_ERR_VALIDATION;
}
- /* Check if this VNI is already present in the system */
- zl3vni = zl3vni_lookup(vni);
- if (zl3vni) {
- snprintf(args->errmsg, args->errmsg_len,
- "VNI %u is already configured as L3-VNI", vni);
+ /* the creation finishes in the apply_finish callback */
+
+ return NB_OK;
+}
+
+int lib_vrf_zebra_filter_protocol_destroy(struct nb_cb_destroy_args *args)
+{
+ struct vrf *vrf;
+ const char *afi_safi = yang_dnode_get_string(args->dnode, "afi-safi");
+ const char *proto = yang_dnode_get_string(args->dnode, "protocol");
+ const char *rmap = yang_dnode_get_string(args->dnode, "route-map");
+ afi_t afi;
+ safi_t safi;
+ int rtype;
+
+ yang_afi_safi_identity2value(afi_safi, &afi, &safi);
+
+ if (strcasecmp(proto, "any") == 0)
+ rtype = ZEBRA_ROUTE_MAX;
+ else
+ rtype = proto_name2num(proto);
+
+ /* deleting an existing entry, it can't be invalid */
+ assert(rtype >= 0);
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ vrf = nb_running_get_entry(args->dnode, NULL, true);
+
+ ip_protocol_rm_del(vrf->info, rmap, rtype, afi, safi);
+
+ return NB_OK;
+}
+
+void lib_vrf_zebra_filter_protocol_apply_finish(
+ struct nb_cb_apply_finish_args *args)
+{
+ struct vrf *vrf;
+ const char *afi_safi = yang_dnode_get_string(args->dnode, "afi-safi");
+ const char *proto = yang_dnode_get_string(args->dnode, "protocol");
+ const char *rmap = yang_dnode_get_string(args->dnode, "route-map");
+ afi_t afi;
+ safi_t safi;
+ int rtype;
+
+ yang_afi_safi_identity2value(afi_safi, &afi, &safi);
+
+ if (strcasecmp(proto, "any") == 0)
+ rtype = ZEBRA_ROUTE_MAX;
+ else
+ rtype = proto_name2num(proto);
+
+ /* finishing apply for a validated entry, it can't be invalid */
+ assert(rtype >= 0);
+
+ vrf = nb_running_get_entry(args->dnode, NULL, true);
+
+ ip_protocol_rm_add(vrf->info, rmap, rtype, afi, safi);
+}
+
+/*
+ * XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/filter-protocol/route-map
+ */
+int lib_vrf_zebra_filter_protocol_route_map_modify(struct nb_cb_modify_args *args)
+{
+ /* the update is done in the apply_finish callback */
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/filter-nht
+ */
+int lib_vrf_zebra_filter_nht_create(struct nb_cb_create_args *args)
+{
+ const char *afi_safi = yang_dnode_get_string(args->dnode, "afi-safi");
+ const char *proto = yang_dnode_get_string(args->dnode, "protocol");
+ afi_t afi;
+ safi_t safi;
+ int rtype;
+
+ yang_afi_safi_identity2value(afi_safi, &afi, &safi);
+
+ if (strcasecmp(proto, "any") == 0)
+ rtype = ZEBRA_ROUTE_MAX;
+ else
+ rtype = proto_name2num(proto);
+
+ if (args->event == NB_EV_VALIDATE) {
+ if (rtype < 0) {
+ snprintfrr(args->errmsg, args->errmsg_len,
+ "invalid protocol name \"%s\"", proto);
+ return NB_ERR_VALIDATION;
+ }
+ if (safi != SAFI_UNICAST) {
+ snprintfrr(args->errmsg, args->errmsg_len,
+ "only SAFI unicast is supported");
return NB_ERR_VALIDATION;
}
+ }
+
+ /* the creation finishes in the apply_finish callback */
+
+ return NB_OK;
+}
+
+int lib_vrf_zebra_filter_nht_destroy(struct nb_cb_destroy_args *args)
+{
+ struct vrf *vrf;
+ const char *afi_safi = yang_dnode_get_string(args->dnode, "afi-safi");
+ const char *proto = yang_dnode_get_string(args->dnode, "protocol");
+ const char *rmap = yang_dnode_get_string(args->dnode, "route-map");
+ afi_t afi;
+ safi_t safi;
+ int rtype;
+
+ yang_afi_safi_identity2value(afi_safi, &afi, &safi);
+
+ if (strcasecmp(proto, "any") == 0)
+ rtype = ZEBRA_ROUTE_MAX;
+ else
+ rtype = proto_name2num(proto);
+
+ /* deleting an existing entry, it can't be invalid */
+ assert(rtype >= 0);
+ assert(safi == SAFI_UNICAST);
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ vrf = nb_running_get_entry(args->dnode, NULL, true);
+
+ ip_nht_rm_del(vrf->info, rmap, rtype, afi);
+
+ return NB_OK;
+}
+
+void lib_vrf_zebra_filter_nht_apply_finish(struct nb_cb_apply_finish_args *args)
+{
+ struct vrf *vrf;
+ const char *afi_safi = yang_dnode_get_string(args->dnode, "afi-safi");
+ const char *proto = yang_dnode_get_string(args->dnode, "protocol");
+ const char *rmap = yang_dnode_get_string(args->dnode, "route-map");
+ afi_t afi;
+ safi_t safi;
+ int rtype;
+
+ yang_afi_safi_identity2value(afi_safi, &afi, &safi);
+
+ if (strcasecmp(proto, "any") == 0)
+ rtype = ZEBRA_ROUTE_MAX;
+ else
+ rtype = proto_name2num(proto);
+
+ /* finishing apply for an existing entry, it can't be invalid */
+ assert(rtype >= 0);
+ assert(safi == SAFI_UNICAST);
+
+ vrf = nb_running_get_entry(args->dnode, NULL, true);
+
+ ip_nht_rm_add(vrf->info, rmap, rtype, afi);
+}
+
+/*
+ * XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/filter-nht/route-map
+ */
+int lib_vrf_zebra_filter_nht_route_map_modify(struct nb_cb_modify_args *args)
+{
+ /* the update is done in the apply_finish callback */
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/resolve-via-default
+ */
+int lib_vrf_zebra_resolve_via_default_modify(struct nb_cb_modify_args *args)
+{
+ struct vrf *vrf;
+ struct zebra_vrf *zvrf;
+ bool resolve_via_default;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ vrf = nb_running_get_entry(args->dnode, NULL, true);
+ zvrf = vrf->info;
+
+ resolve_via_default = yang_dnode_get_bool(args->dnode, NULL);
+
+ if (zvrf->zebra_rnh_ip_default_route == resolve_via_default)
+ return NB_OK;
+
+ zvrf->zebra_rnh_ip_default_route = resolve_via_default;
+
+ zebra_evaluate_rnh(zvrf, AFI_IP, 0, NULL, SAFI_UNICAST);
+
+ return NB_OK;
+}
+
+int lib_vrf_zebra_resolve_via_default_destroy(struct nb_cb_destroy_args *args)
+{
+ struct vrf *vrf;
+ struct zebra_vrf *zvrf;
+ bool resolve_via_default;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ vrf = nb_running_get_entry(args->dnode, NULL, true);
+ zvrf = vrf->info;
+
+ resolve_via_default = DFLT_ZEBRA_IP_NHT_RESOLVE_VIA_DEFAULT;
+
+ if (zvrf->zebra_rnh_ip_default_route == resolve_via_default)
+ return NB_OK;
+
+ zvrf->zebra_rnh_ip_default_route = resolve_via_default;
+
+ zebra_evaluate_rnh(zvrf, AFI_IP, 0, NULL, SAFI_UNICAST);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/ipv6-resolve-via-default
+ */
+int lib_vrf_zebra_ipv6_resolve_via_default_modify(struct nb_cb_modify_args *args)
+{
+ struct vrf *vrf;
+ struct zebra_vrf *zvrf;
+ bool resolve_via_default;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ vrf = nb_running_get_entry(args->dnode, NULL, true);
+ zvrf = vrf->info;
+
+ resolve_via_default = yang_dnode_get_bool(args->dnode, NULL);
+
+ if (zvrf->zebra_rnh_ipv6_default_route == resolve_via_default)
+ return NB_OK;
+
+ zvrf->zebra_rnh_ipv6_default_route = resolve_via_default;
+
+ zebra_evaluate_rnh(zvrf, AFI_IP6, 0, NULL, SAFI_UNICAST);
+
+ return NB_OK;
+}
+
+int lib_vrf_zebra_ipv6_resolve_via_default_destroy(struct nb_cb_destroy_args *args)
+{
+ struct vrf *vrf;
+ struct zebra_vrf *zvrf;
+ bool resolve_via_default;
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ vrf = nb_running_get_entry(args->dnode, NULL, true);
+ zvrf = vrf->info;
+
+ resolve_via_default = DFLT_ZEBRA_IP_NHT_RESOLVE_VIA_DEFAULT;
+
+ if (zvrf->zebra_rnh_ipv6_default_route == resolve_via_default)
+ return NB_OK;
+
+ zvrf->zebra_rnh_ipv6_default_route = resolve_via_default;
+
+ zebra_evaluate_rnh(zvrf, AFI_IP6, 0, NULL, SAFI_UNICAST);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/netns/table-range
+ */
+static int table_range_validate(uint32_t start, uint32_t end, char *errmsg,
+ size_t errmsg_len)
+{
+#if defined(GNU_LINUX)
+ if ((start >= RT_TABLE_ID_COMPAT && start <= RT_TABLE_ID_LOCAL) ||
+ (end >= RT_TABLE_ID_COMPAT && end <= RT_TABLE_ID_LOCAL)) {
+ snprintfrr(errmsg, errmsg_len,
+ "Values forbidden in range [%u;%u]",
+ RT_TABLE_ID_COMPAT, RT_TABLE_ID_LOCAL);
+ return NB_ERR_VALIDATION;
+ }
+ if (start < RT_TABLE_ID_COMPAT && end > RT_TABLE_ID_LOCAL) {
+ snprintfrr(errmsg, errmsg_len,
+ "Range overlaps range [%u;%u] forbidden",
+ RT_TABLE_ID_COMPAT, RT_TABLE_ID_LOCAL);
+ return NB_ERR_VALIDATION;
+ }
+#endif
+ return NB_OK;
+}
+
+int lib_vrf_zebra_netns_table_range_create(struct nb_cb_create_args *args)
+{
+ struct vrf *vrf;
+ uint32_t start, end;
+ const char *vrf_name;
+
+ start = yang_dnode_get_uint32(args->dnode, "start");
+ end = yang_dnode_get_uint32(args->dnode, "end");
+
+ if (args->event == NB_EV_VALIDATE) {
+ vrf_name = yang_dnode_get_string(args->dnode, "../../../name");
+ if (!vrf_is_backend_netns() &&
+ strcmp(vrf_name, VRF_DEFAULT_NAME)) {
+ snprintfrr(args->errmsg, args->errmsg_len,
+ "Configuration is not available in non-default VRFs when using VRF-lite backend.");
+ return NB_ERR_VALIDATION;
+ }
+ return table_range_validate(start, end, args->errmsg,
+ args->errmsg_len);
+ }
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ vrf = nb_running_get_entry(args->dnode, NULL, true);
+
+ table_manager_range(true, vrf->info, start, end);
+
+ return NB_OK;
+}
+
+int lib_vrf_zebra_netns_table_range_destroy(struct nb_cb_destroy_args *args)
+{
+ struct vrf *vrf;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ vrf = nb_running_get_entry(args->dnode, NULL, true);
+
+ table_manager_range(false, vrf->info, 0, 0);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/netns/table-range/start
+ */
+int lib_vrf_zebra_netns_table_range_start_modify(struct nb_cb_modify_args *args)
+{
+ struct vrf *vrf;
+ uint32_t start, end;
+
+ start = yang_dnode_get_uint32(args->dnode, NULL);
+ end = yang_dnode_get_uint32(args->dnode, "../end");
+
+ if (args->event == NB_EV_VALIDATE)
+ return table_range_validate(start, end, args->errmsg,
+ args->errmsg_len);
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ vrf = nb_running_get_entry(args->dnode, NULL, true);
+
+ table_manager_range(true, vrf->info, start, end);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/netns/table-range/end
+ */
+int lib_vrf_zebra_netns_table_range_end_modify(struct nb_cb_modify_args *args)
+{
+ struct vrf *vrf;
+ uint32_t start, end;
+
+ start = yang_dnode_get_uint32(args->dnode, "../start");
+ end = yang_dnode_get_uint32(args->dnode, NULL);
+
+ if (args->event == NB_EV_VALIDATE)
+ return table_range_validate(start, end, args->errmsg,
+ args->errmsg_len);
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ vrf = nb_running_get_entry(args->dnode, NULL, true);
+
+ table_manager_range(true, vrf->info, start, end);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/l3vni-id
+ */
+int lib_vrf_zebra_l3vni_id_modify(struct nb_cb_modify_args *args)
+{
+ struct vrf *vrf;
+ vni_t vni = 0;
+ bool pfx_only = false;
+ uint32_t count;
+
+ vni = yang_dnode_get_uint32(args->dnode, NULL);
+
+ switch (args->event) {
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ return NB_OK;
+ case NB_EV_VALIDATE:
+ count = yang_dnode_count(args->dnode,
+ "/frr-vrf:lib/vrf/frr-zebra:zebra[l3vni-id='%u']",
+ vni);
+ if (count > 1) {
+ snprintfrr(args->errmsg, args->errmsg_len,
+ "vni %u is already mapped to another vrf",
+ vni);
+ return NB_ERR_VALIDATION;
+ }
break;
case NB_EV_APPLY:
-
vrf = nb_running_get_entry(args->dnode, NULL, true);
- zvrf = zebra_vrf_lookup_by_name(vrf->name);
- vni = yang_dnode_get_uint32(args->dnode, NULL);
- /* Note: This covers lib_vrf_zebra_prefix_only_modify() config
- * along with l3vni config
- */
pfx_only = yang_dnode_get_bool(args->dnode, "../prefix-only");
- if (zebra_vxlan_process_vrf_vni_cmd(zvrf, vni, err, ERR_STR_SZ,
- pfx_only ? 1 : 0, 1)
- != 0) {
- if (IS_ZEBRA_DEBUG_VXLAN)
- snprintf(
- args->errmsg, args->errmsg_len,
- "vrf vni %u mapping failed with error: %s",
- vni, err);
- return NB_ERR;
- }
-
+ zebra_vxlan_process_vrf_vni_cmd(vrf->info, vni,
+ pfx_only ? 1 : 0, 1);
break;
}
@@ -1476,10 +3821,7 @@ int lib_vrf_zebra_l3vni_id_modify(struct nb_cb_modify_args *args)
int lib_vrf_zebra_l3vni_id_destroy(struct nb_cb_destroy_args *args)
{
struct vrf *vrf;
- struct zebra_vrf *zvrf;
vni_t vni = 0;
- char err[ERR_STR_SZ];
- uint8_t filter = 0;
switch (args->event) {
case NB_EV_PREPARE:
@@ -1488,32 +3830,9 @@ int lib_vrf_zebra_l3vni_id_destroy(struct nb_cb_destroy_args *args)
return NB_OK;
case NB_EV_APPLY:
vrf = nb_running_get_entry(args->dnode, NULL, true);
- zvrf = zebra_vrf_lookup_by_name(vrf->name);
vni = yang_dnode_get_uint32(args->dnode, NULL);
- if (!zl3vni_lookup(vni))
- return NB_OK;
-
- if (zvrf->l3vni != vni) {
- snprintf(args->errmsg, args->errmsg_len,
- "vrf %s has different vni %u mapped",
- vrf->name, zvrf->l3vni);
- return NB_ERR;
- }
-
- if (is_l3vni_for_prefix_routes_only(zvrf->l3vni))
- filter = 1;
-
- if (zebra_vxlan_process_vrf_vni_cmd(zvrf, vni, err, ERR_STR_SZ,
- filter, 0)
- != 0) {
- if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug(
- "vrf vni %u unmapping failed with error: %s",
- vni, err);
- return NB_ERR;
- }
-
+ zebra_vxlan_process_vrf_vni_cmd(vrf->info, vni, 0, 0);
break;
}
diff --git a/zebra/zebra_nb_state.c b/zebra/zebra_nb_state.c
index acf0b80aca..46492f023a 100644
--- a/zebra/zebra_nb_state.c
+++ b/zebra/zebra_nb_state.c
@@ -49,8 +49,46 @@ lib_interface_zebra_state_down_count_get_elem(struct nb_cb_get_elem_args *args)
struct yang_data *
lib_interface_zebra_state_zif_type_get_elem(struct nb_cb_get_elem_args *args)
{
- /* TODO: implement me. */
- return NULL;
+ const struct interface *ifp = args->list_entry;
+ struct zebra_if *zebra_if;
+ const char *type = NULL;
+
+ zebra_if = ifp->info;
+
+ switch (zebra_if->zif_type) {
+ case ZEBRA_IF_OTHER:
+ type = "frr-zebra:zif-other";
+ break;
+ case ZEBRA_IF_VXLAN:
+ type = "frr-zebra:zif-vxlan";
+ break;
+ case ZEBRA_IF_VRF:
+ type = "frr-zebra:zif-vrf";
+ break;
+ case ZEBRA_IF_BRIDGE:
+ type = "frr-zebra:zif-bridge";
+ break;
+ case ZEBRA_IF_VLAN:
+ type = "frr-zebra:zif-vlan";
+ break;
+ case ZEBRA_IF_MACVLAN:
+ type = "frr-zebra:zif-macvlan";
+ break;
+ case ZEBRA_IF_VETH:
+ type = "frr-zebra:zif-veth";
+ break;
+ case ZEBRA_IF_BOND:
+ type = "frr-zebra:zif-bond";
+ break;
+ case ZEBRA_IF_GRE:
+ type = "frr-zebra:zif-gre";
+ break;
+ }
+
+ if (!type)
+ return NULL;
+
+ return yang_data_new_string(args->xpath, type);
}
/*
@@ -145,6 +183,28 @@ lib_interface_zebra_state_mcast_group_get_elem(struct nb_cb_get_elem_args *args)
return yang_data_new_ipv4(args->xpath, &vni->mcast_grp);
}
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/state/bond
+ */
+struct yang_data *
+lib_interface_zebra_state_bond_get_elem(struct nb_cb_get_elem_args *args)
+{
+ const struct interface *ifp = args->list_entry;
+ struct zebra_if *zebra_if;
+ struct interface *bond;
+
+ if (!IS_ZEBRA_IF_BOND_SLAVE(ifp))
+ return NULL;
+
+ zebra_if = ifp->info;
+ bond = zebra_if->bondslave_info.bond_if;
+
+ if (!bond)
+ return NULL;
+
+ return yang_data_new_string(args->xpath, bond->name);
+}
+
const void *lib_vrf_zebra_ribs_rib_get_next(struct nb_cb_get_next_args *args)
{
struct vrf *vrf = (struct vrf *)args->parent_list_entry;
@@ -156,6 +216,8 @@ const void *lib_vrf_zebra_ribs_rib_get_next(struct nb_cb_get_next_args *args)
safi_t safi;
zvrf = zebra_vrf_lookup_by_id(vrf->vrf_id);
+ if (!zvrf)
+ return NULL;
if (args->list_entry == NULL) {
afi = AFI_IP;
@@ -167,7 +229,8 @@ const void *lib_vrf_zebra_ribs_rib_get_next(struct nb_cb_get_next_args *args)
} else {
zrt = RB_NEXT(zebra_router_table_head, zrt);
/* vrf_id/ns_id do not match, only walk for the given VRF */
- while (zrt && zrt->ns_id != zvrf->zns->ns_id)
+ while (zrt && (zrt->tableid != zvrf->table_id ||
+ zrt->ns_id != zvrf->zns->ns_id))
zrt = RB_NEXT(zebra_router_table_head, zrt);
}
@@ -198,6 +261,8 @@ lib_vrf_zebra_ribs_rib_lookup_entry(struct nb_cb_lookup_entry_args *args)
uint32_t table_id = 0;
zvrf = zebra_vrf_lookup_by_id(vrf->vrf_id);
+ if (!zvrf)
+ return NULL;
yang_afi_safi_identity2value(args->keys->key[0], &afi, &safi);
table_id = yang_str2uint32(args->keys->key[1]);
@@ -208,6 +273,28 @@ lib_vrf_zebra_ribs_rib_lookup_entry(struct nb_cb_lookup_entry_args *args)
return zebra_router_find_zrt(zvrf, table_id, afi, safi);
}
+const void *
+lib_vrf_zebra_ribs_rib_lookup_next(struct nb_cb_lookup_entry_args *args)
+{
+ struct vrf *vrf = (struct vrf *)args->parent_list_entry;
+ struct zebra_vrf *zvrf;
+ afi_t afi;
+ safi_t safi;
+ uint32_t table_id = 0;
+
+ zvrf = zebra_vrf_lookup_by_id(vrf->vrf_id);
+ if (!zvrf)
+ return NULL;
+
+ yang_afi_safi_identity2value(args->keys->key[0], &afi, &safi);
+ table_id = yang_str2uint32(args->keys->key[1]);
+ /* table_id 0 assume vrf's table_id. */
+ if (!table_id)
+ table_id = zvrf->table_id;
+
+ return zebra_router_find_next_zrt(zvrf, table_id, afi, safi);
+}
+
/*
* XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/afi-safi-name
*/
@@ -285,6 +372,25 @@ lib_vrf_zebra_ribs_rib_route_lookup_entry(struct nb_cb_lookup_entry_args *args)
return rn;
}
+const void *
+lib_vrf_zebra_ribs_rib_route_lookup_next(struct nb_cb_lookup_entry_args *args)
+{
+ const struct zebra_router_table *zrt = args->parent_list_entry;
+ struct prefix p;
+ struct route_node *rn;
+
+ yang_str2prefix(args->keys->key[0], &p);
+
+ rn = route_table_get_next(zrt->table, &p);
+
+ if (!rn)
+ return NULL;
+
+ route_unlock_node(rn);
+
+ return rn;
+}
+
/*
* XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route/prefix
*/
@@ -502,7 +608,7 @@ struct yang_data *lib_vrf_zebra_ribs_rib_route_route_entry_uptime_get_elem(
{
struct route_entry *re = (struct route_entry *)args->list_entry;
- return yang_data_new_date_and_time(args->xpath, re->uptime);
+ return yang_data_new_date_and_time(args->xpath, re->uptime, true);
}
/*
@@ -842,6 +948,58 @@ lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_color_get_elem(
/*
* XPath:
+ * /frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route/route-entry/nexthop-group/nexthop/srv6-segs-stack/entry
+ */
+const void *
+lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_srv6_segs_stack_entry_get_next(
+ struct nb_cb_get_next_args *args)
+{
+ /* TODO: implement me. */
+ return NULL;
+}
+
+int lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_srv6_segs_stack_entry_get_keys(
+ struct nb_cb_get_keys_args *args)
+{
+ /* TODO: implement me. */
+ return NB_OK;
+}
+
+const void *
+lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_srv6_segs_stack_entry_lookup_entry(
+ struct nb_cb_lookup_entry_args *args)
+{
+ /* TODO: implement me. */
+ return NULL;
+}
+
+/*
+ * XPath:
+ * /frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route/route-entry/nexthop-group/nexthop/srv6-segs-stack/entry/id
+ */
+struct yang_data *
+lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_srv6_segs_stack_entry_id_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ /* TODO: implement me. */
+ return NULL;
+}
+
+/*
+ * XPath:
+ * /frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route/route-entry/nexthop-group/nexthop/srv6-segs-stack/entry/seg
+ */
+struct yang_data *
+lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_srv6_segs_stack_entry_seg_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ /* TODO: implement me. */
+ return NULL;
+}
+
+
+/*
+ * XPath:
* /frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route/route-entry/nexthop-group/nexthop/mpls-label-stack/entry
*/
const void *
diff --git a/zebra/zebra_neigh.c b/zebra/zebra_neigh.c
index 0c3fb97afd..941088afd6 100644
--- a/zebra/zebra_neigh.c
+++ b/zebra/zebra_neigh.c
@@ -152,6 +152,19 @@ void zebra_neigh_del(struct interface *ifp, struct ipaddr *ip)
zebra_neigh_free(n);
}
+/* kernel neigh delete all for a given interface */
+void zebra_neigh_del_all(struct interface *ifp)
+{
+ struct zebra_neigh_ent *n, *nn;
+
+ if (IS_ZEBRA_DEBUG_NEIGH)
+ zlog_debug("zebra neigh delete all for interface %s/%d",
+ ifp->name, ifp->ifindex);
+
+ RB_FOREACH_SAFE (n, zebra_neigh_rb_head, &zneigh_info->neigh_rb_tree, nn)
+ zebra_neigh_del(ifp, &n->ip);
+}
+
/* kernel neigh add */
void zebra_neigh_add(struct interface *ifp, struct ipaddr *ip,
struct ethaddr *mac)
diff --git a/zebra/zebra_neigh.h b/zebra/zebra_neigh.h
index b957b5efe5..adc5f94f76 100644
--- a/zebra/zebra_neigh.h
+++ b/zebra/zebra_neigh.h
@@ -43,6 +43,7 @@ struct zebra_neigh_info {
extern void zebra_neigh_add(struct interface *ifp, struct ipaddr *ip,
struct ethaddr *mac);
extern void zebra_neigh_del(struct interface *ifp, struct ipaddr *ip);
+extern void zebra_neigh_del_all(struct interface *ifp);
extern void zebra_neigh_show(struct vty *vty);
extern void zebra_neigh_init(void);
extern void zebra_neigh_terminate(void);
diff --git a/zebra/zebra_netns_id.c b/zebra/zebra_netns_id.c
index 0531ab9591..1af3a3e857 100644
--- a/zebra/zebra_netns_id.c
+++ b/zebra/zebra_netns_id.c
@@ -5,6 +5,12 @@
*/
#include <zebra.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#ifdef GNU_LINUX
+#include <linux/if_link.h>
+#endif
#include "ns.h"
#include "vrf.h"
diff --git a/zebra/zebra_netns_notify.c b/zebra/zebra_netns_notify.c
index 4260d29c43..1bb1292e34 100644
--- a/zebra/zebra_netns_notify.c
+++ b/zebra/zebra_netns_notify.c
@@ -5,6 +5,7 @@
*/
#include <zebra.h>
+#include <fcntl.h>
#ifdef HAVE_NETLINK
#ifdef HAVE_NETNS
diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c
index 8616b14050..934b8ba0db 100644
--- a/zebra/zebra_nhg.c
+++ b/zebra/zebra_nhg.c
@@ -72,25 +72,13 @@ static uint32_t nhg_get_next_id(void)
while (1) {
id_counter++;
- if (IS_ZEBRA_DEBUG_NHG_DETAIL)
- zlog_debug("%s: ID %u checking", __func__, id_counter);
-
if (id_counter == ZEBRA_NHG_PROTO_LOWER) {
- if (IS_ZEBRA_DEBUG_NHG_DETAIL)
- zlog_debug("%s: ID counter wrapped", __func__);
-
id_counter = 0;
continue;
}
- if (zebra_nhg_lookup_id(id_counter)) {
- if (IS_ZEBRA_DEBUG_NHG_DETAIL)
- zlog_debug("%s: ID already exists", __func__);
-
- continue;
- }
-
- break;
+ if (!zebra_nhg_lookup_id(id_counter))
+ break;
}
return id_counter;
@@ -321,8 +309,10 @@ static int zebra_nhg_insert_id(struct nhg_hash_entry *nhe)
static void zebra_nhg_set_if(struct nhg_hash_entry *nhe, struct interface *ifp)
{
+ struct zebra_if *zif = (struct zebra_if *)ifp->info;
+
nhe->ifp = ifp;
- if_nhg_dependents_add(ifp, nhe);
+ nhg_connected_tree_add_nhe(&zif->nhg_dependents, nhe);
}
static void
@@ -690,12 +680,6 @@ static bool zebra_nhe_find(struct nhg_hash_entry **nhe, /* return value */
struct nhg_hash_entry *newnhe, *backup_nhe;
struct nexthop *nh = NULL;
- if (IS_ZEBRA_DEBUG_NHG_DETAIL)
- zlog_debug(
- "%s: id %u, lookup %p, vrf %d, type %d, depends %p%s",
- __func__, lookup->id, lookup, lookup->vrf_id,
- lookup->type, nhg_depends,
- (from_dplane ? " (from dplane)" : ""));
if (lookup->id)
(*nhe) = zebra_nhg_lookup_id(lookup->id);
@@ -703,7 +687,10 @@ static bool zebra_nhe_find(struct nhg_hash_entry **nhe, /* return value */
(*nhe) = hash_lookup(zrouter.nhgs, lookup);
if (IS_ZEBRA_DEBUG_NHG_DETAIL)
- zlog_debug("%s: lookup => %p (%pNG)", __func__, *nhe, *nhe);
+ zlog_debug("%s: id %u, lookup %p, vrf %d, type %d, depends %p%s => Found %p(%pNG)",
+ __func__, lookup->id, lookup, lookup->vrf_id,
+ lookup->type, nhg_depends,
+ (from_dplane ? " (from dplane)" : ""), *nhe, *nhe);
/* If we found an existing object, we're done */
if (*nhe)
@@ -1046,31 +1033,25 @@ static struct nhg_ctx *nhg_ctx_init(uint32_t id, struct nexthop *nh,
return ctx;
}
-static void zebra_nhg_set_valid(struct nhg_hash_entry *nhe)
-{
- struct nhg_connected *rb_node_dep;
-
- SET_FLAG(nhe->flags, NEXTHOP_GROUP_VALID);
-
- frr_each(nhg_connected_tree, &nhe->nhg_dependents, rb_node_dep)
- zebra_nhg_set_valid(rb_node_dep->nhe);
-}
-
-static void zebra_nhg_set_invalid(struct nhg_hash_entry *nhe)
+static void zebra_nhg_set_valid(struct nhg_hash_entry *nhe, bool valid)
{
struct nhg_connected *rb_node_dep;
- UNSET_FLAG(nhe->flags, NEXTHOP_GROUP_VALID);
+ if (valid)
+ SET_FLAG(nhe->flags, NEXTHOP_GROUP_VALID);
+ else {
+ UNSET_FLAG(nhe->flags, NEXTHOP_GROUP_VALID);
- /* If we're in shutdown, this interface event needs to clean
- * up installed NHGs, so don't clear that flag directly.
- */
- if (!zebra_router_in_shutdown())
- UNSET_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED);
+ /* If we're in shutdown, this interface event needs to clean
+ * up installed NHGs, so don't clear that flag directly.
+ */
+ if (!zebra_router_in_shutdown())
+ UNSET_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED);
+ }
/* Update validity of nexthops depending on it */
frr_each(nhg_connected_tree, &nhe->nhg_dependents, rb_node_dep)
- zebra_nhg_check_valid(rb_node_dep->nhe);
+ zebra_nhg_set_valid(rb_node_dep->nhe, valid);
}
void zebra_nhg_check_valid(struct nhg_hash_entry *nhe)
@@ -1082,15 +1063,11 @@ void zebra_nhg_check_valid(struct nhg_hash_entry *nhe)
frr_each(nhg_connected_tree, &nhe->nhg_depends, rb_node_dep) {
if (CHECK_FLAG(rb_node_dep->nhe->flags, NEXTHOP_GROUP_VALID)) {
valid = true;
- goto done;
+ break;
}
}
-done:
- if (valid)
- zebra_nhg_set_valid(nhe);
- else
- zebra_nhg_set_invalid(nhe);
+ zebra_nhg_set_valid(nhe, valid);
}
static void zebra_nhg_release_all_deps(struct nhg_hash_entry *nhe)
@@ -1098,8 +1075,11 @@ static void zebra_nhg_release_all_deps(struct nhg_hash_entry *nhe)
/* Remove it from any lists it may be on */
zebra_nhg_depends_release(nhe);
zebra_nhg_dependents_release(nhe);
- if (nhe->ifp)
- if_nhg_dependents_del(nhe->ifp, nhe);
+ if (nhe->ifp) {
+ struct zebra_if *zif = nhe->ifp->info;
+
+ nhg_connected_tree_del_nhe(&zif->nhg_dependents, nhe);
+ }
}
static void zebra_nhg_release(struct nhg_hash_entry *nhe)
@@ -1125,13 +1105,23 @@ static void zebra_nhg_handle_uninstall(struct nhg_hash_entry *nhe)
zebra_nhg_free(nhe);
}
-static void zebra_nhg_handle_install(struct nhg_hash_entry *nhe)
+static void zebra_nhg_handle_install(struct nhg_hash_entry *nhe, bool install)
{
/* Update validity of groups depending on it */
struct nhg_connected *rb_node_dep;
- frr_each_safe(nhg_connected_tree, &nhe->nhg_dependents, rb_node_dep)
- zebra_nhg_set_valid(rb_node_dep->nhe);
+ frr_each_safe (nhg_connected_tree, &nhe->nhg_dependents, rb_node_dep) {
+ zebra_nhg_set_valid(rb_node_dep->nhe, true);
+ /* install dependent NHG into kernel */
+ if (install) {
+ if (IS_ZEBRA_DEBUG_NHG_DETAIL)
+ zlog_debug(
+ "%s nh id %u (flags 0x%x) associated dependent NHG %pNG install",
+ __func__, nhe->id, nhe->flags,
+ rb_node_dep->nhe);
+ zebra_nhg_install_kernel(rb_node_dep->nhe);
+ }
+ }
}
/*
@@ -1300,6 +1290,7 @@ int nhg_ctx_process(struct nhg_ctx *ctx)
break;
case NHG_CTX_OP_DEL:
ret = nhg_ctx_process_del(ctx);
+ break;
case NHG_CTX_OP_NONE:
break;
}
@@ -1515,19 +1506,23 @@ zebra_nhg_rib_find_nhe(struct nhg_hash_entry *rt_nhe, afi_t rt_afi)
{
struct nhg_hash_entry *nhe = NULL;
- if (!(rt_nhe && rt_nhe->nhg.nexthop)) {
+ if (!rt_nhe) {
flog_err(EC_ZEBRA_TABLE_LOOKUP_FAILED,
- "No nexthop passed to %s", __func__);
+ "No nhg_hash_entry passed to %s", __func__);
return NULL;
}
- if (IS_ZEBRA_DEBUG_NHG_DETAIL)
- zlog_debug("%s: rt_nhe %p (%pNG)", __func__, rt_nhe, rt_nhe);
+ if (!rt_nhe->nhg.nexthop) {
+ flog_err(EC_ZEBRA_TABLE_LOOKUP_FAILED,
+ "No nexthop passed to %s", __func__);
+ return NULL;
+ }
zebra_nhe_find(&nhe, rt_nhe, NULL, rt_afi, false);
if (IS_ZEBRA_DEBUG_NHG_DETAIL)
- zlog_debug("%s: => nhe %p (%pNG)", __func__, nhe, nhe);
+ zlog_debug("%s: rt_nhe %p(%pNG) => nhe %p(%pNG)", __func__,
+ rt_nhe, rt_nhe, nhe, nhe);
return nhe;
}
@@ -1858,11 +1853,18 @@ static struct nexthop *nexthop_set_resolved(afi_t afi,
labels);
if (nexthop->nh_srv6) {
- nexthop_add_srv6_seg6local(resolved_hop,
- nexthop->nh_srv6->seg6local_action,
- &nexthop->nh_srv6->seg6local_ctx);
- nexthop_add_srv6_seg6(resolved_hop,
- &nexthop->nh_srv6->seg6_segs);
+ if (nexthop->nh_srv6->seg6local_action !=
+ ZEBRA_SEG6_LOCAL_ACTION_UNSPEC)
+ nexthop_add_srv6_seg6local(resolved_hop,
+ nexthop->nh_srv6
+ ->seg6local_action,
+ &nexthop->nh_srv6
+ ->seg6local_ctx);
+ if (nexthop->nh_srv6->seg6_segs)
+ nexthop_add_srv6_seg6(resolved_hop,
+ &nexthop->nh_srv6->seg6_segs->seg[0],
+ nexthop->nh_srv6->seg6_segs
+ ->num_segs);
}
resolved_hop->rparent = nexthop;
@@ -2111,7 +2113,8 @@ zebra_nhg_connected_ifindex(struct route_node *rn, struct route_entry *match,
* of those ifindexes match as well.
*/
RNODE_FOREACH_RE (rn, re) {
- if (re->type != ZEBRA_ROUTE_CONNECT)
+ if (re->type != ZEBRA_ROUTE_CONNECT &&
+ re->type != ZEBRA_ROUTE_LOCAL)
continue;
if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED))
@@ -2171,11 +2174,7 @@ static int nexthop_active(struct nexthop *nexthop, struct nhg_hash_entry *nhe,
case NEXTHOP_TYPE_IFINDEX:
ifp = if_lookup_by_index(nexthop->ifindex, nexthop->vrf_id);
- /*
- * If the interface exists and its operative or its a kernel
- * route and interface is up, its active. We trust kernel routes
- * to be good.
- */
+ /* If the interface exists and its operative, it's active */
if (ifp && (if_is_operative(ifp)))
return 1;
else
@@ -2234,20 +2233,6 @@ static int nexthop_active(struct nexthop *nexthop, struct nhg_hash_entry *nhe,
return 1;
}
- if (top &&
- ((top->family == AF_INET && top->prefixlen == IPV4_MAX_BITLEN &&
- nexthop->gate.ipv4.s_addr == top->u.prefix4.s_addr) ||
- (top->family == AF_INET6 && top->prefixlen == IPV6_MAX_BITLEN &&
- memcmp(&nexthop->gate.ipv6, &top->u.prefix6, IPV6_MAX_BYTELEN) ==
- 0)) &&
- nexthop->vrf_id == vrf_id) {
- if (IS_ZEBRA_DEBUG_RIB_DETAILED)
- zlog_debug(
- " :%s: Attempting to install a max prefixlength route through itself",
- __func__);
- return 0;
- }
-
/* Validation for ipv4 mapped ipv6 nexthop. */
if (IS_MAPPED_IPV6(&nexthop->gate.ipv6)) {
afi = AFI_IP;
@@ -2350,7 +2335,7 @@ static int nexthop_active(struct nexthop *nexthop, struct nhg_hash_entry *nhe,
zlog_debug(
" %s: Matched against ourself and prefix length is not max bit length",
__func__);
- return 0;
+ goto continue_up_tree;
}
/* Pick up selected route. */
@@ -2360,60 +2345,58 @@ static int nexthop_active(struct nexthop *nexthop, struct nhg_hash_entry *nhe,
if (is_default_prefix(&rn->p)
&& !rnh_resolve_via_default(zvrf, p.family)) {
if (IS_ZEBRA_DEBUG_RIB_DETAILED)
- zlog_debug(
- " :%s: Resolved against default route",
- __func__);
+ zlog_debug(" :%s: %pFX Resolved against default route",
+ __func__, &p);
return 0;
}
dest = rib_dest_from_rnode(rn);
- if (dest && dest->selected_fib
- && !CHECK_FLAG(dest->selected_fib->status,
- ROUTE_ENTRY_REMOVED)
- && dest->selected_fib->type != ZEBRA_ROUTE_TABLE)
+ if (dest && dest->selected_fib &&
+ (!CHECK_FLAG(dest->selected_fib->status,
+ ROUTE_ENTRY_REMOVED) ||
+ CHECK_FLAG(dest->selected_fib->status,
+ ROUTE_ENTRY_ROUTE_REPLACING)) &&
+ dest->selected_fib->type != ZEBRA_ROUTE_TABLE)
match = dest->selected_fib;
/* If there is no selected route or matched route is EGP, go up
* tree.
*/
- if (!match) {
- do {
- rn = rn->parent;
- } while (rn && rn->info == NULL);
- if (rn)
- route_lock_node(rn);
-
- continue;
- }
- if ((match->type == ZEBRA_ROUTE_CONNECT) ||
- (RIB_SYSTEM_ROUTE(match) && RSYSTEM_ROUTE(type))) {
+ /* If the candidate match's type is considered "connected",
+ * we consider it first.
+ */
+ if (match && (RIB_CONNECTED_ROUTE(match) ||
+ (RIB_SYSTEM_ROUTE(match) && RSYSTEM_ROUTE(type)))) {
match = zebra_nhg_connected_ifindex(rn, match,
nexthop->ifindex);
newhop = match->nhe->nhg.nexthop;
- if (nexthop->type == NEXTHOP_TYPE_IPV4 ||
- nexthop->type == NEXTHOP_TYPE_IPV6)
+ if (nexthop->type == NEXTHOP_TYPE_IPV4) {
+ nexthop->ifindex = newhop->ifindex;
+ nexthop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
+ } else if (nexthop->type == NEXTHOP_TYPE_IPV6) {
nexthop->ifindex = newhop->ifindex;
- else if (nexthop->ifindex != newhop->ifindex) {
+ nexthop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
+ } else if (nexthop->ifindex != newhop->ifindex) {
if (IS_ZEBRA_DEBUG_RIB_DETAILED)
zlog_debug(
"%s: %pNHv given ifindex does not match nexthops ifindex found: %pNHv",
__func__, nexthop, newhop);
- /*
- * NEXTHOP_TYPE_*_IFINDEX but ifindex
- * doesn't match what we found.
- */
- return 0;
+ goto continue_up_tree;
}
+ /* NHRP special case: need to indicate onlink */
+ if (match->type == ZEBRA_ROUTE_NHRP)
+ SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK);
+
if (IS_ZEBRA_DEBUG_NHG_DETAIL)
zlog_debug(
"%s: CONNECT match %p (%pNG), newhop %pNHv",
__func__, match, match->nhe, newhop);
return 1;
- } else if (CHECK_FLAG(flags, ZEBRA_FLAG_ALLOW_RECURSION)) {
+ } else if (match && CHECK_FLAG(flags, ZEBRA_FLAG_ALLOW_RECURSION)) {
struct nexthop_group *nhg;
struct nexthop *resolver;
struct backup_nh_map_s map = {};
@@ -2449,6 +2432,10 @@ static int nexthop_active(struct nexthop *nexthop, struct nhg_hash_entry *nhe,
"%s: match %p (%pNG) not installed or being Route Replaced",
__func__, match, match->nhe);
+ if (CHECK_FLAG(match->status,
+ ROUTE_ENTRY_QUEUED))
+ goto continue_up_tree;
+
goto done_with_match;
}
@@ -2517,25 +2504,37 @@ done_with_match:
if (pmtu)
*pmtu = match->mtu;
- } else if (IS_ZEBRA_DEBUG_RIB_DETAILED)
- zlog_debug(
- " %s: Recursion failed to find",
- __func__);
-
- return resolved;
- } else {
- if (IS_ZEBRA_DEBUG_RIB_DETAILED) {
- zlog_debug(
- " %s: Route Type %s has not turned on recursion",
- __func__, zebra_route_string(type));
- if (type == ZEBRA_ROUTE_BGP
- && !CHECK_FLAG(flags, ZEBRA_FLAG_IBGP))
+ } else {
+ if (IS_ZEBRA_DEBUG_RIB_DETAILED)
zlog_debug(
- " EBGP: see \"disable-ebgp-connected-route-check\" or \"disable-connected-check\"");
+ " %s: Recursion failed to find while looking at %pRN",
+ __func__, rn);
+ goto continue_up_tree;
}
- return 0;
+
+ return 1;
+ } else if (IS_ZEBRA_DEBUG_RIB_DETAILED) {
+ zlog_debug(
+ " %s: Route Type %s has not turned on recursion %pRN failed to match",
+ __func__, zebra_route_string(type), rn);
+ if (type == ZEBRA_ROUTE_BGP
+ && !CHECK_FLAG(flags, ZEBRA_FLAG_IBGP))
+ zlog_debug(
+ " EBGP: see \"disable-ebgp-connected-route-check\" or \"disable-connected-check\"");
}
+
+ continue_up_tree:
+ /*
+ * If there is no selected route or matched route is EGP, go up
+ * tree.
+ */
+ do {
+ rn = rn->parent;
+ } while (rn && rn->info == NULL);
+ if (rn)
+ route_lock_node(rn);
}
+
if (IS_ZEBRA_DEBUG_RIB_DETAILED)
zlog_debug(" %s: Nexthop did not lookup in table",
__func__);
@@ -2576,6 +2575,8 @@ static unsigned nexthop_active_check(struct route_node *rn,
if (IS_ZEBRA_DEBUG_NHG_DETAIL)
zlog_debug("%s: re %p, nexthop %pNHv", __func__, re, nexthop);
+ vrf_id = zvrf_id(rib_dest_vrf(rib_dest_from_rnode(rn)));
+
/*
* If this is a kernel route, then if the interface is *up* then
* by golly gee whiz it's a good route.
@@ -2585,13 +2586,12 @@ static unsigned nexthop_active_check(struct route_node *rn,
ifp = if_lookup_by_index(nexthop->ifindex, nexthop->vrf_id);
- if (ifp && (if_is_operative(ifp) || if_is_up(ifp))) {
+ if (ifp && ifp->vrf->vrf_id == vrf_id && if_is_up(ifp)) {
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE);
goto skip_check;
}
}
- vrf_id = zvrf_id(rib_dest_vrf(rib_dest_from_rnode(rn)));
switch (nexthop->type) {
case NEXTHOP_TYPE_IFINDEX:
if (nexthop_active(nexthop, nhe, &rn->p, re->type, re->flags,
@@ -2686,8 +2686,7 @@ skip_check:
}
/* It'll get set if required inside */
- ret = zebra_route_map_check(family, re->type, re->instance, p, nexthop,
- zvrf, re->tag);
+ ret = zebra_route_map_check(family, re, p, nexthop, zvrf);
if (ret == RMAP_DENYMATCH) {
if (IS_ZEBRA_DEBUG_RIB) {
zlog_debug(
@@ -3080,19 +3079,26 @@ void zebra_nhg_install_kernel(struct nhg_hash_entry *nhe)
/* Resolve it first */
nhe = zebra_nhg_resolve(nhe);
+ if (zebra_nhg_set_valid_if_active(nhe)) {
+ if (IS_ZEBRA_DEBUG_NHG_DETAIL)
+ zlog_debug("%s: valid flag set for nh %pNG", __func__,
+ nhe);
+ }
+
/* Make sure all depends are installed/queued */
frr_each(nhg_connected_tree, &nhe->nhg_depends, rb_node_dep) {
zebra_nhg_install_kernel(rb_node_dep->nhe);
}
- if (CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_VALID)
- && !CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED)
- && !CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_QUEUED)) {
+ if (CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_VALID) &&
+ (!CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED) ||
+ CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_REINSTALL)) &&
+ !CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_QUEUED)) {
/* Change its type to us since we are installing it */
if (!ZEBRA_NHG_CREATED(nhe))
nhe->type = ZEBRA_ROUTE_NHG;
- int ret = dplane_nexthop_add(nhe);
+ enum zebra_dplane_result ret = dplane_nexthop_add(nhe);
switch (ret) {
case ZEBRA_DPLANE_REQUEST_QUEUED:
@@ -3105,8 +3111,9 @@ void zebra_nhg_install_kernel(struct nhg_hash_entry *nhe)
nhe);
break;
case ZEBRA_DPLANE_REQUEST_SUCCESS:
- SET_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED);
- zebra_nhg_handle_install(nhe);
+ flog_err(EC_ZEBRA_DP_INVALID_RC,
+ "DPlane returned an invalid result code for attempt of installation of %pNG into the kernel",
+ nhe);
break;
}
}
@@ -3153,8 +3160,7 @@ void zebra_nhg_dplane_result(struct zebra_dplane_ctx *ctx)
"Nexthop dplane ctx %p, op %s, nexthop ID (%u), result %s",
ctx, dplane_op2str(op), id, dplane_res2str(status));
- switch (op) {
- case DPLANE_OP_NH_DELETE:
+ if (op == DPLANE_OP_NH_DELETE) {
if (status != ZEBRA_DPLANE_REQUEST_SUCCESS)
flog_err(
EC_ZEBRA_DP_DELETE_FAIL,
@@ -3162,32 +3168,32 @@ void zebra_nhg_dplane_result(struct zebra_dplane_ctx *ctx)
id);
/* We already free'd the data, nothing to do */
- break;
- case DPLANE_OP_NH_INSTALL:
- case DPLANE_OP_NH_UPDATE:
+ } else if (op == DPLANE_OP_NH_INSTALL || op == DPLANE_OP_NH_UPDATE) {
nhe = zebra_nhg_lookup_id(id);
if (!nhe) {
if (IS_ZEBRA_DEBUG_NHG)
- zlog_debug(
- "%s operation preformed on Nexthop ID (%u) in the kernel, that we no longer have in our table",
- dplane_op2str(op), id);
+ zlog_debug("%s operation performed on Nexthop ID (%u) in the kernel, that we no longer have in our table",
+ dplane_op2str(op), id);
- break;
+ return;
}
UNSET_FLAG(nhe->flags, NEXTHOP_GROUP_QUEUED);
- if (status == ZEBRA_DPLANE_REQUEST_SUCCESS) {
- SET_FLAG(nhe->flags, NEXTHOP_GROUP_VALID);
+ UNSET_FLAG(nhe->flags, NEXTHOP_GROUP_REINSTALL);
+ switch (status) {
+ case ZEBRA_DPLANE_REQUEST_SUCCESS:
SET_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED);
- zebra_nhg_handle_install(nhe);
+ zebra_nhg_handle_install(nhe, true);
/* If daemon nhg, send it an update */
if (PROTO_OWNED(nhe))
zsend_nhg_notify(nhe->type, nhe->zapi_instance,
nhe->zapi_session, nhe->id,
ZAPI_NHG_INSTALLED);
- } else {
+ break;
+ case ZEBRA_DPLANE_REQUEST_FAILURE:
+ UNSET_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED);
/* If daemon nhg, send it an update */
if (PROTO_OWNED(nhe))
zsend_nhg_notify(nhe->type, nhe->zapi_instance,
@@ -3200,61 +3206,13 @@ void zebra_nhg_dplane_result(struct zebra_dplane_ctx *ctx)
EC_ZEBRA_DP_INSTALL_FAIL,
"Failed to install Nexthop (%pNG) into the kernel",
nhe);
+ break;
+ case ZEBRA_DPLANE_REQUEST_QUEUED:
+ flog_err(EC_ZEBRA_DP_INVALID_RC,
+ "Dplane returned an invalid result code for a result from the dplane for %pNG into the kernel",
+ nhe);
+ break;
}
- break;
-
- case DPLANE_OP_ROUTE_INSTALL:
- case DPLANE_OP_ROUTE_UPDATE:
- case DPLANE_OP_ROUTE_DELETE:
- case DPLANE_OP_ROUTE_NOTIFY:
- case DPLANE_OP_LSP_INSTALL:
- case DPLANE_OP_LSP_UPDATE:
- case DPLANE_OP_LSP_DELETE:
- case DPLANE_OP_LSP_NOTIFY:
- case DPLANE_OP_PW_INSTALL:
- case DPLANE_OP_PW_UNINSTALL:
- case DPLANE_OP_SYS_ROUTE_ADD:
- case DPLANE_OP_SYS_ROUTE_DELETE:
- case DPLANE_OP_ADDR_INSTALL:
- case DPLANE_OP_ADDR_UNINSTALL:
- case DPLANE_OP_MAC_INSTALL:
- case DPLANE_OP_MAC_DELETE:
- case DPLANE_OP_NEIGH_INSTALL:
- case DPLANE_OP_NEIGH_UPDATE:
- case DPLANE_OP_NEIGH_DELETE:
- case DPLANE_OP_NEIGH_IP_INSTALL:
- case DPLANE_OP_NEIGH_IP_DELETE:
- case DPLANE_OP_VTEP_ADD:
- case DPLANE_OP_VTEP_DELETE:
- case DPLANE_OP_RULE_ADD:
- case DPLANE_OP_RULE_DELETE:
- case DPLANE_OP_RULE_UPDATE:
- case DPLANE_OP_NEIGH_DISCOVER:
- case DPLANE_OP_BR_PORT_UPDATE:
- case DPLANE_OP_NONE:
- case DPLANE_OP_IPTABLE_ADD:
- case DPLANE_OP_IPTABLE_DELETE:
- case DPLANE_OP_IPSET_ADD:
- case DPLANE_OP_IPSET_DELETE:
- case DPLANE_OP_IPSET_ENTRY_ADD:
- case DPLANE_OP_IPSET_ENTRY_DELETE:
- case DPLANE_OP_NEIGH_TABLE_UPDATE:
- case DPLANE_OP_GRE_SET:
- case DPLANE_OP_INTF_ADDR_ADD:
- case DPLANE_OP_INTF_ADDR_DEL:
- case DPLANE_OP_INTF_NETCONFIG:
- case DPLANE_OP_INTF_INSTALL:
- case DPLANE_OP_INTF_UPDATE:
- case DPLANE_OP_INTF_DELETE:
- case DPLANE_OP_TC_QDISC_INSTALL:
- case DPLANE_OP_TC_QDISC_UNINSTALL:
- case DPLANE_OP_TC_CLASS_ADD:
- case DPLANE_OP_TC_CLASS_DELETE:
- case DPLANE_OP_TC_CLASS_UPDATE:
- case DPLANE_OP_TC_FILTER_ADD:
- case DPLANE_OP_TC_FILTER_DELETE:
- case DPLANE_OP_TC_FILTER_UPDATE:
- break;
}
}
@@ -3397,6 +3355,7 @@ struct nhg_hash_entry *zebra_nhg_proto_add(uint32_t id, int type,
struct nhg_connected *rb_node_dep = NULL;
struct nexthop *newhop;
bool replace = false;
+ int ret = 0;
if (!nhg->nexthop) {
if (IS_ZEBRA_DEBUG_NHG)
@@ -3494,22 +3453,31 @@ struct nhg_hash_entry *zebra_nhg_proto_add(uint32_t id, int type,
if (CHECK_FLAG(old->flags, NEXTHOP_GROUP_PROTO_RELEASED))
zebra_nhg_increment_ref(old);
- rib_handle_nhg_replace(old, new);
+ ret = rib_handle_nhg_replace(old, new);
+ if (ret)
+ /*
+ * if ret > 0, some previous re->nhe has freed the
+ * address to which old_entry is pointing. Hence mark
+ * the old NHE as NULL
+ */
+ old = NULL;
+ else {
+ /* We have to decrement its singletons
+ * because some might not exist in NEW.
+ */
+ if (!zebra_nhg_depends_is_empty(old)) {
+ frr_each (nhg_connected_tree, &old->nhg_depends,
+ rb_node_dep)
+ zebra_nhg_decrement_ref(
+ rb_node_dep->nhe);
+ }
- /* We have to decrement its singletons
- * because some might not exist in NEW.
- */
- if (!zebra_nhg_depends_is_empty(old)) {
- frr_each (nhg_connected_tree, &old->nhg_depends,
- rb_node_dep)
- zebra_nhg_decrement_ref(rb_node_dep->nhe);
+ /* Dont call the dec API, we dont want to uninstall the ID */
+ old->refcnt = 0;
+ EVENT_OFF(old->timer);
+ zebra_nhg_free(old);
+ old = NULL;
}
-
- /* Dont call the dec API, we dont want to uninstall the ID */
- old->refcnt = 0;
- EVENT_OFF(old->timer);
- zebra_nhg_free(old);
- old = NULL;
}
if (IS_ZEBRA_DEBUG_NHG_DETAIL)
@@ -3614,7 +3582,18 @@ unsigned long zebra_nhg_score_proto(int type)
* This should be the last ref if we remove client routes too,
* and thus should remove and free them.
*/
- zebra_nhg_decrement_ref(nhe);
+ if (!CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_PROTO_RELEASED))
+ zebra_nhg_decrement_ref(nhe);
+ else {
+
+ /* protocol sends explicit delete of nhg, the
+ * nhe->refcount is decremented in zread_nhg_del()
+ */
+ if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+ zlog_debug(
+ "%s: nhe %u (%p) refcount %u already decremented in zread_nhg_del",
+ __func__, nhe->id, nhe, nhe->refcnt);
+ }
}
count = iter.found->count;
@@ -3651,3 +3630,70 @@ static ssize_t printfrr_nhghe(struct fbuf *buf, struct printfrr_eargs *ea,
ret += bputs(buf, "]");
return ret;
}
+
+/*
+ * On interface add the nexthop that resolves to this intf needs
+ * a re-install. There are following scenarios when the nexthop group update
+ * gets skipped:
+ * 1. When upper level protocol sends removal of NHG, there is
+ * timer running to keep NHG for 180 seconds, during this interval, same route
+ * with same set of nexthops installation is given , the same NHG is used
+ * but since NHG is not reinstalled on interface address add, it is not aware
+ * in Dplan/Kernel.
+ * 2. Due to a quick port flap due to interface add and delete
+ * to be processed in same queue one after another. Zebra believes that
+ * there is no change in nhg in this case. Hence this re-install will
+ * make sure the nexthop group gets updated to Dplan/Kernel.
+ */
+void zebra_interface_nhg_reinstall(struct interface *ifp)
+{
+ struct nhg_connected *rb_node_dep = NULL;
+ struct zebra_if *zif = ifp->info;
+ struct nexthop *nh;
+
+ if (IS_ZEBRA_DEBUG_NHG_DETAIL)
+ zlog_debug(
+ "%s: Installing interface %s associated NHGs into kernel",
+ __func__, ifp->name);
+
+ frr_each (nhg_connected_tree, &zif->nhg_dependents, rb_node_dep) {
+ nh = rb_node_dep->nhe->nhg.nexthop;
+ if (zebra_nhg_set_valid_if_active(rb_node_dep->nhe)) {
+ if (IS_ZEBRA_DEBUG_NHG_DETAIL)
+ zlog_debug(
+ "%s: Setting the valid flag for nhe %pNG, interface: %s",
+ __func__, rb_node_dep->nhe, ifp->name);
+ }
+ /* Check for singleton NHG associated to interface */
+ if (nexthop_is_ifindex_type(nh) &&
+ zebra_nhg_depends_is_empty(rb_node_dep->nhe)) {
+ struct nhg_connected *rb_node_dependent;
+
+ if (IS_ZEBRA_DEBUG_NHG)
+ zlog_debug(
+ "%s install nhe %pNG nh type %u flags 0x%x",
+ __func__, rb_node_dep->nhe, nh->type,
+ rb_node_dep->nhe->flags);
+ zebra_nhg_install_kernel(rb_node_dep->nhe);
+
+ /* Don't need to modify dependents if installed */
+ if (CHECK_FLAG(rb_node_dep->nhe->flags,
+ NEXTHOP_GROUP_INSTALLED))
+ continue;
+
+ /* mark dependent uninstalled; when interface associated
+ * singleton is installed, install dependent
+ */
+ frr_each_safe (nhg_connected_tree,
+ &rb_node_dep->nhe->nhg_dependents,
+ rb_node_dependent) {
+ if (IS_ZEBRA_DEBUG_NHG)
+ zlog_debug("%s dependent nhe %pNG Setting Reinstall flag",
+ __func__,
+ rb_node_dependent->nhe);
+ SET_FLAG(rb_node_dependent->nhe->flags,
+ NEXTHOP_GROUP_REINSTALL);
+ }
+ }
+ }
+}
diff --git a/zebra/zebra_nhg.h b/zebra/zebra_nhg.h
index b178007b4e..3bb697aa75 100644
--- a/zebra/zebra_nhg.h
+++ b/zebra/zebra_nhg.h
@@ -85,7 +85,7 @@ struct nhg_hash_entry {
* nhg(1)->nhg_dependents is 3 in the tree
*
* nhg(2)->nhg_depends is empty
- * nhg(3)->nhg_dependents is 3 in the tree
+ * nhg(2)->nhg_dependents is 3 in the tree
*/
struct nhg_connected_tree_head nhg_depends, nhg_dependents;
@@ -143,7 +143,15 @@ struct nhg_hash_entry {
/*
* Track FPM installation status..
*/
-#define NEXTHOP_GROUP_FPM (1 << 6)
+#define NEXTHOP_GROUP_FPM (1 << 7)
+
+/*
+ * When an interface comes up install the
+ * singleton's and schedule the NHG's that
+ * are using this nhg to be reinstalled
+ * when installation is successful.
+ */
+#define NEXTHOP_GROUP_REINSTALL (1 << 8)
};
/* Upper 4 bits of the NHG are reserved for indicating the NHG type */
@@ -358,6 +366,7 @@ extern uint8_t zebra_nhg_nhe2grp(struct nh_grp *grp, struct nhg_hash_entry *nhe,
/* Dataplane install/uninstall */
extern void zebra_nhg_install_kernel(struct nhg_hash_entry *nhe);
extern void zebra_nhg_uninstall_kernel(struct nhg_hash_entry *nhe);
+extern void zebra_interface_nhg_reinstall(struct interface *ifp);
/* Forward ref of dplane update context type */
struct zebra_dplane_ctx;
diff --git a/zebra/zebra_ns.c b/zebra/zebra_ns.c
index 6bb5e971e6..803d8f0034 100644
--- a/zebra/zebra_ns.c
+++ b/zebra/zebra_ns.c
@@ -23,6 +23,7 @@
#include "rib.h"
#include "table_manager.h"
#include "zebra_errors.h"
+#include "zebra_dplane.h"
extern struct zebra_privs_t zserv_privs;
@@ -41,11 +42,6 @@ struct zebra_ns *zebra_ns_lookup(ns_id_t ns_id)
return (info == NULL) ? dzns : info;
}
-static struct zebra_ns *zebra_ns_alloc(void)
-{
- return XCALLOC(MTYPE_ZEBRA_NS, sizeof(struct zebra_ns));
-}
-
static int zebra_ns_new(struct ns *ns)
{
struct zebra_ns *zns;
@@ -56,7 +52,7 @@ static int zebra_ns_new(struct ns *ns)
if (IS_ZEBRA_DEBUG_EVENT)
zlog_info("ZNS %s with id %u (created)", ns->name, ns->ns_id);
- zns = zebra_ns_alloc();
+ zns = XCALLOC(MTYPE_ZEBRA_NS, sizeof(struct zebra_ns));
ns->info = zns;
zns->ns = ns;
zns->ns_id = ns->ns_id;
@@ -101,6 +97,36 @@ int zebra_ns_disabled(struct ns *ns)
return zebra_ns_disable_internal(zns, true);
}
+void zebra_ns_startup_continue(struct zebra_dplane_ctx *ctx)
+{
+ struct zebra_ns *zns = zebra_ns_lookup(dplane_ctx_get_ns_id(ctx));
+ enum zebra_dplane_startup_notifications spot;
+
+ if (!zns) {
+ zlog_err("%s: No Namespace associated with %u", __func__,
+ dplane_ctx_get_ns_id(ctx));
+ return;
+ }
+
+ spot = dplane_ctx_get_startup_spot(ctx);
+
+ switch (spot) {
+ case ZEBRA_DPLANE_INTERFACES_READ:
+ interface_list_tunneldump(zns);
+ break;
+ case ZEBRA_DPLANE_TUNNELS_READ:
+ interface_list_second(zns);
+ break;
+ case ZEBRA_DPLANE_ADDRESSES_READ:
+ route_read(zns);
+
+ vlan_read(zns);
+ kernel_read_pbr_rules(zns);
+ kernel_read_tc_qdisc(zns);
+ break;
+ }
+}
+
/* Do global enable actions - open sockets, read kernel config etc. */
int zebra_ns_enable(ns_id_t ns_id, void **info)
{
@@ -111,11 +137,6 @@ int zebra_ns_enable(ns_id_t ns_id, void **info)
kernel_init(zns);
zebra_dplane_ns_enable(zns, true);
interface_list(zns);
- route_read(zns);
-
- vlan_read(zns);
- kernel_read_pbr_rules(zns);
- kernel_read_tc_qdisc(zns);
return 0;
}
@@ -168,6 +189,8 @@ int zebra_ns_final_shutdown(struct ns *ns,
kernel_terminate(zns, true);
+ zebra_ns_delete(ns);
+
return NS_WALK_CONTINUE;
}
@@ -215,10 +238,3 @@ int zebra_ns_init(void)
return 0;
}
-
-int zebra_ns_config_write(struct vty *vty, struct ns *ns)
-{
- if (ns && ns->name != NULL)
- vty_out(vty, " netns %s\n", ns->name);
- return 0;
-}
diff --git a/zebra/zebra_ns.h b/zebra/zebra_ns.h
index e759d522fa..8d988c3f82 100644
--- a/zebra/zebra_ns.h
+++ b/zebra/zebra_ns.h
@@ -18,6 +18,8 @@ extern "C" {
#endif
#ifdef HAVE_NETLINK
+#include <linux/netlink.h>
+
/* Socket interface to kernel */
struct nlsock {
int sock;
@@ -47,6 +49,8 @@ struct zebra_ns {
struct nlsock netlink_dplane_out;
struct nlsock netlink_dplane_in;
struct event *t_netlink;
+
+ struct nlsock ge_netlink_cmd; /* command channel for generic netlink */
#endif
struct route_table *if_table;
@@ -66,7 +70,8 @@ int zebra_ns_early_shutdown(struct ns *ns,
int zebra_ns_final_shutdown(struct ns *ns,
void *param_in __attribute__((unused)),
void **param_out __attribute__((unused)));
-int zebra_ns_config_write(struct vty *vty, struct ns *ns);
+
+void zebra_ns_startup_continue(struct zebra_dplane_ctx *ctx);
#ifdef __cplusplus
}
diff --git a/zebra/zebra_opaque.c b/zebra/zebra_opaque.c
index 8ceb1f8dc5..90533955a4 100644
--- a/zebra/zebra_opaque.c
+++ b/zebra/zebra_opaque.c
@@ -26,10 +26,16 @@ struct opq_client_reg {
int instance;
uint32_t session_id;
+ int flags;
+
struct opq_client_reg *next;
struct opq_client_reg *prev;
};
+/* Registration is for receiving or for notifications */
+#define OPQ_CLIENT_FLAG_RECV 0x01
+#define OPQ_CLIENT_FLAG_NOTIFY 0x02
+
/* Opaque message registration info */
struct opq_msg_reg {
struct opq_regh_item item;
@@ -99,14 +105,18 @@ static int handle_opq_registration(const struct zmsghdr *hdr,
struct stream *msg);
static int handle_opq_unregistration(const struct zmsghdr *hdr,
struct stream *msg);
+static int handle_opq_notif_req(const struct zmsghdr *hdr, struct stream *msg);
+static int handle_opq_notif_unreg(const struct zapi_opaque_notif_info *info);
static int dispatch_opq_messages(struct stream_fifo *msg_fifo);
static struct opq_msg_reg *opq_reg_lookup(uint32_t type);
static bool opq_client_match(const struct opq_client_reg *client,
const struct zapi_opaque_reg_info *info);
+static bool opq_client_notif_match(const struct opq_client_reg *client,
+ const struct zapi_opaque_notif_info *info);
static struct opq_msg_reg *opq_reg_alloc(uint32_t type);
static void opq_reg_free(struct opq_msg_reg **reg);
-static struct opq_client_reg *opq_client_alloc(
- const struct zapi_opaque_reg_info *info);
+static struct opq_client_reg *opq_client_alloc(uint8_t proto, uint16_t instance,
+ uint32_t session_id);
static void opq_client_free(struct opq_client_reg **client);
static const char *opq_client2str(char *buf, size_t buflen,
const struct opq_client_reg *client);
@@ -213,6 +223,7 @@ bool zebra_opaque_handles_msgid(uint16_t id)
case ZEBRA_OPAQUE_MESSAGE:
case ZEBRA_OPAQUE_REGISTER:
case ZEBRA_OPAQUE_UNREGISTER:
+ case ZEBRA_OPAQUE_NOTIFY:
ret = true;
break;
default:
@@ -243,7 +254,7 @@ uint32_t zebra_opaque_enqueue_batch(struct stream_fifo *batch)
}
}
- /* Schedule module pthread to process the batch */
+ /* Schedule module's pthread to process the batch */
if (counter > 0) {
if (IS_ZEBRA_DEBUG_RECV && IS_ZEBRA_DEBUG_DETAIL)
zlog_debug("%s: received %u messages",
@@ -326,6 +337,38 @@ done:
}
/*
+ * Helper to acquire/lock a client session and send the message in 's'.
+ * Note that 's' is enqueued for an io pthread, so don't free it
+ * or touch it if this returns 'true'.
+ */
+static bool opq_send_message(uint8_t proto, uint16_t instance,
+ uint32_t session_id, struct stream *s)
+{
+ bool ret = false;
+ struct zserv *zclient;
+
+ /*
+ * TODO -- this isn't ideal: we're going through an
+ * acquire/release cycle for each client for each
+ * message. Replace this with a batching version.
+ */
+ zclient = zserv_acquire_client(proto, instance, session_id);
+ if (zclient) {
+ /*
+ * Sending a message actually means enqueuing
+ * it for a zapi io pthread to send - so we
+ * don't touch the message after this call.
+ */
+ zserv_send_message(zclient, s);
+
+ zserv_release_client(zclient);
+ ret = true;
+ }
+
+ return ret;
+}
+
+/*
* Process (dispatch) or drop opaque messages.
*/
static int dispatch_opq_messages(struct stream_fifo *msg_fifo)
@@ -336,7 +379,6 @@ static int dispatch_opq_messages(struct stream_fifo *msg_fifo)
struct opq_msg_reg *reg;
int ret;
struct opq_client_reg *client;
- struct zserv *zclient;
char buf[50];
while ((msg = stream_fifo_pop(msg_fifo)) != NULL) {
@@ -350,6 +392,9 @@ static int dispatch_opq_messages(struct stream_fifo *msg_fifo)
} else if (hdr.command == ZEBRA_OPAQUE_UNREGISTER) {
handle_opq_unregistration(&hdr, msg);
continue;
+ } else if (hdr.command == ZEBRA_OPAQUE_NOTIFY) {
+ handle_opq_notif_req(&hdr, msg);
+ continue;
}
/* We only process OPAQUE messages - drop anything else */
@@ -381,9 +426,9 @@ static int dispatch_opq_messages(struct stream_fifo *msg_fifo)
if (CHECK_FLAG(info.flags, ZAPI_OPAQUE_FLAG_UNICAST)) {
- if (client->proto != info.proto ||
- client->instance != info.instance ||
- client->session_id != info.session_id)
+ if (client->proto != info.dest_proto ||
+ client->instance != info.dest_instance ||
+ client->session_id != info.dest_session_id)
continue;
if (IS_ZEBRA_DEBUG_RECV &&
@@ -400,36 +445,25 @@ static int dispatch_opq_messages(struct stream_fifo *msg_fifo)
dup = stream_dup(msg);
}
+ if (IS_ZEBRA_DEBUG_SEND && IS_ZEBRA_DEBUG_DETAIL)
+ zlog_debug("%s: sending %s to client %s",
+ __func__, (dup ? "dup" : "msg"),
+ opq_client2str(buf, sizeof(buf),
+ client));
+
/*
* TODO -- this isn't ideal: we're going through an
* acquire/release cycle for each client for each
* message. Replace this with a batching version.
*/
- zclient = zserv_acquire_client(client->proto,
- client->instance,
- client->session_id);
- if (zclient) {
- if (IS_ZEBRA_DEBUG_SEND &&
- IS_ZEBRA_DEBUG_DETAIL)
- zlog_debug("%s: sending %s to client %s",
- __func__,
- (dup ? "dup" : "msg"),
- opq_client2str(buf,
- sizeof(buf),
- client));
-
- /*
- * Sending a message actually means enqueuing
- * it for a zapi io pthread to send - so we
- * don't touch the message after this call.
- */
- zserv_send_message(zclient, dup ? dup : msg);
+ if (opq_send_message(client->proto, client->instance,
+ client->session_id,
+ (dup ? dup : msg))) {
+ /* Message is gone - don't touch it */
if (dup)
dup = NULL;
else
msg = NULL;
-
- zserv_release_client(zclient);
} else {
if (IS_ZEBRA_DEBUG_RECV &&
IS_ZEBRA_DEBUG_DETAIL)
@@ -457,6 +491,66 @@ drop_it:
return 0;
}
+/* Enqueue registration client object */
+static void opq_enqueue_client(struct opq_msg_reg *reg,
+ struct opq_client_reg *client)
+{
+ client->next = reg->clients;
+ if (reg->clients)
+ reg->clients->prev = client;
+ reg->clients = client;
+}
+
+/* Dequeue registration client object */
+static void opq_dequeue_client(struct opq_msg_reg *reg,
+ struct opq_client_reg *client)
+{
+ if (client->prev)
+ client->prev->next = client->next;
+ if (client->next)
+ client->next->prev = client->prev;
+ if (reg->clients == client)
+ reg->clients = client->next;
+}
+
+/*
+ * Send notification messages to any interested clients in 'reg',
+ * about 'server'; the sense is 'registered' (or not).
+ * The 'server' is not required for un-registrations.
+ */
+static void opq_send_notifications(const struct opq_msg_reg *reg,
+ const struct opq_client_reg *server,
+ bool registered)
+{
+ const struct opq_client_reg *client;
+ struct stream *msg = NULL;
+
+ /* If there are any notification clients, send them a message */
+ for (client = reg->clients; client; client = client->next) {
+ if (CHECK_FLAG(client->flags, OPQ_CLIENT_FLAG_NOTIFY)) {
+ msg = stream_new(ZEBRA_SMALL_PACKET_SIZE);
+
+ if (registered) {
+ zclient_opaque_notif_encode(msg, reg->type,
+ registered,
+ server->proto,
+ server->instance,
+ server->session_id);
+ } else {
+ zclient_opaque_notif_encode(msg, reg->type,
+ registered, 0, 0, 0);
+ }
+
+ /* Locate zebra client and enqueue message to it */
+ if (!opq_send_message(client->proto, client->instance,
+ client->session_id, msg)) {
+ /* Error - need to free the message */
+ stream_free(msg);
+ }
+ }
+ }
+}
+
/*
* Process a register/unregister message
*/
@@ -499,7 +593,9 @@ static int handle_opq_registration(const struct zmsghdr *hdr,
goto done;
}
- client = opq_client_alloc(&info);
+ client = opq_client_alloc(info.proto, info.instance,
+ info.session_id);
+ SET_FLAG(client->flags, OPQ_CLIENT_FLAG_RECV);
if (IS_ZEBRA_DEBUG_RECV)
zlog_debug("%s: client %s registers for %u",
@@ -508,17 +604,20 @@ static int handle_opq_registration(const struct zmsghdr *hdr,
info.type);
/* Link client into registration */
- client->next = reg->clients;
- if (reg->clients)
- reg->clients->prev = client;
- reg->clients = client;
+ opq_enqueue_client(reg, client);
+
+ /* Send notifications to any clients who want them */
+ opq_send_notifications(reg, client, true);
+
} else {
/*
* No existing registrations - create one, add the
* client, and add registration to hash.
*/
reg = opq_reg_alloc(info.type);
- client = opq_client_alloc(&info);
+ client = opq_client_alloc(info.proto, info.instance,
+ info.session_id);
+ SET_FLAG(client->flags, OPQ_CLIENT_FLAG_RECV);
if (IS_ZEBRA_DEBUG_RECV)
zlog_debug("%s: client %s registers for new reg %u",
@@ -545,8 +644,9 @@ static int handle_opq_unregistration(const struct zmsghdr *hdr,
{
int ret = 0;
struct zapi_opaque_reg_info info;
- struct opq_client_reg *client;
+ struct opq_client_reg *client, *tclient;
struct opq_msg_reg key, *reg;
+ int scount;
char buf[50];
memset(&info, 0, sizeof(info));
@@ -571,11 +671,16 @@ static int handle_opq_unregistration(const struct zmsghdr *hdr,
goto done;
}
- /* Look for client */
- for (client = reg->clients; client != NULL;
- client = client->next) {
- if (opq_client_match(client, &info))
- break;
+ /* Look for client info, count servers and notif clients too */
+ client = NULL;
+ scount = 0;
+
+ for (tclient = reg->clients; tclient != NULL; tclient = tclient->next) {
+ if (opq_client_match(tclient, &info))
+ client = tclient;
+
+ if (CHECK_FLAG(tclient->flags, OPQ_CLIENT_FLAG_RECV))
+ scount++;
}
if (client == NULL) {
@@ -592,19 +697,18 @@ static int handle_opq_unregistration(const struct zmsghdr *hdr,
__func__, opq_client2str(buf, sizeof(buf), client),
info.type);
- if (client->prev)
- client->prev->next = client->next;
- if (client->next)
- client->next->prev = client->prev;
- if (reg->clients == client)
- reg->clients = client->next;
-
+ opq_dequeue_client(reg, client);
opq_client_free(&client);
+ scount--;
/* Is registration empty now? */
if (reg->clients == NULL) {
+
opq_regh_del(&opq_reg_hash, reg);
opq_reg_free(&reg);
+ } else if (scount == 0) {
+ /* Send notifications if no more servers for the message. */
+ opq_send_notifications(reg, NULL, false);
}
done:
@@ -613,13 +717,182 @@ done:
return ret;
}
+/*
+ * Handle requests about opaque notifications.
+ */
+static int handle_opq_notif_req(const struct zmsghdr *hdr, struct stream *msg)
+{
+ int ret;
+ struct zapi_opaque_notif_info info = {};
+ struct opq_client_reg *client;
+ struct opq_msg_reg key, *reg;
+ char buf[50];
+
+ ret = zclient_opaque_notif_decode(msg, &info);
+ if (ret < 0)
+ goto done;
+
+ /* Handle deregistration */
+ if (!info.reg) {
+ ret = handle_opq_notif_unreg(&info);
+ goto done;
+ }
+
+ memset(&key, 0, sizeof(key));
+
+ key.type = info.msg_type;
+
+ reg = opq_regh_find(&opq_reg_hash, &key);
+ if (reg) {
+ /* Look for dup client */
+ for (client = reg->clients; client != NULL;
+ client = client->next) {
+ if (opq_client_notif_match(client, &info))
+ break;
+ }
+
+ if (client) {
+ /* Oops - duplicate ? */
+ if (IS_ZEBRA_DEBUG_RECV)
+ zlog_debug("%s: duplicate opq notif reg client %s",
+ __func__, opq_client2str(buf,
+ sizeof(buf),
+ client));
+ goto done;
+ }
+
+ client = opq_client_alloc(info.proto, info.instance,
+ info.session_id);
+ SET_FLAG(client->flags, OPQ_CLIENT_FLAG_NOTIFY);
+
+ if (IS_ZEBRA_DEBUG_RECV)
+ zlog_debug("%s: client %s registers for notif %u",
+ __func__,
+ opq_client2str(buf, sizeof(buf), client),
+ info.msg_type);
+
+ /* Link client into registration */
+ opq_enqueue_client(reg, client);
+
+ /* Send notification if any registered servers */
+ /* Look for a server */
+ for (client = reg->clients; client != NULL;
+ client = client->next) {
+ if (CHECK_FLAG(client->flags, OPQ_CLIENT_FLAG_RECV))
+ break;
+ }
+ if (client)
+ opq_send_notifications(reg, client, true);
+
+ } else if (info.reg) {
+ /*
+ * No existing registrations - create one, add the
+ * client, and add registration to hash.
+ */
+ reg = opq_reg_alloc(info.msg_type);
+ client = opq_client_alloc(info.proto, info.instance,
+ info.session_id);
+ SET_FLAG(client->flags, OPQ_CLIENT_FLAG_NOTIFY);
+
+ if (IS_ZEBRA_DEBUG_RECV)
+ zlog_debug("%s: client %s registers for new notif %u",
+ __func__,
+ opq_client2str(buf, sizeof(buf), client),
+ info.msg_type);
+
+ reg->clients = client;
+
+ opq_regh_add(&opq_reg_hash, reg);
+ }
+
+done:
+ stream_free(msg);
+ return ret;
+}
+
+/*
+ * Unregister notification
+ */
+static int handle_opq_notif_unreg(const struct zapi_opaque_notif_info *info)
+{
+ int ret = 0;
+ struct opq_client_reg *client;
+ struct opq_msg_reg key, *reg;
+ char buf[50];
+
+ memset(&key, 0, sizeof(key));
+
+ key.type = info->msg_type;
+
+ reg = opq_regh_find(&opq_reg_hash, &key);
+ if (reg == NULL) {
+ /* Weird: unregister for unknown message? */
+ if (IS_ZEBRA_DEBUG_RECV)
+ zlog_debug("%s: unknown client %s/%u/%u unregisters notif for unknown type %u",
+ __func__, zebra_route_string(info->proto),
+ info->instance, info->session_id,
+ info->msg_type);
+ goto done;
+ }
+
+ /* Look for client */
+ for (client = reg->clients; client != NULL; client = client->next) {
+ if (opq_client_notif_match(client, info))
+ break;
+ }
+
+ if (client == NULL) {
+ /* Oops - unregister for unknown client? */
+ if (IS_ZEBRA_DEBUG_RECV)
+ zlog_debug("%s: unknown client %s/%u/%u unregisters notif for %u",
+ __func__, zebra_route_string(info->proto),
+ info->instance, info->session_id,
+ info->msg_type);
+ goto done;
+ }
+
+ if (IS_ZEBRA_DEBUG_RECV)
+ zlog_debug("%s: client %s unregisters notif for %u", __func__,
+ opq_client2str(buf, sizeof(buf), client),
+ info->msg_type);
+
+ /* Dequeue client object */
+ opq_dequeue_client(reg, client);
+
+ opq_client_free(&client);
+
+ /* Is registration empty now? */
+ if (reg->clients == NULL) {
+ opq_regh_del(&opq_reg_hash, reg);
+ opq_reg_free(&reg);
+ }
+
+done:
+
+ return ret;
+}
+
/* Compare utility for registered clients */
static bool opq_client_match(const struct opq_client_reg *client,
const struct zapi_opaque_reg_info *info)
{
- if (client->proto == info->proto &&
- client->instance == info->instance &&
- client->session_id == info->session_id)
+ /* look for matching client, skip notifications */
+ if (client->proto == info->proto && client->instance == info->instance &&
+ client->session_id == info->session_id &&
+ CHECK_FLAG(client->flags, OPQ_CLIENT_FLAG_RECV))
+ return true;
+ else
+ return false;
+}
+
+/* Compare helper for clients registered for notifications */
+static bool opq_client_notif_match(const struct opq_client_reg *client,
+ const struct zapi_opaque_notif_info *info)
+{
+ /* look for matching client, only for notifications */
+ if (client->proto == info->proto && client->instance == info->instance &&
+ client->session_id == info->session_id &&
+ CHECK_FLAG(client->flags, OPQ_CLIENT_FLAG_NOTIFY))
return true;
else
return false;
@@ -655,16 +928,16 @@ static void opq_reg_free(struct opq_msg_reg **reg)
XFREE(MTYPE_OPQ, (*reg));
}
-static struct opq_client_reg *opq_client_alloc(
- const struct zapi_opaque_reg_info *info)
+static struct opq_client_reg *opq_client_alloc(uint8_t proto, uint16_t instance,
+ uint32_t session_id)
{
struct opq_client_reg *client;
client = XCALLOC(MTYPE_OPQ, sizeof(struct opq_client_reg));
- client->proto = info->proto;
- client->instance = info->instance;
- client->session_id = info->session_id;
+ client->proto = proto;
+ client->instance = instance;
+ client->session_id = session_id;
return client;
}
diff --git a/zebra/zebra_pbr.c b/zebra/zebra_pbr.c
index 56cac1342e..7f3635702f 100644
--- a/zebra/zebra_pbr.c
+++ b/zebra/zebra_pbr.c
@@ -1,6 +1,9 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/* Zebra Policy Based Routing (PBR) main handling.
* Copyright (C) 2018 Cumulus Networks, Inc.
+ * Portions:
+ * Copyright (c) 2021 The MITRE Corporation.
+ * Copyright (c) 2023 LabN Consulting, L.L.C.
*/
#include <zebra.h>
@@ -166,10 +169,16 @@ uint32_t zebra_pbr_rules_hash_key(const void *arg)
key = jhash(rule->ifname, strlen(rule->ifname), key);
- return jhash_3words(rule->rule.filter.src_port,
- rule->rule.filter.dst_port,
- prefix_hash_key(&rule->rule.filter.dst_ip),
- jhash_1word(rule->rule.unique, key));
+ key = jhash_3words(rule->rule.filter.pcp, rule->rule.filter.vlan_id,
+ rule->rule.filter.vlan_flags, key);
+
+ key = jhash_3words(rule->rule.filter.src_port,
+ rule->rule.filter.dst_port,
+ prefix_hash_key(&rule->rule.filter.dst_ip), key);
+
+ key = jhash_2words(rule->rule.unique, rule->sock, key);
+
+ return key;
}
bool zebra_pbr_rules_hash_equal(const void *arg1, const void *arg2)
@@ -185,6 +194,9 @@ bool zebra_pbr_rules_hash_equal(const void *arg1, const void *arg2)
if (r1->rule.priority != r2->rule.priority)
return false;
+ if (r1->sock != r2->sock)
+ return false;
+
if (r1->rule.unique != r2->rule.unique)
return false;
@@ -220,8 +232,9 @@ bool zebra_pbr_rules_hash_equal(const void *arg1, const void *arg2)
struct pbr_rule_unique_lookup {
struct zebra_pbr_rule *rule;
+ int sock;
uint32_t unique;
- char ifname[INTERFACE_NAMSIZ + 1];
+ char ifname[IFNAMSIZ + 1];
vrf_id_t vrf_id;
};
@@ -230,9 +243,9 @@ static int pbr_rule_lookup_unique_walker(struct hash_bucket *b, void *data)
struct pbr_rule_unique_lookup *pul = data;
struct zebra_pbr_rule *rule = b->data;
- if (pul->unique == rule->rule.unique
- && strncmp(pul->ifname, rule->rule.ifname, INTERFACE_NAMSIZ) == 0
- && pul->vrf_id == rule->vrf_id) {
+ if (pul->sock == rule->sock && pul->unique == rule->rule.unique &&
+ strmatch(pul->ifname, rule->rule.ifname) &&
+ pul->vrf_id == rule->vrf_id) {
pul->rule = rule;
return HASHWALK_ABORT;
}
@@ -246,9 +259,10 @@ pbr_rule_lookup_unique(struct zebra_pbr_rule *zrule)
struct pbr_rule_unique_lookup pul;
pul.unique = zrule->rule.unique;
- strlcpy(pul.ifname, zrule->rule.ifname, INTERFACE_NAMSIZ);
+ strlcpy(pul.ifname, zrule->rule.ifname, IFNAMSIZ);
pul.rule = NULL;
pul.vrf_id = zrule->vrf_id;
+ pul.sock = zrule->sock;
hash_walk(zrouter.rules_hash, &pbr_rule_lookup_unique_walker, &pul);
return pul.rule;
@@ -501,6 +515,7 @@ void zebra_pbr_show_rule_unit(struct zebra_pbr_rule *rule, struct vty *vty)
{
struct pbr_rule *prule = &rule->rule;
struct zebra_pbr_action *zaction = &rule->action;
+ struct pbr_action *pa = &prule->action;
vty_out(vty, "Rules if %s\n", rule->ifname);
vty_out(vty, " Seq %u pri %u\n", prule->seq, prule->priority);
@@ -516,15 +531,55 @@ void zebra_pbr_show_rule_unit(struct zebra_pbr_rule *rule, struct vty *vty)
if (prule->filter.filter_bm & PBR_FILTER_DST_PORT)
vty_out(vty, " DST Port Match: %u\n", prule->filter.dst_port);
- if (prule->filter.filter_bm & PBR_FILTER_DSFIELD) {
+ if (prule->filter.filter_bm & PBR_FILTER_DSCP)
vty_out(vty, " DSCP Match: %u\n",
(prule->filter.dsfield & PBR_DSFIELD_DSCP) >> 2);
+ if (prule->filter.filter_bm & PBR_FILTER_ECN)
vty_out(vty, " ECN Match: %u\n",
prule->filter.dsfield & PBR_DSFIELD_ECN);
- }
if (prule->filter.filter_bm & PBR_FILTER_FWMARK)
vty_out(vty, " MARK Match: %u\n", prule->filter.fwmark);
+ if (prule->filter.filter_bm & PBR_FILTER_PCP)
+ vty_out(vty, " PCP Match: %u\n", prule->filter.pcp);
+ if (prule->filter.filter_bm & PBR_FILTER_VLAN_ID)
+ vty_out(vty, " VLAN ID Match: %u\n", prule->filter.vlan_id);
+ if (prule->filter.filter_bm & PBR_FILTER_VLAN_FLAGS) {
+ vty_out(vty, " VLAN Flags Match:");
+ if (CHECK_FLAG(prule->filter.vlan_flags, PBR_VLAN_FLAGS_TAGGED))
+ vty_out(vty, " tagged");
+ if (CHECK_FLAG(prule->filter.vlan_flags,
+ PBR_VLAN_FLAGS_UNTAGGED))
+ vty_out(vty, " untagged");
+ if (CHECK_FLAG(prule->filter.vlan_flags,
+ PBR_VLAN_FLAGS_UNTAGGED_0))
+ vty_out(vty, " untagged-or-zero");
+ vty_out(vty, "\n");
+ }
+
+ if (CHECK_FLAG(pa->flags, PBR_ACTION_ECN))
+ vty_out(vty, " Action: Set ECN: %u\n", pa->ecn);
+ if (CHECK_FLAG(pa->flags, PBR_ACTION_DSCP))
+ vty_out(vty, " Action: Set DSCP: %u\n", pa->dscp >> 2);
+
+ if (CHECK_FLAG(pa->flags, PBR_ACTION_SRC_IP))
+ vty_out(vty, " Action: Set SRC IP: %pSU\n", &pa->src_ip);
+ if (CHECK_FLAG(pa->flags, PBR_ACTION_DST_IP))
+ vty_out(vty, " Action: Set DST IP: %pSU\n", &pa->dst_ip);
+ if (CHECK_FLAG(pa->flags, PBR_ACTION_SRC_PORT))
+ vty_out(vty, " Action: Set SRC PORT: %u\n", pa->src_port);
+ if (CHECK_FLAG(pa->flags, PBR_ACTION_DST_PORT))
+ vty_out(vty, " Action: Set DST PORT: %u\n", pa->dst_port);
+
+ if (CHECK_FLAG(pa->flags, PBR_ACTION_QUEUE_ID))
+ vty_out(vty, " Action: Set Queue ID: %u\n", pa->queue_id);
+
+ if (CHECK_FLAG(pa->flags, PBR_ACTION_PCP))
+ vty_out(vty, " Action: Set PCP: %u\n", pa->pcp);
+ if (CHECK_FLAG(pa->flags, PBR_ACTION_VLAN_ID))
+ vty_out(vty, " Action: Set VLAN ID: %u\n", pa->vlan_id);
+ if (CHECK_FLAG(pa->flags, PBR_ACTION_VLAN_STRIP_INNER_ANY))
+ vty_out(vty, " Action: Strip VLAN ID\n");
vty_out(vty, " Tableid: %u\n", prule->action.table);
if (zaction->afi == AFI_IP)
@@ -1118,7 +1173,7 @@ static void zebra_pbr_display_port(struct vty *vty, uint32_t filter_bm,
uint16_t port_min, uint16_t port_max,
uint8_t proto)
{
- if (!(filter_bm & PBR_FILTER_PROTO)) {
+ if (!(filter_bm & PBR_FILTER_IP_PROTOCOL)) {
if (port_max)
vty_out(vty, ":udp/tcp:%d-%d",
port_min, port_max);
diff --git a/zebra/zebra_pbr.h b/zebra/zebra_pbr.h
index 15ad4e35cf..1e4b5cd0f3 100644
--- a/zebra/zebra_pbr.h
+++ b/zebra/zebra_pbr.h
@@ -46,7 +46,7 @@ struct zebra_pbr_rule {
struct pbr_rule rule;
- char ifname[INTERFACE_NAMSIZ];
+ char ifname[IFNAMSIZ];
struct zebra_pbr_action action;
@@ -61,8 +61,6 @@ struct zebra_pbr_rule {
(r->rule.filter.filter_bm & PBR_FILTER_SRC_PORT)
#define IS_RULE_FILTERING_ON_DST_PORT(r) \
(r->rule.filter.filter_bm & PBR_FILTER_DST_PORT)
-#define IS_RULE_FILTERING_ON_DSFIELD(r) \
- (r->rule.filter.filter_bm & PBR_FILTER_DSFIELD)
#define IS_RULE_FILTERING_ON_FWMARK(r) \
(r->rule.filter.filter_bm & PBR_FILTER_FWMARK)
diff --git a/zebra/zebra_ptm.c b/zebra/zebra_ptm.c
index a1fee840df..d7d752f01e 100644
--- a/zebra/zebra_ptm.c
+++ b/zebra/zebra_ptm.c
@@ -16,6 +16,7 @@
#include "ptm_lib.h"
#include "rib.h"
#include "stream.h"
+#include "lib/version.h"
#include "vrf.h"
#include "vty.h"
#include "lib_errors.h"
@@ -85,7 +86,6 @@ struct zebra_ptm_cb ptm_cb;
static int zebra_ptm_socket_init(void);
void zebra_ptm_sock_read(struct event *thread);
-static void zebra_ptm_install_commands(void);
static int zebra_ptm_handle_msg_cb(void *arg, void *in_ctxt);
void zebra_bfd_peer_replay_req(void);
void zebra_ptm_send_status_req(void);
@@ -114,7 +114,6 @@ void zebra_ptm_init(void)
}
ptm_cb.pid = getpid();
- zebra_ptm_install_commands();
snprintf(buf, sizeof(buf), "%s", FRR_PTM_NAME);
ptm_hdl = ptm_lib_register(buf, NULL, zebra_ptm_handle_msg_cb,
@@ -239,10 +238,7 @@ void zebra_ptm_connect(struct event *t)
}
}
-DEFUN (zebra_ptm_enable,
- zebra_ptm_enable_cmd,
- "ptm-enable",
- "Enable neighbor check with specified topology\n")
+void zebra_global_ptm_enable(void)
{
struct vrf *vrf;
struct interface *ifp;
@@ -265,27 +261,16 @@ DEFUN (zebra_ptm_enable,
}
zebra_ptm_connect(NULL);
-
- return CMD_SUCCESS;
}
-DEFUN (no_zebra_ptm_enable,
- no_zebra_ptm_enable_cmd,
- "no ptm-enable",
- NO_STR
- "Enable neighbor check with specified topology\n")
+void zebra_global_ptm_disable(void)
{
ptm_cb.ptm_enable = ZEBRA_IF_PTM_ENABLE_OFF;
zebra_ptm_reset_status(1);
- return CMD_SUCCESS;
}
-DEFUN (zebra_ptm_enable_if,
- zebra_ptm_enable_if_cmd,
- "ptm-enable",
- "Enable neighbor check with specified topology\n")
+void zebra_if_ptm_enable(struct interface *ifp)
{
- VTY_DECLVAR_CONTEXT(interface, ifp);
struct zebra_if *if_data;
int old_ptm_enable;
int send_linkdown = 0;
@@ -294,7 +279,7 @@ DEFUN (zebra_ptm_enable_if,
if_data->ptm_enable = ZEBRA_IF_PTM_ENABLE_UNSPEC;
if (ifp->ifindex == IFINDEX_INTERNAL) {
- return CMD_SUCCESS;
+ return;
}
old_ptm_enable = ifp->ptm_enable;
@@ -311,19 +296,12 @@ DEFUN (zebra_ptm_enable_if,
if_down(ifp);
}
}
-
- return CMD_SUCCESS;
}
-DEFUN (no_zebra_ptm_enable_if,
- no_zebra_ptm_enable_if_cmd,
- "no ptm-enable",
- NO_STR
- "Enable neighbor check with specified topology\n")
+void zebra_if_ptm_disable(struct interface *ifp)
{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- int send_linkup = 0;
struct zebra_if *if_data;
+ int send_linkup = 0;
if ((ifp->ifindex != IFINDEX_INTERNAL) && (ifp->ptm_enable)) {
if (!if_is_operative(ifp))
@@ -340,17 +318,6 @@ DEFUN (no_zebra_ptm_enable_if,
if_data = ifp->info;
if_data->ptm_enable = ZEBRA_IF_PTM_ENABLE_OFF;
-
- return CMD_SUCCESS;
-}
-
-
-void zebra_ptm_write(struct vty *vty)
-{
- if (ptm_cb.ptm_enable)
- vty_out(vty, "ptm-enable\n");
-
- return;
}
static int zebra_ptm_socket_init(void)
@@ -393,14 +360,6 @@ static int zebra_ptm_socket_init(void)
return sock;
}
-static void zebra_ptm_install_commands(void)
-{
- install_element(CONFIG_NODE, &zebra_ptm_enable_cmd);
- install_element(CONFIG_NODE, &no_zebra_ptm_enable_cmd);
- install_element(INTERFACE_NODE, &zebra_ptm_enable_if_cmd);
- install_element(INTERFACE_NODE, &no_zebra_ptm_enable_if_cmd);
-}
-
/* BFD session goes down, send message to the protocols. */
static void if_bfd_session_update(struct interface *ifp, struct prefix *dp,
struct prefix *sp, int status,
@@ -677,7 +636,7 @@ void zebra_ptm_bfd_dst_register(ZAPI_HANDLER_ARGS)
uint8_t detect_mul;
unsigned int min_rx_timer;
unsigned int min_tx_timer;
- char if_name[INTERFACE_NAMSIZ];
+ char if_name[IFNAMSIZ];
uint8_t len;
void *out_ctxt;
char buf[INET6_ADDRSTRLEN];
@@ -840,7 +799,7 @@ void zebra_ptm_bfd_dst_deregister(ZAPI_HANDLER_ARGS)
struct prefix src_p;
struct prefix dst_p;
uint8_t multi_hop;
- char if_name[INTERFACE_NAMSIZ];
+ char if_name[IFNAMSIZ];
uint8_t len;
char buf[INET6_ADDRSTRLEN];
char tmp_buf[64];
@@ -1164,12 +1123,6 @@ void zebra_ptm_if_set_ptm_state(struct interface *ifp,
ifp->ptm_enable = zebra_ifp->ptm_enable;
}
-void zebra_ptm_if_write(struct vty *vty, struct zebra_if *zebra_ifp)
-{
- if (zebra_ifp->ptm_enable == ZEBRA_IF_PTM_ENABLE_OFF)
- vty_out(vty, " no ptm-enable\n");
-}
-
#else /* HAVE_BFDD */
/*
@@ -1184,7 +1137,7 @@ struct ptm_process {
TAILQ_HEAD(ppqueue, ptm_process) ppqueue;
DEFINE_MTYPE_STATIC(ZEBRA, ZEBRA_PTM_BFD_PROCESS,
- "PTM BFD process registration table.");
+ "PTM BFD process reg table");
/*
* Prototypes.
@@ -1532,16 +1485,6 @@ void zebra_ptm_show_status(struct vty *vty __attribute__((__unused__)),
/* NOTHING */
}
-void zebra_ptm_write(struct vty *vty __attribute__((__unused__)))
-{
- /* NOTHING */
-}
-
-void zebra_ptm_if_write(struct vty *vty __attribute__((__unused__)),
- struct zebra_if *zifp __attribute__((__unused__)))
-{
- /* NOTHING */
-}
void zebra_ptm_if_set_ptm_state(struct interface *i __attribute__((__unused__)),
struct zebra_if *zi __attribute__((__unused__)))
{
diff --git a/zebra/zebra_ptm.h b/zebra/zebra_ptm.h
index 1b2f7a02d4..20a53e2fea 100644
--- a/zebra/zebra_ptm.h
+++ b/zebra/zebra_ptm.h
@@ -53,14 +53,20 @@ struct zebra_ptm_cb {
(protocol) == ZEBRA_ROUTE_OSPF6 || (protocol) == ZEBRA_ROUTE_ISIS || \
(protocol) == ZEBRA_ROUTE_PIM || \
(protocol) == ZEBRA_ROUTE_OPENFABRIC || \
- (protocol) == ZEBRA_ROUTE_STATIC)
+ (protocol) == ZEBRA_ROUTE_STATIC || (protocol) == ZEBRA_ROUTE_RIP)
void zebra_ptm_init(void);
void zebra_ptm_finish(void);
void zebra_ptm_connect(struct event *t);
-void zebra_ptm_write(struct vty *vty);
int zebra_ptm_get_enable_state(void);
+#if HAVE_BFDD == 0
+void zebra_global_ptm_enable(void);
+void zebra_global_ptm_disable(void);
+void zebra_if_ptm_enable(struct interface *ifp);
+void zebra_if_ptm_disable(struct interface *ifp);
+#endif
+
/* ZAPI message handlers */
void zebra_ptm_bfd_dst_register(ZAPI_HANDLER_ARGS);
void zebra_ptm_bfd_dst_deregister(ZAPI_HANDLER_ARGS);
@@ -74,7 +80,6 @@ void zebra_ptm_show_status(struct vty *vty, json_object *json,
void zebra_ptm_if_init(struct zebra_if *zebra_ifp);
void zebra_ptm_if_set_ptm_state(struct interface *ifp,
struct zebra_if *zebra_ifp);
-void zebra_ptm_if_write(struct vty *vty, struct zebra_if *zebra_ifp);
#ifdef __cplusplus
}
diff --git a/zebra/zebra_pw.c b/zebra/zebra_pw.c
index 12dcac1de5..deed3b6ad3 100644
--- a/zebra/zebra_pw.c
+++ b/zebra/zebra_pw.c
@@ -377,15 +377,18 @@ static int zebra_pw_client_close(struct zserv *client)
return 0;
}
-void zebra_pw_init(struct zebra_vrf *zvrf)
+static void zebra_pw_init(void)
+{
+ hook_register(zserv_client_close, zebra_pw_client_close);
+}
+
+void zebra_pw_init_vrf(struct zebra_vrf *zvrf)
{
RB_INIT(zebra_pw_head, &zvrf->pseudowires);
RB_INIT(zebra_static_pw_head, &zvrf->static_pseudowires);
-
- hook_register(zserv_client_close, zebra_pw_client_close);
}
-void zebra_pw_exit(struct zebra_vrf *zvrf)
+void zebra_pw_exit_vrf(struct zebra_vrf *zvrf)
{
struct zebra_pw *pw;
@@ -396,6 +399,11 @@ void zebra_pw_exit(struct zebra_vrf *zvrf)
}
}
+void zebra_pw_terminate(void)
+{
+ hook_unregister(zserv_client_close, zebra_pw_client_close);
+}
+
DEFUN_NOSH (pseudowire_if,
pseudowire_if_cmd,
"pseudowire IFNAME",
@@ -408,8 +416,6 @@ DEFUN_NOSH (pseudowire_if,
int idx = 0;
zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
- if (!zvrf)
- return CMD_WARNING;
argv_find(argv, argc, "IFNAME", &idx);
ifname = argv[idx]->arg;
@@ -440,8 +446,6 @@ DEFUN (no_pseudowire_if,
int idx = 0;
zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
- if (!zvrf)
- return CMD_WARNING;
argv_find(argv, argc, "IFNAME", &idx);
ifname = argv[idx]->arg;
@@ -564,8 +568,6 @@ DEFUN (show_pseudowires,
struct zebra_pw *pw;
zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
- if (!zvrf)
- return 0;
vty_out(vty, "%-16s %-24s %-12s %-8s %-10s\n", "Interface", "Neighbor",
"Labels", "Protocol", "Status");
@@ -603,8 +605,6 @@ static void vty_show_mpls_pseudowire_detail(struct vty *vty)
struct nexthop_group *nhg;
zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
- if (!zvrf)
- return;
RB_FOREACH (pw, zebra_pw_head, &zvrf->pseudowires) {
char buf_nbr[INET6_ADDRSTRLEN];
@@ -759,8 +759,6 @@ static void vty_show_mpls_pseudowire_detail_json(struct vty *vty)
struct zebra_pw *pw;
zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
- if (!zvrf)
- return;
json = json_object_new_object();
json_pws = json_object_new_array();
@@ -795,8 +793,6 @@ static int zebra_pw_config(struct vty *vty)
struct zebra_pw *pw;
zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
- if (!zvrf)
- return 0;
RB_FOREACH (pw, zebra_static_pw_head, &zvrf->static_pseudowires) {
vty_out(vty, "pseudowire %s\n", pw->ifname);
@@ -849,4 +845,6 @@ void zebra_pw_vty_init(void)
install_element(VIEW_NODE, &show_pseudowires_cmd);
install_element(VIEW_NODE, &show_pseudowires_detail_cmd);
+
+ zebra_pw_init();
}
diff --git a/zebra/zebra_pw.h b/zebra/zebra_pw.h
index fd94d5e5ed..431d663f7c 100644
--- a/zebra/zebra_pw.h
+++ b/zebra/zebra_pw.h
@@ -24,7 +24,7 @@ extern "C" {
struct zebra_pw {
RB_ENTRY(zebra_pw) pw_entry, static_pw_entry;
vrf_id_t vrf_id;
- char ifname[INTERFACE_NAMSIZ];
+ char ifname[IFNAMSIZ];
ifindex_t ifindex;
int type;
int af;
@@ -60,8 +60,9 @@ void zebra_pw_change(struct zebra_pw *, ifindex_t, int, int, union g_addr *,
struct zebra_pw *zebra_pw_find(struct zebra_vrf *, const char *);
void zebra_pw_update(struct zebra_pw *);
void zebra_pw_install_failure(struct zebra_pw *pw, int pwstatus);
-void zebra_pw_init(struct zebra_vrf *);
-void zebra_pw_exit(struct zebra_vrf *);
+void zebra_pw_init_vrf(struct zebra_vrf *);
+void zebra_pw_exit_vrf(struct zebra_vrf *);
+void zebra_pw_terminate(void);
void zebra_pw_vty_init(void);
#ifdef __cplusplus
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index adcaf64044..5b95d8668a 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -5,6 +5,10 @@
#include <zebra.h>
+#ifdef GNU_LINUX
+#include <linux/rtnetlink.h>
+#endif
+
#include "command.h"
#include "if.h"
#include "linklist.h"
@@ -25,6 +29,7 @@
#include "frr_pthread.h"
#include "printfrr.h"
#include "frrscript.h"
+#include "frrdistance.h"
#include "zebra/zebra_router.h"
#include "zebra/connected.h"
@@ -103,6 +108,9 @@ static const struct {
[ZEBRA_ROUTE_CONNECT] = {ZEBRA_ROUTE_CONNECT,
ZEBRA_CONNECT_DISTANCE_DEFAULT,
META_QUEUE_CONNECTED},
+ [ZEBRA_ROUTE_LOCAL] = {ZEBRA_ROUTE_LOCAL,
+ ZEBRA_CONNECT_DISTANCE_DEFAULT,
+ META_QUEUE_CONNECTED},
[ZEBRA_ROUTE_STATIC] = {ZEBRA_ROUTE_STATIC,
ZEBRA_STATIC_DISTANCE_DEFAULT,
META_QUEUE_STATIC},
@@ -130,6 +138,7 @@ static const struct {
[ZEBRA_ROUTE_OLSR] = {ZEBRA_ROUTE_OLSR, ZEBRA_MAX_DISTANCE_DEFAULT,
META_QUEUE_OTHER},
[ZEBRA_ROUTE_TABLE] = {ZEBRA_ROUTE_TABLE, ZEBRA_TABLE_DISTANCE_DEFAULT, META_QUEUE_STATIC},
+ [ZEBRA_ROUTE_TABLE_DIRECT] = {ZEBRA_ROUTE_TABLE_DIRECT, ZEBRA_TABLEDIRECT_DISTANCE_DEFAULT, META_QUEUE_STATIC},
[ZEBRA_ROUTE_LDP] = {ZEBRA_ROUTE_LDP, ZEBRA_LDP_DISTANCE_DEFAULT,
META_QUEUE_OTHER},
[ZEBRA_ROUTE_VNC] = {ZEBRA_ROUTE_VNC, ZEBRA_EBGP_DISTANCE_DEFAULT,
@@ -177,6 +186,7 @@ struct wq_nhg_wrapper {
struct nhg_ctx *ctx;
struct nhg_hash_entry *nhe;
} u;
+ bool deletion;
};
#define WQ_NHG_WRAPPER_TYPE_CTX 0x01
@@ -330,7 +340,7 @@ static char *_dump_re_status(const struct route_entry *re, char *buf,
: "",
CHECK_FLAG(re->status, ROUTE_ENTRY_QUEUED) ? "Queued " : "",
CHECK_FLAG(re->status, ROUTE_ENTRY_ROUTE_REPLACING)
- ? "Replacing"
+ ? "Replacing "
: "",
CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED) ? "Installed "
: "",
@@ -365,7 +375,7 @@ int is_zebra_valid_kernel_table(uint32_t table_id)
int is_zebra_main_routing_table(uint32_t table_id)
{
- if (table_id == RT_TABLE_MAIN)
+ if (table_id == rt_table_main_id)
return 1;
return 0;
}
@@ -428,18 +438,29 @@ int route_entry_update_nhe(struct route_entry *re,
done:
/* Detach / deref previous nhg */
- if (old_nhg)
+
+ if (old_nhg) {
+ /*
+ * Return true if we are deleting the previous NHE
+ * Note: we dont check the return value of the function anywhere
+ * except at rib_handle_nhg_replace().
+ */
+ if (old_nhg->refcnt == 1)
+ ret = 1;
+
zebra_nhg_decrement_ref(old_nhg);
+ }
return ret;
}
-void rib_handle_nhg_replace(struct nhg_hash_entry *old_entry,
- struct nhg_hash_entry *new_entry)
+int rib_handle_nhg_replace(struct nhg_hash_entry *old_entry,
+ struct nhg_hash_entry *new_entry)
{
struct zebra_router_table *zrt;
struct route_node *rn;
struct route_entry *re, *next;
+ int ret = 0;
if (IS_ZEBRA_DEBUG_RIB_DETAILED || IS_ZEBRA_DEBUG_NHG_DETAIL)
zlog_debug("%s: replacing routes nhe (%u) OLD %p NEW %p",
@@ -451,10 +472,17 @@ void rib_handle_nhg_replace(struct nhg_hash_entry *old_entry,
rn = srcdest_route_next(rn)) {
RNODE_FOREACH_RE_SAFE (rn, re, next) {
if (re->nhe && re->nhe == old_entry)
- route_entry_update_nhe(re, new_entry);
+ ret += route_entry_update_nhe(re,
+ new_entry);
}
}
}
+
+ /*
+ * if ret > 0, some previous re->nhe has freed the address to which
+ * old_entry is pointing.
+ */
+ return ret;
}
struct route_entry *rib_match(afi_t afi, safi_t safi, vrf_id_t vrf_id,
@@ -503,7 +531,8 @@ struct route_entry *rib_match(afi_t afi, safi_t safi, vrf_id_t vrf_id,
if (rn)
route_lock_node(rn);
} else {
- if (match->type != ZEBRA_ROUTE_CONNECT) {
+ if (match->type != ZEBRA_ROUTE_CONNECT &&
+ match->type != ZEBRA_ROUTE_LOCAL) {
if (!CHECK_FLAG(match->status,
ROUTE_ENTRY_INSTALLED))
return NULL;
@@ -605,7 +634,8 @@ struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p, vrf_id_t vrf_id)
if (!match)
return NULL;
- if (match->type == ZEBRA_ROUTE_CONNECT)
+ if (match->type == ZEBRA_ROUTE_CONNECT ||
+ match->type == ZEBRA_ROUTE_LOCAL)
return match;
if (CHECK_FLAG(match->status, ROUTE_ENTRY_INSTALLED))
@@ -1104,27 +1134,15 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf,
UNSET_FLAG(new->status, ROUTE_ENTRY_CHANGED);
}
-/* Check if 'alternate' RIB entry is better than 'current'. */
-static struct route_entry *rib_choose_best(struct route_entry *current,
- struct route_entry *alternate)
+static struct route_entry *rib_choose_best_type(uint8_t route_type,
+ struct route_entry *current,
+ struct route_entry *alternate)
{
- if (current == NULL)
- return alternate;
-
- /* filter route selection in following order:
- * - connected beats other types
- * - if both connected, loopback or vrf wins
- * - lower distance beats higher
- * - lower metric beats higher for equal distance
- * - last, hence oldest, route wins tie break.
- */
-
- /* Connected routes. Check to see if either are a vrf
- * or loopback interface. If not, pick the last connected
- * route of the set of lowest metric connected routes.
+ /*
+ * We know that alternate and current are now non-NULL
*/
- if (alternate->type == ZEBRA_ROUTE_CONNECT) {
- if (current->type != ZEBRA_ROUTE_CONNECT)
+ if (alternate->type == route_type) {
+ if (current->type != route_type)
return alternate;
/* both are connected. are either loop or vrf? */
@@ -1153,7 +1171,41 @@ static struct route_entry *rib_choose_best(struct route_entry *current,
return current;
}
- if (current->type == ZEBRA_ROUTE_CONNECT)
+ return NULL;
+}
+
+/* Check if 'alternate' RIB entry is better than 'current'. */
+static struct route_entry *rib_choose_best(struct route_entry *current,
+ struct route_entry *alternate)
+{
+ struct route_entry *possible;
+
+ if (current == NULL)
+ return alternate;
+
+ /* filter route selection in following order:
+ * - Local beats Connected
+ * - connected beats other types
+ * - if both connected, loopback or vrf wins
+ * - lower distance beats higher
+ * - lower metric beats higher for equal distance
+ * - last, hence oldest, route wins tie break.
+ */
+
+ /* Connected or Local routes. Check to see if either are a vrf
+ * or loopback interface. If not, pick the last connected
+ * route of the set of lowest metric connected routes.
+ */
+ possible = rib_choose_best_type(ZEBRA_ROUTE_LOCAL, current, alternate);
+ if (possible)
+ return possible;
+
+ possible = rib_choose_best_type(ZEBRA_ROUTE_CONNECT, current, alternate);
+ if (possible)
+ return possible;
+
+ if (current->type == ZEBRA_ROUTE_CONNECT ||
+ current->type == ZEBRA_ROUTE_LOCAL)
return current;
/* higher distance loses */
@@ -1182,6 +1234,7 @@ static void rib_process(struct route_node *rn)
rib_dest_t *dest;
struct zebra_vrf *zvrf = NULL;
struct vrf *vrf;
+ struct route_entry *proto_re_changed = NULL;
vrf_id_t vrf_id = VRF_UNKNOWN;
@@ -1251,6 +1304,7 @@ static void rib_process(struct route_node *rn)
* skip it.
*/
if (CHECK_FLAG(re->status, ROUTE_ENTRY_CHANGED)) {
+ proto_re_changed = re;
if (!nexthop_active_update(rn, re)) {
const struct prefix *p;
struct rib_table_info *info;
@@ -1336,6 +1390,8 @@ static void rib_process(struct route_node *rn)
* new_selected --- RE entry that is newly SELECTED
* old_fib --- RE entry currently in kernel FIB
* new_fib --- RE entry that is newly to be in kernel FIB
+ * proto_re_changed -- RE that is the last changed entry in the
+ * list of RE's.
*
* new_selected will get SELECTED flag, and is going to be redistributed
* the zclients. new_fib (which can be new_selected) will be installed
@@ -1390,6 +1446,22 @@ static void rib_process(struct route_node *rn)
}
}
+ /*
+ * If zebra has a new_selected and a proto_re_changed
+ * entry that was not the old selected and the protocol
+ * is different, zebra should notify the upper level
+ * protocol that the sent down entry was not selected
+ */
+ if (new_selected && proto_re_changed &&
+ proto_re_changed != old_selected &&
+ new_selected->type != proto_re_changed->type) {
+ struct rib_table_info *info = srcdest_rnode_table_info(rn);
+
+ zsend_route_notify_owner(rn, proto_re_changed,
+ ZAPI_ROUTE_BETTER_ADMIN_WON, info->afi,
+ info->safi);
+ }
+
/* Update fib according to selection results */
if (new_fib && old_fib)
rib_process_update_fib(zvrf, rn, old_fib, new_fib);
@@ -1438,7 +1510,7 @@ static void zebra_rib_evaluate_mpls(struct route_node *rn)
*/
static bool rib_route_match_ctx(const struct route_entry *re,
const struct zebra_dplane_ctx *ctx,
- bool is_update)
+ bool is_update, bool async)
{
bool result = false;
@@ -1454,13 +1526,12 @@ static bool rib_route_match_ctx(const struct route_entry *re,
/* We use an extra test for statics, and another for
* kernel routes.
*/
- if (re->type == ZEBRA_ROUTE_STATIC &&
+ if (re->type == ZEBRA_ROUTE_STATIC && !async &&
(re->distance != dplane_ctx_get_old_distance(ctx) ||
re->tag != dplane_ctx_get_old_tag(ctx))) {
result = false;
} else if (re->type == ZEBRA_ROUTE_KERNEL &&
- re->metric !=
- dplane_ctx_get_old_metric(ctx)) {
+ re->metric != dplane_ctx_get_old_metric(ctx)) {
result = false;
}
}
@@ -1482,14 +1553,15 @@ static bool rib_route_match_ctx(const struct route_entry *re,
/* We use an extra test for statics, and another for
* kernel routes.
*/
- if (re->type == ZEBRA_ROUTE_STATIC &&
+ if (re->type == ZEBRA_ROUTE_STATIC && !async &&
(re->distance != dplane_ctx_get_distance(ctx) ||
re->tag != dplane_ctx_get_tag(ctx))) {
result = false;
} else if (re->type == ZEBRA_ROUTE_KERNEL &&
re->metric != dplane_ctx_get_metric(ctx)) {
result = false;
- } else if (re->type == ZEBRA_ROUTE_CONNECT) {
+ } else if (re->type == ZEBRA_ROUTE_CONNECT ||
+ re->type == ZEBRA_ROUTE_LOCAL) {
result = nexthop_group_equal_no_recurse(
&re->nhe->nhg, dplane_ctx_get_ng(ctx));
}
@@ -1547,7 +1619,7 @@ static bool rib_compare_routes(const struct route_entry *re1,
* v6 link-locals, and we also support multiple addresses in the same
* subnet on a single interface.
*/
- if (re1->type != ZEBRA_ROUTE_CONNECT)
+ if (re1->type != ZEBRA_ROUTE_CONNECT && re1->type != ZEBRA_ROUTE_LOCAL)
return true;
return false;
@@ -1946,13 +2018,13 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx)
RNODE_FOREACH_RE(rn, rib) {
if (re == NULL) {
- if (rib_route_match_ctx(rib, ctx, false))
+ if (rib_route_match_ctx(rib, ctx, false, false))
re = rib;
}
/* Check for old route match */
if (is_update && (old_re == NULL)) {
- if (rib_route_match_ctx(rib, ctx, true /*is_update*/))
+ if (rib_route_match_ctx(rib, ctx, true, false))
old_re = rib;
}
@@ -1997,9 +2069,7 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx)
UNSET_FLAG(old_re->status, ROUTE_ENTRY_QUEUED);
}
- switch (op) {
- case DPLANE_OP_ROUTE_INSTALL:
- case DPLANE_OP_ROUTE_UPDATE:
+ if (op == DPLANE_OP_ROUTE_INSTALL || op == DPLANE_OP_ROUTE_UPDATE) {
if (status == ZEBRA_DPLANE_REQUEST_SUCCESS) {
if (re) {
UNSET_FLAG(re->status, ROUTE_ENTRY_FAILED);
@@ -2090,8 +2160,7 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx)
VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx),
dplane_ctx_get_table(ctx), rn);
}
- break;
- case DPLANE_OP_ROUTE_DELETE:
+ } else if (op == DPLANE_OP_ROUTE_DELETE) {
rt_delete = true;
if (re)
SET_FLAG(re->status, ROUTE_ENTRY_FAILED);
@@ -2130,60 +2199,6 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx)
if ((re && RIB_SYSTEM_ROUTE(re)) ||
(old_re && RIB_SYSTEM_ROUTE(old_re)))
zebra_rib_fixup_system(rn);
- break;
-
- case DPLANE_OP_NONE:
- case DPLANE_OP_ROUTE_NOTIFY:
- case DPLANE_OP_NH_INSTALL:
- case DPLANE_OP_NH_UPDATE:
- case DPLANE_OP_NH_DELETE:
- case DPLANE_OP_LSP_INSTALL:
- case DPLANE_OP_LSP_UPDATE:
- case DPLANE_OP_LSP_DELETE:
- case DPLANE_OP_LSP_NOTIFY:
- case DPLANE_OP_PW_INSTALL:
- case DPLANE_OP_PW_UNINSTALL:
- case DPLANE_OP_SYS_ROUTE_ADD:
- case DPLANE_OP_SYS_ROUTE_DELETE:
- case DPLANE_OP_ADDR_INSTALL:
- case DPLANE_OP_ADDR_UNINSTALL:
- case DPLANE_OP_MAC_INSTALL:
- case DPLANE_OP_MAC_DELETE:
- case DPLANE_OP_NEIGH_INSTALL:
- case DPLANE_OP_NEIGH_UPDATE:
- case DPLANE_OP_NEIGH_DELETE:
- case DPLANE_OP_VTEP_ADD:
- case DPLANE_OP_VTEP_DELETE:
- case DPLANE_OP_RULE_ADD:
- case DPLANE_OP_RULE_DELETE:
- case DPLANE_OP_RULE_UPDATE:
- case DPLANE_OP_NEIGH_DISCOVER:
- case DPLANE_OP_BR_PORT_UPDATE:
- case DPLANE_OP_IPTABLE_ADD:
- case DPLANE_OP_IPTABLE_DELETE:
- case DPLANE_OP_IPSET_ADD:
- case DPLANE_OP_IPSET_DELETE:
- case DPLANE_OP_IPSET_ENTRY_ADD:
- case DPLANE_OP_IPSET_ENTRY_DELETE:
- case DPLANE_OP_NEIGH_IP_INSTALL:
- case DPLANE_OP_NEIGH_IP_DELETE:
- case DPLANE_OP_NEIGH_TABLE_UPDATE:
- case DPLANE_OP_GRE_SET:
- case DPLANE_OP_INTF_ADDR_ADD:
- case DPLANE_OP_INTF_ADDR_DEL:
- case DPLANE_OP_INTF_NETCONFIG:
- case DPLANE_OP_INTF_INSTALL:
- case DPLANE_OP_INTF_UPDATE:
- case DPLANE_OP_INTF_DELETE:
- case DPLANE_OP_TC_QDISC_INSTALL:
- case DPLANE_OP_TC_QDISC_UNINSTALL:
- case DPLANE_OP_TC_CLASS_ADD:
- case DPLANE_OP_TC_CLASS_DELETE:
- case DPLANE_OP_TC_CLASS_UPDATE:
- case DPLANE_OP_TC_FILTER_ADD:
- case DPLANE_OP_TC_FILTER_DELETE:
- case DPLANE_OP_TC_FILTER_UPDATE:
- break;
}
zebra_rib_evaluate_rn_nexthops(rn, seq, rt_delete);
@@ -2271,7 +2286,7 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx)
* info.
*/
RNODE_FOREACH_RE(rn, re) {
- if (rib_route_match_ctx(re, ctx, false /*!update*/))
+ if (rib_route_match_ctx(re, ctx, false, true))
break;
}
@@ -2517,7 +2532,7 @@ static void process_subq_evpn(struct listnode *lnode)
static void process_subq_nhg(struct listnode *lnode)
{
struct nhg_ctx *ctx;
- struct nhg_hash_entry *nhe, *newnhe;
+ struct nhg_hash_entry *nhe, *newnhe, *oldnhe;
struct wq_nhg_wrapper *w;
uint8_t qindex = META_QUEUE_NHG;
@@ -2549,15 +2564,33 @@ static void process_subq_nhg(struct listnode *lnode)
subqueue2str(qindex));
/* Process incoming nhg update, probably from a proto daemon */
- newnhe = zebra_nhg_proto_add(nhe->id, nhe->type,
- nhe->zapi_instance,
- nhe->zapi_session, &nhe->nhg, 0);
+ if (w->deletion) {
+ /*
+ * Delete the received nhg id
+ */
+ oldnhe = zebra_nhg_proto_del(nhe->id, nhe->type);
+ if (oldnhe) {
+ zsend_nhg_notify(nhe->type, nhe->zapi_instance,
+ nhe->zapi_session, nhe->id,
+ ZAPI_NHG_REMOVED);
+ zebra_nhg_decrement_ref(oldnhe);
+ } else
+ zsend_nhg_notify(nhe->type, nhe->zapi_instance,
+ nhe->zapi_session, nhe->id,
+ ZAPI_NHG_REMOVE_FAIL);
- /* Report error to daemon via ZAPI */
- if (newnhe == NULL)
- zsend_nhg_notify(nhe->type, nhe->zapi_instance,
- nhe->zapi_session, nhe->id,
- ZAPI_NHG_FAIL_INSTALL);
+ } else {
+ newnhe = zebra_nhg_proto_add(nhe->id, nhe->type,
+ nhe->zapi_instance,
+ nhe->zapi_session,
+ &nhe->nhg, 0);
+
+ /* Report error to daemon via ZAPI */
+ if (newnhe == NULL)
+ zsend_nhg_notify(nhe->type, nhe->zapi_instance,
+ nhe->zapi_session, nhe->id,
+ ZAPI_NHG_FAIL_INSTALL);
+ }
/* Free temp nhe - we own that memory. */
zebra_nhg_free(nhe);
@@ -2660,6 +2693,7 @@ static void early_route_memory_free(struct zebra_early_route *ere)
if (ere->re_nhe)
zebra_nhg_free(ere->re_nhe);
+ zapi_re_opaque_free(ere->re->opaque);
XFREE(MTYPE_RE, ere->re);
XFREE(MTYPE_WQ_WRAPPER, ere);
}
@@ -2706,6 +2740,8 @@ static void process_subq_early_route_add(struct zebra_early_route *ere)
return;
}
} else {
+ struct nexthop *tmp_nh;
+
/* Lookup nhe from route information */
nhe = zebra_nhg_rib_find_nhe(ere->re_nhe, ere->afi);
if (!nhe) {
@@ -2723,6 +2759,22 @@ static void process_subq_early_route_add(struct zebra_early_route *ere)
early_route_memory_free(ere);
return;
}
+ for (ALL_NEXTHOPS(nhe->nhg, tmp_nh)) {
+ if (CHECK_FLAG(tmp_nh->flags, NEXTHOP_FLAG_EVPN)) {
+ struct ipaddr vtep_ip = {};
+
+ if (ere->afi == AFI_IP) {
+ vtep_ip.ipa_type = IPADDR_V4;
+ vtep_ip.ipaddr_v4 = tmp_nh->gate.ipv4;
+ } else {
+ vtep_ip.ipa_type = IPADDR_V6;
+ vtep_ip.ipaddr_v6 = tmp_nh->gate.ipv6;
+ }
+ zebra_rib_queue_evpn_route_add(
+ re->vrf_id, &tmp_nh->rmac, &vtep_ip,
+ &ere->p);
+ }
+ }
}
/*
@@ -2823,14 +2875,17 @@ static void process_subq_early_route_add(struct zebra_early_route *ere)
SET_FLAG(re->status, ROUTE_ENTRY_CHANGED);
rib_addnode(rn, re, 1);
+ dest = rib_dest_from_rnode(rn);
/* Free implicit route.*/
- if (same)
+ if (same) {
+ if (dest && same == dest->selected_fib)
+ SET_FLAG(same->status, ROUTE_ENTRY_ROUTE_REPLACING);
rib_delnode(rn, same);
+ }
/* See if we can remove some RE entries that are queued for
* removal, but won't be considered in rib processing.
*/
- dest = rib_dest_from_rnode(rn);
RNODE_FOREACH_RE_SAFE (rn, re, same) {
if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) {
/* If the route was used earlier, must retain it. */
@@ -2907,8 +2962,8 @@ static void process_subq_early_route_delete(struct zebra_early_route *ere)
struct nexthop *nh = NULL;
- if (ere->re->nhe)
- nh = ere->re->nhe->nhg.nexthop;
+ if (ere->re_nhe)
+ nh = ere->re_nhe->nhg.nexthop;
/* Lookup same type route. */
RNODE_FOREACH_RE (rn, re) {
@@ -2926,7 +2981,9 @@ static void process_subq_early_route_delete(struct zebra_early_route *ere)
if (re->type == ZEBRA_ROUTE_KERNEL &&
re->metric != ere->re->metric)
continue;
- if (re->type == ZEBRA_ROUTE_CONNECT && (rtnh = nh) &&
+ if ((re->type == ZEBRA_ROUTE_CONNECT ||
+ re->type == ZEBRA_ROUTE_LOCAL) &&
+ (rtnh = re->nhe->nhg.nexthop) &&
rtnh->type == NEXTHOP_TYPE_IFINDEX && nh) {
if (rtnh->ifindex != nh->ifindex)
continue;
@@ -3232,12 +3289,26 @@ static int rib_meta_queue_add(struct meta_queue *mq, void *data)
return -1;
/* Invariant: at this point we always have rn->info set. */
- if (CHECK_FLAG(rib_dest_from_rnode(rn)->flags,
- RIB_ROUTE_QUEUED(qindex))) {
- if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+ /* A route node must only be in one sub-queue at a time. */
+ if (CHECK_FLAG(rib_dest_from_rnode(rn)->flags, MQ_BIT_MASK)) {
+ if (IS_ZEBRA_DEBUG_RIB_DETAILED) {
+ /*
+ * curr_qindex_bitmask is power of 2, because a route node must only be in one sub-queue at a time,
+ * so for getting current sub-queue index from bitmask we may use part of classic msb function
+ * (find most significant set bit).
+ */
+ const uint32_t curr_qindex_bitmask = CHECK_FLAG(rib_dest_from_rnode(rn)->flags, MQ_BIT_MASK);
+ static const uint8_t pos[32] = { 0, 1, 28, 2, 29, 14, 24, 3,
+ 30, 22, 20, 15, 25, 17, 4, 8, 31, 27, 13, 23, 21, 19,
+ 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 };
+
+ curr_qindex = pos[(uint32_t)(curr_qindex_bitmask * 0x077CB531UL) >> 27];
+
rnode_debug(rn, re->vrf_id,
"rn %p is already queued in sub-queue %s",
- (void *)rn, subqueue2str(qindex));
+ (void *)rn, subqueue2str(curr_qindex));
+ }
+
return -1;
}
@@ -3286,7 +3357,8 @@ static int rib_meta_queue_nhg_ctx_add(struct meta_queue *mq, void *data)
return 0;
}
-static int rib_meta_queue_nhg_add(struct meta_queue *mq, void *data)
+static int rib_meta_queue_nhg_process(struct meta_queue *mq, void *data,
+ bool deletion)
{
struct nhg_hash_entry *nhe = NULL;
uint8_t qindex = META_QUEUE_NHG;
@@ -3301,6 +3373,7 @@ static int rib_meta_queue_nhg_add(struct meta_queue *mq, void *data)
w->type = WQ_NHG_WRAPPER_TYPE_NHG;
w->u.nhe = nhe;
+ w->deletion = deletion;
listnode_add(mq->subq[qindex], w);
mq->size++;
@@ -3312,6 +3385,16 @@ static int rib_meta_queue_nhg_add(struct meta_queue *mq, void *data)
return 0;
}
+static int rib_meta_queue_nhg_add(struct meta_queue *mq, void *data)
+{
+ return rib_meta_queue_nhg_process(mq, data, false);
+}
+
+static int rib_meta_queue_nhg_del(struct meta_queue *mq, void *data)
+{
+ return rib_meta_queue_nhg_process(mq, data, true);
+}
+
static int rib_meta_queue_evpn_add(struct meta_queue *mq, void *data)
{
listnode_add(mq->subq[META_QUEUE_EVPN], data);
@@ -3420,6 +3503,17 @@ int rib_queue_nhe_add(struct nhg_hash_entry *nhe)
}
/*
+ * Enqueue incoming nhg from proto daemon for processing
+ */
+int rib_queue_nhe_del(struct nhg_hash_entry *nhe)
+{
+ if (nhe == NULL)
+ return -1;
+
+ return mq_add_handler(nhe, rib_meta_queue_nhg_del);
+}
+
+/*
* Enqueue evpn route for processing
*/
int zebra_rib_queue_evpn_route_add(vrf_id_t vrf_id, const struct ethaddr *rmac,
@@ -3978,6 +4072,10 @@ void rib_delnode(struct route_node *rn, struct route_entry *re)
if (IS_ZEBRA_DEBUG_RIB)
rnode_debug(rn, re->vrf_id, "rn %p, re %p, removing",
(void *)rn, (void *)re);
+
+ if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+ route_entry_dump(&rn->p, NULL, re);
+
SET_FLAG(re->status, ROUTE_ENTRY_REMOVED);
afi = (rn->p.family == AF_INET)
@@ -4023,7 +4121,6 @@ static void _route_entry_dump_nh(const struct route_entry *re,
ifp ? ifp->name : "Unknown");
break;
case NEXTHOP_TYPE_IPV4:
- /* fallthrough */
case NEXTHOP_TYPE_IPV4_IFINDEX:
inet_ntop(AF_INET, &nexthop->gate, nhname, INET6_ADDRSTRLEN);
break;
@@ -4123,8 +4220,8 @@ void _route_entry_dump(const char *func, union prefixconstptr pp,
zclient_dump_route_flags(re->flags, flags_buf,
sizeof(flags_buf)),
_dump_re_status(re, status_buf, sizeof(status_buf)));
- zlog_debug("%s: nexthop_num == %u, nexthop_active_num == %u", straddr,
- nexthop_group_nexthop_num(&(re->nhe->nhg)),
+ zlog_debug("%s: tag == %u, nexthop_num == %u, nexthop_active_num == %u",
+ straddr, re->tag, nexthop_group_nexthop_num(&(re->nhe->nhg)),
nexthop_group_active_nexthop_num(&(re->nhe->nhg)));
/* Dump nexthops */
@@ -4161,10 +4258,10 @@ static int rib_meta_queue_early_route_add(struct meta_queue *mq, void *data)
mq->size++;
if (IS_ZEBRA_DEBUG_RIB_DETAILED)
- zlog_debug(
- "Route %pFX(%u) queued for processing into sub-queue %s",
- &ere->p, ere->re->vrf_id,
- subqueue2str(META_QUEUE_EARLY_ROUTE));
+ zlog_debug("Route %pFX(%u) (%s) queued for processing into sub-queue %s",
+ &ere->p, ere->re->vrf_id,
+ ere->deletion ? "delete" : "add",
+ subqueue2str(META_QUEUE_EARLY_ROUTE));
return 0;
}
@@ -4207,6 +4304,12 @@ struct route_entry *zebra_rib_route_entry_new(vrf_id_t vrf_id, int type,
return re;
}
+
+void zebra_rib_route_entry_free(struct route_entry *re)
+{
+ XFREE(MTYPE_RE, re);
+}
+
/*
* Internal route-add implementation; there are a couple of different public
* signatures. Callers in this path are responsible for the memory they
@@ -4704,6 +4807,21 @@ static void rib_process_dplane_results(struct event *thread)
struct dplane_ctx_list_head ctxlist;
bool shut_p = false;
+#ifdef HAVE_SCRIPTING
+ char *script_name =
+ frrscript_names_get_script_name(ZEBRA_ON_RIB_PROCESS_HOOK_CALL);
+
+ int ret = 1;
+ struct frrscript *fs = NULL;
+
+ if (script_name) {
+ fs = frrscript_new(script_name);
+ if (fs)
+ ret = frrscript_load(fs, ZEBRA_ON_RIB_PROCESS_HOOK_CALL,
+ NULL);
+ }
+#endif /* HAVE_SCRIPTING */
+
/* Dequeue a list of completed updates with one lock/unlock cycle */
do {
@@ -4737,24 +4855,7 @@ static void rib_process_dplane_results(struct event *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,
@@ -4859,8 +4960,12 @@ static void rib_process_dplane_results(struct event *thread)
case DPLANE_OP_BR_PORT_UPDATE:
case DPLANE_OP_NEIGH_TABLE_UPDATE:
case DPLANE_OP_GRE_SET:
+ case DPLANE_OP_SRV6_ENCAP_SRCADDR_SET:
case DPLANE_OP_NONE:
break;
+ case DPLANE_OP_STARTUP_STAGE:
+ zebra_ns_startup_continue(ctx);
+ break;
} /* Dispatch by op code */
@@ -4869,6 +4974,11 @@ static void rib_process_dplane_results(struct event *thread)
}
} while (1);
+
+#ifdef HAVE_SCRIPTING
+ if (fs)
+ frrscript_delete(fs);
+#endif
}
/*
@@ -4913,7 +5023,7 @@ static void check_route_info(void)
}
/* Routing information base initialize. */
-void rib_init(void)
+void zebra_rib_init(void)
{
check_route_info();
@@ -4925,6 +5035,20 @@ void rib_init(void)
zebra_dplane_init(rib_dplane_results);
}
+void zebra_rib_terminate(void)
+{
+ struct zebra_dplane_ctx *ctx;
+
+ EVENT_OFF(t_dplane);
+
+ ctx = dplane_ctx_dequeue(&rib_dplane_q);
+ while (ctx) {
+ dplane_ctx_fini(&ctx);
+
+ ctx = dplane_ctx_dequeue(&rib_dplane_q);
+ }
+}
+
/*
* vrf_id_get_next
*
@@ -4978,7 +5102,7 @@ struct route_table *rib_tables_iter_next(rib_tables_iter_t *iter)
iter->vrf_id = VRF_DEFAULT;
iter->afi_safi_ix = -1;
- /* Fall through */
+ fallthrough;
case RIB_TABLES_ITER_S_ITERATING:
iter->afi_safi_ix++;
diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c
index 3bbcd38d1c..b387e9949b 100644
--- a/zebra/zebra_rnh.c
+++ b/zebra/zebra_rnh.c
@@ -513,10 +513,14 @@ static bool rnh_check_re_nexthops(const struct route_entry *re,
goto done;
}
- /* Some special checks if registration asked for them. */
+ /*
+ * Some special checks if registration asked for them.
+ * LOCAL routes are by their definition not CONNECTED
+ * and as such should not be considered here
+ */
if (CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) {
- if ((re->type == ZEBRA_ROUTE_CONNECT)
- || (re->type == ZEBRA_ROUTE_STATIC))
+ if ((re->type == ZEBRA_ROUTE_CONNECT) ||
+ (re->type == ZEBRA_ROUTE_STATIC))
ret = true;
if (re->type == ZEBRA_ROUTE_NHRP) {
@@ -1268,6 +1272,7 @@ void show_nexthop_json_helper(json_object *json_nexthop,
json_object *json_backups = NULL;
json_object *json_seg6local = NULL;
json_object *json_seg6 = NULL;
+ json_object *json_segs = NULL;
int i;
json_object_int_add(json_nexthop, "flags", nexthop->flags);
@@ -1425,11 +1430,31 @@ void show_nexthop_json_helper(json_object *json_nexthop,
nexthop->nh_srv6->seg6local_action));
json_object_object_add(json_nexthop, "seg6local",
json_seg6local);
-
- json_seg6 = json_object_new_object();
- json_object_string_addf(json_seg6, "segs", "%pI6",
- &nexthop->nh_srv6->seg6_segs);
- json_object_object_add(json_nexthop, "seg6", json_seg6);
+ if (nexthop->nh_srv6->seg6_segs &&
+ nexthop->nh_srv6->seg6_segs->num_segs == 1) {
+ json_seg6 = json_object_new_object();
+ json_object_string_addf(json_seg6, "segs", "%pI6",
+ &nexthop->nh_srv6->seg6_segs
+ ->seg[0]);
+ json_object_object_add(json_nexthop, "seg6", json_seg6);
+ } else {
+ if (nexthop->nh_srv6->seg6_segs) {
+ json_segs = json_object_new_array();
+ for (int seg_idx = 0;
+ seg_idx <
+ nexthop->nh_srv6->seg6_segs->num_segs;
+ seg_idx++)
+ json_object_array_add(
+ json_segs,
+ json_object_new_stringf(
+ "%pI6",
+ &nexthop->nh_srv6
+ ->seg6_segs
+ ->seg[seg_idx]));
+ json_object_object_add(json_nexthop, "seg6",
+ json_segs);
+ }
+ }
}
}
@@ -1440,7 +1465,9 @@ void show_route_nexthop_helper(struct vty *vty, const struct route_entry *re,
const struct nexthop *nexthop)
{
char buf[MPLS_LABEL_STRLEN];
- int i;
+ char seg_buf[SRV6_SEG_STRLEN];
+ struct seg6_segs segs;
+ uint8_t i;
switch (nexthop->type) {
case NEXTHOP_TYPE_IPV4:
@@ -1532,11 +1559,23 @@ void show_route_nexthop_helper(struct vty *vty, const struct route_entry *re,
seg6local_context2str(buf, sizeof(buf),
&nexthop->nh_srv6->seg6local_ctx,
nexthop->nh_srv6->seg6local_action);
- vty_out(vty, ", seg6local %s %s",
- seg6local_action2str(
- nexthop->nh_srv6->seg6local_action),
- buf);
- vty_out(vty, ", seg6 %pI6", &nexthop->nh_srv6->seg6_segs);
+ if (nexthop->nh_srv6->seg6local_action !=
+ ZEBRA_SEG6_LOCAL_ACTION_UNSPEC)
+ vty_out(vty, ", seg6local %s %s",
+ seg6local_action2str(
+ nexthop->nh_srv6->seg6local_action),
+ buf);
+ if (nexthop->nh_srv6->seg6_segs &&
+ IPV6_ADDR_CMP(&nexthop->nh_srv6->seg6_segs->seg[0],
+ &in6addr_any)) {
+ segs.num_segs = nexthop->nh_srv6->seg6_segs->num_segs;
+ for (i = 0; i < segs.num_segs; i++)
+ memcpy(&segs.segs[i],
+ &nexthop->nh_srv6->seg6_segs->seg[i],
+ sizeof(struct in6_addr));
+ snprintf_seg6_segs(seg_buf, SRV6_SEG_STRLEN, &segs);
+ vty_out(vty, ", seg6 %s", seg_buf);
+ }
}
if (nexthop->weight)
diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c
index 142501b149..95da789108 100644
--- a/zebra/zebra_routemap.c
+++ b/zebra/zebra_routemap.c
@@ -14,7 +14,6 @@
#include "filter.h"
#include "plist.h"
#include "nexthop.h"
-#include "northbound_cli.h"
#include "lib/route_types.h"
#include "vrf.h"
#include "frrstr.h"
@@ -24,6 +23,7 @@
#include "zebra/debug.h"
#include "zebra/zebra_rnh.h"
#include "zebra/zebra_routemap.h"
+#include "zebra/zebra_vrf.h"
#include "zebra/zebra_routemap_clippy.c"
@@ -31,17 +31,11 @@ static uint32_t zebra_rmap_update_timer = ZEBRA_RMAP_DEFAULT_UPDATE_TIMER;
static struct event *zebra_t_rmap_update = NULL;
char *zebra_import_table_routemap[AFI_MAX][ZEBRA_KERNEL_TABLE_MAX];
-struct nh_rmap_obj {
+struct zebra_rmap_obj {
struct nexthop *nexthop;
- vrf_id_t vrf_id;
- uint32_t source_protocol;
- uint8_t instance;
- int metric;
- route_tag_t tag;
+ struct route_entry *re;
};
-static void zebra_route_map_set_delay_timer(uint32_t value);
-
/* 'match tag TAG'
* Match function return 1 if match is success else return 0
*/
@@ -49,12 +43,12 @@ static enum route_map_cmd_result_t
route_match_tag(void *rule, const struct prefix *prefix, void *object)
{
route_tag_t *tag;
- struct nh_rmap_obj *nh_data;
+ struct zebra_rmap_obj *rm_data;
tag = rule;
- nh_data = object;
+ rm_data = object;
- if (nh_data->tag == *tag)
+ if (rm_data->re->tag == *tag)
return RMAP_MATCH;
return RMAP_NOMATCH;
@@ -74,19 +68,19 @@ static const struct route_map_rule_cmd route_match_tag_cmd = {
static enum route_map_cmd_result_t
route_match_interface(void *rule, const struct prefix *prefix, void *object)
{
- struct nh_rmap_obj *nh_data;
+ struct zebra_rmap_obj *rm_data;
char *ifname = rule;
ifindex_t ifindex;
if (strcasecmp(ifname, "any") == 0)
return RMAP_MATCH;
- nh_data = object;
- if (!nh_data || !nh_data->nexthop)
+ rm_data = object;
+ if (!rm_data || !rm_data->nexthop)
return RMAP_NOMATCH;
- ifindex = ifname2ifindex(ifname, nh_data->vrf_id);
+ ifindex = ifname2ifindex(ifname, rm_data->nexthop->vrf_id);
if (ifindex == 0)
return RMAP_NOMATCH;
- if (nh_data->nexthop->ifindex == ifindex)
+ if (rm_data->nexthop->ifindex == ifindex)
return RMAP_MATCH;
return RMAP_NOMATCH;
@@ -288,8 +282,8 @@ static const struct route_map_rule_cmd route_match_interface_cmd = {
route_match_interface_free
};
-static int ip_protocol_rm_add(struct zebra_vrf *zvrf, const char *rmap,
- int rtype, afi_t afi, safi_t safi)
+int ip_protocol_rm_add(struct zebra_vrf *zvrf, const char *rmap, int rtype,
+ afi_t afi, safi_t safi)
{
struct route_table *table;
@@ -321,8 +315,8 @@ static int ip_protocol_rm_add(struct zebra_vrf *zvrf, const char *rmap,
return CMD_SUCCESS;
}
-static int ip_protocol_rm_del(struct zebra_vrf *zvrf, const char *rmap,
- int rtype, afi_t afi, safi_t safi)
+int ip_protocol_rm_del(struct zebra_vrf *zvrf, const char *rmap, int rtype,
+ afi_t afi, safi_t safi)
{
struct route_table *table;
@@ -350,8 +344,7 @@ static int ip_protocol_rm_del(struct zebra_vrf *zvrf, const char *rmap,
return CMD_SUCCESS;
}
-static int ip_nht_rm_add(struct zebra_vrf *zvrf, const char *rmap, int rtype,
- int afi)
+int ip_nht_rm_add(struct zebra_vrf *zvrf, const char *rmap, int rtype, int afi)
{
if (NHT_RM_NAME(zvrf, afi, rtype)) {
@@ -367,13 +360,12 @@ static int ip_nht_rm_add(struct zebra_vrf *zvrf, const char *rmap, int rtype,
route_map_counter_increment(NHT_RM_MAP(zvrf, afi, rtype));
if (NHT_RM_MAP(zvrf, afi, rtype))
- zebra_evaluate_rnh(zvrf, AFI_IP, 1, NULL, SAFI_UNICAST);
+ zebra_evaluate_rnh(zvrf, afi, 1, NULL, SAFI_UNICAST);
return CMD_SUCCESS;
}
-static int ip_nht_rm_del(struct zebra_vrf *zvrf, const char *rmap, int rtype,
- int afi)
+int ip_nht_rm_del(struct zebra_vrf *zvrf, const char *rmap, int rtype, int afi)
{
if (!NHT_RM_NAME(zvrf, afi, rtype))
@@ -388,358 +380,14 @@ static int ip_nht_rm_del(struct zebra_vrf *zvrf, const char *rmap, int rtype,
zvrf->vrf->vrf_id, rtype);
NHT_RM_MAP(zvrf, afi, rtype) = NULL;
- zebra_evaluate_rnh(zvrf, AFI_IP, 1, NULL, SAFI_UNICAST);
+ zebra_evaluate_rnh(zvrf, afi, 1, NULL, SAFI_UNICAST);
}
XFREE(MTYPE_ROUTE_MAP_NAME, NHT_RM_NAME(zvrf, afi, rtype));
}
return CMD_SUCCESS;
}
-DEFPY_YANG(
- match_ip_address_prefix_len, match_ip_address_prefix_len_cmd,
- "match ip address prefix-len (0-32)$length",
- MATCH_STR
- IP_STR
- "Match prefix length of IP address\n"
- "Match prefix length of IP address\n"
- "Prefix length\n")
-{
- const char *xpath =
- "./match-condition[condition='frr-zebra-route-map:ipv4-prefix-length']";
- char xpath_value[XPATH_MAXLEN];
-
- nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
- snprintf(
- xpath_value, sizeof(xpath_value),
- "%s/rmap-match-condition/frr-zebra-route-map:ipv4-prefix-length",
- xpath);
- nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, length_str);
-
- return nb_cli_apply_changes(vty, NULL);
-}
-
-DEFPY_YANG(
- no_match_ip_address_prefix_len, no_match_ip_address_prefix_len_cmd,
- "no match ip address prefix-len [(0-32)]",
- NO_STR
- MATCH_STR
- IP_STR
- "Match prefix length of IP address\n"
- "Match prefix length of IP address\n"
- "Prefix length\n")
-{
- const char *xpath =
- "./match-condition[condition='frr-zebra-route-map:ipv4-prefix-length']";
-
- nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
-
- return nb_cli_apply_changes(vty, NULL);
-}
-
-DEFPY_YANG(
- match_ipv6_address_prefix_len, match_ipv6_address_prefix_len_cmd,
- "match ipv6 address prefix-len (0-128)$length",
- MATCH_STR
- IPV6_STR
- "Match prefix length of IPv6 address\n"
- "Match prefix length of IPv6 address\n"
- "Prefix length\n")
-{
- const char *xpath =
- "./match-condition[condition='frr-zebra-route-map:ipv6-prefix-length']";
- char xpath_value[XPATH_MAXLEN];
-
- nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
- snprintf(
- xpath_value, sizeof(xpath_value),
- "%s/rmap-match-condition/frr-zebra-route-map:ipv6-prefix-length",
- xpath);
- nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, length_str);
-
- return nb_cli_apply_changes(vty, NULL);
-}
-
-DEFPY_YANG(
- no_match_ipv6_address_prefix_len, no_match_ipv6_address_prefix_len_cmd,
- "no match ipv6 address prefix-len [(0-128)]",
- NO_STR
- MATCH_STR
- IPV6_STR
- "Match prefix length of IPv6 address\n"
- "Match prefix length of IPv6 address\n"
- "Prefix length\n")
-{
- const char *xpath =
- "./match-condition[condition='frr-zebra-route-map:ipv6-prefix-length']";
-
- nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
-
- return nb_cli_apply_changes(vty, NULL);
-}
-
-DEFPY_YANG(
- match_ip_nexthop_prefix_len, match_ip_nexthop_prefix_len_cmd,
- "match ip next-hop prefix-len (0-32)$length",
- MATCH_STR
- IP_STR
- "Match prefixlen of nexthop IP address\n"
- "Match prefixlen of given nexthop\n"
- "Prefix length\n")
-{
- const char *xpath =
- "./match-condition[condition='frr-zebra-route-map:ipv4-next-hop-prefix-length']";
- char xpath_value[XPATH_MAXLEN];
-
- nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
- snprintf(
- xpath_value, sizeof(xpath_value),
- "%s/rmap-match-condition/frr-zebra-route-map:ipv4-prefix-length",
- xpath);
- nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, length_str);
-
- return nb_cli_apply_changes(vty, NULL);
-}
-
-DEFPY_YANG(
- no_match_ip_nexthop_prefix_len, no_match_ip_nexthop_prefix_len_cmd,
- "no match ip next-hop prefix-len [(0-32)]",
- NO_STR
- MATCH_STR
- IP_STR
- "Match prefixlen of nexthop IP address\n"
- "Match prefix length of nexthop\n"
- "Prefix length\n")
-{
- const char *xpath =
- "./match-condition[condition='frr-zebra-route-map:ipv4-next-hop-prefix-length']";
-
- nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
-
- return nb_cli_apply_changes(vty, NULL);
-}
-
-DEFPY_YANG(
- match_source_protocol, match_source_protocol_cmd,
- "match source-protocol " FRR_REDIST_STR_ZEBRA "$proto",
- MATCH_STR
- "Match protocol via which the route was learnt\n"
- FRR_REDIST_HELP_STR_ZEBRA)
-{
- const char *xpath =
- "./match-condition[condition='frr-zebra-route-map:source-protocol']";
- char xpath_value[XPATH_MAXLEN];
-
- nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
- snprintf(xpath_value, sizeof(xpath_value),
- "%s/rmap-match-condition/frr-zebra-route-map:source-protocol",
- xpath);
- nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, proto);
-
- return nb_cli_apply_changes(vty, NULL);
-}
-
-DEFPY_YANG(
- no_match_source_protocol, no_match_source_protocol_cmd,
- "no match source-protocol [" FRR_REDIST_STR_ZEBRA "]",
- NO_STR
- MATCH_STR
- "Match protocol via which the route was learnt\n"
- FRR_REDIST_HELP_STR_ZEBRA)
-{
- const char *xpath =
- "./match-condition[condition='frr-zebra-route-map:source-protocol']";
-
- nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
-
- return nb_cli_apply_changes(vty, NULL);
-}
-
-DEFPY_YANG(
- match_source_instance, match_source_instance_cmd,
- "match source-instance (0-255)$instance",
- MATCH_STR
- "Match the protocol's instance number\n"
- "The instance number\n")
-{
- const char *xpath =
- "./match-condition[condition='frr-zebra-route-map:source-instance']";
- char xpath_value[XPATH_MAXLEN];
-
- nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
- snprintf(xpath_value, sizeof(xpath_value),
- "%s/rmap-match-condition/frr-zebra-route-map:source-instance",
- xpath);
- nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, instance_str);
-
- return nb_cli_apply_changes(vty, NULL);
-}
-
-DEFPY_YANG(
- no_match_source_instance, no_match_source_instance_cmd,
- "no match source-instance [(0-255)]",
- NO_STR MATCH_STR
- "Match the protocol's instance number\n"
- "The instance number\n")
-{
- const char *xpath =
- "./match-condition[condition='frr-zebra-route-map:source-instance']";
-
- nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
-
- return nb_cli_apply_changes(vty, NULL);
-}
-
-/* set functions */
-
-DEFPY_YANG(
- set_src, set_src_cmd,
- "set src <A.B.C.D$addrv4|X:X::X:X$addrv6>",
- SET_STR
- "src address for route\n"
- "IPv4 src address\n"
- "IPv6 src address\n")
-{
- const char *xpath =
- "./set-action[action='frr-zebra-route-map:src-address']";
- char xpath_value[XPATH_MAXLEN];
-
- nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
- if (addrv4_str) {
- snprintf(
- xpath_value, sizeof(xpath_value),
- "%s/rmap-set-action/frr-zebra-route-map:ipv4-src-address",
- xpath);
- nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
- addrv4_str);
- } else {
- snprintf(
- xpath_value, sizeof(xpath_value),
- "%s/rmap-set-action/frr-zebra-route-map:ipv6-src-address",
- xpath);
- nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
- addrv6_str);
- }
-
- return nb_cli_apply_changes(vty, NULL);
-}
-
-DEFPY_YANG(
- no_set_src, no_set_src_cmd,
- "no set src [<A.B.C.D|X:X::X:X>]",
- NO_STR
- SET_STR
- "Source address for route\n"
- "IPv4 address\n"
- "IPv6 address\n")
-{
- const char *xpath =
- "./set-action[action='frr-zebra-route-map:src-address']";
-
- nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
-
- return nb_cli_apply_changes(vty, NULL);
-}
-
-DEFUN_YANG (zebra_route_map_timer,
- zebra_route_map_timer_cmd,
- "zebra route-map delay-timer (0-600)",
- ZEBRA_STR
- "Set route-map parameters\n"
- "Time to wait before route-map updates are processed\n"
- "0 means route-map changes are run immediately instead of delaying\n")
-{
- int idx_number = 3;
- uint32_t rmap_delay_timer;
-
- rmap_delay_timer = strtoul(argv[idx_number]->arg, NULL, 10);
- zebra_route_map_set_delay_timer(rmap_delay_timer);
-
- return (CMD_SUCCESS);
-}
-
-DEFUN_YANG (no_zebra_route_map_timer,
- no_zebra_route_map_timer_cmd,
- "no zebra route-map delay-timer [(0-600)]",
- NO_STR
- ZEBRA_STR
- "Set route-map parameters\n"
- "Reset delay-timer to default value, 30 secs\n"
- "0 means route-map changes are run immediately instead of delaying\n")
-{
- zebra_route_map_set_delay_timer(ZEBRA_RMAP_DEFAULT_UPDATE_TIMER);
-
- return (CMD_SUCCESS);
-}
-
-DEFPY_YANG (ip_protocol,
- ip_protocol_cmd,
- "ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
- " $proto route-map ROUTE-MAP$rmap",
- IP_STR
- "Filter routing info exchanged between zebra and protocol\n"
- FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
- "Specify route-map\n"
- "Route map name\n")
-{
- int ret, rtype;
-
- assert(proto);
- assert(rmap);
-
- ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
-
- if (!zvrf)
- return CMD_WARNING;
-
- if (strcasecmp(proto, "any") == 0)
- rtype = ZEBRA_ROUTE_MAX;
- else
- rtype = proto_name2num(proto);
- if (rtype < 0) {
- vty_out(vty, "invalid protocol name \"%s\"\n", proto);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- ret = ip_protocol_rm_add(zvrf, rmap, rtype, AFI_IP, SAFI_UNICAST);
-
- return ret;
-}
-
-DEFPY_YANG (no_ip_protocol,
- no_ip_protocol_cmd,
- "no ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
- " $proto [route-map ROUTE-MAP$rmap]",
- NO_STR
- IP_STR
- "Stop filtering routing info between zebra and protocol\n"
- FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
- "Specify route-map\n"
- "Route map name\n")
-{
- int ret, rtype;
-
- assert(proto);
-
- ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
-
- if (!zvrf)
- return CMD_WARNING;
-
- if (strcasecmp(proto, "any") == 0)
- rtype = ZEBRA_ROUTE_MAX;
- else
- rtype = proto_name2num(proto);
- if (rtype < 0) {
- vty_out(vty, "invalid protocol name \"%s\"\n", proto);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- ret = ip_protocol_rm_del(zvrf, rmap, rtype, AFI_IP, SAFI_UNICAST);
-
- return ret;
-}
-
-DEFPY_YANG (show_ip_protocol,
+DEFPY (show_ip_protocol,
show_ip_protocol_cmd,
"show ip protocol [vrf <NAME$vrf_name|all$vrf_all>]",
SHOW_STR
@@ -752,75 +400,7 @@ DEFPY_YANG (show_ip_protocol,
return ret;
}
-DEFPY_YANG (ipv6_protocol,
- ipv6_protocol_cmd,
- "ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
- " $proto route-map ROUTE-MAP$rmap",
- IP6_STR
- "Filter IPv6 routing info exchanged between zebra and protocol\n"
- FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
- "Specify route-map\n"
- "Route map name\n")
-{
- int ret, rtype;
-
- assert(rmap);
- assert(proto);
-
- ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
-
- if (!zvrf)
- return CMD_WARNING;
-
- if (strcasecmp(proto, "any") == 0)
- rtype = ZEBRA_ROUTE_MAX;
- else
- rtype = proto_name2num(proto);
- if (rtype < 0) {
- vty_out(vty, "invalid protocol name \"%s\"\n", proto);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- ret = ip_protocol_rm_add(zvrf, rmap, rtype, AFI_IP6, SAFI_UNICAST);
-
- return ret;
-}
-
-DEFPY_YANG (no_ipv6_protocol,
- no_ipv6_protocol_cmd,
- "no ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
- " $proto [route-map ROUTE-MAP$rmap]",
- NO_STR
- IP6_STR
- "Stop filtering IPv6 routing info between zebra and protocol\n"
- FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
- "Specify route-map\n"
- "Route map name\n")
-{
- int ret, rtype;
-
- assert(proto);
-
- ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
-
- if (!zvrf)
- return CMD_WARNING;
-
- if (strcasecmp(proto, "any") == 0)
- rtype = ZEBRA_ROUTE_MAX;
- else
- rtype = proto_name2num(proto);
- if (rtype < 0) {
- vty_out(vty, "invalid protocol name \"%s\"\n", proto);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- ret = ip_protocol_rm_del(zvrf, rmap, rtype, AFI_IP6, SAFI_UNICAST);
-
- return ret;
-}
-
-DEFPY_YANG (show_ipv6_protocol,
+DEFPY (show_ipv6_protocol,
show_ipv6_protocol_cmd,
"show ipv6 protocol [vrf <NAME$vrf_name|all$vrf_all>]",
SHOW_STR
@@ -833,76 +413,7 @@ DEFPY_YANG (show_ipv6_protocol,
return ret;
}
-DEFPY_YANG (ip_protocol_nht_rmap,
- ip_protocol_nht_rmap_cmd,
- "ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
- " $proto route-map ROUTE-MAP$rmap",
- IP_STR
- "Filter Next Hop tracking route resolution\n"
- FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
- "Specify route map\n"
- "Route map name\n")
-{
-
- int ret, rtype;
-
- assert(proto);
- assert(rmap);
-
- ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
-
- if (!zvrf)
- return CMD_WARNING;
-
- if (strcasecmp(proto, "any") == 0)
- rtype = ZEBRA_ROUTE_MAX;
- else
- rtype = proto_name2num(proto);
- if (rtype < 0) {
- vty_out(vty, "invalid protocol name \"%s\"\n", proto);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- ret = ip_nht_rm_add(zvrf, rmap, rtype, AFI_IP);
-
- return ret;
-}
-
-DEFPY_YANG (no_ip_protocol_nht_rmap,
- no_ip_protocol_nht_rmap_cmd,
- "no ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
- " $proto route-map [ROUTE-MAP$rmap]",
- NO_STR
- IP_STR
- "Filter Next Hop tracking route resolution\n"
- FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
- "Specify route map\n"
- "Route map name\n")
-{
- int ret, rtype;
-
- assert(proto);
-
- ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
-
- if (!zvrf)
- return CMD_WARNING;
-
- if (strcasecmp(proto, "any") == 0)
- rtype = ZEBRA_ROUTE_MAX;
- else
- rtype = proto_name2num(proto);
- if (rtype < 0) {
- vty_out(vty, "invalid protocol name \"%s\"\n", proto);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- ret = ip_nht_rm_del(zvrf, rmap, rtype, AFI_IP);
-
- return ret;
-}
-
-DEFPY_YANG (show_ip_protocol_nht,
+DEFPY (show_ip_protocol_nht,
show_ip_protocol_nht_cmd,
"show ip nht route-map [vrf <NAME$vrf_name|all$vrf_all>] [json]",
SHOW_STR
@@ -921,75 +432,7 @@ DEFPY_YANG (show_ip_protocol_nht,
return ret;
}
-DEFPY_YANG (ipv6_protocol_nht_rmap,
- ipv6_protocol_nht_rmap_cmd,
- "ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
- " $proto route-map ROUTE-MAP$rmap",
- IP6_STR
- "Filter Next Hop tracking route resolution\n"
- FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
- "Specify route map\n"
- "Route map name\n")
-{
- int ret, rtype;
-
- assert(rmap);
- assert(proto);
-
- ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
-
- if (!zvrf)
- return CMD_WARNING;
-
- if (strcasecmp(proto, "any") == 0)
- rtype = ZEBRA_ROUTE_MAX;
- else
- rtype = proto_name2num(proto);
- if (rtype < 0) {
- vty_out(vty, "invalid protocol name \"%s\"\n", proto);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- ret = ip_nht_rm_add(zvrf, rmap, rtype, AFI_IP6);
-
- return ret;
-}
-
-DEFPY_YANG (no_ipv6_protocol_nht_rmap,
- no_ipv6_protocol_nht_rmap_cmd,
- "no ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
- " $proto [route-map ROUTE-MAP$rmap]",
- NO_STR
- IP6_STR
- "Filter Next Hop tracking route resolution\n"
- FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
- "Specify route map\n"
- "Route map name\n")
-{
- int ret, rtype;
-
- assert(proto);
-
- ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
-
- if (!zvrf)
- return CMD_WARNING;
-
- if (strcasecmp(proto, "any") == 0)
- rtype = ZEBRA_ROUTE_MAX;
- else
- rtype = proto_name2num(proto);
- if (rtype < 0) {
- vty_out(vty, "invalid protocol name \"%s\"\n", proto);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- ret = ip_nht_rm_del(zvrf, rmap, rtype, AFI_IP6);
-
- return ret;
-}
-
-DEFPY_YANG (show_ipv6_protocol_nht,
+DEFPY (show_ipv6_protocol_nht,
show_ipv6_protocol_nht_cmd,
"show ipv6 nht route-map [vrf <NAME$vrf_name|all$vrf_all>] [json]",
SHOW_STR
@@ -1017,21 +460,21 @@ static enum route_map_cmd_result_t
route_match_ip_next_hop(void *rule, const struct prefix *prefix, void *object)
{
struct access_list *alist;
- struct nh_rmap_obj *nh_data;
+ struct zebra_rmap_obj *rm_data;
struct prefix_ipv4 p;
- nh_data = object;
- if (!nh_data)
+ rm_data = object;
+ if (!rm_data)
return RMAP_NOMATCH;
- switch (nh_data->nexthop->type) {
+ switch (rm_data->nexthop->type) {
case NEXTHOP_TYPE_IFINDEX:
/* Interface routes can't match ip next-hop */
return RMAP_NOMATCH;
case NEXTHOP_TYPE_IPV4_IFINDEX:
case NEXTHOP_TYPE_IPV4:
p.family = AF_INET;
- p.prefix = nh_data->nexthop->gate.ipv4;
+ p.prefix = rm_data->nexthop->gate.ipv4;
p.prefixlen = IPV4_MAX_BITLEN;
break;
case NEXTHOP_TYPE_IPV6:
@@ -1080,21 +523,21 @@ route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix,
void *object)
{
struct prefix_list *plist;
- struct nh_rmap_obj *nh_data;
+ struct zebra_rmap_obj *rm_data;
struct prefix_ipv4 p;
- nh_data = (struct nh_rmap_obj *)object;
- if (!nh_data)
+ rm_data = (struct zebra_rmap_obj *)object;
+ if (!rm_data)
return RMAP_NOMATCH;
- switch (nh_data->nexthop->type) {
+ switch (rm_data->nexthop->type) {
case NEXTHOP_TYPE_IFINDEX:
/* Interface routes can't match ip next-hop */
return RMAP_NOMATCH;
case NEXTHOP_TYPE_IPV4_IFINDEX:
case NEXTHOP_TYPE_IPV4:
p.family = AF_INET;
- p.prefix = nh_data->nexthop->gate.ipv4;
+ p.prefix = rm_data->nexthop->gate.ipv4;
p.prefixlen = IPV4_MAX_BITLEN;
break;
case NEXTHOP_TYPE_IPV6:
@@ -1264,14 +707,14 @@ static enum route_map_cmd_result_t
route_match_ipv6_next_hop_type(void *rule, const struct prefix *prefix,
void *object)
{
- struct nh_rmap_obj *nh_data;
+ struct zebra_rmap_obj *rm_data;
if (prefix->family == AF_INET6) {
- nh_data = (struct nh_rmap_obj *)object;
- if (!nh_data)
+ rm_data = (struct zebra_rmap_obj *)object;
+ if (!rm_data)
return RMAP_NOMATCH;
- if (nh_data->nexthop->type == NEXTHOP_TYPE_BLACKHOLE)
+ if (rm_data->nexthop->type == NEXTHOP_TYPE_BLACKHOLE)
return RMAP_MATCH;
}
@@ -1356,21 +799,21 @@ route_match_ip_nexthop_prefix_len(void *rule, const struct prefix *prefix,
void *object)
{
uint32_t *prefixlen = (uint32_t *)rule;
- struct nh_rmap_obj *nh_data;
+ struct zebra_rmap_obj *rm_data;
struct prefix_ipv4 p;
- nh_data = (struct nh_rmap_obj *)object;
- if (!nh_data || !nh_data->nexthop)
+ rm_data = (struct zebra_rmap_obj *)object;
+ if (!rm_data || !rm_data->nexthop)
return RMAP_NOMATCH;
- switch (nh_data->nexthop->type) {
+ switch (rm_data->nexthop->type) {
case NEXTHOP_TYPE_IFINDEX:
/* Interface routes can't match ip next-hop */
return RMAP_NOMATCH;
case NEXTHOP_TYPE_IPV4_IFINDEX:
case NEXTHOP_TYPE_IPV4:
p.family = AF_INET;
- p.prefix = nh_data->nexthop->gate.ipv4;
+ p.prefix = rm_data->nexthop->gate.ipv4;
p.prefixlen = IPV4_MAX_BITLEN;
break;
case NEXTHOP_TYPE_IPV6:
@@ -1395,14 +838,14 @@ static enum route_map_cmd_result_t
route_match_ip_next_hop_type(void *rule, const struct prefix *prefix,
void *object)
{
- struct nh_rmap_obj *nh_data;
+ struct zebra_rmap_obj *rm_data;
if (prefix->family == AF_INET) {
- nh_data = (struct nh_rmap_obj *)object;
- if (!nh_data)
+ rm_data = (struct zebra_rmap_obj *)object;
+ if (!rm_data)
return RMAP_NOMATCH;
- if (nh_data->nexthop->type == NEXTHOP_TYPE_BLACKHOLE)
+ if (rm_data->nexthop->type == NEXTHOP_TYPE_BLACKHOLE)
return RMAP_MATCH;
}
@@ -1432,15 +875,14 @@ static const struct route_map_rule_cmd
static enum route_map_cmd_result_t
route_match_source_protocol(void *rule, const struct prefix *p, void *object)
{
- uint32_t *rib_type = (uint32_t *)rule;
- struct nh_rmap_obj *nh_data;
+ int32_t *rib_type = (int32_t *)rule;
+ struct zebra_rmap_obj *rm_data;
- nh_data = (struct nh_rmap_obj *)object;
- if (!nh_data)
+ rm_data = (struct zebra_rmap_obj *)object;
+ if (!rm_data)
return RMAP_NOMATCH;
- return ((nh_data->source_protocol == *rib_type) ? RMAP_MATCH
- : RMAP_NOMATCH);
+ return ((rm_data->re->type == *rib_type) ? RMAP_MATCH : RMAP_NOMATCH);
}
static void *route_match_source_protocol_compile(const char *arg)
@@ -1473,13 +915,13 @@ static enum route_map_cmd_result_t
route_match_source_instance(void *rule, const struct prefix *p, void *object)
{
uint8_t *instance = (uint8_t *)rule;
- struct nh_rmap_obj *nh_data;
+ struct zebra_rmap_obj *rm_data;
- nh_data = (struct nh_rmap_obj *)object;
- if (!nh_data)
+ rm_data = (struct zebra_rmap_obj *)object;
+ if (!rm_data)
return RMAP_NOMATCH;
- return (nh_data->instance == *instance) ? RMAP_MATCH : RMAP_NOMATCH;
+ return (rm_data->re->instance == *instance) ? RMAP_MATCH : RMAP_NOMATCH;
}
static void *route_match_source_instance_compile(const char *arg)
@@ -1513,10 +955,10 @@ static const struct route_map_rule_cmd route_match_source_instance_cmd = {
static enum route_map_cmd_result_t
route_set_src(void *rule, const struct prefix *prefix, void *object)
{
- struct nh_rmap_obj *nh_data;
+ struct zebra_rmap_obj *rm_data;
- nh_data = (struct nh_rmap_obj *)object;
- nh_data->nexthop->rmap_src = *(union g_addr *)rule;
+ rm_data = (struct zebra_rmap_obj *)object;
+ rm_data->nexthop->rmap_src = *(union g_addr *)rule;
return RMAP_OKAY;
}
@@ -1703,7 +1145,7 @@ static void zebra_nht_rm_update(const char *rmap)
afi_ipv6 = 1;
zebra_evaluate_rnh(
- zvrf, AFI_IP, 1, NULL,
+ zvrf, AFI_IP6, 1, NULL,
SAFI_UNICAST);
}
}
@@ -1741,7 +1183,7 @@ static void zebra_route_map_update_timer(struct event *thread)
*/
}
-static void zebra_route_map_set_delay_timer(uint32_t value)
+void zebra_route_map_set_delay_timer(uint32_t value)
{
zebra_rmap_update_timer = value;
if (!value && zebra_t_rmap_update) {
@@ -1761,26 +1203,22 @@ void zebra_routemap_finish(void)
route_map_finish();
}
-route_map_result_t
-zebra_route_map_check(afi_t family, int rib_type, uint8_t instance,
- const struct prefix *p, struct nexthop *nexthop,
- struct zebra_vrf *zvrf, route_tag_t tag)
+route_map_result_t zebra_route_map_check(afi_t family, struct route_entry *re,
+ const struct prefix *p,
+ struct nexthop *nexthop,
+ struct zebra_vrf *zvrf)
{
struct route_map *rmap = NULL;
char *rm_name;
route_map_result_t ret = RMAP_PERMITMATCH;
- struct nh_rmap_obj nh_obj;
+ struct zebra_rmap_obj rm_obj;
- nh_obj.nexthop = nexthop;
- nh_obj.vrf_id = nexthop->vrf_id;
- nh_obj.source_protocol = rib_type;
- nh_obj.instance = instance;
- nh_obj.metric = 0;
- nh_obj.tag = tag;
+ rm_obj.nexthop = nexthop;
+ rm_obj.re = re;
- if (rib_type >= 0 && rib_type < ZEBRA_ROUTE_MAX) {
- rm_name = PROTO_RM_NAME(zvrf, family, rib_type);
- rmap = PROTO_RM_MAP(zvrf, family, rib_type);
+ if (re->type >= 0 && re->type < ZEBRA_ROUTE_MAX) {
+ rm_name = PROTO_RM_NAME(zvrf, family, re->type);
+ rmap = PROTO_RM_MAP(zvrf, family, re->type);
if (rm_name && !rmap)
return RMAP_DENYMATCH;
@@ -1793,7 +1231,7 @@ zebra_route_map_check(afi_t family, int rib_type, uint8_t instance,
return RMAP_DENYMATCH;
}
if (rmap) {
- ret = route_map_apply(rmap, p, &nh_obj);
+ ret = route_map_apply(rmap, p, &rm_obj);
}
return (ret);
@@ -1816,28 +1254,23 @@ void zebra_del_import_table_route_map(afi_t afi, uint32_t table)
XFREE(MTYPE_ROUTE_MAP_NAME, zebra_import_table_routemap[afi][table]);
}
-route_map_result_t
-zebra_import_table_route_map_check(int family, int re_type, uint8_t instance,
- const struct prefix *p,
- struct nexthop *nexthop,
- vrf_id_t vrf_id, route_tag_t tag,
- const char *rmap_name)
+route_map_result_t zebra_import_table_route_map_check(int family,
+ struct route_entry *re,
+ const struct prefix *p,
+ struct nexthop *nexthop,
+ const char *rmap_name)
{
struct route_map *rmap = NULL;
route_map_result_t ret = RMAP_DENYMATCH;
- struct nh_rmap_obj nh_obj;
+ struct zebra_rmap_obj rm_obj;
- nh_obj.nexthop = nexthop;
- nh_obj.vrf_id = vrf_id;
- nh_obj.source_protocol = re_type;
- nh_obj.instance = instance;
- nh_obj.metric = 0;
- nh_obj.tag = tag;
+ rm_obj.nexthop = nexthop;
+ rm_obj.re = re;
- if (re_type >= 0 && re_type < ZEBRA_ROUTE_MAX)
+ if (re->type >= 0 && re->type < ZEBRA_ROUTE_MAX)
rmap = route_map_lookup_by_name(rmap_name);
if (rmap) {
- ret = route_map_apply(rmap, p, &nh_obj);
+ ret = route_map_apply(rmap, p, &rm_obj);
}
return (ret);
@@ -1851,21 +1284,17 @@ route_map_result_t zebra_nht_route_map_check(afi_t afi, int client_proto,
{
struct route_map *rmap = NULL;
route_map_result_t ret = RMAP_PERMITMATCH;
- struct nh_rmap_obj nh_obj;
+ struct zebra_rmap_obj rm_obj;
- nh_obj.nexthop = nexthop;
- nh_obj.vrf_id = nexthop->vrf_id;
- nh_obj.source_protocol = re->type;
- nh_obj.instance = re->instance;
- nh_obj.metric = re->metric;
- nh_obj.tag = re->tag;
+ rm_obj.nexthop = nexthop;
+ rm_obj.re = re;
if (client_proto >= 0 && client_proto < ZEBRA_ROUTE_MAX)
rmap = NHT_RM_MAP(zvrf, afi, client_proto);
if (!rmap && NHT_RM_MAP(zvrf, afi, ZEBRA_ROUTE_MAX))
rmap = NHT_RM_MAP(zvrf, afi, ZEBRA_ROUTE_MAX);
if (rmap)
- ret = route_map_apply(rmap, p, &nh_obj);
+ ret = route_map_apply(rmap, p, &rm_obj);
return ret;
}
@@ -1921,88 +1350,14 @@ void zebra_routemap_vrf_delete(struct zebra_vrf *zvrf)
}
}
-/* ip protocol configuration write function */
-void zebra_routemap_config_write_protocol(struct vty *vty,
- struct zebra_vrf *zvrf)
-{
- int i;
- char space[2];
-
- memset(space, 0, sizeof(space));
-
- if (zvrf_id(zvrf) != VRF_DEFAULT)
- snprintf(space, sizeof(space), "%s", " ");
-
- for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
- if (PROTO_RM_NAME(zvrf, AFI_IP, i))
- vty_out(vty, "%sip protocol %s route-map %s\n", space,
- zebra_route_string(i),
- PROTO_RM_NAME(zvrf, AFI_IP, i));
-
- if (PROTO_RM_NAME(zvrf, AFI_IP6, i))
- vty_out(vty, "%sipv6 protocol %s route-map %s\n", space,
- zebra_route_string(i),
- PROTO_RM_NAME(zvrf, AFI_IP6, i));
-
- if (NHT_RM_NAME(zvrf, AFI_IP, i))
- vty_out(vty, "%sip nht %s route-map %s\n", space,
- zebra_route_string(i),
- NHT_RM_NAME(zvrf, AFI_IP, i));
-
- if (NHT_RM_NAME(zvrf, AFI_IP6, i))
- vty_out(vty, "%sipv6 nht %s route-map %s\n", space,
- zebra_route_string(i),
- NHT_RM_NAME(zvrf, AFI_IP6, i));
- }
-
- if (PROTO_RM_NAME(zvrf, AFI_IP, ZEBRA_ROUTE_MAX))
- vty_out(vty, "%sip protocol %s route-map %s\n", space, "any",
- PROTO_RM_NAME(zvrf, AFI_IP, ZEBRA_ROUTE_MAX));
-
- if (PROTO_RM_NAME(zvrf, AFI_IP6, ZEBRA_ROUTE_MAX))
- vty_out(vty, "%sipv6 protocol %s route-map %s\n", space, "any",
- PROTO_RM_NAME(zvrf, AFI_IP6, ZEBRA_ROUTE_MAX));
-
- if (NHT_RM_NAME(zvrf, AFI_IP, ZEBRA_ROUTE_MAX))
- vty_out(vty, "%sip nht %s route-map %s\n", space, "any",
- NHT_RM_NAME(zvrf, AFI_IP, ZEBRA_ROUTE_MAX));
-
- if (NHT_RM_NAME(zvrf, AFI_IP6, ZEBRA_ROUTE_MAX))
- vty_out(vty, "%sipv6 nht %s route-map %s\n", space, "any",
- NHT_RM_NAME(zvrf, AFI_IP6, ZEBRA_ROUTE_MAX));
-
- if (zvrf_id(zvrf) == VRF_DEFAULT
- && zebra_rmap_update_timer != ZEBRA_RMAP_DEFAULT_UPDATE_TIMER)
- vty_out(vty, "zebra route-map delay-timer %d\n",
- zebra_rmap_update_timer);
-}
-
void zebra_route_map_init(void)
{
- install_element(CONFIG_NODE, &ip_protocol_cmd);
- install_element(CONFIG_NODE, &no_ip_protocol_cmd);
- install_element(VRF_NODE, &ip_protocol_cmd);
- install_element(VRF_NODE, &no_ip_protocol_cmd);
install_element(VIEW_NODE, &show_ip_protocol_cmd);
- install_element(CONFIG_NODE, &ipv6_protocol_cmd);
- install_element(CONFIG_NODE, &no_ipv6_protocol_cmd);
- install_element(VRF_NODE, &ipv6_protocol_cmd);
- install_element(VRF_NODE, &no_ipv6_protocol_cmd);
install_element(VIEW_NODE, &show_ipv6_protocol_cmd);
- install_element(CONFIG_NODE, &ip_protocol_nht_rmap_cmd);
- install_element(CONFIG_NODE, &no_ip_protocol_nht_rmap_cmd);
- install_element(VRF_NODE, &ip_protocol_nht_rmap_cmd);
- install_element(VRF_NODE, &no_ip_protocol_nht_rmap_cmd);
install_element(VIEW_NODE, &show_ip_protocol_nht_cmd);
- install_element(CONFIG_NODE, &ipv6_protocol_nht_rmap_cmd);
- install_element(CONFIG_NODE, &no_ipv6_protocol_nht_rmap_cmd);
- install_element(VRF_NODE, &ipv6_protocol_nht_rmap_cmd);
- install_element(VRF_NODE, &no_ipv6_protocol_nht_rmap_cmd);
install_element(VIEW_NODE, &show_ipv6_protocol_nht_cmd);
- install_element(CONFIG_NODE, &zebra_route_map_timer_cmd);
- install_element(CONFIG_NODE, &no_zebra_route_map_timer_cmd);
- route_map_init();
+ route_map_init_new(true);
route_map_add_hook(zebra_route_map_add);
route_map_delete_hook(zebra_route_map_delete);
@@ -2056,19 +1411,4 @@ void zebra_route_map_init(void)
/* */
route_map_install_set(&route_set_src_cmd);
- /* */
- install_element(RMAP_NODE, &match_ip_nexthop_prefix_len_cmd);
- install_element(RMAP_NODE, &no_match_ip_nexthop_prefix_len_cmd);
- install_element(RMAP_NODE, &match_ip_address_prefix_len_cmd);
- install_element(RMAP_NODE, &match_ipv6_address_prefix_len_cmd);
- install_element(RMAP_NODE, &no_match_ipv6_address_prefix_len_cmd);
- install_element(RMAP_NODE, &no_match_ip_address_prefix_len_cmd);
- install_element(RMAP_NODE, &match_source_protocol_cmd);
- install_element(RMAP_NODE, &no_match_source_protocol_cmd);
- install_element(RMAP_NODE, &match_source_instance_cmd);
- install_element(RMAP_NODE, &no_match_source_instance_cmd);
-
- /* */
- install_element(RMAP_NODE, &set_src_cmd);
- install_element(RMAP_NODE, &no_set_src_cmd);
}
diff --git a/zebra/zebra_routemap.h b/zebra/zebra_routemap.h
index f77735edc2..2039e80e3a 100644
--- a/zebra/zebra_routemap.h
+++ b/zebra/zebra_routemap.h
@@ -14,26 +14,34 @@ extern "C" {
#endif
extern void zebra_route_map_init(void);
-extern void zebra_routemap_config_write_protocol(struct vty *vty,
- struct zebra_vrf *vrf);
extern char *zebra_get_import_table_route_map(afi_t afi, uint32_t table);
extern void zebra_add_import_table_route_map(afi_t afi, const char *rmap_name,
uint32_t table);
extern void zebra_del_import_table_route_map(afi_t afi, uint32_t table);
-extern route_map_result_t
-zebra_import_table_route_map_check(int family, int rib_type, uint8_t instance,
- const struct prefix *p,
- struct nexthop *nexthop, vrf_id_t vrf_id,
- route_tag_t tag, const char *rmap_name);
-extern route_map_result_t
-zebra_route_map_check(afi_t family, int rib_type, uint8_t instance,
- const struct prefix *p, struct nexthop *nexthop,
- struct zebra_vrf *zvrf, route_tag_t tag);
-extern route_map_result_t
-zebra_nht_route_map_check(afi_t afi, int client_proto, const struct prefix *p,
- struct zebra_vrf *zvrf, struct route_entry *,
- struct nexthop *nexthop);
+extern route_map_result_t zebra_import_table_route_map_check(
+ int family, struct route_entry *re, const struct prefix *p,
+ struct nexthop *nexthop, const char *rmap_name);
+extern route_map_result_t zebra_route_map_check(afi_t family,
+ struct route_entry *re,
+ const struct prefix *p,
+ struct nexthop *nexthop,
+ struct zebra_vrf *zvrf);
+extern route_map_result_t zebra_nht_route_map_check(afi_t afi, int client_proto,
+ const struct prefix *p,
+ struct zebra_vrf *zvrf,
+ struct route_entry *re,
+ struct nexthop *nexthop);
+
+extern void zebra_route_map_set_delay_timer(uint32_t value);
+extern int ip_protocol_rm_add(struct zebra_vrf *zvrf, const char *rmap,
+ int rtype, afi_t afi, safi_t safi);
+extern int ip_protocol_rm_del(struct zebra_vrf *zvrf, const char *rmap,
+ int rtype, afi_t afi, safi_t safi);
+extern int ip_nht_rm_add(struct zebra_vrf *zvrf, const char *rmap, int rtype,
+ int afi);
+extern int ip_nht_rm_del(struct zebra_vrf *zvrf, const char *rmap, int rtype,
+ int afi);
extern void zebra_routemap_vrf_delete(struct zebra_vrf *zvrf);
diff --git a/zebra/zebra_routemap_nb_config.c b/zebra/zebra_routemap_nb_config.c
index 5bcfb720e1..ad012da4c2 100644
--- a/zebra/zebra_routemap_nb_config.c
+++ b/zebra/zebra_routemap_nb_config.c
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
#include <zebra.h>
#include "lib/command.h"
diff --git a/zebra/zebra_router.c b/zebra/zebra_router.c
index a477287913..3fd4e6eb1f 100644
--- a/zebra/zebra_router.c
+++ b/zebra/zebra_router.c
@@ -70,6 +70,26 @@ struct zebra_router_table *zebra_router_find_zrt(struct zebra_vrf *zvrf,
return zrt;
}
+struct zebra_router_table *zebra_router_find_next_zrt(struct zebra_vrf *zvrf,
+ uint32_t tableid,
+ afi_t afi, safi_t safi)
+{
+ struct zebra_router_table finder;
+ struct zebra_router_table *zrt;
+
+ memset(&finder, 0, sizeof(finder));
+ finder.afi = afi;
+ finder.safi = safi;
+ finder.tableid = tableid;
+ finder.ns_id = zvrf->zns->ns_id;
+ zrt = RB_NFIND(zebra_router_table_head, &zrouter.tables, &finder);
+ if (zrt->afi == afi && zrt->safi == safi && zrt->tableid == tableid &&
+ zrt->ns_id == finder.ns_id)
+ zrt = RB_NEXT(zebra_router_table_head, zrt);
+
+ return zrt;
+}
+
struct route_table *zebra_router_find_table(struct zebra_vrf *zvrf,
uint32_t tableid, afi_t afi,
safi_t safi)
@@ -241,11 +261,15 @@ void zebra_router_terminate(void)
zebra_pbr_ipset_entry_free);
hash_clean_and_free(&zrouter.ipset_hash, zebra_pbr_ipset_free);
hash_clean_and_free(&zrouter.iptable_hash, zebra_pbr_iptable_free);
+ hash_clean_and_free(&zrouter.filter_hash, (void (*)(void *)) zebra_tc_filter_free);
+ hash_clean_and_free(&zrouter.qdisc_hash, (void (*)(void *)) zebra_tc_qdisc_free);
+ hash_clean_and_free(&zrouter.class_hash, (void (*)(void *)) zebra_tc_class_free);
#ifdef HAVE_SCRIPTING
zebra_script_destroy();
#endif
+ zebra_vxlan_terminate();
/* OS-specific deinit */
kernel_router_terminate();
}
@@ -255,10 +279,13 @@ bool zebra_router_notify_on_ack(void)
return !zrouter.asic_offloaded || zrouter.notify_on_ack;
}
-void zebra_router_init(bool asic_offload, bool notify_on_ack)
+void zebra_router_init(bool asic_offload, bool notify_on_ack,
+ bool v6_with_v4_nexthop)
{
zrouter.sequence_num = 0;
+ zrouter.protodown_r_bit = FRR_PROTODOWN_REASON_DEFAULT_BIT;
+
zrouter.allow_delete = false;
zrouter.packets_to_process = ZEBRA_ZAPI_PACKETS_TO_PROCESS;
@@ -292,10 +319,6 @@ void zebra_router_init(bool asic_offload, bool notify_on_ack)
hash_create_size(8, zebra_nhg_id_key, zebra_nhg_hash_id_equal,
"Zebra Router Nexthop Groups ID index");
- zrouter.rules_hash =
- hash_create_size(8, zebra_pbr_rules_hash_key,
- zebra_pbr_rules_hash_equal, "Rules Hash");
-
zrouter.qdisc_hash =
hash_create_size(8, zebra_tc_qdisc_hash_key,
zebra_tc_qdisc_hash_equal, "TC (qdisc) Hash");
@@ -308,7 +331,7 @@ void zebra_router_init(bool asic_offload, bool notify_on_ack)
zrouter.asic_offloaded = asic_offload;
zrouter.notify_on_ack = notify_on_ack;
-
+ zrouter.v6_with_v4_nexthop = v6_with_v4_nexthop;
/*
* If you start using asic_notification_nexthop_control
* come talk to the FRR community about what you are doing
@@ -320,6 +343,8 @@ void zebra_router_init(bool asic_offload, bool notify_on_ack)
#endif
zrouter.asic_notification_nexthop_control = false;
+ zrouter.nexthop_weight_scale_value = 255;
+
#ifdef HAVE_SCRIPTING
zebra_script_init();
#endif
diff --git a/zebra/zebra_router.h b/zebra/zebra_router.h
index d81c7df589..3041707439 100644
--- a/zebra/zebra_router.h
+++ b/zebra/zebra_router.h
@@ -207,6 +207,9 @@ struct zebra_router {
*/
bool asic_offloaded;
bool notify_on_ack;
+ bool v6_with_v4_nexthop;
+
+ bool v6_rr_semantics;
/*
* If the asic is notifying us about successful nexthop
@@ -228,6 +231,10 @@ struct zebra_router {
/* Should we allow non FRR processes to delete our routes */
bool allow_delete;
+
+ uint8_t protodown_r_bit;
+
+ uint64_t nexthop_weight_scale_value;
};
#define GRACEFUL_RESTART_TIME 60
@@ -235,13 +242,17 @@ struct zebra_router {
extern struct zebra_router zrouter;
extern uint32_t rcvbufsize;
-extern void zebra_router_init(bool asic_offload, bool notify_on_ack);
+extern void zebra_router_init(bool asic_offload, bool notify_on_ack,
+ bool v6_with_v4_nexthop);
extern void zebra_router_cleanup(void);
extern void zebra_router_terminate(void);
extern struct zebra_router_table *zebra_router_find_zrt(struct zebra_vrf *zvrf,
uint32_t tableid,
afi_t afi, safi_t safi);
+extern struct zebra_router_table *
+zebra_router_find_next_zrt(struct zebra_vrf *zvrf, uint32_t tableid, afi_t afi,
+ safi_t safi);
extern struct route_table *zebra_router_find_table(struct zebra_vrf *zvrf,
uint32_t tableid, afi_t afi,
safi_t safi);
@@ -286,6 +297,32 @@ static inline bool zebra_router_in_shutdown(void)
return atomic_load_explicit(&zrouter.in_shutdown, memory_order_relaxed);
}
+#define FRR_PROTODOWN_REASON_DEFAULT_BIT 7
+/* Protodown bit setter/getter
+ *
+ * Allow users to change the bit if it conflicts with another
+ * on their system.
+ */
+static inline void if_netlink_set_frr_protodown_r_bit(uint8_t bit)
+{
+ zrouter.protodown_r_bit = bit;
+}
+
+static inline void if_netlink_unset_frr_protodown_r_bit(void)
+{
+ zrouter.protodown_r_bit = FRR_PROTODOWN_REASON_DEFAULT_BIT;
+}
+
+static inline bool if_netlink_frr_protodown_r_bit_is_set(void)
+{
+ return (zrouter.protodown_r_bit != FRR_PROTODOWN_REASON_DEFAULT_BIT);
+}
+
+static inline uint8_t if_netlink_get_frr_protodown_r_bit(void)
+{
+ return zrouter.protodown_r_bit;
+}
+
/* zebra_northbound.c */
extern const struct frr_yang_module_info frr_zebra_info;
diff --git a/zebra/zebra_script.c b/zebra/zebra_script.c
index 3f107cb48d..6c34d12c64 100644
--- a/zebra/zebra_script.c
+++ b/zebra/zebra_script.c
@@ -396,6 +396,7 @@ void lua_pushzebra_dplane_ctx(lua_State *L, const struct zebra_dplane_ctx *ctx)
lua_setfield(L, -2, "mtu");
}
lua_setfield(L, -2, "gre");
+ break;
case DPLANE_OP_ADDR_INSTALL:
case DPLANE_OP_ADDR_UNINSTALL:
@@ -414,7 +415,9 @@ void lua_pushzebra_dplane_ctx(lua_State *L, const struct zebra_dplane_ctx *ctx)
case DPLANE_OP_TC_FILTER_UPDATE:
/* Not currently handled */
case DPLANE_OP_INTF_NETCONFIG: /*NYI*/
+ case DPLANE_OP_SRV6_ENCAP_SRCADDR_SET:
case DPLANE_OP_NONE:
+ case DPLANE_OP_STARTUP_STAGE:
break;
} /* Dispatch by op code */
}
diff --git a/zebra/zebra_snmp.c b/zebra/zebra_snmp.c
index e06733cb8c..1c6d58159e 100644
--- a/zebra/zebra_snmp.c
+++ b/zebra/zebra_snmp.c
@@ -223,6 +223,8 @@ static int proto_trans(int type)
return 1; /* other */
case ZEBRA_ROUTE_CONNECT:
return 2; /* local interface */
+ case ZEBRA_ROUTE_LOCAL:
+ return 2;
case ZEBRA_ROUTE_STATIC:
return 3; /* static route */
case ZEBRA_ROUTE_RIP:
@@ -353,7 +355,7 @@ static void get_fwtable_route_node(struct variable *v, oid objid[],
if (policy) /* Not supported (yet?) */
return;
for (*np = route_top(table); *np; *np = route_next(*np)) {
- if (!in_addr_cmp(&(*np)->p.u.prefix,
+ if (!in_addr_cmp((uint8_t *)&(*np)->p.u.prefix4,
(uint8_t *)&dest)) {
RNODE_FOREACH_RE (*np, *re) {
if (!in_addr_cmp((uint8_t *)&(*re)->nhe
@@ -374,13 +376,14 @@ static void get_fwtable_route_node(struct variable *v, oid objid[],
for (np2 = route_top(table); np2; np2 = route_next(np2)) {
/* Check destination first */
- if (in_addr_cmp(&np2->p.u.prefix, (uint8_t *)&dest) > 0)
+ if (in_addr_cmp((uint8_t *)&np2->p.u.prefix4,
+ (uint8_t *)&dest) > 0)
RNODE_FOREACH_RE (np2, re2) {
check_replace(np2, re2, np, re);
}
- if (in_addr_cmp(&np2->p.u.prefix, (uint8_t *)&dest)
- == 0) { /* have to look at each re individually */
+ if (in_addr_cmp((uint8_t *)&np2->p.u.prefix4, (uint8_t *)&dest) ==
+ 0) { /* have to look at each re individually */
RNODE_FOREACH_RE (np2, re2) {
int proto2, policy2;
diff --git a/zebra/zebra_srv6.c b/zebra/zebra_srv6.c
index 94b93e5e8d..bb872ef91c 100644
--- a/zebra/zebra_srv6.c
+++ b/zebra/zebra_srv6.c
@@ -17,6 +17,7 @@
#include "zebra/zebra_router.h"
#include "zebra/zebra_srv6.h"
#include "zebra/zebra_errors.h"
+#include "zebra/ge_netlink.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -216,9 +217,10 @@ void zebra_notify_srv6_locator_delete(struct srv6_locator *locator)
}
}
+struct zebra_srv6 srv6;
+
struct zebra_srv6 *zebra_srv6_get_default(void)
{
- static struct zebra_srv6 srv6;
static bool first_execution = true;
if (first_execution) {
@@ -408,6 +410,40 @@ int release_daemon_srv6_locator_chunks(struct zserv *client)
return count;
}
+void zebra_srv6_encap_src_addr_set(struct in6_addr *encap_src_addr)
+{
+ struct zebra_srv6 *srv6 = zebra_srv6_get_default();
+
+ if (!encap_src_addr)
+ return;
+
+ memcpy(&srv6->encap_src_addr, encap_src_addr, sizeof(struct in6_addr));
+}
+
+void zebra_srv6_encap_src_addr_unset(void)
+{
+ struct zebra_srv6 *srv6 = zebra_srv6_get_default();
+
+ memset(&srv6->encap_src_addr, 0, sizeof(struct in6_addr));
+}
+
+void zebra_srv6_terminate(void)
+{
+ struct srv6_locator *locator;
+
+ if (!srv6.locators)
+ return;
+
+ while (listcount(srv6.locators)) {
+ locator = listnode_head(srv6.locators);
+
+ listnode_delete(srv6.locators, locator);
+ srv6_locator_free(locator);
+ }
+
+ list_delete(&srv6.locators);
+}
+
void zebra_srv6_init(void)
{
hook_register(zserv_client_close, zebra_srv6_cleanup);
diff --git a/zebra/zebra_srv6.h b/zebra/zebra_srv6.h
index 51db83d6fb..21936c3323 100644
--- a/zebra/zebra_srv6.h
+++ b/zebra/zebra_srv6.h
@@ -19,6 +19,9 @@
/* SRv6 instance structure. */
struct zebra_srv6 {
struct list *locators;
+
+ /* Source address for SRv6 encapsulation */
+ struct in6_addr encap_src_addr;
};
/* declare hooks for the basic API, so that it can be specialized or served
@@ -52,6 +55,7 @@ void zebra_notify_srv6_locator_add(struct srv6_locator *locator);
void zebra_notify_srv6_locator_delete(struct srv6_locator *locator);
extern void zebra_srv6_init(void);
+extern void zebra_srv6_terminate(void);
extern struct zebra_srv6 *zebra_srv6_get_default(void);
extern bool zebra_srv6_is_enable(void);
@@ -67,4 +71,7 @@ extern void srv6_manager_release_locator_chunk_call(struct zserv *client,
extern int srv6_manager_client_disconnect_cb(struct zserv *client);
extern int release_daemon_srv6_locator_chunks(struct zserv *client);
+extern void zebra_srv6_encap_src_addr_set(struct in6_addr *src_addr);
+extern void zebra_srv6_encap_src_addr_unset(void);
+
#endif /* _ZEBRA_SRV6_H */
diff --git a/zebra/zebra_srv6_vty.c b/zebra/zebra_srv6_vty.c
index 3775d3dcdf..c5b8505992 100644
--- a/zebra/zebra_srv6_vty.c
+++ b/zebra/zebra_srv6_vty.c
@@ -61,6 +61,52 @@ static struct cmd_node srv6_loc_node = {
.prompt = "%s(config-srv6-locator)# "
};
+static struct cmd_node srv6_encap_node = {
+ .name = "srv6-encap",
+ .node = SRV6_ENCAP_NODE,
+ .parent_node = SRV6_NODE,
+ .prompt = "%s(config-srv6-encap)# "
+};
+
+DEFPY (show_srv6_manager,
+ show_srv6_manager_cmd,
+ "show segment-routing srv6 manager [json]",
+ SHOW_STR
+ "Segment Routing\n"
+ "Segment Routing SRv6\n"
+ "Verify SRv6 Manager\n"
+ JSON_STR)
+{
+ const bool uj = use_json(argc, argv);
+ struct zebra_srv6 *srv6 = zebra_srv6_get_default();
+ json_object *json = NULL;
+ json_object *json_parameters = NULL;
+ json_object *json_encapsulation = NULL;
+ json_object *json_source_address = NULL;
+
+ if (uj) {
+ json = json_object_new_object();
+ json_parameters = json_object_new_object();
+ json_object_object_add(json, "parameters", json_parameters);
+ json_encapsulation = json_object_new_object();
+ json_object_object_add(json_parameters, "encapsulation",
+ json_encapsulation);
+ json_source_address = json_object_new_object();
+ json_object_object_add(json_encapsulation, "sourceAddress",
+ json_source_address);
+ json_object_string_addf(json_source_address, "configured",
+ "%pI6", &srv6->encap_src_addr);
+ vty_json(vty, json);
+ } else {
+ vty_out(vty, "Parameters:\n");
+ vty_out(vty, " Encapsulation:\n");
+ vty_out(vty, " Source Address:\n");
+ vty_out(vty, " Configured: %pI6\n", &srv6->encap_src_addr);
+ }
+
+ return CMD_SUCCESS;
+}
+
DEFUN (show_srv6_locator,
show_srv6_locator_cmd,
"show segment-routing srv6 locator [json]",
@@ -391,6 +437,38 @@ DEFPY (locator_behavior,
return CMD_SUCCESS;
}
+DEFUN_NOSH (srv6_encap,
+ srv6_encap_cmd,
+ "encapsulation",
+ "Segment Routing SRv6 encapsulation\n")
+{
+ vty->node = SRV6_ENCAP_NODE;
+ return CMD_SUCCESS;
+}
+
+DEFPY (srv6_src_addr,
+ srv6_src_addr_cmd,
+ "source-address X:X::X:X$encap_src_addr",
+ "Segment Routing SRv6 source address\n"
+ "Specify source address for SRv6 encapsulation\n")
+{
+ zebra_srv6_encap_src_addr_set(&encap_src_addr);
+ dplane_srv6_encap_srcaddr_set(&encap_src_addr, NS_DEFAULT);
+ return CMD_SUCCESS;
+}
+
+DEFPY (no_srv6_src_addr,
+ no_srv6_src_addr_cmd,
+ "no source-address [X:X::X:X$encap_src_addr]",
+ NO_STR
+ "Segment Routing SRv6 source address\n"
+ "Specify source address for SRv6 encapsulation\n")
+{
+ zebra_srv6_encap_src_addr_unset();
+ dplane_srv6_encap_srcaddr_set(&in6addr_any, NS_DEFAULT);
+ return CMD_SUCCESS;
+}
+
static int zebra_sr_config(struct vty *vty)
{
struct zebra_srv6 *srv6 = zebra_srv6_get_default();
@@ -402,6 +480,11 @@ static int zebra_sr_config(struct vty *vty)
if (zebra_srv6_is_enable()) {
vty_out(vty, "segment-routing\n");
vty_out(vty, " srv6\n");
+ if (!IPV6_ADDR_SAME(&srv6->encap_src_addr, &in6addr_any)) {
+ vty_out(vty, " encapsulation\n");
+ vty_out(vty, " source-address %pI6\n",
+ &srv6->encap_src_addr);
+ }
vty_out(vty, " locators\n");
for (ALL_LIST_ELEMENTS_RO(srv6->locators, node, locator)) {
inet_ntop(AF_INET6, &locator->prefix.prefix,
@@ -444,24 +527,30 @@ void zebra_srv6_vty_init(void)
install_node(&srv6_node);
install_node(&srv6_locs_node);
install_node(&srv6_loc_node);
+ install_node(&srv6_encap_node);
install_default(SEGMENT_ROUTING_NODE);
install_default(SRV6_NODE);
install_default(SRV6_LOCS_NODE);
install_default(SRV6_LOC_NODE);
+ install_default(SRV6_ENCAP_NODE);
/* Command for change node */
install_element(CONFIG_NODE, &segment_routing_cmd);
install_element(SEGMENT_ROUTING_NODE, &srv6_cmd);
install_element(SEGMENT_ROUTING_NODE, &no_srv6_cmd);
install_element(SRV6_NODE, &srv6_locators_cmd);
+ install_element(SRV6_NODE, &srv6_encap_cmd);
install_element(SRV6_LOCS_NODE, &srv6_locator_cmd);
install_element(SRV6_LOCS_NODE, &no_srv6_locator_cmd);
/* Command for configuration */
install_element(SRV6_LOC_NODE, &locator_prefix_cmd);
install_element(SRV6_LOC_NODE, &locator_behavior_cmd);
+ install_element(SRV6_ENCAP_NODE, &srv6_src_addr_cmd);
+ install_element(SRV6_ENCAP_NODE, &no_srv6_src_addr_cmd);
/* Command for operation */
install_element(VIEW_NODE, &show_srv6_locator_cmd);
install_element(VIEW_NODE, &show_srv6_locator_detail_cmd);
+ install_element(VIEW_NODE, &show_srv6_manager_cmd);
}
diff --git a/zebra/zebra_tc.c b/zebra/zebra_tc.c
index 3d7e03b63e..1b5a57ae53 100644
--- a/zebra/zebra_tc.c
+++ b/zebra/zebra_tc.c
@@ -132,13 +132,18 @@ static void *tc_qdisc_alloc_intern(void *arg)
return new;
}
+void zebra_tc_qdisc_free(struct zebra_tc_qdisc *qdisc)
+{
+ XFREE(MTYPE_TC_QDISC, qdisc);
+}
+
static struct zebra_tc_qdisc *tc_qdisc_free(struct zebra_tc_qdisc *hash_data,
bool free_data)
{
hash_release(zrouter.qdisc_hash, hash_data);
if (free_data) {
- XFREE(MTYPE_TC_QDISC, hash_data);
+ zebra_tc_qdisc_free(hash_data);
return NULL;
}
@@ -178,7 +183,7 @@ void zebra_tc_qdisc_install(struct zebra_tc_qdisc *qdisc)
new = hash_get(zrouter.qdisc_hash, qdisc,
tc_qdisc_alloc_intern);
(void)dplane_tc_qdisc_install(new);
- XFREE(MTYPE_TC_QDISC, old);
+ zebra_tc_qdisc_free(old);
}
} else {
new = hash_get(zrouter.qdisc_hash, qdisc,
@@ -243,13 +248,18 @@ static void *tc_class_alloc_intern(void *arg)
return new;
}
+void zebra_tc_class_free(struct zebra_tc_class *class)
+{
+ XFREE(MTYPE_TC_CLASS, class);
+}
+
static struct zebra_tc_class *tc_class_free(struct zebra_tc_class *hash_data,
bool free_data)
{
hash_release(zrouter.class_hash, hash_data);
if (free_data) {
- XFREE(MTYPE_TC_CLASS, hash_data);
+ zebra_tc_class_free(hash_data);
return NULL;
}
@@ -353,13 +363,18 @@ bool zebra_tc_filter_hash_equal(const void *arg1, const void *arg2)
return true;
}
+void zebra_tc_filter_free(struct zebra_tc_filter *filter)
+{
+ XFREE(MTYPE_TC_FILTER, filter);
+}
+
static struct zebra_tc_filter *tc_filter_free(struct zebra_tc_filter *hash_data,
bool free_data)
{
hash_release(zrouter.filter_hash, hash_data);
if (free_data) {
- XFREE(MTYPE_TC_FILTER, hash_data);
+ zebra_tc_filter_free(hash_data);
return NULL;
}
diff --git a/zebra/zebra_tc.h b/zebra/zebra_tc.h
index 335430c93d..814b453ec5 100644
--- a/zebra/zebra_tc.h
+++ b/zebra/zebra_tc.h
@@ -42,16 +42,19 @@ uint32_t zebra_tc_qdisc_hash_key(const void *arg);
bool zebra_tc_qdisc_hash_equal(const void *arg1, const void *arg2);
void zebra_tc_qdisc_install(struct zebra_tc_qdisc *qdisc);
void zebra_tc_qdisc_uninstall(struct zebra_tc_qdisc *qdisc);
+void zebra_tc_qdisc_free(struct zebra_tc_qdisc *qdisc);
uint32_t zebra_tc_class_hash_key(const void *arg);
bool zebra_tc_class_hash_equal(const void *arg1, const void *arg2);
void zebra_tc_class_add(struct zebra_tc_class *class);
void zebra_tc_class_delete(struct zebra_tc_class *class);
+void zebra_tc_class_free(struct zebra_tc_class *class);
const char *tc_filter_kind2str(uint32_t type);
enum tc_qdisc_kind tc_filter_str2kind(const char *type);
void zebra_tc_filter_add(struct zebra_tc_filter *filter);
void zebra_tc_filter_delete(struct zebra_tc_filter *filter);
+void zebra_tc_filter_free(struct zebra_tc_filter *filter);
void zebra_tc_filters_free(void *arg);
uint32_t zebra_tc_filter_hash_key(const void *arg);
diff --git a/zebra/zebra_trace.c b/zebra/zebra_trace.c
index fef5ad20ac..7b0fb3279b 100644
--- a/zebra/zebra_trace.c
+++ b/zebra/zebra_trace.c
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
#define TRACEPOINT_CREATE_PROBES
#define TRACEPOINT_DEFINE
diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c
index 3365cdcdba..e464e47b1f 100644
--- a/zebra/zebra_vrf.c
+++ b/zebra/zebra_vrf.c
@@ -195,7 +195,7 @@ static int zebra_vrf_disable(struct vrf *vrf)
/* Cleanup Vxlan, MPLS and PW tables. */
zebra_vxlan_cleanup_tables(zvrf);
zebra_mpls_cleanup_tables(zvrf);
- zebra_pw_exit(zvrf);
+ zebra_pw_exit_vrf(zvrf);
/* Remove link-local IPv4 addresses created for BGP unnumbered peering.
*/
@@ -265,6 +265,12 @@ static int zebra_vrf_delete(struct vrf *vrf)
otable_fini(&zvrf->other_tables);
XFREE(MTYPE_ZEBRA_VRF, zvrf);
+
+ if (vrf->ns_ctxt) {
+ ns_delete(vrf->ns_ctxt);
+ vrf->ns_ctxt = NULL;
+ }
+
vrf->info = NULL;
return 0;
@@ -370,12 +376,45 @@ struct zebra_vrf *zebra_vrf_alloc(struct vrf *vrf)
zebra_vxlan_init_tables(zvrf);
zebra_mpls_init_tables(zvrf);
- zebra_pw_init(zvrf);
- zvrf->table_id = RT_TABLE_MAIN;
+ zebra_pw_init_vrf(zvrf);
+ zvrf->table_id = rt_table_main_id;
/* by default table ID is default one */
+
+ if (DFLT_ZEBRA_IP_NHT_RESOLVE_VIA_DEFAULT) {
+ zvrf->zebra_rnh_ip_default_route = true;
+ zvrf->zebra_rnh_ipv6_default_route = true;
+ }
+
return zvrf;
}
+/*
+ * Pending: create an efficient table_id (in a tree/hash) based lookup)
+ */
+vrf_id_t zebra_vrf_lookup_by_table(uint32_t table_id, ns_id_t ns_id)
+{
+ struct vrf *vrf;
+ struct zebra_vrf *zvrf;
+
+ RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
+ zvrf = vrf->info;
+ if (zvrf == NULL)
+ continue;
+ /* case vrf with netns : match the netnsid */
+ if (vrf_is_backend_netns()) {
+ if (ns_id == zvrf_id(zvrf))
+ return zvrf_id(zvrf);
+ } else {
+ /* VRF is VRF_BACKEND_VRF_LITE */
+ if (zvrf->table_id != table_id)
+ continue;
+ return zvrf_id(zvrf);
+ }
+ }
+
+ return VRF_DEFAULT;
+}
+
/* Lookup VRF by identifier. */
struct zebra_vrf *zebra_vrf_lookup_by_id(vrf_id_t vrf_id)
{
@@ -411,124 +450,6 @@ struct route_table *zebra_vrf_table(afi_t afi, safi_t safi, vrf_id_t vrf_id)
return zvrf->table[afi][safi];
}
-static int vrf_config_write(struct vty *vty)
-{
- struct vrf *vrf;
- struct zebra_vrf *zvrf;
-
- RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
- zvrf = vrf->info;
-
- if (!zvrf)
- continue;
-
- if (zvrf_id(zvrf) == VRF_DEFAULT) {
- if (zvrf->l3vni)
- vty_out(vty, "vni %u%s\n", zvrf->l3vni,
- is_l3vni_for_prefix_routes_only(
- zvrf->l3vni)
- ? " prefix-routes-only"
- : "");
- if (zvrf->zebra_rnh_ip_default_route)
- vty_out(vty, "ip nht resolve-via-default\n");
-
- if (zvrf->zebra_rnh_ipv6_default_route)
- vty_out(vty, "ipv6 nht resolve-via-default\n");
-
- if (zvrf->tbl_mgr
- && (zvrf->tbl_mgr->start || zvrf->tbl_mgr->end))
- vty_out(vty, "ip table range %u %u\n",
- zvrf->tbl_mgr->start,
- zvrf->tbl_mgr->end);
- } else {
- vty_frame(vty, "vrf %s\n", zvrf_name(zvrf));
- if (zvrf->l3vni)
- vty_out(vty, " vni %u%s\n", zvrf->l3vni,
- is_l3vni_for_prefix_routes_only(
- zvrf->l3vni)
- ? " prefix-routes-only"
- : "");
- zebra_ns_config_write(vty, (struct ns *)vrf->ns_ctxt);
- if (zvrf->zebra_rnh_ip_default_route)
- vty_out(vty, " ip nht resolve-via-default\n");
-
- if (zvrf->zebra_rnh_ipv6_default_route)
- vty_out(vty, " ipv6 nht resolve-via-default\n");
-
- if (zvrf->tbl_mgr && vrf_is_backend_netns()
- && (zvrf->tbl_mgr->start || zvrf->tbl_mgr->end))
- vty_out(vty, " ip table range %u %u\n",
- zvrf->tbl_mgr->start,
- zvrf->tbl_mgr->end);
- }
-
-
- zebra_routemap_config_write_protocol(vty, zvrf);
- router_id_write(vty, zvrf);
-
- if (zvrf_id(zvrf) != VRF_DEFAULT)
- vty_endframe(vty, "exit-vrf\n!\n");
- else
- vty_out(vty, "!\n");
- }
- return 0;
-}
-
-DEFPY (vrf_netns,
- vrf_netns_cmd,
- "netns NAME$netns_name",
- "Attach VRF to a Namespace\n"
- "The file name in " NS_RUN_DIR ", or a full pathname\n")
-{
- char *pathname = ns_netns_pathname(vty, netns_name);
- int ret;
-
- VTY_DECLVAR_CONTEXT(vrf, vrf);
-
- if (!pathname)
- return CMD_WARNING_CONFIG_FAILED;
-
- frr_with_privs(&zserv_privs) {
- ret = zebra_vrf_netns_handler_create(
- vty, vrf, pathname, NS_UNKNOWN, NS_UNKNOWN, NS_UNKNOWN);
- }
-
- return ret;
-}
-
-DEFUN (no_vrf_netns,
- no_vrf_netns_cmd,
- "no netns [NAME]",
- NO_STR
- "Detach VRF from a Namespace\n"
- "The file name in " NS_RUN_DIR ", or a full pathname\n")
-{
- struct ns *ns = NULL;
-
- VTY_DECLVAR_CONTEXT(vrf, vrf);
-
- if (!vrf_is_backend_netns()) {
- vty_out(vty, "VRF backend is not Netns. Aborting\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
- if (!vrf->ns_ctxt) {
- vty_out(vty, "VRF %s(%u) is not configured with NetNS\n",
- vrf->name, vrf->vrf_id);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- ns = (struct ns *)vrf->ns_ctxt;
-
- ns->vrf_ctxt = NULL;
- vrf_disable(vrf);
- /* vrf ID from VRF is necessary for Zebra
- * so that propagate to other clients is done
- */
- ns_delete(ns);
- vrf->ns_ctxt = NULL;
- return CMD_SUCCESS;
-}
-
/* if ns_id is different and not VRF_UNKNOWN,
* then update vrf identifier, and enable VRF
*/
@@ -627,12 +548,4 @@ void zebra_vrf_init(void)
zebra_vrf_delete);
hook_register(zserv_client_close, release_daemon_table_chunks);
-
- vrf_cmd_init(vrf_config_write);
-
- if (vrf_is_backend_netns() && ns_have_netns()) {
- /* Install NS commands. */
- install_element(VRF_NODE, &vrf_netns_cmd);
- install_element(VRF_NODE, &no_vrf_netns_cmd);
- }
}
diff --git a/zebra/zebra_vrf.h b/zebra/zebra_vrf.h
index b23b728261..5cbfab1ddc 100644
--- a/zebra/zebra_vrf.h
+++ b/zebra/zebra_vrf.h
@@ -13,11 +13,17 @@
#include <zebra/zebra_pw.h>
#include <zebra/rtadv.h>
#include <lib/vxlan.h>
+#include "defaults.h"
#ifdef __cplusplus
extern "C" {
#endif
+FRR_CFG_DEFAULT_BOOL(ZEBRA_IP_NHT_RESOLVE_VIA_DEFAULT,
+ { .val_bool = true, .match_profile = "traditional", },
+ { .val_bool = false },
+);
+
/* MPLS (Segment Routing) global block */
struct mpls_srgb {
uint32_t start_label;
@@ -237,6 +243,7 @@ extern struct route_table *zebra_vrf_get_table_with_table_id(afi_t afi,
extern void zebra_vrf_update_all(struct zserv *client);
extern struct zebra_vrf *zebra_vrf_lookup_by_id(vrf_id_t vrf_id);
extern struct zebra_vrf *zebra_vrf_lookup_by_name(const char *);
+extern vrf_id_t zebra_vrf_lookup_by_table(uint32_t table_id, ns_id_t ns_id);
extern struct zebra_vrf *zebra_vrf_alloc(struct vrf *vrf);
extern struct route_table *zebra_vrf_table(afi_t, safi_t, vrf_id_t);
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index d100dc0e69..0b5362094e 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -20,6 +20,7 @@
#include "vxlan.h"
#include "termtable.h"
#include "affinitymap.h"
+#include "frrdistance.h"
#include "zebra/zebra_router.h"
#include "zebra/zserv.h"
@@ -50,6 +51,7 @@
#include "zebra/zebra_script.h"
#include "zebra/rtadv.h"
#include "zebra/zebra_neigh.h"
+#include "zebra/zebra_ptm.h"
/* context to manage dumps in multiple tables or vrfs */
struct route_show_ctx {
@@ -58,18 +60,19 @@ struct route_show_ctx {
};
static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi,
- safi_t safi, bool use_fib, bool use_json,
- route_tag_t tag,
+ safi_t safi, bool use_fib, json_object *vrf_json,
+ bool use_json, route_tag_t tag,
const struct prefix *longer_prefix_p,
bool supernets_only, int type,
unsigned short ospf_instance_id, uint32_t tableid,
bool show_ng, struct route_show_ctx *ctx);
static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
int mcast, bool use_fib, bool show_ng);
-static void vty_show_ip_route_summary(struct vty *vty,
- struct route_table *table, bool use_json);
+static void vty_show_ip_route_summary(struct vty *vty, struct route_table *table,
+ json_object *vrf_json, bool use_json);
static void vty_show_ip_route_summary_prefix(struct vty *vty,
struct route_table *table,
+ json_object *vrf_json,
bool use_json);
/* Helper api to format a nexthop in the 'detailed' output path. */
static void show_nexthop_detail_helper(struct vty *vty,
@@ -146,8 +149,8 @@ DEFPY (show_ip_rpf,
};
return do_show_ip_route(vty, VRF_DEFAULT_NAME, ip ? AFI_IP : AFI_IP6,
- SAFI_MULTICAST, false, uj, 0, NULL, false, 0, 0,
- 0, false, &ctx);
+ SAFI_MULTICAST, false, NULL, uj, 0, NULL, false,
+ 0, 0, 0, false, &ctx);
}
DEFPY (show_ip_rpf_addr,
@@ -764,9 +767,10 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
}
/* Distance and metric display. */
- if (((re->type == ZEBRA_ROUTE_CONNECT) &&
+ if (((re->type == ZEBRA_ROUTE_CONNECT ||
+ re->type == ZEBRA_ROUTE_LOCAL) &&
(re->distance || re->metric)) ||
- (re->type != ZEBRA_ROUTE_CONNECT))
+ (re->type != ZEBRA_ROUTE_CONNECT && re->type != ZEBRA_ROUTE_LOCAL))
len += vty_out(vty, " [%u/%u]", re->distance,
re->metric);
@@ -853,14 +857,13 @@ static void vty_show_ip_route_detail_json(struct vty *vty,
vty_json(vty, json);
}
-static void do_show_route_helper(struct vty *vty, struct zebra_vrf *zvrf,
- struct route_table *table, afi_t afi,
- bool use_fib, route_tag_t tag,
- const struct prefix *longer_prefix_p,
- bool supernets_only, int type,
- unsigned short ospf_instance_id, bool use_json,
- uint32_t tableid, bool show_ng,
- struct route_show_ctx *ctx)
+static void
+do_show_route_helper(struct vty *vty, struct zebra_vrf *zvrf,
+ struct route_table *table, afi_t afi, bool use_fib,
+ json_object *vrf_json, route_tag_t tag,
+ const struct prefix *longer_prefix_p, bool supernets_only,
+ int type, unsigned short ospf_instance_id, bool use_json,
+ uint32_t tableid, bool show_ng, struct route_show_ctx *ctx)
{
struct route_node *rn;
struct route_entry *re;
@@ -882,7 +885,7 @@ static void do_show_route_helper(struct vty *vty, struct zebra_vrf *zvrf,
* => display the VRF and table if specific
*/
- if (use_json)
+ if (use_json && !vrf_json)
json = json_object_new_object();
/* Show all routes. */
@@ -957,18 +960,28 @@ static void do_show_route_helper(struct vty *vty, struct zebra_vrf *zvrf,
if (json_prefix) {
prefix2str(&rn->p, buf, sizeof(buf));
- json_object_object_add(json, buf, json_prefix);
+ if (!vrf_json)
+ json_object_object_add(json, buf, json_prefix);
+ else
+ json_object_object_add(vrf_json, buf,
+ json_prefix);
json_prefix = NULL;
}
}
- if (use_json)
- vty_json(vty, json);
+ /*
+ * This is an extremely expensive operation at scale
+ * and non-pretty reduces memory footprint significantly.
+ */
+ if (use_json && !vrf_json) {
+ vty_json_no_pretty(vty, json);
+ json = NULL;
+ }
}
static void do_show_ip_route_all(struct vty *vty, struct zebra_vrf *zvrf,
- afi_t afi, bool use_fib, bool use_json,
- route_tag_t tag,
+ afi_t afi, bool use_fib, json_object *vrf_json,
+ bool use_json, route_tag_t tag,
const struct prefix *longer_prefix_p,
bool supernets_only, int type,
unsigned short ospf_instance_id, bool show_ng,
@@ -988,15 +1001,15 @@ static void do_show_ip_route_all(struct vty *vty, struct zebra_vrf *zvrf,
continue;
do_show_ip_route(vty, zvrf_name(zvrf), afi, SAFI_UNICAST,
- use_fib, use_json, tag, longer_prefix_p,
- supernets_only, type, ospf_instance_id,
- zrt->tableid, show_ng, ctx);
+ use_fib, vrf_json, use_json, tag,
+ longer_prefix_p, supernets_only, type,
+ ospf_instance_id, zrt->tableid, show_ng, ctx);
}
}
static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi,
- safi_t safi, bool use_fib, bool use_json,
- route_tag_t tag,
+ safi_t safi, bool use_fib, json_object *vrf_json,
+ bool use_json, route_tag_t tag,
const struct prefix *longer_prefix_p,
bool supernets_only, int type,
unsigned short ospf_instance_id, uint32_t tableid,
@@ -1031,7 +1044,7 @@ static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi,
return CMD_SUCCESS;
}
- do_show_route_helper(vty, zvrf, table, afi, use_fib, tag,
+ do_show_route_helper(vty, zvrf, table, afi, use_fib, vrf_json, tag,
longer_prefix_p, supernets_only, type,
ospf_instance_id, use_json, tableid, show_ng, ctx);
@@ -1063,16 +1076,22 @@ DEFPY (show_ip_nht,
json_object *json = NULL;
json_object *json_vrf = NULL;
json_object *json_nexthop = NULL;
+ struct zebra_vrf *zvrf;
+ bool resolve_via_default = false;
if (uj)
json = json_object_new_object();
if (vrf_all) {
struct vrf *vrf;
- struct zebra_vrf *zvrf;
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
if ((zvrf = vrf->info) != NULL) {
+ resolve_via_default =
+ (afi == AFI_IP)
+ ? zvrf->zebra_rnh_ip_default_route
+ : zvrf->zebra_rnh_ipv6_default_route;
+
if (uj) {
json_vrf = json_object_new_object();
json_nexthop = json_object_new_object();
@@ -1084,9 +1103,16 @@ DEFPY (show_ip_nht,
? "ipv4"
: "ipv6",
json_nexthop);
+ json_object_boolean_add(json_nexthop,
+ "resolveViaDefault",
+ resolve_via_default);
} else {
vty_out(vty, "\nVRF %s:\n",
zvrf_name(zvrf));
+ vty_out(vty,
+ " Resolve via default: %s\n",
+ resolve_via_default ? "on"
+ : "off");
}
zebra_print_rnh_table(zvrf_id(zvrf), afi, safi,
vty, NULL, json_nexthop);
@@ -1111,6 +1137,11 @@ DEFPY (show_ip_nht,
}
}
+ zvrf = zebra_vrf_lookup_by_id(vrf_id);
+ resolve_via_default = (afi == AFI_IP)
+ ? zvrf->zebra_rnh_ip_default_route
+ : zvrf->zebra_rnh_ipv6_default_route;
+
if (uj) {
json_vrf = json_object_new_object();
json_nexthop = json_object_new_object();
@@ -1122,6 +1153,13 @@ DEFPY (show_ip_nht,
json_object_object_add(json_vrf,
(afi == AFI_IP) ? "ipv4" : "ipv6",
json_nexthop);
+
+ json_object_boolean_add(json_nexthop, "resolveViaDefault",
+ resolve_via_default);
+ } else {
+ vty_out(vty, "VRF %s:\n", zvrf_name(zvrf));
+ vty_out(vty, " Resolve via default: %s\n",
+ resolve_via_default ? "on" : "off");
}
zebra_print_rnh_table(vrf_id, afi, safi, vty, p, json_nexthop);
@@ -1132,27 +1170,6 @@ DEFPY (show_ip_nht,
return CMD_SUCCESS;
}
-DEFUN (ip_nht_default_route,
- ip_nht_default_route_cmd,
- "ip nht resolve-via-default",
- IP_STR
- "Filter Next Hop tracking route resolution\n"
- "Resolve via default route\n")
-{
- ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
-
- if (!zvrf)
- return CMD_WARNING;
-
- if (zvrf->zebra_rnh_ip_default_route)
- return CMD_SUCCESS;
-
- zvrf->zebra_rnh_ip_default_route = true;
-
- zebra_evaluate_rnh(zvrf, AFI_IP, 0, NULL, SAFI_UNICAST);
- return CMD_SUCCESS;
-}
-
static void show_nexthop_group_out(struct vty *vty, struct nhg_hash_entry *nhe,
json_object *json_nhe_hdr)
{
@@ -1209,7 +1226,12 @@ static void show_nexthop_group_out(struct vty *vty, struct nhg_hash_entry *nhe,
json_object_boolean_true_add(json, "valid");
else
vty_out(vty, " Valid");
-
+ if (CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_REINSTALL)) {
+ if (json)
+ json_object_boolean_true_add(json, "reInstall");
+ else
+ vty_out(vty, ", Reinstall");
+ }
if (CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED)) {
if (json)
json_object_boolean_true_add(json, "installed");
@@ -1465,17 +1487,18 @@ static void if_nexthop_group_dump_vty(struct vty *vty, struct interface *ifp)
{
struct zebra_if *zebra_if = NULL;
struct nhg_connected *rb_node_dep = NULL;
+ bool first = true;
zebra_if = ifp->info;
- if (!if_nhg_dependents_is_empty(ifp)) {
- vty_out(vty, "Interface %s:\n", ifp->name);
-
- frr_each(nhg_connected_tree, &zebra_if->nhg_dependents,
- rb_node_dep) {
- vty_out(vty, " ");
- show_nexthop_group_out(vty, rb_node_dep->nhe, NULL);
+ frr_each (nhg_connected_tree, &zebra_if->nhg_dependents, rb_node_dep) {
+ if (first) {
+ vty_out(vty, "Interface %s:\n", ifp->name);
+ first = false;
}
+
+ vty_out(vty, " ");
+ show_nexthop_group_out(vty, rb_node_dep->nhe, NULL);
}
}
@@ -1651,68 +1674,6 @@ DEFPY_HIDDEN(backup_nexthop_recursive_use_enable,
return CMD_SUCCESS;
}
-DEFUN (no_ip_nht_default_route,
- no_ip_nht_default_route_cmd,
- "no ip nht resolve-via-default",
- NO_STR
- IP_STR
- "Filter Next Hop tracking route resolution\n"
- "Resolve via default route\n")
-{
- ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
-
- if (!zvrf)
- return CMD_WARNING;
-
- if (!zvrf->zebra_rnh_ip_default_route)
- return CMD_SUCCESS;
-
- zvrf->zebra_rnh_ip_default_route = false;
- zebra_evaluate_rnh(zvrf, AFI_IP, 0, NULL, SAFI_UNICAST);
- return CMD_SUCCESS;
-}
-
-DEFUN (ipv6_nht_default_route,
- ipv6_nht_default_route_cmd,
- "ipv6 nht resolve-via-default",
- IP6_STR
- "Filter Next Hop tracking route resolution\n"
- "Resolve via default route\n")
-{
- ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
-
- if (!zvrf)
- return CMD_WARNING;
-
- if (zvrf->zebra_rnh_ipv6_default_route)
- return CMD_SUCCESS;
-
- zvrf->zebra_rnh_ipv6_default_route = true;
- zebra_evaluate_rnh(zvrf, AFI_IP6, 0, NULL, SAFI_UNICAST);
- return CMD_SUCCESS;
-}
-
-DEFUN (no_ipv6_nht_default_route,
- no_ipv6_nht_default_route_cmd,
- "no ipv6 nht resolve-via-default",
- NO_STR
- IP6_STR
- "Filter Next Hop tracking route resolution\n"
- "Resolve via default route\n")
-{
- ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
-
- if (!zvrf)
- return CMD_WARNING;
-
- if (!zvrf->zebra_rnh_ipv6_default_route)
- return CMD_SUCCESS;
-
- zvrf->zebra_rnh_ipv6_default_route = false;
- zebra_evaluate_rnh(zvrf, AFI_IP6, 0, NULL, SAFI_UNICAST);
- return CMD_SUCCESS;
-}
-
DEFPY_HIDDEN(rnh_hide_backups, rnh_hide_backups_cmd,
"[no] ip nht hide-backup-events",
NO_STR
@@ -1786,6 +1747,7 @@ DEFPY (show_route,
struct route_show_ctx ctx = {
.multi = vrf_all || table_all,
};
+ json_object *root_json = NULL;
if (!vrf_is_backend_netns()) {
if ((vrf_all || vrf_name) && (table || table_all)) {
@@ -1807,24 +1769,42 @@ DEFPY (show_route,
}
if (vrf_all) {
+ if (!!json)
+ root_json = json_object_new_object();
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
+ json_object *vrf_json = NULL;
+
if ((zvrf = vrf->info) == NULL
|| (zvrf->table[afi][SAFI_UNICAST] == NULL))
continue;
+ if (!!json)
+ vrf_json = json_object_new_object();
+
if (table_all)
- do_show_ip_route_all(
- vty, zvrf, afi, !!fib, !!json, tag,
- prefix_str ? prefix : NULL,
- !!supernets_only, type,
- ospf_instance_id, !!ng, &ctx);
+ do_show_ip_route_all(vty, zvrf, afi, !!fib,
+ vrf_json, !!json, tag,
+ prefix_str ? prefix : NULL,
+ !!supernets_only, type,
+ ospf_instance_id, !!ng,
+ &ctx);
else
- do_show_ip_route(
- vty, zvrf_name(zvrf), afi, SAFI_UNICAST,
- !!fib, !!json, tag,
- prefix_str ? prefix : NULL,
- !!supernets_only, type,
- ospf_instance_id, table, !!ng, &ctx);
+ do_show_ip_route(vty, zvrf_name(zvrf), afi,
+ SAFI_UNICAST, !!fib, vrf_json,
+ !!json, tag,
+ prefix_str ? prefix : NULL,
+ !!supernets_only, type,
+ ospf_instance_id, table, !!ng,
+ &ctx);
+
+ if (!!json)
+ json_object_object_add(root_json,
+ zvrf_name(zvrf),
+ vrf_json);
+ }
+ if (!!json) {
+ vty_json_no_pretty(vty, root_json);
+ root_json = NULL;
}
} else {
vrf_id_t vrf_id = VRF_DEFAULT;
@@ -1840,13 +1820,13 @@ DEFPY (show_route,
return CMD_SUCCESS;
if (table_all)
- do_show_ip_route_all(vty, zvrf, afi, !!fib, !!json, tag,
- prefix_str ? prefix : NULL,
+ do_show_ip_route_all(vty, zvrf, afi, !!fib, NULL, !!json,
+ tag, prefix_str ? prefix : NULL,
!!supernets_only, type,
ospf_instance_id, !!ng, &ctx);
else
do_show_ip_route(vty, vrf->name, afi, SAFI_UNICAST,
- !!fib, !!json, tag,
+ !!fib, NULL, !!json, tag,
prefix_str ? prefix : NULL,
!!supernets_only, type,
ospf_instance_id, table, !!ng, &ctx);
@@ -2018,11 +1998,15 @@ DEFPY (show_route_summary,
afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
struct route_table *table;
bool uj = use_json(argc, argv);
+ json_object *vrf_json = NULL;
if (vrf_all) {
struct vrf *vrf;
struct zebra_vrf *zvrf;
+ if (uj && !vrf_json)
+ vrf_json = json_object_new_object();
+
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
if ((zvrf = vrf->info) == NULL)
continue;
@@ -2040,10 +2024,14 @@ DEFPY (show_route_summary,
if (prefix)
vty_show_ip_route_summary_prefix(vty, table,
- uj);
+ vrf_json, uj);
else
- vty_show_ip_route_summary(vty, table, uj);
+ vty_show_ip_route_summary(vty, table, vrf_json,
+ uj);
}
+
+ if (uj)
+ vty_json(vty, vrf_json);
} else {
vrf_id_t vrf_id = VRF_DEFAULT;
@@ -2059,9 +2047,9 @@ DEFPY (show_route_summary,
return CMD_SUCCESS;
if (prefix)
- vty_show_ip_route_summary_prefix(vty, table, uj);
+ vty_show_ip_route_summary_prefix(vty, table, NULL, uj);
else
- vty_show_ip_route_summary(vty, table, uj);
+ vty_show_ip_route_summary(vty, table, NULL, uj);
}
return CMD_SUCCESS;
@@ -2222,7 +2210,8 @@ static void show_ip_route_dump_vty(struct vty *vty, struct route_table *table)
vrf_id_to_name(re->vrf_id));
vty_out(vty, " flags: %u\n", re->flags);
- if (re->type != ZEBRA_ROUTE_CONNECT) {
+ if (re->type != ZEBRA_ROUTE_CONNECT &&
+ re->type != ZEBRA_ROUTE_LOCAL) {
vty_out(vty, " distance: %u\n", re->distance);
vty_out(vty, " metric: %u\n", re->metric);
}
@@ -2266,8 +2255,8 @@ static void show_ip_route_dump_vty(struct vty *vty, struct route_table *table)
}
}
-static void vty_show_ip_route_summary(struct vty *vty,
- struct route_table *table, bool use_json)
+static void vty_show_ip_route_summary(struct vty *vty, struct route_table *table,
+ json_object *vrf_json, bool use_json)
{
struct route_node *rn;
struct route_entry *re;
@@ -2281,6 +2270,8 @@ static void vty_show_ip_route_summary(struct vty *vty,
uint32_t is_ibgp;
json_object *json_route_summary = NULL;
json_object *json_route_routes = NULL;
+ const char *vrf_name = zvrf_name(
+ ((struct rib_table_info *)route_table_get_info(table))->zvrf);
memset(&rib_cnt, 0, sizeof(rib_cnt));
memset(&fib_cnt, 0, sizeof(fib_cnt));
@@ -2331,10 +2322,7 @@ static void vty_show_ip_route_summary(struct vty *vty,
if (!use_json)
vty_out(vty, "%-20s %-20s %s (vrf %s)\n", "Route Source",
- "Routes", "FIB",
- zvrf_name(((struct rib_table_info *)
- route_table_get_info(table))
- ->zvrf));
+ "Routes", "FIB", vrf_name);
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
if ((rib_cnt[i] > 0) || (i == ZEBRA_ROUTE_BGP
@@ -2426,7 +2414,11 @@ static void vty_show_ip_route_summary(struct vty *vty,
json_object_int_add(json_route_summary, "routesTotalFib",
fib_cnt[ZEBRA_ROUTE_TOTAL]);
- vty_json(vty, json_route_summary);
+ if (!vrf_json)
+ vty_json(vty, json_route_summary);
+ else
+ json_object_object_add(vrf_json, vrf_name,
+ json_route_summary);
} else {
vty_out(vty, "------\n");
vty_out(vty, "%-20s %-20d %-20d \n", "Totals",
@@ -2444,6 +2436,7 @@ static void vty_show_ip_route_summary(struct vty *vty,
*/
static void vty_show_ip_route_summary_prefix(struct vty *vty,
struct route_table *table,
+ json_object *vrf_json,
bool use_json)
{
struct route_node *rn;
@@ -2457,6 +2450,8 @@ static void vty_show_ip_route_summary_prefix(struct vty *vty,
int cnt;
json_object *json_route_summary = NULL;
json_object *json_route_routes = NULL;
+ const char *vrf_name = zvrf_name(
+ ((struct rib_table_info *)route_table_get_info(table))->zvrf);
memset(&rib_cnt, 0, sizeof(rib_cnt));
memset(&fib_cnt, 0, sizeof(fib_cnt));
@@ -2496,10 +2491,7 @@ static void vty_show_ip_route_summary_prefix(struct vty *vty,
if (!use_json)
vty_out(vty, "%-20s %-20s %s (vrf %s)\n", "Route Source",
- "Prefix Routes", "FIB",
- zvrf_name(((struct rib_table_info *)
- route_table_get_info(table))
- ->zvrf));
+ "Prefix Routes", "FIB", vrf_name);
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
if (rib_cnt[i] > 0) {
@@ -2574,7 +2566,11 @@ static void vty_show_ip_route_summary_prefix(struct vty *vty,
json_object_int_add(json_route_summary, "prefixRoutesTotalFib",
fib_cnt[ZEBRA_ROUTE_TOTAL]);
- vty_json(vty, json_route_summary);
+ if (!vrf_json)
+ vty_json(vty, json_route_summary);
+ else
+ json_object_object_add(vrf_json, vrf_name,
+ json_route_summary);
} else {
vty_out(vty, "------\n");
vty_out(vty, "%-20s %-20d %-20d \n", "Totals",
@@ -2695,153 +2691,6 @@ DEFPY(evpn_mh_redirect_off, evpn_mh_redirect_off_cmd,
return zebra_evpn_mh_redirect_off(vty, redirect_off);
}
-DEFUN (default_vrf_vni_mapping,
- default_vrf_vni_mapping_cmd,
- "vni " CMD_VNI_RANGE "[prefix-routes-only]",
- "VNI corresponding to the DEFAULT VRF\n"
- "VNI-ID\n"
- "Prefix routes only \n")
-{
- char xpath[XPATH_MAXLEN];
- struct zebra_vrf *zvrf = NULL;
- int filter = 0;
-
- zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
- if (!zvrf)
- return CMD_WARNING;
-
- if (argc == 3)
- filter = 1;
-
- snprintf(xpath, sizeof(xpath), FRR_VRF_KEY_XPATH "/frr-zebra:zebra",
- VRF_DEFAULT_NAME);
- nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
-
- snprintf(xpath, sizeof(xpath),
- FRR_VRF_KEY_XPATH "/frr-zebra:zebra/l3vni-id",
- VRF_DEFAULT_NAME);
- nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, argv[1]->arg);
-
- if (filter) {
- snprintf(xpath, sizeof(xpath),
- FRR_VRF_KEY_XPATH "/frr-zebra:zebra/prefix-only",
- VRF_DEFAULT_NAME);
- nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, "true");
- }
-
- return nb_cli_apply_changes(vty, NULL);
-}
-
-DEFUN (no_default_vrf_vni_mapping,
- no_default_vrf_vni_mapping_cmd,
- "no vni " CMD_VNI_RANGE "[prefix-routes-only]",
- NO_STR
- "VNI corresponding to DEFAULT VRF\n"
- "VNI-ID\n"
- "Prefix routes only \n")
-{
- char xpath[XPATH_MAXLEN];
- int filter = 0;
- vni_t vni = strtoul(argv[2]->arg, NULL, 10);
- struct zebra_vrf *zvrf = NULL;
-
- zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
- if (!zvrf)
- return CMD_WARNING;
-
- if (argc == 4)
- filter = 1;
-
- if (zvrf->l3vni != vni) {
- vty_out(vty, "VNI %d doesn't exist in VRF: %s \n", vni,
- zvrf->vrf->name);
- return CMD_WARNING;
- }
-
- snprintf(xpath, sizeof(xpath),
- FRR_VRF_KEY_XPATH "/frr-zebra:zebra/l3vni-id",
- VRF_DEFAULT_NAME);
- nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, argv[2]->arg);
-
- if (filter) {
- snprintf(xpath, sizeof(xpath),
- FRR_VRF_KEY_XPATH "/frr-zebra:zebra/prefix-only",
- VRF_DEFAULT_NAME);
- nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, "true");
- }
-
- snprintf(xpath, sizeof(xpath), FRR_VRF_KEY_XPATH "/frr-zebra:zebra",
- VRF_DEFAULT_NAME);
- nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
-
- return nb_cli_apply_changes(vty, NULL);
-}
-
-DEFUN (vrf_vni_mapping,
- vrf_vni_mapping_cmd,
- "vni " CMD_VNI_RANGE "[prefix-routes-only]",
- "VNI corresponding to tenant VRF\n"
- "VNI-ID\n"
- "prefix-routes-only\n")
-{
- int filter = 0;
-
- ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
-
- assert(vrf);
- assert(zvrf);
-
- if (argc == 3)
- filter = 1;
-
- nb_cli_enqueue_change(vty, "./frr-zebra:zebra", NB_OP_CREATE, NULL);
- nb_cli_enqueue_change(vty, "./frr-zebra:zebra/l3vni-id", NB_OP_MODIFY,
- argv[1]->arg);
-
- if (filter)
- nb_cli_enqueue_change(vty, "./frr-zebra:zebra/prefix-only",
- NB_OP_MODIFY, "true");
-
- return nb_cli_apply_changes(vty, NULL);
-}
-
-DEFUN (no_vrf_vni_mapping,
- no_vrf_vni_mapping_cmd,
- "no vni " CMD_VNI_RANGE "[prefix-routes-only]",
- NO_STR
- "VNI corresponding to tenant VRF\n"
- "VNI-ID\n"
- "prefix-routes-only\n")
-{
- int filter = 0;
-
- ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
- vni_t vni = strtoul(argv[2]->arg, NULL, 10);
-
- assert(vrf);
- assert(zvrf);
-
- if (argc == 4)
- filter = 1;
-
- if (zvrf->l3vni != vni) {
- vty_out(vty, "VNI %d doesn't exist in VRF: %s \n", vni,
- zvrf->vrf->name);
- return CMD_WARNING;
- }
-
- nb_cli_enqueue_change(vty, "./frr-zebra:zebra/l3vni-id", NB_OP_DESTROY,
- argv[2]->arg);
-
- if (filter)
- nb_cli_enqueue_change(vty, "./frr-zebra:zebra/prefix-only",
- NB_OP_DESTROY, "true");
-
- nb_cli_enqueue_change(vty, "./frr-zebra:zebra", NB_OP_DESTROY, NULL);
-
- return nb_cli_apply_changes(vty, NULL);
-}
-
/* show vrf */
DEFPY (show_vrf_vni,
show_vrf_vni_cmd,
@@ -4006,6 +3855,17 @@ static int config_write_protocol(struct vty *vty)
return 1;
}
+static inline bool zebra_vty_v6_rr_semantics_used(void)
+{
+ if (zebra_nhg_kernel_nexthops_enabled())
+ return true;
+
+ if (zrouter.v6_rr_semantics)
+ return true;
+
+ return false;
+}
+
DEFUN (show_zebra,
show_zebra_cmd,
"show zebra",
@@ -4025,7 +3885,9 @@ DEFUN (show_zebra,
ttable_add_row(table, "MPLS|%s", mpls_enabled ? "On" : "Off");
ttable_add_row(table, "EVPN|%s", is_evpn_enabled() ? "On" : "Off");
ttable_add_row(table, "Kernel socket buffer size|%d", rcvbufsize);
-
+ ttable_add_row(table, "v6 Route Replace Semantics|%s",
+ zebra_vty_v6_rr_semantics_used() ? "Replace"
+ : "Delete then Add");
#ifdef GNU_LINUX
if (!vrf_is_backend_netns())
@@ -4036,6 +3898,9 @@ DEFUN (show_zebra,
ttable_add_row(table, "VRF|Not Available");
#endif
+ ttable_add_row(table, "v6 with v4 nexthop|%s",
+ zrouter.v6_with_v4_nexthop ? "Used" : "Unavaliable");
+
ttable_add_row(table, "ASIC offload|%s",
zrouter.asic_offloaded ? "Used" : "Unavailable");
@@ -4457,31 +4322,6 @@ DEFPY (no_zebra_protodown_bit,
#endif /* HAVE_NETLINK */
-DEFUN(ip_table_range, ip_table_range_cmd,
- "[no] ip table range (1-4294967295) (1-4294967295)",
- NO_STR IP_STR
- "table configuration\n"
- "Configure table range\n"
- "Start Routing Table\n"
- "End Routing Table\n")
-{
- ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
-
- if (!zvrf)
- return CMD_WARNING;
-
- if (zvrf_id(zvrf) != VRF_DEFAULT && !vrf_is_backend_netns()) {
- vty_out(vty,
- "VRF subcommand does not make any sense in l3mdev based vrf's\n");
- return CMD_WARNING;
- }
-
- if (strmatch(argv[0]->text, "no"))
- return table_manager_range(vty, false, zvrf, NULL, NULL);
-
- 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,
@@ -4593,14 +4433,6 @@ void zebra_vty_init(void)
install_element(VIEW_NODE, &show_ip_rpf_addr_cmd);
install_element(VIEW_NODE, &show_ipv6_rpf_addr_cmd);
- install_element(CONFIG_NODE, &ip_nht_default_route_cmd);
- install_element(CONFIG_NODE, &no_ip_nht_default_route_cmd);
- install_element(CONFIG_NODE, &ipv6_nht_default_route_cmd);
- install_element(CONFIG_NODE, &no_ipv6_nht_default_route_cmd);
- install_element(VRF_NODE, &ip_nht_default_route_cmd);
- install_element(VRF_NODE, &no_ip_nht_default_route_cmd);
- install_element(VRF_NODE, &ipv6_nht_default_route_cmd);
- install_element(VRF_NODE, &no_ipv6_nht_default_route_cmd);
install_element(CONFIG_NODE, &rnh_hide_backups_cmd);
install_element(VIEW_NODE, &show_frr_cmd);
@@ -4652,19 +4484,12 @@ void zebra_vty_init(void)
install_element(CONFIG_NODE, &evpn_mh_neigh_holdtime_cmd);
install_element(CONFIG_NODE, &evpn_mh_startup_delay_cmd);
install_element(CONFIG_NODE, &evpn_mh_redirect_off_cmd);
- install_element(CONFIG_NODE, &default_vrf_vni_mapping_cmd);
- install_element(CONFIG_NODE, &no_default_vrf_vni_mapping_cmd);
- install_element(VRF_NODE, &vrf_vni_mapping_cmd);
- install_element(VRF_NODE, &no_vrf_vni_mapping_cmd);
install_element(VIEW_NODE, &show_dataplane_cmd);
install_element(VIEW_NODE, &show_dataplane_providers_cmd);
install_element(CONFIG_NODE, &zebra_dplane_queue_limit_cmd);
install_element(CONFIG_NODE, &no_zebra_dplane_queue_limit_cmd);
- install_element(CONFIG_NODE, &ip_table_range_cmd);
- install_element(VRF_NODE, &ip_table_range_cmd);
-
#ifdef HAVE_NETLINK
install_element(CONFIG_NODE, &zebra_kernel_netlink_batch_tx_buf_cmd);
install_element(CONFIG_NODE, &no_zebra_kernel_netlink_batch_tx_buf_cmd);
diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c
index 36290f99e0..89b43f6d22 100644
--- a/zebra/zebra_vxlan.c
+++ b/zebra/zebra_vxlan.c
@@ -82,7 +82,7 @@ static int zl3vni_nh_uninstall(struct zebra_l3vni *zl3vni,
struct zebra_neigh *n);
static struct zebra_neigh *svd_nh_add(const struct ipaddr *vtep_ip,
const struct ethaddr *rmac);
-static int svd_nh_del(struct zebra_neigh *n);
+static void svd_nh_del(struct zebra_neigh *n);
static int svd_nh_install(struct zebra_l3vni *zl3vni, struct zebra_neigh *n);
static int svd_nh_uninstall(struct zebra_l3vni *zl3vni, struct zebra_neigh *n);
@@ -194,7 +194,7 @@ static int l3vni_rmac_nh_list_cmp(void *p1, void *p2)
const struct ipaddr *vtep_ip1 = p1;
const struct ipaddr *vtep_ip2 = p2;
- return !ipaddr_cmp(vtep_ip1, vtep_ip2);
+ return ipaddr_cmp(vtep_ip1, vtep_ip2);
}
static void l3vni_rmac_nh_free(struct ipaddr *vtep_ip)
@@ -308,7 +308,7 @@ static void zevpn_print_neigh_hash_all_evpn_detail(struct hash_bucket *bucket,
zevpn = (struct zebra_evpn *)bucket->data;
if (!zevpn) {
if (json)
- vty_out(vty, "{}\n");
+ vty_json_empty(vty, json);
return;
}
num_neigh = hashcount(zevpn->neigh_table);
@@ -515,7 +515,7 @@ static void zevpn_print_mac_hash_all_evpn_detail(struct hash_bucket *bucket,
zevpn = (struct zebra_evpn *)bucket->data;
if (!zevpn) {
if (json)
- vty_out(vty, "{}\n");
+ vty_json_empty(vty, json);
return;
}
wctx->zevpn = zevpn;
@@ -769,10 +769,6 @@ static void zl3vni_print(struct zebra_l3vni *zl3vni, void **ctx)
json_evpn_list = json_object_new_array();
json_object_int_add(json, "vni", zl3vni->vni);
json_object_string_add(json, "type", "L3");
-#if CONFDATE > 20240210
-CPP_NOTICE("Drop `vrf` from JSON outputs")
-#endif
- json_object_string_add(json, "vrf", zl3vni_vrf_name(zl3vni));
json_object_string_add(json, "tenantVrf",
zl3vni_vrf_name(zl3vni));
json_object_string_addf(json, "localVtepIp", "%pI4",
@@ -891,6 +887,7 @@ static int zvni_map_to_svi_ns(struct ns *ns,
if (vl->vid == in_param->vid) {
*p_ifp = tmp_if;
+ route_unlock_node(rn);
return NS_WALK_STOP;
}
}
@@ -1589,17 +1586,24 @@ static struct zebra_neigh *svd_nh_add(const struct ipaddr *ip,
/*
* Del Single VXlan Device neighbor entry.
*/
-static int svd_nh_del(struct zebra_neigh *n)
+static void svd_nh_del(struct zebra_neigh *n)
{
if (n->refcnt > 0)
- return -1;
+ return;
hash_release(svd_nh_table, n);
XFREE(MTYPE_L3NEIGH, n);
+}
- return 0;
+static void svd_nh_del_terminate(void *ptr)
+{
+ struct zebra_neigh *n = ptr;
+
+ n->refcnt = 0;
+ svd_nh_del(n);
}
+
/*
* Common code to install remote nh as neigh into the kernel.
*/
@@ -2005,6 +2009,7 @@ static int zl3vni_map_to_vxlan_if_ns(struct ns *ns,
zl3vni->local_vtep_ip = zif->l2info.vxl.vtep_ip;
*_pifp = (void *)ifp;
+ route_unlock_node(rn);
return NS_WALK_STOP;
}
@@ -2116,6 +2121,7 @@ static int zl3vni_from_svi_ns(struct ns *ns, void *_in_param, void **_p_zl3vni)
zif, in_param->br_if);
if (vni_id) {
found = 1;
+ route_unlock_node(rn);
break;
}
}
@@ -2255,14 +2261,13 @@ static int zl3vni_send_add_to_client(struct zebra_l3vni *zl3vni)
stream_putw_at(s, 0, stream_get_endp(s));
if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug(
- "Send L3_VNI_ADD %u VRF %s RMAC %pEA VRR %pEA local-ip %pI4 filter %s to %s",
- zl3vni->vni, vrf_id_to_name(zl3vni_vrf_id(zl3vni)),
- &svi_rmac, &vrr_rmac, &zl3vni->local_vtep_ip,
- CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY)
- ? "prefix-routes-only"
- : "none",
- zebra_route_string(client->proto));
+ zlog_debug("Send L3VNI ADD %u VRF %s RMAC %pEA VRR %pEA local-ip %pI4 filter %s to %s",
+ zl3vni->vni, vrf_id_to_name(zl3vni_vrf_id(zl3vni)),
+ &svi_rmac, &vrr_rmac, &zl3vni->local_vtep_ip,
+ CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY)
+ ? "prefix-routes-only"
+ : "none",
+ zebra_route_string(client->proto));
client->l3vniadd_cnt++;
return zserv_send_message(client, s);
@@ -2290,7 +2295,7 @@ static int zl3vni_send_del_to_client(struct zebra_l3vni *zl3vni)
stream_putw_at(s, 0, stream_get_endp(s));
if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug("Send L3_VNI_DEL %u VRF %s to %s", zl3vni->vni,
+ zlog_debug("Send L3VNI DEL %u VRF %s to %s", zl3vni->vni,
vrf_id_to_name(zl3vni_vrf_id(zl3vni)),
zebra_route_string(client->proto));
@@ -2402,6 +2407,7 @@ static int zebra_vxlan_handle_vni_transition(struct zebra_vrf *zvrf, vni_t vni,
vnip = zebra_vxlan_if_vni_find(zif, vni);
if (vnip) {
found = true;
+ route_unlock_node(rn);
break;
}
}
@@ -2586,14 +2592,15 @@ void zebra_vxlan_print_specific_rmac_l3vni(struct vty *vty, vni_t l3vni,
json = json_object_new_object();
if (!is_evpn_enabled()) {
- vty_json(vty, json);
+ if (use_json)
+ vty_json_empty(vty, json);
return;
}
zl3vni = zl3vni_lookup(l3vni);
if (!zl3vni) {
if (use_json)
- vty_json(vty, json);
+ vty_json_empty(vty, json);
else
vty_out(vty, "%% L3-VNI %u doesn't exist\n", l3vni);
return;
@@ -2627,14 +2634,15 @@ void zebra_vxlan_print_rmacs_l3vni(struct vty *vty, vni_t l3vni, bool use_json)
json = json_object_new_object();
if (!is_evpn_enabled()) {
- vty_json(vty, json);
+ if (use_json)
+ vty_json_empty(vty, json);
return;
}
zl3vni = zl3vni_lookup(l3vni);
if (!zl3vni) {
if (use_json)
- vty_json(vty, json);
+ vty_json_empty(vty, json);
else
vty_out(vty, "%% L3-VNI %u does not exist\n", l3vni);
return;
@@ -2668,7 +2676,8 @@ void zebra_vxlan_print_rmacs_all_l3vni(struct vty *vty, bool use_json)
json = json_object_new_object();
if (!is_evpn_enabled()) {
- vty_json(vty, json);
+ if (use_json)
+ vty_json_empty(vty, json);
return;
}
@@ -2694,7 +2703,8 @@ void zebra_vxlan_print_specific_nh_l3vni(struct vty *vty, vni_t l3vni,
json = json_object_new_object();
if (!is_evpn_enabled()) {
- vty_json(vty, json);
+ if (use_json)
+ vty_json_empty(vty, json);
return;
}
@@ -2705,7 +2715,7 @@ void zebra_vxlan_print_specific_nh_l3vni(struct vty *vty, vni_t l3vni,
zl3vni = zl3vni_lookup(l3vni);
if (!zl3vni) {
if (use_json)
- vty_out(vty, "{}\n");
+ vty_json(vty, json);
else
vty_out(vty, "%% L3-VNI %u does not exist\n",
l3vni);
@@ -2717,7 +2727,7 @@ void zebra_vxlan_print_specific_nh_l3vni(struct vty *vty, vni_t l3vni,
if (!n) {
if (use_json)
- vty_out(vty, "{}\n");
+ vty_json_empty(vty, json);
else
vty_out(vty,
"%% Requested next-hop not present for L3-VNI %u\n",
@@ -2738,13 +2748,16 @@ static void l3vni_print_nh_table(struct hash *nh_table, struct vty *vty,
struct nh_walk_ctx wctx;
json_object *json = NULL;
- num_nh = hashcount(nh_table);
- if (!num_nh)
- return;
-
if (use_json)
json = json_object_new_object();
+ num_nh = hashcount(nh_table);
+ if (!num_nh) {
+ if (use_json)
+ vty_json_empty(vty, json);
+ return;
+ }
+
wctx.vty = vty;
wctx.json = json;
if (!use_json) {
@@ -2766,14 +2779,14 @@ void zebra_vxlan_print_nh_l3vni(struct vty *vty, vni_t l3vni, bool use_json)
if (!is_evpn_enabled()) {
if (use_json)
- vty_out(vty, "{}\n");
+ vty_json_empty(vty, NULL);
return;
}
zl3vni = zl3vni_lookup(l3vni);
if (!zl3vni) {
if (use_json)
- vty_out(vty, "{}\n");
+ vty_json_empty(vty, NULL);
else
vty_out(vty, "%% L3-VNI %u does not exist\n", l3vni);
return;
@@ -2786,7 +2799,7 @@ void zebra_vxlan_print_nh_svd(struct vty *vty, bool use_json)
{
if (!is_evpn_enabled()) {
if (use_json)
- vty_out(vty, "{}\n");
+ vty_json_empty(vty, NULL);
return;
}
@@ -2802,7 +2815,8 @@ void zebra_vxlan_print_nh_all_l3vni(struct vty *vty, bool use_json)
json = json_object_new_object();
if (!is_evpn_enabled()) {
- vty_json(vty, json);
+ if (use_json)
+ vty_json_empty(vty, json);
return;
}
@@ -2830,14 +2844,15 @@ void zebra_vxlan_print_l3vni(struct vty *vty, vni_t vni, bool use_json)
json = json_object_new_object();
if (!is_evpn_enabled()) {
- vty_json(vty, json);
+ if (use_json)
+ vty_json_empty(vty, json);
return;
}
zl3vni = zl3vni_lookup(vni);
if (!zl3vni) {
if (use_json)
- vty_json(vty, json);
+ vty_json_empty(vty, json);
else
vty_out(vty, "%% VNI %u does not exist\n", vni);
return;
@@ -2901,14 +2916,15 @@ void zebra_vxlan_print_neigh_vni(struct vty *vty, struct zebra_vrf *zvrf,
json = json_object_new_object();
if (!is_evpn_enabled()) {
- vty_json(vty, json);
+ if (use_json)
+ vty_json_empty(vty, json);
return;
}
zevpn = zebra_evpn_lookup(vni);
if (!zevpn) {
if (use_json)
- vty_json(vty, json);
+ vty_json_empty(vty, json);
else
vty_out(vty, "%% VNI %u does not exist\n", vni);
return;
@@ -2955,7 +2971,8 @@ void zebra_vxlan_print_neigh_all_vni(struct vty *vty, struct zebra_vrf *zvrf,
json = json_object_new_object();
if (!is_evpn_enabled()) {
- vty_json(vty, json);
+ if (use_json)
+ vty_json_empty(vty, json);
return;
}
@@ -2985,7 +3002,8 @@ void zebra_vxlan_print_neigh_all_vni_detail(struct vty *vty,
json = json_object_new_object();
if (!is_evpn_enabled()) {
- vty_json(vty, json);
+ if (use_json)
+ vty_json_empty(vty, json);
return;
}
@@ -3016,14 +3034,15 @@ void zebra_vxlan_print_specific_neigh_vni(struct vty *vty,
json = json_object_new_object();
if (!is_evpn_enabled()) {
- vty_json(vty, json);
+ if (use_json)
+ vty_json_empty(vty, json);
return;
}
zevpn = zebra_evpn_lookup(vni);
if (!zevpn) {
if (use_json)
- vty_json(vty, json);
+ vty_json_empty(vty, json);
else
vty_out(vty, "%% VNI %u does not exist\n", vni);
return;
@@ -3060,14 +3079,15 @@ void zebra_vxlan_print_neigh_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf,
json = json_object_new_object();
if (!is_evpn_enabled()) {
- vty_json(vty, json);
+ if (use_json)
+ vty_json_empty(vty, json);
return;
}
zevpn = zebra_evpn_lookup(vni);
if (!zevpn) {
if (use_json)
- vty_json(vty, json);
+ vty_json_empty(vty, json);
else
vty_out(vty, "%% VNI %u does not exist\n", vni);
return;
@@ -3109,14 +3129,15 @@ void zebra_vxlan_print_neigh_vni_dad(struct vty *vty,
json = json_object_new_object();
if (!is_evpn_enabled()) {
- vty_json(vty, json);
+ if (use_json)
+ vty_json_empty(vty, json);
return;
}
zevpn = zebra_evpn_lookup(vni);
if (!zevpn) {
if (use_json)
- vty_json(vty, json);
+ vty_json_empty(vty, json);
else
vty_out(vty, "%% VNI %u does not exist\n", vni);
return;
@@ -3173,21 +3194,24 @@ void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf,
if (!is_evpn_enabled()) {
if (use_json)
- vty_out(vty, "{}\n");
+ vty_json_empty(vty, NULL);
return;
}
zevpn = zebra_evpn_lookup(vni);
if (!zevpn) {
if (use_json)
- vty_out(vty, "{}\n");
+ vty_json_empty(vty, NULL);
else
vty_out(vty, "%% VNI %u does not exist\n", vni);
return;
}
num_macs = num_valid_macs(zevpn);
- if (!num_macs)
+ if (!num_macs) {
+ if (use_json)
+ vty_json_empty(vty, NULL);
return;
+ }
if (use_json) {
json = json_object_new_object();
@@ -3225,7 +3249,11 @@ void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf,
if (use_json) {
json_object_object_add(json, "macs", json_mac);
- vty_json(vty, json);
+ /*
+ * This is an extremely expensive operation at scale
+ * and non-pretty reduces memory footprint significantly.
+ */
+ vty_json_no_pretty(vty, json);
}
}
@@ -3242,7 +3270,8 @@ void zebra_vxlan_print_macs_all_vni(struct vty *vty, struct zebra_vrf *zvrf,
json = json_object_new_object();
if (!is_evpn_enabled()) {
- vty_json(vty, json);
+ if (use_json)
+ vty_json_empty(vty, json);
return;
}
@@ -3270,7 +3299,8 @@ void zebra_vxlan_print_macs_all_vni_detail(struct vty *vty,
json = json_object_new_object();
if (!is_evpn_enabled()) {
- vty_json(vty, json);
+ if (use_json)
+ vty_json_empty(vty, json);
return;
}
@@ -3299,7 +3329,8 @@ void zebra_vxlan_print_macs_all_vni_vtep(struct vty *vty,
json = json_object_new_object();
if (!is_evpn_enabled()) {
- vty_json(vty, json);
+ if (use_json)
+ vty_json_empty(vty, json);
return;
}
@@ -3329,7 +3360,8 @@ void zebra_vxlan_print_specific_mac_vni(struct vty *vty, struct zebra_vrf *zvrf,
json = json_object_new_object();
if (!is_evpn_enabled()) {
- vty_json(vty, json);
+ if (use_json)
+ vty_json_empty(vty, json);
return;
}
@@ -3369,22 +3401,34 @@ void zebra_vxlan_print_macs_vni_dad(struct vty *vty,
json_object *json = NULL;
json_object *json_mac = NULL;
- if (!is_evpn_enabled())
+ if (!is_evpn_enabled()) {
+ if (use_json)
+ vty_json_empty(vty, NULL);
return;
+ }
zevpn = zebra_evpn_lookup(vni);
if (!zevpn) {
- vty_out(vty, "%% VNI %u does not exist\n", vni);
+ if (use_json)
+ vty_json_empty(vty, NULL);
+ else
+ vty_out(vty, "%% VNI %u does not exist\n", vni);
return;
}
num_macs = num_valid_macs(zevpn);
- if (!num_macs)
+ if (!num_macs) {
+ if (use_json)
+ vty_json_empty(vty, NULL);
return;
+ }
num_macs = num_dup_detected_macs(zevpn);
- if (!num_macs)
+ if (!num_macs) {
+ if (use_json)
+ vty_json_empty(vty, NULL);
return;
+ }
if (use_json) {
json = json_object_new_object();
@@ -3719,21 +3763,25 @@ void zebra_vxlan_print_macs_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf,
json_object *json_mac = NULL;
if (!is_evpn_enabled()) {
- vty_json(vty, json);
+ if (use_json)
+ vty_json_empty(vty, NULL);
return;
}
zevpn = zebra_evpn_lookup(vni);
if (!zevpn) {
if (use_json)
- vty_out(vty, "{}\n");
+ vty_json_empty(vty, NULL);
else
vty_out(vty, "%% VNI %u does not exist\n", vni);
return;
}
num_macs = num_valid_macs(zevpn);
- if (!num_macs)
+ if (!num_macs) {
+ if (use_json)
+ vty_json_empty(vty, NULL);
return;
+ }
if (use_json) {
json = json_object_new_object();
@@ -3777,7 +3825,8 @@ void zebra_vxlan_print_vni(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni,
json = json_object_new_object();
if (!is_evpn_enabled()) {
- vty_json(vty, json);
+ if (use_json)
+ vty_json_empty(vty, json);
return;
}
@@ -3821,7 +3870,8 @@ void zebra_vxlan_print_evpn(struct vty *vty, bool uj)
json = json_object_new_object();
if (!is_evpn_enabled()) {
- vty_json(vty, json);
+ if (uj)
+ vty_json(vty, json);
return;
}
@@ -3898,7 +3948,8 @@ void zebra_vxlan_print_vnis(struct vty *vty, struct zebra_vrf *zvrf,
json = json_object_new_object();
if (!is_evpn_enabled()) {
- vty_json(vty, json);
+ if (use_json)
+ vty_json_empty(vty, json);
return;
}
@@ -3982,7 +4033,7 @@ void zebra_vxlan_print_vnis_detail(struct vty *vty, struct zebra_vrf *zvrf,
if (!is_evpn_enabled()) {
if (use_json)
- vty_out(vty, "{}\n");
+ vty_json_empty(vty, NULL);
return;
}
@@ -4010,8 +4061,12 @@ void zebra_vxlan_print_vnis_detail(struct vty *vty, struct zebra_vrf *zvrf,
void *))zl3vni_print_hash_detail,
&zes);
+ /*
+ * This is an extremely expensive operation at scale
+ * and non-pretty reduces memory footprint significantly.
+ */
if (use_json)
- vty_json(vty, json_array);
+ vty_json_no_pretty(vty, json_array);
}
/*
@@ -5098,7 +5153,21 @@ void zebra_vxlan_macvlan_up(struct interface *ifp)
zif = ifp->info;
assert(zif);
+
+ if (zif->link_nsid)
+ /* the link interface is another namespace */
+ return;
+
link_ifp = zif->link;
+ if (!link_ifp) {
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug(
+ "macvlan parent link is not found. Parent index %d ifp %s",
+ zif->link_ifindex,
+ ifindex2ifname(zif->link_ifindex,
+ ifp->vrf->vrf_id));
+ return;
+ }
link_zif = link_ifp->info;
assert(link_zif);
@@ -5115,9 +5184,8 @@ void zebra_vxlan_macvlan_up(struct interface *ifp)
}
}
-int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf *zvrf, vni_t vni,
- char *err, int err_str_sz, int filter,
- int add)
+void zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf *zvrf, vni_t vni,
+ int filter, int add)
{
struct zebra_l3vni *zl3vni = NULL;
struct zebra_vrf *zvrf_evpn = NULL;
@@ -5129,21 +5197,6 @@ int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf *zvrf, vni_t vni,
add ? "ADD" : "DEL");
if (add) {
- /* check if the vni is already present under zvrf */
- if (zvrf->l3vni) {
- snprintf(err, err_str_sz,
- "VNI is already configured under the vrf");
- return -1;
- }
-
- /* check if this VNI is already present in the system */
- zl3vni = zl3vni_lookup(vni);
- if (zl3vni) {
- snprintf(err, err_str_sz,
- "VNI is already configured as L3-VNI");
- return -1;
- }
-
/* Remove L2VNI if present */
zebra_vxlan_handle_vni_transition(zvrf, vni, add);
@@ -5189,23 +5242,7 @@ int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf *zvrf, vni_t vni,
} else {
zl3vni = zl3vni_lookup(vni);
- if (!zl3vni) {
- snprintf(err, err_str_sz, "VNI doesn't exist");
- return -1;
- }
-
- if (zvrf->l3vni != vni) {
- snprintf(err, err_str_sz,
- "VNI %d doesn't exist in VRF: %s",
- vni, zvrf->vrf->name);
- return -1;
- }
-
- if (filter && !CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY)) {
- snprintf(err, ERR_STR_SZ,
- "prefix-routes-only is not set for the vni");
- return -1;
- }
+ assert(zl3vni);
zebra_vxlan_process_l3vni_oper_down(zl3vni);
@@ -5223,7 +5260,6 @@ int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf *zvrf, vni_t vni,
/* Add L2VNI for this VNI */
zebra_vxlan_handle_vni_transition(zvrf, vni, add);
}
- return 0;
}
int zebra_vxlan_vrf_enable(struct zebra_vrf *zvrf)
@@ -5274,7 +5310,9 @@ int zebra_vxlan_vrf_delete(struct zebra_vrf *zvrf)
vni = zl3vni->vni;
zl3vni_del(zl3vni);
- zebra_vxlan_handle_vni_transition(zvrf, vni, 0);
+
+ if (!zrouter.in_shutdown)
+ zebra_vxlan_handle_vni_transition(zvrf, vni, 0);
return 0;
}
@@ -5758,6 +5796,11 @@ void zebra_vxlan_init(void)
zebra_evpn_mh_init();
}
+void zebra_vxlan_terminate(void)
+{
+ hash_clean_and_free(&svd_nh_table, svd_nh_del_terminate);
+}
+
/* free l3vni table */
void zebra_vxlan_disable(void)
{
@@ -5935,8 +5978,6 @@ static void zebra_vxlan_sg_del(struct zebra_vxlan_sg *vxlan_sg)
struct zebra_vrf *zvrf;
zvrf = vrf_info_lookup(VRF_DEFAULT);
- if (!zvrf)
- return;
/* On SG entry deletion remove the reference to its parent XG
* entry
@@ -6006,8 +6047,6 @@ void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip,
return;
zvrf = vrf_info_lookup(VRF_DEFAULT);
- if (!zvrf)
- return;
zebra_vxlan_sg_do_deref(zvrf, local_vtep_ip, mcast_grp);
}
@@ -6021,8 +6060,7 @@ void zebra_vxlan_sg_ref(struct in_addr local_vtep_ip, struct in_addr mcast_grp)
return;
zvrf = vrf_info_lookup(VRF_DEFAULT);
- if (!zvrf)
- return;
+
zebra_vxlan_sg_do_ref(zvrf, local_vtep_ip, mcast_grp);
}
diff --git a/zebra/zebra_vxlan.h b/zebra/zebra_vxlan.h
index 98c2767eb2..eb02de6f7b 100644
--- a/zebra/zebra_vxlan.h
+++ b/zebra/zebra_vxlan.h
@@ -178,13 +178,13 @@ extern int zebra_vxlan_if_add(struct interface *ifp);
extern int zebra_vxlan_if_update(struct interface *ifp,
struct zebra_vxlan_if_update_ctx *ctx);
extern int zebra_vxlan_if_del(struct interface *ifp);
-extern int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf *zvrf, vni_t vni,
- char *err, int err_str_sz,
- int filter, int add);
+extern void zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf *zvrf, vni_t vni,
+ int filter, int add);
extern void zebra_vxlan_init_tables(struct zebra_vrf *zvrf);
extern void zebra_vxlan_close_tables(struct zebra_vrf *);
extern void zebra_vxlan_cleanup_tables(struct zebra_vrf *);
extern void zebra_vxlan_init(void);
+extern void zebra_vxlan_terminate(void);
extern void zebra_vxlan_disable(void);
extern void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id,
const struct ethaddr *rmac,
diff --git a/zebra/zserv.c b/zebra/zserv.c
index 6abd49310c..27668534ee 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -181,9 +181,10 @@ void zserv_log_message(const char *errmsg, struct stream *msg,
*/
static void zserv_client_fail(struct zserv *client)
{
- flog_warn(EC_ZEBRA_CLIENT_IO_ERROR,
- "Client '%s' encountered an error and is shutting down.",
- zebra_route_string(client->proto));
+ flog_warn(
+ EC_ZEBRA_CLIENT_IO_ERROR,
+ "Client '%s' (session id %d) encountered an error and is shutting down.",
+ zebra_route_string(client->proto), client->session_id);
atomic_store_explicit(&client->pthread->running, false,
memory_order_relaxed);
@@ -305,6 +306,14 @@ zwrite_fail:
* this task reschedules itself.
*
* Any failure in any of these actions is handled by terminating the client.
+ *
+ * The client's input buffer ibuf_fifo can have a maximum items as configured
+ * in the packets_to_process. This way we are not filling up the FIFO more
+ * than the maximum when the zebra main is busy. If the fifo has space, we
+ * reschedule ourselves to read more.
+ *
+ * The main thread processes the items in ibuf_fifo and always signals the
+ * client IO thread.
*/
static void zserv_read(struct event *thread)
{
@@ -312,15 +321,25 @@ static void zserv_read(struct event *thread)
int sock;
size_t already;
struct stream_fifo *cache;
- uint32_t p2p_orig;
-
- uint32_t p2p;
+ uint32_t p2p; /* Temp p2p used to process */
+ uint32_t p2p_orig; /* Configured p2p (Default-1000) */
+ int p2p_avail; /* How much space is available for p2p */
struct zmsghdr hdr;
+ size_t client_ibuf_fifo_cnt = stream_fifo_count_safe(client->ibuf_fifo);
p2p_orig = atomic_load_explicit(&zrouter.packets_to_process,
memory_order_relaxed);
+ p2p_avail = p2p_orig - client_ibuf_fifo_cnt;
+
+ /*
+ * Do nothing if ibuf_fifo count has reached its max limit. Otherwise
+ * proceed and reschedule ourselves if there is space in the ibuf_fifo.
+ */
+ if (p2p_avail <= 0)
+ return;
+
+ p2p = p2p_avail;
cache = stream_fifo_new();
- p2p = p2p_orig;
sock = EVENT_FD(thread);
while (p2p) {
@@ -420,7 +439,7 @@ static void zserv_read(struct event *thread)
p2p--;
}
- if (p2p < p2p_orig) {
+ if (p2p < (uint32_t)p2p_avail) {
uint64_t time_now = monotime(NULL);
/* update session statistics */
@@ -434,19 +453,23 @@ static void zserv_read(struct event *thread)
while (cache->head)
stream_fifo_push(client->ibuf_fifo,
stream_fifo_pop(cache));
+ /* Need to update count as main thread could have processed few */
+ client_ibuf_fifo_cnt =
+ stream_fifo_count_safe(client->ibuf_fifo);
}
/* Schedule job to process those packets */
zserv_event(client, ZSERV_PROCESS_MESSAGES);
-
}
if (IS_ZEBRA_DEBUG_PACKET)
- zlog_debug("Read %d packets from client: %s", p2p_orig - p2p,
- zebra_route_string(client->proto));
+ zlog_debug("Read %d packets from client: %s. Current ibuf fifo count: %zu. Conf P2p %d",
+ p2p_avail - p2p, zebra_route_string(client->proto),
+ client_ibuf_fifo_cnt, p2p_orig);
- /* Reschedule ourselves */
- zserv_client_event(client, ZSERV_CLIENT_READ);
+ /* Reschedule ourselves since we have space in ibuf_fifo */
+ if (client_ibuf_fifo_cnt < p2p_orig)
+ zserv_client_event(client, ZSERV_CLIENT_READ);
stream_fifo_free(cache);
@@ -482,14 +505,20 @@ static void zserv_client_event(struct zserv *client,
* as the task argument.
*
* Each message is popped off the client's input queue and the action associated
- * with the message is executed. This proceeds until there are no more messages,
- * an error occurs, or the processing limit is reached.
+ * with the message is executed. This proceeds until an error occurs, or the
+ * processing limit is reached.
*
* The client's I/O thread can push at most zrouter.packets_to_process messages
* onto the input buffer before notifying us there are packets to read. As long
* as we always process zrouter.packets_to_process messages here, then we can
* rely on the read thread to handle queuing this task enough times to process
* everything on the input queue.
+ *
+ * If the client ibuf always schedules a wakeup to the client IO to read more
+ * items from the socked buffer. This way we ensure
+ * - Client IO thread always tries to read the socket buffer and add more
+ * items to the ibuf_fifo (until max limit)
+ * - the hidden config change (zebra zapi-packets <>) is taken into account.
*/
static void zserv_process_messages(struct event *thread)
{
@@ -507,8 +536,6 @@ static void zserv_process_messages(struct event *thread)
stream_fifo_push(cache, msg);
}
- msg = NULL;
-
/* Need to reschedule processing work if there are still
* packets in the fifo.
*/
@@ -525,6 +552,9 @@ static void zserv_process_messages(struct event *thread)
/* Reschedule ourselves if necessary */
if (need_resched)
zserv_event(client, ZSERV_PROCESS_MESSAGES);
+
+ /* Ensure to include the read socket in the select/poll/etc.. */
+ zserv_client_event(client, ZSERV_CLIENT_READ);
}
int zserv_send_message(struct zserv *client, struct stream *msg)
@@ -583,23 +613,27 @@ static void zserv_client_free(struct zserv *client)
/* Close file descriptor. */
if (client->sock) {
- unsigned long nroutes;
- unsigned long nnhgs;
+ unsigned long nroutes = 0;
+ unsigned long nnhgs = 0;
close(client->sock);
if (DYNAMIC_CLIENT_GR_DISABLED(client)) {
- zebra_mpls_client_cleanup_vrf_label(client->proto);
+ if (!client->synchronous) {
+ zebra_mpls_client_cleanup_vrf_label(
+ client->proto);
- nroutes = rib_score_proto(client->proto,
- client->instance);
+ nroutes = rib_score_proto(client->proto,
+ client->instance);
+ }
zlog_notice(
"client %d disconnected %lu %s routes removed from the rib",
client->sock, nroutes,
zebra_route_string(client->proto));
/* Not worrying about instance for now */
- nnhgs = zebra_nhg_score_proto(client->proto);
+ if (!client->synchronous)
+ nnhgs = zebra_nhg_score_proto(client->proto);
zlog_notice(
"client %d disconnected %lu %s nhgs removed from the rib",
client->sock, nnhgs,
@@ -628,23 +662,27 @@ static void zserv_client_free(struct zserv *client)
/* Free bitmaps. */
for (afi_t afi = AFI_IP; afi < AFI_MAX; afi++) {
for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) {
- vrf_bitmap_free(client->redist[afi][i]);
+ vrf_bitmap_free(&client->redist[afi][i]);
redist_del_all_instances(&client->mi_redist[afi][i]);
}
- vrf_bitmap_free(client->redist_default[afi]);
- vrf_bitmap_free(client->ridinfo[afi]);
- vrf_bitmap_free(client->nhrp_neighinfo[afi]);
+ vrf_bitmap_free(&client->redist_default[afi]);
+ vrf_bitmap_free(&client->ridinfo[afi]);
+ vrf_bitmap_free(&client->neighinfo[afi]);
}
/*
* If any instance are graceful restart enabled,
* client is not deleted
*/
- if (DYNAMIC_CLIENT_GR_DISABLED(client)) {
+ if (DYNAMIC_CLIENT_GR_DISABLED(client) || zebra_router_in_shutdown()) {
if (IS_ZEBRA_DEBUG_EVENT)
zlog_debug("%s: Deleting client %s", __func__,
zebra_route_string(client->proto));
+
+ if (zebra_router_in_shutdown())
+ zebra_gr_client_final_shutdown(client);
+
zserv_client_delete(client);
} else {
/* Handle cases where client has GR instance. */
@@ -752,10 +790,10 @@ static struct zserv *zserv_client_create(int sock)
/* Initialize flags */
for (afi = AFI_IP; afi < AFI_MAX; afi++) {
for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
- client->redist[afi][i] = vrf_bitmap_init();
- client->redist_default[afi] = vrf_bitmap_init();
- client->ridinfo[afi] = vrf_bitmap_init();
- client->nhrp_neighinfo[afi] = vrf_bitmap_init();
+ vrf_bitmap_init(&client->redist[afi][i]);
+ vrf_bitmap_init(&client->redist_default[afi]);
+ vrf_bitmap_init(&client->ridinfo[afi]);
+ vrf_bitmap_init(&client->neighinfo[afi]);
}
/* Add this client to linked list. */
@@ -1058,6 +1096,8 @@ static void zebra_show_client_detail(struct vty *vty, struct zserv *client)
0, client->redist_v4_del_cnt);
vty_out(vty, "Redist:v6 %-12u%-12u%-12u\n", client->redist_v6_add_cnt,
0, client->redist_v6_del_cnt);
+ vty_out(vty, "NHG %-12u%-12u%-12u\n", client->nhg_add_cnt,
+ client->nhg_upd8_cnt, client->nhg_del_cnt);
vty_out(vty, "VRF %-12u%-12u%-12u\n", client->vrfadd_cnt, 0,
client->vrfdel_cnt);
vty_out(vty, "Connected %-12u%-12u%-12u\n", client->ifadd_cnt, 0,
@@ -1085,12 +1125,10 @@ static void zebra_show_client_detail(struct vty *vty, struct zserv *client)
vty_out(vty, "ES-EVI %-12u%-12u%-12u\n",
client->local_es_evi_add_cnt, 0, client->local_es_evi_del_cnt);
vty_out(vty, "Errors: %u\n", client->error_cnt);
-
-#if defined DEV_BUILD
vty_out(vty, "Input Fifo: %zu:%zu Output Fifo: %zu:%zu\n",
client->ibuf_fifo->count, client->ibuf_fifo->max_count,
client->obuf_fifo->count, client->obuf_fifo->max_count);
-#endif
+
vty_out(vty, "\n");
}
diff --git a/zebra/zserv.h b/zebra/zserv.h
index 90aa4d53f4..57d673060f 100644
--- a/zebra/zserv.h
+++ b/zebra/zserv.h
@@ -31,9 +31,6 @@ extern "C" {
struct zebra_vrf;
-/* Default port information. */
-#define ZEBRA_VTY_PORT 2601
-
/* Default configuration filename. */
#define DEFAULT_CONFIG_FILE "zebra.conf"
@@ -121,7 +118,7 @@ struct zserv {
vrf_bitmap_t ridinfo[AFI_MAX];
/* Router-id information. */
- vrf_bitmap_t nhrp_neighinfo[AFI_MAX];
+ vrf_bitmap_t neighinfo[AFI_MAX];
bool notify_owner;
@@ -185,6 +182,9 @@ struct zserv {
uint32_t local_es_evi_add_cnt;
uint32_t local_es_evi_del_cnt;
uint32_t error_cnt;
+ uint32_t nhg_add_cnt;
+ uint32_t nhg_upd8_cnt;
+ uint32_t nhg_del_cnt;
time_t nh_reg_time;
time_t nh_dereg_time;
@@ -237,8 +237,7 @@ DECLARE_HOOK(zserv_client_connect, (struct zserv *client), (client));
DECLARE_KOOH(zserv_client_close, (struct zserv *client), (client));
#define DYNAMIC_CLIENT_GR_DISABLED(_client) \
- ((_client->proto <= ZEBRA_ROUTE_CONNECT) \
- || !(_client->gr_instance_count))
+ ((_client->proto <= ZEBRA_ROUTE_LOCAL) || !(_client->gr_instance_count))
/*
* Initialize Zebra API server.
@@ -379,6 +378,7 @@ __attribute__((__noreturn__)) void zebra_finalize(struct event *event);
/*
* Graceful restart functions.
*/
+extern void zebra_gr_client_final_shutdown(struct zserv *client);
extern int zebra_gr_client_disconnect(struct zserv *client);
extern void zebra_gr_client_reconnect(struct zserv *client);
extern void zebra_gr_stale_client_cleanup(struct list *client_list);