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 /* 12 * Not needed by this file; included to work around the lack of off_t 13 * definition for mlx5dv.h with unpatched rdma-core versions. 14 */ 15 #include <sys/types.h> 16 17 #include <rte_ethdev_driver.h> 18 #include <rte_common.h> 19 #include <rte_malloc.h> 20 #include <rte_hypervisor.h> 21 22 #include <mlx5.h> 23 #include <mlx5_nl.h> 24 #include <mlx5_malloc.h> 25 26 /* 27 * Release VLAN network device, created for VM workaround. 28 * 29 * @param[in] dev 30 * Ethernet device object, Netlink context provider. 31 * @param[in] vlan 32 * Object representing the network device to release. 33 */ 34 void 35 mlx5_vlan_vmwa_release(struct rte_eth_dev *dev, 36 struct mlx5_vf_vlan *vlan) 37 { 38 struct mlx5_priv *priv = dev->data->dev_private; 39 struct mlx5_nl_vlan_vmwa_context *vmwa = priv->vmwa_context; 40 struct mlx5_nl_vlan_dev *vlan_dev = &vmwa->vlan_dev[0]; 41 42 MLX5_ASSERT(vlan->created); 43 MLX5_ASSERT(priv->vmwa_context); 44 if (!vlan->created || !vmwa) 45 return; 46 vlan->created = 0; 47 MLX5_ASSERT(vlan_dev[vlan->tag].refcnt); 48 if (--vlan_dev[vlan->tag].refcnt == 0 && 49 vlan_dev[vlan->tag].ifindex) { 50 mlx5_nl_vlan_vmwa_delete(vmwa, vlan_dev[vlan->tag].ifindex); 51 vlan_dev[vlan->tag].ifindex = 0; 52 } 53 } 54 55 /** 56 * Acquire VLAN interface with specified tag for VM workaround. 57 * 58 * @param[in] dev 59 * Ethernet device object, Netlink context provider. 60 * @param[in] vlan 61 * Object representing the network device to acquire. 62 */ 63 void 64 mlx5_vlan_vmwa_acquire(struct rte_eth_dev *dev, 65 struct mlx5_vf_vlan *vlan) 66 { 67 struct mlx5_priv *priv = dev->data->dev_private; 68 struct mlx5_nl_vlan_vmwa_context *vmwa = priv->vmwa_context; 69 struct mlx5_nl_vlan_dev *vlan_dev = &vmwa->vlan_dev[0]; 70 71 MLX5_ASSERT(!vlan->created); 72 MLX5_ASSERT(priv->vmwa_context); 73 if (vlan->created || !vmwa) 74 return; 75 if (vlan_dev[vlan->tag].refcnt == 0) { 76 MLX5_ASSERT(!vlan_dev[vlan->tag].ifindex); 77 vlan_dev[vlan->tag].ifindex = 78 mlx5_nl_vlan_vmwa_create(vmwa, vmwa->vf_ifindex, 79 vlan->tag); 80 } 81 if (vlan_dev[vlan->tag].ifindex) { 82 vlan_dev[vlan->tag].refcnt++; 83 vlan->created = 1; 84 } 85 } 86 87 /* 88 * Create per ethernet device VLAN VM workaround context 89 * 90 * @param dev 91 * Pointer to Ethernet device structure. 92 * @param ifindex 93 * Interface index. 94 * 95 * @Return 96 * Pointer to mlx5_nl_vlan_vmwa_context 97 */ 98 void * 99 mlx5_vlan_vmwa_init(struct rte_eth_dev *dev, uint32_t ifindex) 100 { 101 struct mlx5_priv *priv = dev->data->dev_private; 102 struct mlx5_dev_config *config = &priv->config; 103 struct mlx5_nl_vlan_vmwa_context *vmwa; 104 enum rte_hypervisor hv_type; 105 106 /* Do not engage workaround over PF. */ 107 if (!config->vf) 108 return NULL; 109 /* Check whether there is desired virtual environment */ 110 hv_type = rte_hypervisor_get(); 111 switch (hv_type) { 112 case RTE_HYPERVISOR_UNKNOWN: 113 case RTE_HYPERVISOR_VMWARE: 114 /* 115 * The "white list" of configurations 116 * to engage the workaround. 117 */ 118 break; 119 default: 120 /* 121 * The configuration is not found in the "white list". 122 * We should not engage the VLAN workaround. 123 */ 124 return NULL; 125 } 126 vmwa = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*vmwa), sizeof(uint32_t), 127 SOCKET_ID_ANY); 128 if (!vmwa) { 129 DRV_LOG(WARNING, 130 "Can not allocate memory" 131 " for VLAN workaround context"); 132 return NULL; 133 } 134 vmwa->nl_socket = mlx5_nl_init(NETLINK_ROUTE); 135 if (vmwa->nl_socket < 0) { 136 DRV_LOG(WARNING, 137 "Can not create Netlink socket" 138 " for VLAN workaround context"); 139 mlx5_free(vmwa); 140 return NULL; 141 } 142 vmwa->vf_ifindex = ifindex; 143 /* Cleanup for existing VLAN devices. */ 144 return vmwa; 145 } 146 147 /* 148 * Destroy per ethernet device VLAN VM workaround context 149 * 150 * @param dev 151 * Pointer to VM context 152 */ 153 void 154 mlx5_vlan_vmwa_exit(void *vmctx) 155 { 156 unsigned int i; 157 158 struct mlx5_nl_vlan_vmwa_context *vmwa = vmctx; 159 /* Delete all remaining VLAN devices. */ 160 for (i = 0; i < RTE_DIM(vmwa->vlan_dev); i++) { 161 if (vmwa->vlan_dev[i].ifindex) 162 mlx5_nl_vlan_vmwa_delete(vmwa, 163 vmwa->vlan_dev[i].ifindex); 164 } 165 if (vmwa->nl_socket >= 0) 166 close(vmwa->nl_socket); 167 mlx5_free(vmwa); 168 } 169