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_free(struct dev_map
*dev_map
)
79 free(dev_map
->dev_name
);
83 static void dev_map_cleanup(struct rd
*rd
)
85 struct dev_map
*dev_map
, *tmp
;
87 list_for_each_entry_safe(dev_map
, tmp
,
88 &rd
->dev_map_list
, list
) {
89 list_del(&dev_map
->list
);
90 dev_map_free(dev_map
);
94 static const enum mnl_attr_data_type nldev_policy
[RDMA_NLDEV_ATTR_MAX
] = {
95 [RDMA_NLDEV_ATTR_DEV_INDEX
] = MNL_TYPE_U32
,
96 [RDMA_NLDEV_ATTR_DEV_NAME
] = MNL_TYPE_NUL_STRING
,
97 [RDMA_NLDEV_ATTR_PORT_INDEX
] = MNL_TYPE_U32
,
98 [RDMA_NLDEV_ATTR_CAP_FLAGS
] = MNL_TYPE_U64
,
99 [RDMA_NLDEV_ATTR_FW_VERSION
] = MNL_TYPE_NUL_STRING
,
100 [RDMA_NLDEV_ATTR_NODE_GUID
] = MNL_TYPE_U64
,
101 [RDMA_NLDEV_ATTR_SYS_IMAGE_GUID
] = MNL_TYPE_U64
,
102 [RDMA_NLDEV_ATTR_LID
] = MNL_TYPE_U32
,
103 [RDMA_NLDEV_ATTR_SM_LID
] = MNL_TYPE_U32
,
104 [RDMA_NLDEV_ATTR_LMC
] = MNL_TYPE_U8
,
105 [RDMA_NLDEV_ATTR_PORT_STATE
] = MNL_TYPE_U8
,
106 [RDMA_NLDEV_ATTR_PORT_PHYS_STATE
] = MNL_TYPE_U8
,
107 [RDMA_NLDEV_ATTR_DEV_NODE_TYPE
] = MNL_TYPE_U8
,
110 int rd_attr_cb(const struct nlattr
*attr
, void *data
)
112 const struct nlattr
**tb
= data
;
115 if (mnl_attr_type_valid(attr
, RDMA_NLDEV_ATTR_MAX
) < 0)
118 type
= mnl_attr_get_type(attr
);
120 if (mnl_attr_validate(attr
, nldev_policy
[type
]) < 0)
127 int rd_dev_init_cb(const struct nlmsghdr
*nlh
, void *data
)
129 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
130 struct dev_map
*dev_map
;
131 struct rd
*rd
= data
;
132 const char *dev_name
;
134 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
135 if (!tb
[RDMA_NLDEV_ATTR_DEV_NAME
] || !tb
[RDMA_NLDEV_ATTR_DEV_INDEX
])
137 if (!tb
[RDMA_NLDEV_ATTR_PORT_INDEX
]) {
138 pr_err("This tool doesn't support switches yet\n");
142 dev_name
= mnl_attr_get_str(tb
[RDMA_NLDEV_ATTR_DEV_NAME
]);
144 dev_map
= dev_map_alloc(dev_name
);
146 /* The main function will cleanup the allocations */
148 list_add_tail(&dev_map
->list
, &rd
->dev_map_list
);
150 dev_map
->num_ports
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_PORT_INDEX
]);
151 dev_map
->idx
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_DEV_INDEX
]);
155 void rd_free_devmap(struct rd
*rd
)
162 int rd_exec_cmd(struct rd
*rd
, const struct rd_cmd
*cmds
, const char *str
)
164 const struct rd_cmd
*c
;
166 /* First argument in objs table is default variant */
168 return cmds
->func(rd
);
170 for (c
= cmds
+ 1; c
->cmd
; ++c
) {
171 if (rd_argv_match(rd
, c
->cmd
)) {
172 /* Move to next argument */
178 pr_err("Unknown %s '%s'.\n", str
, rd_argv(rd
));
182 void rd_prepare_msg(struct rd
*rd
, uint32_t cmd
, uint32_t *seq
, uint16_t flags
)
186 rd
->nlh
= mnl_nlmsg_put_header(rd
->buff
);
187 rd
->nlh
->nlmsg_type
= RDMA_NL_GET_TYPE(RDMA_NL_NLDEV
, cmd
);
188 rd
->nlh
->nlmsg_seq
= *seq
;
189 rd
->nlh
->nlmsg_flags
= flags
;
192 int rd_send_msg(struct rd
*rd
)
196 rd
->nl
= mnl_socket_open(NETLINK_RDMA
);
198 pr_err("Failed to open NETLINK_RDMA socket\n");
202 ret
= mnl_socket_bind(rd
->nl
, 0, MNL_SOCKET_AUTOPID
);
204 pr_err("Failed to bind socket with err %d\n", ret
);
208 ret
= mnl_socket_sendto(rd
->nl
, rd
->nlh
, rd
->nlh
->nlmsg_len
);
210 pr_err("Failed to send to socket with err %d\n", ret
);
216 mnl_socket_close(rd
->nl
);
220 int rd_recv_msg(struct rd
*rd
, mnl_cb_t callback
, void *data
, unsigned int seq
)
224 char buf
[MNL_SOCKET_BUFFER_SIZE
];
226 portid
= mnl_socket_get_portid(rd
->nl
);
228 ret
= mnl_socket_recvfrom(rd
->nl
, buf
, sizeof(buf
));
232 ret
= mnl_cb_run(buf
, ret
, seq
, portid
, callback
, data
);
235 mnl_socket_close(rd
->nl
);
239 struct dev_map
*_dev_map_lookup(struct rd
*rd
, const char *dev_name
)
241 struct dev_map
*dev_map
;
243 list_for_each_entry(dev_map
, &rd
->dev_map_list
, list
)
244 if (strcmp(dev_name
, dev_map
->dev_name
) == 0)
250 struct dev_map
*dev_map_lookup(struct rd
*rd
, bool allow_port_index
)
252 struct dev_map
*dev_map
;
256 dev_name
= strdup(rd_argv(rd
));
257 if (allow_port_index
) {
258 slash
= strrchr(dev_name
, '/');
263 dev_map
= _dev_map_lookup(rd
, dev_name
);