Commit 24ba1440 authored by wenxu's avatar wenxu Committed by David S. Miller

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: default avatarwenxu <wenxu@ucloud.cn>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8f4ef499
...@@ -305,7 +305,7 @@ mlxsw_sp_span_gretap4_route(const struct net_device *to_dev, ...@@ -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 { ...@@ -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 { ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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 */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment