From patchwork Wed Mar 29 16:41:46 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Iremonger, Bernard" X-Patchwork-Id: 22752 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 6512EFAD7; Wed, 29 Mar 2017 20:31:33 +0200 (CEST) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by dpdk.org (Postfix) with ESMTP id D532BF97A for ; Wed, 29 Mar 2017 18:42:02 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=intel.com; i=@intel.com; q=dns/txt; s=intel; t=1490805723; x=1522341723; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=HsnKnZq3ywUWzcyV7afJkfDlkXmcDquJM4OtI1iREVE=; b=CBZVdHp2L0fZ+TMrCu82WI6wLA65AZTEJNQ6wpiFqiJYcTLugo65n07t 2BBu4DJtT5q55YD3YRSpDh13pRLkww==; Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 29 Mar 2017 09:42:02 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.36,242,1486454400"; d="scan'208";a="82356443" Received: from sivswdev01.ir.intel.com (HELO localhost.localdomain) ([10.237.217.45]) by fmsmga006.fm.intel.com with ESMTP; 29 Mar 2017 09:42:00 -0700 From: Bernard Iremonger To: dev@dpdk.org, beilei.xing@intel.com, jingjing.wu@intel.com Cc: helin.zhang@intel.com, wenzhuo.lu@intel.com, Bernard Iremonger , Laura Stroe Date: Wed, 29 Mar 2017 17:41:46 +0100 Message-Id: <1490805709-11997-3-git-send-email-bernard.iremonger@intel.com> X-Mailer: git-send-email 1.7.0.7 In-Reply-To: <1490718059-380-1-git-send-email-bernard.iremonger@intel.com> References: <1490718059-380-1-git-send-email-bernard.iremonger@intel.com> Subject: [dpdk-dev] [PATCH v4 2/5] net/i40e: add QinQ filter create 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_cloud_filter_qinq_create function, and call it from i40e_dev_consistent_tunnel_filter_set function. Replace the Outer IP filter with the QinQ filter. QinQ allows multiple VLAN tags to be inserted into a single Ethernet frame. A QinQ frame is a frame that has two VLAN 802.1Q headers. 802.1Q tunneling (QinQ) is a technique often used by Metro Ethernet providers as a layer 2 VPN for customers. Signed-off-by: Laura Stroe Signed-off-by: Bernard Iremonger Acked-by: Wenzhuo Lu --- drivers/net/i40e/i40e_ethdev.c | 113 +++++++++++++++++++++++++++++++++++++++++ drivers/net/i40e/i40e_ethdev.h | 8 ++- 2 files changed, 120 insertions(+), 1 deletion(-) diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c index dafc995a1..41e0fe5f7 100644 --- a/drivers/net/i40e/i40e_ethdev.c +++ b/drivers/net/i40e/i40e_ethdev.c @@ -423,6 +423,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_cloud_filter_qinq_create(struct i40e_pf *pf); static void i40e_ethertype_filter_restore(struct i40e_pf *pf); static void i40e_tunnel_filter_restore(struct i40e_pf *pf); @@ -6709,6 +6710,9 @@ i40e_dev_get_filter_type(uint16_t filter_type, uint16_t *flag) case RTE_TUNNEL_FILTER_IMAC_IVLAN_TENID: *flag = I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN_TEN_ID; break; + case I40E_TUNNEL_FILTER_CUSTOM_QINQ: + *flag = I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ; + break; case RTE_TUNNEL_FILTER_IMAC_TENID: *flag = I40E_AQC_ADD_CLOUD_FILTER_IMAC_TEN_ID; break; @@ -7037,6 +7041,25 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf, big_buffer = 1; tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE; 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_cloud_filter_qinq_create(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."); @@ -7050,6 +7073,9 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf, else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_MPLSoGRE) pfilter->element.flags = I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE; + else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_QINQ) + pfilter->element.flags |= + I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ; else { val = i40e_dev_get_filter_type(tunnel_filter->filter_type, &pfilter->element.flags); @@ -11929,3 +11955,90 @@ rte_pmd_i40e_set_tc_strict_prio(uint8_t port, uint8_t tc_map) return ret; } + +/* 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 Field Vector 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 (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 = 1 (instead of outer IP) + * c. New_filter = 0x10 + * d. Buffer – 2 entries: + * i. Byte0 = 0x80 | 7 (valid | Stag). Byte13 = 0 (rsv) + * ii. Byte8 = 0x80 | 0x10 (valid | new l1 filter step1). Byte9-11 = 0 (rsv) + */ +static int +i40e_cloud_filter_qinq_create(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_AQC_ADD_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_OIP; + filter_replace.new_filter_type = I40E_AQC_ADD_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_AQC_ADD_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 fd1fcd4a9..03e89b5e4 100644 --- a/drivers/net/i40e/i40e_ethdev.h +++ b/drivers/net/i40e/i40e_ethdev.h @@ -1,7 +1,7 @@ /*- * BSD LICENSE * - * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. + * Copyright(c) 2010-2017 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -505,6 +505,7 @@ struct i40e_ethertype_rule { #define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD1 45 #define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP 8 #define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE 9 +#define I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ 0x10 #define I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP 0x11 #define I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE 0x12 #define I40E_AQC_ADD_L1_FILTER_TEID_MPLS 0x11 @@ -553,9 +554,14 @@ enum i40e_tunnel_type { I40E_L2_TUNNEL_TYPE_E_TAG, I40E_TUNNEL_TYPE_MPLSoUDP, I40E_TUNNEL_TYPE_MPLSoGRE, + I40E_TUNNEL_TYPE_QINQ, I40E_TUNNEL_TYPE_MAX, }; +#define ETH_TUNNEL_FILTER_OVLAN 0x40 /**< filter by outer VLAN ID */ +#define I40E_TUNNEL_FILTER_CUSTOM_QINQ (ETH_TUNNEL_FILTER_OMAC | \ + ETH_TUNNEL_FILTER_OVLAN | ETH_TUNNEL_FILTER_IVLAN) + /** * Tunneling Packet filter configuration. */