Skip to contentSkip to conversation

ipv6: recreate ipv6 link-local addresses when increasing MTU over IPV6_MIN_MTU

PATCH In review Hannes Frederic Sowa 5 participants 12 messages Oct 26, 2015 – Oct 30, 2015

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 ipv6: recreate ipv6 link-local addresses when increasing MTU over IPV6_MIN_MTU

Take into consideration that the interface might be disabled for IPv6, thus switch event type.

---
 net/ipv6/addrconf.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)
net/ipv6/addrconf.c +5 -2
index d0c685c..c2dcebe 100644
@@ -3149,6 +3149,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
 
 	case NETDEV_UP:
 	case NETDEV_CHANGE:
+netdev_change:
 		if (dev->flags & IFF_SLAVE)
 			break;
 
@@ -3244,8 +3245,10 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
 
 		if (!idev && dev->mtu >= IPV6_MIN_MTU) {
 			idev = ipv6_add_dev(dev);
-			if (!IS_ERR(idev))
-				break;
+			if (!IS_ERR(idev)) {
+				event = NETDEV_UP;
+				goto netdev_change;
+			}
 		}
 
 		/*
Signature · 1 line
2.5.0
#1 lore raw
Quoted 23 lines · Hannes Frederic Sowa

Take into consideration that the interface might be disabled for IPv6, thus switch event type.

---
  net/ipv6/addrconf.c | 7 +++++--
  1 file changed, 5 insertions(+), 2 deletions(-)
net/ipv6/addrconf.c +1 -0
index d0c685c..c2dcebe 100644
@@ -3149,6 +3149,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
 
  	case NETDEV_UP:
  	case NETDEV_CHANGE:
+netdev_change:
  		if (dev->flags & IFF_SLAVE)
  			break;
 
@@ -3244,8 +3245,10 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
 
  		if (!idev && dev->mtu >= IPV6_MIN_MTU) {

net/ipv6/addrconf.c static int addrconf_notify(struct notifier_block *this, unsigned long event, · line 3254

Quoted 10 lines
net/ipv6/addrconf.c +4 -2
  			idev = ipv6_add_dev(dev);
-			if (!IS_ERR(idev))
-				break;
+			if (!IS_ERR(idev)) {
+				event = NETDEV_UP;
+				goto netdev_change;
+			}
  		}
 
  		/*

Seems like this code isn't quite correct. You are calling ipv6_add_dev for slave devices, and if I understand things correctly I don't believe that was happening before and may be an unintended side effect.

You might want to instead just make it so that you only do the jump, and perhaps change the code in the NETDEV_UP/NETDEV_CHANGE section so that you test for NETDEV_CHANGE instead of NETDEV_UP. That should be enough to get the effect you are looking for and I believe there would be no change to behaviour other than adding IPv6 link-local addresses when the MTU is increased.

Give me a bit and I can submit an alternative that may actually work out a bit better I think.

- Alex

#2 lore raw

Hi Alex,

Quoted 33 lines · Alexander Duyck
Quoted 32 lines · Hannes Frederic Sowa

Take into consideration that the interface might be disabled for IPv6, thus switch event type.

---
  net/ipv6/addrconf.c | 7 +++++--
  1 file changed, 5 insertions(+), 2 deletions(-)
net/ipv6/addrconf.c +5 -2
index d0c685c..c2dcebe 100644
@@ -3149,6 +3149,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
 
  	case NETDEV_UP:
  	case NETDEV_CHANGE:
+netdev_change:
  		if (dev->flags & IFF_SLAVE)
  			break;
 
@@ -3244,8 +3245,10 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
 
  		if (!idev && dev->mtu >= IPV6_MIN_MTU) {
  			idev = ipv6_add_dev(dev);
-			if (!IS_ERR(idev))
-				break;
+			if (!IS_ERR(idev)) {
+				event = NETDEV_UP;
+				goto netdev_change;
+			}
  		}
 
Quoted 5 lines

net/ipv6/addrconf.c static int addrconf_notify(struct notifier_block *this, unsigned long event, · line 3254

Quoted 1 line
net/ipv6/addrconf.c +0 -0
  		/*

Seems like this code isn't quite correct. You are calling ipv6_add_dev for slave devices, and if I understand things correctly I don't believe that was happening before and may be an unintended side effect.

Hmm, could you quickly help me where I get into this situation? I made sure I enter the NETDEV_UP part before the IFF_SLAVE test and disable_ipv6 test.

Quoted 9 lines

You might want to instead just make it so that you only do the jump, and perhaps change the code in the NETDEV_UP/NETDEV_CHANGE section so that you test for NETDEV_CHANGE instead of NETDEV_UP. That should be enough to get the effect you are looking for and I believe there would be no change to behaviour other than adding IPv6 link-local addresses when the MTU is increased.

Give me a bit and I can submit an alternative that may actually work out a bit better I think.

If you go the NETDEV_CHANGE route instead of NETDEV_UP, you end up with the IF_READY flag already set from ipv6_add_dev and thus won't do any initialization of the device.

Sure, I wait.

Bye,
Hannes

#3 lore raw
Quoted 36 lines · Hannes Frederic Sowa

Hi Alex,

Quoted 33 lines · Alexander Duyck
Quoted 32 lines · Hannes Frederic Sowa

Take into consideration that the interface might be disabled for IPv6, thus switch event type.

---
   net/ipv6/addrconf.c | 7 +++++--
   1 file changed, 5 insertions(+), 2 deletions(-)
net/ipv6/addrconf.c +5 -2
index d0c685c..c2dcebe 100644
@@ -3149,6 +3149,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
 
   	case NETDEV_UP:
   	case NETDEV_CHANGE:
+netdev_change:
   		if (dev->flags & IFF_SLAVE)
   			break;
 
@@ -3244,8 +3245,10 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
 
   		if (!idev && dev->mtu >= IPV6_MIN_MTU) {
   			idev = ipv6_add_dev(dev);
-			if (!IS_ERR(idev))
-				break;
+			if (!IS_ERR(idev)) {
+				event = NETDEV_UP;
+				goto netdev_change;
+			}
   		}
 
Quoted 7 lines
Quoted 4 lines

net/ipv6/addrconf.c static int addrconf_notify(struct notifier_block *this, unsigned long event, · line 3254

Quoted 1 line
net/ipv6/addrconf.c +0 -0
   		/*

Seems like this code isn't quite correct. You are calling ipv6_add_dev for slave devices, and if I understand things correctly I don't believe that was happening before and may be an unintended side effect.

Hmm, could you quickly help me where I get into this situation? I made sure I enter the NETDEV_UP part before the IFF_SLAVE test and disable_ipv6 te

I think I was getting a bit a head of myself. I was looking over the NETDEV_UP code and thinking that we could just fall into that path since it is already calling ipv6_add_dev. However now I am wondering if maybe we need to look at adding an idev allocation somewhere before the disable_ipv6 check. I assume that is why you were allocating the idev before you were getting into NETDEV_UP?

Quoted 7 lines
Quoted 7 lines

You might want to instead just make it so that you only do the jump, and perhaps change the code in the NETDEV_UP/NETDEV_CHANGE section so that you test for NETDEV_CHANGE instead of NETDEV_UP. That should be enough to get the effect you are looking for and I believe there would be no change to behaviour other than adding IPv6 link-local addresses when the MTU is increased.

Quoted 5 lines
Quoted 2 lines

Give me a bit and I can submit an alternative that may actually work out a bit better I think.

If you go the NETDEV_CHANGE route instead of NETDEV_UP, you end up with the IF_READY flag already set from ipv6_add_dev and thus won't do any initialization of the device.

What I meant was that you don't need to change the event. If you change the check inside the NETDEV_UP/CHANGE code path so that it tests for event != NETDEV_CHANGE instead of event == NETDEV_UP you don't need to change the event type.

Quoted 1 line

Sure, I wait.

Might be a bit longer. I just realized that I think there is another bug here where you are going through the NETDEV_UP path even though the interface isn't up. I'll run through some testing this morning to work out the kinks.

- Alex

#4 lore raw

Hi Alex,

Quoted 7 lines · Alexander Duyck
Quoted 6 lines
Quoted 3 lines

Seems like this code isn't quite correct. You are calling ipv6_add_dev for slave devices, and if I understand things correctly I don't believe that was happening before and may be an unintended side effect.

Hmm, could you quickly help me where I get into this situation? I made sure I enter the NETDEV_UP part before the IFF_SLAVE test and disable_ipv6 te

Quoted 6 lines

I think I was getting a bit a head of myself. I was looking over the NETDEV_UP code and thinking that we could just fall into that path since it is already calling ipv6_add_dev. However now I am wondering if maybe we need to look at adding an idev allocation somewhere before the disable_ipv6 check. I assume that is why you were allocating the idev before you were getting into NETDEV_UP?

The original bug report was:

If user reduces the MTU below IPV6_MIN_MTU we addrconf_ifdown the interface but don't reinitialize the interface if the MTU is increased later on.

Quoted 9 lines
Quoted 9 lines
Quoted 9 lines

You might want to instead just make it so that you only do the jump, and perhaps change the code in the NETDEV_UP/NETDEV_CHANGE section so that you test for NETDEV_CHANGE instead of NETDEV_UP. That should be enough to get the effect you are looking for and I believe there would be no change to behaviour other than adding IPv6 link-local addresses when the MTU is increased.

Give me a bit and I can submit an alternative that may actually work out a bit better I think.

Quoted 8 lines
Quoted 3 lines

If you go the NETDEV_CHANGE route instead of NETDEV_UP, you end up with the IF_READY flag already set from ipv6_add_dev and thus won't do any initialization of the device.

What I meant was that you don't need to change the event. If you change the check inside the NETDEV_UP/CHANGE code path so that it tests for event != NETDEV_CHANGE instead of event == NETDEV_UP you don't need to change the event type.

Yeah, that would be possible, too. I just find an equal easier to follow. ;)

Quoted 6 lines
Quoted 1 line

Sure, I wait.

Might be a bit longer. I just realized that I think there is another bug here where you are going through the NETDEV_UP path even though the interface isn't up. I'll run through some testing this morning to work out the kinks.

Ok, cool. I have a look at it again, too.

Bye,
Hannes

#5 lore raw
In reply to Alexander Duyck

Hi Alex,

Quoted 4 lines · Alexander Duyck

Might be a bit longer. I just realized that I think there is another bug here where you are going through the NETDEV_UP path even though the interface isn't up. I'll run through some testing this morning to work out the kinks.

When you wrote this, I noticed that if someone removes the LL addresses to disable the interface and raises the MTU again, we would also start adding link-local addresses. Probably we need to safe the last state of disable_ipv6 somewhere in the parent interface. :(

Maybe there is an easier solution for that.

Thanks for your patch, it looks cleaner!

Bye,
Hannes

#6 lore raw
In reply to Alexander Duyck

Hello Alex,

Quoted 3 lines · Alexander Duyck

Seems like this code isn't quite correct. You are calling ipv6_add_dev for slave devices, and if I understand things correctly I don't believe that was happening before and may be an unintended side effect.

Ah, btw., autoconf and ipv6 operation on IFF_SLAVE devices is actually desired nowadays and don't think we can change this. See also:
<https://patchwork.ozlabs.org/patch/531196/>

Bye,
Hannes

#7 lore raw
Quoted 10 lines · Hannes Frederic Sowa

Hello Alex,

Quoted 3 lines · Alexander Duyck

Seems like this code isn't quite correct. You are calling ipv6_add_dev for slave devices, and if I understand things correctly I don't believe that was happening before and may be an unintended side effect.

Ah, btw., autoconf and ipv6 operation on IFF_SLAVE devices is actually desired nowadays and don't think we can change this. See also:
<https://patchwork.ozlabs.org/patch/531196/>

IPv6 addrconf on IFF_SLAVE devices was disabled for bonding
slaves in commit c2edacf80e15 because it caused issues with snooping switches.

This is also referenced in

https://bugzilla.redhat.com/show_bug.cgi?id=236750

Won't re-enabling autoconf on IFF_SLAVE devices cause that issue
to return?

	-J

---
-Jay Vosburgh, [email protected]

#8 lore raw

Hi,

Quoted 17 lines · Jay Vosburgh
Quoted 10 lines · Hannes Frederic Sowa

Hello Alex,

Quoted 3 lines · Alexander Duyck

Seems like this code isn't quite correct. You are calling ipv6_add_dev for slave devices, and if I understand things correctly I don't believe that was happening before and may be an unintended side effect.

Ah, btw., autoconf and ipv6 operation on IFF_SLAVE devices is actually desired nowadays and don't think we can change this. See also:
<https://patchwork.ozlabs.org/patch/531196/>

IPv6 addrconf on IFF_SLAVE devices was disabled for bonding
slaves in commit c2edacf80e15 because it caused issues with snooping switches.

Quoted 6 lines

This is also referenced in

https://bugzilla.redhat.com/show_bug.cgi?id=236750

Won't re-enabling autoconf on IFF_SLAVE devices cause that issue
to return?

Both patches don't enable autoconf on IFF_SLAVE devices. Sorry for being imprecise. The referred patch was changing the behavior to whether the device had a master device.

@Alex, I will take your patch and submit it with the necessary guards to not enable ipv6 again if we forcefully disable ipv6 and later on shrink and increase the MTU again. I will do so in your name. Thanks again for the patch!

Bye,
Hannes

#9 lore raw
Quoted 20 lines · Hannes Frederic Sowa

Hi,

Quoted 17 lines · Jay Vosburgh
Quoted 9 lines · Hannes Frederic Sowa

Hello Alex,

Quoted 3 lines · Alexander Duyck

Seems like this code isn't quite correct. You are calling ipv6_add_dev for slave devices, and if I understand things correctly I don't believe that was happening before and may be an unintended side effect.

Ah, btw., autoconf and ipv6 operation on IFF_SLAVE devices is actually desired nowadays and don't think we can change this. See also:
<https://patchwork.ozlabs.org/patch/531196/>

IPv6 addrconf on IFF_SLAVE devices was disabled for bonding
slaves in commit c2edacf80e15 because it caused issues with snooping switches.

This is also referenced in

Quoted 7 lines
Quoted 4 lines

https://bugzilla.redhat.com/show_bug.cgi?id=236750

Won't re-enabling autoconf on IFF_SLAVE devices cause that issue
to return?

Both patches don't enable autoconf on IFF_SLAVE devices. Sorry for being imprecise. The referred patch was changing the behavior to whether the device had a master device.

Yes, the IFF_SLAVE comment on my part was an error in interpretation of the code.

Quoted 4 lines

@Alex, I will take your patch and submit it with the necessary guards to not enable ipv6 again if we forcefully disable ipv6 and later on shrink and increase the MTU again. I will do so in your name. Thanks again for the patch!

No problem. If you want to you can take over authorship of the patch and just leave my signed-off-by on there. I'm good either way.

- Alex

#10 lore raw

PATCH v2 1/1 ipv6: recreate ipv6 link-local addresses when increasing MTU over IPV6_MIN_MTU

In reply to Hannes Frederic Sowa

This change makes it so that we reinitialize the interface if the MTU is increased back above IPV6_MIN_MTU and the interface is up.

Cc Hannes Frederic Sowa <[email protected]>
---
 net/ipv6/addrconf.c |   46 +++++++++++++++++++++++++++-------------------
 1 file changed, 27 insertions(+), 19 deletions(-)
net/ipv6/addrconf.c +27 -19
index d0c685cdc345..d72fa90d6feb 100644
@@ -3147,6 +3147,32 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
 		}
 		break;
 
+	case NETDEV_CHANGEMTU:
+		/* if MTU under IPV6_MIN_MTU stop IPv6 on this interface. */
+		if (dev->mtu < IPV6_MIN_MTU) {
+			addrconf_ifdown(dev, 1);
+			break;
+		}
+
+		if (idev) {
+			rt6_mtu_change(dev, dev->mtu);
+			idev->cnf.mtu6 = dev->mtu;
+			break;
+		}
+
+		/* allocate new idev */
+		idev = ipv6_add_dev(dev);
+		if (IS_ERR(idev))
+			break;
+
+		/* device is still not ready */
+		if (!(idev->if_flags & IF_READY))
+			break;
+
+		run_pending = 1;
+
+		/* fall through */
+
 	case NETDEV_UP:
 	case NETDEV_CHANGE:
 		if (dev->flags & IFF_SLAVE)
@@ -3170,7 +3196,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
 				idev->if_flags |= IF_READY;
 				run_pending = 1;
 			}
-		} else {
+		} else if (event == NETDEV_CHANGE) {
 			if (!addrconf_qdisc_ok(dev)) {
 				/* device is still not ready. */
 				break;
@@ -3235,24 +3261,6 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
 		}
 		break;
 
-	case NETDEV_CHANGEMTU:
-		if (idev && dev->mtu >= IPV6_MIN_MTU) {
-			rt6_mtu_change(dev, dev->mtu);
-			idev->cnf.mtu6 = dev->mtu;
-			break;
-		}
-
-		if (!idev && dev->mtu >= IPV6_MIN_MTU) {
-			idev = ipv6_add_dev(dev);
-			if (!IS_ERR(idev))
-				break;
-		}
-
-		/*
-		 * if MTU under IPV6_MIN_MTU.
-		 * Stop IPv6 on this interface.
-		 */
-
 	case NETDEV_DOWN:
 	case NETDEV_UNREGISTER:
 		/*