Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bf4e0a3d authored by Nikolay Aleksandrov's avatar Nikolay Aleksandrov Committed by David S. Miller
Browse files

net: ipv4: add support for ECMP hash policy choice



This patch adds support for ECMP hash policy choice via a new sysctl
called fib_multipath_hash_policy and also adds support for L4 hashes.
The current values for fib_multipath_hash_policy are:
 0 - layer 3 (default)
 1 - layer 4
If there's an skb hash already set and it matches the chosen policy then it
will be used instead of being calculated (currently only for L4).
In L3 mode we always calculate the hash due to the ICMP error special
case, the flow dissector's field consistentification should handle the
address order thus we can remove the address reversals.
If the skb is provided we always use it for the hash calculation,
otherwise we fallback to fl4, that is if skb is NULL fl4 has to be set.

Signed-off-by: default avatarNikolay Aleksandrov <nikolay@cumulusnetworks.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 88997e42
Loading
Loading
Loading
Loading
+8 −0
Original line number Original line Diff line number Diff line
@@ -73,6 +73,14 @@ fib_multipath_use_neigh - BOOLEAN
	0 - disabled
	0 - disabled
	1 - enabled
	1 - enabled


fib_multipath_hash_policy - INTEGER
	Controls which hash policy to use for multipath routes. Only valid
	for kernels built with CONFIG_IP_ROUTE_MULTIPATH enabled.
	Default: 0 (Layer 3)
	Possible values:
	0 - Layer 3
	1 - Layer 4

route/max_size - INTEGER
route/max_size - INTEGER
	Maximum number of routes allowed in the kernel.  Increase
	Maximum number of routes allowed in the kernel.  Increase
	this when using large numbers of interfaces and/or routes.
	this when using large numbers of interfaces and/or routes.
+5 −9
Original line number Original line Diff line number Diff line
@@ -395,17 +395,13 @@ int fib_sync_down_dev(struct net_device *dev, unsigned long event, bool force);
int fib_sync_down_addr(struct net_device *dev, __be32 local);
int fib_sync_down_addr(struct net_device *dev, __be32 local);
int fib_sync_up(struct net_device *dev, unsigned int nh_flags);
int fib_sync_up(struct net_device *dev, unsigned int nh_flags);


extern u32 fib_multipath_secret __read_mostly;
#ifdef CONFIG_IP_ROUTE_MULTIPATH

int fib_multipath_hash(const struct fib_info *fi, const struct flowi4 *fl4,
static inline int fib_multipath_hash(__be32 saddr, __be32 daddr)
		       const struct sk_buff *skb);
{
#endif
	return jhash_2words((__force u32)saddr, (__force u32)daddr,
			    fib_multipath_secret) >> 1;
}

void fib_select_multipath(struct fib_result *res, int hash);
void fib_select_multipath(struct fib_result *res, int hash);
void fib_select_path(struct net *net, struct fib_result *res,
void fib_select_path(struct net *net, struct fib_result *res,
		     struct flowi4 *fl4, int mp_hash);
		     struct flowi4 *fl4, const struct sk_buff *skb);


/* Exported by fib_trie.c */
/* Exported by fib_trie.c */
void fib_trie_init(void);
void fib_trie_init(void);
+1 −0
Original line number Original line Diff line number Diff line
@@ -151,6 +151,7 @@ struct netns_ipv4 {
#endif
#endif
#ifdef CONFIG_IP_ROUTE_MULTIPATH
#ifdef CONFIG_IP_ROUTE_MULTIPATH
	int sysctl_fib_multipath_use_neigh;
	int sysctl_fib_multipath_use_neigh;
	int sysctl_fib_multipath_hash_policy;
#endif
#endif


	unsigned int	fib_seq;	/* protected by rtnl_mutex */
	unsigned int	fib_seq;	/* protected by rtnl_mutex */
+3 −3
Original line number Original line Diff line number Diff line
@@ -113,13 +113,13 @@ struct in_device;
int ip_rt_init(void);
int ip_rt_init(void);
void rt_cache_flush(struct net *net);
void rt_cache_flush(struct net *net);
void rt_flush_dev(struct net_device *dev);
void rt_flush_dev(struct net_device *dev);
struct rtable *__ip_route_output_key_hash(struct net *, struct flowi4 *flp,
struct rtable *__ip_route_output_key_hash(struct net *net, struct flowi4 *flp,
					  int mp_hash);
					  const struct sk_buff *skb);


static inline struct rtable *__ip_route_output_key(struct net *net,
static inline struct rtable *__ip_route_output_key(struct net *net,
						   struct flowi4 *flp)
						   struct flowi4 *flp)
{
{
	return __ip_route_output_key_hash(net, flp, -1);
	return __ip_route_output_key_hash(net, flp, NULL);
}
}


struct rtable *ip_route_output_flow(struct net *, struct flowi4 *flp,
struct rtable *ip_route_output_flow(struct net *, struct flowi4 *flp,
+3 −8
Original line number Original line Diff line number Diff line
@@ -57,7 +57,6 @@ static unsigned int fib_info_cnt;
static struct hlist_head fib_info_devhash[DEVINDEX_HASHSIZE];
static struct hlist_head fib_info_devhash[DEVINDEX_HASHSIZE];


#ifdef CONFIG_IP_ROUTE_MULTIPATH
#ifdef CONFIG_IP_ROUTE_MULTIPATH
u32 fib_multipath_secret __read_mostly;


#define for_nexthops(fi) {						\
#define for_nexthops(fi) {						\
	int nhsel; const struct fib_nh *nh;				\
	int nhsel; const struct fib_nh *nh;				\
@@ -576,9 +575,6 @@ static void fib_rebalance(struct fib_info *fi)


		atomic_set(&nexthop_nh->nh_upper_bound, upper_bound);
		atomic_set(&nexthop_nh->nh_upper_bound, upper_bound);
	} endfor_nexthops(fi);
	} endfor_nexthops(fi);

	net_get_random_once(&fib_multipath_secret,
			    sizeof(fib_multipath_secret));
}
}


static inline void fib_add_weight(struct fib_info *fi,
static inline void fib_add_weight(struct fib_info *fi,
@@ -1641,7 +1637,7 @@ void fib_select_multipath(struct fib_result *res, int hash)
#endif
#endif


void fib_select_path(struct net *net, struct fib_result *res,
void fib_select_path(struct net *net, struct fib_result *res,
		     struct flowi4 *fl4, int mp_hash)
		     struct flowi4 *fl4, const struct sk_buff *skb)
{
{
	bool oif_check;
	bool oif_check;


@@ -1650,10 +1646,9 @@ void fib_select_path(struct net *net, struct fib_result *res,


#ifdef CONFIG_IP_ROUTE_MULTIPATH
#ifdef CONFIG_IP_ROUTE_MULTIPATH
	if (res->fi->fib_nhs > 1 && oif_check) {
	if (res->fi->fib_nhs > 1 && oif_check) {
		if (mp_hash < 0)
		int h = fib_multipath_hash(res->fi, fl4, skb);
			mp_hash = get_hash_from_flowi4(fl4) >> 1;


		fib_select_multipath(res, mp_hash);
		fib_select_multipath(res, h);
	}
	}
	else
	else
#endif
#endif
Loading