]> git.baikalelectronics.ru Git - kernel.git/commitdiff
net: change accept_ra_min_rtr_lft to affect all RA lifetimes
authorPatrick Rohr <prohr@google.com>
Wed, 26 Jul 2023 23:07:01 +0000 (16:07 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 10 Oct 2023 20:00:37 +0000 (22:00 +0200)
commit 5027d54a9c30bc7ec808360378e2b4753f053f25 upstream.

accept_ra_min_rtr_lft only considered the lifetime of the default route
and discarded entire RAs accordingly.

This change renames accept_ra_min_rtr_lft to accept_ra_min_lft, and
applies the value to individual RA sections; in particular, router
lifetime, PIO preferred lifetime, and RIO lifetime. If any of those
lifetimes are lower than the configured value, the specific RA section
is ignored.

In order for the sysctl to be useful to Android, it should really apply
to all lifetimes in the RA, since that is what determines the minimum
frequency at which RAs must be processed by the kernel. Android uses
hardware offloads to drop RAs for a fraction of the minimum of all
lifetimes present in the RA (some networks have very frequent RAs (5s)
with high lifetimes (2h)). Despite this, we have encountered networks
that set the router lifetime to 30s which results in very frequent CPU
wakeups. Instead of disabling IPv6 (and dropping IPv6 ethertype in the
WiFi firmware) entirely on such networks, it seems better to ignore the
misconfigured routers while still processing RAs from other IPv6 routers
on the same network (i.e. to support IoT applications).

The previous implementation dropped the entire RA based on router
lifetime. This turned out to be hard to expand to the other lifetimes
present in the RA in a consistent manner; dropping the entire RA based
on RIO/PIO lifetimes would essentially require parsing the whole thing
twice.

Fixes: 1671bcfd76fd ("net: add sysctl accept_ra_min_rtr_lft")
Cc: Lorenzo Colitti <lorenzo@google.com>
Signed-off-by: Patrick Rohr <prohr@google.com>
Reviewed-by: Maciej Żenczykowski <maze@google.com>
Reviewed-by: David Ahern <dsahern@kernel.org>
Link: https://lore.kernel.org/r/20230726230701.919212-1-prohr@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Documentation/networking/ip-sysctl.rst
include/linux/ipv6.h
include/uapi/linux/ipv6.h
net/ipv6/addrconf.c
net/ipv6/ndisc.c

index b0e9210f7a28d6952b6fb4143e95c4b90fbe7a2f..f5f7a464605f9ca8d8c9ca6b4e8c252a094d8fb8 100644 (file)
@@ -2148,11 +2148,11 @@ accept_ra_min_hop_limit - INTEGER
 
        Default: 1
 
-accept_ra_min_rtr_lft - INTEGER
-       Minimum acceptable router lifetime in Router Advertisement.
+accept_ra_min_lft - INTEGER
+       Minimum acceptable lifetime value in Router Advertisement.
 
-       RAs with a router lifetime less than this value shall be
-       ignored. RAs with a router lifetime of 0 are unaffected.
+       RA sections with a lifetime less than this value shall be
+       ignored. Zero lifetimes stay unaffected.
 
        Default: 0
 
index a4b35f4c89d77363c72c390eb3199eb1d164813a..9a44de45cc1f26b4be35f423ca277c38b551b953 100644 (file)
@@ -33,7 +33,7 @@ struct ipv6_devconf {
        __s32           accept_ra_defrtr;
        __u32           ra_defrtr_metric;
        __s32           accept_ra_min_hop_limit;
-       __s32           accept_ra_min_rtr_lft;
+       __s32           accept_ra_min_lft;
        __s32           accept_ra_pinfo;
        __s32           ignore_routes_with_linkdown;
 #ifdef CONFIG_IPV6_ROUTER_PREF
index 2038eff9b63f9f56fe48f78152b33855124c99fa..4fa8511b1e35502a9824a5969647ae69aad848d8 100644 (file)
@@ -198,7 +198,7 @@ enum {
        DEVCONF_IOAM6_ID_WIDE,
        DEVCONF_NDISC_EVICT_NOCARRIER,
        DEVCONF_ACCEPT_UNTRACKED_NA,
-       DEVCONF_ACCEPT_RA_MIN_RTR_LFT,
+       DEVCONF_ACCEPT_RA_MIN_LFT,
        DEVCONF_MAX
 };
 
index c7e939c619c965bfe77bc12f675bd9ef6f8b9276..53db8daa738592388b290728c20ccf6cea25e410 100644 (file)
@@ -202,7 +202,7 @@ static struct ipv6_devconf ipv6_devconf __read_mostly = {
        .ra_defrtr_metric       = IP6_RT_PRIO_USER,
        .accept_ra_from_local   = 0,
        .accept_ra_min_hop_limit= 1,
-       .accept_ra_min_rtr_lft  = 0,
+       .accept_ra_min_lft      = 0,
        .accept_ra_pinfo        = 1,
 #ifdef CONFIG_IPV6_ROUTER_PREF
        .accept_ra_rtr_pref     = 1,
@@ -263,7 +263,7 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
        .ra_defrtr_metric       = IP6_RT_PRIO_USER,
        .accept_ra_from_local   = 0,
        .accept_ra_min_hop_limit= 1,
-       .accept_ra_min_rtr_lft  = 0,
+       .accept_ra_min_lft      = 0,
        .accept_ra_pinfo        = 1,
 #ifdef CONFIG_IPV6_ROUTER_PREF
        .accept_ra_rtr_pref     = 1,
@@ -2733,6 +2733,9 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao)
                return;
        }
 
+       if (valid_lft != 0 && valid_lft < in6_dev->cnf.accept_ra_min_lft)
+               return;
+
        /*
         *      Two things going on here:
         *      1) Add routes for on-link prefixes
@@ -5603,7 +5606,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
        array[DEVCONF_IOAM6_ID_WIDE] = cnf->ioam6_id_wide;
        array[DEVCONF_NDISC_EVICT_NOCARRIER] = cnf->ndisc_evict_nocarrier;
        array[DEVCONF_ACCEPT_UNTRACKED_NA] = cnf->accept_untracked_na;
-       array[DEVCONF_ACCEPT_RA_MIN_RTR_LFT] = cnf->accept_ra_min_rtr_lft;
+       array[DEVCONF_ACCEPT_RA_MIN_LFT] = cnf->accept_ra_min_lft;
 }
 
 static inline size_t inet6_ifla6_size(void)
@@ -6798,8 +6801,8 @@ static const struct ctl_table addrconf_sysctl[] = {
                .proc_handler   = proc_dointvec,
        },
        {
-               .procname       = "accept_ra_min_rtr_lft",
-               .data           = &ipv6_devconf.accept_ra_min_rtr_lft,
+               .procname       = "accept_ra_min_lft",
+               .data           = &ipv6_devconf.accept_ra_min_lft,
                .maxlen         = sizeof(int),
                .mode           = 0644,
                .proc_handler   = proc_dointvec,
index c2a6cda4be2895f62dfdb19fe473a6be9db421b5..6cb2d6a536a84ec3ef89bf1143f9aceaaf7ae9c2 100644 (file)
@@ -1284,8 +1284,6 @@ static void ndisc_router_discovery(struct sk_buff *skb)
                return;
        }
 
-       lifetime = ntohs(ra_msg->icmph.icmp6_rt_lifetime);
-
        if (!ipv6_accept_ra(in6_dev)) {
                ND_PRINTK(2, info,
                          "RA: %s, did not accept ra for dev: %s\n",
@@ -1293,13 +1291,6 @@ static void ndisc_router_discovery(struct sk_buff *skb)
                goto skip_linkparms;
        }
 
-       if (lifetime != 0 && lifetime < in6_dev->cnf.accept_ra_min_rtr_lft) {
-               ND_PRINTK(2, info,
-                         "RA: router lifetime (%ds) is too short: %s\n",
-                         lifetime, skb->dev->name);
-               goto skip_linkparms;
-       }
-
 #ifdef CONFIG_IPV6_NDISC_NODETYPE
        /* skip link-specific parameters from interior routers */
        if (skb->ndisc_nodetype == NDISC_NODETYPE_NODEFAULT) {
@@ -1340,6 +1331,14 @@ static void ndisc_router_discovery(struct sk_buff *skb)
                goto skip_defrtr;
        }
 
+       lifetime = ntohs(ra_msg->icmph.icmp6_rt_lifetime);
+       if (lifetime != 0 && lifetime < in6_dev->cnf.accept_ra_min_lft) {
+               ND_PRINTK(2, info,
+                         "RA: router lifetime (%ds) is too short: %s\n",
+                         lifetime, skb->dev->name);
+               goto skip_defrtr;
+       }
+
        /* Do not accept RA with source-addr found on local machine unless
         * accept_ra_from_local is set to true.
         */
@@ -1502,13 +1501,6 @@ skip_linkparms:
                goto out;
        }
 
-       if (lifetime != 0 && lifetime < in6_dev->cnf.accept_ra_min_rtr_lft) {
-               ND_PRINTK(2, info,
-                         "RA: router lifetime (%ds) is too short: %s\n",
-                         lifetime, skb->dev->name);
-               goto out;
-       }
-
 #ifdef CONFIG_IPV6_ROUTE_INFO
        if (!in6_dev->cnf.accept_ra_from_local &&
            ipv6_chk_addr(dev_net(in6_dev->dev), &ipv6_hdr(skb)->saddr,
@@ -1533,6 +1525,9 @@ skip_linkparms:
                        if (ri->prefix_len == 0 &&
                            !in6_dev->cnf.accept_ra_defrtr)
                                continue;
+                       if (ri->lifetime != 0 &&
+                           ntohl(ri->lifetime) < in6_dev->cnf.accept_ra_min_lft)
+                               continue;
                        if (ri->prefix_len < in6_dev->cnf.accept_ra_rt_info_min_plen)
                                continue;
                        if (ri->prefix_len > in6_dev->cnf.accept_ra_rt_info_max_plen)