blob: 4fff64418fb2ebfcf47b4d521b801d0fc23eb074 [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>
Sachin Kamat27d79f32014-01-27 12:13:57 +053043#include <linux/err.h>
Pravin B Shelarc5441932013-03-25 14:49:35 +000044
45#include <net/sock.h>
46#include <net/ip.h>
47#include <net/icmp.h>
48#include <net/protocol.h>
49#include <net/ip_tunnels.h>
50#include <net/arp.h>
51#include <net/checksum.h>
52#include <net/dsfield.h>
53#include <net/inet_ecn.h>
54#include <net/xfrm.h>
55#include <net/net_namespace.h>
56#include <net/netns/generic.h>
57#include <net/rtnetlink.h>
58
59#if IS_ENABLED(CONFIG_IPV6)
60#include <net/ipv6.h>
61#include <net/ip6_fib.h>
62#include <net/ip6_route.h>
63#endif
64
Duan Jiong967680e2014-01-19 16:43:42 +080065static unsigned int ip_tunnel_hash(__be32 key, __be32 remote)
Pravin B Shelarc5441932013-03-25 14:49:35 +000066{
67 return hash_32((__force u32)key ^ (__force u32)remote,
68 IP_TNL_HASH_BITS);
69}
70
Eric Dumazet6c7e7612014-01-16 16:41:19 -080071static void __tunnel_dst_set(struct ip_tunnel_dst *idst,
72 struct dst_entry *dst)
Tom Herbert7d442fa2014-01-02 11:48:26 -080073{
74 struct dst_entry *old_dst;
75
Eric Dumazet6c7e7612014-01-16 16:41:19 -080076 if (dst) {
77 if (dst->flags & DST_NOCACHE)
78 dst = NULL;
79 else
80 dst_clone(dst);
81 }
82 old_dst = xchg((__force struct dst_entry **)&idst->dst, dst);
Tom Herbert7d442fa2014-01-02 11:48:26 -080083 dst_release(old_dst);
Tom Herbert7d442fa2014-01-02 11:48:26 -080084}
85
Eric Dumazet6c7e7612014-01-16 16:41:19 -080086static void tunnel_dst_set(struct ip_tunnel *t, struct dst_entry *dst)
Tom Herbert7d442fa2014-01-02 11:48:26 -080087{
Tom Herbert9a4aa9a2014-01-02 11:48:33 -080088 __tunnel_dst_set(this_cpu_ptr(t->dst_cache), dst);
Tom Herbert7d442fa2014-01-02 11:48:26 -080089}
90
Eric Dumazet6c7e7612014-01-16 16:41:19 -080091static void tunnel_dst_reset(struct ip_tunnel *t)
Tom Herbert7d442fa2014-01-02 11:48:26 -080092{
93 tunnel_dst_set(t, NULL);
94}
95
Tom Herbert9a4aa9a2014-01-02 11:48:33 -080096static void tunnel_dst_reset_all(struct ip_tunnel *t)
97{
98 int i;
99
100 for_each_possible_cpu(i)
101 __tunnel_dst_set(per_cpu_ptr(t->dst_cache, i), NULL);
102}
103
Eric Dumazetb045d372014-02-03 12:52:14 -0800104static struct rtable *tunnel_rtable_get(struct ip_tunnel *t, u32 cookie)
Tom Herbert7d442fa2014-01-02 11:48:26 -0800105{
106 struct dst_entry *dst;
107
108 rcu_read_lock();
Tom Herbert9a4aa9a2014-01-02 11:48:33 -0800109 dst = rcu_dereference(this_cpu_ptr(t->dst_cache)->dst);
Eric Dumazetb045d372014-02-03 12:52:14 -0800110 if (dst) {
111 if (dst->obsolete && dst->ops->check(dst, cookie) == NULL) {
112 rcu_read_unlock();
113 tunnel_dst_reset(t);
114 return NULL;
115 }
Tom Herbert7d442fa2014-01-02 11:48:26 -0800116 dst_hold(dst);
Tom Herbert7d442fa2014-01-02 11:48:26 -0800117 }
Eric Dumazetb045d372014-02-03 12:52:14 -0800118 rcu_read_unlock();
119 return (struct rtable *)dst;
Tom Herbert7d442fa2014-01-02 11:48:26 -0800120}
121
Pravin B Shelarc5441932013-03-25 14:49:35 +0000122/* Often modified stats are per cpu, other are shared (netdev->stats) */
123struct rtnl_link_stats64 *ip_tunnel_get_stats64(struct net_device *dev,
124 struct rtnl_link_stats64 *tot)
125{
126 int i;
127
128 for_each_possible_cpu(i) {
Li RongQing8f849852014-01-04 13:57:59 +0800129 const struct pcpu_sw_netstats *tstats =
130 per_cpu_ptr(dev->tstats, i);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000131 u64 rx_packets, rx_bytes, tx_packets, tx_bytes;
132 unsigned int start;
133
134 do {
135 start = u64_stats_fetch_begin_bh(&tstats->syncp);
136 rx_packets = tstats->rx_packets;
137 tx_packets = tstats->tx_packets;
138 rx_bytes = tstats->rx_bytes;
139 tx_bytes = tstats->tx_bytes;
140 } while (u64_stats_fetch_retry_bh(&tstats->syncp, start));
141
142 tot->rx_packets += rx_packets;
143 tot->tx_packets += tx_packets;
144 tot->rx_bytes += rx_bytes;
145 tot->tx_bytes += tx_bytes;
146 }
147
148 tot->multicast = dev->stats.multicast;
149
150 tot->rx_crc_errors = dev->stats.rx_crc_errors;
151 tot->rx_fifo_errors = dev->stats.rx_fifo_errors;
152 tot->rx_length_errors = dev->stats.rx_length_errors;
153 tot->rx_frame_errors = dev->stats.rx_frame_errors;
154 tot->rx_errors = dev->stats.rx_errors;
155
156 tot->tx_fifo_errors = dev->stats.tx_fifo_errors;
157 tot->tx_carrier_errors = dev->stats.tx_carrier_errors;
158 tot->tx_dropped = dev->stats.tx_dropped;
159 tot->tx_aborted_errors = dev->stats.tx_aborted_errors;
160 tot->tx_errors = dev->stats.tx_errors;
161
162 tot->collisions = dev->stats.collisions;
163
164 return tot;
165}
166EXPORT_SYMBOL_GPL(ip_tunnel_get_stats64);
167
168static bool ip_tunnel_key_match(const struct ip_tunnel_parm *p,
169 __be16 flags, __be32 key)
170{
171 if (p->i_flags & TUNNEL_KEY) {
172 if (flags & TUNNEL_KEY)
173 return key == p->i_key;
174 else
175 /* key expected, none present */
176 return false;
177 } else
178 return !(flags & TUNNEL_KEY);
179}
180
181/* Fallback tunnel: no source, no destination, no key, no options
182
183 Tunnel hash table:
184 We require exact key match i.e. if a key is present in packet
185 it will match only tunnel with the same key; if it is not present,
186 it will match only keyless tunnel.
187
188 All keysless packets, if not matched configured keyless tunnels
189 will match fallback tunnel.
190 Given src, dst and key, find appropriate for input tunnel.
191*/
192struct ip_tunnel *ip_tunnel_lookup(struct ip_tunnel_net *itn,
193 int link, __be16 flags,
194 __be32 remote, __be32 local,
195 __be32 key)
196{
197 unsigned int hash;
198 struct ip_tunnel *t, *cand = NULL;
199 struct hlist_head *head;
200
Duan Jiong967680e2014-01-19 16:43:42 +0800201 hash = ip_tunnel_hash(key, remote);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000202 head = &itn->tunnels[hash];
203
204 hlist_for_each_entry_rcu(t, head, hash_node) {
205 if (local != t->parms.iph.saddr ||
206 remote != t->parms.iph.daddr ||
207 !(t->dev->flags & IFF_UP))
208 continue;
209
210 if (!ip_tunnel_key_match(&t->parms, flags, key))
211 continue;
212
213 if (t->parms.link == link)
214 return t;
215 else
216 cand = t;
217 }
218
219 hlist_for_each_entry_rcu(t, head, hash_node) {
220 if (remote != t->parms.iph.daddr ||
221 !(t->dev->flags & IFF_UP))
222 continue;
223
224 if (!ip_tunnel_key_match(&t->parms, flags, key))
225 continue;
226
227 if (t->parms.link == link)
228 return t;
229 else if (!cand)
230 cand = t;
231 }
232
Duan Jiong967680e2014-01-19 16:43:42 +0800233 hash = ip_tunnel_hash(key, 0);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000234 head = &itn->tunnels[hash];
235
236 hlist_for_each_entry_rcu(t, head, hash_node) {
237 if ((local != t->parms.iph.saddr &&
238 (local != t->parms.iph.daddr ||
239 !ipv4_is_multicast(local))) ||
240 !(t->dev->flags & IFF_UP))
241 continue;
242
243 if (!ip_tunnel_key_match(&t->parms, flags, key))
244 continue;
245
246 if (t->parms.link == link)
247 return t;
248 else if (!cand)
249 cand = t;
250 }
251
252 if (flags & TUNNEL_NO_KEY)
253 goto skip_key_lookup;
254
255 hlist_for_each_entry_rcu(t, head, hash_node) {
256 if (t->parms.i_key != key ||
257 !(t->dev->flags & IFF_UP))
258 continue;
259
260 if (t->parms.link == link)
261 return t;
262 else if (!cand)
263 cand = t;
264 }
265
266skip_key_lookup:
267 if (cand)
268 return cand;
269
270 if (itn->fb_tunnel_dev && itn->fb_tunnel_dev->flags & IFF_UP)
271 return netdev_priv(itn->fb_tunnel_dev);
272
273
274 return NULL;
275}
276EXPORT_SYMBOL_GPL(ip_tunnel_lookup);
277
278static struct hlist_head *ip_bucket(struct ip_tunnel_net *itn,
279 struct ip_tunnel_parm *parms)
280{
281 unsigned int h;
282 __be32 remote;
Steffen Klassert6d608f02014-02-21 08:41:09 +0100283 __be32 i_key = parms->i_key;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000284
285 if (parms->iph.daddr && !ipv4_is_multicast(parms->iph.daddr))
286 remote = parms->iph.daddr;
287 else
288 remote = 0;
289
Steffen Klassert6d608f02014-02-21 08:41:09 +0100290 if (!(parms->i_flags & TUNNEL_KEY) && (parms->i_flags & VTI_ISVTI))
291 i_key = 0;
292
293 h = ip_tunnel_hash(i_key, remote);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000294 return &itn->tunnels[h];
295}
296
297static void ip_tunnel_add(struct ip_tunnel_net *itn, struct ip_tunnel *t)
298{
299 struct hlist_head *head = ip_bucket(itn, &t->parms);
300
301 hlist_add_head_rcu(&t->hash_node, head);
302}
303
304static void ip_tunnel_del(struct ip_tunnel *t)
305{
306 hlist_del_init_rcu(&t->hash_node);
307}
308
309static struct ip_tunnel *ip_tunnel_find(struct ip_tunnel_net *itn,
310 struct ip_tunnel_parm *parms,
311 int type)
312{
313 __be32 remote = parms->iph.daddr;
314 __be32 local = parms->iph.saddr;
315 __be32 key = parms->i_key;
316 int link = parms->link;
317 struct ip_tunnel *t = NULL;
318 struct hlist_head *head = ip_bucket(itn, parms);
319
320 hlist_for_each_entry_rcu(t, head, hash_node) {
321 if (local == t->parms.iph.saddr &&
322 remote == t->parms.iph.daddr &&
323 key == t->parms.i_key &&
324 link == t->parms.link &&
325 type == t->dev->type)
326 break;
327 }
328 return t;
329}
330
331static struct net_device *__ip_tunnel_create(struct net *net,
332 const struct rtnl_link_ops *ops,
333 struct ip_tunnel_parm *parms)
334{
335 int err;
336 struct ip_tunnel *tunnel;
337 struct net_device *dev;
338 char name[IFNAMSIZ];
339
340 if (parms->name[0])
341 strlcpy(name, parms->name, IFNAMSIZ);
342 else {
Pravin B Shelar54a5d382013-03-28 08:21:46 +0000343 if (strlen(ops->kind) > (IFNAMSIZ - 3)) {
Pravin B Shelarc5441932013-03-25 14:49:35 +0000344 err = -E2BIG;
345 goto failed;
346 }
347 strlcpy(name, ops->kind, IFNAMSIZ);
348 strncat(name, "%d", 2);
349 }
350
351 ASSERT_RTNL();
352 dev = alloc_netdev(ops->priv_size, name, ops->setup);
353 if (!dev) {
354 err = -ENOMEM;
355 goto failed;
356 }
357 dev_net_set(dev, net);
358
359 dev->rtnl_link_ops = ops;
360
361 tunnel = netdev_priv(dev);
362 tunnel->parms = *parms;
Nicolas Dichtel5e6700b2013-06-26 16:11:28 +0200363 tunnel->net = net;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000364
365 err = register_netdevice(dev);
366 if (err)
367 goto failed_free;
368
369 return dev;
370
371failed_free:
372 free_netdev(dev);
373failed:
374 return ERR_PTR(err);
375}
376
Tom Herbert7d442fa2014-01-02 11:48:26 -0800377static inline void init_tunnel_flow(struct flowi4 *fl4,
378 int proto,
379 __be32 daddr, __be32 saddr,
380 __be32 key, __u8 tos, int oif)
Pravin B Shelarc5441932013-03-25 14:49:35 +0000381{
382 memset(fl4, 0, sizeof(*fl4));
383 fl4->flowi4_oif = oif;
384 fl4->daddr = daddr;
385 fl4->saddr = saddr;
386 fl4->flowi4_tos = tos;
387 fl4->flowi4_proto = proto;
388 fl4->fl4_gre_key = key;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000389}
390
391static int ip_tunnel_bind_dev(struct net_device *dev)
392{
393 struct net_device *tdev = NULL;
394 struct ip_tunnel *tunnel = netdev_priv(dev);
395 const struct iphdr *iph;
396 int hlen = LL_MAX_HEADER;
397 int mtu = ETH_DATA_LEN;
398 int t_hlen = tunnel->hlen + sizeof(struct iphdr);
399
400 iph = &tunnel->parms.iph;
401
402 /* Guess output device to choose reasonable mtu and needed_headroom */
403 if (iph->daddr) {
404 struct flowi4 fl4;
405 struct rtable *rt;
406
Tom Herbert7d442fa2014-01-02 11:48:26 -0800407 init_tunnel_flow(&fl4, iph->protocol, iph->daddr,
408 iph->saddr, tunnel->parms.o_key,
409 RT_TOS(iph->tos), tunnel->parms.link);
410 rt = ip_route_output_key(tunnel->net, &fl4);
411
Pravin B Shelarc5441932013-03-25 14:49:35 +0000412 if (!IS_ERR(rt)) {
413 tdev = rt->dst.dev;
Eric Dumazet6c7e7612014-01-16 16:41:19 -0800414 tunnel_dst_set(tunnel, &rt->dst);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000415 ip_rt_put(rt);
416 }
417 if (dev->type != ARPHRD_ETHER)
418 dev->flags |= IFF_POINTOPOINT;
419 }
420
421 if (!tdev && tunnel->parms.link)
Nicolas Dichtel6c742e72013-08-13 17:51:11 +0200422 tdev = __dev_get_by_index(tunnel->net, tunnel->parms.link);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000423
424 if (tdev) {
425 hlen = tdev->hard_header_len + tdev->needed_headroom;
426 mtu = tdev->mtu;
427 }
428 dev->iflink = tunnel->parms.link;
429
430 dev->needed_headroom = t_hlen + hlen;
431 mtu -= (dev->hard_header_len + t_hlen);
432
433 if (mtu < 68)
434 mtu = 68;
435
436 return mtu;
437}
438
439static struct ip_tunnel *ip_tunnel_create(struct net *net,
440 struct ip_tunnel_net *itn,
441 struct ip_tunnel_parm *parms)
442{
443 struct ip_tunnel *nt, *fbt;
444 struct net_device *dev;
445
446 BUG_ON(!itn->fb_tunnel_dev);
447 fbt = netdev_priv(itn->fb_tunnel_dev);
448 dev = __ip_tunnel_create(net, itn->fb_tunnel_dev->rtnl_link_ops, parms);
449 if (IS_ERR(dev))
Florian Westphal6dd3c9e2014-02-14 13:14:39 +0100450 return ERR_CAST(dev);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000451
452 dev->mtu = ip_tunnel_bind_dev(dev);
453
454 nt = netdev_priv(dev);
455 ip_tunnel_add(itn, nt);
456 return nt;
457}
458
459int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb,
460 const struct tnl_ptk_info *tpi, bool log_ecn_error)
461{
Li RongQing8f849852014-01-04 13:57:59 +0800462 struct pcpu_sw_netstats *tstats;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000463 const struct iphdr *iph = ip_hdr(skb);
464 int err;
465
Pravin B Shelarc5441932013-03-25 14:49:35 +0000466#ifdef CONFIG_NET_IPGRE_BROADCAST
467 if (ipv4_is_multicast(iph->daddr)) {
468 /* Looped back packet, drop it! */
469 if (rt_is_output_route(skb_rtable(skb)))
470 goto drop;
471 tunnel->dev->stats.multicast++;
472 skb->pkt_type = PACKET_BROADCAST;
473 }
474#endif
475
476 if ((!(tpi->flags&TUNNEL_CSUM) && (tunnel->parms.i_flags&TUNNEL_CSUM)) ||
477 ((tpi->flags&TUNNEL_CSUM) && !(tunnel->parms.i_flags&TUNNEL_CSUM))) {
478 tunnel->dev->stats.rx_crc_errors++;
479 tunnel->dev->stats.rx_errors++;
480 goto drop;
481 }
482
483 if (tunnel->parms.i_flags&TUNNEL_SEQ) {
484 if (!(tpi->flags&TUNNEL_SEQ) ||
485 (tunnel->i_seqno && (s32)(ntohl(tpi->seq) - tunnel->i_seqno) < 0)) {
486 tunnel->dev->stats.rx_fifo_errors++;
487 tunnel->dev->stats.rx_errors++;
488 goto drop;
489 }
490 tunnel->i_seqno = ntohl(tpi->seq) + 1;
491 }
492
Pravin B Shelarc5441932013-03-25 14:49:35 +0000493 err = IP_ECN_decapsulate(iph, skb);
494 if (unlikely(err)) {
495 if (log_ecn_error)
496 net_info_ratelimited("non-ECT from %pI4 with TOS=%#x\n",
497 &iph->saddr, iph->tos);
498 if (err > 1) {
499 ++tunnel->dev->stats.rx_frame_errors;
500 ++tunnel->dev->stats.rx_errors;
501 goto drop;
502 }
503 }
504
505 tstats = this_cpu_ptr(tunnel->dev->tstats);
506 u64_stats_update_begin(&tstats->syncp);
507 tstats->rx_packets++;
508 tstats->rx_bytes += skb->len;
509 u64_stats_update_end(&tstats->syncp);
510
Alexei Starovoitov81b9eab2013-11-12 14:39:13 -0800511 skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(tunnel->dev)));
512
Pravin B Shelar3d7b46c2013-06-17 17:50:02 -0700513 if (tunnel->dev->type == ARPHRD_ETHER) {
514 skb->protocol = eth_type_trans(skb, tunnel->dev);
515 skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN);
516 } else {
517 skb->dev = tunnel->dev;
518 }
Nicolas Dichtel64261f22013-08-13 17:51:09 +0200519
Pravin B Shelarc5441932013-03-25 14:49:35 +0000520 gro_cells_receive(&tunnel->gro_cells, skb);
521 return 0;
522
523drop:
524 kfree_skb(skb);
525 return 0;
526}
527EXPORT_SYMBOL_GPL(ip_tunnel_rcv);
528
Pravin B Shelar23a36472013-07-02 10:57:33 -0700529static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb,
530 struct rtable *rt, __be16 df)
531{
532 struct ip_tunnel *tunnel = netdev_priv(dev);
Alexander Duyck8c91e162013-07-11 13:12:22 -0700533 int pkt_size = skb->len - tunnel->hlen - dev->hard_header_len;
Pravin B Shelar23a36472013-07-02 10:57:33 -0700534 int mtu;
535
536 if (df)
537 mtu = dst_mtu(&rt->dst) - dev->hard_header_len
538 - sizeof(struct iphdr) - tunnel->hlen;
539 else
540 mtu = skb_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu;
541
542 if (skb_dst(skb))
543 skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu);
544
545 if (skb->protocol == htons(ETH_P_IP)) {
546 if (!skb_is_gso(skb) &&
547 (df & htons(IP_DF)) && mtu < pkt_size) {
548 memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
549 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
550 return -E2BIG;
551 }
552 }
553#if IS_ENABLED(CONFIG_IPV6)
554 else if (skb->protocol == htons(ETH_P_IPV6)) {
555 struct rt6_info *rt6 = (struct rt6_info *)skb_dst(skb);
556
557 if (rt6 && mtu < dst_mtu(skb_dst(skb)) &&
558 mtu >= IPV6_MIN_MTU) {
559 if ((tunnel->parms.iph.daddr &&
560 !ipv4_is_multicast(tunnel->parms.iph.daddr)) ||
561 rt6->rt6i_dst.plen == 128) {
562 rt6->rt6i_flags |= RTF_MODIFIED;
563 dst_metric_set(skb_dst(skb), RTAX_MTU, mtu);
564 }
565 }
566
567 if (!skb_is_gso(skb) && mtu >= IPV6_MIN_MTU &&
568 mtu < pkt_size) {
569 icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
570 return -E2BIG;
571 }
572 }
573#endif
574 return 0;
575}
576
Pravin B Shelarc5441932013-03-25 14:49:35 +0000577void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
Nicolas Dichtelbf3d6a82013-05-27 23:48:15 +0000578 const struct iphdr *tnl_params, const u8 protocol)
Pravin B Shelarc5441932013-03-25 14:49:35 +0000579{
580 struct ip_tunnel *tunnel = netdev_priv(dev);
581 const struct iphdr *inner_iph;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000582 struct flowi4 fl4;
583 u8 tos, ttl;
584 __be16 df;
Eric Dumazetb045d372014-02-03 12:52:14 -0800585 struct rtable *rt; /* Route to the other host */
Pravin B Shelarc5441932013-03-25 14:49:35 +0000586 unsigned int max_headroom; /* The extra header space needed */
587 __be32 dst;
Pravin B Shelar0e6fbc52013-06-17 17:49:56 -0700588 int err;
Tom Herbert7d442fa2014-01-02 11:48:26 -0800589 bool connected = true;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000590
591 inner_iph = (const struct iphdr *)skb_inner_network_header(skb);
592
593 dst = tnl_params->daddr;
594 if (dst == 0) {
595 /* NBMA tunnel */
596
597 if (skb_dst(skb) == NULL) {
598 dev->stats.tx_fifo_errors++;
599 goto tx_error;
600 }
601
602 if (skb->protocol == htons(ETH_P_IP)) {
603 rt = skb_rtable(skb);
604 dst = rt_nexthop(rt, inner_iph->daddr);
605 }
606#if IS_ENABLED(CONFIG_IPV6)
607 else if (skb->protocol == htons(ETH_P_IPV6)) {
608 const struct in6_addr *addr6;
609 struct neighbour *neigh;
610 bool do_tx_error_icmp;
611 int addr_type;
612
613 neigh = dst_neigh_lookup(skb_dst(skb),
614 &ipv6_hdr(skb)->daddr);
615 if (neigh == NULL)
616 goto tx_error;
617
618 addr6 = (const struct in6_addr *)&neigh->primary_key;
619 addr_type = ipv6_addr_type(addr6);
620
621 if (addr_type == IPV6_ADDR_ANY) {
622 addr6 = &ipv6_hdr(skb)->daddr;
623 addr_type = ipv6_addr_type(addr6);
624 }
625
626 if ((addr_type & IPV6_ADDR_COMPATv4) == 0)
627 do_tx_error_icmp = true;
628 else {
629 do_tx_error_icmp = false;
630 dst = addr6->s6_addr32[3];
631 }
632 neigh_release(neigh);
633 if (do_tx_error_icmp)
634 goto tx_error_icmp;
635 }
636#endif
637 else
638 goto tx_error;
Tom Herbert7d442fa2014-01-02 11:48:26 -0800639
640 connected = false;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000641 }
642
643 tos = tnl_params->tos;
644 if (tos & 0x1) {
645 tos &= ~0x1;
Tom Herbert7d442fa2014-01-02 11:48:26 -0800646 if (skb->protocol == htons(ETH_P_IP)) {
Pravin B Shelarc5441932013-03-25 14:49:35 +0000647 tos = inner_iph->tos;
Tom Herbert7d442fa2014-01-02 11:48:26 -0800648 connected = false;
649 } else if (skb->protocol == htons(ETH_P_IPV6)) {
Pravin B Shelarc5441932013-03-25 14:49:35 +0000650 tos = ipv6_get_dsfield((const struct ipv6hdr *)inner_iph);
Tom Herbert7d442fa2014-01-02 11:48:26 -0800651 connected = false;
652 }
Pravin B Shelarc5441932013-03-25 14:49:35 +0000653 }
654
Tom Herbert7d442fa2014-01-02 11:48:26 -0800655 init_tunnel_flow(&fl4, protocol, dst, tnl_params->saddr,
656 tunnel->parms.o_key, RT_TOS(tos), tunnel->parms.link);
657
Eric Dumazetb045d372014-02-03 12:52:14 -0800658 rt = connected ? tunnel_rtable_get(tunnel, 0) : NULL;
Tom Herbert7d442fa2014-01-02 11:48:26 -0800659
660 if (!rt) {
661 rt = ip_route_output_key(tunnel->net, &fl4);
662
663 if (IS_ERR(rt)) {
664 dev->stats.tx_carrier_errors++;
665 goto tx_error;
666 }
667 if (connected)
Eric Dumazet6c7e7612014-01-16 16:41:19 -0800668 tunnel_dst_set(tunnel, &rt->dst);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000669 }
Tom Herbert7d442fa2014-01-02 11:48:26 -0800670
Pravin B Shelar0e6fbc52013-06-17 17:49:56 -0700671 if (rt->dst.dev == dev) {
Pravin B Shelarc5441932013-03-25 14:49:35 +0000672 ip_rt_put(rt);
673 dev->stats.collisions++;
674 goto tx_error;
675 }
Pravin B Shelarc5441932013-03-25 14:49:35 +0000676
Pravin B Shelar23a36472013-07-02 10:57:33 -0700677 if (tnl_update_pmtu(dev, skb, rt, tnl_params->frag_off)) {
678 ip_rt_put(rt);
679 goto tx_error;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000680 }
Pravin B Shelarc5441932013-03-25 14:49:35 +0000681
682 if (tunnel->err_count > 0) {
683 if (time_before(jiffies,
684 tunnel->err_time + IPTUNNEL_ERR_TIMEO)) {
685 tunnel->err_count--;
686
Duan Jiong11c21a32014-01-23 14:00:25 +0800687 memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
Pravin B Shelarc5441932013-03-25 14:49:35 +0000688 dst_link_failure(skb);
689 } else
690 tunnel->err_count = 0;
691 }
692
Pravin B Shelard4a71b12013-09-25 09:57:47 -0700693 tos = ip_tunnel_ecn_encap(tos, inner_iph, skb);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000694 ttl = tnl_params->ttl;
695 if (ttl == 0) {
696 if (skb->protocol == htons(ETH_P_IP))
697 ttl = inner_iph->ttl;
698#if IS_ENABLED(CONFIG_IPV6)
699 else if (skb->protocol == htons(ETH_P_IPV6))
700 ttl = ((const struct ipv6hdr *)inner_iph)->hop_limit;
701#endif
702 else
703 ttl = ip4_dst_hoplimit(&rt->dst);
704 }
705
Pravin B Shelar23a36472013-07-02 10:57:33 -0700706 df = tnl_params->frag_off;
707 if (skb->protocol == htons(ETH_P_IP))
708 df |= (inner_iph->frag_off&htons(IP_DF));
709
Pravin B Shelar0e6fbc52013-06-17 17:49:56 -0700710 max_headroom = LL_RESERVED_SPACE(rt->dst.dev) + sizeof(struct iphdr)
711 + rt->dst.header_len;
Steffen Klassert3e08f4a2013-10-01 11:33:59 +0200712 if (max_headroom > dev->needed_headroom)
Pravin B Shelarc5441932013-03-25 14:49:35 +0000713 dev->needed_headroom = max_headroom;
Steffen Klassert3e08f4a2013-10-01 11:33:59 +0200714
715 if (skb_cow_head(skb, dev->needed_headroom)) {
716 dev->stats.tx_dropped++;
Eric Dumazet3acfa1e2014-01-18 18:27:49 -0800717 kfree_skb(skb);
Steffen Klassert3e08f4a2013-10-01 11:33:59 +0200718 return;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000719 }
720
Nicolas Dichtel8b7ed2d2013-09-02 15:34:54 +0200721 err = iptunnel_xmit(rt, skb, fl4.saddr, fl4.daddr, protocol,
Pravin B Shelard4a71b12013-09-25 09:57:47 -0700722 tos, ttl, df, !net_eq(tunnel->net, dev_net(dev)));
Pravin B Shelar0e6fbc52013-06-17 17:49:56 -0700723 iptunnel_xmit_stats(err, &dev->stats, dev->tstats);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000724
Pravin B Shelarc5441932013-03-25 14:49:35 +0000725 return;
726
727#if IS_ENABLED(CONFIG_IPV6)
728tx_error_icmp:
729 dst_link_failure(skb);
730#endif
731tx_error:
732 dev->stats.tx_errors++;
Eric Dumazet3acfa1e2014-01-18 18:27:49 -0800733 kfree_skb(skb);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000734}
735EXPORT_SYMBOL_GPL(ip_tunnel_xmit);
736
737static void ip_tunnel_update(struct ip_tunnel_net *itn,
738 struct ip_tunnel *t,
739 struct net_device *dev,
740 struct ip_tunnel_parm *p,
741 bool set_mtu)
742{
743 ip_tunnel_del(t);
744 t->parms.iph.saddr = p->iph.saddr;
745 t->parms.iph.daddr = p->iph.daddr;
746 t->parms.i_key = p->i_key;
747 t->parms.o_key = p->o_key;
748 if (dev->type != ARPHRD_ETHER) {
749 memcpy(dev->dev_addr, &p->iph.saddr, 4);
750 memcpy(dev->broadcast, &p->iph.daddr, 4);
751 }
752 ip_tunnel_add(itn, t);
753
754 t->parms.iph.ttl = p->iph.ttl;
755 t->parms.iph.tos = p->iph.tos;
756 t->parms.iph.frag_off = p->iph.frag_off;
757
758 if (t->parms.link != p->link) {
759 int mtu;
760
761 t->parms.link = p->link;
762 mtu = ip_tunnel_bind_dev(dev);
763 if (set_mtu)
764 dev->mtu = mtu;
765 }
Tom Herbert9a4aa9a2014-01-02 11:48:33 -0800766 tunnel_dst_reset_all(t);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000767 netdev_state_change(dev);
768}
769
770int ip_tunnel_ioctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd)
771{
772 int err = 0;
773 struct ip_tunnel *t;
774 struct net *net = dev_net(dev);
775 struct ip_tunnel *tunnel = netdev_priv(dev);
776 struct ip_tunnel_net *itn = net_generic(net, tunnel->ip_tnl_net_id);
777
778 BUG_ON(!itn->fb_tunnel_dev);
779 switch (cmd) {
780 case SIOCGETTUNNEL:
781 t = NULL;
782 if (dev == itn->fb_tunnel_dev)
783 t = ip_tunnel_find(itn, p, itn->fb_tunnel_dev->type);
784 if (t == NULL)
785 t = netdev_priv(dev);
786 memcpy(p, &t->parms, sizeof(*p));
787 break;
788
789 case SIOCADDTUNNEL:
790 case SIOCCHGTUNNEL:
791 err = -EPERM;
792 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
793 goto done;
794 if (p->iph.ttl)
795 p->iph.frag_off |= htons(IP_DF);
796 if (!(p->i_flags&TUNNEL_KEY))
797 p->i_key = 0;
798 if (!(p->o_flags&TUNNEL_KEY))
799 p->o_key = 0;
800
801 t = ip_tunnel_find(itn, p, itn->fb_tunnel_dev->type);
802
Florian Westphal6dd3c9e2014-02-14 13:14:39 +0100803 if (!t && (cmd == SIOCADDTUNNEL)) {
Pravin B Shelarc5441932013-03-25 14:49:35 +0000804 t = ip_tunnel_create(net, itn, p);
Florian Westphal6dd3c9e2014-02-14 13:14:39 +0100805 if (IS_ERR(t)) {
806 err = PTR_ERR(t);
807 break;
808 }
809 }
Pravin B Shelarc5441932013-03-25 14:49:35 +0000810 if (dev != itn->fb_tunnel_dev && cmd == SIOCCHGTUNNEL) {
811 if (t != NULL) {
812 if (t->dev != dev) {
813 err = -EEXIST;
814 break;
815 }
816 } else {
817 unsigned int nflags = 0;
818
819 if (ipv4_is_multicast(p->iph.daddr))
820 nflags = IFF_BROADCAST;
821 else if (p->iph.daddr)
822 nflags = IFF_POINTOPOINT;
823
824 if ((dev->flags^nflags)&(IFF_POINTOPOINT|IFF_BROADCAST)) {
825 err = -EINVAL;
826 break;
827 }
828
829 t = netdev_priv(dev);
830 }
831 }
832
833 if (t) {
834 err = 0;
835 ip_tunnel_update(itn, t, dev, p, true);
Florian Westphal6dd3c9e2014-02-14 13:14:39 +0100836 } else {
837 err = -ENOENT;
838 }
Pravin B Shelarc5441932013-03-25 14:49:35 +0000839 break;
840
841 case SIOCDELTUNNEL:
842 err = -EPERM;
843 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
844 goto done;
845
846 if (dev == itn->fb_tunnel_dev) {
847 err = -ENOENT;
848 t = ip_tunnel_find(itn, p, itn->fb_tunnel_dev->type);
849 if (t == NULL)
850 goto done;
851 err = -EPERM;
852 if (t == netdev_priv(itn->fb_tunnel_dev))
853 goto done;
854 dev = t->dev;
855 }
856 unregister_netdevice(dev);
857 err = 0;
858 break;
859
860 default:
861 err = -EINVAL;
862 }
863
864done:
865 return err;
866}
867EXPORT_SYMBOL_GPL(ip_tunnel_ioctl);
868
869int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu)
870{
871 struct ip_tunnel *tunnel = netdev_priv(dev);
872 int t_hlen = tunnel->hlen + sizeof(struct iphdr);
873
874 if (new_mtu < 68 ||
875 new_mtu > 0xFFF8 - dev->hard_header_len - t_hlen)
876 return -EINVAL;
877 dev->mtu = new_mtu;
878 return 0;
879}
880EXPORT_SYMBOL_GPL(ip_tunnel_change_mtu);
881
882static void ip_tunnel_dev_free(struct net_device *dev)
883{
884 struct ip_tunnel *tunnel = netdev_priv(dev);
885
886 gro_cells_destroy(&tunnel->gro_cells);
Tom Herbert9a4aa9a2014-01-02 11:48:33 -0800887 free_percpu(tunnel->dst_cache);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000888 free_percpu(dev->tstats);
889 free_netdev(dev);
890}
891
892void ip_tunnel_dellink(struct net_device *dev, struct list_head *head)
893{
Pravin B Shelarc5441932013-03-25 14:49:35 +0000894 struct ip_tunnel *tunnel = netdev_priv(dev);
895 struct ip_tunnel_net *itn;
896
Nicolas Dichtel6c742e72013-08-13 17:51:11 +0200897 itn = net_generic(tunnel->net, tunnel->ip_tnl_net_id);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000898
899 if (itn->fb_tunnel_dev != dev) {
900 ip_tunnel_del(netdev_priv(dev));
901 unregister_netdevice_queue(dev, head);
902 }
903}
904EXPORT_SYMBOL_GPL(ip_tunnel_dellink);
905
Eric Dumazetd3b6f612013-06-07 13:26:05 -0700906int ip_tunnel_init_net(struct net *net, int ip_tnl_net_id,
Pravin B Shelarc5441932013-03-25 14:49:35 +0000907 struct rtnl_link_ops *ops, char *devname)
908{
909 struct ip_tunnel_net *itn = net_generic(net, ip_tnl_net_id);
910 struct ip_tunnel_parm parms;
stephen hemminger6261d982013-08-05 22:51:37 -0700911 unsigned int i;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000912
stephen hemminger6261d982013-08-05 22:51:37 -0700913 for (i = 0; i < IP_TNL_HASH_SIZE; i++)
914 INIT_HLIST_HEAD(&itn->tunnels[i]);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000915
916 if (!ops) {
917 itn->fb_tunnel_dev = NULL;
918 return 0;
919 }
stephen hemminger6261d982013-08-05 22:51:37 -0700920
Pravin B Shelarc5441932013-03-25 14:49:35 +0000921 memset(&parms, 0, sizeof(parms));
922 if (devname)
923 strlcpy(parms.name, devname, IFNAMSIZ);
924
925 rtnl_lock();
926 itn->fb_tunnel_dev = __ip_tunnel_create(net, ops, &parms);
Dan Carpenterea857f22013-08-19 10:05:10 +0300927 /* FB netdevice is special: we have one, and only one per netns.
928 * Allowing to move it to another netns is clearly unsafe.
929 */
Steffen Klassert67013282013-10-01 11:34:48 +0200930 if (!IS_ERR(itn->fb_tunnel_dev)) {
Dan Carpenterb4de77a2013-08-23 11:15:37 +0300931 itn->fb_tunnel_dev->features |= NETIF_F_NETNS_LOCAL;
Steffen Klassert67013282013-10-01 11:34:48 +0200932 ip_tunnel_add(itn, netdev_priv(itn->fb_tunnel_dev));
933 }
Dan Carpenterb4de77a2013-08-23 11:15:37 +0300934 rtnl_unlock();
Pravin B Shelarc5441932013-03-25 14:49:35 +0000935
Sachin Kamat27d79f32014-01-27 12:13:57 +0530936 return PTR_ERR_OR_ZERO(itn->fb_tunnel_dev);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000937}
938EXPORT_SYMBOL_GPL(ip_tunnel_init_net);
939
Nicolas Dichtel6c742e72013-08-13 17:51:11 +0200940static void ip_tunnel_destroy(struct ip_tunnel_net *itn, struct list_head *head,
941 struct rtnl_link_ops *ops)
Pravin B Shelarc5441932013-03-25 14:49:35 +0000942{
Nicolas Dichtel6c742e72013-08-13 17:51:11 +0200943 struct net *net = dev_net(itn->fb_tunnel_dev);
944 struct net_device *dev, *aux;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000945 int h;
946
Nicolas Dichtel6c742e72013-08-13 17:51:11 +0200947 for_each_netdev_safe(net, dev, aux)
948 if (dev->rtnl_link_ops == ops)
949 unregister_netdevice_queue(dev, head);
950
Pravin B Shelarc5441932013-03-25 14:49:35 +0000951 for (h = 0; h < IP_TNL_HASH_SIZE; h++) {
952 struct ip_tunnel *t;
953 struct hlist_node *n;
954 struct hlist_head *thead = &itn->tunnels[h];
955
956 hlist_for_each_entry_safe(t, n, thead, hash_node)
Nicolas Dichtel6c742e72013-08-13 17:51:11 +0200957 /* If dev is in the same netns, it has already
958 * been added to the list by the previous loop.
959 */
960 if (!net_eq(dev_net(t->dev), net))
961 unregister_netdevice_queue(t->dev, head);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000962 }
Pravin B Shelarc5441932013-03-25 14:49:35 +0000963}
964
Nicolas Dichtel6c742e72013-08-13 17:51:11 +0200965void ip_tunnel_delete_net(struct ip_tunnel_net *itn, struct rtnl_link_ops *ops)
Pravin B Shelarc5441932013-03-25 14:49:35 +0000966{
967 LIST_HEAD(list);
968
969 rtnl_lock();
Nicolas Dichtel6c742e72013-08-13 17:51:11 +0200970 ip_tunnel_destroy(itn, &list, ops);
Pravin B Shelarc5441932013-03-25 14:49:35 +0000971 unregister_netdevice_many(&list);
972 rtnl_unlock();
Pravin B Shelarc5441932013-03-25 14:49:35 +0000973}
974EXPORT_SYMBOL_GPL(ip_tunnel_delete_net);
975
976int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[],
977 struct ip_tunnel_parm *p)
978{
979 struct ip_tunnel *nt;
980 struct net *net = dev_net(dev);
981 struct ip_tunnel_net *itn;
982 int mtu;
983 int err;
984
985 nt = netdev_priv(dev);
986 itn = net_generic(net, nt->ip_tnl_net_id);
987
988 if (ip_tunnel_find(itn, p, dev->type))
989 return -EEXIST;
990
Nicolas Dichtel5e6700b2013-06-26 16:11:28 +0200991 nt->net = net;
Pravin B Shelarc5441932013-03-25 14:49:35 +0000992 nt->parms = *p;
993 err = register_netdevice(dev);
994 if (err)
995 goto out;
996
997 if (dev->type == ARPHRD_ETHER && !tb[IFLA_ADDRESS])
998 eth_hw_addr_random(dev);
999
1000 mtu = ip_tunnel_bind_dev(dev);
1001 if (!tb[IFLA_MTU])
1002 dev->mtu = mtu;
1003
1004 ip_tunnel_add(itn, nt);
1005
1006out:
1007 return err;
1008}
1009EXPORT_SYMBOL_GPL(ip_tunnel_newlink);
1010
1011int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[],
1012 struct ip_tunnel_parm *p)
1013{
Nicolas Dichtel6c742e72013-08-13 17:51:11 +02001014 struct ip_tunnel *t;
Pravin B Shelarc5441932013-03-25 14:49:35 +00001015 struct ip_tunnel *tunnel = netdev_priv(dev);
Nicolas Dichtel6c742e72013-08-13 17:51:11 +02001016 struct net *net = tunnel->net;
Pravin B Shelarc5441932013-03-25 14:49:35 +00001017 struct ip_tunnel_net *itn = net_generic(net, tunnel->ip_tnl_net_id);
1018
1019 if (dev == itn->fb_tunnel_dev)
1020 return -EINVAL;
1021
Pravin B Shelarc5441932013-03-25 14:49:35 +00001022 t = ip_tunnel_find(itn, p, dev->type);
1023
1024 if (t) {
1025 if (t->dev != dev)
1026 return -EEXIST;
1027 } else {
Nicolas Dichtel6c742e72013-08-13 17:51:11 +02001028 t = tunnel;
Pravin B Shelarc5441932013-03-25 14:49:35 +00001029
1030 if (dev->type != ARPHRD_ETHER) {
1031 unsigned int nflags = 0;
1032
1033 if (ipv4_is_multicast(p->iph.daddr))
1034 nflags = IFF_BROADCAST;
1035 else if (p->iph.daddr)
1036 nflags = IFF_POINTOPOINT;
1037
1038 if ((dev->flags ^ nflags) &
1039 (IFF_POINTOPOINT | IFF_BROADCAST))
1040 return -EINVAL;
1041 }
1042 }
1043
1044 ip_tunnel_update(itn, t, dev, p, !tb[IFLA_MTU]);
1045 return 0;
1046}
1047EXPORT_SYMBOL_GPL(ip_tunnel_changelink);
1048
1049int ip_tunnel_init(struct net_device *dev)
1050{
1051 struct ip_tunnel *tunnel = netdev_priv(dev);
1052 struct iphdr *iph = &tunnel->parms.iph;
WANG Cong1c213bd2014-02-13 11:46:28 -08001053 int err;
Pravin B Shelarc5441932013-03-25 14:49:35 +00001054
1055 dev->destructor = ip_tunnel_dev_free;
WANG Cong1c213bd2014-02-13 11:46:28 -08001056 dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001057 if (!dev->tstats)
1058 return -ENOMEM;
1059
Tom Herbert9a4aa9a2014-01-02 11:48:33 -08001060 tunnel->dst_cache = alloc_percpu(struct ip_tunnel_dst);
1061 if (!tunnel->dst_cache) {
1062 free_percpu(dev->tstats);
1063 return -ENOMEM;
1064 }
1065
Pravin B Shelarc5441932013-03-25 14:49:35 +00001066 err = gro_cells_init(&tunnel->gro_cells, dev);
1067 if (err) {
Tom Herbert9a4aa9a2014-01-02 11:48:33 -08001068 free_percpu(tunnel->dst_cache);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001069 free_percpu(dev->tstats);
1070 return err;
1071 }
1072
1073 tunnel->dev = dev;
Nicolas Dichtel6c742e72013-08-13 17:51:11 +02001074 tunnel->net = dev_net(dev);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001075 strcpy(tunnel->parms.name, dev->name);
1076 iph->version = 4;
1077 iph->ihl = 5;
1078
1079 return 0;
1080}
1081EXPORT_SYMBOL_GPL(ip_tunnel_init);
1082
1083void ip_tunnel_uninit(struct net_device *dev)
1084{
Pravin B Shelarc5441932013-03-25 14:49:35 +00001085 struct ip_tunnel *tunnel = netdev_priv(dev);
Nicolas Dichtel6c742e72013-08-13 17:51:11 +02001086 struct net *net = tunnel->net;
Pravin B Shelarc5441932013-03-25 14:49:35 +00001087 struct ip_tunnel_net *itn;
1088
1089 itn = net_generic(net, tunnel->ip_tnl_net_id);
1090 /* fb_tunnel_dev will be unregisted in net-exit call. */
1091 if (itn->fb_tunnel_dev != dev)
1092 ip_tunnel_del(netdev_priv(dev));
Tom Herbert7d442fa2014-01-02 11:48:26 -08001093
Tom Herbert9a4aa9a2014-01-02 11:48:33 -08001094 tunnel_dst_reset_all(tunnel);
Pravin B Shelarc5441932013-03-25 14:49:35 +00001095}
1096EXPORT_SYMBOL_GPL(ip_tunnel_uninit);
1097
1098/* Do least required initialization, rest of init is done in tunnel_init call */
1099void ip_tunnel_setup(struct net_device *dev, int net_id)
1100{
1101 struct ip_tunnel *tunnel = netdev_priv(dev);
1102 tunnel->ip_tnl_net_id = net_id;
1103}
1104EXPORT_SYMBOL_GPL(ip_tunnel_setup);
1105
1106MODULE_LICENSE("GPL");