From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.7 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id CB26EC43613 for ; Thu, 20 Jun 2019 09:32:35 +0000 (UTC) Received: from dpdk.org (dpdk.org [92.243.14.124]) by mail.kernel.org (Postfix) with ESMTP id 3A89B2082C for ; Thu, 20 Jun 2019 09:32:35 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 3A89B2082C Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=intel.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=dev-bounces@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id AF6231D04B; Thu, 20 Jun 2019 11:32:33 +0200 (CEST) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by dpdk.org (Postfix) with ESMTP id 2ADBA1D049 for ; Thu, 20 Jun 2019 11:32:31 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by fmsmga101.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 20 Jun 2019 02:32:31 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.63,396,1557212400"; d="scan'208";a="358476461" Received: from fmsmsx107.amr.corp.intel.com ([10.18.124.205]) by fmsmga005.fm.intel.com with ESMTP; 20 Jun 2019 02:32:31 -0700 Received: from shsmsx153.ccr.corp.intel.com (10.239.6.53) by fmsmsx107.amr.corp.intel.com (10.18.124.205) with Microsoft SMTP Server (TLS) id 14.3.439.0; Thu, 20 Jun 2019 02:32:31 -0700 Received: from shsmsx106.ccr.corp.intel.com ([169.254.10.89]) by SHSMSX153.ccr.corp.intel.com ([169.254.12.76]) with mapi id 14.03.0439.000; Thu, 20 Jun 2019 17:32:29 +0800 From: "Wang, Xiao W" To: "Yang, Qiming" , "dev@dpdk.org" CC: "Zhang, Qi Z" , "Xing, Beilei" Thread-Topic: [dpdk-dev] [PATCH v3 2/3] net/ice: add generic flow API Thread-Index: AQHVJypxllf3MPXjgEmdman3U5/feaakOwJA Date: Thu, 20 Jun 2019 09:32:28 +0000 Message-ID: References: <1559552722-8970-1-git-send-email-qiming.yang@intel.com> <20190620053449.32959-1-qiming.yang@intel.com> <20190620053449.32959-3-qiming.yang@intel.com> In-Reply-To: <20190620053449.32959-3-qiming.yang@intel.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ctpclassification: CTP_NT x-titus-metadata-40: eyJDYXRlZ29yeUxhYmVscyI6IiIsIk1ldGFkYXRhIjp7Im5zIjoiaHR0cDpcL1wvd3d3LnRpdHVzLmNvbVwvbnNcL0ludGVsMyIsImlkIjoiMGU3MDgwMDMtNmFhZC00MjQ1LWFjOTAtMjBkZjQ4NDc4NGQxIiwicHJvcHMiOlt7Im4iOiJDVFBDbGFzc2lmaWNhdGlvbiIsInZhbHMiOlt7InZhbHVlIjoiQ1RQX05UIn1dfV19LCJTdWJqZWN0TGFiZWxzIjpbXSwiVE1DVmVyc2lvbiI6IjE3LjEwLjE4MDQuNDkiLCJUcnVzdGVkTGFiZWxIYXNoIjoielBrblFaODliU0F2S3Y4b3RNNlNmdnIxc0hiUFJHVU5mV3RvSE5lQXNZdTNwMDFMUUFVSnh1VFwvUWVNaVg5M1kifQ== dlp-product: dlpe-windows dlp-version: 11.2.0.6 dlp-reaction: no-action x-originating-ip: [10.239.127.40] Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Subject: Re: [dpdk-dev] [PATCH v3 2/3] net/ice: add generic flow API 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" Hi, > -----Original Message----- > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Qiming Yang > Sent: Thursday, June 20, 2019 1:35 PM > To: dev@dpdk.org > Cc: Yang, Qiming > Subject: [dpdk-dev] [PATCH v3 2/3] net/ice: add generic flow API >=20 > This patch adds ice_flow_create, ice_flow_destroy, > ice_flow_flush and ice_flow_validate support, > these are used to handle all the generic filters. >=20 > Signed-off-by: Qiming Yang > --- > drivers/net/ice/Makefile | 1 + > drivers/net/ice/ice_ethdev.c | 44 +++ > drivers/net/ice/ice_ethdev.h | 5 + > drivers/net/ice/ice_generic_flow.c | 682 > +++++++++++++++++++++++++++++++++++++ > drivers/net/ice/ice_generic_flow.h | 654 > +++++++++++++++++++++++++++++++++++ > drivers/net/ice/meson.build | 1 + > 6 files changed, 1387 insertions(+) > create mode 100644 drivers/net/ice/ice_generic_flow.c > create mode 100644 drivers/net/ice/ice_generic_flow.h >=20 > diff --git a/drivers/net/ice/Makefile b/drivers/net/ice/Makefile > index b10d826..32abeb6 100644 > --- a/drivers/net/ice/Makefile > +++ b/drivers/net/ice/Makefile > @@ -79,5 +79,6 @@ endif > ifeq ($(CC_AVX2_SUPPORT), 1) > SRCS-$(CONFIG_RTE_LIBRTE_ICE_PMD) +=3D ice_rxtx_vec_avx2.c > endif > +SRCS-$(CONFIG_RTE_LIBRTE_ICE_PMD) +=3D ice_generic_flow.c >=20 > include $(RTE_SDK)/mk/rte.lib.mk > diff --git a/drivers/net/ice/ice_ethdev.c b/drivers/net/ice/ice_ethdev.c > index a94aa7e..8ee06d1 100644 > --- a/drivers/net/ice/ice_ethdev.c > +++ b/drivers/net/ice/ice_ethdev.c > @@ -15,6 +15,7 @@ > #include "base/ice_dcb.h" > #include "ice_ethdev.h" > #include "ice_rxtx.h" > +#include "ice_switch_filter.h" >=20 > #define ICE_MAX_QP_NUM "max_queue_pair_num" > #define ICE_DFLT_OUTER_TAG_TYPE ICE_AQ_VSI_OUTER_TAG_VLAN_9100 > @@ -83,6 +84,10 @@ static int ice_xstats_get(struct rte_eth_dev *dev, > static int ice_xstats_get_names(struct rte_eth_dev *dev, > struct rte_eth_xstat_name *xstats_names, > unsigned int limit); > +static int ice_dev_filter_ctrl(struct rte_eth_dev *dev, > + enum rte_filter_type filter_type, > + enum rte_filter_op filter_op, > + void *arg); >=20 > static const struct rte_pci_id pci_id_ice_map[] =3D { > { RTE_PCI_DEVICE(ICE_INTEL_VENDOR_ID, > ICE_DEV_ID_E810C_BACKPLANE) }, > @@ -141,6 +146,7 @@ static const struct eth_dev_ops ice_eth_dev_ops =3D { > .xstats_get =3D ice_xstats_get, > .xstats_get_names =3D ice_xstats_get_names, > .xstats_reset =3D ice_stats_reset, > + .filter_ctrl =3D ice_dev_filter_ctrl, > }; >=20 > /* store statistics names and its offset in stats structure */ > @@ -1478,6 +1484,8 @@ ice_dev_init(struct rte_eth_dev *dev) > /* get base queue pairs index in the device */ > ice_base_queue_get(pf); >=20 > + TAILQ_INIT(&pf->flow_list); > + > return 0; >=20 > err_pf_setup: > @@ -1620,6 +1628,8 @@ ice_dev_uninit(struct rte_eth_dev *dev) > { > struct rte_pci_device *pci_dev =3D RTE_ETH_DEV_TO_PCI(dev); > struct rte_intr_handle *intr_handle =3D &pci_dev->intr_handle; > + struct ice_pf *pf =3D ICE_DEV_PRIVATE_TO_PF(dev->data->dev_private); > + struct rte_flow *p_flow; >=20 > ice_dev_close(dev); >=20 > @@ -1637,6 +1647,13 @@ ice_dev_uninit(struct rte_eth_dev *dev) > rte_intr_callback_unregister(intr_handle, > ice_interrupt_handler, dev); >=20 > + /* Remove all flows */ > + while ((p_flow =3D TAILQ_FIRST(&pf->flow_list))) { > + TAILQ_REMOVE(&pf->flow_list, p_flow, node); > + ice_free_switch_filter_rule(p_flow->rule); > + rte_free(p_flow); > + } > + > return 0; > } >=20 > @@ -3622,6 +3639,33 @@ static int ice_xstats_get_names(__rte_unused > struct rte_eth_dev *dev, > } >=20 > static int > +ice_dev_filter_ctrl(struct rte_eth_dev *dev, > + enum rte_filter_type filter_type, > + enum rte_filter_op filter_op, > + void *arg) > +{ > + int ret =3D 0; > + > + if (!dev) > + return -EINVAL; > + > + switch (filter_type) { > + case RTE_ETH_FILTER_GENERIC: > + if (filter_op !=3D RTE_ETH_FILTER_GET) > + return -EINVAL; > + *(const void **)arg =3D &ice_flow_ops; > + break; > + default: > + PMD_DRV_LOG(WARNING, "Filter type (%d) not supported", > + filter_type); > + ret =3D -EINVAL; > + break; > + } > + > + return ret; > +} > + > +static int > ice_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, > struct rte_pci_device *pci_dev) > { > diff --git a/drivers/net/ice/ice_ethdev.h b/drivers/net/ice/ice_ethdev.h > index 50b966c..8a52239 100644 > --- a/drivers/net/ice/ice_ethdev.h > +++ b/drivers/net/ice/ice_ethdev.h > @@ -234,12 +234,16 @@ struct ice_vsi { > bool offset_loaded; > }; >=20 > +extern const struct rte_flow_ops ice_flow_ops; > + > /* Struct to store flow created. */ > struct rte_flow { > TAILQ_ENTRY(rte_flow) node; > void *rule; > }; >=20 > +TAILQ_HEAD(ice_flow_list, rte_flow); > + > struct ice_pf { > struct ice_adapter *adapter; /* The adapter this PF associate to */ > struct ice_vsi *main_vsi; /* pointer to main VSI structure */ > @@ -266,6 +270,7 @@ struct ice_pf { > struct ice_eth_stats internal_stats; > bool offset_loaded; > bool adapter_stopped; > + struct ice_flow_list flow_list; > }; >=20 > /** > diff --git a/drivers/net/ice/ice_generic_flow.c > b/drivers/net/ice/ice_generic_flow.c > new file mode 100644 > index 0000000..c6fce88 > --- /dev/null > +++ b/drivers/net/ice/ice_generic_flow.c > @@ -0,0 +1,682 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(c) 2019 Intel Corporation > + */ > + > +#include > +#include > +#include > +#include > +#include [...] > + /* Find a void item */ > + pe =3D ice_find_first_item(pb + 1, true); > + > + cpy_count =3D pe - pb; > + rte_memcpy(items, pb, sizeof(struct rte_flow_item) * > cpy_count); > + > + items +=3D cpy_count; > + > + if (pe->type =3D=3D RTE_FLOW_ITEM_TYPE_END) { > + pb =3D pe; No need to "pb =3D pe". > + break; > + } > + > + pb =3D pe + 1; > + } > + /* Copy the END item. */ > + rte_memcpy(items, pe, sizeof(struct rte_flow_item)); > +} > + > +/* Check if the pattern matches a supported item type array */ > +static bool > +ice_match_pattern(enum rte_flow_item_type *item_array, > + const struct rte_flow_item *pattern) > +{ > + const struct rte_flow_item *item =3D pattern; > + > + while ((*item_array =3D=3D item->type) && [...] > + if (icmp6_mask->code || > + icmp6_mask->checksum) { > + rte_flow_error_set(error, EINVAL, > + > RTE_FLOW_ERROR_TYPE_ITEM, > + item, > + "Invalid ICMP6 mask"); > + return 0; > + } > + > + if (icmp6_mask->type =3D=3D UINT8_MAX) > + input_set |=3D ICE_INSET_ICMP6; Indent. > + break; > + case RTE_FLOW_ITEM_TYPE_VXLAN: > + vxlan_spec =3D item->spec; > + vxlan_mask =3D item->mask; > + /* Check if VXLAN item is used to describe protocol. > + * If yes, both spec and mask should be NULL. > + * If no, both spec and mask shouldn't be NULL. > + */ > + if ((!vxlan_spec && vxlan_mask) || > + (vxlan_spec && !vxlan_mask)) { > + rte_flow_error_set(error, EINVAL, > + RTE_FLOW_ERROR_TYPE_ITEM, > + item, > + "Invalid VXLAN item"); > + return -rte_errno; I think you need to return 0 as above, since the caller will check (!field)= . > + } > + > + break; > + case RTE_FLOW_ITEM_TYPE_NVGRE: > + nvgre_spec =3D item->spec; > + nvgre_mask =3D item->mask; > + /* Check if VXLAN item is used to describe protocol. Typo: VXLAN->NVGRE > + * If yes, both spec and mask should be NULL. > + * If no, both spec and mask shouldn't be NULL. > + */ > + if ((!nvgre_spec && nvgre_mask) || > + (nvgre_spec && !nvgre_mask)) { > + rte_flow_error_set(error, EINVAL, > + RTE_FLOW_ERROR_TYPE_ITEM, > + item, > + "Invalid VXLAN item"); > + return -rte_errno; Ditto. > + } > + > + break; > + default: > + rte_flow_error_set(error, EINVAL, > + RTE_FLOW_ERROR_TYPE_ITEM, > + item, > + "Invalid mask no exist"); > + break; > + } > + } > + return input_set; > +} > + > +static int ice_flow_valid_inset(const struct rte_flow_item pattern[], > + uint64_t inset, struct rte_flow_error *error) > +{ > + uint64_t fields; > + > + /* get valid field */ > + fields =3D ice_get_flow_field(pattern, error); > + if ((!fields) || (fields && (!inset))) { Maybe the intention is to : fields & (~inset), checking if the user's input= set exceeds support scope. > + rte_flow_error_set(error, EINVAL, > + RTE_FLOW_ERROR_TYPE_ITEM_SPEC, > + pattern, > + "Invalid input set"); > + return -rte_errno; > + } > + > + return 0; > +} > + > +static int ice_flow_valid_action(const struct rte_flow_action *actions, > + struct rte_flow_error *error) > +{ > + switch (actions->type) { > + case RTE_FLOW_ACTION_TYPE_QUEUE: > + break; > + case RTE_FLOW_ACTION_TYPE_DROP: > + break; > + default: [...] > + RTE_FLOW_ERROR_TYPE_HANDLE, NULL, > + "Failed to allocate memory"); > + return flow; > + } > + > + ret =3D ice_flow_validate(dev, attr, pattern, actions, error); > + if (ret < 0) > + return NULL; Goto free_flow BRs, Xiao > + > + ret =3D ice_create_switch_filter(pf, pattern, actions, flow, error); > + if (ret) > + goto free_flow; > + > + TAILQ_INSERT_TAIL(&pf->flow_list, flow, node); > + return flow; > + > +free_flow: > + rte_flow_error_set(error, -ret, > + RTE_FLOW_ERROR_TYPE_HANDLE, NULL, > + "Failed to create flow."); > + rte_free(flow); > + return NULL; > +} > + > +static int > +ice_flow_destroy(struct rte_eth_dev *dev, > + struct rte_flow *flow, > + struct rte_flow_error *error) > +{ > + struct ice_pf *pf =3D ICE_DEV_PRIVATE_TO_PF(dev->data->dev_private); > + int ret =3D 0; > + > + ret =3D ice_destroy_switch_filter(pf, flow, error); > + > + if (!ret) { > + TAILQ_REMOVE(&pf->flow_list, flow, node); > + rte_free(flow); > + } else > + rte_flow_error_set(error, -ret, > + RTE_FLOW_ERROR_TYPE_HANDLE, NULL, > + "Failed to destroy flow."); > + > + return ret; > +} > + > +static int > +ice_flow_flush(struct rte_eth_dev *dev, > + struct rte_flow_error *error) > +{ > + struct ice_pf *pf =3D ICE_DEV_PRIVATE_TO_PF(dev->data->dev_private); > + struct rte_flow *p_flow; > + int ret; > + > + TAILQ_FOREACH(p_flow, &pf->flow_list, node) { > + ret =3D ice_flow_destroy(dev, p_flow, error); > + if (ret) { > + rte_flow_error_set(error, -ret, > + RTE_FLOW_ERROR_TYPE_HANDLE, > NULL, > + "Failed to flush SW flows."); > + return -rte_errno; > + } > + } > + > + return ret; > +} > diff --git a/drivers/net/ice/ice_generic_flow.h > b/drivers/net/ice/ice_generic_flow.h > new file mode 100644 > index 0000000..ed7f3fe