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