1012a5729SPravin B Shelar #ifndef __NET_VXLAN_H 2012a5729SPravin B Shelar #define __NET_VXLAN_H 1 3012a5729SPravin B Shelar 45f35227eSJesse Gross #include <linux/ip.h> 55f35227eSJesse Gross #include <linux/ipv6.h> 65f35227eSJesse Gross #include <linux/if_vlan.h> 7012a5729SPravin B Shelar #include <linux/skbuff.h> 8012a5729SPravin B Shelar #include <linux/netdevice.h> 9012a5729SPravin B Shelar #include <linux/udp.h> 10012a5729SPravin B Shelar 11012a5729SPravin B Shelar #define VNI_HASH_BITS 10 12012a5729SPravin B Shelar #define VNI_HASH_SIZE (1<<VNI_HASH_BITS) 13012a5729SPravin B Shelar 143511494cSThomas Graf /* 153511494cSThomas Graf * VXLAN Group Based Policy Extension: 163511494cSThomas Graf * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 173511494cSThomas Graf * |1|-|-|-|1|-|-|-|R|D|R|R|A|R|R|R| Group Policy ID | 183511494cSThomas Graf * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 193511494cSThomas Graf * | VXLAN Network Identifier (VNI) | Reserved | 203511494cSThomas Graf * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 213511494cSThomas Graf * 223511494cSThomas Graf * D = Don't Learn bit. When set, this bit indicates that the egress 233511494cSThomas Graf * VTEP MUST NOT learn the source address of the encapsulated frame. 243511494cSThomas Graf * 253511494cSThomas Graf * A = Indicates that the group policy has already been applied to 263511494cSThomas Graf * this packet. Policies MUST NOT be applied by devices when the 273511494cSThomas Graf * A bit is set. 283511494cSThomas Graf * 293511494cSThomas Graf * [0] https://tools.ietf.org/html/draft-smith-vxlan-group-policy 303511494cSThomas Graf */ 313511494cSThomas Graf struct vxlanhdr_gbp { 323511494cSThomas Graf __u8 vx_flags; 333511494cSThomas Graf #ifdef __LITTLE_ENDIAN_BITFIELD 343511494cSThomas Graf __u8 reserved_flags1:3, 353511494cSThomas Graf policy_applied:1, 363511494cSThomas Graf reserved_flags2:2, 373511494cSThomas Graf dont_learn:1, 383511494cSThomas Graf reserved_flags3:1; 393511494cSThomas Graf #elif defined(__BIG_ENDIAN_BITFIELD) 403511494cSThomas Graf __u8 reserved_flags1:1, 413511494cSThomas Graf dont_learn:1, 423511494cSThomas Graf reserved_flags2:2, 433511494cSThomas Graf policy_applied:1, 443511494cSThomas Graf reserved_flags3:3; 453511494cSThomas Graf #else 463511494cSThomas Graf #error "Please fix <asm/byteorder.h>" 473511494cSThomas Graf #endif 483511494cSThomas Graf __be16 policy_id; 493511494cSThomas Graf __be32 vx_vni; 503511494cSThomas Graf }; 513511494cSThomas Graf 523511494cSThomas Graf #define VXLAN_GBP_USED_BITS (VXLAN_HF_GBP | 0xFFFFFF) 533511494cSThomas Graf 543511494cSThomas Graf /* skb->mark mapping 553511494cSThomas Graf * 563511494cSThomas Graf * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 573511494cSThomas Graf * |R|R|R|R|R|R|R|R|R|D|R|R|A|R|R|R| Group Policy ID | 583511494cSThomas Graf * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 593511494cSThomas Graf */ 603511494cSThomas Graf #define VXLAN_GBP_DONT_LEARN (BIT(6) << 16) 613511494cSThomas Graf #define VXLAN_GBP_POLICY_APPLIED (BIT(3) << 16) 623511494cSThomas Graf #define VXLAN_GBP_ID_MASK (0xFFFF) 633511494cSThomas Graf 643511494cSThomas Graf /* VXLAN protocol header: 653511494cSThomas Graf * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 663511494cSThomas Graf * |G|R|R|R|I|R|R|C| Reserved | 673511494cSThomas Graf * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 683511494cSThomas Graf * | VXLAN Network Identifier (VNI) | Reserved | 693511494cSThomas Graf * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 703511494cSThomas Graf * 713511494cSThomas Graf * G = 1 Group Policy (VXLAN-GBP) 723511494cSThomas Graf * I = 1 VXLAN Network Identifier (VNI) present 733511494cSThomas Graf * C = 1 Remote checksum offload (RCO) 743511494cSThomas Graf */ 7511bf7828SJoe Stringer struct vxlanhdr { 7611bf7828SJoe Stringer __be32 vx_flags; 7711bf7828SJoe Stringer __be32 vx_vni; 7811bf7828SJoe Stringer }; 7911bf7828SJoe Stringer 803bf39475STom Herbert /* VXLAN header flags. */ 813511494cSThomas Graf #define VXLAN_HF_RCO BIT(24) 823511494cSThomas Graf #define VXLAN_HF_VNI BIT(27) 833511494cSThomas Graf #define VXLAN_HF_GBP BIT(31) 84dfd8645eSTom Herbert 85dfd8645eSTom Herbert /* Remote checksum offload header option */ 86dfd8645eSTom Herbert #define VXLAN_RCO_MASK 0x7f /* Last byte of vni field */ 87dfd8645eSTom Herbert #define VXLAN_RCO_UDP 0x80 /* Indicate UDP RCO (TCP when not set *) */ 88dfd8645eSTom Herbert #define VXLAN_RCO_SHIFT 1 /* Left shift of start */ 89dfd8645eSTom Herbert #define VXLAN_RCO_SHIFT_MASK ((1 << VXLAN_RCO_SHIFT) - 1) 90dfd8645eSTom Herbert #define VXLAN_MAX_REMCSUM_START (VXLAN_RCO_MASK << VXLAN_RCO_SHIFT) 913bf39475STom Herbert 923bf39475STom Herbert #define VXLAN_N_VID (1u << 24) 933bf39475STom Herbert #define VXLAN_VID_MASK (VXLAN_N_VID - 1) 943bf39475STom Herbert #define VXLAN_HLEN (sizeof(struct udphdr) + sizeof(struct vxlanhdr)) 953bf39475STom Herbert 963511494cSThomas Graf struct vxlan_metadata { 973511494cSThomas Graf __be32 vni; 983511494cSThomas Graf u32 gbp; 993511494cSThomas Graf }; 1003511494cSThomas Graf 101012a5729SPravin B Shelar struct vxlan_sock; 1023511494cSThomas Graf typedef void (vxlan_rcv_t)(struct vxlan_sock *vh, struct sk_buff *skb, 1033511494cSThomas Graf struct vxlan_metadata *md); 104012a5729SPravin B Shelar 105012a5729SPravin B Shelar /* per UDP socket information */ 106012a5729SPravin B Shelar struct vxlan_sock { 107012a5729SPravin B Shelar struct hlist_node hlist; 108012a5729SPravin B Shelar vxlan_rcv_t *rcv; 109012a5729SPravin B Shelar void *data; 110012a5729SPravin B Shelar struct work_struct del_work; 111012a5729SPravin B Shelar struct socket *sock; 112012a5729SPravin B Shelar struct rcu_head rcu; 113012a5729SPravin B Shelar struct hlist_head vni_list[VNI_HASH_SIZE]; 114012a5729SPravin B Shelar atomic_t refcnt; 115dc01e7d3SOr Gerlitz struct udp_offload udp_offloads; 116dfd8645eSTom Herbert u32 flags; 117012a5729SPravin B Shelar }; 118012a5729SPravin B Shelar 119359a0ea9STom Herbert #define VXLAN_F_LEARN 0x01 120359a0ea9STom Herbert #define VXLAN_F_PROXY 0x02 121359a0ea9STom Herbert #define VXLAN_F_RSC 0x04 122359a0ea9STom Herbert #define VXLAN_F_L2MISS 0x08 123359a0ea9STom Herbert #define VXLAN_F_L3MISS 0x10 124359a0ea9STom Herbert #define VXLAN_F_IPV6 0x20 125359a0ea9STom Herbert #define VXLAN_F_UDP_CSUM 0x40 126359a0ea9STom Herbert #define VXLAN_F_UDP_ZERO_CSUM6_TX 0x80 127359a0ea9STom Herbert #define VXLAN_F_UDP_ZERO_CSUM6_RX 0x100 128dfd8645eSTom Herbert #define VXLAN_F_REMCSUM_TX 0x200 129dfd8645eSTom Herbert #define VXLAN_F_REMCSUM_RX 0x400 1303511494cSThomas Graf #define VXLAN_F_GBP 0x800 131359a0ea9STom Herbert 132ac5132d1SThomas Graf /* These flags must match in order for a socket to be shareable */ 133ac5132d1SThomas Graf #define VXLAN_F_UNSHAREABLE VXLAN_F_GBP 134ac5132d1SThomas Graf 135012a5729SPravin B Shelar struct vxlan_sock *vxlan_sock_add(struct net *net, __be16 port, 136012a5729SPravin B Shelar vxlan_rcv_t *rcv, void *data, 137359a0ea9STom Herbert bool no_share, u32 flags); 138012a5729SPravin B Shelar 139012a5729SPravin B Shelar void vxlan_sock_release(struct vxlan_sock *vs); 14049560532SPravin B Shelar 14111796187SNicolas Dichtel int vxlan_xmit_skb(struct vxlan_sock *vs, 14249560532SPravin B Shelar struct rtable *rt, struct sk_buff *skb, 14349560532SPravin B Shelar __be32 src, __be32 dst, __u8 tos, __u8 ttl, __be16 df, 1443511494cSThomas Graf __be16 src_port, __be16 dst_port, struct vxlan_metadata *md, 1453511494cSThomas Graf bool xnet); 14649560532SPravin B Shelar 1475f35227eSJesse Gross static inline netdev_features_t vxlan_features_check(struct sk_buff *skb, 1485f35227eSJesse Gross netdev_features_t features) 14911bf7828SJoe Stringer { 1505f35227eSJesse Gross u8 l4_hdr = 0; 1515f35227eSJesse Gross 1525f35227eSJesse Gross if (!skb->encapsulation) 1535f35227eSJesse Gross return features; 1545f35227eSJesse Gross 1555f35227eSJesse Gross switch (vlan_get_protocol(skb)) { 1565f35227eSJesse Gross case htons(ETH_P_IP): 1575f35227eSJesse Gross l4_hdr = ip_hdr(skb)->protocol; 1585f35227eSJesse Gross break; 1595f35227eSJesse Gross case htons(ETH_P_IPV6): 1605f35227eSJesse Gross l4_hdr = ipv6_hdr(skb)->nexthdr; 1615f35227eSJesse Gross break; 1625f35227eSJesse Gross default: 1635f35227eSJesse Gross return features;; 1645f35227eSJesse Gross } 1655f35227eSJesse Gross 1665f35227eSJesse Gross if ((l4_hdr == IPPROTO_UDP) && 16711bf7828SJoe Stringer (skb->inner_protocol_type != ENCAP_TYPE_ETHER || 16811bf7828SJoe Stringer skb->inner_protocol != htons(ETH_P_TEB) || 16911bf7828SJoe Stringer (skb_inner_mac_header(skb) - skb_transport_header(skb) != 17011bf7828SJoe Stringer sizeof(struct udphdr) + sizeof(struct vxlanhdr)))) 1715f35227eSJesse Gross return features & ~(NETIF_F_ALL_CSUM | NETIF_F_GSO_MASK); 17211bf7828SJoe Stringer 1735f35227eSJesse Gross return features; 17411bf7828SJoe Stringer } 17523e62de3SJoe Stringer 176e6cd988cSJoseph Gasparakis /* IP header + UDP + VXLAN + Ethernet header */ 177e6cd988cSJoseph Gasparakis #define VXLAN_HEADROOM (20 + 8 + 8 + 14) 178e6cd988cSJoseph Gasparakis /* IPv6 header + UDP + VXLAN + Ethernet header */ 179e6cd988cSJoseph Gasparakis #define VXLAN6_HEADROOM (40 + 8 + 8 + 14) 180e6cd988cSJoseph Gasparakis 181e6cd988cSJoseph Gasparakis #if IS_ENABLED(CONFIG_VXLAN) 18253cf5275SJoseph Gasparakis void vxlan_get_rx_port(struct net_device *netdev); 183e6cd988cSJoseph Gasparakis #else 184e6cd988cSJoseph Gasparakis static inline void vxlan_get_rx_port(struct net_device *netdev) 185e6cd988cSJoseph Gasparakis { 186e6cd988cSJoseph Gasparakis } 187e6cd988cSJoseph Gasparakis #endif 188012a5729SPravin B Shelar #endif 189