Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause 2 : : * Copyright 2015 6WIND S.A. 3 : : * Copyright 2015 Mellanox Technologies, Ltd 4 : : */ 5 : : 6 : : #include <stddef.h> 7 : : #include <errno.h> 8 : : #include <stdint.h> 9 : : #include <unistd.h> 10 : : 11 : : #include <ethdev_driver.h> 12 : : #include <rte_common.h> 13 : : #include <rte_malloc.h> 14 : : #include <rte_hypervisor.h> 15 : : 16 : : #include "mlx5.h" 17 : : #include "mlx5_autoconf.h" 18 : : #include "mlx5_rxtx.h" 19 : : #include "mlx5_rx.h" 20 : : #include "mlx5_utils.h" 21 : : #include "mlx5_devx.h" 22 : : 23 : : /** 24 : : * DPDK callback to configure a VLAN filter. 25 : : * 26 : : * @param dev 27 : : * Pointer to Ethernet device structure. 28 : : * @param vlan_id 29 : : * VLAN ID to filter. 30 : : * @param on 31 : : * Toggle filter. 32 : : * 33 : : * @return 34 : : * 0 on success, a negative errno value otherwise and rte_errno is set. 35 : : */ 36 : : int 37 : 0 : mlx5_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) 38 : : { 39 : 0 : struct mlx5_priv *priv = dev->data->dev_private; 40 : : unsigned int i; 41 : : 42 [ # # ]: 0 : DRV_LOG(DEBUG, "port %u %s VLAN filter ID %" PRIu16, 43 : : dev->data->port_id, (on ? "enable" : "disable"), vlan_id); 44 : : MLX5_ASSERT(priv->vlan_filter_n <= RTE_DIM(priv->vlan_filter)); 45 [ # # ]: 0 : for (i = 0; (i != priv->vlan_filter_n); ++i) 46 [ # # ]: 0 : if (priv->vlan_filter[i] == vlan_id) 47 : : break; 48 : : /* Check if there's room for another VLAN filter. */ 49 [ # # ]: 0 : if (i == RTE_DIM(priv->vlan_filter)) { 50 : 0 : rte_errno = ENOMEM; 51 : 0 : return -rte_errno; 52 : : } 53 [ # # ]: 0 : if (i < priv->vlan_filter_n) { 54 : : MLX5_ASSERT(priv->vlan_filter_n != 0); 55 : : /* Enabling an existing VLAN filter has no effect. */ 56 [ # # ]: 0 : if (on) 57 : 0 : goto out; 58 : : /* Remove VLAN filter from list. */ 59 : 0 : --priv->vlan_filter_n; 60 : 0 : memmove(&priv->vlan_filter[i], 61 : 0 : &priv->vlan_filter[i + 1], 62 : : sizeof(priv->vlan_filter[i]) * 63 : 0 : (priv->vlan_filter_n - i)); 64 : 0 : priv->vlan_filter[priv->vlan_filter_n] = 0; 65 : : } else { 66 : : MLX5_ASSERT(i == priv->vlan_filter_n); 67 : : /* Disabling an unknown VLAN filter has no effect. */ 68 [ # # ]: 0 : if (!on) 69 : 0 : goto out; 70 : : /* Add new VLAN filter. */ 71 : 0 : priv->vlan_filter[priv->vlan_filter_n] = vlan_id; 72 : 0 : ++priv->vlan_filter_n; 73 : : } 74 : 0 : out: 75 [ # # ]: 0 : if (dev->data->dev_started) 76 : 0 : return mlx5_traffic_restart(dev); 77 : : return 0; 78 : : } 79 : : 80 : : /** 81 : : * Callback to set/reset VLAN stripping for a specific queue. 82 : : * 83 : : * @param dev 84 : : * Pointer to Ethernet device structure. 85 : : * @param queue 86 : : * RX queue index. 87 : : * @param on 88 : : * Enable/disable VLAN stripping. 89 : : */ 90 : : void 91 : 0 : mlx5_vlan_strip_queue_set(struct rte_eth_dev *dev, uint16_t queue, int on) 92 : : { 93 : 0 : struct mlx5_priv *priv = dev->data->dev_private; 94 : 0 : struct mlx5_rxq_priv *rxq = mlx5_rxq_get(dev, queue); 95 : 0 : struct mlx5_rxq_data *rxq_data = &rxq->ctrl->rxq; 96 : : int ret = 0; 97 : : 98 : : MLX5_ASSERT(rxq != NULL && rxq->ctrl != NULL); 99 : : /* Validate hw support */ 100 [ # # ]: 0 : if (!priv->sh->dev_cap.hw_vlan_strip) { 101 : 0 : DRV_LOG(ERR, "port %u VLAN stripping is not supported", 102 : : dev->data->port_id); 103 : 0 : return; 104 : : } 105 : : /* Validate queue number */ 106 [ # # ]: 0 : if (queue >= priv->rxqs_n) { 107 : 0 : DRV_LOG(ERR, "port %u VLAN stripping, invalid queue number %d", 108 : : dev->data->port_id, queue); 109 : 0 : return; 110 : : } 111 : 0 : DRV_LOG(DEBUG, "port %u set VLAN stripping offloads %d for port %uqueue %d", 112 : : dev->data->port_id, on, rxq_data->port_id, queue); 113 [ # # ]: 0 : if (rxq->ctrl->obj == NULL) { 114 : : /* Update related bits in RX queue. */ 115 : 0 : rxq_data->vlan_strip = !!on; 116 : 0 : return; 117 : : } 118 : 0 : ret = priv->obj_ops.rxq_obj_modify_vlan_strip(rxq, on); 119 [ # # ]: 0 : if (ret) { 120 : 0 : DRV_LOG(ERR, "Port %u failed to modify object stripping mode:" 121 : : " %s", dev->data->port_id, strerror(rte_errno)); 122 : 0 : return; 123 : : } 124 : : /* Update related bits in RX queue. */ 125 : 0 : rxq_data->vlan_strip = !!on; 126 : : } 127 : : 128 : : /** 129 : : * Callback to set/reset VLAN offloads for a port. 130 : : * 131 : : * @param dev 132 : : * Pointer to Ethernet device structure. 133 : : * @param mask 134 : : * VLAN offload bit mask. 135 : : * 136 : : * @return 137 : : * 0 on success, a negative errno value otherwise and rte_errno is set. 138 : : */ 139 : : int 140 : 0 : mlx5_vlan_offload_set(struct rte_eth_dev *dev, int mask) 141 : : { 142 : 0 : struct mlx5_priv *priv = dev->data->dev_private; 143 : : unsigned int i; 144 : : 145 [ # # ]: 0 : if (mask & RTE_ETH_VLAN_STRIP_MASK) { 146 : 0 : int hw_vlan_strip = !!(dev->data->dev_conf.rxmode.offloads & 147 : : RTE_ETH_RX_OFFLOAD_VLAN_STRIP); 148 : : 149 [ # # ]: 0 : if (!priv->sh->dev_cap.hw_vlan_strip) { 150 : 0 : DRV_LOG(ERR, "port %u VLAN stripping is not supported", 151 : : dev->data->port_id); 152 : 0 : return 0; 153 : : } 154 : : /* Run on every RX queue and set/reset VLAN stripping. */ 155 [ # # ]: 0 : for (i = 0; (i != priv->rxqs_n); i++) 156 : 0 : mlx5_vlan_strip_queue_set(dev, i, hw_vlan_strip); 157 : : } 158 : : return 0; 159 : : }