4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
9 * Authors: Leon Romanovsky <leonro@mellanox.com>
15 static int res_help(struct rd
*rd
)
17 pr_out("Usage: %s resource\n", rd
->filename
);
18 pr_out(" resource show [DEV]\n");
19 pr_out(" resource show [qp|cm_id]\n");
20 pr_out(" resource show qp link [DEV/PORT]\n");
21 pr_out(" resource show qp link [DEV/PORT] [FILTER-NAME FILTER-VALUE]\n");
22 pr_out(" resource show cm_id link [DEV/PORT]\n");
23 pr_out(" resource show cm_id link [DEV/PORT] [FILTER-NAME FILTER-VALUE]\n");
27 static int res_print_summary(struct rd
*rd
, struct nlattr
**tb
)
29 struct nlattr
*nla_table
= tb
[RDMA_NLDEV_ATTR_RES_SUMMARY
];
30 struct nlattr
*nla_entry
;
35 mnl_attr_for_each_nested(nla_entry
, nla_table
) {
36 struct nlattr
*nla_line
[RDMA_NLDEV_ATTR_MAX
] = {};
39 err
= mnl_attr_parse_nested(nla_entry
, rd_attr_cb
, nla_line
);
43 if (!nla_line
[RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_NAME
] ||
44 !nla_line
[RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_CURR
]) {
48 name
= mnl_attr_get_str(nla_line
[RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_NAME
]);
49 curr
= mnl_attr_get_u64(nla_line
[RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_CURR
]);
50 if (rd
->json_output
) {
51 snprintf(json_name
, 32, "%s", name
);
52 jsonw_lluint_field(rd
->jw
, json_name
, curr
);
54 pr_out("%s %"PRId64
" ", name
, curr
);
60 static int res_no_args_parse_cb(const struct nlmsghdr
*nlh
, void *data
)
62 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
67 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
68 if (!tb
[RDMA_NLDEV_ATTR_DEV_INDEX
] ||
69 !tb
[RDMA_NLDEV_ATTR_DEV_NAME
] ||
70 !tb
[RDMA_NLDEV_ATTR_RES_SUMMARY
])
73 idx
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_DEV_INDEX
]);
74 name
= mnl_attr_get_str(tb
[RDMA_NLDEV_ATTR_DEV_NAME
]);
75 if (rd
->json_output
) {
76 jsonw_uint_field(rd
->jw
, "ifindex", idx
);
77 jsonw_string_field(rd
->jw
, "ifname", name
);
79 pr_out("%u: %s: ", idx
, name
);
82 res_print_summary(rd
, tb
);
89 static int _res_send_msg(struct rd
*rd
, uint32_t command
, mnl_cb_t callback
)
91 uint32_t flags
= NLM_F_REQUEST
| NLM_F_ACK
;
95 if (command
!= RDMA_NLDEV_CMD_RES_GET
)
98 rd_prepare_msg(rd
, command
, &seq
, flags
);
99 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
101 mnl_attr_put_u32(rd
->nlh
,
102 RDMA_NLDEV_ATTR_PORT_INDEX
, rd
->port_idx
);
104 ret
= rd_send_msg(rd
);
109 jsonw_start_object(rd
->jw
);
110 ret
= rd_recv_msg(rd
, callback
, rd
, seq
);
112 jsonw_end_object(rd
->jw
);
116 #define RES_FUNC(name, command, valid_filters, strict_port) \
117 static int _##name(struct rd *rd)\
119 return _res_send_msg(rd, command, name##_parse_cb); \
121 static int name(struct rd *rd) \
123 int ret = rd_build_filter(rd, valid_filters); \
126 if ((uintptr_t)valid_filters != (uintptr_t)NULL) { \
127 ret = rd_set_arg_to_devname(rd); \
132 return rd_exec_dev(rd, _##name); \
134 return rd_exec_link(rd, _##name, strict_port); \
137 static const char *path_mig_to_str(uint8_t idx
)
139 static const char * const path_mig_str
[] = { "MIGRATED",
142 if (idx
< ARRAY_SIZE(path_mig_str
))
143 return path_mig_str
[idx
];
147 static const char *qp_states_to_str(uint8_t idx
)
149 static const char * const qp_states_str
[] = { "RESET", "INIT",
153 if (idx
< ARRAY_SIZE(qp_states_str
))
154 return qp_states_str
[idx
];
158 static const char *qp_types_to_str(uint8_t idx
)
160 static const char * const qp_types_str
[] = { "SMI", "GSI", "RC",
161 "UC", "UD", "RAW_IPV6",
163 "UNKNOWN", "RAW_PACKET",
164 "XRC_INI", "XRC_TGT" };
166 if (idx
< ARRAY_SIZE(qp_types_str
))
167 return qp_types_str
[idx
];
171 static void print_lqpn(struct rd
*rd
, uint32_t val
)
174 jsonw_uint_field(rd
->jw
, "lqpn", val
);
176 pr_out("lqpn %u ", val
);
179 static void print_rqpn(struct rd
*rd
, uint32_t val
, struct nlattr
**nla_line
)
181 if (!nla_line
[RDMA_NLDEV_ATTR_RES_RQPN
])
185 jsonw_uint_field(rd
->jw
, "rqpn", val
);
187 pr_out("rqpn %u ", val
);
190 static void print_type(struct rd
*rd
, uint32_t val
)
193 jsonw_string_field(rd
->jw
, "type",
194 qp_types_to_str(val
));
196 pr_out("type %s ", qp_types_to_str(val
));
199 static void print_state(struct rd
*rd
, uint32_t val
)
202 jsonw_string_field(rd
->jw
, "state",
203 qp_states_to_str(val
));
205 pr_out("state %s ", qp_states_to_str(val
));
208 static void print_rqpsn(struct rd
*rd
, uint32_t val
, struct nlattr
**nla_line
)
210 if (!nla_line
[RDMA_NLDEV_ATTR_RES_RQ_PSN
])
214 jsonw_uint_field(rd
->jw
, "rq-psn", val
);
216 pr_out("rq-psn %u ", val
);
219 static void print_sqpsn(struct rd
*rd
, uint32_t val
)
222 jsonw_uint_field(rd
->jw
, "sq-psn", val
);
224 pr_out("sq-psn %u ", val
);
227 static void print_pathmig(struct rd
*rd
, uint32_t val
,
228 struct nlattr
**nla_line
)
230 if (!nla_line
[RDMA_NLDEV_ATTR_RES_PATH_MIG_STATE
])
234 jsonw_string_field(rd
->jw
,
236 path_mig_to_str(val
));
238 pr_out("path-mig-state %s ", path_mig_to_str(val
));
241 static void print_pid(struct rd
*rd
, uint32_t val
)
244 jsonw_uint_field(rd
->jw
, "pid", val
);
246 pr_out("pid %u ", val
);
249 static void print_comm(struct rd
*rd
, const char *str
,
250 struct nlattr
**nla_line
)
254 if (rd
->json_output
) {
255 /* Don't beatify output in JSON format */
256 jsonw_string_field(rd
->jw
, "comm", str
);
260 if (nla_line
[RDMA_NLDEV_ATTR_RES_PID
])
261 snprintf(tmp
, sizeof(tmp
), "%s", str
);
263 snprintf(tmp
, sizeof(tmp
), "[%s]", str
);
265 pr_out("comm %s ", tmp
);
268 static void print_link(struct rd
*rd
, uint32_t idx
, const char *name
,
269 uint32_t port
, struct nlattr
**nla_line
)
271 if (rd
->json_output
) {
272 jsonw_uint_field(rd
->jw
, "ifindex", idx
);
274 if (nla_line
[RDMA_NLDEV_ATTR_PORT_INDEX
])
275 jsonw_uint_field(rd
->jw
, "port", port
);
277 jsonw_string_field(rd
->jw
, "ifname", name
);
279 if (nla_line
[RDMA_NLDEV_ATTR_PORT_INDEX
])
280 pr_out("link %s/%u ", name
, port
);
282 pr_out("link %s/- ", name
);
286 static char *get_task_name(uint32_t pid
)
291 if (asprintf(&comm
, "/proc/%d/comm", pid
) < 0)
294 f
= fopen(comm
, "r");
299 if (fscanf(f
, "%ms\n", &comm
) != 1)
307 static int res_qp_parse_cb(const struct nlmsghdr
*nlh
, void *data
)
309 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
310 struct nlattr
*nla_table
, *nla_entry
;
311 struct rd
*rd
= data
;
315 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
316 if (!tb
[RDMA_NLDEV_ATTR_DEV_INDEX
] ||
317 !tb
[RDMA_NLDEV_ATTR_DEV_NAME
] ||
318 !tb
[RDMA_NLDEV_ATTR_RES_QP
])
321 name
= mnl_attr_get_str(tb
[RDMA_NLDEV_ATTR_DEV_NAME
]);
322 idx
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_DEV_INDEX
]);
323 nla_table
= tb
[RDMA_NLDEV_ATTR_RES_QP
];
325 mnl_attr_for_each_nested(nla_entry
, nla_table
) {
326 struct nlattr
*nla_line
[RDMA_NLDEV_ATTR_MAX
] = {};
327 uint32_t lqpn
, rqpn
= 0, rq_psn
= 0, sq_psn
;
328 uint8_t type
, state
, path_mig_state
= 0;
329 uint32_t port
= 0, pid
= 0;
333 err
= mnl_attr_parse_nested(nla_entry
, rd_attr_cb
, nla_line
);
334 if (err
!= MNL_CB_OK
)
337 if (!nla_line
[RDMA_NLDEV_ATTR_RES_LQPN
] ||
338 !nla_line
[RDMA_NLDEV_ATTR_RES_SQ_PSN
] ||
339 !nla_line
[RDMA_NLDEV_ATTR_RES_TYPE
] ||
340 !nla_line
[RDMA_NLDEV_ATTR_RES_STATE
] ||
341 (!nla_line
[RDMA_NLDEV_ATTR_RES_PID
] &&
342 !nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
])) {
346 if (nla_line
[RDMA_NLDEV_ATTR_PORT_INDEX
])
347 port
= mnl_attr_get_u32(nla_line
[RDMA_NLDEV_ATTR_PORT_INDEX
]);
349 if (port
!= rd
->port_idx
)
352 lqpn
= mnl_attr_get_u32(nla_line
[RDMA_NLDEV_ATTR_RES_LQPN
]);
353 if (rd_check_is_filtered(rd
, "lqpn", lqpn
))
356 if (nla_line
[RDMA_NLDEV_ATTR_RES_RQPN
]) {
357 rqpn
= mnl_attr_get_u32(nla_line
[RDMA_NLDEV_ATTR_RES_RQPN
]);
358 if (rd_check_is_filtered(rd
, "rqpn", rqpn
))
361 if (rd_check_is_key_exist(rd
, "rqpn"))
365 if (nla_line
[RDMA_NLDEV_ATTR_RES_RQ_PSN
]) {
366 rq_psn
= mnl_attr_get_u32(nla_line
[RDMA_NLDEV_ATTR_RES_RQ_PSN
]);
367 if (rd_check_is_filtered(rd
, "rq-psn", rq_psn
))
370 if (rd_check_is_key_exist(rd
, "rq-psn"))
374 sq_psn
= mnl_attr_get_u32(nla_line
[RDMA_NLDEV_ATTR_RES_SQ_PSN
]);
375 if (rd_check_is_filtered(rd
, "sq-psn", sq_psn
))
378 if (nla_line
[RDMA_NLDEV_ATTR_RES_PATH_MIG_STATE
]) {
379 path_mig_state
= mnl_attr_get_u8(nla_line
[RDMA_NLDEV_ATTR_RES_PATH_MIG_STATE
]);
380 if (rd_check_is_string_filtered(rd
, "path-mig-state", path_mig_to_str(path_mig_state
)))
383 if (rd_check_is_key_exist(rd
, "path-mig-state"))
387 type
= mnl_attr_get_u8(nla_line
[RDMA_NLDEV_ATTR_RES_TYPE
]);
388 if (rd_check_is_string_filtered(rd
, "type", qp_types_to_str(type
)))
391 state
= mnl_attr_get_u8(nla_line
[RDMA_NLDEV_ATTR_RES_STATE
]);
392 if (rd_check_is_string_filtered(rd
, "state", qp_states_to_str(state
)))
395 if (nla_line
[RDMA_NLDEV_ATTR_RES_PID
]) {
396 pid
= mnl_attr_get_u32(nla_line
[RDMA_NLDEV_ATTR_RES_PID
]);
397 comm
= get_task_name(pid
);
400 if (rd_check_is_filtered(rd
, "pid", pid
)) {
405 if (nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
])
406 /* discard const from mnl_attr_get_str */
407 comm
= (char *)mnl_attr_get_str(nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
]);
410 jsonw_start_array(rd
->jw
);
412 print_link(rd
, idx
, name
, port
, nla_line
);
414 print_lqpn(rd
, lqpn
);
415 print_rqpn(rd
, rqpn
, nla_line
);
417 print_type(rd
, type
);
418 print_state(rd
, state
);
420 print_rqpsn(rd
, rq_psn
, nla_line
);
421 print_sqpsn(rd
, sq_psn
);
423 print_pathmig(rd
, path_mig_state
, nla_line
);
425 print_comm(rd
, comm
, nla_line
);
427 if (nla_line
[RDMA_NLDEV_ATTR_RES_PID
])
431 jsonw_end_array(rd
->jw
);
438 static void print_qp_type(struct rd
*rd
, uint32_t val
)
441 jsonw_string_field(rd
->jw
, "qp-type",
442 qp_types_to_str(val
));
444 pr_out("qp-type %s ", qp_types_to_str(val
));
447 static const char *cm_id_state_to_str(uint8_t idx
)
449 static const char * const cm_id_states_str
[] = {
450 "IDLE", "ADDR_QUERY", "ADDR_RESOLVED", "ROUTE_QUERY",
451 "ROUTE_RESOLVED", "CONNECT", "DISCONNECT", "ADDR_BOUND",
452 "LISTEN", "DEVICE_REMOVAL", "DESTROYING" };
454 if (idx
< ARRAY_SIZE(cm_id_states_str
))
455 return cm_id_states_str
[idx
];
459 static const char *cm_id_ps_to_str(uint32_t ps
)
475 static void print_cm_id_state(struct rd
*rd
, uint8_t state
)
477 if (rd
->json_output
) {
478 jsonw_string_field(rd
->jw
, "state", cm_id_state_to_str(state
));
481 pr_out("state %s ", cm_id_state_to_str(state
));
484 static void print_ps(struct rd
*rd
, uint32_t ps
)
486 if (rd
->json_output
) {
487 jsonw_string_field(rd
->jw
, "ps", cm_id_ps_to_str(ps
));
490 pr_out("ps %s ", cm_id_ps_to_str(ps
));
493 static void print_ipaddr(struct rd
*rd
, const char *key
, char *addrstr
,
496 if (rd
->json_output
) {
497 int name_size
= INET6_ADDRSTRLEN
+strlen(":65535");
498 char json_name
[name_size
];
500 snprintf(json_name
, name_size
, "%s:%u", addrstr
, port
);
501 jsonw_string_field(rd
->jw
, key
, json_name
);
504 pr_out("%s %s:%u ", key
, addrstr
, port
);
507 static int ss_ntop(struct nlattr
*nla_line
, char *addr_str
, uint16_t *port
)
509 struct __kernel_sockaddr_storage
*addr
;
511 addr
= (struct __kernel_sockaddr_storage
*)
512 mnl_attr_get_payload(nla_line
);
513 switch (addr
->ss_family
) {
515 struct sockaddr_in
*sin
= (struct sockaddr_in
*)addr
;
517 if (!inet_ntop(AF_INET
, (const void *)&sin
->sin_addr
, addr_str
,
520 *port
= ntohs(sin
->sin_port
);
524 struct sockaddr_in6
*sin6
= (struct sockaddr_in6
*)addr
;
526 if (!inet_ntop(AF_INET6
, (const void *)&sin6
->sin6_addr
,
527 addr_str
, INET6_ADDRSTRLEN
))
529 *port
= ntohs(sin6
->sin6_port
);
538 static int res_cm_id_parse_cb(const struct nlmsghdr
*nlh
, void *data
)
540 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
541 struct nlattr
*nla_table
, *nla_entry
;
542 struct rd
*rd
= data
;
546 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
547 if (!tb
[RDMA_NLDEV_ATTR_DEV_INDEX
] ||
548 !tb
[RDMA_NLDEV_ATTR_DEV_NAME
] ||
549 !tb
[RDMA_NLDEV_ATTR_RES_CM_ID
])
552 name
= mnl_attr_get_str(tb
[RDMA_NLDEV_ATTR_DEV_NAME
]);
553 idx
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_DEV_INDEX
]);
554 nla_table
= tb
[RDMA_NLDEV_ATTR_RES_CM_ID
];
555 mnl_attr_for_each_nested(nla_entry
, nla_table
) {
556 struct nlattr
*nla_line
[RDMA_NLDEV_ATTR_MAX
] = {};
557 char src_addr_str
[INET6_ADDRSTRLEN
];
558 char dst_addr_str
[INET6_ADDRSTRLEN
];
559 uint16_t src_port
, dst_port
;
560 uint32_t port
= 0, pid
= 0;
561 uint8_t type
= 0, state
;
562 uint32_t lqpn
= 0, ps
;
566 err
= mnl_attr_parse_nested(nla_entry
, rd_attr_cb
, nla_line
);
567 if (err
!= MNL_CB_OK
)
570 if (!nla_line
[RDMA_NLDEV_ATTR_RES_STATE
] ||
571 !nla_line
[RDMA_NLDEV_ATTR_RES_PS
] ||
572 (!nla_line
[RDMA_NLDEV_ATTR_RES_PID
] &&
573 !nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
])) {
577 if (nla_line
[RDMA_NLDEV_ATTR_PORT_INDEX
])
578 port
= mnl_attr_get_u32(
579 nla_line
[RDMA_NLDEV_ATTR_PORT_INDEX
]);
581 if (port
&& port
!= rd
->port_idx
)
584 if (nla_line
[RDMA_NLDEV_ATTR_RES_LQPN
]) {
585 lqpn
= mnl_attr_get_u32(
586 nla_line
[RDMA_NLDEV_ATTR_RES_LQPN
]);
587 if (rd_check_is_filtered(rd
, "lqpn", lqpn
))
590 if (nla_line
[RDMA_NLDEV_ATTR_RES_TYPE
]) {
591 type
= mnl_attr_get_u8(
592 nla_line
[RDMA_NLDEV_ATTR_RES_TYPE
]);
593 if (rd_check_is_string_filtered(rd
, "qp-type",
594 qp_types_to_str(type
)))
598 ps
= mnl_attr_get_u32(nla_line
[RDMA_NLDEV_ATTR_RES_PS
]);
599 if (rd_check_is_string_filtered(rd
, "ps", cm_id_ps_to_str(ps
)))
602 state
= mnl_attr_get_u8(nla_line
[RDMA_NLDEV_ATTR_RES_STATE
]);
603 if (rd_check_is_string_filtered(rd
, "state",
604 cm_id_state_to_str(state
)))
607 if (nla_line
[RDMA_NLDEV_ATTR_RES_SRC_ADDR
]) {
608 if (ss_ntop(nla_line
[RDMA_NLDEV_ATTR_RES_SRC_ADDR
],
609 src_addr_str
, &src_port
))
611 if (rd_check_is_string_filtered(rd
, "src-addr",
616 if (nla_line
[RDMA_NLDEV_ATTR_RES_DST_ADDR
]) {
617 if (ss_ntop(nla_line
[RDMA_NLDEV_ATTR_RES_DST_ADDR
],
618 dst_addr_str
, &dst_port
))
620 if (rd_check_is_string_filtered(rd
, "dst-addr",
625 if (rd_check_is_filtered(rd
, "src-port", src_port
))
628 if (rd_check_is_filtered(rd
, "dst-port", dst_port
))
631 if (nla_line
[RDMA_NLDEV_ATTR_RES_PID
]) {
632 pid
= mnl_attr_get_u32(
633 nla_line
[RDMA_NLDEV_ATTR_RES_PID
]);
634 comm
= get_task_name(pid
);
637 if (rd_check_is_filtered(rd
, "pid", pid
)) {
642 if (nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
]) {
643 /* discard const from mnl_attr_get_str */
644 comm
= (char *)mnl_attr_get_str(
645 nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
]);
649 jsonw_start_array(rd
->jw
);
651 print_link(rd
, idx
, name
, port
, nla_line
);
652 if (nla_line
[RDMA_NLDEV_ATTR_RES_LQPN
])
653 print_lqpn(rd
, lqpn
);
654 if (nla_line
[RDMA_NLDEV_ATTR_RES_TYPE
])
655 print_qp_type(rd
, type
);
656 print_cm_id_state(rd
, state
);
659 print_comm(rd
, comm
, nla_line
);
661 if (nla_line
[RDMA_NLDEV_ATTR_RES_SRC_ADDR
])
662 print_ipaddr(rd
, "src-addr", src_addr_str
, src_port
);
663 if (nla_line
[RDMA_NLDEV_ATTR_RES_DST_ADDR
])
664 print_ipaddr(rd
, "dst-addr", dst_addr_str
, dst_port
);
666 if (nla_line
[RDMA_NLDEV_ATTR_RES_PID
])
670 jsonw_end_array(rd
->jw
);
677 RES_FUNC(res_no_args
, RDMA_NLDEV_CMD_RES_GET
, NULL
, true);
680 filters qp_valid_filters
[MAX_NUMBER_OF_FILTERS
] = {{ .name
= "link",
681 .is_number
= false },
693 .is_number
= false },
694 { .name
= "path-mig-state",
695 .is_number
= false },
697 .is_number
= false } };
699 RES_FUNC(res_qp
, RDMA_NLDEV_CMD_RES_QP_GET
, qp_valid_filters
, false);
702 struct filters cm_id_valid_filters
[MAX_NUMBER_OF_FILTERS
] = {
703 { .name
= "link", .is_number
= false },
704 { .name
= "lqpn", .is_number
= true },
705 { .name
= "qp-type", .is_number
= false },
706 { .name
= "state", .is_number
= false },
707 { .name
= "ps", .is_number
= false },
708 { .name
= "dev-type", .is_number
= false },
709 { .name
= "transport-type", .is_number
= false },
710 { .name
= "pid", .is_number
= true },
711 { .name
= "src-addr", .is_number
= false },
712 { .name
= "src-port", .is_number
= true },
713 { .name
= "dst-addr", .is_number
= false },
714 { .name
= "dst-port", .is_number
= true }
717 RES_FUNC(res_cm_id
, RDMA_NLDEV_CMD_RES_CM_ID_GET
, cm_id_valid_filters
, false);
719 static int res_show(struct rd
*rd
)
721 const struct rd_cmd cmds
[] = {
722 { NULL
, res_no_args
},
724 { "cm_id", res_cm_id
},
729 * Special case to support "rdma res show DEV_NAME"
731 if (rd_argc(rd
) == 1 && dev_map_lookup(rd
, false))
732 return rd_exec_dev(rd
, _res_no_args
);
734 return rd_exec_cmd(rd
, cmds
, "parameter");
737 int cmd_res(struct rd
*rd
)
739 const struct rd_cmd cmds
[] = {
741 { "show", res_show
},
742 { "list", res_show
},
743 { "help", res_help
},
747 return rd_exec_cmd(rd
, cmds
, "resource command");