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.
9 * Authors: Leon Romanovsky <leonro@mellanox.com>
15 int rd_argc(struct rd
*rd
)
20 char *rd_argv(struct rd
*rd
)
27 static int strcmpx(const char *str1
, const char *str2
)
29 if (strlen(str1
) > strlen(str2
))
31 return strncmp(str1
, str2
, strlen(str1
));
34 static bool rd_argv_match(struct rd
*rd
, const char *pattern
)
38 return strcmpx(rd_argv(rd
), pattern
) == 0;
41 void rd_arg_inc(struct rd
*rd
)
49 bool rd_no_arg(struct rd
*rd
)
51 return rd_argc(rd
) == 0;
55 * Possible input:output
56 * dev/port | first port | is_dump_all
59 * mlx5_1/0 | 0 | false
60 * mlx5_1/1 | 1 | false
61 * mlx5_1/- | 0 | false
63 * In strict mode, /- will return error.
65 static int get_port_from_argv(struct rd
*rd
, uint32_t *port
,
66 bool *is_dump_all
, bool strict_port
)
73 slash
= strchr(rd_argv(rd
), '/');
74 /* if no port found, return 0 */
83 if (isdigit(*slash
)) {
87 if (!*port
&& strlen(slash
))
93 static struct dev_map
*dev_map_alloc(const char *dev_name
)
95 struct dev_map
*dev_map
;
97 dev_map
= calloc(1, sizeof(*dev_map
));
100 dev_map
->dev_name
= strdup(dev_name
);
105 static void dev_map_cleanup(struct rd
*rd
)
107 struct dev_map
*dev_map
, *tmp
;
109 list_for_each_entry_safe(dev_map
, tmp
,
110 &rd
->dev_map_list
, list
) {
111 list_del(&dev_map
->list
);
112 free(dev_map
->dev_name
);
117 static const enum mnl_attr_data_type nldev_policy
[RDMA_NLDEV_ATTR_MAX
] = {
118 [RDMA_NLDEV_ATTR_DEV_INDEX
] = MNL_TYPE_U32
,
119 [RDMA_NLDEV_ATTR_DEV_NAME
] = MNL_TYPE_NUL_STRING
,
120 [RDMA_NLDEV_ATTR_PORT_INDEX
] = MNL_TYPE_U32
,
121 [RDMA_NLDEV_ATTR_CAP_FLAGS
] = MNL_TYPE_U64
,
122 [RDMA_NLDEV_ATTR_FW_VERSION
] = MNL_TYPE_NUL_STRING
,
123 [RDMA_NLDEV_ATTR_NODE_GUID
] = MNL_TYPE_U64
,
124 [RDMA_NLDEV_ATTR_SYS_IMAGE_GUID
] = MNL_TYPE_U64
,
125 [RDMA_NLDEV_ATTR_LID
] = MNL_TYPE_U32
,
126 [RDMA_NLDEV_ATTR_SM_LID
] = MNL_TYPE_U32
,
127 [RDMA_NLDEV_ATTR_LMC
] = MNL_TYPE_U8
,
128 [RDMA_NLDEV_ATTR_PORT_STATE
] = MNL_TYPE_U8
,
129 [RDMA_NLDEV_ATTR_PORT_PHYS_STATE
] = MNL_TYPE_U8
,
130 [RDMA_NLDEV_ATTR_DEV_NODE_TYPE
] = MNL_TYPE_U8
,
133 int rd_attr_cb(const struct nlattr
*attr
, void *data
)
135 const struct nlattr
**tb
= data
;
138 if (mnl_attr_type_valid(attr
, RDMA_NLDEV_ATTR_MAX
) < 0)
141 type
= mnl_attr_get_type(attr
);
143 if (mnl_attr_validate(attr
, nldev_policy
[type
]) < 0)
150 int rd_dev_init_cb(const struct nlmsghdr
*nlh
, void *data
)
152 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
153 struct dev_map
*dev_map
;
154 struct rd
*rd
= data
;
155 const char *dev_name
;
157 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
158 if (!tb
[RDMA_NLDEV_ATTR_DEV_NAME
] || !tb
[RDMA_NLDEV_ATTR_DEV_INDEX
])
160 if (!tb
[RDMA_NLDEV_ATTR_PORT_INDEX
]) {
161 pr_err("This tool doesn't support switches yet\n");
165 dev_name
= mnl_attr_get_str(tb
[RDMA_NLDEV_ATTR_DEV_NAME
]);
167 dev_map
= dev_map_alloc(dev_name
);
169 /* The main function will cleanup the allocations */
171 list_add_tail(&dev_map
->list
, &rd
->dev_map_list
);
173 dev_map
->num_ports
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_PORT_INDEX
]);
174 dev_map
->idx
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_DEV_INDEX
]);
178 void rd_free(struct rd
*rd
)
186 int rd_exec_link(struct rd
*rd
, int (*cb
)(struct rd
*rd
), bool strict_port
)
188 struct dev_map
*dev_map
;
193 jsonw_start_array(rd
->jw
);
195 list_for_each_entry(dev_map
, &rd
->dev_map_list
, list
) {
196 rd
->dev_idx
= dev_map
->idx
;
197 port
= (strict_port
) ? 1 : 0;
198 for (; port
< dev_map
->num_ports
+ 1; port
++) {
209 dev_map
= dev_map_lookup(rd
, true);
210 ret
= get_port_from_argv(rd
, &port
, &is_dump_all
, strict_port
);
211 if (!dev_map
|| port
> dev_map
->num_ports
|| (!port
&& ret
)) {
212 pr_err("Wrong device name\n");
217 rd
->dev_idx
= dev_map
->idx
;
219 for (; rd
->port_idx
< dev_map
->num_ports
+ 1; rd
->port_idx
++) {
225 * We got request to show link for devname
234 jsonw_end_array(rd
->jw
);
238 int rd_exec_dev(struct rd
*rd
, int (*cb
)(struct rd
*rd
))
240 struct dev_map
*dev_map
;
244 jsonw_start_array(rd
->jw
);
246 list_for_each_entry(dev_map
, &rd
->dev_map_list
, list
) {
247 rd
->dev_idx
= dev_map
->idx
;
253 dev_map
= dev_map_lookup(rd
, false);
255 pr_err("Wrong device name - %s\n", rd_argv(rd
));
260 rd
->dev_idx
= dev_map
->idx
;
265 jsonw_end_array(rd
->jw
);
269 int rd_exec_cmd(struct rd
*rd
, const struct rd_cmd
*cmds
, const char *str
)
271 const struct rd_cmd
*c
;
273 /* First argument in objs table is default variant */
275 return cmds
->func(rd
);
277 for (c
= cmds
+ 1; c
->cmd
; ++c
) {
278 if (rd_argv_match(rd
, c
->cmd
)) {
279 /* Move to next argument */
285 pr_err("Unknown %s '%s'.\n", str
, rd_argv(rd
));
289 void rd_prepare_msg(struct rd
*rd
, uint32_t cmd
, uint32_t *seq
, uint16_t flags
)
293 rd
->nlh
= mnl_nlmsg_put_header(rd
->buff
);
294 rd
->nlh
->nlmsg_type
= RDMA_NL_GET_TYPE(RDMA_NL_NLDEV
, cmd
);
295 rd
->nlh
->nlmsg_seq
= *seq
;
296 rd
->nlh
->nlmsg_flags
= flags
;
299 int rd_send_msg(struct rd
*rd
)
303 rd
->nl
= mnl_socket_open(NETLINK_RDMA
);
305 pr_err("Failed to open NETLINK_RDMA socket\n");
309 ret
= mnl_socket_bind(rd
->nl
, 0, MNL_SOCKET_AUTOPID
);
311 pr_err("Failed to bind socket with err %d\n", ret
);
315 ret
= mnl_socket_sendto(rd
->nl
, rd
->nlh
, rd
->nlh
->nlmsg_len
);
317 pr_err("Failed to send to socket with err %d\n", ret
);
323 mnl_socket_close(rd
->nl
);
327 int rd_recv_msg(struct rd
*rd
, mnl_cb_t callback
, void *data
, unsigned int seq
)
331 char buf
[MNL_SOCKET_BUFFER_SIZE
];
333 portid
= mnl_socket_get_portid(rd
->nl
);
335 ret
= mnl_socket_recvfrom(rd
->nl
, buf
, sizeof(buf
));
339 ret
= mnl_cb_run(buf
, ret
, seq
, portid
, callback
, data
);
342 mnl_socket_close(rd
->nl
);
346 static struct dev_map
*_dev_map_lookup(struct rd
*rd
, const char *dev_name
)
348 struct dev_map
*dev_map
;
350 list_for_each_entry(dev_map
, &rd
->dev_map_list
, list
)
351 if (strcmp(dev_name
, dev_map
->dev_name
) == 0)
357 struct dev_map
*dev_map_lookup(struct rd
*rd
, bool allow_port_index
)
359 struct dev_map
*dev_map
;
366 dev_name
= strdup(rd_argv(rd
));
367 if (allow_port_index
) {
368 slash
= strrchr(dev_name
, '/');
373 dev_map
= _dev_map_lookup(rd
, dev_name
);