xref: /linux/net/ipv4/ip_gre.c (revision f7716b318568b22fbf0e3be99279a979e217cf71)
12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  *	Linux NET3:	GRE over IP protocol decoder.
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  *	Authors: Alexey Kuznetsov (kuznet@ms2.inr.ac.ru)
61da177e4SLinus Torvalds  */
71da177e4SLinus Torvalds 
8afd46503SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
9afd46503SJoe Perches 
104fc268d2SRandy Dunlap #include <linux/capability.h>
111da177e4SLinus Torvalds #include <linux/module.h>
121da177e4SLinus Torvalds #include <linux/types.h>
131da177e4SLinus Torvalds #include <linux/kernel.h>
145a0e3ad6STejun Heo #include <linux/slab.h>
157c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
161da177e4SLinus Torvalds #include <linux/skbuff.h>
171da177e4SLinus Torvalds #include <linux/netdevice.h>
181da177e4SLinus Torvalds #include <linux/in.h>
191da177e4SLinus Torvalds #include <linux/tcp.h>
201da177e4SLinus Torvalds #include <linux/udp.h>
211da177e4SLinus Torvalds #include <linux/if_arp.h>
222e15ea39SPravin B Shelar #include <linux/if_vlan.h>
231da177e4SLinus Torvalds #include <linux/init.h>
241da177e4SLinus Torvalds #include <linux/in6.h>
251da177e4SLinus Torvalds #include <linux/inetdevice.h>
261da177e4SLinus Torvalds #include <linux/igmp.h>
271da177e4SLinus Torvalds #include <linux/netfilter_ipv4.h>
28e1a80002SHerbert Xu #include <linux/etherdevice.h>
2946f25dffSKris Katterjohn #include <linux/if_ether.h>
301da177e4SLinus Torvalds 
311da177e4SLinus Torvalds #include <net/sock.h>
321da177e4SLinus Torvalds #include <net/ip.h>
331da177e4SLinus Torvalds #include <net/icmp.h>
341da177e4SLinus Torvalds #include <net/protocol.h>
35c5441932SPravin B Shelar #include <net/ip_tunnels.h>
361da177e4SLinus Torvalds #include <net/arp.h>
371da177e4SLinus Torvalds #include <net/checksum.h>
381da177e4SLinus Torvalds #include <net/dsfield.h>
391da177e4SLinus Torvalds #include <net/inet_ecn.h>
401da177e4SLinus Torvalds #include <net/xfrm.h>
4159a4c759SPavel Emelyanov #include <net/net_namespace.h>
4259a4c759SPavel Emelyanov #include <net/netns/generic.h>
43c19e654dSHerbert Xu #include <net/rtnetlink.h>
4400959adeSDmitry Kozlov #include <net/gre.h>
452e15ea39SPravin B Shelar #include <net/dst_metadata.h>
4684e54fe0SWilliam Tu #include <net/erspan.h>
471da177e4SLinus Torvalds 
481da177e4SLinus Torvalds /*
491da177e4SLinus Torvalds    Problems & solutions
501da177e4SLinus Torvalds    --------------------
511da177e4SLinus Torvalds 
521da177e4SLinus Torvalds    1. The most important issue is detecting local dead loops.
531da177e4SLinus Torvalds    They would cause complete host lockup in transmit, which
541da177e4SLinus Torvalds    would be "resolved" by stack overflow or, if queueing is enabled,
551da177e4SLinus Torvalds    with infinite looping in net_bh.
561da177e4SLinus Torvalds 
571da177e4SLinus Torvalds    We cannot track such dead loops during route installation,
581da177e4SLinus Torvalds    it is infeasible task. The most general solutions would be
591da177e4SLinus Torvalds    to keep skb->encapsulation counter (sort of local ttl),
606d0722a2SEric Dumazet    and silently drop packet when it expires. It is a good
61bff52857Sstephen hemminger    solution, but it supposes maintaining new variable in ALL
621da177e4SLinus Torvalds    skb, even if no tunneling is used.
631da177e4SLinus Torvalds 
646d0722a2SEric Dumazet    Current solution: xmit_recursion breaks dead loops. This is a percpu
656d0722a2SEric Dumazet    counter, since when we enter the first ndo_xmit(), cpu migration is
666d0722a2SEric Dumazet    forbidden. We force an exit if this counter reaches RECURSION_LIMIT
671da177e4SLinus Torvalds 
681da177e4SLinus Torvalds    2. Networking dead loops would not kill routers, but would really
691da177e4SLinus Torvalds    kill network. IP hop limit plays role of "t->recursion" in this case,
701da177e4SLinus Torvalds    if we copy it from packet being encapsulated to upper header.
711da177e4SLinus Torvalds    It is very good solution, but it introduces two problems:
721da177e4SLinus Torvalds 
731da177e4SLinus Torvalds    - Routing protocols, using packets with ttl=1 (OSPF, RIP2),
741da177e4SLinus Torvalds      do not work over tunnels.
751da177e4SLinus Torvalds    - traceroute does not work. I planned to relay ICMP from tunnel,
761da177e4SLinus Torvalds      so that this problem would be solved and traceroute output
771da177e4SLinus Torvalds      would even more informative. This idea appeared to be wrong:
781da177e4SLinus Torvalds      only Linux complies to rfc1812 now (yes, guys, Linux is the only
791da177e4SLinus Torvalds      true router now :-)), all routers (at least, in neighbourhood of mine)
801da177e4SLinus Torvalds      return only 8 bytes of payload. It is the end.
811da177e4SLinus Torvalds 
821da177e4SLinus Torvalds    Hence, if we want that OSPF worked or traceroute said something reasonable,
831da177e4SLinus Torvalds    we should search for another solution.
841da177e4SLinus Torvalds 
851da177e4SLinus Torvalds    One of them is to parse packet trying to detect inner encapsulation
861da177e4SLinus Torvalds    made by our node. It is difficult or even impossible, especially,
87bff52857Sstephen hemminger    taking into account fragmentation. TO be short, ttl is not solution at all.
881da177e4SLinus Torvalds 
891da177e4SLinus Torvalds    Current solution: The solution was UNEXPECTEDLY SIMPLE.
901da177e4SLinus Torvalds    We force DF flag on tunnels with preconfigured hop limit,
911da177e4SLinus Torvalds    that is ALL. :-) Well, it does not remove the problem completely,
921da177e4SLinus Torvalds    but exponential growth of network traffic is changed to linear
931da177e4SLinus Torvalds    (branches, that exceed pmtu are pruned) and tunnel mtu
94bff52857Sstephen hemminger    rapidly degrades to value <68, where looping stops.
951da177e4SLinus Torvalds    Yes, it is not good if there exists a router in the loop,
961da177e4SLinus Torvalds    which does not force DF, even when encapsulating packets have DF set.
971da177e4SLinus Torvalds    But it is not our problem! Nobody could accuse us, we made
981da177e4SLinus Torvalds    all that we could make. Even if it is your gated who injected
991da177e4SLinus Torvalds    fatal route to network, even if it were you who configured
1001da177e4SLinus Torvalds    fatal static route: you are innocent. :-)
1011da177e4SLinus Torvalds 
1021da177e4SLinus Torvalds    Alexey Kuznetsov.
1031da177e4SLinus Torvalds  */
1041da177e4SLinus Torvalds 
105eccc1bb8Sstephen hemminger static bool log_ecn_error = true;
106eccc1bb8Sstephen hemminger module_param(log_ecn_error, bool, 0644);
107eccc1bb8Sstephen hemminger MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN");
108eccc1bb8Sstephen hemminger 
109c19e654dSHerbert Xu static struct rtnl_link_ops ipgre_link_ops __read_mostly;
110aab1e898SGuillaume Nault static const struct header_ops ipgre_header_ops;
111aab1e898SGuillaume Nault 
1121da177e4SLinus Torvalds static int ipgre_tunnel_init(struct net_device *dev);
1131a66a836SWilliam Tu static void erspan_build_header(struct sk_buff *skb,
114c69de58bSWilliam Tu 				u32 id, u32 index,
115a3222dc9SWilliam Tu 				bool truncate, bool is_ipv4);
116eb8ce741SPavel Emelyanov 
117c7d03a00SAlexey Dobriyan static unsigned int ipgre_net_id __read_mostly;
118c7d03a00SAlexey Dobriyan static unsigned int gre_tap_net_id __read_mostly;
11984e54fe0SWilliam Tu static unsigned int erspan_net_id __read_mostly;
120eb8ce741SPavel Emelyanov 
12132bbd879SStefano Brivio static int ipgre_err(struct sk_buff *skb, u32 info,
122bda7bb46SPravin B Shelar 		     const struct tnl_ptk_info *tpi)
1231da177e4SLinus Torvalds {
1241da177e4SLinus Torvalds 
125071f92d0SRami Rosen 	/* All the routers (except for Linux) return only
1261da177e4SLinus Torvalds 	   8 bytes of packet payload. It means, that precise relaying of
1271da177e4SLinus Torvalds 	   ICMP in the real Internet is absolutely infeasible.
1281da177e4SLinus Torvalds 
1291da177e4SLinus Torvalds 	   Moreover, Cisco "wise men" put GRE key to the third word
130c5441932SPravin B Shelar 	   in GRE header. It makes impossible maintaining even soft
131c5441932SPravin B Shelar 	   state for keyed GRE tunnels with enabled checksum. Tell
132c5441932SPravin B Shelar 	   them "thank you".
1331da177e4SLinus Torvalds 
1341da177e4SLinus Torvalds 	   Well, I wonder, rfc1812 was written by Cisco employee,
135bff52857Sstephen hemminger 	   what the hell these idiots break standards established
136bff52857Sstephen hemminger 	   by themselves???
1371da177e4SLinus Torvalds 	   */
138c5441932SPravin B Shelar 	struct net *net = dev_net(skb->dev);
139c5441932SPravin B Shelar 	struct ip_tunnel_net *itn;
14096f5a846SEric Dumazet 	const struct iphdr *iph;
14188c7664fSArnaldo Carvalho de Melo 	const int type = icmp_hdr(skb)->type;
14288c7664fSArnaldo Carvalho de Melo 	const int code = icmp_hdr(skb)->code;
14320e1954fSEric Dumazet 	unsigned int data_len = 0;
1441da177e4SLinus Torvalds 	struct ip_tunnel *t;
145d2083287Sstephen hemminger 
146bda7bb46SPravin B Shelar 	if (tpi->proto == htons(ETH_P_TEB))
147c5441932SPravin B Shelar 		itn = net_generic(net, gre_tap_net_id);
14851dc63e3SHaishuang Yan 	else if (tpi->proto == htons(ETH_P_ERSPAN) ||
14951dc63e3SHaishuang Yan 		 tpi->proto == htons(ETH_P_ERSPAN2))
15051dc63e3SHaishuang Yan 		itn = net_generic(net, erspan_net_id);
151c5441932SPravin B Shelar 	else
152c5441932SPravin B Shelar 		itn = net_generic(net, ipgre_net_id);
153c5441932SPravin B Shelar 
154c0c0c50fSDuan Jiong 	iph = (const struct iphdr *)(icmp_hdr(skb) + 1);
155bda7bb46SPravin B Shelar 	t = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags,
156bda7bb46SPravin B Shelar 			     iph->daddr, iph->saddr, tpi->key);
157d2083287Sstephen hemminger 
15851456b29SIan Morris 	if (!t)
15932bbd879SStefano Brivio 		return -ENOENT;
16032bbd879SStefano Brivio 
16132bbd879SStefano Brivio 	switch (type) {
16232bbd879SStefano Brivio 	default:
16332bbd879SStefano Brivio 	case ICMP_PARAMETERPROB:
16432bbd879SStefano Brivio 		return 0;
16532bbd879SStefano Brivio 
16632bbd879SStefano Brivio 	case ICMP_DEST_UNREACH:
16732bbd879SStefano Brivio 		switch (code) {
16832bbd879SStefano Brivio 		case ICMP_SR_FAILED:
16932bbd879SStefano Brivio 		case ICMP_PORT_UNREACH:
17032bbd879SStefano Brivio 			/* Impossible event. */
17132bbd879SStefano Brivio 			return 0;
17232bbd879SStefano Brivio 		default:
17332bbd879SStefano Brivio 			/* All others are translated to HOST_UNREACH.
17432bbd879SStefano Brivio 			   rfc2003 contains "deep thoughts" about NET_UNREACH,
17532bbd879SStefano Brivio 			   I believe they are just ether pollution. --ANK
17632bbd879SStefano Brivio 			 */
17732bbd879SStefano Brivio 			break;
17832bbd879SStefano Brivio 		}
17932bbd879SStefano Brivio 		break;
18032bbd879SStefano Brivio 
18132bbd879SStefano Brivio 	case ICMP_TIME_EXCEEDED:
18232bbd879SStefano Brivio 		if (code != ICMP_EXC_TTL)
18332bbd879SStefano Brivio 			return 0;
18432bbd879SStefano Brivio 		data_len = icmp_hdr(skb)->un.reserved[1] * 4; /* RFC 4884 4.1 */
18532bbd879SStefano Brivio 		break;
18632bbd879SStefano Brivio 
18732bbd879SStefano Brivio 	case ICMP_REDIRECT:
18832bbd879SStefano Brivio 		break;
18932bbd879SStefano Brivio 	}
19036393395SDavid S. Miller 
1919b8c6d7bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6)
1929b8c6d7bSEric Dumazet        if (tpi->proto == htons(ETH_P_IPV6) &&
19320e1954fSEric Dumazet            !ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4 + tpi->hdr_len,
19420e1954fSEric Dumazet 				       type, data_len))
19532bbd879SStefano Brivio                return 0;
1969b8c6d7bSEric Dumazet #endif
1979b8c6d7bSEric Dumazet 
19836393395SDavid S. Miller 	if (t->parms.iph.daddr == 0 ||
199f97c1e0cSJoe Perches 	    ipv4_is_multicast(t->parms.iph.daddr))
20032bbd879SStefano Brivio 		return 0;
2011da177e4SLinus Torvalds 
2021da177e4SLinus Torvalds 	if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
20332bbd879SStefano Brivio 		return 0;
2041da177e4SLinus Torvalds 
205da6185d8SWei Yongjun 	if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO))
2061da177e4SLinus Torvalds 		t->err_count++;
2071da177e4SLinus Torvalds 	else
2081da177e4SLinus Torvalds 		t->err_count = 1;
2091da177e4SLinus Torvalds 	t->err_time = jiffies;
21032bbd879SStefano Brivio 
21132bbd879SStefano Brivio 	return 0;
2129f57c67cSPravin B Shelar }
2139f57c67cSPravin B Shelar 
2149f57c67cSPravin B Shelar static void gre_err(struct sk_buff *skb, u32 info)
2159f57c67cSPravin B Shelar {
2169f57c67cSPravin B Shelar 	/* All the routers (except for Linux) return only
2179f57c67cSPravin B Shelar 	 * 8 bytes of packet payload. It means, that precise relaying of
2189f57c67cSPravin B Shelar 	 * ICMP in the real Internet is absolutely infeasible.
2199f57c67cSPravin B Shelar 	 *
2209f57c67cSPravin B Shelar 	 * Moreover, Cisco "wise men" put GRE key to the third word
2219f57c67cSPravin B Shelar 	 * in GRE header. It makes impossible maintaining even soft
2229f57c67cSPravin B Shelar 	 * state for keyed
2239f57c67cSPravin B Shelar 	 * GRE tunnels with enabled checksum. Tell them "thank you".
2249f57c67cSPravin B Shelar 	 *
2259f57c67cSPravin B Shelar 	 * Well, I wonder, rfc1812 was written by Cisco employee,
2269f57c67cSPravin B Shelar 	 * what the hell these idiots break standards established
2279f57c67cSPravin B Shelar 	 * by themselves???
2289f57c67cSPravin B Shelar 	 */
2299f57c67cSPravin B Shelar 
230e582615aSEric Dumazet 	const struct iphdr *iph = (struct iphdr *)skb->data;
2319f57c67cSPravin B Shelar 	const int type = icmp_hdr(skb)->type;
2329f57c67cSPravin B Shelar 	const int code = icmp_hdr(skb)->code;
2339f57c67cSPravin B Shelar 	struct tnl_ptk_info tpi;
2349f57c67cSPravin B Shelar 
235b0350d51SHaishuang Yan 	if (gre_parse_header(skb, &tpi, NULL, htons(ETH_P_IP),
236b0350d51SHaishuang Yan 			     iph->ihl * 4) < 0)
2379f57c67cSPravin B Shelar 		return;
2389f57c67cSPravin B Shelar 
2399f57c67cSPravin B Shelar 	if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
2409f57c67cSPravin B Shelar 		ipv4_update_pmtu(skb, dev_net(skb->dev), info,
241d888f396SMaciej Żenczykowski 				 skb->dev->ifindex, IPPROTO_GRE);
2429f57c67cSPravin B Shelar 		return;
2439f57c67cSPravin B Shelar 	}
2449f57c67cSPravin B Shelar 	if (type == ICMP_REDIRECT) {
2451042caa7SMaciej Żenczykowski 		ipv4_redirect(skb, dev_net(skb->dev), skb->dev->ifindex,
2461042caa7SMaciej Żenczykowski 			      IPPROTO_GRE);
2479f57c67cSPravin B Shelar 		return;
2489f57c67cSPravin B Shelar 	}
2499f57c67cSPravin B Shelar 
2509f57c67cSPravin B Shelar 	ipgre_err(skb, info, &tpi);
2511da177e4SLinus Torvalds }
2521da177e4SLinus Torvalds 
253f989d546SWilliam Tu static bool is_erspan_type1(int gre_hdr_len)
254f989d546SWilliam Tu {
255f989d546SWilliam Tu 	/* Both ERSPAN type I (version 0) and type II (version 1) use
256f989d546SWilliam Tu 	 * protocol 0x88BE, but the type I has only 4-byte GRE header,
257f989d546SWilliam Tu 	 * while type II has 8-byte.
258f989d546SWilliam Tu 	 */
259f989d546SWilliam Tu 	return gre_hdr_len == 4;
260f989d546SWilliam Tu }
261f989d546SWilliam Tu 
26284e54fe0SWilliam Tu static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
26384e54fe0SWilliam Tu 		      int gre_hdr_len)
26484e54fe0SWilliam Tu {
26584e54fe0SWilliam Tu 	struct net *net = dev_net(skb->dev);
26684e54fe0SWilliam Tu 	struct metadata_dst *tun_dst = NULL;
2671d7e2ed2SWilliam Tu 	struct erspan_base_hdr *ershdr;
26884e54fe0SWilliam Tu 	struct ip_tunnel_net *itn;
26984e54fe0SWilliam Tu 	struct ip_tunnel *tunnel;
27084e54fe0SWilliam Tu 	const struct iphdr *iph;
2713df19283SWilliam Tu 	struct erspan_md2 *md2;
2721d7e2ed2SWilliam Tu 	int ver;
27384e54fe0SWilliam Tu 	int len;
27484e54fe0SWilliam Tu 
27584e54fe0SWilliam Tu 	itn = net_generic(net, erspan_net_id);
27684e54fe0SWilliam Tu 	iph = ip_hdr(skb);
277f989d546SWilliam Tu 	if (is_erspan_type1(gre_hdr_len)) {
278f989d546SWilliam Tu 		ver = 0;
279f989d546SWilliam Tu 		tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex,
280f989d546SWilliam Tu 					  tpi->flags | TUNNEL_NO_KEY,
281f989d546SWilliam Tu 					  iph->saddr, iph->daddr, 0);
282f989d546SWilliam Tu 	} else {
2831d7e2ed2SWilliam Tu 		ershdr = (struct erspan_base_hdr *)(skb->data + gre_hdr_len);
284c69de58bSWilliam Tu 		ver = ershdr->ver;
28584e54fe0SWilliam Tu 		tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex,
28684e54fe0SWilliam Tu 					  tpi->flags | TUNNEL_KEY,
28784e54fe0SWilliam Tu 					  iph->saddr, iph->daddr, tpi->key);
288f989d546SWilliam Tu 	}
28984e54fe0SWilliam Tu 
29084e54fe0SWilliam Tu 	if (tunnel) {
291f989d546SWilliam Tu 		if (is_erspan_type1(gre_hdr_len))
292f989d546SWilliam Tu 			len = gre_hdr_len;
293f989d546SWilliam Tu 		else
2941d7e2ed2SWilliam Tu 			len = gre_hdr_len + erspan_hdr_len(ver);
295f989d546SWilliam Tu 
2961d7e2ed2SWilliam Tu 		if (unlikely(!pskb_may_pull(skb, len)))
297ae3e1337SWilliam Tu 			return PACKET_REJECT;
2981d7e2ed2SWilliam Tu 
29984e54fe0SWilliam Tu 		if (__iptunnel_pull_header(skb,
3001d7e2ed2SWilliam Tu 					   len,
30184e54fe0SWilliam Tu 					   htons(ETH_P_TEB),
30284e54fe0SWilliam Tu 					   false, false) < 0)
30384e54fe0SWilliam Tu 			goto drop;
30484e54fe0SWilliam Tu 
3051a66a836SWilliam Tu 		if (tunnel->collect_md) {
306492b67e2SLorenzo Bianconi 			struct erspan_metadata *pkt_md, *md;
3071a66a836SWilliam Tu 			struct ip_tunnel_info *info;
308492b67e2SLorenzo Bianconi 			unsigned char *gh;
3091a66a836SWilliam Tu 			__be64 tun_id;
3101a66a836SWilliam Tu 			__be16 flags;
3111a66a836SWilliam Tu 
3121a66a836SWilliam Tu 			tpi->flags |= TUNNEL_KEY;
3131a66a836SWilliam Tu 			flags = tpi->flags;
3141a66a836SWilliam Tu 			tun_id = key32_to_tunnel_id(tpi->key);
3151a66a836SWilliam Tu 
3161a66a836SWilliam Tu 			tun_dst = ip_tun_rx_dst(skb, flags,
3171a66a836SWilliam Tu 						tun_id, sizeof(*md));
3181a66a836SWilliam Tu 			if (!tun_dst)
3191a66a836SWilliam Tu 				return PACKET_REJECT;
3201a66a836SWilliam Tu 
321492b67e2SLorenzo Bianconi 			/* skb can be uncloned in __iptunnel_pull_header, so
322492b67e2SLorenzo Bianconi 			 * old pkt_md is no longer valid and we need to reset
323492b67e2SLorenzo Bianconi 			 * it
324492b67e2SLorenzo Bianconi 			 */
325492b67e2SLorenzo Bianconi 			gh = skb_network_header(skb) +
326492b67e2SLorenzo Bianconi 			     skb_network_header_len(skb);
327492b67e2SLorenzo Bianconi 			pkt_md = (struct erspan_metadata *)(gh + gre_hdr_len +
328492b67e2SLorenzo Bianconi 							    sizeof(*ershdr));
3291a66a836SWilliam Tu 			md = ip_tunnel_info_opts(&tun_dst->u.tun_info);
330f551c91dSWilliam Tu 			md->version = ver;
3313df19283SWilliam Tu 			md2 = &md->u.md2;
3323df19283SWilliam Tu 			memcpy(md2, pkt_md, ver == 1 ? ERSPAN_V1_MDSIZE :
3333df19283SWilliam Tu 						       ERSPAN_V2_MDSIZE);
334f551c91dSWilliam Tu 
3351a66a836SWilliam Tu 			info = &tun_dst->u.tun_info;
3361a66a836SWilliam Tu 			info->key.tun_flags |= TUNNEL_ERSPAN_OPT;
3371a66a836SWilliam Tu 			info->options_len = sizeof(*md);
3381a66a836SWilliam Tu 		}
3391a66a836SWilliam Tu 
34084e54fe0SWilliam Tu 		skb_reset_mac_header(skb);
34184e54fe0SWilliam Tu 		ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error);
34284e54fe0SWilliam Tu 		return PACKET_RCVD;
34384e54fe0SWilliam Tu 	}
3445a64506bSHaishuang Yan 	return PACKET_REJECT;
3455a64506bSHaishuang Yan 
34684e54fe0SWilliam Tu drop:
34784e54fe0SWilliam Tu 	kfree_skb(skb);
34884e54fe0SWilliam Tu 	return PACKET_RCVD;
34984e54fe0SWilliam Tu }
35084e54fe0SWilliam Tu 
351125372faSJiri Benc static int __ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
352125372faSJiri Benc 		       struct ip_tunnel_net *itn, int hdr_len, bool raw_proto)
3531da177e4SLinus Torvalds {
3542e15ea39SPravin B Shelar 	struct metadata_dst *tun_dst = NULL;
355b71d1d42SEric Dumazet 	const struct iphdr *iph;
3561da177e4SLinus Torvalds 	struct ip_tunnel *tunnel;
3571da177e4SLinus Torvalds 
358eddc9ec5SArnaldo Carvalho de Melo 	iph = ip_hdr(skb);
359bda7bb46SPravin B Shelar 	tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags,
360bda7bb46SPravin B Shelar 				  iph->saddr, iph->daddr, tpi->key);
3611da177e4SLinus Torvalds 
362d2083287Sstephen hemminger 	if (tunnel) {
363c0d59da7Swenxu 		const struct iphdr *tnl_params;
364c0d59da7Swenxu 
365125372faSJiri Benc 		if (__iptunnel_pull_header(skb, hdr_len, tpi->proto,
366125372faSJiri Benc 					   raw_proto, false) < 0)
367244a797bSJiri Benc 			goto drop;
368244a797bSJiri Benc 
369aab1e898SGuillaume Nault 		/* Special case for ipgre_header_parse(), which expects the
370aab1e898SGuillaume Nault 		 * mac_header to point to the outer IP header.
371aab1e898SGuillaume Nault 		 */
372aab1e898SGuillaume Nault 		if (tunnel->dev->header_ops == &ipgre_header_ops)
3730e3da5bbSTimo Teräs 			skb_pop_mac_header(skb);
374e271c7b4SJiri Benc 		else
375e271c7b4SJiri Benc 			skb_reset_mac_header(skb);
376c0d59da7Swenxu 
377c0d59da7Swenxu 		tnl_params = &tunnel->parms.iph;
378c0d59da7Swenxu 		if (tunnel->collect_md || tnl_params->daddr == 0) {
379c29a70d2SPravin B Shelar 			__be16 flags;
380c29a70d2SPravin B Shelar 			__be64 tun_id;
3812e15ea39SPravin B Shelar 
382c29a70d2SPravin B Shelar 			flags = tpi->flags & (TUNNEL_CSUM | TUNNEL_KEY);
383d817f432SAmir Vadai 			tun_id = key32_to_tunnel_id(tpi->key);
384c29a70d2SPravin B Shelar 			tun_dst = ip_tun_rx_dst(skb, flags, tun_id, 0);
3852e15ea39SPravin B Shelar 			if (!tun_dst)
3862e15ea39SPravin B Shelar 				return PACKET_REJECT;
3872e15ea39SPravin B Shelar 		}
3882e15ea39SPravin B Shelar 
3892e15ea39SPravin B Shelar 		ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error);
390bda7bb46SPravin B Shelar 		return PACKET_RCVD;
3911da177e4SLinus Torvalds 	}
392125372faSJiri Benc 	return PACKET_NEXT;
393244a797bSJiri Benc 
394244a797bSJiri Benc drop:
395244a797bSJiri Benc 	kfree_skb(skb);
396244a797bSJiri Benc 	return PACKET_RCVD;
3971da177e4SLinus Torvalds }
3981da177e4SLinus Torvalds 
399125372faSJiri Benc static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
400125372faSJiri Benc 		     int hdr_len)
401125372faSJiri Benc {
402125372faSJiri Benc 	struct net *net = dev_net(skb->dev);
403125372faSJiri Benc 	struct ip_tunnel_net *itn;
404125372faSJiri Benc 	int res;
405125372faSJiri Benc 
406125372faSJiri Benc 	if (tpi->proto == htons(ETH_P_TEB))
407125372faSJiri Benc 		itn = net_generic(net, gre_tap_net_id);
408125372faSJiri Benc 	else
409125372faSJiri Benc 		itn = net_generic(net, ipgre_net_id);
410125372faSJiri Benc 
411125372faSJiri Benc 	res = __ipgre_rcv(skb, tpi, itn, hdr_len, false);
412125372faSJiri Benc 	if (res == PACKET_NEXT && tpi->proto == htons(ETH_P_TEB)) {
413125372faSJiri Benc 		/* ipgre tunnels in collect metadata mode should receive
414125372faSJiri Benc 		 * also ETH_P_TEB traffic.
415125372faSJiri Benc 		 */
416125372faSJiri Benc 		itn = net_generic(net, ipgre_net_id);
417125372faSJiri Benc 		res = __ipgre_rcv(skb, tpi, itn, hdr_len, true);
418125372faSJiri Benc 	}
419125372faSJiri Benc 	return res;
420125372faSJiri Benc }
421125372faSJiri Benc 
4229f57c67cSPravin B Shelar static int gre_rcv(struct sk_buff *skb)
4239f57c67cSPravin B Shelar {
4249f57c67cSPravin B Shelar 	struct tnl_ptk_info tpi;
4259f57c67cSPravin B Shelar 	bool csum_err = false;
42695f5c64cSTom Herbert 	int hdr_len;
4279f57c67cSPravin B Shelar 
4289f57c67cSPravin B Shelar #ifdef CONFIG_NET_IPGRE_BROADCAST
4299f57c67cSPravin B Shelar 	if (ipv4_is_multicast(ip_hdr(skb)->daddr)) {
4309f57c67cSPravin B Shelar 		/* Looped back packet, drop it! */
4319f57c67cSPravin B Shelar 		if (rt_is_output_route(skb_rtable(skb)))
4329f57c67cSPravin B Shelar 			goto drop;
4339f57c67cSPravin B Shelar 	}
4349f57c67cSPravin B Shelar #endif
4359f57c67cSPravin B Shelar 
436e582615aSEric Dumazet 	hdr_len = gre_parse_header(skb, &tpi, &csum_err, htons(ETH_P_IP), 0);
437f132ae7cSJiri Benc 	if (hdr_len < 0)
43895f5c64cSTom Herbert 		goto drop;
43995f5c64cSTom Herbert 
440f551c91dSWilliam Tu 	if (unlikely(tpi.proto == htons(ETH_P_ERSPAN) ||
441f551c91dSWilliam Tu 		     tpi.proto == htons(ETH_P_ERSPAN2))) {
44284e54fe0SWilliam Tu 		if (erspan_rcv(skb, &tpi, hdr_len) == PACKET_RCVD)
44384e54fe0SWilliam Tu 			return 0;
444dd8d5b8cSHaishuang Yan 		goto out;
44584e54fe0SWilliam Tu 	}
44684e54fe0SWilliam Tu 
447244a797bSJiri Benc 	if (ipgre_rcv(skb, &tpi, hdr_len) == PACKET_RCVD)
4489f57c67cSPravin B Shelar 		return 0;
4499f57c67cSPravin B Shelar 
450dd8d5b8cSHaishuang Yan out:
4519f57c67cSPravin B Shelar 	icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
4529f57c67cSPravin B Shelar drop:
4539f57c67cSPravin B Shelar 	kfree_skb(skb);
4549f57c67cSPravin B Shelar 	return 0;
4559f57c67cSPravin B Shelar }
4569f57c67cSPravin B Shelar 
457c5441932SPravin B Shelar static void __gre_xmit(struct sk_buff *skb, struct net_device *dev,
458c5441932SPravin B Shelar 		       const struct iphdr *tnl_params,
459c5441932SPravin B Shelar 		       __be16 proto)
460c5441932SPravin B Shelar {
461c5441932SPravin B Shelar 	struct ip_tunnel *tunnel = netdev_priv(dev);
462c5441932SPravin B Shelar 
463c5441932SPravin B Shelar 	if (tunnel->parms.o_flags & TUNNEL_SEQ)
464c5441932SPravin B Shelar 		tunnel->o_seqno++;
465cef401deSEric Dumazet 
466c5441932SPravin B Shelar 	/* Push GRE header. */
467182a352dSTom Herbert 	gre_build_header(skb, tunnel->tun_hlen,
468182a352dSTom Herbert 			 tunnel->parms.o_flags, proto, tunnel->parms.o_key,
469182a352dSTom Herbert 			 htonl(tunnel->o_seqno));
4701da177e4SLinus Torvalds 
471bf3d6a8fSNicolas Dichtel 	ip_tunnel_xmit(skb, dev, tnl_params, tnl_params->protocol);
4721da177e4SLinus Torvalds }
4731da177e4SLinus Torvalds 
474aed069dfSAlexander Duyck static int gre_handle_offloads(struct sk_buff *skb, bool csum)
475b2acd1dcSPravin B Shelar {
4766fa79666SEdward Cree 	return iptunnel_handle_offloads(skb, csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE);
477b2acd1dcSPravin B Shelar }
478b2acd1dcSPravin B Shelar 
479862a03c3SWilliam Tu static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev,
480862a03c3SWilliam Tu 			__be16 proto)
481862a03c3SWilliam Tu {
48277a5196aSWilliam Tu 	struct ip_tunnel *tunnel = netdev_priv(dev);
483862a03c3SWilliam Tu 	struct ip_tunnel_info *tun_info;
484862a03c3SWilliam Tu 	const struct ip_tunnel_key *key;
485862a03c3SWilliam Tu 	int tunnel_hlen;
486962924faSwenxu 	__be16 flags;
487862a03c3SWilliam Tu 
488862a03c3SWilliam Tu 	tun_info = skb_tunnel_info(skb);
489862a03c3SWilliam Tu 	if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) ||
490862a03c3SWilliam Tu 		     ip_tunnel_info_af(tun_info) != AF_INET))
491862a03c3SWilliam Tu 		goto err_free_skb;
492862a03c3SWilliam Tu 
493862a03c3SWilliam Tu 	key = &tun_info->key;
494862a03c3SWilliam Tu 	tunnel_hlen = gre_calc_hlen(key->tun_flags);
495862a03c3SWilliam Tu 
496962924faSwenxu 	if (skb_cow_head(skb, dev->needed_headroom))
497962924faSwenxu 		goto err_free_skb;
4982e15ea39SPravin B Shelar 
4992e15ea39SPravin B Shelar 	/* Push Tunnel header. */
500aed069dfSAlexander Duyck 	if (gre_handle_offloads(skb, !!(tun_info->key.tun_flags & TUNNEL_CSUM)))
501962924faSwenxu 		goto err_free_skb;
5022e15ea39SPravin B Shelar 
50377a5196aSWilliam Tu 	flags = tun_info->key.tun_flags &
50477a5196aSWilliam Tu 		(TUNNEL_CSUM | TUNNEL_KEY | TUNNEL_SEQ);
505cba65321SDavid S. Miller 	gre_build_header(skb, tunnel_hlen, flags, proto,
50677a5196aSWilliam Tu 			 tunnel_id_to_key32(tun_info->key.tun_id),
50715746394SColin Ian King 			 (flags & TUNNEL_SEQ) ? htonl(tunnel->o_seqno++) : 0);
5082e15ea39SPravin B Shelar 
509962924faSwenxu 	ip_md_tunnel_xmit(skb, dev, IPPROTO_GRE, tunnel_hlen);
510039f5062SPravin B Shelar 
5112e15ea39SPravin B Shelar 	return;
5122e15ea39SPravin B Shelar 
5132e15ea39SPravin B Shelar err_free_skb:
5142e15ea39SPravin B Shelar 	kfree_skb(skb);
5152e15ea39SPravin B Shelar 	dev->stats.tx_dropped++;
5162e15ea39SPravin B Shelar }
5172e15ea39SPravin B Shelar 
51820704bd1SXin Long static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev)
5191a66a836SWilliam Tu {
5201a66a836SWilliam Tu 	struct ip_tunnel *tunnel = netdev_priv(dev);
5211a66a836SWilliam Tu 	struct ip_tunnel_info *tun_info;
5221a66a836SWilliam Tu 	const struct ip_tunnel_key *key;
5231a66a836SWilliam Tu 	struct erspan_metadata *md;
5241a66a836SWilliam Tu 	bool truncate = false;
525962924faSwenxu 	__be16 proto;
5261a66a836SWilliam Tu 	int tunnel_hlen;
527f551c91dSWilliam Tu 	int version;
5281baf5ebfSWilliam Tu 	int nhoff;
529d5db21a3SWilliam Tu 	int thoff;
5301a66a836SWilliam Tu 
5311a66a836SWilliam Tu 	tun_info = skb_tunnel_info(skb);
5321a66a836SWilliam Tu 	if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) ||
5331a66a836SWilliam Tu 		     ip_tunnel_info_af(tun_info) != AF_INET))
5341a66a836SWilliam Tu 		goto err_free_skb;
5351a66a836SWilliam Tu 
5361a66a836SWilliam Tu 	key = &tun_info->key;
537256c87c1SPieter Jansen van Vuuren 	if (!(tun_info->key.tun_flags & TUNNEL_ERSPAN_OPT))
538962924faSwenxu 		goto err_free_skb;
5392eb8d6d2SXin Long 	if (tun_info->options_len < sizeof(*md))
540962924faSwenxu 		goto err_free_skb;
5412eb8d6d2SXin Long 	md = ip_tunnel_info_opts(tun_info);
5421a66a836SWilliam Tu 
5431a66a836SWilliam Tu 	/* ERSPAN has fixed 8 byte GRE header */
544f551c91dSWilliam Tu 	version = md->version;
545f551c91dSWilliam Tu 	tunnel_hlen = 8 + erspan_hdr_len(version);
5461a66a836SWilliam Tu 
547962924faSwenxu 	if (skb_cow_head(skb, dev->needed_headroom))
548962924faSwenxu 		goto err_free_skb;
5491a66a836SWilliam Tu 
5501a66a836SWilliam Tu 	if (gre_handle_offloads(skb, false))
551962924faSwenxu 		goto err_free_skb;
5521a66a836SWilliam Tu 
553f192970dSWilliam Tu 	if (skb->len > dev->mtu + dev->hard_header_len) {
554f192970dSWilliam Tu 		pskb_trim(skb, dev->mtu + dev->hard_header_len);
5551a66a836SWilliam Tu 		truncate = true;
5561a66a836SWilliam Tu 	}
5571a66a836SWilliam Tu 
5581baf5ebfSWilliam Tu 	nhoff = skb_network_header(skb) - skb_mac_header(skb);
5591baf5ebfSWilliam Tu 	if (skb->protocol == htons(ETH_P_IP) &&
5601baf5ebfSWilliam Tu 	    (ntohs(ip_hdr(skb)->tot_len) > skb->len - nhoff))
5611baf5ebfSWilliam Tu 		truncate = true;
5621baf5ebfSWilliam Tu 
563d5db21a3SWilliam Tu 	thoff = skb_transport_header(skb) - skb_mac_header(skb);
564d5db21a3SWilliam Tu 	if (skb->protocol == htons(ETH_P_IPV6) &&
565d5db21a3SWilliam Tu 	    (ntohs(ipv6_hdr(skb)->payload_len) > skb->len - thoff))
566d5db21a3SWilliam Tu 		truncate = true;
567d5db21a3SWilliam Tu 
568f551c91dSWilliam Tu 	if (version == 1) {
569c69de58bSWilliam Tu 		erspan_build_header(skb, ntohl(tunnel_id_to_key32(key->tun_id)),
5701d7e2ed2SWilliam Tu 				    ntohl(md->u.index), truncate, true);
57120704bd1SXin Long 		proto = htons(ETH_P_ERSPAN);
572f551c91dSWilliam Tu 	} else if (version == 2) {
573c69de58bSWilliam Tu 		erspan_build_header_v2(skb,
574c69de58bSWilliam Tu 				       ntohl(tunnel_id_to_key32(key->tun_id)),
575c69de58bSWilliam Tu 				       md->u.md2.dir,
576c69de58bSWilliam Tu 				       get_hwid(&md->u.md2),
577c69de58bSWilliam Tu 				       truncate, true);
57820704bd1SXin Long 		proto = htons(ETH_P_ERSPAN2);
579f551c91dSWilliam Tu 	} else {
580962924faSwenxu 		goto err_free_skb;
581f551c91dSWilliam Tu 	}
5821a66a836SWilliam Tu 
5831a66a836SWilliam Tu 	gre_build_header(skb, 8, TUNNEL_SEQ,
58420704bd1SXin Long 			 proto, 0, htonl(tunnel->o_seqno++));
5851a66a836SWilliam Tu 
586962924faSwenxu 	ip_md_tunnel_xmit(skb, dev, IPPROTO_GRE, tunnel_hlen);
5871a66a836SWilliam Tu 
5881a66a836SWilliam Tu 	return;
5891a66a836SWilliam Tu 
5901a66a836SWilliam Tu err_free_skb:
5911a66a836SWilliam Tu 	kfree_skb(skb);
5921a66a836SWilliam Tu 	dev->stats.tx_dropped++;
5931a66a836SWilliam Tu }
5941a66a836SWilliam Tu 
595fc4099f1SPravin B Shelar static int gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
596fc4099f1SPravin B Shelar {
597fc4099f1SPravin B Shelar 	struct ip_tunnel_info *info = skb_tunnel_info(skb);
598962924faSwenxu 	const struct ip_tunnel_key *key;
599fc4099f1SPravin B Shelar 	struct rtable *rt;
600fc4099f1SPravin B Shelar 	struct flowi4 fl4;
601fc4099f1SPravin B Shelar 
602fc4099f1SPravin B Shelar 	if (ip_tunnel_info_af(info) != AF_INET)
603fc4099f1SPravin B Shelar 		return -EINVAL;
604fc4099f1SPravin B Shelar 
605962924faSwenxu 	key = &info->key;
606962924faSwenxu 	ip_tunnel_init_flow(&fl4, IPPROTO_GRE, key->u.ipv4.dst, key->u.ipv4.src,
607*f7716b31SGuillaume Nault 			    tunnel_id_to_key32(key->tun_id),
608*f7716b31SGuillaume Nault 			    key->tos & ~INET_ECN_MASK, 0, skb->mark,
609*f7716b31SGuillaume Nault 			    skb_get_hash(skb));
610962924faSwenxu 	rt = ip_route_output_key(dev_net(dev), &fl4);
611fc4099f1SPravin B Shelar 	if (IS_ERR(rt))
612fc4099f1SPravin B Shelar 		return PTR_ERR(rt);
613fc4099f1SPravin B Shelar 
614fc4099f1SPravin B Shelar 	ip_rt_put(rt);
615fc4099f1SPravin B Shelar 	info->key.u.ipv4.src = fl4.saddr;
616fc4099f1SPravin B Shelar 	return 0;
617fc4099f1SPravin B Shelar }
618fc4099f1SPravin B Shelar 
619c5441932SPravin B Shelar static netdev_tx_t ipgre_xmit(struct sk_buff *skb,
620c5441932SPravin B Shelar 			      struct net_device *dev)
621ee34c1ebSMichal Schmidt {
622c5441932SPravin B Shelar 	struct ip_tunnel *tunnel = netdev_priv(dev);
623c5441932SPravin B Shelar 	const struct iphdr *tnl_params;
624ee34c1ebSMichal Schmidt 
625cb9f1b78SWillem de Bruijn 	if (!pskb_inet_may_pull(skb))
626cb9f1b78SWillem de Bruijn 		goto free_skb;
627cb9f1b78SWillem de Bruijn 
6282e15ea39SPravin B Shelar 	if (tunnel->collect_md) {
6292090714eSJiri Benc 		gre_fb_xmit(skb, dev, skb->protocol);
6302e15ea39SPravin B Shelar 		return NETDEV_TX_OK;
6312e15ea39SPravin B Shelar 	}
6322e15ea39SPravin B Shelar 
633c5441932SPravin B Shelar 	if (dev->header_ops) {
6348a0ed250SWillem de Bruijn 		const int pull_len = tunnel->hlen + sizeof(struct iphdr);
6358a0ed250SWillem de Bruijn 
636fdafed45SCong Wang 		if (skb_cow_head(skb, 0))
637c5441932SPravin B Shelar 			goto free_skb;
638ee34c1ebSMichal Schmidt 
639c5441932SPravin B Shelar 		tnl_params = (const struct iphdr *)skb->data;
640cbb1e85fSDavid S. Miller 
6418a0ed250SWillem de Bruijn 		if (pull_len > skb_transport_offset(skb))
6428a0ed250SWillem de Bruijn 			goto free_skb;
6438a0ed250SWillem de Bruijn 
644c5441932SPravin B Shelar 		/* Pull skb since ip_tunnel_xmit() needs skb->data pointing
645c5441932SPravin B Shelar 		 * to gre header.
646c5441932SPravin B Shelar 		 */
6478a0ed250SWillem de Bruijn 		skb_pull(skb, pull_len);
6488a0033a9STimo Teräs 		skb_reset_mac_header(skb);
649c5441932SPravin B Shelar 	} else {
650c5441932SPravin B Shelar 		if (skb_cow_head(skb, dev->needed_headroom))
651c5441932SPravin B Shelar 			goto free_skb;
652c5441932SPravin B Shelar 
653c5441932SPravin B Shelar 		tnl_params = &tunnel->parms.iph;
654ee34c1ebSMichal Schmidt 	}
655e1a80002SHerbert Xu 
656aed069dfSAlexander Duyck 	if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM)))
657aed069dfSAlexander Duyck 		goto free_skb;
6588a0033a9STimo Teräs 
659c5441932SPravin B Shelar 	__gre_xmit(skb, dev, tnl_params, skb->protocol);
660c5441932SPravin B Shelar 	return NETDEV_TX_OK;
661c5441932SPravin B Shelar 
662c5441932SPravin B Shelar free_skb:
6633acfa1e7SEric Dumazet 	kfree_skb(skb);
664c5441932SPravin B Shelar 	dev->stats.tx_dropped++;
665c5441932SPravin B Shelar 	return NETDEV_TX_OK;
666ee34c1ebSMichal Schmidt }
667ee34c1ebSMichal Schmidt 
66884e54fe0SWilliam Tu static netdev_tx_t erspan_xmit(struct sk_buff *skb,
66984e54fe0SWilliam Tu 			       struct net_device *dev)
67084e54fe0SWilliam Tu {
67184e54fe0SWilliam Tu 	struct ip_tunnel *tunnel = netdev_priv(dev);
67284e54fe0SWilliam Tu 	bool truncate = false;
67320704bd1SXin Long 	__be16 proto;
67484e54fe0SWilliam Tu 
675cb9f1b78SWillem de Bruijn 	if (!pskb_inet_may_pull(skb))
676cb9f1b78SWillem de Bruijn 		goto free_skb;
677cb9f1b78SWillem de Bruijn 
6781a66a836SWilliam Tu 	if (tunnel->collect_md) {
67920704bd1SXin Long 		erspan_fb_xmit(skb, dev);
6801a66a836SWilliam Tu 		return NETDEV_TX_OK;
6811a66a836SWilliam Tu 	}
6821a66a836SWilliam Tu 
68384e54fe0SWilliam Tu 	if (gre_handle_offloads(skb, false))
68484e54fe0SWilliam Tu 		goto free_skb;
68584e54fe0SWilliam Tu 
68684e54fe0SWilliam Tu 	if (skb_cow_head(skb, dev->needed_headroom))
68784e54fe0SWilliam Tu 		goto free_skb;
68884e54fe0SWilliam Tu 
689f192970dSWilliam Tu 	if (skb->len > dev->mtu + dev->hard_header_len) {
690f192970dSWilliam Tu 		pskb_trim(skb, dev->mtu + dev->hard_header_len);
69184e54fe0SWilliam Tu 		truncate = true;
69284e54fe0SWilliam Tu 	}
69384e54fe0SWilliam Tu 
69484e54fe0SWilliam Tu 	/* Push ERSPAN header */
695f989d546SWilliam Tu 	if (tunnel->erspan_ver == 0) {
696f989d546SWilliam Tu 		proto = htons(ETH_P_ERSPAN);
697f989d546SWilliam Tu 		tunnel->parms.o_flags &= ~TUNNEL_SEQ;
698f989d546SWilliam Tu 	} else if (tunnel->erspan_ver == 1) {
699c69de58bSWilliam Tu 		erspan_build_header(skb, ntohl(tunnel->parms.o_key),
700c69de58bSWilliam Tu 				    tunnel->index,
701a3222dc9SWilliam Tu 				    truncate, true);
70220704bd1SXin Long 		proto = htons(ETH_P_ERSPAN);
70320704bd1SXin Long 	} else if (tunnel->erspan_ver == 2) {
704c69de58bSWilliam Tu 		erspan_build_header_v2(skb, ntohl(tunnel->parms.o_key),
705f551c91dSWilliam Tu 				       tunnel->dir, tunnel->hwid,
706f551c91dSWilliam Tu 				       truncate, true);
70720704bd1SXin Long 		proto = htons(ETH_P_ERSPAN2);
70820704bd1SXin Long 	} else {
70902f99df1SWilliam Tu 		goto free_skb;
71020704bd1SXin Long 	}
711f551c91dSWilliam Tu 
71284e54fe0SWilliam Tu 	tunnel->parms.o_flags &= ~TUNNEL_KEY;
71320704bd1SXin Long 	__gre_xmit(skb, dev, &tunnel->parms.iph, proto);
71484e54fe0SWilliam Tu 	return NETDEV_TX_OK;
71584e54fe0SWilliam Tu 
71684e54fe0SWilliam Tu free_skb:
71784e54fe0SWilliam Tu 	kfree_skb(skb);
71884e54fe0SWilliam Tu 	dev->stats.tx_dropped++;
71984e54fe0SWilliam Tu 	return NETDEV_TX_OK;
72084e54fe0SWilliam Tu }
72184e54fe0SWilliam Tu 
722c5441932SPravin B Shelar static netdev_tx_t gre_tap_xmit(struct sk_buff *skb,
723c5441932SPravin B Shelar 				struct net_device *dev)
724c5441932SPravin B Shelar {
725c5441932SPravin B Shelar 	struct ip_tunnel *tunnel = netdev_priv(dev);
726ee34c1ebSMichal Schmidt 
727cb9f1b78SWillem de Bruijn 	if (!pskb_inet_may_pull(skb))
728cb9f1b78SWillem de Bruijn 		goto free_skb;
729cb9f1b78SWillem de Bruijn 
7302e15ea39SPravin B Shelar 	if (tunnel->collect_md) {
7312090714eSJiri Benc 		gre_fb_xmit(skb, dev, htons(ETH_P_TEB));
7322e15ea39SPravin B Shelar 		return NETDEV_TX_OK;
7332e15ea39SPravin B Shelar 	}
7342e15ea39SPravin B Shelar 
735aed069dfSAlexander Duyck 	if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM)))
736aed069dfSAlexander Duyck 		goto free_skb;
737ee34c1ebSMichal Schmidt 
738c5441932SPravin B Shelar 	if (skb_cow_head(skb, dev->needed_headroom))
739c5441932SPravin B Shelar 		goto free_skb;
74042aa9162SHerbert Xu 
741c5441932SPravin B Shelar 	__gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_TEB));
742c5441932SPravin B Shelar 	return NETDEV_TX_OK;
743c5441932SPravin B Shelar 
744c5441932SPravin B Shelar free_skb:
7453acfa1e7SEric Dumazet 	kfree_skb(skb);
746c5441932SPravin B Shelar 	dev->stats.tx_dropped++;
747c5441932SPravin B Shelar 	return NETDEV_TX_OK;
74868c33163SPravin B Shelar }
749ee34c1ebSMichal Schmidt 
750dd9d598cSXin Long static void ipgre_link_update(struct net_device *dev, bool set_mtu)
751dd9d598cSXin Long {
752dd9d598cSXin Long 	struct ip_tunnel *tunnel = netdev_priv(dev);
753dd9d598cSXin Long 	int len;
754dd9d598cSXin Long 
755dd9d598cSXin Long 	len = tunnel->tun_hlen;
756dd9d598cSXin Long 	tunnel->tun_hlen = gre_calc_hlen(tunnel->parms.o_flags);
757dd9d598cSXin Long 	len = tunnel->tun_hlen - len;
758dd9d598cSXin Long 	tunnel->hlen = tunnel->hlen + len;
759dd9d598cSXin Long 
760fdafed45SCong Wang 	if (dev->header_ops)
761fdafed45SCong Wang 		dev->hard_header_len += len;
762fdafed45SCong Wang 	else
763fdafed45SCong Wang 		dev->needed_headroom += len;
764fdafed45SCong Wang 
765dd9d598cSXin Long 	if (set_mtu)
766dd9d598cSXin Long 		dev->mtu = max_t(int, dev->mtu - len, 68);
767dd9d598cSXin Long 
768dd9d598cSXin Long 	if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) {
769dd9d598cSXin Long 		if (!(tunnel->parms.o_flags & TUNNEL_CSUM) ||
770dd9d598cSXin Long 		    tunnel->encap.type == TUNNEL_ENCAP_NONE) {
771dd9d598cSXin Long 			dev->features |= NETIF_F_GSO_SOFTWARE;
772dd9d598cSXin Long 			dev->hw_features |= NETIF_F_GSO_SOFTWARE;
7731cc5954fSSabrina Dubroca 		} else {
7741cc5954fSSabrina Dubroca 			dev->features &= ~NETIF_F_GSO_SOFTWARE;
7751cc5954fSSabrina Dubroca 			dev->hw_features &= ~NETIF_F_GSO_SOFTWARE;
776dd9d598cSXin Long 		}
777dd9d598cSXin Long 		dev->features |= NETIF_F_LLTX;
7781cc5954fSSabrina Dubroca 	} else {
7791cc5954fSSabrina Dubroca 		dev->hw_features &= ~NETIF_F_GSO_SOFTWARE;
7801cc5954fSSabrina Dubroca 		dev->features &= ~(NETIF_F_LLTX | NETIF_F_GSO_SOFTWARE);
781dd9d598cSXin Long 	}
782dd9d598cSXin Long }
783dd9d598cSXin Long 
784607259a6SChristoph Hellwig static int ipgre_tunnel_ctl(struct net_device *dev, struct ip_tunnel_parm *p,
785607259a6SChristoph Hellwig 			    int cmd)
7861da177e4SLinus Torvalds {
787a0efab67SXin Long 	int err;
7881da177e4SLinus Torvalds 
7896c734fb8SCong Wang 	if (cmd == SIOCADDTUNNEL || cmd == SIOCCHGTUNNEL) {
790607259a6SChristoph Hellwig 		if (p->iph.version != 4 || p->iph.protocol != IPPROTO_GRE ||
791607259a6SChristoph Hellwig 		    p->iph.ihl != 5 || (p->iph.frag_off & htons(~IP_DF)) ||
792607259a6SChristoph Hellwig 		    ((p->i_flags | p->o_flags) & (GRE_VERSION | GRE_ROUTING)))
7931da177e4SLinus Torvalds 			return -EINVAL;
794c5441932SPravin B Shelar 	}
795a0efab67SXin Long 
796607259a6SChristoph Hellwig 	p->i_flags = gre_flags_to_tnl_flags(p->i_flags);
797607259a6SChristoph Hellwig 	p->o_flags = gre_flags_to_tnl_flags(p->o_flags);
798c5441932SPravin B Shelar 
799607259a6SChristoph Hellwig 	err = ip_tunnel_ctl(dev, p, cmd);
800c5441932SPravin B Shelar 	if (err)
801c5441932SPravin B Shelar 		return err;
802c5441932SPravin B Shelar 
803a0efab67SXin Long 	if (cmd == SIOCCHGTUNNEL) {
804a0efab67SXin Long 		struct ip_tunnel *t = netdev_priv(dev);
805a0efab67SXin Long 
806607259a6SChristoph Hellwig 		t->parms.i_flags = p->i_flags;
807607259a6SChristoph Hellwig 		t->parms.o_flags = p->o_flags;
808a0efab67SXin Long 
809a0efab67SXin Long 		if (strcmp(dev->rtnl_link_ops->kind, "erspan"))
810a0efab67SXin Long 			ipgre_link_update(dev, true);
811a0efab67SXin Long 	}
812a0efab67SXin Long 
813607259a6SChristoph Hellwig 	p->i_flags = gre_tnl_flags_to_gre_flags(p->i_flags);
814607259a6SChristoph Hellwig 	p->o_flags = gre_tnl_flags_to_gre_flags(p->o_flags);
8151da177e4SLinus Torvalds 	return 0;
8161da177e4SLinus Torvalds }
8171da177e4SLinus Torvalds 
8181da177e4SLinus Torvalds /* Nice toy. Unfortunately, useless in real life :-)
8191da177e4SLinus Torvalds    It allows to construct virtual multiprotocol broadcast "LAN"
8201da177e4SLinus Torvalds    over the Internet, provided multicast routing is tuned.
8211da177e4SLinus Torvalds 
8221da177e4SLinus Torvalds 
8231da177e4SLinus Torvalds    I have no idea was this bicycle invented before me,
8241da177e4SLinus Torvalds    so that I had to set ARPHRD_IPGRE to a random value.
8251da177e4SLinus Torvalds    I have an impression, that Cisco could make something similar,
8261da177e4SLinus Torvalds    but this feature is apparently missing in IOS<=11.2(8).
8271da177e4SLinus Torvalds 
8281da177e4SLinus Torvalds    I set up 10.66.66/24 and fec0:6666:6666::0/96 as virtual networks
8291da177e4SLinus Torvalds    with broadcast 224.66.66.66. If you have access to mbone, play with me :-)
8301da177e4SLinus Torvalds 
8311da177e4SLinus Torvalds    ping -t 255 224.66.66.66
8321da177e4SLinus Torvalds 
8331da177e4SLinus Torvalds    If nobody answers, mbone does not work.
8341da177e4SLinus Torvalds 
8351da177e4SLinus Torvalds    ip tunnel add Universe mode gre remote 224.66.66.66 local <Your_real_addr> ttl 255
8361da177e4SLinus Torvalds    ip addr add 10.66.66.<somewhat>/24 dev Universe
8371da177e4SLinus Torvalds    ifconfig Universe up
8381da177e4SLinus Torvalds    ifconfig Universe add fe80::<Your_real_addr>/10
8391da177e4SLinus Torvalds    ifconfig Universe add fec0:6666:6666::<Your_real_addr>/96
8401da177e4SLinus Torvalds    ftp 10.66.66.66
8411da177e4SLinus Torvalds    ...
8421da177e4SLinus Torvalds    ftp fec0:6666:6666::193.233.7.65
8431da177e4SLinus Torvalds    ...
8441da177e4SLinus Torvalds  */
8453b04dddeSStephen Hemminger static int ipgre_header(struct sk_buff *skb, struct net_device *dev,
8463b04dddeSStephen Hemminger 			unsigned short type,
8471507850bSEric Dumazet 			const void *daddr, const void *saddr, unsigned int len)
8481da177e4SLinus Torvalds {
8492941a486SPatrick McHardy 	struct ip_tunnel *t = netdev_priv(dev);
850c5441932SPravin B Shelar 	struct iphdr *iph;
851c5441932SPravin B Shelar 	struct gre_base_hdr *greh;
852c5441932SPravin B Shelar 
853d58ff351SJohannes Berg 	iph = skb_push(skb, t->hlen + sizeof(*iph));
854c5441932SPravin B Shelar 	greh = (struct gre_base_hdr *)(iph+1);
85595f5c64cSTom Herbert 	greh->flags = gre_tnl_flags_to_gre_flags(t->parms.o_flags);
856c5441932SPravin B Shelar 	greh->protocol = htons(type);
8571da177e4SLinus Torvalds 
8581da177e4SLinus Torvalds 	memcpy(iph, &t->parms.iph, sizeof(struct iphdr));
8591da177e4SLinus Torvalds 
860c5441932SPravin B Shelar 	/* Set the source hardware address. */
8611da177e4SLinus Torvalds 	if (saddr)
8621da177e4SLinus Torvalds 		memcpy(&iph->saddr, saddr, 4);
8636d55cb91STimo Teräs 	if (daddr)
8641da177e4SLinus Torvalds 		memcpy(&iph->daddr, daddr, 4);
8656d55cb91STimo Teräs 	if (iph->daddr)
86677a482bdSTimo Teräs 		return t->hlen + sizeof(*iph);
8671da177e4SLinus Torvalds 
868c5441932SPravin B Shelar 	return -(t->hlen + sizeof(*iph));
8691da177e4SLinus Torvalds }
8701da177e4SLinus Torvalds 
8716a5f44d7STimo Teras static int ipgre_header_parse(const struct sk_buff *skb, unsigned char *haddr)
8726a5f44d7STimo Teras {
873b71d1d42SEric Dumazet 	const struct iphdr *iph = (const struct iphdr *) skb_mac_header(skb);
8746a5f44d7STimo Teras 	memcpy(haddr, &iph->saddr, 4);
8756a5f44d7STimo Teras 	return 4;
8766a5f44d7STimo Teras }
8776a5f44d7STimo Teras 
8783b04dddeSStephen Hemminger static const struct header_ops ipgre_header_ops = {
8793b04dddeSStephen Hemminger 	.create	= ipgre_header,
8806a5f44d7STimo Teras 	.parse	= ipgre_header_parse,
8813b04dddeSStephen Hemminger };
8823b04dddeSStephen Hemminger 
8836a5f44d7STimo Teras #ifdef CONFIG_NET_IPGRE_BROADCAST
8841da177e4SLinus Torvalds static int ipgre_open(struct net_device *dev)
8851da177e4SLinus Torvalds {
8862941a486SPatrick McHardy 	struct ip_tunnel *t = netdev_priv(dev);
8871da177e4SLinus Torvalds 
888f97c1e0cSJoe Perches 	if (ipv4_is_multicast(t->parms.iph.daddr)) {
889cbb1e85fSDavid S. Miller 		struct flowi4 fl4;
890cbb1e85fSDavid S. Miller 		struct rtable *rt;
891cbb1e85fSDavid S. Miller 
892b57708adSNicolas Dichtel 		rt = ip_route_output_gre(t->net, &fl4,
89378fbfd8aSDavid S. Miller 					 t->parms.iph.daddr,
89478fbfd8aSDavid S. Miller 					 t->parms.iph.saddr,
89578fbfd8aSDavid S. Miller 					 t->parms.o_key,
89678fbfd8aSDavid S. Miller 					 RT_TOS(t->parms.iph.tos),
89778fbfd8aSDavid S. Miller 					 t->parms.link);
898b23dd4feSDavid S. Miller 		if (IS_ERR(rt))
8991da177e4SLinus Torvalds 			return -EADDRNOTAVAIL;
900d8d1f30bSChangli Gao 		dev = rt->dst.dev;
9011da177e4SLinus Torvalds 		ip_rt_put(rt);
90251456b29SIan Morris 		if (!__in_dev_get_rtnl(dev))
9031da177e4SLinus Torvalds 			return -EADDRNOTAVAIL;
9041da177e4SLinus Torvalds 		t->mlink = dev->ifindex;
905e5ed6399SHerbert Xu 		ip_mc_inc_group(__in_dev_get_rtnl(dev), t->parms.iph.daddr);
9061da177e4SLinus Torvalds 	}
9071da177e4SLinus Torvalds 	return 0;
9081da177e4SLinus Torvalds }
9091da177e4SLinus Torvalds 
9101da177e4SLinus Torvalds static int ipgre_close(struct net_device *dev)
9111da177e4SLinus Torvalds {
9122941a486SPatrick McHardy 	struct ip_tunnel *t = netdev_priv(dev);
913b8c26a33SStephen Hemminger 
914f97c1e0cSJoe Perches 	if (ipv4_is_multicast(t->parms.iph.daddr) && t->mlink) {
9157fee0ca2SDenis V. Lunev 		struct in_device *in_dev;
916b57708adSNicolas Dichtel 		in_dev = inetdev_by_index(t->net, t->mlink);
9178723e1b4SEric Dumazet 		if (in_dev)
9181da177e4SLinus Torvalds 			ip_mc_dec_group(in_dev, t->parms.iph.daddr);
9191da177e4SLinus Torvalds 	}
9201da177e4SLinus Torvalds 	return 0;
9211da177e4SLinus Torvalds }
9221da177e4SLinus Torvalds #endif
9231da177e4SLinus Torvalds 
924b8c26a33SStephen Hemminger static const struct net_device_ops ipgre_netdev_ops = {
925b8c26a33SStephen Hemminger 	.ndo_init		= ipgre_tunnel_init,
926c5441932SPravin B Shelar 	.ndo_uninit		= ip_tunnel_uninit,
927b8c26a33SStephen Hemminger #ifdef CONFIG_NET_IPGRE_BROADCAST
928b8c26a33SStephen Hemminger 	.ndo_open		= ipgre_open,
929b8c26a33SStephen Hemminger 	.ndo_stop		= ipgre_close,
930b8c26a33SStephen Hemminger #endif
931c5441932SPravin B Shelar 	.ndo_start_xmit		= ipgre_xmit,
9323e7a1c7cSArnd Bergmann 	.ndo_siocdevprivate	= ip_tunnel_siocdevprivate,
933c5441932SPravin B Shelar 	.ndo_change_mtu		= ip_tunnel_change_mtu,
93498d7fc46SHeiner Kallweit 	.ndo_get_stats64	= dev_get_tstats64,
9351e99584bSNicolas Dichtel 	.ndo_get_iflink		= ip_tunnel_get_iflink,
936607259a6SChristoph Hellwig 	.ndo_tunnel_ctl		= ipgre_tunnel_ctl,
937b8c26a33SStephen Hemminger };
938b8c26a33SStephen Hemminger 
9396b78f16eSEric Dumazet #define GRE_FEATURES (NETIF_F_SG |		\
9406b78f16eSEric Dumazet 		      NETIF_F_FRAGLIST |	\
9416b78f16eSEric Dumazet 		      NETIF_F_HIGHDMA |		\
9426b78f16eSEric Dumazet 		      NETIF_F_HW_CSUM)
9436b78f16eSEric Dumazet 
9441da177e4SLinus Torvalds static void ipgre_tunnel_setup(struct net_device *dev)
9451da177e4SLinus Torvalds {
946b8c26a33SStephen Hemminger 	dev->netdev_ops		= &ipgre_netdev_ops;
9475a455275SNicolas Dichtel 	dev->type		= ARPHRD_IPGRE;
948c5441932SPravin B Shelar 	ip_tunnel_setup(dev, ipgre_net_id);
949c5441932SPravin B Shelar }
9501da177e4SLinus Torvalds 
951c5441932SPravin B Shelar static void __gre_tunnel_init(struct net_device *dev)
952c5441932SPravin B Shelar {
953c5441932SPravin B Shelar 	struct ip_tunnel *tunnel;
954c5441932SPravin B Shelar 
955c5441932SPravin B Shelar 	tunnel = netdev_priv(dev);
95695f5c64cSTom Herbert 	tunnel->tun_hlen = gre_calc_hlen(tunnel->parms.o_flags);
957c5441932SPravin B Shelar 	tunnel->parms.iph.protocol = IPPROTO_GRE;
958c5441932SPravin B Shelar 
9594565e991STom Herbert 	tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen;
960fdafed45SCong Wang 	dev->needed_headroom = tunnel->hlen + sizeof(tunnel->parms.iph);
9614565e991STom Herbert 
962b57708adSNicolas Dichtel 	dev->features		|= GRE_FEATURES;
9636b78f16eSEric Dumazet 	dev->hw_features	|= GRE_FEATURES;
964c5441932SPravin B Shelar 
965c5441932SPravin B Shelar 	if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) {
966a0ca153fSAlexander Duyck 		/* TCP offload with GRE SEQ is not supported, nor
967a0ca153fSAlexander Duyck 		 * can we support 2 levels of outer headers requiring
968a0ca153fSAlexander Duyck 		 * an update.
969a0ca153fSAlexander Duyck 		 */
970a0ca153fSAlexander Duyck 		if (!(tunnel->parms.o_flags & TUNNEL_CSUM) ||
971a0ca153fSAlexander Duyck 		    (tunnel->encap.type == TUNNEL_ENCAP_NONE)) {
972c5441932SPravin B Shelar 			dev->features    |= NETIF_F_GSO_SOFTWARE;
973c5441932SPravin B Shelar 			dev->hw_features |= NETIF_F_GSO_SOFTWARE;
974a0ca153fSAlexander Duyck 		}
975a0ca153fSAlexander Duyck 
976c5441932SPravin B Shelar 		/* Can use a lockless transmit, unless we generate
977c5441932SPravin B Shelar 		 * output sequences
978c5441932SPravin B Shelar 		 */
979c5441932SPravin B Shelar 		dev->features |= NETIF_F_LLTX;
980c5441932SPravin B Shelar 	}
9811da177e4SLinus Torvalds }
9821da177e4SLinus Torvalds 
9831da177e4SLinus Torvalds static int ipgre_tunnel_init(struct net_device *dev)
9841da177e4SLinus Torvalds {
985c5441932SPravin B Shelar 	struct ip_tunnel *tunnel = netdev_priv(dev);
986c5441932SPravin B Shelar 	struct iphdr *iph = &tunnel->parms.iph;
9871da177e4SLinus Torvalds 
988c5441932SPravin B Shelar 	__gre_tunnel_init(dev);
9891da177e4SLinus Torvalds 
9905a1b7e1aSJakub Kicinski 	__dev_addr_set(dev, &iph->saddr, 4);
991c5441932SPravin B Shelar 	memcpy(dev->broadcast, &iph->daddr, 4);
9921da177e4SLinus Torvalds 
993c5441932SPravin B Shelar 	dev->flags		= IFF_NOARP;
99402875878SEric Dumazet 	netif_keep_dst(dev);
995c5441932SPravin B Shelar 	dev->addr_len		= 4;
9961da177e4SLinus Torvalds 
997a64b04d8SJiri Benc 	if (iph->daddr && !tunnel->collect_md) {
9981da177e4SLinus Torvalds #ifdef CONFIG_NET_IPGRE_BROADCAST
999f97c1e0cSJoe Perches 		if (ipv4_is_multicast(iph->daddr)) {
10001da177e4SLinus Torvalds 			if (!iph->saddr)
10011da177e4SLinus Torvalds 				return -EINVAL;
10021da177e4SLinus Torvalds 			dev->flags = IFF_BROADCAST;
10033b04dddeSStephen Hemminger 			dev->header_ops = &ipgre_header_ops;
1004fdafed45SCong Wang 			dev->hard_header_len = tunnel->hlen + sizeof(*iph);
1005fdafed45SCong Wang 			dev->needed_headroom = 0;
10061da177e4SLinus Torvalds 		}
10071da177e4SLinus Torvalds #endif
1008a64b04d8SJiri Benc 	} else if (!tunnel->collect_md) {
10096a5f44d7STimo Teras 		dev->header_ops = &ipgre_header_ops;
1010fdafed45SCong Wang 		dev->hard_header_len = tunnel->hlen + sizeof(*iph);
1011fdafed45SCong Wang 		dev->needed_headroom = 0;
1012a64b04d8SJiri Benc 	}
10131da177e4SLinus Torvalds 
1014c5441932SPravin B Shelar 	return ip_tunnel_init(dev);
101560769a5dSEric Dumazet }
101660769a5dSEric Dumazet 
10179f57c67cSPravin B Shelar static const struct gre_protocol ipgre_protocol = {
10189f57c67cSPravin B Shelar 	.handler     = gre_rcv,
10199f57c67cSPravin B Shelar 	.err_handler = gre_err,
10201da177e4SLinus Torvalds };
10211da177e4SLinus Torvalds 
10222c8c1e72SAlexey Dobriyan static int __net_init ipgre_init_net(struct net *net)
102359a4c759SPavel Emelyanov {
1024c5441932SPravin B Shelar 	return ip_tunnel_init_net(net, ipgre_net_id, &ipgre_link_ops, NULL);
102559a4c759SPavel Emelyanov }
102659a4c759SPavel Emelyanov 
102764bc1781SEric Dumazet static void __net_exit ipgre_exit_batch_net(struct list_head *list_net)
102859a4c759SPavel Emelyanov {
102964bc1781SEric Dumazet 	ip_tunnel_delete_nets(list_net, ipgre_net_id, &ipgre_link_ops);
103059a4c759SPavel Emelyanov }
103159a4c759SPavel Emelyanov 
103259a4c759SPavel Emelyanov static struct pernet_operations ipgre_net_ops = {
103359a4c759SPavel Emelyanov 	.init = ipgre_init_net,
103464bc1781SEric Dumazet 	.exit_batch = ipgre_exit_batch_net,
1035cfb8fbf2SEric W. Biederman 	.id   = &ipgre_net_id,
1036c5441932SPravin B Shelar 	.size = sizeof(struct ip_tunnel_net),
103759a4c759SPavel Emelyanov };
10381da177e4SLinus Torvalds 
1039a8b8a889SMatthias Schiffer static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[],
1040a8b8a889SMatthias Schiffer 				 struct netlink_ext_ack *extack)
1041c19e654dSHerbert Xu {
1042c19e654dSHerbert Xu 	__be16 flags;
1043c19e654dSHerbert Xu 
1044c19e654dSHerbert Xu 	if (!data)
1045c19e654dSHerbert Xu 		return 0;
1046c19e654dSHerbert Xu 
1047c19e654dSHerbert Xu 	flags = 0;
1048c19e654dSHerbert Xu 	if (data[IFLA_GRE_IFLAGS])
1049c19e654dSHerbert Xu 		flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]);
1050c19e654dSHerbert Xu 	if (data[IFLA_GRE_OFLAGS])
1051c19e654dSHerbert Xu 		flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]);
1052c19e654dSHerbert Xu 	if (flags & (GRE_VERSION|GRE_ROUTING))
1053c19e654dSHerbert Xu 		return -EINVAL;
1054c19e654dSHerbert Xu 
1055946b636fSJiri Benc 	if (data[IFLA_GRE_COLLECT_METADATA] &&
1056946b636fSJiri Benc 	    data[IFLA_GRE_ENCAP_TYPE] &&
1057946b636fSJiri Benc 	    nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]) != TUNNEL_ENCAP_NONE)
1058946b636fSJiri Benc 		return -EINVAL;
1059946b636fSJiri Benc 
1060c19e654dSHerbert Xu 	return 0;
1061c19e654dSHerbert Xu }
1062c19e654dSHerbert Xu 
1063a8b8a889SMatthias Schiffer static int ipgre_tap_validate(struct nlattr *tb[], struct nlattr *data[],
1064a8b8a889SMatthias Schiffer 			      struct netlink_ext_ack *extack)
1065e1a80002SHerbert Xu {
1066e1a80002SHerbert Xu 	__be32 daddr;
1067e1a80002SHerbert Xu 
1068e1a80002SHerbert Xu 	if (tb[IFLA_ADDRESS]) {
1069e1a80002SHerbert Xu 		if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
1070e1a80002SHerbert Xu 			return -EINVAL;
1071e1a80002SHerbert Xu 		if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
1072e1a80002SHerbert Xu 			return -EADDRNOTAVAIL;
1073e1a80002SHerbert Xu 	}
1074e1a80002SHerbert Xu 
1075e1a80002SHerbert Xu 	if (!data)
1076e1a80002SHerbert Xu 		goto out;
1077e1a80002SHerbert Xu 
1078e1a80002SHerbert Xu 	if (data[IFLA_GRE_REMOTE]) {
1079e1a80002SHerbert Xu 		memcpy(&daddr, nla_data(data[IFLA_GRE_REMOTE]), 4);
1080e1a80002SHerbert Xu 		if (!daddr)
1081e1a80002SHerbert Xu 			return -EINVAL;
1082e1a80002SHerbert Xu 	}
1083e1a80002SHerbert Xu 
1084e1a80002SHerbert Xu out:
1085a8b8a889SMatthias Schiffer 	return ipgre_tunnel_validate(tb, data, extack);
1086e1a80002SHerbert Xu }
1087e1a80002SHerbert Xu 
108884e54fe0SWilliam Tu static int erspan_validate(struct nlattr *tb[], struct nlattr *data[],
108984e54fe0SWilliam Tu 			   struct netlink_ext_ack *extack)
109084e54fe0SWilliam Tu {
109184e54fe0SWilliam Tu 	__be16 flags = 0;
109284e54fe0SWilliam Tu 	int ret;
109384e54fe0SWilliam Tu 
109484e54fe0SWilliam Tu 	if (!data)
109584e54fe0SWilliam Tu 		return 0;
109684e54fe0SWilliam Tu 
109784e54fe0SWilliam Tu 	ret = ipgre_tap_validate(tb, data, extack);
109884e54fe0SWilliam Tu 	if (ret)
109984e54fe0SWilliam Tu 		return ret;
110084e54fe0SWilliam Tu 
110151fa960dSWilliam Tu 	if (data[IFLA_GRE_ERSPAN_VER] &&
110251fa960dSWilliam Tu 	    nla_get_u8(data[IFLA_GRE_ERSPAN_VER]) == 0)
1103f989d546SWilliam Tu 		return 0;
1104f989d546SWilliam Tu 
1105f989d546SWilliam Tu 	/* ERSPAN type II/III should only have GRE sequence and key flag */
11061a66a836SWilliam Tu 	if (data[IFLA_GRE_OFLAGS])
110784e54fe0SWilliam Tu 		flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]);
11081a66a836SWilliam Tu 	if (data[IFLA_GRE_IFLAGS])
110984e54fe0SWilliam Tu 		flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]);
11101a66a836SWilliam Tu 	if (!data[IFLA_GRE_COLLECT_METADATA] &&
11111a66a836SWilliam Tu 	    flags != (GRE_SEQ | GRE_KEY))
111284e54fe0SWilliam Tu 		return -EINVAL;
111384e54fe0SWilliam Tu 
111484e54fe0SWilliam Tu 	/* ERSPAN Session ID only has 10-bit. Since we reuse
111584e54fe0SWilliam Tu 	 * 32-bit key field as ID, check it's range.
111684e54fe0SWilliam Tu 	 */
111784e54fe0SWilliam Tu 	if (data[IFLA_GRE_IKEY] &&
111884e54fe0SWilliam Tu 	    (ntohl(nla_get_be32(data[IFLA_GRE_IKEY])) & ~ID_MASK))
111984e54fe0SWilliam Tu 		return -EINVAL;
112084e54fe0SWilliam Tu 
112184e54fe0SWilliam Tu 	if (data[IFLA_GRE_OKEY] &&
112284e54fe0SWilliam Tu 	    (ntohl(nla_get_be32(data[IFLA_GRE_OKEY])) & ~ID_MASK))
112384e54fe0SWilliam Tu 		return -EINVAL;
112484e54fe0SWilliam Tu 
112584e54fe0SWilliam Tu 	return 0;
112684e54fe0SWilliam Tu }
112784e54fe0SWilliam Tu 
112822a59be8SPhilip Prindeville static int ipgre_netlink_parms(struct net_device *dev,
11292e15ea39SPravin B Shelar 				struct nlattr *data[],
11302e15ea39SPravin B Shelar 				struct nlattr *tb[],
11319830ad4cSCraig Gallek 				struct ip_tunnel_parm *parms,
11329830ad4cSCraig Gallek 				__u32 *fwmark)
1133c19e654dSHerbert Xu {
113422a59be8SPhilip Prindeville 	struct ip_tunnel *t = netdev_priv(dev);
113522a59be8SPhilip Prindeville 
11367bb82d92SHerbert Xu 	memset(parms, 0, sizeof(*parms));
1137c19e654dSHerbert Xu 
1138c19e654dSHerbert Xu 	parms->iph.protocol = IPPROTO_GRE;
1139c19e654dSHerbert Xu 
1140c19e654dSHerbert Xu 	if (!data)
114122a59be8SPhilip Prindeville 		return 0;
1142c19e654dSHerbert Xu 
1143c19e654dSHerbert Xu 	if (data[IFLA_GRE_LINK])
1144c19e654dSHerbert Xu 		parms->link = nla_get_u32(data[IFLA_GRE_LINK]);
1145c19e654dSHerbert Xu 
1146c19e654dSHerbert Xu 	if (data[IFLA_GRE_IFLAGS])
1147c5441932SPravin B Shelar 		parms->i_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_IFLAGS]));
1148c19e654dSHerbert Xu 
1149c19e654dSHerbert Xu 	if (data[IFLA_GRE_OFLAGS])
1150c5441932SPravin B Shelar 		parms->o_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_OFLAGS]));
1151c19e654dSHerbert Xu 
1152c19e654dSHerbert Xu 	if (data[IFLA_GRE_IKEY])
1153c19e654dSHerbert Xu 		parms->i_key = nla_get_be32(data[IFLA_GRE_IKEY]);
1154c19e654dSHerbert Xu 
1155c19e654dSHerbert Xu 	if (data[IFLA_GRE_OKEY])
1156c19e654dSHerbert Xu 		parms->o_key = nla_get_be32(data[IFLA_GRE_OKEY]);
1157c19e654dSHerbert Xu 
1158c19e654dSHerbert Xu 	if (data[IFLA_GRE_LOCAL])
115967b61f6cSJiri Benc 		parms->iph.saddr = nla_get_in_addr(data[IFLA_GRE_LOCAL]);
1160c19e654dSHerbert Xu 
1161c19e654dSHerbert Xu 	if (data[IFLA_GRE_REMOTE])
116267b61f6cSJiri Benc 		parms->iph.daddr = nla_get_in_addr(data[IFLA_GRE_REMOTE]);
1163c19e654dSHerbert Xu 
1164c19e654dSHerbert Xu 	if (data[IFLA_GRE_TTL])
1165c19e654dSHerbert Xu 		parms->iph.ttl = nla_get_u8(data[IFLA_GRE_TTL]);
1166c19e654dSHerbert Xu 
1167c19e654dSHerbert Xu 	if (data[IFLA_GRE_TOS])
1168c19e654dSHerbert Xu 		parms->iph.tos = nla_get_u8(data[IFLA_GRE_TOS]);
1169c19e654dSHerbert Xu 
117022a59be8SPhilip Prindeville 	if (!data[IFLA_GRE_PMTUDISC] || nla_get_u8(data[IFLA_GRE_PMTUDISC])) {
117122a59be8SPhilip Prindeville 		if (t->ignore_df)
117222a59be8SPhilip Prindeville 			return -EINVAL;
1173c19e654dSHerbert Xu 		parms->iph.frag_off = htons(IP_DF);
117422a59be8SPhilip Prindeville 	}
11752e15ea39SPravin B Shelar 
11762e15ea39SPravin B Shelar 	if (data[IFLA_GRE_COLLECT_METADATA]) {
11772e15ea39SPravin B Shelar 		t->collect_md = true;
1178e271c7b4SJiri Benc 		if (dev->type == ARPHRD_IPGRE)
1179e271c7b4SJiri Benc 			dev->type = ARPHRD_NONE;
11802e15ea39SPravin B Shelar 	}
118122a59be8SPhilip Prindeville 
118222a59be8SPhilip Prindeville 	if (data[IFLA_GRE_IGNORE_DF]) {
118322a59be8SPhilip Prindeville 		if (nla_get_u8(data[IFLA_GRE_IGNORE_DF])
118422a59be8SPhilip Prindeville 		  && (parms->iph.frag_off & htons(IP_DF)))
118522a59be8SPhilip Prindeville 			return -EINVAL;
118622a59be8SPhilip Prindeville 		t->ignore_df = !!nla_get_u8(data[IFLA_GRE_IGNORE_DF]);
118722a59be8SPhilip Prindeville 	}
118822a59be8SPhilip Prindeville 
11899830ad4cSCraig Gallek 	if (data[IFLA_GRE_FWMARK])
11909830ad4cSCraig Gallek 		*fwmark = nla_get_u32(data[IFLA_GRE_FWMARK]);
11919830ad4cSCraig Gallek 
1192e1f8f78fSPetr Machata 	return 0;
1193e1f8f78fSPetr Machata }
1194e1f8f78fSPetr Machata 
1195e1f8f78fSPetr Machata static int erspan_netlink_parms(struct net_device *dev,
1196e1f8f78fSPetr Machata 				struct nlattr *data[],
1197e1f8f78fSPetr Machata 				struct nlattr *tb[],
1198e1f8f78fSPetr Machata 				struct ip_tunnel_parm *parms,
1199e1f8f78fSPetr Machata 				__u32 *fwmark)
1200e1f8f78fSPetr Machata {
1201e1f8f78fSPetr Machata 	struct ip_tunnel *t = netdev_priv(dev);
1202e1f8f78fSPetr Machata 	int err;
1203e1f8f78fSPetr Machata 
1204e1f8f78fSPetr Machata 	err = ipgre_netlink_parms(dev, data, tb, parms, fwmark);
1205e1f8f78fSPetr Machata 	if (err)
1206e1f8f78fSPetr Machata 		return err;
120732ca98feSPetr Machata 	if (!data)
120832ca98feSPetr Machata 		return 0;
1209e1f8f78fSPetr Machata 
1210f551c91dSWilliam Tu 	if (data[IFLA_GRE_ERSPAN_VER]) {
1211f551c91dSWilliam Tu 		t->erspan_ver = nla_get_u8(data[IFLA_GRE_ERSPAN_VER]);
1212f551c91dSWilliam Tu 
1213f989d546SWilliam Tu 		if (t->erspan_ver > 2)
1214f551c91dSWilliam Tu 			return -EINVAL;
1215f551c91dSWilliam Tu 	}
1216f551c91dSWilliam Tu 
1217f551c91dSWilliam Tu 	if (t->erspan_ver == 1) {
121884e54fe0SWilliam Tu 		if (data[IFLA_GRE_ERSPAN_INDEX]) {
121984e54fe0SWilliam Tu 			t->index = nla_get_u32(data[IFLA_GRE_ERSPAN_INDEX]);
122084e54fe0SWilliam Tu 			if (t->index & ~INDEX_MASK)
122184e54fe0SWilliam Tu 				return -EINVAL;
122284e54fe0SWilliam Tu 		}
1223f551c91dSWilliam Tu 	} else if (t->erspan_ver == 2) {
1224f551c91dSWilliam Tu 		if (data[IFLA_GRE_ERSPAN_DIR]) {
1225f551c91dSWilliam Tu 			t->dir = nla_get_u8(data[IFLA_GRE_ERSPAN_DIR]);
1226f551c91dSWilliam Tu 			if (t->dir & ~(DIR_MASK >> DIR_OFFSET))
1227f551c91dSWilliam Tu 				return -EINVAL;
1228f551c91dSWilliam Tu 		}
1229f551c91dSWilliam Tu 		if (data[IFLA_GRE_ERSPAN_HWID]) {
1230f551c91dSWilliam Tu 			t->hwid = nla_get_u16(data[IFLA_GRE_ERSPAN_HWID]);
1231f551c91dSWilliam Tu 			if (t->hwid & ~(HWID_MASK >> HWID_OFFSET))
1232f551c91dSWilliam Tu 				return -EINVAL;
1233f551c91dSWilliam Tu 		}
1234f551c91dSWilliam Tu 	}
123584e54fe0SWilliam Tu 
123622a59be8SPhilip Prindeville 	return 0;
1237c19e654dSHerbert Xu }
1238c19e654dSHerbert Xu 
12394565e991STom Herbert /* This function returns true when ENCAP attributes are present in the nl msg */
12404565e991STom Herbert static bool ipgre_netlink_encap_parms(struct nlattr *data[],
12414565e991STom Herbert 				      struct ip_tunnel_encap *ipencap)
12424565e991STom Herbert {
12434565e991STom Herbert 	bool ret = false;
12444565e991STom Herbert 
12454565e991STom Herbert 	memset(ipencap, 0, sizeof(*ipencap));
12464565e991STom Herbert 
12474565e991STom Herbert 	if (!data)
12484565e991STom Herbert 		return ret;
12494565e991STom Herbert 
12504565e991STom Herbert 	if (data[IFLA_GRE_ENCAP_TYPE]) {
12514565e991STom Herbert 		ret = true;
12524565e991STom Herbert 		ipencap->type = nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]);
12534565e991STom Herbert 	}
12544565e991STom Herbert 
12554565e991STom Herbert 	if (data[IFLA_GRE_ENCAP_FLAGS]) {
12564565e991STom Herbert 		ret = true;
12574565e991STom Herbert 		ipencap->flags = nla_get_u16(data[IFLA_GRE_ENCAP_FLAGS]);
12584565e991STom Herbert 	}
12594565e991STom Herbert 
12604565e991STom Herbert 	if (data[IFLA_GRE_ENCAP_SPORT]) {
12614565e991STom Herbert 		ret = true;
12623e97fa70SSabrina Dubroca 		ipencap->sport = nla_get_be16(data[IFLA_GRE_ENCAP_SPORT]);
12634565e991STom Herbert 	}
12644565e991STom Herbert 
12654565e991STom Herbert 	if (data[IFLA_GRE_ENCAP_DPORT]) {
12664565e991STom Herbert 		ret = true;
12673e97fa70SSabrina Dubroca 		ipencap->dport = nla_get_be16(data[IFLA_GRE_ENCAP_DPORT]);
12684565e991STom Herbert 	}
12694565e991STom Herbert 
12704565e991STom Herbert 	return ret;
12714565e991STom Herbert }
12724565e991STom Herbert 
1273c5441932SPravin B Shelar static int gre_tap_init(struct net_device *dev)
1274e1a80002SHerbert Xu {
1275c5441932SPravin B Shelar 	__gre_tunnel_init(dev);
1276bec94d43Sstephen hemminger 	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
1277d51711c0SXin Long 	netif_keep_dst(dev);
1278e1a80002SHerbert Xu 
1279c5441932SPravin B Shelar 	return ip_tunnel_init(dev);
1280e1a80002SHerbert Xu }
1281e1a80002SHerbert Xu 
1282c5441932SPravin B Shelar static const struct net_device_ops gre_tap_netdev_ops = {
1283c5441932SPravin B Shelar 	.ndo_init		= gre_tap_init,
1284c5441932SPravin B Shelar 	.ndo_uninit		= ip_tunnel_uninit,
1285c5441932SPravin B Shelar 	.ndo_start_xmit		= gre_tap_xmit,
1286b8c26a33SStephen Hemminger 	.ndo_set_mac_address 	= eth_mac_addr,
1287b8c26a33SStephen Hemminger 	.ndo_validate_addr	= eth_validate_addr,
1288c5441932SPravin B Shelar 	.ndo_change_mtu		= ip_tunnel_change_mtu,
128998d7fc46SHeiner Kallweit 	.ndo_get_stats64	= dev_get_tstats64,
12901e99584bSNicolas Dichtel 	.ndo_get_iflink		= ip_tunnel_get_iflink,
1291fc4099f1SPravin B Shelar 	.ndo_fill_metadata_dst	= gre_fill_metadata_dst,
1292b8c26a33SStephen Hemminger };
1293b8c26a33SStephen Hemminger 
129484e54fe0SWilliam Tu static int erspan_tunnel_init(struct net_device *dev)
129584e54fe0SWilliam Tu {
129684e54fe0SWilliam Tu 	struct ip_tunnel *tunnel = netdev_priv(dev);
129784e54fe0SWilliam Tu 
1298f989d546SWilliam Tu 	if (tunnel->erspan_ver == 0)
1299f989d546SWilliam Tu 		tunnel->tun_hlen = 4; /* 4-byte GRE hdr. */
1300f989d546SWilliam Tu 	else
1301f989d546SWilliam Tu 		tunnel->tun_hlen = 8; /* 8-byte GRE hdr. */
1302f989d546SWilliam Tu 
130384e54fe0SWilliam Tu 	tunnel->parms.iph.protocol = IPPROTO_GRE;
1304c122fda2SXin Long 	tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen +
1305f551c91dSWilliam Tu 		       erspan_hdr_len(tunnel->erspan_ver);
130684e54fe0SWilliam Tu 
130784e54fe0SWilliam Tu 	dev->features		|= GRE_FEATURES;
130884e54fe0SWilliam Tu 	dev->hw_features	|= GRE_FEATURES;
130984e54fe0SWilliam Tu 	dev->priv_flags		|= IFF_LIVE_ADDR_CHANGE;
1310c84bed44SXin Long 	netif_keep_dst(dev);
131184e54fe0SWilliam Tu 
131284e54fe0SWilliam Tu 	return ip_tunnel_init(dev);
131384e54fe0SWilliam Tu }
131484e54fe0SWilliam Tu 
131584e54fe0SWilliam Tu static const struct net_device_ops erspan_netdev_ops = {
131684e54fe0SWilliam Tu 	.ndo_init		= erspan_tunnel_init,
131784e54fe0SWilliam Tu 	.ndo_uninit		= ip_tunnel_uninit,
131884e54fe0SWilliam Tu 	.ndo_start_xmit		= erspan_xmit,
131984e54fe0SWilliam Tu 	.ndo_set_mac_address	= eth_mac_addr,
132084e54fe0SWilliam Tu 	.ndo_validate_addr	= eth_validate_addr,
132184e54fe0SWilliam Tu 	.ndo_change_mtu		= ip_tunnel_change_mtu,
132298d7fc46SHeiner Kallweit 	.ndo_get_stats64	= dev_get_tstats64,
132384e54fe0SWilliam Tu 	.ndo_get_iflink		= ip_tunnel_get_iflink,
132484e54fe0SWilliam Tu 	.ndo_fill_metadata_dst	= gre_fill_metadata_dst,
132584e54fe0SWilliam Tu };
132684e54fe0SWilliam Tu 
1327e1a80002SHerbert Xu static void ipgre_tap_setup(struct net_device *dev)
1328e1a80002SHerbert Xu {
1329e1a80002SHerbert Xu 	ether_setup(dev);
1330cfddd4c3SXin Long 	dev->max_mtu = 0;
1331c5441932SPravin B Shelar 	dev->netdev_ops	= &gre_tap_netdev_ops;
1332d13b161cSJiri Benc 	dev->priv_flags &= ~IFF_TX_SKB_SHARING;
1333f8c1b7ceSstephen hemminger 	dev->priv_flags	|= IFF_LIVE_ADDR_CHANGE;
1334c5441932SPravin B Shelar 	ip_tunnel_setup(dev, gre_tap_net_id);
1335e1a80002SHerbert Xu }
1336e1a80002SHerbert Xu 
1337e1f8f78fSPetr Machata static int
1338e1f8f78fSPetr Machata ipgre_newlink_encap_setup(struct net_device *dev, struct nlattr *data[])
1339c19e654dSHerbert Xu {
13404565e991STom Herbert 	struct ip_tunnel_encap ipencap;
13414565e991STom Herbert 
13424565e991STom Herbert 	if (ipgre_netlink_encap_parms(data, &ipencap)) {
13434565e991STom Herbert 		struct ip_tunnel *t = netdev_priv(dev);
1344e1f8f78fSPetr Machata 		int err = ip_tunnel_encap_setup(t, &ipencap);
13454565e991STom Herbert 
13464565e991STom Herbert 		if (err < 0)
13474565e991STom Herbert 			return err;
13484565e991STom Herbert 	}
1349c19e654dSHerbert Xu 
1350e1f8f78fSPetr Machata 	return 0;
1351e1f8f78fSPetr Machata }
1352e1f8f78fSPetr Machata 
1353e1f8f78fSPetr Machata static int ipgre_newlink(struct net *src_net, struct net_device *dev,
1354e1f8f78fSPetr Machata 			 struct nlattr *tb[], struct nlattr *data[],
1355e1f8f78fSPetr Machata 			 struct netlink_ext_ack *extack)
1356e1f8f78fSPetr Machata {
1357e1f8f78fSPetr Machata 	struct ip_tunnel_parm p;
1358e1f8f78fSPetr Machata 	__u32 fwmark = 0;
1359e1f8f78fSPetr Machata 	int err;
1360e1f8f78fSPetr Machata 
1361e1f8f78fSPetr Machata 	err = ipgre_newlink_encap_setup(dev, data);
1362e1f8f78fSPetr Machata 	if (err)
1363e1f8f78fSPetr Machata 		return err;
1364e1f8f78fSPetr Machata 
13659830ad4cSCraig Gallek 	err = ipgre_netlink_parms(dev, data, tb, &p, &fwmark);
136622a59be8SPhilip Prindeville 	if (err < 0)
136722a59be8SPhilip Prindeville 		return err;
13689830ad4cSCraig Gallek 	return ip_tunnel_newlink(dev, tb, &p, fwmark);
1369c19e654dSHerbert Xu }
1370c19e654dSHerbert Xu 
1371e1f8f78fSPetr Machata static int erspan_newlink(struct net *src_net, struct net_device *dev,
1372e1f8f78fSPetr Machata 			  struct nlattr *tb[], struct nlattr *data[],
1373e1f8f78fSPetr Machata 			  struct netlink_ext_ack *extack)
1374e1f8f78fSPetr Machata {
1375e1f8f78fSPetr Machata 	struct ip_tunnel_parm p;
1376e1f8f78fSPetr Machata 	__u32 fwmark = 0;
1377e1f8f78fSPetr Machata 	int err;
1378e1f8f78fSPetr Machata 
1379e1f8f78fSPetr Machata 	err = ipgre_newlink_encap_setup(dev, data);
1380e1f8f78fSPetr Machata 	if (err)
1381e1f8f78fSPetr Machata 		return err;
1382e1f8f78fSPetr Machata 
1383e1f8f78fSPetr Machata 	err = erspan_netlink_parms(dev, data, tb, &p, &fwmark);
1384e1f8f78fSPetr Machata 	if (err)
1385e1f8f78fSPetr Machata 		return err;
1386e1f8f78fSPetr Machata 	return ip_tunnel_newlink(dev, tb, &p, fwmark);
1387e1f8f78fSPetr Machata }
1388e1f8f78fSPetr Machata 
1389c19e654dSHerbert Xu static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[],
1390ad744b22SMatthias Schiffer 			    struct nlattr *data[],
1391ad744b22SMatthias Schiffer 			    struct netlink_ext_ack *extack)
1392c19e654dSHerbert Xu {
13939830ad4cSCraig Gallek 	struct ip_tunnel *t = netdev_priv(dev);
13949830ad4cSCraig Gallek 	__u32 fwmark = t->fwmark;
1395dd9d598cSXin Long 	struct ip_tunnel_parm p;
139622a59be8SPhilip Prindeville 	int err;
13974565e991STom Herbert 
1398e1f8f78fSPetr Machata 	err = ipgre_newlink_encap_setup(dev, data);
1399e1f8f78fSPetr Machata 	if (err)
14004565e991STom Herbert 		return err;
1401c19e654dSHerbert Xu 
14029830ad4cSCraig Gallek 	err = ipgre_netlink_parms(dev, data, tb, &p, &fwmark);
140322a59be8SPhilip Prindeville 	if (err < 0)
140422a59be8SPhilip Prindeville 		return err;
1405dd9d598cSXin Long 
1406dd9d598cSXin Long 	err = ip_tunnel_changelink(dev, tb, &p, fwmark);
1407dd9d598cSXin Long 	if (err < 0)
1408dd9d598cSXin Long 		return err;
1409dd9d598cSXin Long 
1410dd9d598cSXin Long 	t->parms.i_flags = p.i_flags;
1411dd9d598cSXin Long 	t->parms.o_flags = p.o_flags;
1412dd9d598cSXin Long 
1413dd9d598cSXin Long 	ipgre_link_update(dev, !tb[IFLA_MTU]);
1414dd9d598cSXin Long 
1415dd9d598cSXin Long 	return 0;
1416c19e654dSHerbert Xu }
1417c19e654dSHerbert Xu 
1418e1f8f78fSPetr Machata static int erspan_changelink(struct net_device *dev, struct nlattr *tb[],
1419e1f8f78fSPetr Machata 			     struct nlattr *data[],
1420e1f8f78fSPetr Machata 			     struct netlink_ext_ack *extack)
1421e1f8f78fSPetr Machata {
1422e1f8f78fSPetr Machata 	struct ip_tunnel *t = netdev_priv(dev);
1423e1f8f78fSPetr Machata 	__u32 fwmark = t->fwmark;
1424e1f8f78fSPetr Machata 	struct ip_tunnel_parm p;
1425e1f8f78fSPetr Machata 	int err;
1426e1f8f78fSPetr Machata 
1427e1f8f78fSPetr Machata 	err = ipgre_newlink_encap_setup(dev, data);
1428e1f8f78fSPetr Machata 	if (err)
1429e1f8f78fSPetr Machata 		return err;
1430e1f8f78fSPetr Machata 
1431e1f8f78fSPetr Machata 	err = erspan_netlink_parms(dev, data, tb, &p, &fwmark);
1432e1f8f78fSPetr Machata 	if (err < 0)
1433e1f8f78fSPetr Machata 		return err;
1434e1f8f78fSPetr Machata 
1435e1f8f78fSPetr Machata 	err = ip_tunnel_changelink(dev, tb, &p, fwmark);
1436e1f8f78fSPetr Machata 	if (err < 0)
1437e1f8f78fSPetr Machata 		return err;
1438e1f8f78fSPetr Machata 
1439e1f8f78fSPetr Machata 	t->parms.i_flags = p.i_flags;
1440e1f8f78fSPetr Machata 	t->parms.o_flags = p.o_flags;
1441e1f8f78fSPetr Machata 
1442e1f8f78fSPetr Machata 	return 0;
1443e1f8f78fSPetr Machata }
1444e1f8f78fSPetr Machata 
1445c19e654dSHerbert Xu static size_t ipgre_get_size(const struct net_device *dev)
1446c19e654dSHerbert Xu {
1447c19e654dSHerbert Xu 	return
1448c19e654dSHerbert Xu 		/* IFLA_GRE_LINK */
1449c19e654dSHerbert Xu 		nla_total_size(4) +
1450c19e654dSHerbert Xu 		/* IFLA_GRE_IFLAGS */
1451c19e654dSHerbert Xu 		nla_total_size(2) +
1452c19e654dSHerbert Xu 		/* IFLA_GRE_OFLAGS */
1453c19e654dSHerbert Xu 		nla_total_size(2) +
1454c19e654dSHerbert Xu 		/* IFLA_GRE_IKEY */
1455c19e654dSHerbert Xu 		nla_total_size(4) +
1456c19e654dSHerbert Xu 		/* IFLA_GRE_OKEY */
1457c19e654dSHerbert Xu 		nla_total_size(4) +
1458c19e654dSHerbert Xu 		/* IFLA_GRE_LOCAL */
1459c19e654dSHerbert Xu 		nla_total_size(4) +
1460c19e654dSHerbert Xu 		/* IFLA_GRE_REMOTE */
1461c19e654dSHerbert Xu 		nla_total_size(4) +
1462c19e654dSHerbert Xu 		/* IFLA_GRE_TTL */
1463c19e654dSHerbert Xu 		nla_total_size(1) +
1464c19e654dSHerbert Xu 		/* IFLA_GRE_TOS */
1465c19e654dSHerbert Xu 		nla_total_size(1) +
1466c19e654dSHerbert Xu 		/* IFLA_GRE_PMTUDISC */
1467c19e654dSHerbert Xu 		nla_total_size(1) +
14684565e991STom Herbert 		/* IFLA_GRE_ENCAP_TYPE */
14694565e991STom Herbert 		nla_total_size(2) +
14704565e991STom Herbert 		/* IFLA_GRE_ENCAP_FLAGS */
14714565e991STom Herbert 		nla_total_size(2) +
14724565e991STom Herbert 		/* IFLA_GRE_ENCAP_SPORT */
14734565e991STom Herbert 		nla_total_size(2) +
14744565e991STom Herbert 		/* IFLA_GRE_ENCAP_DPORT */
14754565e991STom Herbert 		nla_total_size(2) +
14762e15ea39SPravin B Shelar 		/* IFLA_GRE_COLLECT_METADATA */
14772e15ea39SPravin B Shelar 		nla_total_size(0) +
147822a59be8SPhilip Prindeville 		/* IFLA_GRE_IGNORE_DF */
147922a59be8SPhilip Prindeville 		nla_total_size(1) +
14809830ad4cSCraig Gallek 		/* IFLA_GRE_FWMARK */
14819830ad4cSCraig Gallek 		nla_total_size(4) +
148284e54fe0SWilliam Tu 		/* IFLA_GRE_ERSPAN_INDEX */
148384e54fe0SWilliam Tu 		nla_total_size(4) +
1484f551c91dSWilliam Tu 		/* IFLA_GRE_ERSPAN_VER */
1485f551c91dSWilliam Tu 		nla_total_size(1) +
1486f551c91dSWilliam Tu 		/* IFLA_GRE_ERSPAN_DIR */
1487f551c91dSWilliam Tu 		nla_total_size(1) +
1488f551c91dSWilliam Tu 		/* IFLA_GRE_ERSPAN_HWID */
1489f551c91dSWilliam Tu 		nla_total_size(2) +
1490c19e654dSHerbert Xu 		0;
1491c19e654dSHerbert Xu }
1492c19e654dSHerbert Xu 
1493c19e654dSHerbert Xu static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev)
1494c19e654dSHerbert Xu {
1495c19e654dSHerbert Xu 	struct ip_tunnel *t = netdev_priv(dev);
1496c19e654dSHerbert Xu 	struct ip_tunnel_parm *p = &t->parms;
1497feaf5c79SLorenzo Bianconi 	__be16 o_flags = p->o_flags;
1498feaf5c79SLorenzo Bianconi 
1499f989d546SWilliam Tu 	if (t->erspan_ver <= 2) {
1500f989d546SWilliam Tu 		if (t->erspan_ver != 0 && !t->collect_md)
1501feaf5c79SLorenzo Bianconi 			o_flags |= TUNNEL_KEY;
1502c19e654dSHerbert Xu 
15032bdf700eSLorenzo Bianconi 		if (nla_put_u8(skb, IFLA_GRE_ERSPAN_VER, t->erspan_ver))
15042bdf700eSLorenzo Bianconi 			goto nla_put_failure;
15052bdf700eSLorenzo Bianconi 
15062bdf700eSLorenzo Bianconi 		if (t->erspan_ver == 1) {
15072bdf700eSLorenzo Bianconi 			if (nla_put_u32(skb, IFLA_GRE_ERSPAN_INDEX, t->index))
15082bdf700eSLorenzo Bianconi 				goto nla_put_failure;
1509f989d546SWilliam Tu 		} else if (t->erspan_ver == 2) {
15102bdf700eSLorenzo Bianconi 			if (nla_put_u8(skb, IFLA_GRE_ERSPAN_DIR, t->dir))
15112bdf700eSLorenzo Bianconi 				goto nla_put_failure;
15122bdf700eSLorenzo Bianconi 			if (nla_put_u16(skb, IFLA_GRE_ERSPAN_HWID, t->hwid))
15132bdf700eSLorenzo Bianconi 				goto nla_put_failure;
15142bdf700eSLorenzo Bianconi 		}
15152bdf700eSLorenzo Bianconi 	}
15162bdf700eSLorenzo Bianconi 
1517f3756b79SDavid S. Miller 	if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) ||
151895f5c64cSTom Herbert 	    nla_put_be16(skb, IFLA_GRE_IFLAGS,
151995f5c64cSTom Herbert 			 gre_tnl_flags_to_gre_flags(p->i_flags)) ||
152095f5c64cSTom Herbert 	    nla_put_be16(skb, IFLA_GRE_OFLAGS,
1521feaf5c79SLorenzo Bianconi 			 gre_tnl_flags_to_gre_flags(o_flags)) ||
1522f3756b79SDavid S. Miller 	    nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) ||
1523f3756b79SDavid S. Miller 	    nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) ||
1524930345eaSJiri Benc 	    nla_put_in_addr(skb, IFLA_GRE_LOCAL, p->iph.saddr) ||
1525930345eaSJiri Benc 	    nla_put_in_addr(skb, IFLA_GRE_REMOTE, p->iph.daddr) ||
1526f3756b79SDavid S. Miller 	    nla_put_u8(skb, IFLA_GRE_TTL, p->iph.ttl) ||
1527f3756b79SDavid S. Miller 	    nla_put_u8(skb, IFLA_GRE_TOS, p->iph.tos) ||
1528f3756b79SDavid S. Miller 	    nla_put_u8(skb, IFLA_GRE_PMTUDISC,
15299830ad4cSCraig Gallek 		       !!(p->iph.frag_off & htons(IP_DF))) ||
15309830ad4cSCraig Gallek 	    nla_put_u32(skb, IFLA_GRE_FWMARK, t->fwmark))
1531f3756b79SDavid S. Miller 		goto nla_put_failure;
15324565e991STom Herbert 
15334565e991STom Herbert 	if (nla_put_u16(skb, IFLA_GRE_ENCAP_TYPE,
15344565e991STom Herbert 			t->encap.type) ||
15353e97fa70SSabrina Dubroca 	    nla_put_be16(skb, IFLA_GRE_ENCAP_SPORT,
15364565e991STom Herbert 			 t->encap.sport) ||
15373e97fa70SSabrina Dubroca 	    nla_put_be16(skb, IFLA_GRE_ENCAP_DPORT,
15384565e991STom Herbert 			 t->encap.dport) ||
15394565e991STom Herbert 	    nla_put_u16(skb, IFLA_GRE_ENCAP_FLAGS,
1540e1b2cb65STom Herbert 			t->encap.flags))
15414565e991STom Herbert 		goto nla_put_failure;
15424565e991STom Herbert 
154322a59be8SPhilip Prindeville 	if (nla_put_u8(skb, IFLA_GRE_IGNORE_DF, t->ignore_df))
154422a59be8SPhilip Prindeville 		goto nla_put_failure;
154522a59be8SPhilip Prindeville 
15462e15ea39SPravin B Shelar 	if (t->collect_md) {
15472e15ea39SPravin B Shelar 		if (nla_put_flag(skb, IFLA_GRE_COLLECT_METADATA))
15482e15ea39SPravin B Shelar 			goto nla_put_failure;
15492e15ea39SPravin B Shelar 	}
15502e15ea39SPravin B Shelar 
1551c19e654dSHerbert Xu 	return 0;
1552c19e654dSHerbert Xu 
1553c19e654dSHerbert Xu nla_put_failure:
1554c19e654dSHerbert Xu 	return -EMSGSIZE;
1555c19e654dSHerbert Xu }
1556c19e654dSHerbert Xu 
155784e54fe0SWilliam Tu static void erspan_setup(struct net_device *dev)
155884e54fe0SWilliam Tu {
155984581bdaSXin Long 	struct ip_tunnel *t = netdev_priv(dev);
156084581bdaSXin Long 
156184e54fe0SWilliam Tu 	ether_setup(dev);
15620e141f75SHaishuang Yan 	dev->max_mtu = 0;
156384e54fe0SWilliam Tu 	dev->netdev_ops = &erspan_netdev_ops;
156484e54fe0SWilliam Tu 	dev->priv_flags &= ~IFF_TX_SKB_SHARING;
156584e54fe0SWilliam Tu 	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
156684e54fe0SWilliam Tu 	ip_tunnel_setup(dev, erspan_net_id);
156784581bdaSXin Long 	t->erspan_ver = 1;
156884e54fe0SWilliam Tu }
156984e54fe0SWilliam Tu 
1570c19e654dSHerbert Xu static const struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = {
1571c19e654dSHerbert Xu 	[IFLA_GRE_LINK]		= { .type = NLA_U32 },
1572c19e654dSHerbert Xu 	[IFLA_GRE_IFLAGS]	= { .type = NLA_U16 },
1573c19e654dSHerbert Xu 	[IFLA_GRE_OFLAGS]	= { .type = NLA_U16 },
1574c19e654dSHerbert Xu 	[IFLA_GRE_IKEY]		= { .type = NLA_U32 },
1575c19e654dSHerbert Xu 	[IFLA_GRE_OKEY]		= { .type = NLA_U32 },
1576c593642cSPankaj Bharadiya 	[IFLA_GRE_LOCAL]	= { .len = sizeof_field(struct iphdr, saddr) },
1577c593642cSPankaj Bharadiya 	[IFLA_GRE_REMOTE]	= { .len = sizeof_field(struct iphdr, daddr) },
1578c19e654dSHerbert Xu 	[IFLA_GRE_TTL]		= { .type = NLA_U8 },
1579c19e654dSHerbert Xu 	[IFLA_GRE_TOS]		= { .type = NLA_U8 },
1580c19e654dSHerbert Xu 	[IFLA_GRE_PMTUDISC]	= { .type = NLA_U8 },
15814565e991STom Herbert 	[IFLA_GRE_ENCAP_TYPE]	= { .type = NLA_U16 },
15824565e991STom Herbert 	[IFLA_GRE_ENCAP_FLAGS]	= { .type = NLA_U16 },
15834565e991STom Herbert 	[IFLA_GRE_ENCAP_SPORT]	= { .type = NLA_U16 },
15844565e991STom Herbert 	[IFLA_GRE_ENCAP_DPORT]	= { .type = NLA_U16 },
15852e15ea39SPravin B Shelar 	[IFLA_GRE_COLLECT_METADATA]	= { .type = NLA_FLAG },
158622a59be8SPhilip Prindeville 	[IFLA_GRE_IGNORE_DF]	= { .type = NLA_U8 },
15879830ad4cSCraig Gallek 	[IFLA_GRE_FWMARK]	= { .type = NLA_U32 },
158884e54fe0SWilliam Tu 	[IFLA_GRE_ERSPAN_INDEX]	= { .type = NLA_U32 },
1589f551c91dSWilliam Tu 	[IFLA_GRE_ERSPAN_VER]	= { .type = NLA_U8 },
1590f551c91dSWilliam Tu 	[IFLA_GRE_ERSPAN_DIR]	= { .type = NLA_U8 },
1591f551c91dSWilliam Tu 	[IFLA_GRE_ERSPAN_HWID]	= { .type = NLA_U16 },
1592c19e654dSHerbert Xu };
1593c19e654dSHerbert Xu 
1594c19e654dSHerbert Xu static struct rtnl_link_ops ipgre_link_ops __read_mostly = {
1595c19e654dSHerbert Xu 	.kind		= "gre",
1596c19e654dSHerbert Xu 	.maxtype	= IFLA_GRE_MAX,
1597c19e654dSHerbert Xu 	.policy		= ipgre_policy,
1598c19e654dSHerbert Xu 	.priv_size	= sizeof(struct ip_tunnel),
1599c19e654dSHerbert Xu 	.setup		= ipgre_tunnel_setup,
1600c19e654dSHerbert Xu 	.validate	= ipgre_tunnel_validate,
1601c19e654dSHerbert Xu 	.newlink	= ipgre_newlink,
1602c19e654dSHerbert Xu 	.changelink	= ipgre_changelink,
1603c5441932SPravin B Shelar 	.dellink	= ip_tunnel_dellink,
1604c19e654dSHerbert Xu 	.get_size	= ipgre_get_size,
1605c19e654dSHerbert Xu 	.fill_info	= ipgre_fill_info,
16061728d4faSNicolas Dichtel 	.get_link_net	= ip_tunnel_get_link_net,
1607c19e654dSHerbert Xu };
1608c19e654dSHerbert Xu 
1609e1a80002SHerbert Xu static struct rtnl_link_ops ipgre_tap_ops __read_mostly = {
1610e1a80002SHerbert Xu 	.kind		= "gretap",
1611e1a80002SHerbert Xu 	.maxtype	= IFLA_GRE_MAX,
1612e1a80002SHerbert Xu 	.policy		= ipgre_policy,
1613e1a80002SHerbert Xu 	.priv_size	= sizeof(struct ip_tunnel),
1614e1a80002SHerbert Xu 	.setup		= ipgre_tap_setup,
1615e1a80002SHerbert Xu 	.validate	= ipgre_tap_validate,
1616e1a80002SHerbert Xu 	.newlink	= ipgre_newlink,
1617e1a80002SHerbert Xu 	.changelink	= ipgre_changelink,
1618c5441932SPravin B Shelar 	.dellink	= ip_tunnel_dellink,
1619e1a80002SHerbert Xu 	.get_size	= ipgre_get_size,
1620e1a80002SHerbert Xu 	.fill_info	= ipgre_fill_info,
16211728d4faSNicolas Dichtel 	.get_link_net	= ip_tunnel_get_link_net,
1622e1a80002SHerbert Xu };
1623e1a80002SHerbert Xu 
162484e54fe0SWilliam Tu static struct rtnl_link_ops erspan_link_ops __read_mostly = {
162584e54fe0SWilliam Tu 	.kind		= "erspan",
162684e54fe0SWilliam Tu 	.maxtype	= IFLA_GRE_MAX,
162784e54fe0SWilliam Tu 	.policy		= ipgre_policy,
162884e54fe0SWilliam Tu 	.priv_size	= sizeof(struct ip_tunnel),
162984e54fe0SWilliam Tu 	.setup		= erspan_setup,
163084e54fe0SWilliam Tu 	.validate	= erspan_validate,
1631e1f8f78fSPetr Machata 	.newlink	= erspan_newlink,
1632e1f8f78fSPetr Machata 	.changelink	= erspan_changelink,
163384e54fe0SWilliam Tu 	.dellink	= ip_tunnel_dellink,
163484e54fe0SWilliam Tu 	.get_size	= ipgre_get_size,
163584e54fe0SWilliam Tu 	.fill_info	= ipgre_fill_info,
163684e54fe0SWilliam Tu 	.get_link_net	= ip_tunnel_get_link_net,
163784e54fe0SWilliam Tu };
163884e54fe0SWilliam Tu 
1639b2acd1dcSPravin B Shelar struct net_device *gretap_fb_dev_create(struct net *net, const char *name,
1640b2acd1dcSPravin B Shelar 					u8 name_assign_type)
1641b2acd1dcSPravin B Shelar {
1642b2acd1dcSPravin B Shelar 	struct nlattr *tb[IFLA_MAX + 1];
1643b2acd1dcSPravin B Shelar 	struct net_device *dev;
1644106da663SNicolas Dichtel 	LIST_HEAD(list_kill);
1645b2acd1dcSPravin B Shelar 	struct ip_tunnel *t;
1646b2acd1dcSPravin B Shelar 	int err;
1647b2acd1dcSPravin B Shelar 
1648b2acd1dcSPravin B Shelar 	memset(&tb, 0, sizeof(tb));
1649b2acd1dcSPravin B Shelar 
1650b2acd1dcSPravin B Shelar 	dev = rtnl_create_link(net, name, name_assign_type,
1651d0522f1cSDavid Ahern 			       &ipgre_tap_ops, tb, NULL);
1652b2acd1dcSPravin B Shelar 	if (IS_ERR(dev))
1653b2acd1dcSPravin B Shelar 		return dev;
1654b2acd1dcSPravin B Shelar 
1655b2acd1dcSPravin B Shelar 	/* Configure flow based GRE device. */
1656b2acd1dcSPravin B Shelar 	t = netdev_priv(dev);
1657b2acd1dcSPravin B Shelar 	t->collect_md = true;
1658b2acd1dcSPravin B Shelar 
16597a3f4a18SMatthias Schiffer 	err = ipgre_newlink(net, dev, tb, NULL, NULL);
1660106da663SNicolas Dichtel 	if (err < 0) {
1661106da663SNicolas Dichtel 		free_netdev(dev);
1662106da663SNicolas Dichtel 		return ERR_PTR(err);
1663106da663SNicolas Dichtel 	}
16647e059158SDavid Wragg 
16657e059158SDavid Wragg 	/* openvswitch users expect packet sizes to be unrestricted,
16667e059158SDavid Wragg 	 * so set the largest MTU we can.
16677e059158SDavid Wragg 	 */
16687e059158SDavid Wragg 	err = __ip_tunnel_change_mtu(dev, IP_MAX_MTU, false);
16697e059158SDavid Wragg 	if (err)
16707e059158SDavid Wragg 		goto out;
16717e059158SDavid Wragg 
1672da6f1da8SNicolas Dichtel 	err = rtnl_configure_link(dev, NULL);
1673da6f1da8SNicolas Dichtel 	if (err < 0)
1674da6f1da8SNicolas Dichtel 		goto out;
1675da6f1da8SNicolas Dichtel 
1676b2acd1dcSPravin B Shelar 	return dev;
1677b2acd1dcSPravin B Shelar out:
1678106da663SNicolas Dichtel 	ip_tunnel_dellink(dev, &list_kill);
1679106da663SNicolas Dichtel 	unregister_netdevice_many(&list_kill);
1680b2acd1dcSPravin B Shelar 	return ERR_PTR(err);
1681b2acd1dcSPravin B Shelar }
1682b2acd1dcSPravin B Shelar EXPORT_SYMBOL_GPL(gretap_fb_dev_create);
1683b2acd1dcSPravin B Shelar 
1684c5441932SPravin B Shelar static int __net_init ipgre_tap_init_net(struct net *net)
1685c5441932SPravin B Shelar {
16862e15ea39SPravin B Shelar 	return ip_tunnel_init_net(net, gre_tap_net_id, &ipgre_tap_ops, "gretap0");
1687c5441932SPravin B Shelar }
1688c5441932SPravin B Shelar 
168964bc1781SEric Dumazet static void __net_exit ipgre_tap_exit_batch_net(struct list_head *list_net)
1690c5441932SPravin B Shelar {
169164bc1781SEric Dumazet 	ip_tunnel_delete_nets(list_net, gre_tap_net_id, &ipgre_tap_ops);
1692c5441932SPravin B Shelar }
1693c5441932SPravin B Shelar 
1694c5441932SPravin B Shelar static struct pernet_operations ipgre_tap_net_ops = {
1695c5441932SPravin B Shelar 	.init = ipgre_tap_init_net,
169664bc1781SEric Dumazet 	.exit_batch = ipgre_tap_exit_batch_net,
1697c5441932SPravin B Shelar 	.id   = &gre_tap_net_id,
1698c5441932SPravin B Shelar 	.size = sizeof(struct ip_tunnel_net),
1699c5441932SPravin B Shelar };
17001da177e4SLinus Torvalds 
170184e54fe0SWilliam Tu static int __net_init erspan_init_net(struct net *net)
170284e54fe0SWilliam Tu {
170384e54fe0SWilliam Tu 	return ip_tunnel_init_net(net, erspan_net_id,
170484e54fe0SWilliam Tu 				  &erspan_link_ops, "erspan0");
170584e54fe0SWilliam Tu }
170684e54fe0SWilliam Tu 
170764bc1781SEric Dumazet static void __net_exit erspan_exit_batch_net(struct list_head *net_list)
170884e54fe0SWilliam Tu {
170964bc1781SEric Dumazet 	ip_tunnel_delete_nets(net_list, erspan_net_id, &erspan_link_ops);
171084e54fe0SWilliam Tu }
171184e54fe0SWilliam Tu 
171284e54fe0SWilliam Tu static struct pernet_operations erspan_net_ops = {
171384e54fe0SWilliam Tu 	.init = erspan_init_net,
171464bc1781SEric Dumazet 	.exit_batch = erspan_exit_batch_net,
171584e54fe0SWilliam Tu 	.id   = &erspan_net_id,
171684e54fe0SWilliam Tu 	.size = sizeof(struct ip_tunnel_net),
171784e54fe0SWilliam Tu };
171884e54fe0SWilliam Tu 
17191da177e4SLinus Torvalds static int __init ipgre_init(void)
17201da177e4SLinus Torvalds {
17211da177e4SLinus Torvalds 	int err;
17221da177e4SLinus Torvalds 
1723058bd4d2SJoe Perches 	pr_info("GRE over IPv4 tunneling driver\n");
17241da177e4SLinus Torvalds 
1725cfb8fbf2SEric W. Biederman 	err = register_pernet_device(&ipgre_net_ops);
172659a4c759SPavel Emelyanov 	if (err < 0)
1727c2892f02SAlexey Dobriyan 		return err;
1728c2892f02SAlexey Dobriyan 
1729c5441932SPravin B Shelar 	err = register_pernet_device(&ipgre_tap_net_ops);
1730c5441932SPravin B Shelar 	if (err < 0)
1731e3d0328cSWilliam Tu 		goto pnet_tap_failed;
1732c5441932SPravin B Shelar 
173384e54fe0SWilliam Tu 	err = register_pernet_device(&erspan_net_ops);
173484e54fe0SWilliam Tu 	if (err < 0)
173584e54fe0SWilliam Tu 		goto pnet_erspan_failed;
173684e54fe0SWilliam Tu 
17379f57c67cSPravin B Shelar 	err = gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO);
1738c2892f02SAlexey Dobriyan 	if (err < 0) {
1739058bd4d2SJoe Perches 		pr_info("%s: can't add protocol\n", __func__);
1740c2892f02SAlexey Dobriyan 		goto add_proto_failed;
1741c2892f02SAlexey Dobriyan 	}
17427daa0004SPavel Emelyanov 
1743c19e654dSHerbert Xu 	err = rtnl_link_register(&ipgre_link_ops);
1744c19e654dSHerbert Xu 	if (err < 0)
1745c19e654dSHerbert Xu 		goto rtnl_link_failed;
1746c19e654dSHerbert Xu 
1747e1a80002SHerbert Xu 	err = rtnl_link_register(&ipgre_tap_ops);
1748e1a80002SHerbert Xu 	if (err < 0)
1749e1a80002SHerbert Xu 		goto tap_ops_failed;
1750e1a80002SHerbert Xu 
175184e54fe0SWilliam Tu 	err = rtnl_link_register(&erspan_link_ops);
175284e54fe0SWilliam Tu 	if (err < 0)
175384e54fe0SWilliam Tu 		goto erspan_link_failed;
175484e54fe0SWilliam Tu 
1755c5441932SPravin B Shelar 	return 0;
1756c19e654dSHerbert Xu 
175784e54fe0SWilliam Tu erspan_link_failed:
175884e54fe0SWilliam Tu 	rtnl_link_unregister(&ipgre_tap_ops);
1759e1a80002SHerbert Xu tap_ops_failed:
1760e1a80002SHerbert Xu 	rtnl_link_unregister(&ipgre_link_ops);
1761c19e654dSHerbert Xu rtnl_link_failed:
17629f57c67cSPravin B Shelar 	gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
1763c2892f02SAlexey Dobriyan add_proto_failed:
176484e54fe0SWilliam Tu 	unregister_pernet_device(&erspan_net_ops);
176584e54fe0SWilliam Tu pnet_erspan_failed:
1766c5441932SPravin B Shelar 	unregister_pernet_device(&ipgre_tap_net_ops);
1767e3d0328cSWilliam Tu pnet_tap_failed:
1768c2892f02SAlexey Dobriyan 	unregister_pernet_device(&ipgre_net_ops);
1769c5441932SPravin B Shelar 	return err;
17701da177e4SLinus Torvalds }
17711da177e4SLinus Torvalds 
1772db44575fSAlexey Kuznetsov static void __exit ipgre_fini(void)
17731da177e4SLinus Torvalds {
1774e1a80002SHerbert Xu 	rtnl_link_unregister(&ipgre_tap_ops);
1775c19e654dSHerbert Xu 	rtnl_link_unregister(&ipgre_link_ops);
177684e54fe0SWilliam Tu 	rtnl_link_unregister(&erspan_link_ops);
17779f57c67cSPravin B Shelar 	gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
1778c5441932SPravin B Shelar 	unregister_pernet_device(&ipgre_tap_net_ops);
1779c2892f02SAlexey Dobriyan 	unregister_pernet_device(&ipgre_net_ops);
178084e54fe0SWilliam Tu 	unregister_pernet_device(&erspan_net_ops);
17811da177e4SLinus Torvalds }
17821da177e4SLinus Torvalds 
17831da177e4SLinus Torvalds module_init(ipgre_init);
17841da177e4SLinus Torvalds module_exit(ipgre_fini);
17851da177e4SLinus Torvalds MODULE_LICENSE("GPL");
17864d74f8baSPatrick McHardy MODULE_ALIAS_RTNL_LINK("gre");
17874d74f8baSPatrick McHardy MODULE_ALIAS_RTNL_LINK("gretap");
178884e54fe0SWilliam Tu MODULE_ALIAS_RTNL_LINK("erspan");
17898909c9adSVasiliy Kulikov MODULE_ALIAS_NETDEV("gre0");
1790c5441932SPravin B Shelar MODULE_ALIAS_NETDEV("gretap0");
179184e54fe0SWilliam Tu MODULE_ALIAS_NETDEV("erspan0");
1792