return rc;
}
+/** LNet route handling */
+
+/* We can't use struct lnet_ioctl_config_data since it lacks
+ * support for large NIDS
+ */
+struct lnet_route_properties {
+ struct lnet_nid lrp_gateway;
+ u32 lrp_net;
+ s32 lrp_hop;
+ u32 lrp_flags;
+ u32 lrp_priority;
+ u32 lrp_sensitivity;
+};
+
+struct lnet_genl_route_list {
+ unsigned int lgrl_index;
+ unsigned int lgrl_count;
+ GENRADIX(struct lnet_route_properties) lgrl_list;
+};
+
+static inline struct lnet_genl_route_list *
+lnet_route_dump_ctx(struct netlink_callback *cb)
+{
+ return (struct lnet_genl_route_list *)cb->args[0];
+}
+
+static int lnet_route_show_done(struct netlink_callback *cb)
+{
+ struct lnet_genl_route_list *rlist = lnet_route_dump_ctx(cb);
+
+ if (rlist) {
+ genradix_free(&rlist->lgrl_list);
+ CFS_FREE_PTR(rlist);
+ }
+ cb->args[0] = 0;
+
+ return 0;
+}
+
+int lnet_scan_route(struct lnet_genl_route_list *rlist,
+ struct lnet_route_properties *settings)
+{
+ struct lnet_remotenet *rnet;
+ struct list_head *rn_list;
+ struct lnet_route *route;
+ int cpt, i, rc = 0;
+
+ cpt = lnet_net_lock_current();
+
+ for (i = 0; i < LNET_REMOTE_NETS_HASH_SIZE; i++) {
+ rn_list = &the_lnet.ln_remote_nets_hash[i];
+ list_for_each_entry(rnet, rn_list, lrn_list) {
+ if (settings->lrp_net != LNET_NET_ANY &&
+ settings->lrp_net != rnet->lrn_net)
+ continue;
+
+ list_for_each_entry(route, &rnet->lrn_routes,
+ lr_list) {
+ struct lnet_route_properties *prop;
+
+ if (!LNET_NID_IS_ANY(&settings->lrp_gateway) &&
+ !nid_same(&settings->lrp_gateway,
+ &route->lr_nid)) {
+ continue;
+ }
+
+ if (settings->lrp_hop != -1 &&
+ settings->lrp_hop != route->lr_hops)
+ continue;
+
+ if (settings->lrp_priority != -1 &&
+ settings->lrp_priority != route->lr_priority)
+ continue;
+
+ if (settings->lrp_sensitivity != -1 &&
+ settings->lrp_sensitivity !=
+ route->lr_gateway->lp_health_sensitivity)
+ continue;
+
+ prop = genradix_ptr_alloc(&rlist->lgrl_list,
+ rlist->lgrl_count++,
+ GFP_KERNEL);
+ if (!prop)
+ GOTO(failed_alloc, rc = -ENOMEM);
+
+ prop->lrp_net = rnet->lrn_net;
+ prop->lrp_gateway = route->lr_nid;
+ prop->lrp_hop = route->lr_hops;
+ prop->lrp_priority = route->lr_priority;
+ prop->lrp_sensitivity =
+ route->lr_gateway->lp_health_sensitivity;
+ if (lnet_is_route_alive(route))
+ prop->lrp_flags |= LNET_RT_ALIVE;
+ else
+ prop->lrp_flags &= ~LNET_RT_ALIVE;
+ if (route->lr_single_hop)
+ prop->lrp_flags &= ~LNET_RT_MULTI_HOP;
+ else
+ prop->lrp_flags |= LNET_RT_MULTI_HOP;
+ }
+ }
+ }
+
+failed_alloc:
+ lnet_net_unlock(cpt);
+ return rc;
+}
+
+/* LNet route ->start() handler for GET requests */
+static int lnet_route_show_start(struct netlink_callback *cb)
+{
+ struct genlmsghdr *gnlh = nlmsg_data(cb->nlh);
+#ifdef HAVE_NL_PARSE_WITH_EXT_ACK
+ struct netlink_ext_ack *extack = NULL;
+#endif
+ struct lnet_genl_route_list *rlist;
+ int msg_len = genlmsg_len(gnlh);
+ int rc = 0;
+
+#ifdef HAVE_NL_DUMP_WITH_EXT_ACK
+ extack = cb->extack;
+#endif
+ if (the_lnet.ln_refcount == 0 ||
+ the_lnet.ln_state != LNET_STATE_RUNNING) {
+ NL_SET_ERR_MSG(extack, "Network is down");
+ return -ENETDOWN;
+ }
+
+ CFS_ALLOC_PTR(rlist);
+ if (!rlist) {
+ NL_SET_ERR_MSG(extack, "No memory for route list");
+ return -ENOMEM;
+ }
+
+ genradix_init(&rlist->lgrl_list);
+ rlist->lgrl_count = 0;
+ rlist->lgrl_index = 0;
+ cb->args[0] = (long)rlist;
+
+ mutex_lock(&the_lnet.ln_api_mutex);
+ if (!msg_len) {
+ struct lnet_route_properties tmp = {
+ .lrp_gateway = LNET_ANY_NID,
+ .lrp_net = LNET_NET_ANY,
+ .lrp_hop = -1,
+ .lrp_priority = -1,
+ .lrp_sensitivity = -1,
+ };
+
+ rc = lnet_scan_route(rlist, &tmp);
+ if (rc < 0) {
+ NL_SET_ERR_MSG(extack,
+ "failed to allocate router data");
+ GOTO(report_err, rc);
+ }
+ } else {
+ struct nlattr *params = genlmsg_data(gnlh);
+ struct nlattr *attr;
+ int rem;
+
+ nla_for_each_nested(attr, params, rem) {
+ struct lnet_route_properties tmp = {
+ .lrp_gateway = LNET_ANY_NID,
+ .lrp_net = LNET_NET_ANY,
+ .lrp_hop = -1,
+ .lrp_priority = -1,
+ .lrp_sensitivity = -1,
+ };
+ struct nlattr *route;
+ int rem2;
+
+ if (nla_type(attr) != LN_SCALAR_ATTR_LIST)
+ continue;
+
+ nla_for_each_nested(route, attr, rem2) {
+ if (nla_type(route) != LN_SCALAR_ATTR_VALUE)
+ continue;
+
+ if (nla_strcmp(route, "net") == 0) {
+ char nw[LNET_NIDSTR_SIZE];
+
+ route = nla_next(route, &rem2);
+ if (nla_type(route) !=
+ LN_SCALAR_ATTR_VALUE) {
+ NL_SET_ERR_MSG(extack,
+ "invalid net param");
+ GOTO(report_err, rc = -EINVAL);
+ }
+
+ rc = nla_strscpy(nw, route, sizeof(nw));
+ if (rc < 0) {
+ NL_SET_ERR_MSG(extack,
+ "failed to get route param");
+ GOTO(report_err, rc);
+ }
+ rc = 0;
+ tmp.lrp_net = libcfs_str2net(strim(nw));
+ } else if (nla_strcmp(route, "gateway") == 0) {
+ char gw[LNET_NIDSTR_SIZE];
+
+ route = nla_next(route, &rem2);
+ if (nla_type(route) !=
+ LN_SCALAR_ATTR_VALUE) {
+ NL_SET_ERR_MSG(extack,
+ "invalid gateway param");
+ GOTO(report_err, rc = -EINVAL);
+ }
+
+ rc = nla_strscpy(gw, route, sizeof(gw));
+ if (rc < 0) {
+ NL_SET_ERR_MSG(extack,
+ "failed to get route param");
+ GOTO(report_err, rc);
+ }
+ rc = 0;
+ libcfs_strnid(&tmp.lrp_gateway, strim(gw));
+ } else if (nla_strcmp(route, "hop") == 0) {
+ route = nla_next(route, &rem2);
+ if (nla_type(route) !=
+ LN_SCALAR_ATTR_INT_VALUE) {
+ NL_SET_ERR_MSG(extack,
+ "invalid hop param");
+ GOTO(report_err, rc = -EINVAL);
+ }
+
+ tmp.lrp_hop = nla_get_s64(route);
+ if (tmp.lrp_hop != -1)
+ clamp_t(s32, tmp.lrp_hop, 1, 127);
+ } else if (nla_strcmp(route, "priority") == 0) {
+ route = nla_next(route, &rem2);
+ if (nla_type(route) !=
+ LN_SCALAR_ATTR_INT_VALUE) {
+ NL_SET_ERR_MSG(extack,
+ "invalid priority param");
+ GOTO(report_err, rc = -EINVAL);
+ }
+
+ tmp.lrp_priority = nla_get_s64(route);
+ }
+ }
+
+ rc = lnet_scan_route(rlist, &tmp);
+ if (rc < 0) {
+ NL_SET_ERR_MSG(extack,
+ "failed to allocate router data");
+ GOTO(report_err, rc);
+ }
+ }
+ }
+report_err:
+ mutex_unlock(&the_lnet.ln_api_mutex);
+
+ if (rc < 0)
+ lnet_route_show_done(cb);
+
+ return rc;
+}
+
+static const struct ln_key_list route_props_list = {
+ .lkl_maxattr = LNET_ROUTE_ATTR_MAX,
+ .lkl_list = {
+ [LNET_ROUTE_ATTR_HDR] = {
+ .lkp_value = "route",
+ .lkp_key_format = LNKF_SEQUENCE | LNKF_MAPPING,
+ .lkp_data_type = NLA_NUL_STRING,
+ },
+ [LNET_ROUTE_ATTR_NET] = {
+ .lkp_value = "net",
+ .lkp_data_type = NLA_STRING
+ },
+ [LNET_ROUTE_ATTR_GATEWAY] = {
+ .lkp_value = "gateway",
+ .lkp_data_type = NLA_STRING
+ },
+ [LNET_ROUTE_ATTR_HOP] = {
+ .lkp_value = "hop",
+ .lkp_data_type = NLA_S32
+ },
+ [LNET_ROUTE_ATTR_PRIORITY] = {
+ .lkp_value = "priority",
+ .lkp_data_type = NLA_U32
+ },
+ [LNET_ROUTE_ATTR_HEALTH_SENSITIVITY] = {
+ .lkp_value = "health_sensitivity",
+ .lkp_data_type = NLA_U32
+ },
+ [LNET_ROUTE_ATTR_STATE] = {
+ .lkp_value = "state",
+ .lkp_data_type = NLA_STRING,
+ },
+ [LNET_ROUTE_ATTR_TYPE] = {
+ .lkp_value = "type",
+ .lkp_data_type = NLA_STRING,
+ },
+ },
+};
+
+
+static int lnet_route_show_dump(struct sk_buff *msg,
+ struct netlink_callback *cb)
+{
+ struct lnet_genl_route_list *rlist = lnet_route_dump_ctx(cb);
+ struct genlmsghdr *gnlh = nlmsg_data(cb->nlh);
+#ifdef HAVE_NL_PARSE_WITH_EXT_ACK
+ struct netlink_ext_ack *extack = NULL;
+#endif
+ int portid = NETLINK_CB(cb->skb).portid;
+ int seq = cb->nlh->nlmsg_seq;
+ int idx = rlist->lgrl_index;
+ int rc = 0;
+
+#ifdef HAVE_NL_DUMP_WITH_EXT_ACK
+ extack = cb->extack;
+#endif
+ if (!rlist->lgrl_count) {
+ NL_SET_ERR_MSG(extack, "No routes found");
+ GOTO(send_error, rc = -ENOENT);
+ }
+
+ if (!idx) {
+ const struct ln_key_list *all[] = {
+ &route_props_list, NULL
+ };
+
+ rc = lnet_genl_send_scalar_list(msg, portid, seq,
+ &lnet_family,
+ NLM_F_CREATE | NLM_F_MULTI,
+ LNET_CMD_ROUTES, all);
+ if (rc < 0) {
+ NL_SET_ERR_MSG(extack, "failed to send key table");
+ GOTO(send_error, rc);
+ }
+ }
+
+ /* If not routes found send an empty message and not an error */
+ if (!rlist->lgrl_count) {
+ void *hdr;
+
+ hdr = genlmsg_put(msg, portid, seq, &lnet_family,
+ NLM_F_MULTI, LNET_CMD_ROUTES);
+ if (!hdr) {
+ NL_SET_ERR_MSG(extack, "failed to send values");
+ genlmsg_cancel(msg, hdr);
+ GOTO(send_error, rc = -EMSGSIZE);
+ }
+ genlmsg_end(msg, hdr);
+
+ goto send_error;
+ }
+
+ while (idx < rlist->lgrl_count) {
+ struct lnet_route_properties *prop;
+ void *hdr;
+
+ prop = genradix_ptr(&rlist->lgrl_list, idx++);
+
+ hdr = genlmsg_put(msg, portid, seq, &lnet_family,
+ NLM_F_MULTI, LNET_CMD_ROUTES);
+ if (!hdr) {
+ NL_SET_ERR_MSG(extack, "failed to send values");
+ genlmsg_cancel(msg, hdr);
+ GOTO(send_error, rc = -EMSGSIZE);
+ }
+
+ if (idx == 1)
+ nla_put_string(msg, LNET_ROUTE_ATTR_HDR, "");
+
+ nla_put_string(msg, LNET_ROUTE_ATTR_NET,
+ libcfs_net2str(prop->lrp_net));
+ nla_put_string(msg, LNET_ROUTE_ATTR_GATEWAY,
+ libcfs_nidstr(&prop->lrp_gateway));
+ if (gnlh->version) {
+ nla_put_s32(msg, LNET_ROUTE_ATTR_HOP, prop->lrp_hop);
+ nla_put_u32(msg, LNET_ROUTE_ATTR_PRIORITY, prop->lrp_priority);
+ nla_put_u32(msg, LNET_ROUTE_ATTR_HEALTH_SENSITIVITY,
+ prop->lrp_sensitivity);
+
+ nla_put_string(msg, LNET_ROUTE_ATTR_STATE,
+ prop->lrp_flags & LNET_RT_ALIVE ?
+ "up" : "down");
+ nla_put_string(msg, LNET_ROUTE_ATTR_TYPE,
+ prop->lrp_flags & LNET_RT_MULTI_HOP ?
+ "multi-hop" : "single-hop");
+ }
+ genlmsg_end(msg, hdr);
+ }
+ rlist->lgrl_index = idx;
+send_error:
+ return lnet_nl_send_error(cb->skb, portid, seq, rc);
+};
+
+#ifndef HAVE_NETLINK_CALLBACK_START
+static int lnet_old_route_show_dump(struct sk_buff *msg,
+ struct netlink_callback *cb)
+{
+ if (!cb->args[0]) {
+ int rc = lnet_route_show_start(cb);
+
+ if (rc < 0)
+ return rc;
+ }
+
+ return lnet_route_show_dump(msg, cb);
+}
+#endif /* !HAVE_NETLINK_CALLBACK_START */
+
static inline struct lnet_genl_ping_list *
lnet_ping_dump_ctx(struct netlink_callback *cb)
{
static const struct genl_multicast_group lnet_mcast_grps[] = {
{ .name = "ip2net", },
{ .name = "net", },
+ { .name = "route", },
{ .name = "ping", },
};
.doit = lnet_net_cmd,
},
{
+ .cmd = LNET_CMD_ROUTES,
+#ifdef HAVE_NETLINK_CALLBACK_START
+ .start = lnet_route_show_start,
+ .dumpit = lnet_route_show_dump,
+#else
+ .dumpit = lnet_old_route_show_dump,
+#endif
+ .done = lnet_route_show_done,
+ },
+ {
.cmd = LNET_CMD_PING,
#ifdef HAVE_NETLINK_CALLBACK_START
.start = lnet_ping_show_start,
{"add", jt_add_route, 0, "add a route\n"
"\t--net: net name (e.g. tcp0)\n"
"\t--gateway: gateway nid (e.g. 10.1.1.2@tcp)\n"
- "\t--hop: number to final destination (1 < hops < 255)\n"
+ "\t--hop|hop-count: number to final destination (1 <= hops <= 255)\n"
"\t--priority: priority of route (0 - highest prio\n"
"\t--health_sensitivity: gateway health sensitivity (>= 1)\n"},
{"del", jt_del_route, 0, "delete a route\n"
{"show", jt_show_route, 0, "show routes\n"
"\t--net: net name (e.g. tcp0) to filter on\n"
"\t--gateway: gateway nid (e.g. 10.1.1.2@tcp) to filter on\n"
- "\t--hop: number to final destination (1 < hops < 255) to filter on\n"
+ "\t--hop|hop-count: number to final destination (1 <= hops <= 255) to filter on\n"
"\t--priority: priority of route (0 - highest prio to filter on\n"
- "\t--health_sensitivity: gateway health sensitivity (>= 1)\n"
"\t--verbose: display detailed output per route\n"},
{ 0, 0, 0, NULL }
};
return rc;
}
-static void yaml_lnet_print_error(char *flag, char *cmd, const char *errstr)
+static void yaml_lnet_print_error(int op, char *cmd, const char *errstr)
{
+ char errcode[INT_STRING_LEN];
yaml_emitter_t log;
yaml_event_t event;
- char errcode[23];
+ const char *flag;
int rc;
snprintf(errcode, sizeof(errcode), "%d", errno);
yaml_emitter_initialize(&log);
- yaml_emitter_set_output_file(&log, stdout);
+ yaml_emitter_set_indent(&log, 6);
+ yaml_emitter_set_output_file(&log, stderr);
yaml_emitter_open(&log);
yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
if (rc == 0)
goto emitter_error;
+ switch (op) {
+ case NLM_F_CREATE:
+ flag = "add";
+ break;
+ case NLM_F_REPLACE:
+ flag = "set";
+ break;
+ case 0:
+ flag = "del";
+ break;
+ case NLM_F_DUMP:
+ default:
+ flag = "show";
+ break;
+ }
+
yaml_scalar_event_initialize(&event, NULL,
(yaml_char_t *)YAML_STR_TAG,
(yaml_char_t *)flag,
goto emitter_error;
yaml_scalar_event_initialize(&event, NULL,
- (yaml_char_t *)YAML_INT_TAG,
+ (yaml_char_t *)YAML_STR_TAG,
(yaml_char_t *)errstr,
strlen(errstr), 1, 0,
- YAML_PLAIN_SCALAR_STYLE);
+ YAML_DOUBLE_QUOTED_SCALAR_STYLE);
rc = yaml_emitter_emit(&log, &event);
if (rc == 0)
goto emitter_error;
return rc;
}
+
+static int yaml_lnet_route(char *nw, char *gw, int hops, int prio, int sen,
+ int version, int flags)
+{
+ struct nl_sock *sk = NULL;
+ const char *msg = NULL;
+ yaml_emitter_t output;
+ yaml_parser_t reply;
+ yaml_event_t event;
+ int rc;
+
+ /* Create Netlink emitter to send request to kernel */
+ sk = nl_socket_alloc();
+ if (!sk)
+ return -EOPNOTSUPP;
+
+ /* Setup parser to receive Netlink packets */
+ rc = yaml_parser_initialize(&reply);
+ if (rc == 0) {
+ nl_socket_free(sk);
+ return -EOPNOTSUPP;
+ }
+
+ rc = yaml_parser_set_input_netlink(&reply, sk, false);
+ if (rc == 0) {
+ msg = yaml_parser_get_reader_error(&reply);
+ goto free_reply;
+ }
+
+ /* Create Netlink emitter to send request to kernel */
+ rc = yaml_emitter_initialize(&output);
+ if (rc == 0) {
+ msg = "failed to initialize emitter";
+ goto free_reply;
+ }
+
+ rc = yaml_emitter_set_output_netlink(&output, sk, LNET_GENL_NAME,
+ version, LNET_CMD_ROUTES, flags);
+ if (rc == 0)
+ goto emitter_error;
+
+ yaml_emitter_open(&output);
+ yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ yaml_mapping_start_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_MAP_TAG,
+ 1, YAML_ANY_MAPPING_STYLE);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ yaml_scalar_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_STR_TAG,
+ (yaml_char_t *)"route",
+ strlen("route"), 1, 0,
+ YAML_PLAIN_SCALAR_STYLE);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ if (nw || gw || hops != -1 || prio != -1) {
+ char num[INT_STRING_LEN];
+
+ yaml_sequence_start_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_SEQ_TAG,
+ 1,
+ YAML_BLOCK_SEQUENCE_STYLE);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ if (nw) {
+ yaml_mapping_start_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_MAP_TAG,
+ 1,
+ YAML_BLOCK_MAPPING_STYLE);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ yaml_scalar_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_STR_TAG,
+ (yaml_char_t *)"net",
+ strlen("net"), 1, 0,
+ YAML_PLAIN_SCALAR_STYLE);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ yaml_scalar_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_STR_TAG,
+ (yaml_char_t *)nw,
+ strlen(nw), 1, 0,
+ YAML_PLAIN_SCALAR_STYLE);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ yaml_mapping_end_event_initialize(&event);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+ }
+
+ if (gw) {
+ yaml_mapping_start_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_MAP_TAG,
+ 1,
+ YAML_BLOCK_MAPPING_STYLE);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ yaml_scalar_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_STR_TAG,
+ (yaml_char_t *)"gateway",
+ strlen("gateway"), 1, 0,
+ YAML_PLAIN_SCALAR_STYLE);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ yaml_scalar_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_STR_TAG,
+ (yaml_char_t *)gw,
+ strlen(gw), 1, 0,
+ YAML_PLAIN_SCALAR_STYLE);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ yaml_mapping_end_event_initialize(&event);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+ }
+
+ if (hops != -1) {
+ yaml_mapping_start_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_MAP_TAG,
+ 1,
+ YAML_BLOCK_MAPPING_STYLE);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ yaml_scalar_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_STR_TAG,
+ (yaml_char_t *)"hop",
+ strlen("hop"), 1, 0,
+ YAML_PLAIN_SCALAR_STYLE);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ snprintf(num, sizeof(num), "%d", hops);
+ yaml_scalar_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_INT_TAG,
+ (yaml_char_t *)num,
+ strlen(num), 1, 0,
+ YAML_PLAIN_SCALAR_STYLE);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ yaml_mapping_end_event_initialize(&event);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+ }
+
+ if (prio != -1) {
+ yaml_mapping_start_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_MAP_TAG,
+ 1,
+ YAML_BLOCK_MAPPING_STYLE);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ yaml_scalar_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_STR_TAG,
+ (yaml_char_t *)"priority",
+ strlen("priority"), 1, 0,
+ YAML_PLAIN_SCALAR_STYLE);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ snprintf(num, sizeof(num), "%d", prio);
+ yaml_scalar_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_INT_TAG,
+ (yaml_char_t *)num,
+ strlen(num), 1, 0,
+ YAML_PLAIN_SCALAR_STYLE);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ yaml_mapping_end_event_initialize(&event);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+ }
+
+ if (sen != -1) {
+ yaml_mapping_start_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_MAP_TAG,
+ 1,
+ YAML_BLOCK_MAPPING_STYLE);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ yaml_scalar_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_STR_TAG,
+ (yaml_char_t *)"health_sensitivity",
+ strlen("health_sensitivity"),
+ 1, 0,
+ YAML_PLAIN_SCALAR_STYLE);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ snprintf(num, sizeof(num), "%d", sen);
+ yaml_scalar_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_INT_TAG,
+ (yaml_char_t *)num,
+ strlen(num), 1, 0,
+ YAML_PLAIN_SCALAR_STYLE);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ yaml_mapping_end_event_initialize(&event);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+ }
+
+ yaml_sequence_end_event_initialize(&event);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+ } else {
+ yaml_scalar_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_STR_TAG,
+ (yaml_char_t *)"",
+ strlen(""), 1, 0,
+ YAML_PLAIN_SCALAR_STYLE);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+ }
+
+ yaml_mapping_end_event_initialize(&event);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ yaml_document_end_event_initialize(&event, 0);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ rc = yaml_emitter_close(&output);
+emitter_error:
+ if (rc == 0) {
+ yaml_emitter_log_error(&output, stderr);
+ rc = -EINVAL;
+ } else {
+ yaml_document_t errmsg;
+
+ rc = yaml_parser_load(&reply, &errmsg);
+ if (rc == 1 && flags == NLM_F_DUMP) {
+ yaml_emitter_t debug;
+
+ rc = yaml_emitter_initialize(&debug);
+ if (rc == 1) {
+ yaml_emitter_set_indent(&debug, 6);
+ yaml_emitter_set_output_file(&debug,
+ stdout);
+ rc = yaml_emitter_dump(&debug, &errmsg);
+ }
+ yaml_emitter_delete(&debug);
+ } else {
+ msg = yaml_parser_get_reader_error(&reply);
+ /* If we didn't find any routes just be silent */
+ if (msg && strcmp(msg, "No routes found") == 0)
+ rc = 1;
+ }
+ yaml_document_delete(&errmsg);
+ }
+ yaml_emitter_delete(&output);
+free_reply:
+ if (rc == 0) {
+ yaml_lnet_print_error(flags, "route", msg);
+ rc = -EINVAL;
+ }
+ yaml_parser_delete(&reply);
+ nl_socket_free(sk);
+
+ return rc == 1 ? 0 : rc;
+}
+
static int jt_add_route(int argc, char **argv)
{
char *network = NULL, *gateway = NULL;
static const struct option long_options[] = {
{ .name = "net", .has_arg = required_argument, .val = 'n' },
{ .name = "gateway", .has_arg = required_argument, .val = 'g' },
+ { .name = "hop", .has_arg = required_argument, .val = 'c' },
{ .name = "hop-count", .has_arg = required_argument, .val = 'c' },
{ .name = "priority", .has_arg = required_argument, .val = 'p' },
{ .name = "health_sensitivity", .has_arg = required_argument, .val = 's' },
yaml_emitter_delete(&output);
free_reply:
if (rc == 0) {
- yaml_lnet_print_error(flags ? "add" : "del", "net",
+ yaml_lnet_print_error(flags, "net",
yaml_parser_get_reader_error(&reply));
rc = -EINVAL;
}
long int hop = -1, prio = -1;
int detail = 0, rc, opt;
struct cYAML *err_rc = NULL, *show_rc = NULL;
-
- const char *const short_options = "n:g:h:p:v";
+ const char *const short_options = "c:n:g:p:v";
static const struct option long_options[] = {
- { .name = "net", .has_arg = required_argument, .val = 'n' },
- { .name = "gateway", .has_arg = required_argument, .val = 'g' },
- { .name = "hop-count", .has_arg = required_argument, .val = 'c' },
- { .name = "priority", .has_arg = required_argument, .val = 'p' },
- { .name = "verbose", .has_arg = no_argument, .val = 'v' },
- { .name = NULL } };
+ { .name = "net", .has_arg = required_argument, .val = 'n' },
+ { .name = "gateway", .has_arg = required_argument, .val = 'g' },
+ { .name = "hop-count", .has_arg = required_argument, .val = 'c' },
+ { .name = "hop", .has_arg = required_argument, .val = 'c' },
+ { .name = "priority", .has_arg = required_argument, .val = 'p' },
+ { .name = "verbose", .has_arg = no_argument, .val = 'v' },
+ { .name = NULL }
+ };
rc = check_cmd(route_cmds, "route", "show", 0, argc, argv);
if (rc)
}
}
- rc = lustre_lnet_show_route(network, gateway, hop, prio, detail, -1,
+ rc = yaml_lnet_route(network, gateway, hop, prio, -1,
+ detail, NLM_F_DUMP);
+ if (rc <= 0) {
+ if (rc == -EOPNOTSUPP)
+ goto old_api;
+ return rc;
+ }
+old_api:
+ rc = lustre_lnet_show_route(network, gateway, hop, prio,
+ detail ? 1 : 0, -1,
&show_rc, &err_rc, false);
if (rc != LUSTRE_CFG_RC_NO_ERR)