git: 42f8123a4fa8 - main - routing: provide dedicated function for nhgrp creation and linking.

From: Alexander V. Chernikov <melifaro_at_FreeBSD.org>
Date: Fri, 02 Dec 2022 20:08:57 UTC
The branch main has been updated by melifaro:

URL: https://cgit.FreeBSD.org/src/commit/?id=42f8123a4fa8354f07e3ebce1d3b6c2def7db5a3

commit 42f8123a4fa8354f07e3ebce1d3b6c2def7db5a3
Author:     Alexander V. Chernikov <melifaro@FreeBSD.org>
AuthorDate: 2022-12-02 17:58:03 +0000
Commit:     Alexander V. Chernikov <melifaro@FreeBSD.org>
CommitDate: 2022-12-02 20:08:47 +0000

    routing: provide dedicated function for nhgrp creation and linking.
    
    There is a need to store client metadata in nexthops and nexthop groups.
    This metadata is immutable and participate in nhop/nhg comparison.
    
    Nexthops KPI already supports its: nexthop creation pattern is
    ```
    nhop_alloc()
    nhop_set_...()
    ...
    nhop_get_nhop()
    ```
    
    This change provides a similar pattern for the nexthop groups.
    Specifically, it adds nhgrp_alloc(), nhgrp_get_nhgrp() and
    nhgrp_set_uidx().
    
    MFC after:      2 weeks
---
 sys/net/route/nhgrp_ctl.c | 84 ++++++++++++++++++++++++++++++++++++++++-------
 sys/net/route/nhop.h      |  4 +++
 2 files changed, 77 insertions(+), 11 deletions(-)

diff --git a/sys/net/route/nhgrp_ctl.c b/sys/net/route/nhgrp_ctl.c
index 842f9d5376bc..5d6fb219f877 100644
--- a/sys/net/route/nhgrp_ctl.c
+++ b/sys/net/route/nhgrp_ctl.c
@@ -459,15 +459,24 @@ free_nhgrp_nhops(struct nhgrp_priv *nhg_priv)
 }
 
 /*
- * Creates or looks up an existing nexthop group based on @wn and @num_nhops.
- *
- * Returns referenced nhop group or NULL, passing error code in @perror.
+ * Allocate nexthop group of size @num_nhops with nexthops specified by
+ * @wn. Nexthops have to be unique and match the fibnum/family of the group.
+ * Returns unlinked nhgrp object on success or NULL and non-zero perror.
  */
