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