桥设备及端口的开启和关闭(四)

关于设备的添加删除的基本动作,我们已经知道。
这节,我们看看关于网桥设备以及桥设备上的端口的启动和关闭。

我们说过,在初始化一个桥设备的时候有这样一个操作:
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);

    /* 当网桥启动时,设置次定时器,1/10秒到期一次 */
    mod_timer(&br->gc_timer, jiffies + HZ/10);
    /*TX配置bpdu*/
    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);
    /*更改桥的bpdu信息*/
    br_configuration_update(br);
    /*更新所有桥上端口的状态*/
    br_port_state_selection(br);
    /*处理非根网桥到根网桥的转移*/
    if (br_is_root_bridge(br) && !wasroot)
        br_become_root_bridge(br);
}
 注意,当网桥端口关闭时,非根网桥可能会变成根网桥
相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页