[radvd-devel-l] request for comments - DecreaseLifetimes option

Pekka Savola pekkas at netcore.fi
Mon Mar 28 01:30:40 EDT 2011


I will observe that I'm aware of only one RFC 4861 S 6.2 
implementation that supports "lifetimes decreasing in real time" -- 
rtadvd.  I have vague recollection of hearing about this in the 
context of Solaris, but I can't check that.

So, this is not a very widely used feature and not mandated by 
specifications.


On Sun, 27 Mar 2011, Reuben Hawkins wrote:
> On Thu, Mar 24, 2011 at 9:36 PM, Mark Smith <radvd at 02a76c927861ca7413a122f2a73a0d37.nosense.org> wrote:
>       Hi,
>
>       This option is a bit more complicated than the last ones. It provides
>       an option to have radvd decrease the preferred and valid lifetime
>       values of specified prefixes over time. This would be used in
>       conjunction with prefixes supplied by DHCPv6 based Prefix Delegation
>       (DHCPv6-PD). The sequence of events would be as follows -
>
>       1. Initial DHCPv6-PD transaction takes place over a e.g. WAN interface
>       of the router, and a delegated prefix e.g. a /56 is acquired, with e.g.
>       a preferred lifetime of 14400 seconds and a valid lifetime of 86400
>       seconds.
>
>       2. A /64 is taken from within the delegated prefix, for use on the LAN
>       interface of the router.
>
>       3. A radvd configuration is built with to announce this prefix, with
>       preferred and valid lifetimes of 14400 and 86400 seconds respectively,
>       and a prefix DecreaseLifetimes option.
>
>       4. For each RA, either solicited or unsolicited, the preferred and
>       valid lifetimes are decreased by the number of seconds since the last
>       RA.
>
>       5. At time "T1" the DHCPv6-PD client will attempt to renew the
>       delegated prefix. If the delegated prefix is renewed successfully, with
>       the same preferred and valid lifetimes, the DHCPv6-PD client sends a
>       USR1 signal to radvd. This causes radvd to reset the announced preferred
>       and valid lifetimes back to the lifetime values specified in it's
>       configuration file, and then continue to decrease them for each
>       RA. If the delegated prefix either doesn't renew successfully, or has
>       different preferred and valid lifetimes, then the DHCPv6-PD client will
>       have to stop radvd, generate a new configuration for it and start it
>       again.
>
>       6. If radvd never receives the USR1 signal, it will continue to
>       decrease the lifetimes until the preferred lifetime reaches 0.
>       After an announcement of the prefix with a 0 preferred lifetime, radvd
>       then stops announcing that prefix. If it subsequently receives a USR1
>       signal, it will then start announcing the prefix again, with the
>       lifetimes starting back at the specified initial values.
>
>       I'm interested in comments on the following patch. If people are happy
>       with the approach, I'll finish it off by e.g. adding manual page
>       entries.
>
>       Attached and shown below, it should apply to cvs revision 1.115.
> 
>
>       Thanks,
>       Mark.
> 
>
>       diff --git a/defaults.h b/defaults.h
>       index e09a659..d17cb6f 100644
>       --- a/defaults.h
>       +++ b/defaults.h
>       @@ -57,6 +57,7 @@
>        #define DFLT_AdvPreferredLifetime      14400 /* seconds */
>        #define DFLT_AdvAutonomousFlag         1
>        #define DFLT_DeprecatePrefixFlag       0
>       +#define DFLT_DecrementLifetimesFlag    0
>
>        /* Each route has an associated: */
>        #define DFLT_AdvRouteLifetime(iface)   (3 * (iface)->MaxRtrAdvInterval)
>       diff --git a/gram.y b/gram.y
>       index 4c74cc8..eb7fb0d 100644
>       --- a/gram.y
>       +++ b/gram.y
>       @@ -96,6 +96,7 @@ static struct in6_addr get_prefix6(struct in6_addr const *addr, struct in6_addr
>        %token         T_AdvValidLifetime
>        %token         T_AdvPreferredLifetime
>        %token         T_DeprecatePrefix
>       +%token         T_DecrementLifetimes
>
>        %token         T_AdvRouterAddr
>        %token         T_AdvHomeAgentFlag
>       @@ -604,11 +605,13 @@ prefixparms       : T_AdvOnLink SWITCH ';'
>                                              struct AdvPrefix *p = prefix;
>                                              do {
>                                                      p->AdvValidLifetime = $2;
>       +                                               p->curr_validlft = $2;
>                                                      p = p->next;
>                                              } while (p && p->AutoSelected);
>                                      }
>                                      else
>                                              prefix->AdvValidLifetime = $2;
>       +                                       prefix->curr_validlft = $2;
>                              }
>                      }
>                      | T_AdvPreferredLifetime number_or_infinity ';'
>       @@ -618,17 +621,23 @@ prefixparms       : T_AdvOnLink SWITCH ';'
>                                              struct AdvPrefix *p = prefix;
>                                              do {
>                                                      p->AdvPreferredLifetime = $2;
>       +                                               p->curr_preferredlft = $2;
>                                                      p = p->next;
>                                              } while (p && p->AutoSelected);
>                                      }
>                                      else
>                                              prefix->AdvPreferredLifetime = $2;
>       +                                       prefix->curr_preferredlft = $2;
>                              }
>                      }
>                      | T_DeprecatePrefix SWITCH ';'
>                      {
>                              prefix->DeprecatePrefixFlag = $2;
>                      }
>       +               | T_DecrementLifetimes SWITCH ';'
>       +               {
>       +                       prefix->DecrementLifetimesFlag = $2;
>       +               }
>                      | T_Base6Interface name ';'
>                      {
>                              if (prefix) {
>       diff --git a/interface.c b/interface.c
>       index 0e6f672..4ffdbf1 100644
>       --- a/interface.c
>       +++ b/interface.c
>       @@ -58,8 +58,12 @@ prefix_init_defaults(struct AdvPrefix *prefix)
>              prefix->AdvValidLifetime = DFLT_AdvValidLifetime;
>              prefix->AdvPreferredLifetime = DFLT_AdvPreferredLifetime;
>              prefix->DeprecatePrefixFlag = DFLT_DeprecatePrefixFlag;
>       +       prefix->DecrementLifetimesFlag = DFLT_DecrementLifetimesFlag;
>              prefix->if6to4[0] = 0;
>              prefix->enabled = 1;
>       +
>       +       prefix->curr_validlft = prefix->AdvValidLifetime;
>       +       prefix->curr_preferredlft = prefix->AdvPreferredLifetime;
>        }
>
>        void
>       diff --git a/process.c b/process.c
>       index 570911f..3cbebce 100644
>       --- a/process.c
>       +++ b/process.c
>       @@ -333,7 +333,7 @@ process_ra(struct Interface *iface, unsigned char *msg, int len,
>                                      {
>                                              print_addr(&prefix->Prefix, prefix_str);
>
>       -                                       if (valid != prefix->AdvValidLifetime)
>       +                                       if (!prefix->DecrementLifetimesFlag && valid != prefix->AdvValidLifetime)
>                                              {
>                                                      flog(LOG_WARNING, "our AdvValidLifetime on"
>                                                       " %s for %s doesn't agree with %s",
>       @@ -342,7 +342,7 @@ process_ra(struct Interface *iface, unsigned char *msg, int len,
>                                                       addr_str
>                                                       );
>                                              }
>       -                                       if (preferred != prefix->AdvPreferredLifetime)
>       +                                       if (!prefix->DecrementLifetimesFlag && preferred !=
>       prefix->AdvPreferredLifetime)
>                                              {
>                                                      flog(LOG_WARNING, "our AdvPreferredLifetime on"
>                                                       " %s for %s doesn't agree with %s",
>       diff --git a/radvd.c b/radvd.c
>       index 09a6fbe..fe88d79 100644
>       --- a/radvd.c
>       +++ b/radvd.c
>       @@ -78,10 +78,12 @@ int sock = -1;
>        volatile int sighup_received = 0;
>        volatile int sigterm_received = 0;
>        volatile int sigint_received = 0;
>       +volatile int sigusr1_received = 0;
>
>        void sighup_handler(int sig);
>        void sigterm_handler(int sig);
>        void sigint_handler(int sig);
>       +void sigusr1_handler(int sig);
>        void timer_handler(void *data);
>        void config_interface(void);
>        void kickoff_adverts(void);
>       @@ -339,6 +341,7 @@ main(int argc, char *argv[])
>              signal(SIGHUP, sighup_handler);
>              signal(SIGTERM, sigterm_handler);
>              signal(SIGINT, sigint_handler);
>       +       signal(SIGUSR1, sigusr1_handler);
>
>              snprintf(pidstr, sizeof(pidstr), "%ld\n", (long)getpid());
>
>       @@ -446,6 +449,13 @@ void main_loop(void)
>                              reload_config();
>                              sighup_received = 0;
>                      }
>       +
>       +               if (sigusr1_received)
>       +               {
>       +                       reset_prefix_lifetimes();
>       +                       sigusr1_received = 0;
>       +               }
>       +
>              }
>        }
>
>       @@ -502,6 +512,9 @@ kickoff_adverts(void)
>              {
>                      double next;
>
>       +
>       +               gettimeofday(&iface->last_ra_time, NULL);
>       +
>                      if( iface->UnicastOnly )
>                              continue;
>
>       @@ -667,6 +680,45 @@ sigint_handler(int sig)
>              }
>        }
>
>       +
>       +void reset_prefix_lifetimes(void)
>       +{
>       +       struct Interface *iface;
>       +       struct AdvPrefix *prefix;
>       +
>       +
>       +       flog(LOG_INFO, "Resetting prefix lifetimes\n");
>       +
>       +       for (iface = IfaceList; iface; iface = iface->next)
>       +       {
>       +               for (prefix = iface->AdvPrefixList; prefix;
>       +                                                       prefix = prefix->next)
>       +               {
>       +                       if (prefix->DecrementLifetimesFlag)
>       +                       {
>       +                               prefix->curr_validlft =
>       +                                               prefix->AdvValidLifetime;
>       +                               prefix->curr_preferredlft =
>       +                                               prefix->AdvPreferredLifetime;
>       +                       }
>       +               }
>       +
>       +       }
>       +
>       +}
>       +
>       +void sigusr1_handler(int sig)
>       +{
>       +
>       +       /* Linux has "one-shot" signals, reinstall the signal handler */
>       +       signal(SIGUSR1, sigusr1_handler);
>       +
>       +       dlog(LOG_DEBUG, 4, "sigusr1_handler called");
>       +
>       +       sigusr1_received = 1;
>       +
>       +}
>       +
>        int
>        drop_root_privileges(const char *username)
>        {
>       diff --git a/radvd.h b/radvd.h
>       index 16638fa..78e92b1 100644
>       --- a/radvd.h
>       +++ b/radvd.h
>       @@ -49,6 +49,8 @@ struct Interface {
>
>              int                     cease_adv;
>
>       +       struct timeval          last_ra_time;
>       +
>              int                     IgnoreIfMissing;
>              int                     AdvSendAdvert;
>              double                  MaxRtrAdvInterval;
>       @@ -103,6 +105,10 @@ struct AdvPrefix {
>              uint32_t                AdvValidLifetime;
>              uint32_t                AdvPreferredLifetime;
>              int                     DeprecatePrefixFlag;
>       +       int                     DecrementLifetimesFlag;
>       +
>       +       uint32_t                curr_validlft;
>       +       uint32_t                curr_preferredlft;
>
>              /* Mobile IPv6 extensions */
>              int                     AdvRouterAddr;
>       @@ -179,6 +185,7 @@ int yylex(void);
>        /* radvd.c */
>        int check_ip6_forwarding(void);
>        void reload_config(void);
>       +void reset_prefix_lifetimes(void);
>
>        /* timer.c */
>        struct timeval next_timeval(double next);
>       diff --git a/scanner.l b/scanner.l
>       index 77106cf..a413b30 100644
>       --- a/scanner.l
>       +++ b/scanner.l
>       @@ -70,6 +70,7 @@ AdvAutonomous         { return T_AdvAutonomous; }
>        AdvValidLifetime       { return T_AdvValidLifetime; }
>        AdvPreferredLifetime   { return T_AdvPreferredLifetime; }
>        DeprecatePrefix                { return T_DeprecatePrefix; }
>       +DecrementLifetimes     { return T_DecrementLifetimes; }
>
>        AdvRouterAddr          { return T_AdvRouterAddr; }
>        AdvHomeAgentFlag       { return T_AdvHomeAgentFlag; }
>       diff --git a/send.c b/send.c
>       index 5ff5b5b..6dd9a25 100644
>       --- a/send.c
>       +++ b/send.c
>       @@ -77,6 +77,16 @@ send_ra_inc_len(size_t *len, int add)
>              }
>        }
>
>       +static void decrement_lifetime(const long int secs, uint32_t *lifetime)
>       +{
>       +
>       +       if (*lifetime > secs) {
>       +               *lifetime -= secs;
>       +       } else {
>       +               *lifetime = 0;
>       +       }
>       +}
>       +
>        int
>        send_ra(struct Interface *iface, struct in6_addr *dest)
>        {
>       @@ -92,6 +102,8 @@ send_ra(struct Interface *iface, struct in6_addr *dest)
>              struct AdvRoute *route;
>              struct AdvRDNSS *rdnss;
>              struct AdvDNSSL *dnssl;
>       +       struct timeval time_now;
>       +       long int secs_since_last_ra;
>
>              unsigned char buff[MSG_SIZE_SEND];
>              size_t len = 0;
>       @@ -134,6 +146,14 @@ send_ra(struct Interface *iface, struct in6_addr *dest)
>                      gettimeofday(&iface->last_multicast, NULL);
>              }
>
>       +       gettimeofday(&time_now, NULL);
>       +       secs_since_last_ra = time_now.tv_sec - iface->last_ra_time.tv_sec;
>       +       if (secs_since_last_ra < 0) {
>       +               secs_since_last_ra = 0;
>       +               flog(LOG_WARNING, "gettimeofday() went backwards!");
>       +       }
>       +       iface->last_ra_time = time_now;
>       +
>              memset((void *)&addr, 0, sizeof(addr));
>              addr.sin6_family = AF_INET6;
>              addr.sin6_port = htons(IPPROTO_ICMPV6);
>       @@ -177,7 +197,7 @@ send_ra(struct Interface *iface, struct in6_addr *dest)
>
>              while(prefix)
>              {
>       -               if( prefix->enabled )
>       +               if( prefix->enabled && prefix->curr_preferredlft > 0 )
>                      {
>                              struct nd_opt_prefix_info *pinfo;
>
>       @@ -200,9 +220,16 @@ send_ra(struct Interface *iface, struct in6_addr *dest)
>                                      pinfo->nd_opt_pi_valid_time     = htonl(MIN_AdvValidLifetime);
>                                      pinfo->nd_opt_pi_preferred_time = 0;
>                              } else {
>       +                               if (prefix->DecrementLifetimesFlag) {
>       +                                       decrement_lifetime(secs_since_last_ra,
>       +                                                               &prefix->curr_validlft);
>       +
>       +                                       decrement_lifetime(secs_since_last_ra,
>       +                                                               &prefix->curr_preferredlft);
>       +                               }
>       +                               pinfo->nd_opt_pi_valid_time     = htonl(prefix->curr_validlft);
>       +                               pinfo->nd_opt_pi_preferred_time = htonl(prefix->curr_preferredlft);
>
>       -                               pinfo->nd_opt_pi_valid_time     = htonl(prefix->AdvValidLifetime);
>       -                               pinfo->nd_opt_pi_preferred_time = htonl(prefix->AdvPreferredLifetime);
>                              }
>                              pinfo->nd_opt_pi_reserved2      = 0;
> 
> 
> 
> 
> 
> 
>
>       --
>       radvd-devel-l mailing list  :  radvd-devel-l at litech.org
>       http://lists.litech.org/listinfo/radvd-devel-l
> 
> 
> 
> Hi Mark,
> 
> I'm not too enthusiastic about this patch for a few reasons.  I don't like the idea of an advert being dependent on time. 
> Although it's subtle, it makes debugging and/or reproducing a bug more difficult.  However, this is called for in section 6.2.1
> of RFC 2461 under AdvPreferredLifetime and AdvValidLifetime.
> 
> As such, please continue to test this for a while.  Make sure it's working.  If there's no objections to committing this, I'll
> commit it in a few weeks.
> 
> Thanks,
> Reuben
> 
>

-- 
Pekka Savola                 "You each name yourselves king, yet the
Netcore Oy                    kingdom bleeds."
Systems. Networks. Security. -- George R.R. Martin: A Clash of Kings


More information about the radvd-devel-l mailing list