Blame view

net/ipv4/ip_gre.c 45.4 KB
2874c5fd2   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
  /*
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
3
   *	Linux NET3:	GRE over IP protocol decoder.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4
5
   *
   *	Authors: Alexey Kuznetsov (kuznet@ms2.inr.ac.ru)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6
   */
afd465030   Joe Perches   net: ipv4: Standa...
7
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
4fc268d24   Randy Dunlap   [PATCH] capable/c...
8
  #include <linux/capability.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
9
10
  #include <linux/module.h>
  #include <linux/types.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
11
  #include <linux/kernel.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
12
  #include <linux/slab.h>
7c0f6ba68   Linus Torvalds   Replace <asm/uacc...
13
  #include <linux/uaccess.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
15
16
17
18
19
  #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>
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
20
  #include <linux/if_vlan.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
21
22
23
24
25
  #include <linux/init.h>
  #include <linux/in6.h>
  #include <linux/inetdevice.h>
  #include <linux/igmp.h>
  #include <linux/netfilter_ipv4.h>
e1a800022   Herbert Xu   gre: Add Transpar...
26
  #include <linux/etherdevice.h>
46f25dffb   Kris Katterjohn   [NET]: Change 150...
27
  #include <linux/if_ether.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
29
30
31
32
  
  #include <net/sock.h>
  #include <net/ip.h>
  #include <net/icmp.h>
  #include <net/protocol.h>
c54419321   Pravin B Shelar   GRE: Refactor GRE...
33
  #include <net/ip_tunnels.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
35
36
37
38
  #include <net/arp.h>
  #include <net/checksum.h>
  #include <net/dsfield.h>
  #include <net/inet_ecn.h>
  #include <net/xfrm.h>
59a4c7594   Pavel Emelyanov   [GRE]: Introduce ...
39
40
  #include <net/net_namespace.h>
  #include <net/netns/generic.h>
c19e654dd   Herbert Xu   gre: Add netlink ...
41
  #include <net/rtnetlink.h>
00959ade3   Dmitry Kozlov   PPTP: PPP over IP...
42
  #include <net/gre.h>
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
43
  #include <net/dst_metadata.h>
84e54fe0a   William Tu   gre: introduce na...
44
  #include <net/erspan.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
47
48
49
50
51
52
53
54
55
56
57
  /*
     Problems & solutions
     --------------------
  
     1. The most important issue is detecting local dead loops.
     They would cause complete host lockup in transmit, which
     would be "resolved" by stack overflow or, if queueing is enabled,
     with infinite looping in net_bh.
  
     We cannot track such dead loops during route installation,
     it is infeasible task. The most general solutions would be
     to keep skb->encapsulation counter (sort of local ttl),
6d0722a2c   Eric Dumazet   ip_gre: comments ...
58
     and silently drop packet when it expires. It is a good
bff528578   stephen hemminger   gre: fix spelling...
59
     solution, but it supposes maintaining new variable in ALL
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60
     skb, even if no tunneling is used.
6d0722a2c   Eric Dumazet   ip_gre: comments ...
61
62
63
     Current solution: xmit_recursion breaks dead loops. This is a percpu
     counter, since when we enter the first ndo_xmit(), cpu migration is
     forbidden. We force an exit if this counter reaches RECURSION_LIMIT
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
  
     2. Networking dead loops would not kill routers, but would really
     kill network. IP hop limit plays role of "t->recursion" in this case,
     if we copy it from packet being encapsulated to upper header.
     It is very good solution, but it introduces two problems:
  
     - Routing protocols, using packets with ttl=1 (OSPF, RIP2),
       do not work over tunnels.
     - traceroute does not work. I planned to relay ICMP from tunnel,
       so that this problem would be solved and traceroute output
       would even more informative. This idea appeared to be wrong:
       only Linux complies to rfc1812 now (yes, guys, Linux is the only
       true router now :-)), all routers (at least, in neighbourhood of mine)
       return only 8 bytes of payload. It is the end.
  
     Hence, if we want that OSPF worked or traceroute said something reasonable,
     we should search for another solution.
  
     One of them is to parse packet trying to detect inner encapsulation
     made by our node. It is difficult or even impossible, especially,
bff528578   stephen hemminger   gre: fix spelling...
84
     taking into account fragmentation. TO be short, ttl is not solution at all.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
85
86
87
88
89
90
  
     Current solution: The solution was UNEXPECTEDLY SIMPLE.
     We force DF flag on tunnels with preconfigured hop limit,
     that is ALL. :-) Well, it does not remove the problem completely,
     but exponential growth of network traffic is changed to linear
     (branches, that exceed pmtu are pruned) and tunnel mtu
bff528578   stephen hemminger   gre: fix spelling...
91
     rapidly degrades to value <68, where looping stops.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92
93
94
95
96
97
     Yes, it is not good if there exists a router in the loop,
     which does not force DF, even when encapsulating packets have DF set.
     But it is not our problem! Nobody could accuse us, we made
     all that we could make. Even if it is your gated who injected
     fatal route to network, even if it were you who configured
     fatal static route: you are innocent. :-)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
99
     Alexey Kuznetsov.
   */
eccc1bb8d   stephen hemminger   tunnel: drop pack...
100
101
102
  static bool log_ecn_error = true;
  module_param(log_ecn_error, bool, 0644);
  MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN");
c19e654dd   Herbert Xu   gre: Add netlink ...
103
  static struct rtnl_link_ops ipgre_link_ops __read_mostly;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
104
  static int ipgre_tunnel_init(struct net_device *dev);
1a66a836d   William Tu   gre: add collect_...
105
  static void erspan_build_header(struct sk_buff *skb,
c69de58ba   William Tu   net: erspan: use ...
106
  				u32 id, u32 index,
a3222dc95   William Tu   ip_gre: Refector ...
107
  				bool truncate, bool is_ipv4);
eb8ce741a   Pavel Emelyanov   [GRE]: Make tunne...
108

c7d03a00b   Alexey Dobriyan   netns: make struc...
109
110
  static unsigned int ipgre_net_id __read_mostly;
  static unsigned int gre_tap_net_id __read_mostly;
84e54fe0a   William Tu   gre: introduce na...
111
  static unsigned int erspan_net_id __read_mostly;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
112

32bbd8793   Stefano Brivio   net: Convert prot...
113
114
  static int ipgre_err(struct sk_buff *skb, u32 info,
  		     const struct tnl_ptk_info *tpi)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
115
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
116

c54419321   Pravin B Shelar   GRE: Refactor GRE...
117
118
119
  	/* All the routers (except for Linux) return only
  	   8 bytes of packet payload. It means, that precise relaying of
  	   ICMP in the real Internet is absolutely infeasible.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120

c54419321   Pravin B Shelar   GRE: Refactor GRE...
121
122
123
124
  	   Moreover, Cisco "wise men" put GRE key to the third word
  	   in GRE header. It makes impossible maintaining even soft
  	   state for keyed GRE tunnels with enabled checksum. Tell
  	   them "thank you".
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
125

c54419321   Pravin B Shelar   GRE: Refactor GRE...
126
127
128
129
130
131
  	   Well, I wonder, rfc1812 was written by Cisco employee,
  	   what the hell these idiots break standards established
  	   by themselves???
  	   */
  	struct net *net = dev_net(skb->dev);
  	struct ip_tunnel_net *itn;
96f5a846b   Eric Dumazet   ip_gre: fix a pos...
132
  	const struct iphdr *iph;
88c7664f1   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
133
134
  	const int type = icmp_hdr(skb)->type;
  	const int code = icmp_hdr(skb)->code;
20e1954fe   Eric Dumazet   ipv6: RFC 4884 pa...
135
  	unsigned int data_len = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136
  	struct ip_tunnel *t;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
137

32bbd8793   Stefano Brivio   net: Convert prot...
138
139
140
141
142
143
144
145
146
147
148
149
150
151
  	if (tpi->proto == htons(ETH_P_TEB))
  		itn = net_generic(net, gre_tap_net_id);
  	else if (tpi->proto == htons(ETH_P_ERSPAN) ||
  		 tpi->proto == htons(ETH_P_ERSPAN2))
  		itn = net_generic(net, erspan_net_id);
  	else
  		itn = net_generic(net, ipgre_net_id);
  
  	iph = (const struct iphdr *)(icmp_hdr(skb) + 1);
  	t = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags,
  			     iph->daddr, iph->saddr, tpi->key);
  
  	if (!t)
  		return -ENOENT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
152
153
154
  	switch (type) {
  	default:
  	case ICMP_PARAMETERPROB:
32bbd8793   Stefano Brivio   net: Convert prot...
155
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
156
157
158
159
160
161
  
  	case ICMP_DEST_UNREACH:
  		switch (code) {
  		case ICMP_SR_FAILED:
  		case ICMP_PORT_UNREACH:
  			/* Impossible event. */
32bbd8793   Stefano Brivio   net: Convert prot...
162
  			return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
163
164
165
166
167
168
169
170
  		default:
  			/* All others are translated to HOST_UNREACH.
  			   rfc2003 contains "deep thoughts" about NET_UNREACH,
  			   I believe they are just ether pollution. --ANK
  			 */
  			break;
  		}
  		break;
9f57c67c3   Pravin B Shelar   gre: Remove suppo...
171

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
172
173
  	case ICMP_TIME_EXCEEDED:
  		if (code != ICMP_EXC_TTL)
32bbd8793   Stefano Brivio   net: Convert prot...
174
  			return 0;
20e1954fe   Eric Dumazet   ipv6: RFC 4884 pa...
175
  		data_len = icmp_hdr(skb)->un.reserved[1] * 4; /* RFC 4884 4.1 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
176
  		break;
55be7a9c6   David S. Miller   ipv4: Add redirec...
177
178
179
  
  	case ICMP_REDIRECT:
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
180
  	}
9b8c6d7bf   Eric Dumazet   gre: better suppo...
181
182
  #if IS_ENABLED(CONFIG_IPV6)
         if (tpi->proto == htons(ETH_P_IPV6) &&
20e1954fe   Eric Dumazet   ipv6: RFC 4884 pa...
183
184
             !ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4 + tpi->hdr_len,
  				       type, data_len))
32bbd8793   Stefano Brivio   net: Convert prot...
185
                 return 0;
9b8c6d7bf   Eric Dumazet   gre: better suppo...
186
  #endif
363933955   David S. Miller   ipv4: Handle PMTU...
187
  	if (t->parms.iph.daddr == 0 ||
f97c1e0c6   Joe Perches   [IPV4] net/ipv4: ...
188
  	    ipv4_is_multicast(t->parms.iph.daddr))
32bbd8793   Stefano Brivio   net: Convert prot...
189
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
190
191
  
  	if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
32bbd8793   Stefano Brivio   net: Convert prot...
192
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
193

da6185d87   Wei Yongjun   gre: used time_be...
194
  	if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
195
196
197
198
  		t->err_count++;
  	else
  		t->err_count = 1;
  	t->err_time = jiffies;
32bbd8793   Stefano Brivio   net: Convert prot...
199
200
  
  	return 0;
9f57c67c3   Pravin B Shelar   gre: Remove suppo...
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
  }
  
  static void gre_err(struct sk_buff *skb, u32 info)
  {
  	/* All the routers (except for Linux) return only
  	 * 8 bytes of packet payload. It means, that precise relaying of
  	 * ICMP in the real Internet is absolutely infeasible.
  	 *
  	 * Moreover, Cisco "wise men" put GRE key to the third word
  	 * in GRE header. It makes impossible maintaining even soft
  	 * state for keyed
  	 * GRE tunnels with enabled checksum. Tell them "thank you".
  	 *
  	 * Well, I wonder, rfc1812 was written by Cisco employee,
  	 * what the hell these idiots break standards established
  	 * by themselves???
  	 */
e582615ad   Eric Dumazet   gre: fix error ha...
218
  	const struct iphdr *iph = (struct iphdr *)skb->data;
9f57c67c3   Pravin B Shelar   gre: Remove suppo...
219
220
221
  	const int type = icmp_hdr(skb)->type;
  	const int code = icmp_hdr(skb)->code;
  	struct tnl_ptk_info tpi;
9f57c67c3   Pravin B Shelar   gre: Remove suppo...
222

b0350d51f   Haishuang Yan   ip_gre: fix parsi...
223
224
225
  	if (gre_parse_header(skb, &tpi, NULL, htons(ETH_P_IP),
  			     iph->ihl * 4) < 0)
  		return;
9f57c67c3   Pravin B Shelar   gre: Remove suppo...
226
227
228
  
  	if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
  		ipv4_update_pmtu(skb, dev_net(skb->dev), info,
d888f3966   Maciej Å»enczykowski   net-ipv4: remove ...
229
  				 skb->dev->ifindex, IPPROTO_GRE);
9f57c67c3   Pravin B Shelar   gre: Remove suppo...
230
231
232
  		return;
  	}
  	if (type == ICMP_REDIRECT) {
1042caa79   Maciej Å»enczykowski   net-ipv4: remove ...
233
234
  		ipv4_redirect(skb, dev_net(skb->dev), skb->dev->ifindex,
  			      IPPROTO_GRE);
9f57c67c3   Pravin B Shelar   gre: Remove suppo...
235
236
237
238
  		return;
  	}
  
  	ipgre_err(skb, info, &tpi);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
239
  }
f989d546a   William Tu   erspan: Add type ...
240
241
242
243
244
245
246
247
  static bool is_erspan_type1(int gre_hdr_len)
  {
  	/* Both ERSPAN type I (version 0) and type II (version 1) use
  	 * protocol 0x88BE, but the type I has only 4-byte GRE header,
  	 * while type II has 8-byte.
  	 */
  	return gre_hdr_len == 4;
  }
