ice: Enable FDIR Configure for AVF

The virtual channel is going to be extended to support FDIR and
RSS configure from AVF. New data structures and OP codes will be
added, the patch enable the FDIR part.

To support above advanced AVF feature, we need to figure out
what kind of data structure should be passed from VF to PF to describe
an FDIR rule or RSS config rule. The common part of the requirement is
we need a data structure to represent the input set selection of a rule's
hash key.

An input set selection is a group of fields be selected from one or more
network protocol layers that could be identified as a specific flow.
For example, select dst IP address from an IPv4 header combined with
dst port from the TCP header as the input set for an IPv4/TCP flow.

The patch adds a new data structure virtchnl_proto_hdrs to abstract
a network protocol headers group which is composed of layers of network
protocol header(virtchnl_proto_hdr).

A protocol header contains a 32 bits mask (field_selector) to describe
which fields are selected as input sets, as well as a header type
(enum virtchnl_proto_hdr_type). Each bit is mapped to a field in
enum virtchnl_proto_hdr_field guided by its header type.

+------------+-----------+------------------------------+
|            | Proto Hdr | Header Type A                |
|            |           +------------------------------+
|            |           | BIT 31 | ... | BIT 1 | BIT 0 |
|            |-----------+------------------------------+
|Proto Hdrs  | Proto Hdr | Header Type B                |
|            |           +------------------------------+
|            |           | BIT 31 | ... | BIT 1 | BIT 0 |
|            |-----------+------------------------------+
|            | Proto Hdr | Header Type C                |
|            |           +------------------------------+
|            |           | BIT 31 | ... | BIT 1 | BIT 0 |
|            |-----------+------------------------------+
|            |    ....                                  |
+-------------------------------------------------------+

All fields in enum virtchnl_proto_hdr_fields are grouped with header type
and the value of the first field of a header type is always 32 aligned.

enum proto_hdr_type {
        header_type_A = 0;
        header_type_B = 1;
        ....
}

enum proto_hdr_field {
        /* header type A */
        header_A_field_0 = 0,
        header_A_field_1 = 1,
        header_A_field_2 = 2,
        header_A_field_3 = 3,

        /* header type B */
        header_B_field_0 = 32, // = header_type_B << 5
        header_B_field_0 = 33,
        header_B_field_0 = 34
        header_B_field_0 = 35,
        ....
};

So we have:
proto_hdr_type = proto_hdr_field / 32
bit offset = proto_hdr_field % 32

To simply the protocol header's operations, couple help macros are added.
For example, to select src IP and dst port as input set for an IPv4/UDP
flow.

we have:
struct virtchnl_proto_hdr hdr[2];

VIRTCHNL_SET_PROTO_HDR_TYPE(&hdr[0], IPV4)
VIRTCHNL_ADD_PROTO_HDR_FIELD(&hdr[0], IPV4, SRC)

VIRTCHNL_SET_PROTO_HDR_TYPE(&hdr[1], UDP)
VIRTCHNL_ADD_PROTO_HDR_FIELD(&hdr[1], UDP, DST)

The byte array is used to store the protocol header of a training package.
The byte array must be network order.

The patch added virtual channel support for iAVF FDIR add/validate/delete
filter. iAVF FDIR is Flow Director for Intel Adaptive Virtual Function
which can direct Ethernet packets to the queues of the Network Interface
Card. Add/delete command is adding or deleting one rule for each virtual
channel message, while validate command is just verifying if this rule
is valid without any other operations.

To add or delete one rule, driver needs to config TCAM and Profile,
build training packets which contains the input set value, and send
the training packets through FDIR Tx queue. In addition, driver needs to
manage the software context to avoid adding duplicated rules, deleting
non-existent rule, input set conflicts and other invalid cases.

NOTE:
Supported pattern/actions and their parse functions are not be included in
this patch, they will be added in a separate one.

Signed-off-by: Jeff Guo <jia.guo@intel.com>
Signed-off-by: Yahui Cao <yahui.cao@intel.com>
Signed-off-by: Simei Su <simei.su@intel.com>
Signed-off-by: Beilei Xing <beilei.xing@intel.com>
Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
Tested-by: Chen Bo <BoX.C.Chen@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
This commit is contained in:
Qi Zhang 2021-03-09 11:08:04 +08:00 committed by Tony Nguyen
parent da62c5ff9d
commit 1f7ea1cd6a
10 changed files with 1372 additions and 6 deletions

