Skip to content

Commit

Permalink
Merge branch 'vrf-looping'
Browse files Browse the repository at this point in the history
David Ahern says:

====================
net: Fix looping with vrf, xfrms and qdisc on VRF

Trev reported that use of VRFs with xfrms is looping when a qdisc
is added to the VRF device. The combination of xfrm + qdisc is not
handled by the VRF driver which lost track that it has already
seen the packet.

The XFRM_TRANSFORMED flag is used by the netfilter code for a similar
purpose, so re-use for VRF. Patch 1 drops the #ifdef around setting
the flag in the xfrm output functions. Patch 2 adds a check to
the VRF driver for flag; if set the packet has already passed through
the VRF driver once and does not need to recirculated a second time.

This is a day 1 bug with VRFs; stable wise, I would only take this
back to 4.14. I have a set of test cases which I will submit to
net-next.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Apr 22, 2020
2 parents 9175d3f + 16b9db1 commit 87f78f2
Show file tree
Hide file tree
Showing 3 changed files with 4 additions and 6 deletions.
6 changes: 4 additions & 2 deletions drivers/net/vrf.c
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,8 @@ static struct sk_buff *vrf_ip6_out(struct net_device *vrf_dev,
if (rt6_need_strict(&ipv6_hdr(skb)->daddr))
return skb;

if (qdisc_tx_is_default(vrf_dev))
if (qdisc_tx_is_default(vrf_dev) ||
IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED)
return vrf_ip6_out_direct(vrf_dev, sk, skb);

return vrf_ip6_out_redirect(vrf_dev, skb);
Expand Down Expand Up @@ -686,7 +687,8 @@ static struct sk_buff *vrf_ip_out(struct net_device *vrf_dev,
ipv4_is_lbcast(ip_hdr(skb)->daddr))
return skb;

if (qdisc_tx_is_default(vrf_dev))
if (qdisc_tx_is_default(vrf_dev) ||
IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED)
return vrf_ip_out_direct(vrf_dev, sk, skb);

return vrf_ip_out_redirect(vrf_dev, skb);
Expand Down
2 changes: 0 additions & 2 deletions net/ipv4/xfrm4_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,7 @@ int xfrm4_output_finish(struct sock *sk, struct sk_buff *skb)
{
memset(IPCB(skb), 0, sizeof(*IPCB(skb)));

#ifdef CONFIG_NETFILTER
IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
#endif

return xfrm_output(sk, skb);
}
Expand Down
2 changes: 0 additions & 2 deletions net/ipv6/xfrm6_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,7 @@ int xfrm6_output_finish(struct sock *sk, struct sk_buff *skb)
{
memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));

#ifdef CONFIG_NETFILTER
IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED;
#endif

return xfrm_output(sk, skb);
}
Expand Down

0 comments on commit 87f78f2

Please sign in to comment.