84e54fe0a   William Tu   gre: introduce na...
248
249
250
251
252
  static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
  		      int gre_hdr_len)
  {
  	struct net *net = dev_net(skb->dev);
  	struct metadata_dst *tun_dst = NULL;
1d7e2ed22   William Tu   net: erspan: refa...
253
  	struct erspan_base_hdr *ershdr;
84e54fe0a   William Tu   gre: introduce na...
254
255
  	struct ip_tunnel_net *itn;
  	struct ip_tunnel *tunnel;
84e54fe0a   William Tu   gre: introduce na...
256
  	const struct iphdr *iph;
3df192830   William Tu   net: erspan: fix ...
257
  	struct erspan_md2 *md2;
1d7e2ed22   William Tu   net: erspan: refa...
258
  	int ver;
84e54fe0a   William Tu   gre: introduce na...
259
260
261
  	int len;
  
  	itn = net_generic(net, erspan_net_id);
84e54fe0a   William Tu   gre: introduce na...
262
  	iph = ip_hdr(skb);
f989d546a   William Tu   erspan: Add type ...
263
264
265
266
267
268
269
270
271
272
273
274
  	if (is_erspan_type1(gre_hdr_len)) {
  		ver = 0;
  		tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex,
  					  tpi->flags | TUNNEL_NO_KEY,
  					  iph->saddr, iph->daddr, 0);
  	} else {
  		ershdr = (struct erspan_base_hdr *)(skb->data + gre_hdr_len);
  		ver = ershdr->ver;
  		tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex,
  					  tpi->flags | TUNNEL_KEY,
  					  iph->saddr, iph->daddr, tpi->key);
  	}
84e54fe0a   William Tu   gre: introduce na...
275
276
  
  	if (tunnel) {
f989d546a   William Tu   erspan: Add type ...
277
278
279
280
  		if (is_erspan_type1(gre_hdr_len))
  			len = gre_hdr_len;
  		else
  			len = gre_hdr_len + erspan_hdr_len(ver);
1d7e2ed22   William Tu   net: erspan: refa...
281
  		if (unlikely(!pskb_may_pull(skb, len)))
ae3e13373   William Tu   net: erspan: fix ...
282
  			return PACKET_REJECT;
1d7e2ed22   William Tu   net: erspan: refa...
283

84e54fe0a   William Tu   gre: introduce na...
284
  		if (__iptunnel_pull_header(skb,
1d7e2ed22   William Tu   net: erspan: refa...
285
  					   len,
84e54fe0a   William Tu   gre: introduce na...
286
287
288
  					   htons(ETH_P_TEB),
  					   false, false) < 0)
  			goto drop;
1a66a836d   William Tu   gre: add collect_...
289
  		if (tunnel->collect_md) {
492b67e28   Lorenzo Bianconi   net: ip_gre: fix ...
290
  			struct erspan_metadata *pkt_md, *md;
1a66a836d   William Tu   gre: add collect_...
291
  			struct ip_tunnel_info *info;
492b67e28   Lorenzo Bianconi   net: ip_gre: fix ...
292
  			unsigned char *gh;
1a66a836d   William Tu   gre: add collect_...
293
294
295
296
297
298
299
300
301
302
303
  			__be64 tun_id;
  			__be16 flags;
  
  			tpi->flags |= TUNNEL_KEY;
  			flags = tpi->flags;
  			tun_id = key32_to_tunnel_id(tpi->key);
  
  			tun_dst = ip_tun_rx_dst(skb, flags,
  						tun_id, sizeof(*md));
  			if (!tun_dst)
  				return PACKET_REJECT;
492b67e28   Lorenzo Bianconi   net: ip_gre: fix ...
304
305
306
307
308
309
310
311
  			/* skb can be uncloned in __iptunnel_pull_header, so
  			 * old pkt_md is no longer valid and we need to reset
  			 * it
  			 */
  			gh = skb_network_header(skb) +
  			     skb_network_header_len(skb);
  			pkt_md = (struct erspan_metadata *)(gh + gre_hdr_len +
  							    sizeof(*ershdr));
1a66a836d   William Tu   gre: add collect_...
312
  			md = ip_tunnel_info_opts(&tun_dst->u.tun_info);
f551c91de   William Tu   net: erspan: intr...
313
  			md->version = ver;
3df192830   William Tu   net: erspan: fix ...
314
315
316
  			md2 = &md->u.md2;
  			memcpy(md2, pkt_md, ver == 1 ? ERSPAN_V1_MDSIZE :
  						       ERSPAN_V2_MDSIZE);
f551c91de   William Tu   net: erspan: intr...
317

1a66a836d   William Tu   gre: add collect_...
318
319
320
  			info = &tun_dst->u.tun_info;
  			info->key.tun_flags |= TUNNEL_ERSPAN_OPT;
  			info->options_len = sizeof(*md);
1a66a836d   William Tu   gre: add collect_...
321
  		}
84e54fe0a   William Tu   gre: introduce na...
322
323
324
325
  		skb_reset_mac_header(skb);
  		ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error);
  		return PACKET_RCVD;
  	}
5a64506b5   Haishuang Yan   erspan: return PA...
326
  	return PACKET_REJECT;
84e54fe0a   William Tu   gre: introduce na...
327
328
329
330
  drop:
  	kfree_skb(skb);
  	return PACKET_RCVD;
  }
125372faa   Jiri Benc   gre: receive also...
331
332
  static int __ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
  		       struct ip_tunnel_net *itn, int hdr_len, bool raw_proto)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
333
  {
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
334
  	struct metadata_dst *tun_dst = NULL;
b71d1d426   Eric Dumazet   inet: constify ip...
335
  	const struct iphdr *iph;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
336
  	struct ip_tunnel *tunnel;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
337

c54419321   Pravin B Shelar   GRE: Refactor GRE...
338
  	iph = ip_hdr(skb);
bda7bb463   Pravin B Shelar   gre: Allow multip...
339
340
  	tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags,
  				  iph->saddr, iph->daddr, tpi->key);
e1a800022   Herbert Xu   gre: Add Transpar...
341

d20832876   stephen hemminger   gre: fix handling...
342
  	if (tunnel) {
c0d59da79   wenxu   ip_gre: Make none...
343
  		const struct iphdr *tnl_params;
125372faa   Jiri Benc   gre: receive also...
344
345
  		if (__iptunnel_pull_header(skb, hdr_len, tpi->proto,
  					   raw_proto, false) < 0)
244a797bd   Jiri Benc   gre: move iptunne...
346
  			goto drop;
e271c7b44   Jiri Benc   gre: do not keep ...
347
348
349
350
  		if (tunnel->dev->type != ARPHRD_NONE)
  			skb_pop_mac_header(skb);
  		else
  			skb_reset_mac_header(skb);
c0d59da79   wenxu   ip_gre: Make none...
351
352
353
  
  		tnl_params = &tunnel->parms.iph;
  		if (tunnel->collect_md || tnl_params->daddr == 0) {
c29a70d2c   Pravin B Shelar   tunnel: introduce...
354
355
  			__be16 flags;
  			__be64 tun_id;
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
356

c29a70d2c   Pravin B Shelar   tunnel: introduce...
357
  			flags = tpi->flags & (TUNNEL_CSUM | TUNNEL_KEY);
d817f432c   Amir Vadai   net/ip_tunnels: I...
358
  			tun_id = key32_to_tunnel_id(tpi->key);
c29a70d2c   Pravin B Shelar   tunnel: introduce...
359
  			tun_dst = ip_tun_rx_dst(skb, flags, tun_id, 0);
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
360
361
  			if (!tun_dst)
  				return PACKET_REJECT;
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
362
363
364
  		}
  
  		ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error);
bda7bb463   Pravin B Shelar   gre: Allow multip...
365
  		return PACKET_RCVD;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
366
  	}
125372faa   Jiri Benc   gre: receive also...
367
  	return PACKET_NEXT;
244a797bd   Jiri Benc   gre: move iptunne...
368
369
370
371
  
  drop:
  	kfree_skb(skb);
  	return PACKET_RCVD;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
372
  }
125372faa   Jiri Benc   gre: receive also...
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
  static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
  		     int hdr_len)
  {
  	struct net *net = dev_net(skb->dev);
  	struct ip_tunnel_net *itn;
  	int res;
  
  	if (tpi->proto == htons(ETH_P_TEB))
  		itn = net_generic(net, gre_tap_net_id);
  	else
  		itn = net_generic(net, ipgre_net_id);
  
  	res = __ipgre_rcv(skb, tpi, itn, hdr_len, false);
  	if (res == PACKET_NEXT && tpi->proto == htons(ETH_P_TEB)) {
  		/* ipgre tunnels in collect metadata mode should receive
  		 * also ETH_P_TEB traffic.
  		 */
  		itn = net_generic(net, ipgre_net_id);
  		res = __ipgre_rcv(skb, tpi, itn, hdr_len, true);
  	}
  	return res;
  }
9f57c67c3   Pravin B Shelar   gre: Remove suppo...
395
396
397
398
  static int gre_rcv(struct sk_buff *skb)
  {
  	struct tnl_ptk_info tpi;
  	bool csum_err = false;
95f5c64c3   Tom Herbert   gre: Move utility...
399
  	int hdr_len;
9f57c67c3   Pravin B Shelar   gre: Remove suppo...
400
401
402
403
404
405
406
407
  
  #ifdef CONFIG_NET_IPGRE_BROADCAST
  	if (ipv4_is_multicast(ip_hdr(skb)->daddr)) {
  		/* Looped back packet, drop it! */
  		if (rt_is_output_route(skb_rtable(skb)))
  			goto drop;
  	}
  #endif
e582615ad   Eric Dumazet   gre: fix error ha...
408
  	hdr_len = gre_parse_header(skb, &tpi, &csum_err, htons(ETH_P_IP), 0);
f132ae7c4   Jiri Benc   gre: change gre_p...
409
  	if (hdr_len < 0)
95f5c64c3   Tom Herbert   gre: Move utility...
410
  		goto drop;
f551c91de   William Tu   net: erspan: intr...
411
412
  	if (unlikely(tpi.proto == htons(ETH_P_ERSPAN) ||
  		     tpi.proto == htons(ETH_P_ERSPAN2))) {
84e54fe0a   William Tu   gre: introduce na...
413
414
  		if (erspan_rcv(skb, &tpi, hdr_len) == PACKET_RCVD)
  			return 0;
dd8d5b8c5   Haishuang Yan   ip_gre: fix error...
415
  		goto out;
84e54fe0a   William Tu   gre: introduce na...
416
  	}
244a797bd   Jiri Benc   gre: move iptunne...
417
  	if (ipgre_rcv(skb, &tpi, hdr_len) == PACKET_RCVD)
9f57c67c3   Pravin B Shelar   gre: Remove suppo...
418
  		return 0;
dd8d5b8c5   Haishuang Yan   ip_gre: fix error...
419
  out:
9f57c67c3   Pravin B Shelar   gre: Remove suppo...
420
421
422
423
424
  	icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
  drop:
  	kfree_skb(skb);
  	return 0;
  }
c54419321   Pravin B Shelar   GRE: Refactor GRE...
425
426
427
428
429
  static void __gre_xmit(struct sk_buff *skb, struct net_device *dev,
  		       const struct iphdr *tnl_params,
  		       __be16 proto)
  {
  	struct ip_tunnel *tunnel = netdev_priv(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
430

c54419321   Pravin B Shelar   GRE: Refactor GRE...
431
432
  	if (tunnel->parms.o_flags & TUNNEL_SEQ)
  		tunnel->o_seqno++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
433

c54419321   Pravin B Shelar   GRE: Refactor GRE...
434
  	/* Push GRE header. */
182a352d2   Tom Herbert   gre: Create commo...
435
436
437
  	gre_build_header(skb, tunnel->tun_hlen,
  			 tunnel->parms.o_flags, proto, tunnel->parms.o_key,
  			 htonl(tunnel->o_seqno));
54bc9bac3   Tom Herbert   gre: Set inner pr...
438

bf3d6a8f7   Nicolas Dichtel   iptunnel: specify...
439
  	ip_tunnel_xmit(skb, dev, tnl_params, tnl_params->protocol);
c54419321   Pravin B Shelar   GRE: Refactor GRE...
440
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
441

aed069df0   Alexander Duyck   ip_tunnel_core: i...
442
  static int gre_handle_offloads(struct sk_buff *skb, bool csum)
b2acd1dc3   Pravin B Shelar   openvswitch: Use ...
443
  {
6fa79666e   Edward Cree   net: ip_tunnel: r...
444
  	return iptunnel_handle_offloads(skb, csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE);
b2acd1dc3   Pravin B Shelar   openvswitch: Use ...
445
  }
862a03c35   William Tu   gre: refactor the...
446
447
448
  static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev,
  			__be16 proto)
  {
77a5196a8   William Tu   gre: add sequence...
449
  	struct ip_tunnel *tunnel = netdev_priv(dev);
862a03c35   William Tu   gre: refactor the...
450
451
  	struct ip_tunnel_info *tun_info;
  	const struct ip_tunnel_key *key;
862a03c35   William Tu   gre: refactor the...
452
  	int tunnel_hlen;
962924fa2   wenxu   ip_gre: Refactor ...
453
  	__be16 flags;
862a03c35   William Tu   gre: refactor the...
454
455
456
457
458
459
460
461
  
  	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 err_free_skb;
  
  	key = &tun_info->key;
  	tunnel_hlen = gre_calc_hlen(key->tun_flags);
962924fa2   wenxu   ip_gre: Refactor ...
462
463
  	if (skb_cow_head(skb, dev->needed_headroom))
  		goto err_free_skb;
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
464
465
  
  	/* Push Tunnel header. */
aed069df0   Alexander Duyck   ip_tunnel_core: i...
466
  	if (gre_handle_offloads(skb, !!(tun_info->key.tun_flags & TUNNEL_CSUM)))
962924fa2   wenxu   ip_gre: Refactor ...
467
  		goto err_free_skb;
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
468

77a5196a8   William Tu   gre: add sequence...
469
470
  	flags = tun_info->key.tun_flags &
  		(TUNNEL_CSUM | TUNNEL_KEY | TUNNEL_SEQ);
cba653210   David S. Miller   Merge git://git.k...
471
  	gre_build_header(skb, tunnel_hlen, flags, proto,
77a5196a8   William Tu   gre: add sequence...
472
  			 tunnel_id_to_key32(tun_info->key.tun_id),
157463941   Colin Ian King   gre: fix TUNNEL_S...
473
  			 (flags & TUNNEL_SEQ) ? htonl(tunnel->o_seqno++) : 0);
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
474

962924fa2   wenxu   ip_gre: Refactor ...
475
  	ip_md_tunnel_xmit(skb, dev, IPPROTO_GRE, tunnel_hlen);
039f50629   Pravin B Shelar   ip_tunnel: Move s...
476

2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
477
  	return;
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
478
479
480
481
  err_free_skb:
  	kfree_skb(skb);
  	dev->stats.tx_dropped++;
  }
20704bd16   Xin Long   erspan: build the...
482
  static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev)
