linux4.12内核 bridge简介
Bridge是什么?
Bridge(桥)是 Linux 上用来做 TCP/IP 二层协议交换的设备,与现实世界中的交换机功能相似。Bridge 设备实例可以和 Linux 上其他网络设备实例连接,既 attach 一个从设备,类似于在现实世界中的交换机和一个用户终端之间连接一根网线。当有数据到达时,Bridge 会根据报文中的 MAC 信息进行广播、转发、丢弃处理。
Bridge 设备工作过程 。
Bridge重要数据结构
structnet_bridge
{
spinlock_t lock;
spinlock_t hash_lock;
struct list_head port_list;
struct net_device *dev;
struct pcpu_sw_netstats __percpu *stats;
/* These fields are accessed on eachpacket */
#ifdefCONFIG_BRIDGE_VLAN_FILTERING
u8 vlan_enabled;
u8 vlan_stats_enabled;
__be16 vlan_proto;
u16 default_pvid;
struct net_bridge_vlan_group __rcu *vlgrp;
#endif
struct hlist_head hash[BR_HASH_SIZE];
#ifIS_ENABLED(CONFIG_BRIDGE_NETFILTER)
union {
struct rtable fake_rtable;
struct rt6_info fake_rt6_info;
};
bool nf_call_iptables;
bool nf_call_ip6tables;
bool nf_call_arptables;
#endif
u16 group_fwd_mask;
u16 group_fwd_mask_required;
/* STP */
bridge_id designated_root;
bridge_id bridge_id;
u32 root_path_cost;
unsigned char topology_change;
unsigned char topology_change_detected;
u16 root_port;
unsigned long max_age;
unsigned long hello_time;
unsigned long forward_delay;
unsigned long ageing_time;
unsigned long bridge_max_age;
unsigned long bridge_hello_time;
unsigned long bridge_forward_delay;
unsigned long bridge_ageing_time;
u8 group_addr[ETH_ALEN];
bool group_addr_set;
enum {
BR_NO_STP, /* no spanning tree */
BR_KERNEL_STP, /* old STP in kernel */
BR_USER_STP, /* new RSTP in userspace */
} stp_enabled;
#ifdefCONFIG_BRIDGE_IGMP_SNOOPING
unsigned char multicast_router;
u8 multicast_disabled:1;
u8 multicast_querier:1;
u8 multicast_query_use_ifaddr:1;
u8 has_ipv6_addr:1;
u8 multicast_stats_enabled:1;
u32 hash_elasticity;
u32 hash_max;
u32 multicast_last_member_count;
u32 multicast_startup_query_count;
u8 multicast_igmp_version;
unsigned long multicast_last_member_interval;
unsigned long multicast_membership_interval;
unsigned long multicast_querier_interval;
unsigned long multicast_query_interval;
unsigned long multicast_query_response_interval;
unsigned long multicast_startup_query_interval;
spinlock_t multicast_lock;
struct net_bridge_mdb_htable __rcu *mdb;
struct hlist_head router_list;
struct timer_list multicast_router_timer;
struct bridge_mcast_other_query ip4_other_query;
struct bridge_mcast_own_query ip4_own_query;
struct bridge_mcast_querier ip4_querier;
struct bridge_mcast_stats __percpu *mcast_stats;
#ifIS_ENABLED(CONFIG_IPV6)
struct bridge_mcast_other_query ip6_other_query;
struct bridge_mcast_own_query ip6_own_query;
struct bridge_mcast_querier ip6_querier;
u8 multicast_mld_version;
#endif/* IS_ENABLED(CONFIG_IPV6) */
#endif
struct timer_list hello_timer;
struct timer_list tcn_timer;
struct timer_list topology_change_timer;
struct delayed_work gc_work;
struct kobject *ifobj;
u32 auto_cnt;
#ifdefCONFIG_NET_SWITCHDEV
int offload_fwd_mark;
#endif
}
/*此结构是桥下面的port结构*/
structnet_bridge_port
{
struct net_bridge *br; /*指向所属的桥*/
struct net_device *dev; /*指向本port对应的实际网络设备*/
struct list_head list; /* port双向循环链表 */
/* STP */ /*STP相关 */
u8 priority;
u8 state;
u16 port_no; /* port编号,1-1023*/
unsigned char topology_change_ack;
unsigned char config_pending;
port_id port_id;
port_id designated_port;
bridge_id designated_root;
bridge_id designated_bridge;
u32 path_cost;
u32 designated_cost;
struct timer_list forward_delay_timer;
struct timer_list hold_timer;
struct timer_list message_age_timer;
struct kobject kobj;
struct rcu_head rcu;
unsigned long flags;
#defineBR_HAIRPIN_MODE 0x00000001
#ifdefCONFIG_BRIDGE_IGMP_SNOOPING
u32 multicast_startup_queries_sent;
unsigned char multicast_router;
struct timer_list multicast_router_timer;
struct timer_list multicast_query_timer;
struct hlist_head mglist;
struct hlist_node rlist;
#endif
#ifdefCONFIG_SYSFS
char sysfs_name[IFNAMSIZ];
#endif
};
/*转发表项结构*/
structnet_bridge_fdb_entry
{
struct hlist_node hlist;
struct net_bridge_port *dst; /*目的MAC对应的出口port*/
struct rcu_head rcu;
unsigned long ageing_timer; /* 超时值*/
mac_addr addr; /*目的MAC*/
unsigned char is_local; /* addr是本地网口的MAC*/
unsigned char is_static; /*静态的转发表项,不会超时,所有的本地转发表项都是静态的*/};
Bridge数据结构关系图
Bridge模块初始化
在br_init函数中初始化了一个 钩子函数
br_ioctl_hook= br_ioctl_deviceless_stub; /* 用来处理用户层的ioctl的函数,主要是添加/删除桥等操作*/
Bridge的添加和删除
1. 添加
br_ioctl_deviceless_stub->br_add_bridge
2. 删除br_ioctl_deviceless_stub->br_del_bridge
Port的添加和删除
1. 添加
rtnetlink_rcv_msg-> br_add_slave-> br_add_if
br_add_if主要步骤
new_nbp;/*初始化port的相关成员,并将port添加到br的port链表中*/
br_fdb_insert/*根据port创建一个新的转发表项,并加入到br的转发表中*/
netdev_rx_handler_register/*将桥端口收包处理函数br_handle_frame 注册至其对应dev中*/
2. 删除
rtnetlink_rcv_msg ->br_dev_slave-> br_add_if
Bridge接收和转发报文流程
图-1 Bridge报文接收和转发处理
1. 在dev.c的__netif_receive_skb_core函数中会调用skb->dev->rx_handler,即br_handle_frame函数
2. 在br_handle_frame中首先做一些常规检测
3. 如果收包port是学习和转发状态,则调用br_fdb_update在port对应的桥的转发表中建立转发项,转发项的addr是源mac地址,这样下次如果有到此地址的数据则通过查询转发表直接从对应的port发送即可
4. 如果的状态是转发状态并且需要处理桥上的钩子,然后调用br_handle_frame_finish完成转发
5. 在br_handle_frame_finish中,如果桥对应的虚拟设备是混杂模式,调用br_pass_frame_up将skb的dev改为桥的虚拟设备,skb的包类型改为到本地的包,然后调用netif_receive_skb重新进入收包流程
6. 如果是多播包则调用br_multicast_flood进行多播。
7. 通过查找转发表,如果是到本机的包则送到本机,如果不是到本机的包则调用br_forward完成转发
8. 在br_forward中会调用NF_BR_FORWARD链上注册的hook函数,在该hook函数里会调用br_nf_forward_ip,再调用NF_INET_FORWARD上注册的hook函数。9. 如果在单播转发表没有找到对应的转发项或者多播没有找到对应的多播转发项列表或者广播则调用br_flood_forward进行广播。
Bridge发送报文流程
1. 当要发送数据时会调用dev设备的hard_start_xmit函数,从而调用桥设备的br_dev_xmit
2. 在br_dev_xmit中会根据目的地址判断,如果是单播包就根据目的mac在转发表中查找对应的转发项,查到到转发项调用br_forward,并更改源MAC地址为出口port的MAC,skb的dev改为出口port的dev调用__dev_queue_push_xmit发送,最终再次调用dev的hard_start_xmit发送。
3. 如果是多播则查找多播组转发项列表,查找到则调用br_multicast_flood多播发送。4. 如果是广播或者单播未找到转发项或者多播未找到转发项列表,则调用br_flood发送。
linux4.12内核 bridge简介相关推荐
- Linux4.12 tun/tap简介
什么是tun/tap? TUN/TAP虚拟网络设备为用户空间程序提供了网络数据包的发送和接收能力.他既可以当做点对点设备(TUN),也可以当做以太网设备(TAP). TUN/TAP虚拟网络设备的原理比 ...
- linux内核 rps/rfs功能详细测试分析,学习Linux-4.12内核网路协议栈(2.1)——接口层加快传输速率的特性...
前面花了好多篇幅,终于将网络协议栈的初始化相关的内容介绍完了,也就是说完成前面的那些步骤以后,网络协议栈具备了数据包的收发功能.在网络接口层,它只负责数据包的接收与发送,而不关注数据包在网络层的类型是 ...
- 学习Linux-4.12内核网路协议栈(1.2)——协议栈的初始化(sk_buff)
sk_buff 是网络数据包的承载,是最关键的结构体之一 /*** struct sk_buff - socket buffer* @next: Next buffer in list* @prev: ...
- linux4.9编译内核,centos6编译linux-4.9内核启用bbr
一. BBR简介 bbr算法作为google出品的一套拥塞控制算法,致力于解决两个问题: 1. 在一定丢包率的网络上充分利用带宽 2. 降低网络链路buffer ...
- Linux 0.12内核与现代内核在内存管理上的区别
0.12内核的内存管理比较简单粗暴,内核只用了一个页目录,只能映射4G的线性空间,所以每个进程的虚拟空间(逻辑空间)只能给到64M,最多64个进程:每个进程都有对应的任务号nr,当一个进程需要分配进程 ...
- 石川es6课程---1-2、ES6简介
石川es6课程---1-2.ES6简介 一.总结 一句话总结: 从ECMAScript的历史发展来看,太顺了的时候总会遇到一挫折,比如ecma4 1.ECMAScript 和 JavaScript关系 ...
- 《linux内核完全剖析:基于0.12内核》读书笔记一
1. 下载linux0.12内核源代码 http://www.oldlinux.org/Linux.old/kernel/0.1x/ 下载任意一个都行. http://www.oldlinux.org ...
- Linux 0.12内核的内存管理基础
在Linux 0.12内核中,为了有效地使用机器中的物理内存,在系统初始化阶段内存被划分成几个功能区域. Linux内核程序占据在物理内存的开始部分,接下来是供硬盘或软盘等块设备使用的高速缓冲区部分, ...
- 我在售的12部图书简介及网上链接
应多位读者的强烈要求,为方便各位读者朋友及时在各网上书店查阅.购买我的图书,现把我目前在售的12本图书简介,及主要网店上的链接介绍如下. 网络设备四剑客图书: <Cisco/H3C交换机高级配置 ...
- 1. Navicat Premium 12 用户手册之简介
1.Navicat Premium 12 用户手册之简介 第一章 - 简介 关于 Navicat 系统需求 支持的内部部署数据库 支持的云数据库 安装 安装下载版 迁移 Navicat 到新的电脑 升 ...
最新文章
- C语言中字符数组初始化的几种方法
- 用老司机的理财经历告诉你,这才是程序员理财的正确姿势
- Nginx容器动态流量管理方案-nginx-upsync-module+nginx_upstream_check_module初体验
- 机器学习中的相似性度量 (转)
- Joy of Handcraft Gym - 102822J(线段树或差分)
- linux手机摩托,Linux操作系统触控智能机 摩托ZN4图赏
- 【java8新特性】——Optional详解(三)
- iOS 国际化多语言设置 xcode7
- C++中消息自动派发之一 About JSON
- python中for循环怎么打开_详解Python中for循环的使用
- 不要再被Python洗脑了!!
- Pytorch专题实战——激活函数(Activation Functions)
- win10系统无法删除文件提示找不到该项目解决办法
- 命令与征服:红色警戒3 解决游戏启动时界面黑屏,但右上角有五角星电脑卡死的问题——hosts
- flac转mp3,flac格式如何转mp3
- oracle的ofs,windows2003+oracle ofs 双机
- 用线程加锁模拟红绿灯
- 简单总结几种思维模式---助你编程,思绪如飞
- SpringMvc国际化i18n
- 2610_lab2 命令行与快捷键