From patchwork Fri Mar 3 14:48:09 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Iremonger, Bernard" X-Patchwork-Id: 21329 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [IPv6:::1]) by dpdk.org (Postfix) with ESMTP id 927E36CD4; Fri, 3 Mar 2017 15:48:41 +0100 (CET) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by dpdk.org (Postfix) with ESMTP id 0FC402B94 for ; Fri, 3 Mar 2017 15:48:21 +0100 (CET) Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga101.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 03 Mar 2017 06:48:21 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.35,237,1484035200"; d="scan'208";a="55508475" Received: from sivswdev01.ir.intel.com (HELO localhost.localdomain) ([10.237.217.45]) by orsmga002.jf.intel.com with ESMTP; 03 Mar 2017 06:48:20 -0800 From: Bernard Iremonger To: dev@dpdk.org, beilei.xing@intel.com, jingjing.wu@intel.com Cc: helin.zhang@intel.com, Bernard Iremonger , Laura Stroe Date: Fri, 3 Mar 2017 14:48:09 +0000 Message-Id: <1488552491-20432-3-git-send-email-bernard.iremonger@intel.com> X-Mailer: git-send-email 1.7.0.7 In-Reply-To: <1488552491-20432-1-git-send-email-bernard.iremonger@intel.com> References: <1488552491-20432-1-git-send-email-bernard.iremonger@intel.com> Subject: [dpdk-dev] [PATCH v1 2/4] net/i40e: add QinQ wrapper function 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" add i40e_dev_cloud_filter_qinq function. Signed-off-by: Laura Stroe Signed-off-by: Bernard Iremonger --- drivers/net/i40e/i40e_ethdev.c | 116 +++++++++++++++++++++++++++++++++++++++-- drivers/net/i40e/i40e_ethdev.h | 25 +++++++++ 2 files changed, 137 insertions(+), 4 deletions(-) diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c index 91bfd73..744b4ac 100644 --- a/drivers/net/i40e/i40e_ethdev.c +++ b/drivers/net/i40e/i40e_ethdev.c @@ -243,6 +243,8 @@ /* Bit mask of Extended Tag enable/disable */ #define PCI_DEV_CTRL_EXT_TAG_MASK (1 << PCI_DEV_CTRL_EXT_TAG_SHIFT) +#define I40E_CLOUD_FILTER_CUSTOM_QINQ 0x10 + static int eth_i40e_dev_init(struct rte_eth_dev *eth_dev); static int eth_i40e_dev_uninit(struct rte_eth_dev *eth_dev); static int i40e_dev_configure(struct rte_eth_dev *dev); @@ -414,6 +416,7 @@ static int i40e_tunnel_filter_convert( struct i40e_tunnel_filter *tunnel_filter); static int i40e_sw_tunnel_filter_insert(struct i40e_pf *pf, struct i40e_tunnel_filter *tunnel_filter); +static int i40e_dev_cloud_filter_qinq(struct i40e_pf *pf); static void i40e_ethertype_filter_restore(struct i40e_pf *pf); static void i40e_tunnel_filter_restore(struct i40e_pf *pf); @@ -6672,16 +6675,19 @@ static int i40e_dev_get_filter_type(uint16_t filter_type, uint16_t *flag) { switch (filter_type) { - case RTE_TUNNEL_FILTER_IMAC_IVLAN: + case I40E_TUNNEL_FILTER_IMAC_IVLAN: *flag = I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN; break; - case RTE_TUNNEL_FILTER_IMAC_IVLAN_TENID: + case I40E_TUNNEL_FILTER_IMAC_IVLAN_TENID: *flag = I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN_TEN_ID; break; - case RTE_TUNNEL_FILTER_IMAC_TENID: + case I40E_TUNNEL_FILTER_CUSTOM_QINQ: + *flag = I40E_CLOUD_FILTER_CUSTOM_QINQ; + break; + case I40E_TUNNEL_FILTER_IMAC_TENID: *flag = I40E_AQC_ADD_CLOUD_FILTER_IMAC_TEN_ID; break; - case RTE_TUNNEL_FILTER_OMAC_TENID_IMAC: + case I40E_TUNNEL_FILTER_OMAC_TENID_IMAC: *flag = I40E_AQC_ADD_CLOUD_FILTER_OMAC_TEN_ID_IMAC; break; case ETH_TUNNEL_FILTER_IMAC: @@ -6989,6 +6995,24 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf, case I40E_TUNNEL_TYPE_IP_IN_GRE: tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_IP; break; + case I40E_TUNNEL_TYPE_QINQ: + if (tunnel_filter->filter_type == I40E_TUNNEL_FILTER_CUSTOM_QINQ) { + PMD_DRV_LOG(INFO, "Replace a tunnel filter."); + ret = i40e_dev_cloud_filter_qinq(pf); + if (ret < 0) { + PMD_DRV_LOG(ERR, "Failed to replace a tunnel filter."); + return ret; + } + /* Add in the General fields the values of + * the Outer and Inner VLAN + * Big Buffer should be set, see changes in + * i40e_aq_add_cloud_filters + */ + pfilter->general_fields[0] = tunnel_filter->inner_vlan; + pfilter->general_fields[1] = tunnel_filter->outer_vlan; + big_buffer = 1; + } + break; default: /* Other tunnel types is not supported. */ PMD_DRV_LOG(ERR, "tunnel type is not supported."); @@ -11383,3 +11407,87 @@ rte_pmd_i40e_reset_vf_stats(uint8_t port, return 0; } + +/* Create a QinQ cloud filter + * + * The Fortville NIC has limited resources for tunnel filters, + * so we can only reuse existing filters. + * In step 1 we define which fields can be used for filter types. + * As we do not have the inner tag defined as a field, + * we have to define it first, by reusing one of L1 entries. + * In step 2 we are replacing one of existing filter types with + * a new one for QinQ. + * As we reusing L1 and replacing L2, some of the default filter + * types will disappear,which depends on L1 and L2 entries we reuse. + * + * Step 1: Create L1 filter of outer vlan (12b) + inner vlan (12b) + * + * 1. Create L1 filter of outer vlan (12b) which will be in use + * later when we define the cloud filter. + * a. Valid_flags.replace_cloud = 0 + * b. Old_filter = 10 ( instead of stag-inner vlan) + * c. New_filter = 0x10 + * d. TR bit = 0xff (optional, not used here) + * e. Buffer – 2 entries: + * i. Byte0= 8 (outer vlan FV index). Byte1=0 (rsv) Byte 2-3 = 0x0fff + * ii. Byte0= 37 (inner vlan FV index). Byte1=0 (rsv) Byte 2-3 = 0x0fff + * + * Step 2: + * 2. Create cloud filter using two L1 filters entries: stag and + * new filter(outer vlan+ inner vlan) + * a. Valid_flags.replace_cloud = 1 + * b. Old_filter = 3 ( instead of inner-mac,inner vlan) + * c. New_filter = 0x10 + * d. Buffer – 2 entries: + * i. Byte0= 0x80 | 7 (valid | Stag). Byte1-3=0 (rsv) + * ii. Byte8= 0x80 | 0x10 (valid | new l1 filter step1). Byte9-11=0 (rsv) + */ +static int +i40e_dev_cloud_filter_qinq(struct i40e_pf *pf) +{ + int ret = -ENOTSUP; + struct i40e_aqc_replace_cloud_filters_cmd filter_replace; + struct i40e_aqc_replace_cloud_filters_cmd_buf filter_replace_buf; + struct i40e_hw *hw = I40E_PF_TO_HW(pf); + + /* Init */ + memset(&filter_replace, 0, sizeof(struct i40e_aqc_replace_cloud_filters_cmd)); + memset(&filter_replace_buf, 0, sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf)); + + /* create L1 filter */ + filter_replace.old_filter_type = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG_IVLAN; + filter_replace.new_filter_type = I40E_CLOUD_FILTER_CUSTOM_QINQ; + filter_replace.tr_bit = 0xff; /* tr_bit is not used */ + + /* Prepare the buffer, 2 entries */ + filter_replace_buf.data[0] = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_VLAN; + filter_replace_buf.data[0] |= I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED; + /* Field Vector 12b mask */ + filter_replace_buf.data[2] = 0xff; + filter_replace_buf.data[3] = 0x0f; + filter_replace_buf.data[4] = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_INNER_VLAN; + filter_replace_buf.data[4] |= I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED; + /* Field Vector 12b mask */ + filter_replace_buf.data[6] = 0xff; + filter_replace_buf.data[7] = 0x0f; + ret = i40e_aq_replace_cloud_filters(hw, &filter_replace, &filter_replace_buf); + if (ret != I40E_SUCCESS) + return ret; + + /* Apply the second L2 cloud filter */ + memset(&filter_replace, 0, sizeof(struct i40e_aqc_replace_cloud_filters_cmd)); + memset(&filter_replace_buf, 0, sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf)); + + /* create L2 filter, input for L2 filter will be L1 filter */ + filter_replace.valid_flags = I40E_AQC_REPLACE_CLOUD_FILTER; + filter_replace.old_filter_type = I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN; + filter_replace.new_filter_type = I40E_CLOUD_FILTER_CUSTOM_QINQ; + + /* Prepare the buffer, 2 entries */ + filter_replace_buf.data[0] = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG; + filter_replace_buf.data[0] |= I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED; + filter_replace_buf.data[4] = I40E_CLOUD_FILTER_CUSTOM_QINQ; + filter_replace_buf.data[4] |= I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED; + ret = i40e_aq_replace_cloud_filters(hw, &filter_replace, &filter_replace_buf); + return ret; +} diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h index 3e9b129..54fbc4c 100644 --- a/drivers/net/i40e/i40e_ethdev.h +++ b/drivers/net/i40e/i40e_ethdev.h @@ -541,10 +541,35 @@ enum i40e_tunnel_type { I40E_TUNNEL_TYPE_NVGRE, I40E_TUNNEL_TYPE_IP_IN_GRE, I40E_L2_TUNNEL_TYPE_E_TAG, + I40E_TUNNEL_TYPE_QINQ, I40E_TUNNEL_TYPE_MAX, }; /** + * filter type of tunneling packet + */ +#define ETH_TUNNEL_FILTER_OMAC 0x01 /**< filter by outer MAC addr */ +#define ETH_TUNNEL_FILTER_OIP 0x02 /**< filter by outer IP Addr */ +#define ETH_TUNNEL_FILTER_TENID 0x04 /**< filter by tenant ID */ +#define ETH_TUNNEL_FILTER_IMAC 0x08 /**< filter by inner MAC addr */ +#define ETH_TUNNEL_FILTER_IVLAN 0x10 /**< filter by inner VLAN ID */ +#define ETH_TUNNEL_FILTER_IIP 0x20 /**< filter by inner IP addr */ +#define ETH_TUNNEL_FILTER_OVLAN 0x40 /**< filter by outer VLAN ID */ + +#define I40E_TUNNEL_FILTER_IMAC_IVLAN (ETH_TUNNEL_FILTER_IMAC | \ + ETH_TUNNEL_FILTER_IVLAN) +#define I40E_TUNNEL_FILTER_IMAC_IVLAN_TENID (ETH_TUNNEL_FILTER_IMAC | \ + ETH_TUNNEL_FILTER_IVLAN | \ + ETH_TUNNEL_FILTER_TENID) +#define I40E_TUNNEL_FILTER_IMAC_TENID (ETH_TUNNEL_FILTER_IMAC | \ + ETH_TUNNEL_FILTER_TENID) +#define I40E_TUNNEL_FILTER_OMAC_TENID_IMAC (ETH_TUNNEL_FILTER_OMAC | \ + ETH_TUNNEL_FILTER_TENID | \ + ETH_TUNNEL_FILTER_IMAC) +#define I40E_TUNNEL_FILTER_CUSTOM_QINQ (ETH_TUNNEL_FILTER_OMAC | \ + ETH_TUNNEL_FILTER_OVLAN | ETH_TUNNEL_FILTER_IVLAN) + +/** * Tunneling Packet filter configuration. */ struct i40e_tunnel_filter_conf {