ip_tunnel.c 29.9 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0-only
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
/*
 * Copyright (c) 2013 Nicira, Inc.
 */

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/capability.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/in.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/if_arp.h>
#include <linux/init.h>
#include <linux/in6.h>
#include <linux/inetdevice.h>
#include <linux/igmp.h>
#include <linux/netfilter_ipv4.h>
#include <linux/etherdevice.h>
#include <linux/if_ether.h>
#include <linux/if_vlan.h>
#include <linux/rculist.h>
S
Sachin Kamat 已提交
29
#include <linux/err.h>
30 31 32 33 34 35 36 37 38 39 40 41 42 43

#include <net/sock.h>
#include <net/ip.h>
#include <net/icmp.h>
#include <net/protocol.h>
#include <net/ip_tunnels.h>
#include <net/arp.h>
#include <net/checksum.h>
#include <net/dsfield.h>
#include <net/inet_ecn.h>
#include <net/xfrm.h>
#include <net/net_namespace.h>
#include <net/netns/generic.h>
#include <net/rtnetlink.h>
44
#include <net/udp.h>
45
#include <net/dst_metadata.h>
46

47 48 49 50 51 52
#if IS_ENABLED(CONFIG_IPV6)
#include <net/ipv6.h>
#include <net/ip6_fib.h>
#include <net/ip6_route.h>
#endif

53
static unsigned int ip_tunnel_hash(__be32 key, __be32 remote)
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
{
	return hash_32((__force u32)key ^ (__force u32)remote,
			 IP_TNL_HASH_BITS);
}

static bool ip_tunnel_key_match(const struct ip_tunnel_parm *p,
				__be16 flags, __be32 key)
{
	if (p->i_flags & TUNNEL_KEY) {
		if (flags & TUNNEL_KEY)
			return key == p->i_key;
		else
			/* key expected, none present */
			return false;
	} else
		return !(flags & TUNNEL_KEY);
}

/* Fallback tunnel: no source, no destination, no key, no options

   Tunnel hash table:
   We require exact key match i.e. if a key is present in packet
   it will match only tunnel with the same key; if it is not present,
   it will match only keyless tunnel.

   All keysless packets, if not matched configured keyless tunnels
   will match fallback tunnel.
   Given src, dst and key, find appropriate for input tunnel.
*/
struct ip_tunnel *ip_tunnel_lookup(struct ip_tunnel_net *itn,
				   int link, __be16 flags,
				   __be32 remote, __be32 local,
				   __be32 key)
{
	struct ip_tunnel *t, *cand = NULL;
	struct hlist_head *head;
90 91
	struct net_device *ndev;
	unsigned int hash;
92

93
	hash = ip_tunnel_hash(key, remote);
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
	head = &itn->tunnels[hash];

	hlist_for_each_entry_rcu(t, head, hash_node) {
		if (local != t->parms.iph.saddr ||
		    remote != t->parms.iph.daddr ||
		    !(t->dev->flags & IFF_UP))
			continue;

		if (!ip_tunnel_key_match(&t->parms, flags, key))
			continue;

		if (t->parms.link == link)
			return t;
		else
			cand = t;
	}

	hlist_for_each_entry_rcu(t, head, hash_node) {
		if (remote != t->parms.iph.daddr ||
D
Dmitry Popov 已提交
113
		    t->parms.iph.saddr != 0 ||
114 115 116 117 118 119 120 121 122 123 124 125
		    !(t->dev->flags & IFF_UP))
			continue;

		if (!ip_tunnel_key_match(&t->parms, flags, key))
			continue;

		if (t->parms.link == link)
			return t;
		else if (!cand)
			cand = t;
	}

126
	hash = ip_tunnel_hash(key, 0);
127 128 129
	head = &itn->tunnels[hash];

	hlist_for_each_entry_rcu(t, head, hash_node) {
D
Dmitry Popov 已提交
130 131 132 133 134
		if ((local != t->parms.iph.saddr || t->parms.iph.daddr != 0) &&
		    (local != t->parms.iph.daddr || !ipv4_is_multicast(local)))
			continue;

		if (!(t->dev->flags & IFF_UP))
135 136 137 138 139 140 141 142 143 144 145 146
			continue;

		if (!ip_tunnel_key_match(&t->parms, flags, key))
			continue;

		if (t->parms.link == link)
			return t;
		else if (!cand)
			cand = t;
	}

	hlist_for_each_entry_rcu(t, head, hash_node) {
147
		if ((!(flags & TUNNEL_NO_KEY) && t->parms.i_key != key) ||
D
Dmitry Popov 已提交
148 149
		    t->parms.iph.saddr != 0 ||
		    t->parms.iph.daddr != 0 ||
150 151 152 153 154 155 156 157 158 159 160 161
		    !(t->dev->flags & IFF_UP))
			continue;

		if (t->parms.link == link)
			return t;
		else if (!cand)
			cand = t;
	}

	if (cand)
		return cand;

162
	t = rcu_dereference(itn->collect_md_tun);
163
	if (t && t->dev->flags & IFF_UP)
164 165
		return t;

166 167 168
	ndev = READ_ONCE(itn->fb_tunnel_dev);
	if (ndev && ndev->flags & IFF_UP)
		return netdev_priv(ndev);
169 170 171 172 173 174 175 176 177 178

	return NULL;
}
EXPORT_SYMBOL_GPL(ip_tunnel_lookup);

static struct hlist_head *ip_bucket(struct ip_tunnel_net *itn,
				    struct ip_tunnel_parm *parms)
{
	unsigned int h;
	__be32 remote;
179
	__be32 i_key = parms->i_key;
180 181 182 183 184 185

	if (parms->iph.daddr && !ipv4_is_multicast(parms->iph.daddr))
		remote = parms->iph.daddr;
	else
		remote = 0;

186 187 188 189
	if (!(parms->i_flags & TUNNEL_KEY) && (parms->i_flags & VTI_ISVTI))
		i_key = 0;

	h = ip_tunnel_hash(i_key, remote);
190 191 192 193 194 195 196
	return &itn->tunnels[h];
}

