]> git.proxmox.com Git - mirror_frr.git/commitdiff
zebra: re-install nhg on interface up
authorAshwini Reddy <ashred@nvidia.com>
Wed, 19 Apr 2023 18:35:25 +0000 (11:35 -0700)
committerChirag Shah <chirag@nvidia.com>
Fri, 5 May 2023 21:37:52 +0000 (14:37 -0700)
Intermittently zebra and kernel are out of sync
when interface flaps and the add's/dels are in
same processing queue and zebra assumes no change in nexthop.
Hence we need to bring in a reinstall to kernel
of the nexthops and routes to sync their states.

Upon interface flap kernel would have deleted NHGs
associated to a interface (the one flapped),
zebra retains NHGs for 3 mins even though upper
layer protocol removes the nexthops (associated NHG).
As part of interface address add ,
re-add singleton NHGs associated to interface.

Ticket: #3173663
Issue: 3173663

Signed-off-by: Ashwini Reddy <ashred@nvidia.com>
Signed-off-by: Chirag Shah <chirag@nvidia.com>
lib/nexthop.c
lib/nexthop.h
zebra/redistribute.c
zebra/zebra_nhg.c
zebra/zebra_nhg.h

index b04c95c05e114d34b5f0ce09574c1c05f5bba4d6..dcbb76b68e106a4585276d81ac2709b60f6a213e 100644 (file)
@@ -1076,3 +1076,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;
+}
index 1d95a3eee9b869c24548501291fa1fc35ef9bf6f..43dd71e11231c85f3c950b4467d0522e64ba624c 100644 (file)
@@ -234,6 +234,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
index d2fa85eb6446ad491ae0323f588ca17c56090b5a..6767000f3b4ca18a7af882cca0ef7d99e102aa22 100644 (file)
@@ -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. */
index 8616b140506b3b431d4de10f94daf6099259ccc6..2888a9ac6d9bbe7ee7941ca0d7d9dacc1967d4c0 100644 (file)
@@ -3080,6 +3080,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);
@@ -3651,3 +3657,43 @@ 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))
+                       zebra_nhg_install_kernel(rb_node_dep->nhe);
+       }
+}
index b178007b4ef1d4e60288ab91b5c083e5f1f69ccd..6179be3442e79a3e7d00f40e59cfadef86b8eb7e 100644 (file)
@@ -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;