summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_addpath.c6
-rw-r--r--bgpd/bgp_addpath.h6
-rw-r--r--bgpd/bgp_nexthop.h2
-rw-r--r--bgpd/bgp_nht.c11
-rw-r--r--bgpd/bgp_route.c8
-rw-r--r--configure.ac2
-rw-r--r--isisd/isis_lfa.c2
-rw-r--r--isisd/isis_nb_config.c8
-rw-r--r--lib/grammar_sandbox_main.c2
-rw-r--r--lib/libfrr.c3
-rw-r--r--lib/libfrr.h5
-rw-r--r--lib/log.c1
-rw-r--r--lib/northbound.c4
-rw-r--r--lib/northbound.h8
-rw-r--r--lib/yang.c10
-rw-r--r--lib/yang.h10
-rw-r--r--lib/yang_translator.c4
-rw-r--r--lib/zclient.h1
-rw-r--r--mgmtd/mgmt.c3
-rw-r--r--mgmtd/mgmt_main.c2
-rw-r--r--pimd/pim_autorp.c4
-rw-r--r--pimd/pim_nht.c4
-rw-r--r--pimd/pim_nht.h2
-rw-r--r--tests/bgpd/test_peer_attr.c2
-rw-r--r--tests/helpers/c/main.c2
-rw-r--r--tests/isisd/test_isis_spf.c2
-rw-r--r--tests/lib/cli/common_cli.c2
-rw-r--r--tests/lib/cli/test_commands.c2
-rw-r--r--tests/lib/northbound/test_oper_data.c2
-rw-r--r--tests/lib/test_grpc.cpp3
-rw-r--r--tests/topotests/bgp_basic_functionality_topo1/test_bgp_basic_functionality.py289
-rw-r--r--tests/topotests/bgp_default_originate/test_default_orginate_vrf.py8
-rw-r--r--tests/topotests/bgp_received_routes_with_soft_inbound/__init__.py0
-rw-r--r--tests/topotests/bgp_received_routes_with_soft_inbound/r1/frr.conf17
-rw-r--r--tests/topotests/bgp_received_routes_with_soft_inbound/r2/frr.conf14
-rw-r--r--tests/topotests/bgp_received_routes_with_soft_inbound/test_bgp_received_routes_with_soft_inbound.py103
-rw-r--r--tests/topotests/bgp_self_prefix/__init__.py0
-rw-r--r--tests/topotests/bgp_self_prefix/r1/frr.conf19
-rw-r--r--tests/topotests/bgp_self_prefix/r2/frr.conf20
-rw-r--r--tests/topotests/bgp_self_prefix/r3/frr.conf20
-rw-r--r--tests/topotests/bgp_self_prefix/test_bgp_self_prefix.py111
-rw-r--r--tests/topotests/lib/common_config.py2
-rw-r--r--tests/topotests/lib/topogen.py11
-rwxr-xr-xtools/frr-reload.py7
-rw-r--r--tools/gen_northbound_callbacks.c2
-rw-r--r--tools/gen_yang_deviations.c2
-rw-r--r--vrrpd/vrrp_packet.c2
-rw-r--r--zebra/dplane_fpm_nl.c2
-rw-r--r--zebra/if_netlink.c206
-rw-r--r--zebra/if_netlink.h3
-rw-r--r--zebra/rib.h7
-rw-r--r--zebra/rt_netlink.c25
-rw-r--r--zebra/tc_netlink.c40
-rw-r--r--zebra/tc_netlink.h2
-rw-r--r--zebra/zapi_msg.c19
-rw-r--r--zebra/zebra_dplane.c4
-rw-r--r--zebra/zebra_dplane.h2
-rw-r--r--zebra/zebra_nhg.c207
-rw-r--r--zebra/zebra_nhg.h14
-rw-r--r--zebra/zebra_pw.c37
-rw-r--r--zebra/zebra_pw.h1
-rw-r--r--zebra/zebra_rib.c75
-rw-r--r--zebra/zebra_trace.h14
63 files changed, 633 insertions, 775 deletions
diff --git a/bgpd/bgp_addpath.c b/bgpd/bgp_addpath.c
index f391c13847..aada6e555f 100644
--- a/bgpd/bgp_addpath.c
+++ b/bgpd/bgp_addpath.c
@@ -361,8 +361,7 @@ void bgp_addpath_type_changed(struct bgp *bgp)
}
}
-int bgp_addpath_capability_action(enum bgp_addpath_strat addpath_type,
- uint8_t paths)
+int bgp_addpath_capability_action(enum bgp_addpath_strat addpath_type, uint16_t paths)
{
int action = CAPABILITY_ACTION_UNSET;
@@ -392,8 +391,7 @@ int bgp_addpath_capability_action(enum bgp_addpath_strat addpath_type,
* change take effect.
*/
void bgp_addpath_set_peer_type(struct peer *peer, afi_t afi, safi_t safi,
- enum bgp_addpath_strat addpath_type,
- uint8_t paths)
+ enum bgp_addpath_strat addpath_type, uint16_t paths)
{
struct bgp *bgp = peer->bgp;
enum bgp_addpath_strat old_type;
diff --git a/bgpd/bgp_addpath.h b/bgpd/bgp_addpath.h
index c267ebe43e..f1ff98ea7a 100644
--- a/bgpd/bgp_addpath.h
+++ b/bgpd/bgp_addpath.h
@@ -62,13 +62,11 @@ bool bgp_addpath_tx_path(enum bgp_addpath_strat strat,
* Change the type of addpath used for a peer.
*/
void bgp_addpath_set_peer_type(struct peer *peer, afi_t afi, safi_t safi,
- enum bgp_addpath_strat addpath_type,
- uint8_t paths);
+ enum bgp_addpath_strat addpath_type, uint16_t paths);
void bgp_addpath_update_ids(struct bgp *bgp, struct bgp_dest *dest, afi_t afi,
safi_t safi);
void bgp_addpath_type_changed(struct bgp *bgp);
-extern int bgp_addpath_capability_action(enum bgp_addpath_strat addpath_type,
- uint8_t paths);
+extern int bgp_addpath_capability_action(enum bgp_addpath_strat addpath_type, uint16_t paths);
#endif
diff --git a/bgpd/bgp_nexthop.h b/bgpd/bgp_nexthop.h
index 0280960da8..5014eb8f34 100644
--- a/bgpd/bgp_nexthop.h
+++ b/bgpd/bgp_nexthop.h
@@ -38,7 +38,7 @@ struct bgp_nexthop_cache {
uint32_t metric;
/* Nexthop number and nexthop linked list.*/
- uint8_t nexthop_num;
+ uint16_t nexthop_num;
/* This flag is set to TRUE for a bnc that is gateway IP overlay index
* nexthop.
diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c
index 8719af56b3..59566ee6d6 100644
--- a/bgpd/bgp_nht.c
+++ b/bgpd/bgp_nht.c
@@ -347,12 +347,11 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
&p.u.prefix6))
ifindex = pi->peer->connection->su.sin6.sin6_scope_id;
- if (!is_bgp_static_route && orig_prefix
- && prefix_same(&p, orig_prefix)) {
+ if (!is_bgp_static_route && orig_prefix && prefix_same(&p, orig_prefix) &&
+ CHECK_FLAG(bgp_route->flags, BGP_FLAG_IMPORT_CHECK)) {
if (BGP_DEBUG(nht, NHT)) {
- zlog_debug(
- "%s(%pFX): prefix loops through itself",
- __func__, &p);
+ zlog_debug("%s(%pFX): prefix loops through itself (import-check enabled)",
+ __func__, &p);
}
return 0;
}
@@ -761,7 +760,7 @@ static void bgp_nht_ifp_table_handle(struct bgp *bgp,
{
struct bgp_nexthop_cache *bnc;
struct nexthop *nhop;
- uint8_t other_nh_count;
+ uint16_t other_nh_count;
bool nhop_ll_found = false;
bool nhop_found = false;
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 8dbb4e3b04..475b709a07 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -14506,7 +14506,7 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
struct bgp_adj_out *adj = NULL;
struct bgp_dest *dest;
struct bgp *bgp;
- struct attr attr;
+ struct attr attr, attr_unchanged;
int ret;
struct update_subgroup *subgrp;
struct peer_af *paf = NULL;
@@ -14686,6 +14686,7 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
}
attr = *ain->attr;
+ attr_unchanged = *ain->attr;
route_filtered = false;
/* Filter prefix using distribute list,
@@ -14741,9 +14742,8 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
json_ar, json_net,
"%pFX", rn_p);
} else
- route_vty_out_tmp(vty, bgp, dest, rn_p,
- &attr, safi, use_json,
- json_ar, wide);
+ route_vty_out_tmp(vty, bgp, dest, rn_p, &attr_unchanged,
+ safi, use_json, json_ar, wide);
bgp_attr_flush(&attr);
(*output_count)++;
}
diff --git a/configure.ac b/configure.ac
index e1aa05b869..e8036fcff1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -7,7 +7,7 @@
##
AC_PREREQ([2.69])
-AC_INIT([frr], [10.2-dev], [https://github.com/frrouting/frr/issues])
+AC_INIT([frr], [10.3-dev], [https://github.com/frrouting/frr/issues])
PACKAGE_URL="https://frrouting.org/"
AC_SUBST([PACKAGE_URL])
PACKAGE_FULLNAME="FRRouting"
diff --git a/isisd/isis_lfa.c b/isisd/isis_lfa.c
index 887f27eec5..e0b3a4dca1 100644
--- a/isisd/isis_lfa.c
+++ b/isisd/isis_lfa.c
@@ -1064,7 +1064,7 @@ static void lfa_calc_reach_nodes(struct isis_spftree *spftree,
for (ALL_QUEUE_ELEMENTS_RO(&spftree->paths, node, vertex)) {
char buf[VID2STR_BUFFER];
- if (!VTYPE_IS(vertex->type))
+ if (vertex->type != VTYPE_NONPSEUDO_IS && vertex->type != VTYPE_NONPSEUDO_TE_IS)
continue;
/* Skip root node. */
diff --git a/isisd/isis_nb_config.c b/isisd/isis_nb_config.c
index 7286a692f5..0f0c900ec2 100644
--- a/isisd/isis_nb_config.c
+++ b/isisd/isis_nb_config.c
@@ -4297,14 +4297,6 @@ static int lib_interface_isis_multi_topology_common(
switch (event) {
case NB_EV_VALIDATE:
- circuit = nb_running_get_entry(dnode, NULL, false);
- if (circuit && circuit->area && circuit->area->oldmetric) {
- snprintf(
- errmsg, errmsg_len,
- "Multi topology IS-IS can only be used with wide metrics");
- return NB_ERR_VALIDATION;
- }
- break;
case NB_EV_PREPARE:
case NB_EV_ABORT:
break;
diff --git a/lib/grammar_sandbox_main.c b/lib/grammar_sandbox_main.c
index abd42f359f..05088d52d1 100644
--- a/lib/grammar_sandbox_main.c
+++ b/lib/grammar_sandbox_main.c
@@ -40,7 +40,7 @@ int main(int argc, char **argv)
vty_init(master, true);
lib_cmd_init();
- nb_init(master, NULL, 0, false);
+ nb_init(master, NULL, 0, false, false);
vty_stdio(vty_do_exit);
diff --git a/lib/libfrr.c b/lib/libfrr.c
index a1982841d3..f2247a48e5 100644
--- a/lib/libfrr.c
+++ b/lib/libfrr.c
@@ -820,7 +820,8 @@ struct event_loop *frr_init(void)
log_ref_vty_init();
lib_error_init();
- nb_init(master, di->yang_modules, di->n_yang_modules, true);
+ nb_init(master, di->yang_modules, di->n_yang_modules, true,
+ (di->flags & FRR_LOAD_YANG_LIBRARY) != 0);
if (nb_db_init() != NB_OK)
flog_warn(EC_LIB_NB_DATABASE,
"%s: failed to initialize northbound database",
diff --git a/lib/libfrr.h b/lib/libfrr.h
index 7ed7be4d98..df537e2e3b 100644
--- a/lib/libfrr.h
+++ b/lib/libfrr.h
@@ -46,6 +46,11 @@ extern "C" {
* is responsible for calling frr_vty_serv() itself.
*/
#define FRR_MANUAL_VTY_START (1 << 7)
+/* If FRR_LOAD_YANG_LIBRARY is set then libyang will be told to load and
+ * implement it's internal ietf-yang-library implementation. This should
+ * normally only be done from mgmtd.
+ */
+#define FRR_LOAD_YANG_LIBRARY (1 << 8)
PREDECL_DLIST(log_args);
struct log_arg {
diff --git a/lib/log.c b/lib/log.c
index 880180ae5a..04b789b5da 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -351,7 +351,6 @@ static const struct zebra_desc_table command_types[] = {
DESC_ENTRY(ZEBRA_BFD_DEST_REPLAY),
DESC_ENTRY(ZEBRA_REDISTRIBUTE_ROUTE_ADD),
DESC_ENTRY(ZEBRA_REDISTRIBUTE_ROUTE_DEL),
- DESC_ENTRY(ZEBRA_VRF_UNREGISTER),
DESC_ENTRY(ZEBRA_VRF_ADD),
DESC_ENTRY(ZEBRA_VRF_DELETE),
DESC_ENTRY(ZEBRA_VRF_LABEL),
diff --git a/lib/northbound.c b/lib/northbound.c
index 2dae21341e..a385cc9ece 100644
--- a/lib/northbound.c
+++ b/lib/northbound.c
@@ -2701,7 +2701,7 @@ void nb_validate_callbacks(void)
void nb_init(struct event_loop *tm,
const struct frr_yang_module_info *const modules[],
- size_t nmodules, bool db_enabled)
+ size_t nmodules, bool db_enabled, bool load_library)
{
struct yang_module *loaded[nmodules], **loadedp = loaded;
@@ -2717,7 +2717,7 @@ void nb_init(struct event_loop *tm,
nb_db_enabled = db_enabled;
- yang_init(true, explicit_compile);
+ yang_init(true, explicit_compile, load_library);
/* Load YANG modules and their corresponding northbound callbacks. */
for (size_t i = 0; i < nmodules; i++) {
diff --git a/lib/northbound.h b/lib/northbound.h
index dd3fbf8f73..97a1d31e57 100644
--- a/lib/northbound.h
+++ b/lib/northbound.h
@@ -1703,10 +1703,12 @@ void nb_validate_callbacks(void);
*
* db_enabled
* Set this to record the transactions in the transaction log.
+ *
+ * load_library
+ * Set this to have libyang to load/implement the ietf-yang-library.
*/
-extern void nb_init(struct event_loop *tm,
- const struct frr_yang_module_info *const modules[],
- size_t nmodules, bool db_enabled);
+extern void nb_init(struct event_loop *tm, const struct frr_yang_module_info *const modules[],
+ size_t nmodules, bool db_enabled, bool load_library);
/*
* Finish the northbound layer gracefully. Should be called only when the daemon
diff --git a/lib/yang.c b/lib/yang.c
index 14d5b118c6..b847b8b77b 100644
--- a/lib/yang.c
+++ b/lib/yang.c
@@ -976,7 +976,7 @@ void yang_debugging_set(bool enable)
}
}
-struct ly_ctx *yang_ctx_new_setup(bool embedded_modules, bool explicit_compile)
+struct ly_ctx *yang_ctx_new_setup(bool embedded_modules, bool explicit_compile, bool load_library)
{
struct ly_ctx *ctx = NULL;
const char *yang_models_path = YANG_MODELS_PATH;
@@ -994,7 +994,9 @@ struct ly_ctx *yang_ctx_new_setup(bool embedded_modules, bool explicit_compile)
YANG_MODELS_PATH);
}
- options = LY_CTX_NO_YANGLIBRARY | LY_CTX_DISABLE_SEARCHDIR_CWD;
+ options = LY_CTX_DISABLE_SEARCHDIR_CWD;
+ if (!load_library)
+ options |= LY_CTX_NO_YANGLIBRARY;
if (explicit_compile)
options |= LY_CTX_EXPLICIT_COMPILE;
err = ly_ctx_new(yang_models_path, options, &ctx);
@@ -1007,7 +1009,7 @@ struct ly_ctx *yang_ctx_new_setup(bool embedded_modules, bool explicit_compile)
return ctx;
}
-void yang_init(bool embedded_modules, bool defer_compile)
+void yang_init(bool embedded_modules, bool defer_compile, bool load_library)
{
/* Initialize libyang global parameters that affect all containers. */
ly_set_log_clb(ly_zlog_cb
@@ -1019,7 +1021,7 @@ void yang_init(bool embedded_modules, bool defer_compile)
ly_log_options(LY_LOLOG | LY_LOSTORE);
/* Initialize libyang container for native models. */
- ly_native_ctx = yang_ctx_new_setup(embedded_modules, defer_compile);
+ ly_native_ctx = yang_ctx_new_setup(embedded_modules, defer_compile, load_library);
if (!ly_native_ctx) {
flog_err(EC_LIB_LIBYANG, "%s: ly_ctx_new() failed", __func__);
exit(1);
diff --git a/lib/yang.h b/lib/yang.h
index c4fc78b8ae..52857ecf00 100644
--- a/lib/yang.h
+++ b/lib/yang.h
@@ -607,9 +607,11 @@ extern struct yang_data *yang_data_list_find(const struct list *list,
* explicit_compile
* True if the caller will later call ly_ctx_compile to compile all loaded
* modules at once.
+ * load_library
+ * Set this to have libyang to load/implement the ietf-yang-library.
*/
-extern struct ly_ctx *yang_ctx_new_setup(bool embedded_modules,
- bool explicit_compile);
+extern struct ly_ctx *yang_ctx_new_setup(bool embedded_modules, bool explicit_compile,
+ bool load_library);
/*
* Enable or disable libyang verbose debugging.
@@ -727,8 +729,10 @@ extern const char *yang_print_errors(struct ly_ctx *ly_ctx, char *buf,
* Specify whether libyang should attempt to look for embedded YANG modules.
* defer_compile
* Hold off on compiling modules until yang_init_loading_complete is called.
+ * load_library
+ * Set this to have libyang to load/implement the ietf-yang-library.
*/
-extern void yang_init(bool embedded_modules, bool defer_compile);
+extern void yang_init(bool embedded_modules, bool defer_compile, bool load_library);
/*
* Should be called after yang_init and all yang_module_load()s have been done,
diff --git a/lib/yang_translator.c b/lib/yang_translator.c
index 005f6422f3..b7599e0a71 100644
--- a/lib/yang_translator.c
+++ b/lib/yang_translator.c
@@ -166,7 +166,7 @@ struct yang_translator *yang_translator_load(const char *path)
RB_INSERT(yang_translators, &yang_translators, translator);
/* Initialize the translator libyang context. */
- translator->ly_ctx = yang_ctx_new_setup(false, false);
+ translator->ly_ctx = yang_ctx_new_setup(false, false, false);
if (!translator->ly_ctx) {
flog_warn(EC_LIB_LIBYANG, "%s: ly_ctx_new() failed", __func__);
goto error;
@@ -512,7 +512,7 @@ static unsigned int yang_module_nodes_count(const struct lys_module *module)
void yang_translator_init(void)
{
- ly_translator_ctx = yang_ctx_new_setup(true, false);
+ ly_translator_ctx = yang_ctx_new_setup(true, false, false);
if (!ly_translator_ctx) {
flog_err(EC_LIB_LIBYANG, "%s: ly_ctx_new() failed", __func__);
exit(1);
diff --git a/lib/zclient.h b/lib/zclient.h
index 2877b347d8..91c0c9ed6d 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -124,7 +124,6 @@ typedef enum {
ZEBRA_BFD_DEST_REPLAY,
ZEBRA_REDISTRIBUTE_ROUTE_ADD,
ZEBRA_REDISTRIBUTE_ROUTE_DEL,
- ZEBRA_VRF_UNREGISTER,
ZEBRA_VRF_ADD,
ZEBRA_VRF_DELETE,
ZEBRA_VRF_LABEL,
diff --git a/mgmtd/mgmt.c b/mgmtd/mgmt.c
index 02c54b9215..cfadad4829 100644
--- a/mgmtd/mgmt.c
+++ b/mgmtd/mgmt.c
@@ -57,9 +57,6 @@ void mgmt_init(void)
/* Initialize MGMTD Transaction module */
mgmt_txn_init(mm, mm->master);
- /* Add yang-library module */
- yang_module_load("ietf-yang-library", NULL);
-
/* Initialize the MGMTD Frontend Adapter Module */
mgmt_fe_adapter_init(mm->master);
diff --git a/mgmtd/mgmt_main.c b/mgmtd/mgmt_main.c
index e181d0da5e..1880d94415 100644
--- a/mgmtd/mgmt_main.c
+++ b/mgmtd/mgmt_main.c
@@ -214,7 +214,7 @@ FRR_DAEMON_INFO(mgmtd, MGMTD,
.n_yang_modules = array_size(mgmt_yang_modules),
/* avoid libfrr trying to read our config file for us */
- .flags = FRR_MANUAL_VTY_START | FRR_NO_SPLIT_CONFIG,
+ .flags = FRR_MANUAL_VTY_START | FRR_NO_SPLIT_CONFIG | FRR_LOAD_YANG_LIBRARY,
);
/* clang-format on */
diff --git a/pimd/pim_autorp.c b/pimd/pim_autorp.c
index 1f4d0c65af..35347a2790 100644
--- a/pimd/pim_autorp.c
+++ b/pimd/pim_autorp.c
@@ -290,8 +290,8 @@ static bool pim_autorp_add_rp(struct pim_autorp *autorp, pim_addr rpaddr,
event_add_timer(router->master, autorp_rp_holdtime, trp,
holdtime, &(trp->hold_timer));
if (PIM_DEBUG_AUTORP)
- zlog_debug("%s: Started %u second hold timer for RP %pI4",
- __func__, holdtime, &rp->addr);
+ zlog_debug("%s: Started %u second hold timer for RP %pI4", __func__,
+ holdtime, &trp->addr);
} else {
/* If hold time is zero, make sure there doesn't exist a hold timer for it already */
event_cancel(&trp->hold_timer);
diff --git a/pimd/pim_nht.c b/pimd/pim_nht.c
index 030b933e09..5a161c4f16 100644
--- a/pimd/pim_nht.c
+++ b/pimd/pim_nht.c
@@ -573,7 +573,7 @@ static int pim_ecmp_nexthop_search(struct pim_instance *pim,
ifindex_t first_ifindex;
struct interface *ifp = NULL;
uint32_t hash_val = 0, mod_val = 0;
- uint8_t nh_iter = 0, found = 0;
+ uint16_t nh_iter = 0, found = 0;
uint32_t i, num_nbrs = 0;
struct pim_interface *pim_ifp;
@@ -947,7 +947,7 @@ int pim_ecmp_nexthop_lookup(struct pim_instance *pim,
struct interface *ifps[router->multipath], *ifp;
int first_ifindex;
int found = 0;
- uint8_t i = 0;
+ uint16_t i = 0;
uint32_t hash_val = 0, mod_val = 0;
uint32_t num_nbrs = 0;
struct pim_interface *pim_ifp;
diff --git a/pimd/pim_nht.h b/pimd/pim_nht.h
index e74b375dc6..d064f714a5 100644
--- a/pimd/pim_nht.h
+++ b/pimd/pim_nht.h
@@ -23,7 +23,7 @@ struct pim_nexthop_cache {
uint32_t metric;
uint32_t distance;
/* Nexthop number and nexthop linked list. */
- uint8_t nexthop_num;
+ uint16_t nexthop_num;
struct nexthop *nexthop;
int64_t last_update;
uint16_t flags;
diff --git a/tests/bgpd/test_peer_attr.c b/tests/bgpd/test_peer_attr.c
index d5faa33ca8..17002464e1 100644
--- a/tests/bgpd/test_peer_attr.c
+++ b/tests/bgpd/test_peer_attr.c
@@ -1355,7 +1355,7 @@ static void bgp_startup(void)
zprivs_init(&bgpd_privs);
master = event_master_create(NULL);
- nb_init(master, NULL, 0, false);
+ nb_init(master, NULL, 0, false, false);
bgp_master_init(master, BGP_SOCKET_SNDBUF_SIZE, list_new());
bgp_option_set(BGP_OPT_NO_LISTEN);
vrf_init(NULL, NULL, NULL, NULL);
diff --git a/tests/helpers/c/main.c b/tests/helpers/c/main.c
index 9cb395bb1f..344af82fca 100644
--- a/tests/helpers/c/main.c
+++ b/tests/helpers/c/main.c
@@ -143,7 +143,7 @@ int main(int argc, char **argv)
vty_init(master, false);
lib_cmd_init();
debug_init();
- nb_init(master, NULL, 0, false);
+ nb_init(master, NULL, 0, false, false);
/* OSPF vty inits. */
test_vty_init();
diff --git a/tests/isisd/test_isis_spf.c b/tests/isisd/test_isis_spf.c
index 93009a1b84..e5a8f7a513 100644
--- a/tests/isisd/test_isis_spf.c
+++ b/tests/isisd/test_isis_spf.c
@@ -546,7 +546,7 @@ int main(int argc, char **argv)
cmd_init(1);
cmd_hostname_set("test");
vty_init(master, false);
- yang_init(true, false);
+ yang_init(true, false, false);
if (debug)
zlog_aux_init("NONE: ", LOG_DEBUG);
else
diff --git a/tests/lib/cli/common_cli.c b/tests/lib/cli/common_cli.c
index 6401971435..342a91cc79 100644
--- a/tests/lib/cli/common_cli.c
+++ b/tests/lib/cli/common_cli.c
@@ -77,7 +77,7 @@ int main(int argc, char **argv)
for (yangcount = 0; test_yang_modules && test_yang_modules[yangcount];
yangcount++)
;
- nb_init(master, test_yang_modules, yangcount, false);
+ nb_init(master, test_yang_modules, yangcount, false, false);
test_init(argc, argv);
diff --git a/tests/lib/cli/test_commands.c b/tests/lib/cli/test_commands.c
index 0034c2af89..9873383fdc 100644
--- a/tests/lib/cli/test_commands.c
+++ b/tests/lib/cli/test_commands.c
@@ -197,7 +197,7 @@ static void test_init(void)
cmd_init(1);
debug_init();
- nb_init(master, NULL, 0, false);
+ nb_init(master, NULL, 0, false, false);
install_node(&bgp_node);
install_node(&rip_node);
diff --git a/tests/lib/northbound/test_oper_data.c b/tests/lib/northbound/test_oper_data.c
index 74a0dfe6cc..fdc9e53ca3 100644
--- a/tests/lib/northbound/test_oper_data.c
+++ b/tests/lib/northbound/test_oper_data.c
@@ -461,7 +461,7 @@ int main(int argc, char **argv)
vty_init(master, false);
lib_cmd_init();
debug_init();
- nb_init(master, modules, array_size(modules), false);
+ nb_init(master, modules, array_size(modules), false, false);
install_element(ENABLE_NODE, &test_rpc_cmd);
diff --git a/tests/lib/test_grpc.cpp b/tests/lib/test_grpc.cpp
index 2f0282704e..379a8688a7 100644
--- a/tests/lib/test_grpc.cpp
+++ b/tests/lib/test_grpc.cpp
@@ -111,8 +111,7 @@ static void static_startup(void)
static_debug_init();
master = event_master_create(NULL);
- nb_init(master, staticd_yang_modules, array_size(staticd_yang_modules),
- false);
+ nb_init(master, staticd_yang_modules, array_size(staticd_yang_modules), false, false);
static_zebra_init();
vty_init(master, true);
diff --git a/tests/topotests/bgp_basic_functionality_topo1/test_bgp_basic_functionality.py b/tests/topotests/bgp_basic_functionality_topo1/test_bgp_basic_functionality.py
index c97fc5f0eb..5662e5935b 100644
--- a/tests/topotests/bgp_basic_functionality_topo1/test_bgp_basic_functionality.py
+++ b/tests/topotests/bgp_basic_functionality_topo1/test_bgp_basic_functionality.py
@@ -831,7 +831,6 @@ def test_bgp_with_loopback_interface(request):
for bgp_neighbor in topo["routers"][routerN]["bgp"]["address_family"]["ipv4"][
"unicast"
]["neighbor"].keys():
-
# Adding ['source_link'] = 'lo' key:value pair
topo["routers"][routerN]["bgp"]["address_family"]["ipv4"]["unicast"][
"neighbor"
@@ -876,294 +875,6 @@ def test_bgp_with_loopback_interface(request):
write_test_footer(tc_name)
-def test_bgp_with_loopback_with_same_subnet_p1(request):
- """
- Verify routes not installed in zebra when /32 routes received
- with loopback BGP session subnet
- """
-
- tgen = get_topogen()
- if BGP_CONVERGENCE is not True:
- pytest.skip("skipped because of BGP Convergence failure")
-
- # test case name
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Creating configuration from JSON
- reset_config_on_routers(tgen)
- step("Delete BGP seesion created initially")
- input_dict_r1 = {
- "r1": {"bgp": {"delete": True}},
- "r2": {"bgp": {"delete": True}},
- "r3": {"bgp": {"delete": True}},
- "r4": {"bgp": {"delete": True}},
- }
- result = create_router_bgp(tgen, topo, input_dict_r1)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
-
- step("Create BGP session over loop address")
- topo_modify = deepcopy(topo)
-
- for routerN in sorted(topo["routers"].keys()):
- for addr_type in ADDR_TYPES:
- for bgp_neighbor in topo_modify["routers"][routerN]["bgp"][
- "address_family"
- ][addr_type]["unicast"]["neighbor"].keys():
-
- # Adding ['source_link'] = 'lo' key:value pair
- topo_modify["routers"][routerN]["bgp"]["address_family"][addr_type][
- "unicast"
- ]["neighbor"][bgp_neighbor]["dest_link"] = {
- "lo": {"source_link": "lo", "ebgp_multihop": 2}
- }
-
- result = create_router_bgp(tgen, topo_modify["routers"])
- assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
-
- step("Disable IPv6 BGP nbr from ipv4 address family")
- raw_config = {
- "r1": {
- "raw_config": [
- "router bgp {}".format(topo["routers"]["r1"]["bgp"]["local_as"]),
- "address-family ipv4 unicast",
- "no neighbor {} activate".format(
- topo["routers"]["r2"]["links"]["lo"]["ipv6"].split("/")[0]
- ),
- "no neighbor {} activate".format(
- topo["routers"]["r3"]["links"]["lo"]["ipv6"].split("/")[0]
- ),
- ]
- },
- "r2": {
- "raw_config": [
- "router bgp {}".format(topo["routers"]["r2"]["bgp"]["local_as"]),
- "address-family ipv4 unicast",
- "no neighbor {} activate".format(
- topo["routers"]["r1"]["links"]["lo"]["ipv6"].split("/")[0]
- ),
- "no neighbor {} activate".format(
- topo["routers"]["r3"]["links"]["lo"]["ipv6"].split("/")[0]
- ),
- ]
- },
- "r3": {
- "raw_config": [
- "router bgp {}".format(topo["routers"]["r3"]["bgp"]["local_as"]),
- "address-family ipv4 unicast",
- "no neighbor {} activate".format(
- topo["routers"]["r1"]["links"]["lo"]["ipv6"].split("/")[0]
- ),
- "no neighbor {} activate".format(
- topo["routers"]["r2"]["links"]["lo"]["ipv6"].split("/")[0]
- ),
- "no neighbor {} activate".format(
- topo["routers"]["r4"]["links"]["lo"]["ipv6"].split("/")[0]
- ),
- ]
- },
- "r4": {
- "raw_config": [
- "router bgp {}".format(topo["routers"]["r4"]["bgp"]["local_as"]),
- "address-family ipv4 unicast",
- "no neighbor {} activate".format(
- topo["routers"]["r3"]["links"]["lo"]["ipv6"].split("/")[0]
- ),
- ]
- },
- }
-
- step("Configure kernel routes")
- result = apply_raw_config(tgen, raw_config)
- assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
-
- r1_ipv4_lo = topo["routers"]["r1"]["links"]["lo"]["ipv4"]
- r1_ipv6_lo = topo["routers"]["r1"]["links"]["lo"]["ipv6"]
- r2_ipv4_lo = topo["routers"]["r2"]["links"]["lo"]["ipv4"]
- r2_ipv6_lo = topo["routers"]["r2"]["links"]["lo"]["ipv6"]
- r3_ipv4_lo = topo["routers"]["r3"]["links"]["lo"]["ipv4"]
- r3_ipv6_lo = topo["routers"]["r3"]["links"]["lo"]["ipv6"]
- r4_ipv4_lo = topo["routers"]["r4"]["links"]["lo"]["ipv4"]
- r4_ipv6_lo = topo["routers"]["r4"]["links"]["lo"]["ipv6"]
-
- r1_r2 = topo["routers"]["r1"]["links"]["r2"]["ipv6"].split("/")[0]
- r2_r1 = topo["routers"]["r2"]["links"]["r1"]["ipv6"].split("/")[0]
- r1_r3 = topo["routers"]["r1"]["links"]["r3"]["ipv6"].split("/")[0]
- r3_r1 = topo["routers"]["r3"]["links"]["r1"]["ipv6"].split("/")[0]
- r2_r3 = topo["routers"]["r2"]["links"]["r3"]["ipv6"].split("/")[0]
- r3_r2 = topo["routers"]["r3"]["links"]["r2"]["ipv6"].split("/")[0]
- r3_r4 = topo["routers"]["r3"]["links"]["r4"]["ipv6"].split("/")[0]
- r4_r3 = topo["routers"]["r4"]["links"]["r3"]["ipv6"].split("/")[0]
-
- r1_r2_ipv4 = topo["routers"]["r1"]["links"]["r2"]["ipv4"].split("/")[0]
- r2_r1_ipv4 = topo["routers"]["r2"]["links"]["r1"]["ipv4"].split("/")[0]
- r1_r3_ipv4 = topo["routers"]["r1"]["links"]["r3"]["ipv4"].split("/")[0]
- r3_r1_ipv4 = topo["routers"]["r3"]["links"]["r1"]["ipv4"].split("/")[0]
- r2_r3_ipv4 = topo["routers"]["r2"]["links"]["r3"]["ipv4"].split("/")[0]
- r3_r2_ipv4 = topo["routers"]["r3"]["links"]["r2"]["ipv4"].split("/")[0]
- r3_r4_ipv4 = topo["routers"]["r3"]["links"]["r4"]["ipv4"].split("/")[0]
- r4_r3_ipv4 = topo["routers"]["r4"]["links"]["r3"]["ipv4"].split("/")[0]
-
- r1_r2_intf = topo["routers"]["r1"]["links"]["r2"]["interface"]
- r2_r1_intf = topo["routers"]["r2"]["links"]["r1"]["interface"]
- r1_r3_intf = topo["routers"]["r1"]["links"]["r3"]["interface"]
- r3_r1_intf = topo["routers"]["r3"]["links"]["r1"]["interface"]
- r2_r3_intf = topo["routers"]["r2"]["links"]["r3"]["interface"]
- r3_r2_intf = topo["routers"]["r3"]["links"]["r2"]["interface"]
- r3_r4_intf = topo["routers"]["r3"]["links"]["r4"]["interface"]
- r4_r3_intf = topo["routers"]["r4"]["links"]["r3"]["interface"]
-
- ipv4_list = [
- ("r1", r1_r2_intf, r2_ipv4_loopback),
- ("r1", r1_r3_intf, r3_ipv4_loopback),
- ("r2", r2_r1_intf, r1_ipv4_loopback),
- ("r2", r2_r3_intf, r3_ipv4_loopback),
- ("r3", r3_r1_intf, r1_ipv4_loopback),
- ("r3", r3_r2_intf, r2_ipv4_loopback),
- ("r3", r3_r4_intf, r4_ipv4_loopback),
- ("r4", r4_r3_intf, r3_ipv4_loopback),
- ]
-
- ipv6_list = [
- ("r1", r1_r2_intf, r2_ipv6_loopback, r2_r1),
- ("r1", r1_r3_intf, r3_ipv6_loopback, r3_r1),
- ("r2", r2_r1_intf, r1_ipv6_loopback, r1_r2),
- ("r2", r2_r3_intf, r3_ipv6_loopback, r3_r2),
- ("r3", r3_r1_intf, r1_ipv6_loopback, r1_r3),
- ("r3", r3_r2_intf, r2_ipv6_loopback, r2_r3),
- ("r3", r3_r4_intf, r4_ipv6_loopback, r4_r3),
- ("r4", r4_r3_intf, r3_ipv6_loopback, r3_r4),
- ]
-
- for dut, intf, loop_addr in ipv4_list:
- result = addKernelRoute(tgen, dut, intf, loop_addr)
- assert result is True, "Testcase {}:Failed \n Error: {}".format(tc_name, result)
-
- for dut, intf, loop_addr, next_hop in ipv6_list:
- result = addKernelRoute(tgen, dut, intf, loop_addr, next_hop)
- assert result is True, "Testcase {}:Failed \n Error: {}".format(tc_name, result)
-
- step("Configure static routes")
-
- input_dict = {
- "r1": {
- "static_routes": [
- {"network": r2_ipv4_loopback, "next_hop": r2_r1_ipv4},
- {"network": r3_ipv4_loopback, "next_hop": r3_r1_ipv4},
- {"network": r2_ipv6_loopback, "next_hop": r2_r1},
- {"network": r3_ipv6_loopback, "next_hop": r3_r1},
- ]
- },
- "r2": {
- "static_routes": [
- {"network": r1_ipv4_loopback, "next_hop": r1_r2_ipv4},
- {"network": r3_ipv4_loopback, "next_hop": r3_r2_ipv4},
- {"network": r1_ipv6_loopback, "next_hop": r1_r2},
- {"network": r3_ipv6_loopback, "next_hop": r3_r2},
- ]
- },
- "r3": {
- "static_routes": [
- {"network": r1_ipv4_loopback, "next_hop": r1_r3_ipv4},
- {"network": r2_ipv4_loopback, "next_hop": r2_r3_ipv4},
- {"network": r4_ipv4_loopback, "next_hop": r4_r3_ipv4},
- {"network": r1_ipv6_loopback, "next_hop": r1_r3},
- {"network": r2_ipv6_loopback, "next_hop": r2_r3},
- {"network": r4_ipv6_loopback, "next_hop": r4_r3},
- ]
- },
- "r4": {
- "static_routes": [
- {"network": r3_ipv4_loopback, "next_hop": r3_r4_ipv4},
- {"network": r3_ipv6_loopback, "next_hop": r3_r4},
- ]
- },
- }
- result = create_static_routes(tgen, input_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("Verify BGP session convergence")
-
- result = verify_bgp_convergence(tgen, topo_modify)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("Configure redistribute connected on R2 and R4")
- input_dict_1 = {
- "r2": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {"redistribute": [{"redist_type": "connected"}]}
- },
- "ipv6": {
- "unicast": {"redistribute": [{"redist_type": "connected"}]}
- },
- }
- }
- },
- "r4": {
- "bgp": {
- "address_family": {
- "ipv4": {
- "unicast": {"redistribute": [{"redist_type": "connected"}]}
- },
- "ipv6": {
- "unicast": {"redistribute": [{"redist_type": "connected"}]}
- },
- }
- }
- },
- }
-
- result = create_router_bgp(tgen, topo, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("Verify Ipv4 and Ipv6 network installed in R1 RIB but not in FIB")
- input_dict_r1 = {
- "r1": {
- "static_routes": [
- {"network": "1.0.2.17/32"},
- {"network": "2001:db8:f::2:17/128"},
- ]
- }
- }
-
- dut = "r1"
- protocol = "bgp"
- for addr_type in ADDR_TYPES:
- result = verify_fib_routes(
- tgen, addr_type, dut, input_dict_r1, expected=False
- ) # pylint: disable=E1123
- assert result is not True, (
- "Testcase {} : Failed \n "
- "Expected: Routes should not be present in {} FIB \n "
- "Found: {}".format(tc_name, dut, result)
- )
-
- step("Verify Ipv4 and Ipv6 network installed in r3 RIB but not in FIB")
- input_dict_r3 = {
- "r3": {
- "static_routes": [
- {"network": "1.0.4.17/32"},
- {"network": "2001:db8:f::4:17/128"},
- ]
- }
- }
- dut = "r3"
- protocol = "bgp"
- for addr_type in ADDR_TYPES:
- result = verify_fib_routes(
- tgen, addr_type, dut, input_dict_r1, expected=False
- ) # pylint: disable=E1123
- assert result is not True, (
- "Testcase {} : Failed \n "
- "Expected: Routes should not be present in {} FIB \n "
- "Found: {}".format(tc_name, dut, result)
- )
-
- write_test_footer(tc_name)
-
-
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_default_originate/test_default_orginate_vrf.py b/tests/topotests/bgp_default_originate/test_default_orginate_vrf.py
index 1506b02e5d..905c3e2b66 100644
--- a/tests/topotests/bgp_default_originate/test_default_orginate_vrf.py
+++ b/tests/topotests/bgp_default_originate/test_default_orginate_vrf.py
@@ -546,13 +546,7 @@ def test_verify_default_originate_route_with_non_default_VRF_p1(request):
tc_name, result
)
- result = verify_rib(
- tgen,
- addr_type,
- "r2",
- static_routes_input,
- next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type],
- )
+ result = verify_rib(tgen, addr_type, "r2", static_routes_input)
assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result
)
diff --git a/tests/topotests/bgp_received_routes_with_soft_inbound/__init__.py b/tests/topotests/bgp_received_routes_with_soft_inbound/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/bgp_received_routes_with_soft_inbound/__init__.py
diff --git a/tests/topotests/bgp_received_routes_with_soft_inbound/r1/frr.conf b/tests/topotests/bgp_received_routes_with_soft_inbound/r1/frr.conf
new file mode 100644
index 0000000000..01dd4f3c5a
--- /dev/null
+++ b/tests/topotests/bgp_received_routes_with_soft_inbound/r1/frr.conf
@@ -0,0 +1,17 @@
+!
+int r1-eth0
+ ip address 192.168.1.1/24
+!
+router bgp 65001
+ no bgp ebgp-requires-policy
+ no bgp network import-check
+ neighbor 192.168.1.2 remote-as external
+ address-family ipv4 unicast
+ neighbor 192.168.1.2 route-map r2 in
+ neighbor 192.168.1.2 soft-reconfiguration inbound
+ exit-address-family
+!
+route-map r2 permit 10
+ set as-path prepend 65000 65000 65000
+exit
+!
diff --git a/tests/topotests/bgp_received_routes_with_soft_inbound/r2/frr.conf b/tests/topotests/bgp_received_routes_with_soft_inbound/r2/frr.conf
new file mode 100644
index 0000000000..86dd8e3389
--- /dev/null
+++ b/tests/topotests/bgp_received_routes_with_soft_inbound/r2/frr.conf
@@ -0,0 +1,14 @@
+!
+int r2-eth0
+ ip address 192.168.1.2/24
+!
+router bgp 65002
+ no bgp ebgp-requires-policy
+ no bgp network import-check
+ neighbor 192.168.1.1 remote-as external
+ neighbor 192.168.1.1 timers 1 3
+ neighbor 192.168.1.1 timers connect 1
+ address-family ipv4 unicast
+ network 10.0.0.2/32
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_received_routes_with_soft_inbound/test_bgp_received_routes_with_soft_inbound.py b/tests/topotests/bgp_received_routes_with_soft_inbound/test_bgp_received_routes_with_soft_inbound.py
new file mode 100644
index 0000000000..0b933add2f
--- /dev/null
+++ b/tests/topotests/bgp_received_routes_with_soft_inbound/test_bgp_received_routes_with_soft_inbound.py
@@ -0,0 +1,103 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: ISC
+
+# Copyright (c) 2024 by
+# Donatas Abraitis <donatas@opensourcerouting.org>
+#
+
+import os
+import sys
+import json
+import pytest
+import functools
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, get_topogen
+
+pytestmark = [pytest.mark.bgpd]
+
+
+def setup_module(mod):
+ topodef = {"s1": ("r1", "r2")}
+ tgen = Topogen(topodef, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ for _, (rname, router) in enumerate(router_list.items(), 1):
+ router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname)))
+
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_received_routes_with_soft_inbound():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r1 = tgen.gears["r1"]
+
+ def _bgp_converge():
+ output = json.loads(r1.vtysh_cmd("show bgp ipv4 unicast json"))
+ expected = {
+ "routes": {
+ "10.0.0.2/32": [
+ {
+ "valid": True,
+ "path": "65000 65000 65000 65002",
+ "nexthops": [
+ {
+ "ip": "192.168.1.2",
+ }
+ ],
+ }
+ ]
+ }
+ }
+
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(
+ _bgp_converge,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+ assert result is None, "Can't converge"
+
+ def _bgp_check_receveived_routes():
+ output = json.loads(
+ r1.vtysh_cmd(
+ "show bgp ipv4 unicast neighbors 192.168.1.2 received-routes json"
+ )
+ )
+ expected = {
+ "receivedRoutes": {
+ "10.0.0.2/32": {
+ "valid": True,
+ "path": "65002",
+ "nextHop": "192.168.1.2",
+ }
+ }
+ }
+
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(
+ _bgp_check_receveived_routes,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+ assert result is None, "Can't converge"
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_self_prefix/__init__.py b/tests/topotests/bgp_self_prefix/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/bgp_self_prefix/__init__.py
diff --git a/tests/topotests/bgp_self_prefix/r1/frr.conf b/tests/topotests/bgp_self_prefix/r1/frr.conf
new file mode 100644
index 0000000000..879afb1947
--- /dev/null
+++ b/tests/topotests/bgp_self_prefix/r1/frr.conf
@@ -0,0 +1,19 @@
+!
+int lo
+ ip address 10.0.0.1/32
+!
+int r1-eth0
+ ip address 192.168.1.1/24
+!
+router bgp 65000
+ no bgp ebgp-requires-policy
+ no bgp network import-check
+ neighbor 10.0.0.2 remote-as internal
+ neighbor 10.0.0.2 update-source lo
+ neighbor 10.0.0.2 next-hop-self
+ neighbor 10.0.0.3 remote-as external
+ neighbor 10.0.0.3 update-source lo
+ neighbor 10.0.0.3 next-hop-self
+!
+ip route 10.0.0.2/32 192.168.1.2
+ip route 10.0.0.3/32 192.168.1.3
diff --git a/tests/topotests/bgp_self_prefix/r2/frr.conf b/tests/topotests/bgp_self_prefix/r2/frr.conf
new file mode 100644
index 0000000000..eb0db356ea
--- /dev/null
+++ b/tests/topotests/bgp_self_prefix/r2/frr.conf
@@ -0,0 +1,20 @@
+!
+int lo
+ ip address 10.0.0.2/32
+!
+int r2-eth0
+ ip address 192.168.1.2/24
+!
+router bgp 65000
+ no bgp ebgp-requires-policy
+ no bgp network import-check
+ neighbor 10.0.0.1 remote-as internal
+ neighbor 10.0.0.1 timers 1 3
+ neighbor 10.0.0.1 timers connect 1
+ neighbor 10.0.0.1 update-source lo
+ neighbor 10.0.0.1 next-hop-self
+ address-family ipv4 unicast
+ network 10.0.0.2/32
+ exit-address-family
+!
+ip route 10.0.0.1/32 192.168.1.1
diff --git a/tests/topotests/bgp_self_prefix/r3/frr.conf b/tests/topotests/bgp_self_prefix/r3/frr.conf
new file mode 100644
index 0000000000..e2348f4a68
--- /dev/null
+++ b/tests/topotests/bgp_self_prefix/r3/frr.conf
@@ -0,0 +1,20 @@
+!
+int lo
+ ip address 10.0.0.3/32
+!
+int r3-eth0
+ ip address 192.168.1.3/24
+!
+router bgp 65003
+ no bgp ebgp-requires-policy
+ no bgp network import-check
+ neighbor 10.0.0.1 remote-as external
+ neighbor 10.0.0.1 timers 1 3
+ neighbor 10.0.0.1 timers connect 1
+ neighbor 10.0.0.1 update-source lo
+ neighbor 10.0.0.1 next-hop-self
+ address-family ipv4 unicast
+ network 10.0.0.3/32
+ exit-address-family
+!
+ip route 10.0.0.1/32 192.168.1.1
diff --git a/tests/topotests/bgp_self_prefix/test_bgp_self_prefix.py b/tests/topotests/bgp_self_prefix/test_bgp_self_prefix.py
new file mode 100644
index 0000000000..1045800368
--- /dev/null
+++ b/tests/topotests/bgp_self_prefix/test_bgp_self_prefix.py
@@ -0,0 +1,111 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: ISC
+
+# Copyright (c) 2024 by
+# Donatas Abraitis <donatas@opensourcerouting.org>
+#
+
+import os
+import sys
+import json
+import pytest
+import functools
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, get_topogen
+
+pytestmark = [pytest.mark.bgpd]
+
+
+def setup_module(mod):
+ topodef = {"s1": ("r1", "r2", "r3")}
+ tgen = Topogen(topodef, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ for _, (rname, router) in enumerate(router_list.items(), 1):
+ router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname)))
+
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_self_prefix():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r1 = tgen.gears["r1"]
+ r3 = tgen.gears["r3"]
+
+ def _bgp_converge():
+ output = json.loads(r1.vtysh_cmd("show bgp ipv4 unicast json"))
+ expected = {
+ "routes": {
+ "10.0.0.2/32": [
+ {
+ "valid": True,
+ "path": "",
+ "nexthops": [
+ {"ip": "10.0.0.2", "hostname": "r2", "afi": "ipv4"}
+ ],
+ }
+ ],
+ "10.0.0.3/32": [
+ {
+ "valid": True,
+ "path": "65003",
+ "nexthops": [
+ {"ip": "10.0.0.3", "hostname": "r3", "afi": "ipv4"}
+ ],
+ }
+ ],
+ }
+ }
+
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(
+ _bgp_converge,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+ assert result is None, "Can't converge"
+
+ def _bgp_check_received_routes():
+ output = json.loads(r3.vtysh_cmd("show bgp ipv4 unicast json"))
+ expected = {
+ "routes": {
+ "10.0.0.2/32": [
+ {
+ "valid": True,
+ "bestpath": True,
+ "nexthops": [
+ {"ip": "10.0.0.1", "hostname": "r1", "afi": "ipv4"}
+ ],
+ }
+ ],
+ }
+ }
+
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(
+ _bgp_check_received_routes,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+ assert result is None, "Can't see 10.0.0.2/32"
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/lib/common_config.py b/tests/topotests/lib/common_config.py
index cb71112af3..f34c48b890 100644
--- a/tests/topotests/lib/common_config.py
+++ b/tests/topotests/lib/common_config.py
@@ -3371,7 +3371,7 @@ def verify_rib(
found_hops = [
rib_r["ip"]
for rib_r in rib_routes_json[st_rt][0]["nexthops"]
- if "ip" in rib_r
+ if "ip" in rib_r and "active" in rib_r
]
# If somehow key "ip" is not found in nexthops JSON
diff --git a/tests/topotests/lib/topogen.py b/tests/topotests/lib/topogen.py
index 7941e5c1d2..14dd61b077 100644
--- a/tests/topotests/lib/topogen.py
+++ b/tests/topotests/lib/topogen.py
@@ -492,7 +492,16 @@ class Topogen(object):
"Errors found post shutdown - details follow: {}".format(errors)
)
- self.net.stop()
+ try:
+ self.net.stop()
+
+ except OSError as error:
+ # OSError exception is raised when mininet tries to stop switch
+ # though switch is stopped once but mininet tries to stop same
+ # switch again, where it ended up with exception
+
+ logger.info(error)
+ logger.info("Exception ignored: switch is already stopped")
def get_exabgp_cmd(self):
if not self.exabgp_cmd:
diff --git a/tools/frr-reload.py b/tools/frr-reload.py
index 53bb6513e2..08a1f1e07e 100755
--- a/tools/frr-reload.py
+++ b/tools/frr-reload.py
@@ -1163,7 +1163,12 @@ def pim_delete_move_lines(lines_to_add, lines_to_del):
ctx_keys[0] in pim_disable
and ctx_keys[0].startswith("interface")
and line
- and (line.startswith("ip pim ") or line.startswith("ip multicast "))
+ and (
+ line.startswith("ip pim ")
+ or line.startswith("no ip pim ")
+ or line.startswith("ip multicast ")
+ or line.startswith("no ip multicast ")
+ )
):
lines_to_del_to_del.append((ctx_keys, line))
diff --git a/tools/gen_northbound_callbacks.c b/tools/gen_northbound_callbacks.c
index a879811363..046dc9e99e 100644
--- a/tools/gen_northbound_callbacks.c
+++ b/tools/gen_northbound_callbacks.c
@@ -448,7 +448,7 @@ int main(int argc, char *argv[])
if (argc != 1)
usage(EXIT_FAILURE);
- yang_init(false, true);
+ yang_init(false, true, false);
if (search_path)
ly_ctx_set_searchdir(ly_native_ctx, search_path);
diff --git a/tools/gen_yang_deviations.c b/tools/gen_yang_deviations.c
index 251643c69e..c2e7fd91c6 100644
--- a/tools/gen_yang_deviations.c
+++ b/tools/gen_yang_deviations.c
@@ -52,7 +52,7 @@ int main(int argc, char *argv[])
if (argc != 1)
usage(EXIT_FAILURE);
- yang_init(false, false);
+ yang_init(false, false, false);
/* Load YANG module. */
module = yang_module_load(argv[0], NULL);
diff --git a/vrrpd/vrrp_packet.c b/vrrpd/vrrp_packet.c
index 36494c7df8..a2fb2bc321 100644
--- a/vrrpd/vrrp_packet.c
+++ b/vrrpd/vrrp_packet.c
@@ -234,7 +234,7 @@ ssize_t vrrp_pkt_parse_datagram(int family, int version, bool ipv4_ph,
} else if (family == AF_INET6) {
struct cmsghdr *c;
- for (c = CMSG_FIRSTHDR(m); c != NULL; CMSG_NXTHDR(m, c)) {
+ for (c = CMSG_FIRSTHDR(m); c != NULL; c = CMSG_NXTHDR(m, c)) {
if (c->cmsg_level == IPPROTO_IPV6
&& c->cmsg_type == IPV6_HOPLIMIT)
break;
diff --git a/zebra/dplane_fpm_nl.c b/zebra/dplane_fpm_nl.c
index 1d2f9e695f..d594fc2c86 100644
--- a/zebra/dplane_fpm_nl.c
+++ b/zebra/dplane_fpm_nl.c
@@ -1336,7 +1336,7 @@ static void fpm_enqueue_l3vni_table(struct hash_bucket *bucket, void *arg)
struct zebra_l3vni *zl3vni = bucket->data;
fra->zl3vni = zl3vni;
- hash_iterate(zl3vni->rmac_table, fpm_enqueue_rmac_table, zl3vni);
+ hash_iterate(zl3vni->rmac_table, fpm_enqueue_rmac_table, fra);
}
static void fpm_rmac_send(struct event *t)
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index 5fb908eb0d..8beae125d2 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -1032,212 +1032,6 @@ netlink_put_intf_update_msg(struct nl_batch *bth, struct zebra_dplane_ctx *ctx)
return netlink_batch_add_msg(bth, ctx, netlink_intf_msg_encoder, false);
}
-int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup)
-{
- int len;
- struct ifaddrmsg *ifa;
- struct rtattr *tb[IFA_MAX + 1];
- struct interface *ifp;
- void *addr;
- void *broad;
- uint8_t flags = 0;
- char *label = NULL;
- struct zebra_ns *zns;
- uint32_t metric = METRIC_MAX;
- uint32_t kernel_flags = 0;
-
- frrtrace(3, frr_zebra, netlink_interface_addr, h, ns_id, startup);
-
- zns = zebra_ns_lookup(ns_id);
- ifa = NLMSG_DATA(h);
-
- if (ifa->ifa_family != AF_INET && ifa->ifa_family != AF_INET6) {
- flog_warn(
- EC_ZEBRA_UNKNOWN_FAMILY,
- "Invalid address family: %u received from kernel interface addr change: %s",
- ifa->ifa_family, nl_msg_type_to_str(h->nlmsg_type));
- return 0;
- }
-
- if (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR)
- return 0;
-
- len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifaddrmsg));
- if (len < 0) {
- zlog_err(
- "%s: Message received from netlink is of a broken size: %d %zu",
- __func__, h->nlmsg_len,
- (size_t)NLMSG_LENGTH(sizeof(struct ifaddrmsg)));
- return -1;
- }
-
- netlink_parse_rtattr(tb, IFA_MAX, IFA_RTA(ifa), len);
-
- ifp = if_lookup_by_index_per_ns(zns, ifa->ifa_index);
- if (ifp == NULL) {
- 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 */
- if (tb[IFA_FLAGS])
- kernel_flags = *(int *)RTA_DATA(tb[IFA_FLAGS]);
- else
- kernel_flags = ifa->ifa_flags;
-
- if (IS_ZEBRA_DEBUG_KERNEL) /* remove this line to see initial ifcfg */
- {
- char buf[BUFSIZ];
- zlog_debug("%s %s %s flags 0x%x:", __func__,
- nl_msg_type_to_str(h->nlmsg_type), ifp->name,
- kernel_flags);
- if (tb[IFA_LOCAL])
- zlog_debug(" IFA_LOCAL %s/%d",
- inet_ntop(ifa->ifa_family,
- RTA_DATA(tb[IFA_LOCAL]), buf,
- BUFSIZ),
- ifa->ifa_prefixlen);
- if (tb[IFA_ADDRESS])
- zlog_debug(" IFA_ADDRESS %s/%d",
- inet_ntop(ifa->ifa_family,
- RTA_DATA(tb[IFA_ADDRESS]), buf,
- BUFSIZ),
- ifa->ifa_prefixlen);
- if (tb[IFA_BROADCAST])
- zlog_debug(" IFA_BROADCAST %s/%d",
- inet_ntop(ifa->ifa_family,
- RTA_DATA(tb[IFA_BROADCAST]), buf,
- BUFSIZ),
- ifa->ifa_prefixlen);
- if (tb[IFA_LABEL] && strcmp(ifp->name, RTA_DATA(tb[IFA_LABEL])))
- zlog_debug(" IFA_LABEL %s",
- (char *)RTA_DATA(tb[IFA_LABEL]));
-
- if (tb[IFA_CACHEINFO]) {
- struct ifa_cacheinfo *ci = RTA_DATA(tb[IFA_CACHEINFO]);
- zlog_debug(" IFA_CACHEINFO pref %d, valid %d",
- ci->ifa_prefered, ci->ifa_valid);
- }
- }
-
- /* logic copied from iproute2/ip/ipaddress.c:print_addrinfo() */
- if (tb[IFA_LOCAL] == NULL)
- tb[IFA_LOCAL] = tb[IFA_ADDRESS];
- if (tb[IFA_ADDRESS] == NULL)
- tb[IFA_ADDRESS] = tb[IFA_LOCAL];
-
- /* local interface address */
- addr = (tb[IFA_LOCAL] ? RTA_DATA(tb[IFA_LOCAL]) : NULL);
-
- /* is there a peer address? */
- if (tb[IFA_ADDRESS]
- && memcmp(RTA_DATA(tb[IFA_ADDRESS]), RTA_DATA(tb[IFA_LOCAL]),
- RTA_PAYLOAD(tb[IFA_ADDRESS]))) {
- broad = RTA_DATA(tb[IFA_ADDRESS]);
- SET_FLAG(flags, ZEBRA_IFA_PEER);
- } else
- /* seeking a broadcast address */
- broad = (tb[IFA_BROADCAST] ? RTA_DATA(tb[IFA_BROADCAST])
- : NULL);
-
- /* addr is primary key, SOL if we don't have one */
- if (addr == NULL) {
- zlog_debug("%s: Local Interface Address is NULL for %s",
- __func__, ifp->name);
- return -1;
- }
-
- /* Flags. */
- if (kernel_flags & IFA_F_SECONDARY)
- SET_FLAG(flags, ZEBRA_IFA_SECONDARY);
-
- /* Label */
- if (tb[IFA_LABEL])
- label = (char *)RTA_DATA(tb[IFA_LABEL]);
-
- if (label && strcmp(ifp->name, label) == 0)
- label = NULL;
-
- if (tb[IFA_RT_PRIORITY])
- metric = *(uint32_t *)RTA_DATA(tb[IFA_RT_PRIORITY]);
-
- /* Register interface address to the interface. */
- if (ifa->ifa_family == AF_INET) {
- if (ifa->ifa_prefixlen > IPV4_MAX_BITLEN) {
- zlog_err(
- "Invalid prefix length: %u received from kernel interface addr change: %s",
- ifa->ifa_prefixlen,
- nl_msg_type_to_str(h->nlmsg_type));
- return -1;
- }
-
- if (h->nlmsg_type == RTM_NEWADDR)
- connected_add_ipv4(ifp, flags, (struct in_addr *)addr,
- ifa->ifa_prefixlen,
- (struct in_addr *)broad, label,
- metric);
- else if (CHECK_FLAG(flags, ZEBRA_IFA_PEER)) {
- /* Delete with a peer address */
- connected_delete_ipv4(
- ifp, flags, (struct in_addr *)addr,
- ifa->ifa_prefixlen, broad);
- } else
- connected_delete_ipv4(
- ifp, flags, (struct in_addr *)addr,
- ifa->ifa_prefixlen, NULL);
- }
-
- if (ifa->ifa_family == AF_INET6) {
- if (ifa->ifa_prefixlen > IPV6_MAX_BITLEN) {
- zlog_err(
- "Invalid prefix length: %u received from kernel interface addr change: %s",
- ifa->ifa_prefixlen,
- nl_msg_type_to_str(h->nlmsg_type));
- return -1;
- }
- if (h->nlmsg_type == RTM_NEWADDR) {
- /* Only consider valid addresses; we'll not get a
- * notification from
- * the kernel till IPv6 DAD has completed, but at init
- * time, Quagga
- * does query for and will receive all addresses.
- */
- if (!(kernel_flags
- & (IFA_F_DADFAILED | IFA_F_TENTATIVE)))
- connected_add_ipv6(ifp, flags,
- (struct in6_addr *)addr,
- (struct in6_addr *)broad,
- ifa->ifa_prefixlen, label,
- metric);
- } else
- connected_delete_ipv6(ifp, (struct in6_addr *)addr,
- NULL, ifa->ifa_prefixlen);
- }
-
- /*
- * Linux kernel does not send route delete on interface down/addr del
- * so we have to re-process routes it owns (i.e. kernel routes)
- */
- if (h->nlmsg_type != RTM_NEWADDR)
- rib_update(RIB_UPDATE_KERNEL);
-
- return 0;
-}
-
/*
* Parse and validate an incoming interface address change message,
* generating a dplane context object.
diff --git a/zebra/if_netlink.h b/zebra/if_netlink.h
index 9b31906a17..dc1f71cb77 100644
--- a/zebra/if_netlink.h
+++ b/zebra/if_netlink.h
@@ -12,9 +12,6 @@
extern "C" {
#endif
-extern int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id,
- int startup);
-
/*
* Parse an incoming interface address change message, generate a dplane
* context object for processing.
diff --git a/zebra/rib.h b/zebra/rib.h
index 4293b5f240..5fedb07335 100644
--- a/zebra/rib.h
+++ b/zebra/rib.h
@@ -408,9 +408,6 @@ extern struct route_entry *rib_match_multicast(afi_t afi, vrf_id_t vrf_id,
union g_addr *gaddr,
struct route_node **rn_out);
-extern struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p,
- vrf_id_t vrf_id);
-
extern void rib_update(enum rib_update_event event);
extern void rib_update_table(struct route_table *table,
enum rib_update_event event, int rtype);
@@ -637,6 +634,10 @@ extern pid_t pid;
extern uint32_t rt_table_main_id;
+void route_entry_dump_nh(const struct route_entry *re, const char *straddr,
+ const struct vrf *re_vrf,
+ const struct nexthop *nexthop);
+
/* Name of hook calls */
#define ZEBRA_ON_RIB_PROCESS_HOOK_CALL "on_rib_process_dplane_results"
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 75e4396e92..dc679ed495 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -591,12 +591,9 @@ parse_nexthop_unicast(ns_id_t ns_id, struct rtmsg *rtm, struct rtattr **tb,
return nh;
}
-static uint8_t parse_multipath_nexthops_unicast(ns_id_t ns_id,
- struct nexthop_group *ng,
- struct rtmsg *rtm,
- struct rtnexthop *rtnh,
- struct rtattr **tb,
- void *prefsrc, vrf_id_t vrf_id)
+static uint16_t parse_multipath_nexthops_unicast(ns_id_t ns_id, struct nexthop_group *ng,
+ struct rtmsg *rtm, struct rtnexthop *rtnh,
+ struct rtattr **tb, void *prefsrc, vrf_id_t vrf_id)
{
void *gate = NULL;
struct interface *ifp = NULL;
@@ -721,7 +718,7 @@ static uint8_t parse_multipath_nexthops_unicast(ns_id_t ns_id,
rtnh = RTNH_NEXT(rtnh);
}
- uint8_t nhop_num = nexthop_group_nexthop_num(ng);
+ uint16_t nhop_num = nexthop_group_nexthop_num(ng);
return nhop_num;
}
@@ -1000,7 +997,7 @@ int netlink_route_change_read_unicast_internal(struct nlmsghdr *h,
(struct rtnexthop *)RTA_DATA(tb[RTA_MULTIPATH]);
if (!nhe_id) {
- uint8_t nhop_num;
+ uint16_t nhop_num;
/* Use temporary list of nexthops; parse
* message payload's nexthops.
@@ -2644,11 +2641,9 @@ int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *in)
/* Char length to debug ID with */
#define ID_LENGTH 10
-static bool _netlink_nexthop_build_group(struct nlmsghdr *n, size_t req_size,
- uint32_t id,
- const struct nh_grp *z_grp,
- const uint8_t count, bool resilient,
- const struct nhg_resilience *nhgr)
+static bool _netlink_nexthop_build_group(struct nlmsghdr *n, size_t req_size, uint32_t id,
+ const struct nh_grp *z_grp, const uint16_t count,
+ bool resilient, const struct nhg_resilience *nhgr)
{
struct nexthop_grp grp[count];
/* Need space for max group size, "/", and null term */
@@ -3285,7 +3280,7 @@ static int netlink_nexthop_process_group(struct rtattr **tb,
struct nh_grp *z_grp, int z_grp_size,
struct nhg_resilience *nhgr)
{
- uint8_t count = 0;
+ uint16_t count = 0;
/* linux/nexthop.h group struct */
struct nexthop_grp *n_grp = NULL;
@@ -3358,7 +3353,7 @@ int netlink_nexthop_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
struct nexthop nh = {.weight = 1};
struct nh_grp grp[MULTIPATH_NUM] = {};
/* Count of nexthops in group array */
- uint8_t grp_count = 0;
+ uint16_t grp_count = 0;
struct rtattr *tb[NHA_MAX + 1] = {};
frrtrace(3, frr_zebra, netlink_nexthop_change, h, ns_id, startup);
diff --git a/zebra/tc_netlink.c b/zebra/tc_netlink.c
index 19667e66ac..3c4db0090c 100644
--- a/zebra/tc_netlink.c
+++ b/zebra/tc_netlink.c
@@ -661,27 +661,6 @@ netlink_put_tc_filter_update_msg(struct nl_batch *bth,
}
/*
- * Request filters from the kernel
- */
-static int netlink_request_filters(struct zebra_ns *zns, int family, int type,
- ifindex_t ifindex)
-{
- struct {
- struct nlmsghdr n;
- struct tcmsg tc;
- } req;
-
- memset(&req, 0, sizeof(req));
- req.n.nlmsg_type = type;
- req.n.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
- req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg));
- req.tc.tcm_family = family;
- req.tc.tcm_ifindex = ifindex;
-
- return netlink_request(&zns->netlink_cmd, &req);
-}
-
-/*
* Request queue discipline from the kernel
*/
static int netlink_request_qdiscs(struct zebra_ns *zns, int family, int type)
@@ -852,23 +831,4 @@ int netlink_qdisc_read(struct zebra_ns *zns)
return 0;
}
-int netlink_tfilter_read_for_interface(struct zebra_ns *zns, ifindex_t ifindex)
-{
- int ret;
- struct zebra_dplane_info dp_info;
-
- zebra_dplane_info_from_zns(&dp_info, zns, true);
-
- ret = netlink_request_filters(zns, AF_UNSPEC, RTM_GETTFILTER, ifindex);
- if (ret < 0)
- return ret;
-
- ret = netlink_parse_info(netlink_tfilter_change, &zns->netlink_cmd,
- &dp_info, 0, true);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
#endif /* HAVE_NETLINK */
diff --git a/zebra/tc_netlink.h b/zebra/tc_netlink.h
index 5e95e6c1d8..300c53b6f5 100644
--- a/zebra/tc_netlink.h
+++ b/zebra/tc_netlink.h
@@ -50,8 +50,6 @@ netlink_put_tc_filter_update_msg(struct nl_batch *bth,
*/
extern int netlink_qdisc_read(struct zebra_ns *zns);
-extern int netlink_tfilter_read_for_interface(struct zebra_ns *zns,
- ifindex_t ifindex);
extern int netlink_tfilter_change(struct nlmsghdr *h, ns_id_t ns_id,
int startup);
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index c45c61a208..7dae75bacc 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -517,7 +517,7 @@ int zsend_redistribute_route(int cmd, struct zserv *client,
struct zapi_nexthop *api_nh;
struct nexthop *nexthop;
const struct prefix *p, *src_p;
- uint8_t count = 0;
+ uint16_t count = 0;
afi_t afi;
size_t stream_size =
MAX(ZEBRA_MAX_PACKET_SIZ, sizeof(struct zapi_route));
@@ -2477,22 +2477,6 @@ stream_failure:
return;
}
-/* Unregister all information in a VRF. */
-static void zread_vrf_unregister(ZAPI_HANDLER_ARGS)
-{
- int i;
- afi_t afi;
-
- for (afi = AFI_IP; afi < AFI_MAX; afi++) {
- for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
- vrf_bitmap_unset(&client->redist[afi][i],
- zvrf_id(zvrf));
- vrf_bitmap_unset(&client->redist_default[afi], zvrf_id(zvrf));
- vrf_bitmap_unset(&client->ridinfo[afi], zvrf_id(zvrf));
- vrf_bitmap_unset(&client->neighinfo[afi], zvrf_id(zvrf));
- }
-}
-
/*
* Validate incoming zapi mpls lsp / labels message
*/
@@ -4055,7 +4039,6 @@ void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
#if HAVE_BFDD > 0
[ZEBRA_BFD_DEST_REPLAY] = zebra_ptm_bfd_dst_replay,
#endif /* HAVE_BFDD */
- [ZEBRA_VRF_UNREGISTER] = zread_vrf_unregister,
[ZEBRA_VRF_LABEL] = zread_vrf_label,
[ZEBRA_BFD_CLIENT_REGISTER] = zebra_ptm_bfd_client_register,
[ZEBRA_INTERFACE_ENABLE_RADV] = zebra_interface_radv_enable,
diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c
index 75147e7136..00e990e856 100644
--- a/zebra/zebra_dplane.c
+++ b/zebra/zebra_dplane.c
@@ -86,7 +86,7 @@ struct dplane_nexthop_info {
struct nexthop_group ng;
struct nh_grp nh_grp[MULTIPATH_NUM];
- uint8_t nh_grp_count;
+ uint16_t nh_grp_count;
};
/*
@@ -2316,7 +2316,7 @@ dplane_ctx_get_nhe_nh_grp(const struct zebra_dplane_ctx *ctx)
return ctx->u.rinfo.nhe.nh_grp;
}
-uint8_t dplane_ctx_get_nhe_nh_grp_count(const struct zebra_dplane_ctx *ctx)
+uint16_t dplane_ctx_get_nhe_nh_grp_count(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
return ctx->u.rinfo.nhe.nh_grp_count;
diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h
index 0e9a8bfb99..a3318bf5e9 100644
--- a/zebra/zebra_dplane.h
+++ b/zebra/zebra_dplane.h
@@ -597,7 +597,7 @@ const struct nexthop_group *
dplane_ctx_get_nhe_ng(const struct zebra_dplane_ctx *ctx);
const struct nh_grp *
dplane_ctx_get_nhe_nh_grp(const struct zebra_dplane_ctx *ctx);
-uint8_t dplane_ctx_get_nhe_nh_grp_count(const struct zebra_dplane_ctx *ctx);
+uint16_t dplane_ctx_get_nhe_nh_grp_count(const struct zebra_dplane_ctx *ctx);
/* Accessors for LSP information */
diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c
index 4ee9dc5fcf..1519246c17 100644
--- a/zebra/zebra_nhg.c
+++ b/zebra/zebra_nhg.c
@@ -625,9 +625,8 @@ bool zebra_nhg_hash_id_equal(const void *arg1, const void *arg2)
return nhe1->id == nhe2->id;
}
-static int zebra_nhg_process_grp(struct nexthop_group *nhg,
- struct nhg_connected_tree_head *depends,
- struct nh_grp *grp, uint8_t count,
+static int zebra_nhg_process_grp(struct nexthop_group *nhg, struct nhg_connected_tree_head *depends,
+ struct nh_grp *grp, uint16_t count,
struct nhg_resilience *resilience)
{
nhg_connected_tree_init(depends);
@@ -982,7 +981,7 @@ static struct nexthop *nhg_ctx_get_nh(struct nhg_ctx *ctx)
return &ctx->u.nh;
}
-static uint8_t nhg_ctx_get_count(const struct nhg_ctx *ctx)
+static uint16_t nhg_ctx_get_count(const struct nhg_ctx *ctx)
{
return ctx->count;
}
@@ -1028,9 +1027,8 @@ done:
XFREE(MTYPE_NHG_CTX, *ctx);
}
-static struct nhg_ctx *nhg_ctx_init(uint32_t id, struct nexthop *nh,
- struct nh_grp *grp, vrf_id_t vrf_id,
- afi_t afi, int type, uint8_t count,
+static struct nhg_ctx *nhg_ctx_init(uint32_t id, struct nexthop *nh, struct nh_grp *grp,
+ vrf_id_t vrf_id, afi_t afi, int type, uint16_t count,
struct nhg_resilience *resilience)
{
struct nhg_ctx *ctx = NULL;
@@ -1101,11 +1099,15 @@ void zebra_nhg_check_valid(struct nhg_hash_entry *nhe)
bool valid = false;
/*
- * If I have other nhe's depending on me, then this is a
+ * If I have other nhe's depending on me, or I have nothing
+ * I am depending on then this is a
* singleton nhe so set this nexthops flag as appropriate.
*/
- if (nhg_connected_tree_count(&nhe->nhg_depends))
+ if (nhg_connected_tree_count(&nhe->nhg_depends) ||
+ nhg_connected_tree_count(&nhe->nhg_dependents) == 0) {
+ UNSET_FLAG(nhe->nhg.nexthop->flags, NEXTHOP_FLAG_FIB);
UNSET_FLAG(nhe->nhg.nexthop->flags, NEXTHOP_FLAG_ACTIVE);
+ }
/* If anthing else in the group is valid, the group is valid */
frr_each(nhg_connected_tree, &nhe->nhg_depends, rb_node_dep) {
@@ -1200,7 +1202,7 @@ static int nhg_ctx_process_new(struct nhg_ctx *ctx)
struct nhg_hash_entry *nhe = NULL;
uint32_t id = nhg_ctx_get_id(ctx);
- uint8_t count = nhg_ctx_get_count(ctx);
+ uint16_t count = nhg_ctx_get_count(ctx);
vrf_id_t vrf_id = nhg_ctx_get_vrf_id(ctx);
int type = nhg_ctx_get_type(ctx);
afi_t afi = nhg_ctx_get_afi(ctx);
@@ -1352,9 +1354,9 @@ int nhg_ctx_process(struct nhg_ctx *ctx)
}
/* Kernel-side, you either get a single new nexthop or a array of ID's */
-int zebra_nhg_kernel_find(uint32_t id, struct nexthop *nh, struct nh_grp *grp,
- uint8_t count, vrf_id_t vrf_id, afi_t afi, int type,
- int startup, struct nhg_resilience *nhgr)
+int zebra_nhg_kernel_find(uint32_t id, struct nexthop *nh, struct nh_grp *grp, uint16_t count,
+ vrf_id_t vrf_id, afi_t afi, int type, int startup,
+ struct nhg_resilience *nhgr)
{
struct nhg_ctx *ctx = NULL;
@@ -2922,13 +2924,162 @@ static uint32_t proto_nhg_nexthop_active_update(struct nexthop_group *nhg)
}
/*
+ * This function takes the start of two comparable nexthops from two different
+ * nexthop groups and walks them to see if they can be considered the same
+ * or not. This is being used to determine if zebra should reuse a nhg
+ * from the old_re to the new_re, when an interface goes down and the
+ * new nhg sent down from the upper level protocol would resolve to it
+ */
+static bool zebra_nhg_nexthop_compare(const struct nexthop *nhop,
+ const struct nexthop *old_nhop,
+ const struct route_node *rn)
+{
+ bool same = true;
+
+ while (nhop && old_nhop) {
+ if (IS_ZEBRA_DEBUG_NHG_DETAIL)
+ zlog_debug("%s: %pRN Comparing %pNHvv(%u) to old: %pNHvv(%u)",
+ __func__, rn, nhop, nhop->flags, old_nhop,
+ old_nhop->flags);
+ if (!CHECK_FLAG(old_nhop->flags, NEXTHOP_FLAG_ACTIVE)) {
+ if (IS_ZEBRA_DEBUG_NHG_DETAIL)
+ zlog_debug("%s: %pRN Old is not active going to the next one",
+ __func__, rn);
+ old_nhop = old_nhop->next;
+ continue;
+ }
+
+ if (nexthop_same(nhop, old_nhop)) {
+ struct nexthop *new_recursive, *old_recursive;
+
+ if (IS_ZEBRA_DEBUG_NHG_DETAIL)
+ zlog_debug("%s: %pRN New and old are same, continuing search",
+ __func__, rn);
+
+ new_recursive = nhop->resolved;
+ old_recursive = old_nhop->resolved;
+
+ while (new_recursive && old_recursive) {
+ if (!nexthop_same(new_recursive, old_recursive)) {
+ same = false;
+ break;
+ }
+
+ new_recursive = new_recursive->next;
+ old_recursive = old_recursive->next;
+ }
+
+ if (new_recursive)
+ same = false;
+ else if (old_recursive) {
+ while (old_recursive) {
+ if (CHECK_FLAG(old_recursive->flags,
+ NEXTHOP_FLAG_ACTIVE))
+ break;
+ old_recursive = old_recursive->next;
+ }
+
+ if (old_recursive)
+ same = false;
+ }
+
+ if (!same)
+ break;
+
+ nhop = nhop->next;
+ old_nhop = old_nhop->next;
+ continue;
+ } else {
+ if (IS_ZEBRA_DEBUG_NHG_DETAIL)
+ zlog_debug("%s:%pRN They are not the same, stopping using new nexthop entry",
+ __func__, rn);
+ same = false;
+ break;
+ }
+ }
+
+ if (nhop)
+ same = false;
+ else if (old_nhop) {
+ while (old_nhop) {
+ if (CHECK_FLAG(old_nhop->flags, NEXTHOP_FLAG_ACTIVE))
+ break;
+ old_nhop = old_nhop->next;
+ }
+
+ if (old_nhop)
+ same = false;
+ }
+
+ return same;
+}
+
+static struct nhg_hash_entry *zebra_nhg_rib_compare_old_nhe(
+ const struct route_node *rn, const struct route_entry *re,
+ struct nhg_hash_entry *new_nhe, struct nhg_hash_entry *old_nhe)
+{
+ struct nexthop *nhop, *old_nhop;
+ bool same = true;
+ struct vrf *vrf = vrf_lookup_by_id(re->vrf_id);
+
+ if (IS_ZEBRA_DEBUG_NHG_DETAIL) {
+ char straddr[PREFIX_STRLEN];
+
+ prefix2str(&rn->p, straddr, sizeof(straddr));
+ zlog_debug("%s: %pRN new id: %u old id: %u", __func__, rn,
+ new_nhe->id, old_nhe->id);
+ zlog_debug("%s: %pRN NEW", __func__, rn);
+ for (ALL_NEXTHOPS(new_nhe->nhg, nhop))
+ route_entry_dump_nh(re, straddr, vrf, nhop);
+
+ zlog_debug("%s: %pRN OLD", __func__, rn);
+ for (ALL_NEXTHOPS(old_nhe->nhg, nhop))
+ route_entry_dump_nh(re, straddr, vrf, nhop);
+ }
+
+ nhop = new_nhe->nhg.nexthop;
+ old_nhop = old_nhe->nhg.nexthop;
+
+ same = zebra_nhg_nexthop_compare(nhop, old_nhop, rn);
+
+ if (same) {
+ struct nexthop_group *bnhg, *old_bnhg;
+
+ bnhg = zebra_nhg_get_backup_nhg(new_nhe);
+ old_bnhg = zebra_nhg_get_backup_nhg(old_nhe);
+
+ if (bnhg || old_bnhg) {
+ if (bnhg && !old_bnhg)
+ same = false;
+ else if (!bnhg && old_bnhg)
+ same = false;
+ else
+ same = zebra_nhg_nexthop_compare(bnhg->nexthop,
+ old_bnhg->nexthop,
+ rn);
+ }
+ }
+
+ if (IS_ZEBRA_DEBUG_NHG_DETAIL)
+ zlog_debug("%s:%pRN They are %sthe same, using the %s nhg entry",
+ __func__, rn, same ? "" : "not ",
+ same ? "old" : "new");
+
+ if (same)
+ return old_nhe;
+ else
+ return new_nhe;
+}
+
+/*
* Iterate over all nexthops of the given RIB entry and refresh their
* ACTIVE flag. If any nexthop is found to toggle the ACTIVE flag,
* the whole re structure is flagged with ROUTE_ENTRY_CHANGED.
*
* Return value is the new number of active nexthops.
*/
-int nexthop_active_update(struct route_node *rn, struct route_entry *re)
+int nexthop_active_update(struct route_node *rn, struct route_entry *re,
+ struct route_entry *old_re)
{
struct nhg_hash_entry *curr_nhe;
uint32_t curr_active = 0, backup_active = 0;
@@ -2984,6 +3135,11 @@ backups_done:
new_nhe = zebra_nhg_rib_find_nhe(curr_nhe, rt_afi);
+ if (old_re && old_re->type == re->type &&
+ old_re->instance == re->instance)
+ new_nhe = zebra_nhg_rib_compare_old_nhe(rn, re, new_nhe,
+ old_re->nhe);
+
if (IS_ZEBRA_DEBUG_NHG_DETAIL)
zlog_debug(
"%s: re %p CHANGED: nhe %p (%pNG) => new_nhe %p (%pNG)",
@@ -3022,15 +3178,14 @@ backups_done:
* I'm pretty sure we only allow ONE level of group within group currently.
* But making this recursive just in case that ever changes.
*/
-static uint8_t zebra_nhg_nhe2grp_internal(struct nh_grp *grp, uint8_t curr_index,
- struct nhg_hash_entry *nhe,
- struct nhg_hash_entry *original,
- int max_num)
+static uint16_t zebra_nhg_nhe2grp_internal(struct nh_grp *grp, uint16_t curr_index,
+ struct nhg_hash_entry *nhe,
+ struct nhg_hash_entry *original, int max_num)
{
struct nhg_connected *rb_node_dep = NULL;
struct nhg_hash_entry *depend = NULL;
struct nexthop *nexthop;
- uint8_t i = curr_index;
+ uint16_t i = curr_index;
frr_each(nhg_connected_tree, &nhe->nhg_depends, rb_node_dep) {
bool duplicate = false;
@@ -3151,8 +3306,7 @@ done:
}
/* Convert a nhe into a group array */
-uint8_t zebra_nhg_nhe2grp(struct nh_grp *grp, struct nhg_hash_entry *nhe,
- int max_num)
+uint16_t zebra_nhg_nhe2grp(struct nh_grp *grp, struct nhg_hash_entry *nhe, int max_num)
{
/* Call into the recursive function */
return zebra_nhg_nhe2grp_internal(grp, 0, nhe, nhe, max_num);
@@ -3779,6 +3933,17 @@ void zebra_interface_nhg_reinstall(struct interface *ifp)
frr_each_safe (nhg_connected_tree,
&rb_node_dep->nhe->nhg_dependents,
rb_node_dependent) {
+ struct nexthop *nhop_dependent =
+ rb_node_dependent->nhe->nhg.nexthop;
+
+ while (nhop_dependent &&
+ !nexthop_same(nhop_dependent, nh))
+ nhop_dependent = nhop_dependent->next;
+
+ if (nhop_dependent)
+ SET_FLAG(nhop_dependent->flags,
+ NEXTHOP_FLAG_ACTIVE);
+
if (IS_ZEBRA_DEBUG_NHG)
zlog_debug("%s dependent nhe %pNG Setting Reinstall flag",
__func__,
diff --git a/zebra/zebra_nhg.h b/zebra/zebra_nhg.h
index 712c1057a1..0f90627a0d 100644
--- a/zebra/zebra_nhg.h
+++ b/zebra/zebra_nhg.h
@@ -231,7 +231,7 @@ struct nhg_ctx {
int type;
/* If its a group array, how many? */
- uint8_t count;
+ uint16_t count;
/* Its either a single nexthop or an array of ID's */
union {
@@ -317,10 +317,8 @@ extern int nhg_ctx_process(struct nhg_ctx *ctx);
void nhg_ctx_free(struct nhg_ctx **ctx);
/* Find via kernel nh creation */
-extern int zebra_nhg_kernel_find(uint32_t id, struct nexthop *nh,
- struct nh_grp *grp, uint8_t count,
- vrf_id_t vrf_id, afi_t afi, int type,
- int startup,
+extern int zebra_nhg_kernel_find(uint32_t id, struct nexthop *nh, struct nh_grp *grp,
+ uint16_t count, vrf_id_t vrf_id, afi_t afi, int type, int startup,
struct nhg_resilience *resilience);
/* Del via kernel */
extern int zebra_nhg_kernel_del(uint32_t id, vrf_id_t vrf_id);
@@ -379,8 +377,7 @@ extern void zebra_nhg_increment_ref(struct nhg_hash_entry *nhe);
extern void zebra_nhg_check_valid(struct nhg_hash_entry *nhe);
/* Convert nhe depends to a grp context that can be passed around safely */
-extern uint8_t zebra_nhg_nhe2grp(struct nh_grp *grp, struct nhg_hash_entry *nhe,
- int size);
+extern uint16_t zebra_nhg_nhe2grp(struct nh_grp *grp, struct nhg_hash_entry *nhe, int size);
/* Dataplane install/uninstall */
extern void zebra_nhg_install_kernel(struct nhg_hash_entry *nhe, uint8_t type);
@@ -404,7 +401,8 @@ extern void zebra_nhg_mark_keep(void);
/* Nexthop resolution processing */
struct route_entry; /* Forward ref to avoid circular includes */
-extern int nexthop_active_update(struct route_node *rn, struct route_entry *re);
+extern int nexthop_active_update(struct route_node *rn, struct route_entry *re,
+ struct route_entry *old_re);
#ifdef _FRR_ATTRIBUTE_PRINTFRR
#pragma FRR printfrr_ext "%pNG" (const struct nhg_hash_entry *)
diff --git a/zebra/zebra_pw.c b/zebra/zebra_pw.c
index deed3b6ad3..6adc0b1b4a 100644
--- a/zebra/zebra_pw.c
+++ b/zebra/zebra_pw.c
@@ -147,7 +147,6 @@ void zebra_pw_update(struct zebra_pw *pw)
{
if (zebra_pw_check_reachability(pw) < 0) {
zebra_pw_uninstall(pw);
- zebra_pw_install_failure(pw, PW_NOT_FORWARDING);
/* wait for NHT and try again later */
} else {
/*
@@ -167,12 +166,17 @@ static void zebra_pw_install(struct zebra_pw *pw)
hook_call(pw_install, pw);
if (dplane_pw_install(pw) == ZEBRA_DPLANE_REQUEST_FAILURE) {
+ /*
+ * Realistically this is never going to fail passing
+ * the pw data down to the dplane. The failure modes
+ * look like impossible events but we still return
+ * on them.... but I don't see a real clean way to remove this
+ * at all. So let's just leave the retry mechanism for
+ * the moment.
+ */
zebra_pw_install_failure(pw, PW_NOT_FORWARDING);
return;
}
-
- if (pw->status != PW_FORWARDING)
- zebra_pw_update_status(pw, PW_FORWARDING);
}
static void zebra_pw_uninstall(struct zebra_pw *pw)
@@ -188,9 +192,30 @@ static void zebra_pw_uninstall(struct zebra_pw *pw)
/* ignore any possible error */
hook_call(pw_uninstall, pw);
dplane_pw_uninstall(pw);
+}
+
+void zebra_pw_handle_dplane_results(struct zebra_dplane_ctx *ctx)
+{
+ struct zebra_pw *pw;
+ struct zebra_vrf *vrf;
+ enum dplane_op_e op;
+
+ op = dplane_ctx_get_op(ctx);
+
+ vrf = zebra_vrf_lookup_by_id(dplane_ctx_get_vrf(ctx));
+ pw = zebra_pw_find(vrf, dplane_ctx_get_ifname(ctx));
+
+ if (!pw)
+ return;
- if (zebra_pw_enabled(pw))
- zebra_pw_update_status(pw, PW_NOT_FORWARDING);
+ if (dplane_ctx_get_status(ctx) != ZEBRA_DPLANE_REQUEST_SUCCESS) {
+ zebra_pw_install_failure(pw, dplane_ctx_get_pw_status(ctx));
+ } else {
+ if (op == DPLANE_OP_PW_INSTALL && pw->status != PW_FORWARDING)
+ zebra_pw_update_status(pw, PW_FORWARDING);
+ else if (op == DPLANE_OP_PW_UNINSTALL && zebra_pw_enabled(pw))
+ zebra_pw_update_status(pw, PW_NOT_FORWARDING);
+ }
}
/*
diff --git a/zebra/zebra_pw.h b/zebra/zebra_pw.h
index 431d663f7c..e037a55048 100644
--- a/zebra/zebra_pw.h
+++ b/zebra/zebra_pw.h
@@ -64,6 +64,7 @@ void zebra_pw_init_vrf(struct zebra_vrf *);
void zebra_pw_exit_vrf(struct zebra_vrf *);
void zebra_pw_terminate(void);
void zebra_pw_vty_init(void);
+void zebra_pw_handle_dplane_results(struct zebra_dplane_ctx *ctx);
#ifdef __cplusplus
}
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 402a3104b9..8ebc193fba 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -611,45 +611,6 @@ struct route_entry *rib_match_multicast(afi_t afi, vrf_id_t vrf_id,
return re;
}
-struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p, vrf_id_t vrf_id)
-{
- struct route_table *table;
- struct route_node *rn;
- struct route_entry *match = NULL;
- rib_dest_t *dest;
-
- /* Lookup table. */
- table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id);
- if (!table)
- return 0;
-
- rn = route_node_lookup(table, (struct prefix *)p);
-
- /* No route for this prefix. */
- if (!rn)
- return NULL;
-
- /* Unlock node. */
- route_unlock_node(rn);
- dest = rib_dest_from_rnode(rn);
-
- if (dest && dest->selected_fib
- && !CHECK_FLAG(dest->selected_fib->status, ROUTE_ENTRY_REMOVED))
- match = dest->selected_fib;
-
- if (!match)
- return NULL;
-
- if (match->type == ZEBRA_ROUTE_CONNECT ||
- match->type == ZEBRA_ROUTE_LOCAL)
- return match;
-
- if (CHECK_FLAG(match->status, ROUTE_ENTRY_INSTALLED))
- return match;
-
- return NULL;
-}
-
/*
* Is this RIB labeled-unicast? It must be of type BGP and all paths
* (nexthops) must have a label.
@@ -1313,7 +1274,7 @@ static void rib_process(struct route_node *rn)
*/
if (CHECK_FLAG(re->status, ROUTE_ENTRY_CHANGED)) {
proto_re_changed = re;
- if (!nexthop_active_update(rn, re)) {
+ if (!nexthop_active_update(rn, re, old_fib)) {
const struct prefix *p;
struct rib_table_info *info;
@@ -4118,9 +4079,8 @@ void rib_delnode(struct route_node *rn, struct route_entry *re)
/*
* Helper that debugs a single nexthop within a route-entry
*/
-static void _route_entry_dump_nh(const struct route_entry *re,
- const char *straddr, const struct vrf *re_vrf,
- const struct nexthop *nexthop)
+void route_entry_dump_nh(const struct route_entry *re, const char *straddr,
+ const struct vrf *re_vrf, const struct nexthop *nexthop)
{
char nhname[PREFIX_STRLEN];
char backup_str[50];
@@ -4243,7 +4203,7 @@ void _route_entry_dump(const char *func, union prefixconstptr pp,
/* Dump nexthops */
for (ALL_NEXTHOPS(re->nhe->nhg, nexthop))
- _route_entry_dump_nh(re, straddr, vrf, nexthop);
+ route_entry_dump_nh(re, straddr, vrf, nexthop);
if (zebra_nhg_get_backup_nhg(re->nhe)) {
zlog_debug("%s(%s): backup nexthops:", straddr,
@@ -4251,7 +4211,7 @@ void _route_entry_dump(const char *func, union prefixconstptr pp,
nhg = zebra_nhg_get_backup_nhg(re->nhe);
for (ALL_NEXTHOPS_PTR(nhg, nexthop))
- _route_entry_dump_nh(re, straddr, vrf, nexthop);
+ route_entry_dump_nh(re, straddr, vrf, nexthop);
}
zlog_debug("%s(%s): dump complete", straddr, VRF_LOGNAME(vrf));
@@ -4891,29 +4851,6 @@ void rib_close_table(struct route_table *table)
}
/*
- * Handler for async dataplane results after a pseudowire installation
- */
-static void handle_pw_result(struct zebra_dplane_ctx *ctx)
-{
- struct zebra_pw *pw;
- struct zebra_vrf *vrf;
-
- /* The pseudowire code assumes success - we act on an error
- * result for installation attempts here.
- */
- if (dplane_ctx_get_op(ctx) != DPLANE_OP_PW_INSTALL)
- return;
-
- if (dplane_ctx_get_status(ctx) != ZEBRA_DPLANE_REQUEST_SUCCESS) {
- vrf = zebra_vrf_lookup_by_id(dplane_ctx_get_vrf(ctx));
- pw = zebra_pw_find(vrf, dplane_ctx_get_ifname(ctx));
- if (pw)
- zebra_pw_install_failure(pw,
- dplane_ctx_get_pw_status(ctx));
- }
-}
-
-/*
* Handle results from the dataplane system. Dequeue update context
* structs, dispatch to appropriate internal handlers.
*/
@@ -5019,7 +4956,7 @@ static void rib_process_dplane_results(struct event *thread)
case DPLANE_OP_PW_INSTALL:
case DPLANE_OP_PW_UNINSTALL:
- handle_pw_result(ctx);
+ zebra_pw_handle_dplane_results(ctx);
break;
case DPLANE_OP_SYS_ROUTE_ADD:
diff --git a/zebra/zebra_trace.h b/zebra/zebra_trace.h
index 17528c4bf1..6451562466 100644
--- a/zebra/zebra_trace.h
+++ b/zebra/zebra_trace.h
@@ -70,20 +70,6 @@ TRACEPOINT_EVENT(
TRACEPOINT_EVENT(
frr_zebra,
- netlink_interface_addr,
- TP_ARGS(
- struct nlmsghdr *, header,
- ns_id_t, ns_id,
- int, startup),
- TP_FIELDS(
- ctf_integer_hex(intptr_t, header, header)
- ctf_integer(uint32_t, ns_id, ns_id)
- ctf_integer(uint32_t, startup, startup)
- )
- )
-
-TRACEPOINT_EVENT(
- frr_zebra,
netlink_route_change_read_unicast,
TP_ARGS(
struct nlmsghdr *, header,