1a66a836d   William Tu   gre: add collect_...
483
484
485
486
487
  {
  	struct ip_tunnel *tunnel = netdev_priv(dev);
  	struct ip_tunnel_info *tun_info;
  	const struct ip_tunnel_key *key;
  	struct erspan_metadata *md;
1a66a836d   William Tu   gre: add collect_...
488
  	bool truncate = false;
962924fa2   wenxu   ip_gre: Refactor ...
489
  	__be16 proto;
1a66a836d   William Tu   gre: add collect_...
490
  	int tunnel_hlen;
f551c91de   William Tu   net: erspan: intr...
491
  	int version;
1baf5ebf8   William Tu   erspan: auto dete...
492
  	int nhoff;
d5db21a3e   William Tu   erspan: auto dete...
493
  	int thoff;
1a66a836d   William Tu   gre: add collect_...
494
495
496
497
498
499
500
  
  	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 err_free_skb;
  
  	key = &tun_info->key;
256c87c17   Pieter Jansen van Vuuren   net: check tunnel...
501
  	if (!(tun_info->key.tun_flags & TUNNEL_ERSPAN_OPT))
962924fa2   wenxu   ip_gre: Refactor ...
502
  		goto err_free_skb;
2eb8d6d29   Xin Long   erspan: fix the t...
503
  	if (tun_info->options_len < sizeof(*md))
962924fa2   wenxu   ip_gre: Refactor ...
504
  		goto err_free_skb;
2eb8d6d29   Xin Long   erspan: fix the t...
505
  	md = ip_tunnel_info_opts(tun_info);
1a66a836d   William Tu   gre: add collect_...
506
507
  
  	/* ERSPAN has fixed 8 byte GRE header */
f551c91de   William Tu   net: erspan: intr...
508
509
  	version = md->version;
  	tunnel_hlen = 8 + erspan_hdr_len(version);
1a66a836d   William Tu   gre: add collect_...
510

962924fa2   wenxu   ip_gre: Refactor ...
511
512
  	if (skb_cow_head(skb, dev->needed_headroom))
  		goto err_free_skb;
1a66a836d   William Tu   gre: add collect_...
513
514
  
  	if (gre_handle_offloads(skb, false))
962924fa2   wenxu   ip_gre: Refactor ...
515
  		goto err_free_skb;
1a66a836d   William Tu   gre: add collect_...
516

f192970de   William Tu   ip_gre: check pac...
517
518
  	if (skb->len > dev->mtu + dev->hard_header_len) {
  		pskb_trim(skb, dev->mtu + dev->hard_header_len);
1a66a836d   William Tu   gre: add collect_...
519
520
  		truncate = true;
  	}
1baf5ebf8   William Tu   erspan: auto dete...
521
522
523
524
  	nhoff = skb_network_header(skb) - skb_mac_header(skb);
  	if (skb->protocol == htons(ETH_P_IP) &&
  	    (ntohs(ip_hdr(skb)->tot_len) > skb->len - nhoff))
  		truncate = true;
d5db21a3e   William Tu   erspan: auto dete...
525
526
527
528
529
  
  	thoff = skb_transport_header(skb) - skb_mac_header(skb);
  	if (skb->protocol == htons(ETH_P_IPV6) &&
  	    (ntohs(ipv6_hdr(skb)->payload_len) > skb->len - thoff))
  		truncate = true;
1baf5ebf8   William Tu   erspan: auto dete...
530

f551c91de   William Tu   net: erspan: intr...
531
  	if (version == 1) {
c69de58ba   William Tu   net: erspan: use ...
532
  		erspan_build_header(skb, ntohl(tunnel_id_to_key32(key->tun_id)),
f551c91de   William Tu   net: erspan: intr...
533
  				    ntohl(md->u.index), truncate, true);
20704bd16   Xin Long   erspan: build the...
534
  		proto = htons(ETH_P_ERSPAN);
f551c91de   William Tu   net: erspan: intr...
535
  	} else if (version == 2) {
c69de58ba   William Tu   net: erspan: use ...
536
537
538
539
540
  		erspan_build_header_v2(skb,
  				       ntohl(tunnel_id_to_key32(key->tun_id)),
  				       md->u.md2.dir,
  				       get_hwid(&md->u.md2),
  				       truncate, true);
20704bd16   Xin Long   erspan: build the...
541
  		proto = htons(ETH_P_ERSPAN2);
f551c91de   William Tu   net: erspan: intr...
542
  	} else {
962924fa2   wenxu   ip_gre: Refactor ...
543
  		goto err_free_skb;
f551c91de   William Tu   net: erspan: intr...
544
  	}
1a66a836d   William Tu   gre: add collect_...
545
546
  
  	gre_build_header(skb, 8, TUNNEL_SEQ,
20704bd16   Xin Long   erspan: build the...
547
  			 proto, 0, htonl(tunnel->o_seqno++));
1a66a836d   William Tu   gre: add collect_...
548

962924fa2   wenxu   ip_gre: Refactor ...
549
  	ip_md_tunnel_xmit(skb, dev, IPPROTO_GRE, tunnel_hlen);
1a66a836d   William Tu   gre: add collect_...
550

1a66a836d   William Tu   gre: add collect_...
551
  	return;
1a66a836d   William Tu   gre: add collect_...
552
553
554
555
  err_free_skb:
  	kfree_skb(skb);
  	dev->stats.tx_dropped++;
  }
fc4099f17   Pravin B Shelar   openvswitch: Fix ...
556
557
558
  static int gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
  {
  	struct ip_tunnel_info *info = skb_tunnel_info(skb);
962924fa2   wenxu   ip_gre: Refactor ...
559
  	const struct ip_tunnel_key *key;
fc4099f17   Pravin B Shelar   openvswitch: Fix ...
560
561
562
563
564
  	struct rtable *rt;
  	struct flowi4 fl4;
  
  	if (ip_tunnel_info_af(info) != AF_INET)
  		return -EINVAL;
962924fa2   wenxu   ip_gre: Refactor ...
565
566
567
  	key = &info->key;
  	ip_tunnel_init_flow(&fl4, IPPROTO_GRE, key->u.ipv4.dst, key->u.ipv4.src,
  			    tunnel_id_to_key32(key->tun_id), key->tos, 0,
24ba14406   wenxu   route: Add multip...
568
  			    skb->mark, skb_get_hash(skb));
962924fa2   wenxu   ip_gre: Refactor ...
569
  	rt = ip_route_output_key(dev_net(dev), &fl4);
fc4099f17   Pravin B Shelar   openvswitch: Fix ...
570
571
572
573
574
575
576
  	if (IS_ERR(rt))
  		return PTR_ERR(rt);
  
  	ip_rt_put(rt);
  	info->key.u.ipv4.src = fl4.saddr;
  	return 0;
  }
c54419321   Pravin B Shelar   GRE: Refactor GRE...
577
578
579
580
581
  static netdev_tx_t ipgre_xmit(struct sk_buff *skb,
  			      struct net_device *dev)
  {
  	struct ip_tunnel *tunnel = netdev_priv(dev);
  	const struct iphdr *tnl_params;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
582

cb9f1b783   Willem de Bruijn   ip: validate head...
583
584
  	if (!pskb_inet_may_pull(skb))
  		goto free_skb;
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
585
  	if (tunnel->collect_md) {
2090714e1   Jiri Benc   gre: build header...
586
  		gre_fb_xmit(skb, dev, skb->protocol);
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
587
588
  		return NETDEV_TX_OK;
  	}
c54419321   Pravin B Shelar   GRE: Refactor GRE...
589
  	if (dev->header_ops) {
fdafed459   Cong Wang   ip_gre: set dev->...
590
  		if (skb_cow_head(skb, 0))
c54419321   Pravin B Shelar   GRE: Refactor GRE...
591
  			goto free_skb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
592

c54419321   Pravin B Shelar   GRE: Refactor GRE...
593
  		tnl_params = (const struct iphdr *)skb->data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
594

c54419321   Pravin B Shelar   GRE: Refactor GRE...
595
596
597
598
  		/* Pull skb since ip_tunnel_xmit() needs skb->data pointing
  		 * to gre header.
  		 */
  		skb_pull(skb, tunnel->hlen + sizeof(struct iphdr));
8a0033a94   Timo Teräs   gre: fix the inne...
599
  		skb_reset_mac_header(skb);
c54419321   Pravin B Shelar   GRE: Refactor GRE...
600
601
602
  	} else {
  		if (skb_cow_head(skb, dev->needed_headroom))
  			goto free_skb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
603

c54419321   Pravin B Shelar   GRE: Refactor GRE...
604
  		tnl_params = &tunnel->parms.iph;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
605
  	}
aed069df0   Alexander Duyck   ip_tunnel_core: i...
606
607
  	if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM)))
  		goto free_skb;
8a0033a94   Timo Teräs   gre: fix the inne...
608

c54419321   Pravin B Shelar   GRE: Refactor GRE...
609
  	__gre_xmit(skb, dev, tnl_params, skb->protocol);
6ed106549   Patrick McHardy   net: use NETDEV_T...
610
  	return NETDEV_TX_OK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
611

c54419321   Pravin B Shelar   GRE: Refactor GRE...
612
  free_skb:
3acfa1e73   Eric Dumazet   ipv4: be friend w...
613
  	kfree_skb(skb);
c54419321   Pravin B Shelar   GRE: Refactor GRE...
614
  	dev->stats.tx_dropped++;
6ed106549   Patrick McHardy   net: use NETDEV_T...
615
  	return NETDEV_TX_OK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
616
  }
84e54fe0a   William Tu   gre: introduce na...
617
618
619
620
621
  static netdev_tx_t erspan_xmit(struct sk_buff *skb,
  			       struct net_device *dev)
  {
  	struct ip_tunnel *tunnel = netdev_priv(dev);
  	bool truncate = false;
20704bd16   Xin Long   erspan: build the...
622
  	__be16 proto;
84e54fe0a   William Tu   gre: introduce na...
623

cb9f1b783   Willem de Bruijn   ip: validate head...
624
625
  	if (!pskb_inet_may_pull(skb))
  		goto free_skb;
1a66a836d   William Tu   gre: add collect_...
626
  	if (tunnel->collect_md) {
20704bd16   Xin Long   erspan: build the...
627
  		erspan_fb_xmit(skb, dev);
1a66a836d   William Tu   gre: add collect_...
628
629
  		return NETDEV_TX_OK;
  	}
84e54fe0a   William Tu   gre: introduce na...
630
631
632
633
634
  	if (gre_handle_offloads(skb, false))
  		goto free_skb;
  
  	if (skb_cow_head(skb, dev->needed_headroom))
  		goto free_skb;
f192970de   William Tu   ip_gre: check pac...
635
636
  	if (skb->len > dev->mtu + dev->hard_header_len) {
  		pskb_trim(skb, dev->mtu + dev->hard_header_len);
84e54fe0a   William Tu   gre: introduce na...
637
638
639
640
  		truncate = true;
  	}
  
  	/* Push ERSPAN header */
f989d546a   William Tu   erspan: Add type ...
641
642
643
644
  	if (tunnel->erspan_ver == 0) {
  		proto = htons(ETH_P_ERSPAN);
  		tunnel->parms.o_flags &= ~TUNNEL_SEQ;
  	} else if (tunnel->erspan_ver == 1) {
c69de58ba   William Tu   net: erspan: use ...
645
646
  		erspan_build_header(skb, ntohl(tunnel->parms.o_key),
  				    tunnel->index,
f551c91de   William Tu   net: erspan: intr...
647
  				    truncate, true);
20704bd16   Xin Long   erspan: build the...
648
649
  		proto = htons(ETH_P_ERSPAN);
  	} else if (tunnel->erspan_ver == 2) {
c69de58ba   William Tu   net: erspan: use ...
650
  		erspan_build_header_v2(skb, ntohl(tunnel->parms.o_key),
f551c91de   William Tu   net: erspan: intr...
651
652
  				       tunnel->dir, tunnel->hwid,
  				       truncate, true);
20704bd16   Xin Long   erspan: build the...
653
654
  		proto = htons(ETH_P_ERSPAN2);
  	} else {
02f99df18   William Tu   erspan: fix inval...
655
  		goto free_skb;
20704bd16   Xin Long   erspan: build the...
656
  	}
f551c91de   William Tu   net: erspan: intr...
657

84e54fe0a   William Tu   gre: introduce na...
658
  	tunnel->parms.o_flags &= ~TUNNEL_KEY;
20704bd16   Xin Long   erspan: build the...
659
  	__gre_xmit(skb, dev, &tunnel->parms.iph, proto);
84e54fe0a   William Tu   gre: introduce na...
660
661
662
663
664
665
666
  	return NETDEV_TX_OK;
  
  free_skb:
  	kfree_skb(skb);
  	dev->stats.tx_dropped++;
  	return NETDEV_TX_OK;
  }
