Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F157897425
D56187.id176960.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D56187.id176960.diff
View Options
diff --git a/sys/net/route/nhgrp_ctl.c b/sys/net/route/nhgrp_ctl.c
--- a/sys/net/route/nhgrp_ctl.c
+++ b/sys/net/route/nhgrp_ctl.c
@@ -632,6 +632,63 @@
return (nhg_priv);
}
+/*
+ * Merge nexthop group denoted by @gr_add with the nexthop group @gr_orig.
+ *
+ * Returns referenced nexthop group or NULL. In the latter case, @perror is
+ * filled with an error code.
+ * Note that function does NOT care if the next nexthops already exists
+ * in the @gr_orig. As a result, they will be added, resulting in the
+ * same nexthop being present multiple times in the new group.
+ */
+static struct nhgrp_priv *
+merge_nhgrps(struct nh_control *ctl, const struct nhgrp_object *gr_orig,
+ const struct nhgrp_object *gr_add, int *perror)
+{
+ char storage[64];
+ struct weightened_nhop *pnhops;
+ struct nhgrp_priv *nhg_priv;
+ const struct nhgrp_priv *orig_priv, *add_priv;
+ size_t sz;
+ int curr_nhops;
+
+ orig_priv = NHGRP_PRIV_CONST(gr_orig);
+ add_priv = NHGRP_PRIV_CONST(gr_add);
+ curr_nhops = orig_priv->nhg_nh_count;
+
+ *perror = 0;
+
+ sz = (orig_priv->nhg_nh_count + orig_priv->nhg_nh_count) *
+ sizeof(struct weightened_nhop);
+ /* optimize for <= 4 paths, each path=16 bytes */
+ if (sz <= sizeof(storage))
+ pnhops = (struct weightened_nhop *)&storage[0];
+ else {
+ pnhops = malloc(sz, M_TEMP, M_NOWAIT);
+ if (pnhops == NULL) {
+ *perror = ENOMEM;
+ return (NULL);
+ }
+ }
+
+ /* First, copy nhops from first group */
+ memcpy(pnhops, orig_priv->nhg_nh_weights,
+ orig_priv->nhg_nh_count * sizeof(struct weightened_nhop));
+ memcpy(&pnhops[curr_nhops], add_priv->nhg_nh_weights,
+ add_priv->nhg_nh_count * sizeof(struct weightened_nhop));
+ curr_nhops += add_priv->nhg_nh_count;
+
+ nhg_priv = get_nhgrp(ctl, pnhops, curr_nhops, 0, perror);
+
+ if (pnhops != (struct weightened_nhop *)&storage[0])
+ free(pnhops, M_TEMP);
+
+ if (nhg_priv == NULL)
+ return (NULL);
+
+ return (nhg_priv);
+}
+
/*
* Creates/finds nexthop group based on @wn and @num_nhops.
@@ -728,6 +785,8 @@
struct weightened_nhop wn[2] = {};
int error;
+ MPASS((!NH_IS_NHGRP(rnd_add->rnd_nhop)));
+
if (rnd_orig->rnd_nhop == NULL) {
/* No paths to add to, just reference current nhop */
*rnd_new = *rnd_add;
@@ -758,6 +817,46 @@
return (0);
}
+/*
+ * Creates new multipath group based on existing group/nhop in @rnd_orig and
+ * to-be-merged nhgrp @wn_add.
+ * Returns 0 on success and stores result in @rnd_new.
+ */
+int
+nhgrp_get_merge_group(struct rib_head *rh, struct route_nhop_data *rnd_orig,
+ struct route_nhop_data *rnd_add, struct route_nhop_data *rnd_new)
+{
+ struct nh_control *ctl = rh->nh_control;
+ struct nhgrp_priv *nhg_priv;
+ struct weightened_nhop wn = {};
+ int error;
+
+ MPASS((NH_IS_NHGRP(rnd_add->rnd_nhop)));
+
+ /* No paths to add to, Just give up */
+ if (rnd_orig->rnd_nhop == NULL)
+ return (EINVAL);
+
+ if (!NH_IS_NHGRP(rnd_orig->rnd_nhop)) {
+ wn.nh = rnd_orig->rnd_nhop;
+ wn.weight = rnd_orig->rnd_weight;
+ /* Get new nhop group with addition of nhops in nhgrp */
+ nhg_priv = append_nhops(ctl, rnd_add->rnd_nhgrp, &wn, 1,
+ &error);
+ } else {
+ /* Get new nhop group with addition of nhops in nhgrp */
+ nhg_priv = merge_nhgrps(ctl, rnd_orig->rnd_nhgrp, rnd_add->rnd_nhgrp,
+ &error);
+ }
+
+ if (nhg_priv == NULL)
+ return (error);
+ rnd_new->rnd_nhgrp = nhg_priv->nhg;
+ rnd_new->rnd_weight = 0;
+
+ return (0);
+}
+
/*
* Returns pointer to array of nexthops with weights for
* given @nhg. Stores number of items in the array into @pnum_nhops.
diff --git a/sys/net/route/route_ctl.c b/sys/net/route/route_ctl.c
--- a/sys/net/route/route_ctl.c
+++ b/sys/net/route/route_ctl.c
@@ -858,7 +858,10 @@
struct route_nhop_data rnd_new;
int error = 0;
- error = nhgrp_get_addition_group(rnh, rnd_orig, rnd_add, &rnd_new);
+ if (!NH_IS_NHGRP(rnd_add->rnd_nhop))
+ error = nhgrp_get_addition_group(rnh, rnd_orig, rnd_add, &rnd_new);
+ else
+ error = nhgrp_get_merge_group(rnh, rnd_orig, rnd_add, &rnd_new);
if (error != 0) {
if (error == EAGAIN) {
/*
diff --git a/sys/net/route/route_var.h b/sys/net/route/route_var.h
--- a/sys/net/route/route_var.h
+++ b/sys/net/route/route_var.h
@@ -309,6 +309,9 @@
int nhgrp_get_addition_group(struct rib_head *rnh,
struct route_nhop_data *rnd_orig, struct route_nhop_data *rnd_add,
struct route_nhop_data *rnd_new);
+int nhgrp_get_merge_group(struct rib_head *rnh,
+ struct route_nhop_data *rnd_orig, struct route_nhop_data *rnd_add,
+ struct route_nhop_data *rnd_new);
void nhgrp_ref_object(struct nhgrp_object *nhg);
uint32_t nhgrp_get_idx(const struct nhgrp_object *nhg);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, May 27, 7:12 AM (21 h, 6 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33549384
Default Alt Text
D56187.id176960.diff (4 KB)
Attached To
Mode
D56187: routing: Implement merge of nhgrp in new multipath route
Attached
Detach File
Event Timeline
Log In to Comment