首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Linux 3.10 內核 Bridge 轉發邏輯深度解析:netdev_rx_handler_register 機制與 VLAN 支持

     編輯:Java 綜合教學

核心變革:netdev_rx_handler_register

Linux 3.10 引入 netdev_rx_handler_register,允許為 net_device 動態註冊接收處理函數,替代 2.6 時代硬編碼的協議棧入口。橋接、Bonding、Open vSwitch 均通過此機制掛載處理邏輯。

int netdev_rx_handler_register(struct net_device *dev,
                               rx_handler_func_t *rx_handler,
                               void *rx_handler_data) {
    ASSERT_RTNL();
    if (dev->rx_handler) return -EBUSY;
    rcu_assign_pointer(dev->rx_handler_data, rx_handler_data);
    rcu_assign_pointer(dev->rx_handler, rx_handler);
    return 0;
}

Open vSwitch 接入示例

static struct vport *netdev_create(const struct vport_parms *parms) {
    // ...
    err = netdev_rx_handler_register(netdev_vport->dev, netdev_frame_hook, vport);
    // ...
}

2.6 內核需替換 br_handle_frame_hook,3.10 直接註冊獨立 handler,模塊化解耦。

Bridge 數據包接收處理流程

入口:__netif_receive_skb_core

rx_handler = rcu_dereference(skb->dev->rx_handler);
if (rx_handler) {
    switch (rx_handler(&skb)) {
        case RX_HANDLER_CONSUMED: return NET_RX_SUCCESS;
        case RX_HANDLER_ANOTHER: goto another_round;
        case RX_HANDLER_EXACT: deliver_exact = true;
        case RX_HANDLER_PASS: break;
    }
}

橋接端口註冊 br_handle_frame,進入橋接邏輯。

br_handle_frame 核心邏輯

rx_handler_result_t br_handle_frame(struct sk_buff **pskb) {
    struct net_bridge_port *p = br_port_get_rcu(skb->dev);
    // 1. 回環包/無效 MAC 直接丟棄
    // 2. 本地鏈路多播地址特殊處理(STP、LLDP 等)
    // 3. NF_BR_LOCAL_IN hook → br_handle_local_finish
    // 4. 轉發邏輯:FORWARDING/LEARNING 狀態
    //    - 目的 MAC 是橋設備 → PACKET_HOST → 協議棧
    //    - NF_BR_PRE_ROUTING hook → br_handle_frame_finish
}

br_handle_frame_finish 轉發決策

int br_handle_frame_finish(struct sk_buff *skb) {
    // 1. VLAN 入向檢查 br_allowed_ingress
    // 2. 更新 FDB(MAC 表),含 VLAN 維度
    // 3. 多播處理 br_multicast_rcv
    // 4. LEARNING 狀態僅學習不轉發
    // 5. 決策:
    //    - 廣播/多播/未知單播 → 泛洪 br_flood_forward
    //    - 已知單播 → br_forward 到目標端口
    //    - 本地 MAC → br_pass_frame_up 送協議棧
}

本地上送:br_pass_frame_up

static int br_pass_frame_up(struct sk_buff *skb) {
    // VLAN 出向處理 br_handle_vlan
    skb->dev = brdev; // 關鍵:修改設備為橋設備
    return NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, indev, NULL, netif_receive_skb);
}

再次進入 netif_receive_skb,因橋設備無 rx_handler,直接上送協議棧。

轉發路徑:__br_forward → br_forward_finish → br_dev_queue_push_xmit

static void __br_forward(const struct net_bridge_port *to, struct sk_buff *skb) {
    skb = br_handle_vlan(to->br, nbp_get_vlan_info(to), skb); // VLAN 處理
    skb->dev = to->dev; // 設置出口設備
    NF_HOOK(NFPROTO_BRIDGE, NF_BR_FORWARD, ..., br_forward_finish);
}

int br_forward_finish(struct sk_buff *skb) {
    return NF_HOOK(NFPROTO_BRIDGE, NF_BR_POST_ROUTING, ..., br_dev_queue_push_xmit);
}

int br_dev_queue_push_xmit(struct sk_buff *skb) {
    if (nf_bridge_maybe_copy_header(skb) || need_fragment) kfree_skb(skb);
    else {
        skb_push(skb, ETH_HLEN);
        br_drop_fake_rtable(skb);
        dev_queue_xmit(skb); // 驅動發送
    }
    return 0;
}

3.10 Bridge 處理流程圖

Bridge 轉發流程圖

關鍵增強點總結

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
特性2.6 Kernel3.10 Kernel
接收入口硬編碼 br_handle_frame_hooknetdev_rx_handler_register 動態註冊
VLAN 支持無原生支持完整 VLAN 過濾、獨立 FDB、標簽處理
Hook 點基礎NF_BR_LOCAL_IN/PRE_ROUTING/FORWARD/POST_ROUTING 完整
多播基礎 IGMP Snooping增強 MDB、路由器端口檢測