Linux多网卡bond中的几种mode

来源:岁月联盟 编辑:exp 时间:2011-10-13

一、      文档目的
编写本文档主要为了介绍以及整理bond中几种mode,为了方便以后工作查看而整理。

二、      文档内容
随着科学技术的日益革新,数据的安全性已经逐渐体现出了它的重要意义。可以设想,当一个人所有的个人资料都不负存在,那是多么可怕的事情。网络技术的深入使用,数据的网络化传输已经成为了重要,甚至主要的传输方式。所以数据服务器能够正常提供网络服务是所有供应商都需要考虑的问题。

在这个背景下,单网卡的应用已经捉襟见肘,设备冗余技术的普及已是枝繁叶茂。本文之后就引用Linux操作系统下的多网卡bonding技术来阐述这一容错概念。

负载均衡功能也是网卡bonding的另一个功能,它可以实现多网卡同时工作,提高系统网络处理的吞吐能力。

一、网卡的负载均衡模式(mode = BOND_MODE_ROUNDROBIN)

 

1)建立bond虚设备

 

建立一个ifcfg-bond0的设备,然后配置如下信息即可。

 

DEVICE=bond0

 

BOOTPROTO=static

 

IPADDR=172.16.64.208

 

NETMASK=255.255.224.0

 

ONBOOT=yes

 

TYPE=Ethernet

 

2)配置接口文件

 

由于使用一个虚拟的ip地址,所以,其他接口设备都不配置ip信息。

 

3)配置bonding工作方式

 

打开/etc/modprobe.conf文件,将bonding的工作模式配置为如下模式。

 

alias bond0bonding

 

optionsbond0  mode=0 arp_interval=500arp_ip_target=172.16.64.86

 

4)启动bonding

 

需要添加路由来制定发送规则,这个可以自定义添加。配置完后重启设备即可。

 

ifenslave bond0eth0 eth1

 

route add -net0/0 gw 172.16.64.254

 

bond0     Link encap:Ethernet  HWaddr 00:14:10:70:00:25

 

          inet addr:172.16.64.208  Bcast:172.16.95.255  Mask:255.255.224.0

 

          inet6 addr: fe80::200:ff:fe00:0/64Scope:Link

 

          UP BROADCAST RUNNING MASTERMULTICAST  MTU:1500  Metric:1

 

          RX packets:39335 errors:0 dropped:0overruns:0 frame:0

 

          TX packets:3178 errors:0 dropped:0overruns:0 carrier:0

 

          collisions:0 txqueuelen:0

 

          RX bytes:3020656 (2.8 MiB)  TX bytes:269722 (263.4 KiB)

 

eth0      Link encap:Ethernet  HWaddr 00:14:10:70:00:25

 

          UP BROADCAST RUNNING SLAVEMULTICAST  MTU:1500  Metric:1

 

          RX packets:18208 errors:0 dropped:0overruns:0 frame:0

 

          TX packets:5 errors:0 dropped:0overruns:0 carrier:0

 

          collisions:0 txqueuelen:1000

 

          RX bytes:1371589 (1.3 MiB)  TX bytes:378 (378.0 b)

 

eth1      Link encap:Ethernet  HWaddr 00:14:10:70:00:25

 

          UP BROADCAST RUNNING SLAVE MULTICAST  MTU:1500 Metric:1

 

          RX packets:21128 errors:0 dropped:0overruns:0 frame:0

 

          TX packets:3174 errors:0 dropped:0overruns:0 carrier:0

 

          collisions:0 txqueuelen:100

 

          RX bytes:1649127 (1.5 MiB)  TX bytes:269498 (263.1 KiB)

 

       如上图所示,这种模式下bonding模块会将虚接口和所有的slave接口的MAC地址设置为一致。通过定时器,每个slave接口不断发送ARP包来不断更换交换机端口与MAC的对应关系。

 

       这样使得每个网卡都在进行工作。这个ARP的发送规则是:

 

              每arp_interval(MS)间隔向arp_ip_target发送arp请求。也可以向多个arp_ip_target发送arp请求。

 

       观察交换机端口上所学习到的MAC地址,发现MAC会在两个端口上反复切换。

 

       在BOND_MODE_ROUNDROBIN模式下,bonding对于发送和接收数据的处理逻辑是不一致的,对于数据的接收,bonding基本不做任何处理,纯粹依靠交换机端口与MAC的变化来实现交替接收数据。发送的话,交换机会根据数据的源MAC来学习端口和MAC之间的关系,所以bonding做到的就是选择不一样的网卡发送。

 

       对于数据的发送,

 

       static inline voidbond_set_mode_ops(struct net_device *bond_dev, int mode)

 

       {

 

                switch(mode) {

 

                case  BOND_MODE_ROUNDROBIN:

 

                          bond_dev->hard_start_xmit =bond_xmit_roundrobin;

 

                          break;

 

                ...

 

        bond的发送函数被注册为bond_xmit_roundrobin。通过bond_xmit_roundrobin的实现可以发现

 

       static int bond_xmit_roundrobin(structsk_buff *skb, struct net_device *bond_dev)

 

       {

 

                  read_lock(&bond->curr_slave_lock);

 

                 slave = start_at = bond->curr_active_slave;

 

              read_unlock(&bond->curr_slave_lock);

 

                bond_for_each_slave_from(bond, slave, i,start_at) {

 

                 if(IS_UP(slave->dev) &&

 

                          (slave->link == BOND_LINK_UP) &&

 

                            (slave->state ==BOND_STATE_ACTIVE)) {

 

                     res =bond_dev_queue_xmit(bond, skb, slave->dev);

 

                     write_lock(&bond->curr_slave_lock);

 

                     bond->curr_active_slave= slave->next;

 

                     write_unlock(&bond->curr_slave_lock);

 

                     break;

 

       }

 

       bond_xmit_roundrobin会通过curr_active_slave指针所指向的设备来进行发送,当然curr_active_slave会在调用bond_dev_queue_xmit完成实际的发送之后指向下一个slave设备。bond_dev_queue_xmit实际是调用通用的发送函数dev_queue_xmit来进行的,它传递给dev_queue_xmit的是一个skb,在传递之前skb->dev就被指定为了当前的slave设备,这样内核就会找到对应的真实网卡设备来进行发送,最后curr_active_slave指针的轮询切换,实现了bonding的负载均衡工作模式。

 

       从这种模式可以看到,bonding实现了一个类似网卡驱动的模块,对应的bond0设备是一个纯粹的虚设备,数据发送虽然说经过了它,但通过一系列调用,转了一圈之后才回到真正的网卡设备那里进行发送,无疑会消耗一定的系统性能。

 

       简单用100Mbps速率的UDP数据包测试了一下BOND_MODE_ROUNDROBIN模式。

 

       测试过程中发现接收端会有较多的乱序包,观察交换机端口情况,端口之间的切换频率不规则,这个和交换机的配置或者性能应该有很大联系,有必要的话需要进一步研究。数据的正确性和时序性能否保证需要进一步仔细测试。

 

2、网卡的容错模式(mode =BOND_MODE_ACTIVEBACKUP)

 

       容错模式的配置方法和负载均衡模式基本差不多,只不过修改一下/etc/modprobe.conf即可。

 

       alias bond0 bonding

 

       options bond0  mode=1 miimon=100

 

       这里使用的是mii链路检测方式,与之前arp检测方式不同。当然这两种链路检测方式在各种mode下都是可以使用的,但要注意不能同时使用。

 

       介绍一下bonding的mii检测实现。首先和arp-monitor一样,mii也是定时器触发

 

      if(bond->params.miimon) {  /* link checkinterval, in milliseconds. */

 

                 init_timer(mii_timer);

 

                 mii_timer->expires  = jiffies + 1;

 

                mii_timer->data     = (unsigned long)bond_dev;

 

                mii_timer->function = (void*)&bond_mii_monitor;

 

                 add_timer(mii_timer);

 

      }

 

       bond_mii_monitor函数其本质的原理就是检测网卡的链路状态,bonding定义网卡有4个链路状态:

 

       BOND_LINK_UP:        正常状态(处于该状态的网卡是是潜在的发送数据包的候选者)

 

       BOND_LINK_FAIL:      网卡出现故障,向状态BOND_LINK_DOWN 切换中

 

       BOND_LINK_DOWN:      失效状态

 

       BOND_LINK_BACK:        网卡恢复,向状态BOND_LINK_UP切换中

 

       从上到下,表示了网卡链路从正常到失效再到恢复状态。bond_mii_monitor函数就是依次检查网卡的链路状态是否处于这些状态,然后通过标记do_failover变量来说明当前是否需要切换slave网卡。代码篇幅较大,但逻辑还是很清晰的,故此处不罗列了。

 

       在BOND_MODE_ACTIVEBACKUP模式下,两块网卡其实有一块是不工作的,被设置为IFF_NOARP的状态。同时,bond虚设备,还有slave设备的MAC地址均一致,所以这张网卡不会被外界察觉存在。交换机也不存在想该端口发包的情况。当bond的mii检测发现当前的active设备失效了之后,会切换到这个备份设备上。

 

       在bond_change_active_slave函数中

 

       if (bond->params.mode ==BOND_MODE_ACTIVEBACKUP) {

 

              if (old_active) {

 

                     bond_set_slave_inactive_flags(old_active);

 

              }

 

              if (new_active) {

 

                     bond_set_slave_active_flags(new_active);

 

              }

 

       }

 

       这个就是在BOND_MODE_ACTIVEBACKUP模式下的切换逻辑,很简单,需要注意的是,在bond_set_slave_inactive_flags(old_active)中,需要将接口的状态设置为IFF_NOARP,不然交换机就可能会把数据包发送到一个错误的端口上。

 

       BOND_MODE_ACTIVEBACKUP模式下的数据发送非常简单,可想而知curr_active_slave指针始终都指向当前可用的设备,所以直接发送就可以,没有之前BOND_MODE_ROUNDROBIN模式下slave设备切换的过程。

 

3、网卡虚拟化方式(mode = BOND_MODE_ALB)

 

       经过考察,许多磁盘阵列设备采用了网卡虚拟化方式进行多网卡应用。实际就是Linux的bonding技术。它采用了mode = BOND_MODE_ALB的方式。

 

BOND_MODE_ALB的实现方式比较复杂,还有一些不理解的地方,就不做深入分析了。其核心思想可以用下图解释:

 

 

       从这个图中可以看到,客户端A与服务器的传输使用的是MACA;而客户端B与服务器传输使用的是MAC B,但对于IP层来说,客户端A与B都与服务器X.X.X.X 的IP地址进行通讯,并不感知底层传输接口的变化。这样,服务器对于客户端整体上的工作模式就处于负载均衡的状态。当然,这个过程的控制就是bonding模块所完成的。

 

       通过测试发现两台客户端展现的arp表是一致的,如下(服务器端地址为172.16.64.208,服务器端首选接口的MAC为00-14-10-70-00-25)

 

CLIENT A

 

172.16.64.208         00-14-10-70-00-25     dynamic

 

CLIENT B

 

172.16.64.208         00-14-10-70-00-25     dynamic

 

通过抓包可以看到,两次回复的ARP应答的源MAC地址是不一样的,分别为

 

00-14-10-70-00-25和

 

00-14-10-70-00-26。

 

       所以说,能够实现这种处理方法的原因就是bonding修改了ARP应答的源地址导致,使得外界并不感知服务器存在多网卡的状态,在网络上确定了IP和MAC的唯一对应关系,保证了上层业务传输的逻辑一致性。同时内部的处理又交给不同的网卡,实现了负载均衡。

 

       另外,也给了我们一定的容错性,当一个接口失效后,bonding会迅速将另外一块网卡设置为首选slave设备,并修改其MAC地址。由于外界学习到的服务器MAC地址始终是不变的,所以链路的状态不会受很大影响。

 

 

 

 

 

 

 

Bonding的模式一共有7种:

#defineBOND_MODE_ROUNDROBIN       0   (balance-rr模式)网卡的负载均衡模式

#defineBOND_MODE_ACTIVEBACKUP     1   (active-backup模式)网卡的容错模式

#defineBOND_MODE_XOR              2   (balance-xor模式)需要交换机支持

#defineBOND_MODE_BROADCAST        3    (broadcast模式)

#defineBOND_MODE_8023AD           4   (IEEE 802.3ad动态链路聚合模式)需要交换机支持

#defineBOND_MODE_TLB              5   自适应传输负载均衡模式

#defineBOND_MODE_ALB              6   网卡虚拟化方式

 bonding模块的所有工作模式可以分为两类:多主型工作模式和主备型工作模式,balance-rr 和broadcast属于多主型工作模式而active-backup属于主备型工作模式。(balance-xor、自适应传输负载均衡模式(balance-tlb)和自适应负载均衡模式(balance-alb)也属于多主型工作模式,IEEE 802.3ad动态链路聚合模式(802.3ad)属于主备型工作模式