From: Andy Gospodarek Date: Fri, 28 Aug 2015 17:45:41 +0000 (-0400) Subject: add support for brief output for link and addresses X-Git-Tag: v4.2.0~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5d295bb8e1af491bc3de1d2506cbb2bd6bbd9da1;p=thirdparty%2Fiproute2.git add support for brief output for link and addresses This adds support for slightly less output than is normally provided by 'ip link show' and 'ip addr show'. This is a bit better when you have a host with lots of interfaces. Sample output: $ ip -br link show lo UNKNOWN 00:00:00:00:00:00 p2p1 UP 08:00:27:ee:0b:3b p7p1 UP 08:00:27:9d:62:9f p8p1 DOWN 08:00:27:dc:d8:ca p9p1 UP 08:00:27:76:d9:75 p7p1.100@p7p1 UP 08:00:27:9d:62:9f $ ip -br -4 addr show lo UNKNOWN 127.0.0.1/8 p2p1 UP 192.168.56.2/24 p7p1 UP 70.0.0.1/24 p8p1 DOWN 80.0.0.1/24 p9p1 UP 10.0.5.15/24 p7p1.100@p7p1 UP 200.0.0.1/24 $ ip -br -6 addr show lo UNKNOWN ::1/128 p2p1 UP fe80::a00:27ff:feee:b3b/64 p7p1 UP 7000::1/8 fe80::a00:27ff:fe9d:629f/64 p8p1 DOWN 8000::1/8 p9p1 UP fe80::a00:27ff:fe76:d975/64 p7p1.100@p7p1 UP fe80::a00:27ff:fe9d:629f/64 $ ip -br addr show p7p1 p7p1 UP 70.0.0.1/24 7000::1/8 fe80::a00:27ff:fe9d:629f/64 v2: Now with color support! v3: Better field width estimation (except netdev names to keep output at a decent width) and whitespace fixup. Signed-off-by: Andy Gospodarek --- diff --git a/include/utils.h b/include/utils.h index 0c57ccdc7..f77edeb0f 100644 --- a/include/utils.h +++ b/include/utils.h @@ -19,6 +19,7 @@ extern int show_details; extern int show_raw; extern int resolve_hosts; extern int oneline; +extern int brief; extern int timestamp; extern int timestamp_short; extern const char * _SL_; diff --git a/ip/ip.c b/ip/ip.c index e75447e1b..eea00b822 100644 --- a/ip/ip.c +++ b/ip/ip.c @@ -32,6 +32,7 @@ int show_stats; int show_details; int resolve_hosts; int oneline; +int brief; int timestamp; const char *_SL_; int force; @@ -55,7 +56,7 @@ static void usage(void) " -h[uman-readable] | -iec |\n" " -f[amily] { inet | inet6 | ipx | dnet | mpls | bridge | link } |\n" " -4 | -6 | -I | -D | -B | -0 |\n" -" -l[oops] { maximum-addr-flush-attempts } |\n" +" -l[oops] { maximum-addr-flush-attempts } | -br[ief] |\n" " -o[neline] | -t[imestamp] | -ts[hort] | -b[atch] [filename] |\n" " -rc[vbuf] [size] | -n[etns] name | -a[ll] | -c[olor]}\n"); exit(-1); @@ -250,6 +251,8 @@ int main(int argc, char **argv) if (argc <= 1) usage(); batch_file = argv[1]; + } else if (matches(opt, "-brief") == 0) { + ++brief; } else if (matches(opt, "-rcvbuf") == 0) { unsigned int size; diff --git a/ip/ip_common.h b/ip/ip_common.h index f120f5b97..f74face69 100644 --- a/ip/ip_common.h +++ b/ip/ip_common.h @@ -2,6 +2,9 @@ extern int get_operstate(const char *name); extern int print_linkinfo(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg); +extern int print_linkinfo_brief(const struct sockaddr_nl *who, + struct nlmsghdr *n, + void *arg); extern int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg); diff --git a/ip/ipaddress.c b/ip/ipaddress.c index 177b65a9b..5dad5d6f9 100644 --- a/ip/ipaddress.c +++ b/ip/ipaddress.c @@ -138,13 +138,22 @@ static void print_operstate(FILE *f, __u8 state) if (state >= sizeof(oper_states)/sizeof(oper_states[0])) fprintf(f, "state %#x ", state); else { - fprintf(f, "state "); - if (strcmp(oper_states[state], "UP") == 0) - color_fprintf(f, COLOR_OPERSTATE_UP, "%s ", oper_states[state]); - else if (strcmp(oper_states[state], "DOWN") == 0) - color_fprintf(f, COLOR_OPERSTATE_DOWN, "%s ", oper_states[state]); - else - fprintf(f, "%s ", oper_states[state]); + if (brief) { + if (strcmp(oper_states[state], "UP") == 0) + color_fprintf(f, COLOR_OPERSTATE_UP, "%-14s ", oper_states[state]); + else if (strcmp(oper_states[state], "DOWN") == 0) + color_fprintf(f, COLOR_OPERSTATE_DOWN, "%-14s ", oper_states[state]); + else + fprintf(f, "%-14s ", oper_states[state]); + } else { + fprintf(f, "state "); + if (strcmp(oper_states[state], "UP") == 0) + color_fprintf(f, COLOR_OPERSTATE_UP, "%s ", oper_states[state]); + else if (strcmp(oper_states[state], "DOWN") == 0) + color_fprintf(f, COLOR_OPERSTATE_DOWN, "%s ", oper_states[state]); + else + fprintf(f, "%s ", oper_states[state]); + } } } @@ -590,6 +599,88 @@ static void print_link_stats(FILE *fp, struct nlmsghdr *n) fprintf(fp, "%s", _SL_); } +int print_linkinfo_brief(const struct sockaddr_nl *who, + struct nlmsghdr *n, void *arg) +{ + FILE *fp = (FILE*)arg; + struct ifinfomsg *ifi = NLMSG_DATA(n); + struct rtattr * tb[IFLA_MAX+1]; + int len = n->nlmsg_len; + char *name; + char buf[32] = { 0, }; + unsigned m_flag = 0; + + if (n->nlmsg_type != RTM_NEWLINK && n->nlmsg_type != RTM_DELLINK) + return -1; + + len -= NLMSG_LENGTH(sizeof(*ifi)); + if (len < 0) + return -1; + + if (filter.ifindex && ifi->ifi_index != filter.ifindex) + return -1; + if (filter.up && !(ifi->ifi_flags&IFF_UP)) + return -1; + + parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len); + if (tb[IFLA_IFNAME] == NULL) { + fprintf(stderr, "BUG: device with ifindex %d has nil ifname\n", ifi->ifi_index); + } + if (filter.label && + (!filter.family || filter.family == AF_PACKET) && + fnmatch(filter.label, RTA_DATA(tb[IFLA_IFNAME]), 0)) + return -1; + + if (tb[IFLA_GROUP]) { + int group = *(int*)RTA_DATA(tb[IFLA_GROUP]); + if (filter.group != -1 && group != filter.group) + return -1; + } + + if (n->nlmsg_type == RTM_DELLINK) + fprintf(fp, "Deleted "); + + name = (char *)(tb[IFLA_IFNAME] ? rta_getattr_str(tb[IFLA_IFNAME]) : ""); + + if (tb[IFLA_LINK]) { + SPRINT_BUF(b1); + int iflink = *(int*)RTA_DATA(tb[IFLA_LINK]); + if (iflink == 0) + snprintf(buf, sizeof(buf), "%s@NONE", name); + else { + snprintf(buf, sizeof(buf), + "%s@%s", name, ll_idx_n2a(iflink, b1)); + m_flag = ll_index_to_flags(iflink); + m_flag = !(m_flag & IFF_UP); + } + } else + snprintf(buf, sizeof(buf), "%s", name); + + fprintf(fp, "%-16s ", buf); + + if (tb[IFLA_OPERSTATE]) + print_operstate(fp, rta_getattr_u8(tb[IFLA_OPERSTATE])); + + if (filter.family == AF_PACKET) { + SPRINT_BUF(b1); + if (tb[IFLA_ADDRESS]) { + color_fprintf(fp, COLOR_MAC, "%s ", + ll_addr_n2a(RTA_DATA(tb[IFLA_ADDRESS]), + RTA_PAYLOAD(tb[IFLA_ADDRESS]), + ifi->ifi_type, + b1, sizeof(b1))); + } + } + + if (filter.family == AF_PACKET) + print_link_flags(fp, ifi->ifi_flags, m_flag); + + if (filter.family == AF_PACKET) + fprintf(fp, "\n"); + fflush(fp); + return 0; +} + int print_linkinfo(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { @@ -887,18 +978,20 @@ int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n, if (n->nlmsg_type == RTM_DELADDR) fprintf(fp, "Deleted "); - if (filter.oneline || filter.flushb) - fprintf(fp, "%u: %s", ifa->ifa_index, ll_index_to_name(ifa->ifa_index)); - if (ifa->ifa_family == AF_INET) - fprintf(fp, " inet "); - else if (ifa->ifa_family == AF_INET6) - fprintf(fp, " inet6 "); - else if (ifa->ifa_family == AF_DECnet) - fprintf(fp, " dnet "); - else if (ifa->ifa_family == AF_IPX) - fprintf(fp, " ipx "); - else - fprintf(fp, " family %d ", ifa->ifa_family); + if (!brief) { + if (filter.oneline || filter.flushb) + fprintf(fp, "%u: %s", ifa->ifa_index, ll_index_to_name(ifa->ifa_index)); + if (ifa->ifa_family == AF_INET) + fprintf(fp, " inet "); + else if (ifa->ifa_family == AF_INET6) + fprintf(fp, " inet6 "); + else if (ifa->ifa_family == AF_DECnet) + fprintf(fp, " dnet "); + else if (ifa->ifa_family == AF_IPX) + fprintf(fp, " ipx "); + else + fprintf(fp, " family %d ", ifa->ifa_family); + } if (rta_tb[IFA_LOCAL]) { if (ifa->ifa_family == AF_INET) @@ -931,6 +1024,9 @@ int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n, } } + if (brief) + goto brief_exit; + if (rta_tb[IFA_BROADCAST]) { fprintf(fp, "brd %s ", format_host(ifa->ifa_family, @@ -1013,6 +1109,7 @@ int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n, } } fprintf(fp, "\n"); +brief_exit: fflush(fp); return 0; } @@ -1073,6 +1170,10 @@ static int print_selected_addrinfo(struct ifinfomsg *ifi, print_addrinfo(NULL, n, fp); } + if (brief) { + fprintf(fp, "\n"); + fflush(fp); + } return 0; } @@ -1534,9 +1635,16 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action) for (l = linfo.head; l; l = l->next) { int res = 0; + struct ifinfomsg *ifi = NLMSG_DATA(&l->h); - if (no_link || (res = print_linkinfo(NULL, &l->h, stdout)) >= 0) { - struct ifinfomsg *ifi = NLMSG_DATA(&l->h); + if (brief) { + if (print_linkinfo_brief(NULL, &l->h, stdout) == 0) + if (filter.family != AF_PACKET) + print_selected_addrinfo(ifi, + ainfo.head, + stdout); + } else if (no_link || + (res = print_linkinfo(NULL, &l->h, stdout)) >= 0) { if (filter.family != AF_PACKET) print_selected_addrinfo(ifi, ainfo.head, stdout); diff --git a/ip/iplink.c b/ip/iplink.c index cdb3f73e4..5361c2f9f 100644 --- a/ip/iplink.c +++ b/ip/iplink.c @@ -831,7 +831,10 @@ int iplink_get(unsigned int flags, char *name, __u32 filt_mask) if (rtnl_talk(&rth, &req.n, &answer.n, sizeof(answer)) < 0) return -2; - print_linkinfo(NULL, &answer.n, stdout); + if (brief) + print_linkinfo_brief(NULL, &answer.n, stdout); + else + print_linkinfo(NULL, &answer.n, stdout); return 0; } diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in index 2283b710d..81c48920b 100644 --- a/man/man8/ip-link.8.in +++ b/man/man8/ip-link.8.in @@ -21,7 +21,8 @@ ip-link \- network device configuration \fB\-r\fR[\fIesolve\fR] | \fB\-f\fR[\fIamily\fR] { .BR inet " | " inet6 " | " ipx " | " dnet " | " link " } | " -\fB\-o\fR[\fIneline\fR] } +\fB\-o\fR[\fIneline\fR] | +\fB\-br\fR[\fIief\fR] } .ti -8 .BI "ip link add"