xref: /openbmc/linux/drivers/net/vxlan/vxlan_core.c (revision 924f7bbf)
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) {
263267653936SRoopa Prabhu 			u32 rt6i_flags = ((struct 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 
4822f9c4bb0bSRoopa Prabhu 	vxlan_vnifilter_init();
4823f9c4bb0bSRoopa Prabhu 
482467653936SRoopa Prabhu 	return 0;
482567653936SRoopa Prabhu out4:
482667653936SRoopa Prabhu 	unregister_switchdev_notifier(&vxlan_switchdev_notifier_block);
482767653936SRoopa Prabhu out3:
482867653936SRoopa Prabhu 	unregister_netdevice_notifier(&vxlan_notifier_block);
482967653936SRoopa Prabhu out2:
483067653936SRoopa Prabhu 	unregister_pernet_subsys(&vxlan_net_ops);
483167653936SRoopa Prabhu out1:
483267653936SRoopa Prabhu 	return rc;
483367653936SRoopa Prabhu }
483467653936SRoopa Prabhu late_initcall(vxlan_init_module);
483567653936SRoopa Prabhu 
vxlan_cleanup_module(void)483667653936SRoopa Prabhu static void __exit vxlan_cleanup_module(void)
483767653936SRoopa Prabhu {
4838f9c4bb0bSRoopa Prabhu 	vxlan_vnifilter_uninit();
483967653936SRoopa Prabhu 	rtnl_link_unregister(&vxlan_link_ops);
484067653936SRoopa Prabhu 	unregister_switchdev_notifier(&vxlan_switchdev_notifier_block);
484167653936SRoopa Prabhu 	unregister_netdevice_notifier(&vxlan_notifier_block);
484267653936SRoopa Prabhu 	unregister_pernet_subsys(&vxlan_net_ops);
484367653936SRoopa Prabhu 	/* rcu_barrier() is called by netns */
484467653936SRoopa Prabhu }
484567653936SRoopa Prabhu module_exit(vxlan_cleanup_module);
484667653936SRoopa Prabhu 
484767653936SRoopa Prabhu MODULE_LICENSE("GPL");
484867653936SRoopa Prabhu MODULE_VERSION(VXLAN_VERSION);
484967653936SRoopa Prabhu MODULE_AUTHOR("Stephen Hemminger <stephen@networkplumber.org>");
485067653936SRoopa Prabhu MODULE_DESCRIPTION("Driver for VXLAN encapsulated traffic");
485167653936SRoopa Prabhu MODULE_ALIAS_RTNL_LINK("vxlan");
4852