static void ip_tunnel_add(struct ip_tunnel_net *itn, struct ip_tunnel *t)
{
	struct hlist_head *head = ip_bucket(itn, &t->parms);

197 198
	if (t->collect_md)
		rcu_assign_pointer(itn->collect_md_tun, t);
199 200 201
	hlist_add_head_rcu(&t->hash_node, head);
}

202
static void ip_tunnel_del(struct ip_tunnel_net *itn, struct ip_tunnel *t)
203
{
204 205
	if (t->collect_md)
		rcu_assign_pointer(itn->collect_md_tun, NULL);
206 207 208 209 210 211 212 213 214 215
	hlist_del_init_rcu(&t->hash_node);
}

static struct ip_tunnel *ip_tunnel_find(struct ip_tunnel_net *itn,
					struct ip_tunnel_parm *parms,
					int type)
{
	__be32 remote = parms->iph.daddr;
	__be32 local = parms->iph.saddr;
	__be32 key = parms->i_key;
216
	__be16 flags = parms->i_flags;
217 218 219 220 221 222 223 224
	int link = parms->link;
	struct ip_tunnel *t = NULL;
	struct hlist_head *head = ip_bucket(itn, parms);

	hlist_for_each_entry_rcu(t, head, hash_node) {
		if (local == t->parms.iph.saddr &&
		    remote == t->parms.iph.daddr &&
		    link == t->parms.link &&
225 226
		    type == t->dev->type &&
		    ip_tunnel_key_match(&t->parms, flags, key))
227 228 229 230 231 232 233 234 235 236 237 238 239 240
			break;
	}
	return t;
}

static struct net_device *__ip_tunnel_create(struct net *net,
					     const struct rtnl_link_ops *ops,
					     struct ip_tunnel_parm *parms)
{
	int err;
	struct ip_tunnel *tunnel;
	struct net_device *dev;
	char name[IFNAMSIZ];

241 242 243 244
	err = -E2BIG;
	if (parms->name[0]) {
		if (!dev_valid_name(parms->name))
			goto failed;
245
		strlcpy(name, parms->name, IFNAMSIZ);
246 247
	} else {
		if (strlen(ops->kind) > (IFNAMSIZ - 3))
248
			goto failed;
249 250
		strcpy(name, ops->kind);
		strcat(name, "%d");
251 252 253
	}

	ASSERT_RTNL();
254
	dev = alloc_netdev(ops->priv_size, name, NET_NAME_UNKNOWN, ops->setup);
255 256 257 258 259 260 261 262 263 264
	if (!dev) {
		err = -ENOMEM;
		goto failed;
	}
	dev_net_set(dev, net);

	dev->rtnl_link_ops = ops;

	tunnel = netdev_priv(dev);
	tunnel->parms = *parms;
N
Nicolas Dichtel 已提交
265
	tunnel->net = net;
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294

	err = register_netdevice(dev);
	if (err)
		goto failed_free;

	return dev;

failed_free:
	free_netdev(dev);
failed:
	return ERR_PTR(err);
}

static int ip_tunnel_bind_dev(struct net_device *dev)
{
	struct net_device *tdev = NULL;
	struct ip_tunnel *tunnel = netdev_priv(dev);
	const struct iphdr *iph;
	int hlen = LL_MAX_HEADER;
	int mtu = ETH_DATA_LEN;
	int t_hlen = tunnel->hlen + sizeof(struct iphdr);

	iph = &tunnel->parms.iph;

	/* Guess output device to choose reasonable mtu and needed_headroom */
	if (iph->daddr) {
		struct flowi4 fl4;
		struct rtable *rt;

295 296 297
		ip_tunnel_init_flow(&fl4, iph->protocol, iph->daddr,
				    iph->saddr, tunnel->parms.o_key,
				    RT_TOS(iph->tos), tunnel->parms.link,
298
				    tunnel->fwmark, 0);
T
Tom Herbert 已提交
299 300
		rt = ip_route_output_key(tunnel->net, &fl4);

301 302 303 304 305 306
		if (!IS_ERR(rt)) {
			tdev = rt->dst.dev;
			ip_rt_put(rt);
		}
		if (dev->type != ARPHRD_ETHER)
			dev->flags |= IFF_POINTOPOINT;
307 308

		dst_cache_reset(&tunnel->dst_cache);
309 310 311
	}

	if (!tdev && tunnel->parms.link)
N
Nicolas Dichtel 已提交
312
		tdev = __dev_get_by_index(tunnel->net, tunnel->parms.link);
313 314 315

	if (tdev) {
		hlen = tdev->hard_header_len + tdev->needed_headroom;
316
		mtu = min(tdev->mtu, IP_MAX_MTU);
317 318 319 320 321
	}

	dev->needed_headroom = t_hlen + hlen;
	mtu -= (dev->hard_header_len + t_hlen);

322 323
	if (mtu < IPV4_MIN_MTU)
		mtu = IPV4_MIN_MTU;
324 325 326 327 328 329 330 331

	return mtu;
}

static struct ip_tunnel *ip_tunnel_create(struct net *net,
					  struct ip_tunnel_net *itn,
					  struct ip_tunnel_parm *parms)
{
332
	struct ip_tunnel *nt;
333
	struct net_device *dev;
334
	int t_hlen;
335 336
	int mtu;
	int err;
337

338
	dev = __ip_tunnel_create(net, itn->rtnl_link_ops, parms);
339
	if (IS_ERR(dev))
340
		return ERR_CAST(dev);
341

342 343 344 345
	mtu = ip_tunnel_bind_dev(dev);
	err = dev_set_mtu(dev, mtu);
	if (err)
		goto err_dev_set_mtu;
346 347

	nt = netdev_priv(dev);
348 349
	t_hlen = nt->hlen + sizeof(struct iphdr);
	dev->min_mtu = ETH_MIN_MTU;
350
	dev->max_mtu = IP_MAX_MTU - dev->hard_header_len - t_hlen;
351 352
	ip_tunnel_add(itn, nt);
	return nt;
353 354 355 356

err_dev_set_mtu:
	unregister_netdevice(dev);
	return ERR_PTR(err);
357 358 359
}

