tcp/ip stack 中的数据包队列

本文详细介绍了TCP/IP协议栈中的关键队列,包括网络层队列、socket层接收和发送队列以及网络设备队列。阐述了各队列的作用及如何在数据包接收和发送过程中起到桥梁作用。

TCP/IP 是一种存储/转发的协议,因此,在 stack 中必然存在数据包的队列(sk_buff queue)。

正是这些队列,将 stack 的处理逻辑比较清晰的划分成几个部分。

 

数据包接收路径上的队列:

 

1、网络层队列:softnet_data[this_cpu]. input_pkt_queue

 

每个 CPU 有一个这样的队列。此队列将网卡驱动的处理逻辑与协议分析(网络层、传输层)的处理逻辑区分开来。

 

当网卡驱动处理数据的时候,工作在中断上下文,它的处理结果就是将数据包尽快的送入此队列。

而真正的网络层、传输层协议分析和处理逻辑是在 net_rx_action 软中断中完成的。

net_rx_action CPU 调度后,从此队列中接收数据包,进行网络层和传输层的协议分析和处理。

 

 

2、BSD socket 层队列: sock-> receive_queue

每个 struct socket 对应一个这样的队列。此队列将 net_rx_action 软中断与 socket 层的处理逻辑区分开来。

 

net_rx_action 完成了网络层和传输层的处理后,需要将数据包送到对应的 struct socket 结构的此队列中。

而应用层则通过 readrecvfrom 等系统调用从此队礼中取走数据。

 

 

数据包发送路径上的队列:

 

 1BSD socket 层队列:sock->write_queue

当从 user space 调用 write() sendto() sendmsg() 等系统调用发送数据的时候,TCP UDP 的处理过程有所不同。

 

对于 UDP 来说,在这一层不需要通过队列来缓冲数据。Sendto 或者 sendmsg  将原始数据拆分成 sk_buff 结构,然后进行传输层、网络层处理,最后送到相应的 device 对应的输出队列。

 

但是 TCP 是一种流协议,具有拥塞控制的功能,因此可能需要在这一层缓冲数据。这个队列就是struct socket 结构中的write_queue

 

为什么说可能需要用到这个队列了。因为 write 或者 sendmsg 在将原始数据拆分成 sk_buff 结构后,就尝试将这些数据包发送出去并等待对端的 ACK。如果网络足够流畅,那么就不需要将数据缓冲在队列中。如果网络比较繁忙,在设定时间内等不到 ACK,或者对端的 TCP 窗口不允许接收数据,那么就必须先缓冲到队列中,留到合适的时机再发。(显然会有一个定时器来干这个事情)。

 

2、网络设备的队列: dev->qdisc

每个网络设备对应一个此队列(也可以没有,例如 lo)。它将网络层与设备驱动区分开来。

数据包在网络层处理完之后,可能会缓冲到此队列中。

这里也只是可能会缓冲,因为数据包被送到此队列后,如果条件允许,立刻就被发送出去。

 

此队列是 Linux 内核中实现 QoS 的关键。不同的 QoS 策略采用不同的方式对此队列中的数据包进行处理,默认的方式是 FIFO

 

如果底层 driver 处理速度跟不上发送数据包的速度,那么当队列满了以后,后续的数据包就会被丢弃。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值