首页 > 其他分享 >详解网络数据包接受的过程

详解网络数据包接受的过程

时间:2023-12-07 23:02:01浏览次数:30  
标签:调用 队列 rcv 网络 tcp 详解 TCP 数据包

在 tcp_v4_rcv 中,得到 TCP 的头之后,我们可以开始处理 TCP 层的事情。因为 TCP 层是分状态的,状态被维护在数据结构 struct sock 里面,因而我们要根据 IP 地址以及 TCP 头里面的内容,在 tcp_hashinfo 中找到这个包对应的 struct sock,从而得到这个包对应的连接的状态。

接下来,我们就根据不同的状态做不同的处理,TCP_LISTEN、TCP_NEW_SYN_RECV 状态属于连接建立过程中。TCP_TIME_WAIT 状态是连接结束的时候的状态。

我们来分析最主流的网络包的接收过程,这里面涉及三个队列:

  • backlog 队列
  • prequeue 队列
  • sk_receive_queue 队列

为什么接收网络包的过程,需要在这三个队列里面倒腾过来、倒腾过去呢?这是因为,同样一个网络包要在三个主体之间交接。

第一个主体是软中断的处理过程。在执行 tcp_v4_rcv 函数的时候,依然处于软中断的处理逻辑里,所以必然会占用这个软中断。

第二个主体就是用户态进程。如果用户态触发系统调用 read 读取网络包,也要从队列里面找。

第三个主体就是内核协议栈。哪怕用户进程没有调用 read,读取网络包,当网络包来的时候,也得有一个地方收着呀。

当前这个 sock 是不是正有一个用户态进程等着读数据呢,如果没有,内核协议栈也调用 tcp_add_backlog,暂存在 backlog 队列中,并且抓紧离开软中断的处理过程。

如果把 sysctl_tcp_low_latency 设置为 0,那就要放在 prequeue 队列中暂存,这样不用等待网络包处理完毕,就可以离开软中断的处理过程,但是会造成比较长的时延。如果把 sysctl_tcp_low_latency 设置为 1,我们还是调用 tcp_v4_do_rcv。

在 tcp_v4_do_rcv 中,分两种情况,一种情况是连接已经建立,处于 TCP_ESTABLISHED 状态,调用 tcp_rcv_established。另一种情况,就是其他的状态,调用 tcp_rcv_state_process。

对于 TCP 所有状态的处理,其中和连接建立相关的状态。

详解网络数据包接受的过程_tcp

在 tcp_data_queue 中,对于收到的网络包,我们要分情况进行处理。

第一种情况,seq == tp->rcv_nxt,说明来的网络包正是我服务端期望的下一个网络包。这个时候我们判断 sock_owned_by_user,也即用户进程也是正在等待读取,这种情况下,就直接 skb_copy_datagram_msg,将网络包拷贝给用户进程就可以了。

如果用户进程没有正在等待读取,或者因为内存原因没有能够拷贝成功,tcp_queue_rcv 里面还是将网络包放入 sk_receive_queue 队列。

接下来,tcp_rcv_nxt_update 将 tp->rcv_nxt 设置为 end_seq,也即当前的网络包接收成功后,更新下一个期待的网络包。

我们还会判断一下另一个队列,out_of_order_queue,也看看乱序队列的情况,看看乱序队列里面的包,会不会因为这个新的网络包的到来,也能放入到 sk_receive_queue 队列中。

乱序的包不能进入 sk_receive_queue 队列。因为一旦进入到这个队列,意味着可以发送给用户进程。然而,按照 TCP 的定义,用户进程应该是按顺序收到包的,没有排好序,就不能给用户进程。

第二种情况,end_seq 不大于 rcv_nxt,也即服务端期望网络包 5。但是,来了一个网络包 3,怎样才会出现这种情况呢?肯定是服务端早就收到了网络包 3,但是 ACK 没有到达客户端,中途丢了,那客户端就认为网络包 3 没有发送成功,于是又发送了一遍,这种情况下,要赶紧给客户端再发送一次 ACK,表示早就收到了。

