xref: /linux/net/ipv4/ip_gre.c (revision 02f99df1875c11330cd0be69a40fa8ccd14749b2)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  *	Linux NET3:	GRE over IP protocol decoder.
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  *	Authors: Alexey Kuznetsov (kuznet@ms2.inr.ac.ru)
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  *	This program is free software; you can redistribute it and/or
71da177e4SLinus Torvalds  *	modify it under the terms of the GNU General Public License
81da177e4SLinus Torvalds  *	as published by the Free Software Foundation; either version
91da177e4SLinus Torvalds  *	2 of the License, or (at your option) any later version.
101da177e4SLinus Torvalds  *
111da177e4SLinus Torvalds  */
121da177e4SLinus Torvalds 
13afd46503SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
14afd46503SJoe Perches 
154fc268d2SRandy Dunlap #include <linux/capability.h>
161da177e4SLinus Torvalds #include <linux/module.h>
171da177e4SLinus Torvalds #include <linux/types.h>
181da177e4SLinus Torvalds #include <linux/kernel.h>
195a0e3ad6STejun Heo #include <linux/slab.h>
207c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
211da177e4SLinus Torvalds #include <linux/skbuff.h>
221da177e4SLinus Torvalds #include <linux/netdevice.h>
231da177e4SLinus Torvalds #include <linux/in.h>
241da177e4SLinus Torvalds #include <linux/tcp.h>
251da177e4SLinus Torvalds #include <linux/udp.h>
261da177e4SLinus Torvalds #include <linux/if_arp.h>
272e15ea39SPravin B Shelar #include <linux/if_vlan.h>
281da177e4SLinus Torvalds #include <linux/init.h>
291da177e4SLinus Torvalds #include <linux/in6.h>
301da177e4SLinus Torvalds #include <linux/inetdevice.h>
311da177e4SLinus Torvalds #include <linux/igmp.h>
321da177e4SLinus Torvalds #include <linux/netfilter_ipv4.h>
33e1a80002SHerbert Xu #include <linux/etherdevice.h>
3446f25dffSKris Katterjohn #include <linux/if_ether.h>
351da177e4SLinus Torvalds 
361da177e4SLinus Torvalds #include <net/sock.h>
371da177e4SLinus Torvalds #include <net/ip.h>
381da177e4SLinus Torvalds #include <net/icmp.h>
391da177e4SLinus Torvalds #include <net/protocol.h>
40c5441932SPravin B Shelar #include <net/ip_tunnels.h>
411da177e4SLinus Torvalds #include <net/arp.h>
421da177e4SLinus Torvalds #include <net/checksum.h>
431da177e4SLinus Torvalds #include <net/dsfield.h>
441da177e4SLinus Torvalds #include <net/inet_ecn.h>
451da177e4SLinus Torvalds #include <net/xfrm.h>
4659a4c759SPavel Emelyanov #include <net/net_namespace.h>
4759a4c759SPavel Emelyanov #include <net/netns/generic.h>
48c19e654dSHerbert Xu #include <net/rtnetlink.h>
4900959adeSDmitry Kozlov #include <net/gre.h>
502e15ea39SPravin B Shelar #include <net/dst_metadata.h>
5184e54fe0SWilliam Tu #include <net/erspan.h>
521da177e4SLinus Torvalds 
531da177e4SLinus Torvalds /*
541da177e4SLinus Torvalds    Problems & solutions
551da177e4SLinus Torvalds    --------------------
561da177e4SLinus Torvalds 
571da177e4SLinus Torvalds    1. The most important issue is detecting local dead loops.
581da177e4SLinus Torvalds    They would cause complete host lockup in transmit, which
591da177e4SLinus Torvalds    would be "resolved" by stack overflow or, if queueing is enabled,
601da177e4SLinus Torvalds    with infinite looping in net_bh.
611da177e4SLinus Torvalds 
621da177e4SLinus Torvalds    We cannot track such dead loops during route installation,
631da177e4SLinus Torvalds    it is infeasible task. The most general solutions would be
641da177e4SLinus Torvalds    to keep skb->encapsulation counter (sort of local ttl),
656d0722a2SEric Dumazet    and silently drop packet when it expires. It is a good
66bff52857Sstephen hemminger    solution, but it supposes maintaining new variable in ALL
671da177e4SLinus Torvalds    skb, even if no tunneling is used.
681da177e4SLinus Torvalds 
696d0722a2SEric Dumazet    Current solution: xmit_recursion breaks dead loops. This is a percpu
706d0722a2SEric Dumazet    counter, since when we enter the first ndo_xmit(), cpu migration is
716d0722a2SEric Dumazet    forbidden. We force an exit if this counter reaches RECURSION_LIMIT
721da177e4SLinus Torvalds 
731da177e4SLinus Torvalds    2. Networking dead loops would not kill routers, but would really
741da177e4SLinus Torvalds    kill network. IP hop limit plays role of "t->recursion" in this case,
751da177e4SLinus Torvalds    if we copy it from packet being encapsulated to upper header.
761da177e4SLinus Torvalds    It is very good solution, but it introduces two problems:
771da177e4SLinus Torvalds 
781da177e4SLinus Torvalds    - Routing protocols, using packets with ttl=1 (OSPF, RIP2),
791da177e4SLinus Torvalds      do not work over tunnels.
801da177e4SLinus Torvalds    - traceroute does not work. I planned to relay ICMP from tunnel,
811da177e4SLinus Torvalds      so that this problem would be solved and traceroute output
821da177e4SLinus Torvalds      would even more informative. This idea appeared to be wrong:
831da177e4SLinus Torvalds      only Linux complies to rfc1812 now (yes, guys, Linux is the only
841da177e4SLinus Torvalds      true router now :-)), all routers (at least, in neighbourhood of mine)
851da177e4SLinus Torvalds      return only 8 bytes of payload. It is the end.
861da177e4SLinus Torvalds 
871da177e4SLinus Torvalds    Hence, if we want that OSPF worked or traceroute said something reasonable,
881da177e4SLinus Torvalds    we should search for another solution.
891da177e4SLinus Torvalds 
901da177e4SLinus Torvalds    One of them is to parse packet trying to detect inner encapsulation
911da177e4SLinus Torvalds    made by our node. It is difficult or even impossible, especially,
92bff52857Sstephen hemminger    taking into account fragmentation. TO be short, ttl is not solution at all.
931da177e4SLinus Torvalds 
941da177e4SLinus Torvalds    Current solution: The solution was UNEXPECTEDLY SIMPLE.
951da177e4SLinus Torvalds    We force DF flag on tunnels with preconfigured hop limit,
961da177e4SLinus Torvalds    that is ALL. :-) Well, it does not remove the problem completely,
971da177e4SLinus Torvalds    but exponential growth of network traffic is changed to linear
981da177e4SLinus Torvalds    (branches, that exceed pmtu are pruned) and tunnel mtu
99bff52857Sstephen hemminger    rapidly degrades to value <68, where looping stops.
1001da177e4SLinus Torvalds    Yes, it is not good if there exists a router in the loop,
1011da177e4SLinus Torvalds    which does not force DF, even when encapsulating packets have DF set.
1021da177e4SLinus Torvalds    But it is not our problem! Nobody could accuse us, we made
1031da177e4SLinus Torvalds    all that we could make. Even if it is your gated who injected
1041da177e4SLinus Torvalds    fatal route to network, even if it were you who configured
1051da177e4SLinus Torvalds    fatal static route: you are innocent. :-)
1061da177e4SLinus Torvalds 
1071da177e4SLinus Torvalds    Alexey Kuznetsov.
1081da177e4SLinus Torvalds  */
1091da177e4SLinus Torvalds 
110eccc1bb8Sstephen hemminger static bool log_ecn_error = true;
111eccc1bb8Sstephen hemminger module_param(log_ecn_error, bool, 0644);
112eccc1bb8Sstephen hemminger MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN");
113eccc1bb8Sstephen hemminger 
114c19e654dSHerbert Xu static struct rtnl_link_ops ipgre_link_ops __read_mostly;
1151da177e4SLinus Torvalds static int ipgre_tunnel_init(struct net_device *dev);
1161a66a836SWilliam Tu static void erspan_build_header(struct sk_buff *skb,
117c69de58bSWilliam Tu 				u32 id, u32 index,
118a3222dc9SWilliam Tu 				bool truncate, bool is_ipv4);
119eb8ce741SPavel Emelyanov 
120c7d03a00SAlexey Dobriyan static unsigned int ipgre_net_id __read_mostly;
121c7d03a00SAlexey Dobriyan static unsigned int gre_tap_net_id __read_mostly;
12284e54fe0SWilliam Tu static unsigned int erspan_net_id __read_mostly;
123eb8ce741SPavel Emelyanov 
1249f57c67cSPravin B Shelar static void ipgre_err(struct sk_buff *skb, u32 info,
125bda7bb46SPravin B Shelar 		      const struct tnl_ptk_info *tpi)
1261da177e4SLinus Torvalds {
1271da177e4SLinus Torvalds 
128071f92d0SRami Rosen 	/* All the routers (except for Linux) return only
1291da177e4SLinus Torvalds 	   8 bytes of packet payload. It means, that precise relaying of
1301da177e4SLinus Torvalds 	   ICMP in the real Internet is absolutely infeasible.
1311da177e4SLinus Torvalds 
1321da177e4SLinus Torvalds 	   Moreover, Cisco "wise men" put GRE key to the third word
133c5441932SPravin B Shelar 	   in GRE header. It makes impossible maintaining even soft
134c5441932SPravin B Shelar 	   state for keyed GRE tunnels with enabled checksum. Tell
135c5441932SPravin B Shelar 	   them "thank you".
1361da177e4SLinus Torvalds 
1371da177e4SLinus Torvalds 	   Well, I wonder, rfc1812 was written by Cisco employee,
138bff52857Sstephen hemminger 	   what the hell these idiots break standards established
139bff52857Sstephen hemminger 	   by themselves???
1401da177e4SLinus Torvalds 	   */
141c5441932SPravin B Shelar 	struct net *net = dev_net(skb->dev);
142c5441932SPravin B Shelar 	struct ip_tunnel_net *itn;
14396f5a846SEric Dumazet 	const struct iphdr *iph;
14488c7664fSArnaldo Carvalho de Melo 	const int type = icmp_hdr(skb)->type;
14588c7664fSArnaldo Carvalho de Melo 	const int code = icmp_hdr(skb)->code;
14620e1954fSEric Dumazet 	unsigned int data_len = 0;
1471da177e4SLinus Torvalds 	struct ip_tunnel *t;
148d2083287Sstephen hemminger 
1491da177e4SLinus Torvalds 	switch (type) {
1501da177e4SLinus Torvalds 	default:
1511da177e4SLinus Torvalds 	case ICMP_PARAMETERPROB:
1529f57c67cSPravin B Shelar 		return;
1531da177e4SLinus Torvalds 
1541da177e4SLinus Torvalds 	case ICMP_DEST_UNREACH:
1551da177e4SLinus Torvalds 		switch (code) {
1561da177e4SLinus Torvalds 		case ICMP_SR_FAILED:
1571da177e4SLinus Torvalds 		case ICMP_PORT_UNREACH:
1581da177e4SLinus Torvalds 			/* Impossible event. */
1599f57c67cSPravin B Shelar 			return;
1601da177e4SLinus Torvalds 		default:
1611da177e4SLinus Torvalds 			/* All others are translated to HOST_UNREACH.
1621da177e4SLinus Torvalds 			   rfc2003 contains "deep thoughts" about NET_UNREACH,
1631da177e4SLinus Torvalds 			   I believe they are just ether pollution. --ANK
1641da177e4SLinus Torvalds 			 */
1651da177e4SLinus Torvalds 			break;
1661da177e4SLinus Torvalds 		}
1671da177e4SLinus Torvalds 		break;
1689f57c67cSPravin B Shelar 
1691da177e4SLinus Torvalds 	case ICMP_TIME_EXCEEDED:
1701da177e4SLinus Torvalds 		if (code != ICMP_EXC_TTL)
1719f57c67cSPravin B Shelar 			return;
17220e1954fSEric Dumazet 		data_len = icmp_hdr(skb)->un.reserved[1] * 4; /* RFC 4884 4.1 */
1731da177e4SLinus Torvalds 		break;
17455be7a9cSDavid S. Miller 
17555be7a9cSDavid S. Miller 	case ICMP_REDIRECT:
17655be7a9cSDavid S. Miller 		break;
1771da177e4SLinus Torvalds 	}
1781da177e4SLinus Torvalds 
179bda7bb46SPravin B Shelar 	if (tpi->proto == htons(ETH_P_TEB))
180c5441932SPravin B Shelar 		itn = net_generic(net, gre_tap_net_id);
181c5441932SPravin B Shelar 	else
182c5441932SPravin B Shelar 		itn = net_generic(net, ipgre_net_id);
183c5441932SPravin B Shelar 
184c0c0c50fSDuan Jiong 	iph = (const struct iphdr *)(icmp_hdr(skb) + 1);
185bda7bb46SPravin B Shelar 	t = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags,
186bda7bb46SPravin B Shelar 			     iph->daddr, iph->saddr, tpi->key);
187d2083287Sstephen hemminger 
18851456b29SIan Morris 	if (!t)
1899f57c67cSPravin B Shelar 		return;
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))
1959b8c6d7bSEric Dumazet                return;
1969b8c6d7bSEric Dumazet #endif
1979b8c6d7bSEric Dumazet 
19836393395SDavid S. Miller 	if (t->parms.iph.daddr == 0 ||
199f97c1e0cSJoe Perches 	    ipv4_is_multicast(t->parms.iph.daddr))
2009f57c67cSPravin B Shelar 		return;
2011da177e4SLinus Torvalds 
2021da177e4SLinus Torvalds 	if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
2039f57c67cSPravin B Shelar 		return;
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;
2109f57c67cSPravin B Shelar }
2119f57c67cSPravin B Shelar 
2129f57c67cSPravin B Shelar static void gre_err(struct sk_buff *skb, u32 info)
2139f57c67cSPravin B Shelar {
2149f57c67cSPravin B Shelar 	/* All the routers (except for Linux) return only
2159f57c67cSPravin B Shelar 	 * 8 bytes of packet payload. It means, that precise relaying of
2169f57c67cSPravin B Shelar 	 * ICMP in the real Internet is absolutely infeasible.
2179f57c67cSPravin B Shelar 	 *
2189f57c67cSPravin B Shelar 	 * Moreover, Cisco "wise men" put GRE key to the third word
2199f57c67cSPravin B Shelar 	 * in GRE header. It makes impossible maintaining even soft
2209f57c67cSPravin B Shelar 	 * state for keyed
2219f57c67cSPravin B Shelar 	 * GRE tunnels with enabled checksum. Tell them "thank you".
2229f57c67cSPravin B Shelar 	 *
2239f57c67cSPravin B Shelar 	 * Well, I wonder, rfc1812 was written by Cisco employee,
2249f57c67cSPravin B Shelar 	 * what the hell these idiots break standards established
2259f57c67cSPravin B Shelar 	 * by themselves???
2269f57c67cSPravin B Shelar 	 */
2279f57c67cSPravin B Shelar 
228e582615aSEric Dumazet 	const struct iphdr *iph = (struct iphdr *)skb->data;
2299f57c67cSPravin B Shelar 	const int type = icmp_hdr(skb)->type;
2309f57c67cSPravin B Shelar 	const int code = icmp_hdr(skb)->code;
2319f57c67cSPravin B Shelar 	struct tnl_ptk_info tpi;
2329f57c67cSPravin B Shelar 	bool csum_err = false;
2339f57c67cSPravin B Shelar 
234e582615aSEric Dumazet 	if (gre_parse_header(skb, &tpi, &csum_err, htons(ETH_P_IP),
235e582615aSEric Dumazet 			     iph->ihl * 4) < 0) {
2369f57c67cSPravin B Shelar 		if (!csum_err)		/* ignore csum errors. */
2379f57c67cSPravin B Shelar 			return;
2389f57c67cSPravin B Shelar 	}
2399f57c67cSPravin B Shelar 
2409f57c67cSPravin B Shelar 	if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
2419f57c67cSPravin B Shelar 		ipv4_update_pmtu(skb, dev_net(skb->dev), info,
2429f57c67cSPravin B Shelar 				 skb->dev->ifindex, 0, IPPROTO_GRE, 0);
2439f57c67cSPravin B Shelar 		return;
2449f57c67cSPravin B Shelar 	}
2459f57c67cSPravin B Shelar 	if (type == ICMP_REDIRECT) {
2469f57c67cSPravin B Shelar 		ipv4_redirect(skb, dev_net(skb->dev), skb->dev->ifindex, 0,
2479f57c67cSPravin B Shelar 			      IPPROTO_GRE, 0);
2489f57c67cSPravin B Shelar 		return;
2499f57c67cSPravin B Shelar 	}
2509f57c67cSPravin B Shelar 
2519f57c67cSPravin B Shelar 	ipgre_err(skb, info, &tpi);
2521da177e4SLinus Torvalds }
2531da177e4SLinus Torvalds 
25484e54fe0SWilliam Tu static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
25584e54fe0SWilliam Tu 		      int gre_hdr_len)
25684e54fe0SWilliam Tu {
25784e54fe0SWilliam Tu 	struct net *net = dev_net(skb->dev);
25884e54fe0SWilliam Tu 	struct metadata_dst *tun_dst = NULL;
2591d7e2ed2SWilliam Tu 	struct erspan_base_hdr *ershdr;
2601d7e2ed2SWilliam Tu 	struct erspan_metadata *pkt_md;
26184e54fe0SWilliam Tu 	struct ip_tunnel_net *itn;
26284e54fe0SWilliam Tu 	struct ip_tunnel *tunnel;
26384e54fe0SWilliam Tu 	const struct iphdr *iph;
2643df19283SWilliam Tu 	struct erspan_md2 *md2;
2651d7e2ed2SWilliam Tu 	int ver;
26684e54fe0SWilliam Tu 	int len;
26784e54fe0SWilliam Tu 
26884e54fe0SWilliam Tu 	itn = net_generic(net, erspan_net_id);
26984e54fe0SWilliam Tu 	len = gre_hdr_len + sizeof(*ershdr);
27084e54fe0SWilliam Tu 
2711d7e2ed2SWilliam Tu 	/* Check based hdr len */
27284e54fe0SWilliam Tu 	if (unlikely(!pskb_may_pull(skb, len)))
273c05fad57SHaishuang Yan 		return PACKET_REJECT;
27484e54fe0SWilliam Tu 
27584e54fe0SWilliam Tu 	iph = ip_hdr(skb);
2761d7e2ed2SWilliam Tu 	ershdr = (struct erspan_base_hdr *)(skb->data + gre_hdr_len);
277c69de58bSWilliam Tu 	ver = ershdr->ver;
27884e54fe0SWilliam Tu 
27984e54fe0SWilliam Tu 	/* The original GRE header does not have key field,
28084e54fe0SWilliam Tu 	 * Use ERSPAN 10-bit session ID as key.
28184e54fe0SWilliam Tu 	 */
282c69de58bSWilliam Tu 	tpi->key = cpu_to_be32(get_session_id(ershdr));
28384e54fe0SWilliam Tu 	tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex,
28484e54fe0SWilliam Tu 				  tpi->flags | TUNNEL_KEY,
28584e54fe0SWilliam Tu 				  iph->saddr, iph->daddr, tpi->key);
28684e54fe0SWilliam Tu 
28784e54fe0SWilliam Tu 	if (tunnel) {
2881d7e2ed2SWilliam Tu 		len = gre_hdr_len + erspan_hdr_len(ver);
2891d7e2ed2SWilliam Tu 		if (unlikely(!pskb_may_pull(skb, len)))
290ae3e1337SWilliam Tu 			return PACKET_REJECT;
2911d7e2ed2SWilliam Tu 
292d91e8db5SWilliam Tu 		ershdr = (struct erspan_base_hdr *)(skb->data + gre_hdr_len);
293d91e8db5SWilliam Tu 		pkt_md = (struct erspan_metadata *)(ershdr + 1);
294d91e8db5SWilliam Tu 
29584e54fe0SWilliam Tu 		if (__iptunnel_pull_header(skb,
2961d7e2ed2SWilliam Tu 					   len,
29784e54fe0SWilliam Tu 					   htons(ETH_P_TEB),
29884e54fe0SWilliam Tu 					   false, false) < 0)
29984e54fe0SWilliam Tu 			goto drop;
30084e54fe0SWilliam Tu 
3011a66a836SWilliam Tu 		if (tunnel->collect_md) {
3021a66a836SWilliam Tu 			struct ip_tunnel_info *info;
3031a66a836SWilliam Tu 			struct erspan_metadata *md;
3041a66a836SWilliam Tu 			__be64 tun_id;
3051a66a836SWilliam Tu 			__be16 flags;
3061a66a836SWilliam Tu 
3071a66a836SWilliam Tu 			tpi->flags |= TUNNEL_KEY;
3081a66a836SWilliam Tu 			flags = tpi->flags;
3091a66a836SWilliam Tu 			tun_id = key32_to_tunnel_id(tpi->key);
3101a66a836SWilliam Tu 
3111a66a836SWilliam Tu 			tun_dst = ip_tun_rx_dst(skb, flags,
3121a66a836SWilliam Tu 						tun_id, sizeof(*md));
3131a66a836SWilliam Tu 			if (!tun_dst)
3141a66a836SWilliam Tu 				return PACKET_REJECT;
3151a66a836SWilliam Tu 
3161a66a836SWilliam Tu 			md = ip_tunnel_info_opts(&tun_dst->u.tun_info);
317f551c91dSWilliam Tu 			md->version = ver;
3183df19283SWilliam Tu 			md2 = &md->u.md2;
3193df19283SWilliam Tu 			memcpy(md2, pkt_md, ver == 1 ? ERSPAN_V1_MDSIZE :
3203df19283SWilliam Tu 						       ERSPAN_V2_MDSIZE);
321f551c91dSWilliam Tu 
3221a66a836SWilliam Tu 			info = &tun_dst->u.tun_info;
3231a66a836SWilliam Tu 			info->key.tun_flags |= TUNNEL_ERSPAN_OPT;
3241a66a836SWilliam Tu 			info->options_len = sizeof(*md);
3251a66a836SWilliam Tu 		}
3261a66a836SWilliam Tu 
32784e54fe0SWilliam Tu 		skb_reset_mac_header(skb);
32884e54fe0SWilliam Tu 		ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error);
32984e54fe0SWilliam Tu 		return PACKET_RCVD;
33084e54fe0SWilliam Tu 	}
33184e54fe0SWilliam Tu drop:
33284e54fe0SWilliam Tu 	kfree_skb(skb);
33384e54fe0SWilliam Tu 	return PACKET_RCVD;
33484e54fe0SWilliam Tu }
33584e54fe0SWilliam Tu 
336125372faSJiri Benc static int __ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
337125372faSJiri Benc 		       struct ip_tunnel_net *itn, int hdr_len, bool raw_proto)
3381da177e4SLinus Torvalds {
3392e15ea39SPravin B Shelar 	struct metadata_dst *tun_dst = NULL;
340b71d1d42SEric Dumazet 	const struct iphdr *iph;
3411da177e4SLinus Torvalds 	struct ip_tunnel *tunnel;
3421da177e4SLinus Torvalds 
343eddc9ec5SArnaldo Carvalho de Melo 	iph = ip_hdr(skb);
344bda7bb46SPravin B Shelar 	tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags,
345bda7bb46SPravin B Shelar 				  iph->saddr, iph->daddr, tpi->key);
3461da177e4SLinus Torvalds 
347d2083287Sstephen hemminger 	if (tunnel) {
348125372faSJiri Benc 		if (__iptunnel_pull_header(skb, hdr_len, tpi->proto,
349125372faSJiri Benc 					   raw_proto, false) < 0)
350244a797bSJiri Benc 			goto drop;
351244a797bSJiri Benc 
352e271c7b4SJiri Benc 		if (tunnel->dev->type != ARPHRD_NONE)
3530e3da5bbSTimo Teräs 			skb_pop_mac_header(skb);
354e271c7b4SJiri Benc 		else
355e271c7b4SJiri Benc 			skb_reset_mac_header(skb);
3562e15ea39SPravin B Shelar 		if (tunnel->collect_md) {
357c29a70d2SPravin B Shelar 			__be16 flags;
358c29a70d2SPravin B Shelar 			__be64 tun_id;
3592e15ea39SPravin B Shelar 
360c29a70d2SPravin B Shelar 			flags = tpi->flags & (TUNNEL_CSUM | TUNNEL_KEY);
361d817f432SAmir Vadai 			tun_id = key32_to_tunnel_id(tpi->key);
362c29a70d2SPravin B Shelar 			tun_dst = ip_tun_rx_dst(skb, flags, tun_id, 0);
3632e15ea39SPravin B Shelar 			if (!tun_dst)
3642e15ea39SPravin B Shelar 				return PACKET_REJECT;
3652e15ea39SPravin B Shelar 		}
3662e15ea39SPravin B Shelar 
3672e15ea39SPravin B Shelar 		ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error);
368bda7bb46SPravin B Shelar 		return PACKET_RCVD;
3691da177e4SLinus Torvalds 	}
370125372faSJiri Benc 	return PACKET_NEXT;
371244a797bSJiri Benc 
372244a797bSJiri Benc drop:
373244a797bSJiri Benc 	kfree_skb(skb);
374244a797bSJiri Benc 	return PACKET_RCVD;
3751da177e4SLinus Torvalds }
3761da177e4SLinus Torvalds 
377125372faSJiri Benc static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
378125372faSJiri Benc 		     int hdr_len)
379125372faSJiri Benc {
380125372faSJiri Benc 	struct net *net = dev_net(skb->dev);
381125372faSJiri Benc 	struct ip_tunnel_net *itn;
382125372faSJiri Benc 	int res;
383125372faSJiri Benc 
384125372faSJiri Benc 	if (tpi->proto == htons(ETH_P_TEB))
385125372faSJiri Benc 		itn = net_generic(net, gre_tap_net_id);
386125372faSJiri Benc 	else
387125372faSJiri Benc 		itn = net_generic(net, ipgre_net_id);
388125372faSJiri Benc 
389125372faSJiri Benc 	res = __ipgre_rcv(skb, tpi, itn, hdr_len, false);
390125372faSJiri Benc 	if (res == PACKET_NEXT && tpi->proto == htons(ETH_P_TEB)) {
391125372faSJiri Benc 		/* ipgre tunnels in collect metadata mode should receive
392125372faSJiri Benc 		 * also ETH_P_TEB traffic.
393125372faSJiri Benc 		 */
394125372faSJiri Benc 		itn = net_generic(net, ipgre_net_id);
395125372faSJiri Benc 		res = __ipgre_rcv(skb, tpi, itn, hdr_len, true);
396125372faSJiri Benc 	}
397125372faSJiri Benc 	return res;
398125372faSJiri Benc }
399125372faSJiri Benc 
4009f57c67cSPravin B Shelar static int gre_rcv(struct sk_buff *skb)
4019f57c67cSPravin B Shelar {
4029f57c67cSPravin B Shelar 	struct tnl_ptk_info tpi;
4039f57c67cSPravin B Shelar 	bool csum_err = false;
40495f5c64cSTom Herbert 	int hdr_len;
4059f57c67cSPravin B Shelar 
4069f57c67cSPravin B Shelar #ifdef CONFIG_NET_IPGRE_BROADCAST
4079f57c67cSPravin B Shelar 	if (ipv4_is_multicast(ip_hdr(skb)->daddr)) {
4089f57c67cSPravin B Shelar 		/* Looped back packet, drop it! */
4099f57c67cSPravin B Shelar 		if (rt_is_output_route(skb_rtable(skb)))
4109f57c67cSPravin B Shelar 			goto drop;
4119f57c67cSPravin B Shelar 	}
4129f57c67cSPravin B Shelar #endif
4139f57c67cSPravin B Shelar 
414e582615aSEric Dumazet 	hdr_len = gre_parse_header(skb, &tpi, &csum_err, htons(ETH_P_IP), 0);
415f132ae7cSJiri Benc 	if (hdr_len < 0)
41695f5c64cSTom Herbert 		goto drop;
41795f5c64cSTom Herbert 
418f551c91dSWilliam Tu 	if (unlikely(tpi.proto == htons(ETH_P_ERSPAN) ||
419f551c91dSWilliam Tu 		     tpi.proto == htons(ETH_P_ERSPAN2))) {
42084e54fe0SWilliam Tu 		if (erspan_rcv(skb, &tpi, hdr_len) == PACKET_RCVD)
42184e54fe0SWilliam Tu 			return 0;
422dd8d5b8cSHaishuang Yan 		goto out;
42384e54fe0SWilliam Tu 	}
42484e54fe0SWilliam Tu 
425244a797bSJiri Benc 	if (ipgre_rcv(skb, &tpi, hdr_len) == PACKET_RCVD)
4269f57c67cSPravin B Shelar 		return 0;
4279f57c67cSPravin B Shelar 
428dd8d5b8cSHaishuang Yan out:
4299f57c67cSPravin B Shelar 	icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
4309f57c67cSPravin B Shelar drop:
4319f57c67cSPravin B Shelar 	kfree_skb(skb);
4329f57c67cSPravin B Shelar 	return 0;
4339f57c67cSPravin B Shelar }
4349f57c67cSPravin B Shelar 
435c5441932SPravin B Shelar static void __gre_xmit(struct sk_buff *skb, struct net_device *dev,
436c5441932SPravin B Shelar 		       const struct iphdr *tnl_params,
437c5441932SPravin B Shelar 		       __be16 proto)
438c5441932SPravin B Shelar {
439c5441932SPravin B Shelar 	struct ip_tunnel *tunnel = netdev_priv(dev);
440c5441932SPravin B Shelar 
441c5441932SPravin B Shelar 	if (tunnel->parms.o_flags & TUNNEL_SEQ)
442c5441932SPravin B Shelar 		tunnel->o_seqno++;
443cef401deSEric Dumazet 
444c5441932SPravin B Shelar 	/* Push GRE header. */
445182a352dSTom Herbert 	gre_build_header(skb, tunnel->tun_hlen,
446182a352dSTom Herbert 			 tunnel->parms.o_flags, proto, tunnel->parms.o_key,
447182a352dSTom Herbert 			 htonl(tunnel->o_seqno));
4481da177e4SLinus Torvalds 
449bf3d6a8fSNicolas Dichtel 	ip_tunnel_xmit(skb, dev, tnl_params, tnl_params->protocol);
4501da177e4SLinus Torvalds }
4511da177e4SLinus Torvalds 
452aed069dfSAlexander Duyck static int gre_handle_offloads(struct sk_buff *skb, bool csum)
453b2acd1dcSPravin B Shelar {
4546fa79666SEdward Cree 	return iptunnel_handle_offloads(skb, csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE);
455b2acd1dcSPravin B Shelar }
456b2acd1dcSPravin B Shelar 
457fc4099f1SPravin B Shelar static struct rtable *gre_get_rt(struct sk_buff *skb,
458fc4099f1SPravin B Shelar 				 struct net_device *dev,
459fc4099f1SPravin B Shelar 				 struct flowi4 *fl,
460fc4099f1SPravin B Shelar 				 const struct ip_tunnel_key *key)
461fc4099f1SPravin B Shelar {
462fc4099f1SPravin B Shelar 	struct net *net = dev_net(dev);
463fc4099f1SPravin B Shelar 
464fc4099f1SPravin B Shelar 	memset(fl, 0, sizeof(*fl));
465fc4099f1SPravin B Shelar 	fl->daddr = key->u.ipv4.dst;
466fc4099f1SPravin B Shelar 	fl->saddr = key->u.ipv4.src;
467fc4099f1SPravin B Shelar 	fl->flowi4_tos = RT_TOS(key->tos);
468fc4099f1SPravin B Shelar 	fl->flowi4_mark = skb->mark;
469fc4099f1SPravin B Shelar 	fl->flowi4_proto = IPPROTO_GRE;
470fc4099f1SPravin B Shelar 
471fc4099f1SPravin B Shelar 	return ip_route_output_key(net, fl);
472fc4099f1SPravin B Shelar }
473fc4099f1SPravin B Shelar 
474862a03c3SWilliam Tu static struct rtable *prepare_fb_xmit(struct sk_buff *skb,
475862a03c3SWilliam Tu 				      struct net_device *dev,
476862a03c3SWilliam Tu 				      struct flowi4 *fl,
477862a03c3SWilliam Tu 				      int tunnel_hlen)
4782e15ea39SPravin B Shelar {
4792e15ea39SPravin B Shelar 	struct ip_tunnel_info *tun_info;
4802e15ea39SPravin B Shelar 	const struct ip_tunnel_key *key;
481db3c6139SDaniel Borkmann 	struct rtable *rt = NULL;
4822e15ea39SPravin B Shelar 	int min_headroom;
483db3c6139SDaniel Borkmann 	bool use_cache;
4842e15ea39SPravin B Shelar 	int err;
4852e15ea39SPravin B Shelar 
48661adedf3SJiri Benc 	tun_info = skb_tunnel_info(skb);
4872e15ea39SPravin B Shelar 	key = &tun_info->key;
488db3c6139SDaniel Borkmann 	use_cache = ip_tunnel_dst_cache_usable(skb, tun_info);
489862a03c3SWilliam Tu 
490db3c6139SDaniel Borkmann 	if (use_cache)
491862a03c3SWilliam Tu 		rt = dst_cache_get_ip4(&tun_info->dst_cache, &fl->saddr);
4923c1cb4d2SPaolo Abeni 	if (!rt) {
493862a03c3SWilliam Tu 		rt = gre_get_rt(skb, dev, fl, key);
4942e15ea39SPravin B Shelar 		if (IS_ERR(rt))
4952e15ea39SPravin B Shelar 			goto err_free_skb;
496db3c6139SDaniel Borkmann 		if (use_cache)
4973c1cb4d2SPaolo Abeni 			dst_cache_set_ip4(&tun_info->dst_cache, &rt->dst,
498862a03c3SWilliam Tu 					  fl->saddr);
4993c1cb4d2SPaolo Abeni 	}
5002e15ea39SPravin B Shelar 
5012e15ea39SPravin B Shelar 	min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len
5022e15ea39SPravin B Shelar 			+ tunnel_hlen + sizeof(struct iphdr);
5032e15ea39SPravin B Shelar 	if (skb_headroom(skb) < min_headroom || skb_header_cloned(skb)) {
5042e15ea39SPravin B Shelar 		int head_delta = SKB_DATA_ALIGN(min_headroom -
5052e15ea39SPravin B Shelar 						skb_headroom(skb) +
5062e15ea39SPravin B Shelar 						16);
5072e15ea39SPravin B Shelar 		err = pskb_expand_head(skb, max_t(int, head_delta, 0),
5082e15ea39SPravin B Shelar 				       0, GFP_ATOMIC);
5092e15ea39SPravin B Shelar 		if (unlikely(err))
5102e15ea39SPravin B Shelar 			goto err_free_rt;
5112e15ea39SPravin B Shelar 	}
512862a03c3SWilliam Tu 	return rt;
513862a03c3SWilliam Tu 
514862a03c3SWilliam Tu err_free_rt:
515862a03c3SWilliam Tu 	ip_rt_put(rt);
516862a03c3SWilliam Tu err_free_skb:
517862a03c3SWilliam Tu 	kfree_skb(skb);
518862a03c3SWilliam Tu 	dev->stats.tx_dropped++;
519862a03c3SWilliam Tu 	return NULL;
520862a03c3SWilliam Tu }
521862a03c3SWilliam Tu 
522862a03c3SWilliam Tu static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev,
523862a03c3SWilliam Tu 			__be16 proto)
524862a03c3SWilliam Tu {
52577a5196aSWilliam Tu 	struct ip_tunnel *tunnel = netdev_priv(dev);
526862a03c3SWilliam Tu 	struct ip_tunnel_info *tun_info;
527862a03c3SWilliam Tu 	const struct ip_tunnel_key *key;
528862a03c3SWilliam Tu 	struct rtable *rt = NULL;
529862a03c3SWilliam Tu 	struct flowi4 fl;
530862a03c3SWilliam Tu 	int tunnel_hlen;
531862a03c3SWilliam Tu 	__be16 df, flags;
532862a03c3SWilliam Tu 
533862a03c3SWilliam Tu 	tun_info = skb_tunnel_info(skb);
534862a03c3SWilliam Tu 	if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) ||
535862a03c3SWilliam Tu 		     ip_tunnel_info_af(tun_info) != AF_INET))
536862a03c3SWilliam Tu 		goto err_free_skb;
537862a03c3SWilliam Tu 
538862a03c3SWilliam Tu 	key = &tun_info->key;
539862a03c3SWilliam Tu 	tunnel_hlen = gre_calc_hlen(key->tun_flags);
540862a03c3SWilliam Tu 
541862a03c3SWilliam Tu 	rt = prepare_fb_xmit(skb, dev, &fl, tunnel_hlen);
542862a03c3SWilliam Tu 	if (!rt)
543862a03c3SWilliam Tu 		return;
5442e15ea39SPravin B Shelar 
5452e15ea39SPravin B Shelar 	/* Push Tunnel header. */
546aed069dfSAlexander Duyck 	if (gre_handle_offloads(skb, !!(tun_info->key.tun_flags & TUNNEL_CSUM)))
5472e15ea39SPravin B Shelar 		goto err_free_rt;
5482e15ea39SPravin B Shelar 
54977a5196aSWilliam Tu 	flags = tun_info->key.tun_flags &
55077a5196aSWilliam Tu 		(TUNNEL_CSUM | TUNNEL_KEY | TUNNEL_SEQ);
551cba65321SDavid S. Miller 	gre_build_header(skb, tunnel_hlen, flags, proto,
55277a5196aSWilliam Tu 			 tunnel_id_to_key32(tun_info->key.tun_id),
55315746394SColin Ian King 			 (flags & TUNNEL_SEQ) ? htonl(tunnel->o_seqno++) : 0);
5542e15ea39SPravin B Shelar 
5552e15ea39SPravin B Shelar 	df = key->tun_flags & TUNNEL_DONT_FRAGMENT ?  htons(IP_DF) : 0;
556039f5062SPravin B Shelar 
557039f5062SPravin B Shelar 	iptunnel_xmit(skb->sk, rt, skb, fl.saddr, key->u.ipv4.dst, IPPROTO_GRE,
5587c383fb2SJiri Benc 		      key->tos, key->ttl, df, false);
5592e15ea39SPravin B Shelar 	return;
5602e15ea39SPravin B Shelar 
5612e15ea39SPravin B Shelar err_free_rt:
5622e15ea39SPravin B Shelar 	ip_rt_put(rt);
5632e15ea39SPravin B Shelar err_free_skb:
5642e15ea39SPravin B Shelar 	kfree_skb(skb);
5652e15ea39SPravin B Shelar 	dev->stats.tx_dropped++;
5662e15ea39SPravin B Shelar }
5672e15ea39SPravin B Shelar 
5681a66a836SWilliam Tu static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev,
5691a66a836SWilliam Tu 			   __be16 proto)
5701a66a836SWilliam Tu {
5711a66a836SWilliam Tu 	struct ip_tunnel *tunnel = netdev_priv(dev);
5721a66a836SWilliam Tu 	struct ip_tunnel_info *tun_info;
5731a66a836SWilliam Tu 	const struct ip_tunnel_key *key;
5741a66a836SWilliam Tu 	struct erspan_metadata *md;
5751a66a836SWilliam Tu 	struct rtable *rt = NULL;
5761a66a836SWilliam Tu 	bool truncate = false;
5771a66a836SWilliam Tu 	struct flowi4 fl;
5781a66a836SWilliam Tu 	int tunnel_hlen;
579f551c91dSWilliam Tu 	int version;
5801a66a836SWilliam Tu 	__be16 df;
5811a66a836SWilliam Tu 
5821a66a836SWilliam Tu 	tun_info = skb_tunnel_info(skb);
5831a66a836SWilliam Tu 	if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) ||
5841a66a836SWilliam Tu 		     ip_tunnel_info_af(tun_info) != AF_INET))
5851a66a836SWilliam Tu 		goto err_free_skb;
5861a66a836SWilliam Tu 
5871a66a836SWilliam Tu 	key = &tun_info->key;
588f551c91dSWilliam Tu 	md = ip_tunnel_info_opts(tun_info);
589f551c91dSWilliam Tu 	if (!md)
590f551c91dSWilliam Tu 		goto err_free_rt;
5911a66a836SWilliam Tu 
5921a66a836SWilliam Tu 	/* ERSPAN has fixed 8 byte GRE header */
593f551c91dSWilliam Tu 	version = md->version;
594f551c91dSWilliam Tu 	tunnel_hlen = 8 + erspan_hdr_len(version);
5951a66a836SWilliam Tu 
5961a66a836SWilliam Tu 	rt = prepare_fb_xmit(skb, dev, &fl, tunnel_hlen);
5971a66a836SWilliam Tu 	if (!rt)
5981a66a836SWilliam Tu 		return;
5991a66a836SWilliam Tu 
6001a66a836SWilliam Tu 	if (gre_handle_offloads(skb, false))
6011a66a836SWilliam Tu 		goto err_free_rt;
6021a66a836SWilliam Tu 
603f192970dSWilliam Tu 	if (skb->len > dev->mtu + dev->hard_header_len) {
604f192970dSWilliam Tu 		pskb_trim(skb, dev->mtu + dev->hard_header_len);
6051a66a836SWilliam Tu 		truncate = true;
6061a66a836SWilliam Tu 	}
6071a66a836SWilliam Tu 
608f551c91dSWilliam Tu 	if (version == 1) {
609c69de58bSWilliam Tu 		erspan_build_header(skb, ntohl(tunnel_id_to_key32(key->tun_id)),
6101d7e2ed2SWilliam Tu 				    ntohl(md->u.index), truncate, true);
611f551c91dSWilliam Tu 	} else if (version == 2) {
612c69de58bSWilliam Tu 		erspan_build_header_v2(skb,
613c69de58bSWilliam Tu 				       ntohl(tunnel_id_to_key32(key->tun_id)),
614c69de58bSWilliam Tu 				       md->u.md2.dir,
615c69de58bSWilliam Tu 				       get_hwid(&md->u.md2),
616c69de58bSWilliam Tu 				       truncate, true);
617f551c91dSWilliam Tu 	} else {
618f551c91dSWilliam Tu 		goto err_free_rt;
619f551c91dSWilliam Tu 	}
6201a66a836SWilliam Tu 
6211a66a836SWilliam Tu 	gre_build_header(skb, 8, TUNNEL_SEQ,
6221a66a836SWilliam Tu 			 htons(ETH_P_ERSPAN), 0, htonl(tunnel->o_seqno++));
6231a66a836SWilliam Tu 
6241a66a836SWilliam Tu 	df = key->tun_flags & TUNNEL_DONT_FRAGMENT ?  htons(IP_DF) : 0;
6251a66a836SWilliam Tu 
6261a66a836SWilliam Tu 	iptunnel_xmit(skb->sk, rt, skb, fl.saddr, key->u.ipv4.dst, IPPROTO_GRE,
6271a66a836SWilliam Tu 		      key->tos, key->ttl, df, false);
6281a66a836SWilliam Tu 	return;
6291a66a836SWilliam Tu 
6301a66a836SWilliam Tu err_free_rt:
6311a66a836SWilliam Tu 	ip_rt_put(rt);
6321a66a836SWilliam Tu err_free_skb:
6331a66a836SWilliam Tu 	kfree_skb(skb);
6341a66a836SWilliam Tu 	dev->stats.tx_dropped++;
6351a66a836SWilliam Tu }
6361a66a836SWilliam Tu 
637fc4099f1SPravin B Shelar static int gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
638fc4099f1SPravin B Shelar {
639fc4099f1SPravin B Shelar 	struct ip_tunnel_info *info = skb_tunnel_info(skb);
640fc4099f1SPravin B Shelar 	struct rtable *rt;
641fc4099f1SPravin B Shelar 	struct flowi4 fl4;
642fc4099f1SPravin B Shelar 
643fc4099f1SPravin B Shelar 	if (ip_tunnel_info_af(info) != AF_INET)
644fc4099f1SPravin B Shelar 		return -EINVAL;
645fc4099f1SPravin B Shelar 
646fc4099f1SPravin B Shelar 	rt = gre_get_rt(skb, dev, &fl4, &info->key);
647fc4099f1SPravin B Shelar 	if (IS_ERR(rt))
648fc4099f1SPravin B Shelar 		return PTR_ERR(rt);
649fc4099f1SPravin B Shelar 
650fc4099f1SPravin B Shelar 	ip_rt_put(rt);
651fc4099f1SPravin B Shelar 	info->key.u.ipv4.src = fl4.saddr;
652fc4099f1SPravin B Shelar 	return 0;
653fc4099f1SPravin B Shelar }
654fc4099f1SPravin B Shelar 
655c5441932SPravin B Shelar static netdev_tx_t ipgre_xmit(struct sk_buff *skb,
656c5441932SPravin B Shelar 			      struct net_device *dev)
657ee34c1ebSMichal Schmidt {
658c5441932SPravin B Shelar 	struct ip_tunnel *tunnel = netdev_priv(dev);
659c5441932SPravin B Shelar 	const struct iphdr *tnl_params;
660ee34c1ebSMichal Schmidt 
6612e15ea39SPravin B Shelar 	if (tunnel->collect_md) {
6622090714eSJiri Benc 		gre_fb_xmit(skb, dev, skb->protocol);
6632e15ea39SPravin B Shelar 		return NETDEV_TX_OK;
6642e15ea39SPravin B Shelar 	}
6652e15ea39SPravin B Shelar 
666c5441932SPravin B Shelar 	if (dev->header_ops) {
667c5441932SPravin B Shelar 		/* Need space for new headers */
668c5441932SPravin B Shelar 		if (skb_cow_head(skb, dev->needed_headroom -
6692bac7cb3SChen Gang 				      (tunnel->hlen + sizeof(struct iphdr))))
670c5441932SPravin B Shelar 			goto free_skb;
671ee34c1ebSMichal Schmidt 
672c5441932SPravin B Shelar 		tnl_params = (const struct iphdr *)skb->data;
673cbb1e85fSDavid S. Miller 
674c5441932SPravin B Shelar 		/* Pull skb since ip_tunnel_xmit() needs skb->data pointing
675c5441932SPravin B Shelar 		 * to gre header.
676c5441932SPravin B Shelar 		 */
677c5441932SPravin B Shelar 		skb_pull(skb, tunnel->hlen + sizeof(struct iphdr));
6788a0033a9STimo Teräs 		skb_reset_mac_header(skb);
679c5441932SPravin B Shelar 	} else {
680c5441932SPravin B Shelar 		if (skb_cow_head(skb, dev->needed_headroom))
681c5441932SPravin B Shelar 			goto free_skb;
682c5441932SPravin B Shelar 
683c5441932SPravin B Shelar 		tnl_params = &tunnel->parms.iph;
684ee34c1ebSMichal Schmidt 	}
685e1a80002SHerbert Xu 
686aed069dfSAlexander Duyck 	if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM)))
687aed069dfSAlexander Duyck 		goto free_skb;
6888a0033a9STimo Teräs 
689c5441932SPravin B Shelar 	__gre_xmit(skb, dev, tnl_params, skb->protocol);
690c5441932SPravin B Shelar 	return NETDEV_TX_OK;
691c5441932SPravin B Shelar 
692c5441932SPravin B Shelar free_skb:
6933acfa1e7SEric Dumazet 	kfree_skb(skb);
694c5441932SPravin B Shelar 	dev->stats.tx_dropped++;
695c5441932SPravin B Shelar 	return NETDEV_TX_OK;
696ee34c1ebSMichal Schmidt }
697ee34c1ebSMichal Schmidt 
69884e54fe0SWilliam Tu static netdev_tx_t erspan_xmit(struct sk_buff *skb,
69984e54fe0SWilliam Tu 			       struct net_device *dev)
70084e54fe0SWilliam Tu {
70184e54fe0SWilliam Tu 	struct ip_tunnel *tunnel = netdev_priv(dev);
70284e54fe0SWilliam Tu 	bool truncate = false;
70384e54fe0SWilliam Tu 
7041a66a836SWilliam Tu 	if (tunnel->collect_md) {
7051a66a836SWilliam Tu 		erspan_fb_xmit(skb, dev, skb->protocol);
7061a66a836SWilliam Tu 		return NETDEV_TX_OK;
7071a66a836SWilliam Tu 	}
7081a66a836SWilliam Tu 
70984e54fe0SWilliam Tu 	if (gre_handle_offloads(skb, false))
71084e54fe0SWilliam Tu 		goto free_skb;
71184e54fe0SWilliam Tu 
71284e54fe0SWilliam Tu 	if (skb_cow_head(skb, dev->needed_headroom))
71384e54fe0SWilliam Tu 		goto free_skb;
71484e54fe0SWilliam Tu 
715f192970dSWilliam Tu 	if (skb->len > dev->mtu + dev->hard_header_len) {
716f192970dSWilliam Tu 		pskb_trim(skb, dev->mtu + dev->hard_header_len);
71784e54fe0SWilliam Tu 		truncate = true;
71884e54fe0SWilliam Tu 	}
71984e54fe0SWilliam Tu 
72084e54fe0SWilliam Tu 	/* Push ERSPAN header */
721f551c91dSWilliam Tu 	if (tunnel->erspan_ver == 1)
722c69de58bSWilliam Tu 		erspan_build_header(skb, ntohl(tunnel->parms.o_key),
723c69de58bSWilliam Tu 				    tunnel->index,
724a3222dc9SWilliam Tu 				    truncate, true);
725*02f99df1SWilliam Tu 	else if (tunnel->erspan_ver == 2)
726c69de58bSWilliam Tu 		erspan_build_header_v2(skb, ntohl(tunnel->parms.o_key),
727f551c91dSWilliam Tu 				       tunnel->dir, tunnel->hwid,
728f551c91dSWilliam Tu 				       truncate, true);
729*02f99df1SWilliam Tu 	else
730*02f99df1SWilliam Tu 		goto free_skb;
731f551c91dSWilliam Tu 
73284e54fe0SWilliam Tu 	tunnel->parms.o_flags &= ~TUNNEL_KEY;
73384e54fe0SWilliam Tu 	__gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_ERSPAN));
73484e54fe0SWilliam Tu 	return NETDEV_TX_OK;
73584e54fe0SWilliam Tu 
73684e54fe0SWilliam Tu free_skb:
73784e54fe0SWilliam Tu 	kfree_skb(skb);
73884e54fe0SWilliam Tu 	dev->stats.tx_dropped++;
73984e54fe0SWilliam Tu 	return NETDEV_TX_OK;
74084e54fe0SWilliam Tu }
74184e54fe0SWilliam Tu 
742c5441932SPravin B Shelar static netdev_tx_t gre_tap_xmit(struct sk_buff *skb,
743c5441932SPravin B Shelar 				struct net_device *dev)
744c5441932SPravin B Shelar {
745c5441932SPravin B Shelar 	struct ip_tunnel *tunnel = netdev_priv(dev);
746ee34c1ebSMichal Schmidt 
7472e15ea39SPravin B Shelar 	if (tunnel->collect_md) {
7482090714eSJiri Benc 		gre_fb_xmit(skb, dev, htons(ETH_P_TEB));
7492e15ea39SPravin B Shelar 		return NETDEV_TX_OK;
7502e15ea39SPravin B Shelar 	}
7512e15ea39SPravin B Shelar 
752aed069dfSAlexander Duyck 	if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM)))
753aed069dfSAlexander Duyck 		goto free_skb;
754ee34c1ebSMichal Schmidt 
755c5441932SPravin B Shelar 	if (skb_cow_head(skb, dev->needed_headroom))
756c5441932SPravin B Shelar 		goto free_skb;
75742aa9162SHerbert Xu 
758c5441932SPravin B Shelar 	__gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_TEB));
759c5441932SPravin B Shelar 	return NETDEV_TX_OK;
760c5441932SPravin B Shelar 
761c5441932SPravin B Shelar free_skb:
7623acfa1e7SEric Dumazet 	kfree_skb(skb);
763c5441932SPravin B Shelar 	dev->stats.tx_dropped++;
764c5441932SPravin B Shelar 	return NETDEV_TX_OK;
76568c33163SPravin B Shelar }
766ee34c1ebSMichal Schmidt 
767dd9d598cSXin Long static void ipgre_link_update(struct net_device *dev, bool set_mtu)
768dd9d598cSXin Long {
769dd9d598cSXin Long 	struct ip_tunnel *tunnel = netdev_priv(dev);
770dd9d598cSXin Long 	int len;
771dd9d598cSXin Long 
772dd9d598cSXin Long 	len = tunnel->tun_hlen;
773dd9d598cSXin Long 	tunnel->tun_hlen = gre_calc_hlen(tunnel->parms.o_flags);
774dd9d598cSXin Long 	len = tunnel->tun_hlen - len;
775dd9d598cSXin Long 	tunnel->hlen = tunnel->hlen + len;
776dd9d598cSXin Long 
777dd9d598cSXin Long 	dev->needed_headroom = dev->needed_headroom + len;
778dd9d598cSXin Long 	if (set_mtu)
779dd9d598cSXin Long 		dev->mtu = max_t(int, dev->mtu - len, 68);
780dd9d598cSXin Long 
781dd9d598cSXin Long 	if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) {
782dd9d598cSXin Long 		if (!(tunnel->parms.o_flags & TUNNEL_CSUM) ||
783dd9d598cSXin Long 		    tunnel->encap.type == TUNNEL_ENCAP_NONE) {
784dd9d598cSXin Long 			dev->features |= NETIF_F_GSO_SOFTWARE;
785dd9d598cSXin Long 			dev->hw_features |= NETIF_F_GSO_SOFTWARE;
7861cc5954fSSabrina Dubroca 		} else {
7871cc5954fSSabrina Dubroca 			dev->features &= ~NETIF_F_GSO_SOFTWARE;
7881cc5954fSSabrina Dubroca 			dev->hw_features &= ~NETIF_F_GSO_SOFTWARE;
789dd9d598cSXin Long 		}
790dd9d598cSXin Long 		dev->features |= NETIF_F_LLTX;
7911cc5954fSSabrina Dubroca 	} else {
7921cc5954fSSabrina Dubroca 		dev->hw_features &= ~NETIF_F_GSO_SOFTWARE;
7931cc5954fSSabrina Dubroca 		dev->features &= ~(NETIF_F_LLTX | NETIF_F_GSO_SOFTWARE);
794dd9d598cSXin Long 	}
795dd9d598cSXin Long }
796dd9d598cSXin Long 
797c5441932SPravin B Shelar static int ipgre_tunnel_ioctl(struct net_device *dev,
798c5441932SPravin B Shelar 			      struct ifreq *ifr, int cmd)
7991da177e4SLinus Torvalds {
8001da177e4SLinus Torvalds 	struct ip_tunnel_parm p;
801a0efab67SXin Long 	int err;
8021da177e4SLinus Torvalds 
8031da177e4SLinus Torvalds 	if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
804c5441932SPravin B Shelar 		return -EFAULT;
805a0efab67SXin Long 
8066c734fb8SCong Wang 	if (cmd == SIOCADDTUNNEL || cmd == SIOCCHGTUNNEL) {
8071da177e4SLinus Torvalds 		if (p.iph.version != 4 || p.iph.protocol != IPPROTO_GRE ||
8081da177e4SLinus Torvalds 		    p.iph.ihl != 5 || (p.iph.frag_off & htons(~IP_DF)) ||
8096c734fb8SCong Wang 		    ((p.i_flags | p.o_flags) & (GRE_VERSION | GRE_ROUTING)))
8101da177e4SLinus Torvalds 			return -EINVAL;
811c5441932SPravin B Shelar 	}
812a0efab67SXin Long 
813c5441932SPravin B Shelar 	p.i_flags = gre_flags_to_tnl_flags(p.i_flags);
814c5441932SPravin B Shelar 	p.o_flags = gre_flags_to_tnl_flags(p.o_flags);
815c5441932SPravin B Shelar 
816c5441932SPravin B Shelar 	err = ip_tunnel_ioctl(dev, &p, cmd);
817c5441932SPravin B Shelar 	if (err)
818c5441932SPravin B Shelar 		return err;
819c5441932SPravin B Shelar 
820a0efab67SXin Long 	if (cmd == SIOCCHGTUNNEL) {
821a0efab67SXin Long 		struct ip_tunnel *t = netdev_priv(dev);
822a0efab67SXin Long 
823a0efab67SXin Long 		t->parms.i_flags = p.i_flags;
824a0efab67SXin Long 		t->parms.o_flags = p.o_flags;
825a0efab67SXin Long 
826a0efab67SXin Long 		if (strcmp(dev->rtnl_link_ops->kind, "erspan"))
827a0efab67SXin Long 			ipgre_link_update(dev, true);
828a0efab67SXin Long 	}
829a0efab67SXin Long 
83095f5c64cSTom Herbert 	p.i_flags = gre_tnl_flags_to_gre_flags(p.i_flags);
83195f5c64cSTom Herbert 	p.o_flags = gre_tnl_flags_to_gre_flags(p.o_flags);
832c5441932SPravin B Shelar 
833c5441932SPravin B Shelar 	if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p)))
834c5441932SPravin B Shelar 		return -EFAULT;
835a0efab67SXin Long 
8361da177e4SLinus Torvalds 	return 0;
8371da177e4SLinus Torvalds }
8381da177e4SLinus Torvalds 
8391da177e4SLinus Torvalds /* Nice toy. Unfortunately, useless in real life :-)
8401da177e4SLinus Torvalds    It allows to construct virtual multiprotocol broadcast "LAN"
8411da177e4SLinus Torvalds    over the Internet, provided multicast routing is tuned.
8421da177e4SLinus Torvalds 
8431da177e4SLinus Torvalds 
8441da177e4SLinus Torvalds    I have no idea was this bicycle invented before me,
8451da177e4SLinus Torvalds    so that I had to set ARPHRD_IPGRE to a random value.
8461da177e4SLinus Torvalds    I have an impression, that Cisco could make something similar,
8471da177e4SLinus Torvalds    but this feature is apparently missing in IOS<=11.2(8).
8481da177e4SLinus Torvalds 
8491da177e4SLinus Torvalds    I set up 10.66.66/24 and fec0:6666:6666::0/96 as virtual networks
8501da177e4SLinus Torvalds    with broadcast 224.66.66.66. If you have access to mbone, play with me :-)
8511da177e4SLinus Torvalds 
8521da177e4SLinus Torvalds    ping -t 255 224.66.66.66
8531da177e4SLinus Torvalds 
8541da177e4SLinus Torvalds    If nobody answers, mbone does not work.
8551da177e4SLinus Torvalds 
8561da177e4SLinus Torvalds    ip tunnel add Universe mode gre remote 224.66.66.66 local <Your_real_addr> ttl 255
8571da177e4SLinus Torvalds    ip addr add 10.66.66.<somewhat>/24 dev Universe
8581da177e4SLinus Torvalds    ifconfig Universe up
8591da177e4SLinus Torvalds    ifconfig Universe add fe80::<Your_real_addr>/10
8601da177e4SLinus Torvalds    ifconfig Universe add fec0:6666:6666::<Your_real_addr>/96
8611da177e4SLinus Torvalds    ftp 10.66.66.66
8621da177e4SLinus Torvalds    ...
8631da177e4SLinus Torvalds    ftp fec0:6666:6666::193.233.7.65
8641da177e4SLinus Torvalds    ...
8651da177e4SLinus Torvalds  */
8663b04dddeSStephen Hemminger static int ipgre_header(struct sk_buff *skb, struct net_device *dev,
8673b04dddeSStephen Hemminger 			unsigned short type,
8681507850bSEric Dumazet 			const void *daddr, const void *saddr, unsigned int len)
8691da177e4SLinus Torvalds {
8702941a486SPatrick McHardy 	struct ip_tunnel *t = netdev_priv(dev);
871c5441932SPravin B Shelar 	struct iphdr *iph;
872c5441932SPravin B Shelar 	struct gre_base_hdr *greh;
873c5441932SPravin B Shelar 
874d58ff351SJohannes Berg 	iph = skb_push(skb, t->hlen + sizeof(*iph));
875c5441932SPravin B Shelar 	greh = (struct gre_base_hdr *)(iph+1);
87695f5c64cSTom Herbert 	greh->flags = gre_tnl_flags_to_gre_flags(t->parms.o_flags);
877c5441932SPravin B Shelar 	greh->protocol = htons(type);
8781da177e4SLinus Torvalds 
8791da177e4SLinus Torvalds 	memcpy(iph, &t->parms.iph, sizeof(struct iphdr));
8801da177e4SLinus Torvalds 
881c5441932SPravin B Shelar 	/* Set the source hardware address. */
8821da177e4SLinus Torvalds 	if (saddr)
8831da177e4SLinus Torvalds 		memcpy(&iph->saddr, saddr, 4);
8846d55cb91STimo Teräs 	if (daddr)
8851da177e4SLinus Torvalds 		memcpy(&iph->daddr, daddr, 4);
8866d55cb91STimo Teräs 	if (iph->daddr)
88777a482bdSTimo Teräs 		return t->hlen + sizeof(*iph);
8881da177e4SLinus Torvalds 
889c5441932SPravin B Shelar 	return -(t->hlen + sizeof(*iph));
8901da177e4SLinus Torvalds }
8911da177e4SLinus Torvalds 
8926a5f44d7STimo Teras static int ipgre_header_parse(const struct sk_buff *skb, unsigned char *haddr)
8936a5f44d7STimo Teras {
894b71d1d42SEric Dumazet 	const struct iphdr *iph = (const struct iphdr *) skb_mac_header(skb);
8956a5f44d7STimo Teras 	memcpy(haddr, &iph->saddr, 4);
8966a5f44d7STimo Teras 	return 4;
8976a5f44d7STimo Teras }
8986a5f44d7STimo Teras 
8993b04dddeSStephen Hemminger static const struct header_ops ipgre_header_ops = {
9003b04dddeSStephen Hemminger 	.create	= ipgre_header,
9016a5f44d7STimo Teras 	.parse	= ipgre_header_parse,
9023b04dddeSStephen Hemminger };
9033b04dddeSStephen Hemminger 
9046a5f44d7STimo Teras #ifdef CONFIG_NET_IPGRE_BROADCAST
9051da177e4SLinus Torvalds static int ipgre_open(struct net_device *dev)
9061da177e4SLinus Torvalds {
9072941a486SPatrick McHardy 	struct ip_tunnel *t = netdev_priv(dev);
9081da177e4SLinus Torvalds 
909f97c1e0cSJoe Perches 	if (ipv4_is_multicast(t->parms.iph.daddr)) {
910cbb1e85fSDavid S. Miller 		struct flowi4 fl4;
911cbb1e85fSDavid S. Miller 		struct rtable *rt;
912cbb1e85fSDavid S. Miller 
913b57708adSNicolas Dichtel 		rt = ip_route_output_gre(t->net, &fl4,
91478fbfd8aSDavid S. Miller 					 t->parms.iph.daddr,
91578fbfd8aSDavid S. Miller 					 t->parms.iph.saddr,
91678fbfd8aSDavid S. Miller 					 t->parms.o_key,
91778fbfd8aSDavid S. Miller 					 RT_TOS(t->parms.iph.tos),
91878fbfd8aSDavid S. Miller 					 t->parms.link);
919b23dd4feSDavid S. Miller 		if (IS_ERR(rt))
9201da177e4SLinus Torvalds 			return -EADDRNOTAVAIL;
921d8d1f30bSChangli Gao 		dev = rt->dst.dev;
9221da177e4SLinus Torvalds 		ip_rt_put(rt);
92351456b29SIan Morris 		if (!__in_dev_get_rtnl(dev))
9241da177e4SLinus Torvalds 			return -EADDRNOTAVAIL;
9251da177e4SLinus Torvalds 		t->mlink = dev->ifindex;
926e5ed6399SHerbert Xu 		ip_mc_inc_group(__in_dev_get_rtnl(dev), t->parms.iph.daddr);
9271da177e4SLinus Torvalds 	}
9281da177e4SLinus Torvalds 	return 0;
9291da177e4SLinus Torvalds }
9301da177e4SLinus Torvalds 
9311da177e4SLinus Torvalds static int ipgre_close(struct net_device *dev)
9321da177e4SLinus Torvalds {
9332941a486SPatrick McHardy 	struct ip_tunnel *t = netdev_priv(dev);
934b8c26a33SStephen Hemminger 
935f97c1e0cSJoe Perches 	if (ipv4_is_multicast(t->parms.iph.daddr) && t->mlink) {
9367fee0ca2SDenis V. Lunev 		struct in_device *in_dev;
937b57708adSNicolas Dichtel 		in_dev = inetdev_by_index(t->net, t->mlink);
9388723e1b4SEric Dumazet 		if (in_dev)
9391da177e4SLinus Torvalds 			ip_mc_dec_group(in_dev, t->parms.iph.daddr);
9401da177e4SLinus Torvalds 	}
9411da177e4SLinus Torvalds 	return 0;
9421da177e4SLinus Torvalds }
9431da177e4SLinus Torvalds #endif
9441da177e4SLinus Torvalds 
945b8c26a33SStephen Hemminger static const struct net_device_ops ipgre_netdev_ops = {
946b8c26a33SStephen Hemminger 	.ndo_init		= ipgre_tunnel_init,
947c5441932SPravin B Shelar 	.ndo_uninit		= ip_tunnel_uninit,
948b8c26a33SStephen Hemminger #ifdef CONFIG_NET_IPGRE_BROADCAST
949b8c26a33SStephen Hemminger 	.ndo_open		= ipgre_open,
950b8c26a33SStephen Hemminger 	.ndo_stop		= ipgre_close,
951b8c26a33SStephen Hemminger #endif
952c5441932SPravin B Shelar 	.ndo_start_xmit		= ipgre_xmit,
953b8c26a33SStephen Hemminger 	.ndo_do_ioctl		= ipgre_tunnel_ioctl,
954c5441932SPravin B Shelar 	.ndo_change_mtu		= ip_tunnel_change_mtu,
955c5441932SPravin B Shelar 	.ndo_get_stats64	= ip_tunnel_get_stats64,
9561e99584bSNicolas Dichtel 	.ndo_get_iflink		= ip_tunnel_get_iflink,
957b8c26a33SStephen Hemminger };
958b8c26a33SStephen Hemminger 
9596b78f16eSEric Dumazet #define GRE_FEATURES (NETIF_F_SG |		\
9606b78f16eSEric Dumazet 		      NETIF_F_FRAGLIST |	\
9616b78f16eSEric Dumazet 		      NETIF_F_HIGHDMA |		\
9626b78f16eSEric Dumazet 		      NETIF_F_HW_CSUM)
9636b78f16eSEric Dumazet 
9641da177e4SLinus Torvalds static void ipgre_tunnel_setup(struct net_device *dev)
9651da177e4SLinus Torvalds {
966b8c26a33SStephen Hemminger 	dev->netdev_ops		= &ipgre_netdev_ops;
9675a455275SNicolas Dichtel 	dev->type		= ARPHRD_IPGRE;
968c5441932SPravin B Shelar 	ip_tunnel_setup(dev, ipgre_net_id);
969c5441932SPravin B Shelar }
9701da177e4SLinus Torvalds 
971c5441932SPravin B Shelar static void __gre_tunnel_init(struct net_device *dev)
972c5441932SPravin B Shelar {
973c5441932SPravin B Shelar 	struct ip_tunnel *tunnel;
9744565e991STom Herbert 	int t_hlen;
975c5441932SPravin B Shelar 
976c5441932SPravin B Shelar 	tunnel = netdev_priv(dev);
97795f5c64cSTom Herbert 	tunnel->tun_hlen = gre_calc_hlen(tunnel->parms.o_flags);
978c5441932SPravin B Shelar 	tunnel->parms.iph.protocol = IPPROTO_GRE;
979c5441932SPravin B Shelar 
9804565e991STom Herbert 	tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen;
9814565e991STom Herbert 
9824565e991STom Herbert 	t_hlen = tunnel->hlen + sizeof(struct iphdr);
9834565e991STom Herbert 
984b57708adSNicolas Dichtel 	dev->features		|= GRE_FEATURES;
9856b78f16eSEric Dumazet 	dev->hw_features	|= GRE_FEATURES;
986c5441932SPravin B Shelar 
987c5441932SPravin B Shelar 	if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) {
988a0ca153fSAlexander Duyck 		/* TCP offload with GRE SEQ is not supported, nor
989a0ca153fSAlexander Duyck 		 * can we support 2 levels of outer headers requiring
990a0ca153fSAlexander Duyck 		 * an update.
991a0ca153fSAlexander Duyck 		 */
992a0ca153fSAlexander Duyck 		if (!(tunnel->parms.o_flags & TUNNEL_CSUM) ||
993a0ca153fSAlexander Duyck 		    (tunnel->encap.type == TUNNEL_ENCAP_NONE)) {
994c5441932SPravin B Shelar 			dev->features    |= NETIF_F_GSO_SOFTWARE;
995c5441932SPravin B Shelar 			dev->hw_features |= NETIF_F_GSO_SOFTWARE;
996a0ca153fSAlexander Duyck 		}
997a0ca153fSAlexander Duyck 
998c5441932SPravin B Shelar 		/* Can use a lockless transmit, unless we generate
999c5441932SPravin B Shelar 		 * output sequences
1000c5441932SPravin B Shelar 		 */
1001c5441932SPravin B Shelar 		dev->features |= NETIF_F_LLTX;
1002c5441932SPravin B Shelar 	}
10031da177e4SLinus Torvalds }
10041da177e4SLinus Torvalds 
10051da177e4SLinus Torvalds static int ipgre_tunnel_init(struct net_device *dev)
10061da177e4SLinus Torvalds {
1007c5441932SPravin B Shelar 	struct ip_tunnel *tunnel = netdev_priv(dev);
1008c5441932SPravin B Shelar 	struct iphdr *iph = &tunnel->parms.iph;
10091da177e4SLinus Torvalds 
1010c5441932SPravin B Shelar 	__gre_tunnel_init(dev);
10111da177e4SLinus Torvalds 
1012c5441932SPravin B Shelar 	memcpy(dev->dev_addr, &iph->saddr, 4);
1013c5441932SPravin B Shelar 	memcpy(dev->broadcast, &iph->daddr, 4);
10141da177e4SLinus Torvalds 
1015c5441932SPravin B Shelar 	dev->flags		= IFF_NOARP;
101602875878SEric Dumazet 	netif_keep_dst(dev);
1017c5441932SPravin B Shelar 	dev->addr_len		= 4;
10181da177e4SLinus Torvalds 
1019a64b04d8SJiri Benc 	if (iph->daddr && !tunnel->collect_md) {
10201da177e4SLinus Torvalds #ifdef CONFIG_NET_IPGRE_BROADCAST
1021f97c1e0cSJoe Perches 		if (ipv4_is_multicast(iph->daddr)) {
10221da177e4SLinus Torvalds 			if (!iph->saddr)
10231da177e4SLinus Torvalds 				return -EINVAL;
10241da177e4SLinus Torvalds 			dev->flags = IFF_BROADCAST;
10253b04dddeSStephen Hemminger 			dev->header_ops = &ipgre_header_ops;
10261da177e4SLinus Torvalds 		}
10271da177e4SLinus Torvalds #endif
1028a64b04d8SJiri Benc 	} else if (!tunnel->collect_md) {
10296a5f44d7STimo Teras 		dev->header_ops = &ipgre_header_ops;
1030a64b04d8SJiri Benc 	}
10311da177e4SLinus Torvalds 
1032c5441932SPravin B Shelar 	return ip_tunnel_init(dev);
103360769a5dSEric Dumazet }
103460769a5dSEric Dumazet 
10359f57c67cSPravin B Shelar static const struct gre_protocol ipgre_protocol = {
10369f57c67cSPravin B Shelar 	.handler     = gre_rcv,
10379f57c67cSPravin B Shelar 	.err_handler = gre_err,
10381da177e4SLinus Torvalds };
10391da177e4SLinus Torvalds 
10402c8c1e72SAlexey Dobriyan static int __net_init ipgre_init_net(struct net *net)
104159a4c759SPavel Emelyanov {
1042c5441932SPravin B Shelar 	return ip_tunnel_init_net(net, ipgre_net_id, &ipgre_link_ops, NULL);
104359a4c759SPavel Emelyanov }
104459a4c759SPavel Emelyanov 
104564bc1781SEric Dumazet static void __net_exit ipgre_exit_batch_net(struct list_head *list_net)
104659a4c759SPavel Emelyanov {
104764bc1781SEric Dumazet 	ip_tunnel_delete_nets(list_net, ipgre_net_id, &ipgre_link_ops);
104859a4c759SPavel Emelyanov }
104959a4c759SPavel Emelyanov 
105059a4c759SPavel Emelyanov static struct pernet_operations ipgre_net_ops = {
105159a4c759SPavel Emelyanov 	.init = ipgre_init_net,
105264bc1781SEric Dumazet 	.exit_batch = ipgre_exit_batch_net,
1053cfb8fbf2SEric W. Biederman 	.id   = &ipgre_net_id,
1054c5441932SPravin B Shelar 	.size = sizeof(struct ip_tunnel_net),
105559a4c759SPavel Emelyanov };
10561da177e4SLinus Torvalds 
1057a8b8a889SMatthias Schiffer static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[],
1058a8b8a889SMatthias Schiffer 				 struct netlink_ext_ack *extack)
1059c19e654dSHerbert Xu {
1060c19e654dSHerbert Xu 	__be16 flags;
1061c19e654dSHerbert Xu 
1062c19e654dSHerbert Xu 	if (!data)
1063c19e654dSHerbert Xu 		return 0;
1064c19e654dSHerbert Xu 
1065c19e654dSHerbert Xu 	flags = 0;
1066c19e654dSHerbert Xu 	if (data[IFLA_GRE_IFLAGS])
1067c19e654dSHerbert Xu 		flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]);
1068c19e654dSHerbert Xu 	if (data[IFLA_GRE_OFLAGS])
1069c19e654dSHerbert Xu 		flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]);
1070c19e654dSHerbert Xu 	if (flags & (GRE_VERSION|GRE_ROUTING))
1071c19e654dSHerbert Xu 		return -EINVAL;
1072c19e654dSHerbert Xu 
1073946b636fSJiri Benc 	if (data[IFLA_GRE_COLLECT_METADATA] &&
1074946b636fSJiri Benc 	    data[IFLA_GRE_ENCAP_TYPE] &&
1075946b636fSJiri Benc 	    nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]) != TUNNEL_ENCAP_NONE)
1076946b636fSJiri Benc 		return -EINVAL;
1077946b636fSJiri Benc 
1078c19e654dSHerbert Xu 	return 0;
1079c19e654dSHerbert Xu }
1080c19e654dSHerbert Xu 
1081a8b8a889SMatthias Schiffer static int ipgre_tap_validate(struct nlattr *tb[], struct nlattr *data[],
1082a8b8a889SMatthias Schiffer 			      struct netlink_ext_ack *extack)
1083e1a80002SHerbert Xu {
1084e1a80002SHerbert Xu 	__be32 daddr;
1085e1a80002SHerbert Xu 
1086e1a80002SHerbert Xu 	if (tb[IFLA_ADDRESS]) {
1087e1a80002SHerbert Xu 		if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
1088e1a80002SHerbert Xu 			return -EINVAL;
1089e1a80002SHerbert Xu 		if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
1090e1a80002SHerbert Xu 			return -EADDRNOTAVAIL;
1091e1a80002SHerbert Xu 	}
1092e1a80002SHerbert Xu 
1093e1a80002SHerbert Xu 	if (!data)
1094e1a80002SHerbert Xu 		goto out;
1095e1a80002SHerbert Xu 
1096e1a80002SHerbert Xu 	if (data[IFLA_GRE_REMOTE]) {
1097e1a80002SHerbert Xu 		memcpy(&daddr, nla_data(data[IFLA_GRE_REMOTE]), 4);
1098e1a80002SHerbert Xu 		if (!daddr)
1099e1a80002SHerbert Xu 			return -EINVAL;
1100e1a80002SHerbert Xu 	}
1101e1a80002SHerbert Xu 
1102e1a80002SHerbert Xu out:
1103a8b8a889SMatthias Schiffer 	return ipgre_tunnel_validate(tb, data, extack);
1104e1a80002SHerbert Xu }
1105e1a80002SHerbert Xu 
110684e54fe0SWilliam Tu static int erspan_validate(struct nlattr *tb[], struct nlattr *data[],
110784e54fe0SWilliam Tu 			   struct netlink_ext_ack *extack)
110884e54fe0SWilliam Tu {
110984e54fe0SWilliam Tu 	__be16 flags = 0;
111084e54fe0SWilliam Tu 	int ret;
111184e54fe0SWilliam Tu 
111284e54fe0SWilliam Tu 	if (!data)
111384e54fe0SWilliam Tu 		return 0;
111484e54fe0SWilliam Tu 
111584e54fe0SWilliam Tu 	ret = ipgre_tap_validate(tb, data, extack);
111684e54fe0SWilliam Tu 	if (ret)
111784e54fe0SWilliam Tu 		return ret;
111884e54fe0SWilliam Tu 
111984e54fe0SWilliam Tu 	/* ERSPAN should only have GRE sequence and key flag */
11201a66a836SWilliam Tu 	if (data[IFLA_GRE_OFLAGS])
112184e54fe0SWilliam Tu 		flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]);
11221a66a836SWilliam Tu 	if (data[IFLA_GRE_IFLAGS])
112384e54fe0SWilliam Tu 		flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]);
11241a66a836SWilliam Tu 	if (!data[IFLA_GRE_COLLECT_METADATA] &&
11251a66a836SWilliam Tu 	    flags != (GRE_SEQ | GRE_KEY))
112684e54fe0SWilliam Tu 		return -EINVAL;
112784e54fe0SWilliam Tu 
112884e54fe0SWilliam Tu 	/* ERSPAN Session ID only has 10-bit. Since we reuse
112984e54fe0SWilliam Tu 	 * 32-bit key field as ID, check it's range.
113084e54fe0SWilliam Tu 	 */
113184e54fe0SWilliam Tu 	if (data[IFLA_GRE_IKEY] &&
113284e54fe0SWilliam Tu 	    (ntohl(nla_get_be32(data[IFLA_GRE_IKEY])) & ~ID_MASK))
113384e54fe0SWilliam Tu 		return -EINVAL;
113484e54fe0SWilliam Tu 
113584e54fe0SWilliam Tu 	if (data[IFLA_GRE_OKEY] &&
113684e54fe0SWilliam Tu 	    (ntohl(nla_get_be32(data[IFLA_GRE_OKEY])) & ~ID_MASK))
113784e54fe0SWilliam Tu 		return -EINVAL;
113884e54fe0SWilliam Tu 
113984e54fe0SWilliam Tu 	return 0;
114084e54fe0SWilliam Tu }
114184e54fe0SWilliam Tu 
114222a59be8SPhilip Prindeville static int ipgre_netlink_parms(struct net_device *dev,
11432e15ea39SPravin B Shelar 				struct nlattr *data[],
11442e15ea39SPravin B Shelar 				struct nlattr *tb[],
11459830ad4cSCraig Gallek 				struct ip_tunnel_parm *parms,
11469830ad4cSCraig Gallek 				__u32 *fwmark)
1147c19e654dSHerbert Xu {
114822a59be8SPhilip Prindeville 	struct ip_tunnel *t = netdev_priv(dev);
114922a59be8SPhilip Prindeville 
11507bb82d92SHerbert Xu 	memset(parms, 0, sizeof(*parms));
1151c19e654dSHerbert Xu 
1152c19e654dSHerbert Xu 	parms->iph.protocol = IPPROTO_GRE;
1153c19e654dSHerbert Xu 
1154c19e654dSHerbert Xu 	if (!data)
115522a59be8SPhilip Prindeville 		return 0;
1156c19e654dSHerbert Xu 
1157c19e654dSHerbert Xu 	if (data[IFLA_GRE_LINK])
1158c19e654dSHerbert Xu 		parms->link = nla_get_u32(data[IFLA_GRE_LINK]);
1159c19e654dSHerbert Xu 
1160c19e654dSHerbert Xu 	if (data[IFLA_GRE_IFLAGS])
1161c5441932SPravin B Shelar 		parms->i_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_IFLAGS]));
1162c19e654dSHerbert Xu 
1163c19e654dSHerbert Xu 	if (data[IFLA_GRE_OFLAGS])
1164c5441932SPravin B Shelar 		parms->o_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_OFLAGS]));
1165c19e654dSHerbert Xu 
1166c19e654dSHerbert Xu 	if (data[IFLA_GRE_IKEY])
1167c19e654dSHerbert Xu 		parms->i_key = nla_get_be32(data[IFLA_GRE_IKEY]);
1168c19e654dSHerbert Xu 
1169c19e654dSHerbert Xu 	if (data[IFLA_GRE_OKEY])
1170c19e654dSHerbert Xu 		parms->o_key = nla_get_be32(data[IFLA_GRE_OKEY]);
1171c19e654dSHerbert Xu 
1172c19e654dSHerbert Xu 	if (data[IFLA_GRE_LOCAL])
117367b61f6cSJiri Benc 		parms->iph.saddr = nla_get_in_addr(data[IFLA_GRE_LOCAL]);
1174c19e654dSHerbert Xu 
1175c19e654dSHerbert Xu 	if (data[IFLA_GRE_REMOTE])
117667b61f6cSJiri Benc 		parms->iph.daddr = nla_get_in_addr(data[IFLA_GRE_REMOTE]);
1177c19e654dSHerbert Xu 
1178c19e654dSHerbert Xu 	if (data[IFLA_GRE_TTL])
1179c19e654dSHerbert Xu 		parms->iph.ttl = nla_get_u8(data[IFLA_GRE_TTL]);
1180c19e654dSHerbert Xu 
1181c19e654dSHerbert Xu 	if (data[IFLA_GRE_TOS])
1182c19e654dSHerbert Xu 		parms->iph.tos = nla_get_u8(data[IFLA_GRE_TOS]);
1183c19e654dSHerbert Xu 
118422a59be8SPhilip Prindeville 	if (!data[IFLA_GRE_PMTUDISC] || nla_get_u8(data[IFLA_GRE_PMTUDISC])) {
118522a59be8SPhilip Prindeville 		if (t->ignore_df)
118622a59be8SPhilip Prindeville 			return -EINVAL;
1187c19e654dSHerbert Xu 		parms->iph.frag_off = htons(IP_DF);
118822a59be8SPhilip Prindeville 	}
11892e15ea39SPravin B Shelar 
11902e15ea39SPravin B Shelar 	if (data[IFLA_GRE_COLLECT_METADATA]) {
11912e15ea39SPravin B Shelar 		t->collect_md = true;
1192e271c7b4SJiri Benc 		if (dev->type == ARPHRD_IPGRE)
1193e271c7b4SJiri Benc 			dev->type = ARPHRD_NONE;
11942e15ea39SPravin B Shelar 	}
119522a59be8SPhilip Prindeville 
119622a59be8SPhilip Prindeville 	if (data[IFLA_GRE_IGNORE_DF]) {
119722a59be8SPhilip Prindeville 		if (nla_get_u8(data[IFLA_GRE_IGNORE_DF])
119822a59be8SPhilip Prindeville 		  && (parms->iph.frag_off & htons(IP_DF)))
119922a59be8SPhilip Prindeville 			return -EINVAL;
120022a59be8SPhilip Prindeville 		t->ignore_df = !!nla_get_u8(data[IFLA_GRE_IGNORE_DF]);
120122a59be8SPhilip Prindeville 	}
120222a59be8SPhilip Prindeville 
12039830ad4cSCraig Gallek 	if (data[IFLA_GRE_FWMARK])
12049830ad4cSCraig Gallek 		*fwmark = nla_get_u32(data[IFLA_GRE_FWMARK]);
12059830ad4cSCraig Gallek 
1206f551c91dSWilliam Tu 	if (data[IFLA_GRE_ERSPAN_VER]) {
1207f551c91dSWilliam Tu 		t->erspan_ver = nla_get_u8(data[IFLA_GRE_ERSPAN_VER]);
1208f551c91dSWilliam Tu 
1209f551c91dSWilliam Tu 		if (t->erspan_ver != 1 && t->erspan_ver != 2)
1210f551c91dSWilliam Tu 			return -EINVAL;
1211f551c91dSWilliam Tu 	}
1212f551c91dSWilliam Tu 
1213f551c91dSWilliam Tu 	if (t->erspan_ver == 1) {
121484e54fe0SWilliam Tu 		if (data[IFLA_GRE_ERSPAN_INDEX]) {
121584e54fe0SWilliam Tu 			t->index = nla_get_u32(data[IFLA_GRE_ERSPAN_INDEX]);
121684e54fe0SWilliam Tu 			if (t->index & ~INDEX_MASK)
121784e54fe0SWilliam Tu 				return -EINVAL;
121884e54fe0SWilliam Tu 		}
1219f551c91dSWilliam Tu 	} else if (t->erspan_ver == 2) {
1220f551c91dSWilliam Tu 		if (data[IFLA_GRE_ERSPAN_DIR]) {
1221f551c91dSWilliam Tu 			t->dir = nla_get_u8(data[IFLA_GRE_ERSPAN_DIR]);
1222f551c91dSWilliam Tu 			if (t->dir & ~(DIR_MASK >> DIR_OFFSET))
1223f551c91dSWilliam Tu 				return -EINVAL;
1224f551c91dSWilliam Tu 		}
1225f551c91dSWilliam Tu 		if (data[IFLA_GRE_ERSPAN_HWID]) {
1226f551c91dSWilliam Tu 			t->hwid = nla_get_u16(data[IFLA_GRE_ERSPAN_HWID]);
1227f551c91dSWilliam Tu 			if (t->hwid & ~(HWID_MASK >> HWID_OFFSET))
1228f551c91dSWilliam Tu 				return -EINVAL;
1229f551c91dSWilliam Tu 		}
1230f551c91dSWilliam Tu 	}
123184e54fe0SWilliam Tu 
123222a59be8SPhilip Prindeville 	return 0;
1233c19e654dSHerbert Xu }
1234c19e654dSHerbert Xu 
12354565e991STom Herbert /* This function returns true when ENCAP attributes are present in the nl msg */
12364565e991STom Herbert static bool ipgre_netlink_encap_parms(struct nlattr *data[],
12374565e991STom Herbert 				      struct ip_tunnel_encap *ipencap)
12384565e991STom Herbert {
12394565e991STom Herbert 	bool ret = false;
12404565e991STom Herbert 
12414565e991STom Herbert 	memset(ipencap, 0, sizeof(*ipencap));
12424565e991STom Herbert 
12434565e991STom Herbert 	if (!data)
12444565e991STom Herbert 		return ret;
12454565e991STom Herbert 
12464565e991STom Herbert 	if (data[IFLA_GRE_ENCAP_TYPE]) {
12474565e991STom Herbert 		ret = true;
12484565e991STom Herbert 		ipencap->type = nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]);
12494565e991STom Herbert 	}
12504565e991STom Herbert 
12514565e991STom Herbert 	if (data[IFLA_GRE_ENCAP_FLAGS]) {
12524565e991STom Herbert 		ret = true;
12534565e991STom Herbert 		ipencap->flags = nla_get_u16(data[IFLA_GRE_ENCAP_FLAGS]);
12544565e991STom Herbert 	}
12554565e991STom Herbert 
12564565e991STom Herbert 	if (data[IFLA_GRE_ENCAP_SPORT]) {
12574565e991STom Herbert 		ret = true;
12583e97fa70SSabrina Dubroca 		ipencap->sport = nla_get_be16(data[IFLA_GRE_ENCAP_SPORT]);
12594565e991STom Herbert 	}
12604565e991STom Herbert 
12614565e991STom Herbert 	if (data[IFLA_GRE_ENCAP_DPORT]) {
12624565e991STom Herbert 		ret = true;
12633e97fa70SSabrina Dubroca 		ipencap->dport = nla_get_be16(data[IFLA_GRE_ENCAP_DPORT]);
12644565e991STom Herbert 	}
12654565e991STom Herbert 
12664565e991STom Herbert 	return ret;
12674565e991STom Herbert }
12684565e991STom Herbert 
1269c5441932SPravin B Shelar static int gre_tap_init(struct net_device *dev)
1270e1a80002SHerbert Xu {
1271c5441932SPravin B Shelar 	__gre_tunnel_init(dev);
1272bec94d43Sstephen hemminger 	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
1273d51711c0SXin Long 	netif_keep_dst(dev);
1274e1a80002SHerbert Xu 
1275c5441932SPravin B Shelar 	return ip_tunnel_init(dev);
1276e1a80002SHerbert Xu }
1277e1a80002SHerbert Xu 
1278c5441932SPravin B Shelar static const struct net_device_ops gre_tap_netdev_ops = {
1279c5441932SPravin B Shelar 	.ndo_init		= gre_tap_init,
1280c5441932SPravin B Shelar 	.ndo_uninit		= ip_tunnel_uninit,
1281c5441932SPravin B Shelar 	.ndo_start_xmit		= gre_tap_xmit,
1282b8c26a33SStephen Hemminger 	.ndo_set_mac_address 	= eth_mac_addr,
1283b8c26a33SStephen Hemminger 	.ndo_validate_addr	= eth_validate_addr,
1284c5441932SPravin B Shelar 	.ndo_change_mtu		= ip_tunnel_change_mtu,
1285c5441932SPravin B Shelar 	.ndo_get_stats64	= ip_tunnel_get_stats64,
12861e99584bSNicolas Dichtel 	.ndo_get_iflink		= ip_tunnel_get_iflink,
1287fc4099f1SPravin B Shelar 	.ndo_fill_metadata_dst	= gre_fill_metadata_dst,
1288b8c26a33SStephen Hemminger };
1289b8c26a33SStephen Hemminger 
129084e54fe0SWilliam Tu static int erspan_tunnel_init(struct net_device *dev)
129184e54fe0SWilliam Tu {
129284e54fe0SWilliam Tu 	struct ip_tunnel *tunnel = netdev_priv(dev);
129384e54fe0SWilliam Tu 	int t_hlen;
129484e54fe0SWilliam Tu 
129584e54fe0SWilliam Tu 	tunnel->tun_hlen = 8;
129684e54fe0SWilliam Tu 	tunnel->parms.iph.protocol = IPPROTO_GRE;
1297c122fda2SXin Long 	tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen +
1298f551c91dSWilliam Tu 		       erspan_hdr_len(tunnel->erspan_ver);
1299c122fda2SXin Long 	t_hlen = tunnel->hlen + sizeof(struct iphdr);
130084e54fe0SWilliam Tu 
130184e54fe0SWilliam Tu 	dev->features		|= GRE_FEATURES;
130284e54fe0SWilliam Tu 	dev->hw_features	|= GRE_FEATURES;
130384e54fe0SWilliam Tu 	dev->priv_flags		|= IFF_LIVE_ADDR_CHANGE;
1304c84bed44SXin Long 	netif_keep_dst(dev);
130584e54fe0SWilliam Tu 
130684e54fe0SWilliam Tu 	return ip_tunnel_init(dev);
130784e54fe0SWilliam Tu }
130884e54fe0SWilliam Tu 
130984e54fe0SWilliam Tu static const struct net_device_ops erspan_netdev_ops = {
131084e54fe0SWilliam Tu 	.ndo_init		= erspan_tunnel_init,
131184e54fe0SWilliam Tu 	.ndo_uninit		= ip_tunnel_uninit,
131284e54fe0SWilliam Tu 	.ndo_start_xmit		= erspan_xmit,
131384e54fe0SWilliam Tu 	.ndo_set_mac_address	= eth_mac_addr,
131484e54fe0SWilliam Tu 	.ndo_validate_addr	= eth_validate_addr,
131584e54fe0SWilliam Tu 	.ndo_change_mtu		= ip_tunnel_change_mtu,
131684e54fe0SWilliam Tu 	.ndo_get_stats64	= ip_tunnel_get_stats64,
131784e54fe0SWilliam Tu 	.ndo_get_iflink		= ip_tunnel_get_iflink,
131884e54fe0SWilliam Tu 	.ndo_fill_metadata_dst	= gre_fill_metadata_dst,
131984e54fe0SWilliam Tu };
132084e54fe0SWilliam Tu 
1321e1a80002SHerbert Xu static void ipgre_tap_setup(struct net_device *dev)
1322e1a80002SHerbert Xu {
1323e1a80002SHerbert Xu 	ether_setup(dev);
1324cfddd4c3SXin Long 	dev->max_mtu = 0;
1325c5441932SPravin B Shelar 	dev->netdev_ops	= &gre_tap_netdev_ops;
1326d13b161cSJiri Benc 	dev->priv_flags &= ~IFF_TX_SKB_SHARING;
1327f8c1b7ceSstephen hemminger 	dev->priv_flags	|= IFF_LIVE_ADDR_CHANGE;
1328c5441932SPravin B Shelar 	ip_tunnel_setup(dev, gre_tap_net_id);
1329e1a80002SHerbert Xu }
1330e1a80002SHerbert Xu 
1331d1b2a6c4SPetr Machata bool is_gretap_dev(const struct net_device *dev)
1332d1b2a6c4SPetr Machata {
1333d1b2a6c4SPetr Machata 	return dev->netdev_ops == &gre_tap_netdev_ops;
1334d1b2a6c4SPetr Machata }
1335d1b2a6c4SPetr Machata EXPORT_SYMBOL_GPL(is_gretap_dev);
1336d1b2a6c4SPetr Machata 
1337c5441932SPravin B Shelar static int ipgre_newlink(struct net *src_net, struct net_device *dev,
13387a3f4a18SMatthias Schiffer 			 struct nlattr *tb[], struct nlattr *data[],
13397a3f4a18SMatthias Schiffer 			 struct netlink_ext_ack *extack)
1340c19e654dSHerbert Xu {
1341c5441932SPravin B Shelar 	struct ip_tunnel_parm p;
13424565e991STom Herbert 	struct ip_tunnel_encap ipencap;
13439830ad4cSCraig Gallek 	__u32 fwmark = 0;
134422a59be8SPhilip Prindeville 	int err;
13454565e991STom Herbert 
13464565e991STom Herbert 	if (ipgre_netlink_encap_parms(data, &ipencap)) {
13474565e991STom Herbert 		struct ip_tunnel *t = netdev_priv(dev);
134822a59be8SPhilip Prindeville 		err = ip_tunnel_encap_setup(t, &ipencap);
13494565e991STom Herbert 
13504565e991STom Herbert 		if (err < 0)
13514565e991STom Herbert 			return err;
13524565e991STom Herbert 	}
1353c19e654dSHerbert Xu 
13549830ad4cSCraig Gallek 	err = ipgre_netlink_parms(dev, data, tb, &p, &fwmark);
135522a59be8SPhilip Prindeville 	if (err < 0)
135622a59be8SPhilip Prindeville 		return err;
13579830ad4cSCraig Gallek 	return ip_tunnel_newlink(dev, tb, &p, fwmark);
1358c19e654dSHerbert Xu }
1359c19e654dSHerbert Xu 
1360c19e654dSHerbert Xu static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[],
1361ad744b22SMatthias Schiffer 			    struct nlattr *data[],
1362ad744b22SMatthias Schiffer 			    struct netlink_ext_ack *extack)
1363c19e654dSHerbert Xu {
13649830ad4cSCraig Gallek 	struct ip_tunnel *t = netdev_priv(dev);
13654565e991STom Herbert 	struct ip_tunnel_encap ipencap;
13669830ad4cSCraig Gallek 	__u32 fwmark = t->fwmark;
1367dd9d598cSXin Long 	struct ip_tunnel_parm p;
136822a59be8SPhilip Prindeville 	int err;
13694565e991STom Herbert 
13704565e991STom Herbert 	if (ipgre_netlink_encap_parms(data, &ipencap)) {
137122a59be8SPhilip Prindeville 		err = ip_tunnel_encap_setup(t, &ipencap);
13724565e991STom Herbert 
13734565e991STom Herbert 		if (err < 0)
13744565e991STom Herbert 			return err;
13754565e991STom Herbert 	}
1376c19e654dSHerbert Xu 
13779830ad4cSCraig Gallek 	err = ipgre_netlink_parms(dev, data, tb, &p, &fwmark);
137822a59be8SPhilip Prindeville 	if (err < 0)
137922a59be8SPhilip Prindeville 		return err;
1380dd9d598cSXin Long 
1381dd9d598cSXin Long 	err = ip_tunnel_changelink(dev, tb, &p, fwmark);
1382dd9d598cSXin Long 	if (err < 0)
1383dd9d598cSXin Long 		return err;
1384dd9d598cSXin Long 
1385dd9d598cSXin Long 	t->parms.i_flags = p.i_flags;
1386dd9d598cSXin Long 	t->parms.o_flags = p.o_flags;
1387dd9d598cSXin Long 
1388dd9d598cSXin Long 	if (strcmp(dev->rtnl_link_ops->kind, "erspan"))
1389dd9d598cSXin Long 		ipgre_link_update(dev, !tb[IFLA_MTU]);
1390dd9d598cSXin Long 
1391dd9d598cSXin Long 	return 0;
1392c19e654dSHerbert Xu }
1393c19e654dSHerbert Xu 
1394c19e654dSHerbert Xu static size_t ipgre_get_size(const struct net_device *dev)
1395c19e654dSHerbert Xu {
1396c19e654dSHerbert Xu 	return
1397c19e654dSHerbert Xu 		/* IFLA_GRE_LINK */
1398c19e654dSHerbert Xu 		nla_total_size(4) +
1399c19e654dSHerbert Xu 		/* IFLA_GRE_IFLAGS */
1400c19e654dSHerbert Xu 		nla_total_size(2) +
1401c19e654dSHerbert Xu 		/* IFLA_GRE_OFLAGS */
1402c19e654dSHerbert Xu 		nla_total_size(2) +
1403c19e654dSHerbert Xu 		/* IFLA_GRE_IKEY */
1404c19e654dSHerbert Xu 		nla_total_size(4) +
1405c19e654dSHerbert Xu 		/* IFLA_GRE_OKEY */
1406c19e654dSHerbert Xu 		nla_total_size(4) +
1407c19e654dSHerbert Xu 		/* IFLA_GRE_LOCAL */
1408c19e654dSHerbert Xu 		nla_total_size(4) +
1409c19e654dSHerbert Xu 		/* IFLA_GRE_REMOTE */
1410c19e654dSHerbert Xu 		nla_total_size(4) +
1411c19e654dSHerbert Xu 		/* IFLA_GRE_TTL */
1412c19e654dSHerbert Xu 		nla_total_size(1) +
1413c19e654dSHerbert Xu 		/* IFLA_GRE_TOS */
1414c19e654dSHerbert Xu 		nla_total_size(1) +
1415c19e654dSHerbert Xu 		/* IFLA_GRE_PMTUDISC */
1416c19e654dSHerbert Xu 		nla_total_size(1) +
14174565e991STom Herbert 		/* IFLA_GRE_ENCAP_TYPE */
14184565e991STom Herbert 		nla_total_size(2) +
14194565e991STom Herbert 		/* IFLA_GRE_ENCAP_FLAGS */
14204565e991STom Herbert 		nla_total_size(2) +
14214565e991STom Herbert 		/* IFLA_GRE_ENCAP_SPORT */
14224565e991STom Herbert 		nla_total_size(2) +
14234565e991STom Herbert 		/* IFLA_GRE_ENCAP_DPORT */
14244565e991STom Herbert 		nla_total_size(2) +
14252e15ea39SPravin B Shelar 		/* IFLA_GRE_COLLECT_METADATA */
14262e15ea39SPravin B Shelar 		nla_total_size(0) +
142722a59be8SPhilip Prindeville 		/* IFLA_GRE_IGNORE_DF */
142822a59be8SPhilip Prindeville 		nla_total_size(1) +
14299830ad4cSCraig Gallek 		/* IFLA_GRE_FWMARK */
14309830ad4cSCraig Gallek 		nla_total_size(4) +
143184e54fe0SWilliam Tu 		/* IFLA_GRE_ERSPAN_INDEX */
143284e54fe0SWilliam Tu 		nla_total_size(4) +
1433f551c91dSWilliam Tu 		/* IFLA_GRE_ERSPAN_VER */
1434f551c91dSWilliam Tu 		nla_total_size(1) +
1435f551c91dSWilliam Tu 		/* IFLA_GRE_ERSPAN_DIR */
1436f551c91dSWilliam Tu 		nla_total_size(1) +
1437f551c91dSWilliam Tu 		/* IFLA_GRE_ERSPAN_HWID */
1438f551c91dSWilliam Tu 		nla_total_size(2) +
1439c19e654dSHerbert Xu 		0;
1440c19e654dSHerbert Xu }
1441c19e654dSHerbert Xu 
1442c19e654dSHerbert Xu static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev)
1443c19e654dSHerbert Xu {
1444c19e654dSHerbert Xu 	struct ip_tunnel *t = netdev_priv(dev);
1445c19e654dSHerbert Xu 	struct ip_tunnel_parm *p = &t->parms;
1446c19e654dSHerbert Xu 
1447f3756b79SDavid S. Miller 	if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) ||
144895f5c64cSTom Herbert 	    nla_put_be16(skb, IFLA_GRE_IFLAGS,
144995f5c64cSTom Herbert 			 gre_tnl_flags_to_gre_flags(p->i_flags)) ||
145095f5c64cSTom Herbert 	    nla_put_be16(skb, IFLA_GRE_OFLAGS,
145195f5c64cSTom Herbert 			 gre_tnl_flags_to_gre_flags(p->o_flags)) ||
1452f3756b79SDavid S. Miller 	    nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) ||
1453f3756b79SDavid S. Miller 	    nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) ||
1454930345eaSJiri Benc 	    nla_put_in_addr(skb, IFLA_GRE_LOCAL, p->iph.saddr) ||
1455930345eaSJiri Benc 	    nla_put_in_addr(skb, IFLA_GRE_REMOTE, p->iph.daddr) ||
1456f3756b79SDavid S. Miller 	    nla_put_u8(skb, IFLA_GRE_TTL, p->iph.ttl) ||
1457f3756b79SDavid S. Miller 	    nla_put_u8(skb, IFLA_GRE_TOS, p->iph.tos) ||
1458f3756b79SDavid S. Miller 	    nla_put_u8(skb, IFLA_GRE_PMTUDISC,
14599830ad4cSCraig Gallek 		       !!(p->iph.frag_off & htons(IP_DF))) ||
14609830ad4cSCraig Gallek 	    nla_put_u32(skb, IFLA_GRE_FWMARK, t->fwmark))
1461f3756b79SDavid S. Miller 		goto nla_put_failure;
14624565e991STom Herbert 
14634565e991STom Herbert 	if (nla_put_u16(skb, IFLA_GRE_ENCAP_TYPE,
14644565e991STom Herbert 			t->encap.type) ||
14653e97fa70SSabrina Dubroca 	    nla_put_be16(skb, IFLA_GRE_ENCAP_SPORT,
14664565e991STom Herbert 			 t->encap.sport) ||
14673e97fa70SSabrina Dubroca 	    nla_put_be16(skb, IFLA_GRE_ENCAP_DPORT,
14684565e991STom Herbert 			 t->encap.dport) ||
14694565e991STom Herbert 	    nla_put_u16(skb, IFLA_GRE_ENCAP_FLAGS,
1470e1b2cb65STom Herbert 			t->encap.flags))
14714565e991STom Herbert 		goto nla_put_failure;
14724565e991STom Herbert 
147322a59be8SPhilip Prindeville 	if (nla_put_u8(skb, IFLA_GRE_IGNORE_DF, t->ignore_df))
147422a59be8SPhilip Prindeville 		goto nla_put_failure;
147522a59be8SPhilip Prindeville 
14762e15ea39SPravin B Shelar 	if (t->collect_md) {
14772e15ea39SPravin B Shelar 		if (nla_put_flag(skb, IFLA_GRE_COLLECT_METADATA))
14782e15ea39SPravin B Shelar 			goto nla_put_failure;
14792e15ea39SPravin B Shelar 	}
14802e15ea39SPravin B Shelar 
1481f551c91dSWilliam Tu 	if (nla_put_u8(skb, IFLA_GRE_ERSPAN_VER, t->erspan_ver))
1482f551c91dSWilliam Tu 		goto nla_put_failure;
1483f551c91dSWilliam Tu 
1484f551c91dSWilliam Tu 	if (t->erspan_ver == 1) {
148584e54fe0SWilliam Tu 		if (nla_put_u32(skb, IFLA_GRE_ERSPAN_INDEX, t->index))
148684e54fe0SWilliam Tu 			goto nla_put_failure;
1487f551c91dSWilliam Tu 	} else if (t->erspan_ver == 2) {
1488f551c91dSWilliam Tu 		if (nla_put_u8(skb, IFLA_GRE_ERSPAN_DIR, t->dir))
1489f551c91dSWilliam Tu 			goto nla_put_failure;
1490f551c91dSWilliam Tu 		if (nla_put_u16(skb, IFLA_GRE_ERSPAN_HWID, t->hwid))
1491f551c91dSWilliam Tu 			goto nla_put_failure;
1492f551c91dSWilliam Tu 	}
149384e54fe0SWilliam Tu 
1494c19e654dSHerbert Xu 	return 0;
1495c19e654dSHerbert Xu 
1496c19e654dSHerbert Xu nla_put_failure:
1497c19e654dSHerbert Xu 	return -EMSGSIZE;
1498c19e654dSHerbert Xu }
1499c19e654dSHerbert Xu 
150084e54fe0SWilliam Tu static void erspan_setup(struct net_device *dev)
150184e54fe0SWilliam Tu {
150284e54fe0SWilliam Tu 	ether_setup(dev);
150384e54fe0SWilliam Tu 	dev->netdev_ops = &erspan_netdev_ops;
150484e54fe0SWilliam Tu 	dev->priv_flags &= ~IFF_TX_SKB_SHARING;
150584e54fe0SWilliam Tu 	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
150684e54fe0SWilliam Tu 	ip_tunnel_setup(dev, erspan_net_id);
150784e54fe0SWilliam Tu }
150884e54fe0SWilliam Tu 
1509c19e654dSHerbert Xu static const struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = {
1510c19e654dSHerbert Xu 	[IFLA_GRE_LINK]		= { .type = NLA_U32 },
1511c19e654dSHerbert Xu 	[IFLA_GRE_IFLAGS]	= { .type = NLA_U16 },
1512c19e654dSHerbert Xu 	[IFLA_GRE_OFLAGS]	= { .type = NLA_U16 },
1513c19e654dSHerbert Xu 	[IFLA_GRE_IKEY]		= { .type = NLA_U32 },
1514c19e654dSHerbert Xu 	[IFLA_GRE_OKEY]		= { .type = NLA_U32 },
15154d74f8baSPatrick McHardy 	[IFLA_GRE_LOCAL]	= { .len = FIELD_SIZEOF(struct iphdr, saddr) },
15164d74f8baSPatrick McHardy 	[IFLA_GRE_REMOTE]	= { .len = FIELD_SIZEOF(struct iphdr, daddr) },
1517c19e654dSHerbert Xu 	[IFLA_GRE_TTL]		= { .type = NLA_U8 },
1518c19e654dSHerbert Xu 	[IFLA_GRE_TOS]		= { .type = NLA_U8 },
1519c19e654dSHerbert Xu 	[IFLA_GRE_PMTUDISC]	= { .type = NLA_U8 },
15204565e991STom Herbert 	[IFLA_GRE_ENCAP_TYPE]	= { .type = NLA_U16 },
15214565e991STom Herbert 	[IFLA_GRE_ENCAP_FLAGS]	= { .type = NLA_U16 },
15224565e991STom Herbert 	[IFLA_GRE_ENCAP_SPORT]	= { .type = NLA_U16 },
15234565e991STom Herbert 	[IFLA_GRE_ENCAP_DPORT]	= { .type = NLA_U16 },
15242e15ea39SPravin B Shelar 	[IFLA_GRE_COLLECT_METADATA]	= { .type = NLA_FLAG },
152522a59be8SPhilip Prindeville 	[IFLA_GRE_IGNORE_DF]	= { .type = NLA_U8 },
15269830ad4cSCraig Gallek 	[IFLA_GRE_FWMARK]	= { .type = NLA_U32 },
152784e54fe0SWilliam Tu 	[IFLA_GRE_ERSPAN_INDEX]	= { .type = NLA_U32 },
1528f551c91dSWilliam Tu 	[IFLA_GRE_ERSPAN_VER]	= { .type = NLA_U8 },
1529f551c91dSWilliam Tu 	[IFLA_GRE_ERSPAN_DIR]	= { .type = NLA_U8 },
1530f551c91dSWilliam Tu 	[IFLA_GRE_ERSPAN_HWID]	= { .type = NLA_U16 },
1531c19e654dSHerbert Xu };
1532c19e654dSHerbert Xu 
1533c19e654dSHerbert Xu static struct rtnl_link_ops ipgre_link_ops __read_mostly = {
1534c19e654dSHerbert Xu 	.kind		= "gre",
1535c19e654dSHerbert Xu 	.maxtype	= IFLA_GRE_MAX,
1536c19e654dSHerbert Xu 	.policy		= ipgre_policy,
1537c19e654dSHerbert Xu 	.priv_size	= sizeof(struct ip_tunnel),
1538c19e654dSHerbert Xu 	.setup		= ipgre_tunnel_setup,
1539c19e654dSHerbert Xu 	.validate	= ipgre_tunnel_validate,
1540c19e654dSHerbert Xu 	.newlink	= ipgre_newlink,
1541c19e654dSHerbert Xu 	.changelink	= ipgre_changelink,
1542c5441932SPravin B Shelar 	.dellink	= ip_tunnel_dellink,
1543c19e654dSHerbert Xu 	.get_size	= ipgre_get_size,
1544c19e654dSHerbert Xu 	.fill_info	= ipgre_fill_info,
15451728d4faSNicolas Dichtel 	.get_link_net	= ip_tunnel_get_link_net,
1546c19e654dSHerbert Xu };
1547c19e654dSHerbert Xu 
1548e1a80002SHerbert Xu static struct rtnl_link_ops ipgre_tap_ops __read_mostly = {
1549e1a80002SHerbert Xu 	.kind		= "gretap",
1550e1a80002SHerbert Xu 	.maxtype	= IFLA_GRE_MAX,
1551e1a80002SHerbert Xu 	.policy		= ipgre_policy,
1552e1a80002SHerbert Xu 	.priv_size	= sizeof(struct ip_tunnel),
1553e1a80002SHerbert Xu 	.setup		= ipgre_tap_setup,
1554e1a80002SHerbert Xu 	.validate	= ipgre_tap_validate,
1555e1a80002SHerbert Xu 	.newlink	= ipgre_newlink,
1556e1a80002SHerbert Xu 	.changelink	= ipgre_changelink,
1557c5441932SPravin B Shelar 	.dellink	= ip_tunnel_dellink,
1558e1a80002SHerbert Xu 	.get_size	= ipgre_get_size,
1559e1a80002SHerbert Xu 	.fill_info	= ipgre_fill_info,
15601728d4faSNicolas Dichtel 	.get_link_net	= ip_tunnel_get_link_net,
1561e1a80002SHerbert Xu };
1562e1a80002SHerbert Xu 
156384e54fe0SWilliam Tu static struct rtnl_link_ops erspan_link_ops __read_mostly = {
156484e54fe0SWilliam Tu 	.kind		= "erspan",
156584e54fe0SWilliam Tu 	.maxtype	= IFLA_GRE_MAX,
156684e54fe0SWilliam Tu 	.policy		= ipgre_policy,
156784e54fe0SWilliam Tu 	.priv_size	= sizeof(struct ip_tunnel),
156884e54fe0SWilliam Tu 	.setup		= erspan_setup,
156984e54fe0SWilliam Tu 	.validate	= erspan_validate,
157084e54fe0SWilliam Tu 	.newlink	= ipgre_newlink,
157184e54fe0SWilliam Tu 	.changelink	= ipgre_changelink,
157284e54fe0SWilliam Tu 	.dellink	= ip_tunnel_dellink,
157384e54fe0SWilliam Tu 	.get_size	= ipgre_get_size,
157484e54fe0SWilliam Tu 	.fill_info	= ipgre_fill_info,
157584e54fe0SWilliam Tu 	.get_link_net	= ip_tunnel_get_link_net,
157684e54fe0SWilliam Tu };
157784e54fe0SWilliam Tu 
1578b2acd1dcSPravin B Shelar struct net_device *gretap_fb_dev_create(struct net *net, const char *name,
1579b2acd1dcSPravin B Shelar 					u8 name_assign_type)
1580b2acd1dcSPravin B Shelar {
1581b2acd1dcSPravin B Shelar 	struct nlattr *tb[IFLA_MAX + 1];
1582b2acd1dcSPravin B Shelar 	struct net_device *dev;
1583106da663SNicolas Dichtel 	LIST_HEAD(list_kill);
1584b2acd1dcSPravin B Shelar 	struct ip_tunnel *t;
1585b2acd1dcSPravin B Shelar 	int err;
1586b2acd1dcSPravin B Shelar 
1587b2acd1dcSPravin B Shelar 	memset(&tb, 0, sizeof(tb));
1588b2acd1dcSPravin B Shelar 
1589b2acd1dcSPravin B Shelar 	dev = rtnl_create_link(net, name, name_assign_type,
1590b2acd1dcSPravin B Shelar 			       &ipgre_tap_ops, tb);
1591b2acd1dcSPravin B Shelar 	if (IS_ERR(dev))
1592b2acd1dcSPravin B Shelar 		return dev;
1593b2acd1dcSPravin B Shelar 
1594b2acd1dcSPravin B Shelar 	/* Configure flow based GRE device. */
1595b2acd1dcSPravin B Shelar 	t = netdev_priv(dev);
1596b2acd1dcSPravin B Shelar 	t->collect_md = true;
1597b2acd1dcSPravin B Shelar 
15987a3f4a18SMatthias Schiffer 	err = ipgre_newlink(net, dev, tb, NULL, NULL);
1599106da663SNicolas Dichtel 	if (err < 0) {
1600106da663SNicolas Dichtel 		free_netdev(dev);
1601106da663SNicolas Dichtel 		return ERR_PTR(err);
1602106da663SNicolas Dichtel 	}
16037e059158SDavid Wragg 
16047e059158SDavid Wragg 	/* openvswitch users expect packet sizes to be unrestricted,
16057e059158SDavid Wragg 	 * so set the largest MTU we can.
16067e059158SDavid Wragg 	 */
16077e059158SDavid Wragg 	err = __ip_tunnel_change_mtu(dev, IP_MAX_MTU, false);
16087e059158SDavid Wragg 	if (err)
16097e059158SDavid Wragg 		goto out;
16107e059158SDavid Wragg 
1611da6f1da8SNicolas Dichtel 	err = rtnl_configure_link(dev, NULL);
1612da6f1da8SNicolas Dichtel 	if (err < 0)
1613da6f1da8SNicolas Dichtel 		goto out;
1614da6f1da8SNicolas Dichtel 
1615b2acd1dcSPravin B Shelar 	return dev;
1616b2acd1dcSPravin B Shelar out:
1617106da663SNicolas Dichtel 	ip_tunnel_dellink(dev, &list_kill);
1618106da663SNicolas Dichtel 	unregister_netdevice_many(&list_kill);
1619b2acd1dcSPravin B Shelar 	return ERR_PTR(err);
1620b2acd1dcSPravin B Shelar }
1621b2acd1dcSPravin B Shelar EXPORT_SYMBOL_GPL(gretap_fb_dev_create);
1622b2acd1dcSPravin B Shelar 
1623c5441932SPravin B Shelar static int __net_init ipgre_tap_init_net(struct net *net)
1624c5441932SPravin B Shelar {
16252e15ea39SPravin B Shelar 	return ip_tunnel_init_net(net, gre_tap_net_id, &ipgre_tap_ops, "gretap0");
1626c5441932SPravin B Shelar }
1627c5441932SPravin B Shelar 
162864bc1781SEric Dumazet static void __net_exit ipgre_tap_exit_batch_net(struct list_head *list_net)
1629c5441932SPravin B Shelar {
163064bc1781SEric Dumazet 	ip_tunnel_delete_nets(list_net, gre_tap_net_id, &ipgre_tap_ops);
1631c5441932SPravin B Shelar }
1632c5441932SPravin B Shelar 
1633c5441932SPravin B Shelar static struct pernet_operations ipgre_tap_net_ops = {
1634c5441932SPravin B Shelar 	.init = ipgre_tap_init_net,
163564bc1781SEric Dumazet 	.exit_batch = ipgre_tap_exit_batch_net,
1636c5441932SPravin B Shelar 	.id   = &gre_tap_net_id,
1637c5441932SPravin B Shelar 	.size = sizeof(struct ip_tunnel_net),
1638c5441932SPravin B Shelar };
16391da177e4SLinus Torvalds 
164084e54fe0SWilliam Tu static int __net_init erspan_init_net(struct net *net)
164184e54fe0SWilliam Tu {
164284e54fe0SWilliam Tu 	return ip_tunnel_init_net(net, erspan_net_id,
164384e54fe0SWilliam Tu 				  &erspan_link_ops, "erspan0");
164484e54fe0SWilliam Tu }
164584e54fe0SWilliam Tu 
164664bc1781SEric Dumazet static void __net_exit erspan_exit_batch_net(struct list_head *net_list)
164784e54fe0SWilliam Tu {
164864bc1781SEric Dumazet 	ip_tunnel_delete_nets(net_list, erspan_net_id, &erspan_link_ops);
164984e54fe0SWilliam Tu }
165084e54fe0SWilliam Tu 
165184e54fe0SWilliam Tu static struct pernet_operations erspan_net_ops = {
165284e54fe0SWilliam Tu 	.init = erspan_init_net,
165364bc1781SEric Dumazet 	.exit_batch = erspan_exit_batch_net,
165484e54fe0SWilliam Tu 	.id   = &erspan_net_id,
165584e54fe0SWilliam Tu 	.size = sizeof(struct ip_tunnel_net),
165684e54fe0SWilliam Tu };
165784e54fe0SWilliam Tu 
16581da177e4SLinus Torvalds static int __init ipgre_init(void)
16591da177e4SLinus Torvalds {
16601da177e4SLinus Torvalds 	int err;
16611da177e4SLinus Torvalds 
1662058bd4d2SJoe Perches 	pr_info("GRE over IPv4 tunneling driver\n");
16631da177e4SLinus Torvalds 
1664cfb8fbf2SEric W. Biederman 	err = register_pernet_device(&ipgre_net_ops);
166559a4c759SPavel Emelyanov 	if (err < 0)
1666c2892f02SAlexey Dobriyan 		return err;
1667c2892f02SAlexey Dobriyan 
1668c5441932SPravin B Shelar 	err = register_pernet_device(&ipgre_tap_net_ops);
1669c5441932SPravin B Shelar 	if (err < 0)
1670e3d0328cSWilliam Tu 		goto pnet_tap_failed;
1671c5441932SPravin B Shelar 
167284e54fe0SWilliam Tu 	err = register_pernet_device(&erspan_net_ops);
167384e54fe0SWilliam Tu 	if (err < 0)
167484e54fe0SWilliam Tu 		goto pnet_erspan_failed;
167584e54fe0SWilliam Tu 
16769f57c67cSPravin B Shelar 	err = gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO);
1677c2892f02SAlexey Dobriyan 	if (err < 0) {
1678058bd4d2SJoe Perches 		pr_info("%s: can't add protocol\n", __func__);
1679c2892f02SAlexey Dobriyan 		goto add_proto_failed;
1680c2892f02SAlexey Dobriyan 	}
16817daa0004SPavel Emelyanov 
1682c19e654dSHerbert Xu 	err = rtnl_link_register(&ipgre_link_ops);
1683c19e654dSHerbert Xu 	if (err < 0)
1684c19e654dSHerbert Xu 		goto rtnl_link_failed;
1685c19e654dSHerbert Xu 
1686e1a80002SHerbert Xu 	err = rtnl_link_register(&ipgre_tap_ops);
1687e1a80002SHerbert Xu 	if (err < 0)
1688e1a80002SHerbert Xu 		goto tap_ops_failed;
1689e1a80002SHerbert Xu 
169084e54fe0SWilliam Tu 	err = rtnl_link_register(&erspan_link_ops);
169184e54fe0SWilliam Tu 	if (err < 0)
169284e54fe0SWilliam Tu 		goto erspan_link_failed;
169384e54fe0SWilliam Tu 
1694c5441932SPravin B Shelar 	return 0;
1695c19e654dSHerbert Xu 
169684e54fe0SWilliam Tu erspan_link_failed:
169784e54fe0SWilliam Tu 	rtnl_link_unregister(&ipgre_tap_ops);
1698e1a80002SHerbert Xu tap_ops_failed:
1699e1a80002SHerbert Xu 	rtnl_link_unregister(&ipgre_link_ops);
1700c19e654dSHerbert Xu rtnl_link_failed:
17019f57c67cSPravin B Shelar 	gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
1702c2892f02SAlexey Dobriyan add_proto_failed:
170384e54fe0SWilliam Tu 	unregister_pernet_device(&erspan_net_ops);
170484e54fe0SWilliam Tu pnet_erspan_failed:
1705c5441932SPravin B Shelar 	unregister_pernet_device(&ipgre_tap_net_ops);
1706e3d0328cSWilliam Tu pnet_tap_failed:
1707c2892f02SAlexey Dobriyan 	unregister_pernet_device(&ipgre_net_ops);
1708c5441932SPravin B Shelar 	return err;
17091da177e4SLinus Torvalds }
17101da177e4SLinus Torvalds 
1711db44575fSAlexey Kuznetsov static void __exit ipgre_fini(void)
17121da177e4SLinus Torvalds {
1713e1a80002SHerbert Xu 	rtnl_link_unregister(&ipgre_tap_ops);
1714c19e654dSHerbert Xu 	rtnl_link_unregister(&ipgre_link_ops);
171584e54fe0SWilliam Tu 	rtnl_link_unregister(&erspan_link_ops);
17169f57c67cSPravin B Shelar 	gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
1717c5441932SPravin B Shelar 	unregister_pernet_device(&ipgre_tap_net_ops);
1718c2892f02SAlexey Dobriyan 	unregister_pernet_device(&ipgre_net_ops);
171984e54fe0SWilliam Tu 	unregister_pernet_device(&erspan_net_ops);
17201da177e4SLinus Torvalds }
17211da177e4SLinus Torvalds 
17221da177e4SLinus Torvalds module_init(ipgre_init);
17231da177e4SLinus Torvalds module_exit(ipgre_fini);
17241da177e4SLinus Torvalds MODULE_LICENSE("GPL");
17254d74f8baSPatrick McHardy MODULE_ALIAS_RTNL_LINK("gre");
17264d74f8baSPatrick McHardy MODULE_ALIAS_RTNL_LINK("gretap");
172784e54fe0SWilliam Tu MODULE_ALIAS_RTNL_LINK("erspan");
17288909c9adSVasiliy Kulikov MODULE_ALIAS_NETDEV("gre0");
1729c5441932SPravin B Shelar MODULE_ALIAS_NETDEV("gretap0");
173084e54fe0SWilliam Tu MODULE_ALIAS_NETDEV("erspan0");
1731