diff mbox

ipv6:remove ipv6 global address after the interface is down

Message ID 533A8737.8050108@gmail.com
State Not Applicable, archived
Delegated to: David Miller
Headers show

Commit Message

Zhu Yanjun April 1, 2014, 9:30 a.m. UTC
Hi, Paul

With kernel 2.6.34.x, the following problem will appear.

  TargetA ------------------------- TargetB
3000::1/64 3000::2/64

  TargetA
    - bring the interface down by doing an "ifconfig eth1 down"
    - bring the interface back up by doing an "ifconfig eth1 up"

TargetB
    - ping6 3000::1
       ping6 succeeds the first time
    - after bringing the interface on TargetA down and then back up, 
ping6 to the interface fails.

With the latest mainline kernel(3.4+), this problem is resolved. When 
eth1 is down, ipv6 address and route item are removed.
But with kernel 2.6.34.x, when eth1 is down, ipv6 address remains while 
route item is removed.

So when eth1 is up and assign the previous ipv6 address, with 2.6.34.x, 
some errors will appear. But with latest mainline kernel, it can work well.

So I made a patch to fix this problem in kernel 2.6.34.x. Please merge 
this to kernel2.6.34.x.

Thanks a lot.
Zhu Yanjun

Comments

Hannes Frederic Sowa April 1, 2014, 9:35 a.m. UTC | #1
On Tue, Apr 01, 2014 at 05:30:31PM +0800, zhuyj wrote:
> Hi, Paul
> 
> With kernel 2.6.34.x, the following problem will appear.
> 
>  TargetA ------------------------- TargetB
> 3000::1/64 3000::2/64
> 
>  TargetA
>    - bring the interface down by doing an "ifconfig eth1 down"
>    - bring the interface back up by doing an "ifconfig eth1 up"
> 
> TargetB
>    - ping6 3000::1
>       ping6 succeeds the first time
>    - after bringing the interface on TargetA down and then back up, 
> ping6 to the interface fails.
> 
> With the latest mainline kernel(3.4+), this problem is resolved. When 
> eth1 is down, ipv6 address and route item are removed.
> But with kernel 2.6.34.x, when eth1 is down, ipv6 address remains while 
> route item is removed.
> 
> So when eth1 is up and assign the previous ipv6 address, with 2.6.34.x, 
> some errors will appear. But with latest mainline kernel, it can work well.
> 
> So I made a patch to fix this problem in kernel 2.6.34.x. Please merge 
> this to kernel2.6.34.x.

2.6.34 stable is EOL and won't get updated anymore. If this is problem is also
present in other, still maintained, stable kernel this would be possible.

Can you identify the upstream commit which repaired this problem and when it
got introduced?

Thanks,

  Hannes

--
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
Zhu Yanjun April 1, 2014, 10:12 a.m. UTC | #2
On 04/01/2014 05:35 PM, Hannes Frederic Sowa wrote:
> On Tue, Apr 01, 2014 at 05:30:31PM +0800, zhuyj wrote:
>> Hi, Paul
>>
>> With kernel 2.6.34.x, the following problem will appear.
>>
>>   TargetA ------------------------- TargetB
>> 3000::1/64 3000::2/64
>>
>>   TargetA
>>     - bring the interface down by doing an "ifconfig eth1 down"
>>     - bring the interface back up by doing an "ifconfig eth1 up"
>>
>> TargetB
>>     - ping6 3000::1
>>        ping6 succeeds the first time
>>     - after bringing the interface on TargetA down and then back up,
>> ping6 to the interface fails.
>>
>> With the latest mainline kernel(3.4+), this problem is resolved. When
>> eth1 is down, ipv6 address and route item are removed.
>> But with kernel 2.6.34.x, when eth1 is down, ipv6 address remains while
>> route item is removed.
>>
>> So when eth1 is up and assign the previous ipv6 address, with 2.6.34.x,
>> some errors will appear. But with latest mainline kernel, it can work well.
>>
>> So I made a patch to fix this problem in kernel 2.6.34.x. Please merge
>> this to kernel2.6.34.x.
> 2.6.34 stable is EOL and won't get updated anymore. If this is problem is also
> present in other, still maintained, stable kernel this would be possible.
Hi, Hannes

It is fortunate. I checked other stable kernel. They can work well. 
Maybe this patch can only fix the problem on 2.6.34.x.

