Skip to content

Commit a76d1ca

Browse files
pmachatadavem330
authored andcommitted
vxlan: Split vxlan_fdb_update() in two
In order to make it easier to implement rollbacks after FDB update vetoing, separate the FDB update code to two parts: one that deals with updates of existing FDB entries, and one that creates new entries. Signed-off-by: Petr Machata <petrm@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent c2b200e commit a76d1ca

File tree

1 file changed

+97
-61
lines changed

1 file changed

+97
-61
lines changed

drivers/net/vxlan.c

Lines changed: 97 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -855,92 +855,128 @@ static void vxlan_fdb_destroy(struct vxlan_dev *vxlan, struct vxlan_fdb *f,
855855
call_rcu(&f->rcu, vxlan_fdb_free);
856856
}
857857

858-
/* Add new entry to forwarding table -- assumes lock held */
859-
static int vxlan_fdb_update(struct vxlan_dev *vxlan,
860-
const u8 *mac, union vxlan_addr *ip,
861-
__u16 state, __u16 flags,
862-
__be16 port, __be32 src_vni, __be32 vni,
863-
__u32 ifindex, __u16 ndm_flags,
864-
bool swdev_notify)
858+
static int vxlan_fdb_update_existing(struct vxlan_dev *vxlan,
859+
union vxlan_addr *ip,
860+
__u16 state, __u16 flags,
861+
__be16 port, __be32 vni,
862+
__u32 ifindex, __u16 ndm_flags,
863+
struct vxlan_fdb *f,
864+
bool swdev_notify)
865865
{
866866
__u16 fdb_flags = (ndm_flags & ~NTF_USE);
867867
struct vxlan_rdst *rd = NULL;
868-
struct vxlan_fdb *f;
869868
int notify = 0;
870869
int rc;
871870

872-
f = __vxlan_find_mac(vxlan, mac, src_vni);
873-
if (f) {
874-
if (flags & NLM_F_EXCL) {
875-
netdev_dbg(vxlan->dev,
876-
"lost race to create %pM\n", mac);
877-
return -EEXIST;
878-
}
879-
880-
/* Do not allow an externally learned entry to take over an
881-
* entry added by the user.
882-
*/
883-
if (!(fdb_flags & NTF_EXT_LEARNED) ||
884-
!(f->flags & NTF_VXLAN_ADDED_BY_USER)) {
885-
if (f->state != state) {
886-
f->state = state;
887-
f->updated = jiffies;
888-
notify = 1;
889-
}
890-
if (f->flags != fdb_flags) {
891-
f->flags = fdb_flags;
892-
f->updated = jiffies;
893-
notify = 1;
894-
}
871+
/* Do not allow an externally learned entry to take over an entry added
872+
* by the user.
873+
*/
874+
if (!(fdb_flags & NTF_EXT_LEARNED) ||
875+
!(f->flags & NTF_VXLAN_ADDED_BY_USER)) {
876+
if (f->state != state) {
877+
f->state = state;
878+
f->updated = jiffies;
879+
notify = 1;
895880
}
896-
897-
if ((flags & NLM_F_REPLACE)) {
898-
/* Only change unicasts */
899-
if (!(is_multicast_ether_addr(f->eth_addr) ||
900-
is_zero_ether_addr(f->eth_addr))) {
901-
notify |= vxlan_fdb_replace(f, ip, port, vni,
902-
ifindex);
903-
} else
904-
return -EOPNOTSUPP;
881+
if (f->flags != fdb_flags) {
882+
f->flags = fdb_flags;
883+
f->updated = jiffies;
884+
notify = 1;
905885
}
906-
if ((flags & NLM_F_APPEND) &&
907-
(is_multicast_ether_addr(f->eth_addr) ||
908-
is_zero_ether_addr(f->eth_addr))) {
909-
rc = vxlan_fdb_append(f, ip, port, vni, ifindex, &rd);
886+
}
910887

911-
if (rc < 0)
912-
return rc;
888+
if ((flags & NLM_F_REPLACE)) {
889+
/* Only change unicasts */
890+
if (!(is_multicast_ether_addr(f->eth_addr) ||
891+
is_zero_ether_addr(f->eth_addr))) {
892+
rc = vxlan_fdb_replace(f, ip, port, vni,
893+
ifindex);
913894
notify |= rc;
914-
}
915-
916-
if (ndm_flags & NTF_USE)
917-
f->used = jiffies;
918-
} else {
919-
if (!(flags & NLM_F_CREATE))
920-
return -ENOENT;
921-
922-
/* Disallow replace to add a multicast entry */
923-
if ((flags & NLM_F_REPLACE) &&
924-
(is_multicast_ether_addr(mac) || is_zero_ether_addr(mac)))
895+
} else {
925896
return -EOPNOTSUPP;
897+
}
898+
}
899+
if ((flags & NLM_F_APPEND) &&
900+
(is_multicast_ether_addr(f->eth_addr) ||
901+
is_zero_ether_addr(f->eth_addr))) {
902+
rc = vxlan_fdb_append(f, ip, port, vni, ifindex, &rd);
926903

927-
netdev_dbg(vxlan->dev, "add %pM -> %pIS\n", mac, ip);
928-
rc = vxlan_fdb_create(vxlan, mac, ip, state, port, src_vni,
929-
vni, ifindex, fdb_flags, &f);
930904
if (rc < 0)
931905
return rc;
932-
notify = 1;
906+
notify |= rc;
933907
}
934908

909+
if (ndm_flags & NTF_USE)
910+
f->used = jiffies;
911+
935912
if (notify) {
936913
if (rd == NULL)
937914
rd = first_remote_rtnl(f);
915+
938916
vxlan_fdb_notify(vxlan, f, rd, RTM_NEWNEIGH, swdev_notify);
939917
}
940918

941919
return 0;
942920
}
943921

922+
static int vxlan_fdb_update_create(struct vxlan_dev *vxlan,
923+
const u8 *mac, union vxlan_addr *ip,
924+
__u16 state, __u16 flags,
925+
__be16 port, __be32 src_vni, __be32 vni,
926+
__u32 ifindex, __u16 ndm_flags,
927+
bool swdev_notify)
928+
{
929+
__u16 fdb_flags = (ndm_flags & ~NTF_USE);
930+
struct vxlan_fdb *f;
931+
int rc;
932+
933+
/* Disallow replace to add a multicast entry */
934+
if ((flags & NLM_F_REPLACE) &&
935+
(is_multicast_ether_addr(mac) || is_zero_ether_addr(mac)))
936+
return -EOPNOTSUPP;
937+
938+
netdev_dbg(vxlan->dev, "add %pM -> %pIS\n", mac, ip);
939+
rc = vxlan_fdb_create(vxlan, mac, ip, state, port, src_vni,
940+
vni, ifindex, fdb_flags, &f);
941+
if (rc < 0)
942+
return rc;
943+
944+
vxlan_fdb_notify(vxlan, f, first_remote_rtnl(f), RTM_NEWNEIGH,
945+
swdev_notify);
946+
return 0;
947+
}
948+
949+
/* Add new entry to forwarding table -- assumes lock held */
950+
static int vxlan_fdb_update(struct vxlan_dev *vxlan,
951+
const u8 *mac, union vxlan_addr *ip,
952+
__u16 state, __u16 flags,
953+
__be16 port, __be32 src_vni, __be32 vni,
954+
__u32 ifindex, __u16 ndm_flags,
955+
bool swdev_notify)
956+
{
957+
struct vxlan_fdb *f;
958+
959+
f = __vxlan_find_mac(vxlan, mac, src_vni);
960+
if (f) {
961+
if (flags & NLM_F_EXCL) {
962+
netdev_dbg(vxlan->dev,
963+
"lost race to create %pM\n", mac);
964+
return -EEXIST;
965+
}
966+
967+
return vxlan_fdb_update_existing(vxlan, ip, state, flags, port,
968+
vni, ifindex, ndm_flags, f,
969+
swdev_notify);
970+
} else {
971+
if (!(flags & NLM_F_CREATE))
972+
return -ENOENT;
973+
974+
return vxlan_fdb_update_create(vxlan, mac, ip, state, flags,
975+
port, src_vni, vni, ifindex,
976+
ndm_flags, swdev_notify);
977+
}
978+
}
979+
944980
static void vxlan_dst_free(struct rcu_head *head)
945981
{
946982
struct vxlan_rdst *rd = container_of(head, struct vxlan_rdst, rcu);

0 commit comments

Comments
 (0)