[百度分享]Bonding 模块代码及主要工作模式分析(2)

baiduforum 2010-05-20 10:09:06
5. 代码分析

1. 关键数据结构

1. struct bond_params

文件:driver/net/bonding/Bonding.h

该结构是全局结构(每系统一个),对应于加载bonding模块时传入的各个参数

主要成员:
名称 类型 含义
mode int Bonding模块工作模式

BOND_MODE_ROUNDROBIN balance-rr模式

BOND_MODE_ACTIVEBACKUP active-backup模式

BOND_MODE_XOR balance-xor模式

BOND_MODE_BROADCAST broadcast模式

BOND_MODE_8023AD IEEE 802.3ad动态链路聚合模式

BOND_MODE_TLB 自适应传输负载均衡模式

BOND_MODE_ALB 自适应负载均衡模式
miimon int 使用MII链路状态监控时的时间间隔(ms)
arp_interval int 使用arp链路状态监控时的时间间隔(ms)
use_carrier int 使用MII链路状态监控时是否使用更新的carrier调用
updelay int 使用MII链路状态监控时从BACK状态切换到UP状态的时延(ms)
downdelay int 使用MII链路状态监控时从FAIL状态切换到DOWN状态的时延(ms)
primary char[] 用来在active-backup、balance-tlb和balance-alb模式中指定主网卡
arp_targets u32[] 在ARP链路状态监控中将向这些IP地址发送ARP请求。

2. struct slave

文件:driver/net/bonding/Bonding.h

每一个被管辖的物理网卡对应一个该数据结构的实例

主要成员:
名称 类型 含义
dev struct net_device* 指向被绑定的物理网卡
next,prev struct slave * 所有的slave数据结构通过这两个指针双向链接到一起形成*循环*链表
delay s16 用于保存MII链路状态监控和ARP链路状态监控的时延值。
jiffies u32 用于active-backup模式下的ARP状态监控
link s8 表示对应网卡的链路状态,取下列四个值之一:

BOND_LINK_UP 上线状态

BOND_LINK_DOWN 故障状态

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

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

state s8 表示对应网卡活动状态,取下列两个值之一:

BOND_STATE_ACTIVE 活动状态

BOND_STATE_BACKUP 后备状态
original_flags u32 保存被绑定物理网卡原来的flags
perm_hwaddr u8[] 保存被绑定物理网卡原来的MAC地址
ad_info struct

ad_slave_info
记录IEEE 802.3ad动态链路聚合模式下的“每网卡”相关状态信息
tlb_info struct tlb_slave_info 记录自适应传输负载均衡模式下的“每网卡”相关状态信息
link_failure_count u32 网卡从BOND_LINK_FAIL切换到BOND_LINK_DOWN的次数
speed u16 记录网卡的传输速度(10M/100M/1000G)
duplex u8 网卡工作模式(全双工?)

3. struct bonding

文件:driver/net/bonding/Bonding.h

每一个虚拟网卡对应一个该数据结构的实例。

主要成员:
名称 类型 含义
dev struct net_device* 指向虚拟网卡(例如bond0、bond1等等)
first_slave struct slave * 指向被绑定的第一个物理网卡对应的slave结构。
curr_active_slave struct slave * 指向当前活动的网卡对应的slave结构,在不同的工作模式下有不同的含义。
current_arp_slave struct slave * 用于ARP状态监控(只用于bond_activebackup_arp_mon)
primary_slave struct slave * 如果使用BOND_MODE_ACTIVEBACKUP、BOND_MODE_TLB或者BOND_MODE_ALB模式,则指向主物理网卡对应的slave结构(primary_slave)
slave_cnt s32 虚拟网卡所管辖的物理网络接口的个数
lock rwlock_t 每一个虚拟网卡管辖一系列物理网卡,每一个物理网卡对应一个slave结构,所有的slave被放在一个链表中,这个读写锁用来保护该链表。
curr_slave_lock rwlock_t 用来保护curr_active_slave的读写锁。
mii_timer struct timer_list 用于MII链路状态监控的定时器
arp_timer struct timer_list 用于ARP链路状态监控的定时器
kill_timers s8 如果该标志置位,所有的计时器超时后就不再重新设置,从而可以被安全删除
bond_list struct list_head 通过该结构,所有的bonding数据结构被连接为双向链表,链表头是全局变量bond_dev_list。

2. 关键函数

本节描述了bonding模块关键函数的操作流程,这些函数是基本的原子模块,其他没有被列举的函数仅仅是对这些函数的简单包装。

