89 lines
2.4 KiB
Diff
89 lines
2.4 KiB
Diff
|
|
From 0ea0699ea01df81750becf742083933a23a95d94 Mon Sep 17 00:00:00 2001
|
||
|
|
From: Stephen Hemminger <stephen@networkplumber.org>
|
||
|
|
Date: Thu, 4 Jul 2024 17:26:41 -0700
|
||
|
|
Subject: [PATCH] route: filter by interface on multipath routes
|
||
|
|
|
||
|
|
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>
|
||
|
|
|
||
|
|
Conflict: NA
|
||
|
|
Reference: https://github.com/iproute2/iproute2/commit/0ea0699ea01df81750becf742083933a23a95d94.patch
|
||
|
|
---
|
||
|
|
ip/iproute.c | 31 ++++++++++++++++++++++++++-----
|
||
|
|
1 file changed, 26 insertions(+), 5 deletions(-)
|
||
|
|
|
||
|
|
diff --git a/ip/iproute.c b/ip/iproute.c
|
||
|
|
index b53046116..446662404 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;
|