[PATCH iproute2-next 0/3] ip multicast command JSON support

STALE3151d

11 messages, 3 authors, 2018-03-08 · open the first message on its own page

[PATCH iproute2-next 0/3] ip multicast command JSON support

From: Stephen Hemminger <stephen@networkplumber.org>
Date: 2018-03-07 01:03:58

From: Stephen Hemminger <redacted>

Update maddr and mroute to support JSON.
Fix bug in ipmroute that causes it print error on every unicast route.

Stephen Hemminger (3):
  ipmaddr: json and color support
  ipmroute: don't complain about unicast routes
  ipmroute: convert to output JSON

 ip/ipmaddr.c  |  69 ++++++++++++++++++++------------
 ip/ipmroute.c | 124 +++++++++++++++++++++++++++++++++++++---------------------
 2 files changed, 123 insertions(+), 70 deletions(-)

-- 
2.16.1

[PATCH iproute2-next 1/3] ipmaddr: json and color support

From: Stephen Hemminger <stephen@networkplumber.org>
Date: 2018-03-07 01:03:59

From: Stephen Hemminger <redacted>

Support printing mulitcast addresses in json and color mode.
Output format is unchanged for normal use.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 ip/ipmaddr.c | 69 +++++++++++++++++++++++++++++++++++++-----------------------
 1 file changed, 43 insertions(+), 26 deletions(-)
diff --git a/ip/ipmaddr.c b/ip/ipmaddr.c
index d7bf1f99f67e..a48499029e17 100644
--- a/ip/ipmaddr.c
+++ b/ip/ipmaddr.c
@@ -28,6 +28,7 @@
 #include "rt_names.h"
 #include "utils.h"
 #include "ip_common.h"
