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 link_help(struct rd
*rd
)
16 pr_out("Usage: %s link show [DEV/PORT_INDEX]\n", rd
->filename
);
20 static const char *caps_to_str(uint32_t idx
)
22 #define RDMA_PORT_FLAGS(x) \
33 x(SYS_IMAGE_GUIG, 11) \
34 x(PKEY_SW_EXT_PORT_TRAP, 12) \
35 x(EXTENDED_SPEEDS, 14) \
42 x(CAP_MASK_NOTICE, 22) \
48 enum { RDMA_PORT_FLAGS(RDMA_BITMAP_ENUM
) };
50 static const char * const
51 rdma_port_names
[] = { RDMA_PORT_FLAGS(RDMA_BITMAP_NAMES
) };
52 #undef RDMA_PORT_FLAGS
54 if (idx
< ARRAY_SIZE(rdma_port_names
) && rdma_port_names
[idx
])
55 return rdma_port_names
[idx
];
59 static void link_print_caps(struct rd
*rd
, struct nlattr
**tb
)
64 if (!tb
[RDMA_NLDEV_ATTR_CAP_FLAGS
])
67 caps
= mnl_attr_get_u64(tb
[RDMA_NLDEV_ATTR_CAP_FLAGS
]);
69 if (rd
->json_output
) {
70 jsonw_name(rd
->jw
, "caps");
71 jsonw_start_array(rd
->jw
);
75 for (idx
= 0; caps
; idx
++) {
77 if (rd
->json_output
) {
78 jsonw_string(rd
->jw
, caps_to_str(idx
));
80 pr_out("%s", caps_to_str(idx
));
89 jsonw_end_array(rd
->jw
);
94 static void link_print_subnet_prefix(struct rd
*rd
, struct nlattr
**tb
)
96 uint64_t subnet_prefix
;
100 if (!tb
[RDMA_NLDEV_ATTR_SUBNET_PREFIX
])
103 subnet_prefix
= mnl_attr_get_u64(tb
[RDMA_NLDEV_ATTR_SUBNET_PREFIX
]);
104 memcpy(vp
, &subnet_prefix
, sizeof(uint64_t));
105 snprintf(str
, 32, "%04x:%04x:%04x:%04x", vp
[3], vp
[2], vp
[1], vp
[0]);
107 jsonw_string_field(rd
->jw
, "subnet_prefix", str
);
109 pr_out("subnet_prefix %s ", str
);
112 static void link_print_lid(struct rd
*rd
, struct nlattr
**tb
)
116 if (!tb
[RDMA_NLDEV_ATTR_LID
])
119 lid
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_LID
]);
121 jsonw_uint_field(rd
->jw
, "lid", lid
);
123 pr_out("lid %u ", lid
);
126 static void link_print_sm_lid(struct rd
*rd
, struct nlattr
**tb
)
130 if (!tb
[RDMA_NLDEV_ATTR_SM_LID
])
133 sm_lid
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_SM_LID
]);
135 jsonw_uint_field(rd
->jw
, "sm_lid", sm_lid
);
137 pr_out("sm_lid %u ", sm_lid
);
140 static void link_print_lmc(struct rd
*rd
, struct nlattr
**tb
)
144 if (!tb
[RDMA_NLDEV_ATTR_LMC
])
147 lmc
= mnl_attr_get_u8(tb
[RDMA_NLDEV_ATTR_LMC
]);
149 jsonw_uint_field(rd
->jw
, "lmc", lmc
);
151 pr_out("lmc %u ", lmc
);
154 static const char *link_state_to_str(uint8_t link_state
)
156 static const char * const link_state_str
[] = { "NOP", "DOWN",
160 if (link_state
< ARRAY_SIZE(link_state_str
))
161 return link_state_str
[link_state
];
165 static void link_print_state(struct rd
*rd
, struct nlattr
**tb
)
169 if (!tb
[RDMA_NLDEV_ATTR_PORT_STATE
])
172 state
= mnl_attr_get_u8(tb
[RDMA_NLDEV_ATTR_PORT_STATE
]);
174 jsonw_string_field(rd
->jw
, "state", link_state_to_str(state
));
176 pr_out("state %s ", link_state_to_str(state
));
179 static const char *phys_state_to_str(uint8_t phys_state
)
181 static const char * const phys_state_str
[] = { "NOP", "SLEEP",
182 "POLLING", "DISABLED",
184 "LINK_ERROR_RECOVER",
185 "PHY_TEST", "UNKNOWN",
187 "UNKNOWN", "OPA_TEST" };
188 if (phys_state
< ARRAY_SIZE(phys_state_str
))
189 return phys_state_str
[phys_state
];
193 static void link_print_phys_state(struct rd
*rd
, struct nlattr
**tb
)
197 if (!tb
[RDMA_NLDEV_ATTR_PORT_PHYS_STATE
])
200 phys_state
= mnl_attr_get_u8(tb
[RDMA_NLDEV_ATTR_PORT_PHYS_STATE
]);
202 jsonw_string_field(rd
->jw
, "physical_state",
203 phys_state_to_str(phys_state
));
205 pr_out("physical_state %s ", phys_state_to_str(phys_state
));
208 static int link_parse_cb(const struct nlmsghdr
*nlh
, void *data
)
210 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
211 struct rd
*rd
= data
;
215 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
216 if (!tb
[RDMA_NLDEV_ATTR_DEV_INDEX
] || !tb
[RDMA_NLDEV_ATTR_DEV_NAME
])
219 if (!tb
[RDMA_NLDEV_ATTR_PORT_INDEX
]) {
220 pr_err("This tool doesn't support switches yet\n");
224 idx
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_DEV_INDEX
]);
225 port
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_PORT_INDEX
]);
226 snprintf(name
, 32, "%s/%u",
227 mnl_attr_get_str(tb
[RDMA_NLDEV_ATTR_DEV_NAME
]), port
);
229 if (rd
->json_output
) {
230 jsonw_uint_field(rd
->jw
, "ifindex", idx
);
231 jsonw_uint_field(rd
->jw
, "port", port
);
232 jsonw_string_field(rd
->jw
, "ifname", name
);
235 pr_out("%u/%u: %s: ", idx
, port
, name
);
238 link_print_subnet_prefix(rd
, tb
);
239 link_print_lid(rd
, tb
);
240 link_print_sm_lid(rd
, tb
);
241 link_print_lmc(rd
, tb
);
242 link_print_state(rd
, tb
);
243 link_print_phys_state(rd
, tb
);
244 if (rd
->show_details
)
245 link_print_caps(rd
, tb
);
247 if (!rd
->json_output
)
252 static int link_no_args(struct rd
*rd
)
257 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_PORT_GET
, &seq
,
258 (NLM_F_REQUEST
| NLM_F_ACK
));
259 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
260 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_PORT_INDEX
, rd
->port_idx
);
261 ret
= rd_send_msg(rd
);
266 jsonw_start_object(rd
->jw
);
267 ret
= rd_recv_msg(rd
, link_parse_cb
, rd
, seq
);
269 jsonw_end_object(rd
->jw
);
273 static int link_one_show(struct rd
*rd
)
275 const struct rd_cmd cmds
[] = {
276 { NULL
, link_no_args
},
280 return rd_exec_cmd(rd
, cmds
, "parameter");
283 static int link_show(struct rd
*rd
)
285 struct dev_map
*dev_map
;
290 jsonw_start_array(rd
->jw
);
292 list_for_each_entry(dev_map
, &rd
->dev_map_list
, list
) {
293 rd
->dev_idx
= dev_map
->idx
;
294 for (port
= 1; port
< dev_map
->num_ports
+ 1; port
++) {
296 ret
= link_one_show(rd
);
303 dev_map
= dev_map_lookup(rd
, true);
304 port
= get_port_from_argv(rd
);
305 if (!dev_map
|| port
> dev_map
->num_ports
) {
306 pr_err("Wrong device name\n");
311 rd
->dev_idx
= dev_map
->idx
;
312 rd
->port_idx
= port
? : 1;
313 for (; rd
->port_idx
< dev_map
->num_ports
+ 1; rd
->port_idx
++) {
314 ret
= link_one_show(rd
);
319 * We got request to show link for devname
328 jsonw_end_array(rd
->jw
);
332 int cmd_link(struct rd
*rd
)
334 const struct rd_cmd cmds
[] = {
336 { "show", link_show
},
337 { "list", link_show
},
338 { "help", link_help
},
342 return rd_exec_cmd(rd
, cmds
, "link command");