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