+#include "json_print.h"
 
 static struct {
 	char *dev;
@@ -193,50 +194,66 @@ static void read_igmp6(struct ma_info **result_p)
 
 static void print_maddr(FILE *fp, struct ma_info *list)
 {
-	fprintf(fp, "\t");
+	print_string(PRINT_FP, NULL, "\t", NULL);
 
+	open_json_object(NULL);
 	if (list->addr.family == AF_PACKET) {
 		SPRINT_BUF(b1);
-		fprintf(fp, "link  %s", ll_addr_n2a((unsigned char *)list->addr.data,
-						    list->addr.bytelen, 0,
-						    b1, sizeof(b1)));
+
+		print_string(PRINT_FP, NULL, "link  ", NULL);
+		print_color_string(PRINT_ANY, COLOR_MAC, "link", "%s",
+				   ll_addr_n2a((void *)list->addr.data, list->addr.bytelen,
+					       0, b1, sizeof(b1)));
 	} else {
-		switch (list->addr.family) {
-		case AF_INET:
-			fprintf(fp, "inet  ");
-			break;
-		case AF_INET6:
-			fprintf(fp, "inet6 ");
-			break;
-		default:
-			fprintf(fp, "family %d ", list->addr.family);
-			break;
-		}
-		fprintf(fp, "%s",
-			format_host(list->addr.family,
-				    -1, list->addr.data));
+		print_string(PRINT_ANY, "family", "%-5s ",
+			     family_name(list->addr.family));
+		print_color_string(PRINT_ANY, ifa_family_color(list->addr.family),
+				   "address", "%s",
+				   format_host(list->addr.family,
+					       -1, list->addr.data));
 	}
+
 	if (list->users != 1)
-		fprintf(fp, " users %d", list->users);
+		print_uint(PRINT_ANY, "users", " users %u", list->users);
+
 	if (list->features)
-		fprintf(fp, " %s", list->features);
-	fprintf(fp, "\n");
+		print_string(PRINT_ANY, "features", " %s", list->features);
+
+	print_string(PRINT_FP, NULL, "\n", NULL);
+	close_json_object();
 }
 
 static void print_mlist(FILE *fp, struct ma_info *list)
 {
 	int cur_index = 0;
 
+	new_json_obj(json);
 	for (; list; list = list->next) {
-		if (oneline) {
-			cur_index = list->index;
-			fprintf(fp, "%d:\t%s%s", cur_index, list->name, _SL_);
-		} else if (cur_index != list->index) {
+
+		if (list->index != cur_index || oneline) {
+			if (cur_index) {
+				close_json_array(PRINT_JSON, NULL);
+				close_json_object();
+			}
+			open_json_object(NULL);
+
+			print_uint(PRINT_ANY, "ifindex", "%d:", list->index);
+			print_color_string(PRINT_ANY, COLOR_IFNAME,
+					   "ifname", "\t%s", list->name);
+			print_string(PRINT_FP, NULL, "%s", _SL_);
 			cur_index = list->index;
-			fprintf(fp, "%d:\t%s\n", cur_index, list->name);
+
+			open_json_array(PRINT_JSON, "maddr");
 		}
+
 		print_maddr(fp, list);
 	}
+	if (cur_index) {
+		close_json_array(PRINT_JSON, NULL);
+		close_json_object();
+	}
+
+	delete_json_obj();
 }
 
 static int multiaddr_list(int argc, char **argv)
-- 
2.16.1

[PATCH iproute2-next 2/3] ipmroute: don't complain about unicast routes

From: Stephen Hemminger <stephen@networkplumber.org>
Date: 2018-03-07 01:04:01

From: Stephen Hemminger <redacted>

Every non-multicast route prints an error message.
Kernel doesn't filter out unicast routes, it is up to filter function
to do this.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 ip/ipmroute.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/ip/ipmroute.c b/ip/ipmroute.c
index aa5029b44f41..03ca0575e571 100644
--- a/ip/ipmroute.c
+++ b/ip/ipmroute.c
@@ -75,15 +75,14 @@ int print_mroute(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
 		fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
 		return -1;
 	}
-	if (r->rtm_type != RTN_MULTICAST) {
-		fprintf(stderr, "Not a multicast route (type: %s)\n",
-			rtnl_rtntype_n2a(r->rtm_type, b1, sizeof(b1)));
+
+	if (r->rtm_type != RTN_MULTICAST)
 		return 0;
-	}
 
 	parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len);
 	table = rtm_get_table(r, tb);
 
+
 	if (filter.tb > 0 && filter.tb != table)
 		return 0;
 
-- 
2.16.1

[PATCH iproute2-next 3/3] ipmroute: convert to output JSON

From: Stephen Hemminger <stephen@networkplumber.org>
Date: 2018-03-07 01:04:02

From: Stephen Hemminger <redacted>

Should be no change for non-json case except putting color
on address if desired.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 ip/ipmroute.c | 117 ++++++++++++++++++++++++++++++++++++++--------------------
 1 file changed, 77 insertions(+), 40 deletions(-)
diff --git a/ip/ipmroute.c b/ip/ipmroute.c
index 03ca0575e571..8258a4ed0a0b 100644
--- a/ip/ipmroute.c
+++ b/ip/ipmroute.c
@@ -29,6 +29,7 @@
 #include <rt_names.h>
 #include "utils.h"
 #include "ip_common.h"
+#include "json_print.h"
 
 static void usage(void) __attribute__((noreturn));
 
@@ -53,13 +54,12 @@ struct rtfilter {
 
 int print_mroute(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
 {
-	FILE *fp = (FILE *)arg;
 	struct rtmsg *r = NLMSG_DATA(n);
 	int len = n->nlmsg_len;
 	struct rtattr *tb[RTA_MAX+1];
-	char obuf[256];
-
+	const char *src, *dst;
 	SPRINT_BUF(b1);
+	SPRINT_BUF(b2);
 	__u32 table;
 	int iif = 0;
 	int family;
@@ -102,30 +102,44 @@ int print_mroute(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
 
 	family = get_real_family(r->rtm_type, r->rtm_family);
 
+	open_json_object(NULL);
 	if (n->nlmsg_type == RTM_DELROUTE)
-		fprintf(fp, "Deleted ");
+		print_bool(PRINT_ANY, "deleted", "Deleted ", true);
 
 	if (tb[RTA_SRC])
-		len = snprintf(obuf, sizeof(obuf),
-			       "(%s, ", rt_addr_n2a_rta(family, tb[RTA_SRC]));
+		src = rt_addr_n2a_r(family, RTA_PAYLOAD(tb[RTA_SRC]),
+				    RTA_DATA(tb[RTA_SRC]), b1, sizeof(b1));
 	else
-		len = sprintf(obuf, "(unknown, ");
+		src = "unknown";
+
 	if (tb[RTA_DST])
-		snprintf(obuf + len, sizeof(obuf) - len,
-			 "%s)", rt_addr_n2a_rta(family, tb[RTA_DST]));
+		dst = rt_addr_n2a_r(family, RTA_PAYLOAD(tb[RTA_DST]),
+				    RTA_DATA(tb[RTA_DST]), b2, sizeof(b2));
 	else
-		snprintf(obuf + len, sizeof(obuf) - len, "unknown) ");
+		dst = "unknown";
+
+	if (is_json_context()) {
+		print_string(PRINT_JSON, "src", NULL, src);
+		print_string(PRINT_JSON, "dst", NULL, dst);
+	} else {
+		char obuf[256];
+
+		snprintf(obuf, sizeof(obuf), "(%s,%s)", src, dst);
+		print_string(PRINT_FP, NULL,
+			     "%-32s Iif: ", obuf);
+	}
 
-	fprintf(fp, "%-32s Iif: ", obuf);
 	if (iif)
-		fprintf(fp, "%-10s ", ll_index_to_name(iif));
+		print_color_string(PRINT_ANY, COLOR_IFNAME,
+				   "iif", "%-10s ", ll_index_to_name(iif));
 	else
-		fprintf(fp, "unresolved ");
+		print_string(PRINT_ANY,"iif", "%s ", "unresolved");
 
 	if (tb[RTA_MULTIPATH]) {
 		struct rtnexthop *nh = RTA_DATA(tb[RTA_MULTIPATH]);
 		int first = 1;
 
+		open_json_array(PRINT_JSON, "multipath");
 		len = RTA_PAYLOAD(tb[RTA_MULTIPATH]);
 
 		for (;;) {
@@ -134,47 +148,67 @@ int print_mroute(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
 			if (nh->rtnh_len > len)
 				break;
 
+			open_json_object(NULL);
 			if (first) {
-				fprintf(fp, "Oifs: ");
+				print_string(PRINT_FP, NULL, "Oifs: ", NULL);
 				first = 0;
 			}
-			fprintf(fp, "%s", ll_index_to_name(nh->rtnh_ifindex));
+
+			print_color_string(PRINT_ANY, COLOR_IFNAME,
+					   "oif", "%s", ll_index_to_name(nh->rtnh_ifindex));
+
 			if (nh->rtnh_hops > 1)
-				fprintf(fp, "(ttl %d) ", nh->rtnh_hops);
+				print_uint(PRINT_ANY,
+					   "ttl", "(ttl %u) ", nh->rtnh_hops);
 			else
-				fprintf(fp, " ");
+				print_string(PRINT_FP, NULL, " ", NULL);
+
+			close_json_object();
 			len -= NLMSG_ALIGN(nh->rtnh_len);
 			nh = RTNH_NEXT(nh);
 		}
+		close_json_array(PRINT_JSON, NULL);
 	}
-	fprintf(fp, " State: %s",
-		r->rtm_flags & RTNH_F_UNRESOLVED ? "unresolved" : "resolved");
+
+	print_string(PRINT_ANY, "state", " State: %s",
+		     (r->rtm_flags & RTNH_F_UNRESOLVED) ? "unresolved" : "resolved");
+
 	if (r->rtm_flags & RTNH_F_OFFLOAD)
-		fprintf(fp, " offload");
-	if (show_stats && tb[RTA_MFC_STATS]) {
-		struct rta_mfc_stats *mfcs = RTA_DATA(tb[RTA_MFC_STATS]);
-
-		fprintf(fp, "%s  %"PRIu64" packets, %"PRIu64" bytes", _SL_,
-			(uint64_t)mfcs->mfcs_packets,
-			(uint64_t)mfcs->mfcs_bytes);
-		if (mfcs->mfcs_wrong_if)
-			fprintf(fp, ", %"PRIu64" arrived on wrong iif.",
-				(uint64_t)mfcs->mfcs_wrong_if);
-	}
-	if (show_stats && tb[RTA_EXPIRES]) {
-		struct timeval tv;
+		print_null(PRINT_ANY, "offload", " offload", NULL);
+
+	if (show_stats) {
+		if ( tb[RTA_MFC_STATS]) {
+			struct rta_mfc_stats *mfcs = RTA_DATA(tb[RTA_MFC_STATS]);
 
-		__jiffies_to_tv(&tv, rta_getattr_u64(tb[RTA_EXPIRES]));
-		fprintf(fp, ", Age %4i.%.2i", (int)tv.tv_sec,
-			(int)tv.tv_usec/10000);
+			print_string(PRINT_FP, NULL, "%s", _SL_);
+			print_uint(PRINT_ANY, "packets", "  %"PRIu64" packets,",
+				   mfcs->mfcs_packets);
+			print_uint(PRINT_ANY, "bytes", " %"PRIu64" bytes", mfcs->mfcs_bytes);
+
+			if (mfcs->mfcs_wrong_if)
+				print_uint(PRINT_ANY, "wrong_if",
+					   ", %"PRIu64" arrived on wrong iif.",
+					   mfcs->mfcs_wrong_if);
+		}
+
+		if (tb[RTA_EXPIRES]) {
+			struct timeval tv;
+			double age;
+
+			__jiffies_to_tv(&tv, rta_getattr_u64(tb[RTA_EXPIRES]));
+			age = tv.tv_sec;
+			age += tv.tv_usec / 1000000.;
+			print_float(PRINT_ANY, "expires",
+				    ", Age %.2f", age);
+		}
 	}
 
 	if (table && (table != RT_TABLE_MAIN || show_details > 0) && !filter.tb)
-		fprintf(fp, " Table: %s",
-			rtnl_rttable_n2a(table, b1, sizeof(b1)));
+		print_string(PRINT_ANY, "table", " Table: %s",
+			     rtnl_rttable_n2a(table, b1, sizeof(b1)));
 
-	fprintf(fp, "\n");
-	fflush(fp);
+	print_string(PRINT_FP, NULL, "\n", NULL);
+	close_json_object();
 	return 0;
 }
 
@@ -255,12 +289,15 @@ static int mroute_list(int argc, char **argv)
 		return 1;
 	}
 
+	new_json_obj(json);
 	if (rtnl_dump_filter(&rth, print_mroute, stdout) < 0) {
+		delete_json_obj();
 		fprintf(stderr, "Dump terminated\n");
 		exit(1);
 	}
+	delete_json_obj();
 
-	exit(0);
+	return 0;
 }
 
 int do_multiroute(int argc, char **argv)
-- 
2.16.1

Re: [PATCH iproute2-next 2/3] ipmroute: don't complain about unicast routes

From: Sergei Shtylyov <hidden>
Date: 2018-03-07 08:43:36

Hello!

On 3/7/2018 4:03 AM, Stephen Hemminger wrote:
quoted hunk
From: Stephen Hemminger <redacted>

Every non-multicast route prints an error message.
Kernel doesn't filter out unicast routes, it is up to filter function
to do this.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
  ip/ipmroute.c | 7 +++----
  1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/ip/ipmroute.c b/ip/ipmroute.c
index aa5029b44f41..03ca0575e571 100644
--- a/ip/ipmroute.c
+++ b/ip/ipmroute.c
@@ -75,15 +75,14 @@ int print_mroute(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
  		fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
  		return -1;
  	}
-	if (r->rtm_type != RTN_MULTICAST) {
-		fprintf(stderr, "Not a multicast route (type: %s)\n",
-			rtnl_rtntype_n2a(r->rtm_type, b1, sizeof(b1)));
+
+	if (r->rtm_type != RTN_MULTICAST)
  		return 0;
-	}
  
  	parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len);
  	table = rtm_get_table(r, tb);
  
+
   Why?
  	if (filter.tb > 0 && filter.tb != table)
  		return 0;
  
MBR, Sergei

Re: [PATCH iproute2-next 2/3] ipmroute: don't complain about unicast routes

From: Stephen Hemminger <stephen@networkplumber.org>
Date: 2018-03-07 15:55:00

On Wed, 7 Mar 2018 11:43:33 +0300
Sergei Shtylyov [off-list ref] wrote:
Hello!

On 3/7/2018 4:03 AM, Stephen Hemminger wrote:
quoted
From: Stephen Hemminger <redacted>

Every non-multicast route prints an error message.
Kernel doesn't filter out unicast routes, it is up to filter function
to do this.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
  ip/ipmroute.c | 7 +++----
  1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/ip/ipmroute.c b/ip/ipmroute.c
index aa5029b44f41..03ca0575e571 100644
--- a/ip/ipmroute.c
+++ b/ip/ipmroute.c
@@ -75,15 +75,14 @@ int print_mroute(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
  		fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
  		return -1;
  	}
-	if (r->rtm_type != RTN_MULTICAST) {
-		fprintf(stderr, "Not a multicast route (type: %s)\n",
-			rtnl_rtntype_n2a(r->rtm_type, b1, sizeof(b1)));
+
+	if (r->rtm_type != RTN_MULTICAST)
  		return 0;
-	}
  
  	parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len);
  	table = rtm_get_table(r, tb);
  
+  
    Why?
quoted
  	if (filter.tb > 0 && filter.tb != table)
  		return 0;
    
MBR, Sergei
The kernel dumps all routes in response to the RTM_GETROUTE and therefore all routes show
up in print_mroute.  On my system (which has no mcast), I get this with standard 4.14
kernel and ip commands.

$ ip mroute
Not a multicast route (type: unicast)
Not a multicast route (type: unicast)
Not a multicast route (type: unicast)
Not a multicast route (type: unicast)
Not a multicast route (type: unicast)
Not a multicast route (type: broadcast)
Not a multicast route (type: local)
Not a multicast route (type: local)
Not a multicast route (type: broadcast)
Not a multicast route (type: broadcast)
Not a multicast route (type: local)

Re: [PATCH iproute2-next 2/3] ipmroute: don't complain about unicast routes

From: Sergei Shtylyov <hidden>
Date: 2018-03-07 15:57:04

On 03/07/2018 06:54 PM, Stephen Hemminger wrote:
quoted
Hello!

On 3/7/2018 4:03 AM, Stephen Hemminger wrote:
quoted
From: Stephen Hemminger <redacted>

Every non-multicast route prints an error message.
Kernel doesn't filter out unicast routes, it is up to filter function
to do this.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
  ip/ipmroute.c | 7 +++----
  1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/ip/ipmroute.c b/ip/ipmroute.c
index aa5029b44f41..03ca0575e571 100644
--- a/ip/ipmroute.c
+++ b/ip/ipmroute.c
@@ -75,15 +75,14 @@ int print_mroute(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
  		fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
  		return -1;
  	}
-	if (r->rtm_type != RTN_MULTICAST) {
-		fprintf(stderr, "Not a multicast route (type: %s)\n",
-			rtnl_rtntype_n2a(r->rtm_type, b1, sizeof(b1)));
+
+	if (r->rtm_type != RTN_MULTICAST)
  		return 0;
-	}
  
  	parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len);
  	table = rtm_get_table(r, tb);
  
+  
    Why?
quoted
  	if (filter.tb > 0 && filter.tb != table)
  		return 0;
    
MBR, Sergei
The kernel dumps all routes in response to the RTM_GETROUTE and therefore all routes show
up in print_mroute.  On my system (which has no mcast), I get this with standard 4.14
kernel and ip commands.
   I was merely asking about a double new line... :-)

MBR, Sergei

Re: [PATCH iproute2-next 2/3] ipmroute: don't complain about unicast routes

From: Stephen Hemminger <stephen@networkplumber.org>
Date: 2018-03-07 16:03:58

On Tue,  6 Mar 2018 17:03:54 -0800
Stephen Hemminger [off-list ref] wrote:
quoted hunk
From: Stephen Hemminger <redacted>

Every non-multicast route prints an error message.
Kernel doesn't filter out unicast routes, it is up to filter function
to do this.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 ip/ipmroute.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/ip/ipmroute.c b/ip/ipmroute.c
index aa5029b44f41..03ca0575e571 100644
--- a/ip/ipmroute.c
+++ b/ip/ipmroute.c
@@ -75,15 +75,14 @@ int print_mroute(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
 		fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
 		return -1;
 	}
-	if (r->rtm_type != RTN_MULTICAST) {
-		fprintf(stderr, "Not a multicast route (type: %s)\n",
-			rtnl_rtntype_n2a(r->rtm_type, b1, sizeof(b1)));
+
+	if (r->rtm_type != RTN_MULTICAST)
 		return 0;
-	}
 
 	parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len);
 	table = rtm_get_table(r, tb);
 
+
 	if (filter.tb > 0 && filter.tb != table)
 		return 0;
 
Actually, this is a recent kernel regression. Should be fixed there

Re: [PATCH iproute2-next 2/3] ipmroute: don't complain about unicast routes

From: David Ahern <hidden>
Date: 2018-03-07 16:47:21

On 3/7/18 9:03 AM, Stephen Hemminger wrote:
On Tue,  6 Mar 2018 17:03:54 -0800
Stephen Hemminger [off-list ref] wrote:
quoted
From: Stephen Hemminger <redacted>

Every non-multicast route prints an error message.
Kernel doesn't filter out unicast routes, it is up to filter function
to do this.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 ip/ipmroute.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/ip/ipmroute.c b/ip/ipmroute.c
index aa5029b44f41..03ca0575e571 100644
--- a/ip/ipmroute.c
+++ b/ip/ipmroute.c
@@ -75,15 +75,14 @@ int print_mroute(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
 		fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
 		return -1;
 	}
-	if (r->rtm_type != RTN_MULTICAST) {
-		fprintf(stderr, "Not a multicast route (type: %s)\n",
-			rtnl_rtntype_n2a(r->rtm_type, b1, sizeof(b1)));
+
+	if (r->rtm_type != RTN_MULTICAST)
 		return 0;
-	}
 
 	parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len);
 	table = rtm_get_table(r, tb);
 
