There is at least three places implementing same things: two in ipaddress.c print_linkinfo() & print_linkinfo_brief() and one in bridge/link.c.
They are diverge from each other very little: bridge/link.c does not support JSON output at the moment and print_linkinfo_brief() does not handle IFLA_LINK_NETNS case. Introduce and use print_name_and_link() routine to handle name@link output in all possible variations; respect IFLA_LINK_NETNS attribute to handle case when link is in different namespace; use ll_idx_n2a() for interface name instead of "<nil>" to share logic with other code (e.g. ll_name_to_index() and ll_index_to_name()) supporting such template. Signed-off-by: Serhey Popovych <serhe.popov...@gmail.com> --- bridge/link.c | 13 +++---------- include/utils.h | 4 ++++ ip/ipaddress.c | 44 ++------------------------------------------ lib/utils.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 58 insertions(+), 52 deletions(-) diff --git a/bridge/link.c b/bridge/link.c index a11cbb1..90c9734 100644 --- a/bridge/link.c +++ b/bridge/link.c @@ -125,20 +125,13 @@ int print_linkinfo(const struct sockaddr_nl *who, if (n->nlmsg_type == RTM_DELLINK) fprintf(fp, "Deleted "); - fprintf(fp, "%d: %s ", ifi->ifi_index, - tb[IFLA_IFNAME] ? rta_getattr_str(tb[IFLA_IFNAME]) : "<nil>"); + fprintf(fp, "%d: ", ifi->ifi_index); + + print_name_and_link("%s: ", COLOR_NONE, name, tb); if (tb[IFLA_OPERSTATE]) print_operstate(fp, rta_getattr_u8(tb[IFLA_OPERSTATE])); - if (tb[IFLA_LINK]) { - int iflink = rta_getattr_u32(tb[IFLA_LINK]); - - fprintf(fp, "@%s: ", - iflink ? ll_index_to_name(iflink) : "NONE"); - } else - fprintf(fp, ": "); - print_link_flags(fp, ifi->ifi_flags); if (tb[IFLA_MTU]) diff --git a/include/utils.h b/include/utils.h index 84ca873..75ddb4a 100644 --- a/include/utils.h +++ b/include/utils.h @@ -12,6 +12,7 @@ #include "libnetlink.h" #include "ll_map.h" #include "rtm_map.h" +#include "json_print.h" extern int preferred_family; extern int human_readable; @@ -250,6 +251,9 @@ void print_escape_buf(const __u8 *buf, size_t len, const char *escape); int print_timestamp(FILE *fp); void print_nlmsg_timestamp(FILE *fp, const struct nlmsghdr *n); +unsigned int print_name_and_link(const char *fmt, enum color_attr color, + const char *name, struct rtattr *tb[]); + #define BIT(nr) (1UL << (nr)) #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) diff --git a/ip/ipaddress.c b/ip/ipaddress.c index 670d8e0..e14a59e 100644 --- a/ip/ipaddress.c +++ b/ip/ipaddress.c @@ -760,7 +760,6 @@ int print_linkinfo_brief(const struct sockaddr_nl *who, struct rtattr *tb[IFLA_MAX+1]; int len = n->nlmsg_len; const char *name; - char buf[32] = { 0, }; unsigned int m_flag = 0; if (n->nlmsg_type != RTM_NEWLINK && n->nlmsg_type != RTM_DELLINK) @@ -810,25 +809,7 @@ int print_linkinfo_brief(const struct sockaddr_nl *who, if (n->nlmsg_type == RTM_DELLINK) print_bool(PRINT_ANY, "deleted", "Deleted ", true); - if (tb[IFLA_LINK]) { - int iflink = rta_getattr_u32(tb[IFLA_LINK]); - - if (iflink == 0) { - snprintf(buf, sizeof(buf), "%s@NONE", name); - print_null(PRINT_JSON, "link", NULL, NULL); - } else { - const char *link = ll_index_to_name(iflink); - - print_string(PRINT_JSON, "link", NULL, link); - snprintf(buf, sizeof(buf), "%s@%s", name, link); - m_flag = ll_index_to_flags(iflink); - m_flag = !(m_flag & IFF_UP); - } - } else - snprintf(buf, sizeof(buf), "%s", name); - - print_string(PRINT_FP, NULL, "%-16s ", buf); - print_string(PRINT_JSON, "ifname", NULL, name); + m_flag = print_name_and_link("%-16s ", COLOR_NONE, name, tb); if (tb[IFLA_OPERSTATE]) print_operstate(fp, rta_getattr_u8(tb[IFLA_OPERSTATE])); @@ -936,29 +917,8 @@ int print_linkinfo(const struct sockaddr_nl *who, print_bool(PRINT_ANY, "deleted", "Deleted ", true); print_int(PRINT_ANY, "ifindex", "%d: ", ifi->ifi_index); - print_color_string(PRINT_ANY, COLOR_IFNAME, "ifname", "%s", name); - - if (tb[IFLA_LINK]) { - int iflink = rta_getattr_u32(tb[IFLA_LINK]); - if (iflink == 0) - print_null(PRINT_ANY, "link", "@%s: ", "NONE"); - else { - if (tb[IFLA_LINK_NETNSID]) - print_int(PRINT_ANY, - "link_index", "@if%d: ", iflink); - else { - print_string(PRINT_ANY, - "link", - "@%s: ", - ll_index_to_name(iflink)); - m_flag = ll_index_to_flags(iflink); - m_flag = !(m_flag & IFF_UP); - } - } - } else { - print_string(PRINT_FP, NULL, ": ", NULL); - } + m_flag = print_name_and_link("%s: ", COLOR_IFNAME, name, tb); print_link_flags(fp, ifi->ifi_flags, m_flag); if (tb[IFLA_MTU]) diff --git a/lib/utils.c b/lib/utils.c index 572d42a..0f9523c 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -33,6 +33,7 @@ #include "rt_names.h" #include "utils.h" +#include "ll_map.h" #include "namespace.h" int resolve_hosts; @@ -1260,6 +1261,54 @@ int print_timestamp(FILE *fp) return 0; } +unsigned int print_name_and_link(const char *fmt, enum color_attr color, + const char *name, struct rtattr *tb[]) +{ + const char *link = NULL; + unsigned int m_flag = 0; + SPRINT_BUF(b1); + + if (tb[IFLA_LINK]) { + int iflink = rta_getattr_u32(tb[IFLA_LINK]); + + if (iflink) { + if (tb[IFLA_LINK_NETNSID]) { + if (is_json_context()) { + print_int(PRINT_JSON, + "link_index", NULL, iflink); + } else { + link = ll_idx_n2a(iflink); + } + } else { + link = ll_index_to_name(iflink); + + if (is_json_context()) { + print_string(PRINT_JSON, + "link", NULL, link); + link = NULL; + } + + m_flag = ll_index_to_flags(iflink); + m_flag = !(m_flag & IFF_UP); + } + } else { + if (is_json_context()) + print_null(PRINT_JSON, "link", NULL, NULL); + else + link = "NONE"; + } + + if (link) { + snprintf(b1, sizeof(b1), "%s@%s", name, link); + name = b1; + } + } + + print_color_string(PRINT_ANY, color, "ifname", fmt, name); + + return m_flag; +} + int cmdlineno; /* Like glibc getline but handle continuation lines and comments */ -- 1.7.10.4