1. 模块初始化/释放

1. 初始化

* bonding_init

原型:

static int __init bonding_init(void)

bonding_init作为bonging模块的初始化函数,在模块被加载时被调用。它主要做如下工作:

1. 调用函数bond_check_params解析传入模块的参数并检查其合法性,结果放入数据结构params中。其中params是一个类型为bond_params的全局变量。
2. 如果内核支持proc文件系统,调用bond_create_proc_dir在/proc/net下创建目录/proc/net/bonding。
3. 如果传入参数指定了bond设备的个数(通过参数max_bonds),则通过下列步骤创建max_bonds个bond设备(从bond0到bondN)
1. 调用alloc_netdev和dev_alloc_name创建网络设备,指定每一个设备的私有数据是一个bonding结构(dev->priv)。
2. 为每一个新创建的虚拟网络设备调用bond_init函数。
3. 调用register_netdevice注册这个新创建的网络设备。
4. 调用register_netdevice_notifier,注册函数bond_netdev_notifier为网络事件处理函数。

* bond_init

原型:

static int __init bond_init(struct net_device *bond_dev, struct bond_params *params)

该函数对每一个新创建的虚拟网络设备调用一次。它主要做下列工作。

1. 取出虚拟网络设备bond_dev的私有数据块,用bond指向它(struct bonding *bond)。
2. 初始化两个读写锁bond->lock和bond->curr_slave_lock。
3. 把bond->first_slave、bond->curr_active_slave、bond->current_arp_slave、bond->primary_slave全部置为NULL。bond->dev指向属主网络设备bond_dev。
4. 设置bond_dev的一系列通用接口函数,例如open、close、get_stats、do_ioctl、set_multicast_list、change_mtu和set_mac_address。
5. 根据不同的工作模式,设置bond_dev的通用接口函数hard_start_xmit 指向不同的目的函数。例如如果工作模式是BOND_MODE_ROUNDROBIN,则 hard_start_xmit指向函数bond_xmit_roundrobin。
6. 设置bond_dev->tx_queue_len为0,表示发送队列大小没有限制。
7. 设置bond_dev->flags为IFF_MASTER|IFF_MULTICAST表示该设备支持Muticase并且是一个流量均衡组中的master(被它管辖的其他物理网卡将被设置IFF_SLAVE标志)。
8. 其他和VLAN相关的标志设置和初始化。
9. 如果内核支持proc文件系统,调用bond_create_proc_entry在目录/proc/net/bonding下创建对应的proc文件。
10. 调用list_add_tail把该bonding数据结构添加到bond_dev_list中。

2. 释放

* bonding_exit

原型:

static void __exit bonding_exit(void)

该函数在模块被卸载的时候被调用,它主要做如下工作:

1. 调用unregister_netdevice_notifier注销网络事件处理函数。
2. 调用bond_free_all注销所有形如bondN的虚拟网络接口。bond_free_all遍历bond_dev_list链表,并且对其中的每一个类型为 struct bonding*的数据结构bond做如下操作:
1. 调用unregister_netdevice注销bond->dev
2. 调用bond_deinit(bond->dev)
3. 调用bond_destroy_proc_dir删除/proc/net/bonding目录

* bond_deinit

原型:

static inline void bond_deinit(struct net_device *bond_dev)

该函数对每一个虚拟网卡的实例调用一次,它主要做如下操作:

1. 调用list_del把虚拟网卡对应的bonding数据结构从bond_dev_list链表中摘除。
2. 调用bond_remove_proc_entry删除/proc/net/bonding目录中的对应文件。

2. 物理网卡的绑定/解除绑定

在下面的讨论中,假定ifenslave使用新的ABI接口,即:

* 在绑定物理网卡时,如果虚拟的网卡还没有MAC地址,则ifenslave通过IOCTL把该虚拟网卡的MAC地址设置为该物理网卡的MAC地址(保证bond_enslave被调用时虚拟网卡已经有了MAC地址)。
* 如果被绑定网卡处于UP状态,则ifenslave首先把它设置为DOWN状态(保证bond_enslave被调用时被绑定物理网卡处于DOWN状态)。

如果使用旧版本的ABI接口,则虚拟的网卡的MAC地址由bonding模块在bond_enslave函数中自行设置,并且被绑定网卡在bond_enslave被调用时可能处于UP状态,需要由bond_enslave函数自行处理。

1. 绑定

* bond_enslave

原型:

static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)

