forked from mirrors/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>
This commit is contained in:
		
							parent
							
								
									8f4ef499c6
								
							
						
					
					
						commit
						24ba14406c
					
				
					 6 changed files with 13 additions and 6 deletions
				
			
		|  | @ -305,7 +305,7 @@ mlxsw_sp_span_gretap4_route(const struct net_device *to_dev, | ||||||
| 
 | 
 | ||||||
| 	parms = mlxsw_sp_ipip_netdev_parms4(to_dev); | 	parms = mlxsw_sp_ipip_netdev_parms4(to_dev); | ||||||
| 	ip_tunnel_init_flow(&fl4, parms.iph.protocol, *daddrp, *saddrp, | 	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); | 	rt = ip_route_output_key(tun->net, &fl4); | ||||||
| 	if (IS_ERR(rt)) | 	if (IS_ERR(rt)) | ||||||
|  |  | ||||||
|  | @ -40,6 +40,7 @@ struct flowi_common { | ||||||
| 	__u32	flowic_secid; | 	__u32	flowic_secid; | ||||||
| 	kuid_t  flowic_uid; | 	kuid_t  flowic_uid; | ||||||
| 	struct flowi_tunnel flowic_tun_key; | 	struct flowi_tunnel flowic_tun_key; | ||||||
|  | 	__u32		flowic_multipath_hash; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| union flowi_uli { | union flowi_uli { | ||||||
|  | @ -78,6 +79,7 @@ struct flowi4 { | ||||||
| #define flowi4_secid		__fl_common.flowic_secid | #define flowi4_secid		__fl_common.flowic_secid | ||||||
| #define flowi4_tun_key		__fl_common.flowic_tun_key | #define flowi4_tun_key		__fl_common.flowic_tun_key | ||||||
| #define flowi4_uid		__fl_common.flowic_uid | #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 */ | 	/* (saddr,daddr) must be grouped, same order as in IP header */ | ||||||
| 	__be32			saddr; | 	__be32			saddr; | ||||||
|  |  | ||||||
|  | @ -241,7 +241,7 @@ static inline void ip_tunnel_init_flow(struct flowi4 *fl4, | ||||||
| 				       int proto, | 				       int proto, | ||||||
| 				       __be32 daddr, __be32 saddr, | 				       __be32 daddr, __be32 saddr, | ||||||
| 				       __be32 key, __u8 tos, int oif, | 				       __be32 key, __u8 tos, int oif, | ||||||
| 				       __u32 mark) | 				       __u32 mark, __u32 tun_inner_hash) | ||||||
| { | { | ||||||
| 	memset(fl4, 0, sizeof(*fl4)); | 	memset(fl4, 0, sizeof(*fl4)); | ||||||
| 	fl4->flowi4_oif = oif; | 	fl4->flowi4_oif = oif; | ||||||
|  | @ -251,6 +251,7 @@ static inline void ip_tunnel_init_flow(struct flowi4 *fl4, | ||||||
| 	fl4->flowi4_proto = proto; | 	fl4->flowi4_proto = proto; | ||||||
| 	fl4->fl4_gre_key = key; | 	fl4->fl4_gre_key = key; | ||||||
| 	fl4->flowi4_mark = mark; | 	fl4->flowi4_mark = mark; | ||||||
|  | 	fl4->flowi4_multipath_hash = tun_inner_hash; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int ip_tunnel_init(struct net_device *dev); | int ip_tunnel_init(struct net_device *dev); | ||||||
|  |  | ||||||
|  | @ -578,7 +578,7 @@ static int gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) | ||||||
| 	key = &info->key; | 	key = &info->key; | ||||||
| 	ip_tunnel_init_flow(&fl4, IPPROTO_GRE, key->u.ipv4.dst, key->u.ipv4.src, | 	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, | 			    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); | 	rt = ip_route_output_key(dev_net(dev), &fl4); | ||||||
| 	if (IS_ERR(rt)) | 	if (IS_ERR(rt)) | ||||||
| 		return PTR_ERR(rt); | 		return PTR_ERR(rt); | ||||||
|  |  | ||||||
|  | @ -310,7 +310,7 @@ static int ip_tunnel_bind_dev(struct net_device *dev) | ||||||
| 		ip_tunnel_init_flow(&fl4, iph->protocol, iph->daddr, | 		ip_tunnel_init_flow(&fl4, iph->protocol, iph->daddr, | ||||||
| 				    iph->saddr, tunnel->parms.o_key, | 				    iph->saddr, tunnel->parms.o_key, | ||||||
| 				    RT_TOS(iph->tos), tunnel->parms.link, | 				    RT_TOS(iph->tos), tunnel->parms.link, | ||||||
| 				    tunnel->fwmark); | 				    tunnel->fwmark, 0); | ||||||
| 		rt = ip_route_output_key(tunnel->net, &fl4); | 		rt = ip_route_output_key(tunnel->net, &fl4); | ||||||
| 
 | 
 | ||||||
| 		if (!IS_ERR(rt)) { | 		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, | 	ip_tunnel_init_flow(&fl4, proto, key->u.ipv4.dst, key->u.ipv4.src, | ||||||
| 			    tunnel_id_to_key32(key->tun_id), RT_TOS(tos), | 			    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) | 	if (tunnel->encap.type != TUNNEL_ENCAP_NONE) | ||||||
| 		goto tx_error; | 		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, | 	ip_tunnel_init_flow(&fl4, protocol, dst, tnl_params->saddr, | ||||||
| 			    tunnel->parms.o_key, RT_TOS(tos), tunnel->parms.link, | 			    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) | 	if (ip_tunnel_encap(skb, tunnel, &protocol, &fl4) < 0) | ||||||
| 		goto tx_error; | 		goto tx_error; | ||||||
|  |  | ||||||
|  | @ -1820,6 +1820,7 @@ static void ip_multipath_l3_keys(const struct sk_buff *skb, | ||||||
| int fib_multipath_hash(const struct net *net, const struct flowi4 *fl4, | int fib_multipath_hash(const struct net *net, const struct flowi4 *fl4, | ||||||
| 		       const struct sk_buff *skb, struct flow_keys *flkeys) | 		       const struct sk_buff *skb, struct flow_keys *flkeys) | ||||||
| { | { | ||||||
|  | 	u32 multipath_hash = fl4->flowi4_multipath_hash; | ||||||
| 	struct flow_keys hash_keys; | 	struct flow_keys hash_keys; | ||||||
| 	u32 mhash; | 	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); | 	mhash = flow_hash_from_keys(&hash_keys); | ||||||
| 
 | 
 | ||||||
|  | 	if (multipath_hash) | ||||||
|  | 		mhash = jhash_2words(mhash, multipath_hash, 0); | ||||||
|  | 
 | ||||||
| 	return mhash >> 1; | 	return mhash >> 1; | ||||||
| } | } | ||||||
| #endif /* CONFIG_IP_ROUTE_MULTIPATH */ | #endif /* CONFIG_IP_ROUTE_MULTIPATH */ | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 wenxu
						wenxu