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 over GRE over IPv4, 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 <ssuryae...@gmail.com>
---
 net/ipv4/route.c | 21 +++++++++++++++++----
 1 file 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;
                }
-- 
2.17.1

Reply via email to