summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwenxu <wenxu@ucloud.cn>2019-02-23 22:36:20 -0500
committerDavid S. Miller <davem@davemloft.net>2019-02-27 15:50:17 -0500
commit24ba14406c5c8e33fcbe064f77b3ab01b84ec830 (patch)
tree88eee234f6c4e037ad2467b8c370ed1541f5e366
parent8f4ef499c6ca56325c76600777237deaeb58a69b (diff)
route: Add multipath_hash in flowi_common to make user-define hash
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>
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c2
-rw-r--r--include/net/flow.h2
-rw-r--r--include/net/ip_tunnels.h3
-rw-r--r--net/ipv4/ip_gre.c2
-rw-r--r--net/ipv4/ip_tunnel.c6
-rw-r--r--net/ipv4/route.c4
6 files changed, 13 insertions, 6 deletions
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
index ad5a9b9e1466..536c23c578c3 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
@@ -305,7 +305,7 @@ mlxsw_sp_span_gretap4_route(const struct net_device *to_dev,
305 305
306 parms = mlxsw_sp_ipip_netdev_parms4(to_dev); 306 parms = mlxsw_sp_ipip_netdev_parms4(to_dev);
307 ip_tunnel_init_flow(&fl4, parms.iph.protocol, *daddrp, *saddrp, 307 ip_tunnel_init_flow(&fl4, parms.iph.protocol, *daddrp, *saddrp,
308 0, 0, parms.link, tun->fwmark); 308 0, 0, parms.link, tun->fwmark, 0);
309 309
310 rt = ip_route_output_key(tun->net, &fl4); 310 rt = ip_route_output_key(tun->net, &fl4);
311 if (IS_ERR(rt)) 311 if (IS_ERR(rt))
diff --git a/include/net/flow.h b/include/net/flow.h
index 93f2c9a0f098..a50fb77a0b27 100644
--- a/include/net/flow.h
+++ b/include/net/flow.h
@@ -40,6 +40,7 @@ struct flowi_common {
40 __u32 flowic_secid; 40 __u32 flowic_secid;
41 kuid_t flowic_uid; 41 kuid_t flowic_uid;
42 struct flowi_tunnel flowic_tun_key; 42 struct flowi_tunnel flowic_tun_key;
43 __u32 flowic_multipath_hash;
43}; 44};
44 45
45union flowi_uli { 46union flowi_uli {
@@ -78,6 +79,7 @@ struct flowi4 {
78#define flowi4_secid __fl_common.flowic_secid 79#define flowi4_secid __fl_common.flowic_secid
79#define flowi4_tun_key __fl_common.flowic_tun_key 80#define flowi4_tun_key __fl_common.flowic_tun_key
80#define flowi4_uid __fl_common.flowic_uid 81#define flowi4_uid __fl_common.flowic_uid
82#define flowi4_multipath_hash __fl_common.flowic_multipath_hash
81 83
82 /* (saddr,daddr) must be grouped, same order as in IP header */ 84 /* (saddr,daddr) must be grouped, same order as in IP header */
83 __be32 saddr; 85 __be32 saddr;
diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
index f069f64ebf29..af645604f328 100644
--- a/include/net/ip_tunnels.h
+++ b/include/net/ip_tunnels.h
@@ -241,7 +241,7 @@ static inline void ip_tunnel_init_flow(struct flowi4 *fl4,
241 int proto, 241 int proto,
242 __be32 daddr, __be32 saddr, 242 __be32 daddr, __be32 saddr,
243 __be32 key, __u8 tos, int oif, 243 __be32 key, __u8 tos, int oif,
244 __u32 mark) 244 __u32 mark, __u32 tun_inner_hash)
245{ 245{
246 memset(fl4, 0, sizeof(*fl4)); 246 memset(fl4, 0, sizeof(*fl4));
247 fl4->flowi4_oif = oif; 247 fl4->flowi4_oif = oif;
@@ -251,6 +251,7 @@ static inline void ip_tunnel_init_flow(struct flowi4 *fl4,
251 fl4->flowi4_proto = proto; 251 fl4->flowi4_proto = proto;
252 fl4->fl4_gre_key = key; 252 fl4->fl4_gre_key = key;
253 fl4->flowi4_mark = mark; 253 fl4->flowi4_mark = mark;
254 fl4->flowi4_multipath_hash = tun_inner_hash;
254} 255}
255 256
256int ip_tunnel_init(struct net_device *dev); 257int ip_tunnel_init(struct net_device *dev);
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 0f4925a0d6b2..fd219f7bd3ea 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -578,7 +578,7 @@ static int gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
578 key = &info->key; 578 key = &info->key;
579 ip_tunnel_init_flow(&fl4, IPPROTO_GRE, key->u.ipv4.dst, key->u.ipv4.src, 579 ip_tunnel_init_flow(&fl4, IPPROTO_GRE, key->u.ipv4.dst, key->u.ipv4.src,
580 tunnel_id_to_key32(key->tun_id), key->tos, 0, 580 tunnel_id_to_key32(key->tun_id), key->tos, 0,
581 skb->mark); 581 skb->mark, skb_get_hash(skb));
582 rt = ip_route_output_key(dev_net(dev), &fl4); 582 rt = ip_route_output_key(dev_net(dev), &fl4);
583 if (IS_ERR(rt)) 583 if (IS_ERR(rt))
584 return PTR_ERR(rt); 584 return PTR_ERR(rt);
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
index 2973067b831d..2756fb725bf0 100644
--- a/net/ipv4/ip_tunnel.c
+++ b/net/ipv4/ip_tunnel.c
@@ -310,7 +310,7 @@ static int ip_tunnel_bind_dev(struct net_device *dev)
310 ip_tunnel_init_flow(&fl4, iph->protocol, iph->daddr, 310 ip_tunnel_init_flow(&fl4, iph->protocol, iph->daddr,
311 iph->saddr, tunnel->parms.o_key, 311 iph->saddr, tunnel->parms.o_key,
312 RT_TOS(iph->tos), tunnel->parms.link, 312 RT_TOS(iph->tos), tunnel->parms.link,
313 tunnel->fwmark); 313 tunnel->fwmark, 0);
314 rt = ip_route_output_key(tunnel->net, &fl4); 314 rt = ip_route_output_key(tunnel->net, &fl4);
315 315
316 if (!IS_ERR(rt)) { 316 if (!IS_ERR(rt)) {
@@ -584,7 +584,7 @@ void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
584 } 584 }
585 ip_tunnel_init_flow(&fl4, proto, key->u.ipv4.dst, key->u.ipv4.src, 585 ip_tunnel_init_flow(&fl4, proto, key->u.ipv4.dst, key->u.ipv4.src,
586 tunnel_id_to_key32(key->tun_id), RT_TOS(tos), 586 tunnel_id_to_key32(key->tun_id), RT_TOS(tos),
587 0, skb->mark); 587 0, skb->mark, skb_get_hash(skb));
588 if (tunnel->encap.type != TUNNEL_ENCAP_NONE) 588 if (tunnel->encap.type != TUNNEL_ENCAP_NONE)
589 goto tx_error; 589 goto tx_error;
590 590
@@ -744,7 +744,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
744 744
745 ip_tunnel_init_flow(&fl4, protocol, dst, tnl_params->saddr, 745 ip_tunnel_init_flow(&fl4, protocol, dst, tnl_params->saddr,
746 tunnel->parms.o_key, RT_TOS(tos), tunnel->parms.link, 746 tunnel->parms.o_key, RT_TOS(tos), tunnel->parms.link,
747 tunnel->fwmark); 747 tunnel->fwmark, skb_get_hash(skb));
748 748
749 if (ip_tunnel_encap(skb, tunnel, &protocol, &fl4) < 0) 749 if (ip_tunnel_encap(skb, tunnel, &protocol, &fl4) < 0)
750 goto tx_error; 750 goto tx_error;
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index ecc12a768191..7cf4c8305071 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1820,6 +1820,7 @@ out:
1820int fib_multipath_hash(const struct net *net, const struct flowi4 *fl4, 1820int fib_multipath_hash(const struct net *net, const struct flowi4 *fl4,
1821 const struct sk_buff *skb, struct flow_keys *flkeys) 1821 const struct sk_buff *skb, struct flow_keys *flkeys)
1822{ 1822{
1823 u32 multipath_hash = fl4->flowi4_multipath_hash;
1823 struct flow_keys hash_keys; 1824 struct flow_keys hash_keys;
1824 u32 mhash; 1825 u32 mhash;
1825 1826
@@ -1870,6 +1871,9 @@ int fib_multipath_hash(const struct net *net, const struct flowi4 *fl4,
1870 } 1871 }
1871 mhash = flow_hash_from_keys(&hash_keys); 1872 mhash = flow_hash_from_keys(&hash_keys);
1872 1873
1874 if (multipath_hash)
1875 mhash = jhash_2words(mhash, multipath_hash, 0);
1876
1873 return mhash >> 1; 1877 return mhash >> 1;
1874} 1878}
1875#endif /* CONFIG_IP_ROUTE_MULTIPATH */ 1879#endif /* CONFIG_IP_ROUTE_MULTIPATH */