Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F147666052
D26523.1784020536.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
16 KB
Referenced Files
None
Subscribers
None
D26523.1784020536.diff
View Options
Index: sys/conf/files
===================================================================
--- sys/conf/files
+++ sys/conf/files
@@ -4161,7 +4161,7 @@
net/rtsock.c standard
net/slcompress.c optional netgraph_vjc | sppp | \
netgraph_sppp
-net/toeplitz.c optional inet rss | inet6 rss
+net/toeplitz.c optional inet rss | inet6 rss | route_mpath
net/vnet.c optional vimage
net80211/ieee80211.c optional wlan
net80211/ieee80211_acl.c optional wlan wlan_acl
Index: sys/net/radix.c
===================================================================
--- sys/net/radix.c
+++ sys/net/radix.c
@@ -624,21 +624,6 @@
saved_tt = tt = rn_insert(v, head, &keyduplicated, treenodes);
if (keyduplicated) {
for (t = tt; tt; t = tt, tt = tt->rn_dupedkey) {
-#ifdef RADIX_MPATH
- /* permit multipath, if enabled for the family */
- if (rn_mpath_capable(head) && netmask == tt->rn_mask) {
- /*
- * go down to the end of multipaths, so that
- * new entry goes into the end of rn_dupedkey
- * chain.
- */
- do {
- t = tt;
- tt = tt->rn_dupedkey;
- } while (tt && t->rn_mask == tt->rn_mask);
- break;
- }
-#endif
if (tt->rn_mask == netmask)
return (0);
if (netmask == 0 ||
@@ -744,10 +729,8 @@
if (m->rm_flags & RNF_NORMAL) {
mmask = m->rm_leaf->rn_mask;
if (tt->rn_flags & RNF_NORMAL) {
-#if !defined(RADIX_MPATH)
log(LOG_ERR,
"Non-unique normal route, mask not entered\n");
-#endif
return (tt);
}
} else
Index: sys/net/route.h
===================================================================
--- sys/net/route.h
+++ sys/net/route.h
@@ -125,6 +125,10 @@
#define rt_numfibs V_rt_numfibs
VNET_DECLARE(u_int, rt_add_addr_allfibs); /* Announce interfaces to all fibs */
#define V_rt_add_addr_allfibs VNET(rt_add_addr_allfibs)
+
+/* Calculate flowid for locally-originated packets */
+#define V_fib_hash_outbound VNET(fib_hash_outbound)
+VNET_DECLARE(u_int, fib_hash_outbound);
#endif
/*
Index: sys/net/route/mpath_ctl.c
===================================================================
--- sys/net/route/mpath_ctl.c
+++ sys/net/route/mpath_ctl.c
@@ -64,7 +64,21 @@
*/
SYSCTL_DECL(_net_route);
+VNET_DEFINE(u_int, fib_hash_outbound) = 0;
+SYSCTL_UINT(_net_route, OID_AUTO, hash_outbound, CTLFLAG_RD | CTLFLAG_VNET,
+ &VNET_NAME(fib_hash_outbound), 0,
+ "Compute flowid for locally-originated packets");
+/* Default entropy to add to the hash calculation for the outbound connections*/
+uint8_t mpath_entropy_key[MPATH_ENTROPY_KEY_LEN] = {
+ 0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
+ 0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
+ 0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
+ 0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
+ 0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa,
+};
+
+
/*
* Tries to add @rnd_add nhop to the existing set of nhops (@nh_orig) for the
* prefix specified by @rt.
@@ -113,6 +127,17 @@
if (error != EAGAIN)
break;
RTSTAT_INC(rts_add_retry);
+ }
+
+ if (V_fib_hash_outbound == 0 && error == 0 &&
+ NH_IS_NHGRP(rc->rc_nh_new)) {
+ /*
+ * First multipath route got installed. Enable local
+ * outbound connections hashing.
+ */
+ if (bootverbose)
+ printf("FIB: enabled flowid calculation for locally-originated packets\n");
+ V_fib_hash_outbound = 1;
}
return (error);
Index: sys/net/route/route_var.h
===================================================================
--- sys/net/route/route_var.h
+++ sys/net/route/route_var.h
@@ -307,4 +307,8 @@
void nhgrp_free(struct nhgrp_object *nhg);
+/* Entropy data used for outbound hashing */
+#define MPATH_ENTROPY_KEY_LEN 40
+extern uint8_t mpath_entropy_key[MPATH_ENTROPY_KEY_LEN];
+
#endif
Index: sys/netinet/in_fib.h
===================================================================
--- sys/netinet/in_fib.h
+++ sys/netinet/in_fib.h
@@ -51,4 +51,7 @@
uint32_t flags, const struct ifnet *src_if);
struct nhop_object *fib4_lookup_debugnet(uint32_t fibnum, struct in_addr dst,
uint32_t scopeid, uint32_t flags);
+uint32_t fib4_calc_software_hash(struct in_addr src, struct in_addr dst,
+ unsigned short src_port, unsigned short dst_port, char proto,
+ uint32_t *phashtype);
#endif
Index: sys/netinet/in_fib.c
===================================================================
--- sys/netinet/in_fib.c
+++ sys/netinet/in_fib.c
@@ -50,6 +50,7 @@
#include <net/route/route_ctl.h>
#include <net/route/route_var.h>
#include <net/route/nhop.h>
+#include <net/toeplitz.h>
#include <net/vnet.h>
#include <netinet/in.h>
@@ -61,6 +62,40 @@
/* Verify struct route compatiblity */
/* Assert 'struct route_in' is compatible with 'struct route' */
CHK_STRUCT_ROUTE_COMPAT(struct route_in, ro_dst4);
+
+#ifdef ROUTE_MPATH
+struct _hash_5tuple_ipv4 {
+ struct in_addr src;
+ struct in_addr dst;
+ unsigned short src_port;
+ unsigned short dst_port;
+ char proto;
+ char spare[3];
+};
+_Static_assert(sizeof(struct _hash_5tuple_ipv4) == 16,
+ "_hash_5tuple_ipv4 size is wrong");
+
+
+uint32_t
+fib4_calc_software_hash(struct in_addr src, struct in_addr dst,
+ unsigned short src_port, unsigned short dst_port, char proto,
+ uint32_t *phashtype)
+{
+ struct _hash_5tuple_ipv4 data;
+
+ data.src = src;
+ data.dst = dst;
+ data.src_port = src_port;
+ data.dst_port = dst_port;
+ data.proto = proto;
+ data.spare[0] = data.spare[1] = data.spare[2] = 0;
+
+ *phashtype = M_HASHTYPE_OPAQUE;
+
+ return (toeplitz_hash(MPATH_ENTROPY_KEY_LEN, mpath_entropy_key,
+ sizeof(data), (uint8_t *)&data));
+}
+#endif
/*
* Looks up path in fib @fibnum specified by @dst.
Index: sys/netinet/in_pcb.c
===================================================================
--- sys/netinet/in_pcb.c
+++ sys/netinet/in_pcb.c
@@ -46,6 +46,7 @@
#include "opt_inet6.h"
#include "opt_ratelimit.h"
#include "opt_pcbgroup.h"
+#include "opt_route.h"
#include "opt_rss.h"
#include <sys/param.h>
@@ -1327,7 +1328,17 @@
lport = *lportp;
faddr = sin->sin_addr;
fport = sin->sin_port;
+#ifdef ROUTE_MPATH
+ if (V_fib_hash_outbound) {
+ uint32_t hash_val, hash_type;
+ hash_val = fib4_calc_software_hash(laddr, faddr, 0, fport,
+ inp->inp_socket->so_proto->pr_protocol, &hash_type);
+
+ inp->inp_flowid = hash_val;
+ inp->inp_flowtype = hash_type;
+ }
+#endif
if (!CK_STAILQ_EMPTY(&V_in_ifaddrhead)) {
/*
* If the destination address is INADDR_ANY,
Index: sys/netinet/raw_ip.c
===================================================================
--- sys/netinet/raw_ip.c
+++ sys/netinet/raw_ip.c
@@ -38,6 +38,7 @@
#include "opt_inet.h"
#include "opt_inet6.h"
#include "opt_ipsec.h"
+#include "opt_route.h"
#include <sys/param.h>
#include <sys/jail.h>
@@ -67,6 +68,7 @@
#include <netinet/in.h>
#include <netinet/in_systm.h>
+#include <netinet/in_fib.h>
#include <netinet/in_pcb.h>
#include <netinet/in_var.h>
#include <netinet/if_ether.h>
@@ -484,6 +486,17 @@
ip->ip_len = htons(m->m_pkthdr.len);
ip->ip_src = inp->inp_laddr;
ip->ip_dst.s_addr = dst;
+#ifdef ROUTE_MPATH
+ if (V_fib_hash_outbound) {
+ uint32_t hash_type, hash_val;
+
+ hash_val = fib4_calc_software_hash(ip->ip_src,
+ ip->ip_dst, 0, 0, ip->ip_p, &hash_type);
+ m->m_pkthdr.flowid = hash_val;
+ M_HASHTYPE_SET(m, hash_type);
+ flags |= IP_NODEFAULTFLOWID;
+ }
+#endif
if (jailed(inp->inp_cred)) {
/*
* prison_local_ip4() would be good enough but would
@@ -519,7 +532,17 @@
return (EINVAL);
ip = mtod(m, struct ip *);
}
+#ifdef ROUTE_MPATH
+ if (V_fib_hash_outbound) {
+ uint32_t hash_type, hash_val;
+ hash_val = fib4_calc_software_hash(ip->ip_dst,
+ ip->ip_src, 0, 0, ip->ip_p, &hash_type);
+ m->m_pkthdr.flowid = hash_val;
+ M_HASHTYPE_SET(m, hash_type);
+ flags |= IP_NODEFAULTFLOWID;
+ }
+#endif
INP_RLOCK(inp);
/*
* Don't allow both user specified and setsockopt options,
Index: sys/netinet/udp_usrreq.c
===================================================================
--- sys/netinet/udp_usrreq.c
+++ sys/netinet/udp_usrreq.c
@@ -1473,6 +1473,16 @@
((struct ip *)ui)->ip_tos = tos; /* XXX */
UDPSTAT_INC(udps_opackets);
+#ifdef ROUTE_MPATH
+ if (V_fib_hash_outbound) {
+ uint32_t hash_type;
+
+ flowid = fib4_calc_software_hash(laddr, faddr,
+ lport, fport, &hash_type);
+ m->m_pkthdr.flowid = hash_val;
+ M_HASHTYPE_SET(m, hash_type);
+ }
+#endif
/*
* Setup flowid / RSS information for outbound socket.
*
Index: sys/netinet6/in6_fib.h
===================================================================
--- sys/netinet6/in6_fib.h
+++ sys/netinet6/in6_fib.h
@@ -39,4 +39,7 @@
uint32_t scopeid, uint32_t flags, const struct ifnet *src_if);
struct nhop_object *fib6_lookup_debugnet(uint32_t fibnum,
const struct in6_addr *dst6, uint32_t scopeid, uint32_t flags);
+uint32_t fib6_calc_software_hash(const struct in6_addr *src,
+ const struct in6_addr *dst, unsigned short src_port, unsigned short dst_port,
+ char proto, uint32_t *phashtype);
#endif
Index: sys/netinet6/in6_fib.c
===================================================================
--- sys/netinet6/in6_fib.c
+++ sys/netinet6/in6_fib.c
@@ -51,6 +51,7 @@
#include <net/route/route_ctl.h>
#include <net/route/route_var.h>
#include <net/route/nhop.h>
+#include <net/toeplitz.h>
#include <net/vnet.h>
#include <netinet/in.h>
@@ -67,6 +68,39 @@
#ifdef INET6
CHK_STRUCT_ROUTE_COMPAT(struct route_in6, ro_dst);
+
+#ifdef ROUTE_MPATH
+struct _hash_5tuple_ipv6 {
+ struct in6_addr src;
+ struct in6_addr dst;
+ unsigned short src_port;
+ unsigned short dst_port;
+ char proto;
+ char spare[3];
+};
+_Static_assert(sizeof(struct _hash_5tuple_ipv6) == 40,
+ "_hash_5tuple_ipv6 size is wrong");
+
+uint32_t
+fib6_calc_software_hash(const struct in6_addr *src, const struct in6_addr *dst,
+ unsigned short src_port, unsigned short dst_port, char proto,
+ uint32_t *phashtype)
+{
+ struct _hash_5tuple_ipv6 data;
+
+ data.src = *src;
+ data.dst = *dst;
+ data.src_port = src_port;
+ data.dst_port = dst_port;
+ data.proto = proto;
+ data.spare[0] = data.spare[1] = data.spare[2] = 0;
+
+ *phashtype = M_HASHTYPE_OPAQUE_HASH;
+
+ return (toeplitz_hash(MPATH_ENTROPY_KEY_LEN, mpath_entropy_key,
+ sizeof(data), (uint8_t *)&data));
+}
+#endif
/*
* Looks up path in fib @fibnum specified by @dst.
Index: sys/netinet6/in6_pcb.c
===================================================================
--- sys/netinet6/in6_pcb.c
+++ sys/netinet6/in6_pcb.c
@@ -73,6 +73,7 @@
#include "opt_inet6.h"
#include "opt_ipsec.h"
#include "opt_pcbgroup.h"
+#include "opt_route.h"
#include "opt_rss.h"
#include <sys/param.h>
@@ -423,6 +424,17 @@
INP_WLOCK_ASSERT(inp);
INP_HASH_WLOCK_ASSERT(pcbinfo);
+#ifdef ROUTE_MPATH
+ if (V_fib_hash_outbound) {
+ uint32_t hash_type, hash_val;
+
+ hash_val = fib6_calc_software_hash(&inp->in6p_laddr,
+ &sin6->sin6_addr, 0, sin6->sin6_port,
+ inp->inp_socket->so_proto->pr_protocol, &hash_type);
+ inp->inp_flowid = hash_val;
+ inp->inp_flowtype = hash_type;
+ }
+#endif
/*
* Call inner routine, to assign local interface address.
* in6_pcbladdr() may automatically fill in sin6_scope_id.
Index: sys/netinet6/ip6_output.c
===================================================================
--- sys/netinet6/ip6_output.c
+++ sys/netinet6/ip6_output.c
@@ -417,9 +417,6 @@
*
* ifpp - XXX: just for statistics
*/
-/*
- * XXX TODO: no flowid is assigned for outbound flows?
- */
int
ip6_output(struct mbuf *m0, struct ip6_pktopts *opt,
struct route_in6 *ro, int flags, struct ip6_moptions *im6o,
@@ -769,7 +766,8 @@
}
}
- nh = fib6_lookup(fibnum, &kdst, scopeid, NHR_NONE, 0);
+ nh = fib6_lookup(fibnum, &kdst, scopeid, NHR_NONE,
+ m->m_pkthdr.flowid);
if (nh == NULL) {
IP6STAT_INC(ip6s_noroute);
/* No ifp in6_ifstat_inc(ifp, ifs6_out_discard); */
Index: sys/netinet6/raw_ip6.c
===================================================================
--- sys/netinet6/raw_ip6.c
+++ sys/netinet6/raw_ip6.c
@@ -66,6 +66,7 @@
#include "opt_ipsec.h"
#include "opt_inet6.h"
+#include "opt_route.h"
#include <sys/param.h>
#include <sys/errno.h>
@@ -103,6 +104,7 @@
#include <netinet6/ip6_var.h>
#include <netinet6/nd6.h>
#include <netinet6/raw_ip6.h>
+#include <netinet6/in6_fib.h>
#include <netinet6/scope6_var.h>
#include <netinet6/send.h>
@@ -462,6 +464,17 @@
}
ip6 = mtod(m, struct ip6_hdr *);
+#ifdef ROUTE_MPATH
+ if (V_fib_hash_outbound) {
+ uint32_t hash_type, hash_val;
+
+ hash_val = fib6_calc_software_hash(&inp->in6p_laddr,
+ &dstsock->sin6_addr, 0, 0, so->so_proto->pr_protocol,
+ &hash_type);
+ inp->inp_flowid = hash_val;
+ inp->inp_flowtype = hash_type;
+ }
+#endif
/*
* Source address selection.
*/
Index: sys/netinet6/udp6_usrreq.c
===================================================================
--- sys/netinet6/udp6_usrreq.c
+++ sys/netinet6/udp6_usrreq.c
@@ -954,6 +954,16 @@
}
flags = 0;
+#ifdef ROUTE_MPATH
+ if (V_fib_hash_outbound) {
+ uint32_t hash_type, hash_val;
+
+ hash_val = fib6_calc_software_hash(laddr, faddr, lport,
+ inp->inp_lport, &hash_type);
+ m->m_pkthdr.flowid = hash_val;
+ M_HASHTYPE_SET(m, hash_type);
+ }
+#endif
#ifdef RSS
{
uint32_t hash_val, hash_type;
Index: tests/sys/netinet/output.sh
===================================================================
--- tests/sys/netinet/output.sh
+++ tests/sys/netinet/output.sh
@@ -223,11 +223,19 @@
mpath_check()
{
- if [ "`sysctl -i -n net.route.multipath`" != 1 ]; then
+ if [ `sysctl -iW net.route.multipath | wc -l` != "1" ]; then
atf_skip "This test requires ROUTE_MPATH enabled"
fi
}
+mpath_enable()
+{
+ jexec $1 sysctl net.route.multipath=1
+ if [ $? != 0 ]; then
+ atf_fail "Setting multipath in jail $1 failed".
+ fi
+}
+
atf_test_case "output_tcp_flowid_mpath_success" "cleanup"
output_tcp_flowid_mpath_success_head()
{
@@ -258,6 +266,7 @@
lo_dst=$(vnet_mkloopback)
vnet_mkjail ${jname}a ${epair0}a ${epair1}a ${lo_src}
+ mpath_enable ${jname}a
# Setup transit IPv4 networks
jexec ${jname}a ifconfig ${epair0}a up
jexec ${jname}a ifconfig ${epair0}a inet 203.0.113.1/30
@@ -386,6 +395,7 @@
lo_dst=$(vnet_mkloopback)
vnet_mkjail ${jname}a ${epair0}a ${epair1}a ${lo_src}
+ mpath_enable ${jname}a
# Setup transit IPv4 networks
jexec ${jname}a ifconfig ${epair0}a up
jexec ${jname}a ifconfig ${epair0}a inet 203.0.113.1/30
@@ -509,6 +519,7 @@
lo_dst=$(vnet_mkloopback)
vnet_mkjail ${jname}a ${epair0}a ${epair1}a ${lo_src}
+ mpath_enable ${jname}a
# Setup transit IPv4 networks
jexec ${jname}a ifconfig ${epair0}a up
jexec ${jname}a ifconfig ${epair0}a inet 203.0.113.1/30
Index: tests/sys/netinet6/output6.sh
===================================================================
--- tests/sys/netinet6/output6.sh
+++ tests/sys/netinet6/output6.sh
@@ -247,11 +247,20 @@
mpath_check()
{
- if [ "`sysctl -i -n net.route.multipath`" != 1 ]; then
+ if [ `sysctl -iW net.route.multipath | wc -l` != "1" ]; then
atf_skip "This test requires ROUTE_MPATH enabled"
fi
}
+mpath_enable()
+{
+ jexec $1 sysctl net.route.multipath=1
+ if [ $? != 0 ]; then
+ atf_fail "Setting multipath in jail $1 failed".
+ fi
+}
+
+
atf_test_case "output6_tcp_flowid_mpath_success" "cleanup"
output6_tcp_flowid_mpath_success_head()
{
@@ -282,6 +291,7 @@
lo_dst=$(vnet_mkloopback)
vnet_mkjail ${jname}a ${epair0}a ${epair1}a ${lo_src}
+ mpath_enable ${jname}a
jls -N
# enable link-local IPv6
jexec ${jname}a ndp -i ${epair0}a -- -disabled
@@ -422,6 +432,7 @@
lo_dst=$(vnet_mkloopback)
vnet_mkjail ${jname}a ${epair0}a ${epair1}a ${lo_src}
+ mpath_enable ${jname}a
jls -N
# enable link-local IPv6
jexec ${jname}a ndp -i ${epair0}a -- -disabled
@@ -559,6 +570,7 @@
lo_dst=$(vnet_mkloopback)
vnet_mkjail ${jname}a ${epair0}a ${epair1}a ${lo_src}
+ mpath_enable ${jname}a
jls -N
# enable link-local IPv6
jexec ${jname}a ndp -i ${epair0}a -- -disabled
@@ -603,6 +615,9 @@
# A -> towards B via epair1a LL
ll=`jexec ${jname}b ifconfig ${epair1}b inet6 | awk '$2~/^fe80:/{print$2}' | awk -F% '{print$1}'`
jexec ${jname}a route add -6 -net ${net_dst}::/${plen} ${ll}%${epair1}a
+
+ jexec ${jname}a netstat -6rnW
+ jexec ${jname}a netstat -6OnW
# B towards A via epair0b LL
ll=`jexec ${jname}a ifconfig ${epair1}a inet6 | awk '$2~/^fe80:/{print$2}' | awk -F% '{print$1}'`
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Jul 14, 9:15 AM (2 h, 26 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29126977
Default Alt Text
D26523.1784020536.diff (16 KB)
Attached To
Mode
D26523: Enable multipath for outbound connections
Attached
Detach File
Event Timeline
Log In to Comment