int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb,
360 361
		  const struct tnl_ptk_info *tpi, struct metadata_dst *tun_dst,
		  bool log_ecn_error)
362
{
363
	struct pcpu_sw_netstats *tstats;
364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390
	const struct iphdr *iph = ip_hdr(skb);
	int err;

#ifdef CONFIG_NET_IPGRE_BROADCAST
	if (ipv4_is_multicast(iph->daddr)) {
		tunnel->dev->stats.multicast++;
		skb->pkt_type = PACKET_BROADCAST;
	}
#endif

	if ((!(tpi->flags&TUNNEL_CSUM) &&  (tunnel->parms.i_flags&TUNNEL_CSUM)) ||
	     ((tpi->flags&TUNNEL_CSUM) && !(tunnel->parms.i_flags&TUNNEL_CSUM))) {
		tunnel->dev->stats.rx_crc_errors++;
		tunnel->dev->stats.rx_errors++;
		goto drop;
	}

	if (tunnel->parms.i_flags&TUNNEL_SEQ) {
		if (!(tpi->flags&TUNNEL_SEQ) ||
		    (tunnel->i_seqno && (s32)(ntohl(tpi->seq) - tunnel->i_seqno) < 0)) {
			tunnel->dev->stats.rx_fifo_errors++;
			tunnel->dev->stats.rx_errors++;
			goto drop;
		}
		tunnel->i_seqno = ntohl(tpi->seq) + 1;
	}

391 392
	skb_reset_network_header(skb);

393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410
	err = IP_ECN_decapsulate(iph, skb);
	if (unlikely(err)) {
		if (log_ecn_error)
			net_info_ratelimited("non-ECT from %pI4 with TOS=%#x\n",
					&iph->saddr, iph->tos);
		if (err > 1) {
			++tunnel->dev->stats.rx_frame_errors;
			++tunnel->dev->stats.rx_errors;
			goto drop;
		}
	}

	tstats = this_cpu_ptr(tunnel->dev->tstats);
	u64_stats_update_begin(&tstats->syncp);
	tstats->rx_packets++;
	tstats->rx_bytes += skb->len;
	u64_stats_update_end(&tstats->syncp);

411 412
	skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(tunnel->dev)));

413 414 415 416 417 418
	if (tunnel->dev->type == ARPHRD_ETHER) {
		skb->protocol = eth_type_trans(skb, tunnel->dev);
		skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN);
	} else {
		skb->dev = tunnel->dev;
	}
419

420 421 422
	if (tun_dst)
		skb_dst_set(skb, (struct dst_entry *)tun_dst);

423 424 425 426
	gro_cells_receive(&tunnel->gro_cells, skb);
	return 0;

drop:
427 428
	if (tun_dst)
		dst_release((struct dst_entry *)tun_dst);
429 430 431 432 433
	kfree_skb(skb);
	return 0;
}
EXPORT_SYMBOL_GPL(ip_tunnel_rcv);

434 435 436
int ip_tunnel_encap_add_ops(const struct ip_tunnel_encap_ops *ops,
			    unsigned int num)
{
437 438 439
	if (num >= MAX_IPTUN_ENCAP_OPS)
		return -ERANGE;

440 441 442
	return !cmpxchg((const struct ip_tunnel_encap_ops **)
			&iptun_encaps[num],
			NULL, ops) ? 0 : -1;
443
}
444 445 446 447 448 449 450
EXPORT_SYMBOL(ip_tunnel_encap_add_ops);

int ip_tunnel_encap_del_ops(const struct ip_tunnel_encap_ops *ops,
			    unsigned int num)
{
	int ret;

451 452 453
	if (num >= MAX_IPTUN_ENCAP_OPS)
		return -ERANGE;

454 455 456 457 458 459 460 461 462
	ret = (cmpxchg((const struct ip_tunnel_encap_ops **)
		       &iptun_encaps[num],
		       ops, NULL) == ops) ? 0 : -1;

	synchronize_net();

	return ret;
}
EXPORT_SYMBOL(ip_tunnel_encap_del_ops);
463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486

int ip_tunnel_encap_setup(struct ip_tunnel *t,
			  struct ip_tunnel_encap *ipencap)
{
	int hlen;

	memset(&t->encap, 0, sizeof(t->encap));

	hlen = ip_encap_hlen(ipencap);
	if (hlen < 0)
		return hlen;

	t->encap.type = ipencap->type;
	t->encap.sport = ipencap->sport;
	t->encap.dport = ipencap->dport;
	t->encap.flags = ipencap->flags;

	t->encap_hlen = hlen;
	t->hlen = t->encap_hlen + t->tun_hlen;

	return 0;
}
EXPORT_SYMBOL_GPL(ip_tunnel_encap_setup);

487
static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb,
488
			    struct rtable *rt, __be16 df,
489 490
			    const struct iphdr *inner_iph,
			    int tunnel_hlen, __be32 dst, bool md)
491 492
{
	struct ip_tunnel *tunnel = netdev_priv(dev);
493
	int pkt_size;
494 495
	int mtu;

496 497 498
	tunnel_hlen = md ? tunnel_hlen : tunnel->hlen;
	pkt_size = skb->len - tunnel_hlen - dev->hard_header_len;

499 500
	if (df)
		mtu = dst_mtu(&rt->dst) - dev->hard_header_len
501
					- sizeof(struct iphdr) - tunnel_hlen;
502
	else
503
		mtu = skb_valid_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu;
504

505
	if (skb_valid_dst(skb))
506
		skb_dst_update_pmtu_no_confirm(skb, mtu);
507 508 509

	if (skb->protocol == htons(ETH_P_IP)) {
		if (!skb_is_gso(skb) &&
510 511
		    (inner_iph->frag_off & htons(IP_DF)) &&
		    mtu < pkt_size) {
512 513 514 515 516 517 518
			memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
			icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
			return -E2BIG;
		}
	}
#if IS_ENABLED(CONFIG_IPV6)
	else if (skb->protocol == htons(ETH_P_IPV6)) {
519
		struct rt6_info *rt6;
520 521
		__be32 daddr;

522 523
		rt6 = skb_valid_dst(skb) ? (struct rt6_info *)skb_dst(skb) :
					   NULL;
524
		daddr = md ? dst : tunnel->parms.iph.daddr;
525 526 527

		if (rt6 && mtu < dst_mtu(skb_dst(skb)) &&
			   mtu >= IPV6_MIN_MTU) {
528
			if ((daddr && !ipv4_is_multicast(daddr)) ||
529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544
			    rt6->rt6i_dst.plen == 128) {
				rt6->rt6i_flags |= RTF_MODIFIED;
				dst_metric_set(skb_dst(skb), RTAX_MTU, mtu);
			}
		}

		if (!skb_is_gso(skb) && mtu >= IPV6_MIN_MTU &&
					mtu < pkt_size) {
			icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
			return -E2BIG;
		}
	}
#endif
	return 0;
}

