11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Linux NET3: GRE over IP protocol decoder. 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Authors: Alexey Kuznetsov (kuznet@ms2.inr.ac.ru) 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or 71da177e4SLinus Torvalds * modify it under the terms of the GNU General Public License 81da177e4SLinus Torvalds * as published by the Free Software Foundation; either version 91da177e4SLinus Torvalds * 2 of the License, or (at your option) any later version. 101da177e4SLinus Torvalds * 111da177e4SLinus Torvalds */ 121da177e4SLinus Torvalds 13afd46503SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 14afd46503SJoe Perches 154fc268d2SRandy Dunlap #include <linux/capability.h> 161da177e4SLinus Torvalds #include <linux/module.h> 171da177e4SLinus Torvalds #include <linux/types.h> 181da177e4SLinus Torvalds #include <linux/kernel.h> 195a0e3ad6STejun Heo #include <linux/slab.h> 207c0f6ba6SLinus Torvalds #include <linux/uaccess.h> 211da177e4SLinus Torvalds #include <linux/skbuff.h> 221da177e4SLinus Torvalds #include <linux/netdevice.h> 231da177e4SLinus Torvalds #include <linux/in.h> 241da177e4SLinus Torvalds #include <linux/tcp.h> 251da177e4SLinus Torvalds #include <linux/udp.h> 261da177e4SLinus Torvalds #include <linux/if_arp.h> 272e15ea39SPravin B Shelar #include <linux/if_vlan.h> 281da177e4SLinus Torvalds #include <linux/init.h> 291da177e4SLinus Torvalds #include <linux/in6.h> 301da177e4SLinus Torvalds #include <linux/inetdevice.h> 311da177e4SLinus Torvalds #include <linux/igmp.h> 321da177e4SLinus Torvalds #include <linux/netfilter_ipv4.h> 33e1a80002SHerbert Xu #include <linux/etherdevice.h> 3446f25dffSKris Katterjohn #include <linux/if_ether.h> 351da177e4SLinus Torvalds 361da177e4SLinus Torvalds #include <net/sock.h> 371da177e4SLinus Torvalds #include <net/ip.h> 381da177e4SLinus Torvalds #include <net/icmp.h> 391da177e4SLinus Torvalds #include <net/protocol.h> 40c5441932SPravin B Shelar #include <net/ip_tunnels.h> 411da177e4SLinus Torvalds #include <net/arp.h> 421da177e4SLinus Torvalds #include <net/checksum.h> 431da177e4SLinus Torvalds #include <net/dsfield.h> 441da177e4SLinus Torvalds #include <net/inet_ecn.h> 451da177e4SLinus Torvalds #include <net/xfrm.h> 4659a4c759SPavel Emelyanov #include <net/net_namespace.h> 4759a4c759SPavel Emelyanov #include <net/netns/generic.h> 48c19e654dSHerbert Xu #include <net/rtnetlink.h> 4900959adeSDmitry Kozlov #include <net/gre.h> 502e15ea39SPravin B Shelar #include <net/dst_metadata.h> 5184e54fe0SWilliam Tu #include <net/erspan.h> 521da177e4SLinus Torvalds 531da177e4SLinus Torvalds /* 541da177e4SLinus Torvalds Problems & solutions 551da177e4SLinus Torvalds -------------------- 561da177e4SLinus Torvalds 571da177e4SLinus Torvalds 1. The most important issue is detecting local dead loops. 581da177e4SLinus Torvalds They would cause complete host lockup in transmit, which 591da177e4SLinus Torvalds would be "resolved" by stack overflow or, if queueing is enabled, 601da177e4SLinus Torvalds with infinite looping in net_bh. 611da177e4SLinus Torvalds 621da177e4SLinus Torvalds We cannot track such dead loops during route installation, 631da177e4SLinus Torvalds it is infeasible task. The most general solutions would be 641da177e4SLinus Torvalds to keep skb->encapsulation counter (sort of local ttl), 656d0722a2SEric Dumazet and silently drop packet when it expires. It is a good 66bff52857Sstephen hemminger solution, but it supposes maintaining new variable in ALL 671da177e4SLinus Torvalds skb, even if no tunneling is used. 681da177e4SLinus Torvalds 696d0722a2SEric Dumazet Current solution: xmit_recursion breaks dead loops. This is a percpu 706d0722a2SEric Dumazet counter, since when we enter the first ndo_xmit(), cpu migration is 716d0722a2SEric Dumazet forbidden. We force an exit if this counter reaches RECURSION_LIMIT 721da177e4SLinus Torvalds 731da177e4SLinus Torvalds 2. Networking dead loops would not kill routers, but would really 741da177e4SLinus Torvalds kill network. IP hop limit plays role of "t->recursion" in this case, 751da177e4SLinus Torvalds if we copy it from packet being encapsulated to upper header. 761da177e4SLinus Torvalds It is very good solution, but it introduces two problems: 771da177e4SLinus Torvalds 781da177e4SLinus Torvalds - Routing protocols, using packets with ttl=1 (OSPF, RIP2), 791da177e4SLinus Torvalds do not work over tunnels. 801da177e4SLinus Torvalds - traceroute does not work. I planned to relay ICMP from tunnel, 811da177e4SLinus Torvalds so that this problem would be solved and traceroute output 821da177e4SLinus Torvalds would even more informative. This idea appeared to be wrong: 831da177e4SLinus Torvalds only Linux complies to rfc1812 now (yes, guys, Linux is the only 841da177e4SLinus Torvalds true router now :-)), all routers (at least, in neighbourhood of mine) 851da177e4SLinus Torvalds return only 8 bytes of payload. It is the end. 861da177e4SLinus Torvalds 871da177e4SLinus Torvalds Hence, if we want that OSPF worked or traceroute said something reasonable, 881da177e4SLinus Torvalds we should search for another solution. 891da177e4SLinus Torvalds 901da177e4SLinus Torvalds One of them is to parse packet trying to detect inner encapsulation 911da177e4SLinus Torvalds made by our node. It is difficult or even impossible, especially, 92bff52857Sstephen hemminger taking into account fragmentation. TO be short, ttl is not solution at all. 931da177e4SLinus Torvalds 941da177e4SLinus Torvalds Current solution: The solution was UNEXPECTEDLY SIMPLE. 951da177e4SLinus Torvalds We force DF flag on tunnels with preconfigured hop limit, 961da177e4SLinus Torvalds that is ALL. :-) Well, it does not remove the problem completely, 971da177e4SLinus Torvalds but exponential growth of network traffic is changed to linear 981da177e4SLinus Torvalds (branches, that exceed pmtu are pruned) and tunnel mtu 99bff52857Sstephen hemminger rapidly degrades to value <68, where looping stops. 1001da177e4SLinus Torvalds Yes, it is not good if there exists a router in the loop, 1011da177e4SLinus Torvalds which does not force DF, even when encapsulating packets have DF set. 1021da177e4SLinus Torvalds But it is not our problem! Nobody could accuse us, we made 1031da177e4SLinus Torvalds all that we could make. Even if it is your gated who injected 1041da177e4SLinus Torvalds fatal route to network, even if it were you who configured 1051da177e4SLinus Torvalds fatal static route: you are innocent. :-) 1061da177e4SLinus Torvalds 1071da177e4SLinus Torvalds Alexey Kuznetsov. 1081da177e4SLinus Torvalds */ 1091da177e4SLinus Torvalds 110eccc1bb8Sstephen hemminger static bool log_ecn_error = true; 111eccc1bb8Sstephen hemminger module_param(log_ecn_error, bool, 0644); 112eccc1bb8Sstephen hemminger MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN"); 113eccc1bb8Sstephen hemminger 114c19e654dSHerbert Xu static struct rtnl_link_ops ipgre_link_ops __read_mostly; 1151da177e4SLinus Torvalds static int ipgre_tunnel_init(struct net_device *dev); 1161a66a836SWilliam Tu static void erspan_build_header(struct sk_buff *skb, 117a3222dc9SWilliam Tu __be32 id, u32 index, 118a3222dc9SWilliam Tu bool truncate, bool is_ipv4); 119eb8ce741SPavel Emelyanov 120c7d03a00SAlexey Dobriyan static unsigned int ipgre_net_id __read_mostly; 121c7d03a00SAlexey Dobriyan static unsigned int gre_tap_net_id __read_mostly; 12284e54fe0SWilliam Tu static unsigned int erspan_net_id __read_mostly; 123eb8ce741SPavel Emelyanov 1249f57c67cSPravin B Shelar static void ipgre_err(struct sk_buff *skb, u32 info, 125bda7bb46SPravin B Shelar const struct tnl_ptk_info *tpi) 1261da177e4SLinus Torvalds { 1271da177e4SLinus Torvalds 128071f92d0SRami Rosen /* All the routers (except for Linux) return only 1291da177e4SLinus Torvalds 8 bytes of packet payload. It means, that precise relaying of 1301da177e4SLinus Torvalds ICMP in the real Internet is absolutely infeasible. 1311da177e4SLinus Torvalds 1321da177e4SLinus Torvalds Moreover, Cisco "wise men" put GRE key to the third word 133c5441932SPravin B Shelar in GRE header. It makes impossible maintaining even soft 134c5441932SPravin B Shelar state for keyed GRE tunnels with enabled checksum. Tell 135c5441932SPravin B Shelar them "thank you". 1361da177e4SLinus Torvalds 1371da177e4SLinus Torvalds Well, I wonder, rfc1812 was written by Cisco employee, 138bff52857Sstephen hemminger what the hell these idiots break standards established 139bff52857Sstephen hemminger by themselves??? 1401da177e4SLinus Torvalds */ 141c5441932SPravin B Shelar struct net *net = dev_net(skb->dev); 142c5441932SPravin B Shelar struct ip_tunnel_net *itn; 14396f5a846SEric Dumazet const struct iphdr *iph; 14488c7664fSArnaldo Carvalho de Melo const int type = icmp_hdr(skb)->type; 14588c7664fSArnaldo Carvalho de Melo const int code = icmp_hdr(skb)->code; 14620e1954fSEric Dumazet unsigned int data_len = 0; 1471da177e4SLinus Torvalds struct ip_tunnel *t; 148d2083287Sstephen hemminger 1491da177e4SLinus Torvalds switch (type) { 1501da177e4SLinus Torvalds default: 1511da177e4SLinus Torvalds case ICMP_PARAMETERPROB: 1529f57c67cSPravin B Shelar return; 1531da177e4SLinus Torvalds 1541da177e4SLinus Torvalds case ICMP_DEST_UNREACH: 1551da177e4SLinus Torvalds switch (code) { 1561da177e4SLinus Torvalds case ICMP_SR_FAILED: 1571da177e4SLinus Torvalds case ICMP_PORT_UNREACH: 1581da177e4SLinus Torvalds /* Impossible event. */ 1599f57c67cSPravin B Shelar return; 1601da177e4SLinus Torvalds default: 1611da177e4SLinus Torvalds /* All others are translated to HOST_UNREACH. 1621da177e4SLinus Torvalds rfc2003 contains "deep thoughts" about NET_UNREACH, 1631da177e4SLinus Torvalds I believe they are just ether pollution. --ANK 1641da177e4SLinus Torvalds */ 1651da177e4SLinus Torvalds break; 1661da177e4SLinus Torvalds } 1671da177e4SLinus Torvalds break; 1689f57c67cSPravin B Shelar 1691da177e4SLinus Torvalds case ICMP_TIME_EXCEEDED: 1701da177e4SLinus Torvalds if (code != ICMP_EXC_TTL) 1719f57c67cSPravin B Shelar return; 17220e1954fSEric Dumazet data_len = icmp_hdr(skb)->un.reserved[1] * 4; /* RFC 4884 4.1 */ 1731da177e4SLinus Torvalds break; 17455be7a9cSDavid S. Miller 17555be7a9cSDavid S. Miller case ICMP_REDIRECT: 17655be7a9cSDavid S. Miller break; 1771da177e4SLinus Torvalds } 1781da177e4SLinus Torvalds 179bda7bb46SPravin B Shelar if (tpi->proto == htons(ETH_P_TEB)) 180c5441932SPravin B Shelar itn = net_generic(net, gre_tap_net_id); 181c5441932SPravin B Shelar else 182c5441932SPravin B Shelar itn = net_generic(net, ipgre_net_id); 183c5441932SPravin B Shelar 184c0c0c50fSDuan Jiong iph = (const struct iphdr *)(icmp_hdr(skb) + 1); 185bda7bb46SPravin B Shelar t = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags, 186bda7bb46SPravin B Shelar iph->daddr, iph->saddr, tpi->key); 187d2083287Sstephen hemminger 18851456b29SIan Morris if (!t) 1899f57c67cSPravin B Shelar return; 19036393395SDavid S. Miller 1919b8c6d7bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6) 1929b8c6d7bSEric Dumazet if (tpi->proto == htons(ETH_P_IPV6) && 19320e1954fSEric Dumazet !ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4 + tpi->hdr_len, 19420e1954fSEric Dumazet type, data_len)) 1959b8c6d7bSEric Dumazet return; 1969b8c6d7bSEric Dumazet #endif 1979b8c6d7bSEric Dumazet 19836393395SDavid S. Miller if (t->parms.iph.daddr == 0 || 199f97c1e0cSJoe Perches ipv4_is_multicast(t->parms.iph.daddr)) 2009f57c67cSPravin B Shelar return; 2011da177e4SLinus Torvalds 2021da177e4SLinus Torvalds if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) 2039f57c67cSPravin B Shelar return; 2041da177e4SLinus Torvalds 205da6185d8SWei Yongjun if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO)) 2061da177e4SLinus Torvalds t->err_count++; 2071da177e4SLinus Torvalds else 2081da177e4SLinus Torvalds t->err_count = 1; 2091da177e4SLinus Torvalds t->err_time = jiffies; 2109f57c67cSPravin B Shelar } 2119f57c67cSPravin B Shelar 2129f57c67cSPravin B Shelar static void gre_err(struct sk_buff *skb, u32 info) 2139f57c67cSPravin B Shelar { 2149f57c67cSPravin B Shelar /* All the routers (except for Linux) return only 2159f57c67cSPravin B Shelar * 8 bytes of packet payload. It means, that precise relaying of 2169f57c67cSPravin B Shelar * ICMP in the real Internet is absolutely infeasible. 2179f57c67cSPravin B Shelar * 2189f57c67cSPravin B Shelar * Moreover, Cisco "wise men" put GRE key to the third word 2199f57c67cSPravin B Shelar * in GRE header. It makes impossible maintaining even soft 2209f57c67cSPravin B Shelar * state for keyed 2219f57c67cSPravin B Shelar * GRE tunnels with enabled checksum. Tell them "thank you". 2229f57c67cSPravin B Shelar * 2239f57c67cSPravin B Shelar * Well, I wonder, rfc1812 was written by Cisco employee, 2249f57c67cSPravin B Shelar * what the hell these idiots break standards established 2259f57c67cSPravin B Shelar * by themselves??? 2269f57c67cSPravin B Shelar */ 2279f57c67cSPravin B Shelar 228e582615aSEric Dumazet const struct iphdr *iph = (struct iphdr *)skb->data; 2299f57c67cSPravin B Shelar const int type = icmp_hdr(skb)->type; 2309f57c67cSPravin B Shelar const int code = icmp_hdr(skb)->code; 2319f57c67cSPravin B Shelar struct tnl_ptk_info tpi; 2329f57c67cSPravin B Shelar bool csum_err = false; 2339f57c67cSPravin B Shelar 234e582615aSEric Dumazet if (gre_parse_header(skb, &tpi, &csum_err, htons(ETH_P_IP), 235e582615aSEric Dumazet iph->ihl * 4) < 0) { 2369f57c67cSPravin B Shelar if (!csum_err) /* ignore csum errors. */ 2379f57c67cSPravin B Shelar return; 2389f57c67cSPravin B Shelar } 2399f57c67cSPravin B Shelar 2409f57c67cSPravin B Shelar if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) { 2419f57c67cSPravin B Shelar ipv4_update_pmtu(skb, dev_net(skb->dev), info, 2429f57c67cSPravin B Shelar skb->dev->ifindex, 0, IPPROTO_GRE, 0); 2439f57c67cSPravin B Shelar return; 2449f57c67cSPravin B Shelar } 2459f57c67cSPravin B Shelar if (type == ICMP_REDIRECT) { 2469f57c67cSPravin B Shelar ipv4_redirect(skb, dev_net(skb->dev), skb->dev->ifindex, 0, 2479f57c67cSPravin B Shelar IPPROTO_GRE, 0); 2489f57c67cSPravin B Shelar return; 2499f57c67cSPravin B Shelar } 2509f57c67cSPravin B Shelar 2519f57c67cSPravin B Shelar ipgre_err(skb, info, &tpi); 2521da177e4SLinus Torvalds } 2531da177e4SLinus Torvalds 25484e54fe0SWilliam Tu static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi, 25584e54fe0SWilliam Tu int gre_hdr_len) 25684e54fe0SWilliam Tu { 25784e54fe0SWilliam Tu struct net *net = dev_net(skb->dev); 25884e54fe0SWilliam Tu struct metadata_dst *tun_dst = NULL; 2591d7e2ed2SWilliam Tu struct erspan_base_hdr *ershdr; 2601d7e2ed2SWilliam Tu struct erspan_metadata *pkt_md; 26184e54fe0SWilliam Tu struct ip_tunnel_net *itn; 26284e54fe0SWilliam Tu struct ip_tunnel *tunnel; 26384e54fe0SWilliam Tu const struct iphdr *iph; 2641d7e2ed2SWilliam Tu int ver; 26584e54fe0SWilliam Tu int len; 26684e54fe0SWilliam Tu 26784e54fe0SWilliam Tu itn = net_generic(net, erspan_net_id); 26884e54fe0SWilliam Tu len = gre_hdr_len + sizeof(*ershdr); 26984e54fe0SWilliam Tu 2701d7e2ed2SWilliam Tu /* Check based hdr len */ 27184e54fe0SWilliam Tu if (unlikely(!pskb_may_pull(skb, len))) 272c05fad57SHaishuang Yan return PACKET_REJECT; 27384e54fe0SWilliam Tu 27484e54fe0SWilliam Tu iph = ip_hdr(skb); 2751d7e2ed2SWilliam Tu ershdr = (struct erspan_base_hdr *)(skb->data + gre_hdr_len); 2761d7e2ed2SWilliam Tu ver = (ntohs(ershdr->ver_vlan) & VER_MASK) >> VER_OFFSET; 27784e54fe0SWilliam Tu 27884e54fe0SWilliam Tu /* The original GRE header does not have key field, 27984e54fe0SWilliam Tu * Use ERSPAN 10-bit session ID as key. 28084e54fe0SWilliam Tu */ 281935a9749SXin Long tpi->key = cpu_to_be32(ntohs(ershdr->session_id) & ID_MASK); 2821d7e2ed2SWilliam Tu pkt_md = (struct erspan_metadata *)(ershdr + 1); 28384e54fe0SWilliam Tu tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, 28484e54fe0SWilliam Tu tpi->flags | TUNNEL_KEY, 28584e54fe0SWilliam Tu iph->saddr, iph->daddr, tpi->key); 28684e54fe0SWilliam Tu 28784e54fe0SWilliam Tu if (tunnel) { 2881d7e2ed2SWilliam Tu len = gre_hdr_len + erspan_hdr_len(ver); 2891d7e2ed2SWilliam Tu if (unlikely(!pskb_may_pull(skb, len))) 290*ae3e1337SWilliam Tu return PACKET_REJECT; 2911d7e2ed2SWilliam Tu 29284e54fe0SWilliam Tu if (__iptunnel_pull_header(skb, 2931d7e2ed2SWilliam Tu len, 29484e54fe0SWilliam Tu htons(ETH_P_TEB), 29584e54fe0SWilliam Tu false, false) < 0) 29684e54fe0SWilliam Tu goto drop; 29784e54fe0SWilliam Tu 2981a66a836SWilliam Tu if (tunnel->collect_md) { 2991a66a836SWilliam Tu struct ip_tunnel_info *info; 3001a66a836SWilliam Tu struct erspan_metadata *md; 3011a66a836SWilliam Tu __be64 tun_id; 3021a66a836SWilliam Tu __be16 flags; 3031a66a836SWilliam Tu 3041a66a836SWilliam Tu tpi->flags |= TUNNEL_KEY; 3051a66a836SWilliam Tu flags = tpi->flags; 3061a66a836SWilliam Tu tun_id = key32_to_tunnel_id(tpi->key); 3071a66a836SWilliam Tu 3081a66a836SWilliam Tu tun_dst = ip_tun_rx_dst(skb, flags, 3091a66a836SWilliam Tu tun_id, sizeof(*md)); 3101a66a836SWilliam Tu if (!tun_dst) 3111a66a836SWilliam Tu return PACKET_REJECT; 3121a66a836SWilliam Tu 3131a66a836SWilliam Tu md = ip_tunnel_info_opts(&tun_dst->u.tun_info); 3141a66a836SWilliam Tu if (!md) 3151a66a836SWilliam Tu return PACKET_REJECT; 3161a66a836SWilliam Tu 3171d7e2ed2SWilliam Tu memcpy(md, pkt_md, sizeof(*md)); 318f551c91dSWilliam Tu md->version = ver; 319f551c91dSWilliam Tu 3201a66a836SWilliam Tu info = &tun_dst->u.tun_info; 3211a66a836SWilliam Tu info->key.tun_flags |= TUNNEL_ERSPAN_OPT; 3221a66a836SWilliam Tu info->options_len = sizeof(*md); 3231a66a836SWilliam Tu } else { 324f551c91dSWilliam Tu tunnel->erspan_ver = ver; 325f551c91dSWilliam Tu if (ver == 1) { 3261d7e2ed2SWilliam Tu tunnel->index = ntohl(pkt_md->u.index); 327f551c91dSWilliam Tu } else { 328f551c91dSWilliam Tu u16 md2_flags; 329f551c91dSWilliam Tu u16 dir, hwid; 330f551c91dSWilliam Tu 331f551c91dSWilliam Tu md2_flags = ntohs(pkt_md->u.md2.flags); 332f551c91dSWilliam Tu dir = (md2_flags & DIR_MASK) >> DIR_OFFSET; 333f551c91dSWilliam Tu hwid = (md2_flags & HWID_MASK) >> HWID_OFFSET; 334f551c91dSWilliam Tu tunnel->dir = dir; 335f551c91dSWilliam Tu tunnel->hwid = hwid; 336f551c91dSWilliam Tu } 337f551c91dSWilliam Tu 3381a66a836SWilliam Tu } 3391a66a836SWilliam Tu 34084e54fe0SWilliam Tu skb_reset_mac_header(skb); 34184e54fe0SWilliam Tu ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error); 34284e54fe0SWilliam Tu return PACKET_RCVD; 34384e54fe0SWilliam Tu } 34484e54fe0SWilliam Tu drop: 34584e54fe0SWilliam Tu kfree_skb(skb); 34684e54fe0SWilliam Tu return PACKET_RCVD; 34784e54fe0SWilliam Tu } 34884e54fe0SWilliam Tu 349125372faSJiri Benc static int __ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi, 350125372faSJiri Benc struct ip_tunnel_net *itn, int hdr_len, bool raw_proto) 3511da177e4SLinus Torvalds { 3522e15ea39SPravin B Shelar struct metadata_dst *tun_dst = NULL; 353b71d1d42SEric Dumazet const struct iphdr *iph; 3541da177e4SLinus Torvalds struct ip_tunnel *tunnel; 3551da177e4SLinus Torvalds 356eddc9ec5SArnaldo Carvalho de Melo iph = ip_hdr(skb); 357bda7bb46SPravin B Shelar tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags, 358bda7bb46SPravin B Shelar iph->saddr, iph->daddr, tpi->key); 3591da177e4SLinus Torvalds 360d2083287Sstephen hemminger if (tunnel) { 361125372faSJiri Benc if (__iptunnel_pull_header(skb, hdr_len, tpi->proto, 362125372faSJiri Benc raw_proto, false) < 0) 363244a797bSJiri Benc goto drop; 364244a797bSJiri Benc 365e271c7b4SJiri Benc if (tunnel->dev->type != ARPHRD_NONE) 3660e3da5bbSTimo Teräs skb_pop_mac_header(skb); 367e271c7b4SJiri Benc else 368e271c7b4SJiri Benc skb_reset_mac_header(skb); 3692e15ea39SPravin B Shelar if (tunnel->collect_md) { 370c29a70d2SPravin B Shelar __be16 flags; 371c29a70d2SPravin B Shelar __be64 tun_id; 3722e15ea39SPravin B Shelar 373c29a70d2SPravin B Shelar flags = tpi->flags & (TUNNEL_CSUM | TUNNEL_KEY); 374d817f432SAmir Vadai tun_id = key32_to_tunnel_id(tpi->key); 375c29a70d2SPravin B Shelar tun_dst = ip_tun_rx_dst(skb, flags, tun_id, 0); 3762e15ea39SPravin B Shelar if (!tun_dst) 3772e15ea39SPravin B Shelar return PACKET_REJECT; 3782e15ea39SPravin B Shelar } 3792e15ea39SPravin B Shelar 3802e15ea39SPravin B Shelar ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error); 381bda7bb46SPravin B Shelar return PACKET_RCVD; 3821da177e4SLinus Torvalds } 383125372faSJiri Benc return PACKET_NEXT; 384244a797bSJiri Benc 385244a797bSJiri Benc drop: 386244a797bSJiri Benc kfree_skb(skb); 387244a797bSJiri Benc return PACKET_RCVD; 3881da177e4SLinus Torvalds } 3891da177e4SLinus Torvalds 390125372faSJiri Benc static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi, 391125372faSJiri Benc int hdr_len) 392125372faSJiri Benc { 393125372faSJiri Benc struct net *net = dev_net(skb->dev); 394125372faSJiri Benc struct ip_tunnel_net *itn; 395125372faSJiri Benc int res; 396125372faSJiri Benc 397125372faSJiri Benc if (tpi->proto == htons(ETH_P_TEB)) 398125372faSJiri Benc itn = net_generic(net, gre_tap_net_id); 399125372faSJiri Benc else 400125372faSJiri Benc itn = net_generic(net, ipgre_net_id); 401125372faSJiri Benc 402125372faSJiri Benc res = __ipgre_rcv(skb, tpi, itn, hdr_len, false); 403125372faSJiri Benc if (res == PACKET_NEXT && tpi->proto == htons(ETH_P_TEB)) { 404125372faSJiri Benc /* ipgre tunnels in collect metadata mode should receive 405125372faSJiri Benc * also ETH_P_TEB traffic. 406125372faSJiri Benc */ 407125372faSJiri Benc itn = net_generic(net, ipgre_net_id); 408125372faSJiri Benc res = __ipgre_rcv(skb, tpi, itn, hdr_len, true); 409125372faSJiri Benc } 410125372faSJiri Benc return res; 411125372faSJiri Benc } 412125372faSJiri Benc 4139f57c67cSPravin B Shelar static int gre_rcv(struct sk_buff *skb) 4149f57c67cSPravin B Shelar { 4159f57c67cSPravin B Shelar struct tnl_ptk_info tpi; 4169f57c67cSPravin B Shelar bool csum_err = false; 41795f5c64cSTom Herbert int hdr_len; 4189f57c67cSPravin B Shelar 4199f57c67cSPravin B Shelar #ifdef CONFIG_NET_IPGRE_BROADCAST 4209f57c67cSPravin B Shelar if (ipv4_is_multicast(ip_hdr(skb)->daddr)) { 4219f57c67cSPravin B Shelar /* Looped back packet, drop it! */ 4229f57c67cSPravin B Shelar if (rt_is_output_route(skb_rtable(skb))) 4239f57c67cSPravin B Shelar goto drop; 4249f57c67cSPravin B Shelar } 4259f57c67cSPravin B Shelar #endif 4269f57c67cSPravin B Shelar 427e582615aSEric Dumazet hdr_len = gre_parse_header(skb, &tpi, &csum_err, htons(ETH_P_IP), 0); 428f132ae7cSJiri Benc if (hdr_len < 0) 42995f5c64cSTom Herbert goto drop; 43095f5c64cSTom Herbert 431f551c91dSWilliam Tu if (unlikely(tpi.proto == htons(ETH_P_ERSPAN) || 432f551c91dSWilliam Tu tpi.proto == htons(ETH_P_ERSPAN2))) { 43384e54fe0SWilliam Tu if (erspan_rcv(skb, &tpi, hdr_len) == PACKET_RCVD) 43484e54fe0SWilliam Tu return 0; 43584e54fe0SWilliam Tu } 43684e54fe0SWilliam Tu 437244a797bSJiri Benc if (ipgre_rcv(skb, &tpi, hdr_len) == PACKET_RCVD) 4389f57c67cSPravin B Shelar return 0; 4399f57c67cSPravin B Shelar 4409f57c67cSPravin B Shelar icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); 4419f57c67cSPravin B Shelar drop: 4429f57c67cSPravin B Shelar kfree_skb(skb); 4439f57c67cSPravin B Shelar return 0; 4449f57c67cSPravin B Shelar } 4459f57c67cSPravin B Shelar 446c5441932SPravin B Shelar static void __gre_xmit(struct sk_buff *skb, struct net_device *dev, 447c5441932SPravin B Shelar const struct iphdr *tnl_params, 448c5441932SPravin B Shelar __be16 proto) 449c5441932SPravin B Shelar { 450c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 451c5441932SPravin B Shelar 452c5441932SPravin B Shelar if (tunnel->parms.o_flags & TUNNEL_SEQ) 453c5441932SPravin B Shelar tunnel->o_seqno++; 454cef401deSEric Dumazet 455c5441932SPravin B Shelar /* Push GRE header. */ 456182a352dSTom Herbert gre_build_header(skb, tunnel->tun_hlen, 457182a352dSTom Herbert tunnel->parms.o_flags, proto, tunnel->parms.o_key, 458182a352dSTom Herbert htonl(tunnel->o_seqno)); 4591da177e4SLinus Torvalds 460bf3d6a8fSNicolas Dichtel ip_tunnel_xmit(skb, dev, tnl_params, tnl_params->protocol); 4611da177e4SLinus Torvalds } 4621da177e4SLinus Torvalds 463aed069dfSAlexander Duyck static int gre_handle_offloads(struct sk_buff *skb, bool csum) 464b2acd1dcSPravin B Shelar { 4656fa79666SEdward Cree return iptunnel_handle_offloads(skb, csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE); 466b2acd1dcSPravin B Shelar } 467b2acd1dcSPravin B Shelar 468fc4099f1SPravin B Shelar static struct rtable *gre_get_rt(struct sk_buff *skb, 469fc4099f1SPravin B Shelar struct net_device *dev, 470fc4099f1SPravin B Shelar struct flowi4 *fl, 471fc4099f1SPravin B Shelar const struct ip_tunnel_key *key) 472fc4099f1SPravin B Shelar { 473fc4099f1SPravin B Shelar struct net *net = dev_net(dev); 474fc4099f1SPravin B Shelar 475fc4099f1SPravin B Shelar memset(fl, 0, sizeof(*fl)); 476fc4099f1SPravin B Shelar fl->daddr = key->u.ipv4.dst; 477fc4099f1SPravin B Shelar fl->saddr = key->u.ipv4.src; 478fc4099f1SPravin B Shelar fl->flowi4_tos = RT_TOS(key->tos); 479fc4099f1SPravin B Shelar fl->flowi4_mark = skb->mark; 480fc4099f1SPravin B Shelar fl->flowi4_proto = IPPROTO_GRE; 481fc4099f1SPravin B Shelar 482fc4099f1SPravin B Shelar return ip_route_output_key(net, fl); 483fc4099f1SPravin B Shelar } 484fc4099f1SPravin B Shelar 485862a03c3SWilliam Tu static struct rtable *prepare_fb_xmit(struct sk_buff *skb, 486862a03c3SWilliam Tu struct net_device *dev, 487862a03c3SWilliam Tu struct flowi4 *fl, 488862a03c3SWilliam Tu int tunnel_hlen) 4892e15ea39SPravin B Shelar { 4902e15ea39SPravin B Shelar struct ip_tunnel_info *tun_info; 4912e15ea39SPravin B Shelar const struct ip_tunnel_key *key; 492db3c6139SDaniel Borkmann struct rtable *rt = NULL; 4932e15ea39SPravin B Shelar int min_headroom; 494db3c6139SDaniel Borkmann bool use_cache; 4952e15ea39SPravin B Shelar int err; 4962e15ea39SPravin B Shelar 49761adedf3SJiri Benc tun_info = skb_tunnel_info(skb); 4982e15ea39SPravin B Shelar key = &tun_info->key; 499db3c6139SDaniel Borkmann use_cache = ip_tunnel_dst_cache_usable(skb, tun_info); 500862a03c3SWilliam Tu 501db3c6139SDaniel Borkmann if (use_cache) 502862a03c3SWilliam Tu rt = dst_cache_get_ip4(&tun_info->dst_cache, &fl->saddr); 5033c1cb4d2SPaolo Abeni if (!rt) { 504862a03c3SWilliam Tu rt = gre_get_rt(skb, dev, fl, key); 5052e15ea39SPravin B Shelar if (IS_ERR(rt)) 5062e15ea39SPravin B Shelar goto err_free_skb; 507db3c6139SDaniel Borkmann if (use_cache) 5083c1cb4d2SPaolo Abeni dst_cache_set_ip4(&tun_info->dst_cache, &rt->dst, 509862a03c3SWilliam Tu fl->saddr); 5103c1cb4d2SPaolo Abeni } 5112e15ea39SPravin B Shelar 5122e15ea39SPravin B Shelar min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len 5132e15ea39SPravin B Shelar + tunnel_hlen + sizeof(struct iphdr); 5142e15ea39SPravin B Shelar if (skb_headroom(skb) < min_headroom || skb_header_cloned(skb)) { 5152e15ea39SPravin B Shelar int head_delta = SKB_DATA_ALIGN(min_headroom - 5162e15ea39SPravin B Shelar skb_headroom(skb) + 5172e15ea39SPravin B Shelar 16); 5182e15ea39SPravin B Shelar err = pskb_expand_head(skb, max_t(int, head_delta, 0), 5192e15ea39SPravin B Shelar 0, GFP_ATOMIC); 5202e15ea39SPravin B Shelar if (unlikely(err)) 5212e15ea39SPravin B Shelar goto err_free_rt; 5222e15ea39SPravin B Shelar } 523862a03c3SWilliam Tu return rt; 524862a03c3SWilliam Tu 525862a03c3SWilliam Tu err_free_rt: 526862a03c3SWilliam Tu ip_rt_put(rt); 527862a03c3SWilliam Tu err_free_skb: 528862a03c3SWilliam Tu kfree_skb(skb); 529862a03c3SWilliam Tu dev->stats.tx_dropped++; 530862a03c3SWilliam Tu return NULL; 531862a03c3SWilliam Tu } 532862a03c3SWilliam Tu 533862a03c3SWilliam Tu static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev, 534862a03c3SWilliam Tu __be16 proto) 535862a03c3SWilliam Tu { 536862a03c3SWilliam Tu struct ip_tunnel_info *tun_info; 537862a03c3SWilliam Tu const struct ip_tunnel_key *key; 538862a03c3SWilliam Tu struct rtable *rt = NULL; 539862a03c3SWilliam Tu struct flowi4 fl; 540862a03c3SWilliam Tu int tunnel_hlen; 541862a03c3SWilliam Tu __be16 df, flags; 542862a03c3SWilliam Tu 543862a03c3SWilliam Tu tun_info = skb_tunnel_info(skb); 544862a03c3SWilliam Tu if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) || 545862a03c3SWilliam Tu ip_tunnel_info_af(tun_info) != AF_INET)) 546862a03c3SWilliam Tu goto err_free_skb; 547862a03c3SWilliam Tu 548862a03c3SWilliam Tu key = &tun_info->key; 549862a03c3SWilliam Tu tunnel_hlen = gre_calc_hlen(key->tun_flags); 550862a03c3SWilliam Tu 551862a03c3SWilliam Tu rt = prepare_fb_xmit(skb, dev, &fl, tunnel_hlen); 552862a03c3SWilliam Tu if (!rt) 553862a03c3SWilliam Tu return; 5542e15ea39SPravin B Shelar 5552e15ea39SPravin B Shelar /* Push Tunnel header. */ 556aed069dfSAlexander Duyck if (gre_handle_offloads(skb, !!(tun_info->key.tun_flags & TUNNEL_CSUM))) 5572e15ea39SPravin B Shelar goto err_free_rt; 5582e15ea39SPravin B Shelar 5592e15ea39SPravin B Shelar flags = tun_info->key.tun_flags & (TUNNEL_CSUM | TUNNEL_KEY); 560cba65321SDavid S. Miller gre_build_header(skb, tunnel_hlen, flags, proto, 561d817f432SAmir Vadai tunnel_id_to_key32(tun_info->key.tun_id), 0); 5622e15ea39SPravin B Shelar 5632e15ea39SPravin B Shelar df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0; 564039f5062SPravin B Shelar 565039f5062SPravin B Shelar iptunnel_xmit(skb->sk, rt, skb, fl.saddr, key->u.ipv4.dst, IPPROTO_GRE, 5667c383fb2SJiri Benc key->tos, key->ttl, df, false); 5672e15ea39SPravin B Shelar return; 5682e15ea39SPravin B Shelar 5692e15ea39SPravin B Shelar err_free_rt: 5702e15ea39SPravin B Shelar ip_rt_put(rt); 5712e15ea39SPravin B Shelar err_free_skb: 5722e15ea39SPravin B Shelar kfree_skb(skb); 5732e15ea39SPravin B Shelar dev->stats.tx_dropped++; 5742e15ea39SPravin B Shelar } 5752e15ea39SPravin B Shelar 5761a66a836SWilliam Tu static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev, 5771a66a836SWilliam Tu __be16 proto) 5781a66a836SWilliam Tu { 5791a66a836SWilliam Tu struct ip_tunnel *tunnel = netdev_priv(dev); 5801a66a836SWilliam Tu struct ip_tunnel_info *tun_info; 5811a66a836SWilliam Tu const struct ip_tunnel_key *key; 5821a66a836SWilliam Tu struct erspan_metadata *md; 5831a66a836SWilliam Tu struct rtable *rt = NULL; 5841a66a836SWilliam Tu bool truncate = false; 5851a66a836SWilliam Tu struct flowi4 fl; 5861a66a836SWilliam Tu int tunnel_hlen; 587f551c91dSWilliam Tu int version; 5881a66a836SWilliam Tu __be16 df; 5891a66a836SWilliam Tu 5901a66a836SWilliam Tu tun_info = skb_tunnel_info(skb); 5911a66a836SWilliam Tu if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) || 5921a66a836SWilliam Tu ip_tunnel_info_af(tun_info) != AF_INET)) 5931a66a836SWilliam Tu goto err_free_skb; 5941a66a836SWilliam Tu 5951a66a836SWilliam Tu key = &tun_info->key; 596f551c91dSWilliam Tu md = ip_tunnel_info_opts(tun_info); 597f551c91dSWilliam Tu if (!md) 598f551c91dSWilliam Tu goto err_free_rt; 5991a66a836SWilliam Tu 6001a66a836SWilliam Tu /* ERSPAN has fixed 8 byte GRE header */ 601f551c91dSWilliam Tu version = md->version; 602f551c91dSWilliam Tu tunnel_hlen = 8 + erspan_hdr_len(version); 6031a66a836SWilliam Tu 6041a66a836SWilliam Tu rt = prepare_fb_xmit(skb, dev, &fl, tunnel_hlen); 6051a66a836SWilliam Tu if (!rt) 6061a66a836SWilliam Tu return; 6071a66a836SWilliam Tu 6081a66a836SWilliam Tu if (gre_handle_offloads(skb, false)) 6091a66a836SWilliam Tu goto err_free_rt; 6101a66a836SWilliam Tu 611f192970dSWilliam Tu if (skb->len > dev->mtu + dev->hard_header_len) { 612f192970dSWilliam Tu pskb_trim(skb, dev->mtu + dev->hard_header_len); 6131a66a836SWilliam Tu truncate = true; 6141a66a836SWilliam Tu } 6151a66a836SWilliam Tu 616f551c91dSWilliam Tu if (version == 1) { 6171a66a836SWilliam Tu erspan_build_header(skb, tunnel_id_to_key32(key->tun_id), 6181d7e2ed2SWilliam Tu ntohl(md->u.index), truncate, true); 619f551c91dSWilliam Tu } else if (version == 2) { 620f551c91dSWilliam Tu u16 md2_flags; 621f551c91dSWilliam Tu u8 direction; 622f551c91dSWilliam Tu u16 hwid; 623f551c91dSWilliam Tu 624f551c91dSWilliam Tu md2_flags = ntohs(md->u.md2.flags); 625f551c91dSWilliam Tu direction = (md2_flags & DIR_MASK) >> DIR_OFFSET; 626f551c91dSWilliam Tu hwid = (md2_flags & HWID_MASK) >> HWID_OFFSET; 627f551c91dSWilliam Tu 628f551c91dSWilliam Tu erspan_build_header_v2(skb, tunnel_id_to_key32(key->tun_id), 629f551c91dSWilliam Tu direction, hwid, truncate, true); 630f551c91dSWilliam Tu } else { 631f551c91dSWilliam Tu goto err_free_rt; 632f551c91dSWilliam Tu } 6331a66a836SWilliam Tu 6341a66a836SWilliam Tu gre_build_header(skb, 8, TUNNEL_SEQ, 6351a66a836SWilliam Tu htons(ETH_P_ERSPAN), 0, htonl(tunnel->o_seqno++)); 6361a66a836SWilliam Tu 6371a66a836SWilliam Tu df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0; 6381a66a836SWilliam Tu 6391a66a836SWilliam Tu iptunnel_xmit(skb->sk, rt, skb, fl.saddr, key->u.ipv4.dst, IPPROTO_GRE, 6401a66a836SWilliam Tu key->tos, key->ttl, df, false); 6411a66a836SWilliam Tu return; 6421a66a836SWilliam Tu 6431a66a836SWilliam Tu err_free_rt: 6441a66a836SWilliam Tu ip_rt_put(rt); 6451a66a836SWilliam Tu err_free_skb: 6461a66a836SWilliam Tu kfree_skb(skb); 6471a66a836SWilliam Tu dev->stats.tx_dropped++; 6481a66a836SWilliam Tu } 6491a66a836SWilliam Tu 650fc4099f1SPravin B Shelar static int gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) 651fc4099f1SPravin B Shelar { 652fc4099f1SPravin B Shelar struct ip_tunnel_info *info = skb_tunnel_info(skb); 653fc4099f1SPravin B Shelar struct rtable *rt; 654fc4099f1SPravin B Shelar struct flowi4 fl4; 655fc4099f1SPravin B Shelar 656fc4099f1SPravin B Shelar if (ip_tunnel_info_af(info) != AF_INET) 657fc4099f1SPravin B Shelar return -EINVAL; 658fc4099f1SPravin B Shelar 659fc4099f1SPravin B Shelar rt = gre_get_rt(skb, dev, &fl4, &info->key); 660fc4099f1SPravin B Shelar if (IS_ERR(rt)) 661fc4099f1SPravin B Shelar return PTR_ERR(rt); 662fc4099f1SPravin B Shelar 663fc4099f1SPravin B Shelar ip_rt_put(rt); 664fc4099f1SPravin B Shelar info->key.u.ipv4.src = fl4.saddr; 665fc4099f1SPravin B Shelar return 0; 666fc4099f1SPravin B Shelar } 667fc4099f1SPravin B Shelar 668c5441932SPravin B Shelar static netdev_tx_t ipgre_xmit(struct sk_buff *skb, 669c5441932SPravin B Shelar struct net_device *dev) 670ee34c1ebSMichal Schmidt { 671c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 672c5441932SPravin B Shelar const struct iphdr *tnl_params; 673ee34c1ebSMichal Schmidt 6742e15ea39SPravin B Shelar if (tunnel->collect_md) { 6752090714eSJiri Benc gre_fb_xmit(skb, dev, skb->protocol); 6762e15ea39SPravin B Shelar return NETDEV_TX_OK; 6772e15ea39SPravin B Shelar } 6782e15ea39SPravin B Shelar 679c5441932SPravin B Shelar if (dev->header_ops) { 680c5441932SPravin B Shelar /* Need space for new headers */ 681c5441932SPravin B Shelar if (skb_cow_head(skb, dev->needed_headroom - 6822bac7cb3SChen Gang (tunnel->hlen + sizeof(struct iphdr)))) 683c5441932SPravin B Shelar goto free_skb; 684ee34c1ebSMichal Schmidt 685c5441932SPravin B Shelar tnl_params = (const struct iphdr *)skb->data; 686cbb1e85fSDavid S. Miller 687c5441932SPravin B Shelar /* Pull skb since ip_tunnel_xmit() needs skb->data pointing 688c5441932SPravin B Shelar * to gre header. 689c5441932SPravin B Shelar */ 690c5441932SPravin B Shelar skb_pull(skb, tunnel->hlen + sizeof(struct iphdr)); 6918a0033a9STimo Teräs skb_reset_mac_header(skb); 692c5441932SPravin B Shelar } else { 693c5441932SPravin B Shelar if (skb_cow_head(skb, dev->needed_headroom)) 694c5441932SPravin B Shelar goto free_skb; 695c5441932SPravin B Shelar 696c5441932SPravin B Shelar tnl_params = &tunnel->parms.iph; 697ee34c1ebSMichal Schmidt } 698e1a80002SHerbert Xu 699aed069dfSAlexander Duyck if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM))) 700aed069dfSAlexander Duyck goto free_skb; 7018a0033a9STimo Teräs 702c5441932SPravin B Shelar __gre_xmit(skb, dev, tnl_params, skb->protocol); 703c5441932SPravin B Shelar return NETDEV_TX_OK; 704c5441932SPravin B Shelar 705c5441932SPravin B Shelar free_skb: 7063acfa1e7SEric Dumazet kfree_skb(skb); 707c5441932SPravin B Shelar dev->stats.tx_dropped++; 708c5441932SPravin B Shelar return NETDEV_TX_OK; 709ee34c1ebSMichal Schmidt } 710ee34c1ebSMichal Schmidt 71184e54fe0SWilliam Tu static netdev_tx_t erspan_xmit(struct sk_buff *skb, 71284e54fe0SWilliam Tu struct net_device *dev) 71384e54fe0SWilliam Tu { 71484e54fe0SWilliam Tu struct ip_tunnel *tunnel = netdev_priv(dev); 71584e54fe0SWilliam Tu bool truncate = false; 71684e54fe0SWilliam Tu 7171a66a836SWilliam Tu if (tunnel->collect_md) { 7181a66a836SWilliam Tu erspan_fb_xmit(skb, dev, skb->protocol); 7191a66a836SWilliam Tu return NETDEV_TX_OK; 7201a66a836SWilliam Tu } 7211a66a836SWilliam Tu 72284e54fe0SWilliam Tu if (gre_handle_offloads(skb, false)) 72384e54fe0SWilliam Tu goto free_skb; 72484e54fe0SWilliam Tu 72584e54fe0SWilliam Tu if (skb_cow_head(skb, dev->needed_headroom)) 72684e54fe0SWilliam Tu goto free_skb; 72784e54fe0SWilliam Tu 728f192970dSWilliam Tu if (skb->len > dev->mtu + dev->hard_header_len) { 729f192970dSWilliam Tu pskb_trim(skb, dev->mtu + dev->hard_header_len); 73084e54fe0SWilliam Tu truncate = true; 73184e54fe0SWilliam Tu } 73284e54fe0SWilliam Tu 73384e54fe0SWilliam Tu /* Push ERSPAN header */ 734f551c91dSWilliam Tu if (tunnel->erspan_ver == 1) 735a3222dc9SWilliam Tu erspan_build_header(skb, tunnel->parms.o_key, tunnel->index, 736a3222dc9SWilliam Tu truncate, true); 737f551c91dSWilliam Tu else 738f551c91dSWilliam Tu erspan_build_header_v2(skb, tunnel->parms.o_key, 739f551c91dSWilliam Tu tunnel->dir, tunnel->hwid, 740f551c91dSWilliam Tu truncate, true); 741f551c91dSWilliam Tu 74284e54fe0SWilliam Tu tunnel->parms.o_flags &= ~TUNNEL_KEY; 74384e54fe0SWilliam Tu __gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_ERSPAN)); 74484e54fe0SWilliam Tu return NETDEV_TX_OK; 74584e54fe0SWilliam Tu 74684e54fe0SWilliam Tu free_skb: 74784e54fe0SWilliam Tu kfree_skb(skb); 74884e54fe0SWilliam Tu dev->stats.tx_dropped++; 74984e54fe0SWilliam Tu return NETDEV_TX_OK; 75084e54fe0SWilliam Tu } 75184e54fe0SWilliam Tu 752c5441932SPravin B Shelar static netdev_tx_t gre_tap_xmit(struct sk_buff *skb, 753c5441932SPravin B Shelar struct net_device *dev) 754c5441932SPravin B Shelar { 755c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 756ee34c1ebSMichal Schmidt 7572e15ea39SPravin B Shelar if (tunnel->collect_md) { 7582090714eSJiri Benc gre_fb_xmit(skb, dev, htons(ETH_P_TEB)); 7592e15ea39SPravin B Shelar return NETDEV_TX_OK; 7602e15ea39SPravin B Shelar } 7612e15ea39SPravin B Shelar 762aed069dfSAlexander Duyck if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM))) 763aed069dfSAlexander Duyck goto free_skb; 764ee34c1ebSMichal Schmidt 765c5441932SPravin B Shelar if (skb_cow_head(skb, dev->needed_headroom)) 766c5441932SPravin B Shelar goto free_skb; 76742aa9162SHerbert Xu 768c5441932SPravin B Shelar __gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_TEB)); 769c5441932SPravin B Shelar return NETDEV_TX_OK; 770c5441932SPravin B Shelar 771c5441932SPravin B Shelar free_skb: 7723acfa1e7SEric Dumazet kfree_skb(skb); 773c5441932SPravin B Shelar dev->stats.tx_dropped++; 774c5441932SPravin B Shelar return NETDEV_TX_OK; 77568c33163SPravin B Shelar } 776ee34c1ebSMichal Schmidt 777dd9d598cSXin Long static void ipgre_link_update(struct net_device *dev, bool set_mtu) 778dd9d598cSXin Long { 779dd9d598cSXin Long struct ip_tunnel *tunnel = netdev_priv(dev); 780dd9d598cSXin Long int len; 781dd9d598cSXin Long 782dd9d598cSXin Long len = tunnel->tun_hlen; 783dd9d598cSXin Long tunnel->tun_hlen = gre_calc_hlen(tunnel->parms.o_flags); 784dd9d598cSXin Long len = tunnel->tun_hlen - len; 785dd9d598cSXin Long tunnel->hlen = tunnel->hlen + len; 786dd9d598cSXin Long 787dd9d598cSXin Long dev->needed_headroom = dev->needed_headroom + len; 788dd9d598cSXin Long if (set_mtu) 789dd9d598cSXin Long dev->mtu = max_t(int, dev->mtu - len, 68); 790dd9d598cSXin Long 791dd9d598cSXin Long if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) { 792dd9d598cSXin Long if (!(tunnel->parms.o_flags & TUNNEL_CSUM) || 793dd9d598cSXin Long tunnel->encap.type == TUNNEL_ENCAP_NONE) { 794dd9d598cSXin Long dev->features |= NETIF_F_GSO_SOFTWARE; 795dd9d598cSXin Long dev->hw_features |= NETIF_F_GSO_SOFTWARE; 796dd9d598cSXin Long } 797dd9d598cSXin Long dev->features |= NETIF_F_LLTX; 798dd9d598cSXin Long } 799dd9d598cSXin Long } 800dd9d598cSXin Long 801c5441932SPravin B Shelar static int ipgre_tunnel_ioctl(struct net_device *dev, 802c5441932SPravin B Shelar struct ifreq *ifr, int cmd) 8031da177e4SLinus Torvalds { 8041da177e4SLinus Torvalds struct ip_tunnel_parm p; 805a0efab67SXin Long int err; 8061da177e4SLinus Torvalds 8071da177e4SLinus Torvalds if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) 808c5441932SPravin B Shelar return -EFAULT; 809a0efab67SXin Long 8106c734fb8SCong Wang if (cmd == SIOCADDTUNNEL || cmd == SIOCCHGTUNNEL) { 8111da177e4SLinus Torvalds if (p.iph.version != 4 || p.iph.protocol != IPPROTO_GRE || 8121da177e4SLinus Torvalds p.iph.ihl != 5 || (p.iph.frag_off & htons(~IP_DF)) || 8136c734fb8SCong Wang ((p.i_flags | p.o_flags) & (GRE_VERSION | GRE_ROUTING))) 8141da177e4SLinus Torvalds return -EINVAL; 815c5441932SPravin B Shelar } 816a0efab67SXin Long 817c5441932SPravin B Shelar p.i_flags = gre_flags_to_tnl_flags(p.i_flags); 818c5441932SPravin B Shelar p.o_flags = gre_flags_to_tnl_flags(p.o_flags); 819c5441932SPravin B Shelar 820c5441932SPravin B Shelar err = ip_tunnel_ioctl(dev, &p, cmd); 821c5441932SPravin B Shelar if (err) 822c5441932SPravin B Shelar return err; 823c5441932SPravin B Shelar 824a0efab67SXin Long if (cmd == SIOCCHGTUNNEL) { 825a0efab67SXin Long struct ip_tunnel *t = netdev_priv(dev); 826a0efab67SXin Long 827a0efab67SXin Long t->parms.i_flags = p.i_flags; 828a0efab67SXin Long t->parms.o_flags = p.o_flags; 829a0efab67SXin Long 830a0efab67SXin Long if (strcmp(dev->rtnl_link_ops->kind, "erspan")) 831a0efab67SXin Long ipgre_link_update(dev, true); 832a0efab67SXin Long } 833a0efab67SXin Long 83495f5c64cSTom Herbert p.i_flags = gre_tnl_flags_to_gre_flags(p.i_flags); 83595f5c64cSTom Herbert p.o_flags = gre_tnl_flags_to_gre_flags(p.o_flags); 836c5441932SPravin B Shelar 837c5441932SPravin B Shelar if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) 838c5441932SPravin B Shelar return -EFAULT; 839a0efab67SXin Long 8401da177e4SLinus Torvalds return 0; 8411da177e4SLinus Torvalds } 8421da177e4SLinus Torvalds 8431da177e4SLinus Torvalds /* Nice toy. Unfortunately, useless in real life :-) 8441da177e4SLinus Torvalds It allows to construct virtual multiprotocol broadcast "LAN" 8451da177e4SLinus Torvalds over the Internet, provided multicast routing is tuned. 8461da177e4SLinus Torvalds 8471da177e4SLinus Torvalds 8481da177e4SLinus Torvalds I have no idea was this bicycle invented before me, 8491da177e4SLinus Torvalds so that I had to set ARPHRD_IPGRE to a random value. 8501da177e4SLinus Torvalds I have an impression, that Cisco could make something similar, 8511da177e4SLinus Torvalds but this feature is apparently missing in IOS<=11.2(8). 8521da177e4SLinus Torvalds 8531da177e4SLinus Torvalds I set up 10.66.66/24 and fec0:6666:6666::0/96 as virtual networks 8541da177e4SLinus Torvalds with broadcast 224.66.66.66. If you have access to mbone, play with me :-) 8551da177e4SLinus Torvalds 8561da177e4SLinus Torvalds ping -t 255 224.66.66.66 8571da177e4SLinus Torvalds 8581da177e4SLinus Torvalds If nobody answers, mbone does not work. 8591da177e4SLinus Torvalds 8601da177e4SLinus Torvalds ip tunnel add Universe mode gre remote 224.66.66.66 local <Your_real_addr> ttl 255 8611da177e4SLinus Torvalds ip addr add 10.66.66.<somewhat>/24 dev Universe 8621da177e4SLinus Torvalds ifconfig Universe up 8631da177e4SLinus Torvalds ifconfig Universe add fe80::<Your_real_addr>/10 8641da177e4SLinus Torvalds ifconfig Universe add fec0:6666:6666::<Your_real_addr>/96 8651da177e4SLinus Torvalds ftp 10.66.66.66 8661da177e4SLinus Torvalds ... 8671da177e4SLinus Torvalds ftp fec0:6666:6666::193.233.7.65 8681da177e4SLinus Torvalds ... 8691da177e4SLinus Torvalds */ 8703b04dddeSStephen Hemminger static int ipgre_header(struct sk_buff *skb, struct net_device *dev, 8713b04dddeSStephen Hemminger unsigned short type, 8721507850bSEric Dumazet const void *daddr, const void *saddr, unsigned int len) 8731da177e4SLinus Torvalds { 8742941a486SPatrick McHardy struct ip_tunnel *t = netdev_priv(dev); 875c5441932SPravin B Shelar struct iphdr *iph; 876c5441932SPravin B Shelar struct gre_base_hdr *greh; 877c5441932SPravin B Shelar 878d58ff351SJohannes Berg iph = skb_push(skb, t->hlen + sizeof(*iph)); 879c5441932SPravin B Shelar greh = (struct gre_base_hdr *)(iph+1); 88095f5c64cSTom Herbert greh->flags = gre_tnl_flags_to_gre_flags(t->parms.o_flags); 881c5441932SPravin B Shelar greh->protocol = htons(type); 8821da177e4SLinus Torvalds 8831da177e4SLinus Torvalds memcpy(iph, &t->parms.iph, sizeof(struct iphdr)); 8841da177e4SLinus Torvalds 885c5441932SPravin B Shelar /* Set the source hardware address. */ 8861da177e4SLinus Torvalds if (saddr) 8871da177e4SLinus Torvalds memcpy(&iph->saddr, saddr, 4); 8886d55cb91STimo Teräs if (daddr) 8891da177e4SLinus Torvalds memcpy(&iph->daddr, daddr, 4); 8906d55cb91STimo Teräs if (iph->daddr) 89177a482bdSTimo Teräs return t->hlen + sizeof(*iph); 8921da177e4SLinus Torvalds 893c5441932SPravin B Shelar return -(t->hlen + sizeof(*iph)); 8941da177e4SLinus Torvalds } 8951da177e4SLinus Torvalds 8966a5f44d7STimo Teras static int ipgre_header_parse(const struct sk_buff *skb, unsigned char *haddr) 8976a5f44d7STimo Teras { 898b71d1d42SEric Dumazet const struct iphdr *iph = (const struct iphdr *) skb_mac_header(skb); 8996a5f44d7STimo Teras memcpy(haddr, &iph->saddr, 4); 9006a5f44d7STimo Teras return 4; 9016a5f44d7STimo Teras } 9026a5f44d7STimo Teras 9033b04dddeSStephen Hemminger static const struct header_ops ipgre_header_ops = { 9043b04dddeSStephen Hemminger .create = ipgre_header, 9056a5f44d7STimo Teras .parse = ipgre_header_parse, 9063b04dddeSStephen Hemminger }; 9073b04dddeSStephen Hemminger 9086a5f44d7STimo Teras #ifdef CONFIG_NET_IPGRE_BROADCAST 9091da177e4SLinus Torvalds static int ipgre_open(struct net_device *dev) 9101da177e4SLinus Torvalds { 9112941a486SPatrick McHardy struct ip_tunnel *t = netdev_priv(dev); 9121da177e4SLinus Torvalds 913f97c1e0cSJoe Perches if (ipv4_is_multicast(t->parms.iph.daddr)) { 914cbb1e85fSDavid S. Miller struct flowi4 fl4; 915cbb1e85fSDavid S. Miller struct rtable *rt; 916cbb1e85fSDavid S. Miller 917b57708adSNicolas Dichtel rt = ip_route_output_gre(t->net, &fl4, 91878fbfd8aSDavid S. Miller t->parms.iph.daddr, 91978fbfd8aSDavid S. Miller t->parms.iph.saddr, 92078fbfd8aSDavid S. Miller t->parms.o_key, 92178fbfd8aSDavid S. Miller RT_TOS(t->parms.iph.tos), 92278fbfd8aSDavid S. Miller t->parms.link); 923b23dd4feSDavid S. Miller if (IS_ERR(rt)) 9241da177e4SLinus Torvalds return -EADDRNOTAVAIL; 925d8d1f30bSChangli Gao dev = rt->dst.dev; 9261da177e4SLinus Torvalds ip_rt_put(rt); 92751456b29SIan Morris if (!__in_dev_get_rtnl(dev)) 9281da177e4SLinus Torvalds return -EADDRNOTAVAIL; 9291da177e4SLinus Torvalds t->mlink = dev->ifindex; 930e5ed6399SHerbert Xu ip_mc_inc_group(__in_dev_get_rtnl(dev), t->parms.iph.daddr); 9311da177e4SLinus Torvalds } 9321da177e4SLinus Torvalds return 0; 9331da177e4SLinus Torvalds } 9341da177e4SLinus Torvalds 9351da177e4SLinus Torvalds static int ipgre_close(struct net_device *dev) 9361da177e4SLinus Torvalds { 9372941a486SPatrick McHardy struct ip_tunnel *t = netdev_priv(dev); 938b8c26a33SStephen Hemminger 939f97c1e0cSJoe Perches if (ipv4_is_multicast(t->parms.iph.daddr) && t->mlink) { 9407fee0ca2SDenis V. Lunev struct in_device *in_dev; 941b57708adSNicolas Dichtel in_dev = inetdev_by_index(t->net, t->mlink); 9428723e1b4SEric Dumazet if (in_dev) 9431da177e4SLinus Torvalds ip_mc_dec_group(in_dev, t->parms.iph.daddr); 9441da177e4SLinus Torvalds } 9451da177e4SLinus Torvalds return 0; 9461da177e4SLinus Torvalds } 9471da177e4SLinus Torvalds #endif 9481da177e4SLinus Torvalds 949b8c26a33SStephen Hemminger static const struct net_device_ops ipgre_netdev_ops = { 950b8c26a33SStephen Hemminger .ndo_init = ipgre_tunnel_init, 951c5441932SPravin B Shelar .ndo_uninit = ip_tunnel_uninit, 952b8c26a33SStephen Hemminger #ifdef CONFIG_NET_IPGRE_BROADCAST 953b8c26a33SStephen Hemminger .ndo_open = ipgre_open, 954b8c26a33SStephen Hemminger .ndo_stop = ipgre_close, 955b8c26a33SStephen Hemminger #endif 956c5441932SPravin B Shelar .ndo_start_xmit = ipgre_xmit, 957b8c26a33SStephen Hemminger .ndo_do_ioctl = ipgre_tunnel_ioctl, 958c5441932SPravin B Shelar .ndo_change_mtu = ip_tunnel_change_mtu, 959c5441932SPravin B Shelar .ndo_get_stats64 = ip_tunnel_get_stats64, 9601e99584bSNicolas Dichtel .ndo_get_iflink = ip_tunnel_get_iflink, 961b8c26a33SStephen Hemminger }; 962b8c26a33SStephen Hemminger 9636b78f16eSEric Dumazet #define GRE_FEATURES (NETIF_F_SG | \ 9646b78f16eSEric Dumazet NETIF_F_FRAGLIST | \ 9656b78f16eSEric Dumazet NETIF_F_HIGHDMA | \ 9666b78f16eSEric Dumazet NETIF_F_HW_CSUM) 9676b78f16eSEric Dumazet 9681da177e4SLinus Torvalds static void ipgre_tunnel_setup(struct net_device *dev) 9691da177e4SLinus Torvalds { 970b8c26a33SStephen Hemminger dev->netdev_ops = &ipgre_netdev_ops; 9715a455275SNicolas Dichtel dev->type = ARPHRD_IPGRE; 972c5441932SPravin B Shelar ip_tunnel_setup(dev, ipgre_net_id); 973c5441932SPravin B Shelar } 9741da177e4SLinus Torvalds 975c5441932SPravin B Shelar static void __gre_tunnel_init(struct net_device *dev) 976c5441932SPravin B Shelar { 977c5441932SPravin B Shelar struct ip_tunnel *tunnel; 9784565e991STom Herbert int t_hlen; 979c5441932SPravin B Shelar 980c5441932SPravin B Shelar tunnel = netdev_priv(dev); 98195f5c64cSTom Herbert tunnel->tun_hlen = gre_calc_hlen(tunnel->parms.o_flags); 982c5441932SPravin B Shelar tunnel->parms.iph.protocol = IPPROTO_GRE; 983c5441932SPravin B Shelar 9844565e991STom Herbert tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen; 9854565e991STom Herbert 9864565e991STom Herbert t_hlen = tunnel->hlen + sizeof(struct iphdr); 9874565e991STom Herbert 9884565e991STom Herbert dev->needed_headroom = LL_MAX_HEADER + t_hlen + 4; 9894565e991STom Herbert dev->mtu = ETH_DATA_LEN - t_hlen - 4; 9906b78f16eSEric Dumazet 991b57708adSNicolas Dichtel dev->features |= GRE_FEATURES; 9926b78f16eSEric Dumazet dev->hw_features |= GRE_FEATURES; 993c5441932SPravin B Shelar 994c5441932SPravin B Shelar if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) { 995a0ca153fSAlexander Duyck /* TCP offload with GRE SEQ is not supported, nor 996a0ca153fSAlexander Duyck * can we support 2 levels of outer headers requiring 997a0ca153fSAlexander Duyck * an update. 998a0ca153fSAlexander Duyck */ 999a0ca153fSAlexander Duyck if (!(tunnel->parms.o_flags & TUNNEL_CSUM) || 1000a0ca153fSAlexander Duyck (tunnel->encap.type == TUNNEL_ENCAP_NONE)) { 1001c5441932SPravin B Shelar dev->features |= NETIF_F_GSO_SOFTWARE; 1002c5441932SPravin B Shelar dev->hw_features |= NETIF_F_GSO_SOFTWARE; 1003a0ca153fSAlexander Duyck } 1004a0ca153fSAlexander Duyck 1005c5441932SPravin B Shelar /* Can use a lockless transmit, unless we generate 1006c5441932SPravin B Shelar * output sequences 1007c5441932SPravin B Shelar */ 1008c5441932SPravin B Shelar dev->features |= NETIF_F_LLTX; 1009c5441932SPravin B Shelar } 10101da177e4SLinus Torvalds } 10111da177e4SLinus Torvalds 10121da177e4SLinus Torvalds static int ipgre_tunnel_init(struct net_device *dev) 10131da177e4SLinus Torvalds { 1014c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 1015c5441932SPravin B Shelar struct iphdr *iph = &tunnel->parms.iph; 10161da177e4SLinus Torvalds 1017c5441932SPravin B Shelar __gre_tunnel_init(dev); 10181da177e4SLinus Torvalds 1019c5441932SPravin B Shelar memcpy(dev->dev_addr, &iph->saddr, 4); 1020c5441932SPravin B Shelar memcpy(dev->broadcast, &iph->daddr, 4); 10211da177e4SLinus Torvalds 1022c5441932SPravin B Shelar dev->flags = IFF_NOARP; 102302875878SEric Dumazet netif_keep_dst(dev); 1024c5441932SPravin B Shelar dev->addr_len = 4; 10251da177e4SLinus Torvalds 1026a64b04d8SJiri Benc if (iph->daddr && !tunnel->collect_md) { 10271da177e4SLinus Torvalds #ifdef CONFIG_NET_IPGRE_BROADCAST 1028f97c1e0cSJoe Perches if (ipv4_is_multicast(iph->daddr)) { 10291da177e4SLinus Torvalds if (!iph->saddr) 10301da177e4SLinus Torvalds return -EINVAL; 10311da177e4SLinus Torvalds dev->flags = IFF_BROADCAST; 10323b04dddeSStephen Hemminger dev->header_ops = &ipgre_header_ops; 10331da177e4SLinus Torvalds } 10341da177e4SLinus Torvalds #endif 1035a64b04d8SJiri Benc } else if (!tunnel->collect_md) { 10366a5f44d7STimo Teras dev->header_ops = &ipgre_header_ops; 1037a64b04d8SJiri Benc } 10381da177e4SLinus Torvalds 1039c5441932SPravin B Shelar return ip_tunnel_init(dev); 104060769a5dSEric Dumazet } 104160769a5dSEric Dumazet 10429f57c67cSPravin B Shelar static const struct gre_protocol ipgre_protocol = { 10439f57c67cSPravin B Shelar .handler = gre_rcv, 10449f57c67cSPravin B Shelar .err_handler = gre_err, 10451da177e4SLinus Torvalds }; 10461da177e4SLinus Torvalds 10472c8c1e72SAlexey Dobriyan static int __net_init ipgre_init_net(struct net *net) 104859a4c759SPavel Emelyanov { 1049c5441932SPravin B Shelar return ip_tunnel_init_net(net, ipgre_net_id, &ipgre_link_ops, NULL); 105059a4c759SPavel Emelyanov } 105159a4c759SPavel Emelyanov 105264bc1781SEric Dumazet static void __net_exit ipgre_exit_batch_net(struct list_head *list_net) 105359a4c759SPavel Emelyanov { 105464bc1781SEric Dumazet ip_tunnel_delete_nets(list_net, ipgre_net_id, &ipgre_link_ops); 105559a4c759SPavel Emelyanov } 105659a4c759SPavel Emelyanov 105759a4c759SPavel Emelyanov static struct pernet_operations ipgre_net_ops = { 105859a4c759SPavel Emelyanov .init = ipgre_init_net, 105964bc1781SEric Dumazet .exit_batch = ipgre_exit_batch_net, 1060cfb8fbf2SEric W. Biederman .id = &ipgre_net_id, 1061c5441932SPravin B Shelar .size = sizeof(struct ip_tunnel_net), 106259a4c759SPavel Emelyanov }; 10631da177e4SLinus Torvalds 1064a8b8a889SMatthias Schiffer static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[], 1065a8b8a889SMatthias Schiffer struct netlink_ext_ack *extack) 1066c19e654dSHerbert Xu { 1067c19e654dSHerbert Xu __be16 flags; 1068c19e654dSHerbert Xu 1069c19e654dSHerbert Xu if (!data) 1070c19e654dSHerbert Xu return 0; 1071c19e654dSHerbert Xu 1072c19e654dSHerbert Xu flags = 0; 1073c19e654dSHerbert Xu if (data[IFLA_GRE_IFLAGS]) 1074c19e654dSHerbert Xu flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]); 1075c19e654dSHerbert Xu if (data[IFLA_GRE_OFLAGS]) 1076c19e654dSHerbert Xu flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]); 1077c19e654dSHerbert Xu if (flags & (GRE_VERSION|GRE_ROUTING)) 1078c19e654dSHerbert Xu return -EINVAL; 1079c19e654dSHerbert Xu 1080946b636fSJiri Benc if (data[IFLA_GRE_COLLECT_METADATA] && 1081946b636fSJiri Benc data[IFLA_GRE_ENCAP_TYPE] && 1082946b636fSJiri Benc nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]) != TUNNEL_ENCAP_NONE) 1083946b636fSJiri Benc return -EINVAL; 1084946b636fSJiri Benc 1085c19e654dSHerbert Xu return 0; 1086c19e654dSHerbert Xu } 1087c19e654dSHerbert Xu 1088a8b8a889SMatthias Schiffer static int ipgre_tap_validate(struct nlattr *tb[], struct nlattr *data[], 1089a8b8a889SMatthias Schiffer struct netlink_ext_ack *extack) 1090e1a80002SHerbert Xu { 1091e1a80002SHerbert Xu __be32 daddr; 1092e1a80002SHerbert Xu 1093e1a80002SHerbert Xu if (tb[IFLA_ADDRESS]) { 1094e1a80002SHerbert Xu if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) 1095e1a80002SHerbert Xu return -EINVAL; 1096e1a80002SHerbert Xu if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) 1097e1a80002SHerbert Xu return -EADDRNOTAVAIL; 1098e1a80002SHerbert Xu } 1099e1a80002SHerbert Xu 1100e1a80002SHerbert Xu if (!data) 1101e1a80002SHerbert Xu goto out; 1102e1a80002SHerbert Xu 1103e1a80002SHerbert Xu if (data[IFLA_GRE_REMOTE]) { 1104e1a80002SHerbert Xu memcpy(&daddr, nla_data(data[IFLA_GRE_REMOTE]), 4); 1105e1a80002SHerbert Xu if (!daddr) 1106e1a80002SHerbert Xu return -EINVAL; 1107e1a80002SHerbert Xu } 1108e1a80002SHerbert Xu 1109e1a80002SHerbert Xu out: 1110a8b8a889SMatthias Schiffer return ipgre_tunnel_validate(tb, data, extack); 1111e1a80002SHerbert Xu } 1112e1a80002SHerbert Xu 111384e54fe0SWilliam Tu static int erspan_validate(struct nlattr *tb[], struct nlattr *data[], 111484e54fe0SWilliam Tu struct netlink_ext_ack *extack) 111584e54fe0SWilliam Tu { 111684e54fe0SWilliam Tu __be16 flags = 0; 111784e54fe0SWilliam Tu int ret; 111884e54fe0SWilliam Tu 111984e54fe0SWilliam Tu if (!data) 112084e54fe0SWilliam Tu return 0; 112184e54fe0SWilliam Tu 112284e54fe0SWilliam Tu ret = ipgre_tap_validate(tb, data, extack); 112384e54fe0SWilliam Tu if (ret) 112484e54fe0SWilliam Tu return ret; 112584e54fe0SWilliam Tu 112684e54fe0SWilliam Tu /* ERSPAN should only have GRE sequence and key flag */ 11271a66a836SWilliam Tu if (data[IFLA_GRE_OFLAGS]) 112884e54fe0SWilliam Tu flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]); 11291a66a836SWilliam Tu if (data[IFLA_GRE_IFLAGS]) 113084e54fe0SWilliam Tu flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]); 11311a66a836SWilliam Tu if (!data[IFLA_GRE_COLLECT_METADATA] && 11321a66a836SWilliam Tu flags != (GRE_SEQ | GRE_KEY)) 113384e54fe0SWilliam Tu return -EINVAL; 113484e54fe0SWilliam Tu 113584e54fe0SWilliam Tu /* ERSPAN Session ID only has 10-bit. Since we reuse 113684e54fe0SWilliam Tu * 32-bit key field as ID, check it's range. 113784e54fe0SWilliam Tu */ 113884e54fe0SWilliam Tu if (data[IFLA_GRE_IKEY] && 113984e54fe0SWilliam Tu (ntohl(nla_get_be32(data[IFLA_GRE_IKEY])) & ~ID_MASK)) 114084e54fe0SWilliam Tu return -EINVAL; 114184e54fe0SWilliam Tu 114284e54fe0SWilliam Tu if (data[IFLA_GRE_OKEY] && 114384e54fe0SWilliam Tu (ntohl(nla_get_be32(data[IFLA_GRE_OKEY])) & ~ID_MASK)) 114484e54fe0SWilliam Tu return -EINVAL; 114584e54fe0SWilliam Tu 114684e54fe0SWilliam Tu return 0; 114784e54fe0SWilliam Tu } 114884e54fe0SWilliam Tu 114922a59be8SPhilip Prindeville static int ipgre_netlink_parms(struct net_device *dev, 11502e15ea39SPravin B Shelar struct nlattr *data[], 11512e15ea39SPravin B Shelar struct nlattr *tb[], 11529830ad4cSCraig Gallek struct ip_tunnel_parm *parms, 11539830ad4cSCraig Gallek __u32 *fwmark) 1154c19e654dSHerbert Xu { 115522a59be8SPhilip Prindeville struct ip_tunnel *t = netdev_priv(dev); 115622a59be8SPhilip Prindeville 11577bb82d92SHerbert Xu memset(parms, 0, sizeof(*parms)); 1158c19e654dSHerbert Xu 1159c19e654dSHerbert Xu parms->iph.protocol = IPPROTO_GRE; 1160c19e654dSHerbert Xu 1161c19e654dSHerbert Xu if (!data) 116222a59be8SPhilip Prindeville return 0; 1163c19e654dSHerbert Xu 1164c19e654dSHerbert Xu if (data[IFLA_GRE_LINK]) 1165c19e654dSHerbert Xu parms->link = nla_get_u32(data[IFLA_GRE_LINK]); 1166c19e654dSHerbert Xu 1167c19e654dSHerbert Xu if (data[IFLA_GRE_IFLAGS]) 1168c5441932SPravin B Shelar parms->i_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_IFLAGS])); 1169c19e654dSHerbert Xu 1170c19e654dSHerbert Xu if (data[IFLA_GRE_OFLAGS]) 1171c5441932SPravin B Shelar parms->o_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_OFLAGS])); 1172c19e654dSHerbert Xu 1173c19e654dSHerbert Xu if (data[IFLA_GRE_IKEY]) 1174c19e654dSHerbert Xu parms->i_key = nla_get_be32(data[IFLA_GRE_IKEY]); 1175c19e654dSHerbert Xu 1176c19e654dSHerbert Xu if (data[IFLA_GRE_OKEY]) 1177c19e654dSHerbert Xu parms->o_key = nla_get_be32(data[IFLA_GRE_OKEY]); 1178c19e654dSHerbert Xu 1179c19e654dSHerbert Xu if (data[IFLA_GRE_LOCAL]) 118067b61f6cSJiri Benc parms->iph.saddr = nla_get_in_addr(data[IFLA_GRE_LOCAL]); 1181c19e654dSHerbert Xu 1182c19e654dSHerbert Xu if (data[IFLA_GRE_REMOTE]) 118367b61f6cSJiri Benc parms->iph.daddr = nla_get_in_addr(data[IFLA_GRE_REMOTE]); 1184c19e654dSHerbert Xu 1185c19e654dSHerbert Xu if (data[IFLA_GRE_TTL]) 1186c19e654dSHerbert Xu parms->iph.ttl = nla_get_u8(data[IFLA_GRE_TTL]); 1187c19e654dSHerbert Xu 1188c19e654dSHerbert Xu if (data[IFLA_GRE_TOS]) 1189c19e654dSHerbert Xu parms->iph.tos = nla_get_u8(data[IFLA_GRE_TOS]); 1190c19e654dSHerbert Xu 119122a59be8SPhilip Prindeville if (!data[IFLA_GRE_PMTUDISC] || nla_get_u8(data[IFLA_GRE_PMTUDISC])) { 119222a59be8SPhilip Prindeville if (t->ignore_df) 119322a59be8SPhilip Prindeville return -EINVAL; 1194c19e654dSHerbert Xu parms->iph.frag_off = htons(IP_DF); 119522a59be8SPhilip Prindeville } 11962e15ea39SPravin B Shelar 11972e15ea39SPravin B Shelar if (data[IFLA_GRE_COLLECT_METADATA]) { 11982e15ea39SPravin B Shelar t->collect_md = true; 1199e271c7b4SJiri Benc if (dev->type == ARPHRD_IPGRE) 1200e271c7b4SJiri Benc dev->type = ARPHRD_NONE; 12012e15ea39SPravin B Shelar } 120222a59be8SPhilip Prindeville 120322a59be8SPhilip Prindeville if (data[IFLA_GRE_IGNORE_DF]) { 120422a59be8SPhilip Prindeville if (nla_get_u8(data[IFLA_GRE_IGNORE_DF]) 120522a59be8SPhilip Prindeville && (parms->iph.frag_off & htons(IP_DF))) 120622a59be8SPhilip Prindeville return -EINVAL; 120722a59be8SPhilip Prindeville t->ignore_df = !!nla_get_u8(data[IFLA_GRE_IGNORE_DF]); 120822a59be8SPhilip Prindeville } 120922a59be8SPhilip Prindeville 12109830ad4cSCraig Gallek if (data[IFLA_GRE_FWMARK]) 12119830ad4cSCraig Gallek *fwmark = nla_get_u32(data[IFLA_GRE_FWMARK]); 12129830ad4cSCraig Gallek 1213f551c91dSWilliam Tu if (data[IFLA_GRE_ERSPAN_VER]) { 1214f551c91dSWilliam Tu t->erspan_ver = nla_get_u8(data[IFLA_GRE_ERSPAN_VER]); 1215f551c91dSWilliam Tu 1216f551c91dSWilliam Tu if (t->erspan_ver != 1 && t->erspan_ver != 2) 1217f551c91dSWilliam Tu return -EINVAL; 1218f551c91dSWilliam Tu } 1219f551c91dSWilliam Tu 1220f551c91dSWilliam Tu if (t->erspan_ver == 1) { 122184e54fe0SWilliam Tu if (data[IFLA_GRE_ERSPAN_INDEX]) { 122284e54fe0SWilliam Tu t->index = nla_get_u32(data[IFLA_GRE_ERSPAN_INDEX]); 122384e54fe0SWilliam Tu if (t->index & ~INDEX_MASK) 122484e54fe0SWilliam Tu return -EINVAL; 122584e54fe0SWilliam Tu } 1226f551c91dSWilliam Tu } else if (t->erspan_ver == 2) { 1227f551c91dSWilliam Tu if (data[IFLA_GRE_ERSPAN_DIR]) { 1228f551c91dSWilliam Tu t->dir = nla_get_u8(data[IFLA_GRE_ERSPAN_DIR]); 1229f551c91dSWilliam Tu if (t->dir & ~(DIR_MASK >> DIR_OFFSET)) 1230f551c91dSWilliam Tu return -EINVAL; 1231f551c91dSWilliam Tu } 1232f551c91dSWilliam Tu if (data[IFLA_GRE_ERSPAN_HWID]) { 1233f551c91dSWilliam Tu t->hwid = nla_get_u16(data[IFLA_GRE_ERSPAN_HWID]); 1234f551c91dSWilliam Tu if (t->hwid & ~(HWID_MASK >> HWID_OFFSET)) 1235f551c91dSWilliam Tu return -EINVAL; 1236f551c91dSWilliam Tu } 1237f551c91dSWilliam Tu } 123884e54fe0SWilliam Tu 123922a59be8SPhilip Prindeville return 0; 1240c19e654dSHerbert Xu } 1241c19e654dSHerbert Xu 12424565e991STom Herbert /* This function returns true when ENCAP attributes are present in the nl msg */ 12434565e991STom Herbert static bool ipgre_netlink_encap_parms(struct nlattr *data[], 12444565e991STom Herbert struct ip_tunnel_encap *ipencap) 12454565e991STom Herbert { 12464565e991STom Herbert bool ret = false; 12474565e991STom Herbert 12484565e991STom Herbert memset(ipencap, 0, sizeof(*ipencap)); 12494565e991STom Herbert 12504565e991STom Herbert if (!data) 12514565e991STom Herbert return ret; 12524565e991STom Herbert 12534565e991STom Herbert if (data[IFLA_GRE_ENCAP_TYPE]) { 12544565e991STom Herbert ret = true; 12554565e991STom Herbert ipencap->type = nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]); 12564565e991STom Herbert } 12574565e991STom Herbert 12584565e991STom Herbert if (data[IFLA_GRE_ENCAP_FLAGS]) { 12594565e991STom Herbert ret = true; 12604565e991STom Herbert ipencap->flags = nla_get_u16(data[IFLA_GRE_ENCAP_FLAGS]); 12614565e991STom Herbert } 12624565e991STom Herbert 12634565e991STom Herbert if (data[IFLA_GRE_ENCAP_SPORT]) { 12644565e991STom Herbert ret = true; 12653e97fa70SSabrina Dubroca ipencap->sport = nla_get_be16(data[IFLA_GRE_ENCAP_SPORT]); 12664565e991STom Herbert } 12674565e991STom Herbert 12684565e991STom Herbert if (data[IFLA_GRE_ENCAP_DPORT]) { 12694565e991STom Herbert ret = true; 12703e97fa70SSabrina Dubroca ipencap->dport = nla_get_be16(data[IFLA_GRE_ENCAP_DPORT]); 12714565e991STom Herbert } 12724565e991STom Herbert 12734565e991STom Herbert return ret; 12744565e991STom Herbert } 12754565e991STom Herbert 1276c5441932SPravin B Shelar static int gre_tap_init(struct net_device *dev) 1277e1a80002SHerbert Xu { 1278c5441932SPravin B Shelar __gre_tunnel_init(dev); 1279bec94d43Sstephen hemminger dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; 1280d51711c0SXin Long netif_keep_dst(dev); 1281e1a80002SHerbert Xu 1282c5441932SPravin B Shelar return ip_tunnel_init(dev); 1283e1a80002SHerbert Xu } 1284e1a80002SHerbert Xu 1285c5441932SPravin B Shelar static const struct net_device_ops gre_tap_netdev_ops = { 1286c5441932SPravin B Shelar .ndo_init = gre_tap_init, 1287c5441932SPravin B Shelar .ndo_uninit = ip_tunnel_uninit, 1288c5441932SPravin B Shelar .ndo_start_xmit = gre_tap_xmit, 1289b8c26a33SStephen Hemminger .ndo_set_mac_address = eth_mac_addr, 1290b8c26a33SStephen Hemminger .ndo_validate_addr = eth_validate_addr, 1291c5441932SPravin B Shelar .ndo_change_mtu = ip_tunnel_change_mtu, 1292c5441932SPravin B Shelar .ndo_get_stats64 = ip_tunnel_get_stats64, 12931e99584bSNicolas Dichtel .ndo_get_iflink = ip_tunnel_get_iflink, 1294fc4099f1SPravin B Shelar .ndo_fill_metadata_dst = gre_fill_metadata_dst, 1295b8c26a33SStephen Hemminger }; 1296b8c26a33SStephen Hemminger 129784e54fe0SWilliam Tu static int erspan_tunnel_init(struct net_device *dev) 129884e54fe0SWilliam Tu { 129984e54fe0SWilliam Tu struct ip_tunnel *tunnel = netdev_priv(dev); 130084e54fe0SWilliam Tu int t_hlen; 130184e54fe0SWilliam Tu 130284e54fe0SWilliam Tu tunnel->tun_hlen = 8; 130384e54fe0SWilliam Tu tunnel->parms.iph.protocol = IPPROTO_GRE; 1304c122fda2SXin Long tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen + 1305f551c91dSWilliam Tu erspan_hdr_len(tunnel->erspan_ver); 1306c122fda2SXin Long t_hlen = tunnel->hlen + sizeof(struct iphdr); 130784e54fe0SWilliam Tu 130884e54fe0SWilliam Tu dev->needed_headroom = LL_MAX_HEADER + t_hlen + 4; 130984e54fe0SWilliam Tu dev->mtu = ETH_DATA_LEN - t_hlen - 4; 131084e54fe0SWilliam Tu dev->features |= GRE_FEATURES; 131184e54fe0SWilliam Tu dev->hw_features |= GRE_FEATURES; 131284e54fe0SWilliam Tu dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; 1313c84bed44SXin Long netif_keep_dst(dev); 131484e54fe0SWilliam Tu 131584e54fe0SWilliam Tu return ip_tunnel_init(dev); 131684e54fe0SWilliam Tu } 131784e54fe0SWilliam Tu 131884e54fe0SWilliam Tu static const struct net_device_ops erspan_netdev_ops = { 131984e54fe0SWilliam Tu .ndo_init = erspan_tunnel_init, 132084e54fe0SWilliam Tu .ndo_uninit = ip_tunnel_uninit, 132184e54fe0SWilliam Tu .ndo_start_xmit = erspan_xmit, 132284e54fe0SWilliam Tu .ndo_set_mac_address = eth_mac_addr, 132384e54fe0SWilliam Tu .ndo_validate_addr = eth_validate_addr, 132484e54fe0SWilliam Tu .ndo_change_mtu = ip_tunnel_change_mtu, 132584e54fe0SWilliam Tu .ndo_get_stats64 = ip_tunnel_get_stats64, 132684e54fe0SWilliam Tu .ndo_get_iflink = ip_tunnel_get_iflink, 132784e54fe0SWilliam Tu .ndo_fill_metadata_dst = gre_fill_metadata_dst, 132884e54fe0SWilliam Tu }; 132984e54fe0SWilliam Tu 1330e1a80002SHerbert Xu static void ipgre_tap_setup(struct net_device *dev) 1331e1a80002SHerbert Xu { 1332e1a80002SHerbert Xu ether_setup(dev); 1333c5441932SPravin B Shelar dev->netdev_ops = &gre_tap_netdev_ops; 1334d13b161cSJiri Benc dev->priv_flags &= ~IFF_TX_SKB_SHARING; 1335f8c1b7ceSstephen hemminger dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; 1336c5441932SPravin B Shelar ip_tunnel_setup(dev, gre_tap_net_id); 1337e1a80002SHerbert Xu } 1338e1a80002SHerbert Xu 1339c5441932SPravin B Shelar static int ipgre_newlink(struct net *src_net, struct net_device *dev, 13407a3f4a18SMatthias Schiffer struct nlattr *tb[], struct nlattr *data[], 13417a3f4a18SMatthias Schiffer struct netlink_ext_ack *extack) 1342c19e654dSHerbert Xu { 1343c5441932SPravin B Shelar struct ip_tunnel_parm p; 13444565e991STom Herbert struct ip_tunnel_encap ipencap; 13459830ad4cSCraig Gallek __u32 fwmark = 0; 134622a59be8SPhilip Prindeville int err; 13474565e991STom Herbert 13484565e991STom Herbert if (ipgre_netlink_encap_parms(data, &ipencap)) { 13494565e991STom Herbert struct ip_tunnel *t = netdev_priv(dev); 135022a59be8SPhilip Prindeville err = ip_tunnel_encap_setup(t, &ipencap); 13514565e991STom Herbert 13524565e991STom Herbert if (err < 0) 13534565e991STom Herbert return err; 13544565e991STom Herbert } 1355c19e654dSHerbert Xu 13569830ad4cSCraig Gallek err = ipgre_netlink_parms(dev, data, tb, &p, &fwmark); 135722a59be8SPhilip Prindeville if (err < 0) 135822a59be8SPhilip Prindeville return err; 13599830ad4cSCraig Gallek return ip_tunnel_newlink(dev, tb, &p, fwmark); 1360c19e654dSHerbert Xu } 1361c19e654dSHerbert Xu 1362c19e654dSHerbert Xu static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[], 1363ad744b22SMatthias Schiffer struct nlattr *data[], 1364ad744b22SMatthias Schiffer struct netlink_ext_ack *extack) 1365c19e654dSHerbert Xu { 13669830ad4cSCraig Gallek struct ip_tunnel *t = netdev_priv(dev); 13674565e991STom Herbert struct ip_tunnel_encap ipencap; 13689830ad4cSCraig Gallek __u32 fwmark = t->fwmark; 1369dd9d598cSXin Long struct ip_tunnel_parm p; 137022a59be8SPhilip Prindeville int err; 13714565e991STom Herbert 13724565e991STom Herbert if (ipgre_netlink_encap_parms(data, &ipencap)) { 137322a59be8SPhilip Prindeville err = ip_tunnel_encap_setup(t, &ipencap); 13744565e991STom Herbert 13754565e991STom Herbert if (err < 0) 13764565e991STom Herbert return err; 13774565e991STom Herbert } 1378c19e654dSHerbert Xu 13799830ad4cSCraig Gallek err = ipgre_netlink_parms(dev, data, tb, &p, &fwmark); 138022a59be8SPhilip Prindeville if (err < 0) 138122a59be8SPhilip Prindeville return err; 1382dd9d598cSXin Long 1383dd9d598cSXin Long err = ip_tunnel_changelink(dev, tb, &p, fwmark); 1384dd9d598cSXin Long if (err < 0) 1385dd9d598cSXin Long return err; 1386dd9d598cSXin Long 1387dd9d598cSXin Long t->parms.i_flags = p.i_flags; 1388dd9d598cSXin Long t->parms.o_flags = p.o_flags; 1389dd9d598cSXin Long 1390dd9d598cSXin Long if (strcmp(dev->rtnl_link_ops->kind, "erspan")) 1391dd9d598cSXin Long ipgre_link_update(dev, !tb[IFLA_MTU]); 1392dd9d598cSXin Long 1393dd9d598cSXin Long return 0; 1394c19e654dSHerbert Xu } 1395c19e654dSHerbert Xu 1396c19e654dSHerbert Xu static size_t ipgre_get_size(const struct net_device *dev) 1397c19e654dSHerbert Xu { 1398c19e654dSHerbert Xu return 1399c19e654dSHerbert Xu /* IFLA_GRE_LINK */ 1400c19e654dSHerbert Xu nla_total_size(4) + 1401c19e654dSHerbert Xu /* IFLA_GRE_IFLAGS */ 1402c19e654dSHerbert Xu nla_total_size(2) + 1403c19e654dSHerbert Xu /* IFLA_GRE_OFLAGS */ 1404c19e654dSHerbert Xu nla_total_size(2) + 1405c19e654dSHerbert Xu /* IFLA_GRE_IKEY */ 1406c19e654dSHerbert Xu nla_total_size(4) + 1407c19e654dSHerbert Xu /* IFLA_GRE_OKEY */ 1408c19e654dSHerbert Xu nla_total_size(4) + 1409c19e654dSHerbert Xu /* IFLA_GRE_LOCAL */ 1410c19e654dSHerbert Xu nla_total_size(4) + 1411c19e654dSHerbert Xu /* IFLA_GRE_REMOTE */ 1412c19e654dSHerbert Xu nla_total_size(4) + 1413c19e654dSHerbert Xu /* IFLA_GRE_TTL */ 1414c19e654dSHerbert Xu nla_total_size(1) + 1415c19e654dSHerbert Xu /* IFLA_GRE_TOS */ 1416c19e654dSHerbert Xu nla_total_size(1) + 1417c19e654dSHerbert Xu /* IFLA_GRE_PMTUDISC */ 1418c19e654dSHerbert Xu nla_total_size(1) + 14194565e991STom Herbert /* IFLA_GRE_ENCAP_TYPE */ 14204565e991STom Herbert nla_total_size(2) + 14214565e991STom Herbert /* IFLA_GRE_ENCAP_FLAGS */ 14224565e991STom Herbert nla_total_size(2) + 14234565e991STom Herbert /* IFLA_GRE_ENCAP_SPORT */ 14244565e991STom Herbert nla_total_size(2) + 14254565e991STom Herbert /* IFLA_GRE_ENCAP_DPORT */ 14264565e991STom Herbert nla_total_size(2) + 14272e15ea39SPravin B Shelar /* IFLA_GRE_COLLECT_METADATA */ 14282e15ea39SPravin B Shelar nla_total_size(0) + 142922a59be8SPhilip Prindeville /* IFLA_GRE_IGNORE_DF */ 143022a59be8SPhilip Prindeville nla_total_size(1) + 14319830ad4cSCraig Gallek /* IFLA_GRE_FWMARK */ 14329830ad4cSCraig Gallek nla_total_size(4) + 143384e54fe0SWilliam Tu /* IFLA_GRE_ERSPAN_INDEX */ 143484e54fe0SWilliam Tu nla_total_size(4) + 1435f551c91dSWilliam Tu /* IFLA_GRE_ERSPAN_VER */ 1436f551c91dSWilliam Tu nla_total_size(1) + 1437f551c91dSWilliam Tu /* IFLA_GRE_ERSPAN_DIR */ 1438f551c91dSWilliam Tu nla_total_size(1) + 1439f551c91dSWilliam Tu /* IFLA_GRE_ERSPAN_HWID */ 1440f551c91dSWilliam Tu nla_total_size(2) + 1441c19e654dSHerbert Xu 0; 1442c19e654dSHerbert Xu } 1443c19e654dSHerbert Xu 1444c19e654dSHerbert Xu static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev) 1445c19e654dSHerbert Xu { 1446c19e654dSHerbert Xu struct ip_tunnel *t = netdev_priv(dev); 1447c19e654dSHerbert Xu struct ip_tunnel_parm *p = &t->parms; 1448c19e654dSHerbert Xu 1449f3756b79SDavid S. Miller if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) || 145095f5c64cSTom Herbert nla_put_be16(skb, IFLA_GRE_IFLAGS, 145195f5c64cSTom Herbert gre_tnl_flags_to_gre_flags(p->i_flags)) || 145295f5c64cSTom Herbert nla_put_be16(skb, IFLA_GRE_OFLAGS, 145395f5c64cSTom Herbert gre_tnl_flags_to_gre_flags(p->o_flags)) || 1454f3756b79SDavid S. Miller nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) || 1455f3756b79SDavid S. Miller nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) || 1456930345eaSJiri Benc nla_put_in_addr(skb, IFLA_GRE_LOCAL, p->iph.saddr) || 1457930345eaSJiri Benc nla_put_in_addr(skb, IFLA_GRE_REMOTE, p->iph.daddr) || 1458f3756b79SDavid S. Miller nla_put_u8(skb, IFLA_GRE_TTL, p->iph.ttl) || 1459f3756b79SDavid S. Miller nla_put_u8(skb, IFLA_GRE_TOS, p->iph.tos) || 1460f3756b79SDavid S. Miller nla_put_u8(skb, IFLA_GRE_PMTUDISC, 14619830ad4cSCraig Gallek !!(p->iph.frag_off & htons(IP_DF))) || 14629830ad4cSCraig Gallek nla_put_u32(skb, IFLA_GRE_FWMARK, t->fwmark)) 1463f3756b79SDavid S. Miller goto nla_put_failure; 14644565e991STom Herbert 14654565e991STom Herbert if (nla_put_u16(skb, IFLA_GRE_ENCAP_TYPE, 14664565e991STom Herbert t->encap.type) || 14673e97fa70SSabrina Dubroca nla_put_be16(skb, IFLA_GRE_ENCAP_SPORT, 14684565e991STom Herbert t->encap.sport) || 14693e97fa70SSabrina Dubroca nla_put_be16(skb, IFLA_GRE_ENCAP_DPORT, 14704565e991STom Herbert t->encap.dport) || 14714565e991STom Herbert nla_put_u16(skb, IFLA_GRE_ENCAP_FLAGS, 1472e1b2cb65STom Herbert t->encap.flags)) 14734565e991STom Herbert goto nla_put_failure; 14744565e991STom Herbert 147522a59be8SPhilip Prindeville if (nla_put_u8(skb, IFLA_GRE_IGNORE_DF, t->ignore_df)) 147622a59be8SPhilip Prindeville goto nla_put_failure; 147722a59be8SPhilip Prindeville 14782e15ea39SPravin B Shelar if (t->collect_md) { 14792e15ea39SPravin B Shelar if (nla_put_flag(skb, IFLA_GRE_COLLECT_METADATA)) 14802e15ea39SPravin B Shelar goto nla_put_failure; 14812e15ea39SPravin B Shelar } 14822e15ea39SPravin B Shelar 1483f551c91dSWilliam Tu if (nla_put_u8(skb, IFLA_GRE_ERSPAN_VER, t->erspan_ver)) 1484f551c91dSWilliam Tu goto nla_put_failure; 1485f551c91dSWilliam Tu 1486f551c91dSWilliam Tu if (t->erspan_ver == 1) { 148784e54fe0SWilliam Tu if (nla_put_u32(skb, IFLA_GRE_ERSPAN_INDEX, t->index)) 148884e54fe0SWilliam Tu goto nla_put_failure; 1489f551c91dSWilliam Tu } else if (t->erspan_ver == 2) { 1490f551c91dSWilliam Tu if (nla_put_u8(skb, IFLA_GRE_ERSPAN_DIR, t->dir)) 1491f551c91dSWilliam Tu goto nla_put_failure; 1492f551c91dSWilliam Tu if (nla_put_u16(skb, IFLA_GRE_ERSPAN_HWID, t->hwid)) 1493f551c91dSWilliam Tu goto nla_put_failure; 1494f551c91dSWilliam Tu } 149584e54fe0SWilliam Tu 1496c19e654dSHerbert Xu return 0; 1497c19e654dSHerbert Xu 1498c19e654dSHerbert Xu nla_put_failure: 1499c19e654dSHerbert Xu return -EMSGSIZE; 1500c19e654dSHerbert Xu } 1501c19e654dSHerbert Xu 150284e54fe0SWilliam Tu static void erspan_setup(struct net_device *dev) 150384e54fe0SWilliam Tu { 150484e54fe0SWilliam Tu ether_setup(dev); 150584e54fe0SWilliam Tu dev->netdev_ops = &erspan_netdev_ops; 150684e54fe0SWilliam Tu dev->priv_flags &= ~IFF_TX_SKB_SHARING; 150784e54fe0SWilliam Tu dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; 150884e54fe0SWilliam Tu ip_tunnel_setup(dev, erspan_net_id); 150984e54fe0SWilliam Tu } 151084e54fe0SWilliam Tu 1511c19e654dSHerbert Xu static const struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = { 1512c19e654dSHerbert Xu [IFLA_GRE_LINK] = { .type = NLA_U32 }, 1513c19e654dSHerbert Xu [IFLA_GRE_IFLAGS] = { .type = NLA_U16 }, 1514c19e654dSHerbert Xu [IFLA_GRE_OFLAGS] = { .type = NLA_U16 }, 1515c19e654dSHerbert Xu [IFLA_GRE_IKEY] = { .type = NLA_U32 }, 1516c19e654dSHerbert Xu [IFLA_GRE_OKEY] = { .type = NLA_U32 }, 15174d74f8baSPatrick McHardy [IFLA_GRE_LOCAL] = { .len = FIELD_SIZEOF(struct iphdr, saddr) }, 15184d74f8baSPatrick McHardy [IFLA_GRE_REMOTE] = { .len = FIELD_SIZEOF(struct iphdr, daddr) }, 1519c19e654dSHerbert Xu [IFLA_GRE_TTL] = { .type = NLA_U8 }, 1520c19e654dSHerbert Xu [IFLA_GRE_TOS] = { .type = NLA_U8 }, 1521c19e654dSHerbert Xu [IFLA_GRE_PMTUDISC] = { .type = NLA_U8 }, 15224565e991STom Herbert [IFLA_GRE_ENCAP_TYPE] = { .type = NLA_U16 }, 15234565e991STom Herbert [IFLA_GRE_ENCAP_FLAGS] = { .type = NLA_U16 }, 15244565e991STom Herbert [IFLA_GRE_ENCAP_SPORT] = { .type = NLA_U16 }, 15254565e991STom Herbert [IFLA_GRE_ENCAP_DPORT] = { .type = NLA_U16 }, 15262e15ea39SPravin B Shelar [IFLA_GRE_COLLECT_METADATA] = { .type = NLA_FLAG }, 152722a59be8SPhilip Prindeville [IFLA_GRE_IGNORE_DF] = { .type = NLA_U8 }, 15289830ad4cSCraig Gallek [IFLA_GRE_FWMARK] = { .type = NLA_U32 }, 152984e54fe0SWilliam Tu [IFLA_GRE_ERSPAN_INDEX] = { .type = NLA_U32 }, 1530f551c91dSWilliam Tu [IFLA_GRE_ERSPAN_VER] = { .type = NLA_U8 }, 1531f551c91dSWilliam Tu [IFLA_GRE_ERSPAN_DIR] = { .type = NLA_U8 }, 1532f551c91dSWilliam Tu [IFLA_GRE_ERSPAN_HWID] = { .type = NLA_U16 }, 1533c19e654dSHerbert Xu }; 1534c19e654dSHerbert Xu 1535c19e654dSHerbert Xu static struct rtnl_link_ops ipgre_link_ops __read_mostly = { 1536c19e654dSHerbert Xu .kind = "gre", 1537c19e654dSHerbert Xu .maxtype = IFLA_GRE_MAX, 1538c19e654dSHerbert Xu .policy = ipgre_policy, 1539c19e654dSHerbert Xu .priv_size = sizeof(struct ip_tunnel), 1540c19e654dSHerbert Xu .setup = ipgre_tunnel_setup, 1541c19e654dSHerbert Xu .validate = ipgre_tunnel_validate, 1542c19e654dSHerbert Xu .newlink = ipgre_newlink, 1543c19e654dSHerbert Xu .changelink = ipgre_changelink, 1544c5441932SPravin B Shelar .dellink = ip_tunnel_dellink, 1545c19e654dSHerbert Xu .get_size = ipgre_get_size, 1546c19e654dSHerbert Xu .fill_info = ipgre_fill_info, 15471728d4faSNicolas Dichtel .get_link_net = ip_tunnel_get_link_net, 1548c19e654dSHerbert Xu }; 1549c19e654dSHerbert Xu 1550e1a80002SHerbert Xu static struct rtnl_link_ops ipgre_tap_ops __read_mostly = { 1551e1a80002SHerbert Xu .kind = "gretap", 1552e1a80002SHerbert Xu .maxtype = IFLA_GRE_MAX, 1553e1a80002SHerbert Xu .policy = ipgre_policy, 1554e1a80002SHerbert Xu .priv_size = sizeof(struct ip_tunnel), 1555e1a80002SHerbert Xu .setup = ipgre_tap_setup, 1556e1a80002SHerbert Xu .validate = ipgre_tap_validate, 1557e1a80002SHerbert Xu .newlink = ipgre_newlink, 1558e1a80002SHerbert Xu .changelink = ipgre_changelink, 1559c5441932SPravin B Shelar .dellink = ip_tunnel_dellink, 1560e1a80002SHerbert Xu .get_size = ipgre_get_size, 1561e1a80002SHerbert Xu .fill_info = ipgre_fill_info, 15621728d4faSNicolas Dichtel .get_link_net = ip_tunnel_get_link_net, 1563e1a80002SHerbert Xu }; 1564e1a80002SHerbert Xu 156584e54fe0SWilliam Tu static struct rtnl_link_ops erspan_link_ops __read_mostly = { 156684e54fe0SWilliam Tu .kind = "erspan", 156784e54fe0SWilliam Tu .maxtype = IFLA_GRE_MAX, 156884e54fe0SWilliam Tu .policy = ipgre_policy, 156984e54fe0SWilliam Tu .priv_size = sizeof(struct ip_tunnel), 157084e54fe0SWilliam Tu .setup = erspan_setup, 157184e54fe0SWilliam Tu .validate = erspan_validate, 157284e54fe0SWilliam Tu .newlink = ipgre_newlink, 157384e54fe0SWilliam Tu .changelink = ipgre_changelink, 157484e54fe0SWilliam Tu .dellink = ip_tunnel_dellink, 157584e54fe0SWilliam Tu .get_size = ipgre_get_size, 157684e54fe0SWilliam Tu .fill_info = ipgre_fill_info, 157784e54fe0SWilliam Tu .get_link_net = ip_tunnel_get_link_net, 157884e54fe0SWilliam Tu }; 157984e54fe0SWilliam Tu 1580b2acd1dcSPravin B Shelar struct net_device *gretap_fb_dev_create(struct net *net, const char *name, 1581b2acd1dcSPravin B Shelar u8 name_assign_type) 1582b2acd1dcSPravin B Shelar { 1583b2acd1dcSPravin B Shelar struct nlattr *tb[IFLA_MAX + 1]; 1584b2acd1dcSPravin B Shelar struct net_device *dev; 1585106da663SNicolas Dichtel LIST_HEAD(list_kill); 1586b2acd1dcSPravin B Shelar struct ip_tunnel *t; 1587b2acd1dcSPravin B Shelar int err; 1588b2acd1dcSPravin B Shelar 1589b2acd1dcSPravin B Shelar memset(&tb, 0, sizeof(tb)); 1590b2acd1dcSPravin B Shelar 1591b2acd1dcSPravin B Shelar dev = rtnl_create_link(net, name, name_assign_type, 1592b2acd1dcSPravin B Shelar &ipgre_tap_ops, tb); 1593b2acd1dcSPravin B Shelar if (IS_ERR(dev)) 1594b2acd1dcSPravin B Shelar return dev; 1595b2acd1dcSPravin B Shelar 1596b2acd1dcSPravin B Shelar /* Configure flow based GRE device. */ 1597b2acd1dcSPravin B Shelar t = netdev_priv(dev); 1598b2acd1dcSPravin B Shelar t->collect_md = true; 1599b2acd1dcSPravin B Shelar 16007a3f4a18SMatthias Schiffer err = ipgre_newlink(net, dev, tb, NULL, NULL); 1601106da663SNicolas Dichtel if (err < 0) { 1602106da663SNicolas Dichtel free_netdev(dev); 1603106da663SNicolas Dichtel return ERR_PTR(err); 1604106da663SNicolas Dichtel } 16057e059158SDavid Wragg 16067e059158SDavid Wragg /* openvswitch users expect packet sizes to be unrestricted, 16077e059158SDavid Wragg * so set the largest MTU we can. 16087e059158SDavid Wragg */ 16097e059158SDavid Wragg err = __ip_tunnel_change_mtu(dev, IP_MAX_MTU, false); 16107e059158SDavid Wragg if (err) 16117e059158SDavid Wragg goto out; 16127e059158SDavid Wragg 1613da6f1da8SNicolas Dichtel err = rtnl_configure_link(dev, NULL); 1614da6f1da8SNicolas Dichtel if (err < 0) 1615da6f1da8SNicolas Dichtel goto out; 1616da6f1da8SNicolas Dichtel 1617b2acd1dcSPravin B Shelar return dev; 1618b2acd1dcSPravin B Shelar out: 1619106da663SNicolas Dichtel ip_tunnel_dellink(dev, &list_kill); 1620106da663SNicolas Dichtel unregister_netdevice_many(&list_kill); 1621b2acd1dcSPravin B Shelar return ERR_PTR(err); 1622b2acd1dcSPravin B Shelar } 1623b2acd1dcSPravin B Shelar EXPORT_SYMBOL_GPL(gretap_fb_dev_create); 1624b2acd1dcSPravin B Shelar 1625c5441932SPravin B Shelar static int __net_init ipgre_tap_init_net(struct net *net) 1626c5441932SPravin B Shelar { 16272e15ea39SPravin B Shelar return ip_tunnel_init_net(net, gre_tap_net_id, &ipgre_tap_ops, "gretap0"); 1628c5441932SPravin B Shelar } 1629c5441932SPravin B Shelar 163064bc1781SEric Dumazet static void __net_exit ipgre_tap_exit_batch_net(struct list_head *list_net) 1631c5441932SPravin B Shelar { 163264bc1781SEric Dumazet ip_tunnel_delete_nets(list_net, gre_tap_net_id, &ipgre_tap_ops); 1633c5441932SPravin B Shelar } 1634c5441932SPravin B Shelar 1635c5441932SPravin B Shelar static struct pernet_operations ipgre_tap_net_ops = { 1636c5441932SPravin B Shelar .init = ipgre_tap_init_net, 163764bc1781SEric Dumazet .exit_batch = ipgre_tap_exit_batch_net, 1638c5441932SPravin B Shelar .id = &gre_tap_net_id, 1639c5441932SPravin B Shelar .size = sizeof(struct ip_tunnel_net), 1640c5441932SPravin B Shelar }; 16411da177e4SLinus Torvalds 164284e54fe0SWilliam Tu static int __net_init erspan_init_net(struct net *net) 164384e54fe0SWilliam Tu { 164484e54fe0SWilliam Tu return ip_tunnel_init_net(net, erspan_net_id, 164584e54fe0SWilliam Tu &erspan_link_ops, "erspan0"); 164684e54fe0SWilliam Tu } 164784e54fe0SWilliam Tu 164864bc1781SEric Dumazet static void __net_exit erspan_exit_batch_net(struct list_head *net_list) 164984e54fe0SWilliam Tu { 165064bc1781SEric Dumazet ip_tunnel_delete_nets(net_list, erspan_net_id, &erspan_link_ops); 165184e54fe0SWilliam Tu } 165284e54fe0SWilliam Tu 165384e54fe0SWilliam Tu static struct pernet_operations erspan_net_ops = { 165484e54fe0SWilliam Tu .init = erspan_init_net, 165564bc1781SEric Dumazet .exit_batch = erspan_exit_batch_net, 165684e54fe0SWilliam Tu .id = &erspan_net_id, 165784e54fe0SWilliam Tu .size = sizeof(struct ip_tunnel_net), 165884e54fe0SWilliam Tu }; 165984e54fe0SWilliam Tu 16601da177e4SLinus Torvalds static int __init ipgre_init(void) 16611da177e4SLinus Torvalds { 16621da177e4SLinus Torvalds int err; 16631da177e4SLinus Torvalds 1664058bd4d2SJoe Perches pr_info("GRE over IPv4 tunneling driver\n"); 16651da177e4SLinus Torvalds 1666cfb8fbf2SEric W. Biederman err = register_pernet_device(&ipgre_net_ops); 166759a4c759SPavel Emelyanov if (err < 0) 1668c2892f02SAlexey Dobriyan return err; 1669c2892f02SAlexey Dobriyan 1670c5441932SPravin B Shelar err = register_pernet_device(&ipgre_tap_net_ops); 1671c5441932SPravin B Shelar if (err < 0) 1672e3d0328cSWilliam Tu goto pnet_tap_failed; 1673c5441932SPravin B Shelar 167484e54fe0SWilliam Tu err = register_pernet_device(&erspan_net_ops); 167584e54fe0SWilliam Tu if (err < 0) 167684e54fe0SWilliam Tu goto pnet_erspan_failed; 167784e54fe0SWilliam Tu 16789f57c67cSPravin B Shelar err = gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO); 1679c2892f02SAlexey Dobriyan if (err < 0) { 1680058bd4d2SJoe Perches pr_info("%s: can't add protocol\n", __func__); 1681c2892f02SAlexey Dobriyan goto add_proto_failed; 1682c2892f02SAlexey Dobriyan } 16837daa0004SPavel Emelyanov 1684c19e654dSHerbert Xu err = rtnl_link_register(&ipgre_link_ops); 1685c19e654dSHerbert Xu if (err < 0) 1686c19e654dSHerbert Xu goto rtnl_link_failed; 1687c19e654dSHerbert Xu 1688e1a80002SHerbert Xu err = rtnl_link_register(&ipgre_tap_ops); 1689e1a80002SHerbert Xu if (err < 0) 1690e1a80002SHerbert Xu goto tap_ops_failed; 1691e1a80002SHerbert Xu 169284e54fe0SWilliam Tu err = rtnl_link_register(&erspan_link_ops); 169384e54fe0SWilliam Tu if (err < 0) 169484e54fe0SWilliam Tu goto erspan_link_failed; 169584e54fe0SWilliam Tu 1696c5441932SPravin B Shelar return 0; 1697c19e654dSHerbert Xu 169884e54fe0SWilliam Tu erspan_link_failed: 169984e54fe0SWilliam Tu rtnl_link_unregister(&ipgre_tap_ops); 1700e1a80002SHerbert Xu tap_ops_failed: 1701e1a80002SHerbert Xu rtnl_link_unregister(&ipgre_link_ops); 1702c19e654dSHerbert Xu rtnl_link_failed: 17039f57c67cSPravin B Shelar gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO); 1704c2892f02SAlexey Dobriyan add_proto_failed: 170584e54fe0SWilliam Tu unregister_pernet_device(&erspan_net_ops); 170684e54fe0SWilliam Tu pnet_erspan_failed: 1707c5441932SPravin B Shelar unregister_pernet_device(&ipgre_tap_net_ops); 1708e3d0328cSWilliam Tu pnet_tap_failed: 1709c2892f02SAlexey Dobriyan unregister_pernet_device(&ipgre_net_ops); 1710c5441932SPravin B Shelar return err; 17111da177e4SLinus Torvalds } 17121da177e4SLinus Torvalds 1713db44575fSAlexey Kuznetsov static void __exit ipgre_fini(void) 17141da177e4SLinus Torvalds { 1715e1a80002SHerbert Xu rtnl_link_unregister(&ipgre_tap_ops); 1716c19e654dSHerbert Xu rtnl_link_unregister(&ipgre_link_ops); 171784e54fe0SWilliam Tu rtnl_link_unregister(&erspan_link_ops); 17189f57c67cSPravin B Shelar gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO); 1719c5441932SPravin B Shelar unregister_pernet_device(&ipgre_tap_net_ops); 1720c2892f02SAlexey Dobriyan unregister_pernet_device(&ipgre_net_ops); 172184e54fe0SWilliam Tu unregister_pernet_device(&erspan_net_ops); 17221da177e4SLinus Torvalds } 17231da177e4SLinus Torvalds 17241da177e4SLinus Torvalds module_init(ipgre_init); 17251da177e4SLinus Torvalds module_exit(ipgre_fini); 17261da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 17274d74f8baSPatrick McHardy MODULE_ALIAS_RTNL_LINK("gre"); 17284d74f8baSPatrick McHardy MODULE_ALIAS_RTNL_LINK("gretap"); 172984e54fe0SWilliam Tu MODULE_ALIAS_RTNL_LINK("erspan"); 17308909c9adSVasiliy Kulikov MODULE_ALIAS_NETDEV("gre0"); 1731c5441932SPravin B Shelar MODULE_ALIAS_NETDEV("gretap0"); 173284e54fe0SWilliam Tu MODULE_ALIAS_NETDEV("erspan0"); 1733