Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

zebra: re-install NHG on interface up (backport #13413) #15362

Merged
merged 2 commits into from
Feb 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions lib/nexthop.c
Original file line number Diff line number Diff line change
Expand Up @@ -1092,3 +1092,12 @@ static ssize_t printfrr_nh(struct fbuf *buf, struct printfrr_eargs *ea,
}
return -1;
}

bool nexthop_is_ifindex_type(const struct nexthop *nh)
{
if (nh->type == NEXTHOP_TYPE_IFINDEX ||
nh->type == NEXTHOP_TYPE_IPV4_IFINDEX ||
nh->type == NEXTHOP_TYPE_IPV6_IFINDEX)
return true;
return false;
}
3 changes: 3 additions & 0 deletions lib/nexthop.h
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,9 @@ extern struct nexthop *nexthop_dup(const struct nexthop *nexthop,
extern struct nexthop *nexthop_dup_no_recurse(const struct nexthop *nexthop,
struct nexthop *rparent);

/* Check nexthop of IFINDEX type */
extern bool nexthop_is_ifindex_type(const struct nexthop *nh);

/*
* Parse one or more backup index values, as comma-separated numbers,
* into caller's array of uint8_ts. The array must be NEXTHOP_MAX_BACKUPS
Expand Down
4 changes: 4 additions & 0 deletions zebra/redistribute.c
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,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. */
Expand Down
87 changes: 83 additions & 4 deletions zebra/zebra_nhg.c
Original file line number Diff line number Diff line change
Expand Up @@ -1140,13 +1140,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);
}
}
}

/*
Expand Down Expand Up @@ -3003,6 +3013,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);
Expand All @@ -3029,7 +3045,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;
}
}
Expand Down Expand Up @@ -3103,7 +3119,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))
Expand Down Expand Up @@ -3585,3 +3601,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);
}
}
}
}
1 change: 1 addition & 0 deletions zebra/zebra_nhg.h
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,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;
Expand Down
Loading