ipv4: Support multipath hashing on inner IP pkts for GRE tunnel
authorStephen Suryaputra <ssuryaextr@gmail.com>
Thu, 13 Jun 2019 18:38:58 +0000 (14:38 -0400)
committerDavid S. Miller <davem@davemloft.net>
Sat, 15 Jun 2019 02:42:35 +0000 (19:42 -0700)
Multipath hash policy value of 0 isn't distributing since the outer IP
dest and src aren't varied eventhough the inner ones are. Since the flow
is on the inner ones in the case of tunneled traffic, hashing on them is
desired.

This is done mainly for IP over GRE, hence only tested for that. But
anything else supported by flow dissection should work.

v2: Use skb_flow_dissect_flow_keys() directly so that other tunneling
    can be supported through flow dissection (per Nikolay Aleksandrov).
v3: Remove accidental inclusion of ports in the hash keys and clarify
    the documentation (Nikolay Alexandrov).
Signed-off-by: Stephen Suryaputra <ssuryaextr@gmail.com>
Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Documentation/networking/ip-sysctl.txt
net/ipv4/route.c
net/ipv4/sysctl_net_ipv4.c

index f4b1043e92edc78e93a64eaec467ea615ee21eab..dc473354d90b11fe9ebe0f6a40d55b5a37002ea6 100644 (file)
@@ -80,6 +80,7 @@ fib_multipath_hash_policy - INTEGER
        Possible values:
        0 - Layer 3
        1 - Layer 4
+       2 - Layer 3 or inner Layer 3 if present
 
 fib_sync_mem - UNSIGNED INTEGER
        Amount of dirty memory from fib entries that can be backlogged before
index 0700a7d598118c71c22e7c00646a5cc9d9ec8a3a..66cbe8a7a168bf8d202ced43d51bc7830390e30c 100644 (file)
@@ -1930,6 +1930,23 @@ int fib_multipath_hash(const struct net *net, const struct flowi4 *fl4,
                        hash_keys.basic.ip_proto = fl4->flowi4_proto;
                }
                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;
+               } else {
+                       /* Same as case 0 */
+                       hash_keys.addrs.v4addrs.src = fl4->saddr;
+                       hash_keys.addrs.v4addrs.dst = fl4->daddr;
+               }
+               break;
        }
        mhash = flow_hash_from_keys(&hash_keys);
 
index 90f09e47198bff9fdf2d42ff43e8dba11fb7f2df..0edfa810f9b97f74a68071419265631609094c82 100644 (file)
@@ -1008,7 +1008,7 @@ static struct ctl_table ipv4_net_table[] = {
                .mode           = 0644,
                .proc_handler   = proc_fib_multipath_hash_policy,
                .extra1         = &zero,
-               .extra2         = &one,
+               .extra2         = &two,
        },
 #endif
        {