From: Parav Pandit Date: Tue, 23 Jun 2020 10:44:24 +0000 (+0000) Subject: devlink: Support querying hardware address of port function X-Git-Url: https://git.proxmox.com/?a=commitdiff_plain;h=b3adafd15431bf57269d8f1c30bba03885ff5ab2;p=mirror_iproute2.git devlink: Support querying hardware address of port function Add support to query the hardware address of function represented by devlink port function. Example of a PCI VF port which supports a port function: $ devlink port show pci/0000:06:00.0/2 pci/0000:06:00.0/2: type eth netdev enp6s0pf0vf1 flavour pcivf pfnum 0 vfnum 1 function: hw_addr 00:11:22:33:44:66 $ devlink port show pci/0000:06:00.0/2 -jp { "port": { "pci/0000:06:00.0/2": { "type": "eth", "netdev": "enp6s0pf0vf1", "flavour": "pcivf", "pfnum": 0, "vfnum": 1, "function": { "hw_addr": "00:11:22:33:44:66" } } } } Signed-off-by: Parav Pandit Reviewed-by: Jiri Pirko Signed-off-by: David Ahern --- diff --git a/devlink/devlink.c b/devlink/devlink.c index b7699f30..16fc834e 100644 --- a/devlink/devlink.c +++ b/devlink/devlink.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "SNAPSHOT.h" #include "list.h" @@ -708,6 +709,30 @@ static int attr_stats_cb(const struct nlattr *attr, void *data) return MNL_CB_OK; } +static const enum mnl_attr_data_type +devlink_function_policy[DEVLINK_PORT_FUNCTION_ATTR_MAX + 1] = { + [DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR ] = MNL_TYPE_BINARY, +}; + +static int function_attr_cb(const struct nlattr *attr, void *data) +{ + const struct nlattr **tb = data; + int type; + + /* Allow the tool to work on top of newer kernels that might contain + * more attributes. + */ + if (mnl_attr_type_valid(attr, DEVLINK_PORT_FUNCTION_ATTR_MAX) < 0) + return MNL_CB_OK; + + type = mnl_attr_get_type(attr); + if (mnl_attr_validate(attr, devlink_function_policy[type]) < 0) + return MNL_CB_ERROR; + + tb[type] = attr; + return MNL_CB_OK; +} + static int ifname_map_cb(const struct nlmsghdr *nlh, void *data) { struct nlattr *tb[DEVLINK_ATTR_MAX + 1] = {}; @@ -3243,6 +3268,37 @@ static void pr_out_port_pfvf_num(struct dl *dl, struct nlattr **tb) } } +static void pr_out_port_function(struct dl *dl, struct nlattr **tb_port) +{ + struct nlattr *tb[DEVLINK_PORT_FUNCTION_ATTR_MAX + 1] = {}; + unsigned char *data; + SPRINT_BUF(hw_addr); + uint32_t len; + int err; + + if (!tb_port[DEVLINK_ATTR_PORT_FUNCTION]) + return; + + err = mnl_attr_parse_nested(tb_port[DEVLINK_ATTR_PORT_FUNCTION], + function_attr_cb, tb); + if (err != MNL_CB_OK) + return; + + if (!tb[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR]) + return; + + len = mnl_attr_get_payload_len(tb[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR]); + data = mnl_attr_get_payload(tb[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR]); + + pr_out_object_start(dl, "function"); + check_indent_newline(dl); + print_string(PRINT_ANY, "hw_addr", "hw_addr %s", + ll_addr_n2a(data, len, 0, hw_addr, sizeof(hw_addr))); + if (!dl->json_output) + __pr_out_indent_dec(); + pr_out_object_end(dl); +} + static void pr_out_port(struct dl *dl, struct nlattr **tb) { struct nlattr *pt_attr = tb[DEVLINK_ATTR_PORT_TYPE]; @@ -3296,6 +3352,7 @@ static void pr_out_port(struct dl *dl, struct nlattr **tb) if (tb[DEVLINK_ATTR_PORT_SPLIT_GROUP]) print_uint(PRINT_ANY, "split_group", " split_group %u", mnl_attr_get_u32(tb[DEVLINK_ATTR_PORT_SPLIT_GROUP])); + pr_out_port_function(dl, tb); pr_out_port_handle_end(dl); }