545 546
void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
		       u8 proto, int tunnel_hlen)
547 548 549 550 551 552
{
	struct ip_tunnel *tunnel = netdev_priv(dev);
	u32 headroom = sizeof(struct iphdr);
	struct ip_tunnel_info *tun_info;
	const struct ip_tunnel_key *key;
	const struct iphdr *inner_iph;
553
	struct rtable *rt = NULL;
554 555 556
	struct flowi4 fl4;
	__be16 df = 0;
	u8 tos, ttl;
557
	bool use_cache;
558 559 560 561 562 563 564 565 566 567 568 569 570 571 572

	tun_info = skb_tunnel_info(skb);
	if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) ||
		     ip_tunnel_info_af(tun_info) != AF_INET))
		goto tx_error;
	key = &tun_info->key;
	memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
	inner_iph = (const struct iphdr *)skb_inner_network_header(skb);
	tos = key->tos;
	if (tos == 1) {
		if (skb->protocol == htons(ETH_P_IP))
			tos = inner_iph->tos;
		else if (skb->protocol == htons(ETH_P_IPV6))
			tos = ipv6_get_dsfield((const struct ipv6hdr *)inner_iph);
	}
573 574
	ip_tunnel_init_flow(&fl4, proto, key->u.ipv4.dst, key->u.ipv4.src,
			    tunnel_id_to_key32(key->tun_id), RT_TOS(tos),
575
			    0, skb->mark, skb_get_hash(skb));
576 577
	if (tunnel->encap.type != TUNNEL_ENCAP_NONE)
		goto tx_error;
578 579 580 581 582 583 584 585 586 587 588 589 590

	use_cache = ip_tunnel_dst_cache_usable(skb, tun_info);
	if (use_cache)
		rt = dst_cache_get_ip4(&tun_info->dst_cache, &fl4.saddr);
	if (!rt) {
		rt = ip_route_output_key(tunnel->net, &fl4);
		if (IS_ERR(rt)) {
			dev->stats.tx_carrier_errors++;
			goto tx_error;
		}
		if (use_cache)
			dst_cache_set_ip4(&tun_info->dst_cache, &rt->dst,
					  fl4.saddr);
591 592 593 594 595 596
	}
	if (rt->dst.dev == dev) {
		ip_rt_put(rt);
		dev->stats.collisions++;
		goto tx_error;
	}
597 598 599 600 601 602 603 604 605

	if (key->tun_flags & TUNNEL_DONT_FRAGMENT)
		df = htons(IP_DF);
	if (tnl_update_pmtu(dev, skb, rt, df, inner_iph, tunnel_hlen,
			    key->u.ipv4.dst, true)) {
		ip_rt_put(rt);
		goto tx_error;
	}

606 607 608 609 610 611 612 613 614 615
	tos = ip_tunnel_ecn_encap(tos, inner_iph, skb);
	ttl = key->ttl;
	if (ttl == 0) {
		if (skb->protocol == htons(ETH_P_IP))
			ttl = inner_iph->ttl;
		else if (skb->protocol == htons(ETH_P_IPV6))
			ttl = ((const struct ipv6hdr *)inner_iph)->hop_limit;
		else
			ttl = ip4_dst_hoplimit(&rt->dst);
	}
616 617

	if (!df && skb->protocol == htons(ETH_P_IP))
618
		df = inner_iph->frag_off & htons(IP_DF);
619

620 621 622 623 624 625 626 627
	headroom += LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len;
	if (headroom > dev->needed_headroom)
		dev->needed_headroom = headroom;

	if (skb_cow_head(skb, dev->needed_headroom)) {
		ip_rt_put(rt);
		goto tx_dropped;
	}
628 629
	iptunnel_xmit(NULL, rt, skb, fl4.saddr, fl4.daddr, proto, tos, ttl,
		      df, !net_eq(tunnel->net, dev_net(dev)));
630 631 632 633 634 635 636 637 638 639 640
	return;
tx_error:
	dev->stats.tx_errors++;
	goto kfree;
tx_dropped:
	dev->stats.tx_dropped++;
kfree:
	kfree_skb(skb);
}
EXPORT_SYMBOL_GPL(ip_md_tunnel_xmit);

641
void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
642
		    const struct iphdr *tnl_params, u8 protocol)
643 644
{
	struct ip_tunnel *tunnel = netdev_priv(dev);
645
	struct ip_tunnel_info *tun_info = NULL;
646 647
	const struct iphdr *inner_iph;
	unsigned int max_headroom;	/* The extra header space needed */
648 649 650 651
	struct rtable *rt = NULL;		/* Route to the other host */
	bool use_cache = false;
	struct flowi4 fl4;
	bool md = false;
652
	bool connected;
653 654 655
	u8 tos, ttl;
	__be32 dst;
	__be16 df;
656 657

	inner_iph = (const struct iphdr *)skb_inner_network_header(skb);
658
	connected = (tunnel->parms.iph.daddr != 0);
659

660 661
	memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));

