xref: /linux/net/ipv4/ip_gre.c (revision 20704bd1633dd5afb29a321d3a615c9c8e9c9d05)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  *	Linux NET3:	GRE over IP protocol decoder.
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  *	Authors: Alexey Kuznetsov (kuznet@ms2.inr.ac.ru)
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  *	This program is free software; you can redistribute it and/or
71da177e4SLinus Torvalds  *	modify it under the terms of the GNU General Public License
81da177e4SLinus Torvalds  *	as published by the Free Software Foundation; either version
91da177e4SLinus Torvalds  *	2 of the License, or (at your option) any later version.
101da177e4SLinus Torvalds  *
111da177e4SLinus Torvalds  */
121da177e4SLinus Torvalds 
13afd46503SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
14afd46503SJoe Perches 
154fc268d2SRandy Dunlap #include <linux/capability.h>
161da177e4SLinus Torvalds #include <linux/module.h>
171da177e4SLinus Torvalds #include <linux/types.h>
181da177e4SLinus Torvalds #include <linux/kernel.h>
195a0e3ad6STejun Heo #include <linux/slab.h>
207c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
211da177e4SLinus Torvalds #include <linux/skbuff.h>
221da177e4SLinus Torvalds #include <linux/netdevice.h>
231da177e4SLinus Torvalds #include <linux/in.h>
241da177e4SLinus Torvalds #include <linux/tcp.h>
251da177e4SLinus Torvalds #include <linux/udp.h>
261da177e4SLinus Torvalds #include <linux/if_arp.h>
272e15ea39SPravin B Shelar #include <linux/if_vlan.h>
281da177e4SLinus Torvalds #include <linux/init.h>
291da177e4SLinus Torvalds #include <linux/in6.h>
301da177e4SLinus Torvalds #include <linux/inetdevice.h>
311da177e4SLinus Torvalds #include <linux/igmp.h>
321da177e4SLinus Torvalds #include <linux/netfilter_ipv4.h>
33e1a80002SHerbert Xu #include <linux/etherdevice.h>
3446f25dffSKris Katterjohn #include <linux/if_ether.h>
351da177e4SLinus Torvalds 
361da177e4SLinus Torvalds #include <net/sock.h>
371da177e4SLinus Torvalds #include <net/ip.h>
381da177e4SLinus Torvalds #include <net/icmp.h>
391da177e4SLinus Torvalds #include <net/protocol.h>
40c5441932SPravin B Shelar #include <net/ip_tunnels.h>
411da177e4SLinus Torvalds #include <net/arp.h>
421da177e4SLinus Torvalds #include <net/checksum.h>
431da177e4SLinus Torvalds #include <net/dsfield.h>
441da177e4SLinus Torvalds #include <net/inet_ecn.h>
451da177e4SLinus Torvalds #include <net/xfrm.h>
4659a4c759SPavel Emelyanov #include <net/net_namespace.h>
4759a4c759SPavel Emelyanov #include <net/netns/generic.h>
48c19e654dSHerbert Xu #include <net/rtnetlink.h>
4900959adeSDmitry Kozlov #include <net/gre.h>
502e15ea39SPravin B Shelar #include <net/dst_metadata.h>
5184e54fe0SWilliam Tu #include <net/erspan.h>
521da177e4SLinus Torvalds 
531da177e4SLinus Torvalds /*
541da177e4SLinus Torvalds    Problems & solutions
551da177e4SLinus Torvalds    --------------------
561da177e4SLinus Torvalds 
571da177e4SLinus Torvalds    1. The most important issue is detecting local dead loops.
581da177e4SLinus Torvalds    They would cause complete host lockup in transmit, which
591da177e4SLinus Torvalds    would be "resolved" by stack overflow or, if queueing is enabled,
601da177e4SLinus Torvalds    with infinite looping in net_bh.
611da177e4SLinus Torvalds 
621da177e4SLinus Torvalds    We cannot track such dead loops during route installation,
631da177e4SLinus Torvalds    it is infeasible task. The most general solutions would be
641da177e4SLinus Torvalds    to keep skb->encapsulation counter (sort of local ttl),
656d0722a2SEric Dumazet    and silently drop packet when it expires. It is a good
66bff52857Sstephen hemminger    solution, but it supposes maintaining new variable in ALL
671da177e4SLinus Torvalds    skb, even if no tunneling is used.
681da177e4SLinus Torvalds 
696d0722a2SEric Dumazet    Current solution: xmit_recursion breaks dead loops. This is a percpu
706d0722a2SEric Dumazet    counter, since when we enter the first ndo_xmit(), cpu migration is
716d0722a2SEric Dumazet    forbidden. We force an exit if this counter reaches RECURSION_LIMIT
721da177e4SLinus Torvalds 
731da177e4SLinus Torvalds    2. Networking dead loops would not kill routers, but would really
741da177e4SLinus Torvalds    kill network. IP hop limit plays role of "t->recursion" in this case,
751da177e4SLinus Torvalds    if we copy it from packet being encapsulated to upper header.
761da177e4SLinus Torvalds    It is very good solution, but it introduces two problems:
771da177e4SLinus Torvalds 
781da177e4SLinus Torvalds    - Routing protocols, using packets with ttl=1 (OSPF, RIP2),
791da177e4SLinus Torvalds      do not work over tunnels.
801da177e4SLinus Torvalds    - traceroute does not work. I planned to relay ICMP from tunnel,
811da177e4SLinus Torvalds      so that this problem would be solved and traceroute output
821da177e4SLinus Torvalds      would even more informative. This idea appeared to be wrong:
831da177e4SLinus Torvalds      only Linux complies to rfc1812 now (yes, guys, Linux is the only
841da177e4SLinus Torvalds      true router now :-)), all routers (at least, in neighbourhood of mine)
851da177e4SLinus Torvalds      return only 8 bytes of payload. It is the end.
861da177e4SLinus Torvalds 
871da177e4SLinus Torvalds    Hence, if we want that OSPF worked or traceroute said something reasonable,
881da177e4SLinus Torvalds    we should search for another solution.
891da177e4SLinus Torvalds 
901da177e4SLinus Torvalds    One of them is to parse packet trying to detect inner encapsulation
911da177e4SLinus Torvalds    made by our node. It is difficult or even impossible, especially,
92bff52857Sstephen hemminger    taking into account fragmentation. TO be short, ttl is not solution at all.
931da177e4SLinus Torvalds 
941da177e4SLinus Torvalds    Current solution: The solution was UNEXPECTEDLY SIMPLE.
951da177e4SLinus Torvalds    We force DF flag on tunnels with preconfigured hop limit,
961da177e4SLinus Torvalds    that is ALL. :-) Well, it does not remove the problem completely,
971da177e4SLinus Torvalds    but exponential growth of network traffic is changed to linear
981da177e4SLinus Torvalds    (branches, that exceed pmtu are pruned) and tunnel mtu
99bff52857Sstephen hemminger    rapidly degrades to value <68, where looping stops.
1001da177e4SLinus Torvalds    Yes, it is not good if there exists a router in the loop,
1011da177e4SLinus Torvalds    which does not force DF, even when encapsulating packets have DF set.
1021da177e4SLinus Torvalds    But it is not our problem! Nobody could accuse us, we made
1031da177e4SLinus Torvalds    all that we could make. Even if it is your gated who injected
1041da177e4SLinus Torvalds    fatal route to network, even if it were you who configured
1051da177e4SLinus Torvalds    fatal static route: you are innocent. :-)
1061da177e4SLinus Torvalds 
1071da177e4SLinus Torvalds    Alexey Kuznetsov.
1081da177e4SLinus Torvalds  */
1091da177e4SLinus Torvalds 
110eccc1bb8Sstephen hemminger static bool log_ecn_error = true;
111eccc1bb8Sstephen hemminger module_param(log_ecn_error, bool, 0644);
112eccc1bb8Sstephen hemminger MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN");
113eccc1bb8Sstephen hemminger 
114c19e654dSHerbert Xu static struct rtnl_link_ops ipgre_link_ops __read_mostly;
1151da177e4SLinus Torvalds static int ipgre_tunnel_init(struct net_device *dev);
1161a66a836SWilliam Tu static void erspan_build_header(struct sk_buff *skb,
117c69de58bSWilliam Tu 				u32 id, u32 index,
118a3222dc9SWilliam Tu 				bool truncate, bool is_ipv4);
119eb8ce741SPavel Emelyanov 
120c7d03a00SAlexey Dobriyan static unsigned int ipgre_net_id __read_mostly;
121c7d03a00SAlexey Dobriyan static unsigned int gre_tap_net_id __read_mostly;
12284e54fe0SWilliam Tu static unsigned int erspan_net_id __read_mostly;
123eb8ce741SPavel Emelyanov 
12432bbd879SStefano Brivio static int ipgre_err(struct sk_buff *skb, u32 info,
125bda7bb46SPravin B Shelar 		     const struct tnl_ptk_info *tpi)
1261da177e4SLinus Torvalds {
1271da177e4SLinus Torvalds 
128071f92d0SRami Rosen 	/* All the routers (except for Linux) return only
1291da177e4SLinus Torvalds 	   8 bytes of packet payload. It means, that precise relaying of
1301da177e4SLinus Torvalds 	   ICMP in the real Internet is absolutely infeasible.
1311da177e4SLinus Torvalds 
1321da177e4SLinus Torvalds 	   Moreover, Cisco "wise men" put GRE key to the third word
133c5441932SPravin B Shelar 	   in GRE header. It makes impossible maintaining even soft
134c5441932SPravin B Shelar 	   state for keyed GRE tunnels with enabled checksum. Tell
135c5441932SPravin B Shelar 	   them "thank you".
1361da177e4SLinus Torvalds 
1371da177e4SLinus Torvalds 	   Well, I wonder, rfc1812 was written by Cisco employee,
138bff52857Sstephen hemminger 	   what the hell these idiots break standards established
139bff52857Sstephen hemminger 	   by themselves???
1401da177e4SLinus Torvalds 	   */
141c5441932SPravin B Shelar 	struct net *net = dev_net(skb->dev);
142c5441932SPravin B Shelar 	struct ip_tunnel_net *itn;
14396f5a846SEric Dumazet 	const struct iphdr *iph;
14488c7664fSArnaldo Carvalho de Melo 	const int type = icmp_hdr(skb)->type;
14588c7664fSArnaldo Carvalho de Melo 	const int code = icmp_hdr(skb)->code;
14620e1954fSEric Dumazet 	unsigned int data_len = 0;
1471da177e4SLinus Torvalds 	struct ip_tunnel *t;
148d2083287Sstephen hemminger 
149bda7bb46SPravin B Shelar 	if (tpi->proto == htons(ETH_P_TEB))
150c5441932SPravin B Shelar 		itn = net_generic(net, gre_tap_net_id);
15151dc63e3SHaishuang Yan 	else if (tpi->proto == htons(ETH_P_ERSPAN) ||
15251dc63e3SHaishuang Yan 		 tpi->proto == htons(ETH_P_ERSPAN2))
15351dc63e3SHaishuang Yan 		itn = net_generic(net, erspan_net_id);
154c5441932SPravin B Shelar 	else
155c5441932SPravin B Shelar 		itn = net_generic(net, ipgre_net_id);
156c5441932SPravin B Shelar 
157c0c0c50fSDuan Jiong 	iph = (const struct iphdr *)(icmp_hdr(skb) + 1);
158bda7bb46SPravin B Shelar 	t = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags,
159bda7bb46SPravin B Shelar 			     iph->daddr, iph->saddr, tpi->key);
160d2083287Sstephen hemminger 
16151456b29SIan Morris 	if (!t)
16232bbd879SStefano Brivio 		return -ENOENT;
16332bbd879SStefano Brivio 
16432bbd879SStefano Brivio 	switch (type) {
16532bbd879SStefano Brivio 	default:
16632bbd879SStefano Brivio 	case ICMP_PARAMETERPROB:
16732bbd879SStefano Brivio 		return 0;
16832bbd879SStefano Brivio 
16932bbd879SStefano Brivio 	case ICMP_DEST_UNREACH:
17032bbd879SStefano Brivio 		switch (code) {
17132bbd879SStefano Brivio 		case ICMP_SR_FAILED:
17232bbd879SStefano Brivio 		case ICMP_PORT_UNREACH:
17332bbd879SStefano Brivio 			/* Impossible event. */
17432bbd879SStefano Brivio 			return 0;
17532bbd879SStefano Brivio 		default:
17632bbd879SStefano Brivio 			/* All others are translated to HOST_UNREACH.
17732bbd879SStefano Brivio 			   rfc2003 contains "deep thoughts" about NET_UNREACH,
17832bbd879SStefano Brivio 			   I believe they are just ether pollution. --ANK
17932bbd879SStefano Brivio 			 */
18032bbd879SStefano Brivio 			break;
18132bbd879SStefano Brivio 		}
18232bbd879SStefano Brivio 		break;
18332bbd879SStefano Brivio 
18432bbd879SStefano Brivio 	case ICMP_TIME_EXCEEDED:
18532bbd879SStefano Brivio 		if (code != ICMP_EXC_TTL)
18632bbd879SStefano Brivio 			return 0;
18732bbd879SStefano Brivio 		data_len = icmp_hdr(skb)->un.reserved[1] * 4; /* RFC 4884 4.1 */
18832bbd879SStefano Brivio 		break;
18932bbd879SStefano Brivio 
19032bbd879SStefano Brivio 	case ICMP_REDIRECT:
19132bbd879SStefano Brivio 		break;
19232bbd879SStefano Brivio 	}
19336393395SDavid S. Miller 
1949b8c6d7bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6)
1959b8c6d7bSEric Dumazet        if (tpi->proto == htons(ETH_P_IPV6) &&
19620e1954fSEric Dumazet            !ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4 + tpi->hdr_len,
19720e1954fSEric Dumazet 				       type, data_len))
19832bbd879SStefano Brivio                return 0;
1999b8c6d7bSEric Dumazet #endif
2009b8c6d7bSEric Dumazet 
20136393395SDavid S. Miller 	if (t->parms.iph.daddr == 0 ||
202f97c1e0cSJoe Perches 	    ipv4_is_multicast(t->parms.iph.daddr))
20332bbd879SStefano Brivio 		return 0;
2041da177e4SLinus Torvalds 
2051da177e4SLinus Torvalds 	if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
20632bbd879SStefano Brivio 		return 0;
2071da177e4SLinus Torvalds 
208da6185d8SWei Yongjun 	if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO))
2091da177e4SLinus Torvalds 		t->err_count++;
2101da177e4SLinus Torvalds 	else
2111da177e4SLinus Torvalds 		t->err_count = 1;
2121da177e4SLinus Torvalds 	t->err_time = jiffies;
21332bbd879SStefano Brivio 
21432bbd879SStefano Brivio 	return 0;
2159f57c67cSPravin B Shelar }
2169f57c67cSPravin B Shelar 
2179f57c67cSPravin B Shelar static void gre_err(struct sk_buff *skb, u32 info)
2189f57c67cSPravin B Shelar {
2199f57c67cSPravin B Shelar 	/* All the routers (except for Linux) return only
2209f57c67cSPravin B Shelar 	 * 8 bytes of packet payload. It means, that precise relaying of
2219f57c67cSPravin B Shelar 	 * ICMP in the real Internet is absolutely infeasible.
2229f57c67cSPravin B Shelar 	 *
2239f57c67cSPravin B Shelar 	 * Moreover, Cisco "wise men" put GRE key to the third word
2249f57c67cSPravin B Shelar 	 * in GRE header. It makes impossible maintaining even soft
2259f57c67cSPravin B Shelar 	 * state for keyed
2269f57c67cSPravin B Shelar 	 * GRE tunnels with enabled checksum. Tell them "thank you".
2279f57c67cSPravin B Shelar 	 *
2289f57c67cSPravin B Shelar 	 * Well, I wonder, rfc1812 was written by Cisco employee,
2299f57c67cSPravin B Shelar 	 * what the hell these idiots break standards established
2309f57c67cSPravin B Shelar 	 * by themselves???
2319f57c67cSPravin B Shelar 	 */
2329f57c67cSPravin B Shelar 
233e582615aSEric Dumazet 	const struct iphdr *iph = (struct iphdr *)skb->data;
2349f57c67cSPravin B Shelar 	const int type = icmp_hdr(skb)->type;
2359f57c67cSPravin B Shelar 	const int code = icmp_hdr(skb)->code;
2369f57c67cSPravin B Shelar 	struct tnl_ptk_info tpi;
2379f57c67cSPravin B Shelar 
238b0350d51SHaishuang Yan 	if (gre_parse_header(skb, &tpi, NULL, htons(ETH_P_IP),
239b0350d51SHaishuang Yan 			     iph->ihl * 4) < 0)
2409f57c67cSPravin B Shelar 		return;
2419f57c67cSPravin B Shelar 
2429f57c67cSPravin B Shelar 	if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
2439f57c67cSPravin B Shelar 		ipv4_update_pmtu(skb, dev_net(skb->dev), info,
244d888f396SMaciej Żenczykowski 				 skb->dev->ifindex, IPPROTO_GRE);
2459f57c67cSPravin B Shelar 		return;
2469f57c67cSPravin B Shelar 	}
2479f57c67cSPravin B Shelar 	if (type == ICMP_REDIRECT) {
2481042caa7SMaciej Żenczykowski 		ipv4_redirect(skb, dev_net(skb->dev), skb->dev->ifindex,
2491042caa7SMaciej Żenczykowski 			      IPPROTO_GRE);
2509f57c67cSPravin B Shelar 		return;
2519f57c67cSPravin B Shelar 	}
2529f57c67cSPravin B Shelar 
2539f57c67cSPravin B Shelar 	ipgre_err(skb, info, &tpi);
2541da177e4SLinus Torvalds }
2551da177e4SLinus Torvalds 
25684e54fe0SWilliam Tu static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
25784e54fe0SWilliam Tu 		      int gre_hdr_len)
25884e54fe0SWilliam Tu {
25984e54fe0SWilliam Tu 	struct net *net = dev_net(skb->dev);
26084e54fe0SWilliam Tu 	struct metadata_dst *tun_dst = NULL;
2611d7e2ed2SWilliam Tu 	struct erspan_base_hdr *ershdr;
2621d7e2ed2SWilliam Tu 	struct erspan_metadata *pkt_md;
26384e54fe0SWilliam Tu 	struct ip_tunnel_net *itn;
26484e54fe0SWilliam Tu 	struct ip_tunnel *tunnel;
26584e54fe0SWilliam Tu 	const struct iphdr *iph;
2663df19283SWilliam Tu 	struct erspan_md2 *md2;
2671d7e2ed2SWilliam Tu 	int ver;
26884e54fe0SWilliam Tu 	int len;
26984e54fe0SWilliam Tu 
27084e54fe0SWilliam Tu 	itn = net_generic(net, erspan_net_id);
27184e54fe0SWilliam Tu 	len = gre_hdr_len + sizeof(*ershdr);
27284e54fe0SWilliam Tu 
2731d7e2ed2SWilliam Tu 	/* Check based hdr len */
27484e54fe0SWilliam Tu 	if (unlikely(!pskb_may_pull(skb, len)))
275c05fad57SHaishuang Yan 		return PACKET_REJECT;
27684e54fe0SWilliam Tu 
27784e54fe0SWilliam Tu 	iph = ip_hdr(skb);
2781d7e2ed2SWilliam Tu 	ershdr = (struct erspan_base_hdr *)(skb->data + gre_hdr_len);
279c69de58bSWilliam Tu 	ver = ershdr->ver;
28084e54fe0SWilliam Tu 
28184e54fe0SWilliam Tu 	/* The original GRE header does not have key field,
28284e54fe0SWilliam Tu 	 * Use ERSPAN 10-bit session ID as key.
28384e54fe0SWilliam Tu 	 */
284c69de58bSWilliam Tu 	tpi->key = cpu_to_be32(get_session_id(ershdr));
28584e54fe0SWilliam Tu 	tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex,
28684e54fe0SWilliam Tu 				  tpi->flags | TUNNEL_KEY,
28784e54fe0SWilliam Tu 				  iph->saddr, iph->daddr, tpi->key);
28884e54fe0SWilliam Tu 
28984e54fe0SWilliam Tu 	if (tunnel) {
2901d7e2ed2SWilliam Tu 		len = gre_hdr_len + erspan_hdr_len(ver);
2911d7e2ed2SWilliam Tu 		if (unlikely(!pskb_may_pull(skb, len)))
292ae3e1337SWilliam Tu 			return PACKET_REJECT;
2931d7e2ed2SWilliam Tu 
294d91e8db5SWilliam Tu 		ershdr = (struct erspan_base_hdr *)(skb->data + gre_hdr_len);
295d91e8db5SWilliam Tu 		pkt_md = (struct erspan_metadata *)(ershdr + 1);
296d91e8db5SWilliam Tu 
29784e54fe0SWilliam Tu 		if (__iptunnel_pull_header(skb,
2981d7e2ed2SWilliam Tu 					   len,
29984e54fe0SWilliam Tu 					   htons(ETH_P_TEB),
30084e54fe0SWilliam Tu 					   false, false) < 0)
30184e54fe0SWilliam Tu 			goto drop;
30284e54fe0SWilliam Tu 
3031a66a836SWilliam Tu 		if (tunnel->collect_md) {
3041a66a836SWilliam Tu 			struct ip_tunnel_info *info;
3051a66a836SWilliam Tu 			struct erspan_metadata *md;
3061a66a836SWilliam Tu 			__be64 tun_id;
3071a66a836SWilliam Tu 			__be16 flags;
3081a66a836SWilliam Tu 
3091a66a836SWilliam Tu 			tpi->flags |= TUNNEL_KEY;
3101a66a836SWilliam Tu 			flags = tpi->flags;
3111a66a836SWilliam Tu 			tun_id = key32_to_tunnel_id(tpi->key);
3121a66a836SWilliam Tu 
3131a66a836SWilliam Tu 			tun_dst = ip_tun_rx_dst(skb, flags,
3141a66a836SWilliam Tu 						tun_id, sizeof(*md));
3151a66a836SWilliam Tu 			if (!tun_dst)
3161a66a836SWilliam Tu 				return PACKET_REJECT;
3171a66a836SWilliam Tu 
3181a66a836SWilliam Tu 			md = ip_tunnel_info_opts(&tun_dst->u.tun_info);
319f551c91dSWilliam Tu 			md->version = ver;
3203df19283SWilliam Tu 			md2 = &md->u.md2;
3213df19283SWilliam Tu 			memcpy(md2, pkt_md, ver == 1 ? ERSPAN_V1_MDSIZE :
3223df19283SWilliam Tu 						       ERSPAN_V2_MDSIZE);
323f551c91dSWilliam Tu 
3241a66a836SWilliam Tu 			info = &tun_dst->u.tun_info;
3251a66a836SWilliam Tu 			info->key.tun_flags |= TUNNEL_ERSPAN_OPT;
3261a66a836SWilliam Tu 			info->options_len = sizeof(*md);
3271a66a836SWilliam Tu 		}
3281a66a836SWilliam Tu 
32984e54fe0SWilliam Tu 		skb_reset_mac_header(skb);
33084e54fe0SWilliam Tu 		ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error);
33184e54fe0SWilliam Tu 		return PACKET_RCVD;
33284e54fe0SWilliam Tu 	}
3335a64506bSHaishuang Yan 	return PACKET_REJECT;
3345a64506bSHaishuang Yan 
33584e54fe0SWilliam Tu drop:
33684e54fe0SWilliam Tu 	kfree_skb(skb);
33784e54fe0SWilliam Tu 	return PACKET_RCVD;
33884e54fe0SWilliam Tu }
33984e54fe0SWilliam Tu 
340125372faSJiri Benc static int __ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
341125372faSJiri Benc 		       struct ip_tunnel_net *itn, int hdr_len, bool raw_proto)
3421da177e4SLinus Torvalds {
3432e15ea39SPravin B Shelar 	struct metadata_dst *tun_dst = NULL;
344b71d1d42SEric Dumazet 	const struct iphdr *iph;
3451da177e4SLinus Torvalds 	struct ip_tunnel *tunnel;
3461da177e4SLinus Torvalds 
347eddc9ec5SArnaldo Carvalho de Melo 	iph = ip_hdr(skb);
348bda7bb46SPravin B Shelar 	tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags,
349bda7bb46SPravin B Shelar 				  iph->saddr, iph->daddr, tpi->key);
3501da177e4SLinus Torvalds 
351d2083287Sstephen hemminger 	if (tunnel) {
352125372faSJiri Benc 		if (__iptunnel_pull_header(skb, hdr_len, tpi->proto,
353125372faSJiri Benc 					   raw_proto, false) < 0)
354244a797bSJiri Benc 			goto drop;
355244a797bSJiri Benc 
356e271c7b4SJiri Benc 		if (tunnel->dev->type != ARPHRD_NONE)
3570e3da5bbSTimo Teräs 			skb_pop_mac_header(skb);
358e271c7b4SJiri Benc 		else
359e271c7b4SJiri Benc 			skb_reset_mac_header(skb);
3602e15ea39SPravin B Shelar 		if (tunnel->collect_md) {
361c29a70d2SPravin B Shelar 			__be16 flags;
362c29a70d2SPravin B Shelar 			__be64 tun_id;
3632e15ea39SPravin B Shelar 
364c29a70d2SPravin B Shelar 			flags = tpi->flags & (TUNNEL_CSUM | TUNNEL_KEY);
365d817f432SAmir Vadai 			tun_id = key32_to_tunnel_id(tpi->key);
366c29a70d2SPravin B Shelar 			tun_dst = ip_tun_rx_dst(skb, flags, tun_id, 0);
3672e15ea39SPravin B Shelar 			if (!tun_dst)
3682e15ea39SPravin B Shelar 				return PACKET_REJECT;
3692e15ea39SPravin B Shelar 		}
3702e15ea39SPravin B Shelar 
3712e15ea39SPravin B Shelar 		ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error);
372bda7bb46SPravin B Shelar 		return PACKET_RCVD;
3731da177e4SLinus Torvalds 	}
374125372faSJiri Benc 	return PACKET_NEXT;
375244a797bSJiri Benc 
376244a797bSJiri Benc drop:
377244a797bSJiri Benc 	kfree_skb(skb);
378244a797bSJiri Benc 	return PACKET_RCVD;
3791da177e4SLinus Torvalds }
3801da177e4SLinus Torvalds 
381125372faSJiri Benc static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
382125372faSJiri Benc 		     int hdr_len)
383125372faSJiri Benc {
384125372faSJiri Benc 	struct net *net = dev_net(skb->dev);
385125372faSJiri Benc 	struct ip_tunnel_net *itn;
386125372faSJiri Benc 	int res;
387125372faSJiri Benc 
388125372faSJiri Benc 	if (tpi->proto == htons(ETH_P_TEB))
389125372faSJiri Benc 		itn = net_generic(net, gre_tap_net_id);
390125372faSJiri Benc 	else
391125372faSJiri Benc 		itn = net_generic(net, ipgre_net_id);
392125372faSJiri Benc 
393125372faSJiri Benc 	res = __ipgre_rcv(skb, tpi, itn, hdr_len, false);
394125372faSJiri Benc 	if (res == PACKET_NEXT && tpi->proto == htons(ETH_P_TEB)) {
395125372faSJiri Benc 		/* ipgre tunnels in collect metadata mode should receive
396125372faSJiri Benc 		 * also ETH_P_TEB traffic.
397125372faSJiri Benc 		 */
398125372faSJiri Benc 		itn = net_generic(net, ipgre_net_id);
399125372faSJiri Benc 		res = __ipgre_rcv(skb, tpi, itn, hdr_len, true);
400125372faSJiri Benc 	}
401125372faSJiri Benc 	return res;
402125372faSJiri Benc }
403125372faSJiri Benc 
4049f57c67cSPravin B Shelar static int gre_rcv(struct sk_buff *skb)
4059f57c67cSPravin B Shelar {
4069f57c67cSPravin B Shelar 	struct tnl_ptk_info tpi;
4079f57c67cSPravin B Shelar 	bool csum_err = false;
40895f5c64cSTom Herbert 	int hdr_len;
4099f57c67cSPravin B Shelar 
4109f57c67cSPravin B Shelar #ifdef CONFIG_NET_IPGRE_BROADCAST
4119f57c67cSPravin B Shelar 	if (ipv4_is_multicast(ip_hdr(skb)->daddr)) {
4129f57c67cSPravin B Shelar 		/* Looped back packet, drop it! */
4139f57c67cSPravin B Shelar 		if (rt_is_output_route(skb_rtable(skb)))
4149f57c67cSPravin B Shelar 			goto drop;
4159f57c67cSPravin B Shelar 	}
4169f57c67cSPravin B Shelar #endif
4179f57c67cSPravin B Shelar 
418e582615aSEric Dumazet 	hdr_len = gre_parse_header(skb, &tpi, &csum_err, htons(ETH_P_IP), 0);
419f132ae7cSJiri Benc 	if (hdr_len < 0)
42095f5c64cSTom Herbert 		goto drop;
42195f5c64cSTom Herbert 
422f551c91dSWilliam Tu 	if (unlikely(tpi.proto == htons(ETH_P_ERSPAN) ||
423f551c91dSWilliam Tu 		     tpi.proto == htons(ETH_P_ERSPAN2))) {
42484e54fe0SWilliam Tu 		if (erspan_rcv(skb, &tpi, hdr_len) == PACKET_RCVD)
42584e54fe0SWilliam Tu 			return 0;
426dd8d5b8cSHaishuang Yan 		goto out;
42784e54fe0SWilliam Tu 	}
42884e54fe0SWilliam Tu 
429244a797bSJiri Benc 	if (ipgre_rcv(skb, &tpi, hdr_len) == PACKET_RCVD)
4309f57c67cSPravin B Shelar 		return 0;
4319f57c67cSPravin B Shelar 
432dd8d5b8cSHaishuang Yan out:
4339f57c67cSPravin B Shelar 	icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
4349f57c67cSPravin B Shelar drop:
4359f57c67cSPravin B Shelar 	kfree_skb(skb);
4369f57c67cSPravin B Shelar 	return 0;
4379f57c67cSPravin B Shelar }
4389f57c67cSPravin B Shelar 
439c5441932SPravin B Shelar static void __gre_xmit(struct sk_buff *skb, struct net_device *dev,
440c5441932SPravin B Shelar 		       const struct iphdr *tnl_params,
441c5441932SPravin B Shelar 		       __be16 proto)
442c5441932SPravin B Shelar {
443c5441932SPravin B Shelar 	struct ip_tunnel *tunnel = netdev_priv(dev);
444c5441932SPravin B Shelar 
445c5441932SPravin B Shelar 	if (tunnel->parms.o_flags & TUNNEL_SEQ)
446c5441932SPravin B Shelar 		tunnel->o_seqno++;
447cef401deSEric Dumazet 
448c5441932SPravin B Shelar 	/* Push GRE header. */
449182a352dSTom Herbert 	gre_build_header(skb, tunnel->tun_hlen,
450182a352dSTom Herbert 			 tunnel->parms.o_flags, proto, tunnel->parms.o_key,
451182a352dSTom Herbert 			 htonl(tunnel->o_seqno));
4521da177e4SLinus Torvalds 
453bf3d6a8fSNicolas Dichtel 	ip_tunnel_xmit(skb, dev, tnl_params, tnl_params->protocol);
4541da177e4SLinus Torvalds }
4551da177e4SLinus Torvalds 
456aed069dfSAlexander Duyck static int gre_handle_offloads(struct sk_buff *skb, bool csum)
457b2acd1dcSPravin B Shelar {
4586fa79666SEdward Cree 	return iptunnel_handle_offloads(skb, csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE);
459b2acd1dcSPravin B Shelar }
460b2acd1dcSPravin B Shelar 
461fc4099f1SPravin B Shelar static struct rtable *gre_get_rt(struct sk_buff *skb,
462fc4099f1SPravin B Shelar 				 struct net_device *dev,
463fc4099f1SPravin B Shelar 				 struct flowi4 *fl,
464fc4099f1SPravin B Shelar 				 const struct ip_tunnel_key *key)
465fc4099f1SPravin B Shelar {
466fc4099f1SPravin B Shelar 	struct net *net = dev_net(dev);
467fc4099f1SPravin B Shelar 
468fc4099f1SPravin B Shelar 	memset(fl, 0, sizeof(*fl));
469fc4099f1SPravin B Shelar 	fl->daddr = key->u.ipv4.dst;
470fc4099f1SPravin B Shelar 	fl->saddr = key->u.ipv4.src;
471fc4099f1SPravin B Shelar 	fl->flowi4_tos = RT_TOS(key->tos);
472fc4099f1SPravin B Shelar 	fl->flowi4_mark = skb->mark;
473fc4099f1SPravin B Shelar 	fl->flowi4_proto = IPPROTO_GRE;
474fc4099f1SPravin B Shelar 
475fc4099f1SPravin B Shelar 	return ip_route_output_key(net, fl);
476fc4099f1SPravin B Shelar }
477fc4099f1SPravin B Shelar 
478862a03c3SWilliam Tu static struct rtable *prepare_fb_xmit(struct sk_buff *skb,
479862a03c3SWilliam Tu 				      struct net_device *dev,
480862a03c3SWilliam Tu 				      struct flowi4 *fl,
481862a03c3SWilliam Tu 				      int tunnel_hlen)
4822e15ea39SPravin B Shelar {
4832e15ea39SPravin B Shelar 	struct ip_tunnel_info *tun_info;
4842e15ea39SPravin B Shelar 	const struct ip_tunnel_key *key;
485db3c6139SDaniel Borkmann 	struct rtable *rt = NULL;
4862e15ea39SPravin B Shelar 	int min_headroom;
487db3c6139SDaniel Borkmann 	bool use_cache;
4882e15ea39SPravin B Shelar 	int err;
4892e15ea39SPravin B Shelar 
49061adedf3SJiri Benc 	tun_info = skb_tunnel_info(skb);
4912e15ea39SPravin B Shelar 	key = &tun_info->key;
492db3c6139SDaniel Borkmann 	use_cache = ip_tunnel_dst_cache_usable(skb, tun_info);
493862a03c3SWilliam Tu 
494db3c6139SDaniel Borkmann 	if (use_cache)
495862a03c3SWilliam Tu 		rt = dst_cache_get_ip4(&tun_info->dst_cache, &fl->saddr);
4963c1cb4d2SPaolo Abeni 	if (!rt) {
497862a03c3SWilliam Tu 		rt = gre_get_rt(skb, dev, fl, key);
4982e15ea39SPravin B Shelar 		if (IS_ERR(rt))
4992e15ea39SPravin B Shelar 			goto err_free_skb;
500db3c6139SDaniel Borkmann 		if (use_cache)
5013c1cb4d2SPaolo Abeni 			dst_cache_set_ip4(&tun_info->dst_cache, &rt->dst,
502862a03c3SWilliam Tu 					  fl->saddr);
5033c1cb4d2SPaolo Abeni 	}
5042e15ea39SPravin B Shelar 
5052e15ea39SPravin B Shelar 	min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len
5062e15ea39SPravin B Shelar 			+ tunnel_hlen + sizeof(struct iphdr);
5072e15ea39SPravin B Shelar 	if (skb_headroom(skb) < min_headroom || skb_header_cloned(skb)) {
5082e15ea39SPravin B Shelar 		int head_delta = SKB_DATA_ALIGN(min_headroom -
5092e15ea39SPravin B Shelar 						skb_headroom(skb) +
5102e15ea39SPravin B Shelar 						16);
5112e15ea39SPravin B Shelar 		err = pskb_expand_head(skb, max_t(int, head_delta, 0),
5122e15ea39SPravin B Shelar 				       0, GFP_ATOMIC);
5132e15ea39SPravin B Shelar 		if (unlikely(err))
5142e15ea39SPravin B Shelar 			goto err_free_rt;
5152e15ea39SPravin B Shelar 	}
516862a03c3SWilliam Tu 	return rt;
517862a03c3SWilliam Tu 
518862a03c3SWilliam Tu err_free_rt:
519862a03c3SWilliam Tu 	ip_rt_put(rt);
520862a03c3SWilliam Tu err_free_skb:
521862a03c3SWilliam Tu 	kfree_skb(skb);
522862a03c3SWilliam Tu 	dev->stats.tx_dropped++;
523862a03c3SWilliam Tu 	return NULL;
524862a03c3SWilliam Tu }
525862a03c3SWilliam Tu 
526862a03c3SWilliam Tu static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev,
527862a03c3SWilliam Tu 			__be16 proto)
528862a03c3SWilliam Tu {
52977a5196aSWilliam Tu 	struct ip_tunnel *tunnel = netdev_priv(dev);
530862a03c3SWilliam Tu 	struct ip_tunnel_info *tun_info;
531862a03c3SWilliam Tu 	const struct ip_tunnel_key *key;
532862a03c3SWilliam Tu 	struct rtable *rt = NULL;
533862a03c3SWilliam Tu 	struct flowi4 fl;
534862a03c3SWilliam Tu 	int tunnel_hlen;
535862a03c3SWilliam Tu 	__be16 df, flags;
536862a03c3SWilliam Tu 
537862a03c3SWilliam Tu 	tun_info = skb_tunnel_info(skb);
538862a03c3SWilliam Tu 	if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) ||
539862a03c3SWilliam Tu 		     ip_tunnel_info_af(tun_info) != AF_INET))
540862a03c3SWilliam Tu 		goto err_free_skb;
541862a03c3SWilliam Tu 
542862a03c3SWilliam Tu 	key = &tun_info->key;
543862a03c3SWilliam Tu 	tunnel_hlen = gre_calc_hlen(key->tun_flags);
544862a03c3SWilliam Tu 
545862a03c3SWilliam Tu 	rt = prepare_fb_xmit(skb, dev, &fl, tunnel_hlen);
546862a03c3SWilliam Tu 	if (!rt)
547862a03c3SWilliam Tu 		return;
5482e15ea39SPravin B Shelar 
5492e15ea39SPravin B Shelar 	/* Push Tunnel header. */
550aed069dfSAlexander Duyck 	if (gre_handle_offloads(skb, !!(tun_info->key.tun_flags & TUNNEL_CSUM)))
5512e15ea39SPravin B Shelar 		goto err_free_rt;
5522e15ea39SPravin B Shelar 
55377a5196aSWilliam Tu 	flags = tun_info->key.tun_flags &
55477a5196aSWilliam Tu 		(TUNNEL_CSUM | TUNNEL_KEY | TUNNEL_SEQ);
555cba65321SDavid S. Miller 	gre_build_header(skb, tunnel_hlen, flags, proto,
55677a5196aSWilliam Tu 			 tunnel_id_to_key32(tun_info->key.tun_id),
55715746394SColin Ian King 			 (flags & TUNNEL_SEQ) ? htonl(tunnel->o_seqno++) : 0);
5582e15ea39SPravin B Shelar 
5592e15ea39SPravin B Shelar 	df = key->tun_flags & TUNNEL_DONT_FRAGMENT ?  htons(IP_DF) : 0;
560039f5062SPravin B Shelar 
561039f5062SPravin B Shelar 	iptunnel_xmit(skb->sk, rt, skb, fl.saddr, key->u.ipv4.dst, IPPROTO_GRE,
5627c383fb2SJiri Benc 		      key->tos, key->ttl, df, false);
5632e15ea39SPravin B Shelar 	return;
5642e15ea39SPravin B Shelar 
5652e15ea39SPravin B Shelar err_free_rt:
5662e15ea39SPravin B Shelar 	ip_rt_put(rt);
5672e15ea39SPravin B Shelar err_free_skb:
5682e15ea39SPravin B Shelar 	kfree_skb(skb);
5692e15ea39SPravin B Shelar 	dev->stats.tx_dropped++;
5702e15ea39SPravin B Shelar }
5712e15ea39SPravin B Shelar 
572*20704bd1SXin Long static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev)
5731a66a836SWilliam Tu {
5741a66a836SWilliam Tu 	struct ip_tunnel *tunnel = netdev_priv(dev);
5751a66a836SWilliam Tu 	struct ip_tunnel_info *tun_info;
5761a66a836SWilliam Tu 	const struct ip_tunnel_key *key;
5771a66a836SWilliam Tu 	struct erspan_metadata *md;
5781a66a836SWilliam Tu 	struct rtable *rt = NULL;
5791a66a836SWilliam Tu 	bool truncate = false;
580*20704bd1SXin Long 	__be16 df, proto;
5811a66a836SWilliam Tu 	struct flowi4 fl;
5821a66a836SWilliam Tu 	int tunnel_hlen;
583f551c91dSWilliam Tu 	int version;
5841baf5ebfSWilliam Tu 	int nhoff;
585d5db21a3SWilliam Tu 	int thoff;
5861a66a836SWilliam Tu 
5871a66a836SWilliam Tu 	tun_info = skb_tunnel_info(skb);
5881a66a836SWilliam Tu 	if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) ||
5891a66a836SWilliam Tu 		     ip_tunnel_info_af(tun_info) != AF_INET))
5901a66a836SWilliam Tu 		goto err_free_skb;
5911a66a836SWilliam Tu 
5921a66a836SWilliam Tu 	key = &tun_info->key;
593256c87c1SPieter Jansen van Vuuren 	if (!(tun_info->key.tun_flags & TUNNEL_ERSPAN_OPT))
594256c87c1SPieter Jansen van Vuuren 		goto err_free_rt;
595f551c91dSWilliam Tu 	md = ip_tunnel_info_opts(tun_info);
596f551c91dSWilliam Tu 	if (!md)
597f551c91dSWilliam Tu 		goto err_free_rt;
5981a66a836SWilliam Tu 
5991a66a836SWilliam Tu 	/* ERSPAN has fixed 8 byte GRE header */
600f551c91dSWilliam Tu 	version = md->version;
601f551c91dSWilliam Tu 	tunnel_hlen = 8 + erspan_hdr_len(version);
6021a66a836SWilliam Tu 
6031a66a836SWilliam Tu 	rt = prepare_fb_xmit(skb, dev, &fl, tunnel_hlen);
6041a66a836SWilliam Tu 	if (!rt)
6051a66a836SWilliam Tu 		return;
6061a66a836SWilliam Tu 
6071a66a836SWilliam Tu 	if (gre_handle_offloads(skb, false))
6081a66a836SWilliam Tu 		goto err_free_rt;
6091a66a836SWilliam Tu 
610f192970dSWilliam Tu 	if (skb->len > dev->mtu + dev->hard_header_len) {
611f192970dSWilliam Tu 		pskb_trim(skb, dev->mtu + dev->hard_header_len);
6121a66a836SWilliam Tu 		truncate = true;
6131a66a836SWilliam Tu 	}
6141a66a836SWilliam Tu 
6151baf5ebfSWilliam Tu 	nhoff = skb_network_header(skb) - skb_mac_header(skb);
6161baf5ebfSWilliam Tu 	if (skb->protocol == htons(ETH_P_IP) &&
6171baf5ebfSWilliam Tu 	    (ntohs(ip_hdr(skb)->tot_len) > skb->len - nhoff))
6181baf5ebfSWilliam Tu 		truncate = true;
6191baf5ebfSWilliam Tu 
620d5db21a3SWilliam Tu 	thoff = skb_transport_header(skb) - skb_mac_header(skb);
621d5db21a3SWilliam Tu 	if (skb->protocol == htons(ETH_P_IPV6) &&
622d5db21a3SWilliam Tu 	    (ntohs(ipv6_hdr(skb)->payload_len) > skb->len - thoff))
623d5db21a3SWilliam Tu 		truncate = true;
624d5db21a3SWilliam Tu 
625f551c91dSWilliam Tu 	if (version == 1) {
626c69de58bSWilliam Tu 		erspan_build_header(skb, ntohl(tunnel_id_to_key32(key->tun_id)),
6271d7e2ed2SWilliam Tu 				    ntohl(md->u.index), truncate, true);
628*20704bd1SXin Long 		proto = htons(ETH_P_ERSPAN);
629f551c91dSWilliam Tu 	} else if (version == 2) {
630c69de58bSWilliam Tu 		erspan_build_header_v2(skb,
631c69de58bSWilliam Tu 				       ntohl(tunnel_id_to_key32(key->tun_id)),
632c69de58bSWilliam Tu 				       md->u.md2.dir,
633c69de58bSWilliam Tu 				       get_hwid(&md->u.md2),
634c69de58bSWilliam Tu 				       truncate, true);
635*20704bd1SXin Long 		proto = htons(ETH_P_ERSPAN2);
636f551c91dSWilliam Tu 	} else {
637f551c91dSWilliam Tu 		goto err_free_rt;
638f551c91dSWilliam Tu 	}
6391a66a836SWilliam Tu 
6401a66a836SWilliam Tu 	gre_build_header(skb, 8, TUNNEL_SEQ,
641*20704bd1SXin Long 			 proto, 0, htonl(tunnel->o_seqno++));
6421a66a836SWilliam Tu 
6431a66a836SWilliam Tu 	df = key->tun_flags & TUNNEL_DONT_FRAGMENT ?  htons(IP_DF) : 0;
6441a66a836SWilliam Tu 
6451a66a836SWilliam Tu 	iptunnel_xmit(skb->sk, rt, skb, fl.saddr, key->u.ipv4.dst, IPPROTO_GRE,
6461a66a836SWilliam Tu 		      key->tos, key->ttl, df, false);
6471a66a836SWilliam Tu 	return;
6481a66a836SWilliam Tu 
6491a66a836SWilliam Tu err_free_rt:
6501a66a836SWilliam Tu 	ip_rt_put(rt);
6511a66a836SWilliam Tu err_free_skb:
6521a66a836SWilliam Tu 	kfree_skb(skb);
6531a66a836SWilliam Tu 	dev->stats.tx_dropped++;
6541a66a836SWilliam Tu }
6551a66a836SWilliam Tu 
656fc4099f1SPravin B Shelar static int gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
657fc4099f1SPravin B Shelar {
658fc4099f1SPravin B Shelar 	struct ip_tunnel_info *info = skb_tunnel_info(skb);
659fc4099f1SPravin B Shelar 	struct rtable *rt;
660fc4099f1SPravin B Shelar 	struct flowi4 fl4;
661fc4099f1SPravin B Shelar 
662fc4099f1SPravin B Shelar 	if (ip_tunnel_info_af(info) != AF_INET)
663fc4099f1SPravin B Shelar 		return -EINVAL;
664fc4099f1SPravin B Shelar 
665fc4099f1SPravin B Shelar 	rt = gre_get_rt(skb, dev, &fl4, &info->key);
666fc4099f1SPravin B Shelar 	if (IS_ERR(rt))
667fc4099f1SPravin B Shelar 		return PTR_ERR(rt);
668fc4099f1SPravin B Shelar 
669fc4099f1SPravin B Shelar 	ip_rt_put(rt);
670fc4099f1SPravin B Shelar 	info->key.u.ipv4.src = fl4.saddr;
671fc4099f1SPravin B Shelar 	return 0;
672fc4099f1SPravin B Shelar }
673fc4099f1SPravin B Shelar 
674c5441932SPravin B Shelar static netdev_tx_t ipgre_xmit(struct sk_buff *skb,
675c5441932SPravin B Shelar 			      struct net_device *dev)
676ee34c1ebSMichal Schmidt {
677c5441932SPravin B Shelar 	struct ip_tunnel *tunnel = netdev_priv(dev);
678c5441932SPravin B Shelar 	const struct iphdr *tnl_params;
679ee34c1ebSMichal Schmidt 
680cb9f1b78SWillem de Bruijn 	if (!pskb_inet_may_pull(skb))
681cb9f1b78SWillem de Bruijn 		goto free_skb;
682cb9f1b78SWillem de Bruijn 
6832e15ea39SPravin B Shelar 	if (tunnel->collect_md) {
6842090714eSJiri Benc 		gre_fb_xmit(skb, dev, skb->protocol);
6852e15ea39SPravin B Shelar 		return NETDEV_TX_OK;
6862e15ea39SPravin B Shelar 	}
6872e15ea39SPravin B Shelar 
688c5441932SPravin B Shelar 	if (dev->header_ops) {
689c5441932SPravin B Shelar 		/* Need space for new headers */
690c5441932SPravin B Shelar 		if (skb_cow_head(skb, dev->needed_headroom -
6912bac7cb3SChen Gang 				      (tunnel->hlen + sizeof(struct iphdr))))
692c5441932SPravin B Shelar 			goto free_skb;
693ee34c1ebSMichal Schmidt 
694c5441932SPravin B Shelar 		tnl_params = (const struct iphdr *)skb->data;
695cbb1e85fSDavid S. Miller 
696c5441932SPravin B Shelar 		/* Pull skb since ip_tunnel_xmit() needs skb->data pointing
697c5441932SPravin B Shelar 		 * to gre header.
698c5441932SPravin B Shelar 		 */
699c5441932SPravin B Shelar 		skb_pull(skb, tunnel->hlen + sizeof(struct iphdr));
7008a0033a9STimo Teräs 		skb_reset_mac_header(skb);
701c5441932SPravin B Shelar 	} else {
702c5441932SPravin B Shelar 		if (skb_cow_head(skb, dev->needed_headroom))
703c5441932SPravin B Shelar 			goto free_skb;
704c5441932SPravin B Shelar 
705c5441932SPravin B Shelar 		tnl_params = &tunnel->parms.iph;
706ee34c1ebSMichal Schmidt 	}
707e1a80002SHerbert Xu 
708aed069dfSAlexander Duyck 	if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM)))
709aed069dfSAlexander Duyck 		goto free_skb;
7108a0033a9STimo Teräs 
711c5441932SPravin B Shelar 	__gre_xmit(skb, dev, tnl_params, skb->protocol);
712c5441932SPravin B Shelar 	return NETDEV_TX_OK;
713c5441932SPravin B Shelar 
714c5441932SPravin B Shelar free_skb:
7153acfa1e7SEric Dumazet 	kfree_skb(skb);
716c5441932SPravin B Shelar 	dev->stats.tx_dropped++;
717c5441932SPravin B Shelar 	return NETDEV_TX_OK;
718ee34c1ebSMichal Schmidt }
719ee34c1ebSMichal Schmidt 
72084e54fe0SWilliam Tu static netdev_tx_t erspan_xmit(struct sk_buff *skb,
72184e54fe0SWilliam Tu 			       struct net_device *dev)
72284e54fe0SWilliam Tu {
72384e54fe0SWilliam Tu 	struct ip_tunnel *tunnel = netdev_priv(dev);
72484e54fe0SWilliam Tu 	bool truncate = false;
725*20704bd1SXin Long 	__be16 proto;
72684e54fe0SWilliam Tu 
727cb9f1b78SWillem de Bruijn 	if (!pskb_inet_may_pull(skb))
728cb9f1b78SWillem de Bruijn 		goto free_skb;
729cb9f1b78SWillem de Bruijn 
7301a66a836SWilliam Tu 	if (tunnel->collect_md) {
731*20704bd1SXin Long 		erspan_fb_xmit(skb, dev);
7321a66a836SWilliam Tu 		return NETDEV_TX_OK;
7331a66a836SWilliam Tu 	}
7341a66a836SWilliam Tu 
73584e54fe0SWilliam Tu 	if (gre_handle_offloads(skb, false))
73684e54fe0SWilliam Tu 		goto free_skb;
73784e54fe0SWilliam Tu 
73884e54fe0SWilliam Tu 	if (skb_cow_head(skb, dev->needed_headroom))
73984e54fe0SWilliam Tu 		goto free_skb;
74084e54fe0SWilliam Tu 
741f192970dSWilliam Tu 	if (skb->len > dev->mtu + dev->hard_header_len) {
742f192970dSWilliam Tu 		pskb_trim(skb, dev->mtu + dev->hard_header_len);
74384e54fe0SWilliam Tu 		truncate = true;
74484e54fe0SWilliam Tu 	}
74584e54fe0SWilliam Tu 
74684e54fe0SWilliam Tu 	/* Push ERSPAN header */
747*20704bd1SXin Long 	if (tunnel->erspan_ver == 1) {
748c69de58bSWilliam Tu 		erspan_build_header(skb, ntohl(tunnel->parms.o_key),
749c69de58bSWilliam Tu 				    tunnel->index,
750a3222dc9SWilliam Tu 				    truncate, true);
751*20704bd1SXin Long 		proto = htons(ETH_P_ERSPAN);
752*20704bd1SXin Long 	} else if (tunnel->erspan_ver == 2) {
753c69de58bSWilliam Tu 		erspan_build_header_v2(skb, ntohl(tunnel->parms.o_key),
754f551c91dSWilliam Tu 				       tunnel->dir, tunnel->hwid,
755f551c91dSWilliam Tu 				       truncate, true);
756*20704bd1SXin Long 		proto = htons(ETH_P_ERSPAN2);
757*20704bd1SXin Long 	} else {
75802f99df1SWilliam Tu 		goto free_skb;
759*20704bd1SXin Long 	}
760f551c91dSWilliam Tu 
76184e54fe0SWilliam Tu 	tunnel->parms.o_flags &= ~TUNNEL_KEY;
762*20704bd1SXin Long 	__gre_xmit(skb, dev, &tunnel->parms.iph, proto);
76384e54fe0SWilliam Tu 	return NETDEV_TX_OK;
76484e54fe0SWilliam Tu 
76584e54fe0SWilliam Tu free_skb:
76684e54fe0SWilliam Tu 	kfree_skb(skb);
76784e54fe0SWilliam Tu 	dev->stats.tx_dropped++;
76884e54fe0SWilliam Tu 	return NETDEV_TX_OK;
76984e54fe0SWilliam Tu }
77084e54fe0SWilliam Tu 
771c5441932SPravin B Shelar static netdev_tx_t gre_tap_xmit(struct sk_buff *skb,
772c5441932SPravin B Shelar 				struct net_device *dev)
773c5441932SPravin B Shelar {
774c5441932SPravin B Shelar 	struct ip_tunnel *tunnel = netdev_priv(dev);
775ee34c1ebSMichal Schmidt 
776cb9f1b78SWillem de Bruijn 	if (!pskb_inet_may_pull(skb))
777cb9f1b78SWillem de Bruijn 		goto free_skb;
778cb9f1b78SWillem de Bruijn 
7792e15ea39SPravin B Shelar 	if (tunnel->collect_md) {
7802090714eSJiri Benc 		gre_fb_xmit(skb, dev, htons(ETH_P_TEB));
7812e15ea39SPravin B Shelar 		return NETDEV_TX_OK;
7822e15ea39SPravin B Shelar 	}
7832e15ea39SPravin B Shelar 
784aed069dfSAlexander Duyck 	if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM)))
785aed069dfSAlexander Duyck 		goto free_skb;
786ee34c1ebSMichal Schmidt 
787c5441932SPravin B Shelar 	if (skb_cow_head(skb, dev->needed_headroom))
788c5441932SPravin B Shelar 		goto free_skb;
78942aa9162SHerbert Xu 
790c5441932SPravin B Shelar 	__gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_TEB));
791c5441932SPravin B Shelar 	return NETDEV_TX_OK;
792c5441932SPravin B Shelar 
793c5441932SPravin B Shelar free_skb:
7943acfa1e7SEric Dumazet 	kfree_skb(skb);
795c5441932SPravin B Shelar 	dev->stats.tx_dropped++;
796c5441932SPravin B Shelar 	return NETDEV_TX_OK;
79768c33163SPravin B Shelar }
798ee34c1ebSMichal Schmidt 
799dd9d598cSXin Long static void ipgre_link_update(struct net_device *dev, bool set_mtu)
800dd9d598cSXin Long {
801dd9d598cSXin Long 	struct ip_tunnel *tunnel = netdev_priv(dev);
802dd9d598cSXin Long 	int len;
803dd9d598cSXin Long 
804dd9d598cSXin Long 	len = tunnel->tun_hlen;
805dd9d598cSXin Long 	tunnel->tun_hlen = gre_calc_hlen(tunnel->parms.o_flags);
806dd9d598cSXin Long 	len = tunnel->tun_hlen - len;
807dd9d598cSXin Long 	tunnel->hlen = tunnel->hlen + len;
808dd9d598cSXin Long 
809dd9d598cSXin Long 	dev->needed_headroom = dev->needed_headroom + len;
810dd9d598cSXin Long 	if (set_mtu)
811dd9d598cSXin Long 		dev->mtu = max_t(int, dev->mtu - len, 68);
812dd9d598cSXin Long 
813dd9d598cSXin Long 	if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) {
814dd9d598cSXin Long 		if (!(tunnel->parms.o_flags & TUNNEL_CSUM) ||
815dd9d598cSXin Long 		    tunnel->encap.type == TUNNEL_ENCAP_NONE) {
816dd9d598cSXin Long 			dev->features |= NETIF_F_GSO_SOFTWARE;
817dd9d598cSXin Long 			dev->hw_features |= NETIF_F_GSO_SOFTWARE;
8181cc5954fSSabrina Dubroca 		} else {
8191cc5954fSSabrina Dubroca 			dev->features &= ~NETIF_F_GSO_SOFTWARE;
8201cc5954fSSabrina Dubroca 			dev->hw_features &= ~NETIF_F_GSO_SOFTWARE;
821dd9d598cSXin Long 		}
822dd9d598cSXin Long 		dev->features |= NETIF_F_LLTX;
8231cc5954fSSabrina Dubroca 	} else {
8241cc5954fSSabrina Dubroca 		dev->hw_features &= ~NETIF_F_GSO_SOFTWARE;
8251cc5954fSSabrina Dubroca 		dev->features &= ~(NETIF_F_LLTX | NETIF_F_GSO_SOFTWARE);
826dd9d598cSXin Long 	}
827dd9d598cSXin Long }
828dd9d598cSXin Long 
829c5441932SPravin B Shelar static int ipgre_tunnel_ioctl(struct net_device *dev,
830c5441932SPravin B Shelar 			      struct ifreq *ifr, int cmd)
8311da177e4SLinus Torvalds {
8321da177e4SLinus Torvalds 	struct ip_tunnel_parm p;
833a0efab67SXin Long 	int err;
8341da177e4SLinus Torvalds 
8351da177e4SLinus Torvalds 	if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
836c5441932SPravin B Shelar 		return -EFAULT;
837a0efab67SXin Long 
8386c734fb8SCong Wang 	if (cmd == SIOCADDTUNNEL || cmd == SIOCCHGTUNNEL) {
8391da177e4SLinus Torvalds 		if (p.iph.version != 4 || p.iph.protocol != IPPROTO_GRE ||
8401da177e4SLinus Torvalds 		    p.iph.ihl != 5 || (p.iph.frag_off & htons(~IP_DF)) ||
8416c734fb8SCong Wang 		    ((p.i_flags | p.o_flags) & (GRE_VERSION | GRE_ROUTING)))
8421da177e4SLinus Torvalds 			return -EINVAL;
843c5441932SPravin B Shelar 	}
844a0efab67SXin Long 
845c5441932SPravin B Shelar 	p.i_flags = gre_flags_to_tnl_flags(p.i_flags);
846c5441932SPravin B Shelar 	p.o_flags = gre_flags_to_tnl_flags(p.o_flags);
847c5441932SPravin B Shelar 
848c5441932SPravin B Shelar 	err = ip_tunnel_ioctl(dev, &p, cmd);
849c5441932SPravin B Shelar 	if (err)
850c5441932SPravin B Shelar 		return err;
851c5441932SPravin B Shelar 
852a0efab67SXin Long 	if (cmd == SIOCCHGTUNNEL) {
853a0efab67SXin Long 		struct ip_tunnel *t = netdev_priv(dev);
854a0efab67SXin Long 
855a0efab67SXin Long 		t->parms.i_flags = p.i_flags;
856a0efab67SXin Long 		t->parms.o_flags = p.o_flags;
857a0efab67SXin Long 
858a0efab67SXin Long 		if (strcmp(dev->rtnl_link_ops->kind, "erspan"))
859a0efab67SXin Long 			ipgre_link_update(dev, true);
860a0efab67SXin Long 	}
861a0efab67SXin Long 
86295f5c64cSTom Herbert 	p.i_flags = gre_tnl_flags_to_gre_flags(p.i_flags);
86395f5c64cSTom Herbert 	p.o_flags = gre_tnl_flags_to_gre_flags(p.o_flags);
864c5441932SPravin B Shelar 
865c5441932SPravin B Shelar 	if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p)))
866c5441932SPravin B Shelar 		return -EFAULT;
867a0efab67SXin Long 
8681da177e4SLinus Torvalds 	return 0;
8691da177e4SLinus Torvalds }
8701da177e4SLinus Torvalds 
8711da177e4SLinus Torvalds /* Nice toy. Unfortunately, useless in real life :-)
8721da177e4SLinus Torvalds    It allows to construct virtual multiprotocol broadcast "LAN"
8731da177e4SLinus Torvalds    over the Internet, provided multicast routing is tuned.
8741da177e4SLinus Torvalds 
8751da177e4SLinus Torvalds 
8761da177e4SLinus Torvalds    I have no idea was this bicycle invented before me,
8771da177e4SLinus Torvalds    so that I had to set ARPHRD_IPGRE to a random value.
8781da177e4SLinus Torvalds    I have an impression, that Cisco could make something similar,
8791da177e4SLinus Torvalds    but this feature is apparently missing in IOS<=11.2(8).
8801da177e4SLinus Torvalds 
8811da177e4SLinus Torvalds    I set up 10.66.66/24 and fec0:6666:6666::0/96 as virtual networks
8821da177e4SLinus Torvalds    with broadcast 224.66.66.66. If you have access to mbone, play with me :-)
8831da177e4SLinus Torvalds 
8841da177e4SLinus Torvalds    ping -t 255 224.66.66.66
8851da177e4SLinus Torvalds 
8861da177e4SLinus Torvalds    If nobody answers, mbone does not work.
8871da177e4SLinus Torvalds 
8881da177e4SLinus Torvalds    ip tunnel add Universe mode gre remote 224.66.66.66 local <Your_real_addr> ttl 255
8891da177e4SLinus Torvalds    ip addr add 10.66.66.<somewhat>/24 dev Universe
8901da177e4SLinus Torvalds    ifconfig Universe up
8911da177e4SLinus Torvalds    ifconfig Universe add fe80::<Your_real_addr>/10
8921da177e4SLinus Torvalds    ifconfig Universe add fec0:6666:6666::<Your_real_addr>/96
8931da177e4SLinus Torvalds    ftp 10.66.66.66
8941da177e4SLinus Torvalds    ...
8951da177e4SLinus Torvalds    ftp fec0:6666:6666::193.233.7.65
8961da177e4SLinus Torvalds    ...
8971da177e4SLinus Torvalds  */
8983b04dddeSStephen Hemminger static int ipgre_header(struct sk_buff *skb, struct net_device *dev,
8993b04dddeSStephen Hemminger 			unsigned short type,
9001507850bSEric Dumazet 			const void *daddr, const void *saddr, unsigned int len)
9011da177e4SLinus Torvalds {
9022941a486SPatrick McHardy 	struct ip_tunnel *t = netdev_priv(dev);
903c5441932SPravin B Shelar 	struct iphdr *iph;
904c5441932SPravin B Shelar 	struct gre_base_hdr *greh;
905c5441932SPravin B Shelar 
906d58ff351SJohannes Berg 	iph = skb_push(skb, t->hlen + sizeof(*iph));
907c5441932SPravin B Shelar 	greh = (struct gre_base_hdr *)(iph+1);
90895f5c64cSTom Herbert 	greh->flags = gre_tnl_flags_to_gre_flags(t->parms.o_flags);
909c5441932SPravin B Shelar 	greh->protocol = htons(type);
9101da177e4SLinus Torvalds 
9111da177e4SLinus Torvalds 	memcpy(iph, &t->parms.iph, sizeof(struct iphdr));
9121da177e4SLinus Torvalds 
913c5441932SPravin B Shelar 	/* Set the source hardware address. */
9141da177e4SLinus Torvalds 	if (saddr)
9151da177e4SLinus Torvalds 		memcpy(&iph->saddr, saddr, 4);
9166d55cb91STimo Teräs 	if (daddr)
9171da177e4SLinus Torvalds 		memcpy(&iph->daddr, daddr, 4);
9186d55cb91STimo Teräs 	if (iph->daddr)
91977a482bdSTimo Teräs 		return t->hlen + sizeof(*iph);
9201da177e4SLinus Torvalds 
921c5441932SPravin B Shelar 	return -(t->hlen + sizeof(*iph));
9221da177e4SLinus Torvalds }
9231da177e4SLinus Torvalds 
9246a5f44d7STimo Teras static int ipgre_header_parse(const struct sk_buff *skb, unsigned char *haddr)
9256a5f44d7STimo Teras {
926b71d1d42SEric Dumazet 	const struct iphdr *iph = (const struct iphdr *) skb_mac_header(skb);
9276a5f44d7STimo Teras 	memcpy(haddr, &iph->saddr, 4);
9286a5f44d7STimo Teras 	return 4;
9296a5f44d7STimo Teras }
9306a5f44d7STimo Teras 
9313b04dddeSStephen Hemminger static const struct header_ops ipgre_header_ops = {
9323b04dddeSStephen Hemminger 	.create	= ipgre_header,
9336a5f44d7STimo Teras 	.parse	= ipgre_header_parse,
9343b04dddeSStephen Hemminger };
9353b04dddeSStephen Hemminger 
9366a5f44d7STimo Teras #ifdef CONFIG_NET_IPGRE_BROADCAST
9371da177e4SLinus Torvalds static int ipgre_open(struct net_device *dev)
9381da177e4SLinus Torvalds {
9392941a486SPatrick McHardy 	struct ip_tunnel *t = netdev_priv(dev);
9401da177e4SLinus Torvalds 
941f97c1e0cSJoe Perches 	if (ipv4_is_multicast(t->parms.iph.daddr)) {
942cbb1e85fSDavid S. Miller 		struct flowi4 fl4;
943cbb1e85fSDavid S. Miller 		struct rtable *rt;
944cbb1e85fSDavid S. Miller 
945b57708adSNicolas Dichtel 		rt = ip_route_output_gre(t->net, &fl4,
94678fbfd8aSDavid S. Miller 					 t->parms.iph.daddr,
94778fbfd8aSDavid S. Miller 					 t->parms.iph.saddr,
94878fbfd8aSDavid S. Miller 					 t->parms.o_key,
94978fbfd8aSDavid S. Miller 					 RT_TOS(t->parms.iph.tos),
95078fbfd8aSDavid S. Miller 					 t->parms.link);
951b23dd4feSDavid S. Miller 		if (IS_ERR(rt))
9521da177e4SLinus Torvalds 			return -EADDRNOTAVAIL;
953d8d1f30bSChangli Gao 		dev = rt->dst.dev;
9541da177e4SLinus Torvalds 		ip_rt_put(rt);
95551456b29SIan Morris 		if (!__in_dev_get_rtnl(dev))
9561da177e4SLinus Torvalds 			return -EADDRNOTAVAIL;
9571da177e4SLinus Torvalds 		t->mlink = dev->ifindex;
958e5ed6399SHerbert Xu 		ip_mc_inc_group(__in_dev_get_rtnl(dev), t->parms.iph.daddr);
9591da177e4SLinus Torvalds 	}
9601da177e4SLinus Torvalds 	return 0;
9611da177e4SLinus Torvalds }
9621da177e4SLinus Torvalds 
9631da177e4SLinus Torvalds static int ipgre_close(struct net_device *dev)
9641da177e4SLinus Torvalds {
9652941a486SPatrick McHardy 	struct ip_tunnel *t = netdev_priv(dev);
966b8c26a33SStephen Hemminger 
967f97c1e0cSJoe Perches 	if (ipv4_is_multicast(t->parms.iph.daddr) && t->mlink) {
9687fee0ca2SDenis V. Lunev 		struct in_device *in_dev;
969b57708adSNicolas Dichtel 		in_dev = inetdev_by_index(t->net, t->mlink);
9708723e1b4SEric Dumazet 		if (in_dev)
9711da177e4SLinus Torvalds 			ip_mc_dec_group(in_dev, t->parms.iph.daddr);
9721da177e4SLinus Torvalds 	}
9731da177e4SLinus Torvalds 	return 0;
9741da177e4SLinus Torvalds }
9751da177e4SLinus Torvalds #endif
9761da177e4SLinus Torvalds 
977b8c26a33SStephen Hemminger static const struct net_device_ops ipgre_netdev_ops = {
978b8c26a33SStephen Hemminger 	.ndo_init		= ipgre_tunnel_init,
979c5441932SPravin B Shelar 	.ndo_uninit		= ip_tunnel_uninit,
980b8c26a33SStephen Hemminger #ifdef CONFIG_NET_IPGRE_BROADCAST
981b8c26a33SStephen Hemminger 	.ndo_open		= ipgre_open,
982b8c26a33SStephen Hemminger 	.ndo_stop		= ipgre_close,
983b8c26a33SStephen Hemminger #endif
984c5441932SPravin B Shelar 	.ndo_start_xmit		= ipgre_xmit,
985b8c26a33SStephen Hemminger 	.ndo_do_ioctl		= ipgre_tunnel_ioctl,
986c5441932SPravin B Shelar 	.ndo_change_mtu		= ip_tunnel_change_mtu,
987c5441932SPravin B Shelar 	.ndo_get_stats64	= ip_tunnel_get_stats64,
9881e99584bSNicolas Dichtel 	.ndo_get_iflink		= ip_tunnel_get_iflink,
989b8c26a33SStephen Hemminger };
990b8c26a33SStephen Hemminger 
9916b78f16eSEric Dumazet #define GRE_FEATURES (NETIF_F_SG |		\
9926b78f16eSEric Dumazet 		      NETIF_F_FRAGLIST |	\
9936b78f16eSEric Dumazet 		      NETIF_F_HIGHDMA |		\
9946b78f16eSEric Dumazet 		      NETIF_F_HW_CSUM)
9956b78f16eSEric Dumazet 
9961da177e4SLinus Torvalds static void ipgre_tunnel_setup(struct net_device *dev)
9971da177e4SLinus Torvalds {
998b8c26a33SStephen Hemminger 	dev->netdev_ops		= &ipgre_netdev_ops;
9995a455275SNicolas Dichtel 	dev->type		= ARPHRD_IPGRE;
1000c5441932SPravin B Shelar 	ip_tunnel_setup(dev, ipgre_net_id);
1001c5441932SPravin B Shelar }
10021da177e4SLinus Torvalds 
1003c5441932SPravin B Shelar static void __gre_tunnel_init(struct net_device *dev)
1004c5441932SPravin B Shelar {
1005c5441932SPravin B Shelar 	struct ip_tunnel *tunnel;
1006c5441932SPravin B Shelar 
1007c5441932SPravin B Shelar 	tunnel = netdev_priv(dev);
100895f5c64cSTom Herbert 	tunnel->tun_hlen = gre_calc_hlen(tunnel->parms.o_flags);
1009c5441932SPravin B Shelar 	tunnel->parms.iph.protocol = IPPROTO_GRE;
1010c5441932SPravin B Shelar 
10114565e991STom Herbert 	tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen;
10124565e991STom Herbert 
1013b57708adSNicolas Dichtel 	dev->features		|= GRE_FEATURES;
10146b78f16eSEric Dumazet 	dev->hw_features	|= GRE_FEATURES;
1015c5441932SPravin B Shelar 
1016c5441932SPravin B Shelar 	if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) {
1017a0ca153fSAlexander Duyck 		/* TCP offload with GRE SEQ is not supported, nor
1018a0ca153fSAlexander Duyck 		 * can we support 2 levels of outer headers requiring
1019a0ca153fSAlexander Duyck 		 * an update.
1020a0ca153fSAlexander Duyck 		 */
1021a0ca153fSAlexander Duyck 		if (!(tunnel->parms.o_flags & TUNNEL_CSUM) ||
1022a0ca153fSAlexander Duyck 		    (tunnel->encap.type == TUNNEL_ENCAP_NONE)) {
1023c5441932SPravin B Shelar 			dev->features    |= NETIF_F_GSO_SOFTWARE;
1024c5441932SPravin B Shelar 			dev->hw_features |= NETIF_F_GSO_SOFTWARE;
1025a0ca153fSAlexander Duyck 		}
1026a0ca153fSAlexander Duyck 
1027c5441932SPravin B Shelar 		/* Can use a lockless transmit, unless we generate
1028c5441932SPravin B Shelar 		 * output sequences
1029c5441932SPravin B Shelar 		 */
1030c5441932SPravin B Shelar 		dev->features |= NETIF_F_LLTX;
1031c5441932SPravin B Shelar 	}
10321da177e4SLinus Torvalds }
10331da177e4SLinus Torvalds 
10341da177e4SLinus Torvalds static int ipgre_tunnel_init(struct net_device *dev)
10351da177e4SLinus Torvalds {
1036c5441932SPravin B Shelar 	struct ip_tunnel *tunnel = netdev_priv(dev);
1037c5441932SPravin B Shelar 	struct iphdr *iph = &tunnel->parms.iph;
10381da177e4SLinus Torvalds 
1039c5441932SPravin B Shelar 	__gre_tunnel_init(dev);
10401da177e4SLinus Torvalds 
1041c5441932SPravin B Shelar 	memcpy(dev->dev_addr, &iph->saddr, 4);
1042c5441932SPravin B Shelar 	memcpy(dev->broadcast, &iph->daddr, 4);
10431da177e4SLinus Torvalds 
1044c5441932SPravin B Shelar 	dev->flags		= IFF_NOARP;
104502875878SEric Dumazet 	netif_keep_dst(dev);
1046c5441932SPravin B Shelar 	dev->addr_len		= 4;
10471da177e4SLinus Torvalds 
1048a64b04d8SJiri Benc 	if (iph->daddr && !tunnel->collect_md) {
10491da177e4SLinus Torvalds #ifdef CONFIG_NET_IPGRE_BROADCAST
1050f97c1e0cSJoe Perches 		if (ipv4_is_multicast(iph->daddr)) {
10511da177e4SLinus Torvalds 			if (!iph->saddr)
10521da177e4SLinus Torvalds 				return -EINVAL;
10531da177e4SLinus Torvalds 			dev->flags = IFF_BROADCAST;
10543b04dddeSStephen Hemminger 			dev->header_ops = &ipgre_header_ops;
10551da177e4SLinus Torvalds 		}
10561da177e4SLinus Torvalds #endif
1057a64b04d8SJiri Benc 	} else if (!tunnel->collect_md) {
10586a5f44d7STimo Teras 		dev->header_ops = &ipgre_header_ops;
1059a64b04d8SJiri Benc 	}
10601da177e4SLinus Torvalds 
1061c5441932SPravin B Shelar 	return ip_tunnel_init(dev);
106260769a5dSEric Dumazet }
106360769a5dSEric Dumazet 
10649f57c67cSPravin B Shelar static const struct gre_protocol ipgre_protocol = {
10659f57c67cSPravin B Shelar 	.handler     = gre_rcv,
10669f57c67cSPravin B Shelar 	.err_handler = gre_err,
10671da177e4SLinus Torvalds };
10681da177e4SLinus Torvalds 
10692c8c1e72SAlexey Dobriyan static int __net_init ipgre_init_net(struct net *net)
107059a4c759SPavel Emelyanov {
1071c5441932SPravin B Shelar 	return ip_tunnel_init_net(net, ipgre_net_id, &ipgre_link_ops, NULL);
107259a4c759SPavel Emelyanov }
107359a4c759SPavel Emelyanov 
107464bc1781SEric Dumazet static void __net_exit ipgre_exit_batch_net(struct list_head *list_net)
107559a4c759SPavel Emelyanov {
107664bc1781SEric Dumazet 	ip_tunnel_delete_nets(list_net, ipgre_net_id, &ipgre_link_ops);
107759a4c759SPavel Emelyanov }
107859a4c759SPavel Emelyanov 
107959a4c759SPavel Emelyanov static struct pernet_operations ipgre_net_ops = {
108059a4c759SPavel Emelyanov 	.init = ipgre_init_net,
108164bc1781SEric Dumazet 	.exit_batch = ipgre_exit_batch_net,
1082cfb8fbf2SEric W. Biederman 	.id   = &ipgre_net_id,
1083c5441932SPravin B Shelar 	.size = sizeof(struct ip_tunnel_net),
108459a4c759SPavel Emelyanov };
10851da177e4SLinus Torvalds 
1086a8b8a889SMatthias Schiffer static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[],
1087a8b8a889SMatthias Schiffer 				 struct netlink_ext_ack *extack)
1088c19e654dSHerbert Xu {
1089c19e654dSHerbert Xu 	__be16 flags;
1090c19e654dSHerbert Xu 
1091c19e654dSHerbert Xu 	if (!data)
1092c19e654dSHerbert Xu 		return 0;
1093c19e654dSHerbert Xu 
1094c19e654dSHerbert Xu 	flags = 0;
1095c19e654dSHerbert Xu 	if (data[IFLA_GRE_IFLAGS])
1096c19e654dSHerbert Xu 		flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]);
1097c19e654dSHerbert Xu 	if (data[IFLA_GRE_OFLAGS])
1098c19e654dSHerbert Xu 		flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]);
1099c19e654dSHerbert Xu 	if (flags & (GRE_VERSION|GRE_ROUTING))
1100c19e654dSHerbert Xu 		return -EINVAL;
1101c19e654dSHerbert Xu 
1102946b636fSJiri Benc 	if (data[IFLA_GRE_COLLECT_METADATA] &&
1103946b636fSJiri Benc 	    data[IFLA_GRE_ENCAP_TYPE] &&
1104946b636fSJiri Benc 	    nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]) != TUNNEL_ENCAP_NONE)
1105946b636fSJiri Benc 		return -EINVAL;
1106946b636fSJiri Benc 
1107c19e654dSHerbert Xu 	return 0;
1108c19e654dSHerbert Xu }
1109c19e654dSHerbert Xu 
1110a8b8a889SMatthias Schiffer static int ipgre_tap_validate(struct nlattr *tb[], struct nlattr *data[],
1111a8b8a889SMatthias Schiffer 			      struct netlink_ext_ack *extack)
1112e1a80002SHerbert Xu {
1113e1a80002SHerbert Xu 	__be32 daddr;
1114e1a80002SHerbert Xu 
1115e1a80002SHerbert Xu 	if (tb[IFLA_ADDRESS]) {
1116e1a80002SHerbert Xu 		if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
1117e1a80002SHerbert Xu 			return -EINVAL;
1118e1a80002SHerbert Xu 		if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
1119e1a80002SHerbert Xu 			return -EADDRNOTAVAIL;
1120e1a80002SHerbert Xu 	}
1121e1a80002SHerbert Xu 
1122e1a80002SHerbert Xu 	if (!data)
1123e1a80002SHerbert Xu 		goto out;
1124e1a80002SHerbert Xu 
1125e1a80002SHerbert Xu 	if (data[IFLA_GRE_REMOTE]) {
1126e1a80002SHerbert Xu 		memcpy(&daddr, nla_data(data[IFLA_GRE_REMOTE]), 4);
1127e1a80002SHerbert Xu 		if (!daddr)
1128e1a80002SHerbert Xu 			return -EINVAL;
1129e1a80002SHerbert Xu 	}
1130e1a80002SHerbert Xu 
1131e1a80002SHerbert Xu out:
1132a8b8a889SMatthias Schiffer 	return ipgre_tunnel_validate(tb, data, extack);
1133e1a80002SHerbert Xu }
1134e1a80002SHerbert Xu 
113584e54fe0SWilliam Tu static int erspan_validate(struct nlattr *tb[], struct nlattr *data[],
113684e54fe0SWilliam Tu 			   struct netlink_ext_ack *extack)
113784e54fe0SWilliam Tu {
113884e54fe0SWilliam Tu 	__be16 flags = 0;
113984e54fe0SWilliam Tu 	int ret;
114084e54fe0SWilliam Tu 
114184e54fe0SWilliam Tu 	if (!data)
114284e54fe0SWilliam Tu 		return 0;
114384e54fe0SWilliam Tu 
114484e54fe0SWilliam Tu 	ret = ipgre_tap_validate(tb, data, extack);
114584e54fe0SWilliam Tu 	if (ret)
114684e54fe0SWilliam Tu 		return ret;
114784e54fe0SWilliam Tu 
114884e54fe0SWilliam Tu 	/* ERSPAN should only have GRE sequence and key flag */
11491a66a836SWilliam Tu 	if (data[IFLA_GRE_OFLAGS])
115084e54fe0SWilliam Tu 		flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]);
11511a66a836SWilliam Tu 	if (data[IFLA_GRE_IFLAGS])
115284e54fe0SWilliam Tu 		flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]);
11531a66a836SWilliam Tu 	if (!data[IFLA_GRE_COLLECT_METADATA] &&
11541a66a836SWilliam Tu 	    flags != (GRE_SEQ | GRE_KEY))
115584e54fe0SWilliam Tu 		return -EINVAL;
115684e54fe0SWilliam Tu 
115784e54fe0SWilliam Tu 	/* ERSPAN Session ID only has 10-bit. Since we reuse
115884e54fe0SWilliam Tu 	 * 32-bit key field as ID, check it's range.
115984e54fe0SWilliam Tu 	 */
116084e54fe0SWilliam Tu 	if (data[IFLA_GRE_IKEY] &&
116184e54fe0SWilliam Tu 	    (ntohl(nla_get_be32(data[IFLA_GRE_IKEY])) & ~ID_MASK))
116284e54fe0SWilliam Tu 		return -EINVAL;
116384e54fe0SWilliam Tu 
116484e54fe0SWilliam Tu 	if (data[IFLA_GRE_OKEY] &&
116584e54fe0SWilliam Tu 	    (ntohl(nla_get_be32(data[IFLA_GRE_OKEY])) & ~ID_MASK))
116684e54fe0SWilliam Tu 		return -EINVAL;
116784e54fe0SWilliam Tu 
116884e54fe0SWilliam Tu 	return 0;
116984e54fe0SWilliam Tu }
117084e54fe0SWilliam Tu 
117122a59be8SPhilip Prindeville static int ipgre_netlink_parms(struct net_device *dev,
11722e15ea39SPravin B Shelar 				struct nlattr *data[],
11732e15ea39SPravin B Shelar 				struct nlattr *tb[],
11749830ad4cSCraig Gallek 				struct ip_tunnel_parm *parms,
11759830ad4cSCraig Gallek 				__u32 *fwmark)
1176c19e654dSHerbert Xu {
117722a59be8SPhilip Prindeville 	struct ip_tunnel *t = netdev_priv(dev);
117822a59be8SPhilip Prindeville 
11797bb82d92SHerbert Xu 	memset(parms, 0, sizeof(*parms));
1180c19e654dSHerbert Xu 
1181c19e654dSHerbert Xu 	parms->iph.protocol = IPPROTO_GRE;
1182c19e654dSHerbert Xu 
1183c19e654dSHerbert Xu 	if (!data)
118422a59be8SPhilip Prindeville 		return 0;
1185c19e654dSHerbert Xu 
1186c19e654dSHerbert Xu 	if (data[IFLA_GRE_LINK])
1187c19e654dSHerbert Xu 		parms->link = nla_get_u32(data[IFLA_GRE_LINK]);
1188c19e654dSHerbert Xu 
1189c19e654dSHerbert Xu 	if (data[IFLA_GRE_IFLAGS])
1190c5441932SPravin B Shelar 		parms->i_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_IFLAGS]));
1191c19e654dSHerbert Xu 
1192c19e654dSHerbert Xu 	if (data[IFLA_GRE_OFLAGS])
1193c5441932SPravin B Shelar 		parms->o_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_OFLAGS]));
1194c19e654dSHerbert Xu 
1195c19e654dSHerbert Xu 	if (data[IFLA_GRE_IKEY])
1196c19e654dSHerbert Xu 		parms->i_key = nla_get_be32(data[IFLA_GRE_IKEY]);
1197c19e654dSHerbert Xu 
1198c19e654dSHerbert Xu 	if (data[IFLA_GRE_OKEY])
1199c19e654dSHerbert Xu 		parms->o_key = nla_get_be32(data[IFLA_GRE_OKEY]);
1200c19e654dSHerbert Xu 
1201c19e654dSHerbert Xu 	if (data[IFLA_GRE_LOCAL])
120267b61f6cSJiri Benc 		parms->iph.saddr = nla_get_in_addr(data[IFLA_GRE_LOCAL]);
1203c19e654dSHerbert Xu 
1204c19e654dSHerbert Xu 	if (data[IFLA_GRE_REMOTE])
120567b61f6cSJiri Benc 		parms->iph.daddr = nla_get_in_addr(data[IFLA_GRE_REMOTE]);
1206c19e654dSHerbert Xu 
1207c19e654dSHerbert Xu 	if (data[IFLA_GRE_TTL])
1208c19e654dSHerbert Xu 		parms->iph.ttl = nla_get_u8(data[IFLA_GRE_TTL]);
1209c19e654dSHerbert Xu 
1210c19e654dSHerbert Xu 	if (data[IFLA_GRE_TOS])
1211c19e654dSHerbert Xu 		parms->iph.tos = nla_get_u8(data[IFLA_GRE_TOS]);
1212c19e654dSHerbert Xu 
121322a59be8SPhilip Prindeville 	if (!data[IFLA_GRE_PMTUDISC] || nla_get_u8(data[IFLA_GRE_PMTUDISC])) {
121422a59be8SPhilip Prindeville 		if (t->ignore_df)
121522a59be8SPhilip Prindeville 			return -EINVAL;
1216c19e654dSHerbert Xu 		parms->iph.frag_off = htons(IP_DF);
121722a59be8SPhilip Prindeville 	}
12182e15ea39SPravin B Shelar 
12192e15ea39SPravin B Shelar 	if (data[IFLA_GRE_COLLECT_METADATA]) {
12202e15ea39SPravin B Shelar 		t->collect_md = true;
1221e271c7b4SJiri Benc 		if (dev->type == ARPHRD_IPGRE)
1222e271c7b4SJiri Benc 			dev->type = ARPHRD_NONE;
12232e15ea39SPravin B Shelar 	}
122422a59be8SPhilip Prindeville 
122522a59be8SPhilip Prindeville 	if (data[IFLA_GRE_IGNORE_DF]) {
122622a59be8SPhilip Prindeville 		if (nla_get_u8(data[IFLA_GRE_IGNORE_DF])
122722a59be8SPhilip Prindeville 		  && (parms->iph.frag_off & htons(IP_DF)))
122822a59be8SPhilip Prindeville 			return -EINVAL;
122922a59be8SPhilip Prindeville 		t->ignore_df = !!nla_get_u8(data[IFLA_GRE_IGNORE_DF]);
123022a59be8SPhilip Prindeville 	}
123122a59be8SPhilip Prindeville 
12329830ad4cSCraig Gallek 	if (data[IFLA_GRE_FWMARK])
12339830ad4cSCraig Gallek 		*fwmark = nla_get_u32(data[IFLA_GRE_FWMARK]);
12349830ad4cSCraig Gallek 
1235f551c91dSWilliam Tu 	if (data[IFLA_GRE_ERSPAN_VER]) {
1236f551c91dSWilliam Tu 		t->erspan_ver = nla_get_u8(data[IFLA_GRE_ERSPAN_VER]);
1237f551c91dSWilliam Tu 
1238f551c91dSWilliam Tu 		if (t->erspan_ver != 1 && t->erspan_ver != 2)
1239f551c91dSWilliam Tu 			return -EINVAL;
1240f551c91dSWilliam Tu 	}
1241f551c91dSWilliam Tu 
1242f551c91dSWilliam Tu 	if (t->erspan_ver == 1) {
124384e54fe0SWilliam Tu 		if (data[IFLA_GRE_ERSPAN_INDEX]) {
124484e54fe0SWilliam Tu 			t->index = nla_get_u32(data[IFLA_GRE_ERSPAN_INDEX]);
124584e54fe0SWilliam Tu 			if (t->index & ~INDEX_MASK)
124684e54fe0SWilliam Tu 				return -EINVAL;
124784e54fe0SWilliam Tu 		}
1248f551c91dSWilliam Tu 	} else if (t->erspan_ver == 2) {
1249f551c91dSWilliam Tu 		if (data[IFLA_GRE_ERSPAN_DIR]) {
1250f551c91dSWilliam Tu 			t->dir = nla_get_u8(data[IFLA_GRE_ERSPAN_DIR]);
1251f551c91dSWilliam Tu 			if (t->dir & ~(DIR_MASK >> DIR_OFFSET))
1252f551c91dSWilliam Tu 				return -EINVAL;
1253f551c91dSWilliam Tu 		}
1254f551c91dSWilliam Tu 		if (data[IFLA_GRE_ERSPAN_HWID]) {
1255f551c91dSWilliam Tu 			t->hwid = nla_get_u16(data[IFLA_GRE_ERSPAN_HWID]);
1256f551c91dSWilliam Tu 			if (t->hwid & ~(HWID_MASK >> HWID_OFFSET))
1257f551c91dSWilliam Tu 				return -EINVAL;
1258f551c91dSWilliam Tu 		}
1259f551c91dSWilliam Tu 	}
126084e54fe0SWilliam Tu 
126122a59be8SPhilip Prindeville 	return 0;
1262c19e654dSHerbert Xu }
1263c19e654dSHerbert Xu 
12644565e991STom Herbert /* This function returns true when ENCAP attributes are present in the nl msg */
12654565e991STom Herbert static bool ipgre_netlink_encap_parms(struct nlattr *data[],
12664565e991STom Herbert 				      struct ip_tunnel_encap *ipencap)
12674565e991STom Herbert {
12684565e991STom Herbert 	bool ret = false;
12694565e991STom Herbert 
12704565e991STom Herbert 	memset(ipencap, 0, sizeof(*ipencap));
12714565e991STom Herbert 
12724565e991STom Herbert 	if (!data)
12734565e991STom Herbert 		return ret;
12744565e991STom Herbert 
12754565e991STom Herbert 	if (data[IFLA_GRE_ENCAP_TYPE]) {
12764565e991STom Herbert 		ret = true;
12774565e991STom Herbert 		ipencap->type = nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]);
12784565e991STom Herbert 	}
12794565e991STom Herbert 
12804565e991STom Herbert 	if (data[IFLA_GRE_ENCAP_FLAGS]) {
12814565e991STom Herbert 		ret = true;
12824565e991STom Herbert 		ipencap->flags = nla_get_u16(data[IFLA_GRE_ENCAP_FLAGS]);
12834565e991STom Herbert 	}
12844565e991STom Herbert 
12854565e991STom Herbert 	if (data[IFLA_GRE_ENCAP_SPORT]) {
12864565e991STom Herbert 		ret = true;
12873e97fa70SSabrina Dubroca 		ipencap->sport = nla_get_be16(data[IFLA_GRE_ENCAP_SPORT]);
12884565e991STom Herbert 	}
12894565e991STom Herbert 
12904565e991STom Herbert 	if (data[IFLA_GRE_ENCAP_DPORT]) {
12914565e991STom Herbert 		ret = true;
12923e97fa70SSabrina Dubroca 		ipencap->dport = nla_get_be16(data[IFLA_GRE_ENCAP_DPORT]);
12934565e991STom Herbert 	}
12944565e991STom Herbert 
12954565e991STom Herbert 	return ret;
12964565e991STom Herbert }
12974565e991STom Herbert 
1298c5441932SPravin B Shelar static int gre_tap_init(struct net_device *dev)
1299e1a80002SHerbert Xu {
1300c5441932SPravin B Shelar 	__gre_tunnel_init(dev);
1301bec94d43Sstephen hemminger 	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
1302d51711c0SXin Long 	netif_keep_dst(dev);
1303e1a80002SHerbert Xu 
1304c5441932SPravin B Shelar 	return ip_tunnel_init(dev);
1305e1a80002SHerbert Xu }
1306e1a80002SHerbert Xu 
1307c5441932SPravin B Shelar static const struct net_device_ops gre_tap_netdev_ops = {
1308c5441932SPravin B Shelar 	.ndo_init		= gre_tap_init,
1309c5441932SPravin B Shelar 	.ndo_uninit		= ip_tunnel_uninit,
1310c5441932SPravin B Shelar 	.ndo_start_xmit		= gre_tap_xmit,
1311b8c26a33SStephen Hemminger 	.ndo_set_mac_address 	= eth_mac_addr,
1312b8c26a33SStephen Hemminger 	.ndo_validate_addr	= eth_validate_addr,
1313c5441932SPravin B Shelar 	.ndo_change_mtu		= ip_tunnel_change_mtu,
1314c5441932SPravin B Shelar 	.ndo_get_stats64	= ip_tunnel_get_stats64,
13151e99584bSNicolas Dichtel 	.ndo_get_iflink		= ip_tunnel_get_iflink,
1316fc4099f1SPravin B Shelar 	.ndo_fill_metadata_dst	= gre_fill_metadata_dst,
1317b8c26a33SStephen Hemminger };
1318b8c26a33SStephen Hemminger 
131984e54fe0SWilliam Tu static int erspan_tunnel_init(struct net_device *dev)
132084e54fe0SWilliam Tu {
132184e54fe0SWilliam Tu 	struct ip_tunnel *tunnel = netdev_priv(dev);
132284e54fe0SWilliam Tu 
132384e54fe0SWilliam Tu 	tunnel->tun_hlen = 8;
132484e54fe0SWilliam Tu 	tunnel->parms.iph.protocol = IPPROTO_GRE;
1325c122fda2SXin Long 	tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen +
1326f551c91dSWilliam Tu 		       erspan_hdr_len(tunnel->erspan_ver);
132784e54fe0SWilliam Tu 
132884e54fe0SWilliam Tu 	dev->features		|= GRE_FEATURES;
132984e54fe0SWilliam Tu 	dev->hw_features	|= GRE_FEATURES;
133084e54fe0SWilliam Tu 	dev->priv_flags		|= IFF_LIVE_ADDR_CHANGE;
1331c84bed44SXin Long 	netif_keep_dst(dev);
133284e54fe0SWilliam Tu 
133384e54fe0SWilliam Tu 	return ip_tunnel_init(dev);
133484e54fe0SWilliam Tu }
133584e54fe0SWilliam Tu 
133684e54fe0SWilliam Tu static const struct net_device_ops erspan_netdev_ops = {
133784e54fe0SWilliam Tu 	.ndo_init		= erspan_tunnel_init,
133884e54fe0SWilliam Tu 	.ndo_uninit		= ip_tunnel_uninit,
133984e54fe0SWilliam Tu 	.ndo_start_xmit		= erspan_xmit,
134084e54fe0SWilliam Tu 	.ndo_set_mac_address	= eth_mac_addr,
134184e54fe0SWilliam Tu 	.ndo_validate_addr	= eth_validate_addr,
134284e54fe0SWilliam Tu 	.ndo_change_mtu		= ip_tunnel_change_mtu,
134384e54fe0SWilliam Tu 	.ndo_get_stats64	= ip_tunnel_get_stats64,
134484e54fe0SWilliam Tu 	.ndo_get_iflink		= ip_tunnel_get_iflink,
134584e54fe0SWilliam Tu 	.ndo_fill_metadata_dst	= gre_fill_metadata_dst,
134684e54fe0SWilliam Tu };
134784e54fe0SWilliam Tu 
1348e1a80002SHerbert Xu static void ipgre_tap_setup(struct net_device *dev)
1349e1a80002SHerbert Xu {
1350e1a80002SHerbert Xu 	ether_setup(dev);
1351cfddd4c3SXin Long 	dev->max_mtu = 0;
1352c5441932SPravin B Shelar 	dev->netdev_ops	= &gre_tap_netdev_ops;
1353d13b161cSJiri Benc 	dev->priv_flags &= ~IFF_TX_SKB_SHARING;
1354f8c1b7ceSstephen hemminger 	dev->priv_flags	|= IFF_LIVE_ADDR_CHANGE;
1355c5441932SPravin B Shelar 	ip_tunnel_setup(dev, gre_tap_net_id);
1356e1a80002SHerbert Xu }
1357e1a80002SHerbert Xu 
1358c5441932SPravin B Shelar static int ipgre_newlink(struct net *src_net, struct net_device *dev,
13597a3f4a18SMatthias Schiffer 			 struct nlattr *tb[], struct nlattr *data[],
13607a3f4a18SMatthias Schiffer 			 struct netlink_ext_ack *extack)
1361c19e654dSHerbert Xu {
1362c5441932SPravin B Shelar 	struct ip_tunnel_parm p;
13634565e991STom Herbert 	struct ip_tunnel_encap ipencap;
13649830ad4cSCraig Gallek 	__u32 fwmark = 0;
136522a59be8SPhilip Prindeville 	int err;
13664565e991STom Herbert 
13674565e991STom Herbert 	if (ipgre_netlink_encap_parms(data, &ipencap)) {
13684565e991STom Herbert 		struct ip_tunnel *t = netdev_priv(dev);
136922a59be8SPhilip Prindeville 		err = ip_tunnel_encap_setup(t, &ipencap);
13704565e991STom Herbert 
13714565e991STom Herbert 		if (err < 0)
13724565e991STom Herbert 			return err;
13734565e991STom Herbert 	}
1374c19e654dSHerbert Xu 
13759830ad4cSCraig Gallek 	err = ipgre_netlink_parms(dev, data, tb, &p, &fwmark);
137622a59be8SPhilip Prindeville 	if (err < 0)
137722a59be8SPhilip Prindeville 		return err;
13789830ad4cSCraig Gallek 	return ip_tunnel_newlink(dev, tb, &p, fwmark);
1379c19e654dSHerbert Xu }
1380c19e654dSHerbert Xu 
1381c19e654dSHerbert Xu static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[],
1382ad744b22SMatthias Schiffer 			    struct nlattr *data[],
1383ad744b22SMatthias Schiffer 			    struct netlink_ext_ack *extack)
1384c19e654dSHerbert Xu {
13859830ad4cSCraig Gallek 	struct ip_tunnel *t = netdev_priv(dev);
13864565e991STom Herbert 	struct ip_tunnel_encap ipencap;
13879830ad4cSCraig Gallek 	__u32 fwmark = t->fwmark;
1388dd9d598cSXin Long 	struct ip_tunnel_parm p;
138922a59be8SPhilip Prindeville 	int err;
13904565e991STom Herbert 
13914565e991STom Herbert 	if (ipgre_netlink_encap_parms(data, &ipencap)) {
139222a59be8SPhilip Prindeville 		err = ip_tunnel_encap_setup(t, &ipencap);
13934565e991STom Herbert 
13944565e991STom Herbert 		if (err < 0)
13954565e991STom Herbert 			return err;
13964565e991STom Herbert 	}
1397c19e654dSHerbert Xu 
13989830ad4cSCraig Gallek 	err = ipgre_netlink_parms(dev, data, tb, &p, &fwmark);
139922a59be8SPhilip Prindeville 	if (err < 0)
140022a59be8SPhilip Prindeville 		return err;
1401dd9d598cSXin Long 
1402dd9d598cSXin Long 	err = ip_tunnel_changelink(dev, tb, &p, fwmark);
1403dd9d598cSXin Long 	if (err < 0)
1404dd9d598cSXin Long 		return err;
1405dd9d598cSXin Long 
1406dd9d598cSXin Long 	t->parms.i_flags = p.i_flags;
1407dd9d598cSXin Long 	t->parms.o_flags = p.o_flags;
1408dd9d598cSXin Long 
1409dd9d598cSXin Long 	if (strcmp(dev->rtnl_link_ops->kind, "erspan"))
1410dd9d598cSXin Long 		ipgre_link_update(dev, !tb[IFLA_MTU]);
1411dd9d598cSXin Long 
1412dd9d598cSXin Long 	return 0;
1413c19e654dSHerbert Xu }
1414c19e654dSHerbert Xu 
1415c19e654dSHerbert Xu static size_t ipgre_get_size(const struct net_device *dev)
1416c19e654dSHerbert Xu {
1417c19e654dSHerbert Xu 	return
1418c19e654dSHerbert Xu 		/* IFLA_GRE_LINK */
1419c19e654dSHerbert Xu 		nla_total_size(4) +
1420c19e654dSHerbert Xu 		/* IFLA_GRE_IFLAGS */
1421c19e654dSHerbert Xu 		nla_total_size(2) +
1422c19e654dSHerbert Xu 		/* IFLA_GRE_OFLAGS */
1423c19e654dSHerbert Xu 		nla_total_size(2) +
1424c19e654dSHerbert Xu 		/* IFLA_GRE_IKEY */
1425c19e654dSHerbert Xu 		nla_total_size(4) +
1426c19e654dSHerbert Xu 		/* IFLA_GRE_OKEY */
1427c19e654dSHerbert Xu 		nla_total_size(4) +
1428c19e654dSHerbert Xu 		/* IFLA_GRE_LOCAL */
1429c19e654dSHerbert Xu 		nla_total_size(4) +
1430c19e654dSHerbert Xu 		/* IFLA_GRE_REMOTE */
1431c19e654dSHerbert Xu 		nla_total_size(4) +
1432c19e654dSHerbert Xu 		/* IFLA_GRE_TTL */
1433c19e654dSHerbert Xu 		nla_total_size(1) +
1434c19e654dSHerbert Xu 		/* IFLA_GRE_TOS */
1435c19e654dSHerbert Xu 		nla_total_size(1) +
1436c19e654dSHerbert Xu 		/* IFLA_GRE_PMTUDISC */
1437c19e654dSHerbert Xu 		nla_total_size(1) +
14384565e991STom Herbert 		/* IFLA_GRE_ENCAP_TYPE */
14394565e991STom Herbert 		nla_total_size(2) +
14404565e991STom Herbert 		/* IFLA_GRE_ENCAP_FLAGS */
14414565e991STom Herbert 		nla_total_size(2) +
14424565e991STom Herbert 		/* IFLA_GRE_ENCAP_SPORT */
14434565e991STom Herbert 		nla_total_size(2) +
14444565e991STom Herbert 		/* IFLA_GRE_ENCAP_DPORT */
14454565e991STom Herbert 		nla_total_size(2) +
14462e15ea39SPravin B Shelar 		/* IFLA_GRE_COLLECT_METADATA */
14472e15ea39SPravin B Shelar 		nla_total_size(0) +
144822a59be8SPhilip Prindeville 		/* IFLA_GRE_IGNORE_DF */
144922a59be8SPhilip Prindeville 		nla_total_size(1) +
14509830ad4cSCraig Gallek 		/* IFLA_GRE_FWMARK */
14519830ad4cSCraig Gallek 		nla_total_size(4) +
145284e54fe0SWilliam Tu 		/* IFLA_GRE_ERSPAN_INDEX */
145384e54fe0SWilliam Tu 		nla_total_size(4) +
1454f551c91dSWilliam Tu 		/* IFLA_GRE_ERSPAN_VER */
1455f551c91dSWilliam Tu 		nla_total_size(1) +
1456f551c91dSWilliam Tu 		/* IFLA_GRE_ERSPAN_DIR */
1457f551c91dSWilliam Tu 		nla_total_size(1) +
1458f551c91dSWilliam Tu 		/* IFLA_GRE_ERSPAN_HWID */
1459f551c91dSWilliam Tu 		nla_total_size(2) +
1460c19e654dSHerbert Xu 		0;
1461c19e654dSHerbert Xu }
1462c19e654dSHerbert Xu 
1463c19e654dSHerbert Xu static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev)
1464c19e654dSHerbert Xu {
1465c19e654dSHerbert Xu 	struct ip_tunnel *t = netdev_priv(dev);
1466c19e654dSHerbert Xu 	struct ip_tunnel_parm *p = &t->parms;
1467c19e654dSHerbert Xu 
1468f3756b79SDavid S. Miller 	if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) ||
146995f5c64cSTom Herbert 	    nla_put_be16(skb, IFLA_GRE_IFLAGS,
147095f5c64cSTom Herbert 			 gre_tnl_flags_to_gre_flags(p->i_flags)) ||
147195f5c64cSTom Herbert 	    nla_put_be16(skb, IFLA_GRE_OFLAGS,
147295f5c64cSTom Herbert 			 gre_tnl_flags_to_gre_flags(p->o_flags)) ||
1473f3756b79SDavid S. Miller 	    nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) ||
1474f3756b79SDavid S. Miller 	    nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) ||
1475930345eaSJiri Benc 	    nla_put_in_addr(skb, IFLA_GRE_LOCAL, p->iph.saddr) ||
1476930345eaSJiri Benc 	    nla_put_in_addr(skb, IFLA_GRE_REMOTE, p->iph.daddr) ||
1477f3756b79SDavid S. Miller 	    nla_put_u8(skb, IFLA_GRE_TTL, p->iph.ttl) ||
1478f3756b79SDavid S. Miller 	    nla_put_u8(skb, IFLA_GRE_TOS, p->iph.tos) ||
1479f3756b79SDavid S. Miller 	    nla_put_u8(skb, IFLA_GRE_PMTUDISC,
14809830ad4cSCraig Gallek 		       !!(p->iph.frag_off & htons(IP_DF))) ||
14819830ad4cSCraig Gallek 	    nla_put_u32(skb, IFLA_GRE_FWMARK, t->fwmark))
1482f3756b79SDavid S. Miller 		goto nla_put_failure;
14834565e991STom Herbert 
14844565e991STom Herbert 	if (nla_put_u16(skb, IFLA_GRE_ENCAP_TYPE,
14854565e991STom Herbert 			t->encap.type) ||
14863e97fa70SSabrina Dubroca 	    nla_put_be16(skb, IFLA_GRE_ENCAP_SPORT,
14874565e991STom Herbert 			 t->encap.sport) ||
14883e97fa70SSabrina Dubroca 	    nla_put_be16(skb, IFLA_GRE_ENCAP_DPORT,
14894565e991STom Herbert 			 t->encap.dport) ||
14904565e991STom Herbert 	    nla_put_u16(skb, IFLA_GRE_ENCAP_FLAGS,
1491e1b2cb65STom Herbert 			t->encap.flags))
14924565e991STom Herbert 		goto nla_put_failure;
14934565e991STom Herbert 
149422a59be8SPhilip Prindeville 	if (nla_put_u8(skb, IFLA_GRE_IGNORE_DF, t->ignore_df))
149522a59be8SPhilip Prindeville 		goto nla_put_failure;
149622a59be8SPhilip Prindeville 
14972e15ea39SPravin B Shelar 	if (t->collect_md) {
14982e15ea39SPravin B Shelar 		if (nla_put_flag(skb, IFLA_GRE_COLLECT_METADATA))
14992e15ea39SPravin B Shelar 			goto nla_put_failure;
15002e15ea39SPravin B Shelar 	}
15012e15ea39SPravin B Shelar 
1502f551c91dSWilliam Tu 	if (nla_put_u8(skb, IFLA_GRE_ERSPAN_VER, t->erspan_ver))
1503f551c91dSWilliam Tu 		goto nla_put_failure;
1504f551c91dSWilliam Tu 
1505f551c91dSWilliam Tu 	if (t->erspan_ver == 1) {
150684e54fe0SWilliam Tu 		if (nla_put_u32(skb, IFLA_GRE_ERSPAN_INDEX, t->index))
150784e54fe0SWilliam Tu 			goto nla_put_failure;
1508f551c91dSWilliam Tu 	} else if (t->erspan_ver == 2) {
1509f551c91dSWilliam Tu 		if (nla_put_u8(skb, IFLA_GRE_ERSPAN_DIR, t->dir))
1510f551c91dSWilliam Tu 			goto nla_put_failure;
1511f551c91dSWilliam Tu 		if (nla_put_u16(skb, IFLA_GRE_ERSPAN_HWID, t->hwid))
1512f551c91dSWilliam Tu 			goto nla_put_failure;
1513f551c91dSWilliam Tu 	}
151484e54fe0SWilliam Tu 
1515c19e654dSHerbert Xu 	return 0;
1516c19e654dSHerbert Xu 
1517c19e654dSHerbert Xu nla_put_failure:
1518c19e654dSHerbert Xu 	return -EMSGSIZE;
1519c19e654dSHerbert Xu }
1520c19e654dSHerbert Xu 
152184e54fe0SWilliam Tu static void erspan_setup(struct net_device *dev)
152284e54fe0SWilliam Tu {
152384581bdaSXin Long 	struct ip_tunnel *t = netdev_priv(dev);
152484581bdaSXin Long 
152584e54fe0SWilliam Tu 	ether_setup(dev);
152684e54fe0SWilliam Tu 	dev->netdev_ops = &erspan_netdev_ops;
152784e54fe0SWilliam Tu 	dev->priv_flags &= ~IFF_TX_SKB_SHARING;
152884e54fe0SWilliam Tu 	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
152984e54fe0SWilliam Tu 	ip_tunnel_setup(dev, erspan_net_id);
153084581bdaSXin Long 	t->erspan_ver = 1;
153184e54fe0SWilliam Tu }
153284e54fe0SWilliam Tu 
1533c19e654dSHerbert Xu static const struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = {
1534c19e654dSHerbert Xu 	[IFLA_GRE_LINK]		= { .type = NLA_U32 },
1535c19e654dSHerbert Xu 	[IFLA_GRE_IFLAGS]	= { .type = NLA_U16 },
1536c19e654dSHerbert Xu 	[IFLA_GRE_OFLAGS]	= { .type = NLA_U16 },
1537c19e654dSHerbert Xu 	[IFLA_GRE_IKEY]		= { .type = NLA_U32 },
1538c19e654dSHerbert Xu 	[IFLA_GRE_OKEY]		= { .type = NLA_U32 },
15394d74f8baSPatrick McHardy 	[IFLA_GRE_LOCAL]	= { .len = FIELD_SIZEOF(struct iphdr, saddr) },
15404d74f8baSPatrick McHardy 	[IFLA_GRE_REMOTE]	= { .len = FIELD_SIZEOF(struct iphdr, daddr) },
1541c19e654dSHerbert Xu 	[IFLA_GRE_TTL]		= { .type = NLA_U8 },
1542c19e654dSHerbert Xu 	[IFLA_GRE_TOS]		= { .type = NLA_U8 },
1543c19e654dSHerbert Xu 	[IFLA_GRE_PMTUDISC]	= { .type = NLA_U8 },
15444565e991STom Herbert 	[IFLA_GRE_ENCAP_TYPE]	= { .type = NLA_U16 },
15454565e991STom Herbert 	[IFLA_GRE_ENCAP_FLAGS]	= { .type = NLA_U16 },
15464565e991STom Herbert 	[IFLA_GRE_ENCAP_SPORT]	= { .type = NLA_U16 },
15474565e991STom Herbert 	[IFLA_GRE_ENCAP_DPORT]	= { .type = NLA_U16 },
15482e15ea39SPravin B Shelar 	[IFLA_GRE_COLLECT_METADATA]	= { .type = NLA_FLAG },
154922a59be8SPhilip Prindeville 	[IFLA_GRE_IGNORE_DF]	= { .type = NLA_U8 },
15509830ad4cSCraig Gallek 	[IFLA_GRE_FWMARK]	= { .type = NLA_U32 },
155184e54fe0SWilliam Tu 	[IFLA_GRE_ERSPAN_INDEX]	= { .type = NLA_U32 },
1552f551c91dSWilliam Tu 	[IFLA_GRE_ERSPAN_VER]	= { .type = NLA_U8 },
1553f551c91dSWilliam Tu 	[IFLA_GRE_ERSPAN_DIR]	= { .type = NLA_U8 },
1554f551c91dSWilliam Tu 	[IFLA_GRE_ERSPAN_HWID]	= { .type = NLA_U16 },
1555c19e654dSHerbert Xu };
1556c19e654dSHerbert Xu 
1557c19e654dSHerbert Xu static struct rtnl_link_ops ipgre_link_ops __read_mostly = {
1558c19e654dSHerbert Xu 	.kind		= "gre",
1559c19e654dSHerbert Xu 	.maxtype	= IFLA_GRE_MAX,
1560c19e654dSHerbert Xu 	.policy		= ipgre_policy,
1561c19e654dSHerbert Xu 	.priv_size	= sizeof(struct ip_tunnel),
1562c19e654dSHerbert Xu 	.setup		= ipgre_tunnel_setup,
1563c19e654dSHerbert Xu 	.validate	= ipgre_tunnel_validate,
1564c19e654dSHerbert Xu 	.newlink	= ipgre_newlink,
1565c19e654dSHerbert Xu 	.changelink	= ipgre_changelink,
1566c5441932SPravin B Shelar 	.dellink	= ip_tunnel_dellink,
1567c19e654dSHerbert Xu 	.get_size	= ipgre_get_size,
1568c19e654dSHerbert Xu 	.fill_info	= ipgre_fill_info,
15691728d4faSNicolas Dichtel 	.get_link_net	= ip_tunnel_get_link_net,
1570c19e654dSHerbert Xu };
1571c19e654dSHerbert Xu 
1572e1a80002SHerbert Xu static struct rtnl_link_ops ipgre_tap_ops __read_mostly = {
1573e1a80002SHerbert Xu 	.kind		= "gretap",
1574e1a80002SHerbert Xu 	.maxtype	= IFLA_GRE_MAX,
1575e1a80002SHerbert Xu 	.policy		= ipgre_policy,
1576e1a80002SHerbert Xu 	.priv_size	= sizeof(struct ip_tunnel),
1577e1a80002SHerbert Xu 	.setup		= ipgre_tap_setup,
1578e1a80002SHerbert Xu 	.validate	= ipgre_tap_validate,
1579e1a80002SHerbert Xu 	.newlink	= ipgre_newlink,
1580e1a80002SHerbert Xu 	.changelink	= ipgre_changelink,
1581c5441932SPravin B Shelar 	.dellink	= ip_tunnel_dellink,
1582e1a80002SHerbert Xu 	.get_size	= ipgre_get_size,
1583e1a80002SHerbert Xu 	.fill_info	= ipgre_fill_info,
15841728d4faSNicolas Dichtel 	.get_link_net	= ip_tunnel_get_link_net,
1585e1a80002SHerbert Xu };
1586e1a80002SHerbert Xu 
158784e54fe0SWilliam Tu static struct rtnl_link_ops erspan_link_ops __read_mostly = {
158884e54fe0SWilliam Tu 	.kind		= "erspan",
158984e54fe0SWilliam Tu 	.maxtype	= IFLA_GRE_MAX,
159084e54fe0SWilliam Tu 	.policy		= ipgre_policy,
159184e54fe0SWilliam Tu 	.priv_size	= sizeof(struct ip_tunnel),
159284e54fe0SWilliam Tu 	.setup		= erspan_setup,
159384e54fe0SWilliam Tu 	.validate	= erspan_validate,
159484e54fe0SWilliam Tu 	.newlink	= ipgre_newlink,
159584e54fe0SWilliam Tu 	.changelink	= ipgre_changelink,
159684e54fe0SWilliam Tu 	.dellink	= ip_tunnel_dellink,
159784e54fe0SWilliam Tu 	.get_size	= ipgre_get_size,
159884e54fe0SWilliam Tu 	.fill_info	= ipgre_fill_info,
159984e54fe0SWilliam Tu 	.get_link_net	= ip_tunnel_get_link_net,
160084e54fe0SWilliam Tu };
160184e54fe0SWilliam Tu 
1602b2acd1dcSPravin B Shelar struct net_device *gretap_fb_dev_create(struct net *net, const char *name,
1603b2acd1dcSPravin B Shelar 					u8 name_assign_type)
1604b2acd1dcSPravin B Shelar {
1605b2acd1dcSPravin B Shelar 	struct nlattr *tb[IFLA_MAX + 1];
1606b2acd1dcSPravin B Shelar 	struct net_device *dev;
1607106da663SNicolas Dichtel 	LIST_HEAD(list_kill);
1608b2acd1dcSPravin B Shelar 	struct ip_tunnel *t;
1609b2acd1dcSPravin B Shelar 	int err;
1610b2acd1dcSPravin B Shelar 
1611b2acd1dcSPravin B Shelar 	memset(&tb, 0, sizeof(tb));
1612b2acd1dcSPravin B Shelar 
1613b2acd1dcSPravin B Shelar 	dev = rtnl_create_link(net, name, name_assign_type,
1614d0522f1cSDavid Ahern 			       &ipgre_tap_ops, tb, NULL);
1615b2acd1dcSPravin B Shelar 	if (IS_ERR(dev))
1616b2acd1dcSPravin B Shelar 		return dev;
1617b2acd1dcSPravin B Shelar 
1618b2acd1dcSPravin B Shelar 	/* Configure flow based GRE device. */
1619b2acd1dcSPravin B Shelar 	t = netdev_priv(dev);
1620b2acd1dcSPravin B Shelar 	t->collect_md = true;
1621b2acd1dcSPravin B Shelar 
16227a3f4a18SMatthias Schiffer 	err = ipgre_newlink(net, dev, tb, NULL, NULL);
1623106da663SNicolas Dichtel 	if (err < 0) {
1624106da663SNicolas Dichtel 		free_netdev(dev);
1625106da663SNicolas Dichtel 		return ERR_PTR(err);
1626106da663SNicolas Dichtel 	}
16277e059158SDavid Wragg 
16287e059158SDavid Wragg 	/* openvswitch users expect packet sizes to be unrestricted,
16297e059158SDavid Wragg 	 * so set the largest MTU we can.
16307e059158SDavid Wragg 	 */
16317e059158SDavid Wragg 	err = __ip_tunnel_change_mtu(dev, IP_MAX_MTU, false);
16327e059158SDavid Wragg 	if (err)
16337e059158SDavid Wragg 		goto out;
16347e059158SDavid Wragg 
1635da6f1da8SNicolas Dichtel 	err = rtnl_configure_link(dev, NULL);
1636da6f1da8SNicolas Dichtel 	if (err < 0)
1637da6f1da8SNicolas Dichtel 		goto out;
1638da6f1da8SNicolas Dichtel 
1639b2acd1dcSPravin B Shelar 	return dev;
1640b2acd1dcSPravin B Shelar out:
1641106da663SNicolas Dichtel 	ip_tunnel_dellink(dev, &list_kill);
1642106da663SNicolas Dichtel 	unregister_netdevice_many(&list_kill);
1643b2acd1dcSPravin B Shelar 	return ERR_PTR(err);
1644b2acd1dcSPravin B Shelar }
1645b2acd1dcSPravin B Shelar EXPORT_SYMBOL_GPL(gretap_fb_dev_create);
1646b2acd1dcSPravin B Shelar 
1647c5441932SPravin B Shelar static int __net_init ipgre_tap_init_net(struct net *net)
1648c5441932SPravin B Shelar {
16492e15ea39SPravin B Shelar 	return ip_tunnel_init_net(net, gre_tap_net_id, &ipgre_tap_ops, "gretap0");
1650c5441932SPravin B Shelar }
1651c5441932SPravin B Shelar 
165264bc1781SEric Dumazet static void __net_exit ipgre_tap_exit_batch_net(struct list_head *list_net)
1653c5441932SPravin B Shelar {
165464bc1781SEric Dumazet 	ip_tunnel_delete_nets(list_net, gre_tap_net_id, &ipgre_tap_ops);
1655c5441932SPravin B Shelar }
1656c5441932SPravin B Shelar 
1657c5441932SPravin B Shelar static struct pernet_operations ipgre_tap_net_ops = {
1658c5441932SPravin B Shelar 	.init = ipgre_tap_init_net,
165964bc1781SEric Dumazet 	.exit_batch = ipgre_tap_exit_batch_net,
1660c5441932SPravin B Shelar 	.id   = &gre_tap_net_id,
1661c5441932SPravin B Shelar 	.size = sizeof(struct ip_tunnel_net),
1662c5441932SPravin B Shelar };
16631da177e4SLinus Torvalds 
166484e54fe0SWilliam Tu static int __net_init erspan_init_net(struct net *net)
166584e54fe0SWilliam Tu {
166684e54fe0SWilliam Tu 	return ip_tunnel_init_net(net, erspan_net_id,
166784e54fe0SWilliam Tu 				  &erspan_link_ops, "erspan0");
166884e54fe0SWilliam Tu }
166984e54fe0SWilliam Tu 
167064bc1781SEric Dumazet static void __net_exit erspan_exit_batch_net(struct list_head *net_list)
167184e54fe0SWilliam Tu {
167264bc1781SEric Dumazet 	ip_tunnel_delete_nets(net_list, erspan_net_id, &erspan_link_ops);
167384e54fe0SWilliam Tu }
167484e54fe0SWilliam Tu 
167584e54fe0SWilliam Tu static struct pernet_operations erspan_net_ops = {
167684e54fe0SWilliam Tu 	.init = erspan_init_net,
167764bc1781SEric Dumazet 	.exit_batch = erspan_exit_batch_net,
167884e54fe0SWilliam Tu 	.id   = &erspan_net_id,
167984e54fe0SWilliam Tu 	.size = sizeof(struct ip_tunnel_net),
168084e54fe0SWilliam Tu };
168184e54fe0SWilliam Tu 
16821da177e4SLinus Torvalds static int __init ipgre_init(void)
16831da177e4SLinus Torvalds {
16841da177e4SLinus Torvalds 	int err;
16851da177e4SLinus Torvalds 
1686058bd4d2SJoe Perches 	pr_info("GRE over IPv4 tunneling driver\n");
16871da177e4SLinus Torvalds 
1688cfb8fbf2SEric W. Biederman 	err = register_pernet_device(&ipgre_net_ops);
168959a4c759SPavel Emelyanov 	if (err < 0)
1690c2892f02SAlexey Dobriyan 		return err;
1691c2892f02SAlexey Dobriyan 
1692c5441932SPravin B Shelar 	err = register_pernet_device(&ipgre_tap_net_ops);
1693c5441932SPravin B Shelar 	if (err < 0)
1694e3d0328cSWilliam Tu 		goto pnet_tap_failed;
1695c5441932SPravin B Shelar 
169684e54fe0SWilliam Tu 	err = register_pernet_device(&erspan_net_ops);
169784e54fe0SWilliam Tu 	if (err < 0)
169884e54fe0SWilliam Tu 		goto pnet_erspan_failed;
169984e54fe0SWilliam Tu 
17009f57c67cSPravin B Shelar 	err = gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO);
1701c2892f02SAlexey Dobriyan 	if (err < 0) {
1702058bd4d2SJoe Perches 		pr_info("%s: can't add protocol\n", __func__);
1703c2892f02SAlexey Dobriyan 		goto add_proto_failed;
1704c2892f02SAlexey Dobriyan 	}
17057daa0004SPavel Emelyanov 
1706c19e654dSHerbert Xu 	err = rtnl_link_register(&ipgre_link_ops);
1707c19e654dSHerbert Xu 	if (err < 0)
1708c19e654dSHerbert Xu 		goto rtnl_link_failed;
1709c19e654dSHerbert Xu 
1710e1a80002SHerbert Xu 	err = rtnl_link_register(&ipgre_tap_ops);
1711e1a80002SHerbert Xu 	if (err < 0)
1712e1a80002SHerbert Xu 		goto tap_ops_failed;
1713e1a80002SHerbert Xu 
171484e54fe0SWilliam Tu 	err = rtnl_link_register(&erspan_link_ops);
171584e54fe0SWilliam Tu 	if (err < 0)
171684e54fe0SWilliam Tu 		goto erspan_link_failed;
171784e54fe0SWilliam Tu 
1718c5441932SPravin B Shelar 	return 0;
1719c19e654dSHerbert Xu 
172084e54fe0SWilliam Tu erspan_link_failed:
172184e54fe0SWilliam Tu 	rtnl_link_unregister(&ipgre_tap_ops);
1722e1a80002SHerbert Xu tap_ops_failed:
1723e1a80002SHerbert Xu 	rtnl_link_unregister(&ipgre_link_ops);
1724c19e654dSHerbert Xu rtnl_link_failed:
17259f57c67cSPravin B Shelar 	gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
1726c2892f02SAlexey Dobriyan add_proto_failed:
172784e54fe0SWilliam Tu 	unregister_pernet_device(&erspan_net_ops);
172884e54fe0SWilliam Tu pnet_erspan_failed:
1729c5441932SPravin B Shelar 	unregister_pernet_device(&ipgre_tap_net_ops);
1730e3d0328cSWilliam Tu pnet_tap_failed:
1731c2892f02SAlexey Dobriyan 	unregister_pernet_device(&ipgre_net_ops);
1732c5441932SPravin B Shelar 	return err;
17331da177e4SLinus Torvalds }
17341da177e4SLinus Torvalds 
1735db44575fSAlexey Kuznetsov static void __exit ipgre_fini(void)
17361da177e4SLinus Torvalds {
1737e1a80002SHerbert Xu 	rtnl_link_unregister(&ipgre_tap_ops);
1738c19e654dSHerbert Xu 	rtnl_link_unregister(&ipgre_link_ops);
173984e54fe0SWilliam Tu 	rtnl_link_unregister(&erspan_link_ops);
17409f57c67cSPravin B Shelar 	gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
1741c5441932SPravin B Shelar 	unregister_pernet_device(&ipgre_tap_net_ops);
1742c2892f02SAlexey Dobriyan 	unregister_pernet_device(&ipgre_net_ops);
174384e54fe0SWilliam Tu 	unregister_pernet_device(&erspan_net_ops);
17441da177e4SLinus Torvalds }
17451da177e4SLinus Torvalds 
17461da177e4SLinus Torvalds module_init(ipgre_init);
17471da177e4SLinus Torvalds module_exit(ipgre_fini);
17481da177e4SLinus Torvalds MODULE_LICENSE("GPL");
17494d74f8baSPatrick McHardy MODULE_ALIAS_RTNL_LINK("gre");
17504d74f8baSPatrick McHardy MODULE_ALIAS_RTNL_LINK("gretap");
175184e54fe0SWilliam Tu MODULE_ALIAS_RTNL_LINK("erspan");
17528909c9adSVasiliy Kulikov MODULE_ALIAS_NETDEV("gre0");
1753c5441932SPravin B Shelar MODULE_ALIAS_NETDEV("gretap0");
175484e54fe0SWilliam Tu MODULE_ALIAS_NETDEV("erspan0");
1755