]> git.proxmox.com Git - mirror_iproute2.git/blob - rdma/dev.c
rdma: Add an option to query,set net namespace sharing sys parameter
[mirror_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 "rdma.h"
8
9 static int dev_help(struct rd *rd)
10 {
11 pr_out("Usage: %s dev show [DEV]\n", rd->filename);
12 pr_out(" %s dev set [DEV] name DEVNAME\n", rd->filename);
13 return 0;
14 }
15
16 static const char *dev_caps_to_str(uint32_t idx)
17 {
18 #define RDMA_DEV_FLAGS_LOW(x) \
19 x(RESIZE_MAX_WR, 0) \
20 x(BAD_PKEY_CNTR, 1) \
21 x(BAD_QKEY_CNTR, 2) \
22 x(RAW_MULTI, 3) \
23 x(AUTO_PATH_MIG, 4) \
24 x(CHANGE_PHY_PORT, 5) \
25 x(UD_AV_PORT_ENFORCE_PORT_ENFORCE, 6) \
26 x(CURR_QP_STATE_MOD, 7) \
27 x(SHUTDOWN_PORT, 8) \
28 x(INIT_TYPE, 9) \
29 x(PORT_ACTIVE_EVENT, 10) \
30 x(SYS_IMAGE_GUID, 11) \
31 x(RC_RNR_NAK_GEN, 12) \
32 x(SRQ_RESIZE, 13) \
33 x(N_NOTIFY_CQ, 14) \
34 x(LOCAL_DMA_LKEY, 15) \
35 x(MEM_WINDOW, 17) \
36 x(UD_IP_CSUM, 18) \
37 x(UD_TSO, 19) \
38 x(XRC, 20) \
39 x(MEM_MGT_EXTENSIONS, 21) \
40 x(BLOCK_MULTICAST_LOOPBACK, 22) \
41 x(MEM_WINDOW_TYPE_2A, 23) \
42 x(MEM_WINDOW_TYPE_2B, 24) \
43 x(RC_IP_CSUM, 25) \
44 x(RAW_IP_CSUM, 26) \
45 x(CROSS_CHANNEL, 27) \
46 x(MANAGED_FLOW_STEERING, 29) \
47 x(SIGNATURE_HANDOVER, 30) \
48 x(ON_DEMAND_PAGING, 31)
49
50 #define RDMA_DEV_FLAGS_HIGH(x) \
51 x(SG_GAPS_REG, 0) \
52 x(VIRTUAL_FUNCTION, 1) \
53 x(RAW_SCATTER_FCS, 2) \
54 x(RDMA_NETDEV_OPA_VNIC, 3) \
55 x(PCI_WRITE_END_PADDING, 4)
56
57 /*
58 * Separation below is needed to allow compilation of rdmatool
59 * on 32bits systems. On such systems, C-enum is limited to be
60 * int and can't hold more than 32 bits.
61 */
62 enum { RDMA_DEV_FLAGS_LOW(RDMA_BITMAP_ENUM) };
63 enum { RDMA_DEV_FLAGS_HIGH(RDMA_BITMAP_ENUM) };
64
65 static const char * const
66 rdma_dev_names_low[] = { RDMA_DEV_FLAGS_LOW(RDMA_BITMAP_NAMES) };
67 static const char * const
68 rdma_dev_names_high[] = { RDMA_DEV_FLAGS_HIGH(RDMA_BITMAP_NAMES) };
69 uint32_t high_idx;
70 #undef RDMA_DEV_FLAGS_LOW
71 #undef RDMA_DEV_FLAGS_HIGH
72
73 if (idx < ARRAY_SIZE(rdma_dev_names_low) && rdma_dev_names_low[idx])
74 return rdma_dev_names_low[idx];
75
76 high_idx = idx - ARRAY_SIZE(rdma_dev_names_low);
77 if (high_idx < ARRAY_SIZE(rdma_dev_names_high) &&
78 rdma_dev_names_high[high_idx])
79 return rdma_dev_names_high[high_idx];
80
81 return "UNKNOWN";
82 }
83
84 static void dev_print_caps(struct rd *rd, struct nlattr **tb)
85 {
86 uint64_t caps;
87 uint32_t idx;
88
89 if (!tb[RDMA_NLDEV_ATTR_CAP_FLAGS])
90 return;
91
92 caps = mnl_attr_get_u64(tb[RDMA_NLDEV_ATTR_CAP_FLAGS]);
93
94 if (rd->json_output) {
95 jsonw_name(rd->jw, "caps");
96 jsonw_start_array(rd->jw);
97 } else {
98 pr_out("\n caps: <");
99 }
100 for (idx = 0; caps; idx++) {
101 if (caps & 0x1) {
102 if (rd->json_output) {
103 jsonw_string(rd->jw, dev_caps_to_str(idx));
104 } else {
105 pr_out("%s", dev_caps_to_str(idx));
106 if (caps >> 0x1)
107 pr_out(", ");
108 }
109 }
110 caps >>= 0x1;
111 }
112
113 if (rd->json_output)
114 jsonw_end_array(rd->jw);
115 else
116 pr_out(">");
117 }
118
119 static void dev_print_fw(struct rd *rd, struct nlattr **tb)
120 {
121 const char *str;
122 if (!tb[RDMA_NLDEV_ATTR_FW_VERSION])
123 return;
124
125 str = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_FW_VERSION]);
126 if (rd->json_output)
127 jsonw_string_field(rd->jw, "fw", str);
128 else
129 pr_out("fw %s ", str);
130 }
131
132 static void dev_print_node_guid(struct rd *rd, struct nlattr **tb)
133 {
134 uint64_t node_guid;
135 uint16_t vp[4];
136 char str[32];
137
138 if (!tb[RDMA_NLDEV_ATTR_NODE_GUID])
139 return;
140
141 node_guid = mnl_attr_get_u64(tb[RDMA_NLDEV_ATTR_NODE_GUID]);
142 memcpy(vp, &node_guid, sizeof(uint64_t));
143 snprintf(str, 32, "%04x:%04x:%04x:%04x", vp[3], vp[2], vp[1], vp[0]);
144 if (rd->json_output)
145 jsonw_string_field(rd->jw, "node_guid", str);
146 else
147 pr_out("node_guid %s ", str);
148 }
149
150 static void dev_print_sys_image_guid(struct rd *rd, struct nlattr **tb)
151 {
152 uint64_t sys_image_guid;
153 uint16_t vp[4];
154 char str[32];
155
156 if (!tb[RDMA_NLDEV_ATTR_SYS_IMAGE_GUID])
157 return;
158
159 sys_image_guid = mnl_attr_get_u64(tb[RDMA_NLDEV_ATTR_SYS_IMAGE_GUID]);
160 memcpy(vp, &sys_image_guid, sizeof(uint64_t));
161 snprintf(str, 32, "%04x:%04x:%04x:%04x", vp[3], vp[2], vp[1], vp[0]);
162 if (rd->json_output)
163 jsonw_string_field(rd->jw, "sys_image_guid", str);
164 else
165 pr_out("sys_image_guid %s ", str);
166 }
167
168 static const char *node_type_to_str(uint8_t node_type)
169 {
170 static const char * const node_type_str[] = { "unknown", "ca",
171 "switch", "router",
172 "rnic", "usnic",
173 "usnic_udp",
174 "unspecified" };
175 if (node_type < ARRAY_SIZE(node_type_str))
176 return node_type_str[node_type];
177 return "unknown";
178 }
179
180 static void dev_print_node_type(struct rd *rd, struct nlattr **tb)
181 {
182 const char *node_str;
183 uint8_t node_type;
184
185 if (!tb[RDMA_NLDEV_ATTR_DEV_NODE_TYPE])
186 return;
187
188 node_type = mnl_attr_get_u8(tb[RDMA_NLDEV_ATTR_DEV_NODE_TYPE]);
189 node_str = node_type_to_str(node_type);
190 if (rd->json_output)
191 jsonw_string_field(rd->jw, "node_type", node_str);
192 else
193 pr_out("node_type %s ", node_str);
194 }
195
196 static int dev_parse_cb(const struct nlmsghdr *nlh, void *data)
197 {
198 struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
199 struct rd *rd = data;
200 const char *name;
201 uint32_t idx;
202
203 mnl_attr_parse(nlh, 0, rd_attr_cb, tb);
204 if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME])
205 return MNL_CB_ERROR;
206
207 idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
208 name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]);
209 if (rd->json_output) {
210 jsonw_uint_field(rd->jw, "ifindex", idx);
211 jsonw_string_field(rd->jw, "ifname", name);
212 } else {
213 pr_out("%u: %s: ", idx, name);
214 }
215
216 dev_print_node_type(rd, tb);
217 dev_print_fw(rd, tb);
218 dev_print_node_guid(rd, tb);
219 dev_print_sys_image_guid(rd, tb);
220 if (rd->show_details)
221 dev_print_caps(rd, tb);
222
223 if (!rd->json_output)
224 pr_out("\n");
225 return MNL_CB_OK;
226 }
227
228 static int dev_no_args(struct rd *rd)
229 {
230 uint32_t seq;
231 int ret;
232
233 rd_prepare_msg(rd, RDMA_NLDEV_CMD_GET,
234 &seq, (NLM_F_REQUEST | NLM_F_ACK));
235 mnl_attr_put_u32(rd->nlh, RDMA_NLDEV_ATTR_DEV_INDEX, rd->dev_idx);
236 ret = rd_send_msg(rd);
237 if (ret)
238 return ret;
239
240 if (rd->json_output)
241 jsonw_start_object(rd->jw);
242 ret = rd_recv_msg(rd, dev_parse_cb, rd, seq);
243 if (rd->json_output)
244 jsonw_end_object(rd->jw);
245 return ret;
246 }
247
248 static int dev_one_show(struct rd *rd)
249 {
250 const struct rd_cmd cmds[] = {
251 { NULL, dev_no_args},
252 { 0 }
253 };
254
255 return rd_exec_cmd(rd, cmds, "parameter");
256 }
257
258 static int dev_set_name(struct rd *rd)
259 {
260 uint32_t seq;
261
262 if (rd_no_arg(rd)) {
263 pr_err("Please provide device new name.\n");
264 return -EINVAL;
265 }
266
267 rd_prepare_msg(rd, RDMA_NLDEV_CMD_SET,
268 &seq, (NLM_F_REQUEST | NLM_F_ACK));
269 mnl_attr_put_u32(rd->nlh, RDMA_NLDEV_ATTR_DEV_INDEX, rd->dev_idx);
270 mnl_attr_put_strz(rd->nlh, RDMA_NLDEV_ATTR_DEV_NAME, rd_argv(rd));
271
272 return rd_sendrecv_msg(rd, seq);
273 }
274
275 static int dev_one_set(struct rd *rd)
276 {
277 const struct rd_cmd cmds[] = {
278 { NULL, dev_help},
279 { "name", dev_set_name},
280 { 0 }
281 };
282
283 return rd_exec_cmd(rd, cmds, "parameter");
284 }
285
286 static int dev_show(struct rd *rd)
287 {
288 return rd_exec_dev(rd, dev_one_show);
289 }
290
291 static int dev_set(struct rd *rd)
292 {
293 return rd_exec_require_dev(rd, dev_one_set);
294 }
295
296 int cmd_dev(struct rd *rd)
297 {
298 const struct rd_cmd cmds[] = {
299 { NULL, dev_show },
300 { "show", dev_show },
301 { "list", dev_show },
302 { "set", dev_set },
303 { "help", dev_help },
304 { 0 }
305 };
306
307 return rd_exec_cmd(rd, cmds, "dev command");
308 }