From 42f8123a4fa8354f07e3ebce1d3b6c2def7db5a3 Mon Sep 17 00:00:00 2001 From: "Alexander V. Chernikov" Date: Fri, 2 Dec 2022 17:58:03 +0000 Subject: [PATCH] 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);