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

Reuben Hawkins reubenhwk at gmail.com
Sun Mar 27 20:15:55 EDT 2011


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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.litech.org/pipermail/radvd-devel-l/attachments/20110327/cd4d8443/attachment-0001.html>


More information about the radvd-devel-l mailing list