net: add macro for MAC address print
[dpdk.git] / drivers / common / mlx5 / linux / mlx5_nl.c
index dc504d8..efd9297 100644 (file)
 #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
@@ -33,6 +33,8 @@
 #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"
@@ -168,10 +170,10 @@ struct mlx5_nl_ifindex_data {
        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.
@@ -187,8 +189,8 @@ int
 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,
        };
@@ -199,16 +201,36 @@ mlx5_nl_init(int protocol)
                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;
@@ -330,11 +352,7 @@ mlx5_nl_recv(int nlsk_fd, uint32_t sn, int (*cb)(struct nlmsghdr *, void *arg),
             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),
@@ -342,18 +360,43 @@ mlx5_nl_recv(int nlsk_fd, uint32_t sn, int (*cb)(struct nlmsghdr *, void *arg),
                /* 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;
@@ -393,7 +436,7 @@ mlx5_nl_recv(int nlsk_fd, uint32_t sn, int (*cb)(struct nlmsghdr *, void *arg),
                }
        } while (multipart);
 exit:
-       free(buf);
+       mlx5_free(buf);
        return ret;
 }
 
@@ -650,7 +693,7 @@ mlx5_nl_vf_mac_addr_modify(int nlsk_fd, unsigned int iface_idx,
 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],
@@ -746,6 +789,7 @@ mlx5_nl_mac_addr_sync(int nlsk_fd, unsigned int iface_idx,
        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;
@@ -758,11 +802,21 @@ mlx5_nl_mac_addr_sync(int nlsk_fd, unsigned int iface_idx,
                                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;
+                               }
                        }
                }
        }
@@ -789,7 +843,7 @@ mlx5_nl_mac_addr_flush(int nlsk_fd, unsigned int iface_idx,
 {
        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) {
@@ -1148,6 +1202,8 @@ mlx5_nl_check_switch_info(bool num_vf_set,
        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;
@@ -1178,6 +1234,7 @@ mlx5_nl_switch_info_cb(struct nlmsghdr *nh, void *arg)
        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;
@@ -1193,7 +1250,24 @@ mlx5_nl_switch_info_cb(struct nlmsghdr *nh, void *arg)
                        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;