c54419321   Pravin B Shelar   GRE: Refactor GRE...
667
668
  static netdev_tx_t gre_tap_xmit(struct sk_buff *skb,
  				struct net_device *dev)
ee34c1eb3   Michal Schmidt   [IP_GRE]: Rebindi...
669
  {
c54419321   Pravin B Shelar   GRE: Refactor GRE...
670
  	struct ip_tunnel *tunnel = netdev_priv(dev);
ee34c1eb3   Michal Schmidt   [IP_GRE]: Rebindi...
671

cb9f1b783   Willem de Bruijn   ip: validate head...
672
673
  	if (!pskb_inet_may_pull(skb))
  		goto free_skb;
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
674
  	if (tunnel->collect_md) {
2090714e1   Jiri Benc   gre: build header...
675
  		gre_fb_xmit(skb, dev, htons(ETH_P_TEB));
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
676
677
  		return NETDEV_TX_OK;
  	}
aed069df0   Alexander Duyck   ip_tunnel_core: i...
678
679
  	if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM)))
  		goto free_skb;
ee34c1eb3   Michal Schmidt   [IP_GRE]: Rebindi...
680

c54419321   Pravin B Shelar   GRE: Refactor GRE...
681
682
  	if (skb_cow_head(skb, dev->needed_headroom))
  		goto free_skb;
42aa91626   Herbert Xu   gre: Move MTU set...
683

c54419321   Pravin B Shelar   GRE: Refactor GRE...
684
  	__gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_TEB));
c54419321   Pravin B Shelar   GRE: Refactor GRE...
685
  	return NETDEV_TX_OK;
ee34c1eb3   Michal Schmidt   [IP_GRE]: Rebindi...
686

c54419321   Pravin B Shelar   GRE: Refactor GRE...
687
  free_skb:
3acfa1e73   Eric Dumazet   ipv4: be friend w...
688
  	kfree_skb(skb);
c54419321   Pravin B Shelar   GRE: Refactor GRE...
689
690
  	dev->stats.tx_dropped++;
  	return NETDEV_TX_OK;
ee34c1eb3   Michal Schmidt   [IP_GRE]: Rebindi...
691
  }
dd9d598c6   Xin Long   ip_gre: add the s...
692
693
694
695
696
697
698
699
700
  static void ipgre_link_update(struct net_device *dev, bool set_mtu)
  {
  	struct ip_tunnel *tunnel = netdev_priv(dev);
  	int len;
  
  	len = tunnel->tun_hlen;
  	tunnel->tun_hlen = gre_calc_hlen(tunnel->parms.o_flags);
  	len = tunnel->tun_hlen - len;
  	tunnel->hlen = tunnel->hlen + len;
fdafed459   Cong Wang   ip_gre: set dev->...
701
702
703
704
  	if (dev->header_ops)
  		dev->hard_header_len += len;
  	else
  		dev->needed_headroom += len;
dd9d598c6   Xin Long   ip_gre: add the s...
705
706
707
708
709
710
711
712
  	if (set_mtu)
  		dev->mtu = max_t(int, dev->mtu - len, 68);
  
  	if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) {
  		if (!(tunnel->parms.o_flags & TUNNEL_CSUM) ||
  		    tunnel->encap.type == TUNNEL_ENCAP_NONE) {
  			dev->features |= NETIF_F_GSO_SOFTWARE;
  			dev->hw_features |= NETIF_F_GSO_SOFTWARE;
1cc5954f4   Sabrina Dubroca   ip_gre: clear fea...
713
714
715
  		} else {
  			dev->features &= ~NETIF_F_GSO_SOFTWARE;
  			dev->hw_features &= ~NETIF_F_GSO_SOFTWARE;
dd9d598c6   Xin Long   ip_gre: add the s...
716
717
  		}
  		dev->features |= NETIF_F_LLTX;
1cc5954f4   Sabrina Dubroca   ip_gre: clear fea...
718
719
720
  	} else {
  		dev->hw_features &= ~NETIF_F_GSO_SOFTWARE;
  		dev->features &= ~(NETIF_F_LLTX | NETIF_F_GSO_SOFTWARE);
dd9d598c6   Xin Long   ip_gre: add the s...
721
722
  	}
  }
