1. 网桥概念
中继器:只是简单的把一个端口所接收的数据复制到另一个端口,且是按位复制的。多端口的集线器叫做hub
网桥:网桥了解链路层协议,是按帧复制数据,而非按位复制。网桥还具有地址学习的功能,并不是简单的把数据从一个端口转发到其他端口,其会根据学习到的mac地址来决定是否进行转发,如何转发。
2. Linux网桥模型
对于linux而言,网桥是虚拟设备。因此,需要将真实的设备绑定到网桥上,网桥才能正常工作。网桥设备的数据传输与接收模型如下:
如上图,对于数据传输:
当上层协议将需要传输的数据发送到网桥设备br0后,br0就会查询转发数据库(FDB),来决定是将数据广播给出去,还是从某个eth口转发出去
对于数据接收:
从eth0或从eth1接收到的报文被提交给网桥的处理代码,在这里会判断报文该转发、丢弃、或提交到协议栈上层
3、数据结构
下面是bridge代码中比较主要的数据结构,主要包括网桥、网桥端口、转发数据表项
网桥相关的数据结构有
Mac地址的数据结构
struct mac_addr
{
unsigned char addr[6];
};
转发数据表项
struct net_bridge_fdb_entry
{
struct hlist_node hlist;/*将该表项链接到hash表头的指针,关于hash表结构请看上一篇文档 linux hash表的介绍*/
struct net_bridge_port *dst;/*指向目的网桥端口*/
struct rcu_head rcu;/*rcu机制使用*/
unsigned long ageing_timer;/*aging定时器*/
mac_addr addr;/*mac地址*/
unsigned char is_local;/*是否是本地mac地址*/
unsigned char is_static;/*mac地址是否为静态的标志*/
};
桥端口
struct net_bridge_port
{
struct net_bridge *br; /*指向该网桥端口所绑定的网桥*/
struct net_device *dev;/*指向该网桥端口所绑定的网络设备*/
struct list_head list;/*用于将该网桥端口链接到网桥的port_list链表的指针*/
/* STP */
u8 priority;/*端口优先级*/
u8 state;/*端口状态,在对数据进行转发时会对该state值进行判断*/
u16 port_no;/*端口号*/
unsigned char topology_change_ack;
unsigned char config_pending;
port_id port_id;/*端口ID*/
port_id designated_port;
bridge_id designated_root;
bridge_id designated_bridge;
u32 path_cost;/*端口路径开销*/
u32 designated_cost;
unsigned long designated_age;
/*网桥端口定时器*/
struct timer_list forward_delay_timer;
struct timer_list hold_timer;
struct timer_list message_age_timer;
struct kobject kobj;
struct rcu_head rcu;
unsigned long flags;
#define BR_HAIRPIN_MODE 0x00000001
};
net_bridge
struct net_bridge
{
spinlock_t lock; //自旋锁,在向net_bridge中增加port节点或改变net_bridge结构时使用
struct list_head port_list;//网桥端口列表
struct net_device *dev;//网桥设备
spinlock_t hash_lock;//对hash转发库进行操作时需要使用该自旋锁
struct hlist_head hash[BR_HASH_SIZE];//转发数据库hash表,关于hash表的数据结构的介绍,请看上一篇linux hlist介绍
struct list_head age_list;
unsigned long feature_mask;
#ifdef CONFIG_BRIDGE_NETFILTER
struct rtable fake_rtable;
#endif
unsigned long flags;
#define BR_SET_MAC_ADDR 0x00000001
/* STP */
bridge_id designated_root;
bridge_id bridge_id;
u32 root_path_cost;
/*网桥定时器*/
unsigned long max_age;
unsigned long hello_time;
unsigned long forward_delay;
/*本地配置的网桥定时器*/
unsigned long bridge_max_age;
unsigned long bridge_hello_time;
unsigned long bridge_forward_delay;
/*转发数据表项未被使用时可以待在转发数据库里的最大时间*/
unsigned long ageing_time;
u8 group_addr[ETH_ALEN];
u16 root_port; //根端口的端口号
enum {
BR_NO_STP, /* no spanning tree */
BR_KERNEL_STP, /* old STP in kernel */
BR_USER_STP, /* new RSTP in userspace */
} stp_enabled;
unsigned char topology_change;
unsigned char topology_change_detected;
/*网桥定时器*/
struct timer_list hello_timer;
struct timer_list tcn_timer;
struct timer_list topology_change_timer;
struct timer_list gc_timer;
struct kobject *ifobj;
};
这些数据结构的关联如下图(该图取自深入理解linu网络一书):