ethdev: return diagnostic when setting MAC address
[dpdk.git] / drivers / net / mlx5 / mlx5_mac.c
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 <assert.h>
8 #include <stdint.h>
9 #include <string.h>
10 #include <inttypes.h>
11 #include <errno.h>
12 #include <netinet/in.h>
13 #include <sys/ioctl.h>
14 #include <arpa/inet.h>
15
16 /* Verbs header. */
17 /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */
18 #ifdef PEDANTIC
19 #pragma GCC diagnostic ignored "-Wpedantic"
20 #endif
21 #include <infiniband/verbs.h>
22 #ifdef PEDANTIC
23 #pragma GCC diagnostic error "-Wpedantic"
24 #endif
25
26 #include <rte_ether.h>
27 #include <rte_ethdev_driver.h>
28 #include <rte_common.h>
29
30 #include "mlx5.h"
31 #include "mlx5_utils.h"
32 #include "mlx5_rxtx.h"
33 #include "mlx5_defs.h"
34
35 /**
36  * Get MAC address by querying netdevice.
37  *
38  * @param[in] dev
39  *   Pointer to Ethernet device.
40  * @param[out] mac
41  *   MAC address output buffer.
42  *
43  * @return
44  *   0 on success, a negative errno value otherwise and rte_errno is set.
45  */
46 int
47 mlx5_get_mac(struct rte_eth_dev *dev, uint8_t (*mac)[ETHER_ADDR_LEN])
48 {
49         struct ifreq request;
50         int ret;
51
52         ret = mlx5_ifreq(dev, SIOCGIFHWADDR, &request);
53         if (ret)
54                 return ret;
55         memcpy(mac, request.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
56         return 0;
57 }
58
59 /**
60  * DPDK callback to remove a MAC address.
61  *
62  * @param dev
63  *   Pointer to Ethernet device structure.
64  * @param index
65  *   MAC address index.
66  */
67 void
68 mlx5_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index)
69 {
70         struct priv *priv = dev->data->dev_private;
71         const int vf = priv->config.vf;
72         int ret;
73
74         assert(index < MLX5_MAX_MAC_ADDRESSES);
75         if (vf)
76                 mlx5_nl_mac_addr_remove(dev, &dev->data->mac_addrs[index],
77                                         index);
78         memset(&dev->data->mac_addrs[index], 0, sizeof(struct ether_addr));
79         if (!dev->data->promiscuous) {
80                 ret = mlx5_traffic_restart(dev);
81                 if (ret)
82                         DRV_LOG(ERR, "port %u cannot restart traffic: %s",
83                                 dev->data->port_id, strerror(rte_errno));
84         }
85 }
86
87 /**
88  * DPDK callback to add a MAC address.
89  *
90  * @param dev
91  *   Pointer to Ethernet device structure.
92  * @param mac_addr
93  *   MAC address to register.
94  * @param index
95  *   MAC address index.
96  * @param vmdq
97  *   VMDq pool index to associate address with (ignored).
98  *
99  * @return
100  *   0 on success, a negative errno value otherwise and rte_errno is set.
101  */
102 int
103 mlx5_mac_addr_add(struct rte_eth_dev *dev, struct ether_addr *mac,
104                   uint32_t index, uint32_t vmdq __rte_unused)
105 {
106         struct priv *priv = dev->data->dev_private;
107         const int vf = priv->config.vf;
108         unsigned int i;
109
110         assert(index < MLX5_MAX_MAC_ADDRESSES);
111         /* First, make sure this address isn't already configured. */
112         for (i = 0; (i != MLX5_MAX_MAC_ADDRESSES); ++i) {
113                 /* Skip this index, it's going to be reconfigured. */
114                 if (i == index)
115                         continue;
116                 if (memcmp(&dev->data->mac_addrs[i], mac, sizeof(*mac)))
117                         continue;
118                 /* Address already configured elsewhere, return with error. */
119                 rte_errno = EADDRINUSE;
120                 return -rte_errno;
121         }
122         if (vf) {
123                 int ret = mlx5_nl_mac_addr_add(dev, mac, index);
124
125                 if (ret)
126                         return ret;
127         }
128         dev->data->mac_addrs[index] = *mac;
129         if (!dev->data->promiscuous)
130                 return mlx5_traffic_restart(dev);
131         return 0;
132 }
133
134 /**
135  * DPDK callback to set primary MAC address.
136  *
137  * @param dev
138  *   Pointer to Ethernet device structure.
139  * @param mac_addr
140  *   MAC address to register.
141  *
142  * @return
143  *   0 on success, a negative errno value otherwise and rte_errno is set.
144  */
145 int
146 mlx5_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr)
147 {
148         DRV_LOG(DEBUG, "port %u setting primary MAC address",
149                 dev->data->port_id);
150         return mlx5_mac_addr_add(dev, mac_addr, 0, 0);
151 }