Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

wenxu and committed by
David S. Miller
24ba1440 8f4ef499

+13 -6
+1 -1
drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
··· 305 305 306 306 parms = mlxsw_sp_ipip_netdev_parms4(to_dev); 307 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 310 rt = ip_route_output_key(tun->net, &fl4); 311 311 if (IS_ERR(rt))
+2
include/net/flow.h
··· 40 40 __u32 flowic_secid; 41 41 kuid_t flowic_uid; 42 42 struct flowi_tunnel flowic_tun_key; 43 + __u32 flowic_multipath_hash; 43 44 }; 44 45 45 46 union flowi_uli { ··· 79 78 #define flowi4_secid __fl_common.flowic_secid 80 79 #define flowi4_tun_key __fl_common.flowic_tun_key 81 80 #define flowi4_uid __fl_common.flowic_uid 81 + #define flowi4_multipath_hash __fl_common.flowic_multipath_hash 82 82 83 83 /* (saddr,daddr) must be grouped, same order as in IP header */ 84 84 __be32 saddr;
+2 -1
include/net/ip_tunnels.h
··· 241 241 int proto, 242 242 __be32 daddr, __be32 saddr, 243 243 __be32 key, __u8 tos, int oif, 244 - __u32 mark) 244 + __u32 mark, __u32 tun_inner_hash) 245 245 { 246 246 memset(fl4, 0, sizeof(*fl4)); 247 247 fl4->flowi4_oif = oif; ··· 251 251 fl4->flowi4_proto = proto; 252 252 fl4->fl4_gre_key = key; 253 253 fl4->flowi4_mark = mark; 254 + fl4->flowi4_multipath_hash = tun_inner_hash; 254 255 } 255 256 256 257 int ip_tunnel_init(struct net_device *dev);
+1 -1
net/ipv4/ip_gre.c
··· 578 578 key = &info->key; 579 579 ip_tunnel_init_flow(&fl4, IPPROTO_GRE, key->u.ipv4.dst, key->u.ipv4.src, 580 580 tunnel_id_to_key32(key->tun_id), key->tos, 0, 581 - skb->mark); 581 + skb->mark, skb_get_hash(skb)); 582 582 rt = ip_route_output_key(dev_net(dev), &fl4); 583 583 if (IS_ERR(rt)) 584 584 return PTR_ERR(rt);
+3 -3
net/ipv4/ip_tunnel.c
··· 310 310 ip_tunnel_init_flow(&fl4, iph->protocol, iph->daddr, 311 311 iph->saddr, tunnel->parms.o_key, 312 312 RT_TOS(iph->tos), tunnel->parms.link, 313 - tunnel->fwmark); 313 + tunnel->fwmark, 0); 314 314 rt = ip_route_output_key(tunnel->net, &fl4); 315 315 316 316 if (!IS_ERR(rt)) { ··· 584 584 } 585 585 ip_tunnel_init_flow(&fl4, proto, key->u.ipv4.dst, key->u.ipv4.src, 586 586 tunnel_id_to_key32(key->tun_id), RT_TOS(tos), 587 - 0, skb->mark); 587 + 0, skb->mark, skb_get_hash(skb)); 588 588 if (tunnel->encap.type != TUNNEL_ENCAP_NONE) 589 589 goto tx_error; 590 590 ··· 744 744 745 745 ip_tunnel_init_flow(&fl4, protocol, dst, tnl_params->saddr, 746 746 tunnel->parms.o_key, RT_TOS(tos), tunnel->parms.link, 747 - tunnel->fwmark); 747 + tunnel->fwmark, skb_get_hash(skb)); 748 748 749 749 if (ip_tunnel_encap(skb, tunnel, &protocol, &fl4) < 0) 750 750 goto tx_error;
+4
net/ipv4/route.c
··· 1820 1820 int fib_multipath_hash(const struct net *net, const struct flowi4 *fl4, 1821 1821 const struct sk_buff *skb, struct flow_keys *flkeys) 1822 1822 { 1823 + u32 multipath_hash = fl4->flowi4_multipath_hash; 1823 1824 struct flow_keys hash_keys; 1824 1825 u32 mhash; 1825 1826 ··· 1870 1869 break; 1871 1870 } 1872 1871 mhash = flow_hash_from_keys(&hash_keys); 1872 + 1873 + if (multipath_hash) 1874 + mhash = jhash_2words(mhash, multipath_hash, 0); 1873 1875 1874 1876 return mhash >> 1; 1875 1877 }