Created
April 10, 2016 11:04
-
-
Save neutronth/45c210cc3a44600692d67b51e3dd7bf0 to your computer and use it in GitHub Desktop.
Linux 4.4 multipath routing with src_ip, dst_ip, src_port, dst_port hash flow-based
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- include/net/ip_fib.h.orig 2016-04-10 11:44:40.342768815 +0700 | |
+++ include/net/ip_fib.h 2016-04-10 15:28:42.217868332 +0700 | |
@@ -331,6 +331,12 @@ | |
return jhash_2words(saddr, daddr, fib_multipath_secret) >> 1; | |
} | |
+static inline int fib_multipath_hash_ip_port(__be32 saddr, __be32 daddr, | |
+ __be32 ports) | |
+{ | |
+ return jhash_3words(saddr, daddr, ports, fib_multipath_secret) >> 1; | |
+} | |
+ | |
void fib_select_multipath(struct fib_result *res, int hash); | |
void fib_select_path(struct net *net, struct fib_result *res, | |
struct flowi4 *fl4, int mp_hash); | |
--- net/ipv4/route.c.orig 2016-04-10 11:53:31.219926652 +0700 | |
+++ net/ipv4/route.c 2016-04-10 15:33:28.934174428 +0700 | |
@@ -113,6 +113,9 @@ | |
#include <net/secure_seq.h> | |
#include <net/ip_tunnels.h> | |
#include <net/l3mdev.h> | |
+#ifdef CONFIG_IP_ROUTE_MULTIPATH | |
+#include <linux/sctp.h> | |
+#endif | |
#define RT_FL_TOS(oldflp4) \ | |
((oldflp4)->flowi4_tos & (IPTOS_RT_MASK | RTO_ONLINK)) | |
@@ -1745,8 +1748,59 @@ | |
if (unlikely(ip_hdr(skb)->protocol == IPPROTO_ICMP)) | |
h = ip_multipath_icmp_hash(skb); | |
- else | |
- h = fib_multipath_hash(saddr, daddr); | |
+ else { | |
+ const struct iphdr *iph = ip_hdr(skb); | |
+ unsigned int protooff = skb_network_offset(skb) + ip_hdrlen(skb); | |
+ int protocol = iph->protocol; | |
+ __be32 ports = 0; | |
+ __be16 *p_port = &ports; | |
+ | |
+ if (protocol > 0 && !(ntohs(iph->frag_off) & IP_OFFSET)) { | |
+ switch (protocol) { | |
+ case IPPROTO_TCP: { | |
+ struct tcphdr _tcph; | |
+ const struct tcphdr *th; | |
+ | |
+ th = skb_header_pointer(skb, protooff, sizeof(_tcph), &_tcph); | |
+ if (!th) | |
+ break; | |
+ | |
+ *p_port = th->source; | |
+ *(p_port + 1) = th->dest; | |
+ break; | |
+ } | |
+ case IPPROTO_SCTP: { | |
+ sctp_sctphdr_t _sh; | |
+ const sctp_sctphdr_t *sh; | |
+ | |
+ sh = skb_header_pointer(skb, protooff, sizeof(_sh), &_sh); | |
+ if (!sh) | |
+ break; | |
+ | |
+ *p_port = sh->source; | |
+ *(p_port + 1) = sh->dest; | |
+ break; | |
+ } | |
+ case IPPROTO_UDP: | |
+ case IPPROTO_UDPLITE: { | |
+ struct udphdr _udph; | |
+ const struct udphdr *uh; | |
+ | |
+ uh = skb_header_pointer(skb, protooff, sizeof(_udph), &_udph); | |
+ if (!uh) | |
+ break; | |
+ | |
+ *p_port = uh->source; | |
+ *(p_port + 1) = uh->dest; | |
+ break; | |
+ } | |
+ default: | |
+ break; | |
+ } | |
+ } | |
+ | |
+ h = fib_multipath_hash_ip_port(saddr, daddr, ports); | |
+ } | |
fib_select_multipath(res, h); | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment