4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as
8 * published by the Free Software Foundation; either version 2.1 of the
9 * License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
21 * Copyright (c) 2014, 2017, Intel Corporation.
24 * Amir Shehata <amir.shehata@intel.com>
29 * 1. APIs that take the actual parameters expanded. This is for other
30 * entities that would like to link against the library and call the APIs
31 * directly without having to form an intermediate representation.
32 * 2. APIs that take a YAML file and parses out the information there and
33 * calls the APIs mentioned in 1
44 #include <sys/ioctl.h>
46 #include <libcfs/util/ioctl.h>
47 #include <libcfs/util/hash.h>
48 #include <linux/lnet/lnetctl.h>
50 #include <sys/types.h>
54 #include <rdma/rdma_user_cm.h>
55 #include "liblnetconfig.h"
57 #include <libcfs/util/param.h>
59 #ifndef HAVE_USRSPC_RDMA_PS_TCP
60 #define RDMA_PS_TCP 0x0106
63 #define cxi_nic_addr_path "/sys/class/cxi/cxi%u/device/properties/"
64 const char *gmsg_stat_names[] = {"sent_stats", "received_stats",
68 * lustre_lnet_ip_range_descr
69 * Describes an IP range.
70 * Each octect is an expression
72 struct lustre_lnet_ip_range_descr {
73 struct list_head ipr_entry;
74 struct list_head ipr_expr;
79 * Describes an ip2nets rule. This can be on a list of rules.
81 struct lustre_lnet_ip2nets {
82 struct lnet_dlc_network_descr ip2nets_net;
83 struct list_head ip2nets_ip_ranges;
86 static int open_sysfs_file(const char *path, const char *attr, const int mode)
89 char filename[LNET_MAX_STR_LEN];
90 size_t size = sizeof(filename);
93 namelen = snprintf(filename, size, "%s%s", path, attr);
95 filename[size - 1] = '\0';
97 fd = open(filename, mode);
102 static int read_sysfs_file(const char *path, const char *attr,
103 void *val, const size_t size, const int nelem)
106 int rc = LUSTRE_CFG_RC_GENERIC_ERR;
108 fd = open_sysfs_file(path, attr, O_RDONLY);
110 return LUSTRE_CFG_RC_NO_MATCH;
112 if (read(fd, val, size * nelem) == -1)
115 rc = LUSTRE_CFG_RC_NO_ERR;
122 static int write_sysfs_file(const char *path, const char *attr,
123 void *val, const size_t size, const int nelem)
126 int rc = LUSTRE_CFG_RC_GENERIC_ERR;
128 fd = open_sysfs_file(path, attr, O_WRONLY | O_TRUNC);
130 return LUSTRE_CFG_RC_NO_MATCH;
132 if (write(fd, val, size * nelem) == -1)
135 rc = LUSTRE_CFG_RC_NO_ERR;
144 * frees the memory allocated for an intf descriptor.
146 static void free_intf_descr(struct lnet_dlc_intf_descr *intf_descr)
151 if (intf_descr->cpt_expr != NULL)
152 cfs_expr_list_free(intf_descr->cpt_expr);
157 * lustre_lnet_add_ip_range
159 * given a string of the format:
160 * <expr.expr.expr.expr> parse each expr into
161 * a lustre_lnet_ip_range_descr structure and insert on the list.
163 * This function is called from
164 * YAML on each ip-range.
165 * As a result of lnetctl command
166 * When building a NID or P2P selection rules
168 static int lustre_lnet_add_ip_range(struct list_head *list, char *str_ip_range)
170 struct lustre_lnet_ip_range_descr *ip_range;
173 ip_range = calloc(1, sizeof(*ip_range));
174 if (ip_range == NULL)
175 return LUSTRE_CFG_RC_OUT_OF_MEM;
177 INIT_LIST_HEAD(&ip_range->ipr_entry);
178 INIT_LIST_HEAD(&ip_range->ipr_expr);
180 rc = cfs_ip_addr_parse(str_ip_range, strlen(str_ip_range),
181 &ip_range->ipr_expr);
183 return LUSTRE_CFG_RC_BAD_PARAM;
185 list_add_tail(&ip_range->ipr_entry, list);
187 return LUSTRE_CFG_RC_NO_ERR;
190 static int lustre_lnet_add_intf_descr(struct list_head *list, char *intf,
193 char *open_sq_bracket = NULL, *close_sq_bracket = NULL,
195 struct lnet_dlc_intf_descr *intf_descr = NULL;
197 char intf_string[LNET_MAX_STR_LEN];
199 if (len >= LNET_MAX_STR_LEN)
200 return LUSTRE_CFG_RC_BAD_PARAM;
202 strncpy(intf_string, intf, len);
203 intf_string[len] = '\0';
205 intf_descr = calloc(1, sizeof(*intf_descr));
206 if (intf_descr == NULL)
207 return LUSTRE_CFG_RC_OUT_OF_MEM;
209 INIT_LIST_HEAD(&intf_descr->intf_on_network);
211 intf_name = intf_string;
212 open_sq_bracket = strchr(intf_string, '[');
213 if (open_sq_bracket != NULL) {
214 close_sq_bracket = strchr(intf_string, ']');
215 if (close_sq_bracket == NULL) {
217 return LUSTRE_CFG_RC_BAD_PARAM;
219 rc = cfs_expr_list_parse(open_sq_bracket,
220 strlen(open_sq_bracket), 0, UINT_MAX,
221 &intf_descr->cpt_expr);
224 return LUSTRE_CFG_RC_BAD_PARAM;
226 strncpy(intf_descr->intf_name, intf_name,
227 open_sq_bracket - intf_name);
228 intf_descr->intf_name[open_sq_bracket - intf_name] = '\0';
230 strcpy(intf_descr->intf_name, intf_name);
231 intf_descr->cpt_expr = NULL;
234 list_add_tail(&intf_descr->intf_on_network, list);
236 return LUSTRE_CFG_RC_NO_ERR;
239 void lustre_lnet_init_nw_descr(struct lnet_dlc_network_descr *nw_descr)
241 if (nw_descr != NULL) {
243 INIT_LIST_HEAD(&nw_descr->network_on_rule);
244 INIT_LIST_HEAD(&nw_descr->nw_intflist);
248 int lustre_lnet_parse_nidstr(char *nidstr, lnet_nid_t *lnet_nidlist,
249 int max_nids, char *err_str)
251 int rc, num_nids = 0;
252 struct list_head nidlist;
255 snprintf(err_str, LNET_MAX_STR_LEN, "supplied nidstr is NULL");
256 return LUSTRE_CFG_RC_BAD_PARAM;
259 if (strchr(nidstr, '*')) {
260 snprintf(err_str, LNET_MAX_STR_LEN,
261 "asterisk not allowed in nidstring \"%s\"", nidstr);
262 return LUSTRE_CFG_RC_BAD_PARAM;
265 INIT_LIST_HEAD(&nidlist);
266 rc = cfs_parse_nidlist(nidstr, strlen(nidstr), &nidlist);
268 snprintf(err_str, LNET_MAX_STR_LEN,
269 "Unable to parse nidlist from: %s\n", nidstr);
270 return LUSTRE_CFG_RC_BAD_PARAM;
273 if (list_empty(&nidlist)) {
274 snprintf(err_str, LNET_MAX_STR_LEN,
275 "\"%s\" does not specify any valid nid lists", nidstr);
276 return LUSTRE_CFG_RC_BAD_PARAM;
279 num_nids = cfs_expand_nidlist(&nidlist, lnet_nidlist, max_nids);
280 cfs_free_nidlist(&nidlist);
282 if (num_nids == -1) {
283 snprintf(err_str, LNET_MAX_STR_LEN,
284 "\"%s\" specifies more than the %d NIDs allowed by this operation.",
286 return LUSTRE_CFG_RC_BAD_PARAM;
290 snprintf(err_str, LNET_MAX_STR_LEN,
291 "Failed to expand nidstr: %s", strerror(num_nids));
292 return LUSTRE_CFG_RC_OUT_OF_MEM;
296 snprintf(err_str, LNET_MAX_STR_LEN,
297 "\"%s\" did not expand to any nids", nidstr);
298 return LUSTRE_CFG_RC_BAD_PARAM;
306 * <intf>[<expr>], <intf>[<expr>],..
308 int lustre_lnet_parse_interfaces(char *intf_str,
309 struct lnet_dlc_network_descr *nw_descr)
314 char *cur = intf_str, *next = NULL;
315 char *end = intf_str + strlen(intf_str);
317 struct lnet_dlc_intf_descr *intf_descr, *tmp;
319 if (nw_descr == NULL)
320 return LUSTRE_CFG_RC_BAD_PARAM;
325 open_square = strchr(cur, '[');
326 if (open_square != NULL) {
327 close_square = strchr(cur, ']');
328 if (close_square == NULL) {
329 rc = LUSTRE_CFG_RC_BAD_PARAM;
333 comma = strchr(cur, ',');
334 if (comma != NULL && comma > close_square) {
336 len = next - close_square;
342 comma = strchr(cur, ',');
352 /* Extract net id if its a NID string */
353 net = strchr(cur, '@');
355 nw_descr->nw_id = libcfs_str2net(net + 1);
356 rc = lustre_lnet_add_intf_descr(&nw_descr->nw_intflist, cur, len);
357 if (rc != LUSTRE_CFG_RC_NO_ERR)
363 return LUSTRE_CFG_RC_NO_ERR;
366 list_for_each_entry_safe(intf_descr, tmp, &nw_descr->nw_intflist,
368 list_del(&intf_descr->intf_on_network);
369 free_intf_descr(intf_descr);
375 int lustre_lnet_config_lib_init(void)
377 return register_ioc_dev(LNET_DEV_ID, LNET_DEV_PATH);
380 void lustre_lnet_config_lib_uninit(void)
382 unregister_ioc_dev(LNET_DEV_ID);
385 int lustre_lnet_config_ni_system(bool up, bool load_ni_from_mod,
386 int seq_no, struct cYAML **err_rc)
388 struct libcfs_ioctl_data data;
391 char err_str[LNET_MAX_STR_LEN] = "\"Success\"";
393 LIBCFS_IOC_INIT(data);
395 /* Reverse logic is used here in order not to change
396 * the lctl utility */
397 data.ioc_flags = load_ni_from_mod ? 0 : 1;
399 opc = up ? IOC_LIBCFS_CONFIGURE : IOC_LIBCFS_UNCONFIGURE;
401 rc = l_ioctl(LNET_DEV_ID, opc, &data);
405 "\"LNet %s error: %s\"", (up) ? "configure" :
406 "unconfigure", strerror(errno));
410 cYAML_build_error(rc, seq_no, (up) ? CONFIG_CMD : UNCONFIG_CMD,
411 "lnet", err_str, err_rc);
416 int yaml_lnet_configure(int flags, const char **msg)
418 char *err = "lnet configure: ";
419 yaml_parser_t setup, reply;
420 char *config = "net:\n";
421 yaml_document_t results;
422 yaml_emitter_t request;
426 /* Initialize configuration parser */
427 rc = yaml_parser_initialize(&setup);
429 yaml_parser_log_error(&setup, stderr, err);
430 yaml_parser_delete(&setup);
434 yaml_parser_set_input_string(&setup, (unsigned char *)config,
436 rc = yaml_parser_load(&setup, &results);
438 yaml_parser_log_error(&setup, stderr, err);
439 yaml_parser_delete(&setup);
442 yaml_parser_delete(&setup);
444 /* Create Netlink emitter to send request to kernel */
445 sk = nl_socket_alloc();
447 yaml_document_delete(&results);
451 /* Setup parser to recieve Netlink packets */
452 rc = yaml_parser_initialize(&reply);
454 yaml_document_delete(&results);
459 rc = yaml_parser_set_input_netlink(&reply, sk, false);
463 yaml_emitter_initialize(&request);
464 rc = yaml_emitter_set_output_netlink(&request, sk, LNET_GENL_NAME,
466 LNET_CMD_CONFIGURE, flags);
467 if (rc == 1) /* 1 is success */
468 rc = yaml_emitter_dump(&request, &results);
470 yaml_emitter_log_error(&request, stderr);
473 yaml_document_t errmsg;
475 rc = yaml_parser_load(&reply, &errmsg);
477 yaml_emitter_delete(&request);
480 *msg = yaml_parser_get_reader_error(&reply);
484 yaml_parser_delete(&reply);
485 yaml_document_delete(&results);
488 return rc == 1 ? 0 : rc;
491 static int dispatch_peer_ni_cmd(__u32 cmd, struct lnet_ioctl_peer_cfg *data,
492 char *err_str, char *cmd_str)
496 rc = l_ioctl(LNET_DEV_ID, cmd, data);
499 snprintf(err_str, LNET_MAX_STR_LEN,
500 "\"%s peer ni operation failed: %s\"",
501 cmd_str, strerror(errno));
507 static int infra_ping_nid(char *ping_nids, char *src_nidstr, char *oper,
508 int param, int ioc_call, int seq_no,
509 struct cYAML **show_rc, struct cYAML **err_rc)
512 struct lnet_ioctl_ping_data ping;
513 struct cYAML *root = NULL, *ping_node = NULL, *item = NULL,
514 *first_seq = NULL, *tmp = NULL, *peer_ni = NULL;
515 struct lnet_process_id id;
516 char err_str[LNET_MAX_STR_LEN] = {0};
517 char *sep, *token, *end;
520 int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
525 len = (sizeof(struct lnet_process_id) * LNET_INTERFACES_MAX_DEFAULT);
527 data = calloc(1, len);
531 /* create struct cYAML root object */
532 root = cYAML_create_object(NULL, NULL);
536 ping_node = cYAML_create_seq(root, oper);
537 if (ping_node == NULL)
541 src = libcfs_str2nid(src_nidstr);
542 if (src == LNET_NID_ANY) {
543 snprintf(err_str, sizeof(err_str),
544 "\"cannot parse source NID '%s'\"",
546 rc = LUSTRE_CFG_RC_BAD_PARAM;
547 cYAML_build_error(rc, seq_no, MANAGE_CMD,
548 oper, err_str, err_rc);
555 /* tokenise each nid in string ping_nids */
556 token = strtok(ping_nids, ",");
559 item = cYAML_create_seq_item(ping_node);
563 if (first_seq == NULL)
566 /* check if '-' is a part of NID, token */
567 sep = strchr(token, '-');
569 id.pid = LNET_PID_ANY;
570 /* if no net is specified, libcfs_str2nid() will assume tcp */
571 id.nid = libcfs_str2nid(token);
572 if (id.nid == LNET_NID_ANY) {
573 snprintf(err_str, sizeof(err_str),
574 "\"cannot parse NID '%s'\"",
576 rc = LUSTRE_CFG_RC_BAD_PARAM;
577 cYAML_build_error(rc, seq_no, MANAGE_CMD,
578 oper, err_str, err_rc);
582 if (token[0] == 'u' || token[0] == 'U')
583 id.pid = (strtoul(&token[1], &end, 0) |
584 (LNET_PID_USERFLAG));
586 id.pid = strtoul(token, &end, 0);
588 /* assuming '-' is part of hostname */
590 id.pid = LNET_PID_ANY;
591 id.nid = libcfs_str2nid(token);
592 if (id.nid == LNET_NID_ANY) {
593 snprintf(err_str, sizeof(err_str),
594 "\"cannot parse NID '%s'\"",
596 rc = LUSTRE_CFG_RC_BAD_PARAM;
597 cYAML_build_error(rc, seq_no, MANAGE_CMD,
603 id.nid = libcfs_str2nid(sep + 1);
604 if (id.nid == LNET_NID_ANY) {
605 snprintf(err_str, sizeof(err_str),
606 "\"cannot parse NID '%s'\"",
608 rc = LUSTRE_CFG_RC_BAD_PARAM;
609 cYAML_build_error(rc, seq_no, MANAGE_CMD,
616 LIBCFS_IOC_INIT_V2(ping, ping_hdr);
617 ping.ping_hdr.ioc_len = sizeof(ping);
620 ping.op_param = param;
621 ping.ping_count = LNET_INTERFACES_MAX_DEFAULT;
622 ping.ping_buf = data;
624 rc = l_ioctl(LNET_DEV_ID, ioc_call, &ping);
627 sizeof(err_str), "failed to %s %s: %s\n", oper,
628 id.pid == LNET_PID_ANY ?
629 libcfs_nid2str(id.nid) :
630 libcfs_id2str(id), strerror(errno));
631 rc = LUSTRE_CFG_RC_BAD_PARAM;
632 cYAML_build_error(rc, seq_no, MANAGE_CMD,
633 oper, err_str, err_rc);
637 if (cYAML_create_string(item, "primary nid",
638 libcfs_nid2str(ping.ping_id.nid)) == NULL)
641 if (cYAML_create_string(item, "Multi-Rail", ping.mr_info ?
642 "True" : "False") == NULL)
645 tmp = cYAML_create_seq(item, "peer ni");
649 for (i = 0; i < ping.ping_count; i++) {
650 if (ping.ping_buf[i].nid == LNET_NID_LO_0)
652 peer_ni = cYAML_create_seq_item(tmp);
655 memset(buf, 0, sizeof buf);
656 snprintf(buf, sizeof buf, "nid");
657 if (cYAML_create_string(peer_ni, buf,
658 libcfs_nid2str(ping.ping_buf[i].nid)) == NULL)
664 } while ((token = strtok(NULL, ",")) != NULL);
667 rc = LUSTRE_CFG_RC_NO_ERR;
672 if (show_rc == NULL || rc != LUSTRE_CFG_RC_NO_ERR) {
673 cYAML_free_tree(root);
674 } else if (show_rc != NULL && *show_rc != NULL) {
675 struct cYAML *show_node;
676 show_node = cYAML_get_object_item(*show_rc, oper);
677 if (show_node != NULL && cYAML_is_sequence(show_node)) {
678 cYAML_insert_child(show_node, first_seq);
681 } else if (show_node == NULL) {
682 cYAML_insert_sibling((*show_rc)->cy_child,
686 cYAML_free_tree(root);
695 int lustre_lnet_ping_nid(char *ping_nids, char *src_nidstr, int timeout,
696 int seq_no, struct cYAML **show_rc,
697 struct cYAML **err_rc)
701 rc = infra_ping_nid(ping_nids, src_nidstr, "ping", timeout,
702 IOC_LIBCFS_PING_PEER, seq_no, show_rc, err_rc);
706 int lustre_lnet_discover_nid(char *ping_nids, int force, int seq_no,
707 struct cYAML **show_rc, struct cYAML **err_rc)
711 rc = infra_ping_nid(ping_nids, NULL, "discover", force,
712 IOC_LIBCFS_DISCOVER, seq_no, show_rc, err_rc);
716 static int lustre_lnet_handle_peer_nidlist(lnet_nid_t *nidlist, int num_nids,
717 bool is_mr, int option, __u32 cmd,
718 char *cmd_type, char *err_str)
720 struct lnet_ioctl_peer_cfg data;
723 if (cmd == IOC_LIBCFS_ADD_PEER_NI) {
724 /* When adding a peer we first need to create the peer using the
725 * specified (or implied) primary nid. Then we can add
726 * additional nids to this peer using the primary nid as a key
728 LIBCFS_IOC_INIT_V2(data, prcfg_hdr);
729 data.prcfg_mr = is_mr;
730 data.prcfg_prim_nid = nidlist[0];
731 data.prcfg_cfg_nid = LNET_NID_ANY;
732 data.prcfg_count = option;
734 rc = dispatch_peer_ni_cmd(cmd, &data, err_str, cmd_type);
740 /* Add or delete any specified NIs associated with the specified
741 * (or implied) primary nid
743 for (nid_idx = 1; nid_idx < num_nids; nid_idx++) {
744 LIBCFS_IOC_INIT_V2(data, prcfg_hdr);
745 data.prcfg_mr = is_mr;
746 data.prcfg_prim_nid = nidlist[0];
747 data.prcfg_cfg_nid = nidlist[nid_idx];
748 data.prcfg_count = option;
750 rc = dispatch_peer_ni_cmd(cmd, &data, err_str, cmd_type);
756 if (cmd == IOC_LIBCFS_DEL_PEER_NI && num_nids == 1) {
757 /* In the delete case we may have been given just the
758 * primary nid of the peer. This tells us to delete the peer
759 * completely (rather than just delete some of its NIs)
761 LIBCFS_IOC_INIT_V2(data, prcfg_hdr);
762 data.prcfg_prim_nid = nidlist[0];
763 data.prcfg_cfg_nid = LNET_NID_ANY;
764 data.prcfg_count = option;
766 rc = dispatch_peer_ni_cmd(cmd, &data, err_str, cmd_type);
773 lustre_lnet_mod_peer_nidlist(lnet_nid_t pnid, lnet_nid_t *lnet_nidlist,
774 int cmd, int num_nids, bool is_mr, int option,
775 int seq_no, struct cYAML **err_rc)
777 int rc = LUSTRE_CFG_RC_NO_ERR;
778 char err_str[LNET_MAX_STR_LEN];
779 lnet_nid_t *lnet_nidlist2 = NULL;
780 int ioc_cmd = (cmd == LNETCTL_ADD_CMD) ? IOC_LIBCFS_ADD_PEER_NI :
781 IOC_LIBCFS_DEL_PEER_NI;
782 char *cmd_str = (cmd == LNETCTL_ADD_CMD) ? ADD_CMD : DEL_CMD;
785 lnet_nidlist2 = calloc(sizeof(*lnet_nidlist2), num_nids);
786 if (!lnet_nidlist2) {
787 snprintf(err_str, LNET_MAX_STR_LEN, "out of memory");
788 rc = LUSTRE_CFG_RC_OUT_OF_MEM;
791 lnet_nidlist2[0] = pnid;
792 memcpy(&lnet_nidlist2[1], lnet_nidlist, sizeof(*lnet_nidlist) *
795 rc = lustre_lnet_handle_peer_nidlist(lnet_nidlist2,
796 num_nids, is_mr, option,
797 ioc_cmd, cmd_str, err_str);
802 cYAML_build_error(rc, seq_no, cmd_str, "peer_ni", err_str, err_rc);
807 replace_sep(char *str, char sep, char newsep)
813 for (i = 0; i < strlen(str); i++) {
814 /* don't replace ',' within [] */
817 else if (str[i] == ']')
819 else if (str[i] == sep && bracket == 0)
824 int lustre_lnet_modify_peer(char *prim_nid, char *nids, bool is_mr, int cmd,
825 int option, int seq_no, struct cYAML **err_rc)
828 char err_str[LNET_MAX_STR_LEN] = "Error";
829 lnet_nid_t lnet_nidlist[LNET_MAX_NIDS_PER_PEER];
830 lnet_nid_t pnid = LNET_NID_ANY;
833 rc = LUSTRE_CFG_RC_BAD_PARAM;
834 snprintf(err_str, LNET_MAX_STR_LEN,
835 "--prim_nid must be specified");
839 pnid = libcfs_str2nid(prim_nid);
840 if (pnid == LNET_NID_ANY) {
841 rc = LUSTRE_CFG_RC_BAD_PARAM;
842 snprintf(err_str, LNET_MAX_STR_LEN,
843 "badly formatted primary NID: %s", prim_nid);
850 * if there is no primary nid we need to make the first nid in the
851 * nids list the primary nid
853 replace_sep(nids, ',', ' ');
854 rc = lustre_lnet_parse_nidstr(nids, lnet_nidlist,
855 LNET_MAX_NIDS_PER_PEER, err_str);
862 rc = lustre_lnet_mod_peer_nidlist(pnid, lnet_nidlist,
863 cmd, num_nids, is_mr,
867 if (rc != LUSTRE_CFG_RC_NO_ERR)
868 cYAML_build_error(rc, -1, "peer",
869 cmd == LNETCTL_ADD_CMD ? "add" : "del",
875 static int lustre_lnet_route_common(char *nw, char *nidstr, int hops, int prio,
876 int sen, int seq_no, struct cYAML **err_rc,
879 int rc, num_nids, idx;
881 char err_str[LNET_MAX_STR_LEN] = "\"generic error\"";
882 struct lnet_ioctl_config_data data;
883 lnet_nid_t lnet_nidlist[LNET_MAX_NIDS_PER_PEER];
885 if (nw == NULL || nidstr == NULL) {
886 snprintf(err_str, LNET_MAX_STR_LEN,
887 "\"missing mandatory parameter:'%s'\"",
888 (nw == NULL && nidstr == NULL) ? "network, gateway" :
889 (nw == NULL) ? "network" : "gateway");
890 rc = LUSTRE_CFG_RC_MISSING_PARAM;
894 rnet = libcfs_str2net(nw);
895 if (rnet == LNET_NET_ANY) {
896 snprintf(err_str, LNET_MAX_STR_LEN,
897 "\"cannot parse remote net %s\"", nw);
898 rc = LUSTRE_CFG_RC_BAD_PARAM;
902 replace_sep(nidstr, ',', ' ');
903 rc = lustre_lnet_parse_nidstr(nidstr, lnet_nidlist,
904 LNET_MAX_NIDS_PER_PEER, err_str);
910 for (idx = 0; idx < num_nids; idx++) {
911 LIBCFS_IOC_INIT_V2(data, cfg_hdr);
913 if (cmd == LNETCTL_ADD_CMD) {
914 data.cfg_config_u.cfg_route.rtr_hop = hops;
915 data.cfg_config_u.cfg_route.rtr_priority = prio;
916 data.cfg_config_u.cfg_route.rtr_sensitivity = sen;
919 data.cfg_nid = lnet_nidlist[idx];
921 if (cmd == LNETCTL_ADD_CMD)
922 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_ADD_ROUTE,
925 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_DEL_ROUTE,
928 if (rc != 0 && errno != EEXIST &&
929 errno != EHOSTUNREACH) {
931 snprintf(err_str, LNET_MAX_STR_LEN,
932 "route operation failed: %s",
935 } else if (errno == EEXIST) {
937 * continue chugging along if one of the
938 * routes already exists
945 cYAML_build_error(rc, seq_no,
946 cmd == LNETCTL_ADD_CMD ? ADD_CMD : DEL_CMD, "route",
952 int lustre_lnet_config_route(char *nw, char *nidstr, int hops, int prio,
953 int sen, int seq_no, struct cYAML **err_rc)
956 char err_str[LNET_MAX_STR_LEN] = "\"generic error\"";
959 hops = LNET_UNDEFINED_HOPS;
960 } else if (hops < 1 || hops > 255) {
961 snprintf(err_str, LNET_MAX_STR_LEN,
962 "\"invalid hop count %d, must be between 1 and 255\"",
964 rc = LUSTRE_CFG_RC_OUT_OF_RANGE_PARAM;
970 } else if (prio < 0) {
971 snprintf(err_str, LNET_MAX_STR_LEN,
972 "\"invalid priority %d, must be greater than 0\"",
974 rc = LUSTRE_CFG_RC_OUT_OF_RANGE_PARAM;
980 } else if (sen < 1) {
981 snprintf(err_str, LNET_MAX_STR_LEN,
982 "\"invalid health sensitivity %d, must be 1 or greater\"",
984 rc = LUSTRE_CFG_RC_OUT_OF_RANGE_PARAM;
988 rc = lustre_lnet_route_common(nw, nidstr, hops, prio, sen, seq_no,
989 err_rc, LNETCTL_ADD_CMD);
992 cYAML_build_error(rc, seq_no, ADD_CMD, "route", err_str, err_rc);
997 int lustre_lnet_del_route(char *nw, char *nidstr, int seq_no,
998 struct cYAML **err_rc)
1000 return lustre_lnet_route_common(nw, nidstr, 0, 0, 0, seq_no, err_rc,
1004 int lustre_lnet_show_route(char *nw, char *gw, int hops, int prio, int detail,
1005 int seq_no, struct cYAML **show_rc,
1006 struct cYAML **err_rc, bool backup)
1008 struct lnet_ioctl_config_data data;
1009 lnet_nid_t gateway_nid;
1010 int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
1012 __u32 net = LNET_NET_ANY;
1014 struct cYAML *root = NULL, *route = NULL, *item = NULL;
1015 struct cYAML *first_seq = NULL;
1016 char err_str[LNET_MAX_STR_LEN] = "\"out of memory\"";
1020 net = libcfs_str2net(nw);
1021 if (net == LNET_NET_ANY) {
1024 "\"cannot parse net '%s'\"", nw);
1025 rc = LUSTRE_CFG_RC_BAD_PARAM;
1030 /* show all routes without filtering on net */
1035 gateway_nid = libcfs_str2nid(gw);
1036 if (gateway_nid == LNET_NID_ANY) {
1039 "\"cannot parse gateway NID '%s'\"", gw);
1040 rc = LUSTRE_CFG_RC_BAD_PARAM;
1044 /* show all routes with out filtering on gateway */
1045 gateway_nid = LNET_NID_ANY;
1047 if ((hops < 1 && hops != -1) || hops > 255) {
1050 "\"invalid hop count %d, must be between 0 and 256\"",
1052 rc = LUSTRE_CFG_RC_OUT_OF_RANGE_PARAM;
1056 /* create struct cYAML root object */
1057 root = cYAML_create_object(NULL, NULL);
1061 route = cYAML_create_seq(root, "route");
1069 LIBCFS_IOC_INIT_V2(data, cfg_hdr);
1072 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_ROUTE, &data);
1078 /* filter on provided data */
1079 if (net != LNET_NET_ANY &&
1080 net != data.cfg_net)
1083 if (gateway_nid != LNET_NID_ANY &&
1084 gateway_nid != data.cfg_nid)
1088 hops != data.cfg_config_u.cfg_route.rtr_hop)
1092 prio != data.cfg_config_u.cfg_route.rtr_priority)
1095 /* default rc to -1 incase we hit the goto */
1099 item = cYAML_create_seq_item(route);
1103 if (first_seq == NULL)
1106 if (cYAML_create_string(item, "net",
1107 libcfs_net2str(data.cfg_net)) == NULL)
1110 if (cYAML_create_string(item, "gateway",
1111 libcfs_nid2str(data.cfg_nid)) == NULL)
1115 if (cYAML_create_number(item, "hop",
1116 (int) data.cfg_config_u.
1117 cfg_route.rtr_hop) ==
1121 if (cYAML_create_number(item, "priority",
1123 cfg_route.rtr_priority) == NULL)
1126 if (cYAML_create_number(item, "health_sensitivity",
1128 cfg_route.rtr_sensitivity) == NULL)
1131 rt_alive = data.cfg_config_u.cfg_route.rtr_flags &
1133 rt_multi_hop = data.cfg_config_u.cfg_route.rtr_flags &
1137 cYAML_create_string(item, "state",
1139 "up" : "down") == NULL)
1143 cYAML_create_string(item, "type",
1145 "multi-hop" : "single-hop") == NULL)
1150 /* print output iff show_rc is not provided */
1151 if (show_rc == NULL)
1152 cYAML_print_tree(root);
1154 if (l_errno != ENOENT) {
1157 "\"cannot get routes: %s\"",
1162 rc = LUSTRE_CFG_RC_NO_ERR;
1164 snprintf(err_str, sizeof(err_str), "\"success\"");
1166 if (show_rc == NULL || rc != LUSTRE_CFG_RC_NO_ERR || !exist) {
1167 cYAML_free_tree(root);
1168 } else if (show_rc != NULL && *show_rc != NULL) {
1169 struct cYAML *show_node;
1170 /* find the route node, if one doesn't exist then
1171 * insert one. Otherwise add to the one there
1173 show_node = cYAML_get_object_item(*show_rc, "route");
1174 if (show_node != NULL && cYAML_is_sequence(show_node)) {
1175 cYAML_insert_child(show_node, first_seq);
1178 } else if (show_node == NULL) {
1179 cYAML_insert_sibling((*show_rc)->cy_child,
1183 cYAML_free_tree(root);
1189 cYAML_build_error(rc, seq_no, SHOW_CMD, "route", err_str, err_rc);
1194 static int socket_intf_query(int request, char *intf,
1200 if (strlen(intf) >= IFNAMSIZ || ifr == NULL)
1201 return LUSTRE_CFG_RC_BAD_PARAM;
1203 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
1205 return LUSTRE_CFG_RC_BAD_PARAM;
1207 strcpy(ifr->ifr_name, intf);
1208 rc = ioctl(sockfd, request, ifr);
1210 rc = LUSTRE_CFG_RC_BAD_PARAM;
1217 static int lustre_lnet_queryip(struct lnet_dlc_intf_descr *intf, __u32 *ip)
1222 memset(&ifr, 0, sizeof(ifr));
1223 rc = socket_intf_query(SIOCGIFFLAGS, intf->intf_name, &ifr);
1225 return LUSTRE_CFG_RC_BAD_PARAM;
1227 if ((ifr.ifr_flags & IFF_UP) == 0)
1228 return LUSTRE_CFG_RC_BAD_PARAM;
1230 memset(&ifr, 0, sizeof(ifr));
1231 rc = socket_intf_query(SIOCGIFADDR, intf->intf_name, &ifr);
1233 return LUSTRE_CFG_RC_BAD_PARAM;
1235 *ip = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
1236 *ip = bswap_32(*ip);
1238 return LUSTRE_CFG_RC_NO_ERR;
1241 static int lustre_lnet_kfi_intf2nid(struct lnet_dlc_intf_descr *intf,
1244 unsigned int nic_index;
1246 char *nic_addr_path;
1251 rc = sscanf(intf->intf_name, "cxi%u", &nic_index);
1253 return LUSTRE_CFG_RC_NO_MATCH;
1255 size = snprintf(NULL, 0, cxi_nic_addr_path, nic_index) + 1;
1256 nic_addr_path = malloc(size);
1258 return LUSTRE_CFG_RC_OUT_OF_MEM;
1259 sprintf(nic_addr_path, cxi_nic_addr_path, nic_index);
1261 rc = read_sysfs_file(nic_addr_path, "nic_addr", val, 1, sizeof(val));
1262 free(nic_addr_path);
1264 return LUSTRE_CFG_RC_NO_MATCH;
1266 addr = strtol(val, NULL, 16);
1267 if (addr == LONG_MIN || addr == LONG_MAX)
1268 return LUSTRE_CFG_RC_NO_MATCH;
1272 return LUSTRE_CFG_RC_NO_ERR;
1276 * for each interface in the array of interfaces find the IP address of
1277 * that interface, create its nid and add it to an array of NIDs.
1278 * Stop if any of the interfaces is down
1280 static int lustre_lnet_intf2nids(struct lnet_dlc_network_descr *nw,
1281 lnet_nid_t **nids, __u32 *nnids,
1282 char *err_str, size_t str_len)
1284 int i = 0, count = 0, rc;
1285 struct lnet_dlc_intf_descr *intf;
1286 char val[LNET_MAX_STR_LEN];
1294 if (nw == NULL || nids == NULL) {
1295 snprintf(err_str, str_len,
1296 "\"unexpected parameters to lustre_lnet_intf2nids()\"");
1297 return LUSTRE_CFG_RC_BAD_PARAM;
1300 if (LNET_NETTYP(nw->nw_id) == GNILND) {
1303 list_for_each_entry(intf, &nw->nw_intflist, intf_on_network)
1307 *nids = calloc(count, sizeof(lnet_nid_t));
1308 if (*nids == NULL) {
1309 snprintf(err_str, str_len,
1310 "\"out of memory\"");
1311 return LUSTRE_CFG_RC_OUT_OF_MEM;
1314 * special case the GNI interface since it doesn't have an IP
1315 * address. The assumption is that there can only be one GNI
1316 * interface in the system. No interface name is provided.
1318 if (LNET_NETTYP(nw->nw_id) == GNILND) {
1319 rc = read_sysfs_file(gni_nid_path, "nid", val,
1322 snprintf(err_str, str_len,
1323 "\"cannot read gni nid\"");
1326 gni_num = atoi(val);
1328 (*nids)[i] = LNET_MKNID(nw->nw_id, gni_num);
1331 } else if (LNET_NETTYP(nw->nw_id) == KFILND) {
1332 list_for_each_entry(intf, &nw->nw_intflist, intf_on_network) {
1333 rc = lustre_lnet_kfi_intf2nid(intf, &nic_addr);
1334 if (rc != LUSTRE_CFG_RC_NO_ERR) {
1335 snprintf(err_str, str_len,
1336 "\"couldn't query kfi intf %s\"",
1338 err_str[str_len - 1] = '\0';
1342 (*nids)[i] = LNET_MKNID(nw->nw_id, nic_addr);
1348 /* look at the other interfaces */
1349 list_for_each_entry(intf, &nw->nw_intflist, intf_on_network) {
1350 if (LNET_NETTYP(nw->nw_id) == PTL4LND) {
1351 /* handle LNDs with numeric interface name */
1352 num = strtoul(intf->intf_name, &endp, 0);
1353 if (endp == intf->intf_name || *endp != '\0') {
1354 rc = LUSTRE_CFG_RC_BAD_PARAM;
1355 snprintf(err_str, str_len,
1356 "\"couldn't query intf %s\"",
1360 (*nids)[i] = LNET_MKNID(nw->nw_id, num);
1363 /* handle LNDs with ip interface name */
1364 rc = lustre_lnet_queryip(intf, &ip);
1365 if (rc != LUSTRE_CFG_RC_NO_ERR) {
1366 snprintf(err_str, str_len,
1367 "\"couldn't query intf %s\"",
1371 (*nids)[i] = LNET_MKNID(nw->nw_id, ip);
1388 * called repeatedly until a match or no more ip range
1390 * ip_range expression
1391 * interface list with all the interface names.
1392 * all the interfaces in the system.
1394 * try to match the ip_range expr to one of the interfaces' IPs in
1395 * the system. If we hit a patch for an interface. Check if that
1396 * interface name is in the list.
1398 * If there are more than one interface in the list, then make sure
1399 * that the IPs for all of these interfaces match the ip ranges
1402 * for each interface in intf_list
1403 * look up the intf name in ifa
1404 * if not there then no match
1405 * check ip obtained from ifa against a match to any of the
1407 * If no match, then fail
1409 * The result is that all the interfaces have to match.
1411 static int lustre_lnet_match_ip_to_intf(struct ifaddrs *ifa,
1412 struct list_head *intf_list,
1413 struct list_head *ip_ranges)
1417 struct lnet_dlc_intf_descr *intf_descr, *tmp;
1418 struct ifaddrs *ifaddr = ifa;
1419 struct lustre_lnet_ip_range_descr *ip_range;
1423 * if there are no explicit interfaces, and no ip ranges, then
1424 * configure the first tcp interface we encounter.
1426 if (list_empty(intf_list) && list_empty(ip_ranges)) {
1427 for (ifaddr = ifa; ifaddr != NULL; ifaddr = ifaddr->ifa_next) {
1428 if (ifaddr->ifa_addr == NULL)
1431 if ((ifaddr->ifa_flags & IFF_UP) == 0)
1434 family = ifaddr->ifa_addr->sa_family;
1435 if (family == AF_INET &&
1436 strcmp(ifaddr->ifa_name, "lo") != 0) {
1437 rc = lustre_lnet_add_intf_descr
1438 (intf_list, ifaddr->ifa_name,
1439 strlen(ifaddr->ifa_name));
1441 if (rc != LUSTRE_CFG_RC_NO_ERR)
1444 return LUSTRE_CFG_RC_MATCH;
1447 return LUSTRE_CFG_RC_NO_MATCH;
1451 * First interface which matches an IP pattern will be used
1453 if (list_empty(intf_list)) {
1455 * no interfaces provided in the rule, but an ip range is
1456 * provided, so try and match an interface to the ip
1459 for (ifaddr = ifa; ifaddr != NULL; ifaddr = ifaddr->ifa_next) {
1460 if (ifaddr->ifa_addr == NULL)
1463 if ((ifaddr->ifa_flags & IFF_UP) == 0)
1466 family = ifaddr->ifa_addr->sa_family;
1467 if (family == AF_INET) {
1468 ip = ((struct sockaddr_in *)ifaddr->ifa_addr)->
1471 list_for_each_entry(ip_range, ip_ranges,
1473 rc = cfs_ip_addr_match(bswap_32(ip),
1474 &ip_range->ipr_expr);
1478 rc = lustre_lnet_add_intf_descr
1479 (intf_list, ifaddr->ifa_name,
1480 strlen(ifaddr->ifa_name));
1482 if (rc != LUSTRE_CFG_RC_NO_ERR)
1488 if (!list_empty(intf_list))
1489 return LUSTRE_CFG_RC_MATCH;
1491 return LUSTRE_CFG_RC_NO_MATCH;
1495 * If an interface is explicitly specified the ip-range might or
1496 * might not be specified. if specified the interface needs to match the
1497 * ip-range. If no ip-range then the interfaces are
1498 * automatically matched if they are all up.
1499 * If > 1 interfaces all the interfaces must match for the NI to
1502 list_for_each_entry_safe(intf_descr, tmp, intf_list, intf_on_network) {
1503 for (ifaddr = ifa; ifaddr != NULL; ifaddr = ifaddr->ifa_next) {
1504 if (ifaddr->ifa_addr == NULL)
1507 family = ifaddr->ifa_addr->sa_family;
1508 if (family == AF_INET &&
1509 strcmp(intf_descr->intf_name,
1510 ifaddr->ifa_name) == 0)
1514 if (ifaddr == NULL) {
1515 list_del(&intf_descr->intf_on_network);
1516 free_intf_descr(intf_descr);
1520 if ((ifaddr->ifa_flags & IFF_UP) == 0) {
1521 list_del(&intf_descr->intf_on_network);
1522 free_intf_descr(intf_descr);
1526 ip = ((struct sockaddr_in *)ifaddr->ifa_addr)->sin_addr.s_addr;
1529 list_for_each_entry(ip_range, ip_ranges, ipr_entry) {
1530 rc = cfs_ip_addr_match(bswap_32(ip), &ip_range->ipr_expr);
1536 /* no match for this interface */
1537 list_del(&intf_descr->intf_on_network);
1538 free_intf_descr(intf_descr);
1542 return LUSTRE_CFG_RC_MATCH;
1545 static int lustre_lnet_resolve_ip2nets_rule(struct lustre_lnet_ip2nets *ip2nets,
1546 lnet_nid_t **nids, __u32 *nnids,
1547 char *err_str, size_t str_len)
1549 struct ifaddrs *ifa;
1550 int rc = LUSTRE_CFG_RC_NO_ERR;
1552 rc = getifaddrs(&ifa);
1554 snprintf(err_str, str_len,
1555 "\"failed to get interface addresses: %d\"", -errno);
1559 rc = lustre_lnet_match_ip_to_intf(ifa,
1560 &ip2nets->ip2nets_net.nw_intflist,
1561 &ip2nets->ip2nets_ip_ranges);
1562 if (rc != LUSTRE_CFG_RC_MATCH) {
1563 snprintf(err_str, str_len,
1564 "\"couldn't match ip to existing interfaces\"");
1569 rc = lustre_lnet_intf2nids(&ip2nets->ip2nets_net, nids, nnids,
1571 if (rc != LUSTRE_CFG_RC_NO_ERR) {
1581 void lustre_lnet_free_list(struct nid_node *head)
1583 struct nid_node *entry, *tmp;
1585 nl_list_for_each_entry_safe(entry, tmp, &head->children, list) {
1586 nl_list_del(&entry->list);
1591 static int unroll_nid_range_scan(struct nid_node *list, const char *nid,
1592 char *tmp, char *tmp2, char *nidstr,
1593 const char **errmsg)
1595 unsigned int first = 0, last = 0, off = 0, inc = 1;
1596 bool slash = false, hyphen = false;
1597 char num[INT_STRING_LEN] = "";
1598 char *range = tmp + 1;
1602 if (!tmp && !tmp2) {
1603 *errmsg = "Unable to parse nidlist: [] are missing";
1607 if ((tmp && !tmp2) || (!tmp && tmp2)) {
1608 *errmsg = "Unable to parse nidlist: incomplete bracket set";
1613 *errmsg = "Unable to parse nidlist: improper bracket ordering";
1617 if (strchr(nid, ':'))
1620 while (range < tmp2) {
1621 if (isxdigit(*range)) {
1622 if (off > INT_STRING_LEN)
1624 num[off++] = *range++;
1625 } else if (*range == ':') {
1626 /* skip ':' for IPv6 and IB GUID */
1628 } else if (*range == '-') {
1630 if (!isxdigit(*range)) {
1631 *errmsg = "Unable to parse nidlist: range needs number after -";
1635 first = strtoul(num, NULL, base);
1636 memset(num, 0, sizeof(num));
1639 } else if (*range == '/') {
1641 if (!isdigit(*range)) {
1642 *errmsg = "Unable to parse nidlist: range needs number after /";
1646 /* Don't lose last number. This should be the very last item */
1648 last = strtoul(num, NULL, base);
1649 memset(num, 0, sizeof(num));
1653 } else if (*range == ',') {
1654 char *end = strchr(nidstr, ',');
1655 int count = strlen(tmp2 + 1);
1656 struct nid_node *item;
1657 int len = tmp - nid;
1660 if (!isxdigit(*range)) {
1661 *errmsg = "Unable to parse nidlist: range needs number after ,";
1665 /* If hyphen is true then we have the foramt '[first - last],' format.
1666 * The other format is just x, y, z, ... format.
1670 inc = strtoul(num, NULL, base);
1672 last = strtoul(num, NULL, base);
1675 *errmsg = "Unable to parse nidlist: range is wrong order";
1679 while (last >= first) {
1680 char hdr[LNET_MAX_STR_LEN], *next;
1682 snprintf(hdr, sizeof(hdr), "%.*s%d%.*s",
1683 len, nid, first, count,
1685 next = strchr(hdr, '[');
1686 if (next && strchr(next, ']')) {
1687 rc = unroll_nid_range_scan(list, hdr, next,
1693 item = calloc(1, sizeof(struct nid_node));
1695 *errmsg = "Unable to parse nidlist: allocation failed";
1698 snprintf(item->nidstr, sizeof(item->nidstr),
1699 "%s@%s", hdr, nidstr);
1700 nl_init_list_head(&item->list);
1701 nl_list_add_tail(&item->list, &list->children);
1705 /* reset slash / hyphen handing */
1710 int end_len = end ? end - nidstr : strlen(nidstr);
1712 item = calloc(1, sizeof(struct nid_node));
1714 *errmsg = "Unable to parse nidlist: allocation failed";
1717 snprintf(item->nidstr, sizeof(item->nidstr),
1718 "%.*s%s%.*s@%.*s", len, nid, num,
1719 count, tmp2 + 1, end_len, nidstr);
1720 nl_init_list_head(&item->list);
1721 nl_list_add_tail(&item->list, &list->children);
1724 memset(num, 0, sizeof(num));
1727 *errmsg = "Unable to parse nidlist: invalid character in range";
1734 inc = strtoul(num, NULL, base);
1736 last = strtoul(num, NULL, base);
1737 memset(num, 0, sizeof(num));
1743 /* This is the last set of [ first - last ]. We reach this point because
1744 * the above loop reached the end of the range and no ',' was found so
1745 * the final set of number range wasn't processed. Do that handling here.
1747 if (first || last) {
1748 char *next = tmp2 + 1;
1749 int len = strlen(nid);
1752 *errmsg = "Unable to parse nidlist: range is wrong order";
1756 if (strchr(nid, '['))
1757 len = strchr(nid, '[') - nid;
1759 tmp = strchr(tmp2, '[');
1761 tmp2 = strchr(tmp, ']');
1763 while (last >= first) {
1764 char str[LNET_MAX_STR_LEN];
1766 snprintf(str, sizeof(str), "%.*s%u%.*s",
1767 len, nid, first, (int)(tmp - next), next);
1769 rc = unroll_nid_range_scan(list, str, tmp, tmp2,
1774 char *end = strchr(nidstr, ',');
1775 int count = end ? end - nidstr : strlen(nidstr);
1776 struct nid_node *item;
1778 item = calloc(1, sizeof(struct nid_node));
1780 *errmsg = "Unable to parse nidlist: allocation failed";
1783 snprintf(item->nidstr, sizeof(item->nidstr),
1784 "%s@%.*s", str, count, nidstr);
1785 nl_init_list_head(&item->list);
1786 nl_list_add_tail(&item->list, &list->children);
1795 int lustre_lnet_parse_nid_range(struct nid_node *head, char *nidstr,
1796 const char **errmsg)
1802 *errmsg = "supplied nidstr is NULL";
1806 if (strchr(nidstr, '*')) {
1807 *errmsg = "asterisk not allowed in nidstring";
1811 if (strstr(nidstr, "<?>")) {
1812 *errmsg = "Unable to parse nidlist: LNET_ANY_NID is unsupported";
1816 if (strchr(nidstr, '@') == NULL) {
1817 *errmsg = "Unable to parse nidlist: no valid NIDs in string";
1821 while ((nid = strsep(&nidstr, "@")) != NULL) {
1822 char *tmp = NULL, *tmp2 = NULL, *end = NULL;
1824 tmp = strchr(nid, '[');
1825 tmp2 = strchr(nid, ']');
1827 if (!tmp && !tmp2) {
1828 char *end = strchr(nidstr, ',');
1829 struct nid_node *item;
1832 item = calloc(1, sizeof(struct nid_node));
1834 *errmsg = "Unable to parse nidlist: allocation failed";
1839 count = end ? end - nidstr : strlen(nidstr);
1840 snprintf(item->nidstr, sizeof(item->nidstr),
1841 "%s@%.*s", nid, count, nidstr);
1842 nl_init_list_head(&item->list);
1843 nl_list_add_tail(&item->list, &head->children);
1845 rc = unroll_nid_range_scan(head, nid, tmp, tmp2,
1852 end = strchr(nidstr, ',');
1864 lustre_lnet_ioctl_config_ni(struct list_head *intf_list,
1865 struct lnet_ioctl_config_lnd_tunables *tunables,
1866 struct cfs_expr_list *global_cpts,
1867 lnet_nid_t *nids, char *err_str)
1870 struct lnet_ioctl_config_ni *conf;
1871 struct lnet_ioctl_config_lnd_tunables *tun = NULL;
1872 int rc = LUSTRE_CFG_RC_NO_ERR, i = 0;
1875 struct lnet_dlc_intf_descr *intf_descr;
1877 struct cfs_expr_list *cpt_expr;
1879 list_for_each_entry(intf_descr, intf_list,
1881 if (tunables != NULL)
1882 len = sizeof(struct lnet_ioctl_config_ni) +
1883 sizeof(struct lnet_ioctl_config_lnd_tunables);
1885 len = sizeof(struct lnet_ioctl_config_ni);
1887 data = calloc(1, len);
1889 return LUSTRE_CFG_RC_OUT_OF_MEM;
1890 conf = (struct lnet_ioctl_config_ni*) data;
1891 if (tunables != NULL)
1892 tun = (struct lnet_ioctl_config_lnd_tunables*)
1895 LIBCFS_IOC_INIT_V2(*conf, lic_cfg_hdr);
1896 conf->lic_cfg_hdr.ioc_len = len;
1897 conf->lic_nid = nids[i];
1898 strncpy(conf->lic_ni_intf, intf_descr->intf_name,
1901 if (intf_descr->cpt_expr != NULL)
1902 cpt_expr = intf_descr->cpt_expr;
1903 else if (global_cpts != NULL)
1904 cpt_expr = global_cpts;
1908 if (cpt_expr != NULL) {
1909 count = cfs_expr_list_values(cpt_expr,
1910 LNET_MAX_SHOW_NUM_CPT,
1913 memcpy(conf->lic_cpts, cpt_array,
1914 sizeof(cpt_array[0]) * LNET_MAX_STR_LEN);
1923 conf->lic_ncpts = count;
1925 if (tunables != NULL)
1926 memcpy(tun, tunables, sizeof(*tunables));
1928 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_ADD_LOCAL_NI, data);
1933 "\"cannot add network: %s\"", strerror(errno));
1941 return LUSTRE_CFG_RC_NO_ERR;
1945 lustre_lnet_config_ip2nets(struct lustre_lnet_ip2nets *ip2nets,
1946 struct lnet_ioctl_config_lnd_tunables *tunables,
1947 struct cfs_expr_list *global_cpts,
1948 int seq_no, struct cYAML **err_rc)
1950 lnet_nid_t *nids = NULL;
1953 char err_str[LNET_MAX_STR_LEN] = "\"success\"";
1958 "\"incomplete ip2nets information\"");
1959 rc = LUSTRE_CFG_RC_BAD_PARAM;
1964 * call below function to resolve the rules into a list of nids.
1965 * The memory is allocated in that function then freed here when
1966 * it's no longer needed.
1968 rc = lustre_lnet_resolve_ip2nets_rule(ip2nets, &nids, &nnids, err_str,
1970 if (rc != LUSTRE_CFG_RC_NO_ERR && rc != LUSTRE_CFG_RC_MATCH)
1973 if (list_empty(&ip2nets->ip2nets_net.nw_intflist)) {
1974 snprintf(err_str, sizeof(err_str),
1975 "\"no interfaces match ip2nets rules\"");
1979 rc = lustre_lnet_ioctl_config_ni(&ip2nets->ip2nets_net.nw_intflist,
1980 tunables, global_cpts, nids,
1987 cYAML_build_error(rc, seq_no, ADD_CMD, "ip2nets", err_str, err_rc);
1991 int lustre_lnet_config_ni(struct lnet_dlc_network_descr *nw_descr,
1992 struct cfs_expr_list *global_cpts,
1994 struct lnet_ioctl_config_lnd_tunables *tunables,
1995 int seq_no, struct cYAML **err_rc)
1998 struct lnet_ioctl_config_ni *conf;
1999 struct lnet_ioctl_config_lnd_tunables *tun = NULL;
2000 char buf[LNET_MAX_STR_LEN];
2001 int rc = LUSTRE_CFG_RC_NO_ERR;
2002 char err_str[LNET_MAX_STR_LEN * 2] = "\"success\"";
2003 lnet_nid_t *nids = NULL;
2007 struct lnet_dlc_intf_descr *intf_descr, *tmp;
2010 if (ip2net == NULL && (nw_descr == NULL || nw_descr->nw_id == 0 ||
2011 (list_empty(&nw_descr->nw_intflist) &&
2012 LNET_NETTYP(nw_descr->nw_id) != GNILND))) {
2015 "\"missing mandatory parameters in NI config: '%s'\"",
2016 (nw_descr == NULL) ? "network , interface" :
2017 (nw_descr->nw_id == 0) ? "network" : "interface");
2018 rc = LUSTRE_CFG_RC_MISSING_PARAM;
2022 if (ip2net != NULL && strlen(ip2net) >= sizeof(buf)) {
2025 "\"ip2net string too long %d\"",
2026 (int)strlen(ip2net));
2027 rc = LUSTRE_CFG_RC_OUT_OF_RANGE_PARAM;
2031 if (ip2net != NULL) {
2032 if (tunables != NULL)
2033 len = sizeof(struct lnet_ioctl_config_ni) +
2034 sizeof(struct lnet_ioctl_config_lnd_tunables);
2036 len = sizeof(struct lnet_ioctl_config_ni);
2037 data = calloc(1, len);
2039 rc = LUSTRE_CFG_RC_OUT_OF_MEM;
2042 conf = (struct lnet_ioctl_config_ni*) data;
2043 if (tunables != NULL)
2044 tun = (struct lnet_ioctl_config_lnd_tunables*)
2045 (data + sizeof(*conf));
2047 LIBCFS_IOC_INIT_V2(*conf, lic_cfg_hdr);
2048 conf->lic_cfg_hdr.ioc_len = len;
2049 strncpy(conf->lic_legacy_ip2nets, ip2net,
2052 if (global_cpts != NULL) {
2053 count = cfs_expr_list_values(global_cpts,
2054 LNET_MAX_SHOW_NUM_CPT,
2057 memcpy(conf->lic_cpts, cpt_array,
2058 sizeof(cpt_array[0]) * LNET_MAX_STR_LEN);
2067 conf->lic_ncpts = count;
2069 if (tunables != NULL)
2070 memcpy(tun, tunables, sizeof(*tunables));
2072 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_ADD_LOCAL_NI, data);
2077 "\"cannot add network: %s\"", strerror(errno));
2084 if (LNET_NETTYP(nw_descr->nw_id) == LOLND) {
2085 rc = LUSTRE_CFG_RC_NO_ERR;
2089 if (nw_descr->nw_id == LNET_NET_ANY) {
2092 "\"cannot parse net '%s'\"",
2093 libcfs_net2str(nw_descr->nw_id));
2094 rc = LUSTRE_CFG_RC_BAD_PARAM;
2099 * special case the GNI since no interface name is expected
2101 if (list_empty(&nw_descr->nw_intflist) &&
2102 (LNET_NETTYP(nw_descr->nw_id) != GNILND)) {
2105 "\"no interface name provided\"");
2106 rc = LUSTRE_CFG_RC_BAD_PARAM;
2110 rc = lustre_lnet_intf2nids(nw_descr, &nids, &nnids,
2111 err_str, sizeof(err_str));
2113 rc = LUSTRE_CFG_RC_BAD_PARAM;
2117 rc = lustre_lnet_ioctl_config_ni(&nw_descr->nw_intflist,
2118 tunables, global_cpts, nids,
2122 if (nw_descr != NULL) {
2123 list_for_each_entry_safe(intf_descr, tmp,
2124 &nw_descr->nw_intflist,
2126 list_del(&intf_descr->intf_on_network);
2127 free_intf_descr(intf_descr);
2131 cYAML_build_error(rc, seq_no, ADD_CMD, "net", err_str, err_rc);
2142 int lustre_lnet_del_ni(struct lnet_dlc_network_descr *nw_descr,
2143 int seq_no, struct cYAML **err_rc)
2145 struct lnet_ioctl_config_ni data;
2146 int rc = LUSTRE_CFG_RC_NO_ERR, i;
2147 char err_str[LNET_MAX_STR_LEN * 2] = "\"success\"";
2148 lnet_nid_t *nids = NULL;
2150 struct lnet_dlc_intf_descr *intf_descr, *tmp;
2152 if (nw_descr == NULL || nw_descr->nw_id == 0) {
2155 "\"missing mandatory parameter in deleting NI: '%s'\"",
2156 (nw_descr == NULL) ? "network , interface" :
2157 (nw_descr->nw_id == 0) ? "network" : "interface");
2158 rc = LUSTRE_CFG_RC_MISSING_PARAM;
2162 if (LNET_NETTYP(nw_descr->nw_id) == LOLND)
2163 return LUSTRE_CFG_RC_NO_ERR;
2165 if (nw_descr->nw_id == LNET_NET_ANY) {
2168 "\"cannot parse net '%s'\"",
2169 libcfs_net2str(nw_descr->nw_id));
2170 rc = LUSTRE_CFG_RC_BAD_PARAM;
2174 rc = lustre_lnet_intf2nids(nw_descr, &nids, &nnids,
2175 err_str, sizeof(err_str));
2177 rc = LUSTRE_CFG_RC_BAD_PARAM;
2182 * no interfaces just the nw_id is specified
2185 nids = calloc(1, sizeof(*nids));
2187 snprintf(err_str, sizeof(err_str),
2188 "\"out of memory\"");
2189 rc = LUSTRE_CFG_RC_OUT_OF_MEM;
2192 nids[0] = LNET_MKNID(nw_descr->nw_id, 0);
2196 for (i = 0; i < nnids; i++) {
2197 LIBCFS_IOC_INIT_V2(data, lic_cfg_hdr);
2198 data.lic_nid = nids[i];
2200 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_DEL_LOCAL_NI, &data);
2205 "\"cannot del network: %s\"", strerror(errno));
2209 list_for_each_entry_safe(intf_descr, tmp, &nw_descr->nw_intflist,
2211 list_del(&intf_descr->intf_on_network);
2212 free_intf_descr(intf_descr);
2216 cYAML_build_error(rc, seq_no, DEL_CMD, "net", err_str, err_rc);
2225 lustre_lnet_config_healthv(int value, bool all, lnet_nid_t nid,
2226 enum lnet_health_type type, char *name,
2227 int seq_no, struct cYAML **err_rc)
2229 struct lnet_ioctl_reset_health_cfg data;
2230 int rc = LUSTRE_CFG_RC_NO_ERR;
2231 char err_str[LNET_MAX_STR_LEN] = "\"success\"";
2233 LIBCFS_IOC_INIT_V2(data, rh_hdr);
2234 data.rh_type = type;
2236 data.rh_value = value;
2239 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_SET_HEALHV, &data);
2243 sizeof(err_str), "Can not configure health value: %s",
2247 cYAML_build_error(rc, seq_no, ADD_CMD, name, err_str, err_rc);
2253 lustre_lnet_config_peer(int state, lnet_nid_t nid, char *name,
2254 int seq_no, struct cYAML **err_rc)
2256 struct lnet_ioctl_peer_cfg data;
2257 int rc = LUSTRE_CFG_RC_NO_ERR;
2258 char err_str[LNET_MAX_STR_LEN] = "\"success\"";
2260 LIBCFS_IOC_INIT_V2(data, prcfg_hdr);
2261 data.prcfg_state = state;
2262 data.prcfg_prim_nid = nid;
2263 data.prcfg_cfg_nid = LNET_NID_ANY;
2265 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_SET_PEER, &data);
2269 sizeof(err_str), "Can not set peer property: %s",
2273 cYAML_build_error(rc, seq_no, ADD_CMD, name, err_str, err_rc);
2279 lustre_lnet_config_conns_per_peer(int value, bool all, lnet_nid_t nid,
2280 char *name, int seq_no,
2281 struct cYAML **err_rc)
2283 struct lnet_ioctl_reset_conns_per_peer_cfg data;
2284 int rc = LUSTRE_CFG_RC_NO_ERR;
2285 char err_str[LNET_MAX_STR_LEN] = "\"success\"";
2287 LIBCFS_IOC_INIT_V2(data, rcpp_hdr);
2288 data.rcpp_all = all;
2289 data.rcpp_value = value;
2290 data.rcpp_nid = nid;
2292 if (value < 0 || value > 127) {
2293 rc = LUSTRE_CFG_RC_BAD_PARAM;
2294 snprintf(err_str, sizeof(err_str),
2295 "\"Valid values are: 0-127\"");
2298 rc = l_ioctl(LNET_DEV_ID,
2299 IOC_LIBCFS_SET_CONNS_PER_PEER, &data);
2304 "Can not configure conns_per_peer value: %s",
2308 cYAML_build_error(rc, seq_no, ADD_CMD, name, err_str, err_rc);
2313 int lustre_lnet_config_ni_healthv(int value, bool all, char *ni_nid, int seq_no,
2314 struct cYAML **err_rc)
2318 nid = libcfs_str2nid(ni_nid);
2321 return lustre_lnet_config_healthv(value, all, nid,
2322 LNET_HEALTH_TYPE_LOCAL_NI,
2323 "ni healthv", seq_no, err_rc);
2326 int lustre_lnet_config_peer_ni_healthv(int value, bool all, char *lpni_nid,
2327 int seq_no, struct cYAML **err_rc)
2331 nid = libcfs_str2nid(lpni_nid);
2334 return lustre_lnet_config_healthv(value, all, nid,
2335 LNET_HEALTH_TYPE_PEER_NI,
2336 "peer_ni healthv", seq_no, err_rc);
2339 int lustre_lnet_set_peer_state(int state, char *lpni_nid, int seq_no,
2340 struct cYAML **err_rc)
2345 nid = libcfs_str2nid(lpni_nid);
2348 return lustre_lnet_config_peer(state, nid, "peer state", seq_no,
2352 int lustre_lnet_config_ni_conns_per_peer(int value, bool all, char *ni_nid,
2353 int seq_no, struct cYAML **err_rc)
2358 nid = libcfs_str2nid(ni_nid);
2361 return lustre_lnet_config_conns_per_peer(value, all, nid,
2362 "ni conns_per_peer",
2367 add_msg_stats_to_yaml_blk(struct cYAML *yaml,
2368 struct lnet_ioctl_comm_count *counts)
2370 if (cYAML_create_number(yaml, "put",
2371 counts->ico_put_count)
2374 if (cYAML_create_number(yaml, "get",
2375 counts->ico_get_count)
2378 if (cYAML_create_number(yaml, "reply",
2379 counts->ico_reply_count)
2382 if (cYAML_create_number(yaml, "ack",
2383 counts->ico_ack_count)
2386 if (cYAML_create_number(yaml, "hello",
2387 counts->ico_hello_count)
2394 static struct lnet_ioctl_comm_count *
2395 get_counts(struct lnet_ioctl_element_msg_stats *msg_stats, int idx)
2398 return &msg_stats->im_send_stats;
2400 return &msg_stats->im_recv_stats;
2402 return &msg_stats->im_drop_stats;
2408 create_local_udsp_info(struct lnet_ioctl_construct_udsp_info *udsp_info,
2409 struct cYAML *net_node)
2411 char tmp[LNET_MAX_STR_LEN];
2412 struct cYAML *udsp_net;
2413 bool created = false;
2417 /* add the UDSP info */
2418 udsp_net = cYAML_create_object(net_node, "udsp info");
2420 return LUSTRE_CFG_RC_OUT_OF_MEM;
2422 if (!cYAML_create_number(udsp_net, "net priority",
2423 (int) udsp_info->cud_net_priority))
2424 return LUSTRE_CFG_RC_OUT_OF_MEM;
2426 if (!cYAML_create_number(udsp_net, "nid priority",
2427 (int)udsp_info->cud_nid_priority))
2428 return LUSTRE_CFG_RC_OUT_OF_MEM;
2432 for (i = 0; i < LNET_MAX_SHOW_NUM_NID; i++) {
2433 memset(tmp, 0, LNET_MAX_STR_LEN);
2434 if (udsp_info->cud_pref_rtr_nid[i] == 0)
2437 pref = cYAML_create_object(udsp_net,
2438 "Preferred gateway NIDs");
2440 return LUSTRE_CFG_RC_OUT_OF_MEM;
2443 snprintf(tmp, sizeof(tmp), "NID-%d", i);
2444 if (!cYAML_create_string(pref, tmp,
2445 libcfs_nid2str(udsp_info->cud_pref_rtr_nid[i])))
2446 return LUSTRE_CFG_RC_OUT_OF_MEM;
2449 return LUSTRE_CFG_RC_NO_ERR;
2453 create_remote_udsp_info(struct lnet_ioctl_construct_udsp_info *udsp_info,
2454 struct cYAML *nid_node)
2456 char tmp[LNET_MAX_STR_LEN];
2457 struct cYAML *udsp_nid;
2458 bool created = false;
2462 /* add the UDSP info */
2463 udsp_nid = cYAML_create_object(nid_node, "udsp info");
2465 return LUSTRE_CFG_RC_OUT_OF_MEM;
2467 if (!cYAML_create_number(udsp_nid, "net priority",
2468 (int) udsp_info->cud_net_priority))
2469 return LUSTRE_CFG_RC_OUT_OF_MEM;
2471 if (!cYAML_create_number(udsp_nid, "nid priority",
2472 (int) udsp_info->cud_nid_priority))
2473 return LUSTRE_CFG_RC_OUT_OF_MEM;
2476 for (i = 0; i < LNET_MAX_SHOW_NUM_NID; i++) {
2477 memset(tmp, 0, LNET_MAX_STR_LEN);
2478 if (udsp_info->cud_pref_rtr_nid[i] == 0)
2481 pref = cYAML_create_object(udsp_nid,
2482 "Preferred gateway NIDs");
2484 return LUSTRE_CFG_RC_OUT_OF_MEM;
2487 snprintf(tmp, sizeof(tmp), "NID-%d", i);
2488 if (!cYAML_create_string(pref, tmp,
2489 libcfs_nid2str(udsp_info->cud_pref_rtr_nid[i])))
2490 return LUSTRE_CFG_RC_OUT_OF_MEM;
2495 for (i = 0; i < LNET_MAX_SHOW_NUM_NID; i++) {
2496 memset(tmp, 0, LNET_MAX_STR_LEN);
2497 if (udsp_info->cud_pref_nid[i] == 0)
2500 pref = cYAML_create_object(udsp_nid,
2501 "Preferred source NIDs");
2503 return LUSTRE_CFG_RC_OUT_OF_MEM;
2506 snprintf(tmp, sizeof(tmp), "NID-%d", i);
2507 if (!cYAML_create_string(pref, tmp,
2508 libcfs_nid2str(udsp_info->cud_pref_nid[i])))
2509 return LUSTRE_CFG_RC_OUT_OF_MEM;
2512 return LUSTRE_CFG_RC_NO_ERR;
2515 int lustre_lnet_show_net(char *nw, int detail, int seq_no,
2516 struct cYAML **show_rc, struct cYAML **err_rc,
2520 struct lnet_ioctl_config_ni *ni_data;
2521 struct lnet_ioctl_config_lnd_tunables *lnd;
2522 struct lnet_ioctl_element_stats *stats;
2523 struct lnet_ioctl_element_msg_stats msg_stats;
2524 struct lnet_ioctl_local_ni_hstats hstats;
2525 struct lnet_ioctl_construct_udsp_info udsp_info;
2526 __u32 net = LNET_NET_ANY;
2527 __u32 prev_net = LNET_NET_ANY;
2528 int rc = LUSTRE_CFG_RC_OUT_OF_MEM, i, j;
2530 struct cYAML *root = NULL, *tunables = NULL,
2531 *net_node = NULL, *interfaces = NULL,
2532 *item = NULL, *first_seq = NULL,
2533 *tmp = NULL, *statistics = NULL,
2535 int str_buf_len = LNET_MAX_SHOW_NUM_CPT * 2;
2536 char str_buf[str_buf_len];
2538 char err_str[LNET_MAX_STR_LEN] = "\"out of memory\"";
2539 bool exist = false, new_net = true;
2541 size_t buf_size = sizeof(*ni_data) + sizeof(*lnd) + sizeof(*stats);
2543 buf = calloc(1, buf_size);
2547 ni_data = (struct lnet_ioctl_config_ni *)buf;
2550 net = libcfs_str2net(nw);
2551 if (net == LNET_NET_ANY) {
2554 "\"cannot parse net '%s'\"", nw);
2555 rc = LUSTRE_CFG_RC_BAD_PARAM;
2560 root = cYAML_create_object(NULL, NULL);
2564 net_node = cYAML_create_seq(root, "net");
2565 if (net_node == NULL)
2571 memset(buf, 0, buf_size);
2573 LIBCFS_IOC_INIT_V2(*ni_data, lic_cfg_hdr);
2575 * set the ioc_len to the proper value since INIT assumes
2578 ni_data->lic_cfg_hdr.ioc_len = buf_size;
2579 ni_data->lic_idx = i;
2581 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_LOCAL_NI, ni_data);
2587 rc_net = LNET_NIDNET(ni_data->lic_nid);
2589 /* filter on provided data */
2590 if (net != LNET_NET_ANY &&
2594 /* if we're backing up don't store lo */
2595 if (backup && LNET_NETTYP(rc_net) == LOLND)
2598 /* default rc to -1 in case we hit the goto */
2602 stats = (struct lnet_ioctl_element_stats *)ni_data->lic_bulk;
2603 lnd = (struct lnet_ioctl_config_lnd_tunables *)
2604 (ni_data->lic_bulk + sizeof(*stats));
2606 if (rc_net != prev_net) {
2613 tmp = cYAML_create_string(net_node, "net type", libcfs_net2str(rc_net));
2617 if (first_seq == NULL)
2620 tmp = cYAML_create_seq(net_node, "local NI(s)");
2626 /* create the tree to be printed. */
2627 item = cYAML_create_seq_item(tmp);
2632 cYAML_create_string(item, "nid",
2633 libcfs_nid2str(ni_data->lic_nid)) == NULL)
2637 cYAML_create_string(item,
2639 (ni_data->lic_status ==
2640 LNET_NI_STATUS_UP) ?
2641 "up" : "down") == NULL)
2644 /* don't add interfaces unless there is at least one
2646 if (strlen(ni_data->lic_ni_intf) > 0) {
2647 interfaces = cYAML_create_object(item, "interfaces");
2648 if (interfaces == NULL)
2651 snprintf(str_buf, sizeof(str_buf), "%d", 0);
2652 if (cYAML_create_string(interfaces, str_buf,
2653 ni_data->lic_ni_intf) == NULL)
2662 goto continue_without_msg_stats;
2664 statistics = cYAML_create_object(item, "statistics");
2665 if (statistics == NULL)
2668 if (cYAML_create_number(statistics, "send_count",
2669 stats->iel_send_count)
2673 if (cYAML_create_number(statistics, "recv_count",
2674 stats->iel_recv_count)
2678 if (cYAML_create_number(statistics, "drop_count",
2679 stats->iel_drop_count)
2684 goto continue_without_udsp_info;
2686 LIBCFS_IOC_INIT_V2(udsp_info, cud_hdr);
2687 udsp_info.cud_nid = ni_data->lic_nid;
2688 udsp_info.cud_peer = false;
2689 rc = l_ioctl(LNET_DEV_ID,
2690 IOC_LIBCFS_GET_CONST_UDSP_INFO,
2694 goto continue_without_udsp_info;
2697 rc = create_local_udsp_info(&udsp_info, item);
2703 continue_without_udsp_info:
2705 goto continue_without_msg_stats;
2707 LIBCFS_IOC_INIT_V2(msg_stats, im_hdr);
2708 msg_stats.im_hdr.ioc_len = sizeof(msg_stats);
2709 msg_stats.im_idx = i;
2711 rc = l_ioctl(LNET_DEV_ID,
2712 IOC_LIBCFS_GET_LOCAL_NI_MSG_STATS,
2716 goto continue_without_msg_stats;
2719 for (k = 0; k < 3; k++) {
2720 struct lnet_ioctl_comm_count *counts;
2721 struct cYAML *msg_statistics = NULL;
2723 msg_statistics = cYAML_create_object(item,
2724 (char *)gmsg_stat_names[k]);
2725 if (msg_statistics == NULL)
2728 counts = get_counts(&msg_stats, k);
2732 if (!add_msg_stats_to_yaml_blk(msg_statistics,
2737 LIBCFS_IOC_INIT_V2(hstats, hlni_hdr);
2738 hstats.hlni_nid = ni_data->lic_nid;
2739 /* grab health stats */
2740 rc = l_ioctl(LNET_DEV_ID,
2741 IOC_LIBCFS_GET_LOCAL_HSTATS,
2745 goto continue_without_msg_stats;
2747 yhstats = cYAML_create_object(item, "health stats");
2750 if (cYAML_create_number(yhstats, "fatal_error",
2751 hstats.hlni_fatal_error)
2754 if (cYAML_create_number(yhstats, "health value",
2755 hstats.hlni_health_value)
2758 if (cYAML_create_number(yhstats, "interrupts",
2759 hstats.hlni_local_interrupt)
2762 if (cYAML_create_number(yhstats, "dropped",
2763 hstats.hlni_local_dropped)
2766 if (cYAML_create_number(yhstats, "aborted",
2767 hstats.hlni_local_aborted)
2770 if (cYAML_create_number(yhstats, "no route",
2771 hstats.hlni_local_no_route)
2774 if (cYAML_create_number(yhstats, "timeouts",
2775 hstats.hlni_local_timeout)
2778 if (cYAML_create_number(yhstats, "error",
2779 hstats.hlni_local_error)
2782 if (cYAML_create_number(yhstats, "ping_count",
2783 hstats.hlni_ping_count)
2786 if (cYAML_create_number(yhstats, "next_ping",
2787 hstats.hlni_next_ping)
2791 continue_without_msg_stats:
2792 tunables = cYAML_create_object(item, "tunables");
2796 rc = lustre_net_show_tunables(tunables, &lnd->lt_cmn);
2797 if (rc != LUSTRE_CFG_RC_NO_ERR)
2800 if (rc != LUSTRE_CFG_RC_NO_MATCH) {
2801 tunables = cYAML_create_object(item,
2803 if (tunables == NULL)
2807 rc = lustre_ni_show_tunables(tunables,
2808 LNET_NETTYP(rc_net),
2809 &lnd->lt_tun, backup);
2810 if (rc != LUSTRE_CFG_RC_NO_ERR &&
2811 rc != LUSTRE_CFG_RC_NO_MATCH)
2815 cYAML_create_number(item, "dev cpt",
2816 ni_data->lic_dev_cpt) == NULL)
2819 /* out put the CPTs in the format: "[x,x,x,...]" */
2821 limit = str_buf + str_buf_len - 3;
2822 pos += scnprintf(pos, limit - pos, "\"[");
2823 for (j = 0 ; ni_data->lic_ncpts >= 1 &&
2824 j < ni_data->lic_ncpts &&
2826 pos += scnprintf(pos, limit - pos,
2827 "%d", ni_data->lic_cpts[j]);
2828 if ((j + 1) < ni_data->lic_ncpts)
2829 pos += scnprintf(pos, limit - pos, ",");
2831 snprintf(pos, 3, "]\"");
2833 if (ni_data->lic_ncpts >= 1 &&
2834 cYAML_create_string(item, "CPT",
2840 /* Print out the net information only if show_rc is not provided */
2841 if (show_rc == NULL)
2842 cYAML_print_tree(root);
2844 if (l_errno != ENOENT) {
2847 "\"cannot get networks: %s\"",
2852 rc = LUSTRE_CFG_RC_NO_ERR;
2854 snprintf(err_str, sizeof(err_str), "\"success\"");
2856 if (show_rc == NULL || rc != LUSTRE_CFG_RC_NO_ERR || !exist) {
2857 cYAML_free_tree(root);
2858 } else if (show_rc != NULL && *show_rc != NULL) {
2859 struct cYAML *show_node;
2860 /* find the net node, if one doesn't exist
2861 * then insert one. Otherwise add to the one there
2863 show_node = cYAML_get_object_item(*show_rc, "net");
2864 if (show_node != NULL && cYAML_is_sequence(show_node)) {
2865 cYAML_insert_child(show_node, first_seq);
2868 } else if (show_node == NULL) {
2869 cYAML_insert_sibling((*show_rc)->cy_child,
2873 cYAML_free_tree(root);
2879 cYAML_build_error(rc, seq_no, SHOW_CMD, "net", err_str, err_rc);
2884 int lustre_lnet_enable_routing(int enable, int seq_no, struct cYAML **err_rc)
2886 struct lnet_ioctl_config_data data;
2887 int rc = LUSTRE_CFG_RC_NO_ERR;
2888 char err_str[LNET_MAX_STR_LEN] = "\"success\"";
2890 LIBCFS_IOC_INIT_V2(data, cfg_hdr);
2891 data.cfg_config_u.cfg_buffers.buf_enable = (enable) ? 1 : 0;
2893 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_CONFIG_RTR, &data);
2898 "\"cannot %s routing %s\"",
2899 (enable) ? "enable" : "disable", strerror(errno));
2904 cYAML_build_error(rc, seq_no,
2905 (enable) ? ADD_CMD : DEL_CMD,
2906 "routing", err_str, err_rc);
2911 static int ioctl_set_value(__u32 val, int ioc, char *name,
2912 int seq_no, struct cYAML **err_rc)
2914 struct lnet_ioctl_set_value data;
2915 int rc = LUSTRE_CFG_RC_NO_ERR;
2916 char err_str[LNET_MAX_STR_LEN] = "\"success\"";
2918 LIBCFS_IOC_INIT_V2(data, sv_hdr);
2919 data.sv_value = val;
2921 rc = l_ioctl(LNET_DEV_ID, ioc , &data);
2926 "\"cannot configure %s to %d: %s\"", name,
2927 val, strerror(errno));
2930 cYAML_build_error(rc, seq_no, ADD_CMD, name, err_str, err_rc);
2935 int lustre_lnet_config_recov_intrv(int intrv, int seq_no, struct cYAML **err_rc)
2937 int rc = LUSTRE_CFG_RC_NO_ERR;
2938 char err_str[LNET_MAX_STR_LEN] = "\"success\"";
2939 char val[LNET_MAX_STR_LEN];
2941 snprintf(val, sizeof(val), "%d", intrv);
2943 rc = write_sysfs_file(modparam_path, "lnet_recovery_interval", val,
2944 1, strlen(val) + 1);
2946 snprintf(err_str, sizeof(err_str),
2947 "\"cannot configure recovery interval: %s\"",
2950 cYAML_build_error(rc, seq_no, ADD_CMD, "recovery_interval", err_str, err_rc);
2955 int lustre_lnet_config_rtr_sensitivity(int sen, int seq_no, struct cYAML **err_rc)
2957 int rc = LUSTRE_CFG_RC_NO_ERR;
2958 char err_str[LNET_MAX_STR_LEN] = "\"success\"";
2959 char val[LNET_MAX_STR_LEN];
2961 snprintf(val, sizeof(val), "%d", sen);
2963 rc = write_sysfs_file(modparam_path, "router_sensitivity_percentage", val,
2964 1, strlen(val) + 1);
2966 snprintf(err_str, sizeof(err_str),
2967 "\"cannot configure router health sensitivity: %s\"",
2970 cYAML_build_error(rc, seq_no, ADD_CMD, "router_sensitivity", err_str, err_rc);
2975 int lustre_lnet_config_hsensitivity(int sen, int seq_no, struct cYAML **err_rc)
2977 int rc = LUSTRE_CFG_RC_NO_ERR;
2978 char err_str[LNET_MAX_STR_LEN] = "\"success\"";
2979 char val[LNET_MAX_STR_LEN];
2981 snprintf(val, sizeof(val), "%d", sen);
2983 rc = write_sysfs_file(modparam_path, "lnet_health_sensitivity", val,
2984 1, strlen(val) + 1);
2986 snprintf(err_str, sizeof(err_str),
2987 "\"cannot configure health sensitivity: %s\"",
2990 cYAML_build_error(rc, seq_no, ADD_CMD, "health_sensitivity", err_str, err_rc);
2995 int lustre_lnet_config_transaction_to(int timeout, int seq_no, struct cYAML **err_rc)
2997 int rc = LUSTRE_CFG_RC_NO_ERR;
2998 char err_str[LNET_MAX_STR_LEN] = "\"success\"";
2999 char val[LNET_MAX_STR_LEN];
3001 snprintf(val, sizeof(val), "%d", timeout);
3003 rc = write_sysfs_file(modparam_path, "lnet_transaction_timeout", val,
3004 1, strlen(val) + 1);
3006 snprintf(err_str, sizeof(err_str),
3007 "\"cannot configure transaction timeout: %s\"",
3010 cYAML_build_error(rc, seq_no, ADD_CMD, "transaction_timeout", err_str, err_rc);
3015 int lustre_lnet_config_retry_count(int count, int seq_no, struct cYAML **err_rc)
3017 int rc = LUSTRE_CFG_RC_NO_ERR;
3018 char err_str[LNET_MAX_STR_LEN] = "\"success\"";
3019 char val[LNET_MAX_STR_LEN];
3021 snprintf(val, sizeof(val), "%d", count);
3023 rc = write_sysfs_file(modparam_path, "lnet_retry_count", val,
3024 1, strlen(val) + 1);
3026 snprintf(err_str, sizeof(err_str),
3027 "\"cannot configure retry count: %s\"",
3030 cYAML_build_error(rc, seq_no, ADD_CMD, "retry_count", err_str, err_rc);
3035 int lustre_lnet_config_response_tracking(int val, int seq_no,
3036 struct cYAML **err_rc)
3038 int rc = LUSTRE_CFG_RC_NO_ERR;
3039 char err_str[LNET_MAX_STR_LEN];
3040 char val_str[LNET_MAX_STR_LEN];
3042 if (val < 0 || val > 3) {
3043 rc = LUSTRE_CFG_RC_BAD_PARAM;
3044 snprintf(err_str, sizeof(err_str),
3045 "\"Valid values are: 0, 1, 2, or 3\"");
3047 snprintf(err_str, sizeof(err_str), "\"success\"");
3049 snprintf(val_str, sizeof(val_str), "%d", val);
3051 rc = write_sysfs_file(modparam_path, "lnet_response_tracking",
3052 val_str, 1, strlen(val_str) + 1);
3054 snprintf(err_str, sizeof(err_str),
3055 "\"cannot configure response tracking: %s\"",
3059 cYAML_build_error(rc, seq_no, ADD_CMD, "response_tracking", err_str,
3065 int lustre_lnet_config_recovery_limit(int val, int seq_no,
3066 struct cYAML **err_rc)
3068 int rc = LUSTRE_CFG_RC_NO_ERR;
3069 char err_str[LNET_MAX_STR_LEN];
3070 char val_str[LNET_MAX_STR_LEN];
3073 rc = LUSTRE_CFG_RC_BAD_PARAM;
3074 snprintf(err_str, sizeof(err_str),
3075 "\"Must be greater than or equal to 0\"");
3077 snprintf(err_str, sizeof(err_str), "\"success\"");
3079 snprintf(val_str, sizeof(val_str), "%d", val);
3081 rc = write_sysfs_file(modparam_path, "lnet_recovery_limit",
3082 val_str, 1, strlen(val_str) + 1);
3084 snprintf(err_str, sizeof(err_str),
3085 "\"cannot configure recovery limit: %s\"",
3089 cYAML_build_error(rc, seq_no, ADD_CMD, "recovery_limit", err_str,
3095 int lustre_lnet_config_max_intf(int max, int seq_no, struct cYAML **err_rc)
3097 int rc = LUSTRE_CFG_RC_NO_ERR;
3098 char err_str[LNET_MAX_STR_LEN] = "\"success\"";
3099 char val[LNET_MAX_STR_LEN];
3101 snprintf(val, sizeof(val), "%d", max);
3103 rc = write_sysfs_file(modparam_path, "lnet_interfaces_max", val,
3104 1, strlen(val) + 1);
3106 snprintf(err_str, sizeof(err_str),
3107 "\"cannot configure max interfaces: %s\"",
3110 cYAML_build_error(rc, seq_no, ADD_CMD, "max_interfaces", err_str, err_rc);
3115 int lustre_lnet_config_discovery(int enable, int seq_no, struct cYAML **err_rc)
3117 int rc = LUSTRE_CFG_RC_NO_ERR;
3118 char err_str[LNET_MAX_STR_LEN] = "\"success\"";
3119 char val[LNET_MAX_STR_LEN];
3121 snprintf(val, sizeof(val), "%u", (enable) ? 0 : 1);
3123 rc = write_sysfs_file(modparam_path, "lnet_peer_discovery_disabled", val,
3124 1, strlen(val) + 1);
3126 snprintf(err_str, sizeof(err_str),
3127 "\"cannot configure discovery: %s\"",
3130 cYAML_build_error(rc, seq_no, ADD_CMD, "discovery", err_str, err_rc);
3136 int lustre_lnet_config_drop_asym_route(int drop, int seq_no,
3137 struct cYAML **err_rc)
3139 int rc = LUSTRE_CFG_RC_NO_ERR;
3140 char err_str[LNET_MAX_STR_LEN] = "\"success\"";
3141 char val[LNET_MAX_STR_LEN];
3143 snprintf(val, sizeof(val), "%u", (drop) ? 1 : 0);
3145 rc = write_sysfs_file(modparam_path, "lnet_drop_asym_route", val,
3146 1, strlen(val) + 1);
3148 snprintf(err_str, sizeof(err_str),
3149 "\"cannot configure drop asym route: %s\"",
3152 cYAML_build_error(rc, seq_no, ADD_CMD, "drop_asym_route",
3159 int lustre_lnet_config_numa_range(int range, int seq_no, struct cYAML **err_rc)
3161 return ioctl_set_value(range, IOC_LIBCFS_SET_NUMA_RANGE,
3162 "numa_range", seq_no, err_rc);
3165 int lustre_lnet_config_buffers(int tiny, int small, int large, int seq_no,
3166 struct cYAML **err_rc)
3168 struct lnet_ioctl_config_data data;
3169 int rc = LUSTRE_CFG_RC_NO_ERR;
3170 char err_str[LNET_MAX_STR_LEN] = "\"success\"";
3172 /* -1 indicates to ignore changes to this field */
3173 if (tiny < -1 || small < -1 || large < -1) {
3176 "\"tiny, small and large must be >= 0\"");
3177 rc = LUSTRE_CFG_RC_OUT_OF_RANGE_PARAM;
3181 LIBCFS_IOC_INIT_V2(data, cfg_hdr);
3182 data.cfg_config_u.cfg_buffers.buf_tiny = tiny;
3183 data.cfg_config_u.cfg_buffers.buf_small = small;
3184 data.cfg_config_u.cfg_buffers.buf_large = large;
3186 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_ADD_BUF, &data);
3191 "\"cannot configure buffers: %s\"", strerror(errno));
3196 cYAML_build_error(rc, seq_no, ADD_CMD, "buf", err_str, err_rc);
3201 int lustre_lnet_config_max_recovery_ping_interval(int interval, int seq_no,
3202 struct cYAML **err_rc)
3204 int rc = LUSTRE_CFG_RC_NO_ERR;
3205 char err_str[LNET_MAX_STR_LEN] = "\"success\"";
3206 char interval_str[LNET_MAX_STR_LEN];
3208 if (interval <= 0) {
3209 rc = LUSTRE_CFG_RC_BAD_PARAM;
3210 snprintf(err_str, sizeof(err_str),
3211 "\"must be strictly positive\"");
3214 snprintf(interval_str, sizeof(interval_str), "%d", interval);
3216 rc = write_sysfs_file(modparam_path,
3217 "lnet_max_recovery_ping_interval",
3219 strlen(interval_str) + 1);
3221 snprintf(err_str, sizeof(err_str),
3222 "\"cannot configure maximum recovery ping interval: %s\"",
3226 cYAML_build_error(rc, seq_no, ADD_CMD, "maximum recovery ping interval",
3233 int lustre_lnet_show_routing(int seq_no, struct cYAML **show_rc,
3234 struct cYAML **err_rc, bool backup)
3236 struct lnet_ioctl_config_data *data;
3237 struct lnet_ioctl_pool_cfg *pool_cfg = NULL;
3238 int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
3241 char *pools[LNET_NRBPOOLS] = {"tiny", "small", "large"};
3242 int buf_count[LNET_NRBPOOLS] = {0};
3243 struct cYAML *root = NULL, *pools_node = NULL,
3244 *type_node = NULL, *item = NULL, *cpt = NULL,
3245 *first_seq = NULL, *buffers = NULL;
3247 char err_str[LNET_MAX_STR_LEN] = "\"out of memory\"";
3248 char node_name[LNET_MAX_STR_LEN];
3251 buf = calloc(1, sizeof(*data) + sizeof(*pool_cfg));
3255 data = (struct lnet_ioctl_config_data *)buf;
3257 root = cYAML_create_object(NULL, NULL);
3262 pools_node = cYAML_create_object(root, "routing");
3264 pools_node = cYAML_create_seq(root, "routing");
3265 if (pools_node == NULL)
3269 LIBCFS_IOC_INIT_V2(*data, cfg_hdr);
3270 data->cfg_hdr.ioc_len = sizeof(struct lnet_ioctl_config_data) +
3271 sizeof(struct lnet_ioctl_pool_cfg);
3272 data->cfg_count = i;
3274 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_BUF, data);
3282 pool_cfg = (struct lnet_ioctl_pool_cfg *)data->cfg_bulk;
3285 goto calculate_buffers;
3287 snprintf(node_name, sizeof(node_name), "cpt[%d]", i);
3288 item = cYAML_create_seq_item(pools_node);
3292 if (first_seq == NULL)
3295 cpt = cYAML_create_object(item, node_name);
3300 /* create the tree and print */
3301 for (j = 0; j < LNET_NRBPOOLS; j++) {
3303 type_node = cYAML_create_object(cpt, pools[j]);
3304 if (type_node == NULL)
3308 cYAML_create_number(type_node, "npages",
3309 pool_cfg->pl_pools[j].pl_npages)
3313 cYAML_create_number(type_node, "nbuffers",
3314 pool_cfg->pl_pools[j].
3315 pl_nbuffers) == NULL)
3318 cYAML_create_number(type_node, "credits",
3319 pool_cfg->pl_pools[j].
3320 pl_credits) == NULL)
3323 cYAML_create_number(type_node, "mincredits",
3324 pool_cfg->pl_pools[j].
3325 pl_mincredits) == NULL)
3327 /* keep track of the total count for each of the
3328 * tiny, small and large buffers */
3329 buf_count[j] += pool_cfg->pl_pools[j].pl_nbuffers;
3333 if (pool_cfg != NULL) {
3335 if (cYAML_create_number(pools_node, "enable",
3336 pool_cfg->pl_routing) ==
3340 goto add_buffer_section;
3343 item = cYAML_create_seq_item(pools_node);
3347 if (cYAML_create_number(item, "enable", pool_cfg->pl_routing) ==
3353 /* create a buffers entry in the show. This is necessary so that
3354 * if the YAML output is used to configure a node, the buffer
3355 * configuration takes hold */
3356 buffers = cYAML_create_object(root, "buffers");
3357 if (buffers == NULL)
3360 for (i = 0; i < LNET_NRBPOOLS; i++) {
3361 if (cYAML_create_number(buffers, pools[i], buf_count[i]) == NULL)
3365 if (show_rc == NULL)
3366 cYAML_print_tree(root);
3368 if (l_errno != ENOENT) {
3371 "\"cannot get routing information: %s\"",
3376 rc = LUSTRE_CFG_RC_NO_ERR;
3378 snprintf(err_str, sizeof(err_str), "\"success\"");
3379 rc = LUSTRE_CFG_RC_NO_ERR;
3383 if (show_rc == NULL || rc != LUSTRE_CFG_RC_NO_ERR || !exist) {
3384 cYAML_free_tree(root);
3385 } else if (show_rc != NULL && *show_rc != NULL) {
3386 struct cYAML *routing_node;
3387 /* there should exist only one routing block and one
3388 * buffers block. If there already exists a previous one
3389 * then don't add another */
3390 routing_node = cYAML_get_object_item(*show_rc, "routing");
3391 if (routing_node == NULL) {
3392 cYAML_insert_sibling((*show_rc)->cy_child,
3396 cYAML_free_tree(root);
3402 cYAML_build_error(rc, seq_no, SHOW_CMD, "routing", err_str, err_rc);
3407 int lustre_lnet_show_peer(char *knid, int detail, int seq_no,
3408 struct cYAML **show_rc, struct cYAML **err_rc,
3412 * TODO: This function is changing in a future patch to accommodate
3413 * PEER_LIST and proper filtering on any nid of the peer
3415 struct lnet_ioctl_peer_cfg peer_info;
3416 struct lnet_peer_ni_credit_info *lpni_cri;
3417 struct lnet_ioctl_element_stats *lpni_stats;
3418 struct lnet_ioctl_element_msg_stats *msg_stats;
3419 struct lnet_ioctl_peer_ni_hstats *hstats;
3420 struct lnet_ioctl_construct_udsp_info udsp_info;
3422 int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
3427 struct cYAML *root = NULL, *peer = NULL, *peer_ni = NULL,
3428 *first_seq = NULL, *peer_root = NULL, *tmp = NULL,
3429 *msg_statistics = NULL, *statistics = NULL,
3431 char err_str[LNET_MAX_STR_LEN] = "\"out of memory\"";
3432 struct lnet_process_id *list = NULL;
3437 /* create struct cYAML root object */
3438 root = cYAML_create_object(NULL, NULL);
3442 peer_root = cYAML_create_seq(root, "peer");
3443 if (peer_root == NULL)
3447 size = count * sizeof(struct lnet_process_id);
3448 list = malloc(size);
3454 list[0].nid = libcfs_str2nid(knid);
3458 memset(&peer_info, 0, sizeof(peer_info));
3459 LIBCFS_IOC_INIT_V2(peer_info, prcfg_hdr);
3460 peer_info.prcfg_hdr.ioc_len = sizeof(peer_info);
3461 peer_info.prcfg_size = size;
3462 peer_info.prcfg_bulk = list;
3465 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_PEER_LIST,
3467 count = peer_info.prcfg_count;
3471 if (l_errno != E2BIG) {
3474 "\"cannot get peer list: %s\"",
3480 size = peer_info.prcfg_size;
3481 list = malloc(size);
3490 data = malloc(size);
3496 for (i = 0; i < count; i++) {
3498 memset(&peer_info, 0, sizeof(peer_info));
3499 LIBCFS_IOC_INIT_V2(peer_info, prcfg_hdr);
3500 peer_info.prcfg_hdr.ioc_len = sizeof(peer_info);
3501 peer_info.prcfg_prim_nid = list[i].nid;
3502 peer_info.prcfg_size = size;
3503 peer_info.prcfg_bulk = data;
3506 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_PEER_NI,
3511 if (l_errno != E2BIG) {
3514 "\"cannot get peer information: %s\"",
3520 size = peer_info.prcfg_size;
3521 data = malloc(size);
3529 peer = cYAML_create_seq_item(peer_root);
3533 if (first_seq == NULL)
3536 lnet_nid_t pnid = peer_info.prcfg_prim_nid;
3537 if (cYAML_create_string(peer, "primary nid",
3538 libcfs_nid2str(pnid))
3541 if (cYAML_create_string(peer, "Multi-Rail",
3542 peer_info.prcfg_mr ? "True" : "False")
3546 * print out the state of the peer only if details are
3551 cYAML_create_number(peer, "peer state",
3552 peer_info.prcfg_state)
3557 tmp = cYAML_create_seq(peer, "peer ni");
3562 for (j = 0; j < peer_info.prcfg_count; j++) {
3564 lpni_cri = (void*)nidp + sizeof(nidp);
3565 lpni_stats = (void *)lpni_cri + sizeof(*lpni_cri);
3566 msg_stats = (void *)lpni_stats + sizeof(*lpni_stats);
3567 hstats = (void *)msg_stats + sizeof(*msg_stats);
3568 lpni_data = (void *)hstats + sizeof(*hstats);
3570 peer_ni = cYAML_create_seq_item(tmp);
3571 if (peer_ni == NULL)
3574 if (cYAML_create_string(peer_ni, "nid",
3575 libcfs_nid2str(*nidp))
3583 goto continue_without_udsp_info;
3585 LIBCFS_IOC_INIT_V2(udsp_info, cud_hdr);
3586 udsp_info.cud_nid = *nidp;
3587 udsp_info.cud_peer = true;
3588 rc = l_ioctl(LNET_DEV_ID,
3589 IOC_LIBCFS_GET_CONST_UDSP_INFO,
3593 goto continue_without_udsp_info;
3596 rc = create_remote_udsp_info(&udsp_info, peer_ni);
3602 continue_without_udsp_info:
3603 if (cYAML_create_string(peer_ni, "state",
3604 lpni_cri->cr_aliveness)
3611 if (cYAML_create_number(peer_ni, "max_ni_tx_credits",
3612 lpni_cri->cr_ni_peer_tx_credits)
3616 if (cYAML_create_number(peer_ni, "available_tx_credits",
3617 lpni_cri->cr_peer_tx_credits)
3621 if (cYAML_create_number(peer_ni, "min_tx_credits",
3622 lpni_cri->cr_peer_min_tx_credits)
3626 if (cYAML_create_number(peer_ni, "tx_q_num_of_buf",
3627 lpni_cri->cr_peer_tx_qnob)
3631 if (cYAML_create_number(peer_ni, "available_rtr_credits",
3632 lpni_cri->cr_peer_rtr_credits)
3636 if (cYAML_create_number(peer_ni, "min_rtr_credits",
3637 lpni_cri->cr_peer_min_rtr_credits)
3641 if (cYAML_create_number(peer_ni, "refcount",
3642 lpni_cri->cr_refcount) == NULL)
3645 statistics = cYAML_create_object(peer_ni, "statistics");
3646 if (statistics == NULL)
3649 if (cYAML_create_number(statistics, "send_count",
3650 lpni_stats->iel_send_count)
3654 if (cYAML_create_number(statistics, "recv_count",
3655 lpni_stats->iel_recv_count)
3659 if (cYAML_create_number(statistics, "drop_count",
3660 lpni_stats->iel_drop_count)
3667 for (k = 0; k < 3; k++) {
3668 struct lnet_ioctl_comm_count *counts;
3670 msg_statistics = cYAML_create_object(peer_ni,
3671 (char *) gmsg_stat_names[k]);
3672 if (msg_statistics == NULL)
3675 counts = get_counts(msg_stats, k);
3679 if (!add_msg_stats_to_yaml_blk(msg_statistics,
3684 yhstats = cYAML_create_object(peer_ni, "health stats");
3687 if (cYAML_create_number(yhstats, "health value",
3688 hstats->hlpni_health_value)
3691 if (cYAML_create_number(yhstats, "dropped",
3692 hstats->hlpni_remote_dropped)
3695 if (cYAML_create_number(yhstats, "timeout",
3696 hstats->hlpni_remote_timeout)
3699 if (cYAML_create_number(yhstats, "error",
3700 hstats->hlpni_remote_error)
3703 if (cYAML_create_number(yhstats, "network timeout",
3704 hstats->hlpni_network_timeout)
3707 if (cYAML_create_number(yhstats, "ping_count",
3708 hstats->hlpni_ping_count)
3712 if (cYAML_create_number(yhstats, "next_ping",
3713 hstats->hlpni_next_ping)
3720 /* print output iff show_rc is not provided */
3721 if (show_rc == NULL)
3722 cYAML_print_tree(root);
3724 snprintf(err_str, sizeof(err_str), "\"success\"");
3725 rc = LUSTRE_CFG_RC_NO_ERR;
3730 if (show_rc == NULL || rc != LUSTRE_CFG_RC_NO_ERR || !exist) {
3731 cYAML_free_tree(root);
3732 } else if (show_rc != NULL && *show_rc != NULL) {
3733 struct cYAML *show_node;
3734 /* find the peer node, if one doesn't exist then
3735 * insert one. Otherwise add to the one there
3737 show_node = cYAML_get_object_item(*show_rc,
3739 if (show_node != NULL && cYAML_is_sequence(show_node)) {
3740 cYAML_insert_child(show_node, first_seq);
3743 } else if (show_node == NULL) {
3744 cYAML_insert_sibling((*show_rc)->cy_child,
3748 cYAML_free_tree(root);
3754 cYAML_build_error(rc, seq_no, SHOW_CMD, "peer", err_str,
3760 int lustre_lnet_list_peer(int seq_no,
3761 struct cYAML **show_rc, struct cYAML **err_rc)
3763 struct lnet_ioctl_peer_cfg peer_info;
3764 int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
3769 struct cYAML *root = NULL, *list_root = NULL, *first_seq = NULL;
3770 char err_str[LNET_MAX_STR_LEN] = "\"out of memory\"";
3771 struct lnet_process_id *list = NULL;
3773 memset(&peer_info, 0, sizeof(peer_info));
3775 /* create struct cYAML root object */
3776 root = cYAML_create_object(NULL, NULL);
3780 list_root = cYAML_create_seq(root, "peer list");
3781 if (list_root == NULL)
3785 size = count * sizeof(struct lnet_process_id);
3786 list = malloc(size);
3792 LIBCFS_IOC_INIT_V2(peer_info, prcfg_hdr);
3793 peer_info.prcfg_hdr.ioc_len = sizeof(peer_info);
3794 peer_info.prcfg_size = size;
3795 peer_info.prcfg_bulk = list;
3798 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_PEER_LIST, &peer_info);
3799 count = peer_info.prcfg_count;
3803 if (l_errno != E2BIG) {
3806 "\"cannot get peer list: %s\"",
3812 size = peer_info.prcfg_size;
3813 list = malloc(size);
3820 /* count is now the actual number of ids in the list. */
3821 for (i = 0; i < count; i++) {
3822 if (cYAML_create_string(list_root, "nid",
3823 libcfs_nid2str(list[i].nid))
3828 /* print output iff show_rc is not provided */
3829 if (show_rc == NULL)
3830 cYAML_print_tree(root);
3832 snprintf(err_str, sizeof(err_str), "\"success\"");
3833 rc = LUSTRE_CFG_RC_NO_ERR;
3838 if (show_rc == NULL || rc != LUSTRE_CFG_RC_NO_ERR) {
3839 cYAML_free_tree(root);
3840 } else if (show_rc != NULL && *show_rc != NULL) {
3841 struct cYAML *show_node;
3842 /* find the peer node, if one doesn't exist then
3843 * insert one. Otherwise add to the one there
3845 show_node = cYAML_get_object_item(*show_rc,
3847 if (show_node != NULL && cYAML_is_sequence(show_node)) {
3848 cYAML_insert_child(show_node, first_seq);
3851 } else if (show_node == NULL) {
3852 cYAML_insert_sibling((*show_rc)->cy_child,
3856 cYAML_free_tree(root);
3862 cYAML_build_error(rc, seq_no, SHOW_CMD, "peer", err_str,
3868 static void add_to_global(struct cYAML *show_rc, struct cYAML *node,
3871 struct cYAML *show_node;
3873 show_node = cYAML_get_object_item(show_rc, "global");
3874 if (show_node != NULL)
3875 cYAML_insert_sibling(show_node->cy_child,
3878 cYAML_insert_sibling(show_rc->cy_child,
3883 static int build_global_yaml_entry(char *err_str, int err_len, int seq_no,
3884 char *name, __u64 value,
3885 struct cYAML **show_rc,
3886 struct cYAML **err_rc, int err)
3888 int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
3889 struct cYAML *root = NULL, *global = NULL;
3896 root = cYAML_create_object(NULL, NULL);
3900 global = cYAML_create_object(root, "global");
3904 if (cYAML_create_number(global, name,
3908 if (show_rc == NULL)
3909 cYAML_print_tree(root);
3911 snprintf(err_str, err_len, "\"success\"");
3913 rc = LUSTRE_CFG_RC_NO_ERR;
3916 if (show_rc == NULL || rc != LUSTRE_CFG_RC_NO_ERR) {
3917 cYAML_free_tree(root);
3918 } else if (show_rc != NULL && *show_rc != NULL) {
3919 add_to_global(*show_rc, global, root);
3924 cYAML_build_error(rc, seq_no, SHOW_CMD, "global", err_str, err_rc);
3929 static int ioctl_show_global_values(int ioc, int seq_no, char *name,
3930 struct cYAML **show_rc,
3931 struct cYAML **err_rc)
3933 struct lnet_ioctl_set_value data;
3936 char err_str[LNET_MAX_STR_LEN] = "\"out of memory\"";
3938 LIBCFS_IOC_INIT_V2(data, sv_hdr);
3940 rc = l_ioctl(LNET_DEV_ID, ioc, &data);
3945 "\"cannot get %s: %s\"",
3946 name, strerror(l_errno));
3949 return build_global_yaml_entry(err_str, sizeof(err_str), seq_no, name,
3950 data.sv_value, show_rc, err_rc, l_errno);
3953 int lustre_lnet_show_recov_intrv(int seq_no, struct cYAML **show_rc,
3954 struct cYAML **err_rc)
3956 int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
3957 char val[LNET_MAX_STR_LEN];
3958 int intrv = -1, l_errno = 0;
3959 char err_str[LNET_MAX_STR_LEN] = "\"out of memory\"";
3961 rc = read_sysfs_file(modparam_path, "lnet_recovery_interval", val,
3965 snprintf(err_str, sizeof(err_str),
3966 "\"cannot get recovery interval: %d\"", rc);
3971 return build_global_yaml_entry(err_str, sizeof(err_str), seq_no,
3972 "recovery_interval", intrv, show_rc,
3976 int lustre_lnet_show_hsensitivity(int seq_no, struct cYAML **show_rc,
3977 struct cYAML **err_rc)
3979 int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
3980 char val[LNET_MAX_STR_LEN];
3981 int sen = -1, l_errno = 0;
3982 char err_str[LNET_MAX_STR_LEN] = "\"out of memory\"";
3984 rc = read_sysfs_file(modparam_path, "lnet_health_sensitivity", val,
3988 snprintf(err_str, sizeof(err_str),
3989 "\"cannot get health sensitivity: %d\"", rc);
3994 return build_global_yaml_entry(err_str, sizeof(err_str), seq_no,
3995 "health_sensitivity", sen, show_rc,
3999 int lustre_lnet_show_rtr_sensitivity(int seq_no, struct cYAML **show_rc,
4000 struct cYAML **err_rc)
4002 int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
4003 char val[LNET_MAX_STR_LEN];
4004 int sen = -1, l_errno = 0;
4005 char err_str[LNET_MAX_STR_LEN] = "\"out of memory\"";
4007 rc = read_sysfs_file(modparam_path, "router_sensitivity_percentage", val,
4011 snprintf(err_str, sizeof(err_str),
4012 "\"cannot get router sensitivity percentage: %d\"", rc);
4017 return build_global_yaml_entry(err_str, sizeof(err_str), seq_no,
4018 "router_sensitivity", sen, show_rc,
4022 int lustre_lnet_show_lnd_timeout(int seq_no, struct cYAML **show_rc,
4023 struct cYAML **err_rc)
4025 char val[LNET_MAX_STR_LEN];
4026 char err_str[LNET_MAX_STR_LEN] = "\"out of memory\"";
4033 rc = cfs_get_param_paths(&path, "lnet_lnd_timeout");
4036 snprintf(err_str, sizeof(err_str),
4037 "\"cannot get LND timeout: %d\"", rc);
4038 return build_global_yaml_entry(err_str, sizeof(err_str), seq_no,
4039 "lnd_timeout", lnd_to, show_rc,
4043 fd = open(path.gl_pathv[0], O_RDONLY);
4046 snprintf(err_str, sizeof(err_str),
4047 "\"error opening %s\"", path.gl_pathv[0]);
4051 rc = read(fd, val, sizeof(val));
4058 snprintf(err_str, sizeof(err_str),
4059 "\"error reading %s\"", path.gl_pathv[0]);
4066 cfs_free_param_data(&path);
4068 return build_global_yaml_entry(err_str, sizeof(err_str), seq_no,
4069 "lnd_timeout", lnd_to, show_rc,
4073 int lustre_lnet_show_transaction_to(int seq_no, struct cYAML **show_rc,
4074 struct cYAML **err_rc)
4076 int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
4077 char val[LNET_MAX_STR_LEN];
4078 int tto = -1, l_errno = 0;
4079 char err_str[LNET_MAX_STR_LEN] = "\"out of memory\"";
4081 rc = read_sysfs_file(modparam_path, "lnet_transaction_timeout", val,
4085 snprintf(err_str, sizeof(err_str),
4086 "\"cannot get transaction timeout: %d\"", rc);
4091 return build_global_yaml_entry(err_str, sizeof(err_str), seq_no,
4092 "transaction_timeout", tto, show_rc,
4096 int lustre_lnet_show_retry_count(int seq_no, struct cYAML **show_rc,
4097 struct cYAML **err_rc)
4099 int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
4100 char val[LNET_MAX_STR_LEN];
4101 int retry_count = -1, l_errno = 0;
4102 char err_str[LNET_MAX_STR_LEN] = "\"out of memory\"";
4104 rc = read_sysfs_file(modparam_path, "lnet_retry_count", val,
4108 snprintf(err_str, sizeof(err_str),
4109 "\"cannot get retry count: %d\"", rc);
4111 retry_count = atoi(val);
4114 return build_global_yaml_entry(err_str, sizeof(err_str), seq_no,
4115 "retry_count", retry_count, show_rc,
4119 int lustre_lnet_calc_service_id(__u64 *service_id)
4121 int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
4122 char val[LNET_MAX_STR_LEN];
4123 int service_port = -1, l_errno = 0;
4125 rc = read_sysfs_file(o2ib_modparam_path, "service", val,
4129 fprintf(stderr, "error:\n msg: \"cannot get service port: %s (%d)\"\n",
4130 strerror(l_errno), -l_errno);
4133 service_port = atoi(val);
4136 *service_id = htobe64(((__u64)RDMA_PS_TCP << 16) + service_port);
4138 return LUSTRE_CFG_RC_NO_ERR;
4141 int lustre_lnet_setup_mrrouting(struct cYAML **err_rc)
4144 int rc = LUSTRE_CFG_RC_OUT_OF_MEM, i;
4146 char err_str[LNET_MAX_STR_LEN] = "\"out of memory\"";
4147 struct lnet_ioctl_config_ni *ni_data;
4148 struct lnet_ioctl_config_lnd_tunables *lnd;
4149 struct lnet_ioctl_element_stats *stats;
4150 size_t buf_size = sizeof(*ni_data) + sizeof(*lnd) + sizeof(*stats);
4151 char ifstr_buf[LNET_INTERFACES_NUM*LNET_MAX_STR_LEN];
4152 char *ifstr_ptr, *tmp_ptr, *tmp_ptr2;
4153 int if_cnt = 0, prc;
4154 char syscmdbuf[LNET_MAX_STR_LEN];
4155 char cmdpath[LNET_MAX_STR_LEN];
4156 bool use_custom = false;
4158 buf = calloc(1, buf_size);
4162 ni_data = (struct lnet_ioctl_config_ni *)buf;
4165 ifstr_ptr = ifstr_buf;
4170 memset(buf, 0, buf_size);
4172 LIBCFS_IOC_INIT_V2(*ni_data, lic_cfg_hdr);
4173 /* set the ioc_len to the proper value since INIT assumes
4176 ni_data->lic_cfg_hdr.ioc_len = buf_size;
4177 ni_data->lic_idx = i;
4179 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_LOCAL_NI, ni_data);
4185 rc_net = LNET_NIDNET(ni_data->lic_nid);
4187 /* only need to setup routing for tcp */
4188 if (LNET_NETTYP(rc_net) != SOCKLND)
4191 /* don't add interfaces unless there is at least one
4194 if (strlen(ni_data->lic_ni_intf) > 0) {
4196 strcat(ifstr_ptr, ",");
4197 strcat(ifstr_ptr, ni_data->lic_ni_intf);
4202 if (l_errno != ENOENT) {
4205 "\"cannot get networks: %s\"",
4210 rc = LUSTRE_CFG_RC_NO_ERR;
4213 snprintf(err_str, sizeof(err_str), "\"success\"");
4216 tmp_ptr = getenv("KSOCKLND_CONFIG");
4218 tmp_ptr2 = strrchr(tmp_ptr, '/');
4219 if (tmp_ptr2 && !strcmp(tmp_ptr2, "/ksocklnd-config")) {
4220 snprintf(cmdpath, sizeof(cmdpath), "%s",
4227 snprintf(cmdpath, sizeof(cmdpath),
4228 "/usr/sbin/ksocklnd-config");
4230 prc = snprintf(0, 0, "%s %s", cmdpath, ifstr_ptr);
4236 "\"snprintf failed : %s\"",
4239 } else if (prc >= LNET_MAX_STR_LEN) {
4240 snprintf(err_str, sizeof(err_str),
4241 "\"ksocklnd-config: argument too long\"");
4243 prc = snprintf(syscmdbuf, sizeof(syscmdbuf), "%s %s",
4244 cmdpath, ifstr_ptr);
4250 "\"snprintf failed : %s\"",
4256 rc = system(syscmdbuf);
4261 "\"failed to execute ksocklnd-config : %s\"",
4271 cYAML_build_error(rc, -1, MANAGE_CMD, "setup-mrrouting", err_str,
4277 static int show_recovery_queue(enum lnet_health_type type, char *name,
4278 int seq_no, struct cYAML **show_rc,
4279 struct cYAML **err_rc)
4281 struct lnet_ioctl_recovery_list nid_list;
4282 struct cYAML *root = NULL, *nids = NULL;
4284 char err_str[LNET_MAX_STR_LEN] = "failed to print recovery queue\n";
4286 LIBCFS_IOC_INIT_V2(nid_list, rlst_hdr);
4287 nid_list.rlst_type = type;
4289 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_RECOVERY_QUEUE, &nid_list);
4295 if (nid_list.rlst_num_nids == 0)
4298 root = cYAML_create_object(NULL, NULL);
4302 nids = cYAML_create_object(root, name);
4308 for (i = 0; i < nid_list.rlst_num_nids; i++) {
4309 char nidenum[LNET_MAX_STR_LEN];
4310 snprintf(nidenum, sizeof(nidenum), "nid-%d", i);
4311 if (!cYAML_create_string(nids, nidenum,
4312 libcfs_nid2str(nid_list.rlst_nid_array[i])))
4316 snprintf(err_str, sizeof(err_str), "success\n");
4321 if (show_rc == NULL || rc != LUSTRE_CFG_RC_NO_ERR) {
4322 cYAML_free_tree(root);
4323 } else if (show_rc != NULL && *show_rc != NULL) {
4324 struct cYAML *show_node;
4325 /* find the net node, if one doesn't exist
4326 * then insert one. Otherwise add to the one there
4328 show_node = cYAML_get_object_item(*show_rc, name);
4329 if (show_node != NULL && cYAML_is_sequence(show_node)) {
4330 cYAML_insert_child(show_node, nids);
4333 } else if (show_node == NULL) {
4334 cYAML_insert_sibling((*show_rc)->cy_child,
4338 cYAML_free_tree(root);
4344 cYAML_build_error(rc, seq_no, SHOW_CMD, name, err_str, err_rc);
4349 int lustre_lnet_show_peer_debug_info(char *peer_nid, int seq_no,
4350 struct cYAML **err_rc)
4352 struct libcfs_ioctl_data data;
4354 char err_str[LNET_MAX_STR_LEN] = "Error";
4355 lnet_nid_t pnid = LNET_NID_ANY;
4358 rc = LUSTRE_CFG_RC_BAD_PARAM;
4359 snprintf(err_str, LNET_MAX_STR_LEN,
4360 "--nid must be specified");
4364 pnid = libcfs_str2nid(peer_nid);
4365 if (pnid == LNET_NID_ANY) {
4366 rc = LUSTRE_CFG_RC_BAD_PARAM;
4367 snprintf(err_str, LNET_MAX_STR_LEN,
4368 "badly formatted primary NID: %s", peer_nid);
4372 LIBCFS_IOC_INIT(data);
4373 data.ioc_net = LNET_NIDNET(pnid);
4374 data.ioc_nid = pnid;
4376 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_PEER, &data);
4380 cYAML_build_error(rc, seq_no, "debug", "peer", err_str,
4386 int lustre_lnet_show_local_ni_recovq(int seq_no, struct cYAML **show_rc,
4387 struct cYAML **err_rc)
4389 return show_recovery_queue(LNET_HEALTH_TYPE_LOCAL_NI, "local NI recovery",
4390 seq_no, show_rc, err_rc);
4393 int lustre_lnet_show_peer_ni_recovq(int seq_no, struct cYAML **show_rc,
4394 struct cYAML **err_rc)
4396 return show_recovery_queue(LNET_HEALTH_TYPE_PEER_NI, "peer NI recovery",
4397 seq_no, show_rc, err_rc);
4400 int lustre_lnet_show_response_tracking(int seq_no, struct cYAML **show_rc,
4401 struct cYAML **err_rc)
4403 int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
4404 char val[LNET_MAX_STR_LEN];
4405 int rsp_tracking = -1, l_errno = 0;
4406 char err_str[LNET_MAX_STR_LEN] = "\"out of memory\"";
4408 rc = read_sysfs_file(modparam_path, "lnet_response_tracking", val,
4412 snprintf(err_str, sizeof(err_str),
4413 "\"cannot get lnet_response_tracking value: %d\"", rc);
4415 rsp_tracking = atoi(val);
4418 return build_global_yaml_entry(err_str, sizeof(err_str), seq_no,
4419 "response_tracking", rsp_tracking,
4420 show_rc, err_rc, l_errno);
4423 int lustre_lnet_show_recovery_limit(int seq_no, struct cYAML **show_rc,
4424 struct cYAML **err_rc)
4426 int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
4427 char val[LNET_MAX_STR_LEN];
4428 int recov_limit = -1, l_errno = 0;
4429 char err_str[LNET_MAX_STR_LEN];
4431 snprintf(err_str, sizeof(err_str), "\"out of memory\"");
4433 rc = read_sysfs_file(modparam_path, "lnet_recovery_limit", val,
4437 snprintf(err_str, sizeof(err_str),
4438 "\"cannot get lnet_recovery_limit value: %d\"", rc);
4440 recov_limit = atoi(val);
4443 return build_global_yaml_entry(err_str, sizeof(err_str), seq_no,
4444 "recovery_limit", recov_limit,
4445 show_rc, err_rc, l_errno);
4448 int lustre_lnet_show_max_recovery_ping_interval(int seq_no,
4449 struct cYAML **show_rc,
4450 struct cYAML **err_rc)
4452 int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
4453 char val[LNET_MAX_STR_LEN];
4454 int interval = -1, l_errno = 0;
4455 char err_str[LNET_MAX_STR_LEN];
4457 snprintf(err_str, sizeof(err_str), "\"out of memory\"");
4459 rc = read_sysfs_file(modparam_path, "lnet_max_recovery_ping_interval",
4460 val, 1, sizeof(val));
4463 snprintf(err_str, sizeof(err_str),
4464 "\"cannot get lnet_max_recovery_ping_interval value: %d\"",
4467 interval = atoi(val);
4470 return build_global_yaml_entry(err_str, sizeof(err_str), seq_no,
4471 "max_recovery_ping_interval", interval,
4472 show_rc, err_rc, l_errno);
4476 int lustre_lnet_show_max_intf(int seq_no, struct cYAML **show_rc,
4477 struct cYAML **err_rc)
4479 int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
4480 char val[LNET_MAX_STR_LEN];
4481 int max_intf = -1, l_errno = 0;
4482 char err_str[LNET_MAX_STR_LEN] = "\"out of memory\"";
4484 rc = read_sysfs_file(modparam_path, "lnet_interfaces_max", val,
4488 snprintf(err_str, sizeof(err_str),
4489 "\"cannot get max interfaces: %d\"", rc);
4491 max_intf = atoi(val);
4494 return build_global_yaml_entry(err_str, sizeof(err_str), seq_no,
4495 "max_interfaces", max_intf, show_rc,
4499 int lustre_lnet_show_discovery(int seq_no, struct cYAML **show_rc,
4500 struct cYAML **err_rc)
4502 int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
4503 char val[LNET_MAX_STR_LEN];
4504 int discovery = -1, l_errno = 0;
4505 char err_str[LNET_MAX_STR_LEN] = "\"out of memory\"";
4507 rc = read_sysfs_file(modparam_path, "lnet_peer_discovery_disabled", val,
4511 snprintf(err_str, sizeof(err_str),
4512 "\"cannot get discovery setting: %d\"", rc);
4515 * The kernel stores a discovery disabled value. User space
4516 * shows whether discovery is enabled. So the value must be
4519 discovery = !atoi(val);
4522 return build_global_yaml_entry(err_str, sizeof(err_str), seq_no,
4523 "discovery", discovery, show_rc,
4527 int lustre_lnet_show_drop_asym_route(int seq_no, struct cYAML **show_rc,
4528 struct cYAML **err_rc)
4530 int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
4531 char val[LNET_MAX_STR_LEN];
4532 int drop_asym_route = -1, l_errno = 0;
4533 char err_str[LNET_MAX_STR_LEN] = "\"out of memory\"";
4535 rc = read_sysfs_file(modparam_path, "lnet_drop_asym_route", val,
4539 snprintf(err_str, sizeof(err_str),
4540 "\"cannot get drop asym route setting: %d\"", rc);
4542 drop_asym_route = atoi(val);
4545 return build_global_yaml_entry(err_str, sizeof(err_str), seq_no,
4546 "drop_asym_route", drop_asym_route,
4547 show_rc, err_rc, l_errno);
4550 int lustre_lnet_show_numa_range(int seq_no, struct cYAML **show_rc,
4551 struct cYAML **err_rc)
4553 return ioctl_show_global_values(IOC_LIBCFS_GET_NUMA_RANGE, seq_no,
4554 "numa_range", show_rc, err_rc);
4557 int lustre_lnet_show_stats(int seq_no, struct cYAML **show_rc,
4558 struct cYAML **err_rc)
4560 struct lnet_ioctl_lnet_stats data;
4561 struct lnet_counters *cntrs;
4563 char err_str[LNET_MAX_STR_LEN] = "\"out of memory\"";
4564 struct cYAML *root = NULL, *stats = NULL;
4566 LIBCFS_IOC_INIT_V2(data, st_hdr);
4568 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_LNET_STATS, &data);
4572 "\"cannot get lnet statistics: %s\"",
4577 rc = LUSTRE_CFG_RC_OUT_OF_MEM;
4579 cntrs = &data.st_cntrs;
4581 root = cYAML_create_object(NULL, NULL);
4585 stats = cYAML_create_object(root, "statistics");
4589 if (!cYAML_create_number(stats, "msgs_alloc",
4590 cntrs->lct_common.lcc_msgs_alloc))
4593 if (!cYAML_create_number(stats, "msgs_max",
4594 cntrs->lct_common.lcc_msgs_max))
4597 if (!cYAML_create_number(stats, "rst_alloc",
4598 cntrs->lct_health.lch_rst_alloc))
4601 if (!cYAML_create_number(stats, "errors",
4602 cntrs->lct_common.lcc_errors))
4605 if (!cYAML_create_number(stats, "send_count",
4606 cntrs->lct_common.lcc_send_count))
4609 if (!cYAML_create_number(stats, "resend_count",
4610 cntrs->lct_health.lch_resend_count))
4613 if (!cYAML_create_number(stats, "response_timeout_count",
4614 cntrs->lct_health.lch_response_timeout_count))
4617 if (!cYAML_create_number(stats, "local_interrupt_count",
4618 cntrs->lct_health.lch_local_interrupt_count))
4621 if (!cYAML_create_number(stats, "local_dropped_count",
4622 cntrs->lct_health.lch_local_dropped_count))
4625 if (!cYAML_create_number(stats, "local_aborted_count",
4626 cntrs->lct_health.lch_local_aborted_count))
4629 if (!cYAML_create_number(stats, "local_no_route_count",
4630 cntrs->lct_health.lch_local_no_route_count))
4633 if (!cYAML_create_number(stats, "local_timeout_count",
4634 cntrs->lct_health.lch_local_timeout_count))
4637 if (!cYAML_create_number(stats, "local_error_count",
4638 cntrs->lct_health.lch_local_error_count))
4641 if (!cYAML_create_number(stats, "remote_dropped_count",
4642 cntrs->lct_health.lch_remote_dropped_count))
4645 if (!cYAML_create_number(stats, "remote_error_count",
4646 cntrs->lct_health.lch_remote_error_count))
4649 if (!cYAML_create_number(stats, "remote_timeout_count",
4650 cntrs->lct_health.lch_remote_timeout_count))
4653 if (!cYAML_create_number(stats, "network_timeout_count",
4654 cntrs->lct_health.lch_network_timeout_count))
4657 if (!cYAML_create_number(stats, "recv_count",
4658 cntrs->lct_common.lcc_recv_count))
4661 if (!cYAML_create_number(stats, "route_count",
4662 cntrs->lct_common.lcc_route_count))
4665 if (!cYAML_create_number(stats, "drop_count",
4666 cntrs->lct_common.lcc_drop_count))
4669 if (!cYAML_create_number(stats, "send_length",
4670 cntrs->lct_common.lcc_send_length))
4673 if (!cYAML_create_number(stats, "recv_length",
4674 cntrs->lct_common.lcc_recv_length))
4677 if (!cYAML_create_number(stats, "route_length",
4678 cntrs->lct_common.lcc_route_length))
4681 if (!cYAML_create_number(stats, "drop_length",
4682 cntrs->lct_common.lcc_drop_length))
4686 cYAML_print_tree(root);
4688 snprintf(err_str, sizeof(err_str), "\"success\"");
4689 rc = LUSTRE_CFG_RC_NO_ERR;
4691 if (show_rc == NULL || rc != LUSTRE_CFG_RC_NO_ERR) {
4692 cYAML_free_tree(root);
4693 } else if (show_rc != NULL && *show_rc != NULL) {
4694 cYAML_insert_sibling((*show_rc)->cy_child,
4701 cYAML_build_error(rc, seq_no, SHOW_CMD, "statistics", err_str, err_rc);
4706 int lustre_lnet_reset_stats(int seq_no, struct cYAML **err_rc)
4708 struct libcfs_ioctl_data data;
4709 int rc = LUSTRE_CFG_RC_NO_ERR;
4711 char err_str[LNET_MAX_STR_LEN];
4713 LIBCFS_IOC_INIT(data);
4715 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_RESET_LNET_STATS, &data);
4720 "\"cannot reset lnet statistics: %s\"",
4724 snprintf(err_str, sizeof(err_str), "\"success\"");
4725 rc = LUSTRE_CFG_RC_NO_ERR;
4728 cYAML_build_error(rc, seq_no, SHOW_CMD, "statistics", err_str, err_rc);
4732 typedef int (*cmd_handler_t)(struct cYAML *tree,
4733 struct cYAML **show_rc,
4734 struct cYAML **err_rc);
4736 static int handle_yaml_config_route(struct cYAML *tree, struct cYAML **show_rc,
4737 struct cYAML **err_rc)
4739 struct cYAML *net, *gw, *hop, *prio, *sen, *seq_no;
4741 net = cYAML_get_object_item(tree, "net");
4742 gw = cYAML_get_object_item(tree, "gateway");
4743 hop = cYAML_get_object_item(tree, "hop");
4744 prio = cYAML_get_object_item(tree, "priority");
4745 sen = cYAML_get_object_item(tree, "health_sensitivity");
4746 seq_no = cYAML_get_object_item(tree, "seq_no");
4748 return lustre_lnet_config_route((net) ? net->cy_valuestring : NULL,
4749 (gw) ? gw->cy_valuestring : NULL,
4750 (hop) ? hop->cy_valueint : -1,
4751 (prio) ? prio->cy_valueint : -1,
4752 (sen) ? sen->cy_valueint : -1,
4753 (seq_no) ? seq_no->cy_valueint : -1,
4759 * 0: <intf_name>['['<expr>']']
4760 * 1: <intf_name>['['<expr>']']
4762 static int yaml_copy_intf_info(struct cYAML *intf_tree,
4763 struct lnet_dlc_network_descr *nw_descr)
4765 struct cYAML *child = NULL;
4766 int intf_num = 0, rc = LUSTRE_CFG_RC_NO_ERR;
4767 struct lnet_dlc_intf_descr *intf_descr, *tmp;
4769 if (intf_tree == NULL || nw_descr == NULL)
4770 return LUSTRE_CFG_RC_BAD_PARAM;
4772 /* now grab all the interfaces and their cpts */
4773 child = intf_tree->cy_child;
4774 while (child != NULL) {
4775 if (child->cy_valuestring == NULL) {
4776 child = child->cy_next;
4780 if (strlen(child->cy_valuestring) >= LNET_MAX_STR_LEN)
4783 rc = lustre_lnet_add_intf_descr(&nw_descr->nw_intflist,
4784 child->cy_valuestring,
4785 strlen(child->cy_valuestring));
4786 if (rc != LUSTRE_CFG_RC_NO_ERR)
4790 child = child->cy_next;
4794 return LUSTRE_CFG_RC_MISSING_PARAM;
4799 list_for_each_entry_safe(intf_descr, tmp, &nw_descr->nw_intflist,
4801 list_del(&intf_descr->intf_on_network);
4802 free_intf_descr(intf_descr);
4809 yaml_extract_cmn_tunables(struct cYAML *tree,
4810 struct lnet_ioctl_config_lnd_cmn_tunables *tunables)
4812 struct cYAML *tun, *item;
4814 tun = cYAML_get_object_item(tree, "tunables");
4816 item = cYAML_get_object_item(tun, "peer_timeout");
4818 tunables->lct_peer_timeout = item->cy_valueint;
4820 tunables->lct_peer_timeout = -1;
4821 item = cYAML_get_object_item(tun, "peer_credits");
4823 tunables->lct_peer_tx_credits = item->cy_valueint;
4824 item = cYAML_get_object_item(tun, "peer_buffer_credits");
4826 tunables->lct_peer_rtr_credits = item->cy_valueint;
4827 item = cYAML_get_object_item(tun, "credits");
4829 tunables->lct_max_tx_credits = item->cy_valueint;
4838 yaml_extract_tunables(struct cYAML *tree,
4839 struct lnet_ioctl_config_lnd_tunables *tunables,
4844 rc = yaml_extract_cmn_tunables(tree, &tunables->lt_cmn);
4849 lustre_yaml_extract_lnd_tunables(tree, net_type,
4856 yaml_extract_cpt(struct cYAML *tree,
4857 struct cfs_expr_list **global_cpts)
4862 smp = cYAML_get_object_item(tree, "CPT");
4864 rc = cfs_expr_list_parse(smp->cy_valuestring,
4865 strlen(smp->cy_valuestring),
4866 0, UINT_MAX, global_cpts);
4868 *global_cpts = NULL;
4874 * - net type: <net>[<NUM>]
4876 * - nid: <ip>@<net>[<NUM>]
4879 * 0: <intf_name>['['<expr>']']
4880 * 1: <intf_name>['['<expr>']']
4882 * peer_timeout: <NUM>
4883 * peer_credits: <NUM>
4884 * peer_buffer_credits: <NUM>
4887 * peercredits_hiw: <NUM>
4888 * map_on_demand: <NUM>
4889 * concurrent_sends: <NUM>
4890 * fmr_pool_size: <NUM>
4891 * fmr_flush_trigger: <NUM>
4894 * At least one interface is required. If no interfaces are provided the
4895 * network interface can not be configured.
4897 static int handle_yaml_config_ni(struct cYAML *tree, struct cYAML **show_rc,
4898 struct cYAML **err_rc)
4900 struct cYAML *net, *intf, *seq_no, *ip2net = NULL, *local_nis = NULL,
4902 int num_entries = 0, rc;
4903 struct lnet_dlc_network_descr nw_descr;
4904 struct cfs_expr_list *global_cpts = NULL;
4905 struct lnet_ioctl_config_lnd_tunables tunables;
4908 memset(&tunables, 0, sizeof(tunables));
4909 /* Use LND defaults */
4910 tunables.lt_cmn.lct_peer_timeout = -1;
4911 tunables.lt_cmn.lct_peer_tx_credits = -1;
4912 tunables.lt_cmn.lct_peer_rtr_credits = -1;
4913 tunables.lt_cmn.lct_max_tx_credits = -1;
4915 INIT_LIST_HEAD(&nw_descr.network_on_rule);
4916 INIT_LIST_HEAD(&nw_descr.nw_intflist);
4918 ip2net = cYAML_get_object_item(tree, "ip2net");
4919 net = cYAML_get_object_item(tree, "net type");
4921 nw_descr.nw_id = libcfs_str2net(net->cy_valuestring);
4923 nw_descr.nw_id = LOLND;
4926 * if neither net nor ip2nets are present, then we can not
4927 * configure the network.
4929 if (!net && !ip2net)
4930 return LUSTRE_CFG_RC_MISSING_PARAM;
4932 local_nis = cYAML_get_object_item(tree, "local NI(s)");
4933 if (local_nis == NULL)
4934 return LUSTRE_CFG_RC_MISSING_PARAM;
4936 if (!cYAML_is_sequence(local_nis))
4937 return LUSTRE_CFG_RC_BAD_PARAM;
4939 while (cYAML_get_next_seq_item(local_nis, &item) != NULL) {
4940 intf = cYAML_get_object_item(item, "interfaces");
4943 num_entries = yaml_copy_intf_info(intf, &nw_descr);
4944 if (num_entries <= 0) {
4945 cYAML_build_error(num_entries, -1, "ni", "add",
4946 "bad interface list",
4948 return LUSTRE_CFG_RC_BAD_PARAM;
4952 found = yaml_extract_tunables(tree, &tunables,
4953 LNET_NETTYP(nw_descr.nw_id));
4954 yaml_extract_cpt(tree, &global_cpts);
4955 seq_no = cYAML_get_object_item(tree, "seq_no");
4957 rc = lustre_lnet_config_ni(&nw_descr, global_cpts,
4958 (ip2net) ? ip2net->cy_valuestring : NULL,
4959 (found) ? &tunables : NULL,
4960 (seq_no) ? seq_no->cy_valueint : -1,
4963 if (global_cpts != NULL)
4964 cfs_expr_list_free(global_cpts);
4971 * - net-spec: <tcp|o2ib|gni>[NUM]
4973 * 0: <intf name>['['<expr>']']
4974 * 1: <intf name>['['<expr>']']
4976 * 0: <expr.expr.expr.expr>
4977 * 1: <expr.expr.expr.expr>
4979 static int handle_yaml_config_ip2nets(struct cYAML *tree,
4980 struct cYAML **show_rc,
4981 struct cYAML **err_rc)
4983 struct cYAML *net, *ip_range, *item = NULL, *intf = NULL,
4985 struct lustre_lnet_ip2nets ip2nets;
4986 struct lustre_lnet_ip_range_descr *ip_range_descr = NULL,
4988 int rc = LUSTRE_CFG_RC_NO_ERR;
4989 struct cfs_expr_list *global_cpts = NULL;
4990 struct cfs_expr_list *el, *el_tmp;
4991 struct lnet_ioctl_config_lnd_tunables tunables;
4992 struct lnet_dlc_intf_descr *intf_descr, *intf_tmp;
4995 memset(&tunables, 0, sizeof(tunables));
4997 /* initialize all lists */
4998 INIT_LIST_HEAD(&ip2nets.ip2nets_ip_ranges);
4999 INIT_LIST_HEAD(&ip2nets.ip2nets_net.network_on_rule);
5000 INIT_LIST_HEAD(&ip2nets.ip2nets_net.nw_intflist);
5002 net = cYAML_get_object_item(tree, "net-spec");
5004 return LUSTRE_CFG_RC_BAD_PARAM;
5006 if (net != NULL && net->cy_valuestring == NULL)
5007 return LUSTRE_CFG_RC_BAD_PARAM;
5009 /* assign the network id */
5010 ip2nets.ip2nets_net.nw_id = libcfs_str2net(net->cy_valuestring);
5011 if (ip2nets.ip2nets_net.nw_id == LNET_NET_ANY)
5012 return LUSTRE_CFG_RC_BAD_PARAM;
5014 seq_no = cYAML_get_object_item(tree, "seq_no");
5016 intf = cYAML_get_object_item(tree, "interfaces");
5018 rc = yaml_copy_intf_info(intf, &ip2nets.ip2nets_net);
5020 return LUSTRE_CFG_RC_BAD_PARAM;
5023 ip_range = cYAML_get_object_item(tree, "ip-range");
5024 if (ip_range != NULL) {
5025 item = ip_range->cy_child;
5026 while (item != NULL) {
5027 if (item->cy_valuestring == NULL) {
5028 item = item->cy_next;
5032 rc = lustre_lnet_add_ip_range(&ip2nets.ip2nets_ip_ranges,
5033 item->cy_valuestring);
5035 if (rc != LUSTRE_CFG_RC_NO_ERR)
5038 item = item->cy_next;
5042 found = yaml_extract_tunables(tree, &tunables,
5043 LNET_NETTYP(ip2nets.ip2nets_net.nw_id));
5044 yaml_extract_cpt(tree, &global_cpts);
5046 rc = lustre_lnet_config_ip2nets(&ip2nets,
5047 (found) ? &tunables : NULL,
5049 (seq_no) ? seq_no->cy_valueint : -1,
5052 if (global_cpts != NULL)
5053 cfs_expr_list_free(global_cpts);
5056 * don't stop because there was no match. Continue processing the
5057 * rest of the rules. If non-match then nothing is configured
5059 if (rc == LUSTRE_CFG_RC_NO_MATCH)
5060 rc = LUSTRE_CFG_RC_NO_ERR;
5062 list_for_each_entry_safe(intf_descr, intf_tmp,
5063 &ip2nets.ip2nets_net.nw_intflist,
5065 list_del(&intf_descr->intf_on_network);
5066 free_intf_descr(intf_descr);
5069 list_for_each_entry_safe(ip_range_descr, tmp,
5070 &ip2nets.ip2nets_ip_ranges,
5072 list_del(&ip_range_descr->ipr_entry);
5073 list_for_each_entry_safe(el, el_tmp, &ip_range_descr->ipr_expr,
5075 list_del(&el->el_link);
5076 cfs_expr_list_free(el);
5078 free(ip_range_descr);
5084 static int handle_yaml_del_ni(struct cYAML *tree, struct cYAML **show_rc,
5085 struct cYAML **err_rc)
5087 struct cYAML *net = NULL, *intf = NULL, *seq_no = NULL, *item = NULL,
5089 int num_entries, rc;
5090 struct lnet_dlc_network_descr nw_descr;
5092 INIT_LIST_HEAD(&nw_descr.network_on_rule);
5093 INIT_LIST_HEAD(&nw_descr.nw_intflist);
5095 net = cYAML_get_object_item(tree, "net type");
5097 nw_descr.nw_id = libcfs_str2net(net->cy_valuestring);
5099 local_nis = cYAML_get_object_item(tree, "local NI(s)");
5100 if (local_nis == NULL)
5101 return LUSTRE_CFG_RC_MISSING_PARAM;
5103 if (!cYAML_is_sequence(local_nis))
5104 return LUSTRE_CFG_RC_BAD_PARAM;
5106 while (cYAML_get_next_seq_item(local_nis, &item) != NULL) {
5107 intf = cYAML_get_object_item(item, "interfaces");
5110 num_entries = yaml_copy_intf_info(intf, &nw_descr);
5111 if (num_entries <= 0) {
5112 cYAML_build_error(num_entries, -1, "ni", "add",
5113 "bad interface list",
5115 return LUSTRE_CFG_RC_BAD_PARAM;
5119 seq_no = cYAML_get_object_item(tree, "seq_no");
5121 rc = lustre_lnet_del_ni((net) ? &nw_descr : NULL,
5122 (seq_no) ? seq_no->cy_valueint : -1,
5128 /* Create a nidstring parseable by the nidstrings library from the nid
5129 * information encoded in the CYAML structure.
5130 * NOTE: Caller must free memory allocated to nidstr
5132 static int yaml_nids2nidstr(struct cYAML *nids_entry, char **nidstr,
5133 char *prim_nid, int cmd)
5135 int num_strs = 0, rc;
5136 size_t buf_size, buf_pos, nidstr_len = 0;
5138 struct cYAML *child = NULL, *entry = NULL;
5140 if (cYAML_is_sequence(nids_entry)) {
5141 while (cYAML_get_next_seq_item(nids_entry, &child)) {
5142 entry = cYAML_get_object_item(child, "nid");
5143 /* don't count an empty entry */
5144 if (!entry || !entry->cy_valuestring)
5148 (strcmp(entry->cy_valuestring, prim_nid) == 0)) {
5149 if (cmd == LNETCTL_DEL_CMD) {
5151 * primary nid is present in the list of
5152 * nids so that means we want to delete
5153 * the entire peer, so no need to go
5154 * further. Just delete the entire peer.
5156 return LUSTRE_CFG_RC_NO_ERR;
5163 * + 1 for the space separating each string, and
5164 * accounts for the terminating null char
5166 nidstr_len += strlen(entry->cy_valuestring) + 1;
5171 if (num_strs == 0 && !prim_nid)
5172 return LUSTRE_CFG_RC_MISSING_PARAM;
5173 else if (num_strs == 0) /* Only the primary nid was given to add/del */
5174 return LUSTRE_CFG_RC_NO_ERR;
5176 buffer = malloc(nidstr_len);
5178 return LUSTRE_CFG_RC_OUT_OF_MEM;
5180 /* now grab all the nids */
5183 buf_size = nidstr_len;
5185 while (cYAML_get_next_seq_item(nids_entry, &child)) {
5186 entry = cYAML_get_object_item(child, "nid");
5187 if (!entry || !entry->cy_valuestring)
5191 (strcmp(entry->cy_valuestring, prim_nid) == 0))
5195 rc = snprintf(buffer + buf_pos, buf_size, " ");
5196 buf_pos += (rc < buf_size) ? rc : buf_size;
5197 buf_size = nidstr_len - buf_pos;
5200 rc = snprintf(buffer + buf_pos, buf_size, "%s",
5201 entry->cy_valuestring);
5202 buf_pos += (rc < buf_size) ? rc : buf_size;
5203 buf_size = nidstr_len - buf_pos;
5208 return LUSTRE_CFG_RC_NO_ERR;
5211 static int handle_yaml_peer_common(struct cYAML *tree, struct cYAML **show_rc,
5212 struct cYAML **err_rc, int cmd)
5214 int rc, num_nids = 0, seqn;
5215 bool mr_value = false;
5216 char *nidstr = NULL, *prim_nidstr;
5217 char err_str[LNET_MAX_STR_LEN];
5218 struct cYAML *seq_no, *prim_nid, *mr, *peer_nis;
5219 lnet_nid_t lnet_nidlist[LNET_MAX_NIDS_PER_PEER];
5220 lnet_nid_t pnid = LNET_NID_ANY;
5223 seq_no = cYAML_get_object_item(tree, "seq_no");
5224 seqn = seq_no ? seq_no->cy_valueint : -1;
5226 prim_nid = cYAML_get_object_item(tree, "primary nid");
5227 peer_nis = cYAML_get_object_item(tree, "peer ni");
5229 rc = LUSTRE_CFG_RC_BAD_PARAM;
5230 snprintf(err_str, LNET_MAX_STR_LEN,
5231 "\"primary nid\" must be specified");
5235 prim_nidstr = prim_nid->cy_valuestring;
5237 /* if the provided primary NID is bad, no need to go any further */
5238 pnid = libcfs_str2nid(prim_nidstr);
5239 if (pnid == LNET_NID_ANY) {
5240 rc = LUSTRE_CFG_RC_BAD_PARAM;
5241 snprintf(err_str, LNET_MAX_STR_LEN,
5242 "badly formatted primary NID: %s", prim_nidstr);
5246 rc = yaml_nids2nidstr(peer_nis, &nidstr, prim_nidstr, cmd);
5247 if (rc == LUSTRE_CFG_RC_MISSING_PARAM) {
5248 snprintf(err_str, LNET_MAX_STR_LEN,
5249 "No nids defined in YAML block");
5251 } else if (rc == LUSTRE_CFG_RC_OUT_OF_MEM) {
5252 snprintf(err_str, LNET_MAX_STR_LEN, "out of memory");
5254 } else if (rc != LUSTRE_CFG_RC_NO_ERR) {
5255 snprintf(err_str, LNET_MAX_STR_LEN,
5256 "Unrecognized error %d", rc);
5262 num_nids = lustre_lnet_parse_nidstr(nidstr, lnet_nidlist,
5263 LNET_MAX_NIDS_PER_PEER,
5271 if (cmd == LNETCTL_ADD_CMD) {
5272 mr = cYAML_get_object_item(tree, "Multi-Rail");
5274 if (mr && mr->cy_valuestring) {
5275 if (strcmp(mr->cy_valuestring, "False") == 0)
5277 else if (strcmp(mr->cy_valuestring, "True") != 0) {
5278 rc = LUSTRE_CFG_RC_BAD_PARAM;
5279 snprintf(err_str, LNET_MAX_STR_LEN,
5280 "Multi-Rail must be set to \"True\" or \"False\" found \"%s\"",
5281 mr->cy_valuestring);
5287 rc = lustre_lnet_mod_peer_nidlist(pnid, lnet_nidlist, cmd,
5288 num_nids, mr_value, force,
5295 if (rc != LUSTRE_CFG_RC_NO_ERR)
5296 cYAML_build_error(rc, seqn, "peer",
5297 cmd == LNETCTL_ADD_CMD ? ADD_CMD : DEL_CMD,
5303 static int handle_yaml_config_peer(struct cYAML *tree, struct cYAML **show_rc,
5304 struct cYAML **err_rc)
5306 return handle_yaml_peer_common(tree, show_rc, err_rc, LNETCTL_ADD_CMD);
5309 static int handle_yaml_del_peer(struct cYAML *tree, struct cYAML **show_rc,
5310 struct cYAML **err_rc)
5312 return handle_yaml_peer_common(tree, show_rc, err_rc, LNETCTL_DEL_CMD);
5315 static int handle_yaml_config_buffers(struct cYAML *tree,
5316 struct cYAML **show_rc,
5317 struct cYAML **err_rc)
5320 struct cYAML *tiny, *small, *large, *seq_no;
5322 tiny = cYAML_get_object_item(tree, "tiny");
5323 small = cYAML_get_object_item(tree, "small");
5324 large = cYAML_get_object_item(tree, "large");
5325 seq_no = cYAML_get_object_item(tree, "seq_no");
5327 rc = lustre_lnet_config_buffers((tiny) ? tiny->cy_valueint : -1,
5328 (small) ? small->cy_valueint : -1,
5329 (large) ? large->cy_valueint : -1,
5330 (seq_no) ? seq_no->cy_valueint : -1,
5336 static int handle_yaml_config_routing(struct cYAML *tree,
5337 struct cYAML **show_rc,
5338 struct cYAML **err_rc)
5340 int rc = LUSTRE_CFG_RC_NO_ERR;
5341 struct cYAML *seq_no, *enable;
5343 seq_no = cYAML_get_object_item(tree, "seq_no");
5344 enable = cYAML_get_object_item(tree, "enable");
5347 rc = lustre_lnet_enable_routing(enable->cy_valueint,
5349 seq_no->cy_valueint : -1,
5356 static int handle_yaml_del_route(struct cYAML *tree, struct cYAML **show_rc,
5357 struct cYAML **err_rc)
5361 struct cYAML *seq_no;
5363 net = cYAML_get_object_item(tree, "net");
5364 gw = cYAML_get_object_item(tree, "gateway");
5365 seq_no = cYAML_get_object_item(tree, "seq_no");
5367 return lustre_lnet_del_route((net) ? net->cy_valuestring : NULL,
5368 (gw) ? gw->cy_valuestring : NULL,
5369 (seq_no) ? seq_no->cy_valueint : -1,
5373 static int handle_yaml_del_routing(struct cYAML *tree, struct cYAML **show_rc,
5374 struct cYAML **err_rc)
5376 struct cYAML *seq_no;
5378 seq_no = cYAML_get_object_item(tree, "seq_no");
5380 return lustre_lnet_enable_routing(0, (seq_no) ?
5381 seq_no->cy_valueint : -1,
5385 static int handle_yaml_show_route(struct cYAML *tree, struct cYAML **show_rc,
5386 struct cYAML **err_rc)
5392 struct cYAML *detail;
5393 struct cYAML *seq_no;
5395 net = cYAML_get_object_item(tree, "net");
5396 gw = cYAML_get_object_item(tree, "gateway");
5397 hop = cYAML_get_object_item(tree, "hop");
5398 prio = cYAML_get_object_item(tree, "priority");
5399 detail = cYAML_get_object_item(tree, "detail");
5400 seq_no = cYAML_get_object_item(tree, "seq_no");
5402 return lustre_lnet_show_route((net) ? net->cy_valuestring : NULL,
5403 (gw) ? gw->cy_valuestring : NULL,
5404 (hop) ? hop->cy_valueint : -1,
5405 (prio) ? prio->cy_valueint : -1,
5406 (detail) ? detail->cy_valueint : 0,
5407 (seq_no) ? seq_no->cy_valueint : -1,
5408 show_rc, err_rc, false);
5411 static int handle_yaml_show_net(struct cYAML *tree, struct cYAML **show_rc,
5412 struct cYAML **err_rc)
5414 struct cYAML *net, *detail, *seq_no;
5416 net = cYAML_get_object_item(tree, "net type");
5417 detail = cYAML_get_object_item(tree, "detail");
5418 seq_no = cYAML_get_object_item(tree, "seq_no");
5420 return lustre_lnet_show_net((net) ? net->cy_valuestring : NULL,
5421 (detail) ? detail->cy_valueint : 0,
5422 (seq_no) ? seq_no->cy_valueint : -1,
5423 show_rc, err_rc, false);
5426 static int handle_yaml_show_routing(struct cYAML *tree, struct cYAML **show_rc,
5427 struct cYAML **err_rc)
5429 struct cYAML *seq_no;
5431 seq_no = cYAML_get_object_item(tree, "seq_no");
5433 return lustre_lnet_show_routing((seq_no) ? seq_no->cy_valueint : -1,
5434 show_rc, err_rc, false);
5437 static int handle_yaml_show_peers(struct cYAML *tree, struct cYAML **show_rc,
5438 struct cYAML **err_rc)
5440 struct cYAML *seq_no, *nid, *detail;
5442 seq_no = cYAML_get_object_item(tree, "seq_no");
5443 detail = cYAML_get_object_item(tree, "detail");
5444 nid = cYAML_get_object_item(tree, "nid");
5446 return lustre_lnet_show_peer((nid) ? nid->cy_valuestring : NULL,
5447 (detail) ? detail->cy_valueint : 0,
5448 (seq_no) ? seq_no->cy_valueint : -1,
5449 show_rc, err_rc, false);
5452 static int handle_yaml_show_stats(struct cYAML *tree, struct cYAML **show_rc,
5453 struct cYAML **err_rc)
5455 struct cYAML *seq_no;
5457 seq_no = cYAML_get_object_item(tree, "seq_no");
5459 return lustre_lnet_show_stats((seq_no) ? seq_no->cy_valueint : -1,
5463 static int handle_yaml_config_numa(struct cYAML *tree, struct cYAML **show_rc,
5464 struct cYAML **err_rc)
5466 struct cYAML *seq_no, *range;
5468 seq_no = cYAML_get_object_item(tree, "seq_no");
5469 range = cYAML_get_object_item(tree, "range");
5471 return lustre_lnet_config_numa_range(range ? range->cy_valueint : -1,
5472 seq_no ? seq_no->cy_valueint : -1,
5476 static int handle_yaml_del_numa(struct cYAML *tree, struct cYAML **show_rc,
5477 struct cYAML **err_rc)
5479 struct cYAML *seq_no;
5481 seq_no = cYAML_get_object_item(tree, "seq_no");
5483 return lustre_lnet_config_numa_range(0, seq_no ? seq_no->cy_valueint : -1,
5487 static int handle_yaml_show_numa(struct cYAML *tree, struct cYAML **show_rc,
5488 struct cYAML **err_rc)
5490 struct cYAML *seq_no;
5492 seq_no = cYAML_get_object_item(tree, "seq_no");
5494 return lustre_lnet_show_numa_range(seq_no ? seq_no->cy_valueint : -1,
5498 static int handle_yaml_del_udsp(struct cYAML *tree, struct cYAML **show_rc,
5499 struct cYAML **err_rc)
5501 struct cYAML *seq_no, *idx;
5503 seq_no = cYAML_get_object_item(tree, "seq_no");
5504 idx = cYAML_get_object_item(tree, "idx");
5506 return lustre_lnet_del_udsp(idx ? idx->cy_valueint : -1,
5507 seq_no ? seq_no->cy_valueint : -1,
5511 static int handle_yaml_config_udsp(struct cYAML *tree, struct cYAML **show_rc,
5512 struct cYAML **err_rc)
5514 struct cYAML *seq_no, *src, *rte, *dst, *prio, *idx;
5515 union lnet_udsp_action action;
5517 seq_no = cYAML_get_object_item(tree, "seq_no");
5518 src = cYAML_get_object_item(tree, "src");
5519 rte = cYAML_get_object_item(tree, "rte");
5520 dst = cYAML_get_object_item(tree, "dst");
5521 prio = cYAML_get_object_item(tree, "priority");
5522 idx = cYAML_get_object_item(tree, "idx");
5524 action.udsp_priority = prio ? prio->cy_valueint : -1;
5526 return lustre_lnet_add_udsp(src ? src->cy_valuestring : NULL,
5527 dst ? dst->cy_valuestring : NULL,
5528 rte ? rte->cy_valuestring : NULL,
5529 prio ? "priority" : "",
5531 idx ? idx->cy_valueint : -1,
5532 seq_no ? seq_no->cy_valueint : -1,
5536 static int handle_yaml_show_udsp(struct cYAML *tree, struct cYAML **show_rc,
5537 struct cYAML **err_rc)
5539 struct cYAML *seq_no;
5542 seq_no = cYAML_get_object_item(tree, "seq_no");
5543 idx = cYAML_get_object_item(tree, "idx");
5545 return lustre_lnet_show_udsp(idx ? idx->cy_valueint : -1,
5546 seq_no ? seq_no->cy_valueint : -1,
5550 static int handle_yaml_config_global_settings(struct cYAML *tree,
5551 struct cYAML **show_rc,
5552 struct cYAML **err_rc)
5554 struct cYAML *max_intf, *numa, *discovery, *retry, *tto, *seq_no,
5555 *sen, *recov, *rsen, *drop_asym_route, *rsp_tracking,
5559 seq_no = cYAML_get_object_item(tree, "seq_no");
5560 max_intf = cYAML_get_object_item(tree, "max_interfaces");
5561 if (!max_intf) /* try legacy name */
5562 max_intf = cYAML_get_object_item(tree, "max_intf");
5564 rc = lustre_lnet_config_max_intf(max_intf->cy_valueint,
5565 seq_no ? seq_no->cy_valueint
5569 numa = cYAML_get_object_item(tree, "numa_range");
5571 rc = lustre_lnet_config_numa_range(numa->cy_valueint,
5572 seq_no ? seq_no->cy_valueint
5576 discovery = cYAML_get_object_item(tree, "discovery");
5578 rc = lustre_lnet_config_discovery(discovery->cy_valueint,
5579 seq_no ? seq_no->cy_valueint
5583 drop_asym_route = cYAML_get_object_item(tree, "drop_asym_route");
5584 if (drop_asym_route)
5585 rc = lustre_lnet_config_drop_asym_route(
5586 drop_asym_route->cy_valueint,
5587 seq_no ? seq_no->cy_valueint : -1,
5590 retry = cYAML_get_object_item(tree, "retry_count");
5592 rc = lustre_lnet_config_retry_count(retry->cy_valueint,
5593 seq_no ? seq_no->cy_valueint
5597 tto = cYAML_get_object_item(tree, "transaction_timeout");
5599 rc = lustre_lnet_config_transaction_to(tto->cy_valueint,
5600 seq_no ? seq_no->cy_valueint
5604 sen = cYAML_get_object_item(tree, "health_sensitivity");
5606 rc = lustre_lnet_config_hsensitivity(sen->cy_valueint,
5607 seq_no ? seq_no->cy_valueint
5611 recov = cYAML_get_object_item(tree, "recovery_interval");
5613 rc = lustre_lnet_config_recov_intrv(recov->cy_valueint,
5614 seq_no ? seq_no->cy_valueint
5618 rsen = cYAML_get_object_item(tree, "router_sensitivity");
5620 rc = lustre_lnet_config_rtr_sensitivity(rsen->cy_valueint,
5621 seq_no ? seq_no->cy_valueint
5625 rsp_tracking = cYAML_get_object_item(tree, "response_tracking");
5627 rc = lustre_lnet_config_response_tracking(rsp_tracking->cy_valueint,
5628 seq_no ? seq_no->cy_valueint
5632 recov_limit = cYAML_get_object_item(tree, "recovery_limit");
5634 rc = lustre_lnet_config_recovery_limit(recov_limit->cy_valueint,
5635 seq_no ? seq_no->cy_valueint
5642 static int handle_yaml_del_global_settings(struct cYAML *tree,
5643 struct cYAML **show_rc,
5644 struct cYAML **err_rc)
5646 struct cYAML *max_intf, *numa, *discovery, *seq_no, *drop_asym_route;
5649 seq_no = cYAML_get_object_item(tree, "seq_no");
5650 max_intf = cYAML_get_object_item(tree, "max_interfaces");
5651 if (!max_intf) /* try legacy name */
5652 max_intf = cYAML_get_object_item(tree, "max_intf");
5654 rc = lustre_lnet_config_max_intf(LNET_INTERFACES_MAX_DEFAULT,
5655 seq_no ? seq_no->cy_valueint
5659 numa = cYAML_get_object_item(tree, "numa_range");
5661 rc = lustre_lnet_config_numa_range(0,
5662 seq_no ? seq_no->cy_valueint
5666 /* peer discovery is enabled by default */
5667 discovery = cYAML_get_object_item(tree, "discovery");
5669 rc = lustre_lnet_config_discovery(1,
5670 seq_no ? seq_no->cy_valueint
5674 /* asymmetrical route messages are accepted by default */
5675 drop_asym_route = cYAML_get_object_item(tree, "drop_asym_route");
5676 if (drop_asym_route)
5677 rc = lustre_lnet_config_drop_asym_route(
5678 0, seq_no ? seq_no->cy_valueint : -1, err_rc);
5683 static int handle_yaml_show_global_settings(struct cYAML *tree,
5684 struct cYAML **show_rc,
5685 struct cYAML **err_rc)
5687 struct cYAML *max_intf, *numa, *discovery, *retry, *tto, *seq_no,
5688 *sen, *recov, *rsen, *drop_asym_route, *rsp_tracking,
5692 seq_no = cYAML_get_object_item(tree, "seq_no");
5693 max_intf = cYAML_get_object_item(tree, "max_interfaces");
5694 if (!max_intf) /* try legacy name */
5695 max_intf = cYAML_get_object_item(tree, "max_intf");
5697 rc = lustre_lnet_show_max_intf(seq_no ? seq_no->cy_valueint
5701 numa = cYAML_get_object_item(tree, "numa_range");
5703 rc = lustre_lnet_show_numa_range(seq_no ? seq_no->cy_valueint
5707 discovery = cYAML_get_object_item(tree, "discovery");
5709 rc = lustre_lnet_show_discovery(seq_no ? seq_no->cy_valueint
5713 drop_asym_route = cYAML_get_object_item(tree, "drop_asym_route");
5714 if (drop_asym_route)
5715 rc = lustre_lnet_show_drop_asym_route(
5716 seq_no ? seq_no->cy_valueint : -1,
5719 retry = cYAML_get_object_item(tree, "retry_count");
5721 rc = lustre_lnet_show_retry_count(seq_no ? seq_no->cy_valueint
5725 tto = cYAML_get_object_item(tree, "transaction_timeout");
5727 rc = lustre_lnet_show_transaction_to(seq_no ? seq_no->cy_valueint
5731 sen = cYAML_get_object_item(tree, "health_sensitivity");
5733 rc = lustre_lnet_show_hsensitivity(seq_no ? seq_no->cy_valueint
5737 recov = cYAML_get_object_item(tree, "recovery_interval");
5739 rc = lustre_lnet_show_recov_intrv(seq_no ? seq_no->cy_valueint
5743 rsen = cYAML_get_object_item(tree, "router_sensitivity");
5745 rc = lustre_lnet_show_hsensitivity(seq_no ? seq_no->cy_valueint
5749 rsp_tracking = cYAML_get_object_item(tree, "response_tracking");
5751 rc = lustre_lnet_show_response_tracking(seq_no ?
5752 seq_no->cy_valueint :
5756 recov_limit = cYAML_get_object_item(tree, "recovery_limit");
5758 rc = lustre_lnet_show_recovery_limit(seq_no ?
5759 seq_no->cy_valueint :
5766 static int handle_yaml_ping(struct cYAML *tree, struct cYAML **show_rc,
5767 struct cYAML **err_rc)
5769 struct cYAML *seq_no, *nid, *timeout, *src_nid;
5771 seq_no = cYAML_get_object_item(tree, "seq_no");
5772 nid = cYAML_get_object_item(tree, "primary nid");
5773 timeout = cYAML_get_object_item(tree, "timeout");
5774 src_nid = cYAML_get_object_item(tree, "source_nid");
5776 return lustre_lnet_ping_nid((nid) ? nid->cy_valuestring : NULL,
5777 (src_nid) ? src_nid->cy_valuestring : NULL,
5778 (timeout) ? timeout->cy_valueint : 1000,
5779 (seq_no) ? seq_no->cy_valueint : -1,
5783 static int handle_yaml_discover(struct cYAML *tree, struct cYAML **show_rc,
5784 struct cYAML **err_rc)
5786 struct cYAML *seq_no, *nid, *force;
5788 seq_no = cYAML_get_object_item(tree, "seq_no");
5789 nid = cYAML_get_object_item(tree, "primary nid");
5790 force = cYAML_get_object_item(tree, "force");
5792 return lustre_lnet_discover_nid((nid) ? nid->cy_valuestring : NULL,
5793 (force) ? force->cy_valueint : 0,
5794 (seq_no) ? seq_no->cy_valueint : -1,
5798 static int handle_yaml_no_op()
5800 return LUSTRE_CFG_RC_NO_ERR;
5803 struct lookup_cmd_hdlr_tbl {
5808 static struct lookup_cmd_hdlr_tbl lookup_config_tbl[] = {
5809 { .name = "route", .cb = handle_yaml_config_route },
5810 { .name = "net", .cb = handle_yaml_config_ni },
5811 { .name = "ip2nets", .cb = handle_yaml_config_ip2nets },
5812 { .name = "peer", .cb = handle_yaml_config_peer },
5813 { .name = "routing", .cb = handle_yaml_config_routing },
5814 { .name = "buffers", .cb = handle_yaml_config_buffers },
5815 { .name = "statistics", .cb = handle_yaml_no_op },
5816 { .name = "global", .cb = handle_yaml_config_global_settings},
5817 { .name = "numa", .cb = handle_yaml_config_numa },
5818 { .name = "ping", .cb = handle_yaml_no_op },
5819 { .name = "discover", .cb = handle_yaml_no_op },
5820 { .name = "udsp", .cb = handle_yaml_config_udsp },
5823 static struct lookup_cmd_hdlr_tbl lookup_del_tbl[] = {
5824 { .name = "route", .cb = handle_yaml_del_route },
5825 { .name = "net", .cb = handle_yaml_del_ni },
5826 { .name = "ip2nets", .cb = handle_yaml_no_op },
5827 { .name = "peer", .cb = handle_yaml_del_peer },
5828 { .name = "routing", .cb = handle_yaml_del_routing },
5829 { .name = "buffers", .cb = handle_yaml_no_op },
5830 { .name = "statistics", .cb = handle_yaml_no_op },
5831 { .name = "global", .cb = handle_yaml_del_global_settings},
5832 { .name = "numa", .cb = handle_yaml_del_numa },
5833 { .name = "ping", .cb = handle_yaml_no_op },
5834 { .name = "discover", .cb = handle_yaml_no_op },
5835 { .name = "udsp", .cb = handle_yaml_del_udsp },
5838 static struct lookup_cmd_hdlr_tbl lookup_show_tbl[] = {
5839 { .name = "route", .cb = handle_yaml_show_route },
5840 { .name = "net", .cb = handle_yaml_show_net },
5841 { .name = "peer", .cb = handle_yaml_show_peers },
5842 { .name = "ip2nets", .cb = handle_yaml_no_op },
5843 { .name = "routing", .cb = handle_yaml_show_routing },
5844 { .name = "buffers", .cb = handle_yaml_show_routing },
5845 { .name = "statistics", .cb = handle_yaml_show_stats },
5846 { .name = "global", .cb = handle_yaml_show_global_settings},
5847 { .name = "numa", .cb = handle_yaml_show_numa },
5848 { .name = "ping", .cb = handle_yaml_no_op },
5849 { .name = "discover", .cb = handle_yaml_no_op },
5850 { .name = "udsp", .cb = handle_yaml_show_udsp },
5853 static struct lookup_cmd_hdlr_tbl lookup_exec_tbl[] = {
5854 { .name = "route", .cb = handle_yaml_no_op },
5855 { .name = "net", .cb = handle_yaml_no_op },
5856 { .name = "peer", .cb = handle_yaml_no_op },
5857 { .name = "ip2nets", .cb = handle_yaml_no_op },
5858 { .name = "routing", .cb = handle_yaml_no_op },
5859 { .name = "buffers", .cb = handle_yaml_no_op },
5860 { .name = "statistics", .cb = handle_yaml_no_op },
5861 { .name = "global", .cb = handle_yaml_no_op },
5862 { .name = "numa", .cb = handle_yaml_no_op },
5863 { .name = "ping", .cb = handle_yaml_ping },
5864 { .name = "discover", .cb = handle_yaml_discover },
5867 static cmd_handler_t lookup_fn(char *key,
5868 struct lookup_cmd_hdlr_tbl *tbl)
5874 for (i = 0; tbl[i].name != NULL; i++) {
5875 if (strncmp(key, tbl[i].name, strlen(tbl[i].name)) == 0)
5882 static int lustre_yaml_cb_helper(char *f, int len,
5883 struct lookup_cmd_hdlr_tbl *table,
5884 struct cYAML **show_rc, struct cYAML **err_rc)
5886 struct cYAML *tree, *item = NULL, *head, *child;
5888 char err_str[LNET_MAX_STR_LEN];
5889 int rc = LUSTRE_CFG_RC_NO_ERR, return_rc = LUSTRE_CFG_RC_NO_ERR;
5891 tree = cYAML_build_tree(NULL, f, len, err_rc, false);
5893 return LUSTRE_CFG_RC_BAD_PARAM;
5895 child = tree->cy_child;
5896 while (child != NULL) {
5897 cb = lookup_fn(child->cy_string, table);
5899 snprintf(err_str, sizeof(err_str),
5900 "\"call back for '%s' not found\"",
5902 cYAML_build_error(LUSTRE_CFG_RC_BAD_PARAM, -1,
5903 "yaml", "helper", err_str, err_rc);
5907 if (cYAML_is_sequence(child)) {
5908 while ((head = cYAML_get_next_seq_item(child, &item))
5910 rc = cb(head, show_rc, err_rc);
5911 if (rc != LUSTRE_CFG_RC_NO_ERR)
5915 rc = cb(child, show_rc, err_rc);
5916 if (rc != LUSTRE_CFG_RC_NO_ERR)
5920 child = child->cy_next;
5924 cYAML_free_tree(tree);
5929 int lustre_yaml_config(char *f, int len, struct cYAML **err_rc)
5931 return lustre_yaml_cb_helper(f, len, lookup_config_tbl,
5935 int lustre_yaml_del(char *f, int len, struct cYAML **err_rc)
5937 return lustre_yaml_cb_helper(f, len, lookup_del_tbl,
5941 int lustre_yaml_show(char *f, int len, struct cYAML **show_rc,
5942 struct cYAML **err_rc)
5944 return lustre_yaml_cb_helper(f, len, lookup_show_tbl,
5948 int lustre_yaml_exec(char *f, int len, struct cYAML **show_rc,
5949 struct cYAML **err_rc)
5951 return lustre_yaml_cb_helper(f, len, lookup_exec_tbl,