Subject: Bonding and Neighbour Discovery on IPv6-only devices

From: Alex Sidorenko <[email-masked]>
Date: Mon, 15 Sep 2008 13:35:16 -0400

Hello,

I suspect that there are some problems while switching slaves manually on 
IPv6-only bonds. I have tested that this does not work on 2.6.18 kernel 
(RHEL5). I looked at recent sources (2.6.26) and even though there were 
multiple changes in bonding code, I still don't see how this could work.

Testing setup
-------------

Two ethernets enslaved (eth2 and eh3), active-backup bond has IPv6-only 
address (no IPv4)

Everything works fine, but if we switch the slave doing

# ifenslave -c bond0 eth3

the incoming ping6 to this host stops for up to several minutes (waiting until 
the switch updates its caches).

Analysis
--------

Switching slaves invokes bond_change_active_slave(). In case of IPv4, we send 
gratuitous ARP doing bond_send_gratuitous_arp(). This informs switches that 
our active slave has changed, they update their ARP-tables and there is no 
delay.

In case of IPv6 only I would have expected NS-packet to be sent (doing the 
same work as gratuitous ARP). But testing shows that there are no packets 
sent when we switch the slave (checked both by network traces and just 
looking at the number of RX/TX packets per interface). So the switches are 
unaware that active slave has changed and we have a delay.

Inspecting the sources, I hoped that we'll send NS as a result of migrating 
multicast addresses from one slave to another doing bond_mc_swap() and then 
doing bond_resend_igmp_join_requests(). But this does not work either:

bond_mc_swap() tries to swap link-multicasts only (bond->dev->mc_list), but 
this does not work as we have users=2 and dev_mc_delete() does not delete 
addresses in this case. Here is what I see on slaves and bond (eth2 is 
active, ip maddr show):

2:      eth2
        link  33:33:00:00:00:fb users 2
        link  33:33:ff:5c:fd:de users 2
        link  33:33:00:00:00:01 users 2
        inet6 ff02::fb
        inet6 ff02::1:ff5c:fdde
        inet6 ff02::1
3:      eth3
        link  33:33:00:00:00:fb
        link  33:33:ff:5c:fd:de
        link  33:33:00:00:00:01
        inet6 ff02::fb
        inet6 ff02::1:ff5c:fdde
        inet6 ff02::1
<snip>
7:      bond0
        link  33:33:00:00:00:fb
        link  33:33:ff:5c:fd:de
        link  33:33:00:00:00:01
        inet6 ff02::fb
        inet6 ff02::1:ff5c:fdde users 2
        inet6 ff02::1

bond_resend_igmp_join_requests() works for IP-device only, not IPv6 - so once 
again, this does not help.

So how is it supposed to work for IPv6-only case? Please note that I am 
talking about switching slaves via 'ifenslave -c', not disconnecting the 
cable (in the latter case the switch will see carrier lost and we'll change 
the slave device state sending an event).

Once again, the testing was done on a rather old (2.6.18) kernel, so I 
apologize if this is already fixed in 2.6.26 (in this case I would appreciate 
if you briefly explain how this works).

Regards,
Alex
-- 
------------------------------------------------------------------
Alexandre Sidorenko             email: [email-masked]
Global Solutions Engineering:   Unix Networking
Hewlett-Packard (Canada)
------------------------------------------------------------------