+
 	if (filter.tb > 0 && filter.tb != table)
 		return 0;
 
Actually, this is a recent kernel regression. Should be fixed there
from Yuval's recent multicast convergence changes?

Re: [PATCH iproute2-next 2/3] ipmroute: don't complain about unicast routes

From: Stephen Hemminger <stephen@networkplumber.org>
Date: 2018-03-07 16:51:56

On Tue,  6 Mar 2018 17:03:54 -0800
Stephen Hemminger [off-list ref] wrote:
From: Stephen Hemminger <redacted>

Every non-multicast route prints an error message.
Kernel doesn't filter out unicast routes, it is up to filter function
to do this.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
I found the issue (in kernel) but not sure how to deal with it.
If kernel is built without multicast routing configured !CONFIG_IP_MROUTE
then the netlink request to return multicast routes will return all routes!

This is because in the kernel the way route dump works is that each
address family registers a callback to dump routes for a specific address
family.  If that address family is not registered then the fall back
is to address family PF_UNSPEC which has a handler that dumps all
routes.

Unfortunately, changing that behavior in kernel will certainly break
some user. And there is no direct way to determine multicast routing
is enabled in ip mroute code.

Maybe just change the message in ip mroute to do:
diff --git a/ip/ipmroute.c b/ip/ipmroute.c
index aa5029b44f41..31b9bfe95596 100644
--- a/ip/ipmroute.c
+++ b/ip/ipmroute.c
@@ -76,9 +76,8 @@ int print_mroute(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
                return -1;
        }
        if (r->rtm_type != RTN_MULTICAST) {
-               fprintf(stderr, "Not a multicast route (type: %s)\n",
-                       rtnl_rtntype_n2a(r->rtm_type, b1, sizeof(b1)));
-               return 0;
+               fprintf(stderr, "Multicast routing does not appear to be enabled\n");
+               return -1;
        }
 
        parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len);