-struct nhgrp_priv *
-get_nhgrp(struct nh_control *ctl, struct weightened_nhop *wn, int num_nhops,
-    uint32_t uidx, int *perror)
+struct nhgrp_object *
+nhgrp_alloc(uint32_t fibnum, int family, struct weightened_nhop *wn, int num_nhops,
+    int *perror)
 {
-	struct nhgrp_priv *key, *nhg_priv;
+	struct rib_head *rh = rt_tables_get_rnh(fibnum, family);
+	struct nhgrp_priv *nhg_priv;
+	struct nh_control *ctl;
+
+	if (rh == NULL) {
+		*perror = E2BIG;
+		return (NULL);
+	}
+
+	ctl = rh->nh_control;
 
 	if (num_nhops > RIB_MAX_MPATH_WIDTH) {
 		*perror = E2BIG;
@@ -486,6 +495,10 @@ get_nhgrp(struct nh_control *ctl, struct weightened_nhop *wn, int num_nhops,
 	sort_weightened_nhops(wn, num_nhops);
 	uint32_t last_id = 0;
 	for (int i = 0; i < num_nhops; i++) {
+		if (wn[i].nh->nh_priv->nh_control != ctl) {
+			*perror = EINVAL;
+			return (NULL);
+		}
 		if (wn[i].nh->nh_priv->nh_idx == last_id) {
 			*perror = EEXIST;
 			return (NULL);
@@ -493,11 +506,25 @@ get_nhgrp(struct nh_control *ctl, struct weightened_nhop *wn, int num_nhops,
 		last_id = wn[i].nh->nh_priv->nh_idx;
 	}
 
-	if ((key = alloc_nhgrp(wn, num_nhops)) == NULL) {
+	if ((nhg_priv = alloc_nhgrp(wn, num_nhops)) == NULL) {
 		*perror = ENOMEM;
 		return (NULL);
 	}
-	key->nhg_uidx = uidx;
+	nhg_priv->nh_control = ctl;
+
+	*perror = 0;
+	return (nhg_priv->nhg);
+}
+
+/*
+ * Finds an existing group matching @nhg or links @nhg to the tree.
+ * Returns the referenced group or NULL and non-zero @perror.
+ */
+struct nhgrp_object *
+nhgrp_get_nhgrp(struct nhgrp_object *nhg, int *perror)
+{
+	struct nhgrp_priv *nhg_priv, *key = NHGRP_PRIV(nhg);
+	struct nh_control *ctl = key->nh_control;
 
 	nhg_priv = find_nhgrp(ctl, key);
 	if (nhg_priv != NULL) {
@@ -508,7 +535,7 @@ get_nhgrp(struct nh_control *ctl, struct weightened_nhop *wn, int num_nhops,
 		 */
 		destroy_nhgrp_int(key);
 		*perror = 0;
-		return (nhg_priv);
+		return (nhg_priv->nhg);
 	} else {
 		/* No existing group, try to link the new one */
 		if (!ref_nhgrp_nhops(key)) {
@@ -529,12 +556,35 @@ get_nhgrp(struct nh_control *ctl, struct weightened_nhop *wn, int num_nhops,
 			return (NULL);
 		}
 		*perror = 0;
-		return (key);
+		return (nhg);
 	}
 
 	/* NOTREACHED */
 }
 
+/*
+ * Creates or looks up an existing nexthop group based on @wn and @num_nhops.
+ *
+ * Returns referenced nhop group or NULL, passing error code in @perror.
+ */
+struct nhgrp_priv *
+get_nhgrp(struct nh_control *ctl, struct weightened_nhop *wn, int num_nhops,
+    uint32_t uidx, int *perror)
+{
+	struct nhgrp_object *nhg;
+
+	nhg = nhgrp_alloc(ctl->ctl_rh->rib_fibnum, ctl->ctl_rh->rib_family,
+	    wn, num_nhops, perror);
+	if (nhg == NULL)
+		return (NULL);
+	nhgrp_set_uidx(nhg, uidx);
+	nhg = nhgrp_get_nhgrp(nhg, perror);
+	if (nhg != NULL)
+		return (NHGRP_PRIV(nhg));
+	return (NULL);
+}
+
+
 /*
  * Appends one or more nexthops denoted by @wm to the nexthop group @gr_orig.
  *
@@ -732,6 +782,18 @@ nhgrp_get_nhops(const struct nhgrp_object *nhg, uint32_t *pnum_nhops)
 	return (nhg_priv->nhg_nh_weights);
 }
 
+void
+nhgrp_set_uidx(struct nhgrp_object *nhg, uint32_t uidx)
+{
+	struct nhgrp_priv *nhg_priv;
+
+	KASSERT(((nhg->nhg_flags & MPF_MULTIPATH) != 0), ("nhop is not mpath"));
+
+	nhg_priv = NHGRP_PRIV(nhg);
+
+	nhg_priv->nhg_uidx = uidx;
+}
+
 uint32_t
 nhgrp_get_uidx(const struct nhgrp_object *nhg)
 {
diff --git a/sys/net/route/nhop.h b/sys/net/route/nhop.h
index f0feccd6c0f2..f79cdb3459e9 100644
--- a/sys/net/route/nhop.h
+++ b/sys/net/route/nhop.h
@@ -224,6 +224,10 @@ void nhop_set_expire(struct nhop_object *nh, uint32_t expire);
 struct rib_head *nhop_get_rh(const struct nhop_object *nh);
 
 struct nhgrp_object;
+struct nhgrp_object *nhgrp_alloc(uint32_t fibnum, int family,
+    struct weightened_nhop *wn, int num_nhops, int *perror);
+struct nhgrp_object *nhgrp_get_nhgrp(struct nhgrp_object *nhg, int *perror);
+void nhgrp_set_uidx(struct nhgrp_object *nhg, uint32_t uidx);
 uint32_t nhgrp_get_uidx(const struct nhgrp_object *nhg);
 uint8_t nhgrp_get_origin(const struct nhgrp_object *nhg);
 void nhgrp_set_origin(struct nhgrp_object *nhg, uint8_t origin);