]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
route: Add multipath_hash in flowi_common to make user-define hash
authorwenxu <wenxu@ucloud.cn>
Sun, 24 Feb 2019 03:36:20 +0000 (11:36 +0800)
committerDavid S. Miller <davem@davemloft.net>
Wed, 27 Feb 2019 20:50:17 +0000 (12:50 -0800)
Current fib_multipath_hash_policy can make hash based on the L3 or
L4. But it only work on the outer IP. So a specific tunnel always
has the same hash value. But a specific tunnel may contain so many
inner connections.

This patch provide a generic multipath_hash in floi_common. It can
make a user-define hash which can mix with L3 or L4 hash.

Signed-off-by: wenxu <wenxu@ucloud.cn>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
include/net/flow.h
include/net/ip_tunnels.h
net/ipv4/ip_gre.c
net/ipv4/ip_tunnel.c
net/ipv4/route.c

index ad5a9b9e1466deb3f5718970750a2a7c6290f70a..536c23c578c348d103858c8fe48fec53d22d49a2 100644 (file)
@@ -305,7 +305,7 @@ mlxsw_sp_span_gretap4_route(const struct net_device *to_dev,
 
        parms = mlxsw_sp_ipip_netdev_parms4(to_dev);
        ip_tunnel_init_flow(&fl4, parms.iph.protocol, *daddrp, *saddrp,
-                           0, 0, parms.link, tun->fwmark);
+                           0, 0, parms.link, tun->fwmark, 0);
 
        rt = ip_route_output_key(tun->net, &fl4);
        if (IS_ERR(rt))
index 93f2c9a0f0980d95db2b9b577d14233ebdd388da..a50fb77a0b27904bf09727f93a45aa1e35bb9dcf 100644 (file)
@@ -40,6 +40,7 @@ struct flowi_common {
        __u32   flowic_secid;
        kuid_t  flowic_uid;
        struct flowi_tunnel flowic_tun_key;
+       __u32           flowic_multipath_hash;
 };
 
 union flowi_uli {
@@ -78,6 +79,7 @@ struct flowi4 {
 #define flowi4_secid           __fl_common.flowic_secid
 #define flowi4_tun_key         __fl_common.flowic_tun_key
 #define flowi4_uid             __fl_common.flowic_uid
+#define flowi4_multipath_hash  __fl_common.flowic_multipath_hash
 
        /* (saddr,daddr) must be grouped, same order as in IP header */
        __be32                  saddr;
index f069f64ebf297eb8f4166a2896a4f89a6a85edbf..af645604f3289957c420ef2d9d0fdbaebc84c0f2 100644 (file)
@@ -241,7 +241,7 @@ static inline void ip_tunnel_init_flow(struct flowi4 *fl4,
                                       int proto,
                                       __be32 daddr, __be32 saddr,
                                       __be32 key, __u8 tos, int oif,
-                                      __u32 mark)
+                                      __u32 mark, __u32 tun_inner_hash)
 {
        memset(fl4, 0, sizeof(*fl4));
        fl4->flowi4_oif = oif;
@@ -251,6 +251,7 @@ static inline void ip_tunnel_init_flow(struct flowi4 *fl4,
        fl4->flowi4_proto = proto;
        fl4->fl4_gre_key = key;
        fl4->flowi4_mark = mark;
+       fl4->flowi4_multipath_hash = tun_inner_hash;
 }
 
 int ip_tunnel_init(struct net_device *dev);
index 0f4925a0d6b22243502f3a5a9a61aa9d9c5b9d35..fd219f7bd3ea2c9263ac6d21ed3a66fd6442496c 100644 (file)
@@ -578,7 +578,7 @@ static int gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
        key = &info->key;
        ip_tunnel_init_flow(&fl4, IPPROTO_GRE, key->u.ipv4.dst, key->u.ipv4.src,
                            tunnel_id_to_key32(key->tun_id), key->tos, 0,
-                           skb->mark);
+                           skb->mark, skb_get_hash(skb));
        rt = ip_route_output_key(dev_net(dev), &fl4);
        if (IS_ERR(rt))
                return PTR_ERR(rt);
index 2973067b831d58fdd6b78c18c5ab786380903a7f..2756fb725bf0e6de69063d9cad736028057cc94e 100644 (file)
@@ -310,7 +310,7 @@ static int ip_tunnel_bind_dev(struct net_device *dev)
                ip_tunnel_init_flow(&fl4, iph->protocol, iph->daddr,
                                    iph->saddr, tunnel->parms.o_key,
                                    RT_TOS(iph->tos), tunnel->parms.link,
-                                   tunnel->fwmark);
+                                   tunnel->fwmark, 0);
                rt = ip_route_output_key(tunnel->net, &fl4);
 
                if (!IS_ERR(rt)) {
@@ -584,7 +584,7 @@ void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
        }
        ip_tunnel_init_flow(&fl4, proto, key->u.ipv4.dst, key->u.ipv4.src,
                            tunnel_id_to_key32(key->tun_id), RT_TOS(tos),
-                           0, skb->mark);
+                           0, skb->mark, skb_get_hash(skb));
        if (tunnel->encap.type != TUNNEL_ENCAP_NONE)
                goto tx_error;
 
@@ -744,7 +744,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
 
        ip_tunnel_init_flow(&fl4, protocol, dst, tnl_params->saddr,
                            tunnel->parms.o_key, RT_TOS(tos), tunnel->parms.link,
-                           tunnel->fwmark);
+                           tunnel->fwmark, skb_get_hash(skb));
 
        if (ip_tunnel_encap(skb, tunnel, &protocol, &fl4) < 0)
                goto tx_error;
index ecc12a768191a7733602087cbc5d632499b1c961..7cf4c83050710514b08f393557c0bc29870dcdfe 100644 (file)
@@ -1820,6 +1820,7 @@ out:
 int fib_multipath_hash(const struct net *net, const struct flowi4 *fl4,
                       const struct sk_buff *skb, struct flow_keys *flkeys)
 {
+       u32 multipath_hash = fl4->flowi4_multipath_hash;
        struct flow_keys hash_keys;
        u32 mhash;
 
@@ -1870,6 +1871,9 @@ int fib_multipath_hash(const struct net *net, const struct flowi4 *fl4,
        }
        mhash = flow_hash_from_keys(&hash_keys);
 
+       if (multipath_hash)
+               mhash = jhash_2words(mhash, multipath_hash, 0);
+
        return mhash >> 1;
 }
 #endif /* CONFIG_IP_ROUTE_MULTIPATH */