All MAC RX flows must be updated with VLAN information when configuring a VLAN filter.
Signed-off-by: Adrien Mazarguil <adrien.mazarguil at 6wind.com> Signed-off-by: Nelio Laranjeiro <nelio.laranjeiro at 6wind.com> --- drivers/net/mlx5/Makefile | 1 + drivers/net/mlx5/mlx5.c | 1 + drivers/net/mlx5/mlx5.h | 4 ++ drivers/net/mlx5/mlx5_vlan.c | 166 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 172 insertions(+) create mode 100644 drivers/net/mlx5/mlx5_vlan.c diff --git a/drivers/net/mlx5/Makefile b/drivers/net/mlx5/Makefile index 4d25d9c..8b1e32b 100644 --- a/drivers/net/mlx5/Makefile +++ b/drivers/net/mlx5/Makefile @@ -49,6 +49,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_trigger.c SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_ethdev.c SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_mac.c SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_rxmode.c +SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_vlan.c SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_stats.c # Dependencies. diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c index b182d0b..47070f8 100644 --- a/drivers/net/mlx5/mlx5.c +++ b/drivers/net/mlx5/mlx5.c @@ -141,6 +141,7 @@ static const struct eth_dev_ops mlx5_dev_ops = { .stats_get = mlx5_stats_get, .stats_reset = mlx5_stats_reset, .dev_infos_get = mlx5_dev_infos_get, + .vlan_filter_set = mlx5_vlan_filter_set, .rx_queue_setup = mlx5_rx_queue_setup, .tx_queue_setup = mlx5_tx_queue_setup, .rx_queue_release = mlx5_rx_queue_release, diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index 1d488fb..459dc3d 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -203,6 +203,10 @@ void mlx5_allmulticast_disable(struct rte_eth_dev *); void mlx5_stats_get(struct rte_eth_dev *, struct rte_eth_stats *); void mlx5_stats_reset(struct rte_eth_dev *); +/* mlx5_vlan.c */ + +int mlx5_vlan_filter_set(struct rte_eth_dev *, uint16_t, int); + /* mlx5_trigger.c */ int mlx5_dev_start(struct rte_eth_dev *); diff --git a/drivers/net/mlx5/mlx5_vlan.c b/drivers/net/mlx5/mlx5_vlan.c new file mode 100644 index 0000000..60fe06b --- /dev/null +++ b/drivers/net/mlx5/mlx5_vlan.c @@ -0,0 +1,166 @@ +/*- + * BSD LICENSE + * + * Copyright 2015 6WIND S.A. + * Copyright 2015 Mellanox. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of 6WIND S.A. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stddef.h> +#include <errno.h> +#include <assert.h> +#include <stdint.h> + +/* DPDK headers don't like -pedantic. */ +#ifdef PEDANTIC +#pragma GCC diagnostic ignored "-pedantic" +#endif +#include <rte_ethdev.h> +#include <rte_common.h> +#ifdef PEDANTIC +#pragma GCC diagnostic error "-pedantic" +#endif + +#include "mlx5_utils.h" +#include "mlx5.h" + +/** + * Configure a VLAN filter. + * + * @param dev + * Pointer to Ethernet device structure. + * @param vlan_id + * VLAN ID to filter. + * @param on + * Toggle filter. + * + * @return + * 0 on success, errno value on failure. + */ +static int +vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) +{ + struct priv *priv = dev->data->dev_private; + unsigned int i; + unsigned int j = -1; + + DEBUG("%p: %s VLAN filter ID %" PRIu16, + (void *)dev, (on ? "enable" : "disable"), vlan_id); + for (i = 0; (i != RTE_DIM(priv->vlan_filter)); ++i) { + if (!priv->vlan_filter[i].enabled) { + /* Unused index, remember it. */ + j = i; + continue; + } + if (priv->vlan_filter[i].id != vlan_id) + continue; + /* This VLAN ID is already known, use its index. */ + j = i; + break; + } + /* Check if there's room for another VLAN filter. */ + if (j == (unsigned int)-1) + return ENOMEM; + /* + * VLAN filters apply to all configured MAC addresses, flow + * specifications must be reconfigured accordingly. + */ + priv->vlan_filter[j].id = vlan_id; + if ((on) && (!priv->vlan_filter[j].enabled)) { + /* + * Filter is disabled, enable it. + * Rehashing flows in all RX queues is necessary. + */ + if (priv->rss) + rxq_mac_addrs_del(&priv->rxq_parent); + else + for (i = 0; (i != priv->rxqs_n); ++i) + if ((*priv->rxqs)[i] != NULL) + rxq_mac_addrs_del((*priv->rxqs)[i]); + priv->vlan_filter[j].enabled = 1; + if (priv->started) { + if (priv->rss) + rxq_mac_addrs_add(&priv->rxq_parent); + else + for (i = 0; (i != priv->rxqs_n); ++i) { + if ((*priv->rxqs)[i] == NULL) + continue; + rxq_mac_addrs_add((*priv->rxqs)[i]); + } + } + } else if ((!on) && (priv->vlan_filter[j].enabled)) { + /* + * Filter is enabled, disable it. + * Rehashing flows in all RX queues is necessary. + */ + if (priv->rss) + rxq_mac_addrs_del(&priv->rxq_parent); + else + for (i = 0; (i != priv->rxqs_n); ++i) + if ((*priv->rxqs)[i] != NULL) + rxq_mac_addrs_del((*priv->rxqs)[i]); + priv->vlan_filter[j].enabled = 0; + if (priv->started) { + if (priv->rss) + rxq_mac_addrs_add(&priv->rxq_parent); + else + for (i = 0; (i != priv->rxqs_n); ++i) { + if ((*priv->rxqs)[i] == NULL) + continue; + rxq_mac_addrs_add((*priv->rxqs)[i]); + } + } + } + return 0; +} + +/** + * DPDK callback to configure a VLAN filter. + * + * @param dev + * Pointer to Ethernet device structure. + * @param vlan_id + * VLAN ID to filter. + * @param on + * Toggle filter. + * + * @return + * 0 on success, negative errno value on failure. + */ +int +mlx5_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) +{ + struct priv *priv = dev->data->dev_private; + int ret; + + priv_lock(priv); + ret = vlan_filter_set(dev, vlan_id, on); + priv_unlock(priv); + assert(ret >= 0); + return -ret; +} -- 2.1.0