662 663 664 665
	dst = tnl_params->daddr;
	if (dst == 0) {
		/* NBMA tunnel */

666
		if (!skb_dst(skb)) {
667 668 669 670
			dev->stats.tx_fifo_errors++;
			goto tx_error;
		}

671 672 673
		tun_info = skb_tunnel_info(skb);
		if (tun_info && (tun_info->mode & IP_TUNNEL_INFO_TX) &&
		    ip_tunnel_info_af(tun_info) == AF_INET &&
674
		    tun_info->key.u.ipv4.dst) {
675
			dst = tun_info->key.u.ipv4.dst;
676 677 678
			md = true;
			connected = true;
		}
679
		else if (skb->protocol == htons(ETH_P_IP)) {
680 681 682 683 684 685 686 687 688 689 690 691
			rt = skb_rtable(skb);
			dst = rt_nexthop(rt, inner_iph->daddr);
		}
#if IS_ENABLED(CONFIG_IPV6)
		else if (skb->protocol == htons(ETH_P_IPV6)) {
			const struct in6_addr *addr6;
			struct neighbour *neigh;
			bool do_tx_error_icmp;
			int addr_type;

			neigh = dst_neigh_lookup(skb_dst(skb),
						 &ipv6_hdr(skb)->daddr);
692
			if (!neigh)
693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715
				goto tx_error;

			addr6 = (const struct in6_addr *)&neigh->primary_key;
			addr_type = ipv6_addr_type(addr6);

			if (addr_type == IPV6_ADDR_ANY) {
				addr6 = &ipv6_hdr(skb)->daddr;
				addr_type = ipv6_addr_type(addr6);
			}

			if ((addr_type & IPV6_ADDR_COMPATv4) == 0)
				do_tx_error_icmp = true;
			else {
				do_tx_error_icmp = false;
				dst = addr6->s6_addr32[3];
			}
			neigh_release(neigh);
			if (do_tx_error_icmp)
				goto tx_error_icmp;
		}
#endif
		else
			goto tx_error;
T
Tom Herbert 已提交
716

717 718
		if (!md)
			connected = false;
719 720 721 722 723
	}

	tos = tnl_params->tos;
	if (tos & 0x1) {
		tos &= ~0x1;
T
Tom Herbert 已提交
724
		if (skb->protocol == htons(ETH_P_IP)) {
725
			tos = inner_iph->tos;
T
Tom Herbert 已提交
726 727
			connected = false;
		} else if (skb->protocol == htons(ETH_P_IPV6)) {
728
			tos = ipv6_get_dsfield((const struct ipv6hdr *)inner_iph);
T
Tom Herbert 已提交
729 730
			connected = false;
		}
731 732
	}

733 734
	ip_tunnel_init_flow(&fl4, protocol, dst, tnl_params->saddr,
			    tunnel->parms.o_key, RT_TOS(tos), tunnel->parms.link,
735
			    tunnel->fwmark, skb_get_hash(skb));
T
Tom Herbert 已提交
736

737 738 739
	if (ip_tunnel_encap(skb, tunnel, &protocol, &fl4) < 0)
		goto tx_error;

740 741 742 743 744 745 746 747 748
	if (connected && md) {
		use_cache = ip_tunnel_dst_cache_usable(skb, tun_info);
		if (use_cache)
			rt = dst_cache_get_ip4(&tun_info->dst_cache,
					       &fl4.saddr);
	} else {
		rt = connected ? dst_cache_get_ip4(&tunnel->dst_cache,
						&fl4.saddr) : NULL;
	}
T
Tom Herbert 已提交
749 750 751 752 753 754 755 756

	if (!rt) {
		rt = ip_route_output_key(tunnel->net, &fl4);

		if (IS_ERR(rt)) {
			dev->stats.tx_carrier_errors++;
			goto tx_error;
		}
757 758 759 760
		if (use_cache)
			dst_cache_set_ip4(&tun_info->dst_cache, &rt->dst,
					  fl4.saddr);
		else if (!md && connected)
761 762
			dst_cache_set_ip4(&tunnel->dst_cache, &rt->dst,
					  fl4.saddr);
763
	}
T
Tom Herbert 已提交
764

765
	if (rt->dst.dev == dev) {
766 767 768 769 770
		ip_rt_put(rt);
		dev->stats.collisions++;
		goto tx_error;
	}

771 772
	if (tnl_update_pmtu(dev, skb, rt, tnl_params->frag_off, inner_iph,
			    0, 0, false)) {
773 774
		ip_rt_put(rt);
		goto tx_error;
775 776 777 778 779 780 781 782 783 784 785 786
	}

	if (tunnel->err_count > 0) {
		if (time_before(jiffies,
				tunnel->err_time + IPTUNNEL_ERR_TIMEO)) {
			tunnel->err_count--;

			dst_link_failure(skb);
		} else
			tunnel->err_count = 0;
	}

787
	tos = ip_tunnel_ecn_encap(tos, inner_iph, skb);
788 789 790 791 792 793 794 795 796 797 798 799
	ttl = tnl_params->ttl;
	if (ttl == 0) {
		if (skb->protocol == htons(ETH_P_IP))
			ttl = inner_iph->ttl;
#if IS_ENABLED(CONFIG_IPV6)
		else if (skb->protocol == htons(ETH_P_IPV6))
			ttl = ((const struct ipv6hdr *)inner_iph)->hop_limit;
#endif
		else
			ttl = ip4_dst_hoplimit(&rt->dst);
	}

800
	df = tnl_params->frag_off;
801
	if (skb->protocol == htons(ETH_P_IP) && !tunnel->ignore_df)
802 803
		df |= (inner_iph->frag_off&htons(IP_DF));

804
	max_headroom = LL_RESERVED_SPACE(rt->dst.dev) + sizeof(struct iphdr)
805
			+ rt->dst.header_len + ip_encap_hlen(&tunnel->encap);
806
	if (max_headroom > dev->needed_headroom)
807
		dev->needed_headroom = max_headroom;
808 809

	if (skb_cow_head(skb, dev->needed_headroom)) {
810
		ip_rt_put(rt);
811
		dev->stats.tx_dropped++;
E
Eric Dumazet 已提交
812
		kfree_skb(skb);
813
		return;
814 815
	}

816 817
	iptunnel_xmit(NULL, rt, skb, fl4.saddr, fl4.daddr, protocol, tos, ttl,
		      df, !net_eq(tunnel->net, dev_net(dev)));
