4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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.
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/>.
21 * Copyright (c) 2014, 2016, Intel Corporation.
24 * Amir Shehata <amir.shehata@intel.com>
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
44 #include <sys/ioctl.h>
46 #include <libcfs/util/ioctl.h>
47 #include <linux/lnet/lnetctl.h>
49 #include <sys/types.h>
51 #include "liblnetconfig.h"
54 #define CONFIG_CMD "configure"
55 #define UNCONFIG_CMD "unconfigure"
58 #define SHOW_CMD "show"
62 * lustre_lnet_ip_range_descr
63 * Describes an IP range.
64 * Each octect is an expression
66 struct lustre_lnet_ip_range_descr {
67 struct list_head ipr_entry;
68 struct list_head ipr_expr;
73 * Describes an ip2nets rule. This can be on a list of rules.
75 struct lustre_lnet_ip2nets {
76 struct lnet_dlc_network_descr ip2nets_net;
77 struct list_head ip2nets_ip_ranges;
82 * frees the memory allocated for an intf descriptor.
84 void free_intf_descr(struct lnet_dlc_intf_descr *intf_descr)
89 if (intf_descr->cpt_expr != NULL)
90 cfs_expr_list_free(intf_descr->cpt_expr);
95 * lustre_lnet_add_ip_range
97 * given a string of the format:
98 * <expr.expr.expr.expr> parse each expr into
99 * a lustre_lnet_ip_range_descr structure and insert on the list.
101 * This function is called from
102 * YAML on each ip-range.
103 * As a result of lnetctl command
104 * When building a NID or P2P selection rules
106 int lustre_lnet_add_ip_range(struct list_head *list, char *str_ip_range)
108 struct lustre_lnet_ip_range_descr *ip_range;
111 ip_range = calloc(1, sizeof(*ip_range));
112 if (ip_range == NULL)
113 return LUSTRE_CFG_RC_OUT_OF_MEM;
115 INIT_LIST_HEAD(&ip_range->ipr_entry);
116 INIT_LIST_HEAD(&ip_range->ipr_expr);
118 rc = cfs_ip_addr_parse(str_ip_range, strlen(str_ip_range),
119 &ip_range->ipr_expr);
121 return LUSTRE_CFG_RC_BAD_PARAM;
123 list_add_tail(&ip_range->ipr_entry, list);
125 return LUSTRE_CFG_RC_NO_ERR;
128 int lustre_lnet_add_intf_descr(struct list_head *list, char *intf, int len)
130 char *open_sq_bracket = NULL, *close_sq_bracket = NULL,
132 struct lnet_dlc_intf_descr *intf_descr = NULL;
134 char intf_string[LNET_MAX_STR_LEN];
136 if (len >= LNET_MAX_STR_LEN)
137 return LUSTRE_CFG_RC_BAD_PARAM;
139 strncpy(intf_string, intf, len);
140 intf_string[len] = '\0';
142 intf_descr = calloc(1, sizeof(*intf_descr));
143 if (intf_descr == NULL)
144 return LUSTRE_CFG_RC_OUT_OF_MEM;
146 INIT_LIST_HEAD(&intf_descr->intf_on_network);
148 intf_name = intf_string;
149 open_sq_bracket = strchr(intf_string, '[');
150 if (open_sq_bracket != NULL) {
151 close_sq_bracket = strchr(intf_string, ']');
152 if (close_sq_bracket == NULL) {
154 return LUSTRE_CFG_RC_BAD_PARAM;
156 rc = cfs_expr_list_parse(open_sq_bracket,
157 strlen(open_sq_bracket), 0, UINT_MAX,
158 &intf_descr->cpt_expr);
161 return LUSTRE_CFG_RC_BAD_PARAM;
163 strncpy(intf_descr->intf_name, intf_name,
164 open_sq_bracket - intf_name);
165 intf_descr->intf_name[open_sq_bracket - intf_name] = '\0';
167 strcpy(intf_descr->intf_name, intf_name);
168 intf_descr->cpt_expr = NULL;
171 list_add_tail(&intf_descr->intf_on_network, list);
173 return LUSTRE_CFG_RC_NO_ERR;
176 void lustre_lnet_init_nw_descr(struct lnet_dlc_network_descr *nw_descr)
178 if (nw_descr != NULL) {
179 INIT_LIST_HEAD(&nw_descr->network_on_rule);
180 INIT_LIST_HEAD(&nw_descr->nw_intflist);
184 int lustre_lnet_parse_nids(char *nids, char **array, int size,
188 char *comma = nids, *cur, *entry;
190 int i, len, start = 0, finish = 0;
192 if (nids == NULL || strlen(nids) == 0)
195 /* count the number or new nids, by counting the number of commas */
197 comma = strchr(comma, ',');
207 * if the array is not NULL allocate a large enough array to house
208 * the old and new entries
210 new_array = calloc(sizeof(char*),
211 (size > 0) ? size + num_nids : num_nids);
216 /* parse our the new nids and add them to the tail of the array */
219 start = (size > 0) ? size: 0;
220 finish = (size > 0) ? size + num_nids : num_nids;
221 for (i = start; i < finish; i++) {
222 comma = strchr(comma, ',');
225 * the length of the string to be parsed out is
226 * from cur to end of string. So it's good enough
229 len = strlen(cur) + 1;
231 /* length of the string is comma - cur */
232 len = (comma - cur) + 1;
234 entry = calloc(1, len);
236 finish = i > 0 ? i - 1: 0;
239 strncpy(entry, cur, len - 1);
241 new_array[i] = entry;
248 /* add the old entries in the array and delete the old array*/
249 for (i = 0; i < size; i++)
250 new_array[i] = array[i];
255 *out_array = new_array;
260 for (i = start; i < finish; i++)
270 * <intf>[<expr>], <intf>[<expr>],..
272 int lustre_lnet_parse_interfaces(char *intf_str,
273 struct lnet_dlc_network_descr *nw_descr)
278 char *cur = intf_str, *next = NULL;
279 char *end = intf_str + strlen(intf_str);
281 struct lnet_dlc_intf_descr *intf_descr, *tmp;
283 if (nw_descr == NULL)
284 return LUSTRE_CFG_RC_BAD_PARAM;
287 open_square = strchr(cur, '[');
288 if (open_square != NULL) {
289 close_square = strchr(cur, ']');
290 if (close_square == NULL) {
291 rc = LUSTRE_CFG_RC_BAD_PARAM;
295 comma = strchr(cur, ',');
296 if (comma != NULL && comma > close_square) {
298 len = next - close_square;
304 comma = strchr(cur, ',');
314 rc = lustre_lnet_add_intf_descr(&nw_descr->nw_intflist, cur, len);
315 if (rc != LUSTRE_CFG_RC_NO_ERR)
321 return LUSTRE_CFG_RC_NO_ERR;
324 list_for_each_entry_safe(intf_descr, tmp, &nw_descr->nw_intflist,
326 list_del(&intf_descr->intf_on_network);
327 free_intf_descr(intf_descr);
333 int lustre_lnet_config_lib_init(void)
335 return register_ioc_dev(LNET_DEV_ID, LNET_DEV_PATH,
336 LNET_DEV_MAJOR, LNET_DEV_MINOR);
339 void lustre_lnet_config_lib_uninit(void)
341 unregister_ioc_dev(LNET_DEV_ID);
344 int lustre_lnet_config_ni_system(bool up, bool load_ni_from_mod,
345 int seq_no, struct cYAML **err_rc)
347 struct libcfs_ioctl_data data;
350 char err_str[LNET_MAX_STR_LEN];
352 snprintf(err_str, sizeof(err_str), "\"Success\"");
354 LIBCFS_IOC_INIT(data);
356 /* Reverse logic is used here in order not to change
357 * the lctl utility */
358 data.ioc_flags = load_ni_from_mod ? 0 : 1;
360 opc = up ? IOC_LIBCFS_CONFIGURE : IOC_LIBCFS_UNCONFIGURE;
362 rc = l_ioctl(LNET_DEV_ID, opc, &data);
366 "\"LNet %s error: %s\"", (up) ? "configure" :
367 "unconfigure", strerror(errno));
371 cYAML_build_error(rc, seq_no, (up) ? CONFIG_CMD : UNCONFIG_CMD,
372 "lnet", err_str, err_rc);
377 static lnet_nid_t *allocate_create_nid_array(char **nids, __u32 num_nids,
380 lnet_nid_t *array = NULL;
383 if (!nids || num_nids == 0) {
384 snprintf(err_str, LNET_MAX_STR_LEN, "no NIDs to add");
388 array = calloc(sizeof(*array) * num_nids, 1);
390 snprintf(err_str, LNET_MAX_STR_LEN, "out of memory");
394 for (i = 0; i < num_nids; i++) {
395 array[i] = libcfs_str2nid(nids[i]);
396 if (array[i] == LNET_NID_ANY) {
398 snprintf(err_str, LNET_MAX_STR_LEN,
408 static int dispatch_peer_ni_cmd(lnet_nid_t pnid, lnet_nid_t nid, __u32 cmd,
409 struct lnet_ioctl_peer_cfg *data,
410 char *err_str, char *cmd_str)
414 data->prcfg_prim_nid = pnid;
415 data->prcfg_cfg_nid = nid;
417 rc = l_ioctl(LNET_DEV_ID, cmd, data);
422 "\"cannot %s peer ni: %s\"",
423 (cmd_str) ? cmd_str : "add", strerror(errno));
429 int lustre_lnet_config_peer_nid(char *pnid, char **nid, int num_nids,
430 bool mr, int seq_no, struct cYAML **err_rc)
432 struct lnet_ioctl_peer_cfg data;
433 lnet_nid_t prim_nid = LNET_NID_ANY;
434 int rc = LUSTRE_CFG_RC_NO_ERR;
436 bool nid0_used = false;
437 char err_str[LNET_MAX_STR_LEN] = {0};
438 lnet_nid_t *nids = allocate_create_nid_array(nid, num_nids, err_str);
441 prim_nid = libcfs_str2nid(pnid);
442 if (prim_nid == LNET_NID_ANY) {
443 snprintf(err_str, sizeof(err_str),
446 rc = LUSTRE_CFG_RC_MISSING_PARAM;
449 } else if (!nids || nids[0] == LNET_NID_ANY) {
450 snprintf(err_str, sizeof(err_str),
451 "no NIDs provided for configuration");
452 rc = LUSTRE_CFG_RC_MISSING_PARAM;
455 prim_nid = LNET_NID_ANY;
458 snprintf(err_str, sizeof(err_str), "\"Success\"");
460 LIBCFS_IOC_INIT_V2(data, prcfg_hdr);
464 * if prim_nid is not specified use the first nid in the list of
465 * nids provided as the prim_nid. NOTE: on entering 'if' we must
466 * have at least 1 NID
468 if (prim_nid == LNET_NID_ANY) {
473 /* Create the prim_nid first */
474 rc = dispatch_peer_ni_cmd(prim_nid, LNET_NID_ANY,
475 IOC_LIBCFS_ADD_PEER_NI,
476 &data, err_str, "add");
481 /* add the rest of the nids to the key nid if any are available */
482 for (idx = nid0_used ? 1 : 0 ; nids && idx < num_nids; idx++) {
484 * If prim_nid is not provided then the first nid in the
485 * list becomes the prim_nid. First time round the loop use
486 * LNET_NID_ANY for the first parameter, then use nid[0]
487 * as the key nid after wards
489 rc = dispatch_peer_ni_cmd(prim_nid, nids[idx],
490 IOC_LIBCFS_ADD_PEER_NI, &data,
500 cYAML_build_error(rc, seq_no, ADD_CMD, "peer_ni", err_str, err_rc);
504 int lustre_lnet_del_peer_nid(char *pnid, char **nid, int num_nids,
505 int seq_no, struct cYAML **err_rc)
507 struct lnet_ioctl_peer_cfg data;
509 int rc = LUSTRE_CFG_RC_NO_ERR;
511 char err_str[LNET_MAX_STR_LEN] = {0};
512 lnet_nid_t *nids = allocate_create_nid_array(nid, num_nids, err_str);
515 snprintf(err_str, sizeof(err_str),
516 "\"Primary nid is not provided\"");
517 rc = LUSTRE_CFG_RC_MISSING_PARAM;
520 prim_nid = libcfs_str2nid(pnid);
521 if (prim_nid == LNET_NID_ANY) {
522 rc = LUSTRE_CFG_RC_BAD_PARAM;
523 snprintf(err_str, sizeof(err_str),
530 snprintf(err_str, sizeof(err_str), "\"Success\"");
532 LIBCFS_IOC_INIT_V2(data, prcfg_hdr);
533 if (!nids || nids[0] == LNET_NID_ANY) {
534 rc = dispatch_peer_ni_cmd(prim_nid, LNET_NID_ANY,
535 IOC_LIBCFS_DEL_PEER_NI,
536 &data, err_str, "del");
540 for (idx = 0; nids && idx < num_nids; idx++) {
541 rc = dispatch_peer_ni_cmd(prim_nid, nids[idx],
542 IOC_LIBCFS_DEL_PEER_NI, &data,
552 cYAML_build_error(rc, seq_no, DEL_CMD, "peer_ni", err_str, err_rc);
556 int lustre_lnet_config_route(char *nw, char *gw, int hops, int prio,
557 int seq_no, struct cYAML **err_rc)
559 struct lnet_ioctl_config_data data;
560 lnet_nid_t gateway_nid;
561 int rc = LUSTRE_CFG_RC_NO_ERR;
562 __u32 net = LNET_NIDNET(LNET_NID_ANY);
563 char err_str[LNET_MAX_STR_LEN];
565 snprintf(err_str, sizeof(err_str), "\"Success\"");
567 if (nw == NULL || gw == NULL) {
570 "\"missing mandatory parameter(s): '%s'\"",
571 (nw == NULL && gw == NULL) ? "network, gateway" :
572 (nw == NULL) ? "network" : "gateway");
573 rc = LUSTRE_CFG_RC_MISSING_PARAM;
577 net = libcfs_str2net(nw);
578 if (net == LNET_NIDNET(LNET_NID_ANY)) {
581 "\"cannot parse net %s\"", nw);
582 rc = LUSTRE_CFG_RC_BAD_PARAM;
586 gateway_nid = libcfs_str2nid(gw);
587 if (gateway_nid == LNET_NID_ANY) {
590 "\"cannot parse gateway NID '%s'\"", gw);
591 rc = LUSTRE_CFG_RC_BAD_PARAM;
596 /* hops is undefined */
597 hops = LNET_UNDEFINED_HOPS;
598 } else if (hops < 1 || hops > 255) {
601 "\"invalid hop count %d, must be between 1 and 255\"",
603 rc = LUSTRE_CFG_RC_OUT_OF_RANGE_PARAM;
609 } else if (prio < 0) {
612 "\"invalid priority %d, must be greater than 0\"",
614 rc = LUSTRE_CFG_RC_OUT_OF_RANGE_PARAM;
618 LIBCFS_IOC_INIT_V2(data, cfg_hdr);
620 data.cfg_config_u.cfg_route.rtr_hop = hops;
621 data.cfg_config_u.cfg_route.rtr_priority = prio;
622 data.cfg_nid = gateway_nid;
624 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_ADD_ROUTE, &data);
629 "\"cannot add route: %s\"", strerror(errno));
634 cYAML_build_error(rc, seq_no, ADD_CMD, "route", err_str, err_rc);
639 int lustre_lnet_del_route(char *nw, char *gw,
640 int seq_no, struct cYAML **err_rc)
642 struct lnet_ioctl_config_data data;
643 lnet_nid_t gateway_nid;
644 int rc = LUSTRE_CFG_RC_NO_ERR;
645 __u32 net = LNET_NIDNET(LNET_NID_ANY);
646 char err_str[LNET_MAX_STR_LEN];
648 snprintf(err_str, sizeof(err_str), "\"Success\"");
650 if (nw == NULL || gw == NULL) {
653 "\"missing mandatory parameter(s): '%s'\"",
654 (nw == NULL && gw == NULL) ? "network, gateway" :
655 (nw == NULL) ? "network" : "gateway");
656 rc = LUSTRE_CFG_RC_MISSING_PARAM;
660 net = libcfs_str2net(nw);
661 if (net == LNET_NIDNET(LNET_NID_ANY)) {
664 "\"cannot parse net '%s'\"", nw);
665 rc = LUSTRE_CFG_RC_BAD_PARAM;
669 gateway_nid = libcfs_str2nid(gw);
670 if (gateway_nid == LNET_NID_ANY) {
673 "\"cannot parse gateway NID '%s'\"", gw);
674 rc = LUSTRE_CFG_RC_BAD_PARAM;
678 LIBCFS_IOC_INIT_V2(data, cfg_hdr);
680 data.cfg_nid = gateway_nid;
682 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_DEL_ROUTE, &data);
687 "\"cannot delete route: %s\"", strerror(errno));
692 cYAML_build_error(rc, seq_no, DEL_CMD, "route", err_str, err_rc);
697 int lustre_lnet_show_route(char *nw, char *gw, int hops, int prio, int detail,
698 int seq_no, struct cYAML **show_rc,
699 struct cYAML **err_rc)
701 struct lnet_ioctl_config_data data;
702 lnet_nid_t gateway_nid;
703 int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
705 __u32 net = LNET_NIDNET(LNET_NID_ANY);
707 struct cYAML *root = NULL, *route = NULL, *item = NULL;
708 struct cYAML *first_seq = NULL;
709 char err_str[LNET_MAX_STR_LEN];
712 snprintf(err_str, sizeof(err_str),
713 "\"out of memory\"");
716 net = libcfs_str2net(nw);
717 if (net == LNET_NIDNET(LNET_NID_ANY)) {
720 "\"cannot parse net '%s'\"", nw);
721 rc = LUSTRE_CFG_RC_BAD_PARAM;
726 /* show all routes without filtering on net */
727 net = LNET_NIDNET(LNET_NID_ANY);
731 gateway_nid = libcfs_str2nid(gw);
732 if (gateway_nid == LNET_NID_ANY) {
735 "\"cannot parse gateway NID '%s'\"", gw);
736 rc = LUSTRE_CFG_RC_BAD_PARAM;
740 /* show all routes with out filtering on gateway */
741 gateway_nid = LNET_NID_ANY;
743 if ((hops < 1 && hops != -1) || hops > 255) {
746 "\"invalid hop count %d, must be between 0 and 256\"",
748 rc = LUSTRE_CFG_RC_OUT_OF_RANGE_PARAM;
752 /* create struct cYAML root object */
753 root = cYAML_create_object(NULL, NULL);
757 route = cYAML_create_seq(root, "route");
762 LIBCFS_IOC_INIT_V2(data, cfg_hdr);
765 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_ROUTE, &data);
771 /* filter on provided data */
772 if (net != LNET_NIDNET(LNET_NID_ANY) &&
776 if (gateway_nid != LNET_NID_ANY &&
777 gateway_nid != data.cfg_nid)
781 hops != data.cfg_config_u.cfg_route.rtr_hop)
785 prio != data.cfg_config_u.cfg_route.rtr_priority)
788 /* default rc to -1 incase we hit the goto */
792 item = cYAML_create_seq_item(route);
796 if (first_seq == NULL)
799 if (cYAML_create_string(item, "net",
800 libcfs_net2str(data.cfg_net)) == NULL)
803 if (cYAML_create_string(item, "gateway",
804 libcfs_nid2str(data.cfg_nid)) == NULL)
808 if (cYAML_create_number(item, "hop",
809 (int) data.cfg_config_u.
810 cfg_route.rtr_hop) ==
814 if (cYAML_create_number(item, "priority",
816 cfg_route.rtr_priority) == NULL)
819 if (cYAML_create_string(item, "state",
820 data.cfg_config_u.cfg_route.
822 "up" : "down") == NULL)
827 /* print output iff show_rc is not provided */
829 cYAML_print_tree(root);
831 if (l_errno != ENOENT) {
834 "\"cannot get routes: %s\"",
839 rc = LUSTRE_CFG_RC_NO_ERR;
841 snprintf(err_str, sizeof(err_str), "\"success\"");
843 if (show_rc == NULL || rc != LUSTRE_CFG_RC_NO_ERR || !exist) {
844 cYAML_free_tree(root);
845 } else if (show_rc != NULL && *show_rc != NULL) {
846 struct cYAML *show_node;
847 /* find the route node, if one doesn't exist then
848 * insert one. Otherwise add to the one there
850 show_node = cYAML_get_object_item(*show_rc, "route");
851 if (show_node != NULL && cYAML_is_sequence(show_node)) {
852 cYAML_insert_child(show_node, first_seq);
855 } else if (show_node == NULL) {
856 cYAML_insert_sibling((*show_rc)->cy_child,
860 cYAML_free_tree(root);
866 cYAML_build_error(rc, seq_no, SHOW_CMD, "route", err_str, err_rc);
871 static int socket_intf_query(int request, char *intf,
877 if (strlen(intf) >= IFNAMSIZ || ifr == NULL)
878 return LUSTRE_CFG_RC_BAD_PARAM;
880 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
882 return LUSTRE_CFG_RC_BAD_PARAM;
884 strcpy(ifr->ifr_name, intf);
885 rc = ioctl(sockfd, request, ifr);
887 rc = LUSTRE_CFG_RC_BAD_PARAM;
895 * for each interface in the array of interfaces find the IP address of
896 * that interface, create its nid and add it to an array of NIDs.
897 * Stop if any of the interfaces is down
899 static int lustre_lnet_intf2nids(struct lnet_dlc_network_descr *nw,
900 lnet_nid_t **nids, __u32 *nnids)
902 int i = 0, count = 0, rc;
905 struct lnet_dlc_intf_descr *intf;
907 if (nw == NULL || nids == NULL)
908 return LUSTRE_CFG_RC_BAD_PARAM;
910 list_for_each_entry(intf, &nw->nw_intflist, intf_on_network)
913 *nids = calloc(count, sizeof(lnet_nid_t));
915 return LUSTRE_CFG_RC_OUT_OF_MEM;
917 list_for_each_entry(intf, &nw->nw_intflist, intf_on_network) {
918 memset(&ifr, 0, sizeof(ifr));
919 rc = socket_intf_query(SIOCGIFFLAGS, intf->intf_name, &ifr);
923 if ((ifr.ifr_flags & IFF_UP) == 0) {
924 rc = LUSTRE_CFG_RC_BAD_PARAM;
928 memset(&ifr, 0, sizeof(ifr));
929 rc = socket_intf_query(SIOCGIFADDR, intf->intf_name, &ifr);
933 ip = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
935 (*nids)[i] = LNET_MKNID(nw->nw_id, ip);
950 * called repeatedly until a match or no more ip range
952 * ip_range expression
953 * interface list with all the interface names.
954 * all the interfaces in the system.
956 * try to match the ip_range expr to one of the interfaces' IPs in
957 * the system. If we hit a patch for an interface. Check if that
958 * interface name is in the list.
960 * If there are more than one interface in the list, then make sure
961 * that the IPs for all of these interfaces match the ip ranges
964 * for each interface in intf_list
965 * look up the intf name in ifa
966 * if not there then no match
967 * check ip obtained from ifa against a match to any of the
969 * If no match, then fail
971 * The result is that all the interfaces have to match.
973 int lustre_lnet_match_ip_to_intf(struct ifaddrs *ifa,
974 struct list_head *intf_list,
975 struct list_head *ip_ranges)
979 struct lnet_dlc_intf_descr *intf_descr, *tmp;
980 struct ifaddrs *ifaddr = ifa;
981 struct lustre_lnet_ip_range_descr *ip_range;
985 * if there are no explicit interfaces, and no ip ranges, then
986 * configure the first tcp interface we encounter.
988 if (list_empty(intf_list) && list_empty(ip_ranges)) {
989 for (ifaddr = ifa; ifaddr != NULL; ifaddr = ifaddr->ifa_next) {
990 if (ifaddr->ifa_addr == NULL)
993 if ((ifaddr->ifa_flags & IFF_UP) == 0)
996 family = ifaddr->ifa_addr->sa_family;
997 if (family == AF_INET &&
998 strcmp(ifaddr->ifa_name, "lo") != 0) {
999 rc = lustre_lnet_add_intf_descr
1000 (intf_list, ifaddr->ifa_name,
1001 strlen(ifaddr->ifa_name));
1003 if (rc != LUSTRE_CFG_RC_NO_ERR)
1006 return LUSTRE_CFG_RC_MATCH;
1009 return LUSTRE_CFG_RC_NO_MATCH;
1013 * First interface which matches an IP pattern will be used
1015 if (list_empty(intf_list)) {
1017 * no interfaces provided in the rule, but an ip range is
1018 * provided, so try and match an interface to the ip
1021 for (ifaddr = ifa; ifaddr != NULL; ifaddr = ifaddr->ifa_next) {
1022 if (ifaddr->ifa_addr == NULL)
1025 if ((ifaddr->ifa_flags & IFF_UP) == 0)
1028 family = ifaddr->ifa_addr->sa_family;
1029 if (family == AF_INET) {
1030 ip = ((struct sockaddr_in *)ifaddr->ifa_addr)->
1033 list_for_each_entry(ip_range, ip_ranges,
1035 rc = cfs_ip_addr_match(bswap_32(ip),
1036 &ip_range->ipr_expr);
1040 rc = lustre_lnet_add_intf_descr
1041 (intf_list, ifaddr->ifa_name,
1042 strlen(ifaddr->ifa_name));
1044 if (rc != LUSTRE_CFG_RC_NO_ERR)
1050 if (!list_empty(intf_list))
1051 return LUSTRE_CFG_RC_MATCH;
1053 return LUSTRE_CFG_RC_NO_MATCH;
1057 * If an interface is explicitly specified the ip-range might or
1058 * might not be specified. if specified the interface needs to match the
1059 * ip-range. If no ip-range then the interfaces are
1060 * automatically matched if they are all up.
1061 * If > 1 interfaces all the interfaces must match for the NI to
1064 list_for_each_entry_safe(intf_descr, tmp, intf_list, intf_on_network) {
1065 for (ifaddr = ifa; ifaddr != NULL; ifaddr = ifaddr->ifa_next) {
1066 if (ifaddr->ifa_addr == NULL)
1069 family = ifaddr->ifa_addr->sa_family;
1070 if (family == AF_INET &&
1071 strcmp(intf_descr->intf_name,
1072 ifaddr->ifa_name) == 0)
1076 if (ifaddr == NULL) {
1077 list_del(&intf_descr->intf_on_network);
1078 free_intf_descr(intf_descr);
1082 if ((ifaddr->ifa_flags & IFF_UP) == 0) {
1083 list_del(&intf_descr->intf_on_network);
1084 free_intf_descr(intf_descr);
1088 ip = ((struct sockaddr_in *)ifaddr->ifa_addr)->sin_addr.s_addr;
1091 list_for_each_entry(ip_range, ip_ranges, ipr_entry) {
1092 rc = cfs_ip_addr_match(bswap_32(ip), &ip_range->ipr_expr);
1098 /* no match for this interface */
1099 list_del(&intf_descr->intf_on_network);
1100 free_intf_descr(intf_descr);
1104 return LUSTRE_CFG_RC_MATCH;
1107 int lustre_lnet_resolve_ip2nets_rule(struct lustre_lnet_ip2nets *ip2nets,
1108 lnet_nid_t **nids, __u32 *nnids)
1110 struct ifaddrs *ifa;
1111 int rc = LUSTRE_CFG_RC_NO_ERR;
1113 rc = getifaddrs(&ifa);
1117 rc = lustre_lnet_match_ip_to_intf(ifa,
1118 &ip2nets->ip2nets_net.nw_intflist,
1119 &ip2nets->ip2nets_ip_ranges);
1120 if (rc != LUSTRE_CFG_RC_MATCH) {
1125 rc = lustre_lnet_intf2nids(&ip2nets->ip2nets_net, nids, nnids);
1126 if (rc != LUSTRE_CFG_RC_NO_ERR) {
1137 lustre_lnet_ioctl_config_ni(struct list_head *intf_list,
1138 struct lnet_ioctl_config_lnd_tunables *tunables,
1139 struct cfs_expr_list *global_cpts,
1140 lnet_nid_t *nids, char *err_str)
1143 struct lnet_ioctl_config_ni *conf;
1144 struct lnet_ioctl_config_lnd_tunables *tun = NULL;
1145 int rc = LUSTRE_CFG_RC_NO_ERR, i = 0;
1148 struct lnet_dlc_intf_descr *intf_descr;
1150 struct cfs_expr_list *cpt_expr;
1152 list_for_each_entry(intf_descr, intf_list,
1154 if (tunables != NULL)
1155 len = sizeof(struct lnet_ioctl_config_ni) +
1156 sizeof(struct lnet_ioctl_config_lnd_tunables);
1158 len = sizeof(struct lnet_ioctl_config_ni);
1160 data = calloc(1, len);
1162 return LUSTRE_CFG_RC_OUT_OF_MEM;
1163 conf = (struct lnet_ioctl_config_ni*) data;
1164 if (tunables != NULL)
1165 tun = (struct lnet_ioctl_config_lnd_tunables*)
1168 LIBCFS_IOC_INIT_V2(*conf, lic_cfg_hdr);
1169 conf->lic_cfg_hdr.ioc_len = len;
1170 conf->lic_nid = nids[i];
1171 strncpy(conf->lic_ni_intf[0], intf_descr->intf_name,
1174 if (intf_descr->cpt_expr != NULL)
1175 cpt_expr = intf_descr->cpt_expr;
1176 else if (global_cpts != NULL)
1177 cpt_expr = global_cpts;
1181 if (cpt_expr != NULL) {
1182 count = cfs_expr_list_values(cpt_expr,
1183 LNET_MAX_SHOW_NUM_CPT,
1186 memcpy(conf->lic_cpts, cpt_array,
1187 sizeof(cpt_array[0]) * LNET_MAX_STR_LEN);
1196 conf->lic_ncpts = count;
1198 if (tunables != NULL)
1199 memcpy(tun, tunables, sizeof(*tunables));
1201 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_ADD_LOCAL_NI, data);
1206 "\"cannot add network: %s\"", strerror(errno));
1214 return LUSTRE_CFG_RC_NO_ERR;
1218 lustre_lnet_config_ip2nets(struct lustre_lnet_ip2nets *ip2nets,
1219 struct lnet_ioctl_config_lnd_tunables *tunables,
1220 struct cfs_expr_list *global_cpts,
1221 int seq_no, struct cYAML **err_rc)
1223 lnet_nid_t *nids = NULL;
1226 char err_str[LNET_MAX_STR_LEN];
1228 snprintf(err_str, sizeof(err_str), "\"success\"");
1233 "\"incomplete ip2nets information\"");
1234 rc = LUSTRE_CFG_RC_BAD_PARAM;
1239 * call below function to resolve the rules into a list of nids.
1240 * The memory is allocated in that function then freed here when
1241 * it's no longer needed.
1243 rc = lustre_lnet_resolve_ip2nets_rule(ip2nets, &nids, &nnids);
1244 if (rc != LUSTRE_CFG_RC_NO_ERR && rc != LUSTRE_CFG_RC_MATCH) {
1247 "\"cannot resolve ip2nets rule\"");
1251 if (list_empty(&ip2nets->ip2nets_net.nw_intflist)) {
1252 snprintf(err_str, sizeof(err_str),
1253 "\"no interfaces match ip2nets rules\"");
1257 rc = lustre_lnet_ioctl_config_ni(&ip2nets->ip2nets_net.nw_intflist,
1258 tunables, global_cpts, nids,
1265 cYAML_build_error(rc, seq_no, ADD_CMD, "ip2nets", err_str, err_rc);
1269 int lustre_lnet_config_ni(struct lnet_dlc_network_descr *nw_descr,
1270 struct cfs_expr_list *global_cpts,
1272 struct lnet_ioctl_config_lnd_tunables *tunables,
1273 int seq_no, struct cYAML **err_rc)
1276 struct lnet_ioctl_config_ni *conf;
1277 struct lnet_ioctl_config_lnd_tunables *tun = NULL;
1278 char buf[LNET_MAX_STR_LEN];
1279 int rc = LUSTRE_CFG_RC_NO_ERR;
1280 char err_str[LNET_MAX_STR_LEN];
1281 lnet_nid_t *nids = NULL;
1285 struct lnet_dlc_intf_descr *intf_descr, *tmp;
1288 snprintf(err_str, sizeof(err_str), "\"success\"");
1290 if (ip2net == NULL && nw_descr == NULL) {
1293 "\"mandatory parameters not specified.\"");
1294 rc = LUSTRE_CFG_RC_MISSING_PARAM;
1298 if (ip2net != NULL && strlen(ip2net) >= sizeof(buf)) {
1301 "\"ip2net string too long %d\"",
1302 (int)strlen(ip2net));
1303 rc = LUSTRE_CFG_RC_OUT_OF_RANGE_PARAM;
1307 if (ip2net != NULL) {
1308 if (tunables != NULL)
1309 len = sizeof(struct lnet_ioctl_config_ni) +
1310 sizeof(struct lnet_ioctl_config_lnd_tunables);
1312 len = sizeof(struct lnet_ioctl_config_ni);
1313 data = calloc(1, len);
1315 rc = LUSTRE_CFG_RC_OUT_OF_MEM;
1318 conf = (struct lnet_ioctl_config_ni*) data;
1319 if (tunables != NULL)
1320 tun = (struct lnet_ioctl_config_lnd_tunables*)
1321 (data + sizeof(*conf));
1323 LIBCFS_IOC_INIT_V2(*conf, lic_cfg_hdr);
1324 conf->lic_cfg_hdr.ioc_len = len;
1325 strncpy(conf->lic_legacy_ip2nets, ip2net,
1328 if (global_cpts != NULL) {
1329 count = cfs_expr_list_values(global_cpts,
1330 LNET_MAX_SHOW_NUM_CPT,
1333 memcpy(conf->lic_cpts, cpt_array,
1334 sizeof(cpt_array[0]) * LNET_MAX_STR_LEN);
1343 conf->lic_ncpts = count;
1345 if (tunables != NULL)
1346 memcpy(tun, tunables, sizeof(*tunables));
1348 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_ADD_LOCAL_NI, data);
1353 "\"cannot add network: %s\"", strerror(errno));
1360 if (LNET_NETTYP(nw_descr->nw_id) == LOLND) {
1361 rc = LUSTRE_CFG_RC_NO_ERR;
1365 if (nw_descr->nw_id == LNET_NIDNET(LNET_NID_ANY)) {
1368 "\"cannot parse net '%s'\"",
1369 libcfs_net2str(nw_descr->nw_id));
1370 rc = LUSTRE_CFG_RC_BAD_PARAM;
1374 if (list_empty(&nw_descr->nw_intflist)) {
1377 "\"no interface name provided\"");
1378 rc = LUSTRE_CFG_RC_BAD_PARAM;
1382 rc = lustre_lnet_intf2nids(nw_descr, &nids, &nnids);
1384 snprintf(err_str, sizeof(err_str),
1385 "\"bad parameter\"");
1386 rc = LUSTRE_CFG_RC_BAD_PARAM;
1390 rc = lustre_lnet_ioctl_config_ni(&nw_descr->nw_intflist,
1391 tunables, global_cpts, nids,
1395 if (nw_descr != NULL) {
1396 list_for_each_entry_safe(intf_descr, tmp,
1397 &nw_descr->nw_intflist,
1399 list_del(&intf_descr->intf_on_network);
1400 free_intf_descr(intf_descr);
1404 cYAML_build_error(rc, seq_no, ADD_CMD, "net", err_str, err_rc);
1415 int lustre_lnet_del_ni(struct lnet_dlc_network_descr *nw_descr,
1416 int seq_no, struct cYAML **err_rc)
1418 struct lnet_ioctl_config_ni data;
1419 int rc = LUSTRE_CFG_RC_NO_ERR, i;
1420 char err_str[LNET_MAX_STR_LEN];
1421 lnet_nid_t *nids = NULL;
1423 struct lnet_dlc_intf_descr *intf_descr, *tmp;
1425 snprintf(err_str, sizeof(err_str), "\"success\"");
1427 if (nw_descr == NULL) {
1430 "\"missing mandatory parameter\"");
1431 rc = LUSTRE_CFG_RC_MISSING_PARAM;
1435 if (LNET_NETTYP(nw_descr->nw_id) == LOLND)
1436 return LUSTRE_CFG_RC_NO_ERR;
1438 if (nw_descr->nw_id == LNET_NIDNET(LNET_NID_ANY)) {
1441 "\"cannot parse net '%s'\"",
1442 libcfs_net2str(nw_descr->nw_id));
1443 rc = LUSTRE_CFG_RC_BAD_PARAM;
1447 rc = lustre_lnet_intf2nids(nw_descr, &nids, &nnids);
1449 snprintf(err_str, sizeof(err_str),
1450 "\"bad parameter\"");
1451 rc = LUSTRE_CFG_RC_BAD_PARAM;
1456 * no interfaces just the nw_id is specified
1459 nids = calloc(1, sizeof(*nids));
1461 snprintf(err_str, sizeof(err_str),
1462 "\"out of memory\"");
1463 rc = LUSTRE_CFG_RC_OUT_OF_MEM;
1466 nids[0] = LNET_MKNID(nw_descr->nw_id, 0);
1470 for (i = 0; i < nnids; i++) {
1471 LIBCFS_IOC_INIT_V2(data, lic_cfg_hdr);
1472 data.lic_nid = nids[i];
1474 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_DEL_LOCAL_NI, &data);
1479 "\"cannot del network: %s\"", strerror(errno));
1483 list_for_each_entry_safe(intf_descr, tmp, &nw_descr->nw_intflist,
1485 list_del(&intf_descr->intf_on_network);
1486 free_intf_descr(intf_descr);
1490 cYAML_build_error(rc, seq_no, DEL_CMD, "net", err_str, err_rc);
1498 int lustre_lnet_show_net(char *nw, int detail, int seq_no,
1499 struct cYAML **show_rc, struct cYAML **err_rc)
1502 struct lnet_ioctl_config_ni *ni_data;
1503 struct lnet_ioctl_config_lnd_tunables *lnd;
1504 struct lnet_ioctl_element_stats *stats;
1505 __u32 net = LNET_NIDNET(LNET_NID_ANY);
1506 __u32 prev_net = LNET_NIDNET(LNET_NID_ANY);
1507 int rc = LUSTRE_CFG_RC_OUT_OF_MEM, i, j;
1509 struct cYAML *root = NULL, *tunables = NULL,
1510 *net_node = NULL, *interfaces = NULL,
1511 *item = NULL, *first_seq = NULL,
1512 *tmp = NULL, *statistics = NULL;
1513 int str_buf_len = LNET_MAX_SHOW_NUM_CPT * 2;
1514 char str_buf[str_buf_len];
1516 char err_str[LNET_MAX_STR_LEN];
1517 bool exist = false, new_net = true;
1519 size_t buf_size = sizeof(*ni_data) + sizeof(*lnd) + sizeof(*stats);
1521 snprintf(err_str, sizeof(err_str), "\"out of memory\"");
1523 buf = calloc(1, buf_size);
1527 ni_data = (struct lnet_ioctl_config_ni *)buf;
1530 net = libcfs_str2net(nw);
1531 if (net == LNET_NIDNET(LNET_NID_ANY)) {
1534 "\"cannot parse net '%s'\"", nw);
1535 rc = LUSTRE_CFG_RC_BAD_PARAM;
1540 root = cYAML_create_object(NULL, NULL);
1544 net_node = cYAML_create_seq(root, "net");
1545 if (net_node == NULL)
1552 memset(buf, 0, buf_size);
1554 LIBCFS_IOC_INIT_V2(*ni_data, lic_cfg_hdr);
1556 * set the ioc_len to the proper value since INIT assumes
1559 ni_data->lic_cfg_hdr.ioc_len = buf_size;
1560 ni_data->lic_idx = i;
1562 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_LOCAL_NI, ni_data);
1568 rc_net = LNET_NIDNET(ni_data->lic_nid);
1570 /* filter on provided data */
1571 if (net != LNET_NIDNET(LNET_NID_ANY) &&
1575 /* default rc to -1 in case we hit the goto */
1579 stats = (struct lnet_ioctl_element_stats *)ni_data->lic_bulk;
1580 lnd = (struct lnet_ioctl_config_lnd_tunables *)
1581 (ni_data->lic_bulk + sizeof(*stats));
1583 if (rc_net != prev_net) {
1590 if (!cYAML_create_string(net_node, "net type",
1591 libcfs_net2str(rc_net)))
1594 tmp = cYAML_create_seq(net_node, "local NI(s)");
1600 /* create the tree to be printed. */
1601 item = cYAML_create_seq_item(tmp);
1605 if (first_seq == NULL)
1608 if (cYAML_create_string(item, "nid",
1609 libcfs_nid2str(ni_data->lic_nid)) == NULL)
1612 if (cYAML_create_string(item,
1614 (ni_data->lic_status ==
1615 LNET_NI_STATUS_UP) ?
1616 "up" : "down") == NULL)
1619 /* don't add interfaces unless there is at least one
1621 if (strlen(ni_data->lic_ni_intf[0]) > 0) {
1622 interfaces = cYAML_create_object(item, "interfaces");
1623 if (interfaces == NULL)
1626 for (j = 0; j < LNET_NUM_INTERFACES; j++) {
1627 if (strlen(ni_data->lic_ni_intf[j]) > 0) {
1629 sizeof(str_buf), "%d", j);
1630 if (cYAML_create_string(interfaces,
1632 ni_data->lic_ni_intf[j]) ==
1642 statistics = cYAML_create_object(item, "statistics");
1643 if (statistics == NULL)
1646 if (cYAML_create_number(statistics, "send_count",
1647 stats->iel_send_count)
1651 if (cYAML_create_number(statistics, "recv_count",
1652 stats->iel_recv_count)
1656 if (cYAML_create_number(statistics, "drop_count",
1657 stats->iel_drop_count)
1661 tunables = cYAML_create_object(item, "tunables");
1665 rc = lustre_net_show_tunables(tunables, &lnd->lt_cmn);
1666 if (rc != LUSTRE_CFG_RC_NO_ERR)
1669 tunables = cYAML_create_object(item, "lnd tunables");
1670 if (tunables == NULL)
1673 rc = lustre_ni_show_tunables(tunables, LNET_NETTYP(rc_net),
1675 if (rc != LUSTRE_CFG_RC_NO_ERR)
1678 if (cYAML_create_number(item, "tcp bonding",
1679 ni_data->lic_tcp_bonding)
1683 if (cYAML_create_number(item, "dev cpt",
1684 ni_data->lic_dev_cpt) == NULL)
1687 /* out put the CPTs in the format: "[x,x,x,...]" */
1688 limit = str_buf + str_buf_len - 3;
1689 pos += snprintf(pos, limit - pos, "\"[");
1690 for (j = 0 ; ni_data->lic_ncpts >= 1 &&
1691 j < ni_data->lic_ncpts &&
1693 pos += snprintf(pos, limit - pos,
1694 "%d", ni_data->lic_cpts[j]);
1695 if ((j + 1) < ni_data->lic_ncpts)
1696 pos += snprintf(pos, limit - pos, ",");
1698 pos += snprintf(pos, 3, "]\"");
1700 if (ni_data->lic_ncpts >= 1 &&
1701 cYAML_create_string(item, "CPT",
1707 /* Print out the net information only if show_rc is not provided */
1708 if (show_rc == NULL)
1709 cYAML_print_tree(root);
1711 if (l_errno != ENOENT) {
1714 "\"cannot get networks: %s\"",
1719 rc = LUSTRE_CFG_RC_NO_ERR;
1721 snprintf(err_str, sizeof(err_str), "\"success\"");
1723 if (show_rc == NULL || rc != LUSTRE_CFG_RC_NO_ERR || !exist) {
1724 cYAML_free_tree(root);
1725 } else if (show_rc != NULL && *show_rc != NULL) {
1726 struct cYAML *show_node;
1727 /* find the net node, if one doesn't exist
1728 * then insert one. Otherwise add to the one there
1730 show_node = cYAML_get_object_item(*show_rc, "net");
1731 if (show_node != NULL && cYAML_is_sequence(show_node)) {
1732 cYAML_insert_child(show_node, first_seq);
1735 } else if (show_node == NULL) {
1736 cYAML_insert_sibling((*show_rc)->cy_child,
1740 cYAML_free_tree(root);
1746 cYAML_build_error(rc, seq_no, SHOW_CMD, "net", err_str, err_rc);
1751 int lustre_lnet_enable_routing(int enable, int seq_no, struct cYAML **err_rc)
1753 struct lnet_ioctl_config_data data;
1754 int rc = LUSTRE_CFG_RC_NO_ERR;
1755 char err_str[LNET_MAX_STR_LEN];
1757 snprintf(err_str, sizeof(err_str), "\"success\"");
1759 LIBCFS_IOC_INIT_V2(data, cfg_hdr);
1760 data.cfg_config_u.cfg_buffers.buf_enable = (enable) ? 1 : 0;
1762 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_CONFIG_RTR, &data);
1767 "\"cannot %s routing %s\"",
1768 (enable) ? "enable" : "disable", strerror(errno));
1773 cYAML_build_error(rc, seq_no,
1774 (enable) ? ADD_CMD : DEL_CMD,
1775 "routing", err_str, err_rc);
1780 int lustre_lnet_config_numa_range(int range, int seq_no, struct cYAML **err_rc)
1782 struct lnet_ioctl_numa_range data;
1783 int rc = LUSTRE_CFG_RC_NO_ERR;
1784 char err_str[LNET_MAX_STR_LEN];
1786 snprintf(err_str, sizeof(err_str), "\"success\"");
1791 "\"range must be >= 0\"");
1792 rc = LUSTRE_CFG_RC_OUT_OF_RANGE_PARAM;
1796 LIBCFS_IOC_INIT_V2(data, nr_hdr);
1797 data.nr_range = range;
1799 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_SET_NUMA_RANGE, &data);
1804 "\"cannot configure buffers: %s\"", strerror(errno));
1809 cYAML_build_error(rc, seq_no, ADD_CMD, "numa_range", err_str, err_rc);
1814 int lustre_lnet_config_buffers(int tiny, int small, int large, int seq_no,
1815 struct cYAML **err_rc)
1817 struct lnet_ioctl_config_data data;
1818 int rc = LUSTRE_CFG_RC_NO_ERR;
1819 char err_str[LNET_MAX_STR_LEN];
1821 snprintf(err_str, sizeof(err_str), "\"success\"");
1823 /* -1 indicates to ignore changes to this field */
1824 if (tiny < -1 || small < -1 || large < -1) {
1827 "\"tiny, small and large must be >= 0\"");
1828 rc = LUSTRE_CFG_RC_OUT_OF_RANGE_PARAM;
1832 LIBCFS_IOC_INIT_V2(data, cfg_hdr);
1833 data.cfg_config_u.cfg_buffers.buf_tiny = tiny;
1834 data.cfg_config_u.cfg_buffers.buf_small = small;
1835 data.cfg_config_u.cfg_buffers.buf_large = large;
1837 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_ADD_BUF, &data);
1842 "\"cannot configure buffers: %s\"", strerror(errno));
1847 cYAML_build_error(rc, seq_no, ADD_CMD, "buf", err_str, err_rc);
1852 int lustre_lnet_show_routing(int seq_no, struct cYAML **show_rc,
1853 struct cYAML **err_rc)
1855 struct lnet_ioctl_config_data *data;
1856 struct lnet_ioctl_pool_cfg *pool_cfg = NULL;
1857 int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
1860 char *pools[LNET_NRBPOOLS] = {"tiny", "small", "large"};
1861 int buf_count[LNET_NRBPOOLS] = {0};
1862 struct cYAML *root = NULL, *pools_node = NULL,
1863 *type_node = NULL, *item = NULL, *cpt = NULL,
1864 *first_seq = NULL, *buffers = NULL;
1866 char err_str[LNET_MAX_STR_LEN];
1867 char node_name[LNET_MAX_STR_LEN];
1870 snprintf(err_str, sizeof(err_str), "\"out of memory\"");
1872 buf = calloc(1, sizeof(*data) + sizeof(*pool_cfg));
1876 data = (struct lnet_ioctl_config_data *)buf;
1878 root = cYAML_create_object(NULL, NULL);
1882 pools_node = cYAML_create_seq(root, "routing");
1883 if (pools_node == NULL)
1887 LIBCFS_IOC_INIT_V2(*data, cfg_hdr);
1888 data->cfg_hdr.ioc_len = sizeof(struct lnet_ioctl_config_data) +
1889 sizeof(struct lnet_ioctl_pool_cfg);
1890 data->cfg_count = i;
1892 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_BUF, data);
1900 pool_cfg = (struct lnet_ioctl_pool_cfg *)data->cfg_bulk;
1902 snprintf(node_name, sizeof(node_name), "cpt[%d]", i);
1903 item = cYAML_create_seq_item(pools_node);
1907 if (first_seq == NULL)
1910 cpt = cYAML_create_object(item, node_name);
1914 /* create the tree and print */
1915 for (j = 0; j < LNET_NRBPOOLS; j++) {
1916 type_node = cYAML_create_object(cpt, pools[j]);
1917 if (type_node == NULL)
1919 if (cYAML_create_number(type_node, "npages",
1920 pool_cfg->pl_pools[j].pl_npages)
1923 if (cYAML_create_number(type_node, "nbuffers",
1924 pool_cfg->pl_pools[j].
1925 pl_nbuffers) == NULL)
1927 if (cYAML_create_number(type_node, "credits",
1928 pool_cfg->pl_pools[j].
1929 pl_credits) == NULL)
1931 if (cYAML_create_number(type_node, "mincredits",
1932 pool_cfg->pl_pools[j].
1933 pl_mincredits) == NULL)
1935 /* keep track of the total count for each of the
1936 * tiny, small and large buffers */
1937 buf_count[j] += pool_cfg->pl_pools[j].pl_nbuffers;
1941 if (pool_cfg != NULL) {
1942 item = cYAML_create_seq_item(pools_node);
1946 if (cYAML_create_number(item, "enable", pool_cfg->pl_routing) ==
1951 /* create a buffers entry in the show. This is necessary so that
1952 * if the YAML output is used to configure a node, the buffer
1953 * configuration takes hold */
1954 buffers = cYAML_create_object(root, "buffers");
1955 if (buffers == NULL)
1958 for (i = 0; i < LNET_NRBPOOLS; i++) {
1959 if (cYAML_create_number(buffers, pools[i], buf_count[i]) == NULL)
1963 if (show_rc == NULL)
1964 cYAML_print_tree(root);
1966 if (l_errno != ENOENT) {
1969 "\"cannot get routing information: %s\"",
1974 rc = LUSTRE_CFG_RC_NO_ERR;
1976 snprintf(err_str, sizeof(err_str), "\"success\"");
1977 rc = LUSTRE_CFG_RC_NO_ERR;
1981 if (show_rc == NULL || rc != LUSTRE_CFG_RC_NO_ERR || !exist) {
1982 cYAML_free_tree(root);
1983 } else if (show_rc != NULL && *show_rc != NULL) {
1984 struct cYAML *routing_node;
1985 /* there should exist only one routing block and one
1986 * buffers block. If there already exists a previous one
1987 * then don't add another */
1988 routing_node = cYAML_get_object_item(*show_rc, "routing");
1989 if (routing_node == NULL) {
1990 cYAML_insert_sibling((*show_rc)->cy_child,
1994 cYAML_free_tree(root);
2000 cYAML_build_error(rc, seq_no, SHOW_CMD, "routing", err_str, err_rc);
2005 int lustre_lnet_show_peer(char *knid, int detail, int seq_no,
2006 struct cYAML **show_rc, struct cYAML **err_rc)
2009 * TODO: This function is changing in a future patch to accommodate
2010 * PEER_LIST and proper filtering on any nid of the peer
2012 struct lnet_ioctl_peer_cfg peer_info;
2013 struct lnet_peer_ni_credit_info *lpni_cri;
2014 struct lnet_ioctl_element_stats *lpni_stats;
2015 int rc = LUSTRE_CFG_RC_OUT_OF_MEM, ncpt = 0, i = 0, j = 0;
2017 struct cYAML *root = NULL, *peer = NULL, *peer_ni = NULL,
2018 *first_seq = NULL, *peer_root = NULL, *tmp = NULL;
2019 char err_str[LNET_MAX_STR_LEN];
2020 lnet_nid_t prev_primary_nid = LNET_NID_ANY, primary_nid = LNET_NID_ANY;
2021 int data_size = sizeof(*lpni_cri) + sizeof(*lpni_stats);
2022 char *data = malloc(data_size);
2023 bool new_peer = true;
2025 snprintf(err_str, sizeof(err_str),
2026 "\"out of memory\"");
2031 /* create struct cYAML root object */
2032 root = cYAML_create_object(NULL, NULL);
2036 peer_root = cYAML_create_seq(root, "peer");
2037 if (peer_root == NULL)
2041 primary_nid = libcfs_str2nid(knid);
2045 memset(data, 0, data_size);
2046 memset(&peer_info, 0, sizeof(peer_info));
2047 LIBCFS_IOC_INIT_V2(peer_info, prcfg_hdr);
2048 peer_info.prcfg_hdr.ioc_len = sizeof(peer_info);
2049 peer_info.prcfg_count = i;
2050 peer_info.prcfg_bulk = (void *)data;
2051 peer_info.prcfg_size = data_size;
2053 rc = l_ioctl(LNET_DEV_ID,
2054 IOC_LIBCFS_GET_PEER_NI, &peer_info);
2060 if (primary_nid != LNET_NID_ANY &&
2061 primary_nid != peer_info.prcfg_prim_nid)
2064 lpni_cri = peer_info.prcfg_bulk;
2065 lpni_stats = peer_info.prcfg_bulk + sizeof(*lpni_cri);
2067 peer = cYAML_create_seq_item(peer_root);
2071 if (peer_info.prcfg_prim_nid != prev_primary_nid) {
2072 prev_primary_nid = peer_info.prcfg_prim_nid;
2077 lnet_nid_t pnid = peer_info.prcfg_prim_nid;
2078 if (cYAML_create_string(peer, "primary nid",
2079 libcfs_nid2str(pnid))
2082 if (cYAML_create_string(peer, "Multi-Rail",
2083 peer_info.prcfg_mr ?
2087 tmp = cYAML_create_seq(peer, "peer ni");
2093 if (first_seq == NULL)
2096 peer_ni = cYAML_create_seq_item(tmp);
2097 if (peer_ni == NULL)
2100 if (cYAML_create_string(peer_ni, "nid",
2102 (peer_info.prcfg_cfg_nid))
2106 if (cYAML_create_string(peer_ni, "state",
2107 lpni_cri->cr_aliveness)
2114 if (cYAML_create_number(peer_ni, "max_ni_tx_credits",
2115 lpni_cri->cr_ni_peer_tx_credits)
2119 if (cYAML_create_number(peer_ni, "available_tx_credits",
2120 lpni_cri->cr_peer_tx_credits)
2124 if (cYAML_create_number(peer_ni, "min_tx_credits",
2125 lpni_cri->cr_peer_min_tx_credits)
2129 if (cYAML_create_number(peer_ni, "tx_q_num_of_buf",
2130 lpni_cri->cr_peer_tx_qnob)
2134 if (cYAML_create_number(peer_ni, "available_rtr_credits",
2135 lpni_cri->cr_peer_rtr_credits)
2139 if (cYAML_create_number(peer_ni, "min_rtr_credits",
2140 lpni_cri->cr_peer_min_rtr_credits)
2144 if (cYAML_create_number(peer_ni, "send_count",
2145 lpni_stats->iel_send_count)
2149 if (cYAML_create_number(peer_ni, "recv_count",
2150 lpni_stats->iel_recv_count)
2154 if (cYAML_create_number(peer_ni, "drop_count",
2155 lpni_stats->iel_drop_count)
2159 if (cYAML_create_number(peer_ni, "refcount",
2160 lpni_cri->cr_refcount) == NULL)
2164 if (l_errno != ENOENT) {
2167 "\"cannot get peer information: %s\"",
2176 /* print output iff show_rc is not provided */
2177 if (show_rc == NULL)
2178 cYAML_print_tree(root);
2180 snprintf(err_str, sizeof(err_str), "\"success\"");
2181 rc = LUSTRE_CFG_RC_NO_ERR;
2184 if (show_rc == NULL || rc != LUSTRE_CFG_RC_NO_ERR) {
2185 cYAML_free_tree(root);
2186 } else if (show_rc != NULL && *show_rc != NULL) {
2187 struct cYAML *show_node;
2188 /* find the peer node, if one doesn't exist then
2189 * insert one. Otherwise add to the one there
2191 show_node = cYAML_get_object_item(*show_rc,
2193 if (show_node != NULL && cYAML_is_sequence(show_node)) {
2194 cYAML_insert_child(show_node, first_seq);
2197 } else if (show_node == NULL) {
2198 cYAML_insert_sibling((*show_rc)->cy_child,
2202 cYAML_free_tree(root);
2208 cYAML_build_error(rc, seq_no, SHOW_CMD, "peer", err_str,
2214 int lustre_lnet_show_numa_range(int seq_no, struct cYAML **show_rc,
2215 struct cYAML **err_rc)
2217 struct lnet_ioctl_numa_range data;
2220 char err_str[LNET_MAX_STR_LEN];
2221 struct cYAML *root = NULL, *range = NULL;
2223 snprintf(err_str, sizeof(err_str), "\"out of memory\"");
2225 LIBCFS_IOC_INIT_V2(data, nr_hdr);
2227 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_NUMA_RANGE, &data);
2232 "\"cannot get numa range: %s\"",
2238 rc = LUSTRE_CFG_RC_OUT_OF_MEM;
2240 root = cYAML_create_object(NULL, NULL);
2244 range = cYAML_create_object(root, "numa");
2248 if (cYAML_create_number(range, "range",
2249 data.nr_range) == NULL)
2252 if (show_rc == NULL)
2253 cYAML_print_tree(root);
2255 snprintf(err_str, sizeof(err_str), "\"success\"");
2256 rc = LUSTRE_CFG_RC_NO_ERR;
2258 if (show_rc == NULL || rc != LUSTRE_CFG_RC_NO_ERR) {
2259 cYAML_free_tree(root);
2260 } else if (show_rc != NULL && *show_rc != NULL) {
2261 cYAML_insert_sibling((*show_rc)->cy_child,
2268 cYAML_build_error(rc, seq_no, SHOW_CMD, "numa", err_str, err_rc);
2273 int lustre_lnet_show_stats(int seq_no, struct cYAML **show_rc,
2274 struct cYAML **err_rc)
2276 struct lnet_ioctl_lnet_stats data;
2279 char err_str[LNET_MAX_STR_LEN];
2280 struct cYAML *root = NULL, *stats = NULL;
2282 snprintf(err_str, sizeof(err_str), "\"out of memory\"");
2284 LIBCFS_IOC_INIT_V2(data, st_hdr);
2286 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_LNET_STATS, &data);
2291 "\"cannot get lnet statistics: %s\"",
2297 rc = LUSTRE_CFG_RC_OUT_OF_MEM;
2299 root = cYAML_create_object(NULL, NULL);
2303 stats = cYAML_create_object(root, "statistics");
2307 if (cYAML_create_number(stats, "msgs_alloc",
2308 data.st_cntrs.msgs_alloc) == NULL)
2311 if (cYAML_create_number(stats, "msgs_max",
2312 data.st_cntrs.msgs_max) == NULL)
2315 if (cYAML_create_number(stats, "errors",
2316 data.st_cntrs.errors) == NULL)
2319 if (cYAML_create_number(stats, "send_count",
2320 data.st_cntrs.send_count) == NULL)
2323 if (cYAML_create_number(stats, "recv_count",
2324 data.st_cntrs.recv_count) == NULL)
2327 if (cYAML_create_number(stats, "route_count",
2328 data.st_cntrs.route_count) == NULL)
2331 if (cYAML_create_number(stats, "drop_count",
2332 data.st_cntrs.drop_count) == NULL)
2335 if (cYAML_create_number(stats, "send_length",
2336 data.st_cntrs.send_length) == NULL)
2339 if (cYAML_create_number(stats, "recv_length",
2340 data.st_cntrs.recv_length) == NULL)
2343 if (cYAML_create_number(stats, "route_length",
2344 data.st_cntrs.route_length) == NULL)
2347 if (cYAML_create_number(stats, "drop_length",
2348 data.st_cntrs.drop_length) == NULL)
2351 if (show_rc == NULL)
2352 cYAML_print_tree(root);
2354 snprintf(err_str, sizeof(err_str), "\"success\"");
2355 rc = LUSTRE_CFG_RC_NO_ERR;
2357 if (show_rc == NULL || rc != LUSTRE_CFG_RC_NO_ERR) {
2358 cYAML_free_tree(root);
2359 } else if (show_rc != NULL && *show_rc != NULL) {
2360 cYAML_insert_sibling((*show_rc)->cy_child,
2367 cYAML_build_error(rc, seq_no, SHOW_CMD, "statistics", err_str, err_rc);
2372 typedef int (*cmd_handler_t)(struct cYAML *tree,
2373 struct cYAML **show_rc,
2374 struct cYAML **err_rc);
2376 static int handle_yaml_config_route(struct cYAML *tree, struct cYAML **show_rc,
2377 struct cYAML **err_rc)
2379 struct cYAML *net, *gw, *hop, *prio, *seq_no;
2381 net = cYAML_get_object_item(tree, "net");
2382 gw = cYAML_get_object_item(tree, "gateway");
2383 hop = cYAML_get_object_item(tree, "hop");
2384 prio = cYAML_get_object_item(tree, "priority");
2385 seq_no = cYAML_get_object_item(tree, "seq_no");
2387 return lustre_lnet_config_route((net) ? net->cy_valuestring : NULL,
2388 (gw) ? gw->cy_valuestring : NULL,
2389 (hop) ? hop->cy_valueint : -1,
2390 (prio) ? prio->cy_valueint : -1,
2391 (seq_no) ? seq_no->cy_valueint : -1,
2395 static void yaml_free_string_array(char **array, int num)
2398 char **sub_array = array;
2400 for (i = 0; i < num; i++) {
2401 if (*sub_array != NULL)
2411 * 0: <intf_name>['['<expr>']']
2412 * 1: <intf_name>['['<expr>']']
2414 static int yaml_copy_intf_info(struct cYAML *intf_tree,
2415 struct lnet_dlc_network_descr *nw_descr)
2417 struct cYAML *child = NULL;
2418 int intf_num = 0, rc = LUSTRE_CFG_RC_NO_ERR;
2419 struct lnet_dlc_intf_descr *intf_descr, *tmp;
2421 if (intf_tree == NULL || nw_descr == NULL)
2422 return LUSTRE_CFG_RC_BAD_PARAM;
2424 /* now grab all the interfaces and their cpts */
2425 child = intf_tree->cy_child;
2426 while (child != NULL) {
2427 if (child->cy_valuestring == NULL) {
2428 child = child->cy_next;
2432 if (strlen(child->cy_valuestring) >= LNET_MAX_STR_LEN)
2435 rc = lustre_lnet_add_intf_descr(&nw_descr->nw_intflist,
2436 child->cy_valuestring,
2437 strlen(child->cy_valuestring));
2438 if (rc != LUSTRE_CFG_RC_NO_ERR)
2442 child = child->cy_next;
2446 return LUSTRE_CFG_RC_MISSING_PARAM;
2451 list_for_each_entry_safe(intf_descr, tmp, &nw_descr->nw_intflist,
2453 list_del(&intf_descr->intf_on_network);
2454 free_intf_descr(intf_descr);
2461 yaml_extract_cmn_tunables(struct cYAML *tree,
2462 struct lnet_ioctl_config_lnd_cmn_tunables *tunables,
2463 struct cfs_expr_list **global_cpts)
2465 struct cYAML *tun, *item, *smp;
2468 tun = cYAML_get_object_item(tree, "tunables");
2470 item = cYAML_get_object_item(tun, "peer_timeout");
2472 tunables->lct_peer_timeout = item->cy_valueint;
2473 item = cYAML_get_object_item(tun, "peer_credits");
2475 tunables->lct_peer_tx_credits = item->cy_valueint;
2476 item = cYAML_get_object_item(tun, "peer_buffer_credits");
2478 tunables->lct_peer_rtr_credits = item->cy_valueint;
2479 item = cYAML_get_object_item(tun, "credits");
2481 tunables->lct_max_tx_credits = item->cy_valueint;
2482 smp = cYAML_get_object_item(tun, "CPT");
2484 rc = cfs_expr_list_parse(smp->cy_valuestring,
2485 strlen(smp->cy_valuestring),
2486 0, UINT_MAX, global_cpts);
2488 *global_cpts = NULL;
2498 yaml_extract_tunables(struct cYAML *tree,
2499 struct lnet_ioctl_config_lnd_tunables *tunables,
2500 struct cfs_expr_list **global_cpts,
2505 rc = yaml_extract_cmn_tunables(tree, &tunables->lt_cmn,
2511 lustre_yaml_extract_lnd_tunables(tree, net_type,
2519 * - net type: <net>[<NUM>]
2521 * - nid: <ip>@<net>[<NUM>]
2524 * 0: <intf_name>['['<expr>']']
2525 * 1: <intf_name>['['<expr>']']
2527 * peer_timeout: <NUM>
2528 * peer_credits: <NUM>
2529 * peer_buffer_credits: <NUM>
2532 * peercredits_hiw: <NUM>
2533 * map_on_demand: <NUM>
2534 * concurrent_sends: <NUM>
2535 * fmr_pool_size: <NUM>
2536 * fmr_flush_trigger: <NUM>
2539 * At least one interface is required. If no interfaces are provided the
2540 * network interface can not be configured.
2542 static int handle_yaml_config_ni(struct cYAML *tree, struct cYAML **show_rc,
2543 struct cYAML **err_rc)
2545 struct cYAML *net, *intf, *seq_no, *ip2net = NULL, *local_nis = NULL,
2547 int num_entries = 0, rc;
2548 struct lnet_dlc_network_descr nw_descr;
2549 struct cfs_expr_list *global_cpts = NULL;
2550 struct lnet_ioctl_config_lnd_tunables tunables;
2553 memset(&tunables, 0, sizeof(tunables));
2555 INIT_LIST_HEAD(&nw_descr.network_on_rule);
2556 INIT_LIST_HEAD(&nw_descr.nw_intflist);
2558 ip2net = cYAML_get_object_item(tree, "ip2net");
2559 net = cYAML_get_object_item(tree, "net type");
2561 nw_descr.nw_id = libcfs_str2net(net->cy_valuestring);
2563 nw_descr.nw_id = LOLND;
2566 * if neither net nor ip2nets are present, then we can not
2567 * configure the network.
2569 if (!net && !ip2net)
2570 return LUSTRE_CFG_RC_MISSING_PARAM;
2572 local_nis = cYAML_get_object_item(tree, "local NI(s)");
2573 if (local_nis == NULL)
2574 return LUSTRE_CFG_RC_MISSING_PARAM;
2576 if (!cYAML_is_sequence(local_nis))
2577 return LUSTRE_CFG_RC_BAD_PARAM;
2579 while (cYAML_get_next_seq_item(local_nis, &item) != NULL) {
2580 intf = cYAML_get_object_item(item, "interfaces");
2583 num_entries = yaml_copy_intf_info(intf, &nw_descr);
2584 if (num_entries <= 0) {
2585 cYAML_build_error(num_entries, -1, "ni", "add",
2586 "bad interface list",
2588 return LUSTRE_CFG_RC_BAD_PARAM;
2592 found = yaml_extract_tunables(tree, &tunables, &global_cpts,
2593 LNET_NETTYP(nw_descr.nw_id));
2594 seq_no = cYAML_get_object_item(tree, "seq_no");
2596 rc = lustre_lnet_config_ni(&nw_descr,
2598 (ip2net) ? ip2net->cy_valuestring : NULL,
2599 (found) ? &tunables: NULL,
2600 (seq_no) ? seq_no->cy_valueint : -1,
2603 if (global_cpts != NULL)
2604 cfs_expr_list_free(global_cpts);
2611 * - net-spec: <tcp|o2ib|gni>[NUM]
2613 * 0: <intf name>['['<expr>']']
2614 * 1: <intf name>['['<expr>']']
2616 * 0: <expr.expr.expr.expr>
2617 * 1: <expr.expr.expr.expr>
2619 static int handle_yaml_config_ip2nets(struct cYAML *tree,
2620 struct cYAML **show_rc,
2621 struct cYAML **err_rc)
2623 struct cYAML *net, *ip_range, *item = NULL, *intf = NULL,
2625 struct lustre_lnet_ip2nets ip2nets;
2626 struct lustre_lnet_ip_range_descr *ip_range_descr = NULL,
2628 int rc = LUSTRE_CFG_RC_NO_ERR;
2629 struct cfs_expr_list *global_cpts = NULL;
2630 struct cfs_expr_list *el, *el_tmp;
2631 struct lnet_ioctl_config_lnd_tunables tunables;
2632 struct lnet_dlc_intf_descr *intf_descr, *intf_tmp;
2635 memset(&tunables, 0, sizeof(tunables));
2637 /* initialize all lists */
2638 INIT_LIST_HEAD(&ip2nets.ip2nets_ip_ranges);
2639 INIT_LIST_HEAD(&ip2nets.ip2nets_net.network_on_rule);
2640 INIT_LIST_HEAD(&ip2nets.ip2nets_net.nw_intflist);
2642 net = cYAML_get_object_item(tree, "net-spec");
2644 return LUSTRE_CFG_RC_BAD_PARAM;
2646 if (net != NULL && net->cy_valuestring == NULL)
2647 return LUSTRE_CFG_RC_BAD_PARAM;
2649 /* assign the network id */
2650 ip2nets.ip2nets_net.nw_id = libcfs_str2net(net->cy_valuestring);
2651 if (ip2nets.ip2nets_net.nw_id == LNET_NID_ANY)
2652 return LUSTRE_CFG_RC_BAD_PARAM;
2654 seq_no = cYAML_get_object_item(tree, "seq_no");
2656 intf = cYAML_get_object_item(tree, "interfaces");
2658 rc = yaml_copy_intf_info(intf, &ip2nets.ip2nets_net);
2660 return LUSTRE_CFG_RC_BAD_PARAM;
2663 ip_range = cYAML_get_object_item(tree, "ip-range");
2664 if (ip_range != NULL) {
2665 item = ip_range->cy_child;
2666 while (item != NULL) {
2667 if (item->cy_valuestring == NULL) {
2668 item = item->cy_next;
2672 rc = lustre_lnet_add_ip_range(&ip2nets.ip2nets_ip_ranges,
2673 item->cy_valuestring);
2675 if (rc != LUSTRE_CFG_RC_NO_ERR)
2678 item = item->cy_next;
2682 found = yaml_extract_tunables(tree, &tunables, &global_cpts,
2683 LNET_NETTYP(ip2nets.ip2nets_net.nw_id));
2685 rc = lustre_lnet_config_ip2nets(&ip2nets,
2686 (found) ? &tunables : NULL,
2688 (seq_no) ? seq_no->cy_valueint : -1,
2692 * don't stop because there was no match. Continue processing the
2693 * rest of the rules. If non-match then nothing is configured
2695 if (rc == LUSTRE_CFG_RC_NO_MATCH)
2696 rc = LUSTRE_CFG_RC_NO_ERR;
2698 list_for_each_entry_safe(intf_descr, intf_tmp,
2699 &ip2nets.ip2nets_net.nw_intflist,
2701 list_del(&intf_descr->intf_on_network);
2702 free_intf_descr(intf_descr);
2705 list_for_each_entry_safe(ip_range_descr, tmp,
2706 &ip2nets.ip2nets_ip_ranges,
2708 list_del(&ip_range_descr->ipr_entry);
2709 list_for_each_entry_safe(el, el_tmp, &ip_range_descr->ipr_expr,
2711 list_del(&el->el_link);
2712 cfs_expr_list_free(el);
2714 free(ip_range_descr);
2720 static int handle_yaml_del_ni(struct cYAML *tree, struct cYAML **show_rc,
2721 struct cYAML **err_rc)
2723 struct cYAML *net = NULL, *intf = NULL, *seq_no = NULL, *item = NULL,
2725 int num_entries, rc;
2726 struct lnet_dlc_network_descr nw_descr;
2728 INIT_LIST_HEAD(&nw_descr.network_on_rule);
2729 INIT_LIST_HEAD(&nw_descr.nw_intflist);
2731 net = cYAML_get_object_item(tree, "net type");
2733 nw_descr.nw_id = libcfs_str2net(net->cy_valuestring);
2735 local_nis = cYAML_get_object_item(tree, "local NI(s)");
2736 if (local_nis == NULL)
2737 return LUSTRE_CFG_RC_MISSING_PARAM;
2739 if (!cYAML_is_sequence(local_nis))
2740 return LUSTRE_CFG_RC_BAD_PARAM;
2742 while (cYAML_get_next_seq_item(local_nis, &item) != NULL) {
2743 intf = cYAML_get_object_item(item, "interfaces");
2746 num_entries = yaml_copy_intf_info(intf, &nw_descr);
2747 if (num_entries <= 0) {
2748 cYAML_build_error(num_entries, -1, "ni", "add",
2749 "bad interface list",
2751 return LUSTRE_CFG_RC_BAD_PARAM;
2755 seq_no = cYAML_get_object_item(tree, "seq_no");
2757 rc = lustre_lnet_del_ni((net) ? &nw_descr : NULL,
2758 (seq_no) ? seq_no->cy_valueint : -1,
2764 static int yaml_copy_peer_nids(struct cYAML *tree, char ***nidsppp, bool del)
2766 struct cYAML *nids_entry = NULL, *child = NULL, *entry = NULL,
2769 int num = 0, rc = LUSTRE_CFG_RC_NO_ERR;
2771 prim_nid = cYAML_get_object_item(tree, "primary nid");
2772 if (!prim_nid || !prim_nid->cy_valuestring)
2773 return LUSTRE_CFG_RC_MISSING_PARAM;
2775 nids_entry = cYAML_get_object_item(tree, "peer ni");
2776 if (cYAML_is_sequence(nids_entry)) {
2777 while (cYAML_get_next_seq_item(nids_entry, &child)) {
2778 entry = cYAML_get_object_item(child, "nid");
2779 /* don't count an empty entry */
2780 if (!entry || !entry->cy_valuestring)
2783 if ((strcmp(entry->cy_valuestring, prim_nid->cy_valuestring)
2786 * primary nid is present in the list of
2787 * nids so that means we want to delete
2788 * the entire peer, so no need to go
2789 * further. Just delete the entire peer.
2799 return LUSTRE_CFG_RC_MISSING_PARAM;
2801 nids = calloc(sizeof(*nids) * num, 1);
2803 return LUSTRE_CFG_RC_OUT_OF_MEM;
2805 /* now grab all the nids */
2808 while (cYAML_get_next_seq_item(nids_entry, &child)) {
2809 entry = cYAML_get_object_item(child, "nid");
2810 if (!entry || !entry->cy_valuestring)
2813 nids[num] = calloc(strlen(entry->cy_valuestring) + 1, 1);
2815 rc = LUSTRE_CFG_RC_OUT_OF_MEM;
2818 strncpy(nids[num], entry->cy_valuestring,
2819 strlen(entry->cy_valuestring));
2829 yaml_free_string_array(nids, num);
2834 static int handle_yaml_config_peer(struct cYAML *tree, struct cYAML **show_rc,
2835 struct cYAML **err_rc)
2839 struct cYAML *seq_no, *prim_nid, *non_mr;
2841 num = yaml_copy_peer_nids(tree, &nids, false);
2845 seq_no = cYAML_get_object_item(tree, "seq_no");
2846 prim_nid = cYAML_get_object_item(tree, "primary nid");
2847 non_mr = cYAML_get_object_item(tree, "non_mr");
2849 rc = lustre_lnet_config_peer_nid((prim_nid) ? prim_nid->cy_valuestring : NULL,
2851 (non_mr) ? false : true,
2852 (seq_no) ? seq_no->cy_valueint : -1,
2855 yaml_free_string_array(nids, num);
2859 static int handle_yaml_del_peer(struct cYAML *tree, struct cYAML **show_rc,
2860 struct cYAML **err_rc)
2864 struct cYAML *seq_no, *prim_nid;
2866 num = yaml_copy_peer_nids(tree, &nids, true);
2870 seq_no = cYAML_get_object_item(tree, "seq_no");
2871 prim_nid = cYAML_get_object_item(tree, "primary nid");
2873 rc = lustre_lnet_del_peer_nid((prim_nid) ? prim_nid->cy_valuestring : NULL,
2875 (seq_no) ? seq_no->cy_valueint : -1,
2878 yaml_free_string_array(nids, num);
2882 static int handle_yaml_config_buffers(struct cYAML *tree,
2883 struct cYAML **show_rc,
2884 struct cYAML **err_rc)
2887 struct cYAML *tiny, *small, *large, *seq_no;
2889 tiny = cYAML_get_object_item(tree, "tiny");
2890 small = cYAML_get_object_item(tree, "small");
2891 large = cYAML_get_object_item(tree, "large");
2892 seq_no = cYAML_get_object_item(tree, "seq_no");
2894 rc = lustre_lnet_config_buffers((tiny) ? tiny->cy_valueint : -1,
2895 (small) ? small->cy_valueint : -1,
2896 (large) ? large->cy_valueint : -1,
2897 (seq_no) ? seq_no->cy_valueint : -1,
2903 static int handle_yaml_config_routing(struct cYAML *tree,
2904 struct cYAML **show_rc,
2905 struct cYAML **err_rc)
2907 int rc = LUSTRE_CFG_RC_NO_ERR;
2908 struct cYAML *seq_no, *enable;
2910 seq_no = cYAML_get_object_item(tree, "seq_no");
2911 enable = cYAML_get_object_item(tree, "enable");
2914 rc = lustre_lnet_enable_routing(enable->cy_valueint,
2916 seq_no->cy_valueint : -1,
2923 static int handle_yaml_del_route(struct cYAML *tree, struct cYAML **show_rc,
2924 struct cYAML **err_rc)
2928 struct cYAML *seq_no;
2930 net = cYAML_get_object_item(tree, "net");
2931 gw = cYAML_get_object_item(tree, "gateway");
2932 seq_no = cYAML_get_object_item(tree, "seq_no");
2934 return lustre_lnet_del_route((net) ? net->cy_valuestring : NULL,
2935 (gw) ? gw->cy_valuestring : NULL,
2936 (seq_no) ? seq_no->cy_valueint : -1,
2940 static int handle_yaml_del_routing(struct cYAML *tree, struct cYAML **show_rc,
2941 struct cYAML **err_rc)
2943 struct cYAML *seq_no;
2945 seq_no = cYAML_get_object_item(tree, "seq_no");
2947 return lustre_lnet_enable_routing(0, (seq_no) ?
2948 seq_no->cy_valueint : -1,
2952 static int handle_yaml_show_route(struct cYAML *tree, struct cYAML **show_rc,
2953 struct cYAML **err_rc)
2959 struct cYAML *detail;
2960 struct cYAML *seq_no;
2962 net = cYAML_get_object_item(tree, "net");
2963 gw = cYAML_get_object_item(tree, "gateway");
2964 hop = cYAML_get_object_item(tree, "hop");
2965 prio = cYAML_get_object_item(tree, "priority");
2966 detail = cYAML_get_object_item(tree, "detail");
2967 seq_no = cYAML_get_object_item(tree, "seq_no");
2969 return lustre_lnet_show_route((net) ? net->cy_valuestring : NULL,
2970 (gw) ? gw->cy_valuestring : NULL,
2971 (hop) ? hop->cy_valueint : -1,
2972 (prio) ? prio->cy_valueint : -1,
2973 (detail) ? detail->cy_valueint : 0,
2974 (seq_no) ? seq_no->cy_valueint : -1,
2979 static int handle_yaml_show_net(struct cYAML *tree, struct cYAML **show_rc,
2980 struct cYAML **err_rc)
2982 struct cYAML *net, *detail, *seq_no;
2984 net = cYAML_get_object_item(tree, "net");
2985 detail = cYAML_get_object_item(tree, "detail");
2986 seq_no = cYAML_get_object_item(tree, "seq_no");
2988 return lustre_lnet_show_net((net) ? net->cy_valuestring : NULL,
2989 (detail) ? detail->cy_valueint : 0,
2990 (seq_no) ? seq_no->cy_valueint : -1,
2995 static int handle_yaml_show_routing(struct cYAML *tree, struct cYAML **show_rc,
2996 struct cYAML **err_rc)
2998 struct cYAML *seq_no;
3000 seq_no = cYAML_get_object_item(tree, "seq_no");
3002 return lustre_lnet_show_routing((seq_no) ? seq_no->cy_valueint : -1,
3006 static int handle_yaml_show_peers(struct cYAML *tree, struct cYAML **show_rc,
3007 struct cYAML **err_rc)
3009 struct cYAML *seq_no, *nid, *detail;
3011 seq_no = cYAML_get_object_item(tree, "seq_no");
3012 detail = cYAML_get_object_item(tree, "detail");
3013 nid = cYAML_get_object_item(tree, "nid");
3015 return lustre_lnet_show_peer((nid) ? nid->cy_valuestring : NULL,
3016 (detail) ? detail->cy_valueint : 0,
3017 (seq_no) ? seq_no->cy_valueint : -1,
3021 static int handle_yaml_show_stats(struct cYAML *tree, struct cYAML **show_rc,
3022 struct cYAML **err_rc)
3024 struct cYAML *seq_no;
3026 seq_no = cYAML_get_object_item(tree, "seq_no");
3028 return lustre_lnet_show_stats((seq_no) ? seq_no->cy_valueint : -1,
3032 static int handle_yaml_config_numa(struct cYAML *tree, struct cYAML **show_rc,
3033 struct cYAML **err_rc)
3035 struct cYAML *seq_no, *range;
3037 seq_no = cYAML_get_object_item(tree, "seq_no");
3038 range = cYAML_get_object_item(tree, "range");
3040 return lustre_lnet_config_numa_range(range ? range->cy_valueint : -1,
3041 seq_no ? seq_no->cy_valueint : -1,
3045 static int handle_yaml_del_numa(struct cYAML *tree, struct cYAML **show_rc,
3046 struct cYAML **err_rc)
3048 struct cYAML *seq_no;
3050 seq_no = cYAML_get_object_item(tree, "seq_no");
3052 return lustre_lnet_config_numa_range(0, seq_no ? seq_no->cy_valueint : -1,
3056 static int handle_yaml_show_numa(struct cYAML *tree, struct cYAML **show_rc,
3057 struct cYAML **err_rc)
3059 struct cYAML *seq_no;
3061 seq_no = cYAML_get_object_item(tree, "seq_no");
3063 return lustre_lnet_show_numa_range(seq_no ? seq_no->cy_valueint : -1,
3067 struct lookup_cmd_hdlr_tbl {
3072 static struct lookup_cmd_hdlr_tbl lookup_config_tbl[] = {
3073 { .name = "route", .cb = handle_yaml_config_route },
3074 { .name = "net", .cb = handle_yaml_config_ni },
3075 { .name = "ip2nets", .cb = handle_yaml_config_ip2nets },
3076 { .name = "peer", .cb = handle_yaml_config_peer },
3077 { .name = "routing", .cb = handle_yaml_config_routing },
3078 { .name = "buffers", .cb = handle_yaml_config_buffers },
3079 { .name = "numa", .cb = handle_yaml_config_numa },
3082 static struct lookup_cmd_hdlr_tbl lookup_del_tbl[] = {
3083 { .name = "route", .cb = handle_yaml_del_route },
3084 { .name = "net", .cb = handle_yaml_del_ni },
3085 { .name = "peer", .cb = handle_yaml_del_peer },
3086 { .name = "routing", .cb = handle_yaml_del_routing },
3087 { .name = "numa", .cb = handle_yaml_del_numa },
3090 static struct lookup_cmd_hdlr_tbl lookup_show_tbl[] = {
3091 { .name = "route", .cb = handle_yaml_show_route },
3092 { .name = "net", .cb = handle_yaml_show_net },
3093 { .name = "buffers", .cb = handle_yaml_show_routing },
3094 { .name = "routing", .cb = handle_yaml_show_routing },
3095 { .name = "peer", .cb = handle_yaml_show_peers },
3096 { .name = "statistics", .cb = handle_yaml_show_stats },
3097 { .name = "numa", .cb = handle_yaml_show_numa },
3100 static cmd_handler_t lookup_fn(char *key,
3101 struct lookup_cmd_hdlr_tbl *tbl)
3107 for (i = 0; tbl[i].name != NULL; i++) {
3108 if (strncmp(key, tbl[i].name, strlen(tbl[i].name)) == 0)
3115 static int lustre_yaml_cb_helper(char *f, struct lookup_cmd_hdlr_tbl *table,
3116 struct cYAML **show_rc, struct cYAML **err_rc)
3118 struct cYAML *tree, *item = NULL, *head, *child;
3120 char err_str[LNET_MAX_STR_LEN];
3121 int rc = LUSTRE_CFG_RC_NO_ERR, return_rc = LUSTRE_CFG_RC_NO_ERR;
3123 tree = cYAML_build_tree(f, NULL, 0, err_rc, false);
3125 return LUSTRE_CFG_RC_BAD_PARAM;
3127 child = tree->cy_child;
3128 while (child != NULL) {
3129 cb = lookup_fn(child->cy_string, table);
3131 snprintf(err_str, sizeof(err_str),
3132 "\"call back for '%s' not found\"",
3134 cYAML_build_error(LUSTRE_CFG_RC_BAD_PARAM, -1,
3135 "yaml", "helper", err_str, err_rc);
3139 if (cYAML_is_sequence(child)) {
3140 while ((head = cYAML_get_next_seq_item(child, &item))
3142 rc = cb(head, show_rc, err_rc);
3143 if (rc != LUSTRE_CFG_RC_NO_ERR)
3147 rc = cb(child, show_rc, err_rc);
3148 if (rc != LUSTRE_CFG_RC_NO_ERR)
3152 child = child->cy_next;
3156 cYAML_free_tree(tree);
3161 int lustre_yaml_config(char *f, struct cYAML **err_rc)
3163 return lustre_yaml_cb_helper(f, lookup_config_tbl,
3167 int lustre_yaml_del(char *f, struct cYAML **err_rc)
3169 return lustre_yaml_cb_helper(f, lookup_del_tbl,
3173 int lustre_yaml_show(char *f, struct cYAML **show_rc, struct cYAML **err_rc)
3175 return lustre_yaml_cb_helper(f, lookup_show_tbl,