>
> Can you identify the upstream commit which repaired this problem and when it
> got introduced?
commit 73a8bd74 [ipv6:Revert 'administrative down' address handling 
changes] can fix this problem.

Best Regards!
Zhu Yanjun
>
> Thanks,
>
>    Hannes
>
>

--
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

From 4eb7dd9180bcbd7b8196f9e5e6f5db638de799e7 Mon Sep 17 00:00:00 2001
From: yanjun.zhu <yanjun.zhu@windriver.com>
Date: Tue, 1 Apr 2014 17:09:11 +0800
Subject: [PATCH 1/1] ipv6:remove ipv6 global address after the interface is down

2.6.34.x kernels require a similar logic change as commit 73a8bd74
[ipv6:Revert 'administrative down' address handling changes]
introduces for newer kernels.

In 2.6.34.x kernels, when an interface with ipv6 global address is
restarted, the ipv6 route item disappear, but ipv6 global address
still remains. Compared with kernel versions 3.4+, the ipv6 global
address and route item should both disappear. To be consistent with
kernel versions 3.4+, we remove ipv6 address from the interface that
is shutdown.

Signed-off-by: yanjun.zhu <yanjun.zhu@windriver.com>
---
 net/ipv6/addrconf.c |   39 ++++-----------------------------------
 1 files changed, 4 insertions(+), 35 deletions(-)

diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 2b82070..6fd29fb 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -2624,7 +2624,7 @@  static void addrconf_bonding_change(struct net_device *dev, unsigned long event)
 static int addrconf_ifdown(struct net_device *dev, int how)
 {
 	struct inet6_dev *idev;
-	struct inet6_ifaddr *ifa, *keep_list, **bifa;
+	struct inet6_ifaddr *ifa, **bifa;
 	struct net *net = dev_net(dev);
 	int i;
 
@@ -2657,9 +2657,7 @@  static int addrconf_ifdown(struct net_device *dev, int how)
 
 		write_lock_bh(&addrconf_hash_lock);
 		while ((ifa = *bifa) != NULL) {
-			if (ifa->idev == idev &&
-			    (how || !(ifa->flags&IFA_F_PERMANENT) ||
-			     ipv6_addr_type(&ifa->addr) & IPV6_ADDR_LINKLOCAL)) {
+			if (ifa->idev == idev){
 				*bifa = ifa->lst_next;
 				ifa->lst_next = NULL;
 				__in6_ifa_put(ifa);
@@ -2698,40 +2696,12 @@  static int addrconf_ifdown(struct net_device *dev, int how)
 		write_lock_bh(&idev->lock);
 	}
 #endif
-	keep_list = NULL;
-	bifa = &keep_list;
 	while ((ifa = idev->addr_list) != NULL) {
 		idev->addr_list = ifa->if_next;
 		ifa->if_next = NULL;
 
 		addrconf_del_timer(ifa);
-
-		/* If just doing link down, and address is permanent
-		   and not link-local, then retain it. */
-		if (how == 0 &&
-		    (ifa->flags&IFA_F_PERMANENT) &&
-		    !(ipv6_addr_type(&ifa->addr) & IPV6_ADDR_LINKLOCAL)) {
-
-			/* Move to holding list */
-			*bifa = ifa;
-			bifa = &ifa->if_next;
-
-			/* If not doing DAD on this address, just keep it. */
-			if ((dev->flags&(IFF_NOARP|IFF_LOOPBACK)) ||
-			    idev->cnf.accept_dad <= 0 ||
-			    (ifa->flags & IFA_F_NODAD))
-				continue;
-
-			/* If it was tentative already, no need to notify */
-			if (ifa->flags & IFA_F_TENTATIVE)
-				continue;
-
-			/* Flag it for later restoration when link comes up */
-			ifa->flags |= IFA_F_TENTATIVE;
-			in6_ifa_hold(ifa);
-		} else {
-			ifa->dead = 1;
-		}
+		ifa->dead = 1;
 		write_unlock_bh(&idev->lock);
 
 		__ipv6_ifa_notify(RTM_DELADDR, ifa);
@@ -2743,8 +2713,7 @@  static int addrconf_ifdown(struct net_device *dev, int how)
 		write_lock_bh(&idev->lock);
 	}
 
-	idev->addr_list = keep_list;
-
+	idev->addr_list = NULL;
 	write_unlock_bh(&idev->lock);
 
 	/* Step 5: Discard multicast list */
-- 
1.7.3.5