blob: 1886cd40a3f6f44d6f63df50c44465415f0a6e45 [file] [log] [blame]
Pravin B Shelarc5441932013-03-25 14:49:35 +00001/*
2 * Copyright (c) 2013 Nicira, Inc.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of version 2 of the GNU General Public
6 * License as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 * 02110-1301, USA
17 */
18
19#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
20
21#include <linux/capability.h>
22#include <linux/module.h>
23#include <linux/types.h>
24#include <linux/kernel.h>
25#include <linux/slab.h>
26#include <linux/uaccess.h>
27#include <linux/skbuff.h>
28#include <linux/netdevice.h>
29#include <linux/in.h>
30#include <linux/tcp.h>
31#include <linux/udp.h>
32#include <linux/if_arp.h>
33#include <linux/mroute.h>
34#include <linux/init.h>
35#include <linux/in6.h>
36#include <linux/inetdevice.h>
37#include <linux/igmp.h>
38#include <linux/netfilter_ipv4.h>
39#include <linux/etherdevice.h>
40#include <linux/if_ether.h>
41#include <linux/if_vlan.h>
42#include <linux/rculist.h>
43
44#include <net/sock.h>
45#include <net/ip.h>
46#include <net/icmp.h>
47#include <net/protocol.h>
48#include <net/ip_tunnels.h>
49#include <net/arp.h>
50#include <net/checksum.h>
51#include <net/dsfield.h>
52#include <net/inet_ecn.h>
53#include <net/xfrm.h>
54#include <net/net_namespace.h>
55#include <net/netns/generic.h>
56#include <net/rtnetlink.h>
57
58#if IS_ENABLED(CONFIG_IPV6)
59#include <net/ipv6.h>
60#include <net/ip6_fib.h>
61#include <net/ip6_route.h>
62#endif
63
Duan Jiong967680e2014-01-19 16:43:42 +080064static unsigned int ip_tunnel_hash(__be32 key, __be32 remote)
Pravin B Shelarc5441932013-03-25 14:49:35 +000065{
66 return hash_32((__force u32)key ^ (__force u32)remote,
67 IP_TNL_HASH_BITS);
68}
69
Eric Dumazet6c7e7612014-01-16 16:41:19 -080070static void __tunnel_dst_set(struct ip_tunnel_dst *idst,
71 struct dst_entry *dst)
Tom Herbert7d442fa2014-01-02 11:48:26 -080072{
73 struct dst_entry *old_dst;
74
Eric Dumazet6c7e7612014-01-16 16:41:19 -080075 if (dst) {
76 if (dst->flags & DST_NOCACHE)
77 dst = NULL;
78 else
79 dst_clone(dst);
80 }
81 old_dst = xchg((__force struct dst_entry **)&idst->dst, dst);
Tom Herbert7d442fa2014-01-02 11:48:26 -080082 dst_release(old_dst);
Tom Herbert7d442fa2014-01-02 11:48:26 -080083}
84
Eric Dumazet6c7e7612014-01-16 16:41:19 -080085static void tunnel_dst_set(struct ip_tunnel *t, struct dst_entry *dst)
Tom Herbert7d442fa2014-01-02 11:48:26 -080086{
Tom Herbert9a4aa9a2014-01-02 11:48:33 -080087 __tunnel_dst_set(this_cpu_ptr(t->dst_cache), dst);
Tom Herbert7d442fa2014-01-02 11:48:26 -080088}
89
Eric Dumazet6c7e7612014-01-16 16:41:19 -080090static void tunnel_dst_reset(struct ip_tunnel *t)
Tom Herbert7d442fa2014-01-02 11:48:26 -080091{
92 tunnel_dst_set(t, NULL);
93}
94
Tom Herbert9a4aa9a2014-01-02 11:48:33 -080095static void tunnel_dst_reset_all(struct ip_tunnel *t)
96{
97 int i;
98
99 for_each_possible_cpu(i)
100 __tunnel_dst_set(per_cpu_ptr(t->dst_cache, i), NULL);
101}
102
Eric Dumazet6c7e7612014-01-16 16:41:19 -0800103static struct dst_entry *tunnel_dst_get(struct ip_tunnel *t)
Tom Herbert7d442fa2014-01-02 11:48:26 -0800104{
105 struct dst_entry *dst;
106
107 rcu_read_lock();
Tom Herbert9a4aa9a2014-01-02 11:48:33 -0800108 dst = rcu_dereference(this_cpu_ptr(t->dst_cache)->dst);
Tom Herbert7d442fa2014-01-02 11:48:26 -0800109 if (dst)
110 dst_hold(dst);
111 rcu_read_unlock();
112 return dst;
113}
114
Wei Yongjund0eb1f72014-01-08 21:59:30 +0800115static struct dst_entry *tunnel_dst_check(struct ip_tunnel *t, u32 cookie)
Tom Herbert7d442fa2014-01-02 11:48:26 -0800116{
117 struct dst_entry *dst = tunnel_dst_get(t);
118
119 if (dst && dst->obsolete && dst->ops->check(dst, cookie) == NULL) {
120 tunnel_dst_reset(t);
121 return NULL;
122 }
123
124 return dst;
125}
126
Pravin B Shelarc5441932013-03-25 14:49:35 +0000127/* Often modified stats are per cpu, other are shared (netdev->stats) */
128struct rtnl_link_stats64 *ip_tunnel_get_stats64(struct net_device *dev,
129 struct rtnl_link_stats64 *tot)
130{
131 int i;
132
133 for_each_possible_cpu(i) {
Li RongQing8f849852014-01-04 13:57:59 +0800134 const struct pcpu_sw_netstats *tstats =
135 per_cpu_ptr(dev->tstats, i);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000136 u64 rx_packets, rx_bytes, tx_packets, tx_bytes;
137 unsigned int start;
138
139 do {
140 start = u64_stats_fetch_begin_bh(&tstats->syncp);
141 rx_packets = tstats->rx_packets;
142 tx_packets = tstats->tx_packets;
143 rx_bytes = tstats->rx_bytes;
144 tx_bytes = tstats->tx_bytes;
145 } while (u64_stats_fetch_retry_bh(&tstats->syncp, start));
146
147 tot->rx_packets += rx_packets;
148 tot->tx_packets += tx_packets;
149 tot->rx_bytes += rx_bytes;
150 tot->tx_bytes += tx_bytes;
151 }
152
153 tot->multicast = dev->stats.multicast;
154
155 tot->rx_crc_errors = dev->stats.rx_crc_errors;
156 tot->rx_fifo_errors = dev->stats.rx_fifo_errors;
157 tot->rx_length_errors = dev->stats.rx_length_errors;
158 tot->rx_frame_errors = dev->stats.rx_frame_errors;
159 tot->rx_errors = dev->stats.rx_errors;
160
161 tot->tx_fifo_errors = dev->stats.tx_fifo_errors;
162 tot->tx_carrier_errors = dev->stats.tx_carrier_errors;
163 tot->tx_dropped = dev->stats.tx_dropped;
164 tot->tx_aborted_errors = dev->stats.tx_aborted_errors;
165 tot->tx_errors = dev->stats.tx_errors;
166
167 tot->collisions = dev->stats.collisions;
168
169 return tot;
170}
171EXPORT_SYMBOL_GPL(ip_tunnel_get_stats64);
172
173static bool ip_tunnel_key_match(const struct ip_tunnel_parm *p,
174 __be16 flags, __be32 key)
175{
176 if (p->i_flags & TUNNEL_KEY) {
177 if (flags & TUNNEL_KEY)
178 return key == p->i_key;
179 else
180 /* key expected, none present */
181 return false;
182 } else
183 return !(flags & TUNNEL_KEY);
184}
185
186/* Fallback tunnel: no source, no destination, no key, no options
187
188 Tunnel hash table:
189 We require exact key match i.e. if a key is present in packet
190 it will match only tunnel with the same key; if it is not present,
191 it will match only keyless tunnel.
192
193 All keysless packets, if not matched configured keyless tunnels
194 will match fallback tunnel.
195 Given src, dst and key, find appropriate for input tunnel.
196*/
197struct ip_tunnel *ip_tunnel_lookup(struct ip_tunnel_net *itn,
198 int link, __be16 flags,
199 __be32 remote, __be32 local,
200 __be32 key)
201{
202 unsigned int hash;
203 struct ip_tunnel *t, *cand = NULL;
204 struct hlist_head *head;
205
Duan Jiong967680e2014-01-19 16:43:42 +0800206 hash = ip_tunnel_hash(key, remote);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000207 head = &itn->tunnels[hash];
208
209 hlist_for_each_entry_rcu(t, head, hash_node) {
210 if (local != t->parms.iph.saddr ||
211 remote != t->parms.iph.daddr ||
212 !(t->dev->flags & IFF_UP))
213 continue;
214
215 if (!ip_tunnel_key_match(&t->parms, flags, key))
216 continue;
217
218 if (t->parms.link == link)
219 return t;
220 else
221 cand = t;
222 }
223
224 hlist_for_each_entry_rcu(t, head, hash_node) {
225 if (remote != t->parms.iph.daddr ||
226 !(t->dev->flags & IFF_UP))
227 continue;
228
229 if (!ip_tunnel_key_match(&t->parms, flags, key))
230 continue;
231
232 if (t->parms.link == link)
233 return t;
234 else if (!cand)
235 cand = t;
236 }
237
Duan Jiong967680e2014-01-19 16:43:42 +0800238 hash = ip_tunnel_hash(key, 0);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000239 head = &itn->tunnels[hash];
240
241 hlist_for_each_entry_rcu(t, head, hash_node) {
242 if ((local != t->parms.iph.saddr &&
243 (local != t->parms.iph.daddr ||
244 !ipv4_is_multicast(local))) ||
245 !(t->dev->flags & IFF_UP))
246 continue;
247
248 if (!ip_tunnel_key_match(&t->parms, flags, key))
249 continue;
250
251 if (t->parms.link == link)
252 return t;
253 else if (!cand)
254 cand = t;
255 }
256
257 if (flags & TUNNEL_NO_KEY)
258 goto skip_key_lookup;
259
260 hlist_for_each_entry_rcu(t, head, hash_node) {
261 if (t->parms.i_key != key ||
262 !(t->dev->flags & IFF_UP))
263 continue;
264
265 if (t->parms.link == link)
266 return t;
267 else if (!cand)
268 cand = t;
269 }
270
271skip_key_lookup:
272 if (cand)
273 return cand;
274
275 if (itn->fb_tunnel_dev && itn->fb_tunnel_dev->flags & IFF_UP)
276 return netdev_priv(itn->fb_tunnel_dev);
277
278
279 return NULL;
280}
281EXPORT_SYMBOL_GPL(ip_tunnel_lookup);
282
283static struct hlist_head *ip_bucket(struct ip_tunnel_net *itn,
284 struct ip_tunnel_parm *parms)
285{
286 unsigned int h;
287 __be32 remote;
288
289 if (parms->iph.daddr && !ipv4_is_multicast(parms->iph.daddr))
290 remote = parms->iph.daddr;
291 else
292 remote = 0;
293
Duan Jiong967680e2014-01-19 16:43:42 +0800294 h = ip_tunnel_hash(parms->i_key, remote);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000295 return &itn->tunnels[h];
296}
297
298static void ip_tunnel_add(struct ip_tunnel_net *itn, struct ip_tunnel *t)
299{
300 struct hlist_head *head = ip_bucket(itn, &t->parms);
301
302 hlist_add_head_rcu(&t->hash_node, head);
303}
304
305static void ip_tunnel_del(struct ip_tunnel *t)
306{
307 hlist_del_init_rcu(&t->hash_node);
308}
309
310static struct ip_tunnel *ip_tunnel_find(struct ip_tunnel_net *itn,
311 struct ip_tunnel_parm *parms,
312 int type)
313{
314 __be32 remote = parms->iph.daddr;
315 __be32 local = parms->iph.saddr;
316 __be32 key = parms->i_key;
317 int link = parms->link;
318 struct ip_tunnel *t = NULL;
319 struct hlist_head *head = ip_bucket(itn, parms);
320
321 hlist_for_each_entry_rcu(t, head, hash_node) {
322 if (local == t->parms.iph.saddr &&
323 remote == t->parms.iph.daddr &&
324 key == t->parms.i_key &&
325 link == t->parms.link &&
326 type == t->dev->type)
327 break;
328 }
329 return t;
330}
331
332static struct net_device *__ip_tunnel_create(struct net *net,
333 const struct rtnl_link_ops *ops,
334 struct ip_tunnel_parm *parms)
335{
336 int err;
337 struct ip_tunnel *tunnel;
338 struct net_device *dev;
339 char name[IFNAMSIZ];
340
341 if (parms->name[0])
342 strlcpy(name, parms->name, IFNAMSIZ);
343 else {
Pravin B Shelar54a5d382013-03-28 08:21:46 +0000344 if (strlen(ops->kind) > (IFNAMSIZ - 3)) {
Pravin B Shelarc5441932013-03-25 14:49:35 +0000345 err = -E2BIG;
346 goto failed;
347 }
348 strlcpy(name, ops->kind, IFNAMSIZ);
349 strncat(name, "%d", 2);
350 }
351
352 ASSERT_RTNL();
353 dev = alloc_netdev(ops->priv_size, name, ops->setup);
354 if (!dev) {
355 err = -ENOMEM;
356 goto failed;
357 }
358 dev_net_set(dev, net);
359
360 dev->rtnl_link_ops = ops;
361
362 tunnel = netdev_priv(dev);
363 tunnel->parms = *parms;
Nicolas Dichtel5e6700b2013-06-26 16:11:28 +0200364 tunnel->net = net;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000365
366 err = register_netdevice(dev);
367 if (err)
368 goto failed_free;
369
370 return dev;
371
372failed_free:
373 free_netdev(dev);
374failed:
375 return ERR_PTR(err);
376}
377
Tom Herbert7d442fa2014-01-02 11:48:26 -0800378static inline void init_tunnel_flow(struct flowi4 *fl4,
379 int proto,
380 __be32 daddr, __be32 saddr,
381 __be32 key, __u8 tos, int oif)
Pravin B Shelarc5441932013-03-25 14:49:35 +0000382{
383 memset(fl4, 0, sizeof(*fl4));
384 fl4->flowi4_oif = oif;
385 fl4->daddr = daddr;
386 fl4->saddr = saddr;
387 fl4->flowi4_tos = tos;
388 fl4->flowi4_proto = proto;
389 fl4->fl4_gre_key = key;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000390}
391
392static int ip_tunnel_bind_dev(struct net_device *dev)
393{
394 struct net_device *tdev = NULL;
395 struct ip_tunnel *tunnel = netdev_priv(dev);
396 const struct iphdr *iph;
397 int hlen = LL_MAX_HEADER;
398 int mtu = ETH_DATA_LEN;
399 int t_hlen = tunnel->hlen + sizeof(struct iphdr);
400
401 iph = &tunnel->parms.iph;
402
403 /* Guess output device to choose reasonable mtu and needed_headroom */
404 if (iph->daddr) {
405 struct flowi4 fl4;
406 struct rtable *rt;
407
Tom Herbert7d442fa2014-01-02 11:48:26 -0800408 init_tunnel_flow(&fl4, iph->protocol, iph->daddr,
409 iph->saddr, tunnel->parms.o_key,
410 RT_TOS(iph->tos), tunnel->parms.link);
411 rt = ip_route_output_key(tunnel->net, &fl4);
412
Pravin B Shelarc5441932013-03-25 14:49:35 +0000413 if (!IS_ERR(rt)) {
414 tdev = rt->dst.dev;
Eric Dumazet6c7e7612014-01-16 16:41:19 -0800415 tunnel_dst_set(tunnel, &rt->dst);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000416 ip_rt_put(rt);
417 }
418 if (dev->type != ARPHRD_ETHER)
419 dev->flags |= IFF_POINTOPOINT;
420 }
421
422 if (!tdev && tunnel->parms.link)
Nicolas Dichtel6c742e72013-08-13 17:51:11 +0200423 tdev = __dev_get_by_index(tunnel->net, tunnel->parms.link);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000424
425 if (tdev) {
426 hlen = tdev->hard_header_len + tdev->needed_headroom;
427 mtu = tdev->mtu;
428 }
429 dev->iflink = tunnel->parms.link;
430
431 dev->needed_headroom = t_hlen + hlen;
432 mtu -= (dev->hard_header_len + t_hlen);
433
434 if (mtu < 68)
435 mtu = 68;
436
437 return mtu;
438}
439
440static struct ip_tunnel *ip_tunnel_create(struct net *net,
441 struct ip_tunnel_net *itn,
442 struct ip_tunnel_parm *parms)
443{
444 struct ip_tunnel *nt, *fbt;
445 struct net_device *dev;
446
447 BUG_ON(!itn->fb_tunnel_dev);
448 fbt = netdev_priv(itn->fb_tunnel_dev);
449 dev = __ip_tunnel_create(net, itn->fb_tunnel_dev->rtnl_link_ops, parms);
450 if (IS_ERR(dev))
451 return NULL;
452
453 dev->mtu = ip_tunnel_bind_dev(dev);
454
455 nt = netdev_priv(dev);
456 ip_tunnel_add(itn, nt);
457 return nt;
458}
459
460int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb,
461 const struct tnl_ptk_info *tpi, bool log_ecn_error)
462{
Li RongQing8f849852014-01-04 13:57:59 +0800463 struct pcpu_sw_netstats *tstats;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000464 const struct iphdr *iph = ip_hdr(skb);
465 int err;
466
Pravin B Shelarc5441932013-03-25 14:49:35 +0000467#ifdef CONFIG_NET_IPGRE_BROADCAST
468 if (ipv4_is_multicast(iph->daddr)) {
469 /* Looped back packet, drop it! */
470 if (rt_is_output_route(skb_rtable(skb)))
471 goto drop;
472 tunnel->dev->stats.multicast++;
473 skb->pkt_type = PACKET_BROADCAST;
474 }
475#endif
476
477 if ((!(tpi->flags&TUNNEL_CSUM) && (tunnel->parms.i_flags&TUNNEL_CSUM)) ||
478 ((tpi->flags&TUNNEL_CSUM) && !(tunnel->parms.i_flags&TUNNEL_CSUM))) {
479 tunnel->dev->stats.rx_crc_errors++;
480 tunnel->dev->stats.rx_errors++;
481 goto drop;
482 }
483
484 if (tunnel->parms.i_flags&TUNNEL_SEQ) {
485 if (!(tpi->flags&TUNNEL_SEQ) ||
486 (tunnel->i_seqno && (s32)(ntohl(tpi->seq) - tunnel->i_seqno) < 0)) {
487 tunnel->dev->stats.rx_fifo_errors++;
488 tunnel->dev->stats.rx_errors++;
489 goto drop;
490 }
491 tunnel->i_seqno = ntohl(tpi->seq) + 1;
492 }
493
Pravin B Shelarc5441932013-03-25 14:49:35 +0000494 err = IP_ECN_decapsulate(iph, skb);
495 if (unlikely(err)) {
496 if (log_ecn_error)
497 net_info_ratelimited("non-ECT from %pI4 with TOS=%#x\n",
498 &iph->saddr, iph->tos);
499 if (err > 1) {
500 ++tunnel->dev->stats.rx_frame_errors;
501 ++tunnel->dev->stats.rx_errors;
502 goto drop;
503 }
504 }
505
506 tstats = this_cpu_ptr(tunnel->dev->tstats);
507 u64_stats_update_begin(&tstats->syncp);
508 tstats->rx_packets++;
509 tstats->rx_bytes += skb->len;
510 u64_stats_update_end(&tstats->syncp);
511
Alexei Starovoitov81b9eab2013-11-12 14:39:13 -0800512 skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(tunnel->dev)));
513
Pravin B Shelar3d7b46c2013-06-17 17:50:02 -0700514 if (tunnel->dev->type == ARPHRD_ETHER) {
515 skb->protocol = eth_type_trans(skb, tunnel->dev);
516 skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN);
517 } else {
518 skb->dev = tunnel->dev;
519 }
Nicolas Dichtel64261f22013-08-13 17:51:09 +0200520
Pravin B Shelarc5441932013-03-25 14:49:35 +0000521 gro_cells_receive(&tunnel->gro_cells, skb);
522 return 0;
523
524drop:
525 kfree_skb(skb);
526 return 0;
527}
528EXPORT_SYMBOL_GPL(ip_tunnel_rcv);
529
Pravin B Shelar23a36472013-07-02 10:57:33 -0700530static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb,
531 struct rtable *rt, __be16 df)
532{
533 struct ip_tunnel *tunnel = netdev_priv(dev);
Alexander Duyck8c91e162013-07-11 13:12:22 -0700534 int pkt_size = skb->len - tunnel->hlen - dev->hard_header_len;
Pravin B Shelar23a36472013-07-02 10:57:33 -0700535 int mtu;
536
537 if (df)
538 mtu = dst_mtu(&rt->dst) - dev->hard_header_len
539 - sizeof(struct iphdr) - tunnel->hlen;
540 else
541 mtu = skb_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu;
542
543 if (skb_dst(skb))
544 skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu);
545
546 if (skb->protocol == htons(ETH_P_IP)) {
547 if (!skb_is_gso(skb) &&
548 (df & htons(IP_DF)) && mtu < pkt_size) {
549 memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
550 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
551 return -E2BIG;
552 }
553 }
554#if IS_ENABLED(CONFIG_IPV6)
555 else if (skb->protocol == htons(ETH_P_IPV6)) {
556 struct rt6_info *rt6 = (struct rt6_info *)skb_dst(skb);
557
558 if (rt6 && mtu < dst_mtu(skb_dst(skb)) &&
559 mtu >= IPV6_MIN_MTU) {
560 if ((tunnel->parms.iph.daddr &&
561 !ipv4_is_multicast(tunnel->parms.iph.daddr)) ||
562 rt6->rt6i_dst.plen == 128) {
563 rt6->rt6i_flags |= RTF_MODIFIED;
564 dst_metric_set(skb_dst(skb), RTAX_MTU, mtu);
565 }
566 }
567
568 if (!skb_is_gso(skb) && mtu >= IPV6_MIN_MTU &&
569 mtu < pkt_size) {
570 icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
571 return -E2BIG;
572 }
573 }
574#endif
575 return 0;
576}
577
Pravin B Shelarc5441932013-03-25 14:49:35 +0000578void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
Nicolas Dichtelbf3d6a82013-05-27 23:48:15 +0000579 const struct iphdr *tnl_params, const u8 protocol)
Pravin B Shelarc5441932013-03-25 14:49:35 +0000580{
581 struct ip_tunnel *tunnel = netdev_priv(dev);
582 const struct iphdr *inner_iph;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000583 struct flowi4 fl4;
584 u8 tos, ttl;
585 __be16 df;
Tom Herbert7d442fa2014-01-02 11:48:26 -0800586 struct rtable *rt = NULL; /* Route to the other host */
Pravin B Shelarc5441932013-03-25 14:49:35 +0000587 unsigned int max_headroom; /* The extra header space needed */
588 __be32 dst;
Pravin B Shelar0e6fbc52013-06-17 17:49:56 -0700589 int err;
Tom Herbert7d442fa2014-01-02 11:48:26 -0800590 bool connected = true;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000591
592 inner_iph = (const struct iphdr *)skb_inner_network_header(skb);
593
594 dst = tnl_params->daddr;
595 if (dst == 0) {
596 /* NBMA tunnel */
597
598 if (skb_dst(skb) == NULL) {
599 dev->stats.tx_fifo_errors++;
600 goto tx_error;
601 }
602
603 if (skb->protocol == htons(ETH_P_IP)) {
604 rt = skb_rtable(skb);
605 dst = rt_nexthop(rt, inner_iph->daddr);
606 }
607#if IS_ENABLED(CONFIG_IPV6)
608 else if (skb->protocol == htons(ETH_P_IPV6)) {
609 const struct in6_addr *addr6;
610 struct neighbour *neigh;
611 bool do_tx_error_icmp;
612 int addr_type;
613
614 neigh = dst_neigh_lookup(skb_dst(skb),
615 &ipv6_hdr(skb)->daddr);
616 if (neigh == NULL)
617 goto tx_error;
618
619 addr6 = (const struct in6_addr *)&neigh->primary_key;
620 addr_type = ipv6_addr_type(addr6);
621
622 if (addr_type == IPV6_ADDR_ANY) {
623 addr6 = &ipv6_hdr(skb)->daddr;
624 addr_type = ipv6_addr_type(addr6);
625 }
626
627 if ((addr_type & IPV6_ADDR_COMPATv4) == 0)
628 do_tx_error_icmp = true;
629 else {
630 do_tx_error_icmp = false;
631 dst = addr6->s6_addr32[3];
632 }
633 neigh_release(neigh);
634 if (do_tx_error_icmp)
635 goto tx_error_icmp;
636 }
637#endif
638 else
639 goto tx_error;
Tom Herbert7d442fa2014-01-02 11:48:26 -0800640
641 connected = false;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000642 }
643
644 tos = tnl_params->tos;
645 if (tos & 0x1) {
646 tos &= ~0x1;
Tom Herbert7d442fa2014-01-02 11:48:26 -0800647 if (skb->protocol == htons(ETH_P_IP)) {
Pravin B Shelarc5441932013-03-25 14:49:35 +0000648 tos = inner_iph->tos;
Tom Herbert7d442fa2014-01-02 11:48:26 -0800649 connected = false;
650 } else if (skb->protocol == htons(ETH_P_IPV6)) {
Pravin B Shelarc5441932013-03-25 14:49:35 +0000651 tos = ipv6_get_dsfield((const struct ipv6hdr *)inner_iph);
Tom Herbert7d442fa2014-01-02 11:48:26 -0800652 connected = false;
653 }
Pravin B Shelarc5441932013-03-25 14:49:35 +0000654 }
655
Tom Herbert7d442fa2014-01-02 11:48:26 -0800656 init_tunnel_flow(&fl4, protocol, dst, tnl_params->saddr,
657 tunnel->parms.o_key, RT_TOS(tos), tunnel->parms.link);
658
659 if (connected)
660 rt = (struct rtable *)tunnel_dst_check(tunnel, 0);
661
662 if (!rt) {
663 rt = ip_route_output_key(tunnel->net, &fl4);
664
665 if (IS_ERR(rt)) {
666 dev->stats.tx_carrier_errors++;
667 goto tx_error;
668 }
669 if (connected)
Eric Dumazet6c7e7612014-01-16 16:41:19 -0800670 tunnel_dst_set(tunnel, &rt->dst);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000671 }
Tom Herbert7d442fa2014-01-02 11:48:26 -0800672
Pravin B Shelar0e6fbc52013-06-17 17:49:56 -0700673 if (rt->dst.dev == dev) {
Pravin B Shelarc5441932013-03-25 14:49:35 +0000674 ip_rt_put(rt);
675 dev->stats.collisions++;
676 goto tx_error;
677 }
Pravin B Shelarc5441932013-03-25 14:49:35 +0000678
Pravin B Shelar23a36472013-07-02 10:57:33 -0700679 if (tnl_update_pmtu(dev, skb, rt, tnl_params->frag_off)) {
680 ip_rt_put(rt);
681 goto tx_error;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000682 }
Pravin B Shelarc5441932013-03-25 14:49:35 +0000683
684 if (tunnel->err_count > 0) {
685 if (time_before(jiffies,
686 tunnel->err_time + IPTUNNEL_ERR_TIMEO)) {
687 tunnel->err_count--;
688
689 dst_link_failure(skb);
690 } else
691 tunnel->err_count = 0;
692 }
693
Pravin B Shelard4a71b12013-09-25 09:57:47 -0700694 tos = ip_tunnel_ecn_encap(tos, inner_iph, skb);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000695 ttl = tnl_params->ttl;
696 if (ttl == 0) {
697 if (skb->protocol == htons(ETH_P_IP))
698 ttl = inner_iph->ttl;
699#if IS_ENABLED(CONFIG_IPV6)
700 else if (skb->protocol == htons(ETH_P_IPV6))
701 ttl = ((const struct ipv6hdr *)inner_iph)->hop_limit;
702#endif
703 else
704 ttl = ip4_dst_hoplimit(&rt->dst);
705 }
706
Pravin B Shelar23a36472013-07-02 10:57:33 -0700707 df = tnl_params->frag_off;
708 if (skb->protocol == htons(ETH_P_IP))
709 df |= (inner_iph->frag_off&htons(IP_DF));
710
Pravin B Shelar0e6fbc52013-06-17 17:49:56 -0700711 max_headroom = LL_RESERVED_SPACE(rt->dst.dev) + sizeof(struct iphdr)
712 + rt->dst.header_len;
Steffen Klassert3e08f4a2013-10-01 11:33:59 +0200713 if (max_headroom > dev->needed_headroom)
Pravin B Shelarc5441932013-03-25 14:49:35 +0000714 dev->needed_headroom = max_headroom;
Steffen Klassert3e08f4a2013-10-01 11:33:59 +0200715
716 if (skb_cow_head(skb, dev->needed_headroom)) {
717 dev->stats.tx_dropped++;
Eric Dumazet3acfa1e2014-01-18 18:27:49 -0800718 kfree_skb(skb);
Steffen Klassert3e08f4a2013-10-01 11:33:59 +0200719 return;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000720 }
721
Nicolas Dichtel8b7ed2d2013-09-02 15:34:54 +0200722 err = iptunnel_xmit(rt, skb, fl4.saddr, fl4.daddr, protocol,
Pravin B Shelard4a71b12013-09-25 09:57:47 -0700723 tos, ttl, df, !net_eq(tunnel->net, dev_net(dev)));
Pravin B Shelar0e6fbc52013-06-17 17:49:56 -0700724 iptunnel_xmit_stats(err, &dev->stats, dev->tstats);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000725
Pravin B Shelarc5441932013-03-25 14:49:35 +0000726 return;
727
728#if IS_ENABLED(CONFIG_IPV6)
729tx_error_icmp:
730 dst_link_failure(skb);
731#endif
732tx_error:
733 dev->stats.tx_errors++;
Eric Dumazet3acfa1e2014-01-18 18:27:49 -0800734 kfree_skb(skb);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000735}
736EXPORT_SYMBOL_GPL(ip_tunnel_xmit);
737
738static void ip_tunnel_update(struct ip_tunnel_net *itn,
739 struct ip_tunnel *t,
740 struct net_device *dev,
741 struct ip_tunnel_parm *p,
742 bool set_mtu)
743{
744 ip_tunnel_del(t);
745 t->parms.iph.saddr = p->iph.saddr;
746 t->parms.iph.daddr = p->iph.daddr;
747 t->parms.i_key = p->i_key;
748 t->parms.o_key = p->o_key;
749 if (dev->type != ARPHRD_ETHER) {
750 memcpy(dev->dev_addr, &p->iph.saddr, 4);
751 memcpy(dev->broadcast, &p->iph.daddr, 4);
752 }
753 ip_tunnel_add(itn, t);
754
755 t->parms.iph.ttl = p->iph.ttl;
756 t->parms.iph.tos = p->iph.tos;
757 t->parms.iph.frag_off = p->iph.frag_off;
758
759 if (t->parms.link != p->link) {
760 int mtu;
761
762 t->parms.link = p->link;
763 mtu = ip_tunnel_bind_dev(dev);
764 if (set_mtu)
765 dev->mtu = mtu;
766 }
Tom Herbert9a4aa9a2014-01-02 11:48:33 -0800767 tunnel_dst_reset_all(t);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000768 netdev_state_change(dev);
769}
770
771int ip_tunnel_ioctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd)
772{
773 int err = 0;
774 struct ip_tunnel *t;
775 struct net *net = dev_net(dev);
776 struct ip_tunnel *tunnel = netdev_priv(dev);
777 struct ip_tunnel_net *itn = net_generic(net, tunnel->ip_tnl_net_id);
778
779 BUG_ON(!itn->fb_tunnel_dev);
780 switch (cmd) {
781 case SIOCGETTUNNEL:
782 t = NULL;
783 if (dev == itn->fb_tunnel_dev)
784 t = ip_tunnel_find(itn, p, itn->fb_tunnel_dev->type);
785 if (t == NULL)
786 t = netdev_priv(dev);
787 memcpy(p, &t->parms, sizeof(*p));
788 break;
789
790 case SIOCADDTUNNEL:
791 case SIOCCHGTUNNEL:
792 err = -EPERM;
793 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
794 goto done;
795 if (p->iph.ttl)
796 p->iph.frag_off |= htons(IP_DF);
797 if (!(p->i_flags&TUNNEL_KEY))
798 p->i_key = 0;
799 if (!(p->o_flags&TUNNEL_KEY))
800 p->o_key = 0;
801
802 t = ip_tunnel_find(itn, p, itn->fb_tunnel_dev->type);
803
804 if (!t && (cmd == SIOCADDTUNNEL))
805 t = ip_tunnel_create(net, itn, p);
806
807 if (dev != itn->fb_tunnel_dev && cmd == SIOCCHGTUNNEL) {
808 if (t != NULL) {
809 if (t->dev != dev) {
810 err = -EEXIST;
811 break;
812 }
813 } else {
814 unsigned int nflags = 0;
815
816 if (ipv4_is_multicast(p->iph.daddr))
817 nflags = IFF_BROADCAST;
818 else if (p->iph.daddr)
819 nflags = IFF_POINTOPOINT;
820
821 if ((dev->flags^nflags)&(IFF_POINTOPOINT|IFF_BROADCAST)) {
822 err = -EINVAL;
823 break;
824 }
825
826 t = netdev_priv(dev);
827 }
828 }
829
830 if (t) {
831 err = 0;
832 ip_tunnel_update(itn, t, dev, p, true);
833 } else
834 err = (cmd == SIOCADDTUNNEL ? -ENOBUFS : -ENOENT);
835 break;
836
837 case SIOCDELTUNNEL:
838 err = -EPERM;
839 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
840 goto done;
841
842 if (dev == itn->fb_tunnel_dev) {
843 err = -ENOENT;
844 t = ip_tunnel_find(itn, p, itn->fb_tunnel_dev->type);
845 if (t == NULL)
846 goto done;
847 err = -EPERM;
848 if (t == netdev_priv(itn->fb_tunnel_dev))
849 goto done;
850 dev = t->dev;
851 }
852 unregister_netdevice(dev);
853 err = 0;
854 break;
855
856 default:
857 err = -EINVAL;
858 }
859
860done:
861 return err;
862}
863EXPORT_SYMBOL_GPL(ip_tunnel_ioctl);
864
865int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu)
866{
867 struct ip_tunnel *tunnel = netdev_priv(dev);
868 int t_hlen = tunnel->hlen + sizeof(struct iphdr);
869
870 if (new_mtu < 68 ||
871 new_mtu > 0xFFF8 - dev->hard_header_len - t_hlen)
872 return -EINVAL;
873 dev->mtu = new_mtu;
874 return 0;
875}
876EXPORT_SYMBOL_GPL(ip_tunnel_change_mtu);
877
878static void ip_tunnel_dev_free(struct net_device *dev)
879{
880 struct ip_tunnel *tunnel = netdev_priv(dev);
881
882 gro_cells_destroy(&tunnel->gro_cells);
Tom Herbert9a4aa9a2014-01-02 11:48:33 -0800883 free_percpu(tunnel->dst_cache);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000884 free_percpu(dev->tstats);
885 free_netdev(dev);
886}
887
888void ip_tunnel_dellink(struct net_device *dev, struct list_head *head)
889{
Pravin B Shelarc5441932013-03-25 14:49:35 +0000890 struct ip_tunnel *tunnel = netdev_priv(dev);
891 struct ip_tunnel_net *itn;
892
Nicolas Dichtel6c742e72013-08-13 17:51:11 +0200893 itn = net_generic(tunnel->net, tunnel->ip_tnl_net_id);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000894
895 if (itn->fb_tunnel_dev != dev) {
896 ip_tunnel_del(netdev_priv(dev));
897 unregister_netdevice_queue(dev, head);
898 }
899}
900EXPORT_SYMBOL_GPL(ip_tunnel_dellink);
901
Eric Dumazetd3b6f612013-06-07 13:26:05 -0700902int ip_tunnel_init_net(struct net *net, int ip_tnl_net_id,
Pravin B Shelarc5441932013-03-25 14:49:35 +0000903 struct rtnl_link_ops *ops, char *devname)
904{
905 struct ip_tunnel_net *itn = net_generic(net, ip_tnl_net_id);
906 struct ip_tunnel_parm parms;
stephen hemminger6261d982013-08-05 22:51:37 -0700907 unsigned int i;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000908
stephen hemminger6261d982013-08-05 22:51:37 -0700909 for (i = 0; i < IP_TNL_HASH_SIZE; i++)
910 INIT_HLIST_HEAD(&itn->tunnels[i]);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000911
912 if (!ops) {
913 itn->fb_tunnel_dev = NULL;
914 return 0;
915 }
stephen hemminger6261d982013-08-05 22:51:37 -0700916
Pravin B Shelarc5441932013-03-25 14:49:35 +0000917 memset(&parms, 0, sizeof(parms));
918 if (devname)
919 strlcpy(parms.name, devname, IFNAMSIZ);
920
921 rtnl_lock();
922 itn->fb_tunnel_dev = __ip_tunnel_create(net, ops, &parms);
Dan Carpenterea857f22013-08-19 10:05:10 +0300923 /* FB netdevice is special: we have one, and only one per netns.
924 * Allowing to move it to another netns is clearly unsafe.
925 */
Steffen Klassert67013282013-10-01 11:34:48 +0200926 if (!IS_ERR(itn->fb_tunnel_dev)) {
Dan Carpenterb4de77a2013-08-23 11:15:37 +0300927 itn->fb_tunnel_dev->features |= NETIF_F_NETNS_LOCAL;
Steffen Klassert67013282013-10-01 11:34:48 +0200928 ip_tunnel_add(itn, netdev_priv(itn->fb_tunnel_dev));
929 }
Dan Carpenterb4de77a2013-08-23 11:15:37 +0300930 rtnl_unlock();
Pravin B Shelarc5441932013-03-25 14:49:35 +0000931
Dan Carpenterb4de77a2013-08-23 11:15:37 +0300932 return PTR_RET(itn->fb_tunnel_dev);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000933}
934EXPORT_SYMBOL_GPL(ip_tunnel_init_net);
935
Nicolas Dichtel6c742e72013-08-13 17:51:11 +0200936static void ip_tunnel_destroy(struct ip_tunnel_net *itn, struct list_head *head,
937 struct rtnl_link_ops *ops)
Pravin B Shelarc5441932013-03-25 14:49:35 +0000938{
Nicolas Dichtel6c742e72013-08-13 17:51:11 +0200939 struct net *net = dev_net(itn->fb_tunnel_dev);
940 struct net_device *dev, *aux;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000941 int h;
942
Nicolas Dichtel6c742e72013-08-13 17:51:11 +0200943 for_each_netdev_safe(net, dev, aux)
944 if (dev->rtnl_link_ops == ops)
945 unregister_netdevice_queue(dev, head);
946
Pravin B Shelarc5441932013-03-25 14:49:35 +0000947 for (h = 0; h < IP_TNL_HASH_SIZE; h++) {
948 struct ip_tunnel *t;
949 struct hlist_node *n;
950 struct hlist_head *thead = &itn->tunnels[h];
951
952 hlist_for_each_entry_safe(t, n, thead, hash_node)
Nicolas Dichtel6c742e72013-08-13 17:51:11 +0200953 /* If dev is in the same netns, it has already
954 * been added to the list by the previous loop.
955 */
956 if (!net_eq(dev_net(t->dev), net))
957 unregister_netdevice_queue(t->dev, head);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000958 }
Pravin B Shelarc5441932013-03-25 14:49:35 +0000959}
960
Nicolas Dichtel6c742e72013-08-13 17:51:11 +0200961void ip_tunnel_delete_net(struct ip_tunnel_net *itn, struct rtnl_link_ops *ops)
Pravin B Shelarc5441932013-03-25 14:49:35 +0000962{
963 LIST_HEAD(list);
964
965 rtnl_lock();
Nicolas Dichtel6c742e72013-08-13 17:51:11 +0200966 ip_tunnel_destroy(itn, &list, ops);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000967 unregister_netdevice_many(&list);
968 rtnl_unlock();
Pravin B Shelarc5441932013-03-25 14:49:35 +0000969}
970EXPORT_SYMBOL_GPL(ip_tunnel_delete_net);
971
972int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[],
973 struct ip_tunnel_parm *p)
974{
975 struct ip_tunnel *nt;
976 struct net *net = dev_net(dev);
977 struct ip_tunnel_net *itn;
978 int mtu;
979 int err;
980
981 nt = netdev_priv(dev);
982 itn = net_generic(net, nt->ip_tnl_net_id);
983
984 if (ip_tunnel_find(itn, p, dev->type))
985 return -EEXIST;
986
Nicolas Dichtel5e6700b2013-06-26 16:11:28 +0200987 nt->net = net;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000988 nt->parms = *p;
989 err = register_netdevice(dev);
990 if (err)
991 goto out;
992
993 if (dev->type == ARPHRD_ETHER && !tb[IFLA_ADDRESS])
994 eth_hw_addr_random(dev);
995
996 mtu = ip_tunnel_bind_dev(dev);
997 if (!tb[IFLA_MTU])
998 dev->mtu = mtu;
999
1000 ip_tunnel_add(itn, nt);
1001
1002out:
1003 return err;
1004}
1005EXPORT_SYMBOL_GPL(ip_tunnel_newlink);
1006
1007int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[],
1008 struct ip_tunnel_parm *p)
1009{
Nicolas Dichtel6c742e72013-08-13 17:51:11 +02001010 struct ip_tunnel *t;
Pravin B Shelarc5441932013-03-25 14:49:35 +00001011 struct ip_tunnel *tunnel = netdev_priv(dev);
Nicolas Dichtel6c742e72013-08-13 17:51:11 +02001012 struct net *net = tunnel->net;
Pravin B Shelarc5441932013-03-25 14:49:35 +00001013 struct ip_tunnel_net *itn = net_generic(net, tunnel->ip_tnl_net_id);
1014
1015 if (dev == itn->fb_tunnel_dev)
1016 return -EINVAL;
1017
Pravin B Shelarc5441932013-03-25 14:49:35 +00001018 t = ip_tunnel_find(itn, p, dev->type);
1019
1020 if (t) {
1021 if (t->dev != dev)
1022 return -EEXIST;
1023 } else {
Nicolas Dichtel6c742e72013-08-13 17:51:11 +02001024 t = tunnel;
Pravin B Shelarc5441932013-03-25 14:49:35 +00001025
1026 if (dev->type != ARPHRD_ETHER) {
1027 unsigned int nflags = 0;
1028
1029 if (ipv4_is_multicast(p->iph.daddr))
1030 nflags = IFF_BROADCAST;
1031 else if (p->iph.daddr)
1032 nflags = IFF_POINTOPOINT;
1033
1034 if ((dev->flags ^ nflags) &
1035 (IFF_POINTOPOINT | IFF_BROADCAST))
1036 return -EINVAL;
1037 }
1038 }
1039
1040 ip_tunnel_update(itn, t, dev, p, !tb[IFLA_MTU]);
1041 return 0;
1042}
1043EXPORT_SYMBOL_GPL(ip_tunnel_changelink);
1044
1045int ip_tunnel_init(struct net_device *dev)
1046{
1047 struct ip_tunnel *tunnel = netdev_priv(dev);
1048 struct iphdr *iph = &tunnel->parms.iph;
John Stultz827da442013-10-07 15:51:58 -07001049 int i, err;
Pravin B Shelarc5441932013-03-25 14:49:35 +00001050
1051 dev->destructor = ip_tunnel_dev_free;
Li RongQing8f849852014-01-04 13:57:59 +08001052 dev->tstats = alloc_percpu(struct pcpu_sw_netstats);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001053 if (!dev->tstats)
1054 return -ENOMEM;
1055
John Stultz827da442013-10-07 15:51:58 -07001056 for_each_possible_cpu(i) {
Li RongQing8f849852014-01-04 13:57:59 +08001057 struct pcpu_sw_netstats *ipt_stats;
John Stultz827da442013-10-07 15:51:58 -07001058 ipt_stats = per_cpu_ptr(dev->tstats, i);
1059 u64_stats_init(&ipt_stats->syncp);
1060 }
1061
Tom Herbert9a4aa9a2014-01-02 11:48:33 -08001062 tunnel->dst_cache = alloc_percpu(struct ip_tunnel_dst);
1063 if (!tunnel->dst_cache) {
1064 free_percpu(dev->tstats);
1065 return -ENOMEM;
1066 }
1067
Pravin B Shelarc5441932013-03-25 14:49:35 +00001068 err = gro_cells_init(&tunnel->gro_cells, dev);
1069 if (err) {
Tom Herbert9a4aa9a2014-01-02 11:48:33 -08001070 free_percpu(tunnel->dst_cache);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001071 free_percpu(dev->tstats);
1072 return err;
1073 }
1074
1075 tunnel->dev = dev;
Nicolas Dichtel6c742e72013-08-13 17:51:11 +02001076 tunnel->net = dev_net(dev);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001077 strcpy(tunnel->parms.name, dev->name);
1078 iph->version = 4;
1079 iph->ihl = 5;
1080
1081 return 0;
1082}
1083EXPORT_SYMBOL_GPL(ip_tunnel_init);
1084
1085void ip_tunnel_uninit(struct net_device *dev)
1086{
Pravin B Shelarc5441932013-03-25 14:49:35 +00001087 struct ip_tunnel *tunnel = netdev_priv(dev);
Nicolas Dichtel6c742e72013-08-13 17:51:11 +02001088 struct net *net = tunnel->net;
Pravin B Shelarc5441932013-03-25 14:49:35 +00001089 struct ip_tunnel_net *itn;
1090
1091 itn = net_generic(net, tunnel->ip_tnl_net_id);
1092 /* fb_tunnel_dev will be unregisted in net-exit call. */
1093 if (itn->fb_tunnel_dev != dev)
1094 ip_tunnel_del(netdev_priv(dev));
Tom Herbert7d442fa2014-01-02 11:48:26 -08001095
Tom Herbert9a4aa9a2014-01-02 11:48:33 -08001096 tunnel_dst_reset_all(tunnel);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001097}
1098EXPORT_SYMBOL_GPL(ip_tunnel_uninit);
1099
1100/* Do least required initialization, rest of init is done in tunnel_init call */
1101void ip_tunnel_setup(struct net_device *dev, int net_id)
1102{
1103 struct ip_tunnel *tunnel = netdev_priv(dev);
1104 tunnel->ip_tnl_net_id = net_id;
1105}
1106EXPORT_SYMBOL_GPL(ip_tunnel_setup);
1107
1108MODULE_LICENSE("GPL");