funny ECMP
Ingo Flaschberger
if at xip.at
Thu Aug 26 15:58:00 UTC 2010
Hi,
with the help from OpenBSD I was able to get working code.
Patch attached; applies fo Freebsd 8.1 Stable
I was not able to implement all OpenBSD code in function
rn_delete from sys/net/radix.c
Currently I also see this (non critical) warnings:
rn_delete: inconsistent annotation
ifaddr cache = 0xffffff0032721e00 is deleted
I will go on with testing when I'm back from holiday in 1 week.
Kind regards,
Ingo Flaschberger
-------------- next part --------------
diff -r -u /usr/src/sys/amd64/conf/GENERIC /router/usr/src/sys/amd64/conf/GENERIC
--- /usr/src/sys/amd64/conf/GENERIC 2010-08-23 00:53:45.000000000 +0000
+++ /router/usr/src/sys/amd64/conf/GENERIC 2010-08-11 07:11:20.000000000 +0000
@@ -323,5 +323,3 @@
device fwip # IP over FireWire (RFC 2734,3146)
device dcons # Dumb console driver
device dcons_crom # Configuration ROM for dcons
-
-option RADIX_MPATH
diff -r -u /usr/src/sys/contrib/ipfilter/netinet/ip_pool.c /router/usr/src/sys/contrib/ipfilter/netinet/ip_pool.c
--- /usr/src/sys/contrib/ipfilter/netinet/ip_pool.c 2007-10-18 21:42:38.000000000 +0000
+++ /router/usr/src/sys/contrib/ipfilter/netinet/ip_pool.c 2010-08-26 11:52:21.000000000 +0000
@@ -620,7 +620,7 @@
RADIX_NODE_HEAD_LOCK(ipo->ipo_head);
ipo->ipo_head->rnh_deladdr(&ipe->ipn_addr, &ipe->ipn_mask,
- ipo->ipo_head);
+ ipo->ipo_head, NULL);
RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head);
ip_pool_node_deref(ipe);
@@ -751,7 +751,7 @@
RADIX_NODE_HEAD_LOCK(ipo->ipo_head);
while ((n = ipo->ipo_list) != NULL) {
ipo->ipo_head->rnh_deladdr(&n->ipn_addr, &n->ipn_mask,
- ipo->ipo_head);
+ ipo->ipo_head, NULL);
*n->ipn_pnext = n->ipn_next;
if (n->ipn_next)
@@ -963,7 +963,7 @@
struct radix_node_head *rnh = p;
struct radix_node *d;
- d = rnh->rnh_deladdr(n->rn_key, NULL, rnh);
+ d = rnh->rnh_deladdr(n->rn_key, NULL, rnh, NULL);
if (d != NULL) {
FreeS(d, max_keylen + 2 * sizeof (*d));
}
diff -r -u /usr/src/sys/contrib/pf/net/pf.c /router/usr/src/sys/contrib/pf/net/pf.c
--- /usr/src/sys/contrib/pf/net/pf.c 2010-01-23 00:32:19.000000000 +0000
+++ /router/usr/src/sys/contrib/pf/net/pf.c 2010-08-26 15:12:12.000000000 +0000
@@ -99,9 +99,7 @@
#include <net/if_types.h>
#include <net/bpf.h>
#include <net/route.h>
-#ifndef __FreeBSD__
#include <net/radix_mpath.h>
-#endif
#include <netinet/in.h>
#include <netinet/in_var.h>
@@ -6166,9 +6164,9 @@
if (kif->pfik_ifp == ifp)
ret = 1;
#ifdef __FreeBSD__ /* MULTIPATH_ROUTING */
- rn = NULL;
+ rn = rn_mpath_next(rn); /* XXX was before: rn = NULL; */
#else
- rn = rn_mpath_next(rn);
+ rn = rn_mpath_next(rn, 0);
#endif
} while (check_mpath == 1 && rn != NULL && ret == 0);
} else
diff -r -u /usr/src/sys/contrib/pf/net/pf_table.c /router/usr/src/sys/contrib/pf/net/pf_table.c
--- /usr/src/sys/contrib/pf/net/pf_table.c 2009-08-03 08:13:06.000000000 +0000
+++ /router/usr/src/sys/contrib/pf/net/pf_table.c 2010-08-26 11:50:31.000000000 +0000
@@ -1114,17 +1114,9 @@
#endif
if (KENTRY_NETWORK(ke)) {
pfr_prepare_network(&mask, ke->pfrke_af, ke->pfrke_net);
-#ifdef __FreeBSD__
- rn = rn_delete(&ke->pfrke_sa, &mask, head);
-#else
rn = rn_delete(&ke->pfrke_sa, &mask, head, NULL);
-#endif
} else
-#ifdef __FreeBSD__
- rn = rn_delete(&ke->pfrke_sa, NULL, head);
-#else
rn = rn_delete(&ke->pfrke_sa, NULL, head, NULL);
-#endif
splx(s);
if (rn == NULL) {
diff -r -u /usr/src/sys/kern/vfs_export.c /router/usr/src/sys/kern/vfs_export.c
--- /usr/src/sys/kern/vfs_export.c 2009-10-01 13:11:45.000000000 +0000
+++ /router/usr/src/sys/kern/vfs_export.c 2010-08-26 11:52:47.000000000 +0000
@@ -228,7 +228,7 @@
struct radix_node_head *rnh = (struct radix_node_head *) w;
struct ucred *cred;
- (*rnh->rnh_deladdr) (rn->rn_key, rn->rn_mask, rnh);
+ (*rnh->rnh_deladdr) (rn->rn_key, rn->rn_mask, rnh, NULL);
cred = ((struct netcred *)rn)->netc_anon;
if (cred != NULL)
crfree(cred);
diff -r -u /usr/src/sys/net/radix.c /router/usr/src/sys/net/radix.c
--- /usr/src/sys/net/radix.c 2010-04-02 05:02:50.000000000 +0000
+++ /router/usr/src/sys/net/radix.c 2010-08-26 15:23:24.000000000 +0000
@@ -614,7 +614,7 @@
struct radix_node treenodes[2];
{
caddr_t v = (caddr_t)v_arg, netmask = (caddr_t)n_arg;
- register struct radix_node *t, *x = 0, *tt;
+ register struct radix_node *t, *x = 0, *xx = 0, *tt;
struct radix_node *saved_tt, *top = head->rnh_treetop;
short b = 0, b_leaf = 0;
int keyduplicated;
@@ -723,12 +723,19 @@
x = t->rn_right;
/* Promote general routes from below */
if (x->rn_bit < 0) {
- for (mp = &t->rn_mklist; x; x = x->rn_dupedkey)
+ for (mp = &t->rn_mklist; x; xx = x, x = x->rn_dupedkey) {
+ if (xx && xx->rn_mklist && xx->rn_mask == x->rn_mask &&
+ x->rn_mklist == 0) {
+ /* multipath route, bump refcount on first mklist */
+ x->rn_mklist = xx->rn_mklist;
+ x->rn_mklist->rm_refs++;
+ }
if (x->rn_mask && (x->rn_bit >= b_leaf) && x->rn_mklist == 0) {
*mp = m = rn_new_radix_mask(x, 0);
if (m)
mp = &m->rm_mklist;
}
+ }
} else if (x->rn_mklist) {
/*
* Skip over masks whose index is > that of new node
@@ -783,9 +790,10 @@
}
struct radix_node *
-rn_delete(v_arg, netmask_arg, head)
+rn_delete(v_arg, netmask_arg, head, rn)
void *v_arg, *netmask_arg;
struct radix_node_head *head;
+ struct radix_node *rn;
{
register struct radix_node *t, *p, *x, *tt;
struct radix_mask *m, *saved_m, **mp;
@@ -815,6 +823,14 @@
if ((tt = tt->rn_dupedkey) == 0)
return (0);
}
+#ifdef RADIX_MPATH
+ if (rn) {
+ while (tt != rn)
+ if ((tt = tt->rn_dupedkey) == 0)
+ return (0);
+ }
+#endif
+
if (tt->rn_mask == 0 || (saved_m = m = tt->rn_mklist) == 0)
goto on1;
if (tt->rn_flags & RNF_NORMAL) {
@@ -822,6 +838,23 @@
log(LOG_ERR, "rn_delete: inconsistent annotation\n");
return 0; /* dangling ref could cause disaster */
}
+ if (m->rm_leaf != tt) {
+ if (--m->rm_refs >= 0)
+ goto on1;
+ }
+ /* tt is currently the head of the possible multipath chain */
+ if (m->rm_refs > 0) {
+ if (tt->rn_dupedkey == NULL ||
+ tt->rn_dupedkey->rn_mklist != m) {
+ log(LOG_ERR, "rn_delete: inconsistent "
+ "dupedkey list\n");
+ return (0);
+ }
+ m->rm_leaf = tt->rn_dupedkey;
+ --m->rm_refs;
+ goto on1;
+ }
+ /* else tt is last and only route */
} else {
if (m->rm_mask != tt->rn_mask) {
log(LOG_ERR, "rn_delete: inconsistent annotation\n");
@@ -869,21 +902,17 @@
*/
if (tt == saved_tt) {
/* remove from head of chain */
- x = dupedkey; x->rn_parent = t;
+ x = dupedkey;
+ x->rn_parent = t;
if (t->rn_left == tt)
t->rn_left = x;
else
t->rn_right = x;
} else {
- /* find node in front of tt on the chain */
- for (x = p = saved_tt; p && p->rn_dupedkey != tt;)
- p = p->rn_dupedkey;
- if (p) {
- p->rn_dupedkey = tt->rn_dupedkey;
- if (tt->rn_dupedkey) /* parent */
- tt->rn_dupedkey->rn_parent = p;
- /* parent */
- } else log(LOG_ERR, "rn_delete: couldn't find us\n");
+ x = saved_tt;
+ t->rn_dupedkey = tt->rn_dupedkey;
+ if (tt->rn_dupedkey)
+ tt->rn_dupedkey->rn_parent = t;
}
t = tt + 1;
if (t->rn_flags & RNF_ACTIVE) {
@@ -931,14 +960,21 @@
if (m == x->rn_mklist) {
struct radix_mask *mm = m->rm_mklist;
x->rn_mklist = 0;
- if (--(m->rm_refs) < 0)
+ if (--(m->rm_refs) < 0) {
MKFree(m);
+ } else if (m->rm_flags & RNF_NORMAL) {
+ /*
+ * don't progress because this
+ * a multipath route. Next
+ * route will use the same m.
+ */
+ mm = m;
+ }
m = mm;
}
if (m)
log(LOG_ERR,
- "rn_delete: Orphaned Mask %p at %p\n",
- m, x);
+ "rn_delete: Orphaned Mask %p at %p\n", m, x);
}
}
/*
@@ -990,11 +1026,8 @@
* rn_search_m is sort-of-open-coded here. We cannot use the
* function because we need to keep track of the last node seen.
*/
- /* printf("about to search\n"); */
for (rn = h->rnh_treetop; rn->rn_bit >= 0; ) {
last = rn;
- /* printf("rn_bit %d, rn_bmask %x, xm[rn_offset] %x\n",
- rn->rn_bit, rn->rn_bmask, xm[rn->rn_offset]); */
if (!(rn->rn_bmask & xm[rn->rn_offset])) {
break;
}
@@ -1004,7 +1037,6 @@
rn = rn->rn_left;
}
}
- /* printf("done searching\n"); */
/*
* Two cases: either we stepped off the end of our mask,
@@ -1015,8 +1047,6 @@
rn = last;
lastb = rn->rn_bit;
- /* printf("rn %p, lastb %d\n", rn, lastb);*/
-
/*
* This gets complicated because we may delete the node
* while applying the function f to it, so we need to calculate
@@ -1026,7 +1056,6 @@
rn = rn->rn_left;
while (!stopping) {
- /* printf("node %p (%d)\n", rn, rn->rn_bit); */
base = rn;
/* If at right child go back up, otherwise, go right */
while (rn->rn_parent->rn_right == rn
@@ -1036,7 +1065,6 @@
/* if went up beyond last, stop */
if (rn->rn_bit <= lastb) {
stopping = 1;
- /* printf("up too far\n"); */
/*
* XXX we should jump to the 'Process leaves'
* part, because the values of 'rn' and 'next'
@@ -1062,7 +1090,6 @@
/* Process leaves */
while ((rn = base) != 0) {
base = rn->rn_dupedkey;
- /* printf("leaf %p\n", rn); */
if (!(rn->rn_flags & RNF_ROOT)
&& (error = (*f)(rn, w)))
return (error);
@@ -1070,7 +1097,6 @@
rn = next;
if (rn->rn_flags & RNF_ROOT) {
- /* printf("root, stopping"); */
stopping = 1;
}
diff -r -u /usr/src/sys/net/radix.h /router/usr/src/sys/net/radix.h
--- /usr/src/sys/net/radix.h 2010-03-23 09:58:59.000000000 +0000
+++ /router/usr/src/sys/net/radix.h 2010-08-26 12:02:52.000000000 +0000
@@ -114,7 +114,7 @@
(void *v, void *mask,
struct radix_node_head *head, struct radix_node nodes[]);
struct radix_node *(*rnh_deladdr) /* remove based on sockaddr */
- (void *v, void *mask, struct radix_node_head *head);
+ (void *v, void *mask, struct radix_node_head *head, struct radix_node *rn);
struct radix_node *(*rnh_delpkt) /* remove based on packet hdr */
(void *v, void *mask, struct radix_node_head *head);
struct radix_node *(*rnh_matchaddr) /* locate based on sockaddr */
@@ -168,7 +168,7 @@
*rn_addmask(void *, int, int),
*rn_addroute (void *, void *, struct radix_node_head *,
struct radix_node [2]),
- *rn_delete(void *, void *, struct radix_node_head *),
+ *rn_delete(void *, void *, struct radix_node_head *, struct radix_node *),
*rn_lookup (void *v_arg, void *m_arg,
struct radix_node_head *head),
*rn_match(void *, struct radix_node_head *);
diff -r -u /usr/src/sys/net/radix_mpath.c /router/usr/src/sys/net/radix_mpath.c
--- /usr/src/sys/net/radix_mpath.c 2010-08-26 14:26:39.000000000 +0000
+++ /router/usr/src/sys/net/radix_mpath.c 2010-08-26 14:30:25.000000000 +0000
@@ -125,33 +125,6 @@
return (struct rtentry *)rn;
}
-/*
- * go through the chain and unlink "rt" from the list
- * the caller will free "rt"
- */
-int
-rt_mpath_deldup(struct rtentry *headrt, struct rtentry *rt)
-{
- struct radix_node *t, *tt;
-
- if (!headrt || !rt)
- return (0);
- t = (struct radix_node *)headrt;
- tt = rn_mpath_next(t);
- while (tt) {
- if (tt == (struct radix_node *)rt) {
- t->rn_dupedkey = tt->rn_dupedkey;
- tt->rn_dupedkey = NULL;
- tt->rn_flags &= ~RNF_ACTIVE;
- tt[1].rn_flags &= ~RNF_ACTIVE;
- return (1);
- }
- t = tt;
- tt = rn_mpath_next((struct radix_node *)t);
- }
- return (0);
-}
-
/*
* check if we have the same key/mask/gateway on the table already.
*/
@@ -262,9 +235,10 @@
rtalloc_mpath_fib(struct route *ro, uint32_t hash, u_int fibnum)
{
struct radix_node *rn0, *rn;
- u_int32_t n;
+ u_int32_t n = 0;
struct rtentry *rt;
int64_t weight;
+ int64_t lowest_weight;
/*
* XXX we don't attempt to lookup cached route again; what should
@@ -285,23 +259,34 @@
/* beyond here, we use rn as the master copy */
rn0 = rn = (struct radix_node *)ro->ro_rt;
- n = rn_mpath_count(rn0);
-
+
+ /* find lowest weight route */
+ for ( rt = (struct rtentry *)rn, weight = rt->rt_rmx.rmx_weight; rn != NULL; rn = rn_mpath_next( rn)) {
+ /* XXX check if route is up? */
+ rt = (struct rtentry *)rn;
+ if(rt->rt_flags & RTF_UP) {
+ if (weight > rt->rt_rmx.rmx_weight) {
+ weight = rt->rt_rmx.rmx_weight;
+ n = 1;
+ } else if (weight == rt->rt_rmx.rmx_weight)
+ n++;
+ }
+ }
+ lowest_weight = weight;
+
+ /* select now one of the lowest weight routes */
/* 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) {
-
- /* check if next key exists */
- if (rn->rn_dupedkey == NULL)
- break;
- /* stay within the multipath routes */
- if (rn->rn_dupedkey && rn->rn_mask != rn->rn_dupedkey->rn_mask)
- break;
- rn = rn->rn_dupedkey;
+ for ( rn = rn0, n = 0; rn != NULL; rn = rn_mpath_next( rn)) {
rt = (struct rtentry *)rn;
+ if(rt->rt_flags & RTF_UP) {
+ if ( rt->rt_rmx.rmx_weight == lowest_weight) {
+ if (n == hash)
+ break;
+ n++;
+ }
+ }
}
/* XXX try filling rt_gwroute and avoid unreachable gw */
diff -r -u /usr/src/sys/net/route.c /router/usr/src/sys/net/route.c
--- /usr/src/sys/net/route.c 2010-06-18 03:31:33.000000000 +0000
+++ /router/usr/src/sys/net/route.c 2010-08-26 14:42:13.000000000 +0000
@@ -875,7 +875,7 @@
* Remove the item from the tree; it should be there,
* but when callers invoke us blindly it may not (sigh).
*/
- rn = rnh->rnh_deladdr(rt_key(rt), rt_mask(rt), rnh);
+ rn = rnh->rnh_deladdr(rt_key(rt), rt_mask(rt), rnh, NULL);
if (rn == NULL) {
error = ESRCH;
goto bad;
@@ -913,112 +913,6 @@
return (error);
}
-#ifdef RADIX_MPATH
-static int
-rn_mpath_update(int req, struct rt_addrinfo *info,
- struct radix_node_head *rnh, struct rtentry **ret_nrt)
-{
- /*
- * if we got multipath routes, we require users to specify
- * a matching RTAX_GATEWAY.
- */
- struct rtentry *rt, *rto = NULL;
- register struct radix_node *rn;
- int error = 0;
-
- rn = rnh->rnh_matchaddr(dst, rnh);
- if (rn == NULL)
- return (ESRCH);
- rto = rt = RNTORT(rn);
- rt = rt_mpath_matchgate(rt, gateway);
- if (rt == NULL)
- return (ESRCH);
- /*
- * this is the first entry in the chain
- */
- if (rto == rt) {
- rn = rn_mpath_next((struct radix_node *)rt);
- /*
- * there is another entry, now it's active
- */
- if (rn) {
- rto = RNTORT(rn);
- RT_LOCK(rto);
- rto->rt_flags |= RTF_UP;
- RT_UNLOCK(rto);
- } else if (rt->rt_flags & RTF_GATEWAY) {
- /*
- * For gateway routes, we need to
- * make sure that we we are deleting
- * the correct gateway.
- * rt_mpath_matchgate() does not
- * check the case when there is only
- * one route in the chain.
- */
- if (gateway &&
- (rt->rt_gateway->sa_len != gateway->sa_len ||
- memcmp(rt->rt_gateway, gateway, gateway->sa_len)))
- error = ESRCH;
- else {
- /*
- * remove from tree before returning it
- * to the caller
- */
- rn = rnh->rnh_deladdr(dst, netmask, rnh);
- KASSERT(rt == RNTORT(rn), ("radix node disappeared"));
- goto gwdelete;
- }
-
- }
- /*
- * use the normal delete code to remove
- * the first entry
- */
- if (req != RTM_DELETE)
- goto nondelete;
-
- error = ENOENT;
- goto done;
- }
-
- /*
- * if the entry is 2nd and on up
- */
- if ((req == RTM_DELETE) && !rt_mpath_deldup(rto, rt))
- panic ("rtrequest1: rt_mpath_deldup");
-gwdelete:
- RT_LOCK(rt);
- RT_ADDREF(rt);
- if (req == RTM_DELETE) {
- rt->rt_flags &= ~RTF_UP;
- /*
- * One more rtentry floating around that is not
- * linked to the routing table. rttrash will be decremented
- * when RTFREE(rt) is eventually called.
- */
- V_rttrash++;
- }
-
-nondelete:
- if (req != RTM_DELETE)
- panic("unrecognized request %d", req);
-
-
- /*
- * If the caller wants it, then it can have it,
- * but it's up to it to free the rtentry as we won't be
- * doing it.
- */
- if (ret_nrt) {
- *ret_nrt = rt;
- RT_UNLOCK(rt);
- } else
- RTFREE_LOCKED(rt);
-done:
- return (error);
-}
-#endif
-
int
rtrequest1_fib(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt,
u_int fibnum)
@@ -1058,28 +952,30 @@
switch (req) {
case RTM_DELETE:
+ if ((rn = rnh->rnh_lookup(dst, netmask, rnh)) == NULL)
+ senderr(ESRCH);
+ rt = RNTORT(rn);
#ifdef RADIX_MPATH
- if (rn_mpath_capable(rnh)) {
- error = rn_mpath_update(req, info, rnh, ret_nrt);
- /*
- * "bad" holds true for the success case
- * as well
- */
- if (error != ENOENT)
- goto bad;
- error = 0;
- }
+ /*
+ * if we got multipath routes, we require users to specify
+ * a matching RTAX_GATEWAY.
+ */
+ if (rn_mpath_capable(rnh)) {
+ rt = rt_mpath_matchgate( rt, gateway);
+ rn = (struct radix_node *)rt;
+ if (!rt)
+ senderr(ESRCH);
+ }
#endif
/*
* Remove the item from the tree and return it.
* Complain if it is not there and do no more processing.
*/
- rn = rnh->rnh_deladdr(dst, netmask, rnh);
+ rn = rnh->rnh_deladdr(dst, netmask, rnh, rn);
if (rn == NULL)
senderr(ESRCH);
if (rn->rn_flags & (RNF_ACTIVE | RNF_ROOT))
panic ("rtrequest delete");
- rt = RNTORT(rn);
RT_LOCK(rt);
RT_ADDREF(rt);
rt->rt_flags &= ~RTF_UP;
@@ -1474,10 +1370,9 @@
RNTORT(rn)->rt_ifa != ifa ||
!sa_equal((struct sockaddr *)rn->rn_key, dst));
RADIX_NODE_HEAD_UNLOCK(rnh);
- if (error) {
+ if (error)
/* this is only an error if bad on ALL tables */
continue;
- }
}
/*
* Do the actual request
diff -r -u /usr/src/sys/netinet/in.c /router/usr/src/sys/netinet/in.c
--- /usr/src/sys/netinet/in.c 2010-08-26 14:57:57.000000000 +0000
+++ /router/usr/src/sys/netinet/in.c 2010-08-26 14:58:40.000000000 +0000
@@ -1373,12 +1373,45 @@
in_lltable_rtcheck(struct ifnet *ifp, u_int flags, const struct sockaddr *l3addr)
{
struct rtentry *rt;
+#ifdef RADIX_MPATH
+ int64_t weight;
+ struct rtentry *rt0;
+ int32_t found = 0;
+#endif
KASSERT(l3addr->sa_family == AF_INET,
("sin_family %d", l3addr->sa_family));
/* XXX rtalloc1 should take a const param */
rt = rtalloc1(__DECONST(struct sockaddr *, l3addr), 0, 0);
+
+#ifdef RADIX_MPATH
+ rt0 = rt;
+ if ((rt != NULL) && ( rn_mpath_next((struct radix_node *)rt) != NULL)) {
+ /* check if there are other, matching routes */
+ /* find lowest weight route */
+ for ( weight = rt->rt_rmx.rmx_weight; rt != NULL; rt = (struct rtentry *)rn_mpath_next( (struct radix_node *)rt)) {
+ if(rt->rt_flags & RTF_UP) {
+ if (weight > rt->rt_rmx.rmx_weight)
+ weight = rt->rt_rmx.rmx_weight;
+ }
+ }
+
+ /* find now one non gateway route with lowest weight */
+ for ( rt = rt0; rt != NULL; rt = (struct rtentry *)rn_mpath_next( (struct radix_node *)rt)) {
+ if(rt->rt_flags & RTF_UP) {
+ if ((weight == rt->rt_rmx.rmx_weight) && !(rt->rt_flags & RTF_GATEWAY)) {
+ found = 1;
+ break;
+ }
+ }
+ }
+ if (found == 0)
+ rt = NULL;
+ }
+
+#endif
+
if (rt == NULL || (!(flags & LLE_PUB) &&
((rt->rt_flags & RTF_GATEWAY) ||
(rt->rt_ifp != ifp)))) {
@@ -1386,11 +1419,21 @@
log(LOG_INFO, "IPv4 address: \"%s\" is not on the network\n",
inet_ntoa(((const struct sockaddr_in *)l3addr)->sin_addr));
#endif
+#ifdef RADIX_MPATH
+ if (rt0 != NULL)
+ RTFREE_LOCKED(rt0);
+#else
if (rt != NULL)
RTFREE_LOCKED(rt);
+#endif
return (EINVAL);
}
+#ifdef RADIX_MPATH
+ RTFREE_LOCKED(rt0);
+#else
RTFREE_LOCKED(rt);
+#endif
+
return 0;
}
diff -r -u /usr/src/sys/netinet/ipfw/ip_fw_table.c /router/usr/src/sys/netinet/ipfw/ip_fw_table.c
--- /usr/src/sys/netinet/ipfw/ip_fw_table.c 2010-03-23 09:58:59.000000000 +0000
+++ /router/usr/src/sys/netinet/ipfw/ip_fw_table.c 2010-08-26 12:47:27.000000000 +0000
@@ -137,7 +137,7 @@
mask.sin_addr.s_addr = htonl(mlen ? ~((1 << (32 - mlen)) - 1) : 0);
sa.sin_addr.s_addr = addr & mask.sin_addr.s_addr;
IPFW_WLOCK(ch);
- ent = (struct table_entry *)rnh->rnh_deladdr(&sa, &mask, rnh);
+ ent = (struct table_entry *)rnh->rnh_deladdr(&sa, &mask, rnh, NULL);
if (ent == NULL) {
IPFW_WUNLOCK(ch);
return (ESRCH);
@@ -154,7 +154,7 @@
struct table_entry *ent;
ent = (struct table_entry *)
- rnh->rnh_deladdr(rn->rn_key, rn->rn_mask, rnh);
+ rnh->rnh_deladdr(rn->rn_key, rn->rn_mask, rnh, NULL);
if (ent != NULL)
free(ent, M_IPFW_TBL);
return (0);
More information about the freebsd-net
mailing list