xref: /linux/net/ipv4/ip_gre.c (revision a0efab67aeb9406e30b6a19dd6dd335e24f6bd66)
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,
1171a66a836SWilliam Tu 				__be32 id, u32 index, bool truncate);
118eb8ce741SPavel Emelyanov 
119c7d03a00SAlexey Dobriyan static unsigned int ipgre_net_id __read_mostly;
120c7d03a00SAlexey Dobriyan static unsigned int gre_tap_net_id __read_mostly;
12184e54fe0SWilliam Tu static unsigned int erspan_net_id __read_mostly;
122eb8ce741SPavel Emelyanov 
1239f57c67cSPravin B Shelar static void ipgre_err(struct sk_buff *skb, u32 info,
124bda7bb46SPravin B Shelar 		      const struct tnl_ptk_info *tpi)
1251da177e4SLinus Torvalds {
1261da177e4SLinus Torvalds 
127071f92d0SRami Rosen 	/* All the routers (except for Linux) return only
1281da177e4SLinus Torvalds 	   8 bytes of packet payload. It means, that precise relaying of
1291da177e4SLinus Torvalds 	   ICMP in the real Internet is absolutely infeasible.
1301da177e4SLinus Torvalds 
1311da177e4SLinus Torvalds 	   Moreover, Cisco "wise men" put GRE key to the third word
132c5441932SPravin B Shelar 	   in GRE header. It makes impossible maintaining even soft
133c5441932SPravin B Shelar 	   state for keyed GRE tunnels with enabled checksum. Tell
134c5441932SPravin B Shelar 	   them "thank you".
1351da177e4SLinus Torvalds 
1361da177e4SLinus Torvalds 	   Well, I wonder, rfc1812 was written by Cisco employee,
137bff52857Sstephen hemminger 	   what the hell these idiots break standards established
138bff52857Sstephen hemminger 	   by themselves???
1391da177e4SLinus Torvalds 	   */
140c5441932SPravin B Shelar 	struct net *net = dev_net(skb->dev);
141c5441932SPravin B Shelar 	struct ip_tunnel_net *itn;
14296f5a846SEric Dumazet 	const struct iphdr *iph;
14388c7664fSArnaldo Carvalho de Melo 	const int type = icmp_hdr(skb)->type;
14488c7664fSArnaldo Carvalho de Melo 	const int code = icmp_hdr(skb)->code;
14520e1954fSEric Dumazet 	unsigned int data_len = 0;
1461da177e4SLinus Torvalds 	struct ip_tunnel *t;
147d2083287Sstephen hemminger 
1481da177e4SLinus Torvalds 	switch (type) {
1491da177e4SLinus Torvalds 	default:
1501da177e4SLinus Torvalds 	case ICMP_PARAMETERPROB:
1519f57c67cSPravin B Shelar 		return;
1521da177e4SLinus Torvalds 
1531da177e4SLinus Torvalds 	case ICMP_DEST_UNREACH:
1541da177e4SLinus Torvalds 		switch (code) {
1551da177e4SLinus Torvalds 		case ICMP_SR_FAILED:
1561da177e4SLinus Torvalds 		case ICMP_PORT_UNREACH:
1571da177e4SLinus Torvalds 			/* Impossible event. */
1589f57c67cSPravin B Shelar 			return;
1591da177e4SLinus Torvalds 		default:
1601da177e4SLinus Torvalds 			/* All others are translated to HOST_UNREACH.
1611da177e4SLinus Torvalds 			   rfc2003 contains "deep thoughts" about NET_UNREACH,
1621da177e4SLinus Torvalds 			   I believe they are just ether pollution. --ANK
1631da177e4SLinus Torvalds 			 */
1641da177e4SLinus Torvalds 			break;
1651da177e4SLinus Torvalds 		}
1661da177e4SLinus Torvalds 		break;
1679f57c67cSPravin B Shelar 
1681da177e4SLinus Torvalds 	case ICMP_TIME_EXCEEDED:
1691da177e4SLinus Torvalds 		if (code != ICMP_EXC_TTL)
1709f57c67cSPravin B Shelar 			return;
17120e1954fSEric Dumazet 		data_len = icmp_hdr(skb)->un.reserved[1] * 4; /* RFC 4884 4.1 */
1721da177e4SLinus Torvalds 		break;
17355be7a9cSDavid S. Miller 
17455be7a9cSDavid S. Miller 	case ICMP_REDIRECT:
17555be7a9cSDavid S. Miller 		break;
1761da177e4SLinus Torvalds 	}
1771da177e4SLinus Torvalds 
178bda7bb46SPravin B Shelar 	if (tpi->proto == htons(ETH_P_TEB))
179c5441932SPravin B Shelar 		itn = net_generic(net, gre_tap_net_id);
180c5441932SPravin B Shelar 	else
181c5441932SPravin B Shelar 		itn = net_generic(net, ipgre_net_id);
182c5441932SPravin B Shelar 
183c0c0c50fSDuan Jiong 	iph = (const struct iphdr *)(icmp_hdr(skb) + 1);
184bda7bb46SPravin B Shelar 	t = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags,
185bda7bb46SPravin B Shelar 			     iph->daddr, iph->saddr, tpi->key);
186d2083287Sstephen hemminger 
18751456b29SIan Morris 	if (!t)
1889f57c67cSPravin B Shelar 		return;
18936393395SDavid S. Miller 
1909b8c6d7bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6)
1919b8c6d7bSEric Dumazet        if (tpi->proto == htons(ETH_P_IPV6) &&
19220e1954fSEric Dumazet            !ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4 + tpi->hdr_len,
19320e1954fSEric Dumazet 				       type, data_len))
1949b8c6d7bSEric Dumazet                return;
1959b8c6d7bSEric Dumazet #endif
1969b8c6d7bSEric Dumazet 
19736393395SDavid S. Miller 	if (t->parms.iph.daddr == 0 ||
198f97c1e0cSJoe Perches 	    ipv4_is_multicast(t->parms.iph.daddr))
1999f57c67cSPravin B Shelar 		return;
2001da177e4SLinus Torvalds 
2011da177e4SLinus Torvalds 	if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
2029f57c67cSPravin B Shelar 		return;
2031da177e4SLinus Torvalds 
204da6185d8SWei Yongjun 	if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO))
2051da177e4SLinus Torvalds 		t->err_count++;
2061da177e4SLinus Torvalds 	else
2071da177e4SLinus Torvalds 		t->err_count = 1;
2081da177e4SLinus Torvalds 	t->err_time = jiffies;
2099f57c67cSPravin B Shelar }
2109f57c67cSPravin B Shelar 
2119f57c67cSPravin B Shelar static void gre_err(struct sk_buff *skb, u32 info)
2129f57c67cSPravin B Shelar {
2139f57c67cSPravin B Shelar 	/* All the routers (except for Linux) return only
2149f57c67cSPravin B Shelar 	 * 8 bytes of packet payload. It means, that precise relaying of
2159f57c67cSPravin B Shelar 	 * ICMP in the real Internet is absolutely infeasible.
2169f57c67cSPravin B Shelar 	 *
2179f57c67cSPravin B Shelar 	 * Moreover, Cisco "wise men" put GRE key to the third word
2189f57c67cSPravin B Shelar 	 * in GRE header. It makes impossible maintaining even soft
2199f57c67cSPravin B Shelar 	 * state for keyed
2209f57c67cSPravin B Shelar 	 * GRE tunnels with enabled checksum. Tell them "thank you".
2219f57c67cSPravin B Shelar 	 *
2229f57c67cSPravin B Shelar 	 * Well, I wonder, rfc1812 was written by Cisco employee,
2239f57c67cSPravin B Shelar 	 * what the hell these idiots break standards established
2249f57c67cSPravin B Shelar 	 * by themselves???
2259f57c67cSPravin B Shelar 	 */
2269f57c67cSPravin B Shelar 
227e582615aSEric Dumazet 	const struct iphdr *iph = (struct iphdr *)skb->data;
2289f57c67cSPravin B Shelar 	const int type = icmp_hdr(skb)->type;
2299f57c67cSPravin B Shelar 	const int code = icmp_hdr(skb)->code;
2309f57c67cSPravin B Shelar 	struct tnl_ptk_info tpi;
2319f57c67cSPravin B Shelar 	bool csum_err = false;
2329f57c67cSPravin B Shelar 
233e582615aSEric Dumazet 	if (gre_parse_header(skb, &tpi, &csum_err, htons(ETH_P_IP),
234e582615aSEric Dumazet 			     iph->ihl * 4) < 0) {
2359f57c67cSPravin B Shelar 		if (!csum_err)		/* ignore csum errors. */
2369f57c67cSPravin B Shelar 			return;
2379f57c67cSPravin B Shelar 	}
2389f57c67cSPravin B Shelar 
2399f57c67cSPravin B Shelar 	if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
2409f57c67cSPravin B Shelar 		ipv4_update_pmtu(skb, dev_net(skb->dev), info,
2419f57c67cSPravin B Shelar 				 skb->dev->ifindex, 0, IPPROTO_GRE, 0);
2429f57c67cSPravin B Shelar 		return;
2439f57c67cSPravin B Shelar 	}
2449f57c67cSPravin B Shelar 	if (type == ICMP_REDIRECT) {
2459f57c67cSPravin B Shelar 		ipv4_redirect(skb, dev_net(skb->dev), skb->dev->ifindex, 0,
2469f57c67cSPravin B Shelar 			      IPPROTO_GRE, 0);
2479f57c67cSPravin B Shelar 		return;
2489f57c67cSPravin B Shelar 	}
2499f57c67cSPravin B Shelar 
2509f57c67cSPravin B Shelar 	ipgre_err(skb, info, &tpi);
2511da177e4SLinus Torvalds }
2521da177e4SLinus Torvalds 
25384e54fe0SWilliam Tu static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
25484e54fe0SWilliam Tu 		      int gre_hdr_len)
25584e54fe0SWilliam Tu {
25684e54fe0SWilliam Tu 	struct net *net = dev_net(skb->dev);
25784e54fe0SWilliam Tu 	struct metadata_dst *tun_dst = NULL;
25884e54fe0SWilliam Tu 	struct ip_tunnel_net *itn;
25984e54fe0SWilliam Tu 	struct ip_tunnel *tunnel;
26084e54fe0SWilliam Tu 	struct erspanhdr *ershdr;
26184e54fe0SWilliam Tu 	const struct iphdr *iph;
26284e54fe0SWilliam Tu 	__be32 index;
26384e54fe0SWilliam Tu 	int len;
26484e54fe0SWilliam Tu 
26584e54fe0SWilliam Tu 	itn = net_generic(net, erspan_net_id);
26684e54fe0SWilliam Tu 	len = gre_hdr_len + sizeof(*ershdr);
26784e54fe0SWilliam Tu 
26884e54fe0SWilliam Tu 	if (unlikely(!pskb_may_pull(skb, len)))
26984e54fe0SWilliam Tu 		return -ENOMEM;
27084e54fe0SWilliam Tu 
27184e54fe0SWilliam Tu 	iph = ip_hdr(skb);
27284e54fe0SWilliam Tu 	ershdr = (struct erspanhdr *)(skb->data + gre_hdr_len);
27384e54fe0SWilliam Tu 
27484e54fe0SWilliam Tu 	/* The original GRE header does not have key field,
27584e54fe0SWilliam Tu 	 * Use ERSPAN 10-bit session ID as key.
27684e54fe0SWilliam Tu 	 */
277935a9749SXin Long 	tpi->key = cpu_to_be32(ntohs(ershdr->session_id) & ID_MASK);
27884e54fe0SWilliam Tu 	index = ershdr->md.index;
27984e54fe0SWilliam Tu 	tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex,
28084e54fe0SWilliam Tu 				  tpi->flags | TUNNEL_KEY,
28184e54fe0SWilliam Tu 				  iph->saddr, iph->daddr, tpi->key);
28284e54fe0SWilliam Tu 
28384e54fe0SWilliam Tu 	if (tunnel) {
28484e54fe0SWilliam Tu 		if (__iptunnel_pull_header(skb,
28584e54fe0SWilliam Tu 					   gre_hdr_len + sizeof(*ershdr),
28684e54fe0SWilliam Tu 					   htons(ETH_P_TEB),
28784e54fe0SWilliam Tu 					   false, false) < 0)
28884e54fe0SWilliam Tu 			goto drop;
28984e54fe0SWilliam Tu 
2901a66a836SWilliam Tu 		if (tunnel->collect_md) {
2911a66a836SWilliam Tu 			struct ip_tunnel_info *info;
2921a66a836SWilliam Tu 			struct erspan_metadata *md;
2931a66a836SWilliam Tu 			__be64 tun_id;
2941a66a836SWilliam Tu 			__be16 flags;
2951a66a836SWilliam Tu 
2961a66a836SWilliam Tu 			tpi->flags |= TUNNEL_KEY;
2971a66a836SWilliam Tu 			flags = tpi->flags;
2981a66a836SWilliam Tu 			tun_id = key32_to_tunnel_id(tpi->key);
2991a66a836SWilliam Tu 
3001a66a836SWilliam Tu 			tun_dst = ip_tun_rx_dst(skb, flags,
3011a66a836SWilliam Tu 						tun_id, sizeof(*md));
3021a66a836SWilliam Tu 			if (!tun_dst)
3031a66a836SWilliam Tu 				return PACKET_REJECT;
3041a66a836SWilliam Tu 
3051a66a836SWilliam Tu 			md = ip_tunnel_info_opts(&tun_dst->u.tun_info);
3061a66a836SWilliam Tu 			if (!md)
3071a66a836SWilliam Tu 				return PACKET_REJECT;
3081a66a836SWilliam Tu 
3091a66a836SWilliam Tu 			md->index = index;
3101a66a836SWilliam Tu 			info = &tun_dst->u.tun_info;
3111a66a836SWilliam Tu 			info->key.tun_flags |= TUNNEL_ERSPAN_OPT;
3121a66a836SWilliam Tu 			info->options_len = sizeof(*md);
3131a66a836SWilliam Tu 		} else {
31484e54fe0SWilliam Tu 			tunnel->index = ntohl(index);
3151a66a836SWilliam Tu 		}
3161a66a836SWilliam Tu 
31784e54fe0SWilliam Tu 		skb_reset_mac_header(skb);
31884e54fe0SWilliam Tu 		ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error);
31984e54fe0SWilliam Tu 		return PACKET_RCVD;
32084e54fe0SWilliam Tu 	}
32184e54fe0SWilliam Tu drop:
32284e54fe0SWilliam Tu 	kfree_skb(skb);
32384e54fe0SWilliam Tu 	return PACKET_RCVD;
32484e54fe0SWilliam Tu }
32584e54fe0SWilliam Tu 
326125372faSJiri Benc static int __ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
327125372faSJiri Benc 		       struct ip_tunnel_net *itn, int hdr_len, bool raw_proto)
3281da177e4SLinus Torvalds {
3292e15ea39SPravin B Shelar 	struct metadata_dst *tun_dst = NULL;
330b71d1d42SEric Dumazet 	const struct iphdr *iph;
3311da177e4SLinus Torvalds 	struct ip_tunnel *tunnel;
3321da177e4SLinus Torvalds 
333eddc9ec5SArnaldo Carvalho de Melo 	iph = ip_hdr(skb);
334bda7bb46SPravin B Shelar 	tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags,
335bda7bb46SPravin B Shelar 				  iph->saddr, iph->daddr, tpi->key);
3361da177e4SLinus Torvalds 
337d2083287Sstephen hemminger 	if (tunnel) {
338125372faSJiri Benc 		if (__iptunnel_pull_header(skb, hdr_len, tpi->proto,
339125372faSJiri Benc 					   raw_proto, false) < 0)
340244a797bSJiri Benc 			goto drop;
341244a797bSJiri Benc 
342e271c7b4SJiri Benc 		if (tunnel->dev->type != ARPHRD_NONE)
3430e3da5bbSTimo Teräs 			skb_pop_mac_header(skb);
344e271c7b4SJiri Benc 		else
345e271c7b4SJiri Benc 			skb_reset_mac_header(skb);
3462e15ea39SPravin B Shelar 		if (tunnel->collect_md) {
347c29a70d2SPravin B Shelar 			__be16 flags;
348c29a70d2SPravin B Shelar 			__be64 tun_id;
3492e15ea39SPravin B Shelar 
350c29a70d2SPravin B Shelar 			flags = tpi->flags & (TUNNEL_CSUM | TUNNEL_KEY);
351d817f432SAmir Vadai 			tun_id = key32_to_tunnel_id(tpi->key);
352c29a70d2SPravin B Shelar 			tun_dst = ip_tun_rx_dst(skb, flags, tun_id, 0);
3532e15ea39SPravin B Shelar 			if (!tun_dst)
3542e15ea39SPravin B Shelar 				return PACKET_REJECT;
3552e15ea39SPravin B Shelar 		}
3562e15ea39SPravin B Shelar 
3572e15ea39SPravin B Shelar 		ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error);
358bda7bb46SPravin B Shelar 		return PACKET_RCVD;
3591da177e4SLinus Torvalds 	}
360125372faSJiri Benc 	return PACKET_NEXT;
361244a797bSJiri Benc 
362244a797bSJiri Benc drop:
363244a797bSJiri Benc 	kfree_skb(skb);
364244a797bSJiri Benc 	return PACKET_RCVD;
3651da177e4SLinus Torvalds }
3661da177e4SLinus Torvalds 
367125372faSJiri Benc static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
368125372faSJiri Benc 		     int hdr_len)
369125372faSJiri Benc {
370125372faSJiri Benc 	struct net *net = dev_net(skb->dev);
371125372faSJiri Benc 	struct ip_tunnel_net *itn;
372125372faSJiri Benc 	int res;
373125372faSJiri Benc 
374125372faSJiri Benc 	if (tpi->proto == htons(ETH_P_TEB))
375125372faSJiri Benc 		itn = net_generic(net, gre_tap_net_id);
376125372faSJiri Benc 	else
377125372faSJiri Benc 		itn = net_generic(net, ipgre_net_id);
378125372faSJiri Benc 
379125372faSJiri Benc 	res = __ipgre_rcv(skb, tpi, itn, hdr_len, false);
380125372faSJiri Benc 	if (res == PACKET_NEXT && tpi->proto == htons(ETH_P_TEB)) {
381125372faSJiri Benc 		/* ipgre tunnels in collect metadata mode should receive
382125372faSJiri Benc 		 * also ETH_P_TEB traffic.
383125372faSJiri Benc 		 */
384125372faSJiri Benc 		itn = net_generic(net, ipgre_net_id);
385125372faSJiri Benc 		res = __ipgre_rcv(skb, tpi, itn, hdr_len, true);
386125372faSJiri Benc 	}
387125372faSJiri Benc 	return res;
388125372faSJiri Benc }
389125372faSJiri Benc 
3909f57c67cSPravin B Shelar static int gre_rcv(struct sk_buff *skb)
3919f57c67cSPravin B Shelar {
3929f57c67cSPravin B Shelar 	struct tnl_ptk_info tpi;
3939f57c67cSPravin B Shelar 	bool csum_err = false;
39495f5c64cSTom Herbert 	int hdr_len;
3959f57c67cSPravin B Shelar 
3969f57c67cSPravin B Shelar #ifdef CONFIG_NET_IPGRE_BROADCAST
3979f57c67cSPravin B Shelar 	if (ipv4_is_multicast(ip_hdr(skb)->daddr)) {
3989f57c67cSPravin B Shelar 		/* Looped back packet, drop it! */
3999f57c67cSPravin B Shelar 		if (rt_is_output_route(skb_rtable(skb)))
4009f57c67cSPravin B Shelar 			goto drop;
4019f57c67cSPravin B Shelar 	}
4029f57c67cSPravin B Shelar #endif
4039f57c67cSPravin B Shelar 
404e582615aSEric Dumazet 	hdr_len = gre_parse_header(skb, &tpi, &csum_err, htons(ETH_P_IP), 0);
405f132ae7cSJiri Benc 	if (hdr_len < 0)
40695f5c64cSTom Herbert 		goto drop;
40795f5c64cSTom Herbert 
40884e54fe0SWilliam Tu 	if (unlikely(tpi.proto == htons(ETH_P_ERSPAN))) {
40984e54fe0SWilliam Tu 		if (erspan_rcv(skb, &tpi, hdr_len) == PACKET_RCVD)
41084e54fe0SWilliam Tu 			return 0;
41184e54fe0SWilliam Tu 	}
41284e54fe0SWilliam Tu 
413244a797bSJiri Benc 	if (ipgre_rcv(skb, &tpi, hdr_len) == PACKET_RCVD)
4149f57c67cSPravin B Shelar 		return 0;
4159f57c67cSPravin B Shelar 
4169f57c67cSPravin B Shelar 	icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
4179f57c67cSPravin B Shelar drop:
4189f57c67cSPravin B Shelar 	kfree_skb(skb);
4199f57c67cSPravin B Shelar 	return 0;
4209f57c67cSPravin B Shelar }
4219f57c67cSPravin B Shelar 
422c5441932SPravin B Shelar static void __gre_xmit(struct sk_buff *skb, struct net_device *dev,
423c5441932SPravin B Shelar 		       const struct iphdr *tnl_params,
424c5441932SPravin B Shelar 		       __be16 proto)
425c5441932SPravin B Shelar {
426c5441932SPravin B Shelar 	struct ip_tunnel *tunnel = netdev_priv(dev);
427c5441932SPravin B Shelar 
428c5441932SPravin B Shelar 	if (tunnel->parms.o_flags & TUNNEL_SEQ)
429c5441932SPravin B Shelar 		tunnel->o_seqno++;
430cef401deSEric Dumazet 
431c5441932SPravin B Shelar 	/* Push GRE header. */
432182a352dSTom Herbert 	gre_build_header(skb, tunnel->tun_hlen,
433182a352dSTom Herbert 			 tunnel->parms.o_flags, proto, tunnel->parms.o_key,
434182a352dSTom Herbert 			 htonl(tunnel->o_seqno));
4351da177e4SLinus Torvalds 
436bf3d6a8fSNicolas Dichtel 	ip_tunnel_xmit(skb, dev, tnl_params, tnl_params->protocol);
4371da177e4SLinus Torvalds }
4381da177e4SLinus Torvalds 
439aed069dfSAlexander Duyck static int gre_handle_offloads(struct sk_buff *skb, bool csum)
440b2acd1dcSPravin B Shelar {
4416fa79666SEdward Cree 	return iptunnel_handle_offloads(skb, csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE);
442b2acd1dcSPravin B Shelar }
443b2acd1dcSPravin B Shelar 
444fc4099f1SPravin B Shelar static struct rtable *gre_get_rt(struct sk_buff *skb,
445fc4099f1SPravin B Shelar 				 struct net_device *dev,
446fc4099f1SPravin B Shelar 				 struct flowi4 *fl,
447fc4099f1SPravin B Shelar 				 const struct ip_tunnel_key *key)
448fc4099f1SPravin B Shelar {
449fc4099f1SPravin B Shelar 	struct net *net = dev_net(dev);
450fc4099f1SPravin B Shelar 
451fc4099f1SPravin B Shelar 	memset(fl, 0, sizeof(*fl));
452fc4099f1SPravin B Shelar 	fl->daddr = key->u.ipv4.dst;
453fc4099f1SPravin B Shelar 	fl->saddr = key->u.ipv4.src;
454fc4099f1SPravin B Shelar 	fl->flowi4_tos = RT_TOS(key->tos);
455fc4099f1SPravin B Shelar 	fl->flowi4_mark = skb->mark;
456fc4099f1SPravin B Shelar 	fl->flowi4_proto = IPPROTO_GRE;
457fc4099f1SPravin B Shelar 
458fc4099f1SPravin B Shelar 	return ip_route_output_key(net, fl);
459fc4099f1SPravin B Shelar }
460fc4099f1SPravin B Shelar 
461862a03c3SWilliam Tu static struct rtable *prepare_fb_xmit(struct sk_buff *skb,
462862a03c3SWilliam Tu 				      struct net_device *dev,
463862a03c3SWilliam Tu 				      struct flowi4 *fl,
464862a03c3SWilliam Tu 				      int tunnel_hlen)
4652e15ea39SPravin B Shelar {
4662e15ea39SPravin B Shelar 	struct ip_tunnel_info *tun_info;
4672e15ea39SPravin B Shelar 	const struct ip_tunnel_key *key;
468db3c6139SDaniel Borkmann 	struct rtable *rt = NULL;
4692e15ea39SPravin B Shelar 	int min_headroom;
470db3c6139SDaniel Borkmann 	bool use_cache;
4712e15ea39SPravin B Shelar 	int err;
4722e15ea39SPravin B Shelar 
47361adedf3SJiri Benc 	tun_info = skb_tunnel_info(skb);
4742e15ea39SPravin B Shelar 	key = &tun_info->key;
475db3c6139SDaniel Borkmann 	use_cache = ip_tunnel_dst_cache_usable(skb, tun_info);
476862a03c3SWilliam Tu 
477db3c6139SDaniel Borkmann 	if (use_cache)
478862a03c3SWilliam Tu 		rt = dst_cache_get_ip4(&tun_info->dst_cache, &fl->saddr);
4793c1cb4d2SPaolo Abeni 	if (!rt) {
480862a03c3SWilliam Tu 		rt = gre_get_rt(skb, dev, fl, key);
4812e15ea39SPravin B Shelar 		if (IS_ERR(rt))
4822e15ea39SPravin B Shelar 			goto err_free_skb;
483db3c6139SDaniel Borkmann 		if (use_cache)
4843c1cb4d2SPaolo Abeni 			dst_cache_set_ip4(&tun_info->dst_cache, &rt->dst,
485862a03c3SWilliam Tu 					  fl->saddr);
4863c1cb4d2SPaolo Abeni 	}
4872e15ea39SPravin B Shelar 
4882e15ea39SPravin B Shelar 	min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len
4892e15ea39SPravin B Shelar 			+ tunnel_hlen + sizeof(struct iphdr);
4902e15ea39SPravin B Shelar 	if (skb_headroom(skb) < min_headroom || skb_header_cloned(skb)) {
4912e15ea39SPravin B Shelar 		int head_delta = SKB_DATA_ALIGN(min_headroom -
4922e15ea39SPravin B Shelar 						skb_headroom(skb) +
4932e15ea39SPravin B Shelar 						16);
4942e15ea39SPravin B Shelar 		err = pskb_expand_head(skb, max_t(int, head_delta, 0),
4952e15ea39SPravin B Shelar 				       0, GFP_ATOMIC);
4962e15ea39SPravin B Shelar 		if (unlikely(err))
4972e15ea39SPravin B Shelar 			goto err_free_rt;
4982e15ea39SPravin B Shelar 	}
499862a03c3SWilliam Tu 	return rt;
500862a03c3SWilliam Tu 
501862a03c3SWilliam Tu err_free_rt:
502862a03c3SWilliam Tu 	ip_rt_put(rt);
503862a03c3SWilliam Tu err_free_skb:
504862a03c3SWilliam Tu 	kfree_skb(skb);
505862a03c3SWilliam Tu 	dev->stats.tx_dropped++;
506862a03c3SWilliam Tu 	return NULL;
507862a03c3SWilliam Tu }
508862a03c3SWilliam Tu 
509862a03c3SWilliam Tu static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev,
510862a03c3SWilliam Tu 			__be16 proto)
511862a03c3SWilliam Tu {
512862a03c3SWilliam Tu 	struct ip_tunnel_info *tun_info;
513862a03c3SWilliam Tu 	const struct ip_tunnel_key *key;
514862a03c3SWilliam Tu 	struct rtable *rt = NULL;
515862a03c3SWilliam Tu 	struct flowi4 fl;
516862a03c3SWilliam Tu 	int tunnel_hlen;
517862a03c3SWilliam Tu 	__be16 df, flags;
518862a03c3SWilliam Tu 
519862a03c3SWilliam Tu 	tun_info = skb_tunnel_info(skb);
520862a03c3SWilliam Tu 	if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) ||
521862a03c3SWilliam Tu 		     ip_tunnel_info_af(tun_info) != AF_INET))
522862a03c3SWilliam Tu 		goto err_free_skb;
523862a03c3SWilliam Tu 
524862a03c3SWilliam Tu 	key = &tun_info->key;
525862a03c3SWilliam Tu 	tunnel_hlen = gre_calc_hlen(key->tun_flags);
526862a03c3SWilliam Tu 
527862a03c3SWilliam Tu 	rt = prepare_fb_xmit(skb, dev, &fl, tunnel_hlen);
528862a03c3SWilliam Tu 	if (!rt)
529862a03c3SWilliam Tu 		return;
5302e15ea39SPravin B Shelar 
5312e15ea39SPravin B Shelar 	/* Push Tunnel header. */
532aed069dfSAlexander Duyck 	if (gre_handle_offloads(skb, !!(tun_info->key.tun_flags & TUNNEL_CSUM)))
5332e15ea39SPravin B Shelar 		goto err_free_rt;
5342e15ea39SPravin B Shelar 
5352e15ea39SPravin B Shelar 	flags = tun_info->key.tun_flags & (TUNNEL_CSUM | TUNNEL_KEY);
536cba65321SDavid S. Miller 	gre_build_header(skb, tunnel_hlen, flags, proto,
537d817f432SAmir Vadai 			 tunnel_id_to_key32(tun_info->key.tun_id), 0);
5382e15ea39SPravin B Shelar 
5392e15ea39SPravin B Shelar 	df = key->tun_flags & TUNNEL_DONT_FRAGMENT ?  htons(IP_DF) : 0;
540039f5062SPravin B Shelar 
541039f5062SPravin B Shelar 	iptunnel_xmit(skb->sk, rt, skb, fl.saddr, key->u.ipv4.dst, IPPROTO_GRE,
5427c383fb2SJiri Benc 		      key->tos, key->ttl, df, false);
5432e15ea39SPravin B Shelar 	return;
5442e15ea39SPravin B Shelar 
5452e15ea39SPravin B Shelar err_free_rt:
5462e15ea39SPravin B Shelar 	ip_rt_put(rt);
5472e15ea39SPravin B Shelar err_free_skb:
5482e15ea39SPravin B Shelar 	kfree_skb(skb);
5492e15ea39SPravin B Shelar 	dev->stats.tx_dropped++;
5502e15ea39SPravin B Shelar }
5512e15ea39SPravin B Shelar 
5521a66a836SWilliam Tu static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev,
5531a66a836SWilliam Tu 			   __be16 proto)
5541a66a836SWilliam Tu {
5551a66a836SWilliam Tu 	struct ip_tunnel *tunnel = netdev_priv(dev);
5561a66a836SWilliam Tu 	struct ip_tunnel_info *tun_info;
5571a66a836SWilliam Tu 	const struct ip_tunnel_key *key;
5581a66a836SWilliam Tu 	struct erspan_metadata *md;
5591a66a836SWilliam Tu 	struct rtable *rt = NULL;
5601a66a836SWilliam Tu 	bool truncate = false;
5611a66a836SWilliam Tu 	struct flowi4 fl;
5621a66a836SWilliam Tu 	int tunnel_hlen;
5631a66a836SWilliam Tu 	__be16 df;
5641a66a836SWilliam Tu 
5651a66a836SWilliam Tu 	tun_info = skb_tunnel_info(skb);
5661a66a836SWilliam Tu 	if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) ||
5671a66a836SWilliam Tu 		     ip_tunnel_info_af(tun_info) != AF_INET))
5681a66a836SWilliam Tu 		goto err_free_skb;
5691a66a836SWilliam Tu 
5701a66a836SWilliam Tu 	key = &tun_info->key;
5711a66a836SWilliam Tu 
5721a66a836SWilliam Tu 	/* ERSPAN has fixed 8 byte GRE header */
5731a66a836SWilliam Tu 	tunnel_hlen = 8 + sizeof(struct erspanhdr);
5741a66a836SWilliam Tu 
5751a66a836SWilliam Tu 	rt = prepare_fb_xmit(skb, dev, &fl, tunnel_hlen);
5761a66a836SWilliam Tu 	if (!rt)
5771a66a836SWilliam Tu 		return;
5781a66a836SWilliam Tu 
5791a66a836SWilliam Tu 	if (gre_handle_offloads(skb, false))
5801a66a836SWilliam Tu 		goto err_free_rt;
5811a66a836SWilliam Tu 
582f192970dSWilliam Tu 	if (skb->len > dev->mtu + dev->hard_header_len) {
583f192970dSWilliam Tu 		pskb_trim(skb, dev->mtu + dev->hard_header_len);
5841a66a836SWilliam Tu 		truncate = true;
5851a66a836SWilliam Tu 	}
5861a66a836SWilliam Tu 
5871a66a836SWilliam Tu 	md = ip_tunnel_info_opts(tun_info);
5881a66a836SWilliam Tu 	if (!md)
5891a66a836SWilliam Tu 		goto err_free_rt;
5901a66a836SWilliam Tu 
5911a66a836SWilliam Tu 	erspan_build_header(skb, tunnel_id_to_key32(key->tun_id),
5921a66a836SWilliam Tu 			    ntohl(md->index), truncate);
5931a66a836SWilliam Tu 
5941a66a836SWilliam Tu 	gre_build_header(skb, 8, TUNNEL_SEQ,
5951a66a836SWilliam Tu 			 htons(ETH_P_ERSPAN), 0, htonl(tunnel->o_seqno++));
5961a66a836SWilliam Tu 
5971a66a836SWilliam Tu 	df = key->tun_flags & TUNNEL_DONT_FRAGMENT ?  htons(IP_DF) : 0;
5981a66a836SWilliam Tu 
5991a66a836SWilliam Tu 	iptunnel_xmit(skb->sk, rt, skb, fl.saddr, key->u.ipv4.dst, IPPROTO_GRE,
6001a66a836SWilliam Tu 		      key->tos, key->ttl, df, false);
6011a66a836SWilliam Tu 	return;
6021a66a836SWilliam Tu 
6031a66a836SWilliam Tu err_free_rt:
6041a66a836SWilliam Tu 	ip_rt_put(rt);
6051a66a836SWilliam Tu err_free_skb:
6061a66a836SWilliam Tu 	kfree_skb(skb);
6071a66a836SWilliam Tu 	dev->stats.tx_dropped++;
6081a66a836SWilliam Tu }
6091a66a836SWilliam Tu 
610fc4099f1SPravin B Shelar static int gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
611fc4099f1SPravin B Shelar {
612fc4099f1SPravin B Shelar 	struct ip_tunnel_info *info = skb_tunnel_info(skb);
613fc4099f1SPravin B Shelar 	struct rtable *rt;
614fc4099f1SPravin B Shelar 	struct flowi4 fl4;
615fc4099f1SPravin B Shelar 
616fc4099f1SPravin B Shelar 	if (ip_tunnel_info_af(info) != AF_INET)
617fc4099f1SPravin B Shelar 		return -EINVAL;
618fc4099f1SPravin B Shelar 
619fc4099f1SPravin B Shelar 	rt = gre_get_rt(skb, dev, &fl4, &info->key);
620fc4099f1SPravin B Shelar 	if (IS_ERR(rt))
621fc4099f1SPravin B Shelar 		return PTR_ERR(rt);
622fc4099f1SPravin B Shelar 
623fc4099f1SPravin B Shelar 	ip_rt_put(rt);
624fc4099f1SPravin B Shelar 	info->key.u.ipv4.src = fl4.saddr;
625fc4099f1SPravin B Shelar 	return 0;
626fc4099f1SPravin B Shelar }
627fc4099f1SPravin B Shelar 
628c5441932SPravin B Shelar static netdev_tx_t ipgre_xmit(struct sk_buff *skb,
629c5441932SPravin B Shelar 			      struct net_device *dev)
630ee34c1ebSMichal Schmidt {
631c5441932SPravin B Shelar 	struct ip_tunnel *tunnel = netdev_priv(dev);
632c5441932SPravin B Shelar 	const struct iphdr *tnl_params;
633ee34c1ebSMichal Schmidt 
6342e15ea39SPravin B Shelar 	if (tunnel->collect_md) {
6352090714eSJiri Benc 		gre_fb_xmit(skb, dev, skb->protocol);
6362e15ea39SPravin B Shelar 		return NETDEV_TX_OK;
6372e15ea39SPravin B Shelar 	}
6382e15ea39SPravin B Shelar 
639c5441932SPravin B Shelar 	if (dev->header_ops) {
640c5441932SPravin B Shelar 		/* Need space for new headers */
641c5441932SPravin B Shelar 		if (skb_cow_head(skb, dev->needed_headroom -
6422bac7cb3SChen Gang 				      (tunnel->hlen + sizeof(struct iphdr))))
643c5441932SPravin B Shelar 			goto free_skb;
644ee34c1ebSMichal Schmidt 
645c5441932SPravin B Shelar 		tnl_params = (const struct iphdr *)skb->data;
646cbb1e85fSDavid S. Miller 
647c5441932SPravin B Shelar 		/* Pull skb since ip_tunnel_xmit() needs skb->data pointing
648c5441932SPravin B Shelar 		 * to gre header.
649c5441932SPravin B Shelar 		 */
650c5441932SPravin B Shelar 		skb_pull(skb, tunnel->hlen + sizeof(struct iphdr));
6518a0033a9STimo Teräs 		skb_reset_mac_header(skb);
652c5441932SPravin B Shelar 	} else {
653c5441932SPravin B Shelar 		if (skb_cow_head(skb, dev->needed_headroom))
654c5441932SPravin B Shelar 			goto free_skb;
655c5441932SPravin B Shelar 
656c5441932SPravin B Shelar 		tnl_params = &tunnel->parms.iph;
657ee34c1ebSMichal Schmidt 	}
658e1a80002SHerbert Xu 
659aed069dfSAlexander Duyck 	if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM)))
660aed069dfSAlexander Duyck 		goto free_skb;
6618a0033a9STimo Teräs 
662c5441932SPravin B Shelar 	__gre_xmit(skb, dev, tnl_params, skb->protocol);
663c5441932SPravin B Shelar 	return NETDEV_TX_OK;
664c5441932SPravin B Shelar 
665c5441932SPravin B Shelar free_skb:
6663acfa1e7SEric Dumazet 	kfree_skb(skb);
667c5441932SPravin B Shelar 	dev->stats.tx_dropped++;
668c5441932SPravin B Shelar 	return NETDEV_TX_OK;
669ee34c1ebSMichal Schmidt }
670ee34c1ebSMichal Schmidt 
67184e54fe0SWilliam Tu static inline u8 tos_to_cos(u8 tos)
67284e54fe0SWilliam Tu {
67384e54fe0SWilliam Tu 	u8 dscp, cos;
67484e54fe0SWilliam Tu 
67584e54fe0SWilliam Tu 	dscp = tos >> 2;
67684e54fe0SWilliam Tu 	cos = dscp >> 3;
67784e54fe0SWilliam Tu 	return cos;
67884e54fe0SWilliam Tu }
67984e54fe0SWilliam Tu 
68084e54fe0SWilliam Tu static void erspan_build_header(struct sk_buff *skb,
68184e54fe0SWilliam Tu 				__be32 id, u32 index, bool truncate)
68284e54fe0SWilliam Tu {
68384e54fe0SWilliam Tu 	struct iphdr *iphdr = ip_hdr(skb);
68484e54fe0SWilliam Tu 	struct ethhdr *eth = eth_hdr(skb);
68584e54fe0SWilliam Tu 	enum erspan_encap_type enc_type;
68684e54fe0SWilliam Tu 	struct erspanhdr *ershdr;
68784e54fe0SWilliam Tu 	struct qtag_prefix {
68884e54fe0SWilliam Tu 		__be16 eth_type;
68984e54fe0SWilliam Tu 		__be16 tci;
69084e54fe0SWilliam Tu 	} *qp;
69184e54fe0SWilliam Tu 	u16 vlan_tci = 0;
69284e54fe0SWilliam Tu 
69384e54fe0SWilliam Tu 	enc_type = ERSPAN_ENCAP_NOVLAN;
69484e54fe0SWilliam Tu 
69584e54fe0SWilliam Tu 	/* If mirrored packet has vlan tag, extract tci and
69684e54fe0SWilliam Tu 	 *  perserve vlan header in the mirrored frame.
69784e54fe0SWilliam Tu 	 */
69884e54fe0SWilliam Tu 	if (eth->h_proto == htons(ETH_P_8021Q)) {
69984e54fe0SWilliam Tu 		qp = (struct qtag_prefix *)(skb->data + 2 * ETH_ALEN);
70084e54fe0SWilliam Tu 		vlan_tci = ntohs(qp->tci);
70184e54fe0SWilliam Tu 		enc_type = ERSPAN_ENCAP_INFRAME;
70284e54fe0SWilliam Tu 	}
70384e54fe0SWilliam Tu 
70484e54fe0SWilliam Tu 	skb_push(skb, sizeof(*ershdr));
70584e54fe0SWilliam Tu 	ershdr = (struct erspanhdr *)skb->data;
70684e54fe0SWilliam Tu 	memset(ershdr, 0, sizeof(*ershdr));
70784e54fe0SWilliam Tu 
70884e54fe0SWilliam Tu 	ershdr->ver_vlan = htons((vlan_tci & VLAN_MASK) |
70984e54fe0SWilliam Tu 				 (ERSPAN_VERSION << VER_OFFSET));
71084e54fe0SWilliam Tu 	ershdr->session_id = htons((u16)(ntohl(id) & ID_MASK) |
71184e54fe0SWilliam Tu 			   ((tos_to_cos(iphdr->tos) << COS_OFFSET) & COS_MASK) |
71284e54fe0SWilliam Tu 			   (enc_type << EN_OFFSET & EN_MASK) |
71384e54fe0SWilliam Tu 			   ((truncate << T_OFFSET) & T_MASK));
71484e54fe0SWilliam Tu 	ershdr->md.index = htonl(index & INDEX_MASK);
71584e54fe0SWilliam Tu }
71684e54fe0SWilliam Tu 
71784e54fe0SWilliam Tu static netdev_tx_t erspan_xmit(struct sk_buff *skb,
71884e54fe0SWilliam Tu 			       struct net_device *dev)
71984e54fe0SWilliam Tu {
72084e54fe0SWilliam Tu 	struct ip_tunnel *tunnel = netdev_priv(dev);
72184e54fe0SWilliam Tu 	bool truncate = false;
72284e54fe0SWilliam Tu 
7231a66a836SWilliam Tu 	if (tunnel->collect_md) {
7241a66a836SWilliam Tu 		erspan_fb_xmit(skb, dev, skb->protocol);
7251a66a836SWilliam Tu 		return NETDEV_TX_OK;
7261a66a836SWilliam Tu 	}
7271a66a836SWilliam Tu 
72884e54fe0SWilliam Tu 	if (gre_handle_offloads(skb, false))
72984e54fe0SWilliam Tu 		goto free_skb;
73084e54fe0SWilliam Tu 
73184e54fe0SWilliam Tu 	if (skb_cow_head(skb, dev->needed_headroom))
73284e54fe0SWilliam Tu 		goto free_skb;
73384e54fe0SWilliam Tu 
734f192970dSWilliam Tu 	if (skb->len > dev->mtu + dev->hard_header_len) {
735f192970dSWilliam Tu 		pskb_trim(skb, dev->mtu + dev->hard_header_len);
73684e54fe0SWilliam Tu 		truncate = true;
73784e54fe0SWilliam Tu 	}
73884e54fe0SWilliam Tu 
73984e54fe0SWilliam Tu 	/* Push ERSPAN header */
74084e54fe0SWilliam Tu 	erspan_build_header(skb, tunnel->parms.o_key, tunnel->index, truncate);
74184e54fe0SWilliam Tu 	tunnel->parms.o_flags &= ~TUNNEL_KEY;
74284e54fe0SWilliam Tu 	__gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_ERSPAN));
74384e54fe0SWilliam Tu 	return NETDEV_TX_OK;
74484e54fe0SWilliam Tu 
74584e54fe0SWilliam Tu free_skb:
74684e54fe0SWilliam Tu 	kfree_skb(skb);
74784e54fe0SWilliam Tu 	dev->stats.tx_dropped++;
74884e54fe0SWilliam Tu 	return NETDEV_TX_OK;
74984e54fe0SWilliam Tu }
75084e54fe0SWilliam Tu 
751c5441932SPravin B Shelar static netdev_tx_t gre_tap_xmit(struct sk_buff *skb,
752c5441932SPravin B Shelar 				struct net_device *dev)
753c5441932SPravin B Shelar {
754c5441932SPravin B Shelar 	struct ip_tunnel *tunnel = netdev_priv(dev);
755ee34c1ebSMichal Schmidt 
7562e15ea39SPravin B Shelar 	if (tunnel->collect_md) {
7572090714eSJiri Benc 		gre_fb_xmit(skb, dev, htons(ETH_P_TEB));
7582e15ea39SPravin B Shelar 		return NETDEV_TX_OK;
7592e15ea39SPravin B Shelar 	}
7602e15ea39SPravin B Shelar 
761aed069dfSAlexander Duyck 	if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM)))
762aed069dfSAlexander Duyck 		goto free_skb;
763ee34c1ebSMichal Schmidt 
764c5441932SPravin B Shelar 	if (skb_cow_head(skb, dev->needed_headroom))
765c5441932SPravin B Shelar 		goto free_skb;
76642aa9162SHerbert Xu 
767c5441932SPravin B Shelar 	__gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_TEB));
768c5441932SPravin B Shelar 	return NETDEV_TX_OK;
769c5441932SPravin B Shelar 
770c5441932SPravin B Shelar free_skb:
7713acfa1e7SEric Dumazet 	kfree_skb(skb);
772c5441932SPravin B Shelar 	dev->stats.tx_dropped++;
773c5441932SPravin B Shelar 	return NETDEV_TX_OK;
77468c33163SPravin B Shelar }
775ee34c1ebSMichal Schmidt 
776dd9d598cSXin Long static void ipgre_link_update(struct net_device *dev, bool set_mtu)
777dd9d598cSXin Long {
778dd9d598cSXin Long 	struct ip_tunnel *tunnel = netdev_priv(dev);
779dd9d598cSXin Long 	int len;
780dd9d598cSXin Long 
781dd9d598cSXin Long 	len = tunnel->tun_hlen;
782dd9d598cSXin Long 	tunnel->tun_hlen = gre_calc_hlen(tunnel->parms.o_flags);
783dd9d598cSXin Long 	len = tunnel->tun_hlen - len;
784dd9d598cSXin Long 	tunnel->hlen = tunnel->hlen + len;
785dd9d598cSXin Long 
786dd9d598cSXin Long 	dev->needed_headroom = dev->needed_headroom + len;
787dd9d598cSXin Long 	if (set_mtu)
788dd9d598cSXin Long 		dev->mtu = max_t(int, dev->mtu - len, 68);
789dd9d598cSXin Long 
790dd9d598cSXin Long 	if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) {
791dd9d598cSXin Long 		if (!(tunnel->parms.o_flags & TUNNEL_CSUM) ||
792dd9d598cSXin Long 		    tunnel->encap.type == TUNNEL_ENCAP_NONE) {
793dd9d598cSXin Long 			dev->features |= NETIF_F_GSO_SOFTWARE;
794dd9d598cSXin Long 			dev->hw_features |= NETIF_F_GSO_SOFTWARE;
795dd9d598cSXin Long 		}
796dd9d598cSXin Long 		dev->features |= NETIF_F_LLTX;
797dd9d598cSXin Long 	}
798dd9d598cSXin Long }
799dd9d598cSXin Long 
800c5441932SPravin B Shelar static int ipgre_tunnel_ioctl(struct net_device *dev,
801c5441932SPravin B Shelar 			      struct ifreq *ifr, int cmd)
8021da177e4SLinus Torvalds {
8031da177e4SLinus Torvalds 	struct ip_tunnel_parm p;
804*a0efab67SXin Long 	int err;
8051da177e4SLinus Torvalds 
8061da177e4SLinus Torvalds 	if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
807c5441932SPravin B Shelar 		return -EFAULT;
808*a0efab67SXin Long 
8096c734fb8SCong Wang 	if (cmd == SIOCADDTUNNEL || cmd == SIOCCHGTUNNEL) {
8101da177e4SLinus Torvalds 		if (p.iph.version != 4 || p.iph.protocol != IPPROTO_GRE ||
8111da177e4SLinus Torvalds 		    p.iph.ihl != 5 || (p.iph.frag_off & htons(~IP_DF)) ||
8126c734fb8SCong Wang 		    ((p.i_flags | p.o_flags) & (GRE_VERSION | GRE_ROUTING)))
8131da177e4SLinus Torvalds 			return -EINVAL;
814c5441932SPravin B Shelar 	}
815*a0efab67SXin Long 
816c5441932SPravin B Shelar 	p.i_flags = gre_flags_to_tnl_flags(p.i_flags);
817c5441932SPravin B Shelar 	p.o_flags = gre_flags_to_tnl_flags(p.o_flags);
818c5441932SPravin B Shelar 
819c5441932SPravin B Shelar 	err = ip_tunnel_ioctl(dev, &p, cmd);
820c5441932SPravin B Shelar 	if (err)
821c5441932SPravin B Shelar 		return err;
822c5441932SPravin B Shelar 
823*a0efab67SXin Long 	if (cmd == SIOCCHGTUNNEL) {
824*a0efab67SXin Long 		struct ip_tunnel *t = netdev_priv(dev);
825*a0efab67SXin Long 
826*a0efab67SXin Long 		t->parms.i_flags = p.i_flags;
827*a0efab67SXin Long 		t->parms.o_flags = p.o_flags;
828*a0efab67SXin Long 
829*a0efab67SXin Long 		if (strcmp(dev->rtnl_link_ops->kind, "erspan"))
830*a0efab67SXin Long 			ipgre_link_update(dev, true);
831*a0efab67SXin Long 	}
832*a0efab67SXin Long 
83395f5c64cSTom Herbert 	p.i_flags = gre_tnl_flags_to_gre_flags(p.i_flags);
83495f5c64cSTom Herbert 	p.o_flags = gre_tnl_flags_to_gre_flags(p.o_flags);
835c5441932SPravin B Shelar 
836c5441932SPravin B Shelar 	if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p)))
837c5441932SPravin B Shelar 		return -EFAULT;
838*a0efab67SXin Long 
8391da177e4SLinus Torvalds 	return 0;
8401da177e4SLinus Torvalds }
8411da177e4SLinus Torvalds 
8421da177e4SLinus Torvalds /* Nice toy. Unfortunately, useless in real life :-)
8431da177e4SLinus Torvalds    It allows to construct virtual multiprotocol broadcast "LAN"
8441da177e4SLinus Torvalds    over the Internet, provided multicast routing is tuned.
8451da177e4SLinus Torvalds 
8461da177e4SLinus Torvalds 
8471da177e4SLinus Torvalds    I have no idea was this bicycle invented before me,
8481da177e4SLinus Torvalds    so that I had to set ARPHRD_IPGRE to a random value.
8491da177e4SLinus Torvalds    I have an impression, that Cisco could make something similar,
8501da177e4SLinus Torvalds    but this feature is apparently missing in IOS<=11.2(8).
8511da177e4SLinus Torvalds 
8521da177e4SLinus Torvalds    I set up 10.66.66/24 and fec0:6666:6666::0/96 as virtual networks
8531da177e4SLinus Torvalds    with broadcast 224.66.66.66. If you have access to mbone, play with me :-)
8541da177e4SLinus Torvalds 
8551da177e4SLinus Torvalds    ping -t 255 224.66.66.66
8561da177e4SLinus Torvalds 
8571da177e4SLinus Torvalds    If nobody answers, mbone does not work.
8581da177e4SLinus Torvalds 
8591da177e4SLinus Torvalds    ip tunnel add Universe mode gre remote 224.66.66.66 local <Your_real_addr> ttl 255
8601da177e4SLinus Torvalds    ip addr add 10.66.66.<somewhat>/24 dev Universe
8611da177e4SLinus Torvalds    ifconfig Universe up
8621da177e4SLinus Torvalds    ifconfig Universe add fe80::<Your_real_addr>/10
8631da177e4SLinus Torvalds    ifconfig Universe add fec0:6666:6666::<Your_real_addr>/96
8641da177e4SLinus Torvalds    ftp 10.66.66.66
8651da177e4SLinus Torvalds    ...
8661da177e4SLinus Torvalds    ftp fec0:6666:6666::193.233.7.65
8671da177e4SLinus Torvalds    ...
8681da177e4SLinus Torvalds  */
8693b04dddeSStephen Hemminger static int ipgre_header(struct sk_buff *skb, struct net_device *dev,
8703b04dddeSStephen Hemminger 			unsigned short type,
8711507850bSEric Dumazet 			const void *daddr, const void *saddr, unsigned int len)
8721da177e4SLinus Torvalds {
8732941a486SPatrick McHardy 	struct ip_tunnel *t = netdev_priv(dev);
874c5441932SPravin B Shelar 	struct iphdr *iph;
875c5441932SPravin B Shelar 	struct gre_base_hdr *greh;
876c5441932SPravin B Shelar 
877d58ff351SJohannes Berg 	iph = skb_push(skb, t->hlen + sizeof(*iph));
878c5441932SPravin B Shelar 	greh = (struct gre_base_hdr *)(iph+1);
87995f5c64cSTom Herbert 	greh->flags = gre_tnl_flags_to_gre_flags(t->parms.o_flags);
880c5441932SPravin B Shelar 	greh->protocol = htons(type);
8811da177e4SLinus Torvalds 
8821da177e4SLinus Torvalds 	memcpy(iph, &t->parms.iph, sizeof(struct iphdr));
8831da177e4SLinus Torvalds 
884c5441932SPravin B Shelar 	/* Set the source hardware address. */
8851da177e4SLinus Torvalds 	if (saddr)
8861da177e4SLinus Torvalds 		memcpy(&iph->saddr, saddr, 4);
8876d55cb91STimo Teräs 	if (daddr)
8881da177e4SLinus Torvalds 		memcpy(&iph->daddr, daddr, 4);
8896d55cb91STimo Teräs 	if (iph->daddr)
89077a482bdSTimo Teräs 		return t->hlen + sizeof(*iph);
8911da177e4SLinus Torvalds 
892c5441932SPravin B Shelar 	return -(t->hlen + sizeof(*iph));
8931da177e4SLinus Torvalds }
8941da177e4SLinus Torvalds 
8956a5f44d7STimo Teras static int ipgre_header_parse(const struct sk_buff *skb, unsigned char *haddr)
8966a5f44d7STimo Teras {
897b71d1d42SEric Dumazet 	const struct iphdr *iph = (const struct iphdr *) skb_mac_header(skb);
8986a5f44d7STimo Teras 	memcpy(haddr, &iph->saddr, 4);
8996a5f44d7STimo Teras 	return 4;
9006a5f44d7STimo Teras }
9016a5f44d7STimo Teras 
9023b04dddeSStephen Hemminger static const struct header_ops ipgre_header_ops = {
9033b04dddeSStephen Hemminger 	.create	= ipgre_header,
9046a5f44d7STimo Teras 	.parse	= ipgre_header_parse,
9053b04dddeSStephen Hemminger };
9063b04dddeSStephen Hemminger 
9076a5f44d7STimo Teras #ifdef CONFIG_NET_IPGRE_BROADCAST
9081da177e4SLinus Torvalds static int ipgre_open(struct net_device *dev)
9091da177e4SLinus Torvalds {
9102941a486SPatrick McHardy 	struct ip_tunnel *t = netdev_priv(dev);
9111da177e4SLinus Torvalds 
912f97c1e0cSJoe Perches 	if (ipv4_is_multicast(t->parms.iph.daddr)) {
913cbb1e85fSDavid S. Miller 		struct flowi4 fl4;
914cbb1e85fSDavid S. Miller 		struct rtable *rt;
915cbb1e85fSDavid S. Miller 
916b57708adSNicolas Dichtel 		rt = ip_route_output_gre(t->net, &fl4,
91778fbfd8aSDavid S. Miller 					 t->parms.iph.daddr,
91878fbfd8aSDavid S. Miller 					 t->parms.iph.saddr,
91978fbfd8aSDavid S. Miller 					 t->parms.o_key,
92078fbfd8aSDavid S. Miller 					 RT_TOS(t->parms.iph.tos),
92178fbfd8aSDavid S. Miller 					 t->parms.link);
922b23dd4feSDavid S. Miller 		if (IS_ERR(rt))
9231da177e4SLinus Torvalds 			return -EADDRNOTAVAIL;
924d8d1f30bSChangli Gao 		dev = rt->dst.dev;
9251da177e4SLinus Torvalds 		ip_rt_put(rt);
92651456b29SIan Morris 		if (!__in_dev_get_rtnl(dev))
9271da177e4SLinus Torvalds 			return -EADDRNOTAVAIL;
9281da177e4SLinus Torvalds 		t->mlink = dev->ifindex;
929e5ed6399SHerbert Xu 		ip_mc_inc_group(__in_dev_get_rtnl(dev), t->parms.iph.daddr);
9301da177e4SLinus Torvalds 	}
9311da177e4SLinus Torvalds 	return 0;
9321da177e4SLinus Torvalds }
9331da177e4SLinus Torvalds 
9341da177e4SLinus Torvalds static int ipgre_close(struct net_device *dev)
9351da177e4SLinus Torvalds {
9362941a486SPatrick McHardy 	struct ip_tunnel *t = netdev_priv(dev);
937b8c26a33SStephen Hemminger 
938f97c1e0cSJoe Perches 	if (ipv4_is_multicast(t->parms.iph.daddr) && t->mlink) {
9397fee0ca2SDenis V. Lunev 		struct in_device *in_dev;
940b57708adSNicolas Dichtel 		in_dev = inetdev_by_index(t->net, t->mlink);
9418723e1b4SEric Dumazet 		if (in_dev)
9421da177e4SLinus Torvalds 			ip_mc_dec_group(in_dev, t->parms.iph.daddr);
9431da177e4SLinus Torvalds 	}
9441da177e4SLinus Torvalds 	return 0;
9451da177e4SLinus Torvalds }
9461da177e4SLinus Torvalds #endif
9471da177e4SLinus Torvalds 
948b8c26a33SStephen Hemminger static const struct net_device_ops ipgre_netdev_ops = {
949b8c26a33SStephen Hemminger 	.ndo_init		= ipgre_tunnel_init,
950c5441932SPravin B Shelar 	.ndo_uninit		= ip_tunnel_uninit,
951b8c26a33SStephen Hemminger #ifdef CONFIG_NET_IPGRE_BROADCAST
952b8c26a33SStephen Hemminger 	.ndo_open		= ipgre_open,
953b8c26a33SStephen Hemminger 	.ndo_stop		= ipgre_close,
954b8c26a33SStephen Hemminger #endif
955c5441932SPravin B Shelar 	.ndo_start_xmit		= ipgre_xmit,
956b8c26a33SStephen Hemminger 	.ndo_do_ioctl		= ipgre_tunnel_ioctl,
957c5441932SPravin B Shelar 	.ndo_change_mtu		= ip_tunnel_change_mtu,
958c5441932SPravin B Shelar 	.ndo_get_stats64	= ip_tunnel_get_stats64,
9591e99584bSNicolas Dichtel 	.ndo_get_iflink		= ip_tunnel_get_iflink,
960b8c26a33SStephen Hemminger };
961b8c26a33SStephen Hemminger 
9626b78f16eSEric Dumazet #define GRE_FEATURES (NETIF_F_SG |		\
9636b78f16eSEric Dumazet 		      NETIF_F_FRAGLIST |	\
9646b78f16eSEric Dumazet 		      NETIF_F_HIGHDMA |		\
9656b78f16eSEric Dumazet 		      NETIF_F_HW_CSUM)
9666b78f16eSEric Dumazet 
9671da177e4SLinus Torvalds static void ipgre_tunnel_setup(struct net_device *dev)
9681da177e4SLinus Torvalds {
969b8c26a33SStephen Hemminger 	dev->netdev_ops		= &ipgre_netdev_ops;
9705a455275SNicolas Dichtel 	dev->type		= ARPHRD_IPGRE;
971c5441932SPravin B Shelar 	ip_tunnel_setup(dev, ipgre_net_id);
972c5441932SPravin B Shelar }
9731da177e4SLinus Torvalds 
974c5441932SPravin B Shelar static void __gre_tunnel_init(struct net_device *dev)
975c5441932SPravin B Shelar {
976c5441932SPravin B Shelar 	struct ip_tunnel *tunnel;
9774565e991STom Herbert 	int t_hlen;
978c5441932SPravin B Shelar 
979c5441932SPravin B Shelar 	tunnel = netdev_priv(dev);
98095f5c64cSTom Herbert 	tunnel->tun_hlen = gre_calc_hlen(tunnel->parms.o_flags);
981c5441932SPravin B Shelar 	tunnel->parms.iph.protocol = IPPROTO_GRE;
982c5441932SPravin B Shelar 
9834565e991STom Herbert 	tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen;
9844565e991STom Herbert 
9854565e991STom Herbert 	t_hlen = tunnel->hlen + sizeof(struct iphdr);
9864565e991STom Herbert 
9874565e991STom Herbert 	dev->needed_headroom	= LL_MAX_HEADER + t_hlen + 4;
9884565e991STom Herbert 	dev->mtu		= ETH_DATA_LEN - t_hlen - 4;
9896b78f16eSEric Dumazet 
990b57708adSNicolas Dichtel 	dev->features		|= GRE_FEATURES;
9916b78f16eSEric Dumazet 	dev->hw_features	|= GRE_FEATURES;
992c5441932SPravin B Shelar 
993c5441932SPravin B Shelar 	if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) {
994a0ca153fSAlexander Duyck 		/* TCP offload with GRE SEQ is not supported, nor
995a0ca153fSAlexander Duyck 		 * can we support 2 levels of outer headers requiring
996a0ca153fSAlexander Duyck 		 * an update.
997a0ca153fSAlexander Duyck 		 */
998a0ca153fSAlexander Duyck 		if (!(tunnel->parms.o_flags & TUNNEL_CSUM) ||
999a0ca153fSAlexander Duyck 		    (tunnel->encap.type == TUNNEL_ENCAP_NONE)) {
1000c5441932SPravin B Shelar 			dev->features    |= NETIF_F_GSO_SOFTWARE;
1001c5441932SPravin B Shelar 			dev->hw_features |= NETIF_F_GSO_SOFTWARE;
1002a0ca153fSAlexander Duyck 		}
1003a0ca153fSAlexander Duyck 
1004c5441932SPravin B Shelar 		/* Can use a lockless transmit, unless we generate
1005c5441932SPravin B Shelar 		 * output sequences
1006c5441932SPravin B Shelar 		 */
1007c5441932SPravin B Shelar 		dev->features |= NETIF_F_LLTX;
1008c5441932SPravin B Shelar 	}
10091da177e4SLinus Torvalds }
10101da177e4SLinus Torvalds 
10111da177e4SLinus Torvalds static int ipgre_tunnel_init(struct net_device *dev)
10121da177e4SLinus Torvalds {
1013c5441932SPravin B Shelar 	struct ip_tunnel *tunnel = netdev_priv(dev);
1014c5441932SPravin B Shelar 	struct iphdr *iph = &tunnel->parms.iph;
10151da177e4SLinus Torvalds 
1016c5441932SPravin B Shelar 	__gre_tunnel_init(dev);
10171da177e4SLinus Torvalds 
1018c5441932SPravin B Shelar 	memcpy(dev->dev_addr, &iph->saddr, 4);
1019c5441932SPravin B Shelar 	memcpy(dev->broadcast, &iph->daddr, 4);
10201da177e4SLinus Torvalds 
1021c5441932SPravin B Shelar 	dev->flags		= IFF_NOARP;
102202875878SEric Dumazet 	netif_keep_dst(dev);
1023c5441932SPravin B Shelar 	dev->addr_len		= 4;
10241da177e4SLinus Torvalds 
1025a64b04d8SJiri Benc 	if (iph->daddr && !tunnel->collect_md) {
10261da177e4SLinus Torvalds #ifdef CONFIG_NET_IPGRE_BROADCAST
1027f97c1e0cSJoe Perches 		if (ipv4_is_multicast(iph->daddr)) {
10281da177e4SLinus Torvalds 			if (!iph->saddr)
10291da177e4SLinus Torvalds 				return -EINVAL;
10301da177e4SLinus Torvalds 			dev->flags = IFF_BROADCAST;
10313b04dddeSStephen Hemminger 			dev->header_ops = &ipgre_header_ops;
10321da177e4SLinus Torvalds 		}
10331da177e4SLinus Torvalds #endif
1034a64b04d8SJiri Benc 	} else if (!tunnel->collect_md) {
10356a5f44d7STimo Teras 		dev->header_ops = &ipgre_header_ops;
1036a64b04d8SJiri Benc 	}
10371da177e4SLinus Torvalds 
1038c5441932SPravin B Shelar 	return ip_tunnel_init(dev);
103960769a5dSEric Dumazet }
104060769a5dSEric Dumazet 
10419f57c67cSPravin B Shelar static const struct gre_protocol ipgre_protocol = {
10429f57c67cSPravin B Shelar 	.handler     = gre_rcv,
10439f57c67cSPravin B Shelar 	.err_handler = gre_err,
10441da177e4SLinus Torvalds };
10451da177e4SLinus Torvalds 
10462c8c1e72SAlexey Dobriyan static int __net_init ipgre_init_net(struct net *net)
104759a4c759SPavel Emelyanov {
1048c5441932SPravin B Shelar 	return ip_tunnel_init_net(net, ipgre_net_id, &ipgre_link_ops, NULL);
104959a4c759SPavel Emelyanov }
105059a4c759SPavel Emelyanov 
105164bc1781SEric Dumazet static void __net_exit ipgre_exit_batch_net(struct list_head *list_net)
105259a4c759SPavel Emelyanov {
105364bc1781SEric Dumazet 	ip_tunnel_delete_nets(list_net, ipgre_net_id, &ipgre_link_ops);
105459a4c759SPavel Emelyanov }
105559a4c759SPavel Emelyanov 
105659a4c759SPavel Emelyanov static struct pernet_operations ipgre_net_ops = {
105759a4c759SPavel Emelyanov 	.init = ipgre_init_net,
105864bc1781SEric Dumazet 	.exit_batch = ipgre_exit_batch_net,
1059cfb8fbf2SEric W. Biederman 	.id   = &ipgre_net_id,
1060c5441932SPravin B Shelar 	.size = sizeof(struct ip_tunnel_net),
106159a4c759SPavel Emelyanov };
10621da177e4SLinus Torvalds 
1063a8b8a889SMatthias Schiffer static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[],
1064a8b8a889SMatthias Schiffer 				 struct netlink_ext_ack *extack)
1065c19e654dSHerbert Xu {
1066c19e654dSHerbert Xu 	__be16 flags;
1067c19e654dSHerbert Xu 
1068c19e654dSHerbert Xu 	if (!data)
1069c19e654dSHerbert Xu 		return 0;
1070c19e654dSHerbert Xu 
1071c19e654dSHerbert Xu 	flags = 0;
1072c19e654dSHerbert Xu 	if (data[IFLA_GRE_IFLAGS])
1073c19e654dSHerbert Xu 		flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]);
1074c19e654dSHerbert Xu 	if (data[IFLA_GRE_OFLAGS])
1075c19e654dSHerbert Xu 		flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]);
1076c19e654dSHerbert Xu 	if (flags & (GRE_VERSION|GRE_ROUTING))
1077c19e654dSHerbert Xu 		return -EINVAL;
1078c19e654dSHerbert Xu 
1079946b636fSJiri Benc 	if (data[IFLA_GRE_COLLECT_METADATA] &&
1080946b636fSJiri Benc 	    data[IFLA_GRE_ENCAP_TYPE] &&
1081946b636fSJiri Benc 	    nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]) != TUNNEL_ENCAP_NONE)
1082946b636fSJiri Benc 		return -EINVAL;
1083946b636fSJiri Benc 
1084c19e654dSHerbert Xu 	return 0;
1085c19e654dSHerbert Xu }
1086c19e654dSHerbert Xu 
1087a8b8a889SMatthias Schiffer static int ipgre_tap_validate(struct nlattr *tb[], struct nlattr *data[],
1088a8b8a889SMatthias Schiffer 			      struct netlink_ext_ack *extack)
1089e1a80002SHerbert Xu {
1090e1a80002SHerbert Xu 	__be32 daddr;
1091e1a80002SHerbert Xu 
1092e1a80002SHerbert Xu 	if (tb[IFLA_ADDRESS]) {
1093e1a80002SHerbert Xu 		if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
1094e1a80002SHerbert Xu 			return -EINVAL;
1095e1a80002SHerbert Xu 		if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
1096e1a80002SHerbert Xu 			return -EADDRNOTAVAIL;
1097e1a80002SHerbert Xu 	}
1098e1a80002SHerbert Xu 
1099e1a80002SHerbert Xu 	if (!data)
1100e1a80002SHerbert Xu 		goto out;
1101e1a80002SHerbert Xu 
1102e1a80002SHerbert Xu 	if (data[IFLA_GRE_REMOTE]) {
1103e1a80002SHerbert Xu 		memcpy(&daddr, nla_data(data[IFLA_GRE_REMOTE]), 4);
1104e1a80002SHerbert Xu 		if (!daddr)
1105e1a80002SHerbert Xu 			return -EINVAL;
1106e1a80002SHerbert Xu 	}
1107e1a80002SHerbert Xu 
1108e1a80002SHerbert Xu out:
1109a8b8a889SMatthias Schiffer 	return ipgre_tunnel_validate(tb, data, extack);
1110e1a80002SHerbert Xu }
1111e1a80002SHerbert Xu 
111284e54fe0SWilliam Tu static int erspan_validate(struct nlattr *tb[], struct nlattr *data[],
111384e54fe0SWilliam Tu 			   struct netlink_ext_ack *extack)
111484e54fe0SWilliam Tu {
111584e54fe0SWilliam Tu 	__be16 flags = 0;
111684e54fe0SWilliam Tu 	int ret;
111784e54fe0SWilliam Tu 
111884e54fe0SWilliam Tu 	if (!data)
111984e54fe0SWilliam Tu 		return 0;
112084e54fe0SWilliam Tu 
112184e54fe0SWilliam Tu 	ret = ipgre_tap_validate(tb, data, extack);
112284e54fe0SWilliam Tu 	if (ret)
112384e54fe0SWilliam Tu 		return ret;
112484e54fe0SWilliam Tu 
112584e54fe0SWilliam Tu 	/* ERSPAN should only have GRE sequence and key flag */
11261a66a836SWilliam Tu 	if (data[IFLA_GRE_OFLAGS])
112784e54fe0SWilliam Tu 		flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]);
11281a66a836SWilliam Tu 	if (data[IFLA_GRE_IFLAGS])
112984e54fe0SWilliam Tu 		flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]);
11301a66a836SWilliam Tu 	if (!data[IFLA_GRE_COLLECT_METADATA] &&
11311a66a836SWilliam Tu 	    flags != (GRE_SEQ | GRE_KEY))
113284e54fe0SWilliam Tu 		return -EINVAL;
113384e54fe0SWilliam Tu 
113484e54fe0SWilliam Tu 	/* ERSPAN Session ID only has 10-bit. Since we reuse
113584e54fe0SWilliam Tu 	 * 32-bit key field as ID, check it's range.
113684e54fe0SWilliam Tu 	 */
113784e54fe0SWilliam Tu 	if (data[IFLA_GRE_IKEY] &&
113884e54fe0SWilliam Tu 	    (ntohl(nla_get_be32(data[IFLA_GRE_IKEY])) & ~ID_MASK))
113984e54fe0SWilliam Tu 		return -EINVAL;
114084e54fe0SWilliam Tu 
114184e54fe0SWilliam Tu 	if (data[IFLA_GRE_OKEY] &&
114284e54fe0SWilliam Tu 	    (ntohl(nla_get_be32(data[IFLA_GRE_OKEY])) & ~ID_MASK))
114384e54fe0SWilliam Tu 		return -EINVAL;
114484e54fe0SWilliam Tu 
114584e54fe0SWilliam Tu 	return 0;
114684e54fe0SWilliam Tu }
114784e54fe0SWilliam Tu 
114822a59be8SPhilip Prindeville static int ipgre_netlink_parms(struct net_device *dev,
11492e15ea39SPravin B Shelar 				struct nlattr *data[],
11502e15ea39SPravin B Shelar 				struct nlattr *tb[],
11519830ad4cSCraig Gallek 				struct ip_tunnel_parm *parms,
11529830ad4cSCraig Gallek 				__u32 *fwmark)
1153c19e654dSHerbert Xu {
115422a59be8SPhilip Prindeville 	struct ip_tunnel *t = netdev_priv(dev);
115522a59be8SPhilip Prindeville 
11567bb82d92SHerbert Xu 	memset(parms, 0, sizeof(*parms));
1157c19e654dSHerbert Xu 
1158c19e654dSHerbert Xu 	parms->iph.protocol = IPPROTO_GRE;
1159c19e654dSHerbert Xu 
1160c19e654dSHerbert Xu 	if (!data)
116122a59be8SPhilip Prindeville 		return 0;
1162c19e654dSHerbert Xu 
1163c19e654dSHerbert Xu 	if (data[IFLA_GRE_LINK])
1164c19e654dSHerbert Xu 		parms->link = nla_get_u32(data[IFLA_GRE_LINK]);
1165c19e654dSHerbert Xu 
1166c19e654dSHerbert Xu 	if (data[IFLA_GRE_IFLAGS])
1167c5441932SPravin B Shelar 		parms->i_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_IFLAGS]));
1168c19e654dSHerbert Xu 
1169c19e654dSHerbert Xu 	if (data[IFLA_GRE_OFLAGS])
1170c5441932SPravin B Shelar 		parms->o_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_OFLAGS]));
1171c19e654dSHerbert Xu 
1172c19e654dSHerbert Xu 	if (data[IFLA_GRE_IKEY])
1173c19e654dSHerbert Xu 		parms->i_key = nla_get_be32(data[IFLA_GRE_IKEY]);
1174c19e654dSHerbert Xu 
1175c19e654dSHerbert Xu 	if (data[IFLA_GRE_OKEY])
1176c19e654dSHerbert Xu 		parms->o_key = nla_get_be32(data[IFLA_GRE_OKEY]);
1177c19e654dSHerbert Xu 
1178c19e654dSHerbert Xu 	if (data[IFLA_GRE_LOCAL])
117967b61f6cSJiri Benc 		parms->iph.saddr = nla_get_in_addr(data[IFLA_GRE_LOCAL]);
1180c19e654dSHerbert Xu 
1181c19e654dSHerbert Xu 	if (data[IFLA_GRE_REMOTE])
118267b61f6cSJiri Benc 		parms->iph.daddr = nla_get_in_addr(data[IFLA_GRE_REMOTE]);
1183c19e654dSHerbert Xu 
1184c19e654dSHerbert Xu 	if (data[IFLA_GRE_TTL])
1185c19e654dSHerbert Xu 		parms->iph.ttl = nla_get_u8(data[IFLA_GRE_TTL]);
1186c19e654dSHerbert Xu 
1187c19e654dSHerbert Xu 	if (data[IFLA_GRE_TOS])
1188c19e654dSHerbert Xu 		parms->iph.tos = nla_get_u8(data[IFLA_GRE_TOS]);
1189c19e654dSHerbert Xu 
119022a59be8SPhilip Prindeville 	if (!data[IFLA_GRE_PMTUDISC] || nla_get_u8(data[IFLA_GRE_PMTUDISC])) {
119122a59be8SPhilip Prindeville 		if (t->ignore_df)
119222a59be8SPhilip Prindeville 			return -EINVAL;
1193c19e654dSHerbert Xu 		parms->iph.frag_off = htons(IP_DF);
119422a59be8SPhilip Prindeville 	}
11952e15ea39SPravin B Shelar 
11962e15ea39SPravin B Shelar 	if (data[IFLA_GRE_COLLECT_METADATA]) {
11972e15ea39SPravin B Shelar 		t->collect_md = true;
1198e271c7b4SJiri Benc 		if (dev->type == ARPHRD_IPGRE)
1199e271c7b4SJiri Benc 			dev->type = ARPHRD_NONE;
12002e15ea39SPravin B Shelar 	}
120122a59be8SPhilip Prindeville 
120222a59be8SPhilip Prindeville 	if (data[IFLA_GRE_IGNORE_DF]) {
120322a59be8SPhilip Prindeville 		if (nla_get_u8(data[IFLA_GRE_IGNORE_DF])
120422a59be8SPhilip Prindeville 		  && (parms->iph.frag_off & htons(IP_DF)))
120522a59be8SPhilip Prindeville 			return -EINVAL;
120622a59be8SPhilip Prindeville 		t->ignore_df = !!nla_get_u8(data[IFLA_GRE_IGNORE_DF]);
120722a59be8SPhilip Prindeville 	}
120822a59be8SPhilip Prindeville 
12099830ad4cSCraig Gallek 	if (data[IFLA_GRE_FWMARK])
12109830ad4cSCraig Gallek 		*fwmark = nla_get_u32(data[IFLA_GRE_FWMARK]);
12119830ad4cSCraig Gallek 
121284e54fe0SWilliam Tu 	if (data[IFLA_GRE_ERSPAN_INDEX]) {
121384e54fe0SWilliam Tu 		t->index = nla_get_u32(data[IFLA_GRE_ERSPAN_INDEX]);
121484e54fe0SWilliam Tu 
121584e54fe0SWilliam Tu 		if (t->index & ~INDEX_MASK)
121684e54fe0SWilliam Tu 			return -EINVAL;
121784e54fe0SWilliam Tu 	}
121884e54fe0SWilliam Tu 
121922a59be8SPhilip Prindeville 	return 0;
1220c19e654dSHerbert Xu }
1221c19e654dSHerbert Xu 
12224565e991STom Herbert /* This function returns true when ENCAP attributes are present in the nl msg */
12234565e991STom Herbert static bool ipgre_netlink_encap_parms(struct nlattr *data[],
12244565e991STom Herbert 				      struct ip_tunnel_encap *ipencap)
12254565e991STom Herbert {
12264565e991STom Herbert 	bool ret = false;
12274565e991STom Herbert 
12284565e991STom Herbert 	memset(ipencap, 0, sizeof(*ipencap));
12294565e991STom Herbert 
12304565e991STom Herbert 	if (!data)
12314565e991STom Herbert 		return ret;
12324565e991STom Herbert 
12334565e991STom Herbert 	if (data[IFLA_GRE_ENCAP_TYPE]) {
12344565e991STom Herbert 		ret = true;
12354565e991STom Herbert 		ipencap->type = nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]);
12364565e991STom Herbert 	}
12374565e991STom Herbert 
12384565e991STom Herbert 	if (data[IFLA_GRE_ENCAP_FLAGS]) {
12394565e991STom Herbert 		ret = true;
12404565e991STom Herbert 		ipencap->flags = nla_get_u16(data[IFLA_GRE_ENCAP_FLAGS]);
12414565e991STom Herbert 	}
12424565e991STom Herbert 
12434565e991STom Herbert 	if (data[IFLA_GRE_ENCAP_SPORT]) {
12444565e991STom Herbert 		ret = true;
12453e97fa70SSabrina Dubroca 		ipencap->sport = nla_get_be16(data[IFLA_GRE_ENCAP_SPORT]);
12464565e991STom Herbert 	}
12474565e991STom Herbert 
12484565e991STom Herbert 	if (data[IFLA_GRE_ENCAP_DPORT]) {
12494565e991STom Herbert 		ret = true;
12503e97fa70SSabrina Dubroca 		ipencap->dport = nla_get_be16(data[IFLA_GRE_ENCAP_DPORT]);
12514565e991STom Herbert 	}
12524565e991STom Herbert 
12534565e991STom Herbert 	return ret;
12544565e991STom Herbert }
12554565e991STom Herbert 
1256c5441932SPravin B Shelar static int gre_tap_init(struct net_device *dev)
1257e1a80002SHerbert Xu {
1258c5441932SPravin B Shelar 	__gre_tunnel_init(dev);
1259bec94d43Sstephen hemminger 	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
1260d51711c0SXin Long 	netif_keep_dst(dev);
1261e1a80002SHerbert Xu 
1262c5441932SPravin B Shelar 	return ip_tunnel_init(dev);
1263e1a80002SHerbert Xu }
1264e1a80002SHerbert Xu 
1265c5441932SPravin B Shelar static const struct net_device_ops gre_tap_netdev_ops = {
1266c5441932SPravin B Shelar 	.ndo_init		= gre_tap_init,
1267c5441932SPravin B Shelar 	.ndo_uninit		= ip_tunnel_uninit,
1268c5441932SPravin B Shelar 	.ndo_start_xmit		= gre_tap_xmit,
1269b8c26a33SStephen Hemminger 	.ndo_set_mac_address 	= eth_mac_addr,
1270b8c26a33SStephen Hemminger 	.ndo_validate_addr	= eth_validate_addr,
1271c5441932SPravin B Shelar 	.ndo_change_mtu		= ip_tunnel_change_mtu,
1272c5441932SPravin B Shelar 	.ndo_get_stats64	= ip_tunnel_get_stats64,
12731e99584bSNicolas Dichtel 	.ndo_get_iflink		= ip_tunnel_get_iflink,
1274fc4099f1SPravin B Shelar 	.ndo_fill_metadata_dst	= gre_fill_metadata_dst,
1275b8c26a33SStephen Hemminger };
1276b8c26a33SStephen Hemminger 
127784e54fe0SWilliam Tu static int erspan_tunnel_init(struct net_device *dev)
127884e54fe0SWilliam Tu {
127984e54fe0SWilliam Tu 	struct ip_tunnel *tunnel = netdev_priv(dev);
128084e54fe0SWilliam Tu 	int t_hlen;
128184e54fe0SWilliam Tu 
128284e54fe0SWilliam Tu 	tunnel->tun_hlen = 8;
128384e54fe0SWilliam Tu 	tunnel->parms.iph.protocol = IPPROTO_GRE;
1284c122fda2SXin Long 	tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen +
1285c122fda2SXin Long 		       sizeof(struct erspanhdr);
1286c122fda2SXin Long 	t_hlen = tunnel->hlen + sizeof(struct iphdr);
128784e54fe0SWilliam Tu 
128884e54fe0SWilliam Tu 	dev->needed_headroom = LL_MAX_HEADER + t_hlen + 4;
128984e54fe0SWilliam Tu 	dev->mtu = ETH_DATA_LEN - t_hlen - 4;
129084e54fe0SWilliam Tu 	dev->features		|= GRE_FEATURES;
129184e54fe0SWilliam Tu 	dev->hw_features	|= GRE_FEATURES;
129284e54fe0SWilliam Tu 	dev->priv_flags		|= IFF_LIVE_ADDR_CHANGE;
1293c84bed44SXin Long 	netif_keep_dst(dev);
129484e54fe0SWilliam Tu 
129584e54fe0SWilliam Tu 	return ip_tunnel_init(dev);
129684e54fe0SWilliam Tu }
129784e54fe0SWilliam Tu 
129884e54fe0SWilliam Tu static const struct net_device_ops erspan_netdev_ops = {
129984e54fe0SWilliam Tu 	.ndo_init		= erspan_tunnel_init,
130084e54fe0SWilliam Tu 	.ndo_uninit		= ip_tunnel_uninit,
130184e54fe0SWilliam Tu 	.ndo_start_xmit		= erspan_xmit,
130284e54fe0SWilliam Tu 	.ndo_set_mac_address	= eth_mac_addr,
130384e54fe0SWilliam Tu 	.ndo_validate_addr	= eth_validate_addr,
130484e54fe0SWilliam Tu 	.ndo_change_mtu		= ip_tunnel_change_mtu,
130584e54fe0SWilliam Tu 	.ndo_get_stats64	= ip_tunnel_get_stats64,
130684e54fe0SWilliam Tu 	.ndo_get_iflink		= ip_tunnel_get_iflink,
130784e54fe0SWilliam Tu 	.ndo_fill_metadata_dst	= gre_fill_metadata_dst,
130884e54fe0SWilliam Tu };
130984e54fe0SWilliam Tu 
1310e1a80002SHerbert Xu static void ipgre_tap_setup(struct net_device *dev)
1311e1a80002SHerbert Xu {
1312e1a80002SHerbert Xu 	ether_setup(dev);
1313c5441932SPravin B Shelar 	dev->netdev_ops	= &gre_tap_netdev_ops;
1314d13b161cSJiri Benc 	dev->priv_flags &= ~IFF_TX_SKB_SHARING;
1315f8c1b7ceSstephen hemminger 	dev->priv_flags	|= IFF_LIVE_ADDR_CHANGE;
1316c5441932SPravin B Shelar 	ip_tunnel_setup(dev, gre_tap_net_id);
1317e1a80002SHerbert Xu }
1318e1a80002SHerbert Xu 
1319c5441932SPravin B Shelar static int ipgre_newlink(struct net *src_net, struct net_device *dev,
13207a3f4a18SMatthias Schiffer 			 struct nlattr *tb[], struct nlattr *data[],
13217a3f4a18SMatthias Schiffer 			 struct netlink_ext_ack *extack)
1322c19e654dSHerbert Xu {
1323c5441932SPravin B Shelar 	struct ip_tunnel_parm p;
13244565e991STom Herbert 	struct ip_tunnel_encap ipencap;
13259830ad4cSCraig Gallek 	__u32 fwmark = 0;
132622a59be8SPhilip Prindeville 	int err;
13274565e991STom Herbert 
13284565e991STom Herbert 	if (ipgre_netlink_encap_parms(data, &ipencap)) {
13294565e991STom Herbert 		struct ip_tunnel *t = netdev_priv(dev);
133022a59be8SPhilip Prindeville 		err = ip_tunnel_encap_setup(t, &ipencap);
13314565e991STom Herbert 
13324565e991STom Herbert 		if (err < 0)
13334565e991STom Herbert 			return err;
13344565e991STom Herbert 	}
1335c19e654dSHerbert Xu 
13369830ad4cSCraig Gallek 	err = ipgre_netlink_parms(dev, data, tb, &p, &fwmark);
133722a59be8SPhilip Prindeville 	if (err < 0)
133822a59be8SPhilip Prindeville 		return err;
13399830ad4cSCraig Gallek 	return ip_tunnel_newlink(dev, tb, &p, fwmark);
1340c19e654dSHerbert Xu }
1341c19e654dSHerbert Xu 
1342c19e654dSHerbert Xu static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[],
1343ad744b22SMatthias Schiffer 			    struct nlattr *data[],
1344ad744b22SMatthias Schiffer 			    struct netlink_ext_ack *extack)
1345c19e654dSHerbert Xu {
13469830ad4cSCraig Gallek 	struct ip_tunnel *t = netdev_priv(dev);
13474565e991STom Herbert 	struct ip_tunnel_encap ipencap;
13489830ad4cSCraig Gallek 	__u32 fwmark = t->fwmark;
1349dd9d598cSXin Long 	struct ip_tunnel_parm p;
135022a59be8SPhilip Prindeville 	int err;
13514565e991STom Herbert 
13524565e991STom Herbert 	if (ipgre_netlink_encap_parms(data, &ipencap)) {
135322a59be8SPhilip Prindeville 		err = ip_tunnel_encap_setup(t, &ipencap);
13544565e991STom Herbert 
13554565e991STom Herbert 		if (err < 0)
13564565e991STom Herbert 			return err;
13574565e991STom Herbert 	}
1358c19e654dSHerbert Xu 
13599830ad4cSCraig Gallek 	err = ipgre_netlink_parms(dev, data, tb, &p, &fwmark);
136022a59be8SPhilip Prindeville 	if (err < 0)
136122a59be8SPhilip Prindeville 		return err;
1362dd9d598cSXin Long 
1363dd9d598cSXin Long 	err = ip_tunnel_changelink(dev, tb, &p, fwmark);
1364dd9d598cSXin Long 	if (err < 0)
1365dd9d598cSXin Long 		return err;
1366dd9d598cSXin Long 
1367dd9d598cSXin Long 	t->parms.i_flags = p.i_flags;
1368dd9d598cSXin Long 	t->parms.o_flags = p.o_flags;
1369dd9d598cSXin Long 
1370dd9d598cSXin Long 	if (strcmp(dev->rtnl_link_ops->kind, "erspan"))
1371dd9d598cSXin Long 		ipgre_link_update(dev, !tb[IFLA_MTU]);
1372dd9d598cSXin Long 
1373dd9d598cSXin Long 	return 0;
1374c19e654dSHerbert Xu }
1375c19e654dSHerbert Xu 
1376c19e654dSHerbert Xu static size_t ipgre_get_size(const struct net_device *dev)
1377c19e654dSHerbert Xu {
1378c19e654dSHerbert Xu 	return
1379c19e654dSHerbert Xu 		/* IFLA_GRE_LINK */
1380c19e654dSHerbert Xu 		nla_total_size(4) +
1381c19e654dSHerbert Xu 		/* IFLA_GRE_IFLAGS */
1382c19e654dSHerbert Xu 		nla_total_size(2) +
1383c19e654dSHerbert Xu 		/* IFLA_GRE_OFLAGS */
1384c19e654dSHerbert Xu 		nla_total_size(2) +
1385c19e654dSHerbert Xu 		/* IFLA_GRE_IKEY */
1386c19e654dSHerbert Xu 		nla_total_size(4) +
1387c19e654dSHerbert Xu 		/* IFLA_GRE_OKEY */
1388c19e654dSHerbert Xu 		nla_total_size(4) +
1389c19e654dSHerbert Xu 		/* IFLA_GRE_LOCAL */
1390c19e654dSHerbert Xu 		nla_total_size(4) +
1391c19e654dSHerbert Xu 		/* IFLA_GRE_REMOTE */
1392c19e654dSHerbert Xu 		nla_total_size(4) +
1393c19e654dSHerbert Xu 		/* IFLA_GRE_TTL */
1394c19e654dSHerbert Xu 		nla_total_size(1) +
1395c19e654dSHerbert Xu 		/* IFLA_GRE_TOS */
1396c19e654dSHerbert Xu 		nla_total_size(1) +
1397c19e654dSHerbert Xu 		/* IFLA_GRE_PMTUDISC */
1398c19e654dSHerbert Xu 		nla_total_size(1) +
13994565e991STom Herbert 		/* IFLA_GRE_ENCAP_TYPE */
14004565e991STom Herbert 		nla_total_size(2) +
14014565e991STom Herbert 		/* IFLA_GRE_ENCAP_FLAGS */
14024565e991STom Herbert 		nla_total_size(2) +
14034565e991STom Herbert 		/* IFLA_GRE_ENCAP_SPORT */
14044565e991STom Herbert 		nla_total_size(2) +
14054565e991STom Herbert 		/* IFLA_GRE_ENCAP_DPORT */
14064565e991STom Herbert 		nla_total_size(2) +
14072e15ea39SPravin B Shelar 		/* IFLA_GRE_COLLECT_METADATA */
14082e15ea39SPravin B Shelar 		nla_total_size(0) +
140922a59be8SPhilip Prindeville 		/* IFLA_GRE_IGNORE_DF */
141022a59be8SPhilip Prindeville 		nla_total_size(1) +
14119830ad4cSCraig Gallek 		/* IFLA_GRE_FWMARK */
14129830ad4cSCraig Gallek 		nla_total_size(4) +
141384e54fe0SWilliam Tu 		/* IFLA_GRE_ERSPAN_INDEX */
141484e54fe0SWilliam Tu 		nla_total_size(4) +
1415c19e654dSHerbert Xu 		0;
1416c19e654dSHerbert Xu }
1417c19e654dSHerbert Xu 
1418c19e654dSHerbert Xu static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev)
1419c19e654dSHerbert Xu {
1420c19e654dSHerbert Xu 	struct ip_tunnel *t = netdev_priv(dev);
1421c19e654dSHerbert Xu 	struct ip_tunnel_parm *p = &t->parms;
1422c19e654dSHerbert Xu 
1423f3756b79SDavid S. Miller 	if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) ||
142495f5c64cSTom Herbert 	    nla_put_be16(skb, IFLA_GRE_IFLAGS,
142595f5c64cSTom Herbert 			 gre_tnl_flags_to_gre_flags(p->i_flags)) ||
142695f5c64cSTom Herbert 	    nla_put_be16(skb, IFLA_GRE_OFLAGS,
142795f5c64cSTom Herbert 			 gre_tnl_flags_to_gre_flags(p->o_flags)) ||
1428f3756b79SDavid S. Miller 	    nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) ||
1429f3756b79SDavid S. Miller 	    nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) ||
1430930345eaSJiri Benc 	    nla_put_in_addr(skb, IFLA_GRE_LOCAL, p->iph.saddr) ||
1431930345eaSJiri Benc 	    nla_put_in_addr(skb, IFLA_GRE_REMOTE, p->iph.daddr) ||
1432f3756b79SDavid S. Miller 	    nla_put_u8(skb, IFLA_GRE_TTL, p->iph.ttl) ||
1433f3756b79SDavid S. Miller 	    nla_put_u8(skb, IFLA_GRE_TOS, p->iph.tos) ||
1434f3756b79SDavid S. Miller 	    nla_put_u8(skb, IFLA_GRE_PMTUDISC,
14359830ad4cSCraig Gallek 		       !!(p->iph.frag_off & htons(IP_DF))) ||
14369830ad4cSCraig Gallek 	    nla_put_u32(skb, IFLA_GRE_FWMARK, t->fwmark))
1437f3756b79SDavid S. Miller 		goto nla_put_failure;
14384565e991STom Herbert 
14394565e991STom Herbert 	if (nla_put_u16(skb, IFLA_GRE_ENCAP_TYPE,
14404565e991STom Herbert 			t->encap.type) ||
14413e97fa70SSabrina Dubroca 	    nla_put_be16(skb, IFLA_GRE_ENCAP_SPORT,
14424565e991STom Herbert 			 t->encap.sport) ||
14433e97fa70SSabrina Dubroca 	    nla_put_be16(skb, IFLA_GRE_ENCAP_DPORT,
14444565e991STom Herbert 			 t->encap.dport) ||
14454565e991STom Herbert 	    nla_put_u16(skb, IFLA_GRE_ENCAP_FLAGS,
1446e1b2cb65STom Herbert 			t->encap.flags))
14474565e991STom Herbert 		goto nla_put_failure;
14484565e991STom Herbert 
144922a59be8SPhilip Prindeville 	if (nla_put_u8(skb, IFLA_GRE_IGNORE_DF, t->ignore_df))
145022a59be8SPhilip Prindeville 		goto nla_put_failure;
145122a59be8SPhilip Prindeville 
14522e15ea39SPravin B Shelar 	if (t->collect_md) {
14532e15ea39SPravin B Shelar 		if (nla_put_flag(skb, IFLA_GRE_COLLECT_METADATA))
14542e15ea39SPravin B Shelar 			goto nla_put_failure;
14552e15ea39SPravin B Shelar 	}
14562e15ea39SPravin B Shelar 
145784e54fe0SWilliam Tu 	if (t->index)
145884e54fe0SWilliam Tu 		if (nla_put_u32(skb, IFLA_GRE_ERSPAN_INDEX, t->index))
145984e54fe0SWilliam Tu 			goto nla_put_failure;
146084e54fe0SWilliam Tu 
1461c19e654dSHerbert Xu 	return 0;
1462c19e654dSHerbert Xu 
1463c19e654dSHerbert Xu nla_put_failure:
1464c19e654dSHerbert Xu 	return -EMSGSIZE;
1465c19e654dSHerbert Xu }
1466c19e654dSHerbert Xu 
146784e54fe0SWilliam Tu static void erspan_setup(struct net_device *dev)
146884e54fe0SWilliam Tu {
146984e54fe0SWilliam Tu 	ether_setup(dev);
147084e54fe0SWilliam Tu 	dev->netdev_ops = &erspan_netdev_ops;
147184e54fe0SWilliam Tu 	dev->priv_flags &= ~IFF_TX_SKB_SHARING;
147284e54fe0SWilliam Tu 	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
147384e54fe0SWilliam Tu 	ip_tunnel_setup(dev, erspan_net_id);
147484e54fe0SWilliam Tu }
147584e54fe0SWilliam Tu 
1476c19e654dSHerbert Xu static const struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = {
1477c19e654dSHerbert Xu 	[IFLA_GRE_LINK]		= { .type = NLA_U32 },
1478c19e654dSHerbert Xu 	[IFLA_GRE_IFLAGS]	= { .type = NLA_U16 },
1479c19e654dSHerbert Xu 	[IFLA_GRE_OFLAGS]	= { .type = NLA_U16 },
1480c19e654dSHerbert Xu 	[IFLA_GRE_IKEY]		= { .type = NLA_U32 },
1481c19e654dSHerbert Xu 	[IFLA_GRE_OKEY]		= { .type = NLA_U32 },
14824d74f8baSPatrick McHardy 	[IFLA_GRE_LOCAL]	= { .len = FIELD_SIZEOF(struct iphdr, saddr) },
14834d74f8baSPatrick McHardy 	[IFLA_GRE_REMOTE]	= { .len = FIELD_SIZEOF(struct iphdr, daddr) },
1484c19e654dSHerbert Xu 	[IFLA_GRE_TTL]		= { .type = NLA_U8 },
1485c19e654dSHerbert Xu 	[IFLA_GRE_TOS]		= { .type = NLA_U8 },
1486c19e654dSHerbert Xu 	[IFLA_GRE_PMTUDISC]	= { .type = NLA_U8 },
14874565e991STom Herbert 	[IFLA_GRE_ENCAP_TYPE]	= { .type = NLA_U16 },
14884565e991STom Herbert 	[IFLA_GRE_ENCAP_FLAGS]	= { .type = NLA_U16 },
14894565e991STom Herbert 	[IFLA_GRE_ENCAP_SPORT]	= { .type = NLA_U16 },
14904565e991STom Herbert 	[IFLA_GRE_ENCAP_DPORT]	= { .type = NLA_U16 },
14912e15ea39SPravin B Shelar 	[IFLA_GRE_COLLECT_METADATA]	= { .type = NLA_FLAG },
149222a59be8SPhilip Prindeville 	[IFLA_GRE_IGNORE_DF]	= { .type = NLA_U8 },
14939830ad4cSCraig Gallek 	[IFLA_GRE_FWMARK]	= { .type = NLA_U32 },
149484e54fe0SWilliam Tu 	[IFLA_GRE_ERSPAN_INDEX]	= { .type = NLA_U32 },
1495c19e654dSHerbert Xu };
1496c19e654dSHerbert Xu 
1497c19e654dSHerbert Xu static struct rtnl_link_ops ipgre_link_ops __read_mostly = {
1498c19e654dSHerbert Xu 	.kind		= "gre",
1499c19e654dSHerbert Xu 	.maxtype	= IFLA_GRE_MAX,
1500c19e654dSHerbert Xu 	.policy		= ipgre_policy,
1501c19e654dSHerbert Xu 	.priv_size	= sizeof(struct ip_tunnel),
1502c19e654dSHerbert Xu 	.setup		= ipgre_tunnel_setup,
1503c19e654dSHerbert Xu 	.validate	= ipgre_tunnel_validate,
1504c19e654dSHerbert Xu 	.newlink	= ipgre_newlink,
1505c19e654dSHerbert Xu 	.changelink	= ipgre_changelink,
1506c5441932SPravin B Shelar 	.dellink	= ip_tunnel_dellink,
1507c19e654dSHerbert Xu 	.get_size	= ipgre_get_size,
1508c19e654dSHerbert Xu 	.fill_info	= ipgre_fill_info,
15091728d4faSNicolas Dichtel 	.get_link_net	= ip_tunnel_get_link_net,
1510c19e654dSHerbert Xu };
1511c19e654dSHerbert Xu 
1512e1a80002SHerbert Xu static struct rtnl_link_ops ipgre_tap_ops __read_mostly = {
1513e1a80002SHerbert Xu 	.kind		= "gretap",
1514e1a80002SHerbert Xu 	.maxtype	= IFLA_GRE_MAX,
1515e1a80002SHerbert Xu 	.policy		= ipgre_policy,
1516e1a80002SHerbert Xu 	.priv_size	= sizeof(struct ip_tunnel),
1517e1a80002SHerbert Xu 	.setup		= ipgre_tap_setup,
1518e1a80002SHerbert Xu 	.validate	= ipgre_tap_validate,
1519e1a80002SHerbert Xu 	.newlink	= ipgre_newlink,
1520e1a80002SHerbert Xu 	.changelink	= ipgre_changelink,
1521c5441932SPravin B Shelar 	.dellink	= ip_tunnel_dellink,
1522e1a80002SHerbert Xu 	.get_size	= ipgre_get_size,
1523e1a80002SHerbert Xu 	.fill_info	= ipgre_fill_info,
15241728d4faSNicolas Dichtel 	.get_link_net	= ip_tunnel_get_link_net,
1525e1a80002SHerbert Xu };
1526e1a80002SHerbert Xu 
152784e54fe0SWilliam Tu static struct rtnl_link_ops erspan_link_ops __read_mostly = {
152884e54fe0SWilliam Tu 	.kind		= "erspan",
152984e54fe0SWilliam Tu 	.maxtype	= IFLA_GRE_MAX,
153084e54fe0SWilliam Tu 	.policy		= ipgre_policy,
153184e54fe0SWilliam Tu 	.priv_size	= sizeof(struct ip_tunnel),
153284e54fe0SWilliam Tu 	.setup		= erspan_setup,
153384e54fe0SWilliam Tu 	.validate	= erspan_validate,
153484e54fe0SWilliam Tu 	.newlink	= ipgre_newlink,
153584e54fe0SWilliam Tu 	.changelink	= ipgre_changelink,
153684e54fe0SWilliam Tu 	.dellink	= ip_tunnel_dellink,
153784e54fe0SWilliam Tu 	.get_size	= ipgre_get_size,
153884e54fe0SWilliam Tu 	.fill_info	= ipgre_fill_info,
153984e54fe0SWilliam Tu 	.get_link_net	= ip_tunnel_get_link_net,
154084e54fe0SWilliam Tu };
154184e54fe0SWilliam Tu 
1542b2acd1dcSPravin B Shelar struct net_device *gretap_fb_dev_create(struct net *net, const char *name,
1543b2acd1dcSPravin B Shelar 					u8 name_assign_type)
1544b2acd1dcSPravin B Shelar {
1545b2acd1dcSPravin B Shelar 	struct nlattr *tb[IFLA_MAX + 1];
1546b2acd1dcSPravin B Shelar 	struct net_device *dev;
1547106da663SNicolas Dichtel 	LIST_HEAD(list_kill);
1548b2acd1dcSPravin B Shelar 	struct ip_tunnel *t;
1549b2acd1dcSPravin B Shelar 	int err;
1550b2acd1dcSPravin B Shelar 
1551b2acd1dcSPravin B Shelar 	memset(&tb, 0, sizeof(tb));
1552b2acd1dcSPravin B Shelar 
1553b2acd1dcSPravin B Shelar 	dev = rtnl_create_link(net, name, name_assign_type,
1554b2acd1dcSPravin B Shelar 			       &ipgre_tap_ops, tb);
1555b2acd1dcSPravin B Shelar 	if (IS_ERR(dev))
1556b2acd1dcSPravin B Shelar 		return dev;
1557b2acd1dcSPravin B Shelar 
1558b2acd1dcSPravin B Shelar 	/* Configure flow based GRE device. */
1559b2acd1dcSPravin B Shelar 	t = netdev_priv(dev);
1560b2acd1dcSPravin B Shelar 	t->collect_md = true;
1561b2acd1dcSPravin B Shelar 
15627a3f4a18SMatthias Schiffer 	err = ipgre_newlink(net, dev, tb, NULL, NULL);
1563106da663SNicolas Dichtel 	if (err < 0) {
1564106da663SNicolas Dichtel 		free_netdev(dev);
1565106da663SNicolas Dichtel 		return ERR_PTR(err);
1566106da663SNicolas Dichtel 	}
15677e059158SDavid Wragg 
15687e059158SDavid Wragg 	/* openvswitch users expect packet sizes to be unrestricted,
15697e059158SDavid Wragg 	 * so set the largest MTU we can.
15707e059158SDavid Wragg 	 */
15717e059158SDavid Wragg 	err = __ip_tunnel_change_mtu(dev, IP_MAX_MTU, false);
15727e059158SDavid Wragg 	if (err)
15737e059158SDavid Wragg 		goto out;
15747e059158SDavid Wragg 
1575da6f1da8SNicolas Dichtel 	err = rtnl_configure_link(dev, NULL);
1576da6f1da8SNicolas Dichtel 	if (err < 0)
1577da6f1da8SNicolas Dichtel 		goto out;
1578da6f1da8SNicolas Dichtel 
1579b2acd1dcSPravin B Shelar 	return dev;
1580b2acd1dcSPravin B Shelar out:
1581106da663SNicolas Dichtel 	ip_tunnel_dellink(dev, &list_kill);
1582106da663SNicolas Dichtel 	unregister_netdevice_many(&list_kill);
1583b2acd1dcSPravin B Shelar 	return ERR_PTR(err);
1584b2acd1dcSPravin B Shelar }
1585b2acd1dcSPravin B Shelar EXPORT_SYMBOL_GPL(gretap_fb_dev_create);
1586b2acd1dcSPravin B Shelar 
1587c5441932SPravin B Shelar static int __net_init ipgre_tap_init_net(struct net *net)
1588c5441932SPravin B Shelar {
15892e15ea39SPravin B Shelar 	return ip_tunnel_init_net(net, gre_tap_net_id, &ipgre_tap_ops, "gretap0");
1590c5441932SPravin B Shelar }
1591c5441932SPravin B Shelar 
159264bc1781SEric Dumazet static void __net_exit ipgre_tap_exit_batch_net(struct list_head *list_net)
1593c5441932SPravin B Shelar {
159464bc1781SEric Dumazet 	ip_tunnel_delete_nets(list_net, gre_tap_net_id, &ipgre_tap_ops);
1595c5441932SPravin B Shelar }
1596c5441932SPravin B Shelar 
1597c5441932SPravin B Shelar static struct pernet_operations ipgre_tap_net_ops = {
1598c5441932SPravin B Shelar 	.init = ipgre_tap_init_net,
159964bc1781SEric Dumazet 	.exit_batch = ipgre_tap_exit_batch_net,
1600c5441932SPravin B Shelar 	.id   = &gre_tap_net_id,
1601c5441932SPravin B Shelar 	.size = sizeof(struct ip_tunnel_net),
1602c5441932SPravin B Shelar };
16031da177e4SLinus Torvalds 
160484e54fe0SWilliam Tu static int __net_init erspan_init_net(struct net *net)
160584e54fe0SWilliam Tu {
160684e54fe0SWilliam Tu 	return ip_tunnel_init_net(net, erspan_net_id,
160784e54fe0SWilliam Tu 				  &erspan_link_ops, "erspan0");
160884e54fe0SWilliam Tu }
160984e54fe0SWilliam Tu 
161064bc1781SEric Dumazet static void __net_exit erspan_exit_batch_net(struct list_head *net_list)
161184e54fe0SWilliam Tu {
161264bc1781SEric Dumazet 	ip_tunnel_delete_nets(net_list, erspan_net_id, &erspan_link_ops);
161384e54fe0SWilliam Tu }
161484e54fe0SWilliam Tu 
161584e54fe0SWilliam Tu static struct pernet_operations erspan_net_ops = {
161684e54fe0SWilliam Tu 	.init = erspan_init_net,
161764bc1781SEric Dumazet 	.exit_batch = erspan_exit_batch_net,
161884e54fe0SWilliam Tu 	.id   = &erspan_net_id,
161984e54fe0SWilliam Tu 	.size = sizeof(struct ip_tunnel_net),
162084e54fe0SWilliam Tu };
162184e54fe0SWilliam Tu 
16221da177e4SLinus Torvalds static int __init ipgre_init(void)
16231da177e4SLinus Torvalds {
16241da177e4SLinus Torvalds 	int err;
16251da177e4SLinus Torvalds 
1626058bd4d2SJoe Perches 	pr_info("GRE over IPv4 tunneling driver\n");
16271da177e4SLinus Torvalds 
1628cfb8fbf2SEric W. Biederman 	err = register_pernet_device(&ipgre_net_ops);
162959a4c759SPavel Emelyanov 	if (err < 0)
1630c2892f02SAlexey Dobriyan 		return err;
1631c2892f02SAlexey Dobriyan 
1632c5441932SPravin B Shelar 	err = register_pernet_device(&ipgre_tap_net_ops);
1633c5441932SPravin B Shelar 	if (err < 0)
1634e3d0328cSWilliam Tu 		goto pnet_tap_failed;
1635c5441932SPravin B Shelar 
163684e54fe0SWilliam Tu 	err = register_pernet_device(&erspan_net_ops);
163784e54fe0SWilliam Tu 	if (err < 0)
163884e54fe0SWilliam Tu 		goto pnet_erspan_failed;
163984e54fe0SWilliam Tu 
16409f57c67cSPravin B Shelar 	err = gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO);
1641c2892f02SAlexey Dobriyan 	if (err < 0) {
1642058bd4d2SJoe Perches 		pr_info("%s: can't add protocol\n", __func__);
1643c2892f02SAlexey Dobriyan 		goto add_proto_failed;
1644c2892f02SAlexey Dobriyan 	}
16457daa0004SPavel Emelyanov 
1646c19e654dSHerbert Xu 	err = rtnl_link_register(&ipgre_link_ops);
1647c19e654dSHerbert Xu 	if (err < 0)
1648c19e654dSHerbert Xu 		goto rtnl_link_failed;
1649c19e654dSHerbert Xu 
1650e1a80002SHerbert Xu 	err = rtnl_link_register(&ipgre_tap_ops);
1651e1a80002SHerbert Xu 	if (err < 0)
1652e1a80002SHerbert Xu 		goto tap_ops_failed;
1653e1a80002SHerbert Xu 
165484e54fe0SWilliam Tu 	err = rtnl_link_register(&erspan_link_ops);
165584e54fe0SWilliam Tu 	if (err < 0)
165684e54fe0SWilliam Tu 		goto erspan_link_failed;
165784e54fe0SWilliam Tu 
1658c5441932SPravin B Shelar 	return 0;
1659c19e654dSHerbert Xu 
166084e54fe0SWilliam Tu erspan_link_failed:
166184e54fe0SWilliam Tu 	rtnl_link_unregister(&ipgre_tap_ops);
1662e1a80002SHerbert Xu tap_ops_failed:
1663e1a80002SHerbert Xu 	rtnl_link_unregister(&ipgre_link_ops);
1664c19e654dSHerbert Xu rtnl_link_failed:
16659f57c67cSPravin B Shelar 	gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
1666c2892f02SAlexey Dobriyan add_proto_failed:
166784e54fe0SWilliam Tu 	unregister_pernet_device(&erspan_net_ops);
166884e54fe0SWilliam Tu pnet_erspan_failed:
1669c5441932SPravin B Shelar 	unregister_pernet_device(&ipgre_tap_net_ops);
1670e3d0328cSWilliam Tu pnet_tap_failed:
1671c2892f02SAlexey Dobriyan 	unregister_pernet_device(&ipgre_net_ops);
1672c5441932SPravin B Shelar 	return err;
16731da177e4SLinus Torvalds }
16741da177e4SLinus Torvalds 
1675db44575fSAlexey Kuznetsov static void __exit ipgre_fini(void)
16761da177e4SLinus Torvalds {
1677e1a80002SHerbert Xu 	rtnl_link_unregister(&ipgre_tap_ops);
1678c19e654dSHerbert Xu 	rtnl_link_unregister(&ipgre_link_ops);
167984e54fe0SWilliam Tu 	rtnl_link_unregister(&erspan_link_ops);
16809f57c67cSPravin B Shelar 	gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
1681c5441932SPravin B Shelar 	unregister_pernet_device(&ipgre_tap_net_ops);
1682c2892f02SAlexey Dobriyan 	unregister_pernet_device(&ipgre_net_ops);
168384e54fe0SWilliam Tu 	unregister_pernet_device(&erspan_net_ops);
16841da177e4SLinus Torvalds }
16851da177e4SLinus Torvalds 
16861da177e4SLinus Torvalds module_init(ipgre_init);
16871da177e4SLinus Torvalds module_exit(ipgre_fini);
16881da177e4SLinus Torvalds MODULE_LICENSE("GPL");
16894d74f8baSPatrick McHardy MODULE_ALIAS_RTNL_LINK("gre");
16904d74f8baSPatrick McHardy MODULE_ALIAS_RTNL_LINK("gretap");
169184e54fe0SWilliam Tu MODULE_ALIAS_RTNL_LINK("erspan");
16928909c9adSVasiliy Kulikov MODULE_ALIAS_NETDEV("gre0");
1693c5441932SPravin B Shelar MODULE_ALIAS_NETDEV("gretap0");
169484e54fe0SWilliam Tu MODULE_ALIAS_NETDEV("erspan0");
1695