Martin Pieuchot
unread,Oct 25, 2015, 10:25:39 AM10/25/15You do not have permission to delete messages in this group
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to
Instead of having a separate function to check for MPATH conflicts
simply pass the gateway to rtable_insert(). Some regress tests
outputs will need an update as we're now doing one more rtalloc(9)
call in RTM_ADD.
This is a step towards MPATH by default.
ok?
Index: net/route.c
===================================================================
RCS file: /cvs/src/sys/net/route.c,v
retrieving revision 1.262
diff -u -p -r1.262 route.c
--- net/route.c 25 Oct 2015 11:58:11 -0000 1.262
+++ net/route.c 25 Oct 2015 14:14:28 -0000
@@ -837,15 +837,6 @@ rtrequest1(int req, struct rt_addrinfo *
else
memcpy(ndst, info->rti_info[RTAX_DST], dlen);
-#ifndef SMALL_KERNEL
- /* Do not permit exactly the same dst/mask/gw pair. */
- if (rtable_mpath_conflict(tableid, ndst,
- info->rti_info[RTAX_NETMASK], info->rti_info[RTAX_GATEWAY],
- prio, info->rti_flags & RTF_MPATH)) {
- free(ndst, M_RTABLE, dlen);
- return (EEXIST);
- }
-#endif
rt = pool_get(&rtentry_pool, PR_NOWAIT | PR_ZERO);
if (rt == NULL) {
free(ndst, M_RTABLE, dlen);
@@ -953,13 +944,15 @@ rtrequest1(int req, struct rt_addrinfo *
}
error = rtable_insert(tableid, ndst,
- info->rti_info[RTAX_NETMASK], rt->rt_priority, rt);
+ info->rti_info[RTAX_NETMASK], info->rti_info[RTAX_GATEWAY],
+ rt->rt_priority, rt);
if (error != 0 && (crt = rtalloc(ndst, 0, tableid)) != NULL) {
/* overwrite cloned route */
if ((crt->rt_flags & RTF_CLONED) != 0) {
rtdeletemsg(crt, tableid);
error = rtable_insert(tableid, ndst,
info->rti_info[RTAX_NETMASK],
+ info->rti_info[RTAX_GATEWAY],
rt->rt_priority, rt);
}
rtfree(crt);
Index: net/rtable.c
===================================================================
RCS file: /cvs/src/sys/net/rtable.c,v
retrieving revision 1.14
diff -u -p -r1.14 rtable.c
--- net/rtable.c 22 Oct 2015 17:19:38 -0000 1.14
+++ net/rtable.c 25 Oct 2015 14:13:57 -0000
@@ -292,7 +292,8 @@ rtable_match(unsigned int rtableid, stru
int
rtable_insert(unsigned int rtableid, struct sockaddr *dst,
- struct sockaddr *mask, uint8_t prio, struct rtentry *rt)
+ struct sockaddr *mask, struct sockaddr *gateway, uint8_t prio,
+ struct rtentry *rt)
{
struct radix_node_head *rnh;
struct radix_node *rn = (struct radix_node *)rt;
@@ -301,6 +302,15 @@ rtable_insert(unsigned int rtableid, str
if (rnh == NULL)
return (EAFNOSUPPORT);
+#ifndef SMALL_KERNEL
+ if (rnh->rnh_multipath) {
+ /* Do not permit exactly the same dst/mask/gw pair. */
+ if (rt_mpath_conflict(rnh, dst, mask, gateway, prio,
+ ISSET(rt->rt_flags, RTF_MPATH)))
+ return (EEXIST);
+ }
+#endif
+
rn = rn_addroute(dst, mask, rnh, rn, prio);
if (rn == NULL)
return (ESRCH);
@@ -382,22 +392,6 @@ rtable_mpath_match(unsigned int rtableid
return (rt);
}
-int
-rtable_mpath_conflict(unsigned int rtableid, struct sockaddr *dst,
- struct sockaddr *mask, struct sockaddr *gateway, uint8_t prio, int mpathok)
-{
- struct radix_node_head *rnh;
-
- rnh = rtable_get(rtableid, dst->sa_family);
- if (rnh == NULL)
- return (EAFNOSUPPORT);
-
- if (rnh->rnh_multipath == 0)
- return (0);
-
- return (rt_mpath_conflict(rnh, dst, mask, gateway, prio, mpathok));
-}
-
/* Gateway selection by Hash-Threshold (RFC 2992) */
struct rtentry *
rtable_mpath_select(struct rtentry *rt, uint32_t hash)
@@ -526,7 +520,8 @@ rtable_match(unsigned int rtableid, stru
int
rtable_insert(unsigned int rtableid, struct sockaddr *dst,
- struct sockaddr *mask, uint8_t prio, struct rtentry *rt)
+ struct sockaddr *mask, struct sockaddr *gateway, uint8_t prio,
+ struct rtentry *rt)
{
#ifndef SMALL_KERNEL
struct rtentry *mrt;
@@ -545,6 +540,29 @@ rtable_insert(unsigned int rtableid, str
if (plen == -1)
return (EINVAL);
+#ifndef SMALL_KERNEL
+ /* Do not permit exactly the same dst/mask/gw pair. */
+ an = art_lookup(ar, addr, plen);
+ if (an != NULL && an->an_plen == plen &&
+ !memcmp(an->an_dst, dst, dst->sa_len)) {
+ struct rtentry *mrt;
+ int mpathok = ISSET(rt->rt_flags, RTF_MPATH);
+
+ LIST_FOREACH(mrt, &an->an_rtlist, rt_next) {
+ if (prio != RTP_ANY &&
+ (mrt->rt_priority & RTP_MASK) != (prio & RTP_MASK))
+ continue;
+
+ if (!mpathok)
+ return (EEXIST);
+
+ if (mrt->rt_gateway->sa_len == gateway->sa_len &&
+ !memcmp(mrt->rt_gateway, gateway, gateway->sa_len))
+ return (EEXIST);
+ }
+ }
+#endif
+
an = pool_get(&an_pool, PR_NOWAIT | PR_ZERO);
if (an == NULL)
return (ENOBUFS);
@@ -754,48 +772,6 @@ rtable_mpath_match(unsigned int rtableid
rtfree(rt0);
return (rt);
-}
-
-int
-rtable_mpath_conflict(unsigned int rtableid, struct sockaddr *dst,
- struct sockaddr *mask, struct sockaddr *gateway, uint8_t prio, int mpathok)
-{
- struct art_root *ar;
- struct art_node *an;
- struct rtentry *rt;
- uint8_t *addr;
- int plen;
-
- ar = rtable_get(rtableid, dst->sa_family);
- if (ar == NULL)
- return (EAFNOSUPPORT);
-
- addr = satoaddr(ar, dst);
- plen = satoplen(ar, mask);
- if (plen == -1)
- return (EINVAL);
-
- an = art_lookup(ar, addr, plen);
- /* Make sure we've got a perfect match. */
- if (an == NULL || an->an_plen != plen ||
- memcmp(an->an_dst, dst, dst->sa_len))
- return (0);
-
- LIST_FOREACH(rt, &an->an_rtlist, rt_next) {
- if (prio != RTP_ANY &&
- (rt->rt_priority & RTP_MASK) != (prio & RTP_MASK))
- continue;
-
- if (!mpathok)
- return (EEXIST);
-
- if (rt->rt_gateway->sa_len == gateway->sa_len &&
- memcmp(rt->rt_gateway, gateway, gateway->sa_len) == 0)
- return (EEXIST);
- }
-
-
- return (0);
}
/* Gateway selection by Hash-Threshold (RFC 2992) */
Index: net/rtable.h
===================================================================
RCS file: /cvs/src/sys/net/rtable.h,v
retrieving revision 1.7
diff -u -p -r1.7 rtable.h
--- net/rtable.h 22 Oct 2015 17:19:38 -0000 1.7
+++ net/rtable.h 25 Oct 2015 14:13:46 -0000
@@ -57,7 +57,8 @@ struct rtentry *rtable_lookup(unsigned i
struct sockaddr *);
struct rtentry *rtable_match(unsigned int, struct sockaddr *);
int rtable_insert(unsigned int, struct sockaddr *,
- struct sockaddr *, uint8_t, struct rtentry *);
+ struct sockaddr *, struct sockaddr *, uint8_t,
+ struct rtentry *);
int rtable_delete(unsigned int, struct sockaddr *,
struct sockaddr *, uint8_t, struct rtentry *);
int rtable_walk(unsigned int, sa_family_t,
@@ -66,8 +67,6 @@ int rtable_walk(unsigned int, sa_famil
int rtable_mpath_capable(unsigned int, sa_family_t);
struct rtentry *rtable_mpath_match(unsigned int, struct rtentry *,
struct sockaddr *, uint8_t);
-int rtable_mpath_conflict(unsigned int, struct sockaddr *,
- struct sockaddr *, struct sockaddr *, uint8_t, int);
struct rtentry *rtable_mpath_select(struct rtentry *, uint32_t);
void rtable_mpath_reprio(struct rtentry *, uint8_t);
#endif /* _NET_RTABLE_H_ */