818 819 820 821 822 823 824 825
	return;

#if IS_ENABLED(CONFIG_IPV6)
tx_error_icmp:
	dst_link_failure(skb);
#endif
tx_error:
	dev->stats.tx_errors++;
E
Eric Dumazet 已提交
826
	kfree_skb(skb);
827 828 829 830 831 832 833
}
EXPORT_SYMBOL_GPL(ip_tunnel_xmit);

static void ip_tunnel_update(struct ip_tunnel_net *itn,
			     struct ip_tunnel *t,
			     struct net_device *dev,
			     struct ip_tunnel_parm *p,
834 835
			     bool set_mtu,
			     __u32 fwmark)
836
{
837
	ip_tunnel_del(itn, t);
838 839 840 841 842 843 844 845 846 847 848 849 850 851
	t->parms.iph.saddr = p->iph.saddr;
	t->parms.iph.daddr = p->iph.daddr;
	t->parms.i_key = p->i_key;
	t->parms.o_key = p->o_key;
	if (dev->type != ARPHRD_ETHER) {
		memcpy(dev->dev_addr, &p->iph.saddr, 4);
		memcpy(dev->broadcast, &p->iph.daddr, 4);
	}
	ip_tunnel_add(itn, t);

	t->parms.iph.ttl = p->iph.ttl;
	t->parms.iph.tos = p->iph.tos;
	t->parms.iph.frag_off = p->iph.frag_off;

852
	if (t->parms.link != p->link || t->fwmark != fwmark) {
853 854 855
		int mtu;

		t->parms.link = p->link;
856
		t->fwmark = fwmark;
857 858 859 860
		mtu = ip_tunnel_bind_dev(dev);
		if (set_mtu)
			dev->mtu = mtu;
	}
861
	dst_cache_reset(&t->dst_cache);
862 863 864
	netdev_state_change(dev);
}

865
int ip_tunnel_ctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd)
866 867
{
	int err = 0;
868 869 870
	struct ip_tunnel *t = netdev_priv(dev);
	struct net *net = t->net;
	struct ip_tunnel_net *itn = net_generic(net, t->ip_tnl_net_id);
871 872 873

	switch (cmd) {
	case SIOCGETTUNNEL:
874
		if (dev == itn->fb_tunnel_dev) {
875
			t = ip_tunnel_find(itn, p, itn->fb_tunnel_dev->type);
876
			if (!t)
877 878
				t = netdev_priv(dev);
		}
879 880 881 882 883 884 885 886 887 888
		memcpy(p, &t->parms, sizeof(*p));
		break;

	case SIOCADDTUNNEL:
	case SIOCCHGTUNNEL:
		err = -EPERM;
		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
			goto done;
		if (p->iph.ttl)
			p->iph.frag_off |= htons(IP_DF);
889 890 891 892 893 894
		if (!(p->i_flags & VTI_ISVTI)) {
			if (!(p->i_flags & TUNNEL_KEY))
				p->i_key = 0;
			if (!(p->o_flags & TUNNEL_KEY))
				p->o_key = 0;
		}
895

896
		t = ip_tunnel_find(itn, p, itn->type);
897

898 899 900 901 902 903 904 905
		if (cmd == SIOCADDTUNNEL) {
			if (!t) {
				t = ip_tunnel_create(net, itn, p);
				err = PTR_ERR_OR_ZERO(t);
				break;
			}

			err = -EEXIST;
D
Duan Jiong 已提交
906
			break;
907
		}
908
		if (dev != itn->fb_tunnel_dev && cmd == SIOCCHGTUNNEL) {
909
			if (t) {
910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932
				if (t->dev != dev) {
					err = -EEXIST;
					break;
				}
			} else {
				unsigned int nflags = 0;

				if (ipv4_is_multicast(p->iph.daddr))
					nflags = IFF_BROADCAST;
				else if (p->iph.daddr)
					nflags = IFF_POINTOPOINT;

				if ((dev->flags^nflags)&(IFF_POINTOPOINT|IFF_BROADCAST)) {
					err = -EINVAL;
					break;
				}

				t = netdev_priv(dev);
			}
		}

		if (t) {
			err = 0;
933
			ip_tunnel_update(itn, t, dev, p, true, 0);
934 935 936
		} else {
			err = -ENOENT;
		}
937 938 939 940 941 942 943 944 945 946
		break;

	case SIOCDELTUNNEL:
		err = -EPERM;
		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
			goto done;

		if (dev == itn->fb_tunnel_dev) {
			err = -ENOENT;
			t = ip_tunnel_find(itn, p, itn->fb_tunnel_dev->type);
947
			if (!t)
948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964
				goto done;
			err = -EPERM;
			if (t == netdev_priv(itn->fb_tunnel_dev))
				goto done;
			dev = t->dev;
		}
		unregister_netdevice(dev);
		err = 0;
		break;

	default:
		err = -EINVAL;
	}

done:
	return err;
}
965 966 967 968 969 970 971 972 973 974 975 976 977 978
EXPORT_SYMBOL_GPL(ip_tunnel_ctl);

int ip_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
	struct ip_tunnel_parm p;
	int err;

	if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
		return -EFAULT;
	err = dev->netdev_ops->ndo_tunnel_ctl(dev, &p, cmd);
	if (!err && copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p)))
		return -EFAULT;
	return err;
}
979 980
EXPORT_SYMBOL_GPL(ip_tunnel_ioctl);

981
int __ip_tunnel_change_mtu(struct net_device *dev, int new_mtu, bool strict)
982 983 984
{
	struct ip_tunnel *tunnel = netdev_priv(dev);
	int t_hlen = tunnel->hlen + sizeof(struct iphdr);
985
	int max_mtu = IP_MAX_MTU - dev->hard_header_len - t_hlen;
986

987
	if (new_mtu < ETH_MIN_MTU)
988
		return -EINVAL;
989 990 991 992 993 994 995 996

	if (new_mtu > max_mtu) {
		if (strict)
			return -EINVAL;

		new_mtu = max_mtu;
	}

997 998 999
	dev->mtu = new_mtu;
	return 0;
}
1000 1001 1002 1003 1004 1005
EXPORT_SYMBOL_GPL(__ip_tunnel_change_mtu);

