Windows XP Windows 7 Windows 2003 Windows Vista Windows 綜合教學 Linux 系統教學
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟體教學
您现在的位置: Windows教程網 >> Windows教程 >  >> Linux 系統教學 >> Linux 教學

Linux 協議棧網橋端口管理:添加接口流程與 net_bridge_port 初始化

編輯:Linux 教學

Linux 網橋通過 ioctl(SIOCBRADDIF) 將物理網卡添加為橋端口,內核創建 net_bridge_port 結構、綁定設備、初始化 STP 狀態、更新 FDB、設置混雜模式、掛載 sysfs 節點。本文基於 net/bridge/br_if.c、br_ioctl.c 完整解析添加接口流程。

一、 用戶態觸發


// brctl addif br0 eth0
ioctl(br_socket_fd, SIOCBRADDIF, &ifr);  // ifr.ifr_ifindex = eth0 索引

二、 ioctl 入口 br_dev_ioctl()


int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) {
    struct net_bridge *br = netdev_priv(dev);
    switch (cmd) {
        case SIOCDEVPRIVATE:
            return old_dev_ioctl(dev, rq, cmd);
        case SIOCBRADDIF:
        case SIOCBRDELIF:
            return add_del_if(br, rq->ifr_ifindex, cmd == SIOCBRADDIF);
        default:
            return -EOPNOTSUPP;
    }
}

三、 核心添加邏輯 add_del_if() → br_add_if()


static int add_del_if(struct net_bridge *br, int ifindex, int isadd) {
    if (!capable(CAP_NET_ADMIN)) return -EPERM;
    struct net_device *dev = dev_get_by_index(ifindex);
    if (!dev) return -EINVAL;
    int ret = isadd ? br_add_if(br, dev) : br_del_if(br, dev);
    dev_put(dev);
    return ret;
}

四、 br_add_if() 詳細流程


int br_add_if(struct net_bridge *br, struct net_device *dev) {
    struct net_bridge_port *p;
    int err = 0;

    // 1. 基本合法性檢查
    if (dev->flags & IFF_LOOPBACK || dev->type != ARPHRD_ETHER)
        return -EINVAL;  // 非以太網/回環設備

    if (dev->hard_start_xmit == br_dev_xmit)
        return -ELOOP;   // 已經是橋設備,防止環路

    if (dev->br_port)
        return -EBUSY;   // 已屬於其他橋

    // 2. 分配並初始化 net_bridge_port
    if (IS_ERR(p = new_nbp(br, dev, br_initial_port_cost(dev))))
        return PTR_ERR(p);

    // 3. 將設備 MAC 作為本地靜態條目插入 FDB
    if ((err = br_fdb_insert(br, p, dev->dev_addr, 1)))  // is_local=1
        goto err_destroy_nbp;

    // 4. 創建 sysfs 節點 (/sys/class/net/br0/brif/eth0)
    if ((err = br_sysfs_addif(p)))
        goto err_del_nbp;

    // 5. 設置設備混雜模式(接收所有幀用於學習/轉發)
    dev_set_promiscuity(dev, 1);

    // 6. 掛載到橋端口鏈表
    list_add_rcu(&p->list, &br->port_list);

    // 7. STP 狀態機初始化
    spin_lock_bh(&br->lock);
    br_stp_recalculate_bridge_id(br);  // 重新計算橋 ID
    if ((br->dev->flags & IFF_UP) && (dev->flags & IFF_UP) && netif_carrier_ok(dev))
        br_stp_enable_port(p);         // 滿足條件啟用端口
    spin_unlock_bh(&br->lock);

    // 8. 更新橋 MTU(取所有端口最小值)
    dev_set_mtu(br->dev, br_min_mtu(br));

    return 0;

err_del_nbp:
    del_nbp(p);
err_destroy_nbp:
    destroy_nbp(p);
    return err;
}

五、 端口結構創建 new_nbp()


static struct net_bridge_port *new_nbp(struct net_bridge *br, struct net_device *dev, unsigned long cost) {
    int index = find_portno(br);  // 分配端口號 (1-1023)
    if (index < 0) return ERR_PTR(index);

    struct net_bridge_port *p = kmalloc(sizeof(*p), GFP_KERNEL);
    if (!p) return ERR_PTR(-ENOMEM);

    memset(p, 0, sizeof(*p));
    p->br = br;
    dev_hold(dev);
    p->dev = dev;
    p->path_cost = cost;                    // 基於帶寬計算
    p->priority = 0x8000 >> BR_PORT_BITS;   // 默認優先級 0x80
    dev->br_port = p;                       // 反向綁定
    p->port_no = index;
    br_init_port(p);                        // 初始化 STP 端口變量
    p->state = BR_STATE_DISABLED;           // 初始狀態
    kobject_init(&p->kobj);                 // sysfs kobject
    return p;
}

六、 關鍵初始化細節

1. 端口成本計算 br_initial_port_cost()


static unsigned long br_initial_port_cost(struct net_device *dev) {
    if (dev->speed == SPEED_10) return 100;
    if (dev->speed == SPEED_100) return 19;
    if (dev->speed == SPEED_1000) return 4;
    if (dev->speed == SPEED_2500) return 3;
    if (dev->speed == SPEED_10000) return 2;
    return 100;  // 未知速度默認 10M
}

2. STP 端口初始化 br_init_port()

  • 初始化 port_id、designated_root、designated_bridge、designated_port、designated_cost。
  • 設置定時器:forward_delay_timer、hold_timer、message_age_timer。
  • 狀態機變量:topology_change_ack、config_pending 等。

3. FDB 本地靜態條目

br_fdb_insert(br, p, dev->dev_addr, 1) 將橋端口自身 MAC 標記 is_local=1,查找時直接上送本機協議棧,不再轉發。

4. Sysfs 節點


/sys/class/net/br0/brif/eth0/
├── priority
├── path_cost
├── state
├── hairpin_mode
├── root_id
├── bridge_id
├── designated_root
├── designated_bridge
├── designated_port
├── designated_cost
├── message_age_timer
├── forward_delay_timer
├── hold_timer
└── ...

七、 刪除接口對稱流程 br_del_if()

  1. STP 禁用端口 br_stp_disable_port()。
  2. 從端口鏈表移除 list_del_rcu()。
  3. 關閉混雜模式 dev_set_promiscuity(dev, -1)。
  4. 移除 sysfs 節點 br_sysfs_delif()。
  5. 清理 FDB 條目 br_fdb_delete_by_port()。
  6. 釋放 net_bridge_port 內存 destroy_nbp()。
  7. 重新計算橋 ID/MTU。
Copyright © Windows教程網 All Rights Reserved