关于设备的添加删除的基本动作,我们已经知道。
这节,我们看看关于网桥设备以及桥设备上的端口的启动和关闭。
我们说过,在初始化一个桥设备的时候有这样一个操作:
dev->netdev_ops = &br_netdev_ops;
br_netdev_ops这个参数,注册了很多函数,其中包括网桥设备的启动和关闭函数
br_dev_open和br_dev_stop,这两个函数的工作主要是初始化桥设备的一些队列和
桥设备上端口的一些启动和关闭动作。
启动和关闭网桥设备
br_dev_open相当与启动网桥的总设计师
static int br_dev_open(struct net_device *dev)
{
struct net_bridge *br = netdev_priv(dev);
netdev_update_features(dev);
netif_start_queue(dev);
br_stp_enable_bridge(br);
br_multicast_open(br);
return 0;
}
static int br_dev_stop(struct net_device *dev)
{
struct net_bridge *br = netdev_priv(dev);
br_stp_disable_bridge(br);
br_multicast_stop(br);
netif_stop_queue(dev);
return 0;
}
启动网桥设备,当启动网桥设备时,先前绑定在该设备上的端口也会跟着启动
void br_stp_enable_bridge(struct net_bridge *br)
{
struct net_bridge_port *p;
spin_lock_bh(&br->lock);
if (br->stp_enabled == BR_KERNEL_STP)
mod_timer(&br->hello_timer, jiffies + br->hello_time);
mod_timer(&br->gc_timer, jiffies + HZ/10);
br_config_bpdu_generation(br);
list_for_each_entry(p, &br->port_list, list) {
if (netif_running(p->dev) && netif_oper_up(p->dev))
br_stp_enable_port(p);
}
spin_unlock_bh(&br->lock);
}
关闭网桥设备
void br_stp_disable_bridge(struct net_bridge *br)
{
struct net_bridge_port *p;
spin_lock_bh(&br->lock);
list_for_each_entry(p, &br->port_list, list) {
if (p->state != BR_STATE_DISABLED)
br_stp_disable_port(p);
}
br->topology_change = 0;
br->topology_change_detected = 0;
spin_unlock_bh(&br->lock);
del_timer_sync(&br->hello_timer);
del_timer_sync(&br->topology_change_timer);
del_timer_sync(&br->tcn_timer);
del_timer_sync(&br->gc_timer);
}
启动和关闭网桥端口
要启动网桥端口,必须满足下列几个条件
1.被管理的相关设备已用管理手段启动
2.被绑定的相关设备有载波状态
3.相关的网桥设备已用管理手段启动
注意:网桥设备上没有载波状态,因为网桥是虚拟设备。
当网桥是以用户空间命令建起来并且先前三个条件都满足时,该网桥端口就可以立即启用了
但是,假设当端口建立时,由于上述三项条件至少有一项不满足无法启动端口时,下面的条件是
每项条件最终满足时启用端口的场合:
1.当被关闭的网桥设备重新启动时,其所有关闭的端口就会启用
2.当被绑定的设备检测到载波状态时,桥程序会收到NETDE_CHANGE通知消息
3.当被关掉的版定设备重启时,桥程序会收到NETDEV_UP的通知消息
如若还不满足,网桥端口就会被关闭
启动网桥上的端口
void br_stp_enable_port(struct net_bridge_port *p)
{
br_init_port(p);
br_port_state_selection(p->br);
br_ifinfo_notify(RTM_NEWLINK, p);
}
关闭网桥上的端口
void br_stp_disable_port(struct net_bridge_port *p)
{
struct net_bridge *br = p->br;
int wasroot;
wasroot = br_is_root_bridge(br);
br_become_designated_port(p);
br_set_state(p, BR_STATE_DISABLED);
p->topology_change_ack = 0;
p->config_pending = 0;
br_ifinfo_notify(RTM_NEWLINK, p);
del_timer(&p->message_age_timer);
del_timer(&p->forward_delay_timer);
del_timer(&p->hold_timer);
br_fdb_delete_by_port(br, p, 0, 0);
br_multicast_disable_port(p);
br_configuration_update(br);
br_port_state_selection(br);
if (br_is_root_bridge(br) && !wasroot)
br_become_root_bridge(br);
}
注意,当网桥端口关闭时,非根网桥可能会变成根网桥