summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_community.c36
-rw-r--r--isisd/isis_nb_config.c9
-rw-r--r--tests/.gitignore1
-rw-r--r--tests/subdir.am19
-rw-r--r--tests/topotests/bgp_multi_vrf_topo2/test_bgp_multi_vrf_topo2.py3
-rw-r--r--tests/zebra/test_lm_plugin.c134
-rw-r--r--tests/zebra/test_lm_plugin.py5
-rw-r--r--tests/zebra/test_lm_plugin.refout2
-rw-r--r--zebra/label_manager.c23
-rw-r--r--zebra/label_manager.h11
10 files changed, 223 insertions, 20 deletions
diff --git a/bgpd/bgp_community.c b/bgpd/bgp_community.c
index b6cc2b839f..f722a8dbc7 100644
--- a/bgpd/bgp_community.c
+++ b/bgpd/bgp_community.c
@@ -24,6 +24,7 @@
#include "hash.h"
#include "memory.h"
#include "jhash.h"
+#include "frrstr.h"
#include "bgpd/bgp_memory.h"
#include "bgpd/bgp_community.h"
@@ -648,6 +649,31 @@ enum community_token {
community_token_unknown
};
+/* Helper to check if a given community is valid */
+static bool community_valid(const char *community)
+{
+ int octets = 0;
+ char **splits;
+ int num;
+ int invalid = 0;
+
+ frrstr_split(community, ":", &splits, &num);
+
+ for (int i = 0; i < num; i++) {
+ if (strtoul(splits[i], NULL, 10) > UINT16_MAX)
+ invalid++;
+
+ if (strlen(splits[i]) == 0)
+ invalid++;
+
+ octets++;
+ XFREE(MTYPE_TMP, splits[i]);
+ }
+ XFREE(MTYPE_TMP, splits);
+
+ return (octets < 2 || invalid) ? false : true;
+}
+
/* Get next community token from string. */
static const char *
community_gettoken(const char *buf, enum community_token *token, uint32_t *val)
@@ -780,6 +806,11 @@ community_gettoken(const char *buf, enum community_token *token, uint32_t *val)
uint32_t community_low = 0;
uint32_t community_high = 0;
+ if (!community_valid(p)) {
+ *token = community_token_unknown;
+ return NULL;
+ }
+
while (isdigit((unsigned char)*p) || *p == ':') {
if (*p == ':') {
if (separator) {
@@ -810,11 +841,6 @@ community_gettoken(const char *buf, enum community_token *token, uint32_t *val)
return NULL;
}
- if (community_low > UINT16_MAX) {
- *token = community_token_unknown;
- return NULL;
- }
-
*val = community_high + community_low;
*token = community_token_val;
return p;
diff --git a/isisd/isis_nb_config.c b/isisd/isis_nb_config.c
index 84ca801d2b..2f7469b1b1 100644
--- a/isisd/isis_nb_config.c
+++ b/isisd/isis_nb_config.c
@@ -51,6 +51,7 @@
#include "isisd/isis_mt.h"
#include "isisd/isis_redist.h"
#include "isisd/isis_ldp_sync.h"
+#include "isisd/isis_dr.h"
extern struct zclient *zclient;
@@ -213,6 +214,9 @@ int isis_instance_area_address_destroy(struct nb_cb_destroy_args *args)
uint8_t buff[255];
struct isis_area *area;
const char *net_title;
+ struct listnode *cnode;
+ struct isis_circuit *circuit;
+ int lvl;
if (args->event != NB_EV_APPLY)
return NB_OK;
@@ -236,6 +240,11 @@ int isis_instance_area_address_destroy(struct nb_cb_destroy_args *args)
* Last area address - reset the SystemID for this router
*/
if (listcount(area->area_addrs) == 0) {
+ for (ALL_LIST_ELEMENTS_RO(area->circuit_list, cnode, circuit))
+ for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; ++lvl) {
+ if (circuit->u.bc.is_dr[lvl - 1])
+ isis_dr_resign(circuit, lvl);
+ }
memset(area->isis->sysid, 0, ISIS_SYS_ID_LEN);
area->isis->sysid_set = 0;
if (IS_DEBUG_EVENTS)
diff --git a/tests/.gitignore b/tests/.gitignore
index 5e809a81e6..b1b8f92a87 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -51,3 +51,4 @@
/lib/test_zmq
/ospf6d/test_lsdb
/ospf6d/test_lsdb_clippy.c
+/zebra/test_lm_plugin \ No newline at end of file
diff --git a/tests/subdir.am b/tests/subdir.am
index 211814c1c3..1f173d7f1a 100644
--- a/tests/subdir.am
+++ b/tests/subdir.am
@@ -41,6 +41,16 @@ TESTS_OSPF6D =
IGNORE_OSPF6D = --ignore=ospf6d/
endif
+if ZEBRA
+TESTS_ZEBRA = \
+ tests/zebra/test_lm_plugin \
+ #end
+IGNORE_ZEBRA =
+else
+TESTS_ZEBRA =
+IGNORE_ZEBRA = --ignore=zebra/
+endif
+
clippy_scan += \
tests/lib/cli/test_cli.c \
tests/ospf6d/test_lsdb.c \
@@ -81,6 +91,7 @@ check_PROGRAMS = \
$(TESTS_BGPD) \
$(TESTS_ISISD) \
$(TESTS_OSPF6D) \
+ $(TESTS_ZEBRA) \
# end
if ZEROMQ
@@ -135,6 +146,7 @@ ALL_TESTS_LDADD = lib/libfrr.la $(LIBCAP)
BGP_TEST_LDADD = bgpd/libbgp.a $(RFPLDADD) $(ALL_TESTS_LDADD) -lm
ISISD_TEST_LDADD = isisd/libisis.a $(ALL_TESTS_LDADD)
OSPF6_TEST_LDADD = ospf6d/libospf6.a $(ALL_TESTS_LDADD)
+ZEBRA_TEST_LDADD = zebra/label_manager.o $(ALL_TESTS_LDADD)
tests_bgpd_test_aspath_CFLAGS = $(TESTS_CFLAGS)
tests_bgpd_test_aspath_CPPFLAGS = $(TESTS_CPPFLAGS)
@@ -336,6 +348,11 @@ tests_ospf6d_test_lsdb_CPPFLAGS = $(TESTS_CPPFLAGS)
tests_ospf6d_test_lsdb_LDADD = $(OSPF6_TEST_LDADD)
tests_ospf6d_test_lsdb_SOURCES = tests/ospf6d/test_lsdb.c tests/lib/cli/common_cli.c
+tests_zebra_test_lm_plugin_CFLAGS = $(TESTS_CFLAGS)
+tests_zebra_test_lm_plugin_CPPFLAGS = $(TESTS_CPPFLAGS)
+tests_zebra_test_lm_plugin_LDADD = $(ZEBRA_TEST_LDADD)
+tests_zebra_test_lm_plugin_SOURCES = tests/zebra/test_lm_plugin.c
+
EXTRA_DIST += \
tests/runtests.py \
tests/bgpd/test_aspath.py \
@@ -383,6 +400,8 @@ EXTRA_DIST += \
tests/ospf6d/test_lsdb.py \
tests/ospf6d/test_lsdb.in \
tests/ospf6d/test_lsdb.refout \
+ tests/zebra/test_lm_plugin.py \
+ tests/zebra/test_lm_plugin.refout \
# end
.PHONY: tests/tests.xml
diff --git a/tests/topotests/bgp_multi_vrf_topo2/test_bgp_multi_vrf_topo2.py b/tests/topotests/bgp_multi_vrf_topo2/test_bgp_multi_vrf_topo2.py
index d34446e2ee..19a9140c13 100644
--- a/tests/topotests/bgp_multi_vrf_topo2/test_bgp_multi_vrf_topo2.py
+++ b/tests/topotests/bgp_multi_vrf_topo2/test_bgp_multi_vrf_topo2.py
@@ -2687,6 +2687,9 @@ def test_delete_and_re_add_vrf_p1(request):
}
}
+ result = verify_bgp_convergence(tgen, topo)
+ assert result is True, "Testcase {}: Failed\n Error {}".format(tc_name, result)
+
result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2)
assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
diff --git a/tests/zebra/test_lm_plugin.c b/tests/zebra/test_lm_plugin.c
new file mode 100644
index 0000000000..4a9344fee4
--- /dev/null
+++ b/tests/zebra/test_lm_plugin.c
@@ -0,0 +1,134 @@
+/*
+ * Label Manager tests.
+ * Copyright (C) 2020 Volta Networks
+ * Patrick Ruddy
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+
+#include <zebra.h>
+#include "zebra/zapi_msg.h"
+#include "zebra/label_manager.h"
+
+/* shim out unused functions/variables to allow the lablemanager to compile*/
+DEFINE_KOOH(zserv_client_close, (struct zserv * client), (client));
+unsigned long zebra_debug_packet = 0;
+struct zserv *zserv_find_client_session(uint8_t proto, unsigned short instance,
+ uint32_t session_id)
+{
+ return NULL;
+}
+
+int zsend_label_manager_connect_response(struct zserv *client, vrf_id_t vrf_id,
+ unsigned short result)
+{
+ return 0;
+}
+
+int zsend_assign_label_chunk_response(struct zserv *client, vrf_id_t vrf_id,
+ struct label_manager_chunk *lmc)
+{
+ return 0;
+}
+
+
+static int test_client_connect(struct zserv *client, vrf_id_t vrf_id)
+{
+ return 0;
+}
+
+static int test_client_disconnect(struct zserv *client)
+{
+ return 0;
+}
+
+/* external test hook functions */
+static int lm_get_chunk_pi(struct label_manager_chunk **lmc,
+ struct zserv *client, uint8_t keep, uint32_t size,
+ uint32_t base, vrf_id_t vrf_id)
+{
+ if (base == 0)
+ *lmc = create_label_chunk(10, 55, 0, 1, 50, 50 + size);
+ else
+ *lmc = assign_label_chunk(10, 55, 0, 1, size, base);
+
+ return 0;
+}
+
+static int lm_release_chunk_pi(struct zserv *client, uint32_t start,
+ uint32_t end)
+{
+ return release_label_chunk(client->proto, client->instance,
+ client->session_id, start, end);
+}
+
+
+/* use external allocations */
+static void lp_plugin_init()
+{
+ /* register our own hooks */
+ hook_register(lm_client_connect, test_client_connect);
+ hook_register(lm_client_disconnect, test_client_disconnect);
+ hook_register(lm_get_chunk, lm_get_chunk_pi);
+ hook_register(lm_release_chunk, lm_release_chunk_pi);
+}
+
+static void lp_plugin_cleanup()
+{
+ /* register our own hooks */
+ hook_unregister(lm_client_connect, test_client_connect);
+ hook_unregister(lm_client_disconnect, test_client_disconnect);
+ hook_unregister(lm_get_chunk, lm_get_chunk_pi);
+ hook_unregister(lm_release_chunk, lm_release_chunk_pi);
+}
+
+
+/* tests */
+
+static void test_lp_plugin()
+{
+ struct label_manager_chunk *lmc;
+
+ lmc = assign_label_chunk(10, 55, 0, 1, 50, 0);
+ fprintf(stdout,
+ "chunk: start %u end %u proto %u instance %u session %u keep %s\n",
+ lmc->start, lmc->end, lmc->proto, lmc->instance,
+ lmc->session_id, lmc->keep ? "yes" : "no");
+ delete_label_chunk(lmc);
+
+ lmc = assign_label_chunk(10, 55, 0, 1, 50, 100);
+ fprintf(stdout,
+ "chunk: start %u end %u proto %u instance %u session %u keep %s\n",
+ lmc->start, lmc->end, lmc->proto, lmc->instance,
+ lmc->session_id, lmc->keep ? "yes" : "no");
+ release_label_chunk(10, 55, 0, lmc->start, lmc->end);
+}
+
+int main(int argc, char **argv)
+{
+ /* set up label manager and release it's hooks */
+ label_manager_init();
+ lm_hooks_unregister();
+
+ /* test plugin */
+ lp_plugin_init();
+ test_lp_plugin();
+ lp_plugin_cleanup();
+
+ /* this keeps the compiler happy */
+ hook_call(zserv_client_close, NULL);
+ return 0;
+}
diff --git a/tests/zebra/test_lm_plugin.py b/tests/zebra/test_lm_plugin.py
new file mode 100644
index 0000000000..bf4f3cef91
--- /dev/null
+++ b/tests/zebra/test_lm_plugin.py
@@ -0,0 +1,5 @@
+import frrtest
+
+
+class TestLmplugin(frrtest.TestRefOut):
+ program = "./test_lm_plugin"
diff --git a/tests/zebra/test_lm_plugin.refout b/tests/zebra/test_lm_plugin.refout
new file mode 100644
index 0000000000..35824f1055
--- /dev/null
+++ b/tests/zebra/test_lm_plugin.refout
@@ -0,0 +1,2 @@
+chunk: start 16 end 65 proto 10 instance 55 session 0 keep yes
+chunk: start 100 end 149 proto 10 instance 55 session 0 keep yes
diff --git a/zebra/label_manager.c b/zebra/label_manager.c
index feec49ecc2..ef51669022 100644
--- a/zebra/label_manager.c
+++ b/zebra/label_manager.c
@@ -91,11 +91,8 @@ static int label_manager_get_chunk(struct label_manager_chunk **lmc,
vrf_id_t vrf_id);
static int label_manager_release_label_chunk(struct zserv *client,
uint32_t start, uint32_t end);
-static int release_label_chunk(uint8_t proto, unsigned short instance,
- uint32_t session_id, uint32_t start,
- uint32_t end);
-static void delete_label_chunk(void *val)
+void delete_label_chunk(void *val)
{
XFREE(MTYPE_LM_CHUNK, val);
}
@@ -178,11 +175,9 @@ void label_manager_init(void)
}
/* alloc and fill a label chunk */
-static struct label_manager_chunk *create_label_chunk(uint8_t proto,
- unsigned short instance,
- uint32_t session_id,
- uint8_t keep, uint32_t start,
- uint32_t end)
+struct label_manager_chunk *
+create_label_chunk(uint8_t proto, unsigned short instance, uint32_t session_id,
+ uint8_t keep, uint32_t start, uint32_t end)
{
/* alloc chunk, fill it and return it */
struct label_manager_chunk *lmc =
@@ -305,11 +300,9 @@ assign_specific_label_chunk(uint8_t proto, unsigned short instance,
* @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
*/
-static struct label_manager_chunk *assign_label_chunk(uint8_t proto,
- unsigned short instance,
- uint32_t session_id,
- uint8_t keep, uint32_t size,
- uint32_t base)
+struct label_manager_chunk *
+assign_label_chunk(uint8_t proto, unsigned short instance, uint32_t session_id,
+ uint8_t keep, uint32_t size, uint32_t base)
{
struct label_manager_chunk *lmc;
struct listnode *node;
@@ -398,7 +391,7 @@ static int label_manager_release_label_chunk(struct zserv *client,
* @param end Last label of the chunk
* @return 0 on success, -1 otherwise
*/
-static int release_label_chunk(uint8_t proto, unsigned short instance,
+int release_label_chunk(uint8_t proto, unsigned short instance,
uint32_t session_id, uint32_t start, uint32_t end)
{
struct listnode *node;
diff --git a/zebra/label_manager.h b/zebra/label_manager.h
index 094155f714..8636c79219 100644
--- a/zebra/label_manager.h
+++ b/zebra/label_manager.h
@@ -94,6 +94,12 @@ int lm_client_connect_response(uint8_t proto, uint16_t instance,
int lm_get_chunk_response(struct label_manager_chunk *lmc, struct zserv *client,
vrf_id_t vrf_id);
+/* convenience function to allocate an lmc to be consumed by the above API */
+struct label_manager_chunk *
+create_label_chunk(uint8_t proto, unsigned short instance, uint32_t session_id,
+ uint8_t keep, uint32_t start, uint32_t end);
+void delete_label_chunk(void *val);
+
/* register/unregister callbacks for hooks */
void lm_hooks_register(void);
void lm_hooks_unregister(void);
@@ -107,6 +113,11 @@ struct label_manager {
};
void label_manager_init(void);
+struct label_manager_chunk *
+assign_label_chunk(uint8_t proto, unsigned short instance, uint32_t session_id,
+ uint8_t keep, uint32_t size, uint32_t base);
+int release_label_chunk(uint8_t proto, unsigned short instance,
+ uint32_t session_id, uint32_t start, uint32_t end);
int lm_client_disconnect_cb(struct zserv *client);
int release_daemon_label_chunks(struct zserv *client);
void label_manager_close(void);