What is the difference between "all", "default" and "eth*" in /proc/sys/net/ipv[46]/conf/?

I've found the answer while still writing the question. I've decided to post it anyway because others may find this insightful, and then answer it myself; I hope this is not frowned upon :)

The user Philipp Matthias Hahn on the linux-kernel mailing list has figured it out at least partially:

As far as I researched for IPv4 some time ago, the "default" value gets
copied to newly created interfaces only once.
"all" on the other hand allways gets applied in addition to the current
setting, but it depends on the exact setting, if its ORed, ANDed, or
whatevered:
    log_martians         OR
    accept_redirects     AND
    forwarding           ?
    mc_forwarding        AND
    medium_id
    proxy_arp            OR
    shared_media         OR
    secure_redirects     OR
    send_redirects       OR
    bootp_relay          AND
    accept_source_route  AND
    rp_filter            AND
    arp_filter           OR
    arp_announce         MAX
    arp_ignore           MAX
    arp_accept
    app_solicit
    disable_policy
    disable_xfrm
    tag
(see include/linux/inetdevice.h:83 for IN_DEV_{AND,OR,MAX}CONF)

Putting a new value in "all" doesn't change the value you read from
"$interface", but it only gets computed and used internally.

He doesn't cover accept_ra but at least it's clear now how all and default work, or rather, how they do not work as I would have expected.


The handler for accept_ra in net/ipv6/addrconf.c is proc_dointvec. So generic interface code has previously generated an array of all and interface-specific entries, and writing into these with sysctl or procfs just puts the value you specify in the array.

We are concerned with how those values are then used

You'll see from callers of ipv6_accept_ra() function in include/net/ipv6.h that every caller uses a specific interface to call that function.

So there is nowhere in the kernel that net.ipv6.conf.all.accept_ra is ever used except to store a procfs entry, as far as I can see.

If you want to change accept_ra of every interface with one command, you can do this:

for TUNABLE in $(sysctl -aN --pattern "accept_ra$")
do
    sysctl -w "$TUNABLE=0"
done

I'm about 4 years late but this is the correct answer :P