diff options
Diffstat (limited to 'drivers/net/vxlan.c')
-rw-r--r-- | drivers/net/vxlan.c | 40 |
1 files changed, 26 insertions, 14 deletions
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 8111565c35fc..f6dce13c8f89 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c | |||
@@ -603,18 +603,22 @@ skip: | |||
603 | 603 | ||
604 | /* Watch incoming packets to learn mapping between Ethernet address | 604 | /* Watch incoming packets to learn mapping between Ethernet address |
605 | * and Tunnel endpoint. | 605 | * and Tunnel endpoint. |
606 | * Return true if packet is bogus and should be droppped. | ||
606 | */ | 607 | */ |
607 | static void vxlan_snoop(struct net_device *dev, | 608 | static bool vxlan_snoop(struct net_device *dev, |
608 | __be32 src_ip, const u8 *src_mac) | 609 | __be32 src_ip, const u8 *src_mac) |
609 | { | 610 | { |
610 | struct vxlan_dev *vxlan = netdev_priv(dev); | 611 | struct vxlan_dev *vxlan = netdev_priv(dev); |
611 | struct vxlan_fdb *f; | 612 | struct vxlan_fdb *f; |
612 | int err; | ||
613 | 613 | ||
614 | f = vxlan_find_mac(vxlan, src_mac); | 614 | f = vxlan_find_mac(vxlan, src_mac); |
615 | if (likely(f)) { | 615 | if (likely(f)) { |
616 | if (likely(f->remote.remote_ip == src_ip)) | 616 | if (likely(f->remote.remote_ip == src_ip)) |
617 | return; | 617 | return false; |
618 | |||
619 | /* Don't migrate static entries, drop packets */ | ||
620 | if (f->state & NUD_NOARP) | ||
621 | return true; | ||
618 | 622 | ||
619 | if (net_ratelimit()) | 623 | if (net_ratelimit()) |
620 | netdev_info(dev, | 624 | netdev_info(dev, |
@@ -626,14 +630,19 @@ static void vxlan_snoop(struct net_device *dev, | |||
626 | } else { | 630 | } else { |
627 | /* learned new entry */ | 631 | /* learned new entry */ |
628 | spin_lock(&vxlan->hash_lock); | 632 | spin_lock(&vxlan->hash_lock); |
629 | err = vxlan_fdb_create(vxlan, src_mac, src_ip, | 633 | |
630 | NUD_REACHABLE, | 634 | /* close off race between vxlan_flush and incoming packets */ |
631 | NLM_F_EXCL|NLM_F_CREATE, | 635 | if (netif_running(dev)) |
632 | vxlan->dst_port, | 636 | vxlan_fdb_create(vxlan, src_mac, src_ip, |
633 | vxlan->default_dst.remote_vni, | 637 | NUD_REACHABLE, |
634 | 0, NTF_SELF); | 638 | NLM_F_EXCL|NLM_F_CREATE, |
639 | vxlan->dst_port, | ||
640 | vxlan->default_dst.remote_vni, | ||
641 | 0, NTF_SELF); | ||
635 | spin_unlock(&vxlan->hash_lock); | 642 | spin_unlock(&vxlan->hash_lock); |
636 | } | 643 | } |
644 | |||
645 | return false; | ||
637 | } | 646 | } |
638 | 647 | ||
639 | 648 | ||
@@ -766,8 +775,9 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb) | |||
766 | vxlan->dev->dev_addr) == 0) | 775 | vxlan->dev->dev_addr) == 0) |
767 | goto drop; | 776 | goto drop; |
768 | 777 | ||
769 | if (vxlan->flags & VXLAN_F_LEARN) | 778 | if ((vxlan->flags & VXLAN_F_LEARN) && |
770 | vxlan_snoop(skb->dev, oip->saddr, eth_hdr(skb)->h_source); | 779 | vxlan_snoop(skb->dev, oip->saddr, eth_hdr(skb)->h_source)) |
780 | goto drop; | ||
771 | 781 | ||
772 | __skb_tunnel_rx(skb, vxlan->dev); | 782 | __skb_tunnel_rx(skb, vxlan->dev); |
773 | skb_reset_network_header(skb); | 783 | skb_reset_network_header(skb); |
@@ -1190,9 +1200,11 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1190 | struct sk_buff *skb1; | 1200 | struct sk_buff *skb1; |
1191 | 1201 | ||
1192 | skb1 = skb_clone(skb, GFP_ATOMIC); | 1202 | skb1 = skb_clone(skb, GFP_ATOMIC); |
1193 | rc1 = vxlan_xmit_one(skb1, dev, rdst, did_rsc); | 1203 | if (skb1) { |
1194 | if (rc == NETDEV_TX_OK) | 1204 | rc1 = vxlan_xmit_one(skb1, dev, rdst, did_rsc); |
1195 | rc = rc1; | 1205 | if (rc == NETDEV_TX_OK) |
1206 | rc = rc1; | ||
1207 | } | ||
1196 | } | 1208 | } |
1197 | 1209 | ||
1198 | rc1 = vxlan_xmit_one(skb, dev, rdst0, did_rsc); | 1210 | rc1 = vxlan_xmit_one(skb, dev, rdst0, did_rsc); |