1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
4 * Authors: Leon Romanovsky <leonro@mellanox.com>
10 static int dev_help(struct rd *rd)
12 pr_out("Usage: %s dev show [DEV]\n", rd->filename);
13 pr_out(" %s dev set [DEV] name DEVNAME\n", rd->filename);
14 pr_out(" %s dev set [DEV] netns NSNAME\n", rd->filename);
15 pr_out(" %s dev set [DEV] adaptive-moderation [on|off]\n", rd->filename);
19 static const char *dev_caps_to_str(uint32_t idx)
21 #define RDMA_DEV_FLAGS_LOW(x) \
27 x(CHANGE_PHY_PORT, 5) \
28 x(UD_AV_PORT_ENFORCE_PORT_ENFORCE, 6) \
29 x(CURR_QP_STATE_MOD, 7) \
32 x(PORT_ACTIVE_EVENT, 10) \
33 x(SYS_IMAGE_GUID, 11) \
34 x(RC_RNR_NAK_GEN, 12) \
37 x(LOCAL_DMA_LKEY, 15) \
42 x(MEM_MGT_EXTENSIONS, 21) \
43 x(BLOCK_MULTICAST_LOOPBACK, 22) \
44 x(MEM_WINDOW_TYPE_2A, 23) \
45 x(MEM_WINDOW_TYPE_2B, 24) \
48 x(CROSS_CHANNEL, 27) \
49 x(MANAGED_FLOW_STEERING, 29) \
50 x(SIGNATURE_HANDOVER, 30) \
51 x(ON_DEMAND_PAGING, 31)
53 #define RDMA_DEV_FLAGS_HIGH(x) \
55 x(VIRTUAL_FUNCTION, 1) \
56 x(RAW_SCATTER_FCS, 2) \
57 x(RDMA_NETDEV_OPA_VNIC, 3) \
58 x(PCI_WRITE_END_PADDING, 4)
61 * Separation below is needed to allow compilation of rdmatool
62 * on 32bits systems. On such systems, C-enum is limited to be
63 * int and can't hold more than 32 bits.
65 enum { RDMA_DEV_FLAGS_LOW(RDMA_BITMAP_ENUM) };
66 enum { RDMA_DEV_FLAGS_HIGH(RDMA_BITMAP_ENUM) };
68 static const char * const
69 rdma_dev_names_low[] = { RDMA_DEV_FLAGS_LOW(RDMA_BITMAP_NAMES) };
70 static const char * const
71 rdma_dev_names_high[] = { RDMA_DEV_FLAGS_HIGH(RDMA_BITMAP_NAMES) };
73 #undef RDMA_DEV_FLAGS_LOW
74 #undef RDMA_DEV_FLAGS_HIGH
76 if (idx < ARRAY_SIZE(rdma_dev_names_low) && rdma_dev_names_low[idx])
77 return rdma_dev_names_low[idx];
79 high_idx = idx - ARRAY_SIZE(rdma_dev_names_low);
80 if (high_idx < ARRAY_SIZE(rdma_dev_names_high) &&
81 rdma_dev_names_high[high_idx])
82 return rdma_dev_names_high[high_idx];
87 static void dev_print_caps(struct rd *rd, struct nlattr **tb)
92 if (!tb[RDMA_NLDEV_ATTR_CAP_FLAGS])
95 caps = mnl_attr_get_u64(tb[RDMA_NLDEV_ATTR_CAP_FLAGS]);
97 print_color_string(PRINT_FP, COLOR_NONE, NULL, "\n caps: <", NULL);
98 open_json_array(PRINT_JSON, "caps");
99 for (idx = 0; caps; idx++) {
101 print_color_string(PRINT_ANY, COLOR_NONE, NULL,
102 caps >> 0x1 ? "%s, " : "%s",
103 dev_caps_to_str(idx));
106 close_json_array(PRINT_ANY, ">");
109 static void dev_print_fw(struct rd *rd, struct nlattr **tb)
112 if (!tb[RDMA_NLDEV_ATTR_FW_VERSION])
115 str = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_FW_VERSION]);
116 print_color_string(PRINT_ANY, COLOR_NONE, "fw", "fw %s ", str);
119 static void dev_print_node_guid(struct rd *rd, struct nlattr **tb)
125 if (!tb[RDMA_NLDEV_ATTR_NODE_GUID])
128 node_guid = mnl_attr_get_u64(tb[RDMA_NLDEV_ATTR_NODE_GUID]);
129 memcpy(vp, &node_guid, sizeof(uint64_t));
130 snprintf(str, 32, "%04x:%04x:%04x:%04x", vp[3], vp[2], vp[1], vp[0]);
131 print_color_string(PRINT_ANY, COLOR_NONE, "node_guid", "node_guid %s ",
135 static void dev_print_sys_image_guid(struct rd *rd, struct nlattr **tb)
137 uint64_t sys_image_guid;
141 if (!tb[RDMA_NLDEV_ATTR_SYS_IMAGE_GUID])
144 sys_image_guid = mnl_attr_get_u64(tb[RDMA_NLDEV_ATTR_SYS_IMAGE_GUID]);
145 memcpy(vp, &sys_image_guid, sizeof(uint64_t));
146 snprintf(str, 32, "%04x:%04x:%04x:%04x", vp[3], vp[2], vp[1], vp[0]);
147 print_color_string(PRINT_ANY, COLOR_NONE, "sys_image_guid",
148 "sys_image_guid %s ", str);
151 static void dev_print_dim_setting(struct rd *rd, struct nlattr **tb)
155 if (!tb[RDMA_NLDEV_ATTR_DEV_DIM])
158 dim_setting = mnl_attr_get_u8(tb[RDMA_NLDEV_ATTR_DEV_DIM]);
162 print_on_off(rd, "adaptive-moderation", dim_setting);
166 static const char *node_type_to_str(uint8_t node_type)
168 static const char * const node_type_str[] = { "unknown", "ca",
173 if (node_type < ARRAY_SIZE(node_type_str))
174 return node_type_str[node_type];
178 static void dev_print_node_type(struct rd *rd, struct nlattr **tb)
180 const char *node_str;
183 if (!tb[RDMA_NLDEV_ATTR_DEV_NODE_TYPE])
186 node_type = mnl_attr_get_u8(tb[RDMA_NLDEV_ATTR_DEV_NODE_TYPE]);
187 node_str = node_type_to_str(node_type);
188 print_color_string(PRINT_ANY, COLOR_NONE, "node_type", "node_type %s ",
192 static int dev_parse_cb(const struct nlmsghdr *nlh, void *data)
194 struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
195 struct rd *rd = data;
199 mnl_attr_parse(nlh, 0, rd_attr_cb, tb);
200 if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME])
202 open_json_object(NULL);
203 idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
204 name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]);
205 print_color_uint(PRINT_ANY, COLOR_NONE, "ifindex", "%u: ", idx);
206 print_color_string(PRINT_ANY, COLOR_NONE, "ifname", "%s: ", name);
208 dev_print_node_type(rd, tb);
209 dev_print_fw(rd, tb);
210 dev_print_node_guid(rd, tb);
211 dev_print_sys_image_guid(rd, tb);
212 if (rd->show_details) {
213 dev_print_dim_setting(rd, tb);
214 dev_print_caps(rd, tb);
221 static int dev_no_args(struct rd *rd)
226 rd_prepare_msg(rd, RDMA_NLDEV_CMD_GET,
227 &seq, (NLM_F_REQUEST | NLM_F_ACK));
228 mnl_attr_put_u32(rd->nlh, RDMA_NLDEV_ATTR_DEV_INDEX, rd->dev_idx);
229 ret = rd_send_msg(rd);
233 ret = rd_recv_msg(rd, dev_parse_cb, rd, seq);
237 static int dev_one_show(struct rd *rd)
239 const struct rd_cmd cmds[] = {
240 { NULL, dev_no_args},
244 return rd_exec_cmd(rd, cmds, "parameter");
247 static int dev_set_name(struct rd *rd)
252 pr_err("Please provide device new name.\n");
256 rd_prepare_msg(rd, RDMA_NLDEV_CMD_SET,
257 &seq, (NLM_F_REQUEST | NLM_F_ACK));
258 mnl_attr_put_u32(rd->nlh, RDMA_NLDEV_ATTR_DEV_INDEX, rd->dev_idx);
259 mnl_attr_put_strz(rd->nlh, RDMA_NLDEV_ATTR_DEV_NAME, rd_argv(rd));
261 return rd_sendrecv_msg(rd, seq);
264 static int dev_set_netns(struct rd *rd)
272 pr_err("Please provide device name.\n");
276 if (asprintf(&netns_path, "%s/%s", NETNS_RUN_DIR, rd_argv(rd)) < 0)
279 netns = open(netns_path, O_RDONLY | O_CLOEXEC);
281 fprintf(stderr, "Cannot open network namespace \"%s\": %s\n",
282 rd_argv(rd), strerror(errno));
287 rd_prepare_msg(rd, RDMA_NLDEV_CMD_SET,
288 &seq, (NLM_F_REQUEST | NLM_F_ACK));
289 mnl_attr_put_u32(rd->nlh, RDMA_NLDEV_ATTR_DEV_INDEX, rd->dev_idx);
290 mnl_attr_put_u32(rd->nlh, RDMA_NLDEV_NET_NS_FD, netns);
291 ret = rd_sendrecv_msg(rd, seq);
298 static int dev_set_dim_sendmsg(struct rd *rd, uint8_t dim_setting)
302 rd_prepare_msg(rd, RDMA_NLDEV_CMD_SET, &seq,
303 (NLM_F_REQUEST | NLM_F_ACK));
304 mnl_attr_put_u32(rd->nlh, RDMA_NLDEV_ATTR_DEV_INDEX, rd->dev_idx);
305 mnl_attr_put_u8(rd->nlh, RDMA_NLDEV_ATTR_DEV_DIM, dim_setting);
307 return rd_sendrecv_msg(rd, seq);
310 static int dev_set_dim_off(struct rd *rd)
312 return dev_set_dim_sendmsg(rd, 0);
315 static int dev_set_dim_on(struct rd *rd)
317 return dev_set_dim_sendmsg(rd, 1);
320 static int dev_set_dim(struct rd *rd)
322 const struct rd_cmd cmds[] = {
324 { "on", dev_set_dim_on},
325 { "off", dev_set_dim_off},
329 return rd_exec_cmd(rd, cmds, "parameter");
332 static int dev_one_set(struct rd *rd)
334 const struct rd_cmd cmds[] = {
336 { "name", dev_set_name},
337 { "netns", dev_set_netns},
338 { "adaptive-moderation", dev_set_dim},
342 return rd_exec_cmd(rd, cmds, "parameter");
345 static int dev_show(struct rd *rd)
347 return rd_exec_dev(rd, dev_one_show);
350 static int dev_set(struct rd *rd)
352 return rd_exec_require_dev(rd, dev_one_set);
355 int cmd_dev(struct rd *rd)
357 const struct rd_cmd cmds[] = {
359 { "show", dev_show },
360 { "list", dev_show },
362 { "help", dev_help },
366 return rd_exec_cmd(rd, cmds, "dev command");