DPDK-dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH v6 4/4] latencystats: added new library for latency stats
From: Thomas Monjalon @ 2017-01-13  9:53 UTC (permalink / raw)
  To: Mcnamara, John, Horton, Remy; +Cc: Pattan, Reshma, dev, olivier.matz
In-Reply-To: <B27915DBBA3421428155699D51E4CFE2026AFFD0@IRSMSX103.ger.corp.intel.com>

2017-01-13 09:45, Mcnamara, John:
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Thomas Monjalon
> > 2017-01-12 00:03, Remy Horton:
> > > Add a library designed to calculate latency statistics and report them
> > > to the application when queried. The library measures minimum, average
> > > and maximum latencies, and jitter in nano seconds. The current
> > > implementation supports global latency stats, i.e. per application
> > stats.
> > 
> > Is it specific to ethdev ports?
> > 
> > > Added new field to mbuf struct to mark the packet arrival time on Rx.
> > 
> > There was another patch adding a timestamp in mbuf:
> > 	http://dpdk.org/ml/archives/dev/2016-October/048809.html
> 
> Hi Thomas,
> 
> Is that an issue? The other patch adds the same field for more or less the same purpose.
> If the other patch goes in we can rework this patch or if this patch goes in the
> other one won't be required.

Yes
The only issue is that it is not yet accepted or merged.
I think Olivier was considering it in a more global mbuf rework.

^ permalink raw reply

* [PATCH v2 0/4] enhancement to i40e PF host driver
From: Chen Jing D(Mark) @ 2017-01-13  3:13 UTC (permalink / raw)
  To: dev
  Cc: daniels, helin.zhang, ferruh.yigit, vincent.jardin, jingjing.wu,
	Chen Jing D(Mark)
In-Reply-To: <1483405159-9237-2-git-send-email-jing.d.chen@intel.com>

v2:
- add macro to replace numeric
- rework comments

Current PF host driver can serve DPDK VF well, but the
implementation is not complete to support Linux VF,
even both DPDK VF and Linux VF use same API set.

Note that the patch are experimental for use and might
be removed without prior notice.

This patch set made below changes:
1. Make an enhancement on interface to serve VF, so
   both Linux and DPDK VF can be well served.
2. Change API version number so both DPDK and Linux
   VF can recognize and select proper command and
   data structure to request service. But the
   sacrifice is DPDK VF can't identify host driver
   (Linux or DPDK) and extended function provided
   in DPDK PF host driver can't be used.
   This situation will change after negotiate with
   Linux maintainer to provide a better mechanism
   to identify both PF and VF function.

Chen Jing D(Mark) (4):
  net/i40e: change version number to support Linux VF
  net/i40e: return correct VSI id
  net/i40e: parse more VF parameter and configure
  net/i40e: support Linux VF to configure IRQ link list

 drivers/net/i40e/i40e_pf.c |  171 +++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 153 insertions(+), 18 deletions(-)

-- 
1.7.7.6

^ permalink raw reply

* [PATCH v2 1/4] net/i40e: change version number to support Linux VF
From: Chen Jing D(Mark) @ 2017-01-13  3:13 UTC (permalink / raw)
  To: dev
  Cc: daniels, helin.zhang, ferruh.yigit, vincent.jardin, jingjing.wu,
	Chen Jing D(Mark)
In-Reply-To: <1484277201-5930-1-git-send-email-jing.d.chen@intel.com>

i40e PF host only support to work with DPDK VF driver, Linux
VF driver is not supported. This change will enhance in version
number returned.

Current version info returned won't be able to be recognized
by Linux VF driver, change to values that both DPDK VF and Linux
driver can recognize.

The expense is original DPDK host specific feature like
CFG_VLAN_PVID and CONFIG_VSI_QUEUES_EXT will not available.

DPDK VF also can't identify host driver by version number returned.
It always assume talking with Linux PF.

Signed-off-by: Chen Jing D(Mark) <jing.d.chen@intel.com>
---
 drivers/net/i40e/i40e_pf.c |   12 ++++++++++--
 1 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c
index ddfc140..fa4af2b 100644
--- a/drivers/net/i40e/i40e_pf.c
+++ b/drivers/net/i40e/i40e_pf.c
@@ -276,8 +276,16 @@
 {
 	struct i40e_virtchnl_version_info info;
 
-	info.major = I40E_DPDK_VERSION_MAJOR;
-	info.minor = I40E_DPDK_VERSION_MINOR;
+	/* Respond like a Linux PF host in order to support both DPDK VF and
+	 * Linux VF driver. The expense is original DPDK host specific feature
+	 * like CFG_VLAN_PVID and CONFIG_VSI_QUEUES_EXT will not available.
+	 *
+	 * DPDK VF also can't identify host driver by version number returned.
+	 * It always assume talking with Linux PF.
+	 */
+	info.major = I40E_VIRTCHNL_VERSION_MAJOR;
+	info.minor = I40E_VIRTCHNL_VERSION_MINOR_NO_VF_CAPS;
+
 	i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_VERSION,
 		I40E_SUCCESS, (uint8_t *)&info, sizeof(info));
 }
-- 
1.7.7.6

^ permalink raw reply related

* [PATCH v2 2/4] net/i40e: return correct VSI id
From: Chen Jing D(Mark) @ 2017-01-13  3:13 UTC (permalink / raw)
  To: dev
  Cc: daniels, helin.zhang, ferruh.yigit, vincent.jardin, jingjing.wu,
	Chen Jing D(Mark)
In-Reply-To: <1484277201-5930-1-git-send-email-jing.d.chen@intel.com>

PF host didn't return correct VSI id to VF.
This change fix it.

Signed-off-by: Chen Jing D(Mark) <jing.d.chen@intel.com>
---
 drivers/net/i40e/i40e_pf.c |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c
index fa4af2b..fd83c16 100644
--- a/drivers/net/i40e/i40e_pf.c
+++ b/drivers/net/i40e/i40e_pf.c
@@ -329,8 +329,7 @@
 
 	/* Change below setting if PF host can support more VSIs for VF */
 	vf_res->vsi_res[0].vsi_type = I40E_VSI_SRIOV;
-	/* As assume Vf only has single VSI now, always return 0 */
-	vf_res->vsi_res[0].vsi_id = 0;
+	vf_res->vsi_res[0].vsi_id = vf->vsi->vsi_id;
 	vf_res->vsi_res[0].num_queue_pairs = vf->vsi->nb_qps;
 	ether_addr_copy(&vf->mac_addr,
 		(struct ether_addr *)vf_res->vsi_res[0].default_mac_addr);
-- 
1.7.7.6

^ permalink raw reply related

* [PATCH v2 3/4] net/i40e: parse more VF parameter and configure
From: Chen Jing D(Mark) @ 2017-01-13  3:13 UTC (permalink / raw)
  To: dev
  Cc: daniels, helin.zhang, ferruh.yigit, vincent.jardin, jingjing.wu,
	Chen Jing D(Mark)
In-Reply-To: <1484277201-5930-1-git-send-email-jing.d.chen@intel.com>

When VF requested to configure TX queue, a few parameters are
missed to be configured in PF host. This change have more
fields parsed and configured for TX context.

Signed-off-by: Chen Jing D(Mark) <jing.d.chen@intel.com>
---
 drivers/net/i40e/i40e_pf.c |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c
index fd83c16..f12a6aa 100644
--- a/drivers/net/i40e/i40e_pf.c
+++ b/drivers/net/i40e/i40e_pf.c
@@ -400,10 +400,12 @@
 
 	/* clear the context structure first */
 	memset(&tx_ctx, 0, sizeof(tx_ctx));
-	tx_ctx.new_context = 1;
 	tx_ctx.base = txq->dma_ring_addr / I40E_QUEUE_BASE_ADDR_UNIT;
 	tx_ctx.qlen = txq->ring_len;
 	tx_ctx.rdylist = rte_le_to_cpu_16(vf->vsi->info.qs_handle[0]);
+	tx_ctx.head_wb_ena = txq->headwb_enabled;
+	tx_ctx.head_wb_addr = txq->dma_headwb_addr;
+
 	err = i40e_clear_lan_tx_queue_context(hw, abs_queue_id);
 	if (err != I40E_SUCCESS)
 		return err;
-- 
1.7.7.6

^ permalink raw reply related

* [PATCH v2 4/4] net/i40e: support Linux VF to configure IRQ link list
From: Chen Jing D(Mark) @ 2017-01-13  3:13 UTC (permalink / raw)
  To: dev
  Cc: daniels, helin.zhang, ferruh.yigit, vincent.jardin, jingjing.wu,
	Chen Jing D(Mark)
In-Reply-To: <1484277201-5930-1-git-send-email-jing.d.chen@intel.com>

i40e PF host only support to work with DPDK VF driver, Linux
VF driver is not supported. This change will enhance in
configuring IRQ link list.

This Change will identify VF client by number of vector
requested. DPDK VF will ask only single one while Linux VF
will request at least 2. It will have different configuration
for different clients. DPDK VF will be configured to link all
queue together, while Linux VF will be configured per request.

Signed-off-by: Chen Jing D(Mark) <jing.d.chen@intel.com>
---
 drivers/net/i40e/i40e_pf.c |  152 ++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 139 insertions(+), 13 deletions(-)

diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c
index f12a6aa..384dfe9 100644
--- a/drivers/net/i40e/i40e_pf.c
+++ b/drivers/net/i40e/i40e_pf.c
@@ -546,13 +546,116 @@
 	return ret;
 }
 
+static void
+i40e_pf_config_irq_link_list(struct i40e_pf_vf *vf,
+			      struct i40e_virtchnl_vector_map *vvm)
+{
+#define BITS_PER_CHAR 8
+	uint64_t linklistmap = 0, tempmap;
+	struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf);
+	uint16_t qid;
+	bool b_first_q = true;
+	enum i40e_queue_type qtype;
+	uint16_t vector_id;
+	uint32_t reg, reg_idx;
+	uint16_t itr_idx = 0, i;
+
+	vector_id = vvm->vector_id;
+	/* setup the head */
+	if (!vector_id)
+		reg_idx = I40E_VPINT_LNKLST0(vf->vf_idx);
+	else
+		reg_idx = I40E_VPINT_LNKLSTN(
+		((hw->func_caps.num_msix_vectors_vf - 1) * vf->vf_idx)
+		+ (vector_id - 1));
+
+	if (vvm->rxq_map == 0 && vvm->txq_map == 0) {
+		I40E_WRITE_REG(hw, reg_idx,
+			I40E_VPINT_LNKLST0_FIRSTQ_INDX_MASK);
+		goto cfg_irq_done;
+	}
+
+	/* sort all rx and tx queues */
+	tempmap = vvm->rxq_map;
+	for (i = 0; i < sizeof(vvm->rxq_map) * BITS_PER_CHAR; i++) {
+		if (tempmap & 0x1)
+			linklistmap |= (1 << (2 * i));
+		tempmap >>= 1;
+	}
+
+	tempmap = vvm->txq_map;
+	for (i = 0; i < sizeof(vvm->txq_map) * BITS_PER_CHAR; i++) {
+		if (tempmap & 0x1)
+			linklistmap |= (1 << (2 * i + 1));
+		tempmap >>= 1;
+	}
+
+	/* Link all rx and tx queues into a chained list */
+	tempmap = linklistmap;
+	i = 0;
+	b_first_q = true;
+	do {
+		if (tempmap & 0x1) {
+			qtype = (enum i40e_queue_type)(i % 2);
+			qid = vf->vsi->base_queue + i / 2;
+			if (b_first_q) {
+				/* This is header */
+				b_first_q = false;
+				reg = ((qtype <<
+				I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_SHIFT)
+				| qid);
+			} else {
+				/* element in the link list */
+				reg = (vector_id) |
+				(qtype << I40E_QINT_RQCTL_NEXTQ_TYPE_SHIFT) |
+				(qid << I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT) |
+				BIT(I40E_QINT_RQCTL_CAUSE_ENA_SHIFT) |
+				(itr_idx << I40E_QINT_RQCTL_ITR_INDX_SHIFT);
+			}
+			I40E_WRITE_REG(hw, reg_idx, reg);
+			/* find next register to program */
+			switch (qtype) {
+			case I40E_QUEUE_TYPE_RX:
+				reg_idx = I40E_QINT_RQCTL(qid);
+				itr_idx = vvm->rxitr_idx;
+				break;
+			case I40E_QUEUE_TYPE_TX:
+				reg_idx = I40E_QINT_TQCTL(qid);
+				itr_idx = vvm->txitr_idx;
+				break;
+			default:
+				break;
+			}
+		}
+		i++;
+		tempmap >>= 1;
+	} while (tempmap);
+
+	/* Terminate the link list */
+	reg = (vector_id) |
+		(0 << I40E_QINT_RQCTL_NEXTQ_TYPE_SHIFT) |
+		(0x7FF << I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT) |
+		BIT(I40E_QINT_RQCTL_CAUSE_ENA_SHIFT) |
+		(itr_idx << I40E_QINT_RQCTL_ITR_INDX_SHIFT);
+	I40E_WRITE_REG(hw, reg_idx, reg);
+
+cfg_irq_done:
+	I40E_WRITE_FLUSH(hw);
+}
+
 static int
 i40e_pf_host_process_cmd_config_irq_map(struct i40e_pf_vf *vf,
 					uint8_t *msg, uint16_t msglen)
 {
 	int ret = I40E_SUCCESS;
+	struct i40e_pf *pf = vf->pf;
+	struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf);
 	struct i40e_virtchnl_irq_map_info *irqmap =
 	    (struct i40e_virtchnl_irq_map_info *)msg;
+	struct i40e_virtchnl_vector_map *map;
+	int i;
+	uint16_t vector_id;
+	unsigned long qbit_max;
 
 	if (msg == NULL || msglen < sizeof(struct i40e_virtchnl_irq_map_info)) {
 		PMD_DRV_LOG(ERR, "buffer too short");
@@ -560,23 +663,46 @@
 		goto send_msg;
 	}
 
-	/* Assume VF only have 1 vector to bind all queues */
-	if (irqmap->num_vectors != 1) {
-		PMD_DRV_LOG(ERR, "DKDK host only support 1 vector");
-		ret = I40E_ERR_PARAM;
+	/* PF host will support both DPDK VF or Linux VF driver, identify by
+	 * number of vectors requested.
+	 */
+
+	/* DPDK VF only requires single vector */
+	if (irqmap->num_vectors == 1) {
+		/* This MSIX intr store the intr in VF range */
+		vf->vsi->msix_intr = irqmap->vecmap[0].vector_id;
+		vf->vsi->nb_msix = irqmap->num_vectors;
+		vf->vsi->nb_used_qps = vf->vsi->nb_qps;
+
+		/* Don't care how the TX/RX queue mapping with this vector.
+		 * Link all VF RX queues together. Only did mapping work.
+		 * VF can disable/enable the intr by itself.
+		 */
+		i40e_vsi_queues_bind_intr(vf->vsi);
 		goto send_msg;
 	}
 
-	/* This MSIX intr store the intr in VF range */
-	vf->vsi->msix_intr = irqmap->vecmap[0].vector_id;
-	vf->vsi->nb_msix = irqmap->num_vectors;
-	vf->vsi->nb_used_qps = vf->vsi->nb_qps;
+	/* Then, it's Linux VF driver */
+	qbit_max = 1 << pf->vf_nb_qp_max;
+	for (i = 0; i < irqmap->num_vectors; i++) {
+		map = &irqmap->vecmap[i];
+
+		vector_id = map->vector_id;
+		/* validate msg params */
+		if (vector_id >= hw->func_caps.num_msix_vectors_vf) {
+			ret = I40E_ERR_PARAM;
+			goto send_msg;
+		}
+
+		if ((map->rxq_map < qbit_max) && (map->txq_map < qbit_max)) {
+			i40e_pf_config_irq_link_list(vf, map);
+		} else {
+			/* configured queue size excceed limit */
+			ret = I40E_ERR_PARAM;
+			goto send_msg;
+		}
+	}
 
-	/* Don't care how the TX/RX queue mapping with this vector.
-	 * Link all VF RX queues together. Only did mapping work.
-	 * VF can disable/enable the intr by itself.
-	 */
-	i40e_vsi_queues_bind_intr(vf->vsi);
 send_msg:
 	i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP,
 							ret, NULL, 0);
-- 
1.7.7.6

^ permalink raw reply related

* A question about the function fill_vec_buf
From: wangyunjian @ 2017-01-13 10:20 UTC (permalink / raw)
  To: huawei.xie@intel.com, yuanhan.liu@linux.intel.com; +Cc: dev@dpdk.org

In function fill_vec_buf, it will happen uint32_t cast to uint16_t, when the *desc_chain_len is assigned by the len.
This maybe result in data truncation.

static inline int __attribute__((always_inline))
fill_vec_buf(struct virtio_net *dev, struct vhost_virtqueue *vq,
                                                uint32_t avail_idx, uint32_t *vec_idx,
                                                struct buf_vector *buf_vec, uint16_t *desc_chain_head,
                                                uint16_t *desc_chain_len)                                                                        --The desc_chain_len is defined uint16_t.
{
                uint16_t idx = vq->avail->ring[avail_idx & (vq->size - 1)];
                uint32_t vec_id = *vec_idx;
                uint32_t len    = 0;                                                                                                                           --The len is defined uint32_t.
                struct vring_desc *descs = vq->desc;

                *desc_chain_head = idx;
                ...

                while (1) {
                                if (unlikely(vec_id >= BUF_VECTOR_MAX || idx >= vq->size))
                                                return -1;

                                len += descs[idx].len;
                                buf_vec[vec_id].buf_addr = descs[idx].addr;
                                buf_vec[vec_id].buf_len  = descs[idx].len;
                                buf_vec[vec_id].desc_idx = idx;
                                vec_id++;

                                if ((descs[idx].flags & VRING_DESC_F_NEXT) == 0)
                                                break;

                                idx = descs[idx].next;
                }

                *desc_chain_len = len;                                                                                                             --Here, uint32_t cast to uint16_t.
                *vec_idx = vec_id;

                return 0;
}

^ permalink raw reply

* 17.05 Roadmap
From: O'Driscoll, Tim @ 2017-01-13 10:24 UTC (permalink / raw)
  To: dev@dpdk.org

Below are the features that we're planning to submit for the 17.05 release. We'll submit a patch to update the roadmap page with this info.

It would be good if others are also willing to share their plans so that we can build up a complete picture of what's planned for 17.05 and make sure there's no duplication.


Cryptodev DES SW PMD: A PMD will be added which implements an optimized software version of the DES algorithm.

Cryptodev DOCSIS BPI+: The cryptodev API will be enhanced to enable processing of packets according to the Baseline Privacy Interface Plus (BPI+) specification described in the Data-over-Cable Service Interface Specification (DOCSIS) Security Specification (http://www.cablelabs.com/wp-content/uploads/specdocs/CM-SP-SECv3.1-I06-160602.pdf). See the RFC (http://dpdk.org/ml/archives/dev/2016-December/052433.html) for further details. Support will be added to the QAT PMD for AES and DES, to the new software PMD for DES (see previous item), and to the existing AESNI_MB PMD.

Cryptodev Scheduler: This allows packets to be encrypted/decrypted in either SW or HW depending on packet size and HW utilization. Reordering will be supported so that packet order can be preserved.

Ethernet 32-bit CRC Generation: An optimized x86 library for CRC-32 will be added. A CRC may need to be generated for a downstream frame by the DOCSIS MAC layer because the CRC may be removed by the NIC or the frame may be modified by the MAC for PHS (packet header suppression). 

API to Configure Programmable Devices: More devices are now supporting programmable components, for example the Pipeline Personalization Profiles in I40E. An API will be added to allow any programmable device to be configured.

I40E Hardware QoS: Hardware QoS will be supported on the I40E. This will include Tx bandwidth control (min and max), and Rx Traffic Class assignment.

Configurable Tunnel Filters for I40E: DPDK support will be added for a new I40E admin queue which allows configuration of filter types for cloud filters.

Enable MPLS on I40E: MPLSoUDP and MPLSoGRE will be supported for I40E, including the new protocols and filtering (RSS and Flow Director), checksum offload and packet type recognition.

Software Eventdev Implementation: The libeventdev API is being added in 17.02 (http://dpdk.org/ml/archives/dev/2016-December/052877.html). A software implementation of this API will be added.

New Vhost Device Type: The vhost-user framework will be expanded so that it can support additional device types. Support for SCSI will be added initially, but block devices and other device types may be added in future.

Abstraction Layer for QoS: An abstraction layer for Quality of Service (QoS) hierarchical schedulers will be implemented. The goal of the abstraction layer is to provide a simple generic API that is agnostic of the underlying HW, SW or mixed HW-SW implementation. See the RFC (http://dpdk.org/ml/archives/dev/2016-November/050956.html) for details.

IPFIX Support: The Internet Protocol Flow Information Export (IPFIX) protocol provides network administrators with access to IP Flow information. An observation point (one for all the interfaces), metering process and an exporter process will be implemented. The observation point and metering process will be as defined in RFC 5474 (https://tools.ietf.org/html/rfc5474).

Interrupt Mode for Virtio-User: Interrupt mode support will be added for virtio-user, which is a virtual device for high performance container networking.

Automated VF Processing of PF Reset for I40E: In 16.07, changes were made for both IXGBE and I40E to notify a VF when a PF reset occurs. This will be further enhanced for I40E so that the driver handles as much of the processing as possible, including things like resetting VF ports.

Tx Buffering in Vhost PMD: Overall throughput drops as the number of guests increases on a single host.  This is because a Tx burst is spread across multiple guests, so the burst size per guest decreases as the number of guests increases. Tx buffering will be added which will increase the Tx burst size and increase performance.

Consistent PMD Batching Behaviour: PMD Tx batching behavior is not consistent between PMDs. Some PMDs have no limit for nb_pkts (besides number of available descriptors), some (like vhost) have a limit on the max number of Tx packets (32 for vhost), and some define a max burst size and transmit packets in multiple bursts up to that size. The application needs to manage these differences. To make things easier for application developers, we're considering putting the logic for managing this directly into rte_eth_tx_burst.

^ permalink raw reply

* Re: [RFC] ethdev: abstraction layer for QoS hierarchical scheduler
From: Hemant Agrawal @ 2017-01-13 10:36 UTC (permalink / raw)
  To: Cristian Dumitrescu, dev
In-Reply-To: <1480529810-95280-1-git-send-email-cristian.dumitrescu@intel.com>

On 11/30/2016 11:46 PM, Cristian Dumitrescu wrote:
> This RFC proposes an ethdev-based abstraction layer for Quality of Service (QoS)
> hierarchical scheduler. The goal of the abstraction layer is to provide a simple
> generic API that is agnostic of the underlying HW, SW or mixed HW-SW complex
> implementation.
>
> Q1: What is the benefit for having an abstraction layer for QoS hierarchical
> layer?
> A1: There is growing interest in the industry for handling various HW-based,
> SW-based or mixed hierarchical scheduler implementations using a unified DPDK
> API.
>
> Q2: Which devices are targeted by this abstraction layer?
> A2: All current and future devices that expose a hierarchical scheduler feature
> under DPDK, including NICs, FPGAs, ASICs, SOCs, SW libraries.
>
> Q3: Which scheduler hierarchies are supported by the API?
> A3: Hopefully any scheduler hierarchy can be described and covered by the
> current API. Of course, functional correctness, accuracy and performance levels
> depend on the specific implementations of this API.
>
> Q4: Why have this abstraction layer into ethdev as opposed to a new type of
> device (e.g. scheddev) similar to ethdev, cryptodev, eventdev, etc?
> A4: Packets are sent to the Ethernet device using the ethdev API
> rte_eth_tx_burst() function, with the hierarchical scheduling taking place
> automatically (i.e. no SW intervention) in HW implementations. Basically, the
> hierarchical scheduler is done as part of packet TX operation.
> The hierarchical scheduler is typically the last stage before packet TX and it
> is tightly integrated with the TX stage. The hierarchical scheduler is just
> another offload feature of the Ethernet device, which needs to be accommodated
> by the ethdev API similar to any other offload feature (such as RSS, DCB,
> flow director, etc).
> Once the decision to schedule a specific packet has been taken, this packet
> cannot be dropped and it has to be sent over the wire as is, otherwise what
> takes place on the wire is not what was planned at scheduling time, so the
> scheduling is not accurate (Note: there are some devices which allow prepending
> headers to the packet after the scheduling stage at the expense of sending
> correction requests back to the scheduler, but this only strengthens the bond
> between scheduling and TX).
>
egress QoS can be applied to a physical or a logical network device.
At present the network devices are presented as ethdev in DPDK. Even a 
logical device can also be presented by creating a new ethdev. So it 
seems to be a good idea to associate it with ethdev.


> Q5: Given that the packet scheduling takes place automatically for pure HW
> implementations, how does packet scheduling take place for poll-mode SW
> implementations?
> A5: The API provided function rte_sched_run() is designed to take care of this.
> For HW implementations, this function typically does nothing. For SW
> implementations, this function is typically expected to perform dequeue of
> packets from the hierarchical scheduler and their write to Ethernet device TX
> queue, periodic flush of any buffers on enqueue-side into the hierarchical
> scheduler for burst-oriented implementations, etc.
>

I think this is *rte_eth_sched_run* in your APIs.

It will be a no-ops for hw, how do you envision it's usages in the 
typical software. e.g. in the l3fwd application,
  - every time you do a rte_eth_tx_burst - there may be locking concern 
here.
  - creating a per port thread to continue doing rte_eth_sched_run
  - call it in one of the existing polling thread for a port.


> Q6: Which are the scheduling algorithms supported?
> A6: The fundamental scheduling algorithms that are supported are Strict Priority
> (SP) and Weighted Fair Queuing (WFQ). The SP and WFQ algorithms are supported at
> the level of each node of the scheduling hierarchy, regardless of the node
> level/position in the tree. The SP algorithm is used to schedule between sibling
> nodes with different priority, while WFQ is used to schedule between groups of
> siblings that have the same priority.
> Algorithms such as Weighed Round Robin (WRR), byte-level WRR, Deficit WRR
> (DWRR), etc are considered approximations of the ideal WFQ and are therefore
> assimilated to WFQ, although an associated implementation-dependent accuracy,
> performance and resource usage trade-off might exist.
>
> Q7: Which are the supported congestion management algorithms?
> A7: Tail drop, head drop and Weighted Random Early Detection (WRED). They are
> available for every leaf node in the hierarchy, subject to the specific
> implementation supporting them.
>
We may need to introduce some kind capability APIS. e.g. NXP HW do not 
support headdrop.

> Q8: Is traffic shaping supported?
> A8: Yes, there are a number of shapers (rate limiters) that can be supported for
> each node in the hierarchy (built-in limit is currently set to 4 per node). Each
> shaper can be private to a node (used only by that node) or shared between
> multiple nodes.
>

What do you mean by supporting 4 shaper per node? if you need more 
shapers than create new hierarchy nodes.
Also, similarly if a shaper is to be shared between two nodes, than it 
should be in parent node?
Why you want to create shaper hierarchy within a node of hierarchical 
QoS.


> Q9: What is the purpose of having shaper profiles and WRED profiles?
> A9: In most implementations, many shapers typically share the same configuration
> parameters, so defining shaper profiles simplifies the configuration task. Same
> considerations apply to WRED contexts and profiles.
>

Agree

> Q10: How is the scheduling hierarchy defined and created?
> A10: Scheduler hierarchy tree is set up by creating new nodes and connecting
> them to other existing nodes, which thus become parent nodes. The unique ID that
> is assigned to each node when the node is created is further used to update the
> node configuration or to connect children nodes to it. The leaf nodes of the
> scheduler hierarchy are each attached to one of the Ethernet device TX queues.

It may be cleaner to differentiate between a leaf (i.e. a qos_queue) and 
scheduling node.

> Q11: Are on-the-fly changes of the scheduling hierarchy allowed by the API?
> A11: Yes. The actual changes take place subject to the specific implementation
> supporting them, otherwise error code is returned.

What kind of change are you seeing here? creating new nodes/levels? 
reconnecting a node from one parent node to another?

This is more like a implementation capability.


> Q12: What is the typical function call sequence to set up and run the Ethernet
> device scheduler?
> A12: The typical simplified function call sequence is listed below:
> i) Configure the Ethernet device and its TX queues: rte_eth_dev_configure(),
> rte_eth_tx_queue_setup()
> ii) Create WRED profiles and WRED contexts, shaper profiles and shapers:
> rte_eth_sched_wred_profile_add(), rte_eth_sched_wred_context_add(),
> rte_eth_sched_shaper_profile_add(), rte_eth_sched_shaper_add()
> iii) Create the scheduler hierarchy nodes and tree: rte_eth_sched_node_add()
> iv) Freeze the start-up hierarchy and ask the device whether it supports it:
> rte_eth_sched_node_add()
> v) Start the Ethernet port: rte_eth_dev_start()
> vi) Run-time scheduler hierarchy updates: rte_eth_sched_node_add(),
> rte_eth_sched_node_<attribute>_set()
> vii) Run-time packet enqueue into the hierarchical scheduler: rte_eth_tx_burst()
> viii) Run-time support for SW poll-mode implementations (see previous answer):
> rte_sched_run()
>
> Q13: Which are the possible options for the user when the Ethernet port does not
> support the scheduling hierarchy required by the user?
> A13: The following options are available to the user:
> i) abort
> ii) try out a new hierarchy (e.g. with less leaf nodes), if acceptable
> iii) wrap the Ethernet device into a new type of Ethernet device that has a SW
> front-end implementing the hierarchical scheduler (e.g. existing DPDK library
> librte_sched); instantiate the new device type on-the-fly and check if the
> hierarchy requirements can be met by the new device.
>
>

I will like to see some kind of capability APIs upfront.

1. Number of Levels supported
2. Per level capability (capability of each level may be different)
3. - Number of nodes support at a given level
4. - Max Number of input nodes supported
5. - Type of scheduling algo supported (SP, WFQ etc)
6. - Shaper support - Dual Rate
7. - Congestion control
8. - max priorities.


> Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
> ---
>  lib/librte_ether/rte_ethdev.h | 794 ++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 794 insertions(+)
>  mode change 100644 => 100755 lib/librte_ether/rte_ethdev.h
>
> diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
> old mode 100644
> new mode 100755
> index 9678179..d4d8604
> --- a/lib/librte_ether/rte_ethdev.h
> +++ b/lib/librte_ether/rte_ethdev.h
> @@ -182,6 +182,8 @@ extern "C" {
>  #include <rte_pci.h>
>  #include <rte_dev.h>
>  #include <rte_devargs.h>
> +#include <rte_meter.h>
> +#include <rte_red.h>
>  #include "rte_ether.h"
>  #include "rte_eth_ctrl.h"
>  #include "rte_dev_info.h"
> @@ -1038,6 +1040,152 @@ TAILQ_HEAD(rte_eth_dev_cb_list, rte_eth_dev_callback);
>  /**< l2 tunnel forwarding mask */
>  #define ETH_L2_TUNNEL_FORWARDING_MASK   0x00000008
>
> +/**
> + * Scheduler configuration
> + */
> +
> +/**< Max number of shapers per node */
> +#define RTE_ETH_SCHED_SHAPERS_PER_NODE                     4
> +/**< Invalid shaper ID */
> +#define RTE_ETH_SCHED_SHAPER_ID_NONE                       UINT32_MAX
> +/**< Max number of WRED contexts per node */
> +#define RTE_ETH_SCHED_WRED_CONTEXTS_PER_NODE               4
> +/**< Invalid WRED context ID */
> +#define RTE_ETH_SCHED_WRED_CONTEXT_ID_NONE                 UINT32_MAX
> +/**< Invalid node ID */
> +#define RTE_ETH_SCHED_NODE_NULL                            UINT32_MAX
> +
> +/**
> +  * Congestion management (CMAN) mode
> +  *
> +  * This is used for controlling the admission of packets into a packet queue or
> +  * group of packet queues on congestion. On request of writing a new packet
> +  * into the current queue while the queue is full, the *tail drop* algorithm
> +  * drops the new packet while leaving the queue unmodified, as opposed to *head
> +  * drop* algorithm, which drops the packet at the head of the queue (the oldest
> +  * packet waiting in the queue) and admits the new packet at the tail of the
> +  * queue.
> +  *
> +  * The *Random Early Detection (RED)* algorithm works by proactively dropping
> +  * more and more input packets as the queue occupancy builds up. When the queue
> +  * is full or almost full, RED effectively works as *tail drop*. The *Weighted
> +  * RED* algorithm uses a separate set of RED thresholds per packet color.
> +  */
> +enum rte_eth_sched_cman_mode {
> +	RTE_ETH_SCHED_CMAN_TAIL_DROP = 0, /**< Tail drop */
> +	RTE_ETH_SCHED_CMAN_HEAD_DROP, /**< Head drop */
> +	RTE_ETH_SCHED_CMAN_WRED, /**< Weighted Random Early Detection (WRED) */
> +};
> +

you may also need parameters whether the cman is byte based or frame based.

> +/**
> +  * WRED profile
> +  */
> +struct rte_eth_sched_wred_params {
> +	/**< One set of RED parameters per packet color */
> +	struct rte_red_params red_params[e_RTE_METER_COLORS];
> +};
> +
> +/**
> +  * Shaper (rate limiter) profile
> +  *
> +  * Multiple shaper instances can share the same shaper profile. Each node can
> +  * have multiple shapers enabled (up to RTE_ETH_SCHED_SHAPERS_PER_NODE). Each
> +  * shaper can be private to a node (only one node using it) or shared (multiple
> +  * nodes use the same shaper instance).
> +  */
> +struct rte_eth_sched_shaper_params {
> +	uint64_t rate; /**< Token bucket rate (bytes per second) */
> +	uint64_t size; /**< Token bucket size (bytes) */
> +};
> +

dual rate shaper can be supported here.

I guess by size you mean the max burst size?


> +/**
> +  * Node parameters
> +  *
> +  * Each scheduler hierarchy node has multiple inputs (children nodes of the
> +  * current parent node) and a single output (which is input to its parent
> +  * node). The current node arbitrates its inputs using Strict Priority (SP)
> +  * and Weighted Fair Queuing (WFQ) algorithms to schedule input packets on its
> +  * output while observing its shaping/rate limiting constraints.  Algorithms
> +  * such as Weighted Round Robin (WRR), byte-level WRR, Deficit WRR (DWRR), etc
> +  * are considered approximations of the ideal WFQ and are assimilated to WFQ,
> +  * although an associated implementation-dependent trade-off on accuracy,
> +  * performance and resource usage might exist.
> +  *
> +  * Children nodes with different priorities are scheduled using the SP
> +  * algorithm, based on their priority, with zero (0) as the highest priority.
> +  * Children with same priority are scheduled using the WFQ algorithm, based on
> +  * their weight, which is relative to the sum of the weights of all siblings
> +  * with same priority, with one (1) as the lowest weight.
> +  */
> +struct rte_eth_sched_node_params {
> +	/**< Child node priority (used by SP). The highest priority is zero. */
> +	uint32_t priority;
> +	/**< Child node weight (used by WFQ), relative to some of weights of all
> +	     siblings with same priority). The lowest weight is one. */
> +	uint32_t weight;
> +	/**< Set of shaper instances enabled for current node. Each node shaper
> +	     can be disabled by setting it to RTE_ETH_SCHED_SHAPER_ID_NONE. */
> +	uint32_t shaper_id[RTE_ETH_SCHED_SHAPERS_PER_NODE];
> +	/**< Set to zero if current node is not a hierarchy leaf node, set to a
> +	     non-zero value otherwise. A leaf node is a hierarchy node that does
> +	     not have any children. A leaf node has to be connected to a valid
> +	     packet queue. */
> +	int is_leaf;
> +	/**< Parameters valid for leaf nodes only */
> +	struct {
> +		/**< Packet queue ID */
> +		uint64_t queue_id;
> +		/**< Congestion management mode */
> +		enum rte_eth_sched_cman_mode cman;
> +		/**< Set of WRED contexts enabled for current leaf node. Each
> +		     leaf node WRED context can be disabled by setting it to
> +		     RTE_ETH_SCHED_WRED_CONTEXT_ID_NONE. Only valid when
> +		     congestion management for current leaf node is set to WRED. */
> +		uint32_t wred_context_id[RTE_ETH_SCHED_WRED_CONTEXTS_PER_NODE];
> +	} leaf;
> +};
> +

It will be better to separate the leaf i.e. a qos_queue from a sched 
node, it will simplify.

e.g.

struct rte_eth_sched_qos_queue{
	/**< Child node priority (used by SP). The highest priority is zero. */
	uint32_t priority;
	/**< Child node weight (used by WFQ), relative to some of weights of 
all siblings with same priority). The lowest weight is one. */
	uint32_t weight;

	/**< Packet queue ID */
	uint64_t queue_id;

	/**< Congestion management params*/
	enum rte_eth_sched_cman_mode cman;
};


struct rte_eth_sched_node_params {
	/**< Child node priority (used by SP). The highest priority is zero. */
	uint32_t priority;
	/**< Child node weight (used by WFQ), relative to some of weights of 
all siblings with same priority). The lowest weight is one. */
	uint32_t weight;
	/**< Set of shaper instances enabled for current node. Each node shaper 
can be disabled by setting it to RTE_ETH_SCHED_SHAPER_ID_NONE. */
	uint32_t shaper_id;
	
	/**< WRED contexts enabled for current leaf node. Each leaf node WRED 
context can be disabled by setting it to
	     RTE_ETH_SCHED_WRED_CONTEXT_ID_NONE. Only valid when
	     congestion management for current leaf node is set to  WRED. */
	uint32_t wred_context_id;
};
sched_qos_queue (s) will be connected to schdule node.


> +/**
> +  * Node statistics counter type
> +  */
> +enum rte_eth_sched_stats_counter {
> +	/**< Number of packets scheduled from current node. */
> +	RTE_ETH_SCHED_STATS_COUNTER_N_PKTS = 1<< 0,
> +	/**< Number of bytes scheduled from current node. */
> +	RTE_ETH_SCHED_STATS_COUNTER_N_BYTES = 1 << 1,
> +	RTE_ETH_SCHED_STATS_COUNTER_N_PKTS_DROPPED = 1 << 2,
> +	RTE_ETH_SCHED_STATS_COUNTER_N_BYTES_DROPPED = 1 << 3,
> +	/**< Number of packets currently waiting in the packet queue of current
> +	     leaf node. */
> +	RTE_ETH_SCHED_STATS_COUNTER_N_PKTS_QUEUED = 1 << 4,
> +	/**< Number of bytes currently waiting in the packet queue of current
> +	     leaf node. */
> +	RTE_ETH_SCHED_STATS_COUNTER_N_BYTES_QUEUED = 1 << 5,
> +};
> +
> +/**
> +  * Node statistics counters
> +  */
> +struct rte_eth_sched_node_stats {
> +	/**< Number of packets scheduled from current node. */
> +	uint64_t n_pkts;
> +	/**< Number of bytes scheduled from current node. */
> +	uint64_t n_bytes;
> +	/**< Statistics counters for leaf nodes only */
> +	struct {
> +		/**< Number of packets dropped by current leaf node. */
> +		uint64_t n_pkts_dropped;
> +		/**< Number of bytes dropped by current leaf node. */
> +		uint64_t n_bytes_dropped;
> +		/**< Number of packets currently waiting in the packet queue of
> +		     current leaf node. */
> +		uint64_t n_pkts_queued;
> +		/**< Number of bytes currently waiting in the packet queue of
> +		     current leaf node. */
> +		uint64_t n_bytes_queued;
> +	} leaf;
> +};
> +
>  /*
>   * Definitions of all functions exported by an Ethernet driver through the
>   * the generic structure of type *eth_dev_ops* supplied in the *rte_eth_dev*
> @@ -1421,6 +1569,120 @@ typedef int (*eth_get_dcb_info)(struct rte_eth_dev *dev,
>  				 struct rte_eth_dcb_info *dcb_info);
>  /**< @internal Get dcb information on an Ethernet device */
>
> +typedef int (*eth_sched_wred_profile_add_t)(struct rte_eth_dev *dev,
> +	uint32_t wred_profile_id,
> +	struct rte_eth_sched_wred_params *profile);
> +/**< @internal Scheduler WRED profile add */
> +
> +typedef int (*eth_sched_wred_profile_delete_t)(struct rte_eth_dev *dev,
> +	uint32_t wred_profile_id);
> +/**< @internal Scheduler WRED profile delete */
> +
> +typedef int (*eth_sched_wred_context_add_t)(struct rte_eth_dev *dev,
> +	uint32_t wred_context_id,
> +	uint32_t wred_profile_id);
> +/**< @internal Scheduler WRED context add */
> +
> +typedef int (*eth_sched_wred_context_delete_t)(struct rte_eth_dev *dev,
> +	uint32_t wred_context_id);
> +/**< @internal Scheduler WRED context delete */
> +
> +typedef int (*eth_sched_shaper_profile_add_t)(struct rte_eth_dev *dev,
> +	uint32_t shaper_profile_id,
> +	struct rte_eth_sched_shaper_params *profile);
> +/**< @internal Scheduler shaper profile add */
> +
> +typedef int (*eth_sched_shaper_profile_delete_t)(struct rte_eth_dev *dev,
> +	uint32_t shaper_profile_id);
> +/**< @internal Scheduler shaper profile delete */
> +
> +typedef int (*eth_sched_shaper_add_t)(struct rte_eth_dev *dev,
> +	uint32_t shaper_id,
> +	uint32_t shaper_profile_id);
> +/**< @internal Scheduler shaper instance add */
> +
> +typedef int (*eth_sched_shaper_delete_t)(struct rte_eth_dev *dev,
> +	uint32_t shaper_id);
> +/**< @internal Scheduler shaper instance delete */
> +
> +typedef int (*eth_sched_node_add_t)(struct rte_eth_dev *dev,
> +	uint32_t node_id,
> +	uint32_t parent_node_id,
> +	struct rte_eth_sched_node_params *params);
> +/**< @internal Scheduler node add */
> +
> +typedef int (*eth_sched_node_delete_t)(struct rte_eth_dev *dev,
> +	uint32_t node_id);
> +/**< @internal Scheduler node delete */
> +
> +typedef int (*eth_sched_hierarchy_set_t)(struct rte_eth_dev *dev,
> +	int clear_on_fail);
> +/**< @internal Scheduler hierarchy set */
> +
> +typedef int (*eth_sched_node_priority_set_t)(struct rte_eth_dev *dev,
> +	uint32_t node_id,
> +	uint32_t priority);
> +/**< @internal Scheduler node priority set */
> +
> +typedef int (*eth_sched_node_weight_set_t)(struct rte_eth_dev *dev,
> +	uint32_t node_id,
> +	uint32_t weight);
> +/**< @internal Scheduler node weight set */
> +
> +typedef int (*eth_sched_node_shaper_set_t)(struct rte_eth_dev *dev,
> +	uint32_t node_id,
> +	uint32_t shaper_pos,
> +	uint32_t shaper_id);
> +/**< @internal Scheduler node shaper set */
> +
> +typedef int (*eth_sched_node_queue_set_t)(struct rte_eth_dev *dev,
> +	uint32_t node_id,
> +	uint32_t queue_id);
> +/**< @internal Scheduler node queue set */
> +
> +typedef int (*eth_sched_node_cman_set_t)(struct rte_eth_dev *dev,
> +	uint32_t node_id,
> +	enum rte_eth_sched_cman_mode cman);
> +/**< @internal Scheduler node congestion management mode set */
> +
> +typedef int (*eth_sched_node_wred_context_set_t)(struct rte_eth_dev *dev,
> +	uint32_t node_id,
> +	uint32_t wred_context_pos,
> +	uint32_t wred_context_id);
> +/**< @internal Scheduler node WRED context set */
> +
> +typedef int (*eth_sched_stats_get_enabled_t)(struct rte_eth_dev *dev,
> +	uint64_t *nonleaf_node_capability_stats_mask,
> +	uint64_t *nonleaf_node_enabled_stats_mask,
> +	uint64_t *leaf_node_capability_stats_mask,
> +	uint64_t *leaf_node_enabled_stats_mask);
> +/**< @internal Scheduler get set of stats counters enabled for all nodes */
> +
> +typedef int (*eth_sched_stats_enable_t)(struct rte_eth_dev *dev,
> +	uint64_t nonleaf_node_enabled_stats_mask,
> +	uint64_t leaf_node_enabled_stats_mask);
> +/**< @internal Scheduler enable selected stats counters for all nodes */
> +
> +typedef int (*eth_sched_node_stats_get_enabled_t)(struct rte_eth_dev *dev,
> +	uint32_t node_id,
> +	uint64_t *capability_stats_mask,
> +	uint64_t *enabled_stats_mask);
> +/**< @internal Scheduler get set of stats counters enabled for specific node */
> +
> +typedef int (*eth_sched_node_stats_enable_t)(struct rte_eth_dev *dev,
> +	uint32_t node_id,
> +	uint64_t enabled_stats_mask);
> +/**< @internal Scheduler enable selected stats counters for specific node */
> +
> +typedef int (*eth_sched_node_stats_read_t)(struct rte_eth_dev *dev,
> +	uint32_t node_id,
> +	struct rte_eth_sched_node_stats *stats,
> +	int clear);
> +/**< @internal Scheduler read stats counters for specific node */
> +
> +typedef int (*eth_sched_run_t)(struct rte_eth_dev *dev);
> +/**< @internal Scheduler run */
> +
>  /**
>   * @internal A structure containing the functions exported by an Ethernet driver.
>   */
> @@ -1547,6 +1809,53 @@ struct eth_dev_ops {
>  	eth_l2_tunnel_eth_type_conf_t l2_tunnel_eth_type_conf;
>  	/** Enable/disable l2 tunnel offload functions */
>  	eth_l2_tunnel_offload_set_t l2_tunnel_offload_set;
> +
> +	/** Scheduler WRED profile add */
> +	eth_sched_wred_profile_add_t sched_wred_profile_add;
> +	/** Scheduler WRED profile delete */
> +	eth_sched_wred_profile_delete_t sched_wred_profile_delete;
> +	/** Scheduler WRED context add */
> +	eth_sched_wred_context_add_t sched_wred_context_add;
> +	/** Scheduler WRED context delete */
> +	eth_sched_wred_context_delete_t sched_wred_context_delete;
> +	/** Scheduler shaper profile add */
> +	eth_sched_shaper_profile_add_t sched_shaper_profile_add;
> +	/** Scheduler shaper profile delete */
> +	eth_sched_shaper_profile_delete_t sched_shaper_profile_delete;
> +	/** Scheduler shaper instance add */
> +	eth_sched_shaper_add_t sched_shaper_add;
> +	/** Scheduler shaper instance delete */
> +	eth_sched_shaper_delete_t sched_shaper_delete;
> +	/** Scheduler node add */
> +	eth_sched_node_add_t sched_node_add;
> +	/** Scheduler node delete */
> +	eth_sched_node_delete_t sched_node_delete;
> +	/** Scheduler hierarchy set */
> +	eth_sched_hierarchy_set_t sched_hierarchy_set;
> +	/** Scheduler node priority set */
> +	eth_sched_node_priority_set_t sched_node_priority_set;
> +	/** Scheduler node weight set */
> +	eth_sched_node_weight_set_t sched_node_weight_set;
> +	/** Scheduler node shaper set */
> +	eth_sched_node_shaper_set_t sched_node_shaper_set;
> +	/** Scheduler node queue set */
> +	eth_sched_node_queue_set_t sched_node_queue_set;
> +	/** Scheduler node congestion management mode set */
> +	eth_sched_node_cman_set_t sched_node_cman_set;
> +	/** Scheduler node WRED context set */
> +	eth_sched_node_wred_context_set_t sched_node_wred_context_set;
> +	/** Scheduler get statistics counter type enabled for all nodes */
> +	eth_sched_stats_get_enabled_t sched_stats_get_enabled;
> +	/** Scheduler enable selected statistics counters for all nodes */
> +	eth_sched_stats_enable_t sched_stats_enable;
> +	/** Scheduler get statistics counter type enabled for current node */
> +	eth_sched_node_stats_get_enabled_t sched_node_stats_get_enabled;
> +	/** Scheduler enable selected statistics counters for current node */
> +	eth_sched_node_stats_enable_t sched_node_stats_enable;
> +	/** Scheduler read statistics counters for current node */
> +	eth_sched_node_stats_read_t sched_node_stats_read;
> +	/** Scheduler run */
> +	eth_sched_run_t sched_run;
>  };
>
>  /**
> @@ -4336,6 +4645,491 @@ rte_eth_dev_l2_tunnel_offload_set(uint8_t port_id,
>  				  uint8_t en);
>
>  /**
> + * Scheduler WRED profile add
> + *
> + * Create a new WRED profile with ID set to *wred_profile_id*. The new profile
> + * is used to create one or several WRED contexts.
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param wred_profile_id
> + *   WRED profile ID for the new profile. Needs to be unused.
> + * @param profile
> + *   WRED profile parameters. Needs to be pre-allocated and valid.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int rte_eth_sched_wred_profile_add(uint8_t port_id,
> +	uint32_t wred_profile_id,
> +	struct rte_eth_sched_wred_params *profile);
> +
> +/**
> + * Scheduler WRED profile delete
> + *
> + * Delete an existing WRED profile. This operation fails when there is currently
> + * at least one user (i.e. WRED context) of this WRED profile.
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param wred_profile_id
> + *   WRED profile ID. Needs to be the valid.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int rte_eth_sched_wred_profile_delete(uint8_t port_id,
> +	uint32_t wred_profile_id);
> +
> +/**
> + * Scheduler WRED context add or update
> + *
> + * When *wred_context_id* is invalid, a new WRED context with this ID is created
> + * by using the WRED profile identified by *wred_profile_id*.
> + *
> + * When *wred_context_id* is valid, this WRED context is no longer using the
> + * profile previously assigned to it and is updated to use the profile
> + * identified by *wred_profile_id*.
> + *
> + * A valid WRED context is assigned to one or several scheduler hierarchy leaf
> + * nodes configured to use WRED as the congestion management mode.
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param wred_context_id
> + *   WRED context ID
> + * @param wred_profile_id
> + *   WRED profile ID. Needs to be the valid.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int rte_eth_sched_wred_context_add(uint8_t port_id,
> +	uint32_t wred_context_id,
> +	uint32_t wred_profile_id);
> +
> +/**
> + * Scheduler WRED context delete
> + *
> + * Delete an existing WRED context. This operation fails when there is currently
> + * at least one user (i.e. scheduler hierarchy leaf node) of this WRED context.
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param wred_context_id
> + *   WRED context ID. Needs to be the valid.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int rte_eth_sched_wred_context_delete(uint8_t port_id,
> +	uint32_t wred_context_id);
> +
> +/**
> + * Scheduler shaper profile add
> + *
> + * Create a new shaper profile with ID set to *shaper_profile_id*. The new
> + * shaper profile is used to create one or several shapers.
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param shaper_profile_id
> + *   Shaper profile ID for the new profile. Needs to be unused.
> + * @param profile
> + *   Shaper profile parameters. Needs to be pre-allocated and valid.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int rte_eth_sched_shaper_profile_add(uint8_t port_id,
> +	uint32_t shaper_profile_id,
> +	struct rte_eth_sched_shaper_params *profile);
> +
> +/**
> + * Scheduler shaper profile delete
> + *
> + * Delete an existing shaper profile. This operation fails when there is
> + * currently at least one user (i.e. shaper) of this shaper profile.
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param shaper_profile_id
> + *   Shaper profile ID. Needs to be the valid.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +/* no users (shapers) using this profile */
> +int rte_eth_sched_shaper_profile_delete(uint8_t port_id,
> +	uint32_t shaper_profile_id);
> +
> +/**
> + * Scheduler shaper add or update
> + *
> + * When *shaper_id* is not a valid shaper ID, a new shaper with this ID is
> + * created using the shaper profile identified by *shaper_profile_id*.
> + *
> + * When *shaper_id* is a valid shaper ID, this shaper is no longer using the
> + * shaper profile previously assigned to it and is updated to use the shaper
> + * profile identified by *shaper_profile_id*.
> + *
> + * A valid shaper is assigned to one or several scheduler hierarchy nodes.
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param shaper_id
> + *   Shaper ID
> + * @param shaper_profile_id
> + *   Shaper profile ID. Needs to be the valid.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int rte_eth_sched_shaper_add(uint8_t port_id,
> +	uint32_t shaper_id,
> +	uint32_t shaper_profile_id);
> +
> +/**
> + * Scheduler shaper delete
> + *
> + * Delete an existing shaper. This operation fails when there is currently at
> + * least one user (i.e. scheduler hierarchy node) of this shaper.
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param shaper_id
> + *   Shaper ID. Needs to be the valid.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int rte_eth_sched_shaper_delete(uint8_t port_id,
> +	uint32_t shaper_id);
> +
> +/**
> + * Scheduler node add or remap
> + *
> + * When *node_id* is not a valid node ID, a new node with this ID is created and
> + * connected as child to the existing node identified by *parent_node_id*.
> + *
> + * When *node_id* is a valid node ID, this node is disconnected from its current
> + * parent and connected as child to another existing node identified by
> + * *parent_node_id *.
> + *
> + * This function can be called during port initialization phase (before the
> + * Ethernet port is started) for building the scheduler start-up hierarchy.
> + * Subject to the specific Ethernet port supporting on-the-fly scheduler
> + * hierarchy updates, this function can also be called during run-time (after
> + * the Ethernet port is started).
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param node_id
> + *   Node ID
> + * @param parent_node_id
> + *   Parent node ID. Needs to be the valid.
> + * @param params
> + *   Node parameters. Needs to be pre-allocated and valid.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int rte_eth_sched_node_add(uint8_t port_id,
> +	uint32_t node_id,
> +	uint32_t parent_node_id,
> +	struct rte_eth_sched_node_params *params);
> +
> +/**
> + * Scheduler node delete
> + *
> + * Delete an existing node. This operation fails when this node currently has at
> + * least one user (i.e. child node).
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param node_id
> + *   Node ID. Needs to be valid.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int rte_eth_sched_node_delete(uint8_t port_id,
> +	uint32_t node_id);
> +
> +/**
> + * Scheduler hierarchy set
> + *
> + * This function is called during the port initialization phase (before the
> + * Ethernet port is started) to freeze the scheduler start-up hierarchy.
> + *
> + * This function fails when the currently configured scheduler hierarchy is not
> + * supported by the Ethernet port, in which case the user can abort or try out
> + * another hierarchy configuration (e.g. a hierarchy with less leaf nodes),
> + * which can be build from scratch (when *clear_on_fail* is enabled) or by
> + * modifying the existing hierarchy configuration (when *clear_on_fail* is
> + * disabled).
> + *
> + * Note that, even when the configured scheduler hierarchy is supported (so this
> + * function is successful), the Ethernet port start might still fail due to e.g.
> + * not enough memory being available in the system, etc.
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param clear_on_fail
> + *   On function call failure, hierarchy is cleared when this parameter is
> + *   non-zero and preserved when this parameter is equal to zero.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int rte_eth_sched_hierarchy_set(uint8_t port_id,
> +	int clear_on_fail);
> +
> +/**
> + * Scheduler node priority set
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param node_id
> + *   Node ID. Needs to be valid.
> + * @param priority
> + *   Node priority. The highest node priority is zero. Used by the SP algorithm
> + *   running on the parent of the current node for scheduling this child node.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int rte_eth_sched_node_priority_set(uint8_t port_id,
> +	uint32_t node_id,
> +	uint32_t priority);
> +
> +/**
> + * Scheduler node weight set
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param node_id
> + *   Node ID. Needs to be valid.
> + * @param weight
> + *   Node weight. The node weight is relative to the weight sum of all siblings
> + *   that have the same priority. The lowest weight is zero. Used by the WFQ
> + *   algorithm running on the parent of the current node for scheduling this
> + *   child node.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int rte_eth_sched_node_weight_set(uint8_t port_id,
> +	uint32_t node_id,
> +	uint32_t weight);
> +
> +/**
> + * Scheduler node shaper set
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param node_id
> + *   Node ID. Needs to be valid.
> + * @param shaper_pos
> + *   Position in the shaper array of the current node
> + *   (0 .. RTE_ETH_SCHED_SHAPERS_PER_NODE-1).
> + * @param shaper_id
> + *   Shaper ID. Needs to be either valid shaper ID or set to
> + *   RTE_ETH_SCHED_SHAPER_ID_NONE in order to invalidate the shaper on position
> + *   *shaper_pos* within the current node.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int rte_eth_sched_node_shaper_set(uint8_t port_id,
> +	uint32_t node_id,
> +	uint32_t shaper_pos,
> +	uint32_t shaper_id);
> +
> +/**
> + * Scheduler node queue set
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param node_id
> + *   Node ID. Needs to be valid.
> + * @param queue_id
> + *   Queue ID. Needs to be valid.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int rte_eth_sched_node_queue_set(uint8_t port_id,
> +	uint32_t node_id,
> +	uint32_t queue_id);
> +
> +/**
> + * Scheduler node congestion management mode set
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param node_id
> + *   Node ID. Needs to be valid leaf node ID.
> + * @param cman
> + *   Congestion management mode.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int rte_eth_sched_node_cman_set(uint8_t port_id,
> +	uint32_t node_id,
> +	enum rte_eth_sched_cman_mode cman);
> +
> +/**
> + * Scheduler node WRED context set
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param node_id
> + *   Node ID. Needs to be valid leaf node ID that has WRED selected as the
> + *   congestion management mode.
> + * @param wred_context_pos
> + *   Position in the WRED context array of the current leaf node
> + *   (0 .. RTE_ETH_SCHED_WRED_CONTEXTS_PER_NODE-1)
> + * @param wred_context_id
> + *   WRED context ID. Needs to be either valid WRED context ID or set to
> + *   RTE_ETH_SCHED_WRED_CONTEXT_ID_NONE in order to invalidate the WRED context
> + *   on position *wred_context_pos* within the current leaf node.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int rte_eth_sched_node_wred_context_set(uint8_t port_id,
> +	uint32_t node_id,
> +	uint32_t wred_context_pos,
> +	uint32_t wred_context_id);
> +
> +/**
> + * Scheduler get statistics counter types enabled for all nodes
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param nonleaf_node_capability_stats_mask
> + *   Statistics counter types available per node for all non-leaf nodes. Needs
> + *   to be pre-allocated.
> + * @param nonleaf_node_enabled_stats_mask
> + *   Statistics counter types currently enabled per node for each non-leaf node.
> + *   This is a subset of *nonleaf_node_capability_stats_mask*. Needs to be
> + *   pre-allocated.
> + * @param leaf_node_capability_stats_mask
> + *   Statistics counter types available per node for all leaf nodes. Needs to
> + *   be pre-allocated.
> + * @param leaf_node_enabled_stats_mask
> + *   Statistics counter types currently enabled for each leaf node. This is
> + *   a subset of *leaf_node_capability_stats_mask*. Needs to be pre-allocated.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int rte_eth_sched_stats_get_enabled(uint8_t port_id,
> +	uint64_t *nonleaf_node_capability_stats_mask,
> +	uint64_t *nonleaf_node_enabled_stats_mask,
> +	uint64_t *leaf_node_capability_stats_mask,
> +	uint64_t *leaf_node_enabled_stats_mask);
> +
> +/**
> + * Scheduler enable selected statistics counters for all nodes
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param nonleaf_node_enabled_stats_mask
> + *   Statistics counter types to be enabled per node for each non-leaf node.
> + *   This needs to be a subset of the statistics counter types available per
> + *   node for all non-leaf nodes. Any statistics counter type not included in
> + *   this set is to be disabled for all non-leaf nodes.
> + * @param leaf_node_enabled_stats_mask
> + *   Statistics counter types to be enabled per node for each leaf node. This
> + *   needs to be a subset of the statistics counter types available per node for
> + *   all leaf nodes. Any statistics counter type not included in this set is to
> + *   be disabled for all leaf nodes.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int rte_eth_sched_stats_enable(uint8_t port_id,
> +	uint64_t nonleaf_node_enabled_stats_mask,
> +	uint64_t leaf_node_enabled_stats_mask);
> +
> +/**
> + * Scheduler get statistics counter types enabled for current node
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param node_id
> + *   Node ID. Needs to be valid.
> + * @param capability_stats_mask
> + *   Statistics counter types available for the current node. Needs to be pre-allocated.
> + * @param enabled_stats_mask
> + *   Statistics counter types currently enabled for the current node. This is
> + *   a subset of *capability_stats_mask*. Needs to be pre-allocated.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int rte_eth_sched_node_stats_get_enabled(uint8_t port_id,
> +	uint32_t node_id,
> +	uint64_t *capability_stats_mask,
> +	uint64_t *enabled_stats_mask);
> +
> +/**
> + * Scheduler enable selected statistics counters for current node
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param node_id
> + *   Node ID. Needs to be valid.
> + * @param enabled_stats_mask
> + *   Statistics counter types to be enabled for the current node. This needs to
> + *   be a subset of the statistics counter types available for the current node.
> + *   Any statistics counter type not included in this set is to be disabled for
> + *   the current node.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int rte_eth_sched_node_stats_enable(uint8_t port_id,
> +	uint32_t node_id,
> +	uint64_t enabled_stats_mask);
> +
> +/**
> + * Scheduler node statistics counters read
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param node_id
> + *   Node ID. Needs to be valid.
> + * @param stats
> + *   When non-NULL, it contains the current value for the statistics counters
> + *   enabled for the current node.
> + * @param clear
> + *   When this parameter has a non-zero value, the statistics counters are
> + *   cleared (i.e. set to zero) immediately after they have been read, otherwise
> + *   the statistics counters are left untouched.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int rte_eth_sched_node_stats_read(uint8_t port_id,
> +	uint32_t node_id,
> +	struct rte_eth_sched_node_stats *stats,
> +	int clear);
> +
> +/**
> + * Scheduler run
> + *
> + * The packet enqueue side of the scheduler hierarchy is typically done through
> + * the Ethernet device TX function. For HW implementations, the packet dequeue
> + * side is typically done by the Ethernet device without any SW intervention,
> + * therefore this functions should not do anything.
> + *
> + * However, for poll-mode SW or mixed HW-SW implementations, the SW intervention
> + * is likely to be required for running the packet dequeue side of the scheduler
> + * hierarchy. Other potential task performed by this function is periodic flush
> + * of any packet enqueue-side buffers used by the burst-mode implementations.
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +static inline int
> +rte_eth_sched_run(uint8_t port_id)
> +{
> +	struct rte_eth_dev *dev;
> +
> +#ifdef RTE_LIBRTE_ETHDEV_DEBUG
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, 0);
> +#endif
> +
> +	dev = &rte_eth_devices[port_id];
> +
> +	return (dev->dev_ops->sched_run)? dev->dev_ops->sched_run(dev) : 0;
> +}
> +
> +/**
>  * Get the port id from pci adrress or device name
>  * Ex: 0000:2:00.0 or vdev name net_pcap0
>  *
>

^ permalink raw reply

* Re: [PATCH v3 25/29] net/nfp: use eal I/O device memory read/write API
From: Alejandro Lucero @ 2017-01-13 10:49 UTC (permalink / raw)
  To: Jerin Jacob
  Cc: dev, Ananyev, Konstantin, Thomas Monjalon, Bruce Richardson,
	jianbo.liu, Jan Viktorin, santosh.shukla
In-Reply-To: <20170112134022.GA11933@localhost.localdomain>

Thanks for that repo. It really makes things easier.

I have run our NFP PMD unit tests using that repo, and this change seems to
work without no problem.

Thanks again.



On Thu, Jan 12, 2017 at 1:40 PM, Jerin Jacob <jerin.jacob@caviumnetworks.com
> wrote:

> On Thu, Jan 12, 2017 at 10:53:17AM +0000, Alejandro Lucero wrote:
> > Hi,
> >
> > I've tried to find out which dpdk repo should I use for testing this
> change
> > with NFP PMD.
> >
> > It seems rte_read/write functions are not with last dpdk main repo, nor
> > with dpdk-net-next.
> >
> > Can someone tell me which repo should I use?
>
> It is based on the dpdk main repo. This patchset has 29 patches. The
> initial
> patches in the series contains the definition of rte_read/write.
>
> I have created a temporary branch in public repo to make other users to
> test the changes without applying all patches.
>
> https://github.com/jerinjacobk/dpdk.git
> branch: rte_io_v3
> It is based on today's dpdk master and this patchset.
>
>

^ permalink raw reply

* Re: [PATCH v3 25/29] net/nfp: use eal I/O device memory read/write API
From: Jerin Jacob @ 2017-01-13 10:57 UTC (permalink / raw)
  To: Alejandro Lucero
  Cc: dev, Ananyev, Konstantin, Thomas Monjalon, Bruce Richardson,
	jianbo.liu, Jan Viktorin, santosh.shukla
In-Reply-To: <CAD+H991UGEHiRn69drAJNFR9JBCQx4FaPZKXzwd=+E5Pkbkymg@mail.gmail.com>

On Fri, Jan 13, 2017 at 10:49:15AM +0000, Alejandro Lucero wrote:
> Thanks for that repo. It really makes things easier.
> 
> I have run our NFP PMD unit tests using that repo, and this change seems to
> work without no problem.
> 
> Thanks again.

Thanks Alejandro. Can I add you Acked by on your NFP PMD specific
change.i.e only for this patch([PATCH v3 25/29] net/nfp: use eal I/O device memory read/write API)

> 
> 
> 
> On Thu, Jan 12, 2017 at 1:40 PM, Jerin Jacob <jerin.jacob@caviumnetworks.com
> > wrote:
> 
> > On Thu, Jan 12, 2017 at 10:53:17AM +0000, Alejandro Lucero wrote:
> > > Hi,
> > >
> > > I've tried to find out which dpdk repo should I use for testing this
> > change
> > > with NFP PMD.
> > >
> > > It seems rte_read/write functions are not with last dpdk main repo, nor
> > > with dpdk-net-next.
> > >
> > > Can someone tell me which repo should I use?
> >
> > It is based on the dpdk main repo. This patchset has 29 patches. The
> > initial
> > patches in the series contains the definition of rte_read/write.
> >
> > I have created a temporary branch in public repo to make other users to
> > test the changes without applying all patches.
> >
> > https://github.com/jerinjacobk/dpdk.git
> > branch: rte_io_v3
> > It is based on today's dpdk master and this patchset.
> >
> >

^ permalink raw reply

* [PATCH v7 0/6] Add MACsec offload support for ixgbe
From: Tiwei Bie @ 2017-01-13 11:02 UTC (permalink / raw)
  To: dev
  Cc: adrien.mazarguil, wenzhuo.lu, john.mcnamara, olivier.matz,
	thomas.monjalon, konstantin.ananyev, helin.zhang, wei.dai,
	xiao.w.wang
In-Reply-To: <1484100375-124527-1-git-send-email-tiwei.bie@intel.com>

This patch set adds the MACsec offload support for ixgbe.
The testpmd is also updated to support MACsec cmds.

v2:
- Update the documents for testpmd;
- Update the release notes;
- Reuse the functions provided by base code;

v3:
- Add the missing parts of MACsec mbuf flag and reorganize the patch set;
- Add an ethdev event type for MACsec;
- Advertise the MACsec offload capabilities based on the mac type;
- Minor fixes and improvements;

v4:
- Reserve bits in mbuf and ethdev for PMD specific API;
- Use the reserved bits in PMD specific API;

v5:
- Add MACsec offload in the NIC feature list;
- Minor improvements on comments;

v6:
- Revert the changes related to the reserved flags;
- Rebase the patch set on the latest branch, xstats code is changed recently;
- Update the feature list when adding the MACsec support for ixgbe;

v7:
- Fix clang build;

Tiwei Bie (6):
  mbuf: add flag for MACsec
  ethdev: add event type for MACsec
  ethdev: add MACsec offload capability flags
  net/ixgbe: add MACsec offload support
  app/testpmd: add MACsec offload commands
  doc: add ixgbe specific APIs

 app/test-pmd/cmdline.c                      | 389 ++++++++++++++++++++++
 app/test-pmd/macfwd.c                       |   2 +
 app/test-pmd/macswap.c                      |   2 +
 app/test-pmd/testpmd.h                      |   2 +
 app/test-pmd/txonly.c                       |   2 +
 doc/guides/nics/features/default.ini        |   1 +
 doc/guides/nics/features/ixgbe.ini          |   1 +
 doc/guides/rel_notes/release_17_02.rst      |  10 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  32 ++
 drivers/net/ixgbe/ixgbe_ethdev.c            | 482 +++++++++++++++++++++++++++-
 drivers/net/ixgbe/ixgbe_ethdev.h            |  45 +++
 drivers/net/ixgbe/ixgbe_rxtx.c              |   3 +
 drivers/net/ixgbe/rte_pmd_ixgbe.h           | 100 ++++++
 drivers/net/ixgbe/rte_pmd_ixgbe_version.map |  11 +
 lib/librte_ether/rte_ethdev.h               |   3 +
 lib/librte_mbuf/rte_mbuf.c                  |   2 +
 lib/librte_mbuf/rte_mbuf.h                  |   6 +
 17 files changed, 1088 insertions(+), 5 deletions(-)

-- 
2.7.4

^ permalink raw reply

* [PATCH v7 1/6] mbuf: add flag for MACsec
From: Tiwei Bie @ 2017-01-13 11:02 UTC (permalink / raw)
  To: dev
  Cc: adrien.mazarguil, wenzhuo.lu, john.mcnamara, olivier.matz,
	thomas.monjalon, konstantin.ananyev, helin.zhang, wei.dai,
	xiao.w.wang
In-Reply-To: <1484305346-157143-1-git-send-email-tiwei.bie@intel.com>

Add a new Tx flag in mbuf, that can be set by applications to
enable the MACsec offload for a packet to be transmitted.

Signed-off-by: Tiwei Bie <tiwei.bie@intel.com>
Acked-by: Olivier Matz <olivier.matz@6wind.com>
---
 doc/guides/rel_notes/release_17_02.rst | 5 +++++
 lib/librte_mbuf/rte_mbuf.c             | 2 ++
 lib/librte_mbuf/rte_mbuf.h             | 6 ++++++
 3 files changed, 13 insertions(+)

diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst
index 180af82..3958714 100644
--- a/doc/guides/rel_notes/release_17_02.rst
+++ b/doc/guides/rel_notes/release_17_02.rst
@@ -52,6 +52,11 @@ New Features
   See the :ref:`Generic flow API <Generic_flow_API>` documentation for more
   information.
 
+* **Improved offload support in mbuf.**
+
+  Added a new Tx mbuf flag for MACsec, which can be set by applications
+  to enable the MACsec offload for the packets to be transmitted.
+
 
 Resolved Issues
 ---------------
diff --git a/lib/librte_mbuf/rte_mbuf.c b/lib/librte_mbuf/rte_mbuf.c
index 63f43c8..72ad91e 100644
--- a/lib/librte_mbuf/rte_mbuf.c
+++ b/lib/librte_mbuf/rte_mbuf.c
@@ -404,6 +404,7 @@ const char *rte_get_tx_ol_flag_name(uint64_t mask)
 	case PKT_TX_TUNNEL_GRE: return "PKT_TX_TUNNEL_GRE";
 	case PKT_TX_TUNNEL_IPIP: return "PKT_TX_TUNNEL_IPIP";
 	case PKT_TX_TUNNEL_GENEVE: return "PKT_TX_TUNNEL_GENEVE";
+	case PKT_TX_MACSEC: return "PKT_TX_MACSEC";
 	default: return NULL;
 	}
 }
@@ -434,6 +435,7 @@ rte_get_tx_ol_flag_list(uint64_t mask, char *buf, size_t buflen)
 		  "PKT_TX_TUNNEL_NONE" },
 		{ PKT_TX_TUNNEL_GENEVE, PKT_TX_TUNNEL_MASK,
 		  "PKT_TX_TUNNEL_NONE" },
+		{ PKT_TX_MACSEC, PKT_TX_MACSEC, NULL },
 	};
 	const char *name;
 	unsigned int i;
diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
index 4476d75..ffbb4b3 100644
--- a/lib/librte_mbuf/rte_mbuf.h
+++ b/lib/librte_mbuf/rte_mbuf.h
@@ -182,6 +182,12 @@ extern "C" {
 /* add new TX flags here */
 
 /**
+ * Offload the MACsec. This flag must be set by the application to enable
+ * this offload feature for a packet to be transmitted.
+ */
+#define PKT_TX_MACSEC        (1ULL << 44)
+
+/**
  * Bits 45:48 used for the tunnel type.
  * When doing Tx offload like TSO or checksum, the HW needs to configure the
  * tunnel type into the HW descriptors.
-- 
2.7.4

^ permalink raw reply related

* [PATCH v7 2/6] ethdev: add event type for MACsec
From: Tiwei Bie @ 2017-01-13 11:02 UTC (permalink / raw)
  To: dev
  Cc: adrien.mazarguil, wenzhuo.lu, john.mcnamara, olivier.matz,
	thomas.monjalon, konstantin.ananyev, helin.zhang, wei.dai,
	xiao.w.wang
In-Reply-To: <1484305346-157143-1-git-send-email-tiwei.bie@intel.com>

This commit adds a below event type:

- RTE_ETH_EVENT_MACSEC

This event will occur when the PN counter in a MACsec connection
reaches the exhaustion threshold.

Signed-off-by: Tiwei Bie <tiwei.bie@intel.com>
---
 lib/librte_ether/rte_ethdev.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 1c356c1..d5d2956 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -3188,6 +3188,7 @@ enum rte_eth_event_type {
 	RTE_ETH_EVENT_INTR_RESET,
 			/**< reset interrupt event, sent to VF on PF reset */
 	RTE_ETH_EVENT_VF_MBOX,  /**< message from the VF received by PF */
+	RTE_ETH_EVENT_MACSEC,   /**< MACsec offload related event */
 	RTE_ETH_EVENT_MAX       /**< max value of this enum */
 };
 
