167653936SRoopa Prabhu // SPDX-License-Identifier: GPL-2.0-only
267653936SRoopa Prabhu /*
367653936SRoopa Prabhu * VXLAN: Virtual eXtensible Local Area Network
467653936SRoopa Prabhu *
567653936SRoopa Prabhu * Copyright (c) 2012-2013 Vyatta Inc.
667653936SRoopa Prabhu */
767653936SRoopa Prabhu
867653936SRoopa Prabhu #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
967653936SRoopa Prabhu
1067653936SRoopa Prabhu #include <linux/kernel.h>
1167653936SRoopa Prabhu #include <linux/module.h>
1267653936SRoopa Prabhu #include <linux/errno.h>
1367653936SRoopa Prabhu #include <linux/slab.h>
1467653936SRoopa Prabhu #include <linux/udp.h>
1567653936SRoopa Prabhu #include <linux/igmp.h>
1667653936SRoopa Prabhu #include <linux/if_ether.h>
1767653936SRoopa Prabhu #include <linux/ethtool.h>
1867653936SRoopa Prabhu #include <net/arp.h>
1967653936SRoopa Prabhu #include <net/ndisc.h>
2067653936SRoopa Prabhu #include <net/gro.h>
2167653936SRoopa Prabhu #include <net/ipv6_stubs.h>
2267653936SRoopa Prabhu #include <net/ip.h>
2367653936SRoopa Prabhu #include <net/icmp.h>
2467653936SRoopa Prabhu #include <net/rtnetlink.h>
2567653936SRoopa Prabhu #include <net/inet_ecn.h>
2667653936SRoopa Prabhu #include <net/net_namespace.h>
2767653936SRoopa Prabhu #include <net/netns/generic.h>
2867653936SRoopa Prabhu #include <net/tun_proto.h>
2967653936SRoopa Prabhu #include <net/vxlan.h>
3067653936SRoopa Prabhu #include <net/nexthop.h>
3167653936SRoopa Prabhu
3267653936SRoopa Prabhu #if IS_ENABLED(CONFIG_IPV6)
3367653936SRoopa Prabhu #include <net/ip6_tunnel.h>
3467653936SRoopa Prabhu #include <net/ip6_checksum.h>
3567653936SRoopa Prabhu #endif
3667653936SRoopa Prabhu
3776fc217dSRoopa Prabhu #include "vxlan_private.h"
3876fc217dSRoopa Prabhu
3967653936SRoopa Prabhu #define VXLAN_VERSION "0.1"
4067653936SRoopa Prabhu
4167653936SRoopa Prabhu #define FDB_AGE_DEFAULT 300 /* 5 min */
4267653936SRoopa Prabhu #define FDB_AGE_INTERVAL (10 * HZ) /* rescan interval */
4367653936SRoopa Prabhu
4467653936SRoopa Prabhu /* UDP port for VXLAN traffic.
4567653936SRoopa Prabhu * The IANA assigned port is 4789, but the Linux default is 8472
4667653936SRoopa Prabhu * for compatibility with early adopters.
4767653936SRoopa Prabhu */
4867653936SRoopa Prabhu static unsigned short vxlan_port __read_mostly = 8472;
4967653936SRoopa Prabhu module_param_named(udp_port, vxlan_port, ushort, 0444);
5067653936SRoopa Prabhu MODULE_PARM_DESC(udp_port, "Destination UDP port");
5167653936SRoopa Prabhu
5267653936SRoopa Prabhu static bool log_ecn_error = true;
5367653936SRoopa Prabhu module_param(log_ecn_error, bool, 0644);
5467653936SRoopa Prabhu MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN");
5567653936SRoopa Prabhu
5676fc217dSRoopa Prabhu unsigned int vxlan_net_id;
5767653936SRoopa Prabhu
5876fc217dSRoopa Prabhu const u8 all_zeros_mac[ETH_ALEN + 2];
5976fc217dSRoopa Prabhu static struct rtnl_link_ops vxlan_link_ops;
6067653936SRoopa Prabhu
6167653936SRoopa Prabhu static int vxlan_sock_add(struct vxlan_dev *vxlan);
6267653936SRoopa Prabhu
6367653936SRoopa Prabhu static void vxlan_vs_del_dev(struct vxlan_dev *vxlan);
6467653936SRoopa Prabhu
6567653936SRoopa Prabhu /* salt for hash table */
6667653936SRoopa Prabhu static u32 vxlan_salt __read_mostly;
6767653936SRoopa Prabhu
vxlan_collect_metadata(struct vxlan_sock * vs)6867653936SRoopa Prabhu static inline bool vxlan_collect_metadata(struct vxlan_sock *vs)
6967653936SRoopa Prabhu {
7067653936SRoopa Prabhu return vs->flags & VXLAN_F_COLLECT_METADATA ||
7167653936SRoopa Prabhu ip_tunnel_collect_metadata();
7267653936SRoopa Prabhu }
7367653936SRoopa Prabhu
7467653936SRoopa Prabhu /* Find VXLAN socket based on network namespace, address family, UDP port,
7567653936SRoopa Prabhu * enabled unshareable flags and socket device binding (see l3mdev with
7667653936SRoopa Prabhu * non-default VRF).
7767653936SRoopa Prabhu */
vxlan_find_sock(struct net * net,sa_family_t family,__be16 port,u32 flags,int ifindex)7867653936SRoopa Prabhu static struct vxlan_sock *vxlan_find_sock(struct net *net, sa_family_t family,
7967653936SRoopa Prabhu __be16 port, u32 flags, int ifindex)
8067653936SRoopa Prabhu {
8167653936SRoopa Prabhu struct vxlan_sock *vs;
8267653936SRoopa Prabhu
8367653936SRoopa Prabhu flags &= VXLAN_F_RCV_FLAGS;
8467653936SRoopa Prabhu
8567653936SRoopa Prabhu hlist_for_each_entry_rcu(vs, vs_head(net, port), hlist) {
8667653936SRoopa Prabhu if (inet_sk(vs->sock->sk)->inet_sport == port &&
8767653936SRoopa Prabhu vxlan_get_sk_family(vs) == family &&
8867653936SRoopa Prabhu vs->flags == flags &&
8967653936SRoopa Prabhu vs->sock->sk->sk_bound_dev_if == ifindex)
9067653936SRoopa Prabhu return vs;
9167653936SRoopa Prabhu }
9267653936SRoopa Prabhu return NULL;
9367653936SRoopa Prabhu }
9467653936SRoopa Prabhu
vxlan_vs_find_vni(struct vxlan_sock * vs,int ifindex,__be32 vni,struct vxlan_vni_node ** vninode)954095e0e1SNikolay Aleksandrov static struct vxlan_dev *vxlan_vs_find_vni(struct vxlan_sock *vs,
964095e0e1SNikolay Aleksandrov int ifindex, __be32 vni,
974095e0e1SNikolay Aleksandrov struct vxlan_vni_node **vninode)
9867653936SRoopa Prabhu {
994095e0e1SNikolay Aleksandrov struct vxlan_vni_node *vnode;
10067653936SRoopa Prabhu struct vxlan_dev_node *node;
10167653936SRoopa Prabhu
10267653936SRoopa Prabhu /* For flow based devices, map all packets to VNI 0 */
103f9c4bb0bSRoopa Prabhu if (vs->flags & VXLAN_F_COLLECT_METADATA &&
104f9c4bb0bSRoopa Prabhu !(vs->flags & VXLAN_F_VNIFILTER))
10567653936SRoopa Prabhu vni = 0;
10667653936SRoopa Prabhu
10767653936SRoopa Prabhu hlist_for_each_entry_rcu(node, vni_head(vs, vni), hlist) {
108f9c4bb0bSRoopa Prabhu if (!node->vxlan)
10967653936SRoopa Prabhu continue;
1104095e0e1SNikolay Aleksandrov vnode = NULL;
111f9c4bb0bSRoopa Prabhu if (node->vxlan->cfg.flags & VXLAN_F_VNIFILTER) {
1124095e0e1SNikolay Aleksandrov vnode = vxlan_vnifilter_lookup(node->vxlan, vni);
1134095e0e1SNikolay Aleksandrov if (!vnode)
114f9c4bb0bSRoopa Prabhu continue;
115f9c4bb0bSRoopa Prabhu } else if (node->vxlan->default_dst.remote_vni != vni) {
116f9c4bb0bSRoopa Prabhu continue;
117f9c4bb0bSRoopa Prabhu }
11867653936SRoopa Prabhu
11967653936SRoopa Prabhu if (IS_ENABLED(CONFIG_IPV6)) {
12067653936SRoopa Prabhu const struct vxlan_config *cfg = &node->vxlan->cfg;
12167653936SRoopa Prabhu
12267653936SRoopa Prabhu if ((cfg->flags & VXLAN_F_IPV6_LINKLOCAL) &&
12367653936SRoopa Prabhu cfg->remote_ifindex != ifindex)
12467653936SRoopa Prabhu continue;
12567653936SRoopa Prabhu }
12667653936SRoopa Prabhu
1274095e0e1SNikolay Aleksandrov if (vninode)
1284095e0e1SNikolay Aleksandrov *vninode = vnode;
12967653936SRoopa Prabhu return node->vxlan;
13067653936SRoopa Prabhu }
13167653936SRoopa Prabhu
13267653936SRoopa Prabhu return NULL;
13367653936SRoopa Prabhu }
13467653936SRoopa Prabhu
13567653936SRoopa Prabhu /* Look up VNI in a per net namespace table */
vxlan_find_vni(struct net * net,int ifindex,__be32 vni,sa_family_t family,__be16 port,u32 flags)13667653936SRoopa Prabhu static struct vxlan_dev *vxlan_find_vni(struct net *net, int ifindex,
13767653936SRoopa Prabhu __be32 vni, sa_family_t family,
13867653936SRoopa Prabhu __be16 port, u32 flags)
13967653936SRoopa Prabhu {
14067653936SRoopa Prabhu struct vxlan_sock *vs;
14167653936SRoopa Prabhu
14267653936SRoopa Prabhu vs = vxlan_find_sock(net, family, port, flags, ifindex);
14367653936SRoopa Prabhu if (!vs)
14467653936SRoopa Prabhu return NULL;
14567653936SRoopa Prabhu
1464095e0e1SNikolay Aleksandrov return vxlan_vs_find_vni(vs, ifindex, vni, NULL);
14767653936SRoopa Prabhu }
14867653936SRoopa Prabhu
14967653936SRoopa Prabhu /* Fill in neighbour message in skbuff. */
vxlan_fdb_info(struct sk_buff * skb,struct vxlan_dev * vxlan,const struct vxlan_fdb * fdb,u32 portid,u32 seq,int type,unsigned int flags,const struct vxlan_rdst * rdst)15067653936SRoopa Prabhu static int vxlan_fdb_info(struct sk_buff *skb, struct vxlan_dev *vxlan,
15167653936SRoopa Prabhu const struct vxlan_fdb *fdb,
15267653936SRoopa Prabhu u32 portid, u32 seq, int type, unsigned int flags,
15367653936SRoopa Prabhu const struct vxlan_rdst *rdst)
15467653936SRoopa Prabhu {
15567653936SRoopa Prabhu unsigned long now = jiffies;
15667653936SRoopa Prabhu struct nda_cacheinfo ci;
15767653936SRoopa Prabhu bool send_ip, send_eth;
15867653936SRoopa Prabhu struct nlmsghdr *nlh;
15967653936SRoopa Prabhu struct nexthop *nh;
16067653936SRoopa Prabhu struct ndmsg *ndm;
16167653936SRoopa Prabhu int nh_family;
16267653936SRoopa Prabhu u32 nh_id;
16367653936SRoopa Prabhu
16467653936SRoopa Prabhu nlh = nlmsg_put(skb, portid, seq, type, sizeof(*ndm), flags);
16567653936SRoopa Prabhu if (nlh == NULL)
16667653936SRoopa Prabhu return -EMSGSIZE;
16767653936SRoopa Prabhu
16867653936SRoopa Prabhu ndm = nlmsg_data(nlh);
16967653936SRoopa Prabhu memset(ndm, 0, sizeof(*ndm));
17067653936SRoopa Prabhu
17167653936SRoopa Prabhu send_eth = send_ip = true;
17267653936SRoopa Prabhu
17367653936SRoopa Prabhu rcu_read_lock();
17467653936SRoopa Prabhu nh = rcu_dereference(fdb->nh);
17567653936SRoopa Prabhu if (nh) {
17667653936SRoopa Prabhu nh_family = nexthop_get_family(nh);
17767653936SRoopa Prabhu nh_id = nh->id;
17867653936SRoopa Prabhu }
17967653936SRoopa Prabhu rcu_read_unlock();
18067653936SRoopa Prabhu
18167653936SRoopa Prabhu if (type == RTM_GETNEIGH) {
18267653936SRoopa Prabhu if (rdst) {
18367653936SRoopa Prabhu send_ip = !vxlan_addr_any(&rdst->remote_ip);
18467653936SRoopa Prabhu ndm->ndm_family = send_ip ? rdst->remote_ip.sa.sa_family : AF_INET;
18567653936SRoopa Prabhu } else if (nh) {
18667653936SRoopa Prabhu ndm->ndm_family = nh_family;
18767653936SRoopa Prabhu }
18867653936SRoopa Prabhu send_eth = !is_zero_ether_addr(fdb->eth_addr);
18967653936SRoopa Prabhu } else
19067653936SRoopa Prabhu ndm->ndm_family = AF_BRIDGE;
19167653936SRoopa Prabhu ndm->ndm_state = fdb->state;
19267653936SRoopa Prabhu ndm->ndm_ifindex = vxlan->dev->ifindex;
19367653936SRoopa Prabhu ndm->ndm_flags = fdb->flags;
19467653936SRoopa Prabhu if (rdst && rdst->offloaded)
19567653936SRoopa Prabhu ndm->ndm_flags |= NTF_OFFLOADED;
19667653936SRoopa Prabhu ndm->ndm_type = RTN_UNICAST;
19767653936SRoopa Prabhu
19867653936SRoopa Prabhu if (!net_eq(dev_net(vxlan->dev), vxlan->net) &&
19967653936SRoopa Prabhu nla_put_s32(skb, NDA_LINK_NETNSID,
20067653936SRoopa Prabhu peernet2id(dev_net(vxlan->dev), vxlan->net)))
20167653936SRoopa Prabhu goto nla_put_failure;
20267653936SRoopa Prabhu
20367653936SRoopa Prabhu if (send_eth && nla_put(skb, NDA_LLADDR, ETH_ALEN, &fdb->eth_addr))
20467653936SRoopa Prabhu goto nla_put_failure;
20567653936SRoopa Prabhu if (nh) {
20667653936SRoopa Prabhu if (nla_put_u32(skb, NDA_NH_ID, nh_id))
20767653936SRoopa Prabhu goto nla_put_failure;
20867653936SRoopa Prabhu } else if (rdst) {
20967653936SRoopa Prabhu if (send_ip && vxlan_nla_put_addr(skb, NDA_DST,
21067653936SRoopa Prabhu &rdst->remote_ip))
21167653936SRoopa Prabhu goto nla_put_failure;
21267653936SRoopa Prabhu
21367653936SRoopa Prabhu if (rdst->remote_port &&
21467653936SRoopa Prabhu rdst->remote_port != vxlan->cfg.dst_port &&
21567653936SRoopa Prabhu nla_put_be16(skb, NDA_PORT, rdst->remote_port))
21667653936SRoopa Prabhu goto nla_put_failure;
21767653936SRoopa Prabhu if (rdst->remote_vni != vxlan->default_dst.remote_vni &&
21867653936SRoopa Prabhu nla_put_u32(skb, NDA_VNI, be32_to_cpu(rdst->remote_vni)))
21967653936SRoopa Prabhu goto nla_put_failure;
22067653936SRoopa Prabhu if (rdst->remote_ifindex &&
22167653936SRoopa Prabhu nla_put_u32(skb, NDA_IFINDEX, rdst->remote_ifindex))
22267653936SRoopa Prabhu goto nla_put_failure;
22367653936SRoopa Prabhu }
22467653936SRoopa Prabhu
22567653936SRoopa Prabhu if ((vxlan->cfg.flags & VXLAN_F_COLLECT_METADATA) && fdb->vni &&
22667653936SRoopa Prabhu nla_put_u32(skb, NDA_SRC_VNI,
22767653936SRoopa Prabhu be32_to_cpu(fdb->vni)))
22867653936SRoopa Prabhu goto nla_put_failure;
22967653936SRoopa Prabhu
23067653936SRoopa Prabhu ci.ndm_used = jiffies_to_clock_t(now - fdb->used);
23167653936SRoopa Prabhu ci.ndm_confirmed = 0;
23267653936SRoopa Prabhu ci.ndm_updated = jiffies_to_clock_t(now - fdb->updated);
23367653936SRoopa Prabhu ci.ndm_refcnt = 0;
23467653936SRoopa Prabhu
23567653936SRoopa Prabhu if (nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci))
23667653936SRoopa Prabhu goto nla_put_failure;
23767653936SRoopa Prabhu
23867653936SRoopa Prabhu nlmsg_end(skb, nlh);
23967653936SRoopa Prabhu return 0;
24067653936SRoopa Prabhu
24167653936SRoopa Prabhu nla_put_failure:
24267653936SRoopa Prabhu nlmsg_cancel(skb, nlh);
24367653936SRoopa Prabhu return -EMSGSIZE;
24467653936SRoopa Prabhu }
24567653936SRoopa Prabhu
vxlan_nlmsg_size(void)24667653936SRoopa Prabhu static inline size_t vxlan_nlmsg_size(void)
24767653936SRoopa Prabhu {
24867653936SRoopa Prabhu return NLMSG_ALIGN(sizeof(struct ndmsg))
24967653936SRoopa Prabhu + nla_total_size(ETH_ALEN) /* NDA_LLADDR */
25067653936SRoopa Prabhu + nla_total_size(sizeof(struct in6_addr)) /* NDA_DST */
25167653936SRoopa Prabhu + nla_total_size(sizeof(__be16)) /* NDA_PORT */
25267653936SRoopa Prabhu + nla_total_size(sizeof(__be32)) /* NDA_VNI */
25367653936SRoopa Prabhu + nla_total_size(sizeof(__u32)) /* NDA_IFINDEX */
25467653936SRoopa Prabhu + nla_total_size(sizeof(__s32)) /* NDA_LINK_NETNSID */
25567653936SRoopa Prabhu + nla_total_size(sizeof(struct nda_cacheinfo));
25667653936SRoopa Prabhu }
25767653936SRoopa Prabhu
__vxlan_fdb_notify(struct vxlan_dev * vxlan,struct vxlan_fdb * fdb,struct vxlan_rdst * rd,int type)25867653936SRoopa Prabhu static void __vxlan_fdb_notify(struct vxlan_dev *vxlan, struct vxlan_fdb *fdb,
25967653936SRoopa Prabhu struct vxlan_rdst *rd, int type)
26067653936SRoopa Prabhu {
26167653936SRoopa Prabhu struct net *net = dev_net(vxlan->dev);
26267653936SRoopa Prabhu struct sk_buff *skb;
26367653936SRoopa Prabhu int err = -ENOBUFS;
26467653936SRoopa Prabhu
26567653936SRoopa Prabhu skb = nlmsg_new(vxlan_nlmsg_size(), GFP_ATOMIC);
26667653936SRoopa Prabhu if (skb == NULL)
26767653936SRoopa Prabhu goto errout;
26867653936SRoopa Prabhu
26967653936SRoopa Prabhu err = vxlan_fdb_info(skb, vxlan, fdb, 0, 0, type, 0, rd);
27067653936SRoopa Prabhu if (err < 0) {
27167653936SRoopa Prabhu /* -EMSGSIZE implies BUG in vxlan_nlmsg_size() */
27267653936SRoopa Prabhu WARN_ON(err == -EMSGSIZE);
27367653936SRoopa Prabhu kfree_skb(skb);
27467653936SRoopa Prabhu goto errout;
27567653936SRoopa Prabhu }
27667653936SRoopa Prabhu
27767653936SRoopa Prabhu rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
27867653936SRoopa Prabhu return;
27967653936SRoopa Prabhu errout:
28067653936SRoopa Prabhu if (err < 0)
28167653936SRoopa Prabhu rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
28267653936SRoopa Prabhu }
28367653936SRoopa Prabhu
vxlan_fdb_switchdev_notifier_info(const struct vxlan_dev * vxlan,const struct vxlan_fdb * fdb,const struct vxlan_rdst * rd,struct netlink_ext_ack * extack,struct switchdev_notifier_vxlan_fdb_info * fdb_info)28467653936SRoopa Prabhu static void vxlan_fdb_switchdev_notifier_info(const struct vxlan_dev *vxlan,
28567653936SRoopa Prabhu const struct vxlan_fdb *fdb,
28667653936SRoopa Prabhu const struct vxlan_rdst *rd,
28767653936SRoopa Prabhu struct netlink_ext_ack *extack,
28867653936SRoopa Prabhu struct switchdev_notifier_vxlan_fdb_info *fdb_info)
28967653936SRoopa Prabhu {
29067653936SRoopa Prabhu fdb_info->info.dev = vxlan->dev;
29167653936SRoopa Prabhu fdb_info->info.extack = extack;
29267653936SRoopa Prabhu fdb_info->remote_ip = rd->remote_ip;
29367653936SRoopa Prabhu fdb_info->remote_port = rd->remote_port;
29467653936SRoopa Prabhu fdb_info->remote_vni = rd->remote_vni;
29567653936SRoopa Prabhu fdb_info->remote_ifindex = rd->remote_ifindex;
29667653936SRoopa Prabhu memcpy(fdb_info->eth_addr, fdb->eth_addr, ETH_ALEN);
29767653936SRoopa Prabhu fdb_info->vni = fdb->vni;
29867653936SRoopa Prabhu fdb_info->offloaded = rd->offloaded;
29967653936SRoopa Prabhu fdb_info->added_by_user = fdb->flags & NTF_VXLAN_ADDED_BY_USER;
30067653936SRoopa Prabhu }
30167653936SRoopa Prabhu
vxlan_fdb_switchdev_call_notifiers(struct vxlan_dev * vxlan,struct vxlan_fdb * fdb,struct vxlan_rdst * rd,bool adding,struct netlink_ext_ack * extack)30267653936SRoopa Prabhu static int vxlan_fdb_switchdev_call_notifiers(struct vxlan_dev *vxlan,
30367653936SRoopa Prabhu struct vxlan_fdb *fdb,
30467653936SRoopa Prabhu struct vxlan_rdst *rd,
30567653936SRoopa Prabhu bool adding,
30667653936SRoopa Prabhu struct netlink_ext_ack *extack)
30767653936SRoopa Prabhu {
30867653936SRoopa Prabhu struct switchdev_notifier_vxlan_fdb_info info;
30967653936SRoopa Prabhu enum switchdev_notifier_type notifier_type;
31067653936SRoopa Prabhu int ret;
31167653936SRoopa Prabhu
31267653936SRoopa Prabhu if (WARN_ON(!rd))
31367653936SRoopa Prabhu return 0;
31467653936SRoopa Prabhu
31567653936SRoopa Prabhu notifier_type = adding ? SWITCHDEV_VXLAN_FDB_ADD_TO_DEVICE
31667653936SRoopa Prabhu : SWITCHDEV_VXLAN_FDB_DEL_TO_DEVICE;
31767653936SRoopa Prabhu vxlan_fdb_switchdev_notifier_info(vxlan, fdb, rd, NULL, &info);
31867653936SRoopa Prabhu ret = call_switchdev_notifiers(notifier_type, vxlan->dev,
31967653936SRoopa Prabhu &info.info, extack);
32067653936SRoopa Prabhu return notifier_to_errno(ret);
32167653936SRoopa Prabhu }
32267653936SRoopa Prabhu
vxlan_fdb_notify(struct vxlan_dev * vxlan,struct vxlan_fdb * fdb,struct vxlan_rdst * rd,int type,bool swdev_notify,struct netlink_ext_ack * extack)32367653936SRoopa Prabhu static int vxlan_fdb_notify(struct vxlan_dev *vxlan, struct vxlan_fdb *fdb,
32467653936SRoopa Prabhu struct vxlan_rdst *rd, int type, bool swdev_notify,
32567653936SRoopa Prabhu struct netlink_ext_ack *extack)
32667653936SRoopa Prabhu {
32767653936SRoopa Prabhu int err;
32867653936SRoopa Prabhu
32967653936SRoopa Prabhu if (swdev_notify && rd) {
33067653936SRoopa Prabhu switch (type) {
33167653936SRoopa Prabhu case RTM_NEWNEIGH:
33267653936SRoopa Prabhu err = vxlan_fdb_switchdev_call_notifiers(vxlan, fdb, rd,
33367653936SRoopa Prabhu true, extack);
33467653936SRoopa Prabhu if (err)
33567653936SRoopa Prabhu return err;
33667653936SRoopa Prabhu break;
33767653936SRoopa Prabhu case RTM_DELNEIGH:
33867653936SRoopa Prabhu vxlan_fdb_switchdev_call_notifiers(vxlan, fdb, rd,
33967653936SRoopa Prabhu false, extack);
34067653936SRoopa Prabhu break;
34167653936SRoopa Prabhu }
34267653936SRoopa Prabhu }
34367653936SRoopa Prabhu
34467653936SRoopa Prabhu __vxlan_fdb_notify(vxlan, fdb, rd, type);
34567653936SRoopa Prabhu return 0;
34667653936SRoopa Prabhu }
34767653936SRoopa Prabhu
vxlan_ip_miss(struct net_device * dev,union vxlan_addr * ipa)34867653936SRoopa Prabhu static void vxlan_ip_miss(struct net_device *dev, union vxlan_addr *ipa)
34967653936SRoopa Prabhu {
35067653936SRoopa Prabhu struct vxlan_dev *vxlan = netdev_priv(dev);
35167653936SRoopa Prabhu struct vxlan_fdb f = {
35267653936SRoopa Prabhu .state = NUD_STALE,
35367653936SRoopa Prabhu };
35467653936SRoopa Prabhu struct vxlan_rdst remote = {
35567653936SRoopa Prabhu .remote_ip = *ipa, /* goes to NDA_DST */
35667653936SRoopa Prabhu .remote_vni = cpu_to_be32(VXLAN_N_VID),
35767653936SRoopa Prabhu };
35867653936SRoopa Prabhu
35967653936SRoopa Prabhu vxlan_fdb_notify(vxlan, &f, &remote, RTM_GETNEIGH, true, NULL);
36067653936SRoopa Prabhu }
36167653936SRoopa Prabhu
vxlan_fdb_miss(struct vxlan_dev * vxlan,const u8 eth_addr[ETH_ALEN])36267653936SRoopa Prabhu static void vxlan_fdb_miss(struct vxlan_dev *vxlan, const u8 eth_addr[ETH_ALEN])
36367653936SRoopa Prabhu {
36467653936SRoopa Prabhu struct vxlan_fdb f = {
36567653936SRoopa Prabhu .state = NUD_STALE,
36667653936SRoopa Prabhu };
36767653936SRoopa Prabhu struct vxlan_rdst remote = { };
36867653936SRoopa Prabhu
36967653936SRoopa Prabhu memcpy(f.eth_addr, eth_addr, ETH_ALEN);
37067653936SRoopa Prabhu
37167653936SRoopa Prabhu vxlan_fdb_notify(vxlan, &f, &remote, RTM_GETNEIGH, true, NULL);
37267653936SRoopa Prabhu }
37367653936SRoopa Prabhu
37467653936SRoopa Prabhu /* Hash Ethernet address */
eth_hash(const unsigned char * addr)37567653936SRoopa Prabhu static u32 eth_hash(const unsigned char *addr)
37667653936SRoopa Prabhu {
37767653936SRoopa Prabhu u64 value = get_unaligned((u64 *)addr);
37867653936SRoopa Prabhu
37967653936SRoopa Prabhu /* only want 6 bytes */
38067653936SRoopa Prabhu #ifdef __BIG_ENDIAN
38167653936SRoopa Prabhu value >>= 16;
38267653936SRoopa Prabhu #else
38367653936SRoopa Prabhu value <<= 16;
38467653936SRoopa Prabhu #endif
38567653936SRoopa Prabhu return hash_64(value, FDB_HASH_BITS);
38667653936SRoopa Prabhu }
38767653936SRoopa Prabhu
eth_vni_hash(const unsigned char * addr,__be32 vni)388c63053e0SRoopa Prabhu u32 eth_vni_hash(const unsigned char *addr, __be32 vni)
38967653936SRoopa Prabhu {
39067653936SRoopa Prabhu /* use 1 byte of OUI and 3 bytes of NIC */
39167653936SRoopa Prabhu u32 key = get_unaligned((u32 *)(addr + 2));
39267653936SRoopa Prabhu
39367653936SRoopa Prabhu return jhash_2words(key, vni, vxlan_salt) & (FDB_HASH_SIZE - 1);
39467653936SRoopa Prabhu }
39567653936SRoopa Prabhu
fdb_head_index(struct vxlan_dev * vxlan,const u8 * mac,__be32 vni)396c63053e0SRoopa Prabhu u32 fdb_head_index(struct vxlan_dev *vxlan, const u8 *mac, __be32 vni)
39767653936SRoopa Prabhu {
39867653936SRoopa Prabhu if (vxlan->cfg.flags & VXLAN_F_COLLECT_METADATA)
39967653936SRoopa Prabhu return eth_vni_hash(mac, vni);
40067653936SRoopa Prabhu else
40167653936SRoopa Prabhu return eth_hash(mac);
40267653936SRoopa Prabhu }
40367653936SRoopa Prabhu
40467653936SRoopa Prabhu /* Hash chain to use given mac address */
vxlan_fdb_head(struct vxlan_dev * vxlan,const u8 * mac,__be32 vni)40567653936SRoopa Prabhu static inline struct hlist_head *vxlan_fdb_head(struct vxlan_dev *vxlan,
40667653936SRoopa Prabhu const u8 *mac, __be32 vni)
40767653936SRoopa Prabhu {
40867653936SRoopa Prabhu return &vxlan->fdb_head[fdb_head_index(vxlan, mac, vni)];
40967653936SRoopa Prabhu }
41067653936SRoopa Prabhu
41167653936SRoopa Prabhu /* Look up Ethernet address in forwarding table */
__vxlan_find_mac(struct vxlan_dev * vxlan,const u8 * mac,__be32 vni)41267653936SRoopa Prabhu static struct vxlan_fdb *__vxlan_find_mac(struct vxlan_dev *vxlan,
41367653936SRoopa Prabhu const u8 *mac, __be32 vni)
41467653936SRoopa Prabhu {
41567653936SRoopa Prabhu struct hlist_head *head = vxlan_fdb_head(vxlan, mac, vni);
41667653936SRoopa Prabhu struct vxlan_fdb *f;
41767653936SRoopa Prabhu
41867653936SRoopa Prabhu hlist_for_each_entry_rcu(f, head, hlist) {
41967653936SRoopa Prabhu if (ether_addr_equal(mac, f->eth_addr)) {
42067653936SRoopa Prabhu if (vxlan->cfg.flags & VXLAN_F_COLLECT_METADATA) {
42167653936SRoopa Prabhu if (vni == f->vni)
42267653936SRoopa Prabhu return f;
42367653936SRoopa Prabhu } else {
42467653936SRoopa Prabhu return f;
42567653936SRoopa Prabhu }
42667653936SRoopa Prabhu }
42767653936SRoopa Prabhu }
42867653936SRoopa Prabhu
42967653936SRoopa Prabhu return NULL;
43067653936SRoopa Prabhu }
43167653936SRoopa Prabhu
vxlan_find_mac(struct vxlan_dev * vxlan,const u8 * mac,__be32 vni)43267653936SRoopa Prabhu static struct vxlan_fdb *vxlan_find_mac(struct vxlan_dev *vxlan,
43367653936SRoopa Prabhu const u8 *mac, __be32 vni)
43467653936SRoopa Prabhu {
43567653936SRoopa Prabhu struct vxlan_fdb *f;
43667653936SRoopa Prabhu
43767653936SRoopa Prabhu f = __vxlan_find_mac(vxlan, mac, vni);
43867653936SRoopa Prabhu if (f && f->used != jiffies)
43967653936SRoopa Prabhu f->used = jiffies;
44067653936SRoopa Prabhu
44167653936SRoopa Prabhu return f;
44267653936SRoopa Prabhu }
44367653936SRoopa Prabhu
44467653936SRoopa Prabhu /* caller should hold vxlan->hash_lock */
vxlan_fdb_find_rdst(struct vxlan_fdb * f,union vxlan_addr * ip,__be16 port,__be32 vni,__u32 ifindex)44567653936SRoopa Prabhu static struct vxlan_rdst *vxlan_fdb_find_rdst(struct vxlan_fdb *f,
44667653936SRoopa Prabhu union vxlan_addr *ip, __be16 port,
44767653936SRoopa Prabhu __be32 vni, __u32 ifindex)
44867653936SRoopa Prabhu {
44967653936SRoopa Prabhu struct vxlan_rdst *rd;
45067653936SRoopa Prabhu
45167653936SRoopa Prabhu list_for_each_entry(rd, &f->remotes, list) {
45267653936SRoopa Prabhu if (vxlan_addr_equal(&rd->remote_ip, ip) &&
45367653936SRoopa Prabhu rd->remote_port == port &&
45467653936SRoopa Prabhu rd->remote_vni == vni &&
45567653936SRoopa Prabhu rd->remote_ifindex == ifindex)
45667653936SRoopa Prabhu return rd;
45767653936SRoopa Prabhu }
45867653936SRoopa Prabhu
45967653936SRoopa Prabhu return NULL;
46067653936SRoopa Prabhu }
46167653936SRoopa Prabhu
vxlan_fdb_find_uc(struct net_device * dev,const u8 * mac,__be32 vni,struct switchdev_notifier_vxlan_fdb_info * fdb_info)46267653936SRoopa Prabhu int vxlan_fdb_find_uc(struct net_device *dev, const u8 *mac, __be32 vni,
46367653936SRoopa Prabhu struct switchdev_notifier_vxlan_fdb_info *fdb_info)
46467653936SRoopa Prabhu {
46567653936SRoopa Prabhu struct vxlan_dev *vxlan = netdev_priv(dev);
46667653936SRoopa Prabhu u8 eth_addr[ETH_ALEN + 2] = { 0 };
46767653936SRoopa Prabhu struct vxlan_rdst *rdst;
46867653936SRoopa Prabhu struct vxlan_fdb *f;
46967653936SRoopa Prabhu int rc = 0;
47067653936SRoopa Prabhu
47167653936SRoopa Prabhu if (is_multicast_ether_addr(mac) ||
47267653936SRoopa Prabhu is_zero_ether_addr(mac))
47367653936SRoopa Prabhu return -EINVAL;
47467653936SRoopa Prabhu
47567653936SRoopa Prabhu ether_addr_copy(eth_addr, mac);
47667653936SRoopa Prabhu
47767653936SRoopa Prabhu rcu_read_lock();
47867653936SRoopa Prabhu
47967653936SRoopa Prabhu f = __vxlan_find_mac(vxlan, eth_addr, vni);
48067653936SRoopa Prabhu if (!f) {
48167653936SRoopa Prabhu rc = -ENOENT;
48267653936SRoopa Prabhu goto out;
48367653936SRoopa Prabhu }
48467653936SRoopa Prabhu
48567653936SRoopa Prabhu rdst = first_remote_rcu(f);
48667653936SRoopa Prabhu vxlan_fdb_switchdev_notifier_info(vxlan, f, rdst, NULL, fdb_info);
48767653936SRoopa Prabhu
48867653936SRoopa Prabhu out:
48967653936SRoopa Prabhu rcu_read_unlock();
49067653936SRoopa Prabhu return rc;
49167653936SRoopa Prabhu }
49267653936SRoopa Prabhu EXPORT_SYMBOL_GPL(vxlan_fdb_find_uc);
49367653936SRoopa Prabhu
vxlan_fdb_notify_one(struct notifier_block * nb,const struct vxlan_dev * vxlan,const struct vxlan_fdb * f,const struct vxlan_rdst * rdst,struct netlink_ext_ack * extack)49467653936SRoopa Prabhu static int vxlan_fdb_notify_one(struct notifier_block *nb,
49567653936SRoopa Prabhu const struct vxlan_dev *vxlan,
49667653936SRoopa Prabhu const struct vxlan_fdb *f,
49767653936SRoopa Prabhu const struct vxlan_rdst *rdst,
49867653936SRoopa Prabhu struct netlink_ext_ack *extack)
49967653936SRoopa Prabhu {
50067653936SRoopa Prabhu struct switchdev_notifier_vxlan_fdb_info fdb_info;
50167653936SRoopa Prabhu int rc;
50267653936SRoopa Prabhu
50367653936SRoopa Prabhu vxlan_fdb_switchdev_notifier_info(vxlan, f, rdst, extack, &fdb_info);
50467653936SRoopa Prabhu rc = nb->notifier_call(nb, SWITCHDEV_VXLAN_FDB_ADD_TO_DEVICE,
50567653936SRoopa Prabhu &fdb_info);
50667653936SRoopa Prabhu return notifier_to_errno(rc);
50767653936SRoopa Prabhu }
50867653936SRoopa Prabhu
vxlan_fdb_replay(const struct net_device * dev,__be32 vni,struct notifier_block * nb,struct netlink_ext_ack * extack)50967653936SRoopa Prabhu int vxlan_fdb_replay(const struct net_device *dev, __be32 vni,
51067653936SRoopa Prabhu struct notifier_block *nb,
51167653936SRoopa Prabhu struct netlink_ext_ack *extack)
51267653936SRoopa Prabhu {
51367653936SRoopa Prabhu struct vxlan_dev *vxlan;
51467653936SRoopa Prabhu struct vxlan_rdst *rdst;
51567653936SRoopa Prabhu struct vxlan_fdb *f;
51667653936SRoopa Prabhu unsigned int h;
51767653936SRoopa Prabhu int rc = 0;
51867653936SRoopa Prabhu
51967653936SRoopa Prabhu if (!netif_is_vxlan(dev))
52067653936SRoopa Prabhu return -EINVAL;
52167653936SRoopa Prabhu vxlan = netdev_priv(dev);
52267653936SRoopa Prabhu
52367653936SRoopa Prabhu for (h = 0; h < FDB_HASH_SIZE; ++h) {
52467653936SRoopa Prabhu spin_lock_bh(&vxlan->hash_lock[h]);
52567653936SRoopa Prabhu hlist_for_each_entry(f, &vxlan->fdb_head[h], hlist) {
52667653936SRoopa Prabhu if (f->vni == vni) {
52767653936SRoopa Prabhu list_for_each_entry(rdst, &f->remotes, list) {
52867653936SRoopa Prabhu rc = vxlan_fdb_notify_one(nb, vxlan,
52967653936SRoopa Prabhu f, rdst,
53067653936SRoopa Prabhu extack);
53167653936SRoopa Prabhu if (rc)
53267653936SRoopa Prabhu goto unlock;
53367653936SRoopa Prabhu }
53467653936SRoopa Prabhu }
53567653936SRoopa Prabhu }
53667653936SRoopa Prabhu spin_unlock_bh(&vxlan->hash_lock[h]);
53767653936SRoopa Prabhu }
53867653936SRoopa Prabhu return 0;
53967653936SRoopa Prabhu
54067653936SRoopa Prabhu unlock:
54167653936SRoopa Prabhu spin_unlock_bh(&vxlan->hash_lock[h]);
54267653936SRoopa Prabhu return rc;
54367653936SRoopa Prabhu }
54467653936SRoopa Prabhu EXPORT_SYMBOL_GPL(vxlan_fdb_replay);
54567653936SRoopa Prabhu
vxlan_fdb_clear_offload(const struct net_device * dev,__be32 vni)54667653936SRoopa Prabhu void vxlan_fdb_clear_offload(const struct net_device *dev, __be32 vni)
54767653936SRoopa Prabhu {
54867653936SRoopa Prabhu struct vxlan_dev *vxlan;
54967653936SRoopa Prabhu struct vxlan_rdst *rdst;
55067653936SRoopa Prabhu struct vxlan_fdb *f;
55167653936SRoopa Prabhu unsigned int h;
55267653936SRoopa Prabhu
55367653936SRoopa Prabhu if (!netif_is_vxlan(dev))
55467653936SRoopa Prabhu return;
55567653936SRoopa Prabhu vxlan = netdev_priv(dev);
55667653936SRoopa Prabhu
55767653936SRoopa Prabhu for (h = 0; h < FDB_HASH_SIZE; ++h) {
55867653936SRoopa Prabhu spin_lock_bh(&vxlan->hash_lock[h]);
55967653936SRoopa Prabhu hlist_for_each_entry(f, &vxlan->fdb_head[h], hlist)
56067653936SRoopa Prabhu if (f->vni == vni)
56167653936SRoopa Prabhu list_for_each_entry(rdst, &f->remotes, list)
56267653936SRoopa Prabhu rdst->offloaded = false;
56367653936SRoopa Prabhu spin_unlock_bh(&vxlan->hash_lock[h]);
56467653936SRoopa Prabhu }
56567653936SRoopa Prabhu
56667653936SRoopa Prabhu }
56767653936SRoopa Prabhu EXPORT_SYMBOL_GPL(vxlan_fdb_clear_offload);
56867653936SRoopa Prabhu
56967653936SRoopa Prabhu /* Replace destination of unicast mac */
vxlan_fdb_replace(struct vxlan_fdb * f,union vxlan_addr * ip,__be16 port,__be32 vni,__u32 ifindex,struct vxlan_rdst * oldrd)57067653936SRoopa Prabhu static int vxlan_fdb_replace(struct vxlan_fdb *f,
57167653936SRoopa Prabhu union vxlan_addr *ip, __be16 port, __be32 vni,
57267653936SRoopa Prabhu __u32 ifindex, struct vxlan_rdst *oldrd)
57367653936SRoopa Prabhu {
57467653936SRoopa Prabhu struct vxlan_rdst *rd;
57567653936SRoopa Prabhu
57667653936SRoopa Prabhu rd = vxlan_fdb_find_rdst(f, ip, port, vni, ifindex);
57767653936SRoopa Prabhu if (rd)
57867653936SRoopa Prabhu return 0;
57967653936SRoopa Prabhu
58067653936SRoopa Prabhu rd = list_first_entry_or_null(&f->remotes, struct vxlan_rdst, list);
58167653936SRoopa Prabhu if (!rd)
58267653936SRoopa Prabhu return 0;
58367653936SRoopa Prabhu
58467653936SRoopa Prabhu *oldrd = *rd;
58567653936SRoopa Prabhu dst_cache_reset(&rd->dst_cache);
58667653936SRoopa Prabhu rd->remote_ip = *ip;
58767653936SRoopa Prabhu rd->remote_port = port;
58867653936SRoopa Prabhu rd->remote_vni = vni;
58967653936SRoopa Prabhu rd->remote_ifindex = ifindex;
59067653936SRoopa Prabhu rd->offloaded = false;
59167653936SRoopa Prabhu return 1;
59267653936SRoopa Prabhu }
59367653936SRoopa Prabhu
59467653936SRoopa Prabhu /* Add/update destinations for multicast */
vxlan_fdb_append(struct vxlan_fdb * f,union vxlan_addr * ip,__be16 port,__be32 vni,__u32 ifindex,struct vxlan_rdst ** rdp)59567653936SRoopa Prabhu static int vxlan_fdb_append(struct vxlan_fdb *f,
59667653936SRoopa Prabhu union vxlan_addr *ip, __be16 port, __be32 vni,
59767653936SRoopa Prabhu __u32 ifindex, struct vxlan_rdst **rdp)
59867653936SRoopa Prabhu {
59967653936SRoopa Prabhu struct vxlan_rdst *rd;
60067653936SRoopa Prabhu
60167653936SRoopa Prabhu rd = vxlan_fdb_find_rdst(f, ip, port, vni, ifindex);
60267653936SRoopa Prabhu if (rd)
60367653936SRoopa Prabhu return 0;
60467653936SRoopa Prabhu
60567653936SRoopa Prabhu rd = kmalloc(sizeof(*rd), GFP_ATOMIC);
60667653936SRoopa Prabhu if (rd == NULL)
6077cea5560SHongbin Wang return -ENOMEM;
60867653936SRoopa Prabhu
60967653936SRoopa Prabhu if (dst_cache_init(&rd->dst_cache, GFP_ATOMIC)) {
61067653936SRoopa Prabhu kfree(rd);
6117cea5560SHongbin Wang return -ENOMEM;
61267653936SRoopa Prabhu }
61367653936SRoopa Prabhu
61467653936SRoopa Prabhu rd->remote_ip = *ip;
61567653936SRoopa Prabhu rd->remote_port = port;
61667653936SRoopa Prabhu rd->offloaded = false;
61767653936SRoopa Prabhu rd->remote_vni = vni;
61867653936SRoopa Prabhu rd->remote_ifindex = ifindex;
61967653936SRoopa Prabhu
62067653936SRoopa Prabhu list_add_tail_rcu(&rd->list, &f->remotes);
62167653936SRoopa Prabhu
62267653936SRoopa Prabhu *rdp = rd;
62367653936SRoopa Prabhu return 1;
62467653936SRoopa Prabhu }
62567653936SRoopa Prabhu
vxlan_parse_gpe_proto(struct vxlanhdr * hdr,__be16 * protocol)62617a0a644SJiri Benc static bool vxlan_parse_gpe_proto(struct vxlanhdr *hdr, __be16 *protocol)
62717a0a644SJiri Benc {
62817a0a644SJiri Benc struct vxlanhdr_gpe *gpe = (struct vxlanhdr_gpe *)hdr;
62917a0a644SJiri Benc
63017a0a644SJiri Benc /* Need to have Next Protocol set for interfaces in GPE mode. */
63117a0a644SJiri Benc if (!gpe->np_applied)
63217a0a644SJiri Benc return false;
63317a0a644SJiri Benc /* "The initial version is 0. If a receiver does not support the
63417a0a644SJiri Benc * version indicated it MUST drop the packet.
63517a0a644SJiri Benc */
63617a0a644SJiri Benc if (gpe->version != 0)
63717a0a644SJiri Benc return false;
63817a0a644SJiri Benc /* "When the O bit is set to 1, the packet is an OAM packet and OAM
63917a0a644SJiri Benc * processing MUST occur." However, we don't implement OAM
64017a0a644SJiri Benc * processing, thus drop the packet.
64117a0a644SJiri Benc */
64217a0a644SJiri Benc if (gpe->oam_flag)
64317a0a644SJiri Benc return false;
64417a0a644SJiri Benc
64517a0a644SJiri Benc *protocol = tun_p_to_eth_p(gpe->next_protocol);
64617a0a644SJiri Benc if (!*protocol)
64717a0a644SJiri Benc return false;
64817a0a644SJiri Benc
64917a0a644SJiri Benc return true;
65017a0a644SJiri Benc }
65117a0a644SJiri Benc
vxlan_gro_remcsum(struct sk_buff * skb,unsigned int off,struct vxlanhdr * vh,size_t hdrlen,__be32 vni_field,struct gro_remcsum * grc,bool nopartial)65267653936SRoopa Prabhu static struct vxlanhdr *vxlan_gro_remcsum(struct sk_buff *skb,
65367653936SRoopa Prabhu unsigned int off,
65467653936SRoopa Prabhu struct vxlanhdr *vh, size_t hdrlen,
65567653936SRoopa Prabhu __be32 vni_field,
65667653936SRoopa Prabhu struct gro_remcsum *grc,
65767653936SRoopa Prabhu bool nopartial)
65867653936SRoopa Prabhu {
65967653936SRoopa Prabhu size_t start, offset;
66067653936SRoopa Prabhu
66167653936SRoopa Prabhu if (skb->remcsum_offload)
66267653936SRoopa Prabhu return vh;
66367653936SRoopa Prabhu
66467653936SRoopa Prabhu if (!NAPI_GRO_CB(skb)->csum_valid)
66567653936SRoopa Prabhu return NULL;
66667653936SRoopa Prabhu
66767653936SRoopa Prabhu start = vxlan_rco_start(vni_field);
66867653936SRoopa Prabhu offset = start + vxlan_rco_offset(vni_field);
66967653936SRoopa Prabhu
67067653936SRoopa Prabhu vh = skb_gro_remcsum_process(skb, (void *)vh, off, hdrlen,
67167653936SRoopa Prabhu start, offset, grc, nopartial);
67267653936SRoopa Prabhu
67367653936SRoopa Prabhu skb->remcsum_offload = 1;
67467653936SRoopa Prabhu
67567653936SRoopa Prabhu return vh;
67667653936SRoopa Prabhu }
67767653936SRoopa Prabhu
vxlan_gro_prepare_receive(struct sock * sk,struct list_head * head,struct sk_buff * skb,struct gro_remcsum * grc)678b0b672c4SJiri Benc static struct vxlanhdr *vxlan_gro_prepare_receive(struct sock *sk,
67967653936SRoopa Prabhu struct list_head *head,
680b0b672c4SJiri Benc struct sk_buff *skb,
681b0b672c4SJiri Benc struct gro_remcsum *grc)
68267653936SRoopa Prabhu {
68367653936SRoopa Prabhu struct sk_buff *p;
68467653936SRoopa Prabhu struct vxlanhdr *vh, *vh2;
68567653936SRoopa Prabhu unsigned int hlen, off_vx;
68667653936SRoopa Prabhu struct vxlan_sock *vs = rcu_dereference_sk_user_data(sk);
68767653936SRoopa Prabhu __be32 flags;
68867653936SRoopa Prabhu
689b0b672c4SJiri Benc skb_gro_remcsum_init(grc);
69067653936SRoopa Prabhu
69167653936SRoopa Prabhu off_vx = skb_gro_offset(skb);
69267653936SRoopa Prabhu hlen = off_vx + sizeof(*vh);
69335ffb665SRichard Gobert vh = skb_gro_header(skb, hlen, off_vx);
69467653936SRoopa Prabhu if (unlikely(!vh))
695b0b672c4SJiri Benc return NULL;
69667653936SRoopa Prabhu
69767653936SRoopa Prabhu skb_gro_postpull_rcsum(skb, vh, sizeof(struct vxlanhdr));
69867653936SRoopa Prabhu
69967653936SRoopa Prabhu flags = vh->vx_flags;
70067653936SRoopa Prabhu
70167653936SRoopa Prabhu if ((flags & VXLAN_HF_RCO) && (vs->flags & VXLAN_F_REMCSUM_RX)) {
70267653936SRoopa Prabhu vh = vxlan_gro_remcsum(skb, off_vx, vh, sizeof(struct vxlanhdr),
703b0b672c4SJiri Benc vh->vx_vni, grc,
70467653936SRoopa Prabhu !!(vs->flags &
70567653936SRoopa Prabhu VXLAN_F_REMCSUM_NOPARTIAL));
70667653936SRoopa Prabhu
70767653936SRoopa Prabhu if (!vh)
708b0b672c4SJiri Benc return NULL;
70967653936SRoopa Prabhu }
71067653936SRoopa Prabhu
71167653936SRoopa Prabhu skb_gro_pull(skb, sizeof(struct vxlanhdr)); /* pull vxlan header */
71267653936SRoopa Prabhu
71367653936SRoopa Prabhu list_for_each_entry(p, head, list) {
71467653936SRoopa Prabhu if (!NAPI_GRO_CB(p)->same_flow)
71567653936SRoopa Prabhu continue;
71667653936SRoopa Prabhu
71767653936SRoopa Prabhu vh2 = (struct vxlanhdr *)(p->data + off_vx);
71867653936SRoopa Prabhu if (vh->vx_flags != vh2->vx_flags ||
71967653936SRoopa Prabhu vh->vx_vni != vh2->vx_vni) {
72067653936SRoopa Prabhu NAPI_GRO_CB(p)->same_flow = 0;
72167653936SRoopa Prabhu continue;
72267653936SRoopa Prabhu }
72367653936SRoopa Prabhu }
72467653936SRoopa Prabhu
725b0b672c4SJiri Benc return vh;
726b0b672c4SJiri Benc }
727b0b672c4SJiri Benc
vxlan_gro_receive(struct sock * sk,struct list_head * head,struct sk_buff * skb)728b0b672c4SJiri Benc static struct sk_buff *vxlan_gro_receive(struct sock *sk,
729b0b672c4SJiri Benc struct list_head *head,
730b0b672c4SJiri Benc struct sk_buff *skb)
731b0b672c4SJiri Benc {
732b0b672c4SJiri Benc struct sk_buff *pp = NULL;
733b0b672c4SJiri Benc struct gro_remcsum grc;
734b0b672c4SJiri Benc int flush = 1;
735b0b672c4SJiri Benc
736b0b672c4SJiri Benc if (vxlan_gro_prepare_receive(sk, head, skb, &grc)) {
73767653936SRoopa Prabhu pp = call_gro_receive(eth_gro_receive, head, skb);
73867653936SRoopa Prabhu flush = 0;
739b0b672c4SJiri Benc }
740b0b672c4SJiri Benc skb_gro_flush_final_remcsum(skb, pp, flush, &grc);
741b0b672c4SJiri Benc return pp;
742b0b672c4SJiri Benc }
74367653936SRoopa Prabhu
vxlan_gpe_gro_receive(struct sock * sk,struct list_head * head,struct sk_buff * skb)744b0b672c4SJiri Benc static struct sk_buff *vxlan_gpe_gro_receive(struct sock *sk,
745b0b672c4SJiri Benc struct list_head *head,
746b0b672c4SJiri Benc struct sk_buff *skb)
747b0b672c4SJiri Benc {
748b0b672c4SJiri Benc const struct packet_offload *ptype;
749b0b672c4SJiri Benc struct sk_buff *pp = NULL;
750b0b672c4SJiri Benc struct gro_remcsum grc;
751b0b672c4SJiri Benc struct vxlanhdr *vh;
752b0b672c4SJiri Benc __be16 protocol;
753b0b672c4SJiri Benc int flush = 1;
754b0b672c4SJiri Benc
755b0b672c4SJiri Benc vh = vxlan_gro_prepare_receive(sk, head, skb, &grc);
756b0b672c4SJiri Benc if (vh) {
757b0b672c4SJiri Benc if (!vxlan_parse_gpe_proto(vh, &protocol))
758b0b672c4SJiri Benc goto out;
759b0b672c4SJiri Benc ptype = gro_find_receive_by_type(protocol);
760b0b672c4SJiri Benc if (!ptype)
761b0b672c4SJiri Benc goto out;
762b0b672c4SJiri Benc pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb);
763b0b672c4SJiri Benc flush = 0;
764b0b672c4SJiri Benc }
76567653936SRoopa Prabhu out:
76667653936SRoopa Prabhu skb_gro_flush_final_remcsum(skb, pp, flush, &grc);
76767653936SRoopa Prabhu return pp;
76867653936SRoopa Prabhu }
76967653936SRoopa Prabhu
vxlan_gro_complete(struct sock * sk,struct sk_buff * skb,int nhoff)77067653936SRoopa Prabhu static int vxlan_gro_complete(struct sock *sk, struct sk_buff *skb, int nhoff)
77167653936SRoopa Prabhu {
77267653936SRoopa Prabhu /* Sets 'skb->inner_mac_header' since we are always called with
77367653936SRoopa Prabhu * 'skb->encapsulation' set.
77467653936SRoopa Prabhu */
77567653936SRoopa Prabhu return eth_gro_complete(skb, nhoff + sizeof(struct vxlanhdr));
77667653936SRoopa Prabhu }
77767653936SRoopa Prabhu
vxlan_gpe_gro_complete(struct sock * sk,struct sk_buff * skb,int nhoff)778b0b672c4SJiri Benc static int vxlan_gpe_gro_complete(struct sock *sk, struct sk_buff *skb, int nhoff)
779b0b672c4SJiri Benc {
780b0b672c4SJiri Benc struct vxlanhdr *vh = (struct vxlanhdr *)(skb->data + nhoff);
781b0b672c4SJiri Benc const struct packet_offload *ptype;
782b0b672c4SJiri Benc int err = -ENOSYS;
783b0b672c4SJiri Benc __be16 protocol;
784b0b672c4SJiri Benc
785b0b672c4SJiri Benc if (!vxlan_parse_gpe_proto(vh, &protocol))
786b0b672c4SJiri Benc return err;
787b0b672c4SJiri Benc ptype = gro_find_complete_by_type(protocol);
788b0b672c4SJiri Benc if (ptype)
789b0b672c4SJiri Benc err = ptype->callbacks.gro_complete(skb, nhoff + sizeof(struct vxlanhdr));
790b0b672c4SJiri Benc return err;
791b0b672c4SJiri Benc }
792b0b672c4SJiri Benc
vxlan_fdb_alloc(struct vxlan_dev * vxlan,const u8 * mac,__u16 state,__be32 src_vni,__u16 ndm_flags)79367653936SRoopa Prabhu static struct vxlan_fdb *vxlan_fdb_alloc(struct vxlan_dev *vxlan, const u8 *mac,
79467653936SRoopa Prabhu __u16 state, __be32 src_vni,
79567653936SRoopa Prabhu __u16 ndm_flags)
79667653936SRoopa Prabhu {
79767653936SRoopa Prabhu struct vxlan_fdb *f;
79867653936SRoopa Prabhu
79967653936SRoopa Prabhu f = kmalloc(sizeof(*f), GFP_ATOMIC);
80067653936SRoopa Prabhu if (!f)
80167653936SRoopa Prabhu return NULL;
80267653936SRoopa Prabhu f->state = state;
80367653936SRoopa Prabhu f->flags = ndm_flags;
80467653936SRoopa Prabhu f->updated = f->used = jiffies;
80567653936SRoopa Prabhu f->vni = src_vni;
80667653936SRoopa Prabhu f->nh = NULL;
80767653936SRoopa Prabhu RCU_INIT_POINTER(f->vdev, vxlan);
80867653936SRoopa Prabhu INIT_LIST_HEAD(&f->nh_list);
80967653936SRoopa Prabhu INIT_LIST_HEAD(&f->remotes);
81067653936SRoopa Prabhu memcpy(f->eth_addr, mac, ETH_ALEN);
81167653936SRoopa Prabhu
81267653936SRoopa Prabhu return f;
81367653936SRoopa Prabhu }
81467653936SRoopa Prabhu
vxlan_fdb_insert(struct vxlan_dev * vxlan,const u8 * mac,__be32 src_vni,struct vxlan_fdb * f)81567653936SRoopa Prabhu static void vxlan_fdb_insert(struct vxlan_dev *vxlan, const u8 *mac,
81667653936SRoopa Prabhu __be32 src_vni, struct vxlan_fdb *f)
81767653936SRoopa Prabhu {
81867653936SRoopa Prabhu ++vxlan->addrcnt;
81967653936SRoopa Prabhu hlist_add_head_rcu(&f->hlist,
82067653936SRoopa Prabhu vxlan_fdb_head(vxlan, mac, src_vni));
82167653936SRoopa Prabhu }
82267653936SRoopa Prabhu
vxlan_fdb_nh_update(struct vxlan_dev * vxlan,struct vxlan_fdb * fdb,u32 nhid,struct netlink_ext_ack * extack)82367653936SRoopa Prabhu static int vxlan_fdb_nh_update(struct vxlan_dev *vxlan, struct vxlan_fdb *fdb,
82467653936SRoopa Prabhu u32 nhid, struct netlink_ext_ack *extack)
82567653936SRoopa Prabhu {
82667653936SRoopa Prabhu struct nexthop *old_nh = rtnl_dereference(fdb->nh);
82767653936SRoopa Prabhu struct nexthop *nh;
82867653936SRoopa Prabhu int err = -EINVAL;
82967653936SRoopa Prabhu
83067653936SRoopa Prabhu if (old_nh && old_nh->id == nhid)
83167653936SRoopa Prabhu return 0;
83267653936SRoopa Prabhu
83367653936SRoopa Prabhu nh = nexthop_find_by_id(vxlan->net, nhid);
83467653936SRoopa Prabhu if (!nh) {
83567653936SRoopa Prabhu NL_SET_ERR_MSG(extack, "Nexthop id does not exist");
83667653936SRoopa Prabhu goto err_inval;
83767653936SRoopa Prabhu }
83867653936SRoopa Prabhu
83967653936SRoopa Prabhu if (!nexthop_get(nh)) {
84067653936SRoopa Prabhu NL_SET_ERR_MSG(extack, "Nexthop has been deleted");
84167653936SRoopa Prabhu nh = NULL;
84267653936SRoopa Prabhu goto err_inval;
84367653936SRoopa Prabhu }
84467653936SRoopa Prabhu if (!nexthop_is_fdb(nh)) {
84567653936SRoopa Prabhu NL_SET_ERR_MSG(extack, "Nexthop is not a fdb nexthop");
84667653936SRoopa Prabhu goto err_inval;
84767653936SRoopa Prabhu }
84867653936SRoopa Prabhu
84967653936SRoopa Prabhu if (!nexthop_is_multipath(nh)) {
85067653936SRoopa Prabhu NL_SET_ERR_MSG(extack, "Nexthop is not a multipath group");
85167653936SRoopa Prabhu goto err_inval;
85267653936SRoopa Prabhu }
85367653936SRoopa Prabhu
85467653936SRoopa Prabhu /* check nexthop group family */
85567653936SRoopa Prabhu switch (vxlan->default_dst.remote_ip.sa.sa_family) {
85667653936SRoopa Prabhu case AF_INET:
85767653936SRoopa Prabhu if (!nexthop_has_v4(nh)) {
85867653936SRoopa Prabhu err = -EAFNOSUPPORT;
85967653936SRoopa Prabhu NL_SET_ERR_MSG(extack, "Nexthop group family not supported");
86067653936SRoopa Prabhu goto err_inval;
86167653936SRoopa Prabhu }
86267653936SRoopa Prabhu break;
86367653936SRoopa Prabhu case AF_INET6:
86467653936SRoopa Prabhu if (nexthop_has_v4(nh)) {
86567653936SRoopa Prabhu err = -EAFNOSUPPORT;
86667653936SRoopa Prabhu NL_SET_ERR_MSG(extack, "Nexthop group family not supported");
86767653936SRoopa Prabhu goto err_inval;
86867653936SRoopa Prabhu }
86967653936SRoopa Prabhu }
87067653936SRoopa Prabhu
87167653936SRoopa Prabhu if (old_nh) {
87267653936SRoopa Prabhu list_del_rcu(&fdb->nh_list);
87367653936SRoopa Prabhu nexthop_put(old_nh);
87467653936SRoopa Prabhu }
87567653936SRoopa Prabhu rcu_assign_pointer(fdb->nh, nh);
87667653936SRoopa Prabhu list_add_tail_rcu(&fdb->nh_list, &nh->fdb_list);
87767653936SRoopa Prabhu return 1;
87867653936SRoopa Prabhu
87967653936SRoopa Prabhu err_inval:
88067653936SRoopa Prabhu if (nh)
88167653936SRoopa Prabhu nexthop_put(nh);
88267653936SRoopa Prabhu return err;
88367653936SRoopa Prabhu }
88467653936SRoopa Prabhu
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,__u16 ndm_flags,u32 nhid,struct vxlan_fdb ** fdb,struct netlink_ext_ack * extack)885c63053e0SRoopa Prabhu int vxlan_fdb_create(struct vxlan_dev *vxlan,
88667653936SRoopa Prabhu const u8 *mac, union vxlan_addr *ip,
88767653936SRoopa Prabhu __u16 state, __be16 port, __be32 src_vni,
88867653936SRoopa Prabhu __be32 vni, __u32 ifindex, __u16 ndm_flags,
88967653936SRoopa Prabhu u32 nhid, struct vxlan_fdb **fdb,
89067653936SRoopa Prabhu struct netlink_ext_ack *extack)
89167653936SRoopa Prabhu {
89267653936SRoopa Prabhu struct vxlan_rdst *rd = NULL;
89367653936SRoopa Prabhu struct vxlan_fdb *f;
89467653936SRoopa Prabhu int rc;
89567653936SRoopa Prabhu
89667653936SRoopa Prabhu if (vxlan->cfg.addrmax &&
89767653936SRoopa Prabhu vxlan->addrcnt >= vxlan->cfg.addrmax)
89867653936SRoopa Prabhu return -ENOSPC;
89967653936SRoopa Prabhu
90067653936SRoopa Prabhu netdev_dbg(vxlan->dev, "add %pM -> %pIS\n", mac, ip);
90167653936SRoopa Prabhu f = vxlan_fdb_alloc(vxlan, mac, state, src_vni, ndm_flags);
90267653936SRoopa Prabhu if (!f)
90367653936SRoopa Prabhu return -ENOMEM;
90467653936SRoopa Prabhu
90567653936SRoopa Prabhu if (nhid)
90667653936SRoopa Prabhu rc = vxlan_fdb_nh_update(vxlan, f, nhid, extack);
90767653936SRoopa Prabhu else
90867653936SRoopa Prabhu rc = vxlan_fdb_append(f, ip, port, vni, ifindex, &rd);
90967653936SRoopa Prabhu if (rc < 0)
91067653936SRoopa Prabhu goto errout;
91167653936SRoopa Prabhu
91267653936SRoopa Prabhu *fdb = f;
91367653936SRoopa Prabhu
91467653936SRoopa Prabhu return 0;
91567653936SRoopa Prabhu
91667653936SRoopa Prabhu errout:
91767653936SRoopa Prabhu kfree(f);
91867653936SRoopa Prabhu return rc;
91967653936SRoopa Prabhu }
92067653936SRoopa Prabhu
__vxlan_fdb_free(struct vxlan_fdb * f)92167653936SRoopa Prabhu static void __vxlan_fdb_free(struct vxlan_fdb *f)
92267653936SRoopa Prabhu {
92367653936SRoopa Prabhu struct vxlan_rdst *rd, *nd;
92467653936SRoopa Prabhu struct nexthop *nh;
92567653936SRoopa Prabhu
92667653936SRoopa Prabhu nh = rcu_dereference_raw(f->nh);
92767653936SRoopa Prabhu if (nh) {
92867653936SRoopa Prabhu rcu_assign_pointer(f->nh, NULL);
92967653936SRoopa Prabhu rcu_assign_pointer(f->vdev, NULL);
93067653936SRoopa Prabhu nexthop_put(nh);
93167653936SRoopa Prabhu }
93267653936SRoopa Prabhu
93367653936SRoopa Prabhu list_for_each_entry_safe(rd, nd, &f->remotes, list) {
93467653936SRoopa Prabhu dst_cache_destroy(&rd->dst_cache);
93567653936SRoopa Prabhu kfree(rd);
93667653936SRoopa Prabhu }
93767653936SRoopa Prabhu kfree(f);
93867653936SRoopa Prabhu }
93967653936SRoopa Prabhu
vxlan_fdb_free(struct rcu_head * head)94067653936SRoopa Prabhu static void vxlan_fdb_free(struct rcu_head *head)
94167653936SRoopa Prabhu {
94267653936SRoopa Prabhu struct vxlan_fdb *f = container_of(head, struct vxlan_fdb, rcu);
94367653936SRoopa Prabhu
94467653936SRoopa Prabhu __vxlan_fdb_free(f);
94567653936SRoopa Prabhu }
94667653936SRoopa Prabhu
vxlan_fdb_destroy(struct vxlan_dev * vxlan,struct vxlan_fdb * f,bool do_notify,bool swdev_notify)94767653936SRoopa Prabhu static void vxlan_fdb_destroy(struct vxlan_dev *vxlan, struct vxlan_fdb *f,
94867653936SRoopa Prabhu bool do_notify, bool swdev_notify)
94967653936SRoopa Prabhu {
95067653936SRoopa Prabhu struct vxlan_rdst *rd;
95167653936SRoopa Prabhu
95267653936SRoopa Prabhu netdev_dbg(vxlan->dev, "delete %pM\n", f->eth_addr);
95367653936SRoopa Prabhu
95467653936SRoopa Prabhu --vxlan->addrcnt;
95567653936SRoopa Prabhu if (do_notify) {
95667653936SRoopa Prabhu if (rcu_access_pointer(f->nh))
95767653936SRoopa Prabhu vxlan_fdb_notify(vxlan, f, NULL, RTM_DELNEIGH,
95867653936SRoopa Prabhu swdev_notify, NULL);
95967653936SRoopa Prabhu else
96067653936SRoopa Prabhu list_for_each_entry(rd, &f->remotes, list)
96167653936SRoopa Prabhu vxlan_fdb_notify(vxlan, f, rd, RTM_DELNEIGH,
96267653936SRoopa Prabhu swdev_notify, NULL);
96367653936SRoopa Prabhu }
96467653936SRoopa Prabhu
96567653936SRoopa Prabhu hlist_del_rcu(&f->hlist);
96667653936SRoopa Prabhu list_del_rcu(&f->nh_list);
96767653936SRoopa Prabhu call_rcu(&f->rcu, vxlan_fdb_free);
96867653936SRoopa Prabhu }
96967653936SRoopa Prabhu
vxlan_dst_free(struct rcu_head * head)97067653936SRoopa Prabhu static void vxlan_dst_free(struct rcu_head *head)
97167653936SRoopa Prabhu {
97267653936SRoopa Prabhu struct vxlan_rdst *rd = container_of(head, struct vxlan_rdst, rcu);
97367653936SRoopa Prabhu
97467653936SRoopa Prabhu dst_cache_destroy(&rd->dst_cache);
97567653936SRoopa Prabhu kfree(rd);
97667653936SRoopa Prabhu }
97767653936SRoopa Prabhu
vxlan_fdb_update_existing(struct vxlan_dev * vxlan,union vxlan_addr * ip,__u16 state,__u16 flags,__be16 port,__be32 vni,__u32 ifindex,__u16 ndm_flags,struct vxlan_fdb * f,u32 nhid,bool swdev_notify,struct netlink_ext_ack * extack)97867653936SRoopa Prabhu static int vxlan_fdb_update_existing(struct vxlan_dev *vxlan,
97967653936SRoopa Prabhu union vxlan_addr *ip,
98067653936SRoopa Prabhu __u16 state, __u16 flags,
98167653936SRoopa Prabhu __be16 port, __be32 vni,
98267653936SRoopa Prabhu __u32 ifindex, __u16 ndm_flags,
98367653936SRoopa Prabhu struct vxlan_fdb *f, u32 nhid,
98467653936SRoopa Prabhu bool swdev_notify,
98567653936SRoopa Prabhu struct netlink_ext_ack *extack)
98667653936SRoopa Prabhu {
98767653936SRoopa Prabhu __u16 fdb_flags = (ndm_flags & ~NTF_USE);
98867653936SRoopa Prabhu struct vxlan_rdst *rd = NULL;
98967653936SRoopa Prabhu struct vxlan_rdst oldrd;
99067653936SRoopa Prabhu int notify = 0;
99167653936SRoopa Prabhu int rc = 0;
99267653936SRoopa Prabhu int err;
99367653936SRoopa Prabhu
99467653936SRoopa Prabhu if (nhid && !rcu_access_pointer(f->nh)) {
99567653936SRoopa Prabhu NL_SET_ERR_MSG(extack,
99667653936SRoopa Prabhu "Cannot replace an existing non nexthop fdb with a nexthop");
99767653936SRoopa Prabhu return -EOPNOTSUPP;
99867653936SRoopa Prabhu }
99967653936SRoopa Prabhu
100067653936SRoopa Prabhu if (nhid && (flags & NLM_F_APPEND)) {
100167653936SRoopa Prabhu NL_SET_ERR_MSG(extack,
100267653936SRoopa Prabhu "Cannot append to a nexthop fdb");
100367653936SRoopa Prabhu return -EOPNOTSUPP;
100467653936SRoopa Prabhu }
100567653936SRoopa Prabhu
100667653936SRoopa Prabhu /* Do not allow an externally learned entry to take over an entry added
100767653936SRoopa Prabhu * by the user.
100867653936SRoopa Prabhu */
100967653936SRoopa Prabhu if (!(fdb_flags & NTF_EXT_LEARNED) ||
101067653936SRoopa Prabhu !(f->flags & NTF_VXLAN_ADDED_BY_USER)) {
101167653936SRoopa Prabhu if (f->state != state) {
101267653936SRoopa Prabhu f->state = state;
101367653936SRoopa Prabhu f->updated = jiffies;
101467653936SRoopa Prabhu notify = 1;
101567653936SRoopa Prabhu }
101667653936SRoopa Prabhu if (f->flags != fdb_flags) {
101767653936SRoopa Prabhu f->flags = fdb_flags;
101867653936SRoopa Prabhu f->updated = jiffies;
101967653936SRoopa Prabhu notify = 1;
102067653936SRoopa Prabhu }
102167653936SRoopa Prabhu }
102267653936SRoopa Prabhu
102367653936SRoopa Prabhu if ((flags & NLM_F_REPLACE)) {
102467653936SRoopa Prabhu /* Only change unicasts */
102567653936SRoopa Prabhu if (!(is_multicast_ether_addr(f->eth_addr) ||
102667653936SRoopa Prabhu is_zero_ether_addr(f->eth_addr))) {
102767653936SRoopa Prabhu if (nhid) {
102867653936SRoopa Prabhu rc = vxlan_fdb_nh_update(vxlan, f, nhid, extack);
102967653936SRoopa Prabhu if (rc < 0)
103067653936SRoopa Prabhu return rc;
103167653936SRoopa Prabhu } else {
103267653936SRoopa Prabhu rc = vxlan_fdb_replace(f, ip, port, vni,
103367653936SRoopa Prabhu ifindex, &oldrd);
103467653936SRoopa Prabhu }
103567653936SRoopa Prabhu notify |= rc;
103667653936SRoopa Prabhu } else {
103767653936SRoopa Prabhu NL_SET_ERR_MSG(extack, "Cannot replace non-unicast fdb entries");
103867653936SRoopa Prabhu return -EOPNOTSUPP;
103967653936SRoopa Prabhu }
104067653936SRoopa Prabhu }
104167653936SRoopa Prabhu if ((flags & NLM_F_APPEND) &&
104267653936SRoopa Prabhu (is_multicast_ether_addr(f->eth_addr) ||
104367653936SRoopa Prabhu is_zero_ether_addr(f->eth_addr))) {
104467653936SRoopa Prabhu rc = vxlan_fdb_append(f, ip, port, vni, ifindex, &rd);
104567653936SRoopa Prabhu
104667653936SRoopa Prabhu if (rc < 0)
104767653936SRoopa Prabhu return rc;
104867653936SRoopa Prabhu notify |= rc;
104967653936SRoopa Prabhu }
105067653936SRoopa Prabhu
105167653936SRoopa Prabhu if (ndm_flags & NTF_USE)
105267653936SRoopa Prabhu f->used = jiffies;
105367653936SRoopa Prabhu
105467653936SRoopa Prabhu if (notify) {
105567653936SRoopa Prabhu if (rd == NULL)
105667653936SRoopa Prabhu rd = first_remote_rtnl(f);
105767653936SRoopa Prabhu
105867653936SRoopa Prabhu err = vxlan_fdb_notify(vxlan, f, rd, RTM_NEWNEIGH,
105967653936SRoopa Prabhu swdev_notify, extack);
106067653936SRoopa Prabhu if (err)
106167653936SRoopa Prabhu goto err_notify;
106267653936SRoopa Prabhu }
106367653936SRoopa Prabhu
106467653936SRoopa Prabhu return 0;
106567653936SRoopa Prabhu
106667653936SRoopa Prabhu err_notify:
106767653936SRoopa Prabhu if (nhid)
106867653936SRoopa Prabhu return err;
106967653936SRoopa Prabhu if ((flags & NLM_F_REPLACE) && rc)
107067653936SRoopa Prabhu *rd = oldrd;
107167653936SRoopa Prabhu else if ((flags & NLM_F_APPEND) && rc) {
107267653936SRoopa Prabhu list_del_rcu(&rd->list);
107367653936SRoopa Prabhu call_rcu(&rd->rcu, vxlan_dst_free);
107467653936SRoopa Prabhu }
107567653936SRoopa Prabhu return err;
107667653936SRoopa Prabhu }
107767653936SRoopa Prabhu
vxlan_fdb_update_create(struct vxlan_dev * vxlan,const u8 * mac,union vxlan_addr * ip,__u16 state,__u16 flags,__be16 port,__be32 src_vni,__be32 vni,__u32 ifindex,__u16 ndm_flags,u32 nhid,bool swdev_notify,struct netlink_ext_ack * extack)107867653936SRoopa Prabhu static int vxlan_fdb_update_create(struct vxlan_dev *vxlan,
107967653936SRoopa Prabhu const u8 *mac, union vxlan_addr *ip,
108067653936SRoopa Prabhu __u16 state, __u16 flags,
108167653936SRoopa Prabhu __be16 port, __be32 src_vni, __be32 vni,
108267653936SRoopa Prabhu __u32 ifindex, __u16 ndm_flags, u32 nhid,
108367653936SRoopa Prabhu bool swdev_notify,
108467653936SRoopa Prabhu struct netlink_ext_ack *extack)
108567653936SRoopa Prabhu {
108667653936SRoopa Prabhu __u16 fdb_flags = (ndm_flags & ~NTF_USE);
108767653936SRoopa Prabhu struct vxlan_fdb *f;
108867653936SRoopa Prabhu int rc;
108967653936SRoopa Prabhu
109067653936SRoopa Prabhu /* Disallow replace to add a multicast entry */
109167653936SRoopa Prabhu if ((flags & NLM_F_REPLACE) &&
109267653936SRoopa Prabhu (is_multicast_ether_addr(mac) || is_zero_ether_addr(mac)))
109367653936SRoopa Prabhu return -EOPNOTSUPP;
109467653936SRoopa Prabhu
109567653936SRoopa Prabhu netdev_dbg(vxlan->dev, "add %pM -> %pIS\n", mac, ip);
109667653936SRoopa Prabhu rc = vxlan_fdb_create(vxlan, mac, ip, state, port, src_vni,
109767653936SRoopa Prabhu vni, ifindex, fdb_flags, nhid, &f, extack);
109867653936SRoopa Prabhu if (rc < 0)
109967653936SRoopa Prabhu return rc;
110067653936SRoopa Prabhu
110167653936SRoopa Prabhu vxlan_fdb_insert(vxlan, mac, src_vni, f);
110267653936SRoopa Prabhu rc = vxlan_fdb_notify(vxlan, f, first_remote_rtnl(f), RTM_NEWNEIGH,
110367653936SRoopa Prabhu swdev_notify, extack);
110467653936SRoopa Prabhu if (rc)
110567653936SRoopa Prabhu goto err_notify;
110667653936SRoopa Prabhu
110767653936SRoopa Prabhu return 0;
110867653936SRoopa Prabhu
110967653936SRoopa Prabhu err_notify:
111067653936SRoopa Prabhu vxlan_fdb_destroy(vxlan, f, false, false);
111167653936SRoopa Prabhu return rc;
111267653936SRoopa Prabhu }
111367653936SRoopa Prabhu
111467653936SRoopa Prabhu /* Add new entry to forwarding table -- assumes lock held */
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,__u32 ifindex,__u16 ndm_flags,u32 nhid,bool swdev_notify,struct netlink_ext_ack * extack)1115c63053e0SRoopa Prabhu int vxlan_fdb_update(struct vxlan_dev *vxlan,
111667653936SRoopa Prabhu const u8 *mac, union vxlan_addr *ip,
111767653936SRoopa Prabhu __u16 state, __u16 flags,
111867653936SRoopa Prabhu __be16 port, __be32 src_vni, __be32 vni,
111967653936SRoopa Prabhu __u32 ifindex, __u16 ndm_flags, u32 nhid,
112067653936SRoopa Prabhu bool swdev_notify,
112167653936SRoopa Prabhu struct netlink_ext_ack *extack)
112267653936SRoopa Prabhu {
112367653936SRoopa Prabhu struct vxlan_fdb *f;
112467653936SRoopa Prabhu
112567653936SRoopa Prabhu f = __vxlan_find_mac(vxlan, mac, src_vni);
112667653936SRoopa Prabhu if (f) {
112767653936SRoopa Prabhu if (flags & NLM_F_EXCL) {
112867653936SRoopa Prabhu netdev_dbg(vxlan->dev,
112967653936SRoopa Prabhu "lost race to create %pM\n", mac);
113067653936SRoopa Prabhu return -EEXIST;
113167653936SRoopa Prabhu }
113267653936SRoopa Prabhu
113367653936SRoopa Prabhu return vxlan_fdb_update_existing(vxlan, ip, state, flags, port,
113467653936SRoopa Prabhu vni, ifindex, ndm_flags, f,
113567653936SRoopa Prabhu nhid, swdev_notify, extack);
113667653936SRoopa Prabhu } else {
113767653936SRoopa Prabhu if (!(flags & NLM_F_CREATE))
113867653936SRoopa Prabhu return -ENOENT;
113967653936SRoopa Prabhu
114067653936SRoopa Prabhu return vxlan_fdb_update_create(vxlan, mac, ip, state, flags,
114167653936SRoopa Prabhu port, src_vni, vni, ifindex,
114267653936SRoopa Prabhu ndm_flags, nhid, swdev_notify,
114367653936SRoopa Prabhu extack);
114467653936SRoopa Prabhu }
114567653936SRoopa Prabhu }
114667653936SRoopa Prabhu
vxlan_fdb_dst_destroy(struct vxlan_dev * vxlan,struct vxlan_fdb * f,struct vxlan_rdst * rd,bool swdev_notify)114767653936SRoopa Prabhu static void vxlan_fdb_dst_destroy(struct vxlan_dev *vxlan, struct vxlan_fdb *f,
114867653936SRoopa Prabhu struct vxlan_rdst *rd, bool swdev_notify)
114967653936SRoopa Prabhu {
115067653936SRoopa Prabhu list_del_rcu(&rd->list);
115167653936SRoopa Prabhu vxlan_fdb_notify(vxlan, f, rd, RTM_DELNEIGH, swdev_notify, NULL);
115267653936SRoopa Prabhu call_rcu(&rd->rcu, vxlan_dst_free);
115367653936SRoopa Prabhu }
115467653936SRoopa Prabhu
vxlan_fdb_parse(struct nlattr * tb[],struct vxlan_dev * vxlan,union vxlan_addr * ip,__be16 * port,__be32 * src_vni,__be32 * vni,u32 * ifindex,u32 * nhid,struct netlink_ext_ack * extack)115567653936SRoopa Prabhu static int vxlan_fdb_parse(struct nlattr *tb[], struct vxlan_dev *vxlan,
115667653936SRoopa Prabhu union vxlan_addr *ip, __be16 *port, __be32 *src_vni,
1157e92695e5SAlaa Mohamed __be32 *vni, u32 *ifindex, u32 *nhid,
1158e92695e5SAlaa Mohamed struct netlink_ext_ack *extack)
115967653936SRoopa Prabhu {
116067653936SRoopa Prabhu struct net *net = dev_net(vxlan->dev);
116167653936SRoopa Prabhu int err;
116267653936SRoopa Prabhu
1163c2e10f53SAlaa Mohamed if (tb[NDA_NH_ID] &&
1164c2e10f53SAlaa Mohamed (tb[NDA_DST] || tb[NDA_VNI] || tb[NDA_IFINDEX] || tb[NDA_PORT])) {
1165c2e10f53SAlaa Mohamed NL_SET_ERR_MSG(extack, "DST, VNI, ifindex and port are mutually exclusive with NH_ID");
116667653936SRoopa Prabhu return -EINVAL;
1167e92695e5SAlaa Mohamed }
116867653936SRoopa Prabhu
116967653936SRoopa Prabhu if (tb[NDA_DST]) {
117067653936SRoopa Prabhu err = vxlan_nla_get_addr(ip, tb[NDA_DST]);
1171e92695e5SAlaa Mohamed if (err) {
1172e92695e5SAlaa Mohamed NL_SET_ERR_MSG(extack, "Unsupported address family");
117367653936SRoopa Prabhu return err;
1174e92695e5SAlaa Mohamed }
117567653936SRoopa Prabhu } else {
117667653936SRoopa Prabhu union vxlan_addr *remote = &vxlan->default_dst.remote_ip;
117767653936SRoopa Prabhu
117867653936SRoopa Prabhu if (remote->sa.sa_family == AF_INET) {
117967653936SRoopa Prabhu ip->sin.sin_addr.s_addr = htonl(INADDR_ANY);
118067653936SRoopa Prabhu ip->sa.sa_family = AF_INET;
118167653936SRoopa Prabhu #if IS_ENABLED(CONFIG_IPV6)
118267653936SRoopa Prabhu } else {
118367653936SRoopa Prabhu ip->sin6.sin6_addr = in6addr_any;
118467653936SRoopa Prabhu ip->sa.sa_family = AF_INET6;
118567653936SRoopa Prabhu #endif
118667653936SRoopa Prabhu }
118767653936SRoopa Prabhu }
118867653936SRoopa Prabhu
118967653936SRoopa Prabhu if (tb[NDA_PORT]) {
1190e92695e5SAlaa Mohamed if (nla_len(tb[NDA_PORT]) != sizeof(__be16)) {
1191e92695e5SAlaa Mohamed NL_SET_ERR_MSG(extack, "Invalid vxlan port");
119267653936SRoopa Prabhu return -EINVAL;
1193e92695e5SAlaa Mohamed }
119467653936SRoopa Prabhu *port = nla_get_be16(tb[NDA_PORT]);
119567653936SRoopa Prabhu } else {
119667653936SRoopa Prabhu *port = vxlan->cfg.dst_port;
119767653936SRoopa Prabhu }
119867653936SRoopa Prabhu
119967653936SRoopa Prabhu if (tb[NDA_VNI]) {
1200e92695e5SAlaa Mohamed if (nla_len(tb[NDA_VNI]) != sizeof(u32)) {
1201e92695e5SAlaa Mohamed NL_SET_ERR_MSG(extack, "Invalid vni");
120267653936SRoopa Prabhu return -EINVAL;
1203e92695e5SAlaa Mohamed }
120467653936SRoopa Prabhu *vni = cpu_to_be32(nla_get_u32(tb[NDA_VNI]));
120567653936SRoopa Prabhu } else {
120667653936SRoopa Prabhu *vni = vxlan->default_dst.remote_vni;
120767653936SRoopa Prabhu }
120867653936SRoopa Prabhu
120967653936SRoopa Prabhu if (tb[NDA_SRC_VNI]) {
1210e92695e5SAlaa Mohamed if (nla_len(tb[NDA_SRC_VNI]) != sizeof(u32)) {
1211e92695e5SAlaa Mohamed NL_SET_ERR_MSG(extack, "Invalid src vni");
121267653936SRoopa Prabhu return -EINVAL;
1213e92695e5SAlaa Mohamed }
121467653936SRoopa Prabhu *src_vni = cpu_to_be32(nla_get_u32(tb[NDA_SRC_VNI]));
121567653936SRoopa Prabhu } else {
121667653936SRoopa Prabhu *src_vni = vxlan->default_dst.remote_vni;
121767653936SRoopa Prabhu }
121867653936SRoopa Prabhu
121967653936SRoopa Prabhu if (tb[NDA_IFINDEX]) {
122067653936SRoopa Prabhu struct net_device *tdev;
122167653936SRoopa Prabhu
1222e92695e5SAlaa Mohamed if (nla_len(tb[NDA_IFINDEX]) != sizeof(u32)) {
1223e92695e5SAlaa Mohamed NL_SET_ERR_MSG(extack, "Invalid ifindex");
122467653936SRoopa Prabhu return -EINVAL;
1225e92695e5SAlaa Mohamed }
122667653936SRoopa Prabhu *ifindex = nla_get_u32(tb[NDA_IFINDEX]);
122767653936SRoopa Prabhu tdev = __dev_get_by_index(net, *ifindex);
1228e92695e5SAlaa Mohamed if (!tdev) {
1229e92695e5SAlaa Mohamed NL_SET_ERR_MSG(extack, "Device not found");
123067653936SRoopa Prabhu return -EADDRNOTAVAIL;
1231e92695e5SAlaa Mohamed }
123267653936SRoopa Prabhu } else {
123367653936SRoopa Prabhu *ifindex = 0;
123467653936SRoopa Prabhu }
123567653936SRoopa Prabhu
123667653936SRoopa Prabhu if (tb[NDA_NH_ID])
123767653936SRoopa Prabhu *nhid = nla_get_u32(tb[NDA_NH_ID]);
123867653936SRoopa Prabhu else
123967653936SRoopa Prabhu *nhid = 0;
124067653936SRoopa Prabhu
124167653936SRoopa Prabhu return 0;
124267653936SRoopa Prabhu }
124367653936SRoopa Prabhu
124467653936SRoopa Prabhu /* Add static entry (via netlink) */
vxlan_fdb_add(struct ndmsg * ndm,struct nlattr * tb[],struct net_device * dev,const unsigned char * addr,u16 vid,u16 flags,struct netlink_ext_ack * extack)124567653936SRoopa Prabhu static int vxlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
124667653936SRoopa Prabhu struct net_device *dev,
124767653936SRoopa Prabhu const unsigned char *addr, u16 vid, u16 flags,
124867653936SRoopa Prabhu struct netlink_ext_ack *extack)
124967653936SRoopa Prabhu {
125067653936SRoopa Prabhu struct vxlan_dev *vxlan = netdev_priv(dev);
125167653936SRoopa Prabhu /* struct net *net = dev_net(vxlan->dev); */
125267653936SRoopa Prabhu union vxlan_addr ip;
125367653936SRoopa Prabhu __be16 port;
125467653936SRoopa Prabhu __be32 src_vni, vni;
125567653936SRoopa Prabhu u32 ifindex, nhid;
125667653936SRoopa Prabhu u32 hash_index;
125767653936SRoopa Prabhu int err;
125867653936SRoopa Prabhu
125967653936SRoopa Prabhu if (!(ndm->ndm_state & (NUD_PERMANENT|NUD_REACHABLE))) {
126067653936SRoopa Prabhu pr_info("RTM_NEWNEIGH with invalid state %#x\n",
126167653936SRoopa Prabhu ndm->ndm_state);
126267653936SRoopa Prabhu return -EINVAL;
126367653936SRoopa Prabhu }
126467653936SRoopa Prabhu
126567653936SRoopa Prabhu if (!tb || (!tb[NDA_DST] && !tb[NDA_NH_ID]))
126667653936SRoopa Prabhu return -EINVAL;
126767653936SRoopa Prabhu
126867653936SRoopa Prabhu err = vxlan_fdb_parse(tb, vxlan, &ip, &port, &src_vni, &vni, &ifindex,
1269e92695e5SAlaa Mohamed &nhid, extack);
127067653936SRoopa Prabhu if (err)
127167653936SRoopa Prabhu return err;
127267653936SRoopa Prabhu
127367653936SRoopa Prabhu if (vxlan->default_dst.remote_ip.sa.sa_family != ip.sa.sa_family)
127467653936SRoopa Prabhu return -EAFNOSUPPORT;
127567653936SRoopa Prabhu
127667653936SRoopa Prabhu hash_index = fdb_head_index(vxlan, addr, src_vni);
127767653936SRoopa Prabhu spin_lock_bh(&vxlan->hash_lock[hash_index]);
127867653936SRoopa Prabhu err = vxlan_fdb_update(vxlan, addr, &ip, ndm->ndm_state, flags,
127967653936SRoopa Prabhu port, src_vni, vni, ifindex,
128067653936SRoopa Prabhu ndm->ndm_flags | NTF_VXLAN_ADDED_BY_USER,
128167653936SRoopa Prabhu nhid, true, extack);
128267653936SRoopa Prabhu spin_unlock_bh(&vxlan->hash_lock[hash_index]);
128367653936SRoopa Prabhu
128467653936SRoopa Prabhu return err;
128567653936SRoopa Prabhu }
128667653936SRoopa Prabhu
__vxlan_fdb_delete(struct vxlan_dev * vxlan,const unsigned char * addr,union vxlan_addr ip,__be16 port,__be32 src_vni,__be32 vni,u32 ifindex,bool swdev_notify)1287c63053e0SRoopa Prabhu int __vxlan_fdb_delete(struct vxlan_dev *vxlan,
128867653936SRoopa Prabhu const unsigned char *addr, union vxlan_addr ip,
128967653936SRoopa Prabhu __be16 port, __be32 src_vni, __be32 vni,
129067653936SRoopa Prabhu u32 ifindex, bool swdev_notify)
129167653936SRoopa Prabhu {
129267653936SRoopa Prabhu struct vxlan_rdst *rd = NULL;
129367653936SRoopa Prabhu struct vxlan_fdb *f;
129467653936SRoopa Prabhu int err = -ENOENT;
129567653936SRoopa Prabhu
129667653936SRoopa Prabhu f = vxlan_find_mac(vxlan, addr, src_vni);
129767653936SRoopa Prabhu if (!f)
129867653936SRoopa Prabhu return err;
129967653936SRoopa Prabhu
130067653936SRoopa Prabhu if (!vxlan_addr_any(&ip)) {
130167653936SRoopa Prabhu rd = vxlan_fdb_find_rdst(f, &ip, port, vni, ifindex);
130267653936SRoopa Prabhu if (!rd)
130367653936SRoopa Prabhu goto out;
130467653936SRoopa Prabhu }
130567653936SRoopa Prabhu
130667653936SRoopa Prabhu /* remove a destination if it's not the only one on the list,
130767653936SRoopa Prabhu * otherwise destroy the fdb entry
130867653936SRoopa Prabhu */
130967653936SRoopa Prabhu if (rd && !list_is_singular(&f->remotes)) {
131067653936SRoopa Prabhu vxlan_fdb_dst_destroy(vxlan, f, rd, swdev_notify);
131167653936SRoopa Prabhu goto out;
131267653936SRoopa Prabhu }
131367653936SRoopa Prabhu
131467653936SRoopa Prabhu vxlan_fdb_destroy(vxlan, f, true, swdev_notify);
131567653936SRoopa Prabhu
131667653936SRoopa Prabhu out:
131767653936SRoopa Prabhu return 0;
131867653936SRoopa Prabhu }
131967653936SRoopa Prabhu
132067653936SRoopa Prabhu /* Delete entry (via netlink) */
vxlan_fdb_delete(struct ndmsg * ndm,struct nlattr * tb[],struct net_device * dev,const unsigned char * addr,u16 vid,struct netlink_ext_ack * extack)132167653936SRoopa Prabhu static int vxlan_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],
132267653936SRoopa Prabhu struct net_device *dev,
1323ca4567f1SAlaa Mohamed const unsigned char *addr, u16 vid,
1324ca4567f1SAlaa Mohamed struct netlink_ext_ack *extack)
132567653936SRoopa Prabhu {
132667653936SRoopa Prabhu struct vxlan_dev *vxlan = netdev_priv(dev);
132767653936SRoopa Prabhu union vxlan_addr ip;
132867653936SRoopa Prabhu __be32 src_vni, vni;
132967653936SRoopa Prabhu u32 ifindex, nhid;
133067653936SRoopa Prabhu u32 hash_index;
133167653936SRoopa Prabhu __be16 port;
133267653936SRoopa Prabhu int err;
133367653936SRoopa Prabhu
133467653936SRoopa Prabhu err = vxlan_fdb_parse(tb, vxlan, &ip, &port, &src_vni, &vni, &ifindex,
1335e92695e5SAlaa Mohamed &nhid, extack);
133667653936SRoopa Prabhu if (err)
133767653936SRoopa Prabhu return err;
133867653936SRoopa Prabhu
133967653936SRoopa Prabhu hash_index = fdb_head_index(vxlan, addr, src_vni);
134067653936SRoopa Prabhu spin_lock_bh(&vxlan->hash_lock[hash_index]);
134167653936SRoopa Prabhu err = __vxlan_fdb_delete(vxlan, addr, ip, port, src_vni, vni, ifindex,
134267653936SRoopa Prabhu true);
134367653936SRoopa Prabhu spin_unlock_bh(&vxlan->hash_lock[hash_index]);
134467653936SRoopa Prabhu
134567653936SRoopa Prabhu return err;
134667653936SRoopa Prabhu }
134767653936SRoopa Prabhu
134867653936SRoopa Prabhu /* Dump forwarding table */
vxlan_fdb_dump(struct sk_buff * skb,struct netlink_callback * cb,struct net_device * dev,struct net_device * filter_dev,int * idx)134967653936SRoopa Prabhu static int vxlan_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
135067653936SRoopa Prabhu struct net_device *dev,
135167653936SRoopa Prabhu struct net_device *filter_dev, int *idx)
135267653936SRoopa Prabhu {
135367653936SRoopa Prabhu struct vxlan_dev *vxlan = netdev_priv(dev);
135467653936SRoopa Prabhu unsigned int h;
135567653936SRoopa Prabhu int err = 0;
135667653936SRoopa Prabhu
135767653936SRoopa Prabhu for (h = 0; h < FDB_HASH_SIZE; ++h) {
135867653936SRoopa Prabhu struct vxlan_fdb *f;
135967653936SRoopa Prabhu
136067653936SRoopa Prabhu rcu_read_lock();
136167653936SRoopa Prabhu hlist_for_each_entry_rcu(f, &vxlan->fdb_head[h], hlist) {
136267653936SRoopa Prabhu struct vxlan_rdst *rd;
136367653936SRoopa Prabhu
136467653936SRoopa Prabhu if (rcu_access_pointer(f->nh)) {
136567653936SRoopa Prabhu if (*idx < cb->args[2])
136667653936SRoopa Prabhu goto skip_nh;
136767653936SRoopa Prabhu err = vxlan_fdb_info(skb, vxlan, f,
136867653936SRoopa Prabhu NETLINK_CB(cb->skb).portid,
136967653936SRoopa Prabhu cb->nlh->nlmsg_seq,
137067653936SRoopa Prabhu RTM_NEWNEIGH,
137167653936SRoopa Prabhu NLM_F_MULTI, NULL);
137267653936SRoopa Prabhu if (err < 0) {
137367653936SRoopa Prabhu rcu_read_unlock();
137467653936SRoopa Prabhu goto out;
137567653936SRoopa Prabhu }
137667653936SRoopa Prabhu skip_nh:
137767653936SRoopa Prabhu *idx += 1;
137867653936SRoopa Prabhu continue;
137967653936SRoopa Prabhu }
138067653936SRoopa Prabhu
138167653936SRoopa Prabhu list_for_each_entry_rcu(rd, &f->remotes, list) {
138267653936SRoopa Prabhu if (*idx < cb->args[2])
138367653936SRoopa Prabhu goto skip;
138467653936SRoopa Prabhu
138567653936SRoopa Prabhu err = vxlan_fdb_info(skb, vxlan, f,
138667653936SRoopa Prabhu NETLINK_CB(cb->skb).portid,
138767653936SRoopa Prabhu cb->nlh->nlmsg_seq,
138867653936SRoopa Prabhu RTM_NEWNEIGH,
138967653936SRoopa Prabhu NLM_F_MULTI, rd);
139067653936SRoopa Prabhu if (err < 0) {
139167653936SRoopa Prabhu rcu_read_unlock();
139267653936SRoopa Prabhu goto out;
139367653936SRoopa Prabhu }
139467653936SRoopa Prabhu skip:
139567653936SRoopa Prabhu *idx += 1;
139667653936SRoopa Prabhu }
139767653936SRoopa Prabhu }
139867653936SRoopa Prabhu rcu_read_unlock();
139967653936SRoopa Prabhu }
140067653936SRoopa Prabhu out:
140167653936SRoopa Prabhu return err;
140267653936SRoopa Prabhu }
140367653936SRoopa Prabhu
vxlan_fdb_get(struct sk_buff * skb,struct nlattr * tb[],struct net_device * dev,const unsigned char * addr,u16 vid,u32 portid,u32 seq,struct netlink_ext_ack * extack)140467653936SRoopa Prabhu static int vxlan_fdb_get(struct sk_buff *skb,
140567653936SRoopa Prabhu struct nlattr *tb[],
140667653936SRoopa Prabhu struct net_device *dev,
140767653936SRoopa Prabhu const unsigned char *addr,
140867653936SRoopa Prabhu u16 vid, u32 portid, u32 seq,
140967653936SRoopa Prabhu struct netlink_ext_ack *extack)
141067653936SRoopa Prabhu {
141167653936SRoopa Prabhu struct vxlan_dev *vxlan = netdev_priv(dev);
141267653936SRoopa Prabhu struct vxlan_fdb *f;
141367653936SRoopa Prabhu __be32 vni;
141467653936SRoopa Prabhu int err;
141567653936SRoopa Prabhu
141667653936SRoopa Prabhu if (tb[NDA_VNI])
141767653936SRoopa Prabhu vni = cpu_to_be32(nla_get_u32(tb[NDA_VNI]));
141867653936SRoopa Prabhu else
141967653936SRoopa Prabhu vni = vxlan->default_dst.remote_vni;
142067653936SRoopa Prabhu
142167653936SRoopa Prabhu rcu_read_lock();
142267653936SRoopa Prabhu
142367653936SRoopa Prabhu f = __vxlan_find_mac(vxlan, addr, vni);
142467653936SRoopa Prabhu if (!f) {
142567653936SRoopa Prabhu NL_SET_ERR_MSG(extack, "Fdb entry not found");
142667653936SRoopa Prabhu err = -ENOENT;
142767653936SRoopa Prabhu goto errout;
142867653936SRoopa Prabhu }
142967653936SRoopa Prabhu
143067653936SRoopa Prabhu err = vxlan_fdb_info(skb, vxlan, f, portid, seq,
143167653936SRoopa Prabhu RTM_NEWNEIGH, 0, first_remote_rcu(f));
143267653936SRoopa Prabhu errout:
143367653936SRoopa Prabhu rcu_read_unlock();
143467653936SRoopa Prabhu return err;
143567653936SRoopa Prabhu }
143667653936SRoopa Prabhu
143767653936SRoopa Prabhu /* Watch incoming packets to learn mapping between Ethernet address
143867653936SRoopa Prabhu * and Tunnel endpoint.
143967653936SRoopa Prabhu * Return true if packet is bogus and should be dropped.
144067653936SRoopa Prabhu */
vxlan_snoop(struct net_device * dev,union vxlan_addr * src_ip,const u8 * src_mac,u32 src_ifindex,__be32 vni)144167653936SRoopa Prabhu static bool vxlan_snoop(struct net_device *dev,
144267653936SRoopa Prabhu union vxlan_addr *src_ip, const u8 *src_mac,
144367653936SRoopa Prabhu u32 src_ifindex, __be32 vni)
144467653936SRoopa Prabhu {
144567653936SRoopa Prabhu struct vxlan_dev *vxlan = netdev_priv(dev);
144667653936SRoopa Prabhu struct vxlan_fdb *f;
144767653936SRoopa Prabhu u32 ifindex = 0;
144867653936SRoopa Prabhu
1449924f7bbfSDaniel Borkmann /* Ignore packets from invalid src-address */
1450924f7bbfSDaniel Borkmann if (!is_valid_ether_addr(src_mac))
1451924f7bbfSDaniel Borkmann return true;
1452924f7bbfSDaniel Borkmann
145367653936SRoopa Prabhu #if IS_ENABLED(CONFIG_IPV6)
145467653936SRoopa Prabhu if (src_ip->sa.sa_family == AF_INET6 &&
145567653936SRoopa Prabhu (ipv6_addr_type(&src_ip->sin6.sin6_addr) & IPV6_ADDR_LINKLOCAL))
145667653936SRoopa Prabhu ifindex = src_ifindex;
145767653936SRoopa Prabhu #endif
145867653936SRoopa Prabhu
145967653936SRoopa Prabhu f = vxlan_find_mac(vxlan, src_mac, vni);
146067653936SRoopa Prabhu if (likely(f)) {
146167653936SRoopa Prabhu struct vxlan_rdst *rdst = first_remote_rcu(f);
146267653936SRoopa Prabhu
146367653936SRoopa Prabhu if (likely(vxlan_addr_equal(&rdst->remote_ip, src_ip) &&
146467653936SRoopa Prabhu rdst->remote_ifindex == ifindex))
146567653936SRoopa Prabhu return false;
146667653936SRoopa Prabhu
146767653936SRoopa Prabhu /* Don't migrate static entries, drop packets */
146867653936SRoopa Prabhu if (f->state & (NUD_PERMANENT | NUD_NOARP))
146967653936SRoopa Prabhu return true;
147067653936SRoopa Prabhu
147167653936SRoopa Prabhu /* Don't override an fdb with nexthop with a learnt entry */
147267653936SRoopa Prabhu if (rcu_access_pointer(f->nh))
147367653936SRoopa Prabhu return true;
147467653936SRoopa Prabhu
147567653936SRoopa Prabhu if (net_ratelimit())
147667653936SRoopa Prabhu netdev_info(dev,
147767653936SRoopa Prabhu "%pM migrated from %pIS to %pIS\n",
147867653936SRoopa Prabhu src_mac, &rdst->remote_ip.sa, &src_ip->sa);
147967653936SRoopa Prabhu
148067653936SRoopa Prabhu rdst->remote_ip = *src_ip;
148167653936SRoopa Prabhu f->updated = jiffies;
148267653936SRoopa Prabhu vxlan_fdb_notify(vxlan, f, rdst, RTM_NEWNEIGH, true, NULL);
148367653936SRoopa Prabhu } else {
148467653936SRoopa Prabhu u32 hash_index = fdb_head_index(vxlan, src_mac, vni);
148567653936SRoopa Prabhu
148667653936SRoopa Prabhu /* learned new entry */
148767653936SRoopa Prabhu spin_lock(&vxlan->hash_lock[hash_index]);
148867653936SRoopa Prabhu
148967653936SRoopa Prabhu /* close off race between vxlan_flush and incoming packets */
149067653936SRoopa Prabhu if (netif_running(dev))
149167653936SRoopa Prabhu vxlan_fdb_update(vxlan, src_mac, src_ip,
149267653936SRoopa Prabhu NUD_REACHABLE,
149367653936SRoopa Prabhu NLM_F_EXCL|NLM_F_CREATE,
149467653936SRoopa Prabhu vxlan->cfg.dst_port,
149567653936SRoopa Prabhu vni,
149667653936SRoopa Prabhu vxlan->default_dst.remote_vni,
149767653936SRoopa Prabhu ifindex, NTF_SELF, 0, true, NULL);
149867653936SRoopa Prabhu spin_unlock(&vxlan->hash_lock[hash_index]);
149967653936SRoopa Prabhu }
150067653936SRoopa Prabhu
150167653936SRoopa Prabhu return false;
150267653936SRoopa Prabhu }
150367653936SRoopa Prabhu
__vxlan_sock_release_prep(struct vxlan_sock * vs)150467653936SRoopa Prabhu static bool __vxlan_sock_release_prep(struct vxlan_sock *vs)
150567653936SRoopa Prabhu {
150667653936SRoopa Prabhu struct vxlan_net *vn;
150767653936SRoopa Prabhu
150867653936SRoopa Prabhu if (!vs)
150967653936SRoopa Prabhu return false;
151067653936SRoopa Prabhu if (!refcount_dec_and_test(&vs->refcnt))
151167653936SRoopa Prabhu return false;
151267653936SRoopa Prabhu
151367653936SRoopa Prabhu vn = net_generic(sock_net(vs->sock->sk), vxlan_net_id);
151467653936SRoopa Prabhu spin_lock(&vn->sock_lock);
151567653936SRoopa Prabhu hlist_del_rcu(&vs->hlist);
151667653936SRoopa Prabhu udp_tunnel_notify_del_rx_port(vs->sock,
151767653936SRoopa Prabhu (vs->flags & VXLAN_F_GPE) ?
151867653936SRoopa Prabhu UDP_TUNNEL_TYPE_VXLAN_GPE :
151967653936SRoopa Prabhu UDP_TUNNEL_TYPE_VXLAN);
152067653936SRoopa Prabhu spin_unlock(&vn->sock_lock);
152167653936SRoopa Prabhu
152267653936SRoopa Prabhu return true;
152367653936SRoopa Prabhu }
152467653936SRoopa Prabhu
vxlan_sock_release(struct vxlan_dev * vxlan)152567653936SRoopa Prabhu static void vxlan_sock_release(struct vxlan_dev *vxlan)
152667653936SRoopa Prabhu {
152767653936SRoopa Prabhu struct vxlan_sock *sock4 = rtnl_dereference(vxlan->vn4_sock);
152867653936SRoopa Prabhu #if IS_ENABLED(CONFIG_IPV6)
152967653936SRoopa Prabhu struct vxlan_sock *sock6 = rtnl_dereference(vxlan->vn6_sock);
153067653936SRoopa Prabhu
153167653936SRoopa Prabhu RCU_INIT_POINTER(vxlan->vn6_sock, NULL);
153267653936SRoopa Prabhu #endif
153367653936SRoopa Prabhu
153467653936SRoopa Prabhu RCU_INIT_POINTER(vxlan->vn4_sock, NULL);
153567653936SRoopa Prabhu synchronize_net();
153667653936SRoopa Prabhu
1537f9c4bb0bSRoopa Prabhu if (vxlan->cfg.flags & VXLAN_F_VNIFILTER)
1538f9c4bb0bSRoopa Prabhu vxlan_vs_del_vnigrp(vxlan);
1539f9c4bb0bSRoopa Prabhu else
154067653936SRoopa Prabhu vxlan_vs_del_dev(vxlan);
154167653936SRoopa Prabhu
154267653936SRoopa Prabhu if (__vxlan_sock_release_prep(sock4)) {
154367653936SRoopa Prabhu udp_tunnel_sock_release(sock4->sock);
154467653936SRoopa Prabhu kfree(sock4);
154567653936SRoopa Prabhu }
154667653936SRoopa Prabhu
154767653936SRoopa Prabhu #if IS_ENABLED(CONFIG_IPV6)
154867653936SRoopa Prabhu if (__vxlan_sock_release_prep(sock6)) {
154967653936SRoopa Prabhu udp_tunnel_sock_release(sock6->sock);
155067653936SRoopa Prabhu kfree(sock6);
155167653936SRoopa Prabhu }
155267653936SRoopa Prabhu #endif
155367653936SRoopa Prabhu }
155467653936SRoopa Prabhu
vxlan_remcsum(struct vxlanhdr * unparsed,struct sk_buff * skb,u32 vxflags)155567653936SRoopa Prabhu static bool vxlan_remcsum(struct vxlanhdr *unparsed,
155667653936SRoopa Prabhu struct sk_buff *skb, u32 vxflags)
155767653936SRoopa Prabhu {
155867653936SRoopa Prabhu size_t start, offset;
155967653936SRoopa Prabhu
156067653936SRoopa Prabhu if (!(unparsed->vx_flags & VXLAN_HF_RCO) || skb->remcsum_offload)
156167653936SRoopa Prabhu goto out;
156267653936SRoopa Prabhu
156367653936SRoopa Prabhu start = vxlan_rco_start(unparsed->vx_vni);
156467653936SRoopa Prabhu offset = start + vxlan_rco_offset(unparsed->vx_vni);
156567653936SRoopa Prabhu
156667653936SRoopa Prabhu if (!pskb_may_pull(skb, offset + sizeof(u16)))
156767653936SRoopa Prabhu return false;
156867653936SRoopa Prabhu
156967653936SRoopa Prabhu skb_remcsum_process(skb, (void *)(vxlan_hdr(skb) + 1), start, offset,
157067653936SRoopa Prabhu !!(vxflags & VXLAN_F_REMCSUM_NOPARTIAL));
157167653936SRoopa Prabhu out:
157267653936SRoopa Prabhu unparsed->vx_flags &= ~VXLAN_HF_RCO;
157367653936SRoopa Prabhu unparsed->vx_vni &= VXLAN_VNI_MASK;
157467653936SRoopa Prabhu return true;
157567653936SRoopa Prabhu }
157667653936SRoopa Prabhu
vxlan_parse_gbp_hdr(struct vxlanhdr * unparsed,struct sk_buff * skb,u32 vxflags,struct vxlan_metadata * md)157767653936SRoopa Prabhu static void vxlan_parse_gbp_hdr(struct vxlanhdr *unparsed,
157867653936SRoopa Prabhu struct sk_buff *skb, u32 vxflags,
157967653936SRoopa Prabhu struct vxlan_metadata *md)
158067653936SRoopa Prabhu {
158167653936SRoopa Prabhu struct vxlanhdr_gbp *gbp = (struct vxlanhdr_gbp *)unparsed;
158267653936SRoopa Prabhu struct metadata_dst *tun_dst;
158367653936SRoopa Prabhu
158467653936SRoopa Prabhu if (!(unparsed->vx_flags & VXLAN_HF_GBP))
158567653936SRoopa Prabhu goto out;
158667653936SRoopa Prabhu
158767653936SRoopa Prabhu md->gbp = ntohs(gbp->policy_id);
158867653936SRoopa Prabhu
158967653936SRoopa Prabhu tun_dst = (struct metadata_dst *)skb_dst(skb);
159067653936SRoopa Prabhu if (tun_dst) {
159167653936SRoopa Prabhu tun_dst->u.tun_info.key.tun_flags |= TUNNEL_VXLAN_OPT;
159267653936SRoopa Prabhu tun_dst->u.tun_info.options_len = sizeof(*md);
159367653936SRoopa Prabhu }
159467653936SRoopa Prabhu if (gbp->dont_learn)
159567653936SRoopa Prabhu md->gbp |= VXLAN_GBP_DONT_LEARN;
159667653936SRoopa Prabhu
159767653936SRoopa Prabhu if (gbp->policy_applied)
159867653936SRoopa Prabhu md->gbp |= VXLAN_GBP_POLICY_APPLIED;
159967653936SRoopa Prabhu
160067653936SRoopa Prabhu /* In flow-based mode, GBP is carried in dst_metadata */
160167653936SRoopa Prabhu if (!(vxflags & VXLAN_F_COLLECT_METADATA))
160267653936SRoopa Prabhu skb->mark = md->gbp;
160367653936SRoopa Prabhu out:
160467653936SRoopa Prabhu unparsed->vx_flags &= ~VXLAN_GBP_USED_BITS;
160567653936SRoopa Prabhu }
160667653936SRoopa Prabhu
vxlan_set_mac(struct vxlan_dev * vxlan,struct vxlan_sock * vs,struct sk_buff * skb,__be32 vni)160767653936SRoopa Prabhu static bool vxlan_set_mac(struct vxlan_dev *vxlan,
160867653936SRoopa Prabhu struct vxlan_sock *vs,
160967653936SRoopa Prabhu struct sk_buff *skb, __be32 vni)
161067653936SRoopa Prabhu {
161167653936SRoopa Prabhu union vxlan_addr saddr;
161267653936SRoopa Prabhu u32 ifindex = skb->dev->ifindex;
161367653936SRoopa Prabhu
161467653936SRoopa Prabhu skb_reset_mac_header(skb);
161567653936SRoopa Prabhu skb->protocol = eth_type_trans(skb, vxlan->dev);
161667653936SRoopa Prabhu skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN);
161767653936SRoopa Prabhu
161867653936SRoopa Prabhu /* Ignore packet loops (and multicast echo) */
161967653936SRoopa Prabhu if (ether_addr_equal(eth_hdr(skb)->h_source, vxlan->dev->dev_addr))
162067653936SRoopa Prabhu return false;
162167653936SRoopa Prabhu
162267653936SRoopa Prabhu /* Get address from the outer IP header */
162367653936SRoopa Prabhu if (vxlan_get_sk_family(vs) == AF_INET) {
162467653936SRoopa Prabhu saddr.sin.sin_addr.s_addr = ip_hdr(skb)->saddr;
162567653936SRoopa Prabhu saddr.sa.sa_family = AF_INET;
162667653936SRoopa Prabhu #if IS_ENABLED(CONFIG_IPV6)
162767653936SRoopa Prabhu } else {
162867653936SRoopa Prabhu saddr.sin6.sin6_addr = ipv6_hdr(skb)->saddr;
162967653936SRoopa Prabhu saddr.sa.sa_family = AF_INET6;
163067653936SRoopa Prabhu #endif
163167653936SRoopa Prabhu }
163267653936SRoopa Prabhu
163367653936SRoopa Prabhu if ((vxlan->cfg.flags & VXLAN_F_LEARN) &&
163467653936SRoopa Prabhu vxlan_snoop(skb->dev, &saddr, eth_hdr(skb)->h_source, ifindex, vni))
163567653936SRoopa Prabhu return false;
163667653936SRoopa Prabhu
163767653936SRoopa Prabhu return true;
163867653936SRoopa Prabhu }
163967653936SRoopa Prabhu
vxlan_ecn_decapsulate(struct vxlan_sock * vs,void * oiph,struct sk_buff * skb)164067653936SRoopa Prabhu static bool vxlan_ecn_decapsulate(struct vxlan_sock *vs, void *oiph,
164167653936SRoopa Prabhu struct sk_buff *skb)
164267653936SRoopa Prabhu {
164367653936SRoopa Prabhu int err = 0;
164467653936SRoopa Prabhu
164567653936SRoopa Prabhu if (vxlan_get_sk_family(vs) == AF_INET)
164667653936SRoopa Prabhu err = IP_ECN_decapsulate(oiph, skb);
164767653936SRoopa Prabhu #if IS_ENABLED(CONFIG_IPV6)
164867653936SRoopa Prabhu else
164967653936SRoopa Prabhu err = IP6_ECN_decapsulate(oiph, skb);
165067653936SRoopa Prabhu #endif
165167653936SRoopa Prabhu
165267653936SRoopa Prabhu if (unlikely(err) && log_ecn_error) {
165367653936SRoopa Prabhu if (vxlan_get_sk_family(vs) == AF_INET)
165467653936SRoopa Prabhu net_info_ratelimited("non-ECT from %pI4 with TOS=%#x\n",
165567653936SRoopa Prabhu &((struct iphdr *)oiph)->saddr,
165667653936SRoopa Prabhu ((struct iphdr *)oiph)->tos);
165767653936SRoopa Prabhu else
165867653936SRoopa Prabhu net_info_ratelimited("non-ECT from %pI6\n",
165967653936SRoopa Prabhu &((struct ipv6hdr *)oiph)->saddr);
166067653936SRoopa Prabhu }
166167653936SRoopa Prabhu return err <= 1;
166267653936SRoopa Prabhu }
166367653936SRoopa Prabhu
166467653936SRoopa Prabhu /* Callback from net/ipv4/udp.c to receive packets */
vxlan_rcv(struct sock * sk,struct sk_buff * skb)166567653936SRoopa Prabhu static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
166667653936SRoopa Prabhu {
16674095e0e1SNikolay Aleksandrov struct vxlan_vni_node *vninode = NULL;
166867653936SRoopa Prabhu struct vxlan_dev *vxlan;
166967653936SRoopa Prabhu struct vxlan_sock *vs;
167067653936SRoopa Prabhu struct vxlanhdr unparsed;
167167653936SRoopa Prabhu struct vxlan_metadata _md;
167267653936SRoopa Prabhu struct vxlan_metadata *md = &_md;
167367653936SRoopa Prabhu __be16 protocol = htons(ETH_P_TEB);
167467653936SRoopa Prabhu bool raw_proto = false;
167567653936SRoopa Prabhu void *oiph;
167667653936SRoopa Prabhu __be32 vni = 0;
1677935bcb52SGuillaume Nault int nh;
167867653936SRoopa Prabhu
167967653936SRoopa Prabhu /* Need UDP and VXLAN header to be present */
168067653936SRoopa Prabhu if (!pskb_may_pull(skb, VXLAN_HLEN))
168167653936SRoopa Prabhu goto drop;
168267653936SRoopa Prabhu
168367653936SRoopa Prabhu unparsed = *vxlan_hdr(skb);
168467653936SRoopa Prabhu /* VNI flag always required to be set */
168567653936SRoopa Prabhu if (!(unparsed.vx_flags & VXLAN_HF_VNI)) {
168667653936SRoopa Prabhu netdev_dbg(skb->dev, "invalid vxlan flags=%#x vni=%#x\n",
168767653936SRoopa Prabhu ntohl(vxlan_hdr(skb)->vx_flags),
168867653936SRoopa Prabhu ntohl(vxlan_hdr(skb)->vx_vni));
168967653936SRoopa Prabhu /* Return non vxlan pkt */
169067653936SRoopa Prabhu goto drop;
169167653936SRoopa Prabhu }
169267653936SRoopa Prabhu unparsed.vx_flags &= ~VXLAN_HF_VNI;
169367653936SRoopa Prabhu unparsed.vx_vni &= ~VXLAN_VNI_MASK;
169467653936SRoopa Prabhu
169567653936SRoopa Prabhu vs = rcu_dereference_sk_user_data(sk);
169667653936SRoopa Prabhu if (!vs)
169767653936SRoopa Prabhu goto drop;
169867653936SRoopa Prabhu
169967653936SRoopa Prabhu vni = vxlan_vni(vxlan_hdr(skb)->vx_vni);
170067653936SRoopa Prabhu
17014095e0e1SNikolay Aleksandrov vxlan = vxlan_vs_find_vni(vs, skb->dev->ifindex, vni, &vninode);
170267653936SRoopa Prabhu if (!vxlan)
170367653936SRoopa Prabhu goto drop;
170467653936SRoopa Prabhu
170567653936SRoopa Prabhu /* For backwards compatibility, only allow reserved fields to be
170667653936SRoopa Prabhu * used by VXLAN extensions if explicitly requested.
170767653936SRoopa Prabhu */
170867653936SRoopa Prabhu if (vs->flags & VXLAN_F_GPE) {
170917a0a644SJiri Benc if (!vxlan_parse_gpe_proto(&unparsed, &protocol))
171067653936SRoopa Prabhu goto drop;
171117a0a644SJiri Benc unparsed.vx_flags &= ~VXLAN_GPE_USED_BITS;
171267653936SRoopa Prabhu raw_proto = true;
171367653936SRoopa Prabhu }
171467653936SRoopa Prabhu
171567653936SRoopa Prabhu if (__iptunnel_pull_header(skb, VXLAN_HLEN, protocol, raw_proto,
171667653936SRoopa Prabhu !net_eq(vxlan->net, dev_net(vxlan->dev))))
171767653936SRoopa Prabhu goto drop;
171867653936SRoopa Prabhu
171967653936SRoopa Prabhu if (vs->flags & VXLAN_F_REMCSUM_RX)
172067653936SRoopa Prabhu if (unlikely(!vxlan_remcsum(&unparsed, skb, vs->flags)))
172167653936SRoopa Prabhu goto drop;
172267653936SRoopa Prabhu
172367653936SRoopa Prabhu if (vxlan_collect_metadata(vs)) {
172467653936SRoopa Prabhu struct metadata_dst *tun_dst;
172567653936SRoopa Prabhu
172667653936SRoopa Prabhu tun_dst = udp_tun_rx_dst(skb, vxlan_get_sk_family(vs), TUNNEL_KEY,
172767653936SRoopa Prabhu key32_to_tunnel_id(vni), sizeof(*md));
172867653936SRoopa Prabhu
172967653936SRoopa Prabhu if (!tun_dst)
173067653936SRoopa Prabhu goto drop;
173167653936SRoopa Prabhu
173267653936SRoopa Prabhu md = ip_tunnel_info_opts(&tun_dst->u.tun_info);
173367653936SRoopa Prabhu
173467653936SRoopa Prabhu skb_dst_set(skb, (struct dst_entry *)tun_dst);
173567653936SRoopa Prabhu } else {
173667653936SRoopa Prabhu memset(md, 0, sizeof(*md));
173767653936SRoopa Prabhu }
173867653936SRoopa Prabhu
173967653936SRoopa Prabhu if (vs->flags & VXLAN_F_GBP)
174067653936SRoopa Prabhu vxlan_parse_gbp_hdr(&unparsed, skb, vs->flags, md);
174167653936SRoopa Prabhu /* Note that GBP and GPE can never be active together. This is
174267653936SRoopa Prabhu * ensured in vxlan_dev_configure.
174367653936SRoopa Prabhu */
174467653936SRoopa Prabhu
174567653936SRoopa Prabhu if (unparsed.vx_flags || unparsed.vx_vni) {
174667653936SRoopa Prabhu /* If there are any unprocessed flags remaining treat
174767653936SRoopa Prabhu * this as a malformed packet. This behavior diverges from
174867653936SRoopa Prabhu * VXLAN RFC (RFC7348) which stipulates that bits in reserved
174967653936SRoopa Prabhu * in reserved fields are to be ignored. The approach here
175067653936SRoopa Prabhu * maintains compatibility with previous stack code, and also
175167653936SRoopa Prabhu * is more robust and provides a little more security in
175267653936SRoopa Prabhu * adding extensions to VXLAN.
175367653936SRoopa Prabhu */
175467653936SRoopa Prabhu goto drop;
175567653936SRoopa Prabhu }
175667653936SRoopa Prabhu
175767653936SRoopa Prabhu if (!raw_proto) {
175867653936SRoopa Prabhu if (!vxlan_set_mac(vxlan, vs, skb, vni))
175967653936SRoopa Prabhu goto drop;
176067653936SRoopa Prabhu } else {
176167653936SRoopa Prabhu skb_reset_mac_header(skb);
176267653936SRoopa Prabhu skb->dev = vxlan->dev;
176367653936SRoopa Prabhu skb->pkt_type = PACKET_HOST;
176467653936SRoopa Prabhu }
176567653936SRoopa Prabhu
1766935bcb52SGuillaume Nault /* Save offset of outer header relative to skb->head,
1767935bcb52SGuillaume Nault * because we are going to reset the network header to the inner header
1768935bcb52SGuillaume Nault * and might change skb->head.
1769935bcb52SGuillaume Nault */
1770935bcb52SGuillaume Nault nh = skb_network_header(skb) - skb->head;
1771935bcb52SGuillaume Nault
177267653936SRoopa Prabhu skb_reset_network_header(skb);
177367653936SRoopa Prabhu
1774935bcb52SGuillaume Nault if (!pskb_inet_may_pull(skb)) {
1775935bcb52SGuillaume Nault DEV_STATS_INC(vxlan->dev, rx_length_errors);
1776935bcb52SGuillaume Nault DEV_STATS_INC(vxlan->dev, rx_errors);
1777935bcb52SGuillaume Nault vxlan_vnifilter_count(vxlan, vni, vninode,
1778935bcb52SGuillaume Nault VXLAN_VNI_STATS_RX_ERRORS, 0);
1779935bcb52SGuillaume Nault goto drop;
1780935bcb52SGuillaume Nault }
1781935bcb52SGuillaume Nault
1782935bcb52SGuillaume Nault /* Get the outer header. */
1783935bcb52SGuillaume Nault oiph = skb->head + nh;
1784935bcb52SGuillaume Nault
178567653936SRoopa Prabhu if (!vxlan_ecn_decapsulate(vs, oiph, skb)) {
178684321030SGuillaume Nault DEV_STATS_INC(vxlan->dev, rx_frame_errors);
178784321030SGuillaume Nault DEV_STATS_INC(vxlan->dev, rx_errors);
17884095e0e1SNikolay Aleksandrov vxlan_vnifilter_count(vxlan, vni, vninode,
17894095e0e1SNikolay Aleksandrov VXLAN_VNI_STATS_RX_ERRORS, 0);
179067653936SRoopa Prabhu goto drop;
179167653936SRoopa Prabhu }
179267653936SRoopa Prabhu
179367653936SRoopa Prabhu rcu_read_lock();
179467653936SRoopa Prabhu
179567653936SRoopa Prabhu if (unlikely(!(vxlan->dev->flags & IFF_UP))) {
179667653936SRoopa Prabhu rcu_read_unlock();
1797625788b5SEric Dumazet dev_core_stats_rx_dropped_inc(vxlan->dev);
17984095e0e1SNikolay Aleksandrov vxlan_vnifilter_count(vxlan, vni, vninode,
17994095e0e1SNikolay Aleksandrov VXLAN_VNI_STATS_RX_DROPS, 0);
180067653936SRoopa Prabhu goto drop;
180167653936SRoopa Prabhu }
180267653936SRoopa Prabhu
180367653936SRoopa Prabhu dev_sw_netstats_rx_add(vxlan->dev, skb->len);
18044095e0e1SNikolay Aleksandrov vxlan_vnifilter_count(vxlan, vni, vninode, VXLAN_VNI_STATS_RX, skb->len);
180567653936SRoopa Prabhu gro_cells_receive(&vxlan->gro_cells, skb);
180667653936SRoopa Prabhu
180767653936SRoopa Prabhu rcu_read_unlock();
180867653936SRoopa Prabhu
180967653936SRoopa Prabhu return 0;
181067653936SRoopa Prabhu
181167653936SRoopa Prabhu drop:
181267653936SRoopa Prabhu /* Consume bad packet */
181367653936SRoopa Prabhu kfree_skb(skb);
181467653936SRoopa Prabhu return 0;
181567653936SRoopa Prabhu }
181667653936SRoopa Prabhu
181767653936SRoopa Prabhu /* Callback from net/ipv{4,6}/udp.c to check that we have a VNI for errors */
vxlan_err_lookup(struct sock * sk,struct sk_buff * skb)181867653936SRoopa Prabhu static int vxlan_err_lookup(struct sock *sk, struct sk_buff *skb)
181967653936SRoopa Prabhu {
182067653936SRoopa Prabhu struct vxlan_dev *vxlan;
182167653936SRoopa Prabhu struct vxlan_sock *vs;
182267653936SRoopa Prabhu struct vxlanhdr *hdr;
182367653936SRoopa Prabhu __be32 vni;
182467653936SRoopa Prabhu
182567653936SRoopa Prabhu if (!pskb_may_pull(skb, skb_transport_offset(skb) + VXLAN_HLEN))
182667653936SRoopa Prabhu return -EINVAL;
182767653936SRoopa Prabhu
182867653936SRoopa Prabhu hdr = vxlan_hdr(skb);
182967653936SRoopa Prabhu
183067653936SRoopa Prabhu if (!(hdr->vx_flags & VXLAN_HF_VNI))
183167653936SRoopa Prabhu return -EINVAL;
183267653936SRoopa Prabhu
183367653936SRoopa Prabhu vs = rcu_dereference_sk_user_data(sk);
183467653936SRoopa Prabhu if (!vs)
183567653936SRoopa Prabhu return -ENOENT;
183667653936SRoopa Prabhu
183767653936SRoopa Prabhu vni = vxlan_vni(hdr->vx_vni);
18384095e0e1SNikolay Aleksandrov vxlan = vxlan_vs_find_vni(vs, skb->dev->ifindex, vni, NULL);
183967653936SRoopa Prabhu if (!vxlan)
184067653936SRoopa Prabhu return -ENOENT;
184167653936SRoopa Prabhu
184267653936SRoopa Prabhu return 0;
184367653936SRoopa Prabhu }
184467653936SRoopa Prabhu
arp_reduce(struct net_device * dev,struct sk_buff * skb,__be32 vni)184567653936SRoopa Prabhu static int arp_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni)
184667653936SRoopa Prabhu {
184767653936SRoopa Prabhu struct vxlan_dev *vxlan = netdev_priv(dev);
184867653936SRoopa Prabhu struct arphdr *parp;
184967653936SRoopa Prabhu u8 *arpptr, *sha;
185067653936SRoopa Prabhu __be32 sip, tip;
185167653936SRoopa Prabhu struct neighbour *n;
185267653936SRoopa Prabhu
185367653936SRoopa Prabhu if (dev->flags & IFF_NOARP)
185467653936SRoopa Prabhu goto out;
185567653936SRoopa Prabhu
185667653936SRoopa Prabhu if (!pskb_may_pull(skb, arp_hdr_len(dev))) {
185784321030SGuillaume Nault dev_core_stats_tx_dropped_inc(dev);
18580ba4fd45SGuillaume Nault vxlan_vnifilter_count(vxlan, vni, NULL,
18590ba4fd45SGuillaume Nault VXLAN_VNI_STATS_TX_DROPS, 0);
186067653936SRoopa Prabhu goto out;
186167653936SRoopa Prabhu }
186267653936SRoopa Prabhu parp = arp_hdr(skb);
186367653936SRoopa Prabhu
186467653936SRoopa Prabhu if ((parp->ar_hrd != htons(ARPHRD_ETHER) &&
186567653936SRoopa Prabhu parp->ar_hrd != htons(ARPHRD_IEEE802)) ||
186667653936SRoopa Prabhu parp->ar_pro != htons(ETH_P_IP) ||
186767653936SRoopa Prabhu parp->ar_op != htons(ARPOP_REQUEST) ||
186867653936SRoopa Prabhu parp->ar_hln != dev->addr_len ||
186967653936SRoopa Prabhu parp->ar_pln != 4)
187067653936SRoopa Prabhu goto out;
187167653936SRoopa Prabhu arpptr = (u8 *)parp + sizeof(struct arphdr);
187267653936SRoopa Prabhu sha = arpptr;
187367653936SRoopa Prabhu arpptr += dev->addr_len; /* sha */
187467653936SRoopa Prabhu memcpy(&sip, arpptr, sizeof(sip));
187567653936SRoopa Prabhu arpptr += sizeof(sip);
187667653936SRoopa Prabhu arpptr += dev->addr_len; /* tha */
187767653936SRoopa Prabhu memcpy(&tip, arpptr, sizeof(tip));
187867653936SRoopa Prabhu
187967653936SRoopa Prabhu if (ipv4_is_loopback(tip) ||
188067653936SRoopa Prabhu ipv4_is_multicast(tip))
188167653936SRoopa Prabhu goto out;
188267653936SRoopa Prabhu
188367653936SRoopa Prabhu n = neigh_lookup(&arp_tbl, &tip, dev);
188467653936SRoopa Prabhu
188567653936SRoopa Prabhu if (n) {
188667653936SRoopa Prabhu struct vxlan_fdb *f;
188767653936SRoopa Prabhu struct sk_buff *reply;
188867653936SRoopa Prabhu
1889b071af52SEric Dumazet if (!(READ_ONCE(n->nud_state) & NUD_CONNECTED)) {
189067653936SRoopa Prabhu neigh_release(n);
189167653936SRoopa Prabhu goto out;
189267653936SRoopa Prabhu }
189367653936SRoopa Prabhu
189467653936SRoopa Prabhu f = vxlan_find_mac(vxlan, n->ha, vni);
189567653936SRoopa Prabhu if (f && vxlan_addr_any(&(first_remote_rcu(f)->remote_ip))) {
189667653936SRoopa Prabhu /* bridge-local neighbor */
189767653936SRoopa Prabhu neigh_release(n);
189867653936SRoopa Prabhu goto out;
189967653936SRoopa Prabhu }
190067653936SRoopa Prabhu
190167653936SRoopa Prabhu reply = arp_create(ARPOP_REPLY, ETH_P_ARP, sip, dev, tip, sha,
190267653936SRoopa Prabhu n->ha, sha);
190367653936SRoopa Prabhu
190467653936SRoopa Prabhu neigh_release(n);
190567653936SRoopa Prabhu
190667653936SRoopa Prabhu if (reply == NULL)
190767653936SRoopa Prabhu goto out;
190867653936SRoopa Prabhu
190967653936SRoopa Prabhu skb_reset_mac_header(reply);
191067653936SRoopa Prabhu __skb_pull(reply, skb_network_offset(reply));
191167653936SRoopa Prabhu reply->ip_summed = CHECKSUM_UNNECESSARY;
191267653936SRoopa Prabhu reply->pkt_type = PACKET_HOST;
191367653936SRoopa Prabhu
19143d391f65SSebastian Andrzej Siewior if (netif_rx(reply) == NET_RX_DROP) {
191584321030SGuillaume Nault dev_core_stats_rx_dropped_inc(dev);
19164095e0e1SNikolay Aleksandrov vxlan_vnifilter_count(vxlan, vni, NULL,
19174095e0e1SNikolay Aleksandrov VXLAN_VNI_STATS_RX_DROPS, 0);
19184095e0e1SNikolay Aleksandrov }
19194095e0e1SNikolay Aleksandrov
192067653936SRoopa Prabhu } else if (vxlan->cfg.flags & VXLAN_F_L3MISS) {
192167653936SRoopa Prabhu union vxlan_addr ipa = {
192267653936SRoopa Prabhu .sin.sin_addr.s_addr = tip,
192367653936SRoopa Prabhu .sin.sin_family = AF_INET,
192467653936SRoopa Prabhu };
192567653936SRoopa Prabhu
192667653936SRoopa Prabhu vxlan_ip_miss(dev, &ipa);
192767653936SRoopa Prabhu }
192867653936SRoopa Prabhu out:
192967653936SRoopa Prabhu consume_skb(skb);
193067653936SRoopa Prabhu return NETDEV_TX_OK;
193167653936SRoopa Prabhu }
193267653936SRoopa Prabhu
193367653936SRoopa Prabhu #if IS_ENABLED(CONFIG_IPV6)
vxlan_na_create(struct sk_buff * request,struct neighbour * n,bool isrouter)193467653936SRoopa Prabhu static struct sk_buff *vxlan_na_create(struct sk_buff *request,
193567653936SRoopa Prabhu struct neighbour *n, bool isrouter)
193667653936SRoopa Prabhu {
193767653936SRoopa Prabhu struct net_device *dev = request->dev;
193867653936SRoopa Prabhu struct sk_buff *reply;
193967653936SRoopa Prabhu struct nd_msg *ns, *na;
194067653936SRoopa Prabhu struct ipv6hdr *pip6;
194167653936SRoopa Prabhu u8 *daddr;
194267653936SRoopa Prabhu int na_olen = 8; /* opt hdr + ETH_ALEN for target */
194367653936SRoopa Prabhu int ns_olen;
194467653936SRoopa Prabhu int i, len;
194567653936SRoopa Prabhu
194667653936SRoopa Prabhu if (dev == NULL || !pskb_may_pull(request, request->len))
194767653936SRoopa Prabhu return NULL;
194867653936SRoopa Prabhu
194967653936SRoopa Prabhu len = LL_RESERVED_SPACE(dev) + sizeof(struct ipv6hdr) +
195067653936SRoopa Prabhu sizeof(*na) + na_olen + dev->needed_tailroom;
195167653936SRoopa Prabhu reply = alloc_skb(len, GFP_ATOMIC);
195267653936SRoopa Prabhu if (reply == NULL)
195367653936SRoopa Prabhu return NULL;
195467653936SRoopa Prabhu
195567653936SRoopa Prabhu reply->protocol = htons(ETH_P_IPV6);
195667653936SRoopa Prabhu reply->dev = dev;
195767653936SRoopa Prabhu skb_reserve(reply, LL_RESERVED_SPACE(request->dev));
195867653936SRoopa Prabhu skb_push(reply, sizeof(struct ethhdr));
195967653936SRoopa Prabhu skb_reset_mac_header(reply);
196067653936SRoopa Prabhu
196167653936SRoopa Prabhu ns = (struct nd_msg *)(ipv6_hdr(request) + 1);
196267653936SRoopa Prabhu
196367653936SRoopa Prabhu daddr = eth_hdr(request)->h_source;
196467653936SRoopa Prabhu ns_olen = request->len - skb_network_offset(request) -
196567653936SRoopa Prabhu sizeof(struct ipv6hdr) - sizeof(*ns);
196667653936SRoopa Prabhu for (i = 0; i < ns_olen-1; i += (ns->opt[i+1]<<3)) {
196767653936SRoopa Prabhu if (!ns->opt[i + 1]) {
196867653936SRoopa Prabhu kfree_skb(reply);
196967653936SRoopa Prabhu return NULL;
197067653936SRoopa Prabhu }
197167653936SRoopa Prabhu if (ns->opt[i] == ND_OPT_SOURCE_LL_ADDR) {
197267653936SRoopa Prabhu daddr = ns->opt + i + sizeof(struct nd_opt_hdr);
197367653936SRoopa Prabhu break;
197467653936SRoopa Prabhu }
197567653936SRoopa Prabhu }
197667653936SRoopa Prabhu
197767653936SRoopa Prabhu /* Ethernet header */
197867653936SRoopa Prabhu ether_addr_copy(eth_hdr(reply)->h_dest, daddr);
197967653936SRoopa Prabhu ether_addr_copy(eth_hdr(reply)->h_source, n->ha);
198067653936SRoopa Prabhu eth_hdr(reply)->h_proto = htons(ETH_P_IPV6);
198167653936SRoopa Prabhu reply->protocol = htons(ETH_P_IPV6);
198267653936SRoopa Prabhu
198367653936SRoopa Prabhu skb_pull(reply, sizeof(struct ethhdr));
198467653936SRoopa Prabhu skb_reset_network_header(reply);
198567653936SRoopa Prabhu skb_put(reply, sizeof(struct ipv6hdr));
198667653936SRoopa Prabhu
198767653936SRoopa Prabhu /* IPv6 header */
198867653936SRoopa Prabhu
198967653936SRoopa Prabhu pip6 = ipv6_hdr(reply);
199067653936SRoopa Prabhu memset(pip6, 0, sizeof(struct ipv6hdr));
199167653936SRoopa Prabhu pip6->version = 6;
199267653936SRoopa Prabhu pip6->priority = ipv6_hdr(request)->priority;
199367653936SRoopa Prabhu pip6->nexthdr = IPPROTO_ICMPV6;
199467653936SRoopa Prabhu pip6->hop_limit = 255;
199567653936SRoopa Prabhu pip6->daddr = ipv6_hdr(request)->saddr;
199667653936SRoopa Prabhu pip6->saddr = *(struct in6_addr *)n->primary_key;
199767653936SRoopa Prabhu
199867653936SRoopa Prabhu skb_pull(reply, sizeof(struct ipv6hdr));
199967653936SRoopa Prabhu skb_reset_transport_header(reply);
200067653936SRoopa Prabhu
200167653936SRoopa Prabhu /* Neighbor Advertisement */
200267653936SRoopa Prabhu na = skb_put_zero(reply, sizeof(*na) + na_olen);
200367653936SRoopa Prabhu na->icmph.icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT;
200467653936SRoopa Prabhu na->icmph.icmp6_router = isrouter;
200567653936SRoopa Prabhu na->icmph.icmp6_override = 1;
200667653936SRoopa Prabhu na->icmph.icmp6_solicited = 1;
200767653936SRoopa Prabhu na->target = ns->target;
200867653936SRoopa Prabhu ether_addr_copy(&na->opt[2], n->ha);
200967653936SRoopa Prabhu na->opt[0] = ND_OPT_TARGET_LL_ADDR;
201067653936SRoopa Prabhu na->opt[1] = na_olen >> 3;
201167653936SRoopa Prabhu
201267653936SRoopa Prabhu na->icmph.icmp6_cksum = csum_ipv6_magic(&pip6->saddr,
201367653936SRoopa Prabhu &pip6->daddr, sizeof(*na)+na_olen, IPPROTO_ICMPV6,
201467653936SRoopa Prabhu csum_partial(na, sizeof(*na)+na_olen, 0));
201567653936SRoopa Prabhu
201667653936SRoopa Prabhu pip6->payload_len = htons(sizeof(*na)+na_olen);
201767653936SRoopa Prabhu
201867653936SRoopa Prabhu skb_push(reply, sizeof(struct ipv6hdr));
201967653936SRoopa Prabhu
202067653936SRoopa Prabhu reply->ip_summed = CHECKSUM_UNNECESSARY;
202167653936SRoopa Prabhu
202267653936SRoopa Prabhu return reply;
202367653936SRoopa Prabhu }
202467653936SRoopa Prabhu
neigh_reduce(struct net_device * dev,struct sk_buff * skb,__be32 vni)202567653936SRoopa Prabhu static int neigh_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni)
202667653936SRoopa Prabhu {
202767653936SRoopa Prabhu struct vxlan_dev *vxlan = netdev_priv(dev);
202867653936SRoopa Prabhu const struct in6_addr *daddr;
202967653936SRoopa Prabhu const struct ipv6hdr *iphdr;
203067653936SRoopa Prabhu struct inet6_dev *in6_dev;
203167653936SRoopa Prabhu struct neighbour *n;
203267653936SRoopa Prabhu struct nd_msg *msg;
203367653936SRoopa Prabhu
203467653936SRoopa Prabhu rcu_read_lock();
203567653936SRoopa Prabhu in6_dev = __in6_dev_get(dev);
203667653936SRoopa Prabhu if (!in6_dev)
203767653936SRoopa Prabhu goto out;
203867653936SRoopa Prabhu
203967653936SRoopa Prabhu iphdr = ipv6_hdr(skb);
204067653936SRoopa Prabhu daddr = &iphdr->daddr;
204167653936SRoopa Prabhu msg = (struct nd_msg *)(iphdr + 1);
204267653936SRoopa Prabhu
204367653936SRoopa Prabhu if (ipv6_addr_loopback(daddr) ||
204467653936SRoopa Prabhu ipv6_addr_is_multicast(&msg->target))
204567653936SRoopa Prabhu goto out;
204667653936SRoopa Prabhu
204767653936SRoopa Prabhu n = neigh_lookup(ipv6_stub->nd_tbl, &msg->target, dev);
204867653936SRoopa Prabhu
204967653936SRoopa Prabhu if (n) {
205067653936SRoopa Prabhu struct vxlan_fdb *f;
205167653936SRoopa Prabhu struct sk_buff *reply;
205267653936SRoopa Prabhu
2053b071af52SEric Dumazet if (!(READ_ONCE(n->nud_state) & NUD_CONNECTED)) {
205467653936SRoopa Prabhu neigh_release(n);
205567653936SRoopa Prabhu goto out;
205667653936SRoopa Prabhu }
205767653936SRoopa Prabhu
205867653936SRoopa Prabhu f = vxlan_find_mac(vxlan, n->ha, vni);
205967653936SRoopa Prabhu if (f && vxlan_addr_any(&(first_remote_rcu(f)->remote_ip))) {
206067653936SRoopa Prabhu /* bridge-local neighbor */
206167653936SRoopa Prabhu neigh_release(n);
206267653936SRoopa Prabhu goto out;
206367653936SRoopa Prabhu }
206467653936SRoopa Prabhu
206567653936SRoopa Prabhu reply = vxlan_na_create(skb, n,
206667653936SRoopa Prabhu !!(f ? f->flags & NTF_ROUTER : 0));
206767653936SRoopa Prabhu
206867653936SRoopa Prabhu neigh_release(n);
206967653936SRoopa Prabhu
207067653936SRoopa Prabhu if (reply == NULL)
207167653936SRoopa Prabhu goto out;
207267653936SRoopa Prabhu
20733d391f65SSebastian Andrzej Siewior if (netif_rx(reply) == NET_RX_DROP) {
207484321030SGuillaume Nault dev_core_stats_rx_dropped_inc(dev);
20754095e0e1SNikolay Aleksandrov vxlan_vnifilter_count(vxlan, vni, NULL,
20764095e0e1SNikolay Aleksandrov VXLAN_VNI_STATS_RX_DROPS, 0);
20774095e0e1SNikolay Aleksandrov }
207867653936SRoopa Prabhu } else if (vxlan->cfg.flags & VXLAN_F_L3MISS) {
207967653936SRoopa Prabhu union vxlan_addr ipa = {
208067653936SRoopa Prabhu .sin6.sin6_addr = msg->target,
208167653936SRoopa Prabhu .sin6.sin6_family = AF_INET6,
208267653936SRoopa Prabhu };
208367653936SRoopa Prabhu
208467653936SRoopa Prabhu vxlan_ip_miss(dev, &ipa);
208567653936SRoopa Prabhu }
208667653936SRoopa Prabhu
208767653936SRoopa Prabhu out:
208867653936SRoopa Prabhu rcu_read_unlock();
208967653936SRoopa Prabhu consume_skb(skb);
209067653936SRoopa Prabhu return NETDEV_TX_OK;
209167653936SRoopa Prabhu }
209267653936SRoopa Prabhu #endif
209367653936SRoopa Prabhu
route_shortcircuit(struct net_device * dev,struct sk_buff * skb)209467653936SRoopa Prabhu static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb)
209567653936SRoopa Prabhu {
209667653936SRoopa Prabhu struct vxlan_dev *vxlan = netdev_priv(dev);
209767653936SRoopa Prabhu struct neighbour *n;
209867653936SRoopa Prabhu
209967653936SRoopa Prabhu if (is_multicast_ether_addr(eth_hdr(skb)->h_dest))
210067653936SRoopa Prabhu return false;
210167653936SRoopa Prabhu
210267653936SRoopa Prabhu n = NULL;
210367653936SRoopa Prabhu switch (ntohs(eth_hdr(skb)->h_proto)) {
210467653936SRoopa Prabhu case ETH_P_IP:
210567653936SRoopa Prabhu {
210667653936SRoopa Prabhu struct iphdr *pip;
210767653936SRoopa Prabhu
210867653936SRoopa Prabhu if (!pskb_may_pull(skb, sizeof(struct iphdr)))
210967653936SRoopa Prabhu return false;
211067653936SRoopa Prabhu pip = ip_hdr(skb);
211167653936SRoopa Prabhu n = neigh_lookup(&arp_tbl, &pip->daddr, dev);
211267653936SRoopa Prabhu if (!n && (vxlan->cfg.flags & VXLAN_F_L3MISS)) {
211367653936SRoopa Prabhu union vxlan_addr ipa = {
211467653936SRoopa Prabhu .sin.sin_addr.s_addr = pip->daddr,
211567653936SRoopa Prabhu .sin.sin_family = AF_INET,
211667653936SRoopa Prabhu };
211767653936SRoopa Prabhu
211867653936SRoopa Prabhu vxlan_ip_miss(dev, &ipa);
211967653936SRoopa Prabhu return false;
212067653936SRoopa Prabhu }
212167653936SRoopa Prabhu
212267653936SRoopa Prabhu break;
212367653936SRoopa Prabhu }
212467653936SRoopa Prabhu #if IS_ENABLED(CONFIG_IPV6)
212567653936SRoopa Prabhu case ETH_P_IPV6:
212667653936SRoopa Prabhu {
212767653936SRoopa Prabhu struct ipv6hdr *pip6;
212867653936SRoopa Prabhu
212967653936SRoopa Prabhu if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
213067653936SRoopa Prabhu return false;
213167653936SRoopa Prabhu pip6 = ipv6_hdr(skb);
213267653936SRoopa Prabhu n = neigh_lookup(ipv6_stub->nd_tbl, &pip6->daddr, dev);
213367653936SRoopa Prabhu if (!n && (vxlan->cfg.flags & VXLAN_F_L3MISS)) {
213467653936SRoopa Prabhu union vxlan_addr ipa = {
213567653936SRoopa Prabhu .sin6.sin6_addr = pip6->daddr,
213667653936SRoopa Prabhu .sin6.sin6_family = AF_INET6,
213767653936SRoopa Prabhu };
213867653936SRoopa Prabhu
213967653936SRoopa Prabhu vxlan_ip_miss(dev, &ipa);
214067653936SRoopa Prabhu return false;
214167653936SRoopa Prabhu }
214267653936SRoopa Prabhu
214367653936SRoopa Prabhu break;
214467653936SRoopa Prabhu }
214567653936SRoopa Prabhu #endif
214667653936SRoopa Prabhu default:
214767653936SRoopa Prabhu return false;
214867653936SRoopa Prabhu }
214967653936SRoopa Prabhu
215067653936SRoopa Prabhu if (n) {
215167653936SRoopa Prabhu bool diff;
215267653936SRoopa Prabhu
215367653936SRoopa Prabhu diff = !ether_addr_equal(eth_hdr(skb)->h_dest, n->ha);
215467653936SRoopa Prabhu if (diff) {
215567653936SRoopa Prabhu memcpy(eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest,
215667653936SRoopa Prabhu dev->addr_len);
215767653936SRoopa Prabhu memcpy(eth_hdr(skb)->h_dest, n->ha, dev->addr_len);
215867653936SRoopa Prabhu }
215967653936SRoopa Prabhu neigh_release(n);
216067653936SRoopa Prabhu return diff;
216167653936SRoopa Prabhu }
216267653936SRoopa Prabhu
216367653936SRoopa Prabhu return false;
216467653936SRoopa Prabhu }
216567653936SRoopa Prabhu
vxlan_build_gpe_hdr(struct vxlanhdr * vxh,__be16 protocol)2166df5e87f1SGavin Li static int vxlan_build_gpe_hdr(struct vxlanhdr *vxh, __be16 protocol)
216767653936SRoopa Prabhu {
216867653936SRoopa Prabhu struct vxlanhdr_gpe *gpe = (struct vxlanhdr_gpe *)vxh;
216967653936SRoopa Prabhu
217067653936SRoopa Prabhu gpe->np_applied = 1;
217167653936SRoopa Prabhu gpe->next_protocol = tun_p_from_eth_p(protocol);
217267653936SRoopa Prabhu if (!gpe->next_protocol)
217367653936SRoopa Prabhu return -EPFNOSUPPORT;
217467653936SRoopa Prabhu return 0;
217567653936SRoopa Prabhu }
217667653936SRoopa Prabhu
vxlan_build_skb(struct sk_buff * skb,struct dst_entry * dst,int iphdr_len,__be32 vni,struct vxlan_metadata * md,u32 vxflags,bool udp_sum)217767653936SRoopa Prabhu static int vxlan_build_skb(struct sk_buff *skb, struct dst_entry *dst,
217867653936SRoopa Prabhu int iphdr_len, __be32 vni,
217967653936SRoopa Prabhu struct vxlan_metadata *md, u32 vxflags,
218067653936SRoopa Prabhu bool udp_sum)
218167653936SRoopa Prabhu {
218267653936SRoopa Prabhu struct vxlanhdr *vxh;
218367653936SRoopa Prabhu int min_headroom;
218467653936SRoopa Prabhu int err;
218567653936SRoopa Prabhu int type = udp_sum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL;
218667653936SRoopa Prabhu __be16 inner_protocol = htons(ETH_P_TEB);
218767653936SRoopa Prabhu
218867653936SRoopa Prabhu if ((vxflags & VXLAN_F_REMCSUM_TX) &&
218967653936SRoopa Prabhu skb->ip_summed == CHECKSUM_PARTIAL) {
219067653936SRoopa Prabhu int csum_start = skb_checksum_start_offset(skb);
219167653936SRoopa Prabhu
219267653936SRoopa Prabhu if (csum_start <= VXLAN_MAX_REMCSUM_START &&
219367653936SRoopa Prabhu !(csum_start & VXLAN_RCO_SHIFT_MASK) &&
219467653936SRoopa Prabhu (skb->csum_offset == offsetof(struct udphdr, check) ||
219567653936SRoopa Prabhu skb->csum_offset == offsetof(struct tcphdr, check)))
219667653936SRoopa Prabhu type |= SKB_GSO_TUNNEL_REMCSUM;
219767653936SRoopa Prabhu }
219867653936SRoopa Prabhu
219967653936SRoopa Prabhu min_headroom = LL_RESERVED_SPACE(dst->dev) + dst->header_len
220067653936SRoopa Prabhu + VXLAN_HLEN + iphdr_len;
220167653936SRoopa Prabhu
220267653936SRoopa Prabhu /* Need space for new headers (invalidates iph ptr) */
220367653936SRoopa Prabhu err = skb_cow_head(skb, min_headroom);
220467653936SRoopa Prabhu if (unlikely(err))
220567653936SRoopa Prabhu return err;
220667653936SRoopa Prabhu
220767653936SRoopa Prabhu err = iptunnel_handle_offloads(skb, type);
220867653936SRoopa Prabhu if (err)
220967653936SRoopa Prabhu return err;
221067653936SRoopa Prabhu
221167653936SRoopa Prabhu vxh = __skb_push(skb, sizeof(*vxh));
221267653936SRoopa Prabhu vxh->vx_flags = VXLAN_HF_VNI;
221367653936SRoopa Prabhu vxh->vx_vni = vxlan_vni_field(vni);
221467653936SRoopa Prabhu
221567653936SRoopa Prabhu if (type & SKB_GSO_TUNNEL_REMCSUM) {
221667653936SRoopa Prabhu unsigned int start;
221767653936SRoopa Prabhu
221867653936SRoopa Prabhu start = skb_checksum_start_offset(skb) - sizeof(struct vxlanhdr);
221967653936SRoopa Prabhu vxh->vx_vni |= vxlan_compute_rco(start, skb->csum_offset);
222067653936SRoopa Prabhu vxh->vx_flags |= VXLAN_HF_RCO;
222167653936SRoopa Prabhu
222267653936SRoopa Prabhu if (!skb_is_gso(skb)) {
222367653936SRoopa Prabhu skb->ip_summed = CHECKSUM_NONE;
222467653936SRoopa Prabhu skb->encapsulation = 0;
222567653936SRoopa Prabhu }
222667653936SRoopa Prabhu }
222767653936SRoopa Prabhu
222867653936SRoopa Prabhu if (vxflags & VXLAN_F_GBP)
2229df5e87f1SGavin Li vxlan_build_gbp_hdr(vxh, md);
223067653936SRoopa Prabhu if (vxflags & VXLAN_F_GPE) {
2231df5e87f1SGavin Li err = vxlan_build_gpe_hdr(vxh, skb->protocol);
223267653936SRoopa Prabhu if (err < 0)
223367653936SRoopa Prabhu return err;
223467653936SRoopa Prabhu inner_protocol = skb->protocol;
223567653936SRoopa Prabhu }
223667653936SRoopa Prabhu
223767653936SRoopa Prabhu skb_set_inner_protocol(skb, inner_protocol);
223867653936SRoopa Prabhu return 0;
223967653936SRoopa Prabhu }
224067653936SRoopa Prabhu
vxlan_get_route(struct vxlan_dev * vxlan,struct net_device * dev,struct vxlan_sock * sock4,struct sk_buff * skb,int oif,u8 tos,__be32 daddr,__be32 * saddr,__be16 dport,__be16 sport,__u8 flow_flags,struct dst_cache * dst_cache,const struct ip_tunnel_info * info)224167653936SRoopa Prabhu static struct rtable *vxlan_get_route(struct vxlan_dev *vxlan, struct net_device *dev,
224267653936SRoopa Prabhu struct vxlan_sock *sock4,
224367653936SRoopa Prabhu struct sk_buff *skb, int oif, u8 tos,
224467653936SRoopa Prabhu __be32 daddr, __be32 *saddr, __be16 dport, __be16 sport,
22457e2fb8bcSPaul Chaignon __u8 flow_flags, struct dst_cache *dst_cache,
224667653936SRoopa Prabhu const struct ip_tunnel_info *info)
224767653936SRoopa Prabhu {
224867653936SRoopa Prabhu bool use_cache = ip_tunnel_dst_cache_usable(skb, info);
224967653936SRoopa Prabhu struct rtable *rt = NULL;
225067653936SRoopa Prabhu struct flowi4 fl4;
225167653936SRoopa Prabhu
225267653936SRoopa Prabhu if (!sock4)
225367653936SRoopa Prabhu return ERR_PTR(-EIO);
225467653936SRoopa Prabhu
225567653936SRoopa Prabhu if (tos && !info)
225667653936SRoopa Prabhu use_cache = false;
225767653936SRoopa Prabhu if (use_cache) {
225867653936SRoopa Prabhu rt = dst_cache_get_ip4(dst_cache, saddr);
225967653936SRoopa Prabhu if (rt)
226067653936SRoopa Prabhu return rt;
226167653936SRoopa Prabhu }
226267653936SRoopa Prabhu
226367653936SRoopa Prabhu memset(&fl4, 0, sizeof(fl4));
226467653936SRoopa Prabhu fl4.flowi4_oif = oif;
226567653936SRoopa Prabhu fl4.flowi4_tos = RT_TOS(tos);
226667653936SRoopa Prabhu fl4.flowi4_mark = skb->mark;
226767653936SRoopa Prabhu fl4.flowi4_proto = IPPROTO_UDP;
226867653936SRoopa Prabhu fl4.daddr = daddr;
226967653936SRoopa Prabhu fl4.saddr = *saddr;
227067653936SRoopa Prabhu fl4.fl4_dport = dport;
227167653936SRoopa Prabhu fl4.fl4_sport = sport;
22727e2fb8bcSPaul Chaignon fl4.flowi4_flags = flow_flags;
227367653936SRoopa Prabhu
227467653936SRoopa Prabhu rt = ip_route_output_key(vxlan->net, &fl4);
227567653936SRoopa Prabhu if (!IS_ERR(rt)) {
227667653936SRoopa Prabhu if (rt->dst.dev == dev) {
227767653936SRoopa Prabhu netdev_dbg(dev, "circular route to %pI4\n", &daddr);
227867653936SRoopa Prabhu ip_rt_put(rt);
227967653936SRoopa Prabhu return ERR_PTR(-ELOOP);
228067653936SRoopa Prabhu }
228167653936SRoopa Prabhu
228267653936SRoopa Prabhu *saddr = fl4.saddr;
228367653936SRoopa Prabhu if (use_cache)
228467653936SRoopa Prabhu dst_cache_set_ip4(dst_cache, &rt->dst, fl4.saddr);
228567653936SRoopa Prabhu } else {
228667653936SRoopa Prabhu netdev_dbg(dev, "no route to %pI4\n", &daddr);
228767653936SRoopa Prabhu return ERR_PTR(-ENETUNREACH);
228867653936SRoopa Prabhu }
228967653936SRoopa Prabhu return rt;
229067653936SRoopa Prabhu }
229167653936SRoopa Prabhu
229267653936SRoopa Prabhu #if IS_ENABLED(CONFIG_IPV6)
vxlan6_get_route(struct vxlan_dev * vxlan,struct net_device * dev,struct vxlan_sock * sock6,struct sk_buff * skb,int oif,u8 tos,__be32 label,const struct in6_addr * daddr,struct in6_addr * saddr,__be16 dport,__be16 sport,struct dst_cache * dst_cache,const struct ip_tunnel_info * info)229367653936SRoopa Prabhu static struct dst_entry *vxlan6_get_route(struct vxlan_dev *vxlan,
229467653936SRoopa Prabhu struct net_device *dev,
229567653936SRoopa Prabhu struct vxlan_sock *sock6,
229667653936SRoopa Prabhu struct sk_buff *skb, int oif, u8 tos,
229767653936SRoopa Prabhu __be32 label,
229867653936SRoopa Prabhu const struct in6_addr *daddr,
229967653936SRoopa Prabhu struct in6_addr *saddr,
230067653936SRoopa Prabhu __be16 dport, __be16 sport,
230167653936SRoopa Prabhu struct dst_cache *dst_cache,
230267653936SRoopa Prabhu const struct ip_tunnel_info *info)
230367653936SRoopa Prabhu {
230467653936SRoopa Prabhu bool use_cache = ip_tunnel_dst_cache_usable(skb, info);
230567653936SRoopa Prabhu struct dst_entry *ndst;
230667653936SRoopa Prabhu struct flowi6 fl6;
230767653936SRoopa Prabhu
230867653936SRoopa Prabhu if (!sock6)
230967653936SRoopa Prabhu return ERR_PTR(-EIO);
231067653936SRoopa Prabhu
231167653936SRoopa Prabhu if (tos && !info)
231267653936SRoopa Prabhu use_cache = false;
231367653936SRoopa Prabhu if (use_cache) {
231467653936SRoopa Prabhu ndst = dst_cache_get_ip6(dst_cache, saddr);
231567653936SRoopa Prabhu if (ndst)
231667653936SRoopa Prabhu return ndst;
231767653936SRoopa Prabhu }
231867653936SRoopa Prabhu
231967653936SRoopa Prabhu memset(&fl6, 0, sizeof(fl6));
232067653936SRoopa Prabhu fl6.flowi6_oif = oif;
232167653936SRoopa Prabhu fl6.daddr = *daddr;
232267653936SRoopa Prabhu fl6.saddr = *saddr;
2323e488d4f5SMatthias May fl6.flowlabel = ip6_make_flowinfo(tos, label);
232467653936SRoopa Prabhu fl6.flowi6_mark = skb->mark;
232567653936SRoopa Prabhu fl6.flowi6_proto = IPPROTO_UDP;
232667653936SRoopa Prabhu fl6.fl6_dport = dport;
232767653936SRoopa Prabhu fl6.fl6_sport = sport;
232867653936SRoopa Prabhu
232967653936SRoopa Prabhu ndst = ipv6_stub->ipv6_dst_lookup_flow(vxlan->net, sock6->sock->sk,
233067653936SRoopa Prabhu &fl6, NULL);
233167653936SRoopa Prabhu if (IS_ERR(ndst)) {
233267653936SRoopa Prabhu netdev_dbg(dev, "no route to %pI6\n", daddr);
233367653936SRoopa Prabhu return ERR_PTR(-ENETUNREACH);
233467653936SRoopa Prabhu }
233567653936SRoopa Prabhu
233667653936SRoopa Prabhu if (unlikely(ndst->dev == dev)) {
233767653936SRoopa Prabhu netdev_dbg(dev, "circular route to %pI6\n", daddr);
233867653936SRoopa Prabhu dst_release(ndst);
233967653936SRoopa Prabhu return ERR_PTR(-ELOOP);
234067653936SRoopa Prabhu }
234167653936SRoopa Prabhu
234267653936SRoopa Prabhu *saddr = fl6.saddr;
234367653936SRoopa Prabhu if (use_cache)
234467653936SRoopa Prabhu dst_cache_set_ip6(dst_cache, ndst, saddr);
234567653936SRoopa Prabhu return ndst;
234667653936SRoopa Prabhu }
234767653936SRoopa Prabhu #endif
234867653936SRoopa Prabhu
234967653936SRoopa Prabhu /* Bypass encapsulation if the destination is local */
vxlan_encap_bypass(struct sk_buff * skb,struct vxlan_dev * src_vxlan,struct vxlan_dev * dst_vxlan,__be32 vni,bool snoop)235067653936SRoopa Prabhu static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan,
235167653936SRoopa Prabhu struct vxlan_dev *dst_vxlan, __be32 vni,
235267653936SRoopa Prabhu bool snoop)
235367653936SRoopa Prabhu {
235467653936SRoopa Prabhu union vxlan_addr loopback;
235567653936SRoopa Prabhu union vxlan_addr *remote_ip = &dst_vxlan->default_dst.remote_ip;
235667653936SRoopa Prabhu struct net_device *dev;
235767653936SRoopa Prabhu int len = skb->len;
235867653936SRoopa Prabhu
235967653936SRoopa Prabhu skb->pkt_type = PACKET_HOST;
236067653936SRoopa Prabhu skb->encapsulation = 0;
236167653936SRoopa Prabhu skb->dev = dst_vxlan->dev;
236267653936SRoopa Prabhu __skb_pull(skb, skb_network_offset(skb));
236367653936SRoopa Prabhu
236467653936SRoopa Prabhu if (remote_ip->sa.sa_family == AF_INET) {
236567653936SRoopa Prabhu loopback.sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
236667653936SRoopa Prabhu loopback.sa.sa_family = AF_INET;
236767653936SRoopa Prabhu #if IS_ENABLED(CONFIG_IPV6)
236867653936SRoopa Prabhu } else {
236967653936SRoopa Prabhu loopback.sin6.sin6_addr = in6addr_loopback;
237067653936SRoopa Prabhu loopback.sa.sa_family = AF_INET6;
237167653936SRoopa Prabhu #endif
237267653936SRoopa Prabhu }
237367653936SRoopa Prabhu
237467653936SRoopa Prabhu rcu_read_lock();
237567653936SRoopa Prabhu dev = skb->dev;
237667653936SRoopa Prabhu if (unlikely(!(dev->flags & IFF_UP))) {
237767653936SRoopa Prabhu kfree_skb(skb);
237867653936SRoopa Prabhu goto drop;
237967653936SRoopa Prabhu }
238067653936SRoopa Prabhu
238167653936SRoopa Prabhu if ((dst_vxlan->cfg.flags & VXLAN_F_LEARN) && snoop)
238267653936SRoopa Prabhu vxlan_snoop(dev, &loopback, eth_hdr(skb)->h_source, 0, vni);
238367653936SRoopa Prabhu
23843c0930b4SLi Zetao dev_sw_netstats_tx_add(src_vxlan->dev, 1, len);
23854095e0e1SNikolay Aleksandrov vxlan_vnifilter_count(src_vxlan, vni, NULL, VXLAN_VNI_STATS_TX, len);
238667653936SRoopa Prabhu
238767653936SRoopa Prabhu if (__netif_rx(skb) == NET_RX_SUCCESS) {
23883c0930b4SLi Zetao dev_sw_netstats_rx_add(dst_vxlan->dev, len);
23894095e0e1SNikolay Aleksandrov vxlan_vnifilter_count(dst_vxlan, vni, NULL, VXLAN_VNI_STATS_RX,
23904095e0e1SNikolay Aleksandrov len);
239167653936SRoopa Prabhu } else {
239267653936SRoopa Prabhu drop:
239384321030SGuillaume Nault dev_core_stats_rx_dropped_inc(dev);
23944095e0e1SNikolay Aleksandrov vxlan_vnifilter_count(dst_vxlan, vni, NULL,
23954095e0e1SNikolay Aleksandrov VXLAN_VNI_STATS_RX_DROPS, 0);
239667653936SRoopa Prabhu }
239767653936SRoopa Prabhu rcu_read_unlock();
239867653936SRoopa Prabhu }
239967653936SRoopa Prabhu
encap_bypass_if_local(struct sk_buff * skb,struct net_device * dev,struct vxlan_dev * vxlan,union vxlan_addr * daddr,__be16 dst_port,int dst_ifindex,__be32 vni,struct dst_entry * dst,u32 rt_flags)240067653936SRoopa Prabhu static int encap_bypass_if_local(struct sk_buff *skb, struct net_device *dev,
240167653936SRoopa Prabhu struct vxlan_dev *vxlan,
240267653936SRoopa Prabhu union vxlan_addr *daddr,
240367653936SRoopa Prabhu __be16 dst_port, int dst_ifindex, __be32 vni,
240467653936SRoopa Prabhu struct dst_entry *dst,
240567653936SRoopa Prabhu u32 rt_flags)
240667653936SRoopa Prabhu {
240767653936SRoopa Prabhu #if IS_ENABLED(CONFIG_IPV6)
240867653936SRoopa Prabhu /* IPv6 rt-flags are checked against RTF_LOCAL, but the value of
240967653936SRoopa Prabhu * RTF_LOCAL is equal to RTCF_LOCAL. So to keep code simple
241067653936SRoopa Prabhu * we can use RTCF_LOCAL which works for ipv4 and ipv6 route entry.
241167653936SRoopa Prabhu */
241267653936SRoopa Prabhu BUILD_BUG_ON(RTCF_LOCAL != RTF_LOCAL);
241367653936SRoopa Prabhu #endif
241467653936SRoopa Prabhu /* Bypass encapsulation if the destination is local */
241567653936SRoopa Prabhu if (rt_flags & RTCF_LOCAL &&
241669474a8aSVladimir Nikishkin !(rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) &&
241769474a8aSVladimir Nikishkin vxlan->cfg.flags & VXLAN_F_LOCALBYPASS) {
241867653936SRoopa Prabhu struct vxlan_dev *dst_vxlan;
241967653936SRoopa Prabhu
242067653936SRoopa Prabhu dst_release(dst);
242167653936SRoopa Prabhu dst_vxlan = vxlan_find_vni(vxlan->net, dst_ifindex, vni,
242267653936SRoopa Prabhu daddr->sa.sa_family, dst_port,
242367653936SRoopa Prabhu vxlan->cfg.flags);
242467653936SRoopa Prabhu if (!dst_vxlan) {
242584321030SGuillaume Nault DEV_STATS_INC(dev, tx_errors);
24264095e0e1SNikolay Aleksandrov vxlan_vnifilter_count(vxlan, vni, NULL,
24274095e0e1SNikolay Aleksandrov VXLAN_VNI_STATS_TX_ERRORS, 0);
242867653936SRoopa Prabhu kfree_skb(skb);
242967653936SRoopa Prabhu
243067653936SRoopa Prabhu return -ENOENT;
243167653936SRoopa Prabhu }
243267653936SRoopa Prabhu vxlan_encap_bypass(skb, vxlan, dst_vxlan, vni, true);
243367653936SRoopa Prabhu return 1;
243467653936SRoopa Prabhu }
243567653936SRoopa Prabhu
243667653936SRoopa Prabhu return 0;
243767653936SRoopa Prabhu }
243867653936SRoopa Prabhu
vxlan_xmit_one(struct sk_buff * skb,struct net_device * dev,__be32 default_vni,struct vxlan_rdst * rdst,bool did_rsc)24396ab271aaSIdo Schimmel void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
24406ab271aaSIdo Schimmel __be32 default_vni, struct vxlan_rdst *rdst, bool did_rsc)
244167653936SRoopa Prabhu {
244267653936SRoopa Prabhu struct dst_cache *dst_cache;
244367653936SRoopa Prabhu struct ip_tunnel_info *info;
244467653936SRoopa Prabhu struct vxlan_dev *vxlan = netdev_priv(dev);
244567653936SRoopa Prabhu const struct iphdr *old_iph = ip_hdr(skb);
244667653936SRoopa Prabhu union vxlan_addr *dst;
244767653936SRoopa Prabhu union vxlan_addr remote_ip, local_ip;
244867653936SRoopa Prabhu struct vxlan_metadata _md;
244967653936SRoopa Prabhu struct vxlan_metadata *md = &_md;
24504095e0e1SNikolay Aleksandrov unsigned int pkt_len = skb->len;
245167653936SRoopa Prabhu __be16 src_port = 0, dst_port;
245267653936SRoopa Prabhu struct dst_entry *ndst = NULL;
24537e2fb8bcSPaul Chaignon __u8 tos, ttl, flow_flags = 0;
245467653936SRoopa Prabhu int ifindex;
245567653936SRoopa Prabhu int err;
245667653936SRoopa Prabhu u32 flags = vxlan->cfg.flags;
245767653936SRoopa Prabhu bool udp_sum = false;
245867653936SRoopa Prabhu bool xnet = !net_eq(vxlan->net, dev_net(vxlan->dev));
2459fba55a66SRoopa Prabhu __be32 vni = 0;
2460fba55a66SRoopa Prabhu #if IS_ENABLED(CONFIG_IPV6)
2461fba55a66SRoopa Prabhu __be32 label;
2462fba55a66SRoopa Prabhu #endif
246367653936SRoopa Prabhu
246467653936SRoopa Prabhu info = skb_tunnel_info(skb);
246567653936SRoopa Prabhu
246667653936SRoopa Prabhu if (rdst) {
246767653936SRoopa Prabhu dst = &rdst->remote_ip;
246867653936SRoopa Prabhu if (vxlan_addr_any(dst)) {
246967653936SRoopa Prabhu if (did_rsc) {
247067653936SRoopa Prabhu /* short-circuited back to local bridge */
247167653936SRoopa Prabhu vxlan_encap_bypass(skb, vxlan, vxlan,
247267653936SRoopa Prabhu default_vni, true);
247367653936SRoopa Prabhu return;
247467653936SRoopa Prabhu }
247567653936SRoopa Prabhu goto drop;
247667653936SRoopa Prabhu }
247767653936SRoopa Prabhu
247867653936SRoopa Prabhu dst_port = rdst->remote_port ? rdst->remote_port : vxlan->cfg.dst_port;
247967653936SRoopa Prabhu vni = (rdst->remote_vni) ? : default_vni;
248067653936SRoopa Prabhu ifindex = rdst->remote_ifindex;
248167653936SRoopa Prabhu local_ip = vxlan->cfg.saddr;
248267653936SRoopa Prabhu dst_cache = &rdst->dst_cache;
248367653936SRoopa Prabhu md->gbp = skb->mark;
248467653936SRoopa Prabhu if (flags & VXLAN_F_TTL_INHERIT) {
248567653936SRoopa Prabhu ttl = ip_tunnel_get_ttl(old_iph, skb);
248667653936SRoopa Prabhu } else {
248767653936SRoopa Prabhu ttl = vxlan->cfg.ttl;
248867653936SRoopa Prabhu if (!ttl && vxlan_addr_multicast(dst))
248967653936SRoopa Prabhu ttl = 1;
249067653936SRoopa Prabhu }
249167653936SRoopa Prabhu
249267653936SRoopa Prabhu tos = vxlan->cfg.tos;
249367653936SRoopa Prabhu if (tos == 1)
249467653936SRoopa Prabhu tos = ip_tunnel_get_dsfield(old_iph, skb);
249567653936SRoopa Prabhu
249667653936SRoopa Prabhu if (dst->sa.sa_family == AF_INET)
249767653936SRoopa Prabhu udp_sum = !(flags & VXLAN_F_UDP_ZERO_CSUM_TX);
249867653936SRoopa Prabhu else
249967653936SRoopa Prabhu udp_sum = !(flags & VXLAN_F_UDP_ZERO_CSUM6_TX);
2500fba55a66SRoopa Prabhu #if IS_ENABLED(CONFIG_IPV6)
250167653936SRoopa Prabhu label = vxlan->cfg.label;
2502fba55a66SRoopa Prabhu #endif
250367653936SRoopa Prabhu } else {
250467653936SRoopa Prabhu if (!info) {
250567653936SRoopa Prabhu WARN_ONCE(1, "%s: Missing encapsulation instructions\n",
250667653936SRoopa Prabhu dev->name);
250767653936SRoopa Prabhu goto drop;
250867653936SRoopa Prabhu }
250967653936SRoopa Prabhu remote_ip.sa.sa_family = ip_tunnel_info_af(info);
251067653936SRoopa Prabhu if (remote_ip.sa.sa_family == AF_INET) {
251167653936SRoopa Prabhu remote_ip.sin.sin_addr.s_addr = info->key.u.ipv4.dst;
251267653936SRoopa Prabhu local_ip.sin.sin_addr.s_addr = info->key.u.ipv4.src;
251367653936SRoopa Prabhu } else {
251467653936SRoopa Prabhu remote_ip.sin6.sin6_addr = info->key.u.ipv6.dst;
251567653936SRoopa Prabhu local_ip.sin6.sin6_addr = info->key.u.ipv6.src;
251667653936SRoopa Prabhu }
251767653936SRoopa Prabhu dst = &remote_ip;
251867653936SRoopa Prabhu dst_port = info->key.tp_dst ? : vxlan->cfg.dst_port;
25197e2fb8bcSPaul Chaignon flow_flags = info->key.flow_flags;
252067653936SRoopa Prabhu vni = tunnel_id_to_key32(info->key.tun_id);
252167653936SRoopa Prabhu ifindex = 0;
252267653936SRoopa Prabhu dst_cache = &info->dst_cache;
252367653936SRoopa Prabhu if (info->key.tun_flags & TUNNEL_VXLAN_OPT) {
252467653936SRoopa Prabhu if (info->options_len < sizeof(*md))
252567653936SRoopa Prabhu goto drop;
252667653936SRoopa Prabhu md = ip_tunnel_info_opts(info);
252767653936SRoopa Prabhu }
252867653936SRoopa Prabhu ttl = info->key.ttl;
252967653936SRoopa Prabhu tos = info->key.tos;
2530fba55a66SRoopa Prabhu #if IS_ENABLED(CONFIG_IPV6)
253167653936SRoopa Prabhu label = info->key.label;
2532fba55a66SRoopa Prabhu #endif
253367653936SRoopa Prabhu udp_sum = !!(info->key.tun_flags & TUNNEL_CSUM);
253467653936SRoopa Prabhu }
253567653936SRoopa Prabhu src_port = udp_flow_src_port(dev_net(dev), skb, vxlan->cfg.port_min,
253667653936SRoopa Prabhu vxlan->cfg.port_max, true);
253767653936SRoopa Prabhu
253867653936SRoopa Prabhu rcu_read_lock();
253967653936SRoopa Prabhu if (dst->sa.sa_family == AF_INET) {
254067653936SRoopa Prabhu struct vxlan_sock *sock4 = rcu_dereference(vxlan->vn4_sock);
254167653936SRoopa Prabhu struct rtable *rt;
254267653936SRoopa Prabhu __be16 df = 0;
254367653936SRoopa Prabhu
254467653936SRoopa Prabhu if (!ifindex)
254567653936SRoopa Prabhu ifindex = sock4->sock->sk->sk_bound_dev_if;
254667653936SRoopa Prabhu
254767653936SRoopa Prabhu rt = vxlan_get_route(vxlan, dev, sock4, skb, ifindex, tos,
254867653936SRoopa Prabhu dst->sin.sin_addr.s_addr,
254967653936SRoopa Prabhu &local_ip.sin.sin_addr.s_addr,
25507e2fb8bcSPaul Chaignon dst_port, src_port, flow_flags,
255167653936SRoopa Prabhu dst_cache, info);
255267653936SRoopa Prabhu if (IS_ERR(rt)) {
255367653936SRoopa Prabhu err = PTR_ERR(rt);
255467653936SRoopa Prabhu goto tx_error;
255567653936SRoopa Prabhu }
255667653936SRoopa Prabhu
255767653936SRoopa Prabhu if (!info) {
255867653936SRoopa Prabhu /* Bypass encapsulation if the destination is local */
255967653936SRoopa Prabhu err = encap_bypass_if_local(skb, dev, vxlan, dst,
256067653936SRoopa Prabhu dst_port, ifindex, vni,
256167653936SRoopa Prabhu &rt->dst, rt->rt_flags);
256267653936SRoopa Prabhu if (err)
256367653936SRoopa Prabhu goto out_unlock;
256467653936SRoopa Prabhu
256567653936SRoopa Prabhu if (vxlan->cfg.df == VXLAN_DF_SET) {
256667653936SRoopa Prabhu df = htons(IP_DF);
256767653936SRoopa Prabhu } else if (vxlan->cfg.df == VXLAN_DF_INHERIT) {
256867653936SRoopa Prabhu struct ethhdr *eth = eth_hdr(skb);
256967653936SRoopa Prabhu
257067653936SRoopa Prabhu if (ntohs(eth->h_proto) == ETH_P_IPV6 ||
257167653936SRoopa Prabhu (ntohs(eth->h_proto) == ETH_P_IP &&
257267653936SRoopa Prabhu old_iph->frag_off & htons(IP_DF)))
257367653936SRoopa Prabhu df = htons(IP_DF);
257467653936SRoopa Prabhu }
257567653936SRoopa Prabhu } else if (info->key.tun_flags & TUNNEL_DONT_FRAGMENT) {
257667653936SRoopa Prabhu df = htons(IP_DF);
257767653936SRoopa Prabhu }
257867653936SRoopa Prabhu
257967653936SRoopa Prabhu ndst = &rt->dst;
258094d166c5SJiri Benc err = skb_tunnel_check_pmtu(skb, ndst, vxlan_headroom(flags & VXLAN_F_GPE),
258167653936SRoopa Prabhu netif_is_any_bridge_port(dev));
258267653936SRoopa Prabhu if (err < 0) {
258367653936SRoopa Prabhu goto tx_error;
258467653936SRoopa Prabhu } else if (err) {
258567653936SRoopa Prabhu if (info) {
258667653936SRoopa Prabhu struct ip_tunnel_info *unclone;
258767653936SRoopa Prabhu struct in_addr src, dst;
258867653936SRoopa Prabhu
258967653936SRoopa Prabhu unclone = skb_tunnel_info_unclone(skb);
259067653936SRoopa Prabhu if (unlikely(!unclone))
259167653936SRoopa Prabhu goto tx_error;
259267653936SRoopa Prabhu
259367653936SRoopa Prabhu src = remote_ip.sin.sin_addr;
259467653936SRoopa Prabhu dst = local_ip.sin.sin_addr;
259567653936SRoopa Prabhu unclone->key.u.ipv4.src = src.s_addr;
259667653936SRoopa Prabhu unclone->key.u.ipv4.dst = dst.s_addr;
259767653936SRoopa Prabhu }
259867653936SRoopa Prabhu vxlan_encap_bypass(skb, vxlan, vxlan, vni, false);
259967653936SRoopa Prabhu dst_release(ndst);
260067653936SRoopa Prabhu goto out_unlock;
260167653936SRoopa Prabhu }
260267653936SRoopa Prabhu
260367653936SRoopa Prabhu tos = ip_tunnel_ecn_encap(tos, old_iph, skb);
260467653936SRoopa Prabhu ttl = ttl ? : ip4_dst_hoplimit(&rt->dst);
260567653936SRoopa Prabhu err = vxlan_build_skb(skb, ndst, sizeof(struct iphdr),
260667653936SRoopa Prabhu vni, md, flags, udp_sum);
260767653936SRoopa Prabhu if (err < 0)
260867653936SRoopa Prabhu goto tx_error;
260967653936SRoopa Prabhu
261067653936SRoopa Prabhu udp_tunnel_xmit_skb(rt, sock4->sock->sk, skb, local_ip.sin.sin_addr.s_addr,
261167653936SRoopa Prabhu dst->sin.sin_addr.s_addr, tos, ttl, df,
261267653936SRoopa Prabhu src_port, dst_port, xnet, !udp_sum);
261367653936SRoopa Prabhu #if IS_ENABLED(CONFIG_IPV6)
261467653936SRoopa Prabhu } else {
261567653936SRoopa Prabhu struct vxlan_sock *sock6 = rcu_dereference(vxlan->vn6_sock);
261667653936SRoopa Prabhu
261767653936SRoopa Prabhu if (!ifindex)
261867653936SRoopa Prabhu ifindex = sock6->sock->sk->sk_bound_dev_if;
261967653936SRoopa Prabhu
262067653936SRoopa Prabhu ndst = vxlan6_get_route(vxlan, dev, sock6, skb, ifindex, tos,
262167653936SRoopa Prabhu label, &dst->sin6.sin6_addr,
262267653936SRoopa Prabhu &local_ip.sin6.sin6_addr,
262367653936SRoopa Prabhu dst_port, src_port,
262467653936SRoopa Prabhu dst_cache, info);
262567653936SRoopa Prabhu if (IS_ERR(ndst)) {
262667653936SRoopa Prabhu err = PTR_ERR(ndst);
262767653936SRoopa Prabhu ndst = NULL;
262867653936SRoopa Prabhu goto tx_error;
262967653936SRoopa Prabhu }
263067653936SRoopa Prabhu
263167653936SRoopa Prabhu if (!info) {
2632*797a4c1fSEric Dumazet u32 rt6i_flags = dst_rt6_info(ndst)->rt6i_flags;
263367653936SRoopa Prabhu
263467653936SRoopa Prabhu err = encap_bypass_if_local(skb, dev, vxlan, dst,
263567653936SRoopa Prabhu dst_port, ifindex, vni,
263667653936SRoopa Prabhu ndst, rt6i_flags);
263767653936SRoopa Prabhu if (err)
263867653936SRoopa Prabhu goto out_unlock;
263967653936SRoopa Prabhu }
264067653936SRoopa Prabhu
264194d166c5SJiri Benc err = skb_tunnel_check_pmtu(skb, ndst,
264294d166c5SJiri Benc vxlan_headroom((flags & VXLAN_F_GPE) | VXLAN_F_IPV6),
264367653936SRoopa Prabhu netif_is_any_bridge_port(dev));
264467653936SRoopa Prabhu if (err < 0) {
264567653936SRoopa Prabhu goto tx_error;
264667653936SRoopa Prabhu } else if (err) {
264767653936SRoopa Prabhu if (info) {
264867653936SRoopa Prabhu struct ip_tunnel_info *unclone;
264967653936SRoopa Prabhu struct in6_addr src, dst;
265067653936SRoopa Prabhu
265167653936SRoopa Prabhu unclone = skb_tunnel_info_unclone(skb);
265267653936SRoopa Prabhu if (unlikely(!unclone))
265367653936SRoopa Prabhu goto tx_error;
265467653936SRoopa Prabhu
265567653936SRoopa Prabhu src = remote_ip.sin6.sin6_addr;
265667653936SRoopa Prabhu dst = local_ip.sin6.sin6_addr;
265767653936SRoopa Prabhu unclone->key.u.ipv6.src = src;
265867653936SRoopa Prabhu unclone->key.u.ipv6.dst = dst;
265967653936SRoopa Prabhu }
266067653936SRoopa Prabhu
266167653936SRoopa Prabhu vxlan_encap_bypass(skb, vxlan, vxlan, vni, false);
266267653936SRoopa Prabhu dst_release(ndst);
266367653936SRoopa Prabhu goto out_unlock;
266467653936SRoopa Prabhu }
266567653936SRoopa Prabhu
266667653936SRoopa Prabhu tos = ip_tunnel_ecn_encap(tos, old_iph, skb);
266767653936SRoopa Prabhu ttl = ttl ? : ip6_dst_hoplimit(ndst);
266867653936SRoopa Prabhu skb_scrub_packet(skb, xnet);
266967653936SRoopa Prabhu err = vxlan_build_skb(skb, ndst, sizeof(struct ipv6hdr),
267067653936SRoopa Prabhu vni, md, flags, udp_sum);
267167653936SRoopa Prabhu if (err < 0)
267267653936SRoopa Prabhu goto tx_error;
267367653936SRoopa Prabhu
267467653936SRoopa Prabhu udp_tunnel6_xmit_skb(ndst, sock6->sock->sk, skb, dev,
267567653936SRoopa Prabhu &local_ip.sin6.sin6_addr,
267667653936SRoopa Prabhu &dst->sin6.sin6_addr, tos, ttl,
267767653936SRoopa Prabhu label, src_port, dst_port, !udp_sum);
267867653936SRoopa Prabhu #endif
267967653936SRoopa Prabhu }
26804095e0e1SNikolay Aleksandrov vxlan_vnifilter_count(vxlan, vni, NULL, VXLAN_VNI_STATS_TX, pkt_len);
268167653936SRoopa Prabhu out_unlock:
268267653936SRoopa Prabhu rcu_read_unlock();
268367653936SRoopa Prabhu return;
268467653936SRoopa Prabhu
268567653936SRoopa Prabhu drop:
268684321030SGuillaume Nault dev_core_stats_tx_dropped_inc(dev);
26874095e0e1SNikolay Aleksandrov vxlan_vnifilter_count(vxlan, vni, NULL, VXLAN_VNI_STATS_TX_DROPS, 0);
268867653936SRoopa Prabhu dev_kfree_skb(skb);
268967653936SRoopa Prabhu return;
269067653936SRoopa Prabhu
269167653936SRoopa Prabhu tx_error:
269267653936SRoopa Prabhu rcu_read_unlock();
269367653936SRoopa Prabhu if (err == -ELOOP)
269484321030SGuillaume Nault DEV_STATS_INC(dev, collisions);
269567653936SRoopa Prabhu else if (err == -ENETUNREACH)
269684321030SGuillaume Nault DEV_STATS_INC(dev, tx_carrier_errors);
269767653936SRoopa Prabhu dst_release(ndst);
269884321030SGuillaume Nault DEV_STATS_INC(dev, tx_errors);
26994095e0e1SNikolay Aleksandrov vxlan_vnifilter_count(vxlan, vni, NULL, VXLAN_VNI_STATS_TX_ERRORS, 0);
270067653936SRoopa Prabhu kfree_skb(skb);
270167653936SRoopa Prabhu }
270267653936SRoopa Prabhu
vxlan_xmit_nh(struct sk_buff * skb,struct net_device * dev,struct vxlan_fdb * f,__be32 vni,bool did_rsc)270367653936SRoopa Prabhu static void vxlan_xmit_nh(struct sk_buff *skb, struct net_device *dev,
270467653936SRoopa Prabhu struct vxlan_fdb *f, __be32 vni, bool did_rsc)
270567653936SRoopa Prabhu {
270667653936SRoopa Prabhu struct vxlan_rdst nh_rdst;
270767653936SRoopa Prabhu struct nexthop *nh;
270867653936SRoopa Prabhu bool do_xmit;
270967653936SRoopa Prabhu u32 hash;
271067653936SRoopa Prabhu
271167653936SRoopa Prabhu memset(&nh_rdst, 0, sizeof(struct vxlan_rdst));
271267653936SRoopa Prabhu hash = skb_get_hash(skb);
271367653936SRoopa Prabhu
271467653936SRoopa Prabhu rcu_read_lock();
271567653936SRoopa Prabhu nh = rcu_dereference(f->nh);
271667653936SRoopa Prabhu if (!nh) {
271767653936SRoopa Prabhu rcu_read_unlock();
271867653936SRoopa Prabhu goto drop;
271967653936SRoopa Prabhu }
272067653936SRoopa Prabhu do_xmit = vxlan_fdb_nh_path_select(nh, hash, &nh_rdst);
272167653936SRoopa Prabhu rcu_read_unlock();
272267653936SRoopa Prabhu
272367653936SRoopa Prabhu if (likely(do_xmit))
272467653936SRoopa Prabhu vxlan_xmit_one(skb, dev, vni, &nh_rdst, did_rsc);
272567653936SRoopa Prabhu else
272667653936SRoopa Prabhu goto drop;
272767653936SRoopa Prabhu
272867653936SRoopa Prabhu return;
272967653936SRoopa Prabhu
273067653936SRoopa Prabhu drop:
273184321030SGuillaume Nault dev_core_stats_tx_dropped_inc(dev);
27324095e0e1SNikolay Aleksandrov vxlan_vnifilter_count(netdev_priv(dev), vni, NULL,
27334095e0e1SNikolay Aleksandrov VXLAN_VNI_STATS_TX_DROPS, 0);
273467653936SRoopa Prabhu dev_kfree_skb(skb);
273567653936SRoopa Prabhu }
273667653936SRoopa Prabhu
vxlan_xmit_nhid(struct sk_buff * skb,struct net_device * dev,u32 nhid,__be32 vni)2737d977e1c8SIdo Schimmel static netdev_tx_t vxlan_xmit_nhid(struct sk_buff *skb, struct net_device *dev,
2738d977e1c8SIdo Schimmel u32 nhid, __be32 vni)
2739d977e1c8SIdo Schimmel {
2740d977e1c8SIdo Schimmel struct vxlan_dev *vxlan = netdev_priv(dev);
2741d977e1c8SIdo Schimmel struct vxlan_rdst nh_rdst;
2742d977e1c8SIdo Schimmel struct nexthop *nh;
2743d977e1c8SIdo Schimmel bool do_xmit;
2744d977e1c8SIdo Schimmel u32 hash;
2745d977e1c8SIdo Schimmel
2746d977e1c8SIdo Schimmel memset(&nh_rdst, 0, sizeof(struct vxlan_rdst));
2747d977e1c8SIdo Schimmel hash = skb_get_hash(skb);
2748d977e1c8SIdo Schimmel
2749d977e1c8SIdo Schimmel rcu_read_lock();
2750d977e1c8SIdo Schimmel nh = nexthop_find_by_id(dev_net(dev), nhid);
2751d977e1c8SIdo Schimmel if (unlikely(!nh || !nexthop_is_fdb(nh) || !nexthop_is_multipath(nh))) {
2752d977e1c8SIdo Schimmel rcu_read_unlock();
2753d977e1c8SIdo Schimmel goto drop;
2754d977e1c8SIdo Schimmel }
2755d977e1c8SIdo Schimmel do_xmit = vxlan_fdb_nh_path_select(nh, hash, &nh_rdst);
2756d977e1c8SIdo Schimmel rcu_read_unlock();
2757d977e1c8SIdo Schimmel
2758d977e1c8SIdo Schimmel if (vxlan->cfg.saddr.sa.sa_family != nh_rdst.remote_ip.sa.sa_family)
2759d977e1c8SIdo Schimmel goto drop;
2760d977e1c8SIdo Schimmel
2761d977e1c8SIdo Schimmel if (likely(do_xmit))
2762d977e1c8SIdo Schimmel vxlan_xmit_one(skb, dev, vni, &nh_rdst, false);
2763d977e1c8SIdo Schimmel else
2764d977e1c8SIdo Schimmel goto drop;
2765d977e1c8SIdo Schimmel
2766d977e1c8SIdo Schimmel return NETDEV_TX_OK;
2767d977e1c8SIdo Schimmel
2768d977e1c8SIdo Schimmel drop:
276984321030SGuillaume Nault dev_core_stats_tx_dropped_inc(dev);
2770d977e1c8SIdo Schimmel vxlan_vnifilter_count(netdev_priv(dev), vni, NULL,
2771d977e1c8SIdo Schimmel VXLAN_VNI_STATS_TX_DROPS, 0);
2772d977e1c8SIdo Schimmel dev_kfree_skb(skb);
2773d977e1c8SIdo Schimmel return NETDEV_TX_OK;
2774d977e1c8SIdo Schimmel }
2775d977e1c8SIdo Schimmel
277667653936SRoopa Prabhu /* Transmit local packets over Vxlan
277767653936SRoopa Prabhu *
277867653936SRoopa Prabhu * Outer IP header inherits ECN and DF from inner header.
277967653936SRoopa Prabhu * Outer UDP destination is the VXLAN assigned port.
278067653936SRoopa Prabhu * source port is based on hash of flow
278167653936SRoopa Prabhu */
vxlan_xmit(struct sk_buff * skb,struct net_device * dev)278267653936SRoopa Prabhu static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
278367653936SRoopa Prabhu {
278467653936SRoopa Prabhu struct vxlan_dev *vxlan = netdev_priv(dev);
278567653936SRoopa Prabhu struct vxlan_rdst *rdst, *fdst = NULL;
278667653936SRoopa Prabhu const struct ip_tunnel_info *info;
278767653936SRoopa Prabhu bool did_rsc = false;
278867653936SRoopa Prabhu struct vxlan_fdb *f;
278967653936SRoopa Prabhu struct ethhdr *eth;
279067653936SRoopa Prabhu __be32 vni = 0;
2791d977e1c8SIdo Schimmel u32 nhid = 0;
279267653936SRoopa Prabhu
279367653936SRoopa Prabhu info = skb_tunnel_info(skb);
279467653936SRoopa Prabhu
279567653936SRoopa Prabhu skb_reset_mac_header(skb);
279667653936SRoopa Prabhu
279767653936SRoopa Prabhu if (vxlan->cfg.flags & VXLAN_F_COLLECT_METADATA) {
279867653936SRoopa Prabhu if (info && info->mode & IP_TUNNEL_INFO_BRIDGE &&
279967653936SRoopa Prabhu info->mode & IP_TUNNEL_INFO_TX) {
280067653936SRoopa Prabhu vni = tunnel_id_to_key32(info->key.tun_id);
2801d977e1c8SIdo Schimmel nhid = info->key.nhid;
280267653936SRoopa Prabhu } else {
280367653936SRoopa Prabhu if (info && info->mode & IP_TUNNEL_INFO_TX)
280467653936SRoopa Prabhu vxlan_xmit_one(skb, dev, vni, NULL, false);
280567653936SRoopa Prabhu else
280667653936SRoopa Prabhu kfree_skb(skb);
280767653936SRoopa Prabhu return NETDEV_TX_OK;
280867653936SRoopa Prabhu }
280967653936SRoopa Prabhu }
281067653936SRoopa Prabhu
281167653936SRoopa Prabhu if (vxlan->cfg.flags & VXLAN_F_PROXY) {
281267653936SRoopa Prabhu eth = eth_hdr(skb);
281367653936SRoopa Prabhu if (ntohs(eth->h_proto) == ETH_P_ARP)
281467653936SRoopa Prabhu return arp_reduce(dev, skb, vni);
281567653936SRoopa Prabhu #if IS_ENABLED(CONFIG_IPV6)
281667653936SRoopa Prabhu else if (ntohs(eth->h_proto) == ETH_P_IPV6 &&
281767653936SRoopa Prabhu pskb_may_pull(skb, sizeof(struct ipv6hdr) +
281867653936SRoopa Prabhu sizeof(struct nd_msg)) &&
281967653936SRoopa Prabhu ipv6_hdr(skb)->nexthdr == IPPROTO_ICMPV6) {
282067653936SRoopa Prabhu struct nd_msg *m = (struct nd_msg *)(ipv6_hdr(skb) + 1);
282167653936SRoopa Prabhu
282267653936SRoopa Prabhu if (m->icmph.icmp6_code == 0 &&
282367653936SRoopa Prabhu m->icmph.icmp6_type == NDISC_NEIGHBOUR_SOLICITATION)
282467653936SRoopa Prabhu return neigh_reduce(dev, skb, vni);
282567653936SRoopa Prabhu }
282667653936SRoopa Prabhu #endif
282767653936SRoopa Prabhu }
282867653936SRoopa Prabhu
2829d977e1c8SIdo Schimmel if (nhid)
2830d977e1c8SIdo Schimmel return vxlan_xmit_nhid(skb, dev, nhid, vni);
2831d977e1c8SIdo Schimmel
28320f83e69fSIdo Schimmel if (vxlan->cfg.flags & VXLAN_F_MDB) {
28330f83e69fSIdo Schimmel struct vxlan_mdb_entry *mdb_entry;
28340f83e69fSIdo Schimmel
28350f83e69fSIdo Schimmel rcu_read_lock();
28360f83e69fSIdo Schimmel mdb_entry = vxlan_mdb_entry_skb_get(vxlan, skb, vni);
28370f83e69fSIdo Schimmel if (mdb_entry) {
28380f83e69fSIdo Schimmel netdev_tx_t ret;
28390f83e69fSIdo Schimmel
28400f83e69fSIdo Schimmel ret = vxlan_mdb_xmit(vxlan, mdb_entry, skb);
28410f83e69fSIdo Schimmel rcu_read_unlock();
28420f83e69fSIdo Schimmel return ret;
28430f83e69fSIdo Schimmel }
28440f83e69fSIdo Schimmel rcu_read_unlock();
28450f83e69fSIdo Schimmel }
28460f83e69fSIdo Schimmel
284767653936SRoopa Prabhu eth = eth_hdr(skb);
284867653936SRoopa Prabhu f = vxlan_find_mac(vxlan, eth->h_dest, vni);
284967653936SRoopa Prabhu did_rsc = false;
285067653936SRoopa Prabhu
285167653936SRoopa Prabhu if (f && (f->flags & NTF_ROUTER) && (vxlan->cfg.flags & VXLAN_F_RSC) &&
285267653936SRoopa Prabhu (ntohs(eth->h_proto) == ETH_P_IP ||
285367653936SRoopa Prabhu ntohs(eth->h_proto) == ETH_P_IPV6)) {
285467653936SRoopa Prabhu did_rsc = route_shortcircuit(dev, skb);
285567653936SRoopa Prabhu if (did_rsc)
285667653936SRoopa Prabhu f = vxlan_find_mac(vxlan, eth->h_dest, vni);
285767653936SRoopa Prabhu }
285867653936SRoopa Prabhu
285967653936SRoopa Prabhu if (f == NULL) {
286067653936SRoopa Prabhu f = vxlan_find_mac(vxlan, all_zeros_mac, vni);
286167653936SRoopa Prabhu if (f == NULL) {
286267653936SRoopa Prabhu if ((vxlan->cfg.flags & VXLAN_F_L2MISS) &&
286367653936SRoopa Prabhu !is_multicast_ether_addr(eth->h_dest))
286467653936SRoopa Prabhu vxlan_fdb_miss(vxlan, eth->h_dest);
286567653936SRoopa Prabhu
286684321030SGuillaume Nault dev_core_stats_tx_dropped_inc(dev);
28674095e0e1SNikolay Aleksandrov vxlan_vnifilter_count(vxlan, vni, NULL,
28684095e0e1SNikolay Aleksandrov VXLAN_VNI_STATS_TX_DROPS, 0);
286967653936SRoopa Prabhu kfree_skb(skb);
287067653936SRoopa Prabhu return NETDEV_TX_OK;
287167653936SRoopa Prabhu }
287267653936SRoopa Prabhu }
287367653936SRoopa Prabhu
287467653936SRoopa Prabhu if (rcu_access_pointer(f->nh)) {
287567653936SRoopa Prabhu vxlan_xmit_nh(skb, dev, f,
287667653936SRoopa Prabhu (vni ? : vxlan->default_dst.remote_vni), did_rsc);
287767653936SRoopa Prabhu } else {
287867653936SRoopa Prabhu list_for_each_entry_rcu(rdst, &f->remotes, list) {
287967653936SRoopa Prabhu struct sk_buff *skb1;
288067653936SRoopa Prabhu
288167653936SRoopa Prabhu if (!fdst) {
288267653936SRoopa Prabhu fdst = rdst;
288367653936SRoopa Prabhu continue;
288467653936SRoopa Prabhu }
288567653936SRoopa Prabhu skb1 = skb_clone(skb, GFP_ATOMIC);
288667653936SRoopa Prabhu if (skb1)
288767653936SRoopa Prabhu vxlan_xmit_one(skb1, dev, vni, rdst, did_rsc);
288867653936SRoopa Prabhu }
288967653936SRoopa Prabhu if (fdst)
289067653936SRoopa Prabhu vxlan_xmit_one(skb, dev, vni, fdst, did_rsc);
289167653936SRoopa Prabhu else
289267653936SRoopa Prabhu kfree_skb(skb);
289367653936SRoopa Prabhu }
289467653936SRoopa Prabhu
289567653936SRoopa Prabhu return NETDEV_TX_OK;
289667653936SRoopa Prabhu }
289767653936SRoopa Prabhu
289867653936SRoopa Prabhu /* Walk the forwarding table and purge stale entries */
vxlan_cleanup(struct timer_list * t)289967653936SRoopa Prabhu static void vxlan_cleanup(struct timer_list *t)
290067653936SRoopa Prabhu {
290167653936SRoopa Prabhu struct vxlan_dev *vxlan = from_timer(vxlan, t, age_timer);
290267653936SRoopa Prabhu unsigned long next_timer = jiffies + FDB_AGE_INTERVAL;
290367653936SRoopa Prabhu unsigned int h;
290467653936SRoopa Prabhu
290567653936SRoopa Prabhu if (!netif_running(vxlan->dev))
290667653936SRoopa Prabhu return;
290767653936SRoopa Prabhu
290867653936SRoopa Prabhu for (h = 0; h < FDB_HASH_SIZE; ++h) {
290967653936SRoopa Prabhu struct hlist_node *p, *n;
291067653936SRoopa Prabhu
291167653936SRoopa Prabhu spin_lock(&vxlan->hash_lock[h]);
291267653936SRoopa Prabhu hlist_for_each_safe(p, n, &vxlan->fdb_head[h]) {
291367653936SRoopa Prabhu struct vxlan_fdb *f
291467653936SRoopa Prabhu = container_of(p, struct vxlan_fdb, hlist);
291567653936SRoopa Prabhu unsigned long timeout;
291667653936SRoopa Prabhu
291767653936SRoopa Prabhu if (f->state & (NUD_PERMANENT | NUD_NOARP))
291867653936SRoopa Prabhu continue;
291967653936SRoopa Prabhu
292067653936SRoopa Prabhu if (f->flags & NTF_EXT_LEARNED)
292167653936SRoopa Prabhu continue;
292267653936SRoopa Prabhu
292367653936SRoopa Prabhu timeout = f->used + vxlan->cfg.age_interval * HZ;
292467653936SRoopa Prabhu if (time_before_eq(timeout, jiffies)) {
292567653936SRoopa Prabhu netdev_dbg(vxlan->dev,
292667653936SRoopa Prabhu "garbage collect %pM\n",
292767653936SRoopa Prabhu f->eth_addr);
292867653936SRoopa Prabhu f->state = NUD_STALE;
292967653936SRoopa Prabhu vxlan_fdb_destroy(vxlan, f, true, true);
293067653936SRoopa Prabhu } else if (time_before(timeout, next_timer))
293167653936SRoopa Prabhu next_timer = timeout;
293267653936SRoopa Prabhu }
293367653936SRoopa Prabhu spin_unlock(&vxlan->hash_lock[h]);
293467653936SRoopa Prabhu }
293567653936SRoopa Prabhu
293667653936SRoopa Prabhu mod_timer(&vxlan->age_timer, next_timer);
293767653936SRoopa Prabhu }
293867653936SRoopa Prabhu
vxlan_vs_del_dev(struct vxlan_dev * vxlan)293967653936SRoopa Prabhu static void vxlan_vs_del_dev(struct vxlan_dev *vxlan)
294067653936SRoopa Prabhu {
294167653936SRoopa Prabhu struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
294267653936SRoopa Prabhu
294367653936SRoopa Prabhu spin_lock(&vn->sock_lock);
294467653936SRoopa Prabhu hlist_del_init_rcu(&vxlan->hlist4.hlist);
294567653936SRoopa Prabhu #if IS_ENABLED(CONFIG_IPV6)
294667653936SRoopa Prabhu hlist_del_init_rcu(&vxlan->hlist6.hlist);
294767653936SRoopa Prabhu #endif
294867653936SRoopa Prabhu spin_unlock(&vn->sock_lock);
294967653936SRoopa Prabhu }
295067653936SRoopa Prabhu
vxlan_vs_add_dev(struct vxlan_sock * vs,struct vxlan_dev * vxlan,struct vxlan_dev_node * node)295167653936SRoopa Prabhu static void vxlan_vs_add_dev(struct vxlan_sock *vs, struct vxlan_dev *vxlan,
295267653936SRoopa Prabhu struct vxlan_dev_node *node)
295367653936SRoopa Prabhu {
295467653936SRoopa Prabhu struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
295567653936SRoopa Prabhu __be32 vni = vxlan->default_dst.remote_vni;
295667653936SRoopa Prabhu
295767653936SRoopa Prabhu node->vxlan = vxlan;
295867653936SRoopa Prabhu spin_lock(&vn->sock_lock);
295967653936SRoopa Prabhu hlist_add_head_rcu(&node->hlist, vni_head(vs, vni));
296067653936SRoopa Prabhu spin_unlock(&vn->sock_lock);
296167653936SRoopa Prabhu }
296267653936SRoopa Prabhu
296367653936SRoopa Prabhu /* Setup stats when device is created */
vxlan_init(struct net_device * dev)296467653936SRoopa Prabhu static int vxlan_init(struct net_device *dev)
296567653936SRoopa Prabhu {
296667653936SRoopa Prabhu struct vxlan_dev *vxlan = netdev_priv(dev);
296767653936SRoopa Prabhu int err;
296867653936SRoopa Prabhu
2969f9c4bb0bSRoopa Prabhu if (vxlan->cfg.flags & VXLAN_F_VNIFILTER)
2970f9c4bb0bSRoopa Prabhu vxlan_vnigroup_init(vxlan);
2971f9c4bb0bSRoopa Prabhu
297267653936SRoopa Prabhu dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
297306bf6294SIdo Schimmel if (!dev->tstats) {
297406bf6294SIdo Schimmel err = -ENOMEM;
297506bf6294SIdo Schimmel goto err_vnigroup_uninit;
297667653936SRoopa Prabhu }
297767653936SRoopa Prabhu
297806bf6294SIdo Schimmel err = gro_cells_init(&vxlan->gro_cells, dev);
297906bf6294SIdo Schimmel if (err)
298006bf6294SIdo Schimmel goto err_free_percpu;
298106bf6294SIdo Schimmel
2982a3a48de5SIdo Schimmel err = vxlan_mdb_init(vxlan);
2983a3a48de5SIdo Schimmel if (err)
2984a3a48de5SIdo Schimmel goto err_gro_cells_destroy;
2985a3a48de5SIdo Schimmel
2986a7b862abSEric Dumazet netdev_lockdep_set_classes(dev);
298767653936SRoopa Prabhu return 0;
298806bf6294SIdo Schimmel
2989a3a48de5SIdo Schimmel err_gro_cells_destroy:
2990a3a48de5SIdo Schimmel gro_cells_destroy(&vxlan->gro_cells);
299106bf6294SIdo Schimmel err_free_percpu:
299206bf6294SIdo Schimmel free_percpu(dev->tstats);
299306bf6294SIdo Schimmel err_vnigroup_uninit:
299406bf6294SIdo Schimmel if (vxlan->cfg.flags & VXLAN_F_VNIFILTER)
299506bf6294SIdo Schimmel vxlan_vnigroup_uninit(vxlan);
299606bf6294SIdo Schimmel return err;
299767653936SRoopa Prabhu }
299867653936SRoopa Prabhu
vxlan_fdb_delete_default(struct vxlan_dev * vxlan,__be32 vni)299967653936SRoopa Prabhu static void vxlan_fdb_delete_default(struct vxlan_dev *vxlan, __be32 vni)
300067653936SRoopa Prabhu {
300167653936SRoopa Prabhu struct vxlan_fdb *f;
300267653936SRoopa Prabhu u32 hash_index = fdb_head_index(vxlan, all_zeros_mac, vni);
300367653936SRoopa Prabhu
300467653936SRoopa Prabhu spin_lock_bh(&vxlan->hash_lock[hash_index]);
300567653936SRoopa Prabhu f = __vxlan_find_mac(vxlan, all_zeros_mac, vni);
300667653936SRoopa Prabhu if (f)
300767653936SRoopa Prabhu vxlan_fdb_destroy(vxlan, f, true, true);
300867653936SRoopa Prabhu spin_unlock_bh(&vxlan->hash_lock[hash_index]);
300967653936SRoopa Prabhu }
301067653936SRoopa Prabhu
vxlan_uninit(struct net_device * dev)301167653936SRoopa Prabhu static void vxlan_uninit(struct net_device *dev)
301267653936SRoopa Prabhu {
301367653936SRoopa Prabhu struct vxlan_dev *vxlan = netdev_priv(dev);
301467653936SRoopa Prabhu
3015a3a48de5SIdo Schimmel vxlan_mdb_fini(vxlan);
3016a3a48de5SIdo Schimmel
3017f9c4bb0bSRoopa Prabhu if (vxlan->cfg.flags & VXLAN_F_VNIFILTER)
3018f9c4bb0bSRoopa Prabhu vxlan_vnigroup_uninit(vxlan);
3019f9c4bb0bSRoopa Prabhu
302067653936SRoopa Prabhu gro_cells_destroy(&vxlan->gro_cells);
302167653936SRoopa Prabhu
302267653936SRoopa Prabhu vxlan_fdb_delete_default(vxlan, vxlan->cfg.vni);
302367653936SRoopa Prabhu
302467653936SRoopa Prabhu free_percpu(dev->tstats);
302567653936SRoopa Prabhu }
302667653936SRoopa Prabhu
302767653936SRoopa Prabhu /* Start ageing timer and join group when device is brought up */
vxlan_open(struct net_device * dev)302867653936SRoopa Prabhu static int vxlan_open(struct net_device *dev)
302967653936SRoopa Prabhu {
303067653936SRoopa Prabhu struct vxlan_dev *vxlan = netdev_priv(dev);
303167653936SRoopa Prabhu int ret;
303267653936SRoopa Prabhu
303367653936SRoopa Prabhu ret = vxlan_sock_add(vxlan);
303467653936SRoopa Prabhu if (ret < 0)
303567653936SRoopa Prabhu return ret;
303667653936SRoopa Prabhu
3037f9c4bb0bSRoopa Prabhu ret = vxlan_multicast_join(vxlan);
303867653936SRoopa Prabhu if (ret) {
303967653936SRoopa Prabhu vxlan_sock_release(vxlan);
304067653936SRoopa Prabhu return ret;
304167653936SRoopa Prabhu }
304267653936SRoopa Prabhu
304367653936SRoopa Prabhu if (vxlan->cfg.age_interval)
304467653936SRoopa Prabhu mod_timer(&vxlan->age_timer, jiffies + FDB_AGE_INTERVAL);
304567653936SRoopa Prabhu
304667653936SRoopa Prabhu return ret;
304767653936SRoopa Prabhu }
304867653936SRoopa Prabhu
304967653936SRoopa Prabhu /* Purge the forwarding table */
vxlan_flush(struct vxlan_dev * vxlan,bool do_all)305067653936SRoopa Prabhu static void vxlan_flush(struct vxlan_dev *vxlan, bool do_all)
305167653936SRoopa Prabhu {
305267653936SRoopa Prabhu unsigned int h;
305367653936SRoopa Prabhu
305467653936SRoopa Prabhu for (h = 0; h < FDB_HASH_SIZE; ++h) {
305567653936SRoopa Prabhu struct hlist_node *p, *n;
305667653936SRoopa Prabhu
305767653936SRoopa Prabhu spin_lock_bh(&vxlan->hash_lock[h]);
305867653936SRoopa Prabhu hlist_for_each_safe(p, n, &vxlan->fdb_head[h]) {
305967653936SRoopa Prabhu struct vxlan_fdb *f
306067653936SRoopa Prabhu = container_of(p, struct vxlan_fdb, hlist);
306167653936SRoopa Prabhu if (!do_all && (f->state & (NUD_PERMANENT | NUD_NOARP)))
306267653936SRoopa Prabhu continue;
306367653936SRoopa Prabhu /* the all_zeros_mac entry is deleted at vxlan_uninit */
306467653936SRoopa Prabhu if (is_zero_ether_addr(f->eth_addr) &&
306567653936SRoopa Prabhu f->vni == vxlan->cfg.vni)
306667653936SRoopa Prabhu continue;
306767653936SRoopa Prabhu vxlan_fdb_destroy(vxlan, f, true, true);
306867653936SRoopa Prabhu }
306967653936SRoopa Prabhu spin_unlock_bh(&vxlan->hash_lock[h]);
307067653936SRoopa Prabhu }
307167653936SRoopa Prabhu }
307267653936SRoopa Prabhu
307367653936SRoopa Prabhu /* Cleanup timer and forwarding table on shutdown */
vxlan_stop(struct net_device * dev)307467653936SRoopa Prabhu static int vxlan_stop(struct net_device *dev)
307567653936SRoopa Prabhu {
307667653936SRoopa Prabhu struct vxlan_dev *vxlan = netdev_priv(dev);
307767653936SRoopa Prabhu
3078f9c4bb0bSRoopa Prabhu vxlan_multicast_leave(vxlan);
307967653936SRoopa Prabhu
308067653936SRoopa Prabhu del_timer_sync(&vxlan->age_timer);
308167653936SRoopa Prabhu
308267653936SRoopa Prabhu vxlan_flush(vxlan, false);
308367653936SRoopa Prabhu vxlan_sock_release(vxlan);
308467653936SRoopa Prabhu
3085e58bc864SGuo Zhengkui return 0;
308667653936SRoopa Prabhu }
308767653936SRoopa Prabhu
308867653936SRoopa Prabhu /* Stub, nothing needs to be done. */
vxlan_set_multicast_list(struct net_device * dev)308967653936SRoopa Prabhu static void vxlan_set_multicast_list(struct net_device *dev)
309067653936SRoopa Prabhu {
309167653936SRoopa Prabhu }
309267653936SRoopa Prabhu
vxlan_change_mtu(struct net_device * dev,int new_mtu)309367653936SRoopa Prabhu static int vxlan_change_mtu(struct net_device *dev, int new_mtu)
309467653936SRoopa Prabhu {
309567653936SRoopa Prabhu struct vxlan_dev *vxlan = netdev_priv(dev);
309667653936SRoopa Prabhu struct vxlan_rdst *dst = &vxlan->default_dst;
309767653936SRoopa Prabhu struct net_device *lowerdev = __dev_get_by_index(vxlan->net,
309867653936SRoopa Prabhu dst->remote_ifindex);
309967653936SRoopa Prabhu
310067653936SRoopa Prabhu /* This check is different than dev->max_mtu, because it looks at
310167653936SRoopa Prabhu * the lowerdev->mtu, rather than the static dev->max_mtu
310267653936SRoopa Prabhu */
310367653936SRoopa Prabhu if (lowerdev) {
310494d166c5SJiri Benc int max_mtu = lowerdev->mtu - vxlan_headroom(vxlan->cfg.flags);
310567653936SRoopa Prabhu if (new_mtu > max_mtu)
310667653936SRoopa Prabhu return -EINVAL;
310767653936SRoopa Prabhu }
310867653936SRoopa Prabhu
310967653936SRoopa Prabhu dev->mtu = new_mtu;
311067653936SRoopa Prabhu return 0;
311167653936SRoopa Prabhu }
311267653936SRoopa Prabhu
vxlan_fill_metadata_dst(struct net_device * dev,struct sk_buff * skb)311367653936SRoopa Prabhu static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
311467653936SRoopa Prabhu {
311567653936SRoopa Prabhu struct vxlan_dev *vxlan = netdev_priv(dev);
311667653936SRoopa Prabhu struct ip_tunnel_info *info = skb_tunnel_info(skb);
311767653936SRoopa Prabhu __be16 sport, dport;
311867653936SRoopa Prabhu
311967653936SRoopa Prabhu sport = udp_flow_src_port(dev_net(dev), skb, vxlan->cfg.port_min,
312067653936SRoopa Prabhu vxlan->cfg.port_max, true);
312167653936SRoopa Prabhu dport = info->key.tp_dst ? : vxlan->cfg.dst_port;
312267653936SRoopa Prabhu
312367653936SRoopa Prabhu if (ip_tunnel_info_af(info) == AF_INET) {
312467653936SRoopa Prabhu struct vxlan_sock *sock4 = rcu_dereference(vxlan->vn4_sock);
312567653936SRoopa Prabhu struct rtable *rt;
312667653936SRoopa Prabhu
312767653936SRoopa Prabhu rt = vxlan_get_route(vxlan, dev, sock4, skb, 0, info->key.tos,
312867653936SRoopa Prabhu info->key.u.ipv4.dst,
312967653936SRoopa Prabhu &info->key.u.ipv4.src, dport, sport,
31307e2fb8bcSPaul Chaignon info->key.flow_flags, &info->dst_cache,
31317e2fb8bcSPaul Chaignon info);
313267653936SRoopa Prabhu if (IS_ERR(rt))
313367653936SRoopa Prabhu return PTR_ERR(rt);
313467653936SRoopa Prabhu ip_rt_put(rt);
313567653936SRoopa Prabhu } else {
313667653936SRoopa Prabhu #if IS_ENABLED(CONFIG_IPV6)
313767653936SRoopa Prabhu struct vxlan_sock *sock6 = rcu_dereference(vxlan->vn6_sock);
313867653936SRoopa Prabhu struct dst_entry *ndst;
313967653936SRoopa Prabhu
314067653936SRoopa Prabhu ndst = vxlan6_get_route(vxlan, dev, sock6, skb, 0, info->key.tos,
314167653936SRoopa Prabhu info->key.label, &info->key.u.ipv6.dst,
314267653936SRoopa Prabhu &info->key.u.ipv6.src, dport, sport,
314367653936SRoopa Prabhu &info->dst_cache, info);
314467653936SRoopa Prabhu if (IS_ERR(ndst))
314567653936SRoopa Prabhu return PTR_ERR(ndst);
314667653936SRoopa Prabhu dst_release(ndst);
314767653936SRoopa Prabhu #else /* !CONFIG_IPV6 */
314867653936SRoopa Prabhu return -EPFNOSUPPORT;
314967653936SRoopa Prabhu #endif
315067653936SRoopa Prabhu }
315167653936SRoopa Prabhu info->key.tp_src = sport;
315267653936SRoopa Prabhu info->key.tp_dst = dport;
315367653936SRoopa Prabhu return 0;
315467653936SRoopa Prabhu }
315567653936SRoopa Prabhu
315667653936SRoopa Prabhu static const struct net_device_ops vxlan_netdev_ether_ops = {
315767653936SRoopa Prabhu .ndo_init = vxlan_init,
315867653936SRoopa Prabhu .ndo_uninit = vxlan_uninit,
315967653936SRoopa Prabhu .ndo_open = vxlan_open,
316067653936SRoopa Prabhu .ndo_stop = vxlan_stop,
316167653936SRoopa Prabhu .ndo_start_xmit = vxlan_xmit,
316267653936SRoopa Prabhu .ndo_get_stats64 = dev_get_tstats64,
316367653936SRoopa Prabhu .ndo_set_rx_mode = vxlan_set_multicast_list,
316467653936SRoopa Prabhu .ndo_change_mtu = vxlan_change_mtu,
316567653936SRoopa Prabhu .ndo_validate_addr = eth_validate_addr,
316667653936SRoopa Prabhu .ndo_set_mac_address = eth_mac_addr,
316767653936SRoopa Prabhu .ndo_fdb_add = vxlan_fdb_add,
316867653936SRoopa Prabhu .ndo_fdb_del = vxlan_fdb_delete,
316967653936SRoopa Prabhu .ndo_fdb_dump = vxlan_fdb_dump,
317067653936SRoopa Prabhu .ndo_fdb_get = vxlan_fdb_get,
317108f876a7SIdo Schimmel .ndo_mdb_add = vxlan_mdb_add,
317208f876a7SIdo Schimmel .ndo_mdb_del = vxlan_mdb_del,
317308f876a7SIdo Schimmel .ndo_mdb_dump = vxlan_mdb_dump,
317467653936SRoopa Prabhu .ndo_fill_metadata_dst = vxlan_fill_metadata_dst,
317567653936SRoopa Prabhu };
317667653936SRoopa Prabhu
317767653936SRoopa Prabhu static const struct net_device_ops vxlan_netdev_raw_ops = {
317867653936SRoopa Prabhu .ndo_init = vxlan_init,
317967653936SRoopa Prabhu .ndo_uninit = vxlan_uninit,
318067653936SRoopa Prabhu .ndo_open = vxlan_open,
318167653936SRoopa Prabhu .ndo_stop = vxlan_stop,
318267653936SRoopa Prabhu .ndo_start_xmit = vxlan_xmit,
318367653936SRoopa Prabhu .ndo_get_stats64 = dev_get_tstats64,
318467653936SRoopa Prabhu .ndo_change_mtu = vxlan_change_mtu,
318567653936SRoopa Prabhu .ndo_fill_metadata_dst = vxlan_fill_metadata_dst,
318667653936SRoopa Prabhu };
318767653936SRoopa Prabhu
318867653936SRoopa Prabhu /* Info for udev, that this is a virtual tunnel endpoint */
318967653936SRoopa Prabhu static struct device_type vxlan_type = {
319067653936SRoopa Prabhu .name = "vxlan",
319167653936SRoopa Prabhu };
319267653936SRoopa Prabhu
319367653936SRoopa Prabhu /* Calls the ndo_udp_tunnel_add of the caller in order to
319467653936SRoopa Prabhu * supply the listening VXLAN udp ports. Callers are expected
319567653936SRoopa Prabhu * to implement the ndo_udp_tunnel_add.
319667653936SRoopa Prabhu */
vxlan_offload_rx_ports(struct net_device * dev,bool push)319767653936SRoopa Prabhu static void vxlan_offload_rx_ports(struct net_device *dev, bool push)
319867653936SRoopa Prabhu {
319967653936SRoopa Prabhu struct vxlan_sock *vs;
320067653936SRoopa Prabhu struct net *net = dev_net(dev);
320167653936SRoopa Prabhu struct vxlan_net *vn = net_generic(net, vxlan_net_id);
320267653936SRoopa Prabhu unsigned int i;
320367653936SRoopa Prabhu
320467653936SRoopa Prabhu spin_lock(&vn->sock_lock);
320567653936SRoopa Prabhu for (i = 0; i < PORT_HASH_SIZE; ++i) {
320667653936SRoopa Prabhu hlist_for_each_entry_rcu(vs, &vn->sock_list[i], hlist) {
320767653936SRoopa Prabhu unsigned short type;
320867653936SRoopa Prabhu
320967653936SRoopa Prabhu if (vs->flags & VXLAN_F_GPE)
321067653936SRoopa Prabhu type = UDP_TUNNEL_TYPE_VXLAN_GPE;
321167653936SRoopa Prabhu else
321267653936SRoopa Prabhu type = UDP_TUNNEL_TYPE_VXLAN;
321367653936SRoopa Prabhu
321467653936SRoopa Prabhu if (push)
321567653936SRoopa Prabhu udp_tunnel_push_rx_port(dev, vs->sock, type);
321667653936SRoopa Prabhu else
321767653936SRoopa Prabhu udp_tunnel_drop_rx_port(dev, vs->sock, type);
321867653936SRoopa Prabhu }
321967653936SRoopa Prabhu }
322067653936SRoopa Prabhu spin_unlock(&vn->sock_lock);
322167653936SRoopa Prabhu }
322267653936SRoopa Prabhu
322367653936SRoopa Prabhu /* Initialize the device structure. */
vxlan_setup(struct net_device * dev)322467653936SRoopa Prabhu static void vxlan_setup(struct net_device *dev)
322567653936SRoopa Prabhu {
322667653936SRoopa Prabhu struct vxlan_dev *vxlan = netdev_priv(dev);
322767653936SRoopa Prabhu unsigned int h;
322867653936SRoopa Prabhu
322967653936SRoopa Prabhu eth_hw_addr_random(dev);
323067653936SRoopa Prabhu ether_setup(dev);
323167653936SRoopa Prabhu
323267653936SRoopa Prabhu dev->needs_free_netdev = true;
323367653936SRoopa Prabhu SET_NETDEV_DEVTYPE(dev, &vxlan_type);
323467653936SRoopa Prabhu
323567653936SRoopa Prabhu dev->features |= NETIF_F_LLTX;
323667653936SRoopa Prabhu dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_FRAGLIST;
323767653936SRoopa Prabhu dev->features |= NETIF_F_RXCSUM;
323867653936SRoopa Prabhu dev->features |= NETIF_F_GSO_SOFTWARE;
323967653936SRoopa Prabhu
324067653936SRoopa Prabhu dev->vlan_features = dev->features;
324167653936SRoopa Prabhu dev->hw_features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_FRAGLIST;
324267653936SRoopa Prabhu dev->hw_features |= NETIF_F_RXCSUM;
324367653936SRoopa Prabhu dev->hw_features |= NETIF_F_GSO_SOFTWARE;
324467653936SRoopa Prabhu netif_keep_dst(dev);
324567653936SRoopa Prabhu dev->priv_flags |= IFF_NO_QUEUE | IFF_CHANGE_PROTO_DOWN;
324667653936SRoopa Prabhu
324767653936SRoopa Prabhu /* MTU range: 68 - 65535 */
324867653936SRoopa Prabhu dev->min_mtu = ETH_MIN_MTU;
324967653936SRoopa Prabhu dev->max_mtu = ETH_MAX_MTU;
325067653936SRoopa Prabhu
325167653936SRoopa Prabhu INIT_LIST_HEAD(&vxlan->next);
325267653936SRoopa Prabhu
325367653936SRoopa Prabhu timer_setup(&vxlan->age_timer, vxlan_cleanup, TIMER_DEFERRABLE);
325467653936SRoopa Prabhu
325567653936SRoopa Prabhu vxlan->dev = dev;
325667653936SRoopa Prabhu
325767653936SRoopa Prabhu for (h = 0; h < FDB_HASH_SIZE; ++h) {
325867653936SRoopa Prabhu spin_lock_init(&vxlan->hash_lock[h]);
325967653936SRoopa Prabhu INIT_HLIST_HEAD(&vxlan->fdb_head[h]);
326067653936SRoopa Prabhu }
326167653936SRoopa Prabhu }
326267653936SRoopa Prabhu
vxlan_ether_setup(struct net_device * dev)326367653936SRoopa Prabhu static void vxlan_ether_setup(struct net_device *dev)
326467653936SRoopa Prabhu {
326567653936SRoopa Prabhu dev->priv_flags &= ~IFF_TX_SKB_SHARING;
326667653936SRoopa Prabhu dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
326767653936SRoopa Prabhu dev->netdev_ops = &vxlan_netdev_ether_ops;
326867653936SRoopa Prabhu }
326967653936SRoopa Prabhu
vxlan_raw_setup(struct net_device * dev)327067653936SRoopa Prabhu static void vxlan_raw_setup(struct net_device *dev)
327167653936SRoopa Prabhu {
327267653936SRoopa Prabhu dev->header_ops = NULL;
327367653936SRoopa Prabhu dev->type = ARPHRD_NONE;
327467653936SRoopa Prabhu dev->hard_header_len = 0;
327567653936SRoopa Prabhu dev->addr_len = 0;
327667653936SRoopa Prabhu dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
327767653936SRoopa Prabhu dev->netdev_ops = &vxlan_netdev_raw_ops;
327867653936SRoopa Prabhu }
327967653936SRoopa Prabhu
328067653936SRoopa Prabhu static const struct nla_policy vxlan_policy[IFLA_VXLAN_MAX + 1] = {
328169474a8aSVladimir Nikishkin [IFLA_VXLAN_UNSPEC] = { .strict_start_type = IFLA_VXLAN_LOCALBYPASS },
328267653936SRoopa Prabhu [IFLA_VXLAN_ID] = { .type = NLA_U32 },
328367653936SRoopa Prabhu [IFLA_VXLAN_GROUP] = { .len = sizeof_field(struct iphdr, daddr) },
328467653936SRoopa Prabhu [IFLA_VXLAN_GROUP6] = { .len = sizeof(struct in6_addr) },
328567653936SRoopa Prabhu [IFLA_VXLAN_LINK] = { .type = NLA_U32 },
328667653936SRoopa Prabhu [IFLA_VXLAN_LOCAL] = { .len = sizeof_field(struct iphdr, saddr) },
328767653936SRoopa Prabhu [IFLA_VXLAN_LOCAL6] = { .len = sizeof(struct in6_addr) },
328867653936SRoopa Prabhu [IFLA_VXLAN_TOS] = { .type = NLA_U8 },
328967653936SRoopa Prabhu [IFLA_VXLAN_TTL] = { .type = NLA_U8 },
329067653936SRoopa Prabhu [IFLA_VXLAN_LABEL] = { .type = NLA_U32 },
329167653936SRoopa Prabhu [IFLA_VXLAN_LEARNING] = { .type = NLA_U8 },
329267653936SRoopa Prabhu [IFLA_VXLAN_AGEING] = { .type = NLA_U32 },
329367653936SRoopa Prabhu [IFLA_VXLAN_LIMIT] = { .type = NLA_U32 },
329467653936SRoopa Prabhu [IFLA_VXLAN_PORT_RANGE] = { .len = sizeof(struct ifla_vxlan_port_range) },
329567653936SRoopa Prabhu [IFLA_VXLAN_PROXY] = { .type = NLA_U8 },
329667653936SRoopa Prabhu [IFLA_VXLAN_RSC] = { .type = NLA_U8 },
329767653936SRoopa Prabhu [IFLA_VXLAN_L2MISS] = { .type = NLA_U8 },
329867653936SRoopa Prabhu [IFLA_VXLAN_L3MISS] = { .type = NLA_U8 },
329967653936SRoopa Prabhu [IFLA_VXLAN_COLLECT_METADATA] = { .type = NLA_U8 },
330067653936SRoopa Prabhu [IFLA_VXLAN_PORT] = { .type = NLA_U16 },
330167653936SRoopa Prabhu [IFLA_VXLAN_UDP_CSUM] = { .type = NLA_U8 },
330267653936SRoopa Prabhu [IFLA_VXLAN_UDP_ZERO_CSUM6_TX] = { .type = NLA_U8 },
330367653936SRoopa Prabhu [IFLA_VXLAN_UDP_ZERO_CSUM6_RX] = { .type = NLA_U8 },
330467653936SRoopa Prabhu [IFLA_VXLAN_REMCSUM_TX] = { .type = NLA_U8 },
330567653936SRoopa Prabhu [IFLA_VXLAN_REMCSUM_RX] = { .type = NLA_U8 },
330667653936SRoopa Prabhu [IFLA_VXLAN_GBP] = { .type = NLA_FLAG, },
330767653936SRoopa Prabhu [IFLA_VXLAN_GPE] = { .type = NLA_FLAG, },
330867653936SRoopa Prabhu [IFLA_VXLAN_REMCSUM_NOPARTIAL] = { .type = NLA_FLAG },
330967653936SRoopa Prabhu [IFLA_VXLAN_TTL_INHERIT] = { .type = NLA_FLAG },
331067653936SRoopa Prabhu [IFLA_VXLAN_DF] = { .type = NLA_U8 },
3311f9c4bb0bSRoopa Prabhu [IFLA_VXLAN_VNIFILTER] = { .type = NLA_U8 },
331269474a8aSVladimir Nikishkin [IFLA_VXLAN_LOCALBYPASS] = NLA_POLICY_MAX(NLA_U8, 1),
331367653936SRoopa Prabhu };
331467653936SRoopa Prabhu
vxlan_validate(struct nlattr * tb[],struct nlattr * data[],struct netlink_ext_ack * extack)331567653936SRoopa Prabhu static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[],
331667653936SRoopa Prabhu struct netlink_ext_ack *extack)
331767653936SRoopa Prabhu {
331867653936SRoopa Prabhu if (tb[IFLA_ADDRESS]) {
331967653936SRoopa Prabhu if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) {
332067653936SRoopa Prabhu NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_ADDRESS],
332167653936SRoopa Prabhu "Provided link layer address is not Ethernet");
332267653936SRoopa Prabhu return -EINVAL;
332367653936SRoopa Prabhu }
332467653936SRoopa Prabhu
332567653936SRoopa Prabhu if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) {
332667653936SRoopa Prabhu NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_ADDRESS],
332767653936SRoopa Prabhu "Provided Ethernet address is not unicast");
332867653936SRoopa Prabhu return -EADDRNOTAVAIL;
332967653936SRoopa Prabhu }
333067653936SRoopa Prabhu }
333167653936SRoopa Prabhu
333267653936SRoopa Prabhu if (tb[IFLA_MTU]) {
333367653936SRoopa Prabhu u32 mtu = nla_get_u32(tb[IFLA_MTU]);
333467653936SRoopa Prabhu
333567653936SRoopa Prabhu if (mtu < ETH_MIN_MTU || mtu > ETH_MAX_MTU) {
333667653936SRoopa Prabhu NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_MTU],
333767653936SRoopa Prabhu "MTU must be between 68 and 65535");
333867653936SRoopa Prabhu return -EINVAL;
333967653936SRoopa Prabhu }
334067653936SRoopa Prabhu }
334167653936SRoopa Prabhu
334267653936SRoopa Prabhu if (!data) {
334367653936SRoopa Prabhu NL_SET_ERR_MSG(extack,
334467653936SRoopa Prabhu "Required attributes not provided to perform the operation");
334567653936SRoopa Prabhu return -EINVAL;
334667653936SRoopa Prabhu }
334767653936SRoopa Prabhu
334867653936SRoopa Prabhu if (data[IFLA_VXLAN_ID]) {
334967653936SRoopa Prabhu u32 id = nla_get_u32(data[IFLA_VXLAN_ID]);
335067653936SRoopa Prabhu
335167653936SRoopa Prabhu if (id >= VXLAN_N_VID) {
335267653936SRoopa Prabhu NL_SET_ERR_MSG_ATTR(extack, data[IFLA_VXLAN_ID],
335367653936SRoopa Prabhu "VXLAN ID must be lower than 16777216");
335467653936SRoopa Prabhu return -ERANGE;
335567653936SRoopa Prabhu }
335667653936SRoopa Prabhu }
335767653936SRoopa Prabhu
335867653936SRoopa Prabhu if (data[IFLA_VXLAN_PORT_RANGE]) {
335967653936SRoopa Prabhu const struct ifla_vxlan_port_range *p
336067653936SRoopa Prabhu = nla_data(data[IFLA_VXLAN_PORT_RANGE]);
336167653936SRoopa Prabhu
336267653936SRoopa Prabhu if (ntohs(p->high) < ntohs(p->low)) {
336367653936SRoopa Prabhu NL_SET_ERR_MSG_ATTR(extack, data[IFLA_VXLAN_PORT_RANGE],
336467653936SRoopa Prabhu "Invalid source port range");
336567653936SRoopa Prabhu return -EINVAL;
336667653936SRoopa Prabhu }
336767653936SRoopa Prabhu }
336867653936SRoopa Prabhu
336967653936SRoopa Prabhu if (data[IFLA_VXLAN_DF]) {
337067653936SRoopa Prabhu enum ifla_vxlan_df df = nla_get_u8(data[IFLA_VXLAN_DF]);
337167653936SRoopa Prabhu
337267653936SRoopa Prabhu if (df < 0 || df > VXLAN_DF_MAX) {
337367653936SRoopa Prabhu NL_SET_ERR_MSG_ATTR(extack, data[IFLA_VXLAN_DF],
337467653936SRoopa Prabhu "Invalid DF attribute");
337567653936SRoopa Prabhu return -EINVAL;
337667653936SRoopa Prabhu }
337767653936SRoopa Prabhu }
337867653936SRoopa Prabhu
337967653936SRoopa Prabhu return 0;
338067653936SRoopa Prabhu }
338167653936SRoopa Prabhu
vxlan_get_drvinfo(struct net_device * netdev,struct ethtool_drvinfo * drvinfo)338267653936SRoopa Prabhu static void vxlan_get_drvinfo(struct net_device *netdev,
338367653936SRoopa Prabhu struct ethtool_drvinfo *drvinfo)
338467653936SRoopa Prabhu {
3385fb3ceec1SWolfram Sang strscpy(drvinfo->version, VXLAN_VERSION, sizeof(drvinfo->version));
3386fb3ceec1SWolfram Sang strscpy(drvinfo->driver, "vxlan", sizeof(drvinfo->driver));
338767653936SRoopa Prabhu }
338867653936SRoopa Prabhu
vxlan_get_link_ksettings(struct net_device * dev,struct ethtool_link_ksettings * cmd)338967653936SRoopa Prabhu static int vxlan_get_link_ksettings(struct net_device *dev,
339067653936SRoopa Prabhu struct ethtool_link_ksettings *cmd)
339167653936SRoopa Prabhu {
339267653936SRoopa Prabhu struct vxlan_dev *vxlan = netdev_priv(dev);
339367653936SRoopa Prabhu struct vxlan_rdst *dst = &vxlan->default_dst;
339467653936SRoopa Prabhu struct net_device *lowerdev = __dev_get_by_index(vxlan->net,
339567653936SRoopa Prabhu dst->remote_ifindex);
339667653936SRoopa Prabhu
339767653936SRoopa Prabhu if (!lowerdev) {
339867653936SRoopa Prabhu cmd->base.duplex = DUPLEX_UNKNOWN;
339967653936SRoopa Prabhu cmd->base.port = PORT_OTHER;
340067653936SRoopa Prabhu cmd->base.speed = SPEED_UNKNOWN;
340167653936SRoopa Prabhu
340267653936SRoopa Prabhu return 0;
340367653936SRoopa Prabhu }
340467653936SRoopa Prabhu
340567653936SRoopa Prabhu return __ethtool_get_link_ksettings(lowerdev, cmd);
340667653936SRoopa Prabhu }
340767653936SRoopa Prabhu
340867653936SRoopa Prabhu static const struct ethtool_ops vxlan_ethtool_ops = {
340967653936SRoopa Prabhu .get_drvinfo = vxlan_get_drvinfo,
341067653936SRoopa Prabhu .get_link = ethtool_op_get_link,
341167653936SRoopa Prabhu .get_link_ksettings = vxlan_get_link_ksettings,
341267653936SRoopa Prabhu };
341367653936SRoopa Prabhu
vxlan_create_sock(struct net * net,bool ipv6,__be16 port,u32 flags,int ifindex)341467653936SRoopa Prabhu static struct socket *vxlan_create_sock(struct net *net, bool ipv6,
341567653936SRoopa Prabhu __be16 port, u32 flags, int ifindex)
341667653936SRoopa Prabhu {
341767653936SRoopa Prabhu struct socket *sock;
341867653936SRoopa Prabhu struct udp_port_cfg udp_conf;
341967653936SRoopa Prabhu int err;
342067653936SRoopa Prabhu
342167653936SRoopa Prabhu memset(&udp_conf, 0, sizeof(udp_conf));
342267653936SRoopa Prabhu
342367653936SRoopa Prabhu if (ipv6) {
342467653936SRoopa Prabhu udp_conf.family = AF_INET6;
342567653936SRoopa Prabhu udp_conf.use_udp6_rx_checksums =
342667653936SRoopa Prabhu !(flags & VXLAN_F_UDP_ZERO_CSUM6_RX);
342767653936SRoopa Prabhu udp_conf.ipv6_v6only = 1;
342867653936SRoopa Prabhu } else {
342967653936SRoopa Prabhu udp_conf.family = AF_INET;
343067653936SRoopa Prabhu }
343167653936SRoopa Prabhu
343267653936SRoopa Prabhu udp_conf.local_udp_port = port;
343367653936SRoopa Prabhu udp_conf.bind_ifindex = ifindex;
343467653936SRoopa Prabhu
343567653936SRoopa Prabhu /* Open UDP socket */
343667653936SRoopa Prabhu err = udp_sock_create(net, &udp_conf, &sock);
343767653936SRoopa Prabhu if (err < 0)
343867653936SRoopa Prabhu return ERR_PTR(err);
343967653936SRoopa Prabhu
344067653936SRoopa Prabhu udp_allow_gso(sock->sk);
344167653936SRoopa Prabhu return sock;
344267653936SRoopa Prabhu }
344367653936SRoopa Prabhu
344467653936SRoopa Prabhu /* Create new listen socket if needed */
vxlan_socket_create(struct net * net,bool ipv6,__be16 port,u32 flags,int ifindex)344567653936SRoopa Prabhu static struct vxlan_sock *vxlan_socket_create(struct net *net, bool ipv6,
344667653936SRoopa Prabhu __be16 port, u32 flags,
344767653936SRoopa Prabhu int ifindex)
344867653936SRoopa Prabhu {
344967653936SRoopa Prabhu struct vxlan_net *vn = net_generic(net, vxlan_net_id);
345067653936SRoopa Prabhu struct vxlan_sock *vs;
345167653936SRoopa Prabhu struct socket *sock;
345267653936SRoopa Prabhu unsigned int h;
345367653936SRoopa Prabhu struct udp_tunnel_sock_cfg tunnel_cfg;
345467653936SRoopa Prabhu
345567653936SRoopa Prabhu vs = kzalloc(sizeof(*vs), GFP_KERNEL);
345667653936SRoopa Prabhu if (!vs)
345767653936SRoopa Prabhu return ERR_PTR(-ENOMEM);
345867653936SRoopa Prabhu
345967653936SRoopa Prabhu for (h = 0; h < VNI_HASH_SIZE; ++h)
346067653936SRoopa Prabhu INIT_HLIST_HEAD(&vs->vni_list[h]);
346167653936SRoopa Prabhu
346267653936SRoopa Prabhu sock = vxlan_create_sock(net, ipv6, port, flags, ifindex);
346367653936SRoopa Prabhu if (IS_ERR(sock)) {
346467653936SRoopa Prabhu kfree(vs);
346567653936SRoopa Prabhu return ERR_CAST(sock);
346667653936SRoopa Prabhu }
346767653936SRoopa Prabhu
346867653936SRoopa Prabhu vs->sock = sock;
346967653936SRoopa Prabhu refcount_set(&vs->refcnt, 1);
347067653936SRoopa Prabhu vs->flags = (flags & VXLAN_F_RCV_FLAGS);
347167653936SRoopa Prabhu
347267653936SRoopa Prabhu spin_lock(&vn->sock_lock);
347367653936SRoopa Prabhu hlist_add_head_rcu(&vs->hlist, vs_head(net, port));
347467653936SRoopa Prabhu udp_tunnel_notify_add_rx_port(sock,
347567653936SRoopa Prabhu (vs->flags & VXLAN_F_GPE) ?
347667653936SRoopa Prabhu UDP_TUNNEL_TYPE_VXLAN_GPE :
347767653936SRoopa Prabhu UDP_TUNNEL_TYPE_VXLAN);
347867653936SRoopa Prabhu spin_unlock(&vn->sock_lock);
347967653936SRoopa Prabhu
348067653936SRoopa Prabhu /* Mark socket as an encapsulation socket. */
348167653936SRoopa Prabhu memset(&tunnel_cfg, 0, sizeof(tunnel_cfg));
348267653936SRoopa Prabhu tunnel_cfg.sk_user_data = vs;
348367653936SRoopa Prabhu tunnel_cfg.encap_type = 1;
348467653936SRoopa Prabhu tunnel_cfg.encap_rcv = vxlan_rcv;
348567653936SRoopa Prabhu tunnel_cfg.encap_err_lookup = vxlan_err_lookup;
348667653936SRoopa Prabhu tunnel_cfg.encap_destroy = NULL;
3487b0b672c4SJiri Benc if (vs->flags & VXLAN_F_GPE) {
3488b0b672c4SJiri Benc tunnel_cfg.gro_receive = vxlan_gpe_gro_receive;
3489b0b672c4SJiri Benc tunnel_cfg.gro_complete = vxlan_gpe_gro_complete;
3490b0b672c4SJiri Benc } else {
349167653936SRoopa Prabhu tunnel_cfg.gro_receive = vxlan_gro_receive;
349267653936SRoopa Prabhu tunnel_cfg.gro_complete = vxlan_gro_complete;
3493b0b672c4SJiri Benc }
349467653936SRoopa Prabhu
349567653936SRoopa Prabhu setup_udp_tunnel_sock(net, sock, &tunnel_cfg);
349667653936SRoopa Prabhu
349767653936SRoopa Prabhu return vs;
349867653936SRoopa Prabhu }
349967653936SRoopa Prabhu
__vxlan_sock_add(struct vxlan_dev * vxlan,bool ipv6)350067653936SRoopa Prabhu static int __vxlan_sock_add(struct vxlan_dev *vxlan, bool ipv6)
350167653936SRoopa Prabhu {
350267653936SRoopa Prabhu struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
3503f9c4bb0bSRoopa Prabhu bool metadata = vxlan->cfg.flags & VXLAN_F_COLLECT_METADATA;
350467653936SRoopa Prabhu struct vxlan_sock *vs = NULL;
350567653936SRoopa Prabhu struct vxlan_dev_node *node;
350667653936SRoopa Prabhu int l3mdev_index = 0;
350767653936SRoopa Prabhu
350867653936SRoopa Prabhu if (vxlan->cfg.remote_ifindex)
350967653936SRoopa Prabhu l3mdev_index = l3mdev_master_upper_ifindex_by_index(
351067653936SRoopa Prabhu vxlan->net, vxlan->cfg.remote_ifindex);
351167653936SRoopa Prabhu
351267653936SRoopa Prabhu if (!vxlan->cfg.no_share) {
351367653936SRoopa Prabhu spin_lock(&vn->sock_lock);
351467653936SRoopa Prabhu vs = vxlan_find_sock(vxlan->net, ipv6 ? AF_INET6 : AF_INET,
351567653936SRoopa Prabhu vxlan->cfg.dst_port, vxlan->cfg.flags,
351667653936SRoopa Prabhu l3mdev_index);
351767653936SRoopa Prabhu if (vs && !refcount_inc_not_zero(&vs->refcnt)) {
351867653936SRoopa Prabhu spin_unlock(&vn->sock_lock);
351967653936SRoopa Prabhu return -EBUSY;
352067653936SRoopa Prabhu }
352167653936SRoopa Prabhu spin_unlock(&vn->sock_lock);
352267653936SRoopa Prabhu }
352367653936SRoopa Prabhu if (!vs)
352467653936SRoopa Prabhu vs = vxlan_socket_create(vxlan->net, ipv6,
352567653936SRoopa Prabhu vxlan->cfg.dst_port, vxlan->cfg.flags,
352667653936SRoopa Prabhu l3mdev_index);
352767653936SRoopa Prabhu if (IS_ERR(vs))
352867653936SRoopa Prabhu return PTR_ERR(vs);
352967653936SRoopa Prabhu #if IS_ENABLED(CONFIG_IPV6)
353067653936SRoopa Prabhu if (ipv6) {
353167653936SRoopa Prabhu rcu_assign_pointer(vxlan->vn6_sock, vs);
353267653936SRoopa Prabhu node = &vxlan->hlist6;
353367653936SRoopa Prabhu } else
353467653936SRoopa Prabhu #endif
353567653936SRoopa Prabhu {
353667653936SRoopa Prabhu rcu_assign_pointer(vxlan->vn4_sock, vs);
353767653936SRoopa Prabhu node = &vxlan->hlist4;
353867653936SRoopa Prabhu }
3539f9c4bb0bSRoopa Prabhu
3540f9c4bb0bSRoopa Prabhu if (metadata && (vxlan->cfg.flags & VXLAN_F_VNIFILTER))
3541f9c4bb0bSRoopa Prabhu vxlan_vs_add_vnigrp(vxlan, vs, ipv6);
3542f9c4bb0bSRoopa Prabhu else
354367653936SRoopa Prabhu vxlan_vs_add_dev(vs, vxlan, node);
3544f9c4bb0bSRoopa Prabhu
354567653936SRoopa Prabhu return 0;
354667653936SRoopa Prabhu }
354767653936SRoopa Prabhu
vxlan_sock_add(struct vxlan_dev * vxlan)354867653936SRoopa Prabhu static int vxlan_sock_add(struct vxlan_dev *vxlan)
354967653936SRoopa Prabhu {
355067653936SRoopa Prabhu bool metadata = vxlan->cfg.flags & VXLAN_F_COLLECT_METADATA;
355167653936SRoopa Prabhu bool ipv6 = vxlan->cfg.flags & VXLAN_F_IPV6 || metadata;
355267653936SRoopa Prabhu bool ipv4 = !ipv6 || metadata;
355367653936SRoopa Prabhu int ret = 0;
355467653936SRoopa Prabhu
355567653936SRoopa Prabhu RCU_INIT_POINTER(vxlan->vn4_sock, NULL);
355667653936SRoopa Prabhu #if IS_ENABLED(CONFIG_IPV6)
355767653936SRoopa Prabhu RCU_INIT_POINTER(vxlan->vn6_sock, NULL);
355867653936SRoopa Prabhu if (ipv6) {
355967653936SRoopa Prabhu ret = __vxlan_sock_add(vxlan, true);
356067653936SRoopa Prabhu if (ret < 0 && ret != -EAFNOSUPPORT)
356167653936SRoopa Prabhu ipv4 = false;
356267653936SRoopa Prabhu }
356367653936SRoopa Prabhu #endif
356467653936SRoopa Prabhu if (ipv4)
356567653936SRoopa Prabhu ret = __vxlan_sock_add(vxlan, false);
356667653936SRoopa Prabhu if (ret < 0)
356767653936SRoopa Prabhu vxlan_sock_release(vxlan);
356867653936SRoopa Prabhu return ret;
356967653936SRoopa Prabhu }
357067653936SRoopa Prabhu
vxlan_vni_in_use(struct net * src_net,struct vxlan_dev * vxlan,struct vxlan_config * conf,__be32 vni)3571f9c4bb0bSRoopa Prabhu int vxlan_vni_in_use(struct net *src_net, struct vxlan_dev *vxlan,
3572efe0f94bSRoopa Prabhu struct vxlan_config *conf, __be32 vni)
3573efe0f94bSRoopa Prabhu {
3574efe0f94bSRoopa Prabhu struct vxlan_net *vn = net_generic(src_net, vxlan_net_id);
3575efe0f94bSRoopa Prabhu struct vxlan_dev *tmp;
3576efe0f94bSRoopa Prabhu
3577efe0f94bSRoopa Prabhu list_for_each_entry(tmp, &vn->vxlan_list, next) {
3578efe0f94bSRoopa Prabhu if (tmp == vxlan)
3579efe0f94bSRoopa Prabhu continue;
3580f9c4bb0bSRoopa Prabhu if (tmp->cfg.flags & VXLAN_F_VNIFILTER) {
3581f9c4bb0bSRoopa Prabhu if (!vxlan_vnifilter_lookup(tmp, vni))
3582efe0f94bSRoopa Prabhu continue;
3583f9c4bb0bSRoopa Prabhu } else if (tmp->cfg.vni != vni) {
3584f9c4bb0bSRoopa Prabhu continue;
3585f9c4bb0bSRoopa Prabhu }
3586efe0f94bSRoopa Prabhu if (tmp->cfg.dst_port != conf->dst_port)
3587efe0f94bSRoopa Prabhu continue;
3588efe0f94bSRoopa Prabhu if ((tmp->cfg.flags & (VXLAN_F_RCV_FLAGS | VXLAN_F_IPV6)) !=
3589efe0f94bSRoopa Prabhu (conf->flags & (VXLAN_F_RCV_FLAGS | VXLAN_F_IPV6)))
3590efe0f94bSRoopa Prabhu continue;
3591efe0f94bSRoopa Prabhu
3592efe0f94bSRoopa Prabhu if ((conf->flags & VXLAN_F_IPV6_LINKLOCAL) &&
3593efe0f94bSRoopa Prabhu tmp->cfg.remote_ifindex != conf->remote_ifindex)
3594efe0f94bSRoopa Prabhu continue;
3595efe0f94bSRoopa Prabhu
3596efe0f94bSRoopa Prabhu return -EEXIST;
3597efe0f94bSRoopa Prabhu }
3598efe0f94bSRoopa Prabhu
3599efe0f94bSRoopa Prabhu return 0;
3600efe0f94bSRoopa Prabhu }
3601efe0f94bSRoopa Prabhu
vxlan_config_validate(struct net * src_net,struct vxlan_config * conf,struct net_device ** lower,struct vxlan_dev * old,struct netlink_ext_ack * extack)360267653936SRoopa Prabhu static int vxlan_config_validate(struct net *src_net, struct vxlan_config *conf,
360367653936SRoopa Prabhu struct net_device **lower,
360467653936SRoopa Prabhu struct vxlan_dev *old,
360567653936SRoopa Prabhu struct netlink_ext_ack *extack)
360667653936SRoopa Prabhu {
360767653936SRoopa Prabhu bool use_ipv6 = false;
360867653936SRoopa Prabhu
360967653936SRoopa Prabhu if (conf->flags & VXLAN_F_GPE) {
361067653936SRoopa Prabhu /* For now, allow GPE only together with
361167653936SRoopa Prabhu * COLLECT_METADATA. This can be relaxed later; in such
361267653936SRoopa Prabhu * case, the other side of the PtP link will have to be
361367653936SRoopa Prabhu * provided.
361467653936SRoopa Prabhu */
361567653936SRoopa Prabhu if ((conf->flags & ~VXLAN_F_ALLOWED_GPE) ||
361667653936SRoopa Prabhu !(conf->flags & VXLAN_F_COLLECT_METADATA)) {
361767653936SRoopa Prabhu NL_SET_ERR_MSG(extack,
361867653936SRoopa Prabhu "VXLAN GPE does not support this combination of attributes");
361967653936SRoopa Prabhu return -EINVAL;
362067653936SRoopa Prabhu }
362167653936SRoopa Prabhu }
362267653936SRoopa Prabhu
362367653936SRoopa Prabhu if (!conf->remote_ip.sa.sa_family && !conf->saddr.sa.sa_family) {
362467653936SRoopa Prabhu /* Unless IPv6 is explicitly requested, assume IPv4 */
362567653936SRoopa Prabhu conf->remote_ip.sa.sa_family = AF_INET;
362667653936SRoopa Prabhu conf->saddr.sa.sa_family = AF_INET;
362767653936SRoopa Prabhu } else if (!conf->remote_ip.sa.sa_family) {
362867653936SRoopa Prabhu conf->remote_ip.sa.sa_family = conf->saddr.sa.sa_family;
362967653936SRoopa Prabhu } else if (!conf->saddr.sa.sa_family) {
363067653936SRoopa Prabhu conf->saddr.sa.sa_family = conf->remote_ip.sa.sa_family;
363167653936SRoopa Prabhu }
363267653936SRoopa Prabhu
363367653936SRoopa Prabhu if (conf->saddr.sa.sa_family != conf->remote_ip.sa.sa_family) {
363467653936SRoopa Prabhu NL_SET_ERR_MSG(extack,
363567653936SRoopa Prabhu "Local and remote address must be from the same family");
363667653936SRoopa Prabhu return -EINVAL;
363767653936SRoopa Prabhu }
363867653936SRoopa Prabhu
363967653936SRoopa Prabhu if (vxlan_addr_multicast(&conf->saddr)) {
364067653936SRoopa Prabhu NL_SET_ERR_MSG(extack, "Local address cannot be multicast");
364167653936SRoopa Prabhu return -EINVAL;
364267653936SRoopa Prabhu }
364367653936SRoopa Prabhu
364467653936SRoopa Prabhu if (conf->saddr.sa.sa_family == AF_INET6) {
364567653936SRoopa Prabhu if (!IS_ENABLED(CONFIG_IPV6)) {
364667653936SRoopa Prabhu NL_SET_ERR_MSG(extack,
364767653936SRoopa Prabhu "IPv6 support not enabled in the kernel");
364867653936SRoopa Prabhu return -EPFNOSUPPORT;
364967653936SRoopa Prabhu }
365067653936SRoopa Prabhu use_ipv6 = true;
365167653936SRoopa Prabhu conf->flags |= VXLAN_F_IPV6;
365267653936SRoopa Prabhu
365367653936SRoopa Prabhu if (!(conf->flags & VXLAN_F_COLLECT_METADATA)) {
365467653936SRoopa Prabhu int local_type =
365567653936SRoopa Prabhu ipv6_addr_type(&conf->saddr.sin6.sin6_addr);
365667653936SRoopa Prabhu int remote_type =
365767653936SRoopa Prabhu ipv6_addr_type(&conf->remote_ip.sin6.sin6_addr);
365867653936SRoopa Prabhu
365967653936SRoopa Prabhu if (local_type & IPV6_ADDR_LINKLOCAL) {
366067653936SRoopa Prabhu if (!(remote_type & IPV6_ADDR_LINKLOCAL) &&
366167653936SRoopa Prabhu (remote_type != IPV6_ADDR_ANY)) {
366267653936SRoopa Prabhu NL_SET_ERR_MSG(extack,
366367653936SRoopa Prabhu "Invalid combination of local and remote address scopes");
366467653936SRoopa Prabhu return -EINVAL;
366567653936SRoopa Prabhu }
366667653936SRoopa Prabhu
366767653936SRoopa Prabhu conf->flags |= VXLAN_F_IPV6_LINKLOCAL;
366867653936SRoopa Prabhu } else {
366967653936SRoopa Prabhu if (remote_type ==
367067653936SRoopa Prabhu (IPV6_ADDR_UNICAST | IPV6_ADDR_LINKLOCAL)) {
367167653936SRoopa Prabhu NL_SET_ERR_MSG(extack,
367267653936SRoopa Prabhu "Invalid combination of local and remote address scopes");
367367653936SRoopa Prabhu return -EINVAL;
367467653936SRoopa Prabhu }
367567653936SRoopa Prabhu
367667653936SRoopa Prabhu conf->flags &= ~VXLAN_F_IPV6_LINKLOCAL;
367767653936SRoopa Prabhu }
367867653936SRoopa Prabhu }
367967653936SRoopa Prabhu }
368067653936SRoopa Prabhu
368167653936SRoopa Prabhu if (conf->label && !use_ipv6) {
368267653936SRoopa Prabhu NL_SET_ERR_MSG(extack,
368367653936SRoopa Prabhu "Label attribute only applies to IPv6 VXLAN devices");
368467653936SRoopa Prabhu return -EINVAL;
368567653936SRoopa Prabhu }
368667653936SRoopa Prabhu
368767653936SRoopa Prabhu if (conf->remote_ifindex) {
368867653936SRoopa Prabhu struct net_device *lowerdev;
368967653936SRoopa Prabhu
369067653936SRoopa Prabhu lowerdev = __dev_get_by_index(src_net, conf->remote_ifindex);
369167653936SRoopa Prabhu if (!lowerdev) {
369267653936SRoopa Prabhu NL_SET_ERR_MSG(extack,
369367653936SRoopa Prabhu "Invalid local interface, device not found");
369467653936SRoopa Prabhu return -ENODEV;
369567653936SRoopa Prabhu }
369667653936SRoopa Prabhu
369767653936SRoopa Prabhu #if IS_ENABLED(CONFIG_IPV6)
369867653936SRoopa Prabhu if (use_ipv6) {
369967653936SRoopa Prabhu struct inet6_dev *idev = __in6_dev_get(lowerdev);
370067653936SRoopa Prabhu
370167653936SRoopa Prabhu if (idev && idev->cnf.disable_ipv6) {
370267653936SRoopa Prabhu NL_SET_ERR_MSG(extack,
370367653936SRoopa Prabhu "IPv6 support disabled by administrator");
370467653936SRoopa Prabhu return -EPERM;
370567653936SRoopa Prabhu }
370667653936SRoopa Prabhu }
370767653936SRoopa Prabhu #endif
370867653936SRoopa Prabhu
370967653936SRoopa Prabhu *lower = lowerdev;
371067653936SRoopa Prabhu } else {
371167653936SRoopa Prabhu if (vxlan_addr_multicast(&conf->remote_ip)) {
371267653936SRoopa Prabhu NL_SET_ERR_MSG(extack,
371367653936SRoopa Prabhu "Local interface required for multicast remote destination");
371467653936SRoopa Prabhu
371567653936SRoopa Prabhu return -EINVAL;
371667653936SRoopa Prabhu }
371767653936SRoopa Prabhu
371867653936SRoopa Prabhu #if IS_ENABLED(CONFIG_IPV6)
371967653936SRoopa Prabhu if (conf->flags & VXLAN_F_IPV6_LINKLOCAL) {
372067653936SRoopa Prabhu NL_SET_ERR_MSG(extack,
372167653936SRoopa Prabhu "Local interface required for link-local local/remote addresses");
372267653936SRoopa Prabhu return -EINVAL;
372367653936SRoopa Prabhu }
372467653936SRoopa Prabhu #endif
372567653936SRoopa Prabhu
372667653936SRoopa Prabhu *lower = NULL;
372767653936SRoopa Prabhu }
372867653936SRoopa Prabhu
372967653936SRoopa Prabhu if (!conf->dst_port) {
373067653936SRoopa Prabhu if (conf->flags & VXLAN_F_GPE)
373167653936SRoopa Prabhu conf->dst_port = htons(IANA_VXLAN_GPE_UDP_PORT);
373267653936SRoopa Prabhu else
373367653936SRoopa Prabhu conf->dst_port = htons(vxlan_port);
373467653936SRoopa Prabhu }
373567653936SRoopa Prabhu
373667653936SRoopa Prabhu if (!conf->age_interval)
373767653936SRoopa Prabhu conf->age_interval = FDB_AGE_DEFAULT;
373867653936SRoopa Prabhu
3739efe0f94bSRoopa Prabhu if (vxlan_vni_in_use(src_net, old, conf, conf->vni)) {
374067653936SRoopa Prabhu NL_SET_ERR_MSG(extack,
374167653936SRoopa Prabhu "A VXLAN device with the specified VNI already exists");
374267653936SRoopa Prabhu return -EEXIST;
374367653936SRoopa Prabhu }
374467653936SRoopa Prabhu
374567653936SRoopa Prabhu return 0;
374667653936SRoopa Prabhu }
374767653936SRoopa Prabhu
vxlan_config_apply(struct net_device * dev,struct vxlan_config * conf,struct net_device * lowerdev,struct net * src_net,bool changelink)374867653936SRoopa Prabhu static void vxlan_config_apply(struct net_device *dev,
374967653936SRoopa Prabhu struct vxlan_config *conf,
375067653936SRoopa Prabhu struct net_device *lowerdev,
375167653936SRoopa Prabhu struct net *src_net,
375267653936SRoopa Prabhu bool changelink)
375367653936SRoopa Prabhu {
375467653936SRoopa Prabhu struct vxlan_dev *vxlan = netdev_priv(dev);
375567653936SRoopa Prabhu struct vxlan_rdst *dst = &vxlan->default_dst;
375667653936SRoopa Prabhu unsigned short needed_headroom = ETH_HLEN;
375767653936SRoopa Prabhu int max_mtu = ETH_MAX_MTU;
375894d166c5SJiri Benc u32 flags = conf->flags;
375967653936SRoopa Prabhu
376067653936SRoopa Prabhu if (!changelink) {
376194d166c5SJiri Benc if (flags & VXLAN_F_GPE)
376267653936SRoopa Prabhu vxlan_raw_setup(dev);
376367653936SRoopa Prabhu else
376467653936SRoopa Prabhu vxlan_ether_setup(dev);
376567653936SRoopa Prabhu
376667653936SRoopa Prabhu if (conf->mtu)
376767653936SRoopa Prabhu dev->mtu = conf->mtu;
376867653936SRoopa Prabhu
376967653936SRoopa Prabhu vxlan->net = src_net;
377067653936SRoopa Prabhu }
377167653936SRoopa Prabhu
377267653936SRoopa Prabhu dst->remote_vni = conf->vni;
377367653936SRoopa Prabhu
377467653936SRoopa Prabhu memcpy(&dst->remote_ip, &conf->remote_ip, sizeof(conf->remote_ip));
377567653936SRoopa Prabhu
377667653936SRoopa Prabhu if (lowerdev) {
377767653936SRoopa Prabhu dst->remote_ifindex = conf->remote_ifindex;
377867653936SRoopa Prabhu
37796df6398fSJakub Kicinski netif_inherit_tso_max(dev, lowerdev);
378067653936SRoopa Prabhu
378167653936SRoopa Prabhu needed_headroom = lowerdev->hard_header_len;
378267653936SRoopa Prabhu needed_headroom += lowerdev->needed_headroom;
378367653936SRoopa Prabhu
378467653936SRoopa Prabhu dev->needed_tailroom = lowerdev->needed_tailroom;
378567653936SRoopa Prabhu
378694d166c5SJiri Benc max_mtu = lowerdev->mtu - vxlan_headroom(flags);
378767653936SRoopa Prabhu if (max_mtu < ETH_MIN_MTU)
378867653936SRoopa Prabhu max_mtu = ETH_MIN_MTU;
378967653936SRoopa Prabhu
379067653936SRoopa Prabhu if (!changelink && !conf->mtu)
379167653936SRoopa Prabhu dev->mtu = max_mtu;
379267653936SRoopa Prabhu }
379367653936SRoopa Prabhu
379467653936SRoopa Prabhu if (dev->mtu > max_mtu)
379567653936SRoopa Prabhu dev->mtu = max_mtu;
379667653936SRoopa Prabhu
379794d166c5SJiri Benc if (flags & VXLAN_F_COLLECT_METADATA)
379894d166c5SJiri Benc flags |= VXLAN_F_IPV6;
379994d166c5SJiri Benc needed_headroom += vxlan_headroom(flags);
380067653936SRoopa Prabhu dev->needed_headroom = needed_headroom;
380167653936SRoopa Prabhu
380267653936SRoopa Prabhu memcpy(&vxlan->cfg, conf, sizeof(*conf));
380367653936SRoopa Prabhu }
380467653936SRoopa Prabhu
vxlan_dev_configure(struct net * src_net,struct net_device * dev,struct vxlan_config * conf,bool changelink,struct netlink_ext_ack * extack)380567653936SRoopa Prabhu static int vxlan_dev_configure(struct net *src_net, struct net_device *dev,
380667653936SRoopa Prabhu struct vxlan_config *conf, bool changelink,
380767653936SRoopa Prabhu struct netlink_ext_ack *extack)
380867653936SRoopa Prabhu {
380967653936SRoopa Prabhu struct vxlan_dev *vxlan = netdev_priv(dev);
381067653936SRoopa Prabhu struct net_device *lowerdev;
381167653936SRoopa Prabhu int ret;
381267653936SRoopa Prabhu
381367653936SRoopa Prabhu ret = vxlan_config_validate(src_net, conf, &lowerdev, vxlan, extack);
381467653936SRoopa Prabhu if (ret)
381567653936SRoopa Prabhu return ret;
381667653936SRoopa Prabhu
381767653936SRoopa Prabhu vxlan_config_apply(dev, conf, lowerdev, src_net, changelink);
381867653936SRoopa Prabhu
381967653936SRoopa Prabhu return 0;
382067653936SRoopa Prabhu }
382167653936SRoopa Prabhu
__vxlan_dev_create(struct net * net,struct net_device * dev,struct vxlan_config * conf,struct netlink_ext_ack * extack)382267653936SRoopa Prabhu static int __vxlan_dev_create(struct net *net, struct net_device *dev,
382367653936SRoopa Prabhu struct vxlan_config *conf,
382467653936SRoopa Prabhu struct netlink_ext_ack *extack)
382567653936SRoopa Prabhu {
382667653936SRoopa Prabhu struct vxlan_net *vn = net_generic(net, vxlan_net_id);
382767653936SRoopa Prabhu struct vxlan_dev *vxlan = netdev_priv(dev);
382867653936SRoopa Prabhu struct net_device *remote_dev = NULL;
382967653936SRoopa Prabhu struct vxlan_fdb *f = NULL;
383067653936SRoopa Prabhu bool unregister = false;
383167653936SRoopa Prabhu struct vxlan_rdst *dst;
383267653936SRoopa Prabhu int err;
383367653936SRoopa Prabhu
383467653936SRoopa Prabhu dst = &vxlan->default_dst;
383567653936SRoopa Prabhu err = vxlan_dev_configure(net, dev, conf, false, extack);
383667653936SRoopa Prabhu if (err)
383767653936SRoopa Prabhu return err;
383867653936SRoopa Prabhu
383967653936SRoopa Prabhu dev->ethtool_ops = &vxlan_ethtool_ops;
384067653936SRoopa Prabhu
384167653936SRoopa Prabhu /* create an fdb entry for a valid default destination */
384267653936SRoopa Prabhu if (!vxlan_addr_any(&dst->remote_ip)) {
384367653936SRoopa Prabhu err = vxlan_fdb_create(vxlan, all_zeros_mac,
384467653936SRoopa Prabhu &dst->remote_ip,
384567653936SRoopa Prabhu NUD_REACHABLE | NUD_PERMANENT,
384667653936SRoopa Prabhu vxlan->cfg.dst_port,
384767653936SRoopa Prabhu dst->remote_vni,
384867653936SRoopa Prabhu dst->remote_vni,
384967653936SRoopa Prabhu dst->remote_ifindex,
385067653936SRoopa Prabhu NTF_SELF, 0, &f, extack);
385167653936SRoopa Prabhu if (err)
385267653936SRoopa Prabhu return err;
385367653936SRoopa Prabhu }
385467653936SRoopa Prabhu
385567653936SRoopa Prabhu err = register_netdevice(dev);
385667653936SRoopa Prabhu if (err)
385767653936SRoopa Prabhu goto errout;
385867653936SRoopa Prabhu unregister = true;
385967653936SRoopa Prabhu
386067653936SRoopa Prabhu if (dst->remote_ifindex) {
386167653936SRoopa Prabhu remote_dev = __dev_get_by_index(net, dst->remote_ifindex);
386267653936SRoopa Prabhu if (!remote_dev) {
386367653936SRoopa Prabhu err = -ENODEV;
386467653936SRoopa Prabhu goto errout;
386567653936SRoopa Prabhu }
386667653936SRoopa Prabhu
386767653936SRoopa Prabhu err = netdev_upper_dev_link(remote_dev, dev, extack);
386867653936SRoopa Prabhu if (err)
386967653936SRoopa Prabhu goto errout;
387067653936SRoopa Prabhu }
387167653936SRoopa Prabhu
38721d997f10SHangbin Liu err = rtnl_configure_link(dev, NULL, 0, NULL);
387367653936SRoopa Prabhu if (err < 0)
387467653936SRoopa Prabhu goto unlink;
387567653936SRoopa Prabhu
387667653936SRoopa Prabhu if (f) {
387767653936SRoopa Prabhu vxlan_fdb_insert(vxlan, all_zeros_mac, dst->remote_vni, f);
387867653936SRoopa Prabhu
387967653936SRoopa Prabhu /* notify default fdb entry */
388067653936SRoopa Prabhu err = vxlan_fdb_notify(vxlan, f, first_remote_rtnl(f),
388167653936SRoopa Prabhu RTM_NEWNEIGH, true, extack);
388267653936SRoopa Prabhu if (err) {
388367653936SRoopa Prabhu vxlan_fdb_destroy(vxlan, f, false, false);
388467653936SRoopa Prabhu if (remote_dev)
388567653936SRoopa Prabhu netdev_upper_dev_unlink(remote_dev, dev);
388667653936SRoopa Prabhu goto unregister;
388767653936SRoopa Prabhu }
388867653936SRoopa Prabhu }
388967653936SRoopa Prabhu
389067653936SRoopa Prabhu list_add(&vxlan->next, &vn->vxlan_list);
389167653936SRoopa Prabhu if (remote_dev)
389267653936SRoopa Prabhu dst->remote_dev = remote_dev;
389367653936SRoopa Prabhu return 0;
389467653936SRoopa Prabhu unlink:
389567653936SRoopa Prabhu if (remote_dev)
389667653936SRoopa Prabhu netdev_upper_dev_unlink(remote_dev, dev);
389767653936SRoopa Prabhu errout:
389867653936SRoopa Prabhu /* unregister_netdevice() destroys the default FDB entry with deletion
389967653936SRoopa Prabhu * notification. But the addition notification was not sent yet, so
390067653936SRoopa Prabhu * destroy the entry by hand here.
390167653936SRoopa Prabhu */
390267653936SRoopa Prabhu if (f)
390367653936SRoopa Prabhu __vxlan_fdb_free(f);
390467653936SRoopa Prabhu unregister:
390567653936SRoopa Prabhu if (unregister)
390667653936SRoopa Prabhu unregister_netdevice(dev);
390767653936SRoopa Prabhu return err;
390867653936SRoopa Prabhu }
390967653936SRoopa Prabhu
391067653936SRoopa Prabhu /* Set/clear flags based on attribute */
vxlan_nl2flag(struct vxlan_config * conf,struct nlattr * tb[],int attrtype,unsigned long mask,bool changelink,bool changelink_supported,struct netlink_ext_ack * extack)391167653936SRoopa Prabhu static int vxlan_nl2flag(struct vxlan_config *conf, struct nlattr *tb[],
391267653936SRoopa Prabhu int attrtype, unsigned long mask, bool changelink,
391367653936SRoopa Prabhu bool changelink_supported,
391467653936SRoopa Prabhu struct netlink_ext_ack *extack)
391567653936SRoopa Prabhu {
391667653936SRoopa Prabhu unsigned long flags;
391767653936SRoopa Prabhu
391867653936SRoopa Prabhu if (!tb[attrtype])
391967653936SRoopa Prabhu return 0;
392067653936SRoopa Prabhu
392167653936SRoopa Prabhu if (changelink && !changelink_supported) {
392267653936SRoopa Prabhu vxlan_flag_attr_error(attrtype, extack);
392367653936SRoopa Prabhu return -EOPNOTSUPP;
392467653936SRoopa Prabhu }
392567653936SRoopa Prabhu
392667653936SRoopa Prabhu if (vxlan_policy[attrtype].type == NLA_FLAG)
392767653936SRoopa Prabhu flags = conf->flags | mask;
392867653936SRoopa Prabhu else if (nla_get_u8(tb[attrtype]))
392967653936SRoopa Prabhu flags = conf->flags | mask;
393067653936SRoopa Prabhu else
393167653936SRoopa Prabhu flags = conf->flags & ~mask;
393267653936SRoopa Prabhu
393367653936SRoopa Prabhu conf->flags = flags;
393467653936SRoopa Prabhu
393567653936SRoopa Prabhu return 0;
393667653936SRoopa Prabhu }
393767653936SRoopa Prabhu
vxlan_nl2conf(struct nlattr * tb[],struct nlattr * data[],struct net_device * dev,struct vxlan_config * conf,bool changelink,struct netlink_ext_ack * extack)393867653936SRoopa Prabhu static int vxlan_nl2conf(struct nlattr *tb[], struct nlattr *data[],
393967653936SRoopa Prabhu struct net_device *dev, struct vxlan_config *conf,
394067653936SRoopa Prabhu bool changelink, struct netlink_ext_ack *extack)
394167653936SRoopa Prabhu {
394267653936SRoopa Prabhu struct vxlan_dev *vxlan = netdev_priv(dev);
394367653936SRoopa Prabhu int err = 0;
394467653936SRoopa Prabhu
394567653936SRoopa Prabhu memset(conf, 0, sizeof(*conf));
394667653936SRoopa Prabhu
394767653936SRoopa Prabhu /* if changelink operation, start with old existing cfg */
394867653936SRoopa Prabhu if (changelink)
394967653936SRoopa Prabhu memcpy(conf, &vxlan->cfg, sizeof(*conf));
395067653936SRoopa Prabhu
395167653936SRoopa Prabhu if (data[IFLA_VXLAN_ID]) {
395267653936SRoopa Prabhu __be32 vni = cpu_to_be32(nla_get_u32(data[IFLA_VXLAN_ID]));
395367653936SRoopa Prabhu
395467653936SRoopa Prabhu if (changelink && (vni != conf->vni)) {
395567653936SRoopa Prabhu NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_ID], "Cannot change VNI");
395667653936SRoopa Prabhu return -EOPNOTSUPP;
395767653936SRoopa Prabhu }
395867653936SRoopa Prabhu conf->vni = cpu_to_be32(nla_get_u32(data[IFLA_VXLAN_ID]));
395967653936SRoopa Prabhu }
396067653936SRoopa Prabhu
396167653936SRoopa Prabhu if (data[IFLA_VXLAN_GROUP]) {
396267653936SRoopa Prabhu if (changelink && (conf->remote_ip.sa.sa_family != AF_INET)) {
396367653936SRoopa Prabhu NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_GROUP], "New group address family does not match old group");
396467653936SRoopa Prabhu return -EOPNOTSUPP;
396567653936SRoopa Prabhu }
396667653936SRoopa Prabhu
396767653936SRoopa Prabhu conf->remote_ip.sin.sin_addr.s_addr = nla_get_in_addr(data[IFLA_VXLAN_GROUP]);
396867653936SRoopa Prabhu conf->remote_ip.sa.sa_family = AF_INET;
396967653936SRoopa Prabhu } else if (data[IFLA_VXLAN_GROUP6]) {
397067653936SRoopa Prabhu if (!IS_ENABLED(CONFIG_IPV6)) {
397167653936SRoopa Prabhu NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_GROUP6], "IPv6 support not enabled in the kernel");
397267653936SRoopa Prabhu return -EPFNOSUPPORT;
397367653936SRoopa Prabhu }
397467653936SRoopa Prabhu
397567653936SRoopa Prabhu if (changelink && (conf->remote_ip.sa.sa_family != AF_INET6)) {
397667653936SRoopa Prabhu NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_GROUP6], "New group address family does not match old group");
397767653936SRoopa Prabhu return -EOPNOTSUPP;
397867653936SRoopa Prabhu }
397967653936SRoopa Prabhu
398067653936SRoopa Prabhu conf->remote_ip.sin6.sin6_addr = nla_get_in6_addr(data[IFLA_VXLAN_GROUP6]);
398167653936SRoopa Prabhu conf->remote_ip.sa.sa_family = AF_INET6;
398267653936SRoopa Prabhu }
398367653936SRoopa Prabhu
398467653936SRoopa Prabhu if (data[IFLA_VXLAN_LOCAL]) {
398567653936SRoopa Prabhu if (changelink && (conf->saddr.sa.sa_family != AF_INET)) {
398667653936SRoopa Prabhu NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_LOCAL], "New local address family does not match old");
398767653936SRoopa Prabhu return -EOPNOTSUPP;
398867653936SRoopa Prabhu }
398967653936SRoopa Prabhu
399067653936SRoopa Prabhu conf->saddr.sin.sin_addr.s_addr = nla_get_in_addr(data[IFLA_VXLAN_LOCAL]);
399167653936SRoopa Prabhu conf->saddr.sa.sa_family = AF_INET;
399267653936SRoopa Prabhu } else if (data[IFLA_VXLAN_LOCAL6]) {
399367653936SRoopa Prabhu if (!IS_ENABLED(CONFIG_IPV6)) {
399467653936SRoopa Prabhu NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_LOCAL6], "IPv6 support not enabled in the kernel");
399567653936SRoopa Prabhu return -EPFNOSUPPORT;
399667653936SRoopa Prabhu }
399767653936SRoopa Prabhu
399867653936SRoopa Prabhu if (changelink && (conf->saddr.sa.sa_family != AF_INET6)) {
399967653936SRoopa Prabhu NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_LOCAL6], "New local address family does not match old");
400067653936SRoopa Prabhu return -EOPNOTSUPP;
400167653936SRoopa Prabhu }
400267653936SRoopa Prabhu
400367653936SRoopa Prabhu /* TODO: respect scope id */
400467653936SRoopa Prabhu conf->saddr.sin6.sin6_addr = nla_get_in6_addr(data[IFLA_VXLAN_LOCAL6]);
400567653936SRoopa Prabhu conf->saddr.sa.sa_family = AF_INET6;
400667653936SRoopa Prabhu }
400767653936SRoopa Prabhu
400867653936SRoopa Prabhu if (data[IFLA_VXLAN_LINK])
400967653936SRoopa Prabhu conf->remote_ifindex = nla_get_u32(data[IFLA_VXLAN_LINK]);
401067653936SRoopa Prabhu
401167653936SRoopa Prabhu if (data[IFLA_VXLAN_TOS])
401267653936SRoopa Prabhu conf->tos = nla_get_u8(data[IFLA_VXLAN_TOS]);
401367653936SRoopa Prabhu
401467653936SRoopa Prabhu if (data[IFLA_VXLAN_TTL])
401567653936SRoopa Prabhu conf->ttl = nla_get_u8(data[IFLA_VXLAN_TTL]);
401667653936SRoopa Prabhu
401767653936SRoopa Prabhu if (data[IFLA_VXLAN_TTL_INHERIT]) {
401867653936SRoopa Prabhu err = vxlan_nl2flag(conf, data, IFLA_VXLAN_TTL_INHERIT,
401967653936SRoopa Prabhu VXLAN_F_TTL_INHERIT, changelink, false,
402067653936SRoopa Prabhu extack);
402167653936SRoopa Prabhu if (err)
402267653936SRoopa Prabhu return err;
402367653936SRoopa Prabhu
402467653936SRoopa Prabhu }
402567653936SRoopa Prabhu
402667653936SRoopa Prabhu if (data[IFLA_VXLAN_LABEL])
402767653936SRoopa Prabhu conf->label = nla_get_be32(data[IFLA_VXLAN_LABEL]) &
402867653936SRoopa Prabhu IPV6_FLOWLABEL_MASK;
402967653936SRoopa Prabhu
403067653936SRoopa Prabhu if (data[IFLA_VXLAN_LEARNING]) {
403167653936SRoopa Prabhu err = vxlan_nl2flag(conf, data, IFLA_VXLAN_LEARNING,
403267653936SRoopa Prabhu VXLAN_F_LEARN, changelink, true,
403367653936SRoopa Prabhu extack);
403467653936SRoopa Prabhu if (err)
403567653936SRoopa Prabhu return err;
403667653936SRoopa Prabhu } else if (!changelink) {
403767653936SRoopa Prabhu /* default to learn on a new device */
403867653936SRoopa Prabhu conf->flags |= VXLAN_F_LEARN;
403967653936SRoopa Prabhu }
404067653936SRoopa Prabhu
404167653936SRoopa Prabhu if (data[IFLA_VXLAN_AGEING])
404267653936SRoopa Prabhu conf->age_interval = nla_get_u32(data[IFLA_VXLAN_AGEING]);
404367653936SRoopa Prabhu
404467653936SRoopa Prabhu if (data[IFLA_VXLAN_PROXY]) {
404567653936SRoopa Prabhu err = vxlan_nl2flag(conf, data, IFLA_VXLAN_PROXY,
404667653936SRoopa Prabhu VXLAN_F_PROXY, changelink, false,
404767653936SRoopa Prabhu extack);
404867653936SRoopa Prabhu if (err)
404967653936SRoopa Prabhu return err;
405067653936SRoopa Prabhu }
405167653936SRoopa Prabhu
405267653936SRoopa Prabhu if (data[IFLA_VXLAN_RSC]) {
405367653936SRoopa Prabhu err = vxlan_nl2flag(conf, data, IFLA_VXLAN_RSC,
405467653936SRoopa Prabhu VXLAN_F_RSC, changelink, false,
405567653936SRoopa Prabhu extack);
405667653936SRoopa Prabhu if (err)
405767653936SRoopa Prabhu return err;
405867653936SRoopa Prabhu }
405967653936SRoopa Prabhu
406067653936SRoopa Prabhu if (data[IFLA_VXLAN_L2MISS]) {
406167653936SRoopa Prabhu err = vxlan_nl2flag(conf, data, IFLA_VXLAN_L2MISS,
406267653936SRoopa Prabhu VXLAN_F_L2MISS, changelink, false,
406367653936SRoopa Prabhu extack);
406467653936SRoopa Prabhu if (err)
406567653936SRoopa Prabhu return err;
406667653936SRoopa Prabhu }
406767653936SRoopa Prabhu
406867653936SRoopa Prabhu if (data[IFLA_VXLAN_L3MISS]) {
406967653936SRoopa Prabhu err = vxlan_nl2flag(conf, data, IFLA_VXLAN_L3MISS,
407067653936SRoopa Prabhu VXLAN_F_L3MISS, changelink, false,
407167653936SRoopa Prabhu extack);
407267653936SRoopa Prabhu if (err)
407367653936SRoopa Prabhu return err;
407467653936SRoopa Prabhu }
407567653936SRoopa Prabhu
407667653936SRoopa Prabhu if (data[IFLA_VXLAN_LIMIT]) {
407767653936SRoopa Prabhu if (changelink) {
407867653936SRoopa Prabhu NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_LIMIT],
407967653936SRoopa Prabhu "Cannot change limit");
408067653936SRoopa Prabhu return -EOPNOTSUPP;
408167653936SRoopa Prabhu }
408267653936SRoopa Prabhu conf->addrmax = nla_get_u32(data[IFLA_VXLAN_LIMIT]);
408367653936SRoopa Prabhu }
408467653936SRoopa Prabhu
408567653936SRoopa Prabhu if (data[IFLA_VXLAN_COLLECT_METADATA]) {
408667653936SRoopa Prabhu err = vxlan_nl2flag(conf, data, IFLA_VXLAN_COLLECT_METADATA,
408767653936SRoopa Prabhu VXLAN_F_COLLECT_METADATA, changelink, false,
408867653936SRoopa Prabhu extack);
408967653936SRoopa Prabhu if (err)
409067653936SRoopa Prabhu return err;
409167653936SRoopa Prabhu }
409267653936SRoopa Prabhu
409367653936SRoopa Prabhu if (data[IFLA_VXLAN_PORT_RANGE]) {
409467653936SRoopa Prabhu if (!changelink) {
409567653936SRoopa Prabhu const struct ifla_vxlan_port_range *p
409667653936SRoopa Prabhu = nla_data(data[IFLA_VXLAN_PORT_RANGE]);
409767653936SRoopa Prabhu conf->port_min = ntohs(p->low);
409867653936SRoopa Prabhu conf->port_max = ntohs(p->high);
409967653936SRoopa Prabhu } else {
410067653936SRoopa Prabhu NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_PORT_RANGE],
410167653936SRoopa Prabhu "Cannot change port range");
410267653936SRoopa Prabhu return -EOPNOTSUPP;
410367653936SRoopa Prabhu }
410467653936SRoopa Prabhu }
410567653936SRoopa Prabhu
410667653936SRoopa Prabhu if (data[IFLA_VXLAN_PORT]) {
410767653936SRoopa Prabhu if (changelink) {
410867653936SRoopa Prabhu NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_PORT],
410967653936SRoopa Prabhu "Cannot change port");
411067653936SRoopa Prabhu return -EOPNOTSUPP;
411167653936SRoopa Prabhu }
411267653936SRoopa Prabhu conf->dst_port = nla_get_be16(data[IFLA_VXLAN_PORT]);
411367653936SRoopa Prabhu }
411467653936SRoopa Prabhu
411567653936SRoopa Prabhu if (data[IFLA_VXLAN_UDP_CSUM]) {
411667653936SRoopa Prabhu if (changelink) {
411767653936SRoopa Prabhu NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_UDP_CSUM],
411867653936SRoopa Prabhu "Cannot change UDP_CSUM flag");
411967653936SRoopa Prabhu return -EOPNOTSUPP;
412067653936SRoopa Prabhu }
412167653936SRoopa Prabhu if (!nla_get_u8(data[IFLA_VXLAN_UDP_CSUM]))
412267653936SRoopa Prabhu conf->flags |= VXLAN_F_UDP_ZERO_CSUM_TX;
412367653936SRoopa Prabhu }
412467653936SRoopa Prabhu
412569474a8aSVladimir Nikishkin if (data[IFLA_VXLAN_LOCALBYPASS]) {
412669474a8aSVladimir Nikishkin err = vxlan_nl2flag(conf, data, IFLA_VXLAN_LOCALBYPASS,
412769474a8aSVladimir Nikishkin VXLAN_F_LOCALBYPASS, changelink,
412869474a8aSVladimir Nikishkin true, extack);
412969474a8aSVladimir Nikishkin if (err)
413069474a8aSVladimir Nikishkin return err;
413169474a8aSVladimir Nikishkin } else if (!changelink) {
413269474a8aSVladimir Nikishkin /* default to local bypass on a new device */
413369474a8aSVladimir Nikishkin conf->flags |= VXLAN_F_LOCALBYPASS;
413469474a8aSVladimir Nikishkin }
413569474a8aSVladimir Nikishkin
413667653936SRoopa Prabhu if (data[IFLA_VXLAN_UDP_ZERO_CSUM6_TX]) {
413767653936SRoopa Prabhu err = vxlan_nl2flag(conf, data, IFLA_VXLAN_UDP_ZERO_CSUM6_TX,
413867653936SRoopa Prabhu VXLAN_F_UDP_ZERO_CSUM6_TX, changelink,
413967653936SRoopa Prabhu false, extack);
414067653936SRoopa Prabhu if (err)
414167653936SRoopa Prabhu return err;
414267653936SRoopa Prabhu }
414367653936SRoopa Prabhu
414467653936SRoopa Prabhu if (data[IFLA_VXLAN_UDP_ZERO_CSUM6_RX]) {
414567653936SRoopa Prabhu err = vxlan_nl2flag(conf, data, IFLA_VXLAN_UDP_ZERO_CSUM6_RX,
414667653936SRoopa Prabhu VXLAN_F_UDP_ZERO_CSUM6_RX, changelink,
414767653936SRoopa Prabhu false, extack);
414867653936SRoopa Prabhu if (err)
414967653936SRoopa Prabhu return err;
415067653936SRoopa Prabhu }
415167653936SRoopa Prabhu
415267653936SRoopa Prabhu if (data[IFLA_VXLAN_REMCSUM_TX]) {
415367653936SRoopa Prabhu err = vxlan_nl2flag(conf, data, IFLA_VXLAN_REMCSUM_TX,
415467653936SRoopa Prabhu VXLAN_F_REMCSUM_TX, changelink, false,
415567653936SRoopa Prabhu extack);
415667653936SRoopa Prabhu if (err)
415767653936SRoopa Prabhu return err;
415867653936SRoopa Prabhu }
415967653936SRoopa Prabhu
416067653936SRoopa Prabhu if (data[IFLA_VXLAN_REMCSUM_RX]) {
416167653936SRoopa Prabhu err = vxlan_nl2flag(conf, data, IFLA_VXLAN_REMCSUM_RX,
416267653936SRoopa Prabhu VXLAN_F_REMCSUM_RX, changelink, false,
416367653936SRoopa Prabhu extack);
416467653936SRoopa Prabhu if (err)
416567653936SRoopa Prabhu return err;
416667653936SRoopa Prabhu }
416767653936SRoopa Prabhu
416867653936SRoopa Prabhu if (data[IFLA_VXLAN_GBP]) {
416967653936SRoopa Prabhu err = vxlan_nl2flag(conf, data, IFLA_VXLAN_GBP,
417067653936SRoopa Prabhu VXLAN_F_GBP, changelink, false, extack);
417167653936SRoopa Prabhu if (err)
417267653936SRoopa Prabhu return err;
417367653936SRoopa Prabhu }
417467653936SRoopa Prabhu
417567653936SRoopa Prabhu if (data[IFLA_VXLAN_GPE]) {
417667653936SRoopa Prabhu err = vxlan_nl2flag(conf, data, IFLA_VXLAN_GPE,
417767653936SRoopa Prabhu VXLAN_F_GPE, changelink, false,
417867653936SRoopa Prabhu extack);
417967653936SRoopa Prabhu if (err)
418067653936SRoopa Prabhu return err;
418167653936SRoopa Prabhu }
418267653936SRoopa Prabhu
418367653936SRoopa Prabhu if (data[IFLA_VXLAN_REMCSUM_NOPARTIAL]) {
418467653936SRoopa Prabhu err = vxlan_nl2flag(conf, data, IFLA_VXLAN_REMCSUM_NOPARTIAL,
418567653936SRoopa Prabhu VXLAN_F_REMCSUM_NOPARTIAL, changelink,
418667653936SRoopa Prabhu false, extack);
418767653936SRoopa Prabhu if (err)
418867653936SRoopa Prabhu return err;
418967653936SRoopa Prabhu }
419067653936SRoopa Prabhu
419167653936SRoopa Prabhu if (tb[IFLA_MTU]) {
419267653936SRoopa Prabhu if (changelink) {
419367653936SRoopa Prabhu NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_MTU],
419467653936SRoopa Prabhu "Cannot change mtu");
419567653936SRoopa Prabhu return -EOPNOTSUPP;
419667653936SRoopa Prabhu }
419767653936SRoopa Prabhu conf->mtu = nla_get_u32(tb[IFLA_MTU]);
419867653936SRoopa Prabhu }
419967653936SRoopa Prabhu
420067653936SRoopa Prabhu if (data[IFLA_VXLAN_DF])
420167653936SRoopa Prabhu conf->df = nla_get_u8(data[IFLA_VXLAN_DF]);
420267653936SRoopa Prabhu
4203f9c4bb0bSRoopa Prabhu if (data[IFLA_VXLAN_VNIFILTER]) {
4204f9c4bb0bSRoopa Prabhu err = vxlan_nl2flag(conf, data, IFLA_VXLAN_VNIFILTER,
4205f9c4bb0bSRoopa Prabhu VXLAN_F_VNIFILTER, changelink, false,
4206f9c4bb0bSRoopa Prabhu extack);
4207f9c4bb0bSRoopa Prabhu if (err)
4208f9c4bb0bSRoopa Prabhu return err;
4209f9c4bb0bSRoopa Prabhu
4210f9c4bb0bSRoopa Prabhu if ((conf->flags & VXLAN_F_VNIFILTER) &&
4211f9c4bb0bSRoopa Prabhu !(conf->flags & VXLAN_F_COLLECT_METADATA)) {
4212f9c4bb0bSRoopa Prabhu NL_SET_ERR_MSG_ATTR(extack, data[IFLA_VXLAN_VNIFILTER],
4213f9c4bb0bSRoopa Prabhu "vxlan vnifilter only valid in collect metadata mode");
4214f9c4bb0bSRoopa Prabhu return -EINVAL;
4215f9c4bb0bSRoopa Prabhu }
4216f9c4bb0bSRoopa Prabhu }
4217f9c4bb0bSRoopa Prabhu
421867653936SRoopa Prabhu return 0;
421967653936SRoopa Prabhu }
422067653936SRoopa Prabhu
vxlan_newlink(struct net * src_net,struct net_device * dev,struct nlattr * tb[],struct nlattr * data[],struct netlink_ext_ack * extack)422167653936SRoopa Prabhu static int vxlan_newlink(struct net *src_net, struct net_device *dev,
422267653936SRoopa Prabhu struct nlattr *tb[], struct nlattr *data[],
422367653936SRoopa Prabhu struct netlink_ext_ack *extack)
422467653936SRoopa Prabhu {
422567653936SRoopa Prabhu struct vxlan_config conf;
422667653936SRoopa Prabhu int err;
422767653936SRoopa Prabhu
422867653936SRoopa Prabhu err = vxlan_nl2conf(tb, data, dev, &conf, false, extack);
422967653936SRoopa Prabhu if (err)
423067653936SRoopa Prabhu return err;
423167653936SRoopa Prabhu
423267653936SRoopa Prabhu return __vxlan_dev_create(src_net, dev, &conf, extack);
423367653936SRoopa Prabhu }
423467653936SRoopa Prabhu
vxlan_changelink(struct net_device * dev,struct nlattr * tb[],struct nlattr * data[],struct netlink_ext_ack * extack)423567653936SRoopa Prabhu static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
423667653936SRoopa Prabhu struct nlattr *data[],
423767653936SRoopa Prabhu struct netlink_ext_ack *extack)
423867653936SRoopa Prabhu {
423967653936SRoopa Prabhu struct vxlan_dev *vxlan = netdev_priv(dev);
424067653936SRoopa Prabhu struct net_device *lowerdev;
424167653936SRoopa Prabhu struct vxlan_config conf;
424267653936SRoopa Prabhu struct vxlan_rdst *dst;
424367653936SRoopa Prabhu int err;
424467653936SRoopa Prabhu
424567653936SRoopa Prabhu dst = &vxlan->default_dst;
424667653936SRoopa Prabhu err = vxlan_nl2conf(tb, data, dev, &conf, true, extack);
424767653936SRoopa Prabhu if (err)
424867653936SRoopa Prabhu return err;
424967653936SRoopa Prabhu
425067653936SRoopa Prabhu err = vxlan_config_validate(vxlan->net, &conf, &lowerdev,
425167653936SRoopa Prabhu vxlan, extack);
425267653936SRoopa Prabhu if (err)
425367653936SRoopa Prabhu return err;
425467653936SRoopa Prabhu
425567653936SRoopa Prabhu if (dst->remote_dev == lowerdev)
425667653936SRoopa Prabhu lowerdev = NULL;
425767653936SRoopa Prabhu
425867653936SRoopa Prabhu err = netdev_adjacent_change_prepare(dst->remote_dev, lowerdev, dev,
425967653936SRoopa Prabhu extack);
426067653936SRoopa Prabhu if (err)
426167653936SRoopa Prabhu return err;
426267653936SRoopa Prabhu
426367653936SRoopa Prabhu /* handle default dst entry */
426467653936SRoopa Prabhu if (!vxlan_addr_equal(&conf.remote_ip, &dst->remote_ip)) {
426567653936SRoopa Prabhu u32 hash_index = fdb_head_index(vxlan, all_zeros_mac, conf.vni);
426667653936SRoopa Prabhu
426767653936SRoopa Prabhu spin_lock_bh(&vxlan->hash_lock[hash_index]);
426867653936SRoopa Prabhu if (!vxlan_addr_any(&conf.remote_ip)) {
426967653936SRoopa Prabhu err = vxlan_fdb_update(vxlan, all_zeros_mac,
427067653936SRoopa Prabhu &conf.remote_ip,
427167653936SRoopa Prabhu NUD_REACHABLE | NUD_PERMANENT,
427267653936SRoopa Prabhu NLM_F_APPEND | NLM_F_CREATE,
427367653936SRoopa Prabhu vxlan->cfg.dst_port,
427467653936SRoopa Prabhu conf.vni, conf.vni,
427567653936SRoopa Prabhu conf.remote_ifindex,
427667653936SRoopa Prabhu NTF_SELF, 0, true, extack);
427767653936SRoopa Prabhu if (err) {
427867653936SRoopa Prabhu spin_unlock_bh(&vxlan->hash_lock[hash_index]);
427967653936SRoopa Prabhu netdev_adjacent_change_abort(dst->remote_dev,
428067653936SRoopa Prabhu lowerdev, dev);
428167653936SRoopa Prabhu return err;
428267653936SRoopa Prabhu }
428367653936SRoopa Prabhu }
428467653936SRoopa Prabhu if (!vxlan_addr_any(&dst->remote_ip))
428567653936SRoopa Prabhu __vxlan_fdb_delete(vxlan, all_zeros_mac,
428667653936SRoopa Prabhu dst->remote_ip,
428767653936SRoopa Prabhu vxlan->cfg.dst_port,
428867653936SRoopa Prabhu dst->remote_vni,
428967653936SRoopa Prabhu dst->remote_vni,
429067653936SRoopa Prabhu dst->remote_ifindex,
429167653936SRoopa Prabhu true);
429267653936SRoopa Prabhu spin_unlock_bh(&vxlan->hash_lock[hash_index]);
4293f9c4bb0bSRoopa Prabhu
4294f9c4bb0bSRoopa Prabhu /* If vni filtering device, also update fdb entries of
4295f9c4bb0bSRoopa Prabhu * all vnis that were using default remote ip
4296f9c4bb0bSRoopa Prabhu */
4297f9c4bb0bSRoopa Prabhu if (vxlan->cfg.flags & VXLAN_F_VNIFILTER) {
4298f9c4bb0bSRoopa Prabhu err = vxlan_vnilist_update_group(vxlan, &dst->remote_ip,
4299f9c4bb0bSRoopa Prabhu &conf.remote_ip, extack);
4300f9c4bb0bSRoopa Prabhu if (err) {
4301f9c4bb0bSRoopa Prabhu netdev_adjacent_change_abort(dst->remote_dev,
4302f9c4bb0bSRoopa Prabhu lowerdev, dev);
4303f9c4bb0bSRoopa Prabhu return err;
4304f9c4bb0bSRoopa Prabhu }
4305f9c4bb0bSRoopa Prabhu }
430667653936SRoopa Prabhu }
430767653936SRoopa Prabhu
430867653936SRoopa Prabhu if (conf.age_interval != vxlan->cfg.age_interval)
430967653936SRoopa Prabhu mod_timer(&vxlan->age_timer, jiffies);
431067653936SRoopa Prabhu
431167653936SRoopa Prabhu netdev_adjacent_change_commit(dst->remote_dev, lowerdev, dev);
431267653936SRoopa Prabhu if (lowerdev && lowerdev != dst->remote_dev)
431367653936SRoopa Prabhu dst->remote_dev = lowerdev;
431467653936SRoopa Prabhu vxlan_config_apply(dev, &conf, lowerdev, vxlan->net, true);
431567653936SRoopa Prabhu return 0;
431667653936SRoopa Prabhu }
431767653936SRoopa Prabhu
vxlan_dellink(struct net_device * dev,struct list_head * head)431867653936SRoopa Prabhu static void vxlan_dellink(struct net_device *dev, struct list_head *head)
431967653936SRoopa Prabhu {
432067653936SRoopa Prabhu struct vxlan_dev *vxlan = netdev_priv(dev);
432167653936SRoopa Prabhu
432267653936SRoopa Prabhu vxlan_flush(vxlan, true);
432367653936SRoopa Prabhu
432467653936SRoopa Prabhu list_del(&vxlan->next);
432567653936SRoopa Prabhu unregister_netdevice_queue(dev, head);
432667653936SRoopa Prabhu if (vxlan->default_dst.remote_dev)
432767653936SRoopa Prabhu netdev_upper_dev_unlink(vxlan->default_dst.remote_dev, dev);
432867653936SRoopa Prabhu }
432967653936SRoopa Prabhu
vxlan_get_size(const struct net_device * dev)433067653936SRoopa Prabhu static size_t vxlan_get_size(const struct net_device *dev)
433167653936SRoopa Prabhu {
433267653936SRoopa Prabhu
433367653936SRoopa Prabhu return nla_total_size(sizeof(__u32)) + /* IFLA_VXLAN_ID */
433467653936SRoopa Prabhu nla_total_size(sizeof(struct in6_addr)) + /* IFLA_VXLAN_GROUP{6} */
433567653936SRoopa Prabhu nla_total_size(sizeof(__u32)) + /* IFLA_VXLAN_LINK */
433667653936SRoopa Prabhu nla_total_size(sizeof(struct in6_addr)) + /* IFLA_VXLAN_LOCAL{6} */
433767653936SRoopa Prabhu nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_TTL */
433867653936SRoopa Prabhu nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_TTL_INHERIT */
433967653936SRoopa Prabhu nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_TOS */
434067653936SRoopa Prabhu nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_DF */
434167653936SRoopa Prabhu nla_total_size(sizeof(__be32)) + /* IFLA_VXLAN_LABEL */
434267653936SRoopa Prabhu nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_LEARNING */
434367653936SRoopa Prabhu nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_PROXY */
434467653936SRoopa Prabhu nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_RSC */
434567653936SRoopa Prabhu nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_L2MISS */
434667653936SRoopa Prabhu nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_L3MISS */
434767653936SRoopa Prabhu nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_COLLECT_METADATA */
434867653936SRoopa Prabhu nla_total_size(sizeof(__u32)) + /* IFLA_VXLAN_AGEING */
434967653936SRoopa Prabhu nla_total_size(sizeof(__u32)) + /* IFLA_VXLAN_LIMIT */
435067653936SRoopa Prabhu nla_total_size(sizeof(struct ifla_vxlan_port_range)) +
435167653936SRoopa Prabhu nla_total_size(sizeof(__be16)) + /* IFLA_VXLAN_PORT */
435267653936SRoopa Prabhu nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_UDP_CSUM */
435367653936SRoopa Prabhu nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_UDP_ZERO_CSUM6_TX */
435467653936SRoopa Prabhu nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_UDP_ZERO_CSUM6_RX */
435567653936SRoopa Prabhu nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_REMCSUM_TX */
435667653936SRoopa Prabhu nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_REMCSUM_RX */
435769474a8aSVladimir Nikishkin nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_LOCALBYPASS */
43584e4b1798SBenjamin Poirier nla_total_size(0) + /* IFLA_VXLAN_GBP */
43594e4b1798SBenjamin Poirier nla_total_size(0) + /* IFLA_VXLAN_GPE */
43604e4b1798SBenjamin Poirier nla_total_size(0) + /* IFLA_VXLAN_REMCSUM_NOPARTIAL */
43614e4b1798SBenjamin Poirier nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_VNIFILTER */
436267653936SRoopa Prabhu 0;
436367653936SRoopa Prabhu }
436467653936SRoopa Prabhu
vxlan_fill_info(struct sk_buff * skb,const struct net_device * dev)436567653936SRoopa Prabhu static int vxlan_fill_info(struct sk_buff *skb, const struct net_device *dev)
436667653936SRoopa Prabhu {
436767653936SRoopa Prabhu const struct vxlan_dev *vxlan = netdev_priv(dev);
436867653936SRoopa Prabhu const struct vxlan_rdst *dst = &vxlan->default_dst;
436967653936SRoopa Prabhu struct ifla_vxlan_port_range ports = {
437067653936SRoopa Prabhu .low = htons(vxlan->cfg.port_min),
437167653936SRoopa Prabhu .high = htons(vxlan->cfg.port_max),
437267653936SRoopa Prabhu };
437367653936SRoopa Prabhu
437467653936SRoopa Prabhu if (nla_put_u32(skb, IFLA_VXLAN_ID, be32_to_cpu(dst->remote_vni)))
437567653936SRoopa Prabhu goto nla_put_failure;
437667653936SRoopa Prabhu
437767653936SRoopa Prabhu if (!vxlan_addr_any(&dst->remote_ip)) {
437867653936SRoopa Prabhu if (dst->remote_ip.sa.sa_family == AF_INET) {
437967653936SRoopa Prabhu if (nla_put_in_addr(skb, IFLA_VXLAN_GROUP,
438067653936SRoopa Prabhu dst->remote_ip.sin.sin_addr.s_addr))
438167653936SRoopa Prabhu goto nla_put_failure;
438267653936SRoopa Prabhu #if IS_ENABLED(CONFIG_IPV6)
438367653936SRoopa Prabhu } else {
438467653936SRoopa Prabhu if (nla_put_in6_addr(skb, IFLA_VXLAN_GROUP6,
438567653936SRoopa Prabhu &dst->remote_ip.sin6.sin6_addr))
438667653936SRoopa Prabhu goto nla_put_failure;
438767653936SRoopa Prabhu #endif
438867653936SRoopa Prabhu }
438967653936SRoopa Prabhu }
439067653936SRoopa Prabhu
439167653936SRoopa Prabhu if (dst->remote_ifindex && nla_put_u32(skb, IFLA_VXLAN_LINK, dst->remote_ifindex))
439267653936SRoopa Prabhu goto nla_put_failure;
439367653936SRoopa Prabhu
439467653936SRoopa Prabhu if (!vxlan_addr_any(&vxlan->cfg.saddr)) {
439567653936SRoopa Prabhu if (vxlan->cfg.saddr.sa.sa_family == AF_INET) {
439667653936SRoopa Prabhu if (nla_put_in_addr(skb, IFLA_VXLAN_LOCAL,
439767653936SRoopa Prabhu vxlan->cfg.saddr.sin.sin_addr.s_addr))
439867653936SRoopa Prabhu goto nla_put_failure;
439967653936SRoopa Prabhu #if IS_ENABLED(CONFIG_IPV6)
440067653936SRoopa Prabhu } else {
440167653936SRoopa Prabhu if (nla_put_in6_addr(skb, IFLA_VXLAN_LOCAL6,
440267653936SRoopa Prabhu &vxlan->cfg.saddr.sin6.sin6_addr))
440367653936SRoopa Prabhu goto nla_put_failure;
440467653936SRoopa Prabhu #endif
440567653936SRoopa Prabhu }
440667653936SRoopa Prabhu }
440767653936SRoopa Prabhu
440867653936SRoopa Prabhu if (nla_put_u8(skb, IFLA_VXLAN_TTL, vxlan->cfg.ttl) ||
440967653936SRoopa Prabhu nla_put_u8(skb, IFLA_VXLAN_TTL_INHERIT,
441067653936SRoopa Prabhu !!(vxlan->cfg.flags & VXLAN_F_TTL_INHERIT)) ||
441167653936SRoopa Prabhu nla_put_u8(skb, IFLA_VXLAN_TOS, vxlan->cfg.tos) ||
441267653936SRoopa Prabhu nla_put_u8(skb, IFLA_VXLAN_DF, vxlan->cfg.df) ||
441367653936SRoopa Prabhu nla_put_be32(skb, IFLA_VXLAN_LABEL, vxlan->cfg.label) ||
441467653936SRoopa Prabhu nla_put_u8(skb, IFLA_VXLAN_LEARNING,
441567653936SRoopa Prabhu !!(vxlan->cfg.flags & VXLAN_F_LEARN)) ||
441667653936SRoopa Prabhu nla_put_u8(skb, IFLA_VXLAN_PROXY,
441767653936SRoopa Prabhu !!(vxlan->cfg.flags & VXLAN_F_PROXY)) ||
441867653936SRoopa Prabhu nla_put_u8(skb, IFLA_VXLAN_RSC,
441967653936SRoopa Prabhu !!(vxlan->cfg.flags & VXLAN_F_RSC)) ||
442067653936SRoopa Prabhu nla_put_u8(skb, IFLA_VXLAN_L2MISS,
442167653936SRoopa Prabhu !!(vxlan->cfg.flags & VXLAN_F_L2MISS)) ||
442267653936SRoopa Prabhu nla_put_u8(skb, IFLA_VXLAN_L3MISS,
442367653936SRoopa Prabhu !!(vxlan->cfg.flags & VXLAN_F_L3MISS)) ||
442467653936SRoopa Prabhu nla_put_u8(skb, IFLA_VXLAN_COLLECT_METADATA,
442567653936SRoopa Prabhu !!(vxlan->cfg.flags & VXLAN_F_COLLECT_METADATA)) ||
442667653936SRoopa Prabhu nla_put_u32(skb, IFLA_VXLAN_AGEING, vxlan->cfg.age_interval) ||
442767653936SRoopa Prabhu nla_put_u32(skb, IFLA_VXLAN_LIMIT, vxlan->cfg.addrmax) ||
442867653936SRoopa Prabhu nla_put_be16(skb, IFLA_VXLAN_PORT, vxlan->cfg.dst_port) ||
442967653936SRoopa Prabhu nla_put_u8(skb, IFLA_VXLAN_UDP_CSUM,
443067653936SRoopa Prabhu !(vxlan->cfg.flags & VXLAN_F_UDP_ZERO_CSUM_TX)) ||
443167653936SRoopa Prabhu nla_put_u8(skb, IFLA_VXLAN_UDP_ZERO_CSUM6_TX,
443267653936SRoopa Prabhu !!(vxlan->cfg.flags & VXLAN_F_UDP_ZERO_CSUM6_TX)) ||
443367653936SRoopa Prabhu nla_put_u8(skb, IFLA_VXLAN_UDP_ZERO_CSUM6_RX,
443467653936SRoopa Prabhu !!(vxlan->cfg.flags & VXLAN_F_UDP_ZERO_CSUM6_RX)) ||
443567653936SRoopa Prabhu nla_put_u8(skb, IFLA_VXLAN_REMCSUM_TX,
443667653936SRoopa Prabhu !!(vxlan->cfg.flags & VXLAN_F_REMCSUM_TX)) ||
443767653936SRoopa Prabhu nla_put_u8(skb, IFLA_VXLAN_REMCSUM_RX,
443869474a8aSVladimir Nikishkin !!(vxlan->cfg.flags & VXLAN_F_REMCSUM_RX)) ||
443969474a8aSVladimir Nikishkin nla_put_u8(skb, IFLA_VXLAN_LOCALBYPASS,
444069474a8aSVladimir Nikishkin !!(vxlan->cfg.flags & VXLAN_F_LOCALBYPASS)))
444167653936SRoopa Prabhu goto nla_put_failure;
444267653936SRoopa Prabhu
444367653936SRoopa Prabhu if (nla_put(skb, IFLA_VXLAN_PORT_RANGE, sizeof(ports), &ports))
444467653936SRoopa Prabhu goto nla_put_failure;
444567653936SRoopa Prabhu
444667653936SRoopa Prabhu if (vxlan->cfg.flags & VXLAN_F_GBP &&
444767653936SRoopa Prabhu nla_put_flag(skb, IFLA_VXLAN_GBP))
444867653936SRoopa Prabhu goto nla_put_failure;
444967653936SRoopa Prabhu
445067653936SRoopa Prabhu if (vxlan->cfg.flags & VXLAN_F_GPE &&
445167653936SRoopa Prabhu nla_put_flag(skb, IFLA_VXLAN_GPE))
445267653936SRoopa Prabhu goto nla_put_failure;
445367653936SRoopa Prabhu
445467653936SRoopa Prabhu if (vxlan->cfg.flags & VXLAN_F_REMCSUM_NOPARTIAL &&
445567653936SRoopa Prabhu nla_put_flag(skb, IFLA_VXLAN_REMCSUM_NOPARTIAL))
445667653936SRoopa Prabhu goto nla_put_failure;
445767653936SRoopa Prabhu
4458f9c4bb0bSRoopa Prabhu if (vxlan->cfg.flags & VXLAN_F_VNIFILTER &&
4459f9c4bb0bSRoopa Prabhu nla_put_u8(skb, IFLA_VXLAN_VNIFILTER,
4460f9c4bb0bSRoopa Prabhu !!(vxlan->cfg.flags & VXLAN_F_VNIFILTER)))
4461f9c4bb0bSRoopa Prabhu goto nla_put_failure;
4462f9c4bb0bSRoopa Prabhu
446367653936SRoopa Prabhu return 0;
446467653936SRoopa Prabhu
446567653936SRoopa Prabhu nla_put_failure:
446667653936SRoopa Prabhu return -EMSGSIZE;
446767653936SRoopa Prabhu }
446867653936SRoopa Prabhu
vxlan_get_link_net(const struct net_device * dev)446967653936SRoopa Prabhu static struct net *vxlan_get_link_net(const struct net_device *dev)
447067653936SRoopa Prabhu {
447167653936SRoopa Prabhu struct vxlan_dev *vxlan = netdev_priv(dev);
447267653936SRoopa Prabhu
447367653936SRoopa Prabhu return vxlan->net;
447467653936SRoopa Prabhu }
447567653936SRoopa Prabhu
447667653936SRoopa Prabhu static struct rtnl_link_ops vxlan_link_ops __read_mostly = {
447767653936SRoopa Prabhu .kind = "vxlan",
447867653936SRoopa Prabhu .maxtype = IFLA_VXLAN_MAX,
447967653936SRoopa Prabhu .policy = vxlan_policy,
448067653936SRoopa Prabhu .priv_size = sizeof(struct vxlan_dev),
448167653936SRoopa Prabhu .setup = vxlan_setup,
448267653936SRoopa Prabhu .validate = vxlan_validate,
448367653936SRoopa Prabhu .newlink = vxlan_newlink,
448467653936SRoopa Prabhu .changelink = vxlan_changelink,
448567653936SRoopa Prabhu .dellink = vxlan_dellink,
448667653936SRoopa Prabhu .get_size = vxlan_get_size,
448767653936SRoopa Prabhu .fill_info = vxlan_fill_info,
448867653936SRoopa Prabhu .get_link_net = vxlan_get_link_net,
448967653936SRoopa Prabhu };
449067653936SRoopa Prabhu
vxlan_dev_create(struct net * net,const char * name,u8 name_assign_type,struct vxlan_config * conf)449167653936SRoopa Prabhu struct net_device *vxlan_dev_create(struct net *net, const char *name,
449267653936SRoopa Prabhu u8 name_assign_type,
449367653936SRoopa Prabhu struct vxlan_config *conf)
449467653936SRoopa Prabhu {
449567653936SRoopa Prabhu struct nlattr *tb[IFLA_MAX + 1];
449667653936SRoopa Prabhu struct net_device *dev;
449767653936SRoopa Prabhu int err;
449867653936SRoopa Prabhu
449967653936SRoopa Prabhu memset(&tb, 0, sizeof(tb));
450067653936SRoopa Prabhu
450167653936SRoopa Prabhu dev = rtnl_create_link(net, name, name_assign_type,
450267653936SRoopa Prabhu &vxlan_link_ops, tb, NULL);
450367653936SRoopa Prabhu if (IS_ERR(dev))
450467653936SRoopa Prabhu return dev;
450567653936SRoopa Prabhu
450667653936SRoopa Prabhu err = __vxlan_dev_create(net, dev, conf, NULL);
450767653936SRoopa Prabhu if (err < 0) {
450867653936SRoopa Prabhu free_netdev(dev);
450967653936SRoopa Prabhu return ERR_PTR(err);
451067653936SRoopa Prabhu }
451167653936SRoopa Prabhu
45121d997f10SHangbin Liu err = rtnl_configure_link(dev, NULL, 0, NULL);
451367653936SRoopa Prabhu if (err < 0) {
451467653936SRoopa Prabhu LIST_HEAD(list_kill);
451567653936SRoopa Prabhu
451667653936SRoopa Prabhu vxlan_dellink(dev, &list_kill);
451767653936SRoopa Prabhu unregister_netdevice_many(&list_kill);
451867653936SRoopa Prabhu return ERR_PTR(err);
451967653936SRoopa Prabhu }
452067653936SRoopa Prabhu
452167653936SRoopa Prabhu return dev;
452267653936SRoopa Prabhu }
452367653936SRoopa Prabhu EXPORT_SYMBOL_GPL(vxlan_dev_create);
452467653936SRoopa Prabhu
vxlan_handle_lowerdev_unregister(struct vxlan_net * vn,struct net_device * dev)452567653936SRoopa Prabhu static void vxlan_handle_lowerdev_unregister(struct vxlan_net *vn,
452667653936SRoopa Prabhu struct net_device *dev)
452767653936SRoopa Prabhu {
452867653936SRoopa Prabhu struct vxlan_dev *vxlan, *next;
452967653936SRoopa Prabhu LIST_HEAD(list_kill);
453067653936SRoopa Prabhu
453167653936SRoopa Prabhu list_for_each_entry_safe(vxlan, next, &vn->vxlan_list, next) {
453267653936SRoopa Prabhu struct vxlan_rdst *dst = &vxlan->default_dst;
453367653936SRoopa Prabhu
453467653936SRoopa Prabhu /* In case we created vxlan device with carrier
453567653936SRoopa Prabhu * and we loose the carrier due to module unload
453667653936SRoopa Prabhu * we also need to remove vxlan device. In other
453767653936SRoopa Prabhu * cases, it's not necessary and remote_ifindex
453867653936SRoopa Prabhu * is 0 here, so no matches.
453967653936SRoopa Prabhu */
454067653936SRoopa Prabhu if (dst->remote_ifindex == dev->ifindex)
454167653936SRoopa Prabhu vxlan_dellink(vxlan->dev, &list_kill);
454267653936SRoopa Prabhu }
454367653936SRoopa Prabhu
454467653936SRoopa Prabhu unregister_netdevice_many(&list_kill);
454567653936SRoopa Prabhu }
454667653936SRoopa Prabhu
vxlan_netdevice_event(struct notifier_block * unused,unsigned long event,void * ptr)454767653936SRoopa Prabhu static int vxlan_netdevice_event(struct notifier_block *unused,
454867653936SRoopa Prabhu unsigned long event, void *ptr)
454967653936SRoopa Prabhu {
455067653936SRoopa Prabhu struct net_device *dev = netdev_notifier_info_to_dev(ptr);
455167653936SRoopa Prabhu struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id);
455267653936SRoopa Prabhu
455367653936SRoopa Prabhu if (event == NETDEV_UNREGISTER)
455467653936SRoopa Prabhu vxlan_handle_lowerdev_unregister(vn, dev);
455567653936SRoopa Prabhu else if (event == NETDEV_UDP_TUNNEL_PUSH_INFO)
455667653936SRoopa Prabhu vxlan_offload_rx_ports(dev, true);
455767653936SRoopa Prabhu else if (event == NETDEV_UDP_TUNNEL_DROP_INFO)
455867653936SRoopa Prabhu vxlan_offload_rx_ports(dev, false);
455967653936SRoopa Prabhu
456067653936SRoopa Prabhu return NOTIFY_DONE;
456167653936SRoopa Prabhu }
456267653936SRoopa Prabhu
456367653936SRoopa Prabhu static struct notifier_block vxlan_notifier_block __read_mostly = {
456467653936SRoopa Prabhu .notifier_call = vxlan_netdevice_event,
456567653936SRoopa Prabhu };
456667653936SRoopa Prabhu
456767653936SRoopa Prabhu static void
vxlan_fdb_offloaded_set(struct net_device * dev,struct switchdev_notifier_vxlan_fdb_info * fdb_info)456867653936SRoopa Prabhu vxlan_fdb_offloaded_set(struct net_device *dev,
456967653936SRoopa Prabhu struct switchdev_notifier_vxlan_fdb_info *fdb_info)
457067653936SRoopa Prabhu {
457167653936SRoopa Prabhu struct vxlan_dev *vxlan = netdev_priv(dev);
457267653936SRoopa Prabhu struct vxlan_rdst *rdst;
457367653936SRoopa Prabhu struct vxlan_fdb *f;
457467653936SRoopa Prabhu u32 hash_index;
457567653936SRoopa Prabhu
457667653936SRoopa Prabhu hash_index = fdb_head_index(vxlan, fdb_info->eth_addr, fdb_info->vni);
457767653936SRoopa Prabhu
457867653936SRoopa Prabhu spin_lock_bh(&vxlan->hash_lock[hash_index]);
457967653936SRoopa Prabhu
458067653936SRoopa Prabhu f = vxlan_find_mac(vxlan, fdb_info->eth_addr, fdb_info->vni);
458167653936SRoopa Prabhu if (!f)
458267653936SRoopa Prabhu goto out;
458367653936SRoopa Prabhu
458467653936SRoopa Prabhu rdst = vxlan_fdb_find_rdst(f, &fdb_info->remote_ip,
458567653936SRoopa Prabhu fdb_info->remote_port,
458667653936SRoopa Prabhu fdb_info->remote_vni,
458767653936SRoopa Prabhu fdb_info->remote_ifindex);
458867653936SRoopa Prabhu if (!rdst)
458967653936SRoopa Prabhu goto out;
459067653936SRoopa Prabhu
459167653936SRoopa Prabhu rdst->offloaded = fdb_info->offloaded;
459267653936SRoopa Prabhu
459367653936SRoopa Prabhu out:
459467653936SRoopa Prabhu spin_unlock_bh(&vxlan->hash_lock[hash_index]);
459567653936SRoopa Prabhu }
459667653936SRoopa Prabhu
459767653936SRoopa Prabhu static int
vxlan_fdb_external_learn_add(struct net_device * dev,struct switchdev_notifier_vxlan_fdb_info * fdb_info)459867653936SRoopa Prabhu vxlan_fdb_external_learn_add(struct net_device *dev,
459967653936SRoopa Prabhu struct switchdev_notifier_vxlan_fdb_info *fdb_info)
460067653936SRoopa Prabhu {
460167653936SRoopa Prabhu struct vxlan_dev *vxlan = netdev_priv(dev);
460267653936SRoopa Prabhu struct netlink_ext_ack *extack;
460367653936SRoopa Prabhu u32 hash_index;
460467653936SRoopa Prabhu int err;
460567653936SRoopa Prabhu
460667653936SRoopa Prabhu hash_index = fdb_head_index(vxlan, fdb_info->eth_addr, fdb_info->vni);
460767653936SRoopa Prabhu extack = switchdev_notifier_info_to_extack(&fdb_info->info);
460867653936SRoopa Prabhu
460967653936SRoopa Prabhu spin_lock_bh(&vxlan->hash_lock[hash_index]);
461067653936SRoopa Prabhu err = vxlan_fdb_update(vxlan, fdb_info->eth_addr, &fdb_info->remote_ip,
461167653936SRoopa Prabhu NUD_REACHABLE,
461267653936SRoopa Prabhu NLM_F_CREATE | NLM_F_REPLACE,
461367653936SRoopa Prabhu fdb_info->remote_port,
461467653936SRoopa Prabhu fdb_info->vni,
461567653936SRoopa Prabhu fdb_info->remote_vni,
461667653936SRoopa Prabhu fdb_info->remote_ifindex,
461767653936SRoopa Prabhu NTF_USE | NTF_SELF | NTF_EXT_LEARNED,
461867653936SRoopa Prabhu 0, false, extack);
461967653936SRoopa Prabhu spin_unlock_bh(&vxlan->hash_lock[hash_index]);
462067653936SRoopa Prabhu
462167653936SRoopa Prabhu return err;
462267653936SRoopa Prabhu }
462367653936SRoopa Prabhu
462467653936SRoopa Prabhu static int
vxlan_fdb_external_learn_del(struct net_device * dev,struct switchdev_notifier_vxlan_fdb_info * fdb_info)462567653936SRoopa Prabhu vxlan_fdb_external_learn_del(struct net_device *dev,
462667653936SRoopa Prabhu struct switchdev_notifier_vxlan_fdb_info *fdb_info)
462767653936SRoopa Prabhu {
462867653936SRoopa Prabhu struct vxlan_dev *vxlan = netdev_priv(dev);
462967653936SRoopa Prabhu struct vxlan_fdb *f;
463067653936SRoopa Prabhu u32 hash_index;
463167653936SRoopa Prabhu int err = 0;
463267653936SRoopa Prabhu
463367653936SRoopa Prabhu hash_index = fdb_head_index(vxlan, fdb_info->eth_addr, fdb_info->vni);
463467653936SRoopa Prabhu spin_lock_bh(&vxlan->hash_lock[hash_index]);
463567653936SRoopa Prabhu
463667653936SRoopa Prabhu f = vxlan_find_mac(vxlan, fdb_info->eth_addr, fdb_info->vni);
463767653936SRoopa Prabhu if (!f)
463867653936SRoopa Prabhu err = -ENOENT;
463967653936SRoopa Prabhu else if (f->flags & NTF_EXT_LEARNED)
464067653936SRoopa Prabhu err = __vxlan_fdb_delete(vxlan, fdb_info->eth_addr,
464167653936SRoopa Prabhu fdb_info->remote_ip,
464267653936SRoopa Prabhu fdb_info->remote_port,
464367653936SRoopa Prabhu fdb_info->vni,
464467653936SRoopa Prabhu fdb_info->remote_vni,
464567653936SRoopa Prabhu fdb_info->remote_ifindex,
464667653936SRoopa Prabhu false);
464767653936SRoopa Prabhu
464867653936SRoopa Prabhu spin_unlock_bh(&vxlan->hash_lock[hash_index]);
464967653936SRoopa Prabhu
465067653936SRoopa Prabhu return err;
465167653936SRoopa Prabhu }
465267653936SRoopa Prabhu
vxlan_switchdev_event(struct notifier_block * unused,unsigned long event,void * ptr)465367653936SRoopa Prabhu static int vxlan_switchdev_event(struct notifier_block *unused,
465467653936SRoopa Prabhu unsigned long event, void *ptr)
465567653936SRoopa Prabhu {
465667653936SRoopa Prabhu struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
465767653936SRoopa Prabhu struct switchdev_notifier_vxlan_fdb_info *fdb_info;
465867653936SRoopa Prabhu int err = 0;
465967653936SRoopa Prabhu
466067653936SRoopa Prabhu switch (event) {
466167653936SRoopa Prabhu case SWITCHDEV_VXLAN_FDB_OFFLOADED:
466267653936SRoopa Prabhu vxlan_fdb_offloaded_set(dev, ptr);
466367653936SRoopa Prabhu break;
466467653936SRoopa Prabhu case SWITCHDEV_VXLAN_FDB_ADD_TO_BRIDGE:
466567653936SRoopa Prabhu fdb_info = ptr;
466667653936SRoopa Prabhu err = vxlan_fdb_external_learn_add(dev, fdb_info);
466767653936SRoopa Prabhu if (err) {
466867653936SRoopa Prabhu err = notifier_from_errno(err);
466967653936SRoopa Prabhu break;
467067653936SRoopa Prabhu }
467167653936SRoopa Prabhu fdb_info->offloaded = true;
467267653936SRoopa Prabhu vxlan_fdb_offloaded_set(dev, fdb_info);
467367653936SRoopa Prabhu break;
467467653936SRoopa Prabhu case SWITCHDEV_VXLAN_FDB_DEL_TO_BRIDGE:
467567653936SRoopa Prabhu fdb_info = ptr;
467667653936SRoopa Prabhu err = vxlan_fdb_external_learn_del(dev, fdb_info);
467767653936SRoopa Prabhu if (err) {
467867653936SRoopa Prabhu err = notifier_from_errno(err);
467967653936SRoopa Prabhu break;
468067653936SRoopa Prabhu }
468167653936SRoopa Prabhu fdb_info->offloaded = false;
468267653936SRoopa Prabhu vxlan_fdb_offloaded_set(dev, fdb_info);
468367653936SRoopa Prabhu break;
468467653936SRoopa Prabhu }
468567653936SRoopa Prabhu
468667653936SRoopa Prabhu return err;
468767653936SRoopa Prabhu }
468867653936SRoopa Prabhu
468967653936SRoopa Prabhu static struct notifier_block vxlan_switchdev_notifier_block __read_mostly = {
469067653936SRoopa Prabhu .notifier_call = vxlan_switchdev_event,
469167653936SRoopa Prabhu };
469267653936SRoopa Prabhu
vxlan_fdb_nh_flush(struct nexthop * nh)469367653936SRoopa Prabhu static void vxlan_fdb_nh_flush(struct nexthop *nh)
469467653936SRoopa Prabhu {
469567653936SRoopa Prabhu struct vxlan_fdb *fdb;
469667653936SRoopa Prabhu struct vxlan_dev *vxlan;
469767653936SRoopa Prabhu u32 hash_index;
469867653936SRoopa Prabhu
469967653936SRoopa Prabhu rcu_read_lock();
470067653936SRoopa Prabhu list_for_each_entry_rcu(fdb, &nh->fdb_list, nh_list) {
470167653936SRoopa Prabhu vxlan = rcu_dereference(fdb->vdev);
470267653936SRoopa Prabhu WARN_ON(!vxlan);
470367653936SRoopa Prabhu hash_index = fdb_head_index(vxlan, fdb->eth_addr,
470467653936SRoopa Prabhu vxlan->default_dst.remote_vni);
470567653936SRoopa Prabhu spin_lock_bh(&vxlan->hash_lock[hash_index]);
470667653936SRoopa Prabhu if (!hlist_unhashed(&fdb->hlist))
470767653936SRoopa Prabhu vxlan_fdb_destroy(vxlan, fdb, false, false);
470867653936SRoopa Prabhu spin_unlock_bh(&vxlan->hash_lock[hash_index]);
470967653936SRoopa Prabhu }
471067653936SRoopa Prabhu rcu_read_unlock();
471167653936SRoopa Prabhu }
471267653936SRoopa Prabhu
vxlan_nexthop_event(struct notifier_block * nb,unsigned long event,void * ptr)471367653936SRoopa Prabhu static int vxlan_nexthop_event(struct notifier_block *nb,
471467653936SRoopa Prabhu unsigned long event, void *ptr)
471567653936SRoopa Prabhu {
471667653936SRoopa Prabhu struct nh_notifier_info *info = ptr;
471767653936SRoopa Prabhu struct nexthop *nh;
471867653936SRoopa Prabhu
471967653936SRoopa Prabhu if (event != NEXTHOP_EVENT_DEL)
472067653936SRoopa Prabhu return NOTIFY_DONE;
472167653936SRoopa Prabhu
472267653936SRoopa Prabhu nh = nexthop_find_by_id(info->net, info->id);
472367653936SRoopa Prabhu if (!nh)
472467653936SRoopa Prabhu return NOTIFY_DONE;
472567653936SRoopa Prabhu
472667653936SRoopa Prabhu vxlan_fdb_nh_flush(nh);
472767653936SRoopa Prabhu
472867653936SRoopa Prabhu return NOTIFY_DONE;
472967653936SRoopa Prabhu }
473067653936SRoopa Prabhu
vxlan_init_net(struct net * net)473167653936SRoopa Prabhu static __net_init int vxlan_init_net(struct net *net)
473267653936SRoopa Prabhu {
473367653936SRoopa Prabhu struct vxlan_net *vn = net_generic(net, vxlan_net_id);
473467653936SRoopa Prabhu unsigned int h;
473567653936SRoopa Prabhu
473667653936SRoopa Prabhu INIT_LIST_HEAD(&vn->vxlan_list);
473767653936SRoopa Prabhu spin_lock_init(&vn->sock_lock);
473867653936SRoopa Prabhu vn->nexthop_notifier_block.notifier_call = vxlan_nexthop_event;
473967653936SRoopa Prabhu
474067653936SRoopa Prabhu for (h = 0; h < PORT_HASH_SIZE; ++h)
474167653936SRoopa Prabhu INIT_HLIST_HEAD(&vn->sock_list[h]);
474267653936SRoopa Prabhu
474367653936SRoopa Prabhu return register_nexthop_notifier(net, &vn->nexthop_notifier_block,
474467653936SRoopa Prabhu NULL);
474567653936SRoopa Prabhu }
474667653936SRoopa Prabhu
vxlan_destroy_tunnels(struct net * net,struct list_head * head)474767653936SRoopa Prabhu static void vxlan_destroy_tunnels(struct net *net, struct list_head *head)
474867653936SRoopa Prabhu {
474967653936SRoopa Prabhu struct vxlan_net *vn = net_generic(net, vxlan_net_id);
475067653936SRoopa Prabhu struct vxlan_dev *vxlan, *next;
475167653936SRoopa Prabhu struct net_device *dev, *aux;
475267653936SRoopa Prabhu
475367653936SRoopa Prabhu for_each_netdev_safe(net, dev, aux)
475467653936SRoopa Prabhu if (dev->rtnl_link_ops == &vxlan_link_ops)
475567653936SRoopa Prabhu unregister_netdevice_queue(dev, head);
475667653936SRoopa Prabhu
475767653936SRoopa Prabhu list_for_each_entry_safe(vxlan, next, &vn->vxlan_list, next) {
475867653936SRoopa Prabhu /* If vxlan->dev is in the same netns, it has already been added
475967653936SRoopa Prabhu * to the list by the previous loop.
476067653936SRoopa Prabhu */
476167653936SRoopa Prabhu if (!net_eq(dev_net(vxlan->dev), net))
476267653936SRoopa Prabhu unregister_netdevice_queue(vxlan->dev, head);
476367653936SRoopa Prabhu }
476467653936SRoopa Prabhu
476567653936SRoopa Prabhu }
476667653936SRoopa Prabhu
vxlan_exit_batch_net(struct list_head * net_list)476767653936SRoopa Prabhu static void __net_exit vxlan_exit_batch_net(struct list_head *net_list)
476867653936SRoopa Prabhu {
476967653936SRoopa Prabhu struct net *net;
477067653936SRoopa Prabhu LIST_HEAD(list);
477167653936SRoopa Prabhu unsigned int h;
477267653936SRoopa Prabhu
477367653936SRoopa Prabhu list_for_each_entry(net, net_list, exit_list) {
477467653936SRoopa Prabhu struct vxlan_net *vn = net_generic(net, vxlan_net_id);
477567653936SRoopa Prabhu
477667653936SRoopa Prabhu unregister_nexthop_notifier(net, &vn->nexthop_notifier_block);
477767653936SRoopa Prabhu }
477867653936SRoopa Prabhu rtnl_lock();
477967653936SRoopa Prabhu list_for_each_entry(net, net_list, exit_list)
478067653936SRoopa Prabhu vxlan_destroy_tunnels(net, &list);
478167653936SRoopa Prabhu
478267653936SRoopa Prabhu unregister_netdevice_many(&list);
478367653936SRoopa Prabhu rtnl_unlock();
478467653936SRoopa Prabhu
478567653936SRoopa Prabhu list_for_each_entry(net, net_list, exit_list) {
478667653936SRoopa Prabhu struct vxlan_net *vn = net_generic(net, vxlan_net_id);
478767653936SRoopa Prabhu
478867653936SRoopa Prabhu for (h = 0; h < PORT_HASH_SIZE; ++h)
478967653936SRoopa Prabhu WARN_ON_ONCE(!hlist_empty(&vn->sock_list[h]));
479067653936SRoopa Prabhu }
479167653936SRoopa Prabhu }
479267653936SRoopa Prabhu
479367653936SRoopa Prabhu static struct pernet_operations vxlan_net_ops = {
479467653936SRoopa Prabhu .init = vxlan_init_net,
479567653936SRoopa Prabhu .exit_batch = vxlan_exit_batch_net,
479667653936SRoopa Prabhu .id = &vxlan_net_id,
479767653936SRoopa Prabhu .size = sizeof(struct vxlan_net),
479867653936SRoopa Prabhu };
479967653936SRoopa Prabhu
vxlan_init_module(void)480067653936SRoopa Prabhu static int __init vxlan_init_module(void)
480167653936SRoopa Prabhu {
480267653936SRoopa Prabhu int rc;
480367653936SRoopa Prabhu
480467653936SRoopa Prabhu get_random_bytes(&vxlan_salt, sizeof(vxlan_salt));
480567653936SRoopa Prabhu
480667653936SRoopa Prabhu rc = register_pernet_subsys(&vxlan_net_ops);
480767653936SRoopa Prabhu if (rc)
480867653936SRoopa Prabhu goto out1;
480967653936SRoopa Prabhu
481067653936SRoopa Prabhu rc = register_netdevice_notifier(&vxlan_notifier_block);
481167653936SRoopa Prabhu if (rc)
481267653936SRoopa Prabhu goto out2;
481367653936SRoopa Prabhu
481467653936SRoopa Prabhu rc = register_switchdev_notifier(&vxlan_switchdev_notifier_block);
481567653936SRoopa Prabhu if (rc)
481667653936SRoopa Prabhu goto out3;
481767653936SRoopa Prabhu
481867653936SRoopa Prabhu rc = rtnl_link_register(&vxlan_link_ops);
481967653936SRoopa Prabhu if (rc)
482067653936SRoopa Prabhu goto out4;
482167653936SRoopa Prabhu
4822ca15d288SKuniyuki Iwashima rc = vxlan_vnifilter_init();
4823ca15d288SKuniyuki Iwashima if (rc)
4824ca15d288SKuniyuki Iwashima goto out5;
4825f9c4bb0bSRoopa Prabhu
482667653936SRoopa Prabhu return 0;
4827ca15d288SKuniyuki Iwashima out5:
4828ca15d288SKuniyuki Iwashima rtnl_link_unregister(&vxlan_link_ops);
482967653936SRoopa Prabhu out4:
483067653936SRoopa Prabhu unregister_switchdev_notifier(&vxlan_switchdev_notifier_block);
483167653936SRoopa Prabhu out3:
483267653936SRoopa Prabhu unregister_netdevice_notifier(&vxlan_notifier_block);
483367653936SRoopa Prabhu out2:
483467653936SRoopa Prabhu unregister_pernet_subsys(&vxlan_net_ops);
483567653936SRoopa Prabhu out1:
483667653936SRoopa Prabhu return rc;
483767653936SRoopa Prabhu }
483867653936SRoopa Prabhu late_initcall(vxlan_init_module);
483967653936SRoopa Prabhu
vxlan_cleanup_module(void)484067653936SRoopa Prabhu static void __exit vxlan_cleanup_module(void)
484167653936SRoopa Prabhu {
4842f9c4bb0bSRoopa Prabhu vxlan_vnifilter_uninit();
484367653936SRoopa Prabhu rtnl_link_unregister(&vxlan_link_ops);
484467653936SRoopa Prabhu unregister_switchdev_notifier(&vxlan_switchdev_notifier_block);
484567653936SRoopa Prabhu unregister_netdevice_notifier(&vxlan_notifier_block);
484667653936SRoopa Prabhu unregister_pernet_subsys(&vxlan_net_ops);
484767653936SRoopa Prabhu /* rcu_barrier() is called by netns */
484867653936SRoopa Prabhu }
484967653936SRoopa Prabhu module_exit(vxlan_cleanup_module);
485067653936SRoopa Prabhu
485167653936SRoopa Prabhu MODULE_LICENSE("GPL");
485267653936SRoopa Prabhu MODULE_VERSION(VXLAN_VERSION);
485367653936SRoopa Prabhu MODULE_AUTHOR("Stephen Hemminger <stephen@networkplumber.org>");
485467653936SRoopa Prabhu MODULE_DESCRIPTION("Driver for VXLAN encapsulated traffic");
485567653936SRoopa Prabhu MODULE_ALIAS_RTNL_LINK("vxlan");
4856