diff options
Diffstat (limited to 'freebsd/sys/net/radix_mpath.c')
-rw-r--r-- | freebsd/sys/net/radix_mpath.c | 92 |
1 files changed, 58 insertions, 34 deletions
diff --git a/freebsd/sys/net/radix_mpath.c b/freebsd/sys/net/radix_mpath.c index 1bce388e..f5215205 100644 --- a/freebsd/sys/net/radix_mpath.c +++ b/freebsd/sys/net/radix_mpath.c @@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$"); #include <net/radix.h> #include <net/radix_mpath.h> #include <net/route.h> +#include <net/route_var.h> #include <net/if.h> #include <net/if_var.h> @@ -59,12 +60,19 @@ __FBSDID("$FreeBSD$"); static uint32_t hashjitter; int -rn_mpath_capable(struct radix_node_head *rnh) +rt_mpath_capable(struct rib_head *rnh) { return rnh->rnh_multipath; } +int +rn_mpath_capable(struct radix_head *rh) +{ + + return (rt_mpath_capable((struct rib_head *)rh)); +} + struct radix_node * rn_mpath_next(struct radix_node *rn) { @@ -91,7 +99,7 @@ rn_mpath_count(struct radix_node *rn) while (rn != NULL) { rt = (struct rtentry *)rn; - i += rt->rt_rmx.rmx_weight; + i += rt->rt_weight; rn = rn_mpath_next(rn); } return (i); @@ -165,14 +173,14 @@ rt_mpath_deldup(struct rtentry *headrt, struct rtentry *rt) * Assume @rt rt_key host bits are cleared according to @netmask */ int -rt_mpath_conflict(struct radix_node_head *rnh, struct rtentry *rt, +rt_mpath_conflict(struct rib_head *rnh, struct rtentry *rt, struct sockaddr *netmask) { struct radix_node *rn, *rn1; struct rtentry *rt1; rn = (struct radix_node *)rt; - rn1 = rnh->rnh_lookup(rt_key(rt), netmask, rnh); + rn1 = rnh->rnh_lookup(rt_key(rt), netmask, &rnh->head); if (!rn1 || rn1->rn_flags & RNF_ROOT) return (0); @@ -203,18 +211,50 @@ rt_mpath_conflict(struct radix_node_head *rnh, struct rtentry *rt, return (0); } -void -#ifndef __rtems__ -rtalloc_mpath_fib(struct route *ro, uint32_t hash, u_int fibnum) -#else /* __rtems__ */ -rtalloc_mpath_fib(struct route *ro, u_int32_t hash, u_int fibnum) -#endif /* __rtems__ */ +static struct rtentry * +rt_mpath_selectrte(struct rtentry *rte, uint32_t hash) { struct radix_node *rn0, *rn; - u_int32_t n; + uint32_t total_weight; struct rtentry *rt; int64_t weight; + /* beyond here, we use rn as the master copy */ + rn0 = rn = (struct radix_node *)rte; + rt = rte; + + /* gw selection by Modulo-N Hash (RFC2991) XXX need improvement? */ + total_weight = rn_mpath_count(rn0); + hash += hashjitter; + hash %= total_weight; + for (weight = abs((int32_t)hash); + rt != NULL && weight >= rt->rt_weight; + weight -= (rt == NULL) ? 0 : rt->rt_weight) { + + /* stay within the multipath routes */ + if (rn->rn_dupedkey && rn->rn_mask != rn->rn_dupedkey->rn_mask) + break; + rn = rn->rn_dupedkey; + rt = (struct rtentry *)rn; + } + + return (rt); +} + +struct rtentry * +rt_mpath_select(struct rtentry *rte, uint32_t hash) +{ + if (rn_mpath_next((struct radix_node *)rte) == NULL) + return (rte); + + return (rt_mpath_selectrte(rte, hash)); +} + +void +rtalloc_mpath_fib(struct route *ro, uint32_t hash, u_int fibnum) +{ + struct rtentry *rt; + /* * XXX we don't attempt to lookup cached route again; what should * be done for sendto(3) case? @@ -232,34 +272,18 @@ rtalloc_mpath_fib(struct route *ro, u_int32_t hash, u_int fibnum) return; } - /* beyond here, we use rn as the master copy */ - rn0 = rn = (struct radix_node *)ro->ro_rt; - n = rn_mpath_count(rn0); - - /* gw selection by Modulo-N Hash (RFC2991) XXX need improvement? */ - hash += hashjitter; - hash %= n; - for (weight = abs((int32_t)hash), rt = ro->ro_rt; - weight >= rt->rt_rmx.rmx_weight && rn; - weight -= rt->rt_rmx.rmx_weight) { - - /* stay within the multipath routes */ - if (rn->rn_dupedkey && rn->rn_mask != rn->rn_dupedkey->rn_mask) - break; - rn = rn->rn_dupedkey; - rt = (struct rtentry *)rn; - } + rt = rt_mpath_selectrte(ro->ro_rt, hash); /* XXX try filling rt_gwroute and avoid unreachable gw */ /* gw selection has failed - there must be only zero weight routes */ - if (!rn) { + if (!rt) { RT_UNLOCK(ro->ro_rt); ro->ro_rt = NULL; return; } if (ro->ro_rt != rt) { RTFREE_LOCKED(ro->ro_rt); - ro->ro_rt = (struct rtentry *)rn; + ro->ro_rt = rt; RT_LOCK(ro->ro_rt); RT_ADDREF(ro->ro_rt); @@ -274,11 +298,11 @@ extern int in_inithead(void **head, int off); int rn4_mpath_inithead(void **head, int off) { - struct radix_node_head *rnh; + struct rib_head *rnh; hashjitter = arc4random(); if (in_inithead(head, off) == 1) { - rnh = (struct radix_node_head *)*head; + rnh = (struct rib_head *)*head; rnh->rnh_multipath = 1; return 1; } else @@ -290,11 +314,11 @@ rn4_mpath_inithead(void **head, int off) int rn6_mpath_inithead(void **head, int off) { - struct radix_node_head *rnh; + struct rib_head *rnh; hashjitter = arc4random(); if (in6_inithead(head, off) == 1) { - rnh = (struct radix_node_head *)*head; + rnh = (struct rib_head *)*head; rnh->rnh_multipath = 1; return 1; } else |