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_devmap(struct rd
*rd
)
154 int rd_exec_dev(struct rd
*rd
, int (*cb
)(struct rd
*rd
))
156 struct dev_map
*dev_map
;
160 jsonw_start_array(rd
->jw
);
162 list_for_each_entry(dev_map
, &rd
->dev_map_list
, list
) {
163 rd
->dev_idx
= dev_map
->idx
;
169 dev_map
= dev_map_lookup(rd
, false);
171 pr_err("Wrong device name - %s\n", rd_argv(rd
));
176 rd
->dev_idx
= dev_map
->idx
;
181 jsonw_end_array(rd
->jw
);
185 int rd_exec_cmd(struct rd
*rd
, const struct rd_cmd
*cmds
, const char *str
)
187 const struct rd_cmd
*c
;
189 /* First argument in objs table is default variant */
191 return cmds
->func(rd
);
193 for (c
= cmds
+ 1; c
->cmd
; ++c
) {
194 if (rd_argv_match(rd
, c
->cmd
)) {
195 /* Move to next argument */
201 pr_err("Unknown %s '%s'.\n", str
, rd_argv(rd
));
205 void rd_prepare_msg(struct rd
*rd
, uint32_t cmd
, uint32_t *seq
, uint16_t flags
)
209 rd
->nlh
= mnl_nlmsg_put_header(rd
->buff
);
210 rd
->nlh
->nlmsg_type
= RDMA_NL_GET_TYPE(RDMA_NL_NLDEV
, cmd
);
211 rd
->nlh
->nlmsg_seq
= *seq
;
212 rd
->nlh
->nlmsg_flags
= flags
;
215 int rd_send_msg(struct rd
*rd
)
219 rd
->nl
= mnl_socket_open(NETLINK_RDMA
);
221 pr_err("Failed to open NETLINK_RDMA socket\n");
225 ret
= mnl_socket_bind(rd
->nl
, 0, MNL_SOCKET_AUTOPID
);
227 pr_err("Failed to bind socket with err %d\n", ret
);
231 ret
= mnl_socket_sendto(rd
->nl
, rd
->nlh
, rd
->nlh
->nlmsg_len
);
233 pr_err("Failed to send to socket with err %d\n", ret
);
239 mnl_socket_close(rd
->nl
);
243 int rd_recv_msg(struct rd
*rd
, mnl_cb_t callback
, void *data
, unsigned int seq
)
247 char buf
[MNL_SOCKET_BUFFER_SIZE
];
249 portid
= mnl_socket_get_portid(rd
->nl
);
251 ret
= mnl_socket_recvfrom(rd
->nl
, buf
, sizeof(buf
));
255 ret
= mnl_cb_run(buf
, ret
, seq
, portid
, callback
, data
);
258 mnl_socket_close(rd
->nl
);
262 static struct dev_map
*_dev_map_lookup(struct rd
*rd
, const char *dev_name
)
264 struct dev_map
*dev_map
;
266 list_for_each_entry(dev_map
, &rd
->dev_map_list
, list
)
267 if (strcmp(dev_name
, dev_map
->dev_name
) == 0)
273 struct dev_map
*dev_map_lookup(struct rd
*rd
, bool allow_port_index
)
275 struct dev_map
*dev_map
;
282 dev_name
= strdup(rd_argv(rd
));
283 if (allow_port_index
) {
284 slash
= strrchr(dev_name
, '/');
289 dev_map
= _dev_map_lookup(rd
, dev_name
);