607259a69   Christoph Hellwig   net: add a new nd...
723
724
  static int ipgre_tunnel_ctl(struct net_device *dev, struct ip_tunnel_parm *p,
  			    int cmd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
725
  {
a0efab67a   Xin Long   ip_gre: add the s...
726
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
727

6c734fb85   Cong Wang   gre: fix a regres...
728
  	if (cmd == SIOCADDTUNNEL || cmd == SIOCCHGTUNNEL) {
607259a69   Christoph Hellwig   net: add a new nd...
729
730
731
  		if (p->iph.version != 4 || p->iph.protocol != IPPROTO_GRE ||
  		    p->iph.ihl != 5 || (p->iph.frag_off & htons(~IP_DF)) ||
  		    ((p->i_flags | p->o_flags) & (GRE_VERSION | GRE_ROUTING)))
6c734fb85   Cong Wang   gre: fix a regres...
732
  			return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
733
  	}
a0efab67a   Xin Long   ip_gre: add the s...
734

607259a69   Christoph Hellwig   net: add a new nd...
735
736
  	p->i_flags = gre_flags_to_tnl_flags(p->i_flags);
  	p->o_flags = gre_flags_to_tnl_flags(p->o_flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
737

607259a69   Christoph Hellwig   net: add a new nd...
738
  	err = ip_tunnel_ctl(dev, p, cmd);
c54419321   Pravin B Shelar   GRE: Refactor GRE...
739
740
  	if (err)
  		return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
741

a0efab67a   Xin Long   ip_gre: add the s...
742
743
  	if (cmd == SIOCCHGTUNNEL) {
  		struct ip_tunnel *t = netdev_priv(dev);
607259a69   Christoph Hellwig   net: add a new nd...
744
745
  		t->parms.i_flags = p->i_flags;
  		t->parms.o_flags = p->o_flags;
a0efab67a   Xin Long   ip_gre: add the s...
746
747
748
749
  
  		if (strcmp(dev->rtnl_link_ops->kind, "erspan"))
  			ipgre_link_update(dev, true);
  	}
607259a69   Christoph Hellwig   net: add a new nd...
750
751
  	p->i_flags = gre_tnl_flags_to_gre_flags(p->i_flags);
  	p->o_flags = gre_tnl_flags_to_gre_flags(p->o_flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
752
753
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
754
755
756
757
758
759
760
761
762
  /* Nice toy. Unfortunately, useless in real life :-)
     It allows to construct virtual multiprotocol broadcast "LAN"
     over the Internet, provided multicast routing is tuned.
  
  
     I have no idea was this bicycle invented before me,
     so that I had to set ARPHRD_IPGRE to a random value.
     I have an impression, that Cisco could make something similar,
     but this feature is apparently missing in IOS<=11.2(8).
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
763

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
     I set up 10.66.66/24 and fec0:6666:6666::0/96 as virtual networks
     with broadcast 224.66.66.66. If you have access to mbone, play with me :-)
  
     ping -t 255 224.66.66.66
  
     If nobody answers, mbone does not work.
  
     ip tunnel add Universe mode gre remote 224.66.66.66 local <Your_real_addr> ttl 255
     ip addr add 10.66.66.<somewhat>/24 dev Universe
     ifconfig Universe up
     ifconfig Universe add fe80::<Your_real_addr>/10
     ifconfig Universe add fec0:6666:6666::<Your_real_addr>/96
     ftp 10.66.66.66
     ...
     ftp fec0:6666:6666::193.233.7.65
     ...
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
780
   */
3b04ddde0   Stephen Hemminger   [NET]: Move hardw...
781
782
  static int ipgre_header(struct sk_buff *skb, struct net_device *dev,
  			unsigned short type,
1507850b4   Eric Dumazet   gre: get rid of i...
783
  			const void *daddr, const void *saddr, unsigned int len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
784
  {
2941a4863   Patrick McHardy   [NET]: Convert ne...
785
  	struct ip_tunnel *t = netdev_priv(dev);
c54419321   Pravin B Shelar   GRE: Refactor GRE...
786
787
  	struct iphdr *iph;
  	struct gre_base_hdr *greh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
788

d58ff3512   Johannes Berg   networking: make ...
789
  	iph = skb_push(skb, t->hlen + sizeof(*iph));
c54419321   Pravin B Shelar   GRE: Refactor GRE...
790
  	greh = (struct gre_base_hdr *)(iph+1);
95f5c64c3   Tom Herbert   gre: Move utility...
791
  	greh->flags = gre_tnl_flags_to_gre_flags(t->parms.o_flags);
c54419321   Pravin B Shelar   GRE: Refactor GRE...
792
  	greh->protocol = htons(type);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
793

c54419321   Pravin B Shelar   GRE: Refactor GRE...
794
  	memcpy(iph, &t->parms.iph, sizeof(struct iphdr));
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
795

c54419321   Pravin B Shelar   GRE: Refactor GRE...
796
  	/* Set the source hardware address. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
797
798
  	if (saddr)
  		memcpy(&iph->saddr, saddr, 4);
6d55cb91a   Timo Teräs   gre: fix hard hea...
799
  	if (daddr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
800
  		memcpy(&iph->daddr, daddr, 4);
6d55cb91a   Timo Teräs   gre: fix hard hea...
801
  	if (iph->daddr)
77a482bdb   Timo Teräs   ip_gre: fix ipgre...
802
  		return t->hlen + sizeof(*iph);
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
803

c54419321   Pravin B Shelar   GRE: Refactor GRE...
804
  	return -(t->hlen + sizeof(*iph));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
805
  }
6a5f44d7a   Timo Teras   [IPV4] ip_gre: se...
806
807
  static int ipgre_header_parse(const struct sk_buff *skb, unsigned char *haddr)
  {
b71d1d426   Eric Dumazet   inet: constify ip...
808
  	const struct iphdr *iph = (const struct iphdr *) skb_mac_header(skb);
6a5f44d7a   Timo Teras   [IPV4] ip_gre: se...
809
810
811
  	memcpy(haddr, &iph->saddr, 4);
  	return 4;
  }
3b04ddde0   Stephen Hemminger   [NET]: Move hardw...
812
813
  static const struct header_ops ipgre_header_ops = {
  	.create	= ipgre_header,
6a5f44d7a   Timo Teras   [IPV4] ip_gre: se...
814
  	.parse	= ipgre_header_parse,
3b04ddde0   Stephen Hemminger   [NET]: Move hardw...
815
  };
6a5f44d7a   Timo Teras   [IPV4] ip_gre: se...
816
  #ifdef CONFIG_NET_IPGRE_BROADCAST
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
817
818
  static int ipgre_open(struct net_device *dev)
  {
2941a4863   Patrick McHardy   [NET]: Convert ne...
819
  	struct ip_tunnel *t = netdev_priv(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
820

f97c1e0c6   Joe Perches   [IPV4] net/ipv4: ...
821
  	if (ipv4_is_multicast(t->parms.iph.daddr)) {
cbb1e85f9   David S. Miller   ipv4: Kill rt->rt...
822
823
  		struct flowi4 fl4;
  		struct rtable *rt;
b57708add   Nicolas Dichtel   gre: add x-netns ...
824
  		rt = ip_route_output_gre(t->net, &fl4,
cbb1e85f9   David S. Miller   ipv4: Kill rt->rt...
825
826
827
828
829
  					 t->parms.iph.daddr,
  					 t->parms.iph.saddr,
  					 t->parms.o_key,
  					 RT_TOS(t->parms.iph.tos),
  					 t->parms.link);
b23dd4fe4   David S. Miller   ipv4: Make output...
830
  		if (IS_ERR(rt))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
831
  			return -EADDRNOTAVAIL;
d8d1f30b9   Changli Gao   net-next: remove ...
832
  		dev = rt->dst.dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
833
  		ip_rt_put(rt);
51456b291   Ian Morris   ipv4: coding styl...
834
  		if (!__in_dev_get_rtnl(dev))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
835
836
  			return -EADDRNOTAVAIL;
  		t->mlink = dev->ifindex;
e5ed63991   Herbert Xu   [IPV4]: Replace _...
837
  		ip_mc_inc_group(__in_dev_get_rtnl(dev), t->parms.iph.daddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
838
839
840
841
842
843
  	}
  	return 0;
  }
  
  static int ipgre_close(struct net_device *dev)
  {
2941a4863   Patrick McHardy   [NET]: Convert ne...
844
  	struct ip_tunnel *t = netdev_priv(dev);
b8c26a33c   Stephen Hemminger   ipgre: convert to...
845

f97c1e0c6   Joe Perches   [IPV4] net/ipv4: ...
846
  	if (ipv4_is_multicast(t->parms.iph.daddr) && t->mlink) {
7fee0ca23   Denis V. Lunev   [NETNS]: Add netn...
847
  		struct in_device *in_dev;
b57708add   Nicolas Dichtel   gre: add x-netns ...
848
  		in_dev = inetdev_by_index(t->net, t->mlink);
8723e1b4a   Eric Dumazet   inet: RCU changes...
849
  		if (in_dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
850
  			ip_mc_dec_group(in_dev, t->parms.iph.daddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
851
852
853
  	}
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
854
  #endif
b8c26a33c   Stephen Hemminger   ipgre: convert to...
855
856
  static const struct net_device_ops ipgre_netdev_ops = {
  	.ndo_init		= ipgre_tunnel_init,
c54419321   Pravin B Shelar   GRE: Refactor GRE...
857
  	.ndo_uninit		= ip_tunnel_uninit,
b8c26a33c   Stephen Hemminger   ipgre: convert to...
858
859
860
861
  #ifdef CONFIG_NET_IPGRE_BROADCAST
  	.ndo_open		= ipgre_open,
  	.ndo_stop		= ipgre_close,
  #endif
c54419321   Pravin B Shelar   GRE: Refactor GRE...
862
  	.ndo_start_xmit		= ipgre_xmit,
607259a69   Christoph Hellwig   net: add a new nd...
863
  	.ndo_do_ioctl		= ip_tunnel_ioctl,
c54419321   Pravin B Shelar   GRE: Refactor GRE...
864
865
  	.ndo_change_mtu		= ip_tunnel_change_mtu,
  	.ndo_get_stats64	= ip_tunnel_get_stats64,
1e99584b9   Nicolas Dichtel   ipip,gre,vti,sit:...
866
  	.ndo_get_iflink		= ip_tunnel_get_iflink,
607259a69   Christoph Hellwig   net: add a new nd...
867
  	.ndo_tunnel_ctl		= ipgre_tunnel_ctl,
b8c26a33c   Stephen Hemminger   ipgre: convert to...
868
  };
6b78f16e4   Eric Dumazet   gre: add GSO support
869
870
871
872
  #define GRE_FEATURES (NETIF_F_SG |		\
  		      NETIF_F_FRAGLIST |	\
  		      NETIF_F_HIGHDMA |		\
  		      NETIF_F_HW_CSUM)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
873
874
  static void ipgre_tunnel_setup(struct net_device *dev)
  {
b8c26a33c   Stephen Hemminger   ipgre: convert to...
875
  	dev->netdev_ops		= &ipgre_netdev_ops;
5a4552752   Nicolas Dichtel   gre: don't allow ...
876
  	dev->type		= ARPHRD_IPGRE;
c54419321   Pravin B Shelar   GRE: Refactor GRE...
877
878
  	ip_tunnel_setup(dev, ipgre_net_id);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
879

c54419321   Pravin B Shelar   GRE: Refactor GRE...
880
881
882
883
884
  static void __gre_tunnel_init(struct net_device *dev)
  {
  	struct ip_tunnel *tunnel;
  
  	tunnel = netdev_priv(dev);
95f5c64c3   Tom Herbert   gre: Move utility...
885
  	tunnel->tun_hlen = gre_calc_hlen(tunnel->parms.o_flags);
c54419321   Pravin B Shelar   GRE: Refactor GRE...
886
  	tunnel->parms.iph.protocol = IPPROTO_GRE;
4565e9919   Tom Herbert   gre: Setup and TX...
887
  	tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen;
fdafed459   Cong Wang   ip_gre: set dev->...
888
  	dev->needed_headroom = tunnel->hlen + sizeof(tunnel->parms.iph);
4565e9919   Tom Herbert   gre: Setup and TX...
889

b57708add   Nicolas Dichtel   gre: add x-netns ...
890
  	dev->features		|= GRE_FEATURES;
6b78f16e4   Eric Dumazet   gre: add GSO support
891
  	dev->hw_features	|= GRE_FEATURES;
c54419321   Pravin B Shelar   GRE: Refactor GRE...
892
893
  
  	if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) {
a0ca153f9   Alexander Duyck   GRE: Disable segm...
894
895
896
897
898
899
900
901
902
  		/* TCP offload with GRE SEQ is not supported, nor
  		 * can we support 2 levels of outer headers requiring
  		 * an update.
  		 */
  		if (!(tunnel->parms.o_flags & TUNNEL_CSUM) ||
  		    (tunnel->encap.type == TUNNEL_ENCAP_NONE)) {
  			dev->features    |= NETIF_F_GSO_SOFTWARE;
  			dev->hw_features |= NETIF_F_GSO_SOFTWARE;
  		}
c54419321   Pravin B Shelar   GRE: Refactor GRE...
903
904
905
906
907
  		/* Can use a lockless transmit, unless we generate
  		 * output sequences
  		 */
  		dev->features |= NETIF_F_LLTX;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
908
909
910
911
  }
  
  static int ipgre_tunnel_init(struct net_device *dev)
  {
c54419321   Pravin B Shelar   GRE: Refactor GRE...
912
913
  	struct ip_tunnel *tunnel = netdev_priv(dev);
  	struct iphdr *iph = &tunnel->parms.iph;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
914

c54419321   Pravin B Shelar   GRE: Refactor GRE...
915
  	__gre_tunnel_init(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
916

c54419321   Pravin B Shelar   GRE: Refactor GRE...
917
918
  	memcpy(dev->dev_addr, &iph->saddr, 4);
  	memcpy(dev->broadcast, &iph->daddr, 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
919

c54419321   Pravin B Shelar   GRE: Refactor GRE...
920
  	dev->flags		= IFF_NOARP;
028758788   Eric Dumazet   net: better IFF_X...
921
  	netif_keep_dst(dev);
c54419321   Pravin B Shelar   GRE: Refactor GRE...
922
  	dev->addr_len		= 4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
923

a64b04d86   Jiri Benc   gre: do not assig...
924
  	if (iph->daddr && !tunnel->collect_md) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
925
  #ifdef CONFIG_NET_IPGRE_BROADCAST
f97c1e0c6   Joe Perches   [IPV4] net/ipv4: ...
926
  		if (ipv4_is_multicast(iph->daddr)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
927
928
929
  			if (!iph->saddr)
  				return -EINVAL;
  			dev->flags = IFF_BROADCAST;
3b04ddde0   Stephen Hemminger   [NET]: Move hardw...
930
  			dev->header_ops = &ipgre_header_ops;
fdafed459   Cong Wang   ip_gre: set dev->...
931
932
  			dev->hard_header_len = tunnel->hlen + sizeof(*iph);
  			dev->needed_headroom = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
933
934
  		}
  #endif
a64b04d86   Jiri Benc   gre: do not assig...
935
  	} else if (!tunnel->collect_md) {
6a5f44d7a   Timo Teras   [IPV4] ip_gre: se...
936
  		dev->header_ops = &ipgre_header_ops;
fdafed459   Cong Wang   ip_gre: set dev->...
937
938
  		dev->hard_header_len = tunnel->hlen + sizeof(*iph);
  		dev->needed_headroom = 0;
a64b04d86   Jiri Benc   gre: do not assig...
939
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
940

c54419321   Pravin B Shelar   GRE: Refactor GRE...
941
  	return ip_tunnel_init(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
942
  }
9f57c67c3   Pravin B Shelar   gre: Remove suppo...
943
944
945
  static const struct gre_protocol ipgre_protocol = {
  	.handler     = gre_rcv,
  	.err_handler = gre_err,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
946
  };
2c8c1e729   Alexey Dobriyan   net: spread __net...
947
  static int __net_init ipgre_init_net(struct net *net)
59a4c7594   Pavel Emelyanov   [GRE]: Introduce ...
948
  {
c54419321   Pravin B Shelar   GRE: Refactor GRE...
949
  	return ip_tunnel_init_net(net, ipgre_net_id, &ipgre_link_ops, NULL);
59a4c7594   Pavel Emelyanov   [GRE]: Introduce ...
950
  }
64bc17811   Eric Dumazet   ipv4: speedup ipv...
951
  static void __net_exit ipgre_exit_batch_net(struct list_head *list_net)
59a4c7594   Pavel Emelyanov   [GRE]: Introduce ...
952
  {
64bc17811   Eric Dumazet   ipv4: speedup ipv...
953
  	ip_tunnel_delete_nets(list_net, ipgre_net_id, &ipgre_link_ops);
59a4c7594   Pavel Emelyanov   [GRE]: Introduce ...
954
955
956
957
  }
  
  static struct pernet_operations ipgre_net_ops = {
  	.init = ipgre_init_net,
64bc17811   Eric Dumazet   ipv4: speedup ipv...
958
  	.exit_batch = ipgre_exit_batch_net,
cfb8fbf22   Eric W. Biederman   net: Simplify ip_...
959
  	.id   = &ipgre_net_id,
c54419321   Pravin B Shelar   GRE: Refactor GRE...
960
  	.size = sizeof(struct ip_tunnel_net),
59a4c7594   Pavel Emelyanov   [GRE]: Introduce ...
961
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
962

a8b8a889e   Matthias Schiffer   net: add netlink_...
963
964
  static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[],
  				 struct netlink_ext_ack *extack)
c19e654dd   Herbert Xu   gre: Add netlink ...
965
966
967
968
969
970
971
972
973
974
975
976
977
  {
  	__be16 flags;
  
  	if (!data)
  		return 0;
  
  	flags = 0;
  	if (data[IFLA_GRE_IFLAGS])
  		flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]);
  	if (data[IFLA_GRE_OFLAGS])
  		flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]);
  	if (flags & (GRE_VERSION|GRE_ROUTING))
  		return -EINVAL;
946b636f1   Jiri Benc   gre: reject GUE a...
978
979
980
981
  	if (data[IFLA_GRE_COLLECT_METADATA] &&
  	    data[IFLA_GRE_ENCAP_TYPE] &&
  	    nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]) != TUNNEL_ENCAP_NONE)
  		return -EINVAL;
c19e654dd   Herbert Xu   gre: Add netlink ...
982
983
  	return 0;
  }
a8b8a889e   Matthias Schiffer   net: add netlink_...
984
985
  static int ipgre_tap_validate(struct nlattr *tb[], struct nlattr *data[],
  			      struct netlink_ext_ack *extack)
e1a800022   Herbert Xu   gre: Add Transpar...
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
  {
  	__be32 daddr;
  
  	if (tb[IFLA_ADDRESS]) {
  		if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
  			return -EINVAL;
  		if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
  			return -EADDRNOTAVAIL;
  	}
  
  	if (!data)
  		goto out;
  
  	if (data[IFLA_GRE_REMOTE]) {
  		memcpy(&daddr, nla_data(data[IFLA_GRE_REMOTE]), 4);
  		if (!daddr)
  			return -EINVAL;
  	}
  
  out:
a8b8a889e   Matthias Schiffer   net: add netlink_...
1006
  	return ipgre_tunnel_validate(tb, data, extack);
e1a800022   Herbert Xu   gre: Add Transpar...
1007
  }
84e54fe0a   William Tu   gre: introduce na...
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
  static int erspan_validate(struct nlattr *tb[], struct nlattr *data[],
  			   struct netlink_ext_ack *extack)
  {
  	__be16 flags = 0;
  	int ret;
  
  	if (!data)
  		return 0;
  
  	ret = ipgre_tap_validate(tb, data, extack);
  	if (ret)
  		return ret;
51fa960d3   William Tu   erspan: Check IFL...
1020
1021
  	if (data[IFLA_GRE_ERSPAN_VER] &&
  	    nla_get_u8(data[IFLA_GRE_ERSPAN_VER]) == 0)
f989d546a   William Tu   erspan: Add type ...
1022
1023
1024
  		return 0;
  
  	/* ERSPAN type II/III should only have GRE sequence and key flag */
1a66a836d   William Tu   gre: add collect_...
1025
1026
1027
1028
1029
1030
  	if (data[IFLA_GRE_OFLAGS])
  		flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]);
  	if (data[IFLA_GRE_IFLAGS])
  		flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]);
  	if (!data[IFLA_GRE_COLLECT_METADATA] &&
  	    flags != (GRE_SEQ | GRE_KEY))
84e54fe0a   William Tu   gre: introduce na...
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
  		return -EINVAL;
  
  	/* ERSPAN Session ID only has 10-bit. Since we reuse
  	 * 32-bit key field as ID, check it's range.
  	 */
  	if (data[IFLA_GRE_IKEY] &&
  	    (ntohl(nla_get_be32(data[IFLA_GRE_IKEY])) & ~ID_MASK))
  		return -EINVAL;
  
  	if (data[IFLA_GRE_OKEY] &&
  	    (ntohl(nla_get_be32(data[IFLA_GRE_OKEY])) & ~ID_MASK))
  		return -EINVAL;
  
  	return 0;
  }
22a59be8b   Philip Prindeville   net: ipv4: Add ab...
1046
  static int ipgre_netlink_parms(struct net_device *dev,
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
1047
1048
  				struct nlattr *data[],
  				struct nlattr *tb[],
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
1049
1050
  				struct ip_tunnel_parm *parms,
  				__u32 *fwmark)
