diff mbox series

[iproute] route: filter by interface on multipath routes

Message ID 20240705004440.186345-1-stephen@networkplumber.org (mailing list archive)
State Accepted
Commit 0ea0699ea01df81750becf742083933a23a95d94
Headers show
Series [iproute] route: filter by interface on multipath routes | expand

Checks

Context Check Description
netdev/tree_selection success Not a local patch

Commit Message

Stephen Hemminger July 5, 2024, 12:44 a.m. UTC
The ip route command would silently hide multipath routes when filter
by interface. The problem was it was not looking for interface when
filter multipath routes.

Example:
	ip link add name dummy1 up type dummy
	ip link add name dummy2 up type dummy
	ip address add 192.0.2.1/28 dev dummy1
	ip address add 192.0.2.17/28 dev dummy2
	ip route add 198.51.100.0/24 \
		nexthop via 192.0.2.2 dev dummy1 \
		nexthop via 192.0.2.18 dev dummy2

Before:
ip route show dev dummy1
192.0.2.0/28 proto kernel scope link src 192.0.2.1

After:
ip route show dev dummy1
192.0.2.0/28 proto kernel scope link src 192.0.2.1
198.51.100.0/24
	nexthop via 192.0.2.2 dev dummy1 weight 1
	nexthop via 192.0.2.18 dev dummy2 weight 1

Reported-by: "Muggeridge, Matt" <matt.muggeridge2@hpe.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 ip/iproute.c | 31 ++++++++++++++++++++++++++-----
 1 file changed, 26 insertions(+), 5 deletions(-)

Comments

patchwork-bot+netdevbpf@kernel.org July 5, 2024, 4:50 p.m. UTC | #1
Hello:

This patch was applied to iproute2/iproute2.git (main)
by Stephen Hemminger <stephen@networkplumber.org>:

On Thu,  4 Jul 2024 17:44:19 -0700 you wrote:
> The ip route command would silently hide multipath routes when filter
> by interface. The problem was it was not looking for interface when
> filter multipath routes.
> 
> Example:
> 	ip link add name dummy1 up type dummy
> 	ip link add name dummy2 up type dummy
> 	ip address add 192.0.2.1/28 dev dummy1
> 	ip address add 192.0.2.17/28 dev dummy2
> 	ip route add 198.51.100.0/24 \
> 		nexthop via 192.0.2.2 dev dummy1 \
> 		nexthop via 192.0.2.18 dev dummy2
> 
> [...]

Here is the summary with links:
  - [iproute] route: filter by interface on multipath routes
    https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/commit/?id=0ea0699ea01d

You are awesome, thank you!
diff mbox series

Patch

diff --git a/ip/iproute.c b/ip/iproute.c
index b5304611..44666240 100644
--- a/ip/iproute.c
+++ b/ip/iproute.c
@@ -154,6 +154,24 @@  static int flush_update(void)
 	return 0;
 }
 
+static bool filter_multipath(const struct rtattr *rta)
+{
+	const struct rtnexthop *nh = RTA_DATA(rta);
+	int len = RTA_PAYLOAD(rta);
+
+	while (len >= sizeof(*nh)) {
+		if (nh->rtnh_len > len)
+			break;
+
+		if (!((nh->rtnh_ifindex ^ filter.oif) & filter.oifmask))
+			return true;
+
+		len -= NLMSG_ALIGN(nh->rtnh_len);
+		nh = RTNH_NEXT(nh);
+	}
+	return false;
+}
+
 static int filter_nlmsg(struct nlmsghdr *n, struct rtattr **tb, int host_len)
 {
 	struct rtmsg *r = NLMSG_DATA(n);
@@ -310,12 +328,15 @@  static int filter_nlmsg(struct nlmsghdr *n, struct rtattr **tb, int host_len)
 			return 0;
 	}
 	if (filter.oifmask) {
-		int oif = 0;
+		if (tb[RTA_OIF]) {
+			int oif = rta_getattr_u32(tb[RTA_OIF]);
 
-		if (tb[RTA_OIF])
-			oif = rta_getattr_u32(tb[RTA_OIF]);
-		if ((oif^filter.oif)&filter.oifmask)
-			return 0;
+			if ((oif ^ filter.oif) & filter.oifmask)
+				return 0;
+		} else if (tb[RTA_MULTIPATH]) {
+			if (!filter_multipath(tb[RTA_MULTIPATH]))
+				return 0;
+		}
 	}
 	if (filter.markmask) {
 		int mark = 0;