-- 
2.7.4

^ permalink raw reply related

* [PATCH v7 3/6] ethdev: add MACsec offload capability flags
From: Tiwei Bie @ 2017-01-13 11:02 UTC (permalink / raw)
  To: dev
  Cc: adrien.mazarguil, wenzhuo.lu, john.mcnamara, olivier.matz,
	thomas.monjalon, konstantin.ananyev, helin.zhang, wei.dai,
	xiao.w.wang
In-Reply-To: <1484305346-157143-1-git-send-email-tiwei.bie@intel.com>

If these flags are advertised by a PMD, the NIC supports the MACsec
offload. The incoming MACsec traffics can be offloaded transparently
after the MACsec offload is configured correctly by the application.
And the application can set the PKT_TX_MACSEC flag in mbufs to enable
the MACsec offload for the packets to be transmitted.

Signed-off-by: Tiwei Bie <tiwei.bie@intel.com>
---
 lib/librte_ether/rte_ethdev.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index d5d2956..49c073b 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -881,6 +881,7 @@ struct rte_eth_conf {
 #define DEV_RX_OFFLOAD_TCP_LRO     0x00000010
 #define DEV_RX_OFFLOAD_QINQ_STRIP  0x00000020
 #define DEV_RX_OFFLOAD_OUTER_IPV4_CKSUM 0x00000040
+#define DEV_RX_OFFLOAD_MACSEC_STRIP     0x00000080
 
 /**
  * TX offload capabilities of a device.
@@ -898,6 +899,7 @@ struct rte_eth_conf {
 #define DEV_TX_OFFLOAD_GRE_TNL_TSO      0x00000400    /**< Used for tunneling packet. */
 #define DEV_TX_OFFLOAD_IPIP_TNL_TSO     0x00000800    /**< Used for tunneling packet. */
 #define DEV_TX_OFFLOAD_GENEVE_TNL_TSO   0x00001000    /**< Used for tunneling packet. */
+#define DEV_TX_OFFLOAD_MACSEC_INSERT    0x00002000
 
 /**
  * Ethernet device information
-- 
2.7.4

^ permalink raw reply related

* [PATCH v7 4/6] net/ixgbe: add MACsec offload support
From: Tiwei Bie @ 2017-01-13 11:02 UTC (permalink / raw)
  To: dev
  Cc: adrien.mazarguil, wenzhuo.lu, john.mcnamara, olivier.matz,
	thomas.monjalon, konstantin.ananyev, helin.zhang, wei.dai,
	xiao.w.wang
In-Reply-To: <1484305346-157143-1-git-send-email-tiwei.bie@intel.com>

MACsec (or LinkSec, 802.1AE) is a MAC level encryption/authentication
scheme defined in IEEE 802.1AE that uses symmetric cryptography.
This commit adds the MACsec offload support for ixgbe.

Signed-off-by: Tiwei Bie <tiwei.bie@intel.com>
Acked-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 doc/guides/nics/features/default.ini        |   1 +
 doc/guides/nics/features/ixgbe.ini          |   1 +
 drivers/net/ixgbe/ixgbe_ethdev.c            | 482 +++++++++++++++++++++++++++-
 drivers/net/ixgbe/ixgbe_ethdev.h            |  45 +++
 drivers/net/ixgbe/ixgbe_rxtx.c              |   3 +
 drivers/net/ixgbe/rte_pmd_ixgbe.h           | 100 ++++++
 drivers/net/ixgbe/rte_pmd_ixgbe_version.map |  11 +
 7 files changed, 638 insertions(+), 5 deletions(-)

diff --git a/doc/guides/nics/features/default.ini b/doc/guides/nics/features/default.ini
index f1bf9bf..c412d6f 100644
--- a/doc/guides/nics/features/default.ini
+++ b/doc/guides/nics/features/default.ini
@@ -43,6 +43,7 @@ VLAN offload         =
 QinQ offload         =
 L3 checksum offload  =
 L4 checksum offload  =
+MACsec offload       =
 Inner L3 checksum    =
 Inner L4 checksum    =
 Packet type parsing  =
diff --git a/doc/guides/nics/features/ixgbe.ini b/doc/guides/nics/features/ixgbe.ini
index 4a5667f..24c02fb 100644
--- a/doc/guides/nics/features/ixgbe.ini
+++ b/doc/guides/nics/features/ixgbe.ini
@@ -36,6 +36,7 @@ VLAN offload         = Y
 QinQ offload         = Y
 L3 checksum offload  = Y
 L4 checksum offload  = Y
+MACsec offload       = Y
 Inner L3 checksum    = Y
 Inner L4 checksum    = Y
 Packet type parsing  = Y
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index b7415e8..08f4449 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -231,6 +231,7 @@ static int ixgbe_dev_rss_reta_query(struct rte_eth_dev *dev,
 			uint16_t reta_size);
 static void ixgbe_dev_link_status_print(struct rte_eth_dev *dev);
 static int ixgbe_dev_lsc_interrupt_setup(struct rte_eth_dev *dev);
+static int ixgbe_dev_macsec_interrupt_setup(struct rte_eth_dev *dev);
 static int ixgbe_dev_rxq_interrupt_setup(struct rte_eth_dev *dev);
 static int ixgbe_dev_interrupt_get_status(struct rte_eth_dev *dev);
 static int ixgbe_dev_interrupt_action(struct rte_eth_dev *dev,
@@ -747,6 +748,51 @@ static const struct rte_ixgbe_xstats_name_off rte_ixgbe_stats_strings[] = {
 #define IXGBE_NB_HW_STATS (sizeof(rte_ixgbe_stats_strings) / \
 			   sizeof(rte_ixgbe_stats_strings[0]))
 
+/* MACsec statistics */
+static const struct rte_ixgbe_xstats_name_off rte_ixgbe_macsec_strings[] = {
+	{"out_pkts_untagged", offsetof(struct ixgbe_macsec_stats,
+		out_pkts_untagged)},
+	{"out_pkts_encrypted", offsetof(struct ixgbe_macsec_stats,
+		out_pkts_encrypted)},
+	{"out_pkts_protected", offsetof(struct ixgbe_macsec_stats,
+		out_pkts_protected)},
+	{"out_octets_encrypted", offsetof(struct ixgbe_macsec_stats,
+		out_octets_encrypted)},
+	{"out_octets_protected", offsetof(struct ixgbe_macsec_stats,
+		out_octets_protected)},
+	{"in_pkts_untagged", offsetof(struct ixgbe_macsec_stats,
+		in_pkts_untagged)},
+	{"in_pkts_badtag", offsetof(struct ixgbe_macsec_stats,
+		in_pkts_badtag)},
+	{"in_pkts_nosci", offsetof(struct ixgbe_macsec_stats,
+		in_pkts_nosci)},
+	{"in_pkts_unknownsci", offsetof(struct ixgbe_macsec_stats,
+		in_pkts_unknownsci)},
+	{"in_octets_decrypted", offsetof(struct ixgbe_macsec_stats,
+		in_octets_decrypted)},
+	{"in_octets_validated", offsetof(struct ixgbe_macsec_stats,
+		in_octets_validated)},
+	{"in_pkts_unchecked", offsetof(struct ixgbe_macsec_stats,
+		in_pkts_unchecked)},
+	{"in_pkts_delayed", offsetof(struct ixgbe_macsec_stats,
+		in_pkts_delayed)},
+	{"in_pkts_late", offsetof(struct ixgbe_macsec_stats,
+		in_pkts_late)},
+	{"in_pkts_ok", offsetof(struct ixgbe_macsec_stats,
+		in_pkts_ok)},
+	{"in_pkts_invalid", offsetof(struct ixgbe_macsec_stats,
+		in_pkts_invalid)},
+	{"in_pkts_notvalid", offsetof(struct ixgbe_macsec_stats,
+		in_pkts_notvalid)},
+	{"in_pkts_unusedsa", offsetof(struct ixgbe_macsec_stats,
+		in_pkts_unusedsa)},
+	{"in_pkts_notusingsa", offsetof(struct ixgbe_macsec_stats,
+		in_pkts_notusingsa)},
+};
+
+#define IXGBE_NB_MACSEC_STATS (sizeof(rte_ixgbe_macsec_strings) / \
+			   sizeof(rte_ixgbe_macsec_strings[0]))
+
 /* Per-queue statistics */
 static const struct rte_ixgbe_xstats_name_off rte_ixgbe_rxq_strings[] = {
 	{"mbuf_allocation_errors", offsetof(struct ixgbe_hw_stats, rnbc)},
@@ -2371,6 +2417,7 @@ ixgbe_dev_start(struct rte_eth_dev *dev)
 		/* check if lsc interrupt is enabled */
 		if (dev->data->dev_conf.intr_conf.lsc != 0)
 			ixgbe_dev_lsc_interrupt_setup(dev);
+		ixgbe_dev_macsec_interrupt_setup(dev);
 	} else {
 		rte_intr_callback_unregister(intr_handle,
 					     ixgbe_dev_interrupt_handler, dev);
@@ -2561,6 +2608,7 @@ ixgbe_dev_close(struct rte_eth_dev *dev)
 static void
 ixgbe_read_stats_registers(struct ixgbe_hw *hw,
 			   struct ixgbe_hw_stats *hw_stats,
+			   struct ixgbe_macsec_stats *macsec_stats,
 			   uint64_t *total_missed_rx, uint64_t *total_qbrc,
 			   uint64_t *total_qprc, uint64_t *total_qprdc)
 {
@@ -2730,6 +2778,40 @@ ixgbe_read_stats_registers(struct ixgbe_hw *hw,
 	/* Flow Director Stats registers */
 	hw_stats->fdirmatch += IXGBE_READ_REG(hw, IXGBE_FDIRMATCH);
 	hw_stats->fdirmiss += IXGBE_READ_REG(hw, IXGBE_FDIRMISS);
+
+	/* MACsec Stats registers */
+	macsec_stats->out_pkts_untagged += IXGBE_READ_REG(hw, IXGBE_LSECTXUT);
+	macsec_stats->out_pkts_encrypted +=
+		IXGBE_READ_REG(hw, IXGBE_LSECTXPKTE);
+	macsec_stats->out_pkts_protected +=
+		IXGBE_READ_REG(hw, IXGBE_LSECTXPKTP);
+	macsec_stats->out_octets_encrypted +=
+		IXGBE_READ_REG(hw, IXGBE_LSECTXOCTE);
+	macsec_stats->out_octets_protected +=
+		IXGBE_READ_REG(hw, IXGBE_LSECTXOCTP);
+	macsec_stats->in_pkts_untagged += IXGBE_READ_REG(hw, IXGBE_LSECRXUT);
+	macsec_stats->in_pkts_badtag += IXGBE_READ_REG(hw, IXGBE_LSECRXBAD);
+	macsec_stats->in_pkts_nosci += IXGBE_READ_REG(hw, IXGBE_LSECRXNOSCI);
+	macsec_stats->in_pkts_unknownsci +=
+		IXGBE_READ_REG(hw, IXGBE_LSECRXUNSCI);
+	macsec_stats->in_octets_decrypted +=
+		IXGBE_READ_REG(hw, IXGBE_LSECRXOCTD);
+	macsec_stats->in_octets_validated +=
+		IXGBE_READ_REG(hw, IXGBE_LSECRXOCTV);
+	macsec_stats->in_pkts_unchecked += IXGBE_READ_REG(hw, IXGBE_LSECRXUNCH);
+	macsec_stats->in_pkts_delayed += IXGBE_READ_REG(hw, IXGBE_LSECRXDELAY);
+	macsec_stats->in_pkts_late += IXGBE_READ_REG(hw, IXGBE_LSECRXLATE);
+	for (i = 0; i < 2; i++) {
+		macsec_stats->in_pkts_ok +=
+			IXGBE_READ_REG(hw, IXGBE_LSECRXOK(i));
+		macsec_stats->in_pkts_invalid +=
+			IXGBE_READ_REG(hw, IXGBE_LSECRXINV(i));
+		macsec_stats->in_pkts_notvalid +=
+			IXGBE_READ_REG(hw, IXGBE_LSECRXNV(i));
+	}
+	macsec_stats->in_pkts_unusedsa += IXGBE_READ_REG(hw, IXGBE_LSECRXUNSA);
+	macsec_stats->in_pkts_notusingsa +=
+		IXGBE_READ_REG(hw, IXGBE_LSECRXNUSA);
 }
 
 /*
@@ -2742,6 +2824,9 @@ ixgbe_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
 			IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	struct ixgbe_hw_stats *hw_stats =
 			IXGBE_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+	struct ixgbe_macsec_stats *macsec_stats =
+			IXGBE_DEV_PRIVATE_TO_MACSEC_STATS(
+				dev->data->dev_private);
 	uint64_t total_missed_rx, total_qbrc, total_qprc, total_qprdc;
 	unsigned i;
 
@@ -2750,8 +2835,8 @@ ixgbe_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
 	total_qprc = 0;
 	total_qprdc = 0;
 
-	ixgbe_read_stats_registers(hw, hw_stats, &total_missed_rx, &total_qbrc,
-			&total_qprc, &total_qprdc);
+	ixgbe_read_stats_registers(hw, hw_stats, macsec_stats, &total_missed_rx,
+			&total_qbrc, &total_qprc, &total_qprdc);
 
 	if (stats == NULL)
 		return;
@@ -2803,7 +2888,7 @@ ixgbe_dev_stats_reset(struct rte_eth_dev *dev)
 /* This function calculates the number of xstats based on the current config */
 static unsigned
 ixgbe_xstats_calc_num(void) {
-	return IXGBE_NB_HW_STATS +
+	return IXGBE_NB_HW_STATS + IXGBE_NB_MACSEC_STATS +
 		(IXGBE_NB_RXQ_PRIO_STATS * IXGBE_NB_RXQ_PRIO_VALUES) +
 		(IXGBE_NB_TXQ_PRIO_STATS * IXGBE_NB_TXQ_PRIO_VALUES);
 }
@@ -2830,6 +2915,15 @@ static int ixgbe_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 			count++;
 		}
 
+		/* MACsec Stats */
+		for (i = 0; i < IXGBE_NB_MACSEC_STATS; i++) {
+			snprintf(xstats_names[count].name,
+				sizeof(xstats_names[count].name),
+				"%s",
+				rte_ixgbe_macsec_strings[i].name);
+			count++;
+		}
+
 		/* RX Priority Stats */
 		for (stat = 0; stat < IXGBE_NB_RXQ_PRIO_STATS; stat++) {
 			for (i = 0; i < IXGBE_NB_RXQ_PRIO_VALUES; i++) {
@@ -2879,6 +2973,9 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
 			IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	struct ixgbe_hw_stats *hw_stats =
 			IXGBE_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+	struct ixgbe_macsec_stats *macsec_stats =
+			IXGBE_DEV_PRIVATE_TO_MACSEC_STATS(
+				dev->data->dev_private);
 	uint64_t total_missed_rx, total_qbrc, total_qprc, total_qprdc;
 	unsigned i, stat, count = 0;
 
@@ -2892,8 +2989,8 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
 	total_qprc = 0;
 	total_qprdc = 0;
 
-	ixgbe_read_stats_registers(hw, hw_stats, &total_missed_rx, &total_qbrc,
-				   &total_qprc, &total_qprdc);
+	ixgbe_read_stats_registers(hw, hw_stats, macsec_stats, &total_missed_rx,
+			&total_qbrc, &total_qprc, &total_qprdc);
 
 	/* If this is a reset xstats is NULL, and we have cleared the
 	 * registers by reading them.
@@ -2910,6 +3007,14 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
 		count++;
 	}
 
+	/* MACsec Stats */
+	for (i = 0; i < IXGBE_NB_MACSEC_STATS; i++) {
+		xstats[count].value = *(uint64_t *)(((char *)macsec_stats) +
+				rte_ixgbe_macsec_strings[i].offset);
+		xstats[count].id = count;
+		count++;
+	}
+
 	/* RX Priority Stats */
 	for (stat = 0; stat < IXGBE_NB_RXQ_PRIO_STATS; stat++) {
 		for (i = 0; i < IXGBE_NB_RXQ_PRIO_VALUES; i++) {
@@ -2939,6 +3044,9 @@ ixgbe_dev_xstats_reset(struct rte_eth_dev *dev)
 {
 	struct ixgbe_hw_stats *stats =
 			IXGBE_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+	struct ixgbe_macsec_stats *macsec_stats =
+			IXGBE_DEV_PRIVATE_TO_MACSEC_STATS(
+				dev->data->dev_private);
 
 	unsigned count = ixgbe_xstats_calc_num();
 
@@ -2947,6 +3055,7 @@ ixgbe_dev_xstats_reset(struct rte_eth_dev *dev)
 
 	/* Reset software totals */
 	memset(stats, 0, sizeof(*stats));
+	memset(macsec_stats, 0, sizeof(*macsec_stats));
 }
 
 static void
@@ -3079,6 +3188,10 @@ ixgbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 	    !RTE_ETH_DEV_SRIOV(dev).active)
 		dev_info->rx_offload_capa |= DEV_RX_OFFLOAD_TCP_LRO;
 
+	if (hw->mac.type == ixgbe_mac_82599EB ||
+	    hw->mac.type == ixgbe_mac_X540)
+		dev_info->rx_offload_capa |= DEV_RX_OFFLOAD_MACSEC_STRIP;
+
 	if (hw->mac.type == ixgbe_mac_X550 ||
 	    hw->mac.type == ixgbe_mac_X550EM_x ||
 	    hw->mac.type == ixgbe_mac_X550EM_a)
@@ -3092,6 +3205,10 @@ ixgbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 		DEV_TX_OFFLOAD_SCTP_CKSUM  |
 		DEV_TX_OFFLOAD_TCP_TSO;
 
+	if (hw->mac.type == ixgbe_mac_82599EB ||
+	    hw->mac.type == ixgbe_mac_X540)
+		dev_info->tx_offload_capa |= DEV_TX_OFFLOAD_MACSEC_INSERT;
+
 	if (hw->mac.type == ixgbe_mac_X550 ||
 	    hw->mac.type == ixgbe_mac_X550EM_x ||
 	    hw->mac.type == ixgbe_mac_X550EM_a)
@@ -3389,6 +3506,28 @@ ixgbe_dev_rxq_interrupt_setup(struct rte_eth_dev *dev)
 	return 0;
 }
 
+/**
+ * It clears the interrupt causes and enables the interrupt.
+ * It will be called once only during nic initialized.
+ *
+ * @param dev
+ *  Pointer to struct rte_eth_dev.
+ *
+ * @return
+ *  - On success, zero.
+ *  - On failure, a negative value.
+ */
+static int
+ixgbe_dev_macsec_interrupt_setup(struct rte_eth_dev *dev)
+{
+	struct ixgbe_interrupt *intr =
+		IXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private);
+
+	intr->mask |= IXGBE_EICR_LINKSEC;
+
+	return 0;
+}
+
 /*
  * It reads ICR and sets flag (IXGBE_EICR_LSC) for the link_update.
  *
@@ -3423,6 +3562,9 @@ ixgbe_dev_interrupt_get_status(struct rte_eth_dev *dev)
 	if (eicr & IXGBE_EICR_MAILBOX)
 		intr->flags |= IXGBE_FLAG_MAILBOX;
 
+	if (eicr & IXGBE_EICR_LINKSEC)
+		intr->flags |= IXGBE_FLAG_MACSEC;
+
 	if (hw->mac.type ==  ixgbe_mac_X550EM_x &&
 	    hw->phy.type == ixgbe_phy_x550em_ext_t &&
 	    (eicr & IXGBE_EICR_GPI_SDP0_X550EM_x))
@@ -3577,6 +3719,12 @@ ixgbe_dev_interrupt_delayed_handler(void *param)
 		_rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC, NULL);
 	}
 
+	if (intr->flags & IXGBE_FLAG_MACSEC) {
+		_rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_MACSEC,
+					      NULL);
+		intr->flags &= ~IXGBE_FLAG_MACSEC;
+	}
+
 	PMD_DRV_LOG(DEBUG, "enable intr in delayed handler S[%08x]", eicr);
 	ixgbe_enable_intr(dev);
 	rte_intr_enable(intr_handle);
@@ -7617,6 +7765,330 @@ ixgbevf_dev_interrupt_handler(__rte_unused struct rte_intr_handle *handle,
 	ixgbevf_dev_interrupt_action(dev);
 }
 
+/**
+ *  ixgbe_disable_sec_tx_path_generic - Stops the transmit data path
+ *  @hw: pointer to hardware structure
+ *
+ *  Stops the transmit data path and waits for the HW to internally empty
+ *  the Tx security block
+ **/
+int ixgbe_disable_sec_tx_path_generic(struct ixgbe_hw *hw)
+{
+#define IXGBE_MAX_SECTX_POLL 40
+
+	int i;
+	int sectxreg;
+
+	sectxreg = IXGBE_READ_REG(hw, IXGBE_SECTXCTRL);
+	sectxreg |= IXGBE_SECTXCTRL_TX_DIS;
+	IXGBE_WRITE_REG(hw, IXGBE_SECTXCTRL, sectxreg);
+	for (i = 0; i < IXGBE_MAX_SECTX_POLL; i++) {
+		sectxreg = IXGBE_READ_REG(hw, IXGBE_SECTXSTAT);
+		if (sectxreg & IXGBE_SECTXSTAT_SECTX_RDY)
+			break;
+		/* Use interrupt-safe sleep just in case */
+		usec_delay(1000);
+	}
+
+	/* For informational purposes only */
+	if (i >= IXGBE_MAX_SECTX_POLL)
+		PMD_DRV_LOG(DEBUG, "Tx unit being enabled before security "
+			 "path fully disabled.  Continuing with init.\n");
+
+	return IXGBE_SUCCESS;
+}
+
+/**
+ *  ixgbe_enable_sec_tx_path_generic - Enables the transmit data path
+ *  @hw: pointer to hardware structure
+ *
+ *  Enables the transmit data path.
+ **/
+int ixgbe_enable_sec_tx_path_generic(struct ixgbe_hw *hw)
+{
+	uint32_t sectxreg;
+
+	sectxreg = IXGBE_READ_REG(hw, IXGBE_SECTXCTRL);
+	sectxreg &= ~IXGBE_SECTXCTRL_TX_DIS;
+	IXGBE_WRITE_REG(hw, IXGBE_SECTXCTRL, sectxreg);
+	IXGBE_WRITE_FLUSH(hw);
+
+	return IXGBE_SUCCESS;
+}
+
+int
+rte_pmd_ixgbe_macsec_enable(uint8_t port, uint8_t en, uint8_t rp)
+{
+	struct ixgbe_hw *hw;
+	struct rte_eth_dev *dev;
+	uint32_t ctrl;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+	dev = &rte_eth_devices[port];
+	hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	/* Stop the data paths */
+	if (ixgbe_disable_sec_rx_path(hw) != IXGBE_SUCCESS)
+		return -ENOTSUP;
+	/*
+	 * Workaround:
+	 * As no ixgbe_disable_sec_rx_path equivalent is
+	 * implemented for tx in the base code, and we are
+	 * not allowed to modify the base code in DPDK, so
+	 * just call the hand-written one directly for now.
+	 * The hardware support has been checked by
+	 * ixgbe_disable_sec_rx_path().
+	 */
+	ixgbe_disable_sec_tx_path_generic(hw);
+
+	/* Enable Ethernet CRC (required by MACsec offload) */
+	ctrl = IXGBE_READ_REG(hw, IXGBE_HLREG0);
+	ctrl |= IXGBE_HLREG0_TXCRCEN | IXGBE_HLREG0_RXCRCSTRP;
+	IXGBE_WRITE_REG(hw, IXGBE_HLREG0, ctrl);
+
+	/* Enable the TX and RX crypto engines */
+	ctrl = IXGBE_READ_REG(hw, IXGBE_SECTXCTRL);
+	ctrl &= ~IXGBE_SECTXCTRL_SECTX_DIS;
+	IXGBE_WRITE_REG(hw, IXGBE_SECTXCTRL, ctrl);
+
+	ctrl = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL);
+	ctrl &= ~IXGBE_SECRXCTRL_SECRX_DIS;
+	IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, ctrl);
+
+	ctrl = IXGBE_READ_REG(hw, IXGBE_SECTXMINIFG);
+	ctrl &= ~IXGBE_SECTX_MINSECIFG_MASK;
+	ctrl |= 0x3;
+	IXGBE_WRITE_REG(hw, IXGBE_SECTXMINIFG, ctrl);
+
+	/* Enable SA lookup */
+	ctrl = IXGBE_READ_REG(hw, IXGBE_LSECTXCTRL);
+	ctrl &= ~IXGBE_LSECTXCTRL_EN_MASK;
+	ctrl |= en ? IXGBE_LSECTXCTRL_AUTH_ENCRYPT :
+		     IXGBE_LSECTXCTRL_AUTH;
+	ctrl |= IXGBE_LSECTXCTRL_AISCI;
+	ctrl &= ~IXGBE_LSECTXCTRL_PNTHRSH_MASK;
+	ctrl |= IXGBE_MACSEC_PNTHRSH & IXGBE_LSECTXCTRL_PNTHRSH_MASK;
+	IXGBE_WRITE_REG(hw, IXGBE_LSECTXCTRL, ctrl);
+
+	ctrl = IXGBE_READ_REG(hw, IXGBE_LSECRXCTRL);
+	ctrl &= ~IXGBE_LSECRXCTRL_EN_MASK;
+	ctrl |= IXGBE_LSECRXCTRL_STRICT << IXGBE_LSECRXCTRL_EN_SHIFT;
+	ctrl &= ~IXGBE_LSECRXCTRL_PLSH;
+	if (rp)
+		ctrl |= IXGBE_LSECRXCTRL_RP;
+	else
+		ctrl &= ~IXGBE_LSECRXCTRL_RP;
+	IXGBE_WRITE_REG(hw, IXGBE_LSECRXCTRL, ctrl);
+
+	/* Start the data paths */
+	ixgbe_enable_sec_rx_path(hw);
+	/*
+	 * Workaround:
+	 * As no ixgbe_enable_sec_rx_path equivalent is
+	 * implemented for tx in the base code, and we are
+	 * not allowed to modify the base code in DPDK, so
+	 * just call the hand-written one directly for now.
+	 */
+	ixgbe_enable_sec_tx_path_generic(hw);
+
+	return 0;
+}
+
+int
+rte_pmd_ixgbe_macsec_disable(uint8_t port)
+{
+	struct ixgbe_hw *hw;
+	struct rte_eth_dev *dev;
+	uint32_t ctrl;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+	dev = &rte_eth_devices[port];
+	hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	/* Stop the data paths */
+	if (ixgbe_disable_sec_rx_path(hw) != IXGBE_SUCCESS)
+		return -ENOTSUP;
+	/*
+	 * Workaround:
+	 * As no ixgbe_disable_sec_rx_path equivalent is
+	 * implemented for tx in the base code, and we are
+	 * not allowed to modify the base code in DPDK, so
+	 * just call the hand-written one directly for now.
+	 * The hardware support has been checked by
+	 * ixgbe_disable_sec_rx_path().
+	 */
+	ixgbe_disable_sec_tx_path_generic(hw);
+
+	/* Disable the TX and RX crypto engines */
+	ctrl = IXGBE_READ_REG(hw, IXGBE_SECTXCTRL);
+	ctrl |= IXGBE_SECTXCTRL_SECTX_DIS;
+	IXGBE_WRITE_REG(hw, IXGBE_SECTXCTRL, ctrl);
+
+	ctrl = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL);
+	ctrl |= IXGBE_SECRXCTRL_SECRX_DIS;
+	IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, ctrl);
+
+	/* Disable SA lookup */
+	ctrl = IXGBE_READ_REG(hw, IXGBE_LSECTXCTRL);
+	ctrl &= ~IXGBE_LSECTXCTRL_EN_MASK;
+	ctrl |= IXGBE_LSECTXCTRL_DISABLE;
+	IXGBE_WRITE_REG(hw, IXGBE_LSECTXCTRL, ctrl);
+
+	ctrl = IXGBE_READ_REG(hw, IXGBE_LSECRXCTRL);
+	ctrl &= ~IXGBE_LSECRXCTRL_EN_MASK;
+	ctrl |= IXGBE_LSECRXCTRL_DISABLE << IXGBE_LSECRXCTRL_EN_SHIFT;
+	IXGBE_WRITE_REG(hw, IXGBE_LSECRXCTRL, ctrl);
+
+	/* Start the data paths */
+	ixgbe_enable_sec_rx_path(hw);
+	/*
+	 * Workaround:
+	 * As no ixgbe_enable_sec_rx_path equivalent is
+	 * implemented for tx in the base code, and we are
+	 * not allowed to modify the base code in DPDK, so
+	 * just call the hand-written one directly for now.
+	 */
+	ixgbe_enable_sec_tx_path_generic(hw);
+
+	return 0;
+}
+
+int
+rte_pmd_ixgbe_macsec_config_txsc(uint8_t port, uint8_t *mac)
+{
+	struct ixgbe_hw *hw;
+	struct rte_eth_dev *dev;
+	uint32_t ctrl;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+	dev = &rte_eth_devices[port];
+	hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	ctrl = mac[0] | (mac[1] << 8) | (mac[2] << 16) | (mac[3] << 24);
+	IXGBE_WRITE_REG(hw, IXGBE_LSECTXSCL, ctrl);
+
+	ctrl = mac[4] | (mac[5] << 8);
+	IXGBE_WRITE_REG(hw, IXGBE_LSECTXSCH, ctrl);
+
+	return 0;
+}
+
+int
+rte_pmd_ixgbe_macsec_config_rxsc(uint8_t port, uint8_t *mac, uint16_t pi)
+{
+	struct ixgbe_hw *hw;
+	struct rte_eth_dev *dev;
+	uint32_t ctrl;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+	dev = &rte_eth_devices[port];
+	hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	ctrl = mac[0] | (mac[1] << 8) | (mac[2] << 16) | (mac[3] << 24);
+	IXGBE_WRITE_REG(hw, IXGBE_LSECRXSCL, ctrl);
+
+	pi = rte_cpu_to_be_16(pi);
+	ctrl = mac[4] | (mac[5] << 8) | (pi << 16);
+	IXGBE_WRITE_REG(hw, IXGBE_LSECRXSCH, ctrl);
+
+	return 0;
+}
+
+int
+rte_pmd_ixgbe_macsec_select_txsa(uint8_t port, uint8_t idx, uint8_t an,
+				 uint32_t pn, uint8_t *key)
+{
+	struct ixgbe_hw *hw;
+	struct rte_eth_dev *dev;
+	uint32_t ctrl, i;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+	dev = &rte_eth_devices[port];
+	hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (idx != 0 && idx != 1)
+		return -EINVAL;
+
+	if (an >= 4)
+		return -EINVAL;
+
+	hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	/* Set the PN and key */
+	pn = rte_cpu_to_be_32(pn);
+	if (idx == 0) {
+		IXGBE_WRITE_REG(hw, IXGBE_LSECTXPN0, pn);
+
+		for (i = 0; i < 4; i++) {
+			ctrl = (key[i * 4 + 0] <<  0) |
+			       (key[i * 4 + 1] <<  8) |
+			       (key[i * 4 + 2] << 16) |
+			       (key[i * 4 + 3] << 24);
+			IXGBE_WRITE_REG(hw, IXGBE_LSECTXKEY0(i), ctrl);
+		}
+	} else {
+		IXGBE_WRITE_REG(hw, IXGBE_LSECTXPN1, pn);
+
+		for (i = 0; i < 4; i++) {
+			ctrl = (key[i * 4 + 0] <<  0) |
+			       (key[i * 4 + 1] <<  8) |
+			       (key[i * 4 + 2] << 16) |
+			       (key[i * 4 + 3] << 24);
+			IXGBE_WRITE_REG(hw, IXGBE_LSECTXKEY1(i), ctrl);
+		}
+	}
+
+	/* Set AN and select the SA */
+	ctrl = (an << idx * 2) | (idx << 4);
+	IXGBE_WRITE_REG(hw, IXGBE_LSECTXSA, ctrl);
+
+	return 0;
+}
+
+int
+rte_pmd_ixgbe_macsec_select_rxsa(uint8_t port, uint8_t idx, uint8_t an,
+				 uint32_t pn, uint8_t *key)
+{
+	struct ixgbe_hw *hw;
+	struct rte_eth_dev *dev;
+	uint32_t ctrl, i;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+	dev = &rte_eth_devices[port];
+	hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (idx != 0 && idx != 1)
+		return -EINVAL;
+
+	if (an >= 4)
+		return -EINVAL;
+
+	/* Set the PN */
+	pn = rte_cpu_to_be_32(pn);
+	IXGBE_WRITE_REG(hw, IXGBE_LSECRXPN(idx), pn);
+
+	/* Set the key */
+	for (i = 0; i < 4; i++) {
+		ctrl = (key[i * 4 + 0] <<  0) |
+		       (key[i * 4 + 1] <<  8) |
+		       (key[i * 4 + 2] << 16) |
+		       (key[i * 4 + 3] << 24);
+		IXGBE_WRITE_REG(hw, IXGBE_LSECRXKEY(idx, i), ctrl);
+	}
+
+	/* Set the AN and validate the SA */
+	ctrl = an | (1 << 2);
+	IXGBE_WRITE_REG(hw, IXGBE_LSECRXSA(idx), ctrl);
+
+	return 0;
+}
+
 RTE_PMD_REGISTER_PCI(net_ixgbe, rte_ixgbe_pmd.pci_drv);
 RTE_PMD_REGISTER_PCI_TABLE(net_ixgbe, pci_id_ixgbe_map);
 RTE_PMD_REGISTER_KMOD_DEP(net_ixgbe, "* igb_uio | uio_pci_generic | vfio");
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.h b/drivers/net/ixgbe/ixgbe_ethdev.h
index 69b276f..14e1fd6 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.h
+++ b/drivers/net/ixgbe/ixgbe_ethdev.h
@@ -43,6 +43,7 @@
 #define IXGBE_FLAG_NEED_LINK_UPDATE (uint32_t)(1 << 0)
 #define IXGBE_FLAG_MAILBOX          (uint32_t)(1 << 1)
 #define IXGBE_FLAG_PHY_INTERRUPT    (uint32_t)(1 << 2)
