[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