日期:2014-05-16  浏览次数:20763 次

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

  原型

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

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

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

  1. slave_dev->flags是否设置了IFF_SLAVE。
  2. slave结构是否存在。
  3. slave_dev原来的MAC地址是否和bond_dev相同,如果相同给出警告(防止MAC冲突)

  4. 如果虚拟网卡工作在BOND_MODE_8023AD模式,调用bond_3ad_unbind_slave

  5. 调用bond_detach_slave把slave从bond的链表中摘除(通过维护bond-> first_slave和slave结构的next,prev指针)。
  6. 如果slave_dev是虚拟网卡以前的主物理网卡,则设置bond->primary_slave为NULL。
  7. 如果slave_dev是虚拟网卡以前的活动网卡,则设置bond->active_slave为NULL(通过调用bond_change_active_slave函数)。
  8. 如果虚拟网卡工作在模式BOND_MODE_TLB或者BOND_MODE_ALB则调用bond_alb_deinit_slave。
  9. 如果slave_dev是虚拟网卡以前的活动网卡,则调用bond_select_active_slave寻找一个新的活动网卡。
  10. 如果虚拟网卡再也没有管辖的物理网卡,清除虚拟网卡的MAC地址(如果新调用ifenslave绑定物理网卡,则重新设置这个MAC地址)。
  11. 维护VLAN和Multicast相关的数据结构。
  12. 调用netdev_set_master解除master和slave的绑定关系并且调用dev_close关闭slave_dev。
  13. 恢复slave_dev的MAC地址(根据slave->perm_hwaddr)和flags(根据slave->original_flags)。
  14. 调用kfree释放slave结构。

  3. 网卡驱动通用接口(interface service routines)

  既然bonding模块本质上是一个虚拟网卡的驱动模块,所以必须提供一组所有网卡驱动模块都遵守的通用接口函数。

  1. open/close

  * bond_open(net_device->open接口)

  原型:

  static int bond_open(struct net_device *bond_dev)

  该函数在对应的虚拟网卡被打开时调用(即使用ifup/ifconfig工具启动网卡的时候),主要做如下操作(只分析三种主要模式):

  1. 设置bond->kill_timers为0。
  2. 如果使用MII链路状态监控:

  1. 初始化mii_timer。
  2. 设置超时时间mii_timer->expires为当前jiffies+1(立即调用bond_mii_monitor函数)
  3. 设置bond_mii_monitor为定时器的超时处理函数。

  3. 如果使用ARP链路状态监控:

  1. 初始化arp_timer。
  2. 设置超时时间arp_timer->expires为当前jiffies+1(立即调用定时器的超时处理函数)
  3. 如果工作在BOND_MODE_ACTIVEBACKUP,设置bond_activebackup_arp_mon为超时处理函数。
  4. 如果工作在其他模式,设置bond_loadbalance_arp_mon为超时处理函数。

 

  * bond_close(net_device->stop接口)

  原型:

  static int bond_close(struct net_device *bond_dev)

  该函数在对应的虚拟网卡被关闭时调用(即使用ifdown/ifconfig工具关闭网卡的时候),主要做如下操作(只分析三种主要模式):

  1. 调用bond_mc_list_destroy维护Multicast相关数据结构。
  2. 设置bond->kill_timers为1,所有的计时器超时后就不再重新设置,从而可以被安全删除。
  3. 删除所有的定时器,包括mii_timer和arp_timer。
  4. 调用bond_release_all释放所有被绑定的物理网卡,本质上该函数只是遍历slave链表并且对每一个元素调用bond_release。
  5. 如果虚拟网卡工作在BOND_MODE_TLB或者BOND_MODE_ALB模式下,调用bond_alb_deinitialize。

  2. ioctl接口

  * bond_do_ioctl(net_device->do_ioctl 接口)

  原型:

  static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd)

  该函数是虚拟网卡的IOCTRL接口,仅仅根据不同的IOCTRL命令调用其他函数执行相应的功能,所以不再列出操作流程而仅仅列举出这些被调用的函数和相应的功能:

  * 链路状态设置和查询(bond_ethtool_ioctl或者if_mii)
  * Bonding模块状态查询(bond_info_query)
  * 被绑定的物理网卡状态查询(bond_slave_info_query)
  * 物理网卡的绑定和解除绑定(bond_enslave/bond_release)
  * 虚拟网卡的MAC地址设置(bond_sethwaddr)
  * 切换当前活动的物理网卡(bond_ioctl_change_active)

  3. 统计值查询

  * bond_get_stats(net_device-> get_stats 接口)

原型: