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 no_effect; 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 no_effect; 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 : return on ? mlx5_traffic_vlan_add(dev, vlan_id) : mlx5_traffic_vlan_remove(dev, vlan_id); 75 : 0 : no_effect: 76 : : return 0; 77 : : } 78 : : 79 : : /** 80 : : * Callback to set/reset VLAN stripping for a specific queue. 81 : : * 82 : : * @param dev 83 : : * Pointer to Ethernet device structure. 84 : : * @param queue 85 : : * RX queue index. 86 : : * @param on 87 : : * Enable/disable VLAN stripping. 88 : : */ 89 : : void 90 : 0 : mlx5_vlan_strip_queue_set(struct rte_eth_dev *dev, uint16_t queue, int on) 91 : : { 92 : 0 : struct mlx5_priv *priv = dev->data->dev_private; 93 : 0 : struct mlx5_rxq_priv *rxq = mlx5_rxq_get(dev, queue); 94 : 0 : struct mlx5_rxq_data *rxq_data = &rxq->ctrl->rxq; 95 : : int ret = 0; 96 : : 97 : : MLX5_ASSERT(rxq != NULL && rxq->ctrl != NULL); 98 : : /* Validate hw support */ 99 [ # # ]: 0 : if (!priv->sh->dev_cap.hw_vlan_strip) { 100 : 0 : DRV_LOG(ERR, "port %u VLAN stripping is not supported", 101 : : dev->data->port_id); 102 : 0 : return; 103 : : } 104 : : /* Validate queue number */ 105 [ # # ]: 0 : if (queue >= priv->rxqs_n) { 106 : 0 : DRV_LOG(ERR, "port %u VLAN stripping, invalid queue number %d", 107 : : dev->data->port_id, queue); 108 : 0 : return; 109 : : } 110 : 0 : DRV_LOG(DEBUG, "port %u set VLAN stripping offloads %d for port %uqueue %d", 111 : : dev->data->port_id, on, rxq_data->port_id, queue); 112 [ # # ]: 0 : if (rxq->ctrl->obj == NULL) { 113 : : /* Update related bits in RX queue. */ 114 : 0 : rxq_data->vlan_strip = !!on; 115 : 0 : return; 116 : : } 117 : 0 : ret = priv->obj_ops.rxq_obj_modify_vlan_strip(rxq, on); 118 [ # # ]: 0 : if (ret) { 119 : 0 : DRV_LOG(ERR, "Port %u failed to modify object stripping mode:" 120 : : " %s", dev->data->port_id, strerror(rte_errno)); 121 : 0 : return; 122 : : } 123 : : /* Update related bits in RX queue. */ 124 : 0 : rxq_data->vlan_strip = !!on; 125 : : } 126 : : 127 : : /** 128 : : * Callback to set/reset VLAN offloads for a port. 129 : : * 130 : : * @param dev 131 : : * Pointer to Ethernet device structure. 132 : : * @param mask 133 : : * VLAN offload bit mask. 134 : : * 135 : : * @return 136 : : * 0 on success, a negative errno value otherwise and rte_errno is set. 137 : : */ 138 : : int 139 : 0 : mlx5_vlan_offload_set(struct rte_eth_dev *dev, int mask) 140 : : { 141 : 0 : struct mlx5_priv *priv = dev->data->dev_private; 142 : : unsigned int i; 143 : : 144 [ # # ]: 0 : if (mask & RTE_ETH_VLAN_STRIP_MASK) { 145 : 0 : int hw_vlan_strip = !!(dev->data->dev_conf.rxmode.offloads & 146 : : RTE_ETH_RX_OFFLOAD_VLAN_STRIP); 147 : : 148 [ # # ]: 0 : if (!priv->sh->dev_cap.hw_vlan_strip) { 149 : 0 : DRV_LOG(ERR, "port %u VLAN stripping is not supported", 150 : : dev->data->port_id); 151 : 0 : return 0; 152 : : } 153 : : /* Run on every RX queue and set/reset VLAN stripping. */ 154 [ # # ]: 0 : for (i = 0; (i != priv->rxqs_n); i++) 155 : 0 : mlx5_vlan_strip_queue_set(dev, i, hw_vlan_strip); 156 : : } 157 : : return 0; 158 : : }