Linux 网络子系统分析1

Linux 网络子系统分析1(基于Linux6.6)---协议栈分层综述

一、概述

Linux 操作系统的网络协议栈是一个多层次的模块化架构,它负责处理从应用程序到物理网络之间的所有数据传输任务。这个协议栈遵循了经典的 OSI(开放系统互联)模型和 TCP/IP 模型的分层原则,通过将复杂的网络通信任务分解为多个层次,每一层都负责特定的功能和任务。Linux 网络协议栈的设计以其灵活性、可扩展性和可维护性著称。

在 Linux 中,协议栈的分层从最底层的物理传输层到最顶层的应用层,主要可以划分为以下几个层次:数据链路层(Link Layer)、网络层(Network Layer)、传输层(Transport Layer)、应用层(Application Layer)和套接字接口(Socket Layer)。每一层通过特定的接口与上层和下层交互,保证了协议栈的模块化和解耦。

1. 数据链路层(Link Layer)

数据链路层位于最底层,负责与网络硬件(如网卡)直接交互。它处理数据的物理传输和链路层协议(如以太网、Wi-Fi、PPP等),并负责对数据进行帧封装。数据链路层主要包括以下几个组件:

  • 网卡驱动(Network Interface Drivers):负责与网络硬件直接交互,处理发送和接收数据包的硬件操作。
  • 设备管理(Network Device Management):负责对网络设备的管理、初始化、启动、停止等操作。
  • 链路层协议(Ethernet, Wi-Fi 等):对传输的数据进行帧封装,包括错误检测和数据校验(如 CRC)。

数据链路层通过硬件设备将数据包传输到网络层,通常使用 Ethernet(以太网)协议来实现。

2. 网络层(Network Layer)

网络层主要负责数据包的路由和转发,它的核心协议是 IP(Internet Protocol),负责在网络中定位设备和传递数据包。它的主要功能包括:

  • IP协议(IPv4和IPv6):负责数据包的寻址与路由。通过 IP 地址来定位网络中的设备,并使用路由表将数据包从源地址转发到目标地址。
  • ARP协议(Address Resolution Protocol):将 IP 地址映射到 MAC 地址,完成 IP 地址与物理地址之间的转换。
  • 路由与转发:根据路由表将数据包转发到适当的下一跳。Linux 内核通过 net/ipv4 目录下的代码实现路由功能。
  • 数据包分片和重组:IP 协议支持对过大的数据包进行分片,并在目标主机处重新组装。

在网络层,Linux 支持 IPv4 和 IPv6 两种协议栈,允许系统根据配置和网络环境选择不同的协议版本。

3. 传输层(Transport Layer)

传输层负责确保端到端的数据传输可靠性。它在网络层之上,主要提供 TCPUDP 两种传输协议:

  • TCP(Transmission Control Protocol)

    • 提供可靠、面向连接的服务,确保数据的顺序和完整性。
    • 支持流量控制、拥塞控制、重传机制等。
    • TCP 使用 三次握手 建立连接,确保数据可靠传输。
    • 通过 TCP窗口 控制数据流的速率,避免拥塞。
  • UDP(User Datagram Protocol)

    • 提供不可靠、无连接的服务,适用于要求低延迟和高效率的应用,如视频流、DNS查询等。
    • UDP 不做流量控制、拥塞控制和错误重传。

传输层的功能包括:

  • 端口映射:通过源端口和目标端口来区分不同应用之间的数据流。
  • 流量控制:TCP协议通过滑动窗口机制来控制数据传输的速度,避免接收方缓冲区溢出。
  • 错误检测:UDP 和 TCP 都使用校验和来检查数据的完整性。

4. 应用层(Application Layer)

应用层位于协议栈的最顶层,负责为用户提供网络服务和应用协议支持。它包括了各种应用层协议,如 HTTPFTPSMTPDNS 等,主要提供以下功能:

  • 应用层协议:如 HTTP(Web)、FTP(文件传输)、SMTP(邮件传输)等,为用户提供特定的网络服务。
  • 套接字接口(Socket API):为应用程序提供网络通信接口。Linux 提供了一组系统调用,如 socket(), bind(), connect(), send(), recv() 等,使得应用层能够通过编程方式访问下层的网络服务。

