diff options
author | Stephen Suryaputra <ssuryaextr@gmail.com> | 2019-07-06 10:55:17 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-07-08 16:37:29 -0700 |
commit | 828b2b442145cbe94fe3ca0e34a47f64b0f322ef (patch) | |
tree | 6682d5ea1e89a729bac348df03092808555f827a /net/ipv4/route.c | |
parent | faf5577f2498cea23011b5c785ef853ded22700b (diff) | |
download | linux-stable-828b2b442145cbe94fe3ca0e34a47f64b0f322ef.tar.gz linux-stable-828b2b442145cbe94fe3ca0e34a47f64b0f322ef.tar.bz2 linux-stable-828b2b442145cbe94fe3ca0e34a47f64b0f322ef.zip |
ipv4: Multipath hashing on inner L3 needs to consider inner IPv6 pkts
Commit 363887a2cdfe ("ipv4: Support multipath hashing on inner IP pkts
for GRE tunnel") supports multipath policy value of 2, Layer 3 or inner
Layer 3 if present, but it only considers inner IPv4. There is a use
case of IPv6 is tunneled by IPv4 GRE, thus add the ability to hash on
inner IPv6 addresses.
Fixes: 363887a2cdfe ("ipv4: Support multipath hashing on inner IP pkts for GRE tunnel")
Signed-off-by: Stephen Suryaputra <ssuryaextr@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/route.c')
-rw-r--r-- | net/ipv4/route.c | 21 |
1 files changed, 17 insertions, 4 deletions
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index dc1f510a7c81..abaa7f9371e5 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1964,17 +1964,30 @@ int fib_multipath_hash(const struct net *net, const struct flowi4 *fl4, break; case 2: memset(&hash_keys, 0, sizeof(hash_keys)); - hash_keys.control.addr_type = FLOW_DISSECTOR_KEY_IPV4_ADDRS; /* skb is currently provided only when forwarding */ if (skb) { struct flow_keys keys; skb_flow_dissect_flow_keys(skb, &keys, 0); - - hash_keys.addrs.v4addrs.src = keys.addrs.v4addrs.src; - hash_keys.addrs.v4addrs.dst = keys.addrs.v4addrs.dst; + /* Inner can be v4 or v6 */ + if (keys.control.addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) { + hash_keys.control.addr_type = FLOW_DISSECTOR_KEY_IPV4_ADDRS; + hash_keys.addrs.v4addrs.src = keys.addrs.v4addrs.src; + hash_keys.addrs.v4addrs.dst = keys.addrs.v4addrs.dst; + } else if (keys.control.addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) { + hash_keys.control.addr_type = FLOW_DISSECTOR_KEY_IPV6_ADDRS; + hash_keys.addrs.v6addrs.src = keys.addrs.v6addrs.src; + hash_keys.addrs.v6addrs.dst = keys.addrs.v6addrs.dst; + hash_keys.tags.flow_label = keys.tags.flow_label; + hash_keys.basic.ip_proto = keys.basic.ip_proto; + } else { + /* Same as case 0 */ + hash_keys.control.addr_type = FLOW_DISSECTOR_KEY_IPV4_ADDRS; + ip_multipath_l3_keys(skb, &hash_keys); + } } else { /* Same as case 0 */ + hash_keys.control.addr_type = FLOW_DISSECTOR_KEY_IPV4_ADDRS; hash_keys.addrs.v4addrs.src = fl4->saddr; hash_keys.addrs.v4addrs.dst = fl4->daddr; } |