[v3,3/5] net/ice: add protocol extraction support for per Rx queue
Checks
Commit Message
From: Haiyue Wang <haiyue.wang@intel.com>
The ice has the feature to extract protocol fields into flex descriptor
by programming per queue. Currently, the ice PMD will put the protocol
fields into rte_mbuf::udata64 with different type format. Application
can access the protocol fields quickly.
Signed-off-by: Haiyue Wang <haiyue.wang@intel.com>
---
doc/guides/nics/ice.rst | 101 +++++++++
drivers/net/ice/Makefile | 3 +
drivers/net/ice/ice_ethdev.c | 312 ++++++++++++++++++++++++++
drivers/net/ice/ice_ethdev.h | 5 +
drivers/net/ice/ice_rxtx.c | 61 +++++
drivers/net/ice/ice_rxtx.h | 2 +
drivers/net/ice/ice_rxtx_vec_common.h | 3 +
drivers/net/ice/meson.build | 2 +
drivers/net/ice/rte_pmd_ice.h | 152 +++++++++++++
9 files changed, 641 insertions(+)
create mode 100644 drivers/net/ice/rte_pmd_ice.h
Comments
On 09/17, Leyi Rong wrote:
>From: Haiyue Wang <haiyue.wang@intel.com>
>
>The ice has the feature to extract protocol fields into flex descriptor
>by programming per queue. Currently, the ice PMD will put the protocol
>fields into rte_mbuf::udata64 with different type format. Application
>can access the protocol fields quickly.
>
[snip]
>+static int
>+parse_queue_set(const char *input, int xtr_type, struct ice_devargs *devargs)
>+{
>+ const char *str = input;
>+ char *end = NULL;
>+ uint32_t min, max;
>+ uint32_t idx;
>+
>+ while (isblank(*str))
>+ str++;
>+
>+ if ((!isdigit(*str) && *str != '(') || (*str == '\0'))
Minor nit, (*str == '\0') seems redundant here, no?
>+ return -1;
>+
>+ /* process single number or single range of number */
>+ if (*str != '(') {
>+ errno = 0;
>+ idx = strtoul(str, &end, 10);
>+ if (errno || end == NULL || idx >= ICE_MAX_QUEUE_NUM)
>+ return -1;
>+
>+ while (isblank(*end))
>+ end++;
>+
>+ min = idx;
>+ max = idx;
>+
>+ /* process single <number>-<number> */
>+ if (*end == '-') {
>+ end++;
>+ while (isblank(*end))
>+ end++;
>+ if (!isdigit(*end))
>+ return -1;
>+
>+ errno = 0;
>+ idx = strtoul(end, &end, 10);
>+ if (errno || end == NULL || idx >= ICE_MAX_QUEUE_NUM)
>+ return -1;
>+
>+ max = idx;
>+ while (isblank(*end))
>+ end++;
>+ }
>+
>+ if (*end != ':')
>+ return -1;
>+
>+ for (idx = RTE_MIN(min, max);
>+ idx <= RTE_MAX(min, max); idx++)
>+ devargs->proto_xtr[idx] = xtr_type;
>+
>+ return 0;
>+ }
>+
>+ /* process set within bracket */
>+ str++;
>+ while (isblank(*str))
>+ str++;
>+ if (*str == '\0')
>+ return -1;
>+
>+ min = ICE_MAX_QUEUE_NUM;
>+ do {
>+ /* go ahead to the first digit */
>+ while (isblank(*str))
>+ str++;
>+ if (!isdigit(*str))
>+ return -1;
>+
>+ /* get the digit value */
>+ errno = 0;
>+ idx = strtoul(str, &end, 10);
>+ if (errno || end == NULL || idx >= ICE_MAX_QUEUE_NUM)
>+ return -1;
>+
>+ /* go ahead to separator '-',',' and ')' */
>+ while (isblank(*end))
>+ end++;
>+ if (*end == '-') {
>+ if (min == ICE_MAX_QUEUE_NUM)
>+ min = idx;
>+ else /* avoid continuous '-' */
>+ return -1;
>+ } else if (*end == ',' || *end == ')') {
>+ max = idx;
>+ if (min == ICE_MAX_QUEUE_NUM)
>+ min = idx;
>+
>+ for (idx = RTE_MIN(min, max);
>+ idx <= RTE_MAX(min, max); idx++)
>+ devargs->proto_xtr[idx] = xtr_type;
>+
>+ min = ICE_MAX_QUEUE_NUM;
>+ } else {
>+ return -1;
>+ }
>+
>+ str = end + 1;
>+ } while (*end != ')' && *end != '\0');
>+
>+ return 0;
>+}
>+
>+static int
>+parse_queue_proto_xtr(const char *queues, struct ice_devargs *devargs)
>+{
>+ const char *queue_start;
>+ uint32_t idx;
>+ int xtr_type;
>+ char xtr_name[32];
>+
>+ while (isblank(*queues))
>+ queues++;
>+
>+ if (*queues != '[') {
>+ xtr_type = lookup_proto_xtr_type(queues);
>+ if (xtr_type < 0)
>+ return -1;
>+
>+ devargs->proto_xtr_dflt = xtr_type;
If we memset(devargs->proto_xtr, xtr_type, ICE_MAX_QUEUE_NUM) here, seems
we don't need proto_xtr_dflt.
>+ return 0;
>+ }
>+
>+ queues++;
>+ do {
>+ while (isblank(*queues))
>+ queues++;
>+ if (*queues == '\0')
>+ return -1;
>+
>+ queue_start = queues;
>+
>+ /* go across a complete bracket */
>+ if (*queue_start == '(') {
>+ queues += strcspn(queues, ")");
>+ if (*queues != ')')
>+ return -1;
>+ }
>+
>+ /* scan the separator ':' */
>+ queues += strcspn(queues, ":");
>+ if (*queues++ != ':')
>+ return -1;
>+ while (isblank(*queues))
>+ queues++;
>+
>+ for (idx = 0; ; idx++) {
>+ if (isblank(queues[idx]) ||
>+ queues[idx] == ',' ||
>+ queues[idx] == ']' ||
>+ queues[idx] == '\0')
>+ break;
>+
>+ if (idx > sizeof(xtr_name) - 2)
>+ return -1;
>+
>+ xtr_name[idx] = queues[idx];
>+ }
>+ xtr_name[idx] = '\0';
>+ xtr_type = lookup_proto_xtr_type(xtr_name);
>+ if (xtr_type < 0)
>+ return -1;
>+
>+ queues += idx;
>+
>+ while (isblank(*queues) || *queues == ',' || *queues == ']')
>+ queues++;
>+
>+ if (parse_queue_set(queue_start, xtr_type, devargs) < 0)
>+ return -1;
>+ } while (*queues != '\0');
>+
>+ return 0;
>+}
>+
>+static int
>+handle_proto_xtr_arg(__rte_unused const char *key, const char *value,
>+ void *extra_args)
>+{
>+ struct ice_devargs *devargs = extra_args;
>+
>+ if (value == NULL || extra_args == NULL)
>+ return -EINVAL;
>+
>+ if (parse_queue_proto_xtr(value, devargs) < 0) {
>+ PMD_DRV_LOG(ERR,
>+ "The protocol extraction parameter is wrong : '%s'",
>+ value);
>+ return -1;
>+ }
>+
>+ return 0;
>+}
>+
>+static void
>+ice_parse_proto_xtr_devarg(struct rte_kvargs *kvlist,
>+ struct ice_devargs *devargs)
>+{
>+ int i;
>+
>+ devargs->proto_xtr_dflt = PROTO_XTR_NONE;
>+
>+ for (i = 0; i < ICE_MAX_QUEUE_NUM; i++)
>+ devargs->proto_xtr[i] = PROTO_XTR_NONE;
memset(devargs->proto_xtr, PROTO_XTR_NONE, ICE_MAX_QUEUE_NUM) ?
>+
>+ rte_kvargs_process(kvlist, ICE_PROTO_XTR_ARG,
>+ handle_proto_xtr_arg, devargs);
Do we need to check ret of rte_kvargs_process here and change ice_parse_proto_xtr_devarg
to return int?
>+}
>+
>+static bool
>+ice_proto_xtr_support(struct ice_hw *hw)
>+{
>+#define FLX_REG(val, fld, idx) \
>+ (((val) & GLFLXP_RXDID_FLX_WRD_##idx##_##fld##_M) >> \
>+ GLFLXP_RXDID_FLX_WRD_##idx##_##fld##_S)
>+ static struct {
>+ uint32_t rxdid;
>+ uint16_t protid_0;
>+ uint16_t protid_1;
>+ } xtr_sets[] = {
>+ { ICE_RXDID_COMMS_AUX_VLAN, ICE_PROT_EVLAN_O, ICE_PROT_VLAN_O },
>+ { ICE_RXDID_COMMS_AUX_IPV4, ICE_PROT_IPV4_OF_OR_S,
>+ ICE_PROT_IPV4_OF_OR_S },
>+ { ICE_RXDID_COMMS_AUX_IPV6, ICE_PROT_IPV6_OF_OR_S,
>+ ICE_PROT_IPV6_OF_OR_S },
>+ { ICE_RXDID_COMMS_AUX_IPV6_FLOW, ICE_PROT_IPV6_OF_OR_S,
>+ ICE_PROT_IPV6_OF_OR_S },
>+ { ICE_RXDID_COMMS_AUX_TCP, ICE_PROT_TCP_IL, ICE_PROT_ID_INVAL },
>+ };
>+ uint32_t i;
>+
>+ for (i = 0; i < RTE_DIM(xtr_sets); i++) {
>+ uint32_t rxdid = xtr_sets[i].rxdid;
>+ uint32_t v;
>+
>+ if (xtr_sets[i].protid_0 != ICE_PROT_ID_INVAL) {
>+ v = ICE_READ_REG(hw, GLFLXP_RXDID_FLX_WRD_4(rxdid));
>+
>+ if (FLX_REG(v, PROT_MDID, 4) != xtr_sets[i].protid_0 ||
>+ FLX_REG(v, RXDID_OPCODE, 4) != ICE_RX_OPC_EXTRACT)
>+ return false;
>+ }
>+
>+ if (xtr_sets[i].protid_1 != ICE_PROT_ID_INVAL) {
>+ v = ICE_READ_REG(hw, GLFLXP_RXDID_FLX_WRD_5(rxdid));
>+
>+ if (FLX_REG(v, PROT_MDID, 5) != xtr_sets[i].protid_1 ||
>+ FLX_REG(v, RXDID_OPCODE, 5) != ICE_RX_OPC_EXTRACT)
>+ return false;
>+ }
>+ }
>+
>+ return true;
>+}
>+
> static int
> ice_res_pool_init(struct ice_res_pool_info *pool, uint32_t base,
> uint32_t num)
>@@ -1079,6 +1368,8 @@ ice_interrupt_handler(void *param)
> static int
> ice_pf_sw_init(struct rte_eth_dev *dev)
> {
>+ struct ice_adapter *ad =
>+ ICE_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
> struct ice_pf *pf = ICE_DEV_PRIVATE_TO_PF(dev->data->dev_private);
> struct ice_hw *hw = ICE_PF_TO_HW(pf);
>
>@@ -1088,6 +1379,21 @@ ice_pf_sw_init(struct rte_eth_dev *dev)
>
> pf->lan_nb_qps = pf->lan_nb_qp_max;
>
>+ if (ice_proto_xtr_support(hw))
>+ pf->proto_xtr = rte_zmalloc(NULL, pf->lan_nb_qps, 0);
>+
>+ if (pf->proto_xtr != NULL) {
>+ uint16_t i;
>+
>+ for (i = 0; i < pf->lan_nb_qps; i++)
>+ pf->proto_xtr[i] =
>+ ad->devargs.proto_xtr[i] != PROTO_XTR_NONE ?
>+ ad->devargs.proto_xtr[i] :
>+ ad->devargs.proto_xtr_dflt;
>+ } else {
>+ PMD_DRV_LOG(NOTICE, "Protocol extraction is disabled");
>+ }
>+
> return 0;
> }
>
>@@ -1378,6 +1684,8 @@ static int ice_parse_devargs(struct rte_eth_dev *dev)
> return -EINVAL;
> }
>
>+ ice_parse_proto_xtr_devarg(kvlist, &ad->devargs);
>+
> ret = rte_kvargs_process(kvlist, ICE_SAFE_MODE_SUPPORT_ARG,
> &parse_bool, &ad->devargs.safe_mode_support);
>
>@@ -1547,6 +1855,7 @@ ice_dev_init(struct rte_eth_dev *dev)
> ice_sched_cleanup_all(hw);
> rte_free(hw->port_info);
> ice_shutdown_all_ctrlq(hw);
>+ rte_free(pf->proto_xtr);
>
> return ret;
> }
>@@ -1672,6 +1981,8 @@ ice_dev_close(struct rte_eth_dev *dev)
> rte_free(hw->port_info);
> hw->port_info = NULL;
> ice_shutdown_all_ctrlq(hw);
>+ rte_free(pf->proto_xtr);
>+ pf->proto_xtr = NULL;
> }
>
> static int
>@@ -3795,6 +4106,7 @@ RTE_PMD_REGISTER_PCI(net_ice, rte_ice_pmd);
> RTE_PMD_REGISTER_PCI_TABLE(net_ice, pci_id_ice_map);
> RTE_PMD_REGISTER_KMOD_DEP(net_ice, "* igb_uio | uio_pci_generic | vfio-pci");
> RTE_PMD_REGISTER_PARAM_STRING(net_ice,
>+ ICE_PROTO_XTR_ARG "=[queue:]<vlan|ipv4|ipv6|ipv6_flow|tcp>"
> ICE_SAFE_MODE_SUPPORT_ARG "=<0|1>");
>
> RTE_INIT(ice_init_log)
>diff --git a/drivers/net/ice/ice_ethdev.h b/drivers/net/ice/ice_ethdev.h
>index f569da833..e58192104 100644
>--- a/drivers/net/ice/ice_ethdev.h
>+++ b/drivers/net/ice/ice_ethdev.h
>@@ -263,6 +263,7 @@ struct ice_pf {
> uint16_t lan_nb_qp_max;
> uint16_t lan_nb_qps; /* The number of queue pairs of LAN */
> uint16_t base_queue; /* The base queue pairs index in the device */
>+ uint8_t *proto_xtr; /* Protocol extraction type for all queues */
> struct ice_hw_port_stats stats_offset;
> struct ice_hw_port_stats stats;
> /* internal packet statistics, it should be excluded from the total */
>@@ -273,11 +274,15 @@ struct ice_pf {
> struct ice_flow_list flow_list;
> };
>
>+#define ICE_MAX_QUEUE_NUM 2048
>+
> /**
> * Cache devargs parse result.
> */
> struct ice_devargs {
> int safe_mode_support;
>+ uint8_t proto_xtr_dflt;
>+ uint8_t proto_xtr[ICE_MAX_QUEUE_NUM];
> };
>
> /**
>diff --git a/drivers/net/ice/ice_rxtx.c b/drivers/net/ice/ice_rxtx.c
>index d2e36853f..e28310b96 100644
>--- a/drivers/net/ice/ice_rxtx.c
>+++ b/drivers/net/ice/ice_rxtx.c
>@@ -13,6 +13,36 @@
> PKT_TX_TCP_SEG | \
> PKT_TX_OUTER_IP_CKSUM)
>
>+static inline uint8_t
>+ice_rxdid_to_proto_xtr_type(uint8_t rxdid)
>+{
>+ static uint8_t xtr_map[] = {
>+ [ICE_RXDID_COMMS_AUX_VLAN] = PROTO_XTR_VLAN,
>+ [ICE_RXDID_COMMS_AUX_IPV4] = PROTO_XTR_IPV4,
>+ [ICE_RXDID_COMMS_AUX_IPV6] = PROTO_XTR_IPV6,
>+ [ICE_RXDID_COMMS_AUX_IPV6_FLOW] = PROTO_XTR_IPV6_FLOW,
>+ [ICE_RXDID_COMMS_AUX_TCP] = PROTO_XTR_TCP,
>+ };
>+
>+ return rxdid < RTE_DIM(xtr_map) ? xtr_map[rxdid] : PROTO_XTR_NONE;
>+}
>+
>+static inline uint8_t
>+ice_proto_xtr_type_to_rxdid(uint8_t xtr_tpye)
>+{
>+ static uint8_t rxdid_map[] = {
>+ [PROTO_XTR_VLAN] = ICE_RXDID_COMMS_AUX_VLAN,
>+ [PROTO_XTR_IPV4] = ICE_RXDID_COMMS_AUX_IPV4,
>+ [PROTO_XTR_IPV6] = ICE_RXDID_COMMS_AUX_IPV6,
>+ [PROTO_XTR_IPV6_FLOW] = ICE_RXDID_COMMS_AUX_IPV6_FLOW,
>+ [PROTO_XTR_TCP] = ICE_RXDID_COMMS_AUX_TCP,
>+ };
>+ uint8_t rxdid;
>+
>+ rxdid = xtr_tpye < RTE_DIM(rxdid_map) ? rxdid_map[xtr_tpye] : 0;
>+
>+ return rxdid != 0 ? rxdid : ICE_RXDID_COMMS_GENERIC;
>+}
>
> static enum ice_status
> ice_program_hw_rx_queue(struct ice_rx_queue *rxq)
>@@ -84,6 +114,11 @@ ice_program_hw_rx_queue(struct ice_rx_queue *rxq)
> rx_ctx.showiv = 0;
> rx_ctx.crcstrip = (rxq->crc_len == 0) ? 1 : 0;
>
>+ rxdid = ice_proto_xtr_type_to_rxdid(rxq->proto_xtr);
>+
>+ PMD_DRV_LOG(DEBUG, "Port (%u) - Rx queue (%u) is set with RXDID : %u",
>+ rxq->port_id, rxq->queue_id, rxdid);
>+
> /* Enable Flexible Descriptors in the queue context which
> * allows this driver to select a specific receive descriptor format
> */
>@@ -641,6 +676,8 @@ ice_rx_queue_setup(struct rte_eth_dev *dev,
> rxq->drop_en = rx_conf->rx_drop_en;
> rxq->vsi = vsi;
> rxq->rx_deferred_start = rx_conf->rx_deferred_start;
>+ rxq->proto_xtr = pf->proto_xtr != NULL ?
>+ pf->proto_xtr[queue_idx] : PROTO_XTR_NONE;
>
> /* Allocate the maximun number of RX ring hardware descriptor. */
> len = ICE_MAX_RING_DESC;
>@@ -1062,6 +1099,10 @@ ice_rxd_to_vlan_tci(struct rte_mbuf *mb, volatile union ice_rx_flex_desc *rxdp)
> mb->vlan_tci, mb->vlan_tci_outer);
> }
>
>+#define ICE_RX_PROTO_XTR_VALID \
>+ ((1 << ICE_RX_FLEX_DESC_STATUS1_XTRMD4_VALID_S) | \
>+ (1 << ICE_RX_FLEX_DESC_STATUS1_XTRMD5_VALID_S))
>+
> static inline void
> ice_rxd_to_pkt_fields(struct rte_mbuf *mb,
> volatile union ice_rx_flex_desc *rxdp)
>@@ -1075,6 +1116,26 @@ ice_rxd_to_pkt_fields(struct rte_mbuf *mb,
> mb->ol_flags |= PKT_RX_RSS_HASH;
> mb->hash.rss = rte_le_to_cpu_32(desc->rss_hash);
> }
>+
>+#ifndef RTE_LIBRTE_ICE_16BYTE_RX_DESC
>+ init_proto_xtr_flds(mb);
>+
>+ stat_err = rte_le_to_cpu_16(desc->status_error1);
>+ if (stat_err & ICE_RX_PROTO_XTR_VALID) {
>+ struct proto_xtr_flds *xtr = get_proto_xtr_flds(mb);
>+
>+ if (stat_err & (1 << ICE_RX_FLEX_DESC_STATUS1_XTRMD4_VALID_S))
>+ xtr->u.raw.data0 =
>+ rte_le_to_cpu_16(desc->flex_ts.flex.aux0);
>+
>+ if (stat_err & (1 << ICE_RX_FLEX_DESC_STATUS1_XTRMD5_VALID_S))
>+ xtr->u.raw.data1 =
>+ rte_le_to_cpu_16(desc->flex_ts.flex.aux1);
>+
>+ xtr->type = ice_rxdid_to_proto_xtr_type(desc->rxdid);
>+ xtr->magic = PROTO_XTR_MAGIC_ID;
>+ }
>+#endif
> }
>
> #ifdef RTE_LIBRTE_ICE_RX_ALLOW_BULK_ALLOC
>diff --git a/drivers/net/ice/ice_rxtx.h b/drivers/net/ice/ice_rxtx.h
>index 64e891875..de16637f3 100644
>--- a/drivers/net/ice/ice_rxtx.h
>+++ b/drivers/net/ice/ice_rxtx.h
>@@ -5,6 +5,7 @@
> #ifndef _ICE_RXTX_H_
> #define _ICE_RXTX_H_
>
>+#include "rte_pmd_ice.h"
> #include "ice_ethdev.h"
>
> #define ICE_ALIGN_RING_DESC 32
>@@ -78,6 +79,7 @@ struct ice_rx_queue {
> uint16_t max_pkt_len; /* Maximum packet length */
> bool q_set; /* indicate if rx queue has been configured */
> bool rx_deferred_start; /* don't start this queue in dev start */
>+ uint8_t proto_xtr; /* Protocol extraction from flexible descriptor */
> ice_rx_release_mbufs_t rx_rel_mbufs;
> };
>
>diff --git a/drivers/net/ice/ice_rxtx_vec_common.h b/drivers/net/ice/ice_rxtx_vec_common.h
>index c5f0d564f..080ca4175 100644
>--- a/drivers/net/ice/ice_rxtx_vec_common.h
>+++ b/drivers/net/ice/ice_rxtx_vec_common.h
>@@ -234,6 +234,9 @@ ice_rx_vec_queue_default(struct ice_rx_queue *rxq)
> if (rxq->nb_rx_desc % rxq->rx_free_thresh)
> return -1;
>
>+ if (rxq->proto_xtr != PROTO_XTR_NONE)
>+ return -1;
>+
> return 0;
> }
>
>diff --git a/drivers/net/ice/meson.build b/drivers/net/ice/meson.build
>index 36b4b3c85..6828170a9 100644
>--- a/drivers/net/ice/meson.build
>+++ b/drivers/net/ice/meson.build
>@@ -34,3 +34,5 @@ if arch_subdir == 'x86'
> objs += ice_avx2_lib.extract_objects('ice_rxtx_vec_avx2.c')
> endif
> endif
>+
>+install_headers('rte_pmd_ice.h')
>diff --git a/drivers/net/ice/rte_pmd_ice.h b/drivers/net/ice/rte_pmd_ice.h
>new file mode 100644
>index 000000000..719487e1e
>--- /dev/null
>+++ b/drivers/net/ice/rte_pmd_ice.h
>@@ -0,0 +1,152 @@
>+/* SPDX-License-Identifier: BSD-3-Clause
>+ * Copyright(c) 2019 Intel Corporation
>+ */
>+
>+#ifndef _RTE_PMD_ICE_H_
>+#define _RTE_PMD_ICE_H_
>+
>+#include <stdio.h>
>+#include <rte_mbuf.h>
>+#include <rte_ethdev.h>
>+
>+#ifdef __cplusplus
>+extern "C" {
>+#endif
>+
>+enum proto_xtr_type {
>+ PROTO_XTR_NONE,
>+ PROTO_XTR_VLAN,
>+ PROTO_XTR_IPV4,
>+ PROTO_XTR_IPV6,
>+ PROTO_XTR_IPV6_FLOW,
>+ PROTO_XTR_TCP,
>+};
>+
>+struct proto_xtr_flds {
>+ union {
>+ struct {
>+ uint16_t data0;
>+ uint16_t data1;
>+ } raw;
>+ struct {
>+ uint16_t stag_vid:12,
>+ stag_dei:1,
>+ stag_pcp:3;
>+ uint16_t ctag_vid:12,
>+ ctag_dei:1,
>+ ctag_pcp:3;
>+ } vlan;
>+ struct {
>+ uint16_t protocol:8,
>+ ttl:8;
>+ uint16_t tos:8,
>+ ihl:4,
>+ version:4;
>+ } ipv4;
>+ struct {
>+ uint16_t hoplimit:8,
>+ nexthdr:8;
>+ uint16_t flowhi4:4,
>+ tc:8,
>+ version:4;
>+ } ipv6;
>+ struct {
>+ uint16_t flowlo16;
>+ uint16_t flowhi4:4,
>+ tc:8,
>+ version:4;
>+ } ipv6_flow;
>+ struct {
>+ uint16_t fin:1,
>+ syn:1,
>+ rst:1,
>+ psh:1,
>+ ack:1,
>+ urg:1,
>+ ece:1,
>+ cwr:1,
>+ res1:4,
>+ doff:4;
>+ uint16_t rsvd;
>+ } tcp;
>+ } u;
>+
>+ uint16_t rsvd;
>+
>+ uint8_t type;
>+
>+#define PROTO_XTR_MAGIC_ID 0xCE
>+ uint8_t magic;
>+};
>+
>+static inline void
>+init_proto_xtr_flds(struct rte_mbuf *mb)
>+{
>+ mb->udata64 = 0;
>+}
>+
>+static inline struct proto_xtr_flds *
>+get_proto_xtr_flds(struct rte_mbuf *mb)
>+{
>+ RTE_BUILD_BUG_ON(sizeof(struct proto_xtr_flds) > sizeof(mb->udata64));
>+
>+ return (struct proto_xtr_flds *)&mb->udata64;
>+}
>+
>+static inline void
>+dump_proto_xtr_flds(struct rte_mbuf *mb)
>+{
>+ struct proto_xtr_flds *xtr = get_proto_xtr_flds(mb);
>+
>+ if (xtr->magic != PROTO_XTR_MAGIC_ID || xtr->type == PROTO_XTR_NONE)
>+ return;
>+
>+ printf(" - Protocol Extraction:[0x%04x:0x%04x],",
>+ xtr->u.raw.data0, xtr->u.raw.data1);
>+
>+ if (xtr->type == PROTO_XTR_VLAN)
>+ printf("vlan,stag=%u:%u:%u,ctag=%u:%u:%u ",
>+ xtr->u.vlan.stag_pcp,
>+ xtr->u.vlan.stag_dei,
>+ xtr->u.vlan.stag_vid,
>+ xtr->u.vlan.ctag_pcp,
>+ xtr->u.vlan.ctag_dei,
>+ xtr->u.vlan.ctag_vid);
>+ else if (xtr->type == PROTO_XTR_IPV4)
>+ printf("ipv4,ver=%u,hdrlen=%u,tos=%u,ttl=%u,proto=%u ",
>+ xtr->u.ipv4.version,
>+ xtr->u.ipv4.ihl,
>+ xtr->u.ipv4.tos,
>+ xtr->u.ipv4.ttl,
>+ xtr->u.ipv4.protocol);
>+ else if (xtr->type == PROTO_XTR_IPV6)
>+ printf("ipv6,ver=%u,tc=%u,flow_hi4=0x%x,nexthdr=%u,hoplimit=%u ",
>+ xtr->u.ipv6.version,
>+ xtr->u.ipv6.tc,
>+ xtr->u.ipv6.flowhi4,
>+ xtr->u.ipv6.nexthdr,
>+ xtr->u.ipv6.hoplimit);
>+ else if (xtr->type == PROTO_XTR_IPV6_FLOW)
>+ printf("ipv6_flow,ver=%u,tc=%u,flow=0x%x%04x ",
>+ xtr->u.ipv6_flow.version,
>+ xtr->u.ipv6_flow.tc,
>+ xtr->u.ipv6_flow.flowhi4,
>+ xtr->u.ipv6_flow.flowlo16);
>+ else if (xtr->type == PROTO_XTR_TCP)
>+ printf("tcp,doff=%u,flags=%s%s%s%s%s%s%s%s ",
>+ xtr->u.tcp.doff,
>+ xtr->u.tcp.cwr ? "C" : "",
>+ xtr->u.tcp.ece ? "E" : "",
>+ xtr->u.tcp.urg ? "U" : "",
>+ xtr->u.tcp.ack ? "A" : "",
>+ xtr->u.tcp.psh ? "P" : "",
>+ xtr->u.tcp.rst ? "R" : "",
>+ xtr->u.tcp.syn ? "S" : "",
>+ xtr->u.tcp.fin ? "F" : "");
>+}
>+
>+#ifdef __cplusplus
>+}
>+#endif
>+
>+#endif /* _RTE_PMD_ICE_H_ */
>--
>2.17.1
>
> -----Original Message-----
> From: Ye, Xiaolong
> Sent: Thursday, September 19, 2019 07:30
> To: Rong, Leyi <leyi.rong@intel.com>
> Cc: Wang, Haiyue <haiyue.wang@intel.com>; Lu, Wenzhuo <wenzhuo.lu@intel.com>; Zhang, Qi Z
> <qi.z.zhang@intel.com>; dev@dpdk.org
> Subject: Re: [PATCH v3 3/5] net/ice: add protocol extraction support for per Rx queue
>
> On 09/17, Leyi Rong wrote:
> >From: Haiyue Wang <haiyue.wang@intel.com>
> >
> >The ice has the feature to extract protocol fields into flex descriptor
> >by programming per queue. Currently, the ice PMD will put the protocol
> >fields into rte_mbuf::udata64 with different type format. Application
> >can access the protocol fields quickly.
> >
>
> [snip]
>
> >+static int
> >+parse_queue_set(const char *input, int xtr_type, struct ice_devargs *devargs)
> >+{
> >+ const char *str = input;
> >+ char *end = NULL;
> >+ uint32_t min, max;
> >+ uint32_t idx;
> >+
> >+ while (isblank(*str))
> >+ str++;
> >+
> >+ if ((!isdigit(*str) && *str != '(') || (*str == '\0'))
>
> Minor nit, (*str == '\0') seems redundant here, no?
>
Yes! Will make it clean.
> >+ return -1;
> >+
> >+ /* process single number or single range of number */
> >+ if (*str != '(') {
> >+ errno = 0;
> >+ idx = strtoul(str, &end, 10);
> >+ if (errno || end == NULL || idx >= ICE_MAX_QUEUE_NUM)
> >+ return -1;
> >+
> >+ while (isblank(*end))
> >+ end++;
> >+
> >+ min = idx;
> >+ max = idx;
> >+
> >+ /* process single <number>-<number> */
> >+ if (*end == '-') {
> >+ end++;
> >+ while (isblank(*end))
> >+ end++;
> >+ if (!isdigit(*end))
> >+ return -1;
> >+
> >+ errno = 0;
> >+ idx = strtoul(end, &end, 10);
> >+ if (errno || end == NULL || idx >= ICE_MAX_QUEUE_NUM)
> >+ return -1;
> >+
> >+ max = idx;
> >+ while (isblank(*end))
> >+ end++;
> >+ }
> >+
> >+ if (*end != ':')
> >+ return -1;
> >+
> >+ for (idx = RTE_MIN(min, max);
> >+ idx <= RTE_MAX(min, max); idx++)
> >+ devargs->proto_xtr[idx] = xtr_type;
> >+
> >+ return 0;
> >+ }
> >+
> >+ /* process set within bracket */
> >+ str++;
> >+ while (isblank(*str))
> >+ str++;
> >+ if (*str == '\0')
> >+ return -1;
> >+
> >+ min = ICE_MAX_QUEUE_NUM;
> >+ do {
> >+ /* go ahead to the first digit */
> >+ while (isblank(*str))
> >+ str++;
> >+ if (!isdigit(*str))
> >+ return -1;
> >+
> >+ /* get the digit value */
> >+ errno = 0;
> >+ idx = strtoul(str, &end, 10);
> >+ if (errno || end == NULL || idx >= ICE_MAX_QUEUE_NUM)
> >+ return -1;
> >+
> >+ /* go ahead to separator '-',',' and ')' */
> >+ while (isblank(*end))
> >+ end++;
> >+ if (*end == '-') {
> >+ if (min == ICE_MAX_QUEUE_NUM)
> >+ min = idx;
> >+ else /* avoid continuous '-' */
> >+ return -1;
> >+ } else if (*end == ',' || *end == ')') {
> >+ max = idx;
> >+ if (min == ICE_MAX_QUEUE_NUM)
> >+ min = idx;
> >+
> >+ for (idx = RTE_MIN(min, max);
> >+ idx <= RTE_MAX(min, max); idx++)
> >+ devargs->proto_xtr[idx] = xtr_type;
> >+
> >+ min = ICE_MAX_QUEUE_NUM;
> >+ } else {
> >+ return -1;
> >+ }
> >+
> >+ str = end + 1;
> >+ } while (*end != ')' && *end != '\0');
> >+
> >+ return 0;
> >+}
> >+
> >+static int
> >+parse_queue_proto_xtr(const char *queues, struct ice_devargs *devargs)
> >+{
> >+ const char *queue_start;
> >+ uint32_t idx;
> >+ int xtr_type;
> >+ char xtr_name[32];
> >+
> >+ while (isblank(*queues))
> >+ queues++;
> >+
> >+ if (*queues != '[') {
> >+ xtr_type = lookup_proto_xtr_type(queues);
> >+ if (xtr_type < 0)
> >+ return -1;
> >+
> >+ devargs->proto_xtr_dflt = xtr_type;
>
> If we memset(devargs->proto_xtr, xtr_type, ICE_MAX_QUEUE_NUM) here, seems
> we don't need proto_xtr_dflt.
+1, good catch.
>
> >+ return 0;
> >+ }
> >+
> >+ queues++;
> >+ do {
> >+ while (isblank(*queues))
> >+ queues++;
> >+ if (*queues == '\0')
> >+ return -1;
> >+
> >+ queue_start = queues;
> >+
> >+ /* go across a complete bracket */
> >+ if (*queue_start == '(') {
> >+ queues += strcspn(queues, ")");
> >+ if (*queues != ')')
> >+ return -1;
> >+ }
> >+
> >+ /* scan the separator ':' */
> >+ queues += strcspn(queues, ":");
> >+ if (*queues++ != ':')
> >+ return -1;
> >+ while (isblank(*queues))
> >+ queues++;
> >+
> >+ for (idx = 0; ; idx++) {
> >+ if (isblank(queues[idx]) ||
> >+ queues[idx] == ',' ||
> >+ queues[idx] == ']' ||
> >+ queues[idx] == '\0')
> >+ break;
> >+
> >+ if (idx > sizeof(xtr_name) - 2)
> >+ return -1;
> >+
> >+ xtr_name[idx] = queues[idx];
> >+ }
> >+ xtr_name[idx] = '\0';
> >+ xtr_type = lookup_proto_xtr_type(xtr_name);
> >+ if (xtr_type < 0)
> >+ return -1;
> >+
> >+ queues += idx;
> >+
> >+ while (isblank(*queues) || *queues == ',' || *queues == ']')
> >+ queues++;
> >+
> >+ if (parse_queue_set(queue_start, xtr_type, devargs) < 0)
> >+ return -1;
> >+ } while (*queues != '\0');
> >+
> >+ return 0;
> >+}
> >+
> >+static int
> >+handle_proto_xtr_arg(__rte_unused const char *key, const char *value,
> >+ void *extra_args)
> >+{
> >+ struct ice_devargs *devargs = extra_args;
> >+
> >+ if (value == NULL || extra_args == NULL)
> >+ return -EINVAL;
> >+
> >+ if (parse_queue_proto_xtr(value, devargs) < 0) {
> >+ PMD_DRV_LOG(ERR,
> >+ "The protocol extraction parameter is wrong : '%s'",
> >+ value);
> >+ return -1;
> >+ }
> >+
> >+ return 0;
> >+}
> >+
> >+static void
> >+ice_parse_proto_xtr_devarg(struct rte_kvargs *kvlist,
> >+ struct ice_devargs *devargs)
> >+{
> >+ int i;
> >+
> >+ devargs->proto_xtr_dflt = PROTO_XTR_NONE;
> >+
> >+ for (i = 0; i < ICE_MAX_QUEUE_NUM; i++)
> >+ devargs->proto_xtr[i] = PROTO_XTR_NONE;
>
> memset(devargs->proto_xtr, PROTO_XTR_NONE, ICE_MAX_QUEUE_NUM) ?
>
Yes.
> >+
> >+ rte_kvargs_process(kvlist, ICE_PROTO_XTR_ARG,
> >+ handle_proto_xtr_arg, devargs);
>
> Do we need to check ret of rte_kvargs_process here and change ice_parse_proto_xtr_devarg
> to return int?
>
> >+}
> >+
> >+static bool
> >+ice_proto_xtr_support(struct ice_hw *hw)
> >+{
> >+#define FLX_REG(val, fld, idx) \
> >+ (((val) & GLFLXP_RXDID_FLX_WRD_##idx##_##fld##_M) >> \
> >+ GLFLXP_RXDID_FLX_WRD_##idx##_##fld##_S)
> >+ static struct {
> >+ uint32_t rxdid;
> >+ uint16_t protid_0;
> >+ uint16_t protid_1;
> >+ } xtr_sets[] = {
> >+ { ICE_RXDID_COMMS_AUX_VLAN, ICE_PROT_EVLAN_O, ICE_PROT_VLAN_O },
> >+ { ICE_RXDID_COMMS_AUX_IPV4, ICE_PROT_IPV4_OF_OR_S,
> >+ ICE_PROT_IPV4_OF_OR_S },
> >+ { ICE_RXDID_COMMS_AUX_IPV6, ICE_PROT_IPV6_OF_OR_S,
> >+ ICE_PROT_IPV6_OF_OR_S },
> >+ { ICE_RXDID_COMMS_AUX_IPV6_FLOW, ICE_PROT_IPV6_OF_OR_S,
> >+ ICE_PROT_IPV6_OF_OR_S },
> >+ { ICE_RXDID_COMMS_AUX_TCP, ICE_PROT_TCP_IL, ICE_PROT_ID_INVAL },
> >+ };
> >+ uint32_t i;
> >+
> >+ for (i = 0; i < RTE_DIM(xtr_sets); i++) {
> >+ uint32_t rxdid = xtr_sets[i].rxdid;
> >+ uint32_t v;
> >+
> >+ if (xtr_sets[i].protid_0 != ICE_PROT_ID_INVAL) {
> >+ v = ICE_READ_REG(hw, GLFLXP_RXDID_FLX_WRD_4(rxdid));
> >+
> >+ if (FLX_REG(v, PROT_MDID, 4) != xtr_sets[i].protid_0 ||
> >+ FLX_REG(v, RXDID_OPCODE, 4) != ICE_RX_OPC_EXTRACT)
> >+ return false;
> >+ }
> >+
> >+ if (xtr_sets[i].protid_1 != ICE_PROT_ID_INVAL) {
> >+ v = ICE_READ_REG(hw, GLFLXP_RXDID_FLX_WRD_5(rxdid));
> >+
> >+ if (FLX_REG(v, PROT_MDID, 5) != xtr_sets[i].protid_1 ||
> >+ FLX_REG(v, RXDID_OPCODE, 5) != ICE_RX_OPC_EXTRACT)
> >+ return false;
> >+ }
> >+ }
> >+
> >+ return true;
> >+}
> >+
> > static int
> > ice_res_pool_init(struct ice_res_pool_info *pool, uint32_t base,
> > uint32_t num)
> >@@ -1079,6 +1368,8 @@ ice_interrupt_handler(void *param)
> > static int
> > ice_pf_sw_init(struct rte_eth_dev *dev)
> > {
> >+ struct ice_adapter *ad =
> >+ ICE_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
> > struct ice_pf *pf = ICE_DEV_PRIVATE_TO_PF(dev->data->dev_private);
> > struct ice_hw *hw = ICE_PF_TO_HW(pf);
> >
> >@@ -1088,6 +1379,21 @@ ice_pf_sw_init(struct rte_eth_dev *dev)
> >
> > pf->lan_nb_qps = pf->lan_nb_qp_max;
> >
> >+ if (ice_proto_xtr_support(hw))
> >+ pf->proto_xtr = rte_zmalloc(NULL, pf->lan_nb_qps, 0);
> >+
> >+ if (pf->proto_xtr != NULL) {
> >+ uint16_t i;
> >+
> >+ for (i = 0; i < pf->lan_nb_qps; i++)
> >+ pf->proto_xtr[i] =
> >+ ad->devargs.proto_xtr[i] != PROTO_XTR_NONE ?
> >+ ad->devargs.proto_xtr[i] :
> >+ ad->devargs.proto_xtr_dflt;
> >+ } else {
> >+ PMD_DRV_LOG(NOTICE, "Protocol extraction is disabled");
> >+ }
> >+
> > return 0;
> > }
> >
> >@@ -1378,6 +1684,8 @@ static int ice_parse_devargs(struct rte_eth_dev *dev)
> > return -EINVAL;
> > }
> >
> >+ ice_parse_proto_xtr_devarg(kvlist, &ad->devargs);
> >+
> > ret = rte_kvargs_process(kvlist, ICE_SAFE_MODE_SUPPORT_ARG,
> > &parse_bool, &ad->devargs.safe_mode_support);
> >
> >@@ -1547,6 +1855,7 @@ ice_dev_init(struct rte_eth_dev *dev)
> > ice_sched_cleanup_all(hw);
> > rte_free(hw->port_info);
> > ice_shutdown_all_ctrlq(hw);
> >+ rte_free(pf->proto_xtr);
> >
> > return ret;
> > }
> >@@ -1672,6 +1981,8 @@ ice_dev_close(struct rte_eth_dev *dev)
> > rte_free(hw->port_info);
> > hw->port_info = NULL;
> > ice_shutdown_all_ctrlq(hw);
> >+ rte_free(pf->proto_xtr);
> >+ pf->proto_xtr = NULL;
> > }
> >
> > static int
> >@@ -3795,6 +4106,7 @@ RTE_PMD_REGISTER_PCI(net_ice, rte_ice_pmd);
> > RTE_PMD_REGISTER_PCI_TABLE(net_ice, pci_id_ice_map);
> > RTE_PMD_REGISTER_KMOD_DEP(net_ice, "* igb_uio | uio_pci_generic | vfio-pci");
> > RTE_PMD_REGISTER_PARAM_STRING(net_ice,
> >+ ICE_PROTO_XTR_ARG "=[queue:]<vlan|ipv4|ipv6|ipv6_flow|tcp>"
> > ICE_SAFE_MODE_SUPPORT_ARG "=<0|1>");
> >
> > RTE_INIT(ice_init_log)
> >diff --git a/drivers/net/ice/ice_ethdev.h b/drivers/net/ice/ice_ethdev.h
> >index f569da833..e58192104 100644
> >--- a/drivers/net/ice/ice_ethdev.h
> >+++ b/drivers/net/ice/ice_ethdev.h
> >@@ -263,6 +263,7 @@ struct ice_pf {
> > uint16_t lan_nb_qp_max;
> > uint16_t lan_nb_qps; /* The number of queue pairs of LAN */
> > uint16_t base_queue; /* The base queue pairs index in the device */
> >+ uint8_t *proto_xtr; /* Protocol extraction type for all queues */
> > struct ice_hw_port_stats stats_offset;
> > struct ice_hw_port_stats stats;
> > /* internal packet statistics, it should be excluded from the total */
> >@@ -273,11 +274,15 @@ struct ice_pf {
> > struct ice_flow_list flow_list;
> > };
> >
> >+#define ICE_MAX_QUEUE_NUM 2048
> >+
> > /**
> > * Cache devargs parse result.
> > */
> > struct ice_devargs {
> > int safe_mode_support;
> >+ uint8_t proto_xtr_dflt;
> >+ uint8_t proto_xtr[ICE_MAX_QUEUE_NUM];
> > };
> >
> > /**
> >diff --git a/drivers/net/ice/ice_rxtx.c b/drivers/net/ice/ice_rxtx.c
> >index d2e36853f..e28310b96 100644
> >--- a/drivers/net/ice/ice_rxtx.c
> >+++ b/drivers/net/ice/ice_rxtx.c
> >@@ -13,6 +13,36 @@
> > PKT_TX_TCP_SEG | \
> > PKT_TX_OUTER_IP_CKSUM)
> >
> >+static inline uint8_t
> >+ice_rxdid_to_proto_xtr_type(uint8_t rxdid)
> >+{
> >+ static uint8_t xtr_map[] = {
> >+ [ICE_RXDID_COMMS_AUX_VLAN] = PROTO_XTR_VLAN,
> >+ [ICE_RXDID_COMMS_AUX_IPV4] = PROTO_XTR_IPV4,
> >+ [ICE_RXDID_COMMS_AUX_IPV6] = PROTO_XTR_IPV6,
> >+ [ICE_RXDID_COMMS_AUX_IPV6_FLOW] = PROTO_XTR_IPV6_FLOW,
> >+ [ICE_RXDID_COMMS_AUX_TCP] = PROTO_XTR_TCP,
> >+ };
> >+
> >+ return rxdid < RTE_DIM(xtr_map) ? xtr_map[rxdid] : PROTO_XTR_NONE;
> >+}
> >+
> >+static inline uint8_t
> >+ice_proto_xtr_type_to_rxdid(uint8_t xtr_tpye)
> >+{
> >+ static uint8_t rxdid_map[] = {
> >+ [PROTO_XTR_VLAN] = ICE_RXDID_COMMS_AUX_VLAN,
> >+ [PROTO_XTR_IPV4] = ICE_RXDID_COMMS_AUX_IPV4,
> >+ [PROTO_XTR_IPV6] = ICE_RXDID_COMMS_AUX_IPV6,
> >+ [PROTO_XTR_IPV6_FLOW] = ICE_RXDID_COMMS_AUX_IPV6_FLOW,
> >+ [PROTO_XTR_TCP] = ICE_RXDID_COMMS_AUX_TCP,
> >+ };
> >+ uint8_t rxdid;
> >+
> >+ rxdid = xtr_tpye < RTE_DIM(rxdid_map) ? rxdid_map[xtr_tpye] : 0;
> >+
> >+ return rxdid != 0 ? rxdid : ICE_RXDID_COMMS_GENERIC;
> >+}
> >
> > static enum ice_status
> > ice_program_hw_rx_queue(struct ice_rx_queue *rxq)
> >@@ -84,6 +114,11 @@ ice_program_hw_rx_queue(struct ice_rx_queue *rxq)
> > rx_ctx.showiv = 0;
> > rx_ctx.crcstrip = (rxq->crc_len == 0) ? 1 : 0;
> >
> >+ rxdid = ice_proto_xtr_type_to_rxdid(rxq->proto_xtr);
> >+
> >+ PMD_DRV_LOG(DEBUG, "Port (%u) - Rx queue (%u) is set with RXDID : %u",
> >+ rxq->port_id, rxq->queue_id, rxdid);
> >+
> > /* Enable Flexible Descriptors in the queue context which
> > * allows this driver to select a specific receive descriptor format
> > */
> >@@ -641,6 +676,8 @@ ice_rx_queue_setup(struct rte_eth_dev *dev,
> > rxq->drop_en = rx_conf->rx_drop_en;
> > rxq->vsi = vsi;
> > rxq->rx_deferred_start = rx_conf->rx_deferred_start;
> >+ rxq->proto_xtr = pf->proto_xtr != NULL ?
> >+ pf->proto_xtr[queue_idx] : PROTO_XTR_NONE;
> >
> > /* Allocate the maximun number of RX ring hardware descriptor. */
> > len = ICE_MAX_RING_DESC;
> >@@ -1062,6 +1099,10 @@ ice_rxd_to_vlan_tci(struct rte_mbuf *mb, volatile union ice_rx_flex_desc *rxdp)
> > mb->vlan_tci, mb->vlan_tci_outer);
> > }
> >
> >+#define ICE_RX_PROTO_XTR_VALID \
> >+ ((1 << ICE_RX_FLEX_DESC_STATUS1_XTRMD4_VALID_S) | \
> >+ (1 << ICE_RX_FLEX_DESC_STATUS1_XTRMD5_VALID_S))
> >+
> > static inline void
> > ice_rxd_to_pkt_fields(struct rte_mbuf *mb,
> > volatile union ice_rx_flex_desc *rxdp)
> >@@ -1075,6 +1116,26 @@ ice_rxd_to_pkt_fields(struct rte_mbuf *mb,
> > mb->ol_flags |= PKT_RX_RSS_HASH;
> > mb->hash.rss = rte_le_to_cpu_32(desc->rss_hash);
> > }
> >+
> >+#ifndef RTE_LIBRTE_ICE_16BYTE_RX_DESC
> >+ init_proto_xtr_flds(mb);
> >+
> >+ stat_err = rte_le_to_cpu_16(desc->status_error1);
> >+ if (stat_err & ICE_RX_PROTO_XTR_VALID) {
> >+ struct proto_xtr_flds *xtr = get_proto_xtr_flds(mb);
> >+
> >+ if (stat_err & (1 << ICE_RX_FLEX_DESC_STATUS1_XTRMD4_VALID_S))
> >+ xtr->u.raw.data0 =
> >+ rte_le_to_cpu_16(desc->flex_ts.flex.aux0);
> >+
> >+ if (stat_err & (1 << ICE_RX_FLEX_DESC_STATUS1_XTRMD5_VALID_S))
> >+ xtr->u.raw.data1 =
> >+ rte_le_to_cpu_16(desc->flex_ts.flex.aux1);
> >+
> >+ xtr->type = ice_rxdid_to_proto_xtr_type(desc->rxdid);
> >+ xtr->magic = PROTO_XTR_MAGIC_ID;
> >+ }
> >+#endif
> > }
> >
> > #ifdef RTE_LIBRTE_ICE_RX_ALLOW_BULK_ALLOC
> >diff --git a/drivers/net/ice/ice_rxtx.h b/drivers/net/ice/ice_rxtx.h
> >index 64e891875..de16637f3 100644
> >--- a/drivers/net/ice/ice_rxtx.h
> >+++ b/drivers/net/ice/ice_rxtx.h
> >@@ -5,6 +5,7 @@
> > #ifndef _ICE_RXTX_H_
> > #define _ICE_RXTX_H_
> >
> >+#include "rte_pmd_ice.h"
> > #include "ice_ethdev.h"
> >
> > #define ICE_ALIGN_RING_DESC 32
> >@@ -78,6 +79,7 @@ struct ice_rx_queue {
> > uint16_t max_pkt_len; /* Maximum packet length */
> > bool q_set; /* indicate if rx queue has been configured */
> > bool rx_deferred_start; /* don't start this queue in dev start */
> >+ uint8_t proto_xtr; /* Protocol extraction from flexible descriptor */
> > ice_rx_release_mbufs_t rx_rel_mbufs;
> > };
> >
> >diff --git a/drivers/net/ice/ice_rxtx_vec_common.h b/drivers/net/ice/ice_rxtx_vec_common.h
> >index c5f0d564f..080ca4175 100644
> >--- a/drivers/net/ice/ice_rxtx_vec_common.h
> >+++ b/drivers/net/ice/ice_rxtx_vec_common.h
> >@@ -234,6 +234,9 @@ ice_rx_vec_queue_default(struct ice_rx_queue *rxq)
> > if (rxq->nb_rx_desc % rxq->rx_free_thresh)
> > return -1;
> >
> >+ if (rxq->proto_xtr != PROTO_XTR_NONE)
> >+ return -1;
> >+
> > return 0;
> > }
> >
> >diff --git a/drivers/net/ice/meson.build b/drivers/net/ice/meson.build
> >index 36b4b3c85..6828170a9 100644
> >--- a/drivers/net/ice/meson.build
> >+++ b/drivers/net/ice/meson.build
> >@@ -34,3 +34,5 @@ if arch_subdir == 'x86'
> > objs += ice_avx2_lib.extract_objects('ice_rxtx_vec_avx2.c')
> > endif
> > endif
> >+
> >+install_headers('rte_pmd_ice.h')
> >diff --git a/drivers/net/ice/rte_pmd_ice.h b/drivers/net/ice/rte_pmd_ice.h
> >new file mode 100644
> >index 000000000..719487e1e
> >--- /dev/null
> >+++ b/drivers/net/ice/rte_pmd_ice.h
> >@@ -0,0 +1,152 @@
> >+/* SPDX-License-Identifier: BSD-3-Clause
> >+ * Copyright(c) 2019 Intel Corporation
> >+ */
> >+
> >+#ifndef _RTE_PMD_ICE_H_
> >+#define _RTE_PMD_ICE_H_
> >+
> >+#include <stdio.h>
> >+#include <rte_mbuf.h>
> >+#include <rte_ethdev.h>
> >+
> >+#ifdef __cplusplus
> >+extern "C" {
> >+#endif
> >+
> >+enum proto_xtr_type {
> >+ PROTO_XTR_NONE,
> >+ PROTO_XTR_VLAN,
> >+ PROTO_XTR_IPV4,
> >+ PROTO_XTR_IPV6,
> >+ PROTO_XTR_IPV6_FLOW,
> >+ PROTO_XTR_TCP,
> >+};
> >+
> >+struct proto_xtr_flds {
> >+ union {
> >+ struct {
> >+ uint16_t data0;
> >+ uint16_t data1;
> >+ } raw;
> >+ struct {
> >+ uint16_t stag_vid:12,
> >+ stag_dei:1,
> >+ stag_pcp:3;
> >+ uint16_t ctag_vid:12,
> >+ ctag_dei:1,
> >+ ctag_pcp:3;
> >+ } vlan;
> >+ struct {
> >+ uint16_t protocol:8,
> >+ ttl:8;
> >+ uint16_t tos:8,
> >+ ihl:4,
> >+ version:4;
> >+ } ipv4;
> >+ struct {
> >+ uint16_t hoplimit:8,
> >+ nexthdr:8;
> >+ uint16_t flowhi4:4,
> >+ tc:8,
> >+ version:4;
> >+ } ipv6;
> >+ struct {
> >+ uint16_t flowlo16;
> >+ uint16_t flowhi4:4,
> >+ tc:8,
> >+ version:4;
> >+ } ipv6_flow;
> >+ struct {
> >+ uint16_t fin:1,
> >+ syn:1,
> >+ rst:1,
> >+ psh:1,
> >+ ack:1,
> >+ urg:1,
> >+ ece:1,
> >+ cwr:1,
> >+ res1:4,
> >+ doff:4;
> >+ uint16_t rsvd;
> >+ } tcp;
> >+ } u;
> >+
> >+ uint16_t rsvd;
> >+
> >+ uint8_t type;
> >+
> >+#define PROTO_XTR_MAGIC_ID 0xCE
> >+ uint8_t magic;
> >+};
> >+
> >+static inline void
> >+init_proto_xtr_flds(struct rte_mbuf *mb)
> >+{
> >+ mb->udata64 = 0;
> >+}
> >+
> >+static inline struct proto_xtr_flds *
> >+get_proto_xtr_flds(struct rte_mbuf *mb)
> >+{
> >+ RTE_BUILD_BUG_ON(sizeof(struct proto_xtr_flds) > sizeof(mb->udata64));
> >+
> >+ return (struct proto_xtr_flds *)&mb->udata64;
> >+}
> >+
> >+static inline void
> >+dump_proto_xtr_flds(struct rte_mbuf *mb)
> >+{
> >+ struct proto_xtr_flds *xtr = get_proto_xtr_flds(mb);
> >+
> >+ if (xtr->magic != PROTO_XTR_MAGIC_ID || xtr->type == PROTO_XTR_NONE)
> >+ return;
> >+
> >+ printf(" - Protocol Extraction:[0x%04x:0x%04x],",
> >+ xtr->u.raw.data0, xtr->u.raw.data1);
> >+
> >+ if (xtr->type == PROTO_XTR_VLAN)
> >+ printf("vlan,stag=%u:%u:%u,ctag=%u:%u:%u ",
> >+ xtr->u.vlan.stag_pcp,
> >+ xtr->u.vlan.stag_dei,
> >+ xtr->u.vlan.stag_vid,
> >+ xtr->u.vlan.ctag_pcp,
> >+ xtr->u.vlan.ctag_dei,
> >+ xtr->u.vlan.ctag_vid);
> >+ else if (xtr->type == PROTO_XTR_IPV4)
> >+ printf("ipv4,ver=%u,hdrlen=%u,tos=%u,ttl=%u,proto=%u ",
> >+ xtr->u.ipv4.version,
> >+ xtr->u.ipv4.ihl,
> >+ xtr->u.ipv4.tos,
> >+ xtr->u.ipv4.ttl,
> >+ xtr->u.ipv4.protocol);
> >+ else if (xtr->type == PROTO_XTR_IPV6)
> >+ printf("ipv6,ver=%u,tc=%u,flow_hi4=0x%x,nexthdr=%u,hoplimit=%u ",
> >+ xtr->u.ipv6.version,
> >+ xtr->u.ipv6.tc,
> >+ xtr->u.ipv6.flowhi4,
> >+ xtr->u.ipv6.nexthdr,
> >+ xtr->u.ipv6.hoplimit);
> >+ else if (xtr->type == PROTO_XTR_IPV6_FLOW)
> >+ printf("ipv6_flow,ver=%u,tc=%u,flow=0x%x%04x ",
> >+ xtr->u.ipv6_flow.version,
> >+ xtr->u.ipv6_flow.tc,
> >+ xtr->u.ipv6_flow.flowhi4,
> >+ xtr->u.ipv6_flow.flowlo16);
> >+ else if (xtr->type == PROTO_XTR_TCP)
> >+ printf("tcp,doff=%u,flags=%s%s%s%s%s%s%s%s ",
> >+ xtr->u.tcp.doff,
> >+ xtr->u.tcp.cwr ? "C" : "",
> >+ xtr->u.tcp.ece ? "E" : "",
> >+ xtr->u.tcp.urg ? "U" : "",
> >+ xtr->u.tcp.ack ? "A" : "",
> >+ xtr->u.tcp.psh ? "P" : "",
> >+ xtr->u.tcp.rst ? "R" : "",
> >+ xtr->u.tcp.syn ? "S" : "",
> >+ xtr->u.tcp.fin ? "F" : "");
> >+}
> >+
> >+#ifdef __cplusplus
> >+}
> >+#endif
> >+
> >+#endif /* _RTE_PMD_ICE_H_ */
> >--
> >2.17.1
> >
> -----Original Message-----
> From: Ye, Xiaolong
> Sent: Thursday, September 19, 2019 07:30
> To: Rong, Leyi <leyi.rong@intel.com>
> Cc: Wang, Haiyue <haiyue.wang@intel.com>; Lu, Wenzhuo <wenzhuo.lu@intel.com>; Zhang, Qi Z
> <qi.z.zhang@intel.com>; dev@dpdk.org
> Subject: Re: [PATCH v3 3/5] net/ice: add protocol extraction support for per Rx queue
>
> On 09/17, Leyi Rong wrote:
> >From: Haiyue Wang <haiyue.wang@intel.com>
> >
> >The ice has the feature to extract protocol fields into flex descriptor
> >by programming per queue. Currently, the ice PMD will put the protocol
> >fields into rte_mbuf::udata64 with different type format. Application
> >can access the protocol fields quickly.
> >
[snip]
> >+
> >+ rte_kvargs_process(kvlist, ICE_PROTO_XTR_ARG,
> >+ handle_proto_xtr_arg, devargs);
>
> Do we need to check ret of rte_kvargs_process here and change ice_parse_proto_xtr_devarg
> to return int?
>
May be return error is a good idea, if the application wants to use it. I just
give a graceful warning message. Will change it, thanks!
PMD_DRV_LOG(ERR,
"The protocol extraction parameter is wrong : '%s'",
value);
return -1;
> >--
> >2.17.1
> >
@@ -61,6 +61,107 @@ Runtime Config Options
NOTE: In Safe mode, only very limited features are available, features like RSS,
checksum, fdir, tunneling ... are all disabled.
+- ``Protocol extraction for per queue``
+
+ Configure the RX queues to do protocol extraction into ``rte_mbuf::udata64``
+ for protocol handling acceleration, like checking the TCP SYN packets quickly.
+
+ The argument format is::
+
+ -w 18:00.0,proto_xtr=<queues:protocol>[<queues:protocol>...]
+ -w 18:00.0,proto_xtr=<protocol>
+
+ Queues are grouped by ``(`` and ``)`` within the group. The ``-`` character
+ is used as a range separator and ``,`` is used as a single number separator.
+ The grouping ``()`` can be omitted for single element group. If no queues are
+ specified, PMD will use this protocol extraction type for all queues.
+
+ Protocol is : ``vlan, ipv4, ipv6, ipv6_flow, tcp``.
+
+ .. code-block:: console
+
+ testpmd -w 18:00.0,proto_xtr='[(1,2-3,8-9):tcp,10-13:vlan]'
+
+ This setting means queues 1, 2-3, 8-9 are TCP extraction, queues 10-13 are
+ VLAN extraction, other queues run with no protocol extraction.
+
+ .. code-block:: console
+
+ testpmd -w 18:00.0,proto_xtr=vlan,proto_xtr='[(1,2-3,8-9):tcp,10-23:ipv6]'
+
+ This setting means queues 1, 2-3, 8-9 are TCP extraction, queues 10-23 are
+ IPv6 extraction, other queues use the default VLAN extraction.
+
+ The extraction will be copied into the lower 32 bit of ``rte_mbuf::udata64``.
+
+ .. table:: Protocol extraction : ``vlan``
+
+ +----------------------------+----------------------------+
+ | VLAN2 | VLAN1 |
+ +======+===+=================+======+===+=================+
+ | PCP | D | VID | PCP | D | VID |
+ +------+---+-----------------+------+---+-----------------+
+
+ VLAN1 - single or EVLAN (first for QinQ).
+
+ VLAN2 - C-VLAN (second for QinQ).
+
+ .. table:: Protocol extraction : ``ipv4``
+
+ +----------------------------+----------------------------+
+ | IPHDR2 | IPHDR1 |
+ +======+=======+=============+==============+=============+
+ | Ver |Hdr Len| ToS | TTL | Protocol |
+ +------+-------+-------------+--------------+-------------+
+
+ IPHDR1 - IPv4 header word 4, "TTL" and "Protocol" fields.
+
+ IPHDR2 - IPv4 header word 0, "Ver", "Hdr Len" and "Type of Service" fields.
+
+ .. table:: Protocol extraction : ``ipv6``
+
+ +----------------------------+----------------------------+
+ | IPHDR2 | IPHDR1 |
+ +=====+=============+========+=============+==============+
+ | Ver |Traffic class| Flow | Next Header | Hop Limit |
+ +-----+-------------+--------+-------------+--------------+
+
+ IPHDR1 - IPv6 header word 3, "Next Header" and "Hop Limit" fields.
+
+ IPHDR2 - IPv6 header word 0, "Ver", "Traffic class" and high 4 bits of
+ "Flow Label" fields.
+
+ .. table:: Protocol extraction : ``ipv6_flow``
+
+ +----------------------------+----------------------------+
+ | IPHDR2 | IPHDR1 |
+ +=====+=============+========+============================+
+ | Ver |Traffic class| Flow Label |
+ +-----+-------------+-------------------------------------+
+
+ IPHDR1 - IPv6 header word 1, 16 low bits of the "Flow Label" field.
+
+ IPHDR2 - IPv6 header word 0, "Ver", "Traffic class" and high 4 bits of
+ "Flow Label" fields.
+
+ .. table:: Protocol extraction : ``tcp``
+
+ +----------------------------+----------------------------+
+ | TCPHDR2 | TCPHDR1 |
+ +============================+======+======+==============+
+ | Reserved |Offset| RSV | Flags |
+ +----------------------------+------+------+--------------+
+
+ TCPHDR1 - TCP header word 6, "Data Offset" and "Flags" fields.
+
+ TCPHDR2 - Reserved
+
+ Use ``get_proto_xtr_flds(struct rte_mbuf *mb)`` to access the protocol
+ extraction, do not use ``rte_mbuf::udata64`` directly.
+
+ The ``dump_proto_xtr_flds(struct rte_mbuf *mb)`` routine shows how to
+ access the protocol extraction result in ``struct rte_mbuf``.
+
Driver compilation and testing
------------------------------
@@ -82,4 +82,7 @@ ifeq ($(CC_AVX2_SUPPORT), 1)
endif
SRCS-$(CONFIG_RTE_LIBRTE_ICE_PMD) += ice_generic_flow.c
+# install this header file
+SYMLINK-$(CONFIG_RTE_LIBRTE_ICE_PMD)-include := rte_pmd_ice.h
+
include $(RTE_SDK)/mk/rte.lib.mk
@@ -19,9 +19,11 @@
/* devargs */
#define ICE_SAFE_MODE_SUPPORT_ARG "safe-mode-support"
+#define ICE_PROTO_XTR_ARG "proto_xtr"
static const char * const ice_valid_args[] = {
ICE_SAFE_MODE_SUPPORT_ARG,
+ ICE_PROTO_XTR_ARG,
NULL
};
@@ -257,6 +259,293 @@ ice_init_controlq_parameter(struct ice_hw *hw)
hw->mailboxq.sq_buf_size = ICE_MAILBOXQ_BUF_SZ;
}
+static int
+lookup_proto_xtr_type(const char *xtr_name)
+{
+ static struct {
+ const char *name;
+ enum proto_xtr_type type;
+ } xtr_type_map[] = {
+ { "vlan", PROTO_XTR_VLAN },
+ { "ipv4", PROTO_XTR_IPV4 },
+ { "ipv6", PROTO_XTR_IPV6 },
+ { "ipv6_flow", PROTO_XTR_IPV6_FLOW },
+ { "tcp", PROTO_XTR_TCP },
+ };
+ uint32_t i;
+
+ for (i = 0; i < RTE_DIM(xtr_type_map); i++) {
+ if (strcmp(xtr_name, xtr_type_map[i].name) == 0)
+ return xtr_type_map[i].type;
+ }
+
+ return -1;
+}
+
+/*
+ * Parse elem, the elem could be single number/range or '(' ')' group
+ * 1) A single number elem, it's just a simple digit. e.g. 9
+ * 2) A single range elem, two digits with a '-' between. e.g. 2-6
+ * 3) A group elem, combines multiple 1) or 2) with '( )'. e.g (0,2-4,6)
+ * Within group elem, '-' used for a range separator;
+ * ',' used for a single number.
+ */
+static int
+parse_queue_set(const char *input, int xtr_type, struct ice_devargs *devargs)
+{
+ const char *str = input;
+ char *end = NULL;
+ uint32_t min, max;
+ uint32_t idx;
+
+ while (isblank(*str))
+ str++;
+
+ if ((!isdigit(*str) && *str != '(') || (*str == '\0'))
+ return -1;
+
+ /* process single number or single range of number */
+ if (*str != '(') {
+ errno = 0;
+ idx = strtoul(str, &end, 10);
+ if (errno || end == NULL || idx >= ICE_MAX_QUEUE_NUM)
+ return -1;
+
+ while (isblank(*end))
+ end++;
+
+ min = idx;
+ max = idx;
+
+ /* process single <number>-<number> */
+ if (*end == '-') {
+ end++;
+ while (isblank(*end))
+ end++;
+ if (!isdigit(*end))
+ return -1;
+
+ errno = 0;
+ idx = strtoul(end, &end, 10);
+ if (errno || end == NULL || idx >= ICE_MAX_QUEUE_NUM)
+ return -1;
+
+ max = idx;
+ while (isblank(*end))
+ end++;
+ }
+
+ if (*end != ':')
+ return -1;
+
+ for (idx = RTE_MIN(min, max);
+ idx <= RTE_MAX(min, max); idx++)
+ devargs->proto_xtr[idx] = xtr_type;
+
+ return 0;
+ }
+
+ /* process set within bracket */
+ str++;
+ while (isblank(*str))
+ str++;
+ if (*str == '\0')
+ return -1;
+
+ min = ICE_MAX_QUEUE_NUM;
+ do {
+ /* go ahead to the first digit */
+ while (isblank(*str))
+ str++;
+ if (!isdigit(*str))
+ return -1;
+
+ /* get the digit value */
+ errno = 0;
+ idx = strtoul(str, &end, 10);
+ if (errno || end == NULL || idx >= ICE_MAX_QUEUE_NUM)
+ return -1;
+
+ /* go ahead to separator '-',',' and ')' */
+ while (isblank(*end))
+ end++;
+ if (*end == '-') {
+ if (min == ICE_MAX_QUEUE_NUM)
+ min = idx;
+ else /* avoid continuous '-' */
+ return -1;
+ } else if (*end == ',' || *end == ')') {
+ max = idx;
+ if (min == ICE_MAX_QUEUE_NUM)
+ min = idx;
+
+ for (idx = RTE_MIN(min, max);
+ idx <= RTE_MAX(min, max); idx++)
+ devargs->proto_xtr[idx] = xtr_type;
+
+ min = ICE_MAX_QUEUE_NUM;
+ } else {
+ return -1;
+ }
+
+ str = end + 1;
+ } while (*end != ')' && *end != '\0');
+
+ return 0;
+}
+
+static int
+parse_queue_proto_xtr(const char *queues, struct ice_devargs *devargs)
+{
+ const char *queue_start;
+ uint32_t idx;
+ int xtr_type;
+ char xtr_name[32];
+
+ while (isblank(*queues))
+ queues++;
+
+ if (*queues != '[') {
+ xtr_type = lookup_proto_xtr_type(queues);
+ if (xtr_type < 0)
+ return -1;
+
+ devargs->proto_xtr_dflt = xtr_type;
+ return 0;
+ }
+
+ queues++;
+ do {
+ while (isblank(*queues))
+ queues++;
+ if (*queues == '\0')
+ return -1;
+
+ queue_start = queues;
+
+ /* go across a complete bracket */
+ if (*queue_start == '(') {
+ queues += strcspn(queues, ")");
+ if (*queues != ')')
+ return -1;
+ }
+
+ /* scan the separator ':' */
+ queues += strcspn(queues, ":");
+ if (*queues++ != ':')
+ return -1;
+ while (isblank(*queues))
+ queues++;
+
+ for (idx = 0; ; idx++) {
+ if (isblank(queues[idx]) ||
+ queues[idx] == ',' ||
+ queues[idx] == ']' ||
+ queues[idx] == '\0')
+ break;
+
+ if (idx > sizeof(xtr_name) - 2)
+ return -1;
+
+ xtr_name[idx] = queues[idx];
+ }
+ xtr_name[idx] = '\0';
+ xtr_type = lookup_proto_xtr_type(xtr_name);
+ if (xtr_type < 0)
+ return -1;
+
+ queues += idx;
+
+ while (isblank(*queues) || *queues == ',' || *queues == ']')
+ queues++;
+
+ if (parse_queue_set(queue_start, xtr_type, devargs) < 0)
+ return -1;
+ } while (*queues != '\0');
+
+ return 0;
+}
+
+static int
+handle_proto_xtr_arg(__rte_unused const char *key, const char *value,
+ void *extra_args)
+{
+ struct ice_devargs *devargs = extra_args;
+
+ if (value == NULL || extra_args == NULL)
+ return -EINVAL;
+
+ if (parse_queue_proto_xtr(value, devargs) < 0) {
+ PMD_DRV_LOG(ERR,
+ "The protocol extraction parameter is wrong : '%s'",
+ value);
+ return -1;
+ }
+
+ return 0;
+}
+
+static void
+ice_parse_proto_xtr_devarg(struct rte_kvargs *kvlist,
+ struct ice_devargs *devargs)
+{
+ int i;
+
+ devargs->proto_xtr_dflt = PROTO_XTR_NONE;
+
+ for (i = 0; i < ICE_MAX_QUEUE_NUM; i++)
+ devargs->proto_xtr[i] = PROTO_XTR_NONE;
+
+ rte_kvargs_process(kvlist, ICE_PROTO_XTR_ARG,
+ handle_proto_xtr_arg, devargs);
+}
+
+static bool
+ice_proto_xtr_support(struct ice_hw *hw)
+{
+#define FLX_REG(val, fld, idx) \
+ (((val) & GLFLXP_RXDID_FLX_WRD_##idx##_##fld##_M) >> \
+ GLFLXP_RXDID_FLX_WRD_##idx##_##fld##_S)
+ static struct {
+ uint32_t rxdid;
+ uint16_t protid_0;
+ uint16_t protid_1;
+ } xtr_sets[] = {
+ { ICE_RXDID_COMMS_AUX_VLAN, ICE_PROT_EVLAN_O, ICE_PROT_VLAN_O },
+ { ICE_RXDID_COMMS_AUX_IPV4, ICE_PROT_IPV4_OF_OR_S,
+ ICE_PROT_IPV4_OF_OR_S },
+ { ICE_RXDID_COMMS_AUX_IPV6, ICE_PROT_IPV6_OF_OR_S,
+ ICE_PROT_IPV6_OF_OR_S },
+ { ICE_RXDID_COMMS_AUX_IPV6_FLOW, ICE_PROT_IPV6_OF_OR_S,
+ ICE_PROT_IPV6_OF_OR_S },
+ { ICE_RXDID_COMMS_AUX_TCP, ICE_PROT_TCP_IL, ICE_PROT_ID_INVAL },
+ };
+ uint32_t i;
+
+ for (i = 0; i < RTE_DIM(xtr_sets); i++) {
+ uint32_t rxdid = xtr_sets[i].rxdid;
+ uint32_t v;
+
+ if (xtr_sets[i].protid_0 != ICE_PROT_ID_INVAL) {
+ v = ICE_READ_REG(hw, GLFLXP_RXDID_FLX_WRD_4(rxdid));
+
+ if (FLX_REG(v, PROT_MDID, 4) != xtr_sets[i].protid_0 ||
+ FLX_REG(v, RXDID_OPCODE, 4) != ICE_RX_OPC_EXTRACT)
+ return false;
+ }
+
+ if (xtr_sets[i].protid_1 != ICE_PROT_ID_INVAL) {
+ v = ICE_READ_REG(hw, GLFLXP_RXDID_FLX_WRD_5(rxdid));
+
+ if (FLX_REG(v, PROT_MDID, 5) != xtr_sets[i].protid_1 ||
+ FLX_REG(v, RXDID_OPCODE, 5) != ICE_RX_OPC_EXTRACT)
+ return false;
+ }
+ }
+
+ return true;
+}
+
static int
ice_res_pool_init(struct ice_res_pool_info *pool, uint32_t base,
uint32_t num)
@@ -1079,6 +1368,8 @@ ice_interrupt_handler(void *param)
static int
ice_pf_sw_init(struct rte_eth_dev *dev)
{
+ struct ice_adapter *ad =
+ ICE_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
struct ice_pf *pf = ICE_DEV_PRIVATE_TO_PF(dev->data->dev_private);
struct ice_hw *hw = ICE_PF_TO_HW(pf);
@@ -1088,6 +1379,21 @@ ice_pf_sw_init(struct rte_eth_dev *dev)
pf->lan_nb_qps = pf->lan_nb_qp_max;
+ if (ice_proto_xtr_support(hw))
+ pf->proto_xtr = rte_zmalloc(NULL, pf->lan_nb_qps, 0);
+
+ if (pf->proto_xtr != NULL) {
+ uint16_t i;
+
+ for (i = 0; i < pf->lan_nb_qps; i++)
+ pf->proto_xtr[i] =
+ ad->devargs.proto_xtr[i] != PROTO_XTR_NONE ?
+ ad->devargs.proto_xtr[i] :
+ ad->devargs.proto_xtr_dflt;
+ } else {
+ PMD_DRV_LOG(NOTICE, "Protocol extraction is disabled");
+ }
+
return 0;
}
@@ -1378,6 +1684,8 @@ static int ice_parse_devargs(struct rte_eth_dev *dev)
return -EINVAL;
}
+ ice_parse_proto_xtr_devarg(kvlist, &ad->devargs);
+
ret = rte_kvargs_process(kvlist, ICE_SAFE_MODE_SUPPORT_ARG,
&parse_bool, &ad->devargs.safe_mode_support);
@@ -1547,6 +1855,7 @@ ice_dev_init(struct rte_eth_dev *dev)
ice_sched_cleanup_all(hw);
rte_free(hw->port_info);
ice_shutdown_all_ctrlq(hw);
+ rte_free(pf->proto_xtr);
return ret;
}
@@ -1672,6 +1981,8 @@ ice_dev_close(struct rte_eth_dev *dev)
rte_free(hw->port_info);
hw->port_info = NULL;
ice_shutdown_all_ctrlq(hw);
+ rte_free(pf->proto_xtr);
+ pf->proto_xtr = NULL;
}
static int
@@ -3795,6 +4106,7 @@ RTE_PMD_REGISTER_PCI(net_ice, rte_ice_pmd);
RTE_PMD_REGISTER_PCI_TABLE(net_ice, pci_id_ice_map);
RTE_PMD_REGISTER_KMOD_DEP(net_ice, "* igb_uio | uio_pci_generic | vfio-pci");
RTE_PMD_REGISTER_PARAM_STRING(net_ice,
+ ICE_PROTO_XTR_ARG "=[queue:]<vlan|ipv4|ipv6|ipv6_flow|tcp>"
ICE_SAFE_MODE_SUPPORT_ARG "=<0|1>");
RTE_INIT(ice_init_log)
@@ -263,6 +263,7 @@ struct ice_pf {
uint16_t lan_nb_qp_max;
uint16_t lan_nb_qps; /* The number of queue pairs of LAN */
uint16_t base_queue; /* The base queue pairs index in the device */
+ uint8_t *proto_xtr; /* Protocol extraction type for all queues */
struct ice_hw_port_stats stats_offset;
struct ice_hw_port_stats stats;
/* internal packet statistics, it should be excluded from the total */
@@ -273,11 +274,15 @@ struct ice_pf {
struct ice_flow_list flow_list;
};
+#define ICE_MAX_QUEUE_NUM 2048
+
/**
* Cache devargs parse result.
*/
struct ice_devargs {
int safe_mode_support;
+ uint8_t proto_xtr_dflt;
+ uint8_t proto_xtr[ICE_MAX_QUEUE_NUM];
};
/**
@@ -13,6 +13,36 @@
PKT_TX_TCP_SEG | \
PKT_TX_OUTER_IP_CKSUM)
+static inline uint8_t
+ice_rxdid_to_proto_xtr_type(uint8_t rxdid)
+{
+ static uint8_t xtr_map[] = {
+ [ICE_RXDID_COMMS_AUX_VLAN] = PROTO_XTR_VLAN,
+ [ICE_RXDID_COMMS_AUX_IPV4] = PROTO_XTR_IPV4,
+ [ICE_RXDID_COMMS_AUX_IPV6] = PROTO_XTR_IPV6,
+ [ICE_RXDID_COMMS_AUX_IPV6_FLOW] = PROTO_XTR_IPV6_FLOW,
+ [ICE_RXDID_COMMS_AUX_TCP] = PROTO_XTR_TCP,
+ };
+
+ return rxdid < RTE_DIM(xtr_map) ? xtr_map[rxdid] : PROTO_XTR_NONE;
+}
+
+static inline uint8_t
+ice_proto_xtr_type_to_rxdid(uint8_t xtr_tpye)
+{
+ static uint8_t rxdid_map[] = {
+ [PROTO_XTR_VLAN] = ICE_RXDID_COMMS_AUX_VLAN,
+ [PROTO_XTR_IPV4] = ICE_RXDID_COMMS_AUX_IPV4,
+ [PROTO_XTR_IPV6] = ICE_RXDID_COMMS_AUX_IPV6,
+ [PROTO_XTR_IPV6_FLOW] = ICE_RXDID_COMMS_AUX_IPV6_FLOW,
+ [PROTO_XTR_TCP] = ICE_RXDID_COMMS_AUX_TCP,
+ };
+ uint8_t rxdid;
+
+ rxdid = xtr_tpye < RTE_DIM(rxdid_map) ? rxdid_map[xtr_tpye] : 0;
+
+ return rxdid != 0 ? rxdid : ICE_RXDID_COMMS_GENERIC;
+}
static enum ice_status
ice_program_hw_rx_queue(struct ice_rx_queue *rxq)
@@ -84,6 +114,11 @@ ice_program_hw_rx_queue(struct ice_rx_queue *rxq)
rx_ctx.showiv = 0;
rx_ctx.crcstrip = (rxq->crc_len == 0) ? 1 : 0;
+ rxdid = ice_proto_xtr_type_to_rxdid(rxq->proto_xtr);
+
+ PMD_DRV_LOG(DEBUG, "Port (%u) - Rx queue (%u) is set with RXDID : %u",
+ rxq->port_id, rxq->queue_id, rxdid);
+
/* Enable Flexible Descriptors in the queue context which
* allows this driver to select a specific receive descriptor format
*/
@@ -641,6 +676,8 @@ ice_rx_queue_setup(struct rte_eth_dev *dev,
rxq->drop_en = rx_conf->rx_drop_en;
rxq->vsi = vsi;
rxq->rx_deferred_start = rx_conf->rx_deferred_start;
+ rxq->proto_xtr = pf->proto_xtr != NULL ?
+ pf->proto_xtr[queue_idx] : PROTO_XTR_NONE;
/* Allocate the maximun number of RX ring hardware descriptor. */
len = ICE_MAX_RING_DESC;
@@ -1062,6 +1099,10 @@ ice_rxd_to_vlan_tci(struct rte_mbuf *mb, volatile union ice_rx_flex_desc *rxdp)
mb->vlan_tci, mb->vlan_tci_outer);
}
+#define ICE_RX_PROTO_XTR_VALID \
+ ((1 << ICE_RX_FLEX_DESC_STATUS1_XTRMD4_VALID_S) | \
+ (1 << ICE_RX_FLEX_DESC_STATUS1_XTRMD5_VALID_S))
+
static inline void
ice_rxd_to_pkt_fields(struct rte_mbuf *mb,
volatile union ice_rx_flex_desc *rxdp)
@@ -1075,6 +1116,26 @@ ice_rxd_to_pkt_fields(struct rte_mbuf *mb,
mb->ol_flags |= PKT_RX_RSS_HASH;
mb->hash.rss = rte_le_to_cpu_32(desc->rss_hash);
}
+
+#ifndef RTE_LIBRTE_ICE_16BYTE_RX_DESC
+ init_proto_xtr_flds(mb);
+
+ stat_err = rte_le_to_cpu_16(desc->status_error1);
+ if (stat_err & ICE_RX_PROTO_XTR_VALID) {
+ struct proto_xtr_flds *xtr = get_proto_xtr_flds(mb);
+
+ if (stat_err & (1 << ICE_RX_FLEX_DESC_STATUS1_XTRMD4_VALID_S))
+ xtr->u.raw.data0 =
+ rte_le_to_cpu_16(desc->flex_ts.flex.aux0);
+
+ if (stat_err & (1 << ICE_RX_FLEX_DESC_STATUS1_XTRMD5_VALID_S))
+ xtr->u.raw.data1 =
+ rte_le_to_cpu_16(desc->flex_ts.flex.aux1);
+
+ xtr->type = ice_rxdid_to_proto_xtr_type(desc->rxdid);
+ xtr->magic = PROTO_XTR_MAGIC_ID;
+ }
+#endif
}
#ifdef RTE_LIBRTE_ICE_RX_ALLOW_BULK_ALLOC
@@ -5,6 +5,7 @@
#ifndef _ICE_RXTX_H_
#define _ICE_RXTX_H_
+#include "rte_pmd_ice.h"
#include "ice_ethdev.h"
#define ICE_ALIGN_RING_DESC 32
@@ -78,6 +79,7 @@ struct ice_rx_queue {
uint16_t max_pkt_len; /* Maximum packet length */
bool q_set; /* indicate if rx queue has been configured */
bool rx_deferred_start; /* don't start this queue in dev start */
+ uint8_t proto_xtr; /* Protocol extraction from flexible descriptor */
ice_rx_release_mbufs_t rx_rel_mbufs;
};
@@ -234,6 +234,9 @@ ice_rx_vec_queue_default(struct ice_rx_queue *rxq)
if (rxq->nb_rx_desc % rxq->rx_free_thresh)
return -1;
+ if (rxq->proto_xtr != PROTO_XTR_NONE)
+ return -1;
+
return 0;
}
@@ -34,3 +34,5 @@ if arch_subdir == 'x86'
objs += ice_avx2_lib.extract_objects('ice_rxtx_vec_avx2.c')
endif
endif
+
+install_headers('rte_pmd_ice.h')
new file mode 100644
@@ -0,0 +1,152 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019 Intel Corporation
+ */
+
+#ifndef _RTE_PMD_ICE_H_
+#define _RTE_PMD_ICE_H_
+
+#include <stdio.h>
+#include <rte_mbuf.h>
+#include <rte_ethdev.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum proto_xtr_type {
+ PROTO_XTR_NONE,
+ PROTO_XTR_VLAN,
+ PROTO_XTR_IPV4,
+ PROTO_XTR_IPV6,
+ PROTO_XTR_IPV6_FLOW,
+ PROTO_XTR_TCP,
+};
+
+struct proto_xtr_flds {
+ union {
+ struct {
+ uint16_t data0;
+ uint16_t data1;
+ } raw;
+ struct {
+ uint16_t stag_vid:12,
+ stag_dei:1,
+ stag_pcp:3;
+ uint16_t ctag_vid:12,
+ ctag_dei:1,
+ ctag_pcp:3;
+ } vlan;
+ struct {
+ uint16_t protocol:8,
+ ttl:8;
+ uint16_t tos:8,
+ ihl:4,
+ version:4;
+ } ipv4;
+ struct {
+ uint16_t hoplimit:8,
+ nexthdr:8;
+ uint16_t flowhi4:4,
+ tc:8,
+ version:4;
+ } ipv6;
+ struct {
+ uint16_t flowlo16;
+ uint16_t flowhi4:4,
+ tc:8,
+ version:4;
+ } ipv6_flow;
+ struct {
+ uint16_t fin:1,
+ syn:1,
+ rst:1,
+ psh:1,
+ ack:1,
+ urg:1,
+ ece:1,
+ cwr:1,
+ res1:4,
+ doff:4;
+ uint16_t rsvd;
+ } tcp;
+ } u;
+
+ uint16_t rsvd;
+
+ uint8_t type;
+
+#define PROTO_XTR_MAGIC_ID 0xCE
+ uint8_t magic;
+};
+
+static inline void
+init_proto_xtr_flds(struct rte_mbuf *mb)
+{
+ mb->udata64 = 0;
+}
+
+static inline struct proto_xtr_flds *
+get_proto_xtr_flds(struct rte_mbuf *mb)
+{
+ RTE_BUILD_BUG_ON(sizeof(struct proto_xtr_flds) > sizeof(mb->udata64));
+
+ return (struct proto_xtr_flds *)&mb->udata64;
+}
+
+static inline void
+dump_proto_xtr_flds(struct rte_mbuf *mb)
+{
+ struct proto_xtr_flds *xtr = get_proto_xtr_flds(mb);
+
+ if (xtr->magic != PROTO_XTR_MAGIC_ID || xtr->type == PROTO_XTR_NONE)
+ return;
+
+ printf(" - Protocol Extraction:[0x%04x:0x%04x],",
+ xtr->u.raw.data0, xtr->u.raw.data1);
+
+ if (xtr->type == PROTO_XTR_VLAN)
+ printf("vlan,stag=%u:%u:%u,ctag=%u:%u:%u ",
+ xtr->u.vlan.stag_pcp,
+ xtr->u.vlan.stag_dei,
+ xtr->u.vlan.stag_vid,
+ xtr->u.vlan.ctag_pcp,
+ xtr->u.vlan.ctag_dei,
+ xtr->u.vlan.ctag_vid);
+ else if (xtr->type == PROTO_XTR_IPV4)
+ printf("ipv4,ver=%u,hdrlen=%u,tos=%u,ttl=%u,proto=%u ",
+ xtr->u.ipv4.version,
+ xtr->u.ipv4.ihl,
+ xtr->u.ipv4.tos,
+ xtr->u.ipv4.ttl,
+ xtr->u.ipv4.protocol);
+ else if (xtr->type == PROTO_XTR_IPV6)
+ printf("ipv6,ver=%u,tc=%u,flow_hi4=0x%x,nexthdr=%u,hoplimit=%u ",
+ xtr->u.ipv6.version,
+ xtr->u.ipv6.tc,
+ xtr->u.ipv6.flowhi4,
+ xtr->u.ipv6.nexthdr,
+ xtr->u.ipv6.hoplimit);
+ else if (xtr->type == PROTO_XTR_IPV6_FLOW)
+ printf("ipv6_flow,ver=%u,tc=%u,flow=0x%x%04x ",
+ xtr->u.ipv6_flow.version,
+ xtr->u.ipv6_flow.tc,
+ xtr->u.ipv6_flow.flowhi4,
+ xtr->u.ipv6_flow.flowlo16);
+ else if (xtr->type == PROTO_XTR_TCP)
+ printf("tcp,doff=%u,flags=%s%s%s%s%s%s%s%s ",
+ xtr->u.tcp.doff,
+ xtr->u.tcp.cwr ? "C" : "",
+ xtr->u.tcp.ece ? "E" : "",
+ xtr->u.tcp.urg ? "U" : "",
+ xtr->u.tcp.ack ? "A" : "",
+ xtr->u.tcp.psh ? "P" : "",
+ xtr->u.tcp.rst ? "R" : "",
+ xtr->u.tcp.syn ? "S" : "",
+ xtr->u.tcp.fin ? "F" : "");
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_PMD_ICE_H_ */