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