summaryrefslogtreecommitdiffstats
path: root/zebra
diff options
context:
space:
mode:
Diffstat (limited to 'zebra')
-rw-r--r--zebra/redistribute.c4
-rw-r--r--zebra/zebra_dplane.c65
-rw-r--r--zebra/zebra_nhg.c87
-rw-r--r--zebra/zebra_nhg.h1
-rw-r--r--zebra/zebra_rib.c37
5 files changed, 134 insertions, 60 deletions
diff --git a/zebra/redistribute.c b/zebra/redistribute.c
index d2fa85eb6..6767000f3 100644
--- a/zebra/redistribute.c
+++ b/zebra/redistribute.c
@@ -548,6 +548,10 @@ void zebra_interface_address_add_update(struct interface *ifp,
client, ifp, ifc);
}
}
+ /* interface associated NHGs may have been deleted,
+ * re-sync zebra -> dplane NHGs
+ */
+ zebra_interface_nhg_reinstall(ifp);
}
/* Interface address deletion. */
diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c
index f6c1fdd78..3653f7152 100644
--- a/zebra/zebra_dplane.c
+++ b/zebra/zebra_dplane.c
@@ -3785,18 +3785,12 @@ tc_qdisc_update_internal(enum dplane_op_e op,
/* Obtain context block */
ctx = dplane_ctx_alloc();
- if (!ctx) {
- ret = ENOMEM;
- goto done;
- }
-
/* Init context with info from zebra data structs */
ret = dplane_ctx_tc_qdisc_init(ctx, op, qdisc);
if (ret == AOK)
ret = dplane_update_enqueue(ctx);
-done:
/* Update counter */
atomic_fetch_add_explicit(&zdplane_info.dg_tcs_in, 1,
memory_order_relaxed);
@@ -3822,18 +3816,12 @@ tc_class_update_internal(enum dplane_op_e op, struct zebra_tc_class *class)
/* Obtain context block */
ctx = dplane_ctx_alloc();
- if (!ctx) {
- ret = ENOMEM;
- goto done;
- }
-
/* Init context with info from zebra data structs */
ret = dplane_ctx_tc_class_init(ctx, op, class);
if (ret == AOK)
ret = dplane_update_enqueue(ctx);
-done:
/* Update counter */
atomic_fetch_add_explicit(&zdplane_info.dg_tcs_in, 1,
memory_order_relaxed);
@@ -3859,18 +3847,12 @@ tc_filter_update_internal(enum dplane_op_e op, struct zebra_tc_filter *filter)
/* Obtain context block */
ctx = dplane_ctx_alloc();
- if (!ctx) {
- ret = ENOMEM;
- goto done;
- }
-
/* Init context with info from zebra data structs */
ret = dplane_ctx_tc_filter_init(ctx, op, filter);
if (ret == AOK)
ret = dplane_update_enqueue(ctx);
-done:
/* Update counter */
atomic_fetch_add_explicit(&zdplane_info.dg_tcs_in, 1,
memory_order_relaxed);
@@ -3943,16 +3925,11 @@ dplane_nexthop_update_internal(struct nhg_hash_entry *nhe, enum dplane_op_e op)
/* Obtain context block */
ctx = dplane_ctx_alloc();
- if (!ctx) {
- ret = ENOMEM;
- goto done;
- }
ret = dplane_ctx_nexthop_init(ctx, op, nhe);
if (ret == AOK)
ret = dplane_update_enqueue(ctx);
-done:
/* Update counter */
atomic_fetch_add_explicit(&zdplane_info.dg_nexthops_in, 1,
memory_order_relaxed);
@@ -4083,8 +4060,6 @@ dplane_route_notif_update(struct route_node *rn,
goto done;
new_ctx = dplane_ctx_alloc();
- if (new_ctx == NULL)
- goto done;
/* Init context with info from zebra data structs */
dplane_ctx_route_init(new_ctx, op, rn, re);
@@ -4216,10 +4191,6 @@ dplane_lsp_notif_update(struct zebra_lsp *lsp, enum dplane_op_e op,
/* Obtain context block */
ctx = dplane_ctx_alloc();
- if (ctx == NULL) {
- ret = ENOMEM;
- goto done;
- }
/* Copy info from zebra LSP */
ret = dplane_ctx_lsp_init(ctx, op, lsp);
@@ -4589,16 +4560,11 @@ dplane_intf_update_internal(const struct interface *ifp, enum dplane_op_e op)
/* Obtain context block */
ctx = dplane_ctx_alloc();
- if (!ctx) {
- ret = ENOMEM;
- goto done;
- }
ret = dplane_ctx_intf_init(ctx, op, ifp);
if (ret == AOK)
ret = dplane_update_enqueue(ctx);
-done:
/* Update counter */
atomic_fetch_add_explicit(&zdplane_info.dg_intfs_in, 1,
memory_order_relaxed);
@@ -5337,8 +5303,10 @@ dplane_gre_set(struct interface *ifp, struct interface *ifp_link,
ctx = dplane_ctx_alloc();
- if (!ifp)
- return result;
+ if (!ifp) {
+ ret = EINVAL;
+ goto done;
+ }
if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
zlog_debug("init dplane ctx %s: if %s link %s%s",
@@ -5350,8 +5318,11 @@ dplane_gre_set(struct interface *ifp, struct interface *ifp_link,
ctx->zd_op = op;
ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS;
zns = zebra_ns_lookup(ifp->vrf->vrf_id);
- if (!zns)
- return result;
+ if (!zns) {
+ ret = EINVAL;
+ goto done;
+ }
+
dplane_ctx_ns_init(ctx, zns, false);
dplane_ctx_set_ifname(ctx, ifp->name);
@@ -5370,6 +5341,7 @@ dplane_gre_set(struct interface *ifp, struct interface *ifp_link,
/* Enqueue context for processing */
ret = dplane_update_enqueue(ctx);
+done:
/* Update counter */
atomic_fetch_add_explicit(&zdplane_info.dg_gre_set_in, 1,
memory_order_relaxed);
@@ -5764,6 +5736,21 @@ void dplane_provider_enqueue_out_ctx(struct zebra_dplane_provider *prov,
memory_order_relaxed);
}
+static struct zebra_dplane_ctx *
+dplane_provider_dequeue_out_ctx(struct zebra_dplane_provider *prov)
+{
+ struct zebra_dplane_ctx *ctx;
+
+ ctx = dplane_ctx_list_pop(&(prov->dp_ctx_out_list));
+ if (!ctx)
+ return NULL;
+
+ atomic_fetch_sub_explicit(&(prov->dp_out_queued), 1,
+ memory_order_relaxed);
+
+ return ctx;
+}
+
/*
* Accessor for provider object
*/
@@ -6791,7 +6778,7 @@ static void dplane_thread_loop(struct event *event)
dplane_provider_lock(prov);
while (counter < limit) {
- ctx = dplane_ctx_list_pop(&(prov->dp_ctx_out_list));
+ ctx = dplane_provider_dequeue_out_ctx(prov);
if (ctx) {
dplane_ctx_list_add_tail(&work_list, ctx);
counter++;
diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c
index 8616b1405..96e021292 100644
--- a/zebra/zebra_nhg.c
+++ b/zebra/zebra_nhg.c
@@ -1125,13 +1125,23 @@ static void zebra_nhg_handle_uninstall(struct nhg_hash_entry *nhe)
zebra_nhg_free(nhe);
}
-static void zebra_nhg_handle_install(struct nhg_hash_entry *nhe)
+static void zebra_nhg_handle_install(struct nhg_hash_entry *nhe, bool install)
{
/* Update validity of groups depending on it */
struct nhg_connected *rb_node_dep;
- frr_each_safe(nhg_connected_tree, &nhe->nhg_dependents, rb_node_dep)
+ frr_each_safe (nhg_connected_tree, &nhe->nhg_dependents, rb_node_dep) {
zebra_nhg_set_valid(rb_node_dep->nhe);
+ /* install dependent NHG into kernel */
+ if (install) {
+ if (IS_ZEBRA_DEBUG_NHG_DETAIL)
+ zlog_debug(
+ "%s nh id %u (flags 0x%x) associated dependent NHG %pNG install",
+ __func__, nhe->id, nhe->flags,
+ rb_node_dep->nhe);
+ zebra_nhg_install_kernel(rb_node_dep->nhe);
+ }
+ }
}
/*
@@ -3080,6 +3090,12 @@ void zebra_nhg_install_kernel(struct nhg_hash_entry *nhe)
/* Resolve it first */
nhe = zebra_nhg_resolve(nhe);
+ if (zebra_nhg_set_valid_if_active(nhe)) {
+ if (IS_ZEBRA_DEBUG_NHG_DETAIL)
+ zlog_debug("%s: valid flag set for nh %pNG", __func__,
+ nhe);
+ }
+
/* Make sure all depends are installed/queued */
frr_each(nhg_connected_tree, &nhe->nhg_depends, rb_node_dep) {
zebra_nhg_install_kernel(rb_node_dep->nhe);
@@ -3106,7 +3122,7 @@ void zebra_nhg_install_kernel(struct nhg_hash_entry *nhe)
break;
case ZEBRA_DPLANE_REQUEST_SUCCESS:
SET_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED);
- zebra_nhg_handle_install(nhe);
+ zebra_nhg_handle_install(nhe, false);
break;
}
}
@@ -3180,7 +3196,7 @@ void zebra_nhg_dplane_result(struct zebra_dplane_ctx *ctx)
if (status == ZEBRA_DPLANE_REQUEST_SUCCESS) {
SET_FLAG(nhe->flags, NEXTHOP_GROUP_VALID);
SET_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED);
- zebra_nhg_handle_install(nhe);
+ zebra_nhg_handle_install(nhe, true);
/* If daemon nhg, send it an update */
if (PROTO_OWNED(nhe))
@@ -3651,3 +3667,66 @@ static ssize_t printfrr_nhghe(struct fbuf *buf, struct printfrr_eargs *ea,
ret += bputs(buf, "]");
return ret;
}
+
+/*
+ * On interface add the nexthop that resolves to this intf needs
+ * a re-install. There are following scenarios when the nexthop group update
+ * gets skipped:
+ * 1. When upper level protocol sends removal of NHG, there is
+ * timer running to keep NHG for 180 seconds, during this interval, same route
+ * with same set of nexthops installation is given , the same NHG is used
+ * but since NHG is not reinstalled on interface address add, it is not aware
+ * in Dplan/Kernel.
+ * 2. Due to a quick port flap due to interface add and delete
+ * to be processed in same queue one after another. Zebra believes that
+ * there is no change in nhg in this case. Hence this re-install will
+ * make sure the nexthop group gets updated to Dplan/Kernel.
+ */
+void zebra_interface_nhg_reinstall(struct interface *ifp)
+{
+ struct nhg_connected *rb_node_dep = NULL;
+ struct zebra_if *zif = ifp->info;
+ struct nexthop *nh;
+
+ if (IS_ZEBRA_DEBUG_NHG_DETAIL)
+ zlog_debug(
+ "%s: Installing interface %s associated NHGs into kernel",
+ __func__, ifp->name);
+
+ frr_each (nhg_connected_tree, &zif->nhg_dependents, rb_node_dep) {
+ nh = rb_node_dep->nhe->nhg.nexthop;
+ if (zebra_nhg_set_valid_if_active(rb_node_dep->nhe)) {
+ if (IS_ZEBRA_DEBUG_NHG_DETAIL)
+ zlog_debug(
+ "%s: Setting the valid flag for nhe %pNG, interface: %s",
+ __func__, rb_node_dep->nhe, ifp->name);
+ }
+ /* Check for singleton NHG associated to interface */
+ if (nexthop_is_ifindex_type(nh) &&
+ zebra_nhg_depends_is_empty(rb_node_dep->nhe)) {
+ struct nhg_connected *rb_node_dependent;
+
+ if (IS_ZEBRA_DEBUG_NHG)
+ zlog_debug(
+ "%s install nhe %pNG nh type %u flags 0x%x",
+ __func__, rb_node_dep->nhe, nh->type,
+ rb_node_dep->nhe->flags);
+ zebra_nhg_install_kernel(rb_node_dep->nhe);
+
+ /* mark depedent uninstall, when interface associated
+ * singleton is installed, install depedent
+ */
+ frr_each_safe (nhg_connected_tree,
+ &rb_node_dep->nhe->nhg_dependents,
+ rb_node_dependent) {
+ if (IS_ZEBRA_DEBUG_NHG)
+ zlog_debug(
+ "%s dependent nhe %pNG unset installed flag",
+ __func__,
+ rb_node_dependent->nhe);
+ UNSET_FLAG(rb_node_dependent->nhe->flags,
+ NEXTHOP_GROUP_INSTALLED);
+ }
+ }
+ }
+}
diff --git a/zebra/zebra_nhg.h b/zebra/zebra_nhg.h
index b178007b4..6179be344 100644
--- a/zebra/zebra_nhg.h
+++ b/zebra/zebra_nhg.h
@@ -358,6 +358,7 @@ extern uint8_t zebra_nhg_nhe2grp(struct nh_grp *grp, struct nhg_hash_entry *nhe,
/* Dataplane install/uninstall */
extern void zebra_nhg_install_kernel(struct nhg_hash_entry *nhe);
extern void zebra_nhg_uninstall_kernel(struct nhg_hash_entry *nhe);
+extern void zebra_interface_nhg_reinstall(struct interface *ifp);
/* Forward ref of dplane update context type */
struct zebra_dplane_ctx;
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index adcaf6404..357f11282 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -4704,6 +4704,21 @@ static void rib_process_dplane_results(struct event *thread)
struct dplane_ctx_list_head ctxlist;
bool shut_p = false;
+#ifdef HAVE_SCRIPTING
+ char *script_name =
+ frrscript_names_get_script_name(ZEBRA_ON_RIB_PROCESS_HOOK_CALL);
+
+ int ret = 1;
+ struct frrscript *fs = NULL;
+
+ if (script_name) {
+ fs = frrscript_new(script_name);
+ if (fs)
+ ret = frrscript_load(fs, ZEBRA_ON_RIB_PROCESS_HOOK_CALL,
+ NULL);
+ }
+#endif /* HAVE_SCRIPTING */
+
/* Dequeue a list of completed updates with one lock/unlock cycle */
do {
@@ -4737,24 +4752,7 @@ static void rib_process_dplane_results(struct event *thread)
continue;
}
-#ifdef HAVE_SCRIPTING
- char *script_name = frrscript_names_get_script_name(
- ZEBRA_ON_RIB_PROCESS_HOOK_CALL);
-
- int ret = 1;
- struct frrscript *fs;
-
- if (script_name) {
- fs = frrscript_new(script_name);
- if (fs)
- ret = frrscript_load(
- fs, ZEBRA_ON_RIB_PROCESS_HOOK_CALL,
- NULL);
- }
-#endif /* HAVE_SCRIPTING */
-
while (ctx) {
-
#ifdef HAVE_SCRIPTING
if (ret == 0)
frrscript_call(fs,
@@ -4869,6 +4867,11 @@ static void rib_process_dplane_results(struct event *thread)
}
} while (1);
+
+#ifdef HAVE_SCRIPTING
+ if (fs)
+ frrscript_delete(fs);
+#endif
}
/*