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
This commit is contained in:
Alexander V. Chernikov 2022-12-02 17:58:03 +00:00
parent da5d0a1dbc
commit 42f8123a4f
2 changed files with 77 additions and 11 deletions

View File

@ -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. * 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 referenced nhop group or NULL, passing error code in @perror. * Returns unlinked nhgrp object on success or NULL and non-zero perror.
*/ */
struct nhgrp_priv * struct nhgrp_object *
get_nhgrp(struct nh_control *ctl, struct weightened_nhop *wn, int num_nhops, nhgrp_alloc(uint32_t fibnum, int family, struct weightened_nhop *wn, int num_nhops,
uint32_t uidx, int *perror) 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) { if (num_nhops > RIB_MAX_MPATH_WIDTH) {
*perror = E2BIG; *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); sort_weightened_nhops(wn, num_nhops);
uint32_t last_id = 0; uint32_t last_id = 0;
for (int i = 0; i < num_nhops; i++) { 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) { if (wn[i].nh->nh_priv->nh_idx == last_id) {
*perror = EEXIST; *perror = EEXIST;
return (NULL); 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; 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; *perror = ENOMEM;
return (NULL); 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); nhg_priv = find_nhgrp(ctl, key);
if (nhg_priv != NULL) { 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); destroy_nhgrp_int(key);
*perror = 0; *perror = 0;
return (nhg_priv); return (nhg_priv->nhg);
} else { } else {
/* No existing group, try to link the new one */ /* No existing group, try to link the new one */
if (!ref_nhgrp_nhops(key)) { if (!ref_nhgrp_nhops(key)) {
@ -529,12 +556,35 @@ get_nhgrp(struct nh_control *ctl, struct weightened_nhop *wn, int num_nhops,
return (NULL); return (NULL);
} }
*perror = 0; *perror = 0;
return (key); return (nhg);
} }
/* NOTREACHED */ /* 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. * 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); 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 uint32_t
nhgrp_get_uidx(const struct nhgrp_object *nhg) nhgrp_get_uidx(const struct nhgrp_object *nhg)
{ {

View File

@ -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 rib_head *nhop_get_rh(const struct nhop_object *nh);
struct nhgrp_object; 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); uint32_t nhgrp_get_uidx(const struct nhgrp_object *nhg);
uint8_t nhgrp_get_origin(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); void nhgrp_set_origin(struct nhgrp_object *nhg, uint8_t origin);