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_LOW(x) \
34 x(SYS_IMAGE_GUID, 11) \
35 x(PKEY_SW_EXT_PORT_TRAP, 12) \
37 x(EXTENDED_SPEEDS, 14) \
45 x(CAP_MASK_NOTICE, 22) \
49 x(OTHER_LOCAL_CHANGES, 26) \
50 x(LINK_SPPED_WIDTH, 27) \
51 x(VENDOR_SPECIFIC_MADS, 28) \
52 x(MULT_PKER_TRAP, 29) \
56 #define RDMA_PORT_FLAGS_HIGH(x) \
60 x(SWITCH_POR_STATE_TABLE, 3) \
65 * Separation below is needed to allow compilation of rdmatool
66 * on 32bits systems. On such systems, C-enum is limited to be
67 * int and can't hold more than 32 bits.
69 enum { RDMA_PORT_FLAGS_LOW(RDMA_BITMAP_ENUM
) };
70 enum { RDMA_PORT_FLAGS_HIGH(RDMA_BITMAP_ENUM
) };
72 static const char * const
73 rdma_port_names_low
[] = { RDMA_PORT_FLAGS_LOW(RDMA_BITMAP_NAMES
) };
74 static const char * const
75 rdma_port_names_high
[] = { RDMA_PORT_FLAGS_HIGH(RDMA_BITMAP_NAMES
) };
77 #undef RDMA_PORT_FLAGS_LOW
78 #undef RDMA_PORT_FLAGS_HIGH
80 if (idx
< ARRAY_SIZE(rdma_port_names_low
) && rdma_port_names_low
[idx
])
81 return rdma_port_names_low
[idx
];
83 high_idx
= idx
- ARRAY_SIZE(rdma_port_names_low
);
84 if (high_idx
< ARRAY_SIZE(rdma_port_names_high
) &&
85 rdma_port_names_high
[high_idx
])
86 return rdma_port_names_high
[high_idx
];
91 static void link_print_caps(struct rd
*rd
, struct nlattr
**tb
)
96 if (!tb
[RDMA_NLDEV_ATTR_CAP_FLAGS
])
99 caps
= mnl_attr_get_u64(tb
[RDMA_NLDEV_ATTR_CAP_FLAGS
]);
101 if (rd
->json_output
) {
102 jsonw_name(rd
->jw
, "caps");
103 jsonw_start_array(rd
->jw
);
105 pr_out("\n caps: <");
107 for (idx
= 0; caps
; idx
++) {
109 if (rd
->json_output
) {
110 jsonw_string(rd
->jw
, caps_to_str(idx
));
112 pr_out("%s", caps_to_str(idx
));
121 jsonw_end_array(rd
->jw
);
126 static void link_print_subnet_prefix(struct rd
*rd
, struct nlattr
**tb
)
128 uint64_t subnet_prefix
;
132 if (!tb
[RDMA_NLDEV_ATTR_SUBNET_PREFIX
])
135 subnet_prefix
= mnl_attr_get_u64(tb
[RDMA_NLDEV_ATTR_SUBNET_PREFIX
]);
136 memcpy(vp
, &subnet_prefix
, sizeof(uint64_t));
137 snprintf(str
, 32, "%04x:%04x:%04x:%04x", vp
[3], vp
[2], vp
[1], vp
[0]);
139 jsonw_string_field(rd
->jw
, "subnet_prefix", str
);
141 pr_out("subnet_prefix %s ", str
);
144 static void link_print_lid(struct rd
*rd
, struct nlattr
**tb
)
148 if (!tb
[RDMA_NLDEV_ATTR_LID
])
151 lid
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_LID
]);
153 jsonw_uint_field(rd
->jw
, "lid", lid
);
155 pr_out("lid %u ", lid
);
158 static void link_print_sm_lid(struct rd
*rd
, struct nlattr
**tb
)
162 if (!tb
[RDMA_NLDEV_ATTR_SM_LID
])
165 sm_lid
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_SM_LID
]);
167 jsonw_uint_field(rd
->jw
, "sm_lid", sm_lid
);
169 pr_out("sm_lid %u ", sm_lid
);
172 static void link_print_lmc(struct rd
*rd
, struct nlattr
**tb
)
176 if (!tb
[RDMA_NLDEV_ATTR_LMC
])
179 lmc
= mnl_attr_get_u8(tb
[RDMA_NLDEV_ATTR_LMC
]);
181 jsonw_uint_field(rd
->jw
, "lmc", lmc
);
183 pr_out("lmc %u ", lmc
);
186 static const char *link_state_to_str(uint8_t link_state
)
188 static const char * const link_state_str
[] = { "NOP", "DOWN",
192 if (link_state
< ARRAY_SIZE(link_state_str
))
193 return link_state_str
[link_state
];
197 static void link_print_state(struct rd
*rd
, struct nlattr
**tb
)
201 if (!tb
[RDMA_NLDEV_ATTR_PORT_STATE
])
204 state
= mnl_attr_get_u8(tb
[RDMA_NLDEV_ATTR_PORT_STATE
]);
206 jsonw_string_field(rd
->jw
, "state", link_state_to_str(state
));
208 pr_out("state %s ", link_state_to_str(state
));
211 static const char *phys_state_to_str(uint8_t phys_state
)
213 static const char * const phys_state_str
[] = { "NOP", "SLEEP",
214 "POLLING", "DISABLED",
216 "LINK_ERROR_RECOVER",
217 "PHY_TEST", "UNKNOWN",
219 "UNKNOWN", "OPA_TEST" };
220 if (phys_state
< ARRAY_SIZE(phys_state_str
))
221 return phys_state_str
[phys_state
];
225 static void link_print_phys_state(struct rd
*rd
, struct nlattr
**tb
)
229 if (!tb
[RDMA_NLDEV_ATTR_PORT_PHYS_STATE
])
232 phys_state
= mnl_attr_get_u8(tb
[RDMA_NLDEV_ATTR_PORT_PHYS_STATE
]);
234 jsonw_string_field(rd
->jw
, "physical_state",
235 phys_state_to_str(phys_state
));
237 pr_out("physical_state %s ", phys_state_to_str(phys_state
));
240 static void link_print_netdev(struct rd
*rd
, struct nlattr
**tb
)
242 const char *netdev_name
;
245 if (!tb
[RDMA_NLDEV_ATTR_NDEV_NAME
] || !tb
[RDMA_NLDEV_ATTR_NDEV_INDEX
])
248 netdev_name
= mnl_attr_get_str(tb
[RDMA_NLDEV_ATTR_NDEV_NAME
]);
249 idx
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_NDEV_INDEX
]);
250 if (rd
->json_output
) {
251 jsonw_string_field(rd
->jw
, "netdev", netdev_name
);
252 jsonw_uint_field(rd
->jw
, "netdev_index", idx
);
254 pr_out("netdev %s ", netdev_name
);
255 if (rd
->show_details
)
256 pr_out("netdev_index %u ", idx
);
260 static int link_parse_cb(const struct nlmsghdr
*nlh
, void *data
)
262 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
263 struct rd
*rd
= data
;
267 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
268 if (!tb
[RDMA_NLDEV_ATTR_DEV_INDEX
] || !tb
[RDMA_NLDEV_ATTR_DEV_NAME
])
271 if (!tb
[RDMA_NLDEV_ATTR_PORT_INDEX
]) {
272 pr_err("This tool doesn't support switches yet\n");
276 idx
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_DEV_INDEX
]);
277 port
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_PORT_INDEX
]);
278 snprintf(name
, 32, "%s/%u",
279 mnl_attr_get_str(tb
[RDMA_NLDEV_ATTR_DEV_NAME
]), port
);
281 if (rd
->json_output
) {
282 jsonw_uint_field(rd
->jw
, "ifindex", idx
);
283 jsonw_uint_field(rd
->jw
, "port", port
);
284 jsonw_string_field(rd
->jw
, "ifname", name
);
287 pr_out("%u/%u: %s: ", idx
, port
, name
);
290 link_print_subnet_prefix(rd
, tb
);
291 link_print_lid(rd
, tb
);
292 link_print_sm_lid(rd
, tb
);
293 link_print_lmc(rd
, tb
);
294 link_print_state(rd
, tb
);
295 link_print_phys_state(rd
, tb
);
296 link_print_netdev(rd
, tb
);
297 if (rd
->show_details
)
298 link_print_caps(rd
, tb
);
300 if (!rd
->json_output
)
305 static int link_no_args(struct rd
*rd
)
310 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_PORT_GET
, &seq
,
311 (NLM_F_REQUEST
| NLM_F_ACK
));
312 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
313 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_PORT_INDEX
, rd
->port_idx
);
314 ret
= rd_send_msg(rd
);
319 jsonw_start_object(rd
->jw
);
320 ret
= rd_recv_msg(rd
, link_parse_cb
, rd
, seq
);
322 jsonw_end_object(rd
->jw
);
326 static int link_one_show(struct rd
*rd
)
328 const struct rd_cmd cmds
[] = {
329 { NULL
, link_no_args
},
336 return rd_exec_cmd(rd
, cmds
, "parameter");
339 static int link_show(struct rd
*rd
)
341 return rd_exec_link(rd
, link_one_show
, true);
344 int cmd_link(struct rd
*rd
)
346 const struct rd_cmd cmds
[] = {
348 { "show", link_show
},
349 { "list", link_show
},
350 { "help", link_help
},
354 return rd_exec_cmd(rd
, cmds
, "link command");