Whamcloud - gitweb
LU-16460 lnet: validate data sent from user land properly
[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, 2017, 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 <byteswap.h>
39 #include <netdb.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <unistd.h>
44 #include <sys/ioctl.h>
45 #include <net/if.h>
46 #include <libcfs/util/ioctl.h>
47 #include <linux/lnet/lnetctl.h>
48 #include "liblnd.h"
49 #include <sys/types.h>
50 #include <sys/stat.h>
51 #include <fcntl.h>
52 #include <ifaddrs.h>
53 #include <rdma/rdma_user_cm.h>
54 #include "liblnetconfig.h"
55 #include <glob.h>
56 #include <libcfs/util/param.h>
57
58 #ifndef HAVE_USRSPC_RDMA_PS_TCP
59 #define RDMA_PS_TCP 0x0106
60 #endif
61
62 #define cxi_nic_addr_path "/sys/class/cxi/cxi%u/device/properties/"
63 const char *gmsg_stat_names[] = {"sent_stats", "received_stats",
64                                  "dropped_stats"};
65
66 /*
67  * lustre_lnet_ip_range_descr
68  *      Describes an IP range.
69  *      Each octect is an expression
70  */
71 struct lustre_lnet_ip_range_descr {
72         struct list_head ipr_entry;
73         struct list_head ipr_expr;
74 };
75
76 /*
77  * lustre_lnet_ip2nets
78  *      Describes an ip2nets rule. This can be on a list of rules.
79  */
80 struct lustre_lnet_ip2nets {
81         struct lnet_dlc_network_descr ip2nets_net;
82         struct list_head ip2nets_ip_ranges;
83 };
84
85 int open_sysfs_file(const char *path, const char *attr, const int mode)
86 {
87         int fd;
88         char filename[LNET_MAX_STR_LEN];
89
90         if (strlen(path) + strlen(attr) >= LNET_MAX_STR_LEN)
91                 return -1;
92
93         snprintf(filename, sizeof(filename), "%s%s",
94                  path, attr);
95
96         fd = open(filename, mode);
97
98         return fd;
99 }
100
101 static int read_sysfs_file(const char *path, const char *attr,
102                            void *val, const size_t size, const int nelem)
103 {
104         int fd;
105         int rc = LUSTRE_CFG_RC_GENERIC_ERR;
106
107         fd = open_sysfs_file(path, attr, O_RDONLY);
108         if (fd == -1)
109                 return LUSTRE_CFG_RC_NO_MATCH;
110
111         if (read(fd, val, size * nelem) == -1)
112                 goto close_fd;
113
114         rc = LUSTRE_CFG_RC_NO_ERR;
115
116 close_fd:
117         close(fd);
118         return rc;
119 }
120
121 static int write_sysfs_file(const char *path, const char *attr,
122                             void *val, const size_t size, const int nelem)
123 {
124         int fd;
125         int rc = LUSTRE_CFG_RC_GENERIC_ERR;
126
127         fd = open_sysfs_file(path, attr, O_WRONLY | O_TRUNC);
128         if (fd == -1)
129                 return LUSTRE_CFG_RC_NO_MATCH;
130
131         if (write(fd, val, size * nelem) == -1)
132                 goto close_fd;
133
134         rc = LUSTRE_CFG_RC_NO_ERR;
135
136 close_fd:
137         close(fd);
138         return rc;
139 }
140
141 /*
142  * free_intf_descr
143  *      frees the memory allocated for an intf descriptor.
144  */
145 void free_intf_descr(struct lnet_dlc_intf_descr *intf_descr)
146 {
147         if (!intf_descr)
148                 return;
149
150         if (intf_descr->cpt_expr != NULL)
151                 cfs_expr_list_free(intf_descr->cpt_expr);
152         free(intf_descr);
153 }
154
155 /*
156  * lustre_lnet_add_ip_range
157  * Formatting:
158  *      given a string of the format:
159  *      <expr.expr.expr.expr> parse each expr into
160  *      a lustre_lnet_ip_range_descr structure and insert on the list.
161  *
162  *      This function is called from
163  *              YAML on each ip-range.
164  *              As a result of lnetctl command
165  *              When building a NID or P2P selection rules
166  */
167 int lustre_lnet_add_ip_range(struct list_head *list, char *str_ip_range)
168 {
169         struct lustre_lnet_ip_range_descr *ip_range;
170         int rc;
171
172         ip_range = calloc(1, sizeof(*ip_range));
173         if (ip_range == NULL)
174                 return LUSTRE_CFG_RC_OUT_OF_MEM;
175
176         INIT_LIST_HEAD(&ip_range->ipr_entry);
177         INIT_LIST_HEAD(&ip_range->ipr_expr);
178
179         rc = cfs_ip_addr_parse(str_ip_range, strlen(str_ip_range),
180                                &ip_range->ipr_expr);
181         if (rc != 0)
182                 return LUSTRE_CFG_RC_BAD_PARAM;
183
184         list_add_tail(&ip_range->ipr_entry, list);
185
186         return LUSTRE_CFG_RC_NO_ERR;
187 }
188
189 int lustre_lnet_add_intf_descr(struct list_head *list, char *intf, int len)
190 {
191         char *open_sq_bracket = NULL, *close_sq_bracket = NULL,
192              *intf_name;
193         struct lnet_dlc_intf_descr *intf_descr = NULL;
194         int rc;
195         char intf_string[LNET_MAX_STR_LEN];
196
197         if (len >= LNET_MAX_STR_LEN)
198                 return LUSTRE_CFG_RC_BAD_PARAM;
199
200         strncpy(intf_string, intf, len);
201         intf_string[len] = '\0';
202
203         intf_descr = calloc(1, sizeof(*intf_descr));
204         if (intf_descr == NULL)
205                 return LUSTRE_CFG_RC_OUT_OF_MEM;
206
207         INIT_LIST_HEAD(&intf_descr->intf_on_network);
208
209         intf_name = intf_string;
210         open_sq_bracket = strchr(intf_string, '[');
211         if (open_sq_bracket != NULL) {
212                 close_sq_bracket = strchr(intf_string, ']');
213                 if (close_sq_bracket == NULL) {
214                         free(intf_descr);
215                         return LUSTRE_CFG_RC_BAD_PARAM;
216                 }
217                 rc = cfs_expr_list_parse(open_sq_bracket,
218                                          strlen(open_sq_bracket), 0, UINT_MAX,
219                                          &intf_descr->cpt_expr);
220                 if (rc < 0) {
221                         free(intf_descr);
222                         return LUSTRE_CFG_RC_BAD_PARAM;
223                 }
224                 strncpy(intf_descr->intf_name, intf_name,
225                         open_sq_bracket - intf_name);
226                 intf_descr->intf_name[open_sq_bracket - intf_name] = '\0';
227         } else {
228                 strcpy(intf_descr->intf_name, intf_name);
229                 intf_descr->cpt_expr = NULL;
230         }
231
232         list_add_tail(&intf_descr->intf_on_network, list);
233
234         return LUSTRE_CFG_RC_NO_ERR;
235 }
236
237 void lustre_lnet_init_nw_descr(struct lnet_dlc_network_descr *nw_descr)
238 {
239         if (nw_descr != NULL) {
240                 nw_descr->nw_id = 0;
241                 INIT_LIST_HEAD(&nw_descr->network_on_rule);
242                 INIT_LIST_HEAD(&nw_descr->nw_intflist);
243         }
244 }
245
246 int lustre_lnet_parse_nidstr(char *nidstr, lnet_nid_t *lnet_nidlist,
247                              int max_nids, char *err_str)
248 {
249         int rc, num_nids = 0;
250         struct list_head nidlist;
251
252         if (!nidstr) {
253                 snprintf(err_str, LNET_MAX_STR_LEN, "supplied nidstr is NULL");
254                 return LUSTRE_CFG_RC_BAD_PARAM;
255         }
256
257         if (strchr(nidstr, '*')) {
258                 snprintf(err_str, LNET_MAX_STR_LEN,
259                          "asterisk not allowed in nidstring \"%s\"", nidstr);
260                 return LUSTRE_CFG_RC_BAD_PARAM;
261         }
262
263         INIT_LIST_HEAD(&nidlist);
264         rc = cfs_parse_nidlist(nidstr, strlen(nidstr), &nidlist);
265         if (rc == 0) {
266                 snprintf(err_str, LNET_MAX_STR_LEN,
267                          "Unable to parse nidlist from: %s\n", nidstr);
268                 return LUSTRE_CFG_RC_BAD_PARAM;
269         }
270
271         if (list_empty(&nidlist)) {
272                 snprintf(err_str, LNET_MAX_STR_LEN,
273                          "\"%s\" does not specify any valid nid lists", nidstr);
274                 return LUSTRE_CFG_RC_BAD_PARAM;
275         }
276
277         num_nids = cfs_expand_nidlist(&nidlist, lnet_nidlist, max_nids);
278         cfs_free_nidlist(&nidlist);
279
280         if (num_nids == -1) {
281                 snprintf(err_str, LNET_MAX_STR_LEN,
282                          "\"%s\" specifies more than the %d NIDs allowed by this operation.",
283                          nidstr, max_nids);
284                 return LUSTRE_CFG_RC_BAD_PARAM;
285         }
286
287         if (num_nids < 0) {
288                 snprintf(err_str, LNET_MAX_STR_LEN,
289                          "Failed to expand nidstr: %s", strerror(num_nids));
290                 return LUSTRE_CFG_RC_OUT_OF_MEM;
291         }
292
293         if (num_nids == 0) {
294                 snprintf(err_str, LNET_MAX_STR_LEN,
295                          "\"%s\" did not expand to any nids", nidstr);
296                 return LUSTRE_CFG_RC_BAD_PARAM;
297         }
298
299         return num_nids;
300 }
301
302 /*
303  * format expected:
304  *      <intf>[<expr>], <intf>[<expr>],..
305  */
306 int lustre_lnet_parse_interfaces(char *intf_str,
307                                  struct lnet_dlc_network_descr *nw_descr)
308 {
309         char *open_square;
310         char *close_square;
311         char *comma;
312         char *cur = intf_str, *next = NULL;
313         char *end = intf_str + strlen(intf_str);
314         int rc, len;
315         struct lnet_dlc_intf_descr *intf_descr, *tmp;
316
317         if (nw_descr == NULL)
318                 return LUSTRE_CFG_RC_BAD_PARAM;
319
320         while (cur < end) {
321                 open_square = strchr(cur, '[');
322                 if (open_square != NULL) {
323                         close_square = strchr(cur, ']');
324                         if (close_square == NULL) {
325                                 rc = LUSTRE_CFG_RC_BAD_PARAM;
326                                 goto failed;
327                         }
328
329                         comma = strchr(cur, ',');
330                         if (comma != NULL && comma > close_square) {
331                                 next = comma + 1;
332                                 len = next - close_square;
333                         } else {
334                                 len = strlen(cur);
335                                 next = cur + len;
336                         }
337                 } else {
338                         comma = strchr(cur, ',');
339                         if (comma != NULL) {
340                                 next = comma + 1;
341                                 len = comma - cur;
342                         } else {
343                                 len = strlen(cur);
344                                 next = cur + len;
345                         }
346                 }
347
348                 rc = lustre_lnet_add_intf_descr(&nw_descr->nw_intflist, cur, len);
349                 if (rc != LUSTRE_CFG_RC_NO_ERR)
350                         goto failed;
351
352                 cur = next;
353         }
354
355         return LUSTRE_CFG_RC_NO_ERR;
356
357 failed:
358         list_for_each_entry_safe(intf_descr, tmp, &nw_descr->nw_intflist,
359                                  intf_on_network) {
360                 list_del(&intf_descr->intf_on_network);
361                 free_intf_descr(intf_descr);
362         }
363
364         return rc;
365 }
366
367 int lustre_lnet_config_lib_init(void)
368 {
369         return register_ioc_dev(LNET_DEV_ID, LNET_DEV_PATH);
370 }
371
372 void lustre_lnet_config_lib_uninit(void)
373 {
374         unregister_ioc_dev(LNET_DEV_ID);
375 }
376
377 int lustre_lnet_config_ni_system(bool up, bool load_ni_from_mod,
378                                  int seq_no, struct cYAML **err_rc)
379 {
380         struct libcfs_ioctl_data data;
381         unsigned int opc;
382         int rc;
383         char err_str[LNET_MAX_STR_LEN] = "\"Success\"";
384
385         LIBCFS_IOC_INIT(data);
386
387         /* Reverse logic is used here in order not to change
388          * the lctl utility */
389         data.ioc_flags = load_ni_from_mod ? 0 : 1;
390
391         opc = up ? IOC_LIBCFS_CONFIGURE : IOC_LIBCFS_UNCONFIGURE;
392
393         rc = l_ioctl(LNET_DEV_ID, opc, &data);
394         if (rc != 0) {
395                 snprintf(err_str,
396                         sizeof(err_str),
397                         "\"LNet %s error: %s\"", (up) ? "configure" :
398                         "unconfigure", strerror(errno));
399                 rc = -errno;
400         }
401
402         cYAML_build_error(rc, seq_no, (up) ? CONFIG_CMD : UNCONFIG_CMD,
403                           "lnet", err_str, err_rc);
404
405         return rc;
406 }
407
408 static int dispatch_peer_ni_cmd(__u32 cmd, struct lnet_ioctl_peer_cfg *data,
409                                 char *err_str, char *cmd_str)
410 {
411         int rc;
412
413         rc = l_ioctl(LNET_DEV_ID, cmd, data);
414         if (rc) {
415                 rc = -errno;
416                 snprintf(err_str, LNET_MAX_STR_LEN,
417                          "\"%s peer ni operation failed: %s\"",
418                          cmd_str, strerror(errno));
419         }
420
421         return rc;
422 }
423
424 static int infra_ping_nid(char *ping_nids, char *src_nidstr, char *oper,
425                           int param, int ioc_call, int seq_no,
426                           struct cYAML **show_rc, struct cYAML **err_rc)
427 {
428         void *data = NULL;
429         struct lnet_ioctl_ping_data ping;
430         struct cYAML *root = NULL, *ping_node = NULL, *item = NULL,
431                      *first_seq = NULL, *tmp = NULL, *peer_ni = NULL;
432         struct lnet_process_id id;
433         char err_str[LNET_MAX_STR_LEN] = {0};
434         char *sep, *token, *end;
435         char buf[6];
436         size_t len;
437         int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
438         int i;
439         bool flag = false;
440         lnet_nid_t src;
441
442         len = (sizeof(struct lnet_process_id) * LNET_INTERFACES_MAX_DEFAULT);
443
444         data = calloc(1, len);
445         if (data == NULL)
446                 goto out;
447
448         /* create struct cYAML root object */
449         root = cYAML_create_object(NULL, NULL);
450         if (root == NULL)
451                 goto out;
452
453         ping_node = cYAML_create_seq(root, oper);
454         if (ping_node == NULL)
455                 goto out;
456
457         if (src_nidstr) {
458                 src = libcfs_str2nid(src_nidstr);
459                 if (src == LNET_NID_ANY) {
460                         snprintf(err_str, sizeof(err_str),
461                                  "\"cannot parse source NID '%s'\"",
462                                  src_nidstr);
463                         rc = LUSTRE_CFG_RC_BAD_PARAM;
464                         cYAML_build_error(rc, seq_no, MANAGE_CMD,
465                                           oper, err_str, err_rc);
466                         goto out;
467                 }
468         } else {
469                 src = LNET_NID_ANY;
470         }
471
472         /* tokenise each nid in string ping_nids */
473         token = strtok(ping_nids, ",");
474
475         do {
476                 item = cYAML_create_seq_item(ping_node);
477                 if (item == NULL)
478                         goto out;
479
480                 if (first_seq == NULL)
481                         first_seq = item;
482
483                 /* check if '-' is a part of NID, token */
484                 sep = strchr(token, '-');
485                 if (sep == NULL) {
486                         id.pid = LNET_PID_ANY;
487                         /* if no net is specified, libcfs_str2nid() will assume tcp */
488                         id.nid = libcfs_str2nid(token);
489                         if (id.nid == LNET_NID_ANY) {
490                                 snprintf(err_str, sizeof(err_str),
491                                          "\"cannot parse NID '%s'\"",
492                                          token);
493                                 rc = LUSTRE_CFG_RC_BAD_PARAM;
494                                 cYAML_build_error(rc, seq_no, MANAGE_CMD,
495                                                   oper, err_str, err_rc);
496                                 continue;
497                         }
498                 } else {
499                         if (token[0] == 'u' || token[0] == 'U')
500                                 id.pid = (strtoul(&token[1], &end, 0) |
501                                           (LNET_PID_USERFLAG));
502                         else
503                                 id.pid = strtoul(token, &end, 0);
504
505                         /* assuming '-' is part of hostname */
506                         if (end != sep) {
507                                 id.pid = LNET_PID_ANY;
508                                 id.nid = libcfs_str2nid(token);
509                                 if (id.nid == LNET_NID_ANY) {
510                                         snprintf(err_str, sizeof(err_str),
511                                                  "\"cannot parse NID '%s'\"",
512                                                  token);
513                                         rc = LUSTRE_CFG_RC_BAD_PARAM;
514                                         cYAML_build_error(rc, seq_no, MANAGE_CMD,
515                                                           oper, err_str,
516                                                           err_rc);
517                                         continue;
518                                 }
519                         } else {
520                                 id.nid = libcfs_str2nid(sep + 1);
521                                 if (id.nid == LNET_NID_ANY) {
522                                         snprintf(err_str, sizeof(err_str),
523                                                  "\"cannot parse NID '%s'\"",
524                                                  token);
525                                         rc = LUSTRE_CFG_RC_BAD_PARAM;
526                                         cYAML_build_error(rc, seq_no, MANAGE_CMD,
527                                                           oper, err_str,
528                                                           err_rc);
529                                         continue;
530                                 }
531                         }
532                 }
533                 LIBCFS_IOC_INIT_V2(ping, ping_hdr);
534                 ping.ping_hdr.ioc_len = sizeof(ping);
535                 ping.ping_id          = id;
536                 ping.ping_src         = src;
537                 ping.op_param         = param;
538                 ping.ping_count       = LNET_INTERFACES_MAX_DEFAULT;
539                 ping.ping_buf         = data;
540
541                 rc = l_ioctl(LNET_DEV_ID, ioc_call, &ping);
542                 if (rc != 0) {
543                         snprintf(err_str,
544                                  sizeof(err_str), "failed to %s %s: %s\n", oper,
545                                  id.pid == LNET_PID_ANY ?
546                                  libcfs_nid2str(id.nid) :
547                                  libcfs_id2str(id), strerror(errno));
548                         rc = LUSTRE_CFG_RC_BAD_PARAM;
549                         cYAML_build_error(rc, seq_no, MANAGE_CMD,
550                                           oper, err_str, err_rc);
551                         continue;
552                 }
553
554                 if (cYAML_create_string(item, "primary nid",
555                                         libcfs_nid2str(ping.ping_id.nid)) == NULL)
556                         goto out;
557
558                 if (cYAML_create_string(item, "Multi-Rail", ping.mr_info ?
559                                         "True" : "False") == NULL)
560                         goto out;
561
562                 tmp = cYAML_create_seq(item, "peer ni");
563                 if (tmp == NULL)
564                         goto out;
565
566                 for (i = 0; i < ping.ping_count; i++) {
567                         if (ping.ping_buf[i].nid == LNET_NID_LO_0)
568                                 continue;
569                         peer_ni = cYAML_create_seq_item(tmp);
570                         if (peer_ni == NULL)
571                                 goto out;
572                         memset(buf, 0, sizeof buf);
573                         snprintf(buf, sizeof buf, "nid");
574                         if (cYAML_create_string(peer_ni, buf,
575                                                 libcfs_nid2str(ping.ping_buf[i].nid)) == NULL)
576                                 goto out;
577                 }
578
579                 flag = true;
580
581         } while ((token = strtok(NULL, ",")) != NULL);
582
583         if (flag)
584                 rc = LUSTRE_CFG_RC_NO_ERR;
585
586 out:
587         if (data)
588                 free(data);
589         if (show_rc == NULL || rc != LUSTRE_CFG_RC_NO_ERR) {
590                 cYAML_free_tree(root);
591         } else if (show_rc != NULL && *show_rc != NULL) {
592                 struct cYAML *show_node;
593                 show_node = cYAML_get_object_item(*show_rc, oper);
594                 if (show_node != NULL && cYAML_is_sequence(show_node)) {
595                         cYAML_insert_child(show_node, first_seq);
596                         free(ping_node);
597                         free(root);
598                 } else if (show_node == NULL) {
599                         cYAML_insert_sibling((*show_rc)->cy_child,
600                                              ping_node);
601                         free(root);
602                 } else {
603                         cYAML_free_tree(root);
604                 }
605         } else {
606                 *show_rc = root;
607         }
608
609         return rc;
610 }
611
612 int lustre_lnet_ping_nid(char *ping_nids, char *src_nidstr, int timeout,
613                          int seq_no, struct cYAML **show_rc,
614                          struct cYAML **err_rc)
615 {
616         int rc;
617
618         rc = infra_ping_nid(ping_nids, src_nidstr, "ping", timeout,
619                             IOC_LIBCFS_PING_PEER, seq_no, show_rc, err_rc);
620         return rc;
621 }
622
623 int lustre_lnet_discover_nid(char *ping_nids, int force, int seq_no,
624                          struct cYAML **show_rc, struct cYAML **err_rc)
625 {
626         int rc;
627
628         rc = infra_ping_nid(ping_nids, NULL, "discover", force,
629                             IOC_LIBCFS_DISCOVER, seq_no, show_rc, err_rc);
630         return rc;
631 }
632
633 static int lustre_lnet_handle_peer_nidlist(lnet_nid_t *nidlist, int num_nids,
634                                            bool is_mr, __u32 cmd,
635                                            char *cmd_type, char *err_str)
636 {
637         struct lnet_ioctl_peer_cfg data;
638         int rc, nid_idx;
639
640         if (cmd == IOC_LIBCFS_ADD_PEER_NI) {
641                 /* When adding a peer we first need to create the peer using the
642                  * specified (or implied) primary nid. Then we can add
643                  * additional nids to this peer using the primary nid as a key
644                  */
645                 LIBCFS_IOC_INIT_V2(data, prcfg_hdr);
646                 data.prcfg_mr = is_mr;
647                 data.prcfg_prim_nid = nidlist[0];
648                 data.prcfg_cfg_nid = LNET_NID_ANY;
649
650                 rc = dispatch_peer_ni_cmd(cmd, &data, err_str, cmd_type);
651
652                 if (rc)
653                         return rc;
654         }
655
656         /* Add or delete any specified NIs associated with the specified
657          * (or implied) primary nid
658          */
659         for (nid_idx = 1; nid_idx < num_nids; nid_idx++) {
660                 LIBCFS_IOC_INIT_V2(data, prcfg_hdr);
661                 data.prcfg_mr = is_mr;
662                 data.prcfg_prim_nid = nidlist[0];
663                 data.prcfg_cfg_nid = nidlist[nid_idx];
664
665                 rc = dispatch_peer_ni_cmd(cmd, &data, err_str, cmd_type);
666
667                 if (rc)
668                         return rc;
669         }
670
671         if (cmd == IOC_LIBCFS_DEL_PEER_NI && num_nids == 1) {
672                 /* In the delete case we may have been given just the
673                  * primary nid of the peer. This tells us to delete the peer
674                  * completely (rather than just delete some of its NIs)
675                  */
676                 LIBCFS_IOC_INIT_V2(data, prcfg_hdr);
677                 data.prcfg_prim_nid = nidlist[0];
678                 data.prcfg_cfg_nid = LNET_NID_ANY;
679
680                 rc = dispatch_peer_ni_cmd(cmd, &data, err_str, cmd_type);
681         }
682
683         return rc;
684 }
685
686 static int
687 lustre_lnet_mod_peer_nidlist(lnet_nid_t pnid, lnet_nid_t *lnet_nidlist,
688                              int cmd, int num_nids, bool is_mr, int seq_no,
689                              struct cYAML **err_rc)
690 {
691         int rc = LUSTRE_CFG_RC_NO_ERR;
692         char err_str[LNET_MAX_STR_LEN];
693         lnet_nid_t *lnet_nidlist2 = NULL;
694         int ioc_cmd = (cmd == LNETCTL_ADD_CMD) ? IOC_LIBCFS_ADD_PEER_NI :
695                 IOC_LIBCFS_DEL_PEER_NI;
696         char *cmd_str = (cmd == LNETCTL_ADD_CMD) ? ADD_CMD : DEL_CMD;
697
698         num_nids++;
699         lnet_nidlist2 = calloc(sizeof(*lnet_nidlist2), num_nids);
700         if (!lnet_nidlist2) {
701                 snprintf(err_str, LNET_MAX_STR_LEN, "out of memory");
702                 rc = LUSTRE_CFG_RC_OUT_OF_MEM;
703                 goto out;
704         }
705         lnet_nidlist2[0] = pnid;
706         memcpy(&lnet_nidlist2[1], lnet_nidlist, sizeof(*lnet_nidlist) *
707                                                 (num_nids - 1));
708
709         rc = lustre_lnet_handle_peer_nidlist(lnet_nidlist2,
710                                              num_nids, is_mr, ioc_cmd,
711                                              cmd_str, err_str);
712 out:
713         if (lnet_nidlist2)
714                 free(lnet_nidlist2);
715
716         cYAML_build_error(rc, seq_no, cmd_str, "peer_ni", err_str, err_rc);
717         return rc;
718 }
719
720 static void
721 replace_sep(char *str, char sep, char newsep)
722 {
723         int bracket = 0;
724         int i;
725         if (!str)
726                 return;
727         for (i = 0; i < strlen(str); i++) {
728                 /* don't replace ',' within [] */
729                 if (str[i] == '[')
730                         bracket++;
731                 else if (str[i] == ']')
732                         bracket--;
733                 else if (str[i] == sep && bracket == 0)
734                         str[i] = newsep;
735         }
736 }
737
738 int lustre_lnet_modify_peer(char *prim_nid, char *nids, bool is_mr,
739                             int cmd, int seq_no, struct cYAML **err_rc)
740 {
741         int num_nids, rc;
742         char err_str[LNET_MAX_STR_LEN] = "Error";
743         lnet_nid_t lnet_nidlist[LNET_MAX_NIDS_PER_PEER];
744         lnet_nid_t pnid = LNET_NID_ANY;
745
746         if (!prim_nid) {
747                 rc = LUSTRE_CFG_RC_BAD_PARAM;
748                 snprintf(err_str, LNET_MAX_STR_LEN,
749                          "--prim_nid must be specified");
750                 goto out;
751         }
752
753         pnid = libcfs_str2nid(prim_nid);
754         if (pnid == LNET_NID_ANY) {
755                 rc = LUSTRE_CFG_RC_BAD_PARAM;
756                 snprintf(err_str, LNET_MAX_STR_LEN,
757                         "badly formatted primary NID: %s", prim_nid);
758                 goto out;
759         }
760
761         num_nids = 0;
762         if (nids) {
763                 /*
764                 * if there is no primary nid we need to make the first nid in the
765                 * nids list the primary nid
766                 */
767                 replace_sep(nids, ',', ' ');
768                 rc = lustre_lnet_parse_nidstr(nids, lnet_nidlist,
769                                         LNET_MAX_NIDS_PER_PEER, err_str);
770                 if (rc < 0)
771                         goto out;
772
773                 num_nids = rc;
774         }
775
776         rc = lustre_lnet_mod_peer_nidlist(pnid, lnet_nidlist,
777                                           cmd, num_nids, is_mr,
778                                           -1, err_rc);
779
780 out:
781         if (rc != LUSTRE_CFG_RC_NO_ERR)
782                 cYAML_build_error(rc, -1, "peer",
783                                 cmd == LNETCTL_ADD_CMD ? "add" : "del",
784                                 err_str, err_rc);
785
786         return rc;
787 }
788
789 int lustre_lnet_route_common(char *nw, char *nidstr, int hops, int prio,
790                              int sen, int seq_no, struct cYAML **err_rc,
791                              int cmd)
792 {
793         int rc, num_nids, idx;
794         __u32 rnet;
795         char err_str[LNET_MAX_STR_LEN] = "\"generic error\"";
796         struct lnet_ioctl_config_data data;
797         lnet_nid_t lnet_nidlist[LNET_MAX_NIDS_PER_PEER];
798
799         if (nw == NULL || nidstr == NULL) {
800                 snprintf(err_str, LNET_MAX_STR_LEN,
801                          "\"missing mandatory parameter:'%s'\"",
802                          (nw == NULL && nidstr == NULL) ? "network, gateway" :
803                          (nw == NULL) ? "network" : "gateway");
804                 rc = LUSTRE_CFG_RC_MISSING_PARAM;
805                 goto out;
806         }
807
808         rnet = libcfs_str2net(nw);
809         if (rnet == LNET_NET_ANY) {
810                 snprintf(err_str, LNET_MAX_STR_LEN,
811                          "\"cannot parse remote net %s\"", nw);
812                 rc = LUSTRE_CFG_RC_BAD_PARAM;
813                 goto out;
814         }
815
816         replace_sep(nidstr, ',', ' ');
817         rc = lustre_lnet_parse_nidstr(nidstr, lnet_nidlist,
818                                       LNET_MAX_NIDS_PER_PEER, err_str);
819         if (rc < 0)
820                 goto out;
821
822         num_nids = rc;
823
824         for (idx = 0; idx < num_nids; idx++) {
825                 LIBCFS_IOC_INIT_V2(data, cfg_hdr);
826                 data.cfg_net = rnet;
827                 if (cmd == LNETCTL_ADD_CMD) {
828                         data.cfg_config_u.cfg_route.rtr_hop = hops;
829                         data.cfg_config_u.cfg_route.rtr_priority = prio;
830                         data.cfg_config_u.cfg_route.rtr_sensitivity = sen;
831                 }
832
833                 data.cfg_nid = lnet_nidlist[idx];
834
835                 if (cmd == LNETCTL_ADD_CMD)
836                         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_ADD_ROUTE,
837                                         &data);
838                 else
839                         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_DEL_ROUTE,
840                                         &data);
841
842                 if (rc != 0 && errno != EEXIST &&
843                         errno != EHOSTUNREACH) {
844                         rc = -errno;
845                         snprintf(err_str, LNET_MAX_STR_LEN,
846                                         "route operation failed: %s",
847                                         strerror(errno));
848                         goto out;
849                 } else if (errno == EEXIST) {
850                         /*
851                          * continue chugging along if one of the
852                          * routes already exists
853                          */
854                         rc = 0;
855                 }
856         }
857
858 out:
859         cYAML_build_error(rc, seq_no,
860                           cmd == LNETCTL_ADD_CMD ? ADD_CMD : DEL_CMD, "route",
861                           err_str, err_rc);
862
863         return rc;
864 }
865
866 int lustre_lnet_config_route(char *nw, char *nidstr, int hops, int prio,
867                              int sen, int seq_no, struct cYAML **err_rc)
868 {
869         int rc;
870         char err_str[LNET_MAX_STR_LEN] = "\"generic error\"";
871
872         if (hops == -1) {
873                 hops = LNET_UNDEFINED_HOPS;
874         } else if (hops < 1 || hops > 255) {
875                 snprintf(err_str, LNET_MAX_STR_LEN,
876                          "\"invalid hop count %d, must be between 1 and 255\"",
877                          hops);
878                 rc = LUSTRE_CFG_RC_OUT_OF_RANGE_PARAM;
879                 goto out;
880         }
881
882         if (prio == -1) {
883                 prio = 0;
884         } else if (prio < 0) {
885                 snprintf(err_str, LNET_MAX_STR_LEN,
886                          "\"invalid priority %d, must be greater than 0\"",
887                          prio);
888                 rc = LUSTRE_CFG_RC_OUT_OF_RANGE_PARAM;
889                 goto out;
890         }
891
892         if (sen == -1) {
893                 sen = 1;
894         } else if (sen < 1) {
895                 snprintf(err_str, LNET_MAX_STR_LEN,
896                          "\"invalid health sensitivity %d, must be 1 or greater\"",
897                          sen);
898                 rc = LUSTRE_CFG_RC_OUT_OF_RANGE_PARAM;
899                 goto out;
900         }
901
902         rc = lustre_lnet_route_common(nw, nidstr, hops, prio, sen, seq_no,
903                                       err_rc, LNETCTL_ADD_CMD);
904         return rc;
905 out:
906         cYAML_build_error(rc, seq_no, ADD_CMD, "route", err_str, err_rc);
907
908         return rc;
909 }
910
911 int lustre_lnet_del_route(char *nw, char *nidstr, int seq_no,
912                           struct cYAML **err_rc)
913 {
914         return lustre_lnet_route_common(nw, nidstr, 0, 0, 0, seq_no, err_rc,
915                                         LNETCTL_DEL_CMD);
916 }
917
918 int lustre_lnet_show_route(char *nw, char *gw, int hops, int prio, int detail,
919                            int seq_no, struct cYAML **show_rc,
920                            struct cYAML **err_rc, bool backup)
921 {
922         struct lnet_ioctl_config_data data;
923         lnet_nid_t gateway_nid;
924         int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
925         int l_errno = 0;
926         __u32 net = LNET_NET_ANY;
927         int i;
928         struct cYAML *root = NULL, *route = NULL, *item = NULL;
929         struct cYAML *first_seq = NULL;
930         char err_str[LNET_MAX_STR_LEN] = "\"out of memory\"";
931         bool exist = false;
932
933         if (nw != NULL) {
934                 net = libcfs_str2net(nw);
935                 if (net == LNET_NET_ANY) {
936                         snprintf(err_str,
937                                  sizeof(err_str),
938                                  "\"cannot parse net '%s'\"", nw);
939                         rc = LUSTRE_CFG_RC_BAD_PARAM;
940                         goto out;
941                 }
942
943         } else {
944                 /* show all routes without filtering on net */
945                 net = LNET_NET_ANY;
946         }
947
948         if (gw != NULL) {
949                 gateway_nid = libcfs_str2nid(gw);
950                 if (gateway_nid == LNET_NID_ANY) {
951                         snprintf(err_str,
952                                  sizeof(err_str),
953                                  "\"cannot parse gateway NID '%s'\"", gw);
954                         rc = LUSTRE_CFG_RC_BAD_PARAM;
955                         goto out;
956                 }
957         } else
958                 /* show all routes with out filtering on gateway */
959                 gateway_nid = LNET_NID_ANY;
960
961         if ((hops < 1 && hops != -1) || hops > 255) {
962                 snprintf(err_str,
963                          sizeof(err_str),
964                          "\"invalid hop count %d, must be between 0 and 256\"",
965                          hops);
966                 rc = LUSTRE_CFG_RC_OUT_OF_RANGE_PARAM;
967                 goto out;
968         }
969
970         /* create struct cYAML root object */
971         root = cYAML_create_object(NULL, NULL);
972         if (root == NULL)
973                 goto out;
974
975         route = cYAML_create_seq(root, "route");
976         if (route == NULL)
977                 goto out;
978
979         for (i = 0;; i++) {
980                 __u32 rt_alive;
981                 __u32 rt_multi_hop;
982
983                 LIBCFS_IOC_INIT_V2(data, cfg_hdr);
984                 data.cfg_count = i;
985
986                 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_ROUTE, &data);
987                 if (rc != 0) {
988                         l_errno = errno;
989                         break;
990                 }
991
992                 /* filter on provided data */
993                 if (net != LNET_NET_ANY &&
994                     net != data.cfg_net)
995                         continue;
996
997                 if (gateway_nid != LNET_NID_ANY &&
998                     gateway_nid != data.cfg_nid)
999                         continue;
1000
1001                 if (hops != -1 &&
1002                     hops != data.cfg_config_u.cfg_route.rtr_hop)
1003                         continue;
1004
1005                 if (prio != -1 &&
1006                     prio != data.cfg_config_u.cfg_route.rtr_priority)
1007                         continue;
1008
1009                 /* default rc to -1 incase we hit the goto */
1010                 rc = -1;
1011                 exist = true;
1012
1013                 item = cYAML_create_seq_item(route);
1014                 if (item == NULL)
1015                         goto out;
1016
1017                 if (first_seq == NULL)
1018                         first_seq = item;
1019
1020                 if (cYAML_create_string(item, "net",
1021                                         libcfs_net2str(data.cfg_net)) == NULL)
1022                         goto out;
1023
1024                 if (cYAML_create_string(item, "gateway",
1025                                         libcfs_nid2str(data.cfg_nid)) == NULL)
1026                         goto out;
1027
1028                 if (detail) {
1029                         if (cYAML_create_number(item, "hop",
1030                                                 (int) data.cfg_config_u.
1031                                                 cfg_route.rtr_hop) ==
1032                             NULL)
1033                                 goto out;
1034
1035                         if (cYAML_create_number(item, "priority",
1036                                                 data.cfg_config_u.
1037                                                 cfg_route.rtr_priority) == NULL)
1038                                 goto out;
1039
1040                         if (cYAML_create_number(item, "health_sensitivity",
1041                                                 data.cfg_config_u.
1042                                                 cfg_route.rtr_sensitivity) == NULL)
1043                                 goto out;
1044
1045                         rt_alive = data.cfg_config_u.cfg_route.rtr_flags &
1046                                         LNET_RT_ALIVE;
1047                         rt_multi_hop = data.cfg_config_u.cfg_route.rtr_flags &
1048                                         LNET_RT_MULTI_HOP;
1049
1050                         if (!backup &&
1051                             cYAML_create_string(item, "state",
1052                                                 rt_alive ?
1053                                                 "up" : "down") == NULL)
1054                                 goto out;
1055
1056                         if (!backup &&
1057                             cYAML_create_string(item, "type",
1058                                                 rt_multi_hop?
1059                                                 "multi-hop" : "single-hop") == NULL)
1060                                 goto out;
1061                 }
1062         }
1063
1064         /* print output iff show_rc is not provided */
1065         if (show_rc == NULL)
1066                 cYAML_print_tree(root);
1067
1068         if (l_errno != ENOENT) {
1069                 snprintf(err_str,
1070                          sizeof(err_str),
1071                          "\"cannot get routes: %s\"",
1072                          strerror(l_errno));
1073                 rc = -l_errno;
1074                 goto out;
1075         } else
1076                 rc = LUSTRE_CFG_RC_NO_ERR;
1077
1078         snprintf(err_str, sizeof(err_str), "\"success\"");
1079 out:
1080         if (show_rc == NULL || rc != LUSTRE_CFG_RC_NO_ERR || !exist) {
1081                 cYAML_free_tree(root);
1082         } else if (show_rc != NULL && *show_rc != NULL) {
1083                 struct cYAML *show_node;
1084                 /* find the route node, if one doesn't exist then
1085                  * insert one.  Otherwise add to the one there
1086                  */
1087                 show_node = cYAML_get_object_item(*show_rc, "route");
1088                 if (show_node != NULL && cYAML_is_sequence(show_node)) {
1089                         cYAML_insert_child(show_node, first_seq);
1090                         free(route);
1091                         free(root);
1092                 } else if (show_node == NULL) {
1093                         cYAML_insert_sibling((*show_rc)->cy_child,
1094                                                 route);
1095                         free(root);
1096                 } else {
1097                         cYAML_free_tree(root);
1098                 }
1099         } else {
1100                 *show_rc = root;
1101         }
1102
1103         cYAML_build_error(rc, seq_no, SHOW_CMD, "route", err_str, err_rc);
1104
1105         return rc;
1106 }
1107
1108 static int socket_intf_query(int request, char *intf,
1109                              struct ifreq *ifr)
1110 {
1111         int rc = 0;
1112         int sockfd;
1113
1114         if (strlen(intf) >= IFNAMSIZ || ifr == NULL)
1115                 return LUSTRE_CFG_RC_BAD_PARAM;
1116
1117         sockfd = socket(AF_INET, SOCK_DGRAM, 0);
1118         if (sockfd < 0)
1119                 return LUSTRE_CFG_RC_BAD_PARAM;
1120
1121         strcpy(ifr->ifr_name, intf);
1122         rc = ioctl(sockfd, request, ifr);
1123         if (rc != 0)
1124                 rc = LUSTRE_CFG_RC_BAD_PARAM;
1125
1126         close(sockfd);
1127
1128         return rc;
1129 }
1130
1131 static int lustre_lnet_queryip(struct lnet_dlc_intf_descr *intf, __u32 *ip)
1132 {
1133         struct ifreq ifr;
1134         int rc;
1135
1136         memset(&ifr, 0, sizeof(ifr));
1137         rc = socket_intf_query(SIOCGIFFLAGS, intf->intf_name, &ifr);
1138         if (rc != 0)
1139                 return LUSTRE_CFG_RC_BAD_PARAM;
1140
1141         if ((ifr.ifr_flags & IFF_UP) == 0)
1142                 return LUSTRE_CFG_RC_BAD_PARAM;
1143
1144         memset(&ifr, 0, sizeof(ifr));
1145         rc = socket_intf_query(SIOCGIFADDR, intf->intf_name, &ifr);
1146         if (rc != 0)
1147                 return LUSTRE_CFG_RC_BAD_PARAM;
1148
1149         *ip = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
1150         *ip = bswap_32(*ip);
1151
1152         return LUSTRE_CFG_RC_NO_ERR;
1153 }
1154
1155 static int lustre_lnet_kfi_intf2nid(struct lnet_dlc_intf_descr *intf,
1156                                     __u32 *nid_addr)
1157 {
1158         unsigned int nic_index;
1159         int rc;
1160         char *nic_addr_path;
1161         char val[128];
1162         int size;
1163         long int addr;
1164
1165         rc = sscanf(intf->intf_name, "cxi%u", &nic_index);
1166         if (rc != 1)
1167                 return LUSTRE_CFG_RC_NO_MATCH;
1168
1169         size = snprintf(NULL, 0, cxi_nic_addr_path, nic_index) + 1;
1170         nic_addr_path = malloc(size);
1171         if (!nic_addr_path)
1172                 return LUSTRE_CFG_RC_OUT_OF_MEM;
1173         sprintf(nic_addr_path, cxi_nic_addr_path, nic_index);
1174
1175         rc = read_sysfs_file(nic_addr_path, "nic_addr", val, 1, sizeof(val));
1176         free(nic_addr_path);
1177         if (rc)
1178                 return LUSTRE_CFG_RC_NO_MATCH;
1179
1180         addr = strtol(val, NULL, 16);
1181         if (addr == LONG_MIN || addr == LONG_MAX)
1182                 return LUSTRE_CFG_RC_NO_MATCH;
1183
1184         *nid_addr = addr;
1185
1186         return LUSTRE_CFG_RC_NO_ERR;
1187 }
1188
1189 /*
1190  * for each interface in the array of interfaces find the IP address of
1191  * that interface, create its nid and add it to an array of NIDs.
1192  * Stop if any of the interfaces is down
1193  */
1194 static int lustre_lnet_intf2nids(struct lnet_dlc_network_descr *nw,
1195                                  lnet_nid_t **nids, __u32 *nnids,
1196                                  char *err_str, size_t str_len)
1197 {
1198         int i = 0, count = 0, rc;
1199         struct lnet_dlc_intf_descr *intf;
1200         char val[LNET_MAX_STR_LEN];
1201         __u32 ip;
1202         __u32 nic_addr;
1203         int gni_num;
1204         char *endp;
1205         unsigned int num;
1206
1207
1208         if (nw == NULL || nids == NULL) {
1209                 snprintf(err_str, str_len,
1210                          "\"unexpected parameters to lustre_lnet_intf2nids()\"");
1211                 return LUSTRE_CFG_RC_BAD_PARAM;
1212         }
1213
1214         if (LNET_NETTYP(nw->nw_id) == GNILND) {
1215                 count = 1;
1216         } else {
1217                 list_for_each_entry(intf, &nw->nw_intflist, intf_on_network)
1218                         count++;
1219         }
1220
1221         *nids = calloc(count, sizeof(lnet_nid_t));
1222         if (*nids == NULL) {
1223                 snprintf(err_str, str_len,
1224                          "\"out of memory\"");
1225                 return LUSTRE_CFG_RC_OUT_OF_MEM;
1226         }
1227         /*
1228          * special case the GNI interface since it doesn't have an IP
1229          * address. The assumption is that there can only be one GNI
1230          * interface in the system. No interface name is provided.
1231          */
1232         if (LNET_NETTYP(nw->nw_id) == GNILND) {
1233                 rc = read_sysfs_file(gni_nid_path, "nid", val,
1234                                 1, sizeof(val));
1235                 if (rc) {
1236                         snprintf(err_str, str_len,
1237                                  "\"cannot read gni nid\"");
1238                         goto failed;
1239                 }
1240                 gni_num = atoi(val);
1241
1242                 (*nids)[i] = LNET_MKNID(nw->nw_id, gni_num);
1243
1244                 goto out;
1245         } else if (LNET_NETTYP(nw->nw_id) == KFILND) {
1246                 list_for_each_entry(intf, &nw->nw_intflist, intf_on_network) {
1247                         rc = lustre_lnet_kfi_intf2nid(intf, &nic_addr);
1248                         if (rc != LUSTRE_CFG_RC_NO_ERR) {
1249                                 snprintf(err_str, str_len,
1250                                         "\"couldn't query kfi intf %s\"",
1251                                         intf->intf_name);
1252                                 err_str[str_len - 1] = '\0';
1253                                 goto failed;
1254                         }
1255
1256                         (*nids)[i] = LNET_MKNID(nw->nw_id, nic_addr);
1257                         i++;
1258                 }
1259                 goto out;
1260         }
1261
1262         /* look at the other interfaces */
1263         list_for_each_entry(intf, &nw->nw_intflist, intf_on_network) {
1264                 if (LNET_NETTYP(nw->nw_id) == PTL4LND) {
1265                         /* handle LNDs with numeric interface name */
1266                         num = strtoul(intf->intf_name, &endp, 0);
1267                         if (endp == intf->intf_name || *endp != '\0') {
1268                                 rc = LUSTRE_CFG_RC_BAD_PARAM;
1269                                 snprintf(err_str, str_len,
1270                                          "\"couldn't query intf %s\"",
1271                                          intf->intf_name);
1272                                 goto failed;
1273                         }
1274                         (*nids)[i] = LNET_MKNID(nw->nw_id, num);
1275                         i++;
1276                 } else {
1277                         /* handle LNDs with ip interface name */
1278                         rc = lustre_lnet_queryip(intf, &ip);
1279                         if (rc != LUSTRE_CFG_RC_NO_ERR) {
1280                                 snprintf(err_str, str_len,
1281                                          "\"couldn't query intf %s\"",
1282                                          intf->intf_name);
1283                                 goto failed;
1284                         }
1285                         (*nids)[i] = LNET_MKNID(nw->nw_id, ip);
1286                         i++;
1287                 }
1288         }
1289
1290 out:
1291         *nnids = count;
1292
1293         return 0;
1294
1295 failed:
1296         free(*nids);
1297         *nids = NULL;
1298         return rc;
1299 }
1300
1301 /*
1302  * called repeatedly until a match or no more ip range
1303  * What do you have?
1304  *      ip_range expression
1305  *      interface list with all the interface names.
1306  *      all the interfaces in the system.
1307  *
1308  *      try to match the ip_range expr to one of the interfaces' IPs in
1309  *      the system. If we hit a patch for an interface. Check if that
1310  *      interface name is in the list.
1311  *
1312  *      If there are more than one interface in the list, then make sure
1313  *      that the IPs for all of these interfaces match the ip ranges
1314  *      given.
1315  *
1316  *      for each interface in intf_list
1317  *              look up the intf name in ifa
1318  *              if not there then no match
1319  *              check ip obtained from ifa against a match to any of the
1320  *              ip_ranges given.
1321  *              If no match, then fail
1322  *
1323  *      The result is that all the interfaces have to match.
1324  */
1325 int lustre_lnet_match_ip_to_intf(struct ifaddrs *ifa,
1326                                  struct list_head *intf_list,
1327                                  struct list_head *ip_ranges)
1328 {
1329         int rc;
1330         __u32 ip;
1331         struct lnet_dlc_intf_descr *intf_descr, *tmp;
1332         struct ifaddrs *ifaddr = ifa;
1333         struct lustre_lnet_ip_range_descr *ip_range;
1334         int family;
1335
1336         /*
1337          * if there are no explicit interfaces, and no ip ranges, then
1338          * configure the first tcp interface we encounter.
1339          */
1340         if (list_empty(intf_list) && list_empty(ip_ranges)) {
1341                 for (ifaddr = ifa; ifaddr != NULL; ifaddr = ifaddr->ifa_next) {
1342                         if (ifaddr->ifa_addr == NULL)
1343                                 continue;
1344
1345                         if ((ifaddr->ifa_flags & IFF_UP) == 0)
1346                                 continue;
1347
1348                         family = ifaddr->ifa_addr->sa_family;
1349                         if (family == AF_INET &&
1350                             strcmp(ifaddr->ifa_name, "lo") != 0) {
1351                                 rc = lustre_lnet_add_intf_descr
1352                                         (intf_list, ifaddr->ifa_name,
1353                                         strlen(ifaddr->ifa_name));
1354
1355                                 if (rc != LUSTRE_CFG_RC_NO_ERR)
1356                                         return rc;
1357
1358                                 return LUSTRE_CFG_RC_MATCH;
1359                         }
1360                 }
1361                 return LUSTRE_CFG_RC_NO_MATCH;
1362         }
1363
1364         /*
1365          * First interface which matches an IP pattern will be used
1366          */
1367         if (list_empty(intf_list)) {
1368                 /*
1369                  * no interfaces provided in the rule, but an ip range is
1370                  * provided, so try and match an interface to the ip
1371                  * range.
1372                  */
1373                 for (ifaddr = ifa; ifaddr != NULL; ifaddr = ifaddr->ifa_next) {
1374                         if (ifaddr->ifa_addr == NULL)
1375                                 continue;
1376
1377                         if ((ifaddr->ifa_flags & IFF_UP) == 0)
1378                                 continue;
1379
1380                         family = ifaddr->ifa_addr->sa_family;
1381                         if (family == AF_INET) {
1382                                 ip = ((struct sockaddr_in *)ifaddr->ifa_addr)->
1383                                         sin_addr.s_addr;
1384
1385                                 list_for_each_entry(ip_range, ip_ranges,
1386                                                     ipr_entry) {
1387                                         rc = cfs_ip_addr_match(bswap_32(ip),
1388                                                         &ip_range->ipr_expr);
1389                                         if (!rc)
1390                                                 continue;
1391
1392                                         rc = lustre_lnet_add_intf_descr
1393                                           (intf_list, ifaddr->ifa_name,
1394                                            strlen(ifaddr->ifa_name));
1395
1396                                         if (rc != LUSTRE_CFG_RC_NO_ERR)
1397                                                 return rc;
1398                                 }
1399                         }
1400                 }
1401
1402                 if (!list_empty(intf_list))
1403                         return LUSTRE_CFG_RC_MATCH;
1404
1405                 return LUSTRE_CFG_RC_NO_MATCH;
1406         }
1407
1408         /*
1409          * If an interface is explicitly specified the ip-range might or
1410          * might not be specified. if specified the interface needs to match the
1411          * ip-range. If no ip-range then the interfaces are
1412          * automatically matched if they are all up.
1413          * If > 1 interfaces all the interfaces must match for the NI to
1414          * be configured.
1415          */
1416         list_for_each_entry_safe(intf_descr, tmp, intf_list, intf_on_network) {
1417                 for (ifaddr = ifa; ifaddr != NULL; ifaddr = ifaddr->ifa_next) {
1418                         if (ifaddr->ifa_addr == NULL)
1419                                 continue;
1420
1421                         family = ifaddr->ifa_addr->sa_family;
1422                         if (family == AF_INET &&
1423                             strcmp(intf_descr->intf_name,
1424                                    ifaddr->ifa_name) == 0)
1425                                 break;
1426                 }
1427
1428                 if (ifaddr == NULL) {
1429                         list_del(&intf_descr->intf_on_network);
1430                         free_intf_descr(intf_descr);
1431                         continue;
1432                 }
1433
1434                 if ((ifaddr->ifa_flags & IFF_UP) == 0) {
1435                         list_del(&intf_descr->intf_on_network);
1436                         free_intf_descr(intf_descr);
1437                         continue;
1438                 }
1439
1440                 ip = ((struct sockaddr_in *)ifaddr->ifa_addr)->sin_addr.s_addr;
1441
1442                 rc = 1;
1443                 list_for_each_entry(ip_range, ip_ranges, ipr_entry) {
1444                         rc = cfs_ip_addr_match(bswap_32(ip), &ip_range->ipr_expr);
1445                         if (rc)
1446                                 break;
1447                 }
1448
1449                 if (!rc) {
1450                         /* no match for this interface */
1451                         list_del(&intf_descr->intf_on_network);
1452                         free_intf_descr(intf_descr);
1453                 }
1454         }
1455
1456         return LUSTRE_CFG_RC_MATCH;
1457 }
1458
1459 static int lustre_lnet_resolve_ip2nets_rule(struct lustre_lnet_ip2nets *ip2nets,
1460                                             lnet_nid_t **nids, __u32 *nnids,
1461                                             char *err_str, size_t str_len)
1462 {
1463         struct ifaddrs *ifa;
1464         int rc = LUSTRE_CFG_RC_NO_ERR;
1465
1466         rc = getifaddrs(&ifa);
1467         if (rc < 0) {
1468                 snprintf(err_str, str_len,
1469                          "\"failed to get interface addresses: %d\"", -errno);
1470                 return -errno;
1471         }
1472
1473         rc = lustre_lnet_match_ip_to_intf(ifa,
1474                                           &ip2nets->ip2nets_net.nw_intflist,
1475                                           &ip2nets->ip2nets_ip_ranges);
1476         if (rc != LUSTRE_CFG_RC_MATCH) {
1477                 snprintf(err_str, str_len,
1478                          "\"couldn't match ip to existing interfaces\"");
1479                 freeifaddrs(ifa);
1480                 return rc;
1481         }
1482
1483         rc = lustre_lnet_intf2nids(&ip2nets->ip2nets_net, nids, nnids,
1484                                    err_str, str_len);
1485         if (rc != LUSTRE_CFG_RC_NO_ERR) {
1486                 *nids = NULL;
1487                 *nnids = 0;
1488         }
1489
1490         freeifaddrs(ifa);
1491
1492         return rc;
1493 }
1494
1495 static int
1496 lustre_lnet_ioctl_config_ni(struct list_head *intf_list,
1497                             struct lnet_ioctl_config_lnd_tunables *tunables,
1498                             struct cfs_expr_list *global_cpts,
1499                             lnet_nid_t *nids, char *err_str)
1500 {
1501         char *data;
1502         struct lnet_ioctl_config_ni *conf;
1503         struct lnet_ioctl_config_lnd_tunables *tun = NULL;
1504         int rc = LUSTRE_CFG_RC_NO_ERR, i = 0;
1505         size_t len;
1506         int count;
1507         struct lnet_dlc_intf_descr *intf_descr;
1508         __u32 *cpt_array;
1509         struct cfs_expr_list *cpt_expr;
1510
1511         list_for_each_entry(intf_descr, intf_list,
1512                             intf_on_network) {
1513                 if (tunables != NULL)
1514                         len = sizeof(struct lnet_ioctl_config_ni) +
1515                               sizeof(struct lnet_ioctl_config_lnd_tunables);
1516                 else
1517                         len = sizeof(struct lnet_ioctl_config_ni);
1518
1519                 data = calloc(1, len);
1520                 if (!data)
1521                         return LUSTRE_CFG_RC_OUT_OF_MEM;
1522                 conf = (struct lnet_ioctl_config_ni*) data;
1523                 if (tunables != NULL)
1524                         tun = (struct lnet_ioctl_config_lnd_tunables*)
1525                                 conf->lic_bulk;
1526
1527                 LIBCFS_IOC_INIT_V2(*conf, lic_cfg_hdr);
1528                 conf->lic_cfg_hdr.ioc_len = len;
1529                 conf->lic_nid = nids[i];
1530                 strncpy(conf->lic_ni_intf, intf_descr->intf_name,
1531                         LNET_MAX_STR_LEN);
1532
1533                 if (intf_descr->cpt_expr != NULL)
1534                         cpt_expr = intf_descr->cpt_expr;
1535                 else if (global_cpts != NULL)
1536                         cpt_expr = global_cpts;
1537                 else
1538                         cpt_expr = NULL;
1539
1540                 if (cpt_expr != NULL) {
1541                         count = cfs_expr_list_values(cpt_expr,
1542                                                      LNET_MAX_SHOW_NUM_CPT,
1543                                                      &cpt_array);
1544                         if (count > 0) {
1545                                 memcpy(conf->lic_cpts, cpt_array,
1546                                        sizeof(cpt_array[0]) * LNET_MAX_STR_LEN);
1547                                 free(cpt_array);
1548                         } else {
1549                                 count = 0;
1550                         }
1551                 } else {
1552                         count = 0;
1553                 }
1554
1555                 conf->lic_ncpts = count;
1556
1557                 if (tunables != NULL)
1558                         memcpy(tun, tunables, sizeof(*tunables));
1559
1560                 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_ADD_LOCAL_NI, data);
1561                 if (rc < 0) {
1562                         rc = -errno;
1563                         snprintf(err_str,
1564                                  LNET_MAX_STR_LEN,
1565                                  "\"cannot add network: %s\"", strerror(errno));
1566                         free(data);
1567                         return rc;
1568                 }
1569                 free(data);
1570                 i++;
1571         }
1572
1573         return LUSTRE_CFG_RC_NO_ERR;
1574 }
1575
1576 int
1577 lustre_lnet_config_ip2nets(struct lustre_lnet_ip2nets *ip2nets,
1578                            struct lnet_ioctl_config_lnd_tunables *tunables,
1579                            struct cfs_expr_list *global_cpts,
1580                            int seq_no, struct cYAML **err_rc)
1581 {
1582         lnet_nid_t *nids = NULL;
1583         __u32 nnids = 0;
1584         int rc;
1585         char err_str[LNET_MAX_STR_LEN] = "\"success\"";
1586
1587         if (!ip2nets) {
1588                 snprintf(err_str,
1589                          sizeof(err_str),
1590                          "\"incomplete ip2nets information\"");
1591                 rc = LUSTRE_CFG_RC_BAD_PARAM;
1592                 goto out;
1593         }
1594
1595         /*
1596          * call below function to resolve the rules into a list of nids.
1597          * The memory is allocated in that function then freed here when
1598          * it's no longer needed.
1599          */
1600         rc = lustre_lnet_resolve_ip2nets_rule(ip2nets, &nids, &nnids, err_str,
1601                                               sizeof(err_str));
1602         if (rc != LUSTRE_CFG_RC_NO_ERR && rc != LUSTRE_CFG_RC_MATCH)
1603                 goto out;
1604
1605         if (list_empty(&ip2nets->ip2nets_net.nw_intflist)) {
1606                 snprintf(err_str, sizeof(err_str),
1607                          "\"no interfaces match ip2nets rules\"");
1608                 goto free_nids_out;
1609         }
1610
1611         rc = lustre_lnet_ioctl_config_ni(&ip2nets->ip2nets_net.nw_intflist,
1612                                          tunables, global_cpts, nids,
1613                                          err_str);
1614
1615 free_nids_out:
1616         free(nids);
1617
1618 out:
1619         cYAML_build_error(rc, seq_no, ADD_CMD, "ip2nets", err_str, err_rc);
1620         return rc;
1621 }
1622
1623 int lustre_lnet_config_ni(struct lnet_dlc_network_descr *nw_descr,
1624                           struct cfs_expr_list *global_cpts,
1625                           char *ip2net,
1626                           struct lnet_ioctl_config_lnd_tunables *tunables,
1627                           int seq_no, struct cYAML **err_rc)
1628 {
1629         char *data = NULL;
1630         struct lnet_ioctl_config_ni *conf;
1631         struct lnet_ioctl_config_lnd_tunables *tun = NULL;
1632         char buf[LNET_MAX_STR_LEN];
1633         int rc = LUSTRE_CFG_RC_NO_ERR;
1634         char err_str[LNET_MAX_STR_LEN] = "\"success\"";
1635         lnet_nid_t *nids = NULL;
1636         __u32 nnids = 0;
1637         size_t len;
1638         int count;
1639         struct lnet_dlc_intf_descr *intf_descr, *tmp;
1640         __u32 *cpt_array;
1641
1642         if (ip2net == NULL && (nw_descr == NULL || nw_descr->nw_id == 0 ||
1643             (list_empty(&nw_descr->nw_intflist) &&
1644              LNET_NETTYP(nw_descr->nw_id) != GNILND))) {
1645                 snprintf(err_str,
1646                          sizeof(err_str),
1647                          "\"missing mandatory parameters in NI config: '%s'\"",
1648                          (nw_descr == NULL) ? "network , interface" :
1649                          (nw_descr->nw_id == 0) ? "network" : "interface");
1650                 rc = LUSTRE_CFG_RC_MISSING_PARAM;
1651                 goto out;
1652         }
1653
1654         if (ip2net != NULL && strlen(ip2net) >= sizeof(buf)) {
1655                 snprintf(err_str,
1656                          sizeof(err_str),
1657                          "\"ip2net string too long %d\"",
1658                                 (int)strlen(ip2net));
1659                 rc = LUSTRE_CFG_RC_OUT_OF_RANGE_PARAM;
1660                 goto out;
1661         }
1662
1663         if (ip2net != NULL) {
1664                 if (tunables != NULL)
1665                         len = sizeof(struct lnet_ioctl_config_ni) +
1666                               sizeof(struct lnet_ioctl_config_lnd_tunables);
1667                 else
1668                         len = sizeof(struct lnet_ioctl_config_ni);
1669                 data = calloc(1, len);
1670                 if (!data) {
1671                         rc = LUSTRE_CFG_RC_OUT_OF_MEM;
1672                         goto out;
1673                 }
1674                 conf = (struct lnet_ioctl_config_ni*) data;
1675                 if (tunables != NULL)
1676                         tun = (struct lnet_ioctl_config_lnd_tunables*)
1677                                 (data + sizeof(*conf));
1678
1679                 LIBCFS_IOC_INIT_V2(*conf, lic_cfg_hdr);
1680                 conf->lic_cfg_hdr.ioc_len = len;
1681                 strncpy(conf->lic_legacy_ip2nets, ip2net,
1682                         LNET_MAX_STR_LEN);
1683
1684                 if (global_cpts != NULL) {
1685                         count = cfs_expr_list_values(global_cpts,
1686                                                      LNET_MAX_SHOW_NUM_CPT,
1687                                                      &cpt_array);
1688                         if (count > 0) {
1689                                 memcpy(conf->lic_cpts, cpt_array,
1690                                        sizeof(cpt_array[0]) * LNET_MAX_STR_LEN);
1691                                 free(cpt_array);
1692                         } else {
1693                                 count = 0;
1694                         }
1695                 } else {
1696                         count = 0;
1697                 }
1698
1699                 conf->lic_ncpts = count;
1700
1701                 if (tunables != NULL)
1702                         memcpy(tun, tunables, sizeof(*tunables));
1703
1704                 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_ADD_LOCAL_NI, data);
1705                 if (rc < 0) {
1706                         rc = -errno;
1707                         snprintf(err_str,
1708                                 sizeof(err_str),
1709                                 "\"cannot add network: %s\"", strerror(errno));
1710                         goto out;
1711                 }
1712
1713                 goto out;
1714         }
1715
1716         if (LNET_NETTYP(nw_descr->nw_id) == LOLND) {
1717                 rc = LUSTRE_CFG_RC_NO_ERR;
1718                 goto out;
1719         }
1720
1721         if (nw_descr->nw_id == LNET_NET_ANY) {
1722                 snprintf(err_str,
1723                         sizeof(err_str),
1724                         "\"cannot parse net '%s'\"",
1725                         libcfs_net2str(nw_descr->nw_id));
1726                 rc = LUSTRE_CFG_RC_BAD_PARAM;
1727                 goto out;
1728         }
1729
1730         /*
1731          * special case the GNI since no interface name is expected
1732          */
1733         if (list_empty(&nw_descr->nw_intflist) &&
1734             (LNET_NETTYP(nw_descr->nw_id) != GNILND)) {
1735                 snprintf(err_str,
1736                         sizeof(err_str),
1737                         "\"no interface name provided\"");
1738                 rc = LUSTRE_CFG_RC_BAD_PARAM;
1739                 goto out;
1740         }
1741
1742         rc = lustre_lnet_intf2nids(nw_descr, &nids, &nnids,
1743                                    err_str, sizeof(err_str));
1744         if (rc != 0) {
1745                 rc = LUSTRE_CFG_RC_BAD_PARAM;
1746                 goto out;
1747         }
1748
1749         rc = lustre_lnet_ioctl_config_ni(&nw_descr->nw_intflist,
1750                                          tunables, global_cpts, nids,
1751                                          err_str);
1752
1753 out:
1754         if (nw_descr != NULL) {
1755                 list_for_each_entry_safe(intf_descr, tmp,
1756                                          &nw_descr->nw_intflist,
1757                                          intf_on_network) {
1758                         list_del(&intf_descr->intf_on_network);
1759                         free_intf_descr(intf_descr);
1760                 }
1761         }
1762
1763         cYAML_build_error(rc, seq_no, ADD_CMD, "net", err_str, err_rc);
1764
1765         if (nids)
1766                 free(nids);
1767
1768         if (data)
1769                 free(data);
1770
1771         return rc;
1772 }
1773
1774 int lustre_lnet_del_ni(struct lnet_dlc_network_descr *nw_descr,
1775                        int seq_no, struct cYAML **err_rc)
1776 {
1777         struct lnet_ioctl_config_ni data;
1778         int rc = LUSTRE_CFG_RC_NO_ERR, i;
1779         char err_str[LNET_MAX_STR_LEN] = "\"success\"";
1780         lnet_nid_t *nids = NULL;
1781         __u32 nnids = 0;
1782         struct lnet_dlc_intf_descr *intf_descr, *tmp;
1783
1784         if (nw_descr == NULL || nw_descr->nw_id == 0) {
1785                 snprintf(err_str,
1786                          sizeof(err_str),
1787                          "\"missing mandatory parameter in deleting NI: '%s'\"",
1788                          (nw_descr == NULL) ? "network , interface" :
1789                          (nw_descr->nw_id == 0) ? "network" : "interface");
1790                 rc = LUSTRE_CFG_RC_MISSING_PARAM;
1791                 goto out;
1792         }
1793
1794         if (LNET_NETTYP(nw_descr->nw_id) == LOLND)
1795                 return LUSTRE_CFG_RC_NO_ERR;
1796
1797         if (nw_descr->nw_id == LNET_NET_ANY) {
1798                 snprintf(err_str,
1799                          sizeof(err_str),
1800                          "\"cannot parse net '%s'\"",
1801                          libcfs_net2str(nw_descr->nw_id));
1802                 rc = LUSTRE_CFG_RC_BAD_PARAM;
1803                 goto out;
1804         }
1805
1806         rc = lustre_lnet_intf2nids(nw_descr, &nids, &nnids,
1807                                    err_str, sizeof(err_str));
1808         if (rc != 0) {
1809                 rc = LUSTRE_CFG_RC_BAD_PARAM;
1810                 goto out;
1811         }
1812
1813         /*
1814          * no interfaces just the nw_id is specified
1815          */
1816         if (nnids == 0) {
1817                 nids = calloc(1, sizeof(*nids));
1818                 if (nids == NULL) {
1819                         snprintf(err_str, sizeof(err_str),
1820                                 "\"out of memory\"");
1821                         rc = LUSTRE_CFG_RC_OUT_OF_MEM;
1822                         goto out;
1823                 }
1824                 nids[0] = LNET_MKNID(nw_descr->nw_id, 0);
1825                 nnids = 1;
1826         }
1827
1828         for (i = 0; i < nnids; i++) {
1829                 LIBCFS_IOC_INIT_V2(data, lic_cfg_hdr);
1830                 data.lic_nid = nids[i];
1831
1832                 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_DEL_LOCAL_NI, &data);
1833                 if (rc < 0) {
1834                         rc = -errno;
1835                         snprintf(err_str,
1836                                 sizeof(err_str),
1837                                 "\"cannot del network: %s\"", strerror(errno));
1838                 }
1839         }
1840
1841         list_for_each_entry_safe(intf_descr, tmp, &nw_descr->nw_intflist,
1842                                  intf_on_network) {
1843                 list_del(&intf_descr->intf_on_network);
1844                 free_intf_descr(intf_descr);
1845         }
1846
1847 out:
1848         cYAML_build_error(rc, seq_no, DEL_CMD, "net", err_str, err_rc);
1849
1850         if (nids != NULL)
1851                 free(nids);
1852
1853         return rc;
1854 }
1855
1856 static int
1857 lustre_lnet_config_healthv(int value, bool all, lnet_nid_t nid,
1858                            enum lnet_health_type type, char *name,
1859                            int seq_no, struct cYAML **err_rc)
1860 {
1861         struct lnet_ioctl_reset_health_cfg data;
1862         int rc = LUSTRE_CFG_RC_NO_ERR;
1863         char err_str[LNET_MAX_STR_LEN] = "\"success\"";
1864
1865         LIBCFS_IOC_INIT_V2(data, rh_hdr);
1866         data.rh_type = type;
1867         data.rh_all = all;
1868         data.rh_value = value;
1869         data.rh_nid = nid;
1870
1871         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_SET_HEALHV, &data);
1872         if (rc != 0) {
1873                 rc = -errno;
1874                 snprintf(err_str,
1875                          sizeof(err_str), "Can not configure health value: %s",
1876                          strerror(errno));
1877         }
1878
1879         cYAML_build_error(rc, seq_no, ADD_CMD, name, err_str, err_rc);
1880
1881         return rc;
1882 }
1883
1884
1885 static int
1886 lustre_lnet_config_conns_per_peer(int value, bool all, lnet_nid_t nid,
1887                                   char *name, int seq_no,
1888                                   struct cYAML **err_rc)
1889 {
1890         struct lnet_ioctl_reset_conns_per_peer_cfg data;
1891         int rc = LUSTRE_CFG_RC_NO_ERR;
1892         char err_str[LNET_MAX_STR_LEN] = "\"success\"";
1893
1894         LIBCFS_IOC_INIT_V2(data, rcpp_hdr);
1895         data.rcpp_all = all;
1896         data.rcpp_value = value;
1897         data.rcpp_nid = nid;
1898
1899         if (value < 0 || value > 127) {
1900                 rc = LUSTRE_CFG_RC_BAD_PARAM;
1901                 snprintf(err_str, sizeof(err_str),
1902                          "\"Valid values are: 0-127\"");
1903         } else {
1904
1905                 rc = l_ioctl(LNET_DEV_ID,
1906                              IOC_LIBCFS_SET_CONNS_PER_PEER, &data);
1907                 if (rc != 0) {
1908                         rc = -errno;
1909                         snprintf(err_str,
1910                                  sizeof(err_str),
1911                                  "Can not configure conns_per_peer value: %s",
1912                                  strerror(errno));
1913                 }
1914         }
1915         cYAML_build_error(rc, seq_no, ADD_CMD, name, err_str, err_rc);
1916
1917         return rc;
1918 }
1919
1920 int lustre_lnet_config_ni_healthv(int value, bool all, char *ni_nid, int seq_no,
1921                                   struct cYAML **err_rc)
1922 {
1923         lnet_nid_t nid;
1924         if (ni_nid)
1925                 nid = libcfs_str2nid(ni_nid);
1926         else
1927                 nid = LNET_NID_ANY;
1928         return lustre_lnet_config_healthv(value, all, nid,
1929                                           LNET_HEALTH_TYPE_LOCAL_NI,
1930                                           "ni healthv", seq_no, err_rc);
1931 }
1932
1933 int lustre_lnet_config_peer_ni_healthv(int value, bool all, char *lpni_nid,
1934                                        int seq_no, struct cYAML **err_rc)
1935 {
1936         lnet_nid_t nid;
1937         if (lpni_nid)
1938                 nid = libcfs_str2nid(lpni_nid);
1939         else
1940                 nid = LNET_NID_ANY;
1941         return lustre_lnet_config_healthv(value, all, nid,
1942                                           LNET_HEALTH_TYPE_PEER_NI,
1943                                           "peer_ni healthv", seq_no, err_rc);
1944 }
1945
1946 int lustre_lnet_config_ni_conns_per_peer(int value, bool all, char *ni_nid,
1947                                          int seq_no, struct cYAML **err_rc)
1948 {
1949         lnet_nid_t nid;
1950
1951         if (ni_nid)
1952                 nid = libcfs_str2nid(ni_nid);
1953         else
1954                 nid = LNET_NID_ANY;
1955         return lustre_lnet_config_conns_per_peer(value, all, nid,
1956                                                  "ni conns_per_peer",
1957                                                  seq_no, err_rc);
1958 }
1959
1960 static bool
1961 add_msg_stats_to_yaml_blk(struct cYAML *yaml,
1962                           struct lnet_ioctl_comm_count *counts)
1963 {
1964         if (cYAML_create_number(yaml, "put",
1965                                 counts->ico_put_count)
1966                                         == NULL)
1967                 return false;
1968         if (cYAML_create_number(yaml, "get",
1969                                 counts->ico_get_count)
1970                                         == NULL)
1971                 return false;
1972         if (cYAML_create_number(yaml, "reply",
1973                                 counts->ico_reply_count)
1974                                         == NULL)
1975                 return false;
1976         if (cYAML_create_number(yaml, "ack",
1977                                 counts->ico_ack_count)
1978                                         == NULL)
1979                 return false;
1980         if (cYAML_create_number(yaml, "hello",
1981                                 counts->ico_hello_count)
1982                                         == NULL)
1983                 return false;
1984
1985         return true;
1986 }
1987
1988 static struct lnet_ioctl_comm_count *
1989 get_counts(struct lnet_ioctl_element_msg_stats *msg_stats, int idx)
1990 {
1991         if (idx == 0)
1992                 return &msg_stats->im_send_stats;
1993         if (idx == 1)
1994                 return &msg_stats->im_recv_stats;
1995         if (idx == 2)
1996                 return &msg_stats->im_drop_stats;
1997
1998         return NULL;
1999 }
2000
2001 static int
2002 create_local_udsp_info(struct lnet_ioctl_construct_udsp_info *udsp_info,
2003                        struct cYAML *net_node)
2004 {
2005         char tmp[LNET_MAX_STR_LEN];
2006         struct cYAML *udsp_net;
2007         bool created = false;
2008         struct cYAML *pref;
2009         int i;
2010
2011         /* add the UDSP info */
2012         udsp_net = cYAML_create_object(net_node, "udsp info");
2013         if (!udsp_net)
2014                 return LUSTRE_CFG_RC_OUT_OF_MEM;
2015
2016         if (!cYAML_create_number(udsp_net, "net priority",
2017                                  (int) udsp_info->cud_net_priority))
2018                 return LUSTRE_CFG_RC_OUT_OF_MEM;
2019
2020         if (!cYAML_create_number(udsp_net, "nid priority",
2021                                  (int)udsp_info->cud_nid_priority))
2022                 return LUSTRE_CFG_RC_OUT_OF_MEM;
2023
2024         pref = udsp_net;
2025
2026         for (i = 0; i < LNET_MAX_SHOW_NUM_NID; i++) {
2027                 memset(tmp, 0, LNET_MAX_STR_LEN);
2028                 if (udsp_info->cud_pref_rtr_nid[i] == 0)
2029                         break;
2030                 if (!created) {
2031                         pref = cYAML_create_object(udsp_net,
2032                                         "Preferred gateway NIDs");
2033                         if (!pref)
2034                                 return LUSTRE_CFG_RC_OUT_OF_MEM;
2035                         created = true;
2036                 }
2037                 snprintf(tmp, sizeof(tmp), "NID-%d", i);
2038                 if (!cYAML_create_string(pref, tmp,
2039                         libcfs_nid2str(udsp_info->cud_pref_rtr_nid[i])))
2040                         return LUSTRE_CFG_RC_OUT_OF_MEM;
2041         }
2042
2043         return LUSTRE_CFG_RC_NO_ERR;
2044 }
2045
2046 static int
2047 create_remote_udsp_info(struct lnet_ioctl_construct_udsp_info *udsp_info,
2048                         struct cYAML *nid_node)
2049 {
2050         char tmp[LNET_MAX_STR_LEN];
2051         struct cYAML *udsp_nid;
2052         bool created = false;
2053         struct cYAML *pref;
2054         int i;
2055
2056         /* add the UDSP info */
2057         udsp_nid = cYAML_create_object(nid_node, "udsp info");
2058         if (!udsp_nid)
2059                 return LUSTRE_CFG_RC_OUT_OF_MEM;
2060
2061         if (!cYAML_create_number(udsp_nid, "net priority",
2062                                  (int) udsp_info->cud_net_priority))
2063                 return LUSTRE_CFG_RC_OUT_OF_MEM;
2064
2065         if (!cYAML_create_number(udsp_nid, "nid priority",
2066                                  (int) udsp_info->cud_nid_priority))
2067                 return LUSTRE_CFG_RC_OUT_OF_MEM;
2068
2069         pref = udsp_nid;
2070         for (i = 0; i < LNET_MAX_SHOW_NUM_NID; i++) {
2071                 memset(tmp, 0, LNET_MAX_STR_LEN);
2072                 if (udsp_info->cud_pref_rtr_nid[i] == 0)
2073                         break;
2074                 if (!created) {
2075                         pref = cYAML_create_object(udsp_nid,
2076                                         "Preferred gateway NIDs");
2077                         if (!pref)
2078                                 return LUSTRE_CFG_RC_OUT_OF_MEM;
2079                         created = true;
2080                 }
2081                 snprintf(tmp, sizeof(tmp), "NID-%d", i);
2082                 if (!cYAML_create_string(pref, tmp,
2083                         libcfs_nid2str(udsp_info->cud_pref_rtr_nid[i])))
2084                         return LUSTRE_CFG_RC_OUT_OF_MEM;
2085         }
2086
2087         pref = udsp_nid;
2088         created = false;
2089         for (i = 0; i < LNET_MAX_SHOW_NUM_NID; i++) {
2090                 memset(tmp, 0, LNET_MAX_STR_LEN);
2091                 if (udsp_info->cud_pref_nid[i] == 0)
2092                         break;
2093                 if (!created) {
2094                         pref = cYAML_create_object(udsp_nid,
2095                                         "Preferred source NIDs");
2096                         if (!pref)
2097                                 return LUSTRE_CFG_RC_OUT_OF_MEM;
2098                         created = true;
2099                 }
2100                 snprintf(tmp, sizeof(tmp), "NID-%d", i);
2101                 if (!cYAML_create_string(pref, tmp,
2102                         libcfs_nid2str(udsp_info->cud_pref_nid[i])))
2103                         return LUSTRE_CFG_RC_OUT_OF_MEM;
2104         }
2105
2106         return LUSTRE_CFG_RC_NO_ERR;
2107 }
2108
2109 int lustre_lnet_show_net(char *nw, int detail, int seq_no,
2110                          struct cYAML **show_rc, struct cYAML **err_rc,
2111                          bool backup)
2112 {
2113         char *buf;
2114         struct lnet_ioctl_config_ni *ni_data;
2115         struct lnet_ioctl_config_lnd_tunables *lnd;
2116         struct lnet_ioctl_element_stats *stats;
2117         struct lnet_ioctl_element_msg_stats msg_stats;
2118         struct lnet_ioctl_local_ni_hstats hstats;
2119         struct lnet_ioctl_construct_udsp_info udsp_info;
2120         __u32 net = LNET_NET_ANY;
2121         __u32 prev_net = LNET_NET_ANY;
2122         int rc = LUSTRE_CFG_RC_OUT_OF_MEM, i, j;
2123         int l_errno = 0;
2124         struct cYAML *root = NULL, *tunables = NULL,
2125                 *net_node = NULL, *interfaces = NULL,
2126                 *item = NULL, *first_seq = NULL,
2127                 *tmp = NULL, *statistics = NULL,
2128                 *yhstats = NULL;
2129         int str_buf_len = LNET_MAX_SHOW_NUM_CPT * 2;
2130         char str_buf[str_buf_len];
2131         char *pos;
2132         char err_str[LNET_MAX_STR_LEN] = "\"out of memory\"";
2133         bool exist = false, new_net = true;
2134         int net_num = 0;
2135         size_t buf_size = sizeof(*ni_data) + sizeof(*lnd) + sizeof(*stats);
2136
2137         buf = calloc(1, buf_size);
2138         if (buf == NULL)
2139                 goto out;
2140
2141         ni_data = (struct lnet_ioctl_config_ni *)buf;
2142
2143         if (nw != NULL) {
2144                 net = libcfs_str2net(nw);
2145                 if (net == LNET_NET_ANY) {
2146                         snprintf(err_str,
2147                                  sizeof(err_str),
2148                                  "\"cannot parse net '%s'\"", nw);
2149                         rc = LUSTRE_CFG_RC_BAD_PARAM;
2150                         goto out;
2151                 }
2152         }
2153
2154         root = cYAML_create_object(NULL, NULL);
2155         if (root == NULL)
2156                 goto out;
2157
2158         net_node = cYAML_create_seq(root, "net");
2159         if (net_node == NULL)
2160                 goto out;
2161
2162         for (i = 0;; i++) {
2163                 __u32 rc_net;
2164
2165                 memset(buf, 0, buf_size);
2166
2167                 LIBCFS_IOC_INIT_V2(*ni_data, lic_cfg_hdr);
2168                 /*
2169                  * set the ioc_len to the proper value since INIT assumes
2170                  * size of data
2171                  */
2172                 ni_data->lic_cfg_hdr.ioc_len = buf_size;
2173                 ni_data->lic_idx = i;
2174
2175                 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_LOCAL_NI, ni_data);
2176                 if (rc != 0) {
2177                         l_errno = errno;
2178                         break;
2179                 }
2180
2181                 rc_net = LNET_NIDNET(ni_data->lic_nid);
2182
2183                 /* filter on provided data */
2184                 if (net != LNET_NET_ANY &&
2185                     net != rc_net)
2186                         continue;
2187
2188                 /* if we're backing up don't store lo */
2189                 if (backup && LNET_NETTYP(rc_net) == LOLND)
2190                         continue;
2191
2192                 /* default rc to -1 in case we hit the goto */
2193                 rc = -1;
2194                 exist = true;
2195
2196                 stats = (struct lnet_ioctl_element_stats *)ni_data->lic_bulk;
2197                 lnd = (struct lnet_ioctl_config_lnd_tunables *)
2198                         (ni_data->lic_bulk + sizeof(*stats));
2199
2200                 if (rc_net != prev_net) {
2201                         prev_net = rc_net;
2202                         new_net = true;
2203                         net_num++;
2204                 }
2205
2206                 if (new_net) {
2207                         tmp = cYAML_create_string(net_node, "net type", libcfs_net2str(rc_net));
2208                         if (tmp == NULL)
2209                                 goto out;
2210
2211                         if (first_seq == NULL)
2212                                 first_seq = tmp;
2213
2214                         tmp = cYAML_create_seq(net_node, "local NI(s)");
2215                         if (tmp == NULL)
2216                                 goto out;
2217                         new_net = false;
2218                 }
2219
2220                 /* create the tree to be printed. */
2221                 item = cYAML_create_seq_item(tmp);
2222                 if (item == NULL)
2223                         goto out;
2224
2225                 if (!backup &&
2226                     cYAML_create_string(item, "nid",
2227                                         libcfs_nid2str(ni_data->lic_nid)) == NULL)
2228                         goto out;
2229
2230                 if (!backup &&
2231                     cYAML_create_string(item,
2232                                         "status",
2233                                         (ni_data->lic_status ==
2234                                           LNET_NI_STATUS_UP) ?
2235                                             "up" : "down") == NULL)
2236                         goto out;
2237
2238                 /* don't add interfaces unless there is at least one
2239                  * interface */
2240                 if (strlen(ni_data->lic_ni_intf) > 0) {
2241                         interfaces = cYAML_create_object(item, "interfaces");
2242                         if (interfaces == NULL)
2243                                 goto out;
2244
2245                         snprintf(str_buf, sizeof(str_buf), "%d", 0);
2246                         if (cYAML_create_string(interfaces, str_buf,
2247                                                 ni_data->lic_ni_intf) == NULL)
2248                                 goto out;
2249                 }
2250
2251                 if (detail) {
2252                         char *limit;
2253                         int k;
2254
2255                         if (backup)
2256                                 goto continue_without_msg_stats;
2257
2258                         statistics = cYAML_create_object(item, "statistics");
2259                         if (statistics == NULL)
2260                                 goto out;
2261
2262                         if (cYAML_create_number(statistics, "send_count",
2263                                                 stats->iel_send_count)
2264                                                         == NULL)
2265                                 goto out;
2266
2267                         if (cYAML_create_number(statistics, "recv_count",
2268                                                 stats->iel_recv_count)
2269                                                         == NULL)
2270                                 goto out;
2271
2272                         if (cYAML_create_number(statistics, "drop_count",
2273                                                 stats->iel_drop_count)
2274                                                         == NULL)
2275                                 goto out;
2276
2277                         if (detail < 4)
2278                                 goto continue_without_udsp_info;
2279
2280                         LIBCFS_IOC_INIT_V2(udsp_info, cud_hdr);
2281                         udsp_info.cud_nid = ni_data->lic_nid;
2282                         udsp_info.cud_peer = false;
2283                         rc = l_ioctl(LNET_DEV_ID,
2284                                      IOC_LIBCFS_GET_CONST_UDSP_INFO,
2285                                      &udsp_info);
2286                         if (rc != 0) {
2287                                 l_errno = errno;
2288                                 goto continue_without_udsp_info;
2289                         }
2290
2291                         rc = create_local_udsp_info(&udsp_info, item);
2292                         if (rc) {
2293                                 l_errno = errno;
2294                                 goto out;
2295                         }
2296
2297 continue_without_udsp_info:
2298                         if (detail < 2)
2299                                 goto continue_without_msg_stats;
2300
2301                         LIBCFS_IOC_INIT_V2(msg_stats, im_hdr);
2302                         msg_stats.im_hdr.ioc_len = sizeof(msg_stats);
2303                         msg_stats.im_idx = i;
2304
2305                         rc = l_ioctl(LNET_DEV_ID,
2306                                      IOC_LIBCFS_GET_LOCAL_NI_MSG_STATS,
2307                                      &msg_stats);
2308                         if (rc != 0) {
2309                                 l_errno = errno;
2310                                 goto continue_without_msg_stats;
2311                         }
2312
2313                         for (k = 0; k < 3; k++) {
2314                                 struct lnet_ioctl_comm_count *counts;
2315                                 struct cYAML *msg_statistics = NULL;
2316
2317                                 msg_statistics = cYAML_create_object(item,
2318                                                  (char *)gmsg_stat_names[k]);
2319                                 if (msg_statistics == NULL)
2320                                         goto out;
2321
2322                                 counts = get_counts(&msg_stats, k);
2323                                 if (counts == NULL)
2324                                         goto out;
2325
2326                                 if (!add_msg_stats_to_yaml_blk(msg_statistics,
2327                                                                counts))
2328                                         goto out;
2329                         }
2330
2331                         LIBCFS_IOC_INIT_V2(hstats, hlni_hdr);
2332                         hstats.hlni_nid = ni_data->lic_nid;
2333                         /* grab health stats */
2334                         rc = l_ioctl(LNET_DEV_ID,
2335                                      IOC_LIBCFS_GET_LOCAL_HSTATS,
2336                                      &hstats);
2337                         if (rc != 0) {
2338                                 l_errno = errno;
2339                                 goto continue_without_msg_stats;
2340                         }
2341                         yhstats = cYAML_create_object(item, "health stats");
2342                         if (!yhstats)
2343                                 goto out;
2344                         if (cYAML_create_number(yhstats, "fatal_error",
2345                                                 hstats.hlni_fatal_error)
2346                                                         == NULL)
2347                                 goto out;
2348                         if (cYAML_create_number(yhstats, "health value",
2349                                                 hstats.hlni_health_value)
2350                                                         == NULL)
2351                                 goto out;
2352                         if (cYAML_create_number(yhstats, "interrupts",
2353                                                 hstats.hlni_local_interrupt)
2354                                                         == NULL)
2355                                 goto out;
2356                         if (cYAML_create_number(yhstats, "dropped",
2357                                                 hstats.hlni_local_dropped)
2358                                                         == NULL)
2359                                 goto out;
2360                         if (cYAML_create_number(yhstats, "aborted",
2361                                                 hstats.hlni_local_aborted)
2362                                                         == NULL)
2363                                 goto out;
2364                         if (cYAML_create_number(yhstats, "no route",
2365                                                 hstats.hlni_local_no_route)
2366                                                         == NULL)
2367                                 goto out;
2368                         if (cYAML_create_number(yhstats, "timeouts",
2369                                                 hstats.hlni_local_timeout)
2370                                                         == NULL)
2371                                 goto out;
2372                         if (cYAML_create_number(yhstats, "error",
2373                                                 hstats.hlni_local_error)
2374                                                         == NULL)
2375                                 goto out;
2376                         if (cYAML_create_number(yhstats, "ping_count",
2377                                                 hstats.hlni_ping_count)
2378                                                         == NULL)
2379                                 goto out;
2380                         if (cYAML_create_number(yhstats, "next_ping",
2381                                                 hstats.hlni_next_ping)
2382                                                         == NULL)
2383                                 goto out;
2384
2385 continue_without_msg_stats:
2386                         tunables = cYAML_create_object(item, "tunables");
2387                         if (!tunables)
2388                                 goto out;
2389
2390                         rc = lustre_net_show_tunables(tunables, &lnd->lt_cmn);
2391                         if (rc != LUSTRE_CFG_RC_NO_ERR)
2392                                 goto out;
2393
2394                         if (rc != LUSTRE_CFG_RC_NO_MATCH) {
2395                                 tunables = cYAML_create_object(item,
2396                                                                "lnd tunables");
2397                                 if (tunables == NULL)
2398                                         goto out;
2399                         }
2400
2401                         rc = lustre_ni_show_tunables(tunables,
2402                                                      LNET_NETTYP(rc_net),
2403                                                      &lnd->lt_tun);
2404                         if (rc != LUSTRE_CFG_RC_NO_ERR &&
2405                             rc != LUSTRE_CFG_RC_NO_MATCH)
2406                                 goto out;
2407
2408                         if (!backup &&
2409                             cYAML_create_number(item, "dev cpt",
2410                                                 ni_data->lic_dev_cpt) == NULL)
2411                                 goto out;
2412
2413                         /* out put the CPTs in the format: "[x,x,x,...]" */
2414                         pos = str_buf;
2415                         limit = str_buf + str_buf_len - 3;
2416                         pos += scnprintf(pos, limit - pos, "\"[");
2417                         for (j = 0 ; ni_data->lic_ncpts >= 1 &&
2418                                 j < ni_data->lic_ncpts &&
2419                                 pos < limit; j++) {
2420                                 pos += scnprintf(pos, limit - pos,
2421                                                  "%d", ni_data->lic_cpts[j]);
2422                                 if ((j + 1) < ni_data->lic_ncpts)
2423                                         pos += scnprintf(pos, limit - pos, ",");
2424                         }
2425                         snprintf(pos, 3, "]\"");
2426
2427                         if (ni_data->lic_ncpts >= 1 &&
2428                             cYAML_create_string(item, "CPT",
2429                                                 str_buf) == NULL)
2430                                 goto out;
2431                 }
2432         }
2433
2434         /* Print out the net information only if show_rc is not provided */
2435         if (show_rc == NULL)
2436                 cYAML_print_tree(root);
2437
2438         if (l_errno != ENOENT) {
2439                 snprintf(err_str,
2440                          sizeof(err_str),
2441                          "\"cannot get networks: %s\"",
2442                          strerror(l_errno));
2443                 rc = -l_errno;
2444                 goto out;
2445         } else
2446                 rc = LUSTRE_CFG_RC_NO_ERR;
2447
2448         snprintf(err_str, sizeof(err_str), "\"success\"");
2449 out:
2450         if (show_rc == NULL || rc != LUSTRE_CFG_RC_NO_ERR || !exist) {
2451                 cYAML_free_tree(root);
2452         } else if (show_rc != NULL && *show_rc != NULL) {
2453                 struct cYAML *show_node;
2454                 /* find the net node, if one doesn't exist
2455                  * then insert one.  Otherwise add to the one there
2456                  */
2457                 show_node = cYAML_get_object_item(*show_rc, "net");
2458                 if (show_node != NULL && cYAML_is_sequence(show_node)) {
2459                         cYAML_insert_child(show_node, first_seq);
2460                         free(net_node);
2461                         free(root);
2462                 } else if (show_node == NULL) {
2463                         cYAML_insert_sibling((*show_rc)->cy_child,
2464                                                 net_node);
2465                         free(root);
2466                 } else {
2467                         cYAML_free_tree(root);
2468                 }
2469         } else {
2470                 *show_rc = root;
2471         }
2472
2473         cYAML_build_error(rc, seq_no, SHOW_CMD, "net", err_str, err_rc);
2474
2475         return rc;
2476 }
2477
2478 int lustre_lnet_enable_routing(int enable, int seq_no, struct cYAML **err_rc)
2479 {
2480         struct lnet_ioctl_config_data data;
2481         int rc = LUSTRE_CFG_RC_NO_ERR;
2482         char err_str[LNET_MAX_STR_LEN] = "\"success\"";
2483
2484         LIBCFS_IOC_INIT_V2(data, cfg_hdr);
2485         data.cfg_config_u.cfg_buffers.buf_enable = (enable) ? 1 : 0;
2486
2487         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_CONFIG_RTR, &data);
2488         if (rc != 0) {
2489                 rc = -errno;
2490                 snprintf(err_str,
2491                          sizeof(err_str),
2492                          "\"cannot %s routing %s\"",
2493                          (enable) ? "enable" : "disable", strerror(errno));
2494                 goto out;
2495         }
2496
2497 out:
2498         cYAML_build_error(rc, seq_no,
2499                          (enable) ? ADD_CMD : DEL_CMD,
2500                          "routing", err_str, err_rc);
2501
2502         return rc;
2503 }
2504
2505 int ioctl_set_value(__u32 val, int ioc, char *name,
2506                     int seq_no, struct cYAML **err_rc)
2507 {
2508         struct lnet_ioctl_set_value data;
2509         int rc = LUSTRE_CFG_RC_NO_ERR;
2510         char err_str[LNET_MAX_STR_LEN] = "\"success\"";
2511
2512         LIBCFS_IOC_INIT_V2(data, sv_hdr);
2513         data.sv_value = val;
2514
2515         rc = l_ioctl(LNET_DEV_ID, ioc , &data);
2516         if (rc != 0) {
2517                 rc = -errno;
2518                 snprintf(err_str,
2519                          sizeof(err_str),
2520                          "\"cannot configure %s to %d: %s\"", name,
2521                          val, strerror(errno));
2522         }
2523
2524         cYAML_build_error(rc, seq_no, ADD_CMD, name, err_str, err_rc);
2525
2526         return rc;
2527 }
2528
2529 int lustre_lnet_config_recov_intrv(int intrv, int seq_no, struct cYAML **err_rc)
2530 {
2531         int rc = LUSTRE_CFG_RC_NO_ERR;
2532         char err_str[LNET_MAX_STR_LEN] = "\"success\"";
2533         char val[LNET_MAX_STR_LEN];
2534
2535         snprintf(val, sizeof(val), "%d", intrv);
2536
2537         rc = write_sysfs_file(modparam_path, "lnet_recovery_interval", val,
2538                               1, strlen(val) + 1);
2539         if (rc)
2540                 snprintf(err_str, sizeof(err_str),
2541                          "\"cannot configure recovery interval: %s\"",
2542                          strerror(errno));
2543
2544         cYAML_build_error(rc, seq_no, ADD_CMD, "recovery_interval", err_str, err_rc);
2545
2546         return rc;
2547 }
2548
2549 int lustre_lnet_config_rtr_sensitivity(int sen, int seq_no, struct cYAML **err_rc)
2550 {
2551         int rc = LUSTRE_CFG_RC_NO_ERR;
2552         char err_str[LNET_MAX_STR_LEN] = "\"success\"";
2553         char val[LNET_MAX_STR_LEN];
2554
2555         snprintf(val, sizeof(val), "%d", sen);
2556
2557         rc = write_sysfs_file(modparam_path, "router_sensitivity_percentage", val,
2558                               1, strlen(val) + 1);
2559         if (rc)
2560                 snprintf(err_str, sizeof(err_str),
2561                          "\"cannot configure router health sensitivity: %s\"",
2562                          strerror(errno));
2563
2564         cYAML_build_error(rc, seq_no, ADD_CMD, "router_sensitivity", err_str, err_rc);
2565
2566         return rc;
2567 }
2568
2569 int lustre_lnet_config_hsensitivity(int sen, int seq_no, struct cYAML **err_rc)
2570 {
2571         int rc = LUSTRE_CFG_RC_NO_ERR;
2572         char err_str[LNET_MAX_STR_LEN] = "\"success\"";
2573         char val[LNET_MAX_STR_LEN];
2574
2575         snprintf(val, sizeof(val), "%d", sen);
2576
2577         rc = write_sysfs_file(modparam_path, "lnet_health_sensitivity", val,
2578                               1, strlen(val) + 1);
2579         if (rc)
2580                 snprintf(err_str, sizeof(err_str),
2581                          "\"cannot configure health sensitivity: %s\"",
2582                          strerror(errno));
2583
2584         cYAML_build_error(rc, seq_no, ADD_CMD, "health_sensitivity", err_str, err_rc);
2585
2586         return rc;
2587 }
2588
2589 int lustre_lnet_config_transaction_to(int timeout, int seq_no, struct cYAML **err_rc)
2590 {
2591         int rc = LUSTRE_CFG_RC_NO_ERR;
2592         char err_str[LNET_MAX_STR_LEN] = "\"success\"";
2593         char val[LNET_MAX_STR_LEN];
2594
2595         snprintf(val, sizeof(val), "%d", timeout);
2596
2597         rc = write_sysfs_file(modparam_path, "lnet_transaction_timeout", val,
2598                               1, strlen(val) + 1);
2599         if (rc)
2600                 snprintf(err_str, sizeof(err_str),
2601                          "\"cannot configure transaction timeout: %s\"",
2602                          strerror(errno));
2603
2604         cYAML_build_error(rc, seq_no, ADD_CMD, "transaction_timeout", err_str, err_rc);
2605
2606         return rc;
2607 }
2608
2609 int lustre_lnet_config_retry_count(int count, int seq_no, struct cYAML **err_rc)
2610 {
2611         int rc = LUSTRE_CFG_RC_NO_ERR;
2612         char err_str[LNET_MAX_STR_LEN] = "\"success\"";
2613         char val[LNET_MAX_STR_LEN];
2614
2615         snprintf(val, sizeof(val), "%d", count);
2616
2617         rc = write_sysfs_file(modparam_path, "lnet_retry_count", val,
2618                               1, strlen(val) + 1);
2619         if (rc)
2620                 snprintf(err_str, sizeof(err_str),
2621                          "\"cannot configure retry count: %s\"",
2622                          strerror(errno));
2623
2624         cYAML_build_error(rc, seq_no, ADD_CMD, "retry_count", err_str, err_rc);
2625
2626         return rc;
2627 }
2628
2629 int lustre_lnet_config_response_tracking(int val, int seq_no,
2630                                          struct cYAML **err_rc)
2631 {
2632         int rc = LUSTRE_CFG_RC_NO_ERR;
2633         char err_str[LNET_MAX_STR_LEN];
2634         char val_str[LNET_MAX_STR_LEN];
2635
2636         if (val < 0 || val > 3) {
2637                 rc = LUSTRE_CFG_RC_BAD_PARAM;
2638                 snprintf(err_str, sizeof(err_str),
2639                          "\"Valid values are: 0, 1, 2, or 3\"");
2640         } else {
2641                 snprintf(err_str, sizeof(err_str), "\"success\"");
2642
2643                 snprintf(val_str, sizeof(val_str), "%d", val);
2644
2645                 rc = write_sysfs_file(modparam_path, "lnet_response_tracking",
2646                                       val_str, 1, strlen(val_str) + 1);
2647                 if (rc)
2648                         snprintf(err_str, sizeof(err_str),
2649                                  "\"cannot configure response tracking: %s\"",
2650                                  strerror(errno));
2651         }
2652
2653         cYAML_build_error(rc, seq_no, ADD_CMD, "response_tracking", err_str,
2654                           err_rc);
2655
2656         return rc;
2657 }
2658
2659 int lustre_lnet_config_recovery_limit(int val, int seq_no,
2660                                       struct cYAML **err_rc)
2661 {
2662         int rc = LUSTRE_CFG_RC_NO_ERR;
2663         char err_str[LNET_MAX_STR_LEN];
2664         char val_str[LNET_MAX_STR_LEN];
2665
2666         if (val < 0) {
2667                 rc = LUSTRE_CFG_RC_BAD_PARAM;
2668                 snprintf(err_str, sizeof(err_str),
2669                          "\"Must be greater than or equal to 0\"");
2670         } else {
2671                 snprintf(err_str, sizeof(err_str), "\"success\"");
2672
2673                 snprintf(val_str, sizeof(val_str), "%d", val);
2674
2675                 rc = write_sysfs_file(modparam_path, "lnet_recovery_limit",
2676                                       val_str, 1, strlen(val_str) + 1);
2677                 if (rc)
2678                         snprintf(err_str, sizeof(err_str),
2679                                  "\"cannot configure recovery limit: %s\"",
2680                                  strerror(errno));
2681         }
2682
2683         cYAML_build_error(rc, seq_no, ADD_CMD, "recovery_limit", err_str,
2684                           err_rc);
2685
2686         return rc;
2687 }
2688
2689 int lustre_lnet_config_max_intf(int max, int seq_no, struct cYAML **err_rc)
2690 {
2691         int rc = LUSTRE_CFG_RC_NO_ERR;
2692         char err_str[LNET_MAX_STR_LEN] = "\"success\"";
2693         char val[LNET_MAX_STR_LEN];
2694
2695         snprintf(val, sizeof(val), "%d", max);
2696
2697         rc = write_sysfs_file(modparam_path, "lnet_interfaces_max", val,
2698                               1, strlen(val) + 1);
2699         if (rc)
2700                 snprintf(err_str, sizeof(err_str),
2701                          "\"cannot configure max interfaces: %s\"",
2702                          strerror(errno));
2703
2704         cYAML_build_error(rc, seq_no, ADD_CMD, "max_interfaces", err_str, err_rc);
2705
2706         return rc;
2707 }
2708
2709 int lustre_lnet_config_discovery(int enable, int seq_no, struct cYAML **err_rc)
2710 {
2711         int rc = LUSTRE_CFG_RC_NO_ERR;
2712         char err_str[LNET_MAX_STR_LEN] = "\"success\"";
2713         char val[LNET_MAX_STR_LEN];
2714
2715         snprintf(val, sizeof(val), "%u", (enable) ? 0 : 1);
2716
2717         rc = write_sysfs_file(modparam_path, "lnet_peer_discovery_disabled", val,
2718                               1, strlen(val) + 1);
2719         if (rc)
2720                 snprintf(err_str, sizeof(err_str),
2721                          "\"cannot configure discovery: %s\"",
2722                          strerror(errno));
2723
2724         cYAML_build_error(rc, seq_no, ADD_CMD, "discovery", err_str, err_rc);
2725
2726         return rc;
2727
2728 }
2729
2730 int lustre_lnet_config_drop_asym_route(int drop, int seq_no,
2731                                        struct cYAML **err_rc)
2732 {
2733         int rc = LUSTRE_CFG_RC_NO_ERR;
2734         char err_str[LNET_MAX_STR_LEN] = "\"success\"";
2735         char val[LNET_MAX_STR_LEN];
2736
2737         snprintf(val, sizeof(val), "%u", (drop) ? 1 : 0);
2738
2739         rc = write_sysfs_file(modparam_path, "lnet_drop_asym_route", val,
2740                               1, strlen(val) + 1);
2741         if (rc)
2742                 snprintf(err_str, sizeof(err_str),
2743                          "\"cannot configure drop asym route: %s\"",
2744                          strerror(errno));
2745
2746         cYAML_build_error(rc, seq_no, ADD_CMD, "drop_asym_route",
2747                           err_str, err_rc);
2748
2749         return rc;
2750
2751 }
2752
2753 int lustre_lnet_config_numa_range(int range, int seq_no, struct cYAML **err_rc)
2754 {
2755         return ioctl_set_value(range, IOC_LIBCFS_SET_NUMA_RANGE,
2756                                "numa_range", seq_no, err_rc);
2757 }
2758
2759 int lustre_lnet_config_buffers(int tiny, int small, int large, int seq_no,
2760                                struct cYAML **err_rc)
2761 {
2762         struct lnet_ioctl_config_data data;
2763         int rc = LUSTRE_CFG_RC_NO_ERR;
2764         char err_str[LNET_MAX_STR_LEN] = "\"success\"";
2765
2766         /* -1 indicates to ignore changes to this field */
2767         if (tiny < -1 || small < -1 || large < -1) {
2768                 snprintf(err_str,
2769                          sizeof(err_str),
2770                          "\"tiny, small and large must be >= 0\"");
2771                 rc = LUSTRE_CFG_RC_OUT_OF_RANGE_PARAM;
2772                 goto out;
2773         }
2774
2775         LIBCFS_IOC_INIT_V2(data, cfg_hdr);
2776         data.cfg_config_u.cfg_buffers.buf_tiny = tiny;
2777         data.cfg_config_u.cfg_buffers.buf_small = small;
2778         data.cfg_config_u.cfg_buffers.buf_large = large;
2779
2780         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_ADD_BUF, &data);
2781         if (rc != 0) {
2782                 rc = -errno;
2783                 snprintf(err_str,
2784                          sizeof(err_str),
2785                          "\"cannot configure buffers: %s\"", strerror(errno));
2786                 goto out;
2787         }
2788
2789 out:
2790         cYAML_build_error(rc, seq_no, ADD_CMD, "buf", err_str, err_rc);
2791
2792         return rc;
2793 }
2794
2795 int lustre_lnet_config_max_recovery_ping_interval(int interval, int seq_no,
2796                                                   struct cYAML **err_rc)
2797 {
2798         int rc = LUSTRE_CFG_RC_NO_ERR;
2799         char err_str[LNET_MAX_STR_LEN] = "\"success\"";
2800         char interval_str[LNET_MAX_STR_LEN];
2801
2802         if (interval <= 0) {
2803                 rc = LUSTRE_CFG_RC_BAD_PARAM;
2804                 snprintf(err_str, sizeof(err_str),
2805                          "\"must be strictly positive\"");
2806
2807         } else {
2808                 snprintf(interval_str, sizeof(interval_str), "%d", interval);
2809
2810                 rc = write_sysfs_file(modparam_path,
2811                                       "lnet_max_recovery_ping_interval",
2812                                       interval_str, 1,
2813                                       strlen(interval_str) + 1);
2814                 if (rc)
2815                         snprintf(err_str, sizeof(err_str),
2816                                  "\"cannot configure maximum recovery ping interval: %s\"",
2817                                  strerror(errno));
2818         }
2819
2820         cYAML_build_error(rc, seq_no, ADD_CMD, "maximum recovery ping interval",
2821                           err_str, err_rc);
2822
2823         return rc;
2824 }
2825
2826
2827 int lustre_lnet_show_routing(int seq_no, struct cYAML **show_rc,
2828                              struct cYAML **err_rc, bool backup)
2829 {
2830         struct lnet_ioctl_config_data *data;
2831         struct lnet_ioctl_pool_cfg *pool_cfg = NULL;
2832         int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
2833         int l_errno = 0;
2834         char *buf;
2835         char *pools[LNET_NRBPOOLS] = {"tiny", "small", "large"};
2836         int buf_count[LNET_NRBPOOLS] = {0};
2837         struct cYAML *root = NULL, *pools_node = NULL,
2838                      *type_node = NULL, *item = NULL, *cpt = NULL,
2839                      *first_seq = NULL, *buffers = NULL;
2840         int i, j;
2841         char err_str[LNET_MAX_STR_LEN] = "\"out of memory\"";
2842         char node_name[LNET_MAX_STR_LEN];
2843         bool exist = false;
2844
2845         buf = calloc(1, sizeof(*data) + sizeof(*pool_cfg));
2846         if (buf == NULL)
2847                 goto out;
2848
2849         data = (struct lnet_ioctl_config_data *)buf;
2850
2851         root = cYAML_create_object(NULL, NULL);
2852         if (root == NULL)
2853                 goto out;
2854
2855         if (backup)
2856                 pools_node = cYAML_create_object(root, "routing");
2857         else
2858                 pools_node = cYAML_create_seq(root, "routing");
2859         if (pools_node == NULL)
2860                 goto out;
2861
2862         for (i = 0;; i++) {
2863                 LIBCFS_IOC_INIT_V2(*data, cfg_hdr);
2864                 data->cfg_hdr.ioc_len = sizeof(struct lnet_ioctl_config_data) +
2865                                         sizeof(struct lnet_ioctl_pool_cfg);
2866                 data->cfg_count = i;
2867
2868                 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_BUF, data);
2869                 if (rc != 0) {
2870                         l_errno = errno;
2871                         break;
2872                 }
2873
2874                 exist = true;
2875
2876                 pool_cfg = (struct lnet_ioctl_pool_cfg *)data->cfg_bulk;
2877
2878                 if (backup)
2879                         goto calculate_buffers;
2880
2881                 snprintf(node_name, sizeof(node_name), "cpt[%d]", i);
2882                 item = cYAML_create_seq_item(pools_node);
2883                 if (item == NULL)
2884                         goto out;
2885
2886                 if (first_seq == NULL)
2887                         first_seq = item;
2888
2889                 cpt = cYAML_create_object(item, node_name);
2890                 if (cpt == NULL)
2891                         goto out;
2892
2893 calculate_buffers:
2894                 /* create the tree  and print */
2895                 for (j = 0; j < LNET_NRBPOOLS; j++) {
2896                         if (!backup) {
2897                                 type_node = cYAML_create_object(cpt, pools[j]);
2898                                 if (type_node == NULL)
2899                                         goto out;
2900                         }
2901                         if (!backup &&
2902                             cYAML_create_number(type_node, "npages",
2903                                                 pool_cfg->pl_pools[j].pl_npages)
2904                             == NULL)
2905                                 goto out;
2906                         if (!backup &&
2907                             cYAML_create_number(type_node, "nbuffers",
2908                                                 pool_cfg->pl_pools[j].
2909                                                   pl_nbuffers) == NULL)
2910                                 goto out;
2911                         if (!backup &&
2912                             cYAML_create_number(type_node, "credits",
2913                                                 pool_cfg->pl_pools[j].
2914                                                    pl_credits) == NULL)
2915                                 goto out;
2916                         if (!backup &&
2917                             cYAML_create_number(type_node, "mincredits",
2918                                                 pool_cfg->pl_pools[j].
2919                                                    pl_mincredits) == NULL)
2920                                 goto out;
2921                         /* keep track of the total count for each of the
2922                          * tiny, small and large buffers */
2923                         buf_count[j] += pool_cfg->pl_pools[j].pl_nbuffers;
2924                 }
2925         }
2926
2927         if (pool_cfg != NULL) {
2928                 if (backup) {
2929                         if (cYAML_create_number(pools_node, "enable",
2930                                                 pool_cfg->pl_routing) ==
2931                         NULL)
2932                                 goto out;
2933
2934                         goto add_buffer_section;
2935                 }
2936
2937                 item = cYAML_create_seq_item(pools_node);
2938                 if (item == NULL)
2939                         goto out;
2940
2941                 if (cYAML_create_number(item, "enable", pool_cfg->pl_routing) ==
2942                     NULL)
2943                         goto out;
2944         }
2945
2946 add_buffer_section:
2947         /* create a buffers entry in the show. This is necessary so that
2948          * if the YAML output is used to configure a node, the buffer
2949          * configuration takes hold */
2950         buffers = cYAML_create_object(root, "buffers");
2951         if (buffers == NULL)
2952                 goto out;
2953
2954         for (i = 0; i < LNET_NRBPOOLS; i++) {
2955                 if (cYAML_create_number(buffers, pools[i], buf_count[i]) == NULL)
2956                         goto out;
2957         }
2958
2959         if (show_rc == NULL)
2960                 cYAML_print_tree(root);
2961
2962         if (l_errno != ENOENT) {
2963                 snprintf(err_str,
2964                          sizeof(err_str),
2965                          "\"cannot get routing information: %s\"",
2966                          strerror(l_errno));
2967                 rc = -l_errno;
2968                 goto out;
2969         } else
2970                 rc = LUSTRE_CFG_RC_NO_ERR;
2971
2972         snprintf(err_str, sizeof(err_str), "\"success\"");
2973         rc = LUSTRE_CFG_RC_NO_ERR;
2974
2975 out:
2976         free(buf);
2977         if (show_rc == NULL || rc != LUSTRE_CFG_RC_NO_ERR || !exist) {
2978                 cYAML_free_tree(root);
2979         } else if (show_rc != NULL && *show_rc != NULL) {
2980                 struct cYAML *routing_node;
2981                 /* there should exist only one routing block and one
2982                  * buffers block. If there already exists a previous one
2983                  * then don't add another */
2984                 routing_node = cYAML_get_object_item(*show_rc, "routing");
2985                 if (routing_node == NULL) {
2986                         cYAML_insert_sibling((*show_rc)->cy_child,
2987                                                 root->cy_child);
2988                         free(root);
2989                 } else {
2990                         cYAML_free_tree(root);
2991                 }
2992         } else {
2993                 *show_rc = root;
2994         }
2995
2996         cYAML_build_error(rc, seq_no, SHOW_CMD, "routing", err_str, err_rc);
2997
2998         return rc;
2999 }
3000
3001 int lustre_lnet_show_peer(char *knid, int detail, int seq_no,
3002                           struct cYAML **show_rc, struct cYAML **err_rc,
3003                           bool backup)
3004 {
3005         /*
3006          * TODO: This function is changing in a future patch to accommodate
3007          * PEER_LIST and proper filtering on any nid of the peer
3008          */
3009         struct lnet_ioctl_peer_cfg peer_info;
3010         struct lnet_peer_ni_credit_info *lpni_cri;
3011         struct lnet_ioctl_element_stats *lpni_stats;
3012         struct lnet_ioctl_element_msg_stats *msg_stats;
3013         struct lnet_ioctl_peer_ni_hstats *hstats;
3014         struct lnet_ioctl_construct_udsp_info udsp_info;
3015         lnet_nid_t *nidp;
3016         int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
3017         int i, j, k;
3018         int l_errno = 0;
3019         __u32 count;
3020         __u32 size;
3021         struct cYAML *root = NULL, *peer = NULL, *peer_ni = NULL,
3022                      *first_seq = NULL, *peer_root = NULL, *tmp = NULL,
3023                      *msg_statistics = NULL, *statistics = NULL,
3024                      *yhstats;
3025         char err_str[LNET_MAX_STR_LEN] = "\"out of memory\"";
3026         struct lnet_process_id *list = NULL;
3027         void *data = NULL;
3028         void *lpni_data;
3029         bool exist = false;
3030
3031         /* create struct cYAML root object */
3032         root = cYAML_create_object(NULL, NULL);
3033         if (root == NULL)
3034                 goto out;
3035
3036         peer_root = cYAML_create_seq(root, "peer");
3037         if (peer_root == NULL)
3038                 goto out;
3039
3040         count = 1000;
3041         size = count * sizeof(struct lnet_process_id);
3042         list = malloc(size);
3043         if (list == NULL) {
3044                 l_errno = ENOMEM;
3045                 goto out;
3046         }
3047         if (knid != NULL) {
3048                 list[0].nid = libcfs_str2nid(knid);
3049                 count = 1;
3050         } else {
3051                 for (;;) {
3052                         memset(&peer_info, 0, sizeof(peer_info));
3053                         LIBCFS_IOC_INIT_V2(peer_info, prcfg_hdr);
3054                         peer_info.prcfg_hdr.ioc_len = sizeof(peer_info);
3055                         peer_info.prcfg_size = size;
3056                         peer_info.prcfg_bulk = list;
3057
3058                         l_errno = 0;
3059                         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_PEER_LIST,
3060                                      &peer_info);
3061                         count = peer_info.prcfg_count;
3062                         if (rc == 0)
3063                                 break;
3064                         l_errno = errno;
3065                         if (l_errno != E2BIG) {
3066                                 snprintf(err_str,
3067                                         sizeof(err_str),
3068                                         "\"cannot get peer list: %s\"",
3069                                         strerror(l_errno));
3070                                 rc = -l_errno;
3071                                 goto out;
3072                         }
3073                         free(list);
3074                         size = peer_info.prcfg_size;
3075                         list = malloc(size);
3076                         if (list == NULL) {
3077                                 l_errno = ENOMEM;
3078                                 goto out;
3079                         }
3080                 }
3081         }
3082
3083         size = 4096;
3084         data = malloc(size);
3085         if (data == NULL) {
3086                 l_errno = ENOMEM;
3087                 goto out;
3088         }
3089
3090         for (i = 0; i < count; i++) {
3091                 for (;;) {
3092                         memset(&peer_info, 0, sizeof(peer_info));
3093                         LIBCFS_IOC_INIT_V2(peer_info, prcfg_hdr);
3094                         peer_info.prcfg_hdr.ioc_len = sizeof(peer_info);
3095                         peer_info.prcfg_prim_nid = list[i].nid;
3096                         peer_info.prcfg_size = size;
3097                         peer_info.prcfg_bulk = data;
3098
3099                         l_errno = 0;
3100                         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_PEER_NI,
3101                                      &peer_info);
3102                         if (rc == 0)
3103                                 break;
3104                         l_errno = errno;
3105                         if (l_errno != E2BIG) {
3106                                 snprintf(err_str,
3107                                         sizeof(err_str),
3108                                         "\"cannot get peer information: %s\"",
3109                                         strerror(l_errno));
3110                                 rc = -l_errno;
3111                                 goto out;
3112                         }
3113                         free(data);
3114                         size = peer_info.prcfg_size;
3115                         data = malloc(size);
3116                         if (data == NULL) {
3117                                 l_errno = ENOMEM;
3118                                 goto out;
3119                         }
3120                 }
3121                 exist = true;
3122
3123                 peer = cYAML_create_seq_item(peer_root);
3124                 if (peer == NULL)
3125                         goto out;
3126
3127                 if (first_seq == NULL)
3128                         first_seq = peer;
3129
3130                 lnet_nid_t pnid = peer_info.prcfg_prim_nid;
3131                 if (cYAML_create_string(peer, "primary nid",
3132                                         libcfs_nid2str(pnid))
3133                     == NULL)
3134                         goto out;
3135                 if (cYAML_create_string(peer, "Multi-Rail",
3136                                         peer_info.prcfg_mr ? "True" : "False")
3137                     == NULL)
3138                         goto out;
3139                 /*
3140                  * print out the state of the peer only if details are
3141                  * requested
3142                  */
3143                 if (detail >= 3) {
3144                         if (!backup &&
3145                             cYAML_create_number(peer, "peer state",
3146                                                 peer_info.prcfg_state)
3147                                 == NULL)
3148                                 goto out;
3149                 }
3150
3151                 tmp = cYAML_create_seq(peer, "peer ni");
3152                 if (tmp == NULL)
3153                         goto out;
3154
3155                 lpni_data = data;
3156                 for (j = 0; j < peer_info.prcfg_count; j++) {
3157                         nidp = lpni_data;
3158                         lpni_cri = (void*)nidp + sizeof(nidp);
3159                         lpni_stats = (void *)lpni_cri + sizeof(*lpni_cri);
3160                         msg_stats = (void *)lpni_stats + sizeof(*lpni_stats);
3161                         hstats = (void *)msg_stats + sizeof(*msg_stats);
3162                         lpni_data = (void *)hstats + sizeof(*hstats);
3163
3164                         peer_ni = cYAML_create_seq_item(tmp);
3165                         if (peer_ni == NULL)
3166                                 goto out;
3167
3168                         if (cYAML_create_string(peer_ni, "nid",
3169                                                 libcfs_nid2str(*nidp))
3170                             == NULL)
3171                                 goto out;
3172
3173                         if (backup)
3174                                 continue;
3175
3176                         if (detail < 4)
3177                                 goto continue_without_udsp_info;
3178
3179                         LIBCFS_IOC_INIT_V2(udsp_info, cud_hdr);
3180                         udsp_info.cud_nid = *nidp;
3181                         udsp_info.cud_peer = true;
3182                         rc = l_ioctl(LNET_DEV_ID,
3183                                         IOC_LIBCFS_GET_CONST_UDSP_INFO,
3184                                         &udsp_info);
3185                         if (rc != 0) {
3186                                 l_errno = errno;
3187                                 goto continue_without_udsp_info;
3188                         }
3189
3190                         rc = create_remote_udsp_info(&udsp_info, peer_ni);
3191                         if (rc) {
3192                                 l_errno = errno;
3193                                 goto out;
3194                         }
3195
3196 continue_without_udsp_info:
3197                         if (cYAML_create_string(peer_ni, "state",
3198                                                 lpni_cri->cr_aliveness)
3199                             == NULL)
3200                                 goto out;
3201
3202                         if (!detail)
3203                                 continue;
3204
3205                         if (cYAML_create_number(peer_ni, "max_ni_tx_credits",
3206                                                 lpni_cri->cr_ni_peer_tx_credits)
3207                             == NULL)
3208                                 goto out;
3209
3210                         if (cYAML_create_number(peer_ni, "available_tx_credits",
3211                                                 lpni_cri->cr_peer_tx_credits)
3212                             == NULL)
3213                                 goto out;
3214
3215                         if (cYAML_create_number(peer_ni, "min_tx_credits",
3216                                                 lpni_cri->cr_peer_min_tx_credits)
3217                             == NULL)
3218                                 goto out;
3219
3220                         if (cYAML_create_number(peer_ni, "tx_q_num_of_buf",
3221                                                 lpni_cri->cr_peer_tx_qnob)
3222                             == NULL)
3223                                 goto out;
3224
3225                         if (cYAML_create_number(peer_ni, "available_rtr_credits",
3226                                                 lpni_cri->cr_peer_rtr_credits)
3227                             == NULL)
3228                                 goto out;
3229
3230                         if (cYAML_create_number(peer_ni, "min_rtr_credits",
3231                                                 lpni_cri->cr_peer_min_rtr_credits)
3232                             == NULL)
3233                                 goto out;
3234
3235                         if (cYAML_create_number(peer_ni, "refcount",
3236                                                 lpni_cri->cr_refcount) == NULL)
3237                                 goto out;
3238
3239                         statistics = cYAML_create_object(peer_ni, "statistics");
3240                         if (statistics == NULL)
3241                                 goto out;
3242
3243                         if (cYAML_create_number(statistics, "send_count",
3244                                                 lpni_stats->iel_send_count)
3245                             == NULL)
3246                                 goto out;
3247
3248                         if (cYAML_create_number(statistics, "recv_count",
3249                                                 lpni_stats->iel_recv_count)
3250                             == NULL)
3251                                 goto out;
3252
3253                         if (cYAML_create_number(statistics, "drop_count",
3254                                                 lpni_stats->iel_drop_count)
3255                             == NULL)
3256                                 goto out;
3257
3258                         if (detail < 2)
3259                                 continue;
3260
3261                         for (k = 0; k < 3; k++) {
3262                                 struct lnet_ioctl_comm_count *counts;
3263
3264                                 msg_statistics = cYAML_create_object(peer_ni,
3265                                                  (char *) gmsg_stat_names[k]);
3266                                 if (msg_statistics == NULL)
3267                                         goto out;
3268
3269                                 counts = get_counts(msg_stats, k);
3270                                 if (counts == NULL)
3271                                         goto out;
3272
3273                                 if (!add_msg_stats_to_yaml_blk(msg_statistics,
3274                                                                counts))
3275                                         goto out;
3276                         }
3277
3278                         yhstats = cYAML_create_object(peer_ni, "health stats");
3279                         if (!yhstats)
3280                                 goto out;
3281                         if (cYAML_create_number(yhstats, "health value",
3282                                                 hstats->hlpni_health_value)
3283                                                         == NULL)
3284                                 goto out;
3285                         if (cYAML_create_number(yhstats, "dropped",
3286                                                 hstats->hlpni_remote_dropped)
3287                                                         == NULL)
3288                                 goto out;
3289                         if (cYAML_create_number(yhstats, "timeout",
3290                                                 hstats->hlpni_remote_timeout)
3291                                                         == NULL)
3292                                 goto out;
3293                         if (cYAML_create_number(yhstats, "error",
3294                                                 hstats->hlpni_remote_error)
3295                                                         == NULL)
3296                                 goto out;
3297                         if (cYAML_create_number(yhstats, "network timeout",
3298                                                 hstats->hlpni_network_timeout)
3299                                                         == NULL)
3300                                 goto out;
3301                         if (cYAML_create_number(yhstats, "ping_count",
3302                                                 hstats->hlpni_ping_count)
3303                                                         == NULL)
3304                                 goto out;
3305
3306                         if (cYAML_create_number(yhstats, "next_ping",
3307                                                 hstats->hlpni_next_ping)
3308                                                         == NULL)
3309                                 goto out;
3310
3311                 }
3312         }
3313
3314         /* print output iff show_rc is not provided */
3315         if (show_rc == NULL)
3316                 cYAML_print_tree(root);
3317
3318         snprintf(err_str, sizeof(err_str), "\"success\"");
3319         rc = LUSTRE_CFG_RC_NO_ERR;
3320
3321 out:
3322         free(list);
3323         free(data);
3324         if (show_rc == NULL || rc != LUSTRE_CFG_RC_NO_ERR || !exist) {
3325                 cYAML_free_tree(root);
3326         } else if (show_rc != NULL && *show_rc != NULL) {
3327                 struct cYAML *show_node;
3328                 /* find the peer node, if one doesn't exist then
3329                  * insert one.  Otherwise add to the one there
3330                  */
3331                 show_node = cYAML_get_object_item(*show_rc,
3332                                                   "peer");
3333                 if (show_node != NULL && cYAML_is_sequence(show_node)) {
3334                         cYAML_insert_child(show_node, first_seq);
3335                         free(peer_root);
3336                         free(root);
3337                 } else if (show_node == NULL) {
3338                         cYAML_insert_sibling((*show_rc)->cy_child,
3339                                              peer_root);
3340                         free(root);
3341                 } else {
3342                         cYAML_free_tree(root);
3343                 }
3344         } else {
3345                 *show_rc = root;
3346         }
3347
3348         cYAML_build_error(rc, seq_no, SHOW_CMD, "peer", err_str,
3349                           err_rc);
3350
3351         return rc;
3352 }
3353
3354 int lustre_lnet_list_peer(int seq_no,
3355                           struct cYAML **show_rc, struct cYAML **err_rc)
3356 {
3357         struct lnet_ioctl_peer_cfg peer_info;
3358         int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
3359         __u32 count;
3360         __u32 size;
3361         int i = 0;
3362         int l_errno = 0;
3363         struct cYAML *root = NULL, *list_root = NULL, *first_seq = NULL;
3364         char err_str[LNET_MAX_STR_LEN] = "\"out of memory\"";
3365         struct lnet_process_id *list = NULL;
3366
3367         memset(&peer_info, 0, sizeof(peer_info));
3368
3369         /* create struct cYAML root object */
3370         root = cYAML_create_object(NULL, NULL);
3371         if (root == NULL)
3372                 goto out;
3373
3374         list_root = cYAML_create_seq(root, "peer list");
3375         if (list_root == NULL)
3376                 goto out;
3377
3378         count = 1000;
3379         size = count * sizeof(struct lnet_process_id);
3380         list = malloc(size);
3381         if (list == NULL) {
3382                 l_errno = ENOMEM;
3383                 goto out;
3384         }
3385         for (;;) {
3386                 LIBCFS_IOC_INIT_V2(peer_info, prcfg_hdr);
3387                 peer_info.prcfg_hdr.ioc_len = sizeof(peer_info);
3388                 peer_info.prcfg_size = size;
3389                 peer_info.prcfg_bulk = list;
3390
3391                 l_errno = 0;
3392                 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_PEER_LIST, &peer_info);
3393                 count = peer_info.prcfg_count;
3394                 if (rc == 0)
3395                         break;
3396                 l_errno = errno;
3397                 if (l_errno != E2BIG) {
3398                         snprintf(err_str,
3399                                 sizeof(err_str),
3400                                 "\"cannot get peer list: %s\"",
3401                                 strerror(l_errno));
3402                         rc = -l_errno;
3403                         goto out;
3404                 }
3405                 free(list);
3406                 size = peer_info.prcfg_size;
3407                 list = malloc(size);
3408                 if (list == NULL) {
3409                         l_errno = ENOMEM;
3410                         goto out;
3411                 }
3412         }
3413
3414         /* count is now the actual number of ids in the list. */
3415         for (i = 0; i < count; i++) {
3416                 if (cYAML_create_string(list_root, "nid",
3417                                         libcfs_nid2str(list[i].nid))
3418                     == NULL)
3419                         goto out;
3420         }
3421
3422         /* print output iff show_rc is not provided */
3423         if (show_rc == NULL)
3424                 cYAML_print_tree(root);
3425
3426         snprintf(err_str, sizeof(err_str), "\"success\"");
3427         rc = LUSTRE_CFG_RC_NO_ERR;
3428
3429 out:
3430         if (list != NULL)
3431                 free(list);
3432         if (show_rc == NULL || rc != LUSTRE_CFG_RC_NO_ERR) {
3433                 cYAML_free_tree(root);
3434         } else if (show_rc != NULL && *show_rc != NULL) {
3435                 struct cYAML *show_node;
3436                 /* find the peer node, if one doesn't exist then
3437                  * insert one.  Otherwise add to the one there
3438                  */
3439                 show_node = cYAML_get_object_item(*show_rc,
3440                                                   "peer");
3441                 if (show_node != NULL && cYAML_is_sequence(show_node)) {
3442                         cYAML_insert_child(show_node, first_seq);
3443                         free(list_root);
3444                         free(root);
3445                 } else if (show_node == NULL) {
3446                         cYAML_insert_sibling((*show_rc)->cy_child,
3447                                              list_root);
3448                         free(root);
3449                 } else {
3450                         cYAML_free_tree(root);
3451                 }
3452         } else {
3453                 *show_rc = root;
3454         }
3455
3456         cYAML_build_error(rc, seq_no, SHOW_CMD, "peer", err_str,
3457                           err_rc);
3458
3459         return rc;
3460 }
3461
3462 static void add_to_global(struct cYAML *show_rc, struct cYAML *node,
3463                           struct cYAML *root)
3464 {
3465         struct cYAML *show_node;
3466
3467         show_node = cYAML_get_object_item(show_rc, "global");
3468         if (show_node != NULL)
3469                 cYAML_insert_sibling(show_node->cy_child,
3470                                      node->cy_child);
3471         else
3472                 cYAML_insert_sibling(show_rc->cy_child,
3473                                      node);
3474         free(root);
3475 }
3476
3477 static int build_global_yaml_entry(char *err_str, int err_len, int seq_no,
3478                                    char *name, __u64 value,
3479                                    struct cYAML **show_rc,
3480                                    struct cYAML **err_rc, int err)
3481 {
3482         int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
3483         struct cYAML *root = NULL, *global = NULL;
3484
3485         if (err) {
3486                 rc = err;
3487                 goto out;
3488         }
3489
3490         root = cYAML_create_object(NULL, NULL);
3491         if (root == NULL)
3492                 goto out;
3493
3494         global = cYAML_create_object(root, "global");
3495         if (global == NULL)
3496                 goto out;
3497
3498         if (cYAML_create_number(global, name,
3499                                 value) == NULL)
3500                 goto out;
3501
3502         if (show_rc == NULL)
3503                 cYAML_print_tree(root);
3504
3505         snprintf(err_str, err_len, "\"success\"");
3506
3507         rc = LUSTRE_CFG_RC_NO_ERR;
3508
3509 out:
3510         if (show_rc == NULL || rc != LUSTRE_CFG_RC_NO_ERR) {
3511                 cYAML_free_tree(root);
3512         } else if (show_rc != NULL && *show_rc != NULL) {
3513                 add_to_global(*show_rc, global, root);
3514         } else {
3515                 *show_rc = root;
3516         }
3517
3518         cYAML_build_error(rc, seq_no, SHOW_CMD, "global", err_str, err_rc);
3519
3520         return rc;
3521 }
3522
3523 static int ioctl_show_global_values(int ioc, int seq_no, char *name,
3524                                     struct cYAML **show_rc,
3525                                     struct cYAML **err_rc)
3526 {
3527         struct lnet_ioctl_set_value data;
3528         int rc;
3529         int l_errno = 0;
3530         char err_str[LNET_MAX_STR_LEN] = "\"out of memory\"";
3531
3532         LIBCFS_IOC_INIT_V2(data, sv_hdr);
3533
3534         rc = l_ioctl(LNET_DEV_ID, ioc, &data);
3535         if (rc != 0) {
3536                 l_errno = -errno;
3537                 snprintf(err_str,
3538                          sizeof(err_str),
3539                          "\"cannot get %s: %s\"",
3540                          name, strerror(l_errno));
3541         }
3542
3543         return build_global_yaml_entry(err_str, sizeof(err_str), seq_no, name,
3544                                        data.sv_value, show_rc, err_rc, l_errno);
3545 }
3546
3547 int lustre_lnet_show_recov_intrv(int seq_no, struct cYAML **show_rc,
3548                                  struct cYAML **err_rc)
3549 {
3550         int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
3551         char val[LNET_MAX_STR_LEN];
3552         int intrv = -1, l_errno = 0;
3553         char err_str[LNET_MAX_STR_LEN] = "\"out of memory\"";
3554
3555         rc = read_sysfs_file(modparam_path, "lnet_recovery_interval", val,
3556                              1, sizeof(val));
3557         if (rc) {
3558                 l_errno = -errno;
3559                 snprintf(err_str, sizeof(err_str),
3560                          "\"cannot get recovery interval: %d\"", rc);
3561         } else {
3562                 intrv = atoi(val);
3563         }
3564
3565         return build_global_yaml_entry(err_str, sizeof(err_str), seq_no,
3566                                        "recovery_interval", intrv, show_rc,
3567                                        err_rc, l_errno);
3568 }
3569
3570 int lustre_lnet_show_hsensitivity(int seq_no, struct cYAML **show_rc,
3571                                   struct cYAML **err_rc)
3572 {
3573         int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
3574         char val[LNET_MAX_STR_LEN];
3575         int sen = -1, l_errno = 0;
3576         char err_str[LNET_MAX_STR_LEN] = "\"out of memory\"";
3577
3578         rc = read_sysfs_file(modparam_path, "lnet_health_sensitivity", val,
3579                              1, sizeof(val));
3580         if (rc) {
3581                 l_errno = -errno;
3582                 snprintf(err_str, sizeof(err_str),
3583                          "\"cannot get health sensitivity: %d\"", rc);
3584         } else {
3585                 sen = atoi(val);
3586         }
3587
3588         return build_global_yaml_entry(err_str, sizeof(err_str), seq_no,
3589                                        "health_sensitivity", sen, show_rc,
3590                                        err_rc, l_errno);
3591 }
3592
3593 int lustre_lnet_show_rtr_sensitivity(int seq_no, struct cYAML **show_rc,
3594                                      struct cYAML **err_rc)
3595 {
3596         int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
3597         char val[LNET_MAX_STR_LEN];
3598         int sen = -1, l_errno = 0;
3599         char err_str[LNET_MAX_STR_LEN] = "\"out of memory\"";
3600
3601         rc = read_sysfs_file(modparam_path, "router_sensitivity_percentage", val,
3602                              1, sizeof(val));
3603         if (rc) {
3604                 l_errno = -errno;
3605                 snprintf(err_str, sizeof(err_str),
3606                          "\"cannot get router sensitivity percentage: %d\"", rc);
3607         } else {
3608                 sen = atoi(val);
3609         }
3610
3611         return build_global_yaml_entry(err_str, sizeof(err_str), seq_no,
3612                                        "router_sensitivity", sen, show_rc,
3613                                        err_rc, l_errno);
3614 }
3615
3616 int lustre_lnet_show_lnd_timeout(int seq_no, struct cYAML **show_rc,
3617                                  struct cYAML **err_rc)
3618 {
3619         char val[LNET_MAX_STR_LEN];
3620         char err_str[LNET_MAX_STR_LEN] = "\"out of memory\"";
3621         int lnd_to = -1;
3622         int l_errno = 0;
3623         int rc;
3624         int fd;
3625         glob_t path;
3626
3627         rc = cfs_get_param_paths(&path, "lnet_lnd_timeout");
3628         if (rc < 0) {
3629                 l_errno = -errno;
3630                 snprintf(err_str, sizeof(err_str),
3631                          "\"cannot get LND timeout: %d\"", rc);
3632                 return build_global_yaml_entry(err_str, sizeof(err_str), seq_no,
3633                                                "lnd_timeout", lnd_to, show_rc,
3634                                                err_rc, l_errno);
3635         }
3636
3637         fd = open(path.gl_pathv[0], O_RDONLY);
3638         if (fd < 0) {
3639                 l_errno = -errno;
3640                 snprintf(err_str, sizeof(err_str),
3641                          "\"error opening %s\"", path.gl_pathv[0]);
3642                 goto failed;
3643         }
3644
3645         rc = read(fd, val, sizeof(val));
3646         if (rc < 0)
3647                 l_errno = -errno;
3648
3649         close(fd);
3650
3651         if (rc < 0) {
3652                 snprintf(err_str, sizeof(err_str),
3653                          "\"error reading %s\"", path.gl_pathv[0]);
3654                 goto failed;
3655         }
3656
3657         lnd_to = atoi(val);
3658
3659 failed:
3660         cfs_free_param_data(&path);
3661
3662         return build_global_yaml_entry(err_str, sizeof(err_str), seq_no,
3663                                        "lnd_timeout", lnd_to, show_rc,
3664                                        err_rc, l_errno);
3665 }
3666
3667 int lustre_lnet_show_transaction_to(int seq_no, struct cYAML **show_rc,
3668                                     struct cYAML **err_rc)
3669 {
3670         int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
3671         char val[LNET_MAX_STR_LEN];
3672         int tto = -1, l_errno = 0;
3673         char err_str[LNET_MAX_STR_LEN] = "\"out of memory\"";
3674
3675         rc = read_sysfs_file(modparam_path, "lnet_transaction_timeout", val,
3676                              1, sizeof(val));
3677         if (rc) {
3678                 l_errno = -errno;
3679                 snprintf(err_str, sizeof(err_str),
3680                          "\"cannot get transaction timeout: %d\"", rc);
3681         } else {
3682                 tto = atoi(val);
3683         }
3684
3685         return build_global_yaml_entry(err_str, sizeof(err_str), seq_no,
3686                                        "transaction_timeout", tto, show_rc,
3687                                        err_rc, l_errno);
3688 }
3689
3690 int lustre_lnet_show_retry_count(int seq_no, struct cYAML **show_rc,
3691                                  struct cYAML **err_rc)
3692 {
3693         int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
3694         char val[LNET_MAX_STR_LEN];
3695         int retry_count = -1, l_errno = 0;
3696         char err_str[LNET_MAX_STR_LEN] = "\"out of memory\"";
3697
3698         rc = read_sysfs_file(modparam_path, "lnet_retry_count", val,
3699                              1, sizeof(val));
3700         if (rc) {
3701                 l_errno = -errno;
3702                 snprintf(err_str, sizeof(err_str),
3703                          "\"cannot get retry count: %d\"", rc);
3704         } else {
3705                 retry_count = atoi(val);
3706         }
3707
3708         return build_global_yaml_entry(err_str, sizeof(err_str), seq_no,
3709                                        "retry_count", retry_count, show_rc,
3710                                        err_rc, l_errno);
3711 }
3712
3713 int lustre_lnet_calc_service_id(__u64 *service_id)
3714 {
3715         int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
3716         char val[LNET_MAX_STR_LEN];
3717         int service_port = -1, l_errno = 0;
3718
3719         rc = read_sysfs_file(o2ib_modparam_path, "service", val,
3720                              1, sizeof(val));
3721         if (rc) {
3722                 l_errno = errno;
3723                 fprintf(stderr, "error:\n    msg: \"cannot get service port: %s (%d)\"\n",
3724                         strerror(l_errno), -l_errno);
3725                 return rc;
3726         } else {
3727                 service_port = atoi(val);
3728         }
3729
3730         *service_id = htobe64(((__u64)RDMA_PS_TCP << 16) + service_port);
3731
3732         return LUSTRE_CFG_RC_NO_ERR;
3733 }
3734
3735 int lustre_lnet_setup_mrrouting(struct cYAML **err_rc)
3736 {
3737         char *buf;
3738         int rc = LUSTRE_CFG_RC_OUT_OF_MEM, i;
3739         int l_errno = 0;
3740         char err_str[LNET_MAX_STR_LEN] = "\"out of memory\"";
3741         struct lnet_ioctl_config_ni *ni_data;
3742         struct lnet_ioctl_config_lnd_tunables *lnd;
3743         struct lnet_ioctl_element_stats *stats;
3744         size_t buf_size = sizeof(*ni_data) + sizeof(*lnd) + sizeof(*stats);
3745         char ifstr_buf[LNET_INTERFACES_NUM*LNET_MAX_STR_LEN];
3746         char *ifstr_ptr, *tmp_ptr, *tmp_ptr2;
3747         int if_cnt = 0, prc;
3748         char syscmdbuf[LNET_MAX_STR_LEN];
3749         char cmdpath[LNET_MAX_STR_LEN];
3750         bool use_custom = false;
3751
3752         buf = calloc(1, buf_size);
3753         if (buf == NULL)
3754                 goto out;
3755
3756         ni_data = (struct lnet_ioctl_config_ni *)buf;
3757
3758         ifstr_buf[0] = 0;
3759         ifstr_ptr = ifstr_buf;
3760
3761         for (i = 0;; i++) {
3762                 __u32 rc_net;
3763
3764                 memset(buf, 0, buf_size);
3765
3766                 LIBCFS_IOC_INIT_V2(*ni_data, lic_cfg_hdr);
3767                 /* set the ioc_len to the proper value since INIT assumes
3768                  * size of data
3769                  */
3770                 ni_data->lic_cfg_hdr.ioc_len = buf_size;
3771                 ni_data->lic_idx = i;
3772
3773                 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_LOCAL_NI, ni_data);
3774                 if (rc != 0) {
3775                         l_errno = errno;
3776                         break;
3777                 }
3778
3779                 rc_net = LNET_NIDNET(ni_data->lic_nid);
3780
3781                 /* only need to setup routing for tcp */
3782                 if (LNET_NETTYP(rc_net) != SOCKLND)
3783                         continue;
3784
3785                 /* don't add interfaces unless there is at least one
3786                  * interface
3787                  */
3788                 if (strlen(ni_data->lic_ni_intf) > 0) {
3789                         if (if_cnt > 0)
3790                                 strcat(ifstr_ptr, ",");
3791                         strcat(ifstr_ptr, ni_data->lic_ni_intf);
3792                         if_cnt++;
3793                 }
3794         }
3795
3796         if (l_errno != ENOENT) {
3797                 snprintf(err_str,
3798                          sizeof(err_str),
3799                          "\"cannot get networks: %s\"",
3800                          strerror(l_errno));
3801                 rc = -l_errno;
3802                 goto out;
3803         } else {
3804                 rc = LUSTRE_CFG_RC_NO_ERR;
3805         }
3806
3807         snprintf(err_str, sizeof(err_str), "\"success\"");
3808
3809         if (if_cnt > 0) {
3810                 tmp_ptr = getenv("KSOCKLND_CONFIG");
3811                 if (tmp_ptr) {
3812                         tmp_ptr2 = strrchr(tmp_ptr, '/');
3813                         if (tmp_ptr2 && !strcmp(tmp_ptr2, "/ksocklnd-config")) {
3814                                 snprintf(cmdpath, sizeof(cmdpath), "%s",
3815                                          tmp_ptr);
3816                                 use_custom = true;
3817                         }
3818                 }
3819
3820                 if (!use_custom)
3821                         snprintf(cmdpath, sizeof(cmdpath),
3822                                  "/usr/sbin/ksocklnd-config");
3823
3824                 prc = snprintf(0, 0, "%s %s", cmdpath, ifstr_ptr);
3825
3826                 if (prc < 0) {
3827                         l_errno = errno;
3828                         snprintf(err_str,
3829                                  sizeof(err_str),
3830                                  "\"snprintf failed : %s\"",
3831                                  strerror(l_errno));
3832                         rc = -l_errno;
3833                 } else if (prc >= LNET_MAX_STR_LEN) {
3834                         snprintf(err_str, sizeof(err_str),
3835                                  "\"ksocklnd-config: argument too long\"");
3836                 } else {
3837                         prc = snprintf(syscmdbuf, sizeof(syscmdbuf), "%s %s",
3838                                        cmdpath, ifstr_ptr);
3839
3840                         if (prc < 0) {
3841                                 l_errno = errno;
3842                                 snprintf(err_str,
3843                                          sizeof(err_str),
3844                                          "\"snprintf failed : %s\"",
3845                                          strerror(l_errno));
3846                                 rc = -l_errno;
3847                                 goto out;
3848                         }
3849
3850                         rc = system(syscmdbuf);
3851                         if (rc != 0) {
3852                                 l_errno = errno;
3853                                 snprintf(err_str,
3854                                          sizeof(err_str),
3855                                          "\"failed to execute ksocklnd-config : %s\"",
3856                                          strerror(l_errno));
3857                                 rc = -l_errno;
3858                         }
3859                 }
3860         }
3861 out:
3862         if (buf)
3863                 free(buf);
3864
3865         cYAML_build_error(rc, -1, MANAGE_CMD, "setup-mrrouting", err_str,
3866                           err_rc);
3867
3868         return rc;
3869 }
3870
3871 unsigned int
3872 lnet_nid_cpt_hash(lnet_nid_t nid, long int number)
3873 {
3874         __u64 key = nid;
3875         __u64 pair_bits = 0x0001000100010001LLU;
3876         __u64 mask = pair_bits * 0xFF;
3877         __u64 pair_sum;
3878
3879         if (number == 1)
3880                 return 0;
3881
3882         pair_sum = (key & mask) + ((key >> 8) & mask);
3883         pair_sum = (pair_sum * pair_bits) >> 48;
3884
3885         return (unsigned int)(pair_sum) % number;
3886 }
3887
3888 int lustre_lnet_calc_cpt_of_nid(char *nidc, long int ncpts)
3889 {
3890         int rc = LUSTRE_CFG_RC_BAD_PARAM;
3891         lnet_nid_t nid;
3892
3893         if (!nidc) {
3894                 fprintf(stderr, "error:\n    msg: \"no NID provided\"\n");
3895                 return rc;
3896         }
3897
3898         if (ncpts < 0) {
3899                 fprintf(stderr, "error:\n    msg: \"number of CPTs not provided\"\n");
3900                 return rc;
3901         }
3902
3903         nid = libcfs_str2nid(nidc);
3904         if (nid == LNET_NID_ANY) {
3905                 fprintf(stderr, "error:\n    msg: \"bad NID provided %s\"\n",
3906                         nidc);
3907                 return rc;
3908         }
3909
3910         return (int)lnet_nid_cpt_hash(nid, ncpts);
3911 }
3912
3913 int show_recovery_queue(enum lnet_health_type type, char *name, int seq_no,
3914                         struct cYAML **show_rc, struct cYAML **err_rc)
3915 {
3916         struct lnet_ioctl_recovery_list nid_list;
3917         struct cYAML *root = NULL, *nids = NULL;
3918         int rc, i;
3919         char err_str[LNET_MAX_STR_LEN] = "failed to print recovery queue\n";
3920
3921         LIBCFS_IOC_INIT_V2(nid_list, rlst_hdr);
3922         nid_list.rlst_type = type;
3923
3924         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_RECOVERY_QUEUE, &nid_list);
3925         if (rc) {
3926                 rc = errno;
3927                 goto out;
3928         }
3929
3930         if (nid_list.rlst_num_nids == 0)
3931                 goto out;
3932
3933         root = cYAML_create_object(NULL, NULL);
3934         if (root == NULL)
3935                 goto out;
3936
3937         nids = cYAML_create_object(root, name);
3938         if (nids == NULL)
3939                 goto out;
3940
3941         rc = -EINVAL;
3942
3943         for (i = 0; i < nid_list.rlst_num_nids; i++) {
3944                 char nidenum[LNET_MAX_STR_LEN];
3945                 snprintf(nidenum, sizeof(nidenum), "nid-%d", i);
3946                 if (!cYAML_create_string(nids, nidenum,
3947                         libcfs_nid2str(nid_list.rlst_nid_array[i])))
3948                         goto out;
3949         }
3950
3951         snprintf(err_str, sizeof(err_str), "success\n");
3952
3953         rc = 0;
3954
3955 out:
3956         if (show_rc == NULL || rc != LUSTRE_CFG_RC_NO_ERR) {
3957                 cYAML_free_tree(root);
3958         } else if (show_rc != NULL && *show_rc != NULL) {
3959                 struct cYAML *show_node;
3960                 /* find the net node, if one doesn't exist
3961                  * then insert one.  Otherwise add to the one there
3962                  */
3963                 show_node = cYAML_get_object_item(*show_rc, name);
3964                 if (show_node != NULL && cYAML_is_sequence(show_node)) {
3965                         cYAML_insert_child(show_node, nids);
3966                         free(nids);
3967                         free(root);
3968                 } else if (show_node == NULL) {
3969                         cYAML_insert_sibling((*show_rc)->cy_child,
3970                                                 nids);
3971                         free(root);
3972                 } else {
3973                         cYAML_free_tree(root);
3974                 }
3975         } else {
3976                 *show_rc = root;
3977         }
3978
3979         cYAML_build_error(rc, seq_no, SHOW_CMD, name, err_str, err_rc);
3980
3981         return rc;
3982 }
3983
3984 int lustre_lnet_show_peer_debug_info(char *peer_nid, int seq_no,
3985                                      struct cYAML **err_rc)
3986 {
3987         struct libcfs_ioctl_data data;
3988         int rc;
3989         char err_str[LNET_MAX_STR_LEN] = "Error";
3990         lnet_nid_t pnid = LNET_NID_ANY;
3991
3992         if (!peer_nid) {
3993                 rc = LUSTRE_CFG_RC_BAD_PARAM;
3994                 snprintf(err_str, LNET_MAX_STR_LEN,
3995                          "--nid must be specified");
3996                 goto out;
3997         }
3998
3999         pnid = libcfs_str2nid(peer_nid);
4000         if (pnid == LNET_NID_ANY) {
4001                 rc = LUSTRE_CFG_RC_BAD_PARAM;
4002                 snprintf(err_str, LNET_MAX_STR_LEN,
4003                         "badly formatted primary NID: %s", peer_nid);
4004                 goto out;
4005         }
4006
4007         LIBCFS_IOC_INIT(data);
4008         data.ioc_net = LNET_NIDNET(pnid);
4009         data.ioc_nid = pnid;
4010
4011         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_PEER, &data);
4012
4013 out:
4014         if (rc != 0)
4015                 cYAML_build_error(rc, seq_no, "debug", "peer", err_str,
4016                                   err_rc);
4017
4018         return rc;
4019 }
4020
4021 int lustre_lnet_show_local_ni_recovq(int seq_no, struct cYAML **show_rc,
4022                                      struct cYAML **err_rc)
4023 {
4024         return show_recovery_queue(LNET_HEALTH_TYPE_LOCAL_NI, "local NI recovery",
4025                                    seq_no, show_rc, err_rc);
4026 }
4027
4028 int lustre_lnet_show_peer_ni_recovq(int seq_no, struct cYAML **show_rc,
4029                                     struct cYAML **err_rc)
4030 {
4031         return show_recovery_queue(LNET_HEALTH_TYPE_PEER_NI, "peer NI recovery",
4032                                    seq_no, show_rc, err_rc);
4033 }
4034
4035 int lustre_lnet_show_response_tracking(int seq_no, struct cYAML **show_rc,
4036                                        struct cYAML **err_rc)
4037 {
4038         int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
4039         char val[LNET_MAX_STR_LEN];
4040         int rsp_tracking = -1, l_errno = 0;
4041         char err_str[LNET_MAX_STR_LEN] = "\"out of memory\"";
4042
4043         rc = read_sysfs_file(modparam_path, "lnet_response_tracking", val,
4044                              1, sizeof(val));
4045         if (rc) {
4046                 l_errno = -errno;
4047                 snprintf(err_str, sizeof(err_str),
4048                          "\"cannot get lnet_response_tracking value: %d\"", rc);
4049         } else {
4050                 rsp_tracking = atoi(val);
4051         }
4052
4053         return build_global_yaml_entry(err_str, sizeof(err_str), seq_no,
4054                                        "response_tracking", rsp_tracking,
4055                                        show_rc, err_rc, l_errno);
4056 }
4057
4058 int lustre_lnet_show_recovery_limit(int seq_no, struct cYAML **show_rc,
4059                                     struct cYAML **err_rc)
4060 {
4061         int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
4062         char val[LNET_MAX_STR_LEN];
4063         int recov_limit = -1, l_errno = 0;
4064         char err_str[LNET_MAX_STR_LEN];
4065
4066         snprintf(err_str, sizeof(err_str), "\"out of memory\"");
4067
4068         rc = read_sysfs_file(modparam_path, "lnet_recovery_limit", val,
4069                              1, sizeof(val));
4070         if (rc) {
4071                 l_errno = -errno;
4072                 snprintf(err_str, sizeof(err_str),
4073                          "\"cannot get lnet_recovery_limit value: %d\"", rc);
4074         } else {
4075                 recov_limit = atoi(val);
4076         }
4077
4078         return build_global_yaml_entry(err_str, sizeof(err_str), seq_no,
4079                                        "recovery_limit", recov_limit,
4080                                        show_rc, err_rc, l_errno);
4081 }
4082
4083 int lustre_lnet_show_max_recovery_ping_interval(int seq_no,
4084                                                 struct cYAML **show_rc,
4085                                                 struct cYAML **err_rc)
4086 {
4087         int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
4088         char val[LNET_MAX_STR_LEN];
4089         int interval = -1, l_errno = 0;
4090         char err_str[LNET_MAX_STR_LEN];
4091
4092         snprintf(err_str, sizeof(err_str), "\"out of memory\"");
4093
4094         rc = read_sysfs_file(modparam_path, "lnet_max_recovery_ping_interval",
4095                              val, 1, sizeof(val));
4096         if (rc) {
4097                 l_errno = -errno;
4098                 snprintf(err_str, sizeof(err_str),
4099                          "\"cannot get lnet_max_recovery_ping_interval value: %d\"",
4100                          rc);
4101         } else {
4102                 interval = atoi(val);
4103         }
4104
4105         return build_global_yaml_entry(err_str, sizeof(err_str), seq_no,
4106                                        "max_recovery_ping_interval", interval,
4107                                        show_rc, err_rc, l_errno);
4108 }
4109
4110
4111 int lustre_lnet_show_max_intf(int seq_no, struct cYAML **show_rc,
4112                               struct cYAML **err_rc)
4113 {
4114         int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
4115         char val[LNET_MAX_STR_LEN];
4116         int max_intf = -1, l_errno = 0;
4117         char err_str[LNET_MAX_STR_LEN] = "\"out of memory\"";
4118
4119         rc = read_sysfs_file(modparam_path, "lnet_interfaces_max", val,
4120                              1, sizeof(val));
4121         if (rc) {
4122                 l_errno = -errno;
4123                 snprintf(err_str, sizeof(err_str),
4124                          "\"cannot get max interfaces: %d\"", rc);
4125         } else {
4126                 max_intf = atoi(val);
4127         }
4128
4129         return build_global_yaml_entry(err_str, sizeof(err_str), seq_no,
4130                                        "max_interfaces", max_intf, show_rc,
4131                                        err_rc, l_errno);
4132 }
4133
4134 int lustre_lnet_show_discovery(int seq_no, struct cYAML **show_rc,
4135                                struct cYAML **err_rc)
4136 {
4137         int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
4138         char val[LNET_MAX_STR_LEN];
4139         int discovery = -1, l_errno = 0;
4140         char err_str[LNET_MAX_STR_LEN]  = "\"out of memory\"";
4141
4142         rc = read_sysfs_file(modparam_path, "lnet_peer_discovery_disabled", val,
4143                              1, sizeof(val));
4144         if (rc) {
4145                 l_errno = -errno;
4146                 snprintf(err_str, sizeof(err_str),
4147                          "\"cannot get discovery setting: %d\"", rc);
4148         } else {
4149                 /*
4150                  * The kernel stores a discovery disabled value. User space
4151                  * shows whether discovery is enabled. So the value must be
4152                  * inverted.
4153                  */
4154                 discovery = !atoi(val);
4155         }
4156
4157         return build_global_yaml_entry(err_str, sizeof(err_str), seq_no,
4158                                        "discovery", discovery, show_rc,
4159                                        err_rc, l_errno);
4160 }
4161
4162 int lustre_lnet_show_drop_asym_route(int seq_no, struct cYAML **show_rc,
4163                                      struct cYAML **err_rc)
4164 {
4165         int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
4166         char val[LNET_MAX_STR_LEN];
4167         int drop_asym_route = -1, l_errno = 0;
4168         char err_str[LNET_MAX_STR_LEN] = "\"out of memory\"";
4169
4170         rc = read_sysfs_file(modparam_path, "lnet_drop_asym_route", val,
4171                              1, sizeof(val));
4172         if (rc) {
4173                 l_errno = -errno;
4174                 snprintf(err_str, sizeof(err_str),
4175                          "\"cannot get drop asym route setting: %d\"", rc);
4176         } else {
4177                 drop_asym_route = atoi(val);
4178         }
4179
4180         return build_global_yaml_entry(err_str, sizeof(err_str), seq_no,
4181                                        "drop_asym_route", drop_asym_route,
4182                                        show_rc, err_rc, l_errno);
4183 }
4184
4185 int lustre_lnet_show_numa_range(int seq_no, struct cYAML **show_rc,
4186                                 struct cYAML **err_rc)
4187 {
4188         return ioctl_show_global_values(IOC_LIBCFS_GET_NUMA_RANGE, seq_no,
4189                                         "numa_range", show_rc, err_rc);
4190 }
4191
4192 int lustre_lnet_show_stats(int seq_no, struct cYAML **show_rc,
4193                            struct cYAML **err_rc)
4194 {
4195         struct lnet_ioctl_lnet_stats data;
4196         struct lnet_counters *cntrs;
4197         int rc;
4198         int l_errno;
4199         char err_str[LNET_MAX_STR_LEN] = "\"out of memory\"";
4200         struct cYAML *root = NULL, *stats = NULL;
4201
4202         LIBCFS_IOC_INIT_V2(data, st_hdr);
4203
4204         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_LNET_STATS, &data);
4205         if (rc) {
4206                 l_errno = errno;
4207                 snprintf(err_str,
4208                          sizeof(err_str),
4209                          "\"cannot get lnet statistics: %s\"",
4210                          strerror(l_errno));
4211                 rc = -l_errno;
4212                 goto out;
4213         }
4214
4215         rc = LUSTRE_CFG_RC_OUT_OF_MEM;
4216
4217         cntrs = &data.st_cntrs;
4218
4219         root = cYAML_create_object(NULL, NULL);
4220         if (!root)
4221                 goto out;
4222
4223         stats = cYAML_create_object(root, "statistics");
4224         if (!stats)
4225                 goto out;
4226
4227         if (!cYAML_create_number(stats, "msgs_alloc",
4228                                  cntrs->lct_common.lcc_msgs_alloc))
4229                 goto out;
4230
4231         if (!cYAML_create_number(stats, "msgs_max",
4232                                  cntrs->lct_common.lcc_msgs_max))
4233                 goto out;
4234
4235         if (!cYAML_create_number(stats, "rst_alloc",
4236                                  cntrs->lct_health.lch_rst_alloc))
4237                 goto out;
4238
4239         if (!cYAML_create_number(stats, "errors",
4240                                  cntrs->lct_common.lcc_errors))
4241                 goto out;
4242
4243         if (!cYAML_create_number(stats, "send_count",
4244                                  cntrs->lct_common.lcc_send_count))
4245                 goto out;
4246
4247         if (!cYAML_create_number(stats, "resend_count",
4248                                  cntrs->lct_health.lch_resend_count))
4249                 goto out;
4250
4251         if (!cYAML_create_number(stats, "response_timeout_count",
4252                                  cntrs->lct_health.lch_response_timeout_count))
4253                 goto out;
4254
4255         if (!cYAML_create_number(stats, "local_interrupt_count",
4256                                  cntrs->lct_health.lch_local_interrupt_count))
4257                 goto out;
4258
4259         if (!cYAML_create_number(stats, "local_dropped_count",
4260                                  cntrs->lct_health.lch_local_dropped_count))
4261                 goto out;
4262
4263         if (!cYAML_create_number(stats, "local_aborted_count",
4264                                  cntrs->lct_health.lch_local_aborted_count))
4265                 goto out;
4266
4267         if (!cYAML_create_number(stats, "local_no_route_count",
4268                                  cntrs->lct_health.lch_local_no_route_count))
4269                 goto out;
4270
4271         if (!cYAML_create_number(stats, "local_timeout_count",
4272                                  cntrs->lct_health.lch_local_timeout_count))
4273                 goto out;
4274
4275         if (!cYAML_create_number(stats, "local_error_count",
4276                                  cntrs->lct_health.lch_local_error_count))
4277                 goto out;
4278
4279         if (!cYAML_create_number(stats, "remote_dropped_count",
4280                                  cntrs->lct_health.lch_remote_dropped_count))
4281                 goto out;
4282
4283         if (!cYAML_create_number(stats, "remote_error_count",
4284                                  cntrs->lct_health.lch_remote_error_count))
4285                 goto out;
4286
4287         if (!cYAML_create_number(stats, "remote_timeout_count",
4288                                  cntrs->lct_health.lch_remote_timeout_count))
4289                 goto out;
4290
4291         if (!cYAML_create_number(stats, "network_timeout_count",
4292                                  cntrs->lct_health.lch_network_timeout_count))
4293                 goto out;
4294
4295         if (!cYAML_create_number(stats, "recv_count",
4296                                  cntrs->lct_common.lcc_recv_count))
4297                 goto out;
4298
4299         if (!cYAML_create_number(stats, "route_count",
4300                                  cntrs->lct_common.lcc_route_count))
4301                 goto out;
4302
4303         if (!cYAML_create_number(stats, "drop_count",
4304                                  cntrs->lct_common.lcc_drop_count))
4305                 goto out;
4306
4307         if (!cYAML_create_number(stats, "send_length",
4308                                  cntrs->lct_common.lcc_send_length))
4309                 goto out;
4310
4311         if (!cYAML_create_number(stats, "recv_length",
4312                                  cntrs->lct_common.lcc_recv_length))
4313                 goto out;
4314
4315         if (!cYAML_create_number(stats, "route_length",
4316                                  cntrs->lct_common.lcc_route_length))
4317                 goto out;
4318
4319         if (!cYAML_create_number(stats, "drop_length",
4320                                  cntrs->lct_common.lcc_drop_length))
4321                 goto out;
4322
4323         if (!show_rc)
4324                 cYAML_print_tree(root);
4325
4326         snprintf(err_str, sizeof(err_str), "\"success\"");
4327         rc = LUSTRE_CFG_RC_NO_ERR;
4328 out:
4329         if (show_rc == NULL || rc != LUSTRE_CFG_RC_NO_ERR) {
4330                 cYAML_free_tree(root);
4331         } else if (show_rc != NULL && *show_rc != NULL) {
4332                 cYAML_insert_sibling((*show_rc)->cy_child,
4333                                         root->cy_child);
4334                 free(root);
4335         } else {
4336                 *show_rc = root;
4337         }
4338
4339         cYAML_build_error(rc, seq_no, SHOW_CMD, "statistics", err_str, err_rc);
4340
4341         return rc;
4342 }
4343
4344 int lustre_lnet_reset_stats(int seq_no, struct cYAML **err_rc)
4345 {
4346         struct libcfs_ioctl_data data;
4347         int rc = LUSTRE_CFG_RC_NO_ERR;
4348         int l_errno;
4349         char err_str[LNET_MAX_STR_LEN];
4350
4351         LIBCFS_IOC_INIT(data);
4352
4353         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_RESET_LNET_STATS, &data);
4354         if (rc) {
4355                 l_errno = errno;
4356                 snprintf(err_str,
4357                          sizeof(err_str),
4358                          "\"cannot reset lnet statistics: %s\"",
4359                          strerror(l_errno));
4360                 rc = -l_errno;
4361         } else {
4362                 snprintf(err_str, sizeof(err_str), "\"success\"");
4363                 rc = LUSTRE_CFG_RC_NO_ERR;
4364         }
4365
4366         cYAML_build_error(rc, seq_no, SHOW_CMD, "statistics", err_str, err_rc);
4367         return rc;
4368 }
4369
4370 typedef int (*cmd_handler_t)(struct cYAML *tree,
4371                              struct cYAML **show_rc,
4372                              struct cYAML **err_rc);
4373
4374 static int handle_yaml_config_route(struct cYAML *tree, struct cYAML **show_rc,
4375                                     struct cYAML **err_rc)
4376 {
4377         struct cYAML *net, *gw, *hop, *prio, *sen, *seq_no;
4378
4379         net = cYAML_get_object_item(tree, "net");
4380         gw = cYAML_get_object_item(tree, "gateway");
4381         hop = cYAML_get_object_item(tree, "hop");
4382         prio = cYAML_get_object_item(tree, "priority");
4383         sen = cYAML_get_object_item(tree, "health_sensitivity");
4384         seq_no = cYAML_get_object_item(tree, "seq_no");
4385
4386         return lustre_lnet_config_route((net) ? net->cy_valuestring : NULL,
4387                                         (gw) ? gw->cy_valuestring : NULL,
4388                                         (hop) ? hop->cy_valueint : -1,
4389                                         (prio) ? prio->cy_valueint : -1,
4390                                         (sen) ? sen->cy_valueint : -1,
4391                                         (seq_no) ? seq_no->cy_valueint : -1,
4392                                         err_rc);
4393 }
4394
4395 /*
4396  *    interfaces:
4397  *        0: <intf_name>['['<expr>']']
4398  *        1: <intf_name>['['<expr>']']
4399  */
4400 static int yaml_copy_intf_info(struct cYAML *intf_tree,
4401                                struct lnet_dlc_network_descr *nw_descr)
4402 {
4403         struct cYAML *child = NULL;
4404         int intf_num = 0, rc = LUSTRE_CFG_RC_NO_ERR;
4405         struct lnet_dlc_intf_descr *intf_descr, *tmp;
4406
4407         if (intf_tree == NULL || nw_descr == NULL)
4408                 return LUSTRE_CFG_RC_BAD_PARAM;
4409
4410         /* now grab all the interfaces and their cpts */
4411         child = intf_tree->cy_child;
4412         while (child != NULL) {
4413                 if (child->cy_valuestring == NULL) {
4414                         child = child->cy_next;
4415                         continue;
4416                 }
4417
4418                 if (strlen(child->cy_valuestring) >= LNET_MAX_STR_LEN)
4419                         goto failed;
4420
4421                 rc = lustre_lnet_add_intf_descr(&nw_descr->nw_intflist,
4422                                                 child->cy_valuestring,
4423                                                 strlen(child->cy_valuestring));
4424                 if (rc != LUSTRE_CFG_RC_NO_ERR)
4425                         goto failed;
4426
4427                 intf_num++;
4428                 child = child->cy_next;
4429         }
4430
4431         if (intf_num == 0)
4432                 return LUSTRE_CFG_RC_MISSING_PARAM;
4433
4434         return intf_num;
4435
4436 failed:
4437         list_for_each_entry_safe(intf_descr, tmp, &nw_descr->nw_intflist,
4438                                  intf_on_network) {
4439                 list_del(&intf_descr->intf_on_network);
4440                 free_intf_descr(intf_descr);
4441         }
4442
4443         return rc;
4444 }
4445
4446 static bool
4447 yaml_extract_cmn_tunables(struct cYAML *tree,
4448                           struct lnet_ioctl_config_lnd_cmn_tunables *tunables)
4449 {
4450         struct cYAML *tun, *item;
4451
4452         tun = cYAML_get_object_item(tree, "tunables");
4453         if (tun != NULL) {
4454                 item = cYAML_get_object_item(tun, "peer_timeout");
4455                 if (item != NULL)
4456                         tunables->lct_peer_timeout = item->cy_valueint;
4457                 else
4458                         tunables->lct_peer_timeout = -1;
4459                 item = cYAML_get_object_item(tun, "peer_credits");
4460                 if (item != NULL)
4461                         tunables->lct_peer_tx_credits = item->cy_valueint;
4462                 item = cYAML_get_object_item(tun, "peer_buffer_credits");
4463                 if (item != NULL)
4464                         tunables->lct_peer_rtr_credits = item->cy_valueint;
4465                 item = cYAML_get_object_item(tun, "credits");
4466                 if (item != NULL)
4467                         tunables->lct_max_tx_credits = item->cy_valueint;
4468
4469                 return true;
4470         }
4471
4472         return false;
4473 }
4474
4475 static bool
4476 yaml_extract_tunables(struct cYAML *tree,
4477                       struct lnet_ioctl_config_lnd_tunables *tunables,
4478                       __u32 net_type)
4479 {
4480         bool rc;
4481
4482         rc = yaml_extract_cmn_tunables(tree, &tunables->lt_cmn);
4483
4484         if (!rc)
4485                 return rc;
4486
4487         lustre_yaml_extract_lnd_tunables(tree, net_type,
4488                                          &tunables->lt_tun);
4489
4490         return rc;
4491 }
4492
4493 static void
4494 yaml_extract_cpt(struct cYAML *tree,
4495                       struct cfs_expr_list **global_cpts)
4496 {
4497         int rc;
4498         struct cYAML *smp;
4499
4500         smp = cYAML_get_object_item(tree, "CPT");
4501         if (smp != NULL) {
4502                 rc = cfs_expr_list_parse(smp->cy_valuestring,
4503                                          strlen(smp->cy_valuestring),
4504                                          0, UINT_MAX, global_cpts);
4505                 if (rc != 0)
4506                         *global_cpts = NULL;
4507         }
4508 }
4509
4510 /*
4511  * net:
4512  *    - net type: <net>[<NUM>]
4513   *      local NI(s):
4514  *        - nid: <ip>@<net>[<NUM>]
4515  *          status: up
4516  *          interfaces:
4517  *               0: <intf_name>['['<expr>']']
4518  *               1: <intf_name>['['<expr>']']
4519  *        tunables:
4520  *               peer_timeout: <NUM>
4521  *               peer_credits: <NUM>
4522  *               peer_buffer_credits: <NUM>
4523  *               credits: <NUM>
4524 *         lnd tunables:
4525  *               peercredits_hiw: <NUM>
4526  *               map_on_demand: <NUM>
4527  *               concurrent_sends: <NUM>
4528  *               fmr_pool_size: <NUM>
4529  *               fmr_flush_trigger: <NUM>
4530  *               fmr_cache: <NUM>
4531  *
4532  * At least one interface is required. If no interfaces are provided the
4533  * network interface can not be configured.
4534  */
4535 static int handle_yaml_config_ni(struct cYAML *tree, struct cYAML **show_rc,
4536                                  struct cYAML **err_rc)
4537 {
4538         struct cYAML *net, *intf, *seq_no, *ip2net = NULL, *local_nis = NULL,
4539                      *item = NULL;
4540         int num_entries = 0, rc;
4541         struct lnet_dlc_network_descr nw_descr;
4542         struct cfs_expr_list *global_cpts = NULL;
4543         struct lnet_ioctl_config_lnd_tunables tunables;
4544         bool found = false;
4545
4546         memset(&tunables, 0, sizeof(tunables));
4547
4548         INIT_LIST_HEAD(&nw_descr.network_on_rule);
4549         INIT_LIST_HEAD(&nw_descr.nw_intflist);
4550
4551         ip2net = cYAML_get_object_item(tree, "ip2net");
4552         net = cYAML_get_object_item(tree, "net type");
4553         if (net)
4554                 nw_descr.nw_id = libcfs_str2net(net->cy_valuestring);
4555         else
4556                 nw_descr.nw_id = LOLND;
4557
4558         /*
4559          * if neither net nor ip2nets are present, then we can not
4560          * configure the network.
4561          */
4562         if (!net && !ip2net)
4563                 return LUSTRE_CFG_RC_MISSING_PARAM;
4564
4565         local_nis = cYAML_get_object_item(tree, "local NI(s)");
4566         if (local_nis == NULL)
4567                 return LUSTRE_CFG_RC_MISSING_PARAM;
4568
4569         if (!cYAML_is_sequence(local_nis))
4570                 return LUSTRE_CFG_RC_BAD_PARAM;
4571
4572         while (cYAML_get_next_seq_item(local_nis, &item) != NULL) {
4573                 intf = cYAML_get_object_item(item, "interfaces");
4574                 if (intf == NULL)
4575                         continue;
4576                 num_entries = yaml_copy_intf_info(intf, &nw_descr);
4577                 if (num_entries <= 0) {
4578                         cYAML_build_error(num_entries, -1, "ni", "add",
4579                                         "bad interface list",
4580                                         err_rc);
4581                         return LUSTRE_CFG_RC_BAD_PARAM;
4582                 }
4583         }
4584
4585         found = yaml_extract_tunables(tree, &tunables,
4586                                       LNET_NETTYP(nw_descr.nw_id));
4587         yaml_extract_cpt(tree, &global_cpts);
4588         seq_no = cYAML_get_object_item(tree, "seq_no");
4589
4590         rc = lustre_lnet_config_ni(&nw_descr, global_cpts,
4591                                    (ip2net) ? ip2net->cy_valuestring : NULL,
4592                                    (found) ? &tunables : NULL,
4593                                    (seq_no) ? seq_no->cy_valueint : -1,
4594                                    err_rc);
4595
4596         if (global_cpts != NULL)
4597                 cfs_expr_list_free(global_cpts);
4598
4599         return rc;
4600 }
4601
4602 /*
4603  * ip2nets:
4604  *  - net-spec: <tcp|o2ib|gni>[NUM]
4605  *    interfaces:
4606  *        0: <intf name>['['<expr>']']
4607  *        1: <intf name>['['<expr>']']
4608  *    ip-range:
4609  *        0: <expr.expr.expr.expr>
4610  *        1: <expr.expr.expr.expr>
4611  */
4612 static int handle_yaml_config_ip2nets(struct cYAML *tree,
4613                                       struct cYAML **show_rc,
4614                                       struct cYAML **err_rc)
4615 {
4616         struct cYAML *net, *ip_range, *item = NULL, *intf = NULL,
4617                      *seq_no = NULL;
4618         struct lustre_lnet_ip2nets ip2nets;
4619         struct lustre_lnet_ip_range_descr *ip_range_descr = NULL,
4620                                           *tmp = NULL;
4621         int rc = LUSTRE_CFG_RC_NO_ERR;
4622         struct cfs_expr_list *global_cpts = NULL;
4623         struct cfs_expr_list *el, *el_tmp;
4624         struct lnet_ioctl_config_lnd_tunables tunables;
4625         struct lnet_dlc_intf_descr *intf_descr, *intf_tmp;
4626         bool found = false;
4627
4628         memset(&tunables, 0, sizeof(tunables));
4629
4630         /* initialize all lists */
4631         INIT_LIST_HEAD(&ip2nets.ip2nets_ip_ranges);
4632         INIT_LIST_HEAD(&ip2nets.ip2nets_net.network_on_rule);
4633         INIT_LIST_HEAD(&ip2nets.ip2nets_net.nw_intflist);
4634
4635         net = cYAML_get_object_item(tree, "net-spec");
4636         if (net == NULL)
4637                 return LUSTRE_CFG_RC_BAD_PARAM;
4638
4639         if (net != NULL && net->cy_valuestring == NULL)
4640                 return LUSTRE_CFG_RC_BAD_PARAM;
4641
4642         /* assign the network id */
4643         ip2nets.ip2nets_net.nw_id = libcfs_str2net(net->cy_valuestring);
4644         if (ip2nets.ip2nets_net.nw_id == LNET_NID_ANY)
4645                 return LUSTRE_CFG_RC_BAD_PARAM;
4646
4647         seq_no = cYAML_get_object_item(tree, "seq_no");
4648
4649         intf = cYAML_get_object_item(tree, "interfaces");
4650         if (intf != NULL) {
4651                 rc = yaml_copy_intf_info(intf, &ip2nets.ip2nets_net);
4652                 if (rc <= 0)
4653                         return LUSTRE_CFG_RC_BAD_PARAM;
4654         }
4655
4656         ip_range = cYAML_get_object_item(tree, "ip-range");
4657         if (ip_range != NULL) {
4658                 item = ip_range->cy_child;
4659                 while (item != NULL) {
4660                         if (item->cy_valuestring == NULL) {
4661                                 item = item->cy_next;
4662                                 continue;
4663                         }
4664
4665                         rc = lustre_lnet_add_ip_range(&ip2nets.ip2nets_ip_ranges,
4666                                                       item->cy_valuestring);
4667
4668                         if (rc != LUSTRE_CFG_RC_NO_ERR)
4669                                 goto out;
4670
4671                         item = item->cy_next;
4672                 }
4673         }
4674
4675         found = yaml_extract_tunables(tree, &tunables,
4676                                       LNET_NETTYP(ip2nets.ip2nets_net.nw_id));
4677         yaml_extract_cpt(tree, &global_cpts);
4678
4679         rc = lustre_lnet_config_ip2nets(&ip2nets,
4680                         (found) ? &tunables : NULL,
4681                         global_cpts,
4682                         (seq_no) ? seq_no->cy_valueint : -1,
4683                         err_rc);
4684
4685         if (global_cpts != NULL)
4686                 cfs_expr_list_free(global_cpts);
4687
4688         /*
4689          * don't stop because there was no match. Continue processing the
4690          * rest of the rules. If non-match then nothing is configured
4691          */
4692         if (rc == LUSTRE_CFG_RC_NO_MATCH)
4693                 rc = LUSTRE_CFG_RC_NO_ERR;
4694 out:
4695         list_for_each_entry_safe(intf_descr, intf_tmp,
4696                                  &ip2nets.ip2nets_net.nw_intflist,
4697                                  intf_on_network) {
4698                 list_del(&intf_descr->intf_on_network);
4699                 free_intf_descr(intf_descr);
4700         }
4701
4702         list_for_each_entry_safe(ip_range_descr, tmp,
4703                                  &ip2nets.ip2nets_ip_ranges,
4704                                  ipr_entry) {
4705                 list_del(&ip_range_descr->ipr_entry);
4706                 list_for_each_entry_safe(el, el_tmp, &ip_range_descr->ipr_expr,
4707                                          el_link) {
4708                         list_del(&el->el_link);
4709                         cfs_expr_list_free(el);
4710                 }
4711                 free(ip_range_descr);
4712         }
4713
4714         return rc;
4715 }
4716
4717 static int handle_yaml_del_ni(struct cYAML *tree, struct cYAML **show_rc,
4718                               struct cYAML **err_rc)
4719 {
4720         struct cYAML *net = NULL, *intf = NULL, *seq_no = NULL, *item = NULL,
4721                      *local_nis = NULL;
4722         int num_entries, rc;
4723         struct lnet_dlc_network_descr nw_descr;
4724
4725         INIT_LIST_HEAD(&nw_descr.network_on_rule);
4726         INIT_LIST_HEAD(&nw_descr.nw_intflist);
4727
4728         net = cYAML_get_object_item(tree, "net type");
4729         if (net != NULL)
4730                 nw_descr.nw_id = libcfs_str2net(net->cy_valuestring);
4731
4732         local_nis = cYAML_get_object_item(tree, "local NI(s)");
4733         if (local_nis == NULL)
4734                 return LUSTRE_CFG_RC_MISSING_PARAM;
4735
4736         if (!cYAML_is_sequence(local_nis))
4737                 return LUSTRE_CFG_RC_BAD_PARAM;
4738
4739         while (cYAML_get_next_seq_item(local_nis, &item) != NULL) {
4740                 intf = cYAML_get_object_item(item, "interfaces");
4741                 if (intf == NULL)
4742                         continue;
4743                 num_entries = yaml_copy_intf_info(intf, &nw_descr);
4744                 if (num_entries <= 0) {
4745                         cYAML_build_error(num_entries, -1, "ni", "add",
4746                                         "bad interface list",
4747                                         err_rc);
4748                         return LUSTRE_CFG_RC_BAD_PARAM;
4749                 }
4750         }
4751
4752         seq_no = cYAML_get_object_item(tree, "seq_no");
4753
4754         rc = lustre_lnet_del_ni((net) ? &nw_descr : NULL,
4755                                 (seq_no) ? seq_no->cy_valueint : -1,
4756                                 err_rc);
4757
4758         return rc;
4759 }
4760
4761 /* Create a nidstring parseable by the nidstrings library from the nid
4762  * information encoded in the CYAML structure.
4763  * NOTE: Caller must free memory allocated to nidstr
4764  */
4765 static int yaml_nids2nidstr(struct cYAML *nids_entry, char **nidstr,
4766                             char *prim_nid, int cmd)
4767 {
4768         int num_strs = 0, rc;
4769         size_t buf_size, buf_pos, nidstr_len = 0;
4770         char *buffer;
4771         struct cYAML *child = NULL, *entry = NULL;
4772
4773         if (cYAML_is_sequence(nids_entry)) {
4774                 while (cYAML_get_next_seq_item(nids_entry, &child)) {
4775                         entry = cYAML_get_object_item(child, "nid");
4776                         /* don't count an empty entry */
4777                         if (!entry || !entry->cy_valuestring)
4778                                 continue;
4779
4780                         if (prim_nid &&
4781                             (strcmp(entry->cy_valuestring, prim_nid) == 0)) {
4782                                 if (cmd == LNETCTL_DEL_CMD) {
4783                                         /*
4784                                          * primary nid is present in the list of
4785                                          * nids so that means we want to delete
4786                                          * the entire peer, so no need to go
4787                                          * further. Just delete the entire peer.
4788                                          */
4789                                         return LUSTRE_CFG_RC_NO_ERR;
4790                                 } else {
4791                                         continue;
4792                                 }
4793                         }
4794
4795                         /*
4796                          * + 1 for the space separating each string, and
4797                          * accounts for the terminating null char
4798                          */
4799                         nidstr_len += strlen(entry->cy_valuestring) + 1;
4800                         num_strs++;
4801                 }
4802         }
4803
4804         if (num_strs == 0 && !prim_nid)
4805                 return LUSTRE_CFG_RC_MISSING_PARAM;
4806         else if (num_strs == 0) /* Only the primary nid was given to add/del */
4807                 return LUSTRE_CFG_RC_NO_ERR;
4808
4809         buffer = malloc(nidstr_len);
4810         if (!buffer)
4811                 return LUSTRE_CFG_RC_OUT_OF_MEM;
4812
4813         /* now grab all the nids */
4814         rc = 0;
4815         buf_pos = 0;
4816         buf_size = nidstr_len;
4817         child = NULL;
4818         while (cYAML_get_next_seq_item(nids_entry, &child)) {
4819                 entry = cYAML_get_object_item(child, "nid");
4820                 if (!entry || !entry->cy_valuestring)
4821                         continue;
4822
4823                 if (prim_nid &&
4824                     (strcmp(entry->cy_valuestring, prim_nid) == 0))
4825                         continue;
4826
4827                 if (buf_pos) {
4828                         rc = snprintf(buffer + buf_pos, buf_size, " ");
4829                         buf_pos += (rc < buf_size) ? rc : buf_size;
4830                         buf_size = nidstr_len - buf_pos;
4831                 }
4832
4833                 rc = snprintf(buffer + buf_pos, buf_size, "%s",
4834                               entry->cy_valuestring);
4835                 buf_pos += (rc < buf_size) ? rc : buf_size;
4836                 buf_size = nidstr_len - buf_pos;
4837         }
4838
4839         *nidstr = buffer;
4840
4841         return LUSTRE_CFG_RC_NO_ERR;
4842 }
4843
4844 static int handle_yaml_peer_common(struct cYAML *tree, struct cYAML **show_rc,
4845                                    struct cYAML **err_rc, int cmd)
4846 {
4847         int rc, num_nids = 0, seqn;
4848         bool mr_value = false;
4849         char *nidstr = NULL, *prim_nidstr;
4850         char err_str[LNET_MAX_STR_LEN];
4851         struct cYAML *seq_no, *prim_nid, *mr, *peer_nis;
4852         lnet_nid_t lnet_nidlist[LNET_MAX_NIDS_PER_PEER];
4853         lnet_nid_t pnid = LNET_NID_ANY;
4854
4855         seq_no = cYAML_get_object_item(tree, "seq_no");
4856         seqn = seq_no ? seq_no->cy_valueint : -1;
4857
4858         prim_nid = cYAML_get_object_item(tree, "primary nid");
4859         peer_nis = cYAML_get_object_item(tree, "peer ni");
4860         if (!prim_nid) {
4861                 rc = LUSTRE_CFG_RC_BAD_PARAM;
4862                 snprintf(err_str, LNET_MAX_STR_LEN,
4863                          "\"primary nid\" must be specified");
4864                 goto failed;
4865         }
4866
4867         prim_nidstr = prim_nid->cy_valuestring;
4868
4869         /* if the provided primary NID is bad, no need to go any further */
4870         pnid = libcfs_str2nid(prim_nidstr);
4871         if (pnid == LNET_NID_ANY) {
4872                 rc = LUSTRE_CFG_RC_BAD_PARAM;
4873                 snprintf(err_str, LNET_MAX_STR_LEN,
4874                         "badly formatted primary NID: %s", prim_nidstr);
4875                 goto failed;
4876         }
4877
4878         rc = yaml_nids2nidstr(peer_nis, &nidstr, prim_nidstr, cmd);
4879         if (rc == LUSTRE_CFG_RC_MISSING_PARAM) {
4880                 snprintf(err_str, LNET_MAX_STR_LEN,
4881                          "No nids defined in YAML block");
4882                 goto failed;
4883         } else if (rc == LUSTRE_CFG_RC_OUT_OF_MEM) {
4884                 snprintf(err_str, LNET_MAX_STR_LEN, "out of memory");
4885                 goto failed;
4886         } else if (rc != LUSTRE_CFG_RC_NO_ERR) {
4887                 snprintf(err_str, LNET_MAX_STR_LEN,
4888                          "Unrecognized error %d", rc);
4889                 goto failed;
4890         }
4891
4892         num_nids = 0;
4893         if (nidstr) {
4894                 num_nids = lustre_lnet_parse_nidstr(nidstr, lnet_nidlist,
4895                                                     LNET_MAX_NIDS_PER_PEER,
4896                                                     err_str);
4897                 if (num_nids < 0) {
4898                         rc = num_nids;
4899                         goto failed;
4900                 }
4901         }
4902
4903         if (cmd == LNETCTL_ADD_CMD) {
4904                 mr = cYAML_get_object_item(tree, "Multi-Rail");
4905                 mr_value = true;
4906                 if (mr && mr->cy_valuestring) {
4907                         if (strcmp(mr->cy_valuestring, "False") == 0)
4908                                 mr_value = false;
4909                         else if (strcmp(mr->cy_valuestring, "True") != 0) {
4910                                 rc = LUSTRE_CFG_RC_BAD_PARAM;
4911                                 snprintf(err_str, LNET_MAX_STR_LEN,
4912                                          "Multi-Rail must be set to \"True\" or \"False\" found \"%s\"",
4913                                          mr->cy_valuestring);
4914                                 goto failed;
4915                         }
4916                 }
4917         }
4918
4919         rc = lustre_lnet_mod_peer_nidlist(pnid, lnet_nidlist, cmd,
4920                                           num_nids, mr_value, seqn,
4921                                           err_rc);
4922
4923 failed:
4924         if (nidstr)
4925                 free(nidstr);
4926
4927         if (rc != LUSTRE_CFG_RC_NO_ERR)
4928                 cYAML_build_error(rc, seqn, "peer",
4929                                   cmd == LNETCTL_ADD_CMD ? ADD_CMD : DEL_CMD,
4930                                   err_str, err_rc);
4931
4932         return rc;
4933 }
4934
4935 static int handle_yaml_config_peer(struct cYAML *tree, struct cYAML **show_rc,
4936                                    struct cYAML **err_rc)
4937 {
4938         return handle_yaml_peer_common(tree, show_rc, err_rc, LNETCTL_ADD_CMD);
4939 }
4940
4941 static int handle_yaml_del_peer(struct cYAML *tree, struct cYAML **show_rc,
4942                                 struct cYAML **err_rc)
4943 {
4944         return handle_yaml_peer_common(tree, show_rc, err_rc, LNETCTL_DEL_CMD);
4945 }
4946
4947 static int handle_yaml_config_buffers(struct cYAML *tree,
4948                                       struct cYAML **show_rc,
4949                                       struct cYAML **err_rc)
4950 {
4951         int rc;
4952         struct cYAML *tiny, *small, *large, *seq_no;
4953
4954         tiny = cYAML_get_object_item(tree, "tiny");
4955         small = cYAML_get_object_item(tree, "small");
4956         large = cYAML_get_object_item(tree, "large");
4957         seq_no = cYAML_get_object_item(tree, "seq_no");
4958
4959         rc = lustre_lnet_config_buffers((tiny) ? tiny->cy_valueint : -1,
4960                                         (small) ? small->cy_valueint : -1,
4961                                         (large) ? large->cy_valueint : -1,
4962                                         (seq_no) ? seq_no->cy_valueint : -1,
4963                                         err_rc);
4964
4965         return rc;
4966 }
4967
4968 static int handle_yaml_config_routing(struct cYAML *tree,
4969                                       struct cYAML **show_rc,
4970                                       struct cYAML **err_rc)
4971 {
4972         int rc = LUSTRE_CFG_RC_NO_ERR;
4973         struct cYAML *seq_no, *enable;
4974
4975         seq_no = cYAML_get_object_item(tree, "seq_no");
4976         enable = cYAML_get_object_item(tree, "enable");
4977
4978         if (enable) {
4979                 rc = lustre_lnet_enable_routing(enable->cy_valueint,
4980                                                 (seq_no) ?
4981                                                     seq_no->cy_valueint : -1,
4982                                                 err_rc);
4983         }
4984
4985         return rc;
4986 }
4987
4988 static int handle_yaml_del_route(struct cYAML *tree, struct cYAML **show_rc,
4989                                  struct cYAML **err_rc)
4990 {
4991         struct cYAML *net;
4992         struct cYAML *gw;
4993         struct cYAML *seq_no;
4994
4995         net = cYAML_get_object_item(tree, "net");
4996         gw = cYAML_get_object_item(tree, "gateway");
4997         seq_no = cYAML_get_object_item(tree, "seq_no");
4998
4999         return lustre_lnet_del_route((net) ? net->cy_valuestring : NULL,
5000                                      (gw) ? gw->cy_valuestring : NULL,
5001                                      (seq_no) ? seq_no->cy_valueint : -1,
5002                                      err_rc);
5003 }
5004
5005 static int handle_yaml_del_routing(struct cYAML *tree, struct cYAML **show_rc,
5006                                    struct cYAML **err_rc)
5007 {
5008         struct cYAML *seq_no;
5009
5010         seq_no = cYAML_get_object_item(tree, "seq_no");
5011
5012         return lustre_lnet_enable_routing(0, (seq_no) ?
5013                                                 seq_no->cy_valueint : -1,
5014                                         err_rc);
5015 }
5016
5017 static int handle_yaml_show_route(struct cYAML *tree, struct cYAML **show_rc,
5018                                   struct cYAML **err_rc)
5019 {
5020         struct cYAML *net;
5021         struct cYAML *gw;
5022         struct cYAML *hop;
5023         struct cYAML *prio;
5024         struct cYAML *detail;
5025         struct cYAML *seq_no;
5026
5027         net = cYAML_get_object_item(tree, "net");
5028         gw = cYAML_get_object_item(tree, "gateway");
5029         hop = cYAML_get_object_item(tree, "hop");
5030         prio = cYAML_get_object_item(tree, "priority");
5031         detail = cYAML_get_object_item(tree, "detail");
5032         seq_no = cYAML_get_object_item(tree, "seq_no");
5033
5034         return lustre_lnet_show_route((net) ? net->cy_valuestring : NULL,
5035                                       (gw) ? gw->cy_valuestring : NULL,
5036                                       (hop) ? hop->cy_valueint : -1,
5037                                       (prio) ? prio->cy_valueint : -1,
5038                                       (detail) ? detail->cy_valueint : 0,
5039                                       (seq_no) ? seq_no->cy_valueint : -1,
5040                                       show_rc, err_rc, false);
5041 }
5042
5043 static int handle_yaml_show_net(struct cYAML *tree, struct cYAML **show_rc,
5044                                 struct cYAML **err_rc)
5045 {
5046         struct cYAML *net, *detail, *seq_no;
5047
5048         net = cYAML_get_object_item(tree, "net type");
5049         detail = cYAML_get_object_item(tree, "detail");
5050         seq_no = cYAML_get_object_item(tree, "seq_no");
5051
5052         return lustre_lnet_show_net((net) ? net->cy_valuestring : NULL,
5053                                     (detail) ? detail->cy_valueint : 0,
5054                                     (seq_no) ? seq_no->cy_valueint : -1,
5055                                     show_rc, err_rc, false);
5056 }
5057
5058 static int handle_yaml_show_routing(struct cYAML *tree, struct cYAML **show_rc,
5059                                     struct cYAML **err_rc)
5060 {
5061         struct cYAML *seq_no;
5062
5063         seq_no = cYAML_get_object_item(tree, "seq_no");
5064
5065         return lustre_lnet_show_routing((seq_no) ? seq_no->cy_valueint : -1,
5066                                         show_rc, err_rc, false);
5067 }
5068
5069 static int handle_yaml_show_peers(struct cYAML *tree, struct cYAML **show_rc,
5070                                   struct cYAML **err_rc)
5071 {
5072         struct cYAML *seq_no, *nid, *detail;
5073
5074         seq_no = cYAML_get_object_item(tree, "seq_no");
5075         detail = cYAML_get_object_item(tree, "detail");
5076         nid = cYAML_get_object_item(tree, "nid");
5077
5078         return lustre_lnet_show_peer((nid) ? nid->cy_valuestring : NULL,
5079                                      (detail) ? detail->cy_valueint : 0,
5080                                      (seq_no) ? seq_no->cy_valueint : -1,
5081                                      show_rc, err_rc, false);
5082 }
5083
5084 static int handle_yaml_show_stats(struct cYAML *tree, struct cYAML **show_rc,
5085                                   struct cYAML **err_rc)
5086 {
5087         struct cYAML *seq_no;
5088
5089         seq_no = cYAML_get_object_item(tree, "seq_no");
5090
5091         return lustre_lnet_show_stats((seq_no) ? seq_no->cy_valueint : -1,
5092                                       show_rc, err_rc);
5093 }
5094
5095 static int handle_yaml_config_numa(struct cYAML *tree, struct cYAML **show_rc,
5096                                   struct cYAML **err_rc)
5097 {
5098         struct cYAML *seq_no, *range;
5099
5100         seq_no = cYAML_get_object_item(tree, "seq_no");
5101         range = cYAML_get_object_item(tree, "range");
5102
5103         return lustre_lnet_config_numa_range(range ? range->cy_valueint : -1,
5104                                              seq_no ? seq_no->cy_valueint : -1,
5105                                              err_rc);
5106 }
5107
5108 static int handle_yaml_del_numa(struct cYAML *tree, struct cYAML **show_rc,
5109                                struct cYAML **err_rc)
5110 {
5111         struct cYAML *seq_no;
5112
5113         seq_no = cYAML_get_object_item(tree, "seq_no");
5114
5115         return lustre_lnet_config_numa_range(0, seq_no ? seq_no->cy_valueint : -1,
5116                                              err_rc);
5117 }
5118
5119 static int handle_yaml_show_numa(struct cYAML *tree, struct cYAML **show_rc,
5120                                 struct cYAML **err_rc)
5121 {
5122         struct cYAML *seq_no;
5123
5124         seq_no = cYAML_get_object_item(tree, "seq_no");
5125
5126         return lustre_lnet_show_numa_range(seq_no ? seq_no->cy_valueint : -1,
5127                                            show_rc, err_rc);
5128 }
5129
5130 static int handle_yaml_del_udsp(struct cYAML *tree, struct cYAML **show_rc,
5131                                 struct cYAML **err_rc)
5132 {
5133         struct cYAML *seq_no, *idx;
5134
5135         seq_no = cYAML_get_object_item(tree, "seq_no");
5136         idx = cYAML_get_object_item(tree, "idx");
5137
5138         return lustre_lnet_del_udsp(idx ? idx->cy_valueint : -1,
5139                                     seq_no ? seq_no->cy_valueint : -1,
5140                                     err_rc);
5141 }
5142
5143 static int handle_yaml_config_udsp(struct cYAML *tree, struct cYAML **show_rc,
5144                                    struct cYAML **err_rc)
5145 {
5146         struct cYAML *seq_no, *src, *rte, *dst, *prio, *idx;
5147         union lnet_udsp_action action;
5148
5149         seq_no = cYAML_get_object_item(tree, "seq_no");
5150         src = cYAML_get_object_item(tree, "src");
5151         rte = cYAML_get_object_item(tree, "rte");
5152         dst = cYAML_get_object_item(tree, "dst");
5153         prio = cYAML_get_object_item(tree, "priority");
5154         idx = cYAML_get_object_item(tree, "idx");
5155
5156         action.udsp_priority = prio ? prio->cy_valueint : -1;
5157
5158         return lustre_lnet_add_udsp(src ? src->cy_valuestring : NULL,
5159                                     dst ? dst->cy_valuestring : NULL,
5160                                     rte ? rte->cy_valuestring : NULL,
5161                                     prio ? "priority" : "",
5162                                     &action,
5163                                     idx ? idx->cy_valueint : -1,
5164                                     seq_no ? seq_no->cy_valueint : -1,
5165                                     err_rc);
5166 }
5167
5168 static int handle_yaml_show_udsp(struct cYAML *tree, struct cYAML **show_rc,
5169                                  struct cYAML **err_rc)
5170 {
5171         struct cYAML *seq_no;
5172         struct cYAML *idx;
5173
5174         seq_no = cYAML_get_object_item(tree, "seq_no");
5175         idx = cYAML_get_object_item(tree, "idx");
5176
5177         return lustre_lnet_show_udsp(idx ? idx->cy_valueint : -1,
5178                                      seq_no ? seq_no->cy_valueint : -1,
5179                                      show_rc, err_rc);
5180 }
5181
5182 static int handle_yaml_config_global_settings(struct cYAML *tree,
5183                                               struct cYAML **show_rc,
5184                                               struct cYAML **err_rc)
5185 {
5186         struct cYAML *max_intf, *numa, *discovery, *retry, *tto, *seq_no,
5187                      *sen, *recov, *rsen, *drop_asym_route, *rsp_tracking,
5188                      *recov_limit;
5189         int rc = 0;
5190
5191         seq_no = cYAML_get_object_item(tree, "seq_no");
5192         max_intf = cYAML_get_object_item(tree, "max_interfaces");
5193         if (!max_intf) /* try legacy name */
5194                 max_intf = cYAML_get_object_item(tree, "max_intf");
5195         if (max_intf)
5196                 rc = lustre_lnet_config_max_intf(max_intf->cy_valueint,
5197                                                  seq_no ? seq_no->cy_valueint
5198                                                         : -1,
5199                                                  err_rc);
5200
5201         numa = cYAML_get_object_item(tree, "numa_range");
5202         if (numa)
5203                 rc = lustre_lnet_config_numa_range(numa->cy_valueint,
5204                                                    seq_no ? seq_no->cy_valueint
5205                                                         : -1,
5206                                                    err_rc);
5207
5208         discovery = cYAML_get_object_item(tree, "discovery");
5209         if (discovery)
5210                 rc = lustre_lnet_config_discovery(discovery->cy_valueint,
5211                                                   seq_no ? seq_no->cy_valueint
5212                                                         : -1,
5213                                                   err_rc);
5214
5215         drop_asym_route = cYAML_get_object_item(tree, "drop_asym_route");
5216         if (drop_asym_route)
5217                 rc = lustre_lnet_config_drop_asym_route(
5218                         drop_asym_route->cy_valueint,
5219                         seq_no ? seq_no->cy_valueint : -1,
5220                         err_rc);
5221
5222         retry = cYAML_get_object_item(tree, "retry_count");
5223         if (retry)
5224                 rc = lustre_lnet_config_retry_count(retry->cy_valueint,
5225                                                     seq_no ? seq_no->cy_valueint
5226                                                         : -1,
5227                                                     err_rc);
5228
5229         tto = cYAML_get_object_item(tree, "transaction_timeout");
5230         if (tto)
5231                 rc = lustre_lnet_config_transaction_to(tto->cy_valueint,
5232                                                        seq_no ? seq_no->cy_valueint
5233                                                                 : -1,
5234                                                        err_rc);
5235
5236         sen = cYAML_get_object_item(tree, "health_sensitivity");
5237         if (sen)
5238                 rc = lustre_lnet_config_hsensitivity(sen->cy_valueint,
5239                                                      seq_no ? seq_no->cy_valueint
5240                                                         : -1,
5241                                                      err_rc);
5242
5243         recov = cYAML_get_object_item(tree, "recovery_interval");
5244         if (recov)
5245                 rc = lustre_lnet_config_recov_intrv(recov->cy_valueint,
5246                                                     seq_no ? seq_no->cy_valueint
5247                                                         : -1,
5248                                                     err_rc);
5249
5250         rsen = cYAML_get_object_item(tree, "router_sensitivity");
5251         if (rsen)
5252                 rc = lustre_lnet_config_rtr_sensitivity(rsen->cy_valueint,
5253                                                      seq_no ? seq_no->cy_valueint
5254                                                         : -1,
5255                                                      err_rc);
5256
5257         rsp_tracking = cYAML_get_object_item(tree, "response_tracking");
5258         if (rsp_tracking)
5259                 rc = lustre_lnet_config_response_tracking(rsp_tracking->cy_valueint,
5260                                                      seq_no ? seq_no->cy_valueint
5261                                                         : -1,
5262                                                      err_rc);
5263
5264         recov_limit = cYAML_get_object_item(tree, "recovery_limit");
5265         if (recov_limit)
5266                 rc = lustre_lnet_config_recovery_limit(recov_limit->cy_valueint,
5267                                                        seq_no ? seq_no->cy_valueint
5268                                                         : -1,
5269                                                        err_rc);
5270
5271         return rc;
5272 }
5273
5274 static int handle_yaml_del_global_settings(struct cYAML *tree,
5275                                            struct cYAML **show_rc,
5276                                            struct cYAML **err_rc)
5277 {
5278         struct cYAML *max_intf, *numa, *discovery, *seq_no, *drop_asym_route;
5279         int rc = 0;
5280
5281         seq_no = cYAML_get_object_item(tree, "seq_no");
5282         max_intf = cYAML_get_object_item(tree, "max_interfaces");
5283         if (!max_intf) /* try legacy name */
5284                 max_intf = cYAML_get_object_item(tree, "max_intf");
5285         if (max_intf)
5286                 rc = lustre_lnet_config_max_intf(LNET_INTERFACES_MAX_DEFAULT,
5287                                                  seq_no ? seq_no->cy_valueint
5288                                                         : -1,
5289                                                  err_rc);
5290
5291         numa = cYAML_get_object_item(tree, "numa_range");
5292         if (numa)
5293                 rc = lustre_lnet_config_numa_range(0,
5294                                                    seq_no ? seq_no->cy_valueint
5295                                                         : -1,
5296                                                    err_rc);
5297
5298         /* peer discovery is enabled by default */
5299         discovery = cYAML_get_object_item(tree, "discovery");
5300         if (discovery)
5301                 rc = lustre_lnet_config_discovery(1,
5302                                                   seq_no ? seq_no->cy_valueint
5303                                                         : -1,
5304                                                   err_rc);
5305
5306         /* asymmetrical route messages are accepted by default */
5307         drop_asym_route = cYAML_get_object_item(tree, "drop_asym_route");
5308         if (drop_asym_route)
5309                 rc = lustre_lnet_config_drop_asym_route(
5310                         0, seq_no ? seq_no->cy_valueint : -1, err_rc);
5311
5312         return rc;
5313 }
5314
5315 static int handle_yaml_show_global_settings(struct cYAML *tree,
5316                                             struct cYAML **show_rc,
5317                                             struct cYAML **err_rc)
5318 {
5319         struct cYAML *max_intf, *numa, *discovery, *retry, *tto, *seq_no,
5320                      *sen, *recov, *rsen, *drop_asym_route, *rsp_tracking,
5321                      *recov_limit;
5322         int rc = 0;
5323
5324         seq_no = cYAML_get_object_item(tree, "seq_no");
5325         max_intf = cYAML_get_object_item(tree, "max_interfaces");
5326         if (!max_intf) /* try legacy name */
5327                 max_intf = cYAML_get_object_item(tree, "max_intf");
5328         if (max_intf)
5329                 rc = lustre_lnet_show_max_intf(seq_no ? seq_no->cy_valueint
5330                                                         : -1,
5331                                                 show_rc, err_rc);
5332
5333         numa = cYAML_get_object_item(tree, "numa_range");
5334         if (numa)
5335                 rc = lustre_lnet_show_numa_range(seq_no ? seq_no->cy_valueint
5336                                                         : -1,
5337                                                  show_rc, err_rc);
5338
5339         discovery = cYAML_get_object_item(tree, "discovery");
5340         if (discovery)
5341                 rc = lustre_lnet_show_discovery(seq_no ? seq_no->cy_valueint
5342                                                         : -1,
5343                                                 show_rc, err_rc);
5344
5345         drop_asym_route = cYAML_get_object_item(tree, "drop_asym_route");
5346         if (drop_asym_route)
5347                 rc = lustre_lnet_show_drop_asym_route(
5348                         seq_no ? seq_no->cy_valueint : -1,
5349                         show_rc, err_rc);
5350
5351         retry = cYAML_get_object_item(tree, "retry_count");
5352         if (retry)
5353                 rc = lustre_lnet_show_retry_count(seq_no ? seq_no->cy_valueint
5354                                                         : -1,
5355                                                   show_rc, err_rc);
5356
5357         tto = cYAML_get_object_item(tree, "transaction_timeout");
5358         if (tto)
5359                 rc = lustre_lnet_show_transaction_to(seq_no ? seq_no->cy_valueint
5360                                                         : -1,
5361                                                      show_rc, err_rc);
5362
5363         sen = cYAML_get_object_item(tree, "health_sensitivity");
5364         if (sen)
5365                 rc = lustre_lnet_show_hsensitivity(seq_no ? seq_no->cy_valueint
5366                                                         : -1,
5367                                                      show_rc, err_rc);
5368
5369         recov = cYAML_get_object_item(tree, "recovery_interval");
5370         if (recov)
5371                 rc = lustre_lnet_show_recov_intrv(seq_no ? seq_no->cy_valueint
5372                                                         : -1,
5373                                                   show_rc, err_rc);
5374
5375         rsen = cYAML_get_object_item(tree, "router_sensitivity");
5376         if (rsen)
5377                 rc = lustre_lnet_show_hsensitivity(seq_no ? seq_no->cy_valueint
5378                                                         : -1,
5379                                                      show_rc, err_rc);
5380
5381         rsp_tracking = cYAML_get_object_item(tree, "response_tracking");
5382         if (rsp_tracking)
5383                 rc = lustre_lnet_show_response_tracking(seq_no ?
5384                                                         seq_no->cy_valueint :
5385                                                         -1,
5386                                                         show_rc, err_rc);
5387
5388         recov_limit = cYAML_get_object_item(tree, "recovery_limit");
5389         if (recov_limit)
5390                 rc = lustre_lnet_show_recovery_limit(seq_no ?
5391                                                      seq_no->cy_valueint :
5392                                                      -1,
5393                                                      show_rc, err_rc);
5394
5395         return rc;
5396 }
5397
5398 static int handle_yaml_ping(struct cYAML *tree, struct cYAML **show_rc,
5399                             struct cYAML **err_rc)
5400 {
5401         struct cYAML *seq_no, *nid, *timeout, *src_nid;
5402
5403         seq_no = cYAML_get_object_item(tree, "seq_no");
5404         nid = cYAML_get_object_item(tree, "primary nid");
5405         timeout = cYAML_get_object_item(tree, "timeout");
5406         src_nid = cYAML_get_object_item(tree, "source_nid");
5407
5408         return lustre_lnet_ping_nid((nid) ? nid->cy_valuestring : NULL,
5409                                     (src_nid) ? src_nid->cy_valuestring : NULL,
5410                                     (timeout) ? timeout->cy_valueint : 1000,
5411                                     (seq_no) ? seq_no->cy_valueint : -1,
5412                                     show_rc, err_rc);
5413 }
5414
5415 static int handle_yaml_discover(struct cYAML *tree, struct cYAML **show_rc,
5416                                 struct cYAML **err_rc)
5417 {
5418         struct cYAML *seq_no, *nid, *force;
5419
5420         seq_no = cYAML_get_object_item(tree, "seq_no");
5421         nid = cYAML_get_object_item(tree, "primary nid");
5422         force = cYAML_get_object_item(tree, "force");
5423
5424         return lustre_lnet_discover_nid((nid) ? nid->cy_valuestring : NULL,
5425                                         (force) ? force->cy_valueint : 0,
5426                                         (seq_no) ? seq_no->cy_valueint : -1,
5427                                         show_rc, err_rc);
5428 }
5429
5430 static int handle_yaml_no_op()
5431 {
5432         return LUSTRE_CFG_RC_NO_ERR;
5433 }
5434
5435 struct lookup_cmd_hdlr_tbl {
5436         char *name;
5437         cmd_handler_t cb;
5438 };
5439
5440 static struct lookup_cmd_hdlr_tbl lookup_config_tbl[] = {
5441         { .name = "route",      .cb = handle_yaml_config_route },
5442         { .name = "net",        .cb = handle_yaml_config_ni },
5443         { .name = "ip2nets",    .cb = handle_yaml_config_ip2nets },
5444         { .name = "peer",       .cb = handle_yaml_config_peer },
5445         { .name = "routing",    .cb = handle_yaml_config_routing },
5446         { .name = "buffers",    .cb = handle_yaml_config_buffers },
5447         { .name = "statistics", .cb = handle_yaml_no_op },
5448         { .name = "global",     .cb = handle_yaml_config_global_settings},
5449         { .name = "numa",       .cb = handle_yaml_config_numa },
5450         { .name = "ping",       .cb = handle_yaml_no_op },
5451         { .name = "discover",   .cb = handle_yaml_no_op },
5452         { .name = "udsp",       .cb = handle_yaml_config_udsp },
5453         { .name = NULL } };
5454
5455 static struct lookup_cmd_hdlr_tbl lookup_del_tbl[] = {
5456         { .name = "route",      .cb = handle_yaml_del_route },
5457         { .name = "net",        .cb = handle_yaml_del_ni },
5458         { .name = "ip2nets",    .cb = handle_yaml_no_op },
5459         { .name = "peer",       .cb = handle_yaml_del_peer },
5460         { .name = "routing",    .cb = handle_yaml_del_routing },
5461         { .name = "buffers",    .cb = handle_yaml_no_op },
5462         { .name = "statistics", .cb = handle_yaml_no_op },
5463         { .name = "global",     .cb = handle_yaml_del_global_settings},
5464         { .name = "numa",       .cb = handle_yaml_del_numa },
5465         { .name = "ping",       .cb = handle_yaml_no_op },
5466         { .name = "discover",   .cb = handle_yaml_no_op },
5467         { .name = "udsp",       .cb = handle_yaml_del_udsp },
5468         { .name = NULL } };
5469
5470 static struct lookup_cmd_hdlr_tbl lookup_show_tbl[] = {
5471         { .name = "route",      .cb = handle_yaml_show_route },
5472         { .name = "net",        .cb = handle_yaml_show_net },
5473         { .name = "peer",       .cb = handle_yaml_show_peers },
5474         { .name = "ip2nets",    .cb = handle_yaml_no_op },
5475         { .name = "routing",    .cb = handle_yaml_show_routing },
5476         { .name = "buffers",    .cb = handle_yaml_show_routing },
5477         { .name = "statistics", .cb = handle_yaml_show_stats },
5478         { .name = "global",     .cb = handle_yaml_show_global_settings},
5479         { .name = "numa",       .cb = handle_yaml_show_numa },
5480         { .name = "ping",       .cb = handle_yaml_no_op },
5481         { .name = "discover",   .cb = handle_yaml_no_op },
5482         { .name = "udsp",       .cb = handle_yaml_show_udsp },
5483         { .name = NULL } };
5484
5485 static struct lookup_cmd_hdlr_tbl lookup_exec_tbl[] = {
5486         { .name = "route",      .cb = handle_yaml_no_op },
5487         { .name = "net",        .cb = handle_yaml_no_op },
5488         { .name = "peer",       .cb = handle_yaml_no_op },
5489         { .name = "ip2nets",    .cb = handle_yaml_no_op },
5490         { .name = "routing",    .cb = handle_yaml_no_op },
5491         { .name = "buffers",    .cb = handle_yaml_no_op },
5492         { .name = "statistics", .cb = handle_yaml_no_op },
5493         { .name = "global",     .cb = handle_yaml_no_op },
5494         { .name = "numa",       .cb = handle_yaml_no_op },
5495         { .name = "ping",       .cb = handle_yaml_ping },
5496         { .name = "discover",   .cb = handle_yaml_discover },
5497         { .name = NULL } };
5498
5499 static cmd_handler_t lookup_fn(char *key,
5500                                struct lookup_cmd_hdlr_tbl *tbl)
5501 {
5502         int i;
5503         if (key == NULL)
5504                 return NULL;
5505
5506         for (i = 0; tbl[i].name != NULL; i++) {
5507                 if (strncmp(key, tbl[i].name, strlen(tbl[i].name)) == 0)
5508                         return tbl[i].cb;
5509         }
5510
5511         return NULL;
5512 }
5513
5514 static int lustre_yaml_cb_helper(char *f, struct lookup_cmd_hdlr_tbl *table,
5515                                  struct cYAML **show_rc, struct cYAML **err_rc)
5516 {
5517         struct cYAML *tree, *item = NULL, *head, *child;
5518         cmd_handler_t cb;
5519         char err_str[LNET_MAX_STR_LEN];
5520         int rc = LUSTRE_CFG_RC_NO_ERR, return_rc = LUSTRE_CFG_RC_NO_ERR;
5521
5522         tree = cYAML_build_tree(f, NULL, 0, err_rc, false);
5523         if (tree == NULL)
5524                 return LUSTRE_CFG_RC_BAD_PARAM;
5525
5526         child = tree->cy_child;
5527         while (child != NULL) {
5528                 cb = lookup_fn(child->cy_string, table);
5529                 if (cb == NULL) {
5530                         snprintf(err_str, sizeof(err_str),
5531                                 "\"call back for '%s' not found\"",
5532                                 child->cy_string);
5533                         cYAML_build_error(LUSTRE_CFG_RC_BAD_PARAM, -1,
5534                                         "yaml", "helper", err_str, err_rc);
5535                         goto out;
5536                 }
5537
5538                 if (cYAML_is_sequence(child)) {
5539                         while ((head = cYAML_get_next_seq_item(child, &item))
5540                                != NULL) {
5541                                 rc = cb(head, show_rc, err_rc);
5542                                 if (rc != LUSTRE_CFG_RC_NO_ERR)
5543                                         return_rc = rc;
5544                         }
5545                 } else {
5546                         rc = cb(child, show_rc, err_rc);
5547                         if (rc != LUSTRE_CFG_RC_NO_ERR)
5548                                 return_rc = rc;
5549                 }
5550                 item = NULL;
5551                 child = child->cy_next;
5552         }
5553
5554 out:
5555         cYAML_free_tree(tree);
5556
5557         return return_rc;
5558 }
5559
5560 int lustre_yaml_config(char *f, struct cYAML **err_rc)
5561 {
5562         return lustre_yaml_cb_helper(f, lookup_config_tbl,
5563                                      NULL, err_rc);
5564 }
5565
5566 int lustre_yaml_del(char *f, struct cYAML **err_rc)
5567 {
5568         return lustre_yaml_cb_helper(f, lookup_del_tbl,
5569                                      NULL, err_rc);
5570 }
5571
5572 int lustre_yaml_show(char *f, struct cYAML **show_rc, struct cYAML **err_rc)
5573 {
5574         return lustre_yaml_cb_helper(f, lookup_show_tbl,
5575                                      show_rc, err_rc);
5576 }
5577
5578 int lustre_yaml_exec(char *f, struct cYAML **show_rc, struct cYAML **err_rc)
5579 {
5580         return lustre_yaml_cb_helper(f, lookup_exec_tbl,
5581                                      show_rc, err_rc);
5582 }