diff options
| -rw-r--r-- | bgpd/bgp_community.c | 36 | ||||
| -rw-r--r-- | isisd/isis_nb_config.c | 9 | ||||
| -rw-r--r-- | tests/.gitignore | 1 | ||||
| -rw-r--r-- | tests/subdir.am | 19 | ||||
| -rw-r--r-- | tests/topotests/bgp_multi_vrf_topo2/test_bgp_multi_vrf_topo2.py | 3 | ||||
| -rw-r--r-- | tests/zebra/test_lm_plugin.c | 134 | ||||
| -rw-r--r-- | tests/zebra/test_lm_plugin.py | 5 | ||||
| -rw-r--r-- | tests/zebra/test_lm_plugin.refout | 2 | ||||
| -rw-r--r-- | zebra/label_manager.c | 23 | ||||
| -rw-r--r-- | zebra/label_manager.h | 11 |
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); |
