diff mbox series

[iproute2] ip: Extend filter links/addresses

Message ID 20220107141736.11147-1-littlesmilingcloud@gmail.com (mailing list archive)
State Superseded
Delegated to: David Ahern
Headers show
Series [iproute2] ip: Extend filter links/addresses | expand

Checks

Context Check Description
netdev/tree_selection success Not a local patch

Commit Message

Anton Danilov Jan. 7, 2022, 2:17 p.m. UTC
This patch improves the filtering of links/addresses with the next features:
1. Additional types: ether, loopback, ppp
2. Exclude of specific interface types with 'exclude_type' option

Examples:
ip link show type ether
ip address show exclude_type ppp

Signed-off-by: Anton Danilov <littlesmilingcloud@gmail.com>
---
 ip/ip_common.h           |  1 +
 ip/ipaddress.c           | 39 ++++++++++++++++++++++++++++++++++++---
 ip/iplink.c              |  2 +-
 man/man8/ip-address.8.in | 16 +++++++++++++++-
 man/man8/ip-link.8.in    | 13 ++++++++++---
 5 files changed, 63 insertions(+), 8 deletions(-)

Comments

Stephen Hemminger Jan. 7, 2022, 4:51 p.m. UTC | #1
On Fri,  7 Jan 2022 17:17:38 +0300
Anton Danilov <littlesmilingcloud@gmail.com> wrote:

> +	if (filter.exclude_kind && match_link_kind(tb, filter.exclude_kind, 0) == -1 &&
> +	    !strcmp(filter.exclude_kind, "ether") && ifi->ifi_type == ARPHRD_ETHER)
> +		return -1;
> +	if (filter.exclude_kind && match_link_kind(tb, filter.exclude_kind, 0) == -1 &&
> +	    !strcmp(filter.exclude_kind, "loopback") && ifi->ifi_type == ARPHRD_LOOPBACK)
> +		return -1;
> +	if (filter.exclude_kind && match_link_kind(tb, filter.exclude_kind, 0) == -1 &&
> +	    !strcmp(filter.exclude_kind, "ppp") && ifi->ifi_type == ARPHRD_PPP)
> +		return -1;
> +	if (filter.exclude_kind && !match_link_kind(tb, filter.exclude_kind, 0))
> +		return -1;
> +
> +	if (filter.kind && match_link_kind(tb, filter.kind, 0) == -1 &&
> +	    !strcmp(filter.kind, "ether") && ifi->ifi_type == ARPHRD_ETHER)
> +		;
> +	else if (filter.kind && match_link_kind(tb, filter.kind, 0) == -1 &&
> +		 !strcmp(filter.kind, "loopback") && ifi->ifi_type == ARPHRD_LOOPBACK)
> +		;
> +	else if (filter.kind && match_link_kind(tb, filter.kind, 0) == -1 &&
> +		 !strcmp(filter.kind, "ppp") && ifi->ifi_type == ARPHRD_PPP)
> +		;
> +	else if (filter.kind && match_link_kind(tb, filter.kind, 0))
>  		return -1;

This is complex enough it is getting messy, it should be helper functions.
Also the code has duplications which indicates it should be split as well.
diff mbox series

Patch

diff --git a/ip/ip_common.h b/ip/ip_common.h
index ea04c8ff..38377be4 100644
--- a/ip/ip_common.h
+++ b/ip/ip_common.h
@@ -26,6 +26,7 @@  struct link_filter {
 	int master;
 	char *kind;
 	char *slave_kind;
+	char *exclude_kind;
 	int target_nsid;
 };
 
diff --git a/ip/ipaddress.c b/ip/ipaddress.c
index 4109d8bd..4db27c92 100644
--- a/ip/ipaddress.c
+++ b/ip/ipaddress.c
@@ -60,7 +60,7 @@  static void usage(void)
 		"       ip address {save|flush} [ dev IFNAME ] [ scope SCOPE-ID ]\n"
 		"                            [ to PREFIX ] [ FLAG-LIST ] [ label LABEL ] [up]\n"
 		"       ip address [ show [ dev IFNAME ] [ scope SCOPE-ID ] [ master DEVICE ]\n"
-		"                         [ nomaster ]\n"
+		"                         [ nomaster ] [ exclude_type TYPE ]\n"
 		"                         [ type TYPE ] [ to PREFIX ] [ FLAG-LIST ]\n"
 		"                         [ label LABEL ] [up] [ vrf NAME ] ]\n"
 		"       ip address {showdump|restore}\n"
@@ -1023,7 +1023,28 @@  int print_linkinfo(struct nlmsghdr *n, void *arg)
 	} else if (filter.master > 0)
 		return -1;
 
-	if (filter.kind && match_link_kind(tb, filter.kind, 0))
+	if (filter.exclude_kind && match_link_kind(tb, filter.exclude_kind, 0) == -1 &&
+	    !strcmp(filter.exclude_kind, "ether") && ifi->ifi_type == ARPHRD_ETHER)
+		return -1;
+	if (filter.exclude_kind && match_link_kind(tb, filter.exclude_kind, 0) == -1 &&
+	    !strcmp(filter.exclude_kind, "loopback") && ifi->ifi_type == ARPHRD_LOOPBACK)
+		return -1;
+	if (filter.exclude_kind && match_link_kind(tb, filter.exclude_kind, 0) == -1 &&
+	    !strcmp(filter.exclude_kind, "ppp") && ifi->ifi_type == ARPHRD_PPP)
+		return -1;
+	if (filter.exclude_kind && !match_link_kind(tb, filter.exclude_kind, 0))
+		return -1;
+
+	if (filter.kind && match_link_kind(tb, filter.kind, 0) == -1 &&
+	    !strcmp(filter.kind, "ether") && ifi->ifi_type == ARPHRD_ETHER)
+		;
+	else if (filter.kind && match_link_kind(tb, filter.kind, 0) == -1 &&
+		 !strcmp(filter.kind, "loopback") && ifi->ifi_type == ARPHRD_LOOPBACK)
+		;
+	else if (filter.kind && match_link_kind(tb, filter.kind, 0) == -1 &&
+		 !strcmp(filter.kind, "ppp") && ifi->ifi_type == ARPHRD_PPP)
+		;
+	else if (filter.kind && match_link_kind(tb, filter.kind, 0))
 		return -1;
 
 	if (filter.slave_kind && match_link_kind(tb, filter.slave_kind, 1))
@@ -1971,7 +1992,9 @@  static int iplink_filter_req(struct nlmsghdr *nlh, int reqlen)
 			return err;
 	}
 
-	if (filter.kind) {
+	if (filter.kind && !strcmp(filter.kind, "ether") &&
+	    !strcmp(filter.kind, "loopback") && !strcmp(filter.kind, "ppp")) {
+
 		struct rtattr *linkinfo;
 
 		linkinfo = addattr_nest(nlh, reqlen, IFLA_LINKINFO);
@@ -2137,6 +2160,16 @@  static int ipaddr_list_flush_or_save(int argc, char **argv, int action)
 			} else {
 				filter.kind = *argv;
 			}
+		} else if (strcmp(*argv, "exclude_type") == 0) {
+			int soff;
+
+			NEXT_ARG();
+			soff = strlen(*argv) - strlen("_slave");
+			if (!strcmp(*argv + soff, "_slave")) {
+				invarg("Not a valid type for exclude\n", *argv);
+			} else {
+				filter.exclude_kind = *argv;
+			}
 		} else {
 			if (strcmp(*argv, "dev") == 0)
 				NEXT_ARG();
diff --git a/ip/iplink.c b/ip/iplink.c
index a3ea775d..e0d49cab 100644
--- a/ip/iplink.c
+++ b/ip/iplink.c
@@ -120,7 +120,7 @@  void iplink_usage(void)
 		"		[ gso_max_size BYTES ] | [ gso_max_segs PACKETS ]\n"
 		"\n"
 		"	ip link show [ DEVICE | group GROUP ] [up] [master DEV] [vrf NAME] [type TYPE]\n"
-		"		[nomaster]\n"
+		"		[exclude_type TYPE] [nomaster]\n"
 		"\n"
 		"	ip link xstats type TYPE [ ARGS ]\n"
 		"\n"
diff --git a/man/man8/ip-address.8.in b/man/man8/ip-address.8.in
index 65f67e06..21de3d77 100644
--- a/man/man8/ip-address.8.in
+++ b/man/man8/ip-address.8.in
@@ -45,6 +45,8 @@  ip-address \- protocol address management
 .IR PATTERN " ] [ "
 .B  master
 .IR DEVICE " ] [ "
+.B  exclude_type
+.IR TYPE " ] [ "
 .B  type
 .IR TYPE " ] [ "
 .B vrf
@@ -138,7 +140,10 @@  ip-address \- protocol address management
 .BR ipvlan " |"
 .BR lowpan " |"
 .BR geneve " |"
-.BR macsec " ]"
+.BR macsec " |"
+.BR ether " |"
+.BR loopback " |"
+.BR ppp " ]"
 
 .SH "DESCRIPTION"
 The
@@ -337,6 +342,10 @@  interface list by comparing it with the relevant attribute in case the kernel
 didn't filter already. Therefore any string is accepted, but may lead to empty
 output.
 
+.TP
+.BI exclude_type " TYPE"
+don't list linterfaces of the given type.
+
 .TP
 .B up
 only list running interfaces.
@@ -441,6 +450,11 @@  Same as above except that only addresses assigned to active network interfaces
 are shown.
 .RE
 .PP
+ip address show type ether
+.RS 4
+Shows IPv4 and IPv6 addresses assigned to all physical ethernetl interfaces
+.RE
+.PP
 ip address show dev eth0
 .RS 4
 Shows IPv4 and IPv6 addresses assigned to network interface eth0.
diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in
index 1d67c9a4..dc8a1abf 100644
--- a/man/man8/ip-link.8.in
+++ b/man/man8/ip-link.8.in
@@ -176,10 +176,12 @@  ip-link \- network device configuration
 .BR up " ] ["
 .B master
 .IR DEVICE " ] ["
-.B type
-.IR ETYPE " ] ["
 .B vrf
 .IR NAME " ] ["
+.B type
+.IR ETYPE " ] ["
+.B exclude_type
+.IR ETYPE " ] ["
 .BR nomaster " ]"
 
 .ti -8
@@ -237,7 +239,7 @@  ip-link \- network device configuration
 
 .ti -8
 .IR ETYPE " := [ " TYPE " |"
-.BR bridge_slave " | " bond_slave " ]"
+.BR ether " | " loopback " | " ppp " | " bridge_slave " | " bond_slave " ]"
 
 .ti -8
 .IR VFVLAN-LIST " := [ "  VFVLAN-LIST " ] " VFVLAN
@@ -2630,6 +2632,11 @@  ip link show type vlan
 Shows the vlan devices.
 .RE
 .PP
+ip link show exclude_type ppp
+.RS 4
+List the network interfaces except PPP devices.
+.RE
+.PP
 ip link show master br0
 .RS 4
 Shows devices enslaved by br0