]>
Commit | Line | Data |
---|---|---|
438fac3a LR |
1 | // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB |
2 | /* | |
3 | * res-cmid.c RDMA tool | |
4 | * Authors: Leon Romanovsky <leonro@mellanox.com> | |
5 | */ | |
6 | ||
7 | #include "res.h" | |
8 | #include <inttypes.h> | |
9 | ||
10 | static void print_qp_type(struct rd *rd, uint32_t val) | |
11 | { | |
12 | if (rd->json_output) | |
13 | jsonw_string_field(rd->jw, "qp-type", qp_types_to_str(val)); | |
14 | else | |
15 | pr_out("qp-type %s ", qp_types_to_str(val)); | |
16 | } | |
17 | ||
18 | static const char *cm_id_state_to_str(uint8_t idx) | |
19 | { | |
20 | static const char *const cm_id_states_str[] = { | |
21 | "IDLE", "ADDR_QUERY", "ADDR_RESOLVED", | |
22 | "ROUTE_QUERY", "ROUTE_RESOLVED", "CONNECT", | |
23 | "DISCONNECT", "ADDR_BOUND", "LISTEN", | |
24 | "DEVICE_REMOVAL", "DESTROYING" | |
25 | }; | |
26 | ||
27 | if (idx < ARRAY_SIZE(cm_id_states_str)) | |
28 | return cm_id_states_str[idx]; | |
29 | return "UNKNOWN"; | |
30 | } | |
31 | ||
32 | static const char *cm_id_ps_to_str(uint32_t ps) | |
33 | { | |
34 | switch (ps) { | |
35 | case RDMA_PS_IPOIB: | |
36 | return "IPoIB"; | |
37 | case RDMA_PS_IB: | |
38 | return "IPoIB"; | |
39 | case RDMA_PS_TCP: | |
40 | return "TCP"; | |
41 | case RDMA_PS_UDP: | |
42 | return "UDP"; | |
43 | default: | |
44 | return "---"; | |
45 | } | |
46 | } | |
47 | ||
48 | static void print_cm_id_state(struct rd *rd, uint8_t state) | |
49 | { | |
50 | if (rd->json_output) { | |
51 | jsonw_string_field(rd->jw, "state", cm_id_state_to_str(state)); | |
52 | return; | |
53 | } | |
54 | pr_out("state %s ", cm_id_state_to_str(state)); | |
55 | } | |
56 | ||
57 | static void print_ps(struct rd *rd, uint32_t ps) | |
58 | { | |
59 | if (rd->json_output) { | |
60 | jsonw_string_field(rd->jw, "ps", cm_id_ps_to_str(ps)); | |
61 | return; | |
62 | } | |
63 | pr_out("ps %s ", cm_id_ps_to_str(ps)); | |
64 | } | |
65 | ||
66 | static void print_ipaddr(struct rd *rd, const char *key, char *addrstr, | |
67 | uint16_t port) | |
68 | { | |
69 | if (rd->json_output) { | |
70 | int name_size = INET6_ADDRSTRLEN + strlen(":65535"); | |
71 | char json_name[name_size]; | |
72 | ||
73 | snprintf(json_name, name_size, "%s:%u", addrstr, port); | |
74 | jsonw_string_field(rd->jw, key, json_name); | |
75 | return; | |
76 | } | |
77 | pr_out("%s %s:%u ", key, addrstr, port); | |
78 | } | |
79 | ||
80 | static int ss_ntop(struct nlattr *nla_line, char *addr_str, uint16_t *port) | |
81 | { | |
82 | struct __kernel_sockaddr_storage *addr; | |
83 | ||
84 | addr = (struct __kernel_sockaddr_storage *)mnl_attr_get_payload( | |
85 | nla_line); | |
86 | switch (addr->ss_family) { | |
87 | case AF_INET: { | |
88 | struct sockaddr_in *sin = (struct sockaddr_in *)addr; | |
89 | ||
90 | if (!inet_ntop(AF_INET, (const void *)&sin->sin_addr, addr_str, | |
91 | INET6_ADDRSTRLEN)) | |
92 | return -EINVAL; | |
93 | *port = ntohs(sin->sin_port); | |
94 | break; | |
95 | } | |
96 | case AF_INET6: { | |
97 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr; | |
98 | ||
99 | if (!inet_ntop(AF_INET6, (const void *)&sin6->sin6_addr, | |
100 | addr_str, INET6_ADDRSTRLEN)) | |
101 | return -EINVAL; | |
102 | *port = ntohs(sin6->sin6_port); | |
103 | break; | |
104 | } | |
105 | default: | |
106 | return -EINVAL; | |
107 | } | |
108 | return 0; | |
109 | } | |
7d06b31f | 110 | static int res_cm_id_line(struct rd *rd, const char *name, int idx, |
5a823593 | 111 | struct nlattr **nla_line) |
7d06b31f | 112 | { |
7d06b31f LR |
113 | char src_addr_str[INET6_ADDRSTRLEN]; |
114 | char dst_addr_str[INET6_ADDRSTRLEN]; | |
115 | uint16_t src_port, dst_port; | |
116 | uint32_t port = 0, pid = 0; | |
117 | uint8_t type = 0, state; | |
118 | uint32_t lqpn = 0, ps; | |
119 | uint32_t cm_idn = 0; | |
120 | char *comm = NULL; | |
7d06b31f LR |
121 | |
122 | if (!nla_line[RDMA_NLDEV_ATTR_RES_STATE] || | |
123 | !nla_line[RDMA_NLDEV_ATTR_RES_PS] || | |
124 | (!nla_line[RDMA_NLDEV_ATTR_RES_PID] && | |
125 | !nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME])) { | |
126 | return MNL_CB_ERROR; | |
127 | } | |
128 | ||
129 | if (nla_line[RDMA_NLDEV_ATTR_PORT_INDEX]) | |
130 | port = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_PORT_INDEX]); | |
131 | ||
132 | if (port && port != rd->port_idx) | |
133 | goto out; | |
134 | ||
78728b7e | 135 | if (nla_line[RDMA_NLDEV_ATTR_RES_LQPN]) |
7d06b31f | 136 | lqpn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_LQPN]); |
78728b7e LR |
137 | |
138 | if (rd_is_filtered_attr(rd, "lqpn", lqpn, | |
139 | nla_line[RDMA_NLDEV_ATTR_RES_LQPN])) | |
140 | goto out; | |
141 | ||
142 | if (nla_line[RDMA_NLDEV_ATTR_RES_TYPE]) | |
7d06b31f | 143 | type = mnl_attr_get_u8(nla_line[RDMA_NLDEV_ATTR_RES_TYPE]); |
78728b7e LR |
144 | if (rd_is_string_filtered_attr(rd, "qp-type", qp_types_to_str(type), |
145 | nla_line[RDMA_NLDEV_ATTR_RES_TYPE])) | |
146 | goto out; | |
7d06b31f LR |
147 | |
148 | ps = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_PS]); | |
78728b7e LR |
149 | if (rd_is_string_filtered_attr(rd, "ps", cm_id_ps_to_str(ps), |
150 | nla_line[RDMA_NLDEV_ATTR_RES_PS])) | |
7d06b31f LR |
151 | goto out; |
152 | ||
153 | state = mnl_attr_get_u8(nla_line[RDMA_NLDEV_ATTR_RES_STATE]); | |
78728b7e LR |
154 | if (rd_is_string_filtered_attr(rd, "state", cm_id_state_to_str(state), |
155 | nla_line[RDMA_NLDEV_ATTR_RES_STATE])) | |
7d06b31f LR |
156 | goto out; |
157 | ||
78728b7e | 158 | if (nla_line[RDMA_NLDEV_ATTR_RES_SRC_ADDR]) |
7d06b31f LR |
159 | if (ss_ntop(nla_line[RDMA_NLDEV_ATTR_RES_SRC_ADDR], |
160 | src_addr_str, &src_port)) | |
161 | goto out; | |
78728b7e LR |
162 | if (rd_is_string_filtered_attr(rd, "src-addr", src_addr_str, |
163 | nla_line[RDMA_NLDEV_ATTR_RES_SRC_ADDR])) | |
164 | goto out; | |
165 | if (rd_is_filtered_attr(rd, "src-port", src_port, | |
166 | nla_line[RDMA_NLDEV_ATTR_RES_SRC_ADDR])) | |
167 | goto out; | |
7d06b31f | 168 | |
78728b7e | 169 | if (nla_line[RDMA_NLDEV_ATTR_RES_DST_ADDR]) |
7d06b31f LR |
170 | if (ss_ntop(nla_line[RDMA_NLDEV_ATTR_RES_DST_ADDR], |
171 | dst_addr_str, &dst_port)) | |
172 | goto out; | |
78728b7e LR |
173 | if (rd_is_string_filtered_attr(rd, "dst-addr", dst_addr_str, |
174 | nla_line[RDMA_NLDEV_ATTR_RES_DST_ADDR])) | |
175 | goto out; | |
176 | if (rd_is_filtered_attr(rd, "dst-port", dst_port, | |
177 | nla_line[RDMA_NLDEV_ATTR_RES_DST_ADDR])) | |
178 | goto out; | |
7d06b31f LR |
179 | |
180 | if (nla_line[RDMA_NLDEV_ATTR_RES_PID]) { | |
181 | pid = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_PID]); | |
182 | comm = get_task_name(pid); | |
183 | } | |
184 | ||
78728b7e LR |
185 | if (rd_is_filtered_attr(rd, "pid", pid, |
186 | nla_line[RDMA_NLDEV_ATTR_RES_PID])) | |
7d06b31f LR |
187 | goto out; |
188 | ||
189 | if (nla_line[RDMA_NLDEV_ATTR_RES_CM_IDN]) | |
190 | cm_idn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_CM_IDN]); | |
78728b7e LR |
191 | if (rd_is_filtered_attr(rd, "cm-idn", cm_idn, |
192 | nla_line[RDMA_NLDEV_ATTR_RES_CM_IDN])) | |
7d06b31f LR |
193 | goto out; |
194 | ||
195 | if (nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME]) { | |
196 | /* discard const from mnl_attr_get_str */ | |
197 | comm = (char *)mnl_attr_get_str( | |
198 | nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME]); | |
199 | } | |
200 | ||
201 | if (rd->json_output) | |
202 | jsonw_start_array(rd->jw); | |
203 | ||
204 | print_link(rd, idx, name, port, nla_line); | |
127ff956 LR |
205 | res_print_uint(rd, "cm-idn", cm_idn, |
206 | nla_line[RDMA_NLDEV_ATTR_RES_CM_IDN]); | |
207 | res_print_uint(rd, "lqpn", lqpn, nla_line[RDMA_NLDEV_ATTR_RES_LQPN]); | |
7d06b31f LR |
208 | if (nla_line[RDMA_NLDEV_ATTR_RES_TYPE]) |
209 | print_qp_type(rd, type); | |
210 | print_cm_id_state(rd, state); | |
211 | print_ps(rd, ps); | |
127ff956 | 212 | res_print_uint(rd, "pid", pid, nla_line[RDMA_NLDEV_ATTR_RES_PID]); |
7d06b31f | 213 | print_comm(rd, comm, nla_line); |
7d06b31f LR |
214 | |
215 | if (nla_line[RDMA_NLDEV_ATTR_RES_SRC_ADDR]) | |
216 | print_ipaddr(rd, "src-addr", src_addr_str, src_port); | |
217 | if (nla_line[RDMA_NLDEV_ATTR_RES_DST_ADDR]) | |
218 | print_ipaddr(rd, "dst-addr", dst_addr_str, dst_port); | |
219 | ||
220 | print_driver_table(rd, nla_line[RDMA_NLDEV_ATTR_DRIVER]); | |
221 | newline(rd); | |
222 | ||
223 | out: if (nla_line[RDMA_NLDEV_ATTR_RES_PID]) | |
224 | free(comm); | |
225 | return MNL_CB_OK; | |
226 | } | |
227 | ||
5a823593 LR |
228 | int res_cm_id_idx_parse_cb(const struct nlmsghdr *nlh, void *data) |
229 | { | |
230 | struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {}; | |
231 | struct rd *rd = data; | |
232 | const char *name; | |
233 | int idx; | |
234 | ||
235 | mnl_attr_parse(nlh, 0, rd_attr_cb, tb); | |
236 | if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME]) | |
237 | return MNL_CB_ERROR; | |
238 | ||
239 | name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]); | |
240 | idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]); | |
241 | ||
242 | return res_cm_id_line(rd, name, idx, tb); | |
243 | } | |
244 | ||
438fac3a LR |
245 | int res_cm_id_parse_cb(const struct nlmsghdr *nlh, void *data) |
246 | { | |
247 | struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {}; | |
248 | struct nlattr *nla_table, *nla_entry; | |
249 | struct rd *rd = data; | |
7d06b31f | 250 | int ret = MNL_CB_OK; |
438fac3a LR |
251 | const char *name; |
252 | int idx; | |
253 | ||
254 | mnl_attr_parse(nlh, 0, rd_attr_cb, tb); | |
255 | if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME] || | |
256 | !tb[RDMA_NLDEV_ATTR_RES_CM_ID]) | |
257 | return MNL_CB_ERROR; | |
258 | ||
259 | name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]); | |
260 | idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]); | |
261 | nla_table = tb[RDMA_NLDEV_ATTR_RES_CM_ID]; | |
7d06b31f | 262 | |
438fac3a | 263 | mnl_attr_for_each_nested(nla_entry, nla_table) { |
5a823593 LR |
264 | struct nlattr *nla_line[RDMA_NLDEV_ATTR_MAX] = {}; |
265 | ||
266 | ret = mnl_attr_parse_nested(nla_entry, rd_attr_cb, nla_line); | |
267 | if (ret != MNL_CB_OK) | |
268 | break; | |
438fac3a | 269 | |
5a823593 | 270 | ret = res_cm_id_line(rd, name, idx, nla_line); |
7d06b31f LR |
271 | if (ret != MNL_CB_OK) |
272 | break; | |
438fac3a | 273 | } |
7d06b31f | 274 | return ret; |
438fac3a | 275 | } |