c19e654dd   Herbert Xu   gre: Add netlink ...
1051
  {
22a59be8b   Philip Prindeville   net: ipv4: Add ab...
1052
  	struct ip_tunnel *t = netdev_priv(dev);
7bb82d924   Herbert Xu   gre: Initialise r...
1053
  	memset(parms, 0, sizeof(*parms));
c19e654dd   Herbert Xu   gre: Add netlink ...
1054
1055
1056
1057
  
  	parms->iph.protocol = IPPROTO_GRE;
  
  	if (!data)
22a59be8b   Philip Prindeville   net: ipv4: Add ab...
1058
  		return 0;
c19e654dd   Herbert Xu   gre: Add netlink ...
1059
1060
1061
1062
1063
  
  	if (data[IFLA_GRE_LINK])
  		parms->link = nla_get_u32(data[IFLA_GRE_LINK]);
  
  	if (data[IFLA_GRE_IFLAGS])
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1064
  		parms->i_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_IFLAGS]));
c19e654dd   Herbert Xu   gre: Add netlink ...
1065
1066
  
  	if (data[IFLA_GRE_OFLAGS])
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1067
  		parms->o_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_OFLAGS]));
c19e654dd   Herbert Xu   gre: Add netlink ...
1068
1069
1070
1071
1072
1073
1074
1075
  
  	if (data[IFLA_GRE_IKEY])
  		parms->i_key = nla_get_be32(data[IFLA_GRE_IKEY]);
  
  	if (data[IFLA_GRE_OKEY])
  		parms->o_key = nla_get_be32(data[IFLA_GRE_OKEY]);
  
  	if (data[IFLA_GRE_LOCAL])
67b61f6c1   Jiri Benc   netlink: implemen...
1076
  		parms->iph.saddr = nla_get_in_addr(data[IFLA_GRE_LOCAL]);
c19e654dd   Herbert Xu   gre: Add netlink ...
1077
1078
  
  	if (data[IFLA_GRE_REMOTE])
67b61f6c1   Jiri Benc   netlink: implemen...
1079
  		parms->iph.daddr = nla_get_in_addr(data[IFLA_GRE_REMOTE]);
c19e654dd   Herbert Xu   gre: Add netlink ...
1080
1081
1082
1083
1084
1085
  
  	if (data[IFLA_GRE_TTL])
  		parms->iph.ttl = nla_get_u8(data[IFLA_GRE_TTL]);
  
  	if (data[IFLA_GRE_TOS])
  		parms->iph.tos = nla_get_u8(data[IFLA_GRE_TOS]);
22a59be8b   Philip Prindeville   net: ipv4: Add ab...
1086
1087
1088
  	if (!data[IFLA_GRE_PMTUDISC] || nla_get_u8(data[IFLA_GRE_PMTUDISC])) {
  		if (t->ignore_df)
  			return -EINVAL;
c19e654dd   Herbert Xu   gre: Add netlink ...
1089
  		parms->iph.frag_off = htons(IP_DF);
22a59be8b   Philip Prindeville   net: ipv4: Add ab...
1090
  	}
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
1091
1092
  
  	if (data[IFLA_GRE_COLLECT_METADATA]) {
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
1093
  		t->collect_md = true;
e271c7b44   Jiri Benc   gre: do not keep ...
1094
1095
  		if (dev->type == ARPHRD_IPGRE)
  			dev->type = ARPHRD_NONE;
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
1096
  	}
22a59be8b   Philip Prindeville   net: ipv4: Add ab...
1097
1098
1099
1100
1101
1102
1103
  
  	if (data[IFLA_GRE_IGNORE_DF]) {
  		if (nla_get_u8(data[IFLA_GRE_IGNORE_DF])
  		  && (parms->iph.frag_off & htons(IP_DF)))
  			return -EINVAL;
  		t->ignore_df = !!nla_get_u8(data[IFLA_GRE_IGNORE_DF]);
  	}
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
1104
1105
  	if (data[IFLA_GRE_FWMARK])
  		*fwmark = nla_get_u32(data[IFLA_GRE_FWMARK]);
e1f8f78ff   Petr Machata   net: ip_gre: Sepa...
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
  	return 0;
  }
  
  static int erspan_netlink_parms(struct net_device *dev,
  				struct nlattr *data[],
  				struct nlattr *tb[],
  				struct ip_tunnel_parm *parms,
  				__u32 *fwmark)
  {
  	struct ip_tunnel *t = netdev_priv(dev);
  	int err;
  
  	err = ipgre_netlink_parms(dev, data, tb, parms, fwmark);
  	if (err)
  		return err;
32ca98fea   Petr Machata   net: ip_gre: Acce...
1121
1122
  	if (!data)
  		return 0;
e1f8f78ff   Petr Machata   net: ip_gre: Sepa...
1123

f551c91de   William Tu   net: erspan: intr...
1124
1125
  	if (data[IFLA_GRE_ERSPAN_VER]) {
  		t->erspan_ver = nla_get_u8(data[IFLA_GRE_ERSPAN_VER]);
84e54fe0a   William Tu   gre: introduce na...
1126

f989d546a   William Tu   erspan: Add type ...
1127
  		if (t->erspan_ver > 2)
84e54fe0a   William Tu   gre: introduce na...
1128
1129
  			return -EINVAL;
  	}
f551c91de   William Tu   net: erspan: intr...
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
  	if (t->erspan_ver == 1) {
  		if (data[IFLA_GRE_ERSPAN_INDEX]) {
  			t->index = nla_get_u32(data[IFLA_GRE_ERSPAN_INDEX]);
  			if (t->index & ~INDEX_MASK)
  				return -EINVAL;
  		}
  	} else if (t->erspan_ver == 2) {
  		if (data[IFLA_GRE_ERSPAN_DIR]) {
  			t->dir = nla_get_u8(data[IFLA_GRE_ERSPAN_DIR]);
  			if (t->dir & ~(DIR_MASK >> DIR_OFFSET))
  				return -EINVAL;
  		}
  		if (data[IFLA_GRE_ERSPAN_HWID]) {
  			t->hwid = nla_get_u16(data[IFLA_GRE_ERSPAN_HWID]);
  			if (t->hwid & ~(HWID_MASK >> HWID_OFFSET))
  				return -EINVAL;
  		}
  	}
22a59be8b   Philip Prindeville   net: ipv4: Add ab...
1148
  	return 0;
c19e654dd   Herbert Xu   gre: Add netlink ...
1149
  }
4565e9919   Tom Herbert   gre: Setup and TX...
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
  /* This function returns true when ENCAP attributes are present in the nl msg */
  static bool ipgre_netlink_encap_parms(struct nlattr *data[],
  				      struct ip_tunnel_encap *ipencap)
  {
  	bool ret = false;
  
  	memset(ipencap, 0, sizeof(*ipencap));
  
  	if (!data)
  		return ret;
  
  	if (data[IFLA_GRE_ENCAP_TYPE]) {
  		ret = true;
  		ipencap->type = nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]);
  	}
  
  	if (data[IFLA_GRE_ENCAP_FLAGS]) {
  		ret = true;
  		ipencap->flags = nla_get_u16(data[IFLA_GRE_ENCAP_FLAGS]);
  	}
  
  	if (data[IFLA_GRE_ENCAP_SPORT]) {
  		ret = true;
3e97fa705   Sabrina Dubroca   gre/ipip: use be1...
1173
  		ipencap->sport = nla_get_be16(data[IFLA_GRE_ENCAP_SPORT]);
4565e9919   Tom Herbert   gre: Setup and TX...
1174
1175
1176
1177
  	}
  
  	if (data[IFLA_GRE_ENCAP_DPORT]) {
  		ret = true;
3e97fa705   Sabrina Dubroca   gre/ipip: use be1...
1178
  		ipencap->dport = nla_get_be16(data[IFLA_GRE_ENCAP_DPORT]);
4565e9919   Tom Herbert   gre: Setup and TX...
1179
1180
1181
1182
  	}
  
  	return ret;
  }
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1183
  static int gre_tap_init(struct net_device *dev)
e1a800022   Herbert Xu   gre: Add Transpar...
1184
  {
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1185
  	__gre_tunnel_init(dev);
bec94d430   stephen hemminger   gre: allow live a...
1186
  	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
d51711c05   Xin Long   ip_gre: ipgre_tap...
1187
  	netif_keep_dst(dev);
e1a800022   Herbert Xu   gre: Add Transpar...
1188

c54419321   Pravin B Shelar   GRE: Refactor GRE...
1189
  	return ip_tunnel_init(dev);
e1a800022   Herbert Xu   gre: Add Transpar...
1190
  }
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1191
1192
1193
1194
  static const struct net_device_ops gre_tap_netdev_ops = {
  	.ndo_init		= gre_tap_init,
  	.ndo_uninit		= ip_tunnel_uninit,
  	.ndo_start_xmit		= gre_tap_xmit,
b8c26a33c   Stephen Hemminger   ipgre: convert to...
1195
1196
  	.ndo_set_mac_address 	= eth_mac_addr,
  	.ndo_validate_addr	= eth_validate_addr,
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1197
1198
  	.ndo_change_mtu		= ip_tunnel_change_mtu,
  	.ndo_get_stats64	= ip_tunnel_get_stats64,
1e99584b9   Nicolas Dichtel   ipip,gre,vti,sit:...
1199
  	.ndo_get_iflink		= ip_tunnel_get_iflink,
fc4099f17   Pravin B Shelar   openvswitch: Fix ...
1200
  	.ndo_fill_metadata_dst	= gre_fill_metadata_dst,
b8c26a33c   Stephen Hemminger   ipgre: convert to...
1201
  };
84e54fe0a   William Tu   gre: introduce na...
1202
1203
1204
  static int erspan_tunnel_init(struct net_device *dev)
  {
  	struct ip_tunnel *tunnel = netdev_priv(dev);
84e54fe0a   William Tu   gre: introduce na...
1205

f989d546a   William Tu   erspan: Add type ...
1206
1207
1208
1209
  	if (tunnel->erspan_ver == 0)
  		tunnel->tun_hlen = 4; /* 4-byte GRE hdr. */
  	else
  		tunnel->tun_hlen = 8; /* 8-byte GRE hdr. */
84e54fe0a   William Tu   gre: introduce na...
1210
  	tunnel->parms.iph.protocol = IPPROTO_GRE;
c122fda27   Xin Long   ip_gre: set tunne...
1211
  	tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen +
f551c91de   William Tu   net: erspan: intr...
1212
  		       erspan_hdr_len(tunnel->erspan_ver);
84e54fe0a   William Tu   gre: introduce na...
1213

84e54fe0a   William Tu   gre: introduce na...
1214
1215
1216
  	dev->features		|= GRE_FEATURES;
  	dev->hw_features	|= GRE_FEATURES;
  	dev->priv_flags		|= IFF_LIVE_ADDR_CHANGE;
c84bed440   Xin Long   ip_gre: erspan de...
1217
  	netif_keep_dst(dev);
84e54fe0a   William Tu   gre: introduce na...
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
  
  	return ip_tunnel_init(dev);
  }
  
  static const struct net_device_ops erspan_netdev_ops = {
  	.ndo_init		= erspan_tunnel_init,
  	.ndo_uninit		= ip_tunnel_uninit,
  	.ndo_start_xmit		= erspan_xmit,
  	.ndo_set_mac_address	= eth_mac_addr,
  	.ndo_validate_addr	= eth_validate_addr,
  	.ndo_change_mtu		= ip_tunnel_change_mtu,
  	.ndo_get_stats64	= ip_tunnel_get_stats64,
  	.ndo_get_iflink		= ip_tunnel_get_iflink,
  	.ndo_fill_metadata_dst	= gre_fill_metadata_dst,
  };
e1a800022   Herbert Xu   gre: Add Transpar...
1233
1234
  static void ipgre_tap_setup(struct net_device *dev)
  {
e1a800022   Herbert Xu   gre: Add Transpar...
1235
  	ether_setup(dev);
cfddd4c33   Xin Long   ip_gre: remove th...
1236
  	dev->max_mtu = 0;
d13b161c2   Jiri Benc   gre: clear IFF_TX...
1237
1238
1239
  	dev->netdev_ops	= &gre_tap_netdev_ops;
  	dev->priv_flags &= ~IFF_TX_SKB_SHARING;
  	dev->priv_flags	|= IFF_LIVE_ADDR_CHANGE;
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1240
  	ip_tunnel_setup(dev, gre_tap_net_id);
e1a800022   Herbert Xu   gre: Add Transpar...
1241
  }
e1f8f78ff   Petr Machata   net: ip_gre: Sepa...
1242
1243
  static int
  ipgre_newlink_encap_setup(struct net_device *dev, struct nlattr *data[])
c19e654dd   Herbert Xu   gre: Add netlink ...
1244
  {
4565e9919   Tom Herbert   gre: Setup and TX...
1245
1246
1247
1248
  	struct ip_tunnel_encap ipencap;
  
  	if (ipgre_netlink_encap_parms(data, &ipencap)) {
  		struct ip_tunnel *t = netdev_priv(dev);
e1f8f78ff   Petr Machata   net: ip_gre: Sepa...
1249
  		int err = ip_tunnel_encap_setup(t, &ipencap);
4565e9919   Tom Herbert   gre: Setup and TX...
1250
1251
1252
1253
  
  		if (err < 0)
  			return err;
  	}
c19e654dd   Herbert Xu   gre: Add netlink ...
1254

e1f8f78ff   Petr Machata   net: ip_gre: Sepa...
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
  	return 0;
  }
  
  static int ipgre_newlink(struct net *src_net, struct net_device *dev,
  			 struct nlattr *tb[], struct nlattr *data[],
  			 struct netlink_ext_ack *extack)
  {
  	struct ip_tunnel_parm p;
  	__u32 fwmark = 0;
  	int err;
  
  	err = ipgre_newlink_encap_setup(dev, data);
  	if (err)
  		return err;
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
1269
  	err = ipgre_netlink_parms(dev, data, tb, &p, &fwmark);
22a59be8b   Philip Prindeville   net: ipv4: Add ab...
1270
1271
  	if (err < 0)
  		return err;
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
1272
  	return ip_tunnel_newlink(dev, tb, &p, fwmark);
c19e654dd   Herbert Xu   gre: Add netlink ...
1273
  }
