首页
下载应用
提交文章
关于我们
🔥 热搜 🔥
1
1
2
1'"
3
百度
4
习近平
5
@诉说趣闻
6
@纽约时间
7
1'
8
上海
9
bxss.me
10
百度傻逼
分类
社会
娱乐
国际
人权
科技
经济
其它
首页
下载应用
提交文章
关于我们
🔥
热搜
🔥
1
1
2
1'"
3
百度
4
习近平
5
@诉说趣闻
6
@纽约时间
7
1'
8
上海
9
bxss.me
10
百度傻逼
分类
社会
娱乐
国际
人权
科技
经济
其它
二湘:朱令去世一周年,清华学子控诉清华在朱令案中的冷血和无耻
李宜雪的良知卖了2万元,真正需要声援的是罗灿宏啊
故意按摩让女生“产生欲望”后发生关系,算性侵吗?
洗牌电商圈!阿哲放话全网:挑战抖音所有机制!爆全品类大牌!
阿哲现身评论区,@一修!肉肉痛哭,无限期停播!回应舆论黑料,关闭私信评论区!
生成图片,分享到微信朋友圈
查看原文
其他
看图写话:聊聊veth数据流
Original
LanceZhang
二哥聊云原生
2022-11-22
收录于合集
#看图写话
10 个
#容器网络方案
28 个
#云原生
63 个
大家好,我是二哥。
我在公众号菜单里面新加一个“看图写话”的入口。内容么,顾名思义,就是看着图聊聊。控制字数真的很难,我尽量。
本篇看图写话,主要是将下面这两张图结合在一起,看看当数据包从图1的vpeer1流出,流进veth1,再进入bridge时,data flow是什么样子的。这次二哥只聊数据流,不说细节。
值得一说的是数据包(data package)穿过TCP/IP不同层时叫法不同。在应用层叫做message,到了TCP层叫做segment、UDP层叫datagram,流到了IP层叫做datagram,而在链路层则称为frame,到了物理层就变成bitstream(比特流)了。本文统一叫数据包。
先来介绍图1。它一共创建了两个额外的network namespace:ns1和ns2,ns1和default namespace之间用veth pair相连,ns2也是如此。vpeer1和veth是一对veth。在default namespace里创建有一个bridge,veth1和veth2都插在这个虚拟网桥上。这是Docker还有Kubernetes搭建Overlay模式容器网络的基础。
无论是vpeer1,还是veth1都是网卡设备,虽然它们都是虚拟的。图中lo代表loopback,enp0s3是一块物理网卡。
图 1:veth + bridge
再来看看图2。它包含了从网络设备接收数据包到应用层取走数据包之间的完整数据流。作为对比,我故意在这张图里面画出了两种设备:一个物理网卡和veth虚拟网卡。数据从两条路线流入,我分别标了1和2。
对于路线1,数据包到来后,DMA会将它从网卡的板载缓存移动到内存里面的RingBuffer中去。每个物理网卡都可能有若干个这样的环形Buffer。
网卡中断服务程序(ISR)在1.a 处将代表该网卡的net_device挂到了poll_list上。这个poll_list其实位于数据结构softnet_data,后者是每个CPU都会有的一个专属数据结构。各位看到过香肠是怎么晾晒的吧?我们可以将poll_list想象成晾晒香肠的架子,而每个网络设备则如同香肠一样挂到上面等待后续处理。
Linux的软中断都是跑在专门的内核线程(ksoftirqd)中的,每个CPU核对应一个这样的内核线程。ISR还会在1.b处触发ksoftirqd/4运行。这里的4表示这个内核线程与第4个CPU核绑定在一起,它只会处理这个核所拥有的softnet_data。
1.b 处的箭头所指的图示和标有ksoftirqd/4的大方框是一个,这样是为了让整个图好看一些,这其实也是一种(通用)画图技巧。类似的还有RingBuffer和net_device里面的rx_ring,它俩是同一个东西。
既然是一个线程,ksoftirqd/4首先是一个死循环。如果有网络设备挂在poll_list上面,只要满足条件,它就会从poll_list上面将其取下来,执行该设备驱动程序所注册的poll()。poll()不断地从net_device的RingBuffer里面取出数据包,转成skb格式,并沿着网络设备子系统 -> IP协议层 -> TCP层一路调用内核里面的函数来分析和处理这个skb。我把这个过程中每一层的入口函数都标示出来了,便于感兴趣的朋友自行到Linux内核代码搜索。
从这张图可以看到skb从RingBuffer被取出来,到最后落到位于TCP层的socket接收队列里,都是在ksoftirqd/4这个内核线程里完成的。这个处理过程还包括iptables的处理,路由的查询等各种费时费力的工作。所以如果iptables设置得非常多的话,会导致ksoftirqd/4处理每一个skb的时间变长,进而导致消费RingBuffer的速度变慢,对外的表现就是机器的吞吐量降低。
聊完了线路1,我们再来看看线路2。它和线路1最大的区别是:当通过veth发送数据出去(此为发送端veth,相应的另外一个叫接收端veth)的时候,不会触发硬件中断,也没有RingBuffer参与这个过程。发送端的veth在网络设备层会将skb直接塞入一个叫input_pkt_queue里,和poll_list一样,它也是位于数据结构softnet_data中。
图 2:数据接收完整数据流
当数据包从图1的vpeer1流出时,其实是在2.a处把skb所属的设备改为veth1,先暂时放到了input_pkt_queue里,但这个时候还没有到设备veth1处。步骤2.c所触发的软中断使得ksoftirqd/4开始消费input_pkt_queue里的skb。
如果veth1没有插在bridge上的话,当skb流到网络设备子系统的时候,也就来到了veth1(接收端veth)的怀抱。
不过对于图1这种情况,有一点点不同。图1里,veth1是插在bridge上的,bridge的行为类似二层交换机。在网络设备层调用 __netif_receive_skb_core 函数时,skb不会进入协议栈,而是会进入网桥处理。
以上就是本文的全部内容。码字不易,喜欢本文的话请帮忙转发或点击“在看”。您的举手之劳是对二哥莫大的鼓励。谢谢!
您可能也对以下帖子感兴趣
{{{title}}}
文章有问题?点此查看未经处理的缓存