应用层不直接参与协议栈的转发和路由工作,而是通过系统调用与套接字接口与下层进行交互,将应用数据传递到传输层,然后通过网络层和数据链路层发送出去。

5. Socket 接口层(Socket Layer)

Socket API 提供了应用层与网络协议栈之间的接口,它是应用程序和网络协议栈之间的桥梁。通过 socket 接口,用户空间的应用程序可以访问到 Linux 内核的网络协议栈。这个接口抽象了不同协议之间的复杂性,简化了应用程序的开发。

  • 套接字类型

    • SOCK_STREAM:TCP协议,提供可靠的面向连接的流式服务。
    • SOCK_DGRAM:UDP协议,提供不可靠的无连接服务。
    • SOCK_RAW:原始套接字,允许访问网络层和数据链路层。
  • 网络通信模型:应用程序通过套接字创建连接,进行数据的发送和接收。应用程序通常不需要关心协议栈的具体实现,只需要使用标准的套接字 API。

6. Linux 协议栈的实现特点

  • 模块化设计:Linux 网络协议栈的各层实现是高度模块化的,每一层都可以独立开发、维护和替换。网络协议的添加与修改可以相对独立地进行,而不影响其他层的功能。
  • 性能优化:Linux 内核提供了多种性能优化机制,如多队列网络设备支持、TCP 拓扑优化、接收/发送缓冲区管理等。
  • 支持多协议栈:Linux 不仅支持传统的 IPv4 和 IPv6 协议栈,还可以通过插件方式支持更多的协议,如 ARP、MPLS、VPN 等。
  • 网络命名空间(Network Namespace):Linux 提供了网络命名空间功能,允许每个进程在独立的网络环境中运行,支持容器技术中的虚拟网络。

二、Linux网络子系统的分层

2.1、为何要分层

linux网络子系统实现需要:

  • 支持不同的协议族 ( INET, INET6, UNIX, NETLINK...)
  • 支持不同的网络设备
  • 支持统一的BSD socket API

需要屏蔽协议、硬件、平台(API)的差异,因而采用分层结构:

在 Linux 中,网络子系统的架构通常可以分为以下几个主要层次(从底到顶):

  • 数据链路层(Link Layer): 主要负责网络设备的驱动程序和底层的硬件操作,包括处理设备驱动、网卡的初始化、数据帧的发送和接收等。

  • 网络层(Network Layer): 处理 IP 协议相关的工作,负责 IP 数据包的路由、转发、地址映射等。这一层主要涉及 IPv4 和 IPv6 协议的处理。

  • 传输层(Transport Layer): 提供可靠或不可靠的数据传输机制,主要由 TCP(传输控制协议)和 UDP(用户数据报协议)实现,处理端到端的通信、流量控制、错误检测等。

  • 应用层(Application Layer): 位于最上层,负责与用户程序进行交互,如 HTTP、FTP、SMTP 等应用协议。这一层的协议栈为上层应用程序提供接口。

  • Socket API: 这是应用层和内核网络子系统之间的接口,提供了系统调用来操作网络(如 socket(), bind(), send() 等)。

2.2、协议无关接口

 协议无关接口对应socket layer:

上图左半部分的socket layer提供了两个接口:

  1. 向上层提供address family相关接口——net_proto_family{}
  2. 向上层提供对应于BSD socket 的接口——proto_ops{}

同时,网络协议层为socket层提供具体协议接口——proto{},以上三个接口功能即作用总结如下表:

接口名称定义位置注册接口作用
net_proto_family{}include/linux/net.hsock_register为网络协议层提供address family的注册接口
proto{} include/net/sock.h

proto_register/

inet_register_protosw

为网络协议层提供protocol注册接口
proto_ops{}include/linux/net.hinet_register_protosw为VFS提供BSD socket注册接口

协议栈的简化分层组织(假设的图示):

+---------------------+
|     Application     |      <-- 应用层
+---------------------+
|     Socket Layer    |      <-- 套接字接口层(协议无关接口)
+---------------------+
|  Transport Layer    |      <-- 传输层 (TCP/UDP)
+---------------------+
|  Network Layer      |      <-- 网络层 (IP/ARP)
+---------------------+
|  Link Layer         |      <-- 数据链路层 (Ethernet, Wi-Fi等)
+---------------------+
|  Physical Layer     |      <-- 物理层 (网络硬件)
+---------------------+

