[radvd-devel-l] DecrementLifetimes option

Reuben Hawkins reubenhwk at gmail.com
Mon Apr 4 10:30:16 EDT 2011


On Sun, Apr 3, 2011 at 1:57 AM, Mark Smith <
radvd at 02a76c927861ca7413a122f2a73a0d37.nosense.org> wrote:

> Hi,
>
> This is an updated version of the DecrementLifetimes option I posted
> for comments a few weeks ago. I think it is ready to commit. Here is
> the manual page text -
>
>       DecrementLifetimes on|off
>
>              This  option  causes  radvd  to decrement the values of
>              the pre‐ ferred and valid lifetimes for the prefix over
>              time.  The  life‐ times  are  decremented  by the number
>              of seconds since the last RA. If radvd receives a SIGUSR1
>              signal, it will reset the values of  the preferred and
>              valid lifetimes back to the initial values used by radvd
>              when it started. If radvd never receives a SIGUSR1
>              signal,  it  will  continue to decrement the lifetimes
>              until the preferred lifetime reaches zero. After a final
>              RA  with  a  zero value  preferred lifetime, radvd will
>              cease to announce the pre‐ fix. If a SIGUSR1 signal then
>              causes the lifetimes to be  reset, the prefix will then
>              re-appear in the RAs.
>
>              This  option is intended to be used in conjunction with a
>              DHCPv6 client that is using the Identity Association for
>              Prefix Delega‐ tion  (IA_PD) option to acquire a prefix
>              for use by a Requesting Router. In this scenario, the
>              prefix(es) from within  the  delegated  prefix that are
>              announced by radvd should age in parallel with and at the
>              same rate as the delegated prefix, and expire at
>              approximately  the  same  time,  if  the delegated
>              prefix's life isn't extended by the DHCPv6 server.
>
>              See RFC3633, "IPv6 Prefix Options for Dynamic Host
>              Configuration Protocol  (DHCP)  version 6", specifically
>              the Requesting Router sections.
>
> The updates were -
>
> o  some routine renaming
> o  use time_t for timeval seconds calculations
> o  call gettimeofday() per RA, not per prefix
> o  manual page text
>
> It should apply cleanly to cvs revision 1.116. Attached and shown below.
>
> Thanks,
> Mark.
>
>
> diff --git a/defaults.h b/defaults.h
> index 059cbd5..66c5b55 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 3c648fe..52ce610 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
> @@ -605,11 +606,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 ';'
> @@ -619,17 +622,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 54265ec..4c37748 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.conf.5.man b/radvd.conf.5.man
> index a8f1e7b..182ff65 100644
> --- a/radvd.conf.5.man
> +++ b/radvd.conf.5.man
> @@ -432,6 +432,17 @@ See RFC4862, section 5.5.3., "Router Advertisement
> Processing", part (e).
>  Default: off
>
>  .TP
> +.BR DecrementLifetimes " " on | off
> +
> +This option causes radvd to decrement the values of the preferred and
> valid lifetimes for the prefix over time. The lifetimes are decremented by
> the number of seconds since the last RA. If radvd receives a SIGUSR1 signal,
> it will reset the values of the preferred and valid lifetimes back to the
> initial values used by radvd when it started. If radvd never receives a
> SIGUSR1 signal, it will continue to decrement the lifetimes until the
> preferred lifetime reaches zero. After a final RA with a zero value
> preferred lifetime, radvd will cease to announce the prefix. If a SIGUSR1
> signal then causes the lifetimes to be reset, the prefix will then re-appear
> in the RAs.
> +
> +This option is intended to be used in conjunction with a DHCPv6 client
> that is using the Identity Association for Prefix Delegation (IA_PD) option
> to acquire a prefix from a Delegating Router for use by a Requesting Router.
> In this scenario, the prefix(es) from within the delegated prefix that are
> announced by radvd would age in parallel with and at the same rate as the
> delegated prefix, and expire at approximately the same time, if the
> delegated prefix's life isn't extended.
> +
> +See RFC3633, "IPv6 Prefix Options for Dynamic Host Configuration Protocol
> (DHCP) version 6".
> +
> +Default: off
> +
> +.TP
>  .BR "Base6Interface " name
>
>  If this options is specified, this prefix will be combined with the
> diff --git a/radvd.h b/radvd.h
> index 8ea9460..a154ff5 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;
> @@ -180,6 +186,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 21f5b5b..142bba9 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 6d45403..a5dda18 100644
> --- a/send.c
> +++ b/send.c
> @@ -77,6 +77,29 @@ send_ra_inc_len(size_t *len, int add)
>        }
>  }
>
> +static time_t time_diff_secs(const struct timeval *time_x,
> +                            const struct timeval *time_y)
> +{
> +       time_t secs_diff;
> +
> +       secs_diff = time_x->tv_sec - time_y->tv_sec;
> +       if ((time_x->tv_usec - time_y->tv_usec) >= 500000)
> +               secs_diff++;
> +
> +       return secs_diff;
> +
> +}
> +
> +static void decrement_lifetime(const time_t secs, uint32_t *lifetime)
> +{
> +
> +       if (*lifetime > secs) {
> +               *lifetime -= secs;
> +       } else {
> +               *lifetime = 0;
> +       }
> +}
> +
>  int
>  send_ra(struct Interface *iface, struct in6_addr *dest)
>  {
> @@ -92,6 +115,8 @@ send_ra(struct Interface *iface, struct in6_addr *dest)
>        struct AdvRoute *route;
>        struct AdvRDNSS *rdnss;
>        struct AdvDNSSL *dnssl;
> +       struct timeval time_now;
> +       time_t secs_since_last_ra;
>
>        unsigned char buff[MSG_SIZE_SEND];
>        size_t len = 0;
> @@ -134,6 +159,14 @@ send_ra(struct Interface *iface, struct in6_addr
> *dest)
>                gettimeofday(&iface->last_multicast, NULL);
>        }
>
> +       gettimeofday(&time_now, NULL);
> +       secs_since_last_ra = time_diff_secs(&time_now,
> &iface->last_ra_time);
> +       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 +210,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 +233,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,

It looks like everything is working.  I applied the patch.  If you would
like to submit another patch with a some logging, I'll apply it too.  I'd
like to see in the logs, with dlog(LOG_DEBUG, 4,... ), the updated current
and valid lifetimes with the prefix text and with dlog(LOG_DEBUG, 3,... ),
when the prefix times out.

Check CVS to make sure you patch applied correctly.

Thanks,
Reuben
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.litech.org/pipermail/radvd-devel-l/attachments/20110404/53ef698c/attachment-0001.html>


More information about the radvd-devel-l mailing list