它不仅是一个虚拟网络设备,还具备虚拟交换机的功能,能够显著提高网络数据的转发效率
本文将详细解析Linux Bridge的源码,带您一窥其内部工作原理和机制
一、Linux Bridge概述 Bridge(桥接)是一种网络层设备,它允许网络数据在不同的网络接口之间转发
与物理交换机类似,Linux Bridge也具备多个端口,数据可以从任意端口进入,并根据目的MAC地址从相应的端口转发出去
Bridge不仅支持以太网帧的转发,还能实现VLAN(虚拟局域网)和STP(生成树协议)等高级功能
Linux Bridge的源码实现主要位于Linux内核的net/bridge目录下,核心文件包括br.c、br_input.c、br_forward.c等
下面,我们将从这些源码文件出发,深入探讨Linux Bridge的工作原理
二、Linux Bridge的初始化 Linux Bridge的初始化过程在br.c文件的br_init函数中完成
该函数首先初始化forwarding database(转发数据库),用于存储MAC地址与端口的对应关系
接着,设置bridge相关的ioctl函数和收包函数,并注册bridge模块的notifier
static int__initbr_init(void) { br_fdb_init(); #ifdef CONFIG_BRIDGE_NETFILTER if(br_netfilter_init()) return 1; #endif br_ioctl_set(br_ioctl_deviceless_stub); br_handle_frame_hook = br_handle_frame; #if defined(CONFIG_ATM_LANE) ||defined(CONFIG_ATM_LANE_MODULE) br_fdb_get_hook = br_fdb_get; br_fdb_put_hook = br_fdb_put; #endif register_netdevice_notifier(&br_device_notifier); return 0; } 在初始化过程中,br_handle_frame_hook被设置为br_handle_frame函数,这是bridge处理数据包的核心函数
三、数据包的处理流程 当数据包到达网络接口时,Linux内核会调用net_rx_action函数来处理接收到的数据包
在net_rx_action函数中,如果数据包的目的端口是bridge端口组的一员,则会调用handle_bridge函数来处理该数据包
static voidnet_rx_action(struct softirq_action h) { // ... #if defined(CONFIG_BRIDGE) ||defined(CONFIG_BRIDGE_MODULE) if(skb->dev->br_port!= NULL && br_handle_frame_hook!= NULL) { handle_bridge(skb, pt_prev); dev_put(rx_dev); continue; } #endif // ... } handle_bridge函数首先会检查一些前置条件,然后调用br_handle_frame_hook(即br_handle_frame函数)来处理数据包
static __inline__ int handle_bridge(structsk_buff skb, struct packet_type pt_prev) { // ... br_handle_frame_hook(skb); // ... } 在br_handle_frame函数中,首先会获取数据包的目的MAC地址,然后查找forwarding database,确定数据包应该从哪个端口转发出去
如果数据包的目的MAC地址在forwarding database中找不到,bridge会将其广播到所有端口,以寻找目的主机
void br_handle_frame(structsk_buff skb) { structnet_bridge br; unsignedchar dest; structnet_bridge_port p; // ... dest = skb->mac.ethernet->h_dest; p = skb->dev->br_port; // ... if(p == NULL) gotoerr_nolock; br = p->br; // ... if(br_fdb_find(br, dest)) { // Forward the packet to the corresponding port }else { // Broadcast the packet to all ports } // ... } 此外,Linux Bridge还具备学习功能
每当收到一个数据包时,bridge会学习其源MAC地址,并将其添加到forwarding database中
这样,下次当相同源MAC地址的数据包到达时,bridge就能直接查找到对应的端口,而无需广播
if (p->state ==BR_STATE_LEARNING || p->state == BR_STATE_FORWARDING) br_fdb_insert(br, p, skb->mac.ethernet->h_source, 0); 四、Bridge的ioctl操作 Linux Bridge还支持一系列的ioctl操作,用于配置和管理bridge设备
这些操作在br_dev_ioctl函数中实现
int br_dev_ioctl(structnet_device dev, struct ifreq rq, intcmd) { structnet_bridge br = netdev_priv(dev); switch(cmd) { case SIOCDEVPRIVATE: returnold_dev_ioctl(dev, rq,cmd); case SIOCBRADDIF: case SIOCBRDELIF: returnadd_del_if(br, rq->ifr_ifindex, cmd == SIOCBRADDIF); // ... } return -EOPNOTSUPP; } 例如,当用户通过brctl命令添加一个网络接口到bridge设备时,会调用SIOCBRADDIF命令,并在br_dev_ioctl函数中处理
五、Bridge的配置和使用 在Linux系统中,可以使用iproute2工具集或bridge-utils工具集来配置和使用bridge设备
使用iproute2创建一个bridge设备: sudo ip link add name br0 type bridge sudo ip link set br0 up 使用bridge-utils配置bridge设备: sudo brctl addbr br0 sudo brctl addif br0 eth0 sudo brctl addif br0 eth1 sudo ifconfig eth0 0.0.0.0 sudo ifconfig eth1 0.0.0.0 sudo ifconfig br0 192.168.1.10 通过上述命令,我们可以创建一个名为br0的bridge设备,并将eth0和eth1两个网络接口添加到该bridge设备中
然后,将eth0和eth1的IP地址设置为0,并将br0的IP地址设置为192.168.1.10
六、总结 Linux Bridge作为Linux网络子系统的重要组成部分,具备虚拟交换机的功能,能够显著提高网络数据的转发效率
通过深入解析Linux Bridge的源码,我们了解了其初始化过程、数据包处理流程、ioctl操作以及配置和使用方法
希望本文能够帮助您更好地理解Linux Bridge的工作原理和机制,为您的网络设计和优化提供有力支持