summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_labelpool.c7
-rw-r--r--isisd/fabricd.h2
-rw-r--r--isisd/isis_cli.c35
-rw-r--r--isisd/isis_cli.h2
-rw-r--r--isisd/isis_main.c5
-rw-r--r--isisd/isis_northbound.c37
-rw-r--r--isisd/isis_vty_common.c109
-rw-r--r--isisd/isis_vty_common.h32
-rw-r--r--isisd/isis_vty_fabricd.c67
-rw-r--r--isisd/subdir.am3
-rw-r--r--ldpd/lde.c3
-rw-r--r--ldpd/ldpd.c3
-rw-r--r--lib/log.c1
-rw-r--r--lib/monotime.h7
-rw-r--r--lib/mpls.h1
-rw-r--r--lib/zclient.c17
-rw-r--r--lib/zclient.h11
-rw-r--r--ospfd/ospf_packet.c8
-rw-r--r--ospfd/ospf_vty.c121
-rw-r--r--ospfd/ospfd.c17
-rw-r--r--pimd/pim_zebra.c20
-rw-r--r--tests/lib/test_ntop.c1
-rw-r--r--tests/test_lblmgr.c147
-rw-r--r--tests/topotests/lm-proxy-topo1/ce1/bgpd.conf9
-rw-r--r--tests/topotests/lm-proxy-topo1/ce1/zebra.conf11
-rw-r--r--tests/topotests/lm-proxy-topo1/ce2/bgpd.conf9
-rw-r--r--tests/topotests/lm-proxy-topo1/ce2/zebra.conf11
-rw-r--r--tests/topotests/lm-proxy-topo1/lm-proxy-topo1.dot102
-rw-r--r--tests/topotests/lm-proxy-topo1/lm-proxy-topo1.pdfbin16393 -> 0 bytes
-rw-r--r--tests/topotests/lm-proxy-topo1/lm/zebra.conf3
-rw-r--r--tests/topotests/lm-proxy-topo1/p1/ldpd.conf9
-rw-r--r--tests/topotests/lm-proxy-topo1/p1/ospfd.conf7
-rw-r--r--tests/topotests/lm-proxy-topo1/p1/zebra.conf12
-rw-r--r--tests/topotests/lm-proxy-topo1/pe1/bgpd.conf26
-rw-r--r--tests/topotests/lm-proxy-topo1/pe1/ldpd.conf8
-rw-r--r--tests/topotests/lm-proxy-topo1/pe1/ospfd.conf6
-rw-r--r--tests/topotests/lm-proxy-topo1/pe1/zebra.conf14
-rw-r--r--tests/topotests/lm-proxy-topo1/pe2/bgpd.conf26
-rw-r--r--tests/topotests/lm-proxy-topo1/pe2/ldpd.conf8
-rw-r--r--tests/topotests/lm-proxy-topo1/pe2/ospfd.conf6
-rw-r--r--tests/topotests/lm-proxy-topo1/pe2/zebra.conf14
-rw-r--r--tests/topotests/lm-proxy-topo1/test_lm-proxy-topo1.py205
-rw-r--r--vtysh/vtysh_config.c3
-rw-r--r--yang/frr-isisd.yang6
-rw-r--r--zebra/interface.c5
-rw-r--r--zebra/label_manager.c571
-rw-r--r--zebra/label_manager.h61
-rw-r--r--zebra/main.c11
-rw-r--r--zebra/rt_netlink.c17
-rw-r--r--zebra/zapi_msg.c83
-rw-r--r--zebra/zapi_msg.h10
-rw-r--r--zebra/zebra_rib.c2
-rw-r--r--zebra/zebra_vrf.h1
-rw-r--r--zebra/zebra_vxlan.c95
-rw-r--r--zebra/zebra_vxlan.h1
-rw-r--r--zebra/zserv.c25
-rw-r--r--zebra/zserv.h1
57 files changed, 758 insertions, 1276 deletions
diff --git a/bgpd/bgp_labelpool.c b/bgpd/bgp_labelpool.c
index 7518f02acf..feda0328bd 100644
--- a/bgpd/bgp_labelpool.c
+++ b/bgpd/bgp_labelpool.c
@@ -29,6 +29,7 @@
#include "skiplist.h"
#include "workqueue.h"
#include "zclient.h"
+#include "mpls.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_labelpool.h"
@@ -391,7 +392,8 @@ void bgp_lp_get(
if (lp_fifo_count(&lp->requests) > lp->pending_count) {
if (!zclient || zclient->sock < 0)
return;
- if (!zclient_send_get_label_chunk(zclient, 0, LP_CHUNK_SIZE))
+ if (!zclient_send_get_label_chunk(zclient, 0, LP_CHUNK_SIZE,
+ MPLS_LABEL_BASE_ANY))
lp->pending_count += LP_CHUNK_SIZE;
}
}
@@ -552,7 +554,8 @@ void bgp_lp_event_zebra_up(void)
return;
}
- zclient_send_get_label_chunk(zclient, 0, labels_needed);
+ zclient_send_get_label_chunk(zclient, 0, labels_needed,
+ MPLS_LABEL_BASE_ANY);
lp->pending_count = labels_needed;
/*
diff --git a/isisd/fabricd.h b/isisd/fabricd.h
index 315cfba3f0..6e93440f3a 100644
--- a/isisd/fabricd.h
+++ b/isisd/fabricd.h
@@ -53,4 +53,6 @@ void fabricd_update_lsp_no_flood(struct isis_lsp *lsp,
void fabricd_configure_triggered_csnp(struct isis_area *area, int delay,
bool always_send_csnp);
void fabricd_init(void);
+void isis_vty_daemon_init(void);
+
#endif
diff --git a/isisd/isis_cli.c b/isisd/isis_cli.c
index 0334b98a12..4b43260773 100644
--- a/isisd/isis_cli.c
+++ b/isisd/isis_cli.c
@@ -333,6 +333,40 @@ void cli_show_ip_isis_ipv6(struct vty *vty, struct lyd_node *dnode,
}
/*
+ * XPath: /frr-interface:lib/interface/frr-isisd:isis/bfd-monitoring
+ */
+DEFPY(isis_bfd,
+ isis_bfd_cmd,
+ "[no] isis bfd",
+ NO_STR
+ PROTO_HELP
+ "Enable BFD support\n")
+{
+ const struct lyd_node *dnode;
+
+ dnode = yang_dnode_get(vty->candidate_config->dnode,
+ "%s/frr-isisd:isis", VTY_CURR_XPATH);
+ if (dnode == NULL) {
+ vty_out(vty, "ISIS is not enabled on this circuit\n");
+ return CMD_SUCCESS;
+ }
+
+ nb_cli_enqueue_change(vty, "./frr-isisd:isis/bfd-monitoring",
+ NB_OP_MODIFY, no ? "false" : "true");
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+void cli_show_ip_isis_bfd_monitoring(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults)
+{
+ if (!yang_dnode_get_bool(dnode, NULL))
+ vty_out(vty, " no");
+
+ vty_out(vty, "isis bfd\n");
+}
+
+/*
* XPath: /frr-isisd:isis/instance/area-address
*/
DEFPY(net, net_cmd, "[no] net WORD",
@@ -1949,6 +1983,7 @@ void isis_cli_init(void)
install_element(INTERFACE_NODE, &ip_router_isis_cmd);
install_element(INTERFACE_NODE, &ip6_router_isis_cmd);
install_element(INTERFACE_NODE, &no_ip_router_isis_cmd);
+ install_element(INTERFACE_NODE, &isis_bfd_cmd);
install_element(ISIS_NODE, &net_cmd);
diff --git a/isisd/isis_cli.h b/isisd/isis_cli.h
index 8dadf60981..6621dc0fc0 100644
--- a/isisd/isis_cli.h
+++ b/isisd/isis_cli.h
@@ -27,6 +27,8 @@ void cli_show_ip_isis_ipv4(struct vty *vty, struct lyd_node *dnode,
bool show_defaults);
void cli_show_ip_isis_ipv6(struct vty *vty, struct lyd_node *dnode,
bool show_defaults);
+void cli_show_ip_isis_bfd_monitoring(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults);
void cli_show_isis_area_address(struct vty *vty, struct lyd_node *dnode,
bool show_defaults);
void cli_show_isis_is_type(struct vty *vty, struct lyd_node *dnode,
diff --git a/isisd/isis_main.c b/isisd/isis_main.c
index 48ae760173..7f49e9d89a 100644
--- a/isisd/isis_main.c
+++ b/isisd/isis_main.c
@@ -53,7 +53,6 @@
#include "isisd/isis_zebra.h"
#include "isisd/isis_te.h"
#include "isisd/isis_errors.h"
-#include "isisd/isis_vty_common.h"
#include "isisd/isis_bfd.h"
#include "isisd/isis_lsp.h"
#include "isisd/isis_mt.h"
@@ -230,7 +229,9 @@ int main(int argc, char **argv, char **envp)
prefix_list_init();
isis_init();
isis_circuit_init();
- isis_vty_init();
+#ifdef FABRICD
+ isis_vty_daemon_init();
+#endif /* FABRICD */
#ifndef FABRICD
isis_cli_init();
#endif /* ifdef FABRICD */
diff --git a/isisd/isis_northbound.c b/isisd/isis_northbound.c
index ffc6ee0464..0982a468a6 100644
--- a/isisd/isis_northbound.c
+++ b/isisd/isis_northbound.c
@@ -25,6 +25,8 @@
#include "libfrr.h"
#include "linklist.h"
#include "log.h"
+#include "lib/bfd.h"
+#include "isisd/isis_bfd.h"
#include "isisd/isis_constants.h"
#include "isisd/isis_common.h"
#include "isisd/isis_flags.h"
@@ -1703,6 +1705,34 @@ static int lib_interface_isis_ipv6_routing_modify(enum nb_event event,
}
/*
+ * XPath: /frr-interface:lib/interface/frr-isisd:isis/bfd-monitoring
+ */
+static int lib_interface_isis_bfd_monitoring_modify(enum nb_event event,
+ const struct lyd_node *dnode,
+ union nb_resource *resource)
+{
+ struct isis_circuit *circuit;
+ bool bfd_monitoring;
+
+ if (event != NB_EV_APPLY)
+ return NB_OK;
+
+ circuit = nb_running_get_entry(dnode, NULL, true);
+ bfd_monitoring = yang_dnode_get_bool(dnode, NULL);
+
+ if (bfd_monitoring) {
+ isis_bfd_circuit_param_set(circuit, BFD_DEF_MIN_RX,
+ BFD_DEF_MIN_TX, BFD_DEF_DETECT_MULT,
+ true);
+ } else {
+ isis_bfd_circuit_cmd(circuit, ZEBRA_BFD_DEST_DEREGISTER);
+ bfd_info_free(&circuit->bfd_info);
+ }
+
+ return NB_OK;
+}
+
+/*
* XPath: /frr-interface:lib/interface/frr-isisd:isis/csnp-interval/level-1
*/
static int
@@ -3212,6 +3242,13 @@ const struct frr_yang_module_info frr_isisd_info = {
},
},
{
+ .xpath = "/frr-interface:lib/interface/frr-isisd:isis/bfd-monitoring",
+ .cbs = {
+ .modify = lib_interface_isis_bfd_monitoring_modify,
+ .cli_show = cli_show_ip_isis_bfd_monitoring,
+ }
+ },
+ {
.xpath = "/frr-interface:lib/interface/frr-isisd:isis/csnp-interval",
.cbs = {
.cli_show = cli_show_ip_isis_csnp_interval,
diff --git a/isisd/isis_vty_common.c b/isisd/isis_vty_common.c
deleted file mode 100644
index 06432db0b2..0000000000
--- a/isisd/isis_vty_common.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * IS-IS Rout(e)ing protocol - isis_vty_common.c
- *
- * This file contains the CLI that is shared between OpenFabric and IS-IS
- *
- * Copyright (C) 2001,2002 Sampo Saaristo
- * Tampere University of Technology
- * Institute of Communications Engineering
- * Copyright (C) 2016 David Lamparter, for NetDEF, Inc.
- * Copyright (C) 2018 Christian Franke, for NetDEF, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public Licenseas published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <zebra.h>
-
-#include "command.h"
-#include "bfd.h"
-
-#include "isis_circuit.h"
-#include "isis_csm.h"
-#include "isis_misc.h"
-#include "isisd.h"
-#include "isis_bfd.h"
-#include "isis_vty_common.h"
-
-struct isis_circuit *isis_circuit_lookup(struct vty *vty)
-{
- struct interface *ifp = VTY_GET_CONTEXT(interface);
- struct isis_circuit *circuit;
-
- if (!ifp) {
- vty_out(vty, "Invalid interface \n");
- return NULL;
- }
-
- circuit = circuit_scan_by_ifp(ifp);
- if (!circuit) {
- vty_out(vty, "ISIS is not enabled on circuit %s\n", ifp->name);
- return NULL;
- }
-
- return circuit;
-}
-
-DEFUN (isis_bfd,
- isis_bfd_cmd,
- PROTO_NAME " bfd",
- PROTO_HELP
- "Enable BFD support\n")
-{
- struct isis_circuit *circuit = isis_circuit_lookup(vty);
-
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- if (circuit->bfd_info
- && CHECK_FLAG(circuit->bfd_info->flags, BFD_FLAG_PARAM_CFG)) {
- return CMD_SUCCESS;
- }
-
- isis_bfd_circuit_param_set(circuit, BFD_DEF_MIN_RX,
- BFD_DEF_MIN_TX, BFD_DEF_DETECT_MULT, true);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_isis_bfd,
- no_isis_bfd_cmd,
- "no " PROTO_NAME " bfd",
- NO_STR
- PROTO_HELP
- "Disables BFD support\n"
-)
-{
- struct isis_circuit *circuit = isis_circuit_lookup(vty);
-
- if (!circuit)
- return CMD_ERR_NO_MATCH;
-
- if (!circuit->bfd_info)
- return CMD_SUCCESS;
-
- isis_bfd_circuit_cmd(circuit, ZEBRA_BFD_DEST_DEREGISTER);
- bfd_info_free(&circuit->bfd_info);
- return CMD_SUCCESS;
-}
-
-void isis_vty_init(void)
-{
- install_element(INTERFACE_NODE, &isis_bfd_cmd);
- install_element(INTERFACE_NODE, &no_isis_bfd_cmd);
-
-#ifdef FABRICD
- isis_vty_daemon_init();
-#endif /* ifdef FABRICD */
-}
diff --git a/isisd/isis_vty_common.h b/isisd/isis_vty_common.h
deleted file mode 100644
index 297da0e2c1..0000000000
--- a/isisd/isis_vty_common.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * IS-IS Rout(e)ing protocol - isis_vty_common.h
- *
- * Copyright (C) 2001,2002 Sampo Saaristo
- * Tampere University of Technology
- * Institute of Communications Engineering
- * Copyright (C) 2016 David Lamparter, for NetDEF, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public Licenseas published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef ISIS_VTY_COMMON_H
-#define ISIS_VTY_COMMON_H
-
-struct isis_circuit *isis_circuit_lookup(struct vty *vty);
-
-void isis_vty_daemon_init(void);
-void isis_vty_init(void);
-
-#endif
diff --git a/isisd/isis_vty_fabricd.c b/isisd/isis_vty_fabricd.c
index 431ad9712a..24e5c51947 100644
--- a/isisd/isis_vty_fabricd.c
+++ b/isisd/isis_vty_fabricd.c
@@ -23,8 +23,9 @@
#include "command.h"
+#include "lib/bfd.h"
+#include "isisd/isis_bfd.h"
#include "isisd/isisd.h"
-#include "isisd/isis_vty_common.h"
#include "isisd/fabricd.h"
#include "isisd/isis_tlvs.h"
#include "isisd/isis_misc.h"
@@ -34,6 +35,25 @@
#include "lib/spf_backoff.h"
#include "isisd/isis_mt.h"
+static struct isis_circuit *isis_circuit_lookup(struct vty *vty)
+{
+ struct interface *ifp = VTY_GET_CONTEXT(interface);
+ struct isis_circuit *circuit;
+
+ if (!ifp) {
+ vty_out(vty, "Invalid interface \n");
+ return NULL;
+ }
+
+ circuit = circuit_scan_by_ifp(ifp);
+ if (!circuit) {
+ vty_out(vty, "ISIS is not enabled on circuit %s\n", ifp->name);
+ return NULL;
+ }
+
+ return circuit;
+}
+
DEFUN (fabric_tier,
fabric_tier_cmd,
"fabric-tier (0-14)",
@@ -288,6 +308,49 @@ DEFUN (no_ip_router_isis,
return CMD_SUCCESS;
}
+DEFUN (isis_bfd,
+ isis_bfd_cmd,
+ PROTO_NAME " bfd",
+ PROTO_HELP
+ "Enable BFD support\n")
+{
+ struct isis_circuit *circuit = isis_circuit_lookup(vty);
+
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ if (circuit->bfd_info
+ && CHECK_FLAG(circuit->bfd_info->flags, BFD_FLAG_PARAM_CFG)) {
+ return CMD_SUCCESS;
+ }
+
+ isis_bfd_circuit_param_set(circuit, BFD_DEF_MIN_RX,
+ BFD_DEF_MIN_TX, BFD_DEF_DETECT_MULT, true);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_isis_bfd,
+ no_isis_bfd_cmd,
+ "no " PROTO_NAME " bfd",
+ NO_STR
+ PROTO_HELP
+ "Disables BFD support\n"
+)
+{
+ struct isis_circuit *circuit = isis_circuit_lookup(vty);
+
+ if (!circuit)
+ return CMD_ERR_NO_MATCH;
+
+ if (!circuit->bfd_info)
+ return CMD_SUCCESS;
+
+ isis_bfd_circuit_cmd(circuit, ZEBRA_BFD_DEST_DEREGISTER);
+ bfd_info_free(&circuit->bfd_info);
+ return CMD_SUCCESS;
+}
+
DEFUN (set_overload_bit,
set_overload_bit_cmd,
"set-overload-bit",
@@ -1045,6 +1108,8 @@ void isis_vty_daemon_init(void)
install_element(INTERFACE_NODE, &ip_router_isis_cmd);
install_element(INTERFACE_NODE, &ip6_router_isis_cmd);
install_element(INTERFACE_NODE, &no_ip_router_isis_cmd);
+ install_element(INTERFACE_NODE, &isis_bfd_cmd);
+ install_element(INTERFACE_NODE, &no_isis_bfd_cmd);
install_element(ROUTER_NODE, &set_overload_bit_cmd);
install_element(ROUTER_NODE, &no_set_overload_bit_cmd);
diff --git a/isisd/subdir.am b/isisd/subdir.am
index bae56309cf..24f24022a5 100644
--- a/isisd/subdir.am
+++ b/isisd/subdir.am
@@ -11,7 +11,6 @@ vtysh_scan += \
$(top_srcdir)/isisd/isis_redist.c \
$(top_srcdir)/isisd/isis_spf.c \
$(top_srcdir)/isisd/isis_te.c \
- $(top_srcdir)/isisd/isis_vty_common.c \
$(top_srcdir)/isisd/isis_vty_fabricd.c \
$(top_srcdir)/isisd/isisd.c \
# end
@@ -51,7 +50,6 @@ noinst_HEADERS += \
isisd/isis_te.h \
isisd/isis_tlvs.h \
isisd/isis_tx_queue.h \
- isisd/isis_vty_common.h \
isisd/isis_zebra.h \
isisd/isisd.h \
isisd/iso_checksum.h \
@@ -82,7 +80,6 @@ LIBISIS_SOURCES = \
isisd/isis_te.c \
isisd/isis_tlvs.c \
isisd/isis_tx_queue.c \
- isisd/isis_vty_common.c \
isisd/isis_zebra.c \
isisd/isisd.c \
isisd/iso_checksum.c \
diff --git a/ldpd/lde.c b/ldpd/lde.c
index 2aa96546ec..0ddf4f07d9 100644
--- a/ldpd/lde.c
+++ b/ldpd/lde.c
@@ -1660,7 +1660,8 @@ lde_get_label_chunk(void)
uint32_t start, end;
debug_labels("getting label chunk (size %u)", CHUNK_SIZE);
- ret = lm_get_label_chunk(zclient_sync, 0, CHUNK_SIZE, &start, &end);
+ ret = lm_get_label_chunk(zclient_sync, 0, MPLS_LABEL_BASE_ANY,
+ CHUNK_SIZE, &start, &end);
if (ret < 0) {
log_warnx("Error getting label chunk!");
return -1;
diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c
index 9fccb085dd..a6f0519bd7 100644
--- a/ldpd/ldpd.c
+++ b/ldpd/ldpd.c
@@ -236,6 +236,9 @@ main(int argc, char *argv[])
" --ctl_socket Override ctl socket path\n"
" -n, --instance Instance id\n");
+ /* set default instance (to differentiate ldpd socket from lde one */
+ init.instance = 1;
+
while (1) {
int opt;
diff --git a/lib/log.c b/lib/log.c
index 732b238b1e..48ee0f6adb 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -1122,6 +1122,7 @@ static const struct zebra_desc_table command_types[] = {
DESC_ENTRY(ZEBRA_VXLAN_FLOOD_CONTROL),
DESC_ENTRY(ZEBRA_VXLAN_SG_ADD),
DESC_ENTRY(ZEBRA_VXLAN_SG_DEL),
+ DESC_ENTRY(ZEBRA_VXLAN_SG_REPLAY),
};
#undef DESC_ENTRY
diff --git a/lib/monotime.h b/lib/monotime.h
index 6aac966ea1..ca27c45dc6 100644
--- a/lib/monotime.h
+++ b/lib/monotime.h
@@ -84,7 +84,10 @@ static inline int64_t monotime_until(const struct timeval *ref,
return (int64_t)tv.tv_sec * 1000000LL + tv.tv_usec;
}
-static inline char *time_to_string(time_t ts)
+/* Char buffer size for time-to-string api */
+#define MONOTIME_STRLEN 32
+
+static inline char *time_to_string(time_t ts, char *buf)
{
struct timeval tv;
time_t tbuf;
@@ -92,7 +95,7 @@ static inline char *time_to_string(time_t ts)
monotime(&tv);
tbuf = time(NULL) - (tv.tv_sec - ts);
- return ctime(&tbuf);
+ return ctime_r(&tbuf, buf);
}
#ifdef __cplusplus
diff --git a/lib/mpls.h b/lib/mpls.h
index b140c8e317..d7b56c47bd 100644
--- a/lib/mpls.h
+++ b/lib/mpls.h
@@ -54,6 +54,7 @@ extern "C" {
#define MPLS_LABEL_RESERVED_MAX 15
#define MPLS_LABEL_UNRESERVED_MIN 16
#define MPLS_LABEL_UNRESERVED_MAX 1048575
+#define MPLS_LABEL_BASE_ANY 0
/* Default min and max SRGB label range */
/* Even if the SRGB allows to manage different Label space between routers,
diff --git a/lib/zclient.c b/lib/zclient.c
index e9b4f5a58b..6937700199 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -1995,10 +1995,11 @@ int lm_label_manager_connect(struct zclient *zclient, int async)
* @param zclient Zclient used to connect to label manager (zebra)
* @param keep Avoid garbage collection
* @param chunk_size Amount of labels requested
+ * @param base Base for the label chunk. if MPLS_LABEL_BASE_ANY we do not care
* @result 0 on success, -1 otherwise
*/
int zclient_send_get_label_chunk(struct zclient *zclient, uint8_t keep,
- uint32_t chunk_size)
+ uint32_t chunk_size, uint32_t base)
{
struct stream *s;
@@ -2018,6 +2019,7 @@ int zclient_send_get_label_chunk(struct zclient *zclient, uint8_t keep,
stream_putw(s, zclient->instance);
stream_putc(s, keep);
stream_putl(s, chunk_size);
+ stream_putl(s, base);
/* Put length at the first point of the stream. */
stream_putw_at(s, 0, stream_get_endp(s));
@@ -2038,7 +2040,7 @@ int zclient_send_get_label_chunk(struct zclient *zclient, uint8_t keep,
* @param end To write last assigned chunk label to
* @result 0 on success, -1 otherwise
*/
-int lm_get_label_chunk(struct zclient *zclient, uint8_t keep,
+int lm_get_label_chunk(struct zclient *zclient, uint8_t keep, uint32_t base,
uint32_t chunk_size, uint32_t *start, uint32_t *end)
{
int ret;
@@ -2063,6 +2065,8 @@ int lm_get_label_chunk(struct zclient *zclient, uint8_t keep,
stream_putc(s, keep);
/* chunk size */
stream_putl(s, chunk_size);
+ /* requested chunk base */
+ stream_putl(s, base);
/* Put length at the first point of the stream. */
stream_putw_at(s, 0, stream_get_endp(s));
@@ -2103,6 +2107,15 @@ int lm_get_label_chunk(struct zclient *zclient, uint8_t keep,
"Wrong instId (%u) in get chunk response Should be %u",
instance, zclient->instance);
+ /* if we requested a specific chunk and it could not be allocated, the
+ * response message will end here
+ */
+ if (!STREAM_READABLE(s)) {
+ zlog_info("Unable to assign Label Chunk to %s instance %u",
+ zebra_route_string(proto), instance);
+ return -1;
+ }
+
/* keep */
response_keep = stream_getc(s);
/* start and end labels */
diff --git a/lib/zclient.h b/lib/zclient.h
index d651738687..81e454d192 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -176,6 +176,7 @@ typedef enum {
ZEBRA_VXLAN_FLOOD_CONTROL,
ZEBRA_VXLAN_SG_ADD,
ZEBRA_VXLAN_SG_DEL,
+ ZEBRA_VXLAN_SG_REPLAY,
} zebra_message_types_t;
struct redist_proto {
@@ -609,15 +610,13 @@ extern struct interface *zebra_interface_link_params_read(struct stream *s,
vrf_id_t vrf_id);
extern size_t zebra_interface_link_params_write(struct stream *,
struct interface *);
-extern int zclient_send_get_label_chunk(
- struct zclient *zclient,
- uint8_t keep,
- uint32_t chunk_size);
+extern int zclient_send_get_label_chunk(struct zclient *zclient, uint8_t keep,
+ uint32_t chunk_size, uint32_t base);
extern int lm_label_manager_connect(struct zclient *zclient, int async);
extern int lm_get_label_chunk(struct zclient *zclient, uint8_t keep,
- uint32_t chunk_size, uint32_t *start,
- uint32_t *end);
+ uint32_t base, uint32_t chunk_size,
+ uint32_t *start, uint32_t *end);
extern int lm_release_label_chunk(struct zclient *zclient, uint32_t start,
uint32_t end);
extern int tm_table_manager_connect(struct zclient *zclient);
diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c
index 6bc8c25153..50c30a6fa0 100644
--- a/ospfd/ospf_packet.c
+++ b/ospfd/ospf_packet.c
@@ -660,6 +660,14 @@ static int ospf_write(struct thread *thread)
struct in_pktinfo *pi;
#endif
+ if (ospf->fd < 0 || ospf->oi_running == 0) {
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug(
+ "ospf_write failed to send, fd %d, instance %u"
+ ,ospf->fd, ospf->oi_running);
+ return -1;
+ }
+
ospf->t_write = NULL;
node = listhead(ospf->oi_write_q);
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index dfa34f15ef..98ddd6a79e 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -4884,14 +4884,36 @@ static void show_ip_ospf_nbr_nbma_detail_sub(struct vty *vty,
static void show_ip_ospf_neighbor_detail_sub(struct vty *vty,
struct ospf_interface *oi,
struct ospf_neighbor *nbr,
+ struct ospf_neighbor *prev_nbr,
json_object *json, bool use_json)
{
char timebuf[OSPF_TIME_DUMP_SIZE];
- json_object *json_sub = NULL;
+ json_object *json_neigh = NULL, *json_neigh_array = NULL;
+ char neigh_str[INET_ADDRSTRLEN] = {0};
- if (use_json)
- json_sub = json_object_new_object();
- else {
+ if (use_json) {
+ if (prev_nbr &&
+ !IPV4_ADDR_SAME(&prev_nbr->src, &nbr->src)) {
+ json_neigh_array = NULL;
+ }
+
+ if (nbr->state == NSM_Attempt && nbr->router_id.s_addr == 0)
+ strlcpy(neigh_str, "noNbrId", sizeof(neigh_str));
+ else
+ strlcpy(neigh_str, inet_ntoa(nbr->router_id),
+ sizeof(neigh_str));
+
+ json_object_object_get_ex(json, neigh_str, &json_neigh_array);
+
+ if (!json_neigh_array) {
+ json_neigh_array = json_object_new_array();
+ json_object_object_add(json, neigh_str,
+ json_neigh_array);
+ }
+
+ json_neigh = json_object_new_object();
+
+ } else {
/* Show neighbor ID. */
if (nbr->state == NSM_Attempt && nbr->router_id.s_addr == 0)
vty_out(vty, " Neighbor %s,", "-");
@@ -4902,7 +4924,7 @@ static void show_ip_ospf_neighbor_detail_sub(struct vty *vty,
/* Show interface address. */
if (use_json)
- json_object_string_add(json_sub, "ifaceAddress",
+ json_object_string_add(json_neigh, "ifaceAddress",
inet_ntoa(nbr->address.u.prefix4));
else
vty_out(vty, " interface address %s\n",
@@ -4910,18 +4932,18 @@ static void show_ip_ospf_neighbor_detail_sub(struct vty *vty,
/* Show Area ID. */
if (use_json) {
- json_object_string_add(json_sub, "areaId",
+ json_object_string_add(json_neigh, "areaId",
ospf_area_desc_string(oi->area));
- json_object_string_add(json_sub, "ifaceName", oi->ifp->name);
+ json_object_string_add(json_neigh, "ifaceName", oi->ifp->name);
} else
vty_out(vty, " In the area %s via interface %s\n",
ospf_area_desc_string(oi->area), oi->ifp->name);
/* Show neighbor priority and state. */
if (use_json) {
- json_object_int_add(json_sub, "nbrPriority", nbr->priority);
+ json_object_int_add(json_neigh, "nbrPriority", nbr->priority);
json_object_string_add(
- json_sub, "nbrState",
+ json_neigh, "nbrState",
lookup_msg(ospf_nsm_state_msg, nbr->state, NULL));
} else
vty_out(vty, " Neighbor priority is %d, State is %s,",
@@ -4930,7 +4952,7 @@ static void show_ip_ospf_neighbor_detail_sub(struct vty *vty,
/* Show state changes. */
if (use_json)
- json_object_int_add(json_sub, "stateChangeCounter",
+ json_object_int_add(json_neigh, "stateChangeCounter",
nbr->state_change);
else
vty_out(vty, " %d state changes\n", nbr->state_change);
@@ -4942,7 +4964,7 @@ static void show_ip_ospf_neighbor_detail_sub(struct vty *vty,
time_store =
monotime_since(&nbr->ts_last_progress, &res) / 1000LL;
if (use_json) {
- json_object_int_add(json_sub, "lastPrgrsvChangeMsec",
+ json_object_int_add(json_neigh, "lastPrgrsvChangeMsec",
time_store);
} else {
vty_out(vty,
@@ -4960,12 +4982,13 @@ static void show_ip_ospf_neighbor_detail_sub(struct vty *vty,
time_store =
monotime_since(&nbr->ts_last_regress, &res) / 1000LL;
if (use_json) {
- json_object_int_add(json_sub,
+ json_object_int_add(json_neigh,
"lastRegressiveChangeMsec",
time_store);
if (nbr->last_regress_str)
json_object_string_add(
- json_sub, "lastRegressiveChangeReason",
+ json_neigh,
+ "lastRegressiveChangeReason",
nbr->last_regress_str);
} else {
vty_out(vty,
@@ -4979,22 +5002,22 @@ static void show_ip_ospf_neighbor_detail_sub(struct vty *vty,
/* Show Designated Rotuer ID. */
if (use_json)
- json_object_string_add(json_sub, "routerDesignatedId",
+ json_object_string_add(json_neigh, "routerDesignatedId",
inet_ntoa(nbr->d_router));
else
vty_out(vty, " DR is %s,", inet_ntoa(nbr->d_router));
/* Show Backup Designated Rotuer ID. */
if (use_json)
- json_object_string_add(json_sub, "routerDesignatedBackupId",
+ json_object_string_add(json_neigh, "routerDesignatedBackupId",
inet_ntoa(nbr->bd_router));
else
vty_out(vty, " BDR is %s\n", inet_ntoa(nbr->bd_router));
/* Show options. */
if (use_json) {
- json_object_int_add(json_sub, "optionsCounter", nbr->options);
- json_object_string_add(json_sub, "optionsList",
+ json_object_int_add(json_neigh, "optionsCounter", nbr->options);
+ json_object_string_add(json_neigh, "optionsList",
ospf_options_dump(nbr->options));
} else
vty_out(vty, " Options %d %s\n", nbr->options,
@@ -5007,12 +5030,13 @@ static void show_ip_ospf_neighbor_detail_sub(struct vty *vty,
time_store = monotime_until(&nbr->t_inactivity->u.sands,
NULL)
/ 1000LL;
- json_object_int_add(json_sub,
+ json_object_int_add(json_neigh,
"routerDeadIntervalTimerDueMsec",
time_store);
} else
json_object_int_add(
- json_sub, "routerDeadIntervalTimerDueMsec", -1);
+ json_neigh,
+ "routerDeadIntervalTimerDueMsec", -1);
} else
vty_out(vty, " Dead timer due in %s\n",
ospf_timer_dump(nbr->t_inactivity, timebuf,
@@ -5020,7 +5044,7 @@ static void show_ip_ospf_neighbor_detail_sub(struct vty *vty,
/* Show Database Summary list. */
if (use_json)
- json_object_int_add(json_sub, "databaseSummaryListCounter",
+ json_object_int_add(json_neigh, "databaseSummaryListCounter",
ospf_db_summary_count(nbr));
else
vty_out(vty, " Database Summary List %d\n",
@@ -5028,7 +5052,7 @@ static void show_ip_ospf_neighbor_detail_sub(struct vty *vty,
/* Show Link State Request list. */
if (use_json)
- json_object_int_add(json_sub, "linkStateRequestListCounter",
+ json_object_int_add(json_neigh, "linkStateRequestListCounter",
ospf_ls_request_count(nbr));
else
vty_out(vty, " Link State Request List %ld\n",
@@ -5036,7 +5060,7 @@ static void show_ip_ospf_neighbor_detail_sub(struct vty *vty,
/* Show Link State Retransmission list. */
if (use_json)
- json_object_int_add(json_sub,
+ json_object_int_add(json_neigh,
"linkStateRetransmissionListCounter",
ospf_ls_retransmit_count(nbr));
else
@@ -5046,7 +5070,7 @@ static void show_ip_ospf_neighbor_detail_sub(struct vty *vty,
/* Show inactivity timer thread. */
if (use_json) {
if (nbr->t_inactivity != NULL)
- json_object_string_add(json_sub,
+ json_object_string_add(json_neigh,
"threadInactivityTimer", "on");
} else
vty_out(vty, " Thread Inactivity Timer %s\n",
@@ -5056,7 +5080,7 @@ static void show_ip_ospf_neighbor_detail_sub(struct vty *vty,
if (use_json) {
if (nbr->t_db_desc != NULL)
json_object_string_add(
- json_sub,
+ json_neigh,
"threadDatabaseDescriptionRetransmission",
"on");
} else
@@ -5068,7 +5092,7 @@ static void show_ip_ospf_neighbor_detail_sub(struct vty *vty,
if (use_json) {
if (nbr->t_ls_req != NULL)
json_object_string_add(
- json_sub,
+ json_neigh,
"threadLinkStateRequestRetransmission", "on");
} else
vty_out(vty,
@@ -5079,22 +5103,19 @@ static void show_ip_ospf_neighbor_detail_sub(struct vty *vty,
if (use_json) {
if (nbr->t_ls_upd != NULL)
json_object_string_add(
- json_sub, "threadLinkStateUpdateRetransmission",
+ json_neigh,
+ "threadLinkStateUpdateRetransmission",
"on");
} else
vty_out(vty,
" Thread Link State Update Retransmission %s\n\n",
nbr->t_ls_upd != NULL ? "on" : "off");
- if (use_json) {
- if (nbr->state == NSM_Attempt && nbr->router_id.s_addr == 0)
- json_object_object_add(json, "noNbrId", json_sub);
- else
- json_object_object_add(json, inet_ntoa(nbr->router_id),
- json_sub);
- }
+ ospf_bfd_show_info(vty, nbr->bfd_info, json_neigh, use_json, 0);
+
+ if (use_json)
+ json_object_array_add(json_neigh_array, json_neigh);
- ospf_bfd_show_info(vty, nbr->bfd_info, json, use_json, 0);
}
static int show_ip_ospf_neighbor_id_common(struct vty *vty, struct ospf *ospf,
@@ -5121,8 +5142,8 @@ static int show_ip_ospf_neighbor_id_common(struct vty *vty, struct ospf *ospf,
for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) {
if ((nbr = ospf_nbr_lookup_by_routerid(oi->nbrs, router_id))) {
- show_ip_ospf_neighbor_detail_sub(vty, oi, nbr, json,
- use_json);
+ show_ip_ospf_neighbor_detail_sub(vty, oi, nbr, NULL,
+ json, use_json);
}
}
@@ -5192,16 +5213,20 @@ static int show_ip_ospf_neighbor_detail_common(struct vty *vty,
struct ospf_interface *oi;
struct listnode *node;
json_object *json_vrf = NULL;
+ json_object *json_nbr_sub = NULL;
if (use_json) {
if (use_vrf)
json_vrf = json_object_new_object();
else
json_vrf = json;
+
+ json_nbr_sub = json_object_new_object();
}
+
if (ospf->instance) {
if (use_json)
- json_object_int_add(json_vrf, "ospfInstance",
+ json_object_int_add(json, "ospfInstance",
ospf->instance);
else
vty_out(vty, "\nOSPF Instance: %d\n\n", ospf->instance);
@@ -5211,22 +5236,25 @@ static int show_ip_ospf_neighbor_detail_common(struct vty *vty,
for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) {
struct route_node *rn;
- struct ospf_neighbor *nbr;
+ struct ospf_neighbor *nbr, *prev_nbr = NULL;
for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
if ((nbr = rn->info)) {
if (nbr != oi->nbr_self) {
if (nbr->state != NSM_Down) {
show_ip_ospf_neighbor_detail_sub(
- vty, oi, nbr, json_vrf,
- use_json);
+ vty, oi, nbr, prev_nbr,
+ json_nbr_sub, use_json);
}
}
+ prev_nbr = nbr;
}
}
}
if (use_json) {
+ json_object_object_add(json_vrf, "neighbors",
+ json_nbr_sub);
if (use_vrf) {
if (ospf->vrf_id == VRF_DEFAULT)
json_object_object_add(json, "default",
@@ -5389,16 +5417,20 @@ static int show_ip_ospf_neighbor_detail_all_common(struct vty *vty,
for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) {
struct route_node *rn;
- struct ospf_neighbor *nbr;
+ struct ospf_neighbor *nbr, *prev_nbr = NULL;
struct ospf_nbr_nbma *nbr_nbma;
- for (rn = route_top(oi->nbrs); rn; rn = route_next(rn))
- if ((nbr = rn->info))
+ for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
+ if ((nbr = rn->info)) {
if (nbr != oi->nbr_self)
if (nbr->state != NSM_Down)
show_ip_ospf_neighbor_detail_sub(
vty, oi, rn->info,
+ prev_nbr,
json_vrf, use_json);
+ prev_nbr = nbr;
+ }
+ }
if (oi->type == OSPF_IFTYPE_NBMA) {
struct listnode *nd;
@@ -5594,6 +5626,7 @@ static int show_ip_ospf_neighbor_int_detail_common(struct vty *vty,
if (nbr->state != NSM_Down)
show_ip_ospf_neighbor_detail_sub(
vty, oi, nbr,
+ NULL,
json, use_json);
}
}
@@ -5632,7 +5665,7 @@ DEFUN (show_ip_ospf_neighbor_int_detail,
if (!ospf->oi_running)
continue;
ospf_output = true;
- ret = show_ip_ospf_neighbor_int_detail_common(vty, ospf, 0,
+ ret = show_ip_ospf_neighbor_int_detail_common(vty, ospf, 4,
argv, uj);
}
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index aa38a42714..a64ddbc3b7 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -656,6 +656,7 @@ static void ospf_finish_final(struct ospf *ospf)
for (ALL_LIST_ELEMENTS(ospf->oiflist, node, nnode, oi))
ospf_if_free(oi);
list_delete(&ospf->oiflist);
+ ospf->oi_running = 0;
/* De-Register VRF */
ospf_zebra_vrf_deregister(ospf);
@@ -699,6 +700,8 @@ static void ospf_finish_final(struct ospf *ospf)
}
/* Cancel all timers. */
+ OSPF_TIMER_OFF(ospf->t_read);
+ OSPF_TIMER_OFF(ospf->t_write);
OSPF_TIMER_OFF(ospf->t_external_lsa);
OSPF_TIMER_OFF(ospf->t_spf_calc);
OSPF_TIMER_OFF(ospf->t_ase_calc);
@@ -708,14 +711,9 @@ static void ospf_finish_final(struct ospf *ospf)
OSPF_TIMER_OFF(ospf->t_asbr_check);
OSPF_TIMER_OFF(ospf->t_distribute_update);
OSPF_TIMER_OFF(ospf->t_lsa_refresher);
- OSPF_TIMER_OFF(ospf->t_read);
- OSPF_TIMER_OFF(ospf->t_write);
OSPF_TIMER_OFF(ospf->t_opaque_lsa_self);
OSPF_TIMER_OFF(ospf->t_sr_update);
- close(ospf->fd);
- stream_free(ospf->ibuf);
-
LSDB_LOOP (OPAQUE_AS_LSDB(ospf), rn, lsa)
ospf_discard_from_db(ospf, ospf->lsdb, lsa);
LSDB_LOOP (EXTERNAL_LSDB(ospf), rn, lsa)
@@ -755,9 +753,6 @@ static void ospf_finish_final(struct ospf *ospf)
ospf_ase_external_lsas_finish(ospf->external_lsas);
}
- list_delete(&ospf->areas);
- list_delete(&ospf->oi_write_q);
-
for (i = ZEBRA_ROUTE_SYSTEM; i <= ZEBRA_ROUTE_MAX; i++) {
struct list *ext_list;
struct ospf_external *ext;
@@ -789,6 +784,12 @@ static void ospf_finish_final(struct ospf *ospf)
if (!CHECK_FLAG(om->options, OSPF_MASTER_SHUTDOWN))
instance = ospf->instance;
+ list_delete(&ospf->areas);
+ list_delete(&ospf->oi_write_q);
+
+ close(ospf->fd);
+ stream_free(ospf->ibuf);
+ ospf->fd = -1;
ospf_delete(ospf);
if (ospf->name) {
diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c
index 2c814d0fdc..675e81f5a1 100644
--- a/pimd/pim_zebra.c
+++ b/pimd/pim_zebra.c
@@ -580,6 +580,23 @@ static int pim_zebra_vxlan_sg_proc(ZAPI_CALLBACK_ARGS)
return 0;
}
+static void pim_zebra_vxlan_replay(void)
+{
+ struct stream *s = NULL;
+
+ /* Check socket. */
+ if (!zclient || zclient->sock < 0)
+ return;
+
+ s = zclient->obuf;
+ stream_reset(s);
+
+ zclient_create_header(s, ZEBRA_VXLAN_SG_REPLAY, VRF_DEFAULT);
+ stream_putw_at(s, 0, stream_get_endp(s));
+
+ zclient_send_message(zclient);
+}
+
void pim_scan_individual_oil(struct channel_oil *c_oil, int in_vif_index)
{
struct in_addr vif_source;
@@ -783,6 +800,9 @@ static void pim_zebra_connected(struct zclient *zclient)
bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER, router->vrf_id);
zclient_send_reg_requests(zclient, router->vrf_id);
+
+ /* request for VxLAN BUM group addresses */
+ pim_zebra_vxlan_replay();
}
static void pim_zebra_capabilities(struct zclient_capabilities *cap)
diff --git a/tests/lib/test_ntop.c b/tests/lib/test_ntop.c
index 1806059963..0a55ecddb8 100644
--- a/tests/lib/test_ntop.c
+++ b/tests/lib/test_ntop.c
@@ -81,7 +81,6 @@ int main(int argc, char **argv)
assert(inet_pton(AF_INET6, buf1, &i6check));
assert(!memcmp(&i6, &i6check, sizeof(i6)));
- assert(strlen(buf1) <= strlen(buf2));
}
return 0;
}
diff --git a/tests/test_lblmgr.c b/tests/test_lblmgr.c
deleted file mode 100644
index e71e680fad..0000000000
--- a/tests/test_lblmgr.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Label Manager Test
- *
- * Copyright (C) 2017 by Bingen Eguzkitza,
- * Volta Networks Inc.
- *
- * This file is part of FreeRangeRouting (FRR)
- *
- * FRR is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * FRR is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "lib/stream.h"
-#include "lib/zclient.h"
-
-#define ZSERV_PATH "/tmp/zserv.api" // TODO!!
-#define KEEP 0 /* change to 1 to avoid garbage collection */
-#define CHUNK_SIZE 32
-
-struct zclient *zclient;
-unsigned short instance = 1;
-
-const char *sequence = "GGRGGGRRG";
-
-static int zebra_send_get_label_chunk(void);
-static int zebra_send_release_label_chunk(uint32_t start, uint32_t end);
-
-static void process_next_call(uint32_t start, uint32_t end)
-{
- sleep(3);
- if (!*sequence)
- exit(0);
- if (*sequence == 'G')
- zebra_send_get_label_chunk();
- else if (*sequence == 'R')
- zebra_send_release_label_chunk(start, end);
-}
-
-/* Connect to Label Manager */
-
-static int zebra_send_label_manager_connect()
-{
- int ret;
-
- printf("Connect to Label Manager\n");
-
- ret = lm_label_manager_connect(zclient, 0);
- printf("Label Manager connection result: %u \n", ret);
- if (ret != 0) {
- fprintf(stderr, "Error %d connecting to Label Manager %s\n",
- ret, strerror(errno));
- exit(1);
- }
-
- process_next_call(0, 0);
-}
-
-/* Get Label Chunk */
-
-static int zebra_send_get_label_chunk()
-{
- uint32_t start;
- uint32_t end;
- int ret;
-
- printf("Ask for label chunk \n");
-
- ret = lm_get_label_chunk(zclient, KEEP, CHUNK_SIZE, &start, &end);
- if (ret != 0) {
- fprintf(stderr, "Error %d requesting label chunk %s\n", ret,
- strerror(errno));
- exit(1);
- }
-
- sequence++;
-
- printf("Label Chunk assign: %u - %u \n", start, end);
-
- process_next_call(start, end);
-}
-
-/* Release Label Chunk */
-
-static int zebra_send_release_label_chunk(uint32_t start, uint32_t end)
-{
- struct stream *s;
- int ret;
-
- printf("Release label chunk: %u - %u\n", start, end);
-
- ret = lm_release_label_chunk(zclient, start, end);
- if (ret != 0) {
- fprintf(stderr, "Error releasing label chunk\n");
- exit(1);
- }
-
- sequence++;
-
- process_next_call(start - CHUNK_SIZE, end - CHUNK_SIZE);
-}
-
-
-void init_zclient(struct thread_master *master, char *lm_zserv_path)
-{
- frr_zclient_addr(&zclient_addr, &zclient_addr_len, lm_zserv_path);
-
- zclient = zclient_new(master, &zclient_options_default);
- /* zclient_init(zclient, ZEBRA_LABEL_MANAGER, 0); */
- zclient->sock = -1;
- zclient->redist_default = ZEBRA_ROUTE_LDP;
- zclient->instance = instance;
- if (zclient_socket_connect(zclient) < 0) {
- printf("Error connecting synchronous zclient!\n");
- exit(1);
- }
-}
-
-int main(int argc, char *argv[])
-{
- struct thread_master *master;
- struct thread thread;
- int ret;
-
- printf("Sequence to be tested: %s\n", sequence);
-
- master = thread_master_create(NULL);
- init_zclient(master, ZSERV_PATH);
-
- zebra_send_label_manager_connect();
-
- return 0;
-}
diff --git a/tests/topotests/lm-proxy-topo1/ce1/bgpd.conf b/tests/topotests/lm-proxy-topo1/ce1/bgpd.conf
deleted file mode 100644
index 33cb3d3209..0000000000
--- a/tests/topotests/lm-proxy-topo1/ce1/bgpd.conf
+++ /dev/null
@@ -1,9 +0,0 @@
-debug bgp vpn label
-!
-router bgp 9101
- bgp router-id 10.1.1.2
- neighbor 10.1.1.1 remote-as 7777
- address-family ipv4 unicast
- redistribute connected
- exit-address-family
-!
diff --git a/tests/topotests/lm-proxy-topo1/ce1/zebra.conf b/tests/topotests/lm-proxy-topo1/ce1/zebra.conf
deleted file mode 100644
index 7118cc6b88..0000000000
--- a/tests/topotests/lm-proxy-topo1/ce1/zebra.conf
+++ /dev/null
@@ -1,11 +0,0 @@
-debug zebra events
-debug zebra packet
-!
-interface lo
- ip address 66.1.0.1/32
-!
-interface ce1-eth0
- ip address 10.1.1.2/30
-!
-ip forwarding
-!
diff --git a/tests/topotests/lm-proxy-topo1/ce2/bgpd.conf b/tests/topotests/lm-proxy-topo1/ce2/bgpd.conf
deleted file mode 100644
index 358be342a4..0000000000
--- a/tests/topotests/lm-proxy-topo1/ce2/bgpd.conf
+++ /dev/null
@@ -1,9 +0,0 @@
-debug bgp vpn label
-!
-router bgp 9102
- bgp router-id 10.1.2.2
- neighbor 10.1.2.1 remote-as 7777
- address-family ipv4 unicast
- redistribute connected
- exit-address-family
-!
diff --git a/tests/topotests/lm-proxy-topo1/ce2/zebra.conf b/tests/topotests/lm-proxy-topo1/ce2/zebra.conf
deleted file mode 100644
index 8b4e3e31d7..0000000000
--- a/tests/topotests/lm-proxy-topo1/ce2/zebra.conf
+++ /dev/null
@@ -1,11 +0,0 @@
-debug zebra events
-debug zebra packet
-!
-interface lo
- ip address 66.1.0.2/32
-!
-interface ce2-eth0
- ip address 10.1.2.2/30
-!
-ip forwarding
-!
diff --git a/tests/topotests/lm-proxy-topo1/lm-proxy-topo1.dot b/tests/topotests/lm-proxy-topo1/lm-proxy-topo1.dot
deleted file mode 100644
index 71e6f34ba0..0000000000
--- a/tests/topotests/lm-proxy-topo1/lm-proxy-topo1.dot
+++ /dev/null
@@ -1,102 +0,0 @@
-## Color coding:
-#########################
-## Main FRR: #f08080 red
-## Switches: #d0e0d0 gray
-## RIP: #19e3d9 Cyan
-## RIPng: #fcb314 dark yellow
-## OSPFv2: #32b835 Green
-## OSPFv3: #19e3d9 Cyan
-## ISIS IPv4 #fcb314 dark yellow
-## ISIS IPv6 #9a81ec purple
-## BGP IPv4 #eee3d3 beige
-## BGP IPv6 #fdff00 yellow
-##### Colors (see http://www.color-hex.com/)
-
-graph template {
- label="Test Topology - Label Manager proxy";
-
- # Routers
-
- lm [ shape=doubleoctagon,
- label="label manager",
- fillcolor="#f08080",
- style=filled
- ];
- ce1 [
- shape=doubleoctagon,
- label="ce1",
- fillcolor="#f08080",
- style=filled
- ];
- ce2 [
- shape=doubleoctagon
- label="ce2",
- fillcolor="#f08080",
- style=filled
- ];
- pe1 [
- shape=doubleoctagon,
- label="pe1",
- fillcolor="#f08080",
- style=filled
- ];
- pe2 [
- shape=doubleoctagon
- label="pe2",
- fillcolor="#f08080",
- style=filled
- ];
- p1 [
- shape=doubleoctagon
- label="p1",
- fillcolor="#f08080",
- style=filled
- ];
-
- # Switches
-
- s1 [
- shape=oval,
- label="s1\n10.1.1.0/30",
- fillcolor="#d0e0d0",
- style=filled
- ];
- s2 [
- shape=oval,
- label="s2\n77.0.1.0/24",
- fillcolor="#d0e0d0",
- style=filled
- ];
- s3 [
- shape=oval,
- label="s3\n77.0.2.0/24",
- fillcolor="#d0e0d0",
- style=filled
- ];
- s4 [
- shape=oval,
- label="s4\n10.1.2.0/30",
- fillcolor="#d0e0d0",
- style=filled
- ];
-
- # Connections
-
- ce1 -- s1 [label="eth0\n.2"];
- pe1 -- s1 [label="eth0\n.1"];
-
- pe1 -- s2 [label="eth1\n.1"];
- p1 -- s2 [label="eth0\n.2"];
-
- pe2 -- s3 [label="eth1\n.1"];
- p1 -- s3 [label="eth1\n.2"];
-
- ce2 -- s4 [label="eth0\n.2"];
- pe2 -- s4 [label="eth0\n.1"];
-
- lm -- ce1;
- lm -- pe1;
- lm -- p1;
- lm -- pe2;
- lm -- ce2;
-}
diff --git a/tests/topotests/lm-proxy-topo1/lm-proxy-topo1.pdf b/tests/topotests/lm-proxy-topo1/lm-proxy-topo1.pdf
deleted file mode 100644
index 7f7e09ed09..0000000000
--- a/tests/topotests/lm-proxy-topo1/lm-proxy-topo1.pdf
+++ /dev/null
Binary files differ
diff --git a/tests/topotests/lm-proxy-topo1/lm/zebra.conf b/tests/topotests/lm-proxy-topo1/lm/zebra.conf
deleted file mode 100644
index 3c14f3bb3a..0000000000
--- a/tests/topotests/lm-proxy-topo1/lm/zebra.conf
+++ /dev/null
@@ -1,3 +0,0 @@
-debug zebra events
-debug zebra packet
-!
diff --git a/tests/topotests/lm-proxy-topo1/p1/ldpd.conf b/tests/topotests/lm-proxy-topo1/p1/ldpd.conf
deleted file mode 100644
index f86c47e6cc..0000000000
--- a/tests/topotests/lm-proxy-topo1/p1/ldpd.conf
+++ /dev/null
@@ -1,9 +0,0 @@
-!
-mpls ldp
- router-id 7.0.0.101
- address-family ipv4
- discovery transport-address 7.0.0.101
- interface p1-eth0
- interface p1-eth1
- exit-address-family
-!
diff --git a/tests/topotests/lm-proxy-topo1/p1/ospfd.conf b/tests/topotests/lm-proxy-topo1/p1/ospfd.conf
deleted file mode 100644
index 721426cb15..0000000000
--- a/tests/topotests/lm-proxy-topo1/p1/ospfd.conf
+++ /dev/null
@@ -1,7 +0,0 @@
-!
-router ospf
- ospf router-id 7.0.0.101
- network 7.0.0.101/32 area 0
- network 77.0.1.0/24 area 0
- network 77.0.2.0/24 area 0
-!
diff --git a/tests/topotests/lm-proxy-topo1/p1/zebra.conf b/tests/topotests/lm-proxy-topo1/p1/zebra.conf
deleted file mode 100644
index bb2fc2f96e..0000000000
--- a/tests/topotests/lm-proxy-topo1/p1/zebra.conf
+++ /dev/null
@@ -1,12 +0,0 @@
-debug zebra events
-debug zebra packet
-!
-interface lo
- ip address 7.0.0.101/32
-!
-interface p1-eth0
- ip address 77.0.1.2/24
-!
-interface p1-eth1
- ip address 77.0.2.2/24
-!
diff --git a/tests/topotests/lm-proxy-topo1/pe1/bgpd.conf b/tests/topotests/lm-proxy-topo1/pe1/bgpd.conf
deleted file mode 100644
index b9bab30c30..0000000000
--- a/tests/topotests/lm-proxy-topo1/pe1/bgpd.conf
+++ /dev/null
@@ -1,26 +0,0 @@
-debug bgp vpn label
-!
-router bgp 7777
- bgp router-id 7.0.0.1
- neighbor 7.0.0.2 remote-as 7777
- neighbor 7.0.0.2 update-source 7.0.0.1
- address-family ipv4 unicast
- no neighbor 7.0.0.2 activate
- exit-address-family
- address-family ipv4 vpn
- neighbor 7.0.0.2 activate
- exit-address-family
-!
-router bgp 7777 vrf A
- bgp router-id 10.1.1.1
- neighbor 10.1.1.2 remote-as 9101
- address-family ipv4 unicast
- label vpn export auto
- rd vpn export 110:1
- rt vpn both 152:100
- import vpn
- export vpn
- redistribute connected
- redistribute ospf
- exit-address-family
-!
diff --git a/tests/topotests/lm-proxy-topo1/pe1/ldpd.conf b/tests/topotests/lm-proxy-topo1/pe1/ldpd.conf
deleted file mode 100644
index 1b11f19fd3..0000000000
--- a/tests/topotests/lm-proxy-topo1/pe1/ldpd.conf
+++ /dev/null
@@ -1,8 +0,0 @@
-!
-mpls ldp
- router-id 7.0.0.1
- address-family ipv4
- discovery transport-address 7.0.0.1
- interface pe1-eth1
- exit-address-family
-!
diff --git a/tests/topotests/lm-proxy-topo1/pe1/ospfd.conf b/tests/topotests/lm-proxy-topo1/pe1/ospfd.conf
deleted file mode 100644
index 334c2547bf..0000000000
--- a/tests/topotests/lm-proxy-topo1/pe1/ospfd.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-!
-router ospf
- ospf router-id 7.0.0.1
- network 77.0.0.0/16 area 0
- redistribute connected
-!
diff --git a/tests/topotests/lm-proxy-topo1/pe1/zebra.conf b/tests/topotests/lm-proxy-topo1/pe1/zebra.conf
deleted file mode 100644
index ec1413234b..0000000000
--- a/tests/topotests/lm-proxy-topo1/pe1/zebra.conf
+++ /dev/null
@@ -1,14 +0,0 @@
-debug zebra events
-debug zebra packet
-!
-interface lo
- ip address 7.0.0.1/32
-!
-interface pe1-eth0 vrf A
- ip address 10.1.1.1/30
-!
-interface pe1-eth1
- ip address 77.0.1.1/24
-!
-ip forwarding
-!
diff --git a/tests/topotests/lm-proxy-topo1/pe2/bgpd.conf b/tests/topotests/lm-proxy-topo1/pe2/bgpd.conf
deleted file mode 100644
index f1ec2a48e8..0000000000
--- a/tests/topotests/lm-proxy-topo1/pe2/bgpd.conf
+++ /dev/null
@@ -1,26 +0,0 @@
-debug bgp vpn label
-!
-router bgp 7777
- bgp router-id 7.0.0.2
- neighbor 7.0.0.1 remote-as 7777
- neighbor 7.0.0.1 update-source 7.0.0.2
- address-family ipv4 unicast
- no neighbor 7.0.0.1 activate
- exit-address-family
- address-family ipv4 vpn
- neighbor 7.0.0.1 activate
- exit-address-family
-!
-router bgp 7777 vrf A
- bgp router-id 10.1.2.1
- neighbor 10.1.2.2 remote-as 9102
- address-family ipv4 unicast
- label vpn export auto
- rd vpn export 110:2
- rt vpn both 152:100
- import vpn
- export vpn
- redistribute connected
- redistribute ospf
- exit-address-family
-!
diff --git a/tests/topotests/lm-proxy-topo1/pe2/ldpd.conf b/tests/topotests/lm-proxy-topo1/pe2/ldpd.conf
deleted file mode 100644
index 727364fe9f..0000000000
--- a/tests/topotests/lm-proxy-topo1/pe2/ldpd.conf
+++ /dev/null
@@ -1,8 +0,0 @@
-!
-mpls ldp
- router-id 7.0.0.2
- address-family ipv4
- discovery transport-address 7.0.0.2
- interface pe2-eth1
- exit-address-family
-!
diff --git a/tests/topotests/lm-proxy-topo1/pe2/ospfd.conf b/tests/topotests/lm-proxy-topo1/pe2/ospfd.conf
deleted file mode 100644
index 068de09a98..0000000000
--- a/tests/topotests/lm-proxy-topo1/pe2/ospfd.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-!
-router ospf
- ospf router-id 7.0.0.2
- network 77.0.0.0/16 area 0
- redistribute connected
-!
diff --git a/tests/topotests/lm-proxy-topo1/pe2/zebra.conf b/tests/topotests/lm-proxy-topo1/pe2/zebra.conf
deleted file mode 100644
index 0302fd8018..0000000000
--- a/tests/topotests/lm-proxy-topo1/pe2/zebra.conf
+++ /dev/null
@@ -1,14 +0,0 @@
-debug zebra events
-debug zebra packet
-!
-interface lo
- ip address 7.0.0.2/32
-!
-interface pe2-eth1
- ip address 77.0.2.1/24
-!
-interface pe2-eth0 vrf A
- ip address 10.1.2.1/30
-!
-ip forwarding
-!
diff --git a/tests/topotests/lm-proxy-topo1/test_lm-proxy-topo1.py b/tests/topotests/lm-proxy-topo1/test_lm-proxy-topo1.py
deleted file mode 100644
index 7acbb1ee62..0000000000
--- a/tests/topotests/lm-proxy-topo1/test_lm-proxy-topo1.py
+++ /dev/null
@@ -1,205 +0,0 @@
-#!/usr/bin/env python
-
-#
-# test_lm-proxy-topo1.py
-# Part of NetDEF Topology Tests
-#
-# Copyright (c) 2018 by Volta Networks, Inc.
-#
-# Requirements, so the test is not skipped:
-# - Linux kernel with VRF support
-# - 'ip' command with VRF support (e.g. iproute2-ss180129 works)
-# - FRR BGP daemon supporting label manager using instance id
-#
-# Permission to use, copy, modify, and/or distribute this software
-# for any purpose with or without fee is hereby granted, provided
-# that the above copyright notice and this permission notice appear
-# in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
-# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
-# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
-# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
-# OF THIS SOFTWARE.
-#
-
-import os
-import sys
-import pytest
-
-from functools import partial
-
-# Save the Current Working Directory to find configuration files.
-CWD = os.path.dirname(os.path.realpath(__file__))
-sys.path.append(os.path.join(CWD, '../'))
-
-# pylint: disable=C0413
-# Import topogen and topotest helpers
-from lib import topotest
-from lib.topogen import Topogen, TopoRouter, get_topogen
-from lib.topolog import logger
-
-# Required to instantiate the topology builder class.
-from mininet.topo import Topo
-
-vrf_name = 'A'
-
-class NetworkTopo(Topo):
- "Label Manager proxy topology"
-
- # Relationship between routers, switches, and hosts
- def build(self, *_args, **_opts):
- "Build function"
-
- tgen = get_topogen(self)
-
- # FRR routers
-
- for router in ['lm', 'ce1', 'pe1', 'p1', 'pe2', 'ce2']:
- tgen.add_router(router);
-
- # Connections
-
- switch = tgen.add_switch('s1')
- switch.add_link(tgen.gears['ce1'], nodeif='ce1-eth0')
- switch.add_link(tgen.gears['pe1'], nodeif='pe1-eth0')
-
- switch = tgen.add_switch('s2')
- switch.add_link(tgen.gears['pe1'], nodeif='pe1-eth1')
- switch.add_link(tgen.gears['p1'], nodeif='p1-eth0')
-
- switch = tgen.add_switch('s3')
- switch.add_link(tgen.gears['p1'], nodeif='p1-eth1')
- switch.add_link(tgen.gears['pe2'], nodeif='pe2-eth1')
-
- switch = tgen.add_switch('s4')
- switch.add_link(tgen.gears['ce2'], nodeif='ce2-eth0')
- switch.add_link(tgen.gears['pe2'], nodeif='pe2-eth0')
-
-# Test environment handling
-
-def vrf_destroy(router, vrf):
- router.run('ip link delete dev ' + vrf)
-
-def vrf_setup(router, eth_in, vrf, vrf_table):
- cmds = ['ip link set dev lo up',
- 'echo 10000 > /proc/sys/net/mpls/platform_labels',
- 'ip link add dev ' + vrf + ' type vrf table ' + vrf_table,
- 'ip link set ' + vrf + ' up',
- 'ip link set ' + eth_in + ' vrf ' + vrf,
- 'echo 1 > /proc/sys/net/mpls/conf/' + vrf + '/input'
- ]
- vrf_destroy(router, vrf)
- for cmd in cmds:
- logger.info('[vrf_setup] cmd: ' + cmd)
- out = router.run(cmd)
- if out != None and len(out) > 0:
- logger.info('[vrf_setup] "{}" error: out="{}"'.format(cmd, out))
-
-def setup_module(mod):
- "pytest environment setup"
-
- tgen = Topogen(NetworkTopo, mod.__name__)
- tgen.start_topology()
-
- router_list = tgen.routers()
-
- # Load router configuration
-
- ldp_id = 1
- bgp_id = 101
- lm_sock = '../lm/label_mgr.sock'
-
- for rname, router in router_list.iteritems():
- if rname == 'lm' :
- router.load_config(
- TopoRouter.RD_ZEBRA,
- os.path.join(CWD, '{}/zebra.conf'.format(rname)),
- '-z ' + lm_sock
- )
- continue
-
- rtype = ''.join([i for i in rname if not i.isdigit()])
-
- router.load_config(
- TopoRouter.RD_ZEBRA,
- os.path.join(CWD, '{}/zebra.conf'.format(rname)),
- '-l ' + lm_sock
- )
-
- if router.check_capability(TopoRouter.RD_ZEBRA, '--vrfwnetns') == False:
- return pytest.skip('Skipping test: no VRF support')
-
- if rtype == 'ce' or rtype == 'pe':
- if router.check_capability(TopoRouter.RD_BGP, '--int_num') == False:
- return pytest.skip('Skipping test: no BGP LM support')
- router.load_config(
- TopoRouter.RD_BGP,
- os.path.join(CWD, '{}/bgpd.conf'.format(rname)),
- '-I %d' % bgp_id
- )
- bgp_id += 1
-
- if rtype == 'pe' or rtype == 'p':
- router.load_config(
- TopoRouter.RD_OSPF,
- os.path.join(CWD, '{}/ospfd.conf'.format(rname))
- )
- router.load_config(
- TopoRouter.RD_LDP,
- os.path.join(CWD, '{}/ldpd.conf'.format(rname)),
- '-n %d' % ldp_id
- )
- ldp_id += 1
-
- # Prepare VRF's
-
- router = tgen.gears['pe1']
- out = router.run('ip -h 2>&1 | grep vrf | wc -l')
- if int(out) == 0:
- return pytest.skip('Skipping test: ip/iproute2 has no VRF support')
-
- vrf_setup(tgen.gears['pe1'], 'pe1-eth0', vrf_name, '1')
- vrf_setup(tgen.gears['pe2'], 'pe2-eth0', vrf_name, '1')
-
- # Start routers
-
- tgen.start_router(tgen.gears['lm'])
- for rname, router in router_list.iteritems():
- if rname != 'lm':
- tgen.start_router(router)
-
-def teardown_module(mod):
- tgen = get_topogen()
- for router in ['pe1', 'pe2']:
- vrf_destroy(tgen.gears[router], vrf_name)
- tgen.stop_topology()
-
-def test_lm_proxy():
- logger.info('Test: label manager (LDP and BGP)')
- tgen = get_topogen()
-
- # Skip if previous fatal error condition is raised
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- cmd = 'show mpls ldp binding'
-
- router = tgen.gears['p1']
-
- def check_labels(router, cmd):
- output = router.vtysh_cmd(cmd, isjson=False)
- logger.info('chk_labels [' + cmd + ']: ' + output)
- return output.count('\n')
-
- test_func = partial(check_labels, router, cmd)
- result, diff = topotest.run_and_expect(test_func, 12, count=6, wait=30)
- assert result, 'wrong labels'
-
-if __name__ == '__main__':
- args = ["-s"] + sys.argv[1:]
- sys.exit(pytest.main(args))
-
diff --git a/vtysh/vtysh_config.c b/vtysh/vtysh_config.c
index 4ae1e499ff..1e45e6f972 100644
--- a/vtysh/vtysh_config.c
+++ b/vtysh/vtysh_config.c
@@ -265,7 +265,8 @@ void vtysh_config_parse_line(void *arg, const char *line)
|| config->index == INTERFACE_NODE
|| config->index == LOGICALROUTER_NODE
|| config->index == VTY_NODE
- || config->index == VRF_NODE)
+ || config->index == VRF_NODE
+ || config->index == NH_GROUP_NODE)
config_add_line_uniq(config->line, line);
else
config_add_line(config->line, line);
diff --git a/yang/frr-isisd.yang b/yang/frr-isisd.yang
index 7b132cb61e..05a896a1db 100644
--- a/yang/frr-isisd.yang
+++ b/yang/frr-isisd.yang
@@ -756,6 +756,12 @@ module frr-isisd {
"IS-type of this circuit.";
}
+ leaf bfd-monitoring {
+ type boolean;
+ default false;
+ description "Monitor IS-IS peers on this circuit.";
+ }
+
container csnp-interval {
description
"Complete Sequence Number PDU (CSNP) generation interval.";
diff --git a/zebra/interface.c b/zebra/interface.c
index 719cf05db1..4eec435f1c 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -69,6 +69,7 @@ static int if_zebra_speed_update(struct thread *thread)
struct interface *ifp = THREAD_ARG(thread);
struct zebra_if *zif = ifp->info;
uint32_t new_speed;
+ bool changed = false;
zif->speed_update = NULL;
@@ -79,8 +80,12 @@ static int if_zebra_speed_update(struct thread *thread)
new_speed);
ifp->speed = new_speed;
if_add_update(ifp);
+ changed = true;
}
+ if (changed || new_speed == UINT32_MAX)
+ thread_add_timer(zrouter.master, if_zebra_speed_update, ifp, 5,
+ &zif->speed_update);
return 1;
}
diff --git a/zebra/label_manager.c b/zebra/label_manager.c
index 8295e461cc..03cfa572db 100644
--- a/zebra/label_manager.c
+++ b/zebra/label_manager.c
@@ -38,295 +38,65 @@
#include "zebra/zebra_router.h"
#include "zebra/label_manager.h"
#include "zebra/zebra_errors.h"
+#include "zebra/zapi_msg.h"
#define CONNECTION_DELAY 5
struct label_manager lbl_mgr;
-extern struct zebra_privs_t zserv_privs;
-
DEFINE_MGROUP(LBL_MGR, "Label Manager");
DEFINE_MTYPE_STATIC(LBL_MGR, LM_CHUNK, "Label Manager Chunk");
-/* In case this zebra daemon is not acting as label manager,
- * it will be a proxy to relay messages to external label manager
- * This zclient thus is to connect to it
+/* define hooks for the basic API, so that it can be specialized or served
+ * externally
*/
-static struct stream *obuf;
-static struct zclient *zclient;
-bool lm_is_external;
-
-static void delete_label_chunk(void *val)
-{
- XFREE(MTYPE_LM_CHUNK, val);
-}
-
-static int relay_response_back(void)
-{
- int ret = 0;
- struct stream *src, *dst;
- uint16_t size = 0;
- uint8_t marker;
- uint8_t version;
- vrf_id_t vrf_id;
- uint16_t resp_cmd;
- uint8_t proto;
- const char *proto_str;
- unsigned short instance;
- struct zserv *zserv;
-
- /* sanity */
- if (!zclient || zclient->sock < 0)
- return -1;
-
- /* input buffer with msg from label manager */
- src = zclient->ibuf;
-
- stream_reset(src);
-
- /* parse header */
- ret = zclient_read_header(src, zclient->sock, &size, &marker, &version,
- &vrf_id, &resp_cmd);
- if (ret < 0) {
- if (errno != EAGAIN)
- flog_err(EC_ZEBRA_LM_RESPONSE,
- "Error reading Label Manager response: %s",
- strerror(errno));
- return -1;
- }
-
- /* do not relay a msg that has nothing to do with LM */
- switch (resp_cmd) {
- case ZEBRA_LABEL_MANAGER_CONNECT:
- case ZEBRA_LABEL_MANAGER_CONNECT_ASYNC: /* should not be seen */
- case ZEBRA_GET_LABEL_CHUNK:
- case ZEBRA_RELEASE_LABEL_CHUNK:
- break;
- default:
- zlog_debug("Not relaying '%s' response (size %d) from LM",
- zserv_command_string(resp_cmd), size);
- return -1;
- }
-
- zlog_debug("Received '%s' response (size %d) from LM",
- zserv_command_string(resp_cmd), size);
-
- if (size == 0)
- return -1;
-
- /* Get the 'proto' field of the message */
- proto = stream_getc(src);
-
- /* Get the 'instance' field of the message */
- instance = stream_getw(src);
-
- proto_str = zebra_route_string(proto);
-
- /* lookup the client to relay the msg to */
- zserv = zserv_find_client(proto, instance);
- if (!zserv) {
- flog_err(
- EC_ZEBRA_LM_NO_SUCH_CLIENT,
- "Error relaying LM response: can't find client %s, instance %u",
- proto_str, instance);
- return -1;
- }
- zlog_debug("Found client to relay LM response to client %s instance %u",
- proto_str, instance);
-
- /* copy msg into output buffer */
- dst = obuf;
- stream_copy(dst, src);
-
- /* send response back */
- ret = writen(zserv->sock, dst->data, stream_get_endp(dst));
- if (ret <= 0) {
- flog_err(EC_ZEBRA_LM_RELAY_FAILED,
- "Error relaying LM response to %s instance %u: %s",
- proto_str, instance, strerror(errno));
- return -1;
- }
- zlog_debug("Relayed LM response (%d bytes) to %s instance %u", ret,
- proto_str, instance);
- return 0;
-}
-
-static int lm_zclient_read(struct thread *t)
+DEFINE_HOOK(lm_client_connect,
+ (uint8_t proto, uint16_t instance, vrf_id_t vrf_id),
+ (proto, instance, vrf_id));
+DEFINE_HOOK(lm_client_disconnect, (uint8_t proto, uint16_t instance),
+ (proto, instance));
+DEFINE_HOOK(lm_get_chunk,
+ (struct label_manager_chunk * *lmc, uint8_t proto,
+ uint16_t instance, uint8_t keep, uint32_t size, uint32_t base,
+ vrf_id_t vrf_id),
+ (lmc, proto, instance, keep, size, base, vrf_id));
+DEFINE_HOOK(lm_release_chunk,
+ (uint8_t proto, uint16_t instance, uint32_t start, uint32_t end),
+ (proto, instance, start, end));
+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)
+ */
+void lm_client_connect_call(uint8_t proto, uint16_t instance, vrf_id_t vrf_id)
{
- int ret;
-
- zclient->t_read = NULL;
-
- /* read response and send it back */
- ret = relay_response_back();
-
- /* re-arm read */
- thread_add_read(zclient->master, lm_zclient_read, NULL,
- zclient->sock, &zclient->t_read);
- return ret;
+ hook_call(lm_client_connect, proto, instance, vrf_id);
}
-
-static int reply_error(int cmd, struct zserv *zserv, vrf_id_t vrf_id)
+void lm_get_chunk_call(struct label_manager_chunk **lmc, uint8_t proto,
+ uint16_t instance, uint8_t keep, uint32_t size,
+ uint32_t base, vrf_id_t vrf_id)
{
- int ret;
- struct stream *s;
-
- s = stream_new(ZEBRA_MAX_PACKET_SIZ);
-
- zclient_create_header(s, cmd, vrf_id);
-
- /* proto */
- stream_putc(s, zserv->proto);
- /* instance */
- stream_putw(s, zserv->instance);
- /* result */
- stream_putc(s, 1);
-
- /* Write packet size. */
- stream_putw_at(s, 0, stream_get_endp(s));
-
- ret = writen(zserv->sock, s->data, stream_get_endp(s));
-
- stream_free(s);
- return ret;
+ hook_call(lm_get_chunk, lmc, proto, instance, keep, size, base, vrf_id);
}
-/**
- * Receive a request to get or release a label chunk and forward it to external
- * label manager.
- *
- * It's called from zserv in case it's not an actual label manager, but just a
- * proxy.
- *
- * @param cmd Type of request (connect, get or release)
- * @param zserv
- * @return 0 on success, -1 otherwise
- */
-int zread_relay_label_manager_request(int cmd, struct zserv *zserv,
- struct stream *msg, vrf_id_t vrf_id)
+void lm_release_chunk_call(uint8_t proto, uint16_t instance, uint32_t start,
+ uint32_t end)
{
- struct stream *dst;
- int ret = 0;
- uint8_t proto;
- const char *proto_str;
- unsigned short instance;
-
- if (zclient->sock < 0) {
- flog_err(EC_ZEBRA_LM_NO_SOCKET,
- "Unable to relay LM request: no socket");
- reply_error(cmd, zserv, vrf_id);
- return -1;
- }
-
- /* peek msg to get proto and instance id. This zebra, which acts as
- * a proxy needs to have such values for each client in order to
- * relay responses back to it.
- */
-
- /* Get the 'proto' field of incoming msg */
- proto = stream_getc(msg);
-
- /* Get the 'instance' field of incoming msg */
- instance = stream_getw(msg);
-
- /* stringify proto */
- proto_str = zebra_route_string(proto);
-
- /* check & set client proto if unset */
- if (zserv->proto && zserv->proto != proto) {
- flog_warn(EC_ZEBRAING_LM_PROTO_MISMATCH,
- "Client proto(%u) != msg proto(%u)", zserv->proto,
- proto);
- return -1;
- }
-
- /* check & set client instance if unset */
- if (zserv->instance && zserv->instance != instance) {
- flog_err(EC_ZEBRA_LM_BAD_INSTANCE,
- "Client instance(%u) != msg instance(%u)",
- zserv->instance, instance);
- return -1;
- }
-
- /* recall proto and instance */
- zserv->instance = instance;
- zserv->proto = proto;
-
- /* in case there's any incoming message enqueued, read and forward it */
- if (zserv->is_synchronous)
- while (ret == 0)
- ret = relay_response_back();
-
- /* get the msg buffer used toward the 'master' Label Manager */
- dst = zclient->obuf;
-
- /* copy the message */
- stream_copy(dst, msg);
-
- /* Send request to external label manager */
- ret = writen(zclient->sock, dst->data, stream_get_endp(dst));
- if (ret <= 0) {
- flog_err(EC_ZEBRA_LM_RELAY_FAILED,
- "Error relaying LM request from %s instance %u: %s",
- proto_str, instance, strerror(errno));
- reply_error(cmd, zserv, vrf_id);
- return -1;
- }
- zlog_debug("Relayed LM request (%d bytes) from %s instance %u", ret,
- proto_str, instance);
-
-
- /* Release label chunk has no response */
- if (cmd == ZEBRA_RELEASE_LABEL_CHUNK)
- return 0;
-
- /* make sure we listen to the response */
- if (!zclient->t_read)
- thread_add_read(zclient->master, lm_zclient_read, NULL,
- zclient->sock, &zclient->t_read);
-
- return 0;
+ hook_call(lm_release_chunk, proto, instance, start, end);
}
-static int lm_zclient_connect(struct thread *t)
-{
- zclient->t_connect = NULL;
-
- if (zclient->sock >= 0)
- return 0;
-
- if (zclient_socket_connect(zclient) < 0) {
- flog_err(EC_ZEBRA_LM_CLIENT_CONNECTION_FAILED,
- "Error connecting synchronous zclient!");
- thread_add_timer(zrouter.master, lm_zclient_connect, zclient,
- CONNECTION_DELAY, &zclient->t_connect);
- return -1;
- }
-
- /* make socket non-blocking */
- (void)set_nonblocking(zclient->sock);
+/* forward declarations of the static functions to be used for some hooks */
+static int label_manager_connect(uint8_t proto, uint16_t instance,
+ vrf_id_t vrf_id);
+static int label_manager_disconnect(uint8_t proto, uint16_t instance);
+static int label_manager_get_chunk(struct label_manager_chunk **lmc,
+ uint8_t proto, uint16_t instance,
+ uint8_t keep, uint32_t size, uint32_t base,
+ vrf_id_t vrf_id);
- return 0;
-}
-
-/**
- * Function to initialize zclient in case this is not an actual
- * label manager, but just a proxy to an external one.
- *
- * @param lm_zserv_path Path to zserv socket of external label manager
- */
-static void lm_zclient_init(char *lm_zserv_path)
+void delete_label_chunk(void *val)
{
- if (lm_zserv_path)
- frr_zclient_addr(&zclient_addr, &zclient_addr_len,
- lm_zserv_path);
-
- /* Set default values. */
- zclient = zclient_new(zrouter.master, &zclient_options_default);
- zclient->privs = &zserv_privs;
- zclient->sock = -1;
- zclient->t_connect = NULL;
- lm_zclient_connect(NULL);
+ XFREE(MTYPE_LM_CHUNK, val);
}
/**
@@ -339,15 +109,16 @@ static void lm_zclient_init(char *lm_zserv_path)
* @param instance Instance, to identify the owner
* @return Number of chunks released
*/
-int release_daemon_label_chunks(struct zserv *client)
+int release_daemon_label_chunks(uint8_t proto, unsigned short instance)
{
- uint8_t proto = client->proto;
- uint16_t instance = client->instance;
struct listnode *node;
struct label_manager_chunk *lmc;
int count = 0;
int ret;
+ zlog_debug("%s: Releasing chunks for client proto %s, instance %d",
+ __func__, zebra_route_string(proto), instance);
+
for (ALL_LIST_ELEMENTS_RO(lbl_mgr.lc_list, node, lmc)) {
if (lmc->proto == proto && lmc->instance == instance
&& lmc->keep == 0) {
@@ -363,31 +134,153 @@ int release_daemon_label_chunks(struct zserv *client)
return count;
}
+int lm_client_disconnect_cb(struct zserv *client)
+{
+ uint8_t proto = client->proto;
+ uint16_t instance = client->instance;
+
+ hook_call(lm_client_disconnect, proto, instance);
+ return 0;
+}
+
+void lm_hooks_register(void)
+{
+ hook_register(lm_client_connect, label_manager_connect);
+ hook_register(lm_client_disconnect, label_manager_disconnect);
+ hook_register(lm_get_chunk, label_manager_get_chunk);
+ hook_register(lm_release_chunk, release_label_chunk);
+}
+void lm_hooks_unregister(void)
+{
+ hook_unregister(lm_client_connect, label_manager_connect);
+ hook_unregister(lm_client_disconnect, label_manager_disconnect);
+ hook_unregister(lm_get_chunk, label_manager_get_chunk);
+ hook_unregister(lm_release_chunk, release_label_chunk);
+}
+
/**
* Init label manager (or proxy to an external one)
*/
-void label_manager_init(char *lm_zserv_path)
+void label_manager_init(void)
+{
+ lbl_mgr.lc_list = list_new();
+ lbl_mgr.lc_list->del = delete_label_chunk;
+ hook_register(zserv_client_close, lm_client_disconnect_cb);
+
+ /* register default hooks for the label manager actions */
+ lm_hooks_register();
+
+ /* notify any external module that we are done */
+ hook_call(lm_cbs_inited);
+}
+
+/* alloc and fill a label chunk */
+struct label_manager_chunk *create_label_chunk(uint8_t proto,
+ unsigned short instance,
+ uint8_t keep, uint32_t start,
+ uint32_t end)
+{
+ /* alloc chunk, fill it and return it */
+ struct label_manager_chunk *lmc =
+ XCALLOC(MTYPE_LM_CHUNK, sizeof(struct label_manager_chunk));
+
+ lmc->start = start;
+ lmc->end = end;
+ lmc->proto = proto;
+ lmc->instance = instance;
+ lmc->keep = keep;
+
+ return lmc;
+}
+
+/* attempt to get a specific label chunk */
+static struct label_manager_chunk *
+assign_specific_label_chunk(uint8_t proto, unsigned short instance,
+ uint8_t keep, uint32_t size, uint32_t base)
{
- /* this is an actual label manager */
- if (!lm_zserv_path) {
- zlog_debug("Initializing internal label manager");
- lm_is_external = false;
- lbl_mgr.lc_list = list_new();
- lbl_mgr.lc_list->del = delete_label_chunk;
- } else { /* it's acting just as a proxy */
- zlog_debug("Initializing external label manager at %s",
- lm_zserv_path);
- lm_is_external = true;
- lm_zclient_init(lm_zserv_path);
+ struct label_manager_chunk *lmc;
+ struct listnode *node, *next = NULL;
+ struct listnode *first_node = NULL;
+ struct listnode *last_node = NULL;
+ struct listnode *insert_node = NULL;
+
+ /* precompute last label from base and size */
+ uint32_t end = base + size - 1;
+
+ /* sanities */
+ if ((base < MPLS_LABEL_UNRESERVED_MIN)
+ || (end > MPLS_LABEL_UNRESERVED_MAX)) {
+ zlog_err("Invalid LM request arguments: base: %u, size: %u",
+ base, size);
+ 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)) {
+
+ /* skip chunks for labels < base */
+ if (base > lmc->end)
+ continue;
+
+ /* requested range is not covered by any existing, free chunk.
+ * Therefore, need to insert a chunk */
+ if ((end < lmc->start) && !first_node) {
+ insert_node = node;
+ break;
+ }
+
+ if (!first_node)
+ first_node = node;
+
+ /* if chunk is used, cannot honor request */
+ if (lmc->proto != NO_PROTO)
+ return NULL;
+
+ if (end < lmc->end) {
+ last_node = node;
+ break;
+ }
+ }
+
+ /* insert chunk between existing chunks */
+ if (insert_node) {
+ lmc = create_label_chunk(proto, instance, keep, base, end);
+ listnode_add_before(lbl_mgr.lc_list, insert_node, lmc);
+ return lmc;
}
- obuf = stream_new(ZEBRA_MAX_PACKET_SIZ);
+ if (first_node) {
+ /* get node past the last one, if there */
+ if (last_node)
+ last_node = listnextnode(last_node);
+
+ /* delete node coming after the above chunk whose labels are
+ * included in the previous one */
+ for (node = first_node; node && (node != last_node);
+ node = next) {
+ next = listnextnode(node);
+ list_delete_node(lbl_mgr.lc_list, node);
+ }
- hook_register(zserv_client_close, release_daemon_label_chunks);
+ lmc = create_label_chunk(proto, instance, keep, base, end);
+ if (last_node)
+ listnode_add_before(lbl_mgr.lc_list, last_node, lmc);
+ else
+ listnode_add(lbl_mgr.lc_list, lmc);
+
+ return lmc;
+ } else {
+ /* create a new chunk past all the existing ones and link at
+ * tail */
+ lmc = create_label_chunk(proto, instance, keep, base, end);
+ listnode_add(lbl_mgr.lc_list, lmc);
+ return lmc;
+ }
}
/**
- * Core function, assigns label cunks
+ * Core function, assigns label chunks
*
* It first searches through the list to check if there's one available
* (previously released). Otherwise it creates and assigns a new one
@@ -395,15 +288,26 @@ void label_manager_init(char *lm_zserv_path)
* @param proto Daemon protocol of client, to identify the owner
* @param instance Instance, to identify the owner
* @param keep If set, avoid garbage collection
- * @para size Size of the label chunk
- * @return Pointer to the assigned label chunk
+ * @param size Size of the label chunk
+ * @param base Desired starting label of the chunk; if MPLS_LABEL_BASE_ANY it does not apply
+ * @return Pointer to the assigned label chunk, or NULL if the request could not be satisfied
*/
struct label_manager_chunk *assign_label_chunk(uint8_t proto,
unsigned short instance,
- uint8_t keep, uint32_t size)
+ uint8_t keep, uint32_t size,
+ uint32_t base)
{
struct label_manager_chunk *lmc;
struct listnode *node;
+ uint32_t prev_end = 0;
+
+ /* handle chunks request with a specific base label */
+ if (base != MPLS_LABEL_BASE_ANY)
+ return assign_specific_label_chunk(proto, instance, keep, size,
+ base);
+
+ /* appease scan-build, who gets confused by the use of macros */
+ assert(lbl_mgr.lc_list);
/* first check if there's one available */
for (ALL_LIST_ELEMENTS_RO(lbl_mgr.lc_list, node, lmc)) {
@@ -414,35 +318,44 @@ struct label_manager_chunk *assign_label_chunk(uint8_t proto,
lmc->keep = keep;
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)) {
+ lmc = create_label_chunk(proto, instance, keep,
+ prev_end + 1, prev_end + size);
+ listnode_add_before(lbl_mgr.lc_list, node, lmc);
+ return lmc;
+ }
+ prev_end = lmc->end;
}
/* otherwise create a new one */
- lmc = XCALLOC(MTYPE_LM_CHUNK, sizeof(struct label_manager_chunk));
+ uint32_t start_free;
if (list_isempty(lbl_mgr.lc_list))
- lmc->start = MPLS_LABEL_UNRESERVED_MIN;
+ start_free = MPLS_LABEL_UNRESERVED_MIN;
else
- lmc->start = ((struct label_manager_chunk *)listgetdata(
+ start_free = ((struct label_manager_chunk *)listgetdata(
listtail(lbl_mgr.lc_list)))
->end
+ 1;
- if (lmc->start > MPLS_LABEL_UNRESERVED_MAX - size + 1) {
+
+ if (start_free > MPLS_LABEL_UNRESERVED_MAX - size + 1) {
flog_err(EC_ZEBRA_LM_EXHAUSTED_LABELS,
- "Reached max labels. Start: %u, size: %u", lmc->start,
+ "Reached max labels. Start: %u, size: %u", start_free,
size);
- XFREE(MTYPE_LM_CHUNK, lmc);
return NULL;
}
- lmc->end = lmc->start + size - 1;
- lmc->proto = proto;
- lmc->instance = instance;
- lmc->keep = keep;
- listnode_add(lbl_mgr.lc_list, lmc);
+ /* create chunk and link at tail */
+ lmc = create_label_chunk(proto, instance, keep, start_free,
+ start_free + size - 1);
+ listnode_add(lbl_mgr.lc_list, lmc);
return lmc;
}
/**
- * Core function, release no longer used label cunks
+ * Core function, release no longer used label chunks
*
* @param proto Daemon protocol of client, to identify the owner
* @param instance Instance, to identify the owner
@@ -483,9 +396,59 @@ int release_label_chunk(uint8_t proto, unsigned short instance, uint32_t start,
return ret;
}
+/* default functions to be called on hooks */
+static int label_manager_connect(uint8_t proto, uint16_t instance,
+ vrf_id_t vrf_id)
+{
+ /*
+ * Release previous labels of same protocol and instance.
+ * This is done in case it restarted from an unexpected shutdown.
+ */
+ release_daemon_label_chunks(proto, instance);
+ return lm_client_connect_response(proto, instance, vrf_id, 0);
+}
+static int label_manager_disconnect(uint8_t proto, uint16_t instance)
+{
+ release_daemon_label_chunks(proto, instance);
+ return 0;
+}
+static int label_manager_get_chunk(struct label_manager_chunk **lmc,
+ uint8_t proto, uint16_t instance,
+ uint8_t keep, uint32_t size, uint32_t base,
+ vrf_id_t vrf_id)
+{
+ *lmc = assign_label_chunk(proto, instance, keep, size, base);
+ return lm_get_chunk_response(*lmc, proto, instance, vrf_id);
+}
+
+/* Respond to a connect request */
+int lm_client_connect_response(uint8_t proto, uint16_t instance,
+ vrf_id_t vrf_id, uint8_t result)
+{
+ struct zserv *client = zserv_find_client(proto, instance);
+ if (!client) {
+ zlog_err("%s: could not find client for daemon %s instance %u",
+ __func__, zebra_route_string(proto), instance);
+ return 1;
+ }
+ return zsend_label_manager_connect_response(client, vrf_id, result);
+}
+
+/* Respond to a get_chunk request */
+int lm_get_chunk_response(struct label_manager_chunk *lmc, uint8_t proto,
+ uint16_t instance, vrf_id_t vrf_id)
+{
+ struct zserv *client = zserv_find_client(proto, instance);
+ if (!client) {
+ zlog_err("%s: could not find client for daemon %s instance %u",
+ __func__, zebra_route_string(proto), instance);
+ return 1;
+ }
+ return zsend_assign_label_chunk_response(client, vrf_id, proto,
+ instance, lmc);
+}
void label_manager_close(void)
{
list_delete(&lbl_mgr.lc_list);
- stream_free(obuf);
}
diff --git a/zebra/label_manager.h b/zebra/label_manager.h
index 3ea89fbfc3..74e283e85e 100644
--- a/zebra/label_manager.h
+++ b/zebra/label_manager.h
@@ -28,6 +28,7 @@
#include "lib/linklist.h"
#include "lib/thread.h"
+#include "lib/hook.h"
#include "zebra/zserv.h"
@@ -57,6 +58,54 @@ struct label_manager_chunk {
uint32_t end; /* Last label of the chunk */
};
+/* declare hooks for the basic API, so that it can be specialized or served
+ * externally. Also declare a hook when those functions have been registered,
+ * so that any external module wanting to replace those can react
+ */
+
+DECLARE_HOOK(lm_client_connect,
+ (uint8_t proto, uint16_t instance, vrf_id_t vrf_id),
+ (proto, instance, vrf_id));
+DECLARE_HOOK(lm_client_disconnect, (uint8_t proto, uint16_t instance),
+ (proto, instance));
+DECLARE_HOOK(lm_get_chunk,
+ (struct label_manager_chunk * *lmc, uint8_t proto,
+ uint16_t instance, uint8_t keep, uint32_t size, uint32_t base,
+ vrf_id_t vrf_id),
+ (lmc, proto, instance, keep, size, base, vrf_id));
+DECLARE_HOOK(lm_release_chunk,
+ (uint8_t proto, uint16_t instance, uint32_t start, uint32_t end),
+ (proto, instance, start, end));
+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)
+ */
+void lm_client_connect_call(uint8_t proto, uint16_t instance, vrf_id_t vrf_id);
+void lm_get_chunk_call(struct label_manager_chunk **lmc, uint8_t proto,
+ uint16_t instance, uint8_t keep, uint32_t size,
+ uint32_t base, vrf_id_t vrf_id);
+void lm_release_chunk_call(uint8_t proto, uint16_t instance, uint32_t start,
+ uint32_t end);
+
+/* API for an external LM to return responses for requests */
+int lm_client_connect_response(uint8_t proto, uint16_t instance,
+ vrf_id_t vrf_id, uint8_t result);
+int lm_get_chunk_response(struct label_manager_chunk *lmc, uint8_t proto,
+ uint16_t instance, vrf_id_t vrf_id);
+
+/* convenience function to allocate an lmc to be consumed by the above API */
+struct label_manager_chunk *create_label_chunk(uint8_t proto,
+ unsigned short instance,
+ uint8_t keep, uint32_t start,
+ uint32_t end);
+void delete_label_chunk(void *val);
+
+/* register/unregister callbacks for hooks */
+void lm_hooks_register(void);
+void lm_hooks_unregister(void);
+
/*
* Main label manager struct
* Holds a linked list of label chunks.
@@ -65,17 +114,15 @@ struct label_manager {
struct list *lc_list;
};
-bool lm_is_external;
-
-int zread_relay_label_manager_request(int cmd, struct zserv *zserv,
- struct stream *msg, vrf_id_t vrf_id);
-void label_manager_init(char *lm_zserv_path);
+void label_manager_init(void);
struct label_manager_chunk *assign_label_chunk(uint8_t proto,
unsigned short instance,
- uint8_t keep, uint32_t size);
+ uint8_t keep, uint32_t size,
+ uint32_t base);
int release_label_chunk(uint8_t proto, unsigned short instance, uint32_t start,
uint32_t end);
-int release_daemon_label_chunks(struct zserv *client);
+int lm_client_disconnect_cb(struct zserv *client);
+int release_daemon_label_chunks(uint8_t proto, unsigned short instance);
void label_manager_close(void);
#ifdef __cplusplus
diff --git a/zebra/main.c b/zebra/main.c
index 1947106750..84e83bc37e 100644
--- a/zebra/main.c
+++ b/zebra/main.c
@@ -92,7 +92,6 @@ struct option longopts[] = {
{"keep_kernel", no_argument, NULL, 'k'},
{"socket", required_argument, NULL, 'z'},
{"ecmp", required_argument, NULL, 'e'},
- {"label_socket", no_argument, NULL, 'l'},
{"retain", no_argument, NULL, 'r'},
{"vrfdefaultname", required_argument, NULL, 'o'},
{"graceful_restart", required_argument, NULL, 'K'},
@@ -252,8 +251,6 @@ int main(int argc, char **argv)
// int batch_mode = 0;
char *zserv_path = NULL;
char *vrf_default_name_configured = NULL;
- /* Socket to external label manager */
- char *lblmgr_path = NULL;
struct sockaddr_storage dummy;
socklen_t dummylen;
#if defined(HANDLE_ZAPI_FUZZING)
@@ -270,7 +267,7 @@ int main(int argc, char **argv)
frr_preinit(&zebra_di, argc, argv);
frr_opt_add(
- "baz:e:l:o:rK:"
+ "baz:e:o:rK:"
#ifdef HAVE_NETLINK
"s:n"
#endif
@@ -286,7 +283,6 @@ int main(int argc, char **argv)
" -a, --allow_delete Allow other processes to delete zebra routes\n"
" -z, --socket Set path of zebra socket\n"
" -e, --ecmp Specify ECMP to use.\n"
- " -l, --label_socket Socket to external label manager\n"
" -r, --retain When program terminates, retain added route by zebra.\n"
" -o, --vrfdefaultname Set default VRF name.\n"
" -K, --graceful_restart Graceful restart at the kernel level, timer in seconds for expiration\n"
@@ -341,9 +337,6 @@ int main(int argc, char **argv)
exit(1);
}
break;
- case 'l':
- lblmgr_path = optarg;
- break;
case 'r':
retain_mode = 1;
break;
@@ -451,7 +444,7 @@ int main(int argc, char **argv)
zserv_start(zserv_path);
/* Init label manager */
- label_manager_init(lblmgr_path);
+ label_manager_init();
/* RNH init */
zebra_rnh_init();
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index f951738b70..b1d0c1e3a6 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -811,7 +811,9 @@ static int netlink_route_change_read_multicast(struct nlmsghdr *h,
}
if (IS_ZEBRA_DEBUG_KERNEL) {
- struct interface *ifp;
+ struct interface *ifp = NULL;
+ struct zebra_vrf *zvrf = NULL;
+
strlcpy(sbuf, inet_ntoa(m->sg.src), sizeof(sbuf));
strlcpy(gbuf, inet_ntoa(m->sg.grp), sizeof(gbuf));
for (count = 0; count < oif_count; count++) {
@@ -822,13 +824,14 @@ static int netlink_route_change_read_multicast(struct nlmsghdr *h,
oif[count]);
strlcat(oif_list, temp, sizeof(oif_list));
}
- struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(vrf);
+ zvrf = zebra_vrf_lookup_by_id(vrf);
ifp = if_lookup_by_index(iif, vrf);
- zlog_debug("MCAST VRF: %s(%d) %s (%s,%s) IIF: %s(%d) OIF: %s jiffies: %lld",
- zvrf->vrf->name, vrf,
- nl_msg_type_to_str(h->nlmsg_type),
- sbuf, gbuf, ifp ? ifp->name : "Unknown", iif,
- oif_list, m->lastused);
+ zlog_debug(
+ "MCAST VRF: %s(%d) %s (%s,%s) IIF: %s(%d) OIF: %s jiffies: %lld",
+ (zvrf ? zvrf->vrf->name : "Unknown"), vrf,
+ nl_msg_type_to_str(h->nlmsg_type), sbuf, gbuf,
+ ifp ? ifp->name : "Unknown", iif, oif_list,
+ m->lastused);
}
return 0;
}
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index 9a638f8e7f..98bb2eda60 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -57,7 +57,6 @@
#include "zebra/rtadv.h"
#include "zebra/zebra_mpls.h"
#include "zebra/zebra_mroute.h"
-#include "zebra/label_manager.h"
#include "zebra/zebra_vxlan.h"
#include "zebra/rt.h"
#include "zebra/zebra_pbr.h"
@@ -928,20 +927,20 @@ int zsend_pw_update(struct zserv *client, struct zebra_pw *pw)
}
/* Send response to a get label chunk request to client */
-static int zsend_assign_label_chunk_response(struct zserv *client,
- vrf_id_t vrf_id,
- struct label_manager_chunk *lmc)
+int zsend_assign_label_chunk_response(struct zserv *client, vrf_id_t vrf_id,
+ uint8_t proto, uint16_t instance,
+ struct label_manager_chunk *lmc)
{
int ret;
struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
zclient_create_header(s, ZEBRA_GET_LABEL_CHUNK, vrf_id);
+ /* proto */
+ stream_putc(s, proto);
+ /* instance */
+ stream_putw(s, instance);
if (lmc) {
- /* proto */
- stream_putc(s, lmc->proto);
- /* instance */
- stream_putw(s, lmc->instance);
/* keep */
stream_putc(s, lmc->keep);
/* start and end labels */
@@ -958,9 +957,8 @@ static int zsend_assign_label_chunk_response(struct zserv *client,
}
/* Send response to a label manager connect request to client */
-static int zsend_label_manager_connect_response(struct zserv *client,
- vrf_id_t vrf_id,
- unsigned short result)
+int zsend_label_manager_connect_response(struct zserv *client, vrf_id_t vrf_id,
+ unsigned short result)
{
int ret;
struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
@@ -1896,27 +1894,16 @@ static void zread_label_manager_connect(struct zserv *client,
flog_err(EC_ZEBRA_TM_WRONG_PROTO,
"client %d has wrong protocol %s", client->sock,
zebra_route_string(proto));
- if (client->is_synchronous)
- zsend_label_manager_connect_response(client, vrf_id, 1);
+ zsend_label_manager_connect_response(client, vrf_id, 1);
return;
}
- zlog_notice("client %d with vrf %u instance %u connected as %s",
- client->sock, vrf_id, instance, zebra_route_string(proto));
+
+ /* recall proto and instance in this socket */
client->proto = proto;
client->instance = instance;
- /*
- * Release previous labels of same protocol and instance.
- * This is done in case it restarted from an unexpected shutdown.
- */
- release_daemon_label_chunks(client);
-
- zlog_debug(
- " Label Manager client connected: sock %d, proto %s, vrf %u instance %u",
- client->sock, zebra_route_string(proto), vrf_id, instance);
- /* send response back */
- if (client->is_synchronous)
- zsend_label_manager_connect_response(client, vrf_id, 0);
+ /* call hook for connection using wrapper */
+ lm_client_connect_call(proto, instance, vrf_id);
stream_failure:
return;
@@ -1927,8 +1914,8 @@ static void zread_get_label_chunk(struct zserv *client, struct stream *msg,
{
struct stream *s;
uint8_t keep;
- uint32_t size;
- struct label_manager_chunk *lmc;
+ uint32_t size, base;
+ struct label_manager_chunk *lmc = NULL;
uint8_t proto;
unsigned short instance;
@@ -1940,8 +1927,11 @@ static void zread_get_label_chunk(struct zserv *client, struct stream *msg,
STREAM_GETW(s, instance);
STREAM_GETC(s, keep);
STREAM_GETL(s, size);
+ STREAM_GETL(s, base);
+
+ /* call hook to get a chunk using wrapper */
+ lm_get_chunk_call(&lmc, proto, instance, keep, size, base, vrf_id);
- lmc = assign_label_chunk(proto, instance, keep, size);
if (!lmc)
flog_err(
EC_ZEBRA_LM_CANNOT_ASSIGN_CHUNK,
@@ -1951,8 +1941,6 @@ static void zread_get_label_chunk(struct zserv *client, struct stream *msg,
zlog_debug("Assigned Label Chunk %u - %u to %s instance %u",
lmc->start, lmc->end,
zebra_route_string(proto), instance);
- /* send response back */
- zsend_assign_label_chunk_response(client, vrf_id, lmc);
stream_failure:
return;
@@ -1974,33 +1962,23 @@ static void zread_release_label_chunk(struct zserv *client, struct stream *msg)
STREAM_GETL(s, start);
STREAM_GETL(s, end);
- release_label_chunk(proto, instance, start, end);
+ /* call hook to release a chunk using wrapper */
+ lm_release_chunk_call(proto, instance, start, end);
stream_failure:
return;
}
+
static void zread_label_manager_request(ZAPI_HANDLER_ARGS)
{
- /* to avoid sending other messages like ZERBA_INTERFACE_UP */
- client->is_synchronous = hdr->command ==
- ZEBRA_LABEL_MANAGER_CONNECT;
-
- /* external label manager */
- if (lm_is_external)
- zread_relay_label_manager_request(hdr->command, client, msg,
- zvrf_id(zvrf));
- /* this is a label manager */
+ if (hdr->command == ZEBRA_LABEL_MANAGER_CONNECT
+ || hdr->command == ZEBRA_LABEL_MANAGER_CONNECT_ASYNC)
+ zread_label_manager_connect(client, msg, zvrf_id(zvrf));
else {
- if (hdr->command == ZEBRA_LABEL_MANAGER_CONNECT ||
- hdr->command == ZEBRA_LABEL_MANAGER_CONNECT_ASYNC)
- zread_label_manager_connect(client, msg, zvrf_id(zvrf));
- else {
- if (hdr->command == ZEBRA_GET_LABEL_CHUNK)
- zread_get_label_chunk(client, msg,
- zvrf_id(zvrf));
- else if (hdr->command == ZEBRA_RELEASE_LABEL_CHUNK)
- zread_release_label_chunk(client, msg);
- }
+ if (hdr->command == ZEBRA_GET_LABEL_CHUNK)
+ zread_get_label_chunk(client, msg, zvrf_id(zvrf));
+ else if (hdr->command == ZEBRA_RELEASE_LABEL_CHUNK)
+ zread_release_label_chunk(client, msg);
}
}
@@ -2513,6 +2491,7 @@ void (*zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
[ZEBRA_IPTABLE_ADD] = zread_iptable,
[ZEBRA_IPTABLE_DELETE] = zread_iptable,
[ZEBRA_VXLAN_FLOOD_CONTROL] = zebra_vxlan_flood_control,
+ [ZEBRA_VXLAN_SG_REPLAY] = zebra_vxlan_sg_replay,
};
#if defined(HANDLE_ZAPI_FUZZING)
diff --git a/zebra/zapi_msg.h b/zebra/zapi_msg.h
index d30fa2d0ef..884edfef04 100644
--- a/zebra/zapi_msg.h
+++ b/zebra/zapi_msg.h
@@ -29,6 +29,8 @@
#include "zebra/zserv.h"
#include "zebra/zebra_pbr.h"
#include "zebra/zebra_errors.h"
+#include "zebra/label_manager.h"
+
#ifdef __cplusplus
extern "C" {
@@ -90,6 +92,14 @@ extern void zserv_nexthop_num_warn(const char *caller, const struct prefix *p,
const unsigned int nexthop_num);
extern void zsend_capabilities_all_clients(void);
+extern int zsend_assign_label_chunk_response(struct zserv *client,
+ vrf_id_t vrf_id, uint8_t proto,
+ uint16_t instance,
+ struct label_manager_chunk *lmc);
+extern int zsend_label_manager_connect_response(struct zserv *client,
+ vrf_id_t vrf_id,
+ unsigned short result);
+
#ifdef __cplusplus
}
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 9cfaef3a89..afe59b9593 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -193,7 +193,7 @@ int zebra_check_addr(const struct prefix *p)
/* Add nexthop to the end of a rib node's nexthop list */
void route_entry_nexthop_add(struct route_entry *re, struct nexthop *nexthop)
{
- _nexthop_add(&re->ng.nexthop, nexthop);
+ _nexthop_group_add_sorted(&re->ng, nexthop);
re->nexthop_num++;
}
diff --git a/zebra/zebra_vrf.h b/zebra/zebra_vrf.h
index 972fe381cc..f92e1a010b 100644
--- a/zebra/zebra_vrf.h
+++ b/zebra/zebra_vrf.h
@@ -69,6 +69,7 @@ struct zebra_vrf {
/* Flags. */
uint16_t flags;
#define ZEBRA_VRF_RETAIN (1 << 0)
+#define ZEBRA_PIM_SEND_VXLAN_SG (1 << 1)
uint32_t table_id;
diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c
index 222d91105e..dff50ceef4 100644
--- a/zebra/zebra_vxlan.c
+++ b/zebra/zebra_vxlan.c
@@ -732,6 +732,7 @@ static void zvni_print_neigh(zebra_neigh_t *n, void *ctxt, json_object *json)
bool flags_present = false;
struct zebra_vrf *zvrf = NULL;
struct timeval detect_start_time = {0, 0};
+ char timebuf[MONOTIME_STRLEN];
zvrf = zebra_vrf_get_evpn();
if (!zvrf)
@@ -786,19 +787,17 @@ static void zvni_print_neigh(zebra_neigh_t *n, void *ctxt, json_object *json)
if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE)) {
vty_out(vty, " Duplicate, detected at %s",
- time_to_string(n->dad_dup_detect_time));
+ time_to_string(n->dad_dup_detect_time,
+ timebuf));
} else if (n->dad_count) {
monotime_since(&n->detect_start_time,
&detect_start_time);
if (detect_start_time.tv_sec <= zvrf->dad_time) {
- char *buf = time_to_string(
- n->detect_start_time.tv_sec);
- char tmp_buf[30];
-
- strlcpy(tmp_buf, buf, sizeof(tmp_buf));
+ time_to_string(n->detect_start_time.tv_sec,
+ timebuf);
vty_out(vty,
" Duplicate detection started at %s, detection count %u\n",
- tmp_buf, n->dad_count);
+ timebuf, n->dad_count);
}
}
} else {
@@ -1179,6 +1178,7 @@ static void zvni_print_mac(zebra_mac_t *mac, void *ctxt, json_object *json)
char buf2[INET6_ADDRSTRLEN];
struct zebra_vrf *zvrf;
struct timeval detect_start_time = {0, 0};
+ char timebuf[MONOTIME_STRLEN];
zvrf = zebra_vrf_get_evpn();
if (!zvrf)
@@ -1309,19 +1309,17 @@ static void zvni_print_mac(zebra_mac_t *mac, void *ctxt, json_object *json)
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) {
vty_out(vty, " Duplicate, detected at %s",
- time_to_string(mac->dad_dup_detect_time));
+ time_to_string(mac->dad_dup_detect_time,
+ timebuf));
} else if (mac->dad_count) {
monotime_since(&mac->detect_start_time,
&detect_start_time);
if (detect_start_time.tv_sec <= zvrf->dad_time) {
- char *buf = time_to_string(
- mac->detect_start_time.tv_sec);
- char tmp_buf[30];
-
- strlcpy(tmp_buf, buf, sizeof(tmp_buf));
+ time_to_string(mac->detect_start_time.tv_sec,
+ timebuf);
vty_out(vty,
" Duplicate detection started at %s, detection count %u\n",
- tmp_buf, mac->dad_count);
+ timebuf, mac->dad_count);
}
}
@@ -9483,8 +9481,9 @@ static int zebra_vxlan_dad_mac_auto_recovery_exp(struct thread *t)
/************************** vxlan SG cache management ************************/
/* Inform PIM about the mcast group */
-static int zebra_vxlan_sg_send(struct prefix_sg *sg,
- char *sg_str, uint16_t cmd)
+static int zebra_vxlan_sg_send(struct zebra_vrf *zvrf,
+ struct prefix_sg *sg,
+ char *sg_str, uint16_t cmd)
{
struct zserv *client = NULL;
struct stream *s = NULL;
@@ -9493,6 +9492,9 @@ static int zebra_vxlan_sg_send(struct prefix_sg *sg,
if (!client)
return 0;
+ if (!CHECK_FLAG(zvrf->flags, ZEBRA_PIM_SEND_VXLAN_SG))
+ return 0;
+
s = stream_new(ZEBRA_MAX_PACKET_SIZ);
zclient_create_header(s, cmd, VRF_DEFAULT);
@@ -9592,7 +9594,8 @@ static zebra_vxlan_sg_t *zebra_vxlan_sg_add(struct zebra_vrf *zvrf,
return vxlan_sg;
}
- zebra_vxlan_sg_send(sg, vxlan_sg->sg_str, ZEBRA_VXLAN_SG_ADD);
+ zebra_vxlan_sg_send(zvrf, sg, vxlan_sg->sg_str,
+ ZEBRA_VXLAN_SG_ADD);
return vxlan_sg;
}
@@ -9614,8 +9617,8 @@ static void zebra_vxlan_sg_del(zebra_vxlan_sg_t *vxlan_sg)
zebra_vxlan_sg_do_deref(zvrf, sip, vxlan_sg->sg.grp);
}
- zebra_vxlan_sg_send(&vxlan_sg->sg, vxlan_sg->sg_str,
- ZEBRA_VXLAN_SG_DEL);
+ zebra_vxlan_sg_send(zvrf, &vxlan_sg->sg,
+ vxlan_sg->sg_str, ZEBRA_VXLAN_SG_DEL);
hash_release(vxlan_sg->zvrf->vxlan_sg_table, vxlan_sg);
@@ -9699,6 +9702,31 @@ static void zebra_vxlan_sg_cleanup(struct hash_backet *backet, void *arg)
zebra_vxlan_sg_del(vxlan_sg);
}
+static void zebra_vxlan_sg_replay_send(struct hash_backet *backet, void *arg)
+{
+ zebra_vxlan_sg_t *vxlan_sg = (zebra_vxlan_sg_t *)backet->data;
+
+ zebra_vxlan_sg_send(vxlan_sg->zvrf, &vxlan_sg->sg,
+ vxlan_sg->sg_str, ZEBRA_VXLAN_SG_ADD);
+}
+
+/* Handle message from client to replay vxlan SG entries */
+void zebra_vxlan_sg_replay(ZAPI_HANDLER_ARGS)
+{
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug("VxLAN SG updates to PIM, start");
+
+ SET_FLAG(zvrf->flags, ZEBRA_PIM_SEND_VXLAN_SG);
+
+ if (!EVPN_ENABLED(zvrf)) {
+ zlog_debug("VxLAN SG replay request on unexpected vrf %d",
+ zvrf->vrf->vrf_id);
+ return;
+ }
+
+ hash_iterate(zvrf->vxlan_sg_table, zebra_vxlan_sg_replay_send, NULL);
+}
+
/************************** EVPN BGP config management ************************/
/* Notify Local MACs to the clienti, skips GW MAC */
static void zvni_send_mac_hash_entry_to_client(struct hash_bucket *bucket,
@@ -9806,14 +9834,11 @@ static void zebra_evpn_vrf_cfg_cleanup(struct zebra_vrf *zvrf)
}
/* Cleanup BGP EVPN configuration upon client disconnect */
-static int zebra_evpn_cfg_clean_up(struct zserv *client)
+static int zebra_evpn_bgp_cfg_clean_up(struct zserv *client)
{
struct vrf *vrf;
struct zebra_vrf *zvrf;
- if (client->proto != ZEBRA_ROUTE_BGP)
- return 0;
-
RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
zvrf = vrf->info;
if (zvrf)
@@ -9823,6 +9848,30 @@ static int zebra_evpn_cfg_clean_up(struct zserv *client)
return 0;
}
+static int zebra_evpn_pim_cfg_clean_up(struct zserv *client)
+{
+ struct zebra_vrf *zvrf = zebra_vrf_get_evpn();
+
+ if (CHECK_FLAG(zvrf->flags, ZEBRA_PIM_SEND_VXLAN_SG)) {
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug("VxLAN SG updates to PIM, stop");
+ UNSET_FLAG(zvrf->flags, ZEBRA_PIM_SEND_VXLAN_SG);
+ }
+
+ return 0;
+}
+
+static int zebra_evpn_cfg_clean_up(struct zserv *client)
+{
+ if (client->proto == ZEBRA_ROUTE_BGP)
+ return zebra_evpn_bgp_cfg_clean_up(client);
+
+ if (client->proto == ZEBRA_ROUTE_PIM)
+ return zebra_evpn_pim_cfg_clean_up(client);
+
+ return 0;
+}
+
/* Cleanup BGP EVPN configuration upon client disconnect */
extern void zebra_evpn_init(void)
{
diff --git a/zebra/zebra_vxlan.h b/zebra/zebra_vxlan.h
index 6117567bc1..c71953d6bb 100644
--- a/zebra/zebra_vxlan.h
+++ b/zebra/zebra_vxlan.h
@@ -79,6 +79,7 @@ extern void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS);
extern void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS);
extern void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS);
extern void zebra_vxlan_dup_addr_detection(ZAPI_HANDLER_ARGS);
+extern void zebra_vxlan_sg_replay(ZAPI_HANDLER_ARGS);
extern int is_l3vni_for_prefix_routes_only(vni_t vni);
extern ifindex_t get_l3vni_svi_ifindex(vrf_id_t vrf_id);
diff --git a/zebra/zserv.c b/zebra/zserv.c
index cb9ca6578b..70b4594813 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -535,28 +535,6 @@ static int zserv_process_messages(struct thread *thread)
int zserv_send_message(struct zserv *client, struct stream *msg)
{
- /*
- * This is a somewhat poorly named variable added with Zebra's portion
- * of the label manager. That component does not use the regular
- * zserv/zapi_msg interface for handling its messages, as the client
- * itself runs in-process. Instead it uses synchronous writes on the
- * zserv client's socket directly in the zread* handlers for its
- * message types. Furthermore, it cannot handle the usual messages
- * Zebra sends (such as those for interface changes) and so has added
- * this flag and check here as a hack to suppress all messages that it
- * does not explicitly know about.
- *
- * In any case this needs to be cleaned up at some point.
- *
- * See also:
- * zread_label_manager_request
- * zsend_label_manager_connect_response
- * zsend_assign_label_chunk_response
- * ...
- */
- if (client->is_synchronous)
- return 0;
-
pthread_mutex_lock(&client->obuf_mtx);
{
stream_fifo_push(client->obuf_fifo, msg);
@@ -710,9 +688,6 @@ static struct zserv *zserv_client_create(int sock)
}
client->ridinfo = vrf_bitmap_init();
- /* by default, it's not a synchronous client */
- client->is_synchronous = 0;
-
/* Add this client to linked list. */
listnode_add(zrouter.client_list, client);
diff --git a/zebra/zserv.h b/zebra/zserv.h
index 34965618f2..708ff1e226 100644
--- a/zebra/zserv.h
+++ b/zebra/zserv.h
@@ -98,7 +98,6 @@ struct zserv {
/* client's protocol */
uint8_t proto;
uint16_t instance;
- uint8_t is_synchronous;
/* Statistics */
uint32_t redist_v4_add_cnt;