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>
14 static int rd_argc(struct rd
*rd
)
19 char *rd_argv(struct rd
*rd
)
26 static int strcmpx(const char *str1
, const char *str2
)
28 if (strlen(str1
) > strlen(str2
))
30 return strncmp(str1
, str2
, strlen(str1
));
33 static bool rd_argv_match(struct rd
*rd
, const char *pattern
)
37 return strcmpx(rd_argv(rd
), pattern
) == 0;
40 void rd_arg_inc(struct rd
*rd
)
48 bool rd_no_arg(struct rd
*rd
)
50 return rd_argc(rd
) == 0;
53 uint32_t get_port_from_argv(struct rd
*rd
)
57 slash
= strchr(rd_argv(rd
), '/');
58 /* if no port found, return 0 */
59 return slash
? atoi(slash
+ 1) : 0;
62 static struct dev_map
*dev_map_alloc(const char *dev_name
)
64 struct dev_map
*dev_map
;
66 dev_map
= calloc(1, sizeof(*dev_map
));
69 dev_map
->dev_name
= strdup(dev_name
);
74 static void dev_map_cleanup(struct rd
*rd
)
76 struct dev_map
*dev_map
, *tmp
;
78 list_for_each_entry_safe(dev_map
, tmp
,
79 &rd
->dev_map_list
, list
) {
80 list_del(&dev_map
->list
);
81 free(dev_map
->dev_name
);
86 static const enum mnl_attr_data_type nldev_policy
[RDMA_NLDEV_ATTR_MAX
] = {
87 [RDMA_NLDEV_ATTR_DEV_INDEX
] = MNL_TYPE_U32
,
88 [RDMA_NLDEV_ATTR_DEV_NAME
] = MNL_TYPE_NUL_STRING
,
89 [RDMA_NLDEV_ATTR_PORT_INDEX
] = MNL_TYPE_U32
,
90 [RDMA_NLDEV_ATTR_CAP_FLAGS
] = MNL_TYPE_U64
,
91 [RDMA_NLDEV_ATTR_FW_VERSION
] = MNL_TYPE_NUL_STRING
,
92 [RDMA_NLDEV_ATTR_NODE_GUID
] = MNL_TYPE_U64
,
93 [RDMA_NLDEV_ATTR_SYS_IMAGE_GUID
] = MNL_TYPE_U64
,
94 [RDMA_NLDEV_ATTR_LID
] = MNL_TYPE_U32
,
95 [RDMA_NLDEV_ATTR_SM_LID
] = MNL_TYPE_U32
,
96 [RDMA_NLDEV_ATTR_LMC
] = MNL_TYPE_U8
,
97 [RDMA_NLDEV_ATTR_PORT_STATE
] = MNL_TYPE_U8
,
98 [RDMA_NLDEV_ATTR_PORT_PHYS_STATE
] = MNL_TYPE_U8
,
99 [RDMA_NLDEV_ATTR_DEV_NODE_TYPE
] = MNL_TYPE_U8
,
102 int rd_attr_cb(const struct nlattr
*attr
, void *data
)
104 const struct nlattr
**tb
= data
;
107 if (mnl_attr_type_valid(attr
, RDMA_NLDEV_ATTR_MAX
) < 0)
110 type
= mnl_attr_get_type(attr
);
112 if (mnl_attr_validate(attr
, nldev_policy
[type
]) < 0)
119 int rd_dev_init_cb(const struct nlmsghdr
*nlh
, void *data
)
121 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
122 struct dev_map
*dev_map
;
123 struct rd
*rd
= data
;
124 const char *dev_name
;
126 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
127 if (!tb
[RDMA_NLDEV_ATTR_DEV_NAME
] || !tb
[RDMA_NLDEV_ATTR_DEV_INDEX
])
129 if (!tb
[RDMA_NLDEV_ATTR_PORT_INDEX
]) {
130 pr_err("This tool doesn't support switches yet\n");
134 dev_name
= mnl_attr_get_str(tb
[RDMA_NLDEV_ATTR_DEV_NAME
]);
136 dev_map
= dev_map_alloc(dev_name
);
138 /* The main function will cleanup the allocations */
140 list_add_tail(&dev_map
->list
, &rd
->dev_map_list
);
142 dev_map
->num_ports
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_PORT_INDEX
]);
143 dev_map
->idx
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_DEV_INDEX
]);
147 void rd_free(struct rd
*rd
)
155 int rd_exec_dev(struct rd
*rd
, int (*cb
)(struct rd
*rd
))
157 struct dev_map
*dev_map
;
161 jsonw_start_array(rd
->jw
);
163 list_for_each_entry(dev_map
, &rd
->dev_map_list
, list
) {
164 rd
->dev_idx
= dev_map
->idx
;
170 dev_map
= dev_map_lookup(rd
, false);
172 pr_err("Wrong device name - %s\n", rd_argv(rd
));
177 rd
->dev_idx
= dev_map
->idx
;
182 jsonw_end_array(rd
->jw
);
186 int rd_exec_cmd(struct rd
*rd
, const struct rd_cmd
*cmds
, const char *str
)
188 const struct rd_cmd
*c
;
190 /* First argument in objs table is default variant */
192 return cmds
->func(rd
);
194 for (c
= cmds
+ 1; c
->cmd
; ++c
) {
195 if (rd_argv_match(rd
, c
->cmd
)) {
196 /* Move to next argument */
202 pr_err("Unknown %s '%s'.\n", str
, rd_argv(rd
));
206 void rd_prepare_msg(struct rd
*rd
, uint32_t cmd
, uint32_t *seq
, uint16_t flags
)
210 rd
->nlh
= mnl_nlmsg_put_header(rd
->buff
);
211 rd
->nlh
->nlmsg_type
= RDMA_NL_GET_TYPE(RDMA_NL_NLDEV
, cmd
);
212 rd
->nlh
->nlmsg_seq
= *seq
;
213 rd
->nlh
->nlmsg_flags
= flags
;
216 int rd_send_msg(struct rd
*rd
)
220 rd
->nl
= mnl_socket_open(NETLINK_RDMA
);
222 pr_err("Failed to open NETLINK_RDMA socket\n");
226 ret
= mnl_socket_bind(rd
->nl
, 0, MNL_SOCKET_AUTOPID
);
228 pr_err("Failed to bind socket with err %d\n", ret
);
232 ret
= mnl_socket_sendto(rd
->nl
, rd
->nlh
, rd
->nlh
->nlmsg_len
);
234 pr_err("Failed to send to socket with err %d\n", ret
);
240 mnl_socket_close(rd
->nl
);
244 int rd_recv_msg(struct rd
*rd
, mnl_cb_t callback
, void *data
, unsigned int seq
)
248 char buf
[MNL_SOCKET_BUFFER_SIZE
];
250 portid
= mnl_socket_get_portid(rd
->nl
);
252 ret
= mnl_socket_recvfrom(rd
->nl
, buf
, sizeof(buf
));
256 ret
= mnl_cb_run(buf
, ret
, seq
, portid
, callback
, data
);
259 mnl_socket_close(rd
->nl
);
263 static struct dev_map
*_dev_map_lookup(struct rd
*rd
, const char *dev_name
)
265 struct dev_map
*dev_map
;
267 list_for_each_entry(dev_map
, &rd
->dev_map_list
, list
)
268 if (strcmp(dev_name
, dev_map
->dev_name
) == 0)
274 struct dev_map
*dev_map_lookup(struct rd
*rd
, bool allow_port_index
)
276 struct dev_map
*dev_map
;
283 dev_name
= strdup(rd_argv(rd
));
284 if (allow_port_index
) {
285 slash
= strrchr(dev_name
, '/');
290 dev_map
= _dev_map_lookup(rd
, dev_name
);