linux网络协议栈分析笔记2-网桥1
来源:互联网 发布:linux 查内存使用情况 编辑:程序博客网 时间:2024/06/04 19:59
这一章主要看网桥的处理。
网桥是一种2层网络互连设备,而不是一种网络协议。它在协议结构上并没有占有一席之地,因此不能通过向协议栈注册协议的方式来申请网桥数据包的处理。
skb = handle_bridge(skb, &pt_prev, &ret, orig_dev);
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); 网桥处理函数
}
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); 网桥处理函数
}
->br_handle_frame_hook() br_handle_frame_hook = br_handle_frame; br.c br_init()
->br_handle_frame()
is_valid_ether_addr() 校验是否是有效的以太网地址
skb_share_check() skb是共享的话,拷贝一份
if (skb->protocol == htons(ETH_P_PAUSE)) 如果是Pause帧,则丢弃
if (p->br->stp_enabled == BR_NO_STP && dest[5] == 0) STP关闭,则转发
switch (p->state) {
case BR_STATE_FORWARDING:
rhook = rcu_dereference(br_should_route_hook);
rhook(skb);
如果该接口处于Forwarding状态,并且该报文必需要走L3层 进行转发,则直接返回,让代码(2)进行处理。br_should_route_hook 钩子函数在ebtable里面设置为ebt_broute函数,它根据用户的规则来决定该报文是否要能通过L3来转发
case BR_STATE_LEARNING:
skb->pkt_type = PACKET_HOST; 设置为送到本机类型报文。
br_handle_frame_finish();
}
->br_handle_frame_finish()
->br_fdb_update() 源地址学习 (bf_fdb.c 转发数据库管理模块)
->is_multicast_ether_addr() 如果该报文是一个L2多播报文(如arp请求),那么它应该转发到该网桥的所有接口
->dst = __br_fdb_get(br, dest) 查MAC-端口映射表 得到出接口dst
->br_pass_frame_up() 完成发往本机的工作
->br_forward(dst->dst, skb); 由br_forward函数从dst所指向的端口将该报文发出去
->br_flood_forward(br, skb); 此报文是广播或组播报文,由br_flood_forward函数把报文向所有端口转发出去。
->br_pass_frame_up() 完成发往本机的工作
indev = skb->dev;
skb->dev = brdev; ->netif_receive_skb()
br->dev是一个虚拟的网络设备,这是网桥局域网通往本机的必经之道请注意,br->dev是本机和网桥相连的接口。当报文经网桥处理后,发现该报文应该发往本机,那就使用netif_receive_skb函数将该报文向上层协议投递。并且要将skb->dev设置为本机接口即br->dev,并且所有数据在它的入口接口indev的驱动中已处理完毕,因此可直接通知上层协议来处理。
->br_forward(dst->dst, skb); 由br_forward函数从dst所指向的端口将该报文发出去
->should_deliver(to, skb) Should_deliver函数来测试是否应将该包转发出去,它由出口端的状态和报文的入口端口信息来决定
return (((p->flags & BR_HAIRPIN_MODE) || skb->dev != p->dev) && p->state == BR_STATE_FORWARDING);
1) 入口端口和出口端口不能相同,如果是相同的话,那么源主机和目标主机在同一端口的子网段中,也即源主机和目标主机在同一
广播域里面目标主机和网桥都会同时收到该报文,因此网桥无需多此一举。
2) 如果出口端口的状态不是Forwarding,则不能转发出去。如果一个网桥没有启用STP功能,并且网络接口的状态为UP,那么它网 桥端口的状态为Forwarding。如果启用STP,每个端口都有一个严格的状态,规定那些端口在什么情况下才能成为Forwarding状
态,否则容易造成环路,产生网络风暴。
->__br_forward()
->br_forward_finish()
->br_dev_queue_push_xmit()
->skb_push(skb, ETH_HLEN);
->dev_queue_xmit(skb);
->br_flood_forward(br, skb); 由br_flood_forward函数把报文向所有端口转发出去。
->br_flood(br, skb, __br_forward); 把__br_forward函数作为回调函数,依次遍网桥的所有出口端,调用__br_forward函数将该报
文转发出去。一个广播报文从某一端口进入,应该其余的端口都应该转发出去,但入口端口就不需要了
->list_for_each_entry_rcu(p, &br->port_list, list) 即__br_forward()
下一章分析转发数据库模块,即二层MAC-端口转发表处理模块
- linux网络协议栈分析笔记2-网桥1
- linux网络协议栈分析笔记3-网桥2
- linux网络协议栈分析笔记4-网桥3
- linux网络协议栈分析笔记12-路由2-FIB1
- linux网络协议栈分析笔记1-接入部分
- 网络配置过程分析(linux网络协议栈笔记)
- linux网络协议栈分析笔记7-VLAN的处理
- linux网络协议栈分析笔记13-路由3-FIB2
- linux网络协议栈分析笔记14-路由4-FIB3
- linux网络协议栈分析笔记6-IP层的处理2
- linux网络协议栈分析笔记9-arp邻居子系统2
- linux网络协议栈分析笔记5-IP层的处理1
- linux网络协议栈分析笔记8-arp邻居子系统1
- linux网络协议栈分析笔记11-路由1-路由缓存
- 网络配置过程分析二(linux网络协议栈笔记)
- linux网络协议栈分析(一)
- linux网络协议栈分析(二)
- linux网络协议栈分析(三)
- socket基础
- iOS中arc的设置与使用-fobjc-arc或者-fno-objc-arc
- TCP及UDP区别
- Android—TTF字体
- C++ 关键字const使用说明
- linux网络协议栈分析笔记2-网桥1
- unchecked Exception & checked Exception
- 设计模式笔记--代理模式
- hadoop FS Shell
- 把数组显示到EDIT控件中
- Checked vs UnChecked Exception ,使用场合?
- Amazon vs Google 云服务
- 行为型模式之模板方法模式(Template Method)
- SBJson库