Something went wrong. Try again.
(I'm so sorry!) Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613/* SPDX-License-Identifier: GPL-2.0 */#ifndef __NET_VXLAN_H#define __NET_VXLAN_H 1
#include <linux/if_vlan.h>#include <linux/rhashtable-types.h>#include <net/udp_tunnel.h>#include <net/dst_metadata.h>#include <net/rtnetlink.h>#include <net/switchdev.h>#include <net/nexthop.h>
#define IANA_VXLAN_UDP_PORT 4789#define IANA_VXLAN_GPE_UDP_PORT 4790
/* VXLAN protocol (RFC 7348) header: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |R|R|R|R|I|R|R|R| Reserved | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | VXLAN Network Identifier (VNI) | Reserved | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * * I = VXLAN Network Identifier (VNI) present. */struct vxlanhdr { __be32 vx_flags; __be32 vx_vni;};
/* VXLAN header flags. */#define VXLAN_HF_VNI cpu_to_be32(BIT(27))
#define VXLAN_N_VID (1u << 24)#define VXLAN_VID_MASK (VXLAN_N_VID - 1)#define VXLAN_VNI_MASK cpu_to_be32(VXLAN_VID_MASK << 8)#define VXLAN_HLEN (sizeof(struct udphdr) + sizeof(struct vxlanhdr))
#define VNI_HASH_BITS 10#define VNI_HASH_SIZE (1<<VNI_HASH_BITS)#define FDB_HASH_BITS 8#define FDB_HASH_SIZE (1<<FDB_HASH_BITS)
/* Remote checksum offload for VXLAN (VXLAN_F_REMCSUM_[RT]X): * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |R|R|R|R|I|R|R|R|R|R|C| Reserved | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | VXLAN Network Identifier (VNI) |O| Csum start | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * * C = Remote checksum offload bit. When set indicates that the * remote checksum offload data is present. * * O = Offset bit. Indicates the checksum offset relative to * checksum start. * * Csum start = Checksum start divided by two. * * http://tools.ietf.org/html/draft-herbert-vxlan-rco */
/* VXLAN-RCO header flags. */#define VXLAN_HF_RCO cpu_to_be32(BIT(21))
/* Remote checksum offload header option */#define VXLAN_RCO_MASK cpu_to_be32(0x7f) /* Last byte of vni field */#define VXLAN_RCO_UDP cpu_to_be32(0x80) /* Indicate UDP RCO (TCP when not set *) */#define VXLAN_RCO_SHIFT 1 /* Left shift of start */#define VXLAN_RCO_SHIFT_MASK ((1 << VXLAN_RCO_SHIFT) - 1)#define VXLAN_MAX_REMCSUM_START (0x7f << VXLAN_RCO_SHIFT)
/* * VXLAN Group Based Policy Extension (VXLAN_F_GBP): * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |G|R|R|R|I|R|R|R|R|D|R|R|A|R|R|R| Group Policy ID | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | VXLAN Network Identifier (VNI) | Reserved | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * * G = Group Policy ID present. * * D = Don't Learn bit. When set, this bit indicates that the egress * VTEP MUST NOT learn the source address of the encapsulated frame. * * A = Indicates that the group policy has already been applied to * this packet. Policies MUST NOT be applied by devices when the * A bit is set. * * https://tools.ietf.org/html/draft-smith-vxlan-group-policy */struct vxlanhdr_gbp { u8 vx_flags;#ifdef __LITTLE_ENDIAN_BITFIELD u8 reserved_flags1:3, policy_applied:1, reserved_flags2:2, dont_learn:1, reserved_flags3:1;#elif defined(__BIG_ENDIAN_BITFIELD) u8 reserved_flags1:1, dont_learn:1, reserved_flags2:2, policy_applied:1, reserved_flags3:3;#else#error "Please fix <asm/byteorder.h>"#endif __be16 policy_id; __be32 vx_vni;};
/* VXLAN-GBP header flags. */#define VXLAN_HF_GBP cpu_to_be32(BIT(31))
#define VXLAN_GBP_USED_BITS (VXLAN_HF_GBP | cpu_to_be32(0xFFFFFF))
/* skb->mark mapping * * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |R|R|R|R|R|R|R|R|R|D|R|R|A|R|R|R| Group Policy ID | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */#define VXLAN_GBP_DONT_LEARN (BIT(6) << 16)#define VXLAN_GBP_POLICY_APPLIED (BIT(3) << 16)#define VXLAN_GBP_ID_MASK (0xFFFF)
#define VXLAN_GBP_MASK (VXLAN_GBP_DONT_LEARN | VXLAN_GBP_POLICY_APPLIED | \ VXLAN_GBP_ID_MASK)
/* * VXLAN Generic Protocol Extension (VXLAN_F_GPE): * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |R|R|Ver|I|P|R|O| Reserved |Next Protocol | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | VXLAN Network Identifier (VNI) | Reserved | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * * Ver = Version. Indicates VXLAN GPE protocol version. * * P = Next Protocol Bit. The P bit is set to indicate that the * Next Protocol field is present. * * O = OAM Flag Bit. The O bit is set to indicate that the packet * is an OAM packet. * * Next Protocol = This 8 bit field indicates the protocol header * immediately following the VXLAN GPE header. * * https://tools.ietf.org/html/draft-ietf-nvo3-vxlan-gpe-01 */
struct vxlanhdr_gpe {#if defined(__LITTLE_ENDIAN_BITFIELD) u8 oam_flag:1, reserved_flags1:1, np_applied:1, instance_applied:1, version:2, reserved_flags2:2;#elif defined(__BIG_ENDIAN_BITFIELD) u8 reserved_flags2:2, version:2, instance_applied:1, np_applied:1, reserved_flags1:1, oam_flag:1;#endif u8 reserved_flags3; u8 reserved_flags4; u8 next_protocol; __be32 vx_vni;};
/* VXLAN-GPE header flags. */#define VXLAN_HF_VER cpu_to_be32(BIT(29) | BIT(28))#define VXLAN_HF_NP cpu_to_be32(BIT(26))#define VXLAN_HF_OAM cpu_to_be32(BIT(24))
#define VXLAN_GPE_USED_BITS (VXLAN_HF_VER | VXLAN_HF_NP | VXLAN_HF_OAM | \ cpu_to_be32(0xff))
struct vxlan_metadata { u32 gbp;};
/* per UDP socket information */struct vxlan_sock { struct hlist_node hlist; struct sock *sk; struct rcu_head rcu; struct hlist_head vni_list[VNI_HASH_SIZE]; refcount_t refcnt; u32 flags;};
union vxlan_addr { struct sockaddr_in sin; struct sockaddr_in6 sin6; struct sockaddr sa;};
struct vxlan_rdst { union vxlan_addr remote_ip; __be16 remote_port; u8 offloaded:1; __be32 remote_vni; u32 remote_ifindex; struct list_head list; struct rcu_head rcu; struct dst_cache dst_cache;};
struct vxlan_config { union vxlan_addr remote_ip; union vxlan_addr saddr; __be32 vni; int remote_ifindex; int mtu; __be16 dst_port; u16 port_min; u16 port_max; u8 tos; u8 ttl; __be32 label; enum ifla_vxlan_label_policy label_policy; u32 flags; unsigned long age_interval; unsigned int addrmax; bool no_share; enum ifla_vxlan_df df; struct vxlanhdr reserved_bits; struct rcu_head rcu;};
enum { VXLAN_VNI_STATS_RX, VXLAN_VNI_STATS_RX_DROPS, VXLAN_VNI_STATS_RX_ERRORS, VXLAN_VNI_STATS_TX, VXLAN_VNI_STATS_TX_DROPS, VXLAN_VNI_STATS_TX_ERRORS,};
struct vxlan_vni_stats { u64 rx_packets; u64 rx_bytes; u64 rx_drops; u64 rx_errors; u64 tx_packets; u64 tx_bytes; u64 tx_drops; u64 tx_errors;};
struct vxlan_vni_stats_pcpu { struct vxlan_vni_stats stats; struct u64_stats_sync syncp;};
struct vxlan_dev_node { struct hlist_node hlist; struct vxlan_dev *vxlan;};
struct vxlan_vni_node { struct rhash_head vnode; struct vxlan_dev_node hlist4; /* vni hash table for IPv4 socket */#if IS_ENABLED(CONFIG_IPV6) struct vxlan_dev_node hlist6; /* vni hash table for IPv6 socket */#endif struct list_head vlist; __be32 vni; union vxlan_addr remote_ip; /* default remote ip for this vni */ struct vxlan_vni_stats_pcpu __percpu *stats;
struct rcu_head rcu;};
struct vxlan_vni_group { struct rhashtable vni_hash; struct list_head vni_list; u32 num_vnis;};
/* Pseudo network device */struct vxlan_dev { struct vxlan_dev_node hlist4; /* vni hash table for IPv4 socket */#if IS_ENABLED(CONFIG_IPV6) struct vxlan_dev_node hlist6; /* vni hash table for IPv6 socket */#endif struct list_head next; /* vxlan's per namespace list */ struct vxlan_sock __rcu *vn4_sock; /* listening socket for IPv4 */#if IS_ENABLED(CONFIG_IPV6) struct vxlan_sock __rcu *vn6_sock; /* listening socket for IPv6 */#endif struct net_device *dev; struct net *net; /* netns for packet i/o */ struct net_device *lowerdev;
struct timer_list age_timer; spinlock_t hash_lock; unsigned int addrcnt; struct gro_cells gro_cells; unsigned long flags;
struct vxlan_config __rcu *cfg;
struct vxlan_vni_group __rcu *vnigrp;
struct rhashtable fdb_hash_tbl;
struct rhashtable mdb_tbl; struct hlist_head fdb_list; struct hlist_head mdb_list; unsigned int mdb_seq;};
enum vxlan_dev_flags { VXLAN_DEV_F_MDB,};
#define VXLAN_F_LEARN 0x01#define VXLAN_F_PROXY 0x02#define VXLAN_F_RSC 0x04#define VXLAN_F_L2MISS 0x08#define VXLAN_F_L3MISS 0x10#define VXLAN_F_IPV6 0x20#define VXLAN_F_UDP_ZERO_CSUM_TX 0x40#define VXLAN_F_UDP_ZERO_CSUM6_TX 0x80#define VXLAN_F_UDP_ZERO_CSUM6_RX 0x100#define VXLAN_F_REMCSUM_TX 0x200#define VXLAN_F_REMCSUM_RX 0x400#define VXLAN_F_GBP 0x800#define VXLAN_F_REMCSUM_NOPARTIAL 0x1000#define VXLAN_F_COLLECT_METADATA 0x2000#define VXLAN_F_GPE 0x4000#define VXLAN_F_IPV6_LINKLOCAL 0x8000#define VXLAN_F_TTL_INHERIT 0x10000#define VXLAN_F_VNIFILTER 0x20000#define VXLAN_F_LOCALBYPASS 0x80000#define VXLAN_F_MC_ROUTE 0x100000
/* Flags that are used in the receive path. These flags must match in * order for a socket to be shareable */#define VXLAN_F_RCV_FLAGS (VXLAN_F_GBP | \ VXLAN_F_GPE | \ VXLAN_F_UDP_ZERO_CSUM6_RX | \ VXLAN_F_REMCSUM_RX | \ VXLAN_F_REMCSUM_NOPARTIAL | \ VXLAN_F_COLLECT_METADATA | \ VXLAN_F_VNIFILTER)
/* Flags that can be set together with VXLAN_F_GPE. */#define VXLAN_F_ALLOWED_GPE (VXLAN_F_GPE | \ VXLAN_F_IPV6 | \ VXLAN_F_IPV6_LINKLOCAL | \ VXLAN_F_UDP_ZERO_CSUM_TX | \ VXLAN_F_UDP_ZERO_CSUM6_TX | \ VXLAN_F_UDP_ZERO_CSUM6_RX | \ VXLAN_F_COLLECT_METADATA | \ VXLAN_F_VNIFILTER | \ VXLAN_F_LOCALBYPASS | \ VXLAN_F_MC_ROUTE | \ 0)
static inline netdev_features_t vxlan_features_check(struct sk_buff *skb, netdev_features_t features){ u8 l4_hdr = 0;
if (!skb->encapsulation) return features;
switch (vlan_get_protocol(skb)) { case htons(ETH_P_IP): l4_hdr = ip_hdr(skb)->protocol; break; case htons(ETH_P_IPV6): l4_hdr = ipv6_hdr(skb)->nexthdr; break; default: return features; }
if ((l4_hdr == IPPROTO_UDP) && (skb->inner_protocol_type != ENCAP_TYPE_ETHER || skb->inner_protocol != htons(ETH_P_TEB) || (skb_inner_mac_header(skb) - skb_transport_header(skb) != sizeof(struct udphdr) + sizeof(struct vxlanhdr)) || (skb->ip_summed != CHECKSUM_NONE && !can_checksum_protocol(features, inner_eth_hdr(skb)->h_proto)))) return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
return features;}
static inline int vxlan_headroom(u32 flags){ /* VXLAN: IP4/6 header + UDP + VXLAN + Ethernet header */ /* VXLAN-GPE: IP4/6 header + UDP + VXLAN */ return (flags & VXLAN_F_IPV6 ? sizeof(struct ipv6hdr) : sizeof(struct iphdr)) + sizeof(struct udphdr) + sizeof(struct vxlanhdr) + (flags & VXLAN_F_GPE ? 0 : ETH_HLEN);}
static inline struct vxlanhdr *vxlan_hdr(struct sk_buff *skb){ return (struct vxlanhdr *)(udp_hdr(skb) + 1);}
static inline __be32 vxlan_vni(__be32 vni_field){#if defined(__BIG_ENDIAN) return (__force __be32)((__force u32)vni_field >> 8);#else return (__force __be32)((__force u32)(vni_field & VXLAN_VNI_MASK) << 8);#endif}
static inline __be32 vxlan_vni_field(__be32 vni){#if defined(__BIG_ENDIAN) return (__force __be32)((__force u32)vni << 8);#else return (__force __be32)((__force u32)vni >> 8);#endif}
static inline size_t vxlan_rco_start(__be32 vni_field){ return be32_to_cpu(vni_field & VXLAN_RCO_MASK) << VXLAN_RCO_SHIFT;}
static inline size_t vxlan_rco_offset(__be32 vni_field){ return (vni_field & VXLAN_RCO_UDP) ? offsetof(struct udphdr, check) : offsetof(struct tcphdr, check);}
static inline __be32 vxlan_compute_rco(unsigned int start, unsigned int offset){ __be32 vni_field = cpu_to_be32(start >> VXLAN_RCO_SHIFT);
if (offset == offsetof(struct udphdr, check)) vni_field |= VXLAN_RCO_UDP; return vni_field;}
static inline unsigned short vxlan_get_sk_family(struct vxlan_sock *vs){ return vs->sk->sk_family;}
#if IS_ENABLED(CONFIG_IPV6)
static inline bool vxlan_addr_any(const union vxlan_addr *ipa){ if (ipa->sa.sa_family == AF_INET6) return ipv6_addr_any(&ipa->sin6.sin6_addr); else return ipa->sin.sin_addr.s_addr == htonl(INADDR_ANY);}
static inline bool vxlan_addr_multicast(const union vxlan_addr *ipa){ if (ipa->sa.sa_family == AF_INET6) return ipv6_addr_is_multicast(&ipa->sin6.sin6_addr); else return ipv4_is_multicast(ipa->sin.sin_addr.s_addr);}
#else /* !IS_ENABLED(CONFIG_IPV6) */
static inline bool vxlan_addr_any(const union vxlan_addr *ipa){ return ipa->sin.sin_addr.s_addr == htonl(INADDR_ANY);}
static inline bool vxlan_addr_multicast(const union vxlan_addr *ipa){ return ipv4_is_multicast(ipa->sin.sin_addr.s_addr);}
#endif /* IS_ENABLED(CONFIG_IPV6) */
static inline bool netif_is_vxlan(const struct net_device *dev){ return dev->rtnl_link_ops && !strcmp(dev->rtnl_link_ops->kind, "vxlan");}
struct switchdev_notifier_vxlan_fdb_info { struct switchdev_notifier_info info; /* must be first */ union vxlan_addr remote_ip; __be16 remote_port; __be32 remote_vni; u32 remote_ifindex; u8 eth_addr[ETH_ALEN]; __be32 vni; bool offloaded; bool added_by_user;};
#if IS_ENABLED(CONFIG_VXLAN)int vxlan_fdb_find_uc(struct net_device *dev, const u8 *mac, __be32 vni, struct switchdev_notifier_vxlan_fdb_info *fdb_info);int vxlan_fdb_replay(const struct net_device *dev, __be32 vni, struct notifier_block *nb, struct netlink_ext_ack *extack);void vxlan_fdb_clear_offload(const struct net_device *dev, __be32 vni);
#elsestatic inline intvxlan_fdb_find_uc(struct net_device *dev, const u8 *mac, __be32 vni, struct switchdev_notifier_vxlan_fdb_info *fdb_info){ return -ENOENT;}
static inline int vxlan_fdb_replay(const struct net_device *dev, __be32 vni, struct notifier_block *nb, struct netlink_ext_ack *extack){ return -EOPNOTSUPP;}
static inline voidvxlan_fdb_clear_offload(const struct net_device *dev, __be32 vni){}#endif
static inline void vxlan_flag_attr_error(int attrtype, struct netlink_ext_ack *extack){#define VXLAN_FLAG(flg) \ case IFLA_VXLAN_##flg: \ NL_SET_ERR_MSG_MOD(extack, \ "cannot change " #flg " flag"); \ break switch (attrtype) { VXLAN_FLAG(TTL_INHERIT); VXLAN_FLAG(LEARNING); VXLAN_FLAG(PROXY); VXLAN_FLAG(RSC); VXLAN_FLAG(L2MISS); VXLAN_FLAG(L3MISS); VXLAN_FLAG(COLLECT_METADATA); VXLAN_FLAG(UDP_ZERO_CSUM6_TX); VXLAN_FLAG(UDP_ZERO_CSUM6_RX); VXLAN_FLAG(REMCSUM_TX); VXLAN_FLAG(REMCSUM_RX); VXLAN_FLAG(GBP); VXLAN_FLAG(GPE); VXLAN_FLAG(REMCSUM_NOPARTIAL); default: NL_SET_ERR_MSG_MOD(extack, \ "cannot change flag"); break; }#undef VXLAN_FLAG}
static inline bool vxlan_fdb_nh_path_select(struct nexthop *nh, u32 hash, struct vxlan_rdst *rdst){ struct fib_nh_common *nhc; __be16 dst_port = 0;
nhc = nexthop_path_fdb_result(nh, hash >> 1, &dst_port); if (unlikely(!nhc)) return false;
switch (nhc->nhc_gw_family) { case AF_INET: rdst->remote_ip.sin.sin_addr.s_addr = nhc->nhc_gw.ipv4; rdst->remote_ip.sa.sa_family = AF_INET; break; case AF_INET6: rdst->remote_ip.sin6.sin6_addr = nhc->nhc_gw.ipv6; rdst->remote_ip.sa.sa_family = AF_INET6; break; }
rdst->remote_port = dst_port;
return true;}
static inline void vxlan_build_gbp_hdr(struct vxlanhdr *vxh, const struct vxlan_metadata *md){ struct vxlanhdr_gbp *gbp;
if (!md->gbp) return;
gbp = (struct vxlanhdr_gbp *)vxh; vxh->vx_flags |= VXLAN_HF_GBP;
if (md->gbp & VXLAN_GBP_DONT_LEARN) gbp->dont_learn = 1;
if (md->gbp & VXLAN_GBP_POLICY_APPLIED) gbp->policy_applied = 1;
gbp->policy_id = htons(md->gbp & VXLAN_GBP_ID_MASK);}
#endif