Linux 网络协议栈开发(六)—— 二层桥转发蓝图(下)

本文深入探讨Linux网络协议栈中的二层桥转发,详细解析`br_handle_frame_finish`函数的处理流程。包括判断桥转发条件、数据包类型检查、端口状态与转发决策,以及在混杂模式下的数据包处理。文章阐述了广播、多播及单播数据包的转发策略,强调了在桥接网络中防止地址欺骗的安全措施。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  上一节我们了解到,数据包如何走进桥,这一节我们简单看看,入口帧处理函数br_handle_frame_finish.

  作用:br_handle_frame_finish函数主要是决策将不同类别的数据包做不同的分发路径。

其函数处理的过程如下图所示:




首先判断该数据包是否符合桥转发的条件:
(1)桥端口状态是否是开启状态,如果没有开启则丢掉数据包
(2)是否允许从该桥上转发,如果不允许,则直接返回0

获得桥转发的条件以后,开始判断数据包的类型:
(1)判断此时桥的标志为允许做哪些事情,学习还是扩展,如果学习的标志位被至位,则更新数据转发表。否则继续向下走
(2)根据多播或者广播报文的类型决定数据包的去留
(3)判断此时端口的状态,如果是学习状态,则将数据包丢弃
(要注意的是:桥的端口状态(和上面的flag不冲突,上面的flag表示网桥可以做的事情)state表示网桥端口所处于的状态)

在处理完一些需要预备的事情之后,就要为数据包的转发开始做准备了
(1)网桥设备是否处于混杂模式,如果是则建立副本,为发往本地做个备份
 (注意的是,所有网桥端口绑定的设备都会处于混杂模式,因为 网桥运行必须此模式。但除非明确的对其进行配置,否则网桥自己是不会处于混杂模式的)
(2)在次判断广播还是多播地址
广播地址:仅仅设置副本,进行广播转发和发往本地
多播地址:先查多播地址转发表,如果存在,设置副本,进行多播转发,原始数据包指向NULL,如果已经传送至本地,则会释放副本,不进行本地转发,否则重新转发到本地
(3)不是广播或者多播
  判断是否本地地址,如果是本地地址,则将原始数据包指向NULL,发往本地。否则进行数据包转发
 

[cpp]  view plain  copy
  1. /* note: already called with rcu_read_lock */  
  2. int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb)  
  3. {  
  4.     const unsigned char *dest = eth_hdr(skb)->h_dest;  
  5.     struct net_bridge_port *p = br_port_get_rcu(skb->dev);  
  6.     struct net_bridge *br;  
  7.     struct net_bridge_fdb_entry *dst;  
  8.     struct net_bridge_mdb_entry *mdst;  
  9.     struct sk_buff *skb2;  
  10.     bool unicast = true;  
  11.     u16 vid = 0;  
  12.   
  13.     if (!p || p->state == BR_STATE_DISABLED)  
  14.         goto drop;  
  15.     /*判断是否允许进入桥内,如果没有开启vlan则所有的数据包都可以进入, 
  16.       如果开启了vlan则根据vlan相应的规则,从桥上进行数据包转发*/  
  17.     if (!br_allowed_ingress(p->br, nbp_vlan_group_rcu(p), skb, &vid))  
  18.         goto out;  
  19.   
  20.     /* insert into forwarding database after filtering to avoid spoofing */  
  21.     br = p->br;  
  22.     /*如果可以学习,则学习数据包的原地址*/  
  23.     if (p->flags & BR_LEARNING)  
  24.         br_fdb_update(br, p, eth_hdr(skb)->h_source, vid, false);  
  25.   
  26.     if (!is_broadcast_ether_addr(dest) && is_multicast_ether_addr(dest) &&  
  27.         br_multicast_rcv(br, p, skb, vid))  
  28.         goto drop;  
  29.     /*桥的端口状态(和上面的flag不冲突,上面的flag表示网桥可以做的事情) 
  30.       state表示网桥端口所处于的状态*/  
  31.     if (p->state == BR_STATE_LEARNING)  
  32.         goto drop;  
  33.   
  34.     BR_INPUT_SKB_CB(skb)->brdev = br->dev;  
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值