summaryrefslogtreecommitdiffstats
path: root/drivers/net/vxlan.c
diff options
context:
space:
mode:
authorMike Rapoport <mike.rapoport@ravellosystems.com>2013-06-25 09:01:54 -0400
committerStephen Hemminger <stephen@networkplumber.org>2013-06-25 12:31:38 -0400
commitbc7892ba39992c6d645e906f1d52a626395b4b11 (patch)
tree846e364576bd91c051db6d0e234f81c086c69e39 /drivers/net/vxlan.c
parentf0b074be7b61a800e39053d73dabf850649c1c8f (diff)
vxlan: allow removal of single destination from fdb entry
When the last item is deleted from the remote destinations list, the fdb entry is destroyed. Signed-off-by: Mike Rapoport <mike.rapoport@ravellosystems.com> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Diffstat (limited to 'drivers/net/vxlan.c')
-rw-r--r--drivers/net/vxlan.c44
1 files changed, 40 insertions, 4 deletions
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index ee7cc71e57fd..c1825201f9e2 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -105,6 +105,7 @@ struct vxlan_rdst {
105 u32 remote_vni; 105 u32 remote_vni;
106 u32 remote_ifindex; 106 u32 remote_ifindex;
107 struct list_head list; 107 struct list_head list;
108 struct rcu_head rcu;
108}; 109};
109 110
110/* Forwarding table entry */ 111/* Forwarding table entry */
@@ -496,6 +497,12 @@ static int vxlan_fdb_create(struct vxlan_dev *vxlan,
496 return 0; 497 return 0;
497} 498}
498 499
500static void vxlan_fdb_free_rdst(struct rcu_head *head)
501{
502 struct vxlan_rdst *rd = container_of(head, struct vxlan_rdst, rcu);
503 kfree(rd);
504}
505
499static void vxlan_fdb_free(struct rcu_head *head) 506static void vxlan_fdb_free(struct rcu_head *head)
500{ 507{
501 struct vxlan_fdb *f = container_of(head, struct vxlan_fdb, rcu); 508 struct vxlan_fdb *f = container_of(head, struct vxlan_fdb, rcu);
@@ -605,14 +612,43 @@ static int vxlan_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],
605{ 612{
606 struct vxlan_dev *vxlan = netdev_priv(dev); 613 struct vxlan_dev *vxlan = netdev_priv(dev);
607 struct vxlan_fdb *f; 614 struct vxlan_fdb *f;
608 int err = -ENOENT; 615 struct vxlan_rdst *rd = NULL;
616 __be32 ip;
617 __be16 port;
618 u32 vni, ifindex;
619 int err;
620
621 err = vxlan_fdb_parse(tb, vxlan, &ip, &port, &vni, &ifindex);
622 if (err)
623 return err;
624
625 err = -ENOENT;
609 626
610 spin_lock_bh(&vxlan->hash_lock); 627 spin_lock_bh(&vxlan->hash_lock);
611 f = vxlan_find_mac(vxlan, addr); 628 f = vxlan_find_mac(vxlan, addr);
612 if (f) { 629 if (!f)
613 vxlan_fdb_destroy(vxlan, f); 630 goto out;
614 err = 0; 631
632 if (ip != htonl(INADDR_ANY)) {
633 rd = vxlan_fdb_find_rdst(f, ip, port, vni, ifindex);
634 if (!rd)
635 goto out;
636 }
637
638 err = 0;
639
640 /* remove a destination if it's not the only one on the list,
641 * otherwise destroy the fdb entry
642 */
643 if (rd && !list_is_singular(&f->remotes)) {
644 list_del_rcu(&rd->list);
645 call_rcu(&rd->rcu, vxlan_fdb_free_rdst);
646 goto out;
615 } 647 }
648
649 vxlan_fdb_destroy(vxlan, f);
650
651out:
616 spin_unlock_bh(&vxlan->hash_lock); 652 spin_unlock_bh(&vxlan->hash_lock);
617 653
618 return err; 654 return err;