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 <stdint.h>
8 : : #include <string.h>
9 : : #include <inttypes.h>
10 : : #include <errno.h>
11 : :
12 : : #include <rte_ether.h>
13 : : #include <ethdev_driver.h>
14 : : #include <rte_common.h>
15 : :
16 : : #include "mlx5_defs.h"
17 : : #include "mlx5.h"
18 : : #include "mlx5_utils.h"
19 : : #include "mlx5_rxtx.h"
20 : :
21 : : /**
22 : : * Remove a MAC address from the internal array.
23 : : *
24 : : * @param dev
25 : : * Pointer to Ethernet device structure.
26 : : * @param index
27 : : * MAC address index.
28 : : * @param addr
29 : : * If MAC address is actually removed, it will be stored here if pointer is not a NULL.
30 : : *
31 : : * @return
32 : : * True if there was a MAC address under given index.
33 : : */
34 : : static bool
35 : 0 : mlx5_internal_mac_addr_remove(struct rte_eth_dev *dev,
36 : : uint32_t index,
37 : : struct rte_ether_addr *addr)
38 : : {
39 : : MLX5_ASSERT(index < MLX5_MAX_MAC_ADDRESSES);
40 [ # # ]: 0 : if (rte_is_zero_ether_addr(&dev->data->mac_addrs[index]))
41 : : return false;
42 : 0 : mlx5_os_mac_addr_remove(dev, index);
43 [ # # ]: 0 : if (addr != NULL)
44 : 0 : *addr = dev->data->mac_addrs[index];
45 : 0 : memset(&dev->data->mac_addrs[index], 0, sizeof(struct rte_ether_addr));
46 : 0 : return true;
47 : : }
48 : :
49 : : /**
50 : : * Adds a MAC address to the internal array.
51 : : *
52 : : * @param dev
53 : : * Pointer to Ethernet device structure.
54 : : * @param mac_addr
55 : : * MAC address to register.
56 : : * @param index
57 : : * MAC address index.
58 : : *
59 : : * @return
60 : : * 0 on success, a negative errno value otherwise and rte_errno is set.
61 : : */
62 : : static int
63 [ # # ]: 0 : mlx5_internal_mac_addr_add(struct rte_eth_dev *dev, struct rte_ether_addr *mac,
64 : : uint32_t index)
65 : : {
66 : : unsigned int i;
67 : : int ret;
68 : :
69 : : MLX5_ASSERT(index < MLX5_MAX_MAC_ADDRESSES);
70 [ # # ]: 0 : if (rte_is_zero_ether_addr(mac)) {
71 : 0 : rte_errno = EINVAL;
72 : 0 : return -rte_errno;
73 : : }
74 : : /* First, make sure this address isn't already configured. */
75 [ # # ]: 0 : for (i = 0; (i != MLX5_MAX_MAC_ADDRESSES); ++i) {
76 : : /* Skip this index, it's going to be reconfigured. */
77 [ # # ]: 0 : if (i == index)
78 : 0 : continue;
79 [ # # ]: 0 : if (memcmp(&dev->data->mac_addrs[i], mac, sizeof(*mac)))
80 : 0 : continue;
81 : : /* Address already configured elsewhere, return with error. */
82 : 0 : rte_errno = EADDRINUSE;
83 : 0 : return -rte_errno;
84 : : }
85 : 0 : ret = mlx5_os_mac_addr_add(dev, mac, index);
86 [ # # ]: 0 : if (ret)
87 : : return ret;
88 : :
89 : 0 : dev->data->mac_addrs[index] = *mac;
90 : 0 : return 0;
91 : : }
92 : :
93 : : /**
94 : : * DPDK callback to remove a MAC address.
95 : : *
96 : : * @param dev
97 : : * Pointer to Ethernet device structure.
98 : : * @param index
99 : : * MAC address index.
100 : : */
101 : : void
102 : 0 : mlx5_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index)
103 : : {
104 : 0 : struct rte_ether_addr addr = { 0 };
105 : : int ret;
106 : :
107 [ # # ]: 0 : if (index >= MLX5_MAX_UC_MAC_ADDRESSES)
108 : 0 : return;
109 [ # # ]: 0 : if (mlx5_internal_mac_addr_remove(dev, index, &addr)) {
110 : 0 : ret = mlx5_traffic_mac_remove(dev, &addr);
111 [ # # ]: 0 : if (ret)
112 : 0 : DRV_LOG(ERR, "port %u cannot update control flow rules: %s",
113 : : dev->data->port_id, strerror(rte_errno));
114 : : }
115 : : }
116 : :
117 : : /**
118 : : * DPDK callback to add a MAC address.
119 : : *
120 : : * @param dev
121 : : * Pointer to Ethernet device structure.
122 : : * @param mac_addr
123 : : * MAC address to register.
124 : : * @param index
125 : : * MAC address index.
126 : : * @param vmdq
127 : : * VMDq pool index to associate address with (ignored).
128 : : *
129 : : * @return
130 : : * 0 on success, a negative errno value otherwise and rte_errno is set.
131 : : */
132 : : int
133 : 0 : mlx5_mac_addr_add(struct rte_eth_dev *dev, struct rte_ether_addr *mac,
134 : : uint32_t index, uint32_t vmdq __rte_unused)
135 : : {
136 : : int ret;
137 : :
138 [ # # ]: 0 : if (index >= MLX5_MAX_UC_MAC_ADDRESSES) {
139 : 0 : rte_errno = EINVAL;
140 : 0 : return -rte_errno;
141 : : }
142 : 0 : ret = mlx5_internal_mac_addr_add(dev, mac, index);
143 [ # # ]: 0 : if (ret < 0)
144 : : return ret;
145 : 0 : return mlx5_traffic_mac_add(dev, mac);
146 : : }
147 : :
148 : : /**
149 : : * DPDK callback to set primary MAC address.
150 : : *
151 : : * @param dev
152 : : * Pointer to Ethernet device structure.
153 : : * @param mac_addr
154 : : * MAC address to register.
155 : : *
156 : : * @return
157 : : * 0 on success, a negative errno value otherwise and rte_errno is set.
158 : : */
159 : : int
160 : 0 : mlx5_mac_addr_set(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr)
161 : : {
162 : : uint16_t port_id;
163 : 0 : struct mlx5_priv *priv = dev->data->dev_private;
164 : : struct mlx5_priv *pf_priv;
165 [ # # ]: 0 : struct rte_ether_addr old_mac_addr = dev->data->mac_addrs[0];
166 : : int ret;
167 : :
168 : : /* ethdev does not check if new default address is the same as the old one. */
169 [ # # ]: 0 : if (rte_is_same_ether_addr(mac_addr, &old_mac_addr))
170 : : return 0;
171 : :
172 : : /*
173 : : * Configuring the VF instead of its representor,
174 : : * need to skip the special cases:
175 : : * - HPF on BlueField,
176 : : * - SF representors,
177 : : * - uplink ports when running in MPESW mode.
178 : : */
179 [ # # # # : 0 : if (priv->representor && !mlx5_is_hpf(dev) && !mlx5_is_sf_repr(dev) &&
# # ]
180 [ # # ]: 0 : !priv->mpesw_uplink) {
181 : 0 : DRV_LOG(DEBUG, "VF represented by port %u setting primary MAC address",
182 : : dev->data->port_id);
183 [ # # ]: 0 : if (priv->pf_bond >= 0) {
184 : : /* Bonding, get owner PF ifindex from shared data. */
185 : 0 : return mlx5_os_vf_mac_addr_modify
186 : : (priv,
187 : 0 : priv->sh->bond.ports[priv->pf_bond].ifindex,
188 : : mac_addr,
189 : 0 : MLX5_REPRESENTOR_REPR(priv->representor_id));
190 : : }
191 [ # # ]: 0 : RTE_ETH_FOREACH_DEV_SIBLING(port_id, dev->data->port_id) {
192 : 0 : pf_priv = rte_eth_devices[port_id].data->dev_private;
193 [ # # ]: 0 : if (pf_priv->master == 1)
194 : 0 : return mlx5_os_vf_mac_addr_modify
195 : : (priv, pf_priv->if_index, mac_addr,
196 : 0 : MLX5_REPRESENTOR_REPR
197 : : (priv->representor_id));
198 : : }
199 : 0 : rte_errno = -ENOTSUP;
200 : 0 : return rte_errno;
201 : : }
202 : :
203 : 0 : DRV_LOG(DEBUG, "port %u setting primary MAC address",
204 : : dev->data->port_id);
205 : 0 : ret = mlx5_mac_addr_add(dev, mac_addr, 0, 0);
206 [ # # ]: 0 : if (ret)
207 : : return ret;
208 : 0 : return mlx5_traffic_mac_remove(dev, &old_mac_addr);
209 : : }
210 : :
211 : : /**
212 : : * DPDK callback to set multicast addresses list.
213 : : *
214 : : * @see rte_eth_dev_set_mc_addr_list()
215 : : */
216 : : int
217 : 0 : mlx5_set_mc_addr_list(struct rte_eth_dev *dev,
218 : : struct rte_ether_addr *mc_addr_set, uint32_t nb_mc_addr)
219 : : {
220 : : uint32_t i;
221 : : int ret;
222 : :
223 [ # # ]: 0 : if (nb_mc_addr >= MLX5_MAX_MC_MAC_ADDRESSES) {
224 : 0 : rte_errno = ENOSPC;
225 : 0 : return -rte_errno;
226 : : }
227 [ # # ]: 0 : for (i = MLX5_MAX_UC_MAC_ADDRESSES; i != MLX5_MAX_MAC_ADDRESSES; ++i)
228 : 0 : mlx5_internal_mac_addr_remove(dev, i, NULL);
229 : : i = MLX5_MAX_UC_MAC_ADDRESSES;
230 [ # # ]: 0 : while (nb_mc_addr--) {
231 : 0 : ret = mlx5_internal_mac_addr_add(dev, mc_addr_set++, i++);
232 [ # # ]: 0 : if (ret)
233 : 0 : return ret;
234 : : }
235 [ # # ]: 0 : if (!dev->data->promiscuous)
236 : 0 : return mlx5_traffic_restart(dev);
237 : : return 0;
238 : : }
|