From patchwork Mon Feb 22 18:02:07 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adrien Mazarguil X-Patchwork-Id: 10747 X-Patchwork-Delegate: bruce.richardson@intel.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [IPv6:::1]) by dpdk.org (Postfix) with ESMTP id 637383237; Mon, 22 Feb 2016 19:02:37 +0100 (CET) Received: from mail-wm0-f43.google.com (mail-wm0-f43.google.com [74.125.82.43]) by dpdk.org (Postfix) with ESMTP id 246632C6E for ; Mon, 22 Feb 2016 19:02:36 +0100 (CET) Received: by mail-wm0-f43.google.com with SMTP id a4so174767792wme.1 for ; Mon, 22 Feb 2016 10:02:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=6wind-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=3yYyCIituQsiN1Ii/MuUjKwvLZ0c76m8KkK0OECwXns=; b=ga+90DTZuRtbSw9X/g+6Nr0MXfbwoaQ3VXs1v8tqs2xzTbH4zRhnv2oAsbRplcspJh PMew0aUVMnkWOUTiYgZHUIqiZqXfDHZbyq59ooyPHQuSNKJE1a78ARlHyV/kk3dSD/Yj ReG6Y5Pmbfm46XnUT6AwcM1gDwt5XQgAVk/Yz+VobUXfTJ01ESbj//HubPCbQfBJDqfy bDvjt0Rr1gYi4VQqF0d//ughkTiHjBnrGF/4tQdWOWOfK0HRuOaH+2Mn+KECwX5EMEUa j6/q/5UI473arUD78fuLWonsLhYhs9UblGFV7L5ezg73iIJsiRovOLoSHfDQMAf1+0cN BFSw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=3yYyCIituQsiN1Ii/MuUjKwvLZ0c76m8KkK0OECwXns=; b=BP7a74ofrpgai8R9eXZfE3X4E7yCj3FArsoEpHQRx0ncrcuXi+Osktgsb8wU/s2l10 P6cUvX06EjDxBt/5v49ZJ4PaTTRdR4u9HsG59O+aLGy0w78ZZg6M9tplQ9xFv8rn/Ow1 RjDfAkmJ5qdL1o1rioNxHAFF7CeXf1gsRQcejL4Hy1m3C6xEkqxkYNGOBGTN+T9aHho1 UxiXc3a2U5BffLwZPJ+AiGQg+mGMQhb/03QIjtPIT2igkmr8C1+qonnZibPkl7cHCF/O GeWkDr5VbKqdM0Zh/6AQWQdWwghsKfHtRnqJkcZTlYARm3bgz3lSMlKfLWgUd4QiZjei Qg2A== X-Gm-Message-State: AG10YOSzZBtkllwE02pRQydlbgYZvwhj0JScwcIXCKhxhgdcmksYSWH2Hl3ufSf7ej/rneC7 X-Received: by 10.28.68.139 with SMTP id r133mr13513439wma.13.1456164156006; Mon, 22 Feb 2016 10:02:36 -0800 (PST) Received: from 6wind.com (guy78-3-82-239-227-177.fbx.proxad.net. [82.239.227.177]) by smtp.gmail.com with ESMTPSA id b203sm22147862wmh.8.2016.02.22.10.02.34 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 22 Feb 2016 10:02:35 -0800 (PST) From: Adrien Mazarguil To: dev@dpdk.org Date: Mon, 22 Feb 2016 19:02:07 +0100 Message-Id: <1456164127-28072-6-git-send-email-adrien.mazarguil@6wind.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1456164127-28072-1-git-send-email-adrien.mazarguil@6wind.com> References: <1454063522-1948-1-git-send-email-adrien.mazarguil@6wind.com> <1456164127-28072-1-git-send-email-adrien.mazarguil@6wind.com> Subject: [dpdk-dev] [PATCH v2 5/5] mlx5: add support for RX VLAN stripping X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" From: Yaacov Hazan Allows HW to strip the 802.1Q header from incoming frames and report it through the mbuf structure. This feature requires MLNX_OFED >= 3.2. Signed-off-by: Yaacov Hazan Signed-off-by: Adrien Mazarguil --- doc/guides/nics/mlx5.rst | 2 + doc/guides/rel_notes/release_16_04.rst | 6 ++ drivers/net/mlx5/mlx5.c | 16 ++++- drivers/net/mlx5/mlx5.h | 3 + drivers/net/mlx5/mlx5_rxq.c | 17 +++++- drivers/net/mlx5/mlx5_rxtx.c | 27 +++++++++ drivers/net/mlx5/mlx5_rxtx.h | 5 ++ drivers/net/mlx5/mlx5_vlan.c | 104 +++++++++++++++++++++++++++++++++ 8 files changed, 178 insertions(+), 2 deletions(-) diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst index 8981068..8422206 100644 --- a/doc/guides/nics/mlx5.rst +++ b/doc/guides/nics/mlx5.rst @@ -83,6 +83,7 @@ Features - Configurable RETA table. - Support for multiple MAC addresses. - VLAN filtering. +- RX VLAN stripping. - Promiscuous mode. - Multicast promiscuous mode. - Hardware checksum offloads. @@ -229,6 +230,7 @@ Currently supported by DPDK: above only: - Flow director. + - RX VLAN stripping. - Minimum firmware version: diff --git a/doc/guides/rel_notes/release_16_04.rst b/doc/guides/rel_notes/release_16_04.rst index b3ced63..4d2f76c 100644 --- a/doc/guides/rel_notes/release_16_04.rst +++ b/doc/guides/rel_notes/release_16_04.rst @@ -73,6 +73,12 @@ This section should contain new features added in this release. Sample format: Only available with Mellanox OFED >= 3.2. +* **mlx5: RX VLAN stripping support.** + + Added support for RX VLAN stripping. + + Only available with Mellanox OFED >= 3.2. + Resolved Issues --------------- diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c index 43e24ff..575420e 100644 --- a/drivers/net/mlx5/mlx5.c +++ b/drivers/net/mlx5/mlx5.c @@ -171,6 +171,10 @@ static const struct eth_dev_ops mlx5_dev_ops = { .mac_addr_add = mlx5_mac_addr_add, .mac_addr_set = mlx5_mac_addr_set, .mtu_set = mlx5_dev_set_mtu, +#ifdef HAVE_EXP_DEVICE_ATTR_VLAN_OFFLOADS + .vlan_strip_queue_set = mlx5_vlan_strip_queue_set, + .vlan_offload_set = mlx5_vlan_offload_set, +#endif /* HAVE_EXP_DEVICE_ATTR_VLAN_OFFLOADS */ .reta_update = mlx5_dev_rss_reta_update, .reta_query = mlx5_dev_rss_reta_query, .rss_hash_update = mlx5_rss_hash_update, @@ -325,7 +329,11 @@ mlx5_pci_devinit(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev) #ifdef HAVE_EXP_QUERY_DEVICE exp_device_attr.comp_mask = IBV_EXP_DEVICE_ATTR_EXP_CAP_FLAGS | - IBV_EXP_DEVICE_ATTR_RX_HASH; + IBV_EXP_DEVICE_ATTR_RX_HASH | +#ifdef HAVE_EXP_DEVICE_ATTR_VLAN_OFFLOADS + IBV_EXP_DEVICE_ATTR_VLAN_OFFLOADS | +#endif /* HAVE_EXP_DEVICE_ATTR_VLAN_OFFLOADS */ + 0; #endif /* HAVE_EXP_QUERY_DEVICE */ DEBUG("using port %u (%08" PRIx32 ")", port, test); @@ -396,6 +404,12 @@ mlx5_pci_devinit(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev) priv->ind_table_max_size = RSS_INDIRECTION_TABLE_SIZE; DEBUG("maximum RX indirection table size is %u", priv->ind_table_max_size); +#ifdef HAVE_EXP_DEVICE_ATTR_VLAN_OFFLOADS + priv->hw_vlan_strip = !!(exp_device_attr.wq_vlan_offloads_cap & + IBV_EXP_RECEIVE_WQ_CVLAN_STRIP); +#endif /* HAVE_EXP_DEVICE_ATTR_VLAN_OFFLOADS */ + DEBUG("VLAN stripping is %ssupported", + (priv->hw_vlan_strip ? "" : "not ")); #else /* HAVE_EXP_QUERY_DEVICE */ priv->ind_table_max_size = RSS_INDIRECTION_TABLE_SIZE; diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index 8019ee3..8442016 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -101,6 +101,7 @@ struct priv { unsigned int allmulti_req:1; /* All multicast mode requested. */ unsigned int hw_csum:1; /* Checksum offload is supported. */ unsigned int hw_csum_l2tun:1; /* Same for L2 tunnels. */ + unsigned int hw_vlan_strip:1; /* VLAN stripping is supported. */ unsigned int vf:1; /* This is a VF device. */ unsigned int pending_alarm:1; /* An alarm is pending. */ /* RX/TX queues. */ @@ -211,6 +212,8 @@ void mlx5_stats_reset(struct rte_eth_dev *); /* mlx5_vlan.c */ int mlx5_vlan_filter_set(struct rte_eth_dev *, uint16_t, int); +void mlx5_vlan_offload_set(struct rte_eth_dev *, int); +void mlx5_vlan_strip_queue_set(struct rte_eth_dev *, uint16_t, int); /* mlx5_trigger.c */ diff --git a/drivers/net/mlx5/mlx5_rxq.c b/drivers/net/mlx5/mlx5_rxq.c index 093f4e5..573ad8f 100644 --- a/drivers/net/mlx5/mlx5_rxq.c +++ b/drivers/net/mlx5/mlx5_rxq.c @@ -1224,6 +1224,8 @@ rxq_setup(struct rte_eth_dev *dev, struct rxq *rxq, uint16_t desc, priv->device_attr.max_qp_wr); DEBUG("priv->device_attr.max_sge is %d", priv->device_attr.max_sge); + /* Configure VLAN stripping. */ + tmpl.vlan_strip = dev->data->dev_conf.rxmode.hw_vlan_strip; attr.wq = (struct ibv_exp_wq_init_attr){ .wq_context = NULL, /* Could be useful in the future. */ .wq_type = IBV_EXP_WQT_RQ, @@ -1238,8 +1240,18 @@ rxq_setup(struct rte_eth_dev *dev, struct rxq *rxq, uint16_t desc, MLX5_PMD_SGE_WR_N), .pd = priv->pd, .cq = tmpl.cq, - .comp_mask = IBV_EXP_CREATE_WQ_RES_DOMAIN, + .comp_mask = + IBV_EXP_CREATE_WQ_RES_DOMAIN | +#ifdef HAVE_EXP_DEVICE_ATTR_VLAN_OFFLOADS + IBV_EXP_CREATE_WQ_VLAN_OFFLOADS | +#endif /* HAVE_EXP_DEVICE_ATTR_VLAN_OFFLOADS */ + 0, .res_domain = tmpl.rd, +#ifdef HAVE_EXP_DEVICE_ATTR_VLAN_OFFLOADS + .vlan_offloads = (tmpl.vlan_strip ? + IBV_EXP_RECEIVE_WQ_CVLAN_STRIP : + 0), +#endif /* HAVE_EXP_DEVICE_ATTR_VLAN_OFFLOADS */ }; tmpl.wq = ibv_exp_create_wq(priv->ctx, &attr.wq); if (tmpl.wq == NULL) { @@ -1262,6 +1274,9 @@ rxq_setup(struct rte_eth_dev *dev, struct rxq *rxq, uint16_t desc, DEBUG("%p: RTE port ID: %u", (void *)rxq, tmpl.port_id); attr.params = (struct ibv_exp_query_intf_params){ .intf_scope = IBV_EXP_INTF_GLOBAL, +#ifdef HAVE_EXP_DEVICE_ATTR_VLAN_OFFLOADS + .intf_version = 1, +#endif /* HAVE_EXP_DEVICE_ATTR_VLAN_OFFLOADS */ .intf = IBV_EXP_INTF_CQ, .obj = tmpl.cq, }; diff --git a/drivers/net/mlx5/mlx5_rxtx.c b/drivers/net/mlx5/mlx5_rxtx.c index fa5e648..7585570 100644 --- a/drivers/net/mlx5/mlx5_rxtx.c +++ b/drivers/net/mlx5/mlx5_rxtx.c @@ -62,6 +62,7 @@ #include "mlx5.h" #include "mlx5_utils.h" #include "mlx5_rxtx.h" +#include "mlx5_autoconf.h" #include "mlx5_defs.h" /** @@ -713,12 +714,19 @@ mlx5_rx_burst_sp(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n) unsigned int seg_headroom = RTE_PKTMBUF_HEADROOM; unsigned int j = 0; uint32_t flags; + uint16_t vlan_tci; /* Sanity checks. */ assert(elts_head < rxq->elts_n); assert(rxq->elts_head < rxq->elts_n); +#ifdef HAVE_EXP_DEVICE_ATTR_VLAN_OFFLOADS + ret = rxq->if_cq->poll_length_flags_cvlan(rxq->cq, NULL, NULL, + &flags, &vlan_tci); +#else /* HAVE_EXP_DEVICE_ATTR_VLAN_OFFLOADS */ ret = rxq->if_cq->poll_length_flags(rxq->cq, NULL, NULL, &flags); + (void)vlan_tci; +#endif /* HAVE_EXP_DEVICE_ATTR_VLAN_OFFLOADS */ if (unlikely(ret < 0)) { struct ibv_wc wc; int wcs_n; @@ -840,6 +848,12 @@ mlx5_rx_burst_sp(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n) PKT_LEN(pkt_buf) = pkt_buf_len; pkt_buf->packet_type = rxq_cq_to_pkt_type(flags); pkt_buf->ol_flags = rxq_cq_to_ol_flags(rxq, flags); +#ifdef HAVE_EXP_DEVICE_ATTR_VLAN_OFFLOADS + if (flags & IBV_EXP_CQ_RX_CVLAN_STRIPPED_V1) { + pkt_buf->ol_flags |= PKT_RX_VLAN_PKT; + pkt_buf->vlan_tci = vlan_tci; + } +#endif /* HAVE_EXP_DEVICE_ATTR_VLAN_OFFLOADS */ /* Return packet. */ *(pkts++) = pkt_buf; @@ -910,6 +924,7 @@ mlx5_rx_burst(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n) struct rte_mbuf *seg = elt->buf; struct rte_mbuf *rep; uint32_t flags; + uint16_t vlan_tci; /* Sanity checks. */ assert(seg != NULL); @@ -921,8 +936,14 @@ mlx5_rx_burst(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n) */ rte_prefetch0(seg); rte_prefetch0(&seg->cacheline1); +#ifdef HAVE_EXP_DEVICE_ATTR_VLAN_OFFLOADS + ret = rxq->if_cq->poll_length_flags_cvlan(rxq->cq, NULL, NULL, + &flags, &vlan_tci); +#else /* HAVE_EXP_DEVICE_ATTR_VLAN_OFFLOADS */ ret = rxq->if_cq->poll_length_flags(rxq->cq, NULL, NULL, &flags); + (void)vlan_tci; +#endif /* HAVE_EXP_DEVICE_ATTR_VLAN_OFFLOADS */ if (unlikely(ret < 0)) { struct ibv_wc wc; int wcs_n; @@ -989,6 +1010,12 @@ mlx5_rx_burst(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n) DATA_LEN(seg) = len; seg->packet_type = rxq_cq_to_pkt_type(flags); seg->ol_flags = rxq_cq_to_ol_flags(rxq, flags); +#ifdef HAVE_EXP_DEVICE_ATTR_VLAN_OFFLOADS + if (flags & IBV_EXP_CQ_RX_CVLAN_STRIPPED_V1) { + seg->ol_flags |= PKT_RX_VLAN_PKT; + seg->vlan_tci = vlan_tci; + } +#endif /* HAVE_EXP_DEVICE_ATTR_VLAN_OFFLOADS */ /* Return packet. */ *(pkts++) = seg; diff --git a/drivers/net/mlx5/mlx5_rxtx.h b/drivers/net/mlx5/mlx5_rxtx.h index b2f72f8..fde0ca2 100644 --- a/drivers/net/mlx5/mlx5_rxtx.h +++ b/drivers/net/mlx5/mlx5_rxtx.h @@ -109,7 +109,11 @@ struct rxq { struct ibv_cq *cq; /* Completion Queue. */ struct ibv_exp_wq *wq; /* Work Queue. */ struct ibv_exp_wq_family *if_wq; /* WQ burst interface. */ +#ifdef HAVE_EXP_DEVICE_ATTR_VLAN_OFFLOADS + struct ibv_exp_cq_family_v1 *if_cq; /* CQ interface. */ +#else /* HAVE_EXP_DEVICE_ATTR_VLAN_OFFLOADS */ struct ibv_exp_cq_family *if_cq; /* CQ interface. */ +#endif /* HAVE_EXP_DEVICE_ATTR_VLAN_OFFLOADS */ unsigned int port_id; /* Port ID for incoming packets. */ unsigned int elts_n; /* (*elts)[] length. */ unsigned int elts_head; /* Current index in (*elts)[]. */ @@ -120,6 +124,7 @@ struct rxq { unsigned int sp:1; /* Use scattered RX elements. */ unsigned int csum:1; /* Enable checksum offloading. */ unsigned int csum_l2tun:1; /* Same for L2 tunnels. */ + unsigned int vlan_strip:1; /* Enable VLAN stripping. */ uint32_t mb_len; /* Length of a mp-issued mbuf. */ struct mlx5_rxq_stats stats; /* RX queue counters. */ unsigned int socket; /* CPU socket ID for allocations. */ diff --git a/drivers/net/mlx5/mlx5_vlan.c b/drivers/net/mlx5/mlx5_vlan.c index 3a07ad1..fa9e3b8 100644 --- a/drivers/net/mlx5/mlx5_vlan.c +++ b/drivers/net/mlx5/mlx5_vlan.c @@ -48,6 +48,7 @@ #include "mlx5_utils.h" #include "mlx5.h" +#include "mlx5_autoconf.h" /** * Configure a VLAN filter. @@ -127,3 +128,106 @@ mlx5_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) assert(ret >= 0); return -ret; } + +/** + * Set/reset VLAN stripping for a specific queue. + * + * @param priv + * Pointer to private structure. + * @param idx + * RX queue index. + * @param on + * Enable/disable VLAN stripping. + */ +static void +priv_vlan_strip_queue_set(struct priv *priv, uint16_t idx, int on) +{ + struct rxq *rxq = (*priv->rxqs)[idx]; +#ifdef HAVE_EXP_DEVICE_ATTR_VLAN_OFFLOADS + struct ibv_exp_wq_attr mod; + uint16_t vlan_offloads = + (on ? IBV_EXP_RECEIVE_WQ_CVLAN_STRIP : 0) | + 0; + int err; + + DEBUG("set VLAN offloads 0x%x for port %d queue %d", + vlan_offloads, rxq->port_id, idx); + mod = (struct ibv_exp_wq_attr){ + .attr_mask = IBV_EXP_WQ_ATTR_VLAN_OFFLOADS, + .vlan_offloads = vlan_offloads, + }; + + err = ibv_exp_modify_wq(rxq->wq, &mod); + if (err) { + ERROR("%p: failed to modified stripping mode: %s", + (void *)priv, strerror(err)); + return; + } + +#endif /* HAVE_EXP_DEVICE_ATTR_VLAN_OFFLOADS */ + + /* Update related bits in RX queue. */ + rxq->vlan_strip = !!on; +} + +/** + * Callback to set/reset VLAN stripping for a specific queue. + * + * @param dev + * Pointer to Ethernet device structure. + * @param queue + * RX queue index. + * @param on + * Enable/disable VLAN stripping. + */ +void +mlx5_vlan_strip_queue_set(struct rte_eth_dev *dev, uint16_t queue, int on) +{ + struct priv *priv = dev->data->dev_private; + + /* Validate hw support */ + if (!priv->hw_vlan_strip) { + ERROR("VLAN stripping is not supported"); + return; + } + + /* Validate queue number */ + if (queue >= priv->rxqs_n) { + ERROR("VLAN stripping, invalid queue number %d", queue); + return; + } + + priv_lock(priv); + priv_vlan_strip_queue_set(priv, queue, on); + priv_unlock(priv); +} + +/** + * Callback to set/reset VLAN offloads for a port. + * + * @param dev + * Pointer to Ethernet device structure. + * @param mask + * VLAN offload bit mask. + */ +void +mlx5_vlan_offload_set(struct rte_eth_dev *dev, int mask) +{ + struct priv *priv = dev->data->dev_private; + unsigned int i; + + if (mask & ETH_VLAN_STRIP_MASK) { + int hw_vlan_strip = dev->data->dev_conf.rxmode.hw_vlan_strip; + + if (!priv->hw_vlan_strip) { + ERROR("VLAN stripping is not supported"); + return; + } + + /* Run on every RX queue and set/reset VLAN stripping. */ + priv_lock(priv); + for (i = 0; (i != priv->rxqs_n); i++) + priv_vlan_strip_queue_set(priv, i, hw_vlan_strip); + priv_unlock(priv); + } +}