Whamcloud - gitweb
LU-7475 lnet: ensure buffer config symmetry
[fs/lustre-release.git] / lnet / utils / lnetconfig / liblnetconfig.c
1 /*
2  * LGPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
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.
10  *
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.
15  *
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/>.
18  *
19  * LGPL HEADER END
20  *
21  * Copyright (c) 2014, 2015, Intel Corporation.
22  *
23  * Author:
24  *   Amir Shehata <amir.shehata@intel.com>
25  */
26
27 /*
28  * There are two APIs:
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
34  */
35
36 #include <errno.h>
37 #include <limits.h>
38 #include <netdb.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <sys/ioctl.h>
43 #include <libcfs/util/ioctl.h>
44 #include <lnet/lnetctl.h>
45 #include <lnet/socklnd.h>
46 #include <lnet/lnet.h>
47 #include "liblnetconfig.h"
48 #include "cyaml.h"
49
50 #define CONFIG_CMD              "configure"
51 #define UNCONFIG_CMD            "unconfigure"
52 #define ADD_CMD                 "add"
53 #define DEL_CMD                 "del"
54 #define SHOW_CMD                "show"
55
56 int lustre_lnet_config_lib_init(void)
57 {
58         return register_ioc_dev(LNET_DEV_ID, LNET_DEV_PATH,
59                                 LNET_DEV_MAJOR, LNET_DEV_MINOR);
60 }
61
62 int lustre_lnet_config_ni_system(bool up, bool load_ni_from_mod,
63                                  int seq_no, struct cYAML **err_rc)
64 {
65         struct libcfs_ioctl_data data;
66         unsigned int opc;
67         int rc;
68         char err_str[LNET_MAX_STR_LEN];
69
70         snprintf(err_str, sizeof(err_str), "\"Success\"");
71
72         LIBCFS_IOC_INIT(data);
73
74         /* Reverse logic is used here in order not to change
75          * the lctl utility */
76         data.ioc_flags = load_ni_from_mod ? 0 : 1;
77
78         opc = up ? IOC_LIBCFS_CONFIGURE : IOC_LIBCFS_UNCONFIGURE;
79
80         rc = l_ioctl(LNET_DEV_ID, opc, &data);
81         if (rc != 0) {
82                 snprintf(err_str,
83                         sizeof(err_str),
84                         "\"LNet %s error: %s\"", (up) ? "configure" :
85                         "unconfigure", strerror(errno));
86                 rc = -errno;
87         }
88
89         cYAML_build_error(rc, seq_no, (up) ? CONFIG_CMD : UNCONFIG_CMD,
90                           "lnet", err_str, err_rc);
91
92         return rc;
93 }
94
95 int lustre_lnet_config_route(char *nw, char *gw, int hops, int prio,
96                              int seq_no, struct cYAML **err_rc)
97 {
98         struct lnet_ioctl_config_data data;
99         lnet_nid_t gateway_nid;
100         int rc = LUSTRE_CFG_RC_NO_ERR;
101         __u32 net = LNET_NIDNET(LNET_NID_ANY);
102         char err_str[LNET_MAX_STR_LEN];
103
104         snprintf(err_str, sizeof(err_str), "\"Success\"");
105
106         if (nw == NULL || gw == NULL) {
107                 snprintf(err_str,
108                          sizeof(err_str),
109                          "\"missing mandatory parameter(s): '%s'\"",
110                          (nw == NULL && gw == NULL) ? "network, gateway" :
111                          (nw == NULL) ? "network" : "gateway");
112                 rc = LUSTRE_CFG_RC_MISSING_PARAM;
113                 goto out;
114         }
115
116         net = libcfs_str2net(nw);
117         if (net == LNET_NIDNET(LNET_NID_ANY)) {
118                 snprintf(err_str,
119                          sizeof(err_str),
120                          "\"cannot parse net %s\"", nw);
121                 rc = LUSTRE_CFG_RC_BAD_PARAM;
122                 goto out;
123         }
124
125         if (LNET_NETTYP(net) == CIBLND    ||
126             LNET_NETTYP(net) == OPENIBLND ||
127             LNET_NETTYP(net) == IIBLND    ||
128             LNET_NETTYP(net) == VIBLND) {
129                 snprintf(err_str,
130                          sizeof(err_str),
131                          "\"obselete LNet type '%s'\"", libcfs_lnd2str(net));
132                 rc = LUSTRE_CFG_RC_BAD_PARAM;
133                 goto out;
134         }
135
136         gateway_nid = libcfs_str2nid(gw);
137         if (gateway_nid == LNET_NID_ANY) {
138                 snprintf(err_str,
139                         sizeof(err_str),
140                         "\"cannot parse gateway NID '%s'\"", gw);
141                 rc = LUSTRE_CFG_RC_BAD_PARAM;
142                 goto out;
143         }
144
145         if (hops == -1) {
146                 /* hops is undefined */
147                 hops = LNET_UNDEFINED_HOPS;
148         } else if (hops < 1 || hops > 255) {
149                 snprintf(err_str,
150                         sizeof(err_str),
151                         "\"invalid hop count %d, must be between 1 and 255\"",
152                         hops);
153                 rc = LUSTRE_CFG_RC_OUT_OF_RANGE_PARAM;
154                 goto out;
155         }
156
157         if (prio == -1) {
158                 prio = 0;
159         } else if (prio < 0) {
160                 snprintf(err_str,
161                          sizeof(err_str),
162                         "\"invalid priority %d, must be greater than 0\"",
163                         prio);
164                 rc = LUSTRE_CFG_RC_OUT_OF_RANGE_PARAM;
165                 goto out;
166         }
167
168         LIBCFS_IOC_INIT_V2(data, cfg_hdr);
169         data.cfg_net = net;
170         data.cfg_config_u.cfg_route.rtr_hop = hops;
171         data.cfg_config_u.cfg_route.rtr_priority = prio;
172         data.cfg_nid = gateway_nid;
173
174         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_ADD_ROUTE, &data);
175         if (rc != 0) {
176                 rc = -errno;
177                 snprintf(err_str,
178                          sizeof(err_str),
179                          "\"cannot add route: %s\"", strerror(errno));
180                 goto out;
181         }
182
183 out:
184         cYAML_build_error(rc, seq_no, ADD_CMD, "route", err_str, err_rc);
185
186         return rc;
187 }
188
189 int lustre_lnet_del_route(char *nw, char *gw,
190                           int seq_no, struct cYAML **err_rc)
191 {
192         struct lnet_ioctl_config_data data;
193         lnet_nid_t gateway_nid;
194         int rc = LUSTRE_CFG_RC_NO_ERR;
195         __u32 net = LNET_NIDNET(LNET_NID_ANY);
196         char err_str[LNET_MAX_STR_LEN];
197
198         snprintf(err_str, sizeof(err_str), "\"Success\"");
199
200         if (nw == NULL || gw == NULL) {
201                 snprintf(err_str,
202                          sizeof(err_str),
203                          "\"missing mandatory parameter(s): '%s'\"",
204                          (nw == NULL && gw == NULL) ? "network, gateway" :
205                          (nw == NULL) ? "network" : "gateway");
206                 rc = LUSTRE_CFG_RC_MISSING_PARAM;
207                 goto out;
208         }
209
210         net = libcfs_str2net(nw);
211         if (net == LNET_NIDNET(LNET_NID_ANY)) {
212                 snprintf(err_str,
213                          sizeof(err_str),
214                          "\"cannot parse net '%s'\"", nw);
215                 rc = LUSTRE_CFG_RC_BAD_PARAM;
216                 goto out;
217         }
218
219         if (LNET_NETTYP(net) == CIBLND    ||
220             LNET_NETTYP(net) == OPENIBLND ||
221             LNET_NETTYP(net) == IIBLND    ||
222             LNET_NETTYP(net) == VIBLND) {
223                 snprintf(err_str,
224                          sizeof(err_str),
225                          "\"obselete LNet type '%s'\"", libcfs_lnd2str(net));
226                 rc = LUSTRE_CFG_RC_BAD_PARAM;
227                 goto out;
228         }
229
230         gateway_nid = libcfs_str2nid(gw);
231         if (gateway_nid == LNET_NID_ANY) {
232                 snprintf(err_str,
233                          sizeof(err_str),
234                          "\"cannot parse gateway NID '%s'\"", gw);
235                 rc = LUSTRE_CFG_RC_BAD_PARAM;
236                 goto out;
237         }
238
239         LIBCFS_IOC_INIT_V2(data, cfg_hdr);
240         data.cfg_net = net;
241         data.cfg_nid = gateway_nid;
242
243         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_DEL_ROUTE, &data);
244         if (rc != 0) {
245                 rc = -errno;
246                 snprintf(err_str,
247                          sizeof(err_str),
248                          "\"cannot delete route: %s\"", strerror(errno));
249                 goto out;
250         }
251
252 out:
253         cYAML_build_error(rc, seq_no, DEL_CMD, "route", err_str, err_rc);
254
255         return rc;
256 }
257
258 int lustre_lnet_show_route(char *nw, char *gw, int hops, int prio, int detail,
259                            int seq_no, struct cYAML **show_rc,
260                            struct cYAML **err_rc)
261 {
262         struct lnet_ioctl_config_data data;
263         lnet_nid_t gateway_nid;
264         int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
265         int l_errno = 0;
266         __u32 net = LNET_NIDNET(LNET_NID_ANY);
267         int i;
268         struct cYAML *root = NULL, *route = NULL, *item = NULL;
269         struct cYAML *first_seq = NULL;
270         char err_str[LNET_MAX_STR_LEN];
271         bool exist = false;
272
273         snprintf(err_str, sizeof(err_str),
274                  "\"out of memory\"");
275
276         if (nw != NULL) {
277                 net = libcfs_str2net(nw);
278                 if (net == LNET_NIDNET(LNET_NID_ANY)) {
279                         snprintf(err_str,
280                                  sizeof(err_str),
281                                  "\"cannot parse net '%s'\"", nw);
282                         rc = LUSTRE_CFG_RC_BAD_PARAM;
283                         goto out;
284                 }
285
286                 if (LNET_NETTYP(net) == CIBLND    ||
287                     LNET_NETTYP(net) == OPENIBLND ||
288                     LNET_NETTYP(net) == IIBLND    ||
289                     LNET_NETTYP(net) == VIBLND) {
290                         snprintf(err_str,
291                                  sizeof(err_str),
292                                  "\"obsolete LNet type '%s'\"",
293                                  libcfs_lnd2str(net));
294                         rc = LUSTRE_CFG_RC_BAD_PARAM;
295                         goto out;
296                 }
297         } else {
298                 /* show all routes without filtering on net */
299                 net = LNET_NIDNET(LNET_NID_ANY);
300         }
301
302         if (gw != NULL) {
303                 gateway_nid = libcfs_str2nid(gw);
304                 if (gateway_nid == LNET_NID_ANY) {
305                         snprintf(err_str,
306                                  sizeof(err_str),
307                                  "\"cannot parse gateway NID '%s'\"", gw);
308                         rc = LUSTRE_CFG_RC_BAD_PARAM;
309                         goto out;
310                 }
311         } else
312                 /* show all routes with out filtering on gateway */
313                 gateway_nid = LNET_NID_ANY;
314
315         if ((hops < 1 && hops != -1) || hops > 255) {
316                 snprintf(err_str,
317                          sizeof(err_str),
318                          "\"invalid hop count %d, must be between 0 and 256\"",
319                          hops);
320                 rc = LUSTRE_CFG_RC_OUT_OF_RANGE_PARAM;
321                 goto out;
322         }
323
324         /* create struct cYAML root object */
325         root = cYAML_create_object(NULL, NULL);
326         if (root == NULL)
327                 goto out;
328
329         route = cYAML_create_seq(root, "route");
330         if (route == NULL)
331                 goto out;
332
333         for (i = 0;; i++) {
334                 LIBCFS_IOC_INIT_V2(data, cfg_hdr);
335                 data.cfg_count = i;
336
337                 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_ROUTE, &data);
338                 if (rc != 0) {
339                         l_errno = errno;
340                         break;
341                 }
342
343                 /* filter on provided data */
344                 if (net != LNET_NIDNET(LNET_NID_ANY) &&
345                     net != data.cfg_net)
346                         continue;
347
348                 if (gateway_nid != LNET_NID_ANY &&
349                     gateway_nid != data.cfg_nid)
350                         continue;
351
352                 if (hops != -1 &&
353                     hops != data.cfg_config_u.cfg_route.rtr_hop)
354                         continue;
355
356                 if (prio != -1 &&
357                     prio != data.cfg_config_u.cfg_route.rtr_priority)
358                         continue;
359
360                 /* default rc to -1 incase we hit the goto */
361                 rc = -1;
362                 exist = true;
363
364                 item = cYAML_create_seq_item(route);
365                 if (item == NULL)
366                         goto out;
367
368                 if (first_seq == NULL)
369                         first_seq = item;
370
371                 if (cYAML_create_string(item, "net",
372                                         libcfs_net2str(data.cfg_net)) == NULL)
373                         goto out;
374
375                 if (cYAML_create_string(item, "gateway",
376                                         libcfs_nid2str(data.cfg_nid)) == NULL)
377                         goto out;
378
379                 if (detail) {
380                         if (cYAML_create_number(item, "hop",
381                                                 data.cfg_config_u.cfg_route.
382                                                         rtr_hop) ==
383                             NULL)
384                                 goto out;
385
386                         if (cYAML_create_number(item, "priority",
387                                                 data.cfg_config_u.
388                                                 cfg_route.rtr_priority) == NULL)
389                                 goto out;
390
391                         if (cYAML_create_string(item, "state",
392                                                 data.cfg_config_u.cfg_route.
393                                                         rtr_flags ?
394                                                 "up" : "down") == NULL)
395                                 goto out;
396                 }
397         }
398
399         /* print output iff show_rc is not provided */
400         if (show_rc == NULL)
401                 cYAML_print_tree(root);
402
403         if (l_errno != ENOENT) {
404                 snprintf(err_str,
405                          sizeof(err_str),
406                          "\"cannot get routes: %s\"",
407                          strerror(l_errno));
408                 rc = -l_errno;
409                 goto out;
410         } else
411                 rc = LUSTRE_CFG_RC_NO_ERR;
412
413         snprintf(err_str, sizeof(err_str), "\"success\"");
414 out:
415         if (show_rc == NULL || rc != LUSTRE_CFG_RC_NO_ERR || !exist) {
416                 cYAML_free_tree(root);
417         } else if (show_rc != NULL && *show_rc != NULL) {
418                 struct cYAML *show_node;
419                 /* find the route node, if one doesn't exist then
420                  * insert one.  Otherwise add to the one there
421                  */
422                 show_node = cYAML_get_object_item(*show_rc, "route");
423                 if (show_node != NULL && cYAML_is_sequence(show_node)) {
424                         cYAML_insert_child(show_node, first_seq);
425                         free(route);
426                         free(root);
427                 } else if (show_node == NULL) {
428                         cYAML_insert_sibling((*show_rc)->cy_child,
429                                                 route);
430                         free(root);
431                 } else {
432                         cYAML_free_tree(root);
433                 }
434         } else {
435                 *show_rc = root;
436         }
437
438         cYAML_build_error(rc, seq_no, SHOW_CMD, "route", err_str, err_rc);
439
440         return rc;
441 }
442
443 int lustre_lnet_config_net(char *net, char *intf, char *ip2net,
444                            int peer_to, int peer_cr, int peer_buf_cr,
445                            int credits, char *smp, int seq_no,
446                            struct cYAML **err_rc)
447 {
448         struct lnet_ioctl_config_data data;
449         char buf[LNET_MAX_STR_LEN];
450         int rc = LUSTRE_CFG_RC_NO_ERR;
451         char err_str[LNET_MAX_STR_LEN];
452
453         snprintf(err_str, sizeof(err_str), "\"success\"");
454
455         if (ip2net == NULL && (intf == NULL || net == NULL)) {
456                 snprintf(err_str,
457                          sizeof(err_str),
458                          "\"mandatory parameter '%s' not specified."
459                          " Optionally specify ip2net parameter\"",
460                          (intf == NULL && net == NULL) ? "net, if" :
461                          (intf == NULL) ? "if" : "net");
462                 rc = LUSTRE_CFG_RC_MISSING_PARAM;
463                 goto out;
464         }
465
466         if (peer_to != -1 && peer_to <= 0) {
467                 snprintf(err_str,
468                          sizeof(err_str),
469                          "\"peer timeout %d, must be greater than 0\"",
470                          peer_to);
471                 rc = LUSTRE_CFG_RC_OUT_OF_RANGE_PARAM;
472                 goto out;
473         }
474
475         if (ip2net != NULL && strlen(ip2net) >= sizeof(buf)) {
476                 snprintf(err_str,
477                          sizeof(err_str),
478                          "\"ip2net string too long %d\"",
479                                 (int)strlen(ip2net));
480                 rc = LUSTRE_CFG_RC_OUT_OF_RANGE_PARAM;
481                 goto out;
482         }
483
484         if (ip2net == NULL)
485                 snprintf(buf, sizeof(buf) - 1, "%s(%s)%s",
486                         net, intf,
487                         (smp) ? smp : "");
488
489         LIBCFS_IOC_INIT_V2(data, cfg_hdr);
490         strncpy(data.cfg_config_u.cfg_net.net_intf,
491                 (ip2net != NULL) ? ip2net : buf, sizeof(buf));
492         data.cfg_config_u.cfg_net.net_peer_timeout = peer_to;
493         data.cfg_config_u.cfg_net.net_peer_tx_credits = peer_cr;
494         data.cfg_config_u.cfg_net.net_peer_rtr_credits = peer_buf_cr;
495         data.cfg_config_u.cfg_net.net_max_tx_credits = credits;
496
497         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_ADD_NET, &data);
498         if (rc < 0) {
499                 rc = -errno;
500                 snprintf(err_str,
501                          sizeof(err_str),
502                          "\"cannot add network: %s\"", strerror(errno));
503         }
504
505 out:
506         cYAML_build_error(rc, seq_no, ADD_CMD, "net", err_str, err_rc);
507
508         return rc;
509 }
510
511 int lustre_lnet_del_net(char *nw, int seq_no, struct cYAML **err_rc)
512 {
513         struct lnet_ioctl_config_data data;
514         __u32 net = LNET_NIDNET(LNET_NID_ANY);
515         int rc = LUSTRE_CFG_RC_NO_ERR;
516         char err_str[LNET_MAX_STR_LEN];
517
518         snprintf(err_str, sizeof(err_str), "\"success\"");
519
520         if (nw == NULL) {
521                 snprintf(err_str,
522                          sizeof(err_str),
523                          "\"missing mandatory parameter\"");
524                 rc = LUSTRE_CFG_RC_MISSING_PARAM;
525                 goto out;
526         }
527
528         net = libcfs_str2net(nw);
529         if (net == LNET_NIDNET(LNET_NID_ANY)) {
530                 snprintf(err_str,
531                          sizeof(err_str),
532                          "\"cannot parse net '%s'\"", nw);
533                 rc = LUSTRE_CFG_RC_BAD_PARAM;
534                 goto out;
535         }
536
537         LIBCFS_IOC_INIT_V2(data, cfg_hdr);
538         data.cfg_net = net;
539
540         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_DEL_NET, &data);
541         if (rc != 0) {
542                 rc = -errno;
543                 snprintf(err_str,
544                          sizeof(err_str),
545                          "\"cannot delete network: %s\"", strerror(errno));
546                 goto out;
547         }
548
549 out:
550         cYAML_build_error(rc, seq_no, DEL_CMD, "net", err_str, err_rc);
551
552         return rc;
553 }
554
555 int lustre_lnet_show_net(char *nw, int detail, int seq_no,
556                          struct cYAML **show_rc, struct cYAML **err_rc)
557 {
558         char *buf;
559         struct lnet_ioctl_config_data *data;
560         struct lnet_ioctl_net_config *net_config;
561         __u32 net = LNET_NIDNET(LNET_NID_ANY);
562         int rc = LUSTRE_CFG_RC_OUT_OF_MEM, i, j;
563         int l_errno = 0;
564         struct cYAML *root = NULL, *tunables = NULL,
565                 *net_node = NULL, *interfaces = NULL,
566                 *item = NULL, *first_seq = NULL;
567         int str_buf_len = LNET_MAX_SHOW_NUM_CPT * 2;
568         char str_buf[str_buf_len];
569         char *pos;
570         char err_str[LNET_MAX_STR_LEN];
571         bool exist = false;
572
573         snprintf(err_str, sizeof(err_str), "\"out of memory\"");
574
575         buf = calloc(1, sizeof(*data) + sizeof(*net_config));
576         if (buf == NULL)
577                 goto out;
578
579         data = (struct lnet_ioctl_config_data *)buf;
580
581         if (nw != NULL) {
582                 net = libcfs_str2net(nw);
583                 if (net == LNET_NIDNET(LNET_NID_ANY)) {
584                         snprintf(err_str,
585                                  sizeof(err_str),
586                                  "\"cannot parse net '%s'\"", nw);
587                         rc = LUSTRE_CFG_RC_BAD_PARAM;
588                         goto out;
589                 }
590         }
591
592         root = cYAML_create_object(NULL, NULL);
593         if (root == NULL)
594                 goto out;
595
596         net_node = cYAML_create_seq(root, "net");
597         if (net_node == NULL)
598                 goto out;
599
600         for (i = 0;; i++) {
601                 pos = str_buf;
602
603                 memset(buf, 0, sizeof(*data) + sizeof(*net_config));
604
605                 LIBCFS_IOC_INIT_V2(*data, cfg_hdr);
606                 /*
607                  * set the ioc_len to the proper value since INIT assumes
608                  * size of data
609                  */
610                 data->cfg_hdr.ioc_len = sizeof(struct lnet_ioctl_config_data) +
611                   sizeof(struct lnet_ioctl_net_config);
612                 data->cfg_count = i;
613
614                 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_NET, data);
615                 if (rc != 0) {
616                         l_errno = errno;
617                         break;
618                 }
619
620                 /* filter on provided data */
621                 if (net != LNET_NIDNET(LNET_NID_ANY) &&
622                     net != LNET_NIDNET(data->cfg_nid))
623                         continue;
624
625                 /* default rc to -1 in case we hit the goto */
626                 rc = -1;
627                 exist = true;
628
629                 net_config = (struct lnet_ioctl_net_config *)data->cfg_bulk;
630
631                 /* create the tree to be printed. */
632                 item = cYAML_create_seq_item(net_node);
633                 if (item == NULL)
634                         goto out;
635
636                 if (first_seq == NULL)
637                         first_seq = item;
638
639                 if (cYAML_create_string(item,
640                                         "net",
641                                         libcfs_net2str(
642                                                 LNET_NIDNET(data->cfg_nid)))
643                     == NULL)
644                         goto out;
645
646                 if (cYAML_create_string(item, "nid",
647                                         libcfs_nid2str(data->cfg_nid)) == NULL)
648                         goto out;
649
650                 if (cYAML_create_string(item,
651                                         "status",
652                                         (net_config->ni_status ==
653                                           LNET_NI_STATUS_UP) ?
654                                             "up" : "down") == NULL)
655                         goto out;
656
657                 /* don't add interfaces unless there is at least one
658                  * interface */
659                 if (strlen(net_config->ni_interfaces[0]) > 0) {
660                         interfaces = cYAML_create_object(item, "interfaces");
661                         if (interfaces == NULL)
662                                 goto out;
663
664                         for (j = 0; j < LNET_MAX_INTERFACES; j++) {
665                                 if (strlen(net_config->ni_interfaces[j]) > 0) {
666                                         snprintf(str_buf,
667                                                  sizeof(str_buf), "%d", j);
668                                         if (cYAML_create_string(interfaces,
669                                                 str_buf,
670                                                 net_config->ni_interfaces[j]) ==
671                                             NULL)
672                                                 goto out;
673                                 }
674                         }
675                 }
676
677                 if (detail) {
678                         char *limit;
679
680                         tunables = cYAML_create_object(item, "tunables");
681                         if (tunables == NULL)
682                                 goto out;
683
684                         if (cYAML_create_number(tunables, "peer_timeout",
685                                                 data->cfg_config_u.cfg_net.
686                                                  net_peer_timeout) == NULL)
687                                 goto out;
688
689                         if (cYAML_create_number(tunables, "peer_credits",
690                                                 data->cfg_config_u.cfg_net.
691                                                   net_peer_tx_credits) == NULL)
692                                 goto out;
693
694                         if (cYAML_create_number(tunables,
695                                                 "peer_buffer_credits",
696                                                 data->cfg_config_u.cfg_net.
697                                                   net_peer_rtr_credits) == NULL)
698                                 goto out;
699
700                         if (cYAML_create_number(tunables, "credits",
701                                                 data->cfg_config_u.cfg_net.
702                                                   net_max_tx_credits) == NULL)
703                                 goto out;
704
705                         /* out put the CPTs in the format: "[x,x,x,...]" */
706                         limit = str_buf + str_buf_len - 3;
707                         pos += snprintf(pos, limit - pos, "\"[");
708                         for (j = 0 ; data->cfg_ncpts > 1 &&
709                                 j < data->cfg_ncpts &&
710                                 pos < limit; j++) {
711                                 pos += snprintf(pos, limit - pos,
712                                                 "%d", net_config->ni_cpts[j]);
713                                 if ((j + 1) < data->cfg_ncpts)
714                                         pos += snprintf(pos, limit - pos, ",");
715                         }
716                         pos += snprintf(pos, 3, "]\"");
717
718                         if (data->cfg_ncpts > 1 &&
719                             cYAML_create_string(tunables, "CPT",
720                                                 str_buf) == NULL)
721                                 goto out;
722                 }
723         }
724
725         /* Print out the net information only if show_rc is not provided */
726         if (show_rc == NULL)
727                 cYAML_print_tree(root);
728
729         if (l_errno != ENOENT) {
730                 snprintf(err_str,
731                          sizeof(err_str),
732                          "\"cannot get networks: %s\"",
733                          strerror(l_errno));
734                 rc = -l_errno;
735                 goto out;
736         } else
737                 rc = LUSTRE_CFG_RC_NO_ERR;
738
739         snprintf(err_str, sizeof(err_str), "\"success\"");
740 out:
741         if (show_rc == NULL || rc != LUSTRE_CFG_RC_NO_ERR || !exist) {
742                 cYAML_free_tree(root);
743         } else if (show_rc != NULL && *show_rc != NULL) {
744                 struct cYAML *show_node;
745                 /* find the net node, if one doesn't exist
746                  * then insert one.  Otherwise add to the one there
747                  */
748                 show_node = cYAML_get_object_item(*show_rc, "net");
749                 if (show_node != NULL && cYAML_is_sequence(show_node)) {
750                         cYAML_insert_child(show_node, first_seq);
751                         free(net_node);
752                         free(root);
753                 } else if (show_node == NULL) {
754                         cYAML_insert_sibling((*show_rc)->cy_child,
755                                                 net_node);
756                         free(root);
757                 } else {
758                         cYAML_free_tree(root);
759                 }
760         } else {
761                 *show_rc = root;
762         }
763
764         cYAML_build_error(rc, seq_no, SHOW_CMD, "net", err_str, err_rc);
765
766         return rc;
767 }
768
769 int lustre_lnet_enable_routing(int enable, int seq_no, struct cYAML **err_rc)
770 {
771         struct lnet_ioctl_config_data data;
772         int rc = LUSTRE_CFG_RC_NO_ERR;
773         char err_str[LNET_MAX_STR_LEN];
774
775         snprintf(err_str, sizeof(err_str), "\"success\"");
776
777         LIBCFS_IOC_INIT_V2(data, cfg_hdr);
778         data.cfg_config_u.cfg_buffers.buf_enable = (enable) ? 1 : 0;
779
780         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_CONFIG_RTR, &data);
781         if (rc != 0) {
782                 rc = -errno;
783                 snprintf(err_str,
784                          sizeof(err_str),
785                          "\"cannot %s routing %s\"",
786                          (enable) ? "enable" : "disable", strerror(errno));
787                 goto out;
788         }
789
790 out:
791         cYAML_build_error(rc, seq_no,
792                          (enable) ? ADD_CMD : DEL_CMD,
793                          "routing", err_str, err_rc);
794
795         return rc;
796 }
797
798 int lustre_lnet_config_buffers(int tiny, int small, int large, int seq_no,
799                                struct cYAML **err_rc)
800 {
801         struct lnet_ioctl_config_data data;
802         int rc = LUSTRE_CFG_RC_NO_ERR;
803         char err_str[LNET_MAX_STR_LEN];
804
805         snprintf(err_str, sizeof(err_str), "\"success\"");
806
807         /* -1 indicates to ignore changes to this field */
808         if (tiny < -1 || small < -1 || large < -1) {
809                 snprintf(err_str,
810                          sizeof(err_str),
811                          "\"tiny, small and large must be >= 0\"");
812                 rc = LUSTRE_CFG_RC_OUT_OF_RANGE_PARAM;
813                 goto out;
814         }
815
816         LIBCFS_IOC_INIT_V2(data, cfg_hdr);
817         data.cfg_config_u.cfg_buffers.buf_tiny = tiny;
818         data.cfg_config_u.cfg_buffers.buf_small = small;
819         data.cfg_config_u.cfg_buffers.buf_large = large;
820
821         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_ADD_BUF, &data);
822         if (rc != 0) {
823                 rc = -errno;
824                 snprintf(err_str,
825                          sizeof(err_str),
826                          "\"cannot configure buffers: %s\"", strerror(errno));
827                 goto out;
828         }
829
830 out:
831         cYAML_build_error(rc, seq_no, ADD_CMD, "buf", err_str, err_rc);
832
833         return rc;
834 }
835
836 int lustre_lnet_show_routing(int seq_no, struct cYAML **show_rc,
837                              struct cYAML **err_rc)
838 {
839         struct lnet_ioctl_config_data *data;
840         struct lnet_ioctl_pool_cfg *pool_cfg = NULL;
841         int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
842         int l_errno = 0;
843         char *buf;
844         char *pools[LNET_NRBPOOLS] = {"tiny", "small", "large"};
845         int buf_count[LNET_NRBPOOLS] = {0};
846         struct cYAML *root = NULL, *pools_node = NULL,
847                      *type_node = NULL, *item = NULL, *cpt = NULL,
848                      *first_seq = NULL, *buffers = NULL;
849         int i, j;
850         char err_str[LNET_MAX_STR_LEN];
851         char node_name[LNET_MAX_STR_LEN];
852         bool exist = false;
853
854         snprintf(err_str, sizeof(err_str), "\"out of memory\"");
855
856         buf = calloc(1, sizeof(*data) + sizeof(*pool_cfg));
857         if (buf == NULL)
858                 goto out;
859
860         data = (struct lnet_ioctl_config_data *)buf;
861
862         root = cYAML_create_object(NULL, NULL);
863         if (root == NULL)
864                 goto out;
865
866         pools_node = cYAML_create_seq(root, "routing");
867         if (pools_node == NULL)
868                 goto out;
869
870         for (i = 0;; i++) {
871                 LIBCFS_IOC_INIT_V2(*data, cfg_hdr);
872                 data->cfg_hdr.ioc_len = sizeof(struct lnet_ioctl_config_data) +
873                                         sizeof(struct lnet_ioctl_pool_cfg);
874                 data->cfg_count = i;
875
876                 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_BUF, data);
877                 if (rc != 0) {
878                         l_errno = errno;
879                         break;
880                 }
881
882                 exist = true;
883
884                 pool_cfg = (struct lnet_ioctl_pool_cfg *)data->cfg_bulk;
885
886                 snprintf(node_name, sizeof(node_name), "cpt[%d]", i);
887                 item = cYAML_create_seq_item(pools_node);
888                 if (item == NULL)
889                         goto out;
890
891                 if (first_seq == NULL)
892                         first_seq = item;
893
894                 cpt = cYAML_create_object(item, node_name);
895                 if (cpt == NULL)
896                         goto out;
897
898                 /* create the tree  and print */
899                 for (j = 0; j < LNET_NRBPOOLS; j++) {
900                         type_node = cYAML_create_object(cpt, pools[j]);
901                         if (type_node == NULL)
902                                 goto out;
903                         if (cYAML_create_number(type_node, "npages",
904                                                 pool_cfg->pl_pools[j].pl_npages)
905                             == NULL)
906                                 goto out;
907                         if (cYAML_create_number(type_node, "nbuffers",
908                                                 pool_cfg->pl_pools[j].
909                                                   pl_nbuffers) == NULL)
910                                 goto out;
911                         if (cYAML_create_number(type_node, "credits",
912                                                 pool_cfg->pl_pools[j].
913                                                    pl_credits) == NULL)
914                                 goto out;
915                         if (cYAML_create_number(type_node, "mincredits",
916                                                 pool_cfg->pl_pools[j].
917                                                    pl_mincredits) == NULL)
918                                 goto out;
919                         /* keep track of the total count for each of the
920                          * tiny, small and large buffers */
921                         buf_count[j] += pool_cfg->pl_pools[j].pl_nbuffers;
922                 }
923         }
924
925         if (pool_cfg != NULL) {
926                 item = cYAML_create_seq_item(pools_node);
927                 if (item == NULL)
928                         goto out;
929
930                 if (cYAML_create_number(item, "enable", pool_cfg->pl_routing) ==
931                     NULL)
932                         goto out;
933         }
934
935         /* create a buffers entry in the show. This is necessary so that
936          * if the YAML output is used to configure a node, the buffer
937          * configuration takes hold */
938         buffers = cYAML_create_object(root, "buffers");
939         if (buffers == NULL)
940                 goto out;
941
942         for (i = 0; i < LNET_NRBPOOLS; i++) {
943                 if (cYAML_create_number(buffers, pools[i], buf_count[i]) == NULL)
944                         goto out;
945         }
946
947         if (show_rc == NULL)
948                 cYAML_print_tree(root);
949
950         if (l_errno != ENOENT) {
951                 snprintf(err_str,
952                          sizeof(err_str),
953                          "\"cannot get routing information: %s\"",
954                          strerror(l_errno));
955                 rc = -l_errno;
956                 goto out;
957         } else
958                 rc = LUSTRE_CFG_RC_NO_ERR;
959
960         snprintf(err_str, sizeof(err_str), "\"success\"");
961         rc = LUSTRE_CFG_RC_NO_ERR;
962
963 out:
964         free(buf);
965         if (show_rc == NULL || rc != LUSTRE_CFG_RC_NO_ERR || !exist) {
966                 cYAML_free_tree(root);
967         } else if (show_rc != NULL && *show_rc != NULL) {
968                 struct cYAML *routing_node;
969                 /* there should exist only one routing block and one
970                  * buffers block. If there already exists a previous one
971                  * then don't add another */
972                 routing_node = cYAML_get_object_item(*show_rc, "routing");
973                 if (routing_node == NULL) {
974                         cYAML_insert_sibling((*show_rc)->cy_child,
975                                                 root->cy_child);
976                         free(root);
977                 } else {
978                         cYAML_free_tree(root);
979                 }
980         } else {
981                 *show_rc = root;
982         }
983
984         cYAML_build_error(rc, seq_no, SHOW_CMD, "routing", err_str, err_rc);
985
986         return rc;
987 }
988
989 int lustre_lnet_show_peer_credits(int seq_no, struct cYAML **show_rc,
990                                   struct cYAML **err_rc)
991 {
992         struct lnet_ioctl_peer peer_info;
993         int rc = LUSTRE_CFG_RC_OUT_OF_MEM, ncpt = 0, i = 0, j = 0;
994         int l_errno = 0;
995         struct cYAML *root = NULL, *peer = NULL, *first_seq = NULL,
996                      *peer_root = NULL;
997         char err_str[LNET_MAX_STR_LEN];
998         bool ncpt_set = false;
999
1000         snprintf(err_str, sizeof(err_str),
1001                  "\"out of memory\"");
1002
1003         /* create struct cYAML root object */
1004         root = cYAML_create_object(NULL, NULL);
1005         if (root == NULL)
1006                 goto out;
1007
1008         peer_root = cYAML_create_seq(root, "peer");
1009         if (peer_root == NULL)
1010                 goto out;
1011
1012         do {
1013                 for (i = 0;; i++) {
1014                         LIBCFS_IOC_INIT_V2(peer_info, pr_hdr);
1015                         peer_info.pr_count = i;
1016                         peer_info.pr_lnd_u.pr_peer_credits.cr_ncpt = j;
1017                         rc = l_ioctl(LNET_DEV_ID,
1018                                      IOC_LIBCFS_GET_PEER_INFO, &peer_info);
1019                         if (rc != 0) {
1020                                 l_errno = errno;
1021                                 break;
1022                         }
1023
1024                         if (ncpt_set != 0) {
1025                                 ncpt = peer_info.pr_lnd_u.pr_peer_credits.
1026                                         cr_ncpt;
1027                                 ncpt_set = true;
1028                         }
1029
1030                         peer = cYAML_create_seq_item(peer_root);
1031                         if (peer == NULL)
1032                                 goto out;
1033
1034                         if (first_seq == NULL)
1035                                 first_seq = peer;
1036
1037                         if (cYAML_create_string(peer, "nid",
1038                                                 libcfs_nid2str
1039                                                  (peer_info.pr_nid)) == NULL)
1040                                 goto out;
1041
1042                         if (cYAML_create_string(peer, "state",
1043                                                 peer_info.pr_lnd_u.
1044                                                   pr_peer_credits.
1045                                                         cr_aliveness) ==
1046                             NULL)
1047                                 goto out;
1048
1049                         if (cYAML_create_number(peer, "refcount",
1050                                                 peer_info.pr_lnd_u.
1051                                                   pr_peer_credits.
1052                                                         cr_refcount) == NULL)
1053                                 goto out;
1054
1055                         if (cYAML_create_number(peer, "max_ni_tx_credits",
1056                                                 peer_info.pr_lnd_u.
1057                                                   pr_peer_credits.
1058                                                     cr_ni_peer_tx_credits)
1059                             == NULL)
1060                                 goto out;
1061
1062                         if (cYAML_create_number(peer, "available_tx_credits",
1063                                                 peer_info.pr_lnd_u.
1064                                                   pr_peer_credits.
1065                                                     cr_peer_tx_credits)
1066                             == NULL)
1067                                 goto out;
1068
1069                         if (cYAML_create_number(peer, "available_rtr_credits",
1070                                                 peer_info.pr_lnd_u.
1071                                                   pr_peer_credits.
1072                                                     cr_peer_rtr_credits)
1073                             == NULL)
1074                                 goto out;
1075
1076                         if (cYAML_create_number(peer, "min_rtr_credits",
1077                                                 peer_info.pr_lnd_u.
1078                                                   pr_peer_credits.
1079                                                     cr_peer_min_rtr_credits)
1080                             == NULL)
1081                                 goto out;
1082
1083                         if (cYAML_create_number(peer, "tx_q_num_of_buf",
1084                                                 peer_info.pr_lnd_u.
1085                                                   pr_peer_credits.
1086                                                     cr_peer_tx_qnob)
1087                             == NULL)
1088                                 goto out;
1089                 }
1090
1091                 if (l_errno != ENOENT) {
1092                         snprintf(err_str,
1093                                 sizeof(err_str),
1094                                 "\"cannot get peer information: %s\"",
1095                                 strerror(l_errno));
1096                         rc = -l_errno;
1097                         goto out;
1098                 }
1099
1100                 j++;
1101         } while (j < ncpt);
1102
1103         /* print output iff show_rc is not provided */
1104         if (show_rc == NULL)
1105                 cYAML_print_tree(root);
1106
1107         snprintf(err_str, sizeof(err_str), "\"success\"");
1108         rc = LUSTRE_CFG_RC_NO_ERR;
1109
1110 out:
1111         if (show_rc == NULL || rc != LUSTRE_CFG_RC_NO_ERR) {
1112                 cYAML_free_tree(root);
1113         } else if (show_rc != NULL && *show_rc != NULL) {
1114                 struct cYAML *show_node;
1115                 /* find the peer node, if one doesn't exist then
1116                  * insert one.  Otherwise add to the one there
1117                  */
1118                 show_node = cYAML_get_object_item(*show_rc,
1119                                                   "peer_credits");
1120                 if (show_node != NULL && cYAML_is_sequence(show_node)) {
1121                         cYAML_insert_child(show_node, first_seq);
1122                         free(peer_root);
1123                         free(root);
1124                 } else if (show_node == NULL) {
1125                         cYAML_insert_sibling((*show_rc)->cy_child,
1126                                              peer_root);
1127                         free(root);
1128                 } else {
1129                         cYAML_free_tree(root);
1130                 }
1131         } else {
1132                 *show_rc = root;
1133         }
1134
1135         cYAML_build_error(rc, seq_no, SHOW_CMD, "peer_credits", err_str,
1136                           err_rc);
1137
1138         return rc;
1139 }
1140
1141 int lustre_lnet_show_stats(int seq_no, struct cYAML **show_rc,
1142                            struct cYAML **err_rc)
1143 {
1144         struct lnet_ioctl_lnet_stats data;
1145         int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
1146         int l_errno;
1147         char err_str[LNET_MAX_STR_LEN];
1148         struct cYAML *root = NULL, *stats = NULL;
1149
1150         snprintf(err_str, sizeof(err_str), "\"out of memory\"");
1151
1152         LIBCFS_IOC_INIT_V2(data, st_hdr);
1153
1154         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_LNET_STATS, &data);
1155         if (rc != 0) {
1156                 l_errno = errno;
1157                 snprintf(err_str,
1158                          sizeof(err_str),
1159                          "\"cannot get lnet statistics: %s\"",
1160                          strerror(l_errno));
1161                 rc = -l_errno;
1162                 goto out;
1163         }
1164
1165         root = cYAML_create_object(NULL, NULL);
1166         if (root == NULL)
1167                 goto out;
1168
1169         stats = cYAML_create_object(root, "statistics");
1170         if (stats == NULL)
1171                 goto out;
1172
1173         if (cYAML_create_number(stats, "msgs_alloc",
1174                                 data.st_cntrs.msgs_alloc) == NULL)
1175                 goto out;
1176
1177         if (cYAML_create_number(stats, "msgs_max",
1178                                 data.st_cntrs.msgs_max) == NULL)
1179                 goto out;
1180
1181         if (cYAML_create_number(stats, "errors",
1182                                 data.st_cntrs.errors) == NULL)
1183                 goto out;
1184
1185         if (cYAML_create_number(stats, "send_count",
1186                                 data.st_cntrs.send_count) == NULL)
1187                 goto out;
1188
1189         if (cYAML_create_number(stats, "recv_count",
1190                                 data.st_cntrs.recv_count) == NULL)
1191                 goto out;
1192
1193         if (cYAML_create_number(stats, "route_count",
1194                                 data.st_cntrs.route_count) == NULL)
1195                 goto out;
1196
1197         if (cYAML_create_number(stats, "drop_count",
1198                                 data.st_cntrs.drop_count) == NULL)
1199                 goto out;
1200
1201         if (cYAML_create_number(stats, "send_length",
1202                                 data.st_cntrs.send_length) == NULL)
1203                 goto out;
1204
1205         if (cYAML_create_number(stats, "recv_length",
1206                                 data.st_cntrs.recv_length) == NULL)
1207                 goto out;
1208
1209         if (cYAML_create_number(stats, "route_length",
1210                                 data.st_cntrs.route_length) == NULL)
1211                 goto out;
1212
1213         if (cYAML_create_number(stats, "drop_length",
1214                                 data.st_cntrs.drop_length) == NULL)
1215                 goto out;
1216
1217         if (show_rc == NULL)
1218                 cYAML_print_tree(root);
1219
1220         snprintf(err_str, sizeof(err_str), "\"success\"");
1221 out:
1222         if (show_rc == NULL || rc != LUSTRE_CFG_RC_NO_ERR) {
1223                 cYAML_free_tree(root);
1224         } else if (show_rc != NULL && *show_rc != NULL) {
1225                 cYAML_insert_sibling((*show_rc)->cy_child,
1226                                         root->cy_child);
1227                 free(root);
1228         } else {
1229                 *show_rc = root;
1230         }
1231
1232         cYAML_build_error(rc, seq_no, SHOW_CMD, "statistics", err_str, err_rc);
1233
1234         return rc;
1235 }
1236
1237 typedef int (*cmd_handler_t)(struct cYAML *tree,
1238                              struct cYAML **show_rc,
1239                              struct cYAML **err_rc);
1240
1241 static int handle_yaml_config_route(struct cYAML *tree, struct cYAML **show_rc,
1242                                     struct cYAML **err_rc)
1243 {
1244         struct cYAML *net, *gw, *hop, *prio, *seq_no;
1245
1246         net = cYAML_get_object_item(tree, "net");
1247         gw = cYAML_get_object_item(tree, "gateway");
1248         hop = cYAML_get_object_item(tree, "hop");
1249         prio = cYAML_get_object_item(tree, "priority");
1250         seq_no = cYAML_get_object_item(tree, "seq_no");
1251
1252         return lustre_lnet_config_route((net) ? net->cy_valuestring : NULL,
1253                                         (gw) ? gw->cy_valuestring : NULL,
1254                                         (hop) ? hop->cy_valueint : -1,
1255                                         (prio) ? prio->cy_valueint : -1,
1256                                         (seq_no) ? seq_no->cy_valueint : -1,
1257                                         err_rc);
1258 }
1259
1260 static int handle_yaml_config_net(struct cYAML *tree, struct cYAML **show_rc,
1261                                   struct cYAML **err_rc)
1262 {
1263         struct cYAML *net, *intf, *tunables, *seq_no,
1264               *peer_to = NULL, *peer_buf_cr = NULL, *peer_cr = NULL,
1265               *credits = NULL, *ip2net = NULL, *smp = NULL, *child;
1266         char devs[LNET_MAX_STR_LEN];
1267         char *loc = devs;
1268         int size = LNET_MAX_STR_LEN;
1269         int num;
1270         bool intf_found = false;
1271
1272         ip2net = cYAML_get_object_item(tree, "ip2net");
1273         net = cYAML_get_object_item(tree, "net");
1274         intf = cYAML_get_object_item(tree, "interfaces");
1275         if (intf != NULL) {
1276                 /* grab all the interfaces */
1277                 child = intf->cy_child;
1278                 while (child != NULL && size > 0) {
1279                         if (loc > devs)
1280                                 num  = snprintf(loc, size, ",%s",
1281                                                 child->cy_valuestring);
1282                         else
1283                                 num = snprintf(loc, size, "%s",
1284                                                child->cy_valuestring);
1285                         size -= num;
1286                         loc += num;
1287                         intf_found = true;
1288                         child = child->cy_next;
1289                 }
1290         }
1291
1292         tunables = cYAML_get_object_item(tree, "tunables");
1293         if (tunables != NULL) {
1294                 peer_to = cYAML_get_object_item(tunables, "peer_timeout");
1295                 peer_cr = cYAML_get_object_item(tunables, "peer_credits");
1296                 peer_buf_cr = cYAML_get_object_item(tunables,
1297                                                     "peer_buffer_credits");
1298                 credits = cYAML_get_object_item(tunables, "credits");
1299                 smp = cYAML_get_object_item(tunables, "CPT");
1300         }
1301         seq_no = cYAML_get_object_item(tree, "seq_no");
1302
1303         return lustre_lnet_config_net((net) ? net->cy_valuestring : NULL,
1304                                       (intf_found) ? devs : NULL,
1305                                       (ip2net) ? ip2net->cy_valuestring : NULL,
1306                                       (peer_to) ? peer_to->cy_valueint : -1,
1307                                       (peer_cr) ? peer_cr->cy_valueint : -1,
1308                                       (peer_buf_cr) ?
1309                                         peer_buf_cr->cy_valueint : -1,
1310                                       (credits) ? credits->cy_valueint : -1,
1311                                       (smp) ? smp->cy_valuestring : NULL,
1312                                       (seq_no) ? seq_no->cy_valueint : -1,
1313                                       err_rc);
1314 }
1315
1316 static int handle_yaml_config_buffers(struct cYAML *tree,
1317                                       struct cYAML **show_rc,
1318                                       struct cYAML **err_rc)
1319 {
1320         int rc;
1321         struct cYAML *tiny, *small, *large, *seq_no;
1322
1323         tiny = cYAML_get_object_item(tree, "tiny");
1324         small = cYAML_get_object_item(tree, "small");
1325         large = cYAML_get_object_item(tree, "large");
1326         seq_no = cYAML_get_object_item(tree, "seq_no");
1327
1328         rc = lustre_lnet_config_buffers((tiny) ? tiny->cy_valueint : -1,
1329                                         (small) ? small->cy_valueint : -1,
1330                                         (large) ? large->cy_valueint : -1,
1331                                         (seq_no) ? seq_no->cy_valueint : -1,
1332                                         err_rc);
1333
1334         return rc;
1335 }
1336
1337 static int handle_yaml_config_routing(struct cYAML *tree,
1338                                       struct cYAML **show_rc,
1339                                       struct cYAML **err_rc)
1340 {
1341         int rc = LUSTRE_CFG_RC_NO_ERR;
1342         struct cYAML *seq_no, *enable;
1343
1344         seq_no = cYAML_get_object_item(tree, "seq_no");
1345         enable = cYAML_get_object_item(tree, "enable");
1346
1347         if (enable) {
1348                 rc = lustre_lnet_enable_routing(enable->cy_valueint,
1349                                                 (seq_no) ?
1350                                                     seq_no->cy_valueint : -1,
1351                                                 err_rc);
1352         }
1353
1354         return rc;
1355 }
1356
1357 static int handle_yaml_del_route(struct cYAML *tree, struct cYAML **show_rc,
1358                                  struct cYAML **err_rc)
1359 {
1360         struct cYAML *net;
1361         struct cYAML *gw;
1362         struct cYAML *seq_no;
1363
1364         net = cYAML_get_object_item(tree, "net");
1365         gw = cYAML_get_object_item(tree, "gateway");
1366         seq_no = cYAML_get_object_item(tree, "seq_no");
1367
1368         return lustre_lnet_del_route((net) ? net->cy_valuestring : NULL,
1369                                      (gw) ? gw->cy_valuestring : NULL,
1370                                      (seq_no) ? seq_no->cy_valueint : -1,
1371                                      err_rc);
1372 }
1373
1374 static int handle_yaml_del_net(struct cYAML *tree, struct cYAML **show_rc,
1375                                struct cYAML **err_rc)
1376 {
1377         struct cYAML *net, *seq_no;
1378
1379         net = cYAML_get_object_item(tree, "net");
1380         seq_no = cYAML_get_object_item(tree, "seq_no");
1381
1382         return lustre_lnet_del_net((net) ? net->cy_valuestring : NULL,
1383                                    (seq_no) ? seq_no->cy_valueint : -1,
1384                                    err_rc);
1385 }
1386
1387 static int handle_yaml_del_routing(struct cYAML *tree, struct cYAML **show_rc,
1388                                    struct cYAML **err_rc)
1389 {
1390         struct cYAML *seq_no;
1391
1392         seq_no = cYAML_get_object_item(tree, "seq_no");
1393
1394         return lustre_lnet_enable_routing(0, (seq_no) ?
1395                                                 seq_no->cy_valueint : -1,
1396                                         err_rc);
1397 }
1398
1399 static int handle_yaml_show_route(struct cYAML *tree, struct cYAML **show_rc,
1400                                   struct cYAML **err_rc)
1401 {
1402         struct cYAML *net;
1403         struct cYAML *gw;
1404         struct cYAML *hop;
1405         struct cYAML *prio;
1406         struct cYAML *detail;
1407         struct cYAML *seq_no;
1408
1409         net = cYAML_get_object_item(tree, "net");
1410         gw = cYAML_get_object_item(tree, "gateway");
1411         hop = cYAML_get_object_item(tree, "hop");
1412         prio = cYAML_get_object_item(tree, "priority");
1413         detail = cYAML_get_object_item(tree, "detail");
1414         seq_no = cYAML_get_object_item(tree, "seq_no");
1415
1416         return lustre_lnet_show_route((net) ? net->cy_valuestring : NULL,
1417                                       (gw) ? gw->cy_valuestring : NULL,
1418                                       (hop) ? hop->cy_valueint : -1,
1419                                       (prio) ? prio->cy_valueint : -1,
1420                                       (detail) ? detail->cy_valueint : 0,
1421                                       (seq_no) ? seq_no->cy_valueint : -1,
1422                                       show_rc,
1423                                       err_rc);
1424 }
1425
1426 static int handle_yaml_show_net(struct cYAML *tree, struct cYAML **show_rc,
1427                                 struct cYAML **err_rc)
1428 {
1429         struct cYAML *net, *detail, *seq_no;
1430
1431         net = cYAML_get_object_item(tree, "net");
1432         detail = cYAML_get_object_item(tree, "detail");
1433         seq_no = cYAML_get_object_item(tree, "seq_no");
1434
1435         return lustre_lnet_show_net((net) ? net->cy_valuestring : NULL,
1436                                     (detail) ? detail->cy_valueint : 0,
1437                                     (seq_no) ? seq_no->cy_valueint : -1,
1438                                     show_rc,
1439                                     err_rc);
1440 }
1441
1442 static int handle_yaml_show_routing(struct cYAML *tree, struct cYAML **show_rc,
1443                                     struct cYAML **err_rc)
1444 {
1445         struct cYAML *seq_no;
1446
1447         seq_no = cYAML_get_object_item(tree, "seq_no");
1448
1449         return lustre_lnet_show_routing((seq_no) ? seq_no->cy_valueint : -1,
1450                                         show_rc, err_rc);
1451 }
1452
1453 static int handle_yaml_show_credits(struct cYAML *tree, struct cYAML **show_rc,
1454                                     struct cYAML **err_rc)
1455 {
1456         struct cYAML *seq_no;
1457
1458         seq_no = cYAML_get_object_item(tree, "seq_no");
1459
1460         return lustre_lnet_show_peer_credits((seq_no) ?
1461                                                 seq_no->cy_valueint : -1,
1462                                              show_rc, err_rc);
1463 }
1464
1465 static int handle_yaml_show_stats(struct cYAML *tree, struct cYAML **show_rc,
1466                                   struct cYAML **err_rc)
1467 {
1468         struct cYAML *seq_no;
1469
1470         seq_no = cYAML_get_object_item(tree, "seq_no");
1471
1472         return lustre_lnet_show_stats((seq_no) ? seq_no->cy_valueint : -1,
1473                                       show_rc, err_rc);
1474 }
1475
1476 struct lookup_cmd_hdlr_tbl {
1477         char *name;
1478         cmd_handler_t cb;
1479 };
1480
1481 static struct lookup_cmd_hdlr_tbl lookup_config_tbl[] = {
1482         {"route", handle_yaml_config_route},
1483         {"net", handle_yaml_config_net},
1484         {"routing", handle_yaml_config_routing},
1485         {"buffers", handle_yaml_config_buffers},
1486         {NULL, NULL}
1487 };
1488
1489 static struct lookup_cmd_hdlr_tbl lookup_del_tbl[] = {
1490         {"route", handle_yaml_del_route},
1491         {"net", handle_yaml_del_net},
1492         {"routing", handle_yaml_del_routing},
1493         {NULL, NULL}
1494 };
1495
1496 static struct lookup_cmd_hdlr_tbl lookup_show_tbl[] = {
1497         {"route", handle_yaml_show_route},
1498         {"net", handle_yaml_show_net},
1499         {"buffers", handle_yaml_show_routing},
1500         {"routing", handle_yaml_show_routing},
1501         {"credits", handle_yaml_show_credits},
1502         {"statistics", handle_yaml_show_stats},
1503         {NULL, NULL}
1504 };
1505
1506 static cmd_handler_t lookup_fn(char *key,
1507                                struct lookup_cmd_hdlr_tbl *tbl)
1508 {
1509         int i;
1510         if (key == NULL)
1511                 return NULL;
1512
1513         for (i = 0; tbl[i].name != NULL; i++) {
1514                 if (strncmp(key, tbl[i].name, strlen(tbl[i].name)) == 0)
1515                         return tbl[i].cb;
1516         }
1517
1518         return NULL;
1519 }
1520
1521 static int lustre_yaml_cb_helper(char *f, struct lookup_cmd_hdlr_tbl *table,
1522                                  struct cYAML **show_rc, struct cYAML **err_rc)
1523 {
1524         struct cYAML *tree, *item = NULL, *head, *child;
1525         cmd_handler_t cb;
1526         char err_str[LNET_MAX_STR_LEN];
1527         int rc = LUSTRE_CFG_RC_NO_ERR, return_rc = LUSTRE_CFG_RC_NO_ERR;
1528
1529         tree = cYAML_build_tree(f, NULL, 0, err_rc);
1530         if (tree == NULL)
1531                 return LUSTRE_CFG_RC_BAD_PARAM;
1532
1533         child = tree->cy_child;
1534         while (child != NULL) {
1535                 cb = lookup_fn(child->cy_string, table);
1536                 if (cb == NULL) {
1537                         snprintf(err_str, sizeof(err_str),
1538                                 "\"call back for '%s' not found\"",
1539                                 child->cy_string);
1540                         cYAML_build_error(LUSTRE_CFG_RC_BAD_PARAM, -1,
1541                                         "yaml", "helper", err_str, err_rc);
1542                         goto out;
1543                 }
1544
1545                 if (cYAML_is_sequence(child)) {
1546                         while ((head = cYAML_get_next_seq_item(child, &item))
1547                                != NULL) {
1548                                 rc = cb(head, show_rc, err_rc);
1549                                 if (rc != LUSTRE_CFG_RC_NO_ERR)
1550                                         return_rc = rc;
1551                         }
1552                 } else {
1553                         rc = cb(child, show_rc, err_rc);
1554                         if (rc != LUSTRE_CFG_RC_NO_ERR)
1555                                 return_rc = rc;
1556                 }
1557                 item = NULL;
1558                 child = child->cy_next;
1559         }
1560
1561 out:
1562         cYAML_free_tree(tree);
1563
1564         return return_rc;
1565 }
1566
1567 int lustre_yaml_config(char *f, struct cYAML **err_rc)
1568 {
1569         return lustre_yaml_cb_helper(f, lookup_config_tbl,
1570                                      NULL, err_rc);
1571 }
1572
1573 int lustre_yaml_del(char *f, struct cYAML **err_rc)
1574 {
1575         return lustre_yaml_cb_helper(f, lookup_del_tbl,
1576                                      NULL, err_rc);
1577 }
1578
1579 int lustre_yaml_show(char *f, struct cYAML **show_rc, struct cYAML **err_rc)
1580 {
1581         return lustre_yaml_cb_helper(f, lookup_show_tbl,
1582                                      show_rc, err_rc);
1583 }