diff options
author | Roopa Prabhu <roopa@cumulusnetworks.com> | 2018-07-20 16:21:02 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-07-22 13:52:37 -0400 |
commit | 7431016b107c95cb5b2014aa1901fcb115f746bc (patch) | |
tree | ee1a1c54f2e5cc8c75238c863a6600db583adcc7 | |
parent | 5025f7f7d506fba9b39e7fe8ca10f6f34cb9bc2d (diff) |
vxlan: add new fdb alloc and create helpers
- Add new vxlan_fdb_alloc helper
- rename existing vxlan_fdb_create into vxlan_fdb_update:
because it really creates or updates an existing
fdb entry
- move new fdb creation into a separate vxlan_fdb_create
Main motivation for this change is to introduce the ability
to decouple vxlan fdb creation and notify, used in a later patch.
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/vxlan.c | 91 |
1 files changed, 62 insertions, 29 deletions
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index f6bb1d54d4bd..c8d5bfffadef 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c | |||
@@ -636,9 +636,62 @@ static int vxlan_gro_complete(struct sock *sk, struct sk_buff *skb, int nhoff) | |||
636 | return eth_gro_complete(skb, nhoff + sizeof(struct vxlanhdr)); | 636 | return eth_gro_complete(skb, nhoff + sizeof(struct vxlanhdr)); |
637 | } | 637 | } |
638 | 638 | ||
639 | /* Add new entry to forwarding table -- assumes lock held */ | 639 | static struct vxlan_fdb *vxlan_fdb_alloc(struct vxlan_dev *vxlan, |
640 | const u8 *mac, __u16 state, | ||
641 | __be32 src_vni, __u8 ndm_flags) | ||
642 | { | ||
643 | struct vxlan_fdb *f; | ||
644 | |||
645 | f = kmalloc(sizeof(*f), GFP_ATOMIC); | ||
646 | if (!f) | ||
647 | return NULL; | ||
648 | f->state = state; | ||
649 | f->flags = ndm_flags; | ||
650 | f->updated = f->used = jiffies; | ||
651 | f->vni = src_vni; | ||
652 | INIT_LIST_HEAD(&f->remotes); | ||
653 | memcpy(f->eth_addr, mac, ETH_ALEN); | ||
654 | |||
655 | return f; | ||
656 | } | ||
657 | |||
640 | static int vxlan_fdb_create(struct vxlan_dev *vxlan, | 658 | static int vxlan_fdb_create(struct vxlan_dev *vxlan, |
641 | const u8 *mac, union vxlan_addr *ip, | 659 | const u8 *mac, union vxlan_addr *ip, |
660 | __u16 state, __be16 port, __be32 src_vni, | ||
661 | __be32 vni, __u32 ifindex, __u8 ndm_flags, | ||
662 | struct vxlan_fdb **fdb) | ||
663 | { | ||
664 | struct vxlan_rdst *rd = NULL; | ||
665 | struct vxlan_fdb *f; | ||
666 | int rc; | ||
667 | |||
668 | if (vxlan->cfg.addrmax && | ||
669 | vxlan->addrcnt >= vxlan->cfg.addrmax) | ||
670 | return -ENOSPC; | ||
671 | |||
672 | netdev_dbg(vxlan->dev, "add %pM -> %pIS\n", mac, ip); | ||
673 | f = vxlan_fdb_alloc(vxlan, mac, state, src_vni, ndm_flags); | ||
674 | if (!f) | ||
675 | return -ENOMEM; | ||
676 | |||
677 | rc = vxlan_fdb_append(f, ip, port, vni, ifindex, &rd); | ||
678 | if (rc < 0) { | ||
679 | kfree(f); | ||
680 | return rc; | ||
681 | } | ||
682 | |||
683 | ++vxlan->addrcnt; | ||
684 | hlist_add_head_rcu(&f->hlist, | ||
685 | vxlan_fdb_head(vxlan, mac, src_vni)); | ||
686 | |||
687 | *fdb = f; | ||
688 | |||
689 | return 0; | ||
690 | } | ||
691 | |||
692 | /* Add new entry to forwarding table -- assumes lock held */ | ||
693 | static int vxlan_fdb_update(struct vxlan_dev *vxlan, | ||
694 | const u8 *mac, union vxlan_addr *ip, | ||
642 | __u16 state, __u16 flags, | 695 | __u16 state, __u16 flags, |
643 | __be16 port, __be32 src_vni, __be32 vni, | 696 | __be16 port, __be32 src_vni, __be32 vni, |
644 | __u32 ifindex, __u8 ndm_flags) | 697 | __u32 ifindex, __u8 ndm_flags) |
@@ -687,37 +740,17 @@ static int vxlan_fdb_create(struct vxlan_dev *vxlan, | |||
687 | if (!(flags & NLM_F_CREATE)) | 740 | if (!(flags & NLM_F_CREATE)) |
688 | return -ENOENT; | 741 | return -ENOENT; |
689 | 742 | ||
690 | if (vxlan->cfg.addrmax && | ||
691 | vxlan->addrcnt >= vxlan->cfg.addrmax) | ||
692 | return -ENOSPC; | ||
693 | |||
694 | /* Disallow replace to add a multicast entry */ | 743 | /* Disallow replace to add a multicast entry */ |
695 | if ((flags & NLM_F_REPLACE) && | 744 | if ((flags & NLM_F_REPLACE) && |
696 | (is_multicast_ether_addr(mac) || is_zero_ether_addr(mac))) | 745 | (is_multicast_ether_addr(mac) || is_zero_ether_addr(mac))) |
697 | return -EOPNOTSUPP; | 746 | return -EOPNOTSUPP; |
698 | 747 | ||
699 | netdev_dbg(vxlan->dev, "add %pM -> %pIS\n", mac, ip); | 748 | netdev_dbg(vxlan->dev, "add %pM -> %pIS\n", mac, ip); |
700 | f = kmalloc(sizeof(*f), GFP_ATOMIC); | 749 | rc = vxlan_fdb_create(vxlan, mac, ip, state, port, src_vni, |
701 | if (!f) | 750 | vni, ifindex, ndm_flags, &f); |
702 | return -ENOMEM; | 751 | if (rc < 0) |
703 | |||
704 | notify = 1; | ||
705 | f->state = state; | ||
706 | f->flags = ndm_flags; | ||
707 | f->updated = f->used = jiffies; | ||
708 | f->vni = src_vni; | ||
709 | INIT_LIST_HEAD(&f->remotes); | ||
710 | memcpy(f->eth_addr, mac, ETH_ALEN); | ||
711 | |||
712 | rc = vxlan_fdb_append(f, ip, port, vni, ifindex, &rd); | ||
713 | if (rc < 0) { | ||
714 | kfree(f); | ||
715 | return rc; | 752 | return rc; |
716 | } | 753 | notify = 1; |
717 | |||
718 | ++vxlan->addrcnt; | ||
719 | hlist_add_head_rcu(&f->hlist, | ||
720 | vxlan_fdb_head(vxlan, mac, src_vni)); | ||
721 | } | 754 | } |
722 | 755 | ||
723 | if (notify) { | 756 | if (notify) { |
@@ -863,7 +896,7 @@ static int vxlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], | |||
863 | return -EAFNOSUPPORT; | 896 | return -EAFNOSUPPORT; |
864 | 897 | ||
865 | spin_lock_bh(&vxlan->hash_lock); | 898 | spin_lock_bh(&vxlan->hash_lock); |
866 | err = vxlan_fdb_create(vxlan, addr, &ip, ndm->ndm_state, flags, | 899 | err = vxlan_fdb_update(vxlan, addr, &ip, ndm->ndm_state, flags, |
867 | port, src_vni, vni, ifindex, ndm->ndm_flags); | 900 | port, src_vni, vni, ifindex, ndm->ndm_flags); |
868 | spin_unlock_bh(&vxlan->hash_lock); | 901 | spin_unlock_bh(&vxlan->hash_lock); |
869 | 902 | ||
@@ -1006,7 +1039,7 @@ static bool vxlan_snoop(struct net_device *dev, | |||
1006 | 1039 | ||
1007 | /* close off race between vxlan_flush and incoming packets */ | 1040 | /* close off race between vxlan_flush and incoming packets */ |
1008 | if (netif_running(dev)) | 1041 | if (netif_running(dev)) |
1009 | vxlan_fdb_create(vxlan, src_mac, src_ip, | 1042 | vxlan_fdb_update(vxlan, src_mac, src_ip, |
1010 | NUD_REACHABLE, | 1043 | NUD_REACHABLE, |
1011 | NLM_F_EXCL|NLM_F_CREATE, | 1044 | NLM_F_EXCL|NLM_F_CREATE, |
1012 | vxlan->cfg.dst_port, | 1045 | vxlan->cfg.dst_port, |
@@ -3170,7 +3203,7 @@ static int __vxlan_dev_create(struct net *net, struct net_device *dev, | |||
3170 | 3203 | ||
3171 | /* create an fdb entry for a valid default destination */ | 3204 | /* create an fdb entry for a valid default destination */ |
3172 | if (!vxlan_addr_any(&vxlan->default_dst.remote_ip)) { | 3205 | if (!vxlan_addr_any(&vxlan->default_dst.remote_ip)) { |
3173 | err = vxlan_fdb_create(vxlan, all_zeros_mac, | 3206 | err = vxlan_fdb_update(vxlan, all_zeros_mac, |
3174 | &vxlan->default_dst.remote_ip, | 3207 | &vxlan->default_dst.remote_ip, |
3175 | NUD_REACHABLE | NUD_PERMANENT, | 3208 | NUD_REACHABLE | NUD_PERMANENT, |
3176 | NLM_F_EXCL | NLM_F_CREATE, | 3209 | NLM_F_EXCL | NLM_F_CREATE, |
@@ -3450,7 +3483,7 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[], | |||
3450 | old_dst.remote_ifindex, 0); | 3483 | old_dst.remote_ifindex, 0); |
3451 | 3484 | ||
3452 | if (!vxlan_addr_any(&dst->remote_ip)) { | 3485 | if (!vxlan_addr_any(&dst->remote_ip)) { |
3453 | err = vxlan_fdb_create(vxlan, all_zeros_mac, | 3486 | err = vxlan_fdb_update(vxlan, all_zeros_mac, |
3454 | &dst->remote_ip, | 3487 | &dst->remote_ip, |
3455 | NUD_REACHABLE | NUD_PERMANENT, | 3488 | NUD_REACHABLE | NUD_PERMANENT, |
3456 | NLM_F_CREATE | NLM_F_APPEND, | 3489 | NLM_F_CREATE | NLM_F_APPEND, |