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, 117*a3222dc9SWilliam Tu __be32 id, u32 index, 118*a3222dc9SWilliam 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; 25984e54fe0SWilliam Tu struct ip_tunnel_net *itn; 26084e54fe0SWilliam Tu struct ip_tunnel *tunnel; 26184e54fe0SWilliam Tu struct erspanhdr *ershdr; 26284e54fe0SWilliam Tu const struct iphdr *iph; 26384e54fe0SWilliam Tu __be32 index; 26484e54fe0SWilliam Tu int len; 26584e54fe0SWilliam Tu 26684e54fe0SWilliam Tu itn = net_generic(net, erspan_net_id); 26784e54fe0SWilliam Tu len = gre_hdr_len + sizeof(*ershdr); 26884e54fe0SWilliam Tu 26984e54fe0SWilliam Tu if (unlikely(!pskb_may_pull(skb, len))) 27084e54fe0SWilliam Tu return -ENOMEM; 27184e54fe0SWilliam Tu 27284e54fe0SWilliam Tu iph = ip_hdr(skb); 27384e54fe0SWilliam Tu ershdr = (struct erspanhdr *)(skb->data + gre_hdr_len); 27484e54fe0SWilliam Tu 27584e54fe0SWilliam Tu /* The original GRE header does not have key field, 27684e54fe0SWilliam Tu * Use ERSPAN 10-bit session ID as key. 27784e54fe0SWilliam Tu */ 278935a9749SXin Long tpi->key = cpu_to_be32(ntohs(ershdr->session_id) & ID_MASK); 27984e54fe0SWilliam Tu index = ershdr->md.index; 28084e54fe0SWilliam Tu tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, 28184e54fe0SWilliam Tu tpi->flags | TUNNEL_KEY, 28284e54fe0SWilliam Tu iph->saddr, iph->daddr, tpi->key); 28384e54fe0SWilliam Tu 28484e54fe0SWilliam Tu if (tunnel) { 28584e54fe0SWilliam Tu if (__iptunnel_pull_header(skb, 28684e54fe0SWilliam Tu gre_hdr_len + sizeof(*ershdr), 28784e54fe0SWilliam Tu htons(ETH_P_TEB), 28884e54fe0SWilliam Tu false, false) < 0) 28984e54fe0SWilliam Tu goto drop; 29084e54fe0SWilliam Tu 2911a66a836SWilliam Tu if (tunnel->collect_md) { 2921a66a836SWilliam Tu struct ip_tunnel_info *info; 2931a66a836SWilliam Tu struct erspan_metadata *md; 2941a66a836SWilliam Tu __be64 tun_id; 2951a66a836SWilliam Tu __be16 flags; 2961a66a836SWilliam Tu 2971a66a836SWilliam Tu tpi->flags |= TUNNEL_KEY; 2981a66a836SWilliam Tu flags = tpi->flags; 2991a66a836SWilliam Tu tun_id = key32_to_tunnel_id(tpi->key); 3001a66a836SWilliam Tu 3011a66a836SWilliam Tu tun_dst = ip_tun_rx_dst(skb, flags, 3021a66a836SWilliam Tu tun_id, sizeof(*md)); 3031a66a836SWilliam Tu if (!tun_dst) 3041a66a836SWilliam Tu return PACKET_REJECT; 3051a66a836SWilliam Tu 3061a66a836SWilliam Tu md = ip_tunnel_info_opts(&tun_dst->u.tun_info); 3071a66a836SWilliam Tu if (!md) 3081a66a836SWilliam Tu return PACKET_REJECT; 3091a66a836SWilliam Tu 3101a66a836SWilliam Tu md->index = index; 3111a66a836SWilliam Tu info = &tun_dst->u.tun_info; 3121a66a836SWilliam Tu info->key.tun_flags |= TUNNEL_ERSPAN_OPT; 3131a66a836SWilliam Tu info->options_len = sizeof(*md); 3141a66a836SWilliam Tu } else { 31584e54fe0SWilliam Tu tunnel->index = ntohl(index); 3161a66a836SWilliam Tu } 3171a66a836SWilliam Tu 31884e54fe0SWilliam Tu skb_reset_mac_header(skb); 31984e54fe0SWilliam Tu ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error); 32084e54fe0SWilliam Tu return PACKET_RCVD; 32184e54fe0SWilliam Tu } 32284e54fe0SWilliam Tu drop: 32384e54fe0SWilliam Tu kfree_skb(skb); 32484e54fe0SWilliam Tu return PACKET_RCVD; 32584e54fe0SWilliam Tu } 32684e54fe0SWilliam Tu 327125372faSJiri Benc static int __ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi, 328125372faSJiri Benc struct ip_tunnel_net *itn, int hdr_len, bool raw_proto) 3291da177e4SLinus Torvalds { 3302e15ea39SPravin B Shelar struct metadata_dst *tun_dst = NULL; 331b71d1d42SEric Dumazet const struct iphdr *iph; 3321da177e4SLinus Torvalds struct ip_tunnel *tunnel; 3331da177e4SLinus Torvalds 334eddc9ec5SArnaldo Carvalho de Melo iph = ip_hdr(skb); 335bda7bb46SPravin B Shelar tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags, 336bda7bb46SPravin B Shelar iph->saddr, iph->daddr, tpi->key); 3371da177e4SLinus Torvalds 338d2083287Sstephen hemminger if (tunnel) { 339125372faSJiri Benc if (__iptunnel_pull_header(skb, hdr_len, tpi->proto, 340125372faSJiri Benc raw_proto, false) < 0) 341244a797bSJiri Benc goto drop; 342244a797bSJiri Benc 343e271c7b4SJiri Benc if (tunnel->dev->type != ARPHRD_NONE) 3440e3da5bbSTimo Teräs skb_pop_mac_header(skb); 345e271c7b4SJiri Benc else 346e271c7b4SJiri Benc skb_reset_mac_header(skb); 3472e15ea39SPravin B Shelar if (tunnel->collect_md) { 348c29a70d2SPravin B Shelar __be16 flags; 349c29a70d2SPravin B Shelar __be64 tun_id; 3502e15ea39SPravin B Shelar 351c29a70d2SPravin B Shelar flags = tpi->flags & (TUNNEL_CSUM | TUNNEL_KEY); 352d817f432SAmir Vadai tun_id = key32_to_tunnel_id(tpi->key); 353c29a70d2SPravin B Shelar tun_dst = ip_tun_rx_dst(skb, flags, tun_id, 0); 3542e15ea39SPravin B Shelar if (!tun_dst) 3552e15ea39SPravin B Shelar return PACKET_REJECT; 3562e15ea39SPravin B Shelar } 3572e15ea39SPravin B Shelar 3582e15ea39SPravin B Shelar ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error); 359bda7bb46SPravin B Shelar return PACKET_RCVD; 3601da177e4SLinus Torvalds } 361125372faSJiri Benc return PACKET_NEXT; 362244a797bSJiri Benc 363244a797bSJiri Benc drop: 364244a797bSJiri Benc kfree_skb(skb); 365244a797bSJiri Benc return PACKET_RCVD; 3661da177e4SLinus Torvalds } 3671da177e4SLinus Torvalds 368125372faSJiri Benc static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi, 369125372faSJiri Benc int hdr_len) 370125372faSJiri Benc { 371125372faSJiri Benc struct net *net = dev_net(skb->dev); 372125372faSJiri Benc struct ip_tunnel_net *itn; 373125372faSJiri Benc int res; 374125372faSJiri Benc 375125372faSJiri Benc if (tpi->proto == htons(ETH_P_TEB)) 376125372faSJiri Benc itn = net_generic(net, gre_tap_net_id); 377125372faSJiri Benc else 378125372faSJiri Benc itn = net_generic(net, ipgre_net_id); 379125372faSJiri Benc 380125372faSJiri Benc res = __ipgre_rcv(skb, tpi, itn, hdr_len, false); 381125372faSJiri Benc if (res == PACKET_NEXT && tpi->proto == htons(ETH_P_TEB)) { 382125372faSJiri Benc /* ipgre tunnels in collect metadata mode should receive 383125372faSJiri Benc * also ETH_P_TEB traffic. 384125372faSJiri Benc */ 385125372faSJiri Benc itn = net_generic(net, ipgre_net_id); 386125372faSJiri Benc res = __ipgre_rcv(skb, tpi, itn, hdr_len, true); 387125372faSJiri Benc } 388125372faSJiri Benc return res; 389125372faSJiri Benc } 390125372faSJiri Benc 3919f57c67cSPravin B Shelar static int gre_rcv(struct sk_buff *skb) 3929f57c67cSPravin B Shelar { 3939f57c67cSPravin B Shelar struct tnl_ptk_info tpi; 3949f57c67cSPravin B Shelar bool csum_err = false; 39595f5c64cSTom Herbert int hdr_len; 3969f57c67cSPravin B Shelar 3979f57c67cSPravin B Shelar #ifdef CONFIG_NET_IPGRE_BROADCAST 3989f57c67cSPravin B Shelar if (ipv4_is_multicast(ip_hdr(skb)->daddr)) { 3999f57c67cSPravin B Shelar /* Looped back packet, drop it! */ 4009f57c67cSPravin B Shelar if (rt_is_output_route(skb_rtable(skb))) 4019f57c67cSPravin B Shelar goto drop; 4029f57c67cSPravin B Shelar } 4039f57c67cSPravin B Shelar #endif 4049f57c67cSPravin B Shelar 405e582615aSEric Dumazet hdr_len = gre_parse_header(skb, &tpi, &csum_err, htons(ETH_P_IP), 0); 406f132ae7cSJiri Benc if (hdr_len < 0) 40795f5c64cSTom Herbert goto drop; 40895f5c64cSTom Herbert 40984e54fe0SWilliam Tu if (unlikely(tpi.proto == htons(ETH_P_ERSPAN))) { 41084e54fe0SWilliam Tu if (erspan_rcv(skb, &tpi, hdr_len) == PACKET_RCVD) 41184e54fe0SWilliam Tu return 0; 41284e54fe0SWilliam Tu } 41384e54fe0SWilliam Tu 414244a797bSJiri Benc if (ipgre_rcv(skb, &tpi, hdr_len) == PACKET_RCVD) 4159f57c67cSPravin B Shelar return 0; 4169f57c67cSPravin B Shelar 4179f57c67cSPravin B Shelar icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); 4189f57c67cSPravin B Shelar drop: 4199f57c67cSPravin B Shelar kfree_skb(skb); 4209f57c67cSPravin B Shelar return 0; 4219f57c67cSPravin B Shelar } 4229f57c67cSPravin B Shelar 423c5441932SPravin B Shelar static void __gre_xmit(struct sk_buff *skb, struct net_device *dev, 424c5441932SPravin B Shelar const struct iphdr *tnl_params, 425c5441932SPravin B Shelar __be16 proto) 426c5441932SPravin B Shelar { 427c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 428c5441932SPravin B Shelar 429c5441932SPravin B Shelar if (tunnel->parms.o_flags & TUNNEL_SEQ) 430c5441932SPravin B Shelar tunnel->o_seqno++; 431cef401deSEric Dumazet 432c5441932SPravin B Shelar /* Push GRE header. */ 433182a352dSTom Herbert gre_build_header(skb, tunnel->tun_hlen, 434182a352dSTom Herbert tunnel->parms.o_flags, proto, tunnel->parms.o_key, 435182a352dSTom Herbert htonl(tunnel->o_seqno)); 4361da177e4SLinus Torvalds 437bf3d6a8fSNicolas Dichtel ip_tunnel_xmit(skb, dev, tnl_params, tnl_params->protocol); 4381da177e4SLinus Torvalds } 4391da177e4SLinus Torvalds 440aed069dfSAlexander Duyck static int gre_handle_offloads(struct sk_buff *skb, bool csum) 441b2acd1dcSPravin B Shelar { 4426fa79666SEdward Cree return iptunnel_handle_offloads(skb, csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE); 443b2acd1dcSPravin B Shelar } 444b2acd1dcSPravin B Shelar 445fc4099f1SPravin B Shelar static struct rtable *gre_get_rt(struct sk_buff *skb, 446fc4099f1SPravin B Shelar struct net_device *dev, 447fc4099f1SPravin B Shelar struct flowi4 *fl, 448fc4099f1SPravin B Shelar const struct ip_tunnel_key *key) 449fc4099f1SPravin B Shelar { 450fc4099f1SPravin B Shelar struct net *net = dev_net(dev); 451fc4099f1SPravin B Shelar 452fc4099f1SPravin B Shelar memset(fl, 0, sizeof(*fl)); 453fc4099f1SPravin B Shelar fl->daddr = key->u.ipv4.dst; 454fc4099f1SPravin B Shelar fl->saddr = key->u.ipv4.src; 455fc4099f1SPravin B Shelar fl->flowi4_tos = RT_TOS(key->tos); 456fc4099f1SPravin B Shelar fl->flowi4_mark = skb->mark; 457fc4099f1SPravin B Shelar fl->flowi4_proto = IPPROTO_GRE; 458fc4099f1SPravin B Shelar 459fc4099f1SPravin B Shelar return ip_route_output_key(net, fl); 460fc4099f1SPravin B Shelar } 461fc4099f1SPravin B Shelar 462862a03c3SWilliam Tu static struct rtable *prepare_fb_xmit(struct sk_buff *skb, 463862a03c3SWilliam Tu struct net_device *dev, 464862a03c3SWilliam Tu struct flowi4 *fl, 465862a03c3SWilliam Tu int tunnel_hlen) 4662e15ea39SPravin B Shelar { 4672e15ea39SPravin B Shelar struct ip_tunnel_info *tun_info; 4682e15ea39SPravin B Shelar const struct ip_tunnel_key *key; 469db3c6139SDaniel Borkmann struct rtable *rt = NULL; 4702e15ea39SPravin B Shelar int min_headroom; 471db3c6139SDaniel Borkmann bool use_cache; 4722e15ea39SPravin B Shelar int err; 4732e15ea39SPravin B Shelar 47461adedf3SJiri Benc tun_info = skb_tunnel_info(skb); 4752e15ea39SPravin B Shelar key = &tun_info->key; 476db3c6139SDaniel Borkmann use_cache = ip_tunnel_dst_cache_usable(skb, tun_info); 477862a03c3SWilliam Tu 478db3c6139SDaniel Borkmann if (use_cache) 479862a03c3SWilliam Tu rt = dst_cache_get_ip4(&tun_info->dst_cache, &fl->saddr); 4803c1cb4d2SPaolo Abeni if (!rt) { 481862a03c3SWilliam Tu rt = gre_get_rt(skb, dev, fl, key); 4822e15ea39SPravin B Shelar if (IS_ERR(rt)) 4832e15ea39SPravin B Shelar goto err_free_skb; 484db3c6139SDaniel Borkmann if (use_cache) 4853c1cb4d2SPaolo Abeni dst_cache_set_ip4(&tun_info->dst_cache, &rt->dst, 486862a03c3SWilliam Tu fl->saddr); 4873c1cb4d2SPaolo Abeni } 4882e15ea39SPravin B Shelar 4892e15ea39SPravin B Shelar min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len 4902e15ea39SPravin B Shelar + tunnel_hlen + sizeof(struct iphdr); 4912e15ea39SPravin B Shelar if (skb_headroom(skb) < min_headroom || skb_header_cloned(skb)) { 4922e15ea39SPravin B Shelar int head_delta = SKB_DATA_ALIGN(min_headroom - 4932e15ea39SPravin B Shelar skb_headroom(skb) + 4942e15ea39SPravin B Shelar 16); 4952e15ea39SPravin B Shelar err = pskb_expand_head(skb, max_t(int, head_delta, 0), 4962e15ea39SPravin B Shelar 0, GFP_ATOMIC); 4972e15ea39SPravin B Shelar if (unlikely(err)) 4982e15ea39SPravin B Shelar goto err_free_rt; 4992e15ea39SPravin B Shelar } 500862a03c3SWilliam Tu return rt; 501862a03c3SWilliam Tu 502862a03c3SWilliam Tu err_free_rt: 503862a03c3SWilliam Tu ip_rt_put(rt); 504862a03c3SWilliam Tu err_free_skb: 505862a03c3SWilliam Tu kfree_skb(skb); 506862a03c3SWilliam Tu dev->stats.tx_dropped++; 507862a03c3SWilliam Tu return NULL; 508862a03c3SWilliam Tu } 509862a03c3SWilliam Tu 510862a03c3SWilliam Tu static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev, 511862a03c3SWilliam Tu __be16 proto) 512862a03c3SWilliam Tu { 513862a03c3SWilliam Tu struct ip_tunnel_info *tun_info; 514862a03c3SWilliam Tu const struct ip_tunnel_key *key; 515862a03c3SWilliam Tu struct rtable *rt = NULL; 516862a03c3SWilliam Tu struct flowi4 fl; 517862a03c3SWilliam Tu int tunnel_hlen; 518862a03c3SWilliam Tu __be16 df, flags; 519862a03c3SWilliam Tu 520862a03c3SWilliam Tu tun_info = skb_tunnel_info(skb); 521862a03c3SWilliam Tu if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) || 522862a03c3SWilliam Tu ip_tunnel_info_af(tun_info) != AF_INET)) 523862a03c3SWilliam Tu goto err_free_skb; 524862a03c3SWilliam Tu 525862a03c3SWilliam Tu key = &tun_info->key; 526862a03c3SWilliam Tu tunnel_hlen = gre_calc_hlen(key->tun_flags); 527862a03c3SWilliam Tu 528862a03c3SWilliam Tu rt = prepare_fb_xmit(skb, dev, &fl, tunnel_hlen); 529862a03c3SWilliam Tu if (!rt) 530862a03c3SWilliam Tu return; 5312e15ea39SPravin B Shelar 5322e15ea39SPravin B Shelar /* Push Tunnel header. */ 533aed069dfSAlexander Duyck if (gre_handle_offloads(skb, !!(tun_info->key.tun_flags & TUNNEL_CSUM))) 5342e15ea39SPravin B Shelar goto err_free_rt; 5352e15ea39SPravin B Shelar 5362e15ea39SPravin B Shelar flags = tun_info->key.tun_flags & (TUNNEL_CSUM | TUNNEL_KEY); 537cba65321SDavid S. Miller gre_build_header(skb, tunnel_hlen, flags, proto, 538d817f432SAmir Vadai tunnel_id_to_key32(tun_info->key.tun_id), 0); 5392e15ea39SPravin B Shelar 5402e15ea39SPravin B Shelar df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0; 541039f5062SPravin B Shelar 542039f5062SPravin B Shelar iptunnel_xmit(skb->sk, rt, skb, fl.saddr, key->u.ipv4.dst, IPPROTO_GRE, 5437c383fb2SJiri Benc key->tos, key->ttl, df, false); 5442e15ea39SPravin B Shelar return; 5452e15ea39SPravin B Shelar 5462e15ea39SPravin B Shelar err_free_rt: 5472e15ea39SPravin B Shelar ip_rt_put(rt); 5482e15ea39SPravin B Shelar err_free_skb: 5492e15ea39SPravin B Shelar kfree_skb(skb); 5502e15ea39SPravin B Shelar dev->stats.tx_dropped++; 5512e15ea39SPravin B Shelar } 5522e15ea39SPravin B Shelar 5531a66a836SWilliam Tu static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev, 5541a66a836SWilliam Tu __be16 proto) 5551a66a836SWilliam Tu { 5561a66a836SWilliam Tu struct ip_tunnel *tunnel = netdev_priv(dev); 5571a66a836SWilliam Tu struct ip_tunnel_info *tun_info; 5581a66a836SWilliam Tu const struct ip_tunnel_key *key; 5591a66a836SWilliam Tu struct erspan_metadata *md; 5601a66a836SWilliam Tu struct rtable *rt = NULL; 5611a66a836SWilliam Tu bool truncate = false; 5621a66a836SWilliam Tu struct flowi4 fl; 5631a66a836SWilliam Tu int tunnel_hlen; 5641a66a836SWilliam Tu __be16 df; 5651a66a836SWilliam Tu 5661a66a836SWilliam Tu tun_info = skb_tunnel_info(skb); 5671a66a836SWilliam Tu if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) || 5681a66a836SWilliam Tu ip_tunnel_info_af(tun_info) != AF_INET)) 5691a66a836SWilliam Tu goto err_free_skb; 5701a66a836SWilliam Tu 5711a66a836SWilliam Tu key = &tun_info->key; 5721a66a836SWilliam Tu 5731a66a836SWilliam Tu /* ERSPAN has fixed 8 byte GRE header */ 5741a66a836SWilliam Tu tunnel_hlen = 8 + sizeof(struct erspanhdr); 5751a66a836SWilliam Tu 5761a66a836SWilliam Tu rt = prepare_fb_xmit(skb, dev, &fl, tunnel_hlen); 5771a66a836SWilliam Tu if (!rt) 5781a66a836SWilliam Tu return; 5791a66a836SWilliam Tu 5801a66a836SWilliam Tu if (gre_handle_offloads(skb, false)) 5811a66a836SWilliam Tu goto err_free_rt; 5821a66a836SWilliam Tu 583f192970dSWilliam Tu if (skb->len > dev->mtu + dev->hard_header_len) { 584f192970dSWilliam Tu pskb_trim(skb, dev->mtu + dev->hard_header_len); 5851a66a836SWilliam Tu truncate = true; 5861a66a836SWilliam Tu } 5871a66a836SWilliam Tu 5881a66a836SWilliam Tu md = ip_tunnel_info_opts(tun_info); 5891a66a836SWilliam Tu if (!md) 5901a66a836SWilliam Tu goto err_free_rt; 5911a66a836SWilliam Tu 5921a66a836SWilliam Tu erspan_build_header(skb, tunnel_id_to_key32(key->tun_id), 593*a3222dc9SWilliam Tu ntohl(md->index), truncate, true); 5941a66a836SWilliam Tu 5951a66a836SWilliam Tu gre_build_header(skb, 8, TUNNEL_SEQ, 5961a66a836SWilliam Tu htons(ETH_P_ERSPAN), 0, htonl(tunnel->o_seqno++)); 5971a66a836SWilliam Tu 5981a66a836SWilliam Tu df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0; 5991a66a836SWilliam Tu 6001a66a836SWilliam Tu iptunnel_xmit(skb->sk, rt, skb, fl.saddr, key->u.ipv4.dst, IPPROTO_GRE, 6011a66a836SWilliam Tu key->tos, key->ttl, df, false); 6021a66a836SWilliam Tu return; 6031a66a836SWilliam Tu 6041a66a836SWilliam Tu err_free_rt: 6051a66a836SWilliam Tu ip_rt_put(rt); 6061a66a836SWilliam Tu err_free_skb: 6071a66a836SWilliam Tu kfree_skb(skb); 6081a66a836SWilliam Tu dev->stats.tx_dropped++; 6091a66a836SWilliam Tu } 6101a66a836SWilliam Tu 611fc4099f1SPravin B Shelar static int gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) 612fc4099f1SPravin B Shelar { 613fc4099f1SPravin B Shelar struct ip_tunnel_info *info = skb_tunnel_info(skb); 614fc4099f1SPravin B Shelar struct rtable *rt; 615fc4099f1SPravin B Shelar struct flowi4 fl4; 616fc4099f1SPravin B Shelar 617fc4099f1SPravin B Shelar if (ip_tunnel_info_af(info) != AF_INET) 618fc4099f1SPravin B Shelar return -EINVAL; 619fc4099f1SPravin B Shelar 620fc4099f1SPravin B Shelar rt = gre_get_rt(skb, dev, &fl4, &info->key); 621fc4099f1SPravin B Shelar if (IS_ERR(rt)) 622fc4099f1SPravin B Shelar return PTR_ERR(rt); 623fc4099f1SPravin B Shelar 624fc4099f1SPravin B Shelar ip_rt_put(rt); 625fc4099f1SPravin B Shelar info->key.u.ipv4.src = fl4.saddr; 626fc4099f1SPravin B Shelar return 0; 627fc4099f1SPravin B Shelar } 628fc4099f1SPravin B Shelar 629c5441932SPravin B Shelar static netdev_tx_t ipgre_xmit(struct sk_buff *skb, 630c5441932SPravin B Shelar struct net_device *dev) 631ee34c1ebSMichal Schmidt { 632c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 633c5441932SPravin B Shelar const struct iphdr *tnl_params; 634ee34c1ebSMichal Schmidt 6352e15ea39SPravin B Shelar if (tunnel->collect_md) { 6362090714eSJiri Benc gre_fb_xmit(skb, dev, skb->protocol); 6372e15ea39SPravin B Shelar return NETDEV_TX_OK; 6382e15ea39SPravin B Shelar } 6392e15ea39SPravin B Shelar 640c5441932SPravin B Shelar if (dev->header_ops) { 641c5441932SPravin B Shelar /* Need space for new headers */ 642c5441932SPravin B Shelar if (skb_cow_head(skb, dev->needed_headroom - 6432bac7cb3SChen Gang (tunnel->hlen + sizeof(struct iphdr)))) 644c5441932SPravin B Shelar goto free_skb; 645ee34c1ebSMichal Schmidt 646c5441932SPravin B Shelar tnl_params = (const struct iphdr *)skb->data; 647cbb1e85fSDavid S. Miller 648c5441932SPravin B Shelar /* Pull skb since ip_tunnel_xmit() needs skb->data pointing 649c5441932SPravin B Shelar * to gre header. 650c5441932SPravin B Shelar */ 651c5441932SPravin B Shelar skb_pull(skb, tunnel->hlen + sizeof(struct iphdr)); 6528a0033a9STimo Teräs skb_reset_mac_header(skb); 653c5441932SPravin B Shelar } else { 654c5441932SPravin B Shelar if (skb_cow_head(skb, dev->needed_headroom)) 655c5441932SPravin B Shelar goto free_skb; 656c5441932SPravin B Shelar 657c5441932SPravin B Shelar tnl_params = &tunnel->parms.iph; 658ee34c1ebSMichal Schmidt } 659e1a80002SHerbert Xu 660aed069dfSAlexander Duyck if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM))) 661aed069dfSAlexander Duyck goto free_skb; 6628a0033a9STimo Teräs 663c5441932SPravin B Shelar __gre_xmit(skb, dev, tnl_params, skb->protocol); 664c5441932SPravin B Shelar return NETDEV_TX_OK; 665c5441932SPravin B Shelar 666c5441932SPravin B Shelar free_skb: 6673acfa1e7SEric Dumazet kfree_skb(skb); 668c5441932SPravin B Shelar dev->stats.tx_dropped++; 669c5441932SPravin B Shelar return NETDEV_TX_OK; 670ee34c1ebSMichal Schmidt } 671ee34c1ebSMichal Schmidt 67284e54fe0SWilliam Tu static netdev_tx_t erspan_xmit(struct sk_buff *skb, 67384e54fe0SWilliam Tu struct net_device *dev) 67484e54fe0SWilliam Tu { 67584e54fe0SWilliam Tu struct ip_tunnel *tunnel = netdev_priv(dev); 67684e54fe0SWilliam Tu bool truncate = false; 67784e54fe0SWilliam Tu 6781a66a836SWilliam Tu if (tunnel->collect_md) { 6791a66a836SWilliam Tu erspan_fb_xmit(skb, dev, skb->protocol); 6801a66a836SWilliam Tu return NETDEV_TX_OK; 6811a66a836SWilliam Tu } 6821a66a836SWilliam Tu 68384e54fe0SWilliam Tu if (gre_handle_offloads(skb, false)) 68484e54fe0SWilliam Tu goto free_skb; 68584e54fe0SWilliam Tu 68684e54fe0SWilliam Tu if (skb_cow_head(skb, dev->needed_headroom)) 68784e54fe0SWilliam Tu goto free_skb; 68884e54fe0SWilliam Tu 689f192970dSWilliam Tu if (skb->len > dev->mtu + dev->hard_header_len) { 690f192970dSWilliam Tu pskb_trim(skb, dev->mtu + dev->hard_header_len); 69184e54fe0SWilliam Tu truncate = true; 69284e54fe0SWilliam Tu } 69384e54fe0SWilliam Tu 69484e54fe0SWilliam Tu /* Push ERSPAN header */ 695*a3222dc9SWilliam Tu erspan_build_header(skb, tunnel->parms.o_key, tunnel->index, 696*a3222dc9SWilliam Tu truncate, true); 69784e54fe0SWilliam Tu tunnel->parms.o_flags &= ~TUNNEL_KEY; 69884e54fe0SWilliam Tu __gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_ERSPAN)); 69984e54fe0SWilliam Tu return NETDEV_TX_OK; 70084e54fe0SWilliam Tu 70184e54fe0SWilliam Tu free_skb: 70284e54fe0SWilliam Tu kfree_skb(skb); 70384e54fe0SWilliam Tu dev->stats.tx_dropped++; 70484e54fe0SWilliam Tu return NETDEV_TX_OK; 70584e54fe0SWilliam Tu } 70684e54fe0SWilliam Tu 707c5441932SPravin B Shelar static netdev_tx_t gre_tap_xmit(struct sk_buff *skb, 708c5441932SPravin B Shelar struct net_device *dev) 709c5441932SPravin B Shelar { 710c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 711ee34c1ebSMichal Schmidt 7122e15ea39SPravin B Shelar if (tunnel->collect_md) { 7132090714eSJiri Benc gre_fb_xmit(skb, dev, htons(ETH_P_TEB)); 7142e15ea39SPravin B Shelar return NETDEV_TX_OK; 7152e15ea39SPravin B Shelar } 7162e15ea39SPravin B Shelar 717aed069dfSAlexander Duyck if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM))) 718aed069dfSAlexander Duyck goto free_skb; 719ee34c1ebSMichal Schmidt 720c5441932SPravin B Shelar if (skb_cow_head(skb, dev->needed_headroom)) 721c5441932SPravin B Shelar goto free_skb; 72242aa9162SHerbert Xu 723c5441932SPravin B Shelar __gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_TEB)); 724c5441932SPravin B Shelar return NETDEV_TX_OK; 725c5441932SPravin B Shelar 726c5441932SPravin B Shelar free_skb: 7273acfa1e7SEric Dumazet kfree_skb(skb); 728c5441932SPravin B Shelar dev->stats.tx_dropped++; 729c5441932SPravin B Shelar return NETDEV_TX_OK; 73068c33163SPravin B Shelar } 731ee34c1ebSMichal Schmidt 732dd9d598cSXin Long static void ipgre_link_update(struct net_device *dev, bool set_mtu) 733dd9d598cSXin Long { 734dd9d598cSXin Long struct ip_tunnel *tunnel = netdev_priv(dev); 735dd9d598cSXin Long int len; 736dd9d598cSXin Long 737dd9d598cSXin Long len = tunnel->tun_hlen; 738dd9d598cSXin Long tunnel->tun_hlen = gre_calc_hlen(tunnel->parms.o_flags); 739dd9d598cSXin Long len = tunnel->tun_hlen - len; 740dd9d598cSXin Long tunnel->hlen = tunnel->hlen + len; 741dd9d598cSXin Long 742dd9d598cSXin Long dev->needed_headroom = dev->needed_headroom + len; 743dd9d598cSXin Long if (set_mtu) 744dd9d598cSXin Long dev->mtu = max_t(int, dev->mtu - len, 68); 745dd9d598cSXin Long 746dd9d598cSXin Long if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) { 747dd9d598cSXin Long if (!(tunnel->parms.o_flags & TUNNEL_CSUM) || 748dd9d598cSXin Long tunnel->encap.type == TUNNEL_ENCAP_NONE) { 749dd9d598cSXin Long dev->features |= NETIF_F_GSO_SOFTWARE; 750dd9d598cSXin Long dev->hw_features |= NETIF_F_GSO_SOFTWARE; 751dd9d598cSXin Long } 752dd9d598cSXin Long dev->features |= NETIF_F_LLTX; 753dd9d598cSXin Long } 754dd9d598cSXin Long } 755dd9d598cSXin Long 756c5441932SPravin B Shelar static int ipgre_tunnel_ioctl(struct net_device *dev, 757c5441932SPravin B Shelar struct ifreq *ifr, int cmd) 7581da177e4SLinus Torvalds { 7591da177e4SLinus Torvalds struct ip_tunnel_parm p; 760a0efab67SXin Long int err; 7611da177e4SLinus Torvalds 7621da177e4SLinus Torvalds if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) 763c5441932SPravin B Shelar return -EFAULT; 764a0efab67SXin Long 7656c734fb8SCong Wang if (cmd == SIOCADDTUNNEL || cmd == SIOCCHGTUNNEL) { 7661da177e4SLinus Torvalds if (p.iph.version != 4 || p.iph.protocol != IPPROTO_GRE || 7671da177e4SLinus Torvalds p.iph.ihl != 5 || (p.iph.frag_off & htons(~IP_DF)) || 7686c734fb8SCong Wang ((p.i_flags | p.o_flags) & (GRE_VERSION | GRE_ROUTING))) 7691da177e4SLinus Torvalds return -EINVAL; 770c5441932SPravin B Shelar } 771a0efab67SXin Long 772c5441932SPravin B Shelar p.i_flags = gre_flags_to_tnl_flags(p.i_flags); 773c5441932SPravin B Shelar p.o_flags = gre_flags_to_tnl_flags(p.o_flags); 774c5441932SPravin B Shelar 775c5441932SPravin B Shelar err = ip_tunnel_ioctl(dev, &p, cmd); 776c5441932SPravin B Shelar if (err) 777c5441932SPravin B Shelar return err; 778c5441932SPravin B Shelar 779a0efab67SXin Long if (cmd == SIOCCHGTUNNEL) { 780a0efab67SXin Long struct ip_tunnel *t = netdev_priv(dev); 781a0efab67SXin Long 782a0efab67SXin Long t->parms.i_flags = p.i_flags; 783a0efab67SXin Long t->parms.o_flags = p.o_flags; 784a0efab67SXin Long 785a0efab67SXin Long if (strcmp(dev->rtnl_link_ops->kind, "erspan")) 786a0efab67SXin Long ipgre_link_update(dev, true); 787a0efab67SXin Long } 788a0efab67SXin Long 78995f5c64cSTom Herbert p.i_flags = gre_tnl_flags_to_gre_flags(p.i_flags); 79095f5c64cSTom Herbert p.o_flags = gre_tnl_flags_to_gre_flags(p.o_flags); 791c5441932SPravin B Shelar 792c5441932SPravin B Shelar if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) 793c5441932SPravin B Shelar return -EFAULT; 794a0efab67SXin Long 7951da177e4SLinus Torvalds return 0; 7961da177e4SLinus Torvalds } 7971da177e4SLinus Torvalds 7981da177e4SLinus Torvalds /* Nice toy. Unfortunately, useless in real life :-) 7991da177e4SLinus Torvalds It allows to construct virtual multiprotocol broadcast "LAN" 8001da177e4SLinus Torvalds over the Internet, provided multicast routing is tuned. 8011da177e4SLinus Torvalds 8021da177e4SLinus Torvalds 8031da177e4SLinus Torvalds I have no idea was this bicycle invented before me, 8041da177e4SLinus Torvalds so that I had to set ARPHRD_IPGRE to a random value. 8051da177e4SLinus Torvalds I have an impression, that Cisco could make something similar, 8061da177e4SLinus Torvalds but this feature is apparently missing in IOS<=11.2(8). 8071da177e4SLinus Torvalds 8081da177e4SLinus Torvalds I set up 10.66.66/24 and fec0:6666:6666::0/96 as virtual networks 8091da177e4SLinus Torvalds with broadcast 224.66.66.66. If you have access to mbone, play with me :-) 8101da177e4SLinus Torvalds 8111da177e4SLinus Torvalds ping -t 255 224.66.66.66 8121da177e4SLinus Torvalds 8131da177e4SLinus Torvalds If nobody answers, mbone does not work. 8141da177e4SLinus Torvalds 8151da177e4SLinus Torvalds ip tunnel add Universe mode gre remote 224.66.66.66 local <Your_real_addr> ttl 255 8161da177e4SLinus Torvalds ip addr add 10.66.66.<somewhat>/24 dev Universe 8171da177e4SLinus Torvalds ifconfig Universe up 8181da177e4SLinus Torvalds ifconfig Universe add fe80::<Your_real_addr>/10 8191da177e4SLinus Torvalds ifconfig Universe add fec0:6666:6666::<Your_real_addr>/96 8201da177e4SLinus Torvalds ftp 10.66.66.66 8211da177e4SLinus Torvalds ... 8221da177e4SLinus Torvalds ftp fec0:6666:6666::193.233.7.65 8231da177e4SLinus Torvalds ... 8241da177e4SLinus Torvalds */ 8253b04dddeSStephen Hemminger static int ipgre_header(struct sk_buff *skb, struct net_device *dev, 8263b04dddeSStephen Hemminger unsigned short type, 8271507850bSEric Dumazet const void *daddr, const void *saddr, unsigned int len) 8281da177e4SLinus Torvalds { 8292941a486SPatrick McHardy struct ip_tunnel *t = netdev_priv(dev); 830c5441932SPravin B Shelar struct iphdr *iph; 831c5441932SPravin B Shelar struct gre_base_hdr *greh; 832c5441932SPravin B Shelar 833d58ff351SJohannes Berg iph = skb_push(skb, t->hlen + sizeof(*iph)); 834c5441932SPravin B Shelar greh = (struct gre_base_hdr *)(iph+1); 83595f5c64cSTom Herbert greh->flags = gre_tnl_flags_to_gre_flags(t->parms.o_flags); 836c5441932SPravin B Shelar greh->protocol = htons(type); 8371da177e4SLinus Torvalds 8381da177e4SLinus Torvalds memcpy(iph, &t->parms.iph, sizeof(struct iphdr)); 8391da177e4SLinus Torvalds 840c5441932SPravin B Shelar /* Set the source hardware address. */ 8411da177e4SLinus Torvalds if (saddr) 8421da177e4SLinus Torvalds memcpy(&iph->saddr, saddr, 4); 8436d55cb91STimo Teräs if (daddr) 8441da177e4SLinus Torvalds memcpy(&iph->daddr, daddr, 4); 8456d55cb91STimo Teräs if (iph->daddr) 84677a482bdSTimo Teräs return t->hlen + sizeof(*iph); 8471da177e4SLinus Torvalds 848c5441932SPravin B Shelar return -(t->hlen + sizeof(*iph)); 8491da177e4SLinus Torvalds } 8501da177e4SLinus Torvalds 8516a5f44d7STimo Teras static int ipgre_header_parse(const struct sk_buff *skb, unsigned char *haddr) 8526a5f44d7STimo Teras { 853b71d1d42SEric Dumazet const struct iphdr *iph = (const struct iphdr *) skb_mac_header(skb); 8546a5f44d7STimo Teras memcpy(haddr, &iph->saddr, 4); 8556a5f44d7STimo Teras return 4; 8566a5f44d7STimo Teras } 8576a5f44d7STimo Teras 8583b04dddeSStephen Hemminger static const struct header_ops ipgre_header_ops = { 8593b04dddeSStephen Hemminger .create = ipgre_header, 8606a5f44d7STimo Teras .parse = ipgre_header_parse, 8613b04dddeSStephen Hemminger }; 8623b04dddeSStephen Hemminger 8636a5f44d7STimo Teras #ifdef CONFIG_NET_IPGRE_BROADCAST 8641da177e4SLinus Torvalds static int ipgre_open(struct net_device *dev) 8651da177e4SLinus Torvalds { 8662941a486SPatrick McHardy struct ip_tunnel *t = netdev_priv(dev); 8671da177e4SLinus Torvalds 868f97c1e0cSJoe Perches if (ipv4_is_multicast(t->parms.iph.daddr)) { 869cbb1e85fSDavid S. Miller struct flowi4 fl4; 870cbb1e85fSDavid S. Miller struct rtable *rt; 871cbb1e85fSDavid S. Miller 872b57708adSNicolas Dichtel rt = ip_route_output_gre(t->net, &fl4, 87378fbfd8aSDavid S. Miller t->parms.iph.daddr, 87478fbfd8aSDavid S. Miller t->parms.iph.saddr, 87578fbfd8aSDavid S. Miller t->parms.o_key, 87678fbfd8aSDavid S. Miller RT_TOS(t->parms.iph.tos), 87778fbfd8aSDavid S. Miller t->parms.link); 878b23dd4feSDavid S. Miller if (IS_ERR(rt)) 8791da177e4SLinus Torvalds return -EADDRNOTAVAIL; 880d8d1f30bSChangli Gao dev = rt->dst.dev; 8811da177e4SLinus Torvalds ip_rt_put(rt); 88251456b29SIan Morris if (!__in_dev_get_rtnl(dev)) 8831da177e4SLinus Torvalds return -EADDRNOTAVAIL; 8841da177e4SLinus Torvalds t->mlink = dev->ifindex; 885e5ed6399SHerbert Xu ip_mc_inc_group(__in_dev_get_rtnl(dev), t->parms.iph.daddr); 8861da177e4SLinus Torvalds } 8871da177e4SLinus Torvalds return 0; 8881da177e4SLinus Torvalds } 8891da177e4SLinus Torvalds 8901da177e4SLinus Torvalds static int ipgre_close(struct net_device *dev) 8911da177e4SLinus Torvalds { 8922941a486SPatrick McHardy struct ip_tunnel *t = netdev_priv(dev); 893b8c26a33SStephen Hemminger 894f97c1e0cSJoe Perches if (ipv4_is_multicast(t->parms.iph.daddr) && t->mlink) { 8957fee0ca2SDenis V. Lunev struct in_device *in_dev; 896b57708adSNicolas Dichtel in_dev = inetdev_by_index(t->net, t->mlink); 8978723e1b4SEric Dumazet if (in_dev) 8981da177e4SLinus Torvalds ip_mc_dec_group(in_dev, t->parms.iph.daddr); 8991da177e4SLinus Torvalds } 9001da177e4SLinus Torvalds return 0; 9011da177e4SLinus Torvalds } 9021da177e4SLinus Torvalds #endif 9031da177e4SLinus Torvalds 904b8c26a33SStephen Hemminger static const struct net_device_ops ipgre_netdev_ops = { 905b8c26a33SStephen Hemminger .ndo_init = ipgre_tunnel_init, 906c5441932SPravin B Shelar .ndo_uninit = ip_tunnel_uninit, 907b8c26a33SStephen Hemminger #ifdef CONFIG_NET_IPGRE_BROADCAST 908b8c26a33SStephen Hemminger .ndo_open = ipgre_open, 909b8c26a33SStephen Hemminger .ndo_stop = ipgre_close, 910b8c26a33SStephen Hemminger #endif 911c5441932SPravin B Shelar .ndo_start_xmit = ipgre_xmit, 912b8c26a33SStephen Hemminger .ndo_do_ioctl = ipgre_tunnel_ioctl, 913c5441932SPravin B Shelar .ndo_change_mtu = ip_tunnel_change_mtu, 914c5441932SPravin B Shelar .ndo_get_stats64 = ip_tunnel_get_stats64, 9151e99584bSNicolas Dichtel .ndo_get_iflink = ip_tunnel_get_iflink, 916b8c26a33SStephen Hemminger }; 917b8c26a33SStephen Hemminger 9186b78f16eSEric Dumazet #define GRE_FEATURES (NETIF_F_SG | \ 9196b78f16eSEric Dumazet NETIF_F_FRAGLIST | \ 9206b78f16eSEric Dumazet NETIF_F_HIGHDMA | \ 9216b78f16eSEric Dumazet NETIF_F_HW_CSUM) 9226b78f16eSEric Dumazet 9231da177e4SLinus Torvalds static void ipgre_tunnel_setup(struct net_device *dev) 9241da177e4SLinus Torvalds { 925b8c26a33SStephen Hemminger dev->netdev_ops = &ipgre_netdev_ops; 9265a455275SNicolas Dichtel dev->type = ARPHRD_IPGRE; 927c5441932SPravin B Shelar ip_tunnel_setup(dev, ipgre_net_id); 928c5441932SPravin B Shelar } 9291da177e4SLinus Torvalds 930c5441932SPravin B Shelar static void __gre_tunnel_init(struct net_device *dev) 931c5441932SPravin B Shelar { 932c5441932SPravin B Shelar struct ip_tunnel *tunnel; 9334565e991STom Herbert int t_hlen; 934c5441932SPravin B Shelar 935c5441932SPravin B Shelar tunnel = netdev_priv(dev); 93695f5c64cSTom Herbert tunnel->tun_hlen = gre_calc_hlen(tunnel->parms.o_flags); 937c5441932SPravin B Shelar tunnel->parms.iph.protocol = IPPROTO_GRE; 938c5441932SPravin B Shelar 9394565e991STom Herbert tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen; 9404565e991STom Herbert 9414565e991STom Herbert t_hlen = tunnel->hlen + sizeof(struct iphdr); 9424565e991STom Herbert 9434565e991STom Herbert dev->needed_headroom = LL_MAX_HEADER + t_hlen + 4; 9444565e991STom Herbert dev->mtu = ETH_DATA_LEN - t_hlen - 4; 9456b78f16eSEric Dumazet 946b57708adSNicolas Dichtel dev->features |= GRE_FEATURES; 9476b78f16eSEric Dumazet dev->hw_features |= GRE_FEATURES; 948c5441932SPravin B Shelar 949c5441932SPravin B Shelar if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) { 950a0ca153fSAlexander Duyck /* TCP offload with GRE SEQ is not supported, nor 951a0ca153fSAlexander Duyck * can we support 2 levels of outer headers requiring 952a0ca153fSAlexander Duyck * an update. 953a0ca153fSAlexander Duyck */ 954a0ca153fSAlexander Duyck if (!(tunnel->parms.o_flags & TUNNEL_CSUM) || 955a0ca153fSAlexander Duyck (tunnel->encap.type == TUNNEL_ENCAP_NONE)) { 956c5441932SPravin B Shelar dev->features |= NETIF_F_GSO_SOFTWARE; 957c5441932SPravin B Shelar dev->hw_features |= NETIF_F_GSO_SOFTWARE; 958a0ca153fSAlexander Duyck } 959a0ca153fSAlexander Duyck 960c5441932SPravin B Shelar /* Can use a lockless transmit, unless we generate 961c5441932SPravin B Shelar * output sequences 962c5441932SPravin B Shelar */ 963c5441932SPravin B Shelar dev->features |= NETIF_F_LLTX; 964c5441932SPravin B Shelar } 9651da177e4SLinus Torvalds } 9661da177e4SLinus Torvalds 9671da177e4SLinus Torvalds static int ipgre_tunnel_init(struct net_device *dev) 9681da177e4SLinus Torvalds { 969c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 970c5441932SPravin B Shelar struct iphdr *iph = &tunnel->parms.iph; 9711da177e4SLinus Torvalds 972c5441932SPravin B Shelar __gre_tunnel_init(dev); 9731da177e4SLinus Torvalds 974c5441932SPravin B Shelar memcpy(dev->dev_addr, &iph->saddr, 4); 975c5441932SPravin B Shelar memcpy(dev->broadcast, &iph->daddr, 4); 9761da177e4SLinus Torvalds 977c5441932SPravin B Shelar dev->flags = IFF_NOARP; 97802875878SEric Dumazet netif_keep_dst(dev); 979c5441932SPravin B Shelar dev->addr_len = 4; 9801da177e4SLinus Torvalds 981a64b04d8SJiri Benc if (iph->daddr && !tunnel->collect_md) { 9821da177e4SLinus Torvalds #ifdef CONFIG_NET_IPGRE_BROADCAST 983f97c1e0cSJoe Perches if (ipv4_is_multicast(iph->daddr)) { 9841da177e4SLinus Torvalds if (!iph->saddr) 9851da177e4SLinus Torvalds return -EINVAL; 9861da177e4SLinus Torvalds dev->flags = IFF_BROADCAST; 9873b04dddeSStephen Hemminger dev->header_ops = &ipgre_header_ops; 9881da177e4SLinus Torvalds } 9891da177e4SLinus Torvalds #endif 990a64b04d8SJiri Benc } else if (!tunnel->collect_md) { 9916a5f44d7STimo Teras dev->header_ops = &ipgre_header_ops; 992a64b04d8SJiri Benc } 9931da177e4SLinus Torvalds 994c5441932SPravin B Shelar return ip_tunnel_init(dev); 99560769a5dSEric Dumazet } 99660769a5dSEric Dumazet 9979f57c67cSPravin B Shelar static const struct gre_protocol ipgre_protocol = { 9989f57c67cSPravin B Shelar .handler = gre_rcv, 9999f57c67cSPravin B Shelar .err_handler = gre_err, 10001da177e4SLinus Torvalds }; 10011da177e4SLinus Torvalds 10022c8c1e72SAlexey Dobriyan static int __net_init ipgre_init_net(struct net *net) 100359a4c759SPavel Emelyanov { 1004c5441932SPravin B Shelar return ip_tunnel_init_net(net, ipgre_net_id, &ipgre_link_ops, NULL); 100559a4c759SPavel Emelyanov } 100659a4c759SPavel Emelyanov 100764bc1781SEric Dumazet static void __net_exit ipgre_exit_batch_net(struct list_head *list_net) 100859a4c759SPavel Emelyanov { 100964bc1781SEric Dumazet ip_tunnel_delete_nets(list_net, ipgre_net_id, &ipgre_link_ops); 101059a4c759SPavel Emelyanov } 101159a4c759SPavel Emelyanov 101259a4c759SPavel Emelyanov static struct pernet_operations ipgre_net_ops = { 101359a4c759SPavel Emelyanov .init = ipgre_init_net, 101464bc1781SEric Dumazet .exit_batch = ipgre_exit_batch_net, 1015cfb8fbf2SEric W. Biederman .id = &ipgre_net_id, 1016c5441932SPravin B Shelar .size = sizeof(struct ip_tunnel_net), 101759a4c759SPavel Emelyanov }; 10181da177e4SLinus Torvalds 1019a8b8a889SMatthias Schiffer static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[], 1020a8b8a889SMatthias Schiffer struct netlink_ext_ack *extack) 1021c19e654dSHerbert Xu { 1022c19e654dSHerbert Xu __be16 flags; 1023c19e654dSHerbert Xu 1024c19e654dSHerbert Xu if (!data) 1025c19e654dSHerbert Xu return 0; 1026c19e654dSHerbert Xu 1027c19e654dSHerbert Xu flags = 0; 1028c19e654dSHerbert Xu if (data[IFLA_GRE_IFLAGS]) 1029c19e654dSHerbert Xu flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]); 1030c19e654dSHerbert Xu if (data[IFLA_GRE_OFLAGS]) 1031c19e654dSHerbert Xu flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]); 1032c19e654dSHerbert Xu if (flags & (GRE_VERSION|GRE_ROUTING)) 1033c19e654dSHerbert Xu return -EINVAL; 1034c19e654dSHerbert Xu 1035946b636fSJiri Benc if (data[IFLA_GRE_COLLECT_METADATA] && 1036946b636fSJiri Benc data[IFLA_GRE_ENCAP_TYPE] && 1037946b636fSJiri Benc nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]) != TUNNEL_ENCAP_NONE) 1038946b636fSJiri Benc return -EINVAL; 1039946b636fSJiri Benc 1040c19e654dSHerbert Xu return 0; 1041c19e654dSHerbert Xu } 1042c19e654dSHerbert Xu 1043a8b8a889SMatthias Schiffer static int ipgre_tap_validate(struct nlattr *tb[], struct nlattr *data[], 1044a8b8a889SMatthias Schiffer struct netlink_ext_ack *extack) 1045e1a80002SHerbert Xu { 1046e1a80002SHerbert Xu __be32 daddr; 1047e1a80002SHerbert Xu 1048e1a80002SHerbert Xu if (tb[IFLA_ADDRESS]) { 1049e1a80002SHerbert Xu if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) 1050e1a80002SHerbert Xu return -EINVAL; 1051e1a80002SHerbert Xu if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) 1052e1a80002SHerbert Xu return -EADDRNOTAVAIL; 1053e1a80002SHerbert Xu } 1054e1a80002SHerbert Xu 1055e1a80002SHerbert Xu if (!data) 1056e1a80002SHerbert Xu goto out; 1057e1a80002SHerbert Xu 1058e1a80002SHerbert Xu if (data[IFLA_GRE_REMOTE]) { 1059e1a80002SHerbert Xu memcpy(&daddr, nla_data(data[IFLA_GRE_REMOTE]), 4); 1060e1a80002SHerbert Xu if (!daddr) 1061e1a80002SHerbert Xu return -EINVAL; 1062e1a80002SHerbert Xu } 1063e1a80002SHerbert Xu 1064e1a80002SHerbert Xu out: 1065a8b8a889SMatthias Schiffer return ipgre_tunnel_validate(tb, data, extack); 1066e1a80002SHerbert Xu } 1067e1a80002SHerbert Xu 106884e54fe0SWilliam Tu static int erspan_validate(struct nlattr *tb[], struct nlattr *data[], 106984e54fe0SWilliam Tu struct netlink_ext_ack *extack) 107084e54fe0SWilliam Tu { 107184e54fe0SWilliam Tu __be16 flags = 0; 107284e54fe0SWilliam Tu int ret; 107384e54fe0SWilliam Tu 107484e54fe0SWilliam Tu if (!data) 107584e54fe0SWilliam Tu return 0; 107684e54fe0SWilliam Tu 107784e54fe0SWilliam Tu ret = ipgre_tap_validate(tb, data, extack); 107884e54fe0SWilliam Tu if (ret) 107984e54fe0SWilliam Tu return ret; 108084e54fe0SWilliam Tu 108184e54fe0SWilliam Tu /* ERSPAN should only have GRE sequence and key flag */ 10821a66a836SWilliam Tu if (data[IFLA_GRE_OFLAGS]) 108384e54fe0SWilliam Tu flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]); 10841a66a836SWilliam Tu if (data[IFLA_GRE_IFLAGS]) 108584e54fe0SWilliam Tu flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]); 10861a66a836SWilliam Tu if (!data[IFLA_GRE_COLLECT_METADATA] && 10871a66a836SWilliam Tu flags != (GRE_SEQ | GRE_KEY)) 108884e54fe0SWilliam Tu return -EINVAL; 108984e54fe0SWilliam Tu 109084e54fe0SWilliam Tu /* ERSPAN Session ID only has 10-bit. Since we reuse 109184e54fe0SWilliam Tu * 32-bit key field as ID, check it's range. 109284e54fe0SWilliam Tu */ 109384e54fe0SWilliam Tu if (data[IFLA_GRE_IKEY] && 109484e54fe0SWilliam Tu (ntohl(nla_get_be32(data[IFLA_GRE_IKEY])) & ~ID_MASK)) 109584e54fe0SWilliam Tu return -EINVAL; 109684e54fe0SWilliam Tu 109784e54fe0SWilliam Tu if (data[IFLA_GRE_OKEY] && 109884e54fe0SWilliam Tu (ntohl(nla_get_be32(data[IFLA_GRE_OKEY])) & ~ID_MASK)) 109984e54fe0SWilliam Tu return -EINVAL; 110084e54fe0SWilliam Tu 110184e54fe0SWilliam Tu return 0; 110284e54fe0SWilliam Tu } 110384e54fe0SWilliam Tu 110422a59be8SPhilip Prindeville static int ipgre_netlink_parms(struct net_device *dev, 11052e15ea39SPravin B Shelar struct nlattr *data[], 11062e15ea39SPravin B Shelar struct nlattr *tb[], 11079830ad4cSCraig Gallek struct ip_tunnel_parm *parms, 11089830ad4cSCraig Gallek __u32 *fwmark) 1109c19e654dSHerbert Xu { 111022a59be8SPhilip Prindeville struct ip_tunnel *t = netdev_priv(dev); 111122a59be8SPhilip Prindeville 11127bb82d92SHerbert Xu memset(parms, 0, sizeof(*parms)); 1113c19e654dSHerbert Xu 1114c19e654dSHerbert Xu parms->iph.protocol = IPPROTO_GRE; 1115c19e654dSHerbert Xu 1116c19e654dSHerbert Xu if (!data) 111722a59be8SPhilip Prindeville return 0; 1118c19e654dSHerbert Xu 1119c19e654dSHerbert Xu if (data[IFLA_GRE_LINK]) 1120c19e654dSHerbert Xu parms->link = nla_get_u32(data[IFLA_GRE_LINK]); 1121c19e654dSHerbert Xu 1122c19e654dSHerbert Xu if (data[IFLA_GRE_IFLAGS]) 1123c5441932SPravin B Shelar parms->i_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_IFLAGS])); 1124c19e654dSHerbert Xu 1125c19e654dSHerbert Xu if (data[IFLA_GRE_OFLAGS]) 1126c5441932SPravin B Shelar parms->o_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_OFLAGS])); 1127c19e654dSHerbert Xu 1128c19e654dSHerbert Xu if (data[IFLA_GRE_IKEY]) 1129c19e654dSHerbert Xu parms->i_key = nla_get_be32(data[IFLA_GRE_IKEY]); 1130c19e654dSHerbert Xu 1131c19e654dSHerbert Xu if (data[IFLA_GRE_OKEY]) 1132c19e654dSHerbert Xu parms->o_key = nla_get_be32(data[IFLA_GRE_OKEY]); 1133c19e654dSHerbert Xu 1134c19e654dSHerbert Xu if (data[IFLA_GRE_LOCAL]) 113567b61f6cSJiri Benc parms->iph.saddr = nla_get_in_addr(data[IFLA_GRE_LOCAL]); 1136c19e654dSHerbert Xu 1137c19e654dSHerbert Xu if (data[IFLA_GRE_REMOTE]) 113867b61f6cSJiri Benc parms->iph.daddr = nla_get_in_addr(data[IFLA_GRE_REMOTE]); 1139c19e654dSHerbert Xu 1140c19e654dSHerbert Xu if (data[IFLA_GRE_TTL]) 1141c19e654dSHerbert Xu parms->iph.ttl = nla_get_u8(data[IFLA_GRE_TTL]); 1142c19e654dSHerbert Xu 1143c19e654dSHerbert Xu if (data[IFLA_GRE_TOS]) 1144c19e654dSHerbert Xu parms->iph.tos = nla_get_u8(data[IFLA_GRE_TOS]); 1145c19e654dSHerbert Xu 114622a59be8SPhilip Prindeville if (!data[IFLA_GRE_PMTUDISC] || nla_get_u8(data[IFLA_GRE_PMTUDISC])) { 114722a59be8SPhilip Prindeville if (t->ignore_df) 114822a59be8SPhilip Prindeville return -EINVAL; 1149c19e654dSHerbert Xu parms->iph.frag_off = htons(IP_DF); 115022a59be8SPhilip Prindeville } 11512e15ea39SPravin B Shelar 11522e15ea39SPravin B Shelar if (data[IFLA_GRE_COLLECT_METADATA]) { 11532e15ea39SPravin B Shelar t->collect_md = true; 1154e271c7b4SJiri Benc if (dev->type == ARPHRD_IPGRE) 1155e271c7b4SJiri Benc dev->type = ARPHRD_NONE; 11562e15ea39SPravin B Shelar } 115722a59be8SPhilip Prindeville 115822a59be8SPhilip Prindeville if (data[IFLA_GRE_IGNORE_DF]) { 115922a59be8SPhilip Prindeville if (nla_get_u8(data[IFLA_GRE_IGNORE_DF]) 116022a59be8SPhilip Prindeville && (parms->iph.frag_off & htons(IP_DF))) 116122a59be8SPhilip Prindeville return -EINVAL; 116222a59be8SPhilip Prindeville t->ignore_df = !!nla_get_u8(data[IFLA_GRE_IGNORE_DF]); 116322a59be8SPhilip Prindeville } 116422a59be8SPhilip Prindeville 11659830ad4cSCraig Gallek if (data[IFLA_GRE_FWMARK]) 11669830ad4cSCraig Gallek *fwmark = nla_get_u32(data[IFLA_GRE_FWMARK]); 11679830ad4cSCraig Gallek 116884e54fe0SWilliam Tu if (data[IFLA_GRE_ERSPAN_INDEX]) { 116984e54fe0SWilliam Tu t->index = nla_get_u32(data[IFLA_GRE_ERSPAN_INDEX]); 117084e54fe0SWilliam Tu 117184e54fe0SWilliam Tu if (t->index & ~INDEX_MASK) 117284e54fe0SWilliam Tu return -EINVAL; 117384e54fe0SWilliam Tu } 117484e54fe0SWilliam Tu 117522a59be8SPhilip Prindeville return 0; 1176c19e654dSHerbert Xu } 1177c19e654dSHerbert Xu 11784565e991STom Herbert /* This function returns true when ENCAP attributes are present in the nl msg */ 11794565e991STom Herbert static bool ipgre_netlink_encap_parms(struct nlattr *data[], 11804565e991STom Herbert struct ip_tunnel_encap *ipencap) 11814565e991STom Herbert { 11824565e991STom Herbert bool ret = false; 11834565e991STom Herbert 11844565e991STom Herbert memset(ipencap, 0, sizeof(*ipencap)); 11854565e991STom Herbert 11864565e991STom Herbert if (!data) 11874565e991STom Herbert return ret; 11884565e991STom Herbert 11894565e991STom Herbert if (data[IFLA_GRE_ENCAP_TYPE]) { 11904565e991STom Herbert ret = true; 11914565e991STom Herbert ipencap->type = nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]); 11924565e991STom Herbert } 11934565e991STom Herbert 11944565e991STom Herbert if (data[IFLA_GRE_ENCAP_FLAGS]) { 11954565e991STom Herbert ret = true; 11964565e991STom Herbert ipencap->flags = nla_get_u16(data[IFLA_GRE_ENCAP_FLAGS]); 11974565e991STom Herbert } 11984565e991STom Herbert 11994565e991STom Herbert if (data[IFLA_GRE_ENCAP_SPORT]) { 12004565e991STom Herbert ret = true; 12013e97fa70SSabrina Dubroca ipencap->sport = nla_get_be16(data[IFLA_GRE_ENCAP_SPORT]); 12024565e991STom Herbert } 12034565e991STom Herbert 12044565e991STom Herbert if (data[IFLA_GRE_ENCAP_DPORT]) { 12054565e991STom Herbert ret = true; 12063e97fa70SSabrina Dubroca ipencap->dport = nla_get_be16(data[IFLA_GRE_ENCAP_DPORT]); 12074565e991STom Herbert } 12084565e991STom Herbert 12094565e991STom Herbert return ret; 12104565e991STom Herbert } 12114565e991STom Herbert 1212c5441932SPravin B Shelar static int gre_tap_init(struct net_device *dev) 1213e1a80002SHerbert Xu { 1214c5441932SPravin B Shelar __gre_tunnel_init(dev); 1215bec94d43Sstephen hemminger dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; 1216d51711c0SXin Long netif_keep_dst(dev); 1217e1a80002SHerbert Xu 1218c5441932SPravin B Shelar return ip_tunnel_init(dev); 1219e1a80002SHerbert Xu } 1220e1a80002SHerbert Xu 1221c5441932SPravin B Shelar static const struct net_device_ops gre_tap_netdev_ops = { 1222c5441932SPravin B Shelar .ndo_init = gre_tap_init, 1223c5441932SPravin B Shelar .ndo_uninit = ip_tunnel_uninit, 1224c5441932SPravin B Shelar .ndo_start_xmit = gre_tap_xmit, 1225b8c26a33SStephen Hemminger .ndo_set_mac_address = eth_mac_addr, 1226b8c26a33SStephen Hemminger .ndo_validate_addr = eth_validate_addr, 1227c5441932SPravin B Shelar .ndo_change_mtu = ip_tunnel_change_mtu, 1228c5441932SPravin B Shelar .ndo_get_stats64 = ip_tunnel_get_stats64, 12291e99584bSNicolas Dichtel .ndo_get_iflink = ip_tunnel_get_iflink, 1230fc4099f1SPravin B Shelar .ndo_fill_metadata_dst = gre_fill_metadata_dst, 1231b8c26a33SStephen Hemminger }; 1232b8c26a33SStephen Hemminger 123384e54fe0SWilliam Tu static int erspan_tunnel_init(struct net_device *dev) 123484e54fe0SWilliam Tu { 123584e54fe0SWilliam Tu struct ip_tunnel *tunnel = netdev_priv(dev); 123684e54fe0SWilliam Tu int t_hlen; 123784e54fe0SWilliam Tu 123884e54fe0SWilliam Tu tunnel->tun_hlen = 8; 123984e54fe0SWilliam Tu tunnel->parms.iph.protocol = IPPROTO_GRE; 1240c122fda2SXin Long tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen + 1241c122fda2SXin Long sizeof(struct erspanhdr); 1242c122fda2SXin Long t_hlen = tunnel->hlen + sizeof(struct iphdr); 124384e54fe0SWilliam Tu 124484e54fe0SWilliam Tu dev->needed_headroom = LL_MAX_HEADER + t_hlen + 4; 124584e54fe0SWilliam Tu dev->mtu = ETH_DATA_LEN - t_hlen - 4; 124684e54fe0SWilliam Tu dev->features |= GRE_FEATURES; 124784e54fe0SWilliam Tu dev->hw_features |= GRE_FEATURES; 124884e54fe0SWilliam Tu dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; 1249c84bed44SXin Long netif_keep_dst(dev); 125084e54fe0SWilliam Tu 125184e54fe0SWilliam Tu return ip_tunnel_init(dev); 125284e54fe0SWilliam Tu } 125384e54fe0SWilliam Tu 125484e54fe0SWilliam Tu static const struct net_device_ops erspan_netdev_ops = { 125584e54fe0SWilliam Tu .ndo_init = erspan_tunnel_init, 125684e54fe0SWilliam Tu .ndo_uninit = ip_tunnel_uninit, 125784e54fe0SWilliam Tu .ndo_start_xmit = erspan_xmit, 125884e54fe0SWilliam Tu .ndo_set_mac_address = eth_mac_addr, 125984e54fe0SWilliam Tu .ndo_validate_addr = eth_validate_addr, 126084e54fe0SWilliam Tu .ndo_change_mtu = ip_tunnel_change_mtu, 126184e54fe0SWilliam Tu .ndo_get_stats64 = ip_tunnel_get_stats64, 126284e54fe0SWilliam Tu .ndo_get_iflink = ip_tunnel_get_iflink, 126384e54fe0SWilliam Tu .ndo_fill_metadata_dst = gre_fill_metadata_dst, 126484e54fe0SWilliam Tu }; 126584e54fe0SWilliam Tu 1266e1a80002SHerbert Xu static void ipgre_tap_setup(struct net_device *dev) 1267e1a80002SHerbert Xu { 1268e1a80002SHerbert Xu ether_setup(dev); 1269c5441932SPravin B Shelar dev->netdev_ops = &gre_tap_netdev_ops; 1270d13b161cSJiri Benc dev->priv_flags &= ~IFF_TX_SKB_SHARING; 1271f8c1b7ceSstephen hemminger dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; 1272c5441932SPravin B Shelar ip_tunnel_setup(dev, gre_tap_net_id); 1273e1a80002SHerbert Xu } 1274e1a80002SHerbert Xu 1275c5441932SPravin B Shelar static int ipgre_newlink(struct net *src_net, struct net_device *dev, 12767a3f4a18SMatthias Schiffer struct nlattr *tb[], struct nlattr *data[], 12777a3f4a18SMatthias Schiffer struct netlink_ext_ack *extack) 1278c19e654dSHerbert Xu { 1279c5441932SPravin B Shelar struct ip_tunnel_parm p; 12804565e991STom Herbert struct ip_tunnel_encap ipencap; 12819830ad4cSCraig Gallek __u32 fwmark = 0; 128222a59be8SPhilip Prindeville int err; 12834565e991STom Herbert 12844565e991STom Herbert if (ipgre_netlink_encap_parms(data, &ipencap)) { 12854565e991STom Herbert struct ip_tunnel *t = netdev_priv(dev); 128622a59be8SPhilip Prindeville err = ip_tunnel_encap_setup(t, &ipencap); 12874565e991STom Herbert 12884565e991STom Herbert if (err < 0) 12894565e991STom Herbert return err; 12904565e991STom Herbert } 1291c19e654dSHerbert Xu 12929830ad4cSCraig Gallek err = ipgre_netlink_parms(dev, data, tb, &p, &fwmark); 129322a59be8SPhilip Prindeville if (err < 0) 129422a59be8SPhilip Prindeville return err; 12959830ad4cSCraig Gallek return ip_tunnel_newlink(dev, tb, &p, fwmark); 1296c19e654dSHerbert Xu } 1297c19e654dSHerbert Xu 1298c19e654dSHerbert Xu static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[], 1299ad744b22SMatthias Schiffer struct nlattr *data[], 1300ad744b22SMatthias Schiffer struct netlink_ext_ack *extack) 1301c19e654dSHerbert Xu { 13029830ad4cSCraig Gallek struct ip_tunnel *t = netdev_priv(dev); 13034565e991STom Herbert struct ip_tunnel_encap ipencap; 13049830ad4cSCraig Gallek __u32 fwmark = t->fwmark; 1305dd9d598cSXin Long struct ip_tunnel_parm p; 130622a59be8SPhilip Prindeville int err; 13074565e991STom Herbert 13084565e991STom Herbert if (ipgre_netlink_encap_parms(data, &ipencap)) { 130922a59be8SPhilip Prindeville err = ip_tunnel_encap_setup(t, &ipencap); 13104565e991STom Herbert 13114565e991STom Herbert if (err < 0) 13124565e991STom Herbert return err; 13134565e991STom Herbert } 1314c19e654dSHerbert Xu 13159830ad4cSCraig Gallek err = ipgre_netlink_parms(dev, data, tb, &p, &fwmark); 131622a59be8SPhilip Prindeville if (err < 0) 131722a59be8SPhilip Prindeville return err; 1318dd9d598cSXin Long 1319dd9d598cSXin Long err = ip_tunnel_changelink(dev, tb, &p, fwmark); 1320dd9d598cSXin Long if (err < 0) 1321dd9d598cSXin Long return err; 1322dd9d598cSXin Long 1323dd9d598cSXin Long t->parms.i_flags = p.i_flags; 1324dd9d598cSXin Long t->parms.o_flags = p.o_flags; 1325dd9d598cSXin Long 1326dd9d598cSXin Long if (strcmp(dev->rtnl_link_ops->kind, "erspan")) 1327dd9d598cSXin Long ipgre_link_update(dev, !tb[IFLA_MTU]); 1328dd9d598cSXin Long 1329dd9d598cSXin Long return 0; 1330c19e654dSHerbert Xu } 1331c19e654dSHerbert Xu 1332c19e654dSHerbert Xu static size_t ipgre_get_size(const struct net_device *dev) 1333c19e654dSHerbert Xu { 1334c19e654dSHerbert Xu return 1335c19e654dSHerbert Xu /* IFLA_GRE_LINK */ 1336c19e654dSHerbert Xu nla_total_size(4) + 1337c19e654dSHerbert Xu /* IFLA_GRE_IFLAGS */ 1338c19e654dSHerbert Xu nla_total_size(2) + 1339c19e654dSHerbert Xu /* IFLA_GRE_OFLAGS */ 1340c19e654dSHerbert Xu nla_total_size(2) + 1341c19e654dSHerbert Xu /* IFLA_GRE_IKEY */ 1342c19e654dSHerbert Xu nla_total_size(4) + 1343c19e654dSHerbert Xu /* IFLA_GRE_OKEY */ 1344c19e654dSHerbert Xu nla_total_size(4) + 1345c19e654dSHerbert Xu /* IFLA_GRE_LOCAL */ 1346c19e654dSHerbert Xu nla_total_size(4) + 1347c19e654dSHerbert Xu /* IFLA_GRE_REMOTE */ 1348c19e654dSHerbert Xu nla_total_size(4) + 1349c19e654dSHerbert Xu /* IFLA_GRE_TTL */ 1350c19e654dSHerbert Xu nla_total_size(1) + 1351c19e654dSHerbert Xu /* IFLA_GRE_TOS */ 1352c19e654dSHerbert Xu nla_total_size(1) + 1353c19e654dSHerbert Xu /* IFLA_GRE_PMTUDISC */ 1354c19e654dSHerbert Xu nla_total_size(1) + 13554565e991STom Herbert /* IFLA_GRE_ENCAP_TYPE */ 13564565e991STom Herbert nla_total_size(2) + 13574565e991STom Herbert /* IFLA_GRE_ENCAP_FLAGS */ 13584565e991STom Herbert nla_total_size(2) + 13594565e991STom Herbert /* IFLA_GRE_ENCAP_SPORT */ 13604565e991STom Herbert nla_total_size(2) + 13614565e991STom Herbert /* IFLA_GRE_ENCAP_DPORT */ 13624565e991STom Herbert nla_total_size(2) + 13632e15ea39SPravin B Shelar /* IFLA_GRE_COLLECT_METADATA */ 13642e15ea39SPravin B Shelar nla_total_size(0) + 136522a59be8SPhilip Prindeville /* IFLA_GRE_IGNORE_DF */ 136622a59be8SPhilip Prindeville nla_total_size(1) + 13679830ad4cSCraig Gallek /* IFLA_GRE_FWMARK */ 13689830ad4cSCraig Gallek nla_total_size(4) + 136984e54fe0SWilliam Tu /* IFLA_GRE_ERSPAN_INDEX */ 137084e54fe0SWilliam Tu nla_total_size(4) + 1371c19e654dSHerbert Xu 0; 1372c19e654dSHerbert Xu } 1373c19e654dSHerbert Xu 1374c19e654dSHerbert Xu static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev) 1375c19e654dSHerbert Xu { 1376c19e654dSHerbert Xu struct ip_tunnel *t = netdev_priv(dev); 1377c19e654dSHerbert Xu struct ip_tunnel_parm *p = &t->parms; 1378c19e654dSHerbert Xu 1379f3756b79SDavid S. Miller if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) || 138095f5c64cSTom Herbert nla_put_be16(skb, IFLA_GRE_IFLAGS, 138195f5c64cSTom Herbert gre_tnl_flags_to_gre_flags(p->i_flags)) || 138295f5c64cSTom Herbert nla_put_be16(skb, IFLA_GRE_OFLAGS, 138395f5c64cSTom Herbert gre_tnl_flags_to_gre_flags(p->o_flags)) || 1384f3756b79SDavid S. Miller nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) || 1385f3756b79SDavid S. Miller nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) || 1386930345eaSJiri Benc nla_put_in_addr(skb, IFLA_GRE_LOCAL, p->iph.saddr) || 1387930345eaSJiri Benc nla_put_in_addr(skb, IFLA_GRE_REMOTE, p->iph.daddr) || 1388f3756b79SDavid S. Miller nla_put_u8(skb, IFLA_GRE_TTL, p->iph.ttl) || 1389f3756b79SDavid S. Miller nla_put_u8(skb, IFLA_GRE_TOS, p->iph.tos) || 1390f3756b79SDavid S. Miller nla_put_u8(skb, IFLA_GRE_PMTUDISC, 13919830ad4cSCraig Gallek !!(p->iph.frag_off & htons(IP_DF))) || 13929830ad4cSCraig Gallek nla_put_u32(skb, IFLA_GRE_FWMARK, t->fwmark)) 1393f3756b79SDavid S. Miller goto nla_put_failure; 13944565e991STom Herbert 13954565e991STom Herbert if (nla_put_u16(skb, IFLA_GRE_ENCAP_TYPE, 13964565e991STom Herbert t->encap.type) || 13973e97fa70SSabrina Dubroca nla_put_be16(skb, IFLA_GRE_ENCAP_SPORT, 13984565e991STom Herbert t->encap.sport) || 13993e97fa70SSabrina Dubroca nla_put_be16(skb, IFLA_GRE_ENCAP_DPORT, 14004565e991STom Herbert t->encap.dport) || 14014565e991STom Herbert nla_put_u16(skb, IFLA_GRE_ENCAP_FLAGS, 1402e1b2cb65STom Herbert t->encap.flags)) 14034565e991STom Herbert goto nla_put_failure; 14044565e991STom Herbert 140522a59be8SPhilip Prindeville if (nla_put_u8(skb, IFLA_GRE_IGNORE_DF, t->ignore_df)) 140622a59be8SPhilip Prindeville goto nla_put_failure; 140722a59be8SPhilip Prindeville 14082e15ea39SPravin B Shelar if (t->collect_md) { 14092e15ea39SPravin B Shelar if (nla_put_flag(skb, IFLA_GRE_COLLECT_METADATA)) 14102e15ea39SPravin B Shelar goto nla_put_failure; 14112e15ea39SPravin B Shelar } 14122e15ea39SPravin B Shelar 141384e54fe0SWilliam Tu if (t->index) 141484e54fe0SWilliam Tu if (nla_put_u32(skb, IFLA_GRE_ERSPAN_INDEX, t->index)) 141584e54fe0SWilliam Tu goto nla_put_failure; 141684e54fe0SWilliam Tu 1417c19e654dSHerbert Xu return 0; 1418c19e654dSHerbert Xu 1419c19e654dSHerbert Xu nla_put_failure: 1420c19e654dSHerbert Xu return -EMSGSIZE; 1421c19e654dSHerbert Xu } 1422c19e654dSHerbert Xu 142384e54fe0SWilliam Tu static void erspan_setup(struct net_device *dev) 142484e54fe0SWilliam Tu { 142584e54fe0SWilliam Tu ether_setup(dev); 142684e54fe0SWilliam Tu dev->netdev_ops = &erspan_netdev_ops; 142784e54fe0SWilliam Tu dev->priv_flags &= ~IFF_TX_SKB_SHARING; 142884e54fe0SWilliam Tu dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; 142984e54fe0SWilliam Tu ip_tunnel_setup(dev, erspan_net_id); 143084e54fe0SWilliam Tu } 143184e54fe0SWilliam Tu 1432c19e654dSHerbert Xu static const struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = { 1433c19e654dSHerbert Xu [IFLA_GRE_LINK] = { .type = NLA_U32 }, 1434c19e654dSHerbert Xu [IFLA_GRE_IFLAGS] = { .type = NLA_U16 }, 1435c19e654dSHerbert Xu [IFLA_GRE_OFLAGS] = { .type = NLA_U16 }, 1436c19e654dSHerbert Xu [IFLA_GRE_IKEY] = { .type = NLA_U32 }, 1437c19e654dSHerbert Xu [IFLA_GRE_OKEY] = { .type = NLA_U32 }, 14384d74f8baSPatrick McHardy [IFLA_GRE_LOCAL] = { .len = FIELD_SIZEOF(struct iphdr, saddr) }, 14394d74f8baSPatrick McHardy [IFLA_GRE_REMOTE] = { .len = FIELD_SIZEOF(struct iphdr, daddr) }, 1440c19e654dSHerbert Xu [IFLA_GRE_TTL] = { .type = NLA_U8 }, 1441c19e654dSHerbert Xu [IFLA_GRE_TOS] = { .type = NLA_U8 }, 1442c19e654dSHerbert Xu [IFLA_GRE_PMTUDISC] = { .type = NLA_U8 }, 14434565e991STom Herbert [IFLA_GRE_ENCAP_TYPE] = { .type = NLA_U16 }, 14444565e991STom Herbert [IFLA_GRE_ENCAP_FLAGS] = { .type = NLA_U16 }, 14454565e991STom Herbert [IFLA_GRE_ENCAP_SPORT] = { .type = NLA_U16 }, 14464565e991STom Herbert [IFLA_GRE_ENCAP_DPORT] = { .type = NLA_U16 }, 14472e15ea39SPravin B Shelar [IFLA_GRE_COLLECT_METADATA] = { .type = NLA_FLAG }, 144822a59be8SPhilip Prindeville [IFLA_GRE_IGNORE_DF] = { .type = NLA_U8 }, 14499830ad4cSCraig Gallek [IFLA_GRE_FWMARK] = { .type = NLA_U32 }, 145084e54fe0SWilliam Tu [IFLA_GRE_ERSPAN_INDEX] = { .type = NLA_U32 }, 1451c19e654dSHerbert Xu }; 1452c19e654dSHerbert Xu 1453c19e654dSHerbert Xu static struct rtnl_link_ops ipgre_link_ops __read_mostly = { 1454c19e654dSHerbert Xu .kind = "gre", 1455c19e654dSHerbert Xu .maxtype = IFLA_GRE_MAX, 1456c19e654dSHerbert Xu .policy = ipgre_policy, 1457c19e654dSHerbert Xu .priv_size = sizeof(struct ip_tunnel), 1458c19e654dSHerbert Xu .setup = ipgre_tunnel_setup, 1459c19e654dSHerbert Xu .validate = ipgre_tunnel_validate, 1460c19e654dSHerbert Xu .newlink = ipgre_newlink, 1461c19e654dSHerbert Xu .changelink = ipgre_changelink, 1462c5441932SPravin B Shelar .dellink = ip_tunnel_dellink, 1463c19e654dSHerbert Xu .get_size = ipgre_get_size, 1464c19e654dSHerbert Xu .fill_info = ipgre_fill_info, 14651728d4faSNicolas Dichtel .get_link_net = ip_tunnel_get_link_net, 1466c19e654dSHerbert Xu }; 1467c19e654dSHerbert Xu 1468e1a80002SHerbert Xu static struct rtnl_link_ops ipgre_tap_ops __read_mostly = { 1469e1a80002SHerbert Xu .kind = "gretap", 1470e1a80002SHerbert Xu .maxtype = IFLA_GRE_MAX, 1471e1a80002SHerbert Xu .policy = ipgre_policy, 1472e1a80002SHerbert Xu .priv_size = sizeof(struct ip_tunnel), 1473e1a80002SHerbert Xu .setup = ipgre_tap_setup, 1474e1a80002SHerbert Xu .validate = ipgre_tap_validate, 1475e1a80002SHerbert Xu .newlink = ipgre_newlink, 1476e1a80002SHerbert Xu .changelink = ipgre_changelink, 1477c5441932SPravin B Shelar .dellink = ip_tunnel_dellink, 1478e1a80002SHerbert Xu .get_size = ipgre_get_size, 1479e1a80002SHerbert Xu .fill_info = ipgre_fill_info, 14801728d4faSNicolas Dichtel .get_link_net = ip_tunnel_get_link_net, 1481e1a80002SHerbert Xu }; 1482e1a80002SHerbert Xu 148384e54fe0SWilliam Tu static struct rtnl_link_ops erspan_link_ops __read_mostly = { 148484e54fe0SWilliam Tu .kind = "erspan", 148584e54fe0SWilliam Tu .maxtype = IFLA_GRE_MAX, 148684e54fe0SWilliam Tu .policy = ipgre_policy, 148784e54fe0SWilliam Tu .priv_size = sizeof(struct ip_tunnel), 148884e54fe0SWilliam Tu .setup = erspan_setup, 148984e54fe0SWilliam Tu .validate = erspan_validate, 149084e54fe0SWilliam Tu .newlink = ipgre_newlink, 149184e54fe0SWilliam Tu .changelink = ipgre_changelink, 149284e54fe0SWilliam Tu .dellink = ip_tunnel_dellink, 149384e54fe0SWilliam Tu .get_size = ipgre_get_size, 149484e54fe0SWilliam Tu .fill_info = ipgre_fill_info, 149584e54fe0SWilliam Tu .get_link_net = ip_tunnel_get_link_net, 149684e54fe0SWilliam Tu }; 149784e54fe0SWilliam Tu 1498b2acd1dcSPravin B Shelar struct net_device *gretap_fb_dev_create(struct net *net, const char *name, 1499b2acd1dcSPravin B Shelar u8 name_assign_type) 1500b2acd1dcSPravin B Shelar { 1501b2acd1dcSPravin B Shelar struct nlattr *tb[IFLA_MAX + 1]; 1502b2acd1dcSPravin B Shelar struct net_device *dev; 1503106da663SNicolas Dichtel LIST_HEAD(list_kill); 1504b2acd1dcSPravin B Shelar struct ip_tunnel *t; 1505b2acd1dcSPravin B Shelar int err; 1506b2acd1dcSPravin B Shelar 1507b2acd1dcSPravin B Shelar memset(&tb, 0, sizeof(tb)); 1508b2acd1dcSPravin B Shelar 1509b2acd1dcSPravin B Shelar dev = rtnl_create_link(net, name, name_assign_type, 1510b2acd1dcSPravin B Shelar &ipgre_tap_ops, tb); 1511b2acd1dcSPravin B Shelar if (IS_ERR(dev)) 1512b2acd1dcSPravin B Shelar return dev; 1513b2acd1dcSPravin B Shelar 1514b2acd1dcSPravin B Shelar /* Configure flow based GRE device. */ 1515b2acd1dcSPravin B Shelar t = netdev_priv(dev); 1516b2acd1dcSPravin B Shelar t->collect_md = true; 1517b2acd1dcSPravin B Shelar 15187a3f4a18SMatthias Schiffer err = ipgre_newlink(net, dev, tb, NULL, NULL); 1519106da663SNicolas Dichtel if (err < 0) { 1520106da663SNicolas Dichtel free_netdev(dev); 1521106da663SNicolas Dichtel return ERR_PTR(err); 1522106da663SNicolas Dichtel } 15237e059158SDavid Wragg 15247e059158SDavid Wragg /* openvswitch users expect packet sizes to be unrestricted, 15257e059158SDavid Wragg * so set the largest MTU we can. 15267e059158SDavid Wragg */ 15277e059158SDavid Wragg err = __ip_tunnel_change_mtu(dev, IP_MAX_MTU, false); 15287e059158SDavid Wragg if (err) 15297e059158SDavid Wragg goto out; 15307e059158SDavid Wragg 1531da6f1da8SNicolas Dichtel err = rtnl_configure_link(dev, NULL); 1532da6f1da8SNicolas Dichtel if (err < 0) 1533da6f1da8SNicolas Dichtel goto out; 1534da6f1da8SNicolas Dichtel 1535b2acd1dcSPravin B Shelar return dev; 1536b2acd1dcSPravin B Shelar out: 1537106da663SNicolas Dichtel ip_tunnel_dellink(dev, &list_kill); 1538106da663SNicolas Dichtel unregister_netdevice_many(&list_kill); 1539b2acd1dcSPravin B Shelar return ERR_PTR(err); 1540b2acd1dcSPravin B Shelar } 1541b2acd1dcSPravin B Shelar EXPORT_SYMBOL_GPL(gretap_fb_dev_create); 1542b2acd1dcSPravin B Shelar 1543c5441932SPravin B Shelar static int __net_init ipgre_tap_init_net(struct net *net) 1544c5441932SPravin B Shelar { 15452e15ea39SPravin B Shelar return ip_tunnel_init_net(net, gre_tap_net_id, &ipgre_tap_ops, "gretap0"); 1546c5441932SPravin B Shelar } 1547c5441932SPravin B Shelar 154864bc1781SEric Dumazet static void __net_exit ipgre_tap_exit_batch_net(struct list_head *list_net) 1549c5441932SPravin B Shelar { 155064bc1781SEric Dumazet ip_tunnel_delete_nets(list_net, gre_tap_net_id, &ipgre_tap_ops); 1551c5441932SPravin B Shelar } 1552c5441932SPravin B Shelar 1553c5441932SPravin B Shelar static struct pernet_operations ipgre_tap_net_ops = { 1554c5441932SPravin B Shelar .init = ipgre_tap_init_net, 155564bc1781SEric Dumazet .exit_batch = ipgre_tap_exit_batch_net, 1556c5441932SPravin B Shelar .id = &gre_tap_net_id, 1557c5441932SPravin B Shelar .size = sizeof(struct ip_tunnel_net), 1558c5441932SPravin B Shelar }; 15591da177e4SLinus Torvalds 156084e54fe0SWilliam Tu static int __net_init erspan_init_net(struct net *net) 156184e54fe0SWilliam Tu { 156284e54fe0SWilliam Tu return ip_tunnel_init_net(net, erspan_net_id, 156384e54fe0SWilliam Tu &erspan_link_ops, "erspan0"); 156484e54fe0SWilliam Tu } 156584e54fe0SWilliam Tu 156664bc1781SEric Dumazet static void __net_exit erspan_exit_batch_net(struct list_head *net_list) 156784e54fe0SWilliam Tu { 156864bc1781SEric Dumazet ip_tunnel_delete_nets(net_list, erspan_net_id, &erspan_link_ops); 156984e54fe0SWilliam Tu } 157084e54fe0SWilliam Tu 157184e54fe0SWilliam Tu static struct pernet_operations erspan_net_ops = { 157284e54fe0SWilliam Tu .init = erspan_init_net, 157364bc1781SEric Dumazet .exit_batch = erspan_exit_batch_net, 157484e54fe0SWilliam Tu .id = &erspan_net_id, 157584e54fe0SWilliam Tu .size = sizeof(struct ip_tunnel_net), 157684e54fe0SWilliam Tu }; 157784e54fe0SWilliam Tu 15781da177e4SLinus Torvalds static int __init ipgre_init(void) 15791da177e4SLinus Torvalds { 15801da177e4SLinus Torvalds int err; 15811da177e4SLinus Torvalds 1582058bd4d2SJoe Perches pr_info("GRE over IPv4 tunneling driver\n"); 15831da177e4SLinus Torvalds 1584cfb8fbf2SEric W. Biederman err = register_pernet_device(&ipgre_net_ops); 158559a4c759SPavel Emelyanov if (err < 0) 1586c2892f02SAlexey Dobriyan return err; 1587c2892f02SAlexey Dobriyan 1588c5441932SPravin B Shelar err = register_pernet_device(&ipgre_tap_net_ops); 1589c5441932SPravin B Shelar if (err < 0) 1590e3d0328cSWilliam Tu goto pnet_tap_failed; 1591c5441932SPravin B Shelar 159284e54fe0SWilliam Tu err = register_pernet_device(&erspan_net_ops); 159384e54fe0SWilliam Tu if (err < 0) 159484e54fe0SWilliam Tu goto pnet_erspan_failed; 159584e54fe0SWilliam Tu 15969f57c67cSPravin B Shelar err = gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO); 1597c2892f02SAlexey Dobriyan if (err < 0) { 1598058bd4d2SJoe Perches pr_info("%s: can't add protocol\n", __func__); 1599c2892f02SAlexey Dobriyan goto add_proto_failed; 1600c2892f02SAlexey Dobriyan } 16017daa0004SPavel Emelyanov 1602c19e654dSHerbert Xu err = rtnl_link_register(&ipgre_link_ops); 1603c19e654dSHerbert Xu if (err < 0) 1604c19e654dSHerbert Xu goto rtnl_link_failed; 1605c19e654dSHerbert Xu 1606e1a80002SHerbert Xu err = rtnl_link_register(&ipgre_tap_ops); 1607e1a80002SHerbert Xu if (err < 0) 1608e1a80002SHerbert Xu goto tap_ops_failed; 1609e1a80002SHerbert Xu 161084e54fe0SWilliam Tu err = rtnl_link_register(&erspan_link_ops); 161184e54fe0SWilliam Tu if (err < 0) 161284e54fe0SWilliam Tu goto erspan_link_failed; 161384e54fe0SWilliam Tu 1614c5441932SPravin B Shelar return 0; 1615c19e654dSHerbert Xu 161684e54fe0SWilliam Tu erspan_link_failed: 161784e54fe0SWilliam Tu rtnl_link_unregister(&ipgre_tap_ops); 1618e1a80002SHerbert Xu tap_ops_failed: 1619e1a80002SHerbert Xu rtnl_link_unregister(&ipgre_link_ops); 1620c19e654dSHerbert Xu rtnl_link_failed: 16219f57c67cSPravin B Shelar gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO); 1622c2892f02SAlexey Dobriyan add_proto_failed: 162384e54fe0SWilliam Tu unregister_pernet_device(&erspan_net_ops); 162484e54fe0SWilliam Tu pnet_erspan_failed: 1625c5441932SPravin B Shelar unregister_pernet_device(&ipgre_tap_net_ops); 1626e3d0328cSWilliam Tu pnet_tap_failed: 1627c2892f02SAlexey Dobriyan unregister_pernet_device(&ipgre_net_ops); 1628c5441932SPravin B Shelar return err; 16291da177e4SLinus Torvalds } 16301da177e4SLinus Torvalds 1631db44575fSAlexey Kuznetsov static void __exit ipgre_fini(void) 16321da177e4SLinus Torvalds { 1633e1a80002SHerbert Xu rtnl_link_unregister(&ipgre_tap_ops); 1634c19e654dSHerbert Xu rtnl_link_unregister(&ipgre_link_ops); 163584e54fe0SWilliam Tu rtnl_link_unregister(&erspan_link_ops); 16369f57c67cSPravin B Shelar gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO); 1637c5441932SPravin B Shelar unregister_pernet_device(&ipgre_tap_net_ops); 1638c2892f02SAlexey Dobriyan unregister_pernet_device(&ipgre_net_ops); 163984e54fe0SWilliam Tu unregister_pernet_device(&erspan_net_ops); 16401da177e4SLinus Torvalds } 16411da177e4SLinus Torvalds 16421da177e4SLinus Torvalds module_init(ipgre_init); 16431da177e4SLinus Torvalds module_exit(ipgre_fini); 16441da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 16454d74f8baSPatrick McHardy MODULE_ALIAS_RTNL_LINK("gre"); 16464d74f8baSPatrick McHardy MODULE_ALIAS_RTNL_LINK("gretap"); 164784e54fe0SWilliam Tu MODULE_ALIAS_RTNL_LINK("erspan"); 16488909c9adSVasiliy Kulikov MODULE_ALIAS_NETDEV("gre0"); 1649c5441932SPravin B Shelar MODULE_ALIAS_NETDEV("gretap0"); 165084e54fe0SWilliam Tu MODULE_ALIAS_NETDEV("erspan0"); 1651