前言:網橋設備作為一個虛擬設備,用於連接多個端口,可以構建一個局域網。與之相似的是vlan設備,在linux中,vlan設備是為了處理802.1q的添加和去除TAG的問題,這和傳統交換機中vlan的功能—划分局域網,不太一樣,在這里僅僅是處理了消息頭,只是實現了隔離功能,並未實現交換功能,如果需要vlan內的數據轉發,可以把vlan子接口掛接在網橋設備下。
網橋設備中添加的接口,在同一個二層域中。網橋在Linux中的實現如下:
Bridge-utils工具的實現
先查看一下Bridge-utils工具的工作原理,它是用於用戶態配置網橋的工具,可以用於添加/刪除網橋,往網橋添加/刪除接口等操作。
在brctl.c的main()中,讀取了參數列表,這里使用了getopt_long()函數,可以借鑒使用。之后進行br的初始化,主要就是創建一個socket接口,為之后IOCTL操作。然后調用command_lookup(),查找到參數命令,最后調用cmd->func(),執行命令。最后在內核中sock_ioctl()會收到,然后調用br_ioctl_hook(),從這里,就開始內核態的處理。
網橋設備的初始化
Br_init(),br_init是注冊到內核進行初始化的,module_init(br_init),在br_init中,主要做的事如下:
注冊stp(生成樹協議),初始化轉發表,注冊network namespace(暫不知啥用),注冊通知連,netlink的初始化,設置br_ioctl_hook。
網橋的建立和操作
從br_ioctl_hook調用開始,在br_init中注冊的br_ioctl_hook為
br_ioctl_deviceless_stub,可以看到SIOCBRADDBR添加和刪除網橋。添加網橋中alloc_netdev()分配了設備結構體,並進行了初始化設置br_dev_setup,在初始化設置的時候,就填充了netdev_ops->br_netdev_ops,這里就是對於設備的操作回調函數咯,重點關注br_dev_ioctl,在這里,會用添加和刪除接口的操作。等再次添加從接口設備到網橋時,此時網橋設備已經存在,調用br_netdev_ops中的添加接口的回調函數,br_add_if中注冊了接收數據的處理函數:netdev_rx_handler_register(dev, br_handle_frame, p);br_handle_frame就是處理函數咯。
網橋的數據流程
先附一張18摸公司的文章的圖:

發送流程:
首先說一點是,網橋有自己的MAC地址,01:80:c2:00:00:0X,路由后發送函數dev_queue_xmit()發送數據出去,因為此時通過路由,skb->dev已經設置成為了br,所以,最后調用設備的發送回調ndo_start_xmit,在br初始化時,設置為br_dev_xmit,這樣,最后的發送函數就是它咯。在發送中,確定目的地址是單播還是洪泛。
接收流程:
接收上,是從netif_receive_skb()中接收報文,因為只有在attach到網橋的從接口注冊了rx_handle,即br_handle_frame,也就是只有這些接口才會把數據往網橋上送。接着調用br_handle_frame進行報文的處理,是consumed掉,還是轉發等在這里完成。具體的代碼就不分析咯。
注意事項:
網橋設備本身有自己的MAC,以及IP。發送和接收也正是通過路由后找到網橋接口的。
加入網橋的接口,其本身的IP和MAC地址都已經不再有效,路由並不會使用其中的地址,而是使用網橋的。
