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