+#define IXGBE_FLAG_MACSEC           (uint32_t)(1 << 3)
 
 /*
  * Defines that were not part of ixgbe_type.h as they are not used by the
@@ -130,6 +131,10 @@
 #define IXGBE_MISC_VEC_ID               RTE_INTR_VEC_ZERO_OFFSET
 #define IXGBE_RX_VEC_START              RTE_INTR_VEC_RXTX_OFFSET
 
+#define IXGBE_SECTX_MINSECIFG_MASK      0x0000000F
+
+#define IXGBE_MACSEC_PNTHRSH            0xFFFFFE00
+
 /*
  * Information about the fdir mode.
  */
@@ -265,11 +270,44 @@ struct ixgbe_filter_info {
 };
 
 /*
+ * Statistics counters collected by the MACsec
+ */
+struct ixgbe_macsec_stats {
+	/* TX port statistics */
+	uint64_t out_pkts_untagged;
+	uint64_t out_pkts_encrypted;
+	uint64_t out_pkts_protected;
+	uint64_t out_octets_encrypted;
+	uint64_t out_octets_protected;
+
+	/* RX port statistics */
+	uint64_t in_pkts_untagged;
+	uint64_t in_pkts_badtag;
+	uint64_t in_pkts_nosci;
+	uint64_t in_pkts_unknownsci;
+	uint64_t in_octets_decrypted;
+	uint64_t in_octets_validated;
+
+	/* RX SC statistics */
+	uint64_t in_pkts_unchecked;
+	uint64_t in_pkts_delayed;
+	uint64_t in_pkts_late;
+
+	/* RX SA statistics */
+	uint64_t in_pkts_ok;
+	uint64_t in_pkts_invalid;
+	uint64_t in_pkts_notvalid;
+	uint64_t in_pkts_unusedsa;
+	uint64_t in_pkts_notusingsa;
+};
+
+/*
  * Structure to store private data for each driver instance (for each port).
  */
 struct ixgbe_adapter {
 	struct ixgbe_hw             hw;
 	struct ixgbe_hw_stats       stats;
+	struct ixgbe_macsec_stats   macsec_stats;
 	struct ixgbe_hw_fdir_info   fdir;
 	struct ixgbe_interrupt      intr;
 	struct ixgbe_stat_mapping_registers stat_mappings;
@@ -300,6 +338,9 @@ struct ixgbe_adapter {
 #define IXGBE_DEV_PRIVATE_TO_STATS(adapter) \
 	(&((struct ixgbe_adapter *)adapter)->stats)
 
+#define IXGBE_DEV_PRIVATE_TO_MACSEC_STATS(adapter) \
+	(&((struct ixgbe_adapter *)adapter)->macsec_stats)
+
 #define IXGBE_DEV_PRIVATE_TO_INTR(adapter) \
 	(&((struct ixgbe_adapter *)adapter)->intr)
 
@@ -448,4 +489,8 @@ uint32_t ixgbe_convert_vm_rx_mask_to_val(uint16_t rx_mask, uint32_t orig_val);
 
 int ixgbe_fdir_ctrl_func(struct rte_eth_dev *dev,
 			enum rte_filter_op filter_op, void *arg);
+
+int ixgbe_disable_sec_tx_path_generic(struct ixgbe_hw *hw);
+
+int ixgbe_enable_sec_tx_path_generic(struct ixgbe_hw *hw);
 #endif /* _IXGBE_ETHDEV_H_ */
diff --git a/drivers/net/ixgbe/ixgbe_rxtx.c b/drivers/net/ixgbe/ixgbe_rxtx.c
index 0bbc583..00013c6 100644
--- a/drivers/net/ixgbe/ixgbe_rxtx.c
+++ b/drivers/net/ixgbe/ixgbe_rxtx.c
@@ -86,6 +86,7 @@
 		PKT_TX_IP_CKSUM |		 \
 		PKT_TX_L4_MASK |		 \
 		PKT_TX_TCP_SEG |		 \
+		PKT_TX_MACSEC |			 \
 		PKT_TX_OUTER_IP_CKSUM)
 
 #define IXGBE_TX_OFFLOAD_NOTSUP_MASK \
@@ -523,6 +524,8 @@ tx_desc_ol_flags_to_cmdtype(uint64_t ol_flags)
 		cmdtype |= IXGBE_ADVTXD_DCMD_TSE;
 	if (ol_flags & PKT_TX_OUTER_IP_CKSUM)
 		cmdtype |= (1 << IXGBE_ADVTXD_OUTERIPCS_SHIFT);
+	if (ol_flags & PKT_TX_MACSEC)
+		cmdtype |= IXGBE_ADVTXD_MAC_LINKSEC;
 	return cmdtype;
 }
 
