]> git.proxmox.com Git - mirror_iproute2.git/blobdiff - rdma/utils.c
Merge branch 'master' into next
[mirror_iproute2.git] / rdma / utils.c
index 4840bf226d54d01cadbc46e298a7bdb4686d6aa1..37659011d167c77ea540c52c5243ac90f8767652 100644 (file)
@@ -1,11 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
 /*
  * utils.c     RDMA tool
- *
- *              This program is free software; you can redistribute it and/or
- *              modify it under the terms of the GNU General Public License
- *              as published by the Free Software Foundation; either version
- *              2 of the License, or (at your option) any later version.
- *
  * Authors:     Leon Romanovsky <leonro@mellanox.com>
  */
 
@@ -61,7 +56,7 @@ bool rd_no_arg(struct rd *rd)
  * mlx5_1/1    | 1          | false
  * mlx5_1/-    | 0          | false
  *
- * In strict mode, /- will return error.
+ * In strict port mode, a non-0 port must be provided
  */
 static int get_port_from_argv(struct rd *rd, uint32_t *port,
                              bool *is_dump_all, bool strict_port)
@@ -69,7 +64,7 @@ static int get_port_from_argv(struct rd *rd, uint32_t *port,
        char *slash;
 
        *port = 0;
-       *is_dump_all = true;
+       *is_dump_all = strict_port ? false : true;
 
        slash = strchr(rd_argv(rd), '/');
        /* if no port found, return 0 */
@@ -88,6 +83,9 @@ static int get_port_from_argv(struct rd *rd, uint32_t *port,
                if (!*port && strlen(slash))
                        return -EINVAL;
        }
+       if (strict_port && (*port == 0))
+               return -EINVAL;
+
        return 0;
 }
 
@@ -126,6 +124,7 @@ static int add_filter(struct rd *rd, char *key, char *value,
        struct filter_entry *fe;
        bool key_found = false;
        int idx = 0;
+       char *endp;
        int ret;
 
        fe = calloc(1, sizeof(*fe));
@@ -168,6 +167,11 @@ static int add_filter(struct rd *rd, char *key, char *value,
                goto err_alloc;
        }
 
+       errno = 0;
+       strtol(fe->value, &endp, 10);
+       if (valid_filters[idx].is_doit && !errno && *endp == '\0')
+               fe->is_doit = true;
+
        for (idx = 0; idx < strlen(fe->value); idx++)
                fe->value[idx] = tolower(fe->value[idx]);
 
@@ -182,6 +186,20 @@ err:
        return ret;
 }
 
+bool rd_doit_index(struct rd *rd, uint32_t *idx)
+{
+       struct filter_entry *fe;
+
+       list_for_each_entry(fe, &rd->filter_list, list) {
+               if (fe->is_doit) {
+                       *idx = atoi(fe->value);
+                       return true;
+               }
+       }
+
+       return false;
+}
+
 int rd_build_filter(struct rd *rd, const struct filters valid_filters[])
 {
        int ret = 0;
@@ -218,7 +236,7 @@ out:
        return ret;
 }
 
-bool rd_check_is_key_exist(struct rd *rd, const char *key)
+static bool rd_check_is_key_exist(struct rd *rd, const char *key)
 {
        struct filter_entry *fe;
 
@@ -234,8 +252,8 @@ bool rd_check_is_key_exist(struct rd *rd, const char *key)
  * Check if string entry is filtered:
  *  * key doesn't exist -> user didn't request -> not filtered
  */
-bool rd_check_is_string_filtered(struct rd *rd,
-                                const char *key, const char *val)
+static bool rd_check_is_string_filtered(struct rd *rd, const char *key,
+                                       const char *val)
 {
        bool key_is_filtered = false;
        struct filter_entry *fe;
@@ -285,7 +303,7 @@ out:
  * Check if key is filtered:
  * key doesn't exist -> user didn't request -> not filtered
  */
-bool rd_check_is_filtered(struct rd *rd, const char *key, uint32_t val)
+static bool rd_check_is_filtered(struct rd *rd, const char *key, uint32_t val)
 {
        bool key_is_filtered = false;
        struct filter_entry *fe;
@@ -334,6 +352,24 @@ out:
        return key_is_filtered;
 }
 
+bool rd_is_filtered_attr(struct rd *rd, const char *key, uint32_t val,
+                        struct nlattr *attr)
+{
+       if (!attr)
+               return rd_check_is_key_exist(rd, key);
+
+       return rd_check_is_filtered(rd, key, val);
+}
+
+bool rd_is_string_filtered_attr(struct rd *rd, const char *key, const char *val,
+                               struct nlattr *attr)
+{
+       if (!attr)
+               rd_check_is_key_exist(rd, key);
+
+       return rd_check_is_string_filtered(rd, key, val);
+}
+
 static void filters_cleanup(struct rd *rd)
 {
        struct filter_entry *fe, *tmp;
@@ -402,6 +438,18 @@ static const enum mnl_attr_data_type nldev_policy[RDMA_NLDEV_ATTR_MAX] = {
        [RDMA_NLDEV_ATTR_DRIVER_U32] = MNL_TYPE_U32,
        [RDMA_NLDEV_ATTR_DRIVER_S64] = MNL_TYPE_U64,
        [RDMA_NLDEV_ATTR_DRIVER_U64] = MNL_TYPE_U64,
+       [RDMA_NLDEV_SYS_ATTR_NETNS_MODE] = MNL_TYPE_U8,
+       [RDMA_NLDEV_ATTR_STAT_COUNTER] = MNL_TYPE_NESTED,
+       [RDMA_NLDEV_ATTR_STAT_COUNTER_ENTRY] = MNL_TYPE_NESTED,
+       [RDMA_NLDEV_ATTR_STAT_COUNTER_ID] = MNL_TYPE_U32,
+       [RDMA_NLDEV_ATTR_STAT_HWCOUNTERS] = MNL_TYPE_NESTED,
+       [RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY] = MNL_TYPE_NESTED,
+       [RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_NAME] = MNL_TYPE_NUL_STRING,
+       [RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_VALUE] = MNL_TYPE_U64,
+       [RDMA_NLDEV_ATTR_STAT_MODE] = MNL_TYPE_U32,
+       [RDMA_NLDEV_ATTR_STAT_RES] = MNL_TYPE_U32,
+       [RDMA_NLDEV_ATTR_STAT_AUTO_MODE_MASK] = MNL_TYPE_U32,
+       [RDMA_NLDEV_ATTR_DEV_DIM] = MNL_TYPE_U8,
 };
 
 int rd_attr_check(const struct nlattr *attr, int *typep)
@@ -425,8 +473,8 @@ int rd_attr_cb(const struct nlattr *attr, void *data)
        const struct nlattr **tb = data;
        int type;
 
-       if (mnl_attr_type_valid(attr, RDMA_NLDEV_ATTR_MAX) < 0)
-               /* We received uknown attribute */
+       if (mnl_attr_type_valid(attr, RDMA_NLDEV_ATTR_MAX - 1) < 0)
+               /* We received unknown attribute */
                return MNL_CB_OK;
 
        type = mnl_attr_get_type(attr);
@@ -577,6 +625,16 @@ out:
        return ret;
 }
 
+int rd_exec_require_dev(struct rd *rd, int (*cb)(struct rd *rd))
+{
+       if (rd_no_arg(rd)) {
+               pr_err("Please provide device name.\n");
+               return -EINVAL;
+       }
+
+       return rd_exec_dev(rd, cb);
+}
+
 int rd_exec_cmd(struct rd *rd, const struct rd_cmd *cmds, const char *str)
 {
        const struct rd_cmd *c;
@@ -650,10 +708,28 @@ int rd_recv_msg(struct rd *rd, mnl_cb_t callback, void *data, unsigned int seq)
                ret = mnl_cb_run(buf, ret, seq, portid, callback, data);
        } while (ret > 0);
 
+       if (ret < 0 && !rd->suppress_errors)
+               perror("error");
+
        mnl_socket_close(rd->nl);
        return ret;
 }
 
+static int null_cb(const struct nlmsghdr *nlh, void *data)
+{
+       return MNL_CB_OK;
+}
+
+int rd_sendrecv_msg(struct rd *rd, unsigned int seq)
+{
+       int ret;
+
+       ret = rd_send_msg(rd);
+       if (!ret)
+               ret = rd_recv_msg(rd, null_cb, rd, seq);
+       return ret;
+}
+
 static struct dev_map *_dev_map_lookup(struct rd *rd, const char *dev_name)
 {
        struct dev_map *dev_map;
@@ -714,6 +790,11 @@ static int print_driver_string(struct rd *rd, const char *key_str,
        }
 }
 
+void print_on_off(struct rd *rd, const char *key_str, bool on)
+{
+       print_driver_string(rd, key_str, (on) ? "on":"off");
+}
+
 static int print_driver_s32(struct rd *rd, const char *key_str, int32_t val,
                              enum rdma_nldev_print_type print_type)
 {
@@ -786,27 +867,37 @@ static int print_driver_entry(struct rd *rd, struct nlattr *key_attr,
                                struct nlattr *val_attr,
                                enum rdma_nldev_print_type print_type)
 {
-       const char *key_str = mnl_attr_get_str(key_attr);
        int attr_type = nla_type(val_attr);
+       int ret = -EINVAL;
+       char *key_str;
+
+       if (asprintf(&key_str, "drv_%s", mnl_attr_get_str(key_attr)) == -1)
+               return -ENOMEM;
 
        switch (attr_type) {
        case RDMA_NLDEV_ATTR_DRIVER_STRING:
-               return print_driver_string(rd, key_str,
-                               mnl_attr_get_str(val_attr));
+               ret = print_driver_string(rd, key_str,
+                                         mnl_attr_get_str(val_attr));
+               break;
        case RDMA_NLDEV_ATTR_DRIVER_S32:
-               return print_driver_s32(rd, key_str,
-                               mnl_attr_get_u32(val_attr), print_type);
+               ret = print_driver_s32(rd, key_str, mnl_attr_get_u32(val_attr),
+                                      print_type);
+               break;
        case RDMA_NLDEV_ATTR_DRIVER_U32:
-               return print_driver_u32(rd, key_str,
-                               mnl_attr_get_u32(val_attr), print_type);
+               ret = print_driver_u32(rd, key_str, mnl_attr_get_u32(val_attr),
+                                      print_type);
+               break;
        case RDMA_NLDEV_ATTR_DRIVER_S64:
-               return print_driver_s64(rd, key_str,
-                               mnl_attr_get_u64(val_attr), print_type);
+               ret = print_driver_s64(rd, key_str, mnl_attr_get_u64(val_attr),
+                                      print_type);
+               break;
        case RDMA_NLDEV_ATTR_DRIVER_U64:
-               return print_driver_u64(rd, key_str,
-                               mnl_attr_get_u64(val_attr), print_type);
+               ret = print_driver_u64(rd, key_str, mnl_attr_get_u64(val_attr),
+                                      print_type);
+               break;
        }
-       return -EINVAL;
+       free(key_str);
+       return ret;
 }
 
 void print_driver_table(struct rd *rd, struct nlattr *tb)