mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
synced 2025-09-05 11:53:41 +00:00

Add support for offloading cls U32 filters. Only "skbedit queue_mapping" and "drop" actions are supported. Also, only "ip" and "802_3" tc protocols are allowed. The PF must advertise the VIRTCHNL_VF_OFFLOAD_TC_U32 capability flag. Since the filters will be enabled via the FD stage at the PF, a new type of FDIR filters is added and the existing list and state machine are used. The new filters can be used to configure flow directors based on raw (binary) pattern in the rx packet. Examples: 0. # tc qdisc add dev enp175s0v0 ingress 1. Redirect UDP from src IP 192.168.2.1 to queue 12: # tc filter add dev <dev> protocol ip ingress u32 \ match u32 0x45000000 0xff000000 at 0 \ match u32 0x00110000 0x00ff0000 at 8 \ match u32 0xC0A80201 0xffffffff at 12 \ match u32 0x00000000 0x00000000 at 24 \ action skbedit queue_mapping 12 skip_sw 2. Drop all ICMP: # tc filter add dev <dev> protocol ip ingress u32 \ match u32 0x45000000 0xff000000 at 0 \ match u32 0x00010000 0x00ff0000 at 8 \ match u32 0x00000000 0x00000000 at 24 \ action drop skip_sw 3. Redirect ICMP traffic from MAC 3c:fd:fe:a5:47:e0 to queue 7 (note proto: 802_3): # tc filter add dev <dev> protocol 802_3 ingress u32 \ match u32 0x00003CFD 0x0000ffff at 4 \ match u32 0xFEA547E0 0xffffffff at 8 \ match u32 0x08004500 0xffffff00 at 12 \ match u32 0x00000001 0x000000ff at 20 \ match u32 0x0000 0x0000 at 40 \ action skbedit queue_mapping 7 skip_sw Notes on matches: 1 - All intermediate fields that are needed to parse the correct PTYPE must be provided (in e.g. 3: Ethernet Type 0x0800 in MAC, IP version and IP length: 0x45 and protocol: 0x01 (ICMP)). 2 - The last match must provide an offset that guarantees all required headers are accounted for, even if the last header is not matched. For example, in #2, the last match is 4 bytes at offset 24 starting from IP header, so the total is 14 (MAC) + 24 + 4 = 42, which is the sum of MAC+IP+ICMP headers. Reviewed-by: Sridhar Samudrala <sridhar.samudrala@intel.com> Reviewed-by: Marcin Szycik <marcin.szycik@linux.intel.com> Signed-off-by: Ahmed Zaki <ahmed.zaki@intel.com> Tested-by: Rafal Romanowski <rafal.romanowski@intel.com> Reviewed-by: Simon Horman <horms@kernel.org> Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
143 lines
4.0 KiB
C
143 lines
4.0 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/* Copyright (c) 2021, Intel Corporation. */
|
|
|
|
#ifndef _IAVF_FDIR_H_
|
|
#define _IAVF_FDIR_H_
|
|
|
|
struct iavf_adapter;
|
|
|
|
/* State of Flow Director filter
|
|
*
|
|
* *_REQUEST states are used to mark filter to be sent to PF driver to perform
|
|
* an action (either add or delete filter). *_PENDING states are an indication
|
|
* that request was sent to PF and the driver is waiting for response.
|
|
*
|
|
* Both DELETE and DISABLE states are being used to delete a filter in PF.
|
|
* The difference is that after a successful response filter in DEL_PENDING
|
|
* state is being deleted from VF driver as well and filter in DIS_PENDING state
|
|
* is being changed to INACTIVE state.
|
|
*/
|
|
enum iavf_fdir_fltr_state_t {
|
|
IAVF_FDIR_FLTR_ADD_REQUEST, /* User requests to add filter */
|
|
IAVF_FDIR_FLTR_ADD_PENDING, /* Filter pending add by the PF */
|
|
IAVF_FDIR_FLTR_DEL_REQUEST, /* User requests to delete filter */
|
|
IAVF_FDIR_FLTR_DEL_PENDING, /* Filter pending delete by the PF */
|
|
IAVF_FDIR_FLTR_DIS_REQUEST, /* Filter scheduled to be disabled */
|
|
IAVF_FDIR_FLTR_DIS_PENDING, /* Filter pending disable by the PF */
|
|
IAVF_FDIR_FLTR_INACTIVE, /* Filter inactive on link down */
|
|
IAVF_FDIR_FLTR_ACTIVE, /* Filter is active */
|
|
};
|
|
|
|
enum iavf_fdir_flow_type {
|
|
/* NONE - used for undef/error */
|
|
IAVF_FDIR_FLOW_NONE = 0,
|
|
IAVF_FDIR_FLOW_IPV4_TCP,
|
|
IAVF_FDIR_FLOW_IPV4_UDP,
|
|
IAVF_FDIR_FLOW_IPV4_SCTP,
|
|
IAVF_FDIR_FLOW_IPV4_AH,
|
|
IAVF_FDIR_FLOW_IPV4_ESP,
|
|
IAVF_FDIR_FLOW_IPV4_OTHER,
|
|
IAVF_FDIR_FLOW_IPV6_TCP,
|
|
IAVF_FDIR_FLOW_IPV6_UDP,
|
|
IAVF_FDIR_FLOW_IPV6_SCTP,
|
|
IAVF_FDIR_FLOW_IPV6_AH,
|
|
IAVF_FDIR_FLOW_IPV6_ESP,
|
|
IAVF_FDIR_FLOW_IPV6_OTHER,
|
|
IAVF_FDIR_FLOW_NON_IP_L2,
|
|
/* MAX - this must be last and add anything new just above it */
|
|
IAVF_FDIR_FLOW_PTYPE_MAX,
|
|
};
|
|
|
|
/* Must not exceed the array element number of '__be32 data[2]' in the ethtool
|
|
* 'struct ethtool_rx_flow_spec.m_ext.data[2]' to express the flex-byte (word).
|
|
*/
|
|
#define IAVF_FLEX_WORD_NUM 2
|
|
|
|
struct iavf_flex_word {
|
|
u16 offset;
|
|
u16 word;
|
|
};
|
|
|
|
struct iavf_ipv4_addrs {
|
|
__be32 src_ip;
|
|
__be32 dst_ip;
|
|
};
|
|
|
|
struct iavf_ipv6_addrs {
|
|
struct in6_addr src_ip;
|
|
struct in6_addr dst_ip;
|
|
};
|
|
|
|
struct iavf_fdir_eth {
|
|
__be16 etype;
|
|
};
|
|
|
|
struct iavf_fdir_ip {
|
|
union {
|
|
struct iavf_ipv4_addrs v4_addrs;
|
|
struct iavf_ipv6_addrs v6_addrs;
|
|
};
|
|
__be16 src_port;
|
|
__be16 dst_port;
|
|
__be32 l4_header; /* first 4 bytes of the layer 4 header */
|
|
__be32 spi; /* security parameter index for AH/ESP */
|
|
union {
|
|
u8 tos;
|
|
u8 tclass;
|
|
};
|
|
u8 proto;
|
|
};
|
|
|
|
struct iavf_fdir_extra {
|
|
u32 usr_def[IAVF_FLEX_WORD_NUM];
|
|
};
|
|
|
|
/* bookkeeping of Flow Director filters */
|
|
struct iavf_fdir_fltr {
|
|
enum iavf_fdir_fltr_state_t state;
|
|
struct list_head list;
|
|
|
|
enum iavf_fdir_flow_type flow_type;
|
|
|
|
struct iavf_fdir_eth eth_data;
|
|
struct iavf_fdir_eth eth_mask;
|
|
|
|
struct iavf_fdir_ip ip_data;
|
|
struct iavf_fdir_ip ip_mask;
|
|
|
|
struct iavf_fdir_extra ext_data;
|
|
struct iavf_fdir_extra ext_mask;
|
|
|
|
enum virtchnl_action action;
|
|
|
|
/* flex byte filter data */
|
|
u8 ip_ver; /* used to adjust the flex offset, 4 : IPv4, 6 : IPv6 */
|
|
u8 flex_cnt;
|
|
struct iavf_flex_word flex_words[IAVF_FLEX_WORD_NUM];
|
|
|
|
u32 flow_id;
|
|
|
|
u32 cls_u32_handle; /* for FDIR added via tc u32 */
|
|
u32 loc; /* Rule location inside the flow table */
|
|
u32 q_index;
|
|
|
|
struct virtchnl_fdir_add vc_add_msg;
|
|
};
|
|
|
|
static inline bool iavf_is_raw_fdir(struct iavf_fdir_fltr *fltr)
|
|
{
|
|
return !fltr->vc_add_msg.rule_cfg.proto_hdrs.count;
|
|
}
|
|
|
|
int iavf_validate_fdir_fltr_masks(struct iavf_adapter *adapter,
|
|
struct iavf_fdir_fltr *fltr);
|
|
int iavf_fill_fdir_add_msg(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr);
|
|
void iavf_print_fdir_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr);
|
|
bool iavf_fdir_is_dup_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr);
|
|
int iavf_fdir_add_fltr(struct iavf_adapter *adapter,
|
|
struct iavf_fdir_fltr *fltr);
|
|
int iavf_fdir_del_fltr(struct iavf_adapter *adapter, bool is_raw, u32 data);
|
|
struct iavf_fdir_fltr *iavf_find_fdir_fltr(struct iavf_adapter *adapter,
|
|
bool is_raw, u32 data);
|
|
#endif /* _IAVF_FDIR_H_ */
|