Re: [PATCH iproute2-next 2/3] ipmroute: don't complain about unicast routes

From: David Ahern <hidden>
Date: 2018-03-08 17:12:41

On 3/7/18 9:51 AM, Stephen Hemminger wrote:
On Tue,  6 Mar 2018 17:03:54 -0800
Stephen Hemminger [off-list ref] wrote:
quoted
From: Stephen Hemminger <redacted>

Every non-multicast route prints an error message.
Kernel doesn't filter out unicast routes, it is up to filter function
to do this.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
I found the issue (in kernel) but not sure how to deal with it.
If kernel is built without multicast routing configured !CONFIG_IP_MROUTE
then the netlink request to return multicast routes will return all routes!

This is because in the kernel the way route dump works is that each
address family registers a callback to dump routes for a specific address
family.  If that address family is not registered then the fall back
is to address family PF_UNSPEC which has a handler that dumps all
routes.
If I ask the kernel for IP{6}MR address family and the kernel returns a
dump of all address families, that seems like a kernel bug to me. From a
short review it seems to be that way for a long time. I guess iproute2
has no choice but to adapt to the kernel design.

Are you going to resubmit this series?

quoted hunk
Unfortunately, changing that behavior in kernel will certainly break
some user. And there is no direct way to determine multicast routing
is enabled in ip mroute code.

Maybe just change the message in ip mroute to do:
diff --git a/ip/ipmroute.c b/ip/ipmroute.c
index aa5029b44f41..31b9bfe95596 100644
--- a/ip/ipmroute.c
+++ b/ip/ipmroute.c
@@ -76,9 +76,8 @@ int print_mroute(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
                return -1;
        }
        if (r->rtm_type != RTN_MULTICAST) {
-               fprintf(stderr, "Not a multicast route (type: %s)\n",
-                       rtnl_rtntype_n2a(r->rtm_type, b1, sizeof(b1)));
-               return 0;
+               fprintf(stderr, "Multicast routing does not appear to be enabled\n");
+               return -1;
        }
 
        parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len);
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help