diff options
Diffstat (limited to 'drivers/net/ipvlan/ipvlan_core.c')
-rw-r--r-- | drivers/net/ipvlan/ipvlan_core.c | 27 |
1 files changed, 16 insertions, 11 deletions
diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c index 4e60c6bbdb6e..d6d0524ee5fd 100644 --- a/drivers/net/ipvlan/ipvlan_core.c +++ b/drivers/net/ipvlan/ipvlan_core.c @@ -53,8 +53,8 @@ static u8 ipvlan_get_v4_hash(const void *iaddr) IPVLAN_HASH_MASK; } -struct ipvl_addr *ipvlan_ht_addr_lookup(const struct ipvl_port *port, - const void *iaddr, bool is_v6) +static struct ipvl_addr *ipvlan_ht_addr_lookup(const struct ipvl_port *port, + const void *iaddr, bool is_v6) { struct ipvl_addr *addr; u8 hash; @@ -265,20 +265,25 @@ static int ipvlan_rcv_frame(struct ipvl_addr *addr, struct sk_buff **pskb, struct sk_buff *skb = *pskb; len = skb->len + ETH_HLEN; - if (unlikely(!(dev->flags & IFF_UP))) { - kfree_skb(skb); - goto out; - } + /* Only packets exchanged between two local slaves need to have + * device-up check as well as skb-share check. + */ + if (local) { + if (unlikely(!(dev->flags & IFF_UP))) { + kfree_skb(skb); + goto out; + } - skb = skb_share_check(skb, GFP_ATOMIC); - if (!skb) - goto out; + skb = skb_share_check(skb, GFP_ATOMIC); + if (!skb) + goto out; - *pskb = skb; + *pskb = skb; + } skb->dev = dev; - skb->pkt_type = PACKET_HOST; if (local) { + skb->pkt_type = PACKET_HOST; if (dev_forward_skb(ipvlan->dev, skb) == NET_RX_SUCCESS) success = true; } else { |