summaryrefslogtreecommitdiffstats
path: root/sys/net/radix_mpath.c
diff options
context:
space:
mode:
authorkmacy <kmacy@FreeBSD.org>2009-04-14 23:05:36 +0000
committerkmacy <kmacy@FreeBSD.org>2009-04-14 23:05:36 +0000
commit8149bfaed6bb48e24c81b4fe830665f412bc7e32 (patch)
tree2c468e4e81b86a0a66401b94c6626251cbbccf6a /sys/net/radix_mpath.c
parent7500c86f06626d19d1c6296cfdb9f781600f1bf0 (diff)
downloadFreeBSD-src-8149bfaed6bb48e24c81b4fe830665f412bc7e32.zip
FreeBSD-src-8149bfaed6bb48e24c81b4fe830665f412bc7e32.tar.gz
Extend route command:
- add show as alias for get - add weights to allow mpath to do more than equal cost - add sticky / nostick to disable / re-enable per-connection load balancing This adds a field to rt_metrics_lite so network bits of world will need to be re-built. Reviewed by: jeli & qingli
Diffstat (limited to 'sys/net/radix_mpath.c')
-rw-r--r--sys/net/radix_mpath.c43
1 files changed, 27 insertions, 16 deletions
diff --git a/sys/net/radix_mpath.c b/sys/net/radix_mpath.c
index 8d94d01..9be01d2 100644
--- a/sys/net/radix_mpath.c
+++ b/sys/net/radix_mpath.c
@@ -77,15 +77,18 @@ rn_mpath_next(struct radix_node *rn)
return NULL;
}
-u_int32_t
+uint32_t
rn_mpath_count(struct radix_node *rn)
{
- u_int32_t i;
-
- i = 1;
- while ((rn = rn_mpath_next(rn)) != NULL)
- i++;
- return i;
+ uint32_t i = 0;
+ struct rtentry *rt;
+
+ while (rn != NULL) {
+ rt = (struct rtentry *)rn;
+ i += rt->rt_rmx.rmx_weight;
+ rn = rn_mpath_next(rn);
+ }
+ return (i);
}
struct rtentry *
@@ -256,10 +259,12 @@ different:
}
void
-rtalloc_mpath_fib(struct route *ro, u_int32_t hash, u_int fibnum)
+rtalloc_mpath_fib(struct route *ro, uint32_t hash, u_int fibnum)
{
struct radix_node *rn0, *rn;
u_int32_t n;
+ struct rtentry *rt;
+ int64_t weight;
/*
* XXX we don't attempt to lookup cached route again; what should
@@ -284,25 +289,31 @@ rtalloc_mpath_fib(struct route *ro, u_int32_t hash, u_int fibnum)
/* gw selection by Modulo-N Hash (RFC2991) XXX need improvement? */
hash += hashjitter;
hash %= n;
- while (hash-- > 0 && rn) {
+ 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;
}
-
/* XXX try filling rt_gwroute and avoid unreachable gw */
- /* if gw selection fails, use the first match (default) */
+ /* gw selection has failed - there must be only zero weight routes */
if (!rn) {
RT_UNLOCK(ro->ro_rt);
+ ro->ro_rt = NULL;
return;
}
-
- RTFREE_LOCKED(ro->ro_rt);
- ro->ro_rt = (struct rtentry *)rn;
- RT_LOCK(ro->ro_rt);
- RT_ADDREF(ro->ro_rt);
+ if (ro->ro_rt != rt) {
+ RTFREE_LOCKED(ro->ro_rt);
+ ro->ro_rt = (struct rtentry *)rn;
+ RT_LOCK(ro->ro_rt);
+ RT_ADDREF(ro->ro_rt);
+
+ }
RT_UNLOCK(ro->ro_rt);
}
OpenPOWER on IntegriCloud