Commit d8a30706 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'dst-hint-multipath'



Sriram Yagnaraman says:

====================
Avoid TCP resets when using ECMP for load-balancing between multiple servers.

All packets in the same flow (L3/L4 depending on multipath hash policy)
should be directed to the same target, but after [0]/[1] we see stray
packets directed towards other targets. This, for instance, causes RST
to be sent on TCP connections.

The first two patches solve the problem by ignoring route hints for
destinations that are part of multipath group, by using new SKB flags
for IPv4 and IPv6. The third patch is a selftest that tests the
scenario.

Thanks to Ido, for reviewing and suggesting a way forward in [2] and
also suggesting how to write a selftest for this.

v4->v5:
- Fixed review comments from Ido
v3->v4:
- Remove single path test
- Rebase to latest
v2->v3:
- Add NULL check for skb in fib6_select_path (Ido Schimmel)
- Use fib_tests.sh for selftest instead of the forwarding suite (Ido
  Schimmel)
v1->v2:
- Update to commit messages describing the solution (Ido Schimmel)
- Use perf stat to count fib table lookups in selftest (Ido Schimmel)
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 2ea35288 8ae9efb8
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -147,6 +147,7 @@ struct inet6_skb_parm {
#define IP6SKB_JUMBOGRAM      128
#define IP6SKB_SEG6	      256
#define IP6SKB_FAKEJUMBO      512
#define IP6SKB_MULTIPATH      1024
};

#if defined(CONFIG_NET_L3_MASTER_DEV)
+1 −0
Original line number Diff line number Diff line
@@ -57,6 +57,7 @@ struct inet_skb_parm {
#define IPSKB_FRAG_PMTU		BIT(6)
#define IPSKB_L3SLAVE		BIT(7)
#define IPSKB_NOPOLICY		BIT(8)
#define IPSKB_MULTIPATH		BIT(9)

	u16			frag_max_size;
};
+2 −1
Original line number Diff line number Diff line
@@ -584,7 +584,8 @@ static void ip_sublist_rcv_finish(struct list_head *head)
static struct sk_buff *ip_extract_route_hint(const struct net *net,
					     struct sk_buff *skb, int rt_type)
{
	if (fib4_has_custom_rules(net) || rt_type == RTN_BROADCAST)
	if (fib4_has_custom_rules(net) || rt_type == RTN_BROADCAST ||
	    IPCB(skb)->flags & IPSKB_MULTIPATH)
		return NULL;

	return skb;
+1 −0
Original line number Diff line number Diff line
@@ -2144,6 +2144,7 @@ static int ip_mkroute_input(struct sk_buff *skb,
		int h = fib_multipath_hash(res->fi->fib_net, NULL, skb, hkeys);

		fib_select_multipath(res, h);
		IPCB(skb)->flags |= IPSKB_MULTIPATH;
	}
#endif

+2 −1
Original line number Diff line number Diff line
@@ -99,7 +99,8 @@ static bool ip6_can_use_hint(const struct sk_buff *skb,
static struct sk_buff *ip6_extract_route_hint(const struct net *net,
					      struct sk_buff *skb)
{
	if (fib6_routes_require_src(net) || fib6_has_custom_rules(net))
	if (fib6_routes_require_src(net) || fib6_has_custom_rules(net) ||
	    IP6CB(skb)->flags & IP6SKB_MULTIPATH)
		return NULL;

	return skb;
Loading