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 if (rd
->json_output
) {
98 jsonw_name(rd
->jw
, "caps");
99 jsonw_start_array(rd
->jw
);
101 pr_out("\n caps: <");
103 for (idx
= 0; caps
; idx
++) {
105 if (rd
->json_output
) {
106 jsonw_string(rd
->jw
, dev_caps_to_str(idx
));
108 pr_out("%s", dev_caps_to_str(idx
));
117 jsonw_end_array(rd
->jw
);
122 static void dev_print_fw(struct rd
*rd
, struct nlattr
**tb
)
125 if (!tb
[RDMA_NLDEV_ATTR_FW_VERSION
])
128 str
= mnl_attr_get_str(tb
[RDMA_NLDEV_ATTR_FW_VERSION
]);
130 jsonw_string_field(rd
->jw
, "fw", str
);
132 pr_out("fw %s ", str
);
135 static void dev_print_node_guid(struct rd
*rd
, struct nlattr
**tb
)
141 if (!tb
[RDMA_NLDEV_ATTR_NODE_GUID
])
144 node_guid
= mnl_attr_get_u64(tb
[RDMA_NLDEV_ATTR_NODE_GUID
]);
145 memcpy(vp
, &node_guid
, sizeof(uint64_t));
146 snprintf(str
, 32, "%04x:%04x:%04x:%04x", vp
[3], vp
[2], vp
[1], vp
[0]);
148 jsonw_string_field(rd
->jw
, "node_guid", str
);
150 pr_out("node_guid %s ", str
);
153 static void dev_print_sys_image_guid(struct rd
*rd
, struct nlattr
**tb
)
155 uint64_t sys_image_guid
;
159 if (!tb
[RDMA_NLDEV_ATTR_SYS_IMAGE_GUID
])
162 sys_image_guid
= mnl_attr_get_u64(tb
[RDMA_NLDEV_ATTR_SYS_IMAGE_GUID
]);
163 memcpy(vp
, &sys_image_guid
, sizeof(uint64_t));
164 snprintf(str
, 32, "%04x:%04x:%04x:%04x", vp
[3], vp
[2], vp
[1], vp
[0]);
166 jsonw_string_field(rd
->jw
, "sys_image_guid", str
);
168 pr_out("sys_image_guid %s ", str
);
171 static void dev_print_dim_setting(struct rd
*rd
, struct nlattr
**tb
)
175 if (!tb
[RDMA_NLDEV_ATTR_DEV_DIM
])
178 dim_setting
= mnl_attr_get_u8(tb
[RDMA_NLDEV_ATTR_DEV_DIM
]);
182 print_on_off(rd
, "adaptive-moderation", dim_setting
);
186 static const char *node_type_to_str(uint8_t node_type
)
188 static const char * const node_type_str
[] = { "unknown", "ca",
193 if (node_type
< ARRAY_SIZE(node_type_str
))
194 return node_type_str
[node_type
];
198 static void dev_print_node_type(struct rd
*rd
, struct nlattr
**tb
)
200 const char *node_str
;
203 if (!tb
[RDMA_NLDEV_ATTR_DEV_NODE_TYPE
])
206 node_type
= mnl_attr_get_u8(tb
[RDMA_NLDEV_ATTR_DEV_NODE_TYPE
]);
207 node_str
= node_type_to_str(node_type
);
209 jsonw_string_field(rd
->jw
, "node_type", node_str
);
211 pr_out("node_type %s ", node_str
);
214 static int dev_parse_cb(const struct nlmsghdr
*nlh
, void *data
)
216 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
217 struct rd
*rd
= data
;
221 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
222 if (!tb
[RDMA_NLDEV_ATTR_DEV_INDEX
] || !tb
[RDMA_NLDEV_ATTR_DEV_NAME
])
225 idx
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_DEV_INDEX
]);
226 name
= mnl_attr_get_str(tb
[RDMA_NLDEV_ATTR_DEV_NAME
]);
227 if (rd
->json_output
) {
228 jsonw_uint_field(rd
->jw
, "ifindex", idx
);
229 jsonw_string_field(rd
->jw
, "ifname", name
);
231 pr_out("%u: %s: ", idx
, name
);
234 dev_print_node_type(rd
, tb
);
235 dev_print_fw(rd
, tb
);
236 dev_print_node_guid(rd
, tb
);
237 dev_print_sys_image_guid(rd
, tb
);
238 if (rd
->show_details
) {
239 dev_print_dim_setting(rd
, tb
);
240 dev_print_caps(rd
, tb
);
243 if (!rd
->json_output
)
248 static int dev_no_args(struct rd
*rd
)
253 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_GET
,
254 &seq
, (NLM_F_REQUEST
| NLM_F_ACK
));
255 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
256 ret
= rd_send_msg(rd
);
261 jsonw_start_object(rd
->jw
);
262 ret
= rd_recv_msg(rd
, dev_parse_cb
, rd
, seq
);
264 jsonw_end_object(rd
->jw
);
268 static int dev_one_show(struct rd
*rd
)
270 const struct rd_cmd cmds
[] = {
271 { NULL
, dev_no_args
},
275 return rd_exec_cmd(rd
, cmds
, "parameter");
278 static int dev_set_name(struct rd
*rd
)
283 pr_err("Please provide device new name.\n");
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_strz(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_NAME
, rd_argv(rd
));
292 return rd_sendrecv_msg(rd
, seq
);
295 static int dev_set_netns(struct rd
*rd
)
303 pr_err("Please provide device name.\n");
307 if (asprintf(&netns_path
, "%s/%s", NETNS_RUN_DIR
, rd_argv(rd
)) < 0)
310 netns
= open(netns_path
, O_RDONLY
| O_CLOEXEC
);
312 fprintf(stderr
, "Cannot open network namespace \"%s\": %s\n",
313 rd_argv(rd
), strerror(errno
));
318 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_SET
,
319 &seq
, (NLM_F_REQUEST
| NLM_F_ACK
));
320 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
321 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_NET_NS_FD
, netns
);
322 ret
= rd_sendrecv_msg(rd
, seq
);
329 static int dev_set_dim_sendmsg(struct rd
*rd
, uint8_t dim_setting
)
333 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_SET
, &seq
,
334 (NLM_F_REQUEST
| NLM_F_ACK
));
335 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
336 mnl_attr_put_u8(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_DIM
, dim_setting
);
338 return rd_sendrecv_msg(rd
, seq
);
341 static int dev_set_dim_off(struct rd
*rd
)
343 return dev_set_dim_sendmsg(rd
, 0);
346 static int dev_set_dim_on(struct rd
*rd
)
348 return dev_set_dim_sendmsg(rd
, 1);
351 static int dev_set_dim(struct rd
*rd
)
353 const struct rd_cmd cmds
[] = {
355 { "on", dev_set_dim_on
},
356 { "off", dev_set_dim_off
},
360 return rd_exec_cmd(rd
, cmds
, "parameter");
363 static int dev_one_set(struct rd
*rd
)
365 const struct rd_cmd cmds
[] = {
367 { "name", dev_set_name
},
368 { "netns", dev_set_netns
},
369 { "adaptive-moderation", dev_set_dim
},
373 return rd_exec_cmd(rd
, cmds
, "parameter");
376 static int dev_show(struct rd
*rd
)
378 return rd_exec_dev(rd
, dev_one_show
);
381 static int dev_set(struct rd
*rd
)
383 return rd_exec_require_dev(rd
, dev_one_set
);
386 int cmd_dev(struct rd
*rd
)
388 const struct rd_cmd cmds
[] = {
390 { "show", dev_show
},
391 { "list", dev_show
},
393 { "help", dev_help
},
397 return rd_exec_cmd(rd
, cmds
, "dev command");