From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wm0-f41.google.com (mail-wm0-f41.google.com [74.125.82.41]) by dpdk.org (Postfix) with ESMTP id 4440491DD for ; Fri, 30 Oct 2015 19:53:17 +0100 (CET) Received: by wmff134 with SMTP id f134so18465480wmf.1 for ; Fri, 30 Oct 2015 11:53:17 -0700 (PDT) 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=IfBLm36REnSOvIfJgSyHd9nS9VHE+JFyJLyE4JBdnfI=; b=naRQ3+xzHUjEdI/8B42GtEncDQ0eF0zxNJWSxQwPSUBdVlXc6jRIjrJsjiuBDRcEr3 iv3jKcgyckuvdsXQVh3xSYrsOU+E10mOg4M0dzcxybVBPNm3nFeL433CtRN4zyHwvfyq X8a2uaFNXXmdlZo4jOX+sqy9DcpZ0aoR19JyFHc+kDtLyv3vetB/GtiFE2yVpVVONNaZ c+6vDTevZ/Cvhf4Pg4xkbb5GsN9GbfQjAfgYHDKJgMFRb6YtJga49kMZS3sByJKvHA5o xF4H7RSU5Y6YeHeD9pLbyEwtR6WDi36zvxHp7y3x9IHcNHFvXeu/bg988IXYG+w5b07x 2RlA== 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=IfBLm36REnSOvIfJgSyHd9nS9VHE+JFyJLyE4JBdnfI=; b=gYw4Scx1gQOmv5CIzvQqFfu/f8pvHZNcFtyD67Z/WcXiXy/OvFHag0x42oU1+CgR82 aJDmg15Mcd0MDriWMjqQ98TWWcalbkx2Frm8GwuTE1FzSaPXHRMs2WZtRG+3v4GDsjko gwGgRoFLIl4hyQ4jQwk4MKYmBfFb0e9kn6eArL7ZLHRajBFXEOhz7qzrnl6hXjVSpEhQ pfAv3XxccqQqZxVG2Jb2CKy8zLYfhOTY9hRYmVcYyfhkRIXQ+Kdm4Qz4xGYyaD5fFtSt LsCc3mI683YAmTQ2XZN7fFazqXAOrKcq3HXz6nb9ZthRGPL4GVHKAqwve3CVZ/VhfK6N frEg== X-Gm-Message-State: ALoCoQlDmfhGjx7pRXam4ZyYfmjHtX6wTHqxKD2L3lqjoFQkK10I4xhWCFCXV+FNWM9jgjZZm587 X-Received: by 10.28.212.13 with SMTP id l13mr4942442wmg.39.1446231197138; Fri, 30 Oct 2015 11:53:17 -0700 (PDT) Received: from 6wind.com (guy78-3-82-239-227-177.fbx.proxad.net. [82.239.227.177]) by smtp.gmail.com with ESMTPSA id c1sm8383001wjf.19.2015.10.30.11.53.15 (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Fri, 30 Oct 2015 11:53:16 -0700 (PDT) From: Adrien Mazarguil To: dev@dpdk.org Date: Fri, 30 Oct 2015 19:52:32 +0100 Message-Id: <1446231162-8075-4-git-send-email-adrien.mazarguil@6wind.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1446231162-8075-1-git-send-email-adrien.mazarguil@6wind.com> References: <1444067589-29513-1-git-send-email-adrien.mazarguil@6wind.com> <1446231162-8075-1-git-send-email-adrien.mazarguil@6wind.com> Subject: [dpdk-dev] [PATCH v2 03/13] mlx5: add MAC handling X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 30 Oct 2015 18:53:17 -0000 This commit adds support for MAC flow steering rules mandatory for the RX path as well as the related callbacks to add/remove MAC addresses. Signed-off-by: Adrien Mazarguil Signed-off-by: Nelio Laranjeiro Signed-off-by: Didier Pallard --- drivers/net/mlx5/mlx5.c | 4 +- drivers/net/mlx5/mlx5.h | 5 + drivers/net/mlx5/mlx5_mac.c | 282 +++++++++++++++++++++++++++++++++++++++++++ drivers/net/mlx5/mlx5_rxq.c | 10 ++ drivers/net/mlx5/mlx5_rxtx.h | 2 + 5 files changed, 302 insertions(+), 1 deletion(-) diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c index 54bd6b9..a241c28 100644 --- a/drivers/net/mlx5/mlx5.c +++ b/drivers/net/mlx5/mlx5.c @@ -134,6 +134,8 @@ static const struct eth_dev_ops mlx5_dev_ops = { .tx_queue_setup = mlx5_tx_queue_setup, .rx_queue_release = mlx5_rx_queue_release, .tx_queue_release = mlx5_tx_queue_release, + .mac_addr_remove = mlx5_mac_addr_remove, + .mac_addr_add = mlx5_mac_addr_add, }; static struct { @@ -390,7 +392,7 @@ mlx5_pci_devinit(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev) claim_zero(priv_mac_addr_add(priv, 0, (const uint8_t (*)[ETHER_ADDR_LEN]) mac.addr_bytes)); - claim_zero(priv_mac_addr_add(priv, 1, + claim_zero(priv_mac_addr_add(priv, (RTE_DIM(priv->mac) - 1), &(const uint8_t [ETHER_ADDR_LEN]) { "\xff\xff\xff\xff\xff\xff" })); #ifndef NDEBUG diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index 49978f5..6ab31ad 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -166,7 +166,12 @@ int mlx5_ibv_device_to_pci_addr(const struct ibv_device *, /* mlx5_mac.c */ int priv_get_mac(struct priv *, uint8_t (*)[ETHER_ADDR_LEN]); +void rxq_mac_addrs_del(struct rxq *); +void mlx5_mac_addr_remove(struct rte_eth_dev *, uint32_t); +int rxq_mac_addrs_add(struct rxq *); int priv_mac_addr_add(struct priv *, unsigned int, const uint8_t (*)[ETHER_ADDR_LEN]); +void mlx5_mac_addr_add(struct rte_eth_dev *, struct ether_addr *, uint32_t, + uint32_t); #endif /* RTE_PMD_MLX5_H_ */ diff --git a/drivers/net/mlx5/mlx5_mac.c b/drivers/net/mlx5/mlx5_mac.c index f7e1cf6..262d7c6 100644 --- a/drivers/net/mlx5/mlx5_mac.c +++ b/drivers/net/mlx5/mlx5_mac.c @@ -65,6 +65,8 @@ #include "mlx5.h" #include "mlx5_utils.h" +#include "mlx5_rxtx.h" +#include "mlx5_defs.h" /** * Get MAC address by querying netdevice. @@ -89,8 +91,69 @@ priv_get_mac(struct priv *priv, uint8_t (*mac)[ETHER_ADDR_LEN]) } /** + * Delete MAC flow steering rule. + * + * @param rxq + * Pointer to RX queue structure. + * @param mac_index + * MAC address index. + */ +static void +rxq_del_mac_flow(struct rxq *rxq, unsigned int mac_index) +{ +#ifndef NDEBUG + const uint8_t (*mac)[ETHER_ADDR_LEN] = + (const uint8_t (*)[ETHER_ADDR_LEN]) + rxq->priv->mac[mac_index].addr_bytes; +#endif + + assert(mac_index < RTE_DIM(rxq->mac_flow)); + if (rxq->mac_flow[mac_index] == NULL) + return; + DEBUG("%p: removing MAC address %02x:%02x:%02x:%02x:%02x:%02x index %u", + (void *)rxq, + (*mac)[0], (*mac)[1], (*mac)[2], (*mac)[3], (*mac)[4], (*mac)[5], + mac_index); + claim_zero(ibv_destroy_flow(rxq->mac_flow[mac_index])); + rxq->mac_flow[mac_index] = NULL; +} + +/** + * Unregister a MAC address from a RX queue. + * + * @param rxq + * Pointer to RX queue structure. + * @param mac_index + * MAC address index. + */ +static void +rxq_mac_addr_del(struct rxq *rxq, unsigned int mac_index) +{ + assert(mac_index < RTE_DIM(rxq->mac_flow)); + rxq_del_mac_flow(rxq, mac_index); +} + +/** + * Unregister all MAC addresses from a RX queue. + * + * @param rxq + * Pointer to RX queue structure. + */ +void +rxq_mac_addrs_del(struct rxq *rxq) +{ + unsigned int i; + + for (i = 0; (i != RTE_DIM(rxq->mac_flow)); ++i) + rxq_mac_addr_del(rxq, i); +} + +/** * Unregister a MAC address. * + * In RSS mode, the MAC address is unregistered from the parent queue, + * otherwise it is unregistered from each queue directly. + * * @param priv * Pointer to private structure. * @param mac_index @@ -99,15 +162,179 @@ priv_get_mac(struct priv *priv, uint8_t (*mac)[ETHER_ADDR_LEN]) static void priv_mac_addr_del(struct priv *priv, unsigned int mac_index) { + unsigned int i; + assert(mac_index < RTE_DIM(priv->mac)); if (!BITFIELD_ISSET(priv->mac_configured, mac_index)) return; + if (priv->rss) { + rxq_mac_addr_del(&priv->rxq_parent, mac_index); + goto end; + } + for (i = 0; (i != priv->dev->data->nb_rx_queues); ++i) + rxq_mac_addr_del((*priv->rxqs)[i], mac_index); +end: BITFIELD_RESET(priv->mac_configured, mac_index); } /** + * DPDK callback to remove a MAC address. + * + * @param dev + * Pointer to Ethernet device structure. + * @param index + * MAC address index. + */ +void +mlx5_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index) +{ + struct priv *priv = dev->data->dev_private; + + priv_lock(priv); + DEBUG("%p: removing MAC address from index %" PRIu32, + (void *)dev, index); + /* Last array entry is reserved for broadcast. */ + if (index >= (RTE_DIM(priv->mac) - 1)) + goto end; + priv_mac_addr_del(priv, index); +end: + priv_unlock(priv); +} + +/** + * Add MAC flow steering rule. + * + * @param rxq + * Pointer to RX queue structure. + * @param mac_index + * MAC address index to register. + * + * @return + * 0 on success, errno value on failure. + */ +static int +rxq_add_mac_flow(struct rxq *rxq, unsigned int mac_index) +{ + struct ibv_flow *flow; + struct priv *priv = rxq->priv; + const uint8_t (*mac)[ETHER_ADDR_LEN] = + (const uint8_t (*)[ETHER_ADDR_LEN]) + priv->mac[mac_index].addr_bytes; + struct __attribute__((packed)) { + struct ibv_flow_attr attr; + struct ibv_flow_spec_eth spec; + } data; + struct ibv_flow_attr *attr = &data.attr; + struct ibv_flow_spec_eth *spec = &data.spec; + + assert(mac_index < RTE_DIM(rxq->mac_flow)); + if (rxq->mac_flow[mac_index] != NULL) + return 0; + /* + * No padding must be inserted by the compiler between attr and spec. + * This layout is expected by libibverbs. + */ + assert(((uint8_t *)attr + sizeof(*attr)) == (uint8_t *)spec); + *attr = (struct ibv_flow_attr){ + .type = IBV_FLOW_ATTR_NORMAL, + .num_of_specs = 1, + .port = priv->port, + .flags = 0 + }; + *spec = (struct ibv_flow_spec_eth){ + .type = IBV_FLOW_SPEC_ETH, + .size = sizeof(*spec), + .val = { + .dst_mac = { + (*mac)[0], (*mac)[1], (*mac)[2], + (*mac)[3], (*mac)[4], (*mac)[5] + }, + }, + .mask = { + .dst_mac = "\xff\xff\xff\xff\xff\xff", + }, + }; + DEBUG("%p: adding MAC address %02x:%02x:%02x:%02x:%02x:%02x index %u", + (void *)rxq, + (*mac)[0], (*mac)[1], (*mac)[2], (*mac)[3], (*mac)[4], (*mac)[5], + mac_index); + /* Create related flow. */ + errno = 0; + flow = ibv_create_flow(rxq->qp, attr); + if (flow == NULL) { + /* It's not clear whether errno is always set in this case. */ + ERROR("%p: flow configuration failed, errno=%d: %s", + (void *)rxq, errno, + (errno ? strerror(errno) : "Unknown error")); + if (errno) + return errno; + return EINVAL; + } + rxq->mac_flow[mac_index] = flow; + return 0; +} + +/** + * Register a MAC address in a RX queue. + * + * @param rxq + * Pointer to RX queue structure. + * @param mac_index + * MAC address index to register. + * + * @return + * 0 on success, errno value on failure. + */ +static int +rxq_mac_addr_add(struct rxq *rxq, unsigned int mac_index) +{ + int ret; + + assert(mac_index < RTE_DIM(rxq->mac_flow)); + ret = rxq_add_mac_flow(rxq, mac_index); + if (ret) + return ret; + return 0; +} + +/** + * Register all MAC addresses in a RX queue. + * + * @param rxq + * Pointer to RX queue structure. + * + * @return + * 0 on success, errno value on failure. + */ +int +rxq_mac_addrs_add(struct rxq *rxq) +{ + struct priv *priv = rxq->priv; + unsigned int i; + int ret; + + assert(RTE_DIM(priv->mac) == RTE_DIM(rxq->mac_flow)); + for (i = 0; (i != RTE_DIM(priv->mac)); ++i) { + if (!BITFIELD_ISSET(priv->mac_configured, i)) + continue; + ret = rxq_mac_addr_add(rxq, i); + if (!ret) + continue; + /* Failure, rollback. */ + while (i != 0) + rxq_mac_addr_del(rxq, --i); + assert(ret > 0); + return ret; + } + return 0; +} + +/** * Register a MAC address. * + * In RSS mode, the MAC address is registered in the parent queue, + * otherwise it is registered in each queue directly. + * * @param priv * Pointer to private structure. * @param mac_index @@ -123,6 +350,7 @@ priv_mac_addr_add(struct priv *priv, unsigned int mac_index, const uint8_t (*mac)[ETHER_ADDR_LEN]) { unsigned int i; + int ret; assert(mac_index < RTE_DIM(priv->mac)); /* First, make sure this address isn't already configured. */ @@ -145,6 +373,60 @@ priv_mac_addr_add(struct priv *priv, unsigned int mac_index, (*mac)[3], (*mac)[4], (*mac)[5] } }; + /* If device isn't started, this is all we need to do. */ + if (!priv->started) + goto end; + if (priv->rss) { + ret = rxq_mac_addr_add(&priv->rxq_parent, mac_index); + if (ret) + return ret; + goto end; + } + for (i = 0; (i != priv->rxqs_n); ++i) { + if ((*priv->rxqs)[i] == NULL) + continue; + ret = rxq_mac_addr_add((*priv->rxqs)[i], mac_index); + if (!ret) + continue; + /* Failure, rollback. */ + while (i != 0) + if ((*priv->rxqs)[--i] != NULL) + rxq_mac_addr_del((*priv->rxqs)[i], mac_index); + return ret; + } +end: BITFIELD_SET(priv->mac_configured, mac_index); return 0; } + +/** + * DPDK callback to add a MAC address. + * + * @param dev + * Pointer to Ethernet device structure. + * @param mac_addr + * MAC address to register. + * @param index + * MAC address index. + * @param vmdq + * VMDq pool index to associate address with (ignored). + */ +void +mlx5_mac_addr_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr, + uint32_t index, uint32_t vmdq) +{ + struct priv *priv = dev->data->dev_private; + + (void)vmdq; + priv_lock(priv); + DEBUG("%p: adding MAC address at index %" PRIu32, + (void *)dev, index); + /* Last array entry is reserved for broadcast. */ + if (index >= (RTE_DIM(priv->mac) - 1)) + goto end; + priv_mac_addr_add(priv, index, + (const uint8_t (*)[ETHER_ADDR_LEN]) + mac_addr->addr_bytes); +end: + priv_unlock(priv); +} diff --git a/drivers/net/mlx5/mlx5_rxq.c b/drivers/net/mlx5/mlx5_rxq.c index 01cc649..8450fe3 100644 --- a/drivers/net/mlx5/mlx5_rxq.c +++ b/drivers/net/mlx5/mlx5_rxq.c @@ -248,6 +248,7 @@ rxq_cleanup(struct rxq *rxq) ¶ms)); } if (rxq->qp != NULL) { + rxq_mac_addrs_del(rxq); claim_zero(ibv_destroy_qp(rxq->qp)); } if (rxq->cq != NULL) @@ -515,6 +516,15 @@ skip_mr: (void *)dev, strerror(ret)); goto error; } + if ((parent) || (!priv->rss)) { + /* Configure MAC and broadcast addresses. */ + ret = rxq_mac_addrs_add(&tmpl); + if (ret) { + ERROR("%p: QP flow attachment failed: %s", + (void *)dev, strerror(ret)); + goto error; + } + } /* Allocate descriptors for RX queues, except for the RSS parent. */ if (parent) goto skip_alloc; diff --git a/drivers/net/mlx5/mlx5_rxtx.h b/drivers/net/mlx5/mlx5_rxtx.h index 1459317..3733d3e 100644 --- a/drivers/net/mlx5/mlx5_rxtx.h +++ b/drivers/net/mlx5/mlx5_rxtx.h @@ -78,6 +78,8 @@ struct rxq { struct ibv_qp *qp; /* Queue Pair. */ struct ibv_exp_qp_burst_family *if_qp; /* QP burst interface. */ struct ibv_exp_cq_family *if_cq; /* CQ interface. */ + /* MAC flow steering rules. */ + struct ibv_flow *mac_flow[MLX5_MAX_MAC_ADDRESSES]; unsigned int port_id; /* Port ID for incoming packets. */ unsigned int elts_n; /* (*elts)[] length. */ unsigned int elts_head; /* Current index in (*elts)[]. */ -- 2.1.0