View File

@ -26,7 +26,7 @@ ice-y := ice_main.o \
ice_fw_update.o \
ice_lag.o \
ice_ethtool.o
ice-$(CONFIG_PCI_IOV) += ice_virtchnl_pf.o ice_sriov.o
ice-$(CONFIG_PCI_IOV) += ice_virtchnl_pf.o ice_sriov.o ice_virtchnl_fdir.o
ice-$(CONFIG_DCB) += ice_dcb.o ice_dcb_nl.o ice_dcb_lib.o
ice-$(CONFIG_RFS_ACCEL) += ice_arfs.o
ice-$(CONFIG_XDP_SOCKETS) += ice_xsk.o

View File

@ -1679,6 +1679,10 @@ int ice_add_fdir_ethtool(struct ice_vsi *vsi, struct ethtool_rxnfc *cmd)
input->flex_offset = userdata.flex_offset;
}
input->cnt_ena = ICE_FXD_FLTR_QW0_STAT_ENA_PKTS;
input->fdid_prio = ICE_FXD_FLTR_QW1_FDID_PRI_THREE;
input->comp_report = ICE_FXD_FLTR_QW0_COMP_REPORT_SW_FAIL;
/* input struct is added to the HW filter list */
ice_fdir_update_list_entry(pf, input, fsp->location);

View File

@ -378,7 +378,7 @@ ice_fdir_get_prgm_desc(struct ice_hw *hw, struct ice_fdir_fltr *input,
fdir_fltr_ctx.drop = ICE_FXD_FLTR_QW0_DROP_NO;
fdir_fltr_ctx.qindex = input->q_index;
}
fdir_fltr_ctx.cnt_ena = ICE_FXD_FLTR_QW0_STAT_ENA_PKTS;
fdir_fltr_ctx.cnt_ena = input->cnt_ena;
fdir_fltr_ctx.cnt_index = input->cnt_index;
fdir_fltr_ctx.fd_vsi = ice_get_hw_vsi_num(hw, input->dest_vsi);
fdir_fltr_ctx.evict_ena = ICE_FXD_FLTR_QW0_EVICT_ENA_FALSE;
@ -387,8 +387,8 @@ ice_fdir_get_prgm_desc(struct ice_hw *hw, struct ice_fdir_fltr *input,
ICE_FXD_FLTR_QW1_PCMD_REMOVE;
fdir_fltr_ctx.swap = ICE_FXD_FLTR_QW1_SWAP_NOT_SET;
fdir_fltr_ctx.comp_q = ICE_FXD_FLTR_QW0_COMP_Q_ZERO;
fdir_fltr_ctx.comp_report = ICE_FXD_FLTR_QW0_COMP_REPORT_SW_FAIL;
fdir_fltr_ctx.fdid_prio = 3;
fdir_fltr_ctx.comp_report = input->comp_report;
fdir_fltr_ctx.fdid_prio = input->fdid_prio;
fdir_fltr_ctx.desc_prof = 1;
fdir_fltr_ctx.desc_prof_prio = 3;
ice_set_fd_desc_val(&fdir_fltr_ctx, fdesc);

View File

@ -31,6 +31,8 @@
#define ICE_IPV6_HLIM_OFFSET 21
#define ICE_IPV6_PROTO_OFFSET 20
#define ICE_FDIR_MAX_FLTRS 16384
/* IP v4 has 2 flag bits that enable fragment processing: DF and MF. DF
* requests that the packet not be fragmented. MF indicates that a packet has
* been fragmented.
@ -138,9 +140,12 @@ struct ice_fdir_fltr {
u16 q_index;
u16 dest_vsi;
u8 dest_ctl;
u8 cnt_ena;
u8 fltr_status;
u16 cnt_index;
u32 fltr_id;
u8 fdid_prio;
u8 comp_report;
};
/* Dummy packet filter definition structure */

View File

@ -55,6 +55,7 @@ struct ice_fltr_desc {
#define ICE_FXD_FLTR_QW0_COMP_REPORT_M \
(0x3ULL << ICE_FXD_FLTR_QW0_COMP_REPORT_S)
#define ICE_FXD_FLTR_QW0_COMP_REPORT_SW_FAIL 0x1ULL
#define ICE_FXD_FLTR_QW0_COMP_REPORT_SW 0x2ULL
#define ICE_FXD_FLTR_QW0_FD_SPACE_S 14
#define ICE_FXD_FLTR_QW0_FD_SPACE_M (0x3ULL << ICE_FXD_FLTR_QW0_FD_SPACE_S)
@ -128,6 +129,7 @@ struct ice_fltr_desc {
#define ICE_FXD_FLTR_QW1_FDID_PRI_S 25
#define ICE_FXD_FLTR_QW1_FDID_PRI_M (0x7ULL << ICE_FXD_FLTR_QW1_FDID_PRI_S)
#define ICE_FXD_FLTR_QW1_FDID_PRI_ONE 0x1ULL
#define ICE_FXD_FLTR_QW1_FDID_PRI_THREE 0x3ULL
#define ICE_FXD_FLTR_QW1_FDID_MDID_S 28
#define ICE_FXD_FLTR_QW1_FDID_MDID_M (0xFULL << ICE_FXD_FLTR_QW1_FDID_MDID_S)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,24 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (C) 2021, Intel Corporation. */
#ifndef _ICE_VIRTCHNL_FDIR_H_
#define _ICE_VIRTCHNL_FDIR_H_
struct ice_vf;
/* VF FDIR information structure */
struct ice_vf_fdir {
u16 fdir_fltr_cnt[ICE_FLTR_PTYPE_MAX][ICE_FD_HW_SEG_MAX];
int prof_entry_cnt[ICE_FLTR_PTYPE_MAX][ICE_FD_HW_SEG_MAX];
struct ice_fd_hw_prof **fdir_prof;
struct idr fdir_rule_idr;
struct list_head fdir_rule_list;
};
int ice_vc_add_fdir_fltr(struct ice_vf *vf, u8 *msg);
int ice_vc_del_fdir_fltr(struct ice_vf *vf, u8 *msg);
void ice_vf_fdir_init(struct ice_vf *vf);
void ice_vf_fdir_exit(struct ice_vf *vf);
#endif /* _ICE_VIRTCHNL_FDIR_H_ */

View File

@ -233,6 +233,7 @@ static void ice_free_vf_res(struct ice_vf *vf)
* accessing the VF's VSI after it's freed or invalidated.
*/
clear_bit(ICE_VF_STATE_INIT, vf->vf_states);
ice_vf_fdir_exit(vf);
/* free VF control VSI */
if (vf->ctrl_vsi_idx != ICE_NO_VSI)
ice_vf_ctrl_vsi_release(vf);
@ -1300,6 +1301,7 @@ bool ice_reset_all_vfs(struct ice_pf *pf, bool is_vflr)
ice_for_each_vf(pf, v) {
vf = &pf->vf[v];
ice_vf_fdir_exit(vf);
/* clean VF control VSI when resetting VFs since it should be
* setup only when VF creates its first FDIR rule.
*/
@ -1424,6 +1426,7 @@ bool ice_reset_vf(struct ice_vf *vf, bool is_vflr)
dev_err(dev, "disabling promiscuous mode failed\n");
}
ice_vf_fdir_exit(vf);
/* clean VF control VSI when resetting VF since it should be setup
* only when VF creates its first FDIR rule.
*/
@ -1610,6 +1613,7 @@ static void ice_set_dflt_settings_vfs(struct ice_pf *pf)
* creates its first fdir rule.
*/
ice_vf_ctrl_invalidate_vsi(vf);
ice_vf_fdir_init(vf);
}
}
@ -1909,7 +1913,7 @@ ice_vf_lan_overflow_event(struct ice_pf *pf, struct ice_rq_event_info *event)
*
* send msg to VF
*/
static int
int
ice_vc_send_msg_to_vf(struct ice_vf *vf, u32 v_opcode,
enum virtchnl_status_code v_retval, u8 *msg, u16 msglen)
{
@ -2057,6 +2061,9 @@ static int ice_vc_get_vf_res_msg(struct ice_vf *vf, u8 *msg)
vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_RSS_REG;
}
if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_FDIR_PF)
vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_FDIR_PF;
if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2)
vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2;
@ -2145,7 +2152,7 @@ static struct ice_vsi *ice_find_vsi_from_id(struct ice_pf *pf, u16 id)
*
* check for the valid VSI ID
*/
static bool ice_vc_isvalid_vsi_id(struct ice_vf *vf, u16 vsi_id)
bool ice_vc_isvalid_vsi_id(struct ice_vf *vf, u16 vsi_id)
{
struct ice_pf *pf = vf->pf;
struct ice_vsi *vsi;
@ -3877,6 +3884,12 @@ error_handler:
case VIRTCHNL_OP_DISABLE_VLAN_STRIPPING:
err = ice_vc_dis_vlan_stripping(vf);
break;
case VIRTCHNL_OP_ADD_FDIR_FILTER:
err = ice_vc_add_fdir_fltr(vf, msg);
break;
case VIRTCHNL_OP_DEL_FDIR_FILTER:
err = ice_vc_del_fdir_fltr(vf, msg);
break;
case VIRTCHNL_OP_UNKNOWN:
default:
dev_err(dev, "Unsupported opcode %d from VF %d\n", v_opcode,

View File

@ -4,6 +4,7 @@
#ifndef _ICE_VIRTCHNL_PF_H_
#define _ICE_VIRTCHNL_PF_H_
#include "ice.h"
#include "ice_virtchnl_fdir.h"
/* Restrict number of MAC Addr and VLAN that non-trusted VF can programmed */
#define ICE_MAX_VLAN_PER_VF 8
@ -71,6 +72,7 @@ struct ice_vf {
u16 vf_id; /* VF ID in the PF space */
u16 lan_vsi_idx; /* index into PF struct */
u16 ctrl_vsi_idx;
struct ice_vf_fdir fdir;
/* first vector index of this VF in the PF space */
int first_vector_idx;
struct ice_sw *vf_sw_id; /* switch ID the VF VSIs connect to */
@ -140,6 +142,10 @@ ice_vf_lan_overflow_event(struct ice_pf *pf, struct ice_rq_event_info *event);
void ice_print_vfs_mdd_events(struct ice_pf *pf);
void ice_print_vf_rx_mdd_event(struct ice_vf *vf);
struct ice_vsi *ice_vf_ctrl_vsi_setup(struct ice_vf *vf);
int
ice_vc_send_msg_to_vf(struct ice_vf *vf, u32 v_opcode,
enum virtchnl_status_code v_retval, u8 *msg, u16 msglen);
bool ice_vc_isvalid_vsi_id(struct ice_vf *vf, u16 vsi_id);
#else /* CONFIG_PCI_IOV */
#define ice_process_vflr_event(pf) do {} while (0)
#define ice_free_vfs(pf) do {} while (0)

View File

@ -136,6 +136,9 @@ enum virtchnl_ops {
VIRTCHNL_OP_DISABLE_CHANNELS = 31,
VIRTCHNL_OP_ADD_CLOUD_FILTER = 32,
VIRTCHNL_OP_DEL_CLOUD_FILTER = 33,
/* opcode 34 - 46 are reserved */
VIRTCHNL_OP_ADD_FDIR_FILTER = 47,
VIRTCHNL_OP_DEL_FDIR_FILTER = 48,
};
/* These macros are used to generate compilation errors if a structure/union
@ -247,6 +250,7 @@ VIRTCHNL_CHECK_STRUCT_LEN(16, virtchnl_vsi_resource);
#define VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM 0X00200000
#define VIRTCHNL_VF_OFFLOAD_RX_ENCAP_CSUM 0X00400000
#define VIRTCHNL_VF_OFFLOAD_ADQ 0X00800000
#define VIRTCHNL_VF_OFFLOAD_FDIR_PF 0X10000000
/* Define below the capability flags that are not offloads */
#define VIRTCHNL_VF_CAP_ADV_LINK_SPEED 0x00000080
@ -559,6 +563,11 @@ enum virtchnl_action {
/* action types */
VIRTCHNL_ACTION_DROP = 0,
VIRTCHNL_ACTION_TC_REDIRECT,
VIRTCHNL_ACTION_PASSTHRU,
VIRTCHNL_ACTION_QUEUE,
VIRTCHNL_ACTION_Q_REGION,
VIRTCHNL_ACTION_MARK,
VIRTCHNL_ACTION_COUNT,
};
enum virtchnl_flow_type {
@ -668,6 +677,269 @@ enum virtchnl_vfr_states {
VIRTCHNL_VFR_VFACTIVE,
};
#define VIRTCHNL_MAX_NUM_PROTO_HDRS 32
#define PROTO_HDR_SHIFT 5
#define PROTO_HDR_FIELD_START(proto_hdr_type) ((proto_hdr_type) << PROTO_HDR_SHIFT)
#define PROTO_HDR_FIELD_MASK ((1UL << PROTO_HDR_SHIFT) - 1)
/* VF use these macros to configure each protocol header.
* Specify which protocol headers and protocol header fields base on
* virtchnl_proto_hdr_type and virtchnl_proto_hdr_field.
* @param hdr: a struct of virtchnl_proto_hdr
* @param hdr_type: ETH/IPV4/TCP, etc
* @param field: SRC/DST/TEID/SPI, etc
*/
#define VIRTCHNL_ADD_PROTO_HDR_FIELD(hdr, field) \
((hdr)->field_selector |= BIT((field) & PROTO_HDR_FIELD_MASK))
#define VIRTCHNL_DEL_PROTO_HDR_FIELD(hdr, field) \
((hdr)->field_selector &= ~BIT((field) & PROTO_HDR_FIELD_MASK))
#define VIRTCHNL_TEST_PROTO_HDR_FIELD(hdr, val) \
((hdr)->field_selector & BIT((val) & PROTO_HDR_FIELD_MASK))
#define VIRTCHNL_GET_PROTO_HDR_FIELD(hdr) ((hdr)->field_selector)
#define VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, hdr_type, field) \
(VIRTCHNL_ADD_PROTO_HDR_FIELD(hdr, \
VIRTCHNL_PROTO_HDR_ ## hdr_type ## _ ## field))
#define VIRTCHNL_DEL_PROTO_HDR_FIELD_BIT(hdr, hdr_type, field) \
(VIRTCHNL_DEL_PROTO_HDR_FIELD(hdr, \
VIRTCHNL_PROTO_HDR_ ## hdr_type ## _ ## field))
#define VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, hdr_type) \
((hdr)->type = VIRTCHNL_PROTO_HDR_ ## hdr_type)
#define VIRTCHNL_GET_PROTO_HDR_TYPE(hdr) \
(((hdr)->type) >> PROTO_HDR_SHIFT)
#define VIRTCHNL_TEST_PROTO_HDR_TYPE(hdr, val) \
((hdr)->type == ((val) >> PROTO_HDR_SHIFT))
#define VIRTCHNL_TEST_PROTO_HDR(hdr, val) \
(VIRTCHNL_TEST_PROTO_HDR_TYPE((hdr), (val)) && \
VIRTCHNL_TEST_PROTO_HDR_FIELD((hdr), (val)))
/* Protocol header type within a packet segment. A segment consists of one or
* more protocol headers that make up a logical group of protocol headers. Each
* logical group of protocol headers encapsulates or is encapsulated using/by
* tunneling or encapsulation protocols for network virtualization.
*/
enum virtchnl_proto_hdr_type {
VIRTCHNL_PROTO_HDR_NONE,
VIRTCHNL_PROTO_HDR_ETH,
VIRTCHNL_PROTO_HDR_S_VLAN,
VIRTCHNL_PROTO_HDR_C_VLAN,
VIRTCHNL_PROTO_HDR_IPV4,
VIRTCHNL_PROTO_HDR_IPV6,
VIRTCHNL_PROTO_HDR_TCP,
VIRTCHNL_PROTO_HDR_UDP,
VIRTCHNL_PROTO_HDR_SCTP,
VIRTCHNL_PROTO_HDR_GTPU_IP,
VIRTCHNL_PROTO_HDR_GTPU_EH,
VIRTCHNL_PROTO_HDR_GTPU_EH_PDU_DWN,
VIRTCHNL_PROTO_HDR_GTPU_EH_PDU_UP,
VIRTCHNL_PROTO_HDR_PPPOE,
VIRTCHNL_PROTO_HDR_L2TPV3,
VIRTCHNL_PROTO_HDR_ESP,
VIRTCHNL_PROTO_HDR_AH,
VIRTCHNL_PROTO_HDR_PFCP,
};
/* Protocol header field within a protocol header. */
enum virtchnl_proto_hdr_field {
/* ETHER */
VIRTCHNL_PROTO_HDR_ETH_SRC =
PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_ETH),
VIRTCHNL_PROTO_HDR_ETH_DST,
VIRTCHNL_PROTO_HDR_ETH_ETHERTYPE,
/* S-VLAN */
VIRTCHNL_PROTO_HDR_S_VLAN_ID =
PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_S_VLAN),
/* C-VLAN */
VIRTCHNL_PROTO_HDR_C_VLAN_ID =
PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_C_VLAN),
/* IPV4 */
VIRTCHNL_PROTO_HDR_IPV4_SRC =
PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_IPV4),
VIRTCHNL_PROTO_HDR_IPV4_DST,
VIRTCHNL_PROTO_HDR_IPV4_DSCP,
VIRTCHNL_PROTO_HDR_IPV4_TTL,
VIRTCHNL_PROTO_HDR_IPV4_PROT,
/* IPV6 */
VIRTCHNL_PROTO_HDR_IPV6_SRC =
PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_IPV6),
VIRTCHNL_PROTO_HDR_IPV6_DST,
VIRTCHNL_PROTO_HDR_IPV6_TC,
VIRTCHNL_PROTO_HDR_IPV6_HOP_LIMIT,
VIRTCHNL_PROTO_HDR_IPV6_PROT,
/* TCP */
VIRTCHNL_PROTO_HDR_TCP_SRC_PORT =
PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_TCP),
VIRTCHNL_PROTO_HDR_TCP_DST_PORT,
/* UDP */
VIRTCHNL_PROTO_HDR_UDP_SRC_PORT =
PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_UDP),
VIRTCHNL_PROTO_HDR_UDP_DST_PORT,
/* SCTP */
VIRTCHNL_PROTO_HDR_SCTP_SRC_PORT =
PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_SCTP),
VIRTCHNL_PROTO_HDR_SCTP_DST_PORT,
/* GTPU_IP */
VIRTCHNL_PROTO_HDR_GTPU_IP_TEID =
PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_GTPU_IP),
/* GTPU_EH */
VIRTCHNL_PROTO_HDR_GTPU_EH_PDU =
PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_GTPU_EH),
VIRTCHNL_PROTO_HDR_GTPU_EH_QFI,
/* PPPOE */
VIRTCHNL_PROTO_HDR_PPPOE_SESS_ID =
PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_PPPOE),
/* L2TPV3 */
VIRTCHNL_PROTO_HDR_L2TPV3_SESS_ID =
PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_L2TPV3),
/* ESP */
VIRTCHNL_PROTO_HDR_ESP_SPI =
PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_ESP),
/* AH */
VIRTCHNL_PROTO_HDR_AH_SPI =
PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_AH),
/* PFCP */
VIRTCHNL_PROTO_HDR_PFCP_S_FIELD =
PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_PFCP),
VIRTCHNL_PROTO_HDR_PFCP_SEID,
};
struct virtchnl_proto_hdr {
enum virtchnl_proto_hdr_type type;
u32 field_selector; /* a bit mask to select field for header type */
u8 buffer[64];
/**
* binary buffer in network order for specific header type.
* For example, if type = VIRTCHNL_PROTO_HDR_IPV4, a IPv4
* header is expected to be copied into the buffer.
*/
};
VIRTCHNL_CHECK_STRUCT_LEN(72, virtchnl_proto_hdr);
struct virtchnl_proto_hdrs {
u8 tunnel_level;
/**
* specify where protocol header start from.
* 0 - from the outer layer
* 1 - from the first inner layer
* 2 - from the second inner layer
* ....
**/
int count; /* the proto layers must < VIRTCHNL_MAX_NUM_PROTO_HDRS */
struct virtchnl_proto_hdr proto_hdr[VIRTCHNL_MAX_NUM_PROTO_HDRS];
};
VIRTCHNL_CHECK_STRUCT_LEN(2312, virtchnl_proto_hdrs);
/* action configuration for FDIR */
struct virtchnl_filter_action {
enum virtchnl_action type;
union {
/* used for queue and qgroup action */
struct {
u16 index;
u8 region;
} queue;
/* used for count action */
struct {
/* share counter ID with other flow rules */
u8 shared;
u32 id; /* counter ID */
} count;
/* used for mark action */
u32 mark_id;
u8 reserve[32];
} act_conf;
};
VIRTCHNL_CHECK_STRUCT_LEN(36, virtchnl_filter_action);
#define VIRTCHNL_MAX_NUM_ACTIONS 8
struct virtchnl_filter_action_set {
/* action number must be less then VIRTCHNL_MAX_NUM_ACTIONS */
int count;
struct virtchnl_filter_action actions[VIRTCHNL_MAX_NUM_ACTIONS];
};
VIRTCHNL_CHECK_STRUCT_LEN(292, virtchnl_filter_action_set);
/* pattern and action for FDIR rule */
struct virtchnl_fdir_rule {
struct virtchnl_proto_hdrs proto_hdrs;
struct virtchnl_filter_action_set action_set;
};
VIRTCHNL_CHECK_STRUCT_LEN(2604, virtchnl_fdir_rule);
/* Status returned to VF after VF requests FDIR commands
* VIRTCHNL_FDIR_SUCCESS
* VF FDIR related request is successfully done by PF
* The request can be OP_ADD/DEL.
*
* VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE
* OP_ADD_FDIR_FILTER request is failed due to no Hardware resource.
*
* VIRTCHNL_FDIR_FAILURE_RULE_EXIST
* OP_ADD_FDIR_FILTER request is failed due to the rule is already existed.
*
* VIRTCHNL_FDIR_FAILURE_RULE_CONFLICT
* OP_ADD_FDIR_FILTER request is failed due to conflict with existing rule.
*
* VIRTCHNL_FDIR_FAILURE_RULE_NONEXIST
* OP_DEL_FDIR_FILTER request is failed due to this rule doesn't exist.
*
* VIRTCHNL_FDIR_FAILURE_RULE_INVALID
* OP_ADD_FDIR_FILTER request is failed due to parameters validation
* or HW doesn't support.
*
* VIRTCHNL_FDIR_FAILURE_RULE_TIMEOUT
* OP_ADD/DEL_FDIR_FILTER request is failed due to timing out
* for programming.
*/
enum virtchnl_fdir_prgm_status {
VIRTCHNL_FDIR_SUCCESS = 0,
VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE,
VIRTCHNL_FDIR_FAILURE_RULE_EXIST,
VIRTCHNL_FDIR_FAILURE_RULE_CONFLICT,
VIRTCHNL_FDIR_FAILURE_RULE_NONEXIST,
VIRTCHNL_FDIR_FAILURE_RULE_INVALID,
VIRTCHNL_FDIR_FAILURE_RULE_TIMEOUT,
};
/* VIRTCHNL_OP_ADD_FDIR_FILTER
* VF sends this request to PF by filling out vsi_id,
* validate_only and rule_cfg. PF will return flow_id
* if the request is successfully done and return add_status to VF.
*/
struct virtchnl_fdir_add {
u16 vsi_id; /* INPUT */
/*
* 1 for validating a fdir rule, 0 for creating a fdir rule.
* Validate and create share one ops: VIRTCHNL_OP_ADD_FDIR_FILTER.
*/
u16 validate_only; /* INPUT */
u32 flow_id; /* OUTPUT */
struct virtchnl_fdir_rule rule_cfg; /* INPUT */
enum virtchnl_fdir_prgm_status status; /* OUTPUT */
};
VIRTCHNL_CHECK_STRUCT_LEN(2616, virtchnl_fdir_add);
/* VIRTCHNL_OP_DEL_FDIR_FILTER
* VF sends this request to PF by filling out vsi_id
* and flow_id. PF will return del_status to VF.
*/
struct virtchnl_fdir_del {
u16 vsi_id; /* INPUT */
u16 pad;
u32 flow_id; /* INPUT */
enum virtchnl_fdir_prgm_status status; /* OUTPUT */
};
VIRTCHNL_CHECK_STRUCT_LEN(12, virtchnl_fdir_del);
/**
* virtchnl_vc_validate_vf_msg
* @ver: Virtchnl version info
@ -828,6 +1100,12 @@ virtchnl_vc_validate_vf_msg(struct virtchnl_version_info *ver, u32 v_opcode,
case VIRTCHNL_OP_DEL_CLOUD_FILTER:
valid_len = sizeof(struct virtchnl_filter);
break;
case VIRTCHNL_OP_ADD_FDIR_FILTER:
valid_len = sizeof(struct virtchnl_fdir_add);
break;
case VIRTCHNL_OP_DEL_FDIR_FILTER:
valid_len = sizeof(struct virtchnl_fdir_del);
break;
/* These are always errors coming from the VF. */
case VIRTCHNL_OP_EVENT:
case VIRTCHNL_OP_UNKNOWN: