X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lnet%2Futils%2Fportals.c;h=f1e34f03b850112d4d2a433a4f7fdf5ae4e8bbd4;hp=7161f6bb35bf89ca137f6d5acb7ac60f55bcb564;hb=65e067d5d90270d4237a7271008561a4b432b94d;hpb=21d716e6c16424d9deb646456758ebbaa9c70fec diff --git a/lnet/utils/portals.c b/lnet/utils/portals.c index 7161f6b..f1e34f0 100644 --- a/lnet/utils/portals.c +++ b/lnet/utils/portals.c @@ -1,6 +1,8 @@ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * + * Copyright (c) 2013, 2014, Intel Corporation. + * * This file is part of Portals, http://www.sf.net/projects/lustre/ * * Portals is free software; you can redistribute it and/or @@ -19,9 +21,12 @@ */ #include -#include +#include #include #include +#include +#include +#include unsigned int libcfs_debug; unsigned int libcfs_printk = D_CANTMASK; @@ -29,6 +34,10 @@ unsigned int libcfs_printk = D_CANTMASK; static int g_net_set; static __u32 g_net; +#define IOC_BUF_SIZE 8192 +static char local_buf[IOC_BUF_SIZE]; +static char *ioc_buf = local_buf; + /* Convert a string boolean to an int; "enable" -> 1 */ int lnet_parse_bool (int *b, char *str) @@ -1087,12 +1096,12 @@ jt_ptl_fail_nid (int argc, char **argv) int jt_ptl_add_route (int argc, char **argv) { - struct libcfs_ioctl_data data; - lnet_nid_t gateway_nid; - unsigned int hops = 1; + struct lnet_ioctl_config_data data; + lnet_nid_t gateway_nid; + unsigned int hops = 1; unsigned int priority = 0; - char *end; - int rc; + char *end; + int rc; if (argc < 2 || argc > 4) { fprintf(stderr, "usage: %s gateway [hopcount [priority]]\n", @@ -1100,14 +1109,14 @@ jt_ptl_add_route (int argc, char **argv) return -1; } - if (!g_net_is_set(argv[0])) - return (-1); + if (g_net_is_set(argv[0]) == 0) + return -1; - gateway_nid = libcfs_str2nid(argv[1]); - if (gateway_nid == LNET_NID_ANY) { - fprintf (stderr, "Can't parse gateway NID \"%s\"\n", argv[1]); - return (-1); - } + gateway_nid = libcfs_str2nid(argv[1]); + if (gateway_nid == LNET_NID_ANY) { + fprintf(stderr, "Can't parse gateway NID \"%s\"\n", argv[1]); + return -1; + } if (argc > 2) { hops = strtoul(argv[2], &end, 0); @@ -1127,51 +1136,52 @@ jt_ptl_add_route (int argc, char **argv) } } - LIBCFS_IOC_INIT(data); - data.ioc_net = g_net; - data.ioc_count = hops; - data.ioc_nid = gateway_nid; - data.ioc_priority = priority; + LIBCFS_IOC_INIT_V2(data, cfg_hdr); + data.cfg_net = g_net; + data.cfg_config_u.cfg_route.rtr_hop = hops; + data.cfg_nid = gateway_nid; + data.cfg_config_u.cfg_route.rtr_priority = priority; - rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_ADD_ROUTE, &data); - if (rc != 0) { - fprintf (stderr, "IOC_LIBCFS_ADD_ROUTE failed: %s\n", strerror (errno)); - return (-1); - } + rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_ADD_ROUTE, &data); + if (rc != 0) { + fprintf(stderr, "IOC_LIBCFS_ADD_ROUTE failed: %s\n", + strerror(errno)); + return -1; + } - return (0); + return 0; } int jt_ptl_del_route (int argc, char **argv) { - struct libcfs_ioctl_data data; - lnet_nid_t nid; - int rc; + struct lnet_ioctl_config_data data; + lnet_nid_t nid; + int rc; - if (argc != 2) { - fprintf (stderr, "usage: %s gatewayNID\n", argv[0]); - return (0); - } + if (argc != 2) { + fprintf(stderr, "usage: %s gatewayNID\n", argv[0]); + return 0; + } - if (!libcfs_str2anynid(&nid, argv[1])) { - fprintf (stderr, "Can't parse gateway NID " - "\"%s\"\n", argv[1]); - return -1; - } + if (libcfs_str2anynid(&nid, argv[1]) == 0) { + fprintf(stderr, "Can't parse gateway NID " + "\"%s\"\n", argv[1]); + return -1; + } - LIBCFS_IOC_INIT(data); - data.ioc_net = g_net_set ? g_net : LNET_NIDNET(LNET_NID_ANY); - data.ioc_nid = nid; + LIBCFS_IOC_INIT_V2(data, cfg_hdr); + data.cfg_net = g_net_set ? g_net : LNET_NIDNET(LNET_NID_ANY); + data.cfg_nid = nid; - rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_DEL_ROUTE, &data); - if (rc != 0) { - fprintf (stderr, "IOC_LIBCFS_DEL_ROUTE (%s) failed: %s\n", - libcfs_nid2str(nid), strerror (errno)); - return (-1); - } + rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_DEL_ROUTE, &data); + if (rc != 0) { + fprintf(stderr, "IOC_LIBCFS_DEL_ROUTE (%s) failed: %s\n", + libcfs_nid2str(nid), strerror(errno)); + return -1; + } - return (0); + return 0; } int @@ -1236,40 +1246,454 @@ jt_ptl_notify_router (int argc, char **argv) int jt_ptl_print_routes (int argc, char **argv) { - struct libcfs_ioctl_data data; - int rc; - int index; - __u32 net; - lnet_nid_t nid; - unsigned int hops; - int alive; + struct lnet_ioctl_config_data data; + int rc; + int index; + __u32 net; + lnet_nid_t nid; + unsigned int hops; + int alive; unsigned int pri; - for (index = 0;;index++) - { - LIBCFS_IOC_INIT(data); - data.ioc_count = index; + for (index = 0; ; index++) { + LIBCFS_IOC_INIT_V2(data, cfg_hdr); + data.cfg_count = index; - rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_ROUTE, &data); - if (rc != 0) - break; + rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_ROUTE, &data); + if (rc != 0) + break; - net = data.ioc_net; - hops = data.ioc_count; - nid = data.ioc_nid; - alive = data.ioc_flags; - pri = data.ioc_priority; + net = data.cfg_net; + hops = data.cfg_config_u.cfg_route.rtr_hop; + nid = data.cfg_nid; + alive = data.cfg_config_u.cfg_route.rtr_flags; + pri = data.cfg_config_u.cfg_route.rtr_priority; printf("net %18s hops %u gw %32s %s pri %u\n", libcfs_net2str(net), hops, libcfs_nid2str(nid), alive ? "up" : "down", pri); - } + } - if (errno != ENOENT) - fprintf(stderr, "Error getting routes: %s: check dmesg.\n", - strerror(errno)); + if (errno != ENOENT) + fprintf(stderr, "Error getting routes: %s: check dmesg.\n", + strerror(errno)); - return (0); + return 0; +} + +static int +fault_attr_nid_parse(char *str, lnet_nid_t *nid_p) +{ + lnet_nid_t nid; + __u32 net; + int rc = 0; + + /* NB: can't support range ipaddress except * and *@net */ + if (strlen(str) > 2 && str[0] == '*' && str[1] == '@') { + net = libcfs_str2net(str + 2); + if (net == LNET_NIDNET(LNET_NID_ANY)) + goto failed; + + nid = LNET_MKNID(net, LNET_NIDADDR(LNET_NID_ANY)); + } else { + rc = libcfs_str2anynid(&nid, str); + if (!rc) + goto failed; + } + + *nid_p = nid; + return 0; +failed: + fprintf(stderr, "Invalid NID : %s\n", str); + return -1; +} + +static int +fault_attr_msg_parse(char *msg_str, __u32 *mask_p) +{ + if (!strcasecmp(msg_str, "put")) { + *mask_p |= LNET_PUT_BIT; + return 0; + + } else if (!strcasecmp(msg_str, "ack")) { + *mask_p |= LNET_ACK_BIT; + return 0; + + } else if (!strcasecmp(msg_str, "get")) { + *mask_p |= LNET_GET_BIT; + return 0; + + } else if (!strcasecmp(msg_str, "reply")) { + *mask_p |= LNET_REPLY_BIT; + return 0; + } + + fprintf(stderr, "unknown message type %s\n", msg_str); + return -1; +} + +static int +fault_attr_ptl_parse(char *ptl_str, __u64 *mask_p) +{ + unsigned long rc = strtoul(optarg, NULL, 0); + + if (rc >= 64) { + fprintf(stderr, "invalid portal: %lu\n", rc); + return -1; + } + + *mask_p |= (1ULL << rc); + return 0; +} + +static int +fault_simul_rule_add(__u32 opc, char *name, int argc, char **argv) +{ + struct libcfs_ioctl_data data = {{0}}; + struct lnet_fault_attr attr; + char *optstr; + int rc; + + static struct option opts[] = { + {"source", required_argument, 0, 's'}, + {"dest", required_argument, 0, 'd'}, + {"rate", required_argument, 0, 'r'}, + {"interval", required_argument, 0, 'i'}, + {"latency", required_argument, 0, 'l'}, + {"portal", required_argument, 0, 'p'}, + {"message", required_argument, 0, 'm'}, + {0, 0, 0, 0} + }; + + if (argc == 1) { + fprintf(stderr, "Failed, please provide source, destination " + "and rate of rule\n"); + return -1; + } + + optstr = opc == LNET_CTL_DROP_ADD ? "s:d:r:i:p:m:" : "s:d:r:l:p:m:"; + memset(&attr, 0, sizeof(attr)); + while (1) { + char c = getopt_long(argc, argv, optstr, opts, NULL); + + if (c == -1) + break; + + switch (c) { + case 's': /* source NID/NET */ + rc = fault_attr_nid_parse(optarg, &attr.fa_src); + if (rc != 0) + goto getopt_failed; + break; + + case 'd': /* dest NID/NET */ + rc = fault_attr_nid_parse(optarg, &attr.fa_dst); + if (rc != 0) + goto getopt_failed; + break; + + case 'r': /* drop rate */ + if (opc == LNET_CTL_DROP_ADD) + attr.u.drop.da_rate = strtoul(optarg, NULL, 0); + else + attr.u.delay.la_rate = strtoul(optarg, NULL, 0); + break; + + case 'i': /* time interval (# seconds) for message drop */ + if (opc == LNET_CTL_DROP_ADD) + attr.u.drop.da_interval = strtoul(optarg, + NULL, 0); + else + attr.u.delay.la_interval = strtoul(optarg, + NULL, 0); + break; + + case 'l': /* seconds to wait before activating rule */ + attr.u.delay.la_latency = strtoul(optarg, NULL, 0); + break; + + case 'p': /* portal to filter */ + rc = fault_attr_ptl_parse(optarg, &attr.fa_ptl_mask); + if (rc != 0) + goto getopt_failed; + break; + + case 'm': /* message types to filter */ + rc = fault_attr_msg_parse(optarg, &attr.fa_msg_mask); + if (rc != 0) + goto getopt_failed; + break; + + default: + fprintf(stderr, "error: %s: option '%s' " + "unrecognized\n", argv[0], argv[optind - 1]); + goto getopt_failed; + } + } + optind = 1; + + if (opc == LNET_CTL_DROP_ADD) { + /* NB: drop rate and interval are exclusive to each other */ + if (!((attr.u.drop.da_rate == 0) ^ + (attr.u.drop.da_interval == 0))) { + fprintf(stderr, + "please provide either drop rate or interval " + "but not both at the same time.\n"); + return -1; + } + } else if (opc == LNET_CTL_DELAY_ADD) { + if (!((attr.u.delay.la_rate == 0) ^ + (attr.u.delay.la_interval == 0))) { + fprintf(stderr, + "please provide either delay rate or interval " + "but not both at the same time.\n"); + return -1; + } + + if (attr.u.delay.la_latency == 0) { + fprintf(stderr, "latency cannot be zero\n"); + return -1; + } + } + + if (attr.fa_src == 0 || attr.fa_dst == 0) { + fprintf(stderr, "Please provide both source and destination " + "of %s rule\n", name); + return -1; + } + + data.ioc_flags = opc; + data.ioc_inllen1 = sizeof(attr); + data.ioc_inlbuf1 = (char *)&attr; + if (libcfs_ioctl_pack(&data, &ioc_buf, IOC_BUF_SIZE) != 0) { + fprintf(stderr, "libcfs_ioctl_pack failed\n"); + return -1; + } + + rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_LNET_FAULT, ioc_buf); + if (rc != 0) { + fprintf(stderr, "add %s rule %s->%s failed: %s\n", + name, libcfs_nid2str(attr.fa_src), + libcfs_nid2str(attr.fa_dst), strerror(errno)); + return -1; + } + + printf("Added %s rule %s->%s (1/%d)\n", + name, libcfs_nid2str(attr.fa_src), libcfs_nid2str(attr.fa_dst), + opc == LNET_CTL_DROP_ADD ? + attr.u.drop.da_rate : attr.u.delay.la_rate); + return 0; + +getopt_failed: + optind = 1; + return -1; +} + +int +jt_ptl_drop_add(int argc, char **argv) +{ + return fault_simul_rule_add(LNET_CTL_DROP_ADD, "drop", argc, argv); +} + +int +jt_ptl_delay_add(int argc, char **argv) +{ + return fault_simul_rule_add(LNET_CTL_DELAY_ADD, "delay", argc, argv); +} + +static int +fault_simul_rule_del(__u32 opc, char *name, int argc, char **argv) +{ + struct libcfs_ioctl_data data = {{0}}; + struct lnet_fault_attr attr; + bool all = false; + int rc; + + static struct option opts[] = { + {"source", required_argument, 0, 's'}, + {"dest", required_argument, 0, 'd'}, + {"all", no_argument, 0, 'a'}, + {0, 0, 0, 0} + }; + + if (argc == 1) { + fprintf(stderr, "Failed, please provide source and " + "destination of rule\n"); + return -1; + } + + memset(&attr, 0, sizeof(attr)); + while (1) { + char c = getopt_long(argc, argv, "s:d:a", opts, NULL); + + if (c == -1 || all) + break; + + switch (c) { + case 's': + rc = fault_attr_nid_parse(optarg, &attr.fa_src); + if (rc != 0) + goto getopt_failed; + break; + case 'd': + rc = fault_attr_nid_parse(optarg, &attr.fa_dst); + if (rc != 0) + goto getopt_failed; + break; + case 'a': + attr.fa_src = attr.fa_dst = 0; + all = true; + break; + default: + fprintf(stderr, "error: %s: option '%s' " + "unrecognized\n", argv[0], argv[optind - 1]); + goto getopt_failed; + } + } + optind = 1; + + data.ioc_flags = opc; + data.ioc_inllen1 = sizeof(attr); + data.ioc_inlbuf1 = (char *)&attr; + if (libcfs_ioctl_pack(&data, &ioc_buf, IOC_BUF_SIZE) != 0) { + fprintf(stderr, "libcfs_ioctl_pack failed\n"); + return -1; + } + + rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_LNET_FAULT, ioc_buf); + if (rc != 0) { + fprintf(stderr, "remove %s rule %s->%s failed: %s\n", name, + all ? "all" : libcfs_nid2str(attr.fa_src), + all ? "all" : libcfs_nid2str(attr.fa_dst), + strerror(errno)); + return -1; + } + + libcfs_ioctl_unpack(&data, ioc_buf); + printf("Removed %d %s rules\n", data.ioc_count, name); + return 0; + +getopt_failed: + optind = 1; + return -1; +} + +int +jt_ptl_drop_del(int argc, char **argv) +{ + return fault_simul_rule_del(LNET_CTL_DROP_DEL, "drop", argc, argv); +} + +int +jt_ptl_delay_del(int argc, char **argv) +{ + return fault_simul_rule_del(LNET_CTL_DELAY_DEL, "delay", argc, argv); +} + +static int +fault_simul_rule_reset(__u32 opc, char *name, int argc, char **argv) +{ + struct libcfs_ioctl_data data = {{0}}; + int rc; + + LIBCFS_IOC_INIT(data); + data.ioc_flags = opc; + + rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_LNET_FAULT, &data); + if (rc != 0) { + fprintf(stderr, "failed to reset %s stats: %s\n", + name, strerror(errno)); + return -1; + } + return 0; +} + +int +jt_ptl_drop_reset(int argc, char **argv) +{ + return fault_simul_rule_reset(LNET_CTL_DROP_RESET, "drop", argc, argv); +} + +int +jt_ptl_delay_reset(int argc, char **argv) +{ + return fault_simul_rule_reset(LNET_CTL_DELAY_RESET, "delay", + argc, argv); +} + +static int +fault_simul_rule_list(__u32 opc, char *name, int argc, char **argv) +{ + struct libcfs_ioctl_data data = {{0}}; + struct lnet_fault_attr attr; + struct lnet_fault_stat stat; + int pos; + + printf("LNet %s rules:\n", name); + for (pos = 0;; pos++) { + int rc; + + memset(&attr, 0, sizeof(attr)); + memset(&stat, 0, sizeof(stat)); + + data.ioc_count = pos; + data.ioc_flags = opc; + data.ioc_inllen1 = sizeof(attr); + data.ioc_inlbuf1 = (char *)&attr; + data.ioc_inllen2 = sizeof(stat); + data.ioc_inlbuf2 = (char *)&stat; + if (libcfs_ioctl_pack(&data, &ioc_buf, IOC_BUF_SIZE) != 0) { + fprintf(stderr, "libcfs_ioctl_pack failed\n"); + return -1; + } + + rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_LNET_FAULT, ioc_buf); + if (rc != 0) + break; + + libcfs_ioctl_unpack(&data, ioc_buf); + + if (opc == LNET_CTL_DROP_LIST) { + printf("%s->%s (1/%d | %d) ptl "LPX64", msg %x, " + LPU64"/"LPU64", PUT "LPU64", ACK "LPU64", GET " + LPU64", REP "LPU64"\n", + libcfs_nid2str(attr.fa_src), + libcfs_nid2str(attr.fa_dst), + attr.u.drop.da_rate, attr.u.drop.da_interval, + attr.fa_ptl_mask, attr.fa_msg_mask, + stat.u.drop.ds_dropped, stat.fs_count, + stat.fs_put, stat.fs_ack, + stat.fs_get, stat.fs_reply); + + } else if (opc == LNET_CTL_DELAY_LIST) { + printf("%s->%s (1/%d | %d, latency %d) ptl "LPX64 + ", msg %x, "LPU64"/"LPU64", PUT "LPU64 + ", ACK "LPU64", GET "LPU64", REP "LPU64"\n", + libcfs_nid2str(attr.fa_src), + libcfs_nid2str(attr.fa_dst), + attr.u.delay.la_rate, attr.u.delay.la_interval, + attr.u.delay.la_latency, + attr.fa_ptl_mask, attr.fa_msg_mask, + stat.u.delay.ls_delayed, stat.fs_count, + stat.fs_put, stat.fs_ack, stat.fs_get, + stat.fs_reply); + } + } + printf("found total %d\n", pos); + + return 0; +} + +int +jt_ptl_drop_list(int argc, char **argv) +{ + return fault_simul_rule_list(LNET_CTL_DROP_LIST, "drop", argc, argv); +} + +int +jt_ptl_delay_list(int argc, char **argv) +{ + return fault_simul_rule_list(LNET_CTL_DELAY_LIST, "delay", argc, argv); } double