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>
This commit is contained in:
parent
8d356b89f3
commit
25e20e730d
|
@ -637,8 +637,61 @@ static int vxlan_gro_complete(struct sock *sk, struct sk_buff *skb, int nhoff)
|
|||
return eth_gro_complete(skb, nhoff + sizeof(struct vxlanhdr));
|
||||
}
|
||||
|
||||
/* Add new entry to forwarding table -- assumes lock held */
|
||||
static struct vxlan_fdb *vxlan_fdb_alloc(struct vxlan_dev *vxlan,
|
||||
const u8 *mac, __u16 state,
|
||||
__be32 src_vni, __u8 ndm_flags)
|
||||
{
|
||||
struct vxlan_fdb *f;
|
||||
|
||||
f = kmalloc(sizeof(*f), GFP_ATOMIC);
|
||||
if (!f)
|
||||
return NULL;
|
||||
f->state = state;
|
||||
f->flags = ndm_flags;
|
||||
f->updated = f->used = jiffies;
|
||||
f->vni = src_vni;
|
||||
INIT_LIST_HEAD(&f->remotes);
|
||||
memcpy(f->eth_addr, mac, ETH_ALEN);
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
static int vxlan_fdb_create(struct vxlan_dev *vxlan,
|
||||
const u8 *mac, union vxlan_addr *ip,
|
||||
__u16 state, __be16 port, __be32 src_vni,
|
||||
__be32 vni, __u32 ifindex, __u8 ndm_flags,
|
||||
struct vxlan_fdb **fdb)
|
||||
{
|
||||
struct vxlan_rdst *rd = NULL;
|
||||
struct vxlan_fdb *f;
|
||||
int rc;
|
||||
|
||||
if (vxlan->cfg.addrmax &&
|
||||
vxlan->addrcnt >= vxlan->cfg.addrmax)
|
||||
return -ENOSPC;
|
||||
|
||||
netdev_dbg(vxlan->dev, "add %pM -> %pIS\n", mac, ip);
|
||||
f = vxlan_fdb_alloc(vxlan, mac, state, src_vni, ndm_flags);
|
||||
if (!f)
|
||||
return -ENOMEM;
|
||||
|
||||
rc = vxlan_fdb_append(f, ip, port, vni, ifindex, &rd);
|
||||
if (rc < 0) {
|
||||
kfree(f);
|
||||
return rc;
|
||||
}
|
||||
|
||||
++vxlan->addrcnt;
|
||||
hlist_add_head_rcu(&f->hlist,
|
||||
vxlan_fdb_head(vxlan, mac, src_vni));
|
||||
|
||||
*fdb = f;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Add new entry to forwarding table -- assumes lock held */
|
||||
static int vxlan_fdb_update(struct vxlan_dev *vxlan,
|
||||
const u8 *mac, union vxlan_addr *ip,
|
||||
__u16 state, __u16 flags,
|
||||
__be16 port, __be32 src_vni, __be32 vni,
|
||||
|
@ -688,37 +741,17 @@ static int vxlan_fdb_create(struct vxlan_dev *vxlan,
|
|||
if (!(flags & NLM_F_CREATE))
|
||||
return -ENOENT;
|
||||
|
||||
if (vxlan->cfg.addrmax &&
|
||||
vxlan->addrcnt >= vxlan->cfg.addrmax)
|
||||
return -ENOSPC;
|
||||
|
||||
/* Disallow replace to add a multicast entry */
|
||||
if ((flags & NLM_F_REPLACE) &&
|
||||
(is_multicast_ether_addr(mac) || is_zero_ether_addr(mac)))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
netdev_dbg(vxlan->dev, "add %pM -> %pIS\n", mac, ip);
|
||||
f = kmalloc(sizeof(*f), GFP_ATOMIC);
|
||||
if (!f)
|
||||
return -ENOMEM;
|
||||
|
||||
notify = 1;
|
||||
f->state = state;
|
||||
f->flags = ndm_flags;
|
||||
f->updated = f->used = jiffies;
|
||||
f->vni = src_vni;
|
||||
INIT_LIST_HEAD(&f->remotes);
|
||||
memcpy(f->eth_addr, mac, ETH_ALEN);
|
||||
|
||||
rc = vxlan_fdb_append(f, ip, port, vni, ifindex, &rd);
|
||||
if (rc < 0) {
|
||||
kfree(f);
|
||||
rc = vxlan_fdb_create(vxlan, mac, ip, state, port, src_vni,
|
||||
vni, ifindex, ndm_flags, &f);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
}
|
||||
|
||||
++vxlan->addrcnt;
|
||||
hlist_add_head_rcu(&f->hlist,
|
||||
vxlan_fdb_head(vxlan, mac, src_vni));
|
||||
notify = 1;
|
||||
}
|
||||
|
||||
if (notify) {
|
||||
|
@ -864,7 +897,7 @@ static int vxlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
|
|||
return -EAFNOSUPPORT;
|
||||
|
||||
spin_lock_bh(&vxlan->hash_lock);
|
||||
err = vxlan_fdb_create(vxlan, addr, &ip, ndm->ndm_state, flags,
|
||||
err = vxlan_fdb_update(vxlan, addr, &ip, ndm->ndm_state, flags,
|
||||
port, src_vni, vni, ifindex, ndm->ndm_flags);
|
||||
spin_unlock_bh(&vxlan->hash_lock);
|
||||
|
||||
|
@ -1007,7 +1040,7 @@ static bool vxlan_snoop(struct net_device *dev,
|
|||
|
||||
/* close off race between vxlan_flush and incoming packets */
|
||||
if (netif_running(dev))
|
||||
vxlan_fdb_create(vxlan, src_mac, src_ip,
|
||||
vxlan_fdb_update(vxlan, src_mac, src_ip,
|
||||
NUD_REACHABLE,
|
||||
NLM_F_EXCL|NLM_F_CREATE,
|
||||
vxlan->cfg.dst_port,
|
||||
|
@ -3172,7 +3205,7 @@ static int __vxlan_dev_create(struct net *net, struct net_device *dev,
|
|||
|
||||
/* create an fdb entry for a valid default destination */
|
||||
if (!vxlan_addr_any(&vxlan->default_dst.remote_ip)) {
|
||||
err = vxlan_fdb_create(vxlan, all_zeros_mac,
|
||||
err = vxlan_fdb_update(vxlan, all_zeros_mac,
|
||||
&vxlan->default_dst.remote_ip,
|
||||
NUD_REACHABLE | NUD_PERMANENT,
|
||||
NLM_F_EXCL | NLM_F_CREATE,
|
||||
|
@ -3452,7 +3485,7 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
|
|||
old_dst.remote_ifindex, 0);
|
||||
|
||||
if (!vxlan_addr_any(&dst->remote_ip)) {
|
||||
err = vxlan_fdb_create(vxlan, all_zeros_mac,
|
||||
err = vxlan_fdb_update(vxlan, all_zeros_mac,
|
||||
&dst->remote_ip,
|
||||
NUD_REACHABLE | NUD_PERMANENT,
|
||||
NLM_F_CREATE | NLM_F_APPEND,
|
||||
|
|
Loading…
Reference in New Issue