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 void rd_print_u64(char *name
, uint64_t val
)
66 memcpy(vp
, &val
, sizeof(uint64_t));
67 pr_out("%s %04x:%04x:%04x:%04x ", name
, vp
[3], vp
[2], vp
[1], vp
[0]);
70 static struct dev_map
*dev_map_alloc(const char *dev_name
)
72 struct dev_map
*dev_map
;
74 dev_map
= calloc(1, sizeof(*dev_map
));
77 dev_map
->dev_name
= strdup(dev_name
);
82 static void dev_map_free(struct dev_map
*dev_map
)
87 free(dev_map
->dev_name
);
91 static void dev_map_cleanup(struct rd
*rd
)
93 struct dev_map
*dev_map
, *tmp
;
95 list_for_each_entry_safe(dev_map
, tmp
,
96 &rd
->dev_map_list
, list
) {
97 list_del(&dev_map
->list
);
98 dev_map_free(dev_map
);
102 static const enum mnl_attr_data_type nldev_policy
[RDMA_NLDEV_ATTR_MAX
] = {
103 [RDMA_NLDEV_ATTR_DEV_INDEX
] = MNL_TYPE_U32
,
104 [RDMA_NLDEV_ATTR_DEV_NAME
] = MNL_TYPE_NUL_STRING
,
105 [RDMA_NLDEV_ATTR_PORT_INDEX
] = MNL_TYPE_U32
,
106 [RDMA_NLDEV_ATTR_CAP_FLAGS
] = MNL_TYPE_U64
,
107 [RDMA_NLDEV_ATTR_FW_VERSION
] = MNL_TYPE_NUL_STRING
,
108 [RDMA_NLDEV_ATTR_NODE_GUID
] = MNL_TYPE_U64
,
109 [RDMA_NLDEV_ATTR_SYS_IMAGE_GUID
] = MNL_TYPE_U64
,
110 [RDMA_NLDEV_ATTR_LID
] = MNL_TYPE_U32
,
111 [RDMA_NLDEV_ATTR_SM_LID
] = MNL_TYPE_U32
,
112 [RDMA_NLDEV_ATTR_LMC
] = MNL_TYPE_U8
,
113 [RDMA_NLDEV_ATTR_PORT_STATE
] = MNL_TYPE_U8
,
114 [RDMA_NLDEV_ATTR_PORT_PHYS_STATE
] = MNL_TYPE_U8
,
115 [RDMA_NLDEV_ATTR_DEV_NODE_TYPE
] = MNL_TYPE_U8
,
118 int rd_attr_cb(const struct nlattr
*attr
, void *data
)
120 const struct nlattr
**tb
= data
;
123 if (mnl_attr_type_valid(attr
, RDMA_NLDEV_ATTR_MAX
) < 0)
126 type
= mnl_attr_get_type(attr
);
128 if (mnl_attr_validate(attr
, nldev_policy
[type
]) < 0)
135 int rd_dev_init_cb(const struct nlmsghdr
*nlh
, void *data
)
137 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
138 struct dev_map
*dev_map
;
139 struct rd
*rd
= data
;
140 const char *dev_name
;
142 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
143 if (!tb
[RDMA_NLDEV_ATTR_DEV_NAME
] || !tb
[RDMA_NLDEV_ATTR_DEV_INDEX
])
145 if (!tb
[RDMA_NLDEV_ATTR_PORT_INDEX
]) {
146 pr_err("This tool doesn't support switches yet\n");
150 dev_name
= mnl_attr_get_str(tb
[RDMA_NLDEV_ATTR_DEV_NAME
]);
152 dev_map
= dev_map_alloc(dev_name
);
154 /* The main function will cleanup the allocations */
156 list_add_tail(&dev_map
->list
, &rd
->dev_map_list
);
158 dev_map
->num_ports
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_PORT_INDEX
]);
159 dev_map
->idx
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_DEV_INDEX
]);
163 void rd_free_devmap(struct rd
*rd
)
170 int rd_exec_cmd(struct rd
*rd
, const struct rd_cmd
*cmds
, const char *str
)
172 const struct rd_cmd
*c
;
174 /* First argument in objs table is default variant */
176 return cmds
->func(rd
);
178 for (c
= cmds
+ 1; c
->cmd
; ++c
) {
179 if (rd_argv_match(rd
, c
->cmd
)) {
180 /* Move to next argument */
186 pr_err("Unknown %s '%s'.\n", str
, rd_argv(rd
));
190 void rd_prepare_msg(struct rd
*rd
, uint32_t cmd
, uint32_t *seq
, uint16_t flags
)
194 rd
->nlh
= mnl_nlmsg_put_header(rd
->buff
);
195 rd
->nlh
->nlmsg_type
= RDMA_NL_GET_TYPE(RDMA_NL_NLDEV
, cmd
);
196 rd
->nlh
->nlmsg_seq
= *seq
;
197 rd
->nlh
->nlmsg_flags
= flags
;
200 int rd_send_msg(struct rd
*rd
)
204 rd
->nl
= mnl_socket_open(NETLINK_RDMA
);
206 pr_err("Failed to open NETLINK_RDMA socket\n");
210 ret
= mnl_socket_bind(rd
->nl
, 0, MNL_SOCKET_AUTOPID
);
212 pr_err("Failed to bind socket with err %d\n", ret
);
216 ret
= mnl_socket_sendto(rd
->nl
, rd
->nlh
, rd
->nlh
->nlmsg_len
);
218 pr_err("Failed to send to socket with err %d\n", ret
);
224 mnl_socket_close(rd
->nl
);
228 int rd_recv_msg(struct rd
*rd
, mnl_cb_t callback
, void *data
, unsigned int seq
)
232 char buf
[MNL_SOCKET_BUFFER_SIZE
];
234 portid
= mnl_socket_get_portid(rd
->nl
);
236 ret
= mnl_socket_recvfrom(rd
->nl
, buf
, sizeof(buf
));
240 ret
= mnl_cb_run(buf
, ret
, seq
, portid
, callback
, data
);
243 mnl_socket_close(rd
->nl
);
247 struct dev_map
*_dev_map_lookup(struct rd
*rd
, const char *dev_name
)
249 struct dev_map
*dev_map
;
251 list_for_each_entry(dev_map
, &rd
->dev_map_list
, list
)
252 if (strcmp(dev_name
, dev_map
->dev_name
) == 0)
258 struct dev_map
*dev_map_lookup(struct rd
*rd
, bool allow_port_index
)
260 struct dev_map
*dev_map
;
264 dev_name
= strdup(rd_argv(rd
));
265 if (allow_port_index
) {
266 slash
= strrchr(dev_name
, '/');
271 dev_map
= _dev_map_lookup(rd
, dev_name
);