Whamcloud - gitweb
LU-10003 lnet: Update lctl ping to work with large NIDs
[fs/lustre-release.git] / lustre / utils / portals.c
index a0220a6..c29c334 100644 (file)
@@ -32,6 +32,9 @@
 #include <string.h>
 #include <sys/ioctl.h>
 #include <sys/time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
 #include <time.h>
 #include <linux/types.h>
 
@@ -41,7 +44,9 @@
 #include <linux/lnet/lnetctl.h>
 #include <linux/lnet/nidstr.h>
 #include <linux/lnet/socklnd.h>
+#include <lnetconfig/liblnetconfig.h>
 #include <lustre/lustreapi.h>
+#include <lustre_ioctl_old.h>
 
 unsigned int libcfs_debug;
 unsigned int libcfs_printk = D_CANTMASK;
@@ -95,31 +100,6 @@ lnet_parse_port(int *port, char *str)
        return -1;
 }
 
-#ifdef HAVE_GETHOSTBYNAME
-static struct hostent *
-ptl_gethostbyname(char *hname)
-{
-       struct hostent *he;
-
-       he = gethostbyname(hname);
-       if (!he) {
-               switch (h_errno) {
-               case HOST_NOT_FOUND:
-               case NO_ADDRESS:
-                       fprintf(stderr, "Unable to resolve hostname: %s\n",
-                               hname);
-                       break;
-               default:
-                       fprintf(stderr, "gethostbyname error for %s: %s\n",
-                               hname, strerror(h_errno));
-                       break;
-               }
-               return NULL;
-       }
-       return he;
-}
-#endif
-
 int
 lnet_parse_ipquad(__u32 *ipaddrp, char *str)
 {
@@ -139,9 +119,11 @@ lnet_parse_ipquad(__u32 *ipaddrp, char *str)
 int
 lnet_parse_ipaddr(__u32 *ipaddrp, char *str)
 {
-#ifdef HAVE_GETHOSTBYNAME
-       struct hostent *he;
-#endif
+       struct addrinfo *ai = NULL;
+       struct addrinfo *aip = NULL;
+       struct addrinfo hints;
+       int err = 0;
+       int rc = -1;
 
        if (!strcmp(str, "_all_")) {
                *ipaddrp = 0;
@@ -151,40 +133,67 @@ lnet_parse_ipaddr(__u32 *ipaddrp, char *str)
        if (lnet_parse_ipquad(ipaddrp, str) == 0)
                return 0;
 
-#ifdef HAVE_GETHOSTBYNAME
-       if ((('a' <= str[0] && str[0] <= 'z') ||
-            ('A' <= str[0] && str[0] <= 'Z')) &&
-             (he = ptl_gethostbyname(str)) != NULL) {
-               __u32 addr = *(__u32 *)he->h_addr;
+       memset(&hints, 0, sizeof(struct addrinfo));
+       hints.ai_family = AF_INET;
 
-               *ipaddrp = ntohl(addr);         /* HOST byte order */
-               return 0;
+       if (('a' <= str[0] && str[0] <= 'z') ||
+           ('A' <= str[0] && str[0] <= 'Z')) {
+               err = getaddrinfo(str, NULL, &hints, &ai);
+               if (err != 0) {
+                       fprintf(stderr,
+                               "failed to get addrinfo for %s: %s\n",
+                               str, gai_strerror(err));
+                       return -1;
+               }
+
+               for (aip = ai; aip; aip = aip->ai_next) {
+                       if (aip->ai_family == AF_INET && aip->ai_addr) {
+                               struct sockaddr_in *sin =
+                                       (void *)ai->ai_addr;
+
+                               __u32 addr = (__u32)sin->sin_addr.s_addr;
+                               *ipaddrp = ntohl(addr);
+                               break;
+                       }
+               }
+               /* FIXME: handle AF_INET6 */
+
+               if (!aip) {
+                       fprintf(stderr, "failed to get IP address for %s\n",
+                               str);
+                       rc = -1;
+                       goto out;
+               }
+
+               rc = 0;
+               goto out;
        }
-#endif
 
-       return -1;
+out:
+       if (ai != NULL)
+               freeaddrinfo(ai);
+       return rc;
 }
 
 char *
 ptl_ipaddr_2_str(__u32 ipaddr, char *str, size_t strsize, int lookup)
 {
-#ifdef HAVE_GETHOSTBYNAME
-       __u32 net_ip;
-       struct hostent *he;
+       struct sockaddr_in srcaddr;
 
        if (lookup) {
-               net_ip = htonl(ipaddr);
-               he = gethostbyaddr(&net_ip, sizeof(net_ip), AF_INET);
-               if (he) {
-                       snprintf(str, strsize, "%s", he->h_name);
-                       return str;
-               }
+               memset(&srcaddr, 0, sizeof(srcaddr));
+               srcaddr.sin_family = AF_INET;
+               srcaddr.sin_addr.s_addr = (in_addr_t)htonl(ipaddr);
+
+               if (getnameinfo((struct sockaddr *)&srcaddr, sizeof(srcaddr),
+                                 str, strsize, NULL, 0, 0) == 0)
+                       goto out;
        }
-#endif
 
-       sprintf(str, "%d.%d.%d.%d",
-               (ipaddr >> 24) & 0xff, (ipaddr >> 16) & 0xff,
-               (ipaddr >> 8) & 0xff, ipaddr & 0xff);
+       snprintf(str, strsize, "%d.%d.%d.%d",
+                (ipaddr >> 24) & 0xff, (ipaddr >> 16) & 0xff,
+                (ipaddr >> 8) & 0xff, ipaddr & 0xff);
+out:
        return str;
 }
 
@@ -218,12 +227,12 @@ lnet_parse_time(time_t *t, char *str)
 }
 
 int
-lnet_parse_nid(char *nid_str, struct lnet_process_id *id_ptr)
+lnet_parse_nid(char *nid_str, struct lnet_processid *id_ptr)
 {
        id_ptr->pid = LNET_PID_ANY;
-       id_ptr->nid = libcfs_str2nid(nid_str);
-       if (id_ptr->nid == LNET_NID_ANY) {
-               fprintf(stderr, "Can't parse nid \"%s\"\n", nid_str);
+       if (libcfs_strnid(&id_ptr->nid, nid_str) < 0 ||
+           LNET_NID_IS_ANY(&id_ptr->nid)) {
+               fprintf(stderr, "Invalid NID argument \"%s\"\n", nid_str);
                return -1;
        }
 
@@ -292,7 +301,7 @@ int ptl_initialize(int argc, char **argv)
 int jt_ptl_network(int argc, char **argv)
 {
        struct libcfs_ioctl_data data;
-       __u32 net = LNET_NIDNET(LNET_NID_ANY);
+       __u32 net = LNET_NET_ANY;
        int rc;
 
        if (argc != 2) {
@@ -335,7 +344,7 @@ int jt_ptl_network(int argc, char **argv)
        }
 
        net = libcfs_str2net(argv[1]);
-       if (net == LNET_NIDNET(LNET_NID_ANY)) {
+       if (net == LNET_NET_ANY) {
                fprintf(stderr, "Can't parse net %s\n", argv[1]);
                return -1;
        }
@@ -345,13 +354,20 @@ int jt_ptl_network(int argc, char **argv)
        return 0;
 }
 
+#ifndef IOC_LIBCFS_GET_NI
+#define IOC_LIBCFS_GET_NI      _IOWR('e', 50, IOCTL_LIBCFS_TYPE)
+#endif
+
 int
 jt_ptl_list_nids(int argc, char **argv)
 {
-       struct libcfs_ioctl_data data;
        int all = 0, return_nid = 0;
-       int count;
-       int rc;
+       yaml_emitter_t request;
+       yaml_parser_t reply;
+       yaml_event_t event;
+       struct nl_sock *sk;
+       bool done = false;
+       int rc = 0;
 
        all = (argc == 2) && (strcmp(argv[1], "all") == 0);
        /* Hack to pass back value */
@@ -362,7 +378,180 @@ jt_ptl_list_nids(int argc, char **argv)
                return 0;
        }
 
+       sk = nl_socket_alloc();
+       if (!sk)
+               goto old_api;
+
+       /* Setup parser to receive Netlink packets */
+       rc = yaml_parser_initialize(&reply);
+       if (rc == 0) {
+               yaml_parser_log_error(&reply, stderr, NULL);
+               goto old_api;
+       }
+
+       rc = yaml_parser_set_input_netlink(&reply, sk, false);
+       if (rc == 0) {
+               yaml_parser_log_error(&reply, stderr, NULL);
+               yaml_parser_delete(&reply);
+               goto old_api;
+       }
+
+       /* Create Netlink emitter to send request to kernel */
+       rc = yaml_emitter_initialize(&request);
+       if (rc == 0) {
+               yaml_parser_log_error(&reply, stderr, NULL);
+               yaml_parser_delete(&reply);
+               goto old_api;
+       }
+
+       rc = yaml_emitter_set_output_netlink(&request, sk, LNET_GENL_NAME, 1,
+                                            LNET_CMD_NETS, NLM_F_DUMP);
+       if (rc == 0) {
+               yaml_emitter_log_error(&request, stderr);
+               yaml_emitter_delete(&request);
+               yaml_parser_delete(&reply);
+               goto old_api;
+       }
+
+       yaml_emitter_open(&request);
+       yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
+       rc = yaml_emitter_emit(&request, &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(&request, &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(&request, &event);
+       if (rc == 0)
+               goto emitter_error;
+
+       /* no net_id */
+       if (!g_net_set || g_net == LNET_NET_ANY) {
+               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(&request, &event);
+               if (rc == 0)
+                       goto emitter_error;
+       } else {
+               char *net_id = libcfs_net2str(g_net);
+
+               yaml_sequence_start_event_initialize(&event, NULL,
+                                                    (yaml_char_t *)YAML_SEQ_TAG,
+                                                    1, YAML_ANY_SEQUENCE_STYLE);
+               rc = yaml_emitter_emit(&request, &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(&request, &event);
+               if (rc == 0)
+                       goto emitter_error;
+
+               yaml_scalar_event_initialize(&event, NULL,
+                                            (yaml_char_t *)YAML_STR_TAG,
+                                            (yaml_char_t *)"net type",
+                                            strlen("net type"),
+                                            1, 0, YAML_PLAIN_SCALAR_STYLE);
+               rc = yaml_emitter_emit(&request, &event);
+               if (rc == 0)
+                       goto emitter_error;
+
+               yaml_scalar_event_initialize(&event, NULL,
+                                            (yaml_char_t *)YAML_STR_TAG,
+                                            (yaml_char_t *)net_id,
+                                            strlen(net_id), 1, 0,
+                                            YAML_PLAIN_SCALAR_STYLE);
+               rc = yaml_emitter_emit(&request, &event);
+               if (rc == 0)
+                       goto emitter_error;
+
+               yaml_mapping_end_event_initialize(&event);
+               rc = yaml_emitter_emit(&request, &event);
+               if (rc == 0)
+                       goto emitter_error;
+
+               yaml_sequence_end_event_initialize(&event);
+               rc = yaml_emitter_emit(&request, &event);
+               if (rc == 0)
+                       goto emitter_error;
+       }
+       yaml_mapping_end_event_initialize(&event);
+       rc = yaml_emitter_emit(&request, &event);
+       if (rc == 0)
+               goto emitter_error;
+
+       yaml_document_end_event_initialize(&event, 0);
+       rc = yaml_emitter_emit(&request, &event);
+       if (rc == 0)
+               goto emitter_error;
+
+       rc = yaml_emitter_close(&request);
+emitter_error:
+       if (rc == 0) {
+               yaml_emitter_log_error(&request, stderr);
+               rc = -EINVAL;
+       }
+       yaml_emitter_delete(&request);
+
+       while (!done) {
+               rc = yaml_parser_parse(&reply, &event);
+               if (rc == 0)
+                       break;
+
+               if (event.type == YAML_SCALAR_EVENT &&
+                   strcmp((char *)event.data.scalar.value, "nid") == 0) {
+                       char *tmp;
+
+                       yaml_event_delete(&event);
+                       rc = yaml_parser_parse(&reply, &event);
+                       if (rc == 0) {
+                               yaml_event_delete(&event);
+                               break;
+                       }
+
+                       tmp = (char *)event.data.scalar.value;
+                       if (all || strcmp(tmp, "0@lo") != 0) {
+                               printf("%s\n", tmp);
+                               if (return_nid) {
+                                       *(__u64 *)(argv[1]) = libcfs_str2nid(tmp);
+                                       return_nid--;
+                               }
+                       }
+               }
+               done = (event.type == YAML_STREAM_END_EVENT);
+               yaml_event_delete(&event);
+       }
+
+       if (rc == 0)
+               yaml_parser_log_error(&reply, stderr, NULL);
+       yaml_parser_delete(&reply);
+old_api: {
+#ifdef IOC_LIBCFS_GET_NI
+       int count;
+
+       if (sk)
+               nl_socket_free(sk);
+       if (rc == 1)
+               return 0;
+
        for (count = 0;; count++) {
+               struct libcfs_ioctl_data data;
+
                LIBCFS_IOC_INIT(data);
                data.ioc_count = count;
                rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_NI, &data);
@@ -385,19 +574,26 @@ jt_ptl_list_nids(int argc, char **argv)
                }
        }
 
-       return 0;
+#else
+       rc = -1;
+#endif
+       }
+       return rc;
 }
 
 int
 jt_ptl_which_nid(int argc, char **argv)
 {
-       struct libcfs_ioctl_data data;
+       struct lnet_nid best_nid = LNET_ANY_NID;
+       yaml_emitter_t request;
+       yaml_parser_t reply;
+       yaml_event_t event;
+       struct nl_sock *sk;
        int best_dist = 0;
        int best_order = 0;
-       lnet_nid_t   best_nid = LNET_NID_ANY;
-       int dist;
-       int order;
-       lnet_nid_t nid;
+       bool done = false;
+       int dist = 0;
+       int order = 0;
        char *nidstr;
        int rc;
        int i;
@@ -407,16 +603,188 @@ jt_ptl_which_nid(int argc, char **argv)
                return 0;
        }
 
+       /* Create Netlink emitter to send request to kernel */
+       sk = nl_socket_alloc();
+       if (!sk)
+               goto old_api;
+
+       /* Setup parser to recieve Netlink packets */
+       rc = yaml_parser_initialize(&reply);
+       if (rc == 0)
+               goto old_api;
+
+       rc = yaml_parser_set_input_netlink(&reply, sk, false);
+       if (rc == 0)
+               goto free_reply;
+
+       /* Create Netlink emitter to send request to kernel */
+       rc = yaml_emitter_initialize(&request);
+       if (rc == 0)
+               goto free_reply;
+
+       rc = yaml_emitter_set_output_netlink(&request, sk, LNET_GENL_NAME,
+                                            LNET_GENL_VERSION,
+                                            LNET_CMD_PEER_DIST, NLM_F_DUMP);
+       if (rc == 0)
+               goto emitter_error;
+
+       yaml_emitter_open(&request);
+       yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
+       rc = yaml_emitter_emit(&request, &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(&request, &event);
+       if (rc == 0)
+               goto emitter_error;
+
+       yaml_scalar_event_initialize(&event, NULL,
+                                    (yaml_char_t *)YAML_STR_TAG,
+                                    (yaml_char_t *)"peer",
+                                    strlen("peer"), 1, 0,
+                                    YAML_PLAIN_SCALAR_STYLE);
+       rc = yaml_emitter_emit(&request, &event);
+       if (rc == 0)
+               goto emitter_error;
+
+       yaml_sequence_start_event_initialize(&event, NULL,
+                                            (yaml_char_t *)YAML_SEQ_TAG,
+                                            1, YAML_BLOCK_SEQUENCE_STYLE);
+       rc = yaml_emitter_emit(&request, &event);
+       if (rc == 0)
+               goto emitter_error;
+
+       for (i = 1; i < argc; i++) {
+               struct lnet_nid nid;
+
+               nidstr = argv[i];
+               if (strcmp(nidstr, "*") == 0)
+                       nidstr = "<?>";
+
+               rc = libcfs_strnid(&nid, nidstr);
+               if (rc < 0 || nid_same(&nid, &LNET_ANY_NID)) {
+                       fprintf(stderr, "Can't parse NID %s\n", nidstr);
+                       return -1;
+               }
+
+               yaml_scalar_event_initialize(&event, NULL,
+                                            (yaml_char_t *)YAML_STR_TAG,
+                                            (yaml_char_t *)nidstr,
+                                            strlen(nidstr), 1, 0,
+                                            YAML_PLAIN_SCALAR_STYLE);
+               rc = yaml_emitter_emit(&request, &event);
+               if (rc == 0)
+                       goto emitter_error;
+       }
+
+       yaml_sequence_end_event_initialize(&event);
+       rc = yaml_emitter_emit(&request, &event);
+       if (rc == 0)
+               goto emitter_error;
+
+       yaml_mapping_end_event_initialize(&event);
+       rc = yaml_emitter_emit(&request, &event);
+       if (rc == 0)
+               goto emitter_error;
+
+       yaml_document_end_event_initialize(&event, 0);
+       rc = yaml_emitter_emit(&request, &event);
+       if (rc == 0)
+               goto emitter_error;
+
+       rc = yaml_emitter_close(&request);
+emitter_error:
+       if (rc == 0) {
+               yaml_emitter_log_error(&request, stderr);
+               rc = -EINVAL;
+       }
+       yaml_emitter_delete(&request);
+
+       while (!done) {
+               rc = yaml_parser_parse(&reply, &event);
+               if (rc == 0)
+                       break;
+
+               if (event.type != YAML_SCALAR_EVENT)
+                       goto not_scalar;
+
+
+               if (strcmp((char *)event.data.scalar.value, "nid") == 0) {
+                       yaml_event_delete(&event);
+                       rc = yaml_parser_parse(&reply, &event);
+                       if (rc == 0) {
+                               yaml_event_delete(&event);
+                               break;
+                       }
+
+                       nidstr = (char *)event.data.scalar.value;
+
+                       if (nid_same(&best_nid, &LNET_ANY_NID) ||
+                           dist < best_dist ||
+                           (dist == best_dist && order < best_order)) {
+                               best_dist = dist;
+                               best_order = order;
+                               libcfs_strnid(&best_nid, nidstr);
+                       }
+               } else if (strcmp((char *)event.data.scalar.value,
+                                 "distance") == 0) {
+                       yaml_event_delete(&event);
+                       rc = yaml_parser_parse(&reply, &event);
+                       if (rc == 0) {
+                               yaml_event_delete(&event);
+                               break;
+                       }
+
+                       dist = strtol((char *)event.data.scalar.value, NULL, 10);
+               } else if (strcmp((char *)event.data.scalar.value,
+                                 "order") == 0) {
+                       yaml_event_delete(&event);
+                       rc = yaml_parser_parse(&reply, &event);
+                       if (rc == 0) {
+                               yaml_event_delete(&event);
+                               break;
+                       }
+
+                       order = strtol((char *)event.data.scalar.value, NULL, 10);
+               }
+not_scalar:
+               done = (event.type == YAML_STREAM_END_EVENT);
+               yaml_event_delete(&event);
+       }
+
+free_reply:
+       if (rc == 0) {
+               /* yaml_* functions return 0 for error */
+               const char *msg = yaml_parser_get_reader_error(&reply);
+
+               fprintf(stderr, "Unexpected distance: %s\n", msg);
+               rc = -1;
+       } else if (rc == 1) {
+               /* yaml_* functions return 1 for success */
+               rc = 0;
+       }
+
+       yaml_parser_delete(&reply);
+       nl_socket_free(sk);
+       goto finished;
+
+old_api:
        for (i = 1; i < argc; i++) {
+               struct libcfs_ioctl_data data;
+               lnet_nid_t nid4;
+
                nidstr = argv[i];
-               nid = libcfs_str2nid(nidstr);
-               if (nid == LNET_NID_ANY) {
+               nid4 = libcfs_str2nid(nidstr);
+               if (nid4 == LNET_NID_ANY) {
                        fprintf(stderr, "Can't parse NID %s\n", nidstr);
                        return -1;
                }
 
                LIBCFS_IOC_INIT(data);
-               data.ioc_nid = nid;
+               data.ioc_nid = nid4;
 
                rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_LNET_DIST, &data);
                if (rc != 0) {
@@ -437,21 +805,21 @@ jt_ptl_which_nid(int argc, char **argv)
                        return -1;
                }
 
-               if (best_nid == LNET_NID_ANY ||
+               if (nid_same(&best_nid, &LNET_ANY_NID) ||
                    dist < best_dist ||
                    (dist == best_dist && order < best_order)) {
                        best_dist = dist;
                        best_order = order;
-                       best_nid = nid;
+                       lnet_nid4_to_nid(nid4, &best_nid);
                }
        }
-
-       if (best_nid == LNET_NID_ANY) {
+finished:
+       if (nid_same(&best_nid, &LNET_ANY_NID)) {
                fprintf(stderr, "No reachable NID\n");
                return -1;
        }
 
-       printf("%s\n", libcfs_nid2str(best_nid));
+       printf("%s\n", libcfs_nidstr(&best_nid));
        return 0;
 }
 
@@ -896,27 +1264,32 @@ int jt_ptl_push_connection(int argc, char **argv)
        return 0;
 }
 
+#ifndef IOC_LIBCFS_PING_PEER
+#define IOC_LIBCFS_PING_PEER           _IOWR('e', 62, IOCTL_LIBCFS_TYPE)
+#endif
+
 int jt_ptl_ping(int argc, char **argv)
 {
+       bool done = false, print = true;
        int rc;
        int timeout;
-       struct lnet_process_id id;
-       struct lnet_process_id ids[16];
-       int maxids = sizeof(ids) / sizeof(ids[0]);
-       struct libcfs_ioctl_data data;
+       struct lnet_processid id;
+       yaml_emitter_t request;
+       yaml_parser_t reply;
+       yaml_event_t event;
+       struct nl_sock *sk;
        char *sep;
-       int i;
 
        if (argc < 2) {
                fprintf(stderr, "usage: %s id [timeout (secs)]\n", argv[0]);
-               return 0;
+               return -EINVAL;
        }
 
        sep = strchr(argv[1], '-');
        if (!sep) {
                rc = lnet_parse_nid(argv[1], &id);
                if (rc != 0)
-                       return -1;
+                       return -EINVAL;
        } else {
                char   *end;
 
@@ -929,15 +1302,14 @@ int jt_ptl_ping(int argc, char **argv)
                if (end != sep) { /* assuming '-' is part of hostname */
                        rc = lnet_parse_nid(argv[1], &id);
                        if (rc != 0)
-                               return -1;
+                               return -EINVAL;
                } else {
-                       id.nid = libcfs_str2nid(sep + 1);
-
-                       if (id.nid == LNET_NID_ANY) {
+                       if (libcfs_strnid(&id.nid, (sep + 1)) < 0 ||
+                           LNET_NID_IS_ANY(&id.nid)) {
                                fprintf(stderr,
-                                       "Can't parse process id \"%s\"\n",
+                                       "Invalid PID argument \"%s\"\n",
                                        argv[1]);
-                               return -1;
+                               return -EINVAL;
                        }
                }
        }
@@ -947,35 +1319,236 @@ int jt_ptl_ping(int argc, char **argv)
                if (timeout > 120 * 1000) {
                        fprintf(stderr, "Timeout %s is to large\n",
                                argv[2]);
-                       return -1;
+                       return -EINVAL;
                }
        } else {
                timeout = 1000; /* default 1 second timeout */
        }
 
-       LIBCFS_IOC_INIT(data);
-       data.ioc_nid     = id.nid;
-       data.ioc_u32[0]  = id.pid;
-       data.ioc_u32[1]  = timeout;
-       data.ioc_plen1   = sizeof(ids);
-       data.ioc_pbuf1   = (char *)ids;
+       /* Create Netlink emitter to send request to kernel */
+       sk = nl_socket_alloc();
+       if (!sk)
+               goto old_api;
+
+       /* Setup parser to recieve Netlink packets */
+       rc = yaml_parser_initialize(&reply);
+       if (rc == 0)
+               goto old_api;
+
+       rc = yaml_parser_set_input_netlink(&reply, sk, false);
+       if (rc == 0)
+               goto free_reply;
+
+       /* Create Netlink emitter to send request to kernel */
+       rc = yaml_emitter_initialize(&request);
+       if (rc == 0)
+               goto free_reply;
+
+       rc = yaml_emitter_set_output_netlink(&request, sk, LNET_GENL_NAME,
+                                            LNET_GENL_VERSION, LNET_CMD_PING,
+                                            NLM_F_DUMP);
+       if (rc == 0)
+               goto emitter_error;
+
+       yaml_emitter_open(&request);
+       yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
+       rc = yaml_emitter_emit(&request, &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(&request, &event);
+       if (rc == 0)
+               goto emitter_error;
+
+       yaml_scalar_event_initialize(&event, NULL,
+                                    (yaml_char_t *)YAML_STR_TAG,
+                                    (yaml_char_t *)"ping",
+                                    strlen("ping"), 1, 0,
+                                    YAML_PLAIN_SCALAR_STYLE);
+       rc = yaml_emitter_emit(&request, &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(&request, &event);
+       if (rc == 0)
+               goto emitter_error;
+
+       if (timeout != 1000) {
+               yaml_scalar_event_initialize(&event, NULL,
+                                            (yaml_char_t *)YAML_STR_TAG,
+                                            (yaml_char_t *)"timeout",
+                                            strlen("timeout"), 1, 0,
+                                            YAML_PLAIN_SCALAR_STYLE);
+               rc = yaml_emitter_emit(&request, &event);
+               if (rc == 0)
+                       goto emitter_error;
+
+               yaml_scalar_event_initialize(&event, NULL,
+                                            (yaml_char_t *)YAML_INT_TAG,
+                                            (yaml_char_t *)argv[2],
+                                            strlen(argv[2]), 1, 0,
+                                            YAML_PLAIN_SCALAR_STYLE);
+               rc = yaml_emitter_emit(&request, &event);
+               if (rc == 0)
+                       goto emitter_error;
+       }
+
+       yaml_scalar_event_initialize(&event, NULL,
+                                    (yaml_char_t *)YAML_STR_TAG,
+                                    (yaml_char_t *)"nids",
+                                    strlen("nids"), 1, 0,
+                                    YAML_PLAIN_SCALAR_STYLE);
+       rc = yaml_emitter_emit(&request, &event);
+       if (rc == 0)
+               goto emitter_error;
+
+       yaml_sequence_start_event_initialize(&event, NULL,
+                                            (yaml_char_t *)YAML_SEQ_TAG,
+                                            1, YAML_FLOW_SEQUENCE_STYLE);
+       rc = yaml_emitter_emit(&request, &event);
+       if (rc == 0)
+               goto emitter_error;
+
+       /* convert NID to string, in case libcfs_str2nid() did name lookup */
+       yaml_scalar_event_initialize(&event, NULL,
+                                    (yaml_char_t *)YAML_STR_TAG,
+                                    (yaml_char_t *)libcfs_nidstr(&id.nid),
+                                    strlen(libcfs_nidstr(&id.nid)), 1, 0,
+                                    YAML_PLAIN_SCALAR_STYLE);
+       rc = yaml_emitter_emit(&request, &event);
+       if (rc == 0)
+               goto emitter_error;
+
+       yaml_sequence_end_event_initialize(&event);
+       rc = yaml_emitter_emit(&request, &event);
+       if (rc == 0)
+               goto emitter_error;
+
+       yaml_mapping_end_event_initialize(&event);
+       rc = yaml_emitter_emit(&request, &event);
+       if (rc == 0)
+               goto emitter_error;
+
+       yaml_mapping_end_event_initialize(&event);
+       rc = yaml_emitter_emit(&request, &event);
+       if (rc == 0)
+               goto emitter_error;
+
+       yaml_document_end_event_initialize(&event, 0);
+       rc = yaml_emitter_emit(&request, &event);
+       if (rc == 0)
+               goto emitter_error;
+
+       rc = yaml_emitter_close(&request);
+emitter_error:
+       if (rc == 0) {
+               yaml_emitter_log_error(&request, stderr);
+               rc = -EINVAL;
+               goto old_api;
+       }
+       yaml_emitter_delete(&request);
+
+       /* Now parse the reply results */
+       while (!done) {
+               rc = yaml_parser_parse(&reply, &event);
+               if (rc == 0)
+                       break;
+
+               if (event.type != YAML_SCALAR_EVENT)
+                       goto skip;
+
+               if (strcmp((char *)event.data.scalar.value, "nid") == 0) {
+                       yaml_event_delete(&event);
+                       rc = yaml_parser_parse(&reply, &event);
+                       if (rc == 0) {
+                               yaml_event_delete(&event);
+                               goto free_reply;
+                       }
+                       if (print) {
+                               /* Print 0@lo. Its not sent */
+                               printf("12345-0@lo\n");
+                               print = false;
+                       }
+                       printf("%s\n", (char *)event.data.scalar.value);
+               } else if (strcmp((char *)event.data.scalar.value,
+                                 "errno") == 0) {
+                       yaml_event_delete(&event);
+                       rc = yaml_parser_parse(&reply, &event);
+                       if (rc == 0) {
+                               yaml_event_delete(&event);
+                               goto free_reply;
+                       }
+                       rc = strtol((char *)event.data.scalar.value, NULL, 10);
+                       fprintf(stdout, "failed to ping %s: %s\n",
+                               argv[1], strerror(-rc));
+                       break; /* "rc" is clobbered if loop is run again */
+               }
+skip:
+               done = (event.type == YAML_STREAM_END_EVENT);
+               yaml_event_delete(&event);
+       }
+free_reply:
+       if (rc == 0) {
+               /* yaml_* functions return 0 for error */
+               const char *msg = yaml_parser_get_reader_error(&reply);
+
+               rc = errno ? -errno : -EHOSTUNREACH;
+               if (strcmp(msg, "Unspecific failure") != 0) {
+                       fprintf(stdout, "failed to ping %s: %s\n",
+                               argv[1], msg);
+               } else {
+                       fprintf(stdout, "failed to ping %s: %s\n",
+                               argv[1], strerror(errno));
+               }
+       } else if (rc == 1) {
+               /* yaml_* functions return 1 for success */
+               rc = 0;
+       }
+       yaml_parser_delete(&reply);
+       nl_socket_free(sk);
+       return rc;
+old_api:
+#ifdef IOC_LIBCFS_PING_PEER
+       {
+       struct lnet_process_id ids[LNET_INTERFACES_MAX_DEFAULT];
+       int maxids = sizeof(ids) / sizeof(ids[0]);
+       struct lnet_ioctl_ping_data ping = { { 0 } };
+       int i;
+
+       if (sk)
+               nl_socket_free(sk);
+
+       LIBCFS_IOC_INIT_V2(ping, ping_hdr);
+       ping.ping_hdr.ioc_len = sizeof(ping);
+       ping.ping_id = lnet_pid_to_pid4(&id);
+       ping.ping_src = LNET_NID_ANY;
+       ping.op_param = timeout;
+       ping.ping_count = maxids;
+       ping.ping_buf = ids;
 
-       rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_PING, &data);
+       rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_PING_PEER, &ping);
        if (rc != 0) {
-               fprintf(stderr, "failed to ping %s: %s\n",
-                       id.pid == LNET_PID_ANY ?
-                       libcfs_nid2str(id.nid) : libcfs_id2str(id),
+               fprintf(stderr, "failed to ping %s: %s\n", argv[1],
                        strerror(errno));
-               return -1;
+               return rc;
        }
 
-       for (i = 0; i < data.ioc_count && i < maxids; i++)
+       for (i = 0; i < ping.ping_count && i < maxids; i++)
                printf("%s\n", libcfs_id2str(ids[i]));
 
-       if (data.ioc_count > maxids)
-               printf("%d out of %d ids listed\n", maxids, data.ioc_count);
-
-       return 0;
+       if (ping.ping_count > maxids)
+               printf("%d out of %d ids listed\n", maxids, ping.ping_count);
+       }
+#else
+       rc = -ENOTTY;
+#endif
+       return rc;
 }
 
 int jt_ptl_mynid(int argc, char **argv)
@@ -1050,6 +1623,340 @@ jt_ptl_fail_nid(int argc, char **argv)
        return 0;
 }
 
+static int ptl_yaml_route_display(yaml_parser_t *reply)
+{
+       char gw[LNET_MAX_STR_LEN], net[18];
+       bool done = false, alive = false;
+       int hops = -1, prio = -1;
+       yaml_event_t event;
+       int rc;
+
+       /* Now parse the reply results */
+       while (!done) {
+               char *value;
+
+               rc = yaml_parser_parse(reply, &event);
+               if (rc == 0)
+                       break;
+
+               if (event.type == YAML_SEQUENCE_END_EVENT) {
+                       printf("net %18s hops %d gw %32.128s %s pri %u\n",
+                              net, hops, gw, alive ? "up" : "down",
+                              prio);
+                       memset(net, '\0', sizeof(net));
+                       memset(gw, '\0', sizeof(gw));
+                       prio = -1;
+                       hops = -1;
+               }
+
+               if (event.type != YAML_SCALAR_EVENT)
+                       goto skip;
+
+               value = (char *)event.data.scalar.value;
+               if (strcmp(value, "net") == 0) {
+                       yaml_event_delete(&event);
+                       rc = yaml_parser_parse(reply, &event);
+                       if (rc == 0) {
+                               yaml_event_delete(&event);
+                               goto free_reply;
+                       }
+
+                       value = (char *)event.data.scalar.value;
+                       strncpy(net, value, sizeof(net) - 1);
+               } else if (strcmp(value, "gateway") == 0) {
+                       yaml_event_delete(&event);
+                       rc = yaml_parser_parse(reply, &event);
+                       if (rc == 0) {
+                               yaml_event_delete(&event);
+                               goto free_reply;
+                       }
+
+                       value = (char *)event.data.scalar.value;
+                       strncpy(gw, value, sizeof(gw) - 1);
+               } else if (strcmp(value, "state") == 0) {
+                       yaml_event_delete(&event);
+                       rc = yaml_parser_parse(reply, &event);
+                       if (rc == 0) {
+                               yaml_event_delete(&event);
+                               goto free_reply;
+                       }
+
+                       value = (char *)event.data.scalar.value;
+                       if (strcmp(value, "up") == 0) {
+                               alive = true;
+                       } else if (strcmp(value, "down") == 0) {
+                               alive = false;
+                       }
+               } else if (strcmp(value, "hop") == 0) {
+                       yaml_event_delete(&event);
+                       rc = yaml_parser_parse(reply, &event);
+                       if (rc == 0) {
+                               yaml_event_delete(&event);
+                               goto free_reply;
+                       }
+
+                       value = (char *)event.data.scalar.value;
+                       hops = strtol(value, NULL, 10);
+               } else if (strcmp(value, "priority") == 0) {
+                       yaml_event_delete(&event);
+                       rc = yaml_parser_parse(reply, &event);
+                       if (rc == 0) {
+                               yaml_event_delete(&event);
+                               goto free_reply;
+                       }
+
+                       value = (char *)event.data.scalar.value;
+                       prio = strtol(value, NULL, 10);
+               }
+skip:
+               done = (event.type == YAML_STREAM_END_EVENT);
+               yaml_event_delete(&event);
+       }
+
+free_reply:
+       return rc;
+}
+
+static int ptl_yaml_route(char *nw, char *gws, int hops, int prio, bool enable,
+                         time_t notify_time, int flags, int version)
+{
+       struct nl_sock *sk = NULL;
+       const char *msg = NULL;
+       yaml_emitter_t output;
+       yaml_parser_t reply;
+       yaml_event_t event;
+       int rc;
+
+       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 || gws) {
+               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;
+
+               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;
+
+               if (nw) {
+                       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;
+               }
+
+               if (gws) {
+                       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 *)gws,
+                                                    strlen(gws), 1, 0,
+                                                    YAML_PLAIN_SCALAR_STYLE);
+                       rc = yaml_emitter_emit(&output, &event);
+                       if (rc == 0)
+                               goto emitter_error;
+               }
+
+               if (notify_time) {
+                       char when[INT_STRING_LEN];
+
+                       yaml_scalar_event_initialize(&event, NULL,
+                                                    (yaml_char_t *)YAML_STR_TAG,
+                                                    (yaml_char_t *)"notify_time",
+                                                    strlen("notify_time"), 1, 0,
+                                                    YAML_PLAIN_SCALAR_STYLE);
+                       rc = yaml_emitter_emit(&output, &event);
+                       if (rc == 0)
+                               goto emitter_error;
+
+                       snprintf(when, sizeof(when), "%ld", notify_time);
+                       yaml_scalar_event_initialize(&event, NULL,
+                                                    (yaml_char_t *)YAML_INT_TAG,
+                                                    (yaml_char_t *)when,
+                                                    strlen(when), 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 *)"state",
+                                            strlen("state"), 1, 0,
+                                            YAML_PLAIN_SCALAR_STYLE);
+               rc = yaml_emitter_emit(&output, &event);
+               if (rc == 0)
+                       goto emitter_error;
+
+               if (enable)
+                       yaml_scalar_event_initialize(&event, NULL,
+                                                    (yaml_char_t *)YAML_STR_TAG,
+                                                    (yaml_char_t *)"up",
+                                                    strlen("up"), 1, 0,
+                                                    YAML_PLAIN_SCALAR_STYLE);
+               else
+                       yaml_scalar_event_initialize(&event, NULL,
+                                                    (yaml_char_t *)YAML_STR_TAG,
+                                                    (yaml_char_t *)"down",
+                                                    strlen("down"), 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 {
+               if (flags != NLM_F_DUMP) {
+                       yaml_document_t errmsg;
+
+                       rc = yaml_parser_load(&reply, &errmsg);
+                       if (rc == 1) {
+                               yaml_emitter_t debug;
+
+                               rc = yaml_emitter_initialize(&debug);
+                               if (rc == 1) {
+                                       yaml_emitter_set_indent(&debug,
+                                                               LNET_DEFAULT_INDENT);
+                                       yaml_emitter_set_output_file(&debug,
+                                                                    stdout);
+                                       rc = yaml_emitter_dump(&debug,
+                                                              &errmsg);
+                               } else if (rc == 0) {
+                                       yaml_emitter_log_error(&debug, stderr);
+                                       rc = -EINVAL;
+                               }
+                               yaml_emitter_delete(&debug);
+                       }
+                       yaml_document_delete(&errmsg);
+               } else {
+                       rc = ptl_yaml_route_display(&reply);
+               }
+               if (rc == 0)
+                       msg = yaml_parser_get_reader_error(&reply);
+       }
+       yaml_emitter_delete(&output);
+free_reply:
+       if (msg)
+               fprintf(stdout, "%s\n", msg);
+       yaml_parser_delete(&reply);
+       nl_socket_free(sk);
+
+       return rc == 1 ? 0 : rc;
+}
+
 int
 jt_ptl_add_route(int argc, char **argv)
 {
@@ -1094,6 +2001,14 @@ jt_ptl_add_route(int argc, char **argv)
                }
        }
 
+       rc = ptl_yaml_route(libcfs_net2str(g_net), argv[1], hops,
+                           priority, false, 0, NLM_F_CREATE, LNET_GENL_VERSION);
+       if (rc <= 0) {
+               if (rc == -EOPNOTSUPP)
+                       goto old_api;
+               return rc;
+       }
+old_api:
        LIBCFS_IOC_INIT_V2(data, cfg_hdr);
        data.cfg_net = g_net;
        data.cfg_config_u.cfg_route.rtr_hop = hops;
@@ -1127,8 +2042,16 @@ jt_ptl_del_route(int argc, char **argv)
                return -1;
        }
 
+       rc = ptl_yaml_route(g_net_set ? libcfs_net2str(g_net) : NULL, argv[1],
+                           -1, -1, false, 0, 0, LNET_GENL_VERSION);
+       if (rc <= 0) {
+               if (rc == -EOPNOTSUPP)
+                       goto old_api;
+               return rc;
+       }
+old_api:
        LIBCFS_IOC_INIT_V2(data, cfg_hdr);
-       data.cfg_net = g_net_set ? g_net : LNET_NIDNET(LNET_NID_ANY);
+       data.cfg_net = g_net_set ? g_net : LNET_NET_ANY;
        data.cfg_nid = nid;
 
        rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_DEL_ROUTE, &data);
@@ -1183,6 +2106,14 @@ jt_ptl_notify_router(int argc, char **argv)
                return -1;
        }
 
+       rc = ptl_yaml_route(g_net_set ? libcfs_net2str(g_net) : NULL, argv[1],
+                           -1, -1, enable, when, NLM_F_REPLACE, LNET_GENL_VERSION);
+       if (rc <= 0) {
+               if (rc == -EOPNOTSUPP)
+                       goto old_api;
+               return rc;
+       }
+old_api:
        LIBCFS_IOC_INIT(data);
        data.ioc_nid = nid;
        data.ioc_flags = enable;
@@ -1207,10 +2138,18 @@ jt_ptl_print_routes(int argc, char **argv)
        int index;
        __u32 net;
        lnet_nid_t nid;
-       unsigned int hops;
+       int hops;
        int alive;
        unsigned int pri;
 
+       rc = ptl_yaml_route(NULL, NULL, -1, -1, false, 0, NLM_F_DUMP,
+                           LNET_GENL_VERSION);
+       if (rc <= 0) {
+               if (rc == -EOPNOTSUPP)
+                       goto old_api;
+               return rc;
+       }
+old_api:
        for (index = 0; ; index++) {
                LIBCFS_IOC_INIT_V2(data, cfg_hdr);
                data.cfg_count = index;
@@ -1225,7 +2164,7 @@ jt_ptl_print_routes(int argc, char **argv)
                alive   = data.cfg_config_u.cfg_route.rtr_flags & LNET_RT_ALIVE;
                pri     = data.cfg_config_u.cfg_route.rtr_priority;
 
-               printf("net %18s hops %u gw %32s %s pri %u\n",
+               printf("net %18s hops %d gw %32s %s pri %u\n",
                       libcfs_net2str(net), hops,
                       libcfs_nid2str(nid), alive ? "up" : "down", pri);
        }
@@ -1247,7 +2186,7 @@ fault_attr_nid_parse(char *str, lnet_nid_t *nid_p)
        /* 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))
+               if (net == LNET_NET_ANY)
                        goto failed;
 
                nid = LNET_MKNID(net, LNET_NIDADDR(LNET_NID_ANY));