xref: /dpdk/drivers/net/mlx5/mlx5_mac.c (revision 465328609aeca77f455175b12440233dbcc5a826)
18fd92a66SOlivier Matz /* SPDX-License-Identifier: BSD-3-Clause
2771fa900SAdrien Mazarguil  * Copyright 2015 6WIND S.A.
35feecc57SShahaf Shuler  * Copyright 2015 Mellanox Technologies, Ltd
4771fa900SAdrien Mazarguil  */
5771fa900SAdrien Mazarguil 
6771fa900SAdrien Mazarguil #include <stddef.h>
7771fa900SAdrien Mazarguil #include <stdint.h>
8771fa900SAdrien Mazarguil #include <string.h>
9771fa900SAdrien Mazarguil #include <inttypes.h>
10771fa900SAdrien Mazarguil #include <errno.h>
11771fa900SAdrien Mazarguil 
12771fa900SAdrien Mazarguil #include <rte_ether.h>
13df96fd0dSBruce Richardson #include <ethdev_driver.h>
14771fa900SAdrien Mazarguil #include <rte_common.h>
15771fa900SAdrien Mazarguil 
167b4f1e6bSMatan Azrad #include "mlx5_defs.h"
17771fa900SAdrien Mazarguil #include "mlx5.h"
18771fa900SAdrien Mazarguil #include "mlx5_utils.h"
193318aef7SAdrien Mazarguil #include "mlx5_rxtx.h"
20771fa900SAdrien Mazarguil 
21771fa900SAdrien Mazarguil /**
2218c01b98SNélio Laranjeiro  * Remove a MAC address from the internal array.
2318c01b98SNélio Laranjeiro  *
2418c01b98SNélio Laranjeiro  * @param dev
2518c01b98SNélio Laranjeiro  *   Pointer to Ethernet device structure.
2618c01b98SNélio Laranjeiro  * @param index
2718c01b98SNélio Laranjeiro  *   MAC address index.
28*46532860SDariusz Sosnowski  * @param addr
29*46532860SDariusz Sosnowski  *   If MAC address is actually removed, it will be stored here if pointer is not a NULL.
30*46532860SDariusz Sosnowski  *
31*46532860SDariusz Sosnowski  * @return
32*46532860SDariusz Sosnowski  *   True if there was a MAC address under given index.
3318c01b98SNélio Laranjeiro  */
34*46532860SDariusz Sosnowski static bool
35*46532860SDariusz Sosnowski mlx5_internal_mac_addr_remove(struct rte_eth_dev *dev,
36*46532860SDariusz Sosnowski 			      uint32_t index,
37*46532860SDariusz Sosnowski 			      struct rte_ether_addr *addr)
3818c01b98SNélio Laranjeiro {
398e46d4e1SAlexander Kozyrev 	MLX5_ASSERT(index < MLX5_MAX_MAC_ADDRESSES);
40538da7a1SOlivier Matz 	if (rte_is_zero_ether_addr(&dev->data->mac_addrs[index]))
41*46532860SDariusz Sosnowski 		return false;
42ab27cdd9SOphir Munk 	mlx5_os_mac_addr_remove(dev, index);
43*46532860SDariusz Sosnowski 	if (addr != NULL)
44*46532860SDariusz Sosnowski 		*addr = dev->data->mac_addrs[index];
456d13ea8eSOlivier Matz 	memset(&dev->data->mac_addrs[index], 0, sizeof(struct rte_ether_addr));
46*46532860SDariusz Sosnowski 	return true;
4718c01b98SNélio Laranjeiro }
4818c01b98SNélio Laranjeiro 
4918c01b98SNélio Laranjeiro /**
5018c01b98SNélio Laranjeiro  * Adds a MAC address to the internal array.
5118c01b98SNélio Laranjeiro  *
5218c01b98SNélio Laranjeiro  * @param dev
5318c01b98SNélio Laranjeiro  *   Pointer to Ethernet device structure.
5418c01b98SNélio Laranjeiro  * @param mac_addr
5518c01b98SNélio Laranjeiro  *   MAC address to register.
5618c01b98SNélio Laranjeiro  * @param index
5718c01b98SNélio Laranjeiro  *   MAC address index.
5818c01b98SNélio Laranjeiro  *
5918c01b98SNélio Laranjeiro  * @return
6018c01b98SNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
6118c01b98SNélio Laranjeiro  */
6218c01b98SNélio Laranjeiro static int
636d13ea8eSOlivier Matz mlx5_internal_mac_addr_add(struct rte_eth_dev *dev, struct rte_ether_addr *mac,
6418c01b98SNélio Laranjeiro 			   uint32_t index)
6518c01b98SNélio Laranjeiro {
6618c01b98SNélio Laranjeiro 	unsigned int i;
67ab27cdd9SOphir Munk 	int ret;
6818c01b98SNélio Laranjeiro 
698e46d4e1SAlexander Kozyrev 	MLX5_ASSERT(index < MLX5_MAX_MAC_ADDRESSES);
70538da7a1SOlivier Matz 	if (rte_is_zero_ether_addr(mac)) {
7118c01b98SNélio Laranjeiro 		rte_errno = EINVAL;
7218c01b98SNélio Laranjeiro 		return -rte_errno;
7318c01b98SNélio Laranjeiro 	}
7418c01b98SNélio Laranjeiro 	/* First, make sure this address isn't already configured. */
7518c01b98SNélio Laranjeiro 	for (i = 0; (i != MLX5_MAX_MAC_ADDRESSES); ++i) {
7618c01b98SNélio Laranjeiro 		/* Skip this index, it's going to be reconfigured. */
7718c01b98SNélio Laranjeiro 		if (i == index)
7818c01b98SNélio Laranjeiro 			continue;
7918c01b98SNélio Laranjeiro 		if (memcmp(&dev->data->mac_addrs[i], mac, sizeof(*mac)))
8018c01b98SNélio Laranjeiro 			continue;
8118c01b98SNélio Laranjeiro 		/* Address already configured elsewhere, return with error. */
8218c01b98SNélio Laranjeiro 		rte_errno = EADDRINUSE;
8318c01b98SNélio Laranjeiro 		return -rte_errno;
8418c01b98SNélio Laranjeiro 	}
85ab27cdd9SOphir Munk 	ret = mlx5_os_mac_addr_add(dev, mac, index);
8618c01b98SNélio Laranjeiro 	if (ret)
8718c01b98SNélio Laranjeiro 		return ret;
88ab27cdd9SOphir Munk 
8918c01b98SNélio Laranjeiro 	dev->data->mac_addrs[index] = *mac;
9018c01b98SNélio Laranjeiro 	return 0;
9118c01b98SNélio Laranjeiro }
9218c01b98SNélio Laranjeiro 
9318c01b98SNélio Laranjeiro /**
943318aef7SAdrien Mazarguil  * DPDK callback to remove a MAC address.
953318aef7SAdrien Mazarguil  *
963318aef7SAdrien Mazarguil  * @param dev
973318aef7SAdrien Mazarguil  *   Pointer to Ethernet device structure.
983318aef7SAdrien Mazarguil  * @param index
993318aef7SAdrien Mazarguil  *   MAC address index.
1003318aef7SAdrien Mazarguil  */
1013318aef7SAdrien Mazarguil void
1023318aef7SAdrien Mazarguil mlx5_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index)
1033318aef7SAdrien Mazarguil {
104*46532860SDariusz Sosnowski 	struct rte_ether_addr addr = { 0 };
105ccdcba53SNélio Laranjeiro 	int ret;
106ccdcba53SNélio Laranjeiro 
10718c01b98SNélio Laranjeiro 	if (index >= MLX5_MAX_UC_MAC_ADDRESSES)
108fa80b3c9SNélio Laranjeiro 		return;
109*46532860SDariusz Sosnowski 	if (mlx5_internal_mac_addr_remove(dev, index, &addr)) {
110*46532860SDariusz Sosnowski 		ret = mlx5_traffic_mac_remove(dev, &addr);
111a6d83b6aSNélio Laranjeiro 		if (ret)
112*46532860SDariusz Sosnowski 			DRV_LOG(ERR, "port %u cannot update control flow rules: %s",
1130f99970bSNélio Laranjeiro 				dev->data->port_id, strerror(rte_errno));
114a6d83b6aSNélio Laranjeiro 	}
115ecc1c29dSAdrien Mazarguil }
116ecc1c29dSAdrien Mazarguil 
117ecc1c29dSAdrien Mazarguil /**
1183318aef7SAdrien Mazarguil  * DPDK callback to add a MAC address.
1193318aef7SAdrien Mazarguil  *
1203318aef7SAdrien Mazarguil  * @param dev
1213318aef7SAdrien Mazarguil  *   Pointer to Ethernet device structure.
1223318aef7SAdrien Mazarguil  * @param mac_addr
1233318aef7SAdrien Mazarguil  *   MAC address to register.
1243318aef7SAdrien Mazarguil  * @param index
1253318aef7SAdrien Mazarguil  *   MAC address index.
1263318aef7SAdrien Mazarguil  * @param vmdq
1273318aef7SAdrien Mazarguil  *   VMDq pool index to associate address with (ignored).
128272733b5SNélio Laranjeiro  *
129272733b5SNélio Laranjeiro  * @return
130a6d83b6aSNélio Laranjeiro  *   0 on success, a negative errno value otherwise and rte_errno is set.
1313318aef7SAdrien Mazarguil  */
1326d01e580SWei Dai int
1336d13ea8eSOlivier Matz mlx5_mac_addr_add(struct rte_eth_dev *dev, struct rte_ether_addr *mac,
13456f08e16SNélio Laranjeiro 		  uint32_t index, uint32_t vmdq __rte_unused)
1353318aef7SAdrien Mazarguil {
13618c01b98SNélio Laranjeiro 	int ret;
137a48deadaSOr Ami 
13818c01b98SNélio Laranjeiro 	if (index >= MLX5_MAX_UC_MAC_ADDRESSES) {
139fa80b3c9SNélio Laranjeiro 		rte_errno = EINVAL;
140fa80b3c9SNélio Laranjeiro 		return -rte_errno;
141fa80b3c9SNélio Laranjeiro 	}
14218c01b98SNélio Laranjeiro 	ret = mlx5_internal_mac_addr_add(dev, mac, index);
14318c01b98SNélio Laranjeiro 	if (ret < 0)
144ccdcba53SNélio Laranjeiro 		return ret;
145*46532860SDariusz Sosnowski 	return mlx5_traffic_mac_add(dev, mac);
1463318aef7SAdrien Mazarguil }
14786977fccSDavid Marchand 
14886977fccSDavid Marchand /**
14986977fccSDavid Marchand  * DPDK callback to set primary MAC address.
15086977fccSDavid Marchand  *
15186977fccSDavid Marchand  * @param dev
15286977fccSDavid Marchand  *   Pointer to Ethernet device structure.
15386977fccSDavid Marchand  * @param mac_addr
15486977fccSDavid Marchand  *   MAC address to register.
155caccf8b3SOlivier Matz  *
156caccf8b3SOlivier Matz  * @return
157caccf8b3SOlivier Matz  *   0 on success, a negative errno value otherwise and rte_errno is set.
15886977fccSDavid Marchand  */
159caccf8b3SOlivier Matz int
1606d13ea8eSOlivier Matz mlx5_mac_addr_set(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr)
16186977fccSDavid Marchand {
1620d1d7317SRaslan Darawsheh 	uint16_t port_id;
1630d1d7317SRaslan Darawsheh 	struct mlx5_priv *priv = dev->data->dev_private;
1641ce7d26dSXueming Li 	struct mlx5_priv *pf_priv;
165*46532860SDariusz Sosnowski 	struct rte_ether_addr old_mac_addr = dev->data->mac_addrs[0];
166*46532860SDariusz Sosnowski 	int ret;
167*46532860SDariusz Sosnowski 
168*46532860SDariusz Sosnowski 	/* ethdev does not check if new default address is the same as the old one. */
169*46532860SDariusz Sosnowski 	if (rte_is_same_ether_addr(mac_addr, &old_mac_addr))
170*46532860SDariusz Sosnowski 		return 0;
1710d1d7317SRaslan Darawsheh 
172753dd702SRaslan Darawsheh 	/*
173753dd702SRaslan Darawsheh 	 * Configuring the VF instead of its representor,
17411c73de9SDariusz Sosnowski 	 * need to skip the special cases:
17511c73de9SDariusz Sosnowski 	 * - HPF on BlueField,
17611c73de9SDariusz Sosnowski 	 * - SF representors,
17711c73de9SDariusz Sosnowski 	 * - uplink ports when running in MPESW mode.
178753dd702SRaslan Darawsheh 	 */
17911c73de9SDariusz Sosnowski 	if (priv->representor && !mlx5_is_hpf(dev) && !mlx5_is_sf_repr(dev) &&
18011c73de9SDariusz Sosnowski 	    !priv->mpesw_uplink) {
1810d1d7317SRaslan Darawsheh 		DRV_LOG(DEBUG, "VF represented by port %u setting primary MAC address",
1820d1d7317SRaslan Darawsheh 			dev->data->port_id);
1831ce7d26dSXueming Li 		if (priv->pf_bond >= 0) {
1841ce7d26dSXueming Li 			/* Bonding, get owner PF ifindex from shared data. */
185ab27cdd9SOphir Munk 			return mlx5_os_vf_mac_addr_modify
186ab27cdd9SOphir Munk 			       (priv,
1871ce7d26dSXueming Li 				priv->sh->bond.ports[priv->pf_bond].ifindex,
188f926cce3SXueming Li 				mac_addr,
1891ce7d26dSXueming Li 				MLX5_REPRESENTOR_REPR(priv->representor_id));
1901ce7d26dSXueming Li 		}
1911ce7d26dSXueming Li 		RTE_ETH_FOREACH_DEV_SIBLING(port_id, dev->data->port_id) {
1921ce7d26dSXueming Li 			pf_priv = rte_eth_devices[port_id].data->dev_private;
1931ce7d26dSXueming Li 			if (pf_priv->master == 1)
1941ce7d26dSXueming Li 				return mlx5_os_vf_mac_addr_modify
1951ce7d26dSXueming Li 				       (priv, pf_priv->if_index, mac_addr,
196f926cce3SXueming Li 					MLX5_REPRESENTOR_REPR
197f926cce3SXueming Li 						(priv->representor_id));
1980d1d7317SRaslan Darawsheh 		}
1990d1d7317SRaslan Darawsheh 		rte_errno = -ENOTSUP;
2000d1d7317SRaslan Darawsheh 		return rte_errno;
2010d1d7317SRaslan Darawsheh 	}
2020d1d7317SRaslan Darawsheh 
203a170a30dSNélio Laranjeiro 	DRV_LOG(DEBUG, "port %u setting primary MAC address",
204a170a30dSNélio Laranjeiro 		dev->data->port_id);
205*46532860SDariusz Sosnowski 	ret = mlx5_mac_addr_add(dev, mac_addr, 0, 0);
206*46532860SDariusz Sosnowski 	if (ret)
207*46532860SDariusz Sosnowski 		return ret;
208*46532860SDariusz Sosnowski 	return mlx5_traffic_mac_remove(dev, &old_mac_addr);
20986977fccSDavid Marchand }
210e0586a8dSNélio Laranjeiro 
211e0586a8dSNélio Laranjeiro /**
212e0586a8dSNélio Laranjeiro  * DPDK callback to set multicast addresses list.
213e0586a8dSNélio Laranjeiro  *
214e0586a8dSNélio Laranjeiro  * @see rte_eth_dev_set_mc_addr_list()
215e0586a8dSNélio Laranjeiro  */
216e0586a8dSNélio Laranjeiro int
217e0586a8dSNélio Laranjeiro mlx5_set_mc_addr_list(struct rte_eth_dev *dev,
2186d13ea8eSOlivier Matz 		      struct rte_ether_addr *mc_addr_set, uint32_t nb_mc_addr)
219e0586a8dSNélio Laranjeiro {
220e0586a8dSNélio Laranjeiro 	uint32_t i;
221e0586a8dSNélio Laranjeiro 	int ret;
222e0586a8dSNélio Laranjeiro 
223e0586a8dSNélio Laranjeiro 	if (nb_mc_addr >= MLX5_MAX_MC_MAC_ADDRESSES) {
224e0586a8dSNélio Laranjeiro 		rte_errno = ENOSPC;
225e0586a8dSNélio Laranjeiro 		return -rte_errno;
226e0586a8dSNélio Laranjeiro 	}
227e0586a8dSNélio Laranjeiro 	for (i = MLX5_MAX_UC_MAC_ADDRESSES; i != MLX5_MAX_MAC_ADDRESSES; ++i)
228*46532860SDariusz Sosnowski 		mlx5_internal_mac_addr_remove(dev, i, NULL);
229e0586a8dSNélio Laranjeiro 	i = MLX5_MAX_UC_MAC_ADDRESSES;
230e0586a8dSNélio Laranjeiro 	while (nb_mc_addr--) {
231e0586a8dSNélio Laranjeiro 		ret = mlx5_internal_mac_addr_add(dev, mc_addr_set++, i++);
232e0586a8dSNélio Laranjeiro 		if (ret)
233e0586a8dSNélio Laranjeiro 			return ret;
234e0586a8dSNélio Laranjeiro 	}
235e0586a8dSNélio Laranjeiro 	if (!dev->data->promiscuous)
236e0586a8dSNélio Laranjeiro 		return mlx5_traffic_restart(dev);
237e0586a8dSNélio Laranjeiro 	return 0;
238e0586a8dSNélio Laranjeiro }
239