linux网络子系统分析(一)——linux网络协议栈的分层之综述

目录

一、概述

二、Linux网络子系统的分层

2.1 为何要分层

2.2 协议无关接口

2.3 网络协议层

2.4 设备无关接口

2.5 设备层

三、参考


一、概述

开篇,总结一下对linux协议栈的理解,备忘。

关于符号约定,代码路径使用[]包含,结构体使用结构体定义名称+{}表示

二、Linux网络子系统的分层

2.1 为何要分层

linux网络子系统实现需要:

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

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

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.h sock_register 为网络协议层提供address family的注册接口
proto{}  include/net/sock.h

proto_register/

inet_register_protosw

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

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

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.h inet_add_protocol 传输层和网络层收包解复用
packet_type{} include/linux/netdevice.h dev_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.h register_netdev 提供操作具体物理设备的通用接口

2.5 设备层

具体的网络驱动实现,这里先不详细展开。

三、参考

【1】Linux 网络栈剖析

【2】浅析Linux网络子系统(一)

【3】深入浅出Linux TCP/IP协议栈  罗钰 编著

猜你喜欢

转载自blog.csdn.net/whenloce/article/details/84103027
今日推荐