Home | History | Annotate | Download | only in rdma
      1 /*
      2  * dev.c	RDMA tool
      3  *
      4  *              This program is free software; you can redistribute it and/or
      5  *              modify it under the terms of the GNU General Public License
      6  *              as published by the Free Software Foundation; either version
      7  *              2 of the License, or (at your option) any later version.
      8  *
      9  * Authors:     Leon Romanovsky <leonro (at) mellanox.com>
     10  */
     11 
     12 #include "rdma.h"
     13 
     14 static int dev_help(struct rd *rd)
     15 {
     16 	pr_out("Usage: %s dev show [DEV]\n", rd->filename);
     17 	return 0;
     18 }
     19 
     20 static const char *dev_caps_to_str(uint32_t idx)
     21 {
     22 #define RDMA_DEV_FLAGS(x) \
     23 	x(RESIZE_MAX_WR, 0) \
     24 	x(BAD_PKEY_CNTR, 1) \
     25 	x(BAD_QKEY_CNTR, 2) \
     26 	x(RAW_MULTI, 3) \
     27 	x(AUTO_PATH_MIG, 4) \
     28 	x(CHANGE_PHY_PORT, 5) \
     29 	x(UD_AV_PORT_ENFORCE_PORT_ENFORCE, 6) \
     30 	x(CURR_QP_STATE_MOD, 7) \
     31 	x(SHUTDOWN_PORT, 8) \
     32 	x(INIT_TYPE, 9) \
     33 	x(PORT_ACTIVE_EVENT, 10) \
     34 	x(SYS_IMAGE_GUID, 11) \
     35 	x(RC_RNR_NAK_GEN, 12) \
     36 	x(SRQ_RESIZE, 13) \
     37 	x(N_NOTIFY_CQ, 14) \
     38 	x(LOCAL_DMA_LKEY, 15) \
     39 	x(MEM_WINDOW, 17) \
     40 	x(UD_IP_CSUM, 18) \
     41 	x(UD_TSO, 19) \
     42 	x(XRC, 20) \
     43 	x(MEM_MGT_EXTENSIONS, 21) \
     44 	x(BLOCK_MULTICAST_LOOPBACK, 22) \
     45 	x(MEM_WINDOW_TYPE_2A, 23) \
     46 	x(MEM_WINDOW_TYPE_2B, 24) \
     47 	x(RC_IP_CSUM, 25) \
     48 	x(RAW_IP_CSUM, 26) \
     49 	x(CROSS_CHANNEL, 27) \
     50 	x(MANAGED_FLOW_STEERING, 29) \
     51 	x(SIGNATURE_HANDOVER, 30) \
     52 	x(ON_DEMAND_PAGING, 31) \
     53 	x(SG_GAPS_REG, 32) \
     54 	x(VIRTUAL_FUNCTION, 33) \
     55 	x(RAW_SCATTER_FCS, 34) \
     56 	x(RDMA_NETDEV_OPA_VNIC, 35)
     57 
     58 	enum { RDMA_DEV_FLAGS(RDMA_BITMAP_ENUM) };
     59 
     60 	static const char * const
     61 		rdma_dev_names[] = { RDMA_DEV_FLAGS(RDMA_BITMAP_NAMES) };
     62 	#undef RDMA_DEV_FLAGS
     63 
     64 	if (idx < ARRAY_SIZE(rdma_dev_names) && rdma_dev_names[idx])
     65 		return rdma_dev_names[idx];
     66 	return "UNKNOWN";
     67 }
     68 
     69 static void dev_print_caps(struct rd *rd, struct nlattr **tb)
     70 {
     71 	uint64_t caps;
     72 	uint32_t idx;
     73 
     74 	if (!tb[RDMA_NLDEV_ATTR_CAP_FLAGS])
     75 		return;
     76 
     77 	caps = mnl_attr_get_u64(tb[RDMA_NLDEV_ATTR_CAP_FLAGS]);
     78 
     79 	if (rd->json_output) {
     80 		jsonw_name(rd->jw, "caps");
     81 		jsonw_start_array(rd->jw);
     82 	} else {
     83 		pr_out("\n    caps: <");
     84 	}
     85 	for (idx = 0; caps; idx++) {
     86 		if (caps & 0x1) {
     87 			if (rd->json_output) {
     88 				jsonw_string(rd->jw, dev_caps_to_str(idx));
     89 			} else {
     90 				pr_out("%s", dev_caps_to_str(idx));
     91 				if (caps >> 0x1)
     92 					pr_out(", ");
     93 			}
     94 		}
     95 		caps >>= 0x1;
     96 	}
     97 
     98 	if (rd->json_output)
     99 		jsonw_end_array(rd->jw);
    100 	else
    101 		pr_out(">");
    102 }
    103 
    104 static void dev_print_fw(struct rd *rd, struct nlattr **tb)
    105 {
    106 	const char *str;
    107 	if (!tb[RDMA_NLDEV_ATTR_FW_VERSION])
    108 		return;
    109 
    110 	str = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_FW_VERSION]);
    111 	if (rd->json_output)
    112 		jsonw_string_field(rd->jw, "fw", str);
    113 	else
    114 		pr_out("fw %s ", str);
    115 }
    116 
    117 static void dev_print_node_guid(struct rd *rd, struct nlattr **tb)
    118 {
    119 	uint64_t node_guid;
    120 	uint16_t vp[4];
    121 	char str[32];
    122 
    123 	if (!tb[RDMA_NLDEV_ATTR_NODE_GUID])
    124 		return;
    125 
    126 	node_guid = mnl_attr_get_u64(tb[RDMA_NLDEV_ATTR_NODE_GUID]);
    127 	memcpy(vp, &node_guid, sizeof(uint64_t));
    128 	snprintf(str, 32, "%04x:%04x:%04x:%04x", vp[3], vp[2], vp[1], vp[0]);
    129 	if (rd->json_output)
    130 		jsonw_string_field(rd->jw, "node_guid", str);
    131 	else
    132 		pr_out("node_guid %s ", str);
    133 }
    134 
    135 static void dev_print_sys_image_guid(struct rd *rd, struct nlattr **tb)
    136 {
    137 	uint64_t sys_image_guid;
    138 	uint16_t vp[4];
    139 	char str[32];
    140 
    141 	if (!tb[RDMA_NLDEV_ATTR_SYS_IMAGE_GUID])
    142 		return;
    143 
    144 	sys_image_guid = mnl_attr_get_u64(tb[RDMA_NLDEV_ATTR_SYS_IMAGE_GUID]);
    145 	memcpy(vp, &sys_image_guid, sizeof(uint64_t));
    146 	snprintf(str, 32, "%04x:%04x:%04x:%04x", vp[3], vp[2], vp[1], vp[0]);
    147 	if (rd->json_output)
    148 		jsonw_string_field(rd->jw, "sys_image_guid", str);
    149 	else
    150 		pr_out("sys_image_guid %s ", str);
    151 }
    152 
    153 static const char *node_type_to_str(uint8_t node_type)
    154 {
    155 	static const char * const node_type_str[] = { "unknown", "ca",
    156 						      "switch", "router",
    157 						      "rnic", "usnic",
    158 						      "usnic_dp" };
    159 	if (node_type < ARRAY_SIZE(node_type_str))
    160 		return node_type_str[node_type];
    161 	return "unknown";
    162 }
    163 
    164 static void dev_print_node_type(struct rd *rd, struct nlattr **tb)
    165 {
    166 	const char *node_str;
    167 	uint8_t node_type;
    168 
    169 	if (!tb[RDMA_NLDEV_ATTR_DEV_NODE_TYPE])
    170 		return;
    171 
    172 	node_type = mnl_attr_get_u8(tb[RDMA_NLDEV_ATTR_DEV_NODE_TYPE]);
    173 	node_str = node_type_to_str(node_type);
    174 	if (rd->json_output)
    175 		jsonw_string_field(rd->jw, "node_type", node_str);
    176 	else
    177 		pr_out("node_type %s ", node_str);
    178 }
    179 
    180 static int dev_parse_cb(const struct nlmsghdr *nlh, void *data)
    181 {
    182 	struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
    183 	struct rd *rd = data;
    184 	const char *name;
    185 	uint32_t idx;
    186 
    187 	mnl_attr_parse(nlh, 0, rd_attr_cb, tb);
    188 	if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME])
    189 		return MNL_CB_ERROR;
    190 
    191 	idx =  mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
    192 	name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]);
    193 	if (rd->json_output) {
    194 		jsonw_uint_field(rd->jw, "ifindex", idx);
    195 		jsonw_string_field(rd->jw, "ifname", name);
    196 	} else {
    197 		pr_out("%u: %s: ", idx, name);
    198 	}
    199 
    200 	dev_print_node_type(rd, tb);
    201 	dev_print_fw(rd, tb);
    202 	dev_print_node_guid(rd, tb);
    203 	dev_print_sys_image_guid(rd, tb);
    204 	if (rd->show_details)
    205 		dev_print_caps(rd, tb);
    206 
    207 	if (!rd->json_output)
    208 		pr_out("\n");
    209 	return MNL_CB_OK;
    210 }
    211 
    212 static int dev_no_args(struct rd *rd)
    213 {
    214 	uint32_t seq;
    215 	int ret;
    216 
    217 	rd_prepare_msg(rd, RDMA_NLDEV_CMD_GET,
    218 		       &seq, (NLM_F_REQUEST | NLM_F_ACK));
    219 	mnl_attr_put_u32(rd->nlh, RDMA_NLDEV_ATTR_DEV_INDEX, rd->dev_idx);
    220 	ret = rd_send_msg(rd);
    221 	if (ret)
    222 		return ret;
    223 
    224 	if (rd->json_output)
    225 		jsonw_start_object(rd->jw);
    226 	ret = rd_recv_msg(rd, dev_parse_cb, rd, seq);
    227 	if (rd->json_output)
    228 		jsonw_end_object(rd->jw);
    229 	return ret;
    230 }
    231 
    232 static int dev_one_show(struct rd *rd)
    233 {
    234 	const struct rd_cmd cmds[] = {
    235 		{ NULL,		dev_no_args},
    236 		{ 0 }
    237 	};
    238 
    239 	return rd_exec_cmd(rd, cmds, "parameter");
    240 }
    241 
    242 static int dev_show(struct rd *rd)
    243 {
    244 	struct dev_map *dev_map;
    245 	int ret = 0;
    246 
    247 	if (rd->json_output)
    248 		jsonw_start_array(rd->jw);
    249 	if (rd_no_arg(rd)) {
    250 		list_for_each_entry(dev_map, &rd->dev_map_list, list) {
    251 			rd->dev_idx = dev_map->idx;
    252 			ret = dev_one_show(rd);
    253 			if (ret)
    254 				goto out;
    255 		}
    256 	} else {
    257 		dev_map = dev_map_lookup(rd, false);
    258 		if (!dev_map) {
    259 			pr_err("Wrong device name\n");
    260 			ret = -ENOENT;
    261 			goto out;
    262 		}
    263 		rd_arg_inc(rd);
    264 		rd->dev_idx = dev_map->idx;
    265 		ret = dev_one_show(rd);
    266 	}
    267 out:
    268 	if (rd->json_output)
    269 		jsonw_end_array(rd->jw);
    270 	return ret;
    271 }
    272 
    273 int cmd_dev(struct rd *rd)
    274 {
    275 	const struct rd_cmd cmds[] = {
    276 		{ NULL,		dev_show },
    277 		{ "show",	dev_show },
    278 		{ "list",	dev_show },
    279 		{ "help",	dev_help },
    280 		{ 0 }
    281 	};
    282 
    283 	return rd_exec_cmd(rd, cmds, "dev command");
    284 }
    285