Linux内核分析 - 网络[六]:网桥
重新计算网桥的ID, 这里根据br->port_list链表中的net_bridge_port的最小的addr来作为网桥的ID。 br_stp_recalculate_bridge_id (br); 网卡设备的删除br_del_bridge()与端口的移除add_del_if()与添加差不多,不再详述。 熟悉了网桥的创建 与添加,再来看下网桥是如何工作的。 当收到数据包,通过netif_receive_skb()->handle_bridge()处理网桥: static inline struct sk_buff *handle_bridge(struct sk_buff *skb, struct packet_type **pt_prev, int *ret, struct net_device *orig_dev) { struct net_bridge_port *port; if (skb->pkt_type == PACKET_LOOPBACK || (port = rcu_dereference(skb->dev->br_port)) == NULL) return skb; if (*pt_prev) { *ret = deliver_skb(skb, *pt_prev, orig_dev); *pt_prev = NULL; } return br_handle_frame_hook(port, skb); } 1. 如果报文来自lo设备,或者dev->br_port为空(skb->dev是收到报文的网卡设备,而在向网桥添加端口时, dev->br_port被赋予了创建的与网卡相对应的端口p),此时不需要网桥处理,直接返回报文; 2. 如果报文匹配了之前的 ptype_all中的协议,则pt_prev不为空,此时要先进行ptype_all中协议的处理,再进行网桥的处理; 3. br_handle_frame_hook是网桥处理钩子函数,在br_init() [netbridgebr.c]中 br_handle_frame_hook = br_handle_frame; br_handle_frame() [netbridgebr_input.c]是真正的网桥处理函数, 下面进入br_handle_frame()开始网桥部分的处理: 与前面802.1q讲的一样,首先检查users来决定是否复制报文: skb = skb_share_check(skb, GFP_ATOMIC); 如果报文的目的地址是01:80:c2:00:00:0X,则是发往STP的多播地 址,此时调用br_handle_local_finish()来完成报文的进一步处理: if (unlikely(is_link_local(dest))){ …… if (NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev, NULL, br_handle_local_finish)) return NULL; /* frame consumed by filter */ else return skb; } 而br_handle_local_finish()所做的内容很简单,因为是多播报文,主机要做的仅仅是更新报文的源mac与接收端口 的关系(在CAM表中)。 static int br_handle_local_finish(struct sk_buff *skb) { struct net_bridge_port *p = rcu_dereference(skb->dev->br_port); if (p) br_fdb_update(p->br, p, eth_hdr(skb)->h_source); return 0; /* process further */ } (编辑:源码网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |