From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by dpdk.org (Postfix) with ESMTP id 0B6694C6E for ; Tue, 27 May 2014 09:59:56 +0200 (CEST) Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga101.jf.intel.com with ESMTP; 27 May 2014 00:59:57 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.98,917,1392192000"; d="scan'208";a="546983217" Received: from fmsmsx106.amr.corp.intel.com ([10.19.9.37]) by orsmga002.jf.intel.com with ESMTP; 27 May 2014 00:59:33 -0700 Received: from fmsmsx116.amr.corp.intel.com (10.18.116.20) by FMSMSX106.amr.corp.intel.com (10.19.9.37) with Microsoft SMTP Server (TLS) id 14.3.123.3; Tue, 27 May 2014 00:59:33 -0700 Received: from shsmsx102.ccr.corp.intel.com (10.239.4.154) by fmsmsx116.amr.corp.intel.com (10.18.116.20) with Microsoft SMTP Server (TLS) id 14.3.123.3; Tue, 27 May 2014 00:59:33 -0700 Received: from shsmsx104.ccr.corp.intel.com ([169.254.5.192]) by shsmsx102.ccr.corp.intel.com ([169.254.2.190]) with mapi id 14.03.0123.003; Tue, 27 May 2014 15:59:31 +0800 From: "Ming, LiX" To: "Wu, Jingjing" , "dev@dpdk.org" Thread-Topic: [dpdk-dev] [PATCH v2 2/4]e1000: add igb NIC filters of generic filter feature Thread-Index: AQHPdvDTIWXIewxUkUaAuOukTl6ziJtUFOHA Date: Tue, 27 May 2014 07:59:30 +0000 Message-ID: <0976FC66838DDE4585886952506C9436FBA62F@SHSMSX104.ccr.corp.intel.com> References: <1400895442-32433-1-git-send-email-jingjing.wu@intel.com> <1400895442-32433-3-git-send-email-jingjing.wu@intel.com> In-Reply-To: <1400895442-32433-3-git-send-email-jingjing.wu@intel.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-cr-hashedpuzzle: om8= 2nE= AE6A BOxb BvBl BwnT Ct7Y C5mI DqcR D3Jh ETLF EzPG E23S H8yY KPmR KlJ/; 1; ZABlAHYAQABkAHAAZABrAC4AbwByAGcA; Sosha1_v1; 7; {9C006C8A-1B1F-4917-B086-77815FBA0EF2}; bABpAHgALgBtAGkAbgBnAEAAaQBuAHQAZQBsAC4AYwBvAG0A; Tue, 27 May 2014 07:59:28 GMT; UgBFADoAIABbAGQAcABkAGsALQBkAGUAdgBdACAAWwBQAEEAVABDAEgAIAB2ADIAIAAyAC8ANABdAGUAMQAwADAAMAA6ACAAYQBkAGQAIABpAGcAYgAgAE4ASQBDACAAZgBpAGwAdABlAHIAcwAgAG8AZgAgAGcAZQBuAGUAcgBpAGMACQBmAGkAbAB0AGUAcgAgAGYAZQBhAHQAdQByAGUA x-cr-puzzleid: {9C006C8A-1B1F-4917-B086-77815FBA0EF2} 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 v2 2/4]e1000: add igb NIC filters of generic filter feature X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 27 May 2014 07:59:58 -0000 This patch adds following igb NIC filters implement: syn filter, ethertype filter, 2tuple filter, flex filter for intel NIC 82= 580 and i350 syn filter, ethertype filter, 5tuple filter for intel NIC 82576 Signed-off-by: jingjing.wu --- lib/librte_pmd_e1000/e1000_ethdev.h | 53 +++ lib/librte_pmd_e1000/igb_ethdev.c | 745 ++++++++++++++++++++++++++++++++= ++++ 2 files changed, 798 insertions(+) Test-by: lmingX lix,ming@intel.com Compile pass >>Compile OS: FC20 x86_64 >>Kernel version: 3.11.10-301 >>GCC version: 4.8.2 >>Server: Crownpass diff --git a/lib/librte_pmd_e1000/e1000_ethdev.h b/lib/librte_pmd_e1000/e10= 00_ethdev.h index d09064e..239e849 100644 --- a/lib/librte_pmd_e1000/e1000_ethdev.h +++ b/lib/librte_pmd_e1000/e1000_ethdev.h @@ -52,6 +52,59 @@ #define E1000_CTRL_EXT_EXTEND_VLAN (1<<26) /* EXTENDED VLAN */ #define IGB_VFTA_SIZE 128 =20 +#define IGB_MAX_RX_QUEUE_NUM 8 +#define IGB_MAX_RX_QUEUE_NUM_82576 16 + +#define E1000_SYN_FILTER_ENABLE 0x00000001 /** syn filter enable fi= eld*/ +#define E1000_SYN_FILTER_QUEUE 0x0000000E /** syn filter queue fie= ld*/ +#define E1000_SYN_FILTER_QUEUE_SHIFT 1 /** syn filter queue field*/ +#define E1000_RFCTL_SYNQFP 0x00080000 /** SYNQFP in RFCTL regi= ster*/ + +#define E1000_ETQF_ETHERTYPE 0x0000FFFF +#define E1000_ETQF_QUEUE 0x00070000 +#define E1000_ETQF_QUEUE_SHIFT 16 +#define E1000_MAX_ETQF_FILTERS 8 + +#define E1000_IMIR_DSTPORT 0x0000FFFF +#define E1000_IMIR_PRIORITY 0xE0000000 +#define E1000_IMIR_EXT_SIZE_BP 0x00001000 +#define E1000_IMIR_EXT_CTRL_UGR 0x00002000 +#define E1000_IMIR_EXT_CTRL_ACK 0x00004000 +#define E1000_IMIR_EXT_CTRL_PSH 0x00008000 +#define E1000_IMIR_EXT_CTRL_RST 0x00010000 +#define E1000_IMIR_EXT_CTRL_SYN 0x00020000 +#define E1000_IMIR_EXT_CTRL_FIN 0x00040000 +#define E1000_IMIR_EXT_CTRL_BP 0x00080000 +#define E1000_MAX_TTQF_FILTERS 8 +#define E1000_2TUPLE_MAX_PRI 7 + +#define E1000_MAX_FLEXIBLE_FILTERS 8 +#define E1000_MAX_FHFT 4 +#define E1000_MAX_FHFT_EXT 4 +#define E1000_MAX_FLEX_FILTER_PRI 7 +#define E1000_MAX_FLEX_FILTER_LEN 128 +#define E1000_FHFT_QUEUEING_LEN 0x0000007F +#define E1000_FHFT_QUEUEING_QUEUE 0x00000700 +#define E1000_FHFT_QUEUEING_PRIO 0x00070000 +#define E1000_FHFT_QUEUEING_OFFSET 0xFC +#define E1000_FHFT_QUEUEING_QUEUE_SHIFT 8 +#define E1000_FHFT_QUEUEING_PRIO_SHIFT 16 +#define E1000_WUFC_FLEX_HQ 0x00004000 + +#define E1000_SPQF_SRCPORT 0x0000FFFF /** src port field */ + +#define E1000_MAX_FTQF_FILTERS 8 +#define E1000_FTQF_PROTOCOL_MASK 0x000000FF +#define E1000_FTQF_5TUPLE_MASK_SHIFT 28 +#define E1000_FTQF_PROTOCOL_COMP_MASK 0x10000000 +#define E1000_FTQF_SOURCE_ADDR_MASK 0x20000000 +#define E1000_FTQF_DEST_ADDR_MASK 0x40000000 +#define E1000_FTQF_SOURCE_PORT_MASK 0x80000000 +#define E1000_FTQF_VF_MASK_EN 0x00008000 +#define E1000_FTQF_QUEUE_MASK 0x03ff0000 +#define E1000_FTQF_QUEUE_SHIFT 16 +#define E1000_FTQF_QUEUE_ENABLE 0x00000100 + /* structure for interrupt relative data */ struct e1000_interrupt { uint32_t flags; diff --git a/lib/librte_pmd_e1000/igb_ethdev.c b/lib/librte_pmd_e1000/igb_e= thdev.c index 044eac3..1e63a8f 100644 --- a/lib/librte_pmd_e1000/igb_ethdev.c +++ b/lib/librte_pmd_e1000/igb_ethdev.c @@ -124,6 +124,43 @@ static int eth_igb_rss_reta_update(struct rte_eth_dev = *dev, static int eth_igb_rss_reta_query(struct rte_eth_dev *dev, struct rte_eth_rss_reta *reta_conf); =20 +static int eth_igb_set_syn_filter(struct rte_eth_dev *dev, + struct rte_syn_filter *filter, uint8_t rx_queue); +static int eth_igb_get_syn_filter(struct rte_eth_dev *dev, + struct rte_syn_filter *filter, uint8_t *rx_queue); +static int eth_igb_add_ethertype_filter(struct rte_eth_dev *dev, + uint16_t index, + struct rte_ethertype_filter *filter, uint8_t rx_queue); +static int eth_igb_remove_ethertype_filter(struct rte_eth_dev *dev, + uint16_t index); +static int eth_igb_get_ethertype_filter(struct rte_eth_dev *dev, + uint16_t index, + struct rte_ethertype_filter *filter, uint8_t *rx_queue); +static int eth_igb_add_2tuple_filter(struct rte_eth_dev *dev, + uint16_t index, + struct rte_2tuple_filter *filter, uint8_t rx_queue); +static int eth_igb_remove_2tuple_filter(struct rte_eth_dev *dev, + uint16_t index); +static int eth_igb_get_2tuple_filter(struct rte_eth_dev *dev, + uint16_t index, + struct rte_2tuple_filter *filter, uint8_t *rx_queue); +static int eth_igb_add_flex_filter(struct rte_eth_dev *dev, + uint16_t index, + struct rte_flex_filter *filter, uint8_t rx_queue); +static int eth_igb_remove_flex_filter(struct rte_eth_dev *dev, + uint16_t index); +static int eth_igb_get_flex_filter(struct rte_eth_dev *dev, + uint16_t index, + struct rte_flex_filter *filter, uint8_t *rx_queue); +static int eth_igb_add_5tuple_filter(struct rte_eth_dev *dev, + uint16_t index, + struct rte_5tuple_filter *filter, uint8_t rx_queue); +static int eth_igb_remove_5tuple_filter(struct rte_eth_dev *dev, + uint16_t index); +static int eth_igb_get_5tuple_filter(struct rte_eth_dev *dev, + uint16_t index, + struct rte_5tuple_filter *filter, uint8_t *rx_queue); + /* * Define VF Stats MACRO for Non "cleared on read" register */ @@ -194,6 +231,20 @@ static struct eth_dev_ops eth_igb_ops =3D { .mac_addr_remove =3D eth_igb_rar_clear, .reta_update =3D eth_igb_rss_reta_update, .reta_query =3D eth_igb_rss_reta_query, + .set_syn_filter =3D eth_igb_set_syn_filter, + .get_syn_filter =3D eth_igb_get_syn_filter, + .add_ethertype_filter =3D eth_igb_add_ethertype_filter, + .remove_ethertype_filter =3D eth_igb_remove_ethertype_filter, + .get_ethertype_filter =3D eth_igb_get_ethertype_filter, + .add_2tuple_filter =3D eth_igb_add_2tuple_filter, + .remove_2tuple_filter =3D eth_igb_remove_2tuple_filter, + .get_2tuple_filter =3D eth_igb_get_2tuple_filter, + .add_flex_filter =3D eth_igb_add_flex_filter, + .remove_flex_filter =3D eth_igb_remove_flex_filter, + .get_flex_filter =3D eth_igb_get_flex_filter, + .add_5tuple_filter =3D eth_igb_add_5tuple_filter, + .remove_5tuple_filter =3D eth_igb_remove_5tuple_filter, + .get_5tuple_filter =3D eth_igb_get_5tuple_filter, }; =20 /* @@ -2184,6 +2235,700 @@ eth_igb_rss_reta_query(struct rte_eth_dev *dev, return 0; } =20 +#define MAC_TYPE_FILTER_SUP(type) do {\ + if ((type) !=3D e1000_82580 && (type) !=3D e1000_i350 &&\ + (type) !=3D e1000_82576)\ + return -ENOSYS;\ +} while (0) + +/* + *set the syn filter + * + * @param + * dev: Pointer to struct rte_eth_dev. + * syn: 1 means enable, 0 means disable. + * rx_queue: the queue id the filter assigned to + * + * @return + * - On success, zero. + * - On failure, a negative value. + */ +static int +eth_igb_set_syn_filter(struct rte_eth_dev *dev, + struct rte_syn_filter *filter, uint8_t rx_queue) +{ + struct e1000_hw *hw =3D E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + uint32_t synqf, rfctl; + + MAC_TYPE_FILTER_SUP(hw->mac.type); + + if (rx_queue >=3D IGB_MAX_RX_QUEUE_NUM) + return (-EINVAL); + + synqf =3D E1000_READ_REG(hw, E1000_SYNQF(0)); + rfctl =3D E1000_READ_REG(hw, E1000_RFCTL); + + if (filter->enable) { + if (synqf & E1000_SYN_FILTER_ENABLE) + return (-EINVAL); + synqf =3D (uint32_t)(((rx_queue << E1000_SYN_FILTER_QUEUE_SHIFT) & + E1000_SYN_FILTER_QUEUE) | E1000_SYN_FILTER_ENABLE); + } else + synqf =3D 0; + + if (filter->hig_pri) + rfctl |=3D E1000_RFCTL_SYNQFP; + else + rfctl &=3D ~E1000_RFCTL_SYNQFP; + + E1000_WRITE_REG(hw, E1000_SYNQF(0), synqf); + E1000_WRITE_REG(hw, E1000_RFCTL, rfctl); + return 0; +} + +/* + *get the syn filter's info + * + * @param + * dev: Pointer to struct rte_eth_dev. + * *syn: pointer to syn value (1 means enable, 0 means disable). + * *rx_queue: pointer to the queue id the filter assigned to + * + * @return + * - On success, zero. + * - On failure, a negative value. + */ +static int +eth_igb_get_syn_filter(struct rte_eth_dev *dev, + struct rte_syn_filter *filter, uint8_t *rx_queue) +{ + struct e1000_hw *hw =3D E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + uint32_t synqf, rfctl; + + MAC_TYPE_FILTER_SUP(hw->mac.type); + synqf =3D E1000_READ_REG(hw, E1000_SYNQF(0)); + rfctl =3D E1000_READ_REG(hw, E1000_RFCTL); + filter->enable =3D (synqf & E1000_SYN_FILTER_ENABLE) ? 1 : 0; + filter->hig_pri =3D (rfctl & E1000_RFCTL_SYNQFP) ? 1 : 0; + *rx_queue =3D (uint8_t)((synqf & E1000_SYN_FILTER_QUEUE) >> + E1000_SYN_FILTER_QUEUE_SHIFT); + return 0; +} + +/* + *add an ethertype filter + * + * @param + * dev: Pointer to struct rte_eth_dev. + * index: the index the filter allocates + * filter: ponter to the filter that will be added + * rx_queue: the queue id the filter assigned to + * + * @return + * - On success, zero. + * - On failure, a negative value. + */ +static int +eth_igb_add_ethertype_filter(struct rte_eth_dev *dev, uint16_t index, + struct rte_ethertype_filter *filter, uint8_t rx_queue) +{ + struct e1000_hw *hw =3D E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + uint32_t etqf; + + MAC_TYPE_FILTER_SUP(hw->mac.type); + + if (index >=3D E1000_MAX_ETQF_FILTERS || rx_queue >=3D IGB_MAX_RX_QUEUE_N= UM) + return (-EINVAL); + + etqf =3D E1000_READ_REG(hw, E1000_ETQF(index)); + if (etqf & E1000_ETQF_FILTER_ENABLE) + return (-EINVAL); /**filter index is in use*/ + else + etqf =3D 0; + + etqf |=3D E1000_ETQF_FILTER_ENABLE | E1000_ETQF_QUEUE_ENABLE; + etqf |=3D (uint32_t)(filter->ethertype & E1000_ETQF_ETHERTYPE); + etqf |=3D rx_queue << E1000_ETQF_QUEUE_SHIFT; + + if (filter->priority_en) { + PMD_INIT_LOG(ERR, "vlan and priority (%d) is not support" + " in E1000.\n", filter->priority); + return (-EINVAL); + } + + E1000_WRITE_REG(hw, E1000_ETQF(index), etqf); + return 0; +} + +/* + *remove an ethertype filter + * + * @param + * dev: Pointer to struct rte_eth_dev. + * index: the index the filter allocates + * + * @return + * - On success, zero. + * - On failure, a negative value. + */ +static int +eth_igb_remove_ethertype_filter(struct rte_eth_dev *dev, uint16_t index) +{ + struct e1000_hw *hw =3D E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + + MAC_TYPE_FILTER_SUP(hw->mac.type); + + if (index >=3D E1000_MAX_ETQF_FILTERS) + return (-EINVAL); + + E1000_WRITE_REG(hw, E1000_ETQF(index), 0); + return 0; +} + +/* + *gets an ethertype filter + * + * @param + * dev: Pointer to struct rte_eth_dev. + * index: the index the filter allocates + * filter: ponter to the filter that will be gotten + * *rx_queue: the ponited of the queue id the filter assigned to + * + * @return + * - On success, zero. + * - On failure, a negative value. + */ +static int +eth_igb_get_ethertype_filter(struct rte_eth_dev *dev, uint16_t index, + struct rte_ethertype_filter *filter, uint8_t *rx_queue) +{ + struct e1000_hw *hw =3D E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + uint32_t etqf; + + MAC_TYPE_FILTER_SUP(hw->mac.type); + + if (index >=3D E1000_MAX_ETQF_FILTERS) + return (-EINVAL); + + etqf =3D E1000_READ_REG(hw, E1000_ETQF(index)); + if (etqf & E1000_ETQF_FILTER_ENABLE) { + filter->ethertype =3D etqf & E1000_ETQF_ETHERTYPE; + filter->priority_en =3D 0; + *rx_queue =3D (etqf & E1000_ETQF_QUEUE) >> E1000_ETQF_QUEUE_SHIFT; + return 0; + } + return (-ENOENT); +} + +#define MAC_TYPE_FILTER_SUP_EXT(type) do {\ + if ((type) !=3D e1000_82580 && (type) !=3D e1000_i350)\ + return -ENOSYS; \ +} while (0) + +/* + *add a 2tuple filter + * + * @param + * dev: Pointer to struct rte_eth_dev. + * index: the index the filter allocates + * filter: ponter to the filter that will be added + * rx_queue: the queue id the filter assigned to + * + * @return + * - On success, zero. + * - On failure, a negative value. + */ +static int +eth_igb_add_2tuple_filter(struct rte_eth_dev *dev, uint16_t index, + struct rte_2tuple_filter *filter, uint8_t rx_queue) +{ + struct e1000_hw *hw =3D E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + uint32_t ttqf, imir =3D 0; + uint32_t imir_ext =3D 0; + + MAC_TYPE_FILTER_SUP_EXT(hw->mac.type); + + if (index >=3D E1000_MAX_TTQF_FILTERS || + rx_queue >=3D IGB_MAX_RX_QUEUE_NUM || + filter->priority > E1000_2TUPLE_MAX_PRI) + return (-EINVAL); /**filter index is out of range*/ + if (filter->tcp_flags > TCP_FLAG_ALL) + return (-EINVAL); /**flags is invalid*/ + + ttqf =3D E1000_READ_REG(hw, E1000_TTQF(index)); + if (ttqf & E1000_TTQF_QUEUE_ENABLE) + return (-EINVAL); /**filter index is in use*/ + + imir =3D (uint32_t)(filter->dst_port & E1000_IMIR_DSTPORT); + if (filter->dst_port_mask =3D=3D 1) /**1b means not compare*/ + imir |=3D E1000_IMIR_PORT_BP; + else + imir &=3D ~E1000_IMIR_PORT_BP; + + imir |=3D filter->priority << E1000_IMIR_PRIORITY_SHIFT; + + ttqf =3D 0; + ttqf |=3D E1000_TTQF_QUEUE_ENABLE; + ttqf |=3D (uint32_t)(rx_queue << E1000_TTQF_QUEUE_SHIFT); + ttqf |=3D (uint32_t)(filter->protocol & E1000_TTQF_PROTOCOL_MASK); + if (filter->protocol_mask =3D=3D 1) + ttqf |=3D E1000_TTQF_MASK_ENABLE; + else + ttqf &=3D ~E1000_TTQF_MASK_ENABLE; + + imir_ext |=3D E1000_IMIR_EXT_SIZE_BP; + /*tcp flags bits setting*/ + if (filter->tcp_flags & TCP_FLAG_ALL) { + if (filter->tcp_flags & TCP_UGR_FLAG) + imir_ext |=3D E1000_IMIR_EXT_CTRL_UGR; + if (filter->tcp_flags & TCP_ACK_FLAG) + imir_ext |=3D E1000_IMIR_EXT_CTRL_ACK; + if (filter->tcp_flags & TCP_PSH_FLAG) + imir_ext |=3D E1000_IMIR_EXT_CTRL_PSH; + if (filter->tcp_flags & TCP_RST_FLAG) + imir_ext |=3D E1000_IMIR_EXT_CTRL_RST; + if (filter->tcp_flags & TCP_SYN_FLAG) + imir_ext |=3D E1000_IMIR_EXT_CTRL_SYN; + if (filter->tcp_flags & TCP_FIN_FLAG) + imir_ext |=3D E1000_IMIR_EXT_CTRL_FIN; + imir_ext &=3D ~E1000_IMIR_EXT_CTRL_BP; + } else + imir_ext |=3D E1000_IMIR_EXT_CTRL_BP; + E1000_WRITE_REG(hw, E1000_IMIR(index), imir); + E1000_WRITE_REG(hw, E1000_TTQF(index), ttqf); + E1000_WRITE_REG(hw, E1000_IMIREXT(index), imir_ext); + return 0; +} + +/* + *remove a 2tuple filter + * + * @param + * dev: Pointer to struct rte_eth_dev. + * index: the index the filter allocates + * + * @return + * - On success, zero. + * - On failure, a negative value. + */ +static int +eth_igb_remove_2tuple_filter(struct rte_eth_dev *dev, + uint16_t index) +{ + struct e1000_hw *hw =3D E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + + MAC_TYPE_FILTER_SUP_EXT(hw->mac.type); + + if (index >=3D E1000_MAX_TTQF_FILTERS) + return (-EINVAL); /**filter index is out of range*/ + + E1000_WRITE_REG(hw, E1000_TTQF(index), 0); + E1000_WRITE_REG(hw, E1000_IMIR(index), 0); + E1000_WRITE_REG(hw, E1000_IMIREXT(index), 0); + return 0; +} + +/* + *get a 2tuple filter + * + * @param + * dev: Pointer to struct rte_eth_dev. + * index: the index the filter allocates + * filter: ponter to the filter that returns + * *rx_queue: pointer of the queue id the filter assigned to + * + * @return + * - On success, zero. + * - On failure, a negative value. + */ +static int +eth_igb_get_2tuple_filter(struct rte_eth_dev *dev, uint16_t index, + struct rte_2tuple_filter *filter, uint8_t *rx_queue) +{ + struct e1000_hw *hw =3D E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + uint32_t imir, ttqf, imir_ext; + + MAC_TYPE_FILTER_SUP_EXT(hw->mac.type); + + if (index >=3D E1000_MAX_TTQF_FILTERS) + return (-EINVAL); /**filter index is out of range*/ + + ttqf =3D E1000_READ_REG(hw, E1000_TTQF(index)); + if (ttqf & E1000_TTQF_QUEUE_ENABLE) { + imir =3D E1000_READ_REG(hw, E1000_IMIR(index)); + filter->protocol =3D ttqf & E1000_TTQF_PROTOCOL_MASK; + filter->protocol_mask =3D (ttqf & E1000_TTQF_MASK_ENABLE) ? 1 : 0; + *rx_queue =3D (ttqf & E1000_TTQF_RX_QUEUE_MASK) >> + E1000_TTQF_QUEUE_SHIFT; + filter->dst_port =3D (uint16_t)(imir & E1000_IMIR_DSTPORT); + filter->dst_port_mask =3D (imir & E1000_IMIR_PORT_BP) ? 1 : 0; + filter->priority =3D (imir & E1000_IMIR_PRIORITY) >> + E1000_IMIR_PRIORITY_SHIFT; + + imir_ext =3D E1000_READ_REG(hw, E1000_IMIREXT(index)); + if (!(imir_ext & E1000_IMIR_EXT_CTRL_BP)) { + if (imir_ext & E1000_IMIR_EXT_CTRL_UGR) + filter->tcp_flags |=3D TCP_UGR_FLAG; + if (imir_ext & E1000_IMIR_EXT_CTRL_ACK) + filter->tcp_flags |=3D TCP_ACK_FLAG; + if (imir_ext & E1000_IMIR_EXT_CTRL_PSH) + filter->tcp_flags |=3D TCP_PSH_FLAG; + if (imir_ext & E1000_IMIR_EXT_CTRL_RST) + filter->tcp_flags |=3D TCP_RST_FLAG; + if (imir_ext & E1000_IMIR_EXT_CTRL_SYN) + filter->tcp_flags |=3D TCP_SYN_FLAG; + if (imir_ext & E1000_IMIR_EXT_CTRL_FIN) + filter->tcp_flags |=3D TCP_FIN_FLAG; + } else + filter->tcp_flags =3D 0; + return 0; + } + return (-ENOENT); +} + +/* + *add a flex filter + * + * @param + * dev: Pointer to struct rte_eth_dev. + * index: the index the filter allocates + * filter: ponter to the filter that will be added + * rx_queue: the queue id the filter assigned to + * + * @return + * - On success, zero. + * - On failure, a negative value. + */ +static int +eth_igb_add_flex_filter(struct rte_eth_dev *dev, uint16_t index, + struct rte_flex_filter *filter, uint8_t rx_queue) +{ + struct e1000_hw *hw =3D E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + uint32_t wufc, en_bits =3D 0; + uint32_t queueing =3D 0; + uint32_t reg_off =3D 0; + uint8_t i, j =3D 0; + + MAC_TYPE_FILTER_SUP_EXT(hw->mac.type); + + if (index >=3D E1000_MAX_FLEXIBLE_FILTERS) + return (-EINVAL); /**filter index is out of range*/ + + if (filter->len =3D=3D 0 || filter->len > E1000_MAX_FLEX_FILTER_LEN || + filter->len % 8 !=3D 0 || + filter->priority > E1000_MAX_FLEX_FILTER_PRI) + return (-EINVAL); + + wufc =3D E1000_READ_REG(hw, E1000_WUFC); + en_bits =3D E1000_WUFC_FLEX_HQ | (E1000_WUFC_FLX0 << index); + if ((wufc & en_bits) =3D=3D en_bits) + return (-EINVAL); /**the filter is enabled*/ + + E1000_WRITE_REG(hw, E1000_WUFC, + wufc | E1000_WUFC_FLEX_HQ | (E1000_WUFC_FLX0 << index)); + + j =3D 0; + if (index < E1000_MAX_FHFT) + reg_off =3D E1000_FHFT(index); + else + reg_off =3D E1000_FHFT_EXT(index - E1000_MAX_FHFT); + + for (i =3D 0; i < 16; i++) { + E1000_WRITE_REG(hw, reg_off + i*4*4, filter->dwords[j]); + E1000_WRITE_REG(hw, reg_off + (i*4+1)*4, filter->dwords[++j]); + E1000_WRITE_REG(hw, reg_off + (i*4+2)*4, + (uint32_t)filter->mask[i]); + ++j; + } + queueing |=3D filter->len | + (rx_queue << E1000_FHFT_QUEUEING_QUEUE_SHIFT) | + (filter->priority << E1000_FHFT_QUEUEING_PRIO_SHIFT); + E1000_WRITE_REG(hw, reg_off + E1000_FHFT_QUEUEING_OFFSET, queueing); + return 0; +} + +/* + *remove a flex filter + * + * @param + * dev: Pointer to struct rte_eth_dev. + * index: the index the filter allocates + * + * @return + * - On success, zero. + * - On failure, a negative value. + */ +static int +eth_igb_remove_flex_filter(struct rte_eth_dev *dev, + uint16_t index) +{ + struct e1000_hw *hw =3D E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + uint32_t wufc, reg_off =3D 0; + uint8_t i; + + MAC_TYPE_FILTER_SUP_EXT(hw->mac.type); + + if (index >=3D E1000_MAX_FLEXIBLE_FILTERS) + return (-EINVAL); /**filter index is out of range*/ + + wufc =3D E1000_READ_REG(hw, E1000_WUFC); + E1000_WRITE_REG(hw, E1000_WUFC, wufc & (~(E1000_WUFC_FLX0 << index))); + + if (index < E1000_MAX_FHFT) + reg_off =3D E1000_FHFT(index); + else + reg_off =3D E1000_FHFT_EXT(index - E1000_MAX_FHFT); + + for (i =3D 0; i < 64; i++) + E1000_WRITE_REG(hw, reg_off + i*4, 0); + return 0; +} + +/* + *get a flex filter + * + * @param + * dev: Pointer to struct rte_eth_dev. + * index: the index the filter allocates + * filter: ponter to the filter that returns + * *rx_queue: the pointer of the queue id the filter assigned to + * + * @return + * - On success, zero. + * - On failure, a negative value. + */ +static int +eth_igb_get_flex_filter(struct rte_eth_dev *dev, uint16_t index, + struct rte_flex_filter *filter, uint8_t *rx_queue) +{ + struct e1000_hw *hw =3D E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + uint32_t wufc, queueing, wufc_en =3D 0; + uint8_t i, j; + + MAC_TYPE_FILTER_SUP_EXT(hw->mac.type); + + if (index >=3D E1000_MAX_FLEXIBLE_FILTERS) + return (-EINVAL); /**filter index is out of range*/ + + wufc =3D E1000_READ_REG(hw, E1000_WUFC); + wufc_en =3D E1000_WUFC_FLEX_HQ | (E1000_WUFC_FLX0 << index); + + if ((wufc & wufc_en) =3D=3D wufc_en) { + uint32_t reg_off =3D 0; + j =3D 0; + if (index < E1000_MAX_FHFT) + reg_off =3D E1000_FHFT(index); + else + reg_off =3D E1000_FHFT_EXT(index - E1000_MAX_FHFT); + + for (i =3D 0; i < 16; i++, j =3D i * 2) { + filter->dwords[j] =3D + E1000_READ_REG(hw, reg_off + i*4*4); + filter->dwords[j+1] =3D + E1000_READ_REG(hw, reg_off + (i*4+1)*4); + filter->mask[i] =3D + E1000_READ_REG(hw, reg_off + (i*4+2)*4); + } + queueing =3D E1000_READ_REG(hw, + reg_off + E1000_FHFT_QUEUEING_OFFSET); + filter->len =3D queueing & E1000_FHFT_QUEUEING_LEN; + filter->priority =3D (queueing & E1000_FHFT_QUEUEING_PRIO) >> + E1000_FHFT_QUEUEING_PRIO_SHIFT; + *rx_queue =3D (queueing & E1000_FHFT_QUEUEING_QUEUE) >> + E1000_FHFT_QUEUEING_QUEUE_SHIFT; + return 0; + } + return (-ENOENT); +} + +/* + *add a 5tuple filter + * + * @param + * dev: Pointer to struct rte_eth_dev. + * index: the index the filter allocates + * filter: ponter to the filter that will be added + * rx_queue: the queue id the filter assigned to + * + * @return + * - On success, zero. + * - On failure, a negative value. + */ +static int +eth_igb_add_5tuple_filter(struct rte_eth_dev *dev, uint16_t index, + struct rte_5tuple_filter *filter, uint8_t rx_queue) +{ + struct e1000_hw *hw =3D E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + uint32_t ftqf, spqf =3D 0; + uint32_t imir =3D 0; + uint32_t imir_ext =3D 0; + + if (hw->mac.type !=3D e1000_82576) + return (-ENOSYS); + + if (index >=3D E1000_MAX_FTQF_FILTERS || + rx_queue >=3D IGB_MAX_RX_QUEUE_NUM_82576) + return (-EINVAL); /**filter index is out of range*/ + + ftqf =3D E1000_READ_REG(hw, E1000_FTQF(index)); + if (ftqf & E1000_FTQF_QUEUE_ENABLE) + return (-EINVAL); /**filter index is in use*/ + + ftqf =3D 0; + ftqf |=3D filter->protocol & E1000_FTQF_PROTOCOL_MASK; + if (filter->src_ip_mask =3D=3D 1) /** 1b means not compare*/ + ftqf |=3D E1000_FTQF_SOURCE_ADDR_MASK; + if (filter->dst_ip_mask =3D=3D 1) + ftqf |=3D E1000_FTQF_DEST_ADDR_MASK; + if (filter->src_port_mask =3D=3D 1) + ftqf |=3D E1000_FTQF_SOURCE_PORT_MASK; + if (filter->protocol_mask =3D=3D 1) + ftqf |=3D E1000_FTQF_PROTOCOL_COMP_MASK; + ftqf |=3D (rx_queue << E1000_FTQF_QUEUE_SHIFT) & E1000_FTQF_QUEUE_MASK; + ftqf |=3D E1000_FTQF_VF_MASK_EN; + ftqf |=3D E1000_FTQF_QUEUE_ENABLE; + E1000_WRITE_REG(hw, E1000_FTQF(index), ftqf); + E1000_WRITE_REG(hw, E1000_DAQF(index), filter->dst_ip); + E1000_WRITE_REG(hw, E1000_SAQF(index), filter->src_ip); + + spqf |=3D filter->src_port & E1000_SPQF_SRCPORT; + E1000_WRITE_REG(hw, E1000_SPQF(index), spqf); + + imir |=3D (uint32_t)(filter->dst_port & E1000_IMIR_DSTPORT); + if (filter->dst_port_mask =3D=3D 1) /**1b means not compare*/ + imir |=3D E1000_IMIR_PORT_BP; + else + imir &=3D ~E1000_IMIR_PORT_BP; + imir |=3D filter->priority << E1000_IMIR_PRIORITY_SHIFT; + + imir_ext |=3D E1000_IMIR_EXT_SIZE_BP; + /*tcp flags bits setting*/ + if (filter->tcp_flags & TCP_FLAG_ALL) { + if (filter->tcp_flags & TCP_UGR_FLAG) + imir_ext |=3D E1000_IMIR_EXT_CTRL_UGR; + if (filter->tcp_flags & TCP_ACK_FLAG) + imir_ext |=3D E1000_IMIR_EXT_CTRL_ACK; + if (filter->tcp_flags & TCP_PSH_FLAG) + imir_ext |=3D E1000_IMIR_EXT_CTRL_PSH; + if (filter->tcp_flags & TCP_RST_FLAG) + imir_ext |=3D E1000_IMIR_EXT_CTRL_RST; + if (filter->tcp_flags & TCP_SYN_FLAG) + imir_ext |=3D E1000_IMIR_EXT_CTRL_SYN; + if (filter->tcp_flags & TCP_FIN_FLAG) + imir_ext |=3D E1000_IMIR_EXT_CTRL_FIN; + } else + imir_ext |=3D E1000_IMIR_EXT_CTRL_BP; + E1000_WRITE_REG(hw, E1000_IMIR(index), imir); + E1000_WRITE_REG(hw, E1000_IMIREXT(index), imir_ext); + return 0; +} + +/* + *remove a 5tuple filter + * + * @param + * dev: Pointer to struct rte_eth_dev. + * index: the index the filter allocates + * + * @return + * - On success, zero. + * - On failure, a negative value. + */ +static int +eth_igb_remove_5tuple_filter(struct rte_eth_dev *dev, + uint16_t index) +{ + struct e1000_hw *hw =3D E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + + if (hw->mac.type !=3D e1000_82576) + return (-ENOSYS); + + if (index >=3D E1000_MAX_FTQF_FILTERS) + return (-EINVAL); /**filter index is out of range*/ + + E1000_WRITE_REG(hw, E1000_FTQF(index), 0); + E1000_WRITE_REG(hw, E1000_DAQF(index), 0); + E1000_WRITE_REG(hw, E1000_SAQF(index), 0); + E1000_WRITE_REG(hw, E1000_SPQF(index), 0); + E1000_WRITE_REG(hw, E1000_IMIR(index), 0); + E1000_WRITE_REG(hw, E1000_IMIREXT(index), 0); + return 0; +} + +/* + *get a 5tuple filter + * + * @param + * dev: Pointer to struct rte_eth_dev. + * index: the index the filter allocates + * filter: ponter to the filter that returns + * *rx_queue: pointer of the queue id the filter assigned to + * + * @return + * - On success, zero. + * - On failure, a negative value. + */ +static int +eth_igb_get_5tuple_filter(struct rte_eth_dev *dev, uint16_t index, + struct rte_5tuple_filter *filter, uint8_t *rx_queue) +{ + struct e1000_hw *hw =3D E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + uint32_t spqf, ftqf, imir, imir_ext; + + if (hw->mac.type !=3D e1000_82576) + return (-ENOSYS); + + if (index >=3D E1000_MAX_FTQF_FILTERS) + return (-EINVAL); /**filter index is out of range*/ + + ftqf =3D E1000_READ_REG(hw, E1000_FTQF(index)); + if (ftqf & E1000_FTQF_QUEUE_ENABLE) { + filter->src_ip_mask =3D + (ftqf & E1000_FTQF_SOURCE_ADDR_MASK) ? 1 : 0; + filter->dst_ip_mask =3D + (ftqf & E1000_FTQF_DEST_ADDR_MASK) ? 1 : 0; + filter->src_port_mask =3D + (ftqf & E1000_FTQF_SOURCE_PORT_MASK) ? 1 : 0; + filter->protocol_mask =3D + (ftqf & E1000_FTQF_PROTOCOL_COMP_MASK) ? 1 : 0; + filter->protocol =3D + (uint8_t)ftqf & E1000_FTQF_PROTOCOL_MASK; + *rx_queue =3D (uint8_t)((ftqf & E1000_FTQF_QUEUE_MASK) >> + E1000_FTQF_QUEUE_SHIFT); + + spqf =3D E1000_READ_REG(hw, E1000_SPQF(index)); + filter->src_port =3D spqf & E1000_SPQF_SRCPORT; + + filter->dst_ip =3D E1000_READ_REG(hw, E1000_DAQF(index)); + filter->src_ip =3D E1000_READ_REG(hw, E1000_SAQF(index)); + + imir =3D E1000_READ_REG(hw, E1000_IMIR(index)); + filter->dst_port_mask =3D (imir & E1000_IMIR_PORT_BP) ? 1 : 0; + filter->dst_port =3D (uint16_t)(imir & E1000_IMIR_DSTPORT); + filter->priority =3D (imir & E1000_IMIR_PRIORITY) >> + E1000_IMIR_PRIORITY_SHIFT; + + imir_ext =3D E1000_READ_REG(hw, E1000_IMIREXT(index)); + if (!(imir_ext & E1000_IMIR_EXT_CTRL_BP)) { + if (imir_ext & E1000_IMIR_EXT_CTRL_UGR) + filter->tcp_flags |=3D TCP_UGR_FLAG; + if (imir_ext & E1000_IMIR_EXT_CTRL_ACK) + filter->tcp_flags |=3D TCP_ACK_FLAG; + if (imir_ext & E1000_IMIR_EXT_CTRL_PSH) + filter->tcp_flags |=3D TCP_PSH_FLAG; + if (imir_ext & E1000_IMIR_EXT_CTRL_RST) + filter->tcp_flags |=3D TCP_RST_FLAG; + if (imir_ext & E1000_IMIR_EXT_CTRL_SYN) + filter->tcp_flags |=3D TCP_SYN_FLAG; + if (imir_ext & E1000_IMIR_EXT_CTRL_FIN) + filter->tcp_flags |=3D TCP_FIN_FLAG; + } else + filter->tcp_flags =3D 0; + return 0; + } + return (-ENOENT); +} + static struct rte_driver pmd_igb_drv =3D { .type =3D PMD_PDEV, .init =3D rte_igb_pmd_init, --=20 1.8.1.4