* [PATCH iproute-next v3] ipaddress: add support for showing IPv4 devconf attributes
@ 2026-06-14 18:25 Fernando Fernandez Mancera
2026-06-28 17:30 ` David Ahern
0 siblings, 1 reply; 2+ messages in thread
From: Fernando Fernandez Mancera @ 2026-06-14 18:25 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>
---
v2: changed print_string to print_bool for boolean attributes
v3: use print_bool for JSON output only
---
ip/ipaddress.c | 313 ++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 273 insertions(+), 40 deletions(-)
diff --git a/ip/ipaddress.c b/ip/ipaddress.c
index 6017bc83..1530b836 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,285 @@ 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_bool(PRINT_JSON, "forwarding", NULL,
+ conf[IPV4_DEVCONF_FORWARDING - 1]);
+ print_string(PRINT_FP, "forwarding", "forwarding %s ",
+ conf[IPV4_DEVCONF_FORWARDING - 1] ? "on" : "off");
+ }
+
+ if (max_elements >= IPV4_DEVCONF_MC_FORWARDING) {
+ print_bool(PRINT_JSON, "mc_forwarding", NULL,
+ conf[IPV4_DEVCONF_MC_FORWARDING - 1]);
+ print_string(PRINT_FP, "mc_forwarding", "mc_forwarding %s ",
+ conf[IPV4_DEVCONF_MC_FORWARDING - 1] ? "on" : "off");
+ }
+
+ if (max_elements >= IPV4_DEVCONF_PROXY_ARP) {
+ print_bool(PRINT_JSON, "proxy_arp", NULL,
+ conf[IPV4_DEVCONF_PROXY_ARP - 1]);
+ print_string(PRINT_FP, "proxy_arp", "proxy_arp %s ",
+ conf[IPV4_DEVCONF_PROXY_ARP - 1] ? "on" : "off");
+ }
+
+ if (max_elements >= IPV4_DEVCONF_ACCEPT_REDIRECTS) {
+ print_bool(PRINT_JSON, "accept_redirects", NULL,
+ conf[IPV4_DEVCONF_ACCEPT_REDIRECTS - 1]);
+ print_string(PRINT_FP, "accept_redirects",
+ "accept_redirects %s ",
+ conf[IPV4_DEVCONF_ACCEPT_REDIRECTS - 1] ? "on" : "off");
+ }
+
+ if (max_elements >= IPV4_DEVCONF_SECURE_REDIRECTS) {
+ print_bool(PRINT_JSON, "secure_redirects", NULL,
+ conf[IPV4_DEVCONF_SECURE_REDIRECTS - 1]);
+ print_string(PRINT_FP, "secure_redirects",
+ "secure_redirects %s ",
+ conf[IPV4_DEVCONF_SECURE_REDIRECTS - 1] ? "on" : "off");
+ }
+
+ if (max_elements >= IPV4_DEVCONF_SEND_REDIRECTS) {
+ print_bool(PRINT_JSON, "send_redirects", NULL,
+ conf[IPV4_DEVCONF_SEND_REDIRECTS - 1]);
+ print_string(PRINT_FP, "send_redirects", "send_redirects %s ",
+ conf[IPV4_DEVCONF_SEND_REDIRECTS - 1] ? "on" : "off");
+ }
+
+ if (max_elements >= IPV4_DEVCONF_SHARED_MEDIA) {
+ print_bool(PRINT_JSON, "shared_media", NULL,
+ conf[IPV4_DEVCONF_SHARED_MEDIA - 1]);
+ print_string(PRINT_FP, "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_bool(PRINT_JSON, "accept_source_route", NULL,
+ conf[IPV4_DEVCONF_ACCEPT_SOURCE_ROUTE - 1]);
+ print_string(PRINT_FP, "accept_source_route",
+ "accept_source_route %s ",
+ conf[IPV4_DEVCONF_ACCEPT_SOURCE_ROUTE - 1] ? "on" : "off");
+ }
+
+ if (max_elements >= IPV4_DEVCONF_BOOTP_RELAY) {
+ print_bool(PRINT_JSON, "bootp_relay", NULL,
+ conf[IPV4_DEVCONF_BOOTP_RELAY - 1]);
+ print_string(PRINT_FP, "bootp_relay", "bootp_relay %s ",
+ conf[IPV4_DEVCONF_BOOTP_RELAY - 1] ? "on" : "off");
+ }
+
+ if (max_elements >= IPV4_DEVCONF_LOG_MARTIANS) {
+ print_bool(PRINT_JSON, "log_martians", NULL,
+ conf[IPV4_DEVCONF_LOG_MARTIANS - 1]);
+ print_string(PRINT_FP, "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_bool(PRINT_JSON, "arpfilter", NULL,
+ conf[IPV4_DEVCONF_ARPFILTER - 1]);
+ print_string(PRINT_FP, "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_bool(PRINT_JSON, "noxfrm", NULL,
+ conf[IPV4_DEVCONF_NOXFRM - 1]);
+ print_string(PRINT_FP, "noxfrm", "noxfrm %s ",
+ conf[IPV4_DEVCONF_NOXFRM - 1] ? "on" : "off");
+ }
+
+ if (max_elements >= IPV4_DEVCONF_NOPOLICY) {
+ print_bool(PRINT_JSON, "nopolicy", NULL,
+ conf[IPV4_DEVCONF_NOPOLICY - 1]);
+ print_string(PRINT_FP, "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_bool(PRINT_JSON, "promote_secondaries", NULL,
+ conf[IPV4_DEVCONF_PROMOTE_SECONDARIES - 1]);
+ print_string(PRINT_FP, "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_bool(PRINT_JSON, "arp_notify", NULL,
+ conf[IPV4_DEVCONF_ARP_NOTIFY - 1]);
+ print_string(PRINT_FP, "arp_notify", "arp_notify %s ",
+ conf[IPV4_DEVCONF_ARP_NOTIFY - 1] ? "on" : "off");
+ }
+
+ if (max_elements >= IPV4_DEVCONF_ACCEPT_LOCAL) {
+ print_bool(PRINT_JSON, "accept_local", NULL,
+ conf[IPV4_DEVCONF_ACCEPT_LOCAL - 1]);
+ print_string(PRINT_FP, "accept_local", "accept_local %s ",
+ conf[IPV4_DEVCONF_ACCEPT_LOCAL - 1] ? "on" : "off");
+ }
+
+ if (max_elements >= IPV4_DEVCONF_SRC_VMARK) {
+ print_bool(PRINT_JSON, "src_vmark", NULL,
+ conf[IPV4_DEVCONF_SRC_VMARK - 1]);
+ print_string(PRINT_FP, "src_vmark", "src_vmark %s ",
+ conf[IPV4_DEVCONF_SRC_VMARK - 1] ? "on" : "off");
+ }
+
+ if (max_elements >= IPV4_DEVCONF_PROXY_ARP_PVLAN) {
+ print_bool(PRINT_JSON, "proxy_arp_pvlan", NULL,
+ conf[IPV4_DEVCONF_PROXY_ARP_PVLAN - 1]);
+ print_string(PRINT_FP, "proxy_arp_pvlan", "proxy_arp_pvlan %s ",
+ conf[IPV4_DEVCONF_PROXY_ARP_PVLAN - 1] ? "on" : "off");
+ }
+
+ if (max_elements >= IPV4_DEVCONF_ROUTE_LOCALNET) {
+ print_bool(PRINT_JSON, "route_localnet", NULL,
+ conf[IPV4_DEVCONF_ROUTE_LOCALNET - 1]);
+ print_string(PRINT_FP, "route_localnet", "route_localnet %s ",
+ conf[IPV4_DEVCONF_ROUTE_LOCALNET - 1] ? "on" : "off");
+ }
+
+ if (max_elements >= IPV4_DEVCONF_BC_FORWARDING) {
+ print_bool(PRINT_JSON, "bc_forwarding", NULL,
+ conf[IPV4_DEVCONF_BC_FORWARDING - 1]);
+ print_string(PRINT_FP, "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_bool(PRINT_JSON, "ignore_routes_with_linkdown", NULL,
+ conf[IPV4_DEVCONF_IGNORE_ROUTES_WITH_LINKDOWN - 1]);
+ print_string(PRINT_FP, "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_bool(PRINT_JSON, "drop_unicast_in_l2_multicast", NULL,
+ conf[IPV4_DEVCONF_DROP_UNICAST_IN_L2_MULTICAST - 1]);
+ print_string(PRINT_FP, "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_bool(PRINT_JSON, "drop_gratuitous_arp", NULL,
+ conf[IPV4_DEVCONF_DROP_GRATUITOUS_ARP - 1]);
+ print_string(PRINT_FP, "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_bool(PRINT_JSON, "arp_evict_nocarrier", NULL,
+ conf[IPV4_DEVCONF_ARP_EVICT_NOCARRIER - 1]);
+ print_string(PRINT_FP, "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] 2+ messages in thread
* Re: [PATCH iproute-next v3] ipaddress: add support for showing IPv4 devconf attributes
2026-06-14 18:25 [PATCH iproute-next v3] ipaddress: add support for showing IPv4 devconf attributes Fernando Fernandez Mancera
@ 2026-06-28 17:30 ` David Ahern
0 siblings, 0 replies; 2+ messages in thread
From: David Ahern @ 2026-06-28 17:30 UTC (permalink / raw)
To: Fernando Fernandez Mancera, netdev
Cc: stephen, davem, edumazet, kuba, pabeni, horms
On 6/14/26 12:25 PM, Fernando Fernandez Mancera wrote:
> 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.
refactors should be a separate patch.
>
> Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de>
> ---
> v2: changed print_string to print_bool for boolean attributes
> v3: use print_bool for JSON output only
> ---
> ip/ipaddress.c | 313 ++++++++++++++++++++++++++++++++++++++++++-------
> 1 file changed, 273 insertions(+), 40 deletions(-)
>
> diff --git a/ip/ipaddress.c b/ip/ipaddress.c
> index 6017bc83..1530b836 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,285 @@ 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_bool(PRINT_JSON, "forwarding", NULL,
> + conf[IPV4_DEVCONF_FORWARDING - 1]);
> + print_string(PRINT_FP, "forwarding", "forwarding %s ",
> + conf[IPV4_DEVCONF_FORWARDING - 1] ? "on" : "off");
> + }
> +
> + if (max_elements >= IPV4_DEVCONF_MC_FORWARDING) {
> + print_bool(PRINT_JSON, "mc_forwarding", NULL,
> + conf[IPV4_DEVCONF_MC_FORWARDING - 1]);
> + print_string(PRINT_FP, "mc_forwarding", "mc_forwarding %s ",
> + conf[IPV4_DEVCONF_MC_FORWARDING - 1] ? "on" : "off");
> + }
> +
> + if (max_elements >= IPV4_DEVCONF_PROXY_ARP) {
> + print_bool(PRINT_JSON, "proxy_arp", NULL,
> + conf[IPV4_DEVCONF_PROXY_ARP - 1]);
> + print_string(PRINT_FP, "proxy_arp", "proxy_arp %s ",
> + conf[IPV4_DEVCONF_PROXY_ARP - 1] ? "on" : "off");
> + }
> +
> + if (max_elements >= IPV4_DEVCONF_ACCEPT_REDIRECTS) {
> + print_bool(PRINT_JSON, "accept_redirects", NULL,
> + conf[IPV4_DEVCONF_ACCEPT_REDIRECTS - 1]);
> + print_string(PRINT_FP, "accept_redirects",
> + "accept_redirects %s ",
> + conf[IPV4_DEVCONF_ACCEPT_REDIRECTS - 1] ? "on" : "off");
As I stated in the last patch for devconf:
"iproute2 follows netdev with coding standards and those need to be
followed as long as humans are in the loop. Please make sure follow on
patches adhere to roughly 80 columns with a little extra if it improves
readability (and of course strings are not broken across lines)."
Use print_on_off for example for these or use a temp variable for the
attributes.
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-06-28 17:30 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-14 18:25 [PATCH iproute-next v3] ipaddress: add support for showing IPv4 devconf attributes Fernando Fernandez Mancera
2026-06-28 17:30 ` David Ahern
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox