diff mbox

[net-next,1/2] ipv6: introduce per-interface counter for dad-completed ipv6 addresses

Message ID 20130626220656.GA20845@order.stressinduktion.org
State Accepted, archived
Delegated to: David Miller
Headers show

Commit Message

Hannes Frederic Sowa June 26, 2013, 10:06 p.m. UTC
To reduce the number of unnecessary router solicitations, MLDv2 and IGMPv3
messages we need to track the number of valid (as in non-optimistic,
no-dad-failed and non-tentative) link-local addresses. Therefore, this
patch implements a valid_ll_addr_cnt in struct inet6_dev.

We now only emit router solicitations if the first link-local address
finishes duplicate address detection.

The changes for MLDv2 and IGMPv3 are in a follow-up patch.

While there, also simplify one if statement(one minor nit I made in one
of my previous patches):

if (!...)
	do();
else
	return;

<<into>>

if (...)
	return;
do();

Cc: Flavio Leitner <fbl@redhat.com>
Cc: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Cc: David Stevens <dlstevens@us.ibm.com>
Suggested-by: David Stevens <dlstevens@us.ibm.com>
Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
---
 include/net/if_inet6.h |  1 +
 net/ipv6/addrconf.c    | 39 +++++++++++++++++++++++++++++++--------
 2 files changed, 32 insertions(+), 8 deletions(-)

Comments

Flavio Leitner June 27, 2013, 10:02 p.m. UTC | #1
On Thu, Jun 27, 2013 at 12:06:56AM +0200, Hannes Frederic Sowa wrote:
> To reduce the number of unnecessary router solicitations, MLDv2 and IGMPv3
> messages we need to track the number of valid (as in non-optimistic,
> no-dad-failed and non-tentative) link-local addresses. Therefore, this
> patch implements a valid_ll_addr_cnt in struct inet6_dev.
> 
> We now only emit router solicitations if the first link-local address
> finishes duplicate address detection.
> 
> The changes for MLDv2 and IGMPv3 are in a follow-up patch.
> 
> While there, also simplify one if statement(one minor nit I made in one
> of my previous patches):
> 
> if (!...)
> 	do();
> else
> 	return;
> 
> <<into>>
> 
> if (...)
> 	return;
> do();
> 
> Cc: Flavio Leitner <fbl@redhat.com>
> Cc: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
> Cc: David Stevens <dlstevens@us.ibm.com>
> Suggested-by: David Stevens <dlstevens@us.ibm.com>
> Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
> ---

Looks good and works here.
thanks,
Acked-by: Flavio Leitner <fbl@redhat.com>

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Miller June 29, 2013, 4:19 a.m. UTC | #2
From: Flavio Leitner <fbl@redhat.com>
Date: Thu, 27 Jun 2013 19:02:36 -0300

> On Thu, Jun 27, 2013 at 12:06:56AM +0200, Hannes Frederic Sowa wrote:
>> To reduce the number of unnecessary router solicitations, MLDv2 and IGMPv3
>> messages we need to track the number of valid (as in non-optimistic,
>> no-dad-failed and non-tentative) link-local addresses. Therefore, this
>> patch implements a valid_ll_addr_cnt in struct inet6_dev.
>> 
>> We now only emit router solicitations if the first link-local address
>> finishes duplicate address detection.
>> 
>> The changes for MLDv2 and IGMPv3 are in a follow-up patch.
>> 
>> While there, also simplify one if statement(one minor nit I made in one
>> of my previous patches):
>> 
>> if (!...)
>> 	do();
>> else
>> 	return;
>> 
>> <<into>>
>> 
>> if (...)
>> 	return;
>> do();
>> 
>> Cc: Flavio Leitner <fbl@redhat.com>
>> Cc: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
>> Cc: David Stevens <dlstevens@us.ibm.com>
>> Suggested-by: David Stevens <dlstevens@us.ibm.com>
>> Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
>> ---
> 
> Looks good and works here.
> thanks,
> Acked-by: Flavio Leitner <fbl@redhat.com>

Applied.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h
index e4c5a2d..1628b8f 100644
--- a/include/net/if_inet6.h
+++ b/include/net/if_inet6.h
@@ -166,6 +166,7 @@  struct inet6_dev {
 	struct net_device	*dev;
 
 	struct list_head	addr_list;
+	int			valid_ll_addr_cnt;
 
 	struct ifmcaddr6	*mc_list;
 	struct ifmcaddr6	*mc_tomb;
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index afaf3cd..7044785 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -3277,6 +3277,7 @@  static void addrconf_dad_completed(struct inet6_ifaddr *ifp)
 {
 	struct net_device *dev = ifp->idev->dev;
 	struct in6_addr lladdr;
+	bool send_rs;
 
 	addrconf_del_dad_timer(ifp);
 
@@ -3290,20 +3291,25 @@  static void addrconf_dad_completed(struct inet6_ifaddr *ifp)
 	   router advertisements, start sending router solicitations.
 	 */
 
-	if (ipv6_accept_ra(ifp->idev) &&
-	    ifp->idev->cnf.rtr_solicits > 0 &&
-	    (dev->flags&IFF_LOOPBACK) == 0 &&
-	    (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL)) {
+	read_lock_bh(&ifp->idev->lock);
+	spin_lock(&ifp->lock);
+	send_rs = ipv6_accept_ra(ifp->idev) &&
+		  ifp->idev->cnf.rtr_solicits > 0 &&
+		  (dev->flags&IFF_LOOPBACK) == 0 &&
+		  ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL &&
+		  ifp->idev->valid_ll_addr_cnt == 1;
+	spin_unlock(&ifp->lock);
+	read_unlock_bh(&ifp->idev->lock);
+
+	if (send_rs) {
 		/*
 		 *	If a host as already performed a random delay
 		 *	[...] as part of DAD [...] there is no need
 		 *	to delay again before sending the first RS
 		 */
-		if (!ipv6_get_lladdr(dev, &lladdr, IFA_F_TENTATIVE))
-			ndisc_send_rs(dev, &lladdr,
-				      &in6addr_linklocal_allrouters);
-		else
+		if (ipv6_get_lladdr(dev, &lladdr, IFA_F_TENTATIVE))
 			return;
+		ndisc_send_rs(dev, &lladdr, &in6addr_linklocal_allrouters);
 
 		write_lock_bh(&ifp->idev->lock);
 		spin_lock(&ifp->lock);
@@ -4573,6 +4579,19 @@  errout:
 		rtnl_set_sk_err(net, RTNLGRP_IPV6_PREFIX, err);
 }
 
+static void update_valid_ll_addr_cnt(struct inet6_ifaddr *ifp, int count)
+{
+	write_lock_bh(&ifp->idev->lock);
+	spin_lock(&ifp->lock);
+	if (((ifp->flags & (IFA_F_PERMANENT|IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|
+			    IFA_F_DADFAILED)) == IFA_F_PERMANENT) &&
+	    (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL))
+		ifp->idev->valid_ll_addr_cnt += count;
+	WARN_ON(ifp->idev->valid_ll_addr_cnt < 0);
+	spin_unlock(&ifp->lock);
+	write_unlock_bh(&ifp->idev->lock);
+}
+
 static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
 {
 	struct net *net = dev_net(ifp->idev->dev);
@@ -4581,6 +4600,8 @@  static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
 
 	switch (event) {
 	case RTM_NEWADDR:
+		update_valid_ll_addr_cnt(ifp, 1);
+
 		/*
 		 * If the address was optimistic
 		 * we inserted the route at the start of
@@ -4596,6 +4617,8 @@  static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
 					      ifp->idev->dev, 0, 0);
 		break;
 	case RTM_DELADDR:
+		update_valid_ll_addr_cnt(ifp, -1);
+
 		if (ifp->idev->cnf.forwarding)
 			addrconf_leave_anycast(ifp);
 		addrconf_leave_solict(ifp->idev, &ifp->addr);