From patchwork Thu Sep 19 06:25:50 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leyi Rong X-Patchwork-Id: 59356 X-Patchwork-Delegate: xiaolong.ye@intel.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 314EC1E916; Thu, 19 Sep 2019 08:29:00 +0200 (CEST) Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by dpdk.org (Postfix) with ESMTP id EACFB1E8FA for ; Thu, 19 Sep 2019 08:28:55 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga107.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 18 Sep 2019 23:28:55 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.64,522,1559545200"; d="scan'208";a="362421961" Received: from dpdk-lrong-srv-04.sh.intel.com ([10.67.119.187]) by orsmga005.jf.intel.com with ESMTP; 18 Sep 2019 23:28:53 -0700 From: Leyi Rong To: haiyue.wang@intel.com, wenzhuo.lu@intel.com, qi.z.zhang@intel.com, xiaolong.ye@intel.com Cc: dev@dpdk.org Date: Thu, 19 Sep 2019 14:25:50 +0800 Message-Id: <20190919062553.79257-4-leyi.rong@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190919062553.79257-1-leyi.rong@intel.com> References: <20190829023421.112551-1-leyi.rong@intel.com> <20190919062553.79257-1-leyi.rong@intel.com> Subject: [dpdk-dev] [PATCH v4 3/6] net/ice: add protocol extraction support for per Rx queue X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" From: Haiyue Wang 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 --- doc/guides/nics/ice.rst | 101 +++++++++ doc/guides/rel_notes/release_19_11.rst | 4 + drivers/net/ice/Makefile | 3 + drivers/net/ice/ice_ethdev.c | 301 +++++++++++++++++++++++++ drivers/net/ice/ice_ethdev.h | 4 + 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 +++++++++++++ 10 files changed, 633 insertions(+) create mode 100644 drivers/net/ice/rte_pmd_ice.h diff --git a/doc/guides/nics/ice.rst b/doc/guides/nics/ice.rst index 03819d29f..8a6f60e71 100644 --- a/doc/guides/nics/ice.rst +++ b/doc/guides/nics/ice.rst @@ -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=[...] + -w 18:00.0,proto_xtr= + + 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 ------------------------------ diff --git a/doc/guides/rel_notes/release_19_11.rst b/doc/guides/rel_notes/release_19_11.rst index 8490d897c..382806229 100644 --- a/doc/guides/rel_notes/release_19_11.rst +++ b/doc/guides/rel_notes/release_19_11.rst @@ -21,6 +21,10 @@ DPDK Release 19.11 xdg-open build/doc/html/guides/rel_notes/release_19_11.html +* **Updated the ICE driver.** + + * Added support for handling Receive Flex Descriptor. + * Added support for protocol extraction on per Rx queue. New Features ------------ diff --git a/drivers/net/ice/Makefile b/drivers/net/ice/Makefile index ae53c2646..4a279f196 100644 --- a/drivers/net/ice/Makefile +++ b/drivers/net/ice/Makefile @@ -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 diff --git a/drivers/net/ice/ice_ethdev.c b/drivers/net/ice/ice_ethdev.c index 44a14cb8a..7c74b6169 100644 --- a/drivers/net/ice/ice_ethdev.c +++ b/drivers/net/ice/ice_ethdev.c @@ -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,280 @@ 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 != '(') + 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 - */ + 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; + + memset(devargs->proto_xtr, xtr_type, + sizeof(devargs->proto_xtr)); + + 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 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 +1355,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 +1366,16 @@ 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) + rte_memcpy(pf->proto_xtr, ad->devargs.proto_xtr, + RTE_MIN((size_t)pf->lan_nb_qps, + sizeof(ad->devargs.proto_xtr))); + else + PMD_DRV_LOG(NOTICE, "Protocol extraction is disabled"); + return 0; } @@ -1378,9 +1666,18 @@ static int ice_parse_devargs(struct rte_eth_dev *dev) return -EINVAL; } + memset(ad->devargs.proto_xtr, PROTO_XTR_NONE, + sizeof(ad->devargs.proto_xtr)); + + ret = rte_kvargs_process(kvlist, ICE_PROTO_XTR_ARG, + &handle_proto_xtr_arg, &ad->devargs); + if (ret) + goto bail; + ret = rte_kvargs_process(kvlist, ICE_SAFE_MODE_SUPPORT_ARG, &parse_bool, &ad->devargs.safe_mode_support); +bail: rte_kvargs_free(kvlist); return ret; } @@ -1547,6 +1844,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 +1970,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 +4095,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:]" 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..adbb66322 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,14 @@ 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[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 +#include +#include + +#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_ */