2869 lines · c
1/*2 * Copyright (c) 2017 Mellanox Technologies. All rights reserved.3 *4 * Redistribution and use in source and binary forms, with or without5 * modification, are permitted provided that the following conditions are met:6 *7 * 1. Redistributions of source code must retain the above copyright8 * notice, this list of conditions and the following disclaimer.9 * 2. Redistributions in binary form must reproduce the above copyright10 * notice, this list of conditions and the following disclaimer in the11 * documentation and/or other materials provided with the distribution.12 * 3. Neither the names of the copyright holders nor the names of its13 * contributors may be used to endorse or promote products derived from14 * this software without specific prior written permission.15 *16 * Alternatively, this software may be distributed under the terms of the17 * GNU General Public License ("GPL") version 2 as published by the Free18 * Software Foundation.19 *20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE30 * POSSIBILITY OF SUCH DAMAGE.31 */32 33#include <linux/module.h>34#include <linux/pid.h>35#include <linux/pid_namespace.h>36#include <linux/mutex.h>37#include <net/netlink.h>38#include <rdma/rdma_cm.h>39#include <rdma/rdma_netlink.h>40 41#include "core_priv.h"42#include "cma_priv.h"43#include "restrack.h"44#include "uverbs.h"45 46/*47 * This determines whether a non-privileged user is allowed to specify a48 * controlled QKEY or not, when true non-privileged user is allowed to specify49 * a controlled QKEY.50 */51static bool privileged_qkey;52 53typedef int (*res_fill_func_t)(struct sk_buff*, bool,54 struct rdma_restrack_entry*, uint32_t);55 56/*57 * Sort array elements by the netlink attribute name58 */59static const struct nla_policy nldev_policy[RDMA_NLDEV_ATTR_MAX] = {60 [RDMA_NLDEV_ATTR_CHARDEV] = { .type = NLA_U64 },61 [RDMA_NLDEV_ATTR_CHARDEV_ABI] = { .type = NLA_U64 },62 [RDMA_NLDEV_ATTR_CHARDEV_NAME] = { .type = NLA_NUL_STRING,63 .len = RDMA_NLDEV_ATTR_EMPTY_STRING },64 [RDMA_NLDEV_ATTR_CHARDEV_TYPE] = { .type = NLA_NUL_STRING,65 .len = RDMA_NLDEV_ATTR_CHARDEV_TYPE_SIZE },66 [RDMA_NLDEV_ATTR_DEV_DIM] = { .type = NLA_U8 },67 [RDMA_NLDEV_ATTR_DEV_INDEX] = { .type = NLA_U32 },68 [RDMA_NLDEV_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING,69 .len = IB_DEVICE_NAME_MAX },70 [RDMA_NLDEV_ATTR_DEV_NODE_TYPE] = { .type = NLA_U8 },71 [RDMA_NLDEV_ATTR_DEV_PROTOCOL] = { .type = NLA_NUL_STRING,72 .len = RDMA_NLDEV_ATTR_EMPTY_STRING },73 [RDMA_NLDEV_ATTR_DRIVER] = { .type = NLA_NESTED },74 [RDMA_NLDEV_ATTR_DRIVER_ENTRY] = { .type = NLA_NESTED },75 [RDMA_NLDEV_ATTR_DRIVER_PRINT_TYPE] = { .type = NLA_U8 },76 [RDMA_NLDEV_ATTR_DRIVER_STRING] = { .type = NLA_NUL_STRING,77 .len = RDMA_NLDEV_ATTR_EMPTY_STRING },78 [RDMA_NLDEV_ATTR_DRIVER_S32] = { .type = NLA_S32 },79 [RDMA_NLDEV_ATTR_DRIVER_S64] = { .type = NLA_S64 },80 [RDMA_NLDEV_ATTR_DRIVER_U32] = { .type = NLA_U32 },81 [RDMA_NLDEV_ATTR_DRIVER_U64] = { .type = NLA_U64 },82 [RDMA_NLDEV_ATTR_FW_VERSION] = { .type = NLA_NUL_STRING,83 .len = RDMA_NLDEV_ATTR_EMPTY_STRING },84 [RDMA_NLDEV_ATTR_LID] = { .type = NLA_U32 },85 [RDMA_NLDEV_ATTR_LINK_TYPE] = { .type = NLA_NUL_STRING,86 .len = IFNAMSIZ },87 [RDMA_NLDEV_ATTR_LMC] = { .type = NLA_U8 },88 [RDMA_NLDEV_ATTR_NDEV_INDEX] = { .type = NLA_U32 },89 [RDMA_NLDEV_ATTR_NDEV_NAME] = { .type = NLA_NUL_STRING,90 .len = IFNAMSIZ },91 [RDMA_NLDEV_ATTR_NODE_GUID] = { .type = NLA_U64 },92 [RDMA_NLDEV_ATTR_PORT_INDEX] = { .type = NLA_U32 },93 [RDMA_NLDEV_ATTR_PORT_PHYS_STATE] = { .type = NLA_U8 },94 [RDMA_NLDEV_ATTR_PORT_STATE] = { .type = NLA_U8 },95 [RDMA_NLDEV_ATTR_RES_CM_ID] = { .type = NLA_NESTED },96 [RDMA_NLDEV_ATTR_RES_CM_IDN] = { .type = NLA_U32 },97 [RDMA_NLDEV_ATTR_RES_CM_ID_ENTRY] = { .type = NLA_NESTED },98 [RDMA_NLDEV_ATTR_RES_CQ] = { .type = NLA_NESTED },99 [RDMA_NLDEV_ATTR_RES_CQE] = { .type = NLA_U32 },100 [RDMA_NLDEV_ATTR_RES_CQN] = { .type = NLA_U32 },101 [RDMA_NLDEV_ATTR_RES_CQ_ENTRY] = { .type = NLA_NESTED },102 [RDMA_NLDEV_ATTR_RES_CTX] = { .type = NLA_NESTED },103 [RDMA_NLDEV_ATTR_RES_CTXN] = { .type = NLA_U32 },104 [RDMA_NLDEV_ATTR_RES_CTX_ENTRY] = { .type = NLA_NESTED },105 [RDMA_NLDEV_ATTR_RES_DST_ADDR] = {106 .len = sizeof(struct __kernel_sockaddr_storage) },107 [RDMA_NLDEV_ATTR_RES_IOVA] = { .type = NLA_U64 },108 [RDMA_NLDEV_ATTR_RES_KERN_NAME] = { .type = NLA_NUL_STRING,109 .len = RDMA_NLDEV_ATTR_EMPTY_STRING },110 [RDMA_NLDEV_ATTR_RES_LKEY] = { .type = NLA_U32 },111 [RDMA_NLDEV_ATTR_RES_LOCAL_DMA_LKEY] = { .type = NLA_U32 },112 [RDMA_NLDEV_ATTR_RES_LQPN] = { .type = NLA_U32 },113 [RDMA_NLDEV_ATTR_RES_MR] = { .type = NLA_NESTED },114 [RDMA_NLDEV_ATTR_RES_MRLEN] = { .type = NLA_U64 },115 [RDMA_NLDEV_ATTR_RES_MRN] = { .type = NLA_U32 },116 [RDMA_NLDEV_ATTR_RES_MR_ENTRY] = { .type = NLA_NESTED },117 [RDMA_NLDEV_ATTR_RES_PATH_MIG_STATE] = { .type = NLA_U8 },118 [RDMA_NLDEV_ATTR_RES_PD] = { .type = NLA_NESTED },119 [RDMA_NLDEV_ATTR_RES_PDN] = { .type = NLA_U32 },120 [RDMA_NLDEV_ATTR_RES_PD_ENTRY] = { .type = NLA_NESTED },121 [RDMA_NLDEV_ATTR_RES_PID] = { .type = NLA_U32 },122 [RDMA_NLDEV_ATTR_RES_POLL_CTX] = { .type = NLA_U8 },123 [RDMA_NLDEV_ATTR_RES_PS] = { .type = NLA_U32 },124 [RDMA_NLDEV_ATTR_RES_QP] = { .type = NLA_NESTED },125 [RDMA_NLDEV_ATTR_RES_QP_ENTRY] = { .type = NLA_NESTED },126 [RDMA_NLDEV_ATTR_RES_RAW] = { .type = NLA_BINARY },127 [RDMA_NLDEV_ATTR_RES_RKEY] = { .type = NLA_U32 },128 [RDMA_NLDEV_ATTR_RES_RQPN] = { .type = NLA_U32 },129 [RDMA_NLDEV_ATTR_RES_RQ_PSN] = { .type = NLA_U32 },130 [RDMA_NLDEV_ATTR_RES_SQ_PSN] = { .type = NLA_U32 },131 [RDMA_NLDEV_ATTR_RES_SRC_ADDR] = {132 .len = sizeof(struct __kernel_sockaddr_storage) },133 [RDMA_NLDEV_ATTR_RES_STATE] = { .type = NLA_U8 },134 [RDMA_NLDEV_ATTR_RES_SUMMARY] = { .type = NLA_NESTED },135 [RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY] = { .type = NLA_NESTED },136 [RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_CURR]= { .type = NLA_U64 },137 [RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_NAME]= { .type = NLA_NUL_STRING,138 .len = RDMA_NLDEV_ATTR_EMPTY_STRING },139 [RDMA_NLDEV_ATTR_RES_TYPE] = { .type = NLA_U8 },140 [RDMA_NLDEV_ATTR_RES_SUBTYPE] = { .type = NLA_NUL_STRING,141 .len = RDMA_NLDEV_ATTR_EMPTY_STRING },142 [RDMA_NLDEV_ATTR_RES_UNSAFE_GLOBAL_RKEY]= { .type = NLA_U32 },143 [RDMA_NLDEV_ATTR_RES_USECNT] = { .type = NLA_U64 },144 [RDMA_NLDEV_ATTR_RES_SRQ] = { .type = NLA_NESTED },145 [RDMA_NLDEV_ATTR_RES_SRQN] = { .type = NLA_U32 },146 [RDMA_NLDEV_ATTR_RES_SRQ_ENTRY] = { .type = NLA_NESTED },147 [RDMA_NLDEV_ATTR_MIN_RANGE] = { .type = NLA_U32 },148 [RDMA_NLDEV_ATTR_MAX_RANGE] = { .type = NLA_U32 },149 [RDMA_NLDEV_ATTR_SM_LID] = { .type = NLA_U32 },150 [RDMA_NLDEV_ATTR_SUBNET_PREFIX] = { .type = NLA_U64 },151 [RDMA_NLDEV_ATTR_STAT_AUTO_MODE_MASK] = { .type = NLA_U32 },152 [RDMA_NLDEV_ATTR_STAT_MODE] = { .type = NLA_U32 },153 [RDMA_NLDEV_ATTR_STAT_RES] = { .type = NLA_U32 },154 [RDMA_NLDEV_ATTR_STAT_COUNTER] = { .type = NLA_NESTED },155 [RDMA_NLDEV_ATTR_STAT_COUNTER_ENTRY] = { .type = NLA_NESTED },156 [RDMA_NLDEV_ATTR_STAT_COUNTER_ID] = { .type = NLA_U32 },157 [RDMA_NLDEV_ATTR_STAT_HWCOUNTERS] = { .type = NLA_NESTED },158 [RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY] = { .type = NLA_NESTED },159 [RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_NAME] = { .type = NLA_NUL_STRING },160 [RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_VALUE] = { .type = NLA_U64 },161 [RDMA_NLDEV_ATTR_SYS_IMAGE_GUID] = { .type = NLA_U64 },162 [RDMA_NLDEV_ATTR_UVERBS_DRIVER_ID] = { .type = NLA_U32 },163 [RDMA_NLDEV_NET_NS_FD] = { .type = NLA_U32 },164 [RDMA_NLDEV_SYS_ATTR_NETNS_MODE] = { .type = NLA_U8 },165 [RDMA_NLDEV_SYS_ATTR_COPY_ON_FORK] = { .type = NLA_U8 },166 [RDMA_NLDEV_ATTR_STAT_HWCOUNTER_INDEX] = { .type = NLA_U32 },167 [RDMA_NLDEV_ATTR_STAT_HWCOUNTER_DYNAMIC] = { .type = NLA_U8 },168 [RDMA_NLDEV_SYS_ATTR_PRIVILEGED_QKEY_MODE] = { .type = NLA_U8 },169 [RDMA_NLDEV_ATTR_DRIVER_DETAILS] = { .type = NLA_U8 },170 [RDMA_NLDEV_ATTR_DEV_TYPE] = { .type = NLA_U8 },171 [RDMA_NLDEV_ATTR_PARENT_NAME] = { .type = NLA_NUL_STRING },172 [RDMA_NLDEV_ATTR_NAME_ASSIGN_TYPE] = { .type = NLA_U8 },173 [RDMA_NLDEV_ATTR_EVENT_TYPE] = { .type = NLA_U8 },174};175 176static int put_driver_name_print_type(struct sk_buff *msg, const char *name,177 enum rdma_nldev_print_type print_type)178{179 if (nla_put_string(msg, RDMA_NLDEV_ATTR_DRIVER_STRING, name))180 return -EMSGSIZE;181 if (print_type != RDMA_NLDEV_PRINT_TYPE_UNSPEC &&182 nla_put_u8(msg, RDMA_NLDEV_ATTR_DRIVER_PRINT_TYPE, print_type))183 return -EMSGSIZE;184 185 return 0;186}187 188static int _rdma_nl_put_driver_u32(struct sk_buff *msg, const char *name,189 enum rdma_nldev_print_type print_type,190 u32 value)191{192 if (put_driver_name_print_type(msg, name, print_type))193 return -EMSGSIZE;194 if (nla_put_u32(msg, RDMA_NLDEV_ATTR_DRIVER_U32, value))195 return -EMSGSIZE;196 197 return 0;198}199 200static int _rdma_nl_put_driver_u64(struct sk_buff *msg, const char *name,201 enum rdma_nldev_print_type print_type,202 u64 value)203{204 if (put_driver_name_print_type(msg, name, print_type))205 return -EMSGSIZE;206 if (nla_put_u64_64bit(msg, RDMA_NLDEV_ATTR_DRIVER_U64, value,207 RDMA_NLDEV_ATTR_PAD))208 return -EMSGSIZE;209 210 return 0;211}212 213int rdma_nl_put_driver_string(struct sk_buff *msg, const char *name,214 const char *str)215{216 if (put_driver_name_print_type(msg, name,217 RDMA_NLDEV_PRINT_TYPE_UNSPEC))218 return -EMSGSIZE;219 if (nla_put_string(msg, RDMA_NLDEV_ATTR_DRIVER_STRING, str))220 return -EMSGSIZE;221 222 return 0;223}224EXPORT_SYMBOL(rdma_nl_put_driver_string);225 226int rdma_nl_put_driver_u32(struct sk_buff *msg, const char *name, u32 value)227{228 return _rdma_nl_put_driver_u32(msg, name, RDMA_NLDEV_PRINT_TYPE_UNSPEC,229 value);230}231EXPORT_SYMBOL(rdma_nl_put_driver_u32);232 233int rdma_nl_put_driver_u32_hex(struct sk_buff *msg, const char *name,234 u32 value)235{236 return _rdma_nl_put_driver_u32(msg, name, RDMA_NLDEV_PRINT_TYPE_HEX,237 value);238}239EXPORT_SYMBOL(rdma_nl_put_driver_u32_hex);240 241int rdma_nl_put_driver_u64(struct sk_buff *msg, const char *name, u64 value)242{243 return _rdma_nl_put_driver_u64(msg, name, RDMA_NLDEV_PRINT_TYPE_UNSPEC,244 value);245}246EXPORT_SYMBOL(rdma_nl_put_driver_u64);247 248int rdma_nl_put_driver_u64_hex(struct sk_buff *msg, const char *name, u64 value)249{250 return _rdma_nl_put_driver_u64(msg, name, RDMA_NLDEV_PRINT_TYPE_HEX,251 value);252}253EXPORT_SYMBOL(rdma_nl_put_driver_u64_hex);254 255bool rdma_nl_get_privileged_qkey(void)256{257 return privileged_qkey || capable(CAP_NET_RAW);258}259EXPORT_SYMBOL(rdma_nl_get_privileged_qkey);260 261static int fill_nldev_handle(struct sk_buff *msg, struct ib_device *device)262{263 if (nla_put_u32(msg, RDMA_NLDEV_ATTR_DEV_INDEX, device->index))264 return -EMSGSIZE;265 if (nla_put_string(msg, RDMA_NLDEV_ATTR_DEV_NAME,266 dev_name(&device->dev)))267 return -EMSGSIZE;268 269 return 0;270}271 272static int fill_dev_info(struct sk_buff *msg, struct ib_device *device)273{274 char fw[IB_FW_VERSION_NAME_MAX];275 int ret = 0;276 u32 port;277 278 if (fill_nldev_handle(msg, device))279 return -EMSGSIZE;280 281 if (nla_put_u32(msg, RDMA_NLDEV_ATTR_PORT_INDEX, rdma_end_port(device)))282 return -EMSGSIZE;283 284 BUILD_BUG_ON(sizeof(device->attrs.device_cap_flags) != sizeof(u64));285 if (nla_put_u64_64bit(msg, RDMA_NLDEV_ATTR_CAP_FLAGS,286 device->attrs.device_cap_flags,287 RDMA_NLDEV_ATTR_PAD))288 return -EMSGSIZE;289 290 ib_get_device_fw_str(device, fw);291 /* Device without FW has strlen(fw) = 0 */292 if (strlen(fw) && nla_put_string(msg, RDMA_NLDEV_ATTR_FW_VERSION, fw))293 return -EMSGSIZE;294 295 if (nla_put_u64_64bit(msg, RDMA_NLDEV_ATTR_NODE_GUID,296 be64_to_cpu(device->node_guid),297 RDMA_NLDEV_ATTR_PAD))298 return -EMSGSIZE;299 if (nla_put_u64_64bit(msg, RDMA_NLDEV_ATTR_SYS_IMAGE_GUID,300 be64_to_cpu(device->attrs.sys_image_guid),301 RDMA_NLDEV_ATTR_PAD))302 return -EMSGSIZE;303 if (nla_put_u8(msg, RDMA_NLDEV_ATTR_DEV_NODE_TYPE, device->node_type))304 return -EMSGSIZE;305 if (nla_put_u8(msg, RDMA_NLDEV_ATTR_DEV_DIM, device->use_cq_dim))306 return -EMSGSIZE;307 308 if (device->type &&309 nla_put_u8(msg, RDMA_NLDEV_ATTR_DEV_TYPE, device->type))310 return -EMSGSIZE;311 312 if (device->parent &&313 nla_put_string(msg, RDMA_NLDEV_ATTR_PARENT_NAME,314 dev_name(&device->parent->dev)))315 return -EMSGSIZE;316 317 if (nla_put_u8(msg, RDMA_NLDEV_ATTR_NAME_ASSIGN_TYPE,318 device->name_assign_type))319 return -EMSGSIZE;320 321 /*322 * Link type is determined on first port and mlx4 device323 * which can potentially have two different link type for the same324 * IB device is considered as better to be avoided in the future,325 */326 port = rdma_start_port(device);327 if (rdma_cap_opa_mad(device, port))328 ret = nla_put_string(msg, RDMA_NLDEV_ATTR_DEV_PROTOCOL, "opa");329 else if (rdma_protocol_ib(device, port))330 ret = nla_put_string(msg, RDMA_NLDEV_ATTR_DEV_PROTOCOL, "ib");331 else if (rdma_protocol_iwarp(device, port))332 ret = nla_put_string(msg, RDMA_NLDEV_ATTR_DEV_PROTOCOL, "iw");333 else if (rdma_protocol_roce(device, port))334 ret = nla_put_string(msg, RDMA_NLDEV_ATTR_DEV_PROTOCOL, "roce");335 else if (rdma_protocol_usnic(device, port))336 ret = nla_put_string(msg, RDMA_NLDEV_ATTR_DEV_PROTOCOL,337 "usnic");338 return ret;339}340 341static int fill_port_info(struct sk_buff *msg,342 struct ib_device *device, u32 port,343 const struct net *net)344{345 struct net_device *netdev = NULL;346 struct ib_port_attr attr;347 int ret;348 u64 cap_flags = 0;349 350 if (fill_nldev_handle(msg, device))351 return -EMSGSIZE;352 353 if (nla_put_u32(msg, RDMA_NLDEV_ATTR_PORT_INDEX, port))354 return -EMSGSIZE;355 356 ret = ib_query_port(device, port, &attr);357 if (ret)358 return ret;359 360 if (rdma_protocol_ib(device, port)) {361 BUILD_BUG_ON((sizeof(attr.port_cap_flags) +362 sizeof(attr.port_cap_flags2)) > sizeof(u64));363 cap_flags = attr.port_cap_flags |364 ((u64)attr.port_cap_flags2 << 32);365 if (nla_put_u64_64bit(msg, RDMA_NLDEV_ATTR_CAP_FLAGS,366 cap_flags, RDMA_NLDEV_ATTR_PAD))367 return -EMSGSIZE;368 if (nla_put_u64_64bit(msg, RDMA_NLDEV_ATTR_SUBNET_PREFIX,369 attr.subnet_prefix, RDMA_NLDEV_ATTR_PAD))370 return -EMSGSIZE;371 if (nla_put_u32(msg, RDMA_NLDEV_ATTR_LID, attr.lid))372 return -EMSGSIZE;373 if (nla_put_u32(msg, RDMA_NLDEV_ATTR_SM_LID, attr.sm_lid))374 return -EMSGSIZE;375 if (nla_put_u8(msg, RDMA_NLDEV_ATTR_LMC, attr.lmc))376 return -EMSGSIZE;377 }378 if (nla_put_u8(msg, RDMA_NLDEV_ATTR_PORT_STATE, attr.state))379 return -EMSGSIZE;380 if (nla_put_u8(msg, RDMA_NLDEV_ATTR_PORT_PHYS_STATE, attr.phys_state))381 return -EMSGSIZE;382 383 netdev = ib_device_get_netdev(device, port);384 if (netdev && net_eq(dev_net(netdev), net)) {385 ret = nla_put_u32(msg,386 RDMA_NLDEV_ATTR_NDEV_INDEX, netdev->ifindex);387 if (ret)388 goto out;389 ret = nla_put_string(msg,390 RDMA_NLDEV_ATTR_NDEV_NAME, netdev->name);391 }392 393out:394 dev_put(netdev);395 return ret;396}397 398static int fill_res_info_entry(struct sk_buff *msg,399 const char *name, u64 curr)400{401 struct nlattr *entry_attr;402 403 entry_attr = nla_nest_start_noflag(msg,404 RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY);405 if (!entry_attr)406 return -EMSGSIZE;407 408 if (nla_put_string(msg, RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_NAME, name))409 goto err;410 if (nla_put_u64_64bit(msg, RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_CURR, curr,411 RDMA_NLDEV_ATTR_PAD))412 goto err;413 414 nla_nest_end(msg, entry_attr);415 return 0;416 417err:418 nla_nest_cancel(msg, entry_attr);419 return -EMSGSIZE;420}421 422static int fill_res_info(struct sk_buff *msg, struct ib_device *device,423 bool show_details)424{425 static const char * const names[RDMA_RESTRACK_MAX] = {426 [RDMA_RESTRACK_PD] = "pd",427 [RDMA_RESTRACK_CQ] = "cq",428 [RDMA_RESTRACK_QP] = "qp",429 [RDMA_RESTRACK_CM_ID] = "cm_id",430 [RDMA_RESTRACK_MR] = "mr",431 [RDMA_RESTRACK_CTX] = "ctx",432 [RDMA_RESTRACK_SRQ] = "srq",433 };434 435 struct nlattr *table_attr;436 int ret, i, curr;437 438 if (fill_nldev_handle(msg, device))439 return -EMSGSIZE;440 441 table_attr = nla_nest_start_noflag(msg, RDMA_NLDEV_ATTR_RES_SUMMARY);442 if (!table_attr)443 return -EMSGSIZE;444 445 for (i = 0; i < RDMA_RESTRACK_MAX; i++) {446 if (!names[i])447 continue;448 curr = rdma_restrack_count(device, i, show_details);449 ret = fill_res_info_entry(msg, names[i], curr);450 if (ret)451 goto err;452 }453 454 nla_nest_end(msg, table_attr);455 return 0;456 457err:458 nla_nest_cancel(msg, table_attr);459 return ret;460}461 462static int fill_res_name_pid(struct sk_buff *msg,463 struct rdma_restrack_entry *res)464{465 int err = 0;466 467 /*468 * For user resources, user is should read /proc/PID/comm to get the469 * name of the task file.470 */471 if (rdma_is_kernel_res(res)) {472 err = nla_put_string(msg, RDMA_NLDEV_ATTR_RES_KERN_NAME,473 res->kern_name);474 } else {475 pid_t pid;476 477 pid = task_pid_vnr(res->task);478 /*479 * Task is dead and in zombie state.480 * There is no need to print PID anymore.481 */482 if (pid)483 /*484 * This part is racy, task can be killed and PID will485 * be zero right here but it is ok, next query won't486 * return PID. We don't promise real-time reflection487 * of SW objects.488 */489 err = nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_PID, pid);490 }491 492 return err ? -EMSGSIZE : 0;493}494 495static int fill_res_qp_entry_query(struct sk_buff *msg,496 struct rdma_restrack_entry *res,497 struct ib_device *dev,498 struct ib_qp *qp)499{500 struct ib_qp_init_attr qp_init_attr;501 struct ib_qp_attr qp_attr;502 int ret;503 504 ret = ib_query_qp(qp, &qp_attr, 0, &qp_init_attr);505 if (ret)506 return ret;507 508 if (qp->qp_type == IB_QPT_RC || qp->qp_type == IB_QPT_UC) {509 if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_RQPN,510 qp_attr.dest_qp_num))511 goto err;512 if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_RQ_PSN,513 qp_attr.rq_psn))514 goto err;515 }516 517 if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_SQ_PSN, qp_attr.sq_psn))518 goto err;519 520 if (qp->qp_type == IB_QPT_RC || qp->qp_type == IB_QPT_UC ||521 qp->qp_type == IB_QPT_XRC_INI || qp->qp_type == IB_QPT_XRC_TGT) {522 if (nla_put_u8(msg, RDMA_NLDEV_ATTR_RES_PATH_MIG_STATE,523 qp_attr.path_mig_state))524 goto err;525 }526 if (nla_put_u8(msg, RDMA_NLDEV_ATTR_RES_TYPE, qp->qp_type))527 goto err;528 if (nla_put_u8(msg, RDMA_NLDEV_ATTR_RES_STATE, qp_attr.qp_state))529 goto err;530 531 if (dev->ops.fill_res_qp_entry)532 return dev->ops.fill_res_qp_entry(msg, qp);533 return 0;534 535err: return -EMSGSIZE;536}537 538static int fill_res_qp_entry(struct sk_buff *msg, bool has_cap_net_admin,539 struct rdma_restrack_entry *res, uint32_t port)540{541 struct ib_qp *qp = container_of(res, struct ib_qp, res);542 struct ib_device *dev = qp->device;543 int ret;544 545 if (port && port != qp->port)546 return -EAGAIN;547 548 /* In create_qp() port is not set yet */549 if (qp->port && nla_put_u32(msg, RDMA_NLDEV_ATTR_PORT_INDEX, qp->port))550 return -EMSGSIZE;551 552 ret = nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_LQPN, qp->qp_num);553 if (ret)554 return -EMSGSIZE;555 556 if (!rdma_is_kernel_res(res) &&557 nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_PDN, qp->pd->res.id))558 return -EMSGSIZE;559 560 ret = fill_res_name_pid(msg, res);561 if (ret)562 return -EMSGSIZE;563 564 return fill_res_qp_entry_query(msg, res, dev, qp);565}566 567static int fill_res_qp_raw_entry(struct sk_buff *msg, bool has_cap_net_admin,568 struct rdma_restrack_entry *res, uint32_t port)569{570 struct ib_qp *qp = container_of(res, struct ib_qp, res);571 struct ib_device *dev = qp->device;572 573 if (port && port != qp->port)574 return -EAGAIN;575 if (!dev->ops.fill_res_qp_entry_raw)576 return -EINVAL;577 return dev->ops.fill_res_qp_entry_raw(msg, qp);578}579 580static int fill_res_cm_id_entry(struct sk_buff *msg, bool has_cap_net_admin,581 struct rdma_restrack_entry *res, uint32_t port)582{583 struct rdma_id_private *id_priv =584 container_of(res, struct rdma_id_private, res);585 struct ib_device *dev = id_priv->id.device;586 struct rdma_cm_id *cm_id = &id_priv->id;587 588 if (port && port != cm_id->port_num)589 return -EAGAIN;590 591 if (cm_id->port_num &&592 nla_put_u32(msg, RDMA_NLDEV_ATTR_PORT_INDEX, cm_id->port_num))593 goto err;594 595 if (id_priv->qp_num) {596 if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_LQPN, id_priv->qp_num))597 goto err;598 if (nla_put_u8(msg, RDMA_NLDEV_ATTR_RES_TYPE, cm_id->qp_type))599 goto err;600 }601 602 if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_PS, cm_id->ps))603 goto err;604 605 if (nla_put_u8(msg, RDMA_NLDEV_ATTR_RES_STATE, id_priv->state))606 goto err;607 608 if (cm_id->route.addr.src_addr.ss_family &&609 nla_put(msg, RDMA_NLDEV_ATTR_RES_SRC_ADDR,610 sizeof(cm_id->route.addr.src_addr),611 &cm_id->route.addr.src_addr))612 goto err;613 if (cm_id->route.addr.dst_addr.ss_family &&614 nla_put(msg, RDMA_NLDEV_ATTR_RES_DST_ADDR,615 sizeof(cm_id->route.addr.dst_addr),616 &cm_id->route.addr.dst_addr))617 goto err;618 619 if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_CM_IDN, res->id))620 goto err;621 622 if (fill_res_name_pid(msg, res))623 goto err;624 625 if (dev->ops.fill_res_cm_id_entry)626 return dev->ops.fill_res_cm_id_entry(msg, cm_id);627 return 0;628 629err: return -EMSGSIZE;630}631 632static int fill_res_cq_entry(struct sk_buff *msg, bool has_cap_net_admin,633 struct rdma_restrack_entry *res, uint32_t port)634{635 struct ib_cq *cq = container_of(res, struct ib_cq, res);636 struct ib_device *dev = cq->device;637 638 if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_CQE, cq->cqe))639 return -EMSGSIZE;640 if (nla_put_u64_64bit(msg, RDMA_NLDEV_ATTR_RES_USECNT,641 atomic_read(&cq->usecnt), RDMA_NLDEV_ATTR_PAD))642 return -EMSGSIZE;643 644 /* Poll context is only valid for kernel CQs */645 if (rdma_is_kernel_res(res) &&646 nla_put_u8(msg, RDMA_NLDEV_ATTR_RES_POLL_CTX, cq->poll_ctx))647 return -EMSGSIZE;648 649 if (nla_put_u8(msg, RDMA_NLDEV_ATTR_DEV_DIM, (cq->dim != NULL)))650 return -EMSGSIZE;651 652 if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_CQN, res->id))653 return -EMSGSIZE;654 if (!rdma_is_kernel_res(res) &&655 nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_CTXN,656 cq->uobject->uevent.uobject.context->res.id))657 return -EMSGSIZE;658 659 if (fill_res_name_pid(msg, res))660 return -EMSGSIZE;661 662 return (dev->ops.fill_res_cq_entry) ?663 dev->ops.fill_res_cq_entry(msg, cq) : 0;664}665 666static int fill_res_cq_raw_entry(struct sk_buff *msg, bool has_cap_net_admin,667 struct rdma_restrack_entry *res, uint32_t port)668{669 struct ib_cq *cq = container_of(res, struct ib_cq, res);670 struct ib_device *dev = cq->device;671 672 if (!dev->ops.fill_res_cq_entry_raw)673 return -EINVAL;674 return dev->ops.fill_res_cq_entry_raw(msg, cq);675}676 677static int fill_res_mr_entry(struct sk_buff *msg, bool has_cap_net_admin,678 struct rdma_restrack_entry *res, uint32_t port)679{680 struct ib_mr *mr = container_of(res, struct ib_mr, res);681 struct ib_device *dev = mr->pd->device;682 683 if (has_cap_net_admin) {684 if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_RKEY, mr->rkey))685 return -EMSGSIZE;686 if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_LKEY, mr->lkey))687 return -EMSGSIZE;688 }689 690 if (nla_put_u64_64bit(msg, RDMA_NLDEV_ATTR_RES_MRLEN, mr->length,691 RDMA_NLDEV_ATTR_PAD))692 return -EMSGSIZE;693 694 if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_MRN, res->id))695 return -EMSGSIZE;696 697 if (!rdma_is_kernel_res(res) &&698 nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_PDN, mr->pd->res.id))699 return -EMSGSIZE;700 701 if (fill_res_name_pid(msg, res))702 return -EMSGSIZE;703 704 return (dev->ops.fill_res_mr_entry) ?705 dev->ops.fill_res_mr_entry(msg, mr) :706 0;707}708 709static int fill_res_mr_raw_entry(struct sk_buff *msg, bool has_cap_net_admin,710 struct rdma_restrack_entry *res, uint32_t port)711{712 struct ib_mr *mr = container_of(res, struct ib_mr, res);713 struct ib_device *dev = mr->pd->device;714 715 if (!dev->ops.fill_res_mr_entry_raw)716 return -EINVAL;717 return dev->ops.fill_res_mr_entry_raw(msg, mr);718}719 720static int fill_res_pd_entry(struct sk_buff *msg, bool has_cap_net_admin,721 struct rdma_restrack_entry *res, uint32_t port)722{723 struct ib_pd *pd = container_of(res, struct ib_pd, res);724 725 if (has_cap_net_admin) {726 if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_LOCAL_DMA_LKEY,727 pd->local_dma_lkey))728 goto err;729 if ((pd->flags & IB_PD_UNSAFE_GLOBAL_RKEY) &&730 nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_UNSAFE_GLOBAL_RKEY,731 pd->unsafe_global_rkey))732 goto err;733 }734 if (nla_put_u64_64bit(msg, RDMA_NLDEV_ATTR_RES_USECNT,735 atomic_read(&pd->usecnt), RDMA_NLDEV_ATTR_PAD))736 goto err;737 738 if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_PDN, res->id))739 goto err;740 741 if (!rdma_is_kernel_res(res) &&742 nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_CTXN,743 pd->uobject->context->res.id))744 goto err;745 746 return fill_res_name_pid(msg, res);747 748err: return -EMSGSIZE;749}750 751static int fill_res_ctx_entry(struct sk_buff *msg, bool has_cap_net_admin,752 struct rdma_restrack_entry *res, uint32_t port)753{754 struct ib_ucontext *ctx = container_of(res, struct ib_ucontext, res);755 756 if (rdma_is_kernel_res(res))757 return 0;758 759 if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_CTXN, ctx->res.id))760 return -EMSGSIZE;761 762 return fill_res_name_pid(msg, res);763}764 765static int fill_res_range_qp_entry(struct sk_buff *msg, uint32_t min_range,766 uint32_t max_range)767{768 struct nlattr *entry_attr;769 770 if (!min_range)771 return 0;772 773 entry_attr = nla_nest_start(msg, RDMA_NLDEV_ATTR_RES_QP_ENTRY);774 if (!entry_attr)775 return -EMSGSIZE;776 777 if (min_range == max_range) {778 if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_LQPN, min_range))779 goto err;780 } else {781 if (nla_put_u32(msg, RDMA_NLDEV_ATTR_MIN_RANGE, min_range))782 goto err;783 if (nla_put_u32(msg, RDMA_NLDEV_ATTR_MAX_RANGE, max_range))784 goto err;785 }786 nla_nest_end(msg, entry_attr);787 return 0;788 789err:790 nla_nest_cancel(msg, entry_attr);791 return -EMSGSIZE;792}793 794static int fill_res_srq_qps(struct sk_buff *msg, struct ib_srq *srq)795{796 uint32_t min_range = 0, prev = 0;797 struct rdma_restrack_entry *res;798 struct rdma_restrack_root *rt;799 struct nlattr *table_attr;800 struct ib_qp *qp = NULL;801 unsigned long id = 0;802 803 table_attr = nla_nest_start(msg, RDMA_NLDEV_ATTR_RES_QP);804 if (!table_attr)805 return -EMSGSIZE;806 807 rt = &srq->device->res[RDMA_RESTRACK_QP];808 xa_lock(&rt->xa);809 xa_for_each(&rt->xa, id, res) {810 if (!rdma_restrack_get(res))811 continue;812 813 qp = container_of(res, struct ib_qp, res);814 if (!qp->srq || (qp->srq->res.id != srq->res.id)) {815 rdma_restrack_put(res);816 continue;817 }818 819 if (qp->qp_num < prev)820 /* qp_num should be ascending */821 goto err_loop;822 823 if (min_range == 0) {824 min_range = qp->qp_num;825 } else if (qp->qp_num > (prev + 1)) {826 if (fill_res_range_qp_entry(msg, min_range, prev))827 goto err_loop;828 829 min_range = qp->qp_num;830 }831 prev = qp->qp_num;832 rdma_restrack_put(res);833 }834 835 xa_unlock(&rt->xa);836 837 if (fill_res_range_qp_entry(msg, min_range, prev))838 goto err;839 840 nla_nest_end(msg, table_attr);841 return 0;842 843err_loop:844 rdma_restrack_put(res);845 xa_unlock(&rt->xa);846err:847 nla_nest_cancel(msg, table_attr);848 return -EMSGSIZE;849}850 851static int fill_res_srq_entry(struct sk_buff *msg, bool has_cap_net_admin,852 struct rdma_restrack_entry *res, uint32_t port)853{854 struct ib_srq *srq = container_of(res, struct ib_srq, res);855 struct ib_device *dev = srq->device;856 857 if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_SRQN, srq->res.id))858 goto err;859 860 if (nla_put_u8(msg, RDMA_NLDEV_ATTR_RES_TYPE, srq->srq_type))861 goto err;862 863 if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_PDN, srq->pd->res.id))864 goto err;865 866 if (ib_srq_has_cq(srq->srq_type)) {867 if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_CQN,868 srq->ext.cq->res.id))869 goto err;870 }871 872 if (fill_res_srq_qps(msg, srq))873 goto err;874 875 if (fill_res_name_pid(msg, res))876 goto err;877 878 if (dev->ops.fill_res_srq_entry)879 return dev->ops.fill_res_srq_entry(msg, srq);880 881 return 0;882 883err:884 return -EMSGSIZE;885}886 887static int fill_res_srq_raw_entry(struct sk_buff *msg, bool has_cap_net_admin,888 struct rdma_restrack_entry *res, uint32_t port)889{890 struct ib_srq *srq = container_of(res, struct ib_srq, res);891 struct ib_device *dev = srq->device;892 893 if (!dev->ops.fill_res_srq_entry_raw)894 return -EINVAL;895 return dev->ops.fill_res_srq_entry_raw(msg, srq);896}897 898static int fill_stat_counter_mode(struct sk_buff *msg,899 struct rdma_counter *counter)900{901 struct rdma_counter_mode *m = &counter->mode;902 903 if (nla_put_u32(msg, RDMA_NLDEV_ATTR_STAT_MODE, m->mode))904 return -EMSGSIZE;905 906 if (m->mode == RDMA_COUNTER_MODE_AUTO) {907 if ((m->mask & RDMA_COUNTER_MASK_QP_TYPE) &&908 nla_put_u8(msg, RDMA_NLDEV_ATTR_RES_TYPE, m->param.qp_type))909 return -EMSGSIZE;910 911 if ((m->mask & RDMA_COUNTER_MASK_PID) &&912 fill_res_name_pid(msg, &counter->res))913 return -EMSGSIZE;914 }915 916 return 0;917}918 919static int fill_stat_counter_qp_entry(struct sk_buff *msg, u32 qpn)920{921 struct nlattr *entry_attr;922 923 entry_attr = nla_nest_start(msg, RDMA_NLDEV_ATTR_RES_QP_ENTRY);924 if (!entry_attr)925 return -EMSGSIZE;926 927 if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_LQPN, qpn))928 goto err;929 930 nla_nest_end(msg, entry_attr);931 return 0;932 933err:934 nla_nest_cancel(msg, entry_attr);935 return -EMSGSIZE;936}937 938static int fill_stat_counter_qps(struct sk_buff *msg,939 struct rdma_counter *counter)940{941 struct rdma_restrack_entry *res;942 struct rdma_restrack_root *rt;943 struct nlattr *table_attr;944 struct ib_qp *qp = NULL;945 unsigned long id = 0;946 int ret = 0;947 948 table_attr = nla_nest_start(msg, RDMA_NLDEV_ATTR_RES_QP);949 if (!table_attr)950 return -EMSGSIZE;951 952 rt = &counter->device->res[RDMA_RESTRACK_QP];953 xa_lock(&rt->xa);954 xa_for_each(&rt->xa, id, res) {955 qp = container_of(res, struct ib_qp, res);956 if (!qp->counter || (qp->counter->id != counter->id))957 continue;958 959 ret = fill_stat_counter_qp_entry(msg, qp->qp_num);960 if (ret)961 goto err;962 }963 964 xa_unlock(&rt->xa);965 nla_nest_end(msg, table_attr);966 return 0;967 968err:969 xa_unlock(&rt->xa);970 nla_nest_cancel(msg, table_attr);971 return ret;972}973 974int rdma_nl_stat_hwcounter_entry(struct sk_buff *msg, const char *name,975 u64 value)976{977 struct nlattr *entry_attr;978 979 entry_attr = nla_nest_start(msg, RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY);980 if (!entry_attr)981 return -EMSGSIZE;982 983 if (nla_put_string(msg, RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_NAME,984 name))985 goto err;986 if (nla_put_u64_64bit(msg, RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_VALUE,987 value, RDMA_NLDEV_ATTR_PAD))988 goto err;989 990 nla_nest_end(msg, entry_attr);991 return 0;992 993err:994 nla_nest_cancel(msg, entry_attr);995 return -EMSGSIZE;996}997EXPORT_SYMBOL(rdma_nl_stat_hwcounter_entry);998 999static int fill_stat_mr_entry(struct sk_buff *msg, bool has_cap_net_admin,1000 struct rdma_restrack_entry *res, uint32_t port)1001{1002 struct ib_mr *mr = container_of(res, struct ib_mr, res);1003 struct ib_device *dev = mr->pd->device;1004 1005 if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_MRN, res->id))1006 goto err;1007 1008 if (dev->ops.fill_stat_mr_entry)1009 return dev->ops.fill_stat_mr_entry(msg, mr);1010 return 0;1011 1012err:1013 return -EMSGSIZE;1014}1015 1016static int fill_stat_counter_hwcounters(struct sk_buff *msg,1017 struct rdma_counter *counter)1018{1019 struct rdma_hw_stats *st = counter->stats;1020 struct nlattr *table_attr;1021 int i;1022 1023 table_attr = nla_nest_start(msg, RDMA_NLDEV_ATTR_STAT_HWCOUNTERS);1024 if (!table_attr)1025 return -EMSGSIZE;1026 1027 mutex_lock(&st->lock);1028 for (i = 0; i < st->num_counters; i++) {1029 if (test_bit(i, st->is_disabled))1030 continue;1031 if (rdma_nl_stat_hwcounter_entry(msg, st->descs[i].name,1032 st->value[i]))1033 goto err;1034 }1035 mutex_unlock(&st->lock);1036 1037 nla_nest_end(msg, table_attr);1038 return 0;1039 1040err:1041 mutex_unlock(&st->lock);1042 nla_nest_cancel(msg, table_attr);1043 return -EMSGSIZE;1044}1045 1046static int fill_res_counter_entry(struct sk_buff *msg, bool has_cap_net_admin,1047 struct rdma_restrack_entry *res,1048 uint32_t port)1049{1050 struct rdma_counter *counter =1051 container_of(res, struct rdma_counter, res);1052 1053 if (port && port != counter->port)1054 return -EAGAIN;1055 1056 /* Dump it even query failed */1057 rdma_counter_query_stats(counter);1058 1059 if (nla_put_u32(msg, RDMA_NLDEV_ATTR_PORT_INDEX, counter->port) ||1060 nla_put_u32(msg, RDMA_NLDEV_ATTR_STAT_COUNTER_ID, counter->id) ||1061 fill_stat_counter_mode(msg, counter) ||1062 fill_stat_counter_qps(msg, counter) ||1063 fill_stat_counter_hwcounters(msg, counter))1064 return -EMSGSIZE;1065 1066 return 0;1067}1068 1069static int nldev_get_doit(struct sk_buff *skb, struct nlmsghdr *nlh,1070 struct netlink_ext_ack *extack)1071{1072 struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];1073 struct ib_device *device;1074 struct sk_buff *msg;1075 u32 index;1076 int err;1077 1078 err = __nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,1079 nldev_policy, NL_VALIDATE_LIBERAL, extack);1080 if (err || !tb[RDMA_NLDEV_ATTR_DEV_INDEX])1081 return -EINVAL;1082 1083 index = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);1084 1085 device = ib_device_get_by_index(sock_net(skb->sk), index);1086 if (!device)1087 return -EINVAL;1088 1089 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);1090 if (!msg) {1091 err = -ENOMEM;1092 goto err;1093 }1094 1095 nlh = nlmsg_put(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq,1096 RDMA_NL_GET_TYPE(RDMA_NL_NLDEV, RDMA_NLDEV_CMD_GET),1097 0, 0);1098 if (!nlh) {1099 err = -EMSGSIZE;1100 goto err_free;1101 }1102 1103 err = fill_dev_info(msg, device);1104 if (err)1105 goto err_free;1106 1107 nlmsg_end(msg, nlh);1108 1109 ib_device_put(device);1110 return rdma_nl_unicast(sock_net(skb->sk), msg, NETLINK_CB(skb).portid);1111 1112err_free:1113 nlmsg_free(msg);1114err:1115 ib_device_put(device);1116 return err;1117}1118 1119static int nldev_set_doit(struct sk_buff *skb, struct nlmsghdr *nlh,1120 struct netlink_ext_ack *extack)1121{1122 struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];1123 struct ib_device *device;1124 u32 index;1125 int err;1126 1127 err = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,1128 nldev_policy, extack);1129 if (err || !tb[RDMA_NLDEV_ATTR_DEV_INDEX])1130 return -EINVAL;1131 1132 index = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);1133 device = ib_device_get_by_index(sock_net(skb->sk), index);1134 if (!device)1135 return -EINVAL;1136 1137 if (tb[RDMA_NLDEV_ATTR_DEV_NAME]) {1138 char name[IB_DEVICE_NAME_MAX] = {};1139 1140 nla_strscpy(name, tb[RDMA_NLDEV_ATTR_DEV_NAME],1141 IB_DEVICE_NAME_MAX);1142 if (strlen(name) == 0) {1143 err = -EINVAL;1144 goto done;1145 }1146 err = ib_device_rename(device, name);1147 goto done;1148 }1149 1150 if (tb[RDMA_NLDEV_NET_NS_FD]) {1151 u32 ns_fd;1152 1153 ns_fd = nla_get_u32(tb[RDMA_NLDEV_NET_NS_FD]);1154 err = ib_device_set_netns_put(skb, device, ns_fd);1155 goto put_done;1156 }1157 1158 if (tb[RDMA_NLDEV_ATTR_DEV_DIM]) {1159 u8 use_dim;1160 1161 use_dim = nla_get_u8(tb[RDMA_NLDEV_ATTR_DEV_DIM]);1162 err = ib_device_set_dim(device, use_dim);1163 goto done;1164 }1165 1166done:1167 ib_device_put(device);1168put_done:1169 return err;1170}1171 1172static int _nldev_get_dumpit(struct ib_device *device,1173 struct sk_buff *skb,1174 struct netlink_callback *cb,1175 unsigned int idx)1176{1177 int start = cb->args[0];1178 struct nlmsghdr *nlh;1179 1180 if (idx < start)1181 return 0;1182 1183 nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,1184 RDMA_NL_GET_TYPE(RDMA_NL_NLDEV, RDMA_NLDEV_CMD_GET),1185 0, NLM_F_MULTI);1186 1187 if (!nlh || fill_dev_info(skb, device)) {1188 nlmsg_cancel(skb, nlh);1189 goto out;1190 }1191 1192 nlmsg_end(skb, nlh);1193 1194 idx++;1195 1196out: cb->args[0] = idx;1197 return skb->len;1198}1199 1200static int nldev_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)1201{1202 /*1203 * There is no need to take lock, because1204 * we are relying on ib_core's locking.1205 */1206 return ib_enum_all_devs(_nldev_get_dumpit, skb, cb);1207}1208 1209static int nldev_port_get_doit(struct sk_buff *skb, struct nlmsghdr *nlh,1210 struct netlink_ext_ack *extack)1211{1212 struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];1213 struct ib_device *device;1214 struct sk_buff *msg;1215 u32 index;1216 u32 port;1217 int err;1218 1219 err = __nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,1220 nldev_policy, NL_VALIDATE_LIBERAL, extack);1221 if (err ||1222 !tb[RDMA_NLDEV_ATTR_DEV_INDEX] ||1223 !tb[RDMA_NLDEV_ATTR_PORT_INDEX])1224 return -EINVAL;1225 1226 index = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);1227 device = ib_device_get_by_index(sock_net(skb->sk), index);1228 if (!device)1229 return -EINVAL;1230 1231 port = nla_get_u32(tb[RDMA_NLDEV_ATTR_PORT_INDEX]);1232 if (!rdma_is_port_valid(device, port)) {1233 err = -EINVAL;1234 goto err;1235 }1236 1237 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);1238 if (!msg) {1239 err = -ENOMEM;1240 goto err;1241 }1242 1243 nlh = nlmsg_put(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq,1244 RDMA_NL_GET_TYPE(RDMA_NL_NLDEV, RDMA_NLDEV_CMD_GET),1245 0, 0);1246 if (!nlh) {1247 err = -EMSGSIZE;1248 goto err_free;1249 }1250 1251 err = fill_port_info(msg, device, port, sock_net(skb->sk));1252 if (err)1253 goto err_free;1254 1255 nlmsg_end(msg, nlh);1256 ib_device_put(device);1257 1258 return rdma_nl_unicast(sock_net(skb->sk), msg, NETLINK_CB(skb).portid);1259 1260err_free:1261 nlmsg_free(msg);1262err:1263 ib_device_put(device);1264 return err;1265}1266 1267static int nldev_port_get_dumpit(struct sk_buff *skb,1268 struct netlink_callback *cb)1269{1270 struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];1271 struct ib_device *device;1272 int start = cb->args[0];1273 struct nlmsghdr *nlh;1274 u32 idx = 0;1275 u32 ifindex;1276 int err;1277 unsigned int p;1278 1279 err = __nlmsg_parse(cb->nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,1280 nldev_policy, NL_VALIDATE_LIBERAL, NULL);1281 if (err || !tb[RDMA_NLDEV_ATTR_DEV_INDEX])1282 return -EINVAL;1283 1284 ifindex = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);1285 device = ib_device_get_by_index(sock_net(skb->sk), ifindex);1286 if (!device)1287 return -EINVAL;1288 1289 rdma_for_each_port (device, p) {1290 /*1291 * The dumpit function returns all information from specific1292 * index. This specific index is taken from the netlink1293 * messages request sent by user and it is available1294 * in cb->args[0].1295 *1296 * Usually, the user doesn't fill this field and it causes1297 * to return everything.1298 *1299 */1300 if (idx < start) {1301 idx++;1302 continue;1303 }1304 1305 nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid,1306 cb->nlh->nlmsg_seq,1307 RDMA_NL_GET_TYPE(RDMA_NL_NLDEV,1308 RDMA_NLDEV_CMD_PORT_GET),1309 0, NLM_F_MULTI);1310 1311 if (!nlh || fill_port_info(skb, device, p, sock_net(skb->sk))) {1312 nlmsg_cancel(skb, nlh);1313 goto out;1314 }1315 idx++;1316 nlmsg_end(skb, nlh);1317 }1318 1319out:1320 ib_device_put(device);1321 cb->args[0] = idx;1322 return skb->len;1323}1324 1325static int nldev_res_get_doit(struct sk_buff *skb, struct nlmsghdr *nlh,1326 struct netlink_ext_ack *extack)1327{1328 struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];1329 bool show_details = false;1330 struct ib_device *device;1331 struct sk_buff *msg;1332 u32 index;1333 int ret;1334 1335 ret = __nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,1336 nldev_policy, NL_VALIDATE_LIBERAL, extack);1337 if (ret || !tb[RDMA_NLDEV_ATTR_DEV_INDEX])1338 return -EINVAL;1339 1340 index = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);1341 device = ib_device_get_by_index(sock_net(skb->sk), index);1342 if (!device)1343 return -EINVAL;1344 1345 if (tb[RDMA_NLDEV_ATTR_DRIVER_DETAILS])1346 show_details = nla_get_u8(tb[RDMA_NLDEV_ATTR_DRIVER_DETAILS]);1347 1348 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);1349 if (!msg) {1350 ret = -ENOMEM;1351 goto err;1352 }1353 1354 nlh = nlmsg_put(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq,1355 RDMA_NL_GET_TYPE(RDMA_NL_NLDEV, RDMA_NLDEV_CMD_RES_GET),1356 0, 0);1357 if (!nlh) {1358 ret = -EMSGSIZE;1359 goto err_free;1360 }1361 1362 ret = fill_res_info(msg, device, show_details);1363 if (ret)1364 goto err_free;1365 1366 nlmsg_end(msg, nlh);1367 ib_device_put(device);1368 return rdma_nl_unicast(sock_net(skb->sk), msg, NETLINK_CB(skb).portid);1369 1370err_free:1371 nlmsg_free(msg);1372err:1373 ib_device_put(device);1374 return ret;1375}1376 1377static int _nldev_res_get_dumpit(struct ib_device *device,1378 struct sk_buff *skb,1379 struct netlink_callback *cb,1380 unsigned int idx)1381{1382 int start = cb->args[0];1383 struct nlmsghdr *nlh;1384 1385 if (idx < start)1386 return 0;1387 1388 nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,1389 RDMA_NL_GET_TYPE(RDMA_NL_NLDEV, RDMA_NLDEV_CMD_RES_GET),1390 0, NLM_F_MULTI);1391 1392 if (!nlh || fill_res_info(skb, device, false)) {1393 nlmsg_cancel(skb, nlh);1394 goto out;1395 }1396 nlmsg_end(skb, nlh);1397 1398 idx++;1399 1400out:1401 cb->args[0] = idx;1402 return skb->len;1403}1404 1405static int nldev_res_get_dumpit(struct sk_buff *skb,1406 struct netlink_callback *cb)1407{1408 return ib_enum_all_devs(_nldev_res_get_dumpit, skb, cb);1409}1410 1411struct nldev_fill_res_entry {1412 enum rdma_nldev_attr nldev_attr;1413 u8 flags;1414 u32 entry;1415 u32 id;1416};1417 1418enum nldev_res_flags {1419 NLDEV_PER_DEV = 1 << 0,1420};1421 1422static const struct nldev_fill_res_entry fill_entries[RDMA_RESTRACK_MAX] = {1423 [RDMA_RESTRACK_QP] = {1424 .nldev_attr = RDMA_NLDEV_ATTR_RES_QP,1425 .entry = RDMA_NLDEV_ATTR_RES_QP_ENTRY,1426 .id = RDMA_NLDEV_ATTR_RES_LQPN,1427 },1428 [RDMA_RESTRACK_CM_ID] = {1429 .nldev_attr = RDMA_NLDEV_ATTR_RES_CM_ID,1430 .entry = RDMA_NLDEV_ATTR_RES_CM_ID_ENTRY,1431 .id = RDMA_NLDEV_ATTR_RES_CM_IDN,1432 },1433 [RDMA_RESTRACK_CQ] = {1434 .nldev_attr = RDMA_NLDEV_ATTR_RES_CQ,1435 .flags = NLDEV_PER_DEV,1436 .entry = RDMA_NLDEV_ATTR_RES_CQ_ENTRY,1437 .id = RDMA_NLDEV_ATTR_RES_CQN,1438 },1439 [RDMA_RESTRACK_MR] = {1440 .nldev_attr = RDMA_NLDEV_ATTR_RES_MR,1441 .flags = NLDEV_PER_DEV,1442 .entry = RDMA_NLDEV_ATTR_RES_MR_ENTRY,1443 .id = RDMA_NLDEV_ATTR_RES_MRN,1444 },1445 [RDMA_RESTRACK_PD] = {1446 .nldev_attr = RDMA_NLDEV_ATTR_RES_PD,1447 .flags = NLDEV_PER_DEV,1448 .entry = RDMA_NLDEV_ATTR_RES_PD_ENTRY,1449 .id = RDMA_NLDEV_ATTR_RES_PDN,1450 },1451 [RDMA_RESTRACK_COUNTER] = {1452 .nldev_attr = RDMA_NLDEV_ATTR_STAT_COUNTER,1453 .entry = RDMA_NLDEV_ATTR_STAT_COUNTER_ENTRY,1454 .id = RDMA_NLDEV_ATTR_STAT_COUNTER_ID,1455 },1456 [RDMA_RESTRACK_CTX] = {1457 .nldev_attr = RDMA_NLDEV_ATTR_RES_CTX,1458 .flags = NLDEV_PER_DEV,1459 .entry = RDMA_NLDEV_ATTR_RES_CTX_ENTRY,1460 .id = RDMA_NLDEV_ATTR_RES_CTXN,1461 },1462 [RDMA_RESTRACK_SRQ] = {1463 .nldev_attr = RDMA_NLDEV_ATTR_RES_SRQ,1464 .flags = NLDEV_PER_DEV,1465 .entry = RDMA_NLDEV_ATTR_RES_SRQ_ENTRY,1466 .id = RDMA_NLDEV_ATTR_RES_SRQN,1467 },1468 1469};1470 1471static int res_get_common_doit(struct sk_buff *skb, struct nlmsghdr *nlh,1472 struct netlink_ext_ack *extack,1473 enum rdma_restrack_type res_type,1474 res_fill_func_t fill_func)1475{1476 const struct nldev_fill_res_entry *fe = &fill_entries[res_type];1477 struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];1478 struct rdma_restrack_entry *res;1479 struct ib_device *device;1480 u32 index, id, port = 0;1481 bool has_cap_net_admin;1482 struct sk_buff *msg;1483 int ret;1484 1485 ret = __nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,1486 nldev_policy, NL_VALIDATE_LIBERAL, extack);1487 if (ret || !tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !fe->id || !tb[fe->id])1488 return -EINVAL;1489 1490 index = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);1491 device = ib_device_get_by_index(sock_net(skb->sk), index);1492 if (!device)1493 return -EINVAL;1494 1495 if (tb[RDMA_NLDEV_ATTR_PORT_INDEX]) {1496 port = nla_get_u32(tb[RDMA_NLDEV_ATTR_PORT_INDEX]);1497 if (!rdma_is_port_valid(device, port)) {1498 ret = -EINVAL;1499 goto err;1500 }1501 }1502 1503 if ((port && fe->flags & NLDEV_PER_DEV) ||1504 (!port && ~fe->flags & NLDEV_PER_DEV)) {1505 ret = -EINVAL;1506 goto err;1507 }1508 1509 id = nla_get_u32(tb[fe->id]);1510 res = rdma_restrack_get_byid(device, res_type, id);1511 if (IS_ERR(res)) {1512 ret = PTR_ERR(res);1513 goto err;1514 }1515 1516 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);1517 if (!msg) {1518 ret = -ENOMEM;1519 goto err_get;1520 }1521 1522 nlh = nlmsg_put(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq,1523 RDMA_NL_GET_TYPE(RDMA_NL_NLDEV,1524 RDMA_NL_GET_OP(nlh->nlmsg_type)),1525 0, 0);1526 1527 if (!nlh || fill_nldev_handle(msg, device)) {1528 ret = -EMSGSIZE;1529 goto err_free;1530 }1531 1532 has_cap_net_admin = netlink_capable(skb, CAP_NET_ADMIN);1533 1534 ret = fill_func(msg, has_cap_net_admin, res, port);1535 if (ret)1536 goto err_free;1537 1538 rdma_restrack_put(res);1539 nlmsg_end(msg, nlh);1540 ib_device_put(device);1541 return rdma_nl_unicast(sock_net(skb->sk), msg, NETLINK_CB(skb).portid);1542 1543err_free:1544 nlmsg_free(msg);1545err_get:1546 rdma_restrack_put(res);1547err:1548 ib_device_put(device);1549 return ret;1550}1551 1552static int res_get_common_dumpit(struct sk_buff *skb,1553 struct netlink_callback *cb,1554 enum rdma_restrack_type res_type,1555 res_fill_func_t fill_func)1556{1557 const struct nldev_fill_res_entry *fe = &fill_entries[res_type];1558 struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];1559 struct rdma_restrack_entry *res;1560 struct rdma_restrack_root *rt;1561 int err, ret = 0, idx = 0;1562 bool show_details = false;1563 struct nlattr *table_attr;1564 struct nlattr *entry_attr;1565 struct ib_device *device;1566 int start = cb->args[0];1567 bool has_cap_net_admin;1568 struct nlmsghdr *nlh;1569 unsigned long id;1570 u32 index, port = 0;1571 bool filled = false;1572 1573 err = __nlmsg_parse(cb->nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,1574 nldev_policy, NL_VALIDATE_LIBERAL, NULL);1575 /*1576 * Right now, we are expecting the device index to get res information,1577 * but it is possible to extend this code to return all devices in1578 * one shot by checking the existence of RDMA_NLDEV_ATTR_DEV_INDEX.1579 * if it doesn't exist, we will iterate over all devices.1580 *1581 * But it is not needed for now.1582 */1583 if (err || !tb[RDMA_NLDEV_ATTR_DEV_INDEX])1584 return -EINVAL;1585 1586 index = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);1587 device = ib_device_get_by_index(sock_net(skb->sk), index);1588 if (!device)1589 return -EINVAL;1590 1591 if (tb[RDMA_NLDEV_ATTR_DRIVER_DETAILS])1592 show_details = nla_get_u8(tb[RDMA_NLDEV_ATTR_DRIVER_DETAILS]);1593 1594 /*1595 * If no PORT_INDEX is supplied, we will return all QPs from that device1596 */1597 if (tb[RDMA_NLDEV_ATTR_PORT_INDEX]) {1598 port = nla_get_u32(tb[RDMA_NLDEV_ATTR_PORT_INDEX]);1599 if (!rdma_is_port_valid(device, port)) {1600 ret = -EINVAL;1601 goto err_index;1602 }1603 }1604 1605 nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,1606 RDMA_NL_GET_TYPE(RDMA_NL_NLDEV,1607 RDMA_NL_GET_OP(cb->nlh->nlmsg_type)),1608 0, NLM_F_MULTI);1609 1610 if (!nlh || fill_nldev_handle(skb, device)) {1611 ret = -EMSGSIZE;1612 goto err;1613 }1614 1615 table_attr = nla_nest_start_noflag(skb, fe->nldev_attr);1616 if (!table_attr) {1617 ret = -EMSGSIZE;1618 goto err;1619 }1620 1621 has_cap_net_admin = netlink_capable(cb->skb, CAP_NET_ADMIN);1622 1623 rt = &device->res[res_type];1624 xa_lock(&rt->xa);1625 /*1626 * FIXME: if the skip ahead is something common this loop should1627 * use xas_for_each & xas_pause to optimize, we can have a lot of1628 * objects.1629 */1630 xa_for_each(&rt->xa, id, res) {1631 if (xa_get_mark(&rt->xa, res->id, RESTRACK_DD) && !show_details)1632 goto next;1633 1634 if (idx < start || !rdma_restrack_get(res))1635 goto next;1636 1637 xa_unlock(&rt->xa);1638 1639 filled = true;1640 1641 entry_attr = nla_nest_start_noflag(skb, fe->entry);1642 if (!entry_attr) {1643 ret = -EMSGSIZE;1644 rdma_restrack_put(res);1645 goto msg_full;1646 }1647 1648 ret = fill_func(skb, has_cap_net_admin, res, port);1649 1650 rdma_restrack_put(res);1651 1652 if (ret) {1653 nla_nest_cancel(skb, entry_attr);1654 if (ret == -EMSGSIZE)1655 goto msg_full;1656 if (ret == -EAGAIN)1657 goto again;1658 goto res_err;1659 }1660 nla_nest_end(skb, entry_attr);1661again: xa_lock(&rt->xa);1662next: idx++;1663 }1664 xa_unlock(&rt->xa);1665 1666msg_full:1667 nla_nest_end(skb, table_attr);1668 nlmsg_end(skb, nlh);1669 cb->args[0] = idx;1670 1671 /*1672 * No more entries to fill, cancel the message and1673 * return 0 to mark end of dumpit.1674 */1675 if (!filled)1676 goto err;1677 1678 ib_device_put(device);1679 return skb->len;1680 1681res_err:1682 nla_nest_cancel(skb, table_attr);1683 1684err:1685 nlmsg_cancel(skb, nlh);1686 1687err_index:1688 ib_device_put(device);1689 return ret;1690}1691 1692#define RES_GET_FUNCS(name, type) \1693 static int nldev_res_get_##name##_dumpit(struct sk_buff *skb, \1694 struct netlink_callback *cb) \1695 { \1696 return res_get_common_dumpit(skb, cb, type, \1697 fill_res_##name##_entry); \1698 } \1699 static int nldev_res_get_##name##_doit(struct sk_buff *skb, \1700 struct nlmsghdr *nlh, \1701 struct netlink_ext_ack *extack) \1702 { \1703 return res_get_common_doit(skb, nlh, extack, type, \1704 fill_res_##name##_entry); \1705 }1706 1707RES_GET_FUNCS(qp, RDMA_RESTRACK_QP);1708RES_GET_FUNCS(qp_raw, RDMA_RESTRACK_QP);1709RES_GET_FUNCS(cm_id, RDMA_RESTRACK_CM_ID);1710RES_GET_FUNCS(cq, RDMA_RESTRACK_CQ);1711RES_GET_FUNCS(cq_raw, RDMA_RESTRACK_CQ);1712RES_GET_FUNCS(pd, RDMA_RESTRACK_PD);1713RES_GET_FUNCS(mr, RDMA_RESTRACK_MR);1714RES_GET_FUNCS(mr_raw, RDMA_RESTRACK_MR);1715RES_GET_FUNCS(counter, RDMA_RESTRACK_COUNTER);1716RES_GET_FUNCS(ctx, RDMA_RESTRACK_CTX);1717RES_GET_FUNCS(srq, RDMA_RESTRACK_SRQ);1718RES_GET_FUNCS(srq_raw, RDMA_RESTRACK_SRQ);1719 1720static LIST_HEAD(link_ops);1721static DECLARE_RWSEM(link_ops_rwsem);1722 1723static const struct rdma_link_ops *link_ops_get(const char *type)1724{1725 const struct rdma_link_ops *ops;1726 1727 list_for_each_entry(ops, &link_ops, list) {1728 if (!strcmp(ops->type, type))1729 goto out;1730 }1731 ops = NULL;1732out:1733 return ops;1734}1735 1736void rdma_link_register(struct rdma_link_ops *ops)1737{1738 down_write(&link_ops_rwsem);1739 if (WARN_ON_ONCE(link_ops_get(ops->type)))1740 goto out;1741 list_add(&ops->list, &link_ops);1742out:1743 up_write(&link_ops_rwsem);1744}1745EXPORT_SYMBOL(rdma_link_register);1746 1747void rdma_link_unregister(struct rdma_link_ops *ops)1748{1749 down_write(&link_ops_rwsem);1750 list_del(&ops->list);1751 up_write(&link_ops_rwsem);1752}1753EXPORT_SYMBOL(rdma_link_unregister);1754 1755static int nldev_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,1756 struct netlink_ext_ack *extack)1757{1758 struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];1759 char ibdev_name[IB_DEVICE_NAME_MAX];1760 const struct rdma_link_ops *ops;1761 char ndev_name[IFNAMSIZ];1762 struct net_device *ndev;1763 char type[IFNAMSIZ];1764 int err;1765 1766 err = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,1767 nldev_policy, extack);1768 if (err || !tb[RDMA_NLDEV_ATTR_DEV_NAME] ||1769 !tb[RDMA_NLDEV_ATTR_LINK_TYPE] || !tb[RDMA_NLDEV_ATTR_NDEV_NAME])1770 return -EINVAL;1771 1772 nla_strscpy(ibdev_name, tb[RDMA_NLDEV_ATTR_DEV_NAME],1773 sizeof(ibdev_name));1774 if (strchr(ibdev_name, '%') || strlen(ibdev_name) == 0)1775 return -EINVAL;1776 1777 nla_strscpy(type, tb[RDMA_NLDEV_ATTR_LINK_TYPE], sizeof(type));1778 nla_strscpy(ndev_name, tb[RDMA_NLDEV_ATTR_NDEV_NAME],1779 sizeof(ndev_name));1780 1781 ndev = dev_get_by_name(sock_net(skb->sk), ndev_name);1782 if (!ndev)1783 return -ENODEV;1784 1785 down_read(&link_ops_rwsem);1786 ops = link_ops_get(type);1787#ifdef CONFIG_MODULES1788 if (!ops) {1789 up_read(&link_ops_rwsem);1790 request_module("rdma-link-%s", type);1791 down_read(&link_ops_rwsem);1792 ops = link_ops_get(type);1793 }1794#endif1795 err = ops ? ops->newlink(ibdev_name, ndev) : -EINVAL;1796 up_read(&link_ops_rwsem);1797 dev_put(ndev);1798 1799 return err;1800}1801 1802static int nldev_dellink(struct sk_buff *skb, struct nlmsghdr *nlh,1803 struct netlink_ext_ack *extack)1804{1805 struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];1806 struct ib_device *device;1807 u32 index;1808 int err;1809 1810 err = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,1811 nldev_policy, extack);1812 if (err || !tb[RDMA_NLDEV_ATTR_DEV_INDEX])1813 return -EINVAL;1814 1815 index = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);1816 device = ib_device_get_by_index(sock_net(skb->sk), index);1817 if (!device)1818 return -EINVAL;1819 1820 if (!(device->attrs.kernel_cap_flags & IBK_ALLOW_USER_UNREG)) {1821 ib_device_put(device);1822 return -EINVAL;1823 }1824 1825 ib_unregister_device_and_put(device);1826 return 0;1827}1828 1829static int nldev_get_chardev(struct sk_buff *skb, struct nlmsghdr *nlh,1830 struct netlink_ext_ack *extack)1831{1832 struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];1833 char client_name[RDMA_NLDEV_ATTR_CHARDEV_TYPE_SIZE];1834 struct ib_client_nl_info data = {};1835 struct ib_device *ibdev = NULL;1836 struct sk_buff *msg;1837 u32 index;1838 int err;1839 1840 err = __nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1, nldev_policy,1841 NL_VALIDATE_LIBERAL, extack);1842 if (err || !tb[RDMA_NLDEV_ATTR_CHARDEV_TYPE])1843 return -EINVAL;1844 1845 nla_strscpy(client_name, tb[RDMA_NLDEV_ATTR_CHARDEV_TYPE],1846 sizeof(client_name));1847 1848 if (tb[RDMA_NLDEV_ATTR_DEV_INDEX]) {1849 index = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);1850 ibdev = ib_device_get_by_index(sock_net(skb->sk), index);1851 if (!ibdev)1852 return -EINVAL;1853 1854 if (tb[RDMA_NLDEV_ATTR_PORT_INDEX]) {1855 data.port = nla_get_u32(tb[RDMA_NLDEV_ATTR_PORT_INDEX]);1856 if (!rdma_is_port_valid(ibdev, data.port)) {1857 err = -EINVAL;1858 goto out_put;1859 }1860 } else {1861 data.port = -1;1862 }1863 } else if (tb[RDMA_NLDEV_ATTR_PORT_INDEX]) {1864 return -EINVAL;1865 }1866 1867 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);1868 if (!msg) {1869 err = -ENOMEM;1870 goto out_put;1871 }1872 nlh = nlmsg_put(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq,1873 RDMA_NL_GET_TYPE(RDMA_NL_NLDEV,1874 RDMA_NLDEV_CMD_GET_CHARDEV),1875 0, 0);1876 if (!nlh) {1877 err = -EMSGSIZE;1878 goto out_nlmsg;1879 }1880 1881 data.nl_msg = msg;1882 err = ib_get_client_nl_info(ibdev, client_name, &data);1883 if (err)1884 goto out_nlmsg;1885 1886 err = nla_put_u64_64bit(msg, RDMA_NLDEV_ATTR_CHARDEV,1887 huge_encode_dev(data.cdev->devt),1888 RDMA_NLDEV_ATTR_PAD);1889 if (err)1890 goto out_data;1891 err = nla_put_u64_64bit(msg, RDMA_NLDEV_ATTR_CHARDEV_ABI, data.abi,1892 RDMA_NLDEV_ATTR_PAD);1893 if (err)1894 goto out_data;1895 if (nla_put_string(msg, RDMA_NLDEV_ATTR_CHARDEV_NAME,1896 dev_name(data.cdev))) {1897 err = -EMSGSIZE;1898 goto out_data;1899 }1900 1901 nlmsg_end(msg, nlh);1902 put_device(data.cdev);1903 if (ibdev)1904 ib_device_put(ibdev);1905 return rdma_nl_unicast(sock_net(skb->sk), msg, NETLINK_CB(skb).portid);1906 1907out_data:1908 put_device(data.cdev);1909out_nlmsg:1910 nlmsg_free(msg);1911out_put:1912 if (ibdev)1913 ib_device_put(ibdev);1914 return err;1915}1916 1917static int nldev_sys_get_doit(struct sk_buff *skb, struct nlmsghdr *nlh,1918 struct netlink_ext_ack *extack)1919{1920 struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];1921 struct sk_buff *msg;1922 int err;1923 1924 err = __nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,1925 nldev_policy, NL_VALIDATE_LIBERAL, extack);1926 if (err)1927 return err;1928 1929 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);1930 if (!msg)1931 return -ENOMEM;1932 1933 nlh = nlmsg_put(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq,1934 RDMA_NL_GET_TYPE(RDMA_NL_NLDEV,1935 RDMA_NLDEV_CMD_SYS_GET),1936 0, 0);1937 if (!nlh) {1938 nlmsg_free(msg);1939 return -EMSGSIZE;1940 }1941 1942 err = nla_put_u8(msg, RDMA_NLDEV_SYS_ATTR_NETNS_MODE,1943 (u8)ib_devices_shared_netns);1944 if (err) {1945 nlmsg_free(msg);1946 return err;1947 }1948 1949 err = nla_put_u8(msg, RDMA_NLDEV_SYS_ATTR_PRIVILEGED_QKEY_MODE,1950 (u8)privileged_qkey);1951 if (err) {1952 nlmsg_free(msg);1953 return err;1954 }1955 1956 err = nla_put_u8(msg, RDMA_NLDEV_SYS_ATTR_MONITOR_MODE, 1);1957 if (err) {1958 nlmsg_free(msg);1959 return err;1960 }1961 /*1962 * Copy-on-fork is supported.1963 * See commits:1964 * 70e806e4e645 ("mm: Do early cow for pinned pages during fork() for ptes")1965 * 4eae4efa2c29 ("hugetlb: do early cow when page pinned on src mm")1966 * for more details. Don't backport this without them.1967 *1968 * Return value ignored on purpose, assume copy-on-fork is not1969 * supported in case of failure.1970 */1971 nla_put_u8(msg, RDMA_NLDEV_SYS_ATTR_COPY_ON_FORK, 1);1972 1973 nlmsg_end(msg, nlh);1974 return rdma_nl_unicast(sock_net(skb->sk), msg, NETLINK_CB(skb).portid);1975}1976 1977static int nldev_set_sys_set_netns_doit(struct nlattr *tb[])1978{1979 u8 enable;1980 int err;1981 1982 enable = nla_get_u8(tb[RDMA_NLDEV_SYS_ATTR_NETNS_MODE]);1983 /* Only 0 and 1 are supported */1984 if (enable > 1)1985 return -EINVAL;1986 1987 err = rdma_compatdev_set(enable);1988 return err;1989}1990 1991static int nldev_set_sys_set_pqkey_doit(struct nlattr *tb[])1992{1993 u8 enable;1994 1995 enable = nla_get_u8(tb[RDMA_NLDEV_SYS_ATTR_PRIVILEGED_QKEY_MODE]);1996 /* Only 0 and 1 are supported */1997 if (enable > 1)1998 return -EINVAL;1999 2000 privileged_qkey = enable;2001 return 0;2002}2003 2004static int nldev_set_sys_set_doit(struct sk_buff *skb, struct nlmsghdr *nlh,2005 struct netlink_ext_ack *extack)2006{2007 struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];2008 int err;2009 2010 err = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,2011 nldev_policy, extack);2012 if (err)2013 return -EINVAL;2014 2015 if (tb[RDMA_NLDEV_SYS_ATTR_NETNS_MODE])2016 return nldev_set_sys_set_netns_doit(tb);2017 2018 if (tb[RDMA_NLDEV_SYS_ATTR_PRIVILEGED_QKEY_MODE])2019 return nldev_set_sys_set_pqkey_doit(tb);2020 2021 return -EINVAL;2022}2023 2024 2025static int nldev_stat_set_mode_doit(struct sk_buff *msg,2026 struct netlink_ext_ack *extack,2027 struct nlattr *tb[],2028 struct ib_device *device, u32 port)2029{2030 u32 mode, mask = 0, qpn, cntn = 0;2031 int ret;2032 2033 /* Currently only counter for QP is supported */2034 if (!tb[RDMA_NLDEV_ATTR_STAT_RES] ||2035 nla_get_u32(tb[RDMA_NLDEV_ATTR_STAT_RES]) != RDMA_NLDEV_ATTR_RES_QP)2036 return -EINVAL;2037 2038 mode = nla_get_u32(tb[RDMA_NLDEV_ATTR_STAT_MODE]);2039 if (mode == RDMA_COUNTER_MODE_AUTO) {2040 if (tb[RDMA_NLDEV_ATTR_STAT_AUTO_MODE_MASK])2041 mask = nla_get_u32(2042 tb[RDMA_NLDEV_ATTR_STAT_AUTO_MODE_MASK]);2043 return rdma_counter_set_auto_mode(device, port, mask, extack);2044 }2045 2046 if (!tb[RDMA_NLDEV_ATTR_RES_LQPN])2047 return -EINVAL;2048 2049 qpn = nla_get_u32(tb[RDMA_NLDEV_ATTR_RES_LQPN]);2050 if (tb[RDMA_NLDEV_ATTR_STAT_COUNTER_ID]) {2051 cntn = nla_get_u32(tb[RDMA_NLDEV_ATTR_STAT_COUNTER_ID]);2052 ret = rdma_counter_bind_qpn(device, port, qpn, cntn);2053 if (ret)2054 return ret;2055 } else {2056 ret = rdma_counter_bind_qpn_alloc(device, port, qpn, &cntn);2057 if (ret)2058 return ret;2059 }2060 2061 if (nla_put_u32(msg, RDMA_NLDEV_ATTR_STAT_COUNTER_ID, cntn) ||2062 nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_LQPN, qpn)) {2063 ret = -EMSGSIZE;2064 goto err_fill;2065 }2066 2067 return 0;2068 2069err_fill:2070 rdma_counter_unbind_qpn(device, port, qpn, cntn);2071 return ret;2072}2073 2074static int nldev_stat_set_counter_dynamic_doit(struct nlattr *tb[],2075 struct ib_device *device,2076 u32 port)2077{2078 struct rdma_hw_stats *stats;2079 struct nlattr *entry_attr;2080 unsigned long *target;2081 int rem, i, ret = 0;2082 u32 index;2083 2084 stats = ib_get_hw_stats_port(device, port);2085 if (!stats)2086 return -EINVAL;2087 2088 target = kcalloc(BITS_TO_LONGS(stats->num_counters),2089 sizeof(*stats->is_disabled), GFP_KERNEL);2090 if (!target)2091 return -ENOMEM;2092 2093 nla_for_each_nested(entry_attr, tb[RDMA_NLDEV_ATTR_STAT_HWCOUNTERS],2094 rem) {2095 index = nla_get_u32(entry_attr);2096 if ((index >= stats->num_counters) ||2097 !(stats->descs[index].flags & IB_STAT_FLAG_OPTIONAL)) {2098 ret = -EINVAL;2099 goto out;2100 }2101 2102 set_bit(index, target);2103 }2104 2105 for (i = 0; i < stats->num_counters; i++) {2106 if (!(stats->descs[i].flags & IB_STAT_FLAG_OPTIONAL))2107 continue;2108 2109 ret = rdma_counter_modify(device, port, i, test_bit(i, target));2110 if (ret)2111 goto out;2112 }2113 2114out:2115 kfree(target);2116 return ret;2117}2118 2119static int nldev_stat_set_doit(struct sk_buff *skb, struct nlmsghdr *nlh,2120 struct netlink_ext_ack *extack)2121{2122 struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];2123 struct ib_device *device;2124 struct sk_buff *msg;2125 u32 index, port;2126 int ret;2127 2128 ret = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1, nldev_policy,2129 extack);2130 if (ret || !tb[RDMA_NLDEV_ATTR_DEV_INDEX] ||2131 !tb[RDMA_NLDEV_ATTR_PORT_INDEX])2132 return -EINVAL;2133 2134 index = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);2135 device = ib_device_get_by_index(sock_net(skb->sk), index);2136 if (!device)2137 return -EINVAL;2138 2139 port = nla_get_u32(tb[RDMA_NLDEV_ATTR_PORT_INDEX]);2140 if (!rdma_is_port_valid(device, port)) {2141 ret = -EINVAL;2142 goto err_put_device;2143 }2144 2145 if (!tb[RDMA_NLDEV_ATTR_STAT_MODE] &&2146 !tb[RDMA_NLDEV_ATTR_STAT_HWCOUNTERS]) {2147 ret = -EINVAL;2148 goto err_put_device;2149 }2150 2151 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);2152 if (!msg) {2153 ret = -ENOMEM;2154 goto err_put_device;2155 }2156 nlh = nlmsg_put(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq,2157 RDMA_NL_GET_TYPE(RDMA_NL_NLDEV,2158 RDMA_NLDEV_CMD_STAT_SET),2159 0, 0);2160 if (!nlh || fill_nldev_handle(msg, device) ||2161 nla_put_u32(msg, RDMA_NLDEV_ATTR_PORT_INDEX, port)) {2162 ret = -EMSGSIZE;2163 goto err_free_msg;2164 }2165 2166 if (tb[RDMA_NLDEV_ATTR_STAT_MODE]) {2167 ret = nldev_stat_set_mode_doit(msg, extack, tb, device, port);2168 if (ret)2169 goto err_free_msg;2170 }2171 2172 if (tb[RDMA_NLDEV_ATTR_STAT_HWCOUNTERS]) {2173 ret = nldev_stat_set_counter_dynamic_doit(tb, device, port);2174 if (ret)2175 goto err_free_msg;2176 }2177 2178 nlmsg_end(msg, nlh);2179 ib_device_put(device);2180 return rdma_nl_unicast(sock_net(skb->sk), msg, NETLINK_CB(skb).portid);2181 2182err_free_msg:2183 nlmsg_free(msg);2184err_put_device:2185 ib_device_put(device);2186 return ret;2187}2188 2189static int nldev_stat_del_doit(struct sk_buff *skb, struct nlmsghdr *nlh,2190 struct netlink_ext_ack *extack)2191{2192 struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];2193 struct ib_device *device;2194 struct sk_buff *msg;2195 u32 index, port, qpn, cntn;2196 int ret;2197 2198 ret = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,2199 nldev_policy, extack);2200 if (ret || !tb[RDMA_NLDEV_ATTR_STAT_RES] ||2201 !tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_PORT_INDEX] ||2202 !tb[RDMA_NLDEV_ATTR_STAT_COUNTER_ID] ||2203 !tb[RDMA_NLDEV_ATTR_RES_LQPN])2204 return -EINVAL;2205 2206 if (nla_get_u32(tb[RDMA_NLDEV_ATTR_STAT_RES]) != RDMA_NLDEV_ATTR_RES_QP)2207 return -EINVAL;2208 2209 index = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);2210 device = ib_device_get_by_index(sock_net(skb->sk), index);2211 if (!device)2212 return -EINVAL;2213 2214 port = nla_get_u32(tb[RDMA_NLDEV_ATTR_PORT_INDEX]);2215 if (!rdma_is_port_valid(device, port)) {2216 ret = -EINVAL;2217 goto err;2218 }2219 2220 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);2221 if (!msg) {2222 ret = -ENOMEM;2223 goto err;2224 }2225 nlh = nlmsg_put(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq,2226 RDMA_NL_GET_TYPE(RDMA_NL_NLDEV,2227 RDMA_NLDEV_CMD_STAT_SET),2228 0, 0);2229 if (!nlh) {2230 ret = -EMSGSIZE;2231 goto err_fill;2232 }2233 2234 cntn = nla_get_u32(tb[RDMA_NLDEV_ATTR_STAT_COUNTER_ID]);2235 qpn = nla_get_u32(tb[RDMA_NLDEV_ATTR_RES_LQPN]);2236 if (fill_nldev_handle(msg, device) ||2237 nla_put_u32(msg, RDMA_NLDEV_ATTR_PORT_INDEX, port) ||2238 nla_put_u32(msg, RDMA_NLDEV_ATTR_STAT_COUNTER_ID, cntn) ||2239 nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_LQPN, qpn)) {2240 ret = -EMSGSIZE;2241 goto err_fill;2242 }2243 2244 ret = rdma_counter_unbind_qpn(device, port, qpn, cntn);2245 if (ret)2246 goto err_fill;2247 2248 nlmsg_end(msg, nlh);2249 ib_device_put(device);2250 return rdma_nl_unicast(sock_net(skb->sk), msg, NETLINK_CB(skb).portid);2251 2252err_fill:2253 nlmsg_free(msg);2254err:2255 ib_device_put(device);2256 return ret;2257}2258 2259static int stat_get_doit_default_counter(struct sk_buff *skb,2260 struct nlmsghdr *nlh,2261 struct netlink_ext_ack *extack,2262 struct nlattr *tb[])2263{2264 struct rdma_hw_stats *stats;2265 struct nlattr *table_attr;2266 struct ib_device *device;2267 int ret, num_cnts, i;2268 struct sk_buff *msg;2269 u32 index, port;2270 u64 v;2271 2272 if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_PORT_INDEX])2273 return -EINVAL;2274 2275 index = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);2276 device = ib_device_get_by_index(sock_net(skb->sk), index);2277 if (!device)2278 return -EINVAL;2279 2280 if (!device->ops.alloc_hw_port_stats || !device->ops.get_hw_stats) {2281 ret = -EINVAL;2282 goto err;2283 }2284 2285 port = nla_get_u32(tb[RDMA_NLDEV_ATTR_PORT_INDEX]);2286 stats = ib_get_hw_stats_port(device, port);2287 if (!stats) {2288 ret = -EINVAL;2289 goto err;2290 }2291 2292 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);2293 if (!msg) {2294 ret = -ENOMEM;2295 goto err;2296 }2297 2298 nlh = nlmsg_put(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq,2299 RDMA_NL_GET_TYPE(RDMA_NL_NLDEV,2300 RDMA_NLDEV_CMD_STAT_GET),2301 0, 0);2302 2303 if (!nlh || fill_nldev_handle(msg, device) ||2304 nla_put_u32(msg, RDMA_NLDEV_ATTR_PORT_INDEX, port)) {2305 ret = -EMSGSIZE;2306 goto err_msg;2307 }2308 2309 mutex_lock(&stats->lock);2310 2311 num_cnts = device->ops.get_hw_stats(device, stats, port, 0);2312 if (num_cnts < 0) {2313 ret = -EINVAL;2314 goto err_stats;2315 }2316 2317 table_attr = nla_nest_start(msg, RDMA_NLDEV_ATTR_STAT_HWCOUNTERS);2318 if (!table_attr) {2319 ret = -EMSGSIZE;2320 goto err_stats;2321 }2322 for (i = 0; i < num_cnts; i++) {2323 if (test_bit(i, stats->is_disabled))2324 continue;2325 2326 v = stats->value[i] +2327 rdma_counter_get_hwstat_value(device, port, i);2328 if (rdma_nl_stat_hwcounter_entry(msg,2329 stats->descs[i].name, v)) {2330 ret = -EMSGSIZE;2331 goto err_table;2332 }2333 }2334 nla_nest_end(msg, table_attr);2335 2336 mutex_unlock(&stats->lock);2337 nlmsg_end(msg, nlh);2338 ib_device_put(device);2339 return rdma_nl_unicast(sock_net(skb->sk), msg, NETLINK_CB(skb).portid);2340 2341err_table:2342 nla_nest_cancel(msg, table_attr);2343err_stats:2344 mutex_unlock(&stats->lock);2345err_msg:2346 nlmsg_free(msg);2347err:2348 ib_device_put(device);2349 return ret;2350}2351 2352static int stat_get_doit_qp(struct sk_buff *skb, struct nlmsghdr *nlh,2353 struct netlink_ext_ack *extack, struct nlattr *tb[])2354 2355{2356 static enum rdma_nl_counter_mode mode;2357 static enum rdma_nl_counter_mask mask;2358 struct ib_device *device;2359 struct sk_buff *msg;2360 u32 index, port;2361 int ret;2362 2363 if (tb[RDMA_NLDEV_ATTR_STAT_COUNTER_ID])2364 return nldev_res_get_counter_doit(skb, nlh, extack);2365 2366 if (!tb[RDMA_NLDEV_ATTR_STAT_MODE] ||2367 !tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_PORT_INDEX])2368 return -EINVAL;2369 2370 index = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);2371 device = ib_device_get_by_index(sock_net(skb->sk), index);2372 if (!device)2373 return -EINVAL;2374 2375 port = nla_get_u32(tb[RDMA_NLDEV_ATTR_PORT_INDEX]);2376 if (!rdma_is_port_valid(device, port)) {2377 ret = -EINVAL;2378 goto err;2379 }2380 2381 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);2382 if (!msg) {2383 ret = -ENOMEM;2384 goto err;2385 }2386 2387 nlh = nlmsg_put(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq,2388 RDMA_NL_GET_TYPE(RDMA_NL_NLDEV,2389 RDMA_NLDEV_CMD_STAT_GET),2390 0, 0);2391 if (!nlh) {2392 ret = -EMSGSIZE;2393 goto err_msg;2394 }2395 2396 ret = rdma_counter_get_mode(device, port, &mode, &mask);2397 if (ret)2398 goto err_msg;2399 2400 if (fill_nldev_handle(msg, device) ||2401 nla_put_u32(msg, RDMA_NLDEV_ATTR_PORT_INDEX, port) ||2402 nla_put_u32(msg, RDMA_NLDEV_ATTR_STAT_MODE, mode)) {2403 ret = -EMSGSIZE;2404 goto err_msg;2405 }2406 2407 if ((mode == RDMA_COUNTER_MODE_AUTO) &&2408 nla_put_u32(msg, RDMA_NLDEV_ATTR_STAT_AUTO_MODE_MASK, mask)) {2409 ret = -EMSGSIZE;2410 goto err_msg;2411 }2412 2413 nlmsg_end(msg, nlh);2414 ib_device_put(device);2415 return rdma_nl_unicast(sock_net(skb->sk), msg, NETLINK_CB(skb).portid);2416 2417err_msg:2418 nlmsg_free(msg);2419err:2420 ib_device_put(device);2421 return ret;2422}2423 2424static int nldev_stat_get_doit(struct sk_buff *skb, struct nlmsghdr *nlh,2425 struct netlink_ext_ack *extack)2426{2427 struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];2428 int ret;2429 2430 ret = __nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,2431 nldev_policy, NL_VALIDATE_LIBERAL, extack);2432 if (ret)2433 return -EINVAL;2434 2435 if (!tb[RDMA_NLDEV_ATTR_STAT_RES])2436 return stat_get_doit_default_counter(skb, nlh, extack, tb);2437 2438 switch (nla_get_u32(tb[RDMA_NLDEV_ATTR_STAT_RES])) {2439 case RDMA_NLDEV_ATTR_RES_QP:2440 ret = stat_get_doit_qp(skb, nlh, extack, tb);2441 break;2442 case RDMA_NLDEV_ATTR_RES_MR:2443 ret = res_get_common_doit(skb, nlh, extack, RDMA_RESTRACK_MR,2444 fill_stat_mr_entry);2445 break;2446 default:2447 ret = -EINVAL;2448 break;2449 }2450 2451 return ret;2452}2453 2454static int nldev_stat_get_dumpit(struct sk_buff *skb,2455 struct netlink_callback *cb)2456{2457 struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];2458 int ret;2459 2460 ret = __nlmsg_parse(cb->nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,2461 nldev_policy, NL_VALIDATE_LIBERAL, NULL);2462 if (ret || !tb[RDMA_NLDEV_ATTR_STAT_RES])2463 return -EINVAL;2464 2465 switch (nla_get_u32(tb[RDMA_NLDEV_ATTR_STAT_RES])) {2466 case RDMA_NLDEV_ATTR_RES_QP:2467 ret = nldev_res_get_counter_dumpit(skb, cb);2468 break;2469 case RDMA_NLDEV_ATTR_RES_MR:2470 ret = res_get_common_dumpit(skb, cb, RDMA_RESTRACK_MR,2471 fill_stat_mr_entry);2472 break;2473 default:2474 ret = -EINVAL;2475 break;2476 }2477 2478 return ret;2479}2480 2481static int nldev_stat_get_counter_status_doit(struct sk_buff *skb,2482 struct nlmsghdr *nlh,2483 struct netlink_ext_ack *extack)2484{2485 struct nlattr *tb[RDMA_NLDEV_ATTR_MAX], *table, *entry;2486 struct rdma_hw_stats *stats;2487 struct ib_device *device;2488 struct sk_buff *msg;2489 u32 devid, port;2490 int ret, i;2491 2492 ret = __nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,2493 nldev_policy, NL_VALIDATE_LIBERAL, extack);2494 if (ret || !tb[RDMA_NLDEV_ATTR_DEV_INDEX] ||2495 !tb[RDMA_NLDEV_ATTR_PORT_INDEX])2496 return -EINVAL;2497 2498 devid = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);2499 device = ib_device_get_by_index(sock_net(skb->sk), devid);2500 if (!device)2501 return -EINVAL;2502 2503 port = nla_get_u32(tb[RDMA_NLDEV_ATTR_PORT_INDEX]);2504 if (!rdma_is_port_valid(device, port)) {2505 ret = -EINVAL;2506 goto err;2507 }2508 2509 stats = ib_get_hw_stats_port(device, port);2510 if (!stats) {2511 ret = -EINVAL;2512 goto err;2513 }2514 2515 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);2516 if (!msg) {2517 ret = -ENOMEM;2518 goto err;2519 }2520 2521 nlh = nlmsg_put(2522 msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq,2523 RDMA_NL_GET_TYPE(RDMA_NL_NLDEV, RDMA_NLDEV_CMD_STAT_GET_STATUS),2524 0, 0);2525 2526 ret = -EMSGSIZE;2527 if (!nlh || fill_nldev_handle(msg, device) ||2528 nla_put_u32(msg, RDMA_NLDEV_ATTR_PORT_INDEX, port))2529 goto err_msg;2530 2531 table = nla_nest_start(msg, RDMA_NLDEV_ATTR_STAT_HWCOUNTERS);2532 if (!table)2533 goto err_msg;2534 2535 mutex_lock(&stats->lock);2536 for (i = 0; i < stats->num_counters; i++) {2537 entry = nla_nest_start(msg,2538 RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY);2539 if (!entry)2540 goto err_msg_table;2541 2542 if (nla_put_string(msg,2543 RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_NAME,2544 stats->descs[i].name) ||2545 nla_put_u32(msg, RDMA_NLDEV_ATTR_STAT_HWCOUNTER_INDEX, i))2546 goto err_msg_entry;2547 2548 if ((stats->descs[i].flags & IB_STAT_FLAG_OPTIONAL) &&2549 (nla_put_u8(msg, RDMA_NLDEV_ATTR_STAT_HWCOUNTER_DYNAMIC,2550 !test_bit(i, stats->is_disabled))))2551 goto err_msg_entry;2552 2553 nla_nest_end(msg, entry);2554 }2555 mutex_unlock(&stats->lock);2556 2557 nla_nest_end(msg, table);2558 nlmsg_end(msg, nlh);2559 ib_device_put(device);2560 return rdma_nl_unicast(sock_net(skb->sk), msg, NETLINK_CB(skb).portid);2561 2562err_msg_entry:2563 nla_nest_cancel(msg, entry);2564err_msg_table:2565 mutex_unlock(&stats->lock);2566 nla_nest_cancel(msg, table);2567err_msg:2568 nlmsg_free(msg);2569err:2570 ib_device_put(device);2571 return ret;2572}2573 2574static int nldev_newdev(struct sk_buff *skb, struct nlmsghdr *nlh,2575 struct netlink_ext_ack *extack)2576{2577 struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];2578 enum rdma_nl_dev_type type;2579 struct ib_device *parent;2580 char name[IFNAMSIZ] = {};2581 u32 parentid;2582 int ret;2583 2584 ret = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,2585 nldev_policy, extack);2586 if (ret || !tb[RDMA_NLDEV_ATTR_DEV_INDEX] ||2587 !tb[RDMA_NLDEV_ATTR_DEV_NAME] || !tb[RDMA_NLDEV_ATTR_DEV_TYPE])2588 return -EINVAL;2589 2590 nla_strscpy(name, tb[RDMA_NLDEV_ATTR_DEV_NAME], sizeof(name));2591 type = nla_get_u8(tb[RDMA_NLDEV_ATTR_DEV_TYPE]);2592 parentid = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);2593 parent = ib_device_get_by_index(sock_net(skb->sk), parentid);2594 if (!parent)2595 return -EINVAL;2596 2597 ret = ib_add_sub_device(parent, type, name);2598 ib_device_put(parent);2599 2600 return ret;2601}2602 2603static int nldev_deldev(struct sk_buff *skb, struct nlmsghdr *nlh,2604 struct netlink_ext_ack *extack)2605{2606 struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];2607 struct ib_device *device;2608 u32 devid;2609 int ret;2610 2611 ret = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,2612 nldev_policy, extack);2613 if (ret || !tb[RDMA_NLDEV_ATTR_DEV_INDEX])2614 return -EINVAL;2615 2616 devid = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);2617 device = ib_device_get_by_index(sock_net(skb->sk), devid);2618 if (!device)2619 return -EINVAL;2620 2621 return ib_del_sub_device_and_put(device);2622}2623 2624static const struct rdma_nl_cbs nldev_cb_table[RDMA_NLDEV_NUM_OPS] = {2625 [RDMA_NLDEV_CMD_GET] = {2626 .doit = nldev_get_doit,2627 .dump = nldev_get_dumpit,2628 },2629 [RDMA_NLDEV_CMD_GET_CHARDEV] = {2630 .doit = nldev_get_chardev,2631 },2632 [RDMA_NLDEV_CMD_SET] = {2633 .doit = nldev_set_doit,2634 .flags = RDMA_NL_ADMIN_PERM,2635 },2636 [RDMA_NLDEV_CMD_NEWLINK] = {2637 .doit = nldev_newlink,2638 .flags = RDMA_NL_ADMIN_PERM,2639 },2640 [RDMA_NLDEV_CMD_DELLINK] = {2641 .doit = nldev_dellink,2642 .flags = RDMA_NL_ADMIN_PERM,2643 },2644 [RDMA_NLDEV_CMD_PORT_GET] = {2645 .doit = nldev_port_get_doit,2646 .dump = nldev_port_get_dumpit,2647 },2648 [RDMA_NLDEV_CMD_RES_GET] = {2649 .doit = nldev_res_get_doit,2650 .dump = nldev_res_get_dumpit,2651 },2652 [RDMA_NLDEV_CMD_RES_QP_GET] = {2653 .doit = nldev_res_get_qp_doit,2654 .dump = nldev_res_get_qp_dumpit,2655 },2656 [RDMA_NLDEV_CMD_RES_CM_ID_GET] = {2657 .doit = nldev_res_get_cm_id_doit,2658 .dump = nldev_res_get_cm_id_dumpit,2659 },2660 [RDMA_NLDEV_CMD_RES_CQ_GET] = {2661 .doit = nldev_res_get_cq_doit,2662 .dump = nldev_res_get_cq_dumpit,2663 },2664 [RDMA_NLDEV_CMD_RES_MR_GET] = {2665 .doit = nldev_res_get_mr_doit,2666 .dump = nldev_res_get_mr_dumpit,2667 },2668 [RDMA_NLDEV_CMD_RES_PD_GET] = {2669 .doit = nldev_res_get_pd_doit,2670 .dump = nldev_res_get_pd_dumpit,2671 },2672 [RDMA_NLDEV_CMD_RES_CTX_GET] = {2673 .doit = nldev_res_get_ctx_doit,2674 .dump = nldev_res_get_ctx_dumpit,2675 },2676 [RDMA_NLDEV_CMD_RES_SRQ_GET] = {2677 .doit = nldev_res_get_srq_doit,2678 .dump = nldev_res_get_srq_dumpit,2679 },2680 [RDMA_NLDEV_CMD_SYS_GET] = {2681 .doit = nldev_sys_get_doit,2682 },2683 [RDMA_NLDEV_CMD_SYS_SET] = {2684 .doit = nldev_set_sys_set_doit,2685 .flags = RDMA_NL_ADMIN_PERM,2686 },2687 [RDMA_NLDEV_CMD_STAT_SET] = {2688 .doit = nldev_stat_set_doit,2689 .flags = RDMA_NL_ADMIN_PERM,2690 },2691 [RDMA_NLDEV_CMD_STAT_GET] = {2692 .doit = nldev_stat_get_doit,2693 .dump = nldev_stat_get_dumpit,2694 },2695 [RDMA_NLDEV_CMD_STAT_DEL] = {2696 .doit = nldev_stat_del_doit,2697 .flags = RDMA_NL_ADMIN_PERM,2698 },2699 [RDMA_NLDEV_CMD_RES_QP_GET_RAW] = {2700 .doit = nldev_res_get_qp_raw_doit,2701 .dump = nldev_res_get_qp_raw_dumpit,2702 .flags = RDMA_NL_ADMIN_PERM,2703 },2704 [RDMA_NLDEV_CMD_RES_CQ_GET_RAW] = {2705 .doit = nldev_res_get_cq_raw_doit,2706 .dump = nldev_res_get_cq_raw_dumpit,2707 .flags = RDMA_NL_ADMIN_PERM,2708 },2709 [RDMA_NLDEV_CMD_RES_MR_GET_RAW] = {2710 .doit = nldev_res_get_mr_raw_doit,2711 .dump = nldev_res_get_mr_raw_dumpit,2712 .flags = RDMA_NL_ADMIN_PERM,2713 },2714 [RDMA_NLDEV_CMD_RES_SRQ_GET_RAW] = {2715 .doit = nldev_res_get_srq_raw_doit,2716 .dump = nldev_res_get_srq_raw_dumpit,2717 .flags = RDMA_NL_ADMIN_PERM,2718 },2719 [RDMA_NLDEV_CMD_STAT_GET_STATUS] = {2720 .doit = nldev_stat_get_counter_status_doit,2721 },2722 [RDMA_NLDEV_CMD_NEWDEV] = {2723 .doit = nldev_newdev,2724 .flags = RDMA_NL_ADMIN_PERM,2725 },2726 [RDMA_NLDEV_CMD_DELDEV] = {2727 .doit = nldev_deldev,2728 .flags = RDMA_NL_ADMIN_PERM,2729 },2730};2731 2732static int fill_mon_netdev_association(struct sk_buff *msg,2733 struct ib_device *device, u32 port,2734 const struct net *net)2735{2736 struct net_device *netdev = ib_device_get_netdev(device, port);2737 int ret = 0;2738 2739 if (netdev && !net_eq(dev_net(netdev), net))2740 goto out;2741 2742 ret = nla_put_u32(msg, RDMA_NLDEV_ATTR_DEV_INDEX, device->index);2743 if (ret)2744 goto out;2745 2746 ret = nla_put_string(msg, RDMA_NLDEV_ATTR_DEV_NAME,2747 dev_name(&device->dev));2748 if (ret)2749 goto out;2750 2751 ret = nla_put_u32(msg, RDMA_NLDEV_ATTR_PORT_INDEX, port);2752 if (ret)2753 goto out;2754 2755 if (netdev) {2756 ret = nla_put_u32(msg,2757 RDMA_NLDEV_ATTR_NDEV_INDEX, netdev->ifindex);2758 if (ret)2759 goto out;2760 2761 ret = nla_put_string(msg,2762 RDMA_NLDEV_ATTR_NDEV_NAME, netdev->name);2763 }2764 2765out:2766 dev_put(netdev);2767 return ret;2768}2769 2770static void rdma_nl_notify_err_msg(struct ib_device *device, u32 port_num,2771 enum rdma_nl_notify_event_type type)2772{2773 struct net_device *netdev;2774 2775 switch (type) {2776 case RDMA_REGISTER_EVENT:2777 dev_warn_ratelimited(&device->dev,2778 "Failed to send RDMA monitor register device event\n");2779 break;2780 case RDMA_UNREGISTER_EVENT:2781 dev_warn_ratelimited(&device->dev,2782 "Failed to send RDMA monitor unregister device event\n");2783 break;2784 case RDMA_NETDEV_ATTACH_EVENT:2785 netdev = ib_device_get_netdev(device, port_num);2786 dev_warn_ratelimited(&device->dev,2787 "Failed to send RDMA monitor netdev attach event: port %d netdev %d\n",2788 port_num, netdev->ifindex);2789 dev_put(netdev);2790 break;2791 case RDMA_NETDEV_DETACH_EVENT:2792 dev_warn_ratelimited(&device->dev,2793 "Failed to send RDMA monitor netdev detach event: port %d\n",2794 port_num);2795 break;2796 default:2797 break;2798 }2799}2800 2801int rdma_nl_notify_event(struct ib_device *device, u32 port_num,2802 enum rdma_nl_notify_event_type type)2803{2804 struct sk_buff *skb;2805 struct net *net;2806 int ret = 0;2807 void *nlh;2808 2809 net = read_pnet(&device->coredev.rdma_net);2810 if (!net)2811 return -EINVAL;2812 2813 skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);2814 if (!skb)2815 return -ENOMEM;2816 nlh = nlmsg_put(skb, 0, 0,2817 RDMA_NL_GET_TYPE(RDMA_NL_NLDEV, RDMA_NLDEV_CMD_MONITOR),2818 0, 0);2819 if (!nlh)2820 goto err_free;2821 2822 switch (type) {2823 case RDMA_REGISTER_EVENT:2824 case RDMA_UNREGISTER_EVENT:2825 ret = fill_nldev_handle(skb, device);2826 if (ret)2827 goto err_free;2828 break;2829 case RDMA_NETDEV_ATTACH_EVENT:2830 case RDMA_NETDEV_DETACH_EVENT:2831 ret = fill_mon_netdev_association(skb, device,2832 port_num, net);2833 if (ret)2834 goto err_free;2835 break;2836 default:2837 break;2838 }2839 2840 ret = nla_put_u8(skb, RDMA_NLDEV_ATTR_EVENT_TYPE, type);2841 if (ret)2842 goto err_free;2843 2844 nlmsg_end(skb, nlh);2845 ret = rdma_nl_multicast(net, skb, RDMA_NL_GROUP_NOTIFY, GFP_KERNEL);2846 if (ret && ret != -ESRCH) {2847 skb = NULL; /* skb is freed in the netlink send-op handling */2848 goto err_free;2849 }2850 return 0;2851 2852err_free:2853 rdma_nl_notify_err_msg(device, port_num, type);2854 nlmsg_free(skb);2855 return ret;2856}2857 2858void __init nldev_init(void)2859{2860 rdma_nl_register(RDMA_NL_NLDEV, nldev_cb_table);2861}2862 2863void nldev_exit(void)2864{2865 rdma_nl_unregister(RDMA_NL_NLDEV);2866}2867 2868MODULE_ALIAS_RDMA_NETLINK(RDMA_NL_NLDEV, 5);2869