#include <unistd.h>
#include <rte_errno.h>
-#include <rte_atomic.h>
#include "mlx5_nl.h"
-#include "mlx5_common_utils.h"
+#include "../mlx5_common_log.h"
+#include "mlx5_malloc.h"
#ifdef HAVE_DEVLINK
#include <linux/devlink.h>
#endif
#define MLX5_SEND_BUF_SIZE 32768
/* Receive buffer size for the Netlink socket */
#define MLX5_RECV_BUF_SIZE 32768
+/* Maximal physical port name length. */
+#define MLX5_PHYS_PORT_NAME_MAX 128
/** Parameters of VLAN devices created by driver. */
#define MLX5_VMWA_VLAN_DEVICE_PFX "evmlx"
uint32_t portnum; /**< IB device max port number (out). */
};
-rte_atomic32_t atomic_sn = RTE_ATOMIC32_INIT(0);
+uint32_t atomic_sn;
/* Generate Netlink sequence number. */
-#define MLX5_NL_SN_GENERATE ((uint32_t)rte_atomic32_add_return(&atomic_sn, 1))
+#define MLX5_NL_SN_GENERATE __atomic_add_fetch(&atomic_sn, 1, __ATOMIC_RELAXED)
/**
* Opens a Netlink socket.
mlx5_nl_init(int protocol)
{
int fd;
- int sndbuf_size = MLX5_SEND_BUF_SIZE;
- int rcvbuf_size = MLX5_RECV_BUF_SIZE;
+ int buf_size;
+ socklen_t opt_size;
struct sockaddr_nl local = {
.nl_family = AF_NETLINK,
};
rte_errno = errno;
return -rte_errno;
}
- ret = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sndbuf_size, sizeof(int));
+ opt_size = sizeof(buf_size);
+ ret = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buf_size, &opt_size);
if (ret == -1) {
rte_errno = errno;
goto error;
}
- ret = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf_size, sizeof(int));
+ DRV_LOG(DEBUG, "Netlink socket send buffer: %d", buf_size);
+ if (buf_size < MLX5_SEND_BUF_SIZE) {
+ ret = setsockopt(fd, SOL_SOCKET, SO_SNDBUF,
+ &buf_size, sizeof(buf_size));
+ if (ret == -1) {
+ rte_errno = errno;
+ goto error;
+ }
+ }
+ opt_size = sizeof(buf_size);
+ ret = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &buf_size, &opt_size);
if (ret == -1) {
rte_errno = errno;
goto error;
}
+ DRV_LOG(DEBUG, "Netlink socket recv buffer: %d", buf_size);
+ if (buf_size < MLX5_RECV_BUF_SIZE) {
+ ret = setsockopt(fd, SOL_SOCKET, SO_RCVBUF,
+ &buf_size, sizeof(buf_size));
+ if (ret == -1) {
+ rte_errno = errno;
+ goto error;
+ }
+ }
ret = bind(fd, (struct sockaddr *)&local, sizeof(local));
if (ret == -1) {
rte_errno = errno;
void *arg)
{
struct sockaddr_nl sa;
- void *buf = malloc(MLX5_RECV_BUF_SIZE);
- struct iovec iov = {
- .iov_base = buf,
- .iov_len = MLX5_RECV_BUF_SIZE,
- };
+ struct iovec iov;
struct msghdr msg = {
.msg_name = &sa,
.msg_namelen = sizeof(sa),
/* One message at a time */
.msg_iovlen = 1,
};
+ void *buf = NULL;
int multipart = 0;
int ret = 0;
- if (!buf) {
- rte_errno = ENOMEM;
- return -rte_errno;
- }
do {
struct nlmsghdr *nh;
- int recv_bytes = 0;
+ int recv_bytes;
do {
+ /* Query length of incoming message. */
+ iov.iov_base = NULL;
+ iov.iov_len = 0;
+ recv_bytes = recvmsg(nlsk_fd, &msg,
+ MSG_PEEK | MSG_TRUNC);
+ if (recv_bytes < 0) {
+ rte_errno = errno;
+ ret = -rte_errno;
+ goto exit;
+ }
+ if (recv_bytes == 0) {
+ rte_errno = ENODATA;
+ ret = -rte_errno;
+ goto exit;
+ }
+ /* Allocate buffer to fetch the message. */
+ if (recv_bytes < MLX5_RECV_BUF_SIZE)
+ recv_bytes = MLX5_RECV_BUF_SIZE;
+ mlx5_free(buf);
+ buf = mlx5_malloc(0, recv_bytes, 0, SOCKET_ID_ANY);
+ if (!buf) {
+ rte_errno = ENOMEM;
+ ret = -rte_errno;
+ goto exit;
+ }
+ /* Fetch the message. */
+ iov.iov_base = buf;
+ iov.iov_len = recv_bytes;
recv_bytes = recvmsg(nlsk_fd, &msg, 0);
if (recv_bytes == -1) {
rte_errno = errno;
}
} while (multipart);
exit:
- free(buf);
+ mlx5_free(buf);
return ret;
}
error:
DRV_LOG(ERR,
"representor %u cannot set VF MAC address "
- "%02X:%02X:%02X:%02X:%02X:%02X : %s",
+ RTE_ETHER_ADDR_PRT_FMT " : %s",
vf_index,
mac->addr_bytes[0], mac->addr_bytes[1],
mac->addr_bytes[2], mac->addr_bytes[3],
int i;
int ret;
+ memset(macs, 0, n * sizeof(macs[0]));
ret = mlx5_nl_mac_addr_list(nlsk_fd, iface_idx, &macs, &macs_n);
if (ret)
return;
break;
if (j != n)
continue;
- /* Find the first entry available. */
- for (j = 0; j != n; ++j) {
- if (rte_is_zero_ether_addr(&mac_addrs[j])) {
- mac_addrs[j] = macs[i];
- break;
+ if (rte_is_multicast_ether_addr(&macs[i])) {
+ /* Find the first entry available. */
+ for (j = MLX5_MAX_UC_MAC_ADDRESSES; j != n; ++j) {
+ if (rte_is_zero_ether_addr(&mac_addrs[j])) {
+ mac_addrs[j] = macs[i];
+ break;
+ }
+ }
+ } else {
+ /* Find the first entry available. */
+ for (j = 0; j != MLX5_MAX_UC_MAC_ADDRESSES; ++j) {
+ if (rte_is_zero_ether_addr(&mac_addrs[j])) {
+ mac_addrs[j] = macs[i];
+ break;
+ }
}
}
}
{
int i;
- if (n <= 0 || n >= MLX5_MAX_MAC_ADDRESSES)
+ if (n <= 0 || n > MLX5_MAX_MAC_ADDRESSES)
return;
for (i = n - 1; i >= 0; --i) {
case MLX5_PHYS_PORT_NAME_TYPE_PFHPF:
/* Fallthrough */
case MLX5_PHYS_PORT_NAME_TYPE_PFVF:
+ /* Fallthrough */
+ case MLX5_PHYS_PORT_NAME_TYPE_PFSF:
/* New representors naming schema. */
switch_info->representor = 1;
break;
size_t off = NLMSG_LENGTH(sizeof(struct ifinfomsg));
bool switch_id_set = false;
bool num_vf_set = false;
+ int len;
if (nh->nlmsg_type != RTM_NEWLINK)
goto error;
num_vf_set = true;
break;
case IFLA_PHYS_PORT_NAME:
- mlx5_translate_port_name((char *)payload, &info);
+ len = RTA_PAYLOAD(ra);
+ /* Some kernels do not pad attributes with zero. */
+ if (len > 0 && len < MLX5_PHYS_PORT_NAME_MAX) {
+ char name[MLX5_PHYS_PORT_NAME_MAX];
+
+ /*
+ * We can't just patch the message with padding
+ * zero - it might corrupt the following items
+ * in the message, we have to copy the string
+ * by attribute length and pad the copied one.
+ */
+ memcpy(name, payload, len);
+ name[len] = 0;
+ mlx5_translate_port_name(name, &info);
+ } else {
+ info.name_type =
+ MLX5_PHYS_PORT_NAME_TYPE_UNKNOWN;
+ }
break;
case IFLA_PHYS_SWITCH_ID:
info.switch_id = 0;