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