下面以具体的协议INET来分析,对于address family接口,可以看到family<->create的对应

include/linux/net.h 

struct net_proto_family {
	int		family;
	int		(*create)(struct net *net, struct socket *sock,
				  int protocol, int kern);
	struct module	*owner;
};

对于proto接口,情况稍有不同,proto基本上是方法的合集,需要建立和type的映射关系,另一方面作为对上层提供的proto_ops,也需要建立和type的对应,因此inet引入另一个结构,集中进行管理注册,该结构是inet_protosw

include/net/protocol.h

/* This is used to register socket interfaces for IP protocols.  */
struct inet_protosw {
	struct list_head list;

        /* These two fields form the lookup key.  */
	unsigned short	 type;	   /* This is the 2nd argument to socket(2). */
	unsigned short	 protocol; /* This is the L4 protocol number.  */

	struct proto	 *prot;
	const struct proto_ops *ops;
  
	unsigned char	 flags;      /* See INET_PROTOSW_* below.  */
};

看定义看到type<->proto<->proto_ops的对应关系

实际上实现也是如此,通过接口inet_register_protosw将proto和proto_ops加入到inetsw的type数组中便于检索。这里面还有一个永久协议的概念,参见其中的flag参数。

至此,socket层的抽象接口已经建立并管理起来了。

再来看图的右半部分,可以发现每一层都有一个抽象的实体与之对应:file,socket,sock,从图中可以看出socket的承上启下的作用:向上指向file,向下指向sock,所以上面描述的三个分层可以看作是以抽象数据结构作为对象,使用抽象出来的接口作为对象拥有的行为。

这里sock是一个基类,不同的address family有不同的sock,如对于INET来说,初始化为inet_sock。

2.3、网络协议层

以INET层为例,网络协议层分为transport layer和network layer:

这里看到提供接口的方向是向下的,实际对应报文接收流程,报文由下到上需要解复用。

网络层和传输层之间使用net_protocol建立protocol<->handler的对应关系,即通过IP包头protocol分析出传输层handler(tcp/udp/icmp/igmp)在网络层和设备无关层使用packet_type建立type<->func的对应关系,即通过二层头type分析出网络层func(arp, ip)。

接口定义位置注册接口作用
net_protocol{}include/net/protocol.hinet_add_protocol传输层和网络层收包解复用
packet_type{}include/linux/netdevice.hdev_add_pack网络层和设备无关层收报解复用

上图中只说明了发方向,对于发方向,由于在INET中,网络层只有IP,因此就无需提供注册了,网络层向传输层提供的接口有:

ip_append_data/ip_append_page/ip_push_pending_frames。

ip_append_data() and ip_append_page() can make one large IP datagram from many pieces of data. Each pieces will be holded on the socket until ip_push_pending_frames() is called

2.4、设备无关接口

 net_device是对网络设备的抽象,针对net_device有许多通用的接口,在发送侧,向网络层提供接口名称为dev_queue_xmit的接口,这里还有一个QOS层,如上图所示

接口名称定义位置注册接口作用
net_device_ops{}include/linux/netdevice.hregister_netdev提供操作具体物理设备的通用接口

2.5、设备层

1. 网络设备层概述

网络设备层通常包括以下几个关键部分:

  • 网络设备驱动程序:用于控制和管理计算机中的物理网络接口(如以太网卡、无线网卡等)。
  • 数据链路层协议:如以太网协议、Wi-Fi 协议等,负责点对点的数据帧传输。
  • 网络设备接口(Network Interface):Linux 中通过 net_device 结构体来表示每个网络接口。

2. Linux 网络设备结构

在 Linux 中,所有的网络设备都被抽象为 net_device 结构体,这个结构体是网络接口的核心数据结构。每个 net_device 代表一个网络接口(如 eth0、wlan0 等)。通过它,操作系统能够与物理设备进行交互。

主要结构体字段包括:

  • name:设备名称(如 eth0、wlan0)。
  • dev_addr:设备的硬件地址(MAC 地址)。
  • mtu:最大传输单元(Maximum Transmission Unit),指定设备支持的最大数据包大小。
  • type:设备的类型,例如 ARPHRD_ETHER 表示以太网设备。
  • flags:设备的状态标志,如 IFF_UP 表示设备已经启用。
  • tx_queue_len:设备的发送队列长度,表示设备可以缓存的最大数据包数量。
  • operstate:设备的当前状态,如 IF_OPER_UP 表示设备已经启动。

