1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */ 2c5441932SPravin B Shelar #ifndef __NET_IP_TUNNELS_H 3c5441932SPravin B Shelar #define __NET_IP_TUNNELS_H 1 4c5441932SPravin B Shelar 5c5441932SPravin B Shelar #include <linux/if_tunnel.h> 6c5441932SPravin B Shelar #include <linux/netdevice.h> 7c5441932SPravin B Shelar #include <linux/skbuff.h> 87f9562a1SJiri Benc #include <linux/socket.h> 9c5441932SPravin B Shelar #include <linux/types.h> 10c5441932SPravin B Shelar #include <linux/u64_stats_sync.h> 11fca5fdf6SDaniel Borkmann #include <linux/bitops.h> 12fca5fdf6SDaniel Borkmann 13c5441932SPravin B Shelar #include <net/dsfield.h> 14c5441932SPravin B Shelar #include <net/gro_cells.h> 15c5441932SPravin B Shelar #include <net/inet_ecn.h> 1656328486STom Herbert #include <net/netns/generic.h> 17c5441932SPravin B Shelar #include <net/rtnetlink.h> 183093fbe7SThomas Graf #include <net/lwtunnel.h> 19e09acddfSPaolo Abeni #include <net/dst_cache.h> 20c5441932SPravin B Shelar 21c5441932SPravin B Shelar #if IS_ENABLED(CONFIG_IPV6) 22c5441932SPravin B Shelar #include <net/ipv6.h> 23c5441932SPravin B Shelar #include <net/ip6_fib.h> 24c5441932SPravin B Shelar #include <net/ip6_route.h> 25c5441932SPravin B Shelar #endif 26c5441932SPravin B Shelar 27c5441932SPravin B Shelar /* Keep error state on tunnel for 30 sec */ 28c5441932SPravin B Shelar #define IPTUNNEL_ERR_TIMEO (30*HZ) 29c5441932SPravin B Shelar 301d8fff90SThomas Graf /* Used to memset ip_tunnel padding. */ 31376534a3SJiri Benc #define IP_TUNNEL_KEY_SIZE offsetofend(struct ip_tunnel_key, tp_dst) 321d8fff90SThomas Graf 33c1ea5d67SJiri Benc /* Used to memset ipv4 address padding. */ 34c1ea5d67SJiri Benc #define IP_TUNNEL_KEY_IPV4_PAD offsetofend(struct ip_tunnel_key, u.ipv4.dst) 35c1ea5d67SJiri Benc #define IP_TUNNEL_KEY_IPV4_PAD_LEN \ 36c593642cSPankaj Bharadiya (sizeof_field(struct ip_tunnel_key, u) - \ 37c593642cSPankaj Bharadiya sizeof_field(struct ip_tunnel_key, u.ipv4)) 38c1ea5d67SJiri Benc 391d8fff90SThomas Graf struct ip_tunnel_key { 401d8fff90SThomas Graf __be64 tun_id; 41c1ea5d67SJiri Benc union { 42c1ea5d67SJiri Benc struct { 43c1ea5d67SJiri Benc __be32 src; 44c1ea5d67SJiri Benc __be32 dst; 45c1ea5d67SJiri Benc } ipv4; 46c1ea5d67SJiri Benc struct { 47c1ea5d67SJiri Benc struct in6_addr src; 48c1ea5d67SJiri Benc struct in6_addr dst; 49c1ea5d67SJiri Benc } ipv6; 50c1ea5d67SJiri Benc } u; 511d8fff90SThomas Graf __be16 tun_flags; 527c383fb2SJiri Benc u8 tos; /* TOS for IPv4, TC for IPv6 */ 537c383fb2SJiri Benc u8 ttl; /* TTL for IPv4, HL for IPv6 */ 5413461144SDaniel Borkmann __be32 label; /* Flow Label for IPv6 */ 558bb5e825SIdo Schimmel u32 nhid; 561d8fff90SThomas Graf __be16 tp_src; 571d8fff90SThomas Graf __be16 tp_dst; 58451ef36bSPaul Chaignon __u8 flow_flags; 59ac1cf399SJiri Benc }; 601d8fff90SThomas Graf 61ac931d4cSChristian Ehrig struct ip_tunnel_encap { 62ac931d4cSChristian Ehrig u16 type; 63ac931d4cSChristian Ehrig u16 flags; 64ac931d4cSChristian Ehrig __be16 sport; 65ac931d4cSChristian Ehrig __be16 dport; 66ac931d4cSChristian Ehrig }; 67ac931d4cSChristian Ehrig 6846fa062aSJiri Benc /* Flags for ip_tunnel_info mode. */ 6946fa062aSJiri Benc #define IP_TUNNEL_INFO_TX 0x01 /* represents tx tunnel parameters */ 707f9562a1SJiri Benc #define IP_TUNNEL_INFO_IPV6 0x02 /* key contains IPv6 addresses */ 71f35581d6SRoopa Prabhu #define IP_TUNNEL_INFO_BRIDGE 0x04 /* represents a bridged tunnel id */ 72ee122c79SThomas Graf 73fca5fdf6SDaniel Borkmann /* Maximum tunnel options length. */ 74fca5fdf6SDaniel Borkmann #define IP_TUNNEL_OPTS_MAX \ 75c593642cSPankaj Bharadiya GENMASK((sizeof_field(struct ip_tunnel_info, \ 76fca5fdf6SDaniel Borkmann options_len) * BITS_PER_BYTE) - 1, 0) 77fca5fdf6SDaniel Borkmann 78bc9d003dSGavin Li #define ip_tunnel_info_opts(info) \ 79bc9d003dSGavin Li _Generic(info, \ 80bc9d003dSGavin Li const struct ip_tunnel_info * : ((const void *)((info) + 1)),\ 81bc9d003dSGavin Li struct ip_tunnel_info * : ((void *)((info) + 1))\ 82bc9d003dSGavin Li ) 83bc9d003dSGavin Li 841d8fff90SThomas Graf struct ip_tunnel_info { 851d8fff90SThomas Graf struct ip_tunnel_key key; 86ac931d4cSChristian Ehrig struct ip_tunnel_encap encap; 87d71785ffSPaolo Abeni #ifdef CONFIG_DST_CACHE 88d71785ffSPaolo Abeni struct dst_cache dst_cache; 89d71785ffSPaolo Abeni #endif 901d8fff90SThomas Graf u8 options_len; 91ee122c79SThomas Graf u8 mode; 921d8fff90SThomas Graf }; 931d8fff90SThomas Graf 94c5441932SPravin B Shelar /* 6rd prefix/relay information */ 95c5441932SPravin B Shelar #ifdef CONFIG_IPV6_SIT_6RD 96c5441932SPravin B Shelar struct ip_tunnel_6rd_parm { 97c5441932SPravin B Shelar struct in6_addr prefix; 98c5441932SPravin B Shelar __be32 relay_prefix; 99c5441932SPravin B Shelar u16 prefixlen; 100c5441932SPravin B Shelar u16 relay_prefixlen; 101c5441932SPravin B Shelar }; 102c5441932SPravin B Shelar #endif 103c5441932SPravin B Shelar 104c5441932SPravin B Shelar struct ip_tunnel_prl_entry { 105c5441932SPravin B Shelar struct ip_tunnel_prl_entry __rcu *next; 106c5441932SPravin B Shelar __be32 addr; 107c5441932SPravin B Shelar u16 flags; 108c5441932SPravin B Shelar struct rcu_head rcu_head; 109c5441932SPravin B Shelar }; 110c5441932SPravin B Shelar 1112e15ea39SPravin B Shelar struct metadata_dst; 1122e15ea39SPravin B Shelar 113c5441932SPravin B Shelar struct ip_tunnel { 114c5441932SPravin B Shelar struct ip_tunnel __rcu *next; 115c5441932SPravin B Shelar struct hlist_node hash_node; 116c0fd407aSEric Dumazet 117c5441932SPravin B Shelar struct net_device *dev; 118c0fd407aSEric Dumazet netdevice_tracker dev_tracker; 119c0fd407aSEric Dumazet 1205e6700b3SNicolas Dichtel struct net *net; /* netns for packet i/o */ 121c5441932SPravin B Shelar 122c5441932SPravin B Shelar unsigned long err_time; /* Time when the last ICMP error 123c5441932SPravin B Shelar * arrived */ 124f38ba953Sstephen hemminger int err_count; /* Number of arrived ICMP errors */ 125c5441932SPravin B Shelar 126c5441932SPravin B Shelar /* These four fields used only by GRE */ 1276b8847c5SJiri Benc u32 i_seqno; /* The last seen seqno */ 12831c417c9SPeilin Ye atomic_t o_seqno; /* The last output seqno */ 12956328486STom Herbert int tun_hlen; /* Precalculated header length */ 130c5441932SPravin B Shelar 131f551c91dSWilliam Tu /* These four fields used only by ERSPAN */ 13284e54fe0SWilliam Tu u32 index; /* ERSPAN type II index */ 133f551c91dSWilliam Tu u8 erspan_ver; /* ERSPAN version */ 134f551c91dSWilliam Tu u8 dir; /* ERSPAN direction */ 135f551c91dSWilliam Tu u16 hwid; /* ERSPAN hardware ID */ 13684e54fe0SWilliam Tu 137e09acddfSPaolo Abeni struct dst_cache dst_cache; 1387d442fabSTom Herbert 139c5441932SPravin B Shelar struct ip_tunnel_parm parms; 140c5441932SPravin B Shelar 141f38ba953Sstephen hemminger int mlink; 14256328486STom Herbert int encap_hlen; /* Encap header length (FOU,GUE) */ 14356328486STom Herbert int hlen; /* tun_hlen + encap_hlen */ 144f38ba953Sstephen hemminger struct ip_tunnel_encap encap; 14556328486STom Herbert 146c5441932SPravin B Shelar /* for SIT */ 147c5441932SPravin B Shelar #ifdef CONFIG_IPV6_SIT_6RD 148c5441932SPravin B Shelar struct ip_tunnel_6rd_parm ip6rd; 149c5441932SPravin B Shelar #endif 150c5441932SPravin B Shelar struct ip_tunnel_prl_entry __rcu *prl; /* potential router list */ 151c5441932SPravin B Shelar unsigned int prl_count; /* # of entries in PRL */ 152c7d03a00SAlexey Dobriyan unsigned int ip_tnl_net_id; 153c5441932SPravin B Shelar struct gro_cells gro_cells; 1549830ad4cSCraig Gallek __u32 fwmark; 1552e15ea39SPravin B Shelar bool collect_md; 15622a59be8SPhilip Prindeville bool ignore_df; 157c5441932SPravin B Shelar }; 158c5441932SPravin B Shelar 159c5441932SPravin B Shelar struct tnl_ptk_info { 160c5441932SPravin B Shelar __be16 flags; 161c5441932SPravin B Shelar __be16 proto; 162c5441932SPravin B Shelar __be32 key; 163c5441932SPravin B Shelar __be32 seq; 1649b8c6d7bSEric Dumazet int hdr_len; 165c5441932SPravin B Shelar }; 166c5441932SPravin B Shelar 167c5441932SPravin B Shelar #define PACKET_RCVD 0 168c5441932SPravin B Shelar #define PACKET_REJECT 1 169125372faSJiri Benc #define PACKET_NEXT 2 170c5441932SPravin B Shelar 1716261d983Sstephen hemminger #define IP_TNL_HASH_BITS 7 172c5441932SPravin B Shelar #define IP_TNL_HASH_SIZE (1 << IP_TNL_HASH_BITS) 173c5441932SPravin B Shelar 174c5441932SPravin B Shelar struct ip_tunnel_net { 175c5441932SPravin B Shelar struct net_device *fb_tunnel_dev; 17679134e6cSEric Dumazet struct rtnl_link_ops *rtnl_link_ops; 1776261d983Sstephen hemminger struct hlist_head tunnels[IP_TNL_HASH_SIZE]; 1782e15ea39SPravin B Shelar struct ip_tunnel __rcu *collect_md_tun; 17979134e6cSEric Dumazet int type; 180c5441932SPravin B Shelar }; 181c5441932SPravin B Shelar 1824c222798SPravin B Shelar static inline void ip_tunnel_key_init(struct ip_tunnel_key *key, 1831d8fff90SThomas Graf __be32 saddr, __be32 daddr, 18413461144SDaniel Borkmann u8 tos, u8 ttl, __be32 label, 1851d8fff90SThomas Graf __be16 tp_src, __be16 tp_dst, 1864c222798SPravin B Shelar __be64 tun_id, __be16 tun_flags) 1871d8fff90SThomas Graf { 1884c222798SPravin B Shelar key->tun_id = tun_id; 1894c222798SPravin B Shelar key->u.ipv4.src = saddr; 1904c222798SPravin B Shelar key->u.ipv4.dst = daddr; 1914c222798SPravin B Shelar memset((unsigned char *)key + IP_TUNNEL_KEY_IPV4_PAD, 192c1ea5d67SJiri Benc 0, IP_TUNNEL_KEY_IPV4_PAD_LEN); 1934c222798SPravin B Shelar key->tos = tos; 1944c222798SPravin B Shelar key->ttl = ttl; 19513461144SDaniel Borkmann key->label = label; 1964c222798SPravin B Shelar key->tun_flags = tun_flags; 1971d8fff90SThomas Graf 1981d8fff90SThomas Graf /* For the tunnel types on the top of IPsec, the tp_src and tp_dst of 1991d8fff90SThomas Graf * the upper tunnel are used. 2001d8fff90SThomas Graf * E.g: GRE over IPSEC, the tp_src and tp_port are zero. 2011d8fff90SThomas Graf */ 2024c222798SPravin B Shelar key->tp_src = tp_src; 2034c222798SPravin B Shelar key->tp_dst = tp_dst; 2041d8fff90SThomas Graf 2051d8fff90SThomas Graf /* Clear struct padding. */ 2064c222798SPravin B Shelar if (sizeof(*key) != IP_TUNNEL_KEY_SIZE) 2074c222798SPravin B Shelar memset((unsigned char *)key + IP_TUNNEL_KEY_SIZE, 2084c222798SPravin B Shelar 0, sizeof(*key) - IP_TUNNEL_KEY_SIZE); 2091d8fff90SThomas Graf } 2101d8fff90SThomas Graf 211db3c6139SDaniel Borkmann static inline bool 212db3c6139SDaniel Borkmann ip_tunnel_dst_cache_usable(const struct sk_buff *skb, 213db3c6139SDaniel Borkmann const struct ip_tunnel_info *info) 214db3c6139SDaniel Borkmann { 215db3c6139SDaniel Borkmann if (skb->mark) 216db3c6139SDaniel Borkmann return false; 217db3c6139SDaniel Borkmann if (!info) 218db3c6139SDaniel Borkmann return true; 219db3c6139SDaniel Borkmann if (info->key.tun_flags & TUNNEL_NOCACHE) 220db3c6139SDaniel Borkmann return false; 221db3c6139SDaniel Borkmann 222db3c6139SDaniel Borkmann return true; 223db3c6139SDaniel Borkmann } 224db3c6139SDaniel Borkmann 2257f9562a1SJiri Benc static inline unsigned short ip_tunnel_info_af(const struct ip_tunnel_info 2267f9562a1SJiri Benc *tun_info) 2277f9562a1SJiri Benc { 2287f9562a1SJiri Benc return tun_info->mode & IP_TUNNEL_INFO_IPV6 ? AF_INET6 : AF_INET; 2297f9562a1SJiri Benc } 2307f9562a1SJiri Benc 231d817f432SAmir Vadai static inline __be64 key32_to_tunnel_id(__be32 key) 232d817f432SAmir Vadai { 233d817f432SAmir Vadai #ifdef __BIG_ENDIAN 234d817f432SAmir Vadai return (__force __be64)key; 235d817f432SAmir Vadai #else 236d817f432SAmir Vadai return (__force __be64)((__force u64)key << 32); 237d817f432SAmir Vadai #endif 238d817f432SAmir Vadai } 239d817f432SAmir Vadai 240d817f432SAmir Vadai /* Returns the least-significant 32 bits of a __be64. */ 241d817f432SAmir Vadai static inline __be32 tunnel_id_to_key32(__be64 tun_id) 242d817f432SAmir Vadai { 243d817f432SAmir Vadai #ifdef __BIG_ENDIAN 244d817f432SAmir Vadai return (__force __be32)tun_id; 245d817f432SAmir Vadai #else 246d817f432SAmir Vadai return (__force __be32)((__force u64)tun_id >> 32); 247d817f432SAmir Vadai #endif 248d817f432SAmir Vadai } 249d817f432SAmir Vadai 2505243b6acSJesse Gross #ifdef CONFIG_INET 2515243b6acSJesse Gross 252b0066da5SPetr Machata static inline void ip_tunnel_init_flow(struct flowi4 *fl4, 253b0066da5SPetr Machata int proto, 254b0066da5SPetr Machata __be32 daddr, __be32 saddr, 255db53cd3dSDavid Ahern __be32 key, __u8 tos, 256db53cd3dSDavid Ahern struct net *net, int oif, 2577ec9fce4SEyal Birger __u32 mark, __u32 tun_inner_hash, 2587ec9fce4SEyal Birger __u8 flow_flags) 259b0066da5SPetr Machata { 260b0066da5SPetr Machata memset(fl4, 0, sizeof(*fl4)); 261db53cd3dSDavid Ahern 262db53cd3dSDavid Ahern if (oif) { 263db53cd3dSDavid Ahern fl4->flowi4_l3mdev = l3mdev_master_upper_ifindex_by_index_rcu(net, oif); 264db53cd3dSDavid Ahern /* Legacy VRF/l3mdev use case */ 265db53cd3dSDavid Ahern fl4->flowi4_oif = fl4->flowi4_l3mdev ? 0 : oif; 266db53cd3dSDavid Ahern } 267db53cd3dSDavid Ahern 268b0066da5SPetr Machata fl4->daddr = daddr; 269b0066da5SPetr Machata fl4->saddr = saddr; 270b0066da5SPetr Machata fl4->flowi4_tos = tos; 271b0066da5SPetr Machata fl4->flowi4_proto = proto; 272b0066da5SPetr Machata fl4->fl4_gre_key = key; 273b0066da5SPetr Machata fl4->flowi4_mark = mark; 27424ba1440Swenxu fl4->flowi4_multipath_hash = tun_inner_hash; 2757ec9fce4SEyal Birger fl4->flowi4_flags = flow_flags; 276b0066da5SPetr Machata } 277b0066da5SPetr Machata 278c5441932SPravin B Shelar int ip_tunnel_init(struct net_device *dev); 279c5441932SPravin B Shelar void ip_tunnel_uninit(struct net_device *dev); 280c5441932SPravin B Shelar void ip_tunnel_dellink(struct net_device *dev, struct list_head *head); 2811728d4faSNicolas Dichtel struct net *ip_tunnel_get_link_net(const struct net_device *dev); 2821e99584bSNicolas Dichtel int ip_tunnel_get_iflink(const struct net_device *dev); 283c7d03a00SAlexey Dobriyan int ip_tunnel_init_net(struct net *net, unsigned int ip_tnl_net_id, 284c5441932SPravin B Shelar struct rtnl_link_ops *ops, char *devname); 285c5441932SPravin B Shelar 28664bc1781SEric Dumazet void ip_tunnel_delete_nets(struct list_head *list_net, unsigned int id, 2879b5b3637SEric Dumazet struct rtnl_link_ops *ops, 2889b5b3637SEric Dumazet struct list_head *dev_to_kill); 289c5441932SPravin B Shelar 290c5441932SPravin B Shelar void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, 291bf3d6a8fSNicolas Dichtel const struct iphdr *tnl_params, const u8 protocol); 292cfc7381bSAlexei Starovoitov void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, 293c8b34e68Swenxu const u8 proto, int tunnel_hlen); 294607259a6SChristoph Hellwig int ip_tunnel_ctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd); 2953e7a1c7cSArnd Bergmann int ip_tunnel_siocdevprivate(struct net_device *dev, struct ifreq *ifr, 2963e7a1c7cSArnd Bergmann void __user *data, int cmd); 2977e059158SDavid Wragg int __ip_tunnel_change_mtu(struct net_device *dev, int new_mtu, bool strict); 298c5441932SPravin B Shelar int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu); 299c5441932SPravin B Shelar 300c5441932SPravin B Shelar struct ip_tunnel *ip_tunnel_lookup(struct ip_tunnel_net *itn, 301c5441932SPravin B Shelar int link, __be16 flags, 302c5441932SPravin B Shelar __be32 remote, __be32 local, 303c5441932SPravin B Shelar __be32 key); 304c5441932SPravin B Shelar 305ac931d4cSChristian Ehrig void ip_tunnel_md_udp_encap(struct sk_buff *skb, struct ip_tunnel_info *info); 306c5441932SPravin B Shelar int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb, 3072e15ea39SPravin B Shelar const struct tnl_ptk_info *tpi, struct metadata_dst *tun_dst, 3082e15ea39SPravin B Shelar bool log_ecn_error); 309c5441932SPravin B Shelar int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[], 3109830ad4cSCraig Gallek struct ip_tunnel_parm *p, __u32 fwmark); 311c5441932SPravin B Shelar int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[], 3129830ad4cSCraig Gallek struct ip_tunnel_parm *p, __u32 fwmark); 313c7d03a00SAlexey Dobriyan void ip_tunnel_setup(struct net_device *dev, unsigned int net_id); 31455c2bc14STom Herbert 315537dd2d9SLiu Jian bool ip_tunnel_netlink_encap_parms(struct nlattr *data[], 316537dd2d9SLiu Jian struct ip_tunnel_encap *encap); 317537dd2d9SLiu Jian 318b86fca80SLiu Jian void ip_tunnel_netlink_parms(struct nlattr *data[], 319b86fca80SLiu Jian struct ip_tunnel_parm *parms); 320b86fca80SLiu Jian 3212606aff9SJason A. Donenfeld extern const struct header_ops ip_tunnel_header_ops; 3222606aff9SJason A. Donenfeld __be16 ip_tunnel_parse_protocol(const struct sk_buff *skb); 3232606aff9SJason A. Donenfeld 32455c2bc14STom Herbert struct ip_tunnel_encap_ops { 32555c2bc14STom Herbert size_t (*encap_hlen)(struct ip_tunnel_encap *e); 32655c2bc14STom Herbert int (*build_header)(struct sk_buff *skb, struct ip_tunnel_encap *e, 32755c2bc14STom Herbert u8 *protocol, struct flowi4 *fl4); 328e7cc0824SStefano Brivio int (*err_handler)(struct sk_buff *skb, u32 info); 32955c2bc14STom Herbert }; 33055c2bc14STom Herbert 33155c2bc14STom Herbert #define MAX_IPTUN_ENCAP_OPS 8 33255c2bc14STom Herbert 33355c2bc14STom Herbert extern const struct ip_tunnel_encap_ops __rcu * 33455c2bc14STom Herbert iptun_encaps[MAX_IPTUN_ENCAP_OPS]; 33555c2bc14STom Herbert 33655c2bc14STom Herbert int ip_tunnel_encap_add_ops(const struct ip_tunnel_encap_ops *op, 33755c2bc14STom Herbert unsigned int num); 33855c2bc14STom Herbert int ip_tunnel_encap_del_ops(const struct ip_tunnel_encap_ops *op, 33955c2bc14STom Herbert unsigned int num); 34055c2bc14STom Herbert 34156328486STom Herbert int ip_tunnel_encap_setup(struct ip_tunnel *t, 34256328486STom Herbert struct ip_tunnel_encap *ipencap); 343c5441932SPravin B Shelar 344cb9f1b78SWillem de Bruijn static inline bool pskb_inet_may_pull(struct sk_buff *skb) 345cb9f1b78SWillem de Bruijn { 346cb9f1b78SWillem de Bruijn int nhlen; 347cb9f1b78SWillem de Bruijn 348cb9f1b78SWillem de Bruijn switch (skb->protocol) { 349cb9f1b78SWillem de Bruijn #if IS_ENABLED(CONFIG_IPV6) 350cb9f1b78SWillem de Bruijn case htons(ETH_P_IPV6): 351cb9f1b78SWillem de Bruijn nhlen = sizeof(struct ipv6hdr); 352cb9f1b78SWillem de Bruijn break; 353cb9f1b78SWillem de Bruijn #endif 354cb9f1b78SWillem de Bruijn case htons(ETH_P_IP): 355cb9f1b78SWillem de Bruijn nhlen = sizeof(struct iphdr); 356cb9f1b78SWillem de Bruijn break; 357cb9f1b78SWillem de Bruijn default: 358cb9f1b78SWillem de Bruijn nhlen = 0; 359cb9f1b78SWillem de Bruijn } 360cb9f1b78SWillem de Bruijn 361cb9f1b78SWillem de Bruijn return pskb_network_may_pull(skb, nhlen); 362cb9f1b78SWillem de Bruijn } 363cb9f1b78SWillem de Bruijn 364*d8a6213dSEric Dumazet /* Variant of pskb_inet_may_pull(). 365*d8a6213dSEric Dumazet */ 366*d8a6213dSEric Dumazet static inline bool skb_vlan_inet_prepare(struct sk_buff *skb) 367*d8a6213dSEric Dumazet { 368*d8a6213dSEric Dumazet int nhlen = 0, maclen = ETH_HLEN; 369*d8a6213dSEric Dumazet __be16 type = skb->protocol; 370*d8a6213dSEric Dumazet 371*d8a6213dSEric Dumazet /* Essentially this is skb_protocol(skb, true) 372*d8a6213dSEric Dumazet * And we get MAC len. 373*d8a6213dSEric Dumazet */ 374*d8a6213dSEric Dumazet if (eth_type_vlan(type)) 375*d8a6213dSEric Dumazet type = __vlan_get_protocol(skb, type, &maclen); 376*d8a6213dSEric Dumazet 377*d8a6213dSEric Dumazet switch (type) { 378*d8a6213dSEric Dumazet #if IS_ENABLED(CONFIG_IPV6) 379*d8a6213dSEric Dumazet case htons(ETH_P_IPV6): 380*d8a6213dSEric Dumazet nhlen = sizeof(struct ipv6hdr); 381*d8a6213dSEric Dumazet break; 382*d8a6213dSEric Dumazet #endif 383*d8a6213dSEric Dumazet case htons(ETH_P_IP): 384*d8a6213dSEric Dumazet nhlen = sizeof(struct iphdr); 385*d8a6213dSEric Dumazet break; 386*d8a6213dSEric Dumazet } 387*d8a6213dSEric Dumazet /* For ETH_P_IPV6/ETH_P_IP we make sure to pull 388*d8a6213dSEric Dumazet * a base network header in skb->head. 389*d8a6213dSEric Dumazet */ 390*d8a6213dSEric Dumazet if (!pskb_may_pull(skb, maclen + nhlen)) 391*d8a6213dSEric Dumazet return false; 392*d8a6213dSEric Dumazet 393*d8a6213dSEric Dumazet skb_set_network_header(skb, maclen); 394*d8a6213dSEric Dumazet return true; 395*d8a6213dSEric Dumazet } 396*d8a6213dSEric Dumazet 39755c2bc14STom Herbert static inline int ip_encap_hlen(struct ip_tunnel_encap *e) 39855c2bc14STom Herbert { 39955c2bc14STom Herbert const struct ip_tunnel_encap_ops *ops; 40055c2bc14STom Herbert int hlen = -EINVAL; 40155c2bc14STom Herbert 40255c2bc14STom Herbert if (e->type == TUNNEL_ENCAP_NONE) 40355c2bc14STom Herbert return 0; 40455c2bc14STom Herbert 40555c2bc14STom Herbert if (e->type >= MAX_IPTUN_ENCAP_OPS) 40655c2bc14STom Herbert return -EINVAL; 40755c2bc14STom Herbert 40855c2bc14STom Herbert rcu_read_lock(); 40955c2bc14STom Herbert ops = rcu_dereference(iptun_encaps[e->type]); 41055c2bc14STom Herbert if (likely(ops && ops->encap_hlen)) 41155c2bc14STom Herbert hlen = ops->encap_hlen(e); 41255c2bc14STom Herbert rcu_read_unlock(); 41355c2bc14STom Herbert 41455c2bc14STom Herbert return hlen; 41555c2bc14STom Herbert } 41655c2bc14STom Herbert 417ac931d4cSChristian Ehrig static inline int ip_tunnel_encap(struct sk_buff *skb, 418ac931d4cSChristian Ehrig struct ip_tunnel_encap *e, 41955c2bc14STom Herbert u8 *protocol, struct flowi4 *fl4) 42055c2bc14STom Herbert { 42155c2bc14STom Herbert const struct ip_tunnel_encap_ops *ops; 42255c2bc14STom Herbert int ret = -EINVAL; 42355c2bc14STom Herbert 424ac931d4cSChristian Ehrig if (e->type == TUNNEL_ENCAP_NONE) 42555c2bc14STom Herbert return 0; 42655c2bc14STom Herbert 427ac931d4cSChristian Ehrig if (e->type >= MAX_IPTUN_ENCAP_OPS) 42855c2bc14STom Herbert return -EINVAL; 42955c2bc14STom Herbert 43055c2bc14STom Herbert rcu_read_lock(); 431ac931d4cSChristian Ehrig ops = rcu_dereference(iptun_encaps[e->type]); 43255c2bc14STom Herbert if (likely(ops && ops->build_header)) 433ac931d4cSChristian Ehrig ret = ops->build_header(skb, e, protocol, fl4); 43455c2bc14STom Herbert rcu_read_unlock(); 43555c2bc14STom Herbert 43655c2bc14STom Herbert return ret; 43755c2bc14STom Herbert } 43855c2bc14STom Herbert 439c5441932SPravin B Shelar /* Extract dsfield from inner protocol */ 440c5441932SPravin B Shelar static inline u8 ip_tunnel_get_dsfield(const struct iphdr *iph, 441c5441932SPravin B Shelar const struct sk_buff *skb) 442c5441932SPravin B Shelar { 4437074732cSMatthias May __be16 payload_protocol = skb_protocol(skb, true); 4447074732cSMatthias May 4457074732cSMatthias May if (payload_protocol == htons(ETH_P_IP)) 446c5441932SPravin B Shelar return iph->tos; 4477074732cSMatthias May else if (payload_protocol == htons(ETH_P_IPV6)) 448c5441932SPravin B Shelar return ipv6_get_dsfield((const struct ipv6hdr *)iph); 449c5441932SPravin B Shelar else 450c5441932SPravin B Shelar return 0; 451c5441932SPravin B Shelar } 452c5441932SPravin B Shelar 453c6e9dba3SAlce Lafranque static inline __be32 ip_tunnel_get_flowlabel(const struct iphdr *iph, 454c6e9dba3SAlce Lafranque const struct sk_buff *skb) 455c6e9dba3SAlce Lafranque { 456c6e9dba3SAlce Lafranque __be16 payload_protocol = skb_protocol(skb, true); 457c6e9dba3SAlce Lafranque 458c6e9dba3SAlce Lafranque if (payload_protocol == htons(ETH_P_IPV6)) 459c6e9dba3SAlce Lafranque return ip6_flowlabel((const struct ipv6hdr *)iph); 460c6e9dba3SAlce Lafranque else 461c6e9dba3SAlce Lafranque return 0; 462c6e9dba3SAlce Lafranque } 463c6e9dba3SAlce Lafranque 46472f6d71eSHangbin Liu static inline u8 ip_tunnel_get_ttl(const struct iphdr *iph, 46572f6d71eSHangbin Liu const struct sk_buff *skb) 46672f6d71eSHangbin Liu { 4677074732cSMatthias May __be16 payload_protocol = skb_protocol(skb, true); 4687074732cSMatthias May 4697074732cSMatthias May if (payload_protocol == htons(ETH_P_IP)) 47072f6d71eSHangbin Liu return iph->ttl; 4717074732cSMatthias May else if (payload_protocol == htons(ETH_P_IPV6)) 47272f6d71eSHangbin Liu return ((const struct ipv6hdr *)iph)->hop_limit; 47372f6d71eSHangbin Liu else 47472f6d71eSHangbin Liu return 0; 47572f6d71eSHangbin Liu } 47672f6d71eSHangbin Liu 477c5441932SPravin B Shelar /* Propogate ECN bits out */ 478c5441932SPravin B Shelar static inline u8 ip_tunnel_ecn_encap(u8 tos, const struct iphdr *iph, 479c5441932SPravin B Shelar const struct sk_buff *skb) 480c5441932SPravin B Shelar { 481c5441932SPravin B Shelar u8 inner = ip_tunnel_get_dsfield(iph, skb); 482c5441932SPravin B Shelar 483c5441932SPravin B Shelar return INET_ECN_encapsulate(tos, inner); 484c5441932SPravin B Shelar } 485c5441932SPravin B Shelar 486a6d5bbf3SJiri Benc int __iptunnel_pull_header(struct sk_buff *skb, int hdr_len, 487a6d5bbf3SJiri Benc __be16 inner_proto, bool raw_proto, bool xnet); 488a6d5bbf3SJiri Benc 489a6d5bbf3SJiri Benc static inline int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, 490a6d5bbf3SJiri Benc __be16 inner_proto, bool xnet) 491a6d5bbf3SJiri Benc { 492a6d5bbf3SJiri Benc return __iptunnel_pull_header(skb, hdr_len, inner_proto, false, xnet); 493a6d5bbf3SJiri Benc } 494a6d5bbf3SJiri Benc 495039f5062SPravin B Shelar void iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb, 4966b8847c5SJiri Benc __be32 src, __be32 dst, u8 proto, 4976b8847c5SJiri Benc u8 tos, u8 ttl, __be16 df, bool xnet); 49863d008a4SJiri Benc struct metadata_dst *iptunnel_metadata_reply(struct metadata_dst *md, 49963d008a4SJiri Benc gfp_t flags); 5004cb47a86SStefano Brivio int skb_tunnel_check_pmtu(struct sk_buff *skb, struct dst_entry *encap_dst, 5014cb47a86SStefano Brivio int headroom, bool reply); 5020e6fbc5bSPravin B Shelar 503aed069dfSAlexander Duyck int iptunnel_handle_offloads(struct sk_buff *skb, int gso_type_mask); 5042d26f0a3SEric Dumazet 505a09a4c8dSJesse Gross static inline int iptunnel_pull_offloads(struct sk_buff *skb) 506a09a4c8dSJesse Gross { 507a09a4c8dSJesse Gross if (skb_is_gso(skb)) { 508a09a4c8dSJesse Gross int err; 509a09a4c8dSJesse Gross 510a09a4c8dSJesse Gross err = skb_unclone(skb, GFP_ATOMIC); 511a09a4c8dSJesse Gross if (unlikely(err)) 512a09a4c8dSJesse Gross return err; 513a09a4c8dSJesse Gross skb_shinfo(skb)->gso_type &= ~(NETIF_F_GSO_ENCAP_ALL >> 514a09a4c8dSJesse Gross NETIF_F_GSO_SHIFT); 515a09a4c8dSJesse Gross } 516a09a4c8dSJesse Gross 517a09a4c8dSJesse Gross skb->encapsulation = 0; 518a09a4c8dSJesse Gross return 0; 519a09a4c8dSJesse Gross } 520a09a4c8dSJesse Gross 521039f5062SPravin B Shelar static inline void iptunnel_xmit_stats(struct net_device *dev, int pkt_len) 522c5441932SPravin B Shelar { 523039f5062SPravin B Shelar if (pkt_len > 0) { 524039f5062SPravin B Shelar struct pcpu_sw_netstats *tstats = get_cpu_ptr(dev->tstats); 525c5441932SPravin B Shelar 526c5441932SPravin B Shelar u64_stats_update_begin(&tstats->syncp); 5279962acefSEric Dumazet u64_stats_add(&tstats->tx_bytes, pkt_len); 5289962acefSEric Dumazet u64_stats_inc(&tstats->tx_packets); 529c5441932SPravin B Shelar u64_stats_update_end(&tstats->syncp); 530b4fe85f9SJason A. Donenfeld put_cpu_ptr(tstats); 5319b271ebaSEric Dumazet return; 5329b271ebaSEric Dumazet } 533039f5062SPravin B Shelar 534039f5062SPravin B Shelar if (pkt_len < 0) { 5359b271ebaSEric Dumazet DEV_STATS_INC(dev, tx_errors); 5369b271ebaSEric Dumazet DEV_STATS_INC(dev, tx_aborted_errors); 537c5441932SPravin B Shelar } else { 5389b271ebaSEric Dumazet DEV_STATS_INC(dev, tx_dropped); 539c5441932SPravin B Shelar } 540039f5062SPravin B Shelar } 5415243b6acSJesse Gross 5424c222798SPravin B Shelar static inline void ip_tunnel_info_opts_get(void *to, 5434c222798SPravin B Shelar const struct ip_tunnel_info *info) 5444c222798SPravin B Shelar { 5454c222798SPravin B Shelar memcpy(to, info + 1, info->options_len); 5464c222798SPravin B Shelar } 5474c222798SPravin B Shelar 5484c222798SPravin B Shelar static inline void ip_tunnel_info_opts_set(struct ip_tunnel_info *info, 549256c87c1SPieter Jansen van Vuuren const void *from, int len, 550256c87c1SPieter Jansen van Vuuren __be16 flags) 5514c222798SPravin B Shelar { 5524c222798SPravin B Shelar info->options_len = len; 5539c2e14b4SYi-Hung Wei if (len > 0) { 5549c2e14b4SYi-Hung Wei memcpy(ip_tunnel_info_opts(info), from, len); 555256c87c1SPieter Jansen van Vuuren info->key.tun_flags |= flags; 5564c222798SPravin B Shelar } 5579c2e14b4SYi-Hung Wei } 5584c222798SPravin B Shelar 5593093fbe7SThomas Graf static inline struct ip_tunnel_info *lwt_tun_info(struct lwtunnel_state *lwtstate) 5603093fbe7SThomas Graf { 5613093fbe7SThomas Graf return (struct ip_tunnel_info *)lwtstate->data; 5623093fbe7SThomas Graf } 5633093fbe7SThomas Graf 5645263a98fSDavidlohr Bueso DECLARE_STATIC_KEY_FALSE(ip_tunnel_metadata_cnt); 565e7030878SThomas Graf 566e7030878SThomas Graf /* Returns > 0 if metadata should be collected */ 567e7030878SThomas Graf static inline int ip_tunnel_collect_metadata(void) 568e7030878SThomas Graf { 5695263a98fSDavidlohr Bueso return static_branch_unlikely(&ip_tunnel_metadata_cnt); 570e7030878SThomas Graf } 571e7030878SThomas Graf 572045a0fa0SThomas Graf void __init ip_tunnel_core_init(void); 573045a0fa0SThomas Graf 574e7030878SThomas Graf void ip_tunnel_need_metadata(void); 575e7030878SThomas Graf void ip_tunnel_unneed_metadata(void); 576e7030878SThomas Graf 57705283187SThomas Graf #else /* CONFIG_INET */ 57805283187SThomas Graf 57905283187SThomas Graf static inline struct ip_tunnel_info *lwt_tun_info(struct lwtunnel_state *lwtstate) 58005283187SThomas Graf { 58105283187SThomas Graf return NULL; 58205283187SThomas Graf } 58305283187SThomas Graf 58405283187SThomas Graf static inline void ip_tunnel_need_metadata(void) 58505283187SThomas Graf { 58605283187SThomas Graf } 58705283187SThomas Graf 58805283187SThomas Graf static inline void ip_tunnel_unneed_metadata(void) 58905283187SThomas Graf { 59005283187SThomas Graf } 59105283187SThomas Graf 592e28e87edSDaniel Borkmann static inline void ip_tunnel_info_opts_get(void *to, 593e28e87edSDaniel Borkmann const struct ip_tunnel_info *info) 594e28e87edSDaniel Borkmann { 595e28e87edSDaniel Borkmann } 596e28e87edSDaniel Borkmann 597e28e87edSDaniel Borkmann static inline void ip_tunnel_info_opts_set(struct ip_tunnel_info *info, 598256c87c1SPieter Jansen van Vuuren const void *from, int len, 599256c87c1SPieter Jansen van Vuuren __be16 flags) 600e28e87edSDaniel Borkmann { 601e28e87edSDaniel Borkmann info->options_len = 0; 602e28e87edSDaniel Borkmann } 603e28e87edSDaniel Borkmann 6045243b6acSJesse Gross #endif /* CONFIG_INET */ 6055243b6acSJesse Gross 606c5441932SPravin B Shelar #endif /* __NET_IP_TUNNELS_H */ 607