e1f8f78ff   Petr Machata   net: ip_gre: Sepa...
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
  static int erspan_newlink(struct net *src_net, struct net_device *dev,
  			  struct nlattr *tb[], struct nlattr *data[],
  			  struct netlink_ext_ack *extack)
  {
  	struct ip_tunnel_parm p;
  	__u32 fwmark = 0;
  	int err;
  
  	err = ipgre_newlink_encap_setup(dev, data);
  	if (err)
  		return err;
  
  	err = erspan_netlink_parms(dev, data, tb, &p, &fwmark);
  	if (err)
  		return err;
  	return ip_tunnel_newlink(dev, tb, &p, fwmark);
  }
c19e654dd   Herbert Xu   gre: Add netlink ...
1291
  static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[],
ad744b223   Matthias Schiffer   net: add netlink_...
1292
1293
  			    struct nlattr *data[],
  			    struct netlink_ext_ack *extack)
c19e654dd   Herbert Xu   gre: Add netlink ...
1294
  {
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
1295
  	struct ip_tunnel *t = netdev_priv(dev);
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
1296
  	__u32 fwmark = t->fwmark;
dd9d598c6   Xin Long   ip_gre: add the s...
1297
  	struct ip_tunnel_parm p;
22a59be8b   Philip Prindeville   net: ipv4: Add ab...
1298
  	int err;
4565e9919   Tom Herbert   gre: Setup and TX...
1299

e1f8f78ff   Petr Machata   net: ip_gre: Sepa...
1300
1301
1302
  	err = ipgre_newlink_encap_setup(dev, data);
  	if (err)
  		return err;
c19e654dd   Herbert Xu   gre: Add netlink ...
1303

9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
1304
  	err = ipgre_netlink_parms(dev, data, tb, &p, &fwmark);
22a59be8b   Philip Prindeville   net: ipv4: Add ab...
1305
1306
  	if (err < 0)
  		return err;
dd9d598c6   Xin Long   ip_gre: add the s...
1307
1308
1309
1310
1311
1312
1313
  
  	err = ip_tunnel_changelink(dev, tb, &p, fwmark);
  	if (err < 0)
  		return err;
  
  	t->parms.i_flags = p.i_flags;
  	t->parms.o_flags = p.o_flags;
e1f8f78ff   Petr Machata   net: ip_gre: Sepa...
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
  	ipgre_link_update(dev, !tb[IFLA_MTU]);
  
  	return 0;
  }
  
  static int erspan_changelink(struct net_device *dev, struct nlattr *tb[],
  			     struct nlattr *data[],
  			     struct netlink_ext_ack *extack)
  {
  	struct ip_tunnel *t = netdev_priv(dev);
  	__u32 fwmark = t->fwmark;
  	struct ip_tunnel_parm p;
  	int err;
  
  	err = ipgre_newlink_encap_setup(dev, data);
  	if (err)
  		return err;
  
  	err = erspan_netlink_parms(dev, data, tb, &p, &fwmark);
  	if (err < 0)
  		return err;
  
  	err = ip_tunnel_changelink(dev, tb, &p, fwmark);
  	if (err < 0)
  		return err;
  
  	t->parms.i_flags = p.i_flags;
  	t->parms.o_flags = p.o_flags;
dd9d598c6   Xin Long   ip_gre: add the s...
1342
1343
  
  	return 0;
c19e654dd   Herbert Xu   gre: Add netlink ...
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
  }
  
  static size_t ipgre_get_size(const struct net_device *dev)
  {
  	return
  		/* IFLA_GRE_LINK */
  		nla_total_size(4) +
  		/* IFLA_GRE_IFLAGS */
  		nla_total_size(2) +
  		/* IFLA_GRE_OFLAGS */
  		nla_total_size(2) +
  		/* IFLA_GRE_IKEY */
  		nla_total_size(4) +
  		/* IFLA_GRE_OKEY */
  		nla_total_size(4) +
  		/* IFLA_GRE_LOCAL */
  		nla_total_size(4) +
  		/* IFLA_GRE_REMOTE */
  		nla_total_size(4) +
  		/* IFLA_GRE_TTL */
  		nla_total_size(1) +
  		/* IFLA_GRE_TOS */
  		nla_total_size(1) +
  		/* IFLA_GRE_PMTUDISC */
  		nla_total_size(1) +
4565e9919   Tom Herbert   gre: Setup and TX...
1369
1370
1371
1372
1373
1374
1375
1376
  		/* IFLA_GRE_ENCAP_TYPE */
  		nla_total_size(2) +
  		/* IFLA_GRE_ENCAP_FLAGS */
  		nla_total_size(2) +
  		/* IFLA_GRE_ENCAP_SPORT */
  		nla_total_size(2) +
  		/* IFLA_GRE_ENCAP_DPORT */
  		nla_total_size(2) +
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
1377
1378
  		/* IFLA_GRE_COLLECT_METADATA */
  		nla_total_size(0) +
22a59be8b   Philip Prindeville   net: ipv4: Add ab...
1379
1380
  		/* IFLA_GRE_IGNORE_DF */
  		nla_total_size(1) +
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
1381
1382
  		/* IFLA_GRE_FWMARK */
  		nla_total_size(4) +
84e54fe0a   William Tu   gre: introduce na...
1383
1384
  		/* IFLA_GRE_ERSPAN_INDEX */
  		nla_total_size(4) +
f551c91de   William Tu   net: erspan: intr...
1385
1386
1387
1388
1389
1390
  		/* IFLA_GRE_ERSPAN_VER */
  		nla_total_size(1) +
  		/* IFLA_GRE_ERSPAN_DIR */
  		nla_total_size(1) +
  		/* IFLA_GRE_ERSPAN_HWID */
  		nla_total_size(2) +
c19e654dd   Herbert Xu   gre: Add netlink ...
1391
1392
1393
1394
1395
1396
1397
  		0;
  }
  
  static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev)
  {
  	struct ip_tunnel *t = netdev_priv(dev);
  	struct ip_tunnel_parm *p = &t->parms;
feaf5c796   Lorenzo Bianconi   net: ip_gre: alwa...
1398
  	__be16 o_flags = p->o_flags;
f989d546a   William Tu   erspan: Add type ...
1399
1400
  	if (t->erspan_ver <= 2) {
  		if (t->erspan_ver != 0 && !t->collect_md)
2bdf700e5   Lorenzo Bianconi   net: ip_gre: do n...
1401
1402
1403
1404
1405
1406
1407
1408
  			o_flags |= TUNNEL_KEY;
  
  		if (nla_put_u8(skb, IFLA_GRE_ERSPAN_VER, t->erspan_ver))
  			goto nla_put_failure;
  
  		if (t->erspan_ver == 1) {
  			if (nla_put_u32(skb, IFLA_GRE_ERSPAN_INDEX, t->index))
  				goto nla_put_failure;
f989d546a   William Tu   erspan: Add type ...
1409
  		} else if (t->erspan_ver == 2) {
2bdf700e5   Lorenzo Bianconi   net: ip_gre: do n...
1410
1411
1412
1413
1414
1415
  			if (nla_put_u8(skb, IFLA_GRE_ERSPAN_DIR, t->dir))
  				goto nla_put_failure;
  			if (nla_put_u16(skb, IFLA_GRE_ERSPAN_HWID, t->hwid))
  				goto nla_put_failure;
  		}
  	}
c19e654dd   Herbert Xu   gre: Add netlink ...
1416

f3756b79e   David S. Miller   ipv4: Stop using ...
1417
  	if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) ||
95f5c64c3   Tom Herbert   gre: Move utility...
1418
1419
1420
  	    nla_put_be16(skb, IFLA_GRE_IFLAGS,
  			 gre_tnl_flags_to_gre_flags(p->i_flags)) ||
  	    nla_put_be16(skb, IFLA_GRE_OFLAGS,
feaf5c796   Lorenzo Bianconi   net: ip_gre: alwa...
1421
  			 gre_tnl_flags_to_gre_flags(o_flags)) ||
f3756b79e   David S. Miller   ipv4: Stop using ...
1422
1423
  	    nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) ||
  	    nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) ||
930345ea6   Jiri Benc   netlink: implemen...
1424
1425
  	    nla_put_in_addr(skb, IFLA_GRE_LOCAL, p->iph.saddr) ||
  	    nla_put_in_addr(skb, IFLA_GRE_REMOTE, p->iph.daddr) ||
f3756b79e   David S. Miller   ipv4: Stop using ...
1426
1427
1428
  	    nla_put_u8(skb, IFLA_GRE_TTL, p->iph.ttl) ||
  	    nla_put_u8(skb, IFLA_GRE_TOS, p->iph.tos) ||
  	    nla_put_u8(skb, IFLA_GRE_PMTUDISC,
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
1429
1430
  		       !!(p->iph.frag_off & htons(IP_DF))) ||
  	    nla_put_u32(skb, IFLA_GRE_FWMARK, t->fwmark))
f3756b79e   David S. Miller   ipv4: Stop using ...
1431
  		goto nla_put_failure;
4565e9919   Tom Herbert   gre: Setup and TX...
1432
1433
1434
  
  	if (nla_put_u16(skb, IFLA_GRE_ENCAP_TYPE,
  			t->encap.type) ||
3e97fa705   Sabrina Dubroca   gre/ipip: use be1...
1435
1436
1437
1438
  	    nla_put_be16(skb, IFLA_GRE_ENCAP_SPORT,
  			 t->encap.sport) ||
  	    nla_put_be16(skb, IFLA_GRE_ENCAP_DPORT,
  			 t->encap.dport) ||
4565e9919   Tom Herbert   gre: Setup and TX...
1439
  	    nla_put_u16(skb, IFLA_GRE_ENCAP_FLAGS,
e1b2cb655   Tom Herbert   fou: Fix typo in ...
1440
  			t->encap.flags))
4565e9919   Tom Herbert   gre: Setup and TX...
1441
  		goto nla_put_failure;
22a59be8b   Philip Prindeville   net: ipv4: Add ab...
1442
1443
  	if (nla_put_u8(skb, IFLA_GRE_IGNORE_DF, t->ignore_df))
  		goto nla_put_failure;
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
1444
1445
1446
1447
  	if (t->collect_md) {
  		if (nla_put_flag(skb, IFLA_GRE_COLLECT_METADATA))
  			goto nla_put_failure;
  	}
c19e654dd   Herbert Xu   gre: Add netlink ...
1448
1449
1450
1451
1452
  	return 0;
  
  nla_put_failure:
  	return -EMSGSIZE;
  }
84e54fe0a   William Tu   gre: introduce na...
1453
1454
  static void erspan_setup(struct net_device *dev)
  {
84581bdae   Xin Long   erspan: set erspa...
1455
  	struct ip_tunnel *t = netdev_priv(dev);
84e54fe0a   William Tu   gre: introduce na...
1456
  	ether_setup(dev);
0e141f757   Haishuang Yan   erspan: remove th...
1457
  	dev->max_mtu = 0;
84e54fe0a   William Tu   gre: introduce na...
1458
1459
1460
1461
  	dev->netdev_ops = &erspan_netdev_ops;
  	dev->priv_flags &= ~IFF_TX_SKB_SHARING;
  	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
  	ip_tunnel_setup(dev, erspan_net_id);
84581bdae   Xin Long   erspan: set erspa...
1462
  	t->erspan_ver = 1;
84e54fe0a   William Tu   gre: introduce na...
1463
  }
c19e654dd   Herbert Xu   gre: Add netlink ...
1464
1465
1466
1467
1468
1469
  static const struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = {
  	[IFLA_GRE_LINK]		= { .type = NLA_U32 },
  	[IFLA_GRE_IFLAGS]	= { .type = NLA_U16 },
  	[IFLA_GRE_OFLAGS]	= { .type = NLA_U16 },
  	[IFLA_GRE_IKEY]		= { .type = NLA_U32 },
  	[IFLA_GRE_OKEY]		= { .type = NLA_U32 },
c593642c8   Pankaj Bharadiya   treewide: Use siz...
1470
1471
  	[IFLA_GRE_LOCAL]	= { .len = sizeof_field(struct iphdr, saddr) },
  	[IFLA_GRE_REMOTE]	= { .len = sizeof_field(struct iphdr, daddr) },
c19e654dd   Herbert Xu   gre: Add netlink ...
1472
1473
1474
  	[IFLA_GRE_TTL]		= { .type = NLA_U8 },
  	[IFLA_GRE_TOS]		= { .type = NLA_U8 },
  	[IFLA_GRE_PMTUDISC]	= { .type = NLA_U8 },
4565e9919   Tom Herbert   gre: Setup and TX...
1475
1476
1477
1478
  	[IFLA_GRE_ENCAP_TYPE]	= { .type = NLA_U16 },
  	[IFLA_GRE_ENCAP_FLAGS]	= { .type = NLA_U16 },
  	[IFLA_GRE_ENCAP_SPORT]	= { .type = NLA_U16 },
  	[IFLA_GRE_ENCAP_DPORT]	= { .type = NLA_U16 },
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
1479
  	[IFLA_GRE_COLLECT_METADATA]	= { .type = NLA_FLAG },
22a59be8b   Philip Prindeville   net: ipv4: Add ab...
1480
  	[IFLA_GRE_IGNORE_DF]	= { .type = NLA_U8 },
9830ad4c6   Craig Gallek   ip_tunnel: Allow ...
1481
  	[IFLA_GRE_FWMARK]	= { .type = NLA_U32 },
84e54fe0a   William Tu   gre: introduce na...
1482
  	[IFLA_GRE_ERSPAN_INDEX]	= { .type = NLA_U32 },
f551c91de   William Tu   net: erspan: intr...
1483
1484
1485
  	[IFLA_GRE_ERSPAN_VER]	= { .type = NLA_U8 },
  	[IFLA_GRE_ERSPAN_DIR]	= { .type = NLA_U8 },
  	[IFLA_GRE_ERSPAN_HWID]	= { .type = NLA_U16 },
c19e654dd   Herbert Xu   gre: Add netlink ...
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
  };
  
  static struct rtnl_link_ops ipgre_link_ops __read_mostly = {
  	.kind		= "gre",
  	.maxtype	= IFLA_GRE_MAX,
  	.policy		= ipgre_policy,
  	.priv_size	= sizeof(struct ip_tunnel),
  	.setup		= ipgre_tunnel_setup,
  	.validate	= ipgre_tunnel_validate,
  	.newlink	= ipgre_newlink,
  	.changelink	= ipgre_changelink,
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1497
  	.dellink	= ip_tunnel_dellink,
c19e654dd   Herbert Xu   gre: Add netlink ...
1498
1499
  	.get_size	= ipgre_get_size,
  	.fill_info	= ipgre_fill_info,
1728d4fab   Nicolas Dichtel   tunnels: advertis...
1500
  	.get_link_net	= ip_tunnel_get_link_net,
c19e654dd   Herbert Xu   gre: Add netlink ...
1501
  };
