From cf2182c013e57fbcb98ff0f42be7f0d1542c51df Mon Sep 17 00:00:00 2001 From: Mark Stapp Date: Mon, 9 Aug 2021 11:55:15 -0400 Subject: [PATCH 001/188] lib: clear caller's pointer when freeing context struct The zeromq lib wrapper uses an internal context struct to help interact with the libfrr event mechanism. When freeing that context struct, ensure the caller's pointer is also cleared. Signed-off-by: Mark Stapp --- lib/frr_zmq.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/frr_zmq.c b/lib/frr_zmq.c index ea9c828f7c00..994fe656fdd2 100644 --- a/lib/frr_zmq.c +++ b/lib/frr_zmq.c @@ -92,7 +92,8 @@ static int frrzmq_read_msg(struct thread *t) ZMQ_POLLOUT); cb->read.thread = NULL; if (cb->write.cancelled && !cb->write.thread) - XFREE(MTYPE_ZEROMQ_CB, cb); + XFREE(MTYPE_ZEROMQ_CB, *cbp); + return 0; } continue; @@ -120,7 +121,8 @@ static int frrzmq_read_msg(struct thread *t) ZMQ_POLLOUT); cb->read.thread = NULL; if (cb->write.cancelled && !cb->write.thread) - XFREE(MTYPE_ZEROMQ_CB, cb); + XFREE(MTYPE_ZEROMQ_CB, *cbp); + return 0; } @@ -239,7 +241,8 @@ static int frrzmq_write_msg(struct thread *t) frrzmq_check_events(cbp, &cb->read, ZMQ_POLLIN); cb->write.thread = NULL; if (cb->read.cancelled && !cb->read.thread) - XFREE(MTYPE_ZEROMQ_CB, cb); + XFREE(MTYPE_ZEROMQ_CB, *cbp); + return 0; } continue; From 8fd5502b0c2e628b875fdaf1a0ca467f8ba07ce4 Mon Sep 17 00:00:00 2001 From: Mark Stapp Date: Mon, 9 Aug 2021 11:57:17 -0400 Subject: [PATCH 002/188] lib: avoid double-free in zmq wrapper callbacks There were paths where the zmq wrapper lib could call user callbacks that would free the internal context struct, but the context was then used in the lib code. Use a boolean to avoid freeing the context within an application callback. Restore logic that frees the context within the 'cancel' api. Signed-off-by: Mark Stapp --- lib/frr_zmq.c | 34 ++++++++++++++++++---------------- lib/frr_zmq.h | 3 +++ 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/lib/frr_zmq.c b/lib/frr_zmq.c index 994fe656fdd2..4e947a8a8429 100644 --- a/lib/frr_zmq.c +++ b/lib/frr_zmq.c @@ -84,7 +84,10 @@ static int frrzmq_read_msg(struct thread *t) break; if (cb->read.cb_msg) { + cb->in_cb = true; cb->read.cb_msg(cb->read.arg, cb->zmqsock); + cb->in_cb = false; + read = 1; if (cb->read.cancelled) { @@ -113,8 +116,11 @@ static int frrzmq_read_msg(struct thread *t) } read = 1; + cb->in_cb = true; cb->read.cb_part(cb->read.arg, cb->zmqsock, &msg, partno); + cb->in_cb = false; + if (cb->read.cancelled) { zmq_msg_close(&msg); frrzmq_check_events(cbp, &cb->write, @@ -185,7 +191,6 @@ int _frrzmq_thread_add_read(const struct xref_threadsched *xref, cb = *cbp; else { cb = XCALLOC(MTYPE_ZEROMQ_CB, sizeof(struct frrzmq_cb)); - cb->write.cancelled = true; *cbp = cb; } @@ -197,6 +202,7 @@ int _frrzmq_thread_add_read(const struct xref_threadsched *xref, cb->read.cb_part = partfunc; cb->read.cb_error = errfunc; cb->read.cancelled = false; + cb->in_cb = false; if (events & ZMQ_POLLIN) { thread_cancel(&cb->read.thread); @@ -234,7 +240,10 @@ static int frrzmq_write_msg(struct thread *t) break; if (cb->write.cb_msg) { + cb->in_cb = true; cb->write.cb_msg(cb->write.arg, cb->zmqsock); + cb->in_cb = false; + written = 1; if (cb->write.cancelled) { @@ -289,7 +298,6 @@ int _frrzmq_thread_add_write(const struct xref_threadsched *xref, cb = *cbp; else { cb = XCALLOC(MTYPE_ZEROMQ_CB, sizeof(struct frrzmq_cb)); - cb->read.cancelled = true; *cbp = cb; } @@ -301,6 +309,7 @@ int _frrzmq_thread_add_write(const struct xref_threadsched *xref, cb->write.cb_part = NULL; cb->write.cb_error = errfunc; cb->write.cancelled = false; + cb->in_cb = false; if (events & ZMQ_POLLOUT) { thread_cancel(&cb->write.thread); @@ -320,22 +329,15 @@ void frrzmq_thread_cancel(struct frrzmq_cb **cb, struct cb_core *core) core->cancelled = true; thread_cancel(&core->thread); - /* - * Looking at this code one would assume that FRR - * would want a `!(*cb)->write.thread. This was - * attempted in e08165def1c62beee0e87385 but this - * change caused `make check` to stop working - * which was not noticed because our CI system - * does not build with zeromq. Put this back - * to the code as written in 2017. e08165de.. - * was introduced in 2021. So someone was ok - * with frrzmq_thread_cancel for 4 years. This will - * allow those people doing `make check` to continue - * working. In the meantime if the people using - * this code see an issue they can fix it + /* If cancelled from within a callback, don't try to free memory + * in this path. */ + if ((*cb)->in_cb) + return; + + /* Ok to free the callback context if no more ... context. */ if ((*cb)->read.cancelled && !(*cb)->read.thread - && (*cb)->write.cancelled && (*cb)->write.thread) + && (*cb)->write.cancelled && ((*cb)->write.thread == NULL)) XFREE(MTYPE_ZEROMQ_CB, *cb); } diff --git a/lib/frr_zmq.h b/lib/frr_zmq.h index d30cf8a84152..b3be78cbea7c 100644 --- a/lib/frr_zmq.h +++ b/lib/frr_zmq.h @@ -49,10 +49,13 @@ struct cb_core { unsigned partnum); void (*cb_error)(void *arg, void *zmqsock); }; + struct frrzmq_cb { void *zmqsock; int fd; + bool in_cb; /* This context is in a read or write callback. */ + struct cb_core read; struct cb_core write; }; From 4204021e46dec75b09cbbcdcdfa2fe163fa00f34 Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Tue, 17 Aug 2021 14:42:30 +0200 Subject: [PATCH 003/188] bgpd: update auto route target for l3vni appropriately The BGP configuration for BGP EVPN RT5 setup consists in mainly 2 bgp instances (eventually one is enough) and L3VNI config. When L3VNI is configured before BGP instances, and BGP route targets are auto derived as per rfc8365, then, the obtained route targets are wrong. For instance, the following can be obtained: => show bgp vrf cust1 vni BGP VRF: cust1 Local-Ip: 10.209.36.1 L3-VNI: 1000 Rmac: da:85:42:ba:2a:e9 VNI Filter: none L2-VNI List: Export-RTs: RT:12757:1000 Import-RTs: RT:12757:1000 RD: 65000:1000 whereas the derived route targets should be the below ones: => show bgp vrf cust1 vni BGP VRF: cust1 Local-Ip: 10.209.36.1 L3-VNI: 1000 Rmac: 72:f3:af:a0:98:80 VNI Filter: none L2-VNI List: Export-RTs: RT:12757:268436456 Import-RTs: RT:12757:268436456 RD: 65000:1000 There is an update handler that updates appropriately L2VNIs. But this is not the case for L3VNIs. Add the missing code. Signed-off-by: Philippe Guibert --- bgpd/bgp_evpn.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index cbd29c146a38..5a4b46f3708d 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -4334,6 +4334,54 @@ static void update_autort_vni(struct hash_bucket *bucket, struct bgp *bgp) } } +/* + * Handle autort change for L3VNI. + */ +static void update_autort_l3vni(struct bgp *bgp) +{ + if ((CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) + && (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD))) + return; + + if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) { + if (is_l3vni_live(bgp)) + uninstall_routes_for_vrf(bgp); + + /* Cleanup the RT to VRF mapping */ + bgp_evpn_unmap_vrf_from_its_rts(bgp); + + /* Remove auto generated RT */ + evpn_auto_rt_import_delete_for_vrf(bgp); + + list_delete_all_node(bgp->vrf_import_rtl); + + /* Map auto derive or configured RTs */ + evpn_auto_rt_import_add_for_vrf(bgp); + } + + if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) { + list_delete_all_node(bgp->vrf_export_rtl); + + evpn_auto_rt_export_delete_for_vrf(bgp); + + evpn_auto_rt_export_add_for_vrf(bgp); + + if (is_l3vni_live(bgp)) + bgp_evpn_map_vrf_to_its_rts(bgp); + } + + if (!is_l3vni_live(bgp)) + return; + + /* advertise type-5 routes if needed */ + update_advertise_vrf_routes(bgp); + + /* install all remote routes belonging to this l3vni + * into corresponding vrf + */ + install_routes_for_vrf(bgp); +} + /* * Public functions. */ @@ -4706,6 +4754,8 @@ void bgp_evpn_handle_autort_change(struct bgp *bgp) (void (*)(struct hash_bucket *, void*))update_autort_vni, bgp); + if (bgp->l3vni) + update_autort_l3vni(bgp); } /* From 52fad8f6563080c64b5609f8b357ed47b1dfb78c Mon Sep 17 00:00:00 2001 From: "G. Paul Ziemba" Date: Fri, 3 Sep 2021 09:49:05 -0700 Subject: [PATCH 004/188] lib/module.c and callers of frrmod_load(): fix error messages frrmod_load() attempts to dlopen() several possible paths (constructed from its basename argument) until one succeeds. Each dlopen() attempt may fail for a different reason, and the important one might not be the last one. Example: dlopen(a/foo): file not found dlopen(b/foo): symbol "bar" missing dlopen(c/foo): file not found Previous code reported only the most recent error. Now frrmod_load() describes each dlopen() failure. Signed-off-by: G. Paul Ziemba --- ldpd/ldpd.c | 3 +- lib/libfrr.c | 14 ++++--- lib/module.c | 92 ++++++++++++++++++++++++++++++++++------- lib/module.h | 4 +- tests/lib/test_grpc.cpp | 18 ++++---- 5 files changed, 99 insertions(+), 32 deletions(-) diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c index 000d1a330192..e24eba7cd438 100644 --- a/ldpd/ldpd.c +++ b/ldpd/ldpd.c @@ -94,10 +94,9 @@ static void ldp_load_module(const char *name) { const char *dir; dir = ldpd_di.module_path ? ldpd_di.module_path : frr_moduledir; - char moderr[256]; struct frrmod_runtime *module; - module = frrmod_load(name, dir, moderr, sizeof(moderr)); + module = frrmod_load(name, dir, NULL,NULL); if (!module) { fprintf(stderr, "%s: failed to load %s", __func__, name); log_warnx("%s: failed to load %s", __func__, name); diff --git a/lib/libfrr.c b/lib/libfrr.c index d03437328b83..9b05bb4fbf96 100644 --- a/lib/libfrr.c +++ b/lib/libfrr.c @@ -674,13 +674,19 @@ static void frr_mkdir(const char *path, bool strip) strerror(errno)); } +static void _err_print(const void *cookie, const char *errstr) +{ + const char *prefix = (const char *)cookie; + + fprintf(stderr, "%s: %s\n", prefix, errstr); +} + static struct thread_master *master; struct thread_master *frr_init(void) { struct option_chain *oc; struct frrmod_runtime *module; struct zprivs_ids_t ids; - char moderr[256]; char p_instance[16] = "", p_pathspace[256] = ""; const char *dir; dir = di->module_path ? di->module_path : frr_moduledir; @@ -734,11 +740,9 @@ struct thread_master *frr_init(void) frrmod_init(di->module); while (modules) { modules = (oc = modules)->next; - module = frrmod_load(oc->arg, dir, moderr, sizeof(moderr)); - if (!module) { - fprintf(stderr, "%s\n", moderr); + module = frrmod_load(oc->arg, dir, _err_print, __func__); + if (!module) exit(1); - } XFREE(MTYPE_TMP, oc); } diff --git a/lib/module.c b/lib/module.c index 1d51a6396d97..4037bfbeb020 100644 --- a/lib/module.c +++ b/lib/module.c @@ -26,9 +26,11 @@ #include "module.h" #include "memory.h" #include "lib/version.h" +#include "printfrr.h" DEFINE_MTYPE_STATIC(LIB, MODULE_LOADNAME, "Module loading name"); DEFINE_MTYPE_STATIC(LIB, MODULE_LOADARGS, "Module loading arguments"); +DEFINE_MTYPE_STATIC(LIB, MODULE_LOAD_ERR, "Module loading error"); static struct frrmod_info frrmod_default_info = { .name = "libfrr", @@ -67,14 +69,64 @@ void frrmod_init(struct frrmod_runtime *modinfo) execname = modinfo->info->name; } -struct frrmod_runtime *frrmod_load(const char *spec, const char *dir, char *err, - size_t err_len) +/* + * If caller wants error strings, it should define non-NULL pFerrlog + * which will be called with 0-terminated error messages. These + * messages will NOT contain newlines, and the (*pFerrlog)() function + * could be called multiple times for a single call to frrmod_load(). + * + * The (*pFerrlog)() function may copy these strings if needed, but + * should expect them to be freed by frrmod_load() before frrmod_load() + * returns. + * + * frrmod_load() is coded such that (*pFerrlog)() will be called only + * in the case where frrmod_load() returns an error. + */ +struct frrmod_runtime *frrmod_load(const char *spec, const char *dir, + void (*pFerrlog)(const void *, const char *), + const void *pErrlogCookie) { void *handle = NULL; char name[PATH_MAX], fullpath[PATH_MAX * 2], *args; struct frrmod_runtime *rtinfo, **rtinfop; const struct frrmod_info *info; +#define FRRMOD_LOAD_N_ERRSTR 10 + char *aErr[FRRMOD_LOAD_N_ERRSTR]; + unsigned int iErr = 0; + + memset(aErr, 0, sizeof(aErr)); + +#define ERR_RECORD(...) \ + do { \ + if (pFerrlog && (iErr < FRRMOD_LOAD_N_ERRSTR)) { \ + aErr[iErr++] = asprintfrr(MTYPE_MODULE_LOAD_ERR, \ + __VA_ARGS__); \ + } \ + } while (0) + +#define ERR_REPORT \ + do { \ + if (pFerrlog) { \ + unsigned int i; \ + \ + for (i = 0; i < iErr; ++i) { \ + (*pFerrlog)(pErrlogCookie, aErr[i]); \ + } \ + } \ + } while (0) + +#define ERR_FREE \ + do { \ + unsigned int i; \ + \ + for (i = 0; i < iErr; ++i) { \ + XFREE(MTYPE_MODULE_LOAD_ERR, aErr[i]); \ + aErr[i] = 0; \ + } \ + iErr = 0; \ + } while (0) + snprintf(name, sizeof(name), "%s", spec); args = strchr(name, ':'); if (args) @@ -85,32 +137,41 @@ struct frrmod_runtime *frrmod_load(const char *spec, const char *dir, char *err, snprintf(fullpath, sizeof(fullpath), "%s/%s_%s.so", dir, execname, name); handle = dlopen(fullpath, RTLD_NOW | RTLD_GLOBAL); + if (!handle) + ERR_RECORD("loader error: dlopen(%s): %s", + fullpath, dlerror()); } if (!handle) { snprintf(fullpath, sizeof(fullpath), "%s/%s.so", dir, name); handle = dlopen(fullpath, RTLD_NOW | RTLD_GLOBAL); + if (!handle) + ERR_RECORD("loader error: dlopen(%s): %s", + fullpath, dlerror()); } } if (!handle) { snprintf(fullpath, sizeof(fullpath), "%s", name); handle = dlopen(fullpath, RTLD_NOW | RTLD_GLOBAL); + if (!handle) + ERR_RECORD("loader error: dlopen(%s): %s", fullpath, + dlerror()); } if (!handle) { - if (err) - snprintf(err, err_len, - "loading module \"%s\" failed: %s", name, - dlerror()); + ERR_REPORT; + ERR_FREE; return NULL; } + /* previous dlopen() errors are no longer relevant */ + ERR_FREE; + rtinfop = dlsym(handle, "frr_module"); if (!rtinfop) { dlclose(handle); - if (err) - snprintf(err, err_len, - "\"%s\" is not an FRR module: %s", name, - dlerror()); + ERR_RECORD("\"%s\" is not an FRR module: %s", name, dlerror()); + ERR_REPORT; + ERR_FREE; return NULL; } rtinfo = *rtinfop; @@ -122,17 +183,13 @@ struct frrmod_runtime *frrmod_load(const char *spec, const char *dir, char *err, if (rtinfo->finished_loading) { dlclose(handle); - if (err) - snprintf(err, err_len, "module \"%s\" already loaded", - name); + ERR_RECORD("module \"%s\" already loaded", name); goto out_fail; } if (info->init && info->init()) { dlclose(handle); - if (err) - snprintf(err, err_len, - "module \"%s\" initialisation failed", name); + ERR_RECORD("module \"%s\" initialisation failed", name); goto out_fail; } @@ -140,11 +197,14 @@ struct frrmod_runtime *frrmod_load(const char *spec, const char *dir, char *err, *frrmod_last = rtinfo; frrmod_last = &rtinfo->next; + ERR_FREE; return rtinfo; out_fail: XFREE(MTYPE_MODULE_LOADARGS, rtinfo->load_args); XFREE(MTYPE_MODULE_LOADNAME, rtinfo->load_name); + ERR_REPORT; + ERR_FREE; return NULL; } diff --git a/lib/module.h b/lib/module.h index 6275877cb374..ae1ca2f7579f 100644 --- a/lib/module.h +++ b/lib/module.h @@ -91,7 +91,9 @@ extern struct frrmod_runtime *frrmod_list; extern void frrmod_init(struct frrmod_runtime *modinfo); extern struct frrmod_runtime *frrmod_load(const char *spec, const char *dir, - char *err, size_t err_len); + void (*pFerrlog)(const void *, + const char *), + const void *pErrlogCookie); #if 0 /* not implemented yet */ extern void frrmod_unload(struct frrmod_runtime *module); diff --git a/tests/lib/test_grpc.cpp b/tests/lib/test_grpc.cpp index 491796802a23..0aa1bbb7e114 100644 --- a/tests/lib/test_grpc.cpp +++ b/tests/lib/test_grpc.cpp @@ -81,11 +81,16 @@ static const struct frr_yang_module_info *const staticd_yang_modules[] = { static int grpc_thread_stop(struct thread *thread); +static void _err_print(const void *cookie, const char *errstr) +{ + std::cout << "Failed to load grpc module:" << errstr << std::endl; +} + static void static_startup(void) { // struct frrmod_runtime module; // static struct option_chain *oc; - char moderr[256] = {}; + cmd_init(1); zlog_aux_init("NONE: ", LOG_DEBUG); @@ -94,17 +99,14 @@ static void static_startup(void) /* Load the server side module -- check libtool path first */ std::string modpath = std::string(binpath) + std::string("../../../lib/.libs"); - grpc_module = frrmod_load("grpc:50051", modpath.c_str(), moderr, sizeof(moderr)); + grpc_module = frrmod_load("grpc:50051", modpath.c_str(), 0, 0); if (!grpc_module) { modpath = std::string(binpath) + std::string("../../lib"); - grpc_module = frrmod_load("grpc:50051", modpath.c_str(), moderr, - sizeof(moderr)); + grpc_module = frrmod_load("grpc:50051", modpath.c_str(), + _err_print, 0); } - if (!grpc_module) { - std::cout << "Failed to load grpc module:" << moderr - << std::endl; + if (!grpc_module) exit(1); - } static_debug_init(); From 42d4b30e00131923691ef260ed8b1ff11bf3f33c Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Fri, 23 Jul 2021 16:56:28 +0200 Subject: [PATCH 005/188] zebra: extend table manager per vrf, add vty configuration Because vrf backend may be based on namespaces, each vrf can use in the [16-(2^32-1)] range table identifier for daemons that request it. Extend the table manager to be hosted by vrf. That possibility is disabled in the case the vrf backend is vrflite. In that case, all vrf context use the same table manager instance. Add a configuration command to be able to configure the wished range of tables to use. This is a solution that permits to give chunks to bgp daemon when it works with bgp flowspec entries and wants to use specific iptables that do not override vrf tables. Signed-off-by: Philippe Guibert --- doc/user/zebra.rst | 15 ++ tests/topotests/bgp_flowspec/r1/zebra.conf | 1 + zebra/table_manager.c | 190 ++++++++++++++++----- zebra/table_manager.h | 13 +- zebra/zapi_msg.c | 15 +- zebra/zebra_ns.c | 5 - zebra/zebra_vrf.c | 19 +++ zebra/zebra_vrf.h | 2 + zebra/zebra_vty.c | 29 ++++ 9 files changed, 235 insertions(+), 54 deletions(-) diff --git a/doc/user/zebra.rst b/doc/user/zebra.rst index 79036320b824..1ab4dcce255d 100644 --- a/doc/user/zebra.rst +++ b/doc/user/zebra.rst @@ -473,6 +473,21 @@ be updated with the new name. To illustrate, if you want to recompile with ./configure --with-defaultvrfname=global +.. _zebra-table-allocation: + +Table Allocation +================ + +Some services like BGP flowspec allocate routing tables to perform policy +routing based on netfilter criteria and IP rules. In order to avoid +conflicts between VRF allocated routing tables and those services, Zebra +proposes to define a chunk of routing tables to use by other services. + +Allocation configuration can be done like below, with the range of the +chunk of routing tables to be used by the given service. + +.. clicmd:: ip table range + .. _zebra-ecmp: ECMP diff --git a/tests/topotests/bgp_flowspec/r1/zebra.conf b/tests/topotests/bgp_flowspec/r1/zebra.conf index e4d5a21194a9..4b103cb3984b 100644 --- a/tests/topotests/bgp_flowspec/r1/zebra.conf +++ b/tests/topotests/bgp_flowspec/r1/zebra.conf @@ -1,6 +1,7 @@ ! hostname r1 password zebra +ip table range 500 600 interface r1-eth0 ip address 10.0.1.1/24 ipv6 address 1001::1/112 diff --git a/zebra/table_manager.c b/zebra/table_manager.c index bb060588d28b..9f3b44f94479 100644 --- a/zebra/table_manager.c +++ b/zebra/table_manager.c @@ -55,10 +55,9 @@ #define RT_TABLE_ID_UNRESERVED_MIN 1 #define RT_TABLE_ID_UNRESERVED_MAX 0xffffffff -struct table_manager tbl_mgr; - DEFINE_MGROUP(TABLE_MGR, "Table Manager"); DEFINE_MTYPE_STATIC(TABLE_MGR, TM_CHUNK, "Table Manager Chunk"); +DEFINE_MTYPE_STATIC(TABLE_MGR, TM_TABLE, "Table Manager Context"); static void delete_table_chunk(void *val) { @@ -68,12 +67,21 @@ static void delete_table_chunk(void *val) /** * Init table manager */ -void table_manager_enable(ns_id_t ns_id) +void table_manager_enable(struct zebra_vrf *zvrf) { - if (ns_id != NS_DEFAULT) + + if (zvrf->tbl_mgr) return; - tbl_mgr.lc_list = list_new(); - tbl_mgr.lc_list->del = delete_table_chunk; + if (!vrf_is_backend_netns() && zvrf_id(zvrf) != VRF_DEFAULT) { + struct zebra_vrf *def = zebra_vrf_lookup_by_id(VRF_DEFAULT); + + if (def) + zvrf->tbl_mgr = def->tbl_mgr; + return; + } + zvrf->tbl_mgr = XCALLOC(MTYPE_TM_TABLE, sizeof(struct table_manager)); + zvrf->tbl_mgr->lc_list = list_new(); + zvrf->tbl_mgr->lc_list->del = delete_table_chunk; hook_register(zserv_client_close, release_daemon_table_chunks); } @@ -89,14 +97,19 @@ void table_manager_enable(ns_id_t ns_id) * @return Pointer to the assigned table chunk */ struct table_manager_chunk *assign_table_chunk(uint8_t proto, uint16_t instance, - uint32_t size) + uint32_t size, + struct zebra_vrf *zvrf) { struct table_manager_chunk *tmc; struct listnode *node; uint32_t start; + bool manual_conf = false; + + if (!zvrf) + return NULL; /* first check if there's one available */ - for (ALL_LIST_ELEMENTS_RO(tbl_mgr.lc_list, node, tmc)) { + for (ALL_LIST_ELEMENTS_RO(zvrf->tbl_mgr->lc_list, node, tmc)) { if (tmc->proto == NO_PROTO && tmc->end - tmc->start + 1 == size) { tmc->proto = proto; @@ -109,17 +122,26 @@ struct table_manager_chunk *assign_table_chunk(uint8_t proto, uint16_t instance, if (!tmc) return NULL; + if (zvrf->tbl_mgr->start || zvrf->tbl_mgr->end) + manual_conf = true; /* table RT IDs range are [1;252] and [256;0xffffffff] * - check if the requested range can be within the first range, * otherwise elect second one * - TODO : vrf-lites have their own table identifier. * In that case, table_id should be removed from the table range. */ - if (list_isempty(tbl_mgr.lc_list)) - start = RT_TABLE_ID_UNRESERVED_MIN; - else + if (list_isempty(zvrf->tbl_mgr->lc_list)) { + if (!manual_conf) + start = RT_TABLE_ID_UNRESERVED_MIN; + else + start = zvrf->tbl_mgr->start; + } else start = ((struct table_manager_chunk *)listgetdata( - listtail(tbl_mgr.lc_list)))->end + 1; + listtail(zvrf->tbl_mgr->lc_list))) + ->end + + 1; + + if (!manual_conf) { #if !defined(GNU_LINUX) /* BSD systems @@ -127,25 +149,35 @@ struct table_manager_chunk *assign_table_chunk(uint8_t proto, uint16_t instance, #else /* Linux Systems */ - /* if not enough room space between MIN and COMPAT, - * then begin after LOCAL - */ - if (start < RT_TABLE_ID_COMPAT && (size > - RT_TABLE_ID_COMPAT - - RT_TABLE_ID_UNRESERVED_MIN)) - start = RT_TABLE_ID_LOCAL + 1; + /* if not enough room space between MIN and COMPAT, + * then begin after LOCAL + */ + if (start < RT_TABLE_ID_COMPAT + && (size > RT_TABLE_ID_COMPAT - RT_TABLE_ID_UNRESERVED_MIN)) + start = RT_TABLE_ID_LOCAL + 1; #endif /* !def(GNU_LINUX) */ - tmc->start = start; - if (RT_TABLE_ID_UNRESERVED_MAX - size + 1 < start) { - flog_err(EC_ZEBRA_TM_EXHAUSTED_IDS, - "Reached max table id. Start/Size %u/%u", start, size); - XFREE(MTYPE_TM_CHUNK, tmc); - return NULL; + tmc->start = start; + if (RT_TABLE_ID_UNRESERVED_MAX - size + 1 < start) { + flog_err(EC_ZEBRA_TM_EXHAUSTED_IDS, + "Reached max table id. Start/Size %u/%u", + start, size); + XFREE(MTYPE_TM_CHUNK, tmc); + return NULL; + } + } else { + tmc->start = start; + if (zvrf->tbl_mgr->end - size + 1 < start) { + flog_err(EC_ZEBRA_TM_EXHAUSTED_IDS, + "Reached max table id. Start/Size %u/%u", + start, size); + XFREE(MTYPE_TM_CHUNK, tmc); + return NULL; + } } tmc->end = tmc->start + size - 1; tmc->proto = proto; tmc->instance = instance; - listnode_add(tbl_mgr.lc_list, tmc); + listnode_add(zvrf->tbl_mgr->lc_list, tmc); return tmc; } @@ -160,16 +192,23 @@ struct table_manager_chunk *assign_table_chunk(uint8_t proto, uint16_t instance, * @return 0 on success, -1 otherwise */ int release_table_chunk(uint8_t proto, uint16_t instance, uint32_t start, - uint32_t end) + uint32_t end, struct zebra_vrf *zvrf) { struct listnode *node; struct table_manager_chunk *tmc; int ret = -1; + struct table_manager *tbl_mgr; + + if (!zvrf) + return -1; + tbl_mgr = zvrf->tbl_mgr; + if (!tbl_mgr) + return ret; /* check that size matches */ zlog_debug("Releasing table chunk: %u - %u", start, end); /* find chunk and disown */ - for (ALL_LIST_ELEMENTS_RO(tbl_mgr.lc_list, node, tmc)) { + for (ALL_LIST_ELEMENTS_RO(tbl_mgr->lc_list, node, tmc)) { if (tmc->start != start) continue; if (tmc->end != end) @@ -208,24 +247,99 @@ int release_daemon_table_chunks(struct zserv *client) struct table_manager_chunk *tmc; int count = 0; int ret; + struct vrf *vrf; + struct zebra_vrf *zvrf; - for (ALL_LIST_ELEMENTS_RO(tbl_mgr.lc_list, node, tmc)) { - if (tmc->proto == proto && tmc->instance == instance) { - ret = release_table_chunk(tmc->proto, tmc->instance, - tmc->start, tmc->end); - if (ret == 0) - count++; + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { + zvrf = vrf->info; + + if (!zvrf) + continue; + if (!vrf_is_backend_netns() && vrf->vrf_id != VRF_DEFAULT) + continue; + for (ALL_LIST_ELEMENTS_RO(zvrf->tbl_mgr->lc_list, node, tmc)) { + if (tmc->proto == proto && tmc->instance == instance) { + ret = release_table_chunk( + tmc->proto, tmc->instance, tmc->start, + tmc->end, zvrf); + if (ret == 0) + count++; + } } } - zlog_debug("%s: Released %d table chunks", __func__, count); return count; } -void table_manager_disable(ns_id_t ns_id) +static void table_range_add(struct zebra_vrf *zvrf, uint32_t start, + uint32_t end) +{ + if (!zvrf->tbl_mgr) + return; + zvrf->tbl_mgr->start = start; + zvrf->tbl_mgr->end = end; +} + +void table_manager_disable(struct zebra_vrf *zvrf) { - if (ns_id != NS_DEFAULT) + if (!zvrf->tbl_mgr) + return; + if (!vrf_is_backend_netns() && zvrf_id(zvrf) != VRF_DEFAULT) { + zvrf->tbl_mgr = NULL; return; - list_delete(&tbl_mgr.lc_list); + } + list_delete(&zvrf->tbl_mgr->lc_list); + XFREE(MTYPE_TM_TABLE, zvrf->tbl_mgr); + zvrf->tbl_mgr = NULL; +} + +int table_manager_range(struct vty *vty, bool add, struct zebra_vrf *zvrf, + const char *start_table_str, const char *end_table_str) +{ + uint32_t start; + uint32_t end; + + if (add) { + if (!start_table_str || !end_table_str) { + vty_out(vty, "%% Labels not specified\n"); + return CMD_WARNING_CONFIG_FAILED; + } + start = atoi(start_table_str); + end = atoi(end_table_str); + if (end < start) { + vty_out(vty, "%% End table is less than Start table\n"); + return CMD_WARNING_CONFIG_FAILED; + } + +#if !defined(GNU_LINUX) +/* BSD systems + */ +#else + /* Linux Systems + */ + if ((start >= RT_TABLE_ID_COMPAT && start <= RT_TABLE_ID_LOCAL) + || (end >= RT_TABLE_ID_COMPAT + && end <= RT_TABLE_ID_LOCAL)) { + vty_out(vty, "%% Values forbidden in range [%u;%u]\n", + RT_TABLE_ID_COMPAT, RT_TABLE_ID_LOCAL); + return CMD_WARNING_CONFIG_FAILED; + } + if (start < RT_TABLE_ID_COMPAT && end > RT_TABLE_ID_LOCAL) { + vty_out(vty, + "%% Range overlaps range [%u;%u] forbidden\n", + RT_TABLE_ID_COMPAT, RT_TABLE_ID_LOCAL); + return CMD_WARNING_CONFIG_FAILED; + } +#endif + if (zvrf->tbl_mgr + && ((zvrf->tbl_mgr->start && zvrf->tbl_mgr->start != start) + || (zvrf->tbl_mgr->end && zvrf->tbl_mgr->end != end))) { + vty_out(vty, + "%% New range will be taken into account at restart\n"); + } + table_range_add(zvrf, start, end); + } else + table_range_add(zvrf, 0, 0); + return CMD_SUCCESS; } diff --git a/zebra/table_manager.h b/zebra/table_manager.h index 4f78f5097e63..fa1366842e45 100644 --- a/zebra/table_manager.h +++ b/zebra/table_manager.h @@ -57,15 +57,20 @@ struct table_manager_chunk { */ struct table_manager { struct list *lc_list; + uint32_t start; + uint32_t end; }; -void table_manager_enable(ns_id_t ns_id); +void table_manager_enable(struct zebra_vrf *zvrf); struct table_manager_chunk *assign_table_chunk(uint8_t proto, uint16_t instance, - uint32_t size); + uint32_t size, + struct zebra_vrf *zvrf); int release_table_chunk(uint8_t proto, uint16_t instance, uint32_t start, - uint32_t end); + uint32_t end, struct zebra_vrf *zvrf); int release_daemon_table_chunks(struct zserv *client); -void table_manager_disable(ns_id_t ns_id); +void table_manager_disable(struct zebra_vrf *zvrf); +int table_manager_range(struct vty *vty, bool add, struct zebra_vrf *zvrf, + const char *min, const char *max); #ifdef __cplusplus } diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 72c7071502d5..0aef1965d214 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -2827,7 +2827,7 @@ static void zread_label_manager_request(ZAPI_HANDLER_ARGS) } static void zread_get_table_chunk(struct zserv *client, struct stream *msg, - vrf_id_t vrf_id) + struct zebra_vrf *zvrf) { struct stream *s; uint32_t size; @@ -2839,7 +2839,7 @@ static void zread_get_table_chunk(struct zserv *client, struct stream *msg, /* Get data. */ STREAM_GETL(s, size); - tmc = assign_table_chunk(client->proto, client->instance, size); + tmc = assign_table_chunk(client->proto, client->instance, size, zvrf); if (!tmc) flog_err(EC_ZEBRA_TM_CANNOT_ASSIGN_CHUNK, "%s: Unable to assign Table Chunk of size %u", @@ -2848,13 +2848,14 @@ static void zread_get_table_chunk(struct zserv *client, struct stream *msg, zlog_debug("Assigned Table Chunk %u - %u", tmc->start, tmc->end); /* send response back */ - zsend_assign_table_chunk_response(client, vrf_id, tmc); + zsend_assign_table_chunk_response(client, zvrf_id(zvrf), tmc); stream_failure: return; } -static void zread_release_table_chunk(struct zserv *client, struct stream *msg) +static void zread_release_table_chunk(struct zserv *client, struct stream *msg, + struct zebra_vrf *zvrf) { struct stream *s; uint32_t start, end; @@ -2866,7 +2867,7 @@ static void zread_release_table_chunk(struct zserv *client, struct stream *msg) STREAM_GETL(s, start); STREAM_GETL(s, end); - release_table_chunk(client->proto, client->instance, start, end); + release_table_chunk(client->proto, client->instance, start, end, zvrf); stream_failure: return; @@ -2886,9 +2887,9 @@ static void zread_table_manager_request(ZAPI_HANDLER_ARGS) return; } if (hdr->command == ZEBRA_GET_TABLE_CHUNK) - zread_get_table_chunk(client, msg, zvrf_id(zvrf)); + zread_get_table_chunk(client, msg, zvrf); else if (hdr->command == ZEBRA_RELEASE_TABLE_CHUNK) - zread_release_table_chunk(client, msg); + zread_release_table_chunk(client, msg, zvrf); } } diff --git a/zebra/zebra_ns.c b/zebra/zebra_ns.c index 27b8a3ea477e..0f53de8c31c9 100644 --- a/zebra/zebra_ns.c +++ b/zebra/zebra_ns.c @@ -127,9 +127,6 @@ int zebra_ns_enable(ns_id_t ns_id, void **info) route_read(zns); kernel_read_pbr_rules(zns); - /* Initiate Table Manager per ZNS */ - table_manager_enable(ns_id); - return 0; } @@ -142,8 +139,6 @@ static int zebra_ns_disable_internal(struct zebra_ns *zns, bool complete) kernel_terminate(zns, complete); - table_manager_disable(zns->ns_id); - zns->ns_id = NS_DEFAULT; return 0; diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c index 4fbcc6f59647..e1623477267f 100644 --- a/zebra/zebra_vrf.c +++ b/zebra/zebra_vrf.c @@ -44,6 +44,7 @@ #ifndef VTYSH_EXTRACT_PL #include "zebra/zebra_vrf_clippy.c" #endif +#include "zebra/table_manager.h" static void zebra_vrf_table_create(struct zebra_vrf *zvrf, afi_t afi, safi_t safi); @@ -113,6 +114,10 @@ static int zebra_vrf_new(struct vrf *vrf) otable_init(&zvrf->other_tables); router_id_init(zvrf); + + /* Initiate Table Manager per ZNS */ + table_manager_enable(zvrf); + return 0; } @@ -176,6 +181,8 @@ static int zebra_vrf_disable(struct vrf *vrf) zlog_debug("VRF %s id %u is now inactive", zvrf_name(zvrf), zvrf_id(zvrf)); + table_manager_disable(zvrf); + /* Stop any VxLAN-EVPN processing. */ zebra_vxlan_vrf_disable(zvrf); @@ -503,6 +510,12 @@ static int vrf_config_write(struct vty *vty) if (zvrf->zebra_rnh_ipv6_default_route) vty_out(vty, "ipv6 nht resolve-via-default\n"); + + if (zvrf->tbl_mgr + && (zvrf->tbl_mgr->start || zvrf->tbl_mgr->end)) + vty_out(vty, "ip table range %u %u\n", + zvrf->tbl_mgr->start, + zvrf->tbl_mgr->end); } else { vty_frame(vty, "vrf %s\n", zvrf_name(zvrf)); if (zvrf->l3vni) @@ -517,6 +530,12 @@ static int vrf_config_write(struct vty *vty) if (zvrf->zebra_rnh_ipv6_default_route) vty_out(vty, " ipv6 nht resolve-via-default\n"); + + if (zvrf->tbl_mgr && vrf_is_backend_netns() + && (zvrf->tbl_mgr->start || zvrf->tbl_mgr->end)) + vty_out(vty, " ip table range %u %u\n", + zvrf->tbl_mgr->start, + zvrf->tbl_mgr->end); } diff --git a/zebra/zebra_vrf.h b/zebra/zebra_vrf.h index f32f09850b6a..27342908c47e 100644 --- a/zebra/zebra_vrf.h +++ b/zebra/zebra_vrf.h @@ -177,6 +177,8 @@ struct zebra_vrf { uint64_t lsp_installs; uint64_t lsp_removals; + struct table_manager *tbl_mgr; + #if defined(HAVE_RTADV) struct rtadv rtadv; #endif /* HAVE_RTADV */ diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index b204b30ca7a4..b787c7c34285 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -59,6 +59,7 @@ #include "northbound_cli.h" #include "zebra/zebra_nb.h" #include "zebra/kernel_netlink.h" +#include "zebra/table_manager.h" extern int allow_delete; @@ -4298,6 +4299,31 @@ DEFUN_HIDDEN(no_zebra_kernel_netlink_batch_tx_buf, #endif /* HAVE_NETLINK */ +DEFUN(ip_table_range, ip_table_range_cmd, + "[no] ip table range (1-4294967295) (1-4294967295)", + NO_STR IP_STR + "table configuration\n" + "Configure table range\n" + "Start Routing Table\n" + "End Routing Table\n") +{ + ZEBRA_DECLVAR_CONTEXT(vrf, zvrf); + + if (!zvrf) + return CMD_WARNING; + + if (zvrf_id(zvrf) != VRF_DEFAULT && !vrf_is_backend_netns()) { + vty_out(vty, + "VRF subcommand does not make any sense in l3mdev based vrf's\n"); + return CMD_WARNING; + } + + if (strmatch(argv[0]->text, "no")) + return table_manager_range(vty, false, zvrf, NULL, NULL); + + return table_manager_range(vty, true, zvrf, argv[3]->arg, argv[4]->arg); +} + /* IP node for static routes. */ static int zebra_ip_config(struct vty *vty); static struct cmd_node ip_node = { @@ -4446,6 +4472,9 @@ void zebra_vty_init(void) install_element(CONFIG_NODE, &zebra_dplane_queue_limit_cmd); install_element(CONFIG_NODE, &no_zebra_dplane_queue_limit_cmd); + install_element(CONFIG_NODE, &ip_table_range_cmd); + install_element(VRF_NODE, &ip_table_range_cmd); + #ifdef HAVE_NETLINK install_element(CONFIG_NODE, &zebra_kernel_netlink_batch_tx_buf_cmd); install_element(CONFIG_NODE, &no_zebra_kernel_netlink_batch_tx_buf_cmd); From fe226e844aa896d4574b2d575c3660c95d4c3345 Mon Sep 17 00:00:00 2001 From: Christian Hopps Date: Sat, 25 Sep 2021 14:59:13 -0400 Subject: [PATCH 006/188] doc: add sudo environment setup info for topotests Signed-off-by: Christian Hopps --- doc/developer/topotests.rst | 82 ++++++++++++++++++++++++++----------- 1 file changed, 59 insertions(+), 23 deletions(-) diff --git a/doc/developer/topotests.rst b/doc/developer/topotests.rst index c52d210ee539..b4f6ec521c06 100644 --- a/doc/developer/topotests.rst +++ b/doc/developer/topotests.rst @@ -130,12 +130,42 @@ And create ``frr`` user and ``frrvty`` group as follows: Executing Tests --------------- +Configure your sudo environment +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Topotests must be run as root. Normally this will be accomplished through the +use of the ``sudo`` command. In order for topotests to be able to open new +windows (either XTerm or byobu/screen/tmux windows) certain environment +variables must be passed through the sudo command. One way to do this is to +specify the :option:`-E` flag to ``sudo``. This will carry over most if not all +your environment variables include ``PATH``. For example: + +.. code:: shell + + sudo -E python3 -m pytest -s -v + +If you do not wish to use :option:`-E` (e.g., to avoid ``sudo`` inheriting +``PATH``) you can modify your `/etc/sudoers` config file to specifically pass +the environment variables required by topotests. Add the following commands to +your ``/etc/sudoers`` config file. + +.. code:: shell + + Defaults env_keep="TMUX" + Defaults env_keep+="TMUX_PANE" + Defaults env_keep+="STY" + Defaults env_keep+="DISPLAY" + +If there was already an ``env_keep`` configuration there be sure to use the +``+=`` rather than ``=`` on the first line above as well. + + Execute all tests in distributed test mode ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code:: shell - py.test -s -v -nauto --dist=loadfile + sudo -E pytest -s -v -nauto --dist=loadfile The above command must be executed from inside the topotests directory. @@ -167,7 +197,7 @@ the run. Here we see that 4 tests have failed. We an dig deeper by displaying the captured logs and errors. First let's redisplay the results enumerated by adding -the ``-E`` flag +the :option:`-E` flag .. code:: shell @@ -353,6 +383,12 @@ be run within ``tmux`` (or ``screen``)_, as ``gdb``, the shell or ``vtysh`` will be launched using that windowing program, otherwise ``xterm`` will be attempted to launch the given programs. +NOTE: you must run the topotest (pytest) such that your DISPLAY, STY or TMUX +environment variables are carried over. You can do this by passing the +:option:`-E` flag to ``sudo`` or you can modify your ``/etc/sudoers`` config to +automatically pass that environment variable through to the ``sudo`` +environment. + .. _screen: https://www.gnu.org/software/screen/ .. _tmux: https://github.com/tmux/tmux/wiki @@ -364,7 +400,7 @@ One can have a debugging CLI invoked on test failures by specifying the .. code:: shell - pytest --cli-on-error all-protocol-startup + sudo -E pytest --cli-on-error all-protocol-startup The debugging CLI can run shell or vtysh commands on any combination of routers It can also open shells or vtysh in their own windows for any combination of @@ -415,7 +451,7 @@ Here's an example of launching ``vtysh`` on routers ``rt1`` and ``rt2``. .. code:: shell - pytest --vtysh=rt1,rt2 all-protocol-startup + sudo -E pytest --vtysh=rt1,rt2 all-protocol-startup Debugging with GDB """""""""""""""""" @@ -436,7 +472,7 @@ Here's an example of launching ``zebra`` and ``bgpd`` inside ``gdb`` on router .. code:: shell - pytest --gdb-routers=r1 \ + sudo -E pytest --gdb-routers=r1 \ --gdb-daemons=bgpd,zebra \ --gdb-breakpoints=nb_config_diff \ all-protocol-startup @@ -453,7 +489,7 @@ memleak detection is enabled. .. code:: shell - pytest --valgrind-memleaks all-protocol-startup + sudo -E pytest --valgrind-memleaks all-protocol-startup .. _topotests_docker: @@ -555,21 +591,21 @@ top level directory of topotest: $ # Change to the top level directory of topotests. $ cd path/to/topotests $ # Tests must be run as root, since micronet requires it. - $ sudo pytest + $ sudo -E pytest In order to run a specific test, you can use the following command: .. code:: shell $ # running a specific topology - $ sudo pytest ospf-topo1/ + $ sudo -E pytest ospf-topo1/ $ # or inside the test folder $ cd ospf-topo1 - $ sudo pytest # to run all tests inside the directory - $ sudo pytest test_ospf_topo1.py # to run a specific test + $ sudo -E pytest # to run all tests inside the directory + $ sudo -E pytest test_ospf_topo1.py # to run a specific test $ # or outside the test folder $ cd .. - $ sudo pytest ospf-topo1/test_ospf_topo1.py # to run a specific one + $ sudo -E pytest ospf-topo1/test_ospf_topo1.py # to run a specific one The output of the tested daemons will be available at the temporary folder of your machine: @@ -588,7 +624,7 @@ You can also run memory leak tests to get reports: .. code:: shell $ # Set the environment variable to apply to a specific test... - $ sudo env TOPOTESTS_CHECK_MEMLEAK="/tmp/memleak_report_" pytest ospf-topo1/test_ospf_topo1.py + $ sudo -E env TOPOTESTS_CHECK_MEMLEAK="/tmp/memleak_report_" pytest ospf-topo1/test_ospf_topo1.py $ # ...or apply to all tests adding this line to the configuration file $ echo 'memleak_path = /tmp/memleak_report_' >> pytest.ini $ # You can also use your editor @@ -626,12 +662,12 @@ Some things to keep in mind: - Using sleep is almost never appropriate. As an example: if the test resets the peers in BGP, the test should look for the peers re-converging instead of just sleeping an arbitrary amount of time and continuing on. See - `verify_bgp_convergence` as a good example of this. In particular look at it's - use of the `@retry` decorator. If you are having troubles figuring out what to - look for, please do not be afraid to ask. + ``verify_bgp_convergence`` as a good example of this. In particular look at + it's use of the ``@retry`` decorator. If you are having troubles figuring out + what to look for, please do not be afraid to ask. - Don't duplicate effort. There exists many protocol utility functions that can - be found in their eponymous module under `tests/topotests/lib/` (e.g., - `ospf.py`) + be found in their eponymous module under ``tests/topotests/lib/`` (e.g., + ``ospf.py``) @@ -827,11 +863,11 @@ that using the following example commands: .. code:: shell $ # Running your bootstraped topology - $ sudo pytest -s --topology-only new-topo/test_new_topo.py + $ sudo -E pytest -s --topology-only new-topo/test_new_topo.py $ # Running the test_template.py topology - $ sudo pytest -s --topology-only example-test/test_template.py + $ sudo -E pytest -s --topology-only example-test/test_template.py $ # Running the ospf_topo1.py topology - $ sudo pytest -s --topology-only ospf-topo1/test_ospf_topo1.py + $ sudo -E pytest -s --topology-only ospf-topo1/test_ospf_topo1.py Parameters explanation: @@ -851,7 +887,7 @@ output: .. code:: shell - frr/tests/topotests# sudo pytest -s --topology-only ospf_topo1/test_ospf_topo1.py + frr/tests/topotests# sudo -E pytest -s --topology-only ospf_topo1/test_ospf_topo1.py ============================= test session starts ============================== platform linux -- Python 3.9.2, pytest-6.2.4, py-1.10.0, pluggy-0.13.1 rootdir: /home/chopps/w/frr/tests/topotests, configfile: pytest.ini @@ -1011,8 +1047,8 @@ Example: # topology build code ... -- pytest setup/teardown fixture to start the topology and supply `tgen` argument - to tests. +- pytest setup/teardown fixture to start the topology and supply ``tgen`` + argument to tests. .. code:: py From e2874251ed09a9d33bb409b5dd96a8a21b4507ff Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sun, 26 Sep 2021 19:16:10 -0400 Subject: [PATCH 007/188] ospf6d: Log messages cannot have newlines Signed-off-by: Donald Sharp --- ospf6d/ospf6_top.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index 894ebc768133..6fe70552027b 100644 --- a/ospf6d/ospf6_top.c +++ b/ospf6d/ospf6_top.c @@ -651,7 +651,7 @@ bool ospf6_router_id_update(struct ospf6 *ospf6, bool init) for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) { if (oa->full_nbrs) { zlog_err( - "%s: cannot update router-id. Run the \"clear ipv6 ospf6 process\" command\n", + "%s: cannot update router-id. Run the \"clear ipv6 ospf6 process\" command", __func__); return false; } From 0e5cdd59eb0f080c4c82b5b54597b16a94775732 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sun, 26 Sep 2021 19:36:03 -0400 Subject: [PATCH 008/188] bgpd: Don't lookup paf structure get straight to the point The paf data structure is stored based upon an internal bgp enum. The code is looking over all AFI/SAFI's and doing a paf_af_find which then calls afindex to find the right paf structure. Let's just loop over the peer->peer_af_array[] and cut straight to the chase. Under some loads the paf_af_find was taking up 6% of the run time. This removes it entirely. Signed-off-by: Donald Sharp --- bgpd/bgp_packet.c | 18 ++++++++++++++---- bgpd/bgp_vty.c | 10 ++++++++-- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index 4fdb92ce7e36..bb2dbc942766 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -337,11 +337,13 @@ static void bgp_write_proceed_actions(struct peer *peer) struct peer_af *paf; struct bpacket *next_pkt; struct update_subgroup *subgrp; + enum bgp_af_index index; - FOREACH_AFI_SAFI (afi, safi) { - paf = peer_af_find(peer, afi, safi); + for (index = BGP_AF_START; index < BGP_AF_MAX; index++) { + paf = peer->peer_af_array[index]; if (!paf) continue; + subgrp = paf->subgroup; if (!subgrp) continue; @@ -364,6 +366,9 @@ static void bgp_write_proceed_actions(struct peer *peer) return; } + afi = paf->afi; + safi = paf->safi; + /* No packets to send, see if EOR is pending */ if (CHECK_FLAG(peer->cap, PEER_CAP_RESTART_RCV)) { if (!subgrp->t_coalesce && peer->afc_nego[afi][safi] @@ -415,11 +420,16 @@ int bgp_generate_updgrp_packets(struct thread *thread) return 0; do { + enum bgp_af_index index; + s = NULL; - FOREACH_AFI_SAFI (afi, safi) { - paf = peer_af_find(peer, afi, safi); + for (index = BGP_AF_START; index < BGP_AF_MAX; index++) { + paf = peer->peer_af_array[index]; if (!paf || !PAF_SUBGRP(paf)) continue; + + afi = paf->afi; + safi = paf->safi; next_pkt = paf->next_pkt_to_send; /* diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 8a3e74e8a417..14f4fb731050 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -912,13 +912,19 @@ static int bgp_peer_clear(struct peer *peer, afi_t afi, safi_t safi, if ((afi == AFI_UNSPEC) && (safi == SAFI_UNSPEC)) { afi_t tmp_afi; safi_t tmp_safi; + enum bgp_af_index index; + + for (index = BGP_AF_START; index < BGP_AF_MAX; index++) { + paf = peer->peer_af_array[index]; + if (!paf) + continue; - FOREACH_AFI_SAFI (tmp_afi, tmp_safi) { - paf = peer_af_find(peer, tmp_afi, tmp_safi); if (paf && paf->subgroup) SET_FLAG(paf->subgroup->sflags, SUBGRP_STATUS_FORCE_UPDATES); + tmp_afi = paf->afi; + tmp_safi = paf->safi; if (!peer->afc[tmp_afi][tmp_safi]) continue; From 200f56710a462354f55e6189a0d10df03415c1e4 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Mon, 27 Sep 2021 10:33:33 +0200 Subject: [PATCH 009/188] pimd: fix UAF/heap corruption in BSM code This `XFREE()` call is in plainly in the wrong spot. `rp_all` (the 224.0.0.0/4 entry) isn't supposed to be free'd ever, and the conditional above makes quite clear that it remains in use. It may be possible to exploit this as a heap corruption bug, maybe even as RCE. I haven't tried; I randomly noticed this while working on the BSM code. Luckily this code is only run by the CLI for the clear command, so the surface is very small. Signed-off-by: David Lamparter --- pimd/pim_cmd.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 14aa71052422..5fb2ddf732da 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -4140,10 +4140,9 @@ static void clear_pim_bsr_db(struct pim_instance *pim) rpnode->info = NULL; route_unlock_node(rpnode); route_unlock_node(rpnode); + XFREE(MTYPE_PIM_RP, rp_info); } - XFREE(MTYPE_PIM_RP, rp_info); - pim_free_bsgrp_node(bsgrp->scope->bsrp_table, &bsgrp->group); pim_free_bsgrp_data(bsgrp); } From 94ca37e0a9c9f7133e9b9ca3ec9d10303bca4e77 Mon Sep 17 00:00:00 2001 From: Donatas Abraitis Date: Mon, 27 Sep 2021 15:20:51 +0300 Subject: [PATCH 010/188] tools: Add coccinelle script to catch \n or \r at the end of zlog_* Signed-off-by: Donatas Abraitis --- tools/coccinelle/zlog_no_newline.cocci | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 tools/coccinelle/zlog_no_newline.cocci diff --git a/tools/coccinelle/zlog_no_newline.cocci b/tools/coccinelle/zlog_no_newline.cocci new file mode 100644 index 000000000000..20cf9d2c78a6 --- /dev/null +++ b/tools/coccinelle/zlog_no_newline.cocci @@ -0,0 +1,20 @@ +// zlog_* should not have \n or \r at the end usually. +// spatch --sp-file tools/coccinelle/zlog_no_newline.cocci --macro-file tools/cocci.h ./ 2>/dev/null + +@r@ +expression fmt; +identifier func =~ "zlog_"; +position p; +@@ +( + func(fmt)@p +| + func(fmt, ...)@p +) + +@script:python@ +fmt << r.fmt; +p << r.p; +@@ +if "\\n" in str(fmt) or "\\r" in str(fmt): + print("Newline in logging function detected %s:%s:%s:%s" % (p[0].file, p[0].line, p[0].column, fmt)) From 4aabcba0f15d9a37088bfc1c2787d45ed58592e5 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 24 Sep 2021 16:46:09 -0400 Subject: [PATCH 011/188] zebra: Being able to use the default route is a boolean not an int Signed-off-by: Donald Sharp --- zebra/zebra_vrf.h | 4 ++-- zebra/zebra_vty.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/zebra/zebra_vrf.h b/zebra/zebra_vrf.h index f32f09850b6a..eae8e3792463 100644 --- a/zebra/zebra_vrf.h +++ b/zebra/zebra_vrf.h @@ -181,8 +181,8 @@ struct zebra_vrf { struct rtadv rtadv; #endif /* HAVE_RTADV */ - int zebra_rnh_ip_default_route; - int zebra_rnh_ipv6_default_route; + bool zebra_rnh_ip_default_route; + bool zebra_rnh_ipv6_default_route; }; #define PROTO_RM_NAME(zvrf, afi, rtype) zvrf->proto_rm[afi][rtype].name #define NHT_RM_NAME(zvrf, afi, rtype) zvrf->nht_rm[afi][rtype].name diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 79087c584992..9d1df98d3772 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -1378,7 +1378,7 @@ DEFUN (ip_nht_default_route, if (zvrf->zebra_rnh_ip_default_route) return CMD_SUCCESS; - zvrf->zebra_rnh_ip_default_route = 1; + zvrf->zebra_rnh_ip_default_route = true; zebra_evaluate_rnh(zvrf, AFI_IP, 0, RNH_NEXTHOP_TYPE, NULL); return CMD_SUCCESS; @@ -1717,7 +1717,7 @@ DEFUN (no_ip_nht_default_route, if (!zvrf->zebra_rnh_ip_default_route) return CMD_SUCCESS; - zvrf->zebra_rnh_ip_default_route = 0; + zvrf->zebra_rnh_ip_default_route = false; zebra_evaluate_rnh(zvrf, AFI_IP, 0, RNH_NEXTHOP_TYPE, NULL); return CMD_SUCCESS; } @@ -1737,7 +1737,7 @@ DEFUN (ipv6_nht_default_route, if (zvrf->zebra_rnh_ipv6_default_route) return CMD_SUCCESS; - zvrf->zebra_rnh_ipv6_default_route = 1; + zvrf->zebra_rnh_ipv6_default_route = true; zebra_evaluate_rnh(zvrf, AFI_IP6, 0, RNH_NEXTHOP_TYPE, NULL); return CMD_SUCCESS; } @@ -1758,7 +1758,7 @@ DEFUN (no_ipv6_nht_default_route, if (!zvrf->zebra_rnh_ipv6_default_route) return CMD_SUCCESS; - zvrf->zebra_rnh_ipv6_default_route = 0; + zvrf->zebra_rnh_ipv6_default_route = false; zebra_evaluate_rnh(zvrf, AFI_IP6, 0, RNH_NEXTHOP_TYPE, NULL); return CMD_SUCCESS; } From ed6cec97d7f2c5abbc5a2ef2f087a614c54ddcb1 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 24 Sep 2021 15:51:18 -0400 Subject: [PATCH 012/188] *: Add resolve via default flag --- bgpd/bgp_nht.c | 14 ++++++++------ lib/zclient.c | 5 +++-- lib/zclient.h | 2 +- ospf6d/ospf6_zebra.c | 3 ++- pbrd/pbr_zebra.c | 2 +- pimd/pim_nht.c | 3 ++- sharpd/sharp_zebra.c | 2 +- staticd/static_zebra.c | 2 +- zebra/rib.h | 7 ++++--- zebra/zapi_msg.c | 12 ++++++++++-- zebra/zebra_rnh.c | 8 ++++++-- 11 files changed, 39 insertions(+), 21 deletions(-) diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index c77e240855a8..87d76489ba29 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -843,6 +843,7 @@ static int make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p) static void sendmsg_zebra_rnh(struct bgp_nexthop_cache *bnc, int command) { bool exact_match = false; + bool resolve_via_default = false; int ret; if (!zclient) @@ -863,11 +864,12 @@ static void sendmsg_zebra_rnh(struct bgp_nexthop_cache *bnc, int command) "%s: We have not connected yet, cannot send nexthops", __func__); } - if ((command == ZEBRA_NEXTHOP_REGISTER - || command == ZEBRA_IMPORT_ROUTE_REGISTER) - && (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED) - || CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH))) - exact_match = true; + if (command == ZEBRA_NEXTHOP_REGISTER) { + if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)) + exact_match = true; + if (CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH)) + resolve_via_default = true; + } if (BGP_DEBUG(zebra, ZEBRA)) zlog_debug("%s: sending cmd %s for %pFX (vrf %s)", __func__, @@ -875,7 +877,7 @@ static void sendmsg_zebra_rnh(struct bgp_nexthop_cache *bnc, int command) bnc->bgp->name_pretty); ret = zclient_send_rnh(zclient, command, &bnc->prefix, exact_match, - bnc->bgp->vrf_id); + resolve_via_default, bnc->bgp->vrf_id); /* TBD: handle the failure */ if (ret == ZCLIENT_SEND_FAILURE) flog_warn(EC_BGP_ZEBRA_SEND, diff --git a/lib/zclient.c b/lib/zclient.c index dde60a6c9032..bdc7cd5c75f9 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -765,7 +765,8 @@ static int zclient_connect(struct thread *t) enum zclient_send_status zclient_send_rnh(struct zclient *zclient, int command, const struct prefix *p, - bool exact_match, vrf_id_t vrf_id) + bool exact_match, + bool resolve_via_def, vrf_id_t vrf_id) { struct stream *s; @@ -773,7 +774,7 @@ enum zclient_send_status zclient_send_rnh(struct zclient *zclient, int command, stream_reset(s); zclient_create_header(s, command, vrf_id); stream_putc(s, (exact_match) ? 1 : 0); - + stream_putc(s, (resolve_via_def) ? 1 : 0); stream_putw(s, PREFIX_FAMILY(p)); stream_putc(s, p->prefixlen); switch (PREFIX_FAMILY(p)) { diff --git a/lib/zclient.h b/lib/zclient.h index f9438d5db71a..d21ea621e223 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -1107,7 +1107,7 @@ extern enum zclient_send_status zclient_route_send(uint8_t, struct zclient *, struct zapi_route *); extern enum zclient_send_status zclient_send_rnh(struct zclient *zclient, int command, const struct prefix *p, - bool exact_match, vrf_id_t vrf_id); + bool exact_match, bool resolve_via_default, vrf_id_t vrf_id); int zapi_nexthop_encode(struct stream *s, const struct zapi_nexthop *api_nh, uint32_t api_flags, uint32_t api_message); extern int zapi_route_encode(uint8_t, struct stream *, struct zapi_route *); diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c index 1a0c5a9971ed..2e2b069fd604 100644 --- a/ospf6d/ospf6_zebra.c +++ b/ospf6d/ospf6_zebra.c @@ -154,7 +154,8 @@ void ospf6_zebra_import_default_route(struct ospf6 *ospf6, bool unreg) zserv_command_string(command), &prefix, ospf6->vrf_id); - if (zclient_send_rnh(zclient, command, &prefix, true, ospf6->vrf_id) + if (zclient_send_rnh(zclient, command, &prefix, false, true, + ospf6->vrf_id) == ZCLIENT_SEND_FAILURE) flog_err(EC_LIB_ZAPI_SOCKET, "%s: zclient_send_rnh() failed", __func__); diff --git a/pbrd/pbr_zebra.c b/pbrd/pbr_zebra.c index 28def509d5eb..643269e34eac 100644 --- a/pbrd/pbr_zebra.c +++ b/pbrd/pbr_zebra.c @@ -478,7 +478,7 @@ void pbr_send_rnh(struct nexthop *nhop, bool reg) break; } - if (zclient_send_rnh(zclient, command, &p, false, nhop->vrf_id) + if (zclient_send_rnh(zclient, command, &p, false, false, nhop->vrf_id) == ZCLIENT_SEND_FAILURE) { zlog_warn("%s: Failure to send nexthop to zebra", __func__); } diff --git a/pimd/pim_nht.c b/pimd/pim_nht.c index 23ba3498ae6d..50cfc297d4d4 100644 --- a/pimd/pim_nht.c +++ b/pimd/pim_nht.c @@ -54,7 +54,8 @@ void pim_sendmsg_zebra_rnh(struct pim_instance *pim, struct zclient *zclient, int ret; p = &(pnc->rpf.rpf_addr); - ret = zclient_send_rnh(zclient, command, p, false, pim->vrf->vrf_id); + ret = zclient_send_rnh(zclient, command, p, false, false, + pim->vrf->vrf_id); if (ret == ZCLIENT_SEND_FAILURE) zlog_warn("sendmsg_nexthop: zclient_send_message() failed"); diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c index 2575475dd22a..48c9e8ced58d 100644 --- a/sharpd/sharp_zebra.c +++ b/sharpd/sharp_zebra.c @@ -638,7 +638,7 @@ void sharp_zebra_nexthop_watch(struct prefix *p, vrf_id_t vrf_id, bool import, command = ZEBRA_IMPORT_ROUTE_UNREGISTER; } - if (zclient_send_rnh(zclient, command, p, connected, vrf_id) + if (zclient_send_rnh(zclient, command, p, connected, false, vrf_id) == ZCLIENT_SEND_FAILURE) zlog_warn("%s: Failure to send nexthop to zebra", __func__); } diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c index 452b5c42a4c6..a01ecad815d6 100644 --- a/staticd/static_zebra.c +++ b/staticd/static_zebra.c @@ -332,7 +332,7 @@ void static_zebra_nht_register(struct static_nexthop *nh, bool reg) static_nht_hash_free(nhtd); } - if (zclient_send_rnh(zclient, cmd, &p, false, nh->nh_vrf_id) + if (zclient_send_rnh(zclient, cmd, &p, false, false, nh->nh_vrf_id) == ZCLIENT_SEND_FAILURE) zlog_warn("%s: Failure to send nexthop to zebra", __func__); } diff --git a/zebra/rib.h b/zebra/rib.h index 8887053a4c80..0f9d32471fae 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -54,9 +54,10 @@ PREDECL_LIST(rnh_list); struct rnh { uint8_t flags; -#define ZEBRA_NHT_CONNECTED 0x1 -#define ZEBRA_NHT_DELETED 0x2 -#define ZEBRA_NHT_EXACT_MATCH 0x4 +#define ZEBRA_NHT_CONNECTED 0x1 +#define ZEBRA_NHT_DELETED 0x2 +#define ZEBRA_NHT_EXACT_MATCH 0x4 +#define ZEBRA_NHT_RESOLVE_VIA_DEFAULT 0x8 /* VRF identifier. */ vrf_id_t vrf_id; diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 496849251a4a..775e2a4b08a9 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -1179,6 +1179,7 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS) struct prefix p; unsigned short l = 0; uint8_t flags = 0; + uint8_t resolve_via_default; uint16_t type = cmd2type[hdr->command]; bool exist; bool flag_changed = false; @@ -1198,9 +1199,10 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS) while (l < hdr->length) { STREAM_GETC(s, flags); + STREAM_GETC(s, resolve_via_default); STREAM_GETW(s, p.family); STREAM_GETC(s, p.prefixlen); - l += 4; + l += 5; if (p.family == AF_INET) { client->v4_nh_watch_add_cnt++; if (p.prefixlen > IPV4_MAX_BITLEN) { @@ -1250,6 +1252,9 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS) UNSET_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH); } + if (resolve_via_default) + SET_FLAG(rnh->flags, ZEBRA_NHT_RESOLVE_VIA_DEFAULT); + if (orig_flags != rnh->flags) flag_changed = true; @@ -1285,13 +1290,16 @@ static void zread_rnh_unregister(ZAPI_HANDLER_ARGS) while (l < hdr->length) { uint8_t flags; + STREAM_GETC(s, flags); + if (flags != 0) + goto stream_failure; STREAM_GETC(s, flags); if (flags != 0) goto stream_failure; STREAM_GETW(s, p.family); STREAM_GETC(s, p.prefixlen); - l += 4; + l += 5; if (p.family == AF_INET) { client->v4_nh_watch_rem_cnt++; if (p.prefixlen > IPV4_MAX_BITLEN) { diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index 017a4aae7f7d..636fa927117d 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -700,10 +700,14 @@ zebra_rnh_resolve_nexthop_entry(struct zebra_vrf *zvrf, afi_t afi, * match route to be exact if so specified */ if (is_default_prefix(&rn->p) - && !rnh_resolve_via_default(zvrf, rn->p.family)) { + && (!CHECK_FLAG(rnh->flags, ZEBRA_NHT_RESOLVE_VIA_DEFAULT) + && !rnh_resolve_via_default(zvrf, rn->p.family))) { if (IS_ZEBRA_DEBUG_NHT_DETAILED) zlog_debug( - " Not allowed to resolve through default prefix"); + " Not allowed to resolve through default prefix: rnh->resolve_via_default: %u", + CHECK_FLAG( + rnh->flags, + ZEBRA_NHT_RESOLVE_VIA_DEFAULT)); return NULL; } From b8210849b8ac1abe2d5d9a5ab2459abfde65efa5 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 24 Sep 2021 10:10:31 -0400 Subject: [PATCH 013/188] bgpd: Make bgp ready to remove distinction between 2 nh tracking types Allow bgp to figure out if it cares about address resolution instead of having zebra care about it. This will allow the removal of the zapi type for import checking and just use nexthop resolution. Effectively we just look up the route being returned and if it is in either table we just handle it instead of looking for clues from the zapi message type. Signed-off-by: Donald Sharp --- bgpd/bgp_nht.c | 40 ++++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index 87d76489ba29..90fa907308cf 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -664,7 +664,7 @@ void bgp_nht_interface_events(struct peer *peer) void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id) { struct bgp_nexthop_cache_head *tree = NULL; - struct bgp_nexthop_cache *bnc; + struct bgp_nexthop_cache *bnc_nhc, *bnc_import; struct bgp *bgp; struct zapi_route nhr; afi_t afi; @@ -685,22 +685,38 @@ void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id) } afi = family2afi(nhr.prefix.family); - if (command == ZEBRA_NEXTHOP_UPDATE) - tree = &bgp->nexthop_cache_table[afi]; - else if (command == ZEBRA_IMPORT_CHECK_UPDATE) - tree = &bgp->import_check_table[afi]; + tree = &bgp->nexthop_cache_table[afi]; - bnc = bnc_find(tree, &nhr.prefix, nhr.srte_color); - if (!bnc) { + bnc_nhc = bnc_find(tree, &nhr.prefix, nhr.srte_color); + if (!bnc_nhc) { if (BGP_DEBUG(nht, NHT)) zlog_debug( - "parse nexthop update(%pFX(%u)(%s)): bnc info not found", + "parse nexthop update(%pFX(%u)(%s)): bnc info not found for nexthop cache", + &nhr.prefix, nhr.srte_color, bgp->name_pretty); + } else + bgp_process_nexthop_update(bnc_nhc, &nhr); + + tree = &bgp->import_check_table[afi]; + + bnc_import = bnc_find(tree, &nhr.prefix, nhr.srte_color); + if (!bnc_import) { + if (BGP_DEBUG(nht, NHT)) + zlog_debug( + "parse nexthop update(%pFX(%u)(%s)): bnc info not found for import check", &nhr.prefix, nhr.srte_color, bgp->name_pretty); return; + } else { + if (nhr.type == ZEBRA_ROUTE_BGP + || !prefix_same(&bnc_import->prefix, &nhr.prefix)) { + if (BGP_DEBUG(nht, NHT)) + zlog_debug( + "%s: Import Check does not resolve to the same prefix for %pFX received %pFX", + __func__, &bnc_import->prefix, &nhr.prefix); + return; + } + bgp_process_nexthop_update(bnc_import, &nhr); } - bgp_process_nexthop_update(bnc, &nhr); - /* * HACK: if any BGP route is dependant on an SR-policy that doesn't * exist, zebra will never send NH updates relative to that policy. In @@ -712,12 +728,12 @@ void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id) * which should provide a better infrastructure to solve this issue in * a more efficient and elegant way. */ - if (nhr.srte_color == 0) { + if (nhr.srte_color == 0 && bnc_nhc) { struct bgp_nexthop_cache *bnc_iter; frr_each (bgp_nexthop_cache, &bgp->nexthop_cache_table[afi], bnc_iter) { - if (!prefix_same(&bnc->prefix, &bnc_iter->prefix) + if (!prefix_same(&bnc_import->prefix, &bnc_iter->prefix) || bnc_iter->srte_color == 0 || CHECK_FLAG(bnc_iter->flags, BGP_NEXTHOP_VALID)) continue; From ad5c8f67a8aa57d681c4df337dbbfe895529c080 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 27 Sep 2021 08:23:41 -0400 Subject: [PATCH 014/188] ospf6d: Make ospfv3 use normal address resolution instead of import route OSPFv3 recently introduced the usage of import route. Switch it back to using the normal ZEBRA_NEXTHOP_REGISTER command. Signed-off-by: Donald Sharp --- ospf6d/ospf6_zebra.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c index 2e2b069fd604..81573da3a627 100644 --- a/ospf6d/ospf6_zebra.c +++ b/ospf6d/ospf6_zebra.c @@ -145,9 +145,9 @@ void ospf6_zebra_import_default_route(struct ospf6 *ospf6, bool unreg) prefix.prefixlen = 0; if (unreg) - command = ZEBRA_IMPORT_ROUTE_UNREGISTER; + command = ZEBRA_NEXTHOP_UNREGISTER; else - command = ZEBRA_IMPORT_ROUTE_REGISTER; + command = ZEBRA_NEXTHOP_REGISTER; if (IS_OSPF6_DEBUG_ZEBRA(SEND)) zlog_debug("%s: sending cmd %s for %pFX (vrf %u)", __func__, @@ -721,7 +721,7 @@ void ospf6_zebra_init(struct thread_master *master) ospf6_zebra_if_address_update_delete; zclient->redistribute_route_add = ospf6_zebra_read_route; zclient->redistribute_route_del = ospf6_zebra_read_route; - zclient->import_check_update = ospf6_zebra_import_check_update; + zclient->nexthop_update = ospf6_zebra_import_check_update; /* Install command element for zebra node. */ install_element(VIEW_NODE, &show_ospf6_zebra_cmd); From 3d174ce08db7489e2424ac16f35557c9627c75e0 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 24 Sep 2021 10:32:30 -0400 Subject: [PATCH 015/188] *: Remove the ZEBRA_IMPORT_ROUTE_XXX zapi messages These are no longer really needed. The client just needs to call nexthop resolution instead. So let's remove the zapi types. Signed-off-by: Donald Sharp --- bgpd/bgp_nht.c | 16 ++++------------ bgpd/bgp_zebra.c | 7 ------- lib/log.c | 3 --- lib/zclient.c | 7 ------- lib/zclient.h | 4 ---- sharpd/sharp_zebra.c | 14 +++----------- zebra/zapi_msg.c | 4 ---- zebra/zebra_rnh.c | 4 +--- 8 files changed, 8 insertions(+), 51 deletions(-) diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index 90fa907308cf..061fa6f0879f 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -899,11 +899,9 @@ static void sendmsg_zebra_rnh(struct bgp_nexthop_cache *bnc, int command) flog_warn(EC_BGP_ZEBRA_SEND, "sendmsg_nexthop: zclient_send_message() failed"); - if ((command == ZEBRA_NEXTHOP_REGISTER) - || (command == ZEBRA_IMPORT_ROUTE_REGISTER)) + if (command == ZEBRA_NEXTHOP_REGISTER) SET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED); - else if ((command == ZEBRA_NEXTHOP_UNREGISTER) - || (command == ZEBRA_IMPORT_ROUTE_UNREGISTER)) + else if (command == ZEBRA_NEXTHOP_UNREGISTER) UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED); return; } @@ -928,10 +926,7 @@ static void register_zebra_rnh(struct bgp_nexthop_cache *bnc, return; } - if (is_bgp_import_route) - sendmsg_zebra_rnh(bnc, ZEBRA_IMPORT_ROUTE_REGISTER); - else - sendmsg_zebra_rnh(bnc, ZEBRA_NEXTHOP_REGISTER); + sendmsg_zebra_rnh(bnc, ZEBRA_NEXTHOP_REGISTER); } /** @@ -953,10 +948,7 @@ static void unregister_zebra_rnh(struct bgp_nexthop_cache *bnc, return; } - if (is_bgp_import_route) - sendmsg_zebra_rnh(bnc, ZEBRA_IMPORT_ROUTE_UNREGISTER); - else - sendmsg_zebra_rnh(bnc, ZEBRA_NEXTHOP_UNREGISTER); + sendmsg_zebra_rnh(bnc, ZEBRA_NEXTHOP_UNREGISTER); } /** diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 2a67bb2f8c19..9358be8becd9 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -112,12 +112,6 @@ static int bgp_read_nexthop_update(ZAPI_CALLBACK_ARGS) return 0; } -static int bgp_read_import_check_update(ZAPI_CALLBACK_ARGS) -{ - bgp_parse_nexthop_update(cmd, vrf_id); - return 0; -} - /* Set or clear interface on which unnumbered neighbor is configured. This * would in turn cause BGP to initiate or turn off IPv6 RAs on this * interface. @@ -3185,7 +3179,6 @@ void bgp_zebra_init(struct thread_master *master, unsigned short instance) zclient->redistribute_route_add = zebra_read_route; zclient->redistribute_route_del = zebra_read_route; zclient->nexthop_update = bgp_read_nexthop_update; - zclient->import_check_update = bgp_read_import_check_update; zclient->fec_update = bgp_read_fec_update; zclient->local_es_add = bgp_zebra_process_local_es_add; zclient->local_es_del = bgp_zebra_process_local_es_del; diff --git a/lib/log.c b/lib/log.c index 936422104f95..8be171613e8e 100644 --- a/lib/log.c +++ b/lib/log.c @@ -355,9 +355,6 @@ static const struct zebra_desc_table command_types[] = { DESC_ENTRY(ZEBRA_INTERFACE_NBR_ADDRESS_ADD), DESC_ENTRY(ZEBRA_INTERFACE_NBR_ADDRESS_DELETE), DESC_ENTRY(ZEBRA_INTERFACE_BFD_DEST_UPDATE), - DESC_ENTRY(ZEBRA_IMPORT_ROUTE_REGISTER), - DESC_ENTRY(ZEBRA_IMPORT_ROUTE_UNREGISTER), - DESC_ENTRY(ZEBRA_IMPORT_CHECK_UPDATE), DESC_ENTRY(ZEBRA_BFD_DEST_REGISTER), DESC_ENTRY(ZEBRA_BFD_DEST_DEREGISTER), DESC_ENTRY(ZEBRA_BFD_DEST_UPDATE), diff --git a/lib/zclient.c b/lib/zclient.c index bdc7cd5c75f9..96c3d67ba897 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -4017,13 +4017,6 @@ static int zclient_read(struct thread *thread) (*zclient->nexthop_update)(command, zclient, length, vrf_id); break; - case ZEBRA_IMPORT_CHECK_UPDATE: - if (zclient_debug) - zlog_debug("zclient rcvd import check update"); - if (zclient->import_check_update) - (*zclient->import_check_update)(command, zclient, - length, vrf_id); - break; case ZEBRA_BFD_DEST_REPLAY: if (zclient->bfd_dest_replay) (*zclient->bfd_dest_replay)(command, zclient, length, diff --git a/lib/zclient.h b/lib/zclient.h index d21ea621e223..a6d104301ee2 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -126,9 +126,6 @@ typedef enum { ZEBRA_INTERFACE_NBR_ADDRESS_ADD, ZEBRA_INTERFACE_NBR_ADDRESS_DELETE, ZEBRA_INTERFACE_BFD_DEST_UPDATE, - ZEBRA_IMPORT_ROUTE_REGISTER, - ZEBRA_IMPORT_ROUTE_UNREGISTER, - ZEBRA_IMPORT_CHECK_UPDATE, ZEBRA_BFD_DEST_REGISTER, ZEBRA_BFD_DEST_DEREGISTER, ZEBRA_BFD_DEST_UPDATE, @@ -362,7 +359,6 @@ struct zclient { int (*interface_nbr_address_delete)(ZAPI_CALLBACK_ARGS); int (*interface_vrf_update)(ZAPI_CALLBACK_ARGS); int (*nexthop_update)(ZAPI_CALLBACK_ARGS); - int (*import_check_update)(ZAPI_CALLBACK_ARGS); int (*bfd_dest_replay)(ZAPI_CALLBACK_ARGS); int (*redistribute_route_add)(ZAPI_CALLBACK_ARGS); int (*redistribute_route_del)(ZAPI_CALLBACK_ARGS); diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c index 48c9e8ced58d..67cff378ee1e 100644 --- a/sharpd/sharp_zebra.c +++ b/sharpd/sharp_zebra.c @@ -626,17 +626,10 @@ void sharp_zebra_nexthop_watch(struct prefix *p, vrf_id_t vrf_id, bool import, { int command; - if (!import) { - command = ZEBRA_NEXTHOP_REGISTER; + command = ZEBRA_NEXTHOP_REGISTER; - if (!watch) - command = ZEBRA_NEXTHOP_UNREGISTER; - } else { - command = ZEBRA_IMPORT_ROUTE_REGISTER; - - if (!watch) - command = ZEBRA_IMPORT_ROUTE_UNREGISTER; - } + if (!watch) + command = ZEBRA_NEXTHOP_UNREGISTER; if (zclient_send_rnh(zclient, command, p, connected, false, vrf_id) == ZCLIENT_SEND_FAILURE) @@ -984,7 +977,6 @@ void sharp_zebra_init(void) zclient->interface_address_delete = interface_address_delete; zclient->route_notify_owner = route_notify_owner; zclient->nexthop_update = sharp_nexthop_update; - zclient->import_check_update = sharp_nexthop_update; zclient->nhg_notify_owner = nhg_notify_owner; zclient->zebra_buffer_write_ready = sharp_zclient_buffer_ready; zclient->redistribute_route_add = sharp_redistribute_route; diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 775e2a4b08a9..0ed905ad7191 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -1167,8 +1167,6 @@ int zsend_zebra_srv6_locator_delete(struct zserv *client, const int cmd2type[] = { [ZEBRA_NEXTHOP_REGISTER] = RNH_NEXTHOP_TYPE, [ZEBRA_NEXTHOP_UNREGISTER] = RNH_NEXTHOP_TYPE, - [ZEBRA_IMPORT_ROUTE_REGISTER] = RNH_IMPORT_CHECK_TYPE, - [ZEBRA_IMPORT_ROUTE_UNREGISTER] = RNH_IMPORT_CHECK_TYPE, }; /* Nexthop register */ @@ -3690,8 +3688,6 @@ void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = { [ZEBRA_HELLO] = zread_hello, [ZEBRA_NEXTHOP_REGISTER] = zread_rnh_register, [ZEBRA_NEXTHOP_UNREGISTER] = zread_rnh_unregister, - [ZEBRA_IMPORT_ROUTE_REGISTER] = zread_rnh_register, - [ZEBRA_IMPORT_ROUTE_UNREGISTER] = zread_rnh_unregister, [ZEBRA_BFD_DEST_UPDATE] = zebra_ptm_bfd_dst_register, [ZEBRA_BFD_DEST_REGISTER] = zebra_ptm_bfd_dst_register, [ZEBRA_BFD_DEST_DEREGISTER] = zebra_ptm_bfd_dst_deregister, diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index 636fa927117d..ae03a7058378 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -1286,8 +1286,6 @@ int zebra_send_rnh_update(struct rnh *rnh, struct zserv *client, struct route_node *rn; int ret; uint32_t message = 0; - int cmd = (type == RNH_IMPORT_CHECK_TYPE) ? ZEBRA_IMPORT_CHECK_UPDATE - : ZEBRA_NEXTHOP_UPDATE; rn = rnh->node; re = rnh->state; @@ -1295,7 +1293,7 @@ int zebra_send_rnh_update(struct rnh *rnh, struct zserv *client, /* Get output stream. */ s = stream_new(ZEBRA_MAX_PACKET_SIZ); - zclient_create_header(s, cmd, vrf_id); + zclient_create_header(s, ZEBRA_NEXTHOP_UPDATE, vrf_id); /* Message flags. */ if (srte_color) From 7272e2a461ad4d9015634f3e2a73502518e53873 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 24 Sep 2021 10:45:07 -0400 Subject: [PATCH 016/188] zebra: remove import check resolution from zebra The entirety of the import checking no longer needs to be in zebra as that no-one is calling it. Remove the code. Signed-off-by: Donald Sharp --- zebra/rib.h | 2 +- zebra/zapi_msg.c | 8 --- zebra/zebra_rnh.c | 131 ++-------------------------------------------- zebra/zebra_rnh.h | 2 - zebra/zebra_vty.c | 2 - 5 files changed, 4 insertions(+), 141 deletions(-) diff --git a/zebra/rib.h b/zebra/rib.h index 0f9d32471fae..648399176109 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -46,7 +46,7 @@ DECLARE_MGROUP(ZEBRA); DECLARE_MTYPE(RE); -enum rnh_type { RNH_NEXTHOP_TYPE, RNH_IMPORT_CHECK_TYPE }; +enum rnh_type { RNH_NEXTHOP_TYPE }; PREDECL_LIST(rnh_list); diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 0ed905ad7191..640b119d035d 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -1240,14 +1240,6 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS) else if (!flags && CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) UNSET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED); - } else if (type == RNH_IMPORT_CHECK_TYPE) { - if (flags - && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH)) - SET_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH); - else if (!flags - && CHECK_FLAG(rnh->flags, - ZEBRA_NHT_EXACT_MATCH)) - UNSET_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH); } if (resolve_via_default) diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index ae03a7058378..422f2c92c1f7 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -82,9 +82,6 @@ static inline struct route_table *get_rnh_table(vrf_id_t vrfid, afi_t afi, case RNH_NEXTHOP_TYPE: t = zvrf->rnh_table[afi]; break; - case RNH_IMPORT_CHECK_TYPE: - t = zvrf->import_check_table[afi]; - break; } return t; @@ -418,111 +415,6 @@ static int zebra_rnh_apply_nht_rmap(afi_t afi, struct zebra_vrf *zvrf, return (at_least_one); } -/* - * Determine appropriate route (RE entry) resolving a tracked BGP route - * for BGP route for import. - */ -static struct route_entry * -zebra_rnh_resolve_import_entry(struct zebra_vrf *zvrf, afi_t afi, - struct route_node *nrn, struct rnh *rnh, - struct route_node **prn) -{ - struct route_table *route_table; - struct route_node *rn; - struct route_entry *re; - - *prn = NULL; - - route_table = zvrf->table[afi][SAFI_UNICAST]; - if (!route_table) // unexpected - return NULL; - - rn = route_node_match(route_table, &nrn->p); - if (!rn) - return NULL; - - /* Unlock route node - we don't need to lock when walking the tree. */ - route_unlock_node(rn); - - if (CHECK_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH) - && !prefix_same(&nrn->p, &rn->p)) - return NULL; - - if (IS_ZEBRA_DEBUG_NHT_DETAILED) { - zlog_debug("%s: %s(%u):%pRN Resolved Import Entry to %pRN", - __func__, VRF_LOGNAME(zvrf->vrf), rnh->vrf_id, - rnh->node, rn); - } - - /* Identify appropriate route entry. */ - RNODE_FOREACH_RE (rn, re) { - if (!CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED) - && CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED) - && !CHECK_FLAG(re->status, ROUTE_ENTRY_QUEUED) - && (re->type != ZEBRA_ROUTE_BGP)) - break; - } - - if (re) - *prn = rn; - - if (!re && IS_ZEBRA_DEBUG_NHT_DETAILED) - zlog_debug(" Rejected due to removed or is a bgp route"); - - return re; -} - -/* - * See if a tracked route entry for import (by BGP) has undergone any - * change, and if so, notify the client. - */ -static void zebra_rnh_eval_import_check_entry(struct zebra_vrf *zvrf, afi_t afi, - int force, struct route_node *nrn, - struct rnh *rnh, - struct route_node *prn, - struct route_entry *re) -{ - int state_changed = 0; - struct zserv *client; - struct listnode *node; - - zebra_rnh_remove_from_routing_table(rnh); - if (prn) { - prefix_copy(&rnh->resolved_route, &prn->p); - } else { - int family = rnh->resolved_route.family; - - memset(&rnh->resolved_route.family, 0, sizeof(struct prefix)); - rnh->resolved_route.family = family; - } - zebra_rnh_store_in_routing_table(rnh); - - if (re && (rnh->state == NULL)) { - if (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED)) - state_changed = 1; - } else if (!re && (rnh->state != NULL)) - state_changed = 1; - - if (compare_state(re, rnh->state)) { - copy_state(rnh, re, nrn); - state_changed = 1; - } - - if (state_changed || force) { - if (IS_ZEBRA_DEBUG_NHT) - zlog_debug("%s(%u):%pRN: Route import check %s %s", - VRF_LOGNAME(zvrf->vrf), zvrf->vrf->vrf_id, - nrn, rnh->state ? "passed" : "failed", - state_changed ? "(state changed)" : ""); - /* state changed, notify clients */ - for (ALL_LIST_ELEMENTS_RO(rnh->client_list, node, client)) { - zebra_send_rnh_update(rnh, client, - RNH_IMPORT_CHECK_TYPE, - zvrf->vrf->vrf_id, 0); - } - } -} - /* * Notify clients registered for this nexthop about a change. */ @@ -843,10 +735,7 @@ static void zebra_rnh_evaluate_entry(struct zebra_vrf *zvrf, afi_t afi, rnh = nrn->info; /* Identify route entry (RE) resolving this tracked entry. */ - if (type == RNH_IMPORT_CHECK_TYPE) - re = zebra_rnh_resolve_import_entry(zvrf, afi, nrn, rnh, &prn); - else - re = zebra_rnh_resolve_nexthop_entry(zvrf, afi, nrn, rnh, &prn); + re = zebra_rnh_resolve_nexthop_entry(zvrf, afi, nrn, rnh, &prn); /* If the entry cannot be resolved and that is also the existing state, * there is nothing further to do. @@ -855,12 +744,7 @@ static void zebra_rnh_evaluate_entry(struct zebra_vrf *zvrf, afi_t afi, return; /* Process based on type of entry. */ - if (type == RNH_IMPORT_CHECK_TYPE) - zebra_rnh_eval_import_check_entry(zvrf, afi, force, nrn, rnh, - prn, re); - else - zebra_rnh_eval_nexthop_entry(zvrf, afi, force, nrn, rnh, prn, - re); + zebra_rnh_eval_nexthop_entry(zvrf, afi, force, nrn, rnh, prn, re); } /* @@ -882,12 +766,7 @@ static void zebra_rnh_clear_nhc_flag(struct zebra_vrf *zvrf, afi_t afi, rnh = nrn->info; /* Identify route entry (RIB) resolving this tracked entry. */ - if (type == RNH_IMPORT_CHECK_TYPE) - re = zebra_rnh_resolve_import_entry(zvrf, afi, nrn, rnh, - &prn); - else - re = zebra_rnh_resolve_nexthop_entry(zvrf, afi, nrn, rnh, - &prn); + re = zebra_rnh_resolve_nexthop_entry(zvrf, afi, nrn, rnh, &prn); if (re) UNSET_FLAG(re->status, ROUTE_ENTRY_LABELS_CHANGED); @@ -1491,10 +1370,6 @@ static int zebra_client_cleanup_rnh(struct zserv *client) RNH_NEXTHOP_TYPE); zebra_cleanup_rnh_client(zvrf_id(zvrf), AFI_IP6, client, RNH_NEXTHOP_TYPE); - zebra_cleanup_rnh_client(zvrf_id(zvrf), AFI_IP, client, - RNH_IMPORT_CHECK_TYPE); - zebra_cleanup_rnh_client(zvrf_id(zvrf), AFI_IP6, client, - RNH_IMPORT_CHECK_TYPE); } } diff --git a/zebra/zebra_rnh.h b/zebra/zebra_rnh.h index 24ee6d0bd9a4..6a225d43a9d1 100644 --- a/zebra/zebra_rnh.h +++ b/zebra/zebra_rnh.h @@ -36,8 +36,6 @@ static inline const char *rnh_type2str(enum rnh_type type) switch (type) { case RNH_NEXTHOP_TYPE: return "Nexthop"; - case RNH_IMPORT_CHECK_TYPE: - return "Import"; } return "ERROR"; diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 9d1df98d3772..848926400e55 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -1334,8 +1334,6 @@ DEFPY (show_ip_nht, if (strcmp(type, "nht") == 0) rtype = RNH_NEXTHOP_TYPE; - else - rtype = RNH_IMPORT_CHECK_TYPE; if (vrf_all) { struct vrf *vrf; From 6071e5e96e9fd2a4f662ea94363ecabb7e5b81d2 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 24 Sep 2021 11:04:03 -0400 Subject: [PATCH 017/188] zebra: remove 'enum rnh_type' from system This code is now dead code since there are not two nexthop resolution types. Signed-off-by: Donald Sharp --- zebra/rib.h | 4 -- zebra/zapi_msg.c | 33 ++++--------- zebra/zebra_rib.c | 10 ++-- zebra/zebra_rnh.c | 109 +++++++++++++++++------------------------ zebra/zebra_rnh.h | 27 +++------- zebra/zebra_routemap.c | 15 +++--- zebra/zebra_srte.c | 6 +-- zebra/zebra_vty.c | 16 +++--- 8 files changed, 81 insertions(+), 139 deletions(-) diff --git a/zebra/rib.h b/zebra/rib.h index 648399176109..92e1b3635d69 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -46,8 +46,6 @@ DECLARE_MGROUP(ZEBRA); DECLARE_MTYPE(RE); -enum rnh_type { RNH_NEXTHOP_TYPE }; - PREDECL_LIST(rnh_list); /* Nexthop structure. */ @@ -64,8 +62,6 @@ struct rnh { afi_t afi; - enum rnh_type type; - uint32_t seqno; struct route_entry *state; diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 640b119d035d..adf9dfa00022 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -1164,11 +1164,6 @@ int zsend_zebra_srv6_locator_delete(struct zserv *client, /* Inbound message handling ------------------------------------------------ */ -const int cmd2type[] = { - [ZEBRA_NEXTHOP_REGISTER] = RNH_NEXTHOP_TYPE, - [ZEBRA_NEXTHOP_UNREGISTER] = RNH_NEXTHOP_TYPE, -}; - /* Nexthop register */ static void zread_rnh_register(ZAPI_HANDLER_ARGS) { @@ -1178,16 +1173,14 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS) unsigned short l = 0; uint8_t flags = 0; uint8_t resolve_via_default; - uint16_t type = cmd2type[hdr->command]; bool exist; bool flag_changed = false; uint8_t orig_flags; if (IS_ZEBRA_DEBUG_NHT) zlog_debug( - "rnh_register msg from client %s: hdr->length=%d, type=%s vrf=%u", + "rnh_register msg from client %s: hdr->length=%d vrf=%u", zebra_route_string(client->proto), hdr->length, - (type == RNH_NEXTHOP_TYPE) ? "nexthop" : "route", zvrf->vrf->vrf_id); s = msg; @@ -1228,19 +1221,15 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS) p.family); return; } - rnh = zebra_add_rnh(&p, zvrf_id(zvrf), type, &exist); + rnh = zebra_add_rnh(&p, zvrf_id(zvrf), &exist); if (!rnh) return; orig_flags = rnh->flags; - if (type == RNH_NEXTHOP_TYPE) { - if (flags - && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) - SET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED); - else if (!flags - && CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) - UNSET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED); - } + if (flags && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) + SET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED); + else if (!flags && CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) + UNSET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED); if (resolve_via_default) SET_FLAG(rnh->flags, ZEBRA_NHT_RESOLVE_VIA_DEFAULT); @@ -1250,10 +1239,9 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS) /* Anything not AF_INET/INET6 has been filtered out above */ if (!exist || flag_changed) - zebra_evaluate_rnh(zvrf, family2afi(p.family), 1, type, - &p); + zebra_evaluate_rnh(zvrf, family2afi(p.family), 1, &p); - zebra_add_rnh_client(rnh, client, type, zvrf_id(zvrf)); + zebra_add_rnh_client(rnh, client, zvrf_id(zvrf)); } stream_failure: @@ -1267,7 +1255,6 @@ static void zread_rnh_unregister(ZAPI_HANDLER_ARGS) struct stream *s; struct prefix p; unsigned short l = 0; - uint16_t type = cmd2type[hdr->command]; if (IS_ZEBRA_DEBUG_NHT) zlog_debug( @@ -1317,10 +1304,10 @@ static void zread_rnh_unregister(ZAPI_HANDLER_ARGS) p.family); return; } - rnh = zebra_lookup_rnh(&p, zvrf_id(zvrf), type); + rnh = zebra_lookup_rnh(&p, zvrf_id(zvrf)); if (rnh) { client->nh_dereg_time = monotime(NULL); - zebra_remove_rnh_client(rnh, client, type); + zebra_remove_rnh_client(rnh, client); } } stream_failure: diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 24c51e485ff5..5230f0a4d157 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -730,10 +730,9 @@ void zebra_rib_evaluate_rn_nexthops(struct route_node *rn, uint32_t seq) if (IS_ZEBRA_DEBUG_NHT_DETAILED) zlog_debug( - "%s(%u):%pRN has Nexthop(%pFX) Type: %s depending on it, evaluating %u:%u", - zvrf_name(zvrf), zvrf_id(zvrf), - rn, p, rnh_type2str(rnh->type), seq, - rnh->seqno); + "%s(%u):%pRN has Nexthop(%pFX) depending on it, evaluating %u:%u", + zvrf_name(zvrf), zvrf_id(zvrf), rn, p, + seq, rnh->seqno); /* * If we have evaluated this node on this pass @@ -755,8 +754,7 @@ void zebra_rib_evaluate_rn_nexthops(struct route_node *rn, uint32_t seq) } rnh->seqno = seq; - zebra_evaluate_rnh(zvrf, family2afi(p->family), 0, - rnh->type, p); + zebra_evaluate_rnh(zvrf, family2afi(p->family), 0, p); } rn = rn->parent; diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index 422f2c92c1f7..c58debb6affb 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -70,19 +70,14 @@ void zebra_rnh_init(void) hook_register(zserv_client_close, zebra_client_cleanup_rnh); } -static inline struct route_table *get_rnh_table(vrf_id_t vrfid, afi_t afi, - enum rnh_type type) +static inline struct route_table *get_rnh_table(vrf_id_t vrfid, afi_t afi) { struct zebra_vrf *zvrf; struct route_table *t = NULL; zvrf = zebra_vrf_lookup_by_id(vrfid); if (zvrf) - switch (type) { - case RNH_NEXTHOP_TYPE: - t = zvrf->rnh_table[afi]; - break; - } + t = zvrf->rnh_table[afi]; return t; } @@ -132,8 +127,7 @@ static void zebra_rnh_store_in_routing_table(struct rnh *rnh) route_unlock_node(rn); } -struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, enum rnh_type type, - bool *exists) +struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, bool *exists) { struct route_table *table; struct route_node *rn; @@ -143,16 +137,15 @@ struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, enum rnh_type type, if (IS_ZEBRA_DEBUG_NHT) { struct vrf *vrf = vrf_lookup_by_id(vrfid); - zlog_debug("%s(%u): Add RNH %pFX type %s", VRF_LOGNAME(vrf), - vrfid, p, rnh_type2str(type)); + zlog_debug("%s(%u): Add RNH %pFX", VRF_LOGNAME(vrf), vrfid, p); } - table = get_rnh_table(vrfid, afi, type); + table = get_rnh_table(vrfid, afi); if (!table) { struct vrf *vrf = vrf_lookup_by_id(vrfid); flog_warn(EC_ZEBRA_RNH_NO_TABLE, - "%s(%u): Add RNH %pFX type %s - table not found", - VRF_LOGNAME(vrf), vrfid, p, rnh_type2str(type)); + "%s(%u): Add RNH %pFX - table not found", + VRF_LOGNAME(vrf), vrfid, p); *exists = false; return NULL; } @@ -175,7 +168,6 @@ struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, enum rnh_type type, rnh->resolved_route.family = p->family; rnh->client_list = list_new(); rnh->vrf_id = vrfid; - rnh->type = type; rnh->seqno = 0; rnh->afi = afi; rnh->zebra_pseudowire_list = list_new(); @@ -192,13 +184,12 @@ struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, enum rnh_type type, return (rn->info); } -struct rnh *zebra_lookup_rnh(struct prefix *p, vrf_id_t vrfid, - enum rnh_type type) +struct rnh *zebra_lookup_rnh(struct prefix *p, vrf_id_t vrfid) { struct route_table *table; struct route_node *rn; - table = get_rnh_table(vrfid, family2afi(PREFIX_FAMILY(p)), type); + table = get_rnh_table(vrfid, family2afi(PREFIX_FAMILY(p))); if (!table) return NULL; @@ -244,7 +235,7 @@ void zebra_free_rnh(struct rnh *rnh) XFREE(MTYPE_RNH, rnh); } -static void zebra_delete_rnh(struct rnh *rnh, enum rnh_type type) +static void zebra_delete_rnh(struct rnh *rnh) { struct route_node *rn; @@ -258,8 +249,8 @@ static void zebra_delete_rnh(struct rnh *rnh, enum rnh_type type) if (IS_ZEBRA_DEBUG_NHT) { struct vrf *vrf = vrf_lookup_by_id(rnh->vrf_id); - zlog_debug("%s(%u): Del RNH %pRN type %s", VRF_LOGNAME(vrf), - rnh->vrf_id, rnh->node, rnh_type2str(type)); + zlog_debug("%s(%u): Del RNH %pRN", VRF_LOGNAME(vrf), + rnh->vrf_id, rnh->node); } zebra_free_rnh(rnh); @@ -276,15 +267,14 @@ static void zebra_delete_rnh(struct rnh *rnh, enum rnh_type type) * and as such it will have a resolved rnh. */ void zebra_add_rnh_client(struct rnh *rnh, struct zserv *client, - enum rnh_type type, vrf_id_t vrf_id) + vrf_id_t vrf_id) { if (IS_ZEBRA_DEBUG_NHT) { struct vrf *vrf = vrf_lookup_by_id(vrf_id); - zlog_debug("%s(%u): Client %s registers for RNH %pRN type %s", + zlog_debug("%s(%u): Client %s registers for RNH %pRN", VRF_LOGNAME(vrf), vrf_id, - zebra_route_string(client->proto), rnh->node, - rnh_type2str(type)); + zebra_route_string(client->proto), rnh->node); } if (!listnode_lookup(rnh->client_list, client)) listnode_add(rnh->client_list, client); @@ -293,21 +283,20 @@ void zebra_add_rnh_client(struct rnh *rnh, struct zserv *client, * We always need to respond with known information, * currently multiple daemons expect this behavior */ - zebra_send_rnh_update(rnh, client, type, vrf_id, 0); + zebra_send_rnh_update(rnh, client, vrf_id, 0); } -void zebra_remove_rnh_client(struct rnh *rnh, struct zserv *client, - enum rnh_type type) +void zebra_remove_rnh_client(struct rnh *rnh, struct zserv *client) { if (IS_ZEBRA_DEBUG_NHT) { struct vrf *vrf = vrf_lookup_by_id(rnh->vrf_id); - zlog_debug("Client %s unregisters for RNH %s(%u)%pRN type %s", + zlog_debug("Client %s unregisters for RNH %s(%u)%pRN", zebra_route_string(client->proto), VRF_LOGNAME(vrf), - vrf->vrf_id, rnh->node, rnh_type2str(type)); + vrf->vrf_id, rnh->node); } listnode_delete(rnh->client_list, client); - zebra_delete_rnh(rnh, type); + zebra_delete_rnh(rnh); } /* XXX move this utility function elsewhere? */ @@ -347,15 +336,14 @@ void zebra_register_rnh_pseudowire(vrf_id_t vrf_id, struct zebra_pw *pw, return; addr2hostprefix(pw->af, &pw->nexthop, &nh); - rnh = zebra_add_rnh(&nh, vrf_id, RNH_NEXTHOP_TYPE, &exists); + rnh = zebra_add_rnh(&nh, vrf_id, &exists); if (!rnh) return; if (!listnode_lookup(rnh->zebra_pseudowire_list, pw)) { listnode_add(rnh->zebra_pseudowire_list, pw); pw->rnh = rnh; - zebra_evaluate_rnh(zvrf, family2afi(pw->af), 1, - RNH_NEXTHOP_TYPE, &nh); + zebra_evaluate_rnh(zvrf, family2afi(pw->af), 1, &nh); } else *nht_exists = true; } @@ -371,7 +359,7 @@ void zebra_deregister_rnh_pseudowire(vrf_id_t vrf_id, struct zebra_pw *pw) listnode_delete(rnh->zebra_pseudowire_list, pw); pw->rnh = NULL; - zebra_delete_rnh(rnh, RNH_NEXTHOP_TYPE); + zebra_delete_rnh(rnh); } /* Clear the NEXTHOP_FLAG_RNH_FILTERED flags on all nexthops @@ -472,8 +460,7 @@ static void zebra_rnh_notify_protocol_clients(struct zebra_vrf *zvrf, afi_t afi, zebra_route_string(client->proto)); } - zebra_send_rnh_update(rnh, client, RNH_NEXTHOP_TYPE, - zvrf->vrf->vrf_id, 0); + zebra_send_rnh_update(rnh, client, zvrf->vrf->vrf_id, 0); } if (re) @@ -719,17 +706,16 @@ static void zebra_rnh_eval_nexthop_entry(struct zebra_vrf *zvrf, afi_t afi, /* Evaluate one tracked entry */ static void zebra_rnh_evaluate_entry(struct zebra_vrf *zvrf, afi_t afi, - int force, enum rnh_type type, - struct route_node *nrn) + int force, struct route_node *nrn) { struct rnh *rnh; struct route_entry *re; struct route_node *prn; if (IS_ZEBRA_DEBUG_NHT) { - zlog_debug("%s(%u):%pRN: Evaluate RNH, type %s %s", + zlog_debug("%s(%u):%pRN: Evaluate RNH, %s", VRF_LOGNAME(zvrf->vrf), zvrf->vrf->vrf_id, nrn, - rnh_type2str(type), force ? "(force)" : ""); + force ? "(force)" : ""); } rnh = nrn->info; @@ -757,7 +743,7 @@ static void zebra_rnh_evaluate_entry(struct zebra_vrf *zvrf, afi_t afi, * covers multiple nexthops we are interested in. */ static void zebra_rnh_clear_nhc_flag(struct zebra_vrf *zvrf, afi_t afi, - enum rnh_type type, struct route_node *nrn) + struct route_node *nrn) { struct rnh *rnh; struct route_entry *re; @@ -776,12 +762,12 @@ static void zebra_rnh_clear_nhc_flag(struct zebra_vrf *zvrf, afi_t afi, * of a particular VRF and address-family or a specific prefix. */ void zebra_evaluate_rnh(struct zebra_vrf *zvrf, afi_t afi, int force, - enum rnh_type type, struct prefix *p) + struct prefix *p) { struct route_table *rnh_table; struct route_node *nrn; - rnh_table = get_rnh_table(zvrf->vrf->vrf_id, afi, type); + rnh_table = get_rnh_table(zvrf->vrf->vrf_id, afi); if (!rnh_table) // unexpected return; @@ -789,7 +775,7 @@ void zebra_evaluate_rnh(struct zebra_vrf *zvrf, afi_t afi, int force, /* Evaluating a specific entry, make sure it exists. */ nrn = route_node_lookup(rnh_table, p); if (nrn && nrn->info) - zebra_rnh_evaluate_entry(zvrf, afi, force, type, nrn); + zebra_rnh_evaluate_entry(zvrf, afi, force, nrn); if (nrn) route_unlock_node(nrn); @@ -798,26 +784,25 @@ void zebra_evaluate_rnh(struct zebra_vrf *zvrf, afi_t afi, int force, nrn = route_top(rnh_table); while (nrn) { if (nrn->info) - zebra_rnh_evaluate_entry(zvrf, afi, force, type, - nrn); + zebra_rnh_evaluate_entry(zvrf, afi, force, nrn); nrn = route_next(nrn); /* this will also unlock nrn */ } nrn = route_top(rnh_table); while (nrn) { if (nrn->info) - zebra_rnh_clear_nhc_flag(zvrf, afi, type, nrn); + zebra_rnh_clear_nhc_flag(zvrf, afi, nrn); nrn = route_next(nrn); /* this will also unlock nrn */ } } } void zebra_print_rnh_table(vrf_id_t vrfid, afi_t afi, struct vty *vty, - enum rnh_type type, struct prefix *p) + struct prefix *p) { struct route_table *table; struct route_node *rn; - table = get_rnh_table(vrfid, afi, type); + table = get_rnh_table(vrfid, afi); if (!table) { if (IS_ZEBRA_DEBUG_NHT) zlog_debug("print_rnhs: rnh table not found"); @@ -1154,8 +1139,7 @@ static bool compare_state(struct route_entry *r1, } int zebra_send_rnh_update(struct rnh *rnh, struct zserv *client, - enum rnh_type type, vrf_id_t vrf_id, - uint32_t srte_color) + vrf_id_t vrf_id, uint32_t srte_color) { struct stream *s = NULL; struct route_entry *re; @@ -1325,7 +1309,7 @@ static void print_rnh(struct route_node *rn, struct vty *vty) } static int zebra_cleanup_rnh_client(vrf_id_t vrf_id, afi_t afi, - struct zserv *client, enum rnh_type type) + struct zserv *client) { struct route_table *ntable; struct route_node *nrn; @@ -1334,14 +1318,12 @@ static int zebra_cleanup_rnh_client(vrf_id_t vrf_id, afi_t afi, if (IS_ZEBRA_DEBUG_NHT) { struct vrf *vrf = vrf_lookup_by_id(vrf_id); - zlog_debug( - "%s(%u): Client %s RNH cleanup for family %s type %s", - VRF_LOGNAME(vrf), vrf_id, - zebra_route_string(client->proto), afi2str(afi), - rnh_type2str(type)); + zlog_debug("%s(%u): Client %s RNH cleanup for family %s", + VRF_LOGNAME(vrf), vrf_id, + zebra_route_string(client->proto), afi2str(afi)); } - ntable = get_rnh_table(vrf_id, afi, type); + ntable = get_rnh_table(vrf_id, afi); if (!ntable) { zlog_debug("cleanup_rnh_client: rnh table not found"); return -1; @@ -1352,7 +1334,7 @@ static int zebra_cleanup_rnh_client(vrf_id_t vrf_id, afi_t afi, continue; rnh = nrn->info; - zebra_remove_rnh_client(rnh, client, type); + zebra_remove_rnh_client(rnh, client); } return 1; } @@ -1366,10 +1348,9 @@ static int zebra_client_cleanup_rnh(struct zserv *client) RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) { zvrf = vrf->info; if (zvrf) { - zebra_cleanup_rnh_client(zvrf_id(zvrf), AFI_IP, client, - RNH_NEXTHOP_TYPE); - zebra_cleanup_rnh_client(zvrf_id(zvrf), AFI_IP6, client, - RNH_NEXTHOP_TYPE); + zebra_cleanup_rnh_client(zvrf_id(zvrf), AFI_IP, client); + zebra_cleanup_rnh_client(zvrf_id(zvrf), AFI_IP6, + client); } } diff --git a/zebra/zebra_rnh.h b/zebra/zebra_rnh.h index 6a225d43a9d1..01ad7215b802 100644 --- a/zebra/zebra_rnh.h +++ b/zebra/zebra_rnh.h @@ -31,34 +31,21 @@ extern "C" { extern void zebra_rnh_init(void); -static inline const char *rnh_type2str(enum rnh_type type) -{ - switch (type) { - case RNH_NEXTHOP_TYPE: - return "Nexthop"; - } - - return "ERROR"; -} - extern struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, - enum rnh_type type, bool *exists); -extern struct rnh *zebra_lookup_rnh(struct prefix *p, vrf_id_t vrfid, - enum rnh_type type); + bool *exists); +extern struct rnh *zebra_lookup_rnh(struct prefix *p, vrf_id_t vrfid); extern void zebra_free_rnh(struct rnh *rnh); extern void zebra_add_rnh_client(struct rnh *rnh, struct zserv *client, - enum rnh_type type, vrf_id_t vrfid); + vrf_id_t vrfid); extern int zebra_send_rnh_update(struct rnh *rnh, struct zserv *client, - enum rnh_type type, vrf_id_t vrf_id, - uint32_t srte_color); + vrf_id_t vrf_id, uint32_t srte_color); extern void zebra_register_rnh_pseudowire(vrf_id_t, struct zebra_pw *, bool *); extern void zebra_deregister_rnh_pseudowire(vrf_id_t, struct zebra_pw *); -extern void zebra_remove_rnh_client(struct rnh *rnh, struct zserv *client, - enum rnh_type type); +extern void zebra_remove_rnh_client(struct rnh *rnh, struct zserv *client); extern void zebra_evaluate_rnh(struct zebra_vrf *zvrf, afi_t afi, int force, - enum rnh_type type, struct prefix *p); + struct prefix *p); extern void zebra_print_rnh_table(vrf_id_t vrfid, afi_t afi, struct vty *vty, - enum rnh_type type, struct prefix *p); + struct prefix *p); extern int rnh_resolve_via_default(struct zebra_vrf *zvrf, int family); diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c index d07a49fb6e37..0887ce1f0a72 100644 --- a/zebra/zebra_routemap.c +++ b/zebra/zebra_routemap.c @@ -319,7 +319,7 @@ static int ip_nht_rm_add(struct zebra_vrf *zvrf, const char *rmap, int rtype, route_map_counter_increment(NHT_RM_MAP(zvrf, afi, rtype)); if (NHT_RM_MAP(zvrf, afi, rtype)) - zebra_evaluate_rnh(zvrf, AFI_IP, 1, RNH_NEXTHOP_TYPE, NULL); + zebra_evaluate_rnh(zvrf, AFI_IP, 1, NULL); return CMD_SUCCESS; } @@ -340,8 +340,7 @@ static int ip_nht_rm_del(struct zebra_vrf *zvrf, const char *rmap, int rtype, zvrf->vrf->vrf_id, rtype); NHT_RM_MAP(zvrf, afi, rtype) = NULL; - zebra_evaluate_rnh(zvrf, AFI_IP, 1, RNH_NEXTHOP_TYPE, - NULL); + zebra_evaluate_rnh(zvrf, AFI_IP, 1, NULL); } XFREE(MTYPE_ROUTE_MAP_NAME, NHT_RM_NAME(zvrf, afi, rtype)); } @@ -1588,9 +1587,8 @@ static void zebra_nht_rm_update(const char *rmap) afi_ip = 1; - zebra_evaluate_rnh( - zvrf, AFI_IP, 1, - RNH_NEXTHOP_TYPE, NULL); + zebra_evaluate_rnh(zvrf, AFI_IP, + 1, NULL); } } } @@ -1619,9 +1617,8 @@ static void zebra_nht_rm_update(const char *rmap) afi_ipv6 = 1; - zebra_evaluate_rnh( - zvrf, AFI_IP, 1, - RNH_NEXTHOP_TYPE, NULL); + zebra_evaluate_rnh(zvrf, AFI_IP, + 1, NULL); } } } diff --git a/zebra/zebra_srte.c b/zebra/zebra_srte.c index ba3727371cb6..0fa054105e02 100644 --- a/zebra/zebra_srte.c +++ b/zebra/zebra_srte.c @@ -196,7 +196,7 @@ static void zebra_sr_policy_notify_update(struct zebra_sr_policy *policy) exit(1); } - rnh = zebra_lookup_rnh(&p, zvrf_id(zvrf), RNH_NEXTHOP_TYPE); + rnh = zebra_lookup_rnh(&p, zvrf_id(zvrf)); if (!rnh) return; @@ -205,8 +205,8 @@ static void zebra_sr_policy_notify_update(struct zebra_sr_policy *policy) zebra_sr_policy_notify_update_client(policy, client); else /* Fallback to the IGP shortest path. */ - zebra_send_rnh_update(rnh, client, RNH_NEXTHOP_TYPE, - zvrf_id(zvrf), policy->color); + zebra_send_rnh_update(rnh, client, zvrf_id(zvrf), + policy->color); } } diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 848926400e55..779996a80661 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -1330,10 +1330,6 @@ DEFPY (show_ip_nht, afi_t afi = ipv4 ? AFI_IP : AFI_IP6; vrf_id_t vrf_id = VRF_DEFAULT; struct prefix prefix, *p = NULL; - enum rnh_type rtype; - - if (strcmp(type, "nht") == 0) - rtype = RNH_NEXTHOP_TYPE; if (vrf_all) { struct vrf *vrf; @@ -1343,7 +1339,7 @@ DEFPY (show_ip_nht, if ((zvrf = vrf->info) != NULL) { vty_out(vty, "\nVRF %s:\n", zvrf_name(zvrf)); zebra_print_rnh_table(zvrf_id(zvrf), afi, vty, - rtype, NULL); + NULL); } return CMD_SUCCESS; } @@ -1357,7 +1353,7 @@ DEFPY (show_ip_nht, return CMD_WARNING; } - zebra_print_rnh_table(vrf_id, afi, vty, rtype, p); + zebra_print_rnh_table(vrf_id, afi, vty, p); return CMD_SUCCESS; } @@ -1378,7 +1374,7 @@ DEFUN (ip_nht_default_route, zvrf->zebra_rnh_ip_default_route = true; - zebra_evaluate_rnh(zvrf, AFI_IP, 0, RNH_NEXTHOP_TYPE, NULL); + zebra_evaluate_rnh(zvrf, AFI_IP, 0, NULL); return CMD_SUCCESS; } @@ -1716,7 +1712,7 @@ DEFUN (no_ip_nht_default_route, return CMD_SUCCESS; zvrf->zebra_rnh_ip_default_route = false; - zebra_evaluate_rnh(zvrf, AFI_IP, 0, RNH_NEXTHOP_TYPE, NULL); + zebra_evaluate_rnh(zvrf, AFI_IP, 0, NULL); return CMD_SUCCESS; } @@ -1736,7 +1732,7 @@ DEFUN (ipv6_nht_default_route, return CMD_SUCCESS; zvrf->zebra_rnh_ipv6_default_route = true; - zebra_evaluate_rnh(zvrf, AFI_IP6, 0, RNH_NEXTHOP_TYPE, NULL); + zebra_evaluate_rnh(zvrf, AFI_IP6, 0, NULL); return CMD_SUCCESS; } @@ -1757,7 +1753,7 @@ DEFUN (no_ipv6_nht_default_route, return CMD_SUCCESS; zvrf->zebra_rnh_ipv6_default_route = false; - zebra_evaluate_rnh(zvrf, AFI_IP6, 0, RNH_NEXTHOP_TYPE, NULL); + zebra_evaluate_rnh(zvrf, AFI_IP6, 0, NULL); return CMD_SUCCESS; } From 93f533c3085f75ae1bf6b6b1604cfa211399c364 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 24 Sep 2021 11:05:29 -0400 Subject: [PATCH 018/188] zebra: remove zvrf->import_check_table The import_check_table is no longer used, so let's remove it. Signed-off-by: Donald Sharp --- zebra/zebra_vrf.c | 8 -------- zebra/zebra_vrf.h | 3 --- 2 files changed, 11 deletions(-) diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c index 4fbcc6f59647..69b586d71edb 100644 --- a/zebra/zebra_vrf.c +++ b/zebra/zebra_vrf.c @@ -150,10 +150,6 @@ static int zebra_vrf_enable(struct vrf *vrf) table = route_table_init(); table->cleanup = zebra_rnhtable_node_cleanup; zvrf->rnh_table[afi] = table; - - table = route_table_init(); - table->cleanup = zebra_rnhtable_node_cleanup; - zvrf->import_check_table[afi] = table; } /* Kick off any VxLAN-EVPN processing. */ @@ -196,8 +192,6 @@ static int zebra_vrf_disable(struct vrf *vrf) for (afi = AFI_IP; afi <= AFI_IP6; afi++) { route_table_finish(zvrf->rnh_table[afi]); zvrf->rnh_table[afi] = NULL; - route_table_finish(zvrf->import_check_table[afi]); - zvrf->import_check_table[afi] = NULL; for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) rib_close_table(zvrf->table[afi][safi]); @@ -298,8 +292,6 @@ static int zebra_vrf_delete(struct vrf *vrf) if (zvrf->rnh_table[afi]) route_table_finish(zvrf->rnh_table[afi]); - if (zvrf->import_check_table[afi]) - route_table_finish(zvrf->import_check_table[afi]); } otable = otable_pop(&zvrf->other_tables); diff --git a/zebra/zebra_vrf.h b/zebra/zebra_vrf.h index eae8e3792463..e6126a22ca92 100644 --- a/zebra/zebra_vrf.h +++ b/zebra/zebra_vrf.h @@ -79,9 +79,6 @@ struct zebra_vrf { /* Recursive Nexthop table */ struct route_table *rnh_table[AFI_MAX]; - /* Import check table (used mostly by BGP */ - struct route_table *import_check_table[AFI_MAX]; - struct otable_head other_tables; /* 2nd pointer type used primarily to quell a warning on From 6cd9a93dddba199e68c73baca62337b704f32e14 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 24 Sep 2021 16:13:04 -0400 Subject: [PATCH 019/188] zebra: Attempt to clarify variable names as they are used Cleanup the poorly implemented variable names so that we can understand what is going on a bit better. Signed-off-by: Donald Sharp --- lib/zclient.c | 4 ++-- lib/zclient.h | 2 +- zebra/zapi_msg.c | 19 ++++++++++--------- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/lib/zclient.c b/lib/zclient.c index 96c3d67ba897..6f863c5ea6b4 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -765,7 +765,7 @@ static int zclient_connect(struct thread *t) enum zclient_send_status zclient_send_rnh(struct zclient *zclient, int command, const struct prefix *p, - bool exact_match, + bool connected, bool resolve_via_def, vrf_id_t vrf_id) { struct stream *s; @@ -773,7 +773,7 @@ enum zclient_send_status zclient_send_rnh(struct zclient *zclient, int command, s = zclient->obuf; stream_reset(s); zclient_create_header(s, command, vrf_id); - stream_putc(s, (exact_match) ? 1 : 0); + stream_putc(s, (connected) ? 1 : 0); stream_putc(s, (resolve_via_def) ? 1 : 0); stream_putw(s, PREFIX_FAMILY(p)); stream_putc(s, p->prefixlen); diff --git a/lib/zclient.h b/lib/zclient.h index a6d104301ee2..c35753ca8004 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -1103,7 +1103,7 @@ extern enum zclient_send_status zclient_route_send(uint8_t, struct zclient *, struct zapi_route *); extern enum zclient_send_status zclient_send_rnh(struct zclient *zclient, int command, const struct prefix *p, - bool exact_match, bool resolve_via_default, vrf_id_t vrf_id); + bool connected, bool resolve_via_default, vrf_id_t vrf_id); int zapi_nexthop_encode(struct stream *s, const struct zapi_nexthop *api_nh, uint32_t api_flags, uint32_t api_message); extern int zapi_route_encode(uint8_t, struct stream *, struct zapi_route *); diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index adf9dfa00022..4c0a0c82bf81 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -1171,7 +1171,7 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS) struct stream *s; struct prefix p; unsigned short l = 0; - uint8_t flags = 0; + uint8_t connected = 0; uint8_t resolve_via_default; bool exist; bool flag_changed = false; @@ -1189,7 +1189,7 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS) client->nh_reg_time = monotime(NULL); while (l < hdr->length) { - STREAM_GETC(s, flags); + STREAM_GETC(s, connected); STREAM_GETC(s, resolve_via_default); STREAM_GETW(s, p.family); STREAM_GETC(s, p.prefixlen); @@ -1226,9 +1226,10 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS) return; orig_flags = rnh->flags; - if (flags && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) + if (connected && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) SET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED); - else if (!flags && CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) + else if (!connected + && CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) UNSET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED); if (resolve_via_default) @@ -1265,13 +1266,13 @@ static void zread_rnh_unregister(ZAPI_HANDLER_ARGS) s = msg; while (l < hdr->length) { - uint8_t flags; + uint8_t ignore; - STREAM_GETC(s, flags); - if (flags != 0) + STREAM_GETC(s, ignore); + if (ignore != 0) goto stream_failure; - STREAM_GETC(s, flags); - if (flags != 0) + STREAM_GETC(s, ignore); + if (ignore != 0) goto stream_failure; STREAM_GETW(s, p.family); From d597533a9dcabc298a53112c22e94c0264cd3f39 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 24 Sep 2021 16:36:27 -0400 Subject: [PATCH 020/188] zebra: Start carrying safi for rnh processing PIM is going to need to be able to send down the address it is trying to resolve in the multicast rib. We need a way to signal this to the end developer. Start the conversion by adding the ability to have a safi. But only allow SAFI_UNICAST at the moment. Signed-off-by: Donald Sharp --- zebra/rib.h | 1 + zebra/zapi_msg.c | 5 +++-- zebra/zebra_rib.c | 3 ++- zebra/zebra_rnh.c | 32 ++++++++++++++++++++------------ zebra/zebra_rnh.h | 5 +++-- zebra/zebra_routemap.c | 14 ++++++++------ zebra/zebra_srte.c | 2 +- zebra/zebra_vty.c | 8 ++++---- 8 files changed, 42 insertions(+), 28 deletions(-) diff --git a/zebra/rib.h b/zebra/rib.h index 92e1b3635d69..076608bb0f59 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -61,6 +61,7 @@ struct rnh { vrf_id_t vrf_id; afi_t afi; + safi_t safi; uint32_t seqno; diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 4c0a0c82bf81..c5f29b8fe7fb 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -1240,7 +1240,8 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS) /* Anything not AF_INET/INET6 has been filtered out above */ if (!exist || flag_changed) - zebra_evaluate_rnh(zvrf, family2afi(p.family), 1, &p); + zebra_evaluate_rnh(zvrf, family2afi(p.family), 1, &p, + SAFI_UNICAST); zebra_add_rnh_client(rnh, client, zvrf_id(zvrf)); } @@ -1305,7 +1306,7 @@ static void zread_rnh_unregister(ZAPI_HANDLER_ARGS) p.family); return; } - rnh = zebra_lookup_rnh(&p, zvrf_id(zvrf)); + rnh = zebra_lookup_rnh(&p, zvrf_id(zvrf), SAFI_UNICAST); if (rnh) { client->nh_dereg_time = monotime(NULL); zebra_remove_rnh_client(rnh, client); diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 5230f0a4d157..12e82dde9488 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -754,7 +754,8 @@ void zebra_rib_evaluate_rn_nexthops(struct route_node *rn, uint32_t seq) } rnh->seqno = seq; - zebra_evaluate_rnh(zvrf, family2afi(p->family), 0, p); + zebra_evaluate_rnh(zvrf, family2afi(p->family), 0, p, + rnh->safi); } rn = rn->parent; diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index c58debb6affb..e782839d17cd 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -70,14 +70,17 @@ void zebra_rnh_init(void) hook_register(zserv_client_close, zebra_client_cleanup_rnh); } -static inline struct route_table *get_rnh_table(vrf_id_t vrfid, afi_t afi) +static inline struct route_table *get_rnh_table(vrf_id_t vrfid, afi_t afi, + safi_t safi) { struct zebra_vrf *zvrf; struct route_table *t = NULL; zvrf = zebra_vrf_lookup_by_id(vrfid); - if (zvrf) - t = zvrf->rnh_table[afi]; + if (zvrf) { + if (safi == SAFI_UNICAST) + t = zvrf->rnh_table[afi]; + } return t; } @@ -133,13 +136,16 @@ struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, bool *exists) struct route_node *rn; struct rnh *rnh = NULL; afi_t afi = family2afi(p->family); + safi_t safi = SAFI_UNICAST; if (IS_ZEBRA_DEBUG_NHT) { struct vrf *vrf = vrf_lookup_by_id(vrfid); - zlog_debug("%s(%u): Add RNH %pFX", VRF_LOGNAME(vrf), vrfid, p); + zlog_debug("%s(%u): Add RNH %pFX for safi: %u", + VRF_LOGNAME(vrf), vrfid, p, safi); } - table = get_rnh_table(vrfid, afi); + + table = get_rnh_table(vrfid, afi, safi); if (!table) { struct vrf *vrf = vrf_lookup_by_id(vrfid); @@ -170,6 +176,7 @@ struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, bool *exists) rnh->vrf_id = vrfid; rnh->seqno = 0; rnh->afi = afi; + rnh->safi = safi; rnh->zebra_pseudowire_list = list_new(); route_lock_node(rn); rn->info = rnh; @@ -184,12 +191,12 @@ struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, bool *exists) return (rn->info); } -struct rnh *zebra_lookup_rnh(struct prefix *p, vrf_id_t vrfid) +struct rnh *zebra_lookup_rnh(struct prefix *p, vrf_id_t vrfid, safi_t safi) { struct route_table *table; struct route_node *rn; - table = get_rnh_table(vrfid, family2afi(PREFIX_FAMILY(p))); + table = get_rnh_table(vrfid, family2afi(PREFIX_FAMILY(p)), safi); if (!table) return NULL; @@ -343,7 +350,8 @@ void zebra_register_rnh_pseudowire(vrf_id_t vrf_id, struct zebra_pw *pw, if (!listnode_lookup(rnh->zebra_pseudowire_list, pw)) { listnode_add(rnh->zebra_pseudowire_list, pw); pw->rnh = rnh; - zebra_evaluate_rnh(zvrf, family2afi(pw->af), 1, &nh); + zebra_evaluate_rnh(zvrf, family2afi(pw->af), 1, &nh, + SAFI_UNICAST); } else *nht_exists = true; } @@ -762,12 +770,12 @@ static void zebra_rnh_clear_nhc_flag(struct zebra_vrf *zvrf, afi_t afi, * of a particular VRF and address-family or a specific prefix. */ void zebra_evaluate_rnh(struct zebra_vrf *zvrf, afi_t afi, int force, - struct prefix *p) + struct prefix *p, safi_t safi) { struct route_table *rnh_table; struct route_node *nrn; - rnh_table = get_rnh_table(zvrf->vrf->vrf_id, afi); + rnh_table = get_rnh_table(zvrf->vrf->vrf_id, afi, safi); if (!rnh_table) // unexpected return; @@ -802,7 +810,7 @@ void zebra_print_rnh_table(vrf_id_t vrfid, afi_t afi, struct vty *vty, struct route_table *table; struct route_node *rn; - table = get_rnh_table(vrfid, afi); + table = get_rnh_table(vrfid, afi, SAFI_UNICAST); if (!table) { if (IS_ZEBRA_DEBUG_NHT) zlog_debug("print_rnhs: rnh table not found"); @@ -1323,7 +1331,7 @@ static int zebra_cleanup_rnh_client(vrf_id_t vrf_id, afi_t afi, zebra_route_string(client->proto), afi2str(afi)); } - ntable = get_rnh_table(vrf_id, afi); + ntable = get_rnh_table(vrf_id, afi, SAFI_UNICAST); if (!ntable) { zlog_debug("cleanup_rnh_client: rnh table not found"); return -1; diff --git a/zebra/zebra_rnh.h b/zebra/zebra_rnh.h index 01ad7215b802..27c016ebe60f 100644 --- a/zebra/zebra_rnh.h +++ b/zebra/zebra_rnh.h @@ -33,7 +33,8 @@ extern void zebra_rnh_init(void); extern struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, bool *exists); -extern struct rnh *zebra_lookup_rnh(struct prefix *p, vrf_id_t vrfid); +extern struct rnh *zebra_lookup_rnh(struct prefix *p, vrf_id_t vrfid, + safi_t safi); extern void zebra_free_rnh(struct rnh *rnh); extern void zebra_add_rnh_client(struct rnh *rnh, struct zserv *client, vrf_id_t vrfid); @@ -43,7 +44,7 @@ extern void zebra_register_rnh_pseudowire(vrf_id_t, struct zebra_pw *, bool *); extern void zebra_deregister_rnh_pseudowire(vrf_id_t, struct zebra_pw *); extern void zebra_remove_rnh_client(struct rnh *rnh, struct zserv *client); extern void zebra_evaluate_rnh(struct zebra_vrf *zvrf, afi_t afi, int force, - struct prefix *p); + struct prefix *p, safi_t safi); extern void zebra_print_rnh_table(vrf_id_t vrfid, afi_t afi, struct vty *vty, struct prefix *p); diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c index 0887ce1f0a72..908c13f3dfc5 100644 --- a/zebra/zebra_routemap.c +++ b/zebra/zebra_routemap.c @@ -319,7 +319,7 @@ static int ip_nht_rm_add(struct zebra_vrf *zvrf, const char *rmap, int rtype, route_map_counter_increment(NHT_RM_MAP(zvrf, afi, rtype)); if (NHT_RM_MAP(zvrf, afi, rtype)) - zebra_evaluate_rnh(zvrf, AFI_IP, 1, NULL); + zebra_evaluate_rnh(zvrf, AFI_IP, 1, NULL, SAFI_UNICAST); return CMD_SUCCESS; } @@ -340,7 +340,7 @@ static int ip_nht_rm_del(struct zebra_vrf *zvrf, const char *rmap, int rtype, zvrf->vrf->vrf_id, rtype); NHT_RM_MAP(zvrf, afi, rtype) = NULL; - zebra_evaluate_rnh(zvrf, AFI_IP, 1, NULL); + zebra_evaluate_rnh(zvrf, AFI_IP, 1, NULL, SAFI_UNICAST); } XFREE(MTYPE_ROUTE_MAP_NAME, NHT_RM_NAME(zvrf, afi, rtype)); } @@ -1587,8 +1587,9 @@ static void zebra_nht_rm_update(const char *rmap) afi_ip = 1; - zebra_evaluate_rnh(zvrf, AFI_IP, - 1, NULL); + zebra_evaluate_rnh( + zvrf, AFI_IP, 1, NULL, + SAFI_UNICAST); } } } @@ -1617,8 +1618,9 @@ static void zebra_nht_rm_update(const char *rmap) afi_ipv6 = 1; - zebra_evaluate_rnh(zvrf, AFI_IP, - 1, NULL); + zebra_evaluate_rnh( + zvrf, AFI_IP, 1, NULL, + SAFI_UNICAST); } } } diff --git a/zebra/zebra_srte.c b/zebra/zebra_srte.c index 0fa054105e02..d87b3149a648 100644 --- a/zebra/zebra_srte.c +++ b/zebra/zebra_srte.c @@ -196,7 +196,7 @@ static void zebra_sr_policy_notify_update(struct zebra_sr_policy *policy) exit(1); } - rnh = zebra_lookup_rnh(&p, zvrf_id(zvrf)); + rnh = zebra_lookup_rnh(&p, zvrf_id(zvrf), SAFI_UNICAST); if (!rnh) return; diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 779996a80661..fe2ffdfea0d8 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -1374,7 +1374,7 @@ DEFUN (ip_nht_default_route, zvrf->zebra_rnh_ip_default_route = true; - zebra_evaluate_rnh(zvrf, AFI_IP, 0, NULL); + zebra_evaluate_rnh(zvrf, AFI_IP, 0, NULL, SAFI_UNICAST); return CMD_SUCCESS; } @@ -1712,7 +1712,7 @@ DEFUN (no_ip_nht_default_route, return CMD_SUCCESS; zvrf->zebra_rnh_ip_default_route = false; - zebra_evaluate_rnh(zvrf, AFI_IP, 0, NULL); + zebra_evaluate_rnh(zvrf, AFI_IP, 0, NULL, SAFI_UNICAST); return CMD_SUCCESS; } @@ -1732,7 +1732,7 @@ DEFUN (ipv6_nht_default_route, return CMD_SUCCESS; zvrf->zebra_rnh_ipv6_default_route = true; - zebra_evaluate_rnh(zvrf, AFI_IP6, 0, NULL); + zebra_evaluate_rnh(zvrf, AFI_IP6, 0, NULL, SAFI_UNICAST); return CMD_SUCCESS; } @@ -1753,7 +1753,7 @@ DEFUN (no_ipv6_nht_default_route, return CMD_SUCCESS; zvrf->zebra_rnh_ipv6_default_route = false; - zebra_evaluate_rnh(zvrf, AFI_IP6, 0, NULL); + zebra_evaluate_rnh(zvrf, AFI_IP6, 0, NULL, SAFI_UNICAST); return CMD_SUCCESS; } From a4598b97d93937eead669d406afa91fd070de83b Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 24 Sep 2021 16:42:25 -0400 Subject: [PATCH 021/188] zebra: Create the SAFI_MULTICAST rnh tables Actually create the SAFI_MULTICAST rnh tables. No code uses these yet. Signed-off-by: Donald Sharp --- zebra/zebra_rnh.c | 10 ++++++---- zebra/zebra_vrf.c | 8 ++++++++ zebra/zebra_vrf.h | 1 + 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index e782839d17cd..1d33d5f4a404 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -80,6 +80,8 @@ static inline struct route_table *get_rnh_table(vrf_id_t vrfid, afi_t afi, if (zvrf) { if (safi == SAFI_UNICAST) t = zvrf->rnh_table[afi]; + else if (safi == SAFI_MULTICAST) + t = zvrf->rnh_table_multicast[afi]; } return t; @@ -88,7 +90,7 @@ static inline struct route_table *get_rnh_table(vrf_id_t vrfid, afi_t afi, static void zebra_rnh_remove_from_routing_table(struct rnh *rnh) { struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(rnh->vrf_id); - struct route_table *table = zvrf->table[rnh->afi][SAFI_UNICAST]; + struct route_table *table = zvrf->table[rnh->afi][rnh->safi]; struct route_node *rn; rib_dest_t *dest; @@ -112,7 +114,7 @@ static void zebra_rnh_remove_from_routing_table(struct rnh *rnh) static void zebra_rnh_store_in_routing_table(struct rnh *rnh) { struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(rnh->vrf_id); - struct route_table *table = zvrf->table[rnh->afi][SAFI_UNICAST]; + struct route_table *table = zvrf->table[rnh->afi][rnh->safi]; struct route_node *rn; rib_dest_t *dest; @@ -223,7 +225,7 @@ void zebra_free_rnh(struct rnh *rnh) list_delete(&rnh->zebra_pseudowire_list); zvrf = zebra_vrf_lookup_by_id(rnh->vrf_id); - table = zvrf->table[family2afi(rnh->resolved_route.family)][SAFI_UNICAST]; + table = zvrf->table[family2afi(rnh->resolved_route.family)][rnh->safi]; if (table) { struct route_node *rern; @@ -563,7 +565,7 @@ zebra_rnh_resolve_nexthop_entry(struct zebra_vrf *zvrf, afi_t afi, *prn = NULL; - route_table = zvrf->table[afi][SAFI_UNICAST]; + route_table = zvrf->table[afi][rnh->safi]; if (!route_table) return NULL; diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c index 69b586d71edb..d52601b63da2 100644 --- a/zebra/zebra_vrf.c +++ b/zebra/zebra_vrf.c @@ -150,6 +150,10 @@ static int zebra_vrf_enable(struct vrf *vrf) table = route_table_init(); table->cleanup = zebra_rnhtable_node_cleanup; zvrf->rnh_table[afi] = table; + + table = route_table_init(); + table->cleanup = zebra_rnhtable_node_cleanup; + zvrf->rnh_table_multicast[afi] = table; } /* Kick off any VxLAN-EVPN processing. */ @@ -192,6 +196,8 @@ static int zebra_vrf_disable(struct vrf *vrf) for (afi = AFI_IP; afi <= AFI_IP6; afi++) { route_table_finish(zvrf->rnh_table[afi]); zvrf->rnh_table[afi] = NULL; + route_table_finish(zvrf->rnh_table_multicast[afi]); + zvrf->rnh_table_multicast[afi] = NULL; for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) rib_close_table(zvrf->table[afi][safi]); @@ -292,6 +298,8 @@ static int zebra_vrf_delete(struct vrf *vrf) if (zvrf->rnh_table[afi]) route_table_finish(zvrf->rnh_table[afi]); + if (zvrf->rnh_table_multicast[afi]) + route_table_finish(zvrf->rnh_table[afi]); } otable = otable_pop(&zvrf->other_tables); diff --git a/zebra/zebra_vrf.h b/zebra/zebra_vrf.h index e6126a22ca92..5afa655203ad 100644 --- a/zebra/zebra_vrf.h +++ b/zebra/zebra_vrf.h @@ -78,6 +78,7 @@ struct zebra_vrf { /* Recursive Nexthop table */ struct route_table *rnh_table[AFI_MAX]; + struct route_table *rnh_table_multicast[AFI_MAX]; struct otable_head other_tables; From 027db4691747355140e182902ec6412579e43718 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 24 Sep 2021 16:58:27 -0400 Subject: [PATCH 022/188] lib, zebra: Send safi for rnh resolution Pass down the safi for when we need address resolution. At this point in time we are hard coding the safi to SAFI_UNICAST. Future commits will take advantage of this. Signed-off-by: Donald Sharp --- lib/zclient.c | 2 ++ zebra/zapi_msg.c | 12 ++++++++---- zebra/zebra_rnh.c | 1 + zebra/zebra_srte.c | 1 + 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/zclient.c b/lib/zclient.c index 6f863c5ea6b4..d639fa84b80c 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -775,6 +775,7 @@ enum zclient_send_status zclient_send_rnh(struct zclient *zclient, int command, zclient_create_header(s, command, vrf_id); stream_putc(s, (connected) ? 1 : 0); stream_putc(s, (resolve_via_def) ? 1 : 0); + stream_putw(s, SAFI_UNICAST); stream_putw(s, PREFIX_FAMILY(p)); stream_putc(s, p->prefixlen); switch (PREFIX_FAMILY(p)) { @@ -1926,6 +1927,7 @@ bool zapi_nexthop_update_decode(struct stream *s, struct zapi_route *nhr) memset(nhr, 0, sizeof(*nhr)); STREAM_GETL(s, nhr->message); + STREAM_GETW(s, nhr->safi); STREAM_GETW(s, nhr->prefix.family); STREAM_GETC(s, nhr->prefix.prefixlen); switch (nhr->prefix.family) { diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index c5f29b8fe7fb..e0eaaa311b8b 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -1176,6 +1176,7 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS) bool exist; bool flag_changed = false; uint8_t orig_flags; + safi_t safi; if (IS_ZEBRA_DEBUG_NHT) zlog_debug( @@ -1191,9 +1192,10 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS) while (l < hdr->length) { STREAM_GETC(s, connected); STREAM_GETC(s, resolve_via_default); + STREAM_GETW(s, safi); STREAM_GETW(s, p.family); STREAM_GETC(s, p.prefixlen); - l += 5; + l += 7; if (p.family == AF_INET) { client->v4_nh_watch_add_cnt++; if (p.prefixlen > IPV4_MAX_BITLEN) { @@ -1241,7 +1243,7 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS) /* Anything not AF_INET/INET6 has been filtered out above */ if (!exist || flag_changed) zebra_evaluate_rnh(zvrf, family2afi(p.family), 1, &p, - SAFI_UNICAST); + safi); zebra_add_rnh_client(rnh, client, zvrf_id(zvrf)); } @@ -1257,6 +1259,7 @@ static void zread_rnh_unregister(ZAPI_HANDLER_ARGS) struct stream *s; struct prefix p; unsigned short l = 0; + safi_t safi; if (IS_ZEBRA_DEBUG_NHT) zlog_debug( @@ -1276,9 +1279,10 @@ static void zread_rnh_unregister(ZAPI_HANDLER_ARGS) if (ignore != 0) goto stream_failure; + STREAM_GETW(s, safi); STREAM_GETW(s, p.family); STREAM_GETC(s, p.prefixlen); - l += 5; + l += 7; if (p.family == AF_INET) { client->v4_nh_watch_rem_cnt++; if (p.prefixlen > IPV4_MAX_BITLEN) { @@ -1306,7 +1310,7 @@ static void zread_rnh_unregister(ZAPI_HANDLER_ARGS) p.family); return; } - rnh = zebra_lookup_rnh(&p, zvrf_id(zvrf), SAFI_UNICAST); + rnh = zebra_lookup_rnh(&p, zvrf_id(zvrf), safi); if (rnh) { client->nh_dereg_time = monotime(NULL); zebra_remove_rnh_client(rnh, client); diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index 1d33d5f4a404..f5faaab71be2 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -1173,6 +1173,7 @@ int zebra_send_rnh_update(struct rnh *rnh, struct zserv *client, SET_FLAG(message, ZAPI_MESSAGE_SRTE); stream_putl(s, message); + stream_putw(s, rnh->safi); stream_putw(s, rn->p.family); switch (rn->p.family) { case AF_INET: diff --git a/zebra/zebra_srte.c b/zebra/zebra_srte.c index d87b3149a648..7933ef66b147 100644 --- a/zebra/zebra_srte.c +++ b/zebra/zebra_srte.c @@ -116,6 +116,7 @@ static int zebra_sr_policy_notify_update_client(struct zebra_sr_policy *policy, SET_FLAG(message, ZAPI_MESSAGE_SRTE); stream_putl(s, message); + stream_putw(s, SAFI_UNICAST); switch (policy->endpoint.ipa_type) { case IPADDR_V4: stream_putw(s, AF_INET); From 6ba578ef294b041b6e677c78ccf464f775806688 Mon Sep 17 00:00:00 2001 From: Chirag Shah Date: Tue, 21 Sep 2021 15:03:58 -0700 Subject: [PATCH 023/188] zebra: add resolver for nexthop in json zebra rib 'show ip route json' lists all nexthops in a flat list. To identify the recursively resolved nexthops relation adding a flag "resolver" as delimiter to identify recursively resolved nexthop in the list. Testing Done: { "1.1.1.0\/24":[ { "prefix":"1.1.1.0\/24", "protocol":"static", .... "nexthops":[ { "flags":5, "ip":"27.0.0.14", "afi":"ipv4", "active":true, "recursive":true, "weight":1 }, { "flags":3, "fib":true, "ip":"fe80::202:ff:fe00:11", "afi":"ipv6", "interfaceIndex":12, "interfaceName":"uplink-1", "resolver":true, <-- Resolver for recursive true flag nh "active":true, "weight":1 }, ] } ] } Signed-off-by: Chirag Shah --- zebra/zebra_vty.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 79087c584992..133034d1abec 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -775,6 +775,13 @@ static void show_nexthop_json_helper(json_object *json_nexthop, break; } + /* This nexthop is a resolver for the parent nexthop. + * Set resolver flag for better clarity and delimiter + * in flat list of nexthops in json. + */ + if (nexthop->rparent) + json_object_boolean_true_add(json_nexthop, "resolver"); + if (nexthop->vrf_id != re->vrf_id) json_object_string_add(json_nexthop, "vrf", vrf_id_to_name(nexthop->vrf_id)); From 4687748973ff1d062af3347180fafb23ae877d09 Mon Sep 17 00:00:00 2001 From: Adriano Marto Reis Date: Tue, 28 Sep 2021 12:38:41 +1000 Subject: [PATCH 024/188] pimd: fixing command "no ip msdp mesh-group member" Deleting a mesh-group member no longer deletes the mesh-group. Complete bug description at: https://github.com/FRRouting/frr/issues/9664 Signed-off-by: Adriano Marto Reis --- pimd/pim_cmd.c | 8 ++++---- pimd/pim_nb_config.c | 7 +++++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 14aa71052422..ca61d6c57b73 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -3842,7 +3842,7 @@ static void pim_cli_legacy_mesh_group_behavior(struct vty *vty, xpath_member_value)) { member_dnode = yang_dnode_get(vty->candidate_config->dnode, xpath_member_value); - if (!yang_is_last_list_dnode(member_dnode)) + if (!member_dnode || !yang_is_last_list_dnode(member_dnode)) return; } @@ -9762,7 +9762,7 @@ DEFPY(no_ip_msdp_mesh_group_member, return CMD_WARNING_CONFIG_FAILED; } - nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY, NULL); + nb_cli_enqueue_change(vty, xpath_member_value, NB_OP_DESTROY, NULL); /* * If this is the last member, then we must remove the group altogether @@ -9796,7 +9796,7 @@ DEFPY(ip_msdp_mesh_group_source, "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4", gname); nb_cli_enqueue_change(vty, xpath_value, NB_OP_CREATE, NULL); - /* Create mesh group member. */ + /* Create mesh group source. */ strlcat(xpath_value, "/source", sizeof(xpath_value)); nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, saddr_str); @@ -9827,7 +9827,7 @@ DEFPY(no_ip_msdp_mesh_group_source, "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4", gname); nb_cli_enqueue_change(vty, xpath_value, NB_OP_CREATE, NULL); - /* Create mesh group member. */ + /* Create mesh group source. */ strlcat(xpath_value, "/source", sizeof(xpath_value)); nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY, NULL); diff --git a/pimd/pim_nb_config.c b/pimd/pim_nb_config.c index f4627cbcc256..b9da8ec0685c 100644 --- a/pimd/pim_nb_config.c +++ b/pimd/pim_nb_config.c @@ -1168,6 +1168,7 @@ int pim_msdp_mesh_group_members_destroy(struct nb_cb_destroy_args *args) { struct pim_msdp_mg_mbr *mbr; struct pim_msdp_mg *mg; + const struct lyd_node *mg_dnode; switch (args->event) { case NB_EV_VALIDATE: @@ -1176,9 +1177,11 @@ int pim_msdp_mesh_group_members_destroy(struct nb_cb_destroy_args *args) break; case NB_EV_APPLY: mbr = nb_running_get_entry(args->dnode, NULL, true); - mg = nb_running_get_entry(args->dnode, "../", true); - + mg_dnode = + yang_dnode_get_parent(args->dnode, "msdp-mesh-groups"); + mg = nb_running_get_entry(mg_dnode, NULL, true); pim_msdp_mg_mbr_del(mg, mbr); + nb_running_unset_entry(args->dnode); break; } From f62de63c6a0cf38ea20ecdb35194424be06c01fe Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Tue, 28 Sep 2021 11:20:32 +0200 Subject: [PATCH 025/188] *: `frr-format` with unmodified GCC Since there's very few locations where the `frr-format` actually prints false positive warnings, consensus seems to be to just work around the false positives even if the code is correct. In fact, there is only one pattern of false positives currently, in `bfdd/dplane.c` which does `vty_out("%"PRIu64, (uint64_t)be64toh(...))`. The workaround/fix for this is a replacement `be64toh` whose type is always `uint64_t` regardless of what OS we're on, making the cast unnecessary. Signed-off-by: David Lamparter --- bfdd/dplane.c | 31 +++++++++++------------- doc/developer/workflow.rst | 49 ++++++++++++++++++++++++++++++++++++++ lib/network.h | 36 ++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+), 17 deletions(-) diff --git a/bfdd/dplane.c b/bfdd/dplane.c index 4b7f9ba7ace5..9dee2a558952 100644 --- a/bfdd/dplane.c +++ b/bfdd/dplane.c @@ -157,8 +157,8 @@ static void bfd_dplane_debug_message(const struct bfddp_message *msg) case ECHO_REPLY: case ECHO_REQUEST: zlog_debug(" [dp_time=%" PRIu64 " bfdd_time=%" PRIu64 "]", - (uint64_t)be64toh(msg->data.echo.dp_time), - (uint64_t)be64toh(msg->data.echo.bfdd_time)); + be64toh(msg->data.echo.dp_time), + be64toh(msg->data.echo.bfdd_time)); break; case DP_ADD_SESSION: @@ -245,21 +245,18 @@ static void bfd_dplane_debug_message(const struct bfddp_message *msg) " packets), " "out %" PRIu64 " bytes (%" PRIu64 " packets)}]", ntohl(msg->data.session_counters.lid), - (uint64_t)be64toh( - msg->data.session_counters.control_input_bytes), - (uint64_t)be64toh(msg->data.session_counters - .control_input_packets), - (uint64_t)be64toh(msg->data.session_counters - .control_output_bytes), - (uint64_t)be64toh(msg->data.session_counters - .control_output_packets), - (uint64_t)be64toh(msg->data.session_counters.echo_input_bytes), - (uint64_t)be64toh( - msg->data.session_counters.echo_input_packets), - (uint64_t)be64toh( - msg->data.session_counters.echo_output_bytes), - (uint64_t)be64toh(msg->data.session_counters - .echo_output_packets)); + be64toh(msg->data.session_counters.control_input_bytes), + be64toh(msg->data.session_counters + .control_input_packets), + be64toh(msg->data.session_counters + .control_output_bytes), + be64toh(msg->data.session_counters + .control_output_packets), + be64toh(msg->data.session_counters.echo_input_bytes), + be64toh(msg->data.session_counters.echo_input_packets), + be64toh(msg->data.session_counters.echo_output_bytes), + be64toh(msg->data.session_counters + .echo_output_packets)); break; } } diff --git a/doc/developer/workflow.rst b/doc/developer/workflow.rst index 2ce5f5d1c8c9..04a56587ce94 100644 --- a/doc/developer/workflow.rst +++ b/doc/developer/workflow.rst @@ -1151,6 +1151,37 @@ but are no longer actively maintained. MemorySanitizer is not available in GCC. The different Sanitizers are mostly incompatible with each other. Please refer to GCC/LLVM documentation for details. +frr-format plugin + This is a GCC plugin provided with FRR that does extended type checks for + ``%pFX``-style printfrr extensions. To use this plugin, + + 1. install GCC plugin development files, e.g.:: + + apt-get install gcc-10-plugin-dev + + 2. **before** running ``configure``, compile the plugin with:: + + make -C tools/gcc-plugins CXX=g++-10 + + (Edit the GCC version to what you're using, it should work for GCC 9 or + newer.) + + After this, the plugin should be automatically picked up by ``configure``. + The plugin does not change very frequently, so you can keep it around across + work on different FRR branches. After a ``git clean -x``, the ``make`` line + will need to be run again. You can also add ``--with-frr-format`` to the + ``configure`` line to make sure the plugin is used, otherwise if something + is not set up correctly it might be silently ignored. + + .. warning:: + + Do **not** enable this plugin for package/release builds. It is intended + for developer/debug builds only. Since it modifies the compiler, it may + cause silent corruption of the executable files. + + Using the plugin also changes the string for ``PRI[udx]64`` from the + system value to ``%L[udx]`` (normally ``%ll[udx]`` or ``%l[udx]``.) + Additionally, the FRR codebase is regularly scanned with Coverity. Unfortunately Coverity does not have the ability to handle scanning pull requests, but after code is merged it will send an email notifying project @@ -1264,6 +1295,24 @@ may not be obvious in how to fix. Here are some notes on specific warnings: (and varargs calling convention.) This is a notable difference to C++, where the ``void`` is optional and an empty parameter list means no parameters. +* ``"strict match required"`` from the frr-format plugin: check if you are + using a cast in a printf parameter list. The frr-format plugin cannot + access correct full type information for casts like + ``printfrr(..., (uint64_t)something, ...)`` and will print incorrect + warnings particularly if ``uint64_t``, ``size_t`` or ``ptrdiff_t`` are + involved. The problem is *not* triggered with a variable or function return + value of the exact same type (without a cast). + + Since these cases are very rare, community consensus is to just work around + the warning even though the code might be correct. If you are running into + this, your options are: + + 1. try to avoid the cast altogether, maybe using a different printf format + specifier (e.g. ``%lu`` instead of ``%zu`` or ``PRIu64``). + 2. fix the type(s) of the function/variable/struct member being printed + 3. create a temporary variable with the value and print that without a cast + (this is the last resort and was not necessary anywhere so far.) + .. _documentation: diff --git a/lib/network.h b/lib/network.h index 4a9666984fad..10ed917572db 100644 --- a/lib/network.h +++ b/lib/network.h @@ -22,6 +22,13 @@ #ifndef _ZEBRA_NETWORK_H #define _ZEBRA_NETWORK_H +#ifdef HAVE_SYS_ENDIAN_H +#include +#endif +#ifdef HAVE_ENDIAN_H +#include +#endif + #ifdef __cplusplus extern "C" { #endif @@ -45,6 +52,35 @@ extern int set_cloexec(int fd); extern float htonf(float); extern float ntohf(float); +/* force type for be64toh/htobe64 to be uint64_t, *without* a direct cast + * + * this is a workaround for false-positive printfrr warnings from FRR's + * frr-format GCC plugin that would be triggered from + * { printfrr("%"PRIu64, (uint64_t)be64toh(...)); } + * + * the key element here is that "(uint64_t)expr" causes the warning, while + * "({ uint64_t x = expr; x; })" does not. (The cast is the trigger, a + * variable of the same type works correctly.) + */ + +/* zap system definitions... */ +#ifdef be64toh +#undef be64toh +#endif +#ifdef htobe64 +#undef htobe64 +#endif + +#if BYTE_ORDER == LITTLE_ENDIAN +#define be64toh(x) ({ uint64_t r = __builtin_bswap64(x); r; }) +#define htobe64(x) ({ uint64_t r = __builtin_bswap64(x); r; }) +#elif BYTE_ORDER == BIG_ENDIAN +#define be64toh(x) ({ uint64_t r = (x); r; }) +#define htobe64(x) ({ uint64_t r = (x); r; }) +#else +#error nobody expects the endianish inquisition. check OS endian.h headers. +#endif + /** * Helper function that returns a random long value. The main purpose of * this function is to hide a `random()` call that gets flagged by coverity From b7c21fad11d19458ab62202e10401a954cba5e1c Mon Sep 17 00:00:00 2001 From: Igor Ryzhov Date: Tue, 28 Sep 2021 15:44:51 +0300 Subject: [PATCH 026/188] zebra: fix buffer overflow mac is only 6 bytes long and we shouldn't blindly copy unknown number of bytes into it. Fixes #9671. Signed-off-by: Igor Ryzhov --- zebra/rt_netlink.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index e36f320ad917..ec2c09e6802d 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -3744,7 +3744,6 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id) if (tb[NDA_LLADDR]) { /* copy LLADDR information */ l2_len = RTA_PAYLOAD(tb[NDA_LLADDR]); - memcpy(&mac, RTA_DATA(tb[NDA_LLADDR]), l2_len); } if (l2_len == IPV4_MAX_BYTELEN || l2_len == 0) { union sockunion link_layer_ipv4; @@ -3752,7 +3751,7 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id) if (l2_len) { sockunion_family(&link_layer_ipv4) = AF_INET; memcpy((void *)sockunion_get_addr(&link_layer_ipv4), - &mac, l2_len); + RTA_DATA(tb[NDA_LLADDR]), l2_len); } else sockunion_family(&link_layer_ipv4) = AF_UNSPEC; zsend_nhrp_neighbor_notify( From 1b9ebabb27ff74512611742543b214ab9a2ae0dd Mon Sep 17 00:00:00 2001 From: Lou Berger Date: Tue, 28 Sep 2021 11:29:46 -0400 Subject: [PATCH 027/188] tests: get bgp_l3vpn_to_bgp_vrf running, also improve logging Signed-off-by: Lou Berger --- tests/topotests/bgp_l3vpn_to_bgp_vrf/customize.py | 7 ++++++- tests/topotests/lib/ltemplate.py | 6 ++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/customize.py b/tests/topotests/bgp_l3vpn_to_bgp_vrf/customize.py index 8fd344696e46..fce8e708f2fa 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/customize.py +++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/customize.py @@ -206,7 +206,7 @@ def ltemplatePreRouterStartHook(): for cmd in cmds: cc.doCmd(tgen, rtr, cmd.format(rtr)) cc.doCmd(tgen, rtr, "ip link set dev {0}-eth0 master {0}-cust2".format(rtr)) - if cc.getOutput() != 4: + if cc.getOutput() != 0: InitSuccess = False logger.info( "Unexpected output seen ({} times, tests will be skipped".format( @@ -214,6 +214,11 @@ def ltemplatePreRouterStartHook(): ) ) else: + rtrs = ["r1", "r3", "r4", "ce4"] + for rtr in rtrs: + logger.info("{} configured".format(rtr)) + cc.doCmd(tgen, rtr, "ip -d link show type vrf") + cc.doCmd(tgen, rtr, "ip link show") InitSuccess = True logger.info("VRF config successful!") return InitSuccess diff --git a/tests/topotests/lib/ltemplate.py b/tests/topotests/lib/ltemplate.py index 910573c14c56..c98bfac9ee6d 100644 --- a/tests/topotests/lib/ltemplate.py +++ b/tests/topotests/lib/ltemplate.py @@ -217,6 +217,7 @@ def __init__(self): self.resetCounts() def doCmd(self, tgen, rtr, cmd, checkstr=None): + logger.info("doCmd: {} {}".format(rtr, cmd)) output = tgen.net[rtr].cmd(cmd).strip() if len(output): self.output += 1 @@ -227,9 +228,10 @@ def doCmd(self, tgen, rtr, cmd, checkstr=None): else: self.match += 1 return ret - logger.info("command: {} {}".format(rtr, cmd)) logger.info("output: " + output) - self.none += 1 + else: + logger.info("No output") + self.none += 1 return None def resetCounts(self): From 94e8feaa9fa447e1a643fcb1b982630fdb895b4a Mon Sep 17 00:00:00 2001 From: Mark Stapp Date: Wed, 29 Sep 2021 11:49:43 -0400 Subject: [PATCH 028/188] tests: fix string comparison in lib/pim.py Use correct string comparison syntax in lib/pim.py Signed-off-by: Mark Stapp --- tests/topotests/lib/pim.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/topotests/lib/pim.py b/tests/topotests/lib/pim.py index 9d3708821888..944981add422 100644 --- a/tests/topotests/lib/pim.py +++ b/tests/topotests/lib/pim.py @@ -1020,10 +1020,10 @@ def verify_ip_mroutes( if not isinstance(group_addresses, list): group_addresses = [group_addresses] - if not isinstance(iif, list) and iif is not "none": + if not isinstance(iif, list) and iif != "none": iif = [iif] - if not isinstance(oil, list) and oil is not "none": + if not isinstance(oil, list) and oil != "none": oil = [oil] for grp_addr in group_addresses: From ef322b022fa1bd961132cc8f1e818922f5d30962 Mon Sep 17 00:00:00 2001 From: Igor Ryzhov Date: Thu, 30 Sep 2021 12:31:05 +0300 Subject: [PATCH 029/188] *: cleanup interface loopback/vrf check There's a helper function to check whether the interface is loopback or VRF - if_is_loopback_or_vrf. Let's use it whenever we need to check that. There's no functional change in this commit. Signed-off-by: Igor Ryzhov --- ospfd/ospf_interface.c | 6 +++--- zebra/connected.c | 3 +-- zebra/rtadv.c | 34 +++++++++++----------------------- 3 files changed, 15 insertions(+), 28 deletions(-) diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c index eb7a8348e832..81cc34600047 100644 --- a/ospfd/ospf_interface.c +++ b/ospfd/ospf_interface.c @@ -477,7 +477,7 @@ struct ospf_interface *ospf_if_lookup_recv_if(struct ospf *ospf, if (oi->type == OSPF_IFTYPE_VIRTUALLINK) continue; - if (if_is_loopback(oi->ifp) || if_is_vrf(oi->ifp)) + if (if_is_loopback_or_vrf(oi->ifp)) continue; if (CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED)) @@ -719,7 +719,7 @@ static int ospf_if_delete_hook(struct interface *ifp) int ospf_if_is_enable(struct ospf_interface *oi) { - if (!(if_is_loopback(oi->ifp) || if_is_vrf(oi->ifp))) + if (!(if_is_loopback_or_vrf(oi->ifp))) if (if_is_up(oi->ifp)) return 1; @@ -1291,7 +1291,7 @@ uint8_t ospf_default_iftype(struct interface *ifp) { if (if_is_pointopoint(ifp)) return OSPF_IFTYPE_POINTOPOINT; - else if (if_is_loopback(ifp) || if_is_vrf(ifp)) + else if (if_is_loopback_or_vrf(ifp)) return OSPF_IFTYPE_LOOPBACK; else return OSPF_IFTYPE_BROADCAST; diff --git a/zebra/connected.c b/zebra/connected.c index 0511b351854e..80d434bafc7d 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -73,8 +73,7 @@ static void connected_announce(struct interface *ifp, struct connected *ifc) if (!ifc) return; - if (!if_is_loopback(ifp) && ifc->address->family == AF_INET && - !IS_ZEBRA_IF_VRF(ifp)) { + if (!if_is_loopback_or_vrf(ifp) && ifc->address->family == AF_INET) { if (ifc->address->prefixlen == IPV4_MAX_BITLEN) SET_FLAG(ifc->flags, ZEBRA_IFA_UNNUMBERED); else diff --git a/zebra/rtadv.c b/zebra/rtadv.c index 976beefab05f..9610f71d09c7 100644 --- a/zebra/rtadv.c +++ b/zebra/rtadv.c @@ -493,9 +493,7 @@ static int rtadv_timer(struct thread *thread) RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) FOR_ALL_INTERFACES (vrf, ifp) { - if (if_is_loopback(ifp) - || CHECK_FLAG(ifp->status, - ZEBRA_INTERFACE_VRF_LOOPBACK) + if (if_is_loopback_or_vrf(ifp) || !if_is_operative(ifp)) continue; @@ -728,8 +726,7 @@ static void rtadv_process_packet(uint8_t *buf, unsigned int len, VRF_LOGNAME(vrf), ifp->ifindex, len, addr_str); } - if (if_is_loopback(ifp) - || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) + if (if_is_loopback_or_vrf(ifp)) return; /* Check interface configuration. */ @@ -1465,8 +1462,7 @@ DEFUN (ipv6_nd_ra_fast_retrans, VTY_DECLVAR_CONTEXT(interface, ifp); struct zebra_if *zif = ifp->info; - if (if_is_loopback(ifp) - || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) { + if (if_is_loopback_or_vrf(ifp)) { vty_out(vty, "Cannot configure IPv6 Router Advertisements on this interface\n"); return CMD_WARNING_CONFIG_FAILED; @@ -1488,8 +1484,7 @@ DEFUN (no_ipv6_nd_ra_fast_retrans, VTY_DECLVAR_CONTEXT(interface, ifp); struct zebra_if *zif = ifp->info; - if (if_is_loopback(ifp) - || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) { + if (if_is_loopback_or_vrf(ifp)) { vty_out(vty, "Cannot configure IPv6 Router Advertisements on this interface\n"); return CMD_WARNING_CONFIG_FAILED; @@ -1511,8 +1506,7 @@ DEFPY (ipv6_nd_ra_hop_limit, VTY_DECLVAR_CONTEXT(interface, ifp); struct zebra_if *zif = ifp->info; - if (if_is_loopback(ifp) - || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) { + if (if_is_loopback_or_vrf(ifp)) { vty_out(vty, "Cannot configure IPv6 Router Advertisements on this interface\n"); return CMD_WARNING_CONFIG_FAILED; @@ -1535,8 +1529,7 @@ DEFPY (no_ipv6_nd_ra_hop_limit, VTY_DECLVAR_CONTEXT(interface, ifp); struct zebra_if *zif = ifp->info; - if (if_is_loopback(ifp) - || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) { + if (if_is_loopback_or_vrf(ifp)) { vty_out(vty, "Cannot configure IPv6 Router Advertisements on this interface\n"); return CMD_WARNING_CONFIG_FAILED; @@ -1558,8 +1551,7 @@ DEFPY (ipv6_nd_ra_retrans_interval, VTY_DECLVAR_CONTEXT(interface, ifp); struct zebra_if *zif = ifp->info; - if (if_is_loopback(ifp) - || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) { + if (if_is_loopback_or_vrf(ifp)) { vty_out(vty, "Cannot configure IPv6 Router Advertisements on loopback interface\n"); return CMD_WARNING_CONFIG_FAILED; @@ -1582,8 +1574,7 @@ DEFPY (no_ipv6_nd_ra_retrans_interval, VTY_DECLVAR_CONTEXT(interface, ifp); struct zebra_if *zif = ifp->info; - if (if_is_loopback(ifp) - || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) { + if (if_is_loopback_or_vrf(ifp)) { vty_out(vty, "Cannot remove IPv6 Router Advertisements on loopback interface\n"); return CMD_WARNING_CONFIG_FAILED; @@ -1604,8 +1595,7 @@ DEFUN (ipv6_nd_suppress_ra, VTY_DECLVAR_CONTEXT(interface, ifp); struct zebra_if *zif = ifp->info; - if (if_is_loopback(ifp) - || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) { + if (if_is_loopback_or_vrf(ifp)) { vty_out(vty, "Cannot configure IPv6 Router Advertisements on this interface\n"); return CMD_WARNING_CONFIG_FAILED; @@ -1629,8 +1619,7 @@ DEFUN (no_ipv6_nd_suppress_ra, VTY_DECLVAR_CONTEXT(interface, ifp); struct zebra_if *zif = ifp->info; - if (if_is_loopback(ifp) - || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) { + if (if_is_loopback_or_vrf(ifp)) { vty_out(vty, "Cannot configure IPv6 Router Advertisements on this interface\n"); return CMD_WARNING_CONFIG_FAILED; @@ -2619,8 +2608,7 @@ static int rtadv_config_write(struct vty *vty, struct interface *ifp) zif = ifp->info; - if (!(if_is_loopback(ifp) - || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK))) { + if (!if_is_loopback_or_vrf(ifp)) { if (zif->rtadv.AdvSendAdvertisements && CHECK_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED)) vty_out(vty, " no ipv6 nd suppress-ra\n"); From e439b73606d54dd6aebc5e194bc326e9e18c97b1 Mon Sep 17 00:00:00 2001 From: Anuradha Karuppiah Date: Thu, 16 Sep 2021 11:46:02 -0700 Subject: [PATCH 030/188] bgpd: fix build error seen when lttng is enabled Signed-off-by: Anuradha Karuppiah --- bgpd/bgp_trace.h | 1 + 1 file changed, 1 insertion(+) diff --git a/bgpd/bgp_trace.h b/bgpd/bgp_trace.h index 303e06c9c97b..92f23ecf7074 100644 --- a/bgpd/bgp_trace.h +++ b/bgpd/bgp_trace.h @@ -34,6 +34,7 @@ #include #include "bgpd/bgpd.h" +#include "bgpd/bgp_attr.h" #include "lib/stream.h" /* clang-format off */ From 25dd89e398b41c50e0e928a01d5ce8376f60c220 Mon Sep 17 00:00:00 2001 From: Manoj Naragund Date: Thu, 30 Sep 2021 09:15:18 -0700 Subject: [PATCH 031/188] ospf6d: minor struct compare issues. Problem Statement: Multiple struct compare using memcmp, which might result in issue due to structure padding/alignment. Fix: The code changes involve structure member by member comparison to remove any issues related to padding/alignment. Signed-off-by: Manoj Naragund (cherry picked from commit 67db821a1d6d68b19862d50b68ed19278c5f2422) --- ospf6d/ospf6_abr.c | 17 +++++++++++++---- ospf6d/ospf6_abr.h | 2 ++ ospf6d/ospf6_asbr.c | 9 ++------- ospf6d/ospf6_intra.c | 7 ++----- 4 files changed, 19 insertions(+), 16 deletions(-) diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c index 57165201bd82..057e1d9ea25f 100644 --- a/ospf6d/ospf6_abr.c +++ b/ospf6d/ospf6_abr.c @@ -53,6 +53,17 @@ unsigned char conf_debug_ospf6_abr; +int ospf6_ls_origin_cmp(struct ospf6_path *o_path, struct ospf6_route *route) +{ + if (((o_path->origin.type == route->path.origin.type) + && (o_path->origin.id == route->path.origin.id) + && (o_path->origin.adv_router == + route->path.origin.adv_router))) + return 1; + else + return 0; +} + bool ospf6_check_and_set_router_abr(struct ospf6 *o) { struct listnode *node; @@ -816,8 +827,7 @@ void ospf6_abr_old_path_update(struct ospf6_route *old_route, for (ALL_LIST_ELEMENTS(old_route->paths, anode, anext, o_path)) { if (o_path->area_id != route->path.area_id || - (memcmp(&(o_path)->origin, &(route)->path.origin, - sizeof(struct ospf6_ls_origin)) != 0)) + (!ospf6_ls_origin_cmp(o_path, route))) continue; if ((o_path->cost == route->path.cost) && @@ -1233,8 +1243,7 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa) for (ALL_LIST_ELEMENTS_RO(old_route->paths, anode, o_path)) { if (o_path->area_id == route->path.area_id && - (memcmp(&(o_path)->origin, &(route)->path.origin, - sizeof(struct ospf6_ls_origin)) == 0)) + (ospf6_ls_origin_cmp(o_path, route))) break; } diff --git a/ospf6d/ospf6_abr.h b/ospf6d/ospf6_abr.h index 08521ecb0fd1..75e051761db7 100644 --- a/ospf6d/ospf6_abr.h +++ b/ospf6d/ospf6_abr.h @@ -89,5 +89,7 @@ extern void ospf6_abr_init(void); extern void ospf6_abr_range_update(struct ospf6_route *range, struct ospf6 *ospf6); extern void ospf6_abr_remove_unapproved_summaries(struct ospf6 *ospf6); +extern int ospf6_ls_origin_cmp(struct ospf6_path *o_path, + struct ospf6_route *route); #endif /*OSPF6_ABR_H*/ diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c index df40c608a1ea..beed61d04731 100644 --- a/ospf6d/ospf6_asbr.c +++ b/ospf6d/ospf6_asbr.c @@ -290,9 +290,7 @@ void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old, * origin. */ if (o_path->area_id != route->path.area_id - || (memcmp(&(o_path)->origin, &(route)->path.origin, - sizeof(struct ospf6_ls_origin)) - != 0)) + || (!ospf6_ls_origin_cmp(o_path, route))) continue; /* Cost is not same then delete current path */ @@ -411,10 +409,7 @@ void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old, for (ALL_LIST_ELEMENTS_RO(old_route->paths, anode, o_path)) { if (o_path->area_id == route->path.area_id - && (memcmp(&(o_path)->origin, - &(route)->path.origin, - sizeof(struct ospf6_ls_origin)) - == 0)) + && (ospf6_ls_origin_cmp(o_path, route))) break; } /* If path is not found in old_route paths's list, diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c index 277af4b1c521..27e21a041718 100644 --- a/ospf6d/ospf6_intra.c +++ b/ospf6d/ospf6_intra.c @@ -1525,8 +1525,7 @@ void ospf6_intra_prefix_route_ecmp_path(struct ospf6_area *oa, * origin. */ if (o_path->area_id != route->path.area_id || - (memcmp(&(o_path)->origin, &(route)->path.origin, - sizeof(struct ospf6_ls_origin)) != 0)) + (!ospf6_ls_origin_cmp(o_path, route))) continue; /* Cost is not same then delete current path */ @@ -1631,9 +1630,7 @@ void ospf6_intra_prefix_route_ecmp_path(struct ospf6_area *oa, for (ALL_LIST_ELEMENTS_RO(old_route->paths, anode, o_path)) { if (o_path->area_id == route->path.area_id && - (memcmp(&(o_path)->origin, - &(route)->path.origin, - sizeof(struct ospf6_ls_origin)) == 0)) + (ospf6_ls_origin_cmp(o_path, route))) break; } /* If path is not found in old_route paths's list, From 7a53c83a680a4294983e49010237f4755fe90e8d Mon Sep 17 00:00:00 2001 From: Igor Ryzhov Date: Fri, 1 Oct 2021 14:04:42 +0300 Subject: [PATCH 032/188] docker: remove grpc from Travis CI Signed-off-by: Igor Ryzhov --- docker/ubuntu20-ci/Dockerfile | 2 -- 1 file changed, 2 deletions(-) diff --git a/docker/ubuntu20-ci/Dockerfile b/docker/ubuntu20-ci/Dockerfile index 032db8b8ed36..b9fe385c3a9e 100644 --- a/docker/ubuntu20-ci/Dockerfile +++ b/docker/ubuntu20-ci/Dockerfile @@ -11,7 +11,6 @@ RUN apt update && \ install-info build-essential libsnmp-dev perl \ libcap-dev python2 libelf-dev \ sudo gdb curl iputils-ping time \ - libgrpc++-dev libgrpc-dev protobuf-compiler-grpc \ lua5.3 liblua5.3-dev \ net-tools iproute2 && \ curl https://bootstrap.pypa.io/pip/2.7/get-pip.py --output /tmp/get-pip.py && \ @@ -61,7 +60,6 @@ RUN cd ~/frr && \ --sbindir=/usr/lib/frr \ --sysconfdir=/etc/frr \ --enable-vtysh \ - --enable-grpc \ --enable-pimd \ --enable-sharpd \ --enable-multipath=64 \ From b0a007df7ae11e12732a14312cd2a1500e22c200 Mon Sep 17 00:00:00 2001 From: Igor Ryzhov Date: Fri, 1 Oct 2021 12:42:04 +0300 Subject: [PATCH 033/188] bgpd: fix access-list update callback When a regular access-list is updated, we should update references to regular access-lists, not as-path access-lists. Fixes #9707. Signed-off-by: Igor Ryzhov --- bgpd/bgpd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index ec91e7e22994..925af80cb790 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -6266,7 +6266,8 @@ static void peer_distribute_update(struct access_list *access) for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) { if (access->name) - update_group_policy_update(bgp, BGP_POLICY_FILTER_LIST, + update_group_policy_update(bgp, + BGP_POLICY_DISTRIBUTE_LIST, access->name, 0, 0); for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { FOREACH_AFI_SAFI (afi, safi) { From e3cb363a73f01026ae45e2fdd95c7aa5b3a1867c Mon Sep 17 00:00:00 2001 From: Igor Ryzhov Date: Fri, 1 Oct 2021 13:05:40 +0300 Subject: [PATCH 034/188] doc: fix ospf distribute-list command and description Signed-off-by: Igor Ryzhov --- doc/user/ospfd.rst | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/doc/user/ospfd.rst b/doc/user/ospfd.rst index 0122e2ac7594..207459bd1f7d 100644 --- a/doc/user/ospfd.rst +++ b/doc/user/ospfd.rst @@ -691,13 +691,12 @@ Redistribution the 'always' keyword is given then the default is always advertised, even when there is no default present in the routing table. -.. clicmd:: distribute-list NAME out (kernel|connected|static|rip|ospf - - .. _ospf-distribute-list: +.. clicmd:: distribute-list NAME out + Apply the access-list filter, NAME, to redistributed routes of the given - type before allowing the routes to redistributed into OSPF + type before allowing the routes to be redistributed into OSPF (:ref:`ospf redistribution `). .. clicmd:: default-metric (0-16777214) From 0757efc0ce7a3566e833519b67d22ed28a46c262 Mon Sep 17 00:00:00 2001 From: Igor Ryzhov Date: Fri, 1 Oct 2021 18:36:02 +0300 Subject: [PATCH 035/188] doc: fix range for bgp expanded community list Signed-off-by: Igor Ryzhov --- doc/user/bgp.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst index 5c9d96e32b09..d37c2b668280 100644 --- a/doc/user/bgp.rst +++ b/doc/user/bgp.rst @@ -2145,7 +2145,7 @@ Numbered Community Lists When number is used for BGP community list name, the number has special meanings. Community list number in the range from 1 and 99 is standard community list. Community list number in the range from 100 -to 199 is expanded community list. These community lists are called +to 500 is expanded community list. These community lists are called as numbered community lists. On the other hand normal community lists is called as named community lists. @@ -2154,10 +2154,10 @@ is called as named community lists. This command defines a new community list. The argument to (1-99) defines the list identifier. -.. clicmd:: bgp community-list (100-199) permit|deny COMMUNITY +.. clicmd:: bgp community-list (100-500) permit|deny COMMUNITY This command defines a new expanded community list. The argument to - (100-199) defines the list identifier. + (100-500) defines the list identifier. .. _bgp-community-alias: From 23aa35ade57501a408fa57f346450a40f1b0158c Mon Sep 17 00:00:00 2001 From: Anuradha Karuppiah Date: Tue, 28 Sep 2021 11:18:43 -0700 Subject: [PATCH 036/188] bgpd: initial batch of evpn lttng tracepoints Low overhead bgp-evpn TPs have been added which push data out in a binary format - >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> root@switch:~# lttng list --userspace |grep "frr_bgp:evpn" frr_bgp:evpn_mh_nh_rmac_zsend (loglevel: TRACE_DEBUG_LINE (13)) (type: tracepoint) frr_bgp:evpn_mh_nh_zsend (loglevel: TRACE_INFO (6)) (type: tracepoint) frr_bgp:evpn_mh_nhg_zsend (loglevel: TRACE_INFO (6)) (type: tracepoint) frr_bgp:evpn_mh_vtep_zsend (loglevel: TRACE_INFO (6)) (type: tracepoint) frr_bgp:evpn_bum_vtep_zsend (loglevel: TRACE_INFO (6)) (type: tracepoint) frr_bgp:evpn_mac_ip_zsend (loglevel: TRACE_INFO (6)) (type: tracepoint) root@switch:~# >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> In addition to the tracepoints a babeltrace python plugin for pretty printing (binary data is converted into grepable strings). Sample usage - frr_babeltrace.py trace_path Sample tracepoint output - >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 1. frr_bgp: evpn_mac_ip_zsend frr_bgp:evpn_mac_ip_zsend {'action': 'add', 'vni': 1007, 'mac': '00:02:00:00:00:04', 'ip': 'fe80::202:ff:fe00:4', 'vtep': '27.0.0.15', 'esi': '03:44:38:39:ff:ff:01:00:00:02'} 2. frr_bgp: evpn_mh_vtep_zsend frr_bgp:evpn_mh_vtep_zsend {'action': 'add', 'esi': '03:44:38:39:ff:ff:01:00:00:02', 'vtep': '27.0.0.16'} 3. frr_bgp: evpn_mh_nhg_zsend frr_bgp:evpn_mh_nhg_zsend {'action': 'add', 'type': 'v4', 'nhg': 74999998, 'esi': '03:44:38:39:ff:ff:01:00:00:02', 'vrf': 85} 4. frr_bgp: evpn_mh_nh_zsend frr_bgp:evpn_mh_nh_zsend {'nhg': 74999998, 'vtep': '27.0.0.16', 'svi': 93} 5. frr_bgp: evpn_mh_nh_rmac_zsend frr_bgp:evpn_mh_nh_rmac_zsend {'action': 'add', 'vrf': 85, 'nh': '::ffff:1b00:12', 'rmac': '00:02:00:00:00:50'} >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Signed-off-by: Anuradha Karuppiah --- bgpd/bgp_evpn.c | 6 ++ bgpd/bgp_evpn_mh.c | 15 ++++ bgpd/bgp_evpn_mh.h | 2 + bgpd/bgp_trace.h | 90 ++++++++++++++++++++++ tools/frr_babeltrace.py | 163 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 276 insertions(+) create mode 100755 tools/frr_babeltrace.py diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index 3219ae13b5b6..ea54c14222cf 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -54,6 +54,7 @@ #include "bgpd/bgp_mac.h" #include "bgpd/bgp_vty.h" #include "bgpd/bgp_nht.h" +#include "bgpd/bgp_trace.h" /* * Definitions and external declarations. @@ -653,6 +654,9 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn, &p->prefix.macip_addr.mac, &p->prefix.macip_addr.ip, flags, seq, &remote_vtep_ip); + frrtrace(5, frr_bgp, evpn_mac_ip_zsend, add, vpn, p, remote_vtep_ip, + esi); + return zclient_send_message(zclient); } @@ -703,6 +707,8 @@ static int bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn, add ? "ADD" : "DEL", vpn->vni, &p->prefix.imet_addr.ip.ipaddr_v4); + frrtrace(3, frr_bgp, evpn_bum_vtep_zsend, add, vpn, p); + return zclient_send_message(zclient); } diff --git a/bgpd/bgp_evpn_mh.c b/bgpd/bgp_evpn_mh.c index 34094a0bde98..9316d218a286 100644 --- a/bgpd/bgp_evpn_mh.c +++ b/bgpd/bgp_evpn_mh.c @@ -50,6 +50,7 @@ #include "bgpd/bgp_label.h" #include "bgpd/bgp_nht.h" #include "bgpd/bgp_mpath.h" +#include "bgpd/bgp_trace.h" static void bgp_evpn_local_es_down(struct bgp *bgp, struct bgp_evpn_es *es); @@ -1225,6 +1226,8 @@ static struct bgp_evpn_es_vtep *bgp_evpn_es_vtep_new(struct bgp_evpn_es *es, es_vtep->es = es; es_vtep->vtep_ip.s_addr = vtep_ip.s_addr; + inet_ntop(AF_INET, &es_vtep->vtep_ip, es_vtep->vtep_str, + sizeof(es_vtep->vtep_str)); listnode_init(&es_vtep->es_listnode, es_vtep); listnode_add_sort(es->es_vtep_list, &es_vtep->es_listnode); @@ -1301,6 +1304,8 @@ static int bgp_zebra_send_remote_es_vtep(struct bgp *bgp, zlog_debug("Tx %s Remote ESI %s VTEP %pI4", add ? "ADD" : "DEL", es->esi_str, &es_vtep->vtep_ip); + frrtrace(3, frr_bgp, evpn_mh_vtep_zsend, add, es, es_vtep); + return zclient_send_message(zclient); } @@ -2522,6 +2527,8 @@ static void bgp_evpn_l3nhg_zebra_add_v4_or_v6(struct bgp_evpn_es_vrf *es_vrf, es_vrf->bgp_vrf->vrf_id, v4_nhg ? "v4_nhg" : "v6_nhg", nhg_id); + frrtrace(4, frr_bgp, evpn_mh_nhg_zsend, true, v4_nhg, nhg_id, es_vrf); + /* only the gateway ip changes for each NH. rest of the params * are constant */ @@ -2558,6 +2565,8 @@ static void bgp_evpn_l3nhg_zebra_add_v4_or_v6(struct bgp_evpn_es_vrf *es_vrf, zlog_debug("nhg %u vtep %pI4 l3-svi %d", api_nhg.id, &es_vtep->vtep_ip, es_vrf->bgp_vrf->l3vni_svi_ifindex); + + frrtrace(3, frr_bgp, evpn_mh_nh_zsend, nhg_id, es_vtep, es_vrf); } if (!api_nhg.nexthop_num) @@ -2603,6 +2612,10 @@ static void bgp_evpn_l3nhg_zebra_del_v4_or_v6(struct bgp_evpn_es_vrf *es_vrf, es_vrf->es->esi_str, es_vrf->bgp_vrf->vrf_id, v4_nhg ? "v4_nhg" : "v6_nhg", api_nhg.id); + + frrtrace(4, frr_bgp, evpn_mh_nhg_zsend, false, v4_nhg, api_nhg.id, + es_vrf); + zclient_nhg_send(zclient, ZEBRA_NHG_DEL, &api_nhg); } @@ -4202,6 +4215,8 @@ static void bgp_evpn_nh_zebra_update_send(struct bgp_evpn_nh *nh, bool add) nh->bgp_vrf->name, nh->nh_str); } + frrtrace(2, frr_bgp, evpn_mh_nh_rmac_zsend, add, nh); + zclient_send_message(zclient); } diff --git a/bgpd/bgp_evpn_mh.h b/bgpd/bgp_evpn_mh.h index 22a42156641d..37a46c2f0e07 100644 --- a/bgpd/bgp_evpn_mh.h +++ b/bgpd/bgp_evpn_mh.h @@ -145,6 +145,8 @@ struct bgp_evpn_es_vtep { struct bgp_evpn_es *es; /* parent ES */ struct in_addr vtep_ip; + char vtep_str[INET6_ADDRSTRLEN]; + uint32_t flags; /* Rxed a Type4 route from this PE */ #define BGP_EVPNES_VTEP_ESR (1 << 0) diff --git a/bgpd/bgp_trace.h b/bgpd/bgp_trace.h index 303e06c9c97b..1b740d69b534 100644 --- a/bgpd/bgp_trace.h +++ b/bgpd/bgp_trace.h @@ -35,6 +35,9 @@ #include "bgpd/bgpd.h" #include "lib/stream.h" +#include "bgpd/bgp_evpn_private.h" +#include "bgpd/bgp_evpn_mh.h" + /* clang-format off */ @@ -243,6 +246,93 @@ TRACEPOINT_EVENT( ) TRACEPOINT_LOGLEVEL(frr_bgp, bgp_dest_unlock, TRACE_INFO) +TRACEPOINT_EVENT( + frr_bgp, + evpn_mac_ip_zsend, + TP_ARGS(int, add, struct bgpevpn *, vpn, + const struct prefix_evpn *, pfx, + struct in_addr, vtep, esi_t *, esi), + TP_FIELDS( + ctf_string(action, add ? "add" : "del") + ctf_integer(vni_t, vni, vpn->vni) + ctf_array(unsigned char, mac, &pfx->prefix.macip_addr.mac, + sizeof(struct ethaddr)) + ctf_array(unsigned char, ip, &pfx->prefix.macip_addr.ip, + sizeof(struct ipaddr)) + ctf_integer_network_hex(unsigned int, vtep, vtep.s_addr) + ctf_array(unsigned char, esi, esi, sizeof(esi_t)) + ) +) +TRACEPOINT_LOGLEVEL(frr_bgp, evpn_mac_ip_zsend, TRACE_INFO) + +TRACEPOINT_EVENT( + frr_bgp, + evpn_bum_vtep_zsend, + TP_ARGS(int, add, struct bgpevpn *, vpn, + const struct prefix_evpn *, pfx), + TP_FIELDS( + ctf_string(action, add ? "add" : "del") + ctf_integer(vni_t, vni, vpn->vni) + ctf_integer_network_hex(unsigned int, vtep, + pfx->prefix.imet_addr.ip.ipaddr_v4.s_addr) + ) +) +TRACEPOINT_LOGLEVEL(frr_bgp, evpn_bum_vtep_zsend, TRACE_INFO) + +TRACEPOINT_EVENT( + frr_bgp, + evpn_mh_vtep_zsend, + TP_ARGS(bool, add, struct bgp_evpn_es *, es, + struct bgp_evpn_es_vtep *, es_vtep), + TP_FIELDS( + ctf_string(action, add ? "add" : "del") + ctf_string(esi, es->esi_str) + ctf_string(vtep, es_vtep->vtep_str) + ) +) +TRACEPOINT_LOGLEVEL(frr_bgp, evpn_mh_vtep_zsend, TRACE_INFO) + +TRACEPOINT_EVENT( + frr_bgp, + evpn_mh_nhg_zsend, + TP_ARGS(bool, add, bool, type_v4, uint32_t, nhg_id, + struct bgp_evpn_es_vrf *, es_vrf), + TP_FIELDS( + ctf_string(action, add ? "add" : "del") + ctf_string(type, type_v4 ? "v4" : "v6") + ctf_integer(unsigned int, nhg, nhg_id) + ctf_string(esi, es_vrf->es->esi_str) + ctf_integer(int, vrf, es_vrf->bgp_vrf->vrf_id) + ) +) +TRACEPOINT_LOGLEVEL(frr_bgp, evpn_mh_nhg_zsend, TRACE_INFO) + +TRACEPOINT_EVENT( + frr_bgp, + evpn_mh_nh_zsend, + TP_ARGS(uint32_t, nhg_id, struct bgp_evpn_es_vtep *, vtep, + struct bgp_evpn_es_vrf *, es_vrf), + TP_FIELDS( + ctf_integer(unsigned int, nhg, nhg_id) + ctf_string(vtep, vtep->vtep_str) + ctf_integer(int, svi, es_vrf->bgp_vrf->l3vni_svi_ifindex) + ) +) +TRACEPOINT_LOGLEVEL(frr_bgp, evpn_mh_nh_zsend, TRACE_INFO) + +TRACEPOINT_EVENT( + frr_bgp, + evpn_mh_nh_rmac_zsend, + TP_ARGS(bool, add, struct bgp_evpn_nh *, nh), + TP_FIELDS( + ctf_string(action, add ? "add" : "del") + ctf_integer(int, vrf, nh->bgp_vrf->vrf_id) + ctf_string(nh, nh->nh_str) + ctf_array(unsigned char, rmac, &nh->rmac, + sizeof(struct ethaddr)) + ) +) +TRACEPOINT_LOGLEVEL(frr_bgp, evpn_nh_rmac_zsend, TRACE_INFO) /* clang-format on */ #include diff --git a/tools/frr_babeltrace.py b/tools/frr_babeltrace.py new file mode 100755 index 000000000000..305839575846 --- /dev/null +++ b/tools/frr_babeltrace.py @@ -0,0 +1,163 @@ +#!/usr/bin/env python3 +''' +Usage: frr_babeltrace.py trace_path + +FRR pushes data into lttng tracepoints in the least overhead way possible +i.e. as binary-data/crf_arrays. These traces need to be converted into pretty +strings for easy greping etc. This script is a babeltrace python plugin for +that pretty printing. + +Copyright (C) 2021 NVIDIA Corporation +Anuradha Karuppiah + +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 +''' + +import ipaddress +import socket +import sys + +import babeltrace + +########################### common parsers - start ############################ +def print_ip_addr(field_val): + ''' + pretty print "struct ipaddr" + ''' + if field_val[0] == socket.AF_INET: + addr = [str(fv) for fv in field_val[4:8]] + return str(ipaddress.IPv4Address('.'.join(addr))) + + if field_val[0] == socket.AF_INET6: + tmp = ''.join('%02x' % fb for fb in field_val[4:]) + addr = [] + while tmp: + addr.append(tmp[:4]) + tmp = tmp[4:] + addr = ':'.join(addr) + return str(ipaddress.IPv6Address(addr)) + + if not field_val[0]: + return '' + + return field_val + + +def print_mac(field_val): + ''' + pretty print "u8 mac[6]" + ''' + return ':'.join('%02x' % fb for fb in field_val) + +def print_net_ipv4_addr(field_val): + ''' + pretty print ctf_integer_network ipv4 + ''' + return str(ipaddress.IPv4Address(field_val)) + +def print_esi(field_val): + ''' + pretty print ethernet segment id, esi_t + ''' + return ':'.join('%02x' % fb for fb in field_val) + +def get_field_list(event): + ''' + only fetch fields added via the TP, skip metadata etc. + ''' + return event.field_list_with_scope(babeltrace.CTFScope.EVENT_FIELDS) + +def parse_event(event, field_parsers): + ''' + Wild card event parser; doesn't make things any prettier + ''' + field_list = get_field_list(event) + field_info = {} + for field in field_list: + if field in field_parsers: + field_parser = field_parsers.get(field) + field_info[field] = field_parser(event.get(field)) + else: + field_info[field] = event.get(field) + print(event.name, field_info) +############################ common parsers - end ############################# + +############################ evpn parsers - start ############################# +def parse_frr_bgp_evpn_mac_ip_zsend(event): + ''' + bgp evpn mac-ip parser; raw format - + ctf_array(unsigned char, mac, &pfx->prefix.macip_addr.mac, + sizeof(struct ethaddr)) + ctf_array(unsigned char, ip, &pfx->prefix.macip_addr.ip, + sizeof(struct ipaddr)) + ctf_integer_network_hex(unsigned int, vtep, vtep.s_addr) + ctf_array(unsigned char, esi, esi, sizeof(esi_t)) + ''' + field_parsers = {'ip': print_ip_addr, + 'mac': print_mac, + 'esi': print_esi, + 'vtep': print_net_ipv4_addr} + + parse_event(event, field_parsers) + +def parse_frr_bgp_evpn_bum_vtep_zsend(event): + ''' + bgp evpn bum-vtep parser; raw format - + ctf_integer_network_hex(unsigned int, vtep, + pfx->prefix.imet_addr.ip.ipaddr_v4.s_addr) + + ''' + field_parsers = {'vtep': print_net_ipv4_addr} + + parse_event(event, field_parsers) + +def parse_frr_bgp_evpn_mh_nh_rmac_send(event): + ''' + bgp evpn nh-rmac parser; raw format - + ctf_array(unsigned char, rmac, &nh->rmac, sizeof(struct ethaddr)) + ''' + field_parsers = {'rmac': print_mac} + + parse_event(event, field_parsers) + +############################ evpn parsers - end ############################# + +def main(): + ''' + FRR lttng trace output parser; babel trace plugin + ''' + event_parsers = {'frr_bgp:evpn_mac_ip_zsend': + parse_frr_bgp_evpn_mac_ip_zsend, + 'frr_bgp:evpn_bum_vtep_zsend': + parse_frr_bgp_evpn_bum_vtep_zsend, + 'frr_bgp:evpn_mh_nh_rmac_zsend': + parse_frr_bgp_evpn_mh_nh_rmac_send} + + # get the trace path from the first command line argument + trace_path = sys.argv[1] + + # grab events + trace_collection = babeltrace.TraceCollection() + trace_collection.add_traces_recursive(trace_path, 'ctf') + + for event in trace_collection.events: + if event.name in event_parsers: + event_parser = event_parsers.get(event.name) + event_parser(event) + else: + parse_event(event, {}) + +if __name__ == '__main__': + main() From 89eb4727defa522140bfa5b1476d4d050384e78a Mon Sep 17 00:00:00 2001 From: rgirada Date: Fri, 1 Oct 2021 11:59:11 -0700 Subject: [PATCH 037/188] ospfd: GR helper functionality change in helper exit Description: As per the RFC 3623 section 3.2, OSPF nbr shouldn't be deleted even in unsuccessful helper exit. 1. Made the changes to keep neighbour even after exit. 2. Restart the dead timer after expiry in helper. Otherwise, Restarter will be in FULL state in helper forever until it receives the 'hello'. Signed-off-by: Rajesh Girada --- ospfd/ospf_gr_helper.c | 6 +----- ospfd/ospf_nsm.c | 7 +++++-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/ospfd/ospf_gr_helper.c b/ospfd/ospf_gr_helper.c index 11ad45d30f7a..b3eaf7bbdbb6 100644 --- a/ospfd/ospf_gr_helper.c +++ b/ospfd/ospf_gr_helper.c @@ -723,14 +723,10 @@ void ospf_gr_helper_exit(struct ospf_neighbor *nbr, /* check exit triggered due to successful completion * of graceful restart. - * If no, bring down the neighbour. */ if (reason != OSPF_GR_HELPER_COMPLETED) { if (IS_DEBUG_OSPF_GR) - zlog_debug( - "%s, Failed GR exit, so bringing down the neighbour", - __func__); - OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_KillNbr); + zlog_debug("%s, Unsuccessful GR exit", __func__); } /*Recalculate the DR for the network segment */ diff --git a/ospfd/ospf_nsm.c b/ospfd/ospf_nsm.c index 268fb81e52a9..dee25275d694 100644 --- a/ospfd/ospf_nsm.c +++ b/ospfd/ospf_nsm.c @@ -76,10 +76,13 @@ static int ospf_inactivity_timer(struct thread *thread) */ if (!OSPF_GR_IS_ACTIVE_HELPER(nbr)) OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_InactivityTimer); - else if (IS_DEBUG_OSPF_GR) + else if (IS_DEBUG_OSPF_GR) { zlog_debug( - "%s, Acting as HELPER for this neighbour, So inactivitytimer event will not be fired.", + "%s, Acting as HELPER for this neighbour, So restart the dead timer", __func__); + OSPF_NSM_TIMER_ON(nbr->t_inactivity, ospf_inactivity_timer, + nbr->v_inactivity); + } return 0; } From 1b3ac4c7cab99b96870dfbee0160926dfff9ec1c Mon Sep 17 00:00:00 2001 From: Chirag Shah Date: Sun, 3 Oct 2021 15:55:03 -0700 Subject: [PATCH 038/188] zebra: add nhg id to show ip route json Add json field nexthop group id to 'show ip route json'. Testing Done: { "27.0.0.14\/32":[ { "prefix":"27.0.0.14\/32", "protocol":"bgp", "selected":true, "destSelected":true, "distance":20, "metric":0, "installed":true, "table":254, "internalStatus":16, "internalFlags":8, "internalNextHopNum":2, "internalNextHopActiveNum":2, "nexthopGroupId":103, <---- New field "uptime":"00:04:37", "nexthops":[ { "ip":"fe80::202:ff:fe00:11", "interfaceName":"uplink-1", }, { "ip":"fe80::202:ff:fe00:1d", "interfaceName":"uplink-2", } ] } ] } Signed-off-by: Chirag Shah --- zebra/zebra_vty.c | 1 + 1 file changed, 1 insertion(+) diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 79087c584992..4b06e8478862 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -965,6 +965,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn, json_object_int_add(json_route, "internalNextHopActiveNum", nexthop_group_active_nexthop_num( &(re->nhe->nhg))); + json_object_int_add(json_route, "nexthopGroupId", re->nhe_id); json_object_string_add(json_route, "uptime", up_str); From e1a32ec1c5a4468a8ab7f7d92febfdbebe475d79 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 1 Oct 2021 10:32:57 -0400 Subject: [PATCH 039/188] bgpd: bgp_announce_route should know if we should force the update or not When calling bgp_announce_route allow it to properly set the flag to force an update to go out or not. Signed-off-by: Donald Sharp --- bgpd/bgp_packet.c | 8 +++++--- bgpd/bgp_route.c | 14 ++++++++++---- bgpd/bgp_route.h | 3 ++- bgpd/bgpd.c | 17 +++++++++-------- 4 files changed, 26 insertions(+), 16 deletions(-) diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index bb2dbc942766..de9a89523b4e 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -1961,6 +1961,7 @@ static int bgp_route_refresh_receive(struct peer *peer, bgp_size_t size) struct update_group *updgrp; struct peer *updgrp_peer; uint8_t subtype; + bool force_update = false; bgp_size_t msg_length = size - (BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE); @@ -2222,7 +2223,7 @@ static int bgp_route_refresh_receive(struct peer *peer, bgp_size_t size) /* Avoid supressing duplicate routes later * when processing in subgroup_announce_table(). */ - SET_FLAG(paf->subgroup->sflags, SUBGRP_STATUS_FORCE_UPDATES); + force_update = true; /* If the peer is configured for default-originate clear the * SUBGRP_STATUS_DEFAULT_ORIGINATE flag so that we will @@ -2354,7 +2355,7 @@ static int bgp_route_refresh_receive(struct peer *peer, bgp_size_t size) } /* Perform route refreshment to the peer */ - bgp_announce_route(peer, afi, safi); + bgp_announce_route(peer, afi, safi, force_update); /* No FSM action necessary */ return BGP_PACKET_NOOP; @@ -2457,7 +2458,8 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt, peer->afc_recv[afi][safi] = 1; if (peer->afc[afi][safi]) { peer->afc_nego[afi][safi] = 1; - bgp_announce_route(peer, afi, safi); + bgp_announce_route(peer, afi, safi, + false); } } else { peer->afc_recv[afi][safi] = 0; diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index fc9717845006..5bc1b5a40a6b 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -4588,8 +4588,11 @@ static int bgp_announce_route_timer_expired(struct thread *t) * bgp_announce_route * * *Triggers* announcement of routes of a given AFI/SAFI to a peer. + * + * if force is true we will force an update even if the update + * limiting code is attempted to kick in. */ -void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi) +void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi, bool force) { struct peer_af *paf; struct update_subgroup *subgrp; @@ -4606,6 +4609,9 @@ void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi) if (!subgrp || paf->t_announce_route) return; + if (force) + SET_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES); + /* * Start a timer to stagger/delay the announce. This serves * two purposes - announcement can potentially be combined for @@ -4634,7 +4640,7 @@ void bgp_announce_route_all(struct peer *peer) safi_t safi; FOREACH_AFI_SAFI (afi, safi) - bgp_announce_route(peer, afi, safi); + bgp_announce_route(peer, afi, safi, false); } /* Flag or unflag bgp_dest to determine whether it should be treated by @@ -4772,7 +4778,7 @@ static int bgp_soft_reconfig_table_task(struct thread *thread) table->soft_reconfig_peers, peer); bgp_announce_route(peer, table->afi, - table->safi); + table->safi, false); if (list_isempty( table->soft_reconfig_peers)) { list_delete( @@ -4800,7 +4806,7 @@ static int bgp_soft_reconfig_table_task(struct thread *thread) */ for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode, peer)) { listnode_delete(table->soft_reconfig_peers, peer); - bgp_announce_route(peer, table->afi, table->safi); + bgp_announce_route(peer, table->afi, table->safi, false); } list_delete(&table->soft_reconfig_peers); diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index 7609f7196dea..37bf675b674f 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -608,7 +608,8 @@ extern void bgp_process_queue_init(struct bgp *bgp); extern void bgp_route_init(void); extern void bgp_route_finish(void); extern void bgp_cleanup_routes(struct bgp *); -extern void bgp_announce_route(struct peer *, afi_t, safi_t); +extern void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi, + bool force); extern void bgp_stop_announce_route_timer(struct peer_af *paf); extern void bgp_announce_route_all(struct peer *); extern void bgp_default_originate(struct peer *, afi_t, safi_t, int); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 925af80cb790..bdf646f60310 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -2156,7 +2156,8 @@ static int peer_activate_af(struct peer *peer, afi_t afi, safi_t safi) CAPABILITY_ACTION_SET); if (peer->afc_recv[afi][safi]) { peer->afc_nego[afi][safi] = 1; - bgp_announce_route(peer, afi, safi); + bgp_announce_route(peer, afi, safi, + false); } } else { peer->last_reset = PEER_DOWN_AF_ACTIVATE; @@ -4142,7 +4143,7 @@ void peer_change_action(struct peer *peer, afi_t afi, safi_t safi, SUBGRP_STATUS_FORCE_UPDATES); update_group_adjust_peer(paf); - bgp_announce_route(peer, afi, safi); + bgp_announce_route(peer, afi, safi, false); } } @@ -5058,7 +5059,7 @@ int peer_default_originate_set(struct peer *peer, afi_t afi, safi_t safi, if (peer_established(peer) && peer->afc_nego[afi][safi]) { update_group_adjust_peer(peer_af_find(peer, afi, safi)); bgp_default_originate(peer, afi, safi, 0); - bgp_announce_route(peer, afi, safi); + bgp_announce_route(peer, afi, safi, false); } /* Skip peer-group mechanics for regular peers. */ @@ -5095,7 +5096,7 @@ int peer_default_originate_set(struct peer *peer, afi_t afi, safi_t safi, update_group_adjust_peer( peer_af_find(member, afi, safi)); bgp_default_originate(member, afi, safi, 0); - bgp_announce_route(member, afi, safi); + bgp_announce_route(member, afi, safi, false); } } @@ -5134,7 +5135,7 @@ int peer_default_originate_unset(struct peer *peer, afi_t afi, safi_t safi) if (peer_established(peer) && peer->afc_nego[afi][safi]) { update_group_adjust_peer(peer_af_find(peer, afi, safi)); bgp_default_originate(peer, afi, safi, 1); - bgp_announce_route(peer, afi, safi); + bgp_announce_route(peer, afi, safi, false); } /* Skip peer-group mechanics for regular peers. */ @@ -5165,7 +5166,7 @@ int peer_default_originate_unset(struct peer *peer, afi_t afi, safi_t safi) if (peer_established(member) && member->afc_nego[afi][safi]) { update_group_adjust_peer(peer_af_find(member, afi, safi)); bgp_default_originate(member, afi, safi, 1); - bgp_announce_route(member, afi, safi); + bgp_announce_route(member, afi, safi, false); } } @@ -5213,7 +5214,7 @@ static void peer_on_policy_change(struct peer *peer, afi_t afi, safi_t safi, if (outbound) { update_group_adjust_peer(peer_af_find(peer, afi, safi)); if (peer_established(peer)) - bgp_announce_route(peer, afi, safi); + bgp_announce_route(peer, afi, safi, false); } else { if (!peer_established(peer)) return; @@ -7480,7 +7481,7 @@ int peer_clear_soft(struct peer *peer, afi_t afi, safi_t safi, UNSET_FLAG(paf->subgroup->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE); - bgp_announce_route(peer, afi, safi); + bgp_announce_route(peer, afi, safi, false); } if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX) { From f3d20a2aa5746ad4b00a53b04df4fd863d8c49b4 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 29 Sep 2021 11:42:19 -0400 Subject: [PATCH 040/188] bgpd: When removing v6 address being used as a nexthop ensure peer is reset With v6 interface based peering, we send the global as well as the LL address as nexthops to the peer. When either of these were removed on the interface we were not necessarily resetting the connection. Leaving bgp in a state where the peer had reachability for addresses that are no longer in use. Modify the code that when we receive an interface address deletion event. Check to see that we are using the v6 address as nexthops for that peer and if so, tell it to reset. I initially struggled with a hard reset of the peer or a clear but choose to follow other places in the code that we noticed address changes that resulted in hard resets. Ticket: #2799568 Signed-off-by: Donald Sharp --- bgpd/bgp_zebra.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 2a67bb2f8c19..09fe399c295d 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -338,8 +338,11 @@ static int bgp_interface_address_add(ZAPI_CALLBACK_ARGS) static int bgp_interface_address_delete(ZAPI_CALLBACK_ARGS) { + struct listnode *node, *nnode; struct connected *ifc; + struct peer *peer; struct bgp *bgp; + struct prefix *addr; bgp = bgp_lookup_by_vrf_id(vrf_id); @@ -356,6 +359,35 @@ static int bgp_interface_address_delete(ZAPI_CALLBACK_ARGS) bgp_connected_delete(bgp, ifc); } + addr = ifc->address; + + if (bgp) { + /* + * When we are using the v6 global as part of the peering + * nexthops and we are removing it, then we need to + * clear the peer data saved for that nexthop and + * cause a re-announcement of the route. Since + * we do not want the peering to bounce. + */ + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + afi_t afi; + safi_t safi; + + if (addr->family == AF_INET) + continue; + + if (!IN6_IS_ADDR_LINKLOCAL(&addr->u.prefix6) + && memcmp(&peer->nexthop.v6_global, + &addr->u.prefix6, 16) + == 0) { + memset(&peer->nexthop.v6_global, 0, 16); + FOREACH_AFI_SAFI (afi, safi) + bgp_announce_route(peer, afi, safi, + true); + } + } + } + connected_free(&ifc); return 0; From cb00030f9adac6e9159487bd72696947420f9c7c Mon Sep 17 00:00:00 2001 From: Igor Ryzhov Date: Mon, 4 Oct 2021 15:22:24 +0300 Subject: [PATCH 041/188] doc: fix debugging-ospf label Signed-off-by: Igor Ryzhov --- doc/user/ospfd.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/user/ospfd.rst b/doc/user/ospfd.rst index 0122e2ac7594..a058f6dd3613 100644 --- a/doc/user/ospfd.rst +++ b/doc/user/ospfd.rst @@ -954,8 +954,6 @@ Router Information Show Router Capabilities PCE parameters. -.. _debugging-ospf: - Segment Routing =============== @@ -1042,6 +1040,8 @@ TI-LFA requires a proper Segment Routing configuration. Note that so far only P2P interfaces are supported. +.. _debugging-ospf: + Debugging OSPF ============== From 651151f0be906671f7a48fff7a22d30a1d794698 Mon Sep 17 00:00:00 2001 From: Igor Ryzhov Date: Mon, 4 Oct 2021 15:23:46 +0300 Subject: [PATCH 042/188] isisd: remove unused function declaration Signed-off-by: Igor Ryzhov --- isisd/isisd.h | 1 - 1 file changed, 1 deletion(-) diff --git a/isisd/isisd.h b/isisd/isisd.h index 64fbf78a0737..e3d4edd27964 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -248,7 +248,6 @@ void isis_terminate(void); void isis_master_init(struct thread_master *master); void isis_vrf_link(struct isis *isis, struct vrf *vrf); void isis_vrf_unlink(struct isis *isis, struct vrf *vrf); -void isis_global_instance_create(const char *vrf_name); struct isis *isis_lookup_by_vrfid(vrf_id_t vrf_id); struct isis *isis_lookup_by_vrfname(const char *vrfname); struct isis *isis_lookup_by_sysid(const uint8_t *sysid); From c733548963447f4383866f66117fd5e302d53baa Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 4 Oct 2021 09:28:36 -0400 Subject: [PATCH 043/188] ripngd: Ensure better `struct thread *` semantics 1) Remove `struct thread *` pointers that are never used 2) Do not explicitly set the thread pointer to NULL. FRR should only ever use the appropriate THREAD_ON/THREAD_OFF semantics. This is espacially true for the functions we end up calling the thread for. Signed-off-by: Donald Sharp --- ripngd/ripng_interface.c | 1 - ripngd/ripngd.c | 11 ----------- ripngd/ripngd.h | 3 --- 3 files changed, 15 deletions(-) diff --git a/ripngd/ripng_interface.c b/ripngd/ripng_interface.c index f374fcb83901..7b5e7604d273 100644 --- a/ripngd/ripng_interface.c +++ b/ripngd/ripng_interface.c @@ -618,7 +618,6 @@ static int ripng_interface_wakeup(struct thread *t) ifp = THREAD_ARG(t); ri = ifp->info; - ri->t_wakeup = NULL; /* Join to multicast group. */ if (ripng_multicast_join(ifp, ri->ripng->sock) < 0) { diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c index 4f5c8e77609d..86abf1eead7e 100644 --- a/ripngd/ripngd.c +++ b/ripngd/ripngd.c @@ -429,7 +429,6 @@ static int ripng_garbage_collect(struct thread *t) struct agg_node *rp; rinfo = THREAD_ARG(t); - rinfo->t_garbage_collect = NULL; /* Off timeout timer. */ RIPNG_TIMER_OFF(rinfo->t_timeout); @@ -1320,7 +1319,6 @@ static int ripng_read(struct thread *thread) /* Fetch thread data and set read pointer to empty for event managing. `sock' sould be same as ripng->sock. */ sock = THREAD_FD(thread); - ripng->t_read = NULL; /* Add myself to the next event. */ ripng_event(ripng, RIPNG_READ, sock); @@ -1418,9 +1416,6 @@ static int ripng_update(struct thread *t) struct interface *ifp; struct ripng_interface *ri; - /* Clear update timer thread. */ - ripng->t_update = NULL; - /* Logging update event. */ if (IS_RIPNG_DEBUG_EVENT) zlog_debug("RIPng update timer expired!"); @@ -1469,8 +1464,6 @@ static int ripng_triggered_interval(struct thread *t) { struct ripng *ripng = THREAD_ARG(t); - ripng->t_triggered_interval = NULL; - if (ripng->trigger) { ripng->trigger = 0; ripng_triggered_update(t); @@ -1486,8 +1479,6 @@ int ripng_triggered_update(struct thread *t) struct ripng_interface *ri; int interval; - ripng->t_triggered_update = NULL; - /* Cancel interval timer. */ thread_cancel(&ripng->t_triggered_interval); ripng->trigger = 0; @@ -1525,7 +1516,6 @@ int ripng_triggered_update(struct thread *t) update is triggered when the timer expires. */ interval = (frr_weak_random() % 5) + 1; - ripng->t_triggered_interval = NULL; thread_add_timer(master, ripng_triggered_interval, ripng, interval, &ripng->t_triggered_interval); @@ -1942,7 +1932,6 @@ void ripng_event(struct ripng *ripng, enum ripng_event event, int sock) /* Update timer jitter. */ jitter = ripng_update_jitter(ripng->update_time); - ripng->t_update = NULL; thread_add_timer(master, ripng_update, ripng, sock ? 2 : ripng->update_time + jitter, &ripng->t_update); diff --git a/ripngd/ripngd.h b/ripngd/ripngd.h index 12e5a6d4ac2e..6bf687b02a6d 100644 --- a/ripngd/ripngd.h +++ b/ripngd/ripngd.h @@ -137,10 +137,7 @@ struct ripng { /* RIPng threads. */ struct thread *t_read; - struct thread *t_write; struct thread *t_update; - struct thread *t_garbage; - struct thread *t_zebra; /* Triggered update hack. */ int trigger; From 64da2e8ecd842759511847a990274616dc05aade Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 4 Oct 2021 09:36:27 -0400 Subject: [PATCH 044/188] ripd: Ensure better `struct thread *` semantics Do not explicitly set the thread pointer to NULL. FRR should only ever use the appropriate THREAD_ON/THREAD_OFF semantics. This is espacially true for the functions we end up calling the thread for. Signed-off-by: Donald Sharp --- ripd/rip_interface.c | 1 - ripd/rip_peer.c | 1 - ripd/ripd.c | 12 ------------ 3 files changed, 14 deletions(-) diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c index a2c86e3b2280..2eb7bb6da1e6 100644 --- a/ripd/rip_interface.c +++ b/ripd/rip_interface.c @@ -805,7 +805,6 @@ static int rip_interface_wakeup(struct thread *t) ifp = THREAD_ARG(t); ri = ifp->info; - ri->t_wakeup = NULL; /* Join to multicast group. */ if (rip_multicast_join(ifp, ri->rip->sock) < 0) { diff --git a/ripd/rip_peer.c b/ripd/rip_peer.c index 63493e2539c3..12c4edd43611 100644 --- a/ripd/rip_peer.c +++ b/ripd/rip_peer.c @@ -95,7 +95,6 @@ static struct rip_peer *rip_peer_get(struct rip *rip, struct in_addr *addr) } /* Update timeout thread. */ - peer->t_timeout = NULL; thread_add_timer(master, rip_peer_timeout, peer, RIP_PEER_TIMER_DEFAULT, &peer->t_timeout); diff --git a/ripd/ripd.c b/ripd/ripd.c index 84fb67956e63..145b4de0a0d1 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -142,7 +142,6 @@ static int rip_garbage_collect(struct thread *t) struct route_node *rp; rinfo = THREAD_ARG(t); - rinfo->t_garbage_collect = NULL; /* Off timeout timer. */ RIP_TIMER_OFF(rinfo->t_timeout); @@ -1744,7 +1743,6 @@ static int rip_read(struct thread *t) /* Fetch socket then register myself. */ sock = THREAD_FD(t); - rip->t_read = NULL; /* Add myself to tne next event */ rip_event(rip, RIP_READ, sock); @@ -2545,9 +2543,6 @@ static int rip_update(struct thread *t) { struct rip *rip = THREAD_ARG(t); - /* Clear timer pointer. */ - rip->t_update = NULL; - if (IS_RIP_DEBUG_EVENT) zlog_debug("update timer fire!"); @@ -2588,8 +2583,6 @@ static int rip_triggered_interval(struct thread *t) { struct rip *rip = THREAD_ARG(t); - rip->t_triggered_interval = NULL; - if (rip->trigger) { rip->trigger = 0; rip_triggered_update(t); @@ -2603,9 +2596,6 @@ static int rip_triggered_update(struct thread *t) struct rip *rip = THREAD_ARG(t); int interval; - /* Clear thred pointer. */ - rip->t_triggered_update = NULL; - /* Cancel interval timer. */ RIP_TIMER_OFF(rip->t_triggered_interval); rip->trigger = 0; @@ -2628,7 +2618,6 @@ static int rip_triggered_update(struct thread *t) update is triggered when the timer expires. */ interval = (frr_weak_random() % 5) + 1; - rip->t_triggered_interval = NULL; thread_add_timer(master, rip_triggered_interval, rip, interval, &rip->t_triggered_interval); @@ -2834,7 +2823,6 @@ void rip_event(struct rip *rip, enum rip_event event, int sock) switch (event) { case RIP_READ: - rip->t_read = NULL; thread_add_read(master, rip_read, rip, sock, &rip->t_read); break; case RIP_UPDATE_EVENT: From eb946ef5052e7aaddc1975f7a8a287d439e0ee29 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 4 Oct 2021 09:47:29 -0400 Subject: [PATCH 045/188] eigrpd: Ensure better `struct thread *` semantics 1) Do not explicitly set the thread pointer to NULL. FRR should only ever use the appropriate THREAD_ON/THREAD_OFF semantics. This is espacially true for the functions we end up calling the thread for. 2) Fix mixup of `struct eigrp_interface` and `struct eigrp` usage of the same thread pointer. Signed-off-by: Donald Sharp --- eigrpd/eigrp_filter.c | 4 +--- eigrpd/eigrp_hello.c | 2 -- eigrpd/eigrp_interface.c | 2 +- eigrpd/eigrp_packet.c | 6 ------ eigrpd/eigrp_update.c | 4 ---- eigrpd/eigrpd.c | 1 - 6 files changed, 2 insertions(+), 17 deletions(-) diff --git a/eigrpd/eigrp_filter.c b/eigrpd/eigrp_filter.c index 8f80b78d200f..bb0cf51bd8f3 100644 --- a/eigrpd/eigrp_filter.c +++ b/eigrpd/eigrp_filter.c @@ -203,9 +203,8 @@ void eigrp_distribute_update(struct distribute_ctx *ctx, /* Cancel GR scheduled */ thread_cancel(&(ei->t_distribute)); /* schedule Graceful restart for interface in 10sec */ - e->t_distribute = NULL; thread_add_timer(master, eigrp_distribute_timer_interface, ei, 10, - &e->t_distribute); + &ei->t_distribute); } /* @@ -263,7 +262,6 @@ int eigrp_distribute_timer_process(struct thread *thread) struct eigrp *eigrp; eigrp = THREAD_ARG(thread); - eigrp->t_distribute = NULL; /* execute GR for whole process */ eigrp_update_send_process_GR(eigrp, EIGRP_GR_FILTER, NULL); diff --git a/eigrpd/eigrp_hello.c b/eigrpd/eigrp_hello.c index e3680b31a33f..2ff8fc5f39f1 100644 --- a/eigrpd/eigrp_hello.c +++ b/eigrpd/eigrp_hello.c @@ -86,7 +86,6 @@ int eigrp_hello_timer(struct thread *thread) struct eigrp_interface *ei; ei = THREAD_ARG(thread); - ei->t_hello = NULL; if (IS_DEBUG_EIGRP(0, TIMERS)) zlog_debug("Start Hello Timer (%s) Expire [%u]", IF_NAME(ei), @@ -96,7 +95,6 @@ int eigrp_hello_timer(struct thread *thread) eigrp_hello_send(ei, EIGRP_HELLO_NORMAL, NULL); /* Hello timer set. */ - ei->t_hello = NULL; thread_add_timer(master, eigrp_hello_timer, ei, ei->params.v_hello, &ei->t_hello); diff --git a/eigrpd/eigrp_interface.c b/eigrpd/eigrp_interface.c index 02e943043f19..28987b4af65e 100644 --- a/eigrpd/eigrp_interface.c +++ b/eigrpd/eigrp_interface.c @@ -265,7 +265,7 @@ int eigrp_if_up(struct eigrp_interface *ei) /* Set multicast memberships appropriately for new state. */ eigrp_if_set_multicast(ei); - thread_add_event(master, eigrp_hello_timer, ei, (1), NULL); + thread_add_event(master, eigrp_hello_timer, ei, (1), &ei->t_hello); /*Prepare metrics*/ metric.bandwidth = eigrp_bandwidth_to_scaled(ei->params.bandwidth); diff --git a/eigrpd/eigrp_packet.c b/eigrpd/eigrp_packet.c index 39e384c121f5..529d94567de9 100644 --- a/eigrpd/eigrp_packet.c +++ b/eigrpd/eigrp_packet.c @@ -340,8 +340,6 @@ int eigrp_write(struct thread *thread) #endif /* WANT_EIGRP_WRITE_FRAGMENT */ #define EIGRP_WRITE_IPHL_SHIFT 2 - eigrp->t_write = NULL; - node = listhead(eigrp->oi_write_q); assert(node); ei = listgetdata(node); @@ -470,7 +468,6 @@ int eigrp_write(struct thread *thread) /* If packets still remain in queue, call write thread. */ if (!list_isempty(eigrp->oi_write_q)) { - eigrp->t_write = NULL; thread_add_write(master, eigrp_write, eigrp, eigrp->fd, &eigrp->t_write); } @@ -497,7 +494,6 @@ int eigrp_read(struct thread *thread) eigrp = THREAD_ARG(thread); /* prepare for next packet. */ - eigrp->t_read = NULL; thread_add_read(master, eigrp_read, eigrp, eigrp->fd, &eigrp->t_read); stream_reset(eigrp->ibuf); @@ -1013,7 +1009,6 @@ int eigrp_unack_packet_retrans(struct thread *thread) return eigrp_retrans_count_exceeded(ep, nbr); /*Start retransmission timer*/ - ep->t_retrans_timer = NULL; thread_add_timer(master, eigrp_unack_packet_retrans, nbr, EIGRP_PACKET_RETRANS_TIME, &ep->t_retrans_timer); @@ -1049,7 +1044,6 @@ int eigrp_unack_multicast_packet_retrans(struct thread *thread) return eigrp_retrans_count_exceeded(ep, nbr); /*Start retransmission timer*/ - ep->t_retrans_timer = NULL; thread_add_timer(master, eigrp_unack_multicast_packet_retrans, nbr, EIGRP_PACKET_RETRANS_TIME, &ep->t_retrans_timer); diff --git a/eigrpd/eigrp_update.c b/eigrpd/eigrp_update.c index 0dc509706c91..8a9eea8a794d 100644 --- a/eigrpd/eigrp_update.c +++ b/eigrpd/eigrp_update.c @@ -917,12 +917,10 @@ int eigrp_update_send_GR_thread(struct thread *thread) /* get argument from thread */ nbr = THREAD_ARG(thread); /* remove this thread pointer */ - nbr->t_nbr_send_gr = NULL; /* if there is packet waiting in queue, * schedule this thread again with small delay */ if (nbr->retrans_queue->count > 0) { - nbr->t_nbr_send_gr = NULL; thread_add_timer_msec(master, eigrp_update_send_GR_thread, nbr, 10, &nbr->t_nbr_send_gr); return 0; @@ -934,7 +932,6 @@ int eigrp_update_send_GR_thread(struct thread *thread) /* if it wasn't last chunk, schedule this thread again */ if (nbr->nbr_gr_packet_type != EIGRP_PACKET_PART_LAST) { thread_execute(master, eigrp_update_send_GR_thread, nbr, 0); - nbr->t_nbr_send_gr = NULL; } return 0; @@ -1003,7 +1000,6 @@ void eigrp_update_send_GR(struct eigrp_neighbor *nbr, enum GR_type gr_type, nbr->nbr_gr_packet_type = EIGRP_PACKET_PART_FIRST; /* execute packet sending in thread */ thread_execute(master, eigrp_update_send_GR_thread, nbr, 0); - nbr->t_nbr_send_gr = NULL; } /** diff --git a/eigrpd/eigrpd.c b/eigrpd/eigrpd.c index 103015490783..84d4f6aeeb01 100644 --- a/eigrpd/eigrpd.c +++ b/eigrpd/eigrpd.c @@ -171,7 +171,6 @@ static struct eigrp *eigrp_new(uint16_t as, vrf_id_t vrf_id) eigrp->ibuf = stream_new(EIGRP_PACKET_MAX_LEN + 1); - eigrp->t_read = NULL; thread_add_read(master, eigrp_read, eigrp, eigrp->fd, &eigrp->t_read); eigrp->oi_write_q = list_new(); From a33842f08dbbb7bfdd5eab2439a8d202e70f39ff Mon Sep 17 00:00:00 2001 From: Donatas Abraitis Date: Mon, 4 Oct 2021 17:49:06 +0300 Subject: [PATCH 046/188] bgpd: Don't set NULL for struct thread at bgp_dump_interval_func() NULL is already handled by thread_fetch(). Signed-off-by: Donatas Abraitis --- bgpd/bgp_dump.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/bgpd/bgp_dump.c b/bgpd/bgp_dump.c index 299ee305beaf..2f0b87aa3a4e 100644 --- a/bgpd/bgp_dump.c +++ b/bgpd/bgp_dump.c @@ -165,13 +165,11 @@ static int bgp_dump_interval_add(struct bgp_dump *bgp_dump, int interval) interval = interval - secs_into_day % interval; /* always > 0 */ } - bgp_dump->t_interval = NULL; thread_add_timer(bm->master, bgp_dump_interval_func, bgp_dump, interval, &bgp_dump->t_interval); } else { /* One-off dump: execute immediately, don't affect any scheduled * dumps */ - bgp_dump->t_interval = NULL; thread_add_event(bm->master, bgp_dump_interval_func, bgp_dump, 0, &bgp_dump->t_interval); } @@ -453,7 +451,6 @@ static int bgp_dump_interval_func(struct thread *t) { struct bgp_dump *bgp_dump; bgp_dump = THREAD_ARG(t); - bgp_dump->t_interval = NULL; /* Reschedule dump even if file couldn't be opened this time... */ if (bgp_dump_open_file(bgp_dump) != NULL) { From fc3f4adbc6bd0ecd391906930cf10c00c61ae695 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 4 Oct 2021 08:37:16 -0400 Subject: [PATCH 047/188] ospf6d: Ensure expire thread is properly stopped The lsa->expire thread is for keeping track of when we are expecting to expire(remove/delete) a lsa. There are situations where we just decide to straight up delete the lsa, but we are not ensuring that the lsa is not already setup for expiration. In that case just stop the expiry thread and do the deletion. Additionally there was a case where ospf6d was just dropping the fact that a thread was already scheduled for expiration. In that case we should just setup the timer again and it will reset it appropriately. Fixes: #9721 Signed-off-by: Donald Sharp --- ospf6d/ospf6_flood.c | 1 - ospf6d/ospf6_nssa.c | 16 ++++------------ 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/ospf6d/ospf6_flood.c b/ospf6d/ospf6_flood.c index 186eac35a505..3a242575cd71 100644 --- a/ospf6d/ospf6_flood.c +++ b/ospf6d/ospf6_flood.c @@ -288,7 +288,6 @@ void ospf6_install_lsa(struct ospf6_lsa *lsa) monotime(&now); if (!OSPF6_LSA_IS_MAXAGE(lsa)) { - lsa->expire = NULL; thread_add_timer(master, ospf6_lsa_expire, lsa, OSPF_LSA_MAXAGE + lsa->birth.tv_sec - now.tv_sec, diff --git a/ospf6d/ospf6_nssa.c b/ospf6d/ospf6_nssa.c index 2339d339f7db..809768fb5ca9 100644 --- a/ospf6d/ospf6_nssa.c +++ b/ospf6d/ospf6_nssa.c @@ -304,24 +304,16 @@ void ospf6_abr_remove_unapproved_summaries(struct ospf6 *ospf6) type = htons(OSPF6_LSTYPE_INTER_ROUTER); for (ALL_LSDB_TYPED_ADVRTR(area->lsdb, type, ospf6->router_id, lsa)) { - if (CHECK_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED)) { - lsa->header->age = htons(OSPF_LSA_MAXAGE); - THREAD_OFF(lsa->refresh); - thread_execute(master, ospf6_lsa_expire, lsa, - 0); - } + if (CHECK_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED)) + ospf6_lsa_premature_aging(lsa); } /* Inter area prefix LSA */ type = htons(OSPF6_LSTYPE_INTER_PREFIX); for (ALL_LSDB_TYPED_ADVRTR(area->lsdb, type, ospf6->router_id, lsa)) { - if (CHECK_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED)) { - lsa->header->age = htons(OSPF_LSA_MAXAGE); - THREAD_OFF(lsa->refresh); - thread_execute(master, ospf6_lsa_expire, lsa, - 0); - } + if (CHECK_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED)) + ospf6_lsa_premature_aging(lsa); } } From 510404d9f351741449ae81b1102127b6c465e471 Mon Sep 17 00:00:00 2001 From: Donatas Abraitis Date: Mon, 4 Oct 2021 19:23:55 +0300 Subject: [PATCH 048/188] zebra: Do not explicitly set the thread pointer to NULL FRR should only ever use the appropriate THREAD_ON/THREAD_OFF semantics. This is espacially true for the functions we end up calling the thread for. Signed-off-by: Donatas Abraitis --- zebra/irdp_main.c | 1 - zebra/irdp_packet.c | 1 - zebra/zebra_netns_notify.c | 1 - 3 files changed, 3 deletions(-) diff --git a/zebra/irdp_main.c b/zebra/irdp_main.c index 66a6bd054527..f141b727194c 100644 --- a/zebra/irdp_main.c +++ b/zebra/irdp_main.c @@ -112,7 +112,6 @@ int irdp_sock_init(void) return ret; }; - t_irdp_raw = NULL; thread_add_read(zrouter.master, irdp_read_raw, NULL, sock, &t_irdp_raw); return sock; diff --git a/zebra/irdp_packet.c b/zebra/irdp_packet.c index 7d67c42a79e9..5601b13a92ad 100644 --- a/zebra/irdp_packet.c +++ b/zebra/irdp_packet.c @@ -233,7 +233,6 @@ int irdp_read_raw(struct thread *r) int ret, ifindex = 0; int irdp_sock = THREAD_FD(r); - t_irdp_raw = NULL; thread_add_read(zrouter.master, irdp_read_raw, NULL, irdp_sock, &t_irdp_raw); diff --git a/zebra/zebra_netns_notify.c b/zebra/zebra_netns_notify.c index 054015846f47..61f97ce6a948 100644 --- a/zebra/zebra_netns_notify.c +++ b/zebra/zebra_netns_notify.c @@ -346,7 +346,6 @@ void zebra_ns_notify_init(void) { int fd_monitor; - zebra_netns_notify_current = NULL; fd_monitor = inotify_init(); if (fd_monitor < 0) { flog_err_sys( From 876968a6104133c9964ecad376175baf463c86ff Mon Sep 17 00:00:00 2001 From: Donatas Abraitis Date: Mon, 4 Oct 2021 19:24:28 +0300 Subject: [PATCH 049/188] bfdd: Do not explicitly set the thread pointer to NULL FRR should only ever use the appropriate THREAD_ON/THREAD_OFF semantics. This is espacially true for the functions we end up calling the thread for. Signed-off-by: Donatas Abraitis --- bfdd/control.c | 1 - 1 file changed, 1 deletion(-) diff --git a/bfdd/control.c b/bfdd/control.c index 4929bf199847..e772aadfc41b 100644 --- a/bfdd/control.c +++ b/bfdd/control.c @@ -167,7 +167,6 @@ int control_accept(struct thread *t) control_new(csock); - bglobal.bg_csockev = NULL; thread_add_read(master, control_accept, NULL, sd, &bglobal.bg_csockev); return 0; From c34d552dd5fe8a6821ec5efee2eb463fe3108424 Mon Sep 17 00:00:00 2001 From: Donatas Abraitis Date: Mon, 4 Oct 2021 19:24:54 +0300 Subject: [PATCH 050/188] isisd: Do not explicitly set the thread pointer to NULL FRR should only ever use the appropriate THREAD_ON/THREAD_OFF semantics. This is espacially true for the functions we end up calling the thread for. Signed-off-by: Donatas Abraitis --- isisd/fabricd.c | 1 - isisd/isis_tx_queue.c | 1 - 2 files changed, 2 deletions(-) diff --git a/isisd/fabricd.c b/isisd/fabricd.c index 20651706d394..0f10a1516a15 100644 --- a/isisd/fabricd.c +++ b/isisd/fabricd.c @@ -413,7 +413,6 @@ static int fabricd_tier_calculation_cb(struct thread *thread) { struct fabricd *f = THREAD_ARG(thread); uint8_t tier = ISIS_TIER_UNDEFINED; - f->tier_calculation_timer = NULL; tier = fabricd_calculate_fabric_tier(f->area); if (tier == ISIS_TIER_UNDEFINED) diff --git a/isisd/isis_tx_queue.c b/isisd/isis_tx_queue.c index c7266152b706..d3da5b9d39ab 100644 --- a/isisd/isis_tx_queue.c +++ b/isisd/isis_tx_queue.c @@ -119,7 +119,6 @@ static int tx_queue_send_event(struct thread *thread) struct isis_tx_queue_entry *e = THREAD_ARG(thread); struct isis_tx_queue *queue = e->queue; - e->retry = NULL; thread_add_timer(master, tx_queue_send_event, e, 5, &e->retry); if (e->is_retry) From dc4a902689e46717e2f7c34d3546e7b5b78cb3d1 Mon Sep 17 00:00:00 2001 From: Donatas Abraitis Date: Mon, 4 Oct 2021 19:25:18 +0300 Subject: [PATCH 051/188] ldpd: Do not explicitly set the thread pointer to NULL FRR should only ever use the appropriate THREAD_ON/THREAD_OFF semantics. This is espacially true for the functions we end up calling the thread for. Signed-off-by: Donatas Abraitis --- ldpd/accept.c | 4 ---- ldpd/interface.c | 1 - ldpd/lde.c | 2 -- ldpd/lde_lib.c | 1 - ldpd/ldpd.c | 4 ---- ldpd/ldpe.c | 6 ------ ldpd/packet.c | 3 --- 7 files changed, 21 deletions(-) diff --git a/ldpd/accept.c b/ldpd/accept.c index 9bba0f5ddd13..e8d3976ee9af 100644 --- a/ldpd/accept.c +++ b/ldpd/accept.c @@ -58,7 +58,6 @@ accept_add(int fd, int (*cb)(struct thread *), void *arg) av->arg = arg; LIST_INSERT_HEAD(&accept_queue.queue, av, entry); - av->ev = NULL; thread_add_read(master, accept_cb, av, av->fd, &av->ev); log_debug("%s: accepting on fd %d", __func__, fd); @@ -86,7 +85,6 @@ accept_pause(void) { log_debug(__func__); accept_unarm(); - accept_queue.evt = NULL; thread_add_timer(master, accept_timeout, NULL, 1, &accept_queue.evt); } @@ -105,7 +103,6 @@ accept_arm(void) { struct accept_ev *av; LIST_FOREACH(av, &accept_queue.queue, entry) { - av->ev = NULL; thread_add_read(master, accept_cb, av, av->fd, &av->ev); } } @@ -122,7 +119,6 @@ static int accept_cb(struct thread *thread) { struct accept_ev *av = THREAD_ARG(thread); - av->ev = NULL; thread_add_read(master, accept_cb, av, av->fd, &av->ev); av->accept_cb(thread); diff --git a/ldpd/interface.c b/ldpd/interface.c index 3e9f2fa991b0..5e04eab1b354 100644 --- a/ldpd/interface.c +++ b/ldpd/interface.c @@ -471,7 +471,6 @@ static void if_start_hello_timer(struct iface_af *ia) { thread_cancel(&ia->hello_timer); - ia->hello_timer = NULL; thread_add_timer(master, if_hello_timer, ia, if_get_hello_interval(ia), &ia->hello_timer); } diff --git a/ldpd/lde.c b/ldpd/lde.c index 2d35d097a1cd..babadc461fad 100644 --- a/ldpd/lde.c +++ b/ldpd/lde.c @@ -145,7 +145,6 @@ lde(void) fatal(NULL); imsg_init(&iev_main->ibuf, LDPD_FD_ASYNC); iev_main->handler_read = lde_dispatch_parent; - iev_main->ev_read = NULL; thread_add_read(master, iev_main->handler_read, iev_main, iev_main->ibuf.fd, &iev_main->ev_read); iev_main->handler_write = ldp_write_handler; @@ -555,7 +554,6 @@ lde_dispatch_parent(struct thread *thread) fatal(NULL); imsg_init(&iev_ldpe->ibuf, fd); iev_ldpe->handler_read = lde_dispatch_imsg; - iev_ldpe->ev_read = NULL; thread_add_read(master, iev_ldpe->handler_read, iev_ldpe, iev_ldpe->ibuf.fd, &iev_ldpe->ev_read); iev_ldpe->handler_write = ldp_write_handler; diff --git a/ldpd/lde_lib.c b/ldpd/lde_lib.c index 0f91f49920ad..33bb6c0fc73b 100644 --- a/ldpd/lde_lib.c +++ b/ldpd/lde_lib.c @@ -1072,7 +1072,6 @@ void lde_gc_start_timer(void) { thread_cancel(&gc_timer); - gc_timer = NULL; thread_add_timer(master, lde_gc_timer, NULL, LDE_GC_INTERVAL, &gc_timer); } diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c index e24eba7cd438..9d80bed77f81 100644 --- a/ldpd/ldpd.c +++ b/ldpd/ldpd.c @@ -403,28 +403,24 @@ main(int argc, char *argv[]) fatal(NULL); imsg_init(&iev_ldpe->ibuf, pipe_parent2ldpe[0]); iev_ldpe->handler_read = main_dispatch_ldpe; - iev_ldpe->ev_read = NULL; thread_add_read(master, iev_ldpe->handler_read, iev_ldpe, iev_ldpe->ibuf.fd, &iev_ldpe->ev_read); iev_ldpe->handler_write = ldp_write_handler; imsg_init(&iev_ldpe_sync->ibuf, pipe_parent2ldpe_sync[0]); iev_ldpe_sync->handler_read = main_dispatch_ldpe; - iev_ldpe_sync->ev_read = NULL; thread_add_read(master, iev_ldpe_sync->handler_read, iev_ldpe_sync, iev_ldpe_sync->ibuf.fd, &iev_ldpe_sync->ev_read); iev_ldpe_sync->handler_write = ldp_write_handler; imsg_init(&iev_lde->ibuf, pipe_parent2lde[0]); iev_lde->handler_read = main_dispatch_lde; - iev_lde->ev_read = NULL; thread_add_read(master, iev_lde->handler_read, iev_lde, iev_lde->ibuf.fd, &iev_lde->ev_read); iev_lde->handler_write = ldp_write_handler; imsg_init(&iev_lde_sync->ibuf, pipe_parent2lde_sync[0]); iev_lde_sync->handler_read = main_dispatch_lde; - iev_lde_sync->ev_read = NULL; thread_add_read(master, iev_lde_sync->handler_read, iev_lde_sync, iev_lde_sync->ibuf.fd, &iev_lde_sync->ev_read); iev_lde_sync->handler_write = ldp_write_handler; diff --git a/ldpd/ldpe.c b/ldpd/ldpe.c index 428d2ab7b49a..fff7ee7c67d6 100644 --- a/ldpd/ldpe.c +++ b/ldpd/ldpe.c @@ -122,7 +122,6 @@ ldpe(void) fatal(NULL); imsg_init(&iev_main->ibuf, LDPD_FD_ASYNC); iev_main->handler_read = ldpe_dispatch_main; - iev_main->ev_read = NULL; thread_add_read(master, iev_main->handler_read, iev_main, iev_main->ibuf.fd, &iev_main->ev_read); iev_main->handler_write = ldp_write_handler; @@ -149,7 +148,6 @@ ldpe_init(struct ldpd_init *init) /* This socket must be open before dropping privileges. */ global.pfkeysock = pfkey_init(); if (sysdep.no_pfkey == 0) { - pfkey_ev = NULL; thread_add_read(master, ldpe_dispatch_pfkey, NULL, global.pfkeysock, &pfkey_ev); } @@ -377,7 +375,6 @@ ldpe_dispatch_main(struct thread *thread) fatal(NULL); imsg_init(&iev_lde->ibuf, fd); iev_lde->handler_read = ldpe_dispatch_lde; - iev_lde->ev_read = NULL; thread_add_read(master, iev_lde->handler_read, iev_lde, iev_lde->ibuf.fd, &iev_lde->ev_read); iev_lde->handler_write = ldp_write_handler; @@ -784,7 +781,6 @@ ldpe_dispatch_pfkey(struct thread *thread) { int fd = THREAD_FD(thread); - pfkey_ev = NULL; thread_add_read(master, ldpe_dispatch_pfkey, NULL, global.pfkeysock, &pfkey_ev); @@ -805,13 +801,11 @@ ldpe_setup_sockets(int af, int disc_socket, int edisc_socket, /* discovery socket */ af_global->ldp_disc_socket = disc_socket; - af_global->disc_ev = NULL; thread_add_read(master, disc_recv_packet, &af_global->disc_ev, af_global->ldp_disc_socket, &af_global->disc_ev); /* extended discovery socket */ af_global->ldp_edisc_socket = edisc_socket; - af_global->edisc_ev = NULL; thread_add_read(master, disc_recv_packet, &af_global->edisc_ev, af_global->ldp_edisc_socket, &af_global->edisc_ev); diff --git a/ldpd/packet.c b/ldpd/packet.c index 8735faf3dd1a..56af16d28021 100644 --- a/ldpd/packet.c +++ b/ldpd/packet.c @@ -141,7 +141,6 @@ disc_recv_packet(struct thread *thread) struct in_addr lsr_id; /* reschedule read */ - *threadp = NULL; thread_add_read(master, disc_recv_packet, threadp, fd, threadp); /* setup buffer */ @@ -425,7 +424,6 @@ session_read(struct thread *thread) uint16_t pdu_len, msg_len, msg_size, max_pdu_len; int ret; - tcp->rev = NULL; thread_add_read(master, session_read, nbr, fd, &tcp->rev); if ((n = read(fd, tcp->rbuf->buf + tcp->rbuf->wpos, @@ -745,7 +743,6 @@ tcp_new(int fd, struct nbr *nbr) if ((tcp->rbuf = calloc(1, sizeof(struct ibuf_read))) == NULL) fatal(__func__); - tcp->rev = NULL; thread_add_read(master, session_read, nbr, tcp->fd, &tcp->rev); tcp->nbr = nbr; } From 56fb2134937086781e73de7490296b01414e0fe9 Mon Sep 17 00:00:00 2001 From: Donatas Abraitis Date: Mon, 4 Oct 2021 19:25:43 +0300 Subject: [PATCH 052/188] nhrpd: Do not explicitly set the thread pointer to NULL FRR should only ever use the appropriate THREAD_ON/THREAD_OFF semantics. This is espacially true for the functions we end up calling the thread for. Signed-off-by: Donatas Abraitis --- nhrpd/netlink_arp.c | 1 - nhrpd/nhrp_event.c | 3 --- nhrpd/nhrp_multicast.c | 1 - nhrpd/nhrp_nhs.c | 3 --- nhrpd/nhrp_peer.c | 1 - nhrpd/nhrp_shortcut.c | 1 - nhrpd/vici.c | 3 --- 7 files changed, 13 deletions(-) diff --git a/nhrpd/netlink_arp.c b/nhrpd/netlink_arp.c index 5fcb31188896..0a618056d5ed 100644 --- a/nhrpd/netlink_arp.c +++ b/nhrpd/netlink_arp.c @@ -107,7 +107,6 @@ static int netlink_log_recv(struct thread *t) struct zbuf payload, zb; struct nlmsghdr *n; - netlink_log_thread = NULL; zbuf_init(&zb, buf, sizeof(buf), 0); while (zbuf_recv(&zb, fd) > 0) { diff --git a/nhrpd/nhrp_event.c b/nhrpd/nhrp_event.c index f784ef22d62f..206b2caccf4d 100644 --- a/nhrpd/nhrp_event.c +++ b/nhrpd/nhrp_event.c @@ -84,7 +84,6 @@ static int evmgr_read(struct thread *t) struct zbuf *ibuf = &evmgr->ibuf; struct zbuf msg; - evmgr->t_read = NULL; if (zbuf_read(ibuf, evmgr->fd, (size_t)-1) < 0) { evmgr_connection_error(evmgr); return 0; @@ -103,7 +102,6 @@ static int evmgr_write(struct thread *t) struct event_manager *evmgr = THREAD_ARG(t); int r; - evmgr->t_write = NULL; r = zbufq_write(&evmgr->obuf, evmgr->fd); if (r > 0) { thread_add_write(master, evmgr_write, evmgr, evmgr->fd, @@ -193,7 +191,6 @@ static int evmgr_reconnect(struct thread *t) struct event_manager *evmgr = THREAD_ARG(t); int fd; - evmgr->t_reconnect = NULL; if (evmgr->fd >= 0 || !nhrp_event_socket_path) return 0; diff --git a/nhrpd/nhrp_multicast.c b/nhrpd/nhrp_multicast.c index b78afda2c40b..339b6dfabe27 100644 --- a/nhrpd/nhrp_multicast.c +++ b/nhrpd/nhrp_multicast.c @@ -149,7 +149,6 @@ static int netlink_mcast_log_recv(struct thread *t) struct zbuf payload, zb; struct nlmsghdr *n; - netlink_mcast_log_thread = NULL; zbuf_init(&zb, buf, sizeof(buf), 0); while (zbuf_recv(&zb, fd) > 0) { diff --git a/nhrpd/nhrp_nhs.c b/nhrpd/nhrp_nhs.c index 9dfaf073d85c..5179f15ebf85 100644 --- a/nhrpd/nhrp_nhs.c +++ b/nhrpd/nhrp_nhs.c @@ -112,7 +112,6 @@ static int nhrp_reg_timeout(struct thread *t) struct nhrp_registration *r = THREAD_ARG(t); struct nhrp_cache *c; - r->t_register = NULL; if (r->timeout >= 16 && sockunion_family(&r->proto_addr) != AF_UNSPEC) { nhrp_reqid_free(&nhrp_packet_reqid, &r->reqid); @@ -176,7 +175,6 @@ static int nhrp_reg_send_req(struct thread *t) struct nhrp_extension_header *ext; struct nhrp_cie_header *cie; - r->t_register = NULL; if (!nhrp_peer_check(r->peer, 2)) { debugf(NHRP_DEBUG_COMMON, "NHS: Waiting link for %pSU", &r->peer->vc->remote.nbma); @@ -281,7 +279,6 @@ static void nhrp_nhs_resolve_cb(struct resolver_query *q, const char *errstr, struct nhrp_registration *reg, *regn; int i; - nhs->t_resolve = NULL; if (n < 0) { /* Failed, retry in a moment */ thread_add_timer(master, nhrp_nhs_resolve, nhs, 5, diff --git a/nhrpd/nhrp_peer.c b/nhrpd/nhrp_peer.c index 5a7da703acc7..030f4c0ff335 100644 --- a/nhrpd/nhrp_peer.c +++ b/nhrpd/nhrp_peer.c @@ -265,7 +265,6 @@ static int nhrp_peer_request_timeout(struct thread *t) struct interface *ifp = p->ifp; struct nhrp_interface *nifp = ifp->info; - p->t_fallback = NULL; if (p->online) return 0; diff --git a/nhrpd/nhrp_shortcut.c b/nhrpd/nhrp_shortcut.c index 0905ceb72a4b..244273cd5891 100644 --- a/nhrpd/nhrp_shortcut.c +++ b/nhrpd/nhrp_shortcut.c @@ -39,7 +39,6 @@ static int nhrp_shortcut_do_expire(struct thread *t) { struct nhrp_shortcut *s = THREAD_ARG(t); - s->t_timer = NULL; thread_add_timer(master, nhrp_shortcut_do_purge, s, s->holding_time / 3, &s->t_timer); s->expiring = 1; diff --git a/nhrpd/vici.c b/nhrpd/vici.c index c21e01601c14..8fce828663af 100644 --- a/nhrpd/vici.c +++ b/nhrpd/vici.c @@ -361,7 +361,6 @@ static int vici_read(struct thread *t) struct zbuf *ibuf = &vici->ibuf; struct zbuf pktbuf; - vici->t_read = NULL; if (zbuf_read(ibuf, vici->fd, (size_t)-1) < 0) { vici_connection_error(vici); return 0; @@ -392,7 +391,6 @@ static int vici_write(struct thread *t) struct vici_conn *vici = THREAD_ARG(t); int r; - vici->t_write = NULL; r = zbufq_write(&vici->obuf, vici->fd); if (r > 0) { thread_add_write(master, vici_write, vici, vici->fd, @@ -509,7 +507,6 @@ static int vici_reconnect(struct thread *t) int fd; char *file_path; - vici->t_reconnect = NULL; if (vici->fd >= 0) return 0; From f2b64253b8b9fd5029066c5d3b02392f0af1f339 Mon Sep 17 00:00:00 2001 From: Donatas Abraitis Date: Mon, 4 Oct 2021 19:26:01 +0300 Subject: [PATCH 053/188] ospf6d: Do not explicitly set the thread pointer to NULL FRR should only ever use the appropriate THREAD_ON/THREAD_OFF semantics. This is espacially true for the functions we end up calling the thread for. Signed-off-by: Donatas Abraitis --- ospf6d/ospf6_asbr.c | 1 - ospf6d/ospf6_flood.c | 3 --- ospf6d/ospf6_interface.c | 1 - ospf6d/ospf6_lsa.c | 1 - ospf6d/ospf6_message.c | 6 ------ ospf6d/ospf6_neighbor.c | 4 ---- 6 files changed, 16 deletions(-) diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c index df40c608a1ea..3a6078ff0a19 100644 --- a/ospf6d/ospf6_asbr.c +++ b/ospf6d/ospf6_asbr.c @@ -1139,7 +1139,6 @@ void ospf6_asbr_distribute_list_update(struct ospf6 *ospf6, if (IS_OSPF6_DEBUG_ASBR) zlog_debug("%s: trigger redistribute reset thread", __func__); - ospf6->t_distribute_update = NULL; thread_add_timer_msec(master, ospf6_asbr_routemap_update_timer, ospf6, OSPF_MIN_LS_INTERVAL, &ospf6->t_distribute_update); diff --git a/ospf6d/ospf6_flood.c b/ospf6d/ospf6_flood.c index 186eac35a505..6ad2a70f08b1 100644 --- a/ospf6d/ospf6_flood.c +++ b/ospf6d/ospf6_flood.c @@ -288,7 +288,6 @@ void ospf6_install_lsa(struct ospf6_lsa *lsa) monotime(&now); if (!OSPF6_LSA_IS_MAXAGE(lsa)) { - lsa->expire = NULL; thread_add_timer(master, ospf6_lsa_expire, lsa, OSPF_LSA_MAXAGE + lsa->birth.tv_sec - now.tv_sec, @@ -547,7 +546,6 @@ void ospf6_flood_interface(struct ospf6_neighbor *from, struct ospf6_lsa *lsa, /* reschedule retransmissions to all neighbors */ for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) { THREAD_OFF(on->thread_send_lsupdate); - on->thread_send_lsupdate = NULL; thread_add_event(master, ospf6_lsupdate_send_neighbor, on, 0, &on->thread_send_lsupdate); } @@ -1113,7 +1111,6 @@ void ospf6_receive_lsa(struct ospf6_neighbor *from, "Newer instance of the self-originated LSA"); zlog_debug("Schedule reorigination"); } - new->refresh = NULL; thread_add_event(master, ospf6_lsa_refresh, new, 0, &new->refresh); } diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index b63a3c02db3a..a3eb1445f187 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -819,7 +819,6 @@ int interface_up(struct thread *thread) /* Schedule Hello */ if (!CHECK_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE) && !if_is_loopback_or_vrf(oi->interface)) { - oi->thread_send_hello = NULL; thread_add_event(master, ospf6_hello_send, oi, 0, &oi->thread_send_hello); } diff --git a/ospf6d/ospf6_lsa.c b/ospf6d/ospf6_lsa.c index ac07704d2c3e..f406e828e1c1 100644 --- a/ospf6d/ospf6_lsa.c +++ b/ospf6d/ospf6_lsa.c @@ -891,7 +891,6 @@ int ospf6_lsa_refresh(struct thread *thread) new = ospf6_lsa_create(self->header); new->lsdb = old->lsdb; - new->refresh = NULL; thread_add_timer(master, ospf6_lsa_refresh, new, OSPF_LS_REFRESH_TIME, &new->refresh); diff --git a/ospf6d/ospf6_message.c b/ospf6d/ospf6_message.c index 64de9bae4167..56dcbb69cb73 100644 --- a/ospf6d/ospf6_message.c +++ b/ospf6d/ospf6_message.c @@ -775,7 +775,6 @@ static void ospf6_dbdesc_recv_master(struct ospf6_header *oh, && !CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT)) thread_add_event(master, exchange_done, on, 0, NULL); else { - on->thread_send_dbdesc = NULL; thread_add_event(master, ospf6_dbdesc_send_newone, on, 0, &on->thread_send_dbdesc); } @@ -856,7 +855,6 @@ static void ospf6_dbdesc_recv_slave(struct ospf6_header *oh, zlog_debug( "Duplicated dbdesc causes retransmit"); THREAD_OFF(on->thread_send_dbdesc); - on->thread_send_dbdesc = NULL; thread_add_event(master, ospf6_dbdesc_send, on, 0, &on->thread_send_dbdesc); return; @@ -2399,7 +2397,6 @@ int ospf6_lsreq_send(struct thread *thread) /* set next thread */ if (on->request_list->count != 0) { - on->thread_send_lsreq = NULL; thread_add_timer(master, ospf6_lsreq_send, on, on->ospf6_if->rxmt_interval, &on->thread_send_lsreq); @@ -2585,11 +2582,9 @@ int ospf6_lsupdate_send_neighbor(struct thread *thread) ospf6_packet_free(op); if (on->lsupdate_list->count != 0) { - on->thread_send_lsupdate = NULL; thread_add_event(master, ospf6_lsupdate_send_neighbor, on, 0, &on->thread_send_lsupdate); } else if (on->retrans_list->count != 0) { - on->thread_send_lsupdate = NULL; thread_add_timer(master, ospf6_lsupdate_send_neighbor, on, on->ospf6_if->rxmt_interval, &on->thread_send_lsupdate); @@ -2703,7 +2698,6 @@ int ospf6_lsupdate_send_interface(struct thread *thread) ospf6_packet_free(op); if (oi->lsupdate_list->count > 0) { - oi->thread_send_lsupdate = NULL; thread_add_event(master, ospf6_lsupdate_send_interface, oi, 0, &oi->thread_send_lsupdate); } diff --git a/ospf6d/ospf6_neighbor.c b/ospf6d/ospf6_neighbor.c index 35fbd3991cdd..6f2795a56d57 100644 --- a/ospf6d/ospf6_neighbor.c +++ b/ospf6d/ospf6_neighbor.c @@ -273,7 +273,6 @@ int hello_received(struct thread *thread) /* reset Inactivity Timer */ THREAD_OFF(on->inactivity_timer); - on->inactivity_timer = NULL; thread_add_timer(master, inactivity_timer, on, on->ospf6_if->dead_interval, &on->inactivity_timer); @@ -312,7 +311,6 @@ int twoway_received(struct thread *thread) SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT); THREAD_OFF(on->thread_send_dbdesc); - on->thread_send_dbdesc = NULL; thread_add_event(master, ospf6_dbdesc_send, on, 0, &on->thread_send_dbdesc); @@ -438,7 +436,6 @@ void ospf6_check_nbr_loading(struct ospf6_neighbor *on) else if (on->last_ls_req == NULL) { if (on->thread_send_lsreq != NULL) THREAD_OFF(on->thread_send_lsreq); - on->thread_send_lsreq = NULL; thread_add_event(master, ospf6_lsreq_send, on, 0, &on->thread_send_lsreq); } @@ -620,7 +617,6 @@ int inactivity_timer(struct thread *thread) if (IS_OSPF6_DEBUG_NEIGHBOR(EVENT)) zlog_debug("Neighbor Event %s: *InactivityTimer*", on->name); - on->inactivity_timer = NULL; on->drouter = on->prev_drouter = 0; on->bdrouter = on->prev_bdrouter = 0; From bf5335cf3421811cd419d9b40be69d2ad9ed8bde Mon Sep 17 00:00:00 2001 From: Donatas Abraitis Date: Mon, 4 Oct 2021 19:26:20 +0300 Subject: [PATCH 054/188] pimd: Do not explicitly set the thread pointer to NULL FRR should only ever use the appropriate THREAD_ON/THREAD_OFF semantics. This is espacially true for the functions we end up calling the thread for. Signed-off-by: Donatas Abraitis --- pimd/pim_igmp.c | 2 -- pimd/pim_msdp_socket.c | 1 - pimd/pim_pim.c | 1 - 3 files changed, 4 deletions(-) diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index 50de7124d2c4..795c96c83801 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -671,7 +671,6 @@ void pim_igmp_general_query_on(struct igmp_sock *igmp) ifaddr_str, query_interval, startup_mode ? "startup" : "non-startup", igmp->fd); } - igmp->t_igmp_query_timer = NULL; thread_add_timer(router->master, pim_igmp_general_query, igmp, query_interval, &igmp->t_igmp_query_timer); } @@ -1052,7 +1051,6 @@ static void igmp_read_on(struct igmp_sock *igmp) zlog_debug("Scheduling READ event on IGMP socket fd=%d", igmp->fd); } - igmp->t_igmp_read = NULL; thread_add_read(router->master, pim_igmp_read, igmp, igmp->fd, &igmp->t_igmp_read); } diff --git a/pimd/pim_msdp_socket.c b/pimd/pim_msdp_socket.c index 78a8265a1c88..5fff9fca0ed5 100644 --- a/pimd/pim_msdp_socket.c +++ b/pimd/pim_msdp_socket.c @@ -205,7 +205,6 @@ int pim_msdp_sock_listen(struct pim_instance *pim) /* add accept thread */ listener->fd = sock; memcpy(&listener->su, &sin, socklen); - listener->thread = NULL; thread_add_read(pim->msdp.master, pim_msdp_sock_accept, pim, sock, &listener->thread); diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index 8c38cf6c4c38..3df7dc41ce31 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -415,7 +415,6 @@ static void pim_sock_read_on(struct interface *ifp) zlog_debug("Scheduling READ event on PIM socket fd=%d", pim_ifp->pim_sock_fd); } - pim_ifp->t_pim_sock_read = NULL; thread_add_read(router->master, pim_sock_read, ifp, pim_ifp->pim_sock_fd, &pim_ifp->t_pim_sock_read); } From feabd51dae76a1a85913b2d5b9cea95bc720eadc Mon Sep 17 00:00:00 2001 From: Donatas Abraitis Date: Mon, 4 Oct 2021 19:26:39 +0300 Subject: [PATCH 055/188] tests: Do not explicitly set the thread pointer to NULL FRR should only ever use the appropriate THREAD_ON/THREAD_OFF semantics. This is espacially true for the functions we end up calling the thread for. Signed-off-by: Donatas Abraitis --- tests/lib/test_timer_correctness.c | 1 - tests/lib/test_timer_performance.c | 2 -- 2 files changed, 3 deletions(-) diff --git a/tests/lib/test_timer_correctness.c b/tests/lib/test_timer_correctness.c index 416ea3977279..0ae9761b117c 100644 --- a/tests/lib/test_timer_correctness.c +++ b/tests/lib/test_timer_correctness.c @@ -134,7 +134,6 @@ int main(int argc, char **argv) /* Schedule timers to expire in 0..5 seconds */ interval_msec = prng_rand(prng) % 5000; arg = XMALLOC(MTYPE_TMP, TIMESTR_LEN + 1); - timers[i] = NULL; thread_add_timer_msec(master, timer_func, arg, interval_msec, &timers[i]); ret = snprintf(arg, TIMESTR_LEN + 1, "%lld.%06lld", diff --git a/tests/lib/test_timer_performance.c b/tests/lib/test_timer_performance.c index 45b29b92b1ec..23c044c7c1a0 100644 --- a/tests/lib/test_timer_performance.c +++ b/tests/lib/test_timer_performance.c @@ -55,7 +55,6 @@ int main(int argc, char **argv) /* create thread structures so they won't be allocated during the * time measurement */ for (i = 0; i < SCHEDULE_TIMERS; i++) { - timers[i] = NULL; thread_add_timer_msec(master, dummy_func, NULL, 0, &timers[i]); } for (i = 0; i < SCHEDULE_TIMERS; i++) @@ -67,7 +66,6 @@ int main(int argc, char **argv) long interval_msec; interval_msec = prng_rand(prng) % (100 * SCHEDULE_TIMERS); - timers[i] = NULL; thread_add_timer_msec(master, dummy_func, NULL, interval_msec, &timers[i]); } From 62143398ced16e33e693b90a9ec4a7020708e874 Mon Sep 17 00:00:00 2001 From: Donatas Abraitis Date: Mon, 4 Oct 2021 19:26:55 +0300 Subject: [PATCH 056/188] watchfrr: Do not explicitly set the thread pointer to NULL FRR should only ever use the appropriate THREAD_ON/THREAD_OFF semantics. This is espacially true for the functions we end up calling the thread for. Signed-off-by: Donatas Abraitis --- watchfrr/watchfrr.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/watchfrr/watchfrr.c b/watchfrr/watchfrr.c index d0b4be81d482..40749e8fc262 100644 --- a/watchfrr/watchfrr.c +++ b/watchfrr/watchfrr.c @@ -361,7 +361,6 @@ static int restart_kill(struct thread *t_kill) (long)delay.tv_sec, (restart->kills ? SIGKILL : SIGTERM)); kill(-restart->pid, (restart->kills ? SIGKILL : SIGTERM)); restart->kills++; - restart->t_kill = NULL; thread_add_timer(master, restart_kill, restart, gs.restart_timeout, &restart->t_kill); return 0; @@ -495,7 +494,6 @@ static int run_job(struct restart_info *restart, const char *cmdtype, char cmd[strlen(command) + strlen(restart->name) + 1]; snprintf(cmd, sizeof(cmd), command, restart->name); if ((restart->pid = run_background(cmd)) > 0) { - restart->t_kill = NULL; thread_add_timer(master, restart_kill, restart, gs.restart_timeout, &restart->t_kill); restart->what = cmdtype; @@ -833,10 +831,8 @@ static int try_connect(struct daemon *dmn) zlog_debug("%s: connection in progress", dmn->name); dmn->state = DAEMON_CONNECTING; dmn->fd = sock; - dmn->t_write = NULL; thread_add_write(master, check_connect, dmn, dmn->fd, &dmn->t_write); - dmn->t_wakeup = NULL; thread_add_timer(master, wakeup_connect_hanging, dmn, gs.timeout, &dmn->t_wakeup); SET_READ_HANDLER(dmn); @@ -1022,7 +1018,6 @@ static int wakeup_send_echo(struct thread *t_wakeup) daemon_down(dmn, why); } else { gettimeofday(&dmn->echo_sent, NULL); - dmn->t_wakeup = NULL; thread_add_timer(master, wakeup_no_answer, dmn, gs.timeout, &dmn->t_wakeup); } @@ -1269,7 +1264,6 @@ static void watchfrr_init(int argc, char **argv) gs.numdaemons++; gs.numdown++; dmn->fd = -1; - dmn->t_wakeup = NULL; thread_add_timer_msec(master, wakeup_init, dmn, 0, &dmn->t_wakeup); dmn->restart.interval = gs.min_restart_interval; From 83e66fdfd6752fb4e7fd3bb22c9e5b7ede3bfa61 Mon Sep 17 00:00:00 2001 From: Donatas Abraitis Date: Mon, 4 Oct 2021 19:27:27 +0300 Subject: [PATCH 057/188] tools: Add coccinelle script to catch thread to NULL assignments Signed-off-by: Donatas Abraitis --- tools/coccinelle/struct_thread_null.cocci | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 tools/coccinelle/struct_thread_null.cocci diff --git a/tools/coccinelle/struct_thread_null.cocci b/tools/coccinelle/struct_thread_null.cocci new file mode 100644 index 000000000000..4867b4454b2d --- /dev/null +++ b/tools/coccinelle/struct_thread_null.cocci @@ -0,0 +1,9 @@ +@@ +identifier I; +identifier func =~ "thread_add_"; +struct thread *thread; +@@ + +*thread = NULL; +... +func From 0cf0069d31861d575cfa3f84877ce512214b6449 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 4 Oct 2021 16:00:27 -0400 Subject: [PATCH 058/188] zebra: On interface startup note that we are in startup The boolean to notice that we are in startup situations was not being properly set in one spot. Fix. Signed-off-by: Donald Sharp --- zebra/if_netlink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index 28a64407e53e..ce0779e91c60 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -1099,7 +1099,7 @@ int interface_lookup_netlink(struct zebra_ns *zns) if (ret < 0) return ret; ret = netlink_parse_info(netlink_interface, netlink_cmd, &dp_info, 0, - 0); + 1); if (ret < 0) return ret; From 9bfadae860145d64ed7ab6bbfe87c872873cfdbc Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 4 Oct 2021 20:26:38 -0400 Subject: [PATCH 059/188] zebra: Use a bool for startup indications Let's not pass around an int startup when all we are doing is true/falsing it. Signed-off-by: Donald Sharp --- zebra/if_netlink.c | 12 ++++++------ zebra/kernel_netlink.c | 10 +++++----- zebra/kernel_netlink.h | 4 ++-- zebra/rt_netlink.c | 28 ++++++++++++++-------------- zebra/rule_netlink.c | 4 ++-- 5 files changed, 29 insertions(+), 29 deletions(-) diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index ce0779e91c60..15645d024df5 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -1089,7 +1089,7 @@ int interface_lookup_netlink(struct zebra_ns *zns) if (ret < 0) return ret; ret = netlink_parse_info(netlink_interface, netlink_cmd, &dp_info, 0, - 1); + true); if (ret < 0) return ret; @@ -1099,7 +1099,7 @@ int interface_lookup_netlink(struct zebra_ns *zns) if (ret < 0) return ret; ret = netlink_parse_info(netlink_interface, netlink_cmd, &dp_info, 0, - 1); + true); if (ret < 0) return ret; @@ -1128,7 +1128,7 @@ static int interface_addr_lookup_netlink(struct zebra_ns *zns) if (ret < 0) return ret; ret = netlink_parse_info(netlink_interface_addr, netlink_cmd, &dp_info, - 0, 1); + 0, true); if (ret < 0) return ret; @@ -1137,7 +1137,7 @@ static int interface_addr_lookup_netlink(struct zebra_ns *zns) if (ret < 0) return ret; ret = netlink_parse_info(netlink_interface_addr, netlink_cmd, &dp_info, - 0, 1); + 0, true); if (ret < 0) return ret; @@ -1168,7 +1168,7 @@ int kernel_interface_set_master(struct interface *master, nl_attr_put32(&req.n, sizeof(req), IFLA_LINK, slave->ifindex); return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, - 0); + false); } /* Interface address modification. */ @@ -2054,7 +2054,7 @@ int netlink_protodown(struct interface *ifp, bool down) nl_attr_put32(&req.n, sizeof(req), IFLA_LINK, ifp->ifindex); return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, - 0); + false); } /* Interface information read by netlink. */ diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c index 602bdc1dc5ed..86e8f65b5f81 100644 --- a/zebra/kernel_netlink.c +++ b/zebra/kernel_netlink.c @@ -419,7 +419,7 @@ static int kernel_read(struct thread *thread) zebra_dplane_info_from_zns(&dp_info, zns, false); netlink_parse_info(netlink_information_fetch, &zns->netlink, &dp_info, - 5, 0); + 5, false); thread_add_read(zrouter.master, kernel_read, zns, zns->netlink.sock, &zns->t_netlink); @@ -433,7 +433,7 @@ static int kernel_read(struct thread *thread) int kernel_dplane_read(struct zebra_dplane_info *info) { netlink_parse_info(dplane_netlink_information_fetch, &info->nls, info, - 5, 0); + 5, false); return 0; } @@ -933,7 +933,7 @@ static int netlink_parse_error(const struct nlsock *nl, struct nlmsghdr *h, int netlink_parse_info(int (*filter)(struct nlmsghdr *, ns_id_t, int), const struct nlsock *nl, const struct zebra_dplane_info *zns, - int count, int startup) + int count, bool startup) { int status; int ret = 0; @@ -1036,7 +1036,7 @@ int netlink_parse_info(int (*filter)(struct nlmsghdr *, ns_id_t, int), static int netlink_talk_info(int (*filter)(struct nlmsghdr *, ns_id_t, int startup), struct nlmsghdr *n, const struct zebra_dplane_info *dp_info, - int startup) + bool startup) { const struct nlsock *nl; @@ -1067,7 +1067,7 @@ netlink_talk_info(int (*filter)(struct nlmsghdr *, ns_id_t, int startup), */ int netlink_talk(int (*filter)(struct nlmsghdr *, ns_id_t, int startup), struct nlmsghdr *n, struct nlsock *nl, struct zebra_ns *zns, - int startup) + bool startup) { struct zebra_dplane_info dp_info; diff --git a/zebra/kernel_netlink.h b/zebra/kernel_netlink.h index d8e5671b72dd..37c76b9e598d 100644 --- a/zebra/kernel_netlink.h +++ b/zebra/kernel_netlink.h @@ -94,11 +94,11 @@ extern const char *nl_rttype_to_str(uint8_t rttype); extern int netlink_parse_info(int (*filter)(struct nlmsghdr *, ns_id_t, int), const struct nlsock *nl, const struct zebra_dplane_info *dp_info, - int count, int startup); + int count, bool startup); extern int netlink_talk_filter(struct nlmsghdr *h, ns_id_t ns, int startup); extern int netlink_talk(int (*filter)(struct nlmsghdr *, ns_id_t, int startup), struct nlmsghdr *n, struct nlsock *nl, - struct zebra_ns *zns, int startup); + struct zebra_ns *zns, bool startup); extern int netlink_request(struct nlsock *nl, void *req); enum netlink_msg_status { diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index e36f320ad917..488bca06da9a 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -1171,7 +1171,7 @@ int netlink_route_read(struct zebra_ns *zns) if (ret < 0) return ret; ret = netlink_parse_info(netlink_route_change_read_unicast, - &zns->netlink_cmd, &dp_info, 0, 1); + &zns->netlink_cmd, &dp_info, 0, true); if (ret < 0) return ret; @@ -1180,7 +1180,7 @@ int netlink_route_read(struct zebra_ns *zns) if (ret < 0) return ret; ret = netlink_parse_info(netlink_route_change_read_unicast, - &zns->netlink_cmd, &dp_info, 0, 1); + &zns->netlink_cmd, &dp_info, 0, true); if (ret < 0) return ret; @@ -1810,7 +1810,7 @@ static int netlink_neigh_update(int cmd, int ifindex, void *addr, char *lla, nl_attr_put(&req.n, sizeof(req), NDA_LLADDR, lla, llalen); return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, - 0); + false); } static bool nexthop_set_src(const struct nexthop *nexthop, int family, @@ -2268,7 +2268,7 @@ int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *in) nl_attr_put32(&req.n, sizeof(req), RTA_TABLE, actual_table); suc = netlink_talk(netlink_route_change_read_multicast, &req.n, - &zns->netlink_cmd, zns, 0); + &zns->netlink_cmd, zns, false); mroute = NULL; return suc; @@ -3019,7 +3019,7 @@ int netlink_nexthop_read(struct zebra_ns *zns) if (ret < 0) return ret; ret = netlink_parse_info(netlink_nexthop_change, &zns->netlink_cmd, - &dp_info, 0, 1); + &dp_info, 0, true); if (!ret) /* If we succesfully read in nexthop objects, @@ -3427,7 +3427,7 @@ int netlink_macfdb_read(struct zebra_ns *zns) /* We are reading entire table. */ filter_vlan = 0; ret = netlink_parse_info(netlink_macfdb_table, &zns->netlink_cmd, - &dp_info, 0, 1); + &dp_info, 0, true); return ret; } @@ -3461,7 +3461,7 @@ int netlink_macfdb_read_for_bridge(struct zebra_ns *zns, struct interface *ifp, if (ret < 0) return ret; ret = netlink_parse_info(netlink_macfdb_table, &zns->netlink_cmd, - &dp_info, 0, 0); + &dp_info, 0, false); /* Reset VLAN filter. */ filter_vlan = 0; @@ -3526,7 +3526,7 @@ int netlink_macfdb_read_specific_mac(struct zebra_ns *zns, return ret; ret = netlink_parse_info(netlink_macfdb_table, &zns->netlink_cmd, - &dp_info, 1, 0); + &dp_info, 1, false); return ret; } @@ -3930,7 +3930,7 @@ int netlink_neigh_read(struct zebra_ns *zns) if (ret < 0) return ret; ret = netlink_parse_info(netlink_neigh_table, &zns->netlink_cmd, - &dp_info, 0, 1); + &dp_info, 0, true); return ret; } @@ -3951,7 +3951,7 @@ int netlink_neigh_read_for_vlan(struct zebra_ns *zns, struct interface *vlan_if) if (ret < 0) return ret; ret = netlink_parse_info(netlink_neigh_table, &zns->netlink_cmd, - &dp_info, 0, 0); + &dp_info, 0, false); return ret; } @@ -4022,7 +4022,7 @@ int netlink_neigh_read_specific_ip(const struct ipaddr *ip, return ret; ret = netlink_parse_info(netlink_neigh_table, &zns->netlink_cmd, - &dp_info, 1, 0); + &dp_info, 1, false); return ret; } @@ -4442,7 +4442,7 @@ static int netlink_fdb_nh_update(uint32_t nh_id, struct in_addr vtep_ip) } return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, - 0); + false); } static int netlink_fdb_nh_del(uint32_t nh_id) @@ -4477,7 +4477,7 @@ static int netlink_fdb_nh_del(uint32_t nh_id) } return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, - 0); + false); } static int netlink_fdb_nhg_update(uint32_t nhg_id, uint32_t nh_cnt, @@ -4537,7 +4537,7 @@ static int netlink_fdb_nhg_update(uint32_t nhg_id, uint32_t nh_cnt, } return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, - 0); + false); } static int netlink_fdb_nhg_del(uint32_t nhg_id) diff --git a/zebra/rule_netlink.c b/zebra/rule_netlink.c index b651edd8f99f..fbf2620375f3 100644 --- a/zebra/rule_netlink.c +++ b/zebra/rule_netlink.c @@ -403,7 +403,7 @@ int netlink_rules_read(struct zebra_ns *zns) return ret; ret = netlink_parse_info(netlink_rule_change, &zns->netlink_cmd, - &dp_info, 0, 1); + &dp_info, 0, true); if (ret < 0) return ret; @@ -412,7 +412,7 @@ int netlink_rules_read(struct zebra_ns *zns) return ret; ret = netlink_parse_info(netlink_rule_change, &zns->netlink_cmd, - &dp_info, 0, 1); + &dp_info, 0, true); return ret; } From 81eb8fc749b8abd73857321bd9d64f2ead9f6ff5 Mon Sep 17 00:00:00 2001 From: ewlumpkin Date: Tue, 5 Oct 2021 03:05:42 +0000 Subject: [PATCH 060/188] lib: fix spelling nits in command.h Signed-off-by: ewlumpkin --- lib/command_graph.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/command_graph.h b/lib/command_graph.h index c20c9874c273..86157f872e0d 100644 --- a/lib/command_graph.h +++ b/lib/command_graph.h @@ -79,11 +79,11 @@ enum { CMD_ATTR_NORMAL, CMD_ATTR_YANG, }; -/* Comamand token struct. */ +/* Command token struct. */ struct cmd_token { enum cmd_token_type type; // token type uint8_t attr; // token attributes - bool allowrepeat; // matcher allowed to match token repetively? + bool allowrepeat; // matcher allowed to match token repetitively? uint32_t refcnt; char *text; // token text From 405ebe45cf111376fe33bad45b4ec836e0157d9f Mon Sep 17 00:00:00 2001 From: Igor Ryzhov Date: Tue, 5 Oct 2021 13:27:39 +0300 Subject: [PATCH 061/188] yang: replace an empty pattern with a zero-length restriction No functional difference, but `length "0"` is more comprehensible. Suggested-by: Christian Hopps Signed-off-by: Igor Ryzhov --- yang/frr-nexthop.yang | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yang/frr-nexthop.yang b/yang/frr-nexthop.yang index 2df2e2958e92..adcbacbfea5e 100644 --- a/yang/frr-nexthop.yang +++ b/yang/frr-nexthop.yang @@ -61,7 +61,7 @@ module frr-nexthop { type union { type inet:ip-address; type string { - pattern ""; + length "0"; } } } From a60eab9e109fd2625dc3f941d7d9be2b6312f593 Mon Sep 17 00:00:00 2001 From: rgirada Date: Tue, 5 Oct 2021 00:52:36 -0700 Subject: [PATCH 062/188] ospf6d: ospf6d is crashing upon receiving duplicated Grace LSA. Description: When grace lsa received, DUT is adding the copy of the lsas to all nbrs retransmission list as part of flooding procedure and subsequently incrementing the rmt counter in the original the LSA. This counter is supposed to be decremented when ack is received by nbr and the lsa will be removed from retransmission list. But in our current scenario, Step-1: When GR helper is disabled, if DUT receives the grace lsa it adds the lsa copy to nbrs retransmission list but original LSA will be discarded since GR helper disabled. Step-2: GR helper enabled and DUT receives the grace lsa, as part of flooding process all nbrs have same copy of lsa in their corresponding rmt list which was added in step -1 due to this the corresponding rmt counter in the original lsa is not getting incremented. Step-3: If the same copy of the grace lsa received by DUT, It considers as implicit ack from nbr if the same copy of the lsa exits in its rmt list and subsequently decrement the rmt counter. Since counter is zero (because of step-1 and 2) , it is asserting while decrement. Signed-off-by: Rajesh Girada --- ospf6d/ospf6_flood.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/ospf6d/ospf6_flood.c b/ospf6d/ospf6_flood.c index 186eac35a505..fa43c37ac704 100644 --- a/ospf6d/ospf6_flood.c +++ b/ospf6d/ospf6_flood.c @@ -1028,15 +1028,8 @@ void ospf6_receive_lsa(struct ospf6_neighbor *from, if (old) ospf6_flood_clear(old); - /* (b) immediately flood and (c) remove from all retrans-list */ - /* Prevent self-originated LSA to be flooded. this is to make - reoriginated instance of the LSA not to be rejected by other - routers - due to MinLSArrival. */ self_originated = (new->header->adv_router == from->ospf6_if->area->ospf6->router_id); - if (!self_originated) - ospf6_flood(from, new); /* Received non-self-originated Grace LSA. */ if (IS_GRACE_LSA(new) && !self_originated) { @@ -1082,6 +1075,14 @@ void ospf6_receive_lsa(struct ospf6_neighbor *from, } } + /* (b) immediately flood and (c) remove from all retrans-list */ + /* Prevent self-originated LSA to be flooded. this is to make + * reoriginated instance of the LSA not to be rejected by other + * routers due to MinLSArrival. + */ + if (!self_originated) + ospf6_flood(from, new); + /* (d), installing lsdb, which may cause routing table calculation (replacing database copy) */ ospf6_install_lsa(new); From 0f538858c2bd22072539c8dbd4ad87601b0fc8ac Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Mon, 4 Oct 2021 18:10:58 -0300 Subject: [PATCH 063/188] lib: prevent gRPC assert on missing YANG node `yang_dnode_get` will `assert` if no YANG node/model exist, so lets test for its existence first before trying to access it. This `assert` is only acceptable for internal FRR usage otherwise we might miss typos or unmatching YANG models nodes/leaves. For gRPC usage we should let users attempt to use non existing models without `assert`ing. Signed-off-by: Rafael Zalamena --- lib/northbound_grpc.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/northbound_grpc.cpp b/lib/northbound_grpc.cpp index 71f07dfe86d2..e227d0385c4c 100644 --- a/lib/northbound_grpc.cpp +++ b/lib/northbound_grpc.cpp @@ -344,6 +344,10 @@ static struct lyd_node *get_dnode_config(const std::string &path) { struct lyd_node *dnode; + if (!yang_dnode_exists(running_config->dnode, + path.empty() ? NULL : path.c_str())) + return NULL; + dnode = yang_dnode_get(running_config->dnode, path.empty() ? NULL : path.c_str()); if (dnode) From 0d5b3cb9d72670deee6a48721615f98aa2493b4c Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Tue, 5 Oct 2021 16:24:41 +0200 Subject: [PATCH 064/188] bgpd: large community exact match fix The pointer to large community was not the appropriate one. Signed-off-by: Philippe Guibert --- bgpd/bgp_clist.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bgpd/bgp_clist.c b/bgpd/bgp_clist.c index 33e3db2c1669..0e590a463c90 100644 --- a/bgpd/bgp_clist.c +++ b/bgpd/bgp_clist.c @@ -720,7 +720,7 @@ bool lcommunity_list_exact_match(struct lcommunity *lcom, return entry->direct == COMMUNITY_PERMIT; if (entry->style == LARGE_COMMUNITY_LIST_STANDARD) { - if (lcommunity_cmp(lcom, entry->u.com)) + if (lcommunity_cmp(lcom, entry->u.lcom)) return entry->direct == COMMUNITY_PERMIT; } else if (entry->style == LARGE_COMMUNITY_LIST_EXPANDED) { if (lcommunity_regexp_match(lcom, entry->reg)) From 1bfee9368adcd91337b4b4b5ad22330678ed0e78 Mon Sep 17 00:00:00 2001 From: Igor Ryzhov Date: Tue, 5 Oct 2021 17:38:21 +0300 Subject: [PATCH 065/188] isisd: fix redistribute CLI Currently, it is possible to configure IPv6 protocols for IPv4 redistribution and vice versa in CLI. The YANG model doesn't allow this so the user receives the following error: ``` nfware(config-router)# redistribute ipv4 ospf6 level-1 % Failed to edit configuration. YANG error(s): Invalid enumeration value "ospf6". Invalid enumeration value "ospf6". Invalid enumeration value "ospf6". YANG path: Schema location /frr-isisd:isis/instance/redistribute/ipv4/protocol. ``` Let's make CLI more user-friendly and allow only supported protocols in redistribution commands. Signed-off-by: Igor Ryzhov --- isisd/isis_cli.c | 9 ++++++--- isisd/isis_redist.c | 10 ++++++---- isisd/isisd.h | 8 ++++++++ python/clidef.py | 2 ++ 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/isisd/isis_cli.c b/isisd/isis_cli.c index 70ec66fd7feb..f48b142b1a2f 100644 --- a/isisd/isis_cli.c +++ b/isisd/isis_cli.c @@ -1330,11 +1330,14 @@ void cli_show_isis_def_origin_ipv6(struct vty *vty, struct lyd_node *dnode, * XPath: /frr-isisd:isis/instance/redistribute */ DEFPY_YANG(isis_redistribute, isis_redistribute_cmd, - "[no] redistribute $ip " PROTO_REDIST_STR - "$proto $level [{metric (0-16777215)|route-map WORD}]", + "[no] redistribute $level" + "[{metric (0-16777215)|route-map WORD}]", NO_STR REDIST_STR "Redistribute IPv4 routes\n" - "Redistribute IPv6 routes\n" PROTO_REDIST_HELP + PROTO_IP_REDIST_HELP + "Redistribute IPv6 routes\n" + PROTO_IP6_REDIST_HELP "Redistribute into level-1\n" "Redistribute into level-2\n" "Metric for redistributed routes\n" diff --git a/isisd/isis_redist.c b/isisd/isis_redist.c index 2f5e490da1b5..45d69bc352df 100644 --- a/isisd/isis_redist.c +++ b/isisd/isis_redist.c @@ -543,12 +543,13 @@ void isis_redist_area_finish(struct isis_area *area) #ifdef FABRICD DEFUN (isis_redistribute, isis_redistribute_cmd, - "redistribute " PROTO_REDIST_STR + "redistribute " " [{metric (0-16777215)|route-map WORD}]", REDIST_STR "Redistribute IPv4 routes\n" + PROTO_IP_REDIST_HELP "Redistribute IPv6 routes\n" - PROTO_REDIST_HELP + PROTO_IP6_REDIST_HELP "Metric for redistributed routes\n" "ISIS default metric\n" "Route map reference\n" @@ -599,12 +600,13 @@ DEFUN (isis_redistribute, DEFUN (no_isis_redistribute, no_isis_redistribute_cmd, - "no redistribute " PROTO_REDIST_STR, + "no redistribute ", NO_STR REDIST_STR "Redistribute IPv4 routes\n" + PROTO_IP_REDIST_HELP "Redistribute IPv6 routes\n" - PROTO_REDIST_HELP) + PROTO_IP6_REDIST_HELP) { int idx_afi = 2; int idx_protocol = 3; diff --git a/isisd/isisd.h b/isisd/isisd.h index 64fbf78a0737..13f3475b70b5 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -46,7 +46,11 @@ static const bool fabricd = true; #define PROTO_NAME "openfabric" #define PROTO_HELP "OpenFabric routing protocol\n" #define PROTO_REDIST_STR FRR_REDIST_STR_FABRICD +#define PROTO_IP_REDIST_STR FRR_IP_REDIST_STR_FABRICD +#define PROTO_IP6_REDIST_STR FRR_IP6_REDIST_STR_FABRICD #define PROTO_REDIST_HELP FRR_REDIST_HELP_STR_FABRICD +#define PROTO_IP_REDIST_HELP FRR_IP_REDIST_HELP_STR_FABRICD +#define PROTO_IP6_REDIST_HELP FRR_IP6_REDIST_HELP_STR_FABRICD #define ROUTER_NODE OPENFABRIC_NODE #else static const bool fabricd = false; @@ -54,7 +58,11 @@ static const bool fabricd = false; #define PROTO_NAME "isis" #define PROTO_HELP "IS-IS routing protocol\n" #define PROTO_REDIST_STR FRR_REDIST_STR_ISISD +#define PROTO_IP_REDIST_STR FRR_IP_REDIST_STR_ISISD +#define PROTO_IP6_REDIST_STR FRR_IP6_REDIST_STR_ISISD #define PROTO_REDIST_HELP FRR_REDIST_HELP_STR_ISISD +#define PROTO_IP_REDIST_HELP FRR_IP_REDIST_HELP_STR_ISISD +#define PROTO_IP6_REDIST_HELP FRR_IP6_REDIST_HELP_STR_ISISD #define ROUTER_NODE ISIS_NODE extern void isis_cli_init(void); #endif diff --git a/python/clidef.py b/python/clidef.py index a47cee2d6b47..ba7c9072c588 100644 --- a/python/clidef.py +++ b/python/clidef.py @@ -435,6 +435,8 @@ def do_add(handler, basename, varname, attr=""): macros.load(os.path.join(basepath, "bgpd/bgp_vty.h")) # sigh :( macros["PROTO_REDIST_STR"] = "FRR_REDIST_STR_ISISD" + macros["PROTO_IP_REDIST_STR"] = "FRR_IP_REDIST_STR_ISISD" + macros["PROTO_IP6_REDIST_STR"] = "FRR_IP6_REDIST_STR_ISISD" errors = process_file(args.cfile, ofd, dumpfd, args.all_defun, macros) if errors != 0: From a6ce07852c0376dd5ecd9901302c2852086202c8 Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Tue, 5 Oct 2021 12:35:42 -0300 Subject: [PATCH 066/188] topotests: increase OSPF convergence speed Reduce timers so we send hello packets more often and reduce dead interval to converge faster. Previous test wait amount: > INFO: topolog: 'router_json_cmp' succeeded after 47.20 seconds New test wait amount: > INFO: topolog: 'router_json_cmp' succeeded after 20.08 seconds Signed-off-by: Rafael Zalamena --- tests/topotests/bfd_ospf_topo1/rt1/ospf6d.conf | 4 ++++ tests/topotests/bfd_ospf_topo1/rt1/ospfd.conf | 6 ++++++ tests/topotests/bfd_ospf_topo1/rt2/ospf6d.conf | 4 ++++ tests/topotests/bfd_ospf_topo1/rt2/ospfd.conf | 6 ++++++ tests/topotests/bfd_ospf_topo1/rt3/ospf6d.conf | 4 ++++ tests/topotests/bfd_ospf_topo1/rt3/ospfd.conf | 6 ++++++ tests/topotests/bfd_ospf_topo1/rt4/ospf6d.conf | 4 ++++ tests/topotests/bfd_ospf_topo1/rt4/ospfd.conf | 6 ++++++ tests/topotests/bfd_ospf_topo1/rt5/ospf6d.conf | 4 ++++ tests/topotests/bfd_ospf_topo1/rt5/ospfd.conf | 6 ++++++ 10 files changed, 50 insertions(+) diff --git a/tests/topotests/bfd_ospf_topo1/rt1/ospf6d.conf b/tests/topotests/bfd_ospf_topo1/rt1/ospf6d.conf index 18def599b4bf..98da8c261920 100644 --- a/tests/topotests/bfd_ospf_topo1/rt1/ospf6d.conf +++ b/tests/topotests/bfd_ospf_topo1/rt1/ospf6d.conf @@ -6,10 +6,14 @@ hostname rt1 password 1 ! interface eth-rt2 + ipv6 ospf6 hello-interval 2 + ipv6 ospf6 dead-interval 8 ipv6 ospf6 network broadcast ipv6 ospf6 bfd ! interface eth-rt3 + ipv6 ospf6 hello-interval 2 + ipv6 ospf6 dead-interval 8 ipv6 ospf6 network broadcast ipv6 ospf6 bfd ! diff --git a/tests/topotests/bfd_ospf_topo1/rt1/ospfd.conf b/tests/topotests/bfd_ospf_topo1/rt1/ospfd.conf index 07b42f98859c..9da876500535 100644 --- a/tests/topotests/bfd_ospf_topo1/rt1/ospfd.conf +++ b/tests/topotests/bfd_ospf_topo1/rt1/ospfd.conf @@ -10,13 +10,19 @@ debug ospf zebra ! interface lo ip ospf area 0.0.0.0 + ip ospf hello-interval 2 + ip ospf dead-interval 8 ! interface eth-rt2 ip ospf area 0.0.0.0 + ip ospf hello-interval 2 + ip ospf dead-interval 8 ip ospf bfd ! interface eth-rt3 ip ospf area 0.0.0.0 + ip ospf hello-interval 2 + ip ospf dead-interval 8 ip ospf bfd ! router ospf diff --git a/tests/topotests/bfd_ospf_topo1/rt2/ospf6d.conf b/tests/topotests/bfd_ospf_topo1/rt2/ospf6d.conf index 2f35099564ab..34b09020949a 100644 --- a/tests/topotests/bfd_ospf_topo1/rt2/ospf6d.conf +++ b/tests/topotests/bfd_ospf_topo1/rt2/ospf6d.conf @@ -5,10 +5,14 @@ hostname rt2 password 1 ! interface eth-rt1 + ipv6 ospf6 hello-interval 2 + ipv6 ospf6 dead-interval 8 ipv6 ospf6 network broadcast ipv6 ospf6 bfd ! interface eth-rt5 + ipv6 ospf6 hello-interval 2 + ipv6 ospf6 dead-interval 8 ipv6 ospf6 network broadcast ! router ospf6 diff --git a/tests/topotests/bfd_ospf_topo1/rt2/ospfd.conf b/tests/topotests/bfd_ospf_topo1/rt2/ospfd.conf index a05d8b58c8e7..11be6a14b231 100644 --- a/tests/topotests/bfd_ospf_topo1/rt2/ospfd.conf +++ b/tests/topotests/bfd_ospf_topo1/rt2/ospfd.conf @@ -9,13 +9,19 @@ debug ospf zebra ! interface lo ip ospf area 0.0.0.0 + ip ospf hello-interval 2 + ip ospf dead-interval 8 ! interface eth-rt1 ip ospf area 0.0.0.0 + ip ospf hello-interval 2 + ip ospf dead-interval 8 ip ospf bfd ! interface eth-rt5 ip ospf area 0.0.0.0 + ip ospf hello-interval 2 + ip ospf dead-interval 8 ! router ospf ospf router-id 2.2.2.2 diff --git a/tests/topotests/bfd_ospf_topo1/rt3/ospf6d.conf b/tests/topotests/bfd_ospf_topo1/rt3/ospf6d.conf index 3e8777019efa..8ab4eee1d3c4 100644 --- a/tests/topotests/bfd_ospf_topo1/rt3/ospf6d.conf +++ b/tests/topotests/bfd_ospf_topo1/rt3/ospf6d.conf @@ -5,10 +5,14 @@ hostname rt3 password 1 ! interface eth-rt1 + ipv6 ospf6 hello-interval 2 + ipv6 ospf6 dead-interval 8 ipv6 ospf6 network broadcast ipv6 ospf6 bfd ! interface eth-rt4 + ipv6 ospf6 hello-interval 2 + ipv6 ospf6 dead-interval 8 ipv6 ospf6 network broadcast ! router ospf6 diff --git a/tests/topotests/bfd_ospf_topo1/rt3/ospfd.conf b/tests/topotests/bfd_ospf_topo1/rt3/ospfd.conf index 1196e6d18962..acc54b38665e 100644 --- a/tests/topotests/bfd_ospf_topo1/rt3/ospfd.conf +++ b/tests/topotests/bfd_ospf_topo1/rt3/ospfd.conf @@ -9,13 +9,19 @@ debug ospf zebra ! interface lo ip ospf area 0.0.0.0 + ip ospf hello-interval 2 + ip ospf dead-interval 8 ! interface eth-rt1 ip ospf area 0.0.0.0 + ip ospf hello-interval 2 + ip ospf dead-interval 8 ip ospf bfd ! interface eth-rt4 ip ospf area 0.0.0.0 + ip ospf hello-interval 2 + ip ospf dead-interval 8 ! router ospf ospf router-id 3.3.3.3 diff --git a/tests/topotests/bfd_ospf_topo1/rt4/ospf6d.conf b/tests/topotests/bfd_ospf_topo1/rt4/ospf6d.conf index bccd1e75bde8..138b688140d9 100644 --- a/tests/topotests/bfd_ospf_topo1/rt4/ospf6d.conf +++ b/tests/topotests/bfd_ospf_topo1/rt4/ospf6d.conf @@ -5,9 +5,13 @@ hostname rt4 password 1 ! interface eth-rt3 + ipv6 ospf6 hello-interval 2 + ipv6 ospf6 dead-interval 8 ipv6 ospf6 network broadcast ! interface eth-rt5 + ipv6 ospf6 hello-interval 2 + ipv6 ospf6 dead-interval 8 ipv6 ospf6 network broadcast ! router ospf6 diff --git a/tests/topotests/bfd_ospf_topo1/rt4/ospfd.conf b/tests/topotests/bfd_ospf_topo1/rt4/ospfd.conf index 3a2568b4ab52..670e56ccc846 100644 --- a/tests/topotests/bfd_ospf_topo1/rt4/ospfd.conf +++ b/tests/topotests/bfd_ospf_topo1/rt4/ospfd.conf @@ -9,12 +9,18 @@ debug ospf zebra ! interface lo ip ospf area 0.0.0.0 + ip ospf hello-interval 2 + ip ospf dead-interval 8 ! interface eth-rt3 ip ospf area 0.0.0.0 + ip ospf hello-interval 2 + ip ospf dead-interval 8 ! interface eth-rt5 ip ospf area 0.0.0.0 + ip ospf hello-interval 2 + ip ospf dead-interval 8 ! router ospf ospf router-id 4.4.4.4 diff --git a/tests/topotests/bfd_ospf_topo1/rt5/ospf6d.conf b/tests/topotests/bfd_ospf_topo1/rt5/ospf6d.conf index 766862276c95..6eb4fe59a887 100644 --- a/tests/topotests/bfd_ospf_topo1/rt5/ospf6d.conf +++ b/tests/topotests/bfd_ospf_topo1/rt5/ospf6d.conf @@ -6,9 +6,13 @@ password 1 ! interface eth-rt2 ipv6 ospf6 network broadcast + ipv6 ospf6 hello-interval 2 + ipv6 ospf6 dead-interval 8 ! interface eth-rt4 ipv6 ospf6 network broadcast + ipv6 ospf6 hello-interval 2 + ipv6 ospf6 dead-interval 8 ! router ospf6 ospf6 router-id 5.5.5.5 diff --git a/tests/topotests/bfd_ospf_topo1/rt5/ospfd.conf b/tests/topotests/bfd_ospf_topo1/rt5/ospfd.conf index a35de5f45fc0..286de512889d 100644 --- a/tests/topotests/bfd_ospf_topo1/rt5/ospfd.conf +++ b/tests/topotests/bfd_ospf_topo1/rt5/ospfd.conf @@ -9,12 +9,18 @@ debug ospf zebra ! interface lo ip ospf area 0.0.0.0 + ip ospf hello-interval 2 + ip ospf dead-interval 8 ! interface eth-rt2 ip ospf area 0.0.0.0 + ip ospf hello-interval 2 + ip ospf dead-interval 8 ! interface eth-rt4 ip ospf area 0.0.0.0 + ip ospf hello-interval 2 + ip ospf dead-interval 8 ! router ospf ospf router-id 5.5.5.5 From 8ff24fd29effe974d870309bfb7bc89f39de0024 Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Tue, 5 Oct 2021 12:36:43 -0300 Subject: [PATCH 067/188] topotests: decrease result check frequency Call the `show` commands less often to reduce the CPU pressure. Also increase the wait time from 60 to 80 seconds to have spare room for failures (4 times more). This is the latest measure wait time: > INFO: topolog: 'router_json_cmp' succeeded after 20.08 seconds Signed-off-by: Rafael Zalamena --- tests/topotests/bfd_ospf_topo1/test_bfd_ospf_topo1.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/topotests/bfd_ospf_topo1/test_bfd_ospf_topo1.py b/tests/topotests/bfd_ospf_topo1/test_bfd_ospf_topo1.py index 09b86317404a..33245b64c870 100755 --- a/tests/topotests/bfd_ospf_topo1/test_bfd_ospf_topo1.py +++ b/tests/topotests/bfd_ospf_topo1/test_bfd_ospf_topo1.py @@ -132,7 +132,7 @@ def print_cmd_result(rname, command): print(get_topogen().gears[rname].vtysh_cmd(command, isjson=False)) -def router_compare_json_output(rname, command, reference, count=120, wait=0.5): +def router_compare_json_output(rname, command, reference, count=40, wait=2): "Compare router JSON output" logger.info('Comparing router "%s" "%s" output', rname, command) @@ -141,7 +141,7 @@ def router_compare_json_output(rname, command, reference, count=120, wait=0.5): filename = "{}/{}/{}".format(CWD, rname, reference) expected = json.loads(open(filename).read()) - # Run test function until we get an result. Wait at most 60 seconds. + # Run test function until we get an result. Wait at most 80 seconds. test_func = partial(topotest.router_json_cmp, tgen.gears[rname], command, expected) _, diff = topotest.run_and_expect(test_func, None, count=count, wait=wait) assertmsg = '"{}" JSON output mismatches the expected result'.format(rname) From 2d28cbe66137397dcd3416b97edc99f982f1b988 Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Tue, 5 Oct 2021 12:37:34 -0300 Subject: [PATCH 068/188] topotests: justify code sleep Document the `sleep` statement so people know that we are sleeping because we are waiting for the BFD down notification. If we don't sleep here it is possible that we get outdated `show` command results. Signed-off-by: Rafael Zalamena --- tests/topotests/bfd_ospf_topo1/test_bfd_ospf_topo1.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/topotests/bfd_ospf_topo1/test_bfd_ospf_topo1.py b/tests/topotests/bfd_ospf_topo1/test_bfd_ospf_topo1.py index 33245b64c870..bef2c3f162bb 100755 --- a/tests/topotests/bfd_ospf_topo1/test_bfd_ospf_topo1.py +++ b/tests/topotests/bfd_ospf_topo1/test_bfd_ospf_topo1.py @@ -195,8 +195,8 @@ def test_bfd_ospf_interface_failure_rt2_step3(): # By default BFD provides a recovery time of 900ms plus jitter, so let's wait # initial 2 seconds to let the CI not suffer. - # TODO: add check for array size - sleep(2) + topotest.sleep(2, 'Wait for BFD down notification') + router_compare_json_output( "rt1", "show ip route ospf json", "step3/show_ip_route_rt2_down.ref", 1, 0 ) @@ -234,8 +234,7 @@ def test_bfd_ospf_interface_failure_rt3_step3(): # By default BFD provides a recovery time of 900ms plus jitter, so let's wait # initial 2 seconds to let the CI not suffer. - # TODO: add check for array size - sleep(2) + topotest.sleep(2, 'Wait for BFD down notification') router_compare_json_output( "rt1", "show ip route ospf json", "step3/show_ip_route_rt3_down.ref", 1, 0 ) From 214d8a60e15dc1b086d3f6033f686246317739f1 Mon Sep 17 00:00:00 2001 From: ewlumpkin Date: Tue, 5 Oct 2021 21:33:14 +0000 Subject: [PATCH 069/188] lib: fix spelling nits in more lib files Signed-off-by: ewlumpkin --- lib/atomlist.c | 2 +- lib/atomlist.h | 2 +- lib/bfd.c | 2 +- lib/buffer.c | 2 +- lib/command.h | 2 +- lib/command_match.h | 2 +- lib/command_parse.y | 2 +- lib/db.c | 2 +- lib/distribute.h | 2 +- lib/ferr.h | 2 +- lib/filter.c | 4 ++-- lib/frr_zmq.c | 2 +- lib/frrscript.c | 2 +- lib/graph.c | 2 +- lib/hash.h | 2 +- lib/hook.h | 2 +- lib/if.c | 6 +++--- lib/if.h | 4 ++-- lib/lib_errors.c | 8 ++++---- lib/libospf.h | 2 +- lib/netns_linux.c | 2 +- lib/prefix.c | 2 +- lib/routemap.c | 2 +- lib/sbuf.h | 2 +- lib/sigevent.c | 4 ++-- lib/skiplist.c | 2 +- lib/skiplist.h | 2 +- 27 files changed, 35 insertions(+), 35 deletions(-) diff --git a/lib/atomlist.c b/lib/atomlist.c index 8169ba9eb453..3668b083d059 100644 --- a/lib/atomlist.c +++ b/lib/atomlist.c @@ -121,7 +121,7 @@ static void atomlist_del_core(struct atomlist_head *h, memory_order_consume); /* track the beginning of a chain of deleted items - * this is neccessary to make this lock-free; we can + * this is necessary to make this lock-free; we can * complete deletions started by other threads. */ if (!atomptr_l(prevval)) { diff --git a/lib/atomlist.h b/lib/atomlist.h index c795128a34d5..b0c4da4baa82 100644 --- a/lib/atomlist.h +++ b/lib/atomlist.h @@ -100,7 +100,7 @@ static inline bool atomptr_u(atomptr_t val) /* single-linked list, unsorted/arbitrary. * can be used as queue with add_tail / pop * - * all operations are lock-free, but not neccessarily wait-free. this means + * all operations are lock-free, but not necessarily wait-free. this means * that there is no state where the system as a whole stops making process, * but it *is* possible that a *particular* thread is delayed by some time. * diff --git a/lib/bfd.c b/lib/bfd.c index ea363b7ca4a3..5a8a46b67bfa 100644 --- a/lib/bfd.c +++ b/lib/bfd.c @@ -203,7 +203,7 @@ static void bfd_last_update(time_t last_update, char *buf, size_t len) struct tm tm; struct timeval tv; - /* If no BFD satatus update has ever been received, print `never'. */ + /* If no BFD status update has ever been received, print `never'. */ if (last_update == 0) { snprintf(buf, len, "never"); return; diff --git a/lib/buffer.c b/lib/buffer.c index 41b1adc9fc0d..e976fecc1f13 100644 --- a/lib/buffer.c +++ b/lib/buffer.c @@ -59,7 +59,7 @@ struct buffer_data { /* It should always be true that: 0 <= sp <= cp <= size */ /* Default buffer size (used if none specified). It is rounded up to the - next page boundery. */ + next page boundary. */ #define BUFFER_SIZE_DEFAULT 4096 #define BUFFER_DATA_FREE(D) XFREE(MTYPE_BUFFER_DATA, (D)) diff --git a/lib/command.h b/lib/command.h index 8a7c9a2048b4..e2eec1aac68c 100644 --- a/lib/command.h +++ b/lib/command.h @@ -234,7 +234,7 @@ struct cmd_node { /* Argc max counts. */ #define CMD_ARGC_MAX 256 -/* Turn off these macros when uisng cpp with extract.pl */ +/* Turn off these macros when using cpp with extract.pl */ #ifndef VTYSH_EXTRACT_PL /* helper defines for end-user DEFUN* macros */ diff --git a/lib/command_match.h b/lib/command_match.h index fcb333120fb8..0488cc1a1fe6 100644 --- a/lib/command_match.h +++ b/lib/command_match.h @@ -68,7 +68,7 @@ enum match_type { * @param[in] vline vectorized input string * @param[out] argv pointer to argument list if successful match, NULL * otherwise. The elements of this list are pointers to struct cmd_token - * and represent the sequence of tokens matched by the inpu. The ->arg + * and represent the sequence of tokens matched by the input. The ->arg * field of each token points to a copy of the input matched on it. These * may be safely deleted or modified. * @param[out] element pointer to matched cmd_element if successful match, diff --git a/lib/command_parse.y b/lib/command_parse.y index 3e2cdc79af9c..dccd738f3156 100644 --- a/lib/command_parse.y +++ b/lib/command_parse.y @@ -338,7 +338,7 @@ selector: '{' selector_seq_seq '}' varname_token * 1) this allows "at least 1 of" semantics, which are otherwise impossible * 2) this would add a start->end->start loop in the graph that the current * loop-avoidal fails to handle - * just use [{a|b}] if neccessary, that will work perfectly fine, and reason + * just use [{a|b}] if necessary, that will work perfectly fine, and reason * #1 is good enough to keep it this way. */ loopcheck(ctx, &$$); diff --git a/lib/db.c b/lib/db.c index 32ba83b65671..b4286b8d2cbf 100644 --- a/lib/db.c +++ b/lib/db.c @@ -60,7 +60,7 @@ int db_init(const char *path_fmt, ...) (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE), NULL) != SQLITE_OK) { if (dbp == NULL) { - zlog_warn("%s: failed to open dabatase '%s'", __func__, + zlog_warn("%s: failed to open database '%s'", __func__, path); return -1; } diff --git a/lib/distribute.h b/lib/distribute.h index 83682dea6ad4..6b3226e8b4b3 100644 --- a/lib/distribute.h +++ b/lib/distribute.h @@ -29,7 +29,7 @@ extern "C" { #endif -/* Disctirubte list types. */ +/* Distribute list types. */ enum distribute_type { DISTRIBUTE_V4_IN, DISTRIBUTE_V6_IN, diff --git a/lib/ferr.h b/lib/ferr.h index 4e95431cea21..c27601f66c42 100644 --- a/lib/ferr.h +++ b/lib/ferr.h @@ -34,7 +34,7 @@ extern "C" { /* return type when this error indication stuff is used. * * guaranteed to have boolean evaluation to "false" when OK, "true" when error - * (i.e. can be changed to pointer in the future if neccessary) + * (i.e. can be changed to pointer in the future if necessary) * * For checking, always use "if (value)", nothing else. * Do _NOT_ use any integer constant (!= 0), or sign check (< 0). diff --git a/lib/filter.c b/lib/filter.c index 744ea9c480a2..39c2e0e7043c 100644 --- a/lib/filter.c +++ b/lib/filter.c @@ -192,7 +192,7 @@ void access_list_delete(struct access_list *access) access_list_free(access); } -/* Insert new access list to list of access_list. Each acceess_list +/* Insert new access list to list of access_list. Each access_list is sorted by the name. */ static struct access_list *access_list_insert(afi_t afi, const char *name) { @@ -387,7 +387,7 @@ void access_list_filter_add(struct access_list *access, struct filter *replace; struct filter *point; - /* Automatic asignment of seq no. */ + /* Automatic assignment of seq no. */ if (filter->seq == -1) filter->seq = filter_new_seq_get(access); diff --git a/lib/frr_zmq.c b/lib/frr_zmq.c index ea9c828f7c00..e297985f9457 100644 --- a/lib/frr_zmq.c +++ b/lib/frr_zmq.c @@ -19,7 +19,7 @@ /* * IF YOU MODIFY THIS FILE PLEASE RUN `make check` and ensure that - * the test_zmq.c unit test is still working. There are dependancies + * the test_zmq.c unit test is still working. There are dependencies * between the two that are extremely fragile. My understanding * is that there is specialized ownership of the cb pointer based * upon what is happening. Those assumptions are supposed to be diff --git a/lib/frrscript.c b/lib/frrscript.c index 0e0d3c030c82..b935b30cc29c 100644 --- a/lib/frrscript.c +++ b/lib/frrscript.c @@ -226,7 +226,7 @@ void *frrscript_get_result(struct frrscript *fs, const char *function_name, p = lua_to(lfs->L, 2); /* At the end, the Lua state should be same as it was at the start - * i.e. containing soley the returned table. + * i.e. containing solely the returned table. */ assert(lua_gettop(lfs->L) == 1); assert(lua_istable(lfs->L, -1) == 1); diff --git a/lib/graph.c b/lib/graph.c index 1cbe1b90f96d..ba7314fb25b1 100644 --- a/lib/graph.c +++ b/lib/graph.c @@ -69,7 +69,7 @@ static void graph_vector_remove(vector v, unsigned int ix) * and v->active is > ix. */ v->active--; /* if ix == v->active--, we set the item to itself, then to NULL... - * still correct, no check neccessary. */ + * still correct, no check necessary. */ v->index[ix] = v->index[v->active]; v->index[v->active] = NULL; } diff --git a/lib/hash.h b/lib/hash.h index 47d951a34b2a..f3b24f051b8c 100644 --- a/lib/hash.h +++ b/lib/hash.h @@ -161,7 +161,7 @@ hash_create_size(unsigned int size, unsigned int (*hash_key)(const void *), * an element from its key, you must provide the data item itself, with the * portions used in the hash function set to the same values as the data item * to retrieve. To insert a data element, either provide the key as just - * described and provide alloc_func as descrbied below to allocate the full + * described and provide alloc_func as described below to allocate the full * data element, or provide the full data element and pass 'hash_alloc_intern' * to alloc_func. * diff --git a/lib/hook.h b/lib/hook.h index 3a0db6009b45..d75e623edc37 100644 --- a/lib/hook.h +++ b/lib/hook.h @@ -193,7 +193,7 @@ extern void _hook_unregister(struct hook *hook, void *funcptr, void *arg, * usage: DECLARE_HOOK(my_hook, (int arg1, struct foo *arg2), (arg1, arg2)); * as above, "passlist" must use the same order and same names as "arglist" * - * theoretically passlist is not neccessary, but let's keep things simple and + * theoretically passlist is not necessary, but let's keep things simple and * use exact same args on DECLARE and DEFINE. */ #define DECLARE_HOOK(hookname, arglist, passlist) \ diff --git a/lib/if.c b/lib/if.c index 424880ff425a..cbd1b957d97c 100644 --- a/lib/if.c +++ b/lib/if.c @@ -341,7 +341,7 @@ static struct interface *if_lookup_by_ifindex(ifindex_t ifindex, return RB_FIND(if_index_head, &vrf->ifaces_by_index, &if_tmp); } -/* Interface existance check by index. */ +/* Interface existence check by index. */ struct interface *if_lookup_by_index(ifindex_t ifindex, vrf_id_t vrf_id) { switch (vrf_get_backend()) { @@ -354,7 +354,7 @@ struct interface *if_lookup_by_index(ifindex_t ifindex, vrf_id_t vrf_id) return NULL; } -/* Interface existance check by index. */ +/* Interface existence check by index. */ struct interface *if_vrf_lookup_by_index_next(ifindex_t ifindex, vrf_id_t vrf_id) { @@ -406,7 +406,7 @@ ifindex_t ifname2ifindex(const char *name, vrf_id_t vrf_id) : IFINDEX_INTERNAL; } -/* Interface existance check by interface name. */ +/* Interface existence check by interface name. */ struct interface *if_lookup_by_name(const char *name, vrf_id_t vrf_id) { struct vrf *vrf = vrf_lookup_by_id(vrf_id); diff --git a/lib/if.h b/lib/if.h index 43e2d3cffaae..59e75d8b6885 100644 --- a/lib/if.h +++ b/lib/if.h @@ -251,8 +251,8 @@ struct interface { /* Interface MTU. */ unsigned int mtu; /* IPv4 MTU */ unsigned int - mtu6; /* IPv6 MTU - probably, but not neccessarily same as mtu - */ + mtu6; /* IPv6 MTU - probably, but not necessarily same as mtu + */ /* Link-layer information and hardware address */ enum zebra_link_type ll_type; diff --git a/lib/lib_errors.c b/lib/lib_errors.c index 17695e6607c8..a139b9a14ca6 100644 --- a/lib/lib_errors.c +++ b/lib/lib_errors.c @@ -41,19 +41,19 @@ static struct log_ref ferr_lib_warn[] = { { .code = EC_LIB_LINUX_NS, .title = "The Linux namespace subsystem has encountered a parsing error", - .description = "During system startup an invalid parameter for the namesapce was give to FRR", + .description = "During system startup an invalid parameter for the namespace was give to FRR", .suggestion = "Gather log data and open an Issue. restart FRR", }, { .code = EC_LIB_SLOW_THREAD_CPU, .title = "The Event subsystem has detected a slow cpu time process", - .description = "The Event subsystem has detected a slow process, this typically indicates that FRR is having trouble completing work in a timely manner. This can be either a misconfiguration, bug, or some combination therof. In this case total CPU time was over 5 seconds. Which indicates that FRR is very busy doing some work and should be addressed", + .description = "The Event subsystem has detected a slow process, this typically indicates that FRR is having trouble completing work in a timely manner. This can be either a misconfiguration, bug, or some combination thereof. In this case total CPU time was over 5 seconds. Which indicates that FRR is very busy doing some work and should be addressed", .suggestion = "Gather log data and open an Issue", }, { .code = EC_LIB_SLOW_THREAD_WALL, .title = "The Event subsystem has detected a slow wall time process", - .description = "The Event subsystem has detected a slow process, this typically indicates that FRR is having trouble completing work in a timely manner. This can be either a misconfiguration, bug or some combination therof. In this case total WALL time was over 5 seconds. Which indicates that FRR might be having trouble being scheduled or some system call is delaying", + .description = "The Event subsystem has detected a slow process, this typically indicates that FRR is having trouble completing work in a timely manner. This can be either a misconfiguration, bug or some combination thereof. In this case total WALL time was over 5 seconds. Which indicates that FRR might be having trouble being scheduled or some system call is delaying", .suggestion = "Gather log data and open an Issue", }, { @@ -286,7 +286,7 @@ static struct log_ref ferr_lib_err[] = { }, { .code = EC_LIB_NB_CB_INVALID_PRIO, - .title = "Norhtbound callback has an invalid priority", + .title = "Northbound callback has an invalid priority", .description = "The northbound subsystem, during initialization, has detected a callback whose priority is invalid", .suggestion = "This is a bug; please report it" }, diff --git a/lib/libospf.h b/lib/libospf.h index d2bb29d80e16..c8ada9d3c52f 100644 --- a/lib/libospf.h +++ b/lib/libospf.h @@ -36,7 +36,7 @@ extern "C" { #define IPPROTO_OSPFIGP 89 #endif /* IPPROTO_OSPFIGP */ -/* Architectual Constants */ +/* Architectural Constants */ #ifdef DEBUG #define OSPF_LS_REFRESH_TIME 120 #else diff --git a/lib/netns_linux.c b/lib/netns_linux.c index cde842b88c4c..43c0d8c3595e 100644 --- a/lib/netns_linux.c +++ b/lib/netns_linux.c @@ -279,7 +279,7 @@ static void ns_disable_internal(struct ns *ns) } } -/* VRF list existance check by name. */ +/* VRF list existence check by name. */ static struct ns_map_nsid *ns_map_nsid_lookup_by_nsid(ns_id_t ns_id) { struct ns_map_nsid ns_map; diff --git a/lib/prefix.c b/lib/prefix.c index ef7d2e59daad..df753fe10b81 100644 --- a/lib/prefix.c +++ b/lib/prefix.c @@ -113,7 +113,7 @@ const char *family2str(int family) return "?"; } -/* Address Famiy Identifier to Address Family converter. */ +/* Address Family Identifier to Address Family converter. */ int afi2family(afi_t afi) { if (afi == AFI_IP) diff --git a/lib/routemap.c b/lib/routemap.c index 5c60b7d1c6d4..6227ebf15804 100644 --- a/lib/routemap.c +++ b/lib/routemap.c @@ -2480,7 +2480,7 @@ void route_map_notify_pentry_dependencies(const char *affected_name, do whatever the exit policy (EXIT, NEXT or GOTO) tells. on-match next - If this clause is matched, then the set statements are executed and then we drop through to the next clause - on-match goto n - If this clause is matched, then the set statments + on-match goto n - If this clause is matched, then the set statements are executed and then we goto the nth clause, or the first clause greater than this. In order to ensure route-maps *always* exit, you cannot jump backwards. diff --git a/lib/sbuf.h b/lib/sbuf.h index 9f0311006d11..aaa2db0edb8d 100644 --- a/lib/sbuf.h +++ b/lib/sbuf.h @@ -35,7 +35,7 @@ extern "C" { * without any information about the previous parsing steps, is usually not very * helpful. * Using sbuf, the parser can log the whole parsing process into a buffer using - * a printf like API. When an error ocurrs, all the information about previous + * a printf like API. When an error occurs, all the information about previous * parsing steps is there in the log, without any need for backtracking, and can * be used to give a detailed and useful error description. * When parsing completes successfully without any error, the log can just be diff --git a/lib/sigevent.c b/lib/sigevent.c index be7297f26441..6710527ae9f0 100644 --- a/lib/sigevent.c +++ b/lib/sigevent.c @@ -96,7 +96,7 @@ int quagga_sigevent_process(void) struct quagga_signal_t *sig; int i; #ifdef SIGEVENT_BLOCK_SIGNALS - /* shouldnt need to block signals, but potentially may be needed */ + /* shouldn't need to block signals, but potentially may be needed */ sigset_t newmask, oldmask; /* @@ -142,7 +142,7 @@ int quagga_sigevent_process(void) } #ifdef SIGEVENT_SCHEDULE_THREAD -/* timer thread to check signals. Shouldnt be needed */ +/* timer thread to check signals. shouldn't be needed */ int quagga_signal_timer(struct thread *t) { struct quagga_sigevent_master_t *sigm; diff --git a/lib/skiplist.c b/lib/skiplist.c index c5219f7381f9..81407826f2ea 100644 --- a/lib/skiplist.c +++ b/lib/skiplist.c @@ -21,7 +21,7 @@ */ /* - * Skip List impementation based on code from William Pugh. + * Skip List implementation based on code from William Pugh. * ftp://ftp.cs.umd.edu/pub/skipLists/ * * Skip Lists are a probabilistic alternative to balanced trees, as diff --git a/lib/skiplist.h b/lib/skiplist.h index 00950e13bbc5..165607820aac 100644 --- a/lib/skiplist.h +++ b/lib/skiplist.h @@ -21,7 +21,7 @@ */ /* - * Skip List impementation based on code from William Pugh. + * Skip List implementation based on code from William Pugh. * ftp://ftp.cs.umd.edu/pub/skipLists/ */ From 578e1c5331f24d4553c12f0fe5201067c8f50bb3 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Thu, 23 Sep 2021 01:14:00 -0300 Subject: [PATCH 070/188] ospf6d: remove unused function parameter Signed-off-by: Renato Westphal --- ospf6d/ospf6_abr.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c index 57165201bd82..0b2c14bc5430 100644 --- a/ospf6d/ospf6_abr.c +++ b/ospf6d/ospf6_abr.c @@ -96,8 +96,7 @@ static int ospf6_abr_nexthops_belong_to_area(struct ospf6_route *route, return 0; } -static void ospf6_abr_delete_route(struct ospf6_route *range, - struct ospf6_route *summary, +static void ospf6_abr_delete_route(struct ospf6_route *summary, struct ospf6_route_table *summary_table, struct ospf6_lsa *old) { @@ -375,8 +374,8 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, zlog_debug( "The range is not active. withdraw"); - ospf6_abr_delete_route(route, summary, - summary_table, old); + ospf6_abr_delete_route(summary, summary_table, + old); } } else if (old) { ospf6_route_remove(summary, summary_table); @@ -390,7 +389,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, zlog_debug( "Area has been stubbed, purge Inter-Router LSA"); - ospf6_abr_delete_route(route, summary, summary_table, old); + ospf6_abr_delete_route(summary, summary_table, old); return 0; } @@ -399,7 +398,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, if (is_debug) zlog_debug("Area has been stubbed, purge prefix LSA"); - ospf6_abr_delete_route(route, summary, summary_table, old); + ospf6_abr_delete_route(summary, summary_table, old); return 0; } @@ -434,8 +433,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, if (is_debug) zlog_debug( "This is the secondary path to the ASBR, ignore"); - ospf6_abr_delete_route(route, summary, summary_table, - old); + ospf6_abr_delete_route(summary, summary_table, old); return 0; } @@ -465,8 +463,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, zlog_debug( "Suppressed by range %pFX of area %s", &range->prefix, route_area->name); - ospf6_abr_delete_route(route, summary, summary_table, - old); + ospf6_abr_delete_route(summary, summary_table, old); return 0; } } @@ -478,8 +475,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, if (is_debug) zlog_debug( "This is the range with DoNotAdvertise set. ignore"); - ospf6_abr_delete_route(route, summary, summary_table, - old); + ospf6_abr_delete_route(summary, summary_table, old); return 0; } @@ -487,8 +483,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, if (!CHECK_FLAG(route->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)) { if (is_debug) zlog_debug("The range is not active. withdraw"); - ospf6_abr_delete_route(route, summary, summary_table, - old); + ospf6_abr_delete_route(summary, summary_table, old); return 0; } } From 36be5c61b3143225f9ae700ab192bcbc985f3d36 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Thu, 23 Sep 2021 01:14:13 -0300 Subject: [PATCH 071/188] ospf6d: remove unguarded debug message This debug message is of little use so remove it instead of adding a debug guard for it. Signed-off-by: Renato Westphal --- ospf6d/ospf6_area.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/ospf6d/ospf6_area.c b/ospf6d/ospf6_area.c index 999266b8d1ac..43a5ce91fbd0 100644 --- a/ospf6d/ospf6_area.c +++ b/ospf6d/ospf6_area.c @@ -576,8 +576,6 @@ DEFUN (area_range, range->path.u.cost_config = cost; - zlog_debug("%s: for prefix %s, flag = %x", __func__, - argv[idx_ipv6_prefixlen]->arg, range->flag); if (range->rnode == NULL) { ospf6_route_add(range, oa->range_table); } From 19b8369ca7802c41c7632e4e4ebb1f846b2f25c1 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Thu, 23 Sep 2021 01:14:27 -0300 Subject: [PATCH 072/188] ospf6d: remove redundant loop Signed-off-by: Renato Westphal --- ospf6d/ospf6_nssa.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/ospf6d/ospf6_nssa.c b/ospf6d/ospf6_nssa.c index 809768fb5ca9..7f18188861e0 100644 --- a/ospf6d/ospf6_nssa.c +++ b/ospf6d/ospf6_nssa.c @@ -262,22 +262,20 @@ static void ospf6_abr_announce_aggregates(struct ospf6 *ospf6) { struct ospf6_area *area; struct ospf6_route *range; - struct listnode *node, *nnode; + struct listnode *node; if (IS_OSPF6_DEBUG_ABR) zlog_debug("ospf6_abr_announce_aggregates(): Start"); - for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, area)) { - for (range = ospf6_route_head(area->range_table); range; - range = ospf6_route_next(range)) - ospf6_abr_range_update(range, ospf6); - } - for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, area)) { if (IS_OSPF6_DEBUG_ABR) zlog_debug( "ospf_abr_announce_aggregates(): looking at area %pI4", &area->area_id); + + for (range = ospf6_route_head(area->range_table); range; + range = ospf6_route_next(range)) + ospf6_abr_range_update(range, ospf6); } if (IS_OSPF6_DEBUG_ABR) From cdc12294fc93998f933d96c798056b47c30dbe4f Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Thu, 23 Sep 2021 01:25:56 -0300 Subject: [PATCH 073/188] ospf6d: remove unused bitfield Signed-off-by: Renato Westphal --- ospf6d/ospf6_area.c | 1 - ospf6d/ospf6_route.c | 1 - ospf6d/ospf6_route.h | 2 -- 3 files changed, 4 deletions(-) diff --git a/ospf6d/ospf6_area.c b/ospf6d/ospf6_area.c index 43a5ce91fbd0..2e04e0ee093f 100644 --- a/ospf6d/ospf6_area.c +++ b/ospf6d/ospf6_area.c @@ -306,7 +306,6 @@ struct ospf6_area *ospf6_area_create(uint32_t area_id, struct ospf6 *o, int df) oa->range_table = OSPF6_ROUTE_TABLE_CREATE(AREA, PREFIX_RANGES); oa->range_table->scope = oa; - bf_init(oa->range_table->idspace, 32); oa->summary_prefix = OSPF6_ROUTE_TABLE_CREATE(AREA, SUMMARY_PREFIXES); oa->summary_prefix->scope = oa; oa->summary_router = OSPF6_ROUTE_TABLE_CREATE(AREA, SUMMARY_ROUTERS); diff --git a/ospf6d/ospf6_route.c b/ospf6d/ospf6_route.c index 8bfd3b7124df..93e298ef340b 100644 --- a/ospf6d/ospf6_route.c +++ b/ospf6d/ospf6_route.c @@ -1100,7 +1100,6 @@ struct ospf6_route_table *ospf6_route_table_create(int s, int t) void ospf6_route_table_delete(struct ospf6_route_table *table) { ospf6_route_remove_all(table); - bf_free(table->idspace); route_table_finish(table->table); XFREE(MTYPE_OSPF6_ROUTE_TABLE, table); } diff --git a/ospf6d/ospf6_route.h b/ospf6d/ospf6_route.h index e29439b95e67..397860515b9c 100644 --- a/ospf6d/ospf6_route.h +++ b/ospf6d/ospf6_route.h @@ -241,8 +241,6 @@ struct ospf6_route_table { uint32_t count; - bitfield_t idspace; - /* hooks */ void (*hook_add)(struct ospf6_route *); void (*hook_change)(struct ospf6_route *); From a526c05525b3f53b84e69faf67e520ca542b8c86 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Thu, 23 Sep 2021 12:21:09 -0300 Subject: [PATCH 074/188] ospf6d: declare neighbor memtype as static This is the only ospf6d memtype that wasn't being declared as static. Signed-off-by: Renato Westphal --- ospf6d/ospf6_neighbor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ospf6d/ospf6_neighbor.c b/ospf6d/ospf6_neighbor.c index 6f2795a56d57..36948dc0a7cf 100644 --- a/ospf6d/ospf6_neighbor.c +++ b/ospf6d/ospf6_neighbor.c @@ -48,7 +48,7 @@ #include "ospf6_gr.h" #include "lib/json.h" -DEFINE_MTYPE(OSPF6D, OSPF6_NEIGHBOR, "OSPF6 neighbor"); +DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_NEIGHBOR, "OSPF6 neighbor"); DEFINE_HOOK(ospf6_neighbor_change, (struct ospf6_neighbor * on, int state, int next_state), From d2487a663385dc5ec8d3aa2aa590940d283196a5 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Thu, 23 Sep 2021 12:54:16 -0300 Subject: [PATCH 075/188] ospf6d: remove unnecessary code Every received or originated LSA is automatically scheduled to be refreshed periodically, there's no need to do that manually here. Signed-off-by: Renato Westphal --- ospf6d/ospf6_lsa.h | 5 --- ospf6d/ospf6_nssa.c | 101 -------------------------------------------- 2 files changed, 106 deletions(-) diff --git a/ospf6d/ospf6_lsa.h b/ospf6d/ospf6_lsa.h index 2316040694a4..c0d3cc149b47 100644 --- a/ospf6d/ospf6_lsa.h +++ b/ospf6d/ospf6_lsa.h @@ -87,11 +87,6 @@ #define OSPF6_SCOPE_AS 0x4000 #define OSPF6_SCOPE_RESERVED 0x6000 -/* AS-external-LSA refresh method. */ -#define LSA_REFRESH_IF_CHANGED 0 -#define LSA_REFRESH_FORCE 1 - - /* XXX U-bit handling should be treated here */ #define OSPF6_LSA_SCOPE(type) (ntohs(type) & OSPF6_LSTYPE_SCOPE_MASK) diff --git a/ospf6d/ospf6_nssa.c b/ospf6d/ospf6_nssa.c index 7f18188861e0..282eea852623 100644 --- a/ospf6d/ospf6_nssa.c +++ b/ospf6d/ospf6_nssa.c @@ -1061,106 +1061,6 @@ int ospf6_redistribute_check(struct ospf6 *ospf6, struct ospf6_route *route, return 1; } -static void ospf6_external_lsa_refresh_type(struct ospf6 *ospf6, uint8_t type, - unsigned short instance, int force) -{ - struct ospf6_route *route; - struct ospf6_external_info *info; - struct ospf6_lsa *lsa; - - if (type == ZEBRA_ROUTE_MAX) - return; - - for (route = ospf6_route_head(ospf6->external_table); route; - route = ospf6_route_next(route)) { - info = route->route_option; - - /* Find the external LSA in the database */ - if (!is_default_prefix(&route->prefix)) { - lsa = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL), - htonl(info->id), - ospf6->router_id, ospf6->lsdb); - - if (lsa) { - THREAD_OFF(lsa->refresh); - - /* LSA is maxage, immediate refresh */ - if (OSPF6_LSA_IS_MAXAGE(lsa)) - ospf6_flood(NULL, lsa); - else - thread_add_timer(master, - ospf6_lsa_refresh, lsa, - OSPF_LS_REFRESH_TIME, - &lsa->refresh); - } else { - /* LSA not found in the database - * Verify and originate external LSA - */ - if (ospf6_redistribute_check(ospf6, route, - type)) - ospf6_as_external_lsa_originate(route, - ospf6); - } - } - } -} - -/* Refresh default route */ -static void ospf6_external_lsa_refresh_default(struct ospf6 *ospf6) -{ - struct ospf6_route *route; - struct ospf6_external_info *info; - struct ospf6_lsa *lsa; - - for (route = ospf6_route_head(ospf6->external_table); route; - route = ospf6_route_next(route)) { - if (is_default_prefix(&route->prefix)) { - info = route->route_option; - lsa = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL), - htonl(info->id), - ospf6->router_id, ospf6->lsdb); - - if (lsa) { - if (IS_OSPF6_DEBUG_NSSA) - zlog_debug( - "LSA[Type5:0.0.0.0]: Refresh AS-external-LSA %p", - (void *)lsa); - if (OSPF6_LSA_IS_MAXAGE(lsa)) - ospf6_flood(NULL, lsa); - else - thread_add_timer(master, - ospf6_lsa_refresh, lsa, - OSPF_LS_REFRESH_TIME, - &lsa->refresh); - } else if (!lsa) { - if (IS_OSPF6_DEBUG_NSSA) - zlog_debug( - "LSA[Type5:0.0.0.0]: Originate AS-external-LSA"); - ospf6_as_external_lsa_originate(route, ospf6); - } - } - } -} - -/* If there's redistribution configured, we need to refresh external - * LSAs in order to install Type-7 and flood to all NSSA Areas - */ -void ospf6_asbr_nssa_redist_task(struct ospf6 *ospf6) -{ - int type; - struct ospf6_redist *red; - - for (type = 0; type < ZEBRA_ROUTE_MAX; type++) { - red = ospf6_redist_lookup(ospf6, type, 0); - if (!red) - return; - - ospf6_external_lsa_refresh_type(ospf6, type, red->instance, - LSA_REFRESH_IF_CHANGED); - } - ospf6_external_lsa_refresh_default(ospf6); -} - /* This function performs ABR related processing */ static int ospf6_abr_task_timer(struct thread *thread) { @@ -1176,7 +1076,6 @@ static int ospf6_abr_task_timer(struct thread *thread) ospf6_abr_task(ospf6); /* if nssa-abr, then scan Type-7 LSDB */ ospf6_abr_nssa_task(ospf6); - ospf6_asbr_nssa_redist_task(ospf6); return 0; } From 576e842480034f99b5757f0b0b63b5bbb586ccf8 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Tue, 5 Oct 2021 21:25:55 -0300 Subject: [PATCH 076/188] ospf6d: add "nssa" option to the "debug ospf6 lsa" command Signed-off-by: Renato Westphal --- ospf6d/ospf6_lsa.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ospf6d/ospf6_lsa.c b/ospf6d/ospf6_lsa.c index f406e828e1c1..77f0f8f4e56d 100644 --- a/ospf6d/ospf6_lsa.c +++ b/ospf6d/ospf6_lsa.c @@ -1070,7 +1070,7 @@ DEFPY (debug_ospf6_lsa_aggregation, DEFUN (debug_ospf6_lsa_type, debug_ospf6_lsa_hex_cmd, - "debug ospf6 lsa []", + "debug ospf6 lsa []", DEBUG_STR OSPF6_STR "Debug Link State Advertisements (LSAs)\n" @@ -1079,6 +1079,7 @@ DEFUN (debug_ospf6_lsa_type, "Display Inter-Area-Prefix LSAs\n" "Display Inter-Router LSAs\n" "Display As-External LSAs\n" + "Display NSSA LSAs\n" "Display Link LSAs\n" "Display Intra-Area-Prefix LSAs\n" "Display LSAs of unknown origin\n" @@ -1122,7 +1123,7 @@ DEFUN (debug_ospf6_lsa_type, DEFUN (no_debug_ospf6_lsa_type, no_debug_ospf6_lsa_hex_cmd, - "no debug ospf6 lsa []", + "no debug ospf6 lsa []", NO_STR DEBUG_STR OSPF6_STR @@ -1132,6 +1133,7 @@ DEFUN (no_debug_ospf6_lsa_type, "Display Inter-Area-Prefix LSAs\n" "Display Inter-Router LSAs\n" "Display As-External LSAs\n" + "Display NSSA LSAs\n" "Display Link LSAs\n" "Display Intra-Area-Prefix LSAs\n" "Display LSAs of unknown origin\n" From 5f2fe4bb77662abca01557ed5808b7d0d8612e1f Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Tue, 5 Oct 2021 21:25:55 -0300 Subject: [PATCH 077/188] ospf6d: fix selection of NSSA forwarding address Change ospf6_get_nssa_fwd_addr() to try finding a global address on any interface of the area and not on the first one only. Additionally, do a micro-optimization in ospf6_interface_get_global_address() to return as soon as a global address is found. Signed-off-by: Renato Westphal --- ospf6d/ospf6_interface.c | 6 +++--- ospf6d/ospf6_nssa.c | 12 ++++++++---- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index a3eb1445f187..9ac835b565fe 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -1241,7 +1241,6 @@ struct in6_addr *ospf6_interface_get_global_address(struct interface *ifp) { struct listnode *n; struct connected *c; - struct in6_addr *l = (struct in6_addr *)NULL; /* for each connected address */ for (ALL_LIST_ELEMENTS_RO(ifp->connected, n, c)) { @@ -1250,9 +1249,10 @@ struct in6_addr *ospf6_interface_get_global_address(struct interface *ifp) continue; if (!IN6_IS_ADDR_LINKLOCAL(&c->address->u.prefix6)) - l = &c->address->u.prefix6; + return &c->address->u.prefix6; } - return l; + + return NULL; } diff --git a/ospf6d/ospf6_nssa.c b/ospf6d/ospf6_nssa.c index 282eea852623..de0c39ba228c 100644 --- a/ospf6d/ospf6_nssa.c +++ b/ospf6d/ospf6_nssa.c @@ -1249,10 +1249,14 @@ static struct in6_addr *ospf6_get_nssa_fwd_addr(struct ospf6_area *oa) struct ospf6_interface *oi; for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi)) { - if (if_is_operative(oi->interface)) - if (oi->area && IS_AREA_NSSA(oi->area)) - return ospf6_interface_get_global_address( - oi->interface); + struct in6_addr *addr; + + if (!if_is_operative(oi->interface)) + continue; + + addr = ospf6_interface_get_global_address(oi->interface); + if (addr) + return addr; } return NULL; } From 9e49d1aca2859863cf0fc270a70a91a7cf2f08fb Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Tue, 5 Oct 2021 21:25:55 -0300 Subject: [PATCH 078/188] ospf6d: be careful to not refresh translated Type-5 LSAs twice The ABR task already takes care of refreshing translated Type-5 LSAs that correspond to self-originated Type-7 LSAs. There's no need to do that in ospf_external_lsa_install() as well. The ospfd NSSA code takes the same precaution. Signed-off-by: Renato Westphal --- ospf6d/ospf6_flood.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/ospf6d/ospf6_flood.c b/ospf6d/ospf6_flood.c index 6ad2a70f08b1..e48ed72c0532 100644 --- a/ospf6d/ospf6_flood.c +++ b/ospf6d/ospf6_flood.c @@ -266,10 +266,14 @@ void ospf6_decrement_retrans_count(struct ospf6_lsa *lsa) /* RFC2328 section 13.2 Installing LSAs in the database */ void ospf6_install_lsa(struct ospf6_lsa *lsa) { + struct ospf6 *ospf6; struct timeval now; struct ospf6_lsa *old; struct ospf6_area *area = NULL; + ospf6 = ospf6_get_by_lsdb(lsa); + assert(ospf6); + /* Remove the old instance from all neighbors' Link state retransmission list (RFC2328 13.2 last paragraph) */ old = ospf6_lsdb_lookup(lsa->header->type, lsa->header->id, @@ -330,20 +334,14 @@ void ospf6_install_lsa(struct ospf6_lsa *lsa) && !CHECK_FLAG(lsa->flag, OSPF6_LSA_DUPLICATE)) { /* check if it is new lsa ? or existing lsa got modified ?*/ - if (!old || OSPF6_LSA_IS_CHANGED(old, lsa)) { - struct ospf6 *ospf6; - - ospf6 = ospf6_get_by_lsdb(lsa); - - assert(ospf6); - + if (!old || OSPF6_LSA_IS_CHANGED(old, lsa)) ospf6_helper_handle_topo_chg(ospf6, lsa); - } } ospf6_lsdb_add(lsa, lsa->lsdb); - if (ntohs(lsa->header->type) == OSPF6_LSTYPE_TYPE_7) { + if (ntohs(lsa->header->type) == OSPF6_LSTYPE_TYPE_7 + && lsa->header->adv_router != ospf6->router_id) { area = OSPF6_AREA(lsa->lsdb->data); ospf6_translated_nssa_refresh(area, lsa, NULL); ospf6_schedule_abr_task(area->ospf6); From 05da1cbfefe165a639ab52b66d0a06745e9cdb4b Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Tue, 5 Oct 2021 21:25:55 -0300 Subject: [PATCH 079/188] ospf6d: fix processing of translated AS-external LSAs The iteration performed on ospf6_abr_unapprove_translates() was wrong since AS-external LSAs are stored in the global LSDB and not in the area LSDBs. As such, the "unapproved" flag wasn't being set in any translated AS-external LSA, leading them to linger forever. Fix the LSDB iteration and make the required changes to unset the "unapproved" flag for AS-external LSAs that shouldn't be removed. Signed-off-by: Renato Westphal --- ospf6d/ospf6_nssa.c | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/ospf6d/ospf6_nssa.c b/ospf6d/ospf6_nssa.c index de0c39ba228c..8ea48ace3ad4 100644 --- a/ospf6d/ospf6_nssa.c +++ b/ospf6d/ospf6_nssa.c @@ -379,22 +379,18 @@ static void ospf6_abr_unapprove_translates(struct ospf6 *ospf6) { struct ospf6_lsa *lsa; uint16_t type; - struct ospf6_area *oa; - struct listnode *node; if (IS_OSPF6_DEBUG_NSSA) zlog_debug("ospf6_abr_unapprove_translates(): Start"); type = htons(OSPF6_LSTYPE_AS_EXTERNAL); - for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) { - for (ALL_LSDB_TYPED(oa->lsdb, type, lsa)) { - if (CHECK_FLAG(lsa->flag, OSPF6_LSA_LOCAL_XLT)) { - SET_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED); - if (IS_OSPF6_DEBUG_NSSA) - zlog_debug( - "%s : approved unset on link id %pI4", - __func__, &lsa->header->id); - } + for (ALL_LSDB_TYPED(ospf6->lsdb, type, lsa)) { + if (CHECK_FLAG(lsa->flag, OSPF6_LSA_LOCAL_XLT)) { + SET_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED); + if (IS_OSPF6_DEBUG_NSSA) + zlog_debug( + "%s : approved unset on link id %pI4", + __func__, &lsa->header->id); } } @@ -600,6 +596,7 @@ struct ospf6_lsa *ospf6_translated_nssa_refresh(struct ospf6_area *area, __func__, &type7->header->id); return NULL; } + UNSET_FLAG(new->flag, OSPF6_LSA_UNAPPROVED); } if (IS_OSPF6_DEBUG_NSSA) @@ -692,16 +689,13 @@ int ospf6_abr_translate_nssa(struct ospf6_area *area, struct ospf6_lsa *lsa) ospf6->lsdb); } - if (old) { - /* Do not continue if type 5 LSA not approved */ - if (CHECK_FLAG(old->flag, OSPF6_LSA_UNAPPROVED)) { - if (IS_OSPF6_DEBUG_NSSA) - zlog_debug( - "%s : LSA Id %pI4 type 5 is not approved", - __func__, &old->header->id); - return 1; - } + if (OSPF6_LSA_IS_MAXAGE(lsa)) { + if (old) + ospf6_lsa_premature_aging(old); + return; + } + if (old) { if (IS_OSPF6_DEBUG_NSSA) zlog_debug( "%s : found old translated LSA Id %pI4, refreshing", From c8093b99bfdf17f2fe47d0fc556af60f73b36517 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Tue, 5 Oct 2021 21:25:55 -0300 Subject: [PATCH 080/188] ospf6d: remove incomplete support for NSSA ranges This code tries to summarize NSSA Type-7 LSAs using normal ranges which are intended to summarize Type-3 LSAs only. This is not only wrong, but the code is incomplete and lacking lots of things. Better to remove it before implementing NSSA ranges correctly. Signed-off-by: Renato Westphal --- ospf6d/ospf6_nssa.c | 83 --------------------------------------------- 1 file changed, 83 deletions(-) diff --git a/ospf6d/ospf6_nssa.c b/ospf6d/ospf6_nssa.c index 8ea48ace3ad4..b35a04545afd 100644 --- a/ospf6d/ospf6_nssa.c +++ b/ospf6d/ospf6_nssa.c @@ -776,59 +776,6 @@ static void ospf6_abr_process_nssa_translates(struct ospf6 *ospf6) zlog_debug("%s : Stop", __func__); } -/* Generate translated type-5 LSA from the configured area ranges*/ -static void ospf6_abr_translate_nssa_range(struct ospf6 *ospf6) -{ - struct listnode *node, *nnode; - struct ospf6_area *oa; - struct ospf6_route *range; - struct ospf6_lsa *lsa; - - for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) { - for (range = ospf6_route_head(oa->range_table); range; - range = ospf6_route_next(range)) { - if (IS_OSPF6_DEBUG_NSSA) - zlog_debug( - "Translating range %pFX of area %pI4", - &range->prefix, &oa->area_id); - if (CHECK_FLAG(range->flag, - OSPF6_ROUTE_DO_NOT_ADVERTISE)) - continue; - - /* Find the NSSA LSA from the route */ - /* Generate and flood external LSA */ - lsa = ospf6_lsdb_lookup(OSPF6_LSTYPE_TYPE_7, - range->path.origin.id, - ospf6->router_id, oa->lsdb); - if (lsa) - ospf6_abr_translate_nssa(oa, lsa); - } - } -} - -static void ospf6_abr_send_nssa_aggregates(struct ospf6 *ospf6) -{ - struct listnode *node; - struct ospf6_area *area; - - if (IS_OSPF6_DEBUG_NSSA) - zlog_debug("%s : Start", __func__); - - for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, area)) { - if (area->NSSATranslatorState == OSPF6_NSSA_TRANSLATE_DISABLED) - continue; - - if (IS_OSPF6_DEBUG_NSSA) - zlog_debug("%s : looking at area %pI4", __func__, - &area->area_id); - - ospf6_abr_translate_nssa_range(ospf6); - } - - if (IS_OSPF6_DEBUG_NSSA) - zlog_debug("%s : Stop", __func__); -} - /*Flood max age LSA's for the unapproved LSA's */ static int ospf6_abr_remove_unapproved_translates_apply(struct ospf6_lsa *lsa) { @@ -940,11 +887,6 @@ void ospf6_abr_nssa_type_7_defaults(struct ospf6 *ospf6) static void ospf6_abr_nssa_task(struct ospf6 *ospf6) { - /* called only if any_nssa */ - struct ospf6_route *range; - struct ospf6_area *area; - struct listnode *node, *nnode; - if (IS_OSPF6_DEBUG_NSSA) zlog_debug("Check for NSSA-ABR Tasks():"); @@ -970,11 +912,6 @@ static void ospf6_abr_nssa_task(struct ospf6 *ospf6) ospf6_abr_unapprove_translates(ospf6); - /* RESET all Ranges in every Area, same as summaries */ - if (IS_OSPF6_DEBUG_NSSA) - zlog_debug("ospf6_abr_nssa_task(): NSSA initialize aggregates"); - ospf6_abr_range_reset_cost(ospf6); - /* For all NSSAs, Type-7s, translate to 5's, INSTALL/FLOOD, or * Aggregate as Type-7 * Install or Approve in Type-5 Global LSDB @@ -983,32 +920,12 @@ static void ospf6_abr_nssa_task(struct ospf6 *ospf6) zlog_debug("ospf6_abr_nssa_task(): process translates"); ospf6_abr_process_nssa_translates(ospf6); - /* Translate/Send any "ranged" aggregates, and also 5-Install and - * Approve - * Scan Type-7's for aggregates, translate to Type-5's, - * Install/Flood/Approve - */ - if (IS_OSPF6_DEBUG_NSSA) - zlog_debug("ospf6_abr_nssa_task(): send NSSA aggregates"); - ospf6_abr_send_nssa_aggregates(ospf6); /*TURNED OFF FOR NOW */ - /* Flush any unapproved previous translates from Global Data Base */ if (IS_OSPF6_DEBUG_NSSA) zlog_debug( "ospf6_abr_nssa_task(): remove unapproved translates"); ospf6_abr_remove_unapproved_translates(ospf6); - for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, area)) { - for (range = ospf6_route_head(area->range_table); range; - range = ospf6_route_next(range)) { - if (CHECK_FLAG(range->flag, - OSPF6_ROUTE_DO_NOT_ADVERTISE)) - ospf6_zebra_delete_discard(range, ospf6); - else - ospf6_zebra_add_discard(range, ospf6); - } - } - if (IS_OSPF6_DEBUG_NSSA) zlog_debug("ospf6_abr_nssa_task(): Stop"); } From 14bb568af0f734aa6ee8d3ed9ad269e810f6e32f Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Tue, 5 Oct 2021 21:25:55 -0300 Subject: [PATCH 081/188] ospf6d: fix memleak when translating NSSA LSA Stop leaking 4096 bytes for each translated LSA. Signed-off-by: Renato Westphal --- ospf6d/ospf6_nssa.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ospf6d/ospf6_nssa.c b/ospf6d/ospf6_nssa.c index b35a04545afd..f43397fd2649 100644 --- a/ospf6d/ospf6_nssa.c +++ b/ospf6d/ospf6_nssa.c @@ -402,7 +402,7 @@ static void ospf6_abr_unapprove_translates(struct ospf6 *ospf6) static struct ospf6_lsa *ospf6_lsa_translated_nssa_new(struct ospf6_area *area, struct ospf6_lsa *type7) { - char *buffer; + char buffer[OSPF6_MAX_LSASIZE]; struct ospf6_lsa *lsa; struct ospf6_as_external_lsa *ext, *extnew; struct ospf6_lsa_header *lsa_header; @@ -424,7 +424,8 @@ static struct ospf6_lsa *ospf6_lsa_translated_nssa_new(struct ospf6_area *area, return NULL; } - buffer = XCALLOC(MTYPE_OSPF6_LSA, OSPF6_MAX_LSASIZE); + /* prepare buffer */ + memset(buffer, 0, sizeof(buffer)); lsa_header = (struct ospf6_lsa_header *)buffer; extnew = (struct ospf6_as_external_lsa *)((caddr_t)lsa_header From 7270e0edf3b040cc9a7a430f2a1581923e27cd44 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Tue, 5 Oct 2021 21:25:55 -0300 Subject: [PATCH 082/188] ospf6d: remove unnecessary check when translating Type-7 LSA In addition to being unnecessary, this check is problematic for the upcoming NSSA ranges feature since NSSA ranges aren't added to the OSPF routing table. Remove this for simplicity. Signed-off-by: Renato Westphal --- ospf6d/ospf6_nssa.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/ospf6d/ospf6_nssa.c b/ospf6d/ospf6_nssa.c index f43397fd2649..c02e7fcbc037 100644 --- a/ospf6d/ospf6_nssa.c +++ b/ospf6d/ospf6_nssa.c @@ -409,7 +409,6 @@ static struct ospf6_lsa *ospf6_lsa_translated_nssa_new(struct ospf6_area *area, caddr_t old_ptr, new_ptr; struct ospf6_as_external_lsa *nssa; struct prefix prefix; - struct ospf6_route *match; struct ospf6 *ospf6 = area->ospf6; ptrdiff_t tag_offset = 0; route_tag_t network_order; @@ -448,15 +447,6 @@ static struct ospf6_lsa *ospf6_lsa_translated_nssa_new(struct ospf6_area *area, prefix.prefixlen = nssa->prefix.prefix_length; ospf6_prefix_in6_addr(&prefix.u.prefix6, nssa, &nssa->prefix); - /* Find the LSA from the external route */ - match = ospf6_route_lookup(&prefix, area->route_table); - if (match == NULL) { - if (IS_OSPF6_DEBUG_NSSA) - zlog_debug("%s : no matching route %pFX", __func__, - &prefix); - return NULL; - } - /* set Prefix */ memcpy(new_ptr, old_ptr, OSPF6_PREFIX_SPACE(ext->prefix.prefix_length)); ospf6_prefix_apply_mask(&extnew->prefix); From 8ee9d58b0d67fc918259ef69f106586bd0a3a6da Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Tue, 5 Oct 2021 21:25:55 -0300 Subject: [PATCH 083/188] ospf6d: assorted code cleanup This commits consists of several changes that positively impact code reability without introducing any logical change. Summary of the changes: * Return earlier in ospf6_abr_range_update() in order to reduce one level of indentation; * Remove ospf6_translated_nssa_originate() since it's nothing other than a useless wrapper around ospf6_lsa_translated_nssa_new(); * Change ospf6_abr_translate_nssa() to return void; * Change ospf6_abr_process_nssa_translates() checking for NSSA areas before anything else; * Remove ospf6_abr_remove_unapproved_translates_apply() since it's a small function that is only called in one place; * Change ospf6_abr_check_translate_nssa() to avoid an LSDB lookup when the router isn't an ABR. Signed-off-by: Renato Westphal --- ospf6d/ospf6_abr.c | 47 ++++++++++++++--------------- ospf6d/ospf6_nssa.c | 73 +++++++++++++-------------------------------- ospf6d/ospf6_nssa.h | 4 --- 3 files changed, 43 insertions(+), 81 deletions(-) diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c index 0b2c14bc5430..690a0dd254e0 100644 --- a/ospf6d/ospf6_abr.c +++ b/ospf6d/ospf6_abr.c @@ -681,34 +681,31 @@ void ospf6_abr_range_update(struct ospf6_route *range, struct ospf6 *ospf6) * if there * were active ranges. */ + if (!ospf6_abr_range_summary_needs_update(range, cost)) + return; - if (ospf6_abr_range_summary_needs_update(range, cost)) { - if (IS_OSPF6_DEBUG_ABR) - zlog_debug("%s: range %pFX update", __func__, - &range->prefix); - for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) - summary_orig += - ospf6_abr_originate_summary_to_area(range, oa); - - if (CHECK_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY) - && summary_orig) { - if (!CHECK_FLAG(range->flag, - OSPF6_ROUTE_BLACKHOLE_ADDED)) { - if (IS_OSPF6_DEBUG_ABR) - zlog_debug("Add discard route"); + if (IS_OSPF6_DEBUG_ABR) + zlog_debug("%s: range %pFX update", __func__, &range->prefix); - ospf6_zebra_add_discard(range, ospf6); - } - } else { - /* Summary removed or no summary generated as no - * specifics exist */ - if (CHECK_FLAG(range->flag, - OSPF6_ROUTE_BLACKHOLE_ADDED)) { - if (IS_OSPF6_DEBUG_ABR) - zlog_debug("Delete discard route"); + for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) + summary_orig += ospf6_abr_originate_summary_to_area(range, oa); - ospf6_zebra_delete_discard(range, ospf6); - } + if (CHECK_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY) + && summary_orig) { + if (!CHECK_FLAG(range->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) { + if (IS_OSPF6_DEBUG_ABR) + zlog_debug("Add discard route"); + + ospf6_zebra_add_discard(range, ospf6); + } + } else { + /* Summary removed or no summary generated as no + * specifics exist */ + if (CHECK_FLAG(range->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) { + if (IS_OSPF6_DEBUG_ABR) + zlog_debug("Delete discard route"); + + ospf6_zebra_delete_discard(range, ospf6); } } } diff --git a/ospf6d/ospf6_nssa.c b/ospf6d/ospf6_nssa.c index c02e7fcbc037..7ab14fe4ad9f 100644 --- a/ospf6d/ospf6_nssa.c +++ b/ospf6d/ospf6_nssa.c @@ -596,27 +596,7 @@ struct ospf6_lsa *ospf6_translated_nssa_refresh(struct ospf6_area *area, return new; } -/* Originate Translated Type-5 for supplied Type-7 NSSA LSA */ -struct ospf6_lsa *ospf6_translated_nssa_originate(struct ospf6_area *oa, - struct ospf6_lsa *type7) -{ - struct ospf6_lsa *new; - - if (ntohs(type7->header->type) != OSPF6_LSTYPE_TYPE_7) - return NULL; - - if ((new = ospf6_lsa_translated_nssa_new(oa, type7)) == NULL) { - if (IS_OSPF6_DEBUG_NSSA) - zlog_debug( - "%s : Could not translate Type-7, Id %pI4, to Type-5", - __func__, &type7->header->id); - return NULL; - } - - return new; -} - -int ospf6_abr_translate_nssa(struct ospf6_area *area, struct ospf6_lsa *lsa) +static void ospf6_abr_translate_nssa(struct ospf6_area *area, struct ospf6_lsa *lsa) { /* Incoming Type-7 or later aggregated Type-7 * @@ -645,7 +625,7 @@ int ospf6_abr_translate_nssa(struct ospf6_area *area, struct ospf6_lsa *lsa) zlog_debug( "%s : LSA Id %pI4, P-bit off, NO Translation", __func__, &lsa->header->id); - return 1; + return; } if (IS_OSPF6_DEBUG_NSSA) @@ -662,7 +642,7 @@ int ospf6_abr_translate_nssa(struct ospf6_area *area, struct ospf6_lsa *lsa) zlog_debug( "%s : LSA Id %pI4, Forward address is 0, NO Translation", __func__, &lsa->header->id); - return 1; + return; } /* Find the existing AS-External LSA for this prefix */ @@ -705,16 +685,14 @@ int ospf6_abr_translate_nssa(struct ospf6_area *area, struct ospf6_lsa *lsa) * originate translated LSA */ - if (ospf6_translated_nssa_originate(area, lsa) == NULL) { + if (ospf6_lsa_translated_nssa_new(area, lsa) == NULL) { if (IS_OSPF6_DEBUG_NSSA) zlog_debug( "%s : Could not translate Type-7 for %pI4 to Type-5", __func__, &lsa->header->id); - return 1; + return; } } - - return 0; } static void ospf6_abr_process_nssa_translates(struct ospf6 *ospf6) @@ -734,6 +712,8 @@ static void ospf6_abr_process_nssa_translates(struct ospf6 *ospf6) zlog_debug("%s : Start", __func__); for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) { + if (!IS_AREA_NSSA(oa)) + continue; /* skip if not translator */ if (oa->NSSATranslatorState == OSPF6_NSSA_TRANSLATE_DISABLED) { @@ -743,13 +723,6 @@ static void ospf6_abr_process_nssa_translates(struct ospf6 *ospf6) continue; } - /* skip if not Nssa Area */ - if (!IS_AREA_NSSA(oa)) { - zlog_debug("%s area %pI4 Flag %x", __func__, - &oa->area_id, oa->flag); - continue; - } - if (IS_OSPF6_DEBUG_NSSA) zlog_debug("%s : looking at area %pI4", __func__, &oa->area_id); @@ -767,20 +740,6 @@ static void ospf6_abr_process_nssa_translates(struct ospf6 *ospf6) zlog_debug("%s : Stop", __func__); } -/*Flood max age LSA's for the unapproved LSA's */ -static int ospf6_abr_remove_unapproved_translates_apply(struct ospf6_lsa *lsa) -{ - if (CHECK_FLAG(lsa->flag, OSPF6_LSA_LOCAL_XLT) - && CHECK_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED)) { - zlog_debug("%s : removing unapproved translates, lsa : %s", - __func__, lsa->name); - - /* FLUSH THROUGHOUT AS */ - ospf6_lsa_premature_aging(lsa); - } - return 0; -} - static void ospf6_abr_remove_unapproved_translates(struct ospf6 *ospf6) { struct ospf6_lsa *lsa; @@ -792,8 +751,16 @@ static void ospf6_abr_remove_unapproved_translates(struct ospf6 *ospf6) zlog_debug("ospf6_abr_remove_unapproved_translates(): Start"); type = htons(OSPF6_LSTYPE_AS_EXTERNAL); - for (ALL_LSDB_TYPED(ospf6->lsdb, type, lsa)) - ospf6_abr_remove_unapproved_translates_apply(lsa); + for (ALL_LSDB_TYPED(ospf6->lsdb, type, lsa)) { + if (CHECK_FLAG(lsa->flag, OSPF6_LSA_LOCAL_XLT) + && CHECK_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED)) { + zlog_debug( + "%s : removing unapproved translates, lsa : %s", + __func__, lsa->name); + + ospf6_lsa_premature_aging(lsa); + } + } if (IS_OSPF6_DEBUG_NSSA) zlog_debug("ospf_abr_remove_unapproved_translates(): Stop"); @@ -1268,11 +1235,13 @@ void ospf6_abr_check_translate_nssa(struct ospf6_area *area, if (IS_OSPF6_DEBUG_NSSA) zlog_debug("%s : start", __func__); + if (!ospf6_check_and_set_router_abr(ospf6)) + return; + type5 = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL), lsa->external_lsa_id, ospf6->router_id, ospf6->lsdb); - - if (ospf6_check_and_set_router_abr(ospf6) && (type5 == NULL)) { + if (!type5) { if (IS_OSPF6_DEBUG_NSSA) zlog_debug("%s : Originating type5 LSA", __func__); ospf6_lsa_translated_nssa_new(area, lsa); diff --git a/ospf6d/ospf6_nssa.h b/ospf6d/ospf6_nssa.h index 99cb04c0031f..02234cc8bd91 100644 --- a/ospf6d/ospf6_nssa.h +++ b/ospf6d/ospf6_nssa.h @@ -55,8 +55,6 @@ extern void ospf6_nssa_lsa_flush(struct ospf6 *ospf6, struct prefix_ipv6 *p); extern struct ospf6_lsa *ospf6_translated_nssa_refresh(struct ospf6_area *oa, struct ospf6_lsa *type7, struct ospf6_lsa *type5); -extern struct ospf6_lsa * -ospf6_translated_nssa_originate(struct ospf6_area *oa, struct ospf6_lsa *type7); extern void ospf6_asbr_nssa_redist_task(struct ospf6 *ospf6); @@ -69,8 +67,6 @@ extern void install_element_ospf6_debug_nssa(void); extern void ospf6_abr_nssa_type_7_defaults(struct ospf6 *osof6); int ospf6_redistribute_check(struct ospf6 *ospf6, struct ospf6_route *route, int type); -extern int ospf6_abr_translate_nssa(struct ospf6_area *area, - struct ospf6_lsa *lsa); extern void ospf6_abr_check_translate_nssa(struct ospf6_area *area, struct ospf6_lsa *lsa); extern void ospf6_abr_nssa_check_status(struct ospf6 *ospf6); From 2ad3c6dbbe562096cf87b6c51ea093ed608b44de Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Tue, 5 Oct 2021 21:25:55 -0300 Subject: [PATCH 084/188] ospf6d: fix lookup of translated Type-5 LSA Type-7 LSAs and their corresponding Type-5 LSAs don't share the same LS IDs (unlike in the case of OSPFv2). As such, do not attempt to find a translated Type-5 LSA using the LS ID of a Type-7 LSA. Instead, use the LS-ID stored in the OSPF routing table. Signed-off-by: Renato Westphal --- ospf6d/ospf6_nssa.c | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/ospf6d/ospf6_nssa.c b/ospf6d/ospf6_nssa.c index 7ab14fe4ad9f..3f555577e571 100644 --- a/ospf6d/ospf6_nssa.c +++ b/ospf6d/ospf6_nssa.c @@ -527,7 +527,6 @@ struct ospf6_lsa *ospf6_translated_nssa_refresh(struct ospf6_area *area, struct ospf6_lsa *type5) { struct ospf6_lsa *new = NULL; - struct ospf6_as_external_lsa *ext_lsa; struct prefix prefix; struct ospf6 *ospf6 = area->ospf6; @@ -539,27 +538,27 @@ struct ospf6_lsa *ospf6_translated_nssa_refresh(struct ospf6_area *area, /* Find the AS external LSA */ if (type5 == NULL) { + struct ospf6_as_external_lsa *ext_lsa; + struct ospf6_route *match; + + /* Find the AS external LSA from Type-7 LSA */ if (IS_OSPF6_DEBUG_NSSA) zlog_debug( - "%s: No translated Type-5 found for Type-7 with Id %pI4", - __func__, &type7->header->id); + "%s: try to find translated Type-5 LSA for %s", + __func__, type7->name); - /* find the translated Type-5 for this Type-7 */ ext_lsa = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END( type7->header); - prefix.family = AF_INET6; prefix.prefixlen = ext_lsa->prefix.prefix_length; ospf6_prefix_in6_addr(&prefix.u.prefix6, ext_lsa, &ext_lsa->prefix); - /* Find the AS external LSA from Type-7 LSA */ - if (IS_OSPF6_DEBUG_NSSA) - zlog_debug("%s: try to find external LSA id %d", - __func__, type7->external_lsa_id); - type5 = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL), - type7->external_lsa_id, - ospf6->router_id, ospf6->lsdb); + match = ospf6_route_lookup(&prefix, ospf6->external_table); + if (match) + type5 = ospf6_lsdb_lookup( + OSPF6_LSTYPE_AS_EXTERNAL, match->path.origin.id, + ospf6->router_id, ospf6->lsdb); } if (type5) { @@ -653,13 +652,6 @@ static void ospf6_abr_translate_nssa(struct ospf6_area *area, struct ospf6_lsa * ospf6->lsdb); } - /* Check Type 5 LSA using the matching external ID */ - if (old == NULL) { - old = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL), - lsa->external_lsa_id, ospf6->router_id, - ospf6->lsdb); - } - if (OSPF6_LSA_IS_MAXAGE(lsa)) { if (old) ospf6_lsa_premature_aging(old); From 3c77bc809fac8e3a564a6c2ecb380e3917085dcc Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Tue, 5 Oct 2021 21:25:55 -0300 Subject: [PATCH 085/188] ospf6d: add support for NSSA Type-7 address ranges Implement NSSA address ranges as specified by RFC 3101: NSSA border routers may be configured with Type-7 address ranges. Each Type-7 address range is defined as an [address,mask] pair. Many separate Type-7 networks may fall into a single Type-7 address range, just as a subnetted network is composed of many separate subnets. NSSA border routers may aggregate Type-7 routes by advertising a single Type-5 LSA for each Type-7 address range. The Type-5 LSA resulting from a Type-7 address range match will be distributed to all Type-5 capable areas. Syntax: area A.B.C.D nssa range X:X::X:X/M [] Example: router ospf6 ospf6 router-id 1.1.1.1 area 1 nssa area 1 nssa range 2001:db8:1000::/64 area 1 nssa range 2001:db8:2000::/64 ! Signed-off-by: Renato Westphal --- doc/user/ospf6d.rst | 15 ++++ ospf6d/ospf6_abr.c | 47 ++++++++++-- ospf6d/ospf6_area.c | 19 +++++ ospf6d/ospf6_area.h | 1 + ospf6d/ospf6_nssa.c | 173 ++++++++++++++++++++++++++++++++++++++++--- ospf6d/ospf6_route.h | 19 ++--- ospf6d/subdir.am | 1 + 7 files changed, 250 insertions(+), 25 deletions(-) diff --git a/doc/user/ospf6d.rst b/doc/user/ospf6d.rst index d823c5d5b547..4e232235968a 100644 --- a/doc/user/ospf6d.rst +++ b/doc/user/ospf6d.rst @@ -204,6 +204,21 @@ OSPF6 area existence of a default route in the RIB that wasn't learned via the OSPF protocol. +.. clicmd:: area A.B.C.D nssa range X:X::X:X/M [] + +.. clicmd:: area (0-4294967295) nssa range X:X::X:X/M [] + + Summarize a group of external subnets into a single Type-7 LSA, which is + then translated to a Type-5 LSA and avertised to the backbone. + This command can only be used at the area boundary (NSSA ABR router). + + By default, the metric of the summary route is calculated as the highest + metric among the summarized routes. The `cost` option, however, can be used + to set an explicit metric. + + The `not-advertise` option, when present, prevents the summary route from + being advertised, effectively filtering the summarized routes. + .. clicmd:: area A.B.C.D export-list NAME .. clicmd:: area (0-4294967295) export-list NAME diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c index 690a0dd254e0..ddc71b3bbf18 100644 --- a/ospf6d/ospf6_abr.c +++ b/ospf6d/ospf6_abr.c @@ -593,10 +593,14 @@ void ospf6_abr_range_reset_cost(struct ospf6 *ospf6) struct ospf6_area *oa; struct ospf6_route *range; - for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) + for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) { for (range = ospf6_route_head(oa->range_table); range; range = ospf6_route_next(range)) OSPF6_ABR_RANGE_CLEAR_COST(range); + for (range = ospf6_route_head(oa->nssa_range_table); range; + range = ospf6_route_next(range)) + OSPF6_ABR_RANGE_CLEAR_COST(range); + } } static inline uint32_t ospf6_abr_range_compute_cost(struct ospf6_route *range, @@ -607,10 +611,19 @@ static inline uint32_t ospf6_abr_range_compute_cost(struct ospf6_route *range, for (ro = ospf6_route_match_head(&range->prefix, o->route_table); ro; ro = ospf6_route_match_next(&range->prefix, ro)) { - if (ro->path.area_id == range->path.area_id - && (ro->path.type == OSPF6_PATH_TYPE_INTRA) - && !CHECK_FLAG(ro->flag, OSPF6_ROUTE_REMOVE)) - cost = MAX(cost, ro->path.cost); + if (CHECK_FLAG(ro->flag, OSPF6_ROUTE_REMOVE)) + continue; + if (ro->path.area_id != range->path.area_id) + continue; + if (CHECK_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE) + && ro->path.type != OSPF6_PATH_TYPE_EXTERNAL1 + && ro->path.type != OSPF6_PATH_TYPE_EXTERNAL2) + continue; + if (!CHECK_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE) + && ro->path.type != OSPF6_PATH_TYPE_INTRA) + continue; + + cost = MAX(cost, ro->path.cost); } return cost; @@ -659,6 +672,8 @@ void ospf6_abr_range_update(struct ospf6_route *range, struct ospf6 *ospf6) int summary_orig = 0; assert(range->type == OSPF6_DEST_TYPE_RANGE); + oa = ospf6_area_lookup(range->path.area_id, ospf6); + assert(oa); /* update range's cost and active flag */ cost = ospf6_abr_range_compute_cost(range, ospf6); @@ -687,8 +702,26 @@ void ospf6_abr_range_update(struct ospf6_route *range, struct ospf6 *ospf6) if (IS_OSPF6_DEBUG_ABR) zlog_debug("%s: range %pFX update", __func__, &range->prefix); - for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) - summary_orig += ospf6_abr_originate_summary_to_area(range, oa); + if (CHECK_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE)) { + if (CHECK_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY) + && !CHECK_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE)) { + ospf6_nssa_lsa_originate(range, oa, true); + summary_orig = 1; + } else { + struct ospf6_lsa *lsa; + + lsa = ospf6_lsdb_lookup(range->path.origin.type, + range->path.origin.id, + ospf6->router_id, oa->lsdb); + if (lsa) + ospf6_lsa_premature_aging(lsa); + } + } else { + for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) { + summary_orig += + ospf6_abr_originate_summary_to_area(range, oa); + } + } if (CHECK_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY) && summary_orig) { diff --git a/ospf6d/ospf6_area.c b/ospf6d/ospf6_area.c index 2e04e0ee093f..996892c49ca3 100644 --- a/ospf6d/ospf6_area.c +++ b/ospf6d/ospf6_area.c @@ -306,6 +306,8 @@ struct ospf6_area *ospf6_area_create(uint32_t area_id, struct ospf6 *o, int df) oa->range_table = OSPF6_ROUTE_TABLE_CREATE(AREA, PREFIX_RANGES); oa->range_table->scope = oa; + oa->nssa_range_table = OSPF6_ROUTE_TABLE_CREATE(AREA, PREFIX_RANGES); + oa->nssa_range_table->scope = oa; oa->summary_prefix = OSPF6_ROUTE_TABLE_CREATE(AREA, SUMMARY_PREFIXES); oa->summary_prefix->scope = oa; oa->summary_router = OSPF6_ROUTE_TABLE_CREATE(AREA, SUMMARY_ROUTERS); @@ -360,6 +362,7 @@ void ospf6_area_delete(struct ospf6_area *oa) ospf6_route_table_delete(oa->route_table); ospf6_route_table_delete(oa->range_table); + ospf6_route_table_delete(oa->nssa_range_table); ospf6_route_table_delete(oa->summary_prefix); ospf6_route_table_delete(oa->summary_router); @@ -691,6 +694,22 @@ void ospf6_area_config_write(struct vty *vty, struct ospf6 *ospf6) vty_out(vty, " no-summary"); vty_out(vty, "\n"); } + for (range = ospf6_route_head(oa->nssa_range_table); range; + range = ospf6_route_next(range)) { + vty_out(vty, " area %s nssa range %pFX", oa->name, + &range->prefix); + + if (CHECK_FLAG(range->flag, + OSPF6_ROUTE_DO_NOT_ADVERTISE)) { + vty_out(vty, " not-advertise"); + } else { + if (range->path.u.cost_config + != OSPF_AREA_RANGE_COST_UNSPEC) + vty_out(vty, " cost %u", + range->path.u.cost_config); + } + vty_out(vty, "\n"); + } if (PREFIX_NAME_IN(oa)) vty_out(vty, " area %s filter-list prefix %s in\n", oa->name, PREFIX_NAME_IN(oa)); diff --git a/ospf6d/ospf6_area.h b/ospf6d/ospf6_area.h index 77cbad8b9ea5..905fbac94956 100644 --- a/ospf6d/ospf6_area.h +++ b/ospf6d/ospf6_area.h @@ -46,6 +46,7 @@ struct ospf6_area { /* Summary routes to be originated (includes Configured Address Ranges) */ struct ospf6_route_table *range_table; + struct ospf6_route_table *nssa_range_table; struct ospf6_route_table *summary_prefix; struct ospf6_route_table *summary_router; diff --git a/ospf6d/ospf6_nssa.c b/ospf6d/ospf6_nssa.c index 3f555577e571..43bf1b06b385 100644 --- a/ospf6d/ospf6_nssa.c +++ b/ospf6d/ospf6_nssa.c @@ -49,6 +49,9 @@ #include "ospf6_asbr.h" #include "ospf6d.h" #include "ospf6_nssa.h" +#ifndef VTYSH_EXTRACT_PL +#include "ospf6d/ospf6_nssa_clippy.c" +#endif DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_LSA, "OSPF6 LSA"); unsigned char config_debug_ospf6_nssa = 0; @@ -412,6 +415,7 @@ static struct ospf6_lsa *ospf6_lsa_translated_nssa_new(struct ospf6_area *area, struct ospf6 *ospf6 = area->ospf6; ptrdiff_t tag_offset = 0; route_tag_t network_order; + struct ospf6_route *range; if (IS_OSPF6_DEBUG_NSSA) zlog_debug("%s : Start", __func__); @@ -423,6 +427,25 @@ static struct ospf6_lsa *ospf6_lsa_translated_nssa_new(struct ospf6_area *area, return NULL; } + /* find the translated Type-5 for this Type-7 */ + nssa = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END( + type7->header); + prefix.family = AF_INET6; + prefix.prefixlen = nssa->prefix.prefix_length; + ospf6_prefix_in6_addr(&prefix.u.prefix6, nssa, &nssa->prefix); + + /* Check if the Type-7 LSA should be suppressed by aggregation. */ + range = ospf6_route_lookup_bestmatch(&prefix, area->nssa_range_table); + if (range && !prefix_same(&prefix, &range->prefix) + && !CHECK_FLAG(range->flag, OSPF6_ROUTE_REMOVE)) { + if (IS_OSPF6_DEBUG_NSSA) + zlog_debug( + "%s: LSA %s suppressed by range %pFX of area %s", + __func__, type7->name, &range->prefix, + area->name); + return NULL; + } + /* prepare buffer */ memset(buffer, 0, sizeof(buffer)); lsa_header = (struct ospf6_lsa_header *)buffer; @@ -439,14 +462,6 @@ static struct ospf6_lsa *ospf6_lsa_translated_nssa_new(struct ospf6_area *area, memcpy(extnew, ext, sizeof(struct ospf6_as_external_lsa)); - /* find the translated Type-5 for this Type-7 */ - nssa = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END( - type7->header); - - prefix.family = AF_INET6; - prefix.prefixlen = nssa->prefix.prefix_length; - ospf6_prefix_in6_addr(&prefix.u.prefix6, nssa, &nssa->prefix); - /* set Prefix */ memcpy(new_ptr, old_ptr, OSPF6_PREFIX_SPACE(ext->prefix.prefix_length)); ospf6_prefix_apply_mask(&extnew->prefix); @@ -600,7 +615,6 @@ static void ospf6_abr_translate_nssa(struct ospf6_area *area, struct ospf6_lsa * /* Incoming Type-7 or later aggregated Type-7 * * LSA is skipped if P-bit is off. - * LSA is aggregated if within range. * * The Type-7 is translated, Installed/Approved as a Type-5 into * global LSDB, then Flooded through AS @@ -732,6 +746,32 @@ static void ospf6_abr_process_nssa_translates(struct ospf6 *ospf6) zlog_debug("%s : Stop", __func__); } +static void ospf6_abr_send_nssa_aggregates(struct ospf6 *ospf6) +{ + struct listnode *node; + struct ospf6_area *area; + struct ospf6_route *range; + + if (IS_OSPF6_DEBUG_NSSA) + zlog_debug("%s: Start", __func__); + + for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, area)) { + if (area->NSSATranslatorState == OSPF6_NSSA_TRANSLATE_DISABLED) + continue; + + if (IS_OSPF6_DEBUG_NSSA) + zlog_debug("%s: looking at area %pI4", __func__, + &area->area_id); + + for (range = ospf6_route_head(area->nssa_range_table); range; + range = ospf6_route_next(range)) + ospf6_abr_range_update(range, ospf6); + } + + if (IS_OSPF6_DEBUG_NSSA) + zlog_debug("%s: Stop", __func__); +} + static void ospf6_abr_remove_unapproved_translates(struct ospf6 *ospf6) { struct ospf6_lsa *lsa; @@ -862,6 +902,11 @@ static void ospf6_abr_nssa_task(struct ospf6 *ospf6) ospf6_abr_unapprove_translates(ospf6); + /* Originate Type-7 aggregates */ + if (IS_OSPF6_DEBUG_NSSA) + zlog_debug("ospf6_abr_nssa_task(): send NSSA aggregates"); + ospf6_abr_send_nssa_aggregates(ospf6); + /* For all NSSAs, Type-7s, translate to 5's, INSTALL/FLOOD, or * Aggregate as Type-7 * Install or Approve in Type-5 Global LSDB @@ -1097,6 +1142,13 @@ int ospf6_area_nssa_unset(struct ospf6 *ospf6, struct ospf6_area *area) UNSET_FLAG(area->flag, OSPF6_AREA_NSSA); if (IS_OSPF6_DEBUG_NSSA) zlog_debug("area %s nssa reset", area->name); + + /* Clear the table of NSSA ranges. */ + ospf6_route_table_delete(area->nssa_range_table); + area->nssa_range_table = + OSPF6_ROUTE_TABLE_CREATE(AREA, PREFIX_RANGES); + area->nssa_range_table->scope = area; + ospf6_area_nssa_update(area); } @@ -1240,6 +1292,106 @@ void ospf6_abr_check_translate_nssa(struct ospf6_area *area, } } +DEFPY (area_nssa_range, + area_nssa_range_cmd, + "area $area nssa range X:X::X:X/M$prefix []", + "OSPF6 area parameters\n" + "OSPF6 area ID in IP address format\n" + "OSPF6 area ID as a decimal value\n" + "Configure OSPF6 area as nssa\n" + "Configured address range\n" + "Specify IPv6 prefix\n" + "Do not advertise\n" + "User specified metric for this range\n" + "Advertised metric for this range\n") +{ + struct ospf6_area *oa; + struct ospf6_route *range; + + VTY_DECLVAR_CONTEXT(ospf6, ospf6); + + OSPF6_CMD_AREA_GET(area, oa, ospf6); + + if (!IS_AREA_NSSA(oa)) { + vty_out(vty, "%% First configure %s as an NSSA area\n", area); + return CMD_WARNING; + } + + range = ospf6_route_lookup((struct prefix *)prefix, + oa->nssa_range_table); + if (range == NULL) { + range = ospf6_route_create(ospf6); + range->type = OSPF6_DEST_TYPE_RANGE; + SET_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE); + prefix_copy(&range->prefix, prefix); + range->path.area_id = oa->area_id; + range->path.metric_type = 2; + range->path.cost = OSPF_AREA_RANGE_COST_UNSPEC; + range->path.origin.type = htons(OSPF6_LSTYPE_TYPE_7); + range->path.origin.id = htonl(ospf6->external_id++); + range->path.origin.adv_router = ospf6->router_id; + ospf6_route_add(range, oa->nssa_range_table); + } + + /* process "not-advertise" */ + if (not_adv) + SET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE); + else + UNSET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE); + + /* process "cost" */ + if (!cost_str) + cost = OSPF_AREA_RANGE_COST_UNSPEC; + range->path.u.cost_config = cost; + + /* Redo summaries if required */ + if (ospf6_check_and_set_router_abr(ospf6)) + ospf6_schedule_abr_task(ospf6); + + return CMD_SUCCESS; +} + +DEFPY (no_area_nssa_range, + no_area_nssa_range_cmd, + "no area $area nssa range X:X::X:X/M$prefix []", + NO_STR + "OSPF6 area parameters\n" + "OSPF6 area ID in IP address format\n" + "OSPF6 area ID as a decimal value\n" + "Configure OSPF6 area as nssa\n" + "Configured address range\n" + "Specify IPv6 prefix\n" + "Do not advertise\n" + "User specified metric for this range\n" + "Advertised metric for this range\n") +{ + struct ospf6_area *oa; + struct ospf6_route *range; + + VTY_DECLVAR_CONTEXT(ospf6, ospf6); + + OSPF6_CMD_AREA_GET(area, oa, ospf6); + + range = ospf6_route_lookup((struct prefix *)prefix, + oa->nssa_range_table); + if (range == NULL) { + vty_out(vty, "%% range %s does not exists.\n", prefix_str); + return CMD_SUCCESS; + } + + if (ospf6_check_and_set_router_abr(oa->ospf6)) { + /* Blow away the aggregated LSA and route */ + SET_FLAG(range->flag, OSPF6_ROUTE_REMOVE); + + /* Redo summaries if required */ + thread_execute(master, ospf6_abr_task_timer, ospf6, 0); + } + + ospf6_route_remove(range, oa->nssa_range_table); + + return CMD_SUCCESS; +} + DEFUN(debug_ospf6_nssa, debug_ospf6_nssa_cmd, "debug ospf6 nssa", DEBUG_STR @@ -1269,6 +1421,9 @@ void config_write_ospf6_debug_nssa(struct vty *vty) void install_element_ospf6_debug_nssa(void) { + install_element(OSPF6_NODE, &area_nssa_range_cmd); + install_element(OSPF6_NODE, &no_area_nssa_range_cmd); + install_element(ENABLE_NODE, &debug_ospf6_nssa_cmd); install_element(ENABLE_NODE, &no_debug_ospf6_nssa_cmd); install_element(CONFIG_NODE, &debug_ospf6_nssa_cmd); diff --git a/ospf6d/ospf6_route.h b/ospf6d/ospf6_route.h index 397860515b9c..fd8b6a9c1dbf 100644 --- a/ospf6d/ospf6_route.h +++ b/ospf6d/ospf6_route.h @@ -186,7 +186,7 @@ struct ospf6_route { struct timeval changed; /* flag */ - uint8_t flag; + uint16_t flag; /* Prefix Options */ uint8_t prefix_options; @@ -221,14 +221,15 @@ struct ospf6_route { #define OSPF6_DEST_TYPE_RANGE 5 #define OSPF6_DEST_TYPE_MAX 6 -#define OSPF6_ROUTE_CHANGE 0x01 -#define OSPF6_ROUTE_ADD 0x02 -#define OSPF6_ROUTE_REMOVE 0x04 -#define OSPF6_ROUTE_BEST 0x08 -#define OSPF6_ROUTE_ACTIVE_SUMMARY 0x10 -#define OSPF6_ROUTE_DO_NOT_ADVERTISE 0x20 -#define OSPF6_ROUTE_WAS_REMOVED 0x40 -#define OSPF6_ROUTE_BLACKHOLE_ADDED 0x80 +#define OSPF6_ROUTE_CHANGE 0x0001 +#define OSPF6_ROUTE_ADD 0x0002 +#define OSPF6_ROUTE_REMOVE 0x0004 +#define OSPF6_ROUTE_BEST 0x0008 +#define OSPF6_ROUTE_ACTIVE_SUMMARY 0x0010 +#define OSPF6_ROUTE_DO_NOT_ADVERTISE 0x0020 +#define OSPF6_ROUTE_WAS_REMOVED 0x0040 +#define OSPF6_ROUTE_BLACKHOLE_ADDED 0x0080 +#define OSPF6_ROUTE_NSSA_RANGE 0x0100 struct ospf6; struct ospf6_route_table { diff --git a/ospf6d/subdir.am b/ospf6d/subdir.am index be626646a000..34aabc205bbd 100644 --- a/ospf6d/subdir.am +++ b/ospf6d/subdir.am @@ -99,6 +99,7 @@ clippy_scan += \ ospf6d/ospf6_lsa.c \ ospf6d/ospf6_gr_helper.c \ ospf6d/ospf6_gr.c \ + ospf6d/ospf6_nssa.c \ ospf6d/ospf6_route.c \ # end From 81e43fd9f2406d3bb52761795d200e4c897ee8ea Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Tue, 5 Oct 2021 21:25:55 -0300 Subject: [PATCH 086/188] doc: fix small documentation issue Commit 6735622c24a3510032e40aa updated one command form but not the other. Fix this. Signed-off-by: Renato Westphal --- doc/user/ospf6d.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/user/ospf6d.rst b/doc/user/ospf6d.rst index 4e232235968a..b5d8278f0a0d 100644 --- a/doc/user/ospf6d.rst +++ b/doc/user/ospf6d.rst @@ -176,7 +176,7 @@ OSPF6 area The `not-advertise` option, when present, prevents the summary route from being advertised, effectively filtering the summarized routes. -.. clicmd:: area A.B.C.D nssa [no-summary] +.. clicmd:: area A.B.C.D nssa [no-summary] [default-information-originate [metric-type (1-2)] [metric (0-16777214)]] .. clicmd:: area (0-4294967295) nssa [no-summary] [default-information-originate [metric-type (1-2)] [metric (0-16777214)]] From cb81dd25e5538928c5c866a02ca3bad5dee84527 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Tue, 5 Oct 2021 21:25:55 -0300 Subject: [PATCH 087/188] tests: update ospf6_topo2's ospf6d configs * Add new debug directives for NSSA LSAs; * Remove the "debug ospf6 gr helper" command since it doesn't make sense for this test (not to mention it was renamed to "debug ospf6 graceful-restart"); * Migrate to the new interface-level command to enable OSPFv3 on interfaces ("interface WORD area A.B.C.D" was deprecated). Signed-off-by: Renato Westphal --- tests/topotests/ospf6_topo2/r1/ospf6d.conf | 7 +++++-- tests/topotests/ospf6_topo2/r2/ospf6d.conf | 11 +++++++---- tests/topotests/ospf6_topo2/r3/ospf6d.conf | 7 +++++-- tests/topotests/ospf6_topo2/r4/ospf6d.conf | 7 +++++-- 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/tests/topotests/ospf6_topo2/r1/ospf6d.conf b/tests/topotests/ospf6_topo2/r1/ospf6d.conf index 2e465e6d1f6e..1bf6550d9f31 100644 --- a/tests/topotests/ospf6_topo2/r1/ospf6d.conf +++ b/tests/topotests/ospf6_topo2/r1/ospf6d.conf @@ -2,6 +2,10 @@ debug ospf6 lsa router debug ospf6 lsa router originate debug ospf6 lsa router examine debug ospf6 lsa router flooding +debug ospf6 lsa nssa +debug ospf6 lsa nssa originate +debug ospf6 lsa nssa examine +debug ospf6 lsa nssa flooding debug ospf6 lsa as-external debug ospf6 lsa as-external originate debug ospf6 lsa as-external examine @@ -15,7 +19,6 @@ debug ospf6 zebra debug ospf6 interface debug ospf6 neighbor debug ospf6 flooding -debug ospf6 gr helper debug ospf6 spf process debug ospf6 route intra-area debug ospf6 route inter-area @@ -24,11 +27,11 @@ debug ospf6 asbr debug ospf6 nssa ! interface r1-eth0 + ipv6 ospf6 area 0.0.0.1 ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 ! router ospf6 ospf6 router-id 10.254.254.1 area 0.0.0.1 stub - interface r1-eth0 area 0.0.0.1 ! diff --git a/tests/topotests/ospf6_topo2/r2/ospf6d.conf b/tests/topotests/ospf6_topo2/r2/ospf6d.conf index 4a1d10693dba..7567c9cd6464 100644 --- a/tests/topotests/ospf6_topo2/r2/ospf6d.conf +++ b/tests/topotests/ospf6_topo2/r2/ospf6d.conf @@ -2,6 +2,10 @@ debug ospf6 lsa router debug ospf6 lsa router originate debug ospf6 lsa router examine debug ospf6 lsa router flooding +debug ospf6 lsa nssa +debug ospf6 lsa nssa originate +debug ospf6 lsa nssa examine +debug ospf6 lsa nssa flooding debug ospf6 lsa as-external debug ospf6 lsa as-external originate debug ospf6 lsa as-external examine @@ -15,7 +19,6 @@ debug ospf6 zebra debug ospf6 interface debug ospf6 neighbor debug ospf6 flooding -debug ospf6 gr helper debug ospf6 spf process debug ospf6 route intra-area debug ospf6 route inter-area @@ -24,14 +27,17 @@ debug ospf6 asbr debug ospf6 nssa ! interface r2-eth0 + ipv6 ospf6 area 0.0.0.1 ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 ! interface r2-eth1 + ipv6 ospf6 area 0.0.0.0 ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 ! interface r2-eth2 + ipv6 ospf6 area 0.0.0.2 ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 ! @@ -42,7 +48,4 @@ router ospf6 default-information originate always metric 123 area 0.0.0.1 stub area 0.0.0.2 nssa - interface r2-eth0 area 0.0.0.1 - interface r2-eth1 area 0.0.0.0 - interface r2-eth2 area 0.0.0.2 ! diff --git a/tests/topotests/ospf6_topo2/r3/ospf6d.conf b/tests/topotests/ospf6_topo2/r3/ospf6d.conf index 5faeb70e56e0..0fb4e7e36552 100644 --- a/tests/topotests/ospf6_topo2/r3/ospf6d.conf +++ b/tests/topotests/ospf6_topo2/r3/ospf6d.conf @@ -2,6 +2,10 @@ debug ospf6 lsa router debug ospf6 lsa router originate debug ospf6 lsa router examine debug ospf6 lsa router flooding +debug ospf6 lsa nssa +debug ospf6 lsa nssa originate +debug ospf6 lsa nssa examine +debug ospf6 lsa nssa flooding debug ospf6 lsa as-external debug ospf6 lsa as-external originate debug ospf6 lsa as-external examine @@ -15,7 +19,6 @@ debug ospf6 zebra debug ospf6 interface debug ospf6 neighbor debug ospf6 flooding -debug ospf6 gr helper debug ospf6 spf process debug ospf6 route intra-area debug ospf6 route inter-area @@ -24,6 +27,7 @@ debug ospf6 asbr debug ospf6 nssa ! interface r3-eth0 + ipv6 ospf6 area 0.0.0.0 ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 ! @@ -31,5 +35,4 @@ router ospf6 ospf6 router-id 10.254.254.3 redistribute connected redistribute static - interface r3-eth0 area 0.0.0.0 ! diff --git a/tests/topotests/ospf6_topo2/r4/ospf6d.conf b/tests/topotests/ospf6_topo2/r4/ospf6d.conf index 04d763f6a815..91f8df440c76 100644 --- a/tests/topotests/ospf6_topo2/r4/ospf6d.conf +++ b/tests/topotests/ospf6_topo2/r4/ospf6d.conf @@ -2,6 +2,10 @@ debug ospf6 lsa router debug ospf6 lsa router originate debug ospf6 lsa router examine debug ospf6 lsa router flooding +debug ospf6 lsa nssa +debug ospf6 lsa nssa originate +debug ospf6 lsa nssa examine +debug ospf6 lsa nssa flooding debug ospf6 lsa as-external debug ospf6 lsa as-external originate debug ospf6 lsa as-external examine @@ -15,7 +19,6 @@ debug ospf6 zebra debug ospf6 interface debug ospf6 neighbor debug ospf6 flooding -debug ospf6 gr helper debug ospf6 spf process debug ospf6 route intra-area debug ospf6 route inter-area @@ -24,11 +27,11 @@ debug ospf6 asbr debug ospf6 nssa ! interface r4-eth0 + ipv6 ospf6 area 0.0.0.2 ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 ! router ospf6 ospf6 router-id 10.254.254.4 area 0.0.0.2 nssa - interface r4-eth0 area 0.0.0.2 ! From 343e16cec54cc8c6e5df389e3a20efd98e450ff1 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Tue, 5 Oct 2021 21:25:55 -0300 Subject: [PATCH 088/188] tests: extend topotest to test NSSA ranges Test NSSA address ranges, including the "cost" and "not-advertise" options. Signed-off-by: Renato Westphal --- .../topotests/ospf6_topo2/test_ospf6_topo2.py | 100 +++++++++++++++++- 1 file changed, 99 insertions(+), 1 deletion(-) diff --git a/tests/topotests/ospf6_topo2/test_ospf6_topo2.py b/tests/topotests/ospf6_topo2/test_ospf6_topo2.py index 303bcd014d87..eb8561c404fa 100644 --- a/tests/topotests/ospf6_topo2/test_ospf6_topo2.py +++ b/tests/topotests/ospf6_topo2/test_ospf6_topo2.py @@ -131,6 +131,8 @@ def build_topo(tgen): switch.add_link(tgen.gears["r2"]) switch.add_link(tgen.gears["r4"]) + switch = tgen.add_switch("s4") + switch.add_link(tgen.gears["r4"], nodeif="r4-stubnet") def setup_module(mod): "Sets up the pytest environment" @@ -484,7 +486,7 @@ def test_area_filters(): pytest.skip(tgen.errors) # - # Configure import/export filters on r2 (ABR for area 1). + # Configure import/export filters on r2 (ABR for area 2). # config = """ configure terminal @@ -544,6 +546,102 @@ def test_area_filters(): expect_ospfv3_routes("r1", routes, wait=30, type="inter-area") +def test_nssa_range(): + """ + Test NSSA ABR ranges. + """ + tgen = get_topogen() + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Configure new addresses on r4 and enable redistribution of connected + # routes. + config = """ + configure terminal + interface r4-stubnet + ipv6 address 2001:db8:1000::1/128 + ipv6 address 2001:db8:1000::2/128 + router ospf6 + redistribute connected + """ + tgen.gears["r4"].vtysh_cmd(config) + logger.info("Expecting NSSA-translated external routes to be added on r3") + routes = {"2001:db8:1000::1/128": {}, "2001:db8:1000::2/128": {}} + expect_ospfv3_routes("r3", routes, wait=30, type="external-2") + + # Configure an NSSA range on r2 (ABR for area 2). + config = """ + configure terminal + router ospf6 + area 2 nssa range 2001:db8:1000::/64 + """ + tgen.gears["r2"].vtysh_cmd(config) + logger.info("Expecting summarized routes to be removed from r3") + for route in ["2001:db8:1000::1/128", "2001:db8:1000::2/128"]: + test_func = partial(dont_expect_route, "r3", route, type="external-2") + _, result = topotest.run_and_expect(test_func, None, count=30, wait=1) + assertmsg = "{}'s {} summarized route still exists".format("r3", route) + assert result is None, assertmsg + logger.info("Expecting NSSA range to be added on r3") + routes = { + "2001:db8:1000::/64": { + "metricType":2, + "metricCost":20, + "metricCostE2":10, + }} + expect_ospfv3_routes("r3", routes, wait=30, type="external-2", detail=True) + + # Change the NSSA range cost. + config = """ + configure terminal + router ospf6 + area 2 nssa range 2001:db8:1000::/64 cost 1000 + """ + tgen.gears["r2"].vtysh_cmd(config) + logger.info("Expecting NSSA range to be updated with new cost") + routes = { + "2001:db8:1000::/64": { + "metricType":2, + "metricCost":20, + "metricCostE2":1000, + }} + expect_ospfv3_routes("r3", routes, wait=30, type="external-2", detail=True) + + # Configure the NSSA range to not be advertised. + config = """ + configure terminal + router ospf6 + area 2 nssa range 2001:db8:1000::/64 not-advertise + """ + tgen.gears["r2"].vtysh_cmd(config) + logger.info("Expecting NSSA summary route to be removed") + route = "2001:db8:1000::/64" + test_func = partial(dont_expect_route, "r3", route, type="external-2") + _, result = topotest.run_and_expect(test_func, None, count=30, wait=1) + assertmsg = "{}'s {} NSSA summary route still exists".format("r3", route) + assert result is None, assertmsg + + # Remove the NSSA range. + config = """ + configure terminal + router ospf6 + no area 2 nssa range 2001:db8:1000::/64 + """ + tgen.gears["r2"].vtysh_cmd(config) + logger.info("Expecting previously summarized routes to be re-added") + routes = { + "2001:db8:1000::1/128": { + "metricType":2, + "metricCost":20, + }, + "2001:db8:1000::2/128": { + "metricType":2, + "metricCost":20, + }, + } + expect_ospfv3_routes("r3", routes, wait=30, type="external-2", detail=True) + + def teardown_module(_mod): "Teardown the pytest environment" tgen = get_topogen() From 8eec31ef564dcf4e096e700a648570973ca4e96b Mon Sep 17 00:00:00 2001 From: Yuan Yuan Date: Wed, 22 Sep 2021 20:02:40 +0000 Subject: [PATCH 089/188] Zebra: Ignore the failure of startup intf lookup. In startup, zebra would dump interface information from Kernel in 3 steps w/o lock: step1, get interface information; step2, get interface ipv4 address; step3, get interface ipv6 address. If any interface gets added after step1, but before step2/3, zebra would get extra interface addresses in step2/3 that has not been added into zebra in step1. Returning error in the referenced interface lookup would cause the startup interface retrieval to be incomplete. Signed-off-by: Yuan Yuan --- zebra/if_netlink.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index acd6697b6514..8e52ef4047e5 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -1302,11 +1302,22 @@ int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup) ifp = if_lookup_by_index_per_ns(zns, ifa->ifa_index); if (ifp == NULL) { - flog_err( - EC_LIB_INTERFACE, - "netlink_interface_addr can't find interface by index %d", - ifa->ifa_index); - return -1; + if (startup) { + /* During startup, failure to lookup the referenced + * interface should not be an error, so we have + * downgraded this condition to warning, and we permit + * the startup interface state retrieval to continue. + */ + flog_warn(EC_LIB_INTERFACE, + "%s: can't find interface by index %d", + __func__, ifa->ifa_index); + return 0; + } else { + flog_err(EC_LIB_INTERFACE, + "%s: can't find interface by index %d", + __func__, ifa->ifa_index); + return -1; + } } /* Flags passed through */ From f0009d576995db7578bd053a4a3812949490a20b Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Wed, 6 Oct 2021 10:37:59 +0200 Subject: [PATCH 090/188] doc: fix show isis route prefix-sid command This command was not documented, and deprecates the old one. Signed-off-by: Philippe Guibert --- doc/user/isisd.rst | 4 ---- 1 file changed, 4 deletions(-) diff --git a/doc/user/isisd.rst b/doc/user/isisd.rst index 66f8fd56789a..4a711a8febe6 100644 --- a/doc/user/isisd.rst +++ b/doc/user/isisd.rst @@ -394,10 +394,6 @@ Known limitations: clear the Node flag that is set by default for Prefix-SIDs associated to loopback addresses. This option is necessary to configure Anycast-SIDs. -.. clicmd:: show isis segment-routing prefix-sids - - Show detailed information about all learned Segment Routing Prefix-SIDs. - .. clicmd:: show isis segment-routing nodes Show detailed information about all learned Segment Routing Nodes. From 16b398fa5cf21757fd10fb49fb259cf27bc7c2dd Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 6 Oct 2021 07:58:35 -0400 Subject: [PATCH 091/188] bgpd: Check return from generic_set_add Coverity found a couple of spots where FRR was ignoring the return code of generic_set_add. Just follow the code pattern for the rest of the usage in the code. Signed-off-by: Donald Sharp --- bgpd/bgp_routemap_nb_config.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/bgpd/bgp_routemap_nb_config.c b/bgpd/bgp_routemap_nb_config.c index 85676e6758a2..f98c1b0f8fb7 100644 --- a/bgpd/bgp_routemap_nb_config.c +++ b/bgpd/bgp_routemap_nb_config.c @@ -2440,6 +2440,7 @@ void lib_route_map_entry_set_action_rmap_set_action_aggregator_finish( const char *asn; const char *addr; char *argstr; + int ret; /* Add configuration. */ rhc = nb_running_get_entry(args->dnode, NULL, true); @@ -2456,8 +2457,15 @@ void lib_route_map_entry_set_action_rmap_set_action_aggregator_finish( rhc->rhc_rule = "aggregator as"; rhc->rhc_event = RMAP_EVENT_SET_DELETED; - generic_set_add(rhc->rhc_rmi, rhc->rhc_rule, argstr, - args->errmsg, args->errmsg_len); + ret = generic_set_add(rhc->rhc_rmi, rhc->rhc_rule, argstr, args->errmsg, + args->errmsg_len); + /* + * At this point if this is not a successful operation + * bgpd is about to crash. Let's just cut to the + * chase and do it. + */ + assert(ret == CMD_SUCCESS); + XFREE(MTYPE_ROUTE_MAP_COMPILED, argstr); } /* @@ -2604,6 +2612,7 @@ lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_finish( enum ecommunity_lb_type lb_type; char str[VTY_BUFSIZ]; uint16_t bandwidth; + int ret; /* Add configuration. */ rhc = nb_running_get_entry(args->dnode, NULL, true); @@ -2629,9 +2638,14 @@ lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_finish( if (yang_dnode_get_bool(args->dnode, "./two-octet-as-specific")) strlcat(str, " non-transitive", sizeof(str)); - generic_set_add(rhc->rhc_rmi, - "extcommunity bandwidth", str, - args->errmsg, args->errmsg_len); + ret = generic_set_add(rhc->rhc_rmi, "extcommunity bandwidth", str, + args->errmsg, args->errmsg_len); + /* + * At this point if this is not a successful operation + * bgpd is about to crash. Let's just cut to the + * chase and do it. + */ + assert(ret == CMD_SUCCESS); } /* From ac0ed50468ed362f8c1342c7f8de99ae25494beb Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 6 Oct 2021 08:01:30 -0400 Subject: [PATCH 092/188] bgpd: Check return code for bgp_route_match_add FRR uses bgp_route_match_add and checked the return code in every place but one. Fix so that the return code is looked at and warned against Signed-off-by: Donald Sharp --- bgpd/bgp_routemap_nb_config.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/bgpd/bgp_routemap_nb_config.c b/bgpd/bgp_routemap_nb_config.c index f98c1b0f8fb7..09a6be4010f9 100644 --- a/bgpd/bgp_routemap_nb_config.c +++ b/bgpd/bgp_routemap_nb_config.c @@ -1035,6 +1035,7 @@ lib_route_map_entry_match_condition_rmap_match_condition_comm_list_finish( char *argstr; const char *condition; route_map_event_t event; + int ret; /* Add configuration. */ rhc = nb_running_get_entry(args->dnode, NULL, true); @@ -1072,8 +1073,14 @@ lib_route_map_entry_match_condition_rmap_match_condition_comm_list_finish( rhc->rhc_event = RMAP_EVENT_ECLIST_DELETED; } - bgp_route_match_add(rhc->rhc_rmi, rhc->rhc_rule, argstr, event, - args->errmsg, args->errmsg_len); + ret = bgp_route_match_add(rhc->rhc_rmi, rhc->rhc_rule, argstr, event, + args->errmsg, args->errmsg_len); + /* + * At this point if this is not a successful operation + * bgpd is about to crash. Let's just cut to the + * chase and do it. + */ + assert(ret == RMAP_COMPILE_SUCCESS); if (argstr != value) XFREE(MTYPE_ROUTE_MAP_COMPILED, argstr); From b25a11034709055f76f6611bce3912ef46650529 Mon Sep 17 00:00:00 2001 From: Ahmad Caracalli Date: Wed, 6 Oct 2021 15:46:19 +0200 Subject: [PATCH 093/188] ospf6: add the ability of specifying router-id/area-id in no debug ospf6 Add the ability to specify the router-id/area-id when deleting the debug ospf6 configuration. The new commands are as follow: no debug ospf6 border-routers router-id [A.B.C.D] no debug ospf6 border-routers area-id [A.B.C.D] Update the doc as well. Signed-off-by: Ahmad Caracalli --- doc/user/ospf6d.rst | 5 +++-- ospf6d/ospf6_intra.c | 6 ++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/doc/user/ospf6d.rst b/doc/user/ospf6d.rst index d823c5d5b547..093c5382cfa0 100644 --- a/doc/user/ospf6d.rst +++ b/doc/user/ospf6d.rst @@ -476,9 +476,10 @@ The following debug commands are supported: Toggle OSPFv3 ASBR debugging messages. -.. clicmd:: debug ospf6 border-routers +.. clicmd:: debug ospf6 border-routers {router-id [A.B.C.D] | area-id [A.B.C.D]} - Toggle OSPFv3 border router debugging messages. + Toggle OSPFv3 border router debugging messages. This can be specified for a + router with specific Router-ID/Area-ID. .. clicmd:: debug ospf6 flooding diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c index 277af4b1c521..988f37bd2ed7 100644 --- a/ospf6d/ospf6_intra.c +++ b/ospf6d/ospf6_intra.c @@ -2479,12 +2479,13 @@ DEFUN (debug_ospf6_brouter_router, DEFUN (no_debug_ospf6_brouter_router, no_debug_ospf6_brouter_router_cmd, - "no debug ospf6 border-routers router-id", + "no debug ospf6 border-routers router-id [A.B.C.D]", NO_STR DEBUG_STR OSPF6_STR "Debug border router\n" "Debug specific border router\n" + "Specify border-router's router-id\n" ) { OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_OFF(); @@ -2510,12 +2511,13 @@ DEFUN (debug_ospf6_brouter_area, DEFUN (no_debug_ospf6_brouter_area, no_debug_ospf6_brouter_area_cmd, - "no debug ospf6 border-routers area-id", + "no debug ospf6 border-routers area-id [A.B.C.D]", NO_STR DEBUG_STR OSPF6_STR "Debug border router\n" "Debug border routers in specific Area\n" + "Specify Area-ID\n" ) { OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_OFF(); From a1985a2dc9e017e2b0c244176b1a3faad94b4cd5 Mon Sep 17 00:00:00 2001 From: Mark Stapp Date: Wed, 6 Oct 2021 10:51:04 -0400 Subject: [PATCH 094/188] tests: remove deprecated debug cli from some tests Some tests had commented-out references to the old "CLI()" function. Remove those so they're not confusing in the future, and replace at least one with a comment that uses the 'mininet_cli()' function. Signed-off-by: Mark Stapp --- tests/topotests/ldp_topo1/test_ldp_topo1.py | 26 +------------------ tests/topotests/rip_topo1/test_rip_topo1.py | 17 +----------- .../topotests/ripng_topo1/test_ripng_topo1.py | 17 +----------- 3 files changed, 3 insertions(+), 57 deletions(-) diff --git a/tests/topotests/ldp_topo1/test_ldp_topo1.py b/tests/topotests/ldp_topo1/test_ldp_topo1.py index c21d6bf28e36..834205f65354 100644 --- a/tests/topotests/ldp_topo1/test_ldp_topo1.py +++ b/tests/topotests/ldp_topo1/test_ldp_topo1.py @@ -126,7 +126,7 @@ def setup_module(module): tgen.gears["r%s" % i].start() # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) + # tgen.mininet_cli() def teardown_module(module): @@ -153,9 +153,6 @@ def test_router_running(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_mpls_interfaces(): global fatal_error @@ -219,9 +216,6 @@ def test_mpls_interfaces(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_mpls_ldp_neighbor_establish(): global fatal_error @@ -356,9 +350,6 @@ def test_mpls_ldp_discovery(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_mpls_ldp_neighbor(): global fatal_error @@ -426,9 +417,6 @@ def test_mpls_ldp_neighbor(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_mpls_ldp_binding(): global fatal_error @@ -518,9 +506,6 @@ def test_mpls_ldp_binding(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_zebra_ipv4_routingTable(): global fatal_error @@ -595,9 +580,6 @@ def test_zebra_ipv4_routingTable(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_mpls_table(): global fatal_error @@ -674,9 +656,6 @@ def test_mpls_table(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_linux_mpls_routes(): global fatal_error @@ -758,9 +737,6 @@ def test_linux_mpls_routes(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_shutdown_check_stderr(): global fatal_error diff --git a/tests/topotests/rip_topo1/test_rip_topo1.py b/tests/topotests/rip_topo1/test_rip_topo1.py index c5812f28cf46..7d59e8422f51 100644 --- a/tests/topotests/rip_topo1/test_rip_topo1.py +++ b/tests/topotests/rip_topo1/test_rip_topo1.py @@ -108,7 +108,7 @@ def setup_module(module): tgen.gears["r%s" % i].start() # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) + # tgen.mininet_cli() def teardown_module(module): @@ -134,9 +134,6 @@ def test_router_running(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_converge_protocols(): global fatal_error @@ -159,9 +156,6 @@ def test_converge_protocols(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_rip_status(): global fatal_error @@ -220,9 +214,6 @@ def test_rip_status(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_rip_routes(): global fatal_error @@ -275,9 +266,6 @@ def test_rip_routes(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_zebra_ipv4_routingTable(): global fatal_error @@ -341,9 +329,6 @@ def test_zebra_ipv4_routingTable(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_shutdown_check_stderr(): global fatal_error diff --git a/tests/topotests/ripng_topo1/test_ripng_topo1.py b/tests/topotests/ripng_topo1/test_ripng_topo1.py index df81ac08c489..563c4f74979a 100644 --- a/tests/topotests/ripng_topo1/test_ripng_topo1.py +++ b/tests/topotests/ripng_topo1/test_ripng_topo1.py @@ -104,7 +104,7 @@ def setup_module(module): tgen.gears["r%s" % i].start() # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) + # tgen.mininet_cli() def teardown_module(module): @@ -130,9 +130,6 @@ def test_router_running(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_converge_protocols(): global fatal_error @@ -155,9 +152,6 @@ def test_converge_protocols(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_ripng_status(): global fatal_error @@ -223,9 +217,6 @@ def test_ripng_status(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_ripng_routes(): global fatal_error @@ -290,9 +281,6 @@ def test_ripng_routes(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_zebra_ipv6_routingTable(): global fatal_error @@ -358,9 +346,6 @@ def test_zebra_ipv6_routingTable(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_shutdown_check_stderr(): global fatal_error From bc465fb6cc7cfbad3301d6d0ceb4fb539dbaec35 Mon Sep 17 00:00:00 2001 From: Manoj Naragund Date: Thu, 30 Sep 2021 10:28:11 -0700 Subject: [PATCH 095/188] ospf6d: code cleanup. removal of some of the deadcode in ospf6d. Signed-off-by: Manoj Naragund --- ospf6d/ospf6_abr.c | 17 ++++++++--------- ospf6d/ospf6_abr.h | 4 ++-- ospf6d/ospf6_asbr.c | 4 ++-- ospf6d/ospf6_flood.c | 1 - ospf6d/ospf6_intra.c | 8 ++++---- ospf6d/ospf6_message.c | 4 ---- ospf6d/ospf6_route.c | 2 -- 7 files changed, 16 insertions(+), 24 deletions(-) diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c index 057e1d9ea25f..f3e8127a80b6 100644 --- a/ospf6d/ospf6_abr.c +++ b/ospf6d/ospf6_abr.c @@ -53,12 +53,11 @@ unsigned char conf_debug_ospf6_abr; -int ospf6_ls_origin_cmp(struct ospf6_path *o_path, struct ospf6_route *route) +int ospf6_ls_origin_same(struct ospf6_path *o_path, struct ospf6_path *r_path) { - if (((o_path->origin.type == route->path.origin.type) - && (o_path->origin.id == route->path.origin.id) - && (o_path->origin.adv_router == - route->path.origin.adv_router))) + if (((o_path->origin.type == r_path->origin.type) + && (o_path->origin.id == r_path->origin.id) + && (o_path->origin.adv_router == r_path->origin.adv_router))) return 1; else return 0; @@ -826,8 +825,8 @@ void ospf6_abr_old_path_update(struct ospf6_route *old_route, struct ospf6_nexthop *nh, *rnh; for (ALL_LIST_ELEMENTS(old_route->paths, anode, anext, o_path)) { - if (o_path->area_id != route->path.area_id || - (!ospf6_ls_origin_cmp(o_path, route))) + if (o_path->area_id != route->path.area_id + || !ospf6_ls_origin_same(o_path, &route->path)) continue; if ((o_path->cost == route->path.cost) && @@ -1242,8 +1241,8 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa) for (ALL_LIST_ELEMENTS_RO(old_route->paths, anode, o_path)) { - if (o_path->area_id == route->path.area_id && - (ospf6_ls_origin_cmp(o_path, route))) + if (o_path->area_id == route->path.area_id + && ospf6_ls_origin_same(o_path, &route->path)) break; } diff --git a/ospf6d/ospf6_abr.h b/ospf6d/ospf6_abr.h index 75e051761db7..a4dc4ddc843e 100644 --- a/ospf6d/ospf6_abr.h +++ b/ospf6d/ospf6_abr.h @@ -89,7 +89,7 @@ extern void ospf6_abr_init(void); extern void ospf6_abr_range_update(struct ospf6_route *range, struct ospf6 *ospf6); extern void ospf6_abr_remove_unapproved_summaries(struct ospf6 *ospf6); -extern int ospf6_ls_origin_cmp(struct ospf6_path *o_path, - struct ospf6_route *route); +extern int ospf6_ls_origin_same(struct ospf6_path *o_path, + struct ospf6_path *r_path); #endif /*OSPF6_ABR_H*/ diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c index beed61d04731..c5ee22bc5eec 100644 --- a/ospf6d/ospf6_asbr.c +++ b/ospf6d/ospf6_asbr.c @@ -290,7 +290,7 @@ void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old, * origin. */ if (o_path->area_id != route->path.area_id - || (!ospf6_ls_origin_cmp(o_path, route))) + || !ospf6_ls_origin_same(o_path, &route->path)) continue; /* Cost is not same then delete current path */ @@ -409,7 +409,7 @@ void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old, for (ALL_LIST_ELEMENTS_RO(old_route->paths, anode, o_path)) { if (o_path->area_id == route->path.area_id - && (ospf6_ls_origin_cmp(o_path, route))) + && ospf6_ls_origin_same(o_path, &route->path)) break; } /* If path is not found in old_route paths's list, diff --git a/ospf6d/ospf6_flood.c b/ospf6d/ospf6_flood.c index 186eac35a505..0c004b85af02 100644 --- a/ospf6d/ospf6_flood.c +++ b/ospf6d/ospf6_flood.c @@ -1239,7 +1239,6 @@ void ospf6_receive_lsa(struct ospf6_neighbor *from, ospf6_lsa_delete(new); return; } - return; } } diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c index 27e21a041718..830a0960c282 100644 --- a/ospf6d/ospf6_intra.c +++ b/ospf6d/ospf6_intra.c @@ -1524,8 +1524,8 @@ void ospf6_intra_prefix_route_ecmp_path(struct ospf6_area *oa, /* Check old route path and route has same * origin. */ - if (o_path->area_id != route->path.area_id || - (!ospf6_ls_origin_cmp(o_path, route))) + if (o_path->area_id != route->path.area_id + || !ospf6_ls_origin_same(o_path, &route->path)) continue; /* Cost is not same then delete current path */ @@ -1629,8 +1629,8 @@ void ospf6_intra_prefix_route_ecmp_path(struct ospf6_area *oa, */ for (ALL_LIST_ELEMENTS_RO(old_route->paths, anode, o_path)) { - if (o_path->area_id == route->path.area_id && - (ospf6_ls_origin_cmp(o_path, route))) + if (o_path->area_id == route->path.area_id + && ospf6_ls_origin_same(o_path, &route->path)) break; } /* If path is not found in old_route paths's list, diff --git a/ospf6d/ospf6_message.c b/ospf6d/ospf6_message.c index 64de9bae4167..23610f649d47 100644 --- a/ospf6d/ospf6_message.c +++ b/ospf6d/ospf6_message.c @@ -726,7 +726,6 @@ static void ospf6_dbdesc_recv_master(struct ospf6_header *oh, zlog_debug("Ignoring LSA of reserved scope"); ospf6_lsa_delete(his); continue; - break; } if (ntohs(his->header->type) == OSPF6_LSTYPE_AS_EXTERNAL @@ -949,7 +948,6 @@ static void ospf6_dbdesc_recv_slave(struct ospf6_header *oh, zlog_debug("Ignoring LSA of reserved scope"); ospf6_lsa_delete(his); continue; - break; } if (OSPF6_LSA_SCOPE(his->header->type) == OSPF6_SCOPE_AS @@ -1084,7 +1082,6 @@ static void ospf6_lsreq_recv(struct in6_addr *src, struct in6_addr *dst, if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) zlog_debug("Ignoring LSA of reserved scope"); continue; - break; } /* Find database copy */ @@ -1636,7 +1633,6 @@ static void ospf6_lsack_recv(struct in6_addr *src, struct in6_addr *dst, zlog_debug("Ignoring LSA of reserved scope"); ospf6_lsa_delete(his); continue; - break; } if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) diff --git a/ospf6d/ospf6_route.c b/ospf6d/ospf6_route.c index 8bfd3b7124df..4b87c4cf3089 100644 --- a/ospf6d/ospf6_route.c +++ b/ospf6d/ospf6_route.c @@ -408,8 +408,6 @@ int ospf6_nexthop_cmp(struct ospf6_nexthop *a, struct ospf6_nexthop *b) else return memcmp(&a->address, &b->address, sizeof(struct in6_addr)); - - return 0; } static int ospf6_path_cmp(struct ospf6_path *a, struct ospf6_path *b) From 72618ba82af966bbde6fda49905f6b2b6fa25fd0 Mon Sep 17 00:00:00 2001 From: Igor Ryzhov Date: Wed, 6 Oct 2021 17:35:07 +0300 Subject: [PATCH 096/188] lib: fix incorrect thread management The current code passes an address of a local variable to `thread_add_read` which stores it into `thread->ref` by the lib. The next time the thread callback is executed, the lib stores NULL into the `thread->ref` which means it writes into some random memory on the stack. To fix this, we should pass a pointer to the vector entry to the lib. Signed-off-by: Igor Ryzhov --- lib/resolver.c | 28 +++++++++++++++------------- lib/vector.c | 11 +++++++++++ lib/vector.h | 1 + 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/lib/resolver.c b/lib/resolver.c index c2153e0a5e44..4aba909f2555 100644 --- a/lib/resolver.c +++ b/lib/resolver.c @@ -53,14 +53,14 @@ static int resolver_cb_socket_readable(struct thread *t) { struct resolver_state *r = THREAD_ARG(t); int fd = THREAD_FD(t); + struct thread **t_ptr; vector_set_index(r->read_threads, fd, THREAD_RUNNING); ares_process_fd(r->channel, fd, ARES_SOCKET_BAD); if (vector_lookup(r->read_threads, fd) == THREAD_RUNNING) { - t = NULL; + t_ptr = (struct thread **)vector_get_index(r->read_threads, fd); thread_add_read(r->master, resolver_cb_socket_readable, r, fd, - &t); - vector_set_index(r->read_threads, fd, t); + t_ptr); } resolver_update_timeouts(r); @@ -71,14 +71,14 @@ static int resolver_cb_socket_writable(struct thread *t) { struct resolver_state *r = THREAD_ARG(t); int fd = THREAD_FD(t); + struct thread **t_ptr; vector_set_index(r->write_threads, fd, THREAD_RUNNING); ares_process_fd(r->channel, ARES_SOCKET_BAD, fd); if (vector_lookup(r->write_threads, fd) == THREAD_RUNNING) { - t = NULL; + t_ptr = (struct thread **)vector_get_index(r->write_threads, fd); thread_add_write(r->master, resolver_cb_socket_writable, r, fd, - &t); - vector_set_index(r->write_threads, fd, t); + t_ptr); } resolver_update_timeouts(r); @@ -105,14 +105,15 @@ static void ares_socket_cb(void *data, ares_socket_t fd, int readable, int writable) { struct resolver_state *r = (struct resolver_state *)data; - struct thread *t; + struct thread *t, **t_ptr; if (readable) { - t = vector_lookup_ensure(r->read_threads, fd); + t = vector_lookup(r->read_threads, fd); if (!t) { + t_ptr = (struct thread **)vector_get_index( + r->read_threads, fd); thread_add_read(r->master, resolver_cb_socket_readable, - r, fd, &t); - vector_set_index(r->read_threads, fd, t); + r, fd, t_ptr); } } else { t = vector_lookup(r->read_threads, fd); @@ -125,11 +126,12 @@ static void ares_socket_cb(void *data, ares_socket_t fd, int readable, } if (writable) { - t = vector_lookup_ensure(r->write_threads, fd); + t = vector_lookup(r->write_threads, fd); if (!t) { + t_ptr = (struct thread **)vector_get_index( + r->write_threads, fd); thread_add_read(r->master, resolver_cb_socket_writable, - r, fd, &t); - vector_set_index(r->write_threads, fd, t); + r, fd, t_ptr); } } else { t = vector_lookup(r->write_threads, fd); diff --git a/lib/vector.c b/lib/vector.c index 565c49fd59a1..4af564a82ff8 100644 --- a/lib/vector.c +++ b/lib/vector.c @@ -123,6 +123,17 @@ int vector_set_index(vector v, unsigned int i, void *val) return i; } +/* Make a specified index slot active and return its address. */ +void **vector_get_index(vector v, unsigned int i) +{ + vector_ensure(v, i); + + if (v->active <= i) + v->active = i + 1; + + return &v->index[i]; +} + /* Look up vector. */ void *vector_lookup(vector v, unsigned int i) { diff --git a/lib/vector.h b/lib/vector.h index d5857eb599d0..845c8d8b04ef 100644 --- a/lib/vector.h +++ b/lib/vector.h @@ -54,6 +54,7 @@ extern void vector_ensure(vector v, unsigned int num); extern int vector_empty_slot(vector v); extern int vector_set(vector v, void *val); extern int vector_set_index(vector v, unsigned int i, void *val); +extern void **vector_get_index(vector v, unsigned int i); extern void vector_unset(vector v, unsigned int i); extern void vector_unset_value(vector v, void *val); extern void vector_remove(vector v, unsigned int ix); From 16044e7ff7bc06bd85aa8527f2512eff3abec4f9 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 6 Oct 2021 18:12:26 +0200 Subject: [PATCH 097/188] doc/developer: document dev tag on master We have `frr-X.Y-dev` tags on master after pulling stable branches, otherwise the `gitversion` tooling / `--with-pkg-git-version` gets _very_ confused (it'll print something like: ``` FRRouting 8.2-dev-g210a75e65dad (areia). Copyright 1996-2005 Kunihiro Ishiguro, et al. This is a git build of frr-8.1-rc1-8-g210a75e65dad ``` (Note the conflicting version numbers.) Signed-off-by: David Lamparter --- doc/developer/workflow.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/doc/developer/workflow.rst b/doc/developer/workflow.rst index 2ce5f5d1c8c9..7cec5020b25a 100644 --- a/doc/developer/workflow.rst +++ b/doc/developer/workflow.rst @@ -98,6 +98,16 @@ March/July/November. Walking backwards from this date: ``dev/MAJOR.MINOR`` at this point) and a ``rc1`` release candidate is tagged. Master is unfrozen and new features may again proceed. + Part of unfreezing master is editing the ``AC_INIT`` statement in + :file:`configure.ac` to reflect the new development version that master + now refers to. This is accompanied by a ``frr-X.Y-dev`` tag on master, + which should always be on the first commit on master *after* the stable + branch was forked (even if that is not the edit to ``AC_INIT``; it's more + important to have it on the very first commit on master after the fork.) + + (The :file:`configure.ac` edit and tag push are considered git housekeeping + and are pushed directly to ``master``, not through a PR.) + - 2 weeks earlier, a ``rc2`` release candidate is tagged. - on release date, the branch is renamed to ``stable/MAJOR.MINOR``. From 6ea3c091ed87387873f5a9e849b839fb1dbd3ee5 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 6 Oct 2021 18:18:17 +0200 Subject: [PATCH 098/188] build: bump configure.ac to `8.2-dev` [needs to happen ASAP to make sure we're not building confusing packages.] Signed-off-by: David Lamparter --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index f792b1c6527d..873ed18db854 100644 --- a/configure.ac +++ b/configure.ac @@ -7,7 +7,7 @@ ## AC_PREREQ([2.69]) -AC_INIT([frr], [8.1-dev], [https://github.com/frrouting/frr/issues]) +AC_INIT([frr], [8.2-dev], [https://github.com/frrouting/frr/issues]) PACKAGE_URL="https://frrouting.org/" AC_SUBST([PACKAGE_URL]) PACKAGE_FULLNAME="FRRouting" From a91f5417d8e7188b61ddecd4224fbba0f0c61e78 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 4 Oct 2021 20:32:25 -0400 Subject: [PATCH 099/188] watchfrr: Allow an integrated config to work within a namespace Since watchfrr invokes vtysh to gather the show run output and write the data, if we are operating inside of a namespace FRR must also pass this in. Yes. This seems hacky. I don't fully understand why vtysh is invoked this way. New output: sharpd@eva:~/frr3$ sudo vtysh -N one Hello, this is FRRouting (version 8.1-dev). Copyright 1996-2005 Kunihiro Ishiguro, et al. eva# wr mem Note: this version of vtysh never writes vtysh.conf % Can't open configuration file /etc/frr/one/vtysh.conf due to 'No such file or directory'. Building Configuration... Integrated configuration saved to /etc/frr/one/frr.conf [OK] eva# Signed-off-by: Donald Sharp --- watchfrr/watchfrr.c | 8 ++++++++ watchfrr/watchfrr.h | 6 ++++++ watchfrr/watchfrr_vty.c | 5 ++++- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/watchfrr/watchfrr.c b/watchfrr/watchfrr.c index 40749e8fc262..b09d09245884 100644 --- a/watchfrr/watchfrr.c +++ b/watchfrr/watchfrr.c @@ -68,6 +68,7 @@ DEFINE_MTYPE_STATIC(WATCHFRR, WATCHFRR_DAEMON, "watchfrr daemon entry"); struct thread_master *master; static bool watch_only = false; +const char *pathspace; typedef enum { PHASE_NONE = 0, @@ -1513,8 +1514,15 @@ int main(int argc, char **argv) else unsetenv("FRR_PATHSPACE"); + /* + * when watchfrr_di.pathspace is read, if it is not specified + * pathspace is NULL as expected + */ + pathspace = watchfrr_di.pathspace; + if (netns_en && !netns) netns = watchfrr_di.pathspace; + if (netns_en && netns && netns[0]) netns_setup(netns); diff --git a/watchfrr/watchfrr.h b/watchfrr/watchfrr.h index 4df1bf74afb7..4987a932c03c 100644 --- a/watchfrr/watchfrr.h +++ b/watchfrr/watchfrr.h @@ -25,6 +25,12 @@ DECLARE_MGROUP(WATCHFRR); +/* + * This is the name of the pathspace we are in `-N XXX` + * If the default then this is NULL + */ +extern const char *pathspace; + extern void watchfrr_vty_init(void); extern pid_t integrated_write_pid; diff --git a/watchfrr/watchfrr_vty.c b/watchfrr/watchfrr_vty.c index eda4f5d516bf..1492ee37b600 100644 --- a/watchfrr/watchfrr_vty.c +++ b/watchfrr/watchfrr_vty.c @@ -105,7 +105,10 @@ DEFUN(config_write_integrated, /* don't allow the user to pass parameters, we're root here! * should probably harden vtysh at some point too... */ - execl(VTYSH_BIN_PATH, "vtysh", "-w", NULL); + if (pathspace) + execl(VTYSH_BIN_PATH, "vtysh", "-N", pathspace, "-w", NULL); + else + execl(VTYSH_BIN_PATH, "vtysh", "-w", NULL); /* unbuffered write; we just messed with stdout... */ char msg[512]; From 874a549d519d4cb9aaee327f45666cac2b34901d Mon Sep 17 00:00:00 2001 From: Mobashshera Rasool Date: Wed, 6 Oct 2021 10:04:10 -0700 Subject: [PATCH 100/188] ospfd: ospf nbr in full although mismatch in hello packet contents Issue: =================== OSPF neighbors are not going down even after 10 mins when having a mismatch in hello and dead interval. First neighbors are formed and then a mismatch in the interval is created, it is observed that the neighbor is not going down. Root Cause Analysis: ==================== The event HelloReceived defined in RFC 2328 was named as PacketReceived and this event was scheduled whenever LS Update, LS Ack, LS Request, DD description packet or Hello packet is received. Although there is a mismatch in the Hello packet contents, the event PacketReceived gets triggered due to LS Update received and the dead timer gets reset and hence the neighbor was never going Down and remains FULL. Fix: ================== As per RFC 2328, the HelloReceived needs to be triggered only when valid OSPF Hello packet is received and not when other OSPF packets are received. Modified the function name as well. Signed-off-by: Mobashshera Rasool --- ospfd/ospf_nsm.c | 26 +++++++++++++------------- ospfd/ospf_nsm.h | 2 +- ospfd/ospf_packet.c | 14 +------------- 3 files changed, 15 insertions(+), 27 deletions(-) diff --git a/ospfd/ospf_nsm.c b/ospfd/ospf_nsm.c index dee25275d694..5f84d04fedee 100644 --- a/ospfd/ospf_nsm.c +++ b/ospfd/ospf_nsm.c @@ -176,7 +176,7 @@ int nsm_should_adj(struct ospf_neighbor *nbr) } /* OSPF NSM functions. */ -static int nsm_packet_received(struct ospf_neighbor *nbr) +static int nsm_hello_received(struct ospf_neighbor *nbr) { /* Start or Restart Inactivity Timer. */ OSPF_NSM_TIMER_OFF(nbr->t_inactivity); @@ -421,7 +421,7 @@ const struct { { /* DependUpon: dummy state. */ {NULL, NSM_DependUpon}, /* NoEvent */ - {NULL, NSM_DependUpon}, /* PacketReceived */ + {NULL, NSM_DependUpon}, /* HelloReceived */ {NULL, NSM_DependUpon}, /* Start */ {NULL, NSM_DependUpon}, /* 2-WayReceived */ {NULL, NSM_DependUpon}, /* NegotiationDone */ @@ -438,7 +438,7 @@ const struct { { /* Deleted: dummy state. */ {NULL, NSM_Deleted}, /* NoEvent */ - {NULL, NSM_Deleted}, /* PacketReceived */ + {NULL, NSM_Deleted}, /* HelloReceived */ {NULL, NSM_Deleted}, /* Start */ {NULL, NSM_Deleted}, /* 2-WayReceived */ {NULL, NSM_Deleted}, /* NegotiationDone */ @@ -455,8 +455,8 @@ const struct { { /* Down: */ {NULL, NSM_DependUpon}, /* NoEvent */ - {nsm_packet_received, NSM_Init}, /* PacketReceived */ - {nsm_start, NSM_Attempt}, /* Start */ + {nsm_hello_received, NSM_Init}, /* HelloReceived */ + {nsm_start, NSM_Attempt}, /* Start */ {NULL, NSM_Down}, /* 2-WayReceived */ {NULL, NSM_Down}, /* NegotiationDone */ {NULL, NSM_Down}, /* ExchangeDone */ @@ -472,7 +472,7 @@ const struct { { /* Attempt: */ {NULL, NSM_DependUpon}, /* NoEvent */ - {nsm_packet_received, NSM_Init}, /* PacketReceived */ + {nsm_hello_received, NSM_Init}, /* HelloReceived */ {NULL, NSM_Attempt}, /* Start */ {NULL, NSM_Attempt}, /* 2-WayReceived */ {NULL, NSM_Attempt}, /* NegotiationDone */ @@ -489,7 +489,7 @@ const struct { { /* Init: */ {NULL, NSM_DependUpon}, /* NoEvent */ - {nsm_packet_received, NSM_Init}, /* PacketReceived */ + {nsm_hello_received, NSM_Init}, /* HelloReceived */ {NULL, NSM_Init}, /* Start */ {nsm_twoway_received, NSM_DependUpon}, /* 2-WayReceived */ {NULL, NSM_Init}, /* NegotiationDone */ @@ -506,7 +506,7 @@ const struct { { /* 2-Way: */ {NULL, NSM_DependUpon}, /* NoEvent */ - {nsm_packet_received, NSM_TwoWay}, /* HelloReceived */ + {nsm_hello_received, NSM_TwoWay}, /* HelloReceived */ {NULL, NSM_TwoWay}, /* Start */ {NULL, NSM_TwoWay}, /* 2-WayReceived */ {NULL, NSM_TwoWay}, /* NegotiationDone */ @@ -523,7 +523,7 @@ const struct { { /* ExStart: */ {NULL, NSM_DependUpon}, /* NoEvent */ - {nsm_packet_received, NSM_ExStart}, /* PacaketReceived */ + {nsm_hello_received, NSM_ExStart}, /* HelloReceived */ {NULL, NSM_ExStart}, /* Start */ {NULL, NSM_ExStart}, /* 2-WayReceived */ {nsm_negotiation_done, NSM_Exchange}, /* NegotiationDone */ @@ -540,7 +540,7 @@ const struct { { /* Exchange: */ {NULL, NSM_DependUpon}, /* NoEvent */ - {nsm_packet_received, NSM_Exchange}, /* PacketReceived */ + {nsm_hello_received, NSM_Exchange}, /* HelloReceived */ {NULL, NSM_Exchange}, /* Start */ {NULL, NSM_Exchange}, /* 2-WayReceived */ {NULL, NSM_Exchange}, /* NegotiationDone */ @@ -557,7 +557,7 @@ const struct { { /* Loading: */ {NULL, NSM_DependUpon}, /* NoEvent */ - {nsm_packet_received, NSM_Loading}, /* PacketReceived */ + {nsm_hello_received, NSM_Loading}, /* HelloReceived */ {NULL, NSM_Loading}, /* Start */ {NULL, NSM_Loading}, /* 2-WayReceived */ {NULL, NSM_Loading}, /* NegotiationDone */ @@ -574,7 +574,7 @@ const struct { { /* Full: */ {NULL, NSM_DependUpon}, /* NoEvent */ - {nsm_packet_received, NSM_Full}, /* PacketReceived */ + {nsm_hello_received, NSM_Full}, /* HelloReceived */ {NULL, NSM_Full}, /* Start */ {NULL, NSM_Full}, /* 2-WayReceived */ {NULL, NSM_Full}, /* NegotiationDone */ @@ -591,7 +591,7 @@ const struct { }; static const char *const ospf_nsm_event_str[] = { - "NoEvent", "PacketReceived", "Start", + "NoEvent", "HelloReceived", "Start", "2-WayReceived", "NegotiationDone", "ExchangeDone", "BadLSReq", "LoadingDone", "AdjOK?", "SeqNumberMismatch", "1-WayReceived", "KillNbr", diff --git a/ospfd/ospf_nsm.h b/ospfd/ospf_nsm.h index e8573c6301a5..798325f79098 100644 --- a/ospfd/ospf_nsm.h +++ b/ospfd/ospf_nsm.h @@ -40,7 +40,7 @@ /* OSPF Neighbor State Machine Event. */ #define NSM_NoEvent 0 -#define NSM_PacketReceived 1 /* HelloReceived in the protocol */ +#define NSM_HelloReceived 1 /* HelloReceived in the protocol */ #define NSM_Start 2 #define NSM_TwoWayReceived 3 #define NSM_NegotiationDone 4 diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index 1efdfee3b497..1dcf93dcdef7 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -1031,7 +1031,7 @@ static void ospf_hello(struct ip *iph, struct ospf_header *ospfh, old_state = nbr->state; /* Add event to thread. */ - OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_PacketReceived); + OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_HelloReceived); /* RFC2328 Section 9.5.1 If the router is not eligible to become Designated Router, @@ -1375,9 +1375,6 @@ static void ospf_db_desc(struct ip *iph, struct ospf_header *ospfh, UNSET_FLAG(dd->options, OSPF_OPTION_O); } - /* Add event to thread. */ - OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_PacketReceived); - if (CHECK_FLAG(oi->ospf->config, OSPF_LOG_ADJACENCY_DETAIL)) zlog_info( "%s:Packet[DD]: Neighbor %pI4 state is %s, seq_num:0x%x, local:0x%x", @@ -1620,9 +1617,6 @@ static void ospf_ls_req(struct ip *iph, struct ospf_header *ospfh, return; } - /* Add event to thread. */ - OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_PacketReceived); - /* Neighbor State should be Exchange or later. */ if (nbr->state != NSM_Exchange && nbr->state != NSM_Loading && nbr->state != NSM_Full) { @@ -1867,9 +1861,6 @@ static void ospf_ls_upd(struct ospf *ospf, struct ip *iph, return; } - /* Add event to thread. */ - OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_PacketReceived); - /* Check neighbor state. */ if (nbr->state < NSM_Exchange) { if (IS_DEBUG_OSPF(nsm, NSM_EVENTS)) @@ -2256,9 +2247,6 @@ static void ospf_ls_ack(struct ip *iph, struct ospf_header *ospfh, return; } - /* Add event to thread. */ - OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_PacketReceived); - if (nbr->state < NSM_Exchange) { if (IS_DEBUG_OSPF(nsm, NSM_EVENTS)) zlog_debug( From c0fa628e995b1eac223ef936ba2d9427962586a9 Mon Sep 17 00:00:00 2001 From: Mark Stapp Date: Wed, 6 Oct 2021 13:49:52 -0400 Subject: [PATCH 101/188] tests: clean up all_proto_startup a bit Remove references to the deprecated "CLI()" function; clean up a couple of string escapes; make one test-case sensitive to previous failures. Signed-off-by: Mark Stapp --- .../test_all_protocol_startup.py | 55 ++++--------------- 1 file changed, 12 insertions(+), 43 deletions(-) diff --git a/tests/topotests/all_protocol_startup/test_all_protocol_startup.py b/tests/topotests/all_protocol_startup/test_all_protocol_startup.py index 1b99fcea1f25..5e1d95c00bbf 100644 --- a/tests/topotests/all_protocol_startup/test_all_protocol_startup.py +++ b/tests/topotests/all_protocol_startup/test_all_protocol_startup.py @@ -115,7 +115,7 @@ def setup_module(module): tgen.gears["r%s" % i].start() # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) + # tgen.mininet_cli() def teardown_module(module): @@ -127,7 +127,8 @@ def teardown_module(module): def test_router_running(): global fatal_error - net = get_topogen().net + tgen = get_topogen() + net = tgen.net # Skip if previous fatal error condition is raised if fatal_error != "": @@ -143,7 +144,7 @@ def test_router_running(): assert fatal_error == "", fatal_error # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) + # tgen.mininet_cli() def test_error_messages_vtysh(): @@ -198,9 +199,6 @@ def test_error_messages_vtysh(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_error_messages_daemons(): global fatal_error @@ -289,9 +287,6 @@ def test_error_messages_daemons(): assert error_logs == "", "Daemons report errors to StdErr" - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_converge_protocols(): global fatal_error @@ -325,7 +320,7 @@ def test_converge_protocols(): actual = ( net["r%s" % i] .cmd( - "vtysh -c \"show ip route\" | sed -e '/^Codes: /,/^\s*$/d' | sort 2> /dev/null" + "vtysh -c \"show ip route\" | sed -e '/^Codes: /,/^\\s*$/d' | sort 2> /dev/null" ) .rstrip() ) @@ -358,7 +353,7 @@ def test_converge_protocols(): actual = ( net["r%s" % i] .cmd( - "vtysh -c \"show ipv6 route\" | sed -e '/^Codes: /,/^\s*$/d' | sort 2> /dev/null" + "vtysh -c \"show ipv6 route\" | sed -e '/^Codes: /,/^\\s*$/d' | sort 2> /dev/null" ) .rstrip() ) @@ -379,9 +374,6 @@ def test_converge_protocols(): assert failures == 0, "IPv6 Routing table failed for r%s\n%s" % (i, diff) - # For debugging after starting FRR daemons, uncomment the next line - ## CLI(net) - def route_get_nhg_id(route_str): net = get_topogen().net @@ -567,8 +559,6 @@ def test_nexthop_groups(): % nhg_id ) - ##CLI(net) - ## Remove all NHG routes net["r1"].cmd('vtysh -c "sharp remove routes 2.2.2.1 1"') @@ -638,9 +628,6 @@ def test_rip_status(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_ripng_status(): global fatal_error @@ -705,9 +692,6 @@ def test_ripng_status(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_ospfv2_interfaces(): global fatal_error @@ -790,9 +774,6 @@ def test_ospfv2_interfaces(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_isis_interfaces(): global fatal_error @@ -856,9 +837,6 @@ def test_isis_interfaces(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_bgp_summary(): global fatal_error @@ -1037,9 +1015,6 @@ def test_bgp_summary(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_bgp_ipv6_summary(): global fatal_error @@ -1138,12 +1113,15 @@ def test_bgp_ipv6_summary(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_nht(): + global fatal_error net = get_topogen().net + + # Skip if previous fatal error condition is raised + if fatal_error != "": + pytest.skip(fatal_error) + print("\n\n**** Test that nexthop tracking is at least nominally working ****\n") thisDir = os.path.dirname(os.path.realpath(__file__)) @@ -1256,9 +1234,6 @@ def test_bgp_ipv4(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_bgp_ipv6(): global fatal_error @@ -1325,9 +1300,6 @@ def test_bgp_ipv6(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_route_map(): global fatal_error @@ -1567,9 +1539,6 @@ def test_mpls_interfaces(): fatal_error = net["r%s" % i].checkRouterRunning() assert fatal_error == "", fatal_error - # For debugging after starting FRR daemons, uncomment the next line - # CLI(net) - def test_shutdown_check_stderr(): global fatal_error From 7640e3c60b33e13376185a0e0c85f3f6c272d0a9 Mon Sep 17 00:00:00 2001 From: Igor Ryzhov Date: Thu, 7 Oct 2021 15:53:10 +0300 Subject: [PATCH 102/188] *: don't pass pointers to a local variables to thread_add_* We should never pass pointers to local variables to thread_add_* family. When an event is executed, the library writes into this pointer, which means it writes into some random memory on a stack. Signed-off-by: Igor Ryzhov --- ldpd/ldpd.c | 3 +-- lib/agentx.c | 20 ++++++++++++-------- lib/northbound_confd.c | 34 ++++++++++++++++++++++++---------- lib/northbound_sysrepo.c | 9 ++++----- 4 files changed, 41 insertions(+), 25 deletions(-) diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c index 9d80bed77f81..0ff3238ff955 100644 --- a/ldpd/ldpd.c +++ b/ldpd/ldpd.c @@ -243,7 +243,6 @@ main(int argc, char *argv[]) int pipe_parent2ldpe[2], pipe_parent2ldpe_sync[2]; int pipe_parent2lde[2], pipe_parent2lde_sync[2]; char *ctl_sock_name; - struct thread *thread = NULL; bool ctl_sock_used = false; snprintf(ctl_sock_path, sizeof(ctl_sock_path), LDPD_SOCKET, @@ -393,7 +392,7 @@ main(int argc, char *argv[]) frr_config_fork(); /* apply configuration */ - thread_add_event(master, ldp_config_fork_apply, NULL, 0, &thread); + thread_add_event(master, ldp_config_fork_apply, NULL, 0, NULL); /* setup pipes to children */ if ((iev_ldpe = calloc(1, sizeof(struct imsgev))) == NULL || diff --git a/lib/agentx.c b/lib/agentx.c index 6d4e68d65110..5f865ca2b834 100644 --- a/lib/agentx.c +++ b/lib/agentx.c @@ -63,6 +63,8 @@ static int agentx_read(struct thread *t) int flags, new_flags = 0; int nonblock = false; struct listnode *ln = THREAD_ARG(t); + struct thread **thr = listgetdata(ln); + XFREE(MTYPE_TMP, thr); list_delete_node(events, ln); /* fix for non blocking socket */ @@ -109,7 +111,7 @@ static void agentx_events_update(void) struct timeval timeout = {.tv_sec = 0, .tv_usec = 0}; fd_set fds; struct listnode *ln; - struct thread *thr; + struct thread **thr; int fd, thr_fd; thread_cancel(&timeout_thr); @@ -125,7 +127,7 @@ static void agentx_events_update(void) ln = listhead(events); thr = ln ? listgetdata(ln) : NULL; - thr_fd = thr ? THREAD_FD(thr) : -1; + thr_fd = thr ? THREAD_FD(*thr) : -1; /* "two-pointer" / two-list simultaneous iteration * ln/thr/thr_fd point to the next existing event listener to hit while @@ -135,20 +137,21 @@ static void agentx_events_update(void) if (thr_fd == fd) { struct listnode *nextln = listnextnode(ln); if (!FD_ISSET(fd, &fds)) { - thread_cancel(&thr); + thread_cancel(thr); + XFREE(MTYPE_TMP, thr); list_delete_node(events, ln); } ln = nextln; thr = ln ? listgetdata(ln) : NULL; - thr_fd = thr ? THREAD_FD(thr) : -1; + thr_fd = thr ? THREAD_FD(*thr) : -1; } /* need listener, but haven't hit one where it would be */ else if (FD_ISSET(fd, &fds)) { struct listnode *newln; - thr = NULL; - thread_add_read(agentx_tm, agentx_read, NULL, fd, &thr); + thr = XCALLOC(MTYPE_TMP, sizeof(struct thread *)); + thread_add_read(agentx_tm, agentx_read, NULL, fd, thr); newln = listnode_add_before(events, ln, thr); - thr->arg = newln; + (*thr)->arg = newln; } } @@ -157,7 +160,8 @@ static void agentx_events_update(void) while (ln) { struct listnode *nextln = listnextnode(ln); thr = listgetdata(ln); - thread_cancel(&thr); + thread_cancel(thr); + XFREE(MTYPE_TMP, thr); list_delete_node(events, ln); ln = nextln; } diff --git a/lib/northbound_confd.c b/lib/northbound_confd.c index 76af494e30b3..e62a83cee27c 100644 --- a/lib/northbound_confd.c +++ b/lib/northbound_confd.c @@ -425,8 +425,7 @@ static int frr_confd_cdb_read_cb(struct thread *thread) int *subp = NULL; int reslen = 0; - thread = NULL; - thread_add_read(master, frr_confd_cdb_read_cb, NULL, fd, &thread); + thread_add_read(master, frr_confd_cdb_read_cb, NULL, fd, &t_cdb_sub); if (cdb_read_subscription_socket2(fd, &cdb_ev, &flags, &subp, &reslen) != CONFD_OK) { @@ -1164,15 +1163,10 @@ static int frr_confd_action_execute(struct confd_user_info *uinfo, } -static int frr_confd_dp_read(struct thread *thread) +static int frr_confd_dp_read(struct confd_daemon_ctx *dctx, int fd) { - struct confd_daemon_ctx *dctx = THREAD_ARG(thread); - int fd = THREAD_FD(thread); int ret; - thread = NULL; - thread_add_read(master, frr_confd_dp_read, dctx, fd, &thread); - ret = confd_fd_ready(dctx, fd); if (ret == CONFD_EOF) { flog_err_confd("confd_fd_ready"); @@ -1187,6 +1181,26 @@ static int frr_confd_dp_read(struct thread *thread) return 0; } +static int frr_confd_dp_ctl_read(struct thread *thread) +{ + struct confd_daemon_ctx *dctx = THREAD_ARG(thread); + int fd = THREAD_FD(thread); + + thread_add_read(master, frr_confd_dp_ctl_read, dctx, fd, &t_dp_ctl); + + frr_confd_dp_read(dctx, fd); +} + +static int frr_confd_dp_worker_read(struct thread *thread) +{ + struct confd_daemon_ctx *dctx = THREAD_ARG(thread); + int fd = THREAD_FD(thread); + + thread_add_read(master, frr_confd_dp_worker_read, dctx, fd, &t_dp_worker); + + frr_confd_dp_read(dctx, fd); +} + static int frr_confd_subscribe_state(const struct lysc_node *snode, void *arg) { struct nb_node *nb_node = snode->priv; @@ -1314,9 +1328,9 @@ static int frr_confd_init_dp(const char *program_name) goto error; } - thread_add_read(master, frr_confd_dp_read, dctx, dp_ctl_sock, + thread_add_read(master, frr_confd_dp_ctl_read, dctx, dp_ctl_sock, &t_dp_ctl); - thread_add_read(master, frr_confd_dp_read, dctx, dp_worker_sock, + thread_add_read(master, frr_confd_dp_worker_read, dctx, dp_worker_sock, &t_dp_worker); return 0; diff --git a/lib/northbound_sysrepo.c b/lib/northbound_sysrepo.c index 7c463dd61f0e..86a159e5079b 100644 --- a/lib/northbound_sysrepo.c +++ b/lib/northbound_sysrepo.c @@ -528,19 +528,18 @@ static int frr_sr_notification_send(const char *xpath, struct list *arguments) static int frr_sr_read_cb(struct thread *thread) { - sr_subscription_ctx_t *sr_subscription = THREAD_ARG(thread); + struct yang_module *module = THREAD_ARG(thread); int fd = THREAD_FD(thread); int ret; - ret = sr_process_events(sr_subscription, session, NULL); + ret = sr_process_events(module->sr_subscription, session, NULL); if (ret != SR_ERR_OK) { flog_err(EC_LIB_LIBSYSREPO, "%s: sr_fd_event_process(): %s", __func__, sr_strerror(ret)); return -1; } - thread = NULL; - thread_add_read(master, frr_sr_read_cb, sr_subscription, fd, &thread); + thread_add_read(master, frr_sr_read_cb, module, fd, &module->sr_thread); return 0; } @@ -703,7 +702,7 @@ static int frr_sr_init(void) sr_strerror(ret)); goto cleanup; } - thread_add_read(master, frr_sr_read_cb, module->sr_subscription, + thread_add_read(master, frr_sr_read_cb, module, event_pipe, &module->sr_thread); } From c08050d6d10a5acab3d044858b5480bb01351cff Mon Sep 17 00:00:00 2001 From: Donatas Abraitis Date: Thu, 7 Oct 2021 16:20:35 +0300 Subject: [PATCH 103/188] tools: Catch double pointer of struct thread towards thread_add_* ``` % spatch --sp-file tools/coccinelle/struct_thread_double_pointer.cocci --macro-file tools/cocci.h ./ 2>/dev/null ./lib/northbound_confd.c:429:65-66: Passed double 'struct thread' pointer ./lib/northbound_confd.c:1174:61-62: Passed double 'struct thread' pointer ./lib/northbound_sysrepo.c:543:69-70: Passed double 'struct thread' pointer ``` Signed-off-by: Donatas Abraitis --- .../struct_thread_double_pointer.cocci | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 tools/coccinelle/struct_thread_double_pointer.cocci diff --git a/tools/coccinelle/struct_thread_double_pointer.cocci b/tools/coccinelle/struct_thread_double_pointer.cocci new file mode 100644 index 000000000000..a08e6727cf77 --- /dev/null +++ b/tools/coccinelle/struct_thread_double_pointer.cocci @@ -0,0 +1,35 @@ +@r1@ +identifier fn, m, f, a, v, t; +identifier func =~ "thread_add_"; +type T1, T2; +position p; +@@ + +?static +T1 fn(T2 *t) +{ +... +func(m,f,a,v,&t)@p +... +} + +@r2@ +identifier m, f, a, v, t; +identifier func =~ "thread_add_"; +type T1; +position p; +@@ + +T1 *t; +... +func(m,f,a,v,&t)@p + +@script:python@ +p << r1.p; +@@ +coccilib.report.print_report(p[0],"Passed double 'struct thread' pointer") + +@script:python@ +p << r2.p; +@@ +coccilib.report.print_report(p[0],"Passed double 'struct thread' pointer") From d3120452c480c5ac85a3b626df3f64b21bbca2f0 Mon Sep 17 00:00:00 2001 From: Igor Ryzhov Date: Thu, 7 Oct 2021 18:29:22 +0300 Subject: [PATCH 104/188] bgpd: add missing vrf/view parameter to one command "show bgp neighbors PEER received prefix-filter" misses the argument. Signed-off-by: Igor Ryzhov --- bgpd/bgp_route.c | 53 +++++++++++++++--------------------------------- doc/user/bgp.rst | 4 ++++ 2 files changed, 20 insertions(+), 37 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index fc9717845006..1111f867c4d3 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -13961,10 +13961,11 @@ DEFPY (show_ip_bgp_instance_neighbor_advertised_route, DEFUN (show_ip_bgp_neighbor_received_prefix_filter, show_ip_bgp_neighbor_received_prefix_filter_cmd, - "show [ip] bgp [ [unicast]] neighbors received prefix-filter [json]", + "show [ip] bgp [ VIEWVRFNAME] [ [unicast]] neighbors received prefix-filter [json]", SHOW_STR IP_STR BGP_STR + BGP_INSTANCE_HELP_STR "Address Family\n" "Address Family\n" "Address Family modifier\n" @@ -13979,50 +13980,28 @@ DEFUN (show_ip_bgp_neighbor_received_prefix_filter, afi_t afi = AFI_IP6; safi_t safi = SAFI_UNICAST; char *peerstr = NULL; - char name[BUFSIZ]; - union sockunion su; struct peer *peer; - int count, ret; - + int count; int idx = 0; + struct bgp *bgp = NULL; + bool uj = use_json(argc, argv); + + if (uj) + argc--; + + bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi, + &bgp, uj); + if (!idx) + return CMD_WARNING; - /* show [ip] bgp */ - if (argv_find(argv, argc, "ip", &idx)) - afi = AFI_IP; - /* [ [unicast]] */ - if (argv_find(argv, argc, "ipv4", &idx)) - afi = AFI_IP; - if (argv_find(argv, argc, "ipv6", &idx)) - afi = AFI_IP6; /* neighbors */ argv_find(argv, argc, "neighbors", &idx); peerstr = argv[++idx]->arg; - bool uj = use_json(argc, argv); - - ret = str2sockunion(peerstr, &su); - if (ret < 0) { - peer = peer_lookup_by_conf_if(NULL, peerstr); - if (!peer) { - if (uj) - vty_out(vty, "{}\n"); - else - vty_out(vty, - "%% Malformed address or name: %s\n", - peerstr); - return CMD_WARNING; - } - } else { - peer = peer_lookup(NULL, &su); - if (!peer) { - if (uj) - vty_out(vty, "{}\n"); - else - vty_out(vty, "No peer\n"); - return CMD_WARNING; - } - } + peer = peer_lookup_in_view(vty, bgp, peerstr, uj); + if (!peer) + return CMD_WARNING; snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi); count = prefix_bgp_show_prefix_list(NULL, afi, name, uj); diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst index d37c2b668280..5fcddafaaad2 100644 --- a/doc/user/bgp.rst +++ b/doc/user/bgp.rst @@ -3540,6 +3540,10 @@ structure is extended with :clicmd:`show bgp [afi] [safi]`. The ``received-routes`` keyword displays all routes belonging to this address-family (prior to inbound policy) that were received by this peer. +.. clicmd:: show bgp [ VIEWVRFNAME] [afi] [safi] neighbors PEER received prefix-filter [json] + + Display Address Prefix ORFs received from this peer. + .. clicmd:: show bgp [afi] [safi] [all] dampening dampened-paths [wide|json] Display paths suppressed due to dampening of the selected afi and safi From cc3d8343087d47393c5485280e0daa204b0eb99a Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 7 Oct 2021 12:02:57 -0400 Subject: [PATCH 105/188] zebra: GR data was being printed 2 times for `show zebra client` When issuing the `show zebra client` command data about Graceful Restart state is being printed 2 times. Signed-off-by: Donald Sharp --- zebra/zserv.c | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/zebra/zserv.c b/zebra/zserv.c index e4a48093f7cb..0c4515a695ab 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -1007,7 +1007,6 @@ static void zebra_show_client_detail(struct vty *vty, struct zserv *client) char wbuf[ZEBRA_TIME_BUF], nhbuf[ZEBRA_TIME_BUF], mbuf[ZEBRA_TIME_BUF]; time_t connect_time, last_read_time, last_write_time; uint32_t last_read_cmd, last_write_cmd; - struct client_gr_info *info = NULL; vty_out(vty, "Client: %s", zebra_route_string(client->proto)); if (client->instance) @@ -1100,22 +1099,6 @@ static void zebra_show_client_detail(struct vty *vty, struct zserv *client) client->local_es_evi_add_cnt, 0, client->local_es_evi_del_cnt); vty_out(vty, "Errors: %u\n", client->error_cnt); - TAILQ_FOREACH (info, &client->gr_info_queue, gr_info) { - vty_out(vty, "VRF : %s\n", vrf_id_to_name(info->vrf_id)); - vty_out(vty, "Capabilities : "); - switch (info->capabilities) { - case ZEBRA_CLIENT_GR_CAPABILITIES: - vty_out(vty, "Graceful Restart\n"); - break; - case ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE: - case ZEBRA_CLIENT_ROUTE_UPDATE_PENDING: - case ZEBRA_CLIENT_GR_DISABLE: - case ZEBRA_CLIENT_RIB_STALE_TIME: - vty_out(vty, "None\n"); - break; - } - } - #if defined DEV_BUILD vty_out(vty, "Input Fifo: %zu:%zu Output Fifo: %zu:%zu\n", client->ibuf_fifo->count, client->ibuf_fifo->max_count, From 76ab1a97021a7a6f00de9e87643d589c844a3421 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 7 Oct 2021 12:08:42 -0400 Subject: [PATCH 106/188] zebra: Display how long zebra is expected to wait for GR When a client sends to zebra that GR mode is being turned on. The client also passes down the time zebra should hold onto the routes. Display this time with the output of the `show zebra client` command as well. Signed-off-by: Donald Sharp --- zebra/zserv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zebra/zserv.c b/zebra/zserv.c index 0c4515a695ab..abb9c5ca5dc2 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -1134,7 +1134,8 @@ static void zebra_show_stale_client_detail(struct vty *vty, vty_out(vty, "Capabilities : "); switch (info->capabilities) { case ZEBRA_CLIENT_GR_CAPABILITIES: - vty_out(vty, "Graceful Restart\n"); + vty_out(vty, "Graceful Restart(%u seconds)\n", + info->stale_removal_time); break; case ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE: case ZEBRA_CLIENT_ROUTE_UPDATE_PENDING: From 1a8e5aea78aba2d38de0e7bc7bdbe0e4b5a6960d Mon Sep 17 00:00:00 2001 From: Donatas Abraitis Date: Thu, 7 Oct 2021 12:22:18 +0300 Subject: [PATCH 107/188] tests: Do not explicitly set the thread pointer to NULL FRR should only ever use the appropriate THREAD_ON/THREAD_OFF semantics. This is espacially true for the functions we end up calling the thread for. Signed-off-by: Donatas Abraitis --- tests/lib/test_timer_correctness.c | 1 - tests/lib/test_timer_performance.c | 1 - 2 files changed, 2 deletions(-) diff --git a/tests/lib/test_timer_correctness.c b/tests/lib/test_timer_correctness.c index 0ae9761b117c..1756d87a6f42 100644 --- a/tests/lib/test_timer_correctness.c +++ b/tests/lib/test_timer_correctness.c @@ -153,7 +153,6 @@ int main(int argc, char **argv) XFREE(MTYPE_TMP, timers[index]->arg); thread_cancel(&timers[index]); - timers[index] = NULL; timers_pending--; } diff --git a/tests/lib/test_timer_performance.c b/tests/lib/test_timer_performance.c index 23c044c7c1a0..f9d634b6a6d4 100644 --- a/tests/lib/test_timer_performance.c +++ b/tests/lib/test_timer_performance.c @@ -77,7 +77,6 @@ int main(int argc, char **argv) index = prng_rand(prng) % SCHEDULE_TIMERS; thread_cancel(&timers[index]); - timers[index] = NULL; } monotime(&tv_stop); From 30634856b419abac5ac65b7e0269d8d61b7b00a2 Mon Sep 17 00:00:00 2001 From: Donatas Abraitis Date: Thu, 7 Oct 2021 12:25:59 +0300 Subject: [PATCH 108/188] ospfd: Do not explicitly set the thread pointer to NULL FRR should only ever use the appropriate THREAD_ON/THREAD_OFF semantics. This is espacially true for the functions we end up calling the thread for. Signed-off-by: Donatas Abraitis --- ospfd/ospf_opaque.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/ospfd/ospf_opaque.c b/ospfd/ospf_opaque.c index 9ec2ed0aa8df..394c3142eb99 100644 --- a/ospfd/ospf_opaque.c +++ b/ospfd/ospf_opaque.c @@ -578,7 +578,6 @@ register_opaque_info_per_type(struct ospf_opaque_functab *functab, oipt->lsa_type = new->data->type; oipt->opaque_type = GET_OPAQUE_TYPE(ntohl(new->data->id.s_addr)); oipt->status = PROC_NORMAL; - oipt->t_opaque_lsa_self = NULL; oipt->functab = functab; functab->oipt = oipt; oipt->id_list = list_new(); @@ -703,7 +702,6 @@ register_opaque_info_per_id(struct opaque_info_per_type *oipt, sizeof(struct opaque_info_per_id)); oipi->opaque_id = GET_OPAQUE_ID(ntohl(new->data->id.s_addr)); - oipi->t_opaque_lsa_self = NULL; oipi->opqctl_type = oipt; oipi->lsa = ospf_lsa_lock(new); @@ -1845,7 +1843,6 @@ static int ospf_opaque_type9_lsa_reoriginate_timer(struct thread *t) int rc = -1; oipt = THREAD_ARG(t); - oipt->t_opaque_lsa_self = NULL; if ((functab = oipt->functab) == NULL || functab->lsa_originator == NULL) { @@ -1897,7 +1894,6 @@ static int ospf_opaque_type10_lsa_reoriginate_timer(struct thread *t) int n, rc = -1; oipt = THREAD_ARG(t); - oipt->t_opaque_lsa_self = NULL; if ((functab = oipt->functab) == NULL || functab->lsa_originator == NULL) { @@ -1951,7 +1947,6 @@ static int ospf_opaque_type11_lsa_reoriginate_timer(struct thread *t) int rc = -1; oipt = THREAD_ARG(t); - oipt->t_opaque_lsa_self = NULL; if ((functab = oipt->functab) == NULL || functab->lsa_originator == NULL) { @@ -2067,7 +2062,6 @@ static int ospf_opaque_lsa_refresh_timer(struct thread *t) zlog_debug("Timer[Opaque-LSA]: (Opaque-LSA Refresh expire)"); oipi = THREAD_ARG(t); - oipi->t_opaque_lsa_self = NULL; if ((lsa = oipi->lsa) != NULL) if ((functab = oipi->opqctl_type->functab) != NULL) From ae84497d13b2970febfa71b45b6d4b021bb27804 Mon Sep 17 00:00:00 2001 From: Donatas Abraitis Date: Thu, 7 Oct 2021 13:20:15 +0300 Subject: [PATCH 109/188] isisd: Do not explicitly set the thread pointer to NULL FRR should only ever use the appropriate THREAD_ON/THREAD_OFF semantics. This is espacially true for the functions we end up calling the thread for. Signed-off-by: Donatas Abraitis --- isisd/fabricd.c | 2 -- isisd/isis_spf.c | 1 - 2 files changed, 3 deletions(-) diff --git a/isisd/fabricd.c b/isisd/fabricd.c index 0f10a1516a15..2937df992c65 100644 --- a/isisd/fabricd.c +++ b/isisd/fabricd.c @@ -258,7 +258,6 @@ static int fabricd_initial_sync_timeout(struct thread *thread) f->initial_sync_circuit->interface->name); f->initial_sync_state = FABRICD_SYNC_PENDING; f->initial_sync_circuit = NULL; - f->initial_sync_timeout = NULL; return 0; } @@ -403,7 +402,6 @@ static uint8_t fabricd_calculate_fabric_tier(struct isis_area *area) static int fabricd_tier_set_timer(struct thread *thread) { struct fabricd *f = THREAD_ARG(thread); - f->tier_set_timer = NULL; fabricd_set_tier(f, f->tier_pending); return 0; diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c index 45e89897ffa4..5718b48b9d42 100644 --- a/isisd/isis_spf.c +++ b/isisd/isis_spf.c @@ -1840,7 +1840,6 @@ static int isis_run_spf_cb(struct thread *thread) int have_run = 0; XFREE(MTYPE_ISIS_SPF_RUN, run); - area->spf_timer[level - 1] = NULL; if (!(area->is_type & level)) { if (IS_DEBUG_SPF_EVENTS) From d573b8f8639350cfa1edeec6b8e1cd422008ea77 Mon Sep 17 00:00:00 2001 From: Donatas Abraitis Date: Thu, 7 Oct 2021 13:25:43 +0300 Subject: [PATCH 110/188] ospf6d: Do not explicitly set the thread pointer to NULL FRR should only ever use the appropriate THREAD_ON/THREAD_OFF semantics. This is espacially true for the functions we end up calling the thread for. Signed-off-by: Donatas Abraitis --- ospf6d/ospf6_asbr.c | 4 ---- ospf6d/ospf6_gr_helper.c | 2 -- ospf6d/ospf6_intra.c | 5 ----- ospf6d/ospf6_nssa.c | 2 -- ospf6d/ospf6_top.c | 1 - 5 files changed, 14 deletions(-) diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c index 733f4ba1fb71..cd2791fc48cc 100644 --- a/ospf6d/ospf6_asbr.c +++ b/ospf6d/ospf6_asbr.c @@ -204,7 +204,6 @@ int ospf6_orig_as_external_lsa(struct thread *thread) uint32_t type, adv_router; oi = (struct ospf6_interface *)THREAD_ARG(thread); - oi->thread_as_extern_lsa = NULL; if (oi->state == OSPF6_INTERFACE_DOWN) return 0; @@ -1091,8 +1090,6 @@ static int ospf6_asbr_routemap_update_timer(struct thread *thread) struct ospf6_redist *red; int type; - ospf6->t_distribute_update = NULL; - for (type = 0; type < ZEBRA_ROUTE_MAX; type++) { red = ospf6_redist_lookup(ospf6, type, 0); @@ -3372,7 +3369,6 @@ static int ospf6_asbr_summary_process(struct thread *thread) struct ospf6 *ospf6 = THREAD_ARG(thread); int operation = 0; - ospf6->t_external_aggr = NULL; operation = ospf6->aggr_action; if (IS_OSPF6_DEBUG_AGGR) diff --git a/ospf6d/ospf6_gr_helper.c b/ospf6d/ospf6_gr_helper.c index ad8998b1edc0..78f842db6c53 100644 --- a/ospf6d/ospf6_gr_helper.c +++ b/ospf6d/ospf6_gr_helper.c @@ -202,8 +202,6 @@ static int ospf6_handle_grace_timer_expiry(struct thread *thread) { struct ospf6_neighbor *nbr = THREAD_ARG(thread); - nbr->gr_helper_info.t_grace_timer = NULL; - ospf6_gr_helper_exit(nbr, OSPF6_GR_HELPER_GRACE_TIMEOUT); return OSPF6_SUCCESS; } diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c index 2d82ff7ce817..6abc1c7d0993 100644 --- a/ospf6d/ospf6_intra.c +++ b/ospf6d/ospf6_intra.c @@ -248,7 +248,6 @@ int ospf6_router_lsa_originate(struct thread *thread) int count; oa = (struct ospf6_area *)THREAD_ARG(thread); - oa->thread_router_lsa = NULL; if (oa->ospf6->gr_info.restart_in_progress) { if (IS_DEBUG_OSPF6_GR) @@ -533,7 +532,6 @@ int ospf6_network_lsa_originate(struct thread *thread) uint16_t type; oi = (struct ospf6_interface *)THREAD_ARG(thread); - oi->thread_network_lsa = NULL; /* The interface must be enabled until here. A Network-LSA of a disabled interface (but was once enabled) should be flushed @@ -784,7 +782,6 @@ int ospf6_link_lsa_originate(struct thread *thread) struct ospf6_prefix *op; oi = (struct ospf6_interface *)THREAD_ARG(thread); - oi->thread_link_lsa = NULL; assert(oi->area); @@ -1030,7 +1027,6 @@ int ospf6_intra_prefix_lsa_originate_stub(struct thread *thread) int ls_id = 0; oa = (struct ospf6_area *)THREAD_ARG(thread); - oa->thread_intra_prefix_lsa = NULL; if (oa->ospf6->gr_info.restart_in_progress) { if (IS_DEBUG_OSPF6_GR) @@ -1269,7 +1265,6 @@ int ospf6_intra_prefix_lsa_originate_transit(struct thread *thread) uint16_t type; oi = (struct ospf6_interface *)THREAD_ARG(thread); - oi->thread_intra_prefix_lsa = NULL; assert(oi->area); diff --git a/ospf6d/ospf6_nssa.c b/ospf6d/ospf6_nssa.c index 809768fb5ca9..c2e9b7f28af3 100644 --- a/ospf6d/ospf6_nssa.c +++ b/ospf6d/ospf6_nssa.c @@ -1168,8 +1168,6 @@ static int ospf6_abr_task_timer(struct thread *thread) { struct ospf6 *ospf6 = THREAD_ARG(thread); - ospf6->t_abr_task = NULL; - if (IS_OSPF6_DEBUG_ABR) zlog_debug("Running ABR task on timer"); diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index 6fe70552027b..9e3bb4895a82 100644 --- a/ospf6d/ospf6_top.c +++ b/ospf6d/ospf6_top.c @@ -432,7 +432,6 @@ static struct ospf6 *ospf6_create(const char *name) o->rt_aggr_tbl = route_table_init(); o->aggr_delay_interval = OSPF6_EXTL_AGGR_DEFAULT_DELAY; - o->t_external_aggr = NULL; o->aggr_action = OSPF6_ROUTE_AGGR_NONE; o->fd = -1; From 1c49e8138ee377692d8b683fc4bfe292f77b5004 Mon Sep 17 00:00:00 2001 From: Igor Ryzhov Date: Thu, 7 Oct 2021 18:27:29 +0300 Subject: [PATCH 111/188] bgpd: fix crash when using "show bgp vrf all" Any command that uses `peer_lookup_in_view` crashes when "vrf all" is used, because bgp is NULL in this case. Signed-off-by: Igor Ryzhov --- bgpd/bgpd.c | 3 +-- .../all_protocol_startup/test_all_protocol_startup.py | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 925af80cb790..57083440b160 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -7883,8 +7883,7 @@ struct peer *peer_lookup_in_view(struct vty *vty, struct bgp *bgp, json_no, JSON_C_TO_STRING_PRETTY)); json_object_free(json_no); } else - vty_out(vty, "No such neighbor in %s\n", - bgp->name_pretty); + vty_out(vty, "No such neighbor in this view/vrf\n"); return NULL; } diff --git a/tests/topotests/all_protocol_startup/test_all_protocol_startup.py b/tests/topotests/all_protocol_startup/test_all_protocol_startup.py index 1b99fcea1f25..ddb7f4e16e21 100644 --- a/tests/topotests/all_protocol_startup/test_all_protocol_startup.py +++ b/tests/topotests/all_protocol_startup/test_all_protocol_startup.py @@ -966,7 +966,7 @@ def test_bgp_summary(): r"(192.168.7.(1|2)0|fc00:0:0:8::2000).+Active.+", "", expected ) elif "10.0.0.1" in arguments: - expected = "No such neighbor in VRF default" + expected = "No such neighbor in this view/vrf" if "terse" in arguments: expected = re.sub(r"BGP table version .+", "", expected) From 95f473e0d29f4ec39e66aea296b4364bcf34b4ee Mon Sep 17 00:00:00 2001 From: Igor Ryzhov Date: Fri, 8 Oct 2021 14:51:15 +0300 Subject: [PATCH 112/188] bgpd: don't return pointer to a local variable CID 1507651. Signed-off-by: Igor Ryzhov --- bgpd/bgp_table.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bgpd/bgp_table.c b/bgpd/bgp_table.c index 376172a6f91a..4ed8c7c59b71 100644 --- a/bgpd/bgp_table.c +++ b/bgpd/bgp_table.c @@ -88,7 +88,7 @@ struct bgp_dest *bgp_dest_lock_node(struct bgp_dest *dest) const char *bgp_dest_get_prefix_str(struct bgp_dest *dest) { const struct prefix *p = NULL; - char str[PREFIX_STRLEN] = {0}; + static char str[PREFIX_STRLEN] = {0}; p = bgp_dest_get_prefix(dest); if (p) From ab6edbfeef365c7d598e5c171bfcc63687979129 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Thu, 7 Oct 2021 23:45:31 -0300 Subject: [PATCH 113/188] ospfd: preserve DR status across graceful restarts RFC 3623 says: "If the restarting router determines that it was the Designated Router on a given segment prior to the restart, it elects itself as the Designated Router again. The restarting router knows that it was the Designated Router if, while the associated interface is in Waiting state, a Hello packet is received from a neighbor listing the router as the Designated Router". Implement that logic when processing Hello messages to ensure DR interfaces will preserve their DR status across a graceful restart. Signed-off-by: Renato Westphal --- ospfd/ospf_packet.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index 1efdfee3b497..aa576d145240 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -1134,6 +1134,21 @@ static void ospf_hello(struct ip *iph, struct ospf_header *ospfh, nbr->priority = hello->priority; nbr->d_router = hello->d_router; nbr->bd_router = hello->bd_router; + + /* + * RFC 3623 - Section 2: + * "If the restarting router determines that it was the Designated + * Router on a given segment prior to the restart, it elects + * itself as the Designated Router again. The restarting router + * knows that it was the Designated Router if, while the + * associated interface is in Waiting state, a Hello packet is + * received from a neighbor listing the router as the Designated + * Router". + */ + if (oi->area->ospf->gr_info.restart_in_progress + && oi->state == ISM_Waiting + && IPV4_ADDR_SAME(&hello->d_router, &oi->address->u.prefix4)) + DR(oi) = hello->d_router; } /* Save DD flags/options/Seqnum received. */ From 6255aad0bc78c1b110d72988f62427a057c1a80f Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 8 Oct 2021 07:37:15 -0400 Subject: [PATCH 114/188] tests: Fix ospf[6]_gr_topo1 tests to work better under load 2 things: a) Each test was setting up for graceful restart with calls to `graceful-restart prepare ip[v6] ospf`, then sleeping for 3 or 5 seconds. Then killing the ospf process. Under heavy load there is no guarantee that zebra has received/processed this signal. Write some code to ensure that this happens b) Tests are issuing commands in this order: 1) issue gr prepare command 2) kill router 3) 4) start router 5) Imagine that the system is under some load and there is a small amount of time before step 5 happens. In this case ospf could have come up and started neighbor relations and also started installing routes. If zebra receives a new route before step 5 is issued then the route could be in a state where it is not installed, because it is being sent to the kernel for installation. This would fail the test because it would only look 1 time. This is fixed by giving time on restart for the routes to be in the installed state. Signed-off-by: Donald Sharp --- .../ospf6_gr_topo1/test_ospf6_gr_topo1.py | 48 +++++++++++++++---- .../ospf_gr_topo1/test_ospf_gr_topo1.py | 47 ++++++++++++++---- 2 files changed, 78 insertions(+), 17 deletions(-) diff --git a/tests/topotests/ospf6_gr_topo1/test_ospf6_gr_topo1.py b/tests/topotests/ospf6_gr_topo1/test_ospf6_gr_topo1.py index ccbcadb8b12b..d50223191d56 100755 --- a/tests/topotests/ospf6_gr_topo1/test_ospf6_gr_topo1.py +++ b/tests/topotests/ospf6_gr_topo1/test_ospf6_gr_topo1.py @@ -175,10 +175,21 @@ def check_routers(initial_convergence=False, exiting=None, restarting=None): for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6", "rt7"]: # Check the RIB first, which should be preserved across restarts in # all routers of the routing domain. + # If we are not on initial convergence *but* we are checking + # after a restart. Looking in the zebra rib for installed + # is a recipe for test failure. Why? because if we are restarting + # then ospf is in the process of establishing neighbors and passing + # new routes to zebra. Zebra will not mark the route as installed + # when it receives a replacement from ospf until it has finished + # processing it. Let's give it a few seconds to allow this to happen + # under load. if initial_convergence == True: tries = 240 else: - tries = 1 + if restarting != None: + tries = 40 + else: + tries = 1 router_compare_json_output( rname, "show ipv6 route ospf json", "show_ipv6_route.json", tries ) @@ -212,6 +223,26 @@ def check_routers(initial_convergence=False, exiting=None, restarting=None): ) +def ensure_gr_is_in_zebra(rname): + retry = True + retry_times = 10 + tgen = get_topogen() + + while retry and retry_times > 0: + out = tgen.net[rname].cmd( + 'vtysh -c "show zebra client" | grep "Client: ospf6$" -A 40 | grep "Capabilities "' + ) + + if "Graceful Restart" not in out: + sleep(2) + retry_times -= 1 + else: + retry = False + + assertmsg = "%s does not appear to have Graceful Restart setup" % rname + assert not retry and retry_times > 0, assertmsg + + # # Test initial network convergence # @@ -238,10 +269,9 @@ def test_gr_rt1(): pytest.skip(tgen.errors) tgen.net["rt1"].cmd('vtysh -c "graceful-restart prepare ipv6 ospf"') - sleep(5) + ensure_gr_is_in_zebra("rt1") kill_router_daemons(tgen, "rt1", ["ospf6d"], save_config=False) check_routers(exiting="rt1") - start_router_daemons(tgen, "rt1", ["ospf6d"]) check_routers(restarting="rt1") @@ -258,7 +288,7 @@ def test_gr_rt2(): pytest.skip(tgen.errors) tgen.net["rt2"].cmd('vtysh -c "graceful-restart prepare ipv6 ospf"') - sleep(5) + ensure_gr_is_in_zebra("rt2") kill_router_daemons(tgen, "rt2", ["ospf6d"], save_config=False) check_routers(exiting="rt2") @@ -278,7 +308,7 @@ def test_gr_rt3(): pytest.skip(tgen.errors) tgen.net["rt3"].cmd('vtysh -c "graceful-restart prepare ipv6 ospf"') - sleep(5) + ensure_gr_is_in_zebra("rt3") kill_router_daemons(tgen, "rt3", ["ospf6d"], save_config=False) check_routers(exiting="rt3") @@ -298,7 +328,7 @@ def test_gr_rt4(): pytest.skip(tgen.errors) tgen.net["rt4"].cmd('vtysh -c "graceful-restart prepare ipv6 ospf"') - sleep(5) + ensure_gr_is_in_zebra("rt4") kill_router_daemons(tgen, "rt4", ["ospf6d"], save_config=False) check_routers(exiting="rt4") @@ -318,7 +348,7 @@ def test_gr_rt5(): pytest.skip(tgen.errors) tgen.net["rt5"].cmd('vtysh -c "graceful-restart prepare ipv6 ospf"') - sleep(5) + ensure_gr_is_in_zebra("rt5") kill_router_daemons(tgen, "rt5", ["ospf6d"], save_config=False) check_routers(exiting="rt5") @@ -338,7 +368,7 @@ def test_gr_rt6(): pytest.skip(tgen.errors) tgen.net["rt6"].cmd('vtysh -c "graceful-restart prepare ipv6 ospf"') - sleep(5) + ensure_gr_is_in_zebra("rt6") kill_router_daemons(tgen, "rt6", ["ospf6d"], save_config=False) check_routers(exiting="rt6") @@ -358,7 +388,7 @@ def test_gr_rt7(): pytest.skip(tgen.errors) tgen.net["rt7"].cmd('vtysh -c "graceful-restart prepare ipv6 ospf"') - sleep(5) + ensure_gr_is_in_zebra("rt7") kill_router_daemons(tgen, "rt7", ["ospf6d"], save_config=False) check_routers(exiting="rt7") diff --git a/tests/topotests/ospf_gr_topo1/test_ospf_gr_topo1.py b/tests/topotests/ospf_gr_topo1/test_ospf_gr_topo1.py index 7d9cc684128c..1432d53ffc82 100755 --- a/tests/topotests/ospf_gr_topo1/test_ospf_gr_topo1.py +++ b/tests/topotests/ospf_gr_topo1/test_ospf_gr_topo1.py @@ -184,10 +184,21 @@ def check_routers(initial_convergence=False, exiting=None, restarting=None): for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6", "rt7"]: # Check the RIB first, which should be preserved across restarts in # all routers of the routing domain. + # If we are not on initial convergence *but* we are checking + # after a restart. Looking in the zebra rib for installed + # is a recipe for test failure. Why? because if we are restarting + # then ospf is in the process of establishing neighbors and passing + # new routes to zebra. Zebra will not mark the route as installed + # when it receives a replacement from ospf until it has finished + # processing it. Let's give it a few seconds to allow this to happen + # under load. if initial_convergence == True: tries = 240 else: - tries = 1 + if restarting != None: + tries = 40 + else: + tries = 1 router_compare_json_output( rname, "show ip route ospf json", "show_ip_route.json", tries ) @@ -215,6 +226,26 @@ def check_routers(initial_convergence=False, exiting=None, restarting=None): ) +def ensure_gr_is_in_zebra(rname): + retry = True + retry_times = 10 + tgen = get_topogen() + + while retry and retry_times > 0: + out = tgen.net[rname].cmd( + 'vtysh -c "show zebra client" | grep "Client: ospf$" -A 40 | grep "Capabilities "' + ) + + if "Graceful Restart" not in out: + sleep(2) + retry_times -= 1 + else: + retry = False + + assertmsg = "%s does not appear to have Graceful Restart setup" % rname + assert not retry and retry_times > 0, assertmsg + + # # Test initial network convergence # @@ -241,7 +272,7 @@ def test_gr_rt1(): pytest.skip(tgen.errors) tgen.net["rt1"].cmd('vtysh -c "graceful-restart prepare ip ospf"') - sleep(3) + ensure_gr_is_in_zebra("rt1") kill_router_daemons(tgen, "rt1", ["ospfd"], save_config=False) check_routers(exiting="rt1") @@ -261,7 +292,7 @@ def test_gr_rt2(): pytest.skip(tgen.errors) tgen.net["rt2"].cmd('vtysh -c "graceful-restart prepare ip ospf"') - sleep(3) + ensure_gr_is_in_zebra("rt2") kill_router_daemons(tgen, "rt2", ["ospfd"], save_config=False) check_routers(exiting="rt2") @@ -281,7 +312,7 @@ def test_gr_rt3(): pytest.skip(tgen.errors) tgen.net["rt3"].cmd('vtysh -c "graceful-restart prepare ip ospf"') - sleep(3) + ensure_gr_is_in_zebra("rt3") kill_router_daemons(tgen, "rt3", ["ospfd"], save_config=False) check_routers(exiting="rt3") @@ -301,7 +332,7 @@ def test_gr_rt4(): pytest.skip(tgen.errors) tgen.net["rt4"].cmd('vtysh -c "graceful-restart prepare ip ospf"') - sleep(3) + ensure_gr_is_in_zebra("rt4") kill_router_daemons(tgen, "rt4", ["ospfd"], save_config=False) check_routers(exiting="rt4") @@ -321,7 +352,7 @@ def test_gr_rt5(): pytest.skip(tgen.errors) tgen.net["rt5"].cmd('vtysh -c "graceful-restart prepare ip ospf"') - sleep(3) + ensure_gr_is_in_zebra("rt5") kill_router_daemons(tgen, "rt5", ["ospfd"], save_config=False) check_routers(exiting="rt5") @@ -341,7 +372,7 @@ def test_gr_rt6(): pytest.skip(tgen.errors) tgen.net["rt6"].cmd('vtysh -c "graceful-restart prepare ip ospf"') - sleep(3) + ensure_gr_is_in_zebra("rt6") kill_router_daemons(tgen, "rt6", ["ospfd"], save_config=False) check_routers(exiting="rt6") @@ -361,7 +392,7 @@ def test_gr_rt7(): pytest.skip(tgen.errors) tgen.net["rt7"].cmd('vtysh -c "graceful-restart prepare ip ospf"') - sleep(3) + ensure_gr_is_in_zebra("rt7") kill_router_daemons(tgen, "rt7", ["ospfd"], save_config=False) check_routers(exiting="rt7") From a792fa7b150831c1d2f70ddae580e6fc38a51ab0 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Thu, 7 Oct 2021 21:05:20 -0300 Subject: [PATCH 115/188] ospfd: display detailed information about opaque LSAs in JSON format Signed-off-by: Renato Westphal --- ospfd/ospf_opaque.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ospfd/ospf_opaque.c b/ospfd/ospf_opaque.c index 9ec2ed0aa8df..955d9168c4c7 100644 --- a/ospfd/ospf_opaque.c +++ b/ospfd/ospf_opaque.c @@ -1182,6 +1182,16 @@ void show_opaque_info_detail(struct vty *vty, struct ospf_lsa *lsa, VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)"); + } else { + json_object_string_add( + json, "opaqueType", + ospf_opaque_type_name(opaque_type)); + json_object_int_add(json, "opaqueId", opaque_id); + json_object_int_add(json, "opaqueDataLength", + ntohs(lsah->length) + - OSPF_LSA_HEADER_SIZE); + json_object_boolean_add(json, "opaqueDataLengthValid", + VALID_OPAQUE_INFO_LEN(lsah)); } } else { zlog_debug(" Opaque-Type %u (%s)", opaque_type, From 3e63092b83c6710dd978b705537a2bb8c586ea8b Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Thu, 7 Oct 2021 21:06:01 -0300 Subject: [PATCH 116/188] ospfd: fix display of plain-text data on "show ... json" commands Add a 'json' parameter to the 'show_opaque_info' callback definition, and update all instances of that callback to not display plain-text data when the user requested JSON data. Signed-off-by: Renato Westphal --- ospfd/ospf_apiserver.c | 6 +++++- ospfd/ospf_apiserver.h | 3 ++- ospfd/ospf_ext.c | 18 ++++++++++++++---- ospfd/ospf_gr_helper.c | 9 +++++++-- ospfd/ospf_opaque.c | 8 +++++--- ospfd/ospf_opaque.h | 3 ++- ospfd/ospf_ri.c | 11 +++++++++-- ospfd/ospf_te.c | 9 +++++++-- 8 files changed, 51 insertions(+), 16 deletions(-) diff --git a/ospfd/ospf_apiserver.c b/ospfd/ospf_apiserver.c index cbd03441ef94..a33ca957775d 100644 --- a/ospfd/ospf_apiserver.c +++ b/ospfd/ospf_apiserver.c @@ -2059,7 +2059,8 @@ void ospf_apiserver_nsm_change(struct ospf_neighbor *nbr, int old_status) } } -void ospf_apiserver_show_info(struct vty *vty, struct ospf_lsa *lsa) +void ospf_apiserver_show_info(struct vty *vty, struct json_object *json, + struct ospf_lsa *lsa) { struct opaque_lsa { struct lsa_header header; @@ -2070,6 +2071,9 @@ void ospf_apiserver_show_info(struct vty *vty, struct ospf_lsa *lsa) struct opaque_lsa *olsa; int opaquelen; + if (json) + return; + olsa = (struct opaque_lsa *)lsa->data; if (VALID_OPAQUE_INFO_LEN(lsa->data)) diff --git a/ospfd/ospf_apiserver.h b/ospfd/ospf_apiserver.h index 89a94749726c..544a32a28ce1 100644 --- a/ospfd/ospf_apiserver.h +++ b/ospfd/ospf_apiserver.h @@ -182,7 +182,8 @@ extern void ospf_apiserver_nsm_change(struct ospf_neighbor *nbr, extern void ospf_apiserver_config_write_router(struct vty *vty); extern void ospf_apiserver_config_write_if(struct vty *vty, struct interface *ifp); -extern void ospf_apiserver_show_info(struct vty *vty, struct ospf_lsa *lsa); +extern void ospf_apiserver_show_info(struct vty *vty, struct json_object *json, + struct ospf_lsa *lsa); extern int ospf_ospf_apiserver_lsa_originator(void *arg); extern struct ospf_lsa *ospf_apiserver_lsa_refresher(struct ospf_lsa *lsa); extern void ospf_apiserver_flush_opaque_lsa(struct ospf_apiserver *apiserv, diff --git a/ospfd/ospf_ext.c b/ospfd/ospf_ext.c index 2d08eeece234..ea1506ea277d 100644 --- a/ospfd/ospf_ext.c +++ b/ospfd/ospf_ext.c @@ -80,7 +80,8 @@ static struct ospf_ext_lp OspfEXT; */ /* Extended Prefix Opaque LSA related callback functions */ -static void ospf_ext_pref_show_info(struct vty *vty, struct ospf_lsa *lsa); +static void ospf_ext_pref_show_info(struct vty *vty, struct json_object *json, + struct ospf_lsa *lsa); static int ospf_ext_pref_lsa_originate(void *arg); static struct ospf_lsa *ospf_ext_pref_lsa_refresh(struct ospf_lsa *lsa); static void ospf_ext_pref_lsa_schedule(struct ext_itf *exti, @@ -90,7 +91,8 @@ static int ospf_ext_link_new_if(struct interface *ifp); static int ospf_ext_link_del_if(struct interface *ifp); static void ospf_ext_ism_change(struct ospf_interface *oi, int old_status); static void ospf_ext_link_nsm_change(struct ospf_neighbor *nbr, int old_status); -static void ospf_ext_link_show_info(struct vty *vty, struct ospf_lsa *lsa); +static void ospf_ext_link_show_info(struct vty *vty, struct json_object *json, + struct ospf_lsa *lsa); static int ospf_ext_link_lsa_originate(void *arg); static struct ospf_lsa *ospf_ext_link_lsa_refresh(struct ospf_lsa *lsa); static void ospf_ext_link_lsa_schedule(struct ext_itf *exti, @@ -1846,12 +1848,16 @@ static uint16_t show_vty_link_info(struct vty *vty, struct tlv_header *ext, } /* Extended Link TLVs */ -static void ospf_ext_link_show_info(struct vty *vty, struct ospf_lsa *lsa) +static void ospf_ext_link_show_info(struct vty *vty, struct json_object *json, + struct ospf_lsa *lsa) { struct lsa_header *lsah = lsa->data; struct tlv_header *tlvh; uint16_t length = 0, sum = 0; + if (json) + return; + /* Initialize TLV browsing */ length = lsa->size - OSPF_LSA_HEADER_SIZE; @@ -1932,12 +1938,16 @@ static uint16_t show_vty_pref_info(struct vty *vty, struct tlv_header *ext, } /* Extended Prefix TLVs */ -static void ospf_ext_pref_show_info(struct vty *vty, struct ospf_lsa *lsa) +static void ospf_ext_pref_show_info(struct vty *vty, struct json_object *json, + struct ospf_lsa *lsa) { struct lsa_header *lsah = lsa->data; struct tlv_header *tlvh; uint16_t length = 0, sum = 0; + if (json) + return; + /* Initialize TLV browsing */ length = lsa->size - OSPF_LSA_HEADER_SIZE; diff --git a/ospfd/ospf_gr_helper.c b/ospfd/ospf_gr_helper.c index b3eaf7bbdbb6..a58a120b6bab 100644 --- a/ospfd/ospf_gr_helper.c +++ b/ospfd/ospf_gr_helper.c @@ -75,7 +75,8 @@ static const char * const ospf_rejected_reason_desc[] = { "Router is in the process of graceful restart", }; -static void show_ospf_grace_lsa_info(struct vty *vty, struct ospf_lsa *lsa); +static void show_ospf_grace_lsa_info(struct vty *vty, struct json_object *json, + struct ospf_lsa *lsa); static bool ospf_check_change_in_rxmt_list(struct ospf_neighbor *nbr); static unsigned int ospf_enable_rtr_hash_key(const void *data) @@ -1012,7 +1013,8 @@ void ospf_gr_helper_set_supported_planned_only_restart(struct ospf *ospf, * Returns: * Nothing. */ -static void show_ospf_grace_lsa_info(struct vty *vty, struct ospf_lsa *lsa) +static void show_ospf_grace_lsa_info(struct vty *vty, struct json_object *json, + struct ospf_lsa *lsa) { struct lsa_header *lsah = NULL; struct tlv_header *tlvh = NULL; @@ -1022,6 +1024,9 @@ static void show_ospf_grace_lsa_info(struct vty *vty, struct ospf_lsa *lsa) uint16_t length = 0; int sum = 0; + if (json) + return; + lsah = (struct lsa_header *)lsa->data; if (lsa->size <= OSPF_LSA_HEADER_SIZE) { diff --git a/ospfd/ospf_opaque.c b/ospfd/ospf_opaque.c index 955d9168c4c7..a89e90bf70b4 100644 --- a/ospfd/ospf_opaque.c +++ b/ospfd/ospf_opaque.c @@ -274,7 +274,8 @@ struct ospf_opaque_functab { void (*config_write_router)(struct vty *vty); void (*config_write_if)(struct vty *vty, struct interface *ifp); void (*config_write_debug)(struct vty *vty); - void (*show_opaque_info)(struct vty *vty, struct ospf_lsa *lsa); + void (*show_opaque_info)(struct vty *vty, struct json_object *json, + struct ospf_lsa *lsa); int (*lsa_originator)(void *arg); struct ospf_lsa *(*lsa_refresher)(struct ospf_lsa *lsa); int (*new_lsa_hook)(struct ospf_lsa *lsa); @@ -373,7 +374,8 @@ int ospf_register_opaque_functab( void (*config_write_router)(struct vty *vty), void (*config_write_if)(struct vty *vty, struct interface *ifp), void (*config_write_debug)(struct vty *vty), - void (*show_opaque_info)(struct vty *vty, struct ospf_lsa *lsa), + void (*show_opaque_info)(struct vty *vty, struct json_object *json, + struct ospf_lsa *lsa), int (*lsa_originator)(void *arg), struct ospf_lsa *(*lsa_refresher)(struct ospf_lsa *lsa), int (*new_lsa_hook)(struct ospf_lsa *lsa), @@ -1207,7 +1209,7 @@ void show_opaque_info_detail(struct vty *vty, struct ospf_lsa *lsa, /* Call individual output functions. */ if ((functab = ospf_opaque_functab_lookup(lsa)) != NULL) if (functab->show_opaque_info != NULL) - (*functab->show_opaque_info)(vty, lsa); + (*functab->show_opaque_info)(vty, json, lsa); return; } diff --git a/ospfd/ospf_opaque.h b/ospfd/ospf_opaque.h index 7d401c3dcc18..bded32215b0d 100644 --- a/ospfd/ospf_opaque.h +++ b/ospfd/ospf_opaque.h @@ -136,7 +136,8 @@ extern int ospf_register_opaque_functab( void (*config_write_router)(struct vty *vty), void (*config_write_if)(struct vty *vty, struct interface *ifp), void (*config_write_debug)(struct vty *vty), - void (*show_opaque_info)(struct vty *vty, struct ospf_lsa *lsa), + void (*show_opaque_info)(struct vty *vty, struct json_object *json, + struct ospf_lsa *lsa), int (*lsa_originator)(void *arg), struct ospf_lsa *(*lsa_refresher)(struct ospf_lsa *lsa), int (*new_lsa_hook)(struct ospf_lsa *lsa), diff --git a/ospfd/ospf_ri.c b/ospfd/ospf_ri.c index 602f98d14179..0efa6ca4d52a 100644 --- a/ospfd/ospf_ri.c +++ b/ospfd/ospf_ri.c @@ -73,7 +73,9 @@ static struct ospf_router_info OspfRI; static void ospf_router_info_ism_change(struct ospf_interface *oi, int old_status); static void ospf_router_info_config_write_router(struct vty *vty); -static void ospf_router_info_show_info(struct vty *vty, struct ospf_lsa *lsa); +static void ospf_router_info_show_info(struct vty *vty, + struct json_object *json, + struct ospf_lsa *lsa); static int ospf_router_info_lsa_originate(void *arg); static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa); static void ospf_router_info_lsa_schedule(struct ospf_ri_area_info *ai, @@ -1552,12 +1554,17 @@ static uint16_t show_vty_sr_msd(struct vty *vty, struct tlv_header *tlvh) return TLV_SIZE(tlvh); } -static void ospf_router_info_show_info(struct vty *vty, struct ospf_lsa *lsa) +static void ospf_router_info_show_info(struct vty *vty, + struct json_object *json, + struct ospf_lsa *lsa) { struct lsa_header *lsah = lsa->data; struct tlv_header *tlvh; uint16_t length = 0, sum = 0; + if (json) + return; + /* Initialize TLV browsing */ length = lsa->size - OSPF_LSA_HEADER_SIZE; diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c index d95e677f6f2b..03fa572859dd 100644 --- a/ospfd/ospf_te.c +++ b/ospfd/ospf_te.c @@ -87,7 +87,8 @@ static int ospf_mpls_te_del_if(struct interface *ifp); static void ospf_mpls_te_ism_change(struct ospf_interface *oi, int old_status); static void ospf_mpls_te_nsm_change(struct ospf_neighbor *nbr, int old_status); static void ospf_mpls_te_config_write_router(struct vty *vty); -static void ospf_mpls_te_show_info(struct vty *vty, struct ospf_lsa *lsa); +static void ospf_mpls_te_show_info(struct vty *vty, struct json_object *json, + struct ospf_lsa *lsa); static int ospf_mpls_te_lsa_originate_area(void *arg); static int ospf_mpls_te_lsa_inter_as_as(void *arg); static int ospf_mpls_te_lsa_inter_as_area(void *arg); @@ -3783,7 +3784,8 @@ static uint16_t ospf_mpls_te_show_link_subtlv(struct vty *vty, return sum; } -static void ospf_mpls_te_show_info(struct vty *vty, struct ospf_lsa *lsa) +static void ospf_mpls_te_show_info(struct vty *vty, struct json_object *json, + struct ospf_lsa *lsa) { struct lsa_header *lsah = lsa->data; struct tlv_header *tlvh, *next; @@ -3791,6 +3793,9 @@ static void ospf_mpls_te_show_info(struct vty *vty, struct ospf_lsa *lsa) uint16_t (*subfunc)(struct vty * vty, struct tlv_header * tlvh, uint16_t subtotal, uint16_t total) = NULL; + if (json) + return; + sum = 0; total = lsa->size - OSPF_LSA_HEADER_SIZE; From bb2ca6927f98b53e9d860697ed82477eddbebe5c Mon Sep 17 00:00:00 2001 From: Mark Stapp Date: Tue, 5 Oct 2021 11:49:20 -0400 Subject: [PATCH 117/188] bgpd: BGP-LU use implicit-null in some cases In some cases where bgp is at the mpls edge, where it has a BGP-LU peer downstream but an IP peer upstream, it can advertise the IMPLICIT_NULL label instead of a per-prefix label. Signed-off-by: Mark Stapp --- bgpd/bgp_label.c | 4 ++++ bgpd/bgp_route.c | 28 +++++++++++++++++++++++----- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/bgpd/bgp_label.c b/bgpd/bgp_label.c index 3c8f2f36684a..fa2a445165e4 100644 --- a/bgpd/bgp_label.c +++ b/bgpd/bgp_label.c @@ -244,6 +244,10 @@ void bgp_reg_dereg_for_label(struct bgp_dest *dest, struct bgp_path_info *pi, p = bgp_dest_get_prefix(dest); + if (BGP_DEBUG(labelpool, LABELPOOL)) + zlog_debug("%s: %pFX: %s ", __func__, p, + (reg ? "reg" : "dereg")); + if (reg) { assert(pi); /* diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index fc9717845006..f278cef77cb5 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -2711,6 +2711,28 @@ static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi, bgp_evpn_withdraw_type5_route(bgp, p, afi, safi); } +/* + * Utility to determine whether a particular path_info should use + * the IMPLICIT_NULL label. This is pretty specialized: it's only called + * in a path where we basically _know_ this is a BGP-LU route. + */ +static bool bgp_lu_need_imp_null(const struct bgp_path_info *new_select) +{ + /* Certain types get imp null; so do paths where the nexthop is + * not labeled. + */ + if (new_select->sub_type == BGP_ROUTE_STATIC + || new_select->sub_type == BGP_ROUTE_AGGREGATE + || new_select->sub_type == BGP_ROUTE_REDISTRIBUTE) + return true; + else if (new_select->extra == NULL || + !bgp_is_valid_label(&new_select->extra->label[0])) + /* TODO -- should be configurable? */ + return true; + else + return false; +} + /* * old_select = The old best path * new_select = the new best path @@ -2802,11 +2824,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, * implicit-null for local routes, aggregate * and redistributed routes */ - if (new_select->sub_type == BGP_ROUTE_STATIC - || new_select->sub_type - == BGP_ROUTE_AGGREGATE - || new_select->sub_type - == BGP_ROUTE_REDISTRIBUTE) { + if (bgp_lu_need_imp_null(new_select)) { if (CHECK_FLAG( dest->flags, BGP_NODE_REGISTERED_FOR_LABEL) From 8734a29c8f06ebaa555fd9f30f36901b1fba2035 Mon Sep 17 00:00:00 2001 From: Mark Stapp Date: Thu, 30 Sep 2021 15:56:34 -0400 Subject: [PATCH 118/188] tests: add bgp_lu_topo2 test suite Add a second BGP labelled-unicast (BGP-LU) test suite, with an additional router and some additional tests. Signed-off-by: Mark Stapp --- tests/topotests/bgp_lu_topo2/R1/bgpd.conf | 29 +++ .../bgp_lu_topo2/R1/labelpool.summ.json | 8 + tests/topotests/bgp_lu_topo2/R1/zebra.conf | 13 ++ tests/topotests/bgp_lu_topo2/R2/bgpd.conf | 27 +++ .../bgp_lu_topo2/R2/labelpool.summ.json | 8 + tests/topotests/bgp_lu_topo2/R2/zebra.conf | 14 ++ tests/topotests/bgp_lu_topo2/R3/bgpd.conf | 70 ++++++ tests/topotests/bgp_lu_topo2/R3/staticd.conf | 5 + tests/topotests/bgp_lu_topo2/R3/zebra.conf | 11 + tests/topotests/bgp_lu_topo2/R4/bgpd.conf | 23 ++ tests/topotests/bgp_lu_topo2/R4/zebra.conf | 9 + tests/topotests/bgp_lu_topo2/test_bgp_lu2.py | 221 ++++++++++++++++++ 12 files changed, 438 insertions(+) create mode 100644 tests/topotests/bgp_lu_topo2/R1/bgpd.conf create mode 100644 tests/topotests/bgp_lu_topo2/R1/labelpool.summ.json create mode 100644 tests/topotests/bgp_lu_topo2/R1/zebra.conf create mode 100644 tests/topotests/bgp_lu_topo2/R2/bgpd.conf create mode 100644 tests/topotests/bgp_lu_topo2/R2/labelpool.summ.json create mode 100644 tests/topotests/bgp_lu_topo2/R2/zebra.conf create mode 100644 tests/topotests/bgp_lu_topo2/R3/bgpd.conf create mode 100644 tests/topotests/bgp_lu_topo2/R3/staticd.conf create mode 100644 tests/topotests/bgp_lu_topo2/R3/zebra.conf create mode 100644 tests/topotests/bgp_lu_topo2/R4/bgpd.conf create mode 100644 tests/topotests/bgp_lu_topo2/R4/zebra.conf create mode 100644 tests/topotests/bgp_lu_topo2/test_bgp_lu2.py diff --git a/tests/topotests/bgp_lu_topo2/R1/bgpd.conf b/tests/topotests/bgp_lu_topo2/R1/bgpd.conf new file mode 100644 index 000000000000..13383e20b609 --- /dev/null +++ b/tests/topotests/bgp_lu_topo2/R1/bgpd.conf @@ -0,0 +1,29 @@ +! +no log unique-id +! +debug bgp labelpool +debug bgp zebra +! +router bgp 1 + bgp router-id 10.0.0.1 + timers bgp 3 9 + no bgp ebgp-requires-policy + no bgp network import-check + neighbor 10.0.0.2 remote-as 2 +! neighbor 10.0.0.2 solo + neighbor 10.0.0.2 timers connect 10 + neighbor 10.0.4.4 remote-as 4 +! neighbor 10.0.4.4 solo + neighbor 10.0.4.4 timers connect 10 +! + address-family ipv4 unicast + no neighbor 10.0.0.2 activate + no neighbor 10.0.4.4 activate + redistribute connected + exit-address-family + ! + address-family ipv4 labeled-unicast + neighbor 10.0.0.2 activate + neighbor 10.0.4.4 activate + exit-address-family +! diff --git a/tests/topotests/bgp_lu_topo2/R1/labelpool.summ.json b/tests/topotests/bgp_lu_topo2/R1/labelpool.summ.json new file mode 100644 index 000000000000..77705e8d35cc --- /dev/null +++ b/tests/topotests/bgp_lu_topo2/R1/labelpool.summ.json @@ -0,0 +1,8 @@ +{ + "Ledger":51, + "InUse":51, + "Requests":0, + "LabelChunks":2, + "Pending":0, + "Reconnects":0 +} diff --git a/tests/topotests/bgp_lu_topo2/R1/zebra.conf b/tests/topotests/bgp_lu_topo2/R1/zebra.conf new file mode 100644 index 000000000000..c78248186047 --- /dev/null +++ b/tests/topotests/bgp_lu_topo2/R1/zebra.conf @@ -0,0 +1,13 @@ +! +no log unique-id +! +debug zebra events +debug zebra rib det +debug zebra dplane +debug zebra mpls +! +interface R1-eth0 + ip address 10.0.0.1/24 +! +interface R1-eth1 + ip address 10.0.4.1/24 diff --git a/tests/topotests/bgp_lu_topo2/R2/bgpd.conf b/tests/topotests/bgp_lu_topo2/R2/bgpd.conf new file mode 100644 index 000000000000..bab3b8dd7843 --- /dev/null +++ b/tests/topotests/bgp_lu_topo2/R2/bgpd.conf @@ -0,0 +1,27 @@ +! +no log unique-id +! +debug bgp labelpool +debug bgp zebra +! +router bgp 2 + bgp router-id 10.0.0.2 + no bgp ebgp-requires-policy + no bgp network import-check + timers bgp 3 9 + neighbor 10.0.0.1 remote-as 1 + neighbor 10.0.0.1 timers connect 10 + neighbor 10.0.1.3 remote-as 2 + neighbor 10.0.1.3 update-source 10.0.1.2 + neighbor 10.0.1.3 timers connect 10 +! + address-family ipv4 unicast + network 10.0.0.0/24 + neighbor 10.0.1.3 activate + no neighbor 10.0.0.1 activate + exit-address-family + ! + address-family ipv4 labeled-unicast + neighbor 10.0.0.1 activate + exit-address-family +! diff --git a/tests/topotests/bgp_lu_topo2/R2/labelpool.summ.json b/tests/topotests/bgp_lu_topo2/R2/labelpool.summ.json new file mode 100644 index 000000000000..eb1ae93b6cf3 --- /dev/null +++ b/tests/topotests/bgp_lu_topo2/R2/labelpool.summ.json @@ -0,0 +1,8 @@ +{ + "Ledger":1, + "InUse":1, + "Requests":0, + "LabelChunks":1, + "Pending":0, + "Reconnects":0 +} diff --git a/tests/topotests/bgp_lu_topo2/R2/zebra.conf b/tests/topotests/bgp_lu_topo2/R2/zebra.conf new file mode 100644 index 000000000000..b8a03e4fcbc3 --- /dev/null +++ b/tests/topotests/bgp_lu_topo2/R2/zebra.conf @@ -0,0 +1,14 @@ +! +no log unique-id +! +debug zebra events +debug zebra dplane +debug zebra mpls +debug zebra rib det +! +interface R2-eth0 + ip address 10.0.0.2/24 +! +interface R2-eth1 + ip address 10.0.1.2/24 +! \ No newline at end of file diff --git a/tests/topotests/bgp_lu_topo2/R3/bgpd.conf b/tests/topotests/bgp_lu_topo2/R3/bgpd.conf new file mode 100644 index 000000000000..2dfeaa3274b5 --- /dev/null +++ b/tests/topotests/bgp_lu_topo2/R3/bgpd.conf @@ -0,0 +1,70 @@ +log file /tmp/bgpd.log +no log unique-id +! +! +debug bgp updates +! +router bgp 2 + bgp router-id 10.0.1.3 + no bgp ebgp-requires-policy + no bgp network import-check + timers bgp 3 9 + neighbor 10.0.1.2 remote-as 2 + neighbor 10.0.1.2 timers connect 10 + ! + address-family ipv4 unicast + neighbor 10.0.1.2 activate + network 10.0.1.0/24 + network 11.0.0.1/32 + network 11.0.0.2/32 + network 11.0.0.3/32 + network 11.0.0.4/32 + network 11.0.0.5/32 + network 11.0.0.6/32 + network 11.0.0.7/32 + network 11.0.0.8/32 + network 11.0.0.9/32 + network 11.0.0.10/32 + network 11.0.0.11/32 + network 11.0.0.12/32 + network 11.0.0.13/32 + network 11.0.0.14/32 + network 11.0.0.15/32 + network 11.0.0.16/32 + network 11.0.0.17/32 + network 11.0.0.18/32 + network 11.0.0.19/32 + network 11.0.0.20/32 + network 11.0.0.21/32 + network 11.0.0.22/32 + network 11.0.0.23/32 + network 11.0.0.24/32 + network 11.0.0.25/32 + network 11.0.0.26/32 + network 11.0.0.27/32 + network 11.0.0.28/32 + network 11.0.0.29/32 + network 11.0.0.30/32 + network 11.0.0.31/32 + network 11.0.0.32/32 + network 11.0.0.33/32 + network 11.0.0.34/32 + network 11.0.0.35/32 + network 11.0.0.36/32 + network 11.0.0.37/32 + network 11.0.0.38/32 + network 11.0.0.39/32 + network 11.0.0.40/32 + network 11.0.0.41/32 + network 11.0.0.42/32 + network 11.0.0.43/32 + network 11.0.0.44/32 + network 11.0.0.45/32 + network 11.0.0.46/32 + network 11.0.0.47/32 + network 11.0.0.48/32 + network 11.0.0.49/32 + network 11.0.0.50/32 + exit-address-family + ! +! diff --git a/tests/topotests/bgp_lu_topo2/R3/staticd.conf b/tests/topotests/bgp_lu_topo2/R3/staticd.conf new file mode 100644 index 000000000000..867fc5a837f4 --- /dev/null +++ b/tests/topotests/bgp_lu_topo2/R3/staticd.conf @@ -0,0 +1,5 @@ +log file /tmp/staticd.log +no log unique-id +! +! +ip route 10.0.4.0/24 10.0.1.2 diff --git a/tests/topotests/bgp_lu_topo2/R3/zebra.conf b/tests/topotests/bgp_lu_topo2/R3/zebra.conf new file mode 100644 index 000000000000..e4234de48c86 --- /dev/null +++ b/tests/topotests/bgp_lu_topo2/R3/zebra.conf @@ -0,0 +1,11 @@ +log file /tmp/zebra.log +no log unique-id +! +! +debug zebra events +debug zebra packet detail +debug zebra mpls +! +interface R3-eth0 + ip address 10.0.1.3/24 +! diff --git a/tests/topotests/bgp_lu_topo2/R4/bgpd.conf b/tests/topotests/bgp_lu_topo2/R4/bgpd.conf new file mode 100644 index 000000000000..3cef827b8608 --- /dev/null +++ b/tests/topotests/bgp_lu_topo2/R4/bgpd.conf @@ -0,0 +1,23 @@ +! +no log unique-id +! +debug bgp labelpool +debug bgp zebra +! +router bgp 4 + bgp router-id 10.0.4.4 + timers bgp 3 9 + no bgp ebgp-requires-policy + no bgp network import-check + neighbor 10.0.4.1 remote-as 1 + neighbor 10.0.4.1 solo + neighbor 10.0.4.1 timers connect 10 +! + address-family ipv4 unicast + no neighbor 10.0.4.1 activate + exit-address-family + ! + address-family ipv4 labeled-unicast + neighbor 10.0.4.1 activate + exit-address-family +! diff --git a/tests/topotests/bgp_lu_topo2/R4/zebra.conf b/tests/topotests/bgp_lu_topo2/R4/zebra.conf new file mode 100644 index 000000000000..ba1b2bba6e37 --- /dev/null +++ b/tests/topotests/bgp_lu_topo2/R4/zebra.conf @@ -0,0 +1,9 @@ +no log unique-id +! +debug zebra events +debug zebra dplane +debug zebra mpls +debug zebra rib det +! +interface R4-eth0 + ip address 10.0.4.4/24 diff --git a/tests/topotests/bgp_lu_topo2/test_bgp_lu2.py b/tests/topotests/bgp_lu_topo2/test_bgp_lu2.py new file mode 100644 index 000000000000..fc9d2c433a1a --- /dev/null +++ b/tests/topotests/bgp_lu_topo2/test_bgp_lu2.py @@ -0,0 +1,221 @@ +#!/usr/bin/env python +# +# test_bgp_lu2.py +# +# Part of FRR/NetDEF Topology Tests +# +# Copyright (c) 2020 by Volta Networks +# Copyright (c) 2021 by Nvidia, Inc. +# +# 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. +# + +""" +test_bgp_lu2.py: Test BGP LU label allocation +""" + +import os +import sys +import json +from functools import partial +import pytest + +# 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. + +pytestmark = [pytest.mark.bgpd] + +# +# Basic scenario for BGP-LU. Nodes are directly connected. +# Node 3 is advertising routes to 2, which advertises them +# as BGP-LU to 1; this way we get routes with actual labels, as +# opposed to implicit-null routes in the 2-node case. +# +# R2 is an LER, with MPLS towards R1, and IP towards R3. R1 is an LSR, with +# MPLS on both sides. +# +# +# AS4 BGP-LU AS1 BGP-LU AS2 iBGP AS2 +# +-----+ +-----+ +-----+ +-----+ +# | |.4 .1| |.1 .2| |.2 .3| | +# | 4 +-------------+ 1 +----------------+ 2 +-----------------+ 3 | +# | | 10.0.4.0/24 | | 10.0.0.0/24 | | 10.0.1.0/24 | | +# +-----+ +-----+ +-----+ +-----+ +# +# + + +def build_topo(tgen): + "Build function" + + # This function's only purpose is to define allocation and relationship + # between routers, switches and hosts. + # + # + # Create routers + tgen.add_router("R1") + tgen.add_router("R2") + tgen.add_router("R3") + tgen.add_router("R4") + + # R1-R2 + switch = tgen.add_switch("s1") + switch.add_link(tgen.gears["R1"]) + switch.add_link(tgen.gears["R2"]) + + # R2-R3 + switch = tgen.add_switch("s2") + switch.add_link(tgen.gears["R2"]) + switch.add_link(tgen.gears["R3"]) + + # R1-R4 + switch = tgen.add_switch("s3") + switch.add_link(tgen.gears["R1"]) + switch.add_link(tgen.gears["R4"]) + + +def setup_module(mod): + "Sets up the pytest environment" + # This function initiates the topology build with Topogen... + tgen = Topogen(build_topo, mod.__name__) + + # Skip if no mpls support + if not tgen.hasmpls: + logger.info("MPLS is not available, skipping test") + pytest.skip("MPLS is not available, skipping") + return + + # ... and here it calls Mininet initialization functions. + tgen.start_topology() + + # This is a sample of configuration loading. + router_list = tgen.routers() + + # Enable mpls input for routers, so we can ping + sval = "net.mpls.conf.{}.input" + topotest.sysctl_assure(router_list["R2"], sval.format("R2-eth0"), 1) + topotest.sysctl_assure(router_list["R1"], sval.format("R1-eth0"), 1) + topotest.sysctl_assure(router_list["R1"], sval.format("R1-eth1"), 1) + topotest.sysctl_assure(router_list["R4"], sval.format("R4-eth0"), 1) + + # For all registered routers, load the zebra configuration file + for rname, router in router_list.items(): + router.load_config( + TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) + ) + router.load_config( + TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname)) + ) + + # Have static config for R3 too + if router == router_list["R3"]: + router.load_config( + TopoRouter.RD_STATIC, os.path.join(CWD, "{}/staticd.conf".format(rname)) + ) + + # After loading the configurations, this function loads configured daemons. + tgen.start_router() + + +def teardown_module(mod): + "Teardown the pytest environment" + tgen = get_topogen() + + # This function tears down the whole topology. + tgen.stop_topology() + + +def check_labelpool(router): + json_file = "{}/{}/labelpool.summ.json".format(CWD, router.name) + expected = json.loads(open(json_file).read()) + + test_func = partial( + topotest.router_json_cmp, router, "show bgp labelpool summary json", expected + ) + _, result = topotest.run_and_expect(test_func, None, count=20, wait=1) + assertmsg = '"{}" JSON output mismatches - Did not converge'.format(router.name) + assert result is None, assertmsg + + +def test_converge_bgplu(): + "Wait for protocol convergence" + + tgen = get_topogen() + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # TODO -- enable for debugging + # tgen.mininet_cli() + + r1 = tgen.gears["R1"] + r2 = tgen.gears["R2"] + + check_labelpool(r1) + check_labelpool(r2) + + +def test_ping(): + "Simple ping tests" + + tgen = get_topogen() + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # + logger.info("Ping from R2 to R3") + router = tgen.gears["R2"] + output = router.run("ping -c 4 -w 4 {}".format("10.0.1.3")) + assert " 0% packet loss" in output, "Ping R2->R3 FAILED" + logger.info("Ping from R2 to R3 ... success") + + # + logger.info("Ping from R4 to R2") + router = tgen.gears["R4"] + output = router.run("ping -c 4 -w 4 {}".format("10.0.0.2")) + assert " 0% packet loss" in output, "Ping R4->R2 FAILED" + logger.info("Ping from R4 to R2 ... success") + + # + logger.info("Ping from R4 to R3") + router = tgen.gears["R4"] + output = router.run("ping -c 4 -w 4 {}".format("10.0.1.3")) + assert " 0% packet loss" in output, "Ping R4->R3 FAILED" + logger.info("Ping from R4 to R3 ... success") + + +def test_memory_leak(): + "Run the memory leak test and report results." + tgen = get_topogen() + if not tgen.is_memleak_enabled(): + pytest.skip("Memory leak test/report is disabled") + + tgen.report_memory_leaks() + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) From 74d79ead0171f15c7bc935891aaaf288f0ad37ed Mon Sep 17 00:00:00 2001 From: Mark Stapp Date: Fri, 8 Oct 2021 08:43:37 -0400 Subject: [PATCH 119/188] tests: adjust bgp_lu_topo1 for updated BGP LU BGP LU will use implicit-null in more situations now; adjust the original LU topotest to align with that. Node R2 uses imp-null now, while R1 continues to allocate labels. Signed-off-by: Mark Stapp --- tests/topotests/bgp_lu_topo1/R2/labelpool.summ.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/topotests/bgp_lu_topo1/R2/labelpool.summ.json b/tests/topotests/bgp_lu_topo1/R2/labelpool.summ.json index 29e6c2cbf702..9c817e80759a 100644 --- a/tests/topotests/bgp_lu_topo1/R2/labelpool.summ.json +++ b/tests/topotests/bgp_lu_topo1/R2/labelpool.summ.json @@ -1,8 +1,8 @@ { - "Ledger":506, - "InUse":506, + "Ledger":0, + "InUse":0, "Requests":0, - "LabelChunks":11, + "LabelChunks":0, "Pending":0, "Reconnects":0 } From 7e8699914069fb7fa0bb5c74a28ea9c7687670f1 Mon Sep 17 00:00:00 2001 From: Igor Ryzhov Date: Fri, 1 Oct 2021 18:35:11 +0300 Subject: [PATCH 120/188] *: cleanup number-named access-lists in CLI There's no more difference between number-named and word-named access-lists. This commit removes separate arguments for number-named ACLs from CLI. Signed-off-by: Igor Ryzhov --- bgpd/bgp_routemap.c | 12 ++++-------- bgpd/bgp_vty.c | 16 ++++------------ eigrpd/eigrp_routemap.c | 16 ++++------------ ldpd/ldp_vty_cmds.c | 24 +++++------------------- lib/filter.c | 10 +++------- lib/filter_cli.c | 13 +++++-------- lib/routemap_cli.c | 16 ++++------------ tests/lib/cli/test_commands.refout | 24 ++++++++++++------------ 8 files changed, 41 insertions(+), 90 deletions(-) diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 835576a0792e..2f37367a8fba 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -4576,13 +4576,11 @@ DEFUN_YANG (no_match_probability, DEFPY_YANG (match_ip_route_source, match_ip_route_source_cmd, - "match ip route-source <(1-199)|(1300-2699)|WORD>", + "match ip route-source WORD", MATCH_STR IP_STR "Match advertising source address of route\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" - "IP standard access-list name\n") + "IP Access-list name\n") { const char *xpath = "./match-condition[condition='frr-bgp-route-map:ip-route-source']"; @@ -4602,14 +4600,12 @@ DEFPY_YANG (match_ip_route_source, DEFUN_YANG (no_match_ip_route_source, no_match_ip_route_source_cmd, - "no match ip route-source [<(1-199)|(1300-2699)|WORD>]", + "no match ip route-source [WORD]", NO_STR MATCH_STR IP_STR "Match advertising source address of route\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" - "IP standard access-list name\n") + "IP Access-list name\n") { const char *xpath = "./match-condition[condition='frr-bgp-route-map:ip-route-source']"; diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 14f4fb731050..26da38bd7a66 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -7018,12 +7018,10 @@ DEFUN (no_neighbor_interface, DEFUN (neighbor_distribute_list, neighbor_distribute_list_cmd, - "neighbor distribute-list <(1-199)|(1300-2699)|WORD> ", + "neighbor distribute-list WORD ", NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "Filter updates to/from this neighbor\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" "IP Access-list name\n" "Filter incoming updates\n" "Filter outgoing updates\n") @@ -7051,24 +7049,20 @@ DEFUN (neighbor_distribute_list, ALIAS_HIDDEN( neighbor_distribute_list, neighbor_distribute_list_hidden_cmd, - "neighbor distribute-list <(1-199)|(1300-2699)|WORD> ", + "neighbor distribute-list WORD ", NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "Filter updates to/from this neighbor\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" "IP Access-list name\n" "Filter incoming updates\n" "Filter outgoing updates\n") DEFUN (no_neighbor_distribute_list, no_neighbor_distribute_list_cmd, - "no neighbor distribute-list <(1-199)|(1300-2699)|WORD> ", + "no neighbor distribute-list WORD ", NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "Filter updates to/from this neighbor\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" "IP Access-list name\n" "Filter incoming updates\n" "Filter outgoing updates\n") @@ -7094,11 +7088,9 @@ DEFUN (no_neighbor_distribute_list, ALIAS_HIDDEN( no_neighbor_distribute_list, no_neighbor_distribute_list_hidden_cmd, - "no neighbor distribute-list <(1-199)|(1300-2699)|WORD> ", + "no neighbor distribute-list WORD ", NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "Filter updates to/from this neighbor\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" "IP Access-list name\n" "Filter incoming updates\n" "Filter outgoing updates\n") diff --git a/eigrpd/eigrp_routemap.c b/eigrpd/eigrp_routemap.c index 90913a5b2877..67fab89271a8 100644 --- a/eigrpd/eigrp_routemap.c +++ b/eigrpd/eigrp_routemap.c @@ -858,12 +858,10 @@ ALIAS(no_match_interface, no_match_interface_val_cmd, "no match interface WORD", DEFUN (match_ip_next_hop, match_ip_next_hop_cmd, - "match ip next-hop ((1-199)|(1300-2699)|WORD)", + "match ip next-hop WORD", MATCH_STR IP_STR "Match next-hop address of route\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" "IP Access-list name\n") { return eigrp_route_match_add(vty, vty->index, "ip next-hop", argv[0]); @@ -886,10 +884,8 @@ DEFUN (no_match_ip_next_hop, } ALIAS(no_match_ip_next_hop, no_match_ip_next_hop_val_cmd, - "no match ip next-hop ((1-199)|(1300-2699)|WORD)", NO_STR MATCH_STR IP_STR + "no match ip next-hop WORD", NO_STR MATCH_STR IP_STR "Match next-hop address of route\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" "IP Access-list name\n") DEFUN (match_ip_next_hop_prefix_list, @@ -931,12 +927,10 @@ ALIAS(no_match_ip_next_hop_prefix_list, DEFUN (match_ip_address, match_ip_address_cmd, - "match ip address ((1-199)|(1300-2699)|WORD)", + "match ip address WORD", MATCH_STR IP_STR "Match address of route\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" "IP Access-list name\n") { return eigrp_route_match_add(vty, vty->index, "ip address", argv[0]); @@ -958,10 +952,8 @@ DEFUN (no_match_ip_address, } ALIAS(no_match_ip_address, no_match_ip_address_val_cmd, - "no match ip address ((1-199)|(1300-2699)|WORD)", NO_STR MATCH_STR IP_STR + "no match ip address WORD", NO_STR MATCH_STR IP_STR "Match address of route\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" "IP Access-list name\n") DEFUN (match_ip_address_prefix_list, diff --git a/ldpd/ldp_vty_cmds.c b/ldpd/ldp_vty_cmds.c index b65ebf6f559e..9d3d1a606ea2 100644 --- a/ldpd/ldp_vty_cmds.c +++ b/ldpd/ldp_vty_cmds.c @@ -253,14 +253,12 @@ DEFPY (ldp_allow_broken_lsps, DEFPY (ldp_discovery_targeted_hello_accept, ldp_discovery_targeted_hello_accept_cmd, - "[no] discovery targeted-hello accept [from <(1-199)|(1300-2699)|WORD>$from_acl]", + "[no] discovery targeted-hello accept [from WORD$from_acl]", NO_STR "Configure discovery parameters\n" "LDP Targeted Hellos\n" "Accept and respond to targeted hellos\n" "Access list to specify acceptable targeted hello source\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" "IP access-list name\n") { return (ldp_vty_targeted_hello_accept(vty, no, from_acl)); @@ -290,18 +288,14 @@ DEFPY (ldp_discovery_transport_address_ipv6, DEFPY (ldp_label_local_advertise, ldp_label_local_advertise_cmd, - "[no] label local advertise [{to <(1-199)|(1300-2699)|WORD>$to_acl|for <(1-199)|(1300-2699)|WORD>$for_acl}]", + "[no] label local advertise [{to WORD$to_acl|for WORD$for_acl}]", NO_STR "Configure label control and policies\n" "Configure local label control and policies\n" "Configure outbound label advertisement control\n" "IP Access-list specifying controls on LDP Peers\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" "IP access-list name\n" "IP access-list for destination prefixes\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" "IP access-list name\n") { return (ldp_vty_label_advertise(vty, no, to_acl, for_acl)); @@ -309,15 +303,13 @@ DEFPY (ldp_label_local_advertise, DEFPY (ldp_label_local_advertise_explicit_null, ldp_label_local_advertise_explicit_null_cmd, - "[no] label local advertise explicit-null [for <(1-199)|(1300-2699)|WORD>$for_acl]", + "[no] label local advertise explicit-null [for WORD$for_acl]", NO_STR "Configure label control and policies\n" "Configure local label control and policies\n" "Configure outbound label advertisement control\n" "Configure explicit-null advertisement\n" "IP access-list for destination prefixes\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" "IP access-list name\n") { return (ldp_vty_label_expnull(vty, no, for_acl)); @@ -325,15 +317,13 @@ DEFPY (ldp_label_local_advertise_explicit_null, DEFPY (ldp_label_local_allocate, ldp_label_local_allocate_cmd, - "[no] label local allocate $for_acl>", + "[no] label local allocate ", NO_STR "Configure label control and policies\n" "Configure local label control and policies\n" "Configure label allocation control\n" "allocate local label for host routes only\n" "IP access-list\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" "IP access-list name\n") { return (ldp_vty_label_allocate(vty, no, host_routes, for_acl)); @@ -341,18 +331,14 @@ DEFPY (ldp_label_local_allocate, DEFPY (ldp_label_remote_accept, ldp_label_remote_accept_cmd, - "[no] label remote accept {from <(1-199)|(1300-2699)|WORD>$from_acl|for <(1-199)|(1300-2699)|WORD>$for_acl}", + "[no] label remote accept {from WORD$from_acl|for WORD$for_acl}", NO_STR "Configure label control and policies\n" "Configure remote/peer label control and policies\n" "Configure inbound label acceptance control\n" "Neighbor from whom to accept label advertisement\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" "IP access-list name\n" "IP access-list for destination prefixes\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" "IP access-list name\n") { return (ldp_vty_label_accept(vty, no, from_acl, for_acl)); diff --git a/lib/filter.c b/lib/filter.c index 744ea9c480a2..90591def8506 100644 --- a/lib/filter.c +++ b/lib/filter.c @@ -635,15 +635,11 @@ DEFUN (show_ip_access_list, DEFUN (show_ip_access_list_name, show_ip_access_list_name_cmd, - "show ip access-list <(1-99)|(100-199)|(1300-1999)|(2000-2699)|WORD> [json]", + "show ip access-list WORD [json]", SHOW_STR IP_STR "List IP access lists\n" - "IP standard access list\n" - "IP extended access list\n" - "IP standard access list (expanded range)\n" - "IP extended access list (expanded range)\n" - "IP zebra access-list\n" + "IP access-list name\n" JSON_STR) { bool uj = use_json(argc, argv); @@ -669,7 +665,7 @@ DEFUN (show_ipv6_access_list_name, SHOW_STR IPV6_STR "List IPv6 access lists\n" - "IPv6 zebra access-list\n" + "IPv6 access-list name\n" JSON_STR) { bool uj = use_json(argc, argv); diff --git a/lib/filter_cli.c b/lib/filter_cli.c index 45c7544a3b40..e424fcf87868 100644 --- a/lib/filter_cli.c +++ b/lib/filter_cli.c @@ -36,10 +36,7 @@ #endif /* VTYSH_EXTRACT_PL */ #define ACCESS_LIST_STR "Access list entry\n" -#define ACCESS_LIST_LEG_STR "IP standard access list\n" -#define ACCESS_LIST_ELEG_STR "IP extended access list\n" -#define ACCESS_LIST_ELEG_EXT_STR "IP extended access list (expanded range)\n" -#define ACCESS_LIST_ZEBRA_STR "Access list entry\n" +#define ACCESS_LIST_ZEBRA_STR "Access list name\n" #define ACCESS_LIST_SEQ_STR \ "Sequence number of an entry\n" \ "Sequence number\n" @@ -137,7 +134,7 @@ DEFPY_YANG( access_list_std, access_list_std_cmd, "access-list WORD$name [seq (1-4294967295)$seq] $action <[host] A.B.C.D$host|A.B.C.D$host A.B.C.D$mask>", ACCESS_LIST_STR - ACCESS_LIST_LEG_STR + ACCESS_LIST_ZEBRA_STR ACCESS_LIST_SEQ_STR ACCESS_LIST_ACTION_STR "A single host address\n" @@ -214,7 +211,7 @@ DEFPY_YANG( "no access-list WORD$name [seq (1-4294967295)$seq] $action <[host] A.B.C.D$host|A.B.C.D$host A.B.C.D$mask>", NO_STR ACCESS_LIST_STR - ACCESS_LIST_LEG_STR + ACCESS_LIST_ZEBRA_STR ACCESS_LIST_SEQ_STR ACCESS_LIST_ACTION_STR "A single host address\n" @@ -258,7 +255,7 @@ DEFPY_YANG( access_list_ext, access_list_ext_cmd, "access-list WORD$name [seq (1-4294967295)$seq] $action ip ", ACCESS_LIST_STR - ACCESS_LIST_ELEG_STR + ACCESS_LIST_ZEBRA_STR ACCESS_LIST_SEQ_STR ACCESS_LIST_ACTION_STR "IPv4 address\n" @@ -377,7 +374,7 @@ DEFPY_YANG( "no access-list WORD$name [seq (1-4294967295)$seq] $action ip ", NO_STR ACCESS_LIST_STR - ACCESS_LIST_ELEG_STR + ACCESS_LIST_ZEBRA_STR ACCESS_LIST_SEQ_STR ACCESS_LIST_ACTION_STR "Any Internet Protocol\n" diff --git a/lib/routemap_cli.c b/lib/routemap_cli.c index cadad15fa7fd..e2db511fc08f 100644 --- a/lib/routemap_cli.c +++ b/lib/routemap_cli.c @@ -165,12 +165,10 @@ DEFPY_YANG( DEFPY_YANG( match_ip_address, match_ip_address_cmd, - "match ip address <(1-199)|(1300-2699)|WORD>$name", + "match ip address WORD$name", MATCH_STR IP_STR "Match address of route\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" "IP Access-list name\n") { const char *xpath = @@ -187,13 +185,11 @@ DEFPY_YANG( DEFPY_YANG( no_match_ip_address, no_match_ip_address_cmd, - "no match ip address [<(1-199)|(1300-2699)|WORD>]", + "no match ip address [WORD]", NO_STR MATCH_STR IP_STR "Match address of route\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" "IP Access-list name\n") { const char *xpath = @@ -246,12 +242,10 @@ DEFPY_YANG( DEFPY_YANG( match_ip_next_hop, match_ip_next_hop_cmd, - "match ip next-hop <(1-199)|(1300-2699)|WORD>$name", + "match ip next-hop WORD$name", MATCH_STR IP_STR "Match next-hop address of route\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" "IP Access-list name\n") { const char *xpath = @@ -268,13 +262,11 @@ DEFPY_YANG( DEFPY_YANG( no_match_ip_next_hop, no_match_ip_next_hop_cmd, - "no match ip next-hop [<(1-199)|(1300-2699)|WORD>]", + "no match ip next-hop [WORD]", NO_STR MATCH_STR IP_STR "Match address of route\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" "IP Access-list name\n") { const char *xpath = diff --git a/tests/lib/cli/test_commands.refout b/tests/lib/cli/test_commands.refout index 9d4a6ef03e49..2ec3e5504b0e 100644 --- a/tests/lib/cli/test_commands.refout +++ b/tests/lib/cli/test_commands.refout @@ -191,38 +191,38 @@ execute strict 'no ipv6 nd mtu 1'@11: rv==0, 'no ipv6 nd mtu <1-65535>': '1' complete 'no ipv6 nd mtu 1'@11: rv==2 describe 'no ipv6 nd mtu 1'@11: rv==0 '<1-65535>' 'MTU in bytes' -execute relaxed 'no neighbor 1.2.3.4 distribute-list 1 in'@17: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list (<1-199>|<1300-2699>|WORD) (in|out)': '1.2.3.4', '1', 'in' -execute strict 'no neighbor 1.2.3.4 distribute-list 1 in'@17: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list (<1-199>|<1300-2699>|WORD) (in|out)': '1.2.3.4', '1', 'in' +execute relaxed 'no neighbor 1.2.3.4 distribute-list 1 in'@17: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list WORD (in|out)': '1.2.3.4', '1', 'in' +execute strict 'no neighbor 1.2.3.4 distribute-list 1 in'@17: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list WORD (in|out)': '1.2.3.4', '1', 'in' complete 'no neighbor 1.2.3.4 distribute-list 1 in'@17: rv==7 'in' describe 'no neighbor 1.2.3.4 distribute-list 1 in'@17: rv==0 'in' 'Filter incoming updates' -execute relaxed 'no neighbor 1.2.3.4 distribute-list 1 in'@18: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list (<1-199>|<1300-2699>|WORD) (in|out)': '1.2.3.4', '1', 'in' -execute strict 'no neighbor 1.2.3.4 distribute-list 1 in'@18: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list (<1-199>|<1300-2699>|WORD) (in|out)': '1.2.3.4', '1', 'in' +execute relaxed 'no neighbor 1.2.3.4 distribute-list 1 in'@18: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list WORD (in|out)': '1.2.3.4', '1', 'in' +execute strict 'no neighbor 1.2.3.4 distribute-list 1 in'@18: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list WORD (in|out)': '1.2.3.4', '1', 'in' complete 'no neighbor 1.2.3.4 distribute-list 1 in'@18: rv==7 'in' describe 'no neighbor 1.2.3.4 distribute-list 1 in'@18: rv==0 'in' 'Filter incoming updates' -execute relaxed 'no neighbor 1.2.3.4 distribute-list 1 in'@19: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list (<1-199>|<1300-2699>|WORD) (in|out)': '1.2.3.4', '1', 'in' -execute strict 'no neighbor 1.2.3.4 distribute-list 1 in'@19: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list (<1-199>|<1300-2699>|WORD) (in|out)': '1.2.3.4', '1', 'in' +execute relaxed 'no neighbor 1.2.3.4 distribute-list 1 in'@19: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list WORD (in|out)': '1.2.3.4', '1', 'in' +execute strict 'no neighbor 1.2.3.4 distribute-list 1 in'@19: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list WORD (in|out)': '1.2.3.4', '1', 'in' complete 'no neighbor 1.2.3.4 distribute-list 1 in'@19: rv==7 'in' describe 'no neighbor 1.2.3.4 distribute-list 1 in'@19: rv==0 'in' 'Filter incoming updates' -execute relaxed 'no neighbor 1.2.3.4 distribute-list 1 in'@20: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list (<1-199>|<1300-2699>|WORD) (in|out)': '1.2.3.4', '1', 'in' -execute strict 'no neighbor 1.2.3.4 distribute-list 1 in'@20: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list (<1-199>|<1300-2699>|WORD) (in|out)': '1.2.3.4', '1', 'in' +execute relaxed 'no neighbor 1.2.3.4 distribute-list 1 in'@20: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list WORD (in|out)': '1.2.3.4', '1', 'in' +execute strict 'no neighbor 1.2.3.4 distribute-list 1 in'@20: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list WORD (in|out)': '1.2.3.4', '1', 'in' complete 'no neighbor 1.2.3.4 distribute-list 1 in'@20: rv==7 'in' describe 'no neighbor 1.2.3.4 distribute-list 1 in'@20: rv==0 'in' 'Filter incoming updates' -execute relaxed 'no neighbor 1.2.3.4 distribute-list 1 in'@21: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list (<1-199>|<1300-2699>|WORD) (in|out)': '1.2.3.4', '1', 'in' -execute strict 'no neighbor 1.2.3.4 distribute-list 1 in'@21: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list (<1-199>|<1300-2699>|WORD) (in|out)': '1.2.3.4', '1', 'in' +execute relaxed 'no neighbor 1.2.3.4 distribute-list 1 in'@21: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list WORD (in|out)': '1.2.3.4', '1', 'in' +execute strict 'no neighbor 1.2.3.4 distribute-list 1 in'@21: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list WORD (in|out)': '1.2.3.4', '1', 'in' complete 'no neighbor 1.2.3.4 distribute-list 1 in'@21: rv==7 'in' describe 'no neighbor 1.2.3.4 distribute-list 1 in'@21: rv==0 'in' 'Filter incoming updates' -execute relaxed 'no neighbor 1.2.3.4 distribute-list 1 in'@22: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list (<1-199>|<1300-2699>|WORD) (in|out)': '1.2.3.4', '1', 'in' -execute strict 'no neighbor 1.2.3.4 distribute-list 1 in'@22: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list (<1-199>|<1300-2699>|WORD) (in|out)': '1.2.3.4', '1', 'in' +execute relaxed 'no neighbor 1.2.3.4 distribute-list 1 in'@22: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list WORD (in|out)': '1.2.3.4', '1', 'in' +execute strict 'no neighbor 1.2.3.4 distribute-list 1 in'@22: rv==0, 'no neighbor (A.B.C.D|X:X::X:X|WORD) distribute-list WORD (in|out)': '1.2.3.4', '1', 'in' complete 'no neighbor 1.2.3.4 distribute-list 1 in'@22: rv==7 'in' describe 'no neighbor 1.2.3.4 distribute-list 1 in'@22: rv==0 From 10396dc55af08178b96df9d200e288aa6139cc08 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Thu, 7 Oct 2021 21:00:06 -0300 Subject: [PATCH 121/188] tests: check for received Grace-LSAs on the OSPF GR topotests Ensure GR helpers have received a Grace-LSA before killing the ospfd/ospf6d process that is undergoing a graceful restart. Signed-off-by: Renato Westphal --- .../ospf6_gr_topo1/test_ospf6_gr_topo1.py | 47 +++++++++++++++++++ .../ospf_gr_topo1/test_ospf_gr_topo1.py | 47 +++++++++++++++++++ 2 files changed, 94 insertions(+) diff --git a/tests/topotests/ospf6_gr_topo1/test_ospf6_gr_topo1.py b/tests/topotests/ospf6_gr_topo1/test_ospf6_gr_topo1.py index d50223191d56..e59333ebd2a9 100755 --- a/tests/topotests/ospf6_gr_topo1/test_ospf6_gr_topo1.py +++ b/tests/topotests/ospf6_gr_topo1/test_ospf6_gr_topo1.py @@ -171,6 +171,41 @@ def router_compare_json_output(rname, command, reference, tries): assert diff is None, assertmsg +def expect_grace_lsa(restarting, helper): + """ + Check if the given helper neighbor has already received a Grace-LSA from + the router performing a graceful restart. + """ + tgen = get_topogen() + + logger.info( + "'{}': checking if a Grace-LSA was received from '{}'".format( + helper, restarting + ) + ) + test_func = partial( + topotest.router_json_cmp, + tgen.gears[helper], + "show ipv6 ospf6 database json", + { + "interfaceScopedLinkStateDb": [ + { + "lsa": [ + { + "type": "GR", + "advRouter": restarting, + } + ] + } + ] + }, + ) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) + assertmsg = '"{}" didn\'t receive a Grace-LSA from "{}"'.format(helper, restarting) + + assert result is None, assertmsg + + def check_routers(initial_convergence=False, exiting=None, restarting=None): for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6", "rt7"]: # Check the RIB first, which should be preserved across restarts in @@ -269,6 +304,7 @@ def test_gr_rt1(): pytest.skip(tgen.errors) tgen.net["rt1"].cmd('vtysh -c "graceful-restart prepare ipv6 ospf"') + expect_grace_lsa(restarting="1.1.1.1", helper="rt2") ensure_gr_is_in_zebra("rt1") kill_router_daemons(tgen, "rt1", ["ospf6d"], save_config=False) check_routers(exiting="rt1") @@ -288,6 +324,8 @@ def test_gr_rt2(): pytest.skip(tgen.errors) tgen.net["rt2"].cmd('vtysh -c "graceful-restart prepare ipv6 ospf"') + expect_grace_lsa(restarting="2.2.2.2", helper="rt1") + expect_grace_lsa(restarting="2.2.2.2", helper="rt3") ensure_gr_is_in_zebra("rt2") kill_router_daemons(tgen, "rt2", ["ospf6d"], save_config=False) check_routers(exiting="rt2") @@ -308,6 +346,9 @@ def test_gr_rt3(): pytest.skip(tgen.errors) tgen.net["rt3"].cmd('vtysh -c "graceful-restart prepare ipv6 ospf"') + expect_grace_lsa(restarting="3.3.3.3", helper="rt2") + expect_grace_lsa(restarting="3.3.3.3", helper="rt4") + expect_grace_lsa(restarting="3.3.3.3", helper="rt6") ensure_gr_is_in_zebra("rt3") kill_router_daemons(tgen, "rt3", ["ospf6d"], save_config=False) check_routers(exiting="rt3") @@ -328,6 +369,8 @@ def test_gr_rt4(): pytest.skip(tgen.errors) tgen.net["rt4"].cmd('vtysh -c "graceful-restart prepare ipv6 ospf"') + expect_grace_lsa(restarting="4.4.4.4", helper="rt3") + expect_grace_lsa(restarting="4.4.4.4", helper="rt5") ensure_gr_is_in_zebra("rt4") kill_router_daemons(tgen, "rt4", ["ospf6d"], save_config=False) check_routers(exiting="rt4") @@ -348,6 +391,7 @@ def test_gr_rt5(): pytest.skip(tgen.errors) tgen.net["rt5"].cmd('vtysh -c "graceful-restart prepare ipv6 ospf"') + expect_grace_lsa(restarting="5.5.5.5", helper="rt4") ensure_gr_is_in_zebra("rt5") kill_router_daemons(tgen, "rt5", ["ospf6d"], save_config=False) check_routers(exiting="rt5") @@ -368,6 +412,8 @@ def test_gr_rt6(): pytest.skip(tgen.errors) tgen.net["rt6"].cmd('vtysh -c "graceful-restart prepare ipv6 ospf"') + expect_grace_lsa(restarting="6.6.6.6", helper="rt3") + expect_grace_lsa(restarting="6.6.6.6", helper="rt7") ensure_gr_is_in_zebra("rt6") kill_router_daemons(tgen, "rt6", ["ospf6d"], save_config=False) check_routers(exiting="rt6") @@ -388,6 +434,7 @@ def test_gr_rt7(): pytest.skip(tgen.errors) tgen.net["rt7"].cmd('vtysh -c "graceful-restart prepare ipv6 ospf"') + expect_grace_lsa(restarting="6.6.6.6", helper="rt6") ensure_gr_is_in_zebra("rt7") kill_router_daemons(tgen, "rt7", ["ospf6d"], save_config=False) check_routers(exiting="rt7") diff --git a/tests/topotests/ospf_gr_topo1/test_ospf_gr_topo1.py b/tests/topotests/ospf_gr_topo1/test_ospf_gr_topo1.py index 1432d53ffc82..3e3bf5cb8c2c 100755 --- a/tests/topotests/ospf_gr_topo1/test_ospf_gr_topo1.py +++ b/tests/topotests/ospf_gr_topo1/test_ospf_gr_topo1.py @@ -180,6 +180,41 @@ def router_compare_json_output(rname, command, reference, tries): assert diff is None, assertmsg +def expect_grace_lsa(restarting, area, helper): + """ + Check if the given helper neighbor has already received a Grace-LSA from + the router performing a graceful restart. + """ + tgen = get_topogen() + + logger.info( + "'{}': checking if a Grace-LSA was received from '{}'".format( + helper, restarting + ) + ) + test_func = partial( + topotest.router_json_cmp, + tgen.gears[helper], + "show ip ospf database opaque-link json", + { + "linkLocalOpaqueLsa": { + "areas": { + area: [ + { + "advertisingRouter": restarting, + "opaqueType": "Grace-LSA", + } + ] + } + } + }, + ) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) + assertmsg = '"{}" didn\'t receive a Grace-LSA from "{}"'.format(helper, restarting) + + assert result is None, assertmsg + + def check_routers(initial_convergence=False, exiting=None, restarting=None): for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6", "rt7"]: # Check the RIB first, which should be preserved across restarts in @@ -272,6 +307,7 @@ def test_gr_rt1(): pytest.skip(tgen.errors) tgen.net["rt1"].cmd('vtysh -c "graceful-restart prepare ip ospf"') + expect_grace_lsa(restarting="1.1.1.1", area="0.0.0.1", helper="rt2") ensure_gr_is_in_zebra("rt1") kill_router_daemons(tgen, "rt1", ["ospfd"], save_config=False) check_routers(exiting="rt1") @@ -292,6 +328,8 @@ def test_gr_rt2(): pytest.skip(tgen.errors) tgen.net["rt2"].cmd('vtysh -c "graceful-restart prepare ip ospf"') + expect_grace_lsa(restarting="2.2.2.2", area="0.0.0.1", helper="rt1") + expect_grace_lsa(restarting="2.2.2.2", area="0.0.0.0", helper="rt3") ensure_gr_is_in_zebra("rt2") kill_router_daemons(tgen, "rt2", ["ospfd"], save_config=False) check_routers(exiting="rt2") @@ -312,6 +350,9 @@ def test_gr_rt3(): pytest.skip(tgen.errors) tgen.net["rt3"].cmd('vtysh -c "graceful-restart prepare ip ospf"') + expect_grace_lsa(restarting="3.3.3.3", area="0.0.0.0", helper="rt2") + expect_grace_lsa(restarting="3.3.3.3", area="0.0.0.0", helper="rt4") + expect_grace_lsa(restarting="3.3.3.3", area="0.0.0.0", helper="rt6") ensure_gr_is_in_zebra("rt3") kill_router_daemons(tgen, "rt3", ["ospfd"], save_config=False) check_routers(exiting="rt3") @@ -332,6 +373,8 @@ def test_gr_rt4(): pytest.skip(tgen.errors) tgen.net["rt4"].cmd('vtysh -c "graceful-restart prepare ip ospf"') + expect_grace_lsa(restarting="4.4.4.4", area="0.0.0.0", helper="rt3") + expect_grace_lsa(restarting="4.4.4.4", area="0.0.0.2", helper="rt5") ensure_gr_is_in_zebra("rt4") kill_router_daemons(tgen, "rt4", ["ospfd"], save_config=False) check_routers(exiting="rt4") @@ -352,6 +395,7 @@ def test_gr_rt5(): pytest.skip(tgen.errors) tgen.net["rt5"].cmd('vtysh -c "graceful-restart prepare ip ospf"') + expect_grace_lsa(restarting="5.5.5.5", area="0.0.0.2", helper="rt4") ensure_gr_is_in_zebra("rt5") kill_router_daemons(tgen, "rt5", ["ospfd"], save_config=False) check_routers(exiting="rt5") @@ -372,6 +416,8 @@ def test_gr_rt6(): pytest.skip(tgen.errors) tgen.net["rt6"].cmd('vtysh -c "graceful-restart prepare ip ospf"') + expect_grace_lsa(restarting="6.6.6.6", area="0.0.0.0", helper="rt3") + expect_grace_lsa(restarting="6.6.6.6", area="0.0.0.3", helper="rt7") ensure_gr_is_in_zebra("rt6") kill_router_daemons(tgen, "rt6", ["ospfd"], save_config=False) check_routers(exiting="rt6") @@ -392,6 +438,7 @@ def test_gr_rt7(): pytest.skip(tgen.errors) tgen.net["rt7"].cmd('vtysh -c "graceful-restart prepare ip ospf"') + expect_grace_lsa(restarting="7.7.7.7", area="0.0.0.3", helper="rt6") ensure_gr_is_in_zebra("rt7") kill_router_daemons(tgen, "rt7", ["ospfd"], save_config=False) check_routers(exiting="rt7") From 8975bbbdd6885b8a99be4893291a82150c254452 Mon Sep 17 00:00:00 2001 From: Igor Ryzhov Date: Sat, 9 Oct 2021 00:22:31 +0300 Subject: [PATCH 122/188] lib: set type for newly created interfaces Currently, the ll_type is set only in `netlink_interface` which is executed only during startup. If the interface is created when the FRR is already running, the type is not stored. Fixes #1164. Signed-off-by: Igor Ryzhov --- zebra/if_netlink.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index 15645d024df5..9385418655ce 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -1832,6 +1832,8 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) /* Update link. */ zebra_if_update_link(ifp, link_ifindex, ns_id); + ifp->ll_type = + netlink_to_zebra_link_type(ifi->ifi_type); netlink_interface_update_hw_addr(tb, ifp); /* Inform clients, install any configured addresses. */ @@ -1899,6 +1901,8 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) /* Update link. */ zebra_if_update_link(ifp, link_ifindex, ns_id); + ifp->ll_type = + netlink_to_zebra_link_type(ifi->ifi_type); netlink_interface_update_hw_addr(tb, ifp); if (if_is_no_ptm_operative(ifp)) { From ad7e12b0d9ccb1dfea1c3fba7d2355480bf6239b Mon Sep 17 00:00:00 2001 From: Igor Ryzhov Date: Fri, 8 Oct 2021 21:36:14 +0300 Subject: [PATCH 123/188] ospf6d: add missing vrf parameter to "clear ipv6 ospf6 interface" Currently, it's not possible to run this command in any VRF other than default. Signed-off-by: Igor Ryzhov --- doc/user/ospf6d.rst | 5 +++++ ospf6d/ospf6_interface.c | 30 +++++++++++++++++++++--------- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/doc/user/ospf6d.rst b/doc/user/ospf6d.rst index 093c5382cfa0..0b718fcdf232 100644 --- a/doc/user/ospf6d.rst +++ b/doc/user/ospf6d.rst @@ -85,6 +85,11 @@ OSPF6 router change to take effect, user can use this cli instead of restarting the ospf6d daemon. +.. clicmd:: clear ipv6 ospf6 [vrf NAME] interface [IFNAME] + + This command restarts the interface state machine for all interfaces in the + VRF or only for the specific interface if ``IFNAME`` is specified. + ASBR Summarisation Support in OSPFv3 ==================================== diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index a3eb1445f187..9d73740819a4 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -2739,27 +2739,39 @@ void ospf6_interface_clear(struct interface *ifp) /* Clear interface */ DEFUN (clear_ipv6_ospf6_interface, clear_ipv6_ospf6_interface_cmd, - "clear ipv6 ospf6 interface [IFNAME]", + "clear ipv6 ospf6 [vrf NAME] interface [IFNAME]", CLEAR_STR IP6_STR OSPF6_STR + VRF_CMD_HELP_STR INTERFACE_STR IFNAME_STR ) { - struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); + struct vrf *vrf; + int idx_vrf = 3; int idx_ifname = 4; struct interface *ifp; + const char *vrf_name; - if (argc == 4) /* Clear all the ospfv3 interfaces. */ - { + if (argv_find(argv, argc, "vrf", &idx_vrf)) + vrf_name = argv[idx_vrf + 1]->arg; + else + vrf_name = VRF_DEFAULT_NAME; + vrf = vrf_lookup_by_name(vrf_name); + if (!vrf) { + vty_out(vty, "%% VRF %s not found\n", vrf_name); + return CMD_WARNING; + } + + if (!argv_find(argv, argc, "IFNAME", &idx_ifname)) { + /* Clear all the ospfv3 interfaces. */ FOR_ALL_INTERFACES (vrf, ifp) ospf6_interface_clear(ifp); - } else /* Interface name is specified. */ - { - if ((ifp = if_lookup_by_name(argv[idx_ifname]->arg, - VRF_DEFAULT)) - == NULL) { + } else { + /* Interface name is specified. */ + ifp = if_lookup_by_name_vrf(argv[idx_ifname]->arg, vrf); + if (!ifp) { vty_out(vty, "No such Interface: %s\n", argv[idx_ifname]->arg); return CMD_WARNING; From 44076f4dc784686074adcdeb4f3e7390e1066350 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Sat, 9 Oct 2021 20:36:47 -0300 Subject: [PATCH 124/188] ospfd: use ospf_get_name() wherever possible Small cleanup to reduce code duplication. Signed-off-by: Renato Westphal --- ospfd/ospf_gr.c | 6 +- ospfd/ospf_nsm.c | 6 +- ospfd/ospf_packet.c | 13 ++-- ospfd/ospf_vty.c | 184 ++++++++++++-------------------------------- 4 files changed, 60 insertions(+), 149 deletions(-) diff --git a/ospfd/ospf_gr.c b/ospfd/ospf_gr.c index c108040303f1..6a5c0bae988c 100644 --- a/ospfd/ospf_gr.c +++ b/ospfd/ospf_gr.c @@ -584,7 +584,7 @@ static void ospf_gr_nvm_update(struct ospf *ospf) json_object *json_instance; filepath = ospf_gr_nvm_filepath(ospf); - inst_name = ospf->name ? ospf->name : VRF_DEFAULT_NAME; + inst_name = ospf_get_name(ospf); json = json_object_from_file(filepath); if (json == NULL) @@ -630,7 +630,7 @@ static void ospf_gr_nvm_delete(struct ospf *ospf) json_object *json_instances; filepath = ospf_gr_nvm_filepath(ospf); - inst_name = ospf->name ? ospf->name : VRF_DEFAULT_NAME; + inst_name = ospf_get_name(ospf); json = json_object_from_file(filepath); if (json == NULL) @@ -663,7 +663,7 @@ void ospf_gr_nvm_read(struct ospf *ospf) time_t timestamp = 0; filepath = ospf_gr_nvm_filepath(ospf); - inst_name = ospf->name ? ospf->name : VRF_DEFAULT_NAME; + inst_name = ospf_get_name(ospf); json = json_object_from_file(filepath); if (json == NULL) diff --git a/ospfd/ospf_nsm.c b/ospfd/ospf_nsm.c index 5f84d04fedee..865e7d37a81a 100644 --- a/ospfd/ospf_nsm.c +++ b/ospfd/ospf_nsm.c @@ -759,10 +759,8 @@ static void nsm_change_state(struct ospf_neighbor *nbr, int state) if (CHECK_FLAG(oi->ospf->config, OSPF_LOG_ADJACENCY_DETAIL)) zlog_info( "%s: Initializing [DD]: %pI4 with seqnum:%x , flags:%x", - (oi->ospf->name) ? oi->ospf->name - : VRF_DEFAULT_NAME, - &nbr->router_id, nbr->dd_seqnum, - nbr->dd_flags); + ospf_get_name(oi->ospf), &nbr->router_id, + nbr->dd_seqnum, nbr->dd_flags); ospf_db_desc_send(nbr); } diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index 1dcf93dcdef7..23817d2eab2d 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -1378,8 +1378,7 @@ static void ospf_db_desc(struct ip *iph, struct ospf_header *ospfh, if (CHECK_FLAG(oi->ospf->config, OSPF_LOG_ADJACENCY_DETAIL)) zlog_info( "%s:Packet[DD]: Neighbor %pI4 state is %s, seq_num:0x%x, local:0x%x", - (oi->ospf->name) ? oi->ospf->name : VRF_DEFAULT_NAME, - &nbr->router_id, + ospf_get_name(oi->ospf), &nbr->router_id, lookup_msg(ospf_nsm_state_msg, nbr->state, NULL), ntohl(dd->dd_seqnum), nbr->dd_seqnum); @@ -3879,9 +3878,8 @@ void ospf_db_desc_send(struct ospf_neighbor *nbr) if (CHECK_FLAG(oi->ospf->config, OSPF_LOG_ADJACENCY_DETAIL)) zlog_info( "%s:Packet[DD]: %pI4 DB Desc send with seqnum:%x , flags:%x", - (oi->ospf->name) ? oi->ospf->name : VRF_DEFAULT_NAME, - &nbr->router_id, nbr->dd_seqnum, - nbr->dd_flags); + ospf_get_name(oi->ospf), &nbr->router_id, + nbr->dd_seqnum, nbr->dd_flags); } /* Re-send Database Description. */ @@ -3899,9 +3897,8 @@ void ospf_db_desc_resend(struct ospf_neighbor *nbr) if (CHECK_FLAG(oi->ospf->config, OSPF_LOG_ADJACENCY_DETAIL)) zlog_info( "%s:Packet[DD]: %pI4 DB Desc resend with seqnum:%x , flags:%x", - (oi->ospf->name) ? oi->ospf->name : VRF_DEFAULT_NAME, - &nbr->router_id, nbr->dd_seqnum, - nbr->dd_flags); + ospf_get_name(oi->ospf), &nbr->router_id, + nbr->dd_seqnum, nbr->dd_flags); } /* Send Link State Request. */ diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 4109ada64a19..84aa4afe97d9 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -178,19 +178,11 @@ static void ospf_show_vrf_name(struct ospf *ospf, struct vty *vty, { if (use_vrf) { if (json) { - if (ospf->vrf_id == VRF_DEFAULT) - json_object_string_add(json, "vrfName", - "default"); - else - json_object_string_add(json, "vrfName", - ospf->name); + json_object_string_add(json, "vrfName", + ospf_get_name(ospf)); json_object_int_add(json, "vrfId", ospf->vrf_id); - } else { - if (ospf->vrf_id == VRF_DEFAULT) - vty_out(vty, "VRF Name: %s\n", "default"); - else if (ospf->name) - vty_out(vty, "VRF Name: %s\n", ospf->name); - } + } else + vty_out(vty, "VRF Name: %s\n", ospf_get_name(ospf)); } } @@ -230,8 +222,8 @@ DEFUN_NOSH (router_ospf, if (IS_DEBUG_OSPF_EVENT) zlog_debug( "Config command 'router ospf %d' received, vrf %s id %u oi_running %u", - ospf->instance, ospf->name ? ospf->name : "NIL", - ospf->vrf_id, ospf->oi_running); + ospf->instance, ospf_get_name(ospf), ospf->vrf_id, + ospf->oi_running); VTY_PUSH_CONTEXT(OSPF_NODE, ospf); @@ -571,8 +563,7 @@ DEFUN (ospf_network_area, if (IS_DEBUG_OSPF_EVENT) zlog_debug( "%s ospf vrf %s num of %u ip ospf area x config", - __func__, ospf->name ? ospf->name : "NIL", - count); + __func__, ospf_get_name(ospf), count); return CMD_WARNING_CONFIG_FAILED; } @@ -3343,12 +3334,8 @@ static int show_ip_ospf_common(struct vty *vty, struct ospf *ospf, if (json) { if (use_vrf) { json_object_object_add(json_vrf, "areas", json_areas); - if (ospf->vrf_id == VRF_DEFAULT) - json_object_object_add(json, "default", - json_vrf); - else - json_object_object_add(json, ospf->name, - json_vrf); + json_object_object_add(json, ospf_get_name(ospf), + json_vrf); } else { json_object_object_add(json, "areas", json_areas); } @@ -3970,12 +3957,8 @@ static int show_ip_ospf_interface_common(struct vty *vty, struct ospf *ospf, if (use_json) { if (use_vrf) { - if (ospf->vrf_id == VRF_DEFAULT) - json_object_object_add(json, "default", - json_vrf); - else - json_object_object_add(json, ospf->name, - json_vrf); + json_object_object_add(json, ospf_get_name(ospf), + json_vrf); } } else vty_out(vty, "\n"); @@ -4115,14 +4098,9 @@ static int show_ip_ospf_interface_traffic_common( } if (use_json) { - if (use_vrf) { - if (ospf->vrf_id == VRF_DEFAULT) - json_object_object_add(json, "default", - json_vrf); - else - json_object_object_add(json, ospf->name, - json_vrf); - } + if (use_vrf) + json_object_object_add(json, ospf_get_name(ospf), + json_vrf); } else vty_out(vty, "\n"); @@ -4519,14 +4497,9 @@ static int show_ip_ospf_neighbor_common(struct vty *vty, struct ospf *ospf, 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", - json_vrf); - else - json_object_object_add(json, ospf->name, - json_vrf); - } + if (use_vrf) + json_object_object_add(json, ospf_get_name(ospf), + json_vrf); } else vty_out(vty, "\n"); @@ -4748,14 +4721,9 @@ static int show_ip_ospf_neighbor_all_common(struct vty *vty, struct ospf *ospf, } if (use_json) { - if (use_vrf) { - if (ospf->vrf_id == VRF_DEFAULT) - json_object_object_add(json, "default", - json_vrf); - else - json_object_object_add(json, ospf->name, - json_vrf); - } + if (use_vrf) + json_object_object_add(json, ospf_get_name(ospf), + json_vrf); } else vty_out(vty, "\n"); @@ -5541,14 +5509,9 @@ static int show_ip_ospf_neighbor_detail_common(struct vty *vty, 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", - json_vrf); - else - json_object_object_add(json, ospf->name, - json_vrf); - } + if (use_vrf) + json_object_object_add(json, ospf_get_name(ospf), + json_vrf); } else vty_out(vty, "\n"); @@ -5732,14 +5695,9 @@ static int show_ip_ospf_neighbor_detail_all_common(struct vty *vty, } if (use_json) { - if (use_vrf) { - if (ospf->vrf_id == VRF_DEFAULT) - json_object_object_add(json, "default", - json_vrf); - else - json_object_object_add(json, ospf->name, - json_vrf); - } + if (use_vrf) + json_object_object_add(json, ospf_get_name(ospf), + json_vrf); } else { vty_out(vty, "\n"); } @@ -7049,14 +7007,9 @@ static int show_ip_ospf_database_common(struct vty *vty, struct ospf *ospf, if ((argc == arg_base + 4) || (uj && (argc == arg_base + 5))) { show_ip_ospf_database_summary(vty, ospf, 0, json_vrf); if (json) { - if (use_vrf) { - if (ospf->vrf_id == VRF_DEFAULT) - json_object_object_add(json, "default", - json_vrf); - else - json_object_object_add(json, ospf->name, - json_vrf); - } + if (use_vrf) + json_object_object_add( + json, ospf_get_name(ospf), json_vrf); } return CMD_SUCCESS; } @@ -7077,27 +7030,17 @@ static int show_ip_ospf_database_common(struct vty *vty, struct ospf *ospf, else if (strncmp(argv[arg_base + idx_type]->text, "se", 2) == 0) { show_ip_ospf_database_summary(vty, ospf, 1, json_vrf); if (json) { - if (use_vrf) { - if (ospf->vrf_id == VRF_DEFAULT) - json_object_object_add(json, "default", - json_vrf); - else - json_object_object_add(json, ospf->name, - json_vrf); - } + if (use_vrf) + json_object_object_add( + json, ospf_get_name(ospf), json_vrf); } return CMD_SUCCESS; } else if (strncmp(argv[arg_base + idx_type]->text, "m", 1) == 0) { show_ip_ospf_database_maxage(vty, ospf, json_vrf); if (json) { - if (use_vrf) { - if (ospf->vrf_id == VRF_DEFAULT) - json_object_object_add(json, "default", - json_vrf); - else - json_object_object_add(json, ospf->name, - json_vrf); - } + if (use_vrf) + json_object_object_add( + json, ospf_get_name(ospf), json_vrf); } return CMD_SUCCESS; } else if (strncmp(argv[arg_base + idx_type]->text, "opaque-l", 8) == 0) @@ -7137,14 +7080,9 @@ static int show_ip_ospf_database_common(struct vty *vty, struct ospf *ospf, } if (json) { - if (use_vrf) { - if (ospf->vrf_id == VRF_DEFAULT) - json_object_object_add(json, "default", - json_vrf); - else - json_object_object_add(json, ospf->name, - json_vrf); - } + if (use_vrf) + json_object_object_add(json, ospf_get_name(ospf), + json_vrf); } return CMD_SUCCESS; @@ -7373,14 +7311,9 @@ static int show_ip_ospf_database_type_adv_router_common(struct vty *vty, show_lsa_detail_adv_router(vty, ospf, type, &adv_router, json_vrf); if (json) { - if (use_vrf) { - if (ospf->vrf_id == VRF_DEFAULT) - json_object_object_add(json, "default", - json_vrf); - else - json_object_object_add(json, ospf->name, - json_vrf); - } + if (use_vrf) + json_object_object_add(json, ospf_get_name(ospf), + json_vrf); } return CMD_SUCCESS; @@ -10187,14 +10120,9 @@ static int ospf_show_gr_helper_details(struct vty *vty, struct ospf *ospf, ospf_show_vrf_name(ospf, vty, json_vrf, use_vrf); if (uj) { - if (use_vrf) { - if (ospf->vrf_id == VRF_DEFAULT) - json_object_object_add(json, "default", - json_vrf); - else - json_object_object_add(json, ospf->name, - json_vrf); - } + if (use_vrf) + json_object_object_add(json, ospf_get_name(ospf), + json_vrf); } else vty_out(vty, "\n"); @@ -11183,12 +11111,8 @@ static int show_ip_ospf_route_common(struct vty *vty, struct ospf *ospf, if (use_vrf) { // json_object_object_add(json_vrf, "areas", // json_areas); - if (ospf->vrf_id == VRF_DEFAULT) - json_object_object_add(json, "default", - json_vrf); - else - json_object_object_add(json, ospf->name, - json_vrf); + json_object_object_add(json, ospf_get_name(ospf), + json_vrf); } } else { vty_out(vty, "\n"); @@ -11358,10 +11282,7 @@ DEFUN (show_ip_ospf_vrfs, if (uj) json_vrf = json_object_new_object(); - if (ospf->vrf_id == VRF_DEFAULT) - name = VRF_DEFAULT_NAME; - else - name = ospf->name; + name = ospf_get_name(ospf); vrf_id_ui = (ospf->vrf_id == VRF_UNKNOWN) ? -1 @@ -11623,14 +11544,9 @@ static int ospf_show_summary_address(struct vty *vty, struct ospf *ospf, } if (uj) { - if (use_vrf) { - if (ospf->vrf_id == VRF_DEFAULT) - json_object_object_add(json, "default", - json_vrf); - else - json_object_object_add(json, ospf->name, - json_vrf); - } + if (use_vrf) + json_object_object_add(json, ospf_get_name(ospf), + json_vrf); } else vty_out(vty, "\n"); From 4008633d7b9c74b751b25be640206abd29e77404 Mon Sep 17 00:00:00 2001 From: Mark Stapp Date: Mon, 11 Oct 2021 11:57:30 -0400 Subject: [PATCH 125/188] tests: in isis_topo1_vrf, only configure valid interfaces Fix a loop in the setup phase of isis_topo1_vrf: only configure interfaces that each router actually has. Signed-off-by: Mark Stapp --- tests/topotests/isis_topo1_vrf/test_isis_topo1_vrf.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/topotests/isis_topo1_vrf/test_isis_topo1_vrf.py b/tests/topotests/isis_topo1_vrf/test_isis_topo1_vrf.py index 74d5edecabcd..a0cae0a40b34 100644 --- a/tests/topotests/isis_topo1_vrf/test_isis_topo1_vrf.py +++ b/tests/topotests/isis_topo1_vrf/test_isis_topo1_vrf.py @@ -105,15 +105,21 @@ def setup_module(mod): "ip link add {0}-cust1 type vrf table 1001", "ip link add loop1 type dummy", "ip link set {0}-eth0 master {0}-cust1", - "ip link set {0}-eth1 master {0}-cust1", ] + eth1_cmds = ["ip link set {0}-eth1 master {0}-cust1"] + # For all registered routers, load the zebra configuration file for rname, router in tgen.routers().items(): # create VRF rx-cust1 and link rx-eth0 to rx-cust1 for cmd in cmds: output = tgen.net[rname].cmd(cmd.format(rname)) + # If router has an rX-eth1, link that to vrf also + if "{}-eth1".format(rname) in router.links.keys(): + for cmd in eth1_cmds: + output = output + tgen.net[rname].cmd(cmd.format(rname)) + for rname, router in tgen.routers().items(): router.load_config( TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) From beaa0727241b9951e054d507a78ca79cb3d531ff Mon Sep 17 00:00:00 2001 From: Baptiste Jonglez Date: Tue, 12 Oct 2021 17:20:08 +0200 Subject: [PATCH 126/188] doc: Add missing static route options and clarify usage * Add missing "blackhole" and "reject" options * Add missing GATEWAY + IFNAME usage * Add missing "onlink" option * Explicit all possible usage patterns of static routes * Clarify description of each option Signed-off-by: Baptiste Jonglez --- doc/user/static.rst | 56 +++++++++++++++++++++++++++++++++------------ 1 file changed, 41 insertions(+), 15 deletions(-) diff --git a/doc/user/static.rst b/doc/user/static.rst index 200d187370b8..05847ba39409 100644 --- a/doc/user/static.rst +++ b/doc/user/static.rst @@ -33,25 +33,51 @@ Static Route Commands ===================== Static routing is a very fundamental feature of routing technology. It defines -a static prefix and gateway. +a static prefix and gateway, with several possible forms. -.. clicmd:: ip route NETWORK GATEWAY table TABLENO nexthop-vrf VRFNAME DISTANCE vrf VRFNAME +.. clicmd:: ip route NETWORK GATEWAY [DISTANCE] [table TABLENO] [nexthop-vrf VRFNAME] [vrf VRFNAME] -.. clicmd:: ipv6 route NETWORK from SRCPREFIX GATEWAY table TABLENO nexthop-vrf VRFNAME DISTANCE vrf VRFNAME +.. clicmd:: ip route NETWORK IFNAME [DISTANCE] [table TABLENO] [nexthop-vrf VRFNAME] [vrf VRFNAME] + +.. clicmd:: ip route NETWORK GATEWAY IFNAME [DISTANCE] [onlink] [table TABLENO] [nexthop-vrf VRFNAME] [vrf VRFNAME] + +.. clicmd:: ip route NETWORK (Null0|blackhole|reject) [DISTANCE] [table TABLENO] [nexthop-vrf VRFNAME] [vrf VRFNAME] + +.. clicmd:: ipv6 route NETWORK [from SRCPREFIX] GATEWAY [DISTANCE] [table TABLENO] [nexthop-vrf VRFNAME] [vrf VRFNAME] + +.. clicmd:: ipv6 route NETWORK [from SRCPREFIX] IFNAME [DISTANCE] [table TABLENO] [nexthop-vrf VRFNAME] [vrf VRFNAME] + +.. clicmd:: ipv6 route NETWORK [from SRCPREFIX] GATEWAY IFNAME [DISTANCE] [onlink] [table TABLENO] [nexthop-vrf VRFNAME] [vrf VRFNAME] + +.. clicmd:: ipv6 route NETWORK [from SRCPREFIX] (Null0|blackhole|reject) [DISTANCE] [table TABLENO] [nexthop-vrf VRFNAME] [vrf VRFNAME] NETWORK is destination prefix with a valid v4 or v6 network based upon - initial form of the command. GATEWAY is gateway for the prefix it currently - must match the v4 or v6 route type specified at the start of the command. - GATEWAY can also be treated as an interface name. If the interface name - is ``null0`` then zebra installs a blackhole route. TABLENO - is an optional parameter for namespaces that allows you to create the - route in a specified table associated with the vrf namespace. table will - be rejected if you are not using namespace based vrfs. ``nexthop-vrf`` - allows you to create a leaked route with a nexthop in the specified VRFNAME - vrf VRFNAME allows you to create the route in a specified vrf. - ``nexthop-vrf`` cannot be currently used with namespace based vrfs - currently as well. - The v6 variant allows the installation of a static source-specific route + initial form of the command. + + GATEWAY is the IP address to use as next-hop for the prefix. Currently, it must match + the v4 or v6 route type specified at the start of the command. + + IFNAME is the name of the interface to use as next-hop. If only IFNAME is specified + (without GATEWAY), a connected route will be created. + + When both IFNAME and GATEWAY are specified together, it binds the route to the specified + interface. In this case, it is also possible to specify ``onlink`` to force the kernel + to consider the next-hop as "on link" on the given interface. + + Alternatively, the gateway can be specified as ``Null0`` or ``blackhole`` to create a blackhole + route that drops all traffic. It can also be specified as ``reject`` to create an unreachable + route that rejects traffic with ICMP "Destination Unreachable" messages. + + TABLENO is an optional parameter for namespaces that allows you to create the + route in a specified table associated with the vrf namespace. ``table`` will + be rejected if you are not using namespace based vrfs. + + ``vrf`` VRFNAME allows you to create the route in a specified vrf. + + ``nexthop-vrf`` VRFNAME allows you to create a leaked route with a nexthop in the + specified VRFNAME. ``nexthop-vrf`` cannot be currently used with namespace based vrfs. + + The IPv6 variant allows the installation of a static source-specific route with the SRCPREFIX sub command. These routes are currently supported on Linux operating systems only, and perform AND matching on packet's destination and source addresses in the kernel's forwarding path. Note From 7f39a26c775daeba75b7c512342c98bfafe7e220 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 12 Oct 2021 15:41:07 -0400 Subject: [PATCH 127/188] *: If building clippy we must have python3 When building clippy we must have python 3. Let's ensure that we test for it and stop the auto-make if it is not installed on the system. Signed-off-by: Donald Sharp --- configure.ac | 1 + 1 file changed, 1 insertion(+) diff --git a/configure.ac b/configure.ac index 873ed18db854..c5e5d64aa050 100644 --- a/configure.ac +++ b/configure.ac @@ -797,6 +797,7 @@ fi # AS_IF([test "$host" = "$build"], [ + AM_PATH_PYTHON([3]) AC_CHECK_HEADER([gelf.h], [], [ AC_MSG_ERROR([libelf headers are required for building clippy. (Host only when cross-compiling.)]) ]) From 4a0167fee54750693c7d20c84636bcef34e1ebb8 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 8 Oct 2021 09:05:28 -0300 Subject: [PATCH 128/188] ospfd: fix flushing of Grace-LSAs on broadcast interfaces The ospfd opaque LSA infrastruture has an issue where it can't store different versions of the same Type-9 LSA for different interfaces. When flushing the self-originated Grace-LSAs upon exiting from the GR mode, the code was looking up the single self-originated Grace-LSA from the LSDB, setting its age to MaxAge and sending it out on all interfaces. The problem is that Grace-LSAs sent on broadcast interfaces have their own unique "IP interface address" TLV that is used to identify the restarting router. That way, just reusing the same Grace-LSA for all interfaces doesn't work. Fix this by generating a new Grace-LSA with its age manually set to MaxAge whenever one needs to be flushed. This will allow the "IP interface address" TLV to be set correctly and make GR work even in the presence of multiple broadcast interfaces. In the long term, the opaque LSA infrastructure should be updated to support Type-9 link-local LSAs correctly so that we don't need to resort to hacks like this. Signed-off-by: Renato Westphal --- ospfd/ospf_gr.c | 48 ++++++------------------------------------------ 1 file changed, 6 insertions(+), 42 deletions(-) diff --git a/ospfd/ospf_gr.c b/ospfd/ospf_gr.c index c108040303f1..fed8bddb5f9e 100644 --- a/ospfd/ospf_gr.c +++ b/ospfd/ospf_gr.c @@ -150,7 +150,7 @@ static struct ospf_lsa *ospf_gr_lsa_new(struct ospf_interface *oi) } /* Originate and install Grace-LSA for a given interface. */ -static void ospf_gr_lsa_originate(struct ospf_interface *oi) +static void ospf_gr_lsa_originate(struct ospf_interface *oi, bool maxage) { struct ospf_lsa *lsa, *old; @@ -164,6 +164,9 @@ static void ospf_gr_lsa_originate(struct ospf_interface *oi) return; } + if (maxage) + lsa->data->ls_age = htons(OSPF_LSA_MAXAGE); + /* Find the old LSA and increase the seqno. */ old = ospf_gr_lsa_lookup(oi->ospf, oi->area); if (old) @@ -183,37 +186,6 @@ static void ospf_gr_lsa_originate(struct ospf_interface *oi) ospf_flood_through_interface(oi, NULL, lsa); } -/* Flush a given self-originated Grace-LSA. */ -static struct ospf_lsa *ospf_gr_flush_grace_lsa(struct ospf_interface *oi, - struct ospf_lsa *old) -{ - struct ospf_lsa *lsa; - - if (ospf_interface_neighbor_count(oi) == 0) - return NULL; - - if (IS_DEBUG_OSPF_GR) - zlog_debug( - "GR: flushing self-originated Grace-LSAs [interface %s]", - oi->ifp->name); - - lsa = ospf_lsa_dup(old); - lsa->data->ls_age = htons(OSPF_LSA_MAXAGE); - lsa->data->ls_seqnum = lsa_seqnum_increment(lsa); - - /* Install updated LSA into LSDB. */ - if (ospf_lsa_install(oi->ospf, oi, lsa) == NULL) { - zlog_warn("%s: ospf_lsa_install() failed", __func__); - ospf_lsa_unlock(&lsa); - return NULL; - } - - /* Flood the LSA through out the interface */ - ospf_flood_through_interface(oi, NULL, lsa); - - return lsa; -} - /* Flush all self-originated Grace-LSAs. */ static void ospf_gr_flush_grace_lsas(struct ospf *ospf) { @@ -221,7 +193,6 @@ static void ospf_gr_flush_grace_lsas(struct ospf *ospf) struct listnode *anode; for (ALL_LIST_ELEMENTS_RO(ospf->areas, anode, area)) { - struct ospf_lsa *lsa; struct ospf_interface *oi; struct listnode *inode; @@ -230,15 +201,8 @@ static void ospf_gr_flush_grace_lsas(struct ospf *ospf) "GR: flushing self-originated Grace-LSAs [area %pI4]", &area->area_id); - lsa = ospf_gr_lsa_lookup(ospf, area); - if (!lsa) { - zlog_warn("%s: Grace-LSA not found [area %pI4]", - __func__, &area->area_id); - continue; - } - for (ALL_LIST_ELEMENTS_RO(area->oiflist, inode, oi)) - ospf_gr_flush_grace_lsa(oi, lsa); + ospf_gr_lsa_originate(oi, true); } } @@ -750,7 +714,7 @@ static void ospf_gr_prepare(void) /* Send a Grace-LSA to all neighbors. */ for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, inode, oi)) - ospf_gr_lsa_originate(oi); + ospf_gr_lsa_originate(oi, false); /* Record end of the grace period in non-volatile memory. */ ospf_gr_nvm_update(ospf); From d6f60d2276de10d985deceeab5804d24de3c952b Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Sat, 9 Oct 2021 18:59:58 -0300 Subject: [PATCH 129/188] ospf6d: fix LSA name in debug message Signed-off-by: Renato Westphal --- ospf6d/ospf6_gr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ospf6d/ospf6_gr.c b/ospf6d/ospf6_gr.c index 40893ed99824..c3e6f62f067a 100644 --- a/ospf6d/ospf6_gr.c +++ b/ospf6d/ospf6_gr.c @@ -58,7 +58,7 @@ static int ospf6_gr_lsa_originate(struct ospf6_interface *oi) char buffer[OSPF6_MAX_LSASIZE]; if (IS_OSPF6_DEBUG_ORIGINATE(LINK)) - zlog_debug("Originate Link-LSA for Interface %s", + zlog_debug("Originate Grace-LSA for Interface %s", oi->interface->name); /* prepare buffer */ From eedc80c1f59c060d0f313dee9910f32f99c606c3 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Sat, 9 Oct 2021 20:02:16 -0300 Subject: [PATCH 130/188] ospfd: introduce additional opaque capability check in the GR code Before starting the graceful restart procedures, ospf_gr_prepare() verifies for each configured OSPF instance whether it has the opaque capability enabled (a pre-requisite for GR). If not, a warning is emitted and GR isn't performed on that instance. This PR introduces an additional opaque capability check that will return a CLI error when the opaque capability isn't enabled. The idea is to make it easier for the user to identify when the GR activation has failed, instead of requiring him or her to check the logs for errors. The original opaque capability check from ospf_gr_prepare() was retaining as it's possible that that function might be called from other contexts in the future. Signed-off-by: Renato Westphal --- ospfd/ospf_gr.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ospfd/ospf_gr.c b/ospfd/ospf_gr.c index fed8bddb5f9e..aae7e33867d9 100644 --- a/ospfd/ospf_gr.c +++ b/ospfd/ospf_gr.c @@ -734,6 +734,18 @@ DEFPY(graceful_restart_prepare, graceful_restart_prepare_cmd, IP_STR "Prepare to restart the OSPF process") { + struct ospf *ospf; + struct listnode *node; + + for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { + if (!CHECK_FLAG(ospf->config, OSPF_OPAQUE_CAPABLE)) { + vty_out(vty, + "%% Can't start graceful restart: opaque capability not enabled (VRF %s)\n\n", + ospf_get_name(ospf)); + return CMD_WARNING; + } + } + ospf_gr_prepare(); return CMD_SUCCESS; From 3ebf9d34161833d5ab102d3d4f9107b1d8c01481 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Tue, 12 Oct 2021 16:08:23 -0300 Subject: [PATCH 131/188] ospfd: fix another DR election issue during graceful restart Commit 3551ee9e90304 introduced a regression that causes GR to fail under certain circumstances. In short, while ISM events should be ignored while acting as a helper for a restarting router, the DR/BDR fields of the neighbor structure should still be updated while processing a Hello packet. If that isn't done, it can cause the helper to elect the wrong DR while exiting from the helper mode, leading to a situation where there are two DRs for the same network segment (and a failed GR by consequence). Fix this. Signed-off-by: Renato Westphal --- ospfd/ospf_packet.c | 64 +++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index eacc30eba0a5..ea356a2bef29 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -1096,39 +1096,41 @@ static void ospf_hello(struct ip *iph, struct ospf_header *ospfh, zlog_debug( "%s, Neighbor is under GR Restart, hence ignoring the ISM Events", __PRETTY_FUNCTION__); - - return; - } - - /* If neighbor itself declares DR and no BDR exists, - cause event BackupSeen */ - if (IPV4_ADDR_SAME(&nbr->address.u.prefix4, &hello->d_router)) - if (hello->bd_router.s_addr == INADDR_ANY - && oi->state == ISM_Waiting) + } else { + /* If neighbor itself declares DR and no BDR exists, + cause event BackupSeen */ + if (IPV4_ADDR_SAME(&nbr->address.u.prefix4, &hello->d_router)) + if (hello->bd_router.s_addr == INADDR_ANY + && oi->state == ISM_Waiting) + OSPF_ISM_EVENT_SCHEDULE(oi, ISM_BackupSeen); + + /* neighbor itself declares BDR. */ + if (oi->state == ISM_Waiting + && IPV4_ADDR_SAME(&nbr->address.u.prefix4, + &hello->bd_router)) OSPF_ISM_EVENT_SCHEDULE(oi, ISM_BackupSeen); - /* neighbor itself declares BDR. */ - if (oi->state == ISM_Waiting - && IPV4_ADDR_SAME(&nbr->address.u.prefix4, &hello->bd_router)) - OSPF_ISM_EVENT_SCHEDULE(oi, ISM_BackupSeen); - - /* had not previously. */ - if ((IPV4_ADDR_SAME(&nbr->address.u.prefix4, &hello->d_router) - && IPV4_ADDR_CMP(&nbr->address.u.prefix4, &nbr->d_router)) - || (IPV4_ADDR_CMP(&nbr->address.u.prefix4, &hello->d_router) - && IPV4_ADDR_SAME(&nbr->address.u.prefix4, &nbr->d_router))) - OSPF_ISM_EVENT_SCHEDULE(oi, ISM_NeighborChange); - - /* had not previously. */ - if ((IPV4_ADDR_SAME(&nbr->address.u.prefix4, &hello->bd_router) - && IPV4_ADDR_CMP(&nbr->address.u.prefix4, &nbr->bd_router)) - || (IPV4_ADDR_CMP(&nbr->address.u.prefix4, &hello->bd_router) - && IPV4_ADDR_SAME(&nbr->address.u.prefix4, &nbr->bd_router))) - OSPF_ISM_EVENT_SCHEDULE(oi, ISM_NeighborChange); - - /* Neighbor priority check. */ - if (nbr->priority >= 0 && nbr->priority != hello->priority) - OSPF_ISM_EVENT_SCHEDULE(oi, ISM_NeighborChange); + /* had not previously. */ + if ((IPV4_ADDR_SAME(&nbr->address.u.prefix4, &hello->d_router) + && IPV4_ADDR_CMP(&nbr->address.u.prefix4, &nbr->d_router)) + || (IPV4_ADDR_CMP(&nbr->address.u.prefix4, &hello->d_router) + && IPV4_ADDR_SAME(&nbr->address.u.prefix4, + &nbr->d_router))) + OSPF_ISM_EVENT_SCHEDULE(oi, ISM_NeighborChange); + + /* had not previously. */ + if ((IPV4_ADDR_SAME(&nbr->address.u.prefix4, &hello->bd_router) + && IPV4_ADDR_CMP(&nbr->address.u.prefix4, &nbr->bd_router)) + || (IPV4_ADDR_CMP(&nbr->address.u.prefix4, + &hello->bd_router) + && IPV4_ADDR_SAME(&nbr->address.u.prefix4, + &nbr->bd_router))) + OSPF_ISM_EVENT_SCHEDULE(oi, ISM_NeighborChange); + + /* Neighbor priority check. */ + if (nbr->priority >= 0 && nbr->priority != hello->priority) + OSPF_ISM_EVENT_SCHEDULE(oi, ISM_NeighborChange); + } /* Set neighbor information. */ nbr->priority = hello->priority; From ba62a5c522432a4e8ecbf2307324cb384b4dd7e2 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 13 Oct 2021 07:58:37 -0400 Subject: [PATCH 132/188] lib: Add missing enum values in switch statement for if_link_type_str The switch statement over `enum zebra_link_type` had a default and FRR was missing a few of the pre-defined types we cared about. Remove the default statement and add the missing values. Signed-off-by: Donald Sharp --- lib/if.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/if.c b/lib/if.c index 424880ff425a..d8ac34b2507c 100644 --- a/lib/if.c +++ b/lib/if.c @@ -1108,6 +1108,8 @@ const char *if_link_type_str(enum zebra_link_type llt) llts(ZEBRA_LLT_CSLIP, "Compressed SLIP"); llts(ZEBRA_LLT_SLIP6, "SLIPv6"); llts(ZEBRA_LLT_CSLIP6, "Compressed SLIPv6"); + llts(ZEBRA_LLT_RSRVD, "Reserved"); + llts(ZEBRA_LLT_ADAPT, "Adapt"); llts(ZEBRA_LLT_ROSE, "ROSE packet radio"); llts(ZEBRA_LLT_X25, "CCITT X.25"); llts(ZEBRA_LLT_PPP, "PPP"); @@ -1124,8 +1126,10 @@ const char *if_link_type_str(enum zebra_link_type llt) llts(ZEBRA_LLT_SIT, "IPv6-in-IPv4 SIT"); llts(ZEBRA_LLT_IPDDP, "IP-in-DDP tunnel"); llts(ZEBRA_LLT_IPGRE, "GRE over IP"); + llts(ZEBRA_LLT_IP6GRE, "GRE over IPv6"); llts(ZEBRA_LLT_PIMREG, "PIMSM registration"); llts(ZEBRA_LLT_HIPPI, "HiPPI"); + llts(ZEBRA_LLT_ECONET, "Acorn Econet"); llts(ZEBRA_LLT_IRDA, "IrDA"); llts(ZEBRA_LLT_FCPP, "Fibre-Channel PtP"); llts(ZEBRA_LLT_FCAL, "Fibre-Channel Arbitrated Loop"); @@ -1136,9 +1140,6 @@ const char *if_link_type_str(enum zebra_link_type llt) llts(ZEBRA_LLT_IEEE80211_RADIOTAP, "IEEE 802.11 Radiotap"); llts(ZEBRA_LLT_IEEE802154, "IEEE 802.15.4"); llts(ZEBRA_LLT_IEEE802154_PHY, "IEEE 802.15.4 Phy"); - default: - flog_err(EC_LIB_DEVELOPMENT, "Unknown value %d", llt); - return "Unknown type!"; #undef llts } return NULL; From 48f05b233fbc95f3601dfde9335073070b3c1c76 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 13 Oct 2021 09:03:27 -0400 Subject: [PATCH 133/188] tests: Fix `Invalid escape sequence` warnings in test runs Test runs are creating these warnings: bgp_l3vpn_to_bgp_vrf/test_bgp_l3vpn_to_bgp_vrf.py::test_check_linux_mpls :7: DeprecationWarning: invalid escape sequence \d bgp_l3vpn_to_bgp_vrf/test_bgp_l3vpn_to_bgp_vrf.py::test_check_linux_mpls :19: DeprecationWarning: invalid escape sequence \d bgp_l3vpn_to_bgp_vrf/test_bgp_l3vpn_to_bgp_vrf.py::test_check_scale_up :24: DeprecationWarning: invalid escape sequence \d bgp_l3vpn_to_bgp_vrf/test_bgp_l3vpn_to_bgp_vrf.py::test_check_scale_up :191: DeprecationWarning: invalid escape sequence \d -- Docs: https://docs.pytest.org/en/stable/warnings.html Find and destroy these warnings Signed-off-by: Donald Sharp --- .../bgp_l3vpn_to_bgp_vrf/scripts/check_linux_mpls.py | 4 ++-- tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_up.py | 4 ++-- tests/topotests/lib/ltemplate.py | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_mpls.py b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_mpls.py index a5f95f94bf38..91a7adf9970e 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_mpls.py +++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_mpls.py @@ -4,7 +4,7 @@ ret = luCommand( "r2", "ip -M route show", - "\d*(?= via inet 10.0.2.4 dev r2-eth1)", + r"\d*(?= via inet 10.0.2.4 dev r2-eth1)", "wait", "See mpls route to r4", ) @@ -16,7 +16,7 @@ ret = luCommand( "r2", "ip -M route show", - "\d*(?= via inet 10.0.1.1 dev r2-eth0)", + r"\d*(?= via inet 10.0.1.1 dev r2-eth0)", "wait", "See mpls route to r1", ) diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_up.py b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_up.py index 9f100b7c3060..eaa6aa4c3072 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_up.py +++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_up.py @@ -21,7 +21,7 @@ ret = luCommand( rtr, 'vtysh -c "show memory"', - "zebra: System allocator statistics: Total heap allocated: *(\d*) ([A-Za-z]*) .*bgpd: System allocator statistics: Total heap allocated: *(\d*) ([A-Za-z]*)", + r"zebra: System allocator statistics: Total heap allocated: *(\d*) ([A-Za-z]*) .*bgpd: System allocator statistics: Total heap allocated: *(\d*) ([A-Za-z]*)", "none", "collect bgpd memory stats", ) @@ -188,7 +188,7 @@ ret = luCommand( rtr, 'vtysh -c "show memory"', - "zebra: System allocator statistics: Total heap allocated: *(\d*) ([A-Za-z]*) .*bgpd: System allocator statistics: Total heap allocated: *(\d*) ([A-Za-z]*)", + r"zebra: System allocator statistics: Total heap allocated: *(\d*) ([A-Za-z]*) .*bgpd: System allocator statistics: Total heap allocated: *(\d*) ([A-Za-z]*)", "none", "collect bgpd memory stats", ) diff --git a/tests/topotests/lib/ltemplate.py b/tests/topotests/lib/ltemplate.py index c98bfac9ee6d..18882285ed5c 100644 --- a/tests/topotests/lib/ltemplate.py +++ b/tests/topotests/lib/ltemplate.py @@ -291,7 +291,7 @@ def ltemplateVersionCheck( # collect/log info on iproute2 cc = ltemplateRtrCmd() found = cc.doCmd( - tgen, rname, "apt-cache policy iproute2", "Installed: ([\d\.]*)" + tgen, rname, "apt-cache policy iproute2", r"Installed: ([\d\.]*)" ) if found != None: iproute2Ver = found.group(1) From 3766c36a209de3e33df05f71642664921d9cc6c5 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 13 Oct 2021 12:40:35 -0400 Subject: [PATCH 134/188] ospfd: Add `converged` and `role` json output for neighbor command The `show ip ospf neighbor json` command was displaying state:`Full\/DR` Where state was both the role and whether or not the neigbhor was converged. While from a OSPF perspective this is the state. This state is a combination of two things. This creates a problem in testing because we have no guarantee that a particular ospf router will actually have a particular role given how loaded our topotest systems are. So add a bit of json output to display both the converged status as well as the role this router is playing on this neighbor/interface. The above becomes: state:`Full\/DR` converged:`Full` role:`DR` Tests can now be modified to look for `Full` and allow it to continue. Most of the tests do not actually care if this router is the DR or Backup. Signed-off-by: Donald Sharp --- ospfd/ospf_dump.c | 10 ++++++++-- ospfd/ospf_dump.h | 1 + ospfd/ospf_vty.c | 10 ++++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/ospfd/ospf_dump.c b/ospfd/ospf_dump.c index f11c84b092f9..b1aeefcd432d 100644 --- a/ospfd/ospf_dump.c +++ b/ospfd/ospf_dump.c @@ -146,8 +146,7 @@ const char *ospf_if_name_string(struct ospf_interface *oi) return buf; } - -void ospf_nbr_state_message(struct ospf_neighbor *nbr, char *buf, size_t size) +int ospf_nbr_ism_state(struct ospf_neighbor *nbr) { int state; struct ospf_interface *oi = nbr->oi; @@ -159,6 +158,13 @@ void ospf_nbr_state_message(struct ospf_neighbor *nbr, char *buf, size_t size) else state = ISM_DROther; + return state; +} + +void ospf_nbr_state_message(struct ospf_neighbor *nbr, char *buf, size_t size) +{ + int state = ospf_nbr_ism_state(nbr); + snprintf(buf, size, "%s/%s", lookup_msg(ospf_nsm_state_msg, nbr->state, NULL), lookup_msg(ospf_ism_state_msg, state, NULL)); diff --git a/ospfd/ospf_dump.h b/ospfd/ospf_dump.h index a1f55dd0af7c..031ec2f42866 100644 --- a/ospfd/ospf_dump.h +++ b/ospfd/ospf_dump.h @@ -150,6 +150,7 @@ extern char *ospf_lsa_type_str[]; extern const char *ospf_area_name_string(struct ospf_area *); extern const char *ospf_area_desc_string(struct ospf_area *); extern const char *ospf_if_name_string(struct ospf_interface *); +extern int ospf_nbr_ism_state(struct ospf_neighbor *nbr); extern void ospf_nbr_state_message(struct ospf_neighbor *, char *, size_t); extern const char *ospf_timer_dump(struct thread *, char *, size_t); extern const char *ospf_timeval_dump(struct timeval *, char *, size_t); diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 4109ada64a19..4d42734ce5b3 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -4419,6 +4419,16 @@ static void show_ip_ospf_neighbor_sub(struct vty *vty, json_object_string_add(json_neighbor, "state", msgbuf); + json_object_string_add( + json_neighbor, "converged", + lookup_msg(ospf_nsm_state_msg, + nbr->state, NULL)); + json_object_string_add( + json_neighbor, "role", + lookup_msg(ospf_ism_state_msg, + ospf_nbr_ism_state(nbr), + NULL)); + if (nbr->t_inactivity) { long time_store; From a22d51e21eb23d423e59d9c8f1973200283e6f69 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 13 Oct 2021 12:46:22 -0400 Subject: [PATCH 135/188] tests: Convert over to using converged to test for ospf being converged OSPF when it is deciding on whom it should elect for DR and backup has a process that prioritizes network stabilty over the exact same results of who is the DR / Backups. Essentially if we have r1 ----- r2 Let's say r1 has a higher priority, but r2 comes up first, starts sending hello packets and then decides that it is the DR. At some point in time in the future, r1 comes up and then connects to r2 at that point it sees that r2 has elected itself DR and it keeps it that way. This is by design of the system. With our tight ospf timers as well as high load being experienced on our test systems. There exists a bunch of ospf tests that we cannot guarantee that a consistent DR will be elected for the test. As such let's not even pretend that we care a bunch and just look for `Full`. If we care about `ordering` we need to spend more time getting the tests to actually start routers, ensure that htey are up and running in the right order so that priority can take place. Signed-off-by: Donald Sharp --- tests/topotests/bgp_features/r1/ospf_neighbor.json | 4 ++-- tests/topotests/bgp_features/r2/ospf_neighbor.json | 4 ++-- tests/topotests/bgp_features/r3/ospf_neighbor.json | 4 ++-- .../ldp_oc_acl_topo1/r1/show_ip_ospf_neighbor.json | 2 +- .../ldp_oc_acl_topo1/r2/show_ip_ospf_neighbor.json | 6 +++--- .../ldp_oc_acl_topo1/r3/show_ip_ospf_neighbor.json | 4 ++-- .../ldp_oc_acl_topo1/r4/show_ip_ospf_neighbor.json | 4 ++-- .../ldp_oc_topo1/r1/show_ip_ospf_neighbor.json | 2 +- .../ldp_oc_topo1/r2/show_ip_ospf_neighbor.json | 6 +++--- .../ldp_oc_topo1/r3/show_ip_ospf_neighbor.json | 4 ++-- .../ldp_oc_topo1/r4/show_ip_ospf_neighbor.json | 4 ++-- .../ldp_sync_ospf_topo1/r1/show_ip_ospf_neighbor.json | 4 ++-- .../ldp_sync_ospf_topo1/r2/show_ip_ospf_neighbor.json | 4 ++-- .../ldp_sync_ospf_topo1/r3/show_ip_ospf_neighbor.json | 4 ++-- .../ldp_vpls_topo1/r1/show_ip_ospf_neighbor.json | 4 ++-- .../ldp_vpls_topo1/r2/show_ip_ospf_neighbor.json | 4 ++-- .../ldp_vpls_topo1/r3/show_ip_ospf_neighbor.json | 4 ++-- .../ospf_gr_topo1/rt1/show_ip_ospf_neighbor.json | 2 +- .../ospf_gr_topo1/rt2/show_ip_ospf_neighbor.json | 4 ++-- .../ospf_gr_topo1/rt3/show_ip_ospf_neighbor.json | 6 +++--- .../ospf_gr_topo1/rt4/show_ip_ospf_neighbor.json | 4 ++-- .../ospf_gr_topo1/rt5/show_ip_ospf_neighbor.json | 2 +- .../ospf_gr_topo1/rt6/show_ip_ospf_neighbor.json | 4 ++-- .../ospf_gr_topo1/rt7/show_ip_ospf_neighbor.json | 2 +- tests/topotests/ospf_topo1/test_ospf_topo1.py | 6 +++--- tests/topotests/pim_acl/r1/ospf_neighbor.json | 10 +++++----- .../topotests/pim_igmp_vrf/r1/ospf_blue_neighbor.json | 2 +- tests/topotests/pim_igmp_vrf/r1/ospf_red_neighbor.json | 2 +- 28 files changed, 56 insertions(+), 56 deletions(-) diff --git a/tests/topotests/bgp_features/r1/ospf_neighbor.json b/tests/topotests/bgp_features/r1/ospf_neighbor.json index e742c119dadd..3b5f46d9346b 100644 --- a/tests/topotests/bgp_features/r1/ospf_neighbor.json +++ b/tests/topotests/bgp_features/r1/ospf_neighbor.json @@ -3,13 +3,13 @@ "192.168.0.2":[ { "priority":5, - "state":"Full\/Backup" + "converged":"Full" } ], "192.168.0.3":[ { "priority":5, - "state":"Full\/Backup" + "converged":"Full" } ] } diff --git a/tests/topotests/bgp_features/r2/ospf_neighbor.json b/tests/topotests/bgp_features/r2/ospf_neighbor.json index 2fd589ae25d6..47bb57cd00f7 100644 --- a/tests/topotests/bgp_features/r2/ospf_neighbor.json +++ b/tests/topotests/bgp_features/r2/ospf_neighbor.json @@ -3,13 +3,13 @@ "192.168.0.1":[ { "priority":10, - "state":"Full\/DR" + "converged":"Full" } ], "192.168.0.3":[ { "priority":5, - "state":"Full\/Backup" + "converged":"Full" } ] } diff --git a/tests/topotests/bgp_features/r3/ospf_neighbor.json b/tests/topotests/bgp_features/r3/ospf_neighbor.json index 80fc92c3bcd3..b84974ccca64 100644 --- a/tests/topotests/bgp_features/r3/ospf_neighbor.json +++ b/tests/topotests/bgp_features/r3/ospf_neighbor.json @@ -3,13 +3,13 @@ "192.168.0.1":[ { "priority":10, - "state":"Full\/DR" + "converged":"Full" } ], "192.168.0.2":[ { "priority":10, - "state":"Full\/DR" + "converged":"Full" } ] } diff --git a/tests/topotests/ldp_oc_acl_topo1/r1/show_ip_ospf_neighbor.json b/tests/topotests/ldp_oc_acl_topo1/r1/show_ip_ospf_neighbor.json index aa3f74fc5f12..63281e9be33d 100644 --- a/tests/topotests/ldp_oc_acl_topo1/r1/show_ip_ospf_neighbor.json +++ b/tests/topotests/ldp_oc_acl_topo1/r1/show_ip_ospf_neighbor.json @@ -3,7 +3,7 @@ "2.2.2.2":[ { "priority":2, - "state":"Full\/DR", + "converged":"Full", "address":"10.0.1.2", "ifaceName":"r1-eth0:10.0.1.1" } diff --git a/tests/topotests/ldp_oc_acl_topo1/r2/show_ip_ospf_neighbor.json b/tests/topotests/ldp_oc_acl_topo1/r2/show_ip_ospf_neighbor.json index aa68198957b6..f361d605ce30 100644 --- a/tests/topotests/ldp_oc_acl_topo1/r2/show_ip_ospf_neighbor.json +++ b/tests/topotests/ldp_oc_acl_topo1/r2/show_ip_ospf_neighbor.json @@ -3,7 +3,7 @@ "1.1.1.1":[ { "priority":1, - "state":"Full\/Backup", + "converged":"Full", "address":"10.0.1.1", "ifaceName":"r2-eth0:10.0.1.2" } @@ -11,7 +11,7 @@ "3.3.3.3":[ { "priority":2, - "state":"Full\/Backup", + "converged":"Full", "address":"10.0.2.3", "ifaceName":"r2-eth1:10.0.2.2" } @@ -19,7 +19,7 @@ "4.4.4.4":[ { "priority":3, - "state":"Full\/DR", + "converged":"Full", "address":"10.0.2.4", "ifaceName":"r2-eth1:10.0.2.2" } diff --git a/tests/topotests/ldp_oc_acl_topo1/r3/show_ip_ospf_neighbor.json b/tests/topotests/ldp_oc_acl_topo1/r3/show_ip_ospf_neighbor.json index 905774fc466a..38794357ff5b 100644 --- a/tests/topotests/ldp_oc_acl_topo1/r3/show_ip_ospf_neighbor.json +++ b/tests/topotests/ldp_oc_acl_topo1/r3/show_ip_ospf_neighbor.json @@ -3,7 +3,7 @@ "2.2.2.2":[ { "priority":1, - "state":"Full\/DROther", + "converged":"Full", "address":"10.0.2.2", "ifaceName":"r3-eth0:10.0.2.3" } @@ -11,7 +11,7 @@ "4.4.4.4":[ { "priority":3, - "state":"Full\/DR", + "converged":"Full", "address":"10.0.2.4", "ifaceName":"r3-eth0:10.0.2.3" } diff --git a/tests/topotests/ldp_oc_acl_topo1/r4/show_ip_ospf_neighbor.json b/tests/topotests/ldp_oc_acl_topo1/r4/show_ip_ospf_neighbor.json index 67593952cae1..fccca693b92b 100644 --- a/tests/topotests/ldp_oc_acl_topo1/r4/show_ip_ospf_neighbor.json +++ b/tests/topotests/ldp_oc_acl_topo1/r4/show_ip_ospf_neighbor.json @@ -4,7 +4,7 @@ "2.2.2.2":[ { "priority":1, - "state":"Full\/DROther", + "converged":"Full", "address":"10.0.2.2", "ifaceName":"r4-eth0:10.0.2.4" } @@ -12,7 +12,7 @@ "3.3.3.3":[ { "priority":2, - "state":"Full\/Backup", + "converged":"Full", "address":"10.0.2.3", "ifaceName":"r4-eth0:10.0.2.4" } diff --git a/tests/topotests/ldp_oc_topo1/r1/show_ip_ospf_neighbor.json b/tests/topotests/ldp_oc_topo1/r1/show_ip_ospf_neighbor.json index aa3f74fc5f12..63281e9be33d 100644 --- a/tests/topotests/ldp_oc_topo1/r1/show_ip_ospf_neighbor.json +++ b/tests/topotests/ldp_oc_topo1/r1/show_ip_ospf_neighbor.json @@ -3,7 +3,7 @@ "2.2.2.2":[ { "priority":2, - "state":"Full\/DR", + "converged":"Full", "address":"10.0.1.2", "ifaceName":"r1-eth0:10.0.1.1" } diff --git a/tests/topotests/ldp_oc_topo1/r2/show_ip_ospf_neighbor.json b/tests/topotests/ldp_oc_topo1/r2/show_ip_ospf_neighbor.json index aa68198957b6..f361d605ce30 100644 --- a/tests/topotests/ldp_oc_topo1/r2/show_ip_ospf_neighbor.json +++ b/tests/topotests/ldp_oc_topo1/r2/show_ip_ospf_neighbor.json @@ -3,7 +3,7 @@ "1.1.1.1":[ { "priority":1, - "state":"Full\/Backup", + "converged":"Full", "address":"10.0.1.1", "ifaceName":"r2-eth0:10.0.1.2" } @@ -11,7 +11,7 @@ "3.3.3.3":[ { "priority":2, - "state":"Full\/Backup", + "converged":"Full", "address":"10.0.2.3", "ifaceName":"r2-eth1:10.0.2.2" } @@ -19,7 +19,7 @@ "4.4.4.4":[ { "priority":3, - "state":"Full\/DR", + "converged":"Full", "address":"10.0.2.4", "ifaceName":"r2-eth1:10.0.2.2" } diff --git a/tests/topotests/ldp_oc_topo1/r3/show_ip_ospf_neighbor.json b/tests/topotests/ldp_oc_topo1/r3/show_ip_ospf_neighbor.json index 905774fc466a..38794357ff5b 100644 --- a/tests/topotests/ldp_oc_topo1/r3/show_ip_ospf_neighbor.json +++ b/tests/topotests/ldp_oc_topo1/r3/show_ip_ospf_neighbor.json @@ -3,7 +3,7 @@ "2.2.2.2":[ { "priority":1, - "state":"Full\/DROther", + "converged":"Full", "address":"10.0.2.2", "ifaceName":"r3-eth0:10.0.2.3" } @@ -11,7 +11,7 @@ "4.4.4.4":[ { "priority":3, - "state":"Full\/DR", + "converged":"Full", "address":"10.0.2.4", "ifaceName":"r3-eth0:10.0.2.3" } diff --git a/tests/topotests/ldp_oc_topo1/r4/show_ip_ospf_neighbor.json b/tests/topotests/ldp_oc_topo1/r4/show_ip_ospf_neighbor.json index 67593952cae1..fccca693b92b 100644 --- a/tests/topotests/ldp_oc_topo1/r4/show_ip_ospf_neighbor.json +++ b/tests/topotests/ldp_oc_topo1/r4/show_ip_ospf_neighbor.json @@ -4,7 +4,7 @@ "2.2.2.2":[ { "priority":1, - "state":"Full\/DROther", + "converged":"Full", "address":"10.0.2.2", "ifaceName":"r4-eth0:10.0.2.4" } @@ -12,7 +12,7 @@ "3.3.3.3":[ { "priority":2, - "state":"Full\/Backup", + "converged":"Full", "address":"10.0.2.3", "ifaceName":"r4-eth0:10.0.2.4" } diff --git a/tests/topotests/ldp_sync_ospf_topo1/r1/show_ip_ospf_neighbor.json b/tests/topotests/ldp_sync_ospf_topo1/r1/show_ip_ospf_neighbor.json index 3bfda390714c..7efde22f3f3d 100644 --- a/tests/topotests/ldp_sync_ospf_topo1/r1/show_ip_ospf_neighbor.json +++ b/tests/topotests/ldp_sync_ospf_topo1/r1/show_ip_ospf_neighbor.json @@ -5,7 +5,7 @@ "dbSummaryCounter": 0, "retransmitCounter": 0, "priority": 1, - "state": "Full/DROther", + "converged": "Full", "address": "10.0.1.2", "ifaceName": "r1-eth1:10.0.1.1", "requestCounter": 0 @@ -16,7 +16,7 @@ "dbSummaryCounter": 0, "retransmitCounter": 0, "priority": 1, - "state": "Full/DROther", + "converged": "Full", "address": "10.0.2.3", "ifaceName": "r1-eth2:10.0.2.1", "requestCounter": 0 diff --git a/tests/topotests/ldp_sync_ospf_topo1/r2/show_ip_ospf_neighbor.json b/tests/topotests/ldp_sync_ospf_topo1/r2/show_ip_ospf_neighbor.json index 5b7a5ebbb998..5bea193e01a2 100644 --- a/tests/topotests/ldp_sync_ospf_topo1/r2/show_ip_ospf_neighbor.json +++ b/tests/topotests/ldp_sync_ospf_topo1/r2/show_ip_ospf_neighbor.json @@ -3,7 +3,7 @@ "1.1.1.1": [ { "priority":1, - "state":"Full/DROther", + "converged":"Full", "address":"10.0.1.1", "ifaceName":"r2-eth1:10.0.1.2", "retransmitCounter":0, @@ -14,7 +14,7 @@ "3.3.3.3": [ { "priority":1, - "state":"Full/DROther", + "converged":"Full", "address":"10.0.3.3", "ifaceName":"r2-eth2:10.0.3.2", "retransmitCounter":0, diff --git a/tests/topotests/ldp_sync_ospf_topo1/r3/show_ip_ospf_neighbor.json b/tests/topotests/ldp_sync_ospf_topo1/r3/show_ip_ospf_neighbor.json index 1b29b9f94788..9966297d8a71 100644 --- a/tests/topotests/ldp_sync_ospf_topo1/r3/show_ip_ospf_neighbor.json +++ b/tests/topotests/ldp_sync_ospf_topo1/r3/show_ip_ospf_neighbor.json @@ -3,7 +3,7 @@ "1.1.1.1": [ { "priority":1, - "state":"Full/DROther", + "converged":"Full", "address":"10.0.2.1", "ifaceName":"r3-eth1:10.0.2.3", "retransmitCounter":0, @@ -14,7 +14,7 @@ "2.2.2.2": [ { "priority":1, - "state":"Full/DROther", + "converged":"Full", "address":"10.0.3.2", "ifaceName":"r3-eth2:10.0.3.3", "retransmitCounter":0, diff --git a/tests/topotests/ldp_vpls_topo1/r1/show_ip_ospf_neighbor.json b/tests/topotests/ldp_vpls_topo1/r1/show_ip_ospf_neighbor.json index 7e281abb5fd4..90c8195416f1 100644 --- a/tests/topotests/ldp_vpls_topo1/r1/show_ip_ospf_neighbor.json +++ b/tests/topotests/ldp_vpls_topo1/r1/show_ip_ospf_neighbor.json @@ -5,7 +5,7 @@ "dbSummaryCounter": 0, "retransmitCounter": 0, "priority": 2, - "state": "Full\/DR", + "converged": "Full", "address": "10.0.1.2", "ifaceName": "r1-eth1:10.0.1.1", "requestCounter": 0 @@ -16,7 +16,7 @@ "dbSummaryCounter": 0, "retransmitCounter": 0, "priority": 2, - "state": "Full\/DR", + "converged": "Full", "address": "10.0.2.3", "ifaceName": "r1-eth2:10.0.2.1", "requestCounter": 0 diff --git a/tests/topotests/ldp_vpls_topo1/r2/show_ip_ospf_neighbor.json b/tests/topotests/ldp_vpls_topo1/r2/show_ip_ospf_neighbor.json index 22fd98f519c3..29dde53c6d7a 100644 --- a/tests/topotests/ldp_vpls_topo1/r2/show_ip_ospf_neighbor.json +++ b/tests/topotests/ldp_vpls_topo1/r2/show_ip_ospf_neighbor.json @@ -3,7 +3,7 @@ "1.1.1.1": [ { "priority":1, - "state":"Full\/Backup", + "converged":"Full", "address":"10.0.1.1", "ifaceName":"r2-eth1:10.0.1.2", "retransmitCounter":0, @@ -14,7 +14,7 @@ "3.3.3.3": [ { "priority":2, - "state":"Full\/DR", + "converged":"Full", "address":"10.0.3.3", "ifaceName":"r2-eth2:10.0.3.2", "retransmitCounter":0, diff --git a/tests/topotests/ldp_vpls_topo1/r3/show_ip_ospf_neighbor.json b/tests/topotests/ldp_vpls_topo1/r3/show_ip_ospf_neighbor.json index 970eb2fc1d72..9966297d8a71 100644 --- a/tests/topotests/ldp_vpls_topo1/r3/show_ip_ospf_neighbor.json +++ b/tests/topotests/ldp_vpls_topo1/r3/show_ip_ospf_neighbor.json @@ -3,7 +3,7 @@ "1.1.1.1": [ { "priority":1, - "state":"Full\/Backup", + "converged":"Full", "address":"10.0.2.1", "ifaceName":"r3-eth1:10.0.2.3", "retransmitCounter":0, @@ -14,7 +14,7 @@ "2.2.2.2": [ { "priority":1, - "state":"Full\/Backup", + "converged":"Full", "address":"10.0.3.2", "ifaceName":"r3-eth2:10.0.3.3", "retransmitCounter":0, diff --git a/tests/topotests/ospf_gr_topo1/rt1/show_ip_ospf_neighbor.json b/tests/topotests/ospf_gr_topo1/rt1/show_ip_ospf_neighbor.json index ed290323a421..f82758101c0b 100644 --- a/tests/topotests/ospf_gr_topo1/rt1/show_ip_ospf_neighbor.json +++ b/tests/topotests/ospf_gr_topo1/rt1/show_ip_ospf_neighbor.json @@ -2,7 +2,7 @@ "neighbors":{ "2.2.2.2":[ { - "state":"Full\/DROther", + "converged":"Full", "address":"10.0.1.2", "ifaceName":"eth-rt2:10.0.1.1" } diff --git a/tests/topotests/ospf_gr_topo1/rt2/show_ip_ospf_neighbor.json b/tests/topotests/ospf_gr_topo1/rt2/show_ip_ospf_neighbor.json index 4fe92b0b98cc..5a0b09270204 100644 --- a/tests/topotests/ospf_gr_topo1/rt2/show_ip_ospf_neighbor.json +++ b/tests/topotests/ospf_gr_topo1/rt2/show_ip_ospf_neighbor.json @@ -2,14 +2,14 @@ "neighbors":{ "1.1.1.1":[ { - "state":"Full\/DROther", + "converged":"Full", "address":"10.0.1.1", "ifaceName":"eth-rt1:10.0.1.2" } ], "3.3.3.3":[ { - "state":"Full\/DROther", + "converged":"Full", "address":"10.0.2.3", "ifaceName":"eth-rt3:10.0.2.2" } diff --git a/tests/topotests/ospf_gr_topo1/rt3/show_ip_ospf_neighbor.json b/tests/topotests/ospf_gr_topo1/rt3/show_ip_ospf_neighbor.json index e3c36ab9a35f..ab5e78414d1c 100644 --- a/tests/topotests/ospf_gr_topo1/rt3/show_ip_ospf_neighbor.json +++ b/tests/topotests/ospf_gr_topo1/rt3/show_ip_ospf_neighbor.json @@ -2,21 +2,21 @@ "neighbors":{ "2.2.2.2":[ { - "state":"Full\/DROther", + "converged":"Full", "address":"10.0.2.2", "ifaceName":"eth-rt2:10.0.2.3" } ], "4.4.4.4":[ { - "state":"Full\/DROther", + "converged":"Full", "address":"10.0.3.4", "ifaceName":"eth-rt4:10.0.3.3" } ], "6.6.6.6":[ { - "state":"Full\/DROther", + "converged":"Full", "address":"10.0.4.6", "ifaceName":"eth-rt6:10.0.4.3" } diff --git a/tests/topotests/ospf_gr_topo1/rt4/show_ip_ospf_neighbor.json b/tests/topotests/ospf_gr_topo1/rt4/show_ip_ospf_neighbor.json index 2123ecb8da89..405679c10e98 100644 --- a/tests/topotests/ospf_gr_topo1/rt4/show_ip_ospf_neighbor.json +++ b/tests/topotests/ospf_gr_topo1/rt4/show_ip_ospf_neighbor.json @@ -2,14 +2,14 @@ "neighbors":{ "3.3.3.3":[ { - "state":"Full\/DROther", + "converged":"Full", "address":"10.0.3.3", "ifaceName":"eth-rt3:10.0.3.4" } ], "5.5.5.5":[ { - "state":"Full\/DROther", + "converged":"Full", "address":"10.0.5.5", "ifaceName":"eth-rt5:10.0.5.4" } diff --git a/tests/topotests/ospf_gr_topo1/rt5/show_ip_ospf_neighbor.json b/tests/topotests/ospf_gr_topo1/rt5/show_ip_ospf_neighbor.json index 6440b6769875..893d45436853 100644 --- a/tests/topotests/ospf_gr_topo1/rt5/show_ip_ospf_neighbor.json +++ b/tests/topotests/ospf_gr_topo1/rt5/show_ip_ospf_neighbor.json @@ -2,7 +2,7 @@ "neighbors":{ "4.4.4.4":[ { - "state":"Full\/DROther", + "converged":"Full", "address":"10.0.5.4", "ifaceName":"eth-rt4:10.0.5.5" } diff --git a/tests/topotests/ospf_gr_topo1/rt6/show_ip_ospf_neighbor.json b/tests/topotests/ospf_gr_topo1/rt6/show_ip_ospf_neighbor.json index d815c2392799..564a513ac6e9 100644 --- a/tests/topotests/ospf_gr_topo1/rt6/show_ip_ospf_neighbor.json +++ b/tests/topotests/ospf_gr_topo1/rt6/show_ip_ospf_neighbor.json @@ -2,14 +2,14 @@ "neighbors":{ "3.3.3.3":[ { - "state":"Full\/DROther", + "converged":"Full", "address":"10.0.4.3", "ifaceName":"eth-rt3:10.0.4.6" } ], "7.7.7.7":[ { - "state":"Full\/DROther", + "converged":"Full", "address":"10.0.6.7", "ifaceName":"eth-rt7:10.0.6.6" } diff --git a/tests/topotests/ospf_gr_topo1/rt7/show_ip_ospf_neighbor.json b/tests/topotests/ospf_gr_topo1/rt7/show_ip_ospf_neighbor.json index 2254aea9a68d..bc6b60697c70 100644 --- a/tests/topotests/ospf_gr_topo1/rt7/show_ip_ospf_neighbor.json +++ b/tests/topotests/ospf_gr_topo1/rt7/show_ip_ospf_neighbor.json @@ -2,7 +2,7 @@ "neighbors":{ "6.6.6.6":[ { - "state":"Full\/DROther", + "converged":"Full", "address":"10.0.6.6", "ifaceName":"eth-rt6:10.0.6.7" } diff --git a/tests/topotests/ospf_topo1/test_ospf_topo1.py b/tests/topotests/ospf_topo1/test_ospf_topo1.py index d84c41bea32a..710895cc6bab 100644 --- a/tests/topotests/ospf_topo1/test_ospf_topo1.py +++ b/tests/topotests/ospf_topo1/test_ospf_topo1.py @@ -135,7 +135,7 @@ def run_command_and_expect(): ) if ( topotest.json_cmp( - result, {"neighbors": {neighbor: [{"state": "Full/DR"}]}} + result, {"neighbors": {neighbor: [{"converged": "Full"}]}} ) is None ): @@ -143,14 +143,14 @@ def run_command_and_expect(): if ( topotest.json_cmp( - result, {"neighbors": {neighbor: [{"state": "Full/DROther"}]}} + result, {"neighbors": {neighbor: [{"converged": "Full"}]}} ) is None ): return None return topotest.json_cmp( - result, {"neighbors": {neighbor: [{"state": "Full/Backup"}]}} + result, {"neighbors": {neighbor: [{"converged": "Full"}]}} ) _, result = topotest.run_and_expect( diff --git a/tests/topotests/pim_acl/r1/ospf_neighbor.json b/tests/topotests/pim_acl/r1/ospf_neighbor.json index a8fc093e90dd..af83d6bea373 100644 --- a/tests/topotests/pim_acl/r1/ospf_neighbor.json +++ b/tests/topotests/pim_acl/r1/ospf_neighbor.json @@ -3,7 +3,7 @@ "192.168.0.11":[ { "priority":10, - "state":"Full\/Backup", + "converged":"Full", "address":"192.168.101.11", "ifaceName":"r1-eth1:192.168.101.1", "retransmitCounter":0, @@ -14,7 +14,7 @@ "192.168.0.12":[ { "priority":0, - "state":"Full\/DROther", + "converged":"Full", "address":"192.168.101.12", "ifaceName":"r1-eth1:192.168.101.1", "retransmitCounter":0, @@ -25,7 +25,7 @@ "192.168.0.13":[ { "priority":0, - "state":"Full\/DROther", + "converged":"Full", "address":"192.168.101.13", "ifaceName":"r1-eth1:192.168.101.1", "retransmitCounter":0, @@ -36,7 +36,7 @@ "192.168.0.14":[ { "priority":0, - "state":"Full\/DROther", + "converged":"Full", "address":"192.168.101.14", "ifaceName":"r1-eth1:192.168.101.1", "retransmitCounter":0, @@ -47,7 +47,7 @@ "192.168.0.15":[ { "priority":0, - "state":"Full\/DROther", + "converged":"Full", "address":"192.168.101.15", "ifaceName":"r1-eth1:192.168.101.1", "retransmitCounter":0, diff --git a/tests/topotests/pim_igmp_vrf/r1/ospf_blue_neighbor.json b/tests/topotests/pim_igmp_vrf/r1/ospf_blue_neighbor.json index 604d25fac141..1e70fcc36e37 100644 --- a/tests/topotests/pim_igmp_vrf/r1/ospf_blue_neighbor.json +++ b/tests/topotests/pim_igmp_vrf/r1/ospf_blue_neighbor.json @@ -5,7 +5,7 @@ "192.168.0.11":[ { "priority":10, - "state":"Full\/Backup", + "converged":"Full", "address":"192.168.101.11", "ifaceName":"r1-eth1:192.168.101.1" } diff --git a/tests/topotests/pim_igmp_vrf/r1/ospf_red_neighbor.json b/tests/topotests/pim_igmp_vrf/r1/ospf_red_neighbor.json index 456bb8752056..7f2ab248cc1d 100644 --- a/tests/topotests/pim_igmp_vrf/r1/ospf_red_neighbor.json +++ b/tests/topotests/pim_igmp_vrf/r1/ospf_red_neighbor.json @@ -5,7 +5,7 @@ "192.168.0.12":[ { "priority":10, - "state":"Full\/Backup", + "converged":"Full", "address":"192.168.101.12", "ifaceName":"r1-eth3:192.168.101.1" } From f786c3ee29c415fdd2ee014c1dd0c40636acbd6a Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 13 Oct 2021 14:12:51 -0400 Subject: [PATCH 136/188] tests: BFD timing tests under system load need more leeway We have this pattern in this test: # Let's kill the interface on rt2 and see what happens with the RIB and BFD on rt1 tgen.gears["rt2"].link_enable("eth-rt1", enabled=False) # By default BFD provides a recovery time of 900ms plus jitter, so let's wait # initial 2 seconds to let the CI not suffer. topotest.sleep(2, 'Wait for BFD down notification') router_compare_json_output( "rt1", "show ip route ospf json", "step3/show_ip_route_rt2_down.ref", 1, 0 ) Under a heavy CI load, interface down events and then reacting to them may not actually happen within 2 seconds. Allow some more grace time in the test to ensure that we react to it in an appropriate manner. Signed-off-by: Donald Sharp --- tests/topotests/bfd_ospf_topo1/test_bfd_ospf_topo1.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/topotests/bfd_ospf_topo1/test_bfd_ospf_topo1.py b/tests/topotests/bfd_ospf_topo1/test_bfd_ospf_topo1.py index bef2c3f162bb..f35c20e16c20 100755 --- a/tests/topotests/bfd_ospf_topo1/test_bfd_ospf_topo1.py +++ b/tests/topotests/bfd_ospf_topo1/test_bfd_ospf_topo1.py @@ -198,7 +198,7 @@ def test_bfd_ospf_interface_failure_rt2_step3(): topotest.sleep(2, 'Wait for BFD down notification') router_compare_json_output( - "rt1", "show ip route ospf json", "step3/show_ip_route_rt2_down.ref", 1, 0 + "rt1", "show ip route ospf json", "step3/show_ip_route_rt2_down.ref", 10, 2 ) router_compare_json_output( "rt1", "show ipv6 route ospf json", "step3/show_ipv6_route_rt2_down.ref", 1, 0 @@ -236,7 +236,7 @@ def test_bfd_ospf_interface_failure_rt3_step3(): # initial 2 seconds to let the CI not suffer. topotest.sleep(2, 'Wait for BFD down notification') router_compare_json_output( - "rt1", "show ip route ospf json", "step3/show_ip_route_rt3_down.ref", 1, 0 + "rt1", "show ip route ospf json", "step3/show_ip_route_rt3_down.ref", 10, 2 ) router_compare_json_output( "rt1", "show ipv6 route ospf json", "step3/show_ipv6_route_rt3_down.ref", 1, 0 From 2beaba8de9630b3bff2abdf1381295667d051302 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 13 Oct 2021 14:32:52 -0400 Subject: [PATCH 137/188] isisd: Convert signed to time_t for addition Convert a signed value to a time_t before addition so that we can compare unsigned (time_t) to unsigned. Signed-off-by: Donald Sharp --- isisd/isis_snmp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/isisd/isis_snmp.c b/isisd/isis_snmp.c index c530eb916906..1b78dc0be6a1 100644 --- a/isisd/isis_snmp.c +++ b/isisd/isis_snmp.c @@ -2571,7 +2571,7 @@ static uint8_t *isis_snmp_find_isadj(struct variable *v, oid *name, */ if (adj->last_upd != 0) { val = time(NULL); - if (val < (adj->last_upd + adj->hold_time)) + if (val < ((time_t)adj->last_upd + (time_t)adj->hold_time)) return SNMP_INTEGER(adj->last_upd + adj->hold_time - val); } From 2db57f563987d7b1f3fda58974f15e33a62b1b83 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 13 Oct 2021 14:34:08 -0400 Subject: [PATCH 138/188] babeld: Prevent compiler warning about uninited value for n the variable n, when used must have been set via the find_route_slot but the compiler in question is probably getting confused with the multiple levels of indention. Just get around the whole problem by setting n = 0 and being done with it. Signed-off-by: Donald Sharp --- babeld/route.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/babeld/route.c b/babeld/route.c index dfd0bfab8994..8dd1e4043123 100644 --- a/babeld/route.c +++ b/babeld/route.c @@ -166,7 +166,7 @@ resize_route_table(int new_slots) static struct babel_route * insert_route(struct babel_route *route) { - int i, n; + int i, n = 0; assert(!route->installed); From 5393f4db3fc4af608faf2ccc1277fbe79fe42609 Mon Sep 17 00:00:00 2001 From: Igor Ryzhov Date: Wed, 13 Oct 2021 23:23:41 +0300 Subject: [PATCH 139/188] lib: optimize if_lookup_by_name_all_vrf We already have a VRF pointer, no need to search for it again. Signed-off-by: Igor Ryzhov --- lib/if.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/if.c b/lib/if.c index 424880ff425a..ef73ab2525ff 100644 --- a/lib/if.c +++ b/lib/if.c @@ -440,7 +440,7 @@ struct interface *if_lookup_by_name_all_vrf(const char *name) return NULL; RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) { - ifp = if_lookup_by_name(name, vrf->vrf_id); + ifp = if_lookup_by_name_vrf(name, vrf); if (ifp) return ifp; } From 9a0e62d41e2fd3b5aa9e2e3b5830c58fd7589449 Mon Sep 17 00:00:00 2001 From: Igor Ryzhov Date: Thu, 14 Oct 2021 19:45:43 +0300 Subject: [PATCH 140/188] pbrd: protect from a possible NULL dereference Signed-off-by: Igor Ryzhov --- pbrd/pbr_vty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pbrd/pbr_vty.c b/pbrd/pbr_vty.c index d083b9d2b0f4..9436f4430b5b 100644 --- a/pbrd/pbr_vty.c +++ b/pbrd/pbr_vty.c @@ -499,7 +499,7 @@ DEFPY(pbr_map_nexthop, pbr_map_nexthop_cmd, actual = vrf_lookup_by_id(ifp->vrf_id); vty_out(vty, "Specified Intf %s is not in vrf %s but is in vrf %s, using actual vrf\n", - ifp->name, vrf->name, actual->name); + ifp->name, vrf->name, VRF_LOGNAME(actual)); } nhop.ifindex = ifp->ifindex; nhop.vrf_id = ifp->vrf_id; From 33f4519d2c3c651a32743722e247d5c83b33ba68 Mon Sep 17 00:00:00 2001 From: Igor Ryzhov Date: Thu, 14 Oct 2021 19:47:02 +0300 Subject: [PATCH 141/188] ospf6d: remove no-op ospf6_route_create already sets route->ospf6. Signed-off-by: Igor Ryzhov --- ospf6d/ospf6_asbr.c | 1 - 1 file changed, 1 deletion(-) diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c index cd2791fc48cc..1eb53411c119 100644 --- a/ospf6d/ospf6_asbr.c +++ b/ospf6d/ospf6_asbr.c @@ -1522,7 +1522,6 @@ void ospf6_asbr_redistribute_add(int type, ifindex_t ifindex, route = ospf6_route_create(ospf6); route->type = OSPF6_DEST_TYPE_NETWORK; prefix_copy(&route->prefix, prefix); - route->ospf6 = ospf6; info = (struct ospf6_external_info *)XCALLOC( MTYPE_OSPF6_EXTERNAL_INFO, sizeof(struct ospf6_external_info)); From 936c12d71b817e7384625afa44479b2d87f07219 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Thu, 14 Oct 2021 19:02:03 +0200 Subject: [PATCH 142/188] doc/developer: fix C struct references Sphinx wants `c:struct:: foo` rather than `c:type:: struct foo`. Signed-off-by: David Lamparter --- doc/developer/link-state.rst | 19 ++++++++++--------- doc/developer/logging.rst | 6 +++--- doc/developer/memtypes.rst | 2 +- doc/developer/rcu.rst | 8 ++++---- 4 files changed, 18 insertions(+), 17 deletions(-) diff --git a/doc/developer/link-state.rst b/doc/developer/link-state.rst index 1cbaf27ffeb0..2072595e36da 100644 --- a/doc/developer/link-state.rst +++ b/doc/developer/link-state.rst @@ -53,15 +53,15 @@ Data structures 3 types of Link State structure have been defined: -.. c:type:: struct ls_node +.. c:struct:: ls_node that groups all information related to a node -.. c:type:: struct ls_attributes +.. c:struct:: ls_attributes that groups all information related to a link -.. c:type:: struct ls_prefix +.. c:struct:: ls_prefix that groups all information related to a prefix @@ -73,7 +73,7 @@ identifier which advertises the Link State and a bit mask as flags to indicates which parameters are valid i.e. for which the value is valid and corresponds to a Link State information conveyed by the routing protocol. -.. c:type:: struct ls_node_id +.. c:struct:: ls_node_id defines the Node identifier as router ID IPv4 address plus the area ID for OSPF or the ISO System ID plus the IS-IS level for IS-IS. @@ -159,10 +159,11 @@ A unique Key is used to identify both Vertices and Edges within the Graph. 4 data structures have been defined to implement the Graph model: -.. c:type:: struct ls_vertex -.. c:type:: struct ls_edge -.. c:type:: struct ls_prefix -.. c:type:: struct ls_ted +.. c:struct:: ls_vertex +.. c:struct:: ls_edge +.. c:struct:: ls_ted + + - :c:struct:`ls_prefix` TED stores Vertex, Edge and Subnet elements with a RB Tree structure. The Vertex key corresponds to the Router ID for OSPF and ISO System ID for @@ -412,7 +413,7 @@ Data Structures The Link State Message is defined to convey Link State parameters from the routing protocol (OSPF or IS-IS) to other daemons e.g. BGP. -.. c:type:: struct ls_message +.. c:struct:: ls_message The structure is composed of: diff --git a/doc/developer/logging.rst b/doc/developer/logging.rst index 681fc1173c54..eaf8625efac9 100644 --- a/doc/developer/logging.rst +++ b/doc/developer/logging.rst @@ -489,7 +489,7 @@ calls to :c:func:`zlog_tls_buffer_flush()` in appropriate places: buffer. This function is safe to call regardless of the per-thread log buffer being set up / in use or not. -When working with threads that do not use the :c:type:`struct thread_master` +When working with threads that do not use the :c:struct:`thread_master` event loop, per-thread buffers can be managed with: .. c:function:: void zlog_tls_buffer_init(void) @@ -531,7 +531,7 @@ that they use. Basic internals ^^^^^^^^^^^^^^^ -.. c:type:: struct zlog_target +.. c:struct:: zlog_target This struct needs to be filled in by any log target and then passed to :c:func:`zlog_target_replace()`. After it has been registered, @@ -570,7 +570,7 @@ Basic internals Allocates a logging target struct. Note that the ``oldzt`` argument may be ``NULL`` to allocate a "from scratch". If ``oldzt`` is not ``NULL``, the - generic bits in :c:type:`struct zlog_target` are copied. **Target specific + generic bits in :c:struct:`zlog_target` are copied. **Target specific bits are not copied.** .. c:function:: struct zlog_target *zlog_target_replace(struct zlog_target *oldzt, struct zlog_target *newzt) diff --git a/doc/developer/memtypes.rst b/doc/developer/memtypes.rst index 08dad7fb6804..2e181c4f2bd6 100644 --- a/doc/developer/memtypes.rst +++ b/doc/developer/memtypes.rst @@ -42,7 +42,7 @@ Example: Definition ---------- -.. c:type:: struct memtype +.. c:struct:: memtype This is the (internal) type used for MTYPE definitions. The macros below should be used to create these, but in some cases it is useful to pass a diff --git a/doc/developer/rcu.rst b/doc/developer/rcu.rst index c2ddf93f5388..c8248194b7cc 100644 --- a/doc/developer/rcu.rst +++ b/doc/developer/rcu.rst @@ -133,9 +133,9 @@ atomic ops & datastructures with other types of locking, e.g. rwlocks. become invalid, as another thread may have called :c:func:`rcu_free` on them. -.. c:type:: struct rcu_head -.. c:type:: struct rcu_head_close -.. c:type:: struct rcu_action +.. c:struct:: rcu_head +.. c:struct:: rcu_head_close +.. c:struct:: rcu_action The ``rcu_head`` structures are small (16-byte) bits that contain the queueing machinery for the RCU sweeper/cleanup mechanisms. @@ -209,7 +209,7 @@ atomic ops & datastructures with other types of locking, e.g. rwlocks. Internals ^^^^^^^^^ -.. c:type:: struct rcu_thread +.. c:struct:: rcu_thread Per-thread state maintained by the RCU code, set up by the following functions. A pointer to a thread's own ``rcu_thread`` is saved in From e8713b62d1f09326a94f51b150cb6a63fbcfa2a3 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Thu, 14 Oct 2021 19:11:02 +0200 Subject: [PATCH 143/188] doc/developer: fix warnings in topotests doc Sphinx warns about a few nits here, just fix. (Note :option:`-E` can't be used without a "option:: -E" definition, it's intended as a cross reference.) Signed-off-by: David Lamparter --- doc/developer/conf.py | 1 + doc/developer/topotests.rst | 11 +++++------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/developer/conf.py b/doc/developer/conf.py index 8f282c079092..61df6e0e604f 100644 --- a/doc/developer/conf.py +++ b/doc/developer/conf.py @@ -138,6 +138,7 @@ "_build", "building-libyang.rst", "topotests-snippets.rst", + "topotests-markers.rst", "include-compile.rst", ] diff --git a/doc/developer/topotests.rst b/doc/developer/topotests.rst index b4f6ec521c06..d8b3650944b5 100644 --- a/doc/developer/topotests.rst +++ b/doc/developer/topotests.rst @@ -137,14 +137,14 @@ Topotests must be run as root. Normally this will be accomplished through the use of the ``sudo`` command. In order for topotests to be able to open new windows (either XTerm or byobu/screen/tmux windows) certain environment variables must be passed through the sudo command. One way to do this is to -specify the :option:`-E` flag to ``sudo``. This will carry over most if not all +specify the ``-E`` flag to ``sudo``. This will carry over most if not all your environment variables include ``PATH``. For example: .. code:: shell sudo -E python3 -m pytest -s -v -If you do not wish to use :option:`-E` (e.g., to avoid ``sudo`` inheriting +If you do not wish to use ``-E`` (e.g., to avoid ``sudo`` inheriting ``PATH``) you can modify your `/etc/sudoers` config file to specifically pass the environment variables required by topotests. Add the following commands to your ``/etc/sudoers`` config file. @@ -197,7 +197,7 @@ the run. Here we see that 4 tests have failed. We an dig deeper by displaying the captured logs and errors. First let's redisplay the results enumerated by adding -the :option:`-E` flag +the ``-E`` flag .. code:: shell @@ -385,7 +385,7 @@ to launch the given programs. NOTE: you must run the topotest (pytest) such that your DISPLAY, STY or TMUX environment variables are carried over. You can do this by passing the -:option:`-E` flag to ``sudo`` or you can modify your ``/etc/sudoers`` config to +``-E`` flag to ``sudo`` or you can modify your ``/etc/sudoers`` config to automatically pass that environment variable through to the ``sudo`` environment. @@ -903,6 +903,7 @@ Interface), from here you can call your router ``vtysh`` or even bash. Here's the help text: .. code:: shell + unet> help Commands: @@ -912,8 +913,6 @@ Here's the help text: vtysh [hosts] :: open vtysh terminals for hosts [hosts] :: execute vtysh-command on hosts -.. code:: shell - Here are some commands example: .. code:: shell From 8c69c8f743806f48ec5e21ec2bdafbe4fbb724e6 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Thu, 14 Oct 2021 19:17:30 +0200 Subject: [PATCH 144/188] doc/developer: use :c:macro: where appropriate Sphinx tries to parse :c:function: as function prototype, which doesn't quite work with macros. Signed-off-by: David Lamparter --- doc/developer/lists.rst | 16 ++++++++-------- doc/developer/locking.rst | 8 ++++++-- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/doc/developer/lists.rst b/doc/developer/lists.rst index 553bd1f596a8..ea7ca02bda1a 100644 --- a/doc/developer/lists.rst +++ b/doc/developer/lists.rst @@ -182,7 +182,7 @@ Common iteration macros The following iteration macros work across all data structures: -.. c:function:: frr_each(Z, &head, item) +.. c:macro:: frr_each(Z, head, item) Equivalent to: @@ -193,7 +193,7 @@ The following iteration macros work across all data structures: Note that this will fail if the list is modified while being iterated over. -.. c:function:: frr_each_safe(Z, &head, item) +.. c:macro:: frr_each_safe(Z, head, item) Same as the previous, but the next element is pre-loaded into a "hidden" variable (named ``Z_safe``.) Equivalent to: @@ -212,7 +212,7 @@ The following iteration macros work across all data structures: tables is resized while iterating. This will cause items to be skipped or iterated over twice. -.. c:function:: frr_each_from(Z, &head, item, from) +.. c:macro:: frr_each_from(Z, head, item, from) Iterates over the list, starting at item ``from``. This variant is "safe" as in the previous macro. Equivalent to: @@ -346,7 +346,7 @@ are several functions exposed to insert data: ``item`` must not be ``NULL`` for any of the following functions. -.. c:function:: DECLARE_XXX(Z, type, field) +.. c:macro:: DECLARE_XXX(Z, type, field) :param listtype XXX: ``LIST``, ``DLIST`` or ``ATOMLIST`` to select a data structure implementation. @@ -403,7 +403,7 @@ Sorted data structures do not need to have an insertion position specified, therefore the insertion calls are different from unsorted lists. Also, sorted lists can be searched for a value. -.. c:function:: DECLARE_XXX_UNIQ(Z, type, field, compare_func) +.. c:macro:: DECLARE_XXX_UNIQ(Z, type, field, compare_func) :param listtype XXX: One of the following: ``SORTLIST`` (single-linked sorted list), ``SKIPLIST`` (skiplist), @@ -423,7 +423,7 @@ sorted lists can be searched for a value. ``int function(const itemtype *, const itemtype*)``. This function may be static if the list is only used in one file. -.. c:function:: DECLARE_XXX_NONUNIQ(Z, type, field, compare_func) +.. c:macro:: DECLARE_XXX_NONUNIQ(Z, type, field, compare_func) Same as above, but allow adding multiple items to the list that compare as equal in ``compare_func``. Ordering between these items is undefined @@ -477,9 +477,9 @@ sorted lists can be searched for a value. API for hash tables ------------------- -.. c:function:: DECLARE_XXX(Z, type, field, compare_func, hash_func) +.. c:macro:: DECLARE_HASH(Z, type, field, compare_func, hash_func) - :param listtype XXX: Only ``HASH`` is currently available. + :param listtype HASH: Only ``HASH`` is currently available. :param token Z: Gives the name prefix that is used for the functions created for this instantiation. ``DECLARE_XXX(foo, ...)`` gives ``struct foo_item``, ``foo_add()``, ``foo_count()``, etc. Note diff --git a/doc/developer/locking.rst b/doc/developer/locking.rst index d698789f9f1e..c8366480d2a7 100644 --- a/doc/developer/locking.rst +++ b/doc/developer/locking.rst @@ -7,7 +7,9 @@ FRR ships two small wrappers around ``pthread_mutex_lock()`` / ``pthread_mutex_unlock``. Use ``#include "frr_pthread.h"`` to get these macros. -.. c:function:: frr_with_mutex(pthread_mutex_t *mutex) +.. c:macro:: frr_with_mutex(mutex) + + (With ``pthread_mutex_t *mutex``.) Begin a C statement block that is executed with the mutex locked. Any exit from the block (``break``, ``return``, ``goto``, end of block) will @@ -43,7 +45,9 @@ macros. statement works correctly, FRR coding style requires that this macro always be used with a ``{ ... }`` block. -.. c:function:: frr_mutex_lock_autounlock(pthread_mutex_t *mutex) +.. c:macro:: frr_mutex_lock_autounlock(mutex) + + (With ``pthread_mutex_t *mutex``.) Lock mutex and unlock at the end of the current C statement block:: From 4c0e52367af58878ee777d251b3fb6990861532b Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Thu, 14 Oct 2021 19:19:23 +0200 Subject: [PATCH 145/188] doc/developer: fix duplicate const prototypes The const ones have const in the name. Signed-off-by: David Lamparter --- doc/developer/lists.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/developer/lists.rst b/doc/developer/lists.rst index ea7ca02bda1a..718e404764e0 100644 --- a/doc/developer/lists.rst +++ b/doc/developer/lists.rst @@ -297,7 +297,7 @@ The following documentation assumes that a list has been defined using affected by the "modification while iterating" problem. To remove all items from a hash table, use the loop demonstrated above. -.. c:function:: const itemtype *Z_next(const struct Z_head *, const itemtype *prev) +.. c:function:: const itemtype *Z_const_next(const struct Z_head *, const itemtype *prev) .. c:function:: itemtype *Z_next(struct Z_head *, itemtype *prev) Return the item that follows after ``prev``, or ``NULL`` if ``prev`` is @@ -439,7 +439,7 @@ sorted lists can be searched for a value. For ``_NONUNIQ`` lists, this function always returns NULL since ``item`` can always be successfully added to the list. -.. c:function:: const itemtype *Z_find(const struct Z_head *, const itemtype *ref) +.. c:function:: const itemtype *Z_const_find(const struct Z_head *, const itemtype *ref) .. c:function:: itemtype *Z_find(struct Z_head *, const itemtype *ref) Search the list for an item that compares equal to ``ref``. If no equal @@ -461,13 +461,13 @@ sorted lists can be searched for a value. containing non-unique items, more than one item may compare as equal to the item that is searched for. -.. c:function:: const itemtype *Z_find_gteq(const struct Z_head *, const itemtype *ref) +.. c:function:: const itemtype *Z_const_find_gteq(const struct Z_head *, const itemtype *ref) .. c:function:: itemtype *Z_find_gteq(struct Z_head *, const itemtype *ref) Search the list for an item that compares greater or equal to ``ref``. See :c:func:`Z_find()` above. -.. c:function:: const itemtype *Z_find_lt(const struct Z_head *, const itemtype *ref) +.. c:function:: const itemtype *Z_const_find_lt(const struct Z_head *, const itemtype *ref) .. c:function:: itemtype *Z_find_lt(struct Z_head *, const itemtype *ref) Search the list for an item that compares less than From 45cfb2495f2fade4ab903b240bafb0b853549069 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 15 Oct 2021 11:42:06 -0400 Subject: [PATCH 146/188] lib: Add `metric-type` to possible set operations Several tests used the route_map_create functionality with `metric-type` but never bothered to add the backend code to ensure it works correctly. Add it in so it can be used. Signed-off-by: Donald Sharp --- tests/topotests/lib/common_config.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/topotests/lib/common_config.py b/tests/topotests/lib/common_config.py index 1bce3c6bb2bb..cf8efdea169e 100644 --- a/tests/topotests/lib/common_config.py +++ b/tests/topotests/lib/common_config.py @@ -2552,6 +2552,7 @@ def create_route_maps(tgen, input_dict, build=False): nexthop = set_data.setdefault("nexthop", None) origin = set_data.setdefault("origin", None) ext_comm_list = set_data.setdefault("extcommunity", {}) + metrictype = set_data.setdefault("metric-type", {}) # Local Preference if local_preference: @@ -2559,6 +2560,10 @@ def create_route_maps(tgen, input_dict, build=False): "set local-preference {}".format(local_preference) ) + # Metric-Type + if metrictype: + rmap_data.append("set metric-type {}\n".format(metrictype)) + # Metric if metric: rmap_data.append("set metric {} \n".format(metric)) From 6862166ed513f16e1f6cb59d604a08b03d7a87f5 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 15 Oct 2021 11:43:44 -0400 Subject: [PATCH 147/188] tests: Fix ospf_asbr_summary_topo1.py This script is failing occassionally in our upstream topotests. Where it was changing route-maps and attempting to see if summarization was working correctly. The problem was that the code appeared to be attempting to add route-maps to redistribution in ospf then modifying the route-maps behavior to affect summarization as well as the metric type of that summarization. The problem is of course that ospf does not appear to modify the summary routes metric-type when the components of that summary change it's metric-type. So the test is testing nothing. In addition the test had messed up the usage of the route-map generation code and all the generated config was in different sequence numbers but route-map processing would never get to those new sequence numbers because of how route-maps are processed. Let's just remove this part of the test instead of trying to unwind it into anything meaningfull Signed-off-by: Donald Sharp --- .../test_ospf_asbr_summary_topo1.py | 83 ------------------- 1 file changed, 83 deletions(-) diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_asbr_summary_topo1.py b/tests/topotests/ospf_basic_functionality/test_ospf_asbr_summary_topo1.py index 64dfa0c69d18..f9fa55e27501 100644 --- a/tests/topotests/ospf_basic_functionality/test_ospf_asbr_summary_topo1.py +++ b/tests/topotests/ospf_basic_functionality/test_ospf_asbr_summary_topo1.py @@ -669,89 +669,6 @@ def test_ospf_type5_summary_tc48_p0(request): result is True ), "Testcase {} : Failed" "Error: Summary missing in OSPF DB".format(tc_name) - step("Configure metric type as 1 in route map.") - - routemaps = { - "r0": { - "route_maps": { - "rmap_ipv4": [{"action": "permit", "set": {"metric-type": "type-1"}}] - } - } - } - result = create_route_maps(tgen, routemaps) - assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) - - step( - "Verify that external routes(static / connected) are summarised" - " to configured summary address with metric type 2." - ) - input_dict = { - SUMMARY["ipv4"][0]: { - "Summary address": SUMMARY["ipv4"][0], - "Metric-type": "E2", - "Metric": 20, - "Tag": 0, - "External route count": 5, - } - } - dut = "r0" - result = verify_ospf_summary(tgen, topo, dut, input_dict) - assert ( - result is True - ), "Testcase {} : Failed" "Error: Summary missing in OSPF DB".format(tc_name) - - step("Un configure metric type from route map.") - - routemaps = { - "r0": { - "route_maps": { - "rmap_ipv4": [ - { - "action": "permit", - "set": {"metric-type": "type-1"}, - "delete": True, - } - ] - } - } - } - result = create_route_maps(tgen, routemaps) - assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) - - step( - "Verify that external routes(static / connected) are summarised" - " to configured summary address with metric type 2." - ) - input_dict = { - SUMMARY["ipv4"][0]: { - "Summary address": SUMMARY["ipv4"][0], - "Metric-type": "E2", - "Metric": 20, - "Tag": 0, - "External route count": 5, - } - } - dut = "r0" - result = verify_ospf_summary(tgen, topo, dut, input_dict) - assert ( - result is True - ), "Testcase {} : Failed" "Error: Summary missing in OSPF DB".format(tc_name) - - step("Change rule from permit to deny in prefix list.") - pfx_list = { - "r0": { - "prefix_lists": { - "ipv4": { - "pf_list_1_ipv4": [ - {"seqid": 10, "network": "any", "action": "deny"} - ] - } - } - } - } - result = create_prefix_lists(tgen, pfx_list) - assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) - write_test_footer(tc_name) From a383bfc7c9d12ed2a9eca4a276193455099e9fb3 Mon Sep 17 00:00:00 2001 From: Anuradha Karuppiah Date: Mon, 4 Oct 2021 09:41:43 -0700 Subject: [PATCH 148/188] bgpd: lttng tracepoint for local events received from zebra TPs - ===== root@ibm-2410a1-01:mgmt:~# lttng list --userspace |grep frr_bgp:evpn.*recv frr_bgp:evpn_local_l3vni_del_zrecv (loglevel: TRACE_INFO (6)) (type: tracepoint) frr_bgp:evpn_local_l3vni_add_zrecv (loglevel: TRACE_INFO (6)) (type: tracepoint) frr_bgp:evpn_local_macip_del_zrecv (loglevel: TRACE_INFO (6)) (type: tracepoint) frr_bgp:evpn_local_macip_add_zrecv (loglevel: TRACE_INFO (6)) (type: tracepoint) frr_bgp:evpn_local_vni_del_zrecv (loglevel: TRACE_INFO (6)) (type: tracepoint) frr_bgp:evpn_local_vni_add_zrecv (loglevel: TRACE_INFO (6)) (type: tracepoint) frr_bgp:evpn_mh_local_es_evi_del_zrecv (loglevel: TRACE_INFO (6)) (type: tracepoint) frr_bgp:evpn_mh_local_es_evi_add_zrecv (loglevel: TRACE_INFO (6)) (type: tracepoint) frr_bgp:evpn_mh_local_es_del_zrecv (loglevel: TRACE_INFO (6)) (type: tracepoint) frr_bgp:evpn_mh_local_es_add_zrecv (loglevel: TRACE_INFO (6)) (type: tracepoint) root@ibm-2410a1-01:mgmt:~# Sample output - =============== 1. ES frr_bgp:evpn_mh_local_es_add_zrecv {'esi': '03:44:38:39:ff:ff:01:00:00:01', 'vtep': '27.0.0.15', 'active': 0, 'bypass': 0, 'df_pref': 50000} frr_bgp:evpn_mh_local_es_del_zrecv {'esi': '03:44:38:39:ff:ff:01:00:00:01'} 2. ES-EVI frr_bgp:evpn_mh_local_es_evi_add_zrecv {'esi': '03:44:38:39:ff:ff:01:00:00:01', 'vni': 1004} frr_bgp:evpn_mh_local_es_evi_del_zrecv {'esi': '03:44:38:39:ff:ff:01:00:00:01', 'vni': 1001} 3. L2-VNI frr_bgp:evpn_local_vni_add_zrecv {'vni': 1004, 'vtep': '27.0.0.15', 'mc_grp': '239.1.1.104', 'vrf': 97} 4. L3-VNI frr_bgp:evpn_local_l3vni_add_zrecv {'vni': 4001, 'vrf': 87, 'svi_rmac': '24:8a:07:cc:aa:5f', 'vrr_rmac': '24:8a:07:cc:aa:5f', 'vtep': '27.0.0.15', 'filter': 0, 'svi_ifindex': 95, 'anycast_mac': 'n' frr_bgp:evpn_local_l3vni_del_zrecv {'vni': 4003, 'vrf': 107} 5. MAC-IP frr_bgp:evpn_local_macip_add_zrecv {'vni': 1003, 'mac': '00:02:00:00:00:04', 'ip': 'fe80::202:ff:fe00:4', 'flags': 4, 'seq': 0, 'esi': '03:44:38:39:ff:ff:01:00:00:02'} frr_bgp:evpn_local_macip_del_zrecv {'vni': 1000, 'mac': '00:02:00:00:00:04', 'ip': '2001:fee1::4', 'state': 1} Signed-off-by: Anuradha Karuppiah --- bgpd/bgp_trace.h | 141 ++++++++++++++++++++++++++++++++++++++++ bgpd/bgp_zebra.c | 42 ++++++++++-- tools/frr_babeltrace.py | 107 +++++++++++++++++++++++++++++- 3 files changed, 282 insertions(+), 8 deletions(-) diff --git a/bgpd/bgp_trace.h b/bgpd/bgp_trace.h index 91a190722be3..14149b5139a6 100644 --- a/bgpd/bgp_trace.h +++ b/bgpd/bgp_trace.h @@ -334,6 +334,147 @@ TRACEPOINT_EVENT( ) ) TRACEPOINT_LOGLEVEL(frr_bgp, evpn_nh_rmac_zsend, TRACE_INFO) + +TRACEPOINT_EVENT( + frr_bgp, + evpn_mh_local_es_add_zrecv, + TP_ARGS(esi_t *, esi, struct in_addr, vtep, + uint8_t, active, uint8_t, bypass, uint16_t, df_pref), + TP_FIELDS( + ctf_array(unsigned char, esi, esi, sizeof(esi_t)) + ctf_integer_network_hex(unsigned int, vtep, vtep.s_addr) + ctf_integer(uint8_t, active, active) + ctf_integer(uint8_t, bypass, bypass) + ctf_integer(uint16_t, df_pref, df_pref) + ) +) +TRACEPOINT_LOGLEVEL(frr_bgp, evpn_mh_local_es_add_zrecv, TRACE_INFO) + +TRACEPOINT_EVENT( + frr_bgp, + evpn_mh_local_es_del_zrecv, + TP_ARGS(esi_t *, esi), + TP_FIELDS( + ctf_array(unsigned char, esi, esi, sizeof(esi_t)) + ) +) +TRACEPOINT_LOGLEVEL(frr_bgp, evpn_mh_local_es_del_zrecv, TRACE_INFO) + +TRACEPOINT_EVENT( + frr_bgp, + evpn_mh_local_es_evi_add_zrecv, + TP_ARGS(esi_t *, esi, vni_t, vni), + TP_FIELDS( + ctf_array(unsigned char, esi, esi, sizeof(esi_t)) + ctf_integer(vni_t, vni, vni) + ) +) +TRACEPOINT_LOGLEVEL(frr_bgp, evpn_mh_local_es_evi_add_zrecv, TRACE_INFO) + +TRACEPOINT_EVENT( + frr_bgp, + evpn_mh_local_es_evi_del_zrecv, + TP_ARGS(esi_t *, esi, vni_t, vni), + TP_FIELDS( + ctf_array(unsigned char, esi, esi, sizeof(esi_t)) + ctf_integer(vni_t, vni, vni) + ) +) +TRACEPOINT_LOGLEVEL(frr_bgp, evpn_mh_local_es_evi_del_zrecv, TRACE_INFO) + +TRACEPOINT_EVENT( + frr_bgp, + evpn_local_vni_add_zrecv, + TP_ARGS(vni_t, vni, struct in_addr, vtep, vrf_id_t, vrf, + struct in_addr, mc_grp), + TP_FIELDS( + ctf_integer(vni_t, vni, vni) + ctf_integer_network_hex(unsigned int, vtep, vtep.s_addr) + ctf_integer_network_hex(unsigned int, mc_grp, + mc_grp.s_addr) + ctf_integer(int, vrf, vrf) + ) +) +TRACEPOINT_LOGLEVEL(frr_bgp, evpn_local_vni_add_zrecv, TRACE_INFO) + +TRACEPOINT_EVENT( + frr_bgp, + evpn_local_vni_del_zrecv, + TP_ARGS(vni_t, vni), + TP_FIELDS( + ctf_integer(vni_t, vni, vni) + ) +) +TRACEPOINT_LOGLEVEL(frr_bgp, evpn_local_vni_del_zrecv, TRACE_INFO) + +TRACEPOINT_EVENT( + frr_bgp, + evpn_local_macip_add_zrecv, + TP_ARGS(vni_t, vni, struct ethaddr *, mac, + struct ipaddr *, ip, uint32_t, flags, + uint32_t, seqnum, esi_t *, esi), + TP_FIELDS( + ctf_integer(vni_t, vni, vni) + ctf_array(unsigned char, mac, mac, + sizeof(struct ethaddr)) + ctf_array(unsigned char, ip, ip, + sizeof(struct ipaddr)) + ctf_integer(uint32_t, flags, flags) + ctf_integer(uint32_t, seq, seqnum) + ctf_array(unsigned char, esi, esi, sizeof(esi_t)) + ) +) +TRACEPOINT_LOGLEVEL(frr_bgp, evpn_local_macip_add_zrecv, TRACE_INFO) + +TRACEPOINT_EVENT( + frr_bgp, + evpn_local_macip_del_zrecv, + TP_ARGS(vni_t, vni, struct ethaddr *, mac, struct ipaddr *, ip, + int, state), + TP_FIELDS( + ctf_integer(vni_t, vni, vni) + ctf_array(unsigned char, mac, mac, + sizeof(struct ethaddr)) + ctf_array(unsigned char, ip, ip, + sizeof(struct ipaddr)) + ctf_integer(int, state, state) + ) +) +TRACEPOINT_LOGLEVEL(frr_bgp, evpn_local_macip_del_zrecv, TRACE_INFO) + +TRACEPOINT_EVENT( + frr_bgp, + evpn_local_l3vni_add_zrecv, + TP_ARGS(vni_t, vni, vrf_id_t, vrf, + struct ethaddr *, svi_rmac, + struct ethaddr *, vrr_rmac, int, filter, + struct in_addr, vtep, int, svi_ifindex, + bool, anycast_mac), + TP_FIELDS( + ctf_integer(vni_t, vni, vni) + ctf_integer(int, vrf, vrf) + ctf_array(unsigned char, svi_rmac, svi_rmac, + sizeof(struct ethaddr)) + ctf_array(unsigned char, vrr_rmac, vrr_rmac, + sizeof(struct ethaddr)) + ctf_integer_network_hex(unsigned int, vtep, vtep.s_addr) + ctf_integer(int, filter, filter) + ctf_integer(int, svi_ifindex, svi_ifindex) + ctf_string(anycast_mac, anycast_mac ? "y" : "n") + ) +) +TRACEPOINT_LOGLEVEL(frr_bgp, evpn_local_l3vni_add_zrecv, TRACE_INFO) + +TRACEPOINT_EVENT( + frr_bgp, + evpn_local_l3vni_del_zrecv, + TP_ARGS(vni_t, vni, vrf_id_t, vrf), + TP_FIELDS( + ctf_integer(vni_t, vni, vni) + ctf_integer(int, vrf, vrf) + ) +) +TRACEPOINT_LOGLEVEL(frr_bgp, evpn_local_l3vni_del_zrecv, TRACE_INFO) /* clang-format on */ #include diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 0249d53f0218..6161f56fe650 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -64,6 +64,7 @@ #include "bgpd/bgp_evpn_private.h" #include "bgpd/bgp_evpn_mh.h" #include "bgpd/bgp_mac.h" +#include "bgpd/bgp_trace.h" /* All information about zebra. */ struct zclient *zclient = NULL; @@ -2773,6 +2774,9 @@ static int bgp_zebra_process_local_es_add(ZAPI_CALLBACK_ARGS) esi_to_str(&esi, buf, sizeof(buf)), &originator_ip, active, df_pref, bypass ? "bypass" : ""); + frrtrace(5, frr_bgp, evpn_mh_local_es_add_zrecv, &esi, originator_ip, + active, bypass, df_pref); + bgp_evpn_local_es_add(bgp, &esi, originator_ip, active, df_pref, !!bypass); @@ -2798,6 +2802,8 @@ static int bgp_zebra_process_local_es_del(ZAPI_CALLBACK_ARGS) zlog_debug("Rx del ESI %s", esi_to_str(&esi, buf, sizeof(buf))); + frrtrace(1, frr_bgp, evpn_mh_local_es_del_zrecv, &esi); + bgp_evpn_local_es_del(bgp, &esi); return 0; @@ -2824,10 +2830,15 @@ static int bgp_zebra_process_local_es_evi(ZAPI_CALLBACK_ARGS) ZEBRA_VNI_ADD ? "add" : "del", esi_to_str(&esi, buf, sizeof(buf)), vni); - if (cmd == ZEBRA_LOCAL_ES_EVI_ADD) + if (cmd == ZEBRA_LOCAL_ES_EVI_ADD) { + frrtrace(2, frr_bgp, evpn_mh_local_es_evi_add_zrecv, &esi, vni); + bgp_evpn_local_es_evi_add(bgp, &esi, vni); - else + } else { + frrtrace(2, frr_bgp, evpn_mh_local_es_evi_del_zrecv, &esi, vni); + bgp_evpn_local_es_evi_del(bgp, &esi, vni); + } return 0; } @@ -2862,6 +2873,10 @@ static int bgp_zebra_process_local_l3vni(ZAPI_CALLBACK_ARGS) filter ? "prefix-routes-only" : "none", svi_ifindex); + frrtrace(8, frr_bgp, evpn_local_l3vni_add_zrecv, l3vni, vrf_id, + &svi_rmac, &vrr_rmac, filter, originator_ip, + svi_ifindex, is_anycast_mac); + bgp_evpn_local_l3vni_add(l3vni, vrf_id, &svi_rmac, &vrr_rmac, originator_ip, filter, svi_ifindex, is_anycast_mac); @@ -2870,6 +2885,8 @@ static int bgp_zebra_process_local_l3vni(ZAPI_CALLBACK_ARGS) zlog_debug("Rx L3-VNI DEL VRF %s VNI %u", vrf_id_to_name(vrf_id), l3vni); + frrtrace(2, frr_bgp, evpn_local_l3vni_del_zrecv, l3vni, vrf_id); + bgp_evpn_local_l3vni_del(l3vni, vrf_id); } @@ -2906,13 +2923,19 @@ static int bgp_zebra_process_local_vni(ZAPI_CALLBACK_ARGS) vrf_id_to_name(vrf_id), vni, vrf_id_to_name(tenant_vrf_id), svi_ifindex); - if (cmd == ZEBRA_VNI_ADD) + if (cmd == ZEBRA_VNI_ADD) { + frrtrace(4, frr_bgp, evpn_local_vni_add_zrecv, vni, vtep_ip, + tenant_vrf_id, mcast_grp); + return bgp_evpn_local_vni_add( bgp, vni, vtep_ip.s_addr != INADDR_ANY ? vtep_ip : bgp->router_id, tenant_vrf_id, mcast_grp, svi_ifindex); - else + } else { + frrtrace(1, frr_bgp, evpn_local_vni_del_zrecv, vni); + return bgp_evpn_local_vni_del(bgp, vni); + } } static int bgp_zebra_process_local_macip(ZAPI_CALLBACK_ARGS) @@ -2968,11 +2991,18 @@ static int bgp_zebra_process_local_macip(ZAPI_CALLBACK_ARGS) &mac, &ip, vni, seqnum, state, esi_to_str(&esi, buf2, sizeof(buf2))); - if (cmd == ZEBRA_MACIP_ADD) + if (cmd == ZEBRA_MACIP_ADD) { + frrtrace(6, frr_bgp, evpn_local_macip_add_zrecv, vni, &mac, &ip, + flags, seqnum, &esi); + return bgp_evpn_local_macip_add(bgp, vni, &mac, &ip, flags, seqnum, &esi); - else + } else { + frrtrace(4, frr_bgp, evpn_local_macip_del_zrecv, vni, &mac, &ip, + state); + return bgp_evpn_local_macip_del(bgp, vni, &mac, &ip, state); + } } static void bgp_zebra_process_local_ip_prefix(ZAPI_CALLBACK_ARGS) diff --git a/tools/frr_babeltrace.py b/tools/frr_babeltrace.py index 305839575846..4a5dd2bb4ba2 100755 --- a/tools/frr_babeltrace.py +++ b/tools/frr_babeltrace.py @@ -132,7 +132,93 @@ def parse_frr_bgp_evpn_mh_nh_rmac_send(event): parse_event(event, field_parsers) -############################ evpn parsers - end ############################# +def parse_frr_bgp_evpn_mh_local_es_add_zrecv(event): + ''' + bgp evpn local-es parser; raw format - + ctf_array(unsigned char, esi, esi, sizeof(esi_t)) + ctf_integer_network_hex(unsigned int, vtep, vtep.s_addr) + ''' + field_parsers = {'esi': print_esi, + 'vtep': print_net_ipv4_addr} + + parse_event(event, field_parsers) + +def parse_frr_bgp_evpn_mh_local_es_del_zrecv(event): + ''' + bgp evpn local-es parser; raw format - + ctf_array(unsigned char, esi, esi, sizeof(esi_t)) + ''' + field_parsers = {'esi': print_esi} + + parse_event(event, field_parsers) + +def parse_frr_bgp_evpn_mh_local_es_evi_add_zrecv(event): + ''' + bgp evpn local-es-evi parser; raw format - + ctf_array(unsigned char, esi, esi, sizeof(esi_t)) + ''' + field_parsers = {'esi': print_esi} + + parse_event(event, field_parsers) + +def parse_frr_bgp_evpn_mh_local_es_evi_del_zrecv(event): + ''' + bgp evpn local-es-evi parser; raw format - + ctf_array(unsigned char, esi, esi, sizeof(esi_t)) + ''' + field_parsers = {'esi': print_esi} + + parse_event(event, field_parsers) + +def parse_frr_bgp_evpn_local_vni_add_zrecv(event): + ''' + bgp evpn local-vni parser; raw format - + ctf_integer_network_hex(unsigned int, vtep, vtep.s_addr) + ctf_integer_network_hex(unsigned int, mc_grp, mc_grp.s_addr) + ''' + field_parsers = {'vtep': print_net_ipv4_addr, + 'mc_grp': print_net_ipv4_addr} + + parse_event(event, field_parsers) + +def parse_frr_bgp_evpn_local_l3vni_add_zrecv(event): + ''' + bgp evpn local-l3vni parser; raw format - + ctf_integer_network_hex(unsigned int, vtep, vtep.s_addr) + ctf_array(unsigned char, svi_rmac, svi_rmac, sizeof(struct ethaddr)) + ctf_array(unsigned char, vrr_rmac, vrr_rmac, sizeof(struct ethaddr)) + ''' + field_parsers = {'vtep': print_net_ipv4_addr, + 'svi_rmac': print_mac, + 'vrr_rmac': print_mac} + + parse_event(event, field_parsers) + +def parse_frr_bgp_evpn_local_macip_add_zrecv(event): + ''' + bgp evpn local-mac-ip parser; raw format - + ctf_array(unsigned char, ip, ip, sizeof(struct ipaddr)) + ctf_array(unsigned char, mac, mac, sizeof(struct ethaddr)) + ctf_array(unsigned char, esi, esi, sizeof(esi_t)) + ''' + field_parsers = {'ip': print_ip_addr, + 'mac': print_mac, + 'esi': print_esi} + + parse_event(event, field_parsers) + +def parse_frr_bgp_evpn_local_macip_del_zrecv(event): + ''' + bgp evpn local-mac-ip del parser; raw format - + ctf_array(unsigned char, ip, ip, sizeof(struct ipaddr)) + ctf_array(unsigned char, mac, mac, sizeof(struct ethaddr)) + ''' + field_parsers = {'ip': print_ip_addr, + 'mac': print_mac} + + parse_event(event, field_parsers) + +############################ evpn parsers - end *############################# def main(): ''' @@ -143,7 +229,24 @@ def main(): 'frr_bgp:evpn_bum_vtep_zsend': parse_frr_bgp_evpn_bum_vtep_zsend, 'frr_bgp:evpn_mh_nh_rmac_zsend': - parse_frr_bgp_evpn_mh_nh_rmac_send} + parse_frr_bgp_evpn_mh_nh_rmac_send, + 'frr_bgp:evpn_mh_local_es_add_zrecv': + parse_frr_bgp_evpn_mh_local_es_add_zrecv, + 'frr_bgp:evpn_mh_local_es_del_zrecv': + parse_frr_bgp_evpn_mh_local_es_del_zrecv, + 'frr_bgp:evpn_mh_local_es_evi_add_zrecv': + parse_frr_bgp_evpn_mh_local_es_evi_add_zrecv, + 'frr_bgp:evpn_mh_local_es_evi_del_zrecv': + parse_frr_bgp_evpn_mh_local_es_evi_del_zrecv, + 'frr_bgp:evpn_local_vni_add_zrecv': + parse_frr_bgp_evpn_local_vni_add_zrecv, + 'frr_bgp:evpn_local_l3vni_add_zrecv': + parse_frr_bgp_evpn_local_l3vni_add_zrecv, + 'frr_bgp:evpn_local_macip_add_zrecv': + parse_frr_bgp_evpn_local_macip_add_zrecv, + 'frr_bgp:evpn_local_macip_del_zrecv': + parse_frr_bgp_evpn_local_macip_del_zrecv, +} # get the trace path from the first command line argument trace_path = sys.argv[1] From b9c3be8be2aeb333fd8018d03674e1a490ad7b5d Mon Sep 17 00:00:00 2001 From: Anuradha Karuppiah Date: Fri, 1 Oct 2021 09:52:24 -0700 Subject: [PATCH 149/188] tools: add frr_babeltrace.py to /usr/lib/frr Make the script available as a part of the FRR package install for ease of use. Signed-off-by: Anuradha Karuppiah --- debian/frr-pythontools.install | 1 + redhat/frr.spec.in | 3 +++ tools/subdir.am | 2 ++ 3 files changed, 6 insertions(+) diff --git a/debian/frr-pythontools.install b/debian/frr-pythontools.install index 5f7eaebed5c8..820895ce6873 100644 --- a/debian/frr-pythontools.install +++ b/debian/frr-pythontools.install @@ -1,2 +1,3 @@ usr/lib/frr/frr-reload.py usr/lib/frr/generate_support_bundle.py +usr/lib/frr/frr_babeltrace.py diff --git a/redhat/frr.spec.in b/redhat/frr.spec.in index 066c45f55c7b..a7286d18788c 100644 --- a/redhat/frr.spec.in +++ b/redhat/frr.spec.in @@ -717,6 +717,7 @@ fi %files pythontools %{_sbindir}/generate_support_bundle.py %{_sbindir}/frr-reload.py +%{_sbindir}/frr_babeltrace.py %if 0%{?rhel} > 7 || 0%{?fedora} > 29 %{_sbindir}/__pycache__/* %else @@ -724,6 +725,8 @@ fi %{_sbindir}/generate_support_bundle.pyo %{_sbindir}/frr-reload.pyc %{_sbindir}/frr-reload.pyo +%{_sbindir}/frr_babeltrace.pyc +%{_sbindir}/frr_babeltrace.pyo %endif diff --git a/tools/subdir.am b/tools/subdir.am index e4b9ecd84ff3..64ca0bd514e1 100644 --- a/tools/subdir.am +++ b/tools/subdir.am @@ -21,6 +21,7 @@ sbin_SCRIPTS += \ tools/frrcommon.sh \ tools/frrinit.sh \ tools/generate_support_bundle.py \ + tools/frr_babeltrace.py \ tools/watchfrr.sh \ # end @@ -58,6 +59,7 @@ EXTRA_DIST += \ tools/frr.service \ tools/frr@.service \ tools/generate_support_bundle.py \ + tools/frr_babeltrace.py \ tools/multiple-bgpd.sh \ tools/rrcheck.pl \ tools/rrlookup.pl \ From 32dcd36d29dc796d358e03e28e238f1f4669059e Mon Sep 17 00:00:00 2001 From: Anuradha Karuppiah Date: Mon, 4 Oct 2021 10:53:50 -0700 Subject: [PATCH 150/188] tools: upstream linter is recommending double quotes Replaced single quotes with double quotes for strings in the frr_babeltrace.py utility. Signed-off-by: Anuradha Karuppiah --- tools/frr_babeltrace.py | 156 ++++++++++++++++++++-------------------- 1 file changed, 78 insertions(+), 78 deletions(-) diff --git a/tools/frr_babeltrace.py b/tools/frr_babeltrace.py index 4a5dd2bb4ba2..27d830a11997 100755 --- a/tools/frr_babeltrace.py +++ b/tools/frr_babeltrace.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -''' +""" Usage: frr_babeltrace.py trace_path FRR pushes data into lttng tracepoints in the least overhead way possible @@ -23,7 +23,7 @@ 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 -''' +""" import ipaddress import socket @@ -33,56 +33,56 @@ ########################### common parsers - start ############################ def print_ip_addr(field_val): - ''' + """ pretty print "struct ipaddr" - ''' + """ if field_val[0] == socket.AF_INET: addr = [str(fv) for fv in field_val[4:8]] - return str(ipaddress.IPv4Address('.'.join(addr))) + return str(ipaddress.IPv4Address(".".join(addr))) if field_val[0] == socket.AF_INET6: - tmp = ''.join('%02x' % fb for fb in field_val[4:]) + tmp = "".join("%02x" % fb for fb in field_val[4:]) addr = [] while tmp: addr.append(tmp[:4]) tmp = tmp[4:] - addr = ':'.join(addr) + addr = ":".join(addr) return str(ipaddress.IPv6Address(addr)) if not field_val[0]: - return '' + return "" return field_val def print_mac(field_val): - ''' + """ pretty print "u8 mac[6]" - ''' - return ':'.join('%02x' % fb for fb in field_val) + """ + return ":".join("%02x" % fb for fb in field_val) def print_net_ipv4_addr(field_val): - ''' + """ pretty print ctf_integer_network ipv4 - ''' + """ return str(ipaddress.IPv4Address(field_val)) def print_esi(field_val): - ''' + """ pretty print ethernet segment id, esi_t - ''' - return ':'.join('%02x' % fb for fb in field_val) + """ + return ":".join("%02x" % fb for fb in field_val) def get_field_list(event): - ''' + """ only fetch fields added via the TP, skip metadata etc. - ''' + """ return event.field_list_with_scope(babeltrace.CTFScope.EVENT_FIELDS) def parse_event(event, field_parsers): - ''' + """ Wild card event parser; doesn't make things any prettier - ''' + """ field_list = get_field_list(event) field_info = {} for field in field_list: @@ -96,7 +96,7 @@ def parse_event(event, field_parsers): ############################ evpn parsers - start ############################# def parse_frr_bgp_evpn_mac_ip_zsend(event): - ''' + """ bgp evpn mac-ip parser; raw format - ctf_array(unsigned char, mac, &pfx->prefix.macip_addr.mac, sizeof(struct ethaddr)) @@ -104,147 +104,147 @@ def parse_frr_bgp_evpn_mac_ip_zsend(event): sizeof(struct ipaddr)) ctf_integer_network_hex(unsigned int, vtep, vtep.s_addr) ctf_array(unsigned char, esi, esi, sizeof(esi_t)) - ''' - field_parsers = {'ip': print_ip_addr, - 'mac': print_mac, - 'esi': print_esi, - 'vtep': print_net_ipv4_addr} + """ + field_parsers = {"ip": print_ip_addr, + "mac": print_mac, + "esi": print_esi, + "vtep": print_net_ipv4_addr} parse_event(event, field_parsers) def parse_frr_bgp_evpn_bum_vtep_zsend(event): - ''' + """ bgp evpn bum-vtep parser; raw format - ctf_integer_network_hex(unsigned int, vtep, pfx->prefix.imet_addr.ip.ipaddr_v4.s_addr) - ''' - field_parsers = {'vtep': print_net_ipv4_addr} + """ + field_parsers = {"vtep": print_net_ipv4_addr} parse_event(event, field_parsers) def parse_frr_bgp_evpn_mh_nh_rmac_send(event): - ''' + """ bgp evpn nh-rmac parser; raw format - ctf_array(unsigned char, rmac, &nh->rmac, sizeof(struct ethaddr)) - ''' - field_parsers = {'rmac': print_mac} + """ + field_parsers = {"rmac": print_mac} parse_event(event, field_parsers) def parse_frr_bgp_evpn_mh_local_es_add_zrecv(event): - ''' + """ bgp evpn local-es parser; raw format - ctf_array(unsigned char, esi, esi, sizeof(esi_t)) ctf_integer_network_hex(unsigned int, vtep, vtep.s_addr) - ''' - field_parsers = {'esi': print_esi, - 'vtep': print_net_ipv4_addr} + """ + field_parsers = {"esi": print_esi, + "vtep": print_net_ipv4_addr} parse_event(event, field_parsers) def parse_frr_bgp_evpn_mh_local_es_del_zrecv(event): - ''' + """ bgp evpn local-es parser; raw format - ctf_array(unsigned char, esi, esi, sizeof(esi_t)) - ''' - field_parsers = {'esi': print_esi} + """ + field_parsers = {"esi": print_esi} parse_event(event, field_parsers) def parse_frr_bgp_evpn_mh_local_es_evi_add_zrecv(event): - ''' + """ bgp evpn local-es-evi parser; raw format - ctf_array(unsigned char, esi, esi, sizeof(esi_t)) - ''' - field_parsers = {'esi': print_esi} + """ + field_parsers = {"esi": print_esi} parse_event(event, field_parsers) def parse_frr_bgp_evpn_mh_local_es_evi_del_zrecv(event): - ''' + """ bgp evpn local-es-evi parser; raw format - ctf_array(unsigned char, esi, esi, sizeof(esi_t)) - ''' - field_parsers = {'esi': print_esi} + """ + field_parsers = {"esi": print_esi} parse_event(event, field_parsers) def parse_frr_bgp_evpn_local_vni_add_zrecv(event): - ''' + """ bgp evpn local-vni parser; raw format - ctf_integer_network_hex(unsigned int, vtep, vtep.s_addr) ctf_integer_network_hex(unsigned int, mc_grp, mc_grp.s_addr) - ''' - field_parsers = {'vtep': print_net_ipv4_addr, - 'mc_grp': print_net_ipv4_addr} + """ + field_parsers = {"vtep": print_net_ipv4_addr, + "mc_grp": print_net_ipv4_addr} parse_event(event, field_parsers) def parse_frr_bgp_evpn_local_l3vni_add_zrecv(event): - ''' + """ bgp evpn local-l3vni parser; raw format - ctf_integer_network_hex(unsigned int, vtep, vtep.s_addr) ctf_array(unsigned char, svi_rmac, svi_rmac, sizeof(struct ethaddr)) ctf_array(unsigned char, vrr_rmac, vrr_rmac, sizeof(struct ethaddr)) - ''' - field_parsers = {'vtep': print_net_ipv4_addr, - 'svi_rmac': print_mac, - 'vrr_rmac': print_mac} + """ + field_parsers = {"vtep": print_net_ipv4_addr, + "svi_rmac": print_mac, + "vrr_rmac": print_mac} parse_event(event, field_parsers) def parse_frr_bgp_evpn_local_macip_add_zrecv(event): - ''' + """ bgp evpn local-mac-ip parser; raw format - ctf_array(unsigned char, ip, ip, sizeof(struct ipaddr)) ctf_array(unsigned char, mac, mac, sizeof(struct ethaddr)) ctf_array(unsigned char, esi, esi, sizeof(esi_t)) - ''' - field_parsers = {'ip': print_ip_addr, - 'mac': print_mac, - 'esi': print_esi} + """ + field_parsers = {"ip": print_ip_addr, + "mac": print_mac, + "esi": print_esi} parse_event(event, field_parsers) def parse_frr_bgp_evpn_local_macip_del_zrecv(event): - ''' + """ bgp evpn local-mac-ip del parser; raw format - ctf_array(unsigned char, ip, ip, sizeof(struct ipaddr)) ctf_array(unsigned char, mac, mac, sizeof(struct ethaddr)) - ''' - field_parsers = {'ip': print_ip_addr, - 'mac': print_mac} + """ + field_parsers = {"ip": print_ip_addr, + "mac": print_mac} parse_event(event, field_parsers) ############################ evpn parsers - end *############################# def main(): - ''' + """ FRR lttng trace output parser; babel trace plugin - ''' - event_parsers = {'frr_bgp:evpn_mac_ip_zsend': + """ + event_parsers = {"frr_bgp:evpn_mac_ip_zsend": parse_frr_bgp_evpn_mac_ip_zsend, - 'frr_bgp:evpn_bum_vtep_zsend': + "frr_bgp:evpn_bum_vtep_zsend": parse_frr_bgp_evpn_bum_vtep_zsend, - 'frr_bgp:evpn_mh_nh_rmac_zsend': + "frr_bgp:evpn_mh_nh_rmac_zsend": parse_frr_bgp_evpn_mh_nh_rmac_send, - 'frr_bgp:evpn_mh_local_es_add_zrecv': + "frr_bgp:evpn_mh_local_es_add_zrecv": parse_frr_bgp_evpn_mh_local_es_add_zrecv, - 'frr_bgp:evpn_mh_local_es_del_zrecv': + "frr_bgp:evpn_mh_local_es_del_zrecv": parse_frr_bgp_evpn_mh_local_es_del_zrecv, - 'frr_bgp:evpn_mh_local_es_evi_add_zrecv': + "frr_bgp:evpn_mh_local_es_evi_add_zrecv": parse_frr_bgp_evpn_mh_local_es_evi_add_zrecv, - 'frr_bgp:evpn_mh_local_es_evi_del_zrecv': + "frr_bgp:evpn_mh_local_es_evi_del_zrecv": parse_frr_bgp_evpn_mh_local_es_evi_del_zrecv, - 'frr_bgp:evpn_local_vni_add_zrecv': + "frr_bgp:evpn_local_vni_add_zrecv": parse_frr_bgp_evpn_local_vni_add_zrecv, - 'frr_bgp:evpn_local_l3vni_add_zrecv': + "frr_bgp:evpn_local_l3vni_add_zrecv": parse_frr_bgp_evpn_local_l3vni_add_zrecv, - 'frr_bgp:evpn_local_macip_add_zrecv': + "frr_bgp:evpn_local_macip_add_zrecv": parse_frr_bgp_evpn_local_macip_add_zrecv, - 'frr_bgp:evpn_local_macip_del_zrecv': + "frr_bgp:evpn_local_macip_del_zrecv": parse_frr_bgp_evpn_local_macip_del_zrecv, } @@ -253,7 +253,7 @@ def main(): # grab events trace_collection = babeltrace.TraceCollection() - trace_collection.add_traces_recursive(trace_path, 'ctf') + trace_collection.add_traces_recursive(trace_path, "ctf") for event in trace_collection.events: if event.name in event_parsers: @@ -262,5 +262,5 @@ def main(): else: parse_event(event, {}) -if __name__ == '__main__': +if __name__ == "__main__": main() From 6e59c4a71dd262f47dabe8286c59536cb417c494 Mon Sep 17 00:00:00 2001 From: Anuradha Karuppiah Date: Mon, 9 Aug 2021 11:50:22 -0700 Subject: [PATCH 151/188] zebra: deref the ES on interface delete even if it was not setup as a br-port This addresses deletion of ES interfaces that are were not completely configured. Ticket: #2668488 Signed-off-by: Anuradha Karuppiah --- zebra/zebra_evpn_mh.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/zebra/zebra_evpn_mh.c b/zebra/zebra_evpn_mh.c index e03cf9db061f..70382fea6a34 100644 --- a/zebra/zebra_evpn_mh.c +++ b/zebra/zebra_evpn_mh.c @@ -1050,15 +1050,15 @@ void zebra_evpn_if_cleanup(struct zebra_if *zif) vlanid_t vid; struct zebra_evpn_es *es; - if (!bf_is_inited(zif->vlan_bitmap)) - return; + if (bf_is_inited(zif->vlan_bitmap)) { + bf_for_each_set_bit(zif->vlan_bitmap, vid, IF_VLAN_BITMAP_MAX) + { + zebra_evpn_vl_mbr_deref(vid, zif); + } - bf_for_each_set_bit(zif->vlan_bitmap, vid, IF_VLAN_BITMAP_MAX) { - zebra_evpn_vl_mbr_deref(vid, zif); + bf_free(zif->vlan_bitmap); } - bf_free(zif->vlan_bitmap); - /* Delete associated Ethernet Segment */ es = zif->es_info.es; if (es) From 38f681e1cac07dac996ae952c99684501cf820c6 Mon Sep 17 00:00:00 2001 From: Anuradha Karuppiah Date: Tue, 10 Aug 2021 08:56:55 -0700 Subject: [PATCH 152/188] zebra: ignore sync updates from bgp if the dest ES is not ready In the window immediately after an ES deletion bgpd can send MAC-IP updates using that ES. Zebra needs to ignore these updates to prevent creation of stale entries. Ticket: #2668488 Signed-off-by: Anuradha Karuppiah --- zebra/zebra_evpn.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/zebra/zebra_evpn.c b/zebra/zebra_evpn.c index d5e043eea859..4006e1fed51c 100644 --- a/zebra/zebra_evpn.c +++ b/zebra/zebra_evpn.c @@ -1423,8 +1423,24 @@ void zebra_evpn_rem_macip_add(vni_t vni, const struct ethaddr *macaddr, * REMOTE - if ES is not local */ if (flags & ZEBRA_MACIP_TYPE_SYNC_PATH) { - zebra_evpn_process_sync_macip_add(zevpn, macaddr, ipa_len, - ipaddr, flags, seq, esi); + struct zebra_evpn_es *es; + + es = zebra_evpn_es_find(esi); + if (es && (es->flags & ZEBRA_EVPNES_READY_FOR_BGP)) { + zebra_evpn_process_sync_macip_add(zevpn, macaddr, + ipa_len, ipaddr, + flags, seq, esi); + } else { + if (IS_ZEBRA_DEBUG_EVPN_MH_ES) { + char esi_str[ESI_STR_LEN]; + + esi_to_str(esi, esi_str, sizeof(esi_str)); + zlog_debug( + "Ignore sync-macip add; ES %s is not ready", + esi_str); + } + } + return; } From 09de6e45505715ee85d0a4bcd47d9b03ad2b7610 Mon Sep 17 00:00:00 2001 From: Anuradha Karuppiah Date: Tue, 10 Aug 2021 14:31:34 -0700 Subject: [PATCH 153/188] zebra: defer local MAC dataplane install on an ES till the ES-EVI is created When an ES is deleted and re-added bgpd can start sending MAC-IP sync updates before the dataplane and zebra have setup the VLAN membership for the ES. Such MAC entries are not installed in the dataplane till the ES-EVI is created. Ticket: #2668488 Signed-off-by: Anuradha Karuppiah --- zebra/zebra_evpn_mac.c | 19 +++++++++++++++++++ zebra/zebra_evpn_mh.c | 34 ++++++++++++++++++++++++++++++++-- zebra/zebra_evpn_mh.h | 2 ++ 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/zebra/zebra_evpn_mac.c b/zebra/zebra_evpn_mac.c index 472e53b73012..c1bb19d4e506 100644 --- a/zebra/zebra_evpn_mac.c +++ b/zebra/zebra_evpn_mac.c @@ -1342,6 +1342,25 @@ int zebra_evpn_sync_mac_dp_install(struct zebra_mac *mac, bool set_inactive, struct zebra_if *zif; struct interface *br_ifp; + /* If the ES-EVI doesn't exist defer install. When the ES-EVI is + * created we will attempt to install the mac entry again + */ + if (mac->es) { + struct zebra_evpn_es_evi *es_evi; + + es_evi = zebra_evpn_es_evi_find(mac->es, mac->zevpn); + if (!es_evi) { + if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) + zlog_debug( + "%s: dp-install sync-mac vni %u mac %pEA es %s 0x%x %sskipped, no es-evi", + caller, zevpn->vni, &mac->macaddr, + mac->es ? mac->es->esi_str : "-", + mac->flags, + set_inactive ? "inactive " : ""); + return -1; + } + } + /* get the access vlan from the vxlan_device */ zebra_evpn_mac_get_access_info(mac, &ifp, &vid); diff --git a/zebra/zebra_evpn_mh.c b/zebra/zebra_evpn_mh.c index 70382fea6a34..3f7e6256fc2d 100644 --- a/zebra/zebra_evpn_mh.c +++ b/zebra/zebra_evpn_mh.c @@ -186,8 +186,8 @@ static void zebra_evpn_es_evi_free(struct zebra_evpn_es_evi *es_evi) } /* find the ES-EVI in the per-L2-VNI RB tree */ -static struct zebra_evpn_es_evi * -zebra_evpn_es_evi_find(struct zebra_evpn_es *es, struct zebra_evpn *zevpn) +struct zebra_evpn_es_evi *zebra_evpn_es_evi_find(struct zebra_evpn_es *es, + struct zebra_evpn *zevpn) { struct zebra_evpn_es_evi es_evi; @@ -229,6 +229,34 @@ static void zebra_evpn_local_es_evi_del(struct zebra_evpn_es *es, zebra_evpn_local_es_evi_do_del(es_evi); } +/* If there are any existing MAC entries for this es/zevpn we need + * to install it in the dataplane. + * + * Note: primary purpose of this is to handle es del/re-add windows where + * sync MAC entries may be added by bgpd before the es-evi membership is + * created in the dataplane and in zebra + */ +static void zebra_evpn_es_evi_mac_install(struct zebra_evpn_es_evi *es_evi) +{ + struct zebra_mac *mac; + struct listnode *node; + struct zebra_evpn_es *es = es_evi->es; + + if (listcount(es->mac_list) && IS_ZEBRA_DEBUG_EVPN_MH_ES) + zlog_debug("dp-mac install on es %s evi %d add", es->esi_str, + es_evi->zevpn->vni); + + for (ALL_LIST_ELEMENTS_RO(es->mac_list, node, mac)) { + if (mac->zevpn != es_evi->zevpn) + continue; + + if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) + continue; + + zebra_evpn_sync_mac_dp_install(mac, false, false, __func__); + } +} + /* Create an ES-EVI if it doesn't already exist and tell BGP */ static void zebra_evpn_local_es_evi_add(struct zebra_evpn_es *es, struct zebra_evpn *zevpn) @@ -250,6 +278,8 @@ static void zebra_evpn_local_es_evi_add(struct zebra_evpn_es *es, listnode_add(zevpn->local_es_evi_list, &es_evi->l2vni_listnode); zebra_evpn_es_evi_re_eval_send_to_client(es_evi); + + zebra_evpn_es_evi_mac_install(es_evi); } } diff --git a/zebra/zebra_evpn_mh.h b/zebra/zebra_evpn_mh.h index 853af7c4bcbd..af6832092b3c 100644 --- a/zebra/zebra_evpn_mh.h +++ b/zebra/zebra_evpn_mh.h @@ -387,5 +387,7 @@ extern void zebra_evpn_acc_bd_svi_mac_add(struct interface *vlan_if); extern void zebra_evpn_es_bypass_update(struct zebra_evpn_es *es, struct interface *ifp, bool bypass); extern void zebra_evpn_proc_remote_nh(ZAPI_HANDLER_ARGS); +extern struct zebra_evpn_es_evi * +zebra_evpn_es_evi_find(struct zebra_evpn_es *es, struct zebra_evpn *zevpn); #endif /* _ZEBRA_EVPN_MH_H */ From 8005767b2e5c177d0185a1541c7393d9ed8d1712 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Mon, 18 Oct 2021 14:30:01 +0200 Subject: [PATCH 154/188] lib: assign CLI varnames while parsing ... rather than running a costly extra pass across the finished tree. Signed-off-by: David Lamparter --- lib/command_graph.c | 157 +++++++++++++++++++++++--------------------- lib/command_graph.h | 11 ++++ lib/command_parse.y | 14 ++-- 3 files changed, 101 insertions(+), 81 deletions(-) diff --git a/lib/command_graph.c b/lib/command_graph.c index 15c8302e637f..09d802e79670 100644 --- a/lib/command_graph.c +++ b/lib/command_graph.c @@ -77,16 +77,17 @@ struct cmd_token *cmd_token_dup(struct cmd_token *token) return copy; } -void cmd_token_varname_set(struct cmd_token *token, const char *varname) +static void cmd_token_varname_do(struct cmd_token *token, const char *varname, + uint8_t varname_src) { - XFREE(MTYPE_CMD_VAR, token->varname); - if (!varname) { - token->varname = NULL; + if (token->varname_src >= varname_src) return; - } + + XFREE(MTYPE_CMD_VAR, token->varname); size_t len = strlen(varname), i; token->varname = XMALLOC(MTYPE_CMD_VAR, len + 1); + token->varname_src = varname_src; for (i = 0; i < len; i++) switch (varname[i]) { @@ -102,6 +103,80 @@ void cmd_token_varname_set(struct cmd_token *token, const char *varname) token->varname[len] = '\0'; } +void cmd_token_varname_set(struct cmd_token *token, const char *varname) +{ + if (varname) { + cmd_token_varname_do(token, varname, VARNAME_EXPLICIT); + return; + } + if (token->type == VARIABLE_TKN) { + if (strcmp(token->text, "WORD") && strcmp(token->text, "NAME")) + cmd_token_varname_do(token, token->text, VARNAME_TEXT); + } +} + +static void cmd_token_varname_fork(struct graph_node *node, + struct cmd_token *prevtoken) +{ + for (size_t i = 0; i < vector_active(node->to); i++) { + struct graph_node *next = vector_slot(node->to, i); + struct cmd_token *nexttoken = next->data; + + if (nexttoken->type == FORK_TKN) { + cmd_token_varname_fork(next, prevtoken); + continue; + } + if (nexttoken->varname) + continue; + if (!IS_VARYING_TOKEN(nexttoken->type)) + continue; + + cmd_token_varname_do(nexttoken, prevtoken->text, VARNAME_TEXT); + } +} + +void cmd_token_varname_join(struct graph_node *join, const char *varname) +{ + if (!varname) + return; + + for (size_t i = 0; i < vector_active(join->from); i++) { + struct graph_node *prev = vector_slot(join->from, i); + struct cmd_token *token = prev->data; + + if (token->type == JOIN_TKN) + cmd_token_varname_join(prev, varname); + else if (token->type < SPECIAL_TKN) + cmd_token_varname_do(token, varname, VARNAME_EXPLICIT); + } +} + +void cmd_token_varname_seqappend(struct graph_node *node) +{ + struct graph_node *prevnode = node; + struct cmd_token *token = node->data; + struct cmd_token *prevtoken; + + if (token->type == WORD_TKN) + return; + + do { + if (vector_active(prevnode->from) != 1) + return; + + prevnode = vector_slot(prevnode->from, 0); + prevtoken = prevnode->data; + } while (prevtoken->type == FORK_TKN); + + if (prevtoken->type != WORD_TKN) + return; + + if (token->type == FORK_TKN) + cmd_token_varname_fork(node, prevtoken); + else + cmd_token_varname_do(token, prevtoken->text, VARNAME_TEXT); +} + static bool cmd_nodes_link(struct graph_node *from, struct graph_node *to) { for (size_t i = 0; i < vector_active(from->to); i++) @@ -357,72 +432,6 @@ void cmd_graph_merge(struct graph *old, struct graph *new, int direction) vector_slot(new->nodes, 0), direction); } -static void cmd_node_names(struct graph_node *gn, struct graph_node *join, - const char *prevname) -{ - size_t i; - struct cmd_token *tok = gn->data, *jointok; - struct graph_node *stop = cmd_loopstop(gn); - - switch (tok->type) { - case WORD_TKN: - prevname = tok->text; - break; - - case VARIABLE_TKN: - if (!tok->varname && strcmp(tok->text, "WORD") - && strcmp(tok->text, "NAME")) - cmd_token_varname_set(tok, tok->text); - /* fallthrough */ - case RANGE_TKN: - case IPV4_TKN: - case IPV4_PREFIX_TKN: - case IPV6_TKN: - case IPV6_PREFIX_TKN: - case MAC_TKN: - case MAC_PREFIX_TKN: - if (!tok->varname && prevname) - cmd_token_varname_set(tok, prevname); - prevname = NULL; - break; - - case START_TKN: - case JOIN_TKN: - case NEG_ONLY_TKN: - /* " WORD" -> word is not "bar" or "foo" */ - prevname = NULL; - break; - - case FORK_TKN: - /* apply "$name" */ - jointok = tok->forkjoin->data; - if (!jointok->varname) - break; - for (i = 0; i < vector_active(tok->forkjoin->from); i++) { - struct graph_node *tail = - vector_slot(tok->forkjoin->from, i); - struct cmd_token *tailtok = tail->data; - if (tail == gn || tailtok->varname) - continue; - cmd_token_varname_set(tailtok, jointok->varname); - } - break; - - case END_TKN: - return; - } - - for (i = 0; i < vector_active(gn->to); i++) { - struct graph_node *next = vector_slot(gn->to, i); - if (next == stop || next == join) - continue; - cmd_node_names(next, join, prevname); - } - - if (tok->type == FORK_TKN && tok->forkjoin != join) - cmd_node_names(tok->forkjoin, join, NULL); -} - void cmd_graph_names(struct graph *graph) { struct graph_node *start; @@ -451,12 +460,10 @@ void cmd_graph_names(struct graph *graph) struct cmd_token *tok1 = next1->data; /* the other one needs to be "no" (only one will match here) */ if ((tok0->type == WORD_TKN && !strcmp(tok0->text, "no"))) - cmd_token_varname_set(tok0, "no"); + cmd_token_varname_do(tok0, "no", VARNAME_AUTO); if ((tok1->type == WORD_TKN && !strcmp(tok1->text, "no"))) - cmd_token_varname_set(tok1, "no"); + cmd_token_varname_do(tok1, "no", VARNAME_AUTO); } while (0); - - cmd_node_names(start, NULL, NULL); } #ifndef BUILDING_CLIPPY diff --git a/lib/command_graph.h b/lib/command_graph.h index 86157f872e0d..ed4da6aa4c89 100644 --- a/lib/command_graph.h +++ b/lib/command_graph.h @@ -79,11 +79,20 @@ enum { CMD_ATTR_NORMAL, CMD_ATTR_YANG, }; +enum varname_src { + VARNAME_NONE = 0, + VARNAME_AUTO, + VARNAME_VAR, + VARNAME_TEXT, + VARNAME_EXPLICIT, +}; + /* Command token struct. */ struct cmd_token { enum cmd_token_type type; // token type uint8_t attr; // token attributes bool allowrepeat; // matcher allowed to match token repetitively? + uint8_t varname_src; uint32_t refcnt; char *text; // token text @@ -119,6 +128,8 @@ extern struct cmd_token *cmd_token_new(enum cmd_token_type, uint8_t attr, extern struct cmd_token *cmd_token_dup(struct cmd_token *); extern void cmd_token_del(struct cmd_token *); extern void cmd_token_varname_set(struct cmd_token *token, const char *varname); +extern void cmd_token_varname_seqappend(struct graph_node *n); +extern void cmd_token_varname_join(struct graph_node *n, const char *varname); extern void cmd_graph_parse(struct graph *graph, const struct cmd_element *cmd); extern void cmd_graph_names(struct graph *graph); diff --git a/lib/command_parse.y b/lib/command_parse.y index dccd738f3156..35c119691bbb 100644 --- a/lib/command_parse.y +++ b/lib/command_parse.y @@ -217,10 +217,12 @@ cmd_token: { if ((ctx->currnode = graph_add_edge (ctx->currnode, $1)) != $1) graph_delete_node (ctx->graph, $1); + cmd_token_varname_seqappend($1); } | selector { graph_add_edge (ctx->currnode, $1.start); + cmd_token_varname_seqappend($1.start); ctx->currnode = $1.end; } ; @@ -295,9 +297,8 @@ placeholder_token_real: placeholder_token: placeholder_token_real varname_token { - struct cmd_token *token = $$->data; $$ = $1; - cmd_token_varname_set (token, $2); + cmd_token_varname_set ($$->data, $2); XFREE (MTYPE_LEX, $2); }; @@ -306,7 +307,7 @@ placeholder_token: selector: '<' selector_seq_seq '>' varname_token { $$ = $2; - cmd_token_varname_set ($2.end->data, $4); + cmd_token_varname_join ($2.end, $4); XFREE (MTYPE_LEX, $4); }; @@ -342,7 +343,7 @@ selector: '{' selector_seq_seq '}' varname_token * #1 is good enough to keep it this way. */ loopcheck(ctx, &$$); - cmd_token_varname_set ($2.end->data, $4); + cmd_token_varname_join ($2.end, $4); XFREE (MTYPE_LEX, $4); }; @@ -359,6 +360,7 @@ selector_token_seq: selector_token_seq selector_token { graph_add_edge ($1.end, $2.start); + cmd_token_varname_seqappend($2.start); $$.start = $1.start; $$.end = $2.end; } @@ -370,7 +372,7 @@ selector: '[' selector_seq_seq ']' varname_token { $$ = $2; graph_add_edge ($$.start, $$.end); - cmd_token_varname_set ($2.end->data, $4); + cmd_token_varname_join ($2.end, $4); XFREE (MTYPE_LEX, $4); } ; @@ -383,7 +385,7 @@ selector: EXCL_BRACKET selector_seq_seq ']' varname_token $$ = $2; graph_add_edge ($$.start, neg_only); graph_add_edge (neg_only, $$.end); - cmd_token_varname_set ($2.end->data, $4); + cmd_token_varname_join ($2.end, $4); XFREE (MTYPE_LEX, $4); } ; From 0e06eb8b2ea1eff8c67752533d66e96bb9bebfdb Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Mon, 18 Oct 2021 11:51:09 +0200 Subject: [PATCH 155/188] vtysh: defer CLI tree building We don't need the CLI tree until we actually enter the node. Signed-off-by: David Lamparter --- lib/command.c | 75 +++++++++++++++++++++++++++++++++++-------- lib/command.h | 9 ++++++ lib/grammar_sandbox.c | 2 ++ vtysh/vtysh.c | 2 ++ 4 files changed, 74 insertions(+), 14 deletions(-) diff --git a/lib/command.c b/lib/command.c index 53aa06470554..ea66a17bb07c 100644 --- a/lib/command.c +++ b/lib/command.c @@ -86,6 +86,9 @@ vector cmdvec = NULL; /* Host information structure. */ struct host host; +/* for vtysh, put together CLI trees only when switching into node */ +static bool defer_cli_tree; + /* * Returns host.name if any, otherwise * it returns the system hostname. @@ -285,6 +288,11 @@ const char *cmd_prompt(enum node_type node) return cnode->prompt; } +void cmd_defer_tree(bool val) +{ + defer_cli_tree = val; +} + /* Install a command into a node. */ void _install_element(enum node_type ntype, const struct cmd_element *cmd) { @@ -319,20 +327,50 @@ void _install_element(enum node_type ntype, const struct cmd_element *cmd) assert(hash_get(cnode->cmd_hash, (void *)cmd, hash_alloc_intern)); + if (cnode->graph_built || !defer_cli_tree) { + struct graph *graph = graph_new(); + struct cmd_token *token = + cmd_token_new(START_TKN, CMD_ATTR_NORMAL, NULL, NULL); + graph_new_node(graph, token, + (void (*)(void *)) & cmd_token_del); + + cmd_graph_parse(graph, cmd); + cmd_graph_names(graph); + cmd_graph_merge(cnode->cmdgraph, graph, +1); + graph_delete_graph(graph); + + cnode->graph_built = true; + } + + vector_set(cnode->cmd_vector, (void *)cmd); + + if (ntype == VIEW_NODE) + _install_element(ENABLE_NODE, cmd); +} + +static void cmd_finalize_iter(struct hash_bucket *hb, void *arg) +{ + struct cmd_node *cnode = arg; + const struct cmd_element *cmd = hb->data; struct graph *graph = graph_new(); struct cmd_token *token = cmd_token_new(START_TKN, CMD_ATTR_NORMAL, NULL, NULL); + graph_new_node(graph, token, (void (*)(void *)) & cmd_token_del); cmd_graph_parse(graph, cmd); cmd_graph_names(graph); cmd_graph_merge(cnode->cmdgraph, graph, +1); graph_delete_graph(graph); +} - vector_set(cnode->cmd_vector, (void *)cmd); +void cmd_finalize_node(struct cmd_node *cnode) +{ + if (cnode->graph_built) + return; - if (ntype == VIEW_NODE) - _install_element(ENABLE_NODE, cmd); + hash_iterate(cnode->cmd_hash, cmd_finalize_iter, cnode); + cnode->graph_built = true; } void uninstall_element(enum node_type ntype, const struct cmd_element *cmd) @@ -368,15 +406,18 @@ void uninstall_element(enum node_type ntype, const struct cmd_element *cmd) vector_unset_value(cnode->cmd_vector, (void *)cmd); - struct graph *graph = graph_new(); - struct cmd_token *token = - cmd_token_new(START_TKN, CMD_ATTR_NORMAL, NULL, NULL); - graph_new_node(graph, token, (void (*)(void *)) & cmd_token_del); + if (cnode->graph_built) { + struct graph *graph = graph_new(); + struct cmd_token *token = + cmd_token_new(START_TKN, CMD_ATTR_NORMAL, NULL, NULL); + graph_new_node(graph, token, + (void (*)(void *)) & cmd_token_del); - cmd_graph_parse(graph, cmd); - cmd_graph_names(graph); - cmd_graph_merge(cnode->cmdgraph, graph, -1); - graph_delete_graph(graph); + cmd_graph_parse(graph, cmd); + cmd_graph_names(graph); + cmd_graph_merge(cnode->cmdgraph, graph, -1); + graph_delete_graph(graph); + } if (ntype == VIEW_NODE) uninstall_element(ENABLE_NODE, cmd); @@ -503,6 +544,8 @@ static int config_write_host(struct vty *vty) static struct graph *cmd_node_graph(vector v, enum node_type ntype) { struct cmd_node *cnode = vector_slot(v, ntype); + + cmd_finalize_node(cnode); return cnode->cmdgraph; } @@ -1506,9 +1549,10 @@ int cmd_list_cmds(struct vty *vty, int do_permute) { struct cmd_node *node = vector_slot(cmdvec, vty->node); - if (do_permute) + if (do_permute) { + cmd_finalize_node(node); permute(vector_slot(node->cmdgraph->nodes, 0), vty); - else { + } else { /* loop over all commands at this node */ const struct cmd_element *element = NULL; for (unsigned int i = 0; i < vector_active(node->cmd_vector); @@ -1551,7 +1595,10 @@ DEFUN_HIDDEN(show_cli_graph, "Dump current command space as DOT graph\n") { struct cmd_node *cn = vector_slot(cmdvec, vty->node); - char *dot = cmd_graph_dump_dot(cn->cmdgraph); + char *dot; + + cmd_finalize_node(cn); + dot = cmd_graph_dump_dot(cn->cmdgraph); vty_out(vty, "%s\n", dot); XFREE(MTYPE_TMP, dot); diff --git a/lib/command.h b/lib/command.h index e2eec1aac68c..e2086701ad73 100644 --- a/lib/command.h +++ b/lib/command.h @@ -210,6 +210,9 @@ struct cmd_node { /* Hashed index of command node list, for de-dupping primarily */ struct hash *cmd_hash; + + /* set as soon as any command is in cmdgraph */ + bool graph_built; }; /* Return value of the commands. */ @@ -526,6 +529,12 @@ extern void _install_element(enum node_type, const struct cmd_element *); * deprecated/hidden) are not reversed. */ extern void uninstall_element(enum node_type, const struct cmd_element *); +/* construct CLI tree only when entering nodes */ +extern void cmd_defer_tree(bool val); + +/* finish CLI tree for node when above is true (noop otherwise) */ +extern void cmd_finalize_node(struct cmd_node *node); + /* Concatenates argv[shift] through argv[argc-1] into a single NUL-terminated string with a space between each element (allocated using XMALLOC(MTYPE_TMP)). Returns NULL if shift >= argc. */ diff --git a/lib/grammar_sandbox.c b/lib/grammar_sandbox.c index 209765bd6f9a..f9778c5d4c46 100644 --- a/lib/grammar_sandbox.c +++ b/lib/grammar_sandbox.c @@ -395,6 +395,7 @@ DEFUN (grammar_findambig, vector_slot(cmdvec, scannode++); if (!cnode) continue; + cmd_finalize_node(cnode); nodegraph = cnode->cmdgraph; if (!nodegraph) continue; @@ -466,6 +467,7 @@ DEFUN (grammar_access, } vty_out(vty, "node %d\n", (int)cnode->node); + cmd_finalize_node(cnode); nodegraph = cnode->cmdgraph; return CMD_SUCCESS; } diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index beb7045a7d43..53349452e6ac 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -3923,6 +3923,8 @@ void vtysh_uninit(void) void vtysh_init_vty(void) { + cmd_defer_tree(true); + /* Make vty structure. */ vty = vty_new(); vty->type = VTY_SHELL; From 14c39974bbb37a1c95800b75af3d25ff72295f41 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Mon, 18 Oct 2021 15:29:17 +0200 Subject: [PATCH 156/188] lib: keep element count in vector code ... to speed up vector_empty_slot() among other things. Behavior should be 100% identical to previous. Signed-off-by: David Lamparter --- lib/vector.c | 33 ++++++++++++++++++++------------- lib/vector.h | 7 ++++++- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/lib/vector.c b/lib/vector.c index 4af564a82ff8..38f9b1b85fd4 100644 --- a/lib/vector.c +++ b/lib/vector.c @@ -37,6 +37,7 @@ vector vector_init(unsigned int size) v->alloced = size; v->active = 0; + v->count = 0; v->index = XCALLOC(MTYPE_VECTOR_INDEX, sizeof(void *) * size); return v; } @@ -54,6 +55,7 @@ vector vector_copy(vector v) new->active = v->active; new->alloced = v->alloced; + new->count = v->count; size = sizeof(void *) * (v->alloced); new->index = XCALLOC(MTYPE_VECTOR_INDEX, size); @@ -84,6 +86,9 @@ int vector_empty_slot(vector v) { unsigned int i; + if (v->active == v->count) + return v->active; + if (v->active == 0) return 0; @@ -102,6 +107,10 @@ int vector_set(vector v, void *val) i = vector_empty_slot(v); vector_ensure(v, i); + if (v->index[i]) + v->count--; + if (val) + v->count++; v->index[i] = val; if (v->active <= i) @@ -115,6 +124,10 @@ int vector_set_index(vector v, unsigned int i, void *val) { vector_ensure(v, i); + if (v->index[i]) + v->count--; + if (val) + v->count++; v->index[i] = val; if (v->active <= i) @@ -155,6 +168,9 @@ void vector_unset(vector v, unsigned int i) if (i >= v->alloced) return; + if (v->index[i]) + v->count--; + v->index[i] = NULL; if (i + 1 == v->active) { @@ -169,6 +185,9 @@ void vector_remove(vector v, unsigned int ix) if (ix >= v->active) return; + if (v->index[ix]) + v->count--; + int n = (--v->active) - ix; memmove(&v->index[ix], &v->index[ix + 1], n * sizeof(void *)); @@ -192,6 +211,7 @@ void vector_unset_value(vector v, void *val) for (i = 0; i < v->active; i++) if (v->index[i] == val) { v->index[i] = NULL; + v->count--; break; } @@ -201,19 +221,6 @@ void vector_unset_value(vector v, void *val) while (i && v->index[--i] == NULL); } -/* Count the number of not emplty slot. */ -unsigned int vector_count(vector v) -{ - unsigned int i; - unsigned count = 0; - - for (i = 0; i < v->active; i++) - if (v->index[i] != NULL) - count++; - - return count; -} - void vector_to_array(vector v, void ***dest, int *argc) { *dest = XCALLOC(MTYPE_TMP, sizeof(void *) * v->active); diff --git a/lib/vector.h b/lib/vector.h index 845c8d8b04ef..6208be1cc7f1 100644 --- a/lib/vector.h +++ b/lib/vector.h @@ -32,6 +32,7 @@ extern "C" { struct _vector { unsigned int active; /* number of active slots */ unsigned int alloced; /* number of allocated slot */ + unsigned int count; void **index; /* index to data */ }; typedef struct _vector *vector; @@ -60,7 +61,11 @@ extern void vector_unset_value(vector v, void *val); extern void vector_remove(vector v, unsigned int ix); extern void vector_compact(vector v); -extern unsigned int vector_count(vector v); +static inline unsigned int vector_count(vector v) +{ + return v->count; +} + extern void vector_free(vector v); extern vector vector_copy(vector v); From f60a11883cb426f574dbe5abeff8254148e7c371 Mon Sep 17 00:00:00 2001 From: Igor Ryzhov Date: Wed, 13 Oct 2021 15:06:38 +0300 Subject: [PATCH 157/188] lib: allow to create interfaces in non-existing VRFs It allows FRR to read the interface config even when the necessary VRFs are not yet created and interfaces are in "wrong" VRFs. Currently, such config is rejected. For VRF-lite backend, we don't care at all about the VRF of the inactive interface. When the interface is created in the OS and becomes active, we always use its actual VRF instead of the configured one. So there's no need to reject the config. For netns backend, we may have multiple interfaces with the same name in different VRFs. So we care about the VRF of inactive interfaces. And we must allow to preconfigure the interface in a VRF even before it is moved to the corresponding netns. From now on, we allow to create multiple configs for the same interface name in different VRFs and the necessary config is applied once the OS interface is moved to the corresponding netns. Signed-off-by: Igor Ryzhov --- lib/if.c | 274 ++++++++++++++++------------------------- lib/if.h | 13 +- lib/vrf.c | 22 ++-- lib/zclient.c | 6 +- ospf6d/ospf6_top.c | 12 +- ospfd/ospf_interface.c | 4 +- ospfd/ospf_vty.c | 4 +- pimd/pim_iface.c | 3 +- zebra/if_ioctl.c | 6 +- zebra/if_netlink.c | 12 +- zebra/interface.c | 16 +-- zebra/kernel_socket.c | 6 +- 12 files changed, 150 insertions(+), 228 deletions(-) diff --git a/lib/if.c b/lib/if.c index f316d1a9b74c..cb6270f5ecd3 100644 --- a/lib/if.c +++ b/lib/if.c @@ -45,6 +45,7 @@ DEFINE_MTYPE_STATIC(LIB, NBR_CONNECTED, "Neighbor Connected"); DEFINE_MTYPE(LIB, CONNECTED_LABEL, "Connected interface label"); DEFINE_MTYPE_STATIC(LIB, IF_LINK_PARAMS, "Informational Link Parameters"); +static void if_set_name(struct interface *ifp, const char *name); static struct interface *if_lookup_by_ifindex(ifindex_t ifindex, vrf_id_t vrf_id); static int if_cmp_func(const struct interface *, const struct interface *); @@ -153,16 +154,19 @@ static void ifp_connected_free(void *arg) } /* Create new interface structure. */ -static struct interface *if_new(vrf_id_t vrf_id) +static struct interface *if_new(struct vrf *vrf) { struct interface *ifp; + assert(vrf); + ifp = XCALLOC(MTYPE_IF, sizeof(struct interface)); ifp->ifindex = IFINDEX_INTERNAL; ifp->name[0] = '\0'; - ifp->vrf_id = vrf_id; + ifp->vrf = vrf; + ifp->vrf_id = vrf->vrf_id; ifp->connected = list_new(); ifp->connected->del = ifp_connected_free; @@ -207,11 +211,11 @@ void if_down_via_zapi(struct interface *ifp) (*ifp_master.down_hook)(ifp); } -struct interface *if_create_name(const char *name, vrf_id_t vrf_id) +static struct interface *if_create_name(const char *name, struct vrf *vrf) { struct interface *ifp; - ifp = if_new(vrf_id); + ifp = if_new(vrf); if_set_name(ifp, name); @@ -219,35 +223,23 @@ struct interface *if_create_name(const char *name, vrf_id_t vrf_id) return ifp; } -struct interface *if_create_ifindex(ifindex_t ifindex, vrf_id_t vrf_id) -{ - struct interface *ifp; - - ifp = if_new(vrf_id); - - if_set_index(ifp, ifindex); - - hook_call(if_add, ifp); - return ifp; -} - /* Create new interface structure. */ void if_update_to_new_vrf(struct interface *ifp, vrf_id_t vrf_id) { struct vrf *old_vrf, *vrf; /* remove interface from old master vrf list */ - old_vrf = vrf_lookup_by_id(ifp->vrf_id); - if (old_vrf) { - if (ifp->name[0] != '\0') - IFNAME_RB_REMOVE(old_vrf, ifp); + old_vrf = ifp->vrf; - if (ifp->ifindex != IFINDEX_INTERNAL) - IFINDEX_RB_REMOVE(old_vrf, ifp); - } + if (ifp->name[0] != '\0') + IFNAME_RB_REMOVE(old_vrf, ifp); + + if (ifp->ifindex != IFINDEX_INTERNAL) + IFINDEX_RB_REMOVE(old_vrf, ifp); ifp->vrf_id = vrf_id; vrf = vrf_get(ifp->vrf_id, NULL); + ifp->vrf = vrf; if (ifp->name[0] != '\0') IFNAME_RB_INSERT(vrf, ifp); @@ -261,7 +253,7 @@ void if_update_to_new_vrf(struct interface *ifp, vrf_id_t vrf_id) * the interface and readding it in the new VRF, which would have * several implications. */ - if (yang_module_find("frr-interface")) { + if (!vrf_is_backend_netns() && yang_module_find("frr-interface")) { struct lyd_node *if_dnode; char oldpath[XPATH_MAXLEN]; char newpath[XPATH_MAXLEN]; @@ -304,15 +296,15 @@ void if_delete_retain(struct interface *ifp) void if_delete(struct interface **ifp) { struct interface *ptr = *ifp; - struct vrf *vrf; - - vrf = vrf_lookup_by_id(ptr->vrf_id); - assert(vrf); + struct vrf *vrf = ptr->vrf; IFNAME_RB_REMOVE(vrf, ptr); if (ptr->ifindex != IFINDEX_INTERNAL) IFINDEX_RB_REMOVE(vrf, ptr); + if (!vrf_is_enabled(vrf)) + vrf_delete(vrf); + if_delete_retain(ptr); list_delete(&ptr->connected); @@ -439,7 +431,7 @@ struct interface *if_lookup_by_name_all_vrf(const char *name) if (!name || strnlen(name, INTERFACE_NAMSIZ) == INTERFACE_NAMSIZ) return NULL; - RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) { + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { ifp = if_lookup_by_name_vrf(name, vrf); if (ifp) return ifp; @@ -582,72 +574,58 @@ size_t if_lookup_by_hwaddr(const uint8_t *hw_addr, size_t addrsz, /* Get interface by name if given name interface doesn't exist create one. */ -struct interface *if_get_by_name(const char *name, vrf_id_t vrf_id) +struct interface *if_get_by_name(const char *name, vrf_id_t vrf_id, + const char *vrf_name) { - struct interface *ifp; + struct interface *ifp = NULL; + struct vrf *vrf; switch (vrf_get_backend()) { case VRF_BACKEND_UNKNOWN: case VRF_BACKEND_NETNS: - ifp = if_lookup_by_name(name, vrf_id); - if (ifp) - return ifp; - return if_create_name(name, vrf_id); - case VRF_BACKEND_VRF_LITE: - ifp = if_lookup_by_name_all_vrf(name); + vrf = vrf_get(vrf_id, vrf_name); + assert(vrf); + + ifp = if_lookup_by_name_vrf(name, vrf); if (ifp) { - if (ifp->vrf_id == vrf_id) - return ifp; /* If it came from the kernel or by way of zclient, * believe it and update the ifp accordingly. */ - if_update_to_new_vrf(ifp, vrf_id); + if (ifp->vrf_id != vrf_id && vrf_id != VRF_UNKNOWN) + if_update_to_new_vrf(ifp, vrf_id); + return ifp; } - return if_create_name(name, vrf_id); - } - return NULL; -} - -struct interface *if_get_by_ifindex(ifindex_t ifindex, vrf_id_t vrf_id) -{ - struct interface *ifp; - - switch (vrf_get_backend()) { - case VRF_BACKEND_UNKNOWN: - case VRF_BACKEND_NETNS: - ifp = if_lookup_by_ifindex(ifindex, vrf_id); - if (ifp) - return ifp; - return if_create_ifindex(ifindex, vrf_id); + break; case VRF_BACKEND_VRF_LITE: - ifp = if_lookup_by_index_all_vrf(ifindex); + ifp = if_lookup_by_name_all_vrf(name); if (ifp) { - if (ifp->vrf_id == vrf_id) - return ifp; /* If it came from the kernel or by way of zclient, * believe it and update the ifp accordingly. */ - if_update_to_new_vrf(ifp, vrf_id); + if (ifp->vrf_id != vrf_id && vrf_id != VRF_UNKNOWN) + if_update_to_new_vrf(ifp, vrf_id); + return ifp; } - return if_create_ifindex(ifindex, vrf_id); + + vrf = vrf_get(vrf_id, vrf_name); + assert(vrf); + + break; + default: + return NULL; } - return NULL; + return if_create_name(name, vrf); } int if_set_index(struct interface *ifp, ifindex_t ifindex) { - struct vrf *vrf; - if (ifp->ifindex == ifindex) return 0; - vrf = vrf_get(ifp->vrf_id, NULL); - assert(vrf); - /* * If there is already an interface with this ifindex, we will collide * on insertion, so don't even try. @@ -656,7 +634,7 @@ int if_set_index(struct interface *ifp, ifindex_t ifindex) return -1; if (ifp->ifindex != IFINDEX_INTERNAL) - IFINDEX_RB_REMOVE(vrf, ifp); + IFINDEX_RB_REMOVE(ifp->vrf, ifp); ifp->ifindex = ifindex; @@ -666,30 +644,25 @@ int if_set_index(struct interface *ifp, ifindex_t ifindex) * already an interface with the desired ifindex at the top of * the function. Nevertheless. */ - if (IFINDEX_RB_INSERT(vrf, ifp)) + if (IFINDEX_RB_INSERT(ifp->vrf, ifp)) return -1; } return 0; } -void if_set_name(struct interface *ifp, const char *name) +static void if_set_name(struct interface *ifp, const char *name) { - struct vrf *vrf; - - vrf = vrf_get(ifp->vrf_id, NULL); - assert(vrf); - if (if_cmp_name_func(ifp->name, name) == 0) return; if (ifp->name[0] != '\0') - IFNAME_RB_REMOVE(vrf, ifp); + IFNAME_RB_REMOVE(ifp->vrf, ifp); strlcpy(ifp->name, name, sizeof(ifp->name)); if (ifp->name[0] != '\0') - IFNAME_RB_INSERT(vrf, ifp); + IFNAME_RB_INSERT(ifp->vrf, ifp); } /* Does interface up ? */ @@ -817,15 +790,12 @@ static void if_dump(const struct interface *ifp) struct listnode *node; struct connected *c __attribute__((unused)); - for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, c)) { - struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id); - + for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, c)) zlog_info( "Interface %s vrf %s(%u) index %d metric %d mtu %d mtu6 %d %s", - ifp->name, VRF_LOGNAME(vrf), ifp->vrf_id, ifp->ifindex, + ifp->name, ifp->vrf->name, ifp->vrf_id, ifp->ifindex, ifp->metric, ifp->mtu, ifp->mtu6, if_flag_dump(ifp->flags)); - } } /* Interface printing for all interface. */ @@ -894,16 +864,14 @@ connected_log(struct connected *connected, char *str) { struct prefix *p; struct interface *ifp; - struct vrf *vrf; char logbuf[BUFSIZ]; char buf[BUFSIZ]; ifp = connected->ifp; p = connected->address; - vrf = vrf_lookup_by_id(ifp->vrf_id); snprintf(logbuf, sizeof(logbuf), "%s interface %s vrf %s(%u) %s %pFX ", - str, ifp->name, VRF_LOGNAME(vrf), ifp->vrf_id, + str, ifp->name, ifp->vrf->name, ifp->vrf_id, prefix_family_str(p), p); p = connected->destination; @@ -1059,30 +1027,15 @@ struct connected *connected_get_linklocal(struct interface *ifp) void if_terminate(struct vrf *vrf) { struct interface *ifp; - bool delete; - - /* - * If the default VRF is being terminated or has - * already been terminated it means that - * the program is shutting down and we need to - * delete all the interfaces. Otherwise, we only - * need to move VRF's interfaces to the default VRF. - */ - delete = vrf_is_backend_netns() || vrf->vrf_id == VRF_DEFAULT - || !vrf_lookup_by_id(VRF_DEFAULT); while (!RB_EMPTY(if_name_head, &vrf->ifaces_by_name)) { ifp = RB_ROOT(if_name_head, &vrf->ifaces_by_name); - if (delete) { - if (ifp->node) { - ifp->node->info = NULL; - route_unlock_node(ifp->node); - } - if_delete(&ifp); - } else { - if_update_to_new_vrf(ifp, VRF_DEFAULT); + if (ifp->node) { + ifp->node->info = NULL; + route_unlock_node(ifp->node); } + if_delete(&ifp); } } @@ -1186,6 +1139,25 @@ void if_link_params_free(struct interface *ifp) /* ----------- CLI commands ----------- */ +/* Guess the VRF of an interface. */ +static int vrfname_by_ifname(const char *ifname, const char **vrfname) +{ + struct vrf *vrf; + struct interface *ifp; + int count = 0; + + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { + FOR_ALL_INTERFACES (vrf, ifp) { + if (strmatch(ifp->name, ifname)) { + *vrfname = vrf->name; + count++; + } + } + } + + return count; +} + /* * XPath: /frr-interface:lib/interface */ @@ -1197,12 +1169,9 @@ DEFPY_YANG_NOSH (interface, VRF_CMD_HELP_STR) { char xpath_list[XPATH_MAXLEN]; - vrf_id_t vrf_id; struct interface *ifp; - int ret; - - if (!vrf_name) - vrf_name = VRF_DEFAULT_NAME; + struct vrf *vrf; + int ret, count; /* * This command requires special handling to maintain backward @@ -1211,30 +1180,30 @@ DEFPY_YANG_NOSH (interface, * interface is found, then a new one should be created on the default * VRF. */ - VRF_GET_ID(vrf_id, vrf_name, false); - ifp = if_lookup_by_name_all_vrf(ifname); - if (ifp && ifp->vrf_id != vrf_id) { - struct vrf *vrf; - + if (vrf_is_backend_netns()) { /* - * Special case 1: a VRF name was specified, but the found - * interface is associated to different VRF. Reject the command. + * For backward compatibility, if the VRF name is not specified + * and there is exactly one interface with this name in the + * system, use its VRF. Otherwise fallback to the default VRF. */ - if (vrf_id != VRF_DEFAULT) { - vty_out(vty, "%% interface %s not in %s vrf\n", ifname, - vrf_name); - return CMD_WARNING_CONFIG_FAILED; + if (!vrf_name) { + count = vrfname_by_ifname(ifname, &vrf_name); + if (count != 1) + vrf_name = VRF_DEFAULT_NAME; } - + } else { /* - * Special case 2: a VRF name was *not* specified, and the found - * interface is associated to a VRF other than the default one. - * Update vrf_id and vrf_name to account for that. + * If the interface already exists, use its VRF regardless of + * what user specified. We can't have same interface name in + * different VRFs with VRF-lite backend. */ - vrf = vrf_lookup_by_id(ifp->vrf_id); - assert(vrf); - vrf_id = ifp->vrf_id; - vrf_name = vrf->name; + ifp = if_lookup_by_name_all_vrf(ifname); + if (ifp) { + vrf_name = ifp->vrf->name; + } else { + if (!vrf_name) + vrf_name = VRF_DEFAULT_NAME; + } } snprintf(xpath_list, sizeof(xpath_list), @@ -1252,7 +1221,15 @@ DEFPY_YANG_NOSH (interface, * all interface-level commands are converted to the new * northbound model. */ - ifp = if_lookup_by_name(ifname, vrf_id); + if (vrf_is_backend_netns()) { + vrf = vrf_lookup_by_name(vrf_name); + if (vrf) + ifp = if_lookup_by_name_vrf(ifname, vrf); + else + ifp = NULL; + } else { + ifp = if_lookup_by_name_all_vrf(ifname); + } if (ifp) VTY_PUSH_CONTEXT(INTERFACE_NODE, ifp); } @@ -1397,7 +1374,6 @@ static int lib_interface_create(struct nb_cb_create_args *args) { const char *ifname; const char *vrfname; - struct vrf *vrf; struct interface *ifp; ifname = yang_dnode_get_string(args->dnode, "./name"); @@ -1405,39 +1381,11 @@ static int lib_interface_create(struct nb_cb_create_args *args) switch (args->event) { case NB_EV_VALIDATE: - vrf = vrf_lookup_by_name(vrfname); - if (!vrf) { - zlog_warn("%s: VRF %s doesn't exist", __func__, - vrfname); - return NB_ERR_VALIDATION; - } - if (vrf->vrf_id == VRF_UNKNOWN) { - zlog_warn("%s: VRF %s is not active", __func__, - vrf->name); - return NB_ERR_VALIDATION; - } - - /* if VRF is netns or not yet known - init for instance - * then assumption is that passed config is exact - * then the user intent was not to use an other iface - */ - if (vrf_get_backend() == VRF_BACKEND_VRF_LITE) { - ifp = if_lookup_by_name_all_vrf(ifname); - if (ifp && ifp->vrf_id != vrf->vrf_id) { - zlog_warn( - "%s: interface %s already exists in another VRF", - __func__, ifp->name); - return NB_ERR_VALIDATION; - } - } - break; case NB_EV_PREPARE: case NB_EV_ABORT: break; case NB_EV_APPLY: - vrf = vrf_lookup_by_name(vrfname); - assert(vrf); - ifp = if_get_by_name(ifname, vrf->vrf_id); + ifp = if_get_by_name(ifname, VRF_UNKNOWN, vrfname); ifp->configured = true; nb_running_set_entry(args->dnode, ifp); @@ -1488,7 +1436,7 @@ static const void *lib_interface_get_next(struct nb_cb_get_next_args *args) assert(vrf); pif = RB_MIN(if_name_head, &vrf->ifaces_by_name); } else { - vrf = vrf_lookup_by_id(pif->vrf_id); + vrf = pif->vrf; pif = RB_NEXT(if_name_head, pif); /* if no more interfaces, switch to next vrf */ while (pif == NULL) { @@ -1506,13 +1454,9 @@ static int lib_interface_get_keys(struct nb_cb_get_keys_args *args) { const struct interface *ifp = args->list_entry; - struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id); - - assert(vrf); - args->keys->num = 2; strlcpy(args->keys->key[0], ifp->name, sizeof(args->keys->key[0])); - strlcpy(args->keys->key[1], vrf->name, sizeof(args->keys->key[1])); + strlcpy(args->keys->key[1], ifp->vrf->name, sizeof(args->keys->key[1])); return NB_OK; } diff --git a/lib/if.h b/lib/if.h index 59e75d8b6885..1125acd20421 100644 --- a/lib/if.h +++ b/lib/if.h @@ -293,6 +293,8 @@ struct interface { #endif /* HAVE_NET_RT_IFLIST */ struct route_node *node; + + struct vrf *vrf; vrf_id_t vrf_id; /* @@ -510,11 +512,6 @@ extern int if_cmp_name_func(const char *p1, const char *p2); */ extern void if_update_to_new_vrf(struct interface *, vrf_id_t vrf_id); -/* Create new interface, adds to name list only */ -extern struct interface *if_create_name(const char *name, vrf_id_t vrf_id); - -/* Create new interface, adds to index list only */ -extern struct interface *if_create_ifindex(ifindex_t ifindex, vrf_id_t vrf_id); extern struct interface *if_lookup_by_index(ifindex_t, vrf_id_t vrf_id); extern struct interface *if_vrf_lookup_by_index_next(ifindex_t ifindex, vrf_id_t vrf_id); @@ -532,13 +529,11 @@ struct vrf; extern struct interface *if_lookup_by_name_all_vrf(const char *ifname); extern struct interface *if_lookup_by_name_vrf(const char *name, struct vrf *vrf); extern struct interface *if_lookup_by_name(const char *ifname, vrf_id_t vrf_id); -extern struct interface *if_get_by_name(const char *ifname, vrf_id_t vrf_id); -extern struct interface *if_get_by_ifindex(ifindex_t ifindex, vrf_id_t vrf_id); +extern struct interface *if_get_by_name(const char *ifname, vrf_id_t vrf_id, + const char *vrf_name); /* Sets the index and adds to index list */ extern int if_set_index(struct interface *ifp, ifindex_t ifindex); -/* Sets the name and adds to name list */ -extern void if_set_name(struct interface *ifp, const char *name); /* Delete the interface, but do not free the structure, and leave it in the interface list. It is often advisable to leave the pseudo interface diff --git a/lib/vrf.c b/lib/vrf.c index 198d5253c8ed..6bc10b8cfd28 100644 --- a/lib/vrf.c +++ b/lib/vrf.c @@ -272,32 +272,29 @@ void vrf_delete(struct vrf *vrf) if (vrf_is_enabled(vrf)) vrf_disable(vrf); + if (vrf->vrf_id != VRF_UNKNOWN) { + RB_REMOVE(vrf_id_head, &vrfs_by_id, vrf); + vrf->vrf_id = VRF_UNKNOWN; + } + /* If the VRF is user configured, it'll stick around, just remove * the ID mapping. Interfaces assigned to this VRF should've been * removed already as part of the VRF going down. */ if (vrf_is_user_cfged(vrf)) { - if (vrf->vrf_id != VRF_UNKNOWN) { - /* Delete any VRF interfaces - should be only - * the VRF itself, other interfaces should've - * been moved out of the VRF. - */ - if_terminate(vrf); - RB_REMOVE(vrf_id_head, &vrfs_by_id, vrf); - vrf->vrf_id = VRF_UNKNOWN; - } vrf->ns_ctxt = NULL; return; } + /* Do not delete the VRF if it has interfaces configured in it. */ + if (!RB_EMPTY(if_name_head, &vrf->ifaces_by_name)) + return; + if (vrf_master.vrf_delete_hook) (*vrf_master.vrf_delete_hook)(vrf); QOBJ_UNREG(vrf); - if_terminate(vrf); - if (vrf->vrf_id != VRF_UNKNOWN) - RB_REMOVE(vrf_id_head, &vrfs_by_id, vrf); if (vrf->name[0] != '\0') RB_REMOVE(vrf_name_head, &vrfs_by_name, vrf); @@ -571,6 +568,7 @@ static void vrf_terminate_single(struct vrf *vrf) { /* Clear configured flag and invoke delete. */ UNSET_FLAG(vrf->status, VRF_CONFIGURED); + if_terminate(vrf); vrf_delete(vrf); } diff --git a/lib/zclient.c b/lib/zclient.c index d639fa84b80c..eea118738cde 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -2164,19 +2164,21 @@ static int zclient_interface_add(struct zclient *zclient, vrf_id_t vrf_id) struct interface *ifp; char ifname_tmp[INTERFACE_NAMSIZ + 1] = {}; struct stream *s = zclient->ibuf; + struct vrf *vrf; /* Read interface name. */ STREAM_GET(ifname_tmp, s, INTERFACE_NAMSIZ); /* Lookup/create interface by name. */ - if (!vrf_get(vrf_id, NULL)) { + vrf = vrf_lookup_by_id(vrf_id); + if (!vrf) { zlog_debug( "Rx'd interface add from Zebra, but VRF %u does not exist", vrf_id); return -1; } - ifp = if_get_by_name(ifname_tmp, vrf_id); + ifp = if_get_by_name(ifname_tmp, vrf_id, vrf->name); zebra_interface_if_set_value(s, ifp); diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index 9e3bb4895a82..7e9ed4160d54 100644 --- a/ospf6d/ospf6_top.c +++ b/ospf6d/ospf6_top.c @@ -1032,7 +1032,6 @@ DEFUN_HIDDEN (ospf6_interface_area, struct ospf6_area *oa; struct ospf6_interface *oi; struct interface *ifp; - vrf_id_t vrf_id = VRF_DEFAULT; uint32_t area_id; int format; @@ -1041,11 +1040,8 @@ DEFUN_HIDDEN (ospf6_interface_area, vty_out(vty, "Please, use \"ipv6 ospf6 area\" on an interface instead.\n"); - if (ospf6->vrf_id != VRF_UNKNOWN) - vrf_id = ospf6->vrf_id; - /* find/create ospf6 interface */ - ifp = if_get_by_name(argv[idx_ifname]->arg, vrf_id); + ifp = if_get_by_name(argv[idx_ifname]->arg, ospf6->vrf_id, ospf6->name); oi = (struct ospf6_interface *)ifp->info; if (oi == NULL) oi = ospf6_interface_create(ifp); @@ -1107,18 +1103,14 @@ DEFUN_HIDDEN (no_ospf6_interface_area, struct ospf6_area *oa; struct interface *ifp; uint32_t area_id; - vrf_id_t vrf_id = VRF_DEFAULT; vty_out(vty, "This command is deprecated, because it is not VRF-aware.\n"); vty_out(vty, "Please, use \"no ipv6 ospf6 area\" on an interface instead.\n"); - if (ospf6->vrf_id != VRF_UNKNOWN) - vrf_id = ospf6->vrf_id; - /* find/create ospf6 interface */ - ifp = if_get_by_name(argv[idx_ifname]->arg, vrf_id); + ifp = if_get_by_name(argv[idx_ifname]->arg, ospf6->vrf_id, ospf6->name); if (ifp == NULL) { vty_out(vty, "No such interface %s\n", argv[idx_ifname]->arg); diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c index 81cc34600047..60e109ea8006 100644 --- a/ospfd/ospf_interface.c +++ b/ospfd/ospf_interface.c @@ -915,9 +915,9 @@ struct ospf_interface *ospf_vl_new(struct ospf *ospf, ospf->vrf_id); snprintf(ifname, sizeof(ifname), "VLINK%u", vlink_count); - vi = if_create_name(ifname, ospf->vrf_id); + vi = if_get_by_name(ifname, ospf->vrf_id, ospf->name); /* - * if_create_name sets ZEBRA_INTERFACE_LINKDETECTION + * if_get_by_name sets ZEBRA_INTERFACE_LINKDETECTION * virtual links don't need this. */ UNSET_FLAG(vi->status, ZEBRA_INTERFACE_LINKDETECTION); diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 9863a101153f..64d3b7a02817 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -445,7 +445,7 @@ DEFUN_HIDDEN (ospf_passive_interface_addr, "Please, use \"ip ospf passive\" on an interface instead.\n"); if (ospf->vrf_id != VRF_UNKNOWN) - ifp = if_get_by_name(argv[1]->arg, ospf->vrf_id); + ifp = if_get_by_name(argv[1]->arg, ospf->vrf_id, ospf->name); if (ifp == NULL) { vty_out(vty, "interface %s not found.\n", (char *)argv[1]->arg); @@ -506,7 +506,7 @@ DEFUN_HIDDEN (no_ospf_passive_interface, "Please, use \"no ip ospf passive\" on an interface instead.\n"); if (ospf->vrf_id != VRF_UNKNOWN) - ifp = if_get_by_name(argv[2]->arg, ospf->vrf_id); + ifp = if_get_by_name(argv[2]->arg, ospf->vrf_id, ospf->name); if (ifp == NULL) { vty_out(vty, "interface %s not found.\n", (char *)argv[2]->arg); diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index eb19cf4ddfda..5e311d101a10 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -1482,7 +1482,8 @@ void pim_if_create_pimreg(struct pim_instance *pim) snprintf(pimreg_name, sizeof(pimreg_name), "pimreg%u", pim->vrf->data.l.table_id); - pim->regiface = if_create_name(pimreg_name, pim->vrf->vrf_id); + pim->regiface = if_get_by_name(pimreg_name, pim->vrf->vrf_id, + pim->vrf->name); pim->regiface->ifindex = PIM_OIF_PIM_REGISTER_VIF; pim_if_new(pim->regiface, false, false, true, diff --git a/zebra/if_ioctl.c b/zebra/if_ioctl.c index 14d8ac442eba..c3faf22d1727 100644 --- a/zebra/if_ioctl.c +++ b/zebra/if_ioctl.c @@ -109,7 +109,8 @@ static int interface_list_ioctl(void) unsigned int size; ifreq = (struct ifreq *)((caddr_t)ifconf.ifc_req + n); - ifp = if_get_by_name(ifreq->ifr_name, VRF_DEFAULT); + ifp = if_get_by_name(ifreq->ifr_name, VRF_DEFAULT, + VRF_DEFAULT_NAME); if_add_update(ifp); size = ifreq->ifr_addr.sa_len; if (size < sizeof(ifreq->ifr_addr)) @@ -119,7 +120,8 @@ static int interface_list_ioctl(void) } #else for (n = 0; n < ifconf.ifc_len; n += sizeof(struct ifreq)) { - ifp = if_get_by_name(ifreq->ifr_name, VRF_DEFAULT); + ifp = if_get_by_name(ifreq->ifr_name, VRF_DEFAULT, + VRF_DEFAULT_NAME); if_add_update(ifp); ifreq++; } diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index fa3aabb19540..187cd10e9ce2 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -972,17 +972,9 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup) link_nsid = ns_id_get_absolute(ns_id, link_nsid); } - /* Add interface. - * We add by index first because in some cases such as the master - * interface, we have the index before we have the name. Fixing - * back references on the slave interfaces is painful if not done - * this way, i.e. by creating by ifindex. - */ - ifp = if_get_by_ifindex(ifi->ifi_index, vrf_id); + ifp = if_get_by_name(name, vrf_id, NULL); set_ifindex(ifp, ifi->ifi_index, zns); /* add it to ns struct */ - if_set_name(ifp, name); - ifp->flags = ifi->ifi_flags & 0x0000fffff; ifp->mtu6 = ifp->mtu = *(uint32_t *)RTA_DATA(tb[IFLA_MTU]); ifp->metric = 0; @@ -1814,7 +1806,7 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) if (ifp == NULL) { /* unknown interface */ - ifp = if_get_by_name(name, vrf_id); + ifp = if_get_by_name(name, vrf_id, NULL); } else { /* pre-configured interface, learnt now */ if (ifp->vrf_id != vrf_id) diff --git a/zebra/interface.c b/zebra/interface.c index a68d00d55ce0..595862a6c99d 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -1616,7 +1616,6 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp) struct listnode *node; struct route_node *rn; struct zebra_if *zebra_if; - struct vrf *vrf; char pd_buf[ZEBRA_PROTODOWN_RC_STR_LEN]; zebra_if = ifp->info; @@ -1644,8 +1643,7 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp) zebra_ptm_show_status(vty, NULL, ifp); - vrf = vrf_lookup_by_id(ifp->vrf_id); - vty_out(vty, " vrf: %s\n", vrf->name); + vty_out(vty, " vrf: %s\n", ifp->vrf->name); if (ifp->desc) vty_out(vty, " Description: %s\n", ifp->desc); @@ -1941,7 +1939,6 @@ static void if_dump_vty_json(struct vty *vty, struct interface *ifp, struct listnode *node; struct route_node *rn; struct zebra_if *zebra_if; - struct vrf *vrf; char pd_buf[ZEBRA_PROTODOWN_RC_STR_LEN]; char buf[BUFSIZ]; json_object *json_if; @@ -1979,8 +1976,7 @@ static void if_dump_vty_json(struct vty *vty, struct interface *ifp, zebra_ptm_show_status(vty, json, ifp); - vrf = vrf_lookup_by_id(ifp->vrf_id); - json_object_string_add(json_if, "vrfName", vrf->name); + json_object_string_add(json_if, "vrfName", ifp->vrf->name); if (ifp->desc) json_object_string_add(json_if, "description", ifp->desc); @@ -4206,21 +4202,19 @@ static int link_params_config_write(struct vty *vty, struct interface *ifp) static int if_config_write(struct vty *vty) { - struct vrf *vrf0; + struct vrf *vrf; struct interface *ifp; zebra_ptm_write(vty); - RB_FOREACH (vrf0, vrf_name_head, &vrfs_by_name) - FOR_ALL_INTERFACES (vrf0, ifp) { + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) + FOR_ALL_INTERFACES (vrf, ifp) { struct zebra_if *if_data; struct listnode *addrnode; struct connected *ifc; struct prefix *p; - struct vrf *vrf; if_data = ifp->info; - vrf = vrf_lookup_by_id(ifp->vrf_id); if (ifp->vrf_id == VRF_DEFAULT) vty_frame(vty, "interface %s\n", ifp->name); diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index d9c69ceb6d7e..2db3e6e9047a 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -443,7 +443,8 @@ static int ifan_read(struct if_announcemsghdr *ifan) __func__, ifan->ifan_index, ifan->ifan_name); /* Create Interface */ - ifp = if_get_by_name(ifan->ifan_name, VRF_DEFAULT); + ifp = if_get_by_name(ifan->ifan_name, VRF_DEFAULT, + VRF_DEFAULT_NAME); if_set_index(ifp, ifan->ifan_index); if_get_metric(ifp); @@ -624,7 +625,8 @@ int ifm_read(struct if_msghdr *ifm) if (ifp == NULL) { /* Interface that zebra was not previously aware of, so * create. */ - ifp = if_create_name(ifname, VRF_DEFAULT); + ifp = if_get_by_name(ifname, VRF_DEFAULT, + VRF_DEFAULT_NAME); if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug("%s: creating ifp for ifindex %d", __func__, ifm->ifm_index); From 2a342b352a00d3ca77318b523a91257ca20952b3 Mon Sep 17 00:00:00 2001 From: Donatas Abraitis Date: Tue, 19 Oct 2021 15:31:39 +0300 Subject: [PATCH 158/188] bgpd: Add autocomplete for as-path filters ``` exit1-debian-9# show bgp as-path-access-list AS_PATH_FILTER_NAME AS path access list name acl1 acl2 json JavaScript Object Notation exit1-debian-9(config)# route-map testas permit 10 exit1-debian-9(config-route-map)# match as-path ? AS_PATH_FILTER_NAME AS path access-list name acl1 acl2 ``` Signed-off-by: Donatas Abraitis --- bgpd/bgp_filter.c | 30 +++++++++++++++++++++++------- bgpd/bgp_routemap.c | 4 ++-- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/bgpd/bgp_filter.c b/bgpd/bgp_filter.c index 641cc7605fd1..7dda4f0180c5 100644 --- a/bgpd/bgp_filter.c +++ b/bgpd/bgp_filter.c @@ -440,7 +440,7 @@ bool config_bgp_aspath_validate(const char *regstr) } DEFUN(as_path, bgp_as_path_cmd, - "bgp as-path access-list WORD [seq (0-4294967295)] LINE...", + "bgp as-path access-list AS_PATH_FILTER_NAME [seq (0-4294967295)] LINE...", BGP_STR "BGP autonomous system path filter\n" "Specify an access list name\n" @@ -460,7 +460,7 @@ DEFUN(as_path, bgp_as_path_cmd, int64_t seqnum = ASPATH_SEQ_NUMBER_AUTO; /* Retrieve access list name */ - argv_find(argv, argc, "WORD", &idx); + argv_find(argv, argc, "AS_PATH_FILTER_NAME", &idx); char *alname = argv[idx]->arg; if (argv_find(argv, argc, "(0-4294967295)", &idx)) @@ -509,7 +509,7 @@ DEFUN(as_path, bgp_as_path_cmd, } DEFUN(no_as_path, no_bgp_as_path_cmd, - "no bgp as-path access-list WORD [seq (0-4294967295)] LINE...", + "no bgp as-path access-list AS_PATH_FILTER_NAME [seq (0-4294967295)] LINE...", NO_STR BGP_STR "BGP autonomous system path filter\n" @@ -529,7 +529,7 @@ DEFUN(no_as_path, no_bgp_as_path_cmd, regex_t *regex; char *aslistname = - argv_find(argv, argc, "WORD", &idx) ? argv[idx]->arg : NULL; + argv_find(argv, argc, "AS_PATH_FILTER_NAME", &idx) ? argv[idx]->arg : NULL; /* Lookup AS list from AS path list. */ aslist = as_list_lookup(aslistname); @@ -586,7 +586,7 @@ DEFUN(no_as_path, no_bgp_as_path_cmd, DEFUN (no_as_path_all, no_bgp_as_path_all_cmd, - "no bgp as-path access-list WORD", + "no bgp as-path access-list AS_PATH_FILTER_NAME", NO_STR BGP_STR "BGP autonomous system path filter\n" @@ -653,7 +653,7 @@ static void as_list_show_all(struct vty *vty, json_object *json) DEFUN (show_as_path_access_list, show_bgp_as_path_access_list_cmd, - "show bgp as-path-access-list WORD [json]", + "show bgp as-path-access-list AS_PATH_FILTER_NAME [json]", SHOW_STR BGP_STR "List AS path access lists\n" @@ -684,7 +684,7 @@ DEFUN (show_as_path_access_list, ALIAS (show_as_path_access_list, show_ip_as_path_access_list_cmd, - "show ip as-path-access-list WORD [json]", + "show ip as-path-access-list AS_PATH_FILTER_NAME [json]", SHOW_STR IP_STR "List AS path access lists\n" @@ -753,6 +753,20 @@ static struct cmd_node as_list_node = { .config_write = config_write_as_list, }; +static void bgp_aspath_filter_cmd_completion(vector comps, + struct cmd_token *token) +{ + struct as_list *aslist; + + for (aslist = as_list_master.str.head; aslist; aslist = aslist->next) + vector_set(comps, XSTRDUP(MTYPE_COMPLETION, aslist->name)); +} + +static const struct cmd_variable_handler aspath_filter_handlers[] = { + {.tokenname = "AS_PATH_FILTER_NAME", + .completions = bgp_aspath_filter_cmd_completion}, + {.completions = NULL}}; + /* Register functions. */ void bgp_filter_init(void) { @@ -766,6 +780,8 @@ void bgp_filter_init(void) install_element(VIEW_NODE, &show_ip_as_path_access_list_cmd); install_element(VIEW_NODE, &show_bgp_as_path_access_list_all_cmd); install_element(VIEW_NODE, &show_ip_as_path_access_list_all_cmd); + + cmd_variable_handler_register(aspath_filter_handlers); } void bgp_filter_reset(void) diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 2f37367a8fba..75dbc7f3e386 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -4927,7 +4927,7 @@ DEFUN_YANG (no_match_ecommunity, DEFUN_YANG (match_aspath, match_aspath_cmd, - "match as-path WORD", + "match as-path AS_PATH_FILTER_NAME", MATCH_STR "Match BGP AS path list\n" "AS path access-list name\n") @@ -4950,7 +4950,7 @@ DEFUN_YANG (match_aspath, DEFUN_YANG (no_match_aspath, no_match_aspath_cmd, - "no match as-path [WORD]", + "no match as-path [AS_PATH_FILTER_NAME]", NO_STR MATCH_STR "Match BGP AS path list\n" From 9de36e51fee47cf4ce31df420940af6a51528d8b Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 29 Sep 2021 22:13:01 +0200 Subject: [PATCH 159/188] tests: fix leak in test code Even if it doesn't matter for an unit test in general, it hides actual leaks in the code being tested. Fix so any leaks will be actual bugs. (Currently there aren't any, yay.) Signed-off-by: David Lamparter --- tests/lib/test_typelist.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/lib/test_typelist.h b/tests/lib/test_typelist.h index 379a2396b46f..be37a9e6c9c8 100644 --- a/tests/lib/test_typelist.h +++ b/tests/lib/test_typelist.h @@ -239,6 +239,13 @@ static void concat(test_, TYPE)(void) ts_hash_headx( &head, "swap2b", "a538546a6e6ab0484e925940aa8dd02fd934408bbaed8cb66a0721841584d838"); + + while (list_pop(&other)) + ; + list_fini(&other); + prng_free(prng_swap); + + ts_ref("swap-cleanup"); #endif /* !IS_ATOMIC */ k = 0; @@ -449,6 +456,13 @@ static void concat(test_, TYPE)(void) ts_hash_head( &head, "swap2b", "eabfcf1413936daaf20965abced95762f45110a6619b84aac7d38481bce4ea19"); + + while (list_pop(&other)) + ; + list_fini(&other); + prng_free(prng_swap); + + ts_ref("swap-cleanup"); #endif for (i = 0; i < NITEM / 2; i++) { @@ -650,6 +664,7 @@ static void concat(test_, TYPE)(void) list_fini(&head); ts_ref("fini"); ts_end(); + prng_free(prng); printfrr("%s end\n", str(TYPE)); } From 4a1b3289c7a8abc9858bfd1ac2ced35e8d20dd68 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 29 Sep 2021 20:45:34 +0200 Subject: [PATCH 160/188] lib: null out deleted pointers in typesafe containers Some of the typesafe containers didn't null out their innards of items after an item was deleted or popped off the container. This is both a bit unsafe as well as hinders the upcoming _member() from working efficiently. Signed-off-by: David Lamparter --- lib/typerb.c | 2 ++ lib/typesafe.h | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/lib/typerb.c b/lib/typerb.c index 092faa4cc9a5..151d91ce20b7 100644 --- a/lib/typerb.c +++ b/lib/typerb.c @@ -45,6 +45,7 @@ #include "config.h" #endif +#include #include "typerb.h" #define RB_BLACK 0 @@ -330,6 +331,7 @@ rbe_remove(struct rbt_tree *rbt, struct rb_entry *rbe) rbe_remove_color(rbt, parent, child); rbt->count--; + memset(old, 0, sizeof(*old)); return (old); } diff --git a/lib/typesafe.h b/lib/typesafe.h index ecac1a4381c9..6d6fcf282eac 100644 --- a/lib/typesafe.h +++ b/lib/typesafe.h @@ -169,6 +169,7 @@ macro_inline type *prefix ## _del(struct prefix##_head *h, type *item) \ *iter = item->field.si.next; \ if (!item->field.si.next) \ h->sh.last_next = iter; \ + item->field.si.next = NULL; \ return item; \ } \ macro_inline type *prefix ## _pop(struct prefix##_head *h) \ @@ -180,6 +181,7 @@ macro_inline type *prefix ## _pop(struct prefix##_head *h) \ h->sh.first = sitem->next; \ if (h->sh.first == NULL) \ h->sh.last_next = &h->sh.first; \ + sitem->next = NULL; \ return container_of(sitem, type, field.si); \ } \ macro_inline void prefix ## _swap_all(struct prefix##_head *a, \ @@ -321,6 +323,7 @@ macro_inline type *prefix ## _pop(struct prefix##_head *h) \ ditem->prev->next = ditem->next; \ ditem->next->prev = ditem->prev; \ h->dh.count--; \ + ditem->prev = ditem->next = NULL; \ return container_of(ditem, type, field.di); \ } \ macro_inline void prefix ## _swap_all(struct prefix##_head *a, \ @@ -565,6 +568,7 @@ macro_inline type *prefix ## _del(struct prefix##_head *h, type *item) \ return NULL; \ h->sh.count--; \ *iter = item->field.si.next; \ + item->field.si.next = NULL; \ return item; \ } \ macro_inline type *prefix ## _pop(struct prefix##_head *h) \ From f45897e45c57db80b21e31d44723733a17bfac54 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sat, 27 Mar 2021 22:05:07 +0100 Subject: [PATCH 161/188] lib: typesafe *_member() This provides a "is this item on this list" check, which may or may not be faster than using *_find() for the same purpose. (If the container has no faster way of doing it, it falls back to using *_find().) Signed-off-by: David Lamparter --- lib/typerb.c | 8 +++++ lib/typerb.h | 7 ++++ lib/typesafe.c | 38 +++++++++++++++++++++ lib/typesafe.h | 69 ++++++++++++++++++++++++++++++++++++++- tests/lib/test_typelist.h | 57 ++++++++++++++++++++++++++++++-- 5 files changed, 175 insertions(+), 4 deletions(-) diff --git a/lib/typerb.c b/lib/typerb.c index 151d91ce20b7..e1346df191cc 100644 --- a/lib/typerb.c +++ b/lib/typerb.c @@ -480,3 +480,11 @@ struct rb_entry *typed_rb_min(const struct rbt_tree *rbt) return parent; } + +bool typed_rb_member(const struct typed_rb_root *rbt, + const struct typed_rb_entry *rbe) +{ + while (rbe->rbt_parent) + rbe = rbe->rbt_parent; + return rbe == rbt->rbt_root; +} diff --git a/lib/typerb.h b/lib/typerb.h index cbed8d489375..d22d864aae86 100644 --- a/lib/typerb.h +++ b/lib/typerb.h @@ -62,6 +62,8 @@ const struct typed_rb_entry *typed_rb_find_lt(const struct typed_rb_root *rbt, const struct typed_rb_entry *b)); struct typed_rb_entry *typed_rb_min(const struct typed_rb_root *rbt); struct typed_rb_entry *typed_rb_next(const struct typed_rb_entry *rbe); +bool typed_rb_member(const struct typed_rb_root *rbt, + const struct typed_rb_entry *rbe); #define _PREDECL_RBTREE(prefix) \ struct prefix ## _head { struct typed_rb_root rr; }; \ @@ -142,6 +144,11 @@ macro_pure size_t prefix ## _count(const struct prefix##_head *h) \ { \ return h->rr.count; \ } \ +macro_pure bool prefix ## _member(const struct prefix##_head *h, \ + const type *item) \ +{ \ + return typed_rb_member(&h->rr, &item->field.re); \ +} \ MACRO_REQUIRE_SEMICOLON() /* end */ #define PREDECL_RBTREE_UNIQ(prefix) \ diff --git a/lib/typesafe.c b/lib/typesafe.c index 76705fad0d36..f886c5bdf6fe 100644 --- a/lib/typesafe.c +++ b/lib/typesafe.c @@ -29,6 +29,44 @@ DEFINE_MTYPE_STATIC(LIB, TYPEDHASH_BUCKET, "Typed-hash bucket"); DEFINE_MTYPE_STATIC(LIB, SKIPLIST_OFLOW, "Skiplist overflow"); DEFINE_MTYPE_STATIC(LIB, HEAP_ARRAY, "Typed-heap array"); +bool typesafe_list_member(const struct slist_head *head, + const struct slist_item *item) +{ + struct slist_item *fromhead = head->first; + struct slist_item **fromnext = (struct slist_item **)&item->next; + + while (fromhead) { + if (fromhead == item || fromnext == head->last_next) + return true; + + fromhead = fromhead->next; + if (!*fromnext) + break; + fromnext = &(*fromnext)->next; + } + + return false; +} + +bool typesafe_dlist_member(const struct dlist_head *head, + const struct dlist_item *item) +{ + const struct dlist_item *fromhead = head->hitem.next; + const struct dlist_item *fromitem = item->next; + + if (!item->prev || !item->next) + return false; + + while (fromhead != &head->hitem && fromitem != item) { + if (fromitem == &head->hitem || fromhead == item) + return true; + fromhead = fromhead->next; + fromitem = fromitem->next; + } + + return false; +} + #if 0 static void hash_consistency_check(struct thash_head *head) { diff --git a/lib/typesafe.h b/lib/typesafe.h index 6d6fcf282eac..ecf7d10eb1a9 100644 --- a/lib/typesafe.h +++ b/lib/typesafe.h @@ -78,8 +78,34 @@ macro_inline type *prefix ## _find_gteq(struct prefix##_head *h, \ } \ /* ... */ +/* *_member via find - when there is no better membership check than find() */ +#define TYPESAFE_MEMBER_VIA_FIND(prefix, type) \ +macro_inline bool prefix ## _member(struct prefix##_head *h, \ + const type *item) \ +{ \ + return item == prefix ## _const_find(h, item); \ +} \ +/* ... */ + +/* *_member via find_gteq - same for non-unique containers */ +#define TYPESAFE_MEMBER_VIA_FIND_GTEQ(prefix, type, cmpfn) \ +macro_inline bool prefix ## _member(struct prefix##_head *h, \ + const type *item) \ +{ \ + const type *iter; \ + for (iter = prefix ## _const_find_gteq(h, item); iter; \ + iter = prefix ## _const_next(h, iter)) { \ + if (iter == item) \ + return true; \ + if (cmpfn(iter, item) > 0) \ + break; \ + } \ + return false; \ +} \ +/* ... */ + /* SWAP_ALL_SIMPLE = for containers where the items don't point back to the - * head *AND* the head doesn'T points to itself (= everything except LIST, + * head *AND* the head doesn't point to itself (= everything except LIST, * DLIST and SKIPLIST), just switch out the entire head */ #define TYPESAFE_SWAP_ALL_SIMPLE(prefix) \ @@ -116,6 +142,9 @@ static inline void typesafe_list_add(struct slist_head *head, head->count++; } +extern bool typesafe_list_member(const struct slist_head *head, + const struct slist_item *item); + /* use as: * * PREDECL_LIST(namelist); @@ -218,6 +247,11 @@ macro_pure size_t prefix ## _count(const struct prefix##_head *h) \ { \ return h->sh.count; \ } \ +macro_pure bool prefix ## _member(const struct prefix##_head *h, \ + const type *item) \ +{ \ + return typesafe_list_member(&h->sh, &item->field.si); \ +} \ MACRO_REQUIRE_SEMICOLON() /* end */ /* don't use these structs directly */ @@ -269,6 +303,9 @@ static inline void typesafe_dlist_swap_all(struct dlist_head *a, } } +extern bool typesafe_dlist_member(const struct dlist_head *head, + const struct dlist_item *item); + /* double-linked list, for fast item deletion */ #define PREDECL_DLIST(prefix) \ @@ -357,6 +394,11 @@ macro_pure size_t prefix ## _count(const struct prefix##_head *h) \ { \ return h->dh.count; \ } \ +macro_pure bool prefix ## _member(const struct prefix##_head *h, \ + const type *item) \ +{ \ + return typesafe_dlist_member(&h->dh, &item->field.di); \ +} \ MACRO_REQUIRE_SEMICOLON() /* end */ /* note: heap currently caps out at 4G items */ @@ -466,6 +508,14 @@ macro_pure size_t prefix ## _count(const struct prefix##_head *h) \ { \ return h->hh.count; \ } \ +macro_pure bool prefix ## _member(const struct prefix##_head *h, \ + const type *item) \ +{ \ + uint32_t idx = item->field.hi.index; \ + if (idx >= h->hh.count) \ + return false; \ + return h->hh.array[idx] == &item->field.hi; \ +} \ MACRO_REQUIRE_SEMICOLON() /* end */ extern void typesafe_heap_resize(struct heap_head *head, bool grow); @@ -622,6 +672,7 @@ macro_inline const type *prefix ## _const_find(const struct prefix##_head *h, \ return container_of(sitem, type, field.si); \ } \ TYPESAFE_FIND(prefix, type) \ +TYPESAFE_MEMBER_VIA_FIND(prefix, type) \ MACRO_REQUIRE_SEMICOLON() /* end */ #define DECLARE_SORTLIST_NONUNIQ(prefix, type, field, cmpfn) \ @@ -637,6 +688,7 @@ macro_inline int _ ## prefix ## _cmp(const type *a, const type *b) \ return 0; \ } \ _DECLARE_SORTLIST(prefix, type, field, cmpfn, _ ## prefix ## _cmp); \ +TYPESAFE_MEMBER_VIA_FIND_GTEQ(prefix, type, cmpfn) \ MACRO_REQUIRE_SEMICOLON() /* end */ @@ -803,6 +855,19 @@ macro_pure size_t prefix ## _count(const struct prefix##_head *h) \ { \ return h->hh.count; \ } \ +macro_pure bool prefix ## _member(const struct prefix##_head *h, \ + const type *item) \ +{ \ + uint32_t hval = item->field.hi.hashval, hbits = HASH_KEY(h->hh, hval); \ + const struct thash_item *hitem = h->hh.entries[hbits]; \ + while (hitem && hitem->hashval < hval) \ + hitem = hitem->next; \ + for (hitem = h->hh.entries[hbits]; hitem && hitem->hashval <= hval; \ + hitem = hitem->next) \ + if (hitem == &item->field.hi) \ + return true; \ + return false; \ +} \ MACRO_REQUIRE_SEMICOLON() /* end */ /* skiplist, sorted. @@ -941,6 +1006,7 @@ macro_inline const type *prefix ## _const_find(const struct prefix##_head *h, \ return container_of_null(sitem, type, field.si); \ } \ TYPESAFE_FIND(prefix, type) \ +TYPESAFE_MEMBER_VIA_FIND(prefix, type) \ \ _DECLARE_SKIPLIST(prefix, type, field, \ prefix ## __cmp, prefix ## __cmp); \ @@ -972,6 +1038,7 @@ macro_inline int prefix ## __cmp_uq(const struct sskip_item *a, \ \ _DECLARE_SKIPLIST(prefix, type, field, \ prefix ## __cmp, prefix ## __cmp_uq); \ +TYPESAFE_MEMBER_VIA_FIND_GTEQ(prefix, type, cmpfn) \ MACRO_REQUIRE_SEMICOLON() /* end */ diff --git a/tests/lib/test_typelist.h b/tests/lib/test_typelist.h index be37a9e6c9c8..a12a995bf6f3 100644 --- a/tests/lib/test_typelist.h +++ b/tests/lib/test_typelist.h @@ -39,6 +39,7 @@ #define list_find concat(TYPE, _find) #define list_find_lt concat(TYPE, _find_lt) #define list_find_gteq concat(TYPE, _find_gteq) +#define list_member concat(TYPE, _member) #define list_del concat(TYPE, _del) #define list_pop concat(TYPE, _pop) #define list_swap_all concat(TYPE, _swap_all) @@ -301,7 +302,7 @@ static void concat(test_, TYPE)(void) #elif IS_HEAP(REALTYPE) /* heap - partially sorted. */ prev = NULL; - l = k / 2; + l = k / 4; for (i = 0; i < l; i++) { item = list_pop(&head); if (prev) @@ -310,7 +311,24 @@ static void concat(test_, TYPE)(void) k--; prev = item; } - ts_hash("pop", NULL); + ts_hash("pop#1", NULL); + + for (i = 0; i < NITEM; i++) + assertf(list_member(&head, &itm[i]) == itm[i].scratchpad, + "%zu should:%d is:%d", i, itm[i].scratchpad, + list_member(&head, &itm[i])); + ts_hash("member", NULL); + + l = k / 2; + for (; i < l; i++) { + item = list_pop(&head); + if (prev) + assert(prev->val < item->val); + item->scratchpad = 0; + k--; + prev = item; + } + ts_hash("pop#2", NULL); #else /* !IS_UNIQ(REALTYPE) && !IS_HEAP(REALTYPE) */ for (i = 0; i < NITEM; i++) { @@ -387,6 +405,14 @@ static void concat(test_, TYPE)(void) assert(l + list_count(&head) == k); ts_hashx("del", "cb2e5d80f08a803ef7b56c15e981b681adcea214bebc2f55e12e0bfb242b07ca"); +#if !IS_ATOMIC(REALTYPE) + for (i = 0; i < NITEM; i++) + assertf(list_member(&head, &itm[i]) == itm[i].scratchpad, + "%zu should:%d is:%d", i, itm[i].scratchpad, + list_member(&head, &itm[i])); + ts_hashx("member", "cb2e5d80f08a803ef7b56c15e981b681adcea214bebc2f55e12e0bfb242b07ca"); +#endif + frr_each_safe(list, &head, item) { assert(item->scratchpad != 0); @@ -475,7 +501,31 @@ static void concat(test_, TYPE)(void) } ts_hash("del-prng", "86d568a95eb429dab3162976c5a5f3f75aabc835932cd682aa280b6923549564"); +#if !IS_ATOMIC(REALTYPE) + for (i = 0; i < NITEM; i++) + assertf(list_member(&head, &itm[i]) == itm[i].scratchpad, + "%zu should:%d is:%d", i, itm[i].scratchpad, + list_member(&head, &itm[i])); + ts_hash("member", "86d568a95eb429dab3162976c5a5f3f75aabc835932cd682aa280b6923549564"); +#endif + l = 0; + while (l < (k / 4) && (prev = list_pop(&head))) { + assert(prev->scratchpad != 0); + + prev->scratchpad = 0; + l++; + } + ts_hash("pop#1", "42b8950c880535b2d2e0c980f9845f7841ecf675c0fb9801aec4170d2036349d"); + +#if !IS_ATOMIC(REALTYPE) + for (i = 0; i < NITEM; i++) + assertf(list_member(&head, &itm[i]) == itm[i].scratchpad, + "%zu should:%d is:%d", i, itm[i].scratchpad, + list_member(&head, &itm[i])); + ts_hash("member", "42b8950c880535b2d2e0c980f9845f7841ecf675c0fb9801aec4170d2036349d"); +#endif + while ((item = list_pop(&head))) { assert(item->scratchpad != 0); @@ -485,7 +535,7 @@ static void concat(test_, TYPE)(void) assert(l == k); assert(list_count(&head) == 0); assert(list_first(&head) == NULL); - ts_hash("pop", "df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119"); + ts_hash("pop#2", "df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119"); prng_free(prng); prng = prng_new(0x1e5a2d69); @@ -695,6 +745,7 @@ static void concat(test_, TYPE)(void) #undef list_find #undef list_find_lt #undef list_find_gteq +#undef list_member #undef list_del #undef list_pop #undef list_swap_all From d259ca0989c793767c912622437c3c5b2c6d84b2 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 29 Sep 2021 22:15:11 +0200 Subject: [PATCH 162/188] lib: use sentinel for single-linked lists Using a non-NULL sentinel allows distinguishing between "end of list" and "item not on any list". It's a compare either way, just the value is different. Signed-off-by: David Lamparter --- lib/typesafe.c | 6 ++++-- lib/typesafe.h | 27 +++++++++++++++++++-------- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/lib/typesafe.c b/lib/typesafe.c index f886c5bdf6fe..f90b59daf0c3 100644 --- a/lib/typesafe.c +++ b/lib/typesafe.c @@ -29,18 +29,20 @@ DEFINE_MTYPE_STATIC(LIB, TYPEDHASH_BUCKET, "Typed-hash bucket"); DEFINE_MTYPE_STATIC(LIB, SKIPLIST_OFLOW, "Skiplist overflow"); DEFINE_MTYPE_STATIC(LIB, HEAP_ARRAY, "Typed-heap array"); +struct slist_item typesafe_slist_sentinel = { NULL }; + bool typesafe_list_member(const struct slist_head *head, const struct slist_item *item) { struct slist_item *fromhead = head->first; struct slist_item **fromnext = (struct slist_item **)&item->next; - while (fromhead) { + while (fromhead != _SLIST_LAST) { if (fromhead == item || fromnext == head->last_next) return true; fromhead = fromhead->next; - if (!*fromnext) + if (!*fromnext || *fromnext == _SLIST_LAST) break; fromnext = &(*fromnext)->next; } diff --git a/lib/typesafe.h b/lib/typesafe.h index ecf7d10eb1a9..b03934b96494 100644 --- a/lib/typesafe.h +++ b/lib/typesafe.h @@ -132,6 +132,10 @@ struct slist_head { size_t count; }; +/* this replaces NULL as the value for ->next on the last item. */ +extern struct slist_item typesafe_slist_sentinel; +#define _SLIST_LAST &typesafe_slist_sentinel + static inline void typesafe_list_add(struct slist_head *head, struct slist_item **pos, struct slist_item *item) { @@ -165,6 +169,7 @@ MACRO_REQUIRE_SEMICOLON() /* end */ macro_inline void prefix ## _init(struct prefix##_head *h) \ { \ memset(h, 0, sizeof(*h)); \ + h->sh.first = _SLIST_LAST; \ h->sh.last_next = &h->sh.first; \ } \ macro_inline void prefix ## _fini(struct prefix##_head *h) \ @@ -190,13 +195,13 @@ macro_inline void prefix ## _add_after(struct prefix##_head *h, \ macro_inline type *prefix ## _del(struct prefix##_head *h, type *item) \ { \ struct slist_item **iter = &h->sh.first; \ - while (*iter && *iter != &item->field.si) \ + while (*iter != _SLIST_LAST && *iter != &item->field.si) \ iter = &(*iter)->next; \ - if (!*iter) \ + if (*iter == _SLIST_LAST) \ return NULL; \ h->sh.count--; \ *iter = item->field.si.next; \ - if (!item->field.si.next) \ + if (item->field.si.next == _SLIST_LAST) \ h->sh.last_next = iter; \ item->field.si.next = NULL; \ return item; \ @@ -204,11 +209,11 @@ macro_inline type *prefix ## _del(struct prefix##_head *h, type *item) \ macro_inline type *prefix ## _pop(struct prefix##_head *h) \ { \ struct slist_item *sitem = h->sh.first; \ - if (!sitem) \ + if (sitem == _SLIST_LAST) \ return NULL; \ h->sh.count--; \ h->sh.first = sitem->next; \ - if (h->sh.first == NULL) \ + if (h->sh.first == _SLIST_LAST) \ h->sh.last_next = &h->sh.first; \ sitem->next = NULL; \ return container_of(sitem, type, field.si); \ @@ -226,13 +231,17 @@ macro_inline void prefix ## _swap_all(struct prefix##_head *a, \ } \ macro_pure const type *prefix ## _const_first(const struct prefix##_head *h) \ { \ - return container_of_null(h->sh.first, type, field.si); \ + if (h->sh.first != _SLIST_LAST) \ + return container_of(h->sh.first, type, field.si); \ + return NULL; \ } \ macro_pure const type *prefix ## _const_next(const struct prefix##_head *h, \ const type *item) \ { \ const struct slist_item *sitem = &item->field.si; \ - return container_of_null(sitem->next, type, field.si); \ + if (sitem->next != _SLIST_LAST) \ + return container_of(sitem->next, type, field.si); \ + return NULL; \ } \ TYPESAFE_FIRST_NEXT(prefix, type) \ macro_pure type *prefix ## _next_safe(struct prefix##_head *h, type *item) \ @@ -241,7 +250,9 @@ macro_pure type *prefix ## _next_safe(struct prefix##_head *h, type *item) \ if (!item) \ return NULL; \ sitem = &item->field.si; \ - return container_of_null(sitem->next, type, field.si); \ + if (sitem->next != _SLIST_LAST) \ + return container_of(sitem->next, type, field.si); \ + return NULL; \ } \ macro_pure size_t prefix ## _count(const struct prefix##_head *h) \ { \ From 40ee228da9ae156f6129a7fd87845e1272d2bf92 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 29 Sep 2021 19:59:27 +0200 Subject: [PATCH 163/188] lib: add unsorted typesafe_anywhere() *_anywhere(item) returns whether an item is on _any_ container. Only available for unsorted containers for now. Signed-off-by: David Lamparter --- lib/typesafe.h | 9 +++++++++ tests/lib/test_typelist.h | 14 ++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/lib/typesafe.h b/lib/typesafe.h index b03934b96494..44c42ffbca96 100644 --- a/lib/typesafe.h +++ b/lib/typesafe.h @@ -258,6 +258,10 @@ macro_pure size_t prefix ## _count(const struct prefix##_head *h) \ { \ return h->sh.count; \ } \ +macro_pure bool prefix ## _anywhere(const type *item) \ +{ \ + return item->field.si.next != NULL; \ +} \ macro_pure bool prefix ## _member(const struct prefix##_head *h, \ const type *item) \ { \ @@ -405,6 +409,11 @@ macro_pure size_t prefix ## _count(const struct prefix##_head *h) \ { \ return h->dh.count; \ } \ +macro_pure bool prefix ## _anywhere(const type *item) \ +{ \ + const struct dlist_item *ditem = &item->field.di; \ + return ditem->next && ditem->prev; \ +} \ macro_pure bool prefix ## _member(const struct prefix##_head *h, \ const type *item) \ { \ diff --git a/tests/lib/test_typelist.h b/tests/lib/test_typelist.h index a12a995bf6f3..8261616ed215 100644 --- a/tests/lib/test_typelist.h +++ b/tests/lib/test_typelist.h @@ -40,6 +40,7 @@ #define list_find_lt concat(TYPE, _find_lt) #define list_find_gteq concat(TYPE, _find_gteq) #define list_member concat(TYPE, _member) +#define list_anywhere concat(TYPE, _anywhere) #define list_del concat(TYPE, _del) #define list_pop concat(TYPE, _pop) #define list_swap_all concat(TYPE, _swap_all) @@ -502,10 +503,14 @@ static void concat(test_, TYPE)(void) ts_hash("del-prng", "86d568a95eb429dab3162976c5a5f3f75aabc835932cd682aa280b6923549564"); #if !IS_ATOMIC(REALTYPE) - for (i = 0; i < NITEM; i++) + for (i = 0; i < NITEM; i++) { assertf(list_member(&head, &itm[i]) == itm[i].scratchpad, "%zu should:%d is:%d", i, itm[i].scratchpad, list_member(&head, &itm[i])); + assertf(list_anywhere(&itm[i]) == itm[i].scratchpad, + "%zu should:%d is:%d", i, itm[i].scratchpad, + list_anywhere(&itm[i])); + } ts_hash("member", "86d568a95eb429dab3162976c5a5f3f75aabc835932cd682aa280b6923549564"); #endif @@ -519,10 +524,14 @@ static void concat(test_, TYPE)(void) ts_hash("pop#1", "42b8950c880535b2d2e0c980f9845f7841ecf675c0fb9801aec4170d2036349d"); #if !IS_ATOMIC(REALTYPE) - for (i = 0; i < NITEM; i++) + for (i = 0; i < NITEM; i++) { assertf(list_member(&head, &itm[i]) == itm[i].scratchpad, "%zu should:%d is:%d", i, itm[i].scratchpad, list_member(&head, &itm[i])); + assertf(list_anywhere(&itm[i]) == itm[i].scratchpad, + "%zu should:%d is:%d", i, itm[i].scratchpad, + list_anywhere(&itm[i])); + } ts_hash("member", "42b8950c880535b2d2e0c980f9845f7841ecf675c0fb9801aec4170d2036349d"); #endif @@ -746,6 +755,7 @@ static void concat(test_, TYPE)(void) #undef list_find_lt #undef list_find_gteq #undef list_member +#undef list_anywhere #undef list_del #undef list_pop #undef list_swap_all From e1111c5faf97257351f7421c60bf32a8e191522b Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 29 Sep 2021 22:39:59 +0200 Subject: [PATCH 164/188] doc/developer: add _member and _anywhere New members in the typesafe.h API club. Signed-off-by: David Lamparter --- doc/developer/lists.rst | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/doc/developer/lists.rst b/doc/developer/lists.rst index 718e404764e0..dc8f23692775 100644 --- a/doc/developer/lists.rst +++ b/doc/developer/lists.rst @@ -106,19 +106,25 @@ Functions provided: | _init, _fini | yes | yes | yes | yes | yes | +------------------------------------+------+------+------+---------+------------+ | _first, _next, _next_safe, | yes | yes | yes | yes | yes | +| | | | | | | | _const_first, _const_next | | | | | | +------------------------------------+------+------+------+---------+------------+ | _swap_all | yes | yes | yes | yes | yes | +------------------------------------+------+------+------+---------+------------+ +| _anywhere | yes | -- | -- | -- | -- | ++------------------------------------+------+------+------+---------+------------+ | _add_head, _add_tail, _add_after | yes | -- | -- | -- | -- | +------------------------------------+------+------+------+---------+------------+ | _add | -- | yes | yes | yes | yes | +------------------------------------+------+------+------+---------+------------+ +| _member | yes | yes | yes | yes | yes | ++------------------------------------+------+------+------+---------+------------+ | _del, _pop | yes | yes | yes | yes | yes | +------------------------------------+------+------+------+---------+------------+ | _find, _const_find | -- | -- | yes | yes | -- | +------------------------------------+------+------+------+---------+------------+ | _find_lt, _find_gteq, | -- | -- | -- | yes | yes | +| | | | | | | | _const_find_lt, _const_find_gteq | | | | | | +------------------------------------+------+------+------+---------+------------+ | use with frr_each() macros | yes | yes | yes | yes | yes | @@ -268,6 +274,16 @@ The following documentation assumes that a list has been defined using outdated by the time this function returns and can therefore only be used as an estimate. +.. c:function:: bool Z_member(const struct Z_head *, const itemtype *) + + Determines whether some item is a member of the given container. The + item must either be valid on some container, or set to all zeroes. + + On some containers, if no faster way to determine membership is possible, + this is simply ``item == Z_find(head, item)``. + + Not currently available for atomic containers. + .. c:function:: const itemtype *Z_const_first(const struct Z_head *) .. c:function:: itemtype *Z_first(struct Z_head *) @@ -396,6 +412,17 @@ are several functions exposed to insert data: maybe flip the order of ``item`` & ``after``? ``Z_add_after(head, item, after)`` +.. c:function:: bool Z_anywhere(const itemtype *) + + Returns whether an item is a member of *any* container of this type. + The item must either be valid on some container, or set to all zeroes. + + Guaranteed to be fast (pointer compare or similar.) + + Not currently available for sorted and atomic containers. Might be added + for sorted containers at some point (when needed.) + + API for sorted structures ------------------------- From 865bf787fa1213fe62d8747953c1a612b42a3984 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sat, 27 Mar 2021 22:20:10 +0100 Subject: [PATCH 165/188] nhrpd: convert notifier list to DLIST Signed-off-by: David Lamparter --- nhrpd/nhrp_cache.c | 4 ++-- nhrpd/nhrp_interface.c | 13 ++++++++++--- nhrpd/nhrp_peer.c | 2 +- nhrpd/nhrp_vc.c | 2 +- nhrpd/nhrpd.h | 27 ++++++++++++++++----------- 5 files changed, 30 insertions(+), 18 deletions(-) diff --git a/nhrpd/nhrp_cache.c b/nhrpd/nhrp_cache.c index c358baecb27c..3823464a73ed 100644 --- a/nhrpd/nhrp_cache.c +++ b/nhrpd/nhrp_cache.c @@ -315,7 +315,7 @@ static void nhrp_cache_peer_notifier(struct notifier_block *n, static void nhrp_cache_reset_new(struct nhrp_cache *c) { THREAD_OFF(c->t_auth); - if (list_hashed(&c->newpeer_notifier.notifier_entry)) + if (notifier_list_anywhere(&c->newpeer_notifier)) nhrp_peer_notify_del(c->new.peer, &c->newpeer_notifier); nhrp_peer_unref(c->new.peer); memset(&c->new, 0, sizeof(c->new)); @@ -574,5 +574,5 @@ void nhrp_cache_notify_add(struct nhrp_cache *c, struct notifier_block *n, void nhrp_cache_notify_del(struct nhrp_cache *c, struct notifier_block *n) { - notifier_del(n); + notifier_del(n, &c->notifier_list); } diff --git a/nhrpd/nhrp_interface.c b/nhrpd/nhrp_interface.c index 2db8997bad4e..7597526f736f 100644 --- a/nhrpd/nhrp_interface.c +++ b/nhrpd/nhrp_interface.c @@ -224,8 +224,12 @@ void nhrp_interface_update_nbma(struct interface *ifp, nbmanifp = nbmaifp->info; if (nbmaifp != nifp->nbmaifp) { - if (nifp->nbmaifp) - notifier_del(&nifp->nbmanifp_notifier); + if (nifp->nbmaifp) { + struct nhrp_interface *prev_nifp = nifp->nbmaifp->info; + + notifier_del(&nifp->nbmanifp_notifier, + &prev_nifp->notifier_list); + } nifp->nbmaifp = nbmaifp; if (nbmaifp) { notifier_add(&nifp->nbmanifp_notifier, @@ -509,12 +513,15 @@ void nhrp_interface_notify_add(struct interface *ifp, struct notifier_block *n, notifier_fn_t fn) { struct nhrp_interface *nifp = ifp->info; + notifier_add(n, &nifp->notifier_list, fn); } void nhrp_interface_notify_del(struct interface *ifp, struct notifier_block *n) { - notifier_del(n); + struct nhrp_interface *nifp = ifp->info; + + notifier_del(n, &nifp->notifier_list); } void nhrp_interface_set_protection(struct interface *ifp, const char *profile, diff --git a/nhrpd/nhrp_peer.c b/nhrpd/nhrp_peer.c index 030f4c0ff335..51cae44bd1b2 100644 --- a/nhrpd/nhrp_peer.c +++ b/nhrpd/nhrp_peer.c @@ -359,7 +359,7 @@ void nhrp_peer_notify_add(struct nhrp_peer *p, struct notifier_block *n, void nhrp_peer_notify_del(struct nhrp_peer *p, struct notifier_block *n) { - notifier_del(n); + notifier_del(n, &p->notifier_list); nhrp_peer_check_delete(p); } diff --git a/nhrpd/nhrp_vc.c b/nhrpd/nhrp_vc.c index b3b657f3fada..b5de0e91c497 100644 --- a/nhrpd/nhrp_vc.c +++ b/nhrpd/nhrp_vc.c @@ -170,7 +170,7 @@ void nhrp_vc_notify_add(struct nhrp_vc *vc, struct notifier_block *n, void nhrp_vc_notify_del(struct nhrp_vc *vc, struct notifier_block *n) { - notifier_del(n); + notifier_del(n, &vc->notifier_list); nhrp_vc_check_delete(vc); } diff --git a/nhrpd/nhrpd.h b/nhrpd/nhrpd.h index 17abb04762aa..e88a4576fb6b 100644 --- a/nhrpd/nhrpd.h +++ b/nhrpd/nhrpd.h @@ -42,48 +42,53 @@ struct notifier_block; typedef void (*notifier_fn_t)(struct notifier_block *, unsigned long); +PREDECL_DLIST(notifier_list); + struct notifier_block { - struct list_head notifier_entry; + struct notifier_list_item notifier_entry; notifier_fn_t action; }; +DECLARE_DLIST(notifier_list, struct notifier_block, notifier_entry); + struct notifier_list { - struct list_head notifier_head; + struct notifier_list_head head; }; #define NOTIFIER_LIST_INITIALIZER(l) \ { \ - .notifier_head = LIST_INITIALIZER((l)->notifier_head) \ + .head = INIT_DLIST((l)->head) \ } static inline void notifier_init(struct notifier_list *l) { - list_init(&l->notifier_head); + notifier_list_init(&l->head); } static inline void notifier_add(struct notifier_block *n, struct notifier_list *l, notifier_fn_t action) { n->action = action; - list_add_tail(&n->notifier_entry, &l->notifier_head); + notifier_list_add_tail(&l->head, n); } -static inline void notifier_del(struct notifier_block *n) +static inline void notifier_del(struct notifier_block *n, + struct notifier_list *l) { - list_del(&n->notifier_entry); + notifier_list_del(&l->head, n); } static inline void notifier_call(struct notifier_list *l, int cmd) { - struct notifier_block *n, *nn; - list_for_each_entry_safe(n, nn, &l->notifier_head, notifier_entry) { + struct notifier_block *n; + + frr_each_safe (notifier_list, &l->head, n) n->action(n, cmd); - } } static inline int notifier_active(struct notifier_list *l) { - return !list_empty(&l->notifier_head); + return notifier_list_count(&l->head) > 0; } extern struct hash *nhrp_gre_list; From 2ab2a7610131d0d12a4361f851c3e742b058ddd4 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sat, 27 Mar 2021 22:30:51 +0100 Subject: [PATCH 166/188] nhrpd: convert nhs list to DLIST Signed-off-by: David Lamparter --- nhrpd/nhrp_interface.c | 2 +- nhrpd/nhrp_nhs.c | 62 +++++++++++++++++------------------------- nhrpd/nhrp_vty.c | 4 +-- nhrpd/nhrpd.h | 10 +++++-- 4 files changed, 34 insertions(+), 44 deletions(-) diff --git a/nhrpd/nhrp_interface.c b/nhrpd/nhrp_interface.c index 7597526f736f..0211bdd50b9d 100644 --- a/nhrpd/nhrp_interface.c +++ b/nhrpd/nhrp_interface.c @@ -79,7 +79,7 @@ static int nhrp_if_new_hook(struct interface *ifp) for (afi = 0; afi < AFI_MAX; afi++) { struct nhrp_afi_data *ad = &nifp->afi[afi]; ad->holdtime = NHRPD_DEFAULT_HOLDTIME; - list_init(&ad->nhslist_head); + nhrp_nhslist_init(&ad->nhslist_head); list_init(&ad->mcastlist_head); } diff --git a/nhrpd/nhrp_nhs.c b/nhrpd/nhrp_nhs.c index 5179f15ebf85..53c3be4c1aec 100644 --- a/nhrpd/nhrp_nhs.c +++ b/nhrpd/nhrp_nhs.c @@ -344,8 +344,7 @@ int nhrp_nhs_add(struct interface *ifp, afi_t afi, union sockunion *proto_addr, && sockunion_family(proto_addr) != afi2family(afi)) return NHRP_ERR_PROTOCOL_ADDRESS_MISMATCH; - list_for_each_entry(nhs, &nifp->afi[afi].nhslist_head, nhslist_entry) - { + frr_each (nhrp_nhslist, &nifp->afi[afi].nhslist_head, nhs) { if (sockunion_family(&nhs->proto_addr) != AF_UNSPEC && sockunion_family(proto_addr) != AF_UNSPEC && sockunion_same(&nhs->proto_addr, proto_addr)) @@ -364,7 +363,7 @@ int nhrp_nhs_add(struct interface *ifp, afi_t afi, union sockunion *proto_addr, .nbma_fqdn = strdup(nbma_fqdn), .reglist_head = LIST_INITIALIZER(nhs->reglist_head), }; - list_add_tail(&nhs->nhslist_entry, &nifp->afi[afi].nhslist_head); + nhrp_nhslist_add_tail(&nifp->afi[afi].nhslist_head, nhs); thread_add_timer_msec(master, nhrp_nhs_resolve, nhs, 1000, &nhs->t_resolve); @@ -375,36 +374,34 @@ int nhrp_nhs_del(struct interface *ifp, afi_t afi, union sockunion *proto_addr, const char *nbma_fqdn) { struct nhrp_interface *nifp = ifp->info; - struct nhrp_nhs *nhs, *nnhs; + struct nhrp_nhs *nhs; int ret = NHRP_ERR_ENTRY_NOT_FOUND; if (sockunion_family(proto_addr) != AF_UNSPEC && sockunion_family(proto_addr) != afi2family(afi)) return NHRP_ERR_PROTOCOL_ADDRESS_MISMATCH; - list_for_each_entry_safe(nhs, nnhs, &nifp->afi[afi].nhslist_head, - nhslist_entry) - { + frr_each_safe (nhrp_nhslist, &nifp->afi[afi].nhslist_head, nhs) { if (!sockunion_same(&nhs->proto_addr, proto_addr)) continue; if (strcmp(nhs->nbma_fqdn, nbma_fqdn) != 0) continue; - nhrp_nhs_free(nhs); + nhrp_nhs_free(nifp, afi, nhs); ret = NHRP_OK; } return ret; } -int nhrp_nhs_free(struct nhrp_nhs *nhs) +int nhrp_nhs_free(struct nhrp_interface *nifp, afi_t afi, struct nhrp_nhs *nhs) { struct nhrp_registration *r, *rn; list_for_each_entry_safe(r, rn, &nhs->reglist_head, reglist_entry) nhrp_reg_delete(r); THREAD_OFF(nhs->t_resolve); - list_del(&nhs->nhslist_entry); + nhrp_nhslist_del(&nifp->afi[afi].nhslist_head, nhs); free((void *)nhs->nbma_fqdn); XFREE(MTYPE_NHRP_NHS, nhs); return 0; @@ -413,18 +410,15 @@ int nhrp_nhs_free(struct nhrp_nhs *nhs) void nhrp_nhs_interface_del(struct interface *ifp) { struct nhrp_interface *nifp = ifp->info; - struct nhrp_nhs *nhs, *tmp; + struct nhrp_nhs *nhs; afi_t afi; for (afi = 0; afi < AFI_MAX; afi++) { - debugf(NHRP_DEBUG_COMMON, "Cleaning up nhs entries (%d)", - !list_empty(&nifp->afi[afi].nhslist_head)); + debugf(NHRP_DEBUG_COMMON, "Cleaning up nhs entries (%zu)", + nhrp_nhslist_count(&nifp->afi[afi].nhslist_head)); - list_for_each_entry_safe(nhs, tmp, &nifp->afi[afi].nhslist_head, - nhslist_entry) - { - nhrp_nhs_free(nhs); - } + frr_each_safe (nhrp_nhslist, &nifp->afi[afi].nhslist_head, nhs) + nhrp_nhs_free(nifp, afi, nhs); } } @@ -433,15 +427,15 @@ void nhrp_nhs_terminate(void) struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); struct interface *ifp; struct nhrp_interface *nifp; - struct nhrp_nhs *nhs, *tmp; + struct nhrp_nhs *nhs; afi_t afi; FOR_ALL_INTERFACES (vrf, ifp) { nifp = ifp->info; for (afi = 0; afi < AFI_MAX; afi++) { - list_for_each_entry_safe( - nhs, tmp, &nifp->afi[afi].nhslist_head, - nhslist_entry) nhrp_nhs_free(nhs); + frr_each_safe (nhrp_nhslist, + &nifp->afi[afi].nhslist_head, nhs) + nhrp_nhs_free(nifp, afi, nhs); } } } @@ -455,8 +449,7 @@ void nhrp_nhs_foreach(struct interface *ifp, afi_t afi, struct nhrp_nhs *nhs; struct nhrp_registration *reg; - list_for_each_entry(nhs, &nifp->afi[afi].nhslist_head, nhslist_entry) - { + frr_each (nhrp_nhslist, &nifp->afi[afi].nhslist_head, nhs) { if (!list_empty(&nhs->reglist_head)) { list_for_each_entry(reg, &nhs->reglist_head, reglist_entry) cb(nhs, reg, ctx); @@ -472,19 +465,14 @@ int nhrp_nhs_match_ip(union sockunion *in_ip, struct nhrp_interface *nifp) struct nhrp_registration *reg; for (i = 0; i < AFI_MAX; i++) { - list_for_each_entry(nhs, &nifp->afi[i].nhslist_head, - nhslist_entry) - { - if (!list_empty(&nhs->reglist_head)) { - list_for_each_entry(reg, &nhs->reglist_head, - reglist_entry) - { - if (!sockunion_cmp( - in_ip, - ®->peer->vc->remote - .nbma)) - return 1; - } + frr_each (nhrp_nhslist, &nifp->afi[i].nhslist_head, nhs) { + if (!nhrp_reglist_count(&nhs->reglist_head)) + continue; + + frr_each (nhrp_reglist, &nhs->reglist_head, reg) { + if (!sockunion_cmp(in_ip, + ®->peer->vc->remote.nbma)) + return 1; } } } diff --git a/nhrpd/nhrp_vty.c b/nhrpd/nhrp_vty.c index 50161dae2fc3..c6f9a172589c 100644 --- a/nhrpd/nhrp_vty.c +++ b/nhrpd/nhrp_vty.c @@ -1200,9 +1200,7 @@ static int interface_config_write(struct vty *vty) nhrp_cache_config_foreach( ifp, interface_config_write_nhrp_map, &mapctx); - list_for_each_entry(nhs, &ad->nhslist_head, - nhslist_entry) - { + frr_each (nhrp_nhslist, &ad->nhslist_head, nhs) { vty_out(vty, " %s nhrp nhs ", aficmd); if (sockunion_family(&nhs->proto_addr) == AF_UNSPEC) diff --git a/nhrpd/nhrpd.h b/nhrpd/nhrpd.h index e88a4576fb6b..7e4a86cd5521 100644 --- a/nhrpd/nhrpd.h +++ b/nhrpd/nhrpd.h @@ -268,9 +268,11 @@ struct nhrp_shortcut { struct notifier_block cache_notifier; }; +PREDECL_DLIST(nhrp_nhslist); + struct nhrp_nhs { struct interface *ifp; - struct list_head nhslist_entry; + struct nhrp_nhslist_item nhslist_entry; unsigned hub : 1; afi_t afi; @@ -282,6 +284,8 @@ struct nhrp_nhs { struct list_head reglist_head; }; +DECLARE_DLIST(nhrp_nhslist, struct nhrp_nhs, nhslist_entry); + struct nhrp_multicast { struct interface *ifp; struct list_head list_entry; @@ -335,7 +339,7 @@ struct nhrp_interface { short configured_mtu; unsigned short mtu; unsigned int holdtime; - struct list_head nhslist_head; + struct nhrp_nhslist_head nhslist_head; struct list_head mcastlist_head; } afi[AFI_MAX]; }; @@ -386,7 +390,7 @@ int nhrp_nhs_add(struct interface *ifp, afi_t afi, union sockunion *proto_addr, const char *nbma_fqdn); int nhrp_nhs_del(struct interface *ifp, afi_t afi, union sockunion *proto_addr, const char *nbma_fqdn); -int nhrp_nhs_free(struct nhrp_nhs *nhs); +int nhrp_nhs_free(struct nhrp_interface *nifp, afi_t afi, struct nhrp_nhs *nhs); void nhrp_nhs_terminate(void); void nhrp_nhs_foreach(struct interface *ifp, afi_t afi, void (*cb)(struct nhrp_nhs *, struct nhrp_registration *, From db4db2bbdabf172b11013f268082e37832298c6e Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 29 Sep 2021 23:16:17 +0200 Subject: [PATCH 167/188] nhrpd: convert mcast list to DLIST Signed-off-by: David Lamparter --- nhrpd/nhrp_interface.c | 2 +- nhrpd/nhrp_multicast.c | 30 +++++++++++++----------------- nhrpd/nhrp_vty.c | 4 +--- nhrpd/nhrpd.h | 7 +++++-- 4 files changed, 20 insertions(+), 23 deletions(-) diff --git a/nhrpd/nhrp_interface.c b/nhrpd/nhrp_interface.c index 0211bdd50b9d..94cec0281f4a 100644 --- a/nhrpd/nhrp_interface.c +++ b/nhrpd/nhrp_interface.c @@ -80,7 +80,7 @@ static int nhrp_if_new_hook(struct interface *ifp) struct nhrp_afi_data *ad = &nifp->afi[afi]; ad->holdtime = NHRPD_DEFAULT_HOLDTIME; nhrp_nhslist_init(&ad->nhslist_head); - list_init(&ad->mcastlist_head); + nhrp_mcastlist_init(&ad->mcastlist_head); } return 0; diff --git a/nhrpd/nhrp_multicast.c b/nhrpd/nhrp_multicast.c index 339b6dfabe27..d8372ae8a8cd 100644 --- a/nhrpd/nhrp_multicast.c +++ b/nhrpd/nhrp_multicast.c @@ -219,7 +219,9 @@ void netlink_mcast_set_nflog_group(int nlgroup) static int nhrp_multicast_free(struct interface *ifp, struct nhrp_multicast *mcast) { - list_del(&mcast->list_entry); + struct nhrp_interface *nifp = ifp->info; + + nhrp_mcastlist_del(&nifp->afi[mcast->afi].mcastlist_head, mcast); XFREE(MTYPE_NHRP_MULTICAST, mcast); return 0; } @@ -230,8 +232,7 @@ int nhrp_multicast_add(struct interface *ifp, afi_t afi, struct nhrp_interface *nifp = ifp->info; struct nhrp_multicast *mcast; - list_for_each_entry(mcast, &nifp->afi[afi].mcastlist_head, list_entry) - { + frr_each (nhrp_mcastlist, &nifp->afi[afi].mcastlist_head, mcast) { if (sockunion_same(&mcast->nbma_addr, nbma_addr)) return NHRP_ERR_ENTRY_EXISTS; } @@ -241,7 +242,7 @@ int nhrp_multicast_add(struct interface *ifp, afi_t afi, *mcast = (struct nhrp_multicast){ .afi = afi, .ifp = ifp, .nbma_addr = *nbma_addr, }; - list_add_tail(&mcast->list_entry, &nifp->afi[afi].mcastlist_head); + nhrp_mcastlist_add_tail(&nifp->afi[afi].mcastlist_head, mcast); debugf(NHRP_DEBUG_COMMON, "Adding multicast entry (%pSU)", nbma_addr); @@ -252,11 +253,9 @@ int nhrp_multicast_del(struct interface *ifp, afi_t afi, union sockunion *nbma_addr) { struct nhrp_interface *nifp = ifp->info; - struct nhrp_multicast *mcast, *tmp; + struct nhrp_multicast *mcast; - list_for_each_entry_safe(mcast, tmp, &nifp->afi[afi].mcastlist_head, - list_entry) - { + frr_each_safe (nhrp_mcastlist, &nifp->afi[afi].mcastlist_head, mcast) { if (!sockunion_same(&mcast->nbma_addr, nbma_addr)) continue; @@ -274,17 +273,15 @@ int nhrp_multicast_del(struct interface *ifp, afi_t afi, void nhrp_multicast_interface_del(struct interface *ifp) { struct nhrp_interface *nifp = ifp->info; - struct nhrp_multicast *mcast, *tmp; + struct nhrp_multicast *mcast; afi_t afi; for (afi = 0; afi < AFI_MAX; afi++) { - debugf(NHRP_DEBUG_COMMON, - "Cleaning up multicast entries (%d)", - !list_empty(&nifp->afi[afi].mcastlist_head)); + debugf(NHRP_DEBUG_COMMON, "Cleaning up multicast entries (%zu)", + nhrp_mcastlist_count(&nifp->afi[afi].mcastlist_head)); - list_for_each_entry_safe( - mcast, tmp, &nifp->afi[afi].mcastlist_head, list_entry) - { + frr_each_safe (nhrp_mcastlist, &nifp->afi[afi].mcastlist_head, + mcast) { nhrp_multicast_free(ifp, mcast); } } @@ -297,8 +294,7 @@ void nhrp_multicast_foreach(struct interface *ifp, afi_t afi, struct nhrp_interface *nifp = ifp->info; struct nhrp_multicast *mcast; - list_for_each_entry(mcast, &nifp->afi[afi].mcastlist_head, list_entry) - { + frr_each (nhrp_mcastlist, &nifp->afi[afi].mcastlist_head, mcast) { cb(mcast, ctx); } } diff --git a/nhrpd/nhrp_vty.c b/nhrpd/nhrp_vty.c index c6f9a172589c..0dfabcf6ae2b 100644 --- a/nhrpd/nhrp_vty.c +++ b/nhrpd/nhrp_vty.c @@ -1210,9 +1210,7 @@ static int interface_config_write(struct vty *vty) vty_out(vty, " nbma %s\n", nhs->nbma_fqdn); } - list_for_each_entry(mcast, &ad->mcastlist_head, - list_entry) - { + frr_each (nhrp_mcastlist, &ad->mcastlist_head, mcast) { vty_out(vty, " %s nhrp map multicast ", aficmd); if (sockunion_family(&mcast->nbma_addr) == AF_UNSPEC) diff --git a/nhrpd/nhrpd.h b/nhrpd/nhrpd.h index 7e4a86cd5521..2eab3614d45d 100644 --- a/nhrpd/nhrpd.h +++ b/nhrpd/nhrpd.h @@ -269,6 +269,7 @@ struct nhrp_shortcut { }; PREDECL_DLIST(nhrp_nhslist); +PREDECL_DLIST(nhrp_mcastlist); struct nhrp_nhs { struct interface *ifp; @@ -288,11 +289,13 @@ DECLARE_DLIST(nhrp_nhslist, struct nhrp_nhs, nhslist_entry); struct nhrp_multicast { struct interface *ifp; - struct list_head list_entry; + struct nhrp_mcastlist_item mcastlist_entry; afi_t afi; union sockunion nbma_addr; /* IP-address */ }; +DECLARE_DLIST(nhrp_mcastlist, struct nhrp_multicast, mcastlist_entry); + struct nhrp_registration { struct list_head reglist_entry; struct thread *t_register; @@ -340,7 +343,7 @@ struct nhrp_interface { unsigned short mtu; unsigned int holdtime; struct nhrp_nhslist_head nhslist_head; - struct list_head mcastlist_head; + struct nhrp_mcastlist_head mcastlist_head; } afi[AFI_MAX]; }; From 811de44f34345a9b79a1b79fe63452d354c40f6e Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sat, 27 Mar 2021 22:37:25 +0100 Subject: [PATCH 168/188] nhrpd: convert reg list to DLIST Signed-off-by: David Lamparter --- nhrpd/nhrp_nhs.c | 34 +++++++++++++++------------------- nhrpd/nhrpd.h | 7 +++++-- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/nhrpd/nhrp_nhs.c b/nhrpd/nhrp_nhs.c index 53c3be4c1aec..597c125e17b1 100644 --- a/nhrpd/nhrp_nhs.c +++ b/nhrpd/nhrp_nhs.c @@ -254,7 +254,7 @@ static void nhrp_reg_delete(struct nhrp_registration *r) { nhrp_peer_notify_del(r->peer, &r->peer_notifier); nhrp_peer_unref(r->peer); - list_del(&r->reglist_entry); + nhrp_reglist_del(&r->nhs->reglist_head, r); THREAD_OFF(r->t_register); XFREE(MTYPE_NHRP_REGISTRATION, r); } @@ -264,10 +264,9 @@ nhrp_reg_by_nbma(struct nhrp_nhs *nhs, const union sockunion *nbma_addr) { struct nhrp_registration *r; - list_for_each_entry( - r, &nhs->reglist_head, - reglist_entry) if (sockunion_same(&r->peer->vc->remote.nbma, - nbma_addr)) return r; + frr_each (nhrp_reglist, &nhs->reglist_head, r) + if (sockunion_same(&r->peer->vc->remote.nbma, nbma_addr)) + return r; return NULL; } @@ -276,7 +275,7 @@ static void nhrp_nhs_resolve_cb(struct resolver_query *q, const char *errstr, { struct nhrp_nhs *nhs = container_of(q, struct nhrp_nhs, dns_resolve); struct nhrp_interface *nifp = nhs->ifp->info; - struct nhrp_registration *reg, *regn; + struct nhrp_registration *reg; int i; if (n < 0) { @@ -289,8 +288,8 @@ static void nhrp_nhs_resolve_cb(struct resolver_query *q, const char *errstr, thread_add_timer(master, nhrp_nhs_resolve, nhs, 2 * 60 * 60, &nhs->t_resolve); - list_for_each_entry(reg, &nhs->reglist_head, reglist_entry) reg->mark = - 1; + frr_each (nhrp_reglist, &nhs->reglist_head, reg) + reg->mark = 1; nhs->hub = 0; for (i = 0; i < n; i++) { @@ -309,19 +308,16 @@ static void nhrp_nhs_resolve_cb(struct resolver_query *q, const char *errstr, reg->peer = nhrp_peer_get(nhs->ifp, &addrs[i]); reg->nhs = nhs; reg->timeout = 1; - list_init(®->reglist_entry); - list_add_tail(®->reglist_entry, &nhs->reglist_head); + nhrp_reglist_add_tail(&nhs->reglist_head, reg); nhrp_peer_notify_add(reg->peer, ®->peer_notifier, nhrp_reg_peer_notify); thread_add_timer_msec(master, nhrp_reg_send_req, reg, 50, ®->t_register); } - list_for_each_entry_safe(reg, regn, &nhs->reglist_head, reglist_entry) - { + frr_each_safe (nhrp_reglist, &nhs->reglist_head, reg) if (reg->mark) nhrp_reg_delete(reg); - } } static int nhrp_nhs_resolve(struct thread *t) @@ -361,7 +357,7 @@ int nhrp_nhs_add(struct interface *ifp, afi_t afi, union sockunion *proto_addr, .ifp = ifp, .proto_addr = *proto_addr, .nbma_fqdn = strdup(nbma_fqdn), - .reglist_head = LIST_INITIALIZER(nhs->reglist_head), + .reglist_head = INIT_DLIST(nhs->reglist_head), }; nhrp_nhslist_add_tail(&nifp->afi[afi].nhslist_head, nhs); thread_add_timer_msec(master, nhrp_nhs_resolve, nhs, 1000, @@ -396,9 +392,9 @@ int nhrp_nhs_del(struct interface *ifp, afi_t afi, union sockunion *proto_addr, int nhrp_nhs_free(struct nhrp_interface *nifp, afi_t afi, struct nhrp_nhs *nhs) { - struct nhrp_registration *r, *rn; + struct nhrp_registration *r; - list_for_each_entry_safe(r, rn, &nhs->reglist_head, reglist_entry) + frr_each_safe (nhrp_reglist, &nhs->reglist_head, r) nhrp_reg_delete(r); THREAD_OFF(nhs->t_resolve); nhrp_nhslist_del(&nifp->afi[afi].nhslist_head, nhs); @@ -450,9 +446,9 @@ void nhrp_nhs_foreach(struct interface *ifp, afi_t afi, struct nhrp_registration *reg; frr_each (nhrp_nhslist, &nifp->afi[afi].nhslist_head, nhs) { - if (!list_empty(&nhs->reglist_head)) { - list_for_each_entry(reg, &nhs->reglist_head, - reglist_entry) cb(nhs, reg, ctx); + if (nhrp_reglist_count(&nhs->reglist_head)) { + frr_each (nhrp_reglist, &nhs->reglist_head, reg) + cb(nhs, reg, ctx); } else cb(nhs, 0, ctx); } diff --git a/nhrpd/nhrpd.h b/nhrpd/nhrpd.h index 2eab3614d45d..c73f51d40312 100644 --- a/nhrpd/nhrpd.h +++ b/nhrpd/nhrpd.h @@ -270,6 +270,7 @@ struct nhrp_shortcut { PREDECL_DLIST(nhrp_nhslist); PREDECL_DLIST(nhrp_mcastlist); +PREDECL_DLIST(nhrp_reglist); struct nhrp_nhs { struct interface *ifp; @@ -282,7 +283,7 @@ struct nhrp_nhs { struct thread *t_resolve; struct resolver_query dns_resolve; - struct list_head reglist_head; + struct nhrp_reglist_head reglist_head; }; DECLARE_DLIST(nhrp_nhslist, struct nhrp_nhs, nhslist_entry); @@ -297,7 +298,7 @@ struct nhrp_multicast { DECLARE_DLIST(nhrp_mcastlist, struct nhrp_multicast, mcastlist_entry); struct nhrp_registration { - struct list_head reglist_entry; + struct nhrp_reglist_item reglist_entry; struct thread *t_register; struct nhrp_nhs *nhs; struct nhrp_reqid reqid; @@ -308,6 +309,8 @@ struct nhrp_registration { struct notifier_block peer_notifier; }; +DECLARE_DLIST(nhrp_reglist, struct nhrp_registration, reglist_entry); + #define NHRP_IFF_SHORTCUT 0x0001 #define NHRP_IFF_REDIRECT 0x0002 #define NHRP_IFF_REG_NO_UNIQUE 0x0100 From b4f3d41bfd3d595c28a084a90fc78540adb0c4b4 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sat, 27 Mar 2021 22:41:44 +0100 Subject: [PATCH 169/188] nhrpd: convert SA list to DLIST Signed-off-by: David Lamparter --- nhrpd/nhrp_vc.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/nhrpd/nhrp_vc.c b/nhrpd/nhrp_vc.c index b5de0e91c497..4b45389dadd0 100644 --- a/nhrpd/nhrp_vc.c +++ b/nhrpd/nhrp_vc.c @@ -19,14 +19,18 @@ DEFINE_MTYPE_STATIC(NHRPD, NHRP_VC, "NHRP virtual connection"); +PREDECL_DLIST(childlist); + struct child_sa { uint32_t id; struct nhrp_vc *vc; - struct list_head childlist_entry; + struct childlist_item childlist_entry; }; +DECLARE_DLIST(childlist, struct child_sa, childlist_entry); + static struct hash *nhrp_vc_hash; -static struct list_head childlist_head[512]; +static struct childlist_head childlist_head[512]; static unsigned int nhrp_vc_key(const void *peer_data) { @@ -104,8 +108,7 @@ int nhrp_vc_ipsec_updown(uint32_t child_id, struct nhrp_vc *vc) uint32_t child_hash = child_id % array_size(childlist_head); int abort_migration = 0; - list_for_each_entry(lsa, &childlist_head[child_hash], childlist_entry) - { + frr_each (childlist, &childlist_head[child_hash], lsa) { if (lsa->id == child_id) { sa = lsa; break; @@ -120,12 +123,9 @@ int nhrp_vc_ipsec_updown(uint32_t child_id, struct nhrp_vc *vc) *sa = (struct child_sa){ .id = child_id, - .childlist_entry = - LIST_INITIALIZER(sa->childlist_entry), .vc = NULL, }; - list_add_tail(&sa->childlist_entry, - &childlist_head[child_hash]); + childlist_add_tail(&childlist_head[child_hash], sa); } if (sa->vc == vc) @@ -155,7 +155,7 @@ int nhrp_vc_ipsec_updown(uint32_t child_id, struct nhrp_vc *vc) /* Update */ sa->vc = vc; if (!vc) { - list_del(&sa->childlist_entry); + childlist_del(&childlist_head[child_hash], sa); XFREE(MTYPE_NHRP_VC, sa); } @@ -200,17 +200,16 @@ void nhrp_vc_init(void) nhrp_vc_hash = hash_create(nhrp_vc_key, nhrp_vc_cmp, "NHRP VC hash"); for (i = 0; i < array_size(childlist_head); i++) - list_init(&childlist_head[i]); + childlist_init(&childlist_head[i]); } void nhrp_vc_reset(void) { - struct child_sa *sa, *n; + struct child_sa *sa; size_t i; for (i = 0; i < array_size(childlist_head); i++) { - list_for_each_entry_safe(sa, n, &childlist_head[i], - childlist_entry) + frr_each_safe (childlist, &childlist_head[i], sa) nhrp_vc_ipsec_updown(sa->id, 0); } } From f9aa07b1a8b6b33b68956657ebd7a6f2a707c05c Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sat, 27 Mar 2021 22:46:33 +0100 Subject: [PATCH 170/188] nhrpd: convert zbuf queue to DLIST Signed-off-by: David Lamparter --- nhrpd/zbuf.c | 21 +++++++++------------ nhrpd/zbuf.h | 10 +++++++--- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/nhrpd/zbuf.c b/nhrpd/zbuf.c index e191a90f2d8c..9cc2b56245ca 100644 --- a/nhrpd/zbuf.c +++ b/nhrpd/zbuf.c @@ -164,35 +164,33 @@ void *zbuf_may_pull_until(struct zbuf *zb, const char *sep, struct zbuf *msg) void zbufq_init(struct zbuf_queue *zbq) { *zbq = (struct zbuf_queue){ - .queue_head = LIST_INITIALIZER(zbq->queue_head), + .queue_head = INIT_DLIST(zbq->queue_head), }; } void zbufq_reset(struct zbuf_queue *zbq) { - struct zbuf *buf, *bufn; + struct zbuf *buf; - list_for_each_entry_safe(buf, bufn, &zbq->queue_head, queue_list) - { - list_del(&buf->queue_list); + frr_each_safe (zbuf_queue, &zbq->queue_head, buf) { + zbuf_queue_del(&zbq->queue_head, buf); zbuf_free(buf); } } void zbufq_queue(struct zbuf_queue *zbq, struct zbuf *zb) { - list_add_tail(&zb->queue_list, &zbq->queue_head); + zbuf_queue_add_tail(&zbq->queue_head, zb); } int zbufq_write(struct zbuf_queue *zbq, int fd) { struct iovec iov[16]; - struct zbuf *zb, *zbn; + struct zbuf *zb; ssize_t r; size_t iovcnt = 0; - list_for_each_entry_safe(zb, zbn, &zbq->queue_head, queue_list) - { + frr_each_safe (zbuf_queue, &zbq->queue_head, zb) { iov[iovcnt++] = (struct iovec){ .iov_base = zb->head, .iov_len = zbuf_used(zb), }; @@ -204,15 +202,14 @@ int zbufq_write(struct zbuf_queue *zbq, int fd) if (r < 0) return r; - list_for_each_entry_safe(zb, zbn, &zbq->queue_head, queue_list) - { + frr_each_safe (zbuf_queue, &zbq->queue_head, zb) { if (r < (ssize_t)zbuf_used(zb)) { zb->head += r; return 1; } r -= zbuf_used(zb); - list_del(&zb->queue_list); + zbuf_queue_del(&zbq->queue_head, zb); zbuf_free(zb); } diff --git a/nhrpd/zbuf.h b/nhrpd/zbuf.h index 2741860bfd6d..d036b104608d 100644 --- a/nhrpd/zbuf.h +++ b/nhrpd/zbuf.h @@ -15,18 +15,22 @@ #include #include -#include "list.h" +#include "typesafe.h" + +PREDECL_DLIST(zbuf_queue); struct zbuf { - struct list_head queue_list; + struct zbuf_queue_item queue_entry; unsigned allocated : 1; unsigned error : 1; uint8_t *buf, *end; uint8_t *head, *tail; }; +DECLARE_DLIST(zbuf_queue, struct zbuf, queue_entry); + struct zbuf_queue { - struct list_head queue_head; + struct zbuf_queue_head queue_head; }; struct zbuf *zbuf_alloc(size_t size); From 6a596158597801569134b8d8d1a7d1ee66b72f85 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sat, 27 Mar 2021 22:47:28 +0100 Subject: [PATCH 171/188] nhrpd: drop list.h `number_of_linked_lists_in_frr--;` Signed-off-by: David Lamparter --- nhrpd/list.h | 209 ------------------------------------------------ nhrpd/nhrpd.h | 2 - nhrpd/subdir.am | 1 - 3 files changed, 212 deletions(-) delete mode 100644 nhrpd/list.h diff --git a/nhrpd/list.h b/nhrpd/list.h deleted file mode 100644 index a43687ac089a..000000000000 --- a/nhrpd/list.h +++ /dev/null @@ -1,209 +0,0 @@ -/* Linux kernel style list handling function - * - * Written from scratch by Timo Teräs , but modeled - * after the linux kernel code. - * - * This file is free software: you may copy, redistribute 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. - */ - -#ifndef LIST_H -#define LIST_H - -#ifndef NULL -#define NULL 0L -#endif - -#ifndef offsetof -#ifdef __compiler_offsetof -#define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER) -#else -#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) -#endif -#endif - -#ifndef container_of -#define container_of(ptr, type, member) \ - ({ \ - const typeof(((type *)0)->member) *__mptr = (ptr); \ - (type *)((char *)__mptr - offsetof(type, member)); \ - }) -#endif - -struct hlist_head { - struct hlist_node *first; -}; - -struct hlist_node { - struct hlist_node *next; - struct hlist_node **pprev; -}; - -static inline int hlist_empty(const struct hlist_head *h) -{ - return !h->first; -} - -static inline int hlist_hashed(const struct hlist_node *n) -{ - return n->pprev != NULL; -} - -static inline void hlist_del(struct hlist_node *n) -{ - struct hlist_node *next = n->next; - struct hlist_node **pprev = n->pprev; - - *pprev = next; - if (next) - next->pprev = pprev; - - n->next = NULL; - n->pprev = NULL; -} - -static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) -{ - struct hlist_node *first = h->first; - - n->next = first; - if (first) - first->pprev = &n->next; - n->pprev = &h->first; - h->first = n; -} - -static inline void hlist_add_after(struct hlist_node *n, - struct hlist_node *prev) -{ - n->next = prev->next; - n->pprev = &prev->next; - prev->next = n; -} - -static inline struct hlist_node **hlist_tail_ptr(struct hlist_head *h) -{ - struct hlist_node *n = h->first; - if (n == NULL) - return &h->first; - while (n->next != NULL) - n = n->next; - return &n->next; -} - -#define hlist_entry(ptr, type, member) container_of(ptr,type,member) - -#define hlist_for_each(pos, head) \ - for (pos = (head)->first; pos; pos = pos->next) - -#define hlist_for_each_safe(pos, n, head) \ - for (pos = (head)->first; pos && ({ \ - n = pos->next; \ - 1; \ - }); \ - pos = n) - -#define hlist_for_each_entry(tpos, pos, head, member) \ - for (pos = (head)->first; \ - pos && ({ \ - tpos = hlist_entry(pos, typeof(*tpos), member); \ - 1; \ - }); \ - pos = pos->next) - -#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \ - for (pos = (head)->first; \ - pos && ({ \ - n = pos->next; \ - 1; \ - }) \ - && ({ \ - tpos = hlist_entry(pos, typeof(*tpos), member); \ - 1; \ - }); \ - pos = n) - - -struct list_head { - struct list_head *next, *prev; -}; - -#define LIST_INITIALIZER(l) { .next = &l, .prev = &l } - -static inline void list_init(struct list_head *list) -{ - list->next = list; - list->prev = list; -} - -static inline void __list_add(struct list_head *new, struct list_head *prev, - struct list_head *next) -{ - next->prev = new; - new->next = next; - new->prev = prev; - prev->next = new; -} - -static inline void list_add(struct list_head *new, struct list_head *head) -{ - __list_add(new, head, head->next); -} - -static inline void list_add_tail(struct list_head *new, struct list_head *head) -{ - __list_add(new, head->prev, head); -} - -static inline void __list_del(struct list_head *prev, struct list_head *next) -{ - next->prev = prev; - prev->next = next; -} - -static inline void list_del(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); - entry->next = NULL; - entry->prev = NULL; -} - -static inline int list_hashed(const struct list_head *n) -{ - return n->next != n && n->next != NULL; -} - -static inline int list_empty(const struct list_head *n) -{ - return !list_hashed(n); -} - -#define list_next(ptr, type, member) \ - (list_hashed(ptr) ? container_of((ptr)->next, type, member) : NULL) - -#define list_entry(ptr, type, member) container_of(ptr,type,member) - -#define list_for_each(pos, head) \ - for (pos = (head)->next; pos != (head); pos = pos->next) - -#define list_for_each_safe(pos, n, head) \ - for (pos = (head)->next, n = pos->next; pos != (head); \ - pos = n, n = pos->next) - -#define list_for_each_entry(pos, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member); \ - &pos->member != (head); \ - pos = list_entry(pos->member.next, typeof(*pos), member)) - -#define list_for_each_entry_safe(pos, n, head, member) \ - for (pos = ((head)->next != head ? \ - list_entry((head)->next, typeof(*pos), member) : \ - NULL), \ - n = (pos ? \ - list_entry(pos->member.next, typeof(*pos), member) : NULL); \ - pos && (&pos->member != (head)); \ - pos = n, n = list_entry(n->member.next, typeof(*n), member)) - -#endif diff --git a/nhrpd/nhrpd.h b/nhrpd/nhrpd.h index c73f51d40312..63f1cb97efb7 100644 --- a/nhrpd/nhrpd.h +++ b/nhrpd/nhrpd.h @@ -10,8 +10,6 @@ #ifndef NHRPD_H #define NHRPD_H -#include "list.h" - #include "zbuf.h" #include "zclient.h" #include "debug.h" diff --git a/nhrpd/subdir.am b/nhrpd/subdir.am index 9a186d6ed840..dc0c162c832f 100644 --- a/nhrpd/subdir.am +++ b/nhrpd/subdir.am @@ -34,7 +34,6 @@ nhrpd_nhrpd_SOURCES = \ noinst_HEADERS += \ nhrpd/debug.h \ - nhrpd/list.h \ nhrpd/netlink.h \ nhrpd/nhrp_errors.h \ nhrpd/nhrp_protocol.h \ From a1103bd3526009baeb789fb0e6d1e04b121c7c35 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 29 Sep 2021 23:37:10 +0200 Subject: [PATCH 172/188] build: add tests missed in .gitignore Signed-off-by: David Lamparter --- tests/.gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/.gitignore b/tests/.gitignore index 498d7dd0b781..8cc2aa98f92b 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -28,6 +28,7 @@ /lib/test_frrscript /lib/test_frrlua /lib/test_graph +/lib/test_grpc /lib/test_heavy /lib/test_heavy_thread /lib/test_heavy_wq @@ -44,6 +45,7 @@ /lib/test_segv /lib/test_seqlock /lib/test_sig +/lib/test_skiplist /lib/test_srcdest_table /lib/test_stream /lib/test_table From 4d619e25abbd16eb76882e55cccf24ef6bad8a4e Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 13 Oct 2021 00:00:03 +0200 Subject: [PATCH 173/188] tools: add iterators to checkpatch For the purpose of allowing the space in `frr_each (`, copy the list of iterators from .clang-format and wire it up appropriately. Signed-off-by: David Lamparter --- tools/checkpatch.pl | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/tools/checkpatch.pl b/tools/checkpatch.pl index cf15d007965d..984112de051d 100755 --- a/tools/checkpatch.pl +++ b/tools/checkpatch.pl @@ -409,6 +409,25 @@ sub hash_show_words { }x; our $c90_Keywords = qr{do|for|while|if|else|return|goto|continue|switch|default|case|break}x; +our $Iterators = qr{ + frr_each|frr_each_safe|frr_each_from| + frr_with_mutex|frr_with_privs| + LIST_FOREACH|LIST_FOREACH_SAFE| + SLIST_FOREACH|SLIST_FOREACH_SAFE|SLIST_FOREACH_PREVPTR| + STAILQ_FOREACH|STAILQ_FOREACH_SAFE| + TAILQ_FOREACH|TAILQ_FOREACH_SAFE|TAILQ_FOREACH_REVERSE|TAILQ_FOREACH_REVERSE_SAFE| + RB_FOREACH|RB_FOREACH_SAFE|RB_FOREACH_REVERSE|RB_FOREACH_REVERSE_SAFE| + SPLAY_FOREACH| + FOR_ALL_INTERFACES|FOR_ALL_INTERFACES_ADDRESSES|JSON_FOREACH| + LY_FOR_KEYS|LY_LIST_FOR|LY_TREE_FOR|LY_TREE_DFS_BEGIN|LYD_TREE_DFS_BEGIN| + RE_DEST_FOREACH_ROUTE|RE_DEST_FOREACH_ROUTE_SAFE| + RNODE_FOREACH_RE|RNODE_FOREACH_RE_SAFE| + UPDGRP_FOREACH_SUBGRP|UPDGRP_FOREACH_SUBGRP_SAFE| + SUBGRP_FOREACH_PEER|SUBGRP_FOREACH_PEER_SAFE| + SUBGRP_FOREACH_ADJ|SUBGRP_FOREACH_ADJ_SAFE| + AF_FOREACH|FOREACH_AFI_SAFI|FOREACH_SAFI| + LSDB_LOOP + }x; our $BasicType; our $NonptrType; @@ -4028,7 +4047,8 @@ sub process { if|for|while|switch|return|case| volatile|__volatile__| __attribute__|format|__extension__| - asm|__asm__)$/x) + asm|__asm__| + $Iterators)$/x) { # cpp #define statements have non-optional spaces, ie # if there is a space between the name and the open From 7c1803d0a0aa068a1b2e7256df48b0a36f46f14a Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 13 Oct 2021 00:01:43 +0200 Subject: [PATCH 174/188] tools: remove Linux kernel bits from checkpatch These aren't appropriate for use in FRR. Among other things, this enables running checkpatch by calling it in a git working tree with `tools/checkpatch.pl -g origin/master..` Signed-off-by: David Lamparter --- tools/checkpatch.pl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/checkpatch.pl b/tools/checkpatch.pl index 984112de051d..d2eb20ce5b7f 100755 --- a/tools/checkpatch.pl +++ b/tools/checkpatch.pl @@ -1028,9 +1028,9 @@ sub top_of_kernel_tree { my ($root) = @_; my @tree_check = ( - "COPYING", "CREDITS", "Kbuild", "MAINTAINERS", "Makefile", - "README", "Documentation", "arch", "include", "drivers", - "fs", "init", "ipc", "kernel", "lib", "scripts", + "COPYING", "configure.ac", "Makefile.am", + "README.md", "doc", "lib", "vtysh", "watchfrr", "tests", + "zebra", "bgpd", "ospfd", "ospf6d", "isisd", "staticd", ); foreach my $check (@tree_check) { @@ -2674,8 +2674,8 @@ sub process { (defined($1) || defined($2))))) { $is_patch = 1; $reported_maintainer_file = 1; - WARN("FILE_PATH_CHANGES", - "added, moved or deleted file(s), does MAINTAINERS need updating?\n" . $herecurr); + #WARN("FILE_PATH_CHANGES", + # "added, moved or deleted file(s), does MAINTAINERS need updating?\n" . $herecurr); } # Check for wrappage within a valid hunk of the file From de71d43e042144ca73a0ed7b1da9b6ad57f076b2 Mon Sep 17 00:00:00 2001 From: Donatas Abraitis Date: Tue, 19 Oct 2021 18:02:36 +0300 Subject: [PATCH 175/188] bgpd: Add autocomplete for filter-list Signed-off-by: Donatas Abraitis --- bgpd/bgp_route.c | 2 +- bgpd/bgp_vty.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 0eb3cc61e3f4..e1d4d22b7e74 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -12007,7 +12007,7 @@ DEFPY(show_ip_bgp, show_ip_bgp_cmd, <[all$all] dampening \ |route-map WORD\ |prefix-list WORD\ - |filter-list WORD\ + |filter-list AS_PATH_FILTER_NAME\ |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\ |A.B.C.D/M longer-prefixes\ |X:X::X:X/M longer-prefixes\ diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 26da38bd7a66..8e2044fd8abf 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -7242,7 +7242,7 @@ static int peer_aslist_unset_vty(struct vty *vty, const char *ip_str, afi_t afi, DEFUN (neighbor_filter_list, neighbor_filter_list_cmd, - "neighbor filter-list WORD ", + "neighbor filter-list AS_PATH_FILTER_NAME ", NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "Establish BGP filters\n" @@ -7259,7 +7259,7 @@ DEFUN (neighbor_filter_list, } ALIAS_HIDDEN(neighbor_filter_list, neighbor_filter_list_hidden_cmd, - "neighbor filter-list WORD ", + "neighbor filter-list AS_PATH_FILTER_NAME ", NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "Establish BGP filters\n" "AS path access-list name\n" @@ -7268,7 +7268,7 @@ ALIAS_HIDDEN(neighbor_filter_list, neighbor_filter_list_hidden_cmd, DEFUN (no_neighbor_filter_list, no_neighbor_filter_list_cmd, - "no neighbor filter-list WORD ", + "no neighbor filter-list AS_PATH_FILTER_NAME ", NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 @@ -7285,7 +7285,7 @@ DEFUN (no_neighbor_filter_list, } ALIAS_HIDDEN(no_neighbor_filter_list, no_neighbor_filter_list_hidden_cmd, - "no neighbor filter-list WORD ", + "no neighbor filter-list AS_PATH_FILTER_NAME ", NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "Establish BGP filters\n" "AS path access-list name\n" From a2099c1d640e33597e5d9a17691e741ba0ba6201 Mon Sep 17 00:00:00 2001 From: Donatas Abraitis Date: Tue, 19 Oct 2021 15:14:19 +0300 Subject: [PATCH 176/188] bgpd: Add autocomplete for community/large/extcommunity stuff ``` exit1-debian-9(config)# route-map test1 permit 10 exit1-debian-9(config-route-map)# match community ? (1-99) Community-list number (standard) (100-500) Community-list number (expanded) COMMUNITY_LIST_NAME Community-list name testas exit1-debian-9(config-route-map)# match large-community ? (1-99) Large Community-list number (standard) (100-500) Large Community-list number (expanded) LCOMMUNITY_LIST_NAME Large Community-list name LCL-ORIGINATED-ALL exit1-debian-9(config-route-map)# ``` Signed-off-by: Donatas Abraitis --- bgpd/bgp_routemap.c | 20 +++++++------- bgpd/bgp_vty.c | 64 ++++++++++++++++++++++----------------------- 2 files changed, 42 insertions(+), 42 deletions(-) diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 2f37367a8fba..ffeaa3466ec8 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -4761,7 +4761,7 @@ DEFUN_YANG(no_match_alias, no_match_alias_cmd, "no match alias [ALIAS_NAME]", DEFPY_YANG (match_community, match_community_cmd, - "match community <(1-99)|(100-500)|WORD> [exact-match]", + "match community <(1-99)|(100-500)|COMMUNITY_LIST_NAME> [exact-match]", MATCH_STR "Match BGP community list\n" "Community-list number (standard)\n" @@ -4804,7 +4804,7 @@ DEFPY_YANG (match_community, DEFUN_YANG (no_match_community, no_match_community_cmd, - "no match community [<(1-99)|(100-500)|WORD> [exact-match]]", + "no match community [<(1-99)|(100-500)|COMMUNITY_LIST_NAME> [exact-match]]", NO_STR MATCH_STR "Match BGP community list\n" @@ -4822,7 +4822,7 @@ DEFUN_YANG (no_match_community, DEFPY_YANG (match_lcommunity, match_lcommunity_cmd, - "match large-community <(1-99)|(100-500)|WORD> [exact-match]", + "match large-community <(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> [exact-match]", MATCH_STR "Match BGP large community list\n" "Large Community-list number (standard)\n" @@ -4865,7 +4865,7 @@ DEFPY_YANG (match_lcommunity, DEFUN_YANG (no_match_lcommunity, no_match_lcommunity_cmd, - "no match large-community [<(1-99)|(100-500)|WORD> [exact-match]]", + "no match large-community [<(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> [exact-match]]", NO_STR MATCH_STR "Match BGP large community list\n" @@ -4883,7 +4883,7 @@ DEFUN_YANG (no_match_lcommunity, DEFPY_YANG (match_ecommunity, match_ecommunity_cmd, - "match extcommunity <(1-99)|(100-500)|WORD>", + "match extcommunity <(1-99)|(100-500)|EXTCOMMUNITY_LIST_NAME>", MATCH_STR "Match BGP/VPN extended community list\n" "Extended community-list number (standard)\n" @@ -4909,7 +4909,7 @@ DEFPY_YANG (match_ecommunity, DEFUN_YANG (no_match_ecommunity, no_match_ecommunity_cmd, - "no match extcommunity [<(1-99)|(100-500)|WORD>]", + "no match extcommunity [<(1-99)|(100-500)|EXTCOMMUNITY_LIST_NAME>]", NO_STR MATCH_STR "Match BGP/VPN extended community list\n" @@ -5522,7 +5522,7 @@ ALIAS_YANG (no_set_community, DEFPY_YANG (set_community_delete, set_community_delete_cmd, - "set comm-list <(1-99)|(100-500)|WORD> delete", + "set comm-list <(1-99)|(100-500)|COMMUNITY_LIST_NAME> delete", SET_STR "set BGP community list (for deletion)\n" "Community-list number (standard)\n" @@ -5549,7 +5549,7 @@ DEFPY_YANG (set_community_delete, DEFUN_YANG (no_set_community_delete, no_set_community_delete_cmd, - "no set comm-list [<(1-99)|(100-500)|WORD> delete]", + "no set comm-list [<(1-99)|(100-500)|COMMUNITY_LIST_NAME> delete]", NO_STR SET_STR "set BGP community list (for deletion)\n" @@ -5649,7 +5649,7 @@ ALIAS_YANG (no_set_lcommunity1, DEFPY_YANG (set_lcommunity_delete, set_lcommunity_delete_cmd, - "set large-comm-list <(1-99)|(100-500)|WORD> delete", + "set large-comm-list <(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> delete", SET_STR "set BGP large community list (for deletion)\n" "Large Community-list number (standard)\n" @@ -5675,7 +5675,7 @@ DEFPY_YANG (set_lcommunity_delete, DEFUN_YANG (no_set_lcommunity_delete, no_set_lcommunity_delete_cmd, - "no set large-comm-list <(1-99)|(100-500)|WORD> [delete]", + "no set large-comm-list <(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> [delete]", NO_STR SET_STR "set BGP large community list (for deletion)\n" diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 26da38bd7a66..4d972c064293 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -19061,7 +19061,7 @@ static void community_list_perror(struct vty *vty, int ret) /*community-list standard */ DEFUN (community_list_standard, bgp_community_list_standard_cmd, - "bgp community-list <(1-99)|standard WORD> [seq (0-4294967295)] AA:NN...", + "bgp community-list <(1-99)|standard COMMUNITY_LIST_NAME> [seq (0-4294967295)] AA:NN...", BGP_STR COMMUNITY_LIST_STR "Community list number (standard)\n" @@ -19085,7 +19085,7 @@ DEFUN (community_list_standard, idx = 0; argv_find(argv, argc, "(1-99)", &idx); - argv_find(argv, argc, "WORD", &idx); + argv_find(argv, argc, "COMMUNITY_LIST_NAME", &idx); cl_name_or_number = argv[idx]->arg; direct = argv_find(argv, argc, "permit", &idx) ? COMMUNITY_PERMIT : COMMUNITY_DENY; @@ -19108,7 +19108,7 @@ DEFUN (community_list_standard, DEFUN (no_community_list_standard_all, no_bgp_community_list_standard_all_cmd, - "no bgp community-list <(1-99)|standard WORD> [seq (0-4294967295)] AA:NN...", + "no bgp community-list <(1-99)|standard COMMUNITY_LIST_NAME> [seq (0-4294967295)] AA:NN...", NO_STR BGP_STR COMMUNITY_LIST_STR @@ -19148,7 +19148,7 @@ DEFUN (no_community_list_standard_all, idx = 0; argv_find(argv, argc, "(1-99)", &idx); - argv_find(argv, argc, "WORD", &idx); + argv_find(argv, argc, "COMMUNITY_LIST_NAME", &idx); cl_name_or_number = argv[idx]->arg; int ret = community_list_unset(bgp_clist, cl_name_or_number, str, seq, @@ -19165,7 +19165,7 @@ DEFUN (no_community_list_standard_all, } ALIAS(no_community_list_standard_all, no_bgp_community_list_standard_all_list_cmd, - "no bgp community-list <(1-99)|standard WORD>", + "no bgp community-list <(1-99)|standard COMMUNITY_LIST_NAME>", NO_STR BGP_STR COMMUNITY_LIST_STR "Community list number (standard)\n" "Add an standard community-list entry\n" @@ -19174,7 +19174,7 @@ ALIAS(no_community_list_standard_all, no_bgp_community_list_standard_all_list_cm /*community-list expanded */ DEFUN (community_list_expanded_all, bgp_community_list_expanded_all_cmd, - "bgp community-list <(100-500)|expanded WORD> [seq (0-4294967295)] AA:NN...", + "bgp community-list <(100-500)|expanded COMMUNITY_LIST_NAME> [seq (0-4294967295)] AA:NN...", BGP_STR COMMUNITY_LIST_STR "Community list number (expanded)\n" @@ -19199,7 +19199,7 @@ DEFUN (community_list_expanded_all, idx = 0; argv_find(argv, argc, "(100-500)", &idx); - argv_find(argv, argc, "WORD", &idx); + argv_find(argv, argc, "COMMUNITY_LIST_NAME", &idx); cl_name_or_number = argv[idx]->arg; direct = argv_find(argv, argc, "permit", &idx) ? COMMUNITY_PERMIT : COMMUNITY_DENY; @@ -19222,7 +19222,7 @@ DEFUN (community_list_expanded_all, DEFUN (no_community_list_expanded_all, no_bgp_community_list_expanded_all_cmd, - "no bgp community-list <(100-500)|expanded WORD> [seq (0-4294967295)] AA:NN...", + "no bgp community-list <(100-500)|expanded COMMUNITY_LIST_NAME> [seq (0-4294967295)] AA:NN...", NO_STR BGP_STR COMMUNITY_LIST_STR @@ -19262,7 +19262,7 @@ DEFUN (no_community_list_expanded_all, idx = 0; argv_find(argv, argc, "(100-500)", &idx); - argv_find(argv, argc, "WORD", &idx); + argv_find(argv, argc, "COMMUNITY_LIST_NAME", &idx); cl_name_or_number = argv[idx]->arg; int ret = community_list_unset(bgp_clist, cl_name_or_number, str, seq, @@ -19280,7 +19280,7 @@ DEFUN (no_community_list_expanded_all, ALIAS(no_community_list_expanded_all, no_bgp_community_list_expanded_all_list_cmd, - "no bgp community-list <(100-500)|expanded WORD>", + "no bgp community-list <(100-500)|expanded COMMUNITY_LIST_NAME>", NO_STR BGP_STR COMMUNITY_LIST_STR "Community list number (expanded)\n" "Add an expanded community-list entry\n" @@ -19358,7 +19358,7 @@ DEFUN (show_community_list, DEFUN (show_community_list_arg, show_bgp_community_list_arg_cmd, - "show bgp community-list <(1-500)|WORD> detail", + "show bgp community-list <(1-500)|COMMUNITY_LIST_NAME> detail", SHOW_STR BGP_STR "List community-list\n" @@ -19404,7 +19404,7 @@ static int lcommunity_list_set_vty(struct vty *vty, int argc, /* All digit name check. */ idx = 0; - argv_find(argv, argc, "WORD", &idx); + argv_find(argv, argc, "LCOMMUNITY_LIST_NAME", &idx); argv_find(argv, argc, "(1-99)", &idx); argv_find(argv, argc, "(100-500)", &idx); cl_name = argv[idx]->arg; @@ -19468,7 +19468,7 @@ static int lcommunity_list_unset_vty(struct vty *vty, int argc, idx = 0; argv_find(argv, argc, "(1-99)", &idx); argv_find(argv, argc, "(100-500)", &idx); - argv_find(argv, argc, "WORD", &idx); + argv_find(argv, argc, "LCOMMUNITY_LIST_NAME", &idx); /* Unset community list. */ ret = lcommunity_list_unset(bgp_clist, argv[idx]->arg, str, seq, direct, @@ -19524,7 +19524,7 @@ DEFUN (lcommunity_list_expanded, DEFUN (lcommunity_list_name_standard, bgp_lcommunity_list_name_standard_cmd, - "bgp large-community-list standard WORD [seq (0-4294967295)] AA:BB:CC...", + "bgp large-community-list standard LCOMMUNITY_LIST_NAME [seq (0-4294967295)] AA:BB:CC...", BGP_STR LCOMMUNITY_LIST_STR "Specify standard large-community-list\n" @@ -19541,7 +19541,7 @@ DEFUN (lcommunity_list_name_standard, DEFUN (lcommunity_list_name_expanded, bgp_lcommunity_list_name_expanded_cmd, - "bgp large-community-list expanded WORD [seq (0-4294967295)] LINE...", + "bgp large-community-list expanded LCOMMUNITY_LIST_NAME [seq (0-4294967295)] LINE...", BGP_STR LCOMMUNITY_LIST_STR "Specify expanded large-community-list\n" @@ -19558,7 +19558,7 @@ DEFUN (lcommunity_list_name_expanded, DEFUN (no_lcommunity_list_all, no_bgp_lcommunity_list_all_cmd, - "no bgp large-community-list <(1-99)|(100-500)|WORD>", + "no bgp large-community-list <(1-99)|(100-500)|LCOMMUNITY_LIST_NAME>", NO_STR BGP_STR LCOMMUNITY_LIST_STR @@ -19572,7 +19572,7 @@ DEFUN (no_lcommunity_list_all, DEFUN (no_lcommunity_list_name_standard_all, no_bgp_lcommunity_list_name_standard_all_cmd, - "no bgp large-community-list standard WORD", + "no bgp large-community-list standard LCOMMUNITY_LIST_NAME", NO_STR BGP_STR LCOMMUNITY_LIST_STR @@ -19585,7 +19585,7 @@ DEFUN (no_lcommunity_list_name_standard_all, DEFUN (no_lcommunity_list_name_expanded_all, no_bgp_lcommunity_list_name_expanded_all_cmd, - "no bgp large-community-list expanded WORD", + "no bgp large-community-list expanded LCOMMUNITY_LIST_NAME", NO_STR BGP_STR LCOMMUNITY_LIST_STR @@ -19632,7 +19632,7 @@ DEFUN (no_lcommunity_list_expanded, DEFUN (no_lcommunity_list_name_standard, no_bgp_lcommunity_list_name_standard_cmd, - "no bgp large-community-list standard WORD [seq (0-4294967295)] AA:AA:NN...", + "no bgp large-community-list standard LCOMMUNITY_LIST_NAME [seq (0-4294967295)] AA:AA:NN...", NO_STR BGP_STR LCOMMUNITY_LIST_STR @@ -19650,7 +19650,7 @@ DEFUN (no_lcommunity_list_name_standard, DEFUN (no_lcommunity_list_name_expanded, no_bgp_lcommunity_list_name_expanded_cmd, - "no bgp large-community-list expanded WORD [seq (0-4294967295)] LINE...", + "no bgp large-community-list expanded LCOMMUNITY_LIST_NAME [seq (0-4294967295)] LINE...", NO_STR BGP_STR LCOMMUNITY_LIST_STR @@ -19724,7 +19724,7 @@ DEFUN (show_lcommunity_list, DEFUN (show_lcommunity_list_arg, show_bgp_lcommunity_list_arg_cmd, - "show bgp large-community-list <(1-500)|WORD> detail", + "show bgp large-community-list <(1-500)|LCOMMUNITY_LIST_NAME> detail", SHOW_STR BGP_STR "List large-community list\n" @@ -19752,7 +19752,7 @@ DEFUN (show_lcommunity_list_arg, DEFUN (extcommunity_list_standard, bgp_extcommunity_list_standard_cmd, - "bgp extcommunity-list <(1-99)|standard WORD> [seq (0-4294967295)] AA:NN...", + "bgp extcommunity-list <(1-99)|standard EXTCOMMUNITY_LIST_NAME> [seq (0-4294967295)] AA:NN...", BGP_STR EXTCOMMUNITY_LIST_STR "Extended Community list number (standard)\n" @@ -19772,7 +19772,7 @@ DEFUN (extcommunity_list_standard, int idx = 0; argv_find(argv, argc, "(1-99)", &idx); - argv_find(argv, argc, "WORD", &idx); + argv_find(argv, argc, "EXTCOMMUNITY_LIST_NAME", &idx); cl_number_or_name = argv[idx]->arg; if (argv_find(argv, argc, "(0-4294967295)", &idx)) @@ -19798,7 +19798,7 @@ DEFUN (extcommunity_list_standard, DEFUN (extcommunity_list_name_expanded, bgp_extcommunity_list_name_expanded_cmd, - "bgp extcommunity-list <(100-500)|expanded WORD> [seq (0-4294967295)] LINE...", + "bgp extcommunity-list <(100-500)|expanded EXTCOMMUNITY_LIST_NAME> [seq (0-4294967295)] LINE...", BGP_STR EXTCOMMUNITY_LIST_STR "Extended Community list number (expanded)\n" @@ -19817,7 +19817,7 @@ DEFUN (extcommunity_list_name_expanded, int idx = 0; argv_find(argv, argc, "(100-500)", &idx); - argv_find(argv, argc, "WORD", &idx); + argv_find(argv, argc, "EXTCOMMUNITY_LIST_NAME", &idx); cl_number_or_name = argv[idx]->arg; if (argv_find(argv, argc, "(0-4294967295)", &idx)) @@ -19843,7 +19843,7 @@ DEFUN (extcommunity_list_name_expanded, DEFUN (no_extcommunity_list_standard_all, no_bgp_extcommunity_list_standard_all_cmd, - "no bgp extcommunity-list <(1-99)|standard WORD> [seq (0-4294967295)] AA:NN...", + "no bgp extcommunity-list <(1-99)|standard EXTCOMMUNITY_LIST_NAME> [seq (0-4294967295)] AA:NN...", NO_STR BGP_STR EXTCOMMUNITY_LIST_STR @@ -19881,7 +19881,7 @@ DEFUN (no_extcommunity_list_standard_all, idx = 0; argv_find(argv, argc, "(1-99)", &idx); - argv_find(argv, argc, "WORD", &idx); + argv_find(argv, argc, "EXTCOMMUNITY_LIST_NAME", &idx); cl_number_or_name = argv[idx]->arg; int ret = extcommunity_list_unset(bgp_clist, cl_number_or_name, str, @@ -19899,7 +19899,7 @@ DEFUN (no_extcommunity_list_standard_all, ALIAS(no_extcommunity_list_standard_all, no_bgp_extcommunity_list_standard_all_list_cmd, - "no bgp extcommunity-list <(1-99)|standard WORD>", + "no bgp extcommunity-list <(1-99)|standard EXTCOMMUNITY_LIST_NAME>", NO_STR BGP_STR EXTCOMMUNITY_LIST_STR "Extended Community list number (standard)\n" "Specify standard extcommunity-list\n" @@ -19907,7 +19907,7 @@ ALIAS(no_extcommunity_list_standard_all, DEFUN (no_extcommunity_list_expanded_all, no_bgp_extcommunity_list_expanded_all_cmd, - "no bgp extcommunity-list <(100-500)|expanded WORD> [seq (0-4294967295)] LINE...", + "no bgp extcommunity-list <(100-500)|expanded EXTCOMMUNITY_LIST_NAME> [seq (0-4294967295)] LINE...", NO_STR BGP_STR EXTCOMMUNITY_LIST_STR @@ -19946,7 +19946,7 @@ DEFUN (no_extcommunity_list_expanded_all, idx = 0; argv_find(argv, argc, "(100-500)", &idx); - argv_find(argv, argc, "WORD", &idx); + argv_find(argv, argc, "EXTCOMMUNITY_LIST_NAME", &idx); cl_number_or_name = argv[idx]->arg; int ret = extcommunity_list_unset(bgp_clist, cl_number_or_name, str, @@ -19964,7 +19964,7 @@ DEFUN (no_extcommunity_list_expanded_all, ALIAS(no_extcommunity_list_expanded_all, no_bgp_extcommunity_list_expanded_all_list_cmd, - "no bgp extcommunity-list <(100-500)|expanded WORD>", + "no bgp extcommunity-list <(100-500)|expanded EXTCOMMUNITY_LIST_NAME>", NO_STR BGP_STR EXTCOMMUNITY_LIST_STR "Extended Community list number (expanded)\n" "Specify expanded extcommunity-list\n" @@ -20025,7 +20025,7 @@ DEFUN (show_extcommunity_list, DEFUN (show_extcommunity_list_arg, show_bgp_extcommunity_list_arg_cmd, - "show bgp extcommunity-list <(1-500)|WORD> detail", + "show bgp extcommunity-list <(1-500)|EXTCOMMUNITY_LIST_NAME> detail", SHOW_STR BGP_STR "List extended-community list\n" From e15a935c06b8b339940926d908dc250ecd6bda0d Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 20 Oct 2021 08:00:02 -0400 Subject: [PATCH 177/188] ospfd: Close log files before exiting When doing a normal exit from ospf we should close the log file as that we are leaving a bunch of unterminated logging processes by not doing so. Signed-off-by: Donald Sharp --- ospfd/ospfd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index 766be6077805..1e1057dc39e1 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -582,6 +582,7 @@ static void ospf_deferred_shutdown_finish(struct ospf *ospf) /* ospfd being shut-down? If so, was this the last ospf instance? */ if (CHECK_FLAG(om->options, OSPF_MASTER_SHUTDOWN) && (listcount(om->ospf) == 0)) { + frr_fini(); exit(0); } From 6865ffa758d358ba2ed1f94bef9ad53b05652db9 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 20 Oct 2021 08:00:57 -0400 Subject: [PATCH 178/188] pathd: Call frr_fini() before exit pathd was never calling frr_fini and as such the proper shutdown was not happening for libfrr. This includes logging. Signed-off-by: Donald Sharp --- pathd/pathd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pathd/pathd.c b/pathd/pathd.c index 90b87272844a..7f6d34f752b2 100644 --- a/pathd/pathd.c +++ b/pathd/pathd.c @@ -22,6 +22,7 @@ #include "log.h" #include "lib_errors.h" #include "network.h" +#include "libfrr.h" #include "pathd/pathd.h" #include "pathd/path_zebra.h" @@ -1223,6 +1224,7 @@ void pathd_shutdown(void) { path_ted_teardown(); srte_clean_zebra(); + frr_fini(); } void trigger_pathd_candidate_created(struct srte_candidate *candidate) From e9a59a2a597c08f2141e10c848a9feb73956bd8b Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 20 Oct 2021 08:02:10 -0400 Subject: [PATCH 179/188] tests: When heavily loaded do not send SIGBUS so fast Our topotests send SIGBUS 2 seconds after a SIGTERM is initiated. This is bad because under a heavily loaded topotest system we may have a case where the system has not had a chance to properly shut down the daemon. Extend the time greatly before topotests send SIGBUS. Signed-off-by: Donald Sharp --- tests/topotests/lib/topotest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/topotests/lib/topotest.py b/tests/topotests/lib/topotest.py index b98698185c26..947ea196b6d3 100644 --- a/tests/topotests/lib/topotest.py +++ b/tests/topotests/lib/topotest.py @@ -1445,7 +1445,7 @@ def stopRouter(self, assertOnError=True, minErrorVersion="5.1"): running = self.listDaemons() if running: - for _ in range(0, 5): + for _ in range(0, 30): sleep( 0.5, "{}: waiting for daemons stopping: {}".format( From a505383d6a42259b96f5882b493f328bc1dd9301 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 12 Oct 2021 13:22:54 -0400 Subject: [PATCH 180/188] lib: Add a thread_is_scheduled function The function thread_is_scheduled allows us to know if the particular thread is scheduled for execution or not. Signed-off-by: Donald Sharp --- lib/thread.c | 8 ++++++++ lib/thread.h | 1 + 2 files changed, 9 insertions(+) diff --git a/lib/thread.c b/lib/thread.c index 835aa38115ad..71d7798af51a 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -2059,3 +2059,11 @@ void debug_signals(const sigset_t *sigs) zlog_debug("%s: %s", __func__, buf); } + +bool thread_is_scheduled(struct thread *thread) +{ + if (thread == NULL) + return false; + + return true; +} diff --git a/lib/thread.h b/lib/thread.h index abd94ff4f059..c5f0ffbf773d 100644 --- a/lib/thread.h +++ b/lib/thread.h @@ -273,6 +273,7 @@ extern pthread_key_t thread_current; extern char *thread_timer_to_hhmmss(char *buf, int buf_size, struct thread *t_timer); +extern bool thread_is_scheduled(struct thread *thread); /* Debug signal mask */ void debug_signals(const sigset_t *sigs); From e13f12a7d147a993a0aefd0b2b0ba947746071b4 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 12 Oct 2021 13:23:40 -0400 Subject: [PATCH 181/188] zebra: modify rib_update to be a bit smarter about malloc rib_update() was mallocing memory then attempting to schedule and if the schedule failed( it was already going to be run ) FRR would then free the memory. Fix this memory usage pattern Signed-off-by: Donald Sharp --- zebra/zebra_rib.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 12e82dde9488..fcac3328c97b 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -3890,14 +3890,16 @@ void rib_update(enum rib_update_event event) { struct rib_update_ctx *ctx; - ctx = rib_update_ctx_init(0, event); + if (thread_is_scheduled(t_rib_update_threads[event])) + return; + ctx = rib_update_ctx_init(0, event); ctx->vrf_all = true; - if (!thread_add_event(zrouter.master, rib_update_handler, ctx, 0, - &t_rib_update_threads[event])) - rib_update_ctx_fini(&ctx); /* Already scheduled */ - else if (IS_ZEBRA_DEBUG_EVENT) + thread_add_event(zrouter.master, rib_update_handler, ctx, 0, + &t_rib_update_threads[event]); + + if (IS_ZEBRA_DEBUG_EVENT) zlog_debug("%s: Scheduled VRF (ALL), event %s", __func__, rib_update_event2str(event)); } From e8e6febb746c52354396e4004fccc46ef4dde684 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 20 Oct 2021 10:15:41 -0400 Subject: [PATCH 182/188] zebra: Fix code paths that always resolve to true Signed-off-by: Donald Sharp --- zebra/zebra_l2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zebra/zebra_l2.c b/zebra/zebra_l2.c index 5a02149611fb..30e74902aa10 100644 --- a/zebra/zebra_l2.c +++ b/zebra/zebra_l2.c @@ -431,10 +431,10 @@ void zebra_l2if_update_bridge_slave(struct interface *ifp, if (zif->zif_type == ZEBRA_IF_VXLAN && chgflags != ZEBRA_BRIDGE_NO_ACTION) { - if (ZEBRA_BRIDGE_MASTER_MAC_CHANGE) + if (chgflags & ZEBRA_BRIDGE_MASTER_MAC_CHANGE) zebra_vxlan_if_update(ifp, ZEBRA_VXLIF_MASTER_MAC_CHANGE); - if (ZEBRA_BRIDGE_MASTER_UP) + if (chgflags & ZEBRA_BRIDGE_MASTER_UP) zebra_vxlan_if_update(ifp, ZEBRA_VXLIF_MASTER_CHANGE); } old_bridge_ifindex = zif->brslave_info.bridge_ifindex; From ee1455dd983e2b19018890c2da5e22bb97b3adb7 Mon Sep 17 00:00:00 2001 From: Igor Ryzhov Date: Wed, 6 Oct 2021 22:06:23 +0300 Subject: [PATCH 183/188] lib: change thread_add_* API Do not return pointer to the newly created thread from various thread_add functions. This should prevent developers from storing a thread pointer into some variable without letting the lib know that the pointer is stored. When the lib doesn't know that the pointer is stored, it doesn't prevent rescheduling and it can lead to hard to find bugs. If someone wants to store the pointer, they should pass a double pointer as the last argument. Signed-off-by: Igor Ryzhov --- lib/thread.c | 63 ++++++++++++++++---------------------- lib/thread.h | 44 ++++++++++++++------------ lib/vty.c | 16 +++++----- ospfd/ospf_lsa.c | 4 --- ospfd/ospf_lsa.h | 4 --- zebra/zebra_netns_notify.c | 8 ++--- 6 files changed, 63 insertions(+), 76 deletions(-) diff --git a/lib/thread.c b/lib/thread.c index 71d7798af51a..5dbba6363d05 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -922,10 +922,10 @@ static int fd_poll(struct thread_master *m, const struct timeval *timer_wait, } /* Add new read thread. */ -struct thread *_thread_add_read_write(const struct xref_threadsched *xref, - struct thread_master *m, - int (*func)(struct thread *), - void *arg, int fd, struct thread **t_ptr) +void _thread_add_read_write(const struct xref_threadsched *xref, + struct thread_master *m, + int (*func)(struct thread *), void *arg, int fd, + struct thread **t_ptr) { int dir = xref->thread_type; struct thread *thread = NULL; @@ -1000,15 +1000,13 @@ struct thread *_thread_add_read_write(const struct xref_threadsched *xref, AWAKEN(m); } - - return thread; } -static struct thread * -_thread_add_timer_timeval(const struct xref_threadsched *xref, - struct thread_master *m, int (*func)(struct thread *), - void *arg, struct timeval *time_relative, - struct thread **t_ptr) +static void _thread_add_timer_timeval(const struct xref_threadsched *xref, + struct thread_master *m, + int (*func)(struct thread *), void *arg, + struct timeval *time_relative, + struct thread **t_ptr) { struct thread *thread; struct timeval t; @@ -1028,7 +1026,7 @@ _thread_add_timer_timeval(const struct xref_threadsched *xref, frr_with_mutex(&m->mtx) { if (t_ptr && *t_ptr) /* thread is already scheduled; don't reschedule */ - return NULL; + return; thread = thread_get(m, THREAD_TIMER, func, arg, xref); @@ -1048,16 +1046,13 @@ _thread_add_timer_timeval(const struct xref_threadsched *xref, if (thread_timer_list_first(&m->timer) == thread) AWAKEN(m); } - - return thread; } /* Add timer event thread. */ -struct thread *_thread_add_timer(const struct xref_threadsched *xref, - struct thread_master *m, - int (*func)(struct thread *), - void *arg, long timer, struct thread **t_ptr) +void _thread_add_timer(const struct xref_threadsched *xref, + struct thread_master *m, int (*func)(struct thread *), + void *arg, long timer, struct thread **t_ptr) { struct timeval trel; @@ -1066,15 +1061,14 @@ struct thread *_thread_add_timer(const struct xref_threadsched *xref, trel.tv_sec = timer; trel.tv_usec = 0; - return _thread_add_timer_timeval(xref, m, func, arg, &trel, t_ptr); + _thread_add_timer_timeval(xref, m, func, arg, &trel, t_ptr); } /* Add timer event thread with "millisecond" resolution */ -struct thread *_thread_add_timer_msec(const struct xref_threadsched *xref, - struct thread_master *m, - int (*func)(struct thread *), - void *arg, long timer, - struct thread **t_ptr) +void _thread_add_timer_msec(const struct xref_threadsched *xref, + struct thread_master *m, + int (*func)(struct thread *), void *arg, long timer, + struct thread **t_ptr) { struct timeval trel; @@ -1083,24 +1077,21 @@ struct thread *_thread_add_timer_msec(const struct xref_threadsched *xref, trel.tv_sec = timer / 1000; trel.tv_usec = 1000 * (timer % 1000); - return _thread_add_timer_timeval(xref, m, func, arg, &trel, t_ptr); + _thread_add_timer_timeval(xref, m, func, arg, &trel, t_ptr); } /* Add timer event thread with "timeval" resolution */ -struct thread *_thread_add_timer_tv(const struct xref_threadsched *xref, - struct thread_master *m, - int (*func)(struct thread *), - void *arg, struct timeval *tv, - struct thread **t_ptr) +void _thread_add_timer_tv(const struct xref_threadsched *xref, + struct thread_master *m, int (*func)(struct thread *), + void *arg, struct timeval *tv, struct thread **t_ptr) { - return _thread_add_timer_timeval(xref, m, func, arg, tv, t_ptr); + _thread_add_timer_timeval(xref, m, func, arg, tv, t_ptr); } /* Add simple event thread. */ -struct thread *_thread_add_event(const struct xref_threadsched *xref, - struct thread_master *m, - int (*func)(struct thread *), - void *arg, int val, struct thread **t_ptr) +void _thread_add_event(const struct xref_threadsched *xref, + struct thread_master *m, int (*func)(struct thread *), + void *arg, int val, struct thread **t_ptr) { struct thread *thread = NULL; @@ -1128,8 +1119,6 @@ struct thread *_thread_add_event(const struct xref_threadsched *xref, AWAKEN(m); } - - return thread; } /* Thread cancellation ------------------------------------------------------ */ diff --git a/lib/thread.h b/lib/thread.h index c5f0ffbf773d..39f21da11d33 100644 --- a/lib/thread.h +++ b/lib/thread.h @@ -219,26 +219,30 @@ void thread_master_set_name(struct thread_master *master, const char *name); extern void thread_master_free(struct thread_master *); extern void thread_master_free_unused(struct thread_master *); -extern struct thread *_thread_add_read_write( - const struct xref_threadsched *xref, struct thread_master *master, - int (*fn)(struct thread *), void *arg, int fd, struct thread **tref); - -extern struct thread *_thread_add_timer( - const struct xref_threadsched *xref, struct thread_master *master, - int (*fn)(struct thread *), void *arg, long t, struct thread **tref); - -extern struct thread *_thread_add_timer_msec( - const struct xref_threadsched *xref, struct thread_master *master, - int (*fn)(struct thread *), void *arg, long t, struct thread **tref); - -extern struct thread *_thread_add_timer_tv( - const struct xref_threadsched *xref, struct thread_master *master, - int (*fn)(struct thread *), void *arg, struct timeval *tv, - struct thread **tref); - -extern struct thread *_thread_add_event( - const struct xref_threadsched *xref, struct thread_master *master, - int (*fn)(struct thread *), void *arg, int val, struct thread **tref); +extern void _thread_add_read_write(const struct xref_threadsched *xref, + struct thread_master *master, + int (*fn)(struct thread *), void *arg, + int fd, struct thread **tref); + +extern void _thread_add_timer(const struct xref_threadsched *xref, + struct thread_master *master, + int (*fn)(struct thread *), void *arg, long t, + struct thread **tref); + +extern void _thread_add_timer_msec(const struct xref_threadsched *xref, + struct thread_master *master, + int (*fn)(struct thread *), void *arg, + long t, struct thread **tref); + +extern void _thread_add_timer_tv(const struct xref_threadsched *xref, + struct thread_master *master, + int (*fn)(struct thread *), void *arg, + struct timeval *tv, struct thread **tref); + +extern void _thread_add_event(const struct xref_threadsched *xref, + struct thread_master *master, + int (*fn)(struct thread *), void *arg, int val, + struct thread **tref); extern void _thread_execute(const struct xref_threadsched *xref, struct thread_master *master, diff --git a/lib/vty.c b/lib/vty.c index fef16f1ee7a6..11a2fe0d9c40 100644 --- a/lib/vty.c +++ b/lib/vty.c @@ -2697,19 +2697,21 @@ static struct thread_master *vty_master; static void vty_event_serv(enum event event, int sock) { - struct thread *vty_serv_thread = NULL; + struct thread **vty_serv_thread_ptr = NULL; switch (event) { case VTY_SERV: - vty_serv_thread = thread_add_read(vty_master, vty_accept, - NULL, sock, NULL); - vector_set_index(Vvty_serv_thread, sock, vty_serv_thread); + vty_serv_thread_ptr = (struct thread **)vector_get_index( + Vvty_serv_thread, sock); + thread_add_read(vty_master, vty_accept, NULL, sock, + vty_serv_thread_ptr); break; #ifdef VTYSH case VTYSH_SERV: - vty_serv_thread = thread_add_read(vty_master, vtysh_accept, - NULL, sock, NULL); - vector_set_index(Vvty_serv_thread, sock, vty_serv_thread); + vty_serv_thread_ptr = (struct thread **)vector_get_index( + Vvty_serv_thread, sock); + thread_add_read(vty_master, vtysh_accept, NULL, sock, + vty_serv_thread_ptr); break; #endif /* VTYSH */ default: diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index cc1b2919c0cc..10541b09bb89 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -2480,10 +2480,6 @@ ospf_router_lsa_install(struct ospf *ospf, struct ospf_lsa *new, int rt_recalc) return new; } -#define OSPF_INTERFACE_TIMER_ON(T, F, V) \ - if (!(T)) \ - (T) = thread_add_timer(master, (F), oi, (V)) - /* Install network-LSA to an area. */ static struct ospf_lsa *ospf_network_lsa_install(struct ospf *ospf, struct ospf_interface *oi, diff --git a/ospfd/ospf_lsa.h b/ospfd/ospf_lsa.h index 5dcd0727749d..2e648b335437 100644 --- a/ospfd/ospf_lsa.h +++ b/ospfd/ospf_lsa.h @@ -223,10 +223,6 @@ struct as_external_lsa { #define OSPF_LSA_UPDATE_DELAY 2 -#define OSPF_LSA_UPDATE_TIMER_ON(T, F) \ - if (!(T)) \ - (T) = thread_add_timer(master, (F), 0, 2) - #define CHECK_LSA_TYPE_1_TO_5_OR_7(type) \ ((type == OSPF_ROUTER_LSA) || (type == OSPF_NETWORK_LSA) \ || (type == OSPF_SUMMARY_LSA) || (type == OSPF_ASBR_SUMMARY_LSA) \ diff --git a/zebra/zebra_netns_notify.c b/zebra/zebra_netns_notify.c index 61f97ce6a948..2d2580159063 100644 --- a/zebra/zebra_netns_notify.c +++ b/zebra/zebra_netns_notify.c @@ -249,8 +249,8 @@ static int zebra_ns_notify_read(struct thread *t) char buf[BUFSIZ]; ssize_t len; - zebra_netns_notify_current = thread_add_read( - zrouter.master, zebra_ns_notify_read, NULL, fd_monitor, NULL); + thread_add_read(zrouter.master, zebra_ns_notify_read, NULL, fd_monitor, + &zebra_netns_notify_current); len = read(fd_monitor, buf, sizeof(buf)); if (len < 0) { flog_err_sys(EC_ZEBRA_NS_NOTIFY_READ, @@ -359,8 +359,8 @@ void zebra_ns_notify_init(void) "NS notify watch: failed to add watch (%s)", safe_strerror(errno)); } - zebra_netns_notify_current = thread_add_read( - zrouter.master, zebra_ns_notify_read, NULL, fd_monitor, NULL); + thread_add_read(zrouter.master, zebra_ns_notify_read, NULL, fd_monitor, + &zebra_netns_notify_current); } void zebra_ns_notify_close(void) From db52be551b4786d1e086d5830c11a9f9e0275f1f Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Tue, 10 Dec 2019 10:54:27 +0100 Subject: [PATCH 184/188] nhrpd: align nhrp privs with definition from others nhrp_privs global context is aligned with other daemon contexts Signed-off-by: Philippe Guibert --- nhrpd/nhrp_main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nhrpd/nhrp_main.c b/nhrpd/nhrp_main.c index 73684046a8c1..4c98f02e1d35 100644 --- a/nhrpd/nhrp_main.c +++ b/nhrpd/nhrp_main.c @@ -55,8 +55,10 @@ struct zebra_privs_t nhrpd_privs = { #endif .caps_p = _caps_p, .cap_num_p = array_size(_caps_p), + .cap_num_i = 0 }; + static void parse_arguments(int argc, char **argv) { int opt; From 03bad95aa474eeaa73856a71085fa3f9f45d96fa Mon Sep 17 00:00:00 2001 From: ewlumpkin Date: Fri, 22 Oct 2021 02:56:56 +0000 Subject: [PATCH 185/188] lib: finish fixing spelling in lib files Signed-off-by: ewlumpkin --- lib/sockopt.c | 4 ++-- lib/table.c | 2 +- lib/vty.c | 6 +++--- lib/vxlan.h | 2 +- lib/yang.h | 2 +- lib/zclient.c | 20 ++++++++++---------- lib/zclient.h | 4 ++-- 7 files changed, 20 insertions(+), 20 deletions(-) diff --git a/lib/sockopt.c b/lib/sockopt.c index 150736e00c93..45f3c2333073 100644 --- a/lib/sockopt.c +++ b/lib/sockopt.c @@ -122,7 +122,7 @@ int setsockopt_ipv6_pktinfo(int sock, int val) if (ret < 0) flog_err(EC_LIB_SOCKET, "can't setsockopt IPV6_PKTINFO : %s", safe_strerror(errno)); -#endif /* INIA_IPV6 */ +#endif /* IANA_IPV6 */ return ret; } @@ -595,7 +595,7 @@ int sockopt_tcp_signature_ext(int sock, union sockunion *su, uint16_t prefixlen, /* If this does not work, then all users of this sockopt will * need to - * differentiate between IPv4 and IPv6, and keep seperate + * differentiate between IPv4 and IPv6, and keep separate * sockets for * each. * diff --git a/lib/table.c b/lib/table.c index e6030ca4cab7..523183bef228 100644 --- a/lib/table.c +++ b/lib/table.c @@ -393,7 +393,7 @@ void route_node_delete(struct route_node *node) route_node_delete(parent); } -/* Get fist node and lock it. This function is useful when one want +/* Get first node and lock it. This function is useful when one wants to lookup all the node exist in the routing table. */ struct route_node *route_top(struct route_table *table) { diff --git a/lib/vty.c b/lib/vty.c index fef16f1ee7a6..df26cae5410f 100644 --- a/lib/vty.c +++ b/lib/vty.c @@ -776,7 +776,7 @@ static void vty_end_config(struct vty *vty) vty->cp = 0; } -/* Delete a charcter at the current point. */ +/* Delete a character at the current point. */ static void vty_delete_char(struct vty *vty) { int i; @@ -2282,7 +2282,7 @@ static void vty_read_file(struct nb_config *config, FILE *confp) vty = vty_new(); /* vty_close won't close stderr; if some config command prints - * something it'll end up there. (not ideal; it'd be beter if output + * something it'll end up there. (not ideal; it'd be better if output * from a file-load went to logging instead. Also note that if this * function is called after daemonizing, stderr will be /dev/null.) * @@ -3165,7 +3165,7 @@ void vty_init(struct thread_master *master_thread, bool do_command_logging) atexit(vty_stdio_atexit); - /* Initilize server thread vector. */ + /* Initialize server thread vector. */ Vvty_serv_thread = vector_init(VECTOR_MIN_SIZE); /* Install bgp top node. */ diff --git a/lib/vxlan.h b/lib/vxlan.h index 62963a6097d4..220fd8d2323a 100644 --- a/lib/vxlan.h +++ b/lib/vxlan.h @@ -26,7 +26,7 @@ extern "C" { #endif -/* EVPN MH DF election alogorithm */ +/* EVPN MH DF election algorithm */ #define EVPN_MH_DF_ALG_SERVICE_CARVING 0 #define EVPN_MH_DF_ALG_HRW 1 #define EVPN_MH_DF_ALG_PREF 2 diff --git a/lib/yang.h b/lib/yang.h index d4517f969aea..d625b24f6a79 100644 --- a/lib/yang.h +++ b/lib/yang.h @@ -183,7 +183,7 @@ extern int yang_snodes_iterate_subtree(const struct lysc_node *snode, void *arg); /* - * Iterate over all libyang schema nodes from all loeaded modules of from the + * Iterate over all libyang schema nodes from all loaded modules of the * given YANG module. * * module diff --git a/lib/zclient.c b/lib/zclient.c index eea118738cde..90439d5e170c 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -2099,7 +2099,7 @@ int zebra_router_id_update_read(struct stream *s, struct prefix *rid) * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Harware Address Length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Hardware Address if HW lenght different from 0 | + * | Hardware Address if HW length different from 0 | * | ... max INTERFACE_HWADDR_MAX | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Link_params? | Whether a link-params follows: 1 or 0. @@ -2440,7 +2440,7 @@ size_t zebra_interface_link_params_write(struct stream *s, } /* - * format of message for address additon is: + * format of message for address addition is: * 0 * 0 1 2 3 4 5 6 7 * +-+-+-+-+-+-+-+-+ @@ -2705,9 +2705,9 @@ static int zclient_read_sync_response(struct zclient *zclient, return 0; } /** - * Connect to label manager in a syncronous way + * Connect to label manager in a synchronous way * - * It first writes the request to zcient output buffer and then + * It first writes the request to zclient output buffer and then * immediately reads the answer from the input buffer. * * @param zclient Zclient used to connect to label manager (zebra) @@ -2800,7 +2800,7 @@ int lm_label_manager_connect(struct zclient *zclient, int async) } /** - * Function to request a srv6-locator chunk in an Asyncronous way + * Function to request a srv6-locator chunk in an asynchronous way * * @param zclient Zclient used to connect to table manager (zebra) * @param locator_name Name of SRv6-locator @@ -2910,9 +2910,9 @@ enum zclient_send_status zclient_send_get_label_chunk(struct zclient *zclient, } /** - * Function to request a label chunk in a syncronous way + * Function to request a label chunk in a synchronous way * - * It first writes the request to zlcient output buffer and then + * It first writes the request to zclient output buffer and then * immediately reads the answer from the input buffer. * * @param zclient Zclient used to connect to label manager (zebra) @@ -3087,9 +3087,9 @@ int lm_release_label_chunk(struct zclient *zclient, uint32_t start, } /** - * Connect to table manager in a syncronous way + * Connect to table manager in a synchronous way * - * It first writes the request to zcient output buffer and then + * It first writes the request to zclient output buffer and then * immediately reads the answer from the input buffer. * * @param zclient Zclient used to connect to table manager (zebra) @@ -3146,7 +3146,7 @@ int tm_table_manager_connect(struct zclient *zclient) } /** - * Function to request a table chunk in a syncronous way + * Function to request a table chunk in a synchronous way * * It first writes the request to zclient output buffer and then * immediately reads the answer from the input buffer. diff --git a/lib/zclient.h b/lib/zclient.h index c35753ca8004..3cad9bd4fa51 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -289,7 +289,7 @@ struct zclient { /* The thread master we schedule ourselves on */ struct thread_master *master; - /* Priviledges to change socket values */ + /* Privileges to change socket values */ struct zebra_privs_t *privs; /* Do we care about failure events for route install? */ @@ -329,7 +329,7 @@ struct zclient { struct redist_proto mi_redist[AFI_MAX][ZEBRA_ROUTE_MAX]; vrf_bitmap_t redist[AFI_MAX][ZEBRA_ROUTE_MAX]; - /* Redistribute defauilt. */ + /* Redistribute default. */ vrf_bitmap_t default_information[AFI_MAX]; #define ZAPI_CALLBACK_ARGS \ From f24157851bc41ed72df3d7c8e8bb90e8212e292a Mon Sep 17 00:00:00 2001 From: Christian Hopps Date: Sun, 26 Sep 2021 01:51:53 -0400 Subject: [PATCH 186/188] tests: fix missing space in --valgrind-extra option Signed-off-by: Christian Hopps --- tests/topotests/lib/topotest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/topotests/lib/topotest.py b/tests/topotests/lib/topotest.py index 947ea196b6d3..6ee000b0f4fd 100644 --- a/tests/topotests/lib/topotest.py +++ b/tests/topotests/lib/topotest.py @@ -1725,7 +1725,7 @@ def start_daemon(daemon, extra_opts=None): ) if valgrind_extra: cmdenv += ( - "--gen-suppressions=all --expensive-definedness-checks=yes" + " --gen-suppressions=all --expensive-definedness-checks=yes" ) elif daemon in strace_daemons or "all" in strace_daemons: cmdenv = "strace -f -D -o {1}/{2}.strace.{0} ".format( From 1f87861ecc03df43d0d3f32358ad61702505cdde Mon Sep 17 00:00:00 2001 From: Christian Hopps Date: Sun, 26 Sep 2021 01:52:11 -0400 Subject: [PATCH 187/188] tests: revert default enable of memleak tests Revert the accidental enabling of the optional memleak tests that came with the large micronet changeset. Signed-off-by: Christian Hopps --- tests/topotests/pytest.ini | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/topotests/pytest.ini b/tests/topotests/pytest.ini index 33c5635eb24b..7dd13935b1e4 100644 --- a/tests/topotests/pytest.ini +++ b/tests/topotests/pytest.ini @@ -81,4 +81,3 @@ markers = # memleak_path = /tmp/memleak_ # Output files will be named after the testname: # /tmp/memleak_test_ospf_topo1.txt -memleak_path = /tmp/memleak_ From a15e5ac082cff86173f45327db1c276120b88236 Mon Sep 17 00:00:00 2001 From: Christian Hopps Date: Mon, 20 Sep 2021 20:39:09 -0400 Subject: [PATCH 188/188] tests: fix --valgrind-memleaks option Previously, when a valgrind memleak was discovered, would cause a catastrophic pytest failure. Now correctly fails the current pytest as intended. As a result of this fix --valgrind-memleaks now works in distributed pytest mode as well. Signed-off-by: Christian Hopps --- tests/topotests/conftest.py | 58 +++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 31 deletions(-) diff --git a/tests/topotests/conftest.py b/tests/topotests/conftest.py index 7fe6a5aea11c..ce7878c24006 100755 --- a/tests/topotests/conftest.py +++ b/tests/topotests/conftest.py @@ -21,13 +21,6 @@ from lib.topotest import g_extra_config as topotest_extra_config from lib.topotest import json_cmp_result -try: - from _pytest._code.code import ExceptionInfo - - leak_check_ok = True -except ImportError: - leak_check_ok = False - def pytest_addoption(parser): """ @@ -138,8 +131,7 @@ def pytest_addoption(parser): def check_for_memleaks(): - if not topotest_extra_config["valgrind_memleaks"]: - return + assert topotest_extra_config["valgrind_memleaks"] leaks = [] tgen = get_topogen() @@ -151,21 +143,25 @@ def check_for_memleaks(): existing = tgen.valgrind_existing_files latest = glob.glob(os.path.join(logdir, "*.valgrind.*")) + daemons = set() for vfile in latest: if vfile in existing: continue - with open(vfile) as vf: + existing.append(vfile) + with open(vfile, encoding="ascii") as vf: vfcontent = vf.read() match = re.search(r"ERROR SUMMARY: (\d+) errors", vfcontent) if match and match.group(1) != "0": emsg = "{} in {}".format(match.group(1), vfile) leaks.append(emsg) + daemons.add(re.match(r".*\.valgrind\.(.*)\.\d+", vfile).group(1)) + + if tgen is not None: + tgen.valgrind_existing_files = existing if leaks: - if leak_check_ok: - pytest.fail("Memleaks found:\n\t" + "\n\t".join(leaks)) - else: - logger.error("Memleaks found:\n\t" + "\n\t".join(leaks)) + logger.error("valgrind memleaks found:\n\t%s", "\n\t".join(leaks)) + pytest.fail("valgrind memleaks found for daemons: " + " ".join(daemons)) def pytest_runtest_logstart(nodeid, location): @@ -178,18 +174,21 @@ def pytest_runtest_logfinish(nodeid, location): topolog.logfinish(nodeid, location) -def pytest_runtest_call(): - """ - This function must be run after setup_module(), it does standarized post - setup routines. It is only being used for the 'topology-only' option. - """ +@pytest.hookimpl(hookwrapper=True) +def pytest_runtest_call(item: pytest.Item) -> None: + "Hook the function that is called to execute the test." + + # For topology only run the CLI then exit if topotest_extra_config["topology_only"]: - tgen = get_topogen() - if tgen is not None: - # Allow user to play with the setup. - tgen.cli() + get_topogen().cli() + pytest.exit("exiting after --topology-only") + + # Let the default pytest_runtest_call execute the test function + yield - pytest.exit("the topology executed successfully") + # Check for leaks if requested + if topotest_extra_config["valgrind_memleaks"]: + check_for_memleaks() def pytest_assertrepr_compare(op, left, right): @@ -333,7 +332,10 @@ def assert_feature_windows(b, feature): topotest_extra_config["pause"] = pause assert_feature_windows(pause, "--pause") - topotest_extra_config["topology_only"] = config.getoption("--topology-only") + topology_only = config.getoption("--topology-only") + if topology_only and is_xdist: + pytest.exit("Cannot use --topology-only with distributed test mode") + topotest_extra_config["topology_only"] = topology_only # Check environment now that we have config if not diagnose_env(rundir): @@ -373,12 +375,6 @@ def pytest_runtest_makereport(item, call): else: pause = False - if call.excinfo is None and call.when == "call": - try: - check_for_memleaks() - except: - call.excinfo = ExceptionInfo() - title = "unset" if call.excinfo is None: