1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright 2018 6WIND S.A.
3 * Copyright 2018 Mellanox Technologies, Ltd
7 #include <linux/if_link.h>
8 #include <linux/rtnetlink.h>
9 #include <linux/genetlink.h>
11 #include <rdma/rdma_netlink.h>
17 #include <sys/socket.h>
20 #include <rte_errno.h>
23 #include "../mlx5_common_log.h"
24 #include "mlx5_malloc.h"
26 #include <linux/devlink.h>
30 /* Size of the buffer to receive kernel messages */
31 #define MLX5_NL_BUF_SIZE (32 * 1024)
32 /* Send buffer size for the Netlink socket */
33 #define MLX5_SEND_BUF_SIZE 32768
34 /* Receive buffer size for the Netlink socket */
35 #define MLX5_RECV_BUF_SIZE 32768
36 /* Maximal physical port name length. */
37 #define MLX5_PHYS_PORT_NAME_MAX 128
39 /** Parameters of VLAN devices created by driver. */
40 #define MLX5_VMWA_VLAN_DEVICE_PFX "evmlx"
42 * Define NDA_RTA as defined in iproute2 sources.
44 * see in iproute2 sources file include/libnetlink.h
47 #define MLX5_NDA_RTA(r) \
48 ((struct rtattr *)(((char *)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg))))
51 * Define NLMSG_TAIL as defined in iproute2 sources.
53 * see in iproute2 sources file include/libnetlink.h
56 #define NLMSG_TAIL(nmsg) \
57 ((struct rtattr *)(((char *)(nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
60 * The following definitions are normally found in rdma/rdma_netlink.h,
61 * however they are so recent that most systems do not expose them yet.
63 #ifndef HAVE_RDMA_NL_NLDEV
64 #define RDMA_NL_NLDEV 5
66 #ifndef HAVE_RDMA_NLDEV_CMD_GET
67 #define RDMA_NLDEV_CMD_GET 1
69 #ifndef HAVE_RDMA_NLDEV_CMD_PORT_GET
70 #define RDMA_NLDEV_CMD_PORT_GET 5
72 #ifndef HAVE_RDMA_NLDEV_ATTR_DEV_INDEX
73 #define RDMA_NLDEV_ATTR_DEV_INDEX 1
75 #ifndef HAVE_RDMA_NLDEV_ATTR_DEV_NAME
76 #define RDMA_NLDEV_ATTR_DEV_NAME 2
78 #ifndef HAVE_RDMA_NLDEV_ATTR_PORT_INDEX
79 #define RDMA_NLDEV_ATTR_PORT_INDEX 3
81 #ifndef HAVE_RDMA_NLDEV_ATTR_PORT_STATE
82 #define RDMA_NLDEV_ATTR_PORT_STATE 12
84 #ifndef HAVE_RDMA_NLDEV_ATTR_NDEV_INDEX
85 #define RDMA_NLDEV_ATTR_NDEV_INDEX 50
88 /* These are normally found in linux/if_link.h. */
89 #ifndef HAVE_IFLA_NUM_VF
90 #define IFLA_NUM_VF 21
92 #ifndef HAVE_IFLA_EXT_MASK
93 #define IFLA_EXT_MASK 29
95 #ifndef HAVE_IFLA_PHYS_SWITCH_ID
96 #define IFLA_PHYS_SWITCH_ID 36
98 #ifndef HAVE_IFLA_PHYS_PORT_NAME
99 #define IFLA_PHYS_PORT_NAME 38
103 * Some Devlink defines may be missed in old kernel versions,
104 * adjust used defines.
106 #ifndef DEVLINK_GENL_NAME
107 #define DEVLINK_GENL_NAME "devlink"
109 #ifndef DEVLINK_GENL_VERSION
110 #define DEVLINK_GENL_VERSION 1
112 #ifndef DEVLINK_ATTR_BUS_NAME
113 #define DEVLINK_ATTR_BUS_NAME 1
115 #ifndef DEVLINK_ATTR_DEV_NAME
116 #define DEVLINK_ATTR_DEV_NAME 2
118 #ifndef DEVLINK_ATTR_PARAM
119 #define DEVLINK_ATTR_PARAM 80
121 #ifndef DEVLINK_ATTR_PARAM_NAME
122 #define DEVLINK_ATTR_PARAM_NAME 81
124 #ifndef DEVLINK_ATTR_PARAM_TYPE
125 #define DEVLINK_ATTR_PARAM_TYPE 83
127 #ifndef DEVLINK_ATTR_PARAM_VALUES_LIST
128 #define DEVLINK_ATTR_PARAM_VALUES_LIST 84
130 #ifndef DEVLINK_ATTR_PARAM_VALUE
131 #define DEVLINK_ATTR_PARAM_VALUE 85
133 #ifndef DEVLINK_ATTR_PARAM_VALUE_DATA
134 #define DEVLINK_ATTR_PARAM_VALUE_DATA 86
136 #ifndef DEVLINK_ATTR_PARAM_VALUE_CMODE
137 #define DEVLINK_ATTR_PARAM_VALUE_CMODE 87
139 #ifndef DEVLINK_PARAM_CMODE_DRIVERINIT
140 #define DEVLINK_PARAM_CMODE_DRIVERINIT 1
142 #ifndef DEVLINK_CMD_RELOAD
143 #define DEVLINK_CMD_RELOAD 37
145 #ifndef DEVLINK_CMD_PARAM_GET
146 #define DEVLINK_CMD_PARAM_GET 38
148 #ifndef DEVLINK_CMD_PARAM_SET
149 #define DEVLINK_CMD_PARAM_SET 39
155 /* Add/remove MAC address through Netlink */
156 struct mlx5_nl_mac_addr {
157 struct rte_ether_addr (*mac)[];
158 /**< MAC address handled by the device. */
159 int mac_n; /**< Number of addresses in the array. */
162 #define MLX5_NL_CMD_GET_IB_NAME (1 << 0)
163 #define MLX5_NL_CMD_GET_IB_INDEX (1 << 1)
164 #define MLX5_NL_CMD_GET_NET_INDEX (1 << 2)
165 #define MLX5_NL_CMD_GET_PORT_INDEX (1 << 3)
166 #define MLX5_NL_CMD_GET_PORT_STATE (1 << 4)
168 /** Data structure used by mlx5_nl_cmdget_cb(). */
169 struct mlx5_nl_port_info {
170 const char *name; /**< IB device name (in). */
171 uint32_t flags; /**< found attribute flags (out). */
172 uint32_t ibindex; /**< IB device index (out). */
173 uint32_t ifindex; /**< Network interface index (out). */
174 uint32_t portnum; /**< IB device max port number (out). */
175 uint16_t state; /**< IB device port state (out). */
180 /* Generate Netlink sequence number. */
181 #define MLX5_NL_SN_GENERATE __atomic_add_fetch(&atomic_sn, 1, __ATOMIC_RELAXED)
184 * Opens a Netlink socket.
187 * Netlink protocol (e.g. NETLINK_ROUTE, NETLINK_RDMA).
189 * Groups to listen (e.g. RTMGRP_LINK), can be 0.
192 * A file descriptor on success, a negative errno value otherwise and
196 mlx5_nl_init(int protocol, int groups)
201 struct sockaddr_nl local = {
202 .nl_family = AF_NETLINK,
207 fd = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, protocol);
212 opt_size = sizeof(buf_size);
213 ret = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buf_size, &opt_size);
218 DRV_LOG(DEBUG, "Netlink socket send buffer: %d", buf_size);
219 if (buf_size < MLX5_SEND_BUF_SIZE) {
220 ret = setsockopt(fd, SOL_SOCKET, SO_SNDBUF,
221 &buf_size, sizeof(buf_size));
227 opt_size = sizeof(buf_size);
228 ret = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &buf_size, &opt_size);
233 DRV_LOG(DEBUG, "Netlink socket recv buffer: %d", buf_size);
234 if (buf_size < MLX5_RECV_BUF_SIZE) {
235 ret = setsockopt(fd, SOL_SOCKET, SO_RCVBUF,
236 &buf_size, sizeof(buf_size));
242 ret = bind(fd, (struct sockaddr *)&local, sizeof(local));
254 * Send a request message to the kernel on the Netlink socket.
257 * Netlink socket file descriptor.
259 * The Netlink message send to the kernel.
263 * Pointer to the request structure.
265 * Length of the request in bytes.
268 * The number of sent bytes on success, a negative errno value otherwise and
272 mlx5_nl_request(int nlsk_fd, struct nlmsghdr *nh, uint32_t sn, void *req,
275 struct sockaddr_nl sa = {
276 .nl_family = AF_NETLINK,
278 struct iovec iov[2] = {
279 { .iov_base = nh, .iov_len = sizeof(*nh), },
280 { .iov_base = req, .iov_len = len, },
282 struct msghdr msg = {
284 .msg_namelen = sizeof(sa),
290 nh->nlmsg_pid = 0; /* communication with the kernel uses pid 0 */
292 send_bytes = sendmsg(nlsk_fd, &msg, 0);
293 if (send_bytes < 0) {
301 * Send a message to the kernel on the Netlink socket.
304 * The Netlink socket file descriptor used for communication.
306 * The Netlink message send to the kernel.
311 * The number of sent bytes on success, a negative errno value otherwise and
315 mlx5_nl_send(int nlsk_fd, struct nlmsghdr *nh, uint32_t sn)
317 struct sockaddr_nl sa = {
318 .nl_family = AF_NETLINK,
322 .iov_len = nh->nlmsg_len,
324 struct msghdr msg = {
326 .msg_namelen = sizeof(sa),
332 nh->nlmsg_pid = 0; /* communication with the kernel uses pid 0 */
334 send_bytes = sendmsg(nlsk_fd, &msg, 0);
335 if (send_bytes < 0) {
343 * Receive a message from the kernel on the Netlink socket, following
347 * The Netlink socket file descriptor used for communication.
351 * The callback function to call for each Netlink message received.
352 * @param[in, out] arg
353 * Custom arguments for the callback.
356 * 0 on success, a negative errno value otherwise and rte_errno is set.
359 mlx5_nl_recv(int nlsk_fd, uint32_t sn, int (*cb)(struct nlmsghdr *, void *arg),
362 struct sockaddr_nl sa;
364 struct msghdr msg = {
366 .msg_namelen = sizeof(sa),
368 /* One message at a time */
380 /* Query length of incoming message. */
383 recv_bytes = recvmsg(nlsk_fd, &msg,
384 MSG_PEEK | MSG_TRUNC);
385 if (recv_bytes < 0) {
390 if (recv_bytes == 0) {
395 /* Allocate buffer to fetch the message. */
396 if (recv_bytes < MLX5_RECV_BUF_SIZE)
397 recv_bytes = MLX5_RECV_BUF_SIZE;
399 buf = mlx5_malloc(0, recv_bytes, 0, SOCKET_ID_ANY);
405 /* Fetch the message. */
407 iov.iov_len = recv_bytes;
408 recv_bytes = recvmsg(nlsk_fd, &msg, 0);
409 if (recv_bytes == -1) {
414 nh = (struct nlmsghdr *)buf;
415 } while (nh->nlmsg_seq != sn);
417 NLMSG_OK(nh, (unsigned int)recv_bytes);
418 nh = NLMSG_NEXT(nh, recv_bytes)) {
419 if (nh->nlmsg_type == NLMSG_ERROR) {
420 struct nlmsgerr *err_data = NLMSG_DATA(nh);
422 if (err_data->error < 0) {
423 rte_errno = -err_data->error;
431 /* Multi-part msgs and their trailing DONE message. */
432 if (nh->nlmsg_flags & NLM_F_MULTI) {
433 if (nh->nlmsg_type == NLMSG_DONE) {
452 * Parse Netlink message to retrieve the bridge MAC address.
455 * Pointer to Netlink Message Header.
457 * PMD data register with this callback.
460 * 0 on success, a negative errno value otherwise and rte_errno is set.
463 mlx5_nl_mac_addr_cb(struct nlmsghdr *nh, void *arg)
465 struct mlx5_nl_mac_addr *data = arg;
466 struct ndmsg *r = NLMSG_DATA(nh);
467 struct rtattr *attribute;
470 len = nh->nlmsg_len - NLMSG_LENGTH(sizeof(*r));
471 for (attribute = MLX5_NDA_RTA(r);
472 RTA_OK(attribute, len);
473 attribute = RTA_NEXT(attribute, len)) {
474 if (attribute->rta_type == NDA_LLADDR) {
475 if (data->mac_n == MLX5_MAX_MAC_ADDRESSES) {
477 "not enough room to finalize the"
482 #ifdef RTE_LIBRTE_MLX5_DEBUG
483 char m[RTE_ETHER_ADDR_FMT_SIZE];
485 rte_ether_format_addr(m, RTE_ETHER_ADDR_FMT_SIZE,
486 RTA_DATA(attribute));
487 DRV_LOG(DEBUG, "bridge MAC address %s", m);
489 memcpy(&(*data->mac)[data->mac_n++],
490 RTA_DATA(attribute), RTE_ETHER_ADDR_LEN);
497 * Get bridge MAC addresses.
500 * Netlink socket file descriptor.
501 * @param[in] iface_idx
502 * Net device interface index.
504 * Pointer to the array table of MAC addresses to fill.
505 * Its size should be of MLX5_MAX_MAC_ADDRESSES.
507 * Number of entries filled in MAC array.
510 * 0 on success, a negative errno value otherwise and rte_errno is set.
513 mlx5_nl_mac_addr_list(int nlsk_fd, unsigned int iface_idx,
514 struct rte_ether_addr (*mac)[], int *mac_n)
518 struct ifinfomsg ifm;
521 .nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
522 .nlmsg_type = RTM_GETNEIGH,
523 .nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
526 .ifi_family = PF_BRIDGE,
527 .ifi_index = iface_idx,
530 struct mlx5_nl_mac_addr data = {
534 uint32_t sn = MLX5_NL_SN_GENERATE;
539 ret = mlx5_nl_request(nlsk_fd, &req.hdr, sn, &req.ifm,
540 sizeof(struct ifinfomsg));
543 ret = mlx5_nl_recv(nlsk_fd, sn, mlx5_nl_mac_addr_cb, &data);
549 DRV_LOG(DEBUG, "Interface %u cannot retrieve MAC address list %s",
550 iface_idx, strerror(rte_errno));
555 * Modify the MAC address neighbour table with Netlink.
558 * Netlink socket file descriptor.
559 * @param[in] iface_idx
560 * Net device interface index.
562 * MAC address to consider.
564 * 1 to add the MAC address, 0 to remove the MAC address.
567 * 0 on success, a negative errno value otherwise and rte_errno is set.
570 mlx5_nl_mac_addr_modify(int nlsk_fd, unsigned int iface_idx,
571 struct rte_ether_addr *mac, int add)
577 uint8_t buffer[RTE_ETHER_ADDR_LEN];
580 .nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)),
581 .nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE |
582 NLM_F_EXCL | NLM_F_ACK,
583 .nlmsg_type = add ? RTM_NEWNEIGH : RTM_DELNEIGH,
586 .ndm_family = PF_BRIDGE,
587 .ndm_state = NUD_NOARP | NUD_PERMANENT,
588 .ndm_ifindex = iface_idx,
589 .ndm_flags = NTF_SELF,
592 .rta_type = NDA_LLADDR,
593 .rta_len = RTA_LENGTH(RTE_ETHER_ADDR_LEN),
596 uint32_t sn = MLX5_NL_SN_GENERATE;
601 memcpy(RTA_DATA(&req.rta), mac, RTE_ETHER_ADDR_LEN);
602 req.hdr.nlmsg_len = NLMSG_ALIGN(req.hdr.nlmsg_len) +
603 RTA_ALIGN(req.rta.rta_len);
604 ret = mlx5_nl_send(nlsk_fd, &req.hdr, sn);
607 ret = mlx5_nl_recv(nlsk_fd, sn, NULL, NULL);
612 #ifdef RTE_LIBRTE_MLX5_DEBUG
614 char m[RTE_ETHER_ADDR_FMT_SIZE];
616 rte_ether_format_addr(m, RTE_ETHER_ADDR_FMT_SIZE, mac);
618 "Interface %u cannot %s MAC address %s %s",
620 add ? "add" : "remove", m, strerror(rte_errno));
627 * Modify the VF MAC address neighbour table with Netlink.
630 * Netlink socket file descriptor.
631 * @param[in] iface_idx
632 * Net device interface index.
634 * MAC address to consider.
639 * 0 on success, a negative errno value otherwise and rte_errno is set.
642 mlx5_nl_vf_mac_addr_modify(int nlsk_fd, unsigned int iface_idx,
643 struct rte_ether_addr *mac, int vf_index)
648 struct ifinfomsg ifm;
649 struct rtattr vf_list_rta;
650 struct rtattr vf_info_rta;
651 struct rtattr vf_mac_rta;
652 struct ifla_vf_mac ivm;
655 .nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
656 .nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
657 .nlmsg_type = RTM_BASE,
660 .ifi_index = iface_idx,
663 .rta_type = IFLA_VFINFO_LIST,
664 .rta_len = RTA_ALIGN(RTA_LENGTH(0)),
667 .rta_type = IFLA_VF_INFO,
668 .rta_len = RTA_ALIGN(RTA_LENGTH(0)),
671 .rta_type = IFLA_VF_MAC,
674 struct ifla_vf_mac ivm = {
677 uint32_t sn = MLX5_NL_SN_GENERATE;
679 memcpy(&ivm.mac, mac, RTE_ETHER_ADDR_LEN);
680 memcpy(RTA_DATA(&req.vf_mac_rta), &ivm, sizeof(ivm));
682 req.vf_mac_rta.rta_len = RTA_LENGTH(sizeof(ivm));
683 req.hdr.nlmsg_len = NLMSG_ALIGN(req.hdr.nlmsg_len) +
684 RTA_ALIGN(req.vf_list_rta.rta_len) +
685 RTA_ALIGN(req.vf_info_rta.rta_len) +
686 RTA_ALIGN(req.vf_mac_rta.rta_len);
687 req.vf_list_rta.rta_len = RTE_PTR_DIFF(NLMSG_TAIL(&req.hdr),
689 req.vf_info_rta.rta_len = RTE_PTR_DIFF(NLMSG_TAIL(&req.hdr),
694 ret = mlx5_nl_send(nlsk_fd, &req.hdr, sn);
697 ret = mlx5_nl_recv(nlsk_fd, sn, NULL, NULL);
703 "representor %u cannot set VF MAC address "
704 RTE_ETHER_ADDR_PRT_FMT " : %s",
706 RTE_ETHER_ADDR_BYTES(mac),
707 strerror(rte_errno));
715 * Netlink socket file descriptor.
716 * @param[in] iface_idx
717 * Net device interface index.
719 * BITFIELD_DECLARE array to store the mac.
721 * MAC address to register.
726 * 0 on success, a negative errno value otherwise and rte_errno is set.
729 mlx5_nl_mac_addr_add(int nlsk_fd, unsigned int iface_idx,
730 uint64_t *mac_own, struct rte_ether_addr *mac,
735 ret = mlx5_nl_mac_addr_modify(nlsk_fd, iface_idx, mac, 1);
737 MLX5_ASSERT(index < MLX5_MAX_MAC_ADDRESSES);
738 if (index >= MLX5_MAX_MAC_ADDRESSES)
741 BITFIELD_SET(mac_own, index);
749 * Remove a MAC address.
752 * Netlink socket file descriptor.
753 * @param[in] iface_idx
754 * Net device interface index.
756 * BITFIELD_DECLARE array to store the mac.
758 * MAC address to remove.
763 * 0 on success, a negative errno value otherwise and rte_errno is set.
766 mlx5_nl_mac_addr_remove(int nlsk_fd, unsigned int iface_idx, uint64_t *mac_own,
767 struct rte_ether_addr *mac, uint32_t index)
769 MLX5_ASSERT(index < MLX5_MAX_MAC_ADDRESSES);
770 if (index >= MLX5_MAX_MAC_ADDRESSES)
773 BITFIELD_RESET(mac_own, index);
774 return mlx5_nl_mac_addr_modify(nlsk_fd, iface_idx, mac, 0);
778 * Synchronize Netlink bridge table to the internal table.
781 * Netlink socket file descriptor.
782 * @param[in] iface_idx
783 * Net device interface index.
785 * Mac addresses array to sync.
787 * @p mac_addrs array size.
790 mlx5_nl_mac_addr_sync(int nlsk_fd, unsigned int iface_idx,
791 struct rte_ether_addr *mac_addrs, int n)
793 struct rte_ether_addr macs[n];
798 memset(macs, 0, n * sizeof(macs[0]));
799 ret = mlx5_nl_mac_addr_list(nlsk_fd, iface_idx, &macs, &macs_n);
802 for (i = 0; i != macs_n; ++i) {
805 /* Verify the address is not in the array yet. */
806 for (j = 0; j != n; ++j)
807 if (rte_is_same_ether_addr(&macs[i], &mac_addrs[j]))
811 if (rte_is_multicast_ether_addr(&macs[i])) {
812 /* Find the first entry available. */
813 for (j = MLX5_MAX_UC_MAC_ADDRESSES; j != n; ++j) {
814 if (rte_is_zero_ether_addr(&mac_addrs[j])) {
815 mac_addrs[j] = macs[i];
820 /* Find the first entry available. */
821 for (j = 0; j != MLX5_MAX_UC_MAC_ADDRESSES; ++j) {
822 if (rte_is_zero_ether_addr(&mac_addrs[j])) {
823 mac_addrs[j] = macs[i];
832 * Flush all added MAC addresses.
835 * Netlink socket file descriptor.
836 * @param[in] iface_idx
837 * Net device interface index.
838 * @param[in] mac_addrs
839 * Mac addresses array to flush.
841 * @p mac_addrs array size.
843 * BITFIELD_DECLARE array to store the mac.
846 mlx5_nl_mac_addr_flush(int nlsk_fd, unsigned int iface_idx,
847 struct rte_ether_addr *mac_addrs, int n,
852 if (n <= 0 || n > MLX5_MAX_MAC_ADDRESSES)
855 for (i = n - 1; i >= 0; --i) {
856 struct rte_ether_addr *m = &mac_addrs[i];
858 if (BITFIELD_ISSET(mac_own, i))
859 mlx5_nl_mac_addr_remove(nlsk_fd, iface_idx, mac_own, m,
865 * Enable promiscuous / all multicast mode through Netlink.
868 * Netlink socket file descriptor.
869 * @param[in] iface_idx
870 * Net device interface index.
872 * IFF_PROMISC for promiscuous, IFF_ALLMULTI for allmulti.
874 * Nonzero to enable, disable otherwise.
877 * 0 on success, a negative errno value otherwise and rte_errno is set.
880 mlx5_nl_device_flags(int nlsk_fd, unsigned int iface_idx, uint32_t flags,
885 struct ifinfomsg ifi;
888 .nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
889 .nlmsg_type = RTM_NEWLINK,
890 .nlmsg_flags = NLM_F_REQUEST,
893 .ifi_flags = enable ? flags : 0,
895 .ifi_index = iface_idx,
898 uint32_t sn = MLX5_NL_SN_GENERATE;
901 MLX5_ASSERT(!(flags & ~(IFF_PROMISC | IFF_ALLMULTI)));
904 ret = mlx5_nl_send(nlsk_fd, &req.hdr, sn);
911 * Enable promiscuous mode through Netlink.
914 * Netlink socket file descriptor.
915 * @param[in] iface_idx
916 * Net device interface index.
918 * Nonzero to enable, disable otherwise.
921 * 0 on success, a negative errno value otherwise and rte_errno is set.
924 mlx5_nl_promisc(int nlsk_fd, unsigned int iface_idx, int enable)
926 int ret = mlx5_nl_device_flags(nlsk_fd, iface_idx, IFF_PROMISC, enable);
930 "Interface %u cannot %s promisc mode: Netlink error %s",
931 iface_idx, enable ? "enable" : "disable",
932 strerror(rte_errno));
937 * Enable all multicast mode through Netlink.
940 * Netlink socket file descriptor.
941 * @param[in] iface_idx
942 * Net device interface index.
944 * Nonzero to enable, disable otherwise.
947 * 0 on success, a negative errno value otherwise and rte_errno is set.
950 mlx5_nl_allmulti(int nlsk_fd, unsigned int iface_idx, int enable)
952 int ret = mlx5_nl_device_flags(nlsk_fd, iface_idx, IFF_ALLMULTI,
957 "Interface %u cannot %s allmulti : Netlink error %s",
958 iface_idx, enable ? "enable" : "disable",
959 strerror(rte_errno));
964 * Process network interface information from Netlink message.
967 * Pointer to Netlink message header.
969 * Opaque data pointer for this callback.
972 * 0 on success, a negative errno value otherwise and rte_errno is set.
975 mlx5_nl_cmdget_cb(struct nlmsghdr *nh, void *arg)
977 struct mlx5_nl_port_info *data = arg;
978 struct mlx5_nl_port_info local = {
981 size_t off = NLMSG_HDRLEN;
983 if (nh->nlmsg_type !=
984 RDMA_NL_GET_TYPE(RDMA_NL_NLDEV, RDMA_NLDEV_CMD_GET) &&
986 RDMA_NL_GET_TYPE(RDMA_NL_NLDEV, RDMA_NLDEV_CMD_PORT_GET))
988 while (off < nh->nlmsg_len) {
989 struct nlattr *na = (void *)((uintptr_t)nh + off);
990 void *payload = (void *)((uintptr_t)na + NLA_HDRLEN);
992 if (na->nla_len > nh->nlmsg_len - off)
994 switch (na->nla_type) {
995 case RDMA_NLDEV_ATTR_DEV_INDEX:
996 local.ibindex = *(uint32_t *)payload;
997 local.flags |= MLX5_NL_CMD_GET_IB_INDEX;
999 case RDMA_NLDEV_ATTR_DEV_NAME:
1000 if (!strcmp(payload, data->name))
1001 local.flags |= MLX5_NL_CMD_GET_IB_NAME;
1003 case RDMA_NLDEV_ATTR_NDEV_INDEX:
1004 local.ifindex = *(uint32_t *)payload;
1005 local.flags |= MLX5_NL_CMD_GET_NET_INDEX;
1007 case RDMA_NLDEV_ATTR_PORT_INDEX:
1008 local.portnum = *(uint32_t *)payload;
1009 local.flags |= MLX5_NL_CMD_GET_PORT_INDEX;
1011 case RDMA_NLDEV_ATTR_PORT_STATE:
1012 local.state = *(uint8_t *)payload;
1013 local.flags |= MLX5_NL_CMD_GET_PORT_STATE;
1018 off += NLA_ALIGN(na->nla_len);
1021 * It is possible to have multiple messages for all
1022 * Infiniband devices in the system with appropriate name.
1023 * So we should gather parameters locally and copy to
1024 * query context only in case of coinciding device name.
1026 if (local.flags & MLX5_NL_CMD_GET_IB_NAME) {
1027 data->flags = local.flags;
1028 data->ibindex = local.ibindex;
1029 data->ifindex = local.ifindex;
1030 data->portnum = local.portnum;
1031 data->state = local.state;
1040 * Get port info of network interface associated with some IB device.
1042 * This is the only somewhat safe method to avoid resorting to heuristics
1043 * when faced with port representors. Unfortunately it requires at least
1047 * Netlink socket of the RDMA kind (NETLINK_RDMA).
1049 * IB device port index, starting from 1
1051 * Pointer to port info.
1053 * 0 on success, negative on error and rte_errno is set.
1056 mlx5_nl_port_info(int nl, uint32_t pindex, struct mlx5_nl_port_info *data)
1060 uint8_t buf[NLMSG_HDRLEN +
1061 NLA_HDRLEN + NLA_ALIGN(sizeof(data->ibindex)) +
1062 NLA_HDRLEN + NLA_ALIGN(sizeof(pindex))];
1065 .nlmsg_len = NLMSG_LENGTH(0),
1066 .nlmsg_type = RDMA_NL_GET_TYPE(RDMA_NL_NLDEV,
1067 RDMA_NLDEV_CMD_GET),
1068 .nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP,
1072 uint32_t sn = MLX5_NL_SN_GENERATE;
1075 ret = mlx5_nl_send(nl, &req.nh, sn);
1078 ret = mlx5_nl_recv(nl, sn, mlx5_nl_cmdget_cb, data);
1081 if (!(data->flags & MLX5_NL_CMD_GET_IB_NAME) ||
1082 !(data->flags & MLX5_NL_CMD_GET_IB_INDEX))
1085 sn = MLX5_NL_SN_GENERATE;
1086 req.nh.nlmsg_type = RDMA_NL_GET_TYPE(RDMA_NL_NLDEV,
1087 RDMA_NLDEV_CMD_PORT_GET);
1088 req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
1089 req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.buf) - NLMSG_HDRLEN);
1090 na = (void *)((uintptr_t)req.buf + NLMSG_HDRLEN);
1091 na->nla_len = NLA_HDRLEN + sizeof(data->ibindex);
1092 na->nla_type = RDMA_NLDEV_ATTR_DEV_INDEX;
1093 memcpy((void *)((uintptr_t)na + NLA_HDRLEN),
1094 &data->ibindex, sizeof(data->ibindex));
1095 na = (void *)((uintptr_t)na + NLA_ALIGN(na->nla_len));
1096 na->nla_len = NLA_HDRLEN + sizeof(pindex);
1097 na->nla_type = RDMA_NLDEV_ATTR_PORT_INDEX;
1098 memcpy((void *)((uintptr_t)na + NLA_HDRLEN),
1099 &pindex, sizeof(pindex));
1100 ret = mlx5_nl_send(nl, &req.nh, sn);
1103 ret = mlx5_nl_recv(nl, sn, mlx5_nl_cmdget_cb, data);
1106 if (!(data->flags & MLX5_NL_CMD_GET_IB_NAME) ||
1107 !(data->flags & MLX5_NL_CMD_GET_IB_INDEX) ||
1108 !(data->flags & MLX5_NL_CMD_GET_NET_INDEX) ||
1118 * Get index of network interface associated with some IB device.
1120 * This is the only somewhat safe method to avoid resorting to heuristics
1121 * when faced with port representors. Unfortunately it requires at least
1125 * Netlink socket of the RDMA kind (NETLINK_RDMA).
1129 * IB device port index, starting from 1
1131 * A valid (nonzero) interface index on success, 0 otherwise and rte_errno
1135 mlx5_nl_ifindex(int nl, const char *name, uint32_t pindex)
1137 struct mlx5_nl_port_info data = {
1142 if (mlx5_nl_port_info(nl, pindex, &data) < 0)
1144 return data.ifindex;
1148 * Get IB device port state.
1150 * This is the only somewhat safe method to get info for port number >= 255.
1151 * Unfortunately it requires at least Linux 4.17.
1154 * Netlink socket of the RDMA kind (NETLINK_RDMA).
1158 * IB device port index, starting from 1
1160 * Port state (ibv_port_state) on success, negative on error
1161 * and rte_errno is set.
1164 mlx5_nl_port_state(int nl, const char *name, uint32_t pindex)
1166 struct mlx5_nl_port_info data = {
1171 if (mlx5_nl_port_info(nl, pindex, &data) < 0)
1173 if ((data.flags & MLX5_NL_CMD_GET_PORT_STATE) == 0) {
1174 rte_errno = ENOTSUP;
1177 return (int)data.state;
1181 * Get the number of physical ports of given IB device.
1184 * Netlink socket of the RDMA kind (NETLINK_RDMA).
1189 * A valid (nonzero) number of ports on success, 0 otherwise
1190 * and rte_errno is set.
1193 mlx5_nl_portnum(int nl, const char *name)
1195 struct mlx5_nl_port_info data = {
1201 struct nlmsghdr req = {
1202 .nlmsg_len = NLMSG_LENGTH(0),
1203 .nlmsg_type = RDMA_NL_GET_TYPE(RDMA_NL_NLDEV,
1204 RDMA_NLDEV_CMD_GET),
1205 .nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP,
1207 uint32_t sn = MLX5_NL_SN_GENERATE;
1210 ret = mlx5_nl_send(nl, &req, sn);
1213 ret = mlx5_nl_recv(nl, sn, mlx5_nl_cmdget_cb, &data);
1216 if (!(data.flags & MLX5_NL_CMD_GET_IB_NAME) ||
1217 !(data.flags & MLX5_NL_CMD_GET_IB_INDEX) ||
1218 !(data.flags & MLX5_NL_CMD_GET_PORT_INDEX)) {
1224 return data.portnum;
1228 * Analyze gathered port parameters via Netlink to recognize master
1229 * and representor devices for E-Switch configuration.
1231 * @param[in] num_vf_set
1232 * flag of presence of number of VFs port attribute.
1233 * @param[inout] switch_info
1234 * Port information, including port name as a number and port name
1235 * type if recognized
1238 * master and representor flags are set in switch_info according to
1239 * recognized parameters (if any).
1242 mlx5_nl_check_switch_info(bool num_vf_set,
1243 struct mlx5_switch_info *switch_info)
1245 switch (switch_info->name_type) {
1246 case MLX5_PHYS_PORT_NAME_TYPE_UNKNOWN:
1248 * Name is not recognized, assume the master,
1249 * check the number of VFs key presence.
1251 switch_info->master = num_vf_set;
1253 case MLX5_PHYS_PORT_NAME_TYPE_NOTSET:
1255 * Name is not set, this assumes the legacy naming
1256 * schema for master, just check if there is a
1257 * number of VFs key.
1259 switch_info->master = num_vf_set;
1261 case MLX5_PHYS_PORT_NAME_TYPE_UPLINK:
1262 /* New uplink naming schema recognized. */
1263 switch_info->master = 1;
1265 case MLX5_PHYS_PORT_NAME_TYPE_LEGACY:
1266 /* Legacy representors naming schema. */
1267 switch_info->representor = !num_vf_set;
1269 case MLX5_PHYS_PORT_NAME_TYPE_PFHPF:
1271 case MLX5_PHYS_PORT_NAME_TYPE_PFVF:
1273 case MLX5_PHYS_PORT_NAME_TYPE_PFSF:
1274 /* New representors naming schema. */
1275 switch_info->representor = 1;
1281 * Process switch information from Netlink message.
1284 * Pointer to Netlink message header.
1286 * Opaque data pointer for this callback.
1289 * 0 on success, a negative errno value otherwise and rte_errno is set.
1292 mlx5_nl_switch_info_cb(struct nlmsghdr *nh, void *arg)
1294 struct mlx5_switch_info info = {
1297 .name_type = MLX5_PHYS_PORT_NAME_TYPE_NOTSET,
1301 size_t off = NLMSG_LENGTH(sizeof(struct ifinfomsg));
1302 bool switch_id_set = false;
1303 bool num_vf_set = false;
1306 if (nh->nlmsg_type != RTM_NEWLINK)
1308 while (off < nh->nlmsg_len) {
1309 struct rtattr *ra = (void *)((uintptr_t)nh + off);
1310 void *payload = RTA_DATA(ra);
1313 if (ra->rta_len > nh->nlmsg_len - off)
1315 switch (ra->rta_type) {
1319 case IFLA_PHYS_PORT_NAME:
1320 len = RTA_PAYLOAD(ra);
1321 /* Some kernels do not pad attributes with zero. */
1322 if (len > 0 && len < MLX5_PHYS_PORT_NAME_MAX) {
1323 char name[MLX5_PHYS_PORT_NAME_MAX];
1326 * We can't just patch the message with padding
1327 * zero - it might corrupt the following items
1328 * in the message, we have to copy the string
1329 * by attribute length and pad the copied one.
1331 memcpy(name, payload, len);
1333 mlx5_translate_port_name(name, &info);
1336 MLX5_PHYS_PORT_NAME_TYPE_UNKNOWN;
1339 case IFLA_PHYS_SWITCH_ID:
1341 for (i = 0; i < RTA_PAYLOAD(ra); ++i) {
1342 info.switch_id <<= 8;
1343 info.switch_id |= ((uint8_t *)payload)[i];
1345 switch_id_set = true;
1348 off += RTA_ALIGN(ra->rta_len);
1350 if (switch_id_set) {
1351 /* We have some E-Switch configuration. */
1352 mlx5_nl_check_switch_info(num_vf_set, &info);
1354 MLX5_ASSERT(!(info.master && info.representor));
1355 memcpy(arg, &info, sizeof(info));
1363 * Get switch information associated with network interface.
1366 * Netlink socket of the ROUTE kind (NETLINK_ROUTE).
1368 * Network interface index.
1370 * Switch information object, populated in case of success.
1373 * 0 on success, a negative errno value otherwise and rte_errno is set.
1376 mlx5_nl_switch_info(int nl, unsigned int ifindex,
1377 struct mlx5_switch_info *info)
1381 struct ifinfomsg info;
1386 .nlmsg_len = NLMSG_LENGTH
1388 RTA_LENGTH(sizeof(uint32_t))),
1389 .nlmsg_type = RTM_GETLINK,
1390 .nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
1393 .ifi_family = AF_UNSPEC,
1394 .ifi_index = ifindex,
1397 .rta_type = IFLA_EXT_MASK,
1398 .rta_len = RTA_LENGTH(sizeof(int32_t)),
1400 .extmask = RTE_LE32(1),
1402 uint32_t sn = MLX5_NL_SN_GENERATE;
1405 ret = mlx5_nl_send(nl, &req.nh, sn);
1407 ret = mlx5_nl_recv(nl, sn, mlx5_nl_switch_info_cb, info);
1408 if (info->master && info->representor) {
1409 DRV_LOG(ERR, "ifindex %u device is recognized as master"
1410 " and as representor", ifindex);
1418 * Delete VLAN network device by ifindex.
1421 * Context object initialized by mlx5_nl_vlan_vmwa_init().
1422 * @param[in] ifindex
1423 * Interface index of network device to delete.
1426 mlx5_nl_vlan_vmwa_delete(struct mlx5_nl_vlan_vmwa_context *vmwa,
1429 uint32_t sn = MLX5_NL_SN_GENERATE;
1433 struct ifinfomsg info;
1436 .nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
1437 .nlmsg_type = RTM_DELLINK,
1438 .nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
1441 .ifi_family = AF_UNSPEC,
1442 .ifi_index = ifindex,
1447 ret = mlx5_nl_send(vmwa->nl_socket, &req.nh, sn);
1449 ret = mlx5_nl_recv(vmwa->nl_socket, sn, NULL, NULL);
1451 DRV_LOG(WARNING, "netlink: error deleting VLAN WA"
1452 " ifindex %u, %d", ifindex, ret);
1456 /* Set of subroutines to build Netlink message. */
1457 static struct nlattr *
1458 nl_msg_tail(struct nlmsghdr *nlh)
1460 return (struct nlattr *)
1461 (((uint8_t *)nlh) + NLMSG_ALIGN(nlh->nlmsg_len));
1465 nl_attr_put(struct nlmsghdr *nlh, int type, const void *data, int alen)
1467 struct nlattr *nla = nl_msg_tail(nlh);
1469 nla->nla_type = type;
1470 nla->nla_len = NLMSG_ALIGN(sizeof(struct nlattr)) + alen;
1471 nlh->nlmsg_len += NLMSG_ALIGN(nla->nla_len);
1474 memcpy((uint8_t *)nla + sizeof(struct nlattr), data, alen);
1477 static struct nlattr *
1478 nl_attr_nest_start(struct nlmsghdr *nlh, int type)
1480 struct nlattr *nest = (struct nlattr *)nl_msg_tail(nlh);
1482 nl_attr_put(nlh, type, NULL, 0);
1487 nl_attr_nest_end(struct nlmsghdr *nlh, struct nlattr *nest)
1489 nest->nla_len = (uint8_t *)nl_msg_tail(nlh) - (uint8_t *)nest;
1493 * Create network VLAN device with specified VLAN tag.
1496 * Context object initialized by mlx5_nl_vlan_vmwa_init().
1497 * @param[in] ifindex
1498 * Base network interface index.
1500 * VLAN tag for VLAN network device to create.
1503 mlx5_nl_vlan_vmwa_create(struct mlx5_nl_vlan_vmwa_context *vmwa,
1504 uint32_t ifindex, uint16_t tag)
1506 struct nlmsghdr *nlh;
1507 struct ifinfomsg *ifm;
1508 char name[sizeof(MLX5_VMWA_VLAN_DEVICE_PFX) + 32];
1511 uint8_t buf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
1512 NLMSG_ALIGN(sizeof(struct ifinfomsg)) +
1513 NLMSG_ALIGN(sizeof(struct nlattr)) * 8 +
1514 NLMSG_ALIGN(sizeof(uint32_t)) +
1515 NLMSG_ALIGN(sizeof(name)) +
1516 NLMSG_ALIGN(sizeof("vlan")) +
1517 NLMSG_ALIGN(sizeof(uint32_t)) +
1518 NLMSG_ALIGN(sizeof(uint16_t)) + 16];
1519 struct nlattr *na_info;
1520 struct nlattr *na_vlan;
1521 uint32_t sn = MLX5_NL_SN_GENERATE;
1524 memset(buf, 0, sizeof(buf));
1525 nlh = (struct nlmsghdr *)buf;
1526 nlh->nlmsg_len = sizeof(struct nlmsghdr);
1527 nlh->nlmsg_type = RTM_NEWLINK;
1528 nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE |
1529 NLM_F_EXCL | NLM_F_ACK;
1530 ifm = (struct ifinfomsg *)nl_msg_tail(nlh);
1531 nlh->nlmsg_len += sizeof(struct ifinfomsg);
1532 ifm->ifi_family = AF_UNSPEC;
1535 ifm->ifi_flags = IFF_UP;
1536 ifm->ifi_change = 0xffffffff;
1537 nl_attr_put(nlh, IFLA_LINK, &ifindex, sizeof(ifindex));
1538 ret = snprintf(name, sizeof(name), "%s.%u.%u",
1539 MLX5_VMWA_VLAN_DEVICE_PFX, ifindex, tag);
1540 nl_attr_put(nlh, IFLA_IFNAME, name, ret + 1);
1541 na_info = nl_attr_nest_start(nlh, IFLA_LINKINFO);
1542 nl_attr_put(nlh, IFLA_INFO_KIND, "vlan", sizeof("vlan"));
1543 na_vlan = nl_attr_nest_start(nlh, IFLA_INFO_DATA);
1544 nl_attr_put(nlh, IFLA_VLAN_ID, &tag, sizeof(tag));
1545 nl_attr_nest_end(nlh, na_vlan);
1546 nl_attr_nest_end(nlh, na_info);
1547 MLX5_ASSERT(sizeof(buf) >= nlh->nlmsg_len);
1548 ret = mlx5_nl_send(vmwa->nl_socket, nlh, sn);
1550 ret = mlx5_nl_recv(vmwa->nl_socket, sn, NULL, NULL);
1552 DRV_LOG(WARNING, "netlink: VLAN %s create failure (%d)", name,
1555 /* Try to get ifindex of created or pre-existing device. */
1556 ret = if_nametoindex(name);
1558 DRV_LOG(WARNING, "VLAN %s failed to get index (%d)", name,
1566 * Parse Netlink message to retrieve the general family ID.
1569 * Pointer to Netlink Message Header.
1571 * PMD data register with this callback.
1574 * 0 on success, a negative errno value otherwise and rte_errno is set.
1577 mlx5_nl_family_id_cb(struct nlmsghdr *nh, void *arg)
1580 struct nlattr *tail = RTE_PTR_ADD(nh, nh->nlmsg_len);
1581 struct nlattr *nla = RTE_PTR_ADD(nh, NLMSG_ALIGN(sizeof(*nh)) +
1582 NLMSG_ALIGN(sizeof(struct genlmsghdr)));
1584 for (; nla->nla_len && nla < tail;
1585 nla = RTE_PTR_ADD(nla, NLMSG_ALIGN(nla->nla_len))) {
1586 if (nla->nla_type == CTRL_ATTR_FAMILY_ID) {
1587 *(uint16_t *)arg = *(uint16_t *)(nla + 1);
1594 #define MLX5_NL_MAX_ATTR_SIZE 100
1596 * Get generic netlink family ID.
1598 * @param[in] nlsk_fd
1599 * Netlink socket file descriptor.
1604 * ID >= 0 on success and @p enable is updated, a negative errno value
1605 * otherwise and rte_errno is set.
1608 mlx5_nl_generic_family_id_get(int nlsk_fd, const char *name)
1610 struct nlmsghdr *nlh;
1611 struct genlmsghdr *genl;
1612 uint32_t sn = MLX5_NL_SN_GENERATE;
1613 int name_size = strlen(name) + 1;
1616 uint8_t buf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
1617 NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
1618 NLMSG_ALIGN(sizeof(struct nlattr)) +
1619 NLMSG_ALIGN(MLX5_NL_MAX_ATTR_SIZE)];
1621 memset(buf, 0, sizeof(buf));
1622 nlh = (struct nlmsghdr *)buf;
1623 nlh->nlmsg_len = sizeof(struct nlmsghdr);
1624 nlh->nlmsg_type = GENL_ID_CTRL;
1625 nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
1626 genl = (struct genlmsghdr *)nl_msg_tail(nlh);
1627 nlh->nlmsg_len += sizeof(struct genlmsghdr);
1628 genl->cmd = CTRL_CMD_GETFAMILY;
1630 nl_attr_put(nlh, CTRL_ATTR_FAMILY_NAME, name, name_size);
1631 ret = mlx5_nl_send(nlsk_fd, nlh, sn);
1633 ret = mlx5_nl_recv(nlsk_fd, sn, mlx5_nl_family_id_cb, &id);
1635 DRV_LOG(DEBUG, "Failed to get Netlink %s family ID: %d.", name,
1639 DRV_LOG(DEBUG, "Netlink \"%s\" family ID is %u.", name, id);
1644 * Get Devlink family ID.
1646 * @param[in] nlsk_fd
1647 * Netlink socket file descriptor.
1650 * ID >= 0 on success and @p enable is updated, a negative errno value
1651 * otherwise and rte_errno is set.
1655 mlx5_nl_devlink_family_id_get(int nlsk_fd)
1657 return mlx5_nl_generic_family_id_get(nlsk_fd, DEVLINK_GENL_NAME);
1661 * Parse Netlink message to retrieve the ROCE enable status.
1664 * Pointer to Netlink Message Header.
1666 * PMD data register with this callback.
1669 * 0 on success, a negative errno value otherwise and rte_errno is set.
1672 mlx5_nl_roce_cb(struct nlmsghdr *nh, void *arg)
1677 struct nlattr *tail = RTE_PTR_ADD(nh, nh->nlmsg_len);
1678 struct nlattr *nla = RTE_PTR_ADD(nh, NLMSG_ALIGN(sizeof(*nh)) +
1679 NLMSG_ALIGN(sizeof(struct genlmsghdr)));
1681 while (nla->nla_len && nla < tail) {
1682 switch (nla->nla_type) {
1683 /* Expected nested attributes case. */
1684 case DEVLINK_ATTR_PARAM:
1685 case DEVLINK_ATTR_PARAM_VALUES_LIST:
1686 case DEVLINK_ATTR_PARAM_VALUE:
1690 case DEVLINK_ATTR_PARAM_VALUE_DATA:
1694 nla = RTE_PTR_ADD(nla, NLMSG_ALIGN(nla->nla_len));
1702 * Get ROCE enable status through Netlink.
1704 * @param[in] nlsk_fd
1705 * Netlink socket file descriptor.
1706 * @param[in] family_id
1707 * the Devlink family ID.
1709 * The device PCI address.
1710 * @param[out] enable
1711 * Where to store the enable status.
1714 * 0 on success and @p enable is updated, a negative errno value otherwise
1715 * and rte_errno is set.
1718 mlx5_nl_enable_roce_get(int nlsk_fd, int family_id, const char *pci_addr,
1721 struct nlmsghdr *nlh;
1722 struct genlmsghdr *genl;
1723 uint32_t sn = MLX5_NL_SN_GENERATE;
1726 uint8_t buf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
1727 NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
1728 NLMSG_ALIGN(sizeof(struct nlattr)) * 4 +
1729 NLMSG_ALIGN(MLX5_NL_MAX_ATTR_SIZE) * 4];
1731 memset(buf, 0, sizeof(buf));
1732 nlh = (struct nlmsghdr *)buf;
1733 nlh->nlmsg_len = sizeof(struct nlmsghdr);
1734 nlh->nlmsg_type = family_id;
1735 nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
1736 genl = (struct genlmsghdr *)nl_msg_tail(nlh);
1737 nlh->nlmsg_len += sizeof(struct genlmsghdr);
1738 genl->cmd = DEVLINK_CMD_PARAM_GET;
1739 genl->version = DEVLINK_GENL_VERSION;
1740 nl_attr_put(nlh, DEVLINK_ATTR_BUS_NAME, "pci", 4);
1741 nl_attr_put(nlh, DEVLINK_ATTR_DEV_NAME, pci_addr, strlen(pci_addr) + 1);
1742 nl_attr_put(nlh, DEVLINK_ATTR_PARAM_NAME, "enable_roce", 12);
1743 ret = mlx5_nl_send(nlsk_fd, nlh, sn);
1745 ret = mlx5_nl_recv(nlsk_fd, sn, mlx5_nl_roce_cb, &cur_en);
1747 DRV_LOG(DEBUG, "Failed to get ROCE enable on device %s: %d.",
1752 DRV_LOG(DEBUG, "ROCE is %sabled for device \"%s\".",
1753 cur_en ? "en" : "dis", pci_addr);
1758 * Reload mlx5 device kernel driver through Netlink.
1760 * @param[in] nlsk_fd
1761 * Netlink socket file descriptor.
1762 * @param[in] family_id
1763 * the Devlink family ID.
1765 * The device PCI address.
1766 * @param[out] enable
1767 * The enable status to set.
1770 * 0 on success, a negative errno value otherwise and rte_errno is set.
1773 mlx5_nl_driver_reload(int nlsk_fd, int family_id, const char *pci_addr)
1775 struct nlmsghdr *nlh;
1776 struct genlmsghdr *genl;
1777 uint32_t sn = MLX5_NL_SN_GENERATE;
1779 uint8_t buf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
1780 NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
1781 NLMSG_ALIGN(sizeof(struct nlattr)) * 2 +
1782 NLMSG_ALIGN(MLX5_NL_MAX_ATTR_SIZE) * 2];
1784 memset(buf, 0, sizeof(buf));
1785 nlh = (struct nlmsghdr *)buf;
1786 nlh->nlmsg_len = sizeof(struct nlmsghdr);
1787 nlh->nlmsg_type = family_id;
1788 nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
1789 genl = (struct genlmsghdr *)nl_msg_tail(nlh);
1790 nlh->nlmsg_len += sizeof(struct genlmsghdr);
1791 genl->cmd = DEVLINK_CMD_RELOAD;
1792 genl->version = DEVLINK_GENL_VERSION;
1793 nl_attr_put(nlh, DEVLINK_ATTR_BUS_NAME, "pci", 4);
1794 nl_attr_put(nlh, DEVLINK_ATTR_DEV_NAME, pci_addr, strlen(pci_addr) + 1);
1795 ret = mlx5_nl_send(nlsk_fd, nlh, sn);
1797 ret = mlx5_nl_recv(nlsk_fd, sn, NULL, NULL);
1799 DRV_LOG(DEBUG, "Failed to reload %s device by Netlink - %d",
1803 DRV_LOG(DEBUG, "Device \"%s\" was reloaded by Netlink successfully.",
1809 * Set ROCE enable status through Netlink.
1811 * @param[in] nlsk_fd
1812 * Netlink socket file descriptor.
1813 * @param[in] family_id
1814 * the Devlink family ID.
1816 * The device PCI address.
1817 * @param[out] enable
1818 * The enable status to set.
1821 * 0 on success, a negative errno value otherwise and rte_errno is set.
1824 mlx5_nl_enable_roce_set(int nlsk_fd, int family_id, const char *pci_addr,
1827 struct nlmsghdr *nlh;
1828 struct genlmsghdr *genl;
1829 uint32_t sn = MLX5_NL_SN_GENERATE;
1831 uint8_t buf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
1832 NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
1833 NLMSG_ALIGN(sizeof(struct nlattr)) * 6 +
1834 NLMSG_ALIGN(MLX5_NL_MAX_ATTR_SIZE) * 6];
1835 uint8_t cmode = DEVLINK_PARAM_CMODE_DRIVERINIT;
1836 uint8_t ptype = NLA_FLAG;
1839 memset(buf, 0, sizeof(buf));
1840 nlh = (struct nlmsghdr *)buf;
1841 nlh->nlmsg_len = sizeof(struct nlmsghdr);
1842 nlh->nlmsg_type = family_id;
1843 nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
1844 genl = (struct genlmsghdr *)nl_msg_tail(nlh);
1845 nlh->nlmsg_len += sizeof(struct genlmsghdr);
1846 genl->cmd = DEVLINK_CMD_PARAM_SET;
1847 genl->version = DEVLINK_GENL_VERSION;
1848 nl_attr_put(nlh, DEVLINK_ATTR_BUS_NAME, "pci", 4);
1849 nl_attr_put(nlh, DEVLINK_ATTR_DEV_NAME, pci_addr, strlen(pci_addr) + 1);
1850 nl_attr_put(nlh, DEVLINK_ATTR_PARAM_NAME, "enable_roce", 12);
1851 nl_attr_put(nlh, DEVLINK_ATTR_PARAM_VALUE_CMODE, &cmode, sizeof(cmode));
1852 nl_attr_put(nlh, DEVLINK_ATTR_PARAM_TYPE, &ptype, sizeof(ptype));
1854 nl_attr_put(nlh, DEVLINK_ATTR_PARAM_VALUE_DATA, NULL, 0);
1855 ret = mlx5_nl_send(nlsk_fd, nlh, sn);
1857 ret = mlx5_nl_recv(nlsk_fd, sn, NULL, NULL);
1859 DRV_LOG(DEBUG, "Failed to %sable ROCE for device %s by Netlink:"
1860 " %d.", enable ? "en" : "dis", pci_addr, ret);
1863 DRV_LOG(DEBUG, "Device %s ROCE was %sabled by Netlink successfully.",
1864 pci_addr, enable ? "en" : "dis");
1865 /* Now, need to reload the driver. */
1866 return mlx5_nl_driver_reload(nlsk_fd, family_id, pci_addr);
1870 * Try to parse a Netlink message as a link status update.
1873 * Netlink message header.
1874 * @param[out] ifindex
1875 * Index of the updated interface.
1878 * 0 on success, negative on failure.
1881 mlx5_nl_parse_link_status_update(struct nlmsghdr *hdr, uint32_t *ifindex)
1883 struct ifinfomsg *info;
1885 switch (hdr->nlmsg_type) {
1890 info = NLMSG_DATA(hdr);
1891 *ifindex = info->ifi_index;
1898 * Read pending events from a Netlink socket.
1903 * Callback invoked for each of the events.
1905 * User data for the callback.
1908 * 0 on success, including the case when there are no events.
1909 * Negative on failure and rte_errno is set.
1912 mlx5_nl_read_events(int nlsk_fd, mlx5_nl_event_cb *cb, void *cb_arg)
1915 struct sockaddr_nl addr;
1916 struct iovec iov = {
1918 .iov_len = sizeof(buf),
1920 struct msghdr msg = {
1922 .msg_namelen = sizeof(addr),
1926 struct nlmsghdr *hdr;
1930 size = recvmsg(nlsk_fd, &msg, MSG_DONTWAIT);
1932 if (errno == EAGAIN)
1936 DRV_LOG(DEBUG, "Failed to receive netlink message: %s",
1941 hdr = (struct nlmsghdr *)buf;
1942 while (size >= (ssize_t)sizeof(*hdr)) {
1943 ssize_t msg_len = hdr->nlmsg_len;
1944 ssize_t data_len = msg_len - sizeof(*hdr);
1945 ssize_t aligned_len;
1948 DRV_LOG(DEBUG, "Netlink message too short");
1952 aligned_len = NLMSG_ALIGN(msg_len);
1953 if (aligned_len > size) {
1954 DRV_LOG(DEBUG, "Netlink message too long");
1959 hdr = RTE_PTR_ADD(hdr, aligned_len);
1960 size -= aligned_len;