xref: /linux/net/ipv4/ip_gre.c (revision 1d7e2ed22f8d9171fa8b629754022f22115b3f03)
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,
117a3222dc9SWilliam Tu 				__be32 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;
259*1d7e2ed2SWilliam Tu 	struct erspan_base_hdr *ershdr;
260*1d7e2ed2SWilliam 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;
264*1d7e2ed2SWilliam Tu 	int ver;
26584e54fe0SWilliam Tu 	int len;
26684e54fe0SWilliam Tu 
26784e54fe0SWilliam Tu 	itn = net_generic(net, erspan_net_id);
26884e54fe0SWilliam Tu 	len = gre_hdr_len + sizeof(*ershdr);
26984e54fe0SWilliam Tu 
270*1d7e2ed2SWilliam Tu 	/* Check based hdr len */
27184e54fe0SWilliam Tu 	if (unlikely(!pskb_may_pull(skb, len)))
27284e54fe0SWilliam Tu 		return -ENOMEM;
27384e54fe0SWilliam Tu 
27484e54fe0SWilliam Tu 	iph = ip_hdr(skb);
275*1d7e2ed2SWilliam Tu 	ershdr = (struct erspan_base_hdr *)(skb->data + gre_hdr_len);
276*1d7e2ed2SWilliam Tu 	ver = (ntohs(ershdr->ver_vlan) & VER_MASK) >> VER_OFFSET;
27784e54fe0SWilliam Tu 
27884e54fe0SWilliam Tu 	/* The original GRE header does not have key field,
27984e54fe0SWilliam Tu 	 * Use ERSPAN 10-bit session ID as key.
28084e54fe0SWilliam Tu 	 */
281935a9749SXin Long 	tpi->key = cpu_to_be32(ntohs(ershdr->session_id) & ID_MASK);
282*1d7e2ed2SWilliam Tu 	pkt_md = (struct erspan_metadata *)(ershdr + 1);
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) {
288*1d7e2ed2SWilliam Tu 		len = gre_hdr_len + erspan_hdr_len(ver);
289*1d7e2ed2SWilliam Tu 		if (unlikely(!pskb_may_pull(skb, len)))
290*1d7e2ed2SWilliam Tu 			return -ENOMEM;
291*1d7e2ed2SWilliam Tu 
29284e54fe0SWilliam Tu 		if (__iptunnel_pull_header(skb,
293*1d7e2ed2SWilliam Tu 					   len,
29484e54fe0SWilliam Tu 					   htons(ETH_P_TEB),
29584e54fe0SWilliam Tu 					   false, false) < 0)
29684e54fe0SWilliam Tu 			goto drop;
29784e54fe0SWilliam Tu 
2981a66a836SWilliam Tu 		if (tunnel->collect_md) {
2991a66a836SWilliam Tu 			struct ip_tunnel_info *info;
3001a66a836SWilliam Tu 			struct erspan_metadata *md;
3011a66a836SWilliam Tu 			__be64 tun_id;
3021a66a836SWilliam Tu 			__be16 flags;
3031a66a836SWilliam Tu 
3041a66a836SWilliam Tu 			tpi->flags |= TUNNEL_KEY;
3051a66a836SWilliam Tu 			flags = tpi->flags;
3061a66a836SWilliam Tu 			tun_id = key32_to_tunnel_id(tpi->key);
3071a66a836SWilliam Tu 
3081a66a836SWilliam Tu 			tun_dst = ip_tun_rx_dst(skb, flags,
3091a66a836SWilliam Tu 						tun_id, sizeof(*md));
3101a66a836SWilliam Tu 			if (!tun_dst)
3111a66a836SWilliam Tu 				return PACKET_REJECT;
3121a66a836SWilliam Tu 
3131a66a836SWilliam Tu 			md = ip_tunnel_info_opts(&tun_dst->u.tun_info);
3141a66a836SWilliam Tu 			if (!md)
3151a66a836SWilliam Tu 				return PACKET_REJECT;
3161a66a836SWilliam Tu 
317*1d7e2ed2SWilliam Tu 			memcpy(md, pkt_md, sizeof(*md));
3181a66a836SWilliam Tu 			info = &tun_dst->u.tun_info;
3191a66a836SWilliam Tu 			info->key.tun_flags |= TUNNEL_ERSPAN_OPT;
3201a66a836SWilliam Tu 			info->options_len = sizeof(*md);
3211a66a836SWilliam Tu 		} else {
322*1d7e2ed2SWilliam Tu 			tunnel->index = ntohl(pkt_md->u.index);
3231a66a836SWilliam Tu 		}
3241a66a836SWilliam Tu 
32584e54fe0SWilliam Tu 		skb_reset_mac_header(skb);
32684e54fe0SWilliam Tu 		ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error);
32784e54fe0SWilliam Tu 		return PACKET_RCVD;
32884e54fe0SWilliam Tu 	}
32984e54fe0SWilliam Tu drop:
33084e54fe0SWilliam Tu 	kfree_skb(skb);
33184e54fe0SWilliam Tu 	return PACKET_RCVD;
33284e54fe0SWilliam Tu }
33384e54fe0SWilliam Tu 
334125372faSJiri Benc static int __ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
335125372faSJiri Benc 		       struct ip_tunnel_net *itn, int hdr_len, bool raw_proto)
3361da177e4SLinus Torvalds {
3372e15ea39SPravin B Shelar 	struct metadata_dst *tun_dst = NULL;
338b71d1d42SEric Dumazet 	const struct iphdr *iph;
3391da177e4SLinus Torvalds 	struct ip_tunnel *tunnel;
3401da177e4SLinus Torvalds 
341eddc9ec5SArnaldo Carvalho de Melo 	iph = ip_hdr(skb);
342bda7bb46SPravin B Shelar 	tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags,
343bda7bb46SPravin B Shelar 				  iph->saddr, iph->daddr, tpi->key);
3441da177e4SLinus Torvalds 
345d2083287Sstephen hemminger 	if (tunnel) {
346125372faSJiri Benc 		if (__iptunnel_pull_header(skb, hdr_len, tpi->proto,
347125372faSJiri Benc 					   raw_proto, false) < 0)
348244a797bSJiri Benc 			goto drop;
349244a797bSJiri Benc 
350e271c7b4SJiri Benc 		if (tunnel->dev->type != ARPHRD_NONE)
3510e3da5bbSTimo Teräs 			skb_pop_mac_header(skb);
352e271c7b4SJiri Benc 		else
353e271c7b4SJiri Benc 			skb_reset_mac_header(skb);
3542e15ea39SPravin B Shelar 		if (tunnel->collect_md) {
355c29a70d2SPravin B Shelar 			__be16 flags;
356c29a70d2SPravin B Shelar 			__be64 tun_id;
3572e15ea39SPravin B Shelar 
358c29a70d2SPravin B Shelar 			flags = tpi->flags & (TUNNEL_CSUM | TUNNEL_KEY);
359d817f432SAmir Vadai 			tun_id = key32_to_tunnel_id(tpi->key);
360c29a70d2SPravin B Shelar 			tun_dst = ip_tun_rx_dst(skb, flags, tun_id, 0);
3612e15ea39SPravin B Shelar 			if (!tun_dst)
3622e15ea39SPravin B Shelar 				return PACKET_REJECT;
3632e15ea39SPravin B Shelar 		}
3642e15ea39SPravin B Shelar 
3652e15ea39SPravin B Shelar 		ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error);
366bda7bb46SPravin B Shelar 		return PACKET_RCVD;
3671da177e4SLinus Torvalds 	}
368125372faSJiri Benc 	return PACKET_NEXT;
369244a797bSJiri Benc 
370244a797bSJiri Benc drop:
371244a797bSJiri Benc 	kfree_skb(skb);
372244a797bSJiri Benc 	return PACKET_RCVD;
3731da177e4SLinus Torvalds }
3741da177e4SLinus Torvalds 
375125372faSJiri Benc static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
376125372faSJiri Benc 		     int hdr_len)
377125372faSJiri Benc {
378125372faSJiri Benc 	struct net *net = dev_net(skb->dev);
379125372faSJiri Benc 	struct ip_tunnel_net *itn;
380125372faSJiri Benc 	int res;
381125372faSJiri Benc 
382125372faSJiri Benc 	if (tpi->proto == htons(ETH_P_TEB))
383125372faSJiri Benc 		itn = net_generic(net, gre_tap_net_id);
384125372faSJiri Benc 	else
385125372faSJiri Benc 		itn = net_generic(net, ipgre_net_id);
386125372faSJiri Benc 
387125372faSJiri Benc 	res = __ipgre_rcv(skb, tpi, itn, hdr_len, false);
388125372faSJiri Benc 	if (res == PACKET_NEXT && tpi->proto == htons(ETH_P_TEB)) {
389125372faSJiri Benc 		/* ipgre tunnels in collect metadata mode should receive
390125372faSJiri Benc 		 * also ETH_P_TEB traffic.
391125372faSJiri Benc 		 */
392125372faSJiri Benc 		itn = net_generic(net, ipgre_net_id);
393125372faSJiri Benc 		res = __ipgre_rcv(skb, tpi, itn, hdr_len, true);
394125372faSJiri Benc 	}
395125372faSJiri Benc 	return res;
396125372faSJiri Benc }
397125372faSJiri Benc 
3989f57c67cSPravin B Shelar static int gre_rcv(struct sk_buff *skb)
3999f57c67cSPravin B Shelar {
4009f57c67cSPravin B Shelar 	struct tnl_ptk_info tpi;
4019f57c67cSPravin B Shelar 	bool csum_err = false;
40295f5c64cSTom Herbert 	int hdr_len;
4039f57c67cSPravin B Shelar 
4049f57c67cSPravin B Shelar #ifdef CONFIG_NET_IPGRE_BROADCAST
4059f57c67cSPravin B Shelar 	if (ipv4_is_multicast(ip_hdr(skb)->daddr)) {
4069f57c67cSPravin B Shelar 		/* Looped back packet, drop it! */
4079f57c67cSPravin B Shelar 		if (rt_is_output_route(skb_rtable(skb)))
4089f57c67cSPravin B Shelar 			goto drop;
4099f57c67cSPravin B Shelar 	}
4109f57c67cSPravin B Shelar #endif
4119f57c67cSPravin B Shelar 
412e582615aSEric Dumazet 	hdr_len = gre_parse_header(skb, &tpi, &csum_err, htons(ETH_P_IP), 0);
413f132ae7cSJiri Benc 	if (hdr_len < 0)
41495f5c64cSTom Herbert 		goto drop;
41595f5c64cSTom Herbert 
41684e54fe0SWilliam Tu 	if (unlikely(tpi.proto == htons(ETH_P_ERSPAN))) {
41784e54fe0SWilliam Tu 		if (erspan_rcv(skb, &tpi, hdr_len) == PACKET_RCVD)
41884e54fe0SWilliam Tu 			return 0;
41984e54fe0SWilliam Tu 	}
42084e54fe0SWilliam Tu 
421244a797bSJiri Benc 	if (ipgre_rcv(skb, &tpi, hdr_len) == PACKET_RCVD)
4229f57c67cSPravin B Shelar 		return 0;
4239f57c67cSPravin B Shelar 
4249f57c67cSPravin B Shelar 	icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
4259f57c67cSPravin B Shelar drop:
4269f57c67cSPravin B Shelar 	kfree_skb(skb);
4279f57c67cSPravin B Shelar 	return 0;
4289f57c67cSPravin B Shelar }
4299f57c67cSPravin B Shelar 
430c5441932SPravin B Shelar static void __gre_xmit(struct sk_buff *skb, struct net_device *dev,
431c5441932SPravin B Shelar 		       const struct iphdr *tnl_params,
432c5441932SPravin B Shelar 		       __be16 proto)
433c5441932SPravin B Shelar {
434c5441932SPravin B Shelar 	struct ip_tunnel *tunnel = netdev_priv(dev);
435c5441932SPravin B Shelar 
436c5441932SPravin B Shelar 	if (tunnel->parms.o_flags & TUNNEL_SEQ)
437c5441932SPravin B Shelar 		tunnel->o_seqno++;
438cef401deSEric Dumazet 
439c5441932SPravin B Shelar 	/* Push GRE header. */
440182a352dSTom Herbert 	gre_build_header(skb, tunnel->tun_hlen,
441182a352dSTom Herbert 			 tunnel->parms.o_flags, proto, tunnel->parms.o_key,
442182a352dSTom Herbert 			 htonl(tunnel->o_seqno));
4431da177e4SLinus Torvalds 
444bf3d6a8fSNicolas Dichtel 	ip_tunnel_xmit(skb, dev, tnl_params, tnl_params->protocol);
4451da177e4SLinus Torvalds }
4461da177e4SLinus Torvalds 
447aed069dfSAlexander Duyck static int gre_handle_offloads(struct sk_buff *skb, bool csum)
448b2acd1dcSPravin B Shelar {
4496fa79666SEdward Cree 	return iptunnel_handle_offloads(skb, csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE);
450b2acd1dcSPravin B Shelar }
451b2acd1dcSPravin B Shelar 
452fc4099f1SPravin B Shelar static struct rtable *gre_get_rt(struct sk_buff *skb,
453fc4099f1SPravin B Shelar 				 struct net_device *dev,
454fc4099f1SPravin B Shelar 				 struct flowi4 *fl,
455fc4099f1SPravin B Shelar 				 const struct ip_tunnel_key *key)
456fc4099f1SPravin B Shelar {
457fc4099f1SPravin B Shelar 	struct net *net = dev_net(dev);
458fc4099f1SPravin B Shelar 
459fc4099f1SPravin B Shelar 	memset(fl, 0, sizeof(*fl));
460fc4099f1SPravin B Shelar 	fl->daddr = key->u.ipv4.dst;
461fc4099f1SPravin B Shelar 	fl->saddr = key->u.ipv4.src;
462fc4099f1SPravin B Shelar 	fl->flowi4_tos = RT_TOS(key->tos);
463fc4099f1SPravin B Shelar 	fl->flowi4_mark = skb->mark;
464fc4099f1SPravin B Shelar 	fl->flowi4_proto = IPPROTO_GRE;
465fc4099f1SPravin B Shelar 
466fc4099f1SPravin B Shelar 	return ip_route_output_key(net, fl);
467fc4099f1SPravin B Shelar }
468fc4099f1SPravin B Shelar 
469862a03c3SWilliam Tu static struct rtable *prepare_fb_xmit(struct sk_buff *skb,
470862a03c3SWilliam Tu 				      struct net_device *dev,
471862a03c3SWilliam Tu 				      struct flowi4 *fl,
472862a03c3SWilliam Tu 				      int tunnel_hlen)
4732e15ea39SPravin B Shelar {
4742e15ea39SPravin B Shelar 	struct ip_tunnel_info *tun_info;
4752e15ea39SPravin B Shelar 	const struct ip_tunnel_key *key;
476db3c6139SDaniel Borkmann 	struct rtable *rt = NULL;
4772e15ea39SPravin B Shelar 	int min_headroom;
478db3c6139SDaniel Borkmann 	bool use_cache;
4792e15ea39SPravin B Shelar 	int err;
4802e15ea39SPravin B Shelar 
48161adedf3SJiri Benc 	tun_info = skb_tunnel_info(skb);
4822e15ea39SPravin B Shelar 	key = &tun_info->key;
483db3c6139SDaniel Borkmann 	use_cache = ip_tunnel_dst_cache_usable(skb, tun_info);
484862a03c3SWilliam Tu 
485db3c6139SDaniel Borkmann 	if (use_cache)
486862a03c3SWilliam Tu 		rt = dst_cache_get_ip4(&tun_info->dst_cache, &fl->saddr);
4873c1cb4d2SPaolo Abeni 	if (!rt) {
488862a03c3SWilliam Tu 		rt = gre_get_rt(skb, dev, fl, key);
4892e15ea39SPravin B Shelar 		if (IS_ERR(rt))
4902e15ea39SPravin B Shelar 			goto err_free_skb;
491db3c6139SDaniel Borkmann 		if (use_cache)
4923c1cb4d2SPaolo Abeni 			dst_cache_set_ip4(&tun_info->dst_cache, &rt->dst,
493862a03c3SWilliam Tu 					  fl->saddr);
4943c1cb4d2SPaolo Abeni 	}
4952e15ea39SPravin B Shelar 
4962e15ea39SPravin B Shelar 	min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len
4972e15ea39SPravin B Shelar 			+ tunnel_hlen + sizeof(struct iphdr);
4982e15ea39SPravin B Shelar 	if (skb_headroom(skb) < min_headroom || skb_header_cloned(skb)) {
4992e15ea39SPravin B Shelar 		int head_delta = SKB_DATA_ALIGN(min_headroom -
5002e15ea39SPravin B Shelar 						skb_headroom(skb) +
5012e15ea39SPravin B Shelar 						16);
5022e15ea39SPravin B Shelar 		err = pskb_expand_head(skb, max_t(int, head_delta, 0),
5032e15ea39SPravin B Shelar 				       0, GFP_ATOMIC);
5042e15ea39SPravin B Shelar 		if (unlikely(err))
5052e15ea39SPravin B Shelar 			goto err_free_rt;
5062e15ea39SPravin B Shelar 	}
507862a03c3SWilliam Tu 	return rt;
508862a03c3SWilliam Tu 
509862a03c3SWilliam Tu err_free_rt:
510862a03c3SWilliam Tu 	ip_rt_put(rt);
511862a03c3SWilliam Tu err_free_skb:
512862a03c3SWilliam Tu 	kfree_skb(skb);
513862a03c3SWilliam Tu 	dev->stats.tx_dropped++;
514862a03c3SWilliam Tu 	return NULL;
515862a03c3SWilliam Tu }
516862a03c3SWilliam Tu 
517862a03c3SWilliam Tu static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev,
518862a03c3SWilliam Tu 			__be16 proto)
519862a03c3SWilliam Tu {
520862a03c3SWilliam Tu 	struct ip_tunnel_info *tun_info;
521862a03c3SWilliam Tu 	const struct ip_tunnel_key *key;
522862a03c3SWilliam Tu 	struct rtable *rt = NULL;
523862a03c3SWilliam Tu 	struct flowi4 fl;
524862a03c3SWilliam Tu 	int tunnel_hlen;
525862a03c3SWilliam Tu 	__be16 df, flags;
526862a03c3SWilliam Tu 
527862a03c3SWilliam Tu 	tun_info = skb_tunnel_info(skb);
528862a03c3SWilliam Tu 	if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) ||
529862a03c3SWilliam Tu 		     ip_tunnel_info_af(tun_info) != AF_INET))
530862a03c3SWilliam Tu 		goto err_free_skb;
531862a03c3SWilliam Tu 
532862a03c3SWilliam Tu 	key = &tun_info->key;
533862a03c3SWilliam Tu 	tunnel_hlen = gre_calc_hlen(key->tun_flags);
534862a03c3SWilliam Tu 
535862a03c3SWilliam Tu 	rt = prepare_fb_xmit(skb, dev, &fl, tunnel_hlen);
536862a03c3SWilliam Tu 	if (!rt)
537862a03c3SWilliam Tu 		return;
5382e15ea39SPravin B Shelar 
5392e15ea39SPravin B Shelar 	/* Push Tunnel header. */
540aed069dfSAlexander Duyck 	if (gre_handle_offloads(skb, !!(tun_info->key.tun_flags & TUNNEL_CSUM)))
5412e15ea39SPravin B Shelar 		goto err_free_rt;
5422e15ea39SPravin B Shelar 
5432e15ea39SPravin B Shelar 	flags = tun_info->key.tun_flags & (TUNNEL_CSUM | TUNNEL_KEY);
544cba65321SDavid S. Miller 	gre_build_header(skb, tunnel_hlen, flags, proto,
545d817f432SAmir Vadai 			 tunnel_id_to_key32(tun_info->key.tun_id), 0);
5462e15ea39SPravin B Shelar 
5472e15ea39SPravin B Shelar 	df = key->tun_flags & TUNNEL_DONT_FRAGMENT ?  htons(IP_DF) : 0;
548039f5062SPravin B Shelar 
549039f5062SPravin B Shelar 	iptunnel_xmit(skb->sk, rt, skb, fl.saddr, key->u.ipv4.dst, IPPROTO_GRE,
5507c383fb2SJiri Benc 		      key->tos, key->ttl, df, false);
5512e15ea39SPravin B Shelar 	return;
5522e15ea39SPravin B Shelar 
5532e15ea39SPravin B Shelar err_free_rt:
5542e15ea39SPravin B Shelar 	ip_rt_put(rt);
5552e15ea39SPravin B Shelar err_free_skb:
5562e15ea39SPravin B Shelar 	kfree_skb(skb);
5572e15ea39SPravin B Shelar 	dev->stats.tx_dropped++;
5582e15ea39SPravin B Shelar }
5592e15ea39SPravin B Shelar 
5601a66a836SWilliam Tu static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev,
5611a66a836SWilliam Tu 			   __be16 proto)
5621a66a836SWilliam Tu {
5631a66a836SWilliam Tu 	struct ip_tunnel *tunnel = netdev_priv(dev);
5641a66a836SWilliam Tu 	struct ip_tunnel_info *tun_info;
5651a66a836SWilliam Tu 	const struct ip_tunnel_key *key;
5661a66a836SWilliam Tu 	struct erspan_metadata *md;
5671a66a836SWilliam Tu 	struct rtable *rt = NULL;
5681a66a836SWilliam Tu 	bool truncate = false;
5691a66a836SWilliam Tu 	struct flowi4 fl;
5701a66a836SWilliam Tu 	int tunnel_hlen;
5711a66a836SWilliam Tu 	__be16 df;
5721a66a836SWilliam Tu 
5731a66a836SWilliam Tu 	tun_info = skb_tunnel_info(skb);
5741a66a836SWilliam Tu 	if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) ||
5751a66a836SWilliam Tu 		     ip_tunnel_info_af(tun_info) != AF_INET))
5761a66a836SWilliam Tu 		goto err_free_skb;
5771a66a836SWilliam Tu 
5781a66a836SWilliam Tu 	key = &tun_info->key;
5791a66a836SWilliam Tu 
5801a66a836SWilliam Tu 	/* ERSPAN has fixed 8 byte GRE header */
581*1d7e2ed2SWilliam Tu 	tunnel_hlen = 8 + sizeof(struct erspan_base_hdr) + ERSPAN_V1_MDSIZE;
5821a66a836SWilliam Tu 
5831a66a836SWilliam Tu 	rt = prepare_fb_xmit(skb, dev, &fl, tunnel_hlen);
5841a66a836SWilliam Tu 	if (!rt)
5851a66a836SWilliam Tu 		return;
5861a66a836SWilliam Tu 
5871a66a836SWilliam Tu 	if (gre_handle_offloads(skb, false))
5881a66a836SWilliam Tu 		goto err_free_rt;
5891a66a836SWilliam Tu 
590f192970dSWilliam Tu 	if (skb->len > dev->mtu + dev->hard_header_len) {
591f192970dSWilliam Tu 		pskb_trim(skb, dev->mtu + dev->hard_header_len);
5921a66a836SWilliam Tu 		truncate = true;
5931a66a836SWilliam Tu 	}
5941a66a836SWilliam Tu 
5951a66a836SWilliam Tu 	md = ip_tunnel_info_opts(tun_info);
5961a66a836SWilliam Tu 	if (!md)
5971a66a836SWilliam Tu 		goto err_free_rt;
5981a66a836SWilliam Tu 
5991a66a836SWilliam Tu 	erspan_build_header(skb, tunnel_id_to_key32(key->tun_id),
600*1d7e2ed2SWilliam Tu 			    ntohl(md->u.index), truncate, true);
6011a66a836SWilliam Tu 
6021a66a836SWilliam Tu 	gre_build_header(skb, 8, TUNNEL_SEQ,
6031a66a836SWilliam Tu 			 htons(ETH_P_ERSPAN), 0, htonl(tunnel->o_seqno++));
6041a66a836SWilliam Tu 
6051a66a836SWilliam Tu 	df = key->tun_flags & TUNNEL_DONT_FRAGMENT ?  htons(IP_DF) : 0;
6061a66a836SWilliam Tu 
6071a66a836SWilliam Tu 	iptunnel_xmit(skb->sk, rt, skb, fl.saddr, key->u.ipv4.dst, IPPROTO_GRE,
6081a66a836SWilliam Tu 		      key->tos, key->ttl, df, false);
6091a66a836SWilliam Tu 	return;
6101a66a836SWilliam Tu 
6111a66a836SWilliam Tu err_free_rt:
6121a66a836SWilliam Tu 	ip_rt_put(rt);
6131a66a836SWilliam Tu err_free_skb:
6141a66a836SWilliam Tu 	kfree_skb(skb);
6151a66a836SWilliam Tu 	dev->stats.tx_dropped++;
6161a66a836SWilliam Tu }
6171a66a836SWilliam Tu 
618fc4099f1SPravin B Shelar static int gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
619fc4099f1SPravin B Shelar {
620fc4099f1SPravin B Shelar 	struct ip_tunnel_info *info = skb_tunnel_info(skb);
621fc4099f1SPravin B Shelar 	struct rtable *rt;
622fc4099f1SPravin B Shelar 	struct flowi4 fl4;
623fc4099f1SPravin B Shelar 
624fc4099f1SPravin B Shelar 	if (ip_tunnel_info_af(info) != AF_INET)
625fc4099f1SPravin B Shelar 		return -EINVAL;
626fc4099f1SPravin B Shelar 
627fc4099f1SPravin B Shelar 	rt = gre_get_rt(skb, dev, &fl4, &info->key);
628fc4099f1SPravin B Shelar 	if (IS_ERR(rt))
629fc4099f1SPravin B Shelar 		return PTR_ERR(rt);
630fc4099f1SPravin B Shelar 
631fc4099f1SPravin B Shelar 	ip_rt_put(rt);
632fc4099f1SPravin B Shelar 	info->key.u.ipv4.src = fl4.saddr;
633fc4099f1SPravin B Shelar 	return 0;
634fc4099f1SPravin B Shelar }
635fc4099f1SPravin B Shelar 
636c5441932SPravin B Shelar static netdev_tx_t ipgre_xmit(struct sk_buff *skb,
637c5441932SPravin B Shelar 			      struct net_device *dev)
638ee34c1ebSMichal Schmidt {
639c5441932SPravin B Shelar 	struct ip_tunnel *tunnel = netdev_priv(dev);
640c5441932SPravin B Shelar 	const struct iphdr *tnl_params;
641ee34c1ebSMichal Schmidt 
6422e15ea39SPravin B Shelar 	if (tunnel->collect_md) {
6432090714eSJiri Benc 		gre_fb_xmit(skb, dev, skb->protocol);
6442e15ea39SPravin B Shelar 		return NETDEV_TX_OK;
6452e15ea39SPravin B Shelar 	}
6462e15ea39SPravin B Shelar 
647c5441932SPravin B Shelar 	if (dev->header_ops) {
648c5441932SPravin B Shelar 		/* Need space for new headers */
649c5441932SPravin B Shelar 		if (skb_cow_head(skb, dev->needed_headroom -
6502bac7cb3SChen Gang 				      (tunnel->hlen + sizeof(struct iphdr))))
651c5441932SPravin B Shelar 			goto free_skb;
652ee34c1ebSMichal Schmidt 
653c5441932SPravin B Shelar 		tnl_params = (const struct iphdr *)skb->data;
654cbb1e85fSDavid S. Miller 
655c5441932SPravin B Shelar 		/* Pull skb since ip_tunnel_xmit() needs skb->data pointing
656c5441932SPravin B Shelar 		 * to gre header.
657c5441932SPravin B Shelar 		 */
658c5441932SPravin B Shelar 		skb_pull(skb, tunnel->hlen + sizeof(struct iphdr));
6598a0033a9STimo Teräs 		skb_reset_mac_header(skb);
660c5441932SPravin B Shelar 	} else {
661c5441932SPravin B Shelar 		if (skb_cow_head(skb, dev->needed_headroom))
662c5441932SPravin B Shelar 			goto free_skb;
663c5441932SPravin B Shelar 
664c5441932SPravin B Shelar 		tnl_params = &tunnel->parms.iph;
665ee34c1ebSMichal Schmidt 	}
666e1a80002SHerbert Xu 
667aed069dfSAlexander Duyck 	if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM)))
668aed069dfSAlexander Duyck 		goto free_skb;
6698a0033a9STimo Teräs 
670c5441932SPravin B Shelar 	__gre_xmit(skb, dev, tnl_params, skb->protocol);
671c5441932SPravin B Shelar 	return NETDEV_TX_OK;
672c5441932SPravin B Shelar 
673c5441932SPravin B Shelar free_skb:
6743acfa1e7SEric Dumazet 	kfree_skb(skb);
675c5441932SPravin B Shelar 	dev->stats.tx_dropped++;
676c5441932SPravin B Shelar 	return NETDEV_TX_OK;
677ee34c1ebSMichal Schmidt }
678ee34c1ebSMichal Schmidt 
67984e54fe0SWilliam Tu static netdev_tx_t erspan_xmit(struct sk_buff *skb,
68084e54fe0SWilliam Tu 			       struct net_device *dev)
68184e54fe0SWilliam Tu {
68284e54fe0SWilliam Tu 	struct ip_tunnel *tunnel = netdev_priv(dev);
68384e54fe0SWilliam Tu 	bool truncate = false;
68484e54fe0SWilliam Tu 
6851a66a836SWilliam Tu 	if (tunnel->collect_md) {
6861a66a836SWilliam Tu 		erspan_fb_xmit(skb, dev, skb->protocol);
6871a66a836SWilliam Tu 		return NETDEV_TX_OK;
6881a66a836SWilliam Tu 	}
6891a66a836SWilliam Tu 
69084e54fe0SWilliam Tu 	if (gre_handle_offloads(skb, false))
69184e54fe0SWilliam Tu 		goto free_skb;
69284e54fe0SWilliam Tu 
69384e54fe0SWilliam Tu 	if (skb_cow_head(skb, dev->needed_headroom))
69484e54fe0SWilliam Tu 		goto free_skb;
69584e54fe0SWilliam Tu 
696f192970dSWilliam Tu 	if (skb->len > dev->mtu + dev->hard_header_len) {
697f192970dSWilliam Tu 		pskb_trim(skb, dev->mtu + dev->hard_header_len);
69884e54fe0SWilliam Tu 		truncate = true;
69984e54fe0SWilliam Tu 	}
70084e54fe0SWilliam Tu 
70184e54fe0SWilliam Tu 	/* Push ERSPAN header */
702a3222dc9SWilliam Tu 	erspan_build_header(skb, tunnel->parms.o_key, tunnel->index,
703a3222dc9SWilliam Tu 			    truncate, true);
70484e54fe0SWilliam Tu 	tunnel->parms.o_flags &= ~TUNNEL_KEY;
70584e54fe0SWilliam Tu 	__gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_ERSPAN));
70684e54fe0SWilliam Tu 	return NETDEV_TX_OK;
70784e54fe0SWilliam Tu 
70884e54fe0SWilliam Tu free_skb:
70984e54fe0SWilliam Tu 	kfree_skb(skb);
71084e54fe0SWilliam Tu 	dev->stats.tx_dropped++;
71184e54fe0SWilliam Tu 	return NETDEV_TX_OK;
71284e54fe0SWilliam Tu }
71384e54fe0SWilliam Tu 
714c5441932SPravin B Shelar static netdev_tx_t gre_tap_xmit(struct sk_buff *skb,
715c5441932SPravin B Shelar 				struct net_device *dev)
716c5441932SPravin B Shelar {
717c5441932SPravin B Shelar 	struct ip_tunnel *tunnel = netdev_priv(dev);
718ee34c1ebSMichal Schmidt 
7192e15ea39SPravin B Shelar 	if (tunnel->collect_md) {
7202090714eSJiri Benc 		gre_fb_xmit(skb, dev, htons(ETH_P_TEB));
7212e15ea39SPravin B Shelar 		return NETDEV_TX_OK;
7222e15ea39SPravin B Shelar 	}
7232e15ea39SPravin B Shelar 
724aed069dfSAlexander Duyck 	if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM)))
725aed069dfSAlexander Duyck 		goto free_skb;
726ee34c1ebSMichal Schmidt 
727c5441932SPravin B Shelar 	if (skb_cow_head(skb, dev->needed_headroom))
728c5441932SPravin B Shelar 		goto free_skb;
72942aa9162SHerbert Xu 
730c5441932SPravin B Shelar 	__gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_TEB));
731c5441932SPravin B Shelar 	return NETDEV_TX_OK;
732c5441932SPravin B Shelar 
733c5441932SPravin B Shelar free_skb:
7343acfa1e7SEric Dumazet 	kfree_skb(skb);
735c5441932SPravin B Shelar 	dev->stats.tx_dropped++;
736c5441932SPravin B Shelar 	return NETDEV_TX_OK;
73768c33163SPravin B Shelar }
738ee34c1ebSMichal Schmidt 
739dd9d598cSXin Long static void ipgre_link_update(struct net_device *dev, bool set_mtu)
740dd9d598cSXin Long {
741dd9d598cSXin Long 	struct ip_tunnel *tunnel = netdev_priv(dev);
742dd9d598cSXin Long 	int len;
743dd9d598cSXin Long 
744dd9d598cSXin Long 	len = tunnel->tun_hlen;
745dd9d598cSXin Long 	tunnel->tun_hlen = gre_calc_hlen(tunnel->parms.o_flags);
746dd9d598cSXin Long 	len = tunnel->tun_hlen - len;
747dd9d598cSXin Long 	tunnel->hlen = tunnel->hlen + len;
748dd9d598cSXin Long 
749dd9d598cSXin Long 	dev->needed_headroom = dev->needed_headroom + len;
750dd9d598cSXin Long 	if (set_mtu)
751dd9d598cSXin Long 		dev->mtu = max_t(int, dev->mtu - len, 68);
752dd9d598cSXin Long 
753dd9d598cSXin Long 	if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) {
754dd9d598cSXin Long 		if (!(tunnel->parms.o_flags & TUNNEL_CSUM) ||
755dd9d598cSXin Long 		    tunnel->encap.type == TUNNEL_ENCAP_NONE) {
756dd9d598cSXin Long 			dev->features |= NETIF_F_GSO_SOFTWARE;
757dd9d598cSXin Long 			dev->hw_features |= NETIF_F_GSO_SOFTWARE;
758dd9d598cSXin Long 		}
759dd9d598cSXin Long 		dev->features |= NETIF_F_LLTX;
760dd9d598cSXin Long 	}
761dd9d598cSXin Long }
762dd9d598cSXin Long 
763c5441932SPravin B Shelar static int ipgre_tunnel_ioctl(struct net_device *dev,
764c5441932SPravin B Shelar 			      struct ifreq *ifr, int cmd)
7651da177e4SLinus Torvalds {
7661da177e4SLinus Torvalds 	struct ip_tunnel_parm p;
767a0efab67SXin Long 	int err;
7681da177e4SLinus Torvalds 
7691da177e4SLinus Torvalds 	if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
770c5441932SPravin B Shelar 		return -EFAULT;
771a0efab67SXin Long 
7726c734fb8SCong Wang 	if (cmd == SIOCADDTUNNEL || cmd == SIOCCHGTUNNEL) {
7731da177e4SLinus Torvalds 		if (p.iph.version != 4 || p.iph.protocol != IPPROTO_GRE ||
7741da177e4SLinus Torvalds 		    p.iph.ihl != 5 || (p.iph.frag_off & htons(~IP_DF)) ||
7756c734fb8SCong Wang 		    ((p.i_flags | p.o_flags) & (GRE_VERSION | GRE_ROUTING)))
7761da177e4SLinus Torvalds 			return -EINVAL;
777c5441932SPravin B Shelar 	}
778a0efab67SXin Long 
779c5441932SPravin B Shelar 	p.i_flags = gre_flags_to_tnl_flags(p.i_flags);
780c5441932SPravin B Shelar 	p.o_flags = gre_flags_to_tnl_flags(p.o_flags);
781c5441932SPravin B Shelar 
782c5441932SPravin B Shelar 	err = ip_tunnel_ioctl(dev, &p, cmd);
783c5441932SPravin B Shelar 	if (err)
784c5441932SPravin B Shelar 		return err;
785c5441932SPravin B Shelar 
786a0efab67SXin Long 	if (cmd == SIOCCHGTUNNEL) {
787a0efab67SXin Long 		struct ip_tunnel *t = netdev_priv(dev);
788a0efab67SXin Long 
789a0efab67SXin Long 		t->parms.i_flags = p.i_flags;
790a0efab67SXin Long 		t->parms.o_flags = p.o_flags;
791a0efab67SXin Long 
792a0efab67SXin Long 		if (strcmp(dev->rtnl_link_ops->kind, "erspan"))
793a0efab67SXin Long 			ipgre_link_update(dev, true);
794a0efab67SXin Long 	}
795a0efab67SXin Long 
79695f5c64cSTom Herbert 	p.i_flags = gre_tnl_flags_to_gre_flags(p.i_flags);
79795f5c64cSTom Herbert 	p.o_flags = gre_tnl_flags_to_gre_flags(p.o_flags);
798c5441932SPravin B Shelar 
799c5441932SPravin B Shelar 	if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p)))
800c5441932SPravin B Shelar 		return -EFAULT;
801a0efab67SXin Long 
8021da177e4SLinus Torvalds 	return 0;
8031da177e4SLinus Torvalds }
8041da177e4SLinus Torvalds 
8051da177e4SLinus Torvalds /* Nice toy. Unfortunately, useless in real life :-)
8061da177e4SLinus Torvalds    It allows to construct virtual multiprotocol broadcast "LAN"
8071da177e4SLinus Torvalds    over the Internet, provided multicast routing is tuned.
8081da177e4SLinus Torvalds 
8091da177e4SLinus Torvalds 
8101da177e4SLinus Torvalds    I have no idea was this bicycle invented before me,
8111da177e4SLinus Torvalds    so that I had to set ARPHRD_IPGRE to a random value.
8121da177e4SLinus Torvalds    I have an impression, that Cisco could make something similar,
8131da177e4SLinus Torvalds    but this feature is apparently missing in IOS<=11.2(8).
8141da177e4SLinus Torvalds 
8151da177e4SLinus Torvalds    I set up 10.66.66/24 and fec0:6666:6666::0/96 as virtual networks
8161da177e4SLinus Torvalds    with broadcast 224.66.66.66. If you have access to mbone, play with me :-)
8171da177e4SLinus Torvalds 
8181da177e4SLinus Torvalds    ping -t 255 224.66.66.66
8191da177e4SLinus Torvalds 
8201da177e4SLinus Torvalds    If nobody answers, mbone does not work.
8211da177e4SLinus Torvalds 
8221da177e4SLinus Torvalds    ip tunnel add Universe mode gre remote 224.66.66.66 local <Your_real_addr> ttl 255
8231da177e4SLinus Torvalds    ip addr add 10.66.66.<somewhat>/24 dev Universe
8241da177e4SLinus Torvalds    ifconfig Universe up
8251da177e4SLinus Torvalds    ifconfig Universe add fe80::<Your_real_addr>/10
8261da177e4SLinus Torvalds    ifconfig Universe add fec0:6666:6666::<Your_real_addr>/96
8271da177e4SLinus Torvalds    ftp 10.66.66.66
8281da177e4SLinus Torvalds    ...
8291da177e4SLinus Torvalds    ftp fec0:6666:6666::193.233.7.65
8301da177e4SLinus Torvalds    ...
8311da177e4SLinus Torvalds  */
8323b04dddeSStephen Hemminger static int ipgre_header(struct sk_buff *skb, struct net_device *dev,
8333b04dddeSStephen Hemminger 			unsigned short type,
8341507850bSEric Dumazet 			const void *daddr, const void *saddr, unsigned int len)
8351da177e4SLinus Torvalds {
8362941a486SPatrick McHardy 	struct ip_tunnel *t = netdev_priv(dev);
837c5441932SPravin B Shelar 	struct iphdr *iph;
838c5441932SPravin B Shelar 	struct gre_base_hdr *greh;
839c5441932SPravin B Shelar 
840d58ff351SJohannes Berg 	iph = skb_push(skb, t->hlen + sizeof(*iph));
841c5441932SPravin B Shelar 	greh = (struct gre_base_hdr *)(iph+1);
84295f5c64cSTom Herbert 	greh->flags = gre_tnl_flags_to_gre_flags(t->parms.o_flags);
843c5441932SPravin B Shelar 	greh->protocol = htons(type);
8441da177e4SLinus Torvalds 
8451da177e4SLinus Torvalds 	memcpy(iph, &t->parms.iph, sizeof(struct iphdr));
8461da177e4SLinus Torvalds 
847c5441932SPravin B Shelar 	/* Set the source hardware address. */
8481da177e4SLinus Torvalds 	if (saddr)
8491da177e4SLinus Torvalds 		memcpy(&iph->saddr, saddr, 4);
8506d55cb91STimo Teräs 	if (daddr)
8511da177e4SLinus Torvalds 		memcpy(&iph->daddr, daddr, 4);
8526d55cb91STimo Teräs 	if (iph->daddr)
85377a482bdSTimo Teräs 		return t->hlen + sizeof(*iph);
8541da177e4SLinus Torvalds 
855c5441932SPravin B Shelar 	return -(t->hlen + sizeof(*iph));
8561da177e4SLinus Torvalds }
8571da177e4SLinus Torvalds 
8586a5f44d7STimo Teras static int ipgre_header_parse(const struct sk_buff *skb, unsigned char *haddr)
8596a5f44d7STimo Teras {
860b71d1d42SEric Dumazet 	const struct iphdr *iph = (const struct iphdr *) skb_mac_header(skb);
8616a5f44d7STimo Teras 	memcpy(haddr, &iph->saddr, 4);
8626a5f44d7STimo Teras 	return 4;
8636a5f44d7STimo Teras }
8646a5f44d7STimo Teras 
8653b04dddeSStephen Hemminger static const struct header_ops ipgre_header_ops = {
8663b04dddeSStephen Hemminger 	.create	= ipgre_header,
8676a5f44d7STimo Teras 	.parse	= ipgre_header_parse,
8683b04dddeSStephen Hemminger };
8693b04dddeSStephen Hemminger 
8706a5f44d7STimo Teras #ifdef CONFIG_NET_IPGRE_BROADCAST
8711da177e4SLinus Torvalds static int ipgre_open(struct net_device *dev)
8721da177e4SLinus Torvalds {
8732941a486SPatrick McHardy 	struct ip_tunnel *t = netdev_priv(dev);
8741da177e4SLinus Torvalds 
875f97c1e0cSJoe Perches 	if (ipv4_is_multicast(t->parms.iph.daddr)) {
876cbb1e85fSDavid S. Miller 		struct flowi4 fl4;
877cbb1e85fSDavid S. Miller 		struct rtable *rt;
878cbb1e85fSDavid S. Miller 
879b57708adSNicolas Dichtel 		rt = ip_route_output_gre(t->net, &fl4,
88078fbfd8aSDavid S. Miller 					 t->parms.iph.daddr,
88178fbfd8aSDavid S. Miller 					 t->parms.iph.saddr,
88278fbfd8aSDavid S. Miller 					 t->parms.o_key,
88378fbfd8aSDavid S. Miller 					 RT_TOS(t->parms.iph.tos),
88478fbfd8aSDavid S. Miller 					 t->parms.link);
885b23dd4feSDavid S. Miller 		if (IS_ERR(rt))
8861da177e4SLinus Torvalds 			return -EADDRNOTAVAIL;
887d8d1f30bSChangli Gao 		dev = rt->dst.dev;
8881da177e4SLinus Torvalds 		ip_rt_put(rt);
88951456b29SIan Morris 		if (!__in_dev_get_rtnl(dev))
8901da177e4SLinus Torvalds 			return -EADDRNOTAVAIL;
8911da177e4SLinus Torvalds 		t->mlink = dev->ifindex;
892e5ed6399SHerbert Xu 		ip_mc_inc_group(__in_dev_get_rtnl(dev), t->parms.iph.daddr);
8931da177e4SLinus Torvalds 	}
8941da177e4SLinus Torvalds 	return 0;
8951da177e4SLinus Torvalds }
8961da177e4SLinus Torvalds 
8971da177e4SLinus Torvalds static int ipgre_close(struct net_device *dev)
8981da177e4SLinus Torvalds {
8992941a486SPatrick McHardy 	struct ip_tunnel *t = netdev_priv(dev);
900b8c26a33SStephen Hemminger 
901f97c1e0cSJoe Perches 	if (ipv4_is_multicast(t->parms.iph.daddr) && t->mlink) {
9027fee0ca2SDenis V. Lunev 		struct in_device *in_dev;
903b57708adSNicolas Dichtel 		in_dev = inetdev_by_index(t->net, t->mlink);
9048723e1b4SEric Dumazet 		if (in_dev)
9051da177e4SLinus Torvalds 			ip_mc_dec_group(in_dev, t->parms.iph.daddr);
9061da177e4SLinus Torvalds 	}
9071da177e4SLinus Torvalds 	return 0;
9081da177e4SLinus Torvalds }
9091da177e4SLinus Torvalds #endif
9101da177e4SLinus Torvalds 
911b8c26a33SStephen Hemminger static const struct net_device_ops ipgre_netdev_ops = {
912b8c26a33SStephen Hemminger 	.ndo_init		= ipgre_tunnel_init,
913c5441932SPravin B Shelar 	.ndo_uninit		= ip_tunnel_uninit,
914b8c26a33SStephen Hemminger #ifdef CONFIG_NET_IPGRE_BROADCAST
915b8c26a33SStephen Hemminger 	.ndo_open		= ipgre_open,
916b8c26a33SStephen Hemminger 	.ndo_stop		= ipgre_close,
917b8c26a33SStephen Hemminger #endif
918c5441932SPravin B Shelar 	.ndo_start_xmit		= ipgre_xmit,
919b8c26a33SStephen Hemminger 	.ndo_do_ioctl		= ipgre_tunnel_ioctl,
920c5441932SPravin B Shelar 	.ndo_change_mtu		= ip_tunnel_change_mtu,
921c5441932SPravin B Shelar 	.ndo_get_stats64	= ip_tunnel_get_stats64,
9221e99584bSNicolas Dichtel 	.ndo_get_iflink		= ip_tunnel_get_iflink,
923b8c26a33SStephen Hemminger };
924b8c26a33SStephen Hemminger 
9256b78f16eSEric Dumazet #define GRE_FEATURES (NETIF_F_SG |		\
9266b78f16eSEric Dumazet 		      NETIF_F_FRAGLIST |	\
9276b78f16eSEric Dumazet 		      NETIF_F_HIGHDMA |		\
9286b78f16eSEric Dumazet 		      NETIF_F_HW_CSUM)
9296b78f16eSEric Dumazet 
9301da177e4SLinus Torvalds static void ipgre_tunnel_setup(struct net_device *dev)
9311da177e4SLinus Torvalds {
932b8c26a33SStephen Hemminger 	dev->netdev_ops		= &ipgre_netdev_ops;
9335a455275SNicolas Dichtel 	dev->type		= ARPHRD_IPGRE;
934c5441932SPravin B Shelar 	ip_tunnel_setup(dev, ipgre_net_id);
935c5441932SPravin B Shelar }
9361da177e4SLinus Torvalds 
937c5441932SPravin B Shelar static void __gre_tunnel_init(struct net_device *dev)
938c5441932SPravin B Shelar {
939c5441932SPravin B Shelar 	struct ip_tunnel *tunnel;
9404565e991STom Herbert 	int t_hlen;
941c5441932SPravin B Shelar 
942c5441932SPravin B Shelar 	tunnel = netdev_priv(dev);
94395f5c64cSTom Herbert 	tunnel->tun_hlen = gre_calc_hlen(tunnel->parms.o_flags);
944c5441932SPravin B Shelar 	tunnel->parms.iph.protocol = IPPROTO_GRE;
945c5441932SPravin B Shelar 
9464565e991STom Herbert 	tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen;
9474565e991STom Herbert 
9484565e991STom Herbert 	t_hlen = tunnel->hlen + sizeof(struct iphdr);
9494565e991STom Herbert 
9504565e991STom Herbert 	dev->needed_headroom	= LL_MAX_HEADER + t_hlen + 4;
9514565e991STom Herbert 	dev->mtu		= ETH_DATA_LEN - t_hlen - 4;
9526b78f16eSEric Dumazet 
953b57708adSNicolas Dichtel 	dev->features		|= GRE_FEATURES;
9546b78f16eSEric Dumazet 	dev->hw_features	|= GRE_FEATURES;
955c5441932SPravin B Shelar 
956c5441932SPravin B Shelar 	if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) {
957a0ca153fSAlexander Duyck 		/* TCP offload with GRE SEQ is not supported, nor
958a0ca153fSAlexander Duyck 		 * can we support 2 levels of outer headers requiring
959a0ca153fSAlexander Duyck 		 * an update.
960a0ca153fSAlexander Duyck 		 */
961a0ca153fSAlexander Duyck 		if (!(tunnel->parms.o_flags & TUNNEL_CSUM) ||
962a0ca153fSAlexander Duyck 		    (tunnel->encap.type == TUNNEL_ENCAP_NONE)) {
963c5441932SPravin B Shelar 			dev->features    |= NETIF_F_GSO_SOFTWARE;
964c5441932SPravin B Shelar 			dev->hw_features |= NETIF_F_GSO_SOFTWARE;
965a0ca153fSAlexander Duyck 		}
966a0ca153fSAlexander Duyck 
967c5441932SPravin B Shelar 		/* Can use a lockless transmit, unless we generate
968c5441932SPravin B Shelar 		 * output sequences
969c5441932SPravin B Shelar 		 */
970c5441932SPravin B Shelar 		dev->features |= NETIF_F_LLTX;
971c5441932SPravin B Shelar 	}
9721da177e4SLinus Torvalds }
9731da177e4SLinus Torvalds 
9741da177e4SLinus Torvalds static int ipgre_tunnel_init(struct net_device *dev)
9751da177e4SLinus Torvalds {
976c5441932SPravin B Shelar 	struct ip_tunnel *tunnel = netdev_priv(dev);
977c5441932SPravin B Shelar 	struct iphdr *iph = &tunnel->parms.iph;
9781da177e4SLinus Torvalds 
979c5441932SPravin B Shelar 	__gre_tunnel_init(dev);
9801da177e4SLinus Torvalds 
981c5441932SPravin B Shelar 	memcpy(dev->dev_addr, &iph->saddr, 4);
982c5441932SPravin B Shelar 	memcpy(dev->broadcast, &iph->daddr, 4);
9831da177e4SLinus Torvalds 
984c5441932SPravin B Shelar 	dev->flags		= IFF_NOARP;
98502875878SEric Dumazet 	netif_keep_dst(dev);
986c5441932SPravin B Shelar 	dev->addr_len		= 4;
9871da177e4SLinus Torvalds 
988a64b04d8SJiri Benc 	if (iph->daddr && !tunnel->collect_md) {
9891da177e4SLinus Torvalds #ifdef CONFIG_NET_IPGRE_BROADCAST
990f97c1e0cSJoe Perches 		if (ipv4_is_multicast(iph->daddr)) {
9911da177e4SLinus Torvalds 			if (!iph->saddr)
9921da177e4SLinus Torvalds 				return -EINVAL;
9931da177e4SLinus Torvalds 			dev->flags = IFF_BROADCAST;
9943b04dddeSStephen Hemminger 			dev->header_ops = &ipgre_header_ops;
9951da177e4SLinus Torvalds 		}
9961da177e4SLinus Torvalds #endif
997a64b04d8SJiri Benc 	} else if (!tunnel->collect_md) {
9986a5f44d7STimo Teras 		dev->header_ops = &ipgre_header_ops;
999a64b04d8SJiri Benc 	}
10001da177e4SLinus Torvalds 
1001c5441932SPravin B Shelar 	return ip_tunnel_init(dev);
100260769a5dSEric Dumazet }
100360769a5dSEric Dumazet 
10049f57c67cSPravin B Shelar static const struct gre_protocol ipgre_protocol = {
10059f57c67cSPravin B Shelar 	.handler     = gre_rcv,
10069f57c67cSPravin B Shelar 	.err_handler = gre_err,
10071da177e4SLinus Torvalds };
10081da177e4SLinus Torvalds 
10092c8c1e72SAlexey Dobriyan static int __net_init ipgre_init_net(struct net *net)
101059a4c759SPavel Emelyanov {
1011c5441932SPravin B Shelar 	return ip_tunnel_init_net(net, ipgre_net_id, &ipgre_link_ops, NULL);
101259a4c759SPavel Emelyanov }
101359a4c759SPavel Emelyanov 
101464bc1781SEric Dumazet static void __net_exit ipgre_exit_batch_net(struct list_head *list_net)
101559a4c759SPavel Emelyanov {
101664bc1781SEric Dumazet 	ip_tunnel_delete_nets(list_net, ipgre_net_id, &ipgre_link_ops);
101759a4c759SPavel Emelyanov }
101859a4c759SPavel Emelyanov 
101959a4c759SPavel Emelyanov static struct pernet_operations ipgre_net_ops = {
102059a4c759SPavel Emelyanov 	.init = ipgre_init_net,
102164bc1781SEric Dumazet 	.exit_batch = ipgre_exit_batch_net,
1022cfb8fbf2SEric W. Biederman 	.id   = &ipgre_net_id,
1023c5441932SPravin B Shelar 	.size = sizeof(struct ip_tunnel_net),
102459a4c759SPavel Emelyanov };
10251da177e4SLinus Torvalds 
1026a8b8a889SMatthias Schiffer static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[],
1027a8b8a889SMatthias Schiffer 				 struct netlink_ext_ack *extack)
1028c19e654dSHerbert Xu {
1029c19e654dSHerbert Xu 	__be16 flags;
1030c19e654dSHerbert Xu 
1031c19e654dSHerbert Xu 	if (!data)
1032c19e654dSHerbert Xu 		return 0;
1033c19e654dSHerbert Xu 
1034c19e654dSHerbert Xu 	flags = 0;
1035c19e654dSHerbert Xu 	if (data[IFLA_GRE_IFLAGS])
1036c19e654dSHerbert Xu 		flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]);
1037c19e654dSHerbert Xu 	if (data[IFLA_GRE_OFLAGS])
1038c19e654dSHerbert Xu 		flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]);
1039c19e654dSHerbert Xu 	if (flags & (GRE_VERSION|GRE_ROUTING))
1040c19e654dSHerbert Xu 		return -EINVAL;
1041c19e654dSHerbert Xu 
1042946b636fSJiri Benc 	if (data[IFLA_GRE_COLLECT_METADATA] &&
1043946b636fSJiri Benc 	    data[IFLA_GRE_ENCAP_TYPE] &&
1044946b636fSJiri Benc 	    nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]) != TUNNEL_ENCAP_NONE)
1045946b636fSJiri Benc 		return -EINVAL;
1046946b636fSJiri Benc 
1047c19e654dSHerbert Xu 	return 0;
1048c19e654dSHerbert Xu }
1049c19e654dSHerbert Xu 
1050a8b8a889SMatthias Schiffer static int ipgre_tap_validate(struct nlattr *tb[], struct nlattr *data[],
1051a8b8a889SMatthias Schiffer 			      struct netlink_ext_ack *extack)
1052e1a80002SHerbert Xu {
1053e1a80002SHerbert Xu 	__be32 daddr;
1054e1a80002SHerbert Xu 
1055e1a80002SHerbert Xu 	if (tb[IFLA_ADDRESS]) {
1056e1a80002SHerbert Xu 		if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
1057e1a80002SHerbert Xu 			return -EINVAL;
1058e1a80002SHerbert Xu 		if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
1059e1a80002SHerbert Xu 			return -EADDRNOTAVAIL;
1060e1a80002SHerbert Xu 	}
1061e1a80002SHerbert Xu 
1062e1a80002SHerbert Xu 	if (!data)
1063e1a80002SHerbert Xu 		goto out;
1064e1a80002SHerbert Xu 
1065e1a80002SHerbert Xu 	if (data[IFLA_GRE_REMOTE]) {
1066e1a80002SHerbert Xu 		memcpy(&daddr, nla_data(data[IFLA_GRE_REMOTE]), 4);
1067e1a80002SHerbert Xu 		if (!daddr)
1068e1a80002SHerbert Xu 			return -EINVAL;
1069e1a80002SHerbert Xu 	}
1070e1a80002SHerbert Xu 
1071e1a80002SHerbert Xu out:
1072a8b8a889SMatthias Schiffer 	return ipgre_tunnel_validate(tb, data, extack);
1073e1a80002SHerbert Xu }
1074e1a80002SHerbert Xu 
107584e54fe0SWilliam Tu static int erspan_validate(struct nlattr *tb[], struct nlattr *data[],
107684e54fe0SWilliam Tu 			   struct netlink_ext_ack *extack)
107784e54fe0SWilliam Tu {
107884e54fe0SWilliam Tu 	__be16 flags = 0;
107984e54fe0SWilliam Tu 	int ret;
108084e54fe0SWilliam Tu 
108184e54fe0SWilliam Tu 	if (!data)
108284e54fe0SWilliam Tu 		return 0;
108384e54fe0SWilliam Tu 
108484e54fe0SWilliam Tu 	ret = ipgre_tap_validate(tb, data, extack);
108584e54fe0SWilliam Tu 	if (ret)
108684e54fe0SWilliam Tu 		return ret;
108784e54fe0SWilliam Tu 
108884e54fe0SWilliam Tu 	/* ERSPAN should only have GRE sequence and key flag */
10891a66a836SWilliam Tu 	if (data[IFLA_GRE_OFLAGS])
109084e54fe0SWilliam Tu 		flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]);
10911a66a836SWilliam Tu 	if (data[IFLA_GRE_IFLAGS])
109284e54fe0SWilliam Tu 		flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]);
10931a66a836SWilliam Tu 	if (!data[IFLA_GRE_COLLECT_METADATA] &&
10941a66a836SWilliam Tu 	    flags != (GRE_SEQ | GRE_KEY))
109584e54fe0SWilliam Tu 		return -EINVAL;
109684e54fe0SWilliam Tu 
109784e54fe0SWilliam Tu 	/* ERSPAN Session ID only has 10-bit. Since we reuse
109884e54fe0SWilliam Tu 	 * 32-bit key field as ID, check it's range.
109984e54fe0SWilliam Tu 	 */
110084e54fe0SWilliam Tu 	if (data[IFLA_GRE_IKEY] &&
110184e54fe0SWilliam Tu 	    (ntohl(nla_get_be32(data[IFLA_GRE_IKEY])) & ~ID_MASK))
110284e54fe0SWilliam Tu 		return -EINVAL;
110384e54fe0SWilliam Tu 
110484e54fe0SWilliam Tu 	if (data[IFLA_GRE_OKEY] &&
110584e54fe0SWilliam Tu 	    (ntohl(nla_get_be32(data[IFLA_GRE_OKEY])) & ~ID_MASK))
110684e54fe0SWilliam Tu 		return -EINVAL;
110784e54fe0SWilliam Tu 
110884e54fe0SWilliam Tu 	return 0;
110984e54fe0SWilliam Tu }
111084e54fe0SWilliam Tu 
111122a59be8SPhilip Prindeville static int ipgre_netlink_parms(struct net_device *dev,
11122e15ea39SPravin B Shelar 				struct nlattr *data[],
11132e15ea39SPravin B Shelar 				struct nlattr *tb[],
11149830ad4cSCraig Gallek 				struct ip_tunnel_parm *parms,
11159830ad4cSCraig Gallek 				__u32 *fwmark)
1116c19e654dSHerbert Xu {
111722a59be8SPhilip Prindeville 	struct ip_tunnel *t = netdev_priv(dev);
111822a59be8SPhilip Prindeville 
11197bb82d92SHerbert Xu 	memset(parms, 0, sizeof(*parms));
1120c19e654dSHerbert Xu 
1121c19e654dSHerbert Xu 	parms->iph.protocol = IPPROTO_GRE;
1122c19e654dSHerbert Xu 
1123c19e654dSHerbert Xu 	if (!data)
112422a59be8SPhilip Prindeville 		return 0;
1125c19e654dSHerbert Xu 
1126c19e654dSHerbert Xu 	if (data[IFLA_GRE_LINK])
1127c19e654dSHerbert Xu 		parms->link = nla_get_u32(data[IFLA_GRE_LINK]);
1128c19e654dSHerbert Xu 
1129c19e654dSHerbert Xu 	if (data[IFLA_GRE_IFLAGS])
1130c5441932SPravin B Shelar 		parms->i_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_IFLAGS]));
1131c19e654dSHerbert Xu 
1132c19e654dSHerbert Xu 	if (data[IFLA_GRE_OFLAGS])
1133c5441932SPravin B Shelar 		parms->o_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_OFLAGS]));
1134c19e654dSHerbert Xu 
1135c19e654dSHerbert Xu 	if (data[IFLA_GRE_IKEY])
1136c19e654dSHerbert Xu 		parms->i_key = nla_get_be32(data[IFLA_GRE_IKEY]);
1137c19e654dSHerbert Xu 
1138c19e654dSHerbert Xu 	if (data[IFLA_GRE_OKEY])
1139c19e654dSHerbert Xu 		parms->o_key = nla_get_be32(data[IFLA_GRE_OKEY]);
1140c19e654dSHerbert Xu 
1141c19e654dSHerbert Xu 	if (data[IFLA_GRE_LOCAL])
114267b61f6cSJiri Benc 		parms->iph.saddr = nla_get_in_addr(data[IFLA_GRE_LOCAL]);
1143c19e654dSHerbert Xu 
1144c19e654dSHerbert Xu 	if (data[IFLA_GRE_REMOTE])
114567b61f6cSJiri Benc 		parms->iph.daddr = nla_get_in_addr(data[IFLA_GRE_REMOTE]);
1146c19e654dSHerbert Xu 
1147c19e654dSHerbert Xu 	if (data[IFLA_GRE_TTL])
1148c19e654dSHerbert Xu 		parms->iph.ttl = nla_get_u8(data[IFLA_GRE_TTL]);
1149c19e654dSHerbert Xu 
1150c19e654dSHerbert Xu 	if (data[IFLA_GRE_TOS])
1151c19e654dSHerbert Xu 		parms->iph.tos = nla_get_u8(data[IFLA_GRE_TOS]);
1152c19e654dSHerbert Xu 
115322a59be8SPhilip Prindeville 	if (!data[IFLA_GRE_PMTUDISC] || nla_get_u8(data[IFLA_GRE_PMTUDISC])) {
115422a59be8SPhilip Prindeville 		if (t->ignore_df)
115522a59be8SPhilip Prindeville 			return -EINVAL;
1156c19e654dSHerbert Xu 		parms->iph.frag_off = htons(IP_DF);
115722a59be8SPhilip Prindeville 	}
11582e15ea39SPravin B Shelar 
11592e15ea39SPravin B Shelar 	if (data[IFLA_GRE_COLLECT_METADATA]) {
11602e15ea39SPravin B Shelar 		t->collect_md = true;
1161e271c7b4SJiri Benc 		if (dev->type == ARPHRD_IPGRE)
1162e271c7b4SJiri Benc 			dev->type = ARPHRD_NONE;
11632e15ea39SPravin B Shelar 	}
116422a59be8SPhilip Prindeville 
116522a59be8SPhilip Prindeville 	if (data[IFLA_GRE_IGNORE_DF]) {
116622a59be8SPhilip Prindeville 		if (nla_get_u8(data[IFLA_GRE_IGNORE_DF])
116722a59be8SPhilip Prindeville 		  && (parms->iph.frag_off & htons(IP_DF)))
116822a59be8SPhilip Prindeville 			return -EINVAL;
116922a59be8SPhilip Prindeville 		t->ignore_df = !!nla_get_u8(data[IFLA_GRE_IGNORE_DF]);
117022a59be8SPhilip Prindeville 	}
117122a59be8SPhilip Prindeville 
11729830ad4cSCraig Gallek 	if (data[IFLA_GRE_FWMARK])
11739830ad4cSCraig Gallek 		*fwmark = nla_get_u32(data[IFLA_GRE_FWMARK]);
11749830ad4cSCraig Gallek 
117584e54fe0SWilliam Tu 	if (data[IFLA_GRE_ERSPAN_INDEX]) {
117684e54fe0SWilliam Tu 		t->index = nla_get_u32(data[IFLA_GRE_ERSPAN_INDEX]);
117784e54fe0SWilliam Tu 
117884e54fe0SWilliam Tu 		if (t->index & ~INDEX_MASK)
117984e54fe0SWilliam Tu 			return -EINVAL;
118084e54fe0SWilliam Tu 	}
118184e54fe0SWilliam Tu 
118222a59be8SPhilip Prindeville 	return 0;
1183c19e654dSHerbert Xu }
1184c19e654dSHerbert Xu 
11854565e991STom Herbert /* This function returns true when ENCAP attributes are present in the nl msg */
11864565e991STom Herbert static bool ipgre_netlink_encap_parms(struct nlattr *data[],
11874565e991STom Herbert 				      struct ip_tunnel_encap *ipencap)
11884565e991STom Herbert {
11894565e991STom Herbert 	bool ret = false;
11904565e991STom Herbert 
11914565e991STom Herbert 	memset(ipencap, 0, sizeof(*ipencap));
11924565e991STom Herbert 
11934565e991STom Herbert 	if (!data)
11944565e991STom Herbert 		return ret;
11954565e991STom Herbert 
11964565e991STom Herbert 	if (data[IFLA_GRE_ENCAP_TYPE]) {
11974565e991STom Herbert 		ret = true;
11984565e991STom Herbert 		ipencap->type = nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]);
11994565e991STom Herbert 	}
12004565e991STom Herbert 
12014565e991STom Herbert 	if (data[IFLA_GRE_ENCAP_FLAGS]) {
12024565e991STom Herbert 		ret = true;
12034565e991STom Herbert 		ipencap->flags = nla_get_u16(data[IFLA_GRE_ENCAP_FLAGS]);
12044565e991STom Herbert 	}
12054565e991STom Herbert 
12064565e991STom Herbert 	if (data[IFLA_GRE_ENCAP_SPORT]) {
12074565e991STom Herbert 		ret = true;
12083e97fa70SSabrina Dubroca 		ipencap->sport = nla_get_be16(data[IFLA_GRE_ENCAP_SPORT]);
12094565e991STom Herbert 	}
12104565e991STom Herbert 
12114565e991STom Herbert 	if (data[IFLA_GRE_ENCAP_DPORT]) {
12124565e991STom Herbert 		ret = true;
12133e97fa70SSabrina Dubroca 		ipencap->dport = nla_get_be16(data[IFLA_GRE_ENCAP_DPORT]);
12144565e991STom Herbert 	}
12154565e991STom Herbert 
12164565e991STom Herbert 	return ret;
12174565e991STom Herbert }
12184565e991STom Herbert 
1219c5441932SPravin B Shelar static int gre_tap_init(struct net_device *dev)
1220e1a80002SHerbert Xu {
1221c5441932SPravin B Shelar 	__gre_tunnel_init(dev);
1222bec94d43Sstephen hemminger 	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
1223d51711c0SXin Long 	netif_keep_dst(dev);
1224e1a80002SHerbert Xu 
1225c5441932SPravin B Shelar 	return ip_tunnel_init(dev);
1226e1a80002SHerbert Xu }
1227e1a80002SHerbert Xu 
1228c5441932SPravin B Shelar static const struct net_device_ops gre_tap_netdev_ops = {
1229c5441932SPravin B Shelar 	.ndo_init		= gre_tap_init,
1230c5441932SPravin B Shelar 	.ndo_uninit		= ip_tunnel_uninit,
1231c5441932SPravin B Shelar 	.ndo_start_xmit		= gre_tap_xmit,
1232b8c26a33SStephen Hemminger 	.ndo_set_mac_address 	= eth_mac_addr,
1233b8c26a33SStephen Hemminger 	.ndo_validate_addr	= eth_validate_addr,
1234c5441932SPravin B Shelar 	.ndo_change_mtu		= ip_tunnel_change_mtu,
1235c5441932SPravin B Shelar 	.ndo_get_stats64	= ip_tunnel_get_stats64,
12361e99584bSNicolas Dichtel 	.ndo_get_iflink		= ip_tunnel_get_iflink,
1237fc4099f1SPravin B Shelar 	.ndo_fill_metadata_dst	= gre_fill_metadata_dst,
1238b8c26a33SStephen Hemminger };
1239b8c26a33SStephen Hemminger 
124084e54fe0SWilliam Tu static int erspan_tunnel_init(struct net_device *dev)
124184e54fe0SWilliam Tu {
124284e54fe0SWilliam Tu 	struct ip_tunnel *tunnel = netdev_priv(dev);
124384e54fe0SWilliam Tu 	int t_hlen;
124484e54fe0SWilliam Tu 
124584e54fe0SWilliam Tu 	tunnel->tun_hlen = 8;
124684e54fe0SWilliam Tu 	tunnel->parms.iph.protocol = IPPROTO_GRE;
1247c122fda2SXin Long 	tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen +
1248*1d7e2ed2SWilliam Tu 		       sizeof(struct erspan_base_hdr) + ERSPAN_V1_MDSIZE;
1249c122fda2SXin Long 	t_hlen = tunnel->hlen + sizeof(struct iphdr);
125084e54fe0SWilliam Tu 
125184e54fe0SWilliam Tu 	dev->needed_headroom = LL_MAX_HEADER + t_hlen + 4;
125284e54fe0SWilliam Tu 	dev->mtu = ETH_DATA_LEN - t_hlen - 4;
125384e54fe0SWilliam Tu 	dev->features		|= GRE_FEATURES;
125484e54fe0SWilliam Tu 	dev->hw_features	|= GRE_FEATURES;
125584e54fe0SWilliam Tu 	dev->priv_flags		|= IFF_LIVE_ADDR_CHANGE;
1256c84bed44SXin Long 	netif_keep_dst(dev);
125784e54fe0SWilliam Tu 
125884e54fe0SWilliam Tu 	return ip_tunnel_init(dev);
125984e54fe0SWilliam Tu }
126084e54fe0SWilliam Tu 
126184e54fe0SWilliam Tu static const struct net_device_ops erspan_netdev_ops = {
126284e54fe0SWilliam Tu 	.ndo_init		= erspan_tunnel_init,
126384e54fe0SWilliam Tu 	.ndo_uninit		= ip_tunnel_uninit,
126484e54fe0SWilliam Tu 	.ndo_start_xmit		= erspan_xmit,
126584e54fe0SWilliam Tu 	.ndo_set_mac_address	= eth_mac_addr,
126684e54fe0SWilliam Tu 	.ndo_validate_addr	= eth_validate_addr,
126784e54fe0SWilliam Tu 	.ndo_change_mtu		= ip_tunnel_change_mtu,
126884e54fe0SWilliam Tu 	.ndo_get_stats64	= ip_tunnel_get_stats64,
126984e54fe0SWilliam Tu 	.ndo_get_iflink		= ip_tunnel_get_iflink,
127084e54fe0SWilliam Tu 	.ndo_fill_metadata_dst	= gre_fill_metadata_dst,
127184e54fe0SWilliam Tu };
127284e54fe0SWilliam Tu 
1273e1a80002SHerbert Xu static void ipgre_tap_setup(struct net_device *dev)
1274e1a80002SHerbert Xu {
1275e1a80002SHerbert Xu 	ether_setup(dev);
1276c5441932SPravin B Shelar 	dev->netdev_ops	= &gre_tap_netdev_ops;
1277d13b161cSJiri Benc 	dev->priv_flags &= ~IFF_TX_SKB_SHARING;
1278f8c1b7ceSstephen hemminger 	dev->priv_flags	|= IFF_LIVE_ADDR_CHANGE;
1279c5441932SPravin B Shelar 	ip_tunnel_setup(dev, gre_tap_net_id);
1280e1a80002SHerbert Xu }
1281e1a80002SHerbert Xu 
1282c5441932SPravin B Shelar static int ipgre_newlink(struct net *src_net, struct net_device *dev,
12837a3f4a18SMatthias Schiffer 			 struct nlattr *tb[], struct nlattr *data[],
12847a3f4a18SMatthias Schiffer 			 struct netlink_ext_ack *extack)
1285c19e654dSHerbert Xu {
1286c5441932SPravin B Shelar 	struct ip_tunnel_parm p;
12874565e991STom Herbert 	struct ip_tunnel_encap ipencap;
12889830ad4cSCraig Gallek 	__u32 fwmark = 0;
128922a59be8SPhilip Prindeville 	int err;
12904565e991STom Herbert 
12914565e991STom Herbert 	if (ipgre_netlink_encap_parms(data, &ipencap)) {
12924565e991STom Herbert 		struct ip_tunnel *t = netdev_priv(dev);
129322a59be8SPhilip Prindeville 		err = ip_tunnel_encap_setup(t, &ipencap);
12944565e991STom Herbert 
12954565e991STom Herbert 		if (err < 0)
12964565e991STom Herbert 			return err;
12974565e991STom Herbert 	}
1298c19e654dSHerbert Xu 
12999830ad4cSCraig Gallek 	err = ipgre_netlink_parms(dev, data, tb, &p, &fwmark);
130022a59be8SPhilip Prindeville 	if (err < 0)
130122a59be8SPhilip Prindeville 		return err;
13029830ad4cSCraig Gallek 	return ip_tunnel_newlink(dev, tb, &p, fwmark);
1303c19e654dSHerbert Xu }
1304c19e654dSHerbert Xu 
1305c19e654dSHerbert Xu static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[],
1306ad744b22SMatthias Schiffer 			    struct nlattr *data[],
1307ad744b22SMatthias Schiffer 			    struct netlink_ext_ack *extack)
1308c19e654dSHerbert Xu {
13099830ad4cSCraig Gallek 	struct ip_tunnel *t = netdev_priv(dev);
13104565e991STom Herbert 	struct ip_tunnel_encap ipencap;
13119830ad4cSCraig Gallek 	__u32 fwmark = t->fwmark;
1312dd9d598cSXin Long 	struct ip_tunnel_parm p;
131322a59be8SPhilip Prindeville 	int err;
13144565e991STom Herbert 
13154565e991STom Herbert 	if (ipgre_netlink_encap_parms(data, &ipencap)) {
131622a59be8SPhilip Prindeville 		err = ip_tunnel_encap_setup(t, &ipencap);
13174565e991STom Herbert 
13184565e991STom Herbert 		if (err < 0)
13194565e991STom Herbert 			return err;
13204565e991STom Herbert 	}
1321c19e654dSHerbert Xu 
13229830ad4cSCraig Gallek 	err = ipgre_netlink_parms(dev, data, tb, &p, &fwmark);
132322a59be8SPhilip Prindeville 	if (err < 0)
132422a59be8SPhilip Prindeville 		return err;
1325dd9d598cSXin Long 
1326dd9d598cSXin Long 	err = ip_tunnel_changelink(dev, tb, &p, fwmark);
1327dd9d598cSXin Long 	if (err < 0)
1328dd9d598cSXin Long 		return err;
1329dd9d598cSXin Long 
1330dd9d598cSXin Long 	t->parms.i_flags = p.i_flags;
1331dd9d598cSXin Long 	t->parms.o_flags = p.o_flags;
1332dd9d598cSXin Long 
1333dd9d598cSXin Long 	if (strcmp(dev->rtnl_link_ops->kind, "erspan"))
1334dd9d598cSXin Long 		ipgre_link_update(dev, !tb[IFLA_MTU]);
1335dd9d598cSXin Long 
1336dd9d598cSXin Long 	return 0;
1337c19e654dSHerbert Xu }
1338c19e654dSHerbert Xu 
1339c19e654dSHerbert Xu static size_t ipgre_get_size(const struct net_device *dev)
1340c19e654dSHerbert Xu {
1341c19e654dSHerbert Xu 	return
1342c19e654dSHerbert Xu 		/* IFLA_GRE_LINK */
1343c19e654dSHerbert Xu 		nla_total_size(4) +
1344c19e654dSHerbert Xu 		/* IFLA_GRE_IFLAGS */
1345c19e654dSHerbert Xu 		nla_total_size(2) +
1346c19e654dSHerbert Xu 		/* IFLA_GRE_OFLAGS */
1347c19e654dSHerbert Xu 		nla_total_size(2) +
1348c19e654dSHerbert Xu 		/* IFLA_GRE_IKEY */
1349c19e654dSHerbert Xu 		nla_total_size(4) +
1350c19e654dSHerbert Xu 		/* IFLA_GRE_OKEY */
1351c19e654dSHerbert Xu 		nla_total_size(4) +
1352c19e654dSHerbert Xu 		/* IFLA_GRE_LOCAL */
1353c19e654dSHerbert Xu 		nla_total_size(4) +
1354c19e654dSHerbert Xu 		/* IFLA_GRE_REMOTE */
1355c19e654dSHerbert Xu 		nla_total_size(4) +
1356c19e654dSHerbert Xu 		/* IFLA_GRE_TTL */
1357c19e654dSHerbert Xu 		nla_total_size(1) +
1358c19e654dSHerbert Xu 		/* IFLA_GRE_TOS */
1359c19e654dSHerbert Xu 		nla_total_size(1) +
1360c19e654dSHerbert Xu 		/* IFLA_GRE_PMTUDISC */
1361c19e654dSHerbert Xu 		nla_total_size(1) +
13624565e991STom Herbert 		/* IFLA_GRE_ENCAP_TYPE */
13634565e991STom Herbert 		nla_total_size(2) +
13644565e991STom Herbert 		/* IFLA_GRE_ENCAP_FLAGS */
13654565e991STom Herbert 		nla_total_size(2) +
13664565e991STom Herbert 		/* IFLA_GRE_ENCAP_SPORT */
13674565e991STom Herbert 		nla_total_size(2) +
13684565e991STom Herbert 		/* IFLA_GRE_ENCAP_DPORT */
13694565e991STom Herbert 		nla_total_size(2) +
13702e15ea39SPravin B Shelar 		/* IFLA_GRE_COLLECT_METADATA */
13712e15ea39SPravin B Shelar 		nla_total_size(0) +
137222a59be8SPhilip Prindeville 		/* IFLA_GRE_IGNORE_DF */
137322a59be8SPhilip Prindeville 		nla_total_size(1) +
13749830ad4cSCraig Gallek 		/* IFLA_GRE_FWMARK */
13759830ad4cSCraig Gallek 		nla_total_size(4) +
137684e54fe0SWilliam Tu 		/* IFLA_GRE_ERSPAN_INDEX */
137784e54fe0SWilliam Tu 		nla_total_size(4) +
1378c19e654dSHerbert Xu 		0;
1379c19e654dSHerbert Xu }
1380c19e654dSHerbert Xu 
1381c19e654dSHerbert Xu static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev)
1382c19e654dSHerbert Xu {
1383c19e654dSHerbert Xu 	struct ip_tunnel *t = netdev_priv(dev);
1384c19e654dSHerbert Xu 	struct ip_tunnel_parm *p = &t->parms;
1385c19e654dSHerbert Xu 
1386f3756b79SDavid S. Miller 	if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) ||
138795f5c64cSTom Herbert 	    nla_put_be16(skb, IFLA_GRE_IFLAGS,
138895f5c64cSTom Herbert 			 gre_tnl_flags_to_gre_flags(p->i_flags)) ||
138995f5c64cSTom Herbert 	    nla_put_be16(skb, IFLA_GRE_OFLAGS,
139095f5c64cSTom Herbert 			 gre_tnl_flags_to_gre_flags(p->o_flags)) ||
1391f3756b79SDavid S. Miller 	    nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) ||
1392f3756b79SDavid S. Miller 	    nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) ||
1393930345eaSJiri Benc 	    nla_put_in_addr(skb, IFLA_GRE_LOCAL, p->iph.saddr) ||
1394930345eaSJiri Benc 	    nla_put_in_addr(skb, IFLA_GRE_REMOTE, p->iph.daddr) ||
1395f3756b79SDavid S. Miller 	    nla_put_u8(skb, IFLA_GRE_TTL, p->iph.ttl) ||
1396f3756b79SDavid S. Miller 	    nla_put_u8(skb, IFLA_GRE_TOS, p->iph.tos) ||
1397f3756b79SDavid S. Miller 	    nla_put_u8(skb, IFLA_GRE_PMTUDISC,
13989830ad4cSCraig Gallek 		       !!(p->iph.frag_off & htons(IP_DF))) ||
13999830ad4cSCraig Gallek 	    nla_put_u32(skb, IFLA_GRE_FWMARK, t->fwmark))
1400f3756b79SDavid S. Miller 		goto nla_put_failure;
14014565e991STom Herbert 
14024565e991STom Herbert 	if (nla_put_u16(skb, IFLA_GRE_ENCAP_TYPE,
14034565e991STom Herbert 			t->encap.type) ||
14043e97fa70SSabrina Dubroca 	    nla_put_be16(skb, IFLA_GRE_ENCAP_SPORT,
14054565e991STom Herbert 			 t->encap.sport) ||
14063e97fa70SSabrina Dubroca 	    nla_put_be16(skb, IFLA_GRE_ENCAP_DPORT,
14074565e991STom Herbert 			 t->encap.dport) ||
14084565e991STom Herbert 	    nla_put_u16(skb, IFLA_GRE_ENCAP_FLAGS,
1409e1b2cb65STom Herbert 			t->encap.flags))
14104565e991STom Herbert 		goto nla_put_failure;
14114565e991STom Herbert 
141222a59be8SPhilip Prindeville 	if (nla_put_u8(skb, IFLA_GRE_IGNORE_DF, t->ignore_df))
141322a59be8SPhilip Prindeville 		goto nla_put_failure;
141422a59be8SPhilip Prindeville 
14152e15ea39SPravin B Shelar 	if (t->collect_md) {
14162e15ea39SPravin B Shelar 		if (nla_put_flag(skb, IFLA_GRE_COLLECT_METADATA))
14172e15ea39SPravin B Shelar 			goto nla_put_failure;
14182e15ea39SPravin B Shelar 	}
14192e15ea39SPravin B Shelar 
142084e54fe0SWilliam Tu 	if (t->index)
142184e54fe0SWilliam Tu 		if (nla_put_u32(skb, IFLA_GRE_ERSPAN_INDEX, t->index))
142284e54fe0SWilliam Tu 			goto nla_put_failure;
142384e54fe0SWilliam Tu 
1424c19e654dSHerbert Xu 	return 0;
1425c19e654dSHerbert Xu 
1426c19e654dSHerbert Xu nla_put_failure:
1427c19e654dSHerbert Xu 	return -EMSGSIZE;
1428c19e654dSHerbert Xu }
1429c19e654dSHerbert Xu 
143084e54fe0SWilliam Tu static void erspan_setup(struct net_device *dev)
143184e54fe0SWilliam Tu {
143284e54fe0SWilliam Tu 	ether_setup(dev);
143384e54fe0SWilliam Tu 	dev->netdev_ops = &erspan_netdev_ops;
143484e54fe0SWilliam Tu 	dev->priv_flags &= ~IFF_TX_SKB_SHARING;
143584e54fe0SWilliam Tu 	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
143684e54fe0SWilliam Tu 	ip_tunnel_setup(dev, erspan_net_id);
143784e54fe0SWilliam Tu }
143884e54fe0SWilliam Tu 
1439c19e654dSHerbert Xu static const struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = {
1440c19e654dSHerbert Xu 	[IFLA_GRE_LINK]		= { .type = NLA_U32 },
1441c19e654dSHerbert Xu 	[IFLA_GRE_IFLAGS]	= { .type = NLA_U16 },
1442c19e654dSHerbert Xu 	[IFLA_GRE_OFLAGS]	= { .type = NLA_U16 },
1443c19e654dSHerbert Xu 	[IFLA_GRE_IKEY]		= { .type = NLA_U32 },
1444c19e654dSHerbert Xu 	[IFLA_GRE_OKEY]		= { .type = NLA_U32 },
14454d74f8baSPatrick McHardy 	[IFLA_GRE_LOCAL]	= { .len = FIELD_SIZEOF(struct iphdr, saddr) },
14464d74f8baSPatrick McHardy 	[IFLA_GRE_REMOTE]	= { .len = FIELD_SIZEOF(struct iphdr, daddr) },
1447c19e654dSHerbert Xu 	[IFLA_GRE_TTL]		= { .type = NLA_U8 },
1448c19e654dSHerbert Xu 	[IFLA_GRE_TOS]		= { .type = NLA_U8 },
1449c19e654dSHerbert Xu 	[IFLA_GRE_PMTUDISC]	= { .type = NLA_U8 },
14504565e991STom Herbert 	[IFLA_GRE_ENCAP_TYPE]	= { .type = NLA_U16 },
14514565e991STom Herbert 	[IFLA_GRE_ENCAP_FLAGS]	= { .type = NLA_U16 },
14524565e991STom Herbert 	[IFLA_GRE_ENCAP_SPORT]	= { .type = NLA_U16 },
14534565e991STom Herbert 	[IFLA_GRE_ENCAP_DPORT]	= { .type = NLA_U16 },
14542e15ea39SPravin B Shelar 	[IFLA_GRE_COLLECT_METADATA]	= { .type = NLA_FLAG },
145522a59be8SPhilip Prindeville 	[IFLA_GRE_IGNORE_DF]	= { .type = NLA_U8 },
14569830ad4cSCraig Gallek 	[IFLA_GRE_FWMARK]	= { .type = NLA_U32 },
145784e54fe0SWilliam Tu 	[IFLA_GRE_ERSPAN_INDEX]	= { .type = NLA_U32 },
1458c19e654dSHerbert Xu };
1459c19e654dSHerbert Xu 
1460c19e654dSHerbert Xu static struct rtnl_link_ops ipgre_link_ops __read_mostly = {
1461c19e654dSHerbert Xu 	.kind		= "gre",
1462c19e654dSHerbert Xu 	.maxtype	= IFLA_GRE_MAX,
1463c19e654dSHerbert Xu 	.policy		= ipgre_policy,
1464c19e654dSHerbert Xu 	.priv_size	= sizeof(struct ip_tunnel),
1465c19e654dSHerbert Xu 	.setup		= ipgre_tunnel_setup,
1466c19e654dSHerbert Xu 	.validate	= ipgre_tunnel_validate,
1467c19e654dSHerbert Xu 	.newlink	= ipgre_newlink,
1468c19e654dSHerbert Xu 	.changelink	= ipgre_changelink,
1469c5441932SPravin B Shelar 	.dellink	= ip_tunnel_dellink,
1470c19e654dSHerbert Xu 	.get_size	= ipgre_get_size,
1471c19e654dSHerbert Xu 	.fill_info	= ipgre_fill_info,
14721728d4faSNicolas Dichtel 	.get_link_net	= ip_tunnel_get_link_net,
1473c19e654dSHerbert Xu };
1474c19e654dSHerbert Xu 
1475e1a80002SHerbert Xu static struct rtnl_link_ops ipgre_tap_ops __read_mostly = {
1476e1a80002SHerbert Xu 	.kind		= "gretap",
1477e1a80002SHerbert Xu 	.maxtype	= IFLA_GRE_MAX,
1478e1a80002SHerbert Xu 	.policy		= ipgre_policy,
1479e1a80002SHerbert Xu 	.priv_size	= sizeof(struct ip_tunnel),
1480e1a80002SHerbert Xu 	.setup		= ipgre_tap_setup,
1481e1a80002SHerbert Xu 	.validate	= ipgre_tap_validate,
1482e1a80002SHerbert Xu 	.newlink	= ipgre_newlink,
1483e1a80002SHerbert Xu 	.changelink	= ipgre_changelink,
1484c5441932SPravin B Shelar 	.dellink	= ip_tunnel_dellink,
1485e1a80002SHerbert Xu 	.get_size	= ipgre_get_size,
1486e1a80002SHerbert Xu 	.fill_info	= ipgre_fill_info,
14871728d4faSNicolas Dichtel 	.get_link_net	= ip_tunnel_get_link_net,
1488e1a80002SHerbert Xu };
1489e1a80002SHerbert Xu 
149084e54fe0SWilliam Tu static struct rtnl_link_ops erspan_link_ops __read_mostly = {
149184e54fe0SWilliam Tu 	.kind		= "erspan",
149284e54fe0SWilliam Tu 	.maxtype	= IFLA_GRE_MAX,
149384e54fe0SWilliam Tu 	.policy		= ipgre_policy,
149484e54fe0SWilliam Tu 	.priv_size	= sizeof(struct ip_tunnel),
149584e54fe0SWilliam Tu 	.setup		= erspan_setup,
149684e54fe0SWilliam Tu 	.validate	= erspan_validate,
149784e54fe0SWilliam Tu 	.newlink	= ipgre_newlink,
149884e54fe0SWilliam Tu 	.changelink	= ipgre_changelink,
149984e54fe0SWilliam Tu 	.dellink	= ip_tunnel_dellink,
150084e54fe0SWilliam Tu 	.get_size	= ipgre_get_size,
150184e54fe0SWilliam Tu 	.fill_info	= ipgre_fill_info,
150284e54fe0SWilliam Tu 	.get_link_net	= ip_tunnel_get_link_net,
150384e54fe0SWilliam Tu };
150484e54fe0SWilliam Tu 
1505b2acd1dcSPravin B Shelar struct net_device *gretap_fb_dev_create(struct net *net, const char *name,
1506b2acd1dcSPravin B Shelar 					u8 name_assign_type)
1507b2acd1dcSPravin B Shelar {
1508b2acd1dcSPravin B Shelar 	struct nlattr *tb[IFLA_MAX + 1];
1509b2acd1dcSPravin B Shelar 	struct net_device *dev;
1510106da663SNicolas Dichtel 	LIST_HEAD(list_kill);
1511b2acd1dcSPravin B Shelar 	struct ip_tunnel *t;
1512b2acd1dcSPravin B Shelar 	int err;
1513b2acd1dcSPravin B Shelar 
1514b2acd1dcSPravin B Shelar 	memset(&tb, 0, sizeof(tb));
1515b2acd1dcSPravin B Shelar 
1516b2acd1dcSPravin B Shelar 	dev = rtnl_create_link(net, name, name_assign_type,
1517b2acd1dcSPravin B Shelar 			       &ipgre_tap_ops, tb);
1518b2acd1dcSPravin B Shelar 	if (IS_ERR(dev))
1519b2acd1dcSPravin B Shelar 		return dev;
1520b2acd1dcSPravin B Shelar 
1521b2acd1dcSPravin B Shelar 	/* Configure flow based GRE device. */
1522b2acd1dcSPravin B Shelar 	t = netdev_priv(dev);
1523b2acd1dcSPravin B Shelar 	t->collect_md = true;
1524b2acd1dcSPravin B Shelar 
15257a3f4a18SMatthias Schiffer 	err = ipgre_newlink(net, dev, tb, NULL, NULL);
1526106da663SNicolas Dichtel 	if (err < 0) {
1527106da663SNicolas Dichtel 		free_netdev(dev);
1528106da663SNicolas Dichtel 		return ERR_PTR(err);
1529106da663SNicolas Dichtel 	}
15307e059158SDavid Wragg 
15317e059158SDavid Wragg 	/* openvswitch users expect packet sizes to be unrestricted,
15327e059158SDavid Wragg 	 * so set the largest MTU we can.
15337e059158SDavid Wragg 	 */
15347e059158SDavid Wragg 	err = __ip_tunnel_change_mtu(dev, IP_MAX_MTU, false);
15357e059158SDavid Wragg 	if (err)
15367e059158SDavid Wragg 		goto out;
15377e059158SDavid Wragg 
1538da6f1da8SNicolas Dichtel 	err = rtnl_configure_link(dev, NULL);
1539da6f1da8SNicolas Dichtel 	if (err < 0)
1540da6f1da8SNicolas Dichtel 		goto out;
1541da6f1da8SNicolas Dichtel 
1542b2acd1dcSPravin B Shelar 	return dev;
1543b2acd1dcSPravin B Shelar out:
1544106da663SNicolas Dichtel 	ip_tunnel_dellink(dev, &list_kill);
1545106da663SNicolas Dichtel 	unregister_netdevice_many(&list_kill);
1546b2acd1dcSPravin B Shelar 	return ERR_PTR(err);
1547b2acd1dcSPravin B Shelar }
1548b2acd1dcSPravin B Shelar EXPORT_SYMBOL_GPL(gretap_fb_dev_create);
1549b2acd1dcSPravin B Shelar 
1550c5441932SPravin B Shelar static int __net_init ipgre_tap_init_net(struct net *net)
1551c5441932SPravin B Shelar {
15522e15ea39SPravin B Shelar 	return ip_tunnel_init_net(net, gre_tap_net_id, &ipgre_tap_ops, "gretap0");
1553c5441932SPravin B Shelar }
1554c5441932SPravin B Shelar 
155564bc1781SEric Dumazet static void __net_exit ipgre_tap_exit_batch_net(struct list_head *list_net)
1556c5441932SPravin B Shelar {
155764bc1781SEric Dumazet 	ip_tunnel_delete_nets(list_net, gre_tap_net_id, &ipgre_tap_ops);
1558c5441932SPravin B Shelar }
1559c5441932SPravin B Shelar 
1560c5441932SPravin B Shelar static struct pernet_operations ipgre_tap_net_ops = {
1561c5441932SPravin B Shelar 	.init = ipgre_tap_init_net,
156264bc1781SEric Dumazet 	.exit_batch = ipgre_tap_exit_batch_net,
1563c5441932SPravin B Shelar 	.id   = &gre_tap_net_id,
1564c5441932SPravin B Shelar 	.size = sizeof(struct ip_tunnel_net),
1565c5441932SPravin B Shelar };
15661da177e4SLinus Torvalds 
156784e54fe0SWilliam Tu static int __net_init erspan_init_net(struct net *net)
156884e54fe0SWilliam Tu {
156984e54fe0SWilliam Tu 	return ip_tunnel_init_net(net, erspan_net_id,
157084e54fe0SWilliam Tu 				  &erspan_link_ops, "erspan0");
157184e54fe0SWilliam Tu }
157284e54fe0SWilliam Tu 
157364bc1781SEric Dumazet static void __net_exit erspan_exit_batch_net(struct list_head *net_list)
157484e54fe0SWilliam Tu {
157564bc1781SEric Dumazet 	ip_tunnel_delete_nets(net_list, erspan_net_id, &erspan_link_ops);
157684e54fe0SWilliam Tu }
157784e54fe0SWilliam Tu 
157884e54fe0SWilliam Tu static struct pernet_operations erspan_net_ops = {
157984e54fe0SWilliam Tu 	.init = erspan_init_net,
158064bc1781SEric Dumazet 	.exit_batch = erspan_exit_batch_net,
158184e54fe0SWilliam Tu 	.id   = &erspan_net_id,
158284e54fe0SWilliam Tu 	.size = sizeof(struct ip_tunnel_net),
158384e54fe0SWilliam Tu };
158484e54fe0SWilliam Tu 
15851da177e4SLinus Torvalds static int __init ipgre_init(void)
15861da177e4SLinus Torvalds {
15871da177e4SLinus Torvalds 	int err;
15881da177e4SLinus Torvalds 
1589058bd4d2SJoe Perches 	pr_info("GRE over IPv4 tunneling driver\n");
15901da177e4SLinus Torvalds 
1591cfb8fbf2SEric W. Biederman 	err = register_pernet_device(&ipgre_net_ops);
159259a4c759SPavel Emelyanov 	if (err < 0)
1593c2892f02SAlexey Dobriyan 		return err;
1594c2892f02SAlexey Dobriyan 
1595c5441932SPravin B Shelar 	err = register_pernet_device(&ipgre_tap_net_ops);
1596c5441932SPravin B Shelar 	if (err < 0)
1597e3d0328cSWilliam Tu 		goto pnet_tap_failed;
1598c5441932SPravin B Shelar 
159984e54fe0SWilliam Tu 	err = register_pernet_device(&erspan_net_ops);
160084e54fe0SWilliam Tu 	if (err < 0)
160184e54fe0SWilliam Tu 		goto pnet_erspan_failed;
160284e54fe0SWilliam Tu 
16039f57c67cSPravin B Shelar 	err = gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO);
1604c2892f02SAlexey Dobriyan 	if (err < 0) {
1605058bd4d2SJoe Perches 		pr_info("%s: can't add protocol\n", __func__);
1606c2892f02SAlexey Dobriyan 		goto add_proto_failed;
1607c2892f02SAlexey Dobriyan 	}
16087daa0004SPavel Emelyanov 
1609c19e654dSHerbert Xu 	err = rtnl_link_register(&ipgre_link_ops);
1610c19e654dSHerbert Xu 	if (err < 0)
1611c19e654dSHerbert Xu 		goto rtnl_link_failed;
1612c19e654dSHerbert Xu 
1613e1a80002SHerbert Xu 	err = rtnl_link_register(&ipgre_tap_ops);
1614e1a80002SHerbert Xu 	if (err < 0)
1615e1a80002SHerbert Xu 		goto tap_ops_failed;
1616e1a80002SHerbert Xu 
161784e54fe0SWilliam Tu 	err = rtnl_link_register(&erspan_link_ops);
161884e54fe0SWilliam Tu 	if (err < 0)
161984e54fe0SWilliam Tu 		goto erspan_link_failed;
162084e54fe0SWilliam Tu 
1621c5441932SPravin B Shelar 	return 0;
1622c19e654dSHerbert Xu 
162384e54fe0SWilliam Tu erspan_link_failed:
162484e54fe0SWilliam Tu 	rtnl_link_unregister(&ipgre_tap_ops);
1625e1a80002SHerbert Xu tap_ops_failed:
1626e1a80002SHerbert Xu 	rtnl_link_unregister(&ipgre_link_ops);
1627c19e654dSHerbert Xu rtnl_link_failed:
16289f57c67cSPravin B Shelar 	gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
1629c2892f02SAlexey Dobriyan add_proto_failed:
163084e54fe0SWilliam Tu 	unregister_pernet_device(&erspan_net_ops);
163184e54fe0SWilliam Tu pnet_erspan_failed:
1632c5441932SPravin B Shelar 	unregister_pernet_device(&ipgre_tap_net_ops);
1633e3d0328cSWilliam Tu pnet_tap_failed:
1634c2892f02SAlexey Dobriyan 	unregister_pernet_device(&ipgre_net_ops);
1635c5441932SPravin B Shelar 	return err;
16361da177e4SLinus Torvalds }
16371da177e4SLinus Torvalds 
1638db44575fSAlexey Kuznetsov static void __exit ipgre_fini(void)
16391da177e4SLinus Torvalds {
1640e1a80002SHerbert Xu 	rtnl_link_unregister(&ipgre_tap_ops);
1641c19e654dSHerbert Xu 	rtnl_link_unregister(&ipgre_link_ops);
164284e54fe0SWilliam Tu 	rtnl_link_unregister(&erspan_link_ops);
16439f57c67cSPravin B Shelar 	gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
1644c5441932SPravin B Shelar 	unregister_pernet_device(&ipgre_tap_net_ops);
1645c2892f02SAlexey Dobriyan 	unregister_pernet_device(&ipgre_net_ops);
164684e54fe0SWilliam Tu 	unregister_pernet_device(&erspan_net_ops);
16471da177e4SLinus Torvalds }
16481da177e4SLinus Torvalds 
16491da177e4SLinus Torvalds module_init(ipgre_init);
16501da177e4SLinus Torvalds module_exit(ipgre_fini);
16511da177e4SLinus Torvalds MODULE_LICENSE("GPL");
16524d74f8baSPatrick McHardy MODULE_ALIAS_RTNL_LINK("gre");
16534d74f8baSPatrick McHardy MODULE_ALIAS_RTNL_LINK("gretap");
165484e54fe0SWilliam Tu MODULE_ALIAS_RTNL_LINK("erspan");
16558909c9adSVasiliy Kulikov MODULE_ALIAS_NETDEV("gre0");
1656c5441932SPravin B Shelar MODULE_ALIAS_NETDEV("gretap0");
165784e54fe0SWilliam Tu MODULE_ALIAS_NETDEV("erspan0");
1658