1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
4 * Authors: Leon Romanovsky <leonro@mellanox.com>
9 static int link_help(struct rd
*rd
)
11 pr_out("Usage: %s link show [DEV/PORT_INDEX]\n", rd
->filename
);
12 pr_out("Usage: %s link add NAME type TYPE netdev NETDEV\n",
14 pr_out("Usage: %s link delete NAME\n", rd
->filename
);
18 static const char *caps_to_str(uint32_t idx
)
20 #define RDMA_PORT_FLAGS_LOW(x) \
32 x(SYS_IMAGE_GUID, 11) \
33 x(PKEY_SW_EXT_PORT_TRAP, 12) \
35 x(EXTENDED_SPEEDS, 14) \
43 x(CAP_MASK_NOTICE, 22) \
47 x(OTHER_LOCAL_CHANGES, 26) \
48 x(LINK_SPPED_WIDTH, 27) \
49 x(VENDOR_SPECIFIC_MADS, 28) \
50 x(MULT_PKER_TRAP, 29) \
54 #define RDMA_PORT_FLAGS_HIGH(x) \
58 x(SWITCH_POR_STATE_TABLE, 3) \
63 * Separation below is needed to allow compilation of rdmatool
64 * on 32bits systems. On such systems, C-enum is limited to be
65 * int and can't hold more than 32 bits.
67 enum { RDMA_PORT_FLAGS_LOW(RDMA_BITMAP_ENUM
) };
68 enum { RDMA_PORT_FLAGS_HIGH(RDMA_BITMAP_ENUM
) };
70 static const char * const
71 rdma_port_names_low
[] = { RDMA_PORT_FLAGS_LOW(RDMA_BITMAP_NAMES
) };
72 static const char * const
73 rdma_port_names_high
[] = { RDMA_PORT_FLAGS_HIGH(RDMA_BITMAP_NAMES
) };
75 #undef RDMA_PORT_FLAGS_LOW
76 #undef RDMA_PORT_FLAGS_HIGH
78 if (idx
< ARRAY_SIZE(rdma_port_names_low
) && rdma_port_names_low
[idx
])
79 return rdma_port_names_low
[idx
];
81 high_idx
= idx
- ARRAY_SIZE(rdma_port_names_low
);
82 if (high_idx
< ARRAY_SIZE(rdma_port_names_high
) &&
83 rdma_port_names_high
[high_idx
])
84 return rdma_port_names_high
[high_idx
];
89 static void link_print_caps(struct rd
*rd
, struct nlattr
**tb
)
94 if (!tb
[RDMA_NLDEV_ATTR_CAP_FLAGS
])
97 caps
= mnl_attr_get_u64(tb
[RDMA_NLDEV_ATTR_CAP_FLAGS
]);
99 print_color_string(PRINT_FP
, COLOR_NONE
, NULL
, "\n caps: <", NULL
);
100 open_json_array(PRINT_JSON
, "caps");
101 for (idx
= 0; caps
; idx
++) {
103 print_color_string(PRINT_ANY
, COLOR_NONE
, NULL
,
104 caps
>> 0x1 ? "%s, " : "%s",
108 close_json_array(PRINT_ANY
, ">");
111 static void link_print_subnet_prefix(struct rd
*rd
, struct nlattr
**tb
)
113 uint64_t subnet_prefix
;
117 if (!tb
[RDMA_NLDEV_ATTR_SUBNET_PREFIX
])
120 subnet_prefix
= mnl_attr_get_u64(tb
[RDMA_NLDEV_ATTR_SUBNET_PREFIX
]);
121 memcpy(vp
, &subnet_prefix
, sizeof(uint64_t));
122 snprintf(str
, 32, "%04x:%04x:%04x:%04x", vp
[3], vp
[2], vp
[1], vp
[0]);
123 print_color_string(PRINT_ANY
, COLOR_NONE
, "subnet_prefix",
124 "subnet_prefix %s ", str
);
127 static void link_print_lid(struct rd
*rd
, struct nlattr
**tb
)
131 if (!tb
[RDMA_NLDEV_ATTR_LID
])
134 lid
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_LID
]);
135 print_color_uint(PRINT_ANY
, COLOR_NONE
, "lid", "lid %u ", lid
);
138 static void link_print_sm_lid(struct rd
*rd
, struct nlattr
**tb
)
142 if (!tb
[RDMA_NLDEV_ATTR_SM_LID
])
145 sm_lid
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_SM_LID
]);
146 print_color_uint(PRINT_ANY
, COLOR_NONE
, "sm_lid", "sm_lid %u ", sm_lid
);
149 static void link_print_lmc(struct rd
*rd
, struct nlattr
**tb
)
153 if (!tb
[RDMA_NLDEV_ATTR_LMC
])
156 lmc
= mnl_attr_get_u8(tb
[RDMA_NLDEV_ATTR_LMC
]);
157 print_color_uint(PRINT_ANY
, COLOR_NONE
, "lmc", "lmc %u ", lmc
);
160 static const char *link_state_to_str(uint8_t link_state
)
162 static const char * const link_state_str
[] = { "NOP", "DOWN",
166 if (link_state
< ARRAY_SIZE(link_state_str
))
167 return link_state_str
[link_state
];
171 static void link_print_state(struct rd
*rd
, struct nlattr
**tb
)
175 if (!tb
[RDMA_NLDEV_ATTR_PORT_STATE
])
178 state
= mnl_attr_get_u8(tb
[RDMA_NLDEV_ATTR_PORT_STATE
]);
179 print_color_string(PRINT_ANY
, COLOR_NONE
, "state", "state %s ",
180 link_state_to_str(state
));
183 static const char *phys_state_to_str(uint8_t phys_state
)
185 static const char * const phys_state_str
[] = { "NOP", "SLEEP",
186 "POLLING", "DISABLED",
188 "LINK_ERROR_RECOVER",
189 "PHY_TEST", "UNKNOWN",
191 "UNKNOWN", "OPA_TEST" };
192 if (phys_state
< ARRAY_SIZE(phys_state_str
))
193 return phys_state_str
[phys_state
];
197 static void link_print_phys_state(struct rd
*rd
, struct nlattr
**tb
)
201 if (!tb
[RDMA_NLDEV_ATTR_PORT_PHYS_STATE
])
204 phys_state
= mnl_attr_get_u8(tb
[RDMA_NLDEV_ATTR_PORT_PHYS_STATE
]);
205 print_color_string(PRINT_ANY
, COLOR_NONE
, "physical_state",
206 "physical_state %s ", phys_state_to_str(phys_state
));
209 static void link_print_netdev(struct rd
*rd
, struct nlattr
**tb
)
211 const char *netdev_name
;
214 if (!tb
[RDMA_NLDEV_ATTR_NDEV_NAME
] || !tb
[RDMA_NLDEV_ATTR_NDEV_INDEX
])
217 netdev_name
= mnl_attr_get_str(tb
[RDMA_NLDEV_ATTR_NDEV_NAME
]);
218 idx
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_NDEV_INDEX
]);
219 print_color_string(PRINT_ANY
, COLOR_NONE
, "netdev", "netdev %s ",
221 print_color_uint(PRINT_ANY
, COLOR_NONE
, "netdev_index",
222 rd
->show_details
? "netdev_index %u " : "", idx
);
225 static int link_parse_cb(const struct nlmsghdr
*nlh
, void *data
)
227 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
228 struct rd
*rd
= data
;
232 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
233 if (!tb
[RDMA_NLDEV_ATTR_DEV_INDEX
] || !tb
[RDMA_NLDEV_ATTR_DEV_NAME
])
236 if (!tb
[RDMA_NLDEV_ATTR_PORT_INDEX
]) {
237 pr_err("This tool doesn't support switches yet\n");
241 idx
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_DEV_INDEX
]);
242 port
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_PORT_INDEX
]);
243 name
= mnl_attr_get_str(tb
[RDMA_NLDEV_ATTR_DEV_NAME
]);
245 open_json_object(NULL
);
246 print_color_uint(PRINT_JSON
, COLOR_NONE
, "ifindex", NULL
, idx
);
247 print_color_string(PRINT_ANY
, COLOR_NONE
, "ifname", "link %s/", name
);
248 print_color_uint(PRINT_ANY
, COLOR_NONE
, "port", "%u ", port
);
249 link_print_subnet_prefix(rd
, tb
);
250 link_print_lid(rd
, tb
);
251 link_print_sm_lid(rd
, tb
);
252 link_print_lmc(rd
, tb
);
253 link_print_state(rd
, tb
);
254 link_print_phys_state(rd
, tb
);
255 link_print_netdev(rd
, tb
);
256 if (rd
->show_details
)
257 link_print_caps(rd
, tb
);
263 static int link_no_args(struct rd
*rd
)
268 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_PORT_GET
, &seq
,
269 (NLM_F_REQUEST
| NLM_F_ACK
));
270 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
271 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_PORT_INDEX
, rd
->port_idx
);
272 ret
= rd_send_msg(rd
);
276 ret
= rd_recv_msg(rd
, link_parse_cb
, rd
, seq
);
280 static int link_one_show(struct rd
*rd
)
282 const struct rd_cmd cmds
[] = {
283 { NULL
, link_no_args
},
290 return rd_exec_cmd(rd
, cmds
, "parameter");
293 static int link_show(struct rd
*rd
)
295 return rd_exec_link(rd
, link_one_show
, true);
298 static int link_add_netdev(struct rd
*rd
)
304 pr_err("Please provide a net device name.\n");
308 link_netdev
= rd_argv(rd
);
309 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_NEWLINK
, &seq
,
310 (NLM_F_REQUEST
| NLM_F_ACK
));
311 mnl_attr_put_strz(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_NAME
, rd
->link_name
);
312 mnl_attr_put_strz(rd
->nlh
, RDMA_NLDEV_ATTR_LINK_TYPE
, rd
->link_type
);
313 mnl_attr_put_strz(rd
->nlh
, RDMA_NLDEV_ATTR_NDEV_NAME
, link_netdev
);
314 return rd_sendrecv_msg(rd
, seq
);
317 static int link_add_type(struct rd
*rd
)
319 const struct rd_cmd cmds
[] = {
321 { "netdev", link_add_netdev
},
326 pr_err("Please provide a link type name.\n");
329 rd
->link_type
= rd_argv(rd
);
331 return rd_exec_cmd(rd
, cmds
, "parameter");
334 static int link_add(struct rd
*rd
)
336 const struct rd_cmd cmds
[] = {
338 { "type", link_add_type
},
343 pr_err("Please provide a link name to add.\n");
346 rd
->link_name
= rd_argv(rd
);
349 return rd_exec_cmd(rd
, cmds
, "parameter");
352 static int _link_del(struct rd
*rd
)
356 if (!rd_no_arg(rd
)) {
357 pr_err("Unknown parameter %s\n", rd_argv(rd
));
360 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_DELLINK
, &seq
,
361 (NLM_F_REQUEST
| NLM_F_ACK
));
362 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
363 return rd_sendrecv_msg(rd
, seq
);
366 static int link_del(struct rd
*rd
)
368 return rd_exec_require_dev(rd
, _link_del
);
371 int cmd_link(struct rd
*rd
)
373 const struct rd_cmd cmds
[] = {
376 { "delete", link_del
},
377 { "show", link_show
},
378 { "list", link_show
},
379 { "help", link_help
},
383 return rd_exec_cmd(rd
, cmds
, "link command");