该函数在试图把一个物理网卡绑定到一个虚拟的网卡时被调用,其中bond_dev表示虚拟的网卡,slave_dev表示真实的物理网卡。该函数主要做如下操作:

1. 取出bond_dev的私有数据,用bond指向它(struct bonding *)。
2. 一系列的合法性检查,包括:

1. bond_dev的flags是否已经设置了IFF_UP(虚拟的网卡必须已经处于UP状态)
2. slave_dev的flags是否没有设置IFF_SLAVE(防止同一个物理网卡被绑定两次)
3. bond_dev的flags如果设置了NETIF_F_VLAN_CHALLENGED,则bond->vlan_list不能为空。
4. slave_dev->flags是否没有设置IFF_UP(物理网卡应该处于DOWN状态)
5. slave_dev->set_mac_address不能为NULL(物理网卡应该支持设置MAC地址)

3. 调用kmalloc分配一个新的slave结构。

4. 把slave_dev->flags保存在slave->original_flags中。
5. 把slave_dev原有的MAC地址保存在slave-> perm_hwaddr中。
6. 设置slave_dev新的MAC地址为虚拟网卡的MAC地址。
7. 调用netdev_set_master设置slave_dev,该函数主要作如下操作:

1. 设置slave_dev->flags的IFF_SLAVE标志。
2. 设置slave_dev->master指向虚拟网卡bond_dev。

8. 设置slave->dev指向slave_dev。

9. 如果bond_dev工作在模式BOND_MODE_TLB或者BOND_MODE_ALB,对slave调用bond_alb_init_slave函数。
10. 维护和Multicast以及VLAN相关的一系列数据结构。
11. 调用bond_attach_slave把slave加入bond的链表(通过维护bond-> first_slave和slave结构的next,prev指针)
12. 把slave的delay和link_failure_count都清零。
13. 监测slave_dev的链路状态:

1. 如果使用MII链路,并且bond_check_dev_link返回BMSR_LSTATUS(表示链路正常),或者不使用MII链路监控,则根据updelay是否为0把slave->link设置为BOND_LINK_BACK或者BOND_LINK_UP。
2. 如果使用MII链路,并且bond_check_dev_link返回非BMSR_LSTATUS值,则设置slave->link为BOND_LINK_DOWN。

14. 调用bond_update_speed_duplex更新slave_dev的链路速率,如果失败则设置slave_dev的链路速率为100M全双工。

15. 如果虚拟网卡工作在BOND_MODE_ACTIVEBACKUP、BOND_MODE_TLB或者BOND_MODE_ALB模式下,并且slave_dev是用户指定的主网卡,则设置bond->primary_slave为slave_dev。
16. 设置bond->curr_active_slave和slave的活动状态,维护VLAN和Multicast相关数据结构:

1. 如果虚拟网卡工作在BOND_MODE_ACTIVEBACKUP:如果bond->curr_active_slave没有被设置或者bond->curr_active_slave不响应ARP(设置了IFF_NOARP标志),并且slave_dev不处于BOND_LINK_DOWN状态,则设置slave_dev为活动网卡(设置BOND_STATE_ACTIVE标志,清除IFF_NOARP标志),否则设置slave_dev为后备网卡(设置BOND_STATE_BACKUP标志,设置IFF_NOARP标志)。
2. 如果虚拟网卡工作在BOND_MODE_ROUNDROBIN或者 BOND_MODE_BROADCAST:直接设置slave_dev的活动状态为BOND_STATE_ACTIVE(在BOND_MODE_ROUNDROBIN和BOND_MODE_BROADCAST 模式下,IFF_NOARP标志始终被清除),如果没有设置bond->curr_active_slave,则设置bond->curr_active_slave指向slave。
3. 其他工作模式:(还没有加以分析)

2. 解除绑定
...全文
588 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
steptodream 2010-05-24
  • 打赏
  • 举报
回复
好帖就顶。百度名人!
2010-05-24
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 steptodream 的回复:]
百度名人勋章是什么 楼主先讲讲 我就看你发的内容 嘿嘿
[/Quote]肥脸。。
kwest 2010-05-21
  • 打赏
  • 举报
回复
好帖就顶。
  • 打赏
  • 举报
回复
很好,继续收藏。
steptodream 2010-05-20
  • 打赏
  • 举报
回复

百度名人勋章是什么 楼主先讲讲 我就看你发的内容 嘿嘿

3,286

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 实用资料发布区
社区管理员
  • 实用资料发布区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