* [PATCH iproute2-next] ipaddress: add support for showing IPv4 devconf attributes
@ 2026-06-12 23:17 Fernando Fernandez Mancera
2026-06-13 2:29 ` Stephen Hemminger
0 siblings, 1 reply; 3+ messages in thread
From: Fernando Fernandez Mancera @ 2026-06-12 23:17 UTC (permalink / raw)
To: netdev
Cc: dsahern, stephen, davem, edumazet, kuba, pabeni, horms,
Fernando Fernandez Mancera
This patch introduces support for showing IPv4 devconf attributes on
detailed output of an interface e.g "ip -d link show dev enp1s0".
Additionally, this refactors 'print_af_spec()' to sequentially process
both AF_INET and AF_INET6 attributes rather than returning early if
AF_INET6 is missing.
Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de>
---
Note/question: Is this too verbose? Maybe we should introduce a new
option to query this on itself? I do not think this will scale up when
adding IPv6.. although for IPv6 we can limit it to "-6" usage only.
---
ip/ipaddress.c | 241 +++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 201 insertions(+), 40 deletions(-)
diff --git a/ip/ipaddress.c b/ip/ipaddress.c
index 6017bc83..b066ec53 100644
--- a/ip/ipaddress.c
+++ b/ip/ipaddress.c
@@ -23,6 +23,7 @@
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <linux/if_infiniband.h>
+#include <linux/ip.h>
#include <linux/sockios.h>
#include <linux/net_namespace.h>
@@ -294,53 +295,213 @@ static void print_linktype(FILE *fp, struct rtattr *tb)
close_json_object();
}
+static void print_inet(FILE *fp, struct rtattr *inet_attr)
+{
+ struct rtattr *tb[IFLA_INET_MAX + 1];
+
+ parse_rtattr_nested(tb, IFLA_INET_MAX, inet_attr);
+
+ if (tb[IFLA_INET_CONF] && show_details) {
+ int *conf = RTA_DATA(tb[IFLA_INET_CONF]);
+ int max_elements = RTA_PAYLOAD(tb[IFLA_INET_CONF]) / sizeof(int);
+
+ if (max_elements >= IPV4_DEVCONF_FORWARDING)
+ print_string(PRINT_ANY, "forwarding", "forwarding %s ",
+ conf[IPV4_DEVCONF_FORWARDING - 1] ? "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_MC_FORWARDING)
+ print_string(PRINT_ANY, "mc_forwarding", "mc_forwarding %s ",
+ conf[IPV4_DEVCONF_MC_FORWARDING - 1] ? "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_PROXY_ARP)
+ print_string(PRINT_ANY, "proxy_arp", "proxy_arp %s ",
+ conf[IPV4_DEVCONF_PROXY_ARP - 1] ? "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_ACCEPT_REDIRECTS)
+ print_string(PRINT_ANY, "accept_redirects",
+ "accept_redirects %s ",
+ conf[IPV4_DEVCONF_ACCEPT_REDIRECTS - 1] ? "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_SECURE_REDIRECTS)
+ print_string(PRINT_ANY, "secure_redirects",
+ "secure_redirects %s ",
+ conf[IPV4_DEVCONF_SECURE_REDIRECTS - 1] ? "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_SEND_REDIRECTS)
+ print_string(PRINT_ANY, "send_redirects", "send_redirects %s ",
+ conf[IPV4_DEVCONF_SEND_REDIRECTS - 1] ? "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_SHARED_MEDIA)
+ print_string(PRINT_ANY, "shared_media", "shared_media %s ",
+ conf[IPV4_DEVCONF_SHARED_MEDIA - 1] ? "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_RP_FILTER)
+ print_int(PRINT_ANY, "rp_filter", "rp_filter %d ",
+ conf[IPV4_DEVCONF_RP_FILTER - 1]);
+
+ if (max_elements >= IPV4_DEVCONF_ACCEPT_SOURCE_ROUTE)
+ print_string(PRINT_ANY, "accept_source_route",
+ "accept_source_route %s ",
+ conf[IPV4_DEVCONF_ACCEPT_SOURCE_ROUTE - 1] ? "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_BOOTP_RELAY)
+ print_string(PRINT_ANY, "bootp_relay", "bootp_relay %s ",
+ conf[IPV4_DEVCONF_BOOTP_RELAY - 1] ? "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_LOG_MARTIANS)
+ print_string(PRINT_ANY, "log_martians", "log_martians %s ",
+ conf[IPV4_DEVCONF_LOG_MARTIANS - 1] ? "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_TAG)
+ print_int(PRINT_ANY, "tag", "tag %d ",
+ conf[IPV4_DEVCONF_TAG - 1]);
+
+ if (max_elements >= IPV4_DEVCONF_ARPFILTER)
+ print_string(PRINT_ANY, "arpfilter", "arpfilter %s ",
+ conf[IPV4_DEVCONF_ARPFILTER - 1] ? "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_MEDIUM_ID)
+ print_int(PRINT_ANY, "medium_id", "medium_id %d ",
+ conf[IPV4_DEVCONF_MEDIUM_ID - 1]);
+
+ if (max_elements >= IPV4_DEVCONF_NOXFRM)
+ print_string(PRINT_ANY, "noxfrm", "noxfrm %s ",
+ conf[IPV4_DEVCONF_NOXFRM - 1] ? "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_NOPOLICY)
+ print_string(PRINT_ANY, "nopolicy", "nopolicy %s ",
+ conf[IPV4_DEVCONF_NOPOLICY - 1] ? "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_FORCE_IGMP_VERSION)
+ print_int(PRINT_ANY, "force_igmp_version", "force_igmp_version %d ",
+ conf[IPV4_DEVCONF_FORCE_IGMP_VERSION - 1]);
+
+ if (max_elements >= IPV4_DEVCONF_ARP_ANNOUNCE)
+ print_int(PRINT_ANY, "arp_announce", "arp_announce %d ",
+ conf[IPV4_DEVCONF_ARP_ANNOUNCE - 1]);
+
+ if (max_elements >= IPV4_DEVCONF_ARP_IGNORE)
+ print_int(PRINT_ANY, "arp_ignore", "arp_ignore %d ",
+ conf[IPV4_DEVCONF_ARP_IGNORE - 1]);
+
+ if (max_elements >= IPV4_DEVCONF_PROMOTE_SECONDARIES)
+ print_string(PRINT_ANY, "promote_secondaries",
+ "promote_secondaries %s ",
+ conf[IPV4_DEVCONF_PROMOTE_SECONDARIES - 1] ? "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_ARP_ACCEPT)
+ print_int(PRINT_ANY, "arp_accept", "arp_accept %d ",
+ conf[IPV4_DEVCONF_ARP_ACCEPT - 1]);
+
+ if (max_elements >= IPV4_DEVCONF_ARP_NOTIFY)
+ print_string(PRINT_ANY, "arp_notify", "arp_notify %s ",
+ conf[IPV4_DEVCONF_ARP_NOTIFY - 1] ? "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_ACCEPT_LOCAL)
+ print_string(PRINT_ANY, "accept_local", "accept_local %s ",
+ conf[IPV4_DEVCONF_ACCEPT_LOCAL - 1] ? "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_SRC_VMARK)
+ print_string(PRINT_ANY, "src_vmark", " src_vmark %s",
+ conf[IPV4_DEVCONF_SRC_VMARK - 1] ? "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_PROXY_ARP_PVLAN)
+ print_string(PRINT_ANY, "proxy_arp_pvlan", "proxy_arp_pvlan %s ",
+ conf[IPV4_DEVCONF_PROXY_ARP_PVLAN - 1] ? "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_ROUTE_LOCALNET)
+ print_string(PRINT_ANY, "route_localnet", "route_localnet %s ",
+ conf[IPV4_DEVCONF_ROUTE_LOCALNET - 1] ? "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_BC_FORWARDING)
+ print_string(PRINT_ANY, "bc_forwarding", "bc_forwarding %s ",
+ conf[IPV4_DEVCONF_BC_FORWARDING - 1] ? "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_IGMPV2_UNSOLICITED_REPORT_INTERVAL)
+ print_int(PRINT_ANY, "igmpv2_unsolicited_report_interval",
+ "igmpv2_unsolicited_report_interval %d ",
+ conf[IPV4_DEVCONF_IGMPV2_UNSOLICITED_REPORT_INTERVAL - 1]);
+
+ if (max_elements >= IPV4_DEVCONF_IGMPV3_UNSOLICITED_REPORT_INTERVAL)
+ print_int(PRINT_ANY, "igmpv3_unsolicited_report_interval",
+ "igmpv3_unsolicited_report_interval %d ",
+ conf[IPV4_DEVCONF_IGMPV3_UNSOLICITED_REPORT_INTERVAL - 1]);
+
+ if (max_elements >= IPV4_DEVCONF_IGNORE_ROUTES_WITH_LINKDOWN)
+ print_string(PRINT_ANY, "ignore_routes_with_linkdown",
+ "ignore_routes_with_linkdown %s ",
+ conf[IPV4_DEVCONF_IGNORE_ROUTES_WITH_LINKDOWN - 1] ?
+ "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_DROP_UNICAST_IN_L2_MULTICAST)
+ print_string(PRINT_ANY, "drop_unicast_in_l2_multicast",
+ "drop_unicast_in_l2_multicast %s ",
+ conf[IPV4_DEVCONF_DROP_UNICAST_IN_L2_MULTICAST - 1] ?
+ "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_DROP_GRATUITOUS_ARP)
+ print_string(PRINT_ANY, "drop_gratuitous_arp",
+ "drop_gratuitous_arp %s ",
+ conf[IPV4_DEVCONF_DROP_GRATUITOUS_ARP - 1] ? "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_ARP_EVICT_NOCARRIER)
+ print_string(PRINT_ANY, "arp_evict_nocarrier",
+ "arp_evict_nocarrier %s ",
+ conf[IPV4_DEVCONF_ARP_EVICT_NOCARRIER - 1] ? "on" : "off");
+ }
+}
+
static void print_af_spec(FILE *fp, struct rtattr *af_spec_attr)
{
- struct rtattr *inet6_attr;
struct rtattr *tb[IFLA_INET6_MAX + 1];
+ struct rtattr *inet6_attr;
+ struct rtattr *inet_attr;
- inet6_attr = parse_rtattr_one_nested(AF_INET6, af_spec_attr);
- if (!inet6_attr)
- return;
+ inet_attr = parse_rtattr_one_nested(AF_INET, af_spec_attr);
+ if (inet_attr)
+ print_inet(fp, inet_attr);
- parse_rtattr_nested(tb, IFLA_INET6_MAX, inet6_attr);
+ inet6_attr = parse_rtattr_one_nested(AF_INET6, af_spec_attr);
+ if (inet6_attr) {
+ parse_rtattr_nested(tb, IFLA_INET6_MAX, inet6_attr);
- if (tb[IFLA_INET6_ADDR_GEN_MODE]) {
- __u8 mode = rta_getattr_u8(tb[IFLA_INET6_ADDR_GEN_MODE]);
- SPRINT_BUF(b1);
+ if (tb[IFLA_INET6_ADDR_GEN_MODE]) {
+ __u8 mode = rta_getattr_u8(tb[IFLA_INET6_ADDR_GEN_MODE]);
- switch (mode) {
- case IN6_ADDR_GEN_MODE_EUI64:
- print_string(PRINT_ANY,
- "inet6_addr_gen_mode",
- "addrgenmode %s ",
- "eui64");
- break;
- case IN6_ADDR_GEN_MODE_NONE:
- print_string(PRINT_ANY,
- "inet6_addr_gen_mode",
- "addrgenmode %s ",
- "none");
- break;
- case IN6_ADDR_GEN_MODE_STABLE_PRIVACY:
- print_string(PRINT_ANY,
- "inet6_addr_gen_mode",
- "addrgenmode %s ",
- "stable_secret");
- break;
- case IN6_ADDR_GEN_MODE_RANDOM:
- print_string(PRINT_ANY,
- "inet6_addr_gen_mode",
- "addrgenmode %s ",
- "random");
- break;
- default:
- snprintf(b1, sizeof(b1), "%#.2hhx", mode);
- print_string(PRINT_ANY,
- "inet6_addr_gen_mode",
- "addrgenmode %s ",
- b1);
- break;
+ SPRINT_BUF(b1);
+ switch (mode) {
+ case IN6_ADDR_GEN_MODE_EUI64:
+ print_string(PRINT_ANY,
+ "inet6_addr_gen_mode",
+ "addrgenmode %s ",
+ "eui64");
+ break;
+ case IN6_ADDR_GEN_MODE_NONE:
+ print_string(PRINT_ANY,
+ "inet6_addr_gen_mode",
+ "addrgenmode %s ",
+ "none");
+ break;
+ case IN6_ADDR_GEN_MODE_STABLE_PRIVACY:
+ print_string(PRINT_ANY,
+ "inet6_addr_gen_mode",
+ "addrgenmode %s ",
+ "stable_secret");
+ break;
+ case IN6_ADDR_GEN_MODE_RANDOM:
+ print_string(PRINT_ANY,
+ "inet6_addr_gen_mode",
+ " addrgenmode %s ",
+ "random");
+ break;
+ default:
+ snprintf(b1, sizeof(b1), "%#.2hhx", mode);
+ print_string(PRINT_ANY,
+ "inet6_addr_gen_mode",
+ "addrgenmode %s ",
+ b1);
+ break;
+ }
}
}
}
--
2.54.0
^ permalink raw reply related [flat|nested] 3+ messages in thread* Re: [PATCH iproute2-next] ipaddress: add support for showing IPv4 devconf attributes
2026-06-12 23:17 [PATCH iproute2-next] ipaddress: add support for showing IPv4 devconf attributes Fernando Fernandez Mancera
@ 2026-06-13 2:29 ` Stephen Hemminger
0 siblings, 0 replies; 3+ messages in thread
From: Stephen Hemminger @ 2026-06-13 2:29 UTC (permalink / raw)
To: Fernando Fernandez Mancera
Cc: netdev, dsahern, davem, edumazet, kuba, pabeni, horms
On Sat, 13 Jun 2026 01:17:22 +0200
Fernando Fernandez Mancera <fmancera@suse.de> wrote:
> tatic void print_inet(FILE *fp, struct rtattr *inet_attr)
> +{
> + struct rtattr *tb[IFLA_INET_MAX + 1];
> +
> + parse_rtattr_nested(tb, IFLA_INET_MAX, inet_attr);
> +
> + if (tb[IFLA_INET_CONF] && show_details) {
> + int *conf = RTA_DATA(tb[IFLA_INET_CONF]);
> + int max_elements = RTA_PAYLOAD(tb[IFLA_INET_CONF]) / sizeof(int);
> +
> + if (max_elements >= IPV4_DEVCONF_FORWARDING)
> + print_string(PRINT_ANY, "forwarding", "forwarding %s ",
> + conf[IPV4_DEVCONF_FORWARDING - 1] ? "on" : "off");
> +
> + if (max_elements >= IPV4_DEVCONF_MC_FORWARDING)
> + print_string(PRINT_ANY, "mc_forwarding", "mc_forwarding %s ",
> + conf[IPV4_DEVCONF_MC_FORWARDING - 1] ? "on" : "off");
> +
> + if (max_elements >= IPV4_DEVCONF_PROXY_ARP)
> + print_string(PRINT_ANY, "proxy_arp", "proxy_arp %s ",
> + conf[IPV4_DEVCONF_PROXY_ARP - 1] ? "on" : "off");
> +
> + if (max_elements >= IPV4_DEVCONF_ACCEPT_REDIRECTS)
> + print_string(PRINT_ANY, "accept_redirects",
> + "accept_redirects %s ",
> + conf[IPV4_DEVCONF_ACCEPT_REDIRECTS - 1] ? "on" : "off");
> +
> + if (max_elements >= IPV4_DEVCONF_SECURE_REDIRECTS)
> + print_string(PRINT_ANY, "secure_redirects",
> + "secure_redirects %s ",
> + conf[IPV4_DEVCONF_SECURE_REDIRECTS - 1] ? "on" : "off");
> +
> + if (max_elements >= IPV4_DEVCONF_SEND_REDIRECTS)
> + print_string(PRINT_ANY, "send_redirects", "send_redirects %s ",
> + conf[IPV4_DEVCONF_SEND_REDIRECTS - 1] ? "on" : "off");
> +
> + if (max_elements >= IPV4_DEVCONF_SHARED_MEDIA)
> + print_string(PRINT_ANY, "shared_media", "shared_media %s ",
> + conf[IPV4_DEVCONF_SHARED_MEDIA - 1] ? "on" : "off");
> +
> + if (max_elements >= IPV4_DEVCONF_RP_FILTER)
> + print_int(PRINT_ANY, "rp_filter", "rp_filter %d ",
> + conf[IPV4_DEVCONF_RP_FILTER - 1]);
> +
> + if (max_elements >= IPV4_DEVCONF_ACCEPT_SOURCE_ROUTE)
> + print_string(PRINT_ANY, "accept_source_route",
> + "accept_source_route %s ",
> + conf[IPV4_DEVCONF_ACCEPT_SOURCE_ROUTE - 1] ? "on" : "off");
> +
> + if (max_elements >= IPV4_DEVCONF_BOOTP_RELAY)
> + print_string(PRINT_ANY, "bootp_relay", "bootp_relay %s ",
> + conf[IPV4_DEVCONF_BOOTP_RELAY - 1] ? "on" : "off");
> +
> + if (max_elements >= IPV4_DEVCONF_LOG_MARTIANS)
> + print_string(PRINT_ANY, "log_martians", "log_martians %s ",
> + conf[IPV4_DEVCONF_LOG_MARTIANS - 1] ? "on" : "off");
> +
> + if (max_elements >= IPV4_DEVCONF_TAG)
> + print_int(PRINT_ANY, "tag", "tag %d ",
> + conf[IPV4_DEVCONF_TAG - 1]);
> +
> + if (max_elements >= IPV4_DEVCONF_ARPFILTER)
> + print_string(PRINT_ANY, "arpfilter", "arpfilter %s ",
> + conf[IPV4_DEVCONF_ARPFILTER - 1] ? "on" : "off");
> +
> + if (max_elements >= IPV4_DEVCONF_MEDIUM_ID)
> + print_int(PRINT_ANY, "medium_id", "medium_id %d ",
> + conf[IPV4_DEVCONF_MEDIUM_ID - 1]);
> +
> + if (max_elements >= IPV4_DEVCONF_NOXFRM)
> + print_string(PRINT_ANY, "noxfrm", "noxfrm %s ",
> + conf[IPV4_DEVCONF_NOXFRM - 1] ? "on" : "off");
> +
> + if (max_elements >= IPV4_DEVCONF_NOPOLICY)
> + print_string(PRINT_ANY, "nopolicy", "nopolicy %s ",
> + conf[IPV4_DEVCONF_NOPOLICY - 1] ? "on" : "off");
> +
> + if (max_elements >= IPV4_DEVCONF_FORCE_IGMP_VERSION)
> + print_int(PRINT_ANY, "force_igmp_version", "force_igmp_version %d ",
> + conf[IPV4_DEVCONF_FORCE_IGMP_VERSION - 1]);
> +
> + if (max_elements >= IPV4_DEVCONF_ARP_ANNOUNCE)
> + print_int(PRINT_ANY, "arp_announce", "arp_announce %d ",
> + conf[IPV4_DEVCONF_ARP_ANNOUNCE - 1]);
> +
> + if (max_elements >= IPV4_DEVCONF_ARP_IGNORE)
> + print_int(PRINT_ANY, "arp_ignore", "arp_ignore %d ",
> + conf[IPV4_DEVCONF_ARP_IGNORE - 1]);
> +
> + if (max_elements >= IPV4_DEVCONF_PROMOTE_SECONDARIES)
> + print_string(PRINT_ANY, "promote_secondaries",
> + "promote_secondaries %s ",
> + conf[IPV4_DEVCONF_PROMOTE_SECONDARIES - 1] ? "on" : "off");
> +
> + if (max_elements >= IPV4_DEVCONF_ARP_ACCEPT)
> + print_int(PRINT_ANY, "arp_accept", "arp_accept %d ",
> + conf[IPV4_DEVCONF_ARP_ACCEPT - 1]);
> +
> + if (max_elements >= IPV4_DEVCONF_ARP_NOTIFY)
> + print_string(PRINT_ANY, "arp_notify", "arp_notify %s ",
> + conf[IPV4_DEVCONF_ARP_NOTIFY - 1] ? "on" : "off");
> +
> + if (max_elements >= IPV4_DEVCONF_ACCEPT_LOCAL)
> + print_string(PRINT_ANY, "accept_local", "accept_local %s ",
> + conf[IPV4_DEVCONF_ACCEPT_LOCAL - 1] ? "on" : "off");
> +
> + if (max_elements >= IPV4_DEVCONF_SRC_VMARK)
> + print_string(PRINT_ANY, "src_vmark", " src_vmark %s",
> + conf[IPV4_DEVCONF_SRC_VMARK - 1] ? "on" : "off");
> +
> + if (max_elements >= IPV4_DEVCONF_PROXY_ARP_PVLAN)
> + print_string(PRINT_ANY, "proxy_arp_pvlan", "proxy_arp_pvlan %s ",
> + conf[IPV4_DEVCONF_PROXY_ARP_PVLAN - 1] ? "on" : "off");
> +
> + if (max_elements >= IPV4_DEVCONF_ROUTE_LOCALNET)
> + print_string(PRINT_ANY, "route_localnet", "route_localnet %s ",
> + conf[IPV4_DEVCONF_ROUTE_LOCALNET - 1] ? "on" : "off");
> +
> + if (max_elements >= IPV4_DEVCONF_BC_FORWARDING)
> + print_string(PRINT_ANY, "bc_forwarding", "bc_forwarding %s ",
> + conf[IPV4_DEVCONF_BC_FORWARDING - 1] ? "on" : "off");
> +
> + if (max_elements >= IPV4_DEVCONF_IGMPV2_UNSOLICITED_REPORT_INTERVAL)
> + print_int(PRINT_ANY, "igmpv2_unsolicited_report_interval",
> + "igmpv2_unsolicited_report_interval %d ",
> + conf[IPV4_DEVCONF_IGMPV2_UNSOLICITED_REPORT_INTERVAL - 1]);
> +
> + if (max_elements >= IPV4_DEVCONF_IGMPV3_UNSOLICITED_REPORT_INTERVAL)
> + print_int(PRINT_ANY, "igmpv3_unsolicited_report_interval",
> + "igmpv3_unsolicited_report_interval %d ",
> + conf[IPV4_DEVCONF_IGMPV3_UNSOLICITED_REPORT_INTERVAL - 1]);
> +
> + if (max_elements >= IPV4_DEVCONF_IGNORE_ROUTES_WITH_LINKDOWN)
> + print_string(PRINT_ANY, "ignore_routes_with_linkdown",
> + "ignore_routes_with_linkdown %s ",
> + conf[IPV4_DEVCONF_IGNORE_ROUTES_WITH_LINKDOWN - 1] ?
> + "on" : "off");
> +
> + if (max_elements >= IPV4_DEVCONF_DROP_UNICAST_IN_L2_MULTICAST)
> + print_string(PRINT_ANY, "drop_unicast_in_l2_multicast",
> + "drop_unicast_in_l2_multicast %s ",
> + conf[IPV4_DEVCONF_DROP_UNICAST_IN_L2_MULTICAST - 1] ?
> + "on" : "off");
> +
> + if (max_elements >= IPV4_DEVCONF_DROP_GRATUITOUS_ARP)
> + print_string(PRINT_ANY, "drop_gratuitous_arp",
> + "drop_gratuitous_arp %s ",
> + conf[IPV4_DEVCONF_DROP_GRATUITOUS_ARP - 1] ? "on" : "off");
> +
> + if (max_elements >= IPV4_DEVCONF_ARP_EVICT_NOCARRIER)
> + print_string(PRINT_ANY, "arp_evict_nocarrier",
> + "arp_evict_nocarrier %s ",
> + conf[IPV4_DEVCONF_ARP_EVICT_NOCARRIER - 1] ? "on" : "off");
> + }
> +}
> +
There are three different ways to display a flag value in JSON used in iproute2.
This one is my least favorite.
The three ways are:
- print_bool
- print_null (only if on)
- print_string
I would use the print_null pattern but print_bool would also be ok.
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH iproute2-next] ipaddress: add support for showing IPv4 devconf attributes
@ 2026-06-12 23:27 Fernando Fernandez Mancera
0 siblings, 0 replies; 3+ messages in thread
From: Fernando Fernandez Mancera @ 2026-06-12 23:27 UTC (permalink / raw)
To: netdev
Cc: dsahern, stephen, davem, edumazet, kuba, pabeni, horms,
Fernando Fernandez Mancera
This patch introduces support for showing IPv4 devconf attributes on
detailed output of an interface e.g "ip -d link show dev enp1s0".
Additionally, this refactors 'print_af_spec()' to sequentially process
both AF_INET and AF_INET6 attributes rather than returning early if
AF_INET6 is missing.
Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de>
---
Note/question: Is this too verbose? Maybe we should introduce a new
option to query this on itself? I do not think this will scale up when
adding IPv6.. although for IPv6 we can limit it to "-6" usage only.
---
ip/ipaddress.c | 241 +++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 201 insertions(+), 40 deletions(-)
diff --git a/ip/ipaddress.c b/ip/ipaddress.c
index 6017bc83..ab5cb0ae 100644
--- a/ip/ipaddress.c
+++ b/ip/ipaddress.c
@@ -23,6 +23,7 @@
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <linux/if_infiniband.h>
+#include <linux/ip.h>
#include <linux/sockios.h>
#include <linux/net_namespace.h>
@@ -294,53 +295,213 @@ static void print_linktype(FILE *fp, struct rtattr *tb)
close_json_object();
}
+static void print_inet(FILE *fp, struct rtattr *inet_attr)
+{
+ struct rtattr *tb[IFLA_INET_MAX + 1];
+
+ parse_rtattr_nested(tb, IFLA_INET_MAX, inet_attr);
+
+ if (tb[IFLA_INET_CONF]) {
+ int *conf = RTA_DATA(tb[IFLA_INET_CONF]);
+ int max_elements = RTA_PAYLOAD(tb[IFLA_INET_CONF]) / sizeof(int);
+
+ if (max_elements >= IPV4_DEVCONF_FORWARDING)
+ print_string(PRINT_ANY, "forwarding", "forwarding %s ",
+ conf[IPV4_DEVCONF_FORWARDING - 1] ? "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_MC_FORWARDING)
+ print_string(PRINT_ANY, "mc_forwarding", "mc_forwarding %s ",
+ conf[IPV4_DEVCONF_MC_FORWARDING - 1] ? "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_PROXY_ARP)
+ print_string(PRINT_ANY, "proxy_arp", "proxy_arp %s ",
+ conf[IPV4_DEVCONF_PROXY_ARP - 1] ? "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_ACCEPT_REDIRECTS)
+ print_string(PRINT_ANY, "accept_redirects",
+ "accept_redirects %s ",
+ conf[IPV4_DEVCONF_ACCEPT_REDIRECTS - 1] ? "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_SECURE_REDIRECTS)
+ print_string(PRINT_ANY, "secure_redirects",
+ "secure_redirects %s ",
+ conf[IPV4_DEVCONF_SECURE_REDIRECTS - 1] ? "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_SEND_REDIRECTS)
+ print_string(PRINT_ANY, "send_redirects", "send_redirects %s ",
+ conf[IPV4_DEVCONF_SEND_REDIRECTS - 1] ? "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_SHARED_MEDIA)
+ print_string(PRINT_ANY, "shared_media", "shared_media %s ",
+ conf[IPV4_DEVCONF_SHARED_MEDIA - 1] ? "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_RP_FILTER)
+ print_int(PRINT_ANY, "rp_filter", "rp_filter %d ",
+ conf[IPV4_DEVCONF_RP_FILTER - 1]);
+
+ if (max_elements >= IPV4_DEVCONF_ACCEPT_SOURCE_ROUTE)
+ print_string(PRINT_ANY, "accept_source_route",
+ "accept_source_route %s ",
+ conf[IPV4_DEVCONF_ACCEPT_SOURCE_ROUTE - 1] ? "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_BOOTP_RELAY)
+ print_string(PRINT_ANY, "bootp_relay", "bootp_relay %s ",
+ conf[IPV4_DEVCONF_BOOTP_RELAY - 1] ? "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_LOG_MARTIANS)
+ print_string(PRINT_ANY, "log_martians", "log_martians %s ",
+ conf[IPV4_DEVCONF_LOG_MARTIANS - 1] ? "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_TAG)
+ print_int(PRINT_ANY, "tag", "tag %d ",
+ conf[IPV4_DEVCONF_TAG - 1]);
+
+ if (max_elements >= IPV4_DEVCONF_ARPFILTER)
+ print_string(PRINT_ANY, "arpfilter", "arpfilter %s ",
+ conf[IPV4_DEVCONF_ARPFILTER - 1] ? "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_MEDIUM_ID)
+ print_int(PRINT_ANY, "medium_id", "medium_id %d ",
+ conf[IPV4_DEVCONF_MEDIUM_ID - 1]);
+
+ if (max_elements >= IPV4_DEVCONF_NOXFRM)
+ print_string(PRINT_ANY, "noxfrm", "noxfrm %s ",
+ conf[IPV4_DEVCONF_NOXFRM - 1] ? "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_NOPOLICY)
+ print_string(PRINT_ANY, "nopolicy", "nopolicy %s ",
+ conf[IPV4_DEVCONF_NOPOLICY - 1] ? "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_FORCE_IGMP_VERSION)
+ print_int(PRINT_ANY, "force_igmp_version", "force_igmp_version %d ",
+ conf[IPV4_DEVCONF_FORCE_IGMP_VERSION - 1]);
+
+ if (max_elements >= IPV4_DEVCONF_ARP_ANNOUNCE)
+ print_int(PRINT_ANY, "arp_announce", "arp_announce %d ",
+ conf[IPV4_DEVCONF_ARP_ANNOUNCE - 1]);
+
+ if (max_elements >= IPV4_DEVCONF_ARP_IGNORE)
+ print_int(PRINT_ANY, "arp_ignore", "arp_ignore %d ",
+ conf[IPV4_DEVCONF_ARP_IGNORE - 1]);
+
+ if (max_elements >= IPV4_DEVCONF_PROMOTE_SECONDARIES)
+ print_string(PRINT_ANY, "promote_secondaries",
+ "promote_secondaries %s ",
+ conf[IPV4_DEVCONF_PROMOTE_SECONDARIES - 1] ? "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_ARP_ACCEPT)
+ print_int(PRINT_ANY, "arp_accept", "arp_accept %d ",
+ conf[IPV4_DEVCONF_ARP_ACCEPT - 1]);
+
+ if (max_elements >= IPV4_DEVCONF_ARP_NOTIFY)
+ print_string(PRINT_ANY, "arp_notify", "arp_notify %s ",
+ conf[IPV4_DEVCONF_ARP_NOTIFY - 1] ? "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_ACCEPT_LOCAL)
+ print_string(PRINT_ANY, "accept_local", "accept_local %s ",
+ conf[IPV4_DEVCONF_ACCEPT_LOCAL - 1] ? "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_SRC_VMARK)
+ print_string(PRINT_ANY, "src_vmark", " src_vmark %s",
+ conf[IPV4_DEVCONF_SRC_VMARK - 1] ? "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_PROXY_ARP_PVLAN)
+ print_string(PRINT_ANY, "proxy_arp_pvlan", "proxy_arp_pvlan %s ",
+ conf[IPV4_DEVCONF_PROXY_ARP_PVLAN - 1] ? "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_ROUTE_LOCALNET)
+ print_string(PRINT_ANY, "route_localnet", "route_localnet %s ",
+ conf[IPV4_DEVCONF_ROUTE_LOCALNET - 1] ? "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_BC_FORWARDING)
+ print_string(PRINT_ANY, "bc_forwarding", "bc_forwarding %s ",
+ conf[IPV4_DEVCONF_BC_FORWARDING - 1] ? "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_IGMPV2_UNSOLICITED_REPORT_INTERVAL)
+ print_int(PRINT_ANY, "igmpv2_unsolicited_report_interval",
+ "igmpv2_unsolicited_report_interval %d ",
+ conf[IPV4_DEVCONF_IGMPV2_UNSOLICITED_REPORT_INTERVAL - 1]);
+
+ if (max_elements >= IPV4_DEVCONF_IGMPV3_UNSOLICITED_REPORT_INTERVAL)
+ print_int(PRINT_ANY, "igmpv3_unsolicited_report_interval",
+ "igmpv3_unsolicited_report_interval %d ",
+ conf[IPV4_DEVCONF_IGMPV3_UNSOLICITED_REPORT_INTERVAL - 1]);
+
+ if (max_elements >= IPV4_DEVCONF_IGNORE_ROUTES_WITH_LINKDOWN)
+ print_string(PRINT_ANY, "ignore_routes_with_linkdown",
+ "ignore_routes_with_linkdown %s ",
+ conf[IPV4_DEVCONF_IGNORE_ROUTES_WITH_LINKDOWN - 1] ?
+ "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_DROP_UNICAST_IN_L2_MULTICAST)
+ print_string(PRINT_ANY, "drop_unicast_in_l2_multicast",
+ "drop_unicast_in_l2_multicast %s ",
+ conf[IPV4_DEVCONF_DROP_UNICAST_IN_L2_MULTICAST - 1] ?
+ "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_DROP_GRATUITOUS_ARP)
+ print_string(PRINT_ANY, "drop_gratuitous_arp",
+ "drop_gratuitous_arp %s ",
+ conf[IPV4_DEVCONF_DROP_GRATUITOUS_ARP - 1] ? "on" : "off");
+
+ if (max_elements >= IPV4_DEVCONF_ARP_EVICT_NOCARRIER)
+ print_string(PRINT_ANY, "arp_evict_nocarrier",
+ "arp_evict_nocarrier %s ",
+ conf[IPV4_DEVCONF_ARP_EVICT_NOCARRIER - 1] ? "on" : "off");
+ }
+}
+
static void print_af_spec(FILE *fp, struct rtattr *af_spec_attr)
{
- struct rtattr *inet6_attr;
struct rtattr *tb[IFLA_INET6_MAX + 1];
+ struct rtattr *inet6_attr;
+ struct rtattr *inet_attr;
- inet6_attr = parse_rtattr_one_nested(AF_INET6, af_spec_attr);
- if (!inet6_attr)
- return;
+ inet_attr = parse_rtattr_one_nested(AF_INET, af_spec_attr);
+ if (inet_attr)
+ print_inet(fp, inet_attr);
- parse_rtattr_nested(tb, IFLA_INET6_MAX, inet6_attr);
+ inet6_attr = parse_rtattr_one_nested(AF_INET6, af_spec_attr);
+ if (inet6_attr) {
+ parse_rtattr_nested(tb, IFLA_INET6_MAX, inet6_attr);
- if (tb[IFLA_INET6_ADDR_GEN_MODE]) {
- __u8 mode = rta_getattr_u8(tb[IFLA_INET6_ADDR_GEN_MODE]);
- SPRINT_BUF(b1);
+ if (tb[IFLA_INET6_ADDR_GEN_MODE]) {
+ __u8 mode = rta_getattr_u8(tb[IFLA_INET6_ADDR_GEN_MODE]);
- switch (mode) {
- case IN6_ADDR_GEN_MODE_EUI64:
- print_string(PRINT_ANY,
- "inet6_addr_gen_mode",
- "addrgenmode %s ",
- "eui64");
- break;
- case IN6_ADDR_GEN_MODE_NONE:
- print_string(PRINT_ANY,
- "inet6_addr_gen_mode",
- "addrgenmode %s ",
- "none");
- break;
- case IN6_ADDR_GEN_MODE_STABLE_PRIVACY:
- print_string(PRINT_ANY,
- "inet6_addr_gen_mode",
- "addrgenmode %s ",
- "stable_secret");
- break;
- case IN6_ADDR_GEN_MODE_RANDOM:
- print_string(PRINT_ANY,
- "inet6_addr_gen_mode",
- "addrgenmode %s ",
- "random");
- break;
- default:
- snprintf(b1, sizeof(b1), "%#.2hhx", mode);
- print_string(PRINT_ANY,
- "inet6_addr_gen_mode",
- "addrgenmode %s ",
- b1);
- break;
+ SPRINT_BUF(b1);
+ switch (mode) {
+ case IN6_ADDR_GEN_MODE_EUI64:
+ print_string(PRINT_ANY,
+ "inet6_addr_gen_mode",
+ "addrgenmode %s ",
+ "eui64");
+ break;
+ case IN6_ADDR_GEN_MODE_NONE:
+ print_string(PRINT_ANY,
+ "inet6_addr_gen_mode",
+ "addrgenmode %s ",
+ "none");
+ break;
+ case IN6_ADDR_GEN_MODE_STABLE_PRIVACY:
+ print_string(PRINT_ANY,
+ "inet6_addr_gen_mode",
+ "addrgenmode %s ",
+ "stable_secret");
+ break;
+ case IN6_ADDR_GEN_MODE_RANDOM:
+ print_string(PRINT_ANY,
+ "inet6_addr_gen_mode",
+ " addrgenmode %s ",
+ "random");
+ break;
+ default:
+ snprintf(b1, sizeof(b1), "%#.2hhx", mode);
+ print_string(PRINT_ANY,
+ "inet6_addr_gen_mode",
+ "addrgenmode %s ",
+ b1);
+ break;
+ }
}
}
}
--
2.54.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-06-13 2:29 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-12 23:17 [PATCH iproute2-next] ipaddress: add support for showing IPv4 devconf attributes Fernando Fernandez Mancera
2026-06-13 2:29 ` Stephen Hemminger
-- strict thread matches above, loose matches on Subject: below --
2026-06-12 23:27 Fernando Fernandez Mancera
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox