/* SPDX-License-Identifier: GPL-2.0 */#ifndef _NET_FLOW_DISSECTOR_H#define _NET_FLOW_DISSECTOR_H #include <linux/types.h>#include <linux/in6.h>#include <linux/siphash.h>#include <linux/string.h>#include <uapi/linux/if_ether.h>#include <uapi/linux/pkt_cls.h> struct bpf_prog;struct net;struct sk_buff; /** * struct flow_dissector_key_control: * @thoff: Transport header offset * @addr_type: Type of key. One of FLOW_DISSECTOR_KEY_* * @flags: Key flags. * Any of FLOW_DIS_(IS_FRAGMENT|FIRST_FRAG|ENCAPSULATION|F_*) */struct flow_dissector_key_control { u16 thoff; u16 addr_type; u32 flags;}; /* The control flags are kept in sync with TCA_FLOWER_KEY_FLAGS_*, as those * flags are exposed to userspace in some error paths, ie. unsupported flags. */enum flow_dissector_ctrl_flags { FLOW_DIS_IS_FRAGMENT = TCA_FLOWER_KEY_FLAGS_IS_FRAGMENT, FLOW_DIS_FIRST_FRAG = TCA_FLOWER_KEY_FLAGS_FRAG_IS_FIRST, FLOW_DIS_F_TUNNEL_CSUM = TCA_FLOWER_KEY_FLAGS_TUNNEL_CSUM, FLOW_DIS_F_TUNNEL_DONT_FRAGMENT = TCA_FLOWER_KEY_FLAGS_TUNNEL_DONT_FRAGMENT, FLOW_DIS_F_TUNNEL_OAM = TCA_FLOWER_KEY_FLAGS_TUNNEL_OAM, FLOW_DIS_F_TUNNEL_CRIT_OPT = TCA_FLOWER_KEY_FLAGS_TUNNEL_CRIT_OPT, /* These flags are internal to the kernel */ FLOW_DIS_ENCAPSULATION = (TCA_FLOWER_KEY_FLAGS_MAX << 1),}; enum flow_dissect_ret { FLOW_DISSECT_RET_OUT_GOOD, FLOW_DISSECT_RET_OUT_BAD, FLOW_DISSECT_RET_PROTO_AGAIN, FLOW_DISSECT_RET_IPPROTO_AGAIN, FLOW_DISSECT_RET_CONTINUE,}; /** * struct flow_dissector_key_basic: * @n_proto: Network header protocol (eg. IPv4/IPv6) * @ip_proto: Transport header protocol (eg. TCP/UDP) * @padding: Unused */struct flow_dissector_key_basic { __be16 n_proto; u8 ip_proto; u8 padding;}; struct flow_dissector_key_tags { u32 flow_label;}; struct flow_dissector_key_vlan { union { struct { u16 vlan_id:12, vlan_dei:1, vlan_priority:3; }; __be16 vlan_tci; }; __be16 vlan_tpid; __be16 vlan_eth_type; u16 padding;}; struct flow_dissector_mpls_lse { u32 mpls_ttl:8, mpls_bos:1, mpls_tc:3, mpls_label:20;}; #define FLOW_DIS_MPLS_MAX 7struct flow_dissector_key_mpls { struct flow_dissector_mpls_lse ls[FLOW_DIS_MPLS_MAX]; /* Label Stack */ u8 used_lses; /* One bit set for each Label Stack Entry in use */}; static inline void dissector_set_mpls_lse(struct flow_dissector_key_mpls *mpls, int lse_index){ mpls->used_lses |= 1 << lse_index;} #define FLOW_DIS_TUN_OPTS_MAX 255/** * struct flow_dissector_key_enc_opts: * @data: tunnel option data * @len: length of tunnel option data * @dst_opt_type: tunnel option type */struct flow_dissector_key_enc_opts { u8 data[FLOW_DIS_TUN_OPTS_MAX]; /* Using IP_TUNNEL_OPTS_MAX is desired * here but seems difficult to #include */ u8 len; u32 dst_opt_type;}; struct flow_dissector_key_keyid { __be32 keyid;}; /** * struct flow_dissector_key_ipv4_addrs: * @src: source ip address * @dst: destination ip address */struct flow_dissector_key_ipv4_addrs { /* (src,dst) must be grouped, in the same way than in IP header */ __be32 src; __be32 dst;}; /** * struct flow_dissector_key_ipv6_addrs: * @src: source ip address * @dst: destination ip address */struct flow_dissector_key_ipv6_addrs { /* (src,dst) must be grouped, in the same way than in IP header */ struct in6_addr src; struct in6_addr dst;}; /** * struct flow_dissector_key_tipc: * @key: source node address combined with selector */struct flow_dissector_key_tipc { __be32 key;}; /** * struct flow_dissector_key_addrs: * @v4addrs: IPv4 addresses * @v6addrs: IPv6 addresses * @tipckey: TIPC key */struct flow_dissector_key_addrs { union { struct flow_dissector_key_ipv4_addrs v4addrs; struct flow_dissector_key_ipv6_addrs v6addrs; struct flow_dissector_key_tipc tipckey; };}; /** * struct flow_dissector_key_arp: * @sip: Sender IP address * @tip: Target IP address * @op: Operation * @sha: Sender hardware address * @tha: Target hardware address */struct flow_dissector_key_arp { __u32 sip; __u32 tip; __u8 op; unsigned char sha[ETH_ALEN]; unsigned char tha[ETH_ALEN];}; /** * struct flow_dissector_key_ports: * @ports: port numbers of Transport header * @src: source port number * @dst: destination port number */struct flow_dissector_key_ports { union { __be32 ports; struct { __be16 src; __be16 dst; }; };}; /** * struct flow_dissector_key_ports_range * @tp: port number from packet * @tp_min: min port number in range * @tp_max: max port number in range */struct flow_dissector_key_ports_range { union { struct flow_dissector_key_ports tp; struct { struct flow_dissector_key_ports tp_min; struct flow_dissector_key_ports tp_max; }; };}; /** * struct flow_dissector_key_icmp: * @type: ICMP type * @code: ICMP code * @id: Session identifier */struct flow_dissector_key_icmp { struct { u8 type; u8 code; }; u16 id;}; /** * struct flow_dissector_key_eth_addrs: * @src: source Ethernet address * @dst: destination Ethernet address */struct flow_dissector_key_eth_addrs { /* (dst,src) must be grouped, in the same way than in ETH header */ unsigned char dst[ETH_ALEN]; unsigned char src[ETH_ALEN];}; /** * struct flow_dissector_key_tcp: * @flags: flags */struct flow_dissector_key_tcp { __be16 flags;}; /** * struct flow_dissector_key_ip: * @tos: tos * @ttl: ttl */struct flow_dissector_key_ip { __u8 tos; __u8 ttl;}; /** * struct flow_dissector_key_meta: * @ingress_ifindex: ingress ifindex * @ingress_iftype: ingress interface type * @l2_miss: packet did not match an L2 entry during forwarding */struct flow_dissector_key_meta { int ingress_ifindex; u16 ingress_iftype; u8 l2_miss;}; /** * struct flow_dissector_key_ct: * @ct_state: conntrack state after converting with map * @ct_mark: conttrack mark * @ct_zone: conntrack zone * @ct_labels: conntrack labels */struct flow_dissector_key_ct { u16 ct_state; u16 ct_zone; u32 ct_mark; u32 ct_labels[4];}; /** * struct flow_dissector_key_hash: * @hash: hash value */struct flow_dissector_key_hash { u32 hash;}; /** * struct flow_dissector_key_num_of_vlans: * @num_of_vlans: num_of_vlans value */struct flow_dissector_key_num_of_vlans { u8 num_of_vlans;}; /** * struct flow_dissector_key_pppoe: * @session_id: pppoe session id * @ppp_proto: ppp protocol * @type: pppoe eth type */struct flow_dissector_key_pppoe { __be16 session_id; __be16 ppp_proto; __be16 type;}; /** * struct flow_dissector_key_l2tpv3: * @session_id: identifier for a l2tp session */struct flow_dissector_key_l2tpv3 { __be32 session_id;}; /** * struct flow_dissector_key_ipsec: * @spi: identifier for a ipsec connection */struct flow_dissector_key_ipsec { __be32 spi;}; /** * struct flow_dissector_key_cfm * @mdl_ver: maintenance domain level (mdl) and cfm protocol version * @opcode: code specifying a type of cfm protocol packet * * See 802.1ag, ITU-T G.8013/Y.1731 * 1 2 * |7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0| * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | mdl | version | opcode | * +-----+---------+-+-+-+-+-+-+-+-+ */struct flow_dissector_key_cfm { u8 mdl_ver; u8 opcode;}; #define FLOW_DIS_CFM_MDL_MASK GENMASK(7, 5)#define FLOW_DIS_CFM_MDL_MAX 7 enum flow_dissector_key_id { FLOW_DISSECTOR_KEY_CONTROL, /* struct flow_dissector_key_control */ FLOW_DISSECTOR_KEY_BASIC, /* struct flow_dissector_key_basic */ FLOW_DISSECTOR_KEY_IPV4_ADDRS, /* struct flow_dissector_key_ipv4_addrs */ FLOW_DISSECTOR_KEY_IPV6_ADDRS, /* struct flow_dissector_key_ipv6_addrs */ FLOW_DISSECTOR_KEY_PORTS, /* struct flow_dissector_key_ports */ FLOW_DISSECTOR_KEY_PORTS_RANGE, /* struct flow_dissector_key_ports */ FLOW_DISSECTOR_KEY_ICMP, /* struct flow_dissector_key_icmp */ FLOW_DISSECTOR_KEY_ETH_ADDRS, /* struct flow_dissector_key_eth_addrs */ FLOW_DISSECTOR_KEY_TIPC, /* struct flow_dissector_key_tipc */ FLOW_DISSECTOR_KEY_ARP, /* struct flow_dissector_key_arp */ FLOW_DISSECTOR_KEY_VLAN, /* struct flow_dissector_key_vlan */ FLOW_DISSECTOR_KEY_FLOW_LABEL, /* struct flow_dissector_key_tags */ FLOW_DISSECTOR_KEY_GRE_KEYID, /* struct flow_dissector_key_keyid */ FLOW_DISSECTOR_KEY_MPLS_ENTROPY, /* struct flow_dissector_key_keyid */ FLOW_DISSECTOR_KEY_ENC_KEYID, /* struct flow_dissector_key_keyid */ FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS, /* struct flow_dissector_key_ipv4_addrs */ FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS, /* struct flow_dissector_key_ipv6_addrs */ FLOW_DISSECTOR_KEY_ENC_CONTROL, /* struct flow_dissector_key_control */ FLOW_DISSECTOR_KEY_ENC_PORTS, /* struct flow_dissector_key_ports */ FLOW_DISSECTOR_KEY_MPLS, /* struct flow_dissector_key_mpls */ FLOW_DISSECTOR_KEY_TCP, /* struct flow_dissector_key_tcp */ FLOW_DISSECTOR_KEY_IP, /* struct flow_dissector_key_ip */ FLOW_DISSECTOR_KEY_CVLAN, /* struct flow_dissector_key_vlan */ FLOW_DISSECTOR_KEY_ENC_IP, /* struct flow_dissector_key_ip */ FLOW_DISSECTOR_KEY_ENC_OPTS, /* struct flow_dissector_key_enc_opts */ FLOW_DISSECTOR_KEY_META, /* struct flow_dissector_key_meta */ FLOW_DISSECTOR_KEY_CT, /* struct flow_dissector_key_ct */ FLOW_DISSECTOR_KEY_HASH, /* struct flow_dissector_key_hash */ FLOW_DISSECTOR_KEY_NUM_OF_VLANS, /* struct flow_dissector_key_num_of_vlans */ FLOW_DISSECTOR_KEY_PPPOE, /* struct flow_dissector_key_pppoe */ FLOW_DISSECTOR_KEY_L2TPV3, /* struct flow_dissector_key_l2tpv3 */ FLOW_DISSECTOR_KEY_CFM, /* struct flow_dissector_key_cfm */ FLOW_DISSECTOR_KEY_IPSEC, /* struct flow_dissector_key_ipsec */ FLOW_DISSECTOR_KEY_MAX,}; #define FLOW_DISSECTOR_F_PARSE_1ST_FRAG BIT(0)#define FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL BIT(1)#define FLOW_DISSECTOR_F_STOP_AT_ENCAP BIT(2)#define FLOW_DISSECTOR_F_STOP_BEFORE_ENCAP BIT(3) struct flow_dissector_key { enum flow_dissector_key_id key_id; size_t offset; /* offset of struct flow_dissector_key_* in target the struct */}; struct flow_dissector { unsigned long long used_keys; /* each bit represents presence of one key id */ unsigned short int offset[FLOW_DISSECTOR_KEY_MAX];}; struct flow_keys_basic { struct flow_dissector_key_control control; struct flow_dissector_key_basic basic;}; struct flow_keys { struct flow_dissector_key_control control;#define FLOW_KEYS_HASH_START_FIELD basic struct flow_dissector_key_basic basic __aligned(SIPHASH_ALIGNMENT); struct flow_dissector_key_tags tags; struct flow_dissector_key_vlan vlan; struct flow_dissector_key_vlan cvlan; struct flow_dissector_key_keyid keyid; struct flow_dissector_key_ports ports; struct flow_dissector_key_icmp icmp; /* 'addrs' must be the last member */ struct flow_dissector_key_addrs addrs;}; #define FLOW_KEYS_HASH_OFFSET \ offsetof(struct flow_keys, FLOW_KEYS_HASH_START_FIELD) __be32 flow_get_u32_src(const struct flow_keys *flow);__be32 flow_get_u32_dst(const struct flow_keys *flow); extern struct flow_dissector flow_keys_dissector;extern struct flow_dissector flow_keys_basic_dissector; /* struct flow_keys_digest: * * This structure is used to hold a digest of the full flow keys. This is a * larger "hash" of a flow to allow definitively matching specific flows where * the 32 bit skb->hash is not large enough. The size is limited to 16 bytes so * that it can be used in CB of skb (see sch_choke for an example). */#define FLOW_KEYS_DIGEST_LEN 16struct flow_keys_digest { u8 data[FLOW_KEYS_DIGEST_LEN];}; void make_flow_keys_digest(struct flow_keys_digest *digest, const struct flow_keys *flow); static inline bool flow_keys_have_l4(const struct flow_keys *keys){ return (keys->ports.ports || keys->tags.flow_label);} u32 flow_hash_from_keys(struct flow_keys *keys);u32 flow_hash_from_keys_seed(struct flow_keys *keys, const siphash_key_t *keyval);void skb_flow_get_icmp_tci(const struct sk_buff *skb, struct flow_dissector_key_icmp *key_icmp, const void *data, int thoff, int hlen); static inline bool dissector_uses_key(const struct flow_dissector *flow_dissector, enum flow_dissector_key_id key_id){ return flow_dissector->used_keys & (1ULL << key_id);} static inline void *skb_flow_dissector_target(struct flow_dissector *flow_dissector, enum flow_dissector_key_id key_id, void *target_container){ return ((char *)target_container) + flow_dissector->offset[key_id];} struct bpf_flow_dissector { struct bpf_flow_keys *flow_keys; const struct sk_buff *skb; const void *data; const void *data_end;}; static inline voidflow_dissector_init_keys(struct flow_dissector_key_control *key_control, struct flow_dissector_key_basic *key_basic){ memset(key_control, 0, sizeof(*key_control)); memset(key_basic, 0, sizeof(*key_basic));} #ifdef CONFIG_BPF_SYSCALLint flow_dissector_bpf_prog_attach_check(struct net *net, struct bpf_prog *prog);#endif /* CONFIG_BPF_SYSCALL */ #endif
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NET_FLOW_DISSECTOR_H
#define _NET_FLOW_DISSECTOR_H
#include <linux/types.h>
#include <linux/in6.h>
#include <linux/siphash.h>
#include <linux/string.h>
#include <uapi/linux/if_ether.h>
#include <uapi/linux/pkt_cls.h>
struct bpf_prog;
struct net;
struct sk_buff;
/**
* struct flow_dissector_key_control:
* @thoff: Transport header offset
* @addr_type: Type of key. One of FLOW_DISSECTOR_KEY_*
* @flags: Key flags.
* Any of FLOW_DIS_(IS_FRAGMENT|FIRST_FRAG|ENCAPSULATION|F_*)
*/
struct flow_dissector_key_control {
u16 thoff;
u16 addr_type;
u32 flags;
};
/* The control flags are kept in sync with TCA_FLOWER_KEY_FLAGS_*, as those
* flags are exposed to userspace in some error paths, ie. unsupported flags.
*/
enum flow_dissector_ctrl_flags {
FLOW_DIS_IS_FRAGMENT = TCA_FLOWER_KEY_FLAGS_IS_FRAGMENT,
FLOW_DIS_FIRST_FRAG = TCA_FLOWER_KEY_FLAGS_FRAG_IS_FIRST,
FLOW_DIS_F_TUNNEL_CSUM = TCA_FLOWER_KEY_FLAGS_TUNNEL_CSUM,
FLOW_DIS_F_TUNNEL_DONT_FRAGMENT = TCA_FLOWER_KEY_FLAGS_TUNNEL_DONT_FRAGMENT,
FLOW_DIS_F_TUNNEL_OAM = TCA_FLOWER_KEY_FLAGS_TUNNEL_OAM,
FLOW_DIS_F_TUNNEL_CRIT_OPT = TCA_FLOWER_KEY_FLAGS_TUNNEL_CRIT_OPT,
/* These flags are internal to the kernel */
FLOW_DIS_ENCAPSULATION = (TCA_FLOWER_KEY_FLAGS_MAX << 1),
};
enum flow_dissect_ret {
FLOW_DISSECT_RET_OUT_GOOD,
FLOW_DISSECT_RET_OUT_BAD,
FLOW_DISSECT_RET_PROTO_AGAIN,
FLOW_DISSECT_RET_IPPROTO_AGAIN,
FLOW_DISSECT_RET_CONTINUE,
};
/**
* struct flow_dissector_key_basic:
* @n_proto: Network header protocol (eg. IPv4/IPv6)
* @ip_proto: Transport header protocol (eg. TCP/UDP)
* @padding: Unused
*/
struct flow_dissector_key_basic {
__be16 n_proto;
u8 ip_proto;
u8 padding;
};
struct flow_dissector_key_tags {
u32 flow_label;
};
struct flow_dissector_key_vlan {
union {
struct {
u16 vlan_id:12,
vlan_dei:1,
vlan_priority:3;
};
__be16 vlan_tci;
};
__be16 vlan_tpid;
__be16 vlan_eth_type;
u16 padding;
};
struct flow_dissector_mpls_lse {
u32 mpls_ttl:8,
mpls_bos:1,
mpls_tc:3,
mpls_label:20;
};
#define FLOW_DIS_MPLS_MAX 7
struct flow_dissector_key_mpls {
struct flow_dissector_mpls_lse ls[FLOW_DIS_MPLS_MAX]; /* Label Stack */
u8 used_lses; /* One bit set for each Label Stack Entry in use */
};
static inline void dissector_set_mpls_lse(struct flow_dissector_key_mpls *mpls,
int lse_index)
{
mpls->used_lses |= 1 << lse_index;
}
#define FLOW_DIS_TUN_OPTS_MAX 255
/**
* struct flow_dissector_key_enc_opts:
* @data: tunnel option data
* @len: length of tunnel option data
* @dst_opt_type: tunnel option type
*/
struct flow_dissector_key_enc_opts {
u8 data[FLOW_DIS_TUN_OPTS_MAX]; /* Using IP_TUNNEL_OPTS_MAX is desired
* here but seems difficult to #include
*/
u8 len;
u32 dst_opt_type;
};
struct flow_dissector_key_keyid {
__be32 keyid;
};
/**
* struct flow_dissector_key_ipv4_addrs:
* @src: source ip address
* @dst: destination ip address
*/
struct flow_dissector_key_ipv4_addrs {
/* (src,dst) must be grouped, in the same way than in IP header */
__be32 src;
__be32 dst;
};
/**
* struct flow_dissector_key_ipv6_addrs:
* @src: source ip address
* @dst: destination ip address
*/
struct flow_dissector_key_ipv6_addrs {
/* (src,dst) must be grouped, in the same way than in IP header */
struct in6_addr src;
struct in6_addr dst;
};
/**
* struct flow_dissector_key_tipc:
* @key: source node address combined with selector
*/
struct flow_dissector_key_tipc {
__be32 key;
};
/**
* struct flow_dissector_key_addrs:
* @v4addrs: IPv4 addresses
* @v6addrs: IPv6 addresses
* @tipckey: TIPC key
*/
struct flow_dissector_key_addrs {
union {
struct flow_dissector_key_ipv4_addrs v4addrs;
struct flow_dissector_key_ipv6_addrs v6addrs;
struct flow_dissector_key_tipc tipckey;
};
};
/**
* struct flow_dissector_key_arp:
* @sip: Sender IP address
* @tip: Target IP address
* @op: Operation
* @sha: Sender hardware address
* @tha: Target hardware address
*/
struct flow_dissector_key_arp {
__u32 sip;
__u32 tip;
__u8 op;
unsigned char sha[ETH_ALEN];
unsigned char tha[ETH_ALEN];
};
/**
* struct flow_dissector_key_ports:
* @ports: port numbers of Transport header
* @src: source port number
* @dst: destination port number
*/
struct flow_dissector_key_ports {
union {
__be32 ports;
struct {
__be16 src;
__be16 dst;
};
};
};
/**
* struct flow_dissector_key_ports_range
* @tp: port number from packet
* @tp_min: min port number in range
* @tp_max: max port number in range
*/
struct flow_dissector_key_ports_range {
union {
struct flow_dissector_key_ports tp;
struct {
struct flow_dissector_key_ports tp_min;
struct flow_dissector_key_ports tp_max;
};
};
};
/**
* struct flow_dissector_key_icmp:
* @type: ICMP type
* @code: ICMP code
* @id: Session identifier
*/
struct flow_dissector_key_icmp {
struct {
u8 type;
u8 code;
};
u16 id;
};
/**
* struct flow_dissector_key_eth_addrs:
* @src: source Ethernet address
* @dst: destination Ethernet address
*/
struct flow_dissector_key_eth_addrs {
/* (dst,src) must be grouped, in the same way than in ETH header */
unsigned char dst[ETH_ALEN];
unsigned char src[ETH_ALEN];
};
/**
* struct flow_dissector_key_tcp:
* @flags: flags
*/
struct flow_dissector_key_tcp {
__be16 flags;
};
/**
* struct flow_dissector_key_ip:
* @tos: tos
* @ttl: ttl
*/
struct flow_dissector_key_ip {
__u8 tos;
__u8 ttl;
};
/**
* struct flow_dissector_key_meta:
* @ingress_ifindex: ingress ifindex
* @ingress_iftype: ingress interface type
* @l2_miss: packet did not match an L2 entry during forwarding
*/
struct flow_dissector_key_meta {
int ingress_ifindex;
u16 ingress_iftype;
u8 l2_miss;
};
/**
* struct flow_dissector_key_ct:
* @ct_state: conntrack state after converting with map
* @ct_mark: conttrack mark
* @ct_zone: conntrack zone
* @ct_labels: conntrack labels
*/
struct flow_dissector_key_ct {
u16 ct_state;
u16 ct_zone;
u32 ct_mark;
u32 ct_labels[4];
};
/**
* struct flow_dissector_key_hash:
* @hash: hash value
*/
struct flow_dissector_key_hash {
u32 hash;
};
/**
* struct flow_dissector_key_num_of_vlans:
* @num_of_vlans: num_of_vlans value
*/
struct flow_dissector_key_num_of_vlans {
u8 num_of_vlans;
};
/**
* struct flow_dissector_key_pppoe:
* @session_id: pppoe session id
* @ppp_proto: ppp protocol
* @type: pppoe eth type
*/
struct flow_dissector_key_pppoe {
__be16 session_id;
__be16 ppp_proto;
__be16 type;
};
/**
* struct flow_dissector_key_l2tpv3:
* @session_id: identifier for a l2tp session
*/
struct flow_dissector_key_l2tpv3 {
__be32 session_id;
};
/**
* struct flow_dissector_key_ipsec:
* @spi: identifier for a ipsec connection
*/
struct flow_dissector_key_ipsec {
__be32 spi;
};
/**
* struct flow_dissector_key_cfm
* @mdl_ver: maintenance domain level (mdl) and cfm protocol version
* @opcode: code specifying a type of cfm protocol packet
*
* See 802.1ag, ITU-T G.8013/Y.1731
* 1 2
* |7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | mdl | version | opcode |
* +-----+---------+-+-+-+-+-+-+-+-+
*/
struct flow_dissector_key_cfm {
u8 mdl_ver;
u8 opcode;
};
#define FLOW_DIS_CFM_MDL_MASK GENMASK(7, 5)
#define FLOW_DIS_CFM_MDL_MAX 7
enum flow_dissector_key_id {
FLOW_DISSECTOR_KEY_CONTROL, /* struct flow_dissector_key_control */
FLOW_DISSECTOR_KEY_BASIC, /* struct flow_dissector_key_basic */
FLOW_DISSECTOR_KEY_IPV4_ADDRS, /* struct flow_dissector_key_ipv4_addrs */
FLOW_DISSECTOR_KEY_IPV6_ADDRS, /* struct flow_dissector_key_ipv6_addrs */
FLOW_DISSECTOR_KEY_PORTS, /* struct flow_dissector_key_ports */
FLOW_DISSECTOR_KEY_PORTS_RANGE, /* struct flow_dissector_key_ports */
FLOW_DISSECTOR_KEY_ICMP, /* struct flow_dissector_key_icmp */
FLOW_DISSECTOR_KEY_ETH_ADDRS, /* struct flow_dissector_key_eth_addrs */
FLOW_DISSECTOR_KEY_TIPC, /* struct flow_dissector_key_tipc */
FLOW_DISSECTOR_KEY_ARP, /* struct flow_dissector_key_arp */
FLOW_DISSECTOR_KEY_VLAN, /* struct flow_dissector_key_vlan */
FLOW_DISSECTOR_KEY_FLOW_LABEL, /* struct flow_dissector_key_tags */
FLOW_DISSECTOR_KEY_GRE_KEYID, /* struct flow_dissector_key_keyid */
FLOW_DISSECTOR_KEY_MPLS_ENTROPY, /* struct flow_dissector_key_keyid */
FLOW_DISSECTOR_KEY_ENC_KEYID, /* struct flow_dissector_key_keyid */
FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS, /* struct flow_dissector_key_ipv4_addrs */
FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS, /* struct flow_dissector_key_ipv6_addrs */
FLOW_DISSECTOR_KEY_ENC_CONTROL, /* struct flow_dissector_key_control */
FLOW_DISSECTOR_KEY_ENC_PORTS, /* struct flow_dissector_key_ports */
FLOW_DISSECTOR_KEY_MPLS, /* struct flow_dissector_key_mpls */
FLOW_DISSECTOR_KEY_TCP, /* struct flow_dissector_key_tcp */
FLOW_DISSECTOR_KEY_IP, /* struct flow_dissector_key_ip */
FLOW_DISSECTOR_KEY_CVLAN, /* struct flow_dissector_key_vlan */
FLOW_DISSECTOR_KEY_ENC_IP, /* struct flow_dissector_key_ip */
FLOW_DISSECTOR_KEY_ENC_OPTS, /* struct flow_dissector_key_enc_opts */
FLOW_DISSECTOR_KEY_META, /* struct flow_dissector_key_meta */
FLOW_DISSECTOR_KEY_CT, /* struct flow_dissector_key_ct */
FLOW_DISSECTOR_KEY_HASH, /* struct flow_dissector_key_hash */
FLOW_DISSECTOR_KEY_NUM_OF_VLANS, /* struct flow_dissector_key_num_of_vlans */
FLOW_DISSECTOR_KEY_PPPOE, /* struct flow_dissector_key_pppoe */
FLOW_DISSECTOR_KEY_L2TPV3, /* struct flow_dissector_key_l2tpv3 */
FLOW_DISSECTOR_KEY_CFM, /* struct flow_dissector_key_cfm */
FLOW_DISSECTOR_KEY_IPSEC, /* struct flow_dissector_key_ipsec */
FLOW_DISSECTOR_KEY_MAX,
};
#define FLOW_DISSECTOR_F_PARSE_1ST_FRAG BIT(0)
#define FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL BIT(1)
#define FLOW_DISSECTOR_F_STOP_AT_ENCAP BIT(2)
#define FLOW_DISSECTOR_F_STOP_BEFORE_ENCAP BIT(3)
struct flow_dissector_key {
enum flow_dissector_key_id key_id;
size_t offset; /* offset of struct flow_dissector_key_*
in target the struct */
};
struct flow_dissector {
unsigned long long used_keys;
/* each bit represents presence of one key id */
unsigned short int offset[FLOW_DISSECTOR_KEY_MAX];
};
struct flow_keys_basic {
struct flow_dissector_key_control control;
struct flow_dissector_key_basic basic;
};
struct flow_keys {
struct flow_dissector_key_control control;
#define FLOW_KEYS_HASH_START_FIELD basic
struct flow_dissector_key_basic basic __aligned(SIPHASH_ALIGNMENT);
struct flow_dissector_key_tags tags;
struct flow_dissector_key_vlan vlan;
struct flow_dissector_key_vlan cvlan;
struct flow_dissector_key_keyid keyid;
struct flow_dissector_key_ports ports;
struct flow_dissector_key_icmp icmp;
/* 'addrs' must be the last member */
struct flow_dissector_key_addrs addrs;
};
#define FLOW_KEYS_HASH_OFFSET \
offsetof(struct flow_keys, FLOW_KEYS_HASH_START_FIELD)
__be32 flow_get_u32_src(const struct flow_keys *flow);
__be32 flow_get_u32_dst(const struct flow_keys *flow);
extern struct flow_dissector flow_keys_dissector;
extern struct flow_dissector flow_keys_basic_dissector;
/* struct flow_keys_digest:
*
* This structure is used to hold a digest of the full flow keys. This is a
* larger "hash" of a flow to allow definitively matching specific flows where
* the 32 bit skb->hash is not large enough. The size is limited to 16 bytes so
* that it can be used in CB of skb (see sch_choke for an example).
*/
#define FLOW_KEYS_DIGEST_LEN 16
struct flow_keys_digest {
u8 data[FLOW_KEYS_DIGEST_LEN];
};
void make_flow_keys_digest(struct flow_keys_digest *digest,
const struct flow_keys *flow);
static inline bool flow_keys_have_l4(const struct flow_keys *keys)
{
return (keys->ports.ports || keys->tags.flow_label);
}
u32 flow_hash_from_keys(struct flow_keys *keys);
u32 flow_hash_from_keys_seed(struct flow_keys *keys,
const siphash_key_t *keyval);
void skb_flow_get_icmp_tci(const struct sk_buff *skb,
struct flow_dissector_key_icmp *key_icmp,
const void *data, int thoff, int hlen);
static inline bool dissector_uses_key(const struct flow_dissector *flow_dissector,
enum flow_dissector_key_id key_id)
{
return flow_dissector->used_keys & (1ULL << key_id);
}
static inline void *skb_flow_dissector_target(struct flow_dissector *flow_dissector,
enum flow_dissector_key_id key_id,
void *target_container)
{
return ((char *)target_container) + flow_dissector->offset[key_id];
}
struct bpf_flow_dissector {
struct bpf_flow_keys *flow_keys;
const struct sk_buff *skb;
const void *data;
const void *data_end;
};
static inline void
flow_dissector_init_keys(struct flow_dissector_key_control *key_control,
struct flow_dissector_key_basic *key_basic)
{
memset(key_control, 0, sizeof(*key_control));
memset(key_basic, 0, sizeof(*key_basic));
}
#ifdef CONFIG_BPF_SYSCALL
int flow_dissector_bpf_prog_attach_check(struct net *net,
struct bpf_prog *prog);
#endif /* CONFIG_BPF_SYSCALL */
#endif