Merge branch 'rdma-object-ids' into next
Leon Romanovsky says: ==================== This series adds ability to present and query all known to rdmatool object by their respective, unique IDs (e.g. pdn. mrn, cqn e.t.c). All objects which have "parent" object has this information too. ==================== Signed-off-by: David Ahern <dsahern@gmail.com>
This commit is contained in:
commit
65a94784fb
|
|
@ -1,4 +1,4 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
# SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
|
||||
include ../config.mk
|
||||
|
||||
TARGETS :=
|
||||
|
|
@ -6,7 +6,8 @@ TARGETS :=
|
|||
ifeq ($(HAVE_MNL),y)
|
||||
CFLAGS += -I./include/uapi/
|
||||
|
||||
RDMA_OBJ = rdma.o utils.o dev.o link.o res.o
|
||||
RDMA_OBJ = rdma.o utils.o dev.o link.o res.o res-pd.o res-mr.o res-cq.o \
|
||||
res-cmid.o res-qp.o
|
||||
|
||||
TARGETS += rdma
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -1,11 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
|
||||
/*
|
||||
* dev.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>
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@
|
|||
#include <linux/types.h>
|
||||
|
||||
enum {
|
||||
RDMA_NL_RDMA_CM = 1,
|
||||
RDMA_NL_IWCM,
|
||||
RDMA_NL_IWCM = 2,
|
||||
RDMA_NL_RSVD,
|
||||
RDMA_NL_LS, /* RDMA Local Services */
|
||||
RDMA_NL_NLDEV, /* RDMA device interface */
|
||||
|
|
@ -14,8 +13,7 @@ enum {
|
|||
};
|
||||
|
||||
enum {
|
||||
RDMA_NL_GROUP_CM = 1,
|
||||
RDMA_NL_GROUP_IWPM,
|
||||
RDMA_NL_GROUP_IWPM = 2,
|
||||
RDMA_NL_GROUP_LS,
|
||||
RDMA_NL_NUM_GROUPS
|
||||
};
|
||||
|
|
@ -24,15 +22,17 @@ enum {
|
|||
#define RDMA_NL_GET_OP(type) (type & ((1 << 10) - 1))
|
||||
#define RDMA_NL_GET_TYPE(client, op) ((client << 10) + op)
|
||||
|
||||
enum {
|
||||
RDMA_NL_RDMA_CM_ID_STATS = 0,
|
||||
RDMA_NL_RDMA_CM_NUM_OPS
|
||||
};
|
||||
/* The minimum version that the iwpm kernel supports */
|
||||
#define IWPM_UABI_VERSION_MIN 3
|
||||
|
||||
/* The latest version that the iwpm kernel supports */
|
||||
#define IWPM_UABI_VERSION 4
|
||||
|
||||
/* iwarp port mapper message flags */
|
||||
enum {
|
||||
RDMA_NL_RDMA_CM_ATTR_SRC_ADDR = 1,
|
||||
RDMA_NL_RDMA_CM_ATTR_DST_ADDR,
|
||||
RDMA_NL_RDMA_CM_NUM_ATTR,
|
||||
|
||||
/* Do not map the port for this IWPM request */
|
||||
IWPM_FLAGS_NO_PORT_MAP = (1 << 0),
|
||||
};
|
||||
|
||||
/* iwarp port mapper op-codes */
|
||||
|
|
@ -45,6 +45,7 @@ enum {
|
|||
RDMA_NL_IWPM_HANDLE_ERR,
|
||||
RDMA_NL_IWPM_MAPINFO,
|
||||
RDMA_NL_IWPM_MAPINFO_NUM,
|
||||
RDMA_NL_IWPM_HELLO,
|
||||
RDMA_NL_IWPM_NUM_OPS
|
||||
};
|
||||
|
||||
|
|
@ -83,20 +84,38 @@ enum {
|
|||
IWPM_NLA_MANAGE_MAPPING_UNSPEC = 0,
|
||||
IWPM_NLA_MANAGE_MAPPING_SEQ,
|
||||
IWPM_NLA_MANAGE_ADDR,
|
||||
IWPM_NLA_MANAGE_MAPPED_LOC_ADDR,
|
||||
IWPM_NLA_MANAGE_FLAGS,
|
||||
IWPM_NLA_MANAGE_MAPPING_MAX
|
||||
};
|
||||
|
||||
enum {
|
||||
IWPM_NLA_RMANAGE_MAPPING_UNSPEC = 0,
|
||||
IWPM_NLA_RMANAGE_MAPPING_SEQ,
|
||||
IWPM_NLA_RMANAGE_ADDR,
|
||||
IWPM_NLA_RMANAGE_MAPPED_LOC_ADDR,
|
||||
/* The following maintains bisectability of rdma-core */
|
||||
IWPM_NLA_MANAGE_MAPPED_LOC_ADDR = IWPM_NLA_RMANAGE_MAPPED_LOC_ADDR,
|
||||
IWPM_NLA_RMANAGE_MAPPING_ERR,
|
||||
IWPM_NLA_RMANAGE_MAPPING_MAX
|
||||
};
|
||||
|
||||
#define IWPM_NLA_MANAGE_MAPPING_MAX 3
|
||||
#define IWPM_NLA_QUERY_MAPPING_MAX 4
|
||||
#define IWPM_NLA_MAPINFO_SEND_MAX 3
|
||||
#define IWPM_NLA_REMOVE_MAPPING_MAX 3
|
||||
|
||||
enum {
|
||||
IWPM_NLA_QUERY_MAPPING_UNSPEC = 0,
|
||||
IWPM_NLA_QUERY_MAPPING_SEQ,
|
||||
IWPM_NLA_QUERY_LOCAL_ADDR,
|
||||
IWPM_NLA_QUERY_REMOTE_ADDR,
|
||||
IWPM_NLA_QUERY_FLAGS,
|
||||
IWPM_NLA_QUERY_MAPPING_MAX,
|
||||
};
|
||||
|
||||
enum {
|
||||
IWPM_NLA_RQUERY_MAPPING_UNSPEC = 0,
|
||||
IWPM_NLA_RQUERY_MAPPING_SEQ,
|
||||
IWPM_NLA_RQUERY_LOCAL_ADDR,
|
||||
IWPM_NLA_RQUERY_REMOTE_ADDR,
|
||||
IWPM_NLA_RQUERY_MAPPED_LOC_ADDR,
|
||||
IWPM_NLA_RQUERY_MAPPED_REM_ADDR,
|
||||
IWPM_NLA_RQUERY_MAPPING_ERR,
|
||||
|
|
@ -114,6 +133,7 @@ enum {
|
|||
IWPM_NLA_MAPINFO_UNSPEC = 0,
|
||||
IWPM_NLA_MAPINFO_LOCAL_ADDR,
|
||||
IWPM_NLA_MAPINFO_MAPPED_ADDR,
|
||||
IWPM_NLA_MAPINFO_FLAGS,
|
||||
IWPM_NLA_MAPINFO_MAX
|
||||
};
|
||||
|
||||
|
|
@ -132,6 +152,12 @@ enum {
|
|||
IWPM_NLA_ERR_MAX
|
||||
};
|
||||
|
||||
enum {
|
||||
IWPM_NLA_HELLO_UNSPEC = 0,
|
||||
IWPM_NLA_HELLO_ABI_VERSION,
|
||||
IWPM_NLA_HELLO_MAX
|
||||
};
|
||||
|
||||
/*
|
||||
* Local service operations:
|
||||
* RESOLVE - The client requests the local service to resolve a path.
|
||||
|
|
@ -430,6 +456,16 @@ enum rdma_nldev_attr {
|
|||
RDMA_NLDEV_ATTR_DRIVER_S64, /* s64 */
|
||||
RDMA_NLDEV_ATTR_DRIVER_U64, /* u64 */
|
||||
|
||||
/*
|
||||
* Indexes to get/set secific entry,
|
||||
* for QP use RDMA_NLDEV_ATTR_RES_LQPN
|
||||
*/
|
||||
RDMA_NLDEV_ATTR_RES_PDN, /* u32 */
|
||||
RDMA_NLDEV_ATTR_RES_CQN, /* u32 */
|
||||
RDMA_NLDEV_ATTR_RES_MRN, /* u32 */
|
||||
RDMA_NLDEV_ATTR_RES_CM_IDN, /* u32 */
|
||||
RDMA_NLDEV_ATTR_RES_CTXN, /* u32 */
|
||||
|
||||
/*
|
||||
* Always the end
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,11 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
|
||||
/*
|
||||
* link.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>
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
|
||||
/*
|
||||
* rdma.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>
|
||||
*/
|
||||
|
||||
|
|
|
|||
24
rdma/rdma.h
24
rdma/rdma.h
|
|
@ -1,11 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
|
||||
/*
|
||||
* rdma.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>
|
||||
*/
|
||||
#ifndef _RDMA_TOOL_H_
|
||||
|
|
@ -35,13 +30,20 @@
|
|||
#define MAX_NUMBER_OF_FILTERS 64
|
||||
struct filters {
|
||||
const char *name;
|
||||
bool is_number;
|
||||
uint8_t is_number:1;
|
||||
uint8_t is_doit:1;
|
||||
};
|
||||
|
||||
struct filter_entry {
|
||||
struct list_head list;
|
||||
char *key;
|
||||
char *value;
|
||||
/*
|
||||
* This field menas that we can try to issue .doit calback
|
||||
* on value above. This value can be converted to integer
|
||||
* with simple atoi(). Otherwise "is_doit" will be false.
|
||||
*/
|
||||
uint8_t is_doit:1;
|
||||
};
|
||||
|
||||
struct dev_map {
|
||||
|
|
@ -106,10 +108,12 @@ struct dev_map *dev_map_lookup(struct rd *rd, bool allow_port_index);
|
|||
/*
|
||||
* Filter manipulation
|
||||
*/
|
||||
bool rd_doit_index(struct rd *rd, uint32_t *idx);
|
||||
int rd_build_filter(struct rd *rd, const struct filters valid_filters[]);
|
||||
bool rd_check_is_filtered(struct rd *rd, const char *key, uint32_t val);
|
||||
bool rd_check_is_string_filtered(struct rd *rd, const char *key, const char *val);
|
||||
bool rd_check_is_key_exist(struct rd *rd, const char *key);
|
||||
bool rd_is_filtered_attr(struct rd *rd, const char *key, uint32_t val,
|
||||
struct nlattr *attr);
|
||||
bool rd_is_string_filtered_attr(struct rd *rd, const char *key, const char *val,
|
||||
struct nlattr *attr);
|
||||
/*
|
||||
* Netlink
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,275 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
|
||||
/*
|
||||
* res-cmid.c RDMA tool
|
||||
* Authors: Leon Romanovsky <leonro@mellanox.com>
|
||||
*/
|
||||
|
||||
#include "res.h"
|
||||
#include <inttypes.h>
|
||||
|
||||
static void print_qp_type(struct rd *rd, uint32_t val)
|
||||
{
|
||||
if (rd->json_output)
|
||||
jsonw_string_field(rd->jw, "qp-type", qp_types_to_str(val));
|
||||
else
|
||||
pr_out("qp-type %s ", qp_types_to_str(val));
|
||||
}
|
||||
|
||||
static const char *cm_id_state_to_str(uint8_t idx)
|
||||
{
|
||||
static const char *const cm_id_states_str[] = {
|
||||
"IDLE", "ADDR_QUERY", "ADDR_RESOLVED",
|
||||
"ROUTE_QUERY", "ROUTE_RESOLVED", "CONNECT",
|
||||
"DISCONNECT", "ADDR_BOUND", "LISTEN",
|
||||
"DEVICE_REMOVAL", "DESTROYING"
|
||||
};
|
||||
|
||||
if (idx < ARRAY_SIZE(cm_id_states_str))
|
||||
return cm_id_states_str[idx];
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
static const char *cm_id_ps_to_str(uint32_t ps)
|
||||
{
|
||||
switch (ps) {
|
||||
case RDMA_PS_IPOIB:
|
||||
return "IPoIB";
|
||||
case RDMA_PS_IB:
|
||||
return "IPoIB";
|
||||
case RDMA_PS_TCP:
|
||||
return "TCP";
|
||||
case RDMA_PS_UDP:
|
||||
return "UDP";
|
||||
default:
|
||||
return "---";
|
||||
}
|
||||
}
|
||||
|
||||
static void print_cm_id_state(struct rd *rd, uint8_t state)
|
||||
{
|
||||
if (rd->json_output) {
|
||||
jsonw_string_field(rd->jw, "state", cm_id_state_to_str(state));
|
||||
return;
|
||||
}
|
||||
pr_out("state %s ", cm_id_state_to_str(state));
|
||||
}
|
||||
|
||||
static void print_ps(struct rd *rd, uint32_t ps)
|
||||
{
|
||||
if (rd->json_output) {
|
||||
jsonw_string_field(rd->jw, "ps", cm_id_ps_to_str(ps));
|
||||
return;
|
||||
}
|
||||
pr_out("ps %s ", cm_id_ps_to_str(ps));
|
||||
}
|
||||
|
||||
static void print_ipaddr(struct rd *rd, const char *key, char *addrstr,
|
||||
uint16_t port)
|
||||
{
|
||||
if (rd->json_output) {
|
||||
int name_size = INET6_ADDRSTRLEN + strlen(":65535");
|
||||
char json_name[name_size];
|
||||
|
||||
snprintf(json_name, name_size, "%s:%u", addrstr, port);
|
||||
jsonw_string_field(rd->jw, key, json_name);
|
||||
return;
|
||||
}
|
||||
pr_out("%s %s:%u ", key, addrstr, port);
|
||||
}
|
||||
|
||||
static int ss_ntop(struct nlattr *nla_line, char *addr_str, uint16_t *port)
|
||||
{
|
||||
struct __kernel_sockaddr_storage *addr;
|
||||
|
||||
addr = (struct __kernel_sockaddr_storage *)mnl_attr_get_payload(
|
||||
nla_line);
|
||||
switch (addr->ss_family) {
|
||||
case AF_INET: {
|
||||
struct sockaddr_in *sin = (struct sockaddr_in *)addr;
|
||||
|
||||
if (!inet_ntop(AF_INET, (const void *)&sin->sin_addr, addr_str,
|
||||
INET6_ADDRSTRLEN))
|
||||
return -EINVAL;
|
||||
*port = ntohs(sin->sin_port);
|
||||
break;
|
||||
}
|
||||
case AF_INET6: {
|
||||
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr;
|
||||
|
||||
if (!inet_ntop(AF_INET6, (const void *)&sin6->sin6_addr,
|
||||
addr_str, INET6_ADDRSTRLEN))
|
||||
return -EINVAL;
|
||||
*port = ntohs(sin6->sin6_port);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int res_cm_id_line(struct rd *rd, const char *name, int idx,
|
||||
struct nlattr **nla_line)
|
||||
{
|
||||
char src_addr_str[INET6_ADDRSTRLEN];
|
||||
char dst_addr_str[INET6_ADDRSTRLEN];
|
||||
uint16_t src_port, dst_port;
|
||||
uint32_t port = 0, pid = 0;
|
||||
uint8_t type = 0, state;
|
||||
uint32_t lqpn = 0, ps;
|
||||
uint32_t cm_idn = 0;
|
||||
char *comm = NULL;
|
||||
|
||||
if (!nla_line[RDMA_NLDEV_ATTR_RES_STATE] ||
|
||||
!nla_line[RDMA_NLDEV_ATTR_RES_PS] ||
|
||||
(!nla_line[RDMA_NLDEV_ATTR_RES_PID] &&
|
||||
!nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME])) {
|
||||
return MNL_CB_ERROR;
|
||||
}
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_PORT_INDEX])
|
||||
port = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_PORT_INDEX]);
|
||||
|
||||
if (port && port != rd->port_idx)
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_LQPN])
|
||||
lqpn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_LQPN]);
|
||||
|
||||
if (rd_is_filtered_attr(rd, "lqpn", lqpn,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_LQPN]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_TYPE])
|
||||
type = mnl_attr_get_u8(nla_line[RDMA_NLDEV_ATTR_RES_TYPE]);
|
||||
if (rd_is_string_filtered_attr(rd, "qp-type", qp_types_to_str(type),
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_TYPE]))
|
||||
goto out;
|
||||
|
||||
ps = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_PS]);
|
||||
if (rd_is_string_filtered_attr(rd, "ps", cm_id_ps_to_str(ps),
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_PS]))
|
||||
goto out;
|
||||
|
||||
state = mnl_attr_get_u8(nla_line[RDMA_NLDEV_ATTR_RES_STATE]);
|
||||
if (rd_is_string_filtered_attr(rd, "state", cm_id_state_to_str(state),
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_STATE]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_SRC_ADDR])
|
||||
if (ss_ntop(nla_line[RDMA_NLDEV_ATTR_RES_SRC_ADDR],
|
||||
src_addr_str, &src_port))
|
||||
goto out;
|
||||
if (rd_is_string_filtered_attr(rd, "src-addr", src_addr_str,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_SRC_ADDR]))
|
||||
goto out;
|
||||
if (rd_is_filtered_attr(rd, "src-port", src_port,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_SRC_ADDR]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_DST_ADDR])
|
||||
if (ss_ntop(nla_line[RDMA_NLDEV_ATTR_RES_DST_ADDR],
|
||||
dst_addr_str, &dst_port))
|
||||
goto out;
|
||||
if (rd_is_string_filtered_attr(rd, "dst-addr", dst_addr_str,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_DST_ADDR]))
|
||||
goto out;
|
||||
if (rd_is_filtered_attr(rd, "dst-port", dst_port,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_DST_ADDR]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_PID]) {
|
||||
pid = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_PID]);
|
||||
comm = get_task_name(pid);
|
||||
}
|
||||
|
||||
if (rd_is_filtered_attr(rd, "pid", pid,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_PID]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_CM_IDN])
|
||||
cm_idn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_CM_IDN]);
|
||||
if (rd_is_filtered_attr(rd, "cm-idn", cm_idn,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_CM_IDN]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME]) {
|
||||
/* discard const from mnl_attr_get_str */
|
||||
comm = (char *)mnl_attr_get_str(
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME]);
|
||||
}
|
||||
|
||||
if (rd->json_output)
|
||||
jsonw_start_array(rd->jw);
|
||||
|
||||
print_link(rd, idx, name, port, nla_line);
|
||||
res_print_uint(rd, "cm-idn", cm_idn,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_CM_IDN]);
|
||||
res_print_uint(rd, "lqpn", lqpn, nla_line[RDMA_NLDEV_ATTR_RES_LQPN]);
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_TYPE])
|
||||
print_qp_type(rd, type);
|
||||
print_cm_id_state(rd, state);
|
||||
print_ps(rd, ps);
|
||||
res_print_uint(rd, "pid", pid, nla_line[RDMA_NLDEV_ATTR_RES_PID]);
|
||||
print_comm(rd, comm, nla_line);
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_SRC_ADDR])
|
||||
print_ipaddr(rd, "src-addr", src_addr_str, src_port);
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_DST_ADDR])
|
||||
print_ipaddr(rd, "dst-addr", dst_addr_str, dst_port);
|
||||
|
||||
print_driver_table(rd, nla_line[RDMA_NLDEV_ATTR_DRIVER]);
|
||||
newline(rd);
|
||||
|
||||
out: if (nla_line[RDMA_NLDEV_ATTR_RES_PID])
|
||||
free(comm);
|
||||
return MNL_CB_OK;
|
||||
}
|
||||
|
||||
int res_cm_id_idx_parse_cb(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
|
||||
struct rd *rd = data;
|
||||
const char *name;
|
||||
int idx;
|
||||
|
||||
mnl_attr_parse(nlh, 0, rd_attr_cb, tb);
|
||||
if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME])
|
||||
return MNL_CB_ERROR;
|
||||
|
||||
name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]);
|
||||
idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
|
||||
|
||||
return res_cm_id_line(rd, name, idx, tb);
|
||||
}
|
||||
|
||||
int res_cm_id_parse_cb(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
|
||||
struct nlattr *nla_table, *nla_entry;
|
||||
struct rd *rd = data;
|
||||
int ret = MNL_CB_OK;
|
||||
const char *name;
|
||||
int idx;
|
||||
|
||||
mnl_attr_parse(nlh, 0, rd_attr_cb, tb);
|
||||
if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME] ||
|
||||
!tb[RDMA_NLDEV_ATTR_RES_CM_ID])
|
||||
return MNL_CB_ERROR;
|
||||
|
||||
name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]);
|
||||
idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
|
||||
nla_table = tb[RDMA_NLDEV_ATTR_RES_CM_ID];
|
||||
|
||||
mnl_attr_for_each_nested(nla_entry, nla_table) {
|
||||
struct nlattr *nla_line[RDMA_NLDEV_ATTR_MAX] = {};
|
||||
|
||||
ret = mnl_attr_parse_nested(nla_entry, rd_attr_cb, nla_line);
|
||||
if (ret != MNL_CB_OK)
|
||||
break;
|
||||
|
||||
ret = res_cm_id_line(rd, name, idx, nla_line);
|
||||
if (ret != MNL_CB_OK)
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -0,0 +1,160 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
|
||||
/*
|
||||
* res-cq.c RDMA tool
|
||||
* Authors: Leon Romanovsky <leonro@mellanox.com>
|
||||
*/
|
||||
|
||||
#include "res.h"
|
||||
#include <inttypes.h>
|
||||
|
||||
static const char *poll_ctx_to_str(uint8_t idx)
|
||||
{
|
||||
static const char * const cm_id_states_str[] = {
|
||||
"DIRECT", "SOFTIRQ", "WORKQUEUE", "UNBOUND_WORKQUEUE"};
|
||||
|
||||
if (idx < ARRAY_SIZE(cm_id_states_str))
|
||||
return cm_id_states_str[idx];
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
static void print_poll_ctx(struct rd *rd, uint8_t poll_ctx, struct nlattr *attr)
|
||||
{
|
||||
if (!attr)
|
||||
return;
|
||||
|
||||
if (rd->json_output) {
|
||||
jsonw_string_field(rd->jw, "poll-ctx",
|
||||
poll_ctx_to_str(poll_ctx));
|
||||
return;
|
||||
}
|
||||
pr_out("poll-ctx %s ", poll_ctx_to_str(poll_ctx));
|
||||
}
|
||||
|
||||
static int res_cq_line(struct rd *rd, const char *name, int idx,
|
||||
struct nlattr **nla_line)
|
||||
{
|
||||
char *comm = NULL;
|
||||
uint32_t pid = 0;
|
||||
uint8_t poll_ctx = 0;
|
||||
uint32_t ctxn = 0;
|
||||
uint32_t cqn = 0;
|
||||
uint64_t users;
|
||||
uint32_t cqe;
|
||||
|
||||
if (!nla_line[RDMA_NLDEV_ATTR_RES_CQE] ||
|
||||
!nla_line[RDMA_NLDEV_ATTR_RES_USECNT] ||
|
||||
(!nla_line[RDMA_NLDEV_ATTR_RES_PID] &&
|
||||
!nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME])) {
|
||||
return MNL_CB_ERROR;
|
||||
}
|
||||
|
||||
cqe = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_CQE]);
|
||||
|
||||
users = mnl_attr_get_u64(nla_line[RDMA_NLDEV_ATTR_RES_USECNT]);
|
||||
if (rd_is_filtered_attr(rd, "users", users,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_USECNT]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_POLL_CTX])
|
||||
poll_ctx =
|
||||
mnl_attr_get_u8(nla_line[RDMA_NLDEV_ATTR_RES_POLL_CTX]);
|
||||
if (rd_is_string_filtered_attr(rd, "poll-ctx",
|
||||
poll_ctx_to_str(poll_ctx),
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_POLL_CTX]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_PID]) {
|
||||
pid = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_PID]);
|
||||
comm = get_task_name(pid);
|
||||
}
|
||||
|
||||
if (rd_is_filtered_attr(rd, "pid", pid,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_PID]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_CQN])
|
||||
cqn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_CQN]);
|
||||
if (rd_is_filtered_attr(rd, "cqn", cqn,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_CQN]))
|
||||
goto out;
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_CTXN])
|
||||
ctxn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_CTXN]);
|
||||
if (rd_is_filtered_attr(rd, "ctxn", ctxn,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_CTXN]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME])
|
||||
/* discard const from mnl_attr_get_str */
|
||||
comm = (char *)mnl_attr_get_str(
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME]);
|
||||
|
||||
if (rd->json_output)
|
||||
jsonw_start_array(rd->jw);
|
||||
|
||||
print_dev(rd, idx, name);
|
||||
res_print_uint(rd, "cqn", cqn, nla_line[RDMA_NLDEV_ATTR_RES_CQN]);
|
||||
res_print_uint(rd, "cqe", cqe, nla_line[RDMA_NLDEV_ATTR_RES_CQE]);
|
||||
res_print_uint(rd, "users", users,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_USECNT]);
|
||||
print_poll_ctx(rd, poll_ctx, nla_line[RDMA_NLDEV_ATTR_RES_POLL_CTX]);
|
||||
res_print_uint(rd, "ctxn", ctxn, nla_line[RDMA_NLDEV_ATTR_RES_CTXN]);
|
||||
res_print_uint(rd, "pid", pid, nla_line[RDMA_NLDEV_ATTR_RES_PID]);
|
||||
print_comm(rd, comm, nla_line);
|
||||
|
||||
print_driver_table(rd, nla_line[RDMA_NLDEV_ATTR_DRIVER]);
|
||||
newline(rd);
|
||||
|
||||
out: if (nla_line[RDMA_NLDEV_ATTR_RES_PID])
|
||||
free(comm);
|
||||
return MNL_CB_OK;
|
||||
}
|
||||
|
||||
int res_cq_idx_parse_cb(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
|
||||
struct rd *rd = data;
|
||||
const char *name;
|
||||
uint32_t idx;
|
||||
|
||||
mnl_attr_parse(nlh, 0, rd_attr_cb, tb);
|
||||
if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME])
|
||||
return MNL_CB_ERROR;
|
||||
|
||||
name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]);
|
||||
idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
|
||||
|
||||
return res_cq_line(rd, name, idx, tb);
|
||||
}
|
||||
|
||||
int res_cq_parse_cb(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
|
||||
struct nlattr *nla_table, *nla_entry;
|
||||
struct rd *rd = data;
|
||||
int ret = MNL_CB_OK;
|
||||
const char *name;
|
||||
uint32_t idx;
|
||||
|
||||
mnl_attr_parse(nlh, 0, rd_attr_cb, tb);
|
||||
if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME] ||
|
||||
!tb[RDMA_NLDEV_ATTR_RES_CQ])
|
||||
return MNL_CB_ERROR;
|
||||
|
||||
name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]);
|
||||
idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
|
||||
nla_table = tb[RDMA_NLDEV_ATTR_RES_CQ];
|
||||
|
||||
mnl_attr_for_each_nested(nla_entry, nla_table) {
|
||||
struct nlattr *nla_line[RDMA_NLDEV_ATTR_MAX] = {};
|
||||
|
||||
ret = mnl_attr_parse_nested(nla_entry, rd_attr_cb, nla_line);
|
||||
if (ret != MNL_CB_OK)
|
||||
break;
|
||||
|
||||
ret = res_cq_line(rd, name, idx, nla_line);
|
||||
|
||||
if (ret != MNL_CB_OK)
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
|
||||
/*
|
||||
* res-mr.c RDMA tool
|
||||
* Authors: Leon Romanovsky <leonro@mellanox.com>
|
||||
*/
|
||||
|
||||
#include "res.h"
|
||||
#include <inttypes.h>
|
||||
|
||||
static int res_mr_line(struct rd *rd, const char *name, int idx,
|
||||
struct nlattr **nla_line)
|
||||
{
|
||||
uint32_t rkey = 0, lkey = 0;
|
||||
uint64_t iova = 0, mrlen;
|
||||
char *comm = NULL;
|
||||
uint32_t pdn = 0;
|
||||
uint32_t mrn = 0;
|
||||
uint32_t pid = 0;
|
||||
|
||||
if (!nla_line[RDMA_NLDEV_ATTR_RES_MRLEN] ||
|
||||
(!nla_line[RDMA_NLDEV_ATTR_RES_PID] &&
|
||||
!nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME])) {
|
||||
return MNL_CB_ERROR;
|
||||
}
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_RKEY])
|
||||
rkey = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_RKEY]);
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_LKEY])
|
||||
lkey = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_LKEY]);
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_IOVA])
|
||||
iova = mnl_attr_get_u64(nla_line[RDMA_NLDEV_ATTR_RES_IOVA]);
|
||||
|
||||
mrlen = mnl_attr_get_u64(nla_line[RDMA_NLDEV_ATTR_RES_MRLEN]);
|
||||
if (rd_is_filtered_attr(rd, "mrlen", mrlen,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_MRLEN]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_PID]) {
|
||||
pid = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_PID]);
|
||||
comm = get_task_name(pid);
|
||||
}
|
||||
|
||||
if (rd_is_filtered_attr(rd, "pid", pid,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_PID]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_MRN])
|
||||
mrn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_MRN]);
|
||||
if (rd_is_filtered_attr(rd, "mrn", mrn,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_MRN]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_PDN])
|
||||
pdn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_PDN]);
|
||||
if (rd_is_filtered_attr(rd, "pdn", pdn,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_PDN]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME])
|
||||
/* discard const from mnl_attr_get_str */
|
||||
comm = (char *)mnl_attr_get_str(
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME]);
|
||||
|
||||
if (rd->json_output)
|
||||
jsonw_start_array(rd->jw);
|
||||
|
||||
print_dev(rd, idx, name);
|
||||
res_print_uint(rd, "mrn", mrn, nla_line[RDMA_NLDEV_ATTR_RES_MRN]);
|
||||
print_key(rd, "rkey", rkey, nla_line[RDMA_NLDEV_ATTR_RES_RKEY]);
|
||||
print_key(rd, "lkey", lkey, nla_line[RDMA_NLDEV_ATTR_RES_LKEY]);
|
||||
print_key(rd, "iova", iova, nla_line[RDMA_NLDEV_ATTR_RES_IOVA]);
|
||||
res_print_uint(rd, "mrlen", mrlen, nla_line[RDMA_NLDEV_ATTR_RES_MRLEN]);
|
||||
res_print_uint(rd, "pdn", pdn, nla_line[RDMA_NLDEV_ATTR_RES_PDN]);
|
||||
res_print_uint(rd, "pid", pid, nla_line[RDMA_NLDEV_ATTR_RES_PID]);
|
||||
print_comm(rd, comm, nla_line);
|
||||
|
||||
print_driver_table(rd, nla_line[RDMA_NLDEV_ATTR_DRIVER]);
|
||||
newline(rd);
|
||||
|
||||
out:
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_PID])
|
||||
free(comm);
|
||||
return MNL_CB_OK;
|
||||
}
|
||||
|
||||
int res_mr_idx_parse_cb(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
|
||||
struct rd *rd = data;
|
||||
const char *name;
|
||||
uint32_t idx;
|
||||
|
||||
mnl_attr_parse(nlh, 0, rd_attr_cb, tb);
|
||||
if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME])
|
||||
return MNL_CB_ERROR;
|
||||
|
||||
name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]);
|
||||
idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
|
||||
|
||||
return res_mr_line(rd, name, idx, tb);
|
||||
}
|
||||
|
||||
int res_mr_parse_cb(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
|
||||
struct nlattr *nla_table, *nla_entry;
|
||||
struct rd *rd = data;
|
||||
int ret = MNL_CB_OK;
|
||||
const char *name;
|
||||
uint32_t idx;
|
||||
|
||||
mnl_attr_parse(nlh, 0, rd_attr_cb, tb);
|
||||
if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME] ||
|
||||
!tb[RDMA_NLDEV_ATTR_RES_MR])
|
||||
return MNL_CB_ERROR;
|
||||
|
||||
name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]);
|
||||
idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
|
||||
nla_table = tb[RDMA_NLDEV_ATTR_RES_MR];
|
||||
|
||||
mnl_attr_for_each_nested(nla_entry, nla_table) {
|
||||
struct nlattr *nla_line[RDMA_NLDEV_ATTR_MAX] = {};
|
||||
|
||||
ret = mnl_attr_parse_nested(nla_entry, rd_attr_cb, nla_line);
|
||||
if (ret != MNL_CB_OK)
|
||||
break;
|
||||
|
||||
ret = res_mr_line(rd, name, idx, nla_line);
|
||||
if (ret != MNL_CB_OK)
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
|
||||
/*
|
||||
* res-pd.c RDMA tool
|
||||
* Authors: Leon Romanovsky <leonro@mellanox.com>
|
||||
*/
|
||||
|
||||
#include "res.h"
|
||||
#include <inttypes.h>
|
||||
|
||||
static int res_pd_line(struct rd *rd, const char *name, int idx,
|
||||
struct nlattr **nla_line)
|
||||
{
|
||||
uint32_t local_dma_lkey = 0, unsafe_global_rkey = 0;
|
||||
char *comm = NULL;
|
||||
uint32_t ctxn = 0;
|
||||
uint32_t pid = 0;
|
||||
uint32_t pdn = 0;
|
||||
uint64_t users;
|
||||
|
||||
if (!nla_line[RDMA_NLDEV_ATTR_RES_USECNT] ||
|
||||
(!nla_line[RDMA_NLDEV_ATTR_RES_PID] &&
|
||||
!nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME])) {
|
||||
return MNL_CB_ERROR;
|
||||
}
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_LOCAL_DMA_LKEY])
|
||||
local_dma_lkey = mnl_attr_get_u32(
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_LOCAL_DMA_LKEY]);
|
||||
|
||||
users = mnl_attr_get_u64(nla_line[RDMA_NLDEV_ATTR_RES_USECNT]);
|
||||
if (rd_is_filtered_attr(rd, "users", users,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_USECNT]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_UNSAFE_GLOBAL_RKEY])
|
||||
unsafe_global_rkey = mnl_attr_get_u32(
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_UNSAFE_GLOBAL_RKEY]);
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_PID]) {
|
||||
pid = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_PID]);
|
||||
comm = get_task_name(pid);
|
||||
}
|
||||
|
||||
if (rd_is_filtered_attr(rd, "pid", pid,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_PID]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_CTXN])
|
||||
ctxn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_CTXN]);
|
||||
|
||||
if (rd_is_filtered_attr(rd, "ctxn", ctxn,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_CTXN]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_PDN])
|
||||
pdn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_PDN]);
|
||||
if (rd_is_filtered_attr(rd, "pdn", pdn,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_PDN]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME])
|
||||
/* discard const from mnl_attr_get_str */
|
||||
comm = (char *)mnl_attr_get_str(
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME]);
|
||||
|
||||
if (rd->json_output)
|
||||
jsonw_start_array(rd->jw);
|
||||
|
||||
print_dev(rd, idx, name);
|
||||
res_print_uint(rd, "pdn", pdn, nla_line[RDMA_NLDEV_ATTR_RES_PDN]);
|
||||
print_key(rd, "local_dma_lkey", local_dma_lkey,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_LOCAL_DMA_LKEY]);
|
||||
res_print_uint(rd, "users", users,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_USECNT]);
|
||||
print_key(rd, "unsafe_global_rkey", unsafe_global_rkey,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_UNSAFE_GLOBAL_RKEY]);
|
||||
res_print_uint(rd, "ctxn", ctxn, nla_line[RDMA_NLDEV_ATTR_RES_CTXN]);
|
||||
res_print_uint(rd, "pid", pid, nla_line[RDMA_NLDEV_ATTR_RES_PID]);
|
||||
print_comm(rd, comm, nla_line);
|
||||
|
||||
print_driver_table(rd, nla_line[RDMA_NLDEV_ATTR_DRIVER]);
|
||||
newline(rd);
|
||||
|
||||
out: if (nla_line[RDMA_NLDEV_ATTR_RES_PID])
|
||||
free(comm);
|
||||
return MNL_CB_OK;
|
||||
}
|
||||
|
||||
int res_pd_idx_parse_cb(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
|
||||
struct rd *rd = data;
|
||||
const char *name;
|
||||
uint32_t idx;
|
||||
|
||||
mnl_attr_parse(nlh, 0, rd_attr_cb, tb);
|
||||
if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME])
|
||||
return MNL_CB_ERROR;
|
||||
|
||||
name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]);
|
||||
idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
|
||||
|
||||
return res_pd_line(rd, name, idx, tb);
|
||||
}
|
||||
|
||||
int res_pd_parse_cb(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
|
||||
struct nlattr *nla_table, *nla_entry;
|
||||
struct rd *rd = data;
|
||||
int ret = MNL_CB_OK;
|
||||
const char *name;
|
||||
uint32_t idx;
|
||||
|
||||
mnl_attr_parse(nlh, 0, rd_attr_cb, tb);
|
||||
if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME] ||
|
||||
!tb[RDMA_NLDEV_ATTR_RES_PD])
|
||||
return MNL_CB_ERROR;
|
||||
|
||||
name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]);
|
||||
idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
|
||||
nla_table = tb[RDMA_NLDEV_ATTR_RES_PD];
|
||||
|
||||
mnl_attr_for_each_nested(nla_entry, nla_table) {
|
||||
struct nlattr *nla_line[RDMA_NLDEV_ATTR_MAX] = {};
|
||||
|
||||
ret = mnl_attr_parse_nested(nla_entry, rd_attr_cb, nla_line);
|
||||
if (ret != MNL_CB_OK)
|
||||
break;
|
||||
|
||||
ret = res_pd_line(rd, name, idx, nla_line);
|
||||
if (ret != MNL_CB_OK)
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -0,0 +1,240 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
|
||||
/*
|
||||
* res-qp.c RDMA tool
|
||||
* Authors: Leon Romanovsky <leonro@mellanox.com>
|
||||
*/
|
||||
|
||||
#include "res.h"
|
||||
#include <inttypes.h>
|
||||
|
||||
static const char *path_mig_to_str(uint8_t idx)
|
||||
{
|
||||
static const char *const path_mig_str[] = { "MIGRATED", "REARM",
|
||||
"ARMED" };
|
||||
|
||||
if (idx < ARRAY_SIZE(path_mig_str))
|
||||
return path_mig_str[idx];
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
static const char *qp_states_to_str(uint8_t idx)
|
||||
{
|
||||
static const char *const qp_states_str[] = { "RESET", "INIT", "RTR",
|
||||
"RTS", "SQD", "SQE",
|
||||
"ERR" };
|
||||
|
||||
if (idx < ARRAY_SIZE(qp_states_str))
|
||||
return qp_states_str[idx];
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
static void print_rqpn(struct rd *rd, uint32_t val, struct nlattr **nla_line)
|
||||
{
|
||||
if (!nla_line[RDMA_NLDEV_ATTR_RES_RQPN])
|
||||
return;
|
||||
|
||||
if (rd->json_output)
|
||||
jsonw_uint_field(rd->jw, "rqpn", val);
|
||||
else
|
||||
pr_out("rqpn %u ", val);
|
||||
}
|
||||
|
||||
static void print_type(struct rd *rd, uint32_t val)
|
||||
{
|
||||
if (rd->json_output)
|
||||
jsonw_string_field(rd->jw, "type", qp_types_to_str(val));
|
||||
else
|
||||
pr_out("type %s ", qp_types_to_str(val));
|
||||
}
|
||||
|
||||
static void print_state(struct rd *rd, uint32_t val)
|
||||
{
|
||||
if (rd->json_output)
|
||||
jsonw_string_field(rd->jw, "state", qp_states_to_str(val));
|
||||
else
|
||||
pr_out("state %s ", qp_states_to_str(val));
|
||||
}
|
||||
|
||||
static void print_rqpsn(struct rd *rd, uint32_t val, struct nlattr **nla_line)
|
||||
{
|
||||
if (!nla_line[RDMA_NLDEV_ATTR_RES_RQ_PSN])
|
||||
return;
|
||||
|
||||
if (rd->json_output)
|
||||
jsonw_uint_field(rd->jw, "rq-psn", val);
|
||||
else
|
||||
pr_out("rq-psn %u ", val);
|
||||
}
|
||||
|
||||
static void print_pathmig(struct rd *rd, uint32_t val, struct nlattr **nla_line)
|
||||
{
|
||||
if (!nla_line[RDMA_NLDEV_ATTR_RES_PATH_MIG_STATE])
|
||||
return;
|
||||
|
||||
if (rd->json_output)
|
||||
jsonw_string_field(rd->jw, "path-mig-state",
|
||||
path_mig_to_str(val));
|
||||
else
|
||||
pr_out("path-mig-state %s ", path_mig_to_str(val));
|
||||
}
|
||||
|
||||
static int res_qp_line(struct rd *rd, const char *name, int idx,
|
||||
struct nlattr **nla_line)
|
||||
{
|
||||
uint32_t lqpn, rqpn = 0, rq_psn = 0, sq_psn;
|
||||
uint8_t type, state, path_mig_state = 0;
|
||||
uint32_t port = 0, pid = 0;
|
||||
uint32_t pdn = 0;
|
||||
char *comm = NULL;
|
||||
|
||||
if (!nla_line[RDMA_NLDEV_ATTR_RES_LQPN] ||
|
||||
!nla_line[RDMA_NLDEV_ATTR_RES_SQ_PSN] ||
|
||||
!nla_line[RDMA_NLDEV_ATTR_RES_TYPE] ||
|
||||
!nla_line[RDMA_NLDEV_ATTR_RES_STATE] ||
|
||||
(!nla_line[RDMA_NLDEV_ATTR_RES_PID] &&
|
||||
!nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME])) {
|
||||
return MNL_CB_ERROR;
|
||||
}
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_PORT_INDEX])
|
||||
port = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_PORT_INDEX]);
|
||||
|
||||
if (port != rd->port_idx)
|
||||
goto out;
|
||||
|
||||
lqpn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_LQPN]);
|
||||
if (rd_is_filtered_attr(rd, "lqpn", lqpn,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_LQPN]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_PDN])
|
||||
pdn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_PDN]);
|
||||
if (rd_is_filtered_attr(rd, "pdn", pdn,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_PDN]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_RQPN])
|
||||
rqpn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_RQPN]);
|
||||
if (rd_is_filtered_attr(rd, "rqpn", rqpn,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_RQPN]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_RQ_PSN])
|
||||
rq_psn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_RQ_PSN]);
|
||||
if (rd_is_filtered_attr(rd, "rq-psn", rq_psn,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_RQ_PSN]))
|
||||
goto out;
|
||||
|
||||
sq_psn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_SQ_PSN]);
|
||||
if (rd_is_filtered_attr(rd, "sq-psn", sq_psn,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_SQ_PSN]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_PATH_MIG_STATE])
|
||||
path_mig_state = mnl_attr_get_u8(
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_PATH_MIG_STATE]);
|
||||
if (rd_is_string_filtered_attr(
|
||||
rd, "path-mig-state", path_mig_to_str(path_mig_state),
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_PATH_MIG_STATE]))
|
||||
goto out;
|
||||
|
||||
type = mnl_attr_get_u8(nla_line[RDMA_NLDEV_ATTR_RES_TYPE]);
|
||||
if (rd_is_string_filtered_attr(rd, "type", qp_types_to_str(type),
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_TYPE]))
|
||||
goto out;
|
||||
|
||||
state = mnl_attr_get_u8(nla_line[RDMA_NLDEV_ATTR_RES_STATE]);
|
||||
if (rd_is_string_filtered_attr(rd, "state", qp_states_to_str(state),
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_STATE]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_PID]) {
|
||||
pid = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_PID]);
|
||||
comm = get_task_name(pid);
|
||||
}
|
||||
|
||||
if (rd_is_filtered_attr(rd, "pid", pid,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_PID]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME])
|
||||
/* discard const from mnl_attr_get_str */
|
||||
comm = (char *)mnl_attr_get_str(
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME]);
|
||||
|
||||
if (rd->json_output)
|
||||
jsonw_start_array(rd->jw);
|
||||
|
||||
print_link(rd, idx, name, port, nla_line);
|
||||
|
||||
res_print_uint(rd, "lqpn", lqpn, nla_line[RDMA_NLDEV_ATTR_RES_LQPN]);
|
||||
print_rqpn(rd, rqpn, nla_line);
|
||||
|
||||
print_type(rd, type);
|
||||
print_state(rd, state);
|
||||
|
||||
print_rqpsn(rd, rq_psn, nla_line);
|
||||
res_print_uint(rd, "sq-psn", sq_psn,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_SQ_PSN]);
|
||||
|
||||
print_pathmig(rd, path_mig_state, nla_line);
|
||||
res_print_uint(rd, "pdn", pdn, nla_line[RDMA_NLDEV_ATTR_RES_PDN]);
|
||||
res_print_uint(rd, "pid", pid, nla_line[RDMA_NLDEV_ATTR_RES_PID]);
|
||||
print_comm(rd, comm, nla_line);
|
||||
|
||||
print_driver_table(rd, nla_line[RDMA_NLDEV_ATTR_DRIVER]);
|
||||
newline(rd);
|
||||
out:
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_PID])
|
||||
free(comm);
|
||||
return MNL_CB_OK;
|
||||
}
|
||||
|
||||
int res_qp_idx_parse_cb(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
|
||||
struct rd *rd = data;
|
||||
const char *name;
|
||||
uint32_t idx;
|
||||
|
||||
mnl_attr_parse(nlh, 0, rd_attr_cb, tb);
|
||||
if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME])
|
||||
return MNL_CB_ERROR;
|
||||
|
||||
name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]);
|
||||
idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
|
||||
|
||||
return res_qp_line(rd, name, idx, tb);
|
||||
}
|
||||
|
||||
int res_qp_parse_cb(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
|
||||
struct nlattr *nla_table, *nla_entry;
|
||||
struct rd *rd = data;
|
||||
int ret = MNL_CB_OK;
|
||||
const char *name;
|
||||
uint32_t idx;
|
||||
|
||||
mnl_attr_parse(nlh, 0, rd_attr_cb, tb);
|
||||
if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME] ||
|
||||
!tb[RDMA_NLDEV_ATTR_RES_QP])
|
||||
return MNL_CB_ERROR;
|
||||
|
||||
name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]);
|
||||
idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
|
||||
nla_table = tb[RDMA_NLDEV_ATTR_RES_QP];
|
||||
|
||||
mnl_attr_for_each_nested(nla_entry, nla_table) {
|
||||
struct nlattr *nla_line[RDMA_NLDEV_ATTR_MAX] = {};
|
||||
|
||||
ret = mnl_attr_parse_nested(nla_entry, rd_attr_cb, nla_line);
|
||||
if (ret != MNL_CB_OK)
|
||||
break;
|
||||
|
||||
ret = res_qp_line(rd, name, idx, nla_line);
|
||||
if (ret != MNL_CB_OK)
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
940
rdma/res.c
940
rdma/res.c
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,148 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
|
||||
/*
|
||||
* res.h RDMA tool
|
||||
* Authors: Leon Romanovsky <leonro@mellanox.com>
|
||||
*/
|
||||
#ifndef _RDMA_TOOL_RES_H_
|
||||
#define _RDMA_TOOL_RES_H_
|
||||
|
||||
#include "rdma.h"
|
||||
|
||||
int _res_send_msg(struct rd *rd, uint32_t command, mnl_cb_t callback);
|
||||
int _res_send_idx_msg(struct rd *rd, uint32_t command, mnl_cb_t callback,
|
||||
uint32_t idx, uint32_t id);
|
||||
|
||||
int res_pd_parse_cb(const struct nlmsghdr *nlh, void *data);
|
||||
int res_pd_idx_parse_cb(const struct nlmsghdr *nlh, void *data);
|
||||
int res_mr_parse_cb(const struct nlmsghdr *nlh, void *data);
|
||||
int res_mr_idx_parse_cb(const struct nlmsghdr *nlh, void *data);
|
||||
int res_cq_parse_cb(const struct nlmsghdr *nlh, void *data);
|
||||
int res_cq_idx_parse_cb(const struct nlmsghdr *nlh, void *data);
|
||||
int res_cm_id_parse_cb(const struct nlmsghdr *nlh, void *data);
|
||||
int res_cm_id_idx_parse_cb(const struct nlmsghdr *nlh, void *data);
|
||||
int res_qp_parse_cb(const struct nlmsghdr *nlh, void *data);
|
||||
int res_qp_idx_parse_cb(const struct nlmsghdr *nlh, void *data);
|
||||
|
||||
#define RES_FUNC(name, command, valid_filters, strict_port, id) \
|
||||
static inline int _##name(struct rd *rd) \
|
||||
{ \
|
||||
uint32_t idx; \
|
||||
int ret; \
|
||||
if (id) { \
|
||||
ret = rd_doit_index(rd, &idx); \
|
||||
if (ret) { \
|
||||
ret = _res_send_idx_msg(rd, command, \
|
||||
name##_idx_parse_cb, \
|
||||
idx, id); \
|
||||
if (!ret) \
|
||||
return ret; \
|
||||
/* Fallback for old systems without .doit callbacks */ \
|
||||
} \
|
||||
} \
|
||||
return _res_send_msg(rd, command, name##_parse_cb); \
|
||||
} \
|
||||
static inline int name(struct rd *rd) \
|
||||
{ \
|
||||
int ret = rd_build_filter(rd, valid_filters); \
|
||||
if (ret) \
|
||||
return ret; \
|
||||
if ((uintptr_t)valid_filters != (uintptr_t)NULL) { \
|
||||
ret = rd_set_arg_to_devname(rd); \
|
||||
if (ret) \
|
||||
return ret; \
|
||||
} \
|
||||
if (strict_port) \
|
||||
return rd_exec_dev(rd, _##name); \
|
||||
else \
|
||||
return rd_exec_link(rd, _##name, strict_port); \
|
||||
}
|
||||
|
||||
static const
|
||||
struct filters pd_valid_filters[MAX_NUMBER_OF_FILTERS] = {
|
||||
{ .name = "dev", .is_number = false },
|
||||
{ .name = "users", .is_number = true },
|
||||
{ .name = "pid", .is_number = true },
|
||||
{ .name = "ctxn", .is_number = true },
|
||||
{ .name = "pdn", .is_number = true, .is_doit = true },
|
||||
{ .name = "ctxn", .is_number = true }
|
||||
};
|
||||
|
||||
RES_FUNC(res_pd, RDMA_NLDEV_CMD_RES_PD_GET, pd_valid_filters, true,
|
||||
RDMA_NLDEV_ATTR_RES_PDN);
|
||||
|
||||
static const
|
||||
struct filters mr_valid_filters[MAX_NUMBER_OF_FILTERS] = {
|
||||
{ .name = "dev", .is_number = false },
|
||||
{ .name = "rkey", .is_number = true },
|
||||
{ .name = "lkey", .is_number = true },
|
||||
{ .name = "mrlen", .is_number = true },
|
||||
{ .name = "pid", .is_number = true },
|
||||
{ .name = "mrn", .is_number = true, .is_doit = true },
|
||||
{ .name = "pdn", .is_number = true }
|
||||
};
|
||||
|
||||
RES_FUNC(res_mr, RDMA_NLDEV_CMD_RES_MR_GET, mr_valid_filters, true,
|
||||
RDMA_NLDEV_ATTR_RES_MRN);
|
||||
|
||||
static const
|
||||
struct filters cq_valid_filters[MAX_NUMBER_OF_FILTERS] = {
|
||||
{ .name = "dev", .is_number = false },
|
||||
{ .name = "users", .is_number = true },
|
||||
{ .name = "poll-ctx", .is_number = false },
|
||||
{ .name = "pid", .is_number = true },
|
||||
{ .name = "cqn", .is_number = true, .is_doit = true },
|
||||
{ .name = "ctxn", .is_number = true }
|
||||
};
|
||||
|
||||
RES_FUNC(res_cq, RDMA_NLDEV_CMD_RES_CQ_GET, cq_valid_filters, true,
|
||||
RDMA_NLDEV_ATTR_RES_CQN);
|
||||
|
||||
static const
|
||||
struct filters cm_id_valid_filters[MAX_NUMBER_OF_FILTERS] = {
|
||||
{ .name = "link", .is_number = false },
|
||||
{ .name = "lqpn", .is_number = true },
|
||||
{ .name = "qp-type", .is_number = false },
|
||||
{ .name = "state", .is_number = false },
|
||||
{ .name = "ps", .is_number = false },
|
||||
{ .name = "dev-type", .is_number = false },
|
||||
{ .name = "transport-type", .is_number = false },
|
||||
{ .name = "pid", .is_number = true },
|
||||
{ .name = "src-addr", .is_number = false },
|
||||
{ .name = "src-port", .is_number = true },
|
||||
{ .name = "dst-addr", .is_number = false },
|
||||
{ .name = "dst-port", .is_number = true },
|
||||
{ .name = "cm-idn", .is_number = true, .is_doit = true }
|
||||
};
|
||||
|
||||
RES_FUNC(res_cm_id, RDMA_NLDEV_CMD_RES_CM_ID_GET, cm_id_valid_filters, false,
|
||||
RDMA_NLDEV_ATTR_RES_CM_IDN);
|
||||
|
||||
static const struct
|
||||
filters qp_valid_filters[MAX_NUMBER_OF_FILTERS] = {
|
||||
{ .name = "link", .is_number = false },
|
||||
{ .name = "lqpn", .is_number = true, .is_doit = true },
|
||||
{ .name = "rqpn", .is_number = true },
|
||||
{ .name = "pid", .is_number = true },
|
||||
{ .name = "sq-psn", .is_number = true },
|
||||
{ .name = "rq-psn", .is_number = true },
|
||||
{ .name = "type", .is_number = false },
|
||||
{ .name = "path-mig-state", .is_number = false },
|
||||
{ .name = "state", .is_number = false },
|
||||
{ .name = "pdn", .is_number = true },
|
||||
};
|
||||
|
||||
RES_FUNC(res_qp, RDMA_NLDEV_CMD_RES_QP_GET, qp_valid_filters, false,
|
||||
RDMA_NLDEV_ATTR_RES_LQPN);
|
||||
|
||||
char *get_task_name(uint32_t pid);
|
||||
void print_dev(struct rd *rd, uint32_t idx, const char *name);
|
||||
void print_link(struct rd *rd, uint32_t idx, const char *name, uint32_t port,
|
||||
struct nlattr **nla_line);
|
||||
void print_key(struct rd *rd, const char *name, uint64_t val,
|
||||
struct nlattr *nlattr);
|
||||
void res_print_uint(struct rd *rd, const char *name, uint64_t val,
|
||||
struct nlattr *nlattr);
|
||||
void print_comm(struct rd *rd, const char *str, struct nlattr **nla_line);
|
||||
const char *qp_types_to_str(uint8_t idx);
|
||||
|
||||
#endif /* _RDMA_TOOL_RES_H_ */
|
||||
53
rdma/utils.c
53
rdma/utils.c
|
|
@ -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>
|
||||
*/
|
||||
|
||||
|
|
@ -126,6 +121,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 +164,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 +183,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 +233,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 +249,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 +300,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 +349,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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue