]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
route lifetime behaviour should mirror other lifetimes
authorRoy Marples <roy@marples.name>
Sat, 22 Feb 2025 13:21:17 +0000 (13:21 +0000)
committerRoy Marples <roy@marples.name>
Sat, 22 Feb 2025 13:21:17 +0000 (13:21 +0000)
Each lifetime has a an aquistion time so we can compare to
now to know how much of the lifetime is left.
Apply the difference when adding/changing the route just as we
do for addresses.

This allow us to work out better when we need to update the
route lifetime from a newer aquisition.

Fixes #465.

src/common.h
src/if-linux.c
src/ipv6.c
src/ipv6nd.c
src/route.c
src/route.h

index a2ab05ea4b73098f5fe29d3968310d4f3539040d..12f9c1f44a0ebb64601f055cc59c90ad01e2c528 100644 (file)
 #ifndef timespecclear
 #define timespecclear(tsp)      (tsp)->tv_sec = (time_t)((tsp)->tv_nsec = 0L)
 #define timespecisset(tsp)      ((tsp)->tv_sec || (tsp)->tv_nsec)
+#define timespecadd(tsp, usp, vsp)                                      \
+       do {                                                            \
+               (vsp)->tv_sec = (tsp)->tv_sec + (usp)->tv_sec;          \
+               (vsp)->tv_nsec = (tsp)->tv_nsec + (usp)->tv_nsec;       \
+               if ((vsp)->tv_nsec >= 1000000000L) {                    \
+                       (vsp)->tv_sec++;                                \
+                       (vsp)->tv_nsec -= 1000000000L;                  \
+               }                                                       \
+       } while (0)
+#define timespecsub(tsp, usp, vsp)                                      \
+       do {                                                            \
+               (vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec;          \
+               (vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec;       \
+               if ((vsp)->tv_nsec < 0) {                               \
+                       (vsp)->tv_sec--;                                \
+                       (vsp)->tv_nsec += 1000000000L;                  \
+               }                                                       \
+       } while (0)
 #endif
 
 #if __GNUC__ > 2 || defined(__INTEL_COMPILER)
index 2a105a1125dbc6c7b337eb011645c837e7ba95b9..5a4a89c3aaf5ea0b5f5d946adfd4729a02b53de4 100644 (file)
@@ -1770,8 +1770,12 @@ if_route(unsigned char cmd, const struct rt *rt)
                add_attr_32(&nlm.hdr, sizeof(nlm), RTA_OIF, rt->rt_ifp->index);
 
 #ifdef HAVE_ROUTE_LIFETIME
-       if (rt->rt_lifetime != 0)
-               add_attr_32(&nlm.hdr, sizeof(nlm), RTA_EXPIRES,rt->rt_lifetime);
+       if (rt->rt_lifetime != 0) {
+               uint32_t expires;
+
+               expires = lifetime_left(rt->rt_lifetime, &rt->rt_aquired, NULL);
+               add_attr_32(&nlm.hdr, sizeof(nlm), RTA_EXPIRES, expires);
+       }
 #endif
 
        if (rt->rt_metric != 0)
index 4561762b1e78a3f382d5a4d4608b2a69d350d126..934d5b2479d4e061162455e6efd9d896055b0876 100644 (file)
@@ -709,9 +709,7 @@ ipv6_addaddr1(struct ipv6_addr *ia, struct timespec *now)
                 * The saved times will be re-applied to the ia
                 * before exiting this function. */
                ia->prefix_vltime = ia->prefix_pltime = ND6_INFINITE_LIFETIME;
-       }
-
-       if (timespecisset(&ia->acquired)) {
+       } else if (timespecisset(&ia->acquired)) {
                ia->prefix_pltime = lifetime_left(ia->prefix_pltime,
                    &ia->acquired, now);
                ia->prefix_vltime = lifetime_left(ia->prefix_vltime,
@@ -2274,13 +2272,10 @@ inet6_raroutes(rb_tree_t *routes, struct dhcpcd_ctx *ctx)
        const struct routeinfo *rinfo;
        const struct ipv6_addr *addr;
        struct in6_addr netmask;
-       struct timespec now;
 
        if (ctx->ra_routers == NULL)
                return 0;
 
-       timespecclear(&now);
-
        TAILQ_FOREACH(rap, ctx->ra_routers, next) {
                if (rap->expired)
                        continue;
@@ -2302,8 +2297,8 @@ inet6_raroutes(rb_tree_t *routes, struct dhcpcd_ctx *ctx)
                        rt->rt_pref = ipv6nd_rtpref(rinfo->flags);
 #endif
 #ifdef HAVE_ROUTE_LIFETIME
-                       rt->rt_lifetime = lifetime_left(rinfo->lifetime,
-                           &rinfo->acquired, &now);
+                       rt->rt_aquired = rinfo->acquired;
+                       rt->rt_lifetime = rinfo->lifetime,
 #endif
                        rt_proto_add(routes, rt);
                }
@@ -2319,9 +2314,8 @@ inet6_raroutes(rb_tree_t *routes, struct dhcpcd_ctx *ctx)
                                rt->rt_pref = ipv6nd_rtpref(rap->flags);
 #endif
 #ifdef HAVE_ROUTE_LIFETIME
-                               rt->rt_lifetime =
-                                   lifetime_left(addr->prefix_vltime,
-                                   &addr->acquired, &now);
+                               rt->rt_aquired = addr->acquired;
+                               rt->rt_lifetime = addr->prefix_vltime;
 #endif
 
                                rt_proto_add(routes, rt);
@@ -2356,8 +2350,8 @@ inet6_raroutes(rb_tree_t *routes, struct dhcpcd_ctx *ctx)
                rt->rt_pref = ipv6nd_rtpref(rap->flags);
 #endif
 #ifdef HAVE_ROUTE_LIFETIME
-               rt->rt_lifetime = lifetime_left(rap->lifetime,
-                   &rap->acquired, &now);
+               rt->rt_aquired = rap->acquired;
+               rt->rt_lifetime = rap->lifetime;
 #endif
 
                rt_proto_add(routes, rt);
@@ -2395,6 +2389,10 @@ inet6_dhcproutes(rb_tree_t *routes, struct dhcpcd_ctx *ctx,
                        if (rt == NULL)
                                continue;
                        rt->rt_dflags |= RTDF_DHCP;
+#ifdef HAVE_ROUTE_LIFETIME
+                       rt->rt_aquired = ia->acquired;
+                       rt->rt_lifetime = ia->prefix_vltime;
+#endif
                        rt_proto_add(routes, rt);
                }
        }
index 4e1a536eab24c6f1a3130905c0c4939afd5a7f0b..fe3423dda9dd7816e138ba54d83bf50a99a7fdd6 100644 (file)
@@ -148,6 +148,7 @@ __CTASSERT(sizeof(struct nd_opt_dnssl) == 8);
 static void ipv6nd_handledata(void *, unsigned short);
 static struct routeinfo *routeinfo_findalloc(struct ra *, const struct in6_addr *, uint8_t);
 static void routeinfohead_free(struct routeinfohead *);
+static void ipv6nd_startrs2(void *);
 
 /*
  * Android ships buggy ICMP6 filter headers.
@@ -1497,6 +1498,8 @@ nodhcp6:
        /* Expire should be called last as the rap object could be destroyed */
        ipv6nd_expirera(ifp);
 #undef FREE_RAP
+
+       eloop_timeout_add_sec(ifp->ctx->eloop, 5, ipv6nd_startrs2, ifp);
 }
 
 bool
index bbc7bfd7faedc3ac94af86844158fdd6a435e29a..4d08da7e1e747c19476879fc9e06e3221689f77c 100644 (file)
@@ -521,12 +521,19 @@ rt_cmp_misc(struct rt *nrt, struct rt *ort)
 #endif
 
 #ifdef HAVE_ROUTE_LIFETIME
-       uint32_t deviation;
-
        /* There might be a minor difference between kernel route
         * lifetime and our lifetime due to processing times.
         * We allow a small deviation to avoid needless route changes.
-        * dhcpcd will expire the route regardless of route lifetime support. */
+        * dhcpcd will expire the route regardless of route lifetime support.
+        */
+       struct timespec ts;
+       uint32_t deviation;
+
+       timespecsub(&nrt->rt_aquired, &ort->rt_aquired, &ts);
+       if (ts.tv_sec < 0)
+               ts.tv_sec = -ts.tv_sec;
+       if (ts.tv_sec > RTLIFETIME_DEV_MAX)
+               return false;
        if (nrt->rt_lifetime > ort->rt_lifetime)
                deviation = nrt->rt_lifetime - ort->rt_lifetime;
        else
index 5c06d1da786bb9a10f526e94101790d62e78a2e1..2c85b90f4fb55b4aefdb7062d5dbcf8689402698 100644 (file)
@@ -126,6 +126,7 @@ struct rt {
        size_t                  rt_order;
        rb_node_t               rt_tree;
 #ifdef HAVE_ROUTE_LIFETIME
+       struct timespec         rt_aquired;     /* timestamp of aquisition */
        uint32_t                rt_lifetime;    /* current lifetime of route */
 #define        RTLIFETIME_DEV_MAX      2               /* max deviation for cmp */
 #endif