diff --git a/drivers/net/ixgbe/rte_pmd_ixgbe.h b/drivers/net/ixgbe/rte_pmd_ixgbe.h
index c2fb826..22bc4c7 100644
--- a/drivers/net/ixgbe/rte_pmd_ixgbe.h
+++ b/drivers/net/ixgbe/rte_pmd_ixgbe.h
@@ -183,6 +183,106 @@ int
 rte_pmd_ixgbe_set_vf_vlan_stripq(uint8_t port, uint16_t vf, uint8_t on);
 
 /**
+ * Enable MACsec offload.
+ *
+ * @param port
+ *   The port identifier of the Ethernet device.
+ * @param en
+ *    1 - Enable encryption (encrypt and add integrity signature).
+ *    0 - Disable encryption (only add integrity signature).
+ * @param rp
+ *    1 - Enable replay protection.
+ *    0 - Disable replay protection.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-ENOTSUP) if hardware doesn't support this feature.
+ */
+int rte_pmd_ixgbe_macsec_enable(uint8_t port, uint8_t en, uint8_t rp);
+
+/**
+ * Disable MACsec offload.
+ *
+ * @param port
+ *   The port identifier of the Ethernet device.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-ENOTSUP) if hardware doesn't support this feature.
+ */
+int rte_pmd_ixgbe_macsec_disable(uint8_t port);
+
+/**
+ * Configure Tx SC (Secure Connection).
+ *
+ * @param port
+ *   The port identifier of the Ethernet device.
+ * @param mac
+ *   The MAC address on the local side.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if *port* invalid.
+ */
+int rte_pmd_ixgbe_macsec_config_txsc(uint8_t port, uint8_t *mac);
+
+/**
+ * Configure Rx SC (Secure Connection).
+ *
+ * @param port
+ *   The port identifier of the Ethernet device.
+ * @param mac
+ *   The MAC address on the remote side.
+ * @param pi
+ *   The PI (port identifier) on the remote side.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if *port* invalid.
+ */
+int rte_pmd_ixgbe_macsec_config_rxsc(uint8_t port, uint8_t *mac, uint16_t pi);
+
+/**
+ * Enable Tx SA (Secure Association).
+ *
+ * @param port
+ *   The port identifier of the Ethernet device.
+ * @param idx
+ *   The SA to be enabled (0 or 1).
+ * @param an
+ *   The association number on the local side.
+ * @param pn
+ *   The packet number on the local side.
+ * @param key
+ *   The key on the local side.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int rte_pmd_ixgbe_macsec_select_txsa(uint8_t port, uint8_t idx, uint8_t an,
+		uint32_t pn, uint8_t *key);
+
+/**
+ * Enable Rx SA (Secure Association).
+ *
+ * @param port
+ *   The port identifier of the Ethernet device.
+ * @param idx
+ *   The SA to be enabled (0 or 1)
+ * @param an
+ *   The association number on the remote side.
+ * @param pn
+ *   The packet number on the remote side.
+ * @param key
+ *   The key on the remote side.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int rte_pmd_ixgbe_macsec_select_rxsa(uint8_t port, uint8_t idx, uint8_t an,
+		uint32_t pn, uint8_t *key);
+
+/**
  * Response sent back to ixgbe driver from user app after callback
  */
 enum rte_pmd_ixgbe_mb_event_rsp {
diff --git a/drivers/net/ixgbe/rte_pmd_ixgbe_version.map b/drivers/net/ixgbe/rte_pmd_ixgbe_version.map
index 92434f3..6d68934 100644
--- a/drivers/net/ixgbe/rte_pmd_ixgbe_version.map
+++ b/drivers/net/ixgbe/rte_pmd_ixgbe_version.map
@@ -15,3 +15,14 @@ DPDK_16.11 {
 	rte_pmd_ixgbe_set_vf_vlan_insert;
 	rte_pmd_ixgbe_set_vf_vlan_stripq;
 } DPDK_2.0;
+
+DPDK_17.02 {
+	global:
+
+	rte_pmd_ixgbe_macsec_enable;
+	rte_pmd_ixgbe_macsec_disable;
+	rte_pmd_ixgbe_macsec_config_txsc;
+	rte_pmd_ixgbe_macsec_config_rxsc;
+	rte_pmd_ixgbe_macsec_select_txsa;
+	rte_pmd_ixgbe_macsec_select_rxsa;
+} DPDK_16.11;
-- 
2.7.4

^ permalink raw reply related

* [PATCH v7 5/6] app/testpmd: add MACsec offload commands
From: Tiwei Bie @ 2017-01-13 11:02 UTC (permalink / raw)
  To: dev
  Cc: adrien.mazarguil, wenzhuo.lu, john.mcnamara, olivier.matz,
	thomas.monjalon, konstantin.ananyev, helin.zhang, wei.dai,
	xiao.w.wang
In-Reply-To: <1484305346-157143-1-git-send-email-tiwei.bie@intel.com>

Below MACsec offload commands are added:

- set macsec offload <port_id> on encrypt on|off replay-protect on|off
- set macsec offload <port_id> off
- set macsec sc tx|rx <port_id> <mac> <pi>
- set macsec sa tx|rx <port_id> <idx> <an> <pn> <key>

Also update the testpmd user guide.

Signed-off-by: Tiwei Bie <tiwei.bie@intel.com>
Acked-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 app/test-pmd/cmdline.c                      | 389 ++++++++++++++++++++++++++++
 app/test-pmd/macfwd.c                       |   2 +
 app/test-pmd/macswap.c                      |   2 +
 app/test-pmd/testpmd.h                      |   2 +
 app/test-pmd/txonly.c                       |   2 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  32 +++
 6 files changed, 429 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index f768b6b..1bf42ba 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -275,6 +275,18 @@ static void cmd_help_long_parsed(void *parsed_result,
 
 			"set vf mac antispoof (port_id) (vf_id) (on|off).\n"
 			"    Set MAC antispoof for a VF from the PF.\n\n"
+
+			"set macsec offload (port_id) on encrypt (on|off) replay-protect (on|off)\n"
+			"    Enable MACsec offload.\n\n"
+
+			"set macsec offload (port_id) off\n"
+			"    Disable MACsec offload.\n\n"
+
+			"set macsec sc (tx|rx) (port_id) (mac) (pi)\n"
+			"    Configure MACsec secure connection (SC).\n\n"
+
+			"set macsec sa (tx|rx) (port_id) (idx) (an) (pn) (key)\n"
+			"    Configure MACsec secure association (SA).\n\n"
 #endif
 
 			"vlan set strip (on|off) (port_id)\n"
@@ -11488,6 +11500,379 @@ cmdline_parse_inst_t cmd_set_vf_mac_addr = {
 		NULL,
 	},
 };
+
+/* MACsec configuration */
+
+/* Common result structure for MACsec offload enable */
+struct cmd_macsec_offload_on_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t macsec;
+	cmdline_fixed_string_t offload;
+	uint8_t port_id;
+	cmdline_fixed_string_t on;
+	cmdline_fixed_string_t encrypt;
+	cmdline_fixed_string_t en_on_off;
+	cmdline_fixed_string_t replay_protect;
+	cmdline_fixed_string_t rp_on_off;
+};
+
+/* Common CLI fields for MACsec offload disable */
+cmdline_parse_token_string_t cmd_macsec_offload_on_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_macsec_offload_on_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_macsec_offload_on_macsec =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_macsec_offload_on_result,
+		 macsec, "macsec");
+cmdline_parse_token_string_t cmd_macsec_offload_on_offload =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_macsec_offload_on_result,
+		 offload, "offload");
+cmdline_parse_token_num_t cmd_macsec_offload_on_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_macsec_offload_on_result,
+		 port_id, UINT8);
+cmdline_parse_token_string_t cmd_macsec_offload_on_on =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_macsec_offload_on_result,
+		 on, "on");
+cmdline_parse_token_string_t cmd_macsec_offload_on_encrypt =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_macsec_offload_on_result,
+		 encrypt, "encrypt");
+cmdline_parse_token_string_t cmd_macsec_offload_on_en_on_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_macsec_offload_on_result,
+		 en_on_off, "on#off");
+cmdline_parse_token_string_t cmd_macsec_offload_on_replay_protect =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_macsec_offload_on_result,
+		 replay_protect, "replay-protect");
+cmdline_parse_token_string_t cmd_macsec_offload_on_rp_on_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_macsec_offload_on_result,
+		 rp_on_off, "on#off");
+
+static void
+cmd_set_macsec_offload_on_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_macsec_offload_on_result *res = parsed_result;
+	int ret;
+	portid_t port_id = res->port_id;
+	int en = (strcmp(res->en_on_off, "on") == 0) ? 1 : 0;
+	int rp = (strcmp(res->rp_on_off, "on") == 0) ? 1 : 0;
+
+	if (port_id_is_invalid(port_id, ENABLED_WARN))
+		return;
+
+	ports[port_id].tx_ol_flags |= TESTPMD_TX_OFFLOAD_MACSEC;
+	ret = rte_pmd_ixgbe_macsec_enable(port_id, en, rp);
+
+	switch (ret) {
+	case 0:
+		break;
+	case -ENODEV:
+		printf("invalid port_id %d\n", port_id);
+		break;
+	default:
+		printf("programming error: (%s)\n", strerror(-ret));
+	}
+}
+
+cmdline_parse_inst_t cmd_set_macsec_offload_on = {
+	.f = cmd_set_macsec_offload_on_parsed,
+	.data = NULL,
+	.help_str = "set macsec offload <port_id> on "
+		"encrypt on|off replay-protect on|off",
+	.tokens = {
+		(void *)&cmd_macsec_offload_on_set,
+		(void *)&cmd_macsec_offload_on_macsec,
+		(void *)&cmd_macsec_offload_on_offload,
+		(void *)&cmd_macsec_offload_on_port_id,
+		(void *)&cmd_macsec_offload_on_on,
+		(void *)&cmd_macsec_offload_on_encrypt,
+		(void *)&cmd_macsec_offload_on_en_on_off,
+		(void *)&cmd_macsec_offload_on_replay_protect,
+		(void *)&cmd_macsec_offload_on_rp_on_off,
+		NULL,
+	},
+};
+
+/* Common result structure for MACsec offload disable */
+struct cmd_macsec_offload_off_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t macsec;
+	cmdline_fixed_string_t offload;
+	uint8_t port_id;
+	cmdline_fixed_string_t off;
+};
+
+/* Common CLI fields for MACsec offload disable */
+cmdline_parse_token_string_t cmd_macsec_offload_off_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_macsec_offload_off_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_macsec_offload_off_macsec =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_macsec_offload_off_result,
+		 macsec, "macsec");
+cmdline_parse_token_string_t cmd_macsec_offload_off_offload =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_macsec_offload_off_result,
+		 offload, "offload");
+cmdline_parse_token_num_t cmd_macsec_offload_off_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_macsec_offload_off_result,
+		 port_id, UINT8);
+cmdline_parse_token_string_t cmd_macsec_offload_off_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_macsec_offload_off_result,
+		 off, "off");
+
+static void
+cmd_set_macsec_offload_off_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_macsec_offload_off_result *res = parsed_result;
+	int ret;
+	portid_t port_id = res->port_id;
+
+	if (port_id_is_invalid(port_id, ENABLED_WARN))
+		return;
+
+	ports[port_id].tx_ol_flags &= ~TESTPMD_TX_OFFLOAD_MACSEC;
+	ret = rte_pmd_ixgbe_macsec_disable(port_id);
+
+	switch (ret) {
+	case 0:
+		break;
+	case -ENODEV:
+		printf("invalid port_id %d\n", port_id);
+		break;
+	default:
+		printf("programming error: (%s)\n", strerror(-ret));
+	}
+}
+
+cmdline_parse_inst_t cmd_set_macsec_offload_off = {
+	.f = cmd_set_macsec_offload_off_parsed,
+	.data = NULL,
+	.help_str = "set macsec offload <port_id> off",
+	.tokens = {
+		(void *)&cmd_macsec_offload_off_set,
+		(void *)&cmd_macsec_offload_off_macsec,
+		(void *)&cmd_macsec_offload_off_offload,
+		(void *)&cmd_macsec_offload_off_port_id,
+		(void *)&cmd_macsec_offload_off_off,
+		NULL,
+	},
+};
+
+/* Common result structure for MACsec secure connection configure */
+struct cmd_macsec_sc_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t macsec;
+	cmdline_fixed_string_t sc;
+	cmdline_fixed_string_t tx_rx;
+	uint8_t port_id;
+	struct ether_addr mac;
+	uint16_t pi;
+};
+
+/* Common CLI fields for MACsec secure connection configure */
+cmdline_parse_token_string_t cmd_macsec_sc_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_macsec_sc_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_macsec_sc_macsec =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_macsec_sc_result,
+		 macsec, "macsec");
+cmdline_parse_token_string_t cmd_macsec_sc_sc =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_macsec_sc_result,
+		 sc, "sc");
+cmdline_parse_token_string_t cmd_macsec_sc_tx_rx =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_macsec_sc_result,
+		 tx_rx, "tx#rx");
+cmdline_parse_token_num_t cmd_macsec_sc_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_macsec_sc_result,
+		 port_id, UINT8);
+cmdline_parse_token_etheraddr_t cmd_macsec_sc_mac =
+	TOKEN_ETHERADDR_INITIALIZER
+		(struct cmd_macsec_sc_result,
+		 mac);
+cmdline_parse_token_num_t cmd_macsec_sc_pi =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_macsec_sc_result,
+		 pi, UINT16);
+
+static void
+cmd_set_macsec_sc_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_macsec_sc_result *res = parsed_result;
+	int ret;
+	int is_tx = (strcmp(res->tx_rx, "tx") == 0) ? 1 : 0;
+
+	ret = is_tx ?
+		rte_pmd_ixgbe_macsec_config_txsc(res->port_id,
+				res->mac.addr_bytes) :
+		rte_pmd_ixgbe_macsec_config_rxsc(res->port_id,
+				res->mac.addr_bytes, res->pi);
+	switch (ret) {
+	case 0:
+		break;
+	case -ENODEV:
+		printf("invalid port_id %d\n", res->port_id);
+		break;
+	default:
+		printf("programming error: (%s)\n", strerror(-ret));
+	}
+}
+
+cmdline_parse_inst_t cmd_set_macsec_sc = {
+	.f = cmd_set_macsec_sc_parsed,
+	.data = NULL,
+	.help_str = "set macsec sc tx|rx <port_id> <mac> <pi>",
+	.tokens = {
+		(void *)&cmd_macsec_sc_set,
+		(void *)&cmd_macsec_sc_macsec,
+		(void *)&cmd_macsec_sc_sc,
+		(void *)&cmd_macsec_sc_tx_rx,
+		(void *)&cmd_macsec_sc_port_id,
+		(void *)&cmd_macsec_sc_mac,
+		(void *)&cmd_macsec_sc_pi,
+		NULL,
+	},
+};
+
+/* Common result structure for MACsec secure connection configure */
+struct cmd_macsec_sa_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t macsec;
+	cmdline_fixed_string_t sa;
+	cmdline_fixed_string_t tx_rx;
+	uint8_t port_id;
+	uint8_t idx;
+	uint8_t an;
+	uint32_t pn;
+	cmdline_fixed_string_t key;
+};
+
+/* Common CLI fields for MACsec secure connection configure */
+cmdline_parse_token_string_t cmd_macsec_sa_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_macsec_sa_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_macsec_sa_macsec =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_macsec_sa_result,
+		 macsec, "macsec");
+cmdline_parse_token_string_t cmd_macsec_sa_sa =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_macsec_sa_result,
+		 sa, "sa");
+cmdline_parse_token_string_t cmd_macsec_sa_tx_rx =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_macsec_sa_result,
+		 tx_rx, "tx#rx");
+cmdline_parse_token_num_t cmd_macsec_sa_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_macsec_sa_result,
+		 port_id, UINT8);
+cmdline_parse_token_num_t cmd_macsec_sa_idx =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_macsec_sa_result,
+		 idx, UINT8);
+cmdline_parse_token_num_t cmd_macsec_sa_an =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_macsec_sa_result,
+		 an, UINT8);
+cmdline_parse_token_num_t cmd_macsec_sa_pn =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_macsec_sa_result,
+		 pn, UINT32);
+cmdline_parse_token_string_t cmd_macsec_sa_key =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_macsec_sa_result,
+		 key, NULL);
+
+static void
+cmd_set_macsec_sa_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_macsec_sa_result *res = parsed_result;
+	int ret;
+	int is_tx = (strcmp(res->tx_rx, "tx") == 0) ? 1 : 0;
+	uint8_t key[16] = { 0 };
+	uint8_t xdgt0;
+	uint8_t xdgt1;
+	int key_len;
+	int i;
+
+	key_len = strlen(res->key) / 2;
+	if (key_len > 16)
+		key_len = 16;
+
+	for (i = 0; i < key_len; i++) {
+		xdgt0 = parse_and_check_key_hexa_digit(res->key, (i * 2));
+		if (xdgt0 == 0xFF)
+			return;
+		xdgt1 = parse_and_check_key_hexa_digit(res->key, (i * 2) + 1);
+		if (xdgt1 == 0xFF)
+			return;
+		key[i] = (uint8_t) ((xdgt0 * 16) + xdgt1);
+	}
+
+	ret = is_tx ?
+		rte_pmd_ixgbe_macsec_select_txsa(res->port_id,
+			res->idx, res->an, res->pn, key) :
+		rte_pmd_ixgbe_macsec_select_rxsa(res->port_id,
+			res->idx, res->an, res->pn, key);
+	switch (ret) {
+	case 0:
+		break;
+	case -EINVAL:
+		printf("invalid idx %d or an %d\n", res->idx, res->an);
+		break;
+	case -ENODEV:
+		printf("invalid port_id %d\n", res->port_id);
+		break;
+	default:
+		printf("programming error: (%s)\n", strerror(-ret));
+	}
+}
+
+cmdline_parse_inst_t cmd_set_macsec_sa = {
+	.f = cmd_set_macsec_sa_parsed,
+	.data = NULL,
+	.help_str = "set macsec sa tx|rx <port_id> <idx> <an> <pn> <key>",
+	.tokens = {
+		(void *)&cmd_macsec_sa_set,
+		(void *)&cmd_macsec_sa_macsec,
+		(void *)&cmd_macsec_sa_sa,
+		(void *)&cmd_macsec_sa_tx_rx,
+		(void *)&cmd_macsec_sa_port_id,
+		(void *)&cmd_macsec_sa_idx,
+		(void *)&cmd_macsec_sa_an,
+		(void *)&cmd_macsec_sa_pn,
+		(void *)&cmd_macsec_sa_key,
+		NULL,
+	},
+};
 #endif
 
 /* ******************************************************************************** */
@@ -11656,6 +12041,10 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_set_all_queues_drop_en,
 	(cmdline_parse_inst_t *)&cmd_set_vf_split_drop_en,
 	(cmdline_parse_inst_t *)&cmd_set_vf_mac_addr,
+	(cmdline_parse_inst_t *)&cmd_set_macsec_offload_on,
+	(cmdline_parse_inst_t *)&cmd_set_macsec_offload_off,
+	(cmdline_parse_inst_t *)&cmd_set_macsec_sc,
+	(cmdline_parse_inst_t *)&cmd_set_macsec_sa,
 #endif
 	NULL,
 };
diff --git a/app/test-pmd/macfwd.c b/app/test-pmd/macfwd.c
index d361db1..cf7eab1 100644
--- a/app/test-pmd/macfwd.c
+++ b/app/test-pmd/macfwd.c
@@ -113,6 +113,8 @@ pkt_burst_mac_forward(struct fwd_stream *fs)
 		ol_flags = PKT_TX_VLAN_PKT;
 	if (txp->tx_ol_flags & TESTPMD_TX_OFFLOAD_INSERT_QINQ)
 		ol_flags |= PKT_TX_QINQ_PKT;
+	if (txp->tx_ol_flags & TESTPMD_TX_OFFLOAD_MACSEC)
+		ol_flags |= PKT_TX_MACSEC;
 	for (i = 0; i < nb_rx; i++) {
 		if (likely(i < nb_rx - 1))
 			rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i + 1],
diff --git a/app/test-pmd/macswap.c b/app/test-pmd/macswap.c
index f996039..3a09351 100644
--- a/app/test-pmd/macswap.c
+++ b/app/test-pmd/macswap.c
@@ -113,6 +113,8 @@ pkt_burst_mac_swap(struct fwd_stream *fs)
 		ol_flags = PKT_TX_VLAN_PKT;
 	if (txp->tx_ol_flags & TESTPMD_TX_OFFLOAD_INSERT_QINQ)
 		ol_flags |= PKT_TX_QINQ_PKT;
+	if (txp->tx_ol_flags & TESTPMD_TX_OFFLOAD_MACSEC)
+		ol_flags |= PKT_TX_MACSEC;
 	for (i = 0; i < nb_rx; i++) {
 		if (likely(i < nb_rx - 1))
 			rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i + 1],
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index 22ce2d6..0a9a1af 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -143,6 +143,8 @@ struct fwd_stream {
 #define TESTPMD_TX_OFFLOAD_INSERT_VLAN       0x0040
 /** Insert double VLAN header in forward engine */
 #define TESTPMD_TX_OFFLOAD_INSERT_QINQ       0x0080
+/** Offload MACsec in forward engine */
+#define TESTPMD_TX_OFFLOAD_MACSEC            0x0100
 
 /** Descriptor for a single flow. */
 struct port_flow {
diff --git a/app/test-pmd/txonly.c b/app/test-pmd/txonly.c
index e996f35..8b1a2af 100644
--- a/app/test-pmd/txonly.c
+++ b/app/test-pmd/txonly.c
@@ -215,6 +215,8 @@ pkt_burst_transmit(struct fwd_stream *fs)
 		ol_flags = PKT_TX_VLAN_PKT;
 	if (txp->tx_ol_flags & TESTPMD_TX_OFFLOAD_INSERT_QINQ)
 		ol_flags |= PKT_TX_QINQ_PKT;
+	if (txp->tx_ol_flags & TESTPMD_TX_OFFLOAD_MACSEC)
+		ol_flags |= PKT_TX_MACSEC;
 	for (nb_pkt = 0; nb_pkt < nb_pkt_per_burst; nb_pkt++) {
 		pkt = rte_mbuf_raw_alloc(mbp);
 		if (pkt == NULL) {
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index c611dc5..e3222c0 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -507,6 +507,38 @@ Set mac antispoof for a VF from the PF::
 
    testpmd> set vf mac antispoof  (port_id) (vf_id) (on|off)
 
+set macsec offload
+~~~~~~~~~~~~~~~~~~
+
+Enable/disable MACsec offload::
+
+   testpmd> set macsec offload (port_id) on encrypt (on|off) replay-protect (on|off)
+   testpmd> set macsec offload (port_id) off
+
+set macsec sc
+~~~~~~~~~~~~~
+
+Configure MACsec secure connection (SC)::
+
+   testpmd> set macsec sc (tx|rx) (port_id) (mac) (pi)
+
+.. note::
+
+   The pi argument is ignored for tx.
+   Check the NIC Datasheet for hardware limits.
+
+set macsec sa
+~~~~~~~~~~~~~
+
+Configure MACsec secure association (SA)::
+
+   testpmd> set macsec sa (tx|rx) (port_id) (idx) (an) (pn) (key)
+
+.. note::
+
+   The IDX value must be 0 or 1.
+   Check the NIC Datasheet for hardware limits.
+
 vlan set strip
 ~~~~~~~~~~~~~~
 
-- 
2.7.4

^ permalink raw reply related

* [PATCH v7 6/6] doc: add ixgbe specific APIs
From: Tiwei Bie @ 2017-01-13 11:02 UTC (permalink / raw)
  To: dev
  Cc: adrien.mazarguil, wenzhuo.lu, john.mcnamara, olivier.matz,
	thomas.monjalon, konstantin.ananyev, helin.zhang, wei.dai,
	xiao.w.wang
In-Reply-To: <1484305346-157143-1-git-send-email-tiwei.bie@intel.com>

Add information about the new ixgbe PMD APIs in the release notes.

Signed-off-by: Tiwei Bie <tiwei.bie@intel.com>
Acked-by: John McNamara <john.mcnamara@intel.com>
---
 doc/guides/rel_notes/release_17_02.rst | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst
index 3958714..a3490a5 100644
--- a/doc/guides/rel_notes/release_17_02.rst
+++ b/doc/guides/rel_notes/release_17_02.rst
@@ -52,6 +52,11 @@ New Features
   See the :ref:`Generic flow API <Generic_flow_API>` documentation for more
   information.
 
+* **Added APIs for MACsec offload support to the ixgbe PMD.**
+
+  Six new APIs have been added to the ixgbe PMD for MACsec offload support.
+  The declarations for the APIs can be found in ``rte_pmd_ixgbe.h``.
+
 * **Improved offload support in mbuf.**
 
   Added a new Tx mbuf flag for MACsec, which can be set by applications
-- 
2.7.4

^ permalink raw reply related

* Re: [PATCH v3 25/29] net/nfp: use eal I/O device memory read/write API
From: Alejandro Lucero @ 2017-01-13 11:11 UTC (permalink / raw)
  To: Jerin Jacob
  Cc: dev, Ananyev, Konstantin, Thomas Monjalon, Bruce Richardson,
	jianbo.liu, Jan Viktorin, santosh.shukla
In-Reply-To: <20170113105750.GA28699@localhost.localdomain>

On Fri, Jan 13, 2017 at 10:57 AM, Jerin Jacob <
jerin.jacob@caviumnetworks.com> wrote:

> On Fri, Jan 13, 2017 at 10:49:15AM +0000, Alejandro Lucero wrote:
> > Thanks for that repo. It really makes things easier.
> >
> > I have run our NFP PMD unit tests using that repo, and this change seems
> to
> > work without no problem.
> >
> > Thanks again.
>
> Thanks Alejandro. Can I add you Acked by on your NFP PMD specific
> change.i.e only for this patch([PATCH v3 25/29] net/nfp: use eal I/O
> device memory read/write API)
>
>
Sure.

Thanks!


> >
> >
> >
> > On Thu, Jan 12, 2017 at 1:40 PM, Jerin Jacob <
> jerin.jacob@caviumnetworks.com
> > > wrote:
> >
> > > On Thu, Jan 12, 2017 at 10:53:17AM +0000, Alejandro Lucero wrote:
> > > > Hi,
> > > >
> > > > I've tried to find out which dpdk repo should I use for testing this
> > > change
> > > > with NFP PMD.
> > > >
> > > > It seems rte_read/write functions are not with last dpdk main repo,
> nor
> > > > with dpdk-net-next.
> > > >
> > > > Can someone tell me which repo should I use?
> > >
> > > It is based on the dpdk main repo. This patchset has 29 patches. The
> > > initial
> > > patches in the series contains the definition of rte_read/write.
> > >
> > > I have created a temporary branch in public repo to make other users to
> > > test the changes without applying all patches.
> > >
> > > https://github.com/jerinjacobk/dpdk.git
> > > branch: rte_io_v3
> > > It is based on today's dpdk master and this patchset.
> > >
> > >
>

^ permalink raw reply

* Re: [dpdk-users]  IGB_UIO: PCI Resources Management
From: Alejandro Lucero @ 2017-01-13 11:10 UTC (permalink / raw)
  To: Tan, Jianfeng; +Cc: Yigit, Ferruh, Gregory Etelson, dev, users@dpdk.org
In-Reply-To: <ED26CBA2FAD1BF48A8719AEF02201E3651111E1E@SHSMSX103.ccr.corp.intel.com>

I completely misread the patch, and I wrongly thought that code was linked
to module removal, but I see this is not about that, but about releasing
the /dev/uio file calling release function, what is done by the kernel when
the process exits.

So yes, the patch avoids the problem I talked about.

However, calling that specific ixgbe driver function will break other
devices relying on igb_uio. What about implementing a notifier chain for
this? The igb_uio code would be agnostic and each interested driver, like
ixgbe or nfp_net, could execute the specific port close code when the
notifier chain triggers.


On Fri, Jan 13, 2017 at 5:33 AM, Tan, Jianfeng <jianfeng.tan@intel.com>
wrote:

>
>
> > -----Original Message-----
> > From: Yigit, Ferruh
> > Sent: Friday, January 13, 2017 10:05 AM
> > To: Tan, Jianfeng; Alejandro Lucero
> > Cc: Gregory Etelson; dev; users@dpdk.org
> > Subject: Re: [dpdk-users] [dpdk-dev] IGB_UIO: PCI Resources Management
> >
> > On 1/13/2017 1:51 AM, Tan, Jianfeng wrote:
> > >
> > >
> > >> -----Original Message-----
> > >> From: users [mailto:users-bounces@dpdk.org] On Behalf Of Ferruh Yigit
> > >> Sent: Thursday, January 12, 2017 8:22 PM
> > >> To: Alejandro Lucero
> > >> Cc: Gregory Etelson; dev; users@dpdk.org
> > >> Subject: Re: [dpdk-users] [dpdk-dev] IGB_UIO: PCI Resources
> > Management
> > >>
> > >> On 1/12/2017 12:12 PM, Alejandro Lucero wrote:
> > >>>
> > >>>
> > >>> On Thu, Jan 12, 2017 at 11:55 AM, Ferruh Yigit <
> ferruh.yigit@intel.com
> > >>> <mailto:ferruh.yigit@intel.com>> wrote:
> > >>>
> > >>>     On 12/9/2016 8:54 AM, Gregory Etelson wrote:
> > >>>     > Hello,
> > >>>     >
> > >>>     > IGB_UIO driver does not close port PCI activities after DPDK
> process
> > >> exits.
> > >>>     > DPDK API provides rte_eth_dev_close() to manage port PCI,
> > >>>     > but it can be skipped if process receives SIGKILL signal
> > >>>
> > >>>     I guess I understand the problem.
> > >>>
> > >>>
> > >>> This is a known problem, but it is not just a UIO problem, and this
> > >>> patch does not solve it, maybe it just solves part of it.
> > >>>
> > >>> In fact, a DPDK program crashing could imply the NIC DMAing after
> that
> > >>> and after that memory was assigned to another program.
> > >>
> > >> Yes.
> > >> Can there be a way to stop NIC DMA, (or prevent it access to mem
> > >> anymore) when app crashes?
> > >> I think that is what this patch is looking for.
> > >
> > > If I understand it correctly, you are looking for this patch?
> > > http://dpdk.org/dev/patchwork/patch/17495/
> > >
> >
> > That is good, thanks Jianfeng, I will check it.
> >
> > btw, patch's current state is rejected, which is by mistake, it seems I
> > confused it with "iomem and ioport mapping" patch, sorry about it, I
> > will update its status immediately.
>
> No problem at all. This patch is rejected as it's based on "iomem and
> ioport mapping" patch. As "iomem and ioport mapping" patch has backward
> compatibility issue, we need to figure out a way to resubmit this patch
> without changing the original "iomem and ioport mapping" in igb_uio.
>
> Thanks,
> Jianfeng
>

^ permalink raw reply

* Re: [PATCH v6 14/18] net/ixgbe: parse L2 tunnel filter
From: Ferruh Yigit @ 2017-01-13 11:18 UTC (permalink / raw)
  To: Wei Zhao, dev, Adrien Mazarguil; +Cc: Wenzhuo Lu
In-Reply-To: <1484295192-34009-15-git-send-email-wei.zhao1@intel.com>

On 1/13/2017 8:13 AM, Wei Zhao wrote:
> check if the rule is a L2 tunnel rule, and get the L2 tunnel info.
> 
> Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
> Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
> ---
>  drivers/net/ixgbe/ixgbe_ethdev.c |   3 +-
>  drivers/net/ixgbe/ixgbe_flow.c   | 216 +++++++++++++++++++++++++++++++++++++++
>  lib/librte_ether/rte_flow.h      |  48 +++++++++
>  3 files changed, 266 insertions(+), 1 deletion(-)

> <...>

Hi Adrien,

Can you please review rte_flow related part of the patch below?

I am OK with rest of the patch, and planning to apply to next-net if you
don't have any objection.

Thanks,
ferruh


>  
> diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
> index 98084ac..7142479 100644
> --- a/lib/librte_ether/rte_flow.h
> +++ b/lib/librte_ether/rte_flow.h
> @@ -268,6 +268,20 @@ enum rte_flow_item_type {
>  	 * See struct rte_flow_item_vxlan.
>  	 */
>  	RTE_FLOW_ITEM_TYPE_VXLAN,
> +
> +	/**
> +	 * Matches a E_TAG header.
> +	 *
> +	 * See struct rte_flow_item_e_tag.
> +	 */
> +	RTE_FLOW_ITEM_TYPE_E_TAG,
> +
> +	/**
> +	 * Matches a NVGRE header.
> +	 *
> +	 * See struct rte_flow_item_nvgre.
> +	 */
> +	RTE_FLOW_ITEM_TYPE_NVGRE,
>  };
>  
>  /**
> @@ -454,6 +468,40 @@ struct rte_flow_item_vxlan {
>  };
>  
>  /**
> + * RTE_FLOW_ITEM_TYPE_E_TAG.
> + *
> + * Matches a E-tag header.
> + */
> +struct rte_flow_item_e_tag {
> +	uint16_t tpid; /**< Tag protocol identifier (0x893F). */
> +	/** E-Tag control information (E-TCI). */
> +	/**< E-PCP (3b), E-DEI (1b), ingress E-CID base (12b). */
> +	uint16_t epcp_edei_in_ecid_b;
> +	/**< Reserved (2b), GRP (2b), E-CID base (12b). */
> +	uint16_t rsvd_grp_ecid_b;
> +	uint8_t in_ecid_e; /**< Ingress E-CID ext. */
> +	uint8_t ecid_e; /**< E-CID ext. */
> +};
> +
> +/**
> + * RTE_FLOW_ITEM_TYPE_NVGRE.
> + *
> + * Matches a NVGRE header.
> + */
> +struct rte_flow_item_nvgre {
> +     /**
> +      * Checksum (1b), undefined (1b), key bit (1b), sequence number (1b),
> +      * reserved 0 (9b), version (3b).
> +      *
> +      * \c_k_s_rsvd0_ver must have value 0x2000 according to RFC 7637.
> +      */
> +	uint16_t c_k_s_rsvd0_ver;
> +	uint16_t protocol; /**< Protocol type (0x6558). */
> +	uint8_t tni[3]; /**< Virtual subnet ID. */
> +	uint8_t flow_id; /**< Flow ID. */
> +};
> +
> +/**
>   * Matching pattern item definition.
>   *
>   * A pattern is formed by stacking items starting from the lowest protocol
> 

^ permalink raw reply

* [PATCH v7 1/6] mbuf: add flag for MACsec
From: Tiwei Bie @ 2017-01-13 11:21 UTC (permalink / raw)
  To: dev
  Cc: adrien.mazarguil, wenzhuo.lu, john.mcnamara, olivier.matz,
	thomas.monjalon, konstantin.ananyev, helin.zhang, wei.dai,
	xiao.w.wang
In-Reply-To: <1484306501-164565-1-git-send-email-tiwei.bie@intel.com>

Add a new Tx flag in mbuf, that can be set by applications to
enable the MACsec offload for a packet to be transmitted.

Signed-off-by: Tiwei Bie <tiwei.bie@intel.com>
Acked-by: Olivier Matz <olivier.matz@6wind.com>
---
 doc/guides/rel_notes/release_17_02.rst | 5 +++++
 lib/librte_mbuf/rte_mbuf.c             | 2 ++
 lib/librte_mbuf/rte_mbuf.h             | 6 ++++++
 3 files changed, 13 insertions(+)

diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst
index 180af82..3958714 100644
--- a/doc/guides/rel_notes/release_17_02.rst
+++ b/doc/guides/rel_notes/release_17_02.rst
@@ -52,6 +52,11 @@ New Features
   See the :ref:`Generic flow API <Generic_flow_API>` documentation for more
   information.
 
+* **Improved offload support in mbuf.**
+
+  Added a new Tx mbuf flag for MACsec, which can be set by applications
+  to enable the MACsec offload for the packets to be transmitted.
+
 
 Resolved Issues
 ---------------
diff --git a/lib/librte_mbuf/rte_mbuf.c b/lib/librte_mbuf/rte_mbuf.c
index 63f43c8..72ad91e 100644
--- a/lib/librte_mbuf/rte_mbuf.c
+++ b/lib/librte_mbuf/rte_mbuf.c
@@ -404,6 +404,7 @@ const char *rte_get_tx_ol_flag_name(uint64_t mask)
 	case PKT_TX_TUNNEL_GRE: return "PKT_TX_TUNNEL_GRE";
 	case PKT_TX_TUNNEL_IPIP: return "PKT_TX_TUNNEL_IPIP";
 	case PKT_TX_TUNNEL_GENEVE: return "PKT_TX_TUNNEL_GENEVE";
+	case PKT_TX_MACSEC: return "PKT_TX_MACSEC";
 	default: return NULL;
 	}
 }
@@ -434,6 +435,7 @@ rte_get_tx_ol_flag_list(uint64_t mask, char *buf, size_t buflen)
 		  "PKT_TX_TUNNEL_NONE" },
 		{ PKT_TX_TUNNEL_GENEVE, PKT_TX_TUNNEL_MASK,
 		  "PKT_TX_TUNNEL_NONE" },
+		{ PKT_TX_MACSEC, PKT_TX_MACSEC, NULL },
 	};
 	const char *name;
 	unsigned int i;
diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
index 4476d75..ffbb4b3 100644
--- a/lib/librte_mbuf/rte_mbuf.h
+++ b/lib/librte_mbuf/rte_mbuf.h
@@ -182,6 +182,12 @@ extern "C" {
 /* add new TX flags here */
 
 /**
+ * Offload the MACsec. This flag must be set by the application to enable
+ * this offload feature for a packet to be transmitted.
+ */
+#define PKT_TX_MACSEC        (1ULL << 44)
+
+/**
  * Bits 45:48 used for the tunnel type.
  * When doing Tx offload like TSO or checksum, the HW needs to configure the
  * tunnel type into the HW descriptors.
-- 
2.7.4

^ permalink raw reply related

* [PATCH v7 0/6] Add MACsec offload support for ixgbe
From: Tiwei Bie @ 2017-01-13 11:21 UTC (permalink / raw)
  To: dev
  Cc: adrien.mazarguil, wenzhuo.lu, john.mcnamara, olivier.matz,
	thomas.monjalon, konstantin.ananyev, helin.zhang, wei.dai,
	xiao.w.wang
In-Reply-To: <1484109098-8936-1-git-send-email-tiwei.bie@intel.com>

This patch set adds the MACsec offload support for ixgbe.
The testpmd is also updated to support MACsec cmds.

v2:
- Update the documents for testpmd;
- Update the release notes;
- Reuse the functions provided by base code;

v3:
- Add the missing parts of MACsec mbuf flag and reorganize the patch set;
- Add an ethdev event type for MACsec;
- Advertise the MACsec offload capabilities based on the mac type;
- Minor fixes and improvements;

v4:
- Reserve bits in mbuf and ethdev for PMD specific API;
- Use the reserved bits in PMD specific API;

v5:
- Add MACsec offload in the NIC feature list;
- Minor improvements on comments;

v6:
- Revert the changes related to the reserved flags;
- Rebase the patch set on the latest branch, xstats code is changed recently;
- Update the feature list when adding the MACsec support for ixgbe;

v7:
- Fix clang build;

Tiwei Bie (6):
  mbuf: add flag for MACsec
  ethdev: add event type for MACsec
  ethdev: add MACsec offload capability flags
  net/ixgbe: add MACsec offload support
  app/testpmd: add MACsec offload commands
  doc: add ixgbe specific APIs

 app/test-pmd/cmdline.c                      | 389 ++++++++++++++++++++++
 app/test-pmd/macfwd.c                       |   2 +
 app/test-pmd/macswap.c                      |   2 +
 app/test-pmd/testpmd.h                      |   2 +
 app/test-pmd/txonly.c                       |   2 +
 doc/guides/nics/features/default.ini        |   1 +
 doc/guides/nics/features/ixgbe.ini          |   1 +
 doc/guides/rel_notes/release_17_02.rst      |  10 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  32 ++
 drivers/net/ixgbe/ixgbe_ethdev.c            | 482 +++++++++++++++++++++++++++-
 drivers/net/ixgbe/ixgbe_ethdev.h            |  45 +++
 drivers/net/ixgbe/ixgbe_rxtx.c              |   3 +
 drivers/net/ixgbe/rte_pmd_ixgbe.h           | 100 ++++++
 drivers/net/ixgbe/rte_pmd_ixgbe_version.map |  11 +
 lib/librte_ether/rte_ethdev.h               |   3 +
 lib/librte_mbuf/rte_mbuf.c                  |   2 +
 lib/librte_mbuf/rte_mbuf.h                  |   6 +
 17 files changed, 1088 insertions(+), 5 deletions(-)

-- 
2.7.4

^ permalink raw reply

* [PATCH v7 2/6] ethdev: add event type for MACsec
From: Tiwei Bie @ 2017-01-13 11:21 UTC (permalink / raw)
  To: dev
  Cc: adrien.mazarguil, wenzhuo.lu, john.mcnamara, olivier.matz,
	thomas.monjalon, konstantin.ananyev, helin.zhang, wei.dai,
	xiao.w.wang
In-Reply-To: <1484306501-164565-1-git-send-email-tiwei.bie@intel.com>

This commit adds a below event type:

- RTE_ETH_EVENT_MACSEC

This event will occur when the PN counter in a MACsec connection
reaches the exhaustion threshold.

Signed-off-by: Tiwei Bie <tiwei.bie@intel.com>
---
 lib/librte_ether/rte_ethdev.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 1c356c1..d5d2956 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -3188,6 +3188,7 @@ enum rte_eth_event_type {
 	RTE_ETH_EVENT_INTR_RESET,
 			/**< reset interrupt event, sent to VF on PF reset */
 	RTE_ETH_EVENT_VF_MBOX,  /**< message from the VF received by PF */
+	RTE_ETH_EVENT_MACSEC,   /**< MACsec offload related event */
 	RTE_ETH_EVENT_MAX       /**< max value of this enum */
 };
 
-- 
2.7.4

^ permalink raw reply related

* [PATCH v7 3/6] ethdev: add MACsec offload capability flags
From: Tiwei Bie @ 2017-01-13 11:21 UTC (permalink / raw)
  To: dev
  Cc: adrien.mazarguil, wenzhuo.lu, john.mcnamara, olivier.matz,
	thomas.monjalon, konstantin.ananyev, helin.zhang, wei.dai,
	xiao.w.wang
In-Reply-To: <1484306501-164565-1-git-send-email-tiwei.bie@intel.com>

If these flags are advertised by a PMD, the NIC supports the MACsec
offload. The incoming MACsec traffics can be offloaded transparently
after the MACsec offload is configured correctly by the application.
And the application can set the PKT_TX_MACSEC flag in mbufs to enable
the MACsec offload for the packets to be transmitted.

Signed-off-by: Tiwei Bie <tiwei.bie@intel.com>
---
 lib/librte_ether/rte_ethdev.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index d5d2956..49c073b 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -881,6 +881,7 @@ struct rte_eth_conf {
 #define DEV_RX_OFFLOAD_TCP_LRO     0x00000010
 #define DEV_RX_OFFLOAD_QINQ_STRIP  0x00000020
 #define DEV_RX_OFFLOAD_OUTER_IPV4_CKSUM 0x00000040
+#define DEV_RX_OFFLOAD_MACSEC_STRIP     0x00000080
 
 /**
  * TX offload capabilities of a device.
@@ -898,6 +899,7 @@ struct rte_eth_conf {
 #define DEV_TX_OFFLOAD_GRE_TNL_TSO      0x00000400    /**< Used for tunneling packet. */
 #define DEV_TX_OFFLOAD_IPIP_TNL_TSO     0x00000800    /**< Used for tunneling packet. */
 #define DEV_TX_OFFLOAD_GENEVE_TNL_TSO   0x00001000    /**< Used for tunneling packet. */
+#define DEV_TX_OFFLOAD_MACSEC_INSERT    0x00002000
 
 /**
  * Ethernet device information
-- 
2.7.4

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox