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

Mark Smith radvd at 02a76c927861ca7413a122f2a73a0d37.nosense.org
Fri Mar 25 00:36:25 EDT 2011


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;
 





-------------- next part --------------
A non-text attachment was scrubbed...
Name: DecreaseLifetimes.patch
Type: text/x-patch
Size: 8367 bytes
Desc: not available
URL: <http://lists.litech.org/pipermail/radvd-devel-l/attachments/20110325/819b2752/attachment.bin>


More information about the radvd-devel-l mailing list