linux 内核协议栈 linux内核协议栈skb被释放

大家好,如果您还对linux 内核协议栈不太了解,没有关系,今天就由本站为大家分享linux 内核协议栈的知识,包括linux内核协议栈skb被释放的问题都会给大家分析到,还望可以解决大家的问题,下面我们就开始吧!

linux 网络路径中网络协议栈有几种

1.总述

Linux中用户空间的网络编程,是以socket为接口,一般创建一个sockfd= socket(family,type,protocol),之后以该sockfd为参数,进行各种系统调用来实现网络通信功能。其中family指明使用哪种协议域(如INET、UNIX等),protocol指明该协议域中具体哪种协议(如INET中的TCP、UDP等),type表明该接口的类型(如STREAM、DGRAM等),一般设protocol=0,那么就会用该family中该type类型的默认协议(如INET中的STREAM默认就是TCP协议)。

Linux中利用module机制,层次分明地实现了这套协议体系,并具有很好的扩展性,其基本模块构成如下:

先看右边,顶层的socket模块提供一个sock_register()函数,供各个协议域模块使用,在全局的net_family[]数组中增加一项;各个协议域模块也提供一个类似的register_xx_proto()函数,供各个具体的协议使用,在该协议域私有的xx_proto[]数组中增加一项。这两个数组中的存放的都是指针,指向的数据结构如下图所示:

很明显它们是用来创建不同类型的socket接口的,且是一种分层次的创建过程,可想而知,顶层socket_create()完成一些共有的操作,如分配内存等,然后调用下一层create;协议域内的create()完成一些该协议域内共有的初始化工作;最后具体协议中的create()完成协议特有的初始化。具体的下一节讲。

再来看上图右边的,也是顶层socket模块提供的4个函数,前两个一般由具体协议模块调用,由于协议栈与应用层的交互,具体的后面会讲到。后两个一般有协议域模块调用,用于底层设备与协议栈间的交互。但这也不绝对,如在PPPOE协议中,这4个函数都由具体协议模块调用,这是因为PPPOX协议域内的共有部分不多,各个协议间几乎独立。这4个函数的功能及所用到的数据结构,在后面具体用到时会详细说明。

2.socket插口创建

首先来看一下最终创建好的socket插口由哪些部分组成,该结构是相当庞大的,这里只给出框架:

基本属性有state(listen、accept等),flags标志(blocked等),type类型,这里family和protocol都没有了,因为它们再创建时使用过了,已经被融入到socket结构中。

File指针指向一个file结构,在Linux中一个socket也被抽象为一个文件,所以在应用层一般通过标准的文件操作来操作它。

Ops指向一个struct proto_ops结构,它是每种协议特有的,应用层的系统调用,最终映射到网络栈中具体协议的操作方法。

Sk指向一个struct sock结构,而该结构在分配空间时,多分配了一点以作为该协议的私有部分,这里包含了该协议的具体信息,内容相当多。首先是一个struct sock_common结构,包含了协议的基本信息;然后是一个sk_prot_create指针,指向一个struct proto结构体,该结构体就是第一节中所述的,用proto_regsiter()注册到内核中的,它包含应用层到协议栈的交互操作和信息(也可以说成是Appà transport layer的交互信息);然后还有一个sk_backlog_rcv函数指针,所指函数在协议栈处理完接收到的包之后调用,一般仅是把数据包放到该socket的接收队列中,等待APP读取;最后协议的私有部分里存放该协议的私有信息,如pppoe的sessionID、daddr,tcp的连接4元组等,这些信息很重要,利用它们来区分同一个协议中的多个socket。

附上出处链接:

Linux 虚拟网络设备之 TUN/TAP 设备

TUN/TAP设备是Linux内核中的虚拟网络组件,为用户空间程序提供数据包接收和发送功能。它们相当于点对点或以太网设备,但不依赖物理介质,而是从用户空间程序接收数据并将其写回给用户空间,模拟从外部接收数据的行为。TAP设备处理第二层数据包(如以太网帧),而TUN设备则操作第三层数据包(如IP数据包)。

物理网卡的工作流程是:数据从外部网络通过网卡进入内核协议栈,由内核处理后发送,反之则从内核写入数据发送到网卡。而TUN/TAP设备在用户空间和内核网络栈之间扮演桥梁角色,用户空间程序能像操作硬件网卡一样操作它们,但数据传输方式不同,物理网卡以比特流形式,TUN/TAP则在内核和用户空间之间通过内存直接拷贝。

与物理网卡相比,虚拟网卡如TAP和TUN,提供了连接其他设备(如其他网卡或虚拟交换机)以及用户空间程序收发数据的功能。TAP设备更像传统网卡,常用于连接虚拟交换机,而TUN常用于实现三层IP隧道,如OpenVPN中的数据传输。TAP接口在虚拟化环境中,如KVM虚拟机之间通过LinuxBridge通信时被广泛使用。

Linux内核协议栈丢弃SYN报文的主要场景剖析

在排查网络问题时,常遇到TCP连接建立失败。本文从TCP协议栈角度总结常见原因,集中于内核处理SYN报文阶段。若服务器端内核不回应SYNACK,通常与服务器端处理逻辑或特定配置相关,而非客户端重传SYN报文问题。

本文以CentOS 7内核版本为例,分析处于listen状态的socket处理TCP SYN报文的主要逻辑。关键代码逻辑在tcp_v4_conn_request()函数内。正常情况下,报文包含TCP SYN flag置位且请求队列未满。然而,实际情况中,该函数需考虑多种异常情况,其中一种涉及per-host PAWS检查。

per-host PAWS检查是一种防止sequence number缠绕的机制,尤其在NAT客户端访问服务器时常见。开启net.ipv4.tcp_tw_recycle和net.ipv4.tcp_timestamps时,此问题出现概率高。客户端在NAT环境下,新建连接时会出现时通时不通现象。此问题根源在于服务器快速回收TIME_WAIT状态时,NAT内部设备利用TCP option中timestamp字段的增长来判断串扰数据,导致新建连接被拒绝。

Linux内核实现中,接收SYN报文前需验证peer是否为proven,即进行per-host PAWS检查。在tcp_ipv4.c中,实现逻辑包含接收报文后检查timestamp是否增长。这一机制在NAT环境下的客户端带来副作用,即新建连接时通时不通。解决此问题的方法是关闭TIME-WAIT快速回收,调整net.ipv4.tcp_tw_recycle参数为0。

另一种主要场景涉及accept queue满情况,导致新来的SYN报文被丢弃。accept queue满通常发生在应用程序处理新连接时效率低下,导致无法及时从队列中获取连接。内核在判断accept queue满后,直接丢弃新来的SYN报文。

排查此类问题时,可利用ss命令查看实时情况及netstat-s统计进行历史分析。确认接受队列满或timestamp问题后,针对应用程序优化或调整内核参数进行解决方案。

总结,本文主要探讨了per-host PAWS检查和accept queue满导致的SYN报文丢弃两种常见场景,并详细描述了现象、原理、代码逻辑及排查方法。这些场景基本覆盖了TCP协议栈丢弃SYN报文的大部分问题。遇到其他场景时,需要结合特定配置和代码逻辑进行逐一排查。

阅读剩余
THE END