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, 2016, 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
42 #include <sys/ioctl.h>
43 #include <libcfs/util/ioctl.h>
44 #include <lnet/lnetctl.h>
45 #include <lnet/socklnd.h>
47 #include "liblnetconfig.h"
50 #define CONFIG_CMD "configure"
51 #define UNCONFIG_CMD "unconfigure"
54 #define SHOW_CMD "show"
56 int lustre_lnet_config_lib_init(void)
58 return register_ioc_dev(LNET_DEV_ID, LNET_DEV_PATH,
59 LNET_DEV_MAJOR, LNET_DEV_MINOR);
62 int lustre_lnet_config_ni_system(bool up, bool load_ni_from_mod,
63 int seq_no, struct cYAML **err_rc)
65 struct libcfs_ioctl_data data;
68 char err_str[LNET_MAX_STR_LEN];
70 snprintf(err_str, sizeof(err_str), "\"Success\"");
72 LIBCFS_IOC_INIT(data);
74 /* Reverse logic is used here in order not to change
76 data.ioc_flags = load_ni_from_mod ? 0 : 1;
78 opc = up ? IOC_LIBCFS_CONFIGURE : IOC_LIBCFS_UNCONFIGURE;
80 rc = l_ioctl(LNET_DEV_ID, opc, &data);
84 "\"LNet %s error: %s\"", (up) ? "configure" :
85 "unconfigure", strerror(errno));
89 cYAML_build_error(rc, seq_no, (up) ? CONFIG_CMD : UNCONFIG_CMD,
90 "lnet", err_str, err_rc);
95 static lnet_nid_t *allocate_create_nid_array(char **nids, char *err_str)
97 lnet_nid_t *array = NULL;
101 snprintf(err_str, LNET_MAX_STR_LEN, "no NIDs to add");
105 /* count the size of the array */
106 while (nids[idx] != NULL)
109 array = calloc(sizeof(*array) * idx + 1, 1);
111 snprintf(err_str, LNET_MAX_STR_LEN, "out of memory");
116 while (nids[idx] != NULL) {
117 array[idx] = libcfs_str2nid(nids[idx]);
118 if (array[idx] == LNET_NID_ANY) {
120 snprintf(err_str, LNET_MAX_STR_LEN,
128 /* identify last entry */
129 array[idx] = LNET_NID_ANY;
134 static int dispatch_peer_ni_cmd(lnet_nid_t knid, lnet_nid_t nid, __u32 cmd,
135 struct lnet_ioctl_peer_cfg *data,
136 char *err_str, char *cmd_str)
140 data->prcfg_key_nid = knid;
141 data->prcfg_cfg_nid = nid;
143 rc = l_ioctl(LNET_DEV_ID, cmd, data);
148 "\"cannot %s peer ni: %s\"",
149 (cmd_str) ? cmd_str : "add", strerror(errno));
155 int lustre_lnet_config_peer_nid(char *knid, char **nid, int seq_no,
156 struct cYAML **err_rc)
158 struct lnet_ioctl_peer_cfg data;
159 lnet_nid_t key_nid = LNET_NID_ANY;
160 int rc = LUSTRE_CFG_RC_NO_ERR;
162 char err_str[LNET_MAX_STR_LEN] = {0};
163 lnet_nid_t *nids = allocate_create_nid_array(nid, err_str);
166 key_nid = libcfs_str2nid(knid);
167 if (key_nid == LNET_NID_ANY) {
168 snprintf(err_str, sizeof(err_str),
171 rc = LUSTRE_CFG_RC_MISSING_PARAM;
174 } else if (nids[0] == LNET_NID_ANY) {
175 snprintf(err_str, sizeof(err_str),
176 "no NIDs provided for configuration");
177 rc = LUSTRE_CFG_RC_MISSING_PARAM;
180 key_nid = LNET_NID_ANY;
183 snprintf(err_str, sizeof(err_str), "\"Success\"");
185 LIBCFS_IOC_INIT_V2(data, prcfg_hdr);
186 if (nids[0] == LNET_NID_ANY) {
187 rc = dispatch_peer_ni_cmd(LNET_NID_ANY, key_nid,
188 IOC_LIBCFS_ADD_PEER_NI,
189 &data, err_str, "add");
193 while (nids[idx] != LNET_NID_ANY) {
195 * If key_nid is not provided then the first nid in the
196 * list becomes the key_nid. First time round the loop use
197 * LNET_NID_ANY for the first parameter, then use nid[0]
198 * as the key nid after wards
200 rc = dispatch_peer_ni_cmd(key_nid, nids[idx],
201 IOC_LIBCFS_ADD_PEER_NI, &data,
207 if (idx == 0 && key_nid == LNET_NID_ANY)
216 cYAML_build_error(rc, seq_no, ADD_CMD, "peer_ni", err_str, err_rc);
220 int lustre_lnet_del_peer_nid(char *knid, char **nid, int seq_no,
221 struct cYAML **err_rc)
223 struct lnet_ioctl_peer_cfg data;
225 int rc = LUSTRE_CFG_RC_NO_ERR;
227 char err_str[LNET_MAX_STR_LEN] = {0};
228 lnet_nid_t *nids = allocate_create_nid_array(nid, err_str);
231 snprintf(err_str, sizeof(err_str),
232 "\"Primary nid is not provided\"");
233 rc = LUSTRE_CFG_RC_MISSING_PARAM;
236 key_nid = libcfs_str2nid(knid);
237 if (key_nid == LNET_NID_ANY) {
238 rc = LUSTRE_CFG_RC_BAD_PARAM;
239 snprintf(err_str, sizeof(err_str),
246 snprintf(err_str, sizeof(err_str), "\"Success\"");
248 LIBCFS_IOC_INIT_V2(data, prcfg_hdr);
249 if (nids[0] == LNET_NID_ANY) {
250 rc = dispatch_peer_ni_cmd(key_nid, LNET_NID_ANY,
251 IOC_LIBCFS_DEL_PEER_NI,
252 &data, err_str, "del");
256 while (nids[idx] != LNET_NID_ANY) {
257 rc = dispatch_peer_ni_cmd(key_nid, nids[idx],
258 IOC_LIBCFS_DEL_PEER_NI, &data,
270 cYAML_build_error(rc, seq_no, DEL_CMD, "peer_ni", err_str, err_rc);
274 int lustre_lnet_config_route(char *nw, char *gw, int hops, int prio,
275 int seq_no, struct cYAML **err_rc)
277 struct lnet_ioctl_config_data data;
278 lnet_nid_t gateway_nid;
279 int rc = LUSTRE_CFG_RC_NO_ERR;
280 __u32 net = LNET_NIDNET(LNET_NID_ANY);
281 char err_str[LNET_MAX_STR_LEN];
283 snprintf(err_str, sizeof(err_str), "\"Success\"");
285 if (nw == NULL || gw == NULL) {
288 "\"missing mandatory parameter(s): '%s'\"",
289 (nw == NULL && gw == NULL) ? "network, gateway" :
290 (nw == NULL) ? "network" : "gateway");
291 rc = LUSTRE_CFG_RC_MISSING_PARAM;
295 net = libcfs_str2net(nw);
296 if (net == LNET_NIDNET(LNET_NID_ANY)) {
299 "\"cannot parse net %s\"", nw);
300 rc = LUSTRE_CFG_RC_BAD_PARAM;
304 if (LNET_NETTYP(net) == CIBLND ||
305 LNET_NETTYP(net) == OPENIBLND ||
306 LNET_NETTYP(net) == IIBLND ||
307 LNET_NETTYP(net) == VIBLND) {
310 "\"obselete LNet type '%s'\"", libcfs_lnd2str(net));
311 rc = LUSTRE_CFG_RC_BAD_PARAM;
315 gateway_nid = libcfs_str2nid(gw);
316 if (gateway_nid == LNET_NID_ANY) {
319 "\"cannot parse gateway NID '%s'\"", gw);
320 rc = LUSTRE_CFG_RC_BAD_PARAM;
325 /* hops is undefined */
326 hops = LNET_UNDEFINED_HOPS;
327 } else if (hops < 1 || hops > 255) {
330 "\"invalid hop count %d, must be between 1 and 255\"",
332 rc = LUSTRE_CFG_RC_OUT_OF_RANGE_PARAM;
338 } else if (prio < 0) {
341 "\"invalid priority %d, must be greater than 0\"",
343 rc = LUSTRE_CFG_RC_OUT_OF_RANGE_PARAM;
347 LIBCFS_IOC_INIT_V2(data, cfg_hdr);
349 data.cfg_config_u.cfg_route.rtr_hop = hops;
350 data.cfg_config_u.cfg_route.rtr_priority = prio;
351 data.cfg_nid = gateway_nid;
353 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_ADD_ROUTE, &data);
358 "\"cannot add route: %s\"", strerror(errno));
363 cYAML_build_error(rc, seq_no, ADD_CMD, "route", err_str, err_rc);
368 int lustre_lnet_del_route(char *nw, char *gw,
369 int seq_no, struct cYAML **err_rc)
371 struct lnet_ioctl_config_data data;
372 lnet_nid_t gateway_nid;
373 int rc = LUSTRE_CFG_RC_NO_ERR;
374 __u32 net = LNET_NIDNET(LNET_NID_ANY);
375 char err_str[LNET_MAX_STR_LEN];
377 snprintf(err_str, sizeof(err_str), "\"Success\"");
379 if (nw == NULL || gw == NULL) {
382 "\"missing mandatory parameter(s): '%s'\"",
383 (nw == NULL && gw == NULL) ? "network, gateway" :
384 (nw == NULL) ? "network" : "gateway");
385 rc = LUSTRE_CFG_RC_MISSING_PARAM;
389 net = libcfs_str2net(nw);
390 if (net == LNET_NIDNET(LNET_NID_ANY)) {
393 "\"cannot parse net '%s'\"", nw);
394 rc = LUSTRE_CFG_RC_BAD_PARAM;
398 if (LNET_NETTYP(net) == CIBLND ||
399 LNET_NETTYP(net) == OPENIBLND ||
400 LNET_NETTYP(net) == IIBLND ||
401 LNET_NETTYP(net) == VIBLND) {
404 "\"obselete LNet type '%s'\"", libcfs_lnd2str(net));
405 rc = LUSTRE_CFG_RC_BAD_PARAM;
409 gateway_nid = libcfs_str2nid(gw);
410 if (gateway_nid == LNET_NID_ANY) {
413 "\"cannot parse gateway NID '%s'\"", gw);
414 rc = LUSTRE_CFG_RC_BAD_PARAM;
418 LIBCFS_IOC_INIT_V2(data, cfg_hdr);
420 data.cfg_nid = gateway_nid;
422 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_DEL_ROUTE, &data);
427 "\"cannot delete route: %s\"", strerror(errno));
432 cYAML_build_error(rc, seq_no, DEL_CMD, "route", err_str, err_rc);
437 int lustre_lnet_show_route(char *nw, char *gw, int hops, int prio, int detail,
438 int seq_no, struct cYAML **show_rc,
439 struct cYAML **err_rc)
441 struct lnet_ioctl_config_data data;
442 lnet_nid_t gateway_nid;
443 int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
445 __u32 net = LNET_NIDNET(LNET_NID_ANY);
447 struct cYAML *root = NULL, *route = NULL, *item = NULL;
448 struct cYAML *first_seq = NULL;
449 char err_str[LNET_MAX_STR_LEN];
452 snprintf(err_str, sizeof(err_str),
453 "\"out of memory\"");
456 net = libcfs_str2net(nw);
457 if (net == LNET_NIDNET(LNET_NID_ANY)) {
460 "\"cannot parse net '%s'\"", nw);
461 rc = LUSTRE_CFG_RC_BAD_PARAM;
465 if (LNET_NETTYP(net) == CIBLND ||
466 LNET_NETTYP(net) == OPENIBLND ||
467 LNET_NETTYP(net) == IIBLND ||
468 LNET_NETTYP(net) == VIBLND) {
471 "\"obsolete LNet type '%s'\"",
472 libcfs_lnd2str(net));
473 rc = LUSTRE_CFG_RC_BAD_PARAM;
477 /* show all routes without filtering on net */
478 net = LNET_NIDNET(LNET_NID_ANY);
482 gateway_nid = libcfs_str2nid(gw);
483 if (gateway_nid == LNET_NID_ANY) {
486 "\"cannot parse gateway NID '%s'\"", gw);
487 rc = LUSTRE_CFG_RC_BAD_PARAM;
491 /* show all routes with out filtering on gateway */
492 gateway_nid = LNET_NID_ANY;
494 if ((hops < 1 && hops != -1) || hops > 255) {
497 "\"invalid hop count %d, must be between 0 and 256\"",
499 rc = LUSTRE_CFG_RC_OUT_OF_RANGE_PARAM;
503 /* create struct cYAML root object */
504 root = cYAML_create_object(NULL, NULL);
508 route = cYAML_create_seq(root, "route");
513 LIBCFS_IOC_INIT_V2(data, cfg_hdr);
516 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_ROUTE, &data);
522 /* filter on provided data */
523 if (net != LNET_NIDNET(LNET_NID_ANY) &&
527 if (gateway_nid != LNET_NID_ANY &&
528 gateway_nid != data.cfg_nid)
532 hops != data.cfg_config_u.cfg_route.rtr_hop)
536 prio != data.cfg_config_u.cfg_route.rtr_priority)
539 /* default rc to -1 incase we hit the goto */
543 item = cYAML_create_seq_item(route);
547 if (first_seq == NULL)
550 if (cYAML_create_string(item, "net",
551 libcfs_net2str(data.cfg_net)) == NULL)
554 if (cYAML_create_string(item, "gateway",
555 libcfs_nid2str(data.cfg_nid)) == NULL)
559 if (cYAML_create_number(item, "hop",
560 data.cfg_config_u.cfg_route.
565 if (cYAML_create_number(item, "priority",
567 cfg_route.rtr_priority) == NULL)
570 if (cYAML_create_string(item, "state",
571 data.cfg_config_u.cfg_route.
573 "up" : "down") == NULL)
578 /* print output iff show_rc is not provided */
580 cYAML_print_tree(root);
582 if (l_errno != ENOENT) {
585 "\"cannot get routes: %s\"",
590 rc = LUSTRE_CFG_RC_NO_ERR;
592 snprintf(err_str, sizeof(err_str), "\"success\"");
594 if (show_rc == NULL || rc != LUSTRE_CFG_RC_NO_ERR || !exist) {
595 cYAML_free_tree(root);
596 } else if (show_rc != NULL && *show_rc != NULL) {
597 struct cYAML *show_node;
598 /* find the route node, if one doesn't exist then
599 * insert one. Otherwise add to the one there
601 show_node = cYAML_get_object_item(*show_rc, "route");
602 if (show_node != NULL && cYAML_is_sequence(show_node)) {
603 cYAML_insert_child(show_node, first_seq);
606 } else if (show_node == NULL) {
607 cYAML_insert_sibling((*show_rc)->cy_child,
611 cYAML_free_tree(root);
617 cYAML_build_error(rc, seq_no, SHOW_CMD, "route", err_str, err_rc);
622 int lustre_lnet_config_net(char *net, char *intf, char *ip2net,
623 int peer_to, int peer_cr, int peer_buf_cr,
624 int credits, char *smp, int seq_no,
625 struct lnet_ioctl_config_lnd_tunables *lnd_tunables,
626 struct cYAML **err_rc)
628 struct lnet_ioctl_config_lnd_tunables *lnd = NULL;
629 struct lnet_ioctl_config_data *data;
630 size_t ioctl_size = sizeof(*data);
631 char buf[LNET_MAX_STR_LEN];
632 int rc = LUSTRE_CFG_RC_NO_ERR;
633 char err_str[LNET_MAX_STR_LEN];
635 snprintf(err_str, sizeof(err_str), "\"success\"");
637 /* No need to register lo */
638 if (net != NULL && !strcmp(net, "lo"))
641 if (ip2net == NULL && (intf == NULL || net == NULL)) {
644 "\"mandatory parameter '%s' not specified."
645 " Optionally specify ip2net parameter\"",
646 (intf == NULL && net == NULL) ? "net, if" :
647 (intf == NULL) ? "if" : "net");
648 rc = LUSTRE_CFG_RC_MISSING_PARAM;
652 if (peer_to != -1 && peer_to <= 0) {
655 "\"peer timeout %d, must be greater than 0\"",
657 rc = LUSTRE_CFG_RC_OUT_OF_RANGE_PARAM;
661 if (ip2net != NULL && strlen(ip2net) >= sizeof(buf)) {
664 "\"ip2net string too long %d\"",
665 (int)strlen(ip2net));
666 rc = LUSTRE_CFG_RC_OUT_OF_RANGE_PARAM;
670 if (lnd_tunables != NULL)
671 ioctl_size += sizeof(*lnd_tunables);
673 data = calloc(1, ioctl_size);
678 snprintf(buf, sizeof(buf) - 1, "%s(%s)%s",
682 LIBCFS_IOC_INIT_V2(*data, cfg_hdr);
683 strncpy(data->cfg_config_u.cfg_net.net_intf,
684 (ip2net != NULL) ? ip2net : buf, sizeof(buf));
685 data->cfg_config_u.cfg_net.net_peer_timeout = peer_to;
686 data->cfg_config_u.cfg_net.net_peer_tx_credits = peer_cr;
687 data->cfg_config_u.cfg_net.net_peer_rtr_credits = peer_buf_cr;
688 data->cfg_config_u.cfg_net.net_max_tx_credits = credits;
689 /* Add in tunable settings if available */
690 if (lnd_tunables != NULL) {
691 lnd = (struct lnet_ioctl_config_lnd_tunables *)data->cfg_bulk;
693 data->cfg_hdr.ioc_len = ioctl_size;
694 memcpy(lnd, lnd_tunables, sizeof(*lnd_tunables));
697 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_ADD_NET, data);
702 "\"cannot add network: %s\"", strerror(errno));
707 cYAML_build_error(rc, seq_no, ADD_CMD, "net", err_str, err_rc);
712 int lustre_lnet_del_net(char *nw, int seq_no, struct cYAML **err_rc)
714 struct lnet_ioctl_config_data data;
715 __u32 net = LNET_NIDNET(LNET_NID_ANY);
716 int rc = LUSTRE_CFG_RC_NO_ERR;
717 char err_str[LNET_MAX_STR_LEN];
719 snprintf(err_str, sizeof(err_str), "\"success\"");
724 "\"missing mandatory parameter\"");
725 rc = LUSTRE_CFG_RC_MISSING_PARAM;
729 net = libcfs_str2net(nw);
730 if (net == LNET_NIDNET(LNET_NID_ANY)) {
733 "\"cannot parse net '%s'\"", nw);
734 rc = LUSTRE_CFG_RC_BAD_PARAM;
738 LIBCFS_IOC_INIT_V2(data, cfg_hdr);
741 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_DEL_NET, &data);
746 "\"cannot delete network: %s\"", strerror(errno));
751 cYAML_build_error(rc, seq_no, DEL_CMD, "net", err_str, err_rc);
756 int lustre_lnet_show_net(char *nw, int detail, int seq_no,
757 struct cYAML **show_rc, struct cYAML **err_rc)
760 struct lnet_ioctl_config_lnd_tunables *lnd_cfg;
761 struct lnet_ioctl_config_data *data;
762 struct lnet_ioctl_net_config *net_config;
763 __u32 net = LNET_NIDNET(LNET_NID_ANY);
764 int rc = LUSTRE_CFG_RC_OUT_OF_MEM, i, j;
766 struct cYAML *root = NULL, *tunables = NULL, *net_node = NULL,
767 *interfaces = NULL, *item = NULL, *first_seq = NULL;
768 int str_buf_len = LNET_MAX_SHOW_NUM_CPT * 2;
769 char str_buf[str_buf_len];
771 char err_str[LNET_MAX_STR_LEN];
775 snprintf(err_str, sizeof(err_str), "\"out of memory\"");
777 buf_len = sizeof(*data) + sizeof(*net_config) + sizeof(*lnd_cfg);
778 buf = calloc(1, buf_len);
782 data = (struct lnet_ioctl_config_data *)buf;
785 net = libcfs_str2net(nw);
786 if (net == LNET_NIDNET(LNET_NID_ANY)) {
789 "\"cannot parse net '%s'\"", nw);
790 rc = LUSTRE_CFG_RC_BAD_PARAM;
795 root = cYAML_create_object(NULL, NULL);
799 net_node = cYAML_create_seq(root, "net");
800 if (net_node == NULL)
806 memset(buf, 0, buf_len);
808 LIBCFS_IOC_INIT_V2(*data, cfg_hdr);
810 * set the ioc_len to the proper value since INIT assumes
813 data->cfg_hdr.ioc_len = buf_len;
816 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_NET, data);
822 /* filter on provided data */
823 if (net != LNET_NIDNET(LNET_NID_ANY) &&
824 net != LNET_NIDNET(data->cfg_nid))
827 /* default rc to -1 in case we hit the goto */
831 net_config = (struct lnet_ioctl_net_config *)data->cfg_bulk;
833 /* create the tree to be printed. */
834 item = cYAML_create_seq_item(net_node);
838 if (first_seq == NULL)
841 if (cYAML_create_string(item, "net",
843 LNET_NIDNET(data->cfg_nid)))
847 if (cYAML_create_string(item, "nid",
848 libcfs_nid2str(data->cfg_nid)) == NULL)
851 if (cYAML_create_string(item, "status",
852 (net_config->ni_status ==
854 "up" : "down") == NULL)
857 /* don't add interfaces unless there is at least one
859 if (strlen(net_config->ni_interfaces[0]) > 0) {
860 interfaces = cYAML_create_object(item, "interfaces");
861 if (interfaces == NULL)
864 for (j = 0; j < LNET_MAX_INTERFACES; j++) {
865 if (lustre_interface_show_net(interfaces, j,
875 tunables = cYAML_create_object(item, "tunables");
876 if (tunables == NULL)
879 if (cYAML_create_number(tunables, "peer_timeout",
880 data->cfg_config_u.cfg_net.
881 net_peer_timeout) == NULL)
884 if (cYAML_create_number(tunables, "peer_credits",
885 data->cfg_config_u.cfg_net.
886 net_peer_tx_credits) == NULL)
889 if (cYAML_create_number(tunables,
890 "peer_buffer_credits",
891 data->cfg_config_u.cfg_net.
892 net_peer_rtr_credits) == NULL)
895 if (cYAML_create_number(tunables, "credits",
896 data->cfg_config_u.cfg_net.
897 net_max_tx_credits) == NULL)
900 /* out put the CPTs in the format: "[x,x,x,...]" */
901 limit = str_buf + str_buf_len - 3;
902 pos += snprintf(pos, limit - pos, "\"[");
903 for (j = 0 ; data->cfg_ncpts > 1 &&
904 j < data->cfg_ncpts &&
906 pos += snprintf(pos, limit - pos,
907 "%d", net_config->ni_cpts[j]);
908 if ((j + 1) < data->cfg_ncpts)
909 pos += snprintf(pos, limit - pos, ",");
911 pos += snprintf(pos, 3, "]\"");
913 if (data->cfg_ncpts > 1 &&
914 cYAML_create_string(tunables, "CPT",
920 /* Print out the net information only if show_rc is not provided */
922 cYAML_print_tree(root);
924 if (l_errno != ENOENT) {
927 "\"cannot get networks: %s\"",
932 rc = LUSTRE_CFG_RC_NO_ERR;
934 snprintf(err_str, sizeof(err_str), "\"success\"");
936 if (show_rc == NULL || rc != LUSTRE_CFG_RC_NO_ERR || !exist) {
937 cYAML_free_tree(root);
938 } else if (show_rc != NULL && *show_rc != NULL) {
939 struct cYAML *show_node;
940 /* find the net node, if one doesn't exist
941 * then insert one. Otherwise add to the one there
943 show_node = cYAML_get_object_item(*show_rc, "net");
944 if (show_node != NULL && cYAML_is_sequence(show_node)) {
945 cYAML_insert_child(show_node, first_seq);
948 } else if (show_node == NULL) {
949 cYAML_insert_sibling((*show_rc)->cy_child,
953 cYAML_free_tree(root);
959 cYAML_build_error(rc, seq_no, SHOW_CMD, "net", err_str, err_rc);
964 int lustre_lnet_enable_routing(int enable, int seq_no, struct cYAML **err_rc)
966 struct lnet_ioctl_config_data data;
967 int rc = LUSTRE_CFG_RC_NO_ERR;
968 char err_str[LNET_MAX_STR_LEN];
970 snprintf(err_str, sizeof(err_str), "\"success\"");
972 LIBCFS_IOC_INIT_V2(data, cfg_hdr);
973 data.cfg_config_u.cfg_buffers.buf_enable = (enable) ? 1 : 0;
975 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_CONFIG_RTR, &data);
980 "\"cannot %s routing %s\"",
981 (enable) ? "enable" : "disable", strerror(errno));
986 cYAML_build_error(rc, seq_no,
987 (enable) ? ADD_CMD : DEL_CMD,
988 "routing", err_str, err_rc);
993 int lustre_lnet_config_buffers(int tiny, int small, int large, int seq_no,
994 struct cYAML **err_rc)
996 struct lnet_ioctl_config_data data;
997 int rc = LUSTRE_CFG_RC_NO_ERR;
998 char err_str[LNET_MAX_STR_LEN];
1000 snprintf(err_str, sizeof(err_str), "\"success\"");
1002 /* -1 indicates to ignore changes to this field */
1003 if (tiny < -1 || small < -1 || large < -1) {
1006 "\"tiny, small and large must be >= 0\"");
1007 rc = LUSTRE_CFG_RC_OUT_OF_RANGE_PARAM;
1011 LIBCFS_IOC_INIT_V2(data, cfg_hdr);
1012 data.cfg_config_u.cfg_buffers.buf_tiny = tiny;
1013 data.cfg_config_u.cfg_buffers.buf_small = small;
1014 data.cfg_config_u.cfg_buffers.buf_large = large;
1016 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_ADD_BUF, &data);
1021 "\"cannot configure buffers: %s\"", strerror(errno));
1026 cYAML_build_error(rc, seq_no, ADD_CMD, "buf", err_str, err_rc);
1031 int lustre_lnet_show_routing(int seq_no, struct cYAML **show_rc,
1032 struct cYAML **err_rc)
1034 struct lnet_ioctl_config_data *data;
1035 struct lnet_ioctl_pool_cfg *pool_cfg = NULL;
1036 int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
1039 char *pools[LNET_NRBPOOLS] = {"tiny", "small", "large"};
1040 int buf_count[LNET_NRBPOOLS] = {0};
1041 struct cYAML *root = NULL, *pools_node = NULL,
1042 *type_node = NULL, *item = NULL, *cpt = NULL,
1043 *first_seq = NULL, *buffers = NULL;
1045 char err_str[LNET_MAX_STR_LEN];
1046 char node_name[LNET_MAX_STR_LEN];
1049 snprintf(err_str, sizeof(err_str), "\"out of memory\"");
1051 buf = calloc(1, sizeof(*data) + sizeof(*pool_cfg));
1055 data = (struct lnet_ioctl_config_data *)buf;
1057 root = cYAML_create_object(NULL, NULL);
1061 pools_node = cYAML_create_seq(root, "routing");
1062 if (pools_node == NULL)
1066 LIBCFS_IOC_INIT_V2(*data, cfg_hdr);
1067 data->cfg_hdr.ioc_len = sizeof(struct lnet_ioctl_config_data) +
1068 sizeof(struct lnet_ioctl_pool_cfg);
1069 data->cfg_count = i;
1071 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_BUF, data);
1079 pool_cfg = (struct lnet_ioctl_pool_cfg *)data->cfg_bulk;
1081 snprintf(node_name, sizeof(node_name), "cpt[%d]", i);
1082 item = cYAML_create_seq_item(pools_node);
1086 if (first_seq == NULL)
1089 cpt = cYAML_create_object(item, node_name);
1093 /* create the tree and print */
1094 for (j = 0; j < LNET_NRBPOOLS; j++) {
1095 type_node = cYAML_create_object(cpt, pools[j]);
1096 if (type_node == NULL)
1098 if (cYAML_create_number(type_node, "npages",
1099 pool_cfg->pl_pools[j].pl_npages)
1102 if (cYAML_create_number(type_node, "nbuffers",
1103 pool_cfg->pl_pools[j].
1104 pl_nbuffers) == NULL)
1106 if (cYAML_create_number(type_node, "credits",
1107 pool_cfg->pl_pools[j].
1108 pl_credits) == NULL)
1110 if (cYAML_create_number(type_node, "mincredits",
1111 pool_cfg->pl_pools[j].
1112 pl_mincredits) == NULL)
1114 /* keep track of the total count for each of the
1115 * tiny, small and large buffers */
1116 buf_count[j] += pool_cfg->pl_pools[j].pl_nbuffers;
1120 if (pool_cfg != NULL) {
1121 item = cYAML_create_seq_item(pools_node);
1125 if (cYAML_create_number(item, "enable", pool_cfg->pl_routing) ==
1130 /* create a buffers entry in the show. This is necessary so that
1131 * if the YAML output is used to configure a node, the buffer
1132 * configuration takes hold */
1133 buffers = cYAML_create_object(root, "buffers");
1134 if (buffers == NULL)
1137 for (i = 0; i < LNET_NRBPOOLS; i++) {
1138 if (cYAML_create_number(buffers, pools[i], buf_count[i]) == NULL)
1142 if (show_rc == NULL)
1143 cYAML_print_tree(root);
1145 if (l_errno != ENOENT) {
1148 "\"cannot get routing information: %s\"",
1153 rc = LUSTRE_CFG_RC_NO_ERR;
1155 snprintf(err_str, sizeof(err_str), "\"success\"");
1156 rc = LUSTRE_CFG_RC_NO_ERR;
1160 if (show_rc == NULL || rc != LUSTRE_CFG_RC_NO_ERR || !exist) {
1161 cYAML_free_tree(root);
1162 } else if (show_rc != NULL && *show_rc != NULL) {
1163 struct cYAML *routing_node;
1164 /* there should exist only one routing block and one
1165 * buffers block. If there already exists a previous one
1166 * then don't add another */
1167 routing_node = cYAML_get_object_item(*show_rc, "routing");
1168 if (routing_node == NULL) {
1169 cYAML_insert_sibling((*show_rc)->cy_child,
1173 cYAML_free_tree(root);
1179 cYAML_build_error(rc, seq_no, SHOW_CMD, "routing", err_str, err_rc);
1184 int lustre_lnet_show_peer(char *knid, int seq_no, struct cYAML **show_rc,
1185 struct cYAML **err_rc)
1187 struct lnet_ioctl_peer_cfg *peer_info;
1188 struct lnet_peer_ni_credit_info *lpni_cri;
1189 int rc = LUSTRE_CFG_RC_OUT_OF_MEM, ncpt = 0, i = 0, j = 0;
1191 struct cYAML *root = NULL, *peer = NULL, *peer_ni = NULL,
1192 *first_seq = NULL, *peer_root = NULL, *tmp = NULL;
1193 char err_str[LNET_MAX_STR_LEN];
1194 lnet_nid_t prev_primary_nid = LNET_NID_ANY, primary_nid = LNET_NID_ANY;
1195 char *data = calloc(sizeof(*peer_info) + sizeof(*lpni_cri), 1);
1196 bool new_peer = true;
1198 snprintf(err_str, sizeof(err_str),
1199 "\"out of memory\"");
1204 peer_info = (struct lnet_ioctl_peer_cfg *)data;
1206 /* create struct cYAML root object */
1207 root = cYAML_create_object(NULL, NULL);
1211 peer_root = cYAML_create_seq(root, "peer");
1212 if (peer_root == NULL)
1216 primary_nid = libcfs_str2nid(knid);
1220 memset(data, 0, sizeof(*peer_info) + sizeof(*lpni_cri));
1221 LIBCFS_IOC_INIT_V2(*peer_info, prcfg_hdr);
1222 peer_info->prcfg_hdr.ioc_len = sizeof(*peer_info) +
1224 peer_info->prcfg_idx = i;
1226 rc = l_ioctl(LNET_DEV_ID,
1227 IOC_LIBCFS_GET_PEER_NI, peer_info);
1233 if (primary_nid != LNET_NID_ANY &&
1234 primary_nid != peer_info->prcfg_key_nid)
1237 lpni_cri = (struct lnet_peer_ni_credit_info*)peer_info->prcfg_bulk;
1239 peer = cYAML_create_seq_item(peer_root);
1243 if (peer_info->prcfg_key_nid != prev_primary_nid) {
1244 prev_primary_nid = peer_info->prcfg_key_nid;
1249 lnet_nid_t pnid = peer_info->prcfg_key_nid;
1250 if (cYAML_create_string(peer, "primary nid",
1251 libcfs_nid2str(pnid))
1254 tmp = cYAML_create_seq(peer, "peer ni");
1260 if (first_seq == NULL)
1263 peer_ni = cYAML_create_seq_item(tmp);
1264 if (peer_ni == NULL)
1267 if (cYAML_create_string(peer_ni, "nid",
1269 (peer_info->prcfg_cfg_nid))
1273 if (cYAML_create_string(peer_ni, "state",
1274 lpni_cri->cr_aliveness)
1278 if (cYAML_create_number(peer_ni, "refcount",
1279 lpni_cri->cr_refcount) == NULL)
1282 if (cYAML_create_number(peer_ni, "max_ni_tx_credits",
1283 lpni_cri->cr_ni_peer_tx_credits)
1287 if (cYAML_create_number(peer_ni, "available_tx_credits",
1288 lpni_cri->cr_peer_tx_credits)
1292 if (cYAML_create_number(peer_ni, "available_rtr_credits",
1293 lpni_cri->cr_peer_rtr_credits)
1297 if (cYAML_create_number(peer_ni, "min_rtr_credits",
1298 lpni_cri->cr_peer_min_rtr_credits)
1302 if (cYAML_create_number(peer_ni, "tx_q_num_of_buf",
1303 lpni_cri->cr_peer_tx_qnob)
1308 if (l_errno != ENOENT) {
1311 "\"cannot get peer information: %s\"",
1320 /* print output iff show_rc is not provided */
1321 if (show_rc == NULL)
1322 cYAML_print_tree(root);
1324 snprintf(err_str, sizeof(err_str), "\"success\"");
1325 rc = LUSTRE_CFG_RC_NO_ERR;
1328 if (show_rc == NULL || rc != LUSTRE_CFG_RC_NO_ERR) {
1329 cYAML_free_tree(root);
1330 } else if (show_rc != NULL && *show_rc != NULL) {
1331 struct cYAML *show_node;
1332 /* find the peer node, if one doesn't exist then
1333 * insert one. Otherwise add to the one there
1335 show_node = cYAML_get_object_item(*show_rc,
1337 if (show_node != NULL && cYAML_is_sequence(show_node)) {
1338 cYAML_insert_child(show_node, first_seq);
1341 } else if (show_node == NULL) {
1342 cYAML_insert_sibling((*show_rc)->cy_child,
1346 cYAML_free_tree(root);
1352 cYAML_build_error(rc, seq_no, SHOW_CMD, "peer", err_str,
1358 int lustre_lnet_show_stats(int seq_no, struct cYAML **show_rc,
1359 struct cYAML **err_rc)
1361 struct lnet_ioctl_lnet_stats data;
1362 int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
1364 char err_str[LNET_MAX_STR_LEN];
1365 struct cYAML *root = NULL, *stats = NULL;
1367 snprintf(err_str, sizeof(err_str), "\"out of memory\"");
1369 LIBCFS_IOC_INIT_V2(data, st_hdr);
1371 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_LNET_STATS, &data);
1376 "\"cannot get lnet statistics: %s\"",
1382 root = cYAML_create_object(NULL, NULL);
1386 stats = cYAML_create_object(root, "statistics");
1390 if (cYAML_create_number(stats, "msgs_alloc",
1391 data.st_cntrs.msgs_alloc) == NULL)
1394 if (cYAML_create_number(stats, "msgs_max",
1395 data.st_cntrs.msgs_max) == NULL)
1398 if (cYAML_create_number(stats, "errors",
1399 data.st_cntrs.errors) == NULL)
1402 if (cYAML_create_number(stats, "send_count",
1403 data.st_cntrs.send_count) == NULL)
1406 if (cYAML_create_number(stats, "recv_count",
1407 data.st_cntrs.recv_count) == NULL)
1410 if (cYAML_create_number(stats, "route_count",
1411 data.st_cntrs.route_count) == NULL)
1414 if (cYAML_create_number(stats, "drop_count",
1415 data.st_cntrs.drop_count) == NULL)
1418 if (cYAML_create_number(stats, "send_length",
1419 data.st_cntrs.send_length) == NULL)
1422 if (cYAML_create_number(stats, "recv_length",
1423 data.st_cntrs.recv_length) == NULL)
1426 if (cYAML_create_number(stats, "route_length",
1427 data.st_cntrs.route_length) == NULL)
1430 if (cYAML_create_number(stats, "drop_length",
1431 data.st_cntrs.drop_length) == NULL)
1434 if (show_rc == NULL)
1435 cYAML_print_tree(root);
1437 snprintf(err_str, sizeof(err_str), "\"success\"");
1439 if (show_rc == NULL || rc != LUSTRE_CFG_RC_NO_ERR) {
1440 cYAML_free_tree(root);
1441 } else if (show_rc != NULL && *show_rc != NULL) {
1442 cYAML_insert_sibling((*show_rc)->cy_child,
1449 cYAML_build_error(rc, seq_no, SHOW_CMD, "statistics", err_str, err_rc);
1454 typedef int (*cmd_handler_t)(struct cYAML *tree,
1455 struct cYAML **show_rc,
1456 struct cYAML **err_rc);
1458 static int handle_yaml_config_route(struct cYAML *tree, struct cYAML **show_rc,
1459 struct cYAML **err_rc)
1461 struct cYAML *net, *gw, *hop, *prio, *seq_no;
1463 net = cYAML_get_object_item(tree, "net");
1464 gw = cYAML_get_object_item(tree, "gateway");
1465 hop = cYAML_get_object_item(tree, "hop");
1466 prio = cYAML_get_object_item(tree, "priority");
1467 seq_no = cYAML_get_object_item(tree, "seq_no");
1469 return lustre_lnet_config_route((net) ? net->cy_valuestring : NULL,
1470 (gw) ? gw->cy_valuestring : NULL,
1471 (hop) ? hop->cy_valueint : -1,
1472 (prio) ? prio->cy_valueint : -1,
1473 (seq_no) ? seq_no->cy_valueint : -1,
1477 static int handle_yaml_config_net(struct cYAML *tree, struct cYAML **show_rc,
1478 struct cYAML **err_rc)
1480 struct cYAML *net, *intf, *tunables, *seq_no,
1481 *peer_to = NULL, *peer_buf_cr = NULL, *peer_cr = NULL,
1482 *credits = NULL, *ip2net = NULL, *smp = NULL, *child;
1483 struct lnet_ioctl_config_lnd_tunables *lnd_tunables_p = NULL;
1484 struct lnet_ioctl_config_lnd_tunables lnd_tunables;
1485 char devs[LNET_MAX_STR_LEN];
1487 int size = LNET_MAX_STR_LEN;
1489 bool intf_found = false;
1491 ip2net = cYAML_get_object_item(tree, "ip2net");
1492 net = cYAML_get_object_item(tree, "net");
1493 intf = cYAML_get_object_item(tree, "interfaces");
1495 /* grab all the interfaces */
1496 child = intf->cy_child;
1497 while (child != NULL && size > 0) {
1498 struct cYAML *lnd_params;
1500 if (child->cy_valuestring == NULL)
1504 num = snprintf(loc, size, ",%s",
1505 child->cy_valuestring);
1507 num = snprintf(loc, size, "%s",
1508 child->cy_valuestring);
1513 lnd_params = cYAML_get_object_item(intf,
1515 if (lnd_params != NULL) {
1516 const char *dev_name = child->cy_valuestring;
1517 lnd_tunables_p = &lnd_tunables;
1519 lustre_interface_parse(lnd_params, dev_name,
1523 child = child->cy_next;
1527 tunables = cYAML_get_object_item(tree, "tunables");
1528 if (tunables != NULL) {
1529 peer_to = cYAML_get_object_item(tunables, "peer_timeout");
1530 peer_cr = cYAML_get_object_item(tunables, "peer_credits");
1531 peer_buf_cr = cYAML_get_object_item(tunables,
1532 "peer_buffer_credits");
1533 credits = cYAML_get_object_item(tunables, "credits");
1534 smp = cYAML_get_object_item(tunables, "CPT");
1536 seq_no = cYAML_get_object_item(tree, "seq_no");
1538 return lustre_lnet_config_net((net) ? net->cy_valuestring : NULL,
1539 (intf_found) ? devs : NULL,
1540 (ip2net) ? ip2net->cy_valuestring : NULL,
1541 (peer_to) ? peer_to->cy_valueint : -1,
1542 (peer_cr) ? peer_cr->cy_valueint : -1,
1544 peer_buf_cr->cy_valueint : -1,
1545 (credits) ? credits->cy_valueint : -1,
1546 (smp) ? smp->cy_valuestring : NULL,
1547 (seq_no) ? seq_no->cy_valueint : -1,
1552 static void yaml_free_string_array(char **str_array, int num)
1556 for (i = 0; i < num; i++)
1557 free(str_array[num]);
1561 static int yaml_copy_peer_nids(struct cYAML *tree, char ***nidsppp)
1563 struct cYAML *nids_entry = NULL, *child;
1565 int num = 0, rc = LUSTRE_CFG_RC_NO_ERR;
1567 nids_entry = cYAML_get_object_item(tree, "nids");
1568 if (nids_entry != NULL) {
1570 child = nids_entry->cy_child;
1571 while (child != NULL) {
1573 child = child->cy_next;
1577 return LUSTRE_CFG_RC_MISSING_PARAM;
1579 nids = calloc(sizeof(*nids) * num, 1);
1581 return LUSTRE_CFG_RC_OUT_OF_MEM;
1583 /* now grab all the nids */
1584 child = nids_entry->cy_child;
1586 while (child != NULL) {
1587 nids[num] = calloc(strlen(child->cy_valuestring) + 1,
1589 if (nids[num] == NULL) {
1590 rc = LUSTRE_CFG_RC_OUT_OF_MEM;
1593 strncpy(nids[num], child->cy_valuestring,
1594 strlen(child->cy_valuestring));
1595 child = child->cy_next;
1600 rc = LUSTRE_CFG_RC_MISSING_PARAM;
1609 yaml_free_string_array(nids, num);
1614 static int handle_yaml_config_peer(struct cYAML *tree, struct cYAML **show_rc,
1615 struct cYAML **err_rc)
1619 struct cYAML *seq_no, *key_nid;
1621 num = yaml_copy_peer_nids(tree, &nids);
1625 seq_no = cYAML_get_object_item(tree, "seq_no");
1626 key_nid = cYAML_get_object_item(tree, "key_nid");
1628 rc = lustre_lnet_config_peer_nid((key_nid) ? key_nid->cy_valuestring : NULL,
1630 (seq_no) ? seq_no->cy_valueint : -1,
1633 yaml_free_string_array(nids, num);
1637 static int handle_yaml_del_peer(struct cYAML *tree, struct cYAML **show_rc,
1638 struct cYAML **err_rc)
1642 struct cYAML *seq_no, *key_nid;
1644 num = yaml_copy_peer_nids(tree, &nids);
1648 seq_no = cYAML_get_object_item(tree, "seq_no");
1649 key_nid = cYAML_get_object_item(tree, "key_nid");
1651 rc = lustre_lnet_del_peer_nid((key_nid) ? key_nid->cy_valuestring : NULL,
1653 (seq_no) ? seq_no->cy_valueint : -1,
1656 yaml_free_string_array(nids, num);
1660 static int handle_yaml_config_buffers(struct cYAML *tree,
1661 struct cYAML **show_rc,
1662 struct cYAML **err_rc)
1665 struct cYAML *tiny, *small, *large, *seq_no;
1667 tiny = cYAML_get_object_item(tree, "tiny");
1668 small = cYAML_get_object_item(tree, "small");
1669 large = cYAML_get_object_item(tree, "large");
1670 seq_no = cYAML_get_object_item(tree, "seq_no");
1672 rc = lustre_lnet_config_buffers((tiny) ? tiny->cy_valueint : -1,
1673 (small) ? small->cy_valueint : -1,
1674 (large) ? large->cy_valueint : -1,
1675 (seq_no) ? seq_no->cy_valueint : -1,
1681 static int handle_yaml_config_routing(struct cYAML *tree,
1682 struct cYAML **show_rc,
1683 struct cYAML **err_rc)
1685 int rc = LUSTRE_CFG_RC_NO_ERR;
1686 struct cYAML *seq_no, *enable;
1688 seq_no = cYAML_get_object_item(tree, "seq_no");
1689 enable = cYAML_get_object_item(tree, "enable");
1692 rc = lustre_lnet_enable_routing(enable->cy_valueint,
1694 seq_no->cy_valueint : -1,
1701 static int handle_yaml_del_route(struct cYAML *tree, struct cYAML **show_rc,
1702 struct cYAML **err_rc)
1706 struct cYAML *seq_no;
1708 net = cYAML_get_object_item(tree, "net");
1709 gw = cYAML_get_object_item(tree, "gateway");
1710 seq_no = cYAML_get_object_item(tree, "seq_no");
1712 return lustre_lnet_del_route((net) ? net->cy_valuestring : NULL,
1713 (gw) ? gw->cy_valuestring : NULL,
1714 (seq_no) ? seq_no->cy_valueint : -1,
1718 static int handle_yaml_del_net(struct cYAML *tree, struct cYAML **show_rc,
1719 struct cYAML **err_rc)
1721 struct cYAML *net, *seq_no;
1723 net = cYAML_get_object_item(tree, "net");
1724 seq_no = cYAML_get_object_item(tree, "seq_no");
1726 return lustre_lnet_del_net((net) ? net->cy_valuestring : NULL,
1727 (seq_no) ? seq_no->cy_valueint : -1,
1731 static int handle_yaml_del_routing(struct cYAML *tree, struct cYAML **show_rc,
1732 struct cYAML **err_rc)
1734 struct cYAML *seq_no;
1736 seq_no = cYAML_get_object_item(tree, "seq_no");
1738 return lustre_lnet_enable_routing(0, (seq_no) ?
1739 seq_no->cy_valueint : -1,
1743 static int handle_yaml_show_route(struct cYAML *tree, struct cYAML **show_rc,
1744 struct cYAML **err_rc)
1750 struct cYAML *detail;
1751 struct cYAML *seq_no;
1753 net = cYAML_get_object_item(tree, "net");
1754 gw = cYAML_get_object_item(tree, "gateway");
1755 hop = cYAML_get_object_item(tree, "hop");
1756 prio = cYAML_get_object_item(tree, "priority");
1757 detail = cYAML_get_object_item(tree, "detail");
1758 seq_no = cYAML_get_object_item(tree, "seq_no");
1760 return lustre_lnet_show_route((net) ? net->cy_valuestring : NULL,
1761 (gw) ? gw->cy_valuestring : NULL,
1762 (hop) ? hop->cy_valueint : -1,
1763 (prio) ? prio->cy_valueint : -1,
1764 (detail) ? detail->cy_valueint : 0,
1765 (seq_no) ? seq_no->cy_valueint : -1,
1770 static int handle_yaml_show_net(struct cYAML *tree, struct cYAML **show_rc,
1771 struct cYAML **err_rc)
1773 struct cYAML *net, *detail, *seq_no;
1775 net = cYAML_get_object_item(tree, "net");
1776 detail = cYAML_get_object_item(tree, "detail");
1777 seq_no = cYAML_get_object_item(tree, "seq_no");
1779 return lustre_lnet_show_net((net) ? net->cy_valuestring : NULL,
1780 (detail) ? detail->cy_valueint : 0,
1781 (seq_no) ? seq_no->cy_valueint : -1,
1786 static int handle_yaml_show_routing(struct cYAML *tree, struct cYAML **show_rc,
1787 struct cYAML **err_rc)
1789 struct cYAML *seq_no;
1791 seq_no = cYAML_get_object_item(tree, "seq_no");
1793 return lustre_lnet_show_routing((seq_no) ? seq_no->cy_valueint : -1,
1797 static int handle_yaml_show_credits(struct cYAML *tree, struct cYAML **show_rc,
1798 struct cYAML **err_rc)
1800 struct cYAML *seq_no, *key_nid;
1802 seq_no = cYAML_get_object_item(tree, "seq_no");
1803 key_nid = cYAML_get_object_item(tree, "key_nid");
1805 return lustre_lnet_show_peer((key_nid) ? key_nid->cy_valuestring : NULL,
1806 (seq_no) ? seq_no->cy_valueint : -1,
1810 static int handle_yaml_show_stats(struct cYAML *tree, struct cYAML **show_rc,
1811 struct cYAML **err_rc)
1813 struct cYAML *seq_no;
1815 seq_no = cYAML_get_object_item(tree, "seq_no");
1817 return lustre_lnet_show_stats((seq_no) ? seq_no->cy_valueint : -1,
1821 struct lookup_cmd_hdlr_tbl {
1826 static struct lookup_cmd_hdlr_tbl lookup_config_tbl[] = {
1827 {"route", handle_yaml_config_route},
1828 {"net", handle_yaml_config_net},
1829 {"peer", handle_yaml_config_peer},
1830 {"routing", handle_yaml_config_routing},
1831 {"buffers", handle_yaml_config_buffers},
1835 static struct lookup_cmd_hdlr_tbl lookup_del_tbl[] = {
1836 {"route", handle_yaml_del_route},
1837 {"net", handle_yaml_del_net},
1838 {"peer", handle_yaml_del_peer},
1839 {"routing", handle_yaml_del_routing},
1843 static struct lookup_cmd_hdlr_tbl lookup_show_tbl[] = {
1844 {"route", handle_yaml_show_route},
1845 {"net", handle_yaml_show_net},
1846 {"buffers", handle_yaml_show_routing},
1847 {"routing", handle_yaml_show_routing},
1848 {"credits", handle_yaml_show_credits},
1849 {"statistics", handle_yaml_show_stats},
1853 static cmd_handler_t lookup_fn(char *key,
1854 struct lookup_cmd_hdlr_tbl *tbl)
1860 for (i = 0; tbl[i].name != NULL; i++) {
1861 if (strncmp(key, tbl[i].name, strlen(tbl[i].name)) == 0)
1868 static int lustre_yaml_cb_helper(char *f, struct lookup_cmd_hdlr_tbl *table,
1869 struct cYAML **show_rc, struct cYAML **err_rc)
1871 struct cYAML *tree, *item = NULL, *head, *child;
1873 char err_str[LNET_MAX_STR_LEN];
1874 int rc = LUSTRE_CFG_RC_NO_ERR, return_rc = LUSTRE_CFG_RC_NO_ERR;
1876 tree = cYAML_build_tree(f, NULL, 0, err_rc);
1878 return LUSTRE_CFG_RC_BAD_PARAM;
1880 child = tree->cy_child;
1881 while (child != NULL) {
1882 cb = lookup_fn(child->cy_string, table);
1884 snprintf(err_str, sizeof(err_str),
1885 "\"call back for '%s' not found\"",
1887 cYAML_build_error(LUSTRE_CFG_RC_BAD_PARAM, -1,
1888 "yaml", "helper", err_str, err_rc);
1892 if (cYAML_is_sequence(child)) {
1893 while ((head = cYAML_get_next_seq_item(child, &item))
1895 rc = cb(head, show_rc, err_rc);
1896 if (rc != LUSTRE_CFG_RC_NO_ERR)
1900 rc = cb(child, show_rc, err_rc);
1901 if (rc != LUSTRE_CFG_RC_NO_ERR)
1905 child = child->cy_next;
1909 cYAML_free_tree(tree);
1914 int lustre_yaml_config(char *f, struct cYAML **err_rc)
1916 return lustre_yaml_cb_helper(f, lookup_config_tbl,
1920 int lustre_yaml_del(char *f, struct cYAML **err_rc)
1922 return lustre_yaml_cb_helper(f, lookup_del_tbl,
1926 int lustre_yaml_show(char *f, struct cYAML **show_rc, struct cYAML **err_rc)
1928 return lustre_yaml_cb_helper(f, lookup_show_tbl,