e1a800022   Herbert Xu   gre: Add Transpar...
1502
1503
1504
1505
1506
1507
1508
1509
1510
  static struct rtnl_link_ops ipgre_tap_ops __read_mostly = {
  	.kind		= "gretap",
  	.maxtype	= IFLA_GRE_MAX,
  	.policy		= ipgre_policy,
  	.priv_size	= sizeof(struct ip_tunnel),
  	.setup		= ipgre_tap_setup,
  	.validate	= ipgre_tap_validate,
  	.newlink	= ipgre_newlink,
  	.changelink	= ipgre_changelink,
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1511
  	.dellink	= ip_tunnel_dellink,
e1a800022   Herbert Xu   gre: Add Transpar...
1512
1513
  	.get_size	= ipgre_get_size,
  	.fill_info	= ipgre_fill_info,
1728d4fab   Nicolas Dichtel   tunnels: advertis...
1514
  	.get_link_net	= ip_tunnel_get_link_net,
e1a800022   Herbert Xu   gre: Add Transpar...
1515
  };
84e54fe0a   William Tu   gre: introduce na...
1516
1517
1518
1519
1520
1521
1522
  static struct rtnl_link_ops erspan_link_ops __read_mostly = {
  	.kind		= "erspan",
  	.maxtype	= IFLA_GRE_MAX,
  	.policy		= ipgre_policy,
  	.priv_size	= sizeof(struct ip_tunnel),
  	.setup		= erspan_setup,
  	.validate	= erspan_validate,
e1f8f78ff   Petr Machata   net: ip_gre: Sepa...
1523
1524
  	.newlink	= erspan_newlink,
  	.changelink	= erspan_changelink,
84e54fe0a   William Tu   gre: introduce na...
1525
1526
1527
1528
1529
  	.dellink	= ip_tunnel_dellink,
  	.get_size	= ipgre_get_size,
  	.fill_info	= ipgre_fill_info,
  	.get_link_net	= ip_tunnel_get_link_net,
  };
b2acd1dc3   Pravin B Shelar   openvswitch: Use ...
1530
1531
1532
1533
1534
  struct net_device *gretap_fb_dev_create(struct net *net, const char *name,
  					u8 name_assign_type)
  {
  	struct nlattr *tb[IFLA_MAX + 1];
  	struct net_device *dev;
106da663f   Nicolas Dichtel   ovs/gre,geneve: f...
1535
  	LIST_HEAD(list_kill);
b2acd1dc3   Pravin B Shelar   openvswitch: Use ...
1536
1537
1538
1539
1540
1541
  	struct ip_tunnel *t;
  	int err;
  
  	memset(&tb, 0, sizeof(tb));
  
  	dev = rtnl_create_link(net, name, name_assign_type,
d0522f1cd   David Ahern   net: Add extack a...
1542
  			       &ipgre_tap_ops, tb, NULL);
b2acd1dc3   Pravin B Shelar   openvswitch: Use ...
1543
1544
1545
1546
1547
1548
  	if (IS_ERR(dev))
  		return dev;
  
  	/* Configure flow based GRE device. */
  	t = netdev_priv(dev);
  	t->collect_md = true;
7a3f4a185   Matthias Schiffer   net: add netlink_...
1549
  	err = ipgre_newlink(net, dev, tb, NULL, NULL);
106da663f   Nicolas Dichtel   ovs/gre,geneve: f...
1550
1551
1552
1553
  	if (err < 0) {
  		free_netdev(dev);
  		return ERR_PTR(err);
  	}
7e059158d   David Wragg   vxlan, gre, genev...
1554
1555
1556
1557
1558
1559
1560
  
  	/* openvswitch users expect packet sizes to be unrestricted,
  	 * so set the largest MTU we can.
  	 */
  	err = __ip_tunnel_change_mtu(dev, IP_MAX_MTU, false);
  	if (err)
  		goto out;
da6f1da81   Nicolas Dichtel   ovs/gre: fix rtnl...
1561
1562
1563
  	err = rtnl_configure_link(dev, NULL);
  	if (err < 0)
  		goto out;
b2acd1dc3   Pravin B Shelar   openvswitch: Use ...
1564
1565
  	return dev;
  out:
106da663f   Nicolas Dichtel   ovs/gre,geneve: f...
1566
1567
  	ip_tunnel_dellink(dev, &list_kill);
  	unregister_netdevice_many(&list_kill);
b2acd1dc3   Pravin B Shelar   openvswitch: Use ...
1568
1569
1570
  	return ERR_PTR(err);
  }
  EXPORT_SYMBOL_GPL(gretap_fb_dev_create);
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1571
1572
  static int __net_init ipgre_tap_init_net(struct net *net)
  {
2e15ea390   Pravin B Shelar   ip_gre: Add suppo...
1573
  	return ip_tunnel_init_net(net, gre_tap_net_id, &ipgre_tap_ops, "gretap0");
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1574
  }
64bc17811   Eric Dumazet   ipv4: speedup ipv...
1575
  static void __net_exit ipgre_tap_exit_batch_net(struct list_head *list_net)
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1576
  {
64bc17811   Eric Dumazet   ipv4: speedup ipv...
1577
  	ip_tunnel_delete_nets(list_net, gre_tap_net_id, &ipgre_tap_ops);
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1578
1579
1580
1581
  }
  
  static struct pernet_operations ipgre_tap_net_ops = {
  	.init = ipgre_tap_init_net,
64bc17811   Eric Dumazet   ipv4: speedup ipv...
1582
  	.exit_batch = ipgre_tap_exit_batch_net,
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1583
1584
1585
  	.id   = &gre_tap_net_id,
  	.size = sizeof(struct ip_tunnel_net),
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1586

84e54fe0a   William Tu   gre: introduce na...
1587
1588
1589
1590
1591
  static int __net_init erspan_init_net(struct net *net)
  {
  	return ip_tunnel_init_net(net, erspan_net_id,
  				  &erspan_link_ops, "erspan0");
  }
64bc17811   Eric Dumazet   ipv4: speedup ipv...
1592
  static void __net_exit erspan_exit_batch_net(struct list_head *net_list)
84e54fe0a   William Tu   gre: introduce na...
1593
  {
64bc17811   Eric Dumazet   ipv4: speedup ipv...
1594
  	ip_tunnel_delete_nets(net_list, erspan_net_id, &erspan_link_ops);
84e54fe0a   William Tu   gre: introduce na...
1595
1596
1597
1598
  }
  
  static struct pernet_operations erspan_net_ops = {
  	.init = erspan_init_net,
64bc17811   Eric Dumazet   ipv4: speedup ipv...
1599
  	.exit_batch = erspan_exit_batch_net,
84e54fe0a   William Tu   gre: introduce na...
1600
1601
1602
  	.id   = &erspan_net_id,
  	.size = sizeof(struct ip_tunnel_net),
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1603
1604
1605
  static int __init ipgre_init(void)
  {
  	int err;
058bd4d2a   Joe Perches   net: Convert prin...
1606
1607
  	pr_info("GRE over IPv4 tunneling driver
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1608

cfb8fbf22   Eric W. Biederman   net: Simplify ip_...
1609
  	err = register_pernet_device(&ipgre_net_ops);
59a4c7594   Pavel Emelyanov   [GRE]: Introduce ...
1610
  	if (err < 0)
c2892f027   Alexey Dobriyan   gre: fix netns vs...
1611
  		return err;
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1612
1613
  	err = register_pernet_device(&ipgre_tap_net_ops);
  	if (err < 0)
e3d0328c7   William Tu   gre: fix goto sta...
1614
  		goto pnet_tap_failed;
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1615

84e54fe0a   William Tu   gre: introduce na...
1616
1617
1618
  	err = register_pernet_device(&erspan_net_ops);
  	if (err < 0)
  		goto pnet_erspan_failed;
9f57c67c3   Pravin B Shelar   gre: Remove suppo...
1619
  	err = gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO);
c2892f027   Alexey Dobriyan   gre: fix netns vs...
1620
  	if (err < 0) {
058bd4d2a   Joe Perches   net: Convert prin...
1621
1622
  		pr_info("%s: can't add protocol
  ", __func__);
c2892f027   Alexey Dobriyan   gre: fix netns vs...
1623
1624
  		goto add_proto_failed;
  	}
7daa00048   Pavel Emelyanov   [GRE]: Make the f...
1625

c19e654dd   Herbert Xu   gre: Add netlink ...
1626
1627
1628
  	err = rtnl_link_register(&ipgre_link_ops);
  	if (err < 0)
  		goto rtnl_link_failed;
e1a800022   Herbert Xu   gre: Add Transpar...
1629
1630
1631
  	err = rtnl_link_register(&ipgre_tap_ops);
  	if (err < 0)
  		goto tap_ops_failed;
84e54fe0a   William Tu   gre: introduce na...
1632
1633
1634
  	err = rtnl_link_register(&erspan_link_ops);
  	if (err < 0)
  		goto erspan_link_failed;
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1635
  	return 0;
c19e654dd   Herbert Xu   gre: Add netlink ...
1636

84e54fe0a   William Tu   gre: introduce na...
1637
1638
  erspan_link_failed:
  	rtnl_link_unregister(&ipgre_tap_ops);
e1a800022   Herbert Xu   gre: Add Transpar...
1639
1640
  tap_ops_failed:
  	rtnl_link_unregister(&ipgre_link_ops);
c19e654dd   Herbert Xu   gre: Add netlink ...
1641
  rtnl_link_failed:
9f57c67c3   Pravin B Shelar   gre: Remove suppo...
1642
  	gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
c2892f027   Alexey Dobriyan   gre: fix netns vs...
1643
  add_proto_failed:
84e54fe0a   William Tu   gre: introduce na...
1644
1645
  	unregister_pernet_device(&erspan_net_ops);
  pnet_erspan_failed:
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1646
  	unregister_pernet_device(&ipgre_tap_net_ops);
e3d0328c7   William Tu   gre: fix goto sta...
1647
  pnet_tap_failed:
c2892f027   Alexey Dobriyan   gre: fix netns vs...
1648
  	unregister_pernet_device(&ipgre_net_ops);
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1649
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1650
  }
db44575f6   Alexey Kuznetsov   [NET]: fix oops a...
1651
  static void __exit ipgre_fini(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1652
  {
e1a800022   Herbert Xu   gre: Add Transpar...
1653
  	rtnl_link_unregister(&ipgre_tap_ops);
c19e654dd   Herbert Xu   gre: Add netlink ...
1654
  	rtnl_link_unregister(&ipgre_link_ops);
84e54fe0a   William Tu   gre: introduce na...
1655
  	rtnl_link_unregister(&erspan_link_ops);
9f57c67c3   Pravin B Shelar   gre: Remove suppo...
1656
  	gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1657
  	unregister_pernet_device(&ipgre_tap_net_ops);
c2892f027   Alexey Dobriyan   gre: fix netns vs...
1658
  	unregister_pernet_device(&ipgre_net_ops);
84e54fe0a   William Tu   gre: introduce na...
1659
  	unregister_pernet_device(&erspan_net_ops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1660
1661
1662
1663
1664
  }
  
  module_init(ipgre_init);
  module_exit(ipgre_fini);
  MODULE_LICENSE("GPL");
4d74f8ba1   Patrick McHardy   gre: minor cleanu...
1665
1666
  MODULE_ALIAS_RTNL_LINK("gre");
  MODULE_ALIAS_RTNL_LINK("gretap");
84e54fe0a   William Tu   gre: introduce na...
1667
  MODULE_ALIAS_RTNL_LINK("erspan");
8909c9ad8   Vasiliy Kulikov   net: don't allow ...
1668
  MODULE_ALIAS_NETDEV("gre0");
c54419321   Pravin B Shelar   GRE: Refactor GRE...
1669
  MODULE_ALIAS_NETDEV("gretap0");
84e54fe0a   William Tu   gre: introduce na...
1670
  MODULE_ALIAS_NETDEV("erspan0");