net: ipv4: fix list processing on L3 slave devices
If we have an L3 master device, l3mdev_ip_rcv() will steal the skb, but
we were returning NET_RX_SUCCESS from ip_rcv_finish_core() which meant
that ip_list_rcv_finish() would keep it on the list. Instead let's
move the l3mdev_ip_rcv() call into the caller, so that our response to
a steal can be different in the single packet path (return
NET_RX_SUCCESS) and the list path (forget this packet and continue).
Fixes: 5fa12739a5
("net: ipv4: listify ip_rcv_finish")
Signed-off-by: Edward Cree <ecree@solarflare.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
2cc0608e42
commit
efe6aaca67
@ -316,13 +316,6 @@ static int ip_rcv_finish_core(struct net *net, struct sock *sk,
|
|||||||
struct rtable *rt;
|
struct rtable *rt;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
/* if ingress device is enslaved to an L3 master device pass the
|
|
||||||
* skb to its handler for processing
|
|
||||||
*/
|
|
||||||
skb = l3mdev_ip_rcv(skb);
|
|
||||||
if (!skb)
|
|
||||||
return NET_RX_SUCCESS;
|
|
||||||
|
|
||||||
if (net->ipv4.sysctl_ip_early_demux &&
|
if (net->ipv4.sysctl_ip_early_demux &&
|
||||||
!skb_dst(skb) &&
|
!skb_dst(skb) &&
|
||||||
!skb->sk &&
|
!skb->sk &&
|
||||||
@ -408,8 +401,16 @@ drop_error:
|
|||||||
|
|
||||||
static int ip_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
|
static int ip_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
int ret = ip_rcv_finish_core(net, sk, skb);
|
int ret;
|
||||||
|
|
||||||
|
/* if ingress device is enslaved to an L3 master device pass the
|
||||||
|
* skb to its handler for processing
|
||||||
|
*/
|
||||||
|
skb = l3mdev_ip_rcv(skb);
|
||||||
|
if (!skb)
|
||||||
|
return NET_RX_SUCCESS;
|
||||||
|
|
||||||
|
ret = ip_rcv_finish_core(net, sk, skb);
|
||||||
if (ret != NET_RX_DROP)
|
if (ret != NET_RX_DROP)
|
||||||
ret = dst_input(skb);
|
ret = dst_input(skb);
|
||||||
return ret;
|
return ret;
|
||||||
@ -545,6 +546,12 @@ static void ip_list_rcv_finish(struct net *net, struct sock *sk,
|
|||||||
struct dst_entry *dst;
|
struct dst_entry *dst;
|
||||||
|
|
||||||
list_del(&skb->list);
|
list_del(&skb->list);
|
||||||
|
/* if ingress device is enslaved to an L3 master device pass the
|
||||||
|
* skb to its handler for processing
|
||||||
|
*/
|
||||||
|
skb = l3mdev_ip_rcv(skb);
|
||||||
|
if (!skb)
|
||||||
|
continue;
|
||||||
if (ip_rcv_finish_core(net, sk, skb) == NET_RX_DROP)
|
if (ip_rcv_finish_core(net, sk, skb) == NET_RX_DROP)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user