summaryrefslogtreecommitdiffstats
path: root/zebra
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 04:24:31 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 04:24:31 +0000
commitacb594b1d825c6e12369cebb941968ec08c840ce (patch)
treed544788908e7353a4f117e2991f15f4236a0c963 /zebra
parentAdding upstream version 9.1. (diff)
downloadfrr-acb594b1d825c6e12369cebb941968ec08c840ce.tar.xz
frr-acb594b1d825c6e12369cebb941968ec08c840ce.zip
Adding upstream version 10.0.upstream/10.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--zebra/connected.c87
-rw-r--r--zebra/debug.c4
-rw-r--r--zebra/debug_nl.c1
-rw-r--r--zebra/dplane_fpm_nl.c44
-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.c83
-rw-r--r--zebra/if_sysctl.c2
-rw-r--r--zebra/interface.c2004
-rw-r--r--zebra/interface.h26
-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.c171
-rw-r--r--zebra/kernel_netlink.h3
-rw-r--r--zebra/kernel_socket.c17
-rw-r--r--zebra/label_manager.c191
-rw-r--r--zebra/label_manager.h15
-rw-r--r--zebra/main.c50
-rw-r--r--zebra/netconf_netlink.c3
-rw-r--r--zebra/redistribute.c92
-rw-r--r--zebra/rib.h36
-rw-r--r--zebra/router-id.c270
-rw-r--r--zebra/router-id.h2
-rw-r--r--zebra/rt.h3
-rw-r--r--zebra/rt_netlink.c116
-rw-r--r--zebra/rt_socket.c2
-rw-r--r--zebra/rtadv.c1283
-rw-r--r--zebra/rtadv.h25
-rw-r--r--zebra/rtread_sysctl.c2
-rw-r--r--zebra/rule_netlink.c3
-rw-r--r--zebra/subdir.am6
-rw-r--r--zebra/table_manager.c64
-rw-r--r--zebra/table_manager.h20
-rw-r--r--zebra/tc_netlink.c1
-rw-r--r--zebra/zapi_msg.c151
-rw-r--r--zebra/zapi_msg.h9
-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.c159
-rw-r--r--zebra/zebra_dplane.h15
-rw-r--r--zebra/zebra_evpn.c9
-rw-r--r--zebra/zebra_evpn_mh.c359
-rw-r--r--zebra/zebra_evpn_mh.h19
-rw-r--r--zebra/zebra_evpn_neigh.c4
-rw-r--r--zebra/zebra_fpm.c4
-rw-r--r--zebra/zebra_fpm_dt.c4
-rw-r--r--zebra/zebra_fpm_netlink.c3
-rw-r--r--zebra/zebra_gr.c2
-rw-r--r--zebra/zebra_mlag.c35
-rw-r--r--zebra/zebra_mpls.c99
-rw-r--r--zebra/zebra_mpls.h3
-rw-r--r--zebra/zebra_mpls_netlink.c4
-rw-r--r--zebra/zebra_mpls_openbsd.c134
-rw-r--r--zebra/zebra_mpls_vty.c3
-rw-r--r--zebra/zebra_nb.c489
-rw-r--r--zebra/zebra_nb.h211
-rw-r--r--zebra/zebra_nb_config.c2783
-rw-r--r--zebra/zebra_nb_state.c48
-rw-r--r--zebra/zebra_netns_id.c6
-rw-r--r--zebra/zebra_netns_notify.c1
-rw-r--r--zebra/zebra_nhg.c199
-rw-r--r--zebra/zebra_nhg.h2
-rw-r--r--zebra/zebra_ns.c16
-rw-r--r--zebra/zebra_ns.h5
-rw-r--r--zebra/zebra_pbr.c4
-rw-r--r--zebra/zebra_pbr.h2
-rw-r--r--zebra/zebra_ptm.c74
-rw-r--r--zebra/zebra_ptm.h9
-rw-r--r--zebra/zebra_pw.c18
-rw-r--r--zebra/zebra_pw.h7
-rw-r--r--zebra/zebra_rib.c264
-rw-r--r--zebra/zebra_rnh.c10
-rw-r--r--zebra/zebra_routemap.c668
-rw-r--r--zebra/zebra_routemap.h12
-rw-r--r--zebra/zebra_router.c30
-rw-r--r--zebra/zebra_router.h7
-rw-r--r--zebra/zebra_script.c2
-rw-r--r--zebra/zebra_snmp.c2
-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_vrf.c153
-rw-r--r--zebra/zebra_vty.c386
-rw-r--r--zebra/zebra_vxlan.c227
-rw-r--r--zebra/zebra_vxlan.h6
-rw-r--r--zebra/zserv.c6
-rw-r--r--zebra/zserv.h11
92 files changed, 8776 insertions, 6241 deletions
diff --git a/zebra/connected.c b/zebra/connected.c
index ee0823f..404f892 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 68bedaf..cf1701b 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 df0b5aa..a7cccdb 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/dplane_fpm_nl.c b/zebra/dplane_fpm_nl.c
index 2a87925..7ae1b2a 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"
@@ -42,7 +45,12 @@
#include "fpm/fpm.h"
#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:
@@ -90,6 +98,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;
@@ -207,7 +216,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 */
@@ -225,7 +234,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 */
@@ -392,7 +401,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");
@@ -401,7 +410,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");
@@ -859,7 +868,7 @@ 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],
@@ -969,6 +978,7 @@ 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;
@@ -1364,6 +1374,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);
@@ -1408,9 +1430,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
@@ -1614,7 +1640,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 */
diff --git a/zebra/ge_netlink.c b/zebra/ge_netlink.c
new file mode 100644
index 0000000..e7d2e6b
--- /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 0000000..20d0911
--- /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 b3cf865..d0aa216 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 ed2e0a2..5f096e3 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>
@@ -215,6 +217,8 @@ 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, "team") == 0)
+ *zif_type = ZEBRA_IF_BOND;
else if (strcmp(kind, "gre") == 0)
*zif_type = ZEBRA_IF_GRE;
}
@@ -257,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;
@@ -281,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 */
@@ -295,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)
@@ -998,68 +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:
- case DPLANE_OP_STARTUP_STAGE:
+ else {
flog_err(
EC_ZEBRA_NHG_FIB_UPDATE,
"Context received for kernel interface update with incorrect OP code (%u)",
@@ -1474,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]);
diff --git a/zebra/if_sysctl.c b/zebra/if_sysctl.c
index ae29268..9db9598 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 1afd9d5..5ce222c 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;
@@ -136,7 +133,7 @@ static int if_zebra_new_hook(struct interface *ifp)
zebra_if->multicast = IF_ZEBRA_DATA_UNSPEC;
zebra_if->mpls_config = IF_ZEBRA_DATA_UNSPEC;
- zebra_if->shutdown = IF_ZEBRA_DATA_OFF;
+ zebra_if->shutdown = IF_ZEBRA_DATA_UNSPEC;
zebra_if->link_nsid = NS_UNKNOWN;
@@ -148,6 +145,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. */
@@ -171,18 +170,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)
@@ -192,7 +186,7 @@ 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);
}
}
@@ -489,12 +483,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)
@@ -637,32 +630,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);
}
}
@@ -670,20 +655,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);
@@ -732,11 +712,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. */
@@ -751,14 +735,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;
}
}
}
@@ -1068,6 +1048,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
@@ -1331,6 +1313,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);
@@ -1800,6 +1785,9 @@ interface_bridge_vxlan_vlan_vni_map_update(struct zebra_dplane_ctx *ctx,
vlanid_t vid;
int i;
+ if (vniarray == NULL)
+ return;
+
memset(&vni_start, 0, sizeof(vni_start));
memset(&vni_end, 0, sizeof(vni_end));
@@ -2295,15 +2283,10 @@ void zebra_if_dplane_result(struct zebra_dplane_ctx *ctx)
ifp = if_lookup_by_index_per_ns(zns, ifindex);
- 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:
+ } 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
@@ -2313,62 +2296,8 @@ void zebra_if_dplane_result(struct zebra_dplane_ctx *ctx)
zebra_if_dplane_ifp_handling(ctx);
else
zebra_if_update_ctx(ctx, ifp);
- break;
-
- case DPLANE_OP_INTF_NETCONFIG:
+ } 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:
- case DPLANE_OP_STARTUP_STAGE:
- break; /* should never hit here */
}
}
@@ -2408,6 +2337,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));
@@ -2556,34 +2491,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)
@@ -2595,7 +2523,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) {
@@ -2611,13 +2538,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(
@@ -2824,9 +2746,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);
}
@@ -2958,8 +2879,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);
@@ -3201,9 +3122,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);
}
@@ -3360,7 +3280,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);
@@ -3744,63 +3665,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$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);
+ return 0;
}
int if_multicast_unset(struct interface *ifp)
@@ -3821,30 +3722,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;
@@ -3868,30 +3745,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;
@@ -3911,31 +3764,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;
@@ -3960,984 +3788,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. */
@@ -4945,7 +3845,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. */
@@ -4962,13 +3862,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
@@ -4976,407 +3870,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. */
- }
+ ifc = connected_check_ptp(ifp, prefix, pp);
+ assert(ifc);
- 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);
- }
-
- 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;
-}
+ dplane_intf_addr_unset(ifp, ifc);
-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;
- }
-
- /* 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)
-{
- 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)
+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;
- 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. */
@@ -5393,265 +3930,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_config == IF_ZEBRA_DATA_ON)
- vty_out(vty, " mpls enable\n");
- else if (if_data->mpls_config ==
- IF_ZEBRA_DATA_OFF)
- vty_out(vty, " mpls disable\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. */
@@ -5661,15 +3969,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);
@@ -5677,55 +3976,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 3b67995..7d633f3 100644
--- a/zebra/interface.h
+++ b/zebra/interface.h
@@ -201,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;
@@ -218,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)
@@ -283,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);
@@ -308,18 +308,28 @@ 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);
diff --git a/zebra/ioctl.c b/zebra/ioctl.c
index 8da1ae3..a35784c 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 253e6a8..70f3f57 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 6548790..349ae1a 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 7c934ed..8a64a1e 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));
@@ -1219,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.
*/
@@ -1612,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;
@@ -1748,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);
@@ -1760,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);
@@ -1773,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);
@@ -1787,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);
@@ -1795,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
@@ -1833,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
@@ -1865,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
@@ -1889,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 */
@@ -1913,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 e910f62..e37bba0 100644
--- a/zebra/kernel_netlink.h
+++ b/zebra/kernel_netlink.h
@@ -98,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 d897f4a..d50e7de 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;
@@ -1626,6 +1624,7 @@ void kernel_update_multi(struct dplane_ctx_list_head *ctx_list)
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 fa7dbb0..c97beb6 100644
--- a/zebra/label_manager.c
+++ b/zebra/label_manager.c
@@ -51,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)
{
@@ -71,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);
@@ -80,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)
{
@@ -138,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)
{
@@ -145,24 +158,129 @@ 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",
+DEFPY(show_label_table, show_label_table_cmd, "show debugging label-table [json$uj]",
SHOW_STR
DEBUG_STR
- "Display allocated label chunks\n")
+ "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;
+}
+
/**
* Init label manager (or proxy to an external one)
*/
@@ -170,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 */
@@ -179,12 +299,18 @@ void label_manager_init(void)
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 =
@@ -196,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;
}
@@ -223,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)) {
@@ -254,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;
}
@@ -277,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
@@ -288,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;
}
@@ -313,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);
@@ -325,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);
@@ -364,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;
}
diff --git a/zebra/label_manager.h b/zebra/label_manager.h
index 74f40fa..03cf6a6 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,6 +77,7 @@ 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,
@@ -82,7 +87,7 @@ int lm_client_connect_response(uint8_t proto, uint16_t instance,
/* 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 */
@@ -95,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 1e833ce..27e05e7 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
@@ -140,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);
@@ -195,6 +204,12 @@ static void sigint(void)
list_delete(&zrouter.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
* with the 'finalize' function.
@@ -226,8 +241,17 @@ void zebra_finalize(struct event *dummy)
/* 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);
@@ -271,19 +295,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)
@@ -385,7 +413,7 @@ int main(int argc, char **argv)
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"))
@@ -408,7 +436,7 @@ int main(int argc, char **argv)
/* Zebra related initialize. */
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();
@@ -418,8 +446,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 7352dfb..002d2c7 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 7559e31..70ace35 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"
@@ -78,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);
@@ -89,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;
@@ -126,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.
*/
@@ -147,8 +174,19 @@ 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) &&
@@ -186,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(
@@ -211,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);
+ }
}
}
@@ -234,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;
@@ -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,8 +383,7 @@ 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],
@@ -340,7 +395,7 @@ void zebra_redistribute_add(ZAPI_HANDLER_ARGS)
zvrf_id(zvrf));
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);
}
}
@@ -663,9 +718,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;
}
diff --git a/zebra/rib.h b/zebra/rib.h
index e70b5c1..a721f4b 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,7 +147,20 @@ 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)
@@ -169,7 +169,7 @@ struct route_entry {
/* Define route types that are equivalent to "connected". */
#define RIB_CONNECTED_ROUTE(R) \
- ((R)->type == ZEBRA_ROUTE_CONNECT || (R)->type == ZEBRA_ROUTE_NHRP)
+ ((R)->type == ZEBRA_ROUTE_CONNECT || (R)->type == ZEBRA_ROUTE_LOCAL || (R)->type == ZEBRA_ROUTE_NHRP)
/* meta-queue structure:
* sub-queue 0: nexthop group objects
@@ -345,6 +345,8 @@ 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,
@@ -414,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,
@@ -429,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,
@@ -627,8 +631,6 @@ 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 */
diff --git a/zebra/router-id.c b/zebra/router-id.c
index ef87d92..2f251a7 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 45860d8..09ad4ec 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 af170a2..e5dc261 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
/*
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index b8362bb..f092fc5 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -278,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;
@@ -366,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
@@ -1025,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
@@ -2208,7 +2212,8 @@ ssize_t netlink_route_multipath_msg_encode(int cmd, struct zebra_dplane_ctx *ctx
req->n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
if (((cmd == RTM_NEWROUTE) &&
- ((p->family == AF_INET) || v6_rr_semantics)) ||
+ ((p->family == AF_INET) || kernel_nexthops_supported() ||
+ zrouter.v6_rr_semantics)) ||
force_rr)
req->n.nlmsg_flags |= NLM_F_REPLACE;
@@ -2622,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",
@@ -3087,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 */
/*
@@ -4237,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);
@@ -4251,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;
@@ -4717,77 +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:
- case DPLANE_OP_STARTUP_STAGE:
+ else
ret = -1;
- }
return ret;
}
diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c
index f9888b1..0bfcd51 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 9af41cb..6aca643 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;
};
@@ -187,8 +189,9 @@ static void rtadv_send_packet(int sock, struct interface *ifp,
struct cmsghdr *cmsgptr;
struct in6_pktinfo *pkt;
struct sockaddr_in6 addr;
- static void *adata = NULL;
unsigned char buf[RTADV_MSG_SIZE];
+ char adata[RTADV_ADATA_SIZE];
+
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 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 *rtadv_dnssl_set(struct zebra_if *zif,
+ 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 1ec376a..0983ea5 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 ef1e21b..8e2d13f 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 f00aef5..0528279 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"
diff --git a/zebra/subdir.am b/zebra/subdir.am
index b3bd9be..d9c8d90 100644
--- a/zebra/subdir.am
+++ b/zebra/subdir.am
@@ -28,7 +28,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 +52,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 \
@@ -117,7 +118,6 @@ clippy_scan += \
zebra/debug.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 \
@@ -125,6 +125,7 @@ clippy_scan += \
zebra/zebra_vrf.c \
zebra/dpdk/zebra_dplane_dpdk_vty.c \
zebra/label_manager.c \
+ zebra/zebra_cli.c \
# end
noinst_HEADERS += \
@@ -144,6 +145,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 512508b..8417a22 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
@@ -279,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 f8e99a3..2169199 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 d633c07..19667e6 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>
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index 6754238..76cabd1 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -24,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"
@@ -63,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);
@@ -414,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;
@@ -510,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;
@@ -526,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);
@@ -593,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) {
@@ -834,7 +842,7 @@ void zsend_rule_notify_owner(const struct zebra_dplane_ctx *ctx,
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));
@@ -960,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;
@@ -979,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);
}
@@ -1028,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);
@@ -1679,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));
@@ -1697,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
@@ -1912,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)
@@ -1934,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) {
@@ -1992,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)
@@ -2329,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),
@@ -2381,7 +2431,7 @@ static void zread_vrf_unregister(ZAPI_HANDLER_ARGS)
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->neighinfo[afi], zvrf_id(zvrf));
}
}
@@ -2961,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;
@@ -2977,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);
@@ -3074,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;
@@ -3513,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;
}
@@ -3529,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;
}
@@ -3855,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,
@@ -3886,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,
diff --git a/zebra/zapi_msg.h b/zebra/zapi_msg.h
index a01cbf6..43f734d 100644
--- a/zebra/zapi_msg.h
+++ b/zebra/zapi_msg.h
@@ -53,7 +53,8 @@ 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);
@@ -90,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 ae0f9a8..79bc78a 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 0000000..00e0a49
--- /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 0000000..01931a4
--- /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 0b40631..99693a5 100644
--- a/zebra/zebra_dplane.c
+++ b/zebra/zebra_dplane.c
@@ -230,6 +230,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;
@@ -356,6 +357,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).
@@ -391,7 +399,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 */
@@ -417,6 +425,7 @@ struct zebra_dplane_ctx {
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 */
@@ -598,6 +607,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;
@@ -860,6 +872,7 @@ static void dplane_ctx_free_internal(struct zebra_dplane_ctx *ctx)
case DPLANE_OP_GRE_SET:
case DPLANE_OP_INTF_NETCONFIG:
case DPLANE_OP_STARTUP_STAGE:
+ case DPLANE_OP_SRV6_ENCAP_SRCADDR_SET:
break;
}
}
@@ -1185,6 +1198,11 @@ const char *dplane_op2str(enum dplane_op_e op)
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;
@@ -2541,6 +2559,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);
@@ -2569,6 +2594,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);
@@ -2584,6 +2616,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)
{
@@ -5858,6 +5900,59 @@ done:
}
/*
+ * 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)
@@ -6582,6 +6677,12 @@ static void kernel_dplane_log_detail(struct zebra_dplane_ctx *ctx)
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;
}
}
@@ -6752,6 +6853,13 @@ 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)
@@ -6860,6 +6968,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
/*
@@ -6932,12 +7065,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",
@@ -7338,6 +7469,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");
@@ -7365,8 +7497,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();
}
/*
diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h
index 87c2e03..2f7d218 100644
--- a/zebra/zebra_dplane.h
+++ b/zebra/zebra_dplane.h
@@ -18,6 +18,7 @@
#include "zebra/zserv.h"
#include "zebra/zebra_mpls.h"
#include "zebra/zebra_nhg.h"
+#include "zebra/ge_netlink.h"
#ifdef __cplusplus
extern "C" {
@@ -198,6 +199,9 @@ enum dplane_op_e {
/* Startup Control */
DPLANE_OP_STARTUP_STAGE,
+
+ /* Source address for SRv6 encapsulation */
+ DPLANE_OP_SRV6_ENCAP_SRCADDR_SET,
};
/*
@@ -658,10 +662,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);
@@ -990,6 +998,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;
diff --git a/zebra/zebra_evpn.c b/zebra/zebra_evpn.c
index ce5e639..147f5b9 100644
--- a/zebra/zebra_evpn.c
+++ b/zebra/zebra_evpn.c
@@ -310,13 +310,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 +343,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))
@@ -409,13 +407,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));
diff --git a/zebra/zebra_evpn_mh.c b/zebra/zebra_evpn_mh.c
index a5092c6..35d5027 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);
@@ -1139,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
@@ -2250,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;
@@ -2402,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)
@@ -2673,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;
-
- rv = zebra_evpn_type3_esi_update(zif, lid, &zif->es_info.sysmac);
- if (!rv)
- zif->es_info.lid = lid;
+ 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)
@@ -2726,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;
@@ -2740,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 */
@@ -2833,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);
@@ -3326,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)
+void zebra_evpn_mh_if_init(struct zebra_if *zif)
{
- 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")
-{
- 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)
@@ -3864,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;
@@ -4087,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 59a41d0..34ef79f 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,8 +335,6 @@ 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,
@@ -382,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 a00d8c9..81705d4 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"
diff --git a/zebra/zebra_fpm.c b/zebra/zebra_fpm.c
index 699f3ed..92dc591 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"
diff --git a/zebra/zebra_fpm_dt.c b/zebra/zebra_fpm_dt.c
index 94308a9..ce5eb6f 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 1279762..1dd9634 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"
diff --git a/zebra/zebra_gr.c b/zebra/zebra_gr.c
index 39fd864..f4241f1 100644
--- a/zebra/zebra_gr.c
+++ b/zebra/zebra_gr.c
@@ -327,7 +327,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_mlag.c b/zebra/zebra_mlag.c
index 7715eab..8fd373c 100644
--- a/zebra/zebra_mlag.c
+++ b/zebra/zebra_mlag.c
@@ -627,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;
}
@@ -983,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);
@@ -1032,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: {
@@ -1059,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: {
@@ -1083,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);
@@ -1103,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);
@@ -1134,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;
@@ -1150,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 eac4fcc..15e36ac 100644
--- a/zebra/zebra_mpls.c
+++ b/zebra/zebra_mpls.c
@@ -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;
}
@@ -1182,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;
}
@@ -1769,9 +1772,7 @@ 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);
lsp_table = zvrf->lsp_table;
@@ -1782,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' */
@@ -1793,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 */
@@ -1814,74 +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:
- case DPLANE_OP_STARTUP_STAGE:
- break;
-
- } /* Switch */
+ }
}
/*
@@ -4093,10 +4036,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);
+ }
}
/*
@@ -4115,3 +4060,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 7feace5..1ed2f9b 100644
--- a/zebra/zebra_mpls.h
+++ b/zebra/zebra_mpls.h
@@ -400,9 +400,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 4bc676f..f0f2c4b 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 5015f2e..9cbe6a2 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
@@ -229,71 +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:
- case DPLANE_OP_STARTUP_STAGE:
+ else
return -1;
- }
head = dplane_ctx_get_nhlfe_list(ctx);
frr_each(nhlfe_list_const, head, nhlfe) {
@@ -443,69 +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:
- case DPLANE_OP_STARTUP_STAGE:
- break;
- }
return result;
}
diff --git a/zebra/zebra_mpls_vty.c b/zebra/zebra_mpls_vty.c
index e64e700..fd09e6b 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,
@@ -270,6 +271,8 @@ static int zebra_mpls_config(struct vty *vty)
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;
}
diff --git a/zebra/zebra_nb.c b/zebra/zebra_nb.c
index a93dbbb..e1ca5ec 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_ipv4_addrs_create,
+ .destroy = lib_interface_zebra_ipv4_addrs_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv4-addrs/label",
+ .cbs = {
+ .modify = lib_interface_zebra_ipv4_addrs_label_modify,
+ .destroy = lib_interface_zebra_ipv4_addrs_label_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv4-p2p-addrs",
.cbs = {
- .create = lib_interface_zebra_ip_addrs_create,
- .destroy = lib_interface_zebra_ip_addrs_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/ip-addrs/label",
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv4-p2p-addrs/label",
.cbs = {
- .modify = lib_interface_zebra_ip_addrs_label_modify,
- .destroy = lib_interface_zebra_ip_addrs_label_destroy,
+ .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/ip-addrs/ip4-peer",
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/ipv6-addrs",
.cbs = {
- .modify = lib_interface_zebra_ip_addrs_ip4_peer_modify,
- .destroy = lib_interface_zebra_ip_addrs_ip4_peer_destroy,
+ .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,
}
},
{
@@ -346,10 +384,66 @@ 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/link-params",
.cbs = {
- .modify = lib_interface_zebra_bandwidth_modify,
- .destroy = lib_interface_zebra_bandwidth_destroy,
+ .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,
}
},
{
@@ -357,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,
},
},
{
@@ -377,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,
@@ -429,11 +803,87 @@ const struct frr_yang_module_info frr_zebra_info = {
}
},
{
+ .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,
}
},
{
@@ -454,6 +904,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,
}
},
{
diff --git a/zebra/zebra_nb.h b/zebra/zebra_nb.h
index 80d2aaa..d7cf5f4 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,31 +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_mpls_modify(struct nb_cb_modify_args *args);
int lib_interface_zebra_mpls_destroy(struct nb_cb_destroy_args *args);
-int lib_interface_zebra_legacy_admin_group_modify(
+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 *
@@ -121,10 +285,35 @@ 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);
+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 *
@@ -134,6 +323,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(
diff --git a/zebra/zebra_nb_config.c b/zebra/zebra_nb_config.c
index 5ea0311..5cb9985 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;
+}
- /* 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);
+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;
+ }
+
+ 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,23 +1184,7 @@ 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");
-
- if_linkdetect(ifp, link_detect);
-
- return NB_OK;
-}
-
-int lib_interface_zebra_link_detect_destroy(struct nb_cb_destroy_args *args)
-{
- if (args->event != NB_EV_APPLY)
- return NB_OK;
-
- struct interface *ifp;
- 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);
@@ -1057,32 +1192,39 @@ int lib_interface_zebra_link_detect_destroy(struct nb_cb_destroy_args *args)
}
/*
- * XPath: /frr-interface:lib/interface/frr-zebra:zebra/shutdown
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/enabled
*/
-int lib_interface_zebra_shutdown_modify(struct nb_cb_modify_args *args)
+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 enabled;
ifp = nb_running_get_entry(args->dnode, NULL, true);
+ enabled = yang_dnode_get_bool(args->dnode, NULL);
- if_shutdown(ifp);
+ if (enabled)
+ if_no_shutdown(ifp);
+ else
+ if_shutdown(ifp);
return NB_OK;
}
-int lib_interface_zebra_shutdown_destroy(struct nb_cb_destroy_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_no_shutdown(ifp);
+ zif->shutdown = IF_ZEBRA_DATA_UNSPEC;
return NB_OK;
}
@@ -1143,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;
@@ -1173,58 +1315,425 @@ 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 (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 (!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, 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;
+}
+
+int lib_interface_zebra_link_params_residual_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_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;
- admin_group_clear(&iflp->ext_admin_grp);
- UNSET_PARAM(iflp, LP_EXTEND_ADM_GRP);
+ ava_bw = yang_dnode_get_bandwidth_ieee_float32(args->dnode, NULL);
- if (if_is_operative(ifp))
- zebra_interface_parameters_update(ifp);
+ 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:
@@ -1232,14 +1741,33 @@ 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 = 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:
+ 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 = 0;
UNSET_PARAM(iflp, LP_ADM_GRP);
-
- if (if_is_operative(ifp))
- zebra_interface_parameters_update(ifp);
break;
}
return NB_OK;
@@ -1247,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)
@@ -1257,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 ||
@@ -1303,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;
@@ -1319,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)) {
@@ -1357,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;
@@ -1375,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)) {
@@ -1433,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 (if_is_operative(ifp))
- zebra_interface_parameters_update(ifp);
+ 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;
+}
+
+/*
+ * 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;
}
@@ -1520,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:
@@ -1532,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 ba53747..00df9bf 100644
--- a/zebra/zebra_nb_state.c
+++ b/zebra/zebra_nb_state.c
@@ -156,6 +156,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 +169,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 +201,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 +213,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 +312,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
*/
diff --git a/zebra/zebra_netns_id.c b/zebra/zebra_netns_id.c
index 0531ab9..1af3a3e 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 4260d29..1bb1292 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 1879baf..dc403b8 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;
@@ -690,12 +678,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 +685,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)
@@ -1082,11 +1067,10 @@ 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
@@ -1310,6 +1294,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;
}
@@ -1525,19 +1510,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;
}
@@ -2128,7 +2117,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))
@@ -2247,20 +2237,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;
@@ -2363,7 +2339,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. */
@@ -2390,20 +2366,12 @@ static int nexthop_active(struct nexthop *nexthop, struct nhg_hash_entry *nhe,
/* 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 the candidate match's type is considered "connected",
* we consider it first.
*/
- if (RIB_CONNECTED_ROUTE(match) ||
- (RIB_SYSTEM_ROUTE(match) && RSYSTEM_ROUTE(type))) {
+ if (match && (RIB_CONNECTED_ROUTE(match) ||
+ (RIB_SYSTEM_ROUTE(match) && RSYSTEM_ROUTE(type)))) {
match = zebra_nhg_connected_ifindex(rn, match,
nexthop->ifindex);
@@ -2419,11 +2387,7 @@ static int nexthop_active(struct nexthop *nexthop, struct nhg_hash_entry *nhe,
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 */
@@ -2436,7 +2400,7 @@ static int nexthop_active(struct nexthop *nexthop, struct nhg_hash_entry *nhe,
__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 = {};
@@ -2472,6 +2436,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;
}
@@ -2540,25 +2508,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__);
@@ -3182,8 +3162,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,
@@ -3191,18 +3170,15 @@ 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);
@@ -3230,61 +3206,6 @@ void zebra_nhg_dplane_result(struct zebra_dplane_ctx *ctx)
"Failed to install Nexthop (%pNG) into the kernel",
nhe);
}
- 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:
- case DPLANE_OP_STARTUP_STAGE:
- break;
}
}
diff --git a/zebra/zebra_nhg.h b/zebra/zebra_nhg.h
index 6179be3..4eddecb 100644
--- a/zebra/zebra_nhg.h
+++ b/zebra/zebra_nhg.h
@@ -143,7 +143,7 @@ struct nhg_hash_entry {
/*
* Track FPM installation status..
*/
-#define NEXTHOP_GROUP_FPM (1 << 6)
+#define NEXTHOP_GROUP_FPM (1 << 7)
};
/* Upper 4 bits of the NHG are reserved for indicating the NHG type */
diff --git a/zebra/zebra_ns.c b/zebra/zebra_ns.c
index ffdb9df..803d8f0 100644
--- a/zebra/zebra_ns.c
+++ b/zebra/zebra_ns.c
@@ -42,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;
@@ -57,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;
@@ -194,6 +189,8 @@ int zebra_ns_final_shutdown(struct ns *ns,
kernel_terminate(zns, true);
+ zebra_ns_delete(ns);
+
return NS_WALK_CONTINUE;
}
@@ -241,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 edf2611..8d988c3 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,6 @@ 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);
diff --git a/zebra/zebra_pbr.c b/zebra/zebra_pbr.c
index c04c5f5..7f36357 100644
--- a/zebra/zebra_pbr.c
+++ b/zebra/zebra_pbr.c
@@ -234,7 +234,7 @@ 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;
};
@@ -259,7 +259,7 @@ 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;
diff --git a/zebra/zebra_pbr.h b/zebra/zebra_pbr.h
index ddc1460..1e4b5cd 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;
diff --git a/zebra/zebra_ptm.c b/zebra/zebra_ptm.c
index a678e71..d7d752f 100644
--- a/zebra/zebra_ptm.c
+++ b/zebra/zebra_ptm.c
@@ -86,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);
@@ -115,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,
@@ -240,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;
@@ -266,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;
@@ -295,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;
@@ -312,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))
@@ -341,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)
@@ -394,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,
@@ -678,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];
@@ -841,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];
@@ -1165,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 */
/*
@@ -1533,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 4d09474..20a53e2 100644
--- a/zebra/zebra_ptm.h
+++ b/zebra/zebra_ptm.h
@@ -58,9 +58,15 @@ struct zebra_ptm_cb {
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 f76bf74..deed3b6 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",
@@ -837,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 fd94d5e..431d663 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 6538b5e..5b95d86 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 "
: "",
@@ -521,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;
@@ -623,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))
@@ -1122,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? */
@@ -1171,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 */
@@ -1200,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;
@@ -1269,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;
@@ -1354,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
@@ -1408,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);
@@ -1506,7 +1560,8 @@ static bool rib_route_match_ctx(const struct route_entry *re,
} 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));
}
@@ -1564,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;
@@ -2014,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);
@@ -2107,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);
@@ -2147,61 +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:
- case DPLANE_OP_STARTUP_STAGE:
- break;
}
zebra_rib_evaluate_rn_nexthops(rn, seq, rt_delete);
@@ -2535,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;
@@ -2567,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);
@@ -2678,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);
}
@@ -2859,11 +2875,10 @@ 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) {
- rib_dest_t *dest = rn->info;
-
- if (same == dest->selected_fib)
+ if (dest && same == dest->selected_fib)
SET_FLAG(same->status, ROUTE_ENTRY_ROUTE_REPLACING);
rib_delnode(rn, same);
}
@@ -2871,7 +2886,6 @@ static void process_subq_early_route_add(struct zebra_early_route *ere)
/* 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. */
@@ -2967,7 +2981,8 @@ 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 &&
+ 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)
@@ -3342,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;
@@ -3357,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++;
@@ -3368,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);
@@ -3476,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,
@@ -4083,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;
@@ -4267,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
@@ -4917,6 +4960,7 @@ 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:
@@ -4979,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();
@@ -4991,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
*
@@ -5044,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 aeb7ae3..b387e99 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) {
diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c
index 21aaf1d..95da789 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"
@@ -36,8 +36,6 @@ struct zebra_rmap_obj {
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
*/
@@ -284,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;
@@ -317,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;
@@ -346,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)) {
@@ -368,8 +365,7 @@ static int ip_nht_rm_add(struct zebra_vrf *zvrf, const char *rmap, int rtype,
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))
@@ -391,351 +387,7 @@ static int ip_nht_rm_del(struct zebra_vrf *zvrf, const char *rmap, int 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
@@ -748,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
@@ -829,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
@@ -917,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
@@ -1736,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) {
@@ -1903,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);
@@ -2038,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 fceb53c..2039e80 100644
--- a/zebra/zebra_routemap.h
+++ b/zebra/zebra_routemap.h
@@ -14,8 +14,6 @@ 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);
@@ -35,6 +33,16 @@ extern route_map_result_t zebra_nht_route_map_check(afi_t afi, int client_proto,
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);
#ifdef __cplusplus
diff --git a/zebra/zebra_router.c b/zebra/zebra_router.c
index 4caaf8a..3fd4e6e 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();
}
@@ -295,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");
@@ -323,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 bd86cfb..3041707 100644
--- a/zebra/zebra_router.h
+++ b/zebra/zebra_router.h
@@ -209,6 +209,8 @@ struct zebra_router {
bool notify_on_ack;
bool v6_with_v4_nexthop;
+ bool v6_rr_semantics;
+
/*
* If the asic is notifying us about successful nexthop
* allocation/control. Some developers have made their
@@ -231,6 +233,8 @@ struct zebra_router {
bool allow_delete;
uint8_t protodown_r_bit;
+
+ uint64_t nexthop_weight_scale_value;
};
#define GRACEFUL_RESTART_TIME 60
@@ -246,6 +250,9 @@ 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);
diff --git a/zebra/zebra_script.c b/zebra/zebra_script.c
index 9f8490a..6c34d12 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,6 +415,7 @@ 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;
diff --git a/zebra/zebra_snmp.c b/zebra/zebra_snmp.c
index 8cab184..1c6d581 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:
diff --git a/zebra/zebra_srv6.c b/zebra/zebra_srv6.c
index 94b93e5..bb872ef 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 51db83d..21936c3 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 3775d3d..c5b8505 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 3d7e03b..1b5a57a 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 335430c..814b453 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_vrf.c b/zebra/zebra_vrf.c
index 25e6513..e464e47 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,7 +376,7 @@ struct zebra_vrf *zebra_vrf_alloc(struct vrf *vrf)
zebra_vxlan_init_tables(zvrf);
zebra_mpls_init_tables(zvrf);
- zebra_pw_init(zvrf);
+ zebra_pw_init_vrf(zvrf);
zvrf->table_id = rt_table_main_id;
/* by default table ID is default one */
@@ -444,141 +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 !=
- SAVE_ZEBRA_IP_NHT_RESOLVE_VIA_DEFAULT)
- vty_out(vty, "%sip nht resolve-via-default\n",
- zvrf->zebra_rnh_ip_default_route
- ? ""
- : "no ");
-
- if (zvrf->zebra_rnh_ipv6_default_route !=
- SAVE_ZEBRA_IP_NHT_RESOLVE_VIA_DEFAULT)
- vty_out(vty, "%sipv6 nht resolve-via-default\n",
- zvrf->zebra_rnh_ipv6_default_route
- ? ""
- : "no ");
-
- 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 !=
- SAVE_ZEBRA_IP_NHT_RESOLVE_VIA_DEFAULT)
- vty_out(vty, " %sip nht resolve-via-default\n",
- zvrf->zebra_rnh_ip_default_route
- ? ""
- : "no ");
-
- if (zvrf->zebra_rnh_ipv6_default_route !=
- SAVE_ZEBRA_IP_NHT_RESOLVE_VIA_DEFAULT)
- vty_out(vty, " %sipv6 nht resolve-via-default\n",
- zvrf->zebra_rnh_ipv6_default_route
- ? ""
- : "no ");
-
- 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
*/
@@ -677,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_vty.c b/zebra/zebra_vty.c
index d36c2f8..9a68d5a 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,8 +60,8 @@ 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,
@@ -146,8 +148,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 +766,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 +856,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 +884,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,7 +959,11 @@ 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;
}
}
@@ -966,13 +972,15 @@ static void do_show_route_helper(struct vty *vty, struct zebra_vrf *zvrf,
* This is an extremely expensive operation at scale
* and non-pretty reduces memory footprint significantly.
*/
- if (use_json)
+ 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,
@@ -992,15 +1000,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,
@@ -1035,7 +1043,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);
@@ -1161,27 +1169,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)
{
@@ -1680,68 +1667,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
@@ -1815,6 +1740,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)) {
@@ -1836,24 +1762,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;
@@ -1869,13 +1813,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);
@@ -2251,7 +2195,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);
}
@@ -2724,146 +2669,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];
- int filter = 0;
-
- 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 (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,
@@ -4028,6 +3833,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",
@@ -4047,7 +3863,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())
@@ -4482,31 +4300,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,
@@ -4618,14 +4411,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);
@@ -4677,19 +4462,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 50a7462..2ffaefd 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);
@@ -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;
@@ -1590,17 +1590,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.
*/
@@ -2258,14 +2265,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);
@@ -2293,7 +2299,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));
@@ -2590,14 +2596,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;
@@ -2631,14 +2638,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;
@@ -2672,7 +2680,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;
}
@@ -2698,7 +2707,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;
}
@@ -2709,7 +2719,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);
@@ -2721,7 +2731,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",
@@ -2742,13 +2752,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) {
@@ -2770,14 +2783,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;
@@ -2790,7 +2803,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;
}
@@ -2806,7 +2819,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;
}
@@ -2834,14 +2848,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;
@@ -2905,14 +2920,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;
@@ -2959,7 +2975,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;
}
@@ -2989,7 +3006,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;
}
@@ -3020,14 +3038,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;
@@ -3064,14 +3083,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;
@@ -3113,14 +3133,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;
@@ -3177,21 +3198,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();
@@ -3250,7 +3274,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;
}
@@ -3278,7 +3303,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;
}
@@ -3307,7 +3333,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;
}
@@ -3337,7 +3364,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;
}
@@ -3377,22 +3405,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();
@@ -3727,21 +3767,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();
@@ -3785,7 +3829,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;
}
@@ -3829,7 +3874,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;
}
@@ -3906,7 +3952,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;
}
@@ -3990,7 +4037,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;
}
@@ -5110,7 +5157,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);
@@ -5127,9 +5188,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;
@@ -5141,21 +5201,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);
@@ -5201,23 +5246,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);
@@ -5235,7 +5264,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)
@@ -5772,6 +5800,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)
{
diff --git a/zebra/zebra_vxlan.h b/zebra/zebra_vxlan.h
index 98c2767..eb02de6 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 2db228b..6a64176 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -637,7 +637,7 @@ static void zserv_client_free(struct zserv *client)
vrf_bitmap_free(&client->redist_default[afi]);
vrf_bitmap_free(&client->ridinfo[afi]);
- vrf_bitmap_free(&client->nhrp_neighinfo[afi]);
+ vrf_bitmap_free(&client->neighinfo[afi]);
}
/*
@@ -758,7 +758,7 @@ static struct zserv *zserv_client_create(int sock)
vrf_bitmap_init(&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(&client->neighinfo[afi]);
}
/* Add this client to linked list. */
@@ -1061,6 +1061,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,
diff --git a/zebra/zserv.h b/zebra/zserv.h
index 90aa4d5..e1c990f 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.