diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2019-06-25 02:32:59 +0300 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2019-06-25 02:32:59 +0300 |
commit | 1c5ba67d2277ac2faf37c61076e8b5fa312be492 (patch) | |
tree | a645a1a2f7aea7faafcd67c6ba1bfd424b95cd7d /drivers/net/vxlan.c | |
parent | dbb5281a1f84b2f93032d4864c211ce8a20811a7 (diff) | |
parent | 045df37e743c7448931131988e99e8fe0cc92a54 (diff) | |
download | linux-1c5ba67d2277ac2faf37c61076e8b5fa312be492.tar.xz |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Resolve conflict between d2912cb15bdd ("treewide: Replace GPLv2
boilerplate/reference with SPDX - rule 500") removing the GPL disclaimer
and fe03d4745675 ("Update my email address") which updates Jozsef
Kadlecsik's email.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'drivers/net/vxlan.c')
-rw-r--r-- | drivers/net/vxlan.c | 99 |
1 files changed, 61 insertions, 38 deletions
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index f31d226b5f2a..5e2323592e08 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -1,11 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * VXLAN: Virtual eXtensible Local Area Network * * Copyright (c) 2012-2013 Vyatta Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt @@ -471,14 +468,19 @@ static u32 eth_vni_hash(const unsigned char *addr, __be32 vni) return jhash_2words(key, vni, vxlan_salt) & (FDB_HASH_SIZE - 1); } +static u32 fdb_head_index(struct vxlan_dev *vxlan, const u8 *mac, __be32 vni) +{ + if (vxlan->cfg.flags & VXLAN_F_COLLECT_METADATA) + return eth_vni_hash(mac, vni); + else + return eth_hash(mac); +} + /* Hash chain to use given mac address */ static inline struct hlist_head *vxlan_fdb_head(struct vxlan_dev *vxlan, const u8 *mac, __be32 vni) { - if (vxlan->cfg.flags & VXLAN_F_COLLECT_METADATA) - return &vxlan->fdb_head[eth_vni_hash(mac, vni)]; - else - return &vxlan->fdb_head[eth_hash(mac)]; + return &vxlan->fdb_head[fdb_head_index(vxlan, mac, vni)]; } /* Look up Ethernet address in forwarding table */ @@ -593,8 +595,8 @@ int vxlan_fdb_replay(const struct net_device *dev, __be32 vni, return -EINVAL; vxlan = netdev_priv(dev); - spin_lock_bh(&vxlan->hash_lock); for (h = 0; h < FDB_HASH_SIZE; ++h) { + spin_lock_bh(&vxlan->hash_lock[h]); hlist_for_each_entry(f, &vxlan->fdb_head[h], hlist) { if (f->vni == vni) { list_for_each_entry(rdst, &f->remotes, list) { @@ -602,14 +604,16 @@ int vxlan_fdb_replay(const struct net_device *dev, __be32 vni, f, rdst, extack); if (rc) - goto out; + goto unlock; } } } + spin_unlock_bh(&vxlan->hash_lock[h]); } + return 0; -out: - spin_unlock_bh(&vxlan->hash_lock); +unlock: + spin_unlock_bh(&vxlan->hash_lock[h]); return rc; } EXPORT_SYMBOL_GPL(vxlan_fdb_replay); @@ -625,14 +629,15 @@ void vxlan_fdb_clear_offload(const struct net_device *dev, __be32 vni) return; vxlan = netdev_priv(dev); - spin_lock_bh(&vxlan->hash_lock); for (h = 0; h < FDB_HASH_SIZE; ++h) { + spin_lock_bh(&vxlan->hash_lock[h]); hlist_for_each_entry(f, &vxlan->fdb_head[h], hlist) if (f->vni == vni) list_for_each_entry(rdst, &f->remotes, list) rdst->offloaded = false; + spin_unlock_bh(&vxlan->hash_lock[h]); } - spin_unlock_bh(&vxlan->hash_lock); + } EXPORT_SYMBOL_GPL(vxlan_fdb_clear_offload); @@ -1108,6 +1113,7 @@ static int vxlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], __be16 port; __be32 src_vni, vni; u32 ifindex; + u32 hash_index; int err; if (!(ndm->ndm_state & (NUD_PERMANENT|NUD_REACHABLE))) { @@ -1126,12 +1132,13 @@ static int vxlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], if (vxlan->default_dst.remote_ip.sa.sa_family != ip.sa.sa_family) return -EAFNOSUPPORT; - spin_lock_bh(&vxlan->hash_lock); + hash_index = fdb_head_index(vxlan, addr, src_vni); + spin_lock_bh(&vxlan->hash_lock[hash_index]); err = vxlan_fdb_update(vxlan, addr, &ip, ndm->ndm_state, flags, port, src_vni, vni, ifindex, ndm->ndm_flags | NTF_VXLAN_ADDED_BY_USER, true, extack); - spin_unlock_bh(&vxlan->hash_lock); + spin_unlock_bh(&vxlan->hash_lock[hash_index]); return err; } @@ -1179,16 +1186,18 @@ static int vxlan_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[], __be32 src_vni, vni; __be16 port; u32 ifindex; + u32 hash_index; int err; err = vxlan_fdb_parse(tb, vxlan, &ip, &port, &src_vni, &vni, &ifindex); if (err) return err; - spin_lock_bh(&vxlan->hash_lock); + hash_index = fdb_head_index(vxlan, addr, src_vni); + spin_lock_bh(&vxlan->hash_lock[hash_index]); err = __vxlan_fdb_delete(vxlan, addr, ip, port, src_vni, vni, ifindex, true); - spin_unlock_bh(&vxlan->hash_lock); + spin_unlock_bh(&vxlan->hash_lock[hash_index]); return err; } @@ -1300,8 +1309,10 @@ static bool vxlan_snoop(struct net_device *dev, f->updated = jiffies; vxlan_fdb_notify(vxlan, f, rdst, RTM_NEWNEIGH, true, NULL); } else { + u32 hash_index = fdb_head_index(vxlan, src_mac, vni); + /* learned new entry */ - spin_lock(&vxlan->hash_lock); + spin_lock(&vxlan->hash_lock[hash_index]); /* close off race between vxlan_flush and incoming packets */ if (netif_running(dev)) @@ -1312,7 +1323,7 @@ static bool vxlan_snoop(struct net_device *dev, vni, vxlan->default_dst.remote_vni, ifindex, NTF_SELF, true, NULL); - spin_unlock(&vxlan->hash_lock); + spin_unlock(&vxlan->hash_lock[hash_index]); } return false; @@ -1766,7 +1777,7 @@ static int vxlan_err_lookup(struct sock *sk, struct sk_buff *skb) struct vxlanhdr *hdr; __be32 vni; - if (skb->len < VXLAN_HLEN) + if (!pskb_may_pull(skb, skb_transport_offset(skb) + VXLAN_HLEN)) return -EINVAL; hdr = vxlan_hdr(skb); @@ -2702,7 +2713,7 @@ static void vxlan_cleanup(struct timer_list *t) for (h = 0; h < FDB_HASH_SIZE; ++h) { struct hlist_node *p, *n; - spin_lock(&vxlan->hash_lock); + spin_lock(&vxlan->hash_lock[h]); hlist_for_each_safe(p, n, &vxlan->fdb_head[h]) { struct vxlan_fdb *f = container_of(p, struct vxlan_fdb, hlist); @@ -2724,7 +2735,7 @@ static void vxlan_cleanup(struct timer_list *t) } else if (time_before(timeout, next_timer)) next_timer = timeout; } - spin_unlock(&vxlan->hash_lock); + spin_unlock(&vxlan->hash_lock[h]); } mod_timer(&vxlan->age_timer, next_timer); @@ -2767,12 +2778,13 @@ static int vxlan_init(struct net_device *dev) static void vxlan_fdb_delete_default(struct vxlan_dev *vxlan, __be32 vni) { struct vxlan_fdb *f; + u32 hash_index = fdb_head_index(vxlan, all_zeros_mac, vni); - spin_lock_bh(&vxlan->hash_lock); + spin_lock_bh(&vxlan->hash_lock[hash_index]); f = __vxlan_find_mac(vxlan, all_zeros_mac, vni); if (f) vxlan_fdb_destroy(vxlan, f, true, true); - spin_unlock_bh(&vxlan->hash_lock); + spin_unlock_bh(&vxlan->hash_lock[hash_index]); } static void vxlan_uninit(struct net_device *dev) @@ -2817,9 +2829,10 @@ static void vxlan_flush(struct vxlan_dev *vxlan, bool do_all) { unsigned int h; - spin_lock_bh(&vxlan->hash_lock); for (h = 0; h < FDB_HASH_SIZE; ++h) { struct hlist_node *p, *n; + + spin_lock_bh(&vxlan->hash_lock[h]); hlist_for_each_safe(p, n, &vxlan->fdb_head[h]) { struct vxlan_fdb *f = container_of(p, struct vxlan_fdb, hlist); @@ -2829,8 +2842,8 @@ static void vxlan_flush(struct vxlan_dev *vxlan, bool do_all) if (!is_zero_ether_addr(f->eth_addr)) vxlan_fdb_destroy(vxlan, f, true, true); } + spin_unlock_bh(&vxlan->hash_lock[h]); } - spin_unlock_bh(&vxlan->hash_lock); } /* Cleanup timer and forwarding table on shutdown */ @@ -3014,7 +3027,6 @@ static void vxlan_setup(struct net_device *dev) dev->max_mtu = ETH_MAX_MTU; INIT_LIST_HEAD(&vxlan->next); - spin_lock_init(&vxlan->hash_lock); timer_setup(&vxlan->age_timer, vxlan_cleanup, TIMER_DEFERRABLE); @@ -3022,8 +3034,10 @@ static void vxlan_setup(struct net_device *dev) gro_cells_init(&vxlan->gro_cells, dev); - for (h = 0; h < FDB_HASH_SIZE; ++h) + for (h = 0; h < FDB_HASH_SIZE; ++h) { + spin_lock_init(&vxlan->hash_lock[h]); INIT_HLIST_HEAD(&vxlan->fdb_head[h]); + } } static void vxlan_ether_setup(struct net_device *dev) @@ -3917,7 +3931,9 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[], /* handle default dst entry */ if (!vxlan_addr_equal(&conf.remote_ip, &dst->remote_ip)) { - spin_lock_bh(&vxlan->hash_lock); + u32 hash_index = fdb_head_index(vxlan, all_zeros_mac, conf.vni); + + spin_lock_bh(&vxlan->hash_lock[hash_index]); if (!vxlan_addr_any(&conf.remote_ip)) { err = vxlan_fdb_update(vxlan, all_zeros_mac, &conf.remote_ip, @@ -3928,7 +3944,7 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[], conf.remote_ifindex, NTF_SELF, true, extack); if (err) { - spin_unlock_bh(&vxlan->hash_lock); + spin_unlock_bh(&vxlan->hash_lock[hash_index]); return err; } } @@ -3940,7 +3956,7 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[], dst->remote_vni, dst->remote_ifindex, true); - spin_unlock_bh(&vxlan->hash_lock); + spin_unlock_bh(&vxlan->hash_lock[hash_index]); } if (conf.age_interval != vxlan->cfg.age_interval) @@ -4195,8 +4211,11 @@ vxlan_fdb_offloaded_set(struct net_device *dev, struct vxlan_dev *vxlan = netdev_priv(dev); struct vxlan_rdst *rdst; struct vxlan_fdb *f; + u32 hash_index; + + hash_index = fdb_head_index(vxlan, fdb_info->eth_addr, fdb_info->vni); - spin_lock_bh(&vxlan->hash_lock); + spin_lock_bh(&vxlan->hash_lock[hash_index]); f = vxlan_find_mac(vxlan, fdb_info->eth_addr, fdb_info->vni); if (!f) @@ -4212,7 +4231,7 @@ vxlan_fdb_offloaded_set(struct net_device *dev, rdst->offloaded = fdb_info->offloaded; out: - spin_unlock_bh(&vxlan->hash_lock); + spin_unlock_bh(&vxlan->hash_lock[hash_index]); } static int @@ -4221,11 +4240,13 @@ vxlan_fdb_external_learn_add(struct net_device *dev, { struct vxlan_dev *vxlan = netdev_priv(dev); struct netlink_ext_ack *extack; + u32 hash_index; int err; + hash_index = fdb_head_index(vxlan, fdb_info->eth_addr, fdb_info->vni); extack = switchdev_notifier_info_to_extack(&fdb_info->info); - spin_lock_bh(&vxlan->hash_lock); + spin_lock_bh(&vxlan->hash_lock[hash_index]); err = vxlan_fdb_update(vxlan, fdb_info->eth_addr, &fdb_info->remote_ip, NUD_REACHABLE, NLM_F_CREATE | NLM_F_REPLACE, @@ -4235,7 +4256,7 @@ vxlan_fdb_external_learn_add(struct net_device *dev, fdb_info->remote_ifindex, NTF_USE | NTF_SELF | NTF_EXT_LEARNED, false, extack); - spin_unlock_bh(&vxlan->hash_lock); + spin_unlock_bh(&vxlan->hash_lock[hash_index]); return err; } @@ -4246,9 +4267,11 @@ vxlan_fdb_external_learn_del(struct net_device *dev, { struct vxlan_dev *vxlan = netdev_priv(dev); struct vxlan_fdb *f; + u32 hash_index; int err = 0; - spin_lock_bh(&vxlan->hash_lock); + hash_index = fdb_head_index(vxlan, fdb_info->eth_addr, fdb_info->vni); + spin_lock_bh(&vxlan->hash_lock[hash_index]); f = vxlan_find_mac(vxlan, fdb_info->eth_addr, fdb_info->vni); if (!f) @@ -4262,7 +4285,7 @@ vxlan_fdb_external_learn_del(struct net_device *dev, fdb_info->remote_ifindex, false); - spin_unlock_bh(&vxlan->hash_lock); + spin_unlock_bh(&vxlan->hash_lock[hash_index]); return err; } |