Hello again,

Things turned out to be not so hard. Please take a look at the attached patch.
I'm only not sure if RTA_PRIORITY is enough. Because the print_route
function prints "metric" also for some situations with RTA_METRICS,
which I haven't managed to understand.

On Fri, Nov 17, 2017 at 1:40 AM, Alexander Zubkov <zubkov...@gmail.com> wrote:
> Hello all,
>
> Currently routes in the Linux routing table have these "key" fields:
> prefix, tos, table, metric (as I know). I.e. we cannot have two
> different routes with the same set of this fields. And "ip route list"
> command can be provided with all but one of those fields. We cannot
> pass metric to it and this is inconvenient. I ask if this behaviour
> can be changed by someone. We can even use "secondary" fields, for
> example type, dev or via, but not metric unfortunately.
> Sorry, I can not provide patches. I have written code long time ago. I
> tried to trace it, but as I see it parses arguments and fills some
> structures. And then my tries to understand failed.
> I opened the bug: https://bugzilla.kernel.org/show_bug.cgi?id=197897,
> but I was pointed out that this mailing list is a better place for
> this question.
>
> --
> Alexander Zubkov
--- a/ip/iproute.c
+++ b/ip/iproute.c
@@ -126,6 +126,8 @@ static struct
 	int oif, oifmask;
 	int mark, markmask;
 	int realm, realmmask;
+	int have_metric;
+	__u32 metric;
 	inet_prefix rprefsrc;
 	inet_prefix rvia;
 	inet_prefix rdst;
@@ -288,6 +290,14 @@ static int filter_nlmsg(struct nlmsghdr *n, struct rtattr **tb, int host_len)
 		if ((mark ^ filter.mark) & filter.markmask)
 			return 0;
 	}
+	if (filter.have_metric) {
+		__u32 metric = 0;
+
+		if (tb[RTA_PRIORITY])
+			metric = rta_getattr_u32(tb[RTA_PRIORITY]);
+		if (filter.metric != metric)
+			return 0;
+	}
 	if (filter.flushb &&
 	    r->rtm_family == AF_INET6 &&
 	    r->rtm_dst_len == 0 &&
@@ -1518,6 +1528,16 @@ static int iproute_list_flush_or_save(int argc, char **argv, int action)
 			if (get_unsigned(&mark, *argv, 0))
 				invarg("invalid mark value", *argv);
 			filter.markmask = -1;
+		} else if (matches(*argv, "metric") == 0 ||
+		           matches(*argv, "priority") == 0 ||
+		           strcmp(*argv, "preference") == 0) {
+			__u32 metric;
+
+			NEXT_ARG();
+			if (get_u32(&metric, *argv, 0))
+				invarg("\"metric\" value is invalid\n", *argv);
+			filter.metric = metric;
+			filter.have_metric = 1;
 		} else if (strcmp(*argv, "via") == 0) {
 			int family;
 

Reply via email to