Fix build break in 64bit architectures
[platform/upstream/iproute2.git] / rdma / dev.c
1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 /*
3  * dev.c        RDMA tool
4  * Authors:     Leon Romanovsky <leonro@mellanox.com>
5  */
6
7 #include <fcntl.h>
8 #include "rdma.h"
9
10 static int dev_help(struct rd *rd)
11 {
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);
16         return 0;
17 }
18
19 static const char *dev_caps_to_str(uint32_t idx)
20 {
21 #define RDMA_DEV_FLAGS_LOW(x) \
22         x(RESIZE_MAX_WR, 0) \
23         x(BAD_PKEY_CNTR, 1) \
24         x(BAD_QKEY_CNTR, 2) \
25         x(RAW_MULTI, 3) \
26         x(AUTO_PATH_MIG, 4) \
27         x(CHANGE_PHY_PORT, 5) \
28         x(UD_AV_PORT_ENFORCE_PORT_ENFORCE, 6) \
29         x(CURR_QP_STATE_MOD, 7) \
30         x(SHUTDOWN_PORT, 8) \
31         x(INIT_TYPE, 9) \
32         x(PORT_ACTIVE_EVENT, 10) \
33         x(SYS_IMAGE_GUID, 11) \
34         x(RC_RNR_NAK_GEN, 12) \
35         x(SRQ_RESIZE, 13) \
36         x(N_NOTIFY_CQ, 14) \
37         x(LOCAL_DMA_LKEY, 15) \
38         x(MEM_WINDOW, 17) \
39         x(UD_IP_CSUM, 18) \
40         x(UD_TSO, 19) \
41         x(XRC, 20) \
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) \
46         x(RC_IP_CSUM, 25) \
47         x(RAW_IP_CSUM, 26) \
48         x(CROSS_CHANNEL, 27) \
49         x(MANAGED_FLOW_STEERING, 29) \
50         x(SIGNATURE_HANDOVER, 30) \
51         x(ON_DEMAND_PAGING, 31)
52
53 #define RDMA_DEV_FLAGS_HIGH(x) \
54         x(SG_GAPS_REG, 0) \
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)
59
60         /*
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.
64          */
65         enum { RDMA_DEV_FLAGS_LOW(RDMA_BITMAP_ENUM) };
66         enum { RDMA_DEV_FLAGS_HIGH(RDMA_BITMAP_ENUM) };
67
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) };
72         uint32_t high_idx;
73         #undef RDMA_DEV_FLAGS_LOW
74         #undef RDMA_DEV_FLAGS_HIGH
75
76         if (idx < ARRAY_SIZE(rdma_dev_names_low) && rdma_dev_names_low[idx])
77                 return rdma_dev_names_low[idx];
78
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];
83
84         return "UNKNOWN";
85 }
86
87 static void dev_print_caps(struct rd *rd, struct nlattr **tb)
88 {
89         uint64_t caps;
90         uint32_t idx;
91
92         if (!tb[RDMA_NLDEV_ATTR_CAP_FLAGS])
93                 return;
94
95         caps = mnl_attr_get_u64(tb[RDMA_NLDEV_ATTR_CAP_FLAGS]);
96
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++) {
100                 if (caps & 0x1)
101                         print_color_string(PRINT_ANY, COLOR_NONE, NULL,
102                                            caps >> 0x1 ? "%s, " : "%s",
103                                            dev_caps_to_str(idx));
104                 caps >>= 0x1;
105         }
106         close_json_array(PRINT_ANY, ">");
107 }
108
109 static void dev_print_fw(struct rd *rd, struct nlattr **tb)
110 {
111         const char *str;
112         if (!tb[RDMA_NLDEV_ATTR_FW_VERSION])
113                 return;
114
115         str = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_FW_VERSION]);
116         print_color_string(PRINT_ANY, COLOR_NONE, "fw", "fw %s ", str);
117 }
118
119 static void dev_print_node_guid(struct rd *rd, struct nlattr **tb)
120 {
121         uint64_t node_guid;
122         uint16_t vp[4];
123         char str[32];
124
125         if (!tb[RDMA_NLDEV_ATTR_NODE_GUID])
126                 return;
127
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 ",
132                            str);
133 }
134
135 static void dev_print_sys_image_guid(struct rd *rd, struct nlattr **tb)
136 {
137         uint64_t sys_image_guid;
138         uint16_t vp[4];
139         char str[32];
140
141         if (!tb[RDMA_NLDEV_ATTR_SYS_IMAGE_GUID])
142                 return;
143
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);
149 }
150
151 static void dev_print_dim_setting(struct rd *rd, struct nlattr **tb)
152 {
153         uint8_t dim_setting;
154
155         if (!tb[RDMA_NLDEV_ATTR_DEV_DIM])
156                 return;
157
158         dim_setting = mnl_attr_get_u8(tb[RDMA_NLDEV_ATTR_DEV_DIM]);
159         if (dim_setting > 1)
160                 return;
161
162         print_on_off(rd, "adaptive-moderation", dim_setting);
163
164 }
165
166 static const char *node_type_to_str(uint8_t node_type)
167 {
168         static const char * const node_type_str[] = { "unknown", "ca",
169                                                       "switch", "router",
170                                                       "rnic", "usnic",
171                                                       "usnic_udp",
172                                                       "unspecified" };
173         if (node_type < ARRAY_SIZE(node_type_str))
174                 return node_type_str[node_type];
175         return "unknown";
176 }
177
178 static void dev_print_node_type(struct rd *rd, struct nlattr **tb)
179 {
180         const char *node_str;
181         uint8_t node_type;
182
183         if (!tb[RDMA_NLDEV_ATTR_DEV_NODE_TYPE])
184                 return;
185
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 ",
189                            node_str);
190 }
191
192 static int dev_parse_cb(const struct nlmsghdr *nlh, void *data)
193 {
194         struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
195         struct rd *rd = data;
196         const char *name;
197         uint32_t idx;
198
199         mnl_attr_parse(nlh, 0, rd_attr_cb, tb);
200         if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME])
201                 return MNL_CB_ERROR;
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);
207
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);
215         }
216
217         newline(rd);
218         return MNL_CB_OK;
219 }
220
221 static int dev_no_args(struct rd *rd)
222 {
223         uint32_t seq;
224         int ret;
225
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);
230         if (ret)
231                 return ret;
232
233         ret = rd_recv_msg(rd, dev_parse_cb, rd, seq);
234         return ret;
235 }
236
237 static int dev_one_show(struct rd *rd)
238 {
239         const struct rd_cmd cmds[] = {
240                 { NULL,         dev_no_args},
241                 { 0 }
242         };
243
244         return rd_exec_cmd(rd, cmds, "parameter");
245 }
246
247 static int dev_set_name(struct rd *rd)
248 {
249         uint32_t seq;
250
251         if (rd_no_arg(rd)) {
252                 pr_err("Please provide device new name.\n");
253                 return -EINVAL;
254         }
255
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));
260
261         return rd_sendrecv_msg(rd, seq);
262 }
263
264 static int dev_set_netns(struct rd *rd)
265 {
266         char *netns_path;
267         uint32_t seq;
268         int netns;
269         int ret;
270
271         if (rd_no_arg(rd)) {
272                 pr_err("Please provide device name.\n");
273                 return -EINVAL;
274         }
275
276         if (asprintf(&netns_path, "%s/%s", NETNS_RUN_DIR, rd_argv(rd)) < 0)
277                 return -ENOMEM;
278
279         netns = open(netns_path, O_RDONLY | O_CLOEXEC);
280         if (netns < 0) {
281                 fprintf(stderr, "Cannot open network namespace \"%s\": %s\n",
282                         rd_argv(rd), strerror(errno));
283                 ret = -EINVAL;
284                 goto done;
285         }
286
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);
292         close(netns);
293 done:
294         free(netns_path);
295         return ret;
296 }
297
298 static int dev_set_dim_sendmsg(struct rd *rd, uint8_t dim_setting)
299 {
300         uint32_t seq;
301
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);
306
307         return rd_sendrecv_msg(rd, seq);
308 }
309
310 static int dev_set_dim_off(struct rd *rd)
311 {
312         return dev_set_dim_sendmsg(rd, 0);
313 }
314
315 static int dev_set_dim_on(struct rd *rd)
316 {
317         return dev_set_dim_sendmsg(rd, 1);
318 }
319
320 static int dev_set_dim(struct rd *rd)
321 {
322         const struct rd_cmd cmds[] = {
323                 { NULL,         dev_help},
324                 { "on",         dev_set_dim_on},
325                 { "off",        dev_set_dim_off},
326                 { 0 }
327         };
328
329         return rd_exec_cmd(rd, cmds, "parameter");
330 }
331
332 static int dev_one_set(struct rd *rd)
333 {
334         const struct rd_cmd cmds[] = {
335                 { NULL,         dev_help},
336                 { "name",       dev_set_name},
337                 { "netns",      dev_set_netns},
338                 { "adaptive-moderation",        dev_set_dim},
339                 { 0 }
340         };
341
342         return rd_exec_cmd(rd, cmds, "parameter");
343 }
344
345 static int dev_show(struct rd *rd)
346 {
347         return rd_exec_dev(rd, dev_one_show);
348 }
349
350 static int dev_set(struct rd *rd)
351 {
352         return rd_exec_require_dev(rd, dev_one_set);
353 }
354
355 int cmd_dev(struct rd *rd)
356 {
357         const struct rd_cmd cmds[] = {
358                 { NULL,         dev_show },
359                 { "show",       dev_show },
360                 { "list",       dev_show },
361                 { "set",        dev_set },
362                 { "help",       dev_help },
363                 { 0 }
364         };
365
366         return rd_exec_cmd(rd, cmds, "dev command");
367 }