Linux协议栈(8)——传输层实现

简介: Linux协议栈(8)——传输层实现 ip_local_deliver负责分发IP分组传输的数据内容。基于IP的主要传输协议分别是UDP和TCP。处理函数分别是udp_rcv和tcp_rcv。

Linux协议栈(8)——传输层实现

ip_local_deliver负责分发IP分组传输的数据内容。基于IP的主要传输协议分别是UDP和TCP。处理函数分别是udp_rcv和tcp_rcv。

1.1.1.1  接收

1.1.1.1.1          tcp接收

函数tcp_v4_rcv()定义在net/ipv4/tcp_ipv4.c中负责接收来自网络层的TCP数据包。相比UDP,TCP在内核中实现要困难得多,其状态转换如下图,珍藏多年的一张好图,高清图可以从网上下载。

0d62ad21bd0365c51b5165b09b6ae64f8ead0da2

  tcp报头定义在include/uapi/linux/tcp.h

struct tcphdr {         

        __be16  source; 

        __be16  dest;   

        __be32  seq;    

        __be32  ack_seq;

#if defined(__LITTLE_ENDIAN_BITFIELD)

        __u16   res1:4

                doff:4

                fin:1,  

                syn:1,

                rst:1,

                psh:1,  

                ack:1,

                urg:1,  

                ece:1,

                cwr:1;  

#elif defined(__BIG_ENDIAN_BITFIELD)

        __u16   doff:4,

                res1:4

                cwr:1,  

                ece:1,  

                urg:1,  

                ack:1,  

                psh:1,  

                rst:1,  

                syn:1,

                fin:1;  

#else 

#error  "Adjust your <asm/byteorder.h> defines"

#endif                  

        __be16  window; 

        __sum16 check;  

        __be16  urg_ptr;

};

tcp协议对象,位于net/ipv4/af_inet.c文件中

static struct net_protocol tcp_protocol = {

        .early_demux    =       tcp_v4_early_demux,

        .early_demux_handler =  tcp_v4_early_demux,

        .handler        =       tcp_v4_rcv,

        .err_handler    =       tcp_v4_err,

        .no_policy      =       1,  

        .netns_ok       =       1,  

        .icmp_strict_tag_validation = 1,

};

 在inet_init(net/ipv4/af_inet.c)函数中调用inet_add_protocol(net/ipv4/protocol.c)函数来添加协议。

  tcp定时器定义在net/ipv4/tcp_timer.c中,有四个定时器:重传定时器、延迟确认定时器、存活定时器、零窗口探测定时器。

TCP的接收入口是tcp_v4_rcv, 调用__inet_lookup_skb函数,该函数会调用__inet_lookup,调用

__inet_lookup_established函数,检测套接字,没有套接字就调用__inet_lookup_listener.

  根据链接的状态,如果sk->sk_state == TCP_LISTEN,调用tcp_v4_do_rcv,进入TCP状态自动机。

  代码流程图如下:

1a0a4cfe17067763a6885f11a905cc8483b3edab

 


1.1.1.1.2          udp接收

  udp_rcv是处理UDP数据包的函数,定义在net/ipv4/udp.c,该函数是__udp4_lib_rcv函数的包装函数。入参包含套接字缓冲区。会调用__udp4_lib_lookup_skb函数在udptable中找套接字,找到则调用udp_queue_rcv_skb函数。

            udp包头文件定义在:include/uapi/linux/udp.h 文件中。

struct udphdr {

        __be16  source;

        __be16  dest;

        __be16  len;

        __sum16 check;  

};


 f9ce1c7e4faf3f8bb48f33263184e2ed351e1477

1.1.1.2  发送

1.1.1.2.1          tcp发送分组

  tcp分组的发送从tcp_sendmsg函数调用开始。tcp_sendmsg(net/ipv4/tcp.c)函数会首先检查已经建立的 TCP connection 的状态,然后获取该连接的MSS,开始发送流程。

  构造 TCP 段的 playload:它在内核空间中创建该 packet 的 sk_buffer 数据结构的实例 skb,从 用户空间的 buffer 中拷贝 packet 的数据到 skb 的 buffer。构造 TCP header。

  计算 TCP 校验和(checksum)和 顺序号 (sequence number)。TCP的校验和是必需的。然后发到 IP 层处理:调用 IP handler 句柄 ip_queue_xmit,将 skb 传入 IP 处理流程。

  SOCK_STREAM类socket的TCP层操作函数集实例为tcp_prot定义在net/ipv4/tcp_ipv4.c文件中。之后调用tcp_write_xmit()来把sock发送队列中的skb尽量地发送出去。

传输层协议inet_sendmsg的proto指向的操作也不一样,而对于TCP协议,inet_sendmsg指向tcp_sendmsg函数,

 

1.1.1.2.2          udp发送分组
对于 UDP socket 来说, sendto 调用,真正去做工作的是 udp_sendmsg 这个函数 , 定义在 net/ipv4/udp.c文件中
目录
相关文章
|
1月前
|
存储 Shell Linux
【Shell 命令集合 磁盘管理 】⭐⭐ Linux 显示当前shell会话中的目录栈 dirs命令使用教程
【Shell 命令集合 磁盘管理 】⭐⭐ Linux 显示当前shell会话中的目录栈 dirs命令使用教程
27 0
|
1月前
|
Shell Linux C语言
【Shell 命令集合 磁盘管理 】Linux 显示当前shell会话中的目录栈 dirs命令使用教程
【Shell 命令集合 磁盘管理 】Linux 显示当前shell会话中的目录栈 dirs命令使用教程
35 1
|
2月前
|
传感器 网络协议 物联网
在Linux中搭建Mosquitto MQTT协议消息服务端并结合内网穿透工具实现公网访问
Mosquitto是一个开源的消息代理,它实现了MQTT协议版本3.1和3.1.1。它可以在不同的平台上运行,包括Windows、Linux、macOS等。mosquitto可以用于物联网、传感器、移动应用程序等场景,提供了一种轻量级的、可靠的、基于发布/订阅模式的消息传递机制。
|
16天前
|
网络协议 Linux SDN
虚拟网络设备与Linux网络协议栈
在现代计算环境中,虚拟网络设备在实现灵活的网络配置和隔离方面发挥了至关重要的作用🔧,特别是在容器化和虚拟化技术广泛应用的今天🌐。而Linux网络协议栈则是操作系统处理网络通信的核心💻,它支持广泛的协议和网络服务🌍,确保数据正确地在网络中传输。本文将深入分析虚拟网络设备与Linux网络协议栈的关联,揭示它们如何共同工作以支持复杂的网络需求。
|
1月前
|
Linux 网络安全
Linux NFS协议详解
Linux NFS协议详解
32 5
|
3月前
|
网络协议 Linux C++
Linux C/C++ websocket协议与服务器实现
Linux C/C++ websocket协议与服务器实现
69 0
|
3月前
|
存储 网络协议 Linux
Linux C/C++ 开发(学习笔记九 ):DNS协议与请求的实现
Linux C/C++ 开发(学习笔记九 ):DNS协议与请求的实现
55 0
|
4月前
|
网络协议 Linux 数据处理
Linux网络编程(各种协议模型的基础知识)
Linux网络编程(各种协议模型的基础知识)
45 0
|
4月前
|
缓存 网络协议 算法
深入理解Linux网络——TCP协议三次握手和四次挥手详细流程
• 找到套接字:创建内核对象的时候,fd会跟file对象做通过fd_install关联起来,通过进程的fd_table就可以找到对应的file,而file的private指针就指向了socket对象,所以根据fd即可找到套接字 • 判断当前套接字的状态:只有SS_UNCONNECTED状态(刚创建的套接字就是该状态)才会继续,其他状态都会报错 1. 注意此处是socket的状态,而不是sock的状态 2. 会将socket状态更改为SS_CONNECTING • 更改sock状态为TCP_SYN_SENT
|
4月前
|
缓存 网络协议 算法
Linux网络-MAC协议
Linux网络-MAC协议