int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu)
{
	return __ip_tunnel_change_mtu(dev, new_mtu, true);
}
1006 1007 1008 1009 1010 1011 1012
EXPORT_SYMBOL_GPL(ip_tunnel_change_mtu);

static void ip_tunnel_dev_free(struct net_device *dev)
{
	struct ip_tunnel *tunnel = netdev_priv(dev);

	gro_cells_destroy(&tunnel->gro_cells);
1013
	dst_cache_destroy(&tunnel->dst_cache);
1014 1015 1016 1017 1018 1019 1020 1021
	free_percpu(dev->tstats);
}

void ip_tunnel_dellink(struct net_device *dev, struct list_head *head)
{
	struct ip_tunnel *tunnel = netdev_priv(dev);
	struct ip_tunnel_net *itn;

N
Nicolas Dichtel 已提交
1022
	itn = net_generic(tunnel->net, tunnel->ip_tnl_net_id);
1023 1024

	if (itn->fb_tunnel_dev != dev) {
1025
		ip_tunnel_del(itn, netdev_priv(dev));
1026 1027 1028 1029 1030
		unregister_netdevice_queue(dev, head);
	}
}
EXPORT_SYMBOL_GPL(ip_tunnel_dellink);

1031 1032 1033 1034 1035 1036 1037 1038
struct net *ip_tunnel_get_link_net(const struct net_device *dev)
{
	struct ip_tunnel *tunnel = netdev_priv(dev);

	return tunnel->net;
}
EXPORT_SYMBOL(ip_tunnel_get_link_net);

1039 1040 1041 1042 1043 1044 1045 1046
int ip_tunnel_get_iflink(const struct net_device *dev)
{
	struct ip_tunnel *tunnel = netdev_priv(dev);

	return tunnel->parms.link;
}
EXPORT_SYMBOL(ip_tunnel_get_iflink);

1047
int ip_tunnel_init_net(struct net *net, unsigned int ip_tnl_net_id,
1048 1049 1050 1051
				  struct rtnl_link_ops *ops, char *devname)
{
	struct ip_tunnel_net *itn = net_generic(net, ip_tnl_net_id);
	struct ip_tunnel_parm parms;
1052
	unsigned int i;
1053

1054
	itn->rtnl_link_ops = ops;
1055 1056
	for (i = 0; i < IP_TNL_HASH_SIZE; i++)
		INIT_HLIST_HEAD(&itn->tunnels[i]);
1057

1058 1059 1060 1061 1062
	if (!ops || !net_has_fallback_tunnels(net)) {
		struct ip_tunnel_net *it_init_net;

		it_init_net = net_generic(&init_net, ip_tnl_net_id);
		itn->type = it_init_net->type;
1063 1064 1065
		itn->fb_tunnel_dev = NULL;
		return 0;
	}
1066

1067 1068 1069 1070 1071 1072
	memset(&parms, 0, sizeof(parms));
	if (devname)
		strlcpy(parms.name, devname, IFNAMSIZ);

	rtnl_lock();
	itn->fb_tunnel_dev = __ip_tunnel_create(net, ops, &parms);
1073 1074 1075
	/* FB netdevice is special: we have one, and only one per netns.
	 * Allowing to move it to another netns is clearly unsafe.
	 */
1076
	if (!IS_ERR(itn->fb_tunnel_dev)) {
1077
		itn->fb_tunnel_dev->features |= NETIF_F_NETNS_LOCAL;
1078
		itn->fb_tunnel_dev->mtu = ip_tunnel_bind_dev(itn->fb_tunnel_dev);
1079
		ip_tunnel_add(itn, netdev_priv(itn->fb_tunnel_dev));
1080
		itn->type = itn->fb_tunnel_dev->type;
1081
	}
1082
	rtnl_unlock();
1083

S
Sachin Kamat 已提交
1084
	return PTR_ERR_OR_ZERO(itn->fb_tunnel_dev);
1085 1086 1087
}
EXPORT_SYMBOL_GPL(ip_tunnel_init_net);

1088 1089
static void ip_tunnel_destroy(struct net *net, struct ip_tunnel_net *itn,
			      struct list_head *head,
N
Nicolas Dichtel 已提交
1090
			      struct rtnl_link_ops *ops)
1091
{
N
Nicolas Dichtel 已提交
1092
	struct net_device *dev, *aux;
1093 1094
	int h;

N
Nicolas Dichtel 已提交
1095 1096 1097 1098
	for_each_netdev_safe(net, dev, aux)
		if (dev->rtnl_link_ops == ops)
			unregister_netdevice_queue(dev, head);

1099 1100 1101 1102 1103 1104
	for (h = 0; h < IP_TNL_HASH_SIZE; h++) {
		struct ip_tunnel *t;
		struct hlist_node *n;
		struct hlist_head *thead = &itn->tunnels[h];

		hlist_for_each_entry_safe(t, n, thead, hash_node)
N
Nicolas Dichtel 已提交
1105 1106 1107 1108 1109
			/* If dev is in the same netns, it has already
			 * been added to the list by the previous loop.
			 */
			if (!net_eq(dev_net(t->dev), net))
				unregister_netdevice_queue(t->dev, head);
1110 1111 1112
	}
}

1113 1114
void ip_tunnel_delete_nets(struct list_head *net_list, unsigned int id,
			   struct rtnl_link_ops *ops)
1115
{
1116 1117
	struct ip_tunnel_net *itn;
	struct net *net;
1118 1119 1120
	LIST_HEAD(list);

	rtnl_lock();
1121 1122
	list_for_each_entry(net, net_list, exit_list) {
		itn = net_generic(net, id);
1123
		ip_tunnel_destroy(net, itn, &list, ops);
1124
	}
1125 1126 1127
	unregister_netdevice_many(&list);
	rtnl_unlock();
}
1128
EXPORT_SYMBOL_GPL(ip_tunnel_delete_nets);
1129 1130

int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[],
1131
		      struct ip_tunnel_parm *p, __u32 fwmark)
1132 1133 1134 1135 1136 1137 1138 1139 1140 1141
{
	struct ip_tunnel *nt;
	struct net *net = dev_net(dev);
	struct ip_tunnel_net *itn;
	int mtu;
	int err;

	nt = netdev_priv(dev);
	itn = net_generic(net, nt->ip_tnl_net_id);

1142 1143 1144 1145 1146 1147 1148
	if (nt->collect_md) {
		if (rtnl_dereference(itn->collect_md_tun))
			return -EEXIST;
	} else {
		if (ip_tunnel_find(itn, p, dev->type))
			return -EEXIST;
	}
1149

N
Nicolas Dichtel 已提交
1150
	nt->net = net;
1151
	nt->parms = *p;
1152
	nt->fwmark = fwmark;
1153 1154
	err = register_netdevice(dev);
	if (err)
1155
		goto err_register_netdevice;
1156 1157 1158 1159 1160

	if (dev->type == ARPHRD_ETHER && !tb[IFLA_ADDRESS])
		eth_hw_addr_random(dev);

	mtu = ip_tunnel_bind_dev(dev);
1161
	if (tb[IFLA_MTU]) {
1162
		unsigned int max = IP_MAX_MTU - dev->hard_header_len - nt->hlen;
1163

1164 1165
		mtu = clamp(dev->mtu, (unsigned int)ETH_MIN_MTU,
			    (unsigned int)(max - sizeof(struct iphdr)));
1166
	}
1167

1168 1169 1170
	err = dev_set_mtu(dev, mtu);
	if (err)
		goto err_dev_set_mtu;
1171 1172

	ip_tunnel_add(itn, nt);
1173 1174 1175 1176 1177
	return 0;

err_dev_set_mtu:
	unregister_netdevice(dev);
err_register_netdevice:
1178 1179 1180 1181 1182
	return err;
}
EXPORT_SYMBOL_GPL(ip_tunnel_newlink);

int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[],
1183
			 struct ip_tunnel_parm *p, __u32 fwmark)
1184
{
N
Nicolas Dichtel 已提交
1185
	struct ip_tunnel *t;
1186
	struct ip_tunnel *tunnel = netdev_priv(dev);
N
Nicolas Dichtel 已提交
1187
	struct net *net = tunnel->net;
1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198
	struct ip_tunnel_net *itn = net_generic(net, tunnel->ip_tnl_net_id);

	if (dev == itn->fb_tunnel_dev)
		return -EINVAL;

	t = ip_tunnel_find(itn, p, dev->type);

	if (t) {
		if (t->dev != dev)
			return -EEXIST;
	} else {
N
Nicolas Dichtel 已提交
1199
		t = tunnel;
1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214

		if (dev->type != ARPHRD_ETHER) {
			unsigned int nflags = 0;

			if (ipv4_is_multicast(p->iph.daddr))
				nflags = IFF_BROADCAST;
			else if (p->iph.daddr)
				nflags = IFF_POINTOPOINT;

			if ((dev->flags ^ nflags) &
			    (IFF_POINTOPOINT | IFF_BROADCAST))
				return -EINVAL;
		}
	}

1215
	ip_tunnel_update(itn, t, dev, p, !tb[IFLA_MTU], fwmark);
1216 1217 1218 1219 1220 1221 1222 1223
	return 0;
}
EXPORT_SYMBOL_GPL(ip_tunnel_changelink);

int ip_tunnel_init(struct net_device *dev)
{
	struct ip_tunnel *tunnel = netdev_priv(dev);
	struct iphdr *iph = &tunnel->parms.iph;
1224
	int err;
1225

1226 1227
	dev->needs_free_netdev = true;
	dev->priv_destructor = ip_tunnel_dev_free;
1228
	dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
1229 1230 1231
	if (!dev->tstats)
		return -ENOMEM;

1232 1233
	err = dst_cache_init(&tunnel->dst_cache, GFP_KERNEL);
	if (err) {
1234
		free_percpu(dev->tstats);
1235
		return err;
1236 1237
	}

1238 1239
	err = gro_cells_init(&tunnel->gro_cells, dev);
	if (err) {
1240
		dst_cache_destroy(&tunnel->dst_cache);
1241 1242 1243 1244 1245
		free_percpu(dev->tstats);
		return err;
	}

	tunnel->dev = dev;
N
Nicolas Dichtel 已提交
1246
	tunnel->net = dev_net(dev);
1247 1248 1249 1250
	strcpy(tunnel->parms.name, dev->name);
	iph->version		= 4;
	iph->ihl		= 5;

1251
	if (tunnel->collect_md)
1252
		netif_keep_dst(dev);
1253 1254 1255 1256 1257 1258 1259
	return 0;
}
EXPORT_SYMBOL_GPL(ip_tunnel_init);

void ip_tunnel_uninit(struct net_device *dev)
{
	struct ip_tunnel *tunnel = netdev_priv(dev);
N
Nicolas Dichtel 已提交
1260
	struct net *net = tunnel->net;
1261 1262 1263
	struct ip_tunnel_net *itn;

	itn = net_generic(net, tunnel->ip_tnl_net_id);
1264 1265 1266
	ip_tunnel_del(itn, netdev_priv(dev));
	if (itn->fb_tunnel_dev == dev)
		WRITE_ONCE(itn->fb_tunnel_dev, NULL);
T
Tom Herbert 已提交
1267

1268
	dst_cache_reset(&tunnel->dst_cache);
1269 1270 1271 1272
}
EXPORT_SYMBOL_GPL(ip_tunnel_uninit);

/* Do least required initialization, rest of init is done in tunnel_init call */
1273
void ip_tunnel_setup(struct net_device *dev, unsigned int net_id)
1274 1275 1276 1277 1278 1279 1280
{
	struct ip_tunnel *tunnel = netdev_priv(dev);
	tunnel->ip_tnl_net_id = net_id;
}
EXPORT_SYMBOL_GPL(ip_tunnel_setup);

MODULE_LICENSE("GPL");