加入收藏 | 设为首页 | 会员中心 | 我要投稿 温州站长网 (https://www.0577zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

Linux内核分析 - 网络[六]:网桥

发布时间:2016-09-28 06:27:19 所属栏目:Linux 来源:站长网
导读:副标题#e# 看完了路由表,重新回到netif_receive_skb ()函数,在提交给上层协议处理前,会执行下面一句,这就是网桥的相关操作 ,也是这篇要讲解的内容。 skb = handle_bridge(skb, pt_prev, ret, orig_dev); 网桥可以简单理 解为交换机,以下图为例,一台l

重新计算网桥的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 */ 
}

(编辑:温州站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读