3. Linux 网络设备驱动程序

Linux 的网络设备驱动程序负责管理和控制实际的硬件设备(例如网络适配器)。网络设备驱动程序的主要任务是:

  • 初始化硬件设备:驱动程序负责设备的初始化,如设置网卡的 MAC 地址、配置设备的工作模式等。
  • 发送和接收数据:驱动程序提供函数接口,允许操作系统将数据帧传递给网络设备,也能将接收到的帧传递给内核网络协议栈。
  • 错误处理和性能监控:包括传输错误、缓冲区溢出、设备性能统计等。

驱动程序的工作流程:

  1. 初始化:设备启动时,驱动程序会配置硬件并分配资源。
  2. 数据接收:当设备收到数据包时,驱动程序将其传递给网络协议栈。
  3. 数据发送:当协议栈需要发送数据时,它会将数据传递给设备驱动程序,驱动程序负责将数据转换为物理帧,并通过网络设备发送出去。

4. 数据链路层协议

数据链路层负责在物理网络上传输数据帧。常见的数据链路层协议有:

  • 以太网协议 (Ethernet):以太网是最常见的局域网协议,它负责将网络数据封装成帧,并通过物理媒体传输。
  • Wi-Fi (802.11):无线局域网协议,用于通过无线信号传输数据帧。

Linux 中,网络设备通常使用以太网协议,因此在设备层的数据传输使用的是 以太网帧格式。以太网帧包括:

  • 前导码(Preamble):用于同步发送和接收设备。
  • 目标 MAC 地址:接收设备的硬件地址。
  • 源 MAC 地址:发送设备的硬件地址。
  • 类型字段(EtherType):指示数据部分的协议类型,如 0x0800 表示 IP 数据包。
  • 数据:要传输的数据。
  • CRC 校验:用于错误检测。

5. 网络设备与协议栈的交互

网络设备层位于操作系统网络协议栈的底部,与上层协议栈(如 IP、TCP)进行交互。数据流动的过程如下:

  1. 数据发送流程

    • 应用层通过套接字将数据传输到传输层(如 TCP 或 UDP)。
    • 传输层将数据交给网络层,网络层添加 IP 头部并生成数据包。
    • 数据包被传递到数据链路层,链路层负责将其封装为以太网帧。
    • 最后,通过设备驱动程序将数据帧发送到网络接口,物理设备通过电缆或无线信号将数据传输到目标设备。
  2. 数据接收流程

    • 网络设备接收到数据帧后,设备驱动程序将其提取并交给数据链路层。
    • 数据链路层解析以太网帧,并将有效载荷传递给网络层。
    • 网络层处理 IP 地址,并将数据包传递给传输层,最终传递给应用程序。

6. Linux 网络设备管理命令

Linux 提供了一些命令来管理网络设备,以下是常用的网络设备管理命令:

  • ifconfig:显示或配置网络接口的基本信息,如 IP 地址、MAC 地址、接口状态等(在某些 Linux 发行版中已经被 ip 命令替代)。
  • ip link:用于显示或配置网络接口的详细信息,例如查看接口的状态、修改接口的 MAC 地址等。
  • ethtool:用于查询和修改网卡的配置(如速率、双工模式等)。
  • mii-tool:用于查询和设置网卡的 MII (Media Independent Interface) 配置。
  • lspci:查看系统中所有 PCI 设备,包括网络设备。

7. 网络设备和内核模块

网络设备通常由内核模块来管理,内核模块提供了对硬件的访问接口。Linux 支持多种不同的硬件设备,并通过内核模块加载特定的驱动程序来支持它们。

  • 驱动程序模块:例如 e1000(Intel 网卡驱动)、r8169(Realtek 网卡驱动)。
  • 通用网络协议模块:如 802.11(用于无线网络设备的驱动)和 bridge(用于虚拟交换机和网桥的驱动)等。

可以通过以下命令加载或卸载网络驱动程序模块:

modprobe e1000  # 加载 Intel 网卡驱动模块
rmmod e1000     # 卸载该驱动模块

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值