没有合适的资源?快使用搜索试试~ 我知道了~
Linux内核bridge浅析.doc
0 下载量 61 浏览量
2022-11-29
05:14:42
上传
评论
收藏 206KB DOC 举报
温馨提示
试读
11页
Linux内核bridge浅析.doc
资源推荐
资源详情
资源评论
Linux 内核 bridge 浅析
Linux 网桥模型:
Linux 内核通过一个虚拟的网桥设备来实现桥接的,这个设备可以绑定若干
个以太网接口设备,从而将它们桥接起来。如下图所示:
网桥设备 br0 绑定了 eth0 和 eth1。对于网络协议栈的上层来说,只看得到
br0,因为桥接是在数据链路层实现的,上层不需要关心桥接的细节。于是协议
栈上层需要发送的报文被送到 br0,网桥设备的处理代码再来判断报文该被转发
到 eth0 或是 eth1,或者两者皆是;反过来,从 eth0 或从 eth1 接收到的报文被
提交给网桥的处理代码,在这里会判断报文该转发、丢弃、或提交到协议栈上层。
而有时候 eth0、eth1 也可能会作为报文的源地址或目的地址,直接参与报
文的发送与接收(从而绕过网桥)。
相关数据结构:
其中最左边的 net_device 是一个代表网桥的虚拟设备结构,它关联了一个
net_bridge 结构,这是网桥设备所特有的数据结构。
在 net_bridge 结构中,port_list 成员下挂一个链表,链表中的每一个节
点(net_bridge_port 结构)关联到一个真实的网口设备的 net_device。网口设
备也通过其 br_port 指针做反向的关联(那么显然,一个网口最多只能同时被绑
定到一个网桥)。
net_bridge 结构中还维护了一个 hash 表,是用来处理地址学习的。当网桥
准备转发一个报文时,以报文的目的 Mac 地址为 key,如果可以在 hash 表中索
引到一个 net_bridge_fdb_entry 结构,通过这个结构能找到一个网口设备的
net_device,于是报文就应该从这个网口转发出去;否则,报文将从所有网口转
发。
网桥数据包的处理流程:
接收过程:
对于数据包的处理流程并没有明显的主线,主要就是根据内核代码中网桥部
分的源码进行分析。
网口设备接收到的报文最终通过 net_receive_skb 函数被网络协议栈所接
收。这个函数主要做三件事情:1、如果有抓包程序需要 skb,将 skb 复制给它
们;2、处理桥接;3、将 skb 提交给网络层。
int netif_receive_skb(struct sk_buff *skb)
{
......
if (handle_bridge(&skb, &pt_prev, &ret, orig_dev))
goto out;
......
}
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;
//对于回环设备以及 skb->dev->br_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);
}
br_handle_frame_hook 在网桥初始化模块 br_init(void)函数中被赋值.
br_handle_frame_hook = br_handle_frame;
所以网桥对于数据包的处理过程是从 br_handle_frame 开始的。
struct sk_buff *br_handle_frame(struct net_bridge_port *p, struct
sk_buff *skb)
{
const unsigned char *dest = eth_hdr(skb)->h_dest;
int (*rhook)(struct sk_buff *skb);
//判断是否为有效的物理地址,非全 0 地址以及非广播地址
if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
goto drop;
//判断 skb 包是否被共享 skb->users != 1,若是,则复制一份,否则直接返
回
skb = skb_share_check(skb, GFP_ATOMIC);
if (!skb)
return NULL;
//这个函数并非像想象的那样,判断是否为本地地址
//而是在判断是否为链路本地多播地址,01:80:c2:00:00:0x
if (unlikely(is_link_local(dest))) {
/* Pause frames shouldn't be passed up by driver anyway */
if (skb->protocol == htons(ETH_P_PAUSE))
goto drop;
/* If STP is turned off, then forward */
if (p->br->stp_enabled == BR_NO_STP && dest[5] == 0)
goto forward;
剩余10页未读,继续阅读
资源评论
智慧安全方案
- 粉丝: 3615
- 资源: 59万+
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功