第三种情况,seq 不小于 rcv_nxt + tcp_receive_window。这说明客户端发送得太猛了。本来 seq 肯定应该在接收窗口里面的,这样服务端才来得及处理,结果现在超出了接收窗口,说明客户端一下子把服务端给塞满了。

这种情况下,服务端不能再接收数据包了,只能发送 ACK 了,在 ACK 中会将接收窗口为 0 的情况告知客户端,客户端就知道不能再发送了。这个时候双方只能交互窗口探测数据包,直到服务端因为用户进程把数据读走了,空出接收窗口,才能在 ACK 里面再次告诉客户端,又有窗口了,又能发送数据包了。

第四种情况,seq 小于 rcv_nxt,但是 end_seq 大于 rcv_nxt,这说明从 seq 到 rcv_nxt 这部分网络包原来的 ACK 客户端没有收到,所以重新发送了一次,从 rcv_nxt 到 end_seq 时新发送的,可以放入 sk_receive_queue 队列。

当接收的网络包进入各种队列之后,接下来我们就要等待用户进程去读取它们了。

读取一个 socket,就像读取一个文件一样,读取 socket 的文件描述符,通过 read 系统调用。

read 系统调用对于一个文件描述符的操作,大致过程都是类似的。最终它会调用到用来表示一个打开文件的结构 stuct file 指向的 file_operations 操作。

整个过程可以分成以下几个层次。

  • 硬件网卡接收到网络包之后,通过 DMA 技术,将网络包放入 Ring Buffer;
  • 硬件网卡通过中断通知 CPU 新的网络包的到来;
  • 网卡驱动程序会注册中断处理函数 ixgb_intr;
  • 中断处理函数处理完需要暂时屏蔽中断的核心流程之后,通过软中断 NET_RX_SOFTIRQ 触发接下来的处理过程;
  • NET_RX_SOFTIRQ 软中断处理函数 net_rx_action,net_rx_action 会调用 napi_poll,进而调用 ixgb_clean_rx_irq,从 Ring Buffer 中读取数据到内核 struct sk_buff;
  • 调用 netif_receive_skb 进入内核网络协议栈,进行一些关于 VLAN 的二层逻辑处理后,调用 ip_rcv 进入三层 IP 层;
  • 在 IP 层,会处理 iptables 规则,然后调用 ip_local_deliver 交给更上层 TCP 层;
  • 在 TCP 层调用 tcp_v4_rcv,这里面有三个队列需要处理,如果当前的 Socket 不是正在被读;取,则放入 backlog 队列,如果正在被读取,不需要很实时的话,则放入 prequeue 队列,其他情况调用 tcp_v4_do_rcv;
  • 在 tcp_v4_do_rcv 中,如果是处于 TCP_ESTABLISHED 状态,调用 tcp_rcv_established,其他的状态,调用 tcp_rcv_state_process;
  • 在 tcp_rcv_established 中,调用 tcp_data_queue,如果序列号能够接的上,则放入 sk_receive_queue 队列;如果序列号接不上,则暂时放入 out_of_order_queue 队列,等序列号能够接上的时候,再放入 sk_receive_queue 队列。

接下来就是用户态读取网络包的过程,这个过程分成几个层次。

  • VFS 层:read 系统调用找到 struct file,根据里面的 file_operations 的定义,调用 sock_read_iter 函数。sock_read_iter 函数调用 sock_recvmsg 函数。
  • Socket 层:从 struct file 里面的 private_data 得到 struct socket,根据里面 ops 的定义,调用 inet_recvmsg 函数。
  • Sock 层:从 struct socket 里面的 sk 得到 struct sock,根据里面 sk_prot 的定义,调用 tcp_recvmsg 函数。
  • TCP 层:tcp_recvmsg 函数会依次读取 receive_queue 队列、prequeue 队列和 backlog 队列。

详解网络数据包接受的过程_tcp_02

详解网络数据包接受的过程_tcp_03



标签:调用,队列,rcv,网络,tcp,详解,TCP,数据包
From: https://blog.51cto.com/key3feng/8728313

相关文章

  • Thread常见方法:join 方法详解
    为什么需要join下面的代码执行,打印r是什么?staticintr=0;publicstaticvoidmain(String[]args)throwsInterruptedException{test1();}privatestaticvoidtest1()throwsInterruptedException{log.debug("开始");Threadt1=newThread(()->{log.de......
  • 蚂蚁SEO网络蜘蛛可以帮助我们做什么
    蜘蛛池是一种特殊的搜索引擎优化技术,通过大量的蜘蛛池增加网站的权重和收录,从而提升网站的排名和流量。那么,蜘蛛池可以帮助我们做什么呢?如何联系蚂蚁seo?baidu搜索:如何联系蚂蚁SEO?baidu搜索:如何联系蚂蚁SEO?baidu搜索:如何联系蚂蚁SEO?首先,蜘蛛池可以帮助我们快速提升网站的权重和收录......
  • 《2023-2024-1 20232427《网络空间安全导论》第五周学习总结》
    《2023-2024-120232427《网络空间安全导论》第五周学习总结》教学学习内容总结第五章内容安全基础5.1信息内容安全概述社会信息化和网络化发展加快,现在全球数据增长十分迅速,数据内容成为了互联网的中心关注点。各种社交网络不断涌现。但是!互联网和信息媒体的发展带来了许多......
  • HTTPS 请求中的证书验证详解(Python版)
    在网络通信中,HTTPS是一种通过SSL/TLS加密的安全HTTP通信协议。证书在HTTPS中扮演着至关重要的角色,用于验证服务器身份并加密数据传输。本文将深入探讨Python中HTTPS请求中的证书相关内容,并提供详细的代码示例。1.证书的基本概念SSL/TLS证书是一种由证书颁发机构签发的......
  • Java File类详解(下)练习部分
    练习第一题需求:在当前模块下的aaa文件夹中创建一个a.txt文件importjava.io.File;importjava.io.IOException;publicclassFileExer01{publicstaticvoidmain(String[]args)throwsIOException{Filef1=newFile("AllInOne\\aaa");f1.mkdirs();Filesrc=ne......
  • 2023-2024-1 20232312 《网络空间安全导论》第五周学习
    2023-2024-120232312《网络空间安全导论》第五周学习教材学习内容总结思维导图5.1信息安全内容概述一、互联网现状:开放性、异构性、移动性、动态性二、不良信息&&不规范行为产生原因:相关方面规范和管理措施未随互联网同步发展互联网提供思想碰撞场所5.2信......
  • UML学习详解
    一、用例图:描述角色以及角色与用例之间的连接关系。说明的是谁要使用系统,以及他们使用该系统可以做些什么。1.用例图的含义由参与者(Actor)、用例(UseCase)以及它们之间的关系构成的用于描述系统功能的动态视图称为用例图。要在用例图上显示某个用例,可绘制一个椭圆,然后将用例的......
  • 11K+ Star!图解计算机网络、操作系统、计算机组成、数据库!
    大家好,我是Java陈序员。俗话说得好,面试造火箭,入职拧螺丝。我们在工作中,其实很少用到一些计算机底层知识,往往只要编码完事。但是,知其然还要知其所以然,我们不仅要做一个合格的“CV工程师”,更是要掌握一些底层原理!计算机基础知识,作为计算机的底层原理,往往是晦涩难懂,如果没用心的......
  • EF CodeFirst 数据注解特性详解
    数据注解特性是.NET特性,可以在EF或者EFCore中,应用于实体类上或者属性上进行生成数据表,并对表名、字段类型、长度、主键、是否为空、外键等进行设置。1、命名空间在EF6和EFCore中,数据注解特性包含在System.ComponentModel.DataAnnotations命名空间和System.ComponentModel.Dat......
  • 2023-2024-1学期20232423《网络及空间安全导论》第五周学习总结
    教材学习——内容安全基础信息内容安全概述信息内容的安全分为:政治信息安全、军事信息安全、商业信息安全。全球数据的爆炸增长,让数据内容成为互联网的中心关注点,大数据技术逐步演化为重要生产力。同时,随着数据内容的价值不断提高,保护数据内容安全迫在眉睫。网络战的打响,注......