精华内容
下载资源
问答
  • 协议栈的内部结构
    2021-07-13 08:11:29

    协议栈的内部如图2.1所示,分为几个部分,分别承担不同的功能。这张图中的上下关系是有一定规则的,上面的部分会向下面的部分委派工作,下面的部分接受委派的工作并实际执行,这一点大家在看图时可以参考一下。当然,这一上下关系只是一个总体的规则,其中也有一部分上下关系不明确,或者上下关系相反的情况,所以也不必过于纠结。

    在这里插入图片描述
    上层会向下层逐层委派工作。

    下面我们从上到下来看一遍。图中最上面的部分是网络应用程序,也就是浏览器、电子邮件客户端、Web服务器、电子邮件服务器等程序,它们会将收发数据等工作委派给下层的部分来完成。当然,除了浏览器之外,其他应用程序在网络上收发数据的操作也都是类似上面这样的,也就是说,尽管不同的应用程序收发的数据内容不同,但收发数据的操作是共通的

    应用程序的下面是Socket库,其中包括解析器,解析器用来向DNS服务器发出查询

    再下面就是操作系统内部了,其中包括协议栈。协议栈的上半部分有两块,分别是负责用TCP协议收发数据的部分和负责用UDP协议收发数据的部分,它们会接受应用程序的委托执行收发数据的操作。

    浏览器、邮件等一般应用程序收发数据时用TCP;DNS查询等收发较短的控制数据时用UDP。

    下面一半是用IP协议控制网络包收发操作的部分。在互联网上传送数据时,数据会被切分成一个一个的网络包,而将网络包发送给通信对象的操作就是由IP来负责的。

    IP下面的网卡驱动程序负责控制网卡硬件,而最下面的网卡则负责完成实际的收发操作,也就是对网线中的信号执行发送和接收的操作。

    socket的实体就是IP+port

    在协议栈内部有一块用于存放控制信息的内存空间,这里记录了用于控制通信操作的控制信息,例如通信对象的IP地址、端口号、通信操作的进行状态等。本来socket就只是一个概念而已,并不存在实体,如果一定要赋予它一个实体,我们可以说这些控制信息就是套接字的实体,或者说存放控制信息的内存空间就是套接字的实体。

    协议栈在执行操作时需要参阅这些控制信息

    例如,在发送数据时,需要看一看套接字中的通信对象IP地址和port,以便向指定的IP地址和port发送数据。

    在发送数据之后,协议栈需要等待对方返回收到数据的响应信息,但数据也可能在中途丢失,永远也等不到对方的响应。在这样的情况下,我们不能一直等下去,需要在等待一定时间之后重新发送丢失的数据,这就需要协议栈能够知道执行发送数据操作后过了多长时间。为此,套接字中必须要记录是否已经收到响应,以及发送数据后经过了多长时间,才能根据这些信息按照需要执行重发操作。

    套接字中记录了用于控制通信操作的各种控制信息,协议栈则需要根据这些信息判断下一步的行动,这就是套接字的作用。

    协议栈是根据套接字中记录的控制信息来工作的。

    讲了这么多抽象的概念,可能大家还不太容易理解,所以下面来看看真正的套接字。在Windows中可以用netstat命令显示套接字内容(图2.2)。图中每一行相当于一个套接字,当创建套接字时,就会在这里增加一行新的控制信息,赋予“即将开始通信”的状态,并进行通信的准备工作,如分配用于临时存放收发数据的缓冲区空间。在这里插入图片描述

    调用socket时的操作

    看过套接字的具体样子之后,我们的探索之旅将继续前进,看一看当浏览器调用socket、connect等Socket库中的程序组件时,协议栈内部是如何工作的。

    首先,我们再来看一下浏览器通过Socket库向协议栈发出委托的一系列操作(图2.3)。这张图和介绍浏览器时用的那张图的内容大体相同,只作了少许修改。正如我们之前讲过的那样,浏览器委托协议栈使用TCP协议来收发数据,因此下面的讲解都是关于TCP的。

    首先是创建socket的阶段。如图2.3①所示,应用程序调用socket申请创建套接字,协议栈根据应用程序的申请执行创建套接字的操作

    在这个过程中,协议栈首先会分配用于存放一个socket所需的内存空间

    用于记录套接字控制信息的内存空间并不是一开始就存在的,因此我们先要开辟出这样一块空间来,这相当于为控制信息准备一个容器。但光一个容器并没有什么用,还需要往里面存入控制信息。套接字刚刚创建时,数据收发操作还没有开始,因此需要在套接字的内存空间中写入表示这一初始状态的控制信息。到这里,创建套接字的操作就完成了。

    在这里插入图片描述
    创建套接字时,首先分配一个套接字所需的内存空间,然后向其中写入初始状态。

    接下来,需要将表示这个套接字的描述符告知应用程序。描述符相当于用来区分协议栈中的多个套接字的号码牌。

    收到描述符之后,应用程序在向协议栈进行收发数据委托时就需要提供这个描述符。由于套接字中记录了通信双方的信息以及通信处于怎样的状态,所以只要通过描述符确定了相应的套接字,协议栈就能够获取所有的相关信息,这样一来,应用程序就不需要每次都告诉协议栈应该和谁进行通信了。

    更多相关内容
  • Bluetooth Mesh协议栈架构: Mesh是基于BLE协议基础上的一个协议,基本扩展了BLE的能力。通俗一點說就是蓝牙MESH是构建于BLE之上的网络协议。 广播连接的一个基本特性: 广播只能单方向只发送数据,要快速...

    Bluetooth BR/EDR (传统蓝牙)协议栈整体架构:

    Bluetooth Low Energy​ 低功耗蓝牙协议栈的体系结构如下:

    Bluetooth Mesh协议栈架构:

    Mesh是基于BLE协议基础上的一个协议,基本扩展了BLE的能力。通俗一點說就是蓝牙MESH是构建于BLE之上的网络协议。

    广播连接的一个基本特性:

    广播只能单方向只发送数据,要快速可靠双向通信,必须要建立连接(当然,你也可以即广播也扫描不建立连接实现双向通信,但这样效率不高)。那么BLE是如何建立连接呢?首先得知道啥时可连接广播。下图为Radio TX 或者RX 活跃时,则拉高对应的IO口, 然后用逻辑分析仪捕获的瞬间图。

    可连接广播与不可连接广播

    由上图可以看到,可连接广播,在Radio层面上每次在一个信道上发送完后,会开一个短暂的RX,如果此时,有其他设备发送连接请求时,则瞬间两者就建立连接了。

    BR/EDR与BLE的区别:

    首先一个基本概念:

    低功耗蓝牙采用了高斯频移键控(GFSK)。这里我们先抛开蓝牙的协议,单纯从Radio的角度看收发通信,Radio发送到空中的数据比较简单,要么是0,要么是1,接收端每次也只能在一小段(一个信道)频率上扫描。比方说在2402MHz这个频点上发送数据,发送的频率小于2402MHz负频代表发送0,发送的频率大于2402MHz代表发送1。

    ​信道:

    传统蓝牙BR/EDR,有79个窄信道。 而低功耗蓝牙,使用40个无线信道。3个广播信道(初级广播),37个数据信道。Radio每次发送数据只能往一个信道里面发送,大多数芯片的Radio(接收方)每次也只能扫描一个信道的数据。

    BLE 的广播在没有引入扩展广播之前,是一个比较简单的概念。这里介绍用得最普遍的在1M PHY层上的广播。在没有建立连接之前,设备与设备之前只能通过广播发送数据,为了增加发送数据的可靠性,避免频点被一直干扰,所以BLE默认选择每次广播在37,38,39三个信道上遍历发送广播数据。

    能量消耗:

    低功耗是BLE的一大亮点。仅使用纽扣电池,BLE设备即可运行数月甚至数年。蓝牙智能的灵活配置还可以使应用程序更好地管理连接间隔(连接间隔),从而优化接收器的占空比。对于蓝牙BR / EDR,由于其较高的数据吞吐量,因此功耗会相应增加。

    拓扑结构:

    BR / EDR支持星形拓扑的Piconet,也支持Scatternet的Piconet。在Scatternet中,每个微微网都有一个主设备,而从属设备可以基于时分复用参与不同的微微网。​

    BLE 4.1版本支持“双模式”,该模式允许BLE设备同时扮演“中央”和“外围设备”两个角色。支持中心角色的设备可以启动与外围设备的连接,而支持中心角色的设备也可以用作外围设备以连接到其他中心设备。将来,它还将支持BluetoothSmart Mesh(5.2已经支持)

    开发方式:

    BLE开发非常灵活,开发人员可以借助蓝牙技术联盟使用的配置文件更灵活地自定义应用程序。无论开发人员想要构建哪种应用程序场景,灵活的配置文件定义都可以满足技术要求。

    BR / EDR技术相对成熟,并且其开发是模块化的,因此通常只需要将模块集成到产品中即可。例如,在开发Beacon应用程序时应选择BLE,因为BR / EDR不支持Beacon应用程序

    配对:

    配对对于蓝牙BR / EDR是必需的,但对于BLE能则是选择性的。

    简单的BLE应用程序可能不需要配对。例如 ibeacon 等应用

    数据吞吐量:

    BLE吞吐量约为1 Mbps(如规格中所述),但还取决于应用场景。

    蓝牙BR / EDR吞吐量超过2Mbps,适用于高质量音频比特流或其他需要维持更高带宽连接的应用。

    Profile:

    通用属性配置文件(GATT)可以由应用程序或其他配置文件调用,以允许客户端与服务器进行交互。当前,有许多使用GATT构建的配置文件。

    联网能力:

    蓝牙技术联盟提供了三种基于BLE 的联网能力,RESTFul API,HTTP代理服务(HPS)和互联网协议支持配置文件(IPSP)的Internet访问方式。他们都需要网关设备进行连接。网关设备可以是任何可以访问Internet的设备,例如路由器,机顶盒,甚至是家里闲置的智能手机。 BLE的Internet功能使物联网更加可靠且易于实现。

    展开全文
  • https://download.csdn.net/download/wuhuacai/10157233 https://blog.csdn.net/zxorange321/article/details/75676063 ...LINUX内核协议栈分析 目 录 1说明...4 2TCP协议...4 2.1分层...

    https://download.csdn.net/download/wuhuacai/10157233

    https://blog.csdn.net/zxorange321/article/details/75676063 

    LINUX内核协议栈分析 

    目  录

    1      说明...4

    2      TCP协议...4

    2.1       分层...4

    2.2       TCP/IP的分层...5

    2.3       互联网的地址...6

    2.4       封装...7

    2.5       分用...8

    3      数据包格式...8

    3.1       ethhdr.8

    3.2       iphdr.10

    3.3       udphdr.11

    4      数据结构...12

    4.1       内核协议栈分层结构...13

    4.2       msghdr.14

    4.3       iovec.14

    4.4       file.15

    4.5       file_operations.16

    4.6       socket.17

    4.7       sock.18

    4.8       sock_common.22

    4.9       inet_sock.23

    4.10     udp_sock.25

    4.11     proto_ops.25

    4.12     proto.27

    4.13     net_proto_family.29

    4.14     softnet_data.31

    4.15     sk_buff31

    4.16     sk_buff_head.35

    4.17     net_device.35

    4.18     inet_protosw..42

    4.19     inetsw_array.43

    4.20     sock_type.44

    4.21     IPPROTO..45

    4.22     net_protocol46

    4.23     packet_type.46

    4.24     rtable.49

    4.25     dst_entry.50

    4.26     napi_struct.52

    5      数据结构类图...53

    6      协议栈注册流程...53

    6.1       内核启动流程...53

    6.2       协议栈初始化流程...55

    7      协议栈收包流程...56

    7.1       驱动收包流程...57

    7.2       应用层收包流程...57

    8      协议栈发包流程...57

    9      总结...57

    10        参考文献...57

     


     

    1      说明

    本文档制作基于版本  linux-2.6.32,本文档的目的是让有一定的网络协议基础的人了解到网络数据包在协议栈中的传输流程,大致理解到从网卡收到数据包传输到应用层所经历的步骤,以及每个步骤所做的事情。 图片贴到最后。

    本文档阅读基础:C语言基础,C语言回调函数,UML建模基础,C++面向对象封装思想,TCP/IP协议或网络基础。

    2      TCP协议

    本章摘自[TCP-IP详解卷一] 第一章。

    2.1分层

    网络协议通常分不同层次进行开发,每一层分别负责不同的通信功能。一个协议族,比如T C P / I P,是一组不同层次上的多个协议的组合。T C P / I P通常被认为是一个四层协议系统,如图1 - 1所示。每一层负责不同的功能:

    1)链路层,有时也称作数据链路层或网络接口层,通常包括操作系统中的设备驱动程序和计算机中对应的网络接口卡。它们一起处理与电缆(或其他任何传输媒介)的物理接口细节。

    2)网络层,有时也称作互联网层,处理分组在网络中的活动,例如分组的选路。在

    TC P / I P协议族中,网络层协议包括I P协议(网际协议),I C M P协议(I n t e r n e t互联网控制报文协议),以及I G M P协议(I n t e r n e t组管理协议)。

    3) 运输层主要为两台主机上的应用程序提供端到端的通信。在T C P / I P协议族中,有两个互不相同的传输协议:T C P(传输控制协议)和U D P(用户数据报协议)。T C P为两台主机提供高可靠性的数据通信。它所做的工作包括把应用程序交给它的数据分成合适的小块交给下面的网络层,确认接收到的分组,设置发送最后确认分组的超时时钟等。由于运输层提供了高可靠性的端到端的通信,因此应用层可以忽略所有这些细节。而另一方面,U D P则为应用层提供一种非常简单的服务。它只是把称作数据报的分组从一台主机发送到另一台主机,但并不保证该数据报能到达另一端。任何必需的可靠性必须由应用层来提供。

    这两种运输层协议分别在不同的应用程序中有不同的用途,这一点将在后面看到。

    4 ) 应用层负责处理特定的应用程序细节。几乎各种不同的T C P / I P实现都会提供下面这些通用的应用程序:

    • Telnet 远程登录。

    • FTP 文件传输协议。

    • SMTP 简单邮件传送协议。

    • SNMP 简单网络管理协议。

    2.2TCP/IP的分层

    在TC P / I P协议族中,有很多种协议。图1 - 4给出了本书将要讨论的其他协议。

     

    T C P和U D P是两种最为著名的运输层协议,二者都使用I P作为网络层协议。

    虽然T C P使用不可靠的I P服务,但它却提供一种可靠的运输层服务。本书第1 7~2 2章将详细讨论T C P的内部操作细节。然后,我们将介绍一些T C P的应用,如第2 6章中的Te l n e t和R l o g i n、第2 7章中的F T P以及第2 8章中的S M T P等。这些应用通常都是用户进程。

    U D P为应用程序发送和接收数据报。一个数据报是指从发送方传输到接收方的一个信息单元(例如,发送方指定的一定字节数的信息)。但是与T C P不同的是,U D P是不可靠的,它不能保证数据报能安全无误地到达最终目的。本书第11章将讨论U D P,然后在第1 4章(D N S :域名系统),第1 5章(T F T P:简单文件传送协议),以及第1 6章(BO OT P:引导程序协议)介绍使用U D P的应用程序。S N M P也使用了U D P协议,但是由于它还要处理许多其他的协议,因此本书把它留到第2 5章再进行讨论。

    I P是网络层上的主要协议,同时被T C P和U D P使用。T C P和U D P的每组数据都通过端系统和每个中间路由器中的I P层在互联网中进行传输。在图1 - 4中,我们给出了一个直接访问I P的应用程序。这是很少见的,但也是可能的(一些较老的选路协议就是以这种方式来实现的。当然新的运输层协议也有可能使用这种方式)。第3章主要讨论I P协议,但是为了使内容更加有针对性,一些细节将留在后面的章节中进行讨论。第9章和第1 0章讨论I P如何进行选路。

    I C M P是I P协议的附属协议。I P层用它来与其他主机或路由器交换错误报文和其他重要信息。

    第6章对I C M P的有关细节进行讨论。尽管I C M P主要被I P使用,但应用程序也有可能访问它。我们将分析两个流行的诊断工具,P i n g和Tr a c e r o u t e(第7章和第8章),它们都使用了I C M P。

    I G M P是I n t e r n e t组管理协议。它用来把一个U D P数据报多播到多个主机。我们在第1 2章中描述广播(把一个U D P数据报发送到某个指定网络上的所有主机)和多播的一般特性,然后在第1 3章中对I G M P协议本身进行描述。

    A R P(地址解析协议)和R A R P(逆地址解析协议)是某些网络接口(如以太网和令牌环网)使用的特殊协议,用来转换I P层和网络接口层使用的地址。我们分别在第4章和第5章对这两种协议进行分析和介绍。

    2.3互联网的地址

    互联网上的每个接口必须有一个唯一的I n t er n e t地址(也称作I P地址)。I P地址长32 bit。I n t e r n e t地址并不采用平面形式的地址空间,如1、2、3等。I P地址具有一定的结构,五类不同 的互联网地址格式如图1 - 5所示。

    这些3 2位的地址通常写成四个十进制的数,其中每个整数对应一个字节。这种表示方法称作“点分十进制表示法(Dotted decimal notation)”。例如,作者的系统就是一个B类地址,它表示为:1 4 0 . 2 5 2 .1 3 . 3 3。

    区分各类地址的最简单方法是看它的第一个十进制整数。图1 - 6列出了各类地址的起止范围,其中第一个十进制整数用加黑字体表示。

    需要再次指出的是,多接口主机具有多个I P地址,其中每个接口都对应一个I P地址。

    由于互联网上的每个接口必须有一个唯一的I P地址,因此必须要有一个管理机构为接入互联网的网络分配I P地址。这个管理机构就是互联网络信息中心(Internet Network InformationC e n t r e),称作I n t e r N I C。I n t e r N I C只分配网络号。主机号的分配由系统管理员来负责。

    I n t e r n e t注册服务( I P地址和D N S域名)过去由N I C来负责,其网络地址是n i c . d d n . m i l。1 9 9 3年4月1日,I n t e r N I C成立。现在,N I C只负责处理国防数据网的注册请求,所有其他的I n t e r n e t用户注册请求均由I n t e rN I C负责处理,其网址是:r s . i n t er n i c . n e t。

    事实上I n t e r N I C由三部分组成:注册服务(r s. i n t e r n i c . n e t),目录和数据库服

    务(d s . i n t e r n i c. n e t),以及信息服务(i s . i n t e rn i c . n e t)。有关I n t e r N I C的其他信息参见习题1 . 8。

    有三类I P地址:单播地址(目的为单个主机)、广播地址(目的端为给定网络上的所有主机)以及多播地址(目的端为同一组内的所有主机)。第1 2章和第1 3章将分别讨论广播和多播的更多细节。

    在3 . 4节中,我们在介绍I P选路以后将进一步介绍子网的概念。图3 - 9给出了几个特殊的I P地址:主机号和网络号为全0或全1。

    2.4封装

     

    当应用程序用T C P传送数据时,数据被送入协议栈中,然后逐个通过每一层直到被当作一串比特流送入网络。其中每一层对收到的数据都要增加一些首部信息(有时还要增加尾部信息),该过程如图1 - 7所示。T C P传给I P的数据单元称作T C P报文段或简称为T C P段(T C P s e g m e n t)。I P传给网络接口层的数据单元称作I P数据报(IP datagram)。通过以太网传输的比特流称作帧(Fr a m e )。1 - 7中帧头和帧尾下面所标注的数字是典型以太网帧首部的字节长度

     

     

     

    2.5分用

     

    当目的主机收到一个以太网数据帧时,数据就开始从协议栈中由底向上升,同时去掉各

    层协议加上的报文首部。每层协议盒都要去检查报文首部中的协议标识,以确定接收数据的

    上层协议。这个过程称作分用( D e m u lt i p l e x i n g),图1 - 8显示了该过程是如何发生的。[TCP-IP详解卷一]

    3      数据包格式

    1. 

    2. 

    3.1ethhdr

     

    描述以太网头部

    /*

     *  Thisis an Ethernet frame header.

     */

     

    struct ethhdr {

        unsigned char h_dest[ETH_ALEN];/* destination ethaddr  */

        unsigned char h_source[ETH_ALEN]; /* source ether addr */

        __be16     h_proto;     /* packet type ID field  */

    } __attribute__((packed));

     

     

     

    /*

     *  Theseare the defined Ethernet Protocol ID's.

     */

     

    #define ETH_P_LOOP   0x0060    /* Ethernet Loopback packet */

    #define ETH_P_PUP 0x0200     /* Xerox PUP packet      */

    #define ETH_P_PUPAT  0x0201    /* Xerox PUP Addr Trans packet  */

    #define ETH_P_IP  0x0800     /* Internet Protocol packet */

    #define ETH_P_X25 0x0805     /* CCITT X.25        */

    #define ETH_P_ARP 0x0806     /* Address Resolution packet    */

    #define    ETH_P_BPQ  0x08FF    /* G8BPQ AX.25Ethernet Packet  [ NOT AN OFFICIALLYREGISTERED ID ] */

    #define ETH_P_IEEEPUP    0x0a00    /* Xerox IEEE802.3 PUP packet */

    #define ETH_P_IEEEPUPAT  0x0a01    /* Xerox IEEE802.3 PUP Addr Trans packet */

    #define ETH_P_DEC       0x6000         /* DEC Assigned proto           */

    #define ETH_P_DNA_DL    0x6001         /* DEC DNA Dump/Load            */

    #define ETH_P_DNA_RC    0x6002         /* DEC DNA Remote Console       */

    #define ETH_P_DNA_RT    0x6003         /* DEC DNA Routing              */

    #define ETH_P_LAT       0x6004         /* DEC LAT                      */

    #define ETH_P_DIAG      0x6005         /* DEC Diagnostics              */

    #define ETH_P_CUST      0x6006         /* DEC Customer use             */

    #define ETH_P_SCA       0x6007         /* DEC Systems Comms Arch       */

    #define ETH_P_TEB 0x6558     /* Trans Ether Bridging     */

    #define ETH_P_RARP      0x8035      /* Reverse Addr Res packet  */

    #define ETH_P_ATALK  0x809B    /* Appletalk DDP     */

    #define ETH_P_AARP   0x80F3    /* Appletalk AARP    */

    #define ETH_P_8021Q  0x8100         /* 802.1Q VLAN Extended Header  */

    #define ETH_P_IPX 0x8137     /* IPX over DIX          */

    #define ETH_P_IPV6   0x86DD    /* IPv6 over bluebook       */

    #define ETH_P_PAUSE  0x8808    /* IEEE Pause frames. See 802.3 31B */

    #define ETH_P_SLOW   0x8809    /* Slow Protocol. See 802.3ad 43B */

    #define ETH_P_WCCP   0x883E    /* Web-cache coordination protocol

                       * defined in draft-wilson-wrec-wccp-v2-00.txt*/

    #define ETH_P_PPP_DISC   0x8863    /* PPPoE discovery messages     */

    #define ETH_P_PPP_SES    0x8864    /* PPPoE session messages   */

    #define ETH_P_MPLS_UC    0x8847    /* MPLS Unicast traffic     */

    #define ETH_P_MPLS_MC    0x8848    /* MPLS Multicast traffic   */

    #define ETH_P_ATMMPOA    0x884c    /* MultiProtocol Over ATM   */

    #define ETH_P_ATMFATE    0x8884    /* Frame-based ATM Transport

                       * over Ethernet

                       */

    #define ETH_P_PAE 0x888E     /* Port Access Entity (IEEE 802.1X) */

    #define ETH_P_AOE 0x88A2     /* ATA over Ethernet     */

    #define ETH_P_TIPC   0x88CA    /* TIPC           */

    #define ETH_P_1588   0x88F7    /* IEEE 1588 Timesync */

    #define ETH_P_FCOE   0x8906    /* Fibre Channel over Ethernet  */

    #define ETH_P_TDLS   0x890D    /* TDLS */

    #define ETH_P_FIP 0x8914     /* FCoE Initialization Protocol */

    #define ETH_P_EDSA   0xDADA    /* Ethertype DSA [ NOT AN OFFICIALLY REGISTERED ID] */

    #define ETH_P_AF_IUCV   0xFBFB     /* IBM af_iucv [ NOT AN OFFICIALLY REGISTERED ID ]*/

     

     

    3.2iphdr

    描述ip头部

    struct iphdr {

    #if defined(__LITTLE_ENDIAN_BITFIELD)

        __u8   ihl:4,

           version:4;

    #elif defined (__BIG_ENDIAN_BITFIELD)

        __u8   version:4,

            ihl:4;

    #else

    #error "Please fix<asm/byteorder.h>"

    #endif

        __u8   tos;

        __be16 tot_len;

        __be16 id;

        __be16 frag_off;

        __u8   ttl;

        __u8   protocol;

        __sum16    check;

        __be32 saddr;

        __be32 daddr;

        /*The options start here. */

    };

     

     

    3.3udphdr

    描述udp头部

    struct udphdr {

        __be16 source;

        __be16 dest;

        __be16 len;

        __sum16    check;

    };

     

     

    4      数据结构

    内核协议栈涉及的数据结较多,错综复杂,这里只是粘贴了设计到的数据结构的源码。源码和注释用10字体,高亮显示;重要的成员和方法用加粗11号字体标出。例如

     

    4.1内核协议栈分层结构

     

    图4-1 内核协议栈分层结构

     

    Physical device hardware : 指的实实在在的物理设备。    对应physical layer

    Device agnostic interface : 设备无关层。                                对应Link layer

    Network protocols            :  网络层。                                        对应Ip layer 和 transportlayer

    Protocol agnostic interface: 协议无关层                                  适配系统调用层,屏蔽了协议的细节

    System callinterface:系统调用层     提供给应用层的系统调用,屏蔽了socket操作的细节

    BSD socket:  BSD Socket层           提供统一socket操作的接口, socket结构关系紧密

    Inet socket:      inet socket 层          调用ip层协议的统一接口,sock结构关系紧密

    4.2msghdr

    描述了从应用层传递下来的消息格式,包含有用户空间地址,消息标记等重要信息。

    /*

     *  Aswe do 4.4BSD message passing we use a 4.4BSD message passing

     *  system,not 4.3. Thus msg_accrights(len) are now missing. They

     *  belongin an obscure libc emulation or the bin.

     */

     

    struct msghdr {

        void   *   msg_name; /* Socket name           */

        int    msg_namelen; /* Length of name    */

        struct iovec*    msg_iov;  /* Data blocks           */

        __kernel_size_t   msg_iovlen;  /* Number of blocks      */

        void   *   msg_control; /* Per protocolmagic (eg BSD file descriptor passing) */

        __kernel_size_t   msg_controllen;  /* Length of cmsglist */

        unsigned   msg_flags;

    };

    4.3iovec

    描述了用户空间地址的起始位置。

    /*

     *  Berkeleystyle UIO structures   -   Alan Cox 1994.

     *

     *     Thisprogram is free software; you can redistribute it and/or

     *     modifyit under the terms of the GNU General Public License

     *     aspublished by the Free Software Foundation; either version

     *     2of the License, or (at your option) any later version.

     */

     

    struct iovec {

        void __user*iov_base;  /* BSD uses caddr_t(1003.1g requires void *) */

        __kernel_size_t iov_len;/* Must be size_t(1003.1g) */

    };

     

    4.4file

    描述文件属性的结构体,与文件描述符一一对应。

     

    struct file {

        /*

         * fu_list becomes invalid after file_free iscalled and queued via

         * fu_rcuhead for RCU freeing

         */

        union {

           struct list_head  fu_list;

           struct rcu_head   fu_rcuhead;

        } f_u;

        struct path       f_path;

    #define f_dentry  f_path.dentry

    #define f_vfsmnt  f_path.mnt

        const struct file_operations   *f_op;

        spinlock_t    f_lock; /* f_ep_links,f_flags, no IRQ */

        atomic_long_t     f_count;

        unsigned int      f_flags;

        fmode_t           f_mode;

        loff_t        f_pos;

        struct fown_struct   f_owner;

        const struct cred *f_cred;

        struct file_ra_state f_ra;

     

        u64        f_version;

    #ifdef CONFIG_SECURITY

        void          *f_security;

    #endif

        /* needed for tty driver, and maybeothers */

       void        *private_data;

     

    #ifdef CONFIG_EPOLL

        /* Used by fs/eventpoll.c to link allthe hooks to this file */

        struct list_head  f_ep_links;

    #endif /*#ifdef CONFIG_EPOLL */

        struct address_space*f_mapping;

    #ifdef CONFIG_DEBUG_WRITECOUNT

        unsigned long f_mnt_write_state;

    #endif

    };

    4.5file_operations

    文件操作相关结构体,包括read(), write(), open(),ioctl()等。

     

    /*

     * NOTE:

     * read, write, poll, fsync, readv,writev, unlocked_ioctl and compat_ioctl

     * can be called without the bigkernel lock held in all filesystems.

     */

    structfile_operations {

        struct module *owner;

        loff_t (*llseek)(struct file*, loff_t,int);

        ssize_t (*read) (struct file*,char __user*,size_t, loff_t*);

        ssize_t (*write) (struct file*,constchar __user*,size_t, loff_t*);

        ssize_t (*aio_read)(struct kiocb*, const struct iovec *,unsignedlong, loff_t);

        ssize_t (*aio_write)(struct kiocb*, const struct iovec *,unsignedlong, loff_t);

        int (*readdir)(struct file*,void*, filldir_t);

        unsigned int (*poll)(struct file*,struct poll_table_struct *);

        int (*ioctl) (struct inode*,struct file*,unsignedint,unsignedlong);

        long (*unlocked_ioctl)(struct file*, unsigned int,unsignedlong);

        long (*compat_ioctl)(struct file*, unsigned int,unsignedlong);

        int (*mmap)(struct file*,struct vm_area_struct *);

        int (*open) (struct inode*,struct file*);

        int (*flush)(struct file*, fl_owner_t id);

        int (*release)(struct inode*,struct file *);

        int (*fsync)(struct file*,struct dentry *,int datasync);

        int (*aio_fsync)(struct kiocb*, int datasync);

        int (*fasync)(int,struct file *,int);

        int (*lock)(struct file*,int,struct file_lock *);

        ssize_t (*sendpage)(struct file*, struct page *, int, size_t, loff_t *,int);

        unsigned long (*get_unmapped_area)(struct file*,unsignedlong,unsignedlong,unsignedlong,unsignedlong);

        int (*check_flags)(int);

        int (*flock)(struct file*,int,struct file_lock *);

        ssize_t (*splice_write)(struct pipe_inode_info*,struct file *, loff_t*,size_t,unsignedint);

        ssize_t (*splice_read)(struct file*, loff_t *,struct pipe_inode_info*,size_t,unsignedint);

        int (*setlease)(struct file*,long,struct file_lock **);

    };

     

    4.6socket

    向应用层提供的BSD socket操作结构体,协议无关,主要作用为应用层提供统一的socket操作。BSD: BerkeleySoftwareDistribution)

     

    /**

     * struct socket - general BSD socket

     * @state: socket state (%SS_CONNECTED, etc)

     * @type: socket type (%SOCK_STREAM, etc)

     * @flags: socket flags (%SOCK_ASYNC_NOSPACE, etc)

     *  @ops:protocol specific socket operations

     * @fasync_list: Asynchronous wake up list

     * @file: File back pointer for gc

     *  @sk:internal networking protocol agnostic socket representation

     * @wait: wait queue for several uses

     */

    struct socket {

       socket_state    state;

     

        kmemcheck_bitfield_begin(type);

        short         type;

        kmemcheck_bitfield_end(type);

     

        unsigned long     flags;

        /*

         * Please keep fasync_list & wait fields inthe same cache line

         */

        struct fasync_struct*fasync_list;

        wait_queue_head_t wait;

     

        struct file    *file;

       struct sock    *sk;

       const struct proto_ops   *ops;

    };

     

    typedef enum {

        SS_FREE = 0,         /* not allocated     */

        SS_UNCONNECTED,         /* unconnected to any socket    */

        SS_CONNECTING,          /* in process of connecting */

        SS_CONNECTED,       /* connected to socket      */

        SS_DISCONNECTING     /* in process of disconnecting  */

    } socket_state;

    4.7sock

    网络层sock(可理解为C++基类),定义与协议无关操作,是网络层的统一的结构,传输层在此基础上实现了inet_sock(可理解为C++派生类)。

    /**

      * structsock - network layer representation of sockets

      * @__sk_common:shared layout with inet_timewait_sock

      * @sk_shutdown:mask of %SEND_SHUTDOWN and/or %RCV_SHUTDOWN

      * @sk_userlocks:%SO_SNDBUF and %SO_RCVBUF settings

      * @sk_lock:  synchronizer

      * @sk_rcvbuf:size of receive buffer in bytes

      * @sk_sleep:sock wait queue

      * @sk_dst_cache:destination cache

      * @sk_dst_lock:destination cache lock

      * @sk_policy:flow policy

      * @sk_rmem_alloc:receive queue bytes committed

      * @sk_receive_queue:incoming packets

      * @sk_wmem_alloc:transmit queue bytes committed

      * @sk_write_queue:Packet sending queue

      * @sk_async_wait_queue:DMA copied packets

      * @sk_omem_alloc:"o" is "option" or "other"

      * @sk_wmem_queued:persistent queue size

      * @sk_forward_alloc:space allocated forward

      * @sk_allocation:allocation mode

      * @sk_sndbuf:size of send buffer in bytes

      * @sk_flags:%SO_LINGER (l_onoff), %SO_BROADCAST, %SO_KEEPALIVE,

      *        %SO_OOBINLINE settings, %SO_TIMESTAMPINGsettings

      * @sk_no_check:%SO_NO_CHECK setting, wether or not checkup packets

      * @sk_route_caps:route capabilities (e.g. %NETIF_F_TSO)

      * @sk_gso_type:GSO type (e.g. %SKB_GSO_TCPV4)

      * @sk_gso_max_size:Maximum GSO segment size to build

      * @sk_lingertime:%SO_LINGER l_linger setting

      * @sk_backlog:always used with the per-socket spinlock held

      * @sk_callback_lock:used with the callbacks in the end of this struct

      * @sk_error_queue:rarely used

      * @sk_prot_creator:sk_prot of original sock creator (see ipv6_setsockopt,

      *          IPV6_ADDRFORM for instance)

      * @sk_err:last error

      * @sk_err_soft:errors that don't cause failure but are the cause of a

      *           persistent failure not just 'timed out'

      * @sk_drops:raw/udp drops counter

      * @sk_ack_backlog:current listen backlog

      * @sk_max_ack_backlog:listen backlog set in listen()

      * @sk_priority:%SO_PRIORITY setting

      * @sk_type:socket type (%SOCK_STREAM, etc)

      * @sk_protocol:which protocol this socket belongs in this network family

      * @sk_peercred:%SO_PEERCRED setting

      * @sk_rcvlowat:%SO_RCVLOWAT setting

      * @sk_rcvtimeo:%SO_RCVTIMEO setting

      * @sk_sndtimeo:%SO_SNDTIMEO setting

      * @sk_filter:socket filtering instructions

      * @sk_protinfo:private area, net family specific, when not using slab

      * @sk_timer:sock cleanup timer

      * @sk_stamp:time stamp of last packet received

      * @sk_socket:Identd and reporting IO signals

      * @sk_user_data:RPC layer private data

      * @sk_sndmsg_page:cached page for sendmsg

      * @sk_sndmsg_off:cached offset for sendmsg

      * @sk_send_head:front of stuff to transmit

      * @sk_security:used by security modules

      * @sk_mark:generic packet mark

      * @sk_write_pending:a write to stream socket waits to start

      * @sk_state_change:callback to indicate change in the state of the sock

      * @sk_data_ready:callback to indicate there is data to be processed

      * @sk_write_space:callback to indicate there is bf sending space available

      * @sk_error_report:callback to indicate errors (e.g. %MSG_ERRQUEUE)

      * @sk_backlog_rcv:callback to process the backlog

      * @sk_destruct:called at sock freeing time, i.e. when all refcnt == 0

     */

    struct sock {

        /*

         * Now struct inet_timewait_sock also usessock_common, so please just

         * don't add nothing before this first member(__sk_common) --acme

         */

        struct sock_common   __sk_common;

    #define sk_node          __sk_common.skc_node

    #define sk_nulls_node       __sk_common.skc_nulls_node

    #define sk_refcnt    __sk_common.skc_refcnt

     

    #define sk_copy_start       __sk_common.skc_hash

    #define sk_hash          __sk_common.skc_hash

    #define sk_family    __sk_common.skc_family

    #define sk_state     __sk_common.skc_state

    #define sk_reuse     __sk_common.skc_reuse

    #define sk_bound_dev_if     __sk_common.skc_bound_dev_if

    #define sk_bind_node     __sk_common.skc_bind_node

    #definesk_prot          __sk_common.skc_prot

    #define sk_net           __sk_common.skc_net

        kmemcheck_bitfield_begin(flags);

        unsigned int      sk_shutdown  : 2,

                  sk_no_check  :2,

                  sk_userlocks :4,

                  sk_protocol  :8,

                  sk_type      :16;

        kmemcheck_bitfield_end(flags);

        int        sk_rcvbuf;

        socket_lock_t     sk_lock;

        /*

         * The backlog queue is special, it is alwaysused with

         * the per-socket spinlock held and requireslow latency

         * access. Therefore we special case it'simplementation.

         */

        struct {

           struct sk_buff *head;

           struct sk_buff *tail;

        } sk_backlog;

        wait_queue_head_t *sk_sleep;

        struct dst_entry  *sk_dst_cache;

    #ifdef CONFIG_XFRM

        struct xfrm_policy  *sk_policy[2];

    #endif

        rwlock_t      sk_dst_lock;

        atomic_t       sk_rmem_alloc;

        atomic_t      sk_wmem_alloc;

        atomic_t      sk_omem_alloc;

        int        sk_sndbuf;

        struct sk_buff_head  sk_receive_queue;

        struct sk_buff_head  sk_write_queue;

    #ifdef CONFIG_NET_DMA

        struct sk_buff_head  sk_async_wait_queue;

    #endif

        int        sk_wmem_queued;

        int        sk_forward_alloc;

        gfp_t         sk_allocation;

        int        sk_route_caps;

        int        sk_gso_type;

        unsigned int      sk_gso_max_size;

        int        sk_rcvlowat;

        unsigned long     sk_flags;

        unsigned long        sk_lingertime;

        struct sk_buff_head  sk_error_queue;

        struct proto      *sk_prot_creator;

        rwlock_t      sk_callback_lock;

        int        sk_err,

                  sk_err_soft;

        atomic_t      sk_drops;

        unsigned short       sk_ack_backlog;

        unsigned short       sk_max_ack_backlog;

        __u32         sk_priority;

        struct ucred      sk_peercred;

        long          sk_rcvtimeo;

        long          sk_sndtimeo;

        struct sk_filter     *sk_filter;

        void          *sk_protinfo;

        struct timer_list sk_timer;

        ktime_t           sk_stamp;

        struct socket     *sk_socket;

        void          *sk_user_data;

        struct page       *sk_sndmsg_page;

        struct sk_buff      *sk_send_head;

        __u32         sk_sndmsg_off;

        int        sk_write_pending;

    #ifdef CONFIG_SECURITY

        void          *sk_security;

    #endif

        __u32         sk_mark;

        u32        sk_classid;

        void          (*sk_state_change)(struct sock*sk);

        void          (*sk_data_ready)(struct sock*sk,int bytes);

        void          (*sk_write_space)(struct sock*sk);

        void          (*sk_error_report)(struct sock*sk);

        int        (*sk_backlog_rcv)(struct sock*sk,

                           struct sk_buff*skb); 

        void                   (*sk_destruct)(struct sock*sk);

    };

     

    4.8sock_common

    最小网络层表示结构体

     

    /**

     *  structsock_common - minimal network layer representation of sockets

     *  @skc_node:main hash linkage for various protocol lookup tables

     *  @skc_nulls_node:main hash linkage for UDP/UDP-Lite protocol

     *  @skc_refcnt:reference count

     *  @skc_hash:hash value used with various protocol lookup tables

     *  @skc_family:network address family

     *  @skc_state:Connection state

     *  @skc_reuse:%SO_REUSEADDR setting

     *  @skc_bound_dev_if:bound device index if != 0

     *  @skc_bind_node:bind hash linkage for various protocol lookup tables

     *  @skc_prot:protocol handlers inside a network family

     *  @skc_net:reference to the network namespace of this socket

     *

     *  Thisis the minimal network layer representation of sockets, the header

     *  forstruct sock and struct inet_timewait_sock.

     */

    struct sock_common {

        /*

         * first fields are not copied in sock_copy()

         */

        union {

           struct hlist_node skc_node;

           struct hlist_nulls_node skc_nulls_node;

        };

        atomic_t      skc_refcnt;

     

        unsigned int      skc_hash;

        unsigned short       skc_family;

        volatile unsigned char   skc_state;

        unsigned char     skc_reuse;

        int        skc_bound_dev_if;

        struct hlist_node skc_bind_node;

        struct proto     *skc_prot;

    #ifdef CONFIG_NET_NS

        struct net    *skc_net;

    #endif

    };

     

     

    4.9inet_sock

    Inet_sock表示层结构体,在sock上做的扩展,用于在网络层之上表示inet协议族的的传输层公共结构体。

    /** struct inet_sock - representation of INET sockets

     *

     * @sk - ancestor class

     * @pinet6 - pointer to IPv6 controlblock

     * @daddr - Foreign IPv4 addr

     * @rcv_saddr - Bound local IPv4addr

     * @dport - Destination port

     * @num - Local port

     * @saddr - Sending source

     * @uc_ttl - Unicast TTL

     * @sport - Source port

     * @id - ID counter for DF pkts

     * @tos - TOS

     * @mc_ttl - Multicasting TTL

     * @is_icsk - is this aninet_connection_sock?

     * @mc_index - Multicast deviceindex

     * @mc_list - Group array

     * @cork - info to build ip hdr oneach ip frag while socket is corked

     */

    structinet_sock {

        /* sk and pinet6 has to be the firsttwo members of inet_sock */

        struct sock       sk;

    #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)

        struct ipv6_pinfo *pinet6;

    #endif

        /* Socket demultiplex comparisons onincoming packets. */

        __be32        daddr;

        __be32        rcv_saddr;

        __be16        dport;

        __u16         num;

        __be32        saddr;

        __s16         uc_ttl;

        __u16         cmsg_flags;

        struct ip_options *opt;

        __be16        sport;

        __u16         id;

        __u8          tos;

        __u8          mc_ttl;

        __u8          pmtudisc;

        __u8          recverr:1,

                  is_icsk:1,

                  freebind:1,

                  hdrincl:1,

                  mc_loop:1,

                  transparent:1,

                  mc_all:1;

        int        mc_index;

        __be32        mc_addr;

        struct ip_mc_socklist   *mc_list;

        struct {

           unsigned int      flags;

           unsigned int      fragsize;

           struct ip_options*opt;

           struct dst_entry *dst;

           int        length;/* Total length ofall frames */

           __be32        addr;

           struct flowi      fl;

        } cork;

    };

     

     

    4.10  udp_sock

    传输层UDP协议专用sock结构,在传输层inet_sock上扩展

    structudp_sock {

        /* inet_sock has to be the firstmember */

        struct inet_sock inet;

        int    pending; /* Any pending frames ? */

        unsigned int  corkflag; /* Cork is required*/

        __u16      encap_type; /* Is this anEncapsulation socket? */

        /*

         * Following member retains the information tocreate a UDP header

         * when the socket is uncorked.

         */

        __u16      len;     /* total length ofpending frames */

        /*

         * Fields specific to UDP-Lite.

         */

        __u16      pcslen;

        __u16      pcrlen;

    /* indicator bits used by pcflag: */

    #define UDPLITE_BIT      0x1        /* set by udpliteproto init function */

    #define UDPLITE_SEND_CC  0x2       /* set via udplitesetsockopt         */

    #define UDPLITE_RECV_CC  0x4   /* set via udplite setsocktopt        */

        __u8       pcflag;       /* marks socket asUDP-Lite if > 0    */

        __u8       unused[3];

        /*

         * For encapsulation sockets.

         */

        int (*encap_rcv)(struct sock*sk,struct sk_buff *skb);

    };

     

    4.11  proto_ops

    BSD socket层到inet_sock层接口,主要用于操作socket结构

    structproto_ops {

     

        int    family;

        struct module *owner;

        int    (*release)  (struct socket*sock);

        int    (*bind)        (struct socket*sock,

                        struct sockaddr*myaddr,

                        int sockaddr_len);

        int    (*connect)  (struct socket*sock,

                        struct sockaddr*vaddr,

                         int sockaddr_len,int flags);

        int    (*socketpair)(struct socket*sock1,

                        struct socket*sock2);

        int    (*accept)   (struct socket*sock,

                        struct socket*newsock,int flags);

        int    (*getname)  (struct socket*sock,

                        struct sockaddr*addr,

                        int*sockaddr_len,int peer);

        unsigned int  (*poll)        (struct file*file,struct socket *sock,

                        struct poll_table_struct*wait);

        int    (*ioctl)    (struct socket*sock,unsignedint cmd,

                        unsignedlong arg);

        int    (*compat_ioctl)(struct socket*sock,unsignedint cmd,

                        unsignedlong arg);

        int    (*listen)   (struct socket*sock,int len);

        int    (*shutdown) (struct socket*sock,int flags);

        int    (*setsockopt)(struct socket*sock,int level,

                        int optname,char __user*optval,unsignedint optlen);

        int    (*getsockopt)(struct socket*sock,int level,

                        int optname,char __user*optval,int __user*optlen);

        int    (*compat_setsockopt)(struct socket*sock,int level,

                        int optname,char __user*optval,unsignedint optlen);

        int    (*compat_getsockopt)(struct socket*sock,int level,

                        int optname,char __user*optval,int __user*optlen);

        int    (*sendmsg)  (struct kiocb*iocb,struct socket*sock,

                        struct msghdr*m, size_t total_len);

        int    (*recvmsg)  (struct kiocb*iocb,struct socket*sock,

                        struct msghdr*m, size_t total_len,

                        int flags);

        int    (*mmap)        (struct file*file,struct socket*sock,

                        struct vm_area_struct* vma);

        ssize_t       (*sendpage) (struct socket*sock,struct page *page,

                        int offset, size_t size,int flags);

        ssize_t    (*splice_read)(struct socket*sock,  loff_t*ppos,

                         struct pipe_inode_info*pipe, size_t len,unsignedint flags);

    };

    4.12  proto

    inet_sock 层到传输层 操作的统一接口,主要用于操作sock结构

    /* Networking protocol blocks we attach to sockets.

     * socket layer -> transportlayer interface

     * transport -> network interfaceis defined by struct inet_proto

     */

    struct proto {

        void          (*close)(struct sock*sk,

                      long timeout);

        int        (*connect)(struct sock*sk,

                          struct sockaddr*uaddr,

                      int addr_len);

        int        (*disconnect)(struct sock*sk,int flags);

     

        struct sock *     (*accept)(struct sock*sk,int flags,int*err);

     

        int        (*ioctl)(struct sock*sk,int cmd,

                       unsignedlong arg);

        int        (*init)(struct sock*sk);

        void          (*destroy)(struct sock*sk);

        void          (*shutdown)(struct sock*sk,int how);

        int        (*setsockopt)(struct sock*sk,int level,

                      int optname,char __user*optval,

                      unsignedint optlen);

        int        (*getsockopt)(struct sock*sk,int level,

                      int optname,char __user*optval,

                      int __user*option);      

    #ifdef CONFIG_COMPAT

        int        (*compat_setsockopt)(struct sock*sk,

                      int level,

                      int optname,char __user*optval,

                      unsignedint optlen);

        int        (*compat_getsockopt)(struct sock*sk,

                      int level,

                      int optname,char __user*optval,

                      int __user*option);

    #endif

        int        (*sendmsg)(struct kiocb*iocb,struct sock *sk,

                         struct msghdr*msg, size_t len);

        int        (*recvmsg)(struct kiocb*iocb,struct sock *sk,

                         struct msghdr*msg,

                      size_t len,int noblock,int flags,

                      int *addr_len);

        int        (*sendpage)(struct sock*sk,struct page *page,

                      int offset, size_t size,int flags);

        int        (*bind)(struct sock*sk,

                      struct sockaddr*uaddr,int addr_len);

     

        int        (*backlog_rcv)(struct sock*sk,

                         struct sk_buff*skb);

     

        /* Keeping track of sk's, lookingthem up, and port selection methods. */

        void          (*hash)(struct sock*sk);

        void          (*unhash)(struct sock*sk);

        int        (*get_port)(struct sock*sk,unsignedshort snum);

     

        /* Keeping track of sockets in use */

    #ifdef CONFIG_PROC_FS

        unsigned int      inuse_idx;

    #endif

     

        /* Memory pressure */

        void          (*enter_memory_pressure)(struct sock*sk);

        atomic_t      *memory_allocated;  /* Current allocated memory. */

        struct percpu_counter   *sockets_allocated; /* Current number ofsockets. */

        /*

         * Pressure flag: try to collapse.

         * Technical note: it is used by multiplecontexts non atomically.

         * All the __sk_mem_schedule() is of thisnature: accounting

         * is strict, actions are advisory and havesome latency.

         */

        int        *memory_pressure;

        int        *sysctl_mem;

        int        *sysctl_wmem;

        int        *sysctl_rmem;

        int        max_header;

     

        struct kmem_cache *slab;

        unsigned int      obj_size;

        int        slab_flags;

     

        struct percpu_counter   *orphan_count;

     

        struct request_sock_ops *rsk_prot;

        struct timewait_sock_ops*twsk_prot;

     

        union {

           struct inet_hashinfo*hashinfo;

           struct udp_table *udp_table;

           struct raw_hashinfo *raw_hash;

        } h;

     

        struct module     *owner;

     

        char          name[32];

     

        struct list_head  node;

    #ifdef SOCK_REFCNT_DEBUG

        atomic_t      socks;

    #endif

    };

     

     

    4.13  net_proto_family

    用于标识和注册协议族,常见的协议族有 ipv4, ipv6。

    协议族: 用于完成某些特定的功能的协议集合。

    structnet_proto_family {

        int    family;

        int    (*create)(struct net*net,struct socket *sock,

                    int protocol,int kern);

        struct module *owner;

    };

     

    内核中声明了大量的协议族,并不是所有的协议族都支持。

    /* Supported address families. */

    #define AF_UNSPEC 0

    #define AF_UNIX      1   /* Unix domain sockets      */

    #define AF_LOCAL  1   /* POSIX name for AF_UNIX   */

    #define AF_INET      2   /* Internet IP Protocol */

    #define AF_AX25      3   /* Amateur Radio AX.25      */

    #define AF_IPX       4   /* Novell IPX        */

    #define AF_APPLETALK 5   /* AppleTalk DDP     */

    #define AF_NETROM 6   /* Amateur Radio NET/ROM    */

    #define AF_BRIDGE 7   /* Multiprotocol bridge */

    #define AF_ATMPVC 8   /* ATM PVCs          */

    #define AF_X25       9   /* Reserved for X.25 project    */

    #define AF_INET6  10  /* IP version 6          */

    #define AF_ROSE      11  /* Amateur Radio X.25 PLP   */

    #define AF_DECnet 12  /* Reserved for DECnet project  */

    #define AF_NETBEUI   13  /* Reserved for 802.2LLC project*/

    #define AF_SECURITY  14  /* Security callback pseudo AF */

    #define AF_KEY       15      /* PF_KEY key management API */

    #define AF_NETLINK   16

    #define AF_ROUTE  AF_NETLINK /* Alias to emulate4.4BSD */

    #define AF_PACKET 17  /* Packet family     */

    #define AF_ASH       18  /* Ash            */

    #define AF_ECONET 19  /* Acorn Econet          */

    #define AF_ATMSVC 20  /* ATM SVCs          */

    #define AF_RDS       21  /* RDS sockets           */

    #define AF_SNA       22  /* Linux SNA Project (nutters!) */

    #define AF_IRDA      23  /* IRDA sockets          */

    #define AF_PPPOX  24  /* PPPoX sockets     */

    #define AF_WANPIPE   25  /* Wanpipe API Sockets */

    #define AF_LLC       26  /* Linux LLC         */

    #define AF_CAN       29  /* Controller Area Network      */

    #define AF_TIPC      30  /* TIPC sockets          */

    #define AF_BLUETOOTH 31  /* Bluetooth sockets     */

    #define AF_IUCV      32  /* IUCV sockets          */

    #define AF_RXRPC  33  /* RxRPC sockets     */

    #define AF_ISDN      34  /* mISDN sockets     */

    #define AF_PHONET 35  /* Phonet sockets    */

    #define AF_IEEE802154    36  /* IEEE802154 sockets       */

    #define AF_MAX       37  /* For now.. */

     

    static const struct net_proto_family *net_families[NPROTO];

     

    4.14  softnet_data

    内核为每个CPU都分配一个这样的softnet_data数据空间。

    每个CPU都有一个这样的队列,用于接收数据包。

    /*

     * Incoming packets are placed onper-cpu queues so that

     * no locking is needed.

     */

    structsoftnet_data {

        struct Qdisc      *output_queue;

        struct list_head  poll_list;

        struct sk_buff      *completion_queue;

     

        /* Elements below can be accessedbetween CPUs for RPS */

        struct call_single_data  csd ____cacheline_aligned_in_smp;

        unsigned int            input_queue_head;

        struct sk_buff_head  input_pkt_queue;

        struct napi_struct   backlog;

    };

     

     

    4.15  sk_buff

    描述一个帧结构的属性,持有socket,到达时间,到达设备,各层头部大小,下一站路由入口,帧长度,校验和,等等。

    /**

     *  structsk_buff - socket buffer

     *  @next:Next buffer in list

     *  @prev:Previous buffer in list

     *  @sk:Socket we are owned by

     *  @tstamp:Time we arrived

     *  @dev:Device we arrived on/are leaving by

     *  @transport_header:Transport layer header

     *  @network_header:Network layer header

     *  @mac_header:Link layer header

     *  @_skb_dst:destination entry

     *  @sp:the security path, used for xfrm

     *  @cb:Control buffer. Free for use by every layer. Put private vars here

     *  @len:Length of actual data

     *  @data_len:Data length

     *  @mac_len:Length of link layer header

     *  @hdr_len:writable header length of cloned skb

     *  @csum:Checksum (must include start/offset pair)

     *  @csum_start:Offset from skb->head where checksumming should start

     *  @csum_offset:Offset from csum_start where checksum should be stored

     *  @local_df:allow local fragmentation

     *  @cloned:Head may be cloned (check refcnt to be sure)

     *  @nohdr:Payload reference only, must not modify header

     *  @pkt_type:Packet class

     *  @fclone:skbuff clone status

     *  @ip_summed:Driver fed us an IP checksum

     *  @priority:Packet queueing priority

     *  @users:User count - see {datagram,tcp}.c

     *  @protocol:Packet protocol from driver

     *  @truesize:Buffer size

     *  @head:Head of buffer

     *  @data:Data head pointer

     *  @tail:Tail pointer

     *  @end:End pointer

     *  @destructor:Destruct function

     *  @mark:Generic packet mark

     *  @nfct:Associated connection, if any

     *  @ipvs_property:skbuff is owned by ipvs

     *  @peeked:this packet has been seen already, so stats have been

     *     donefor it, don't do them again

     *  @nf_trace:netfilter packet trace flag

     *  @nfctinfo:Relationship of this skb to the connection

     *  @nfct_reasm:netfilter conntrack re-assembly pointer

     *  @nf_bridge:Saved data about a bridged frame - see br_netfilter.c

     *  @iif:ifindex of device we arrived on

     *  @queue_mapping:Queue mapping for multiqueue devices

     *  @tc_index:Traffic control index

     *  @tc_verd:traffic control verdict

     *  @ndisc_nodetype:router type (from link layer)

     *  @dma_cookie:a cookie to one of several possible DMA operations

     *     doneby skb DMA functions

     *  @secmark:security marking

     *  @vlan_tci:vlan tag control information

     */

    struct sk_buff{

        /* These two members must be first. */

        struct sk_buff      *next;

        struct sk_buff      *prev;

     

        struct sock      *sk;

        ktime_t           tstamp;

        struct net_device*dev;

     

        unsigned long     _skb_dst;

    #ifdef CONFIG_XFRM

        struct sec_path   *sp;

    #endif

        /*

         * This is the control buffer. It is free touse for every

         * layer. Please put your private variablesthere. If you

         * want to keep them across layers you have todo a skb_clone()

         * first. This is owned by whoever has the skbqueued ATM.

         */

        char          cb[48];

     

        unsigned int      len,

                  data_len;

        __u16         mac_len,

                  hdr_len;

        union {

           __wsum     csum;

           struct {

               __u16  csum_start;

               __u16  csum_offset;

           };

        };

        __u32         priority;

        kmemcheck_bitfield_begin(flags1);

        __u8          local_df:1,

                  cloned:1,

                  ip_summed:2,

                  nohdr:1,

                  nfctinfo:3;

        __u8          pkt_type:3,

                   fclone:2,

                  ipvs_property:1,

                  peeked:1,

                  nf_trace:1;

        __be16        protocol:16;

        kmemcheck_bitfield_end(flags1);

     

        void          (*destructor)(struct sk_buff*skb);

    #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)

        struct nf_conntrack *nfct;

        struct sk_buff      *nfct_reasm;

    #endif

    #ifdef CONFIG_BRIDGE_NETFILTER

        struct nf_bridge_info   *nf_bridge;

    #endif

     

        int        iif;

    #ifdef CONFIG_NET_SCHED

        __u16         tc_index; /* traffic controlindex */

    #ifdef CONFIG_NET_CLS_ACT

        __u16         tc_verd;  /* traffic controlverdict */

    #endif

    #endif

     

        kmemcheck_bitfield_begin(flags2);

        __u16         queue_mapping:16;

    #ifdef CONFIG_IPV6_NDISC_NODETYPE

        __u8          ndisc_nodetype:2,

                  deliver_no_wcard:1;

    #else

        __u8          deliver_no_wcard:1;

    #endif

    #ifndef __GENKSYMS__

        __u8          ooo_okay:1;

    #endif

        kmemcheck_bitfield_end(flags2);

     

        /* 0/13 bit hole */

     

    #ifdef CONFIG_NET_DMA

        dma_cookie_t      dma_cookie;

    #endif

    #ifdef CONFIG_NETWORK_SECMARK

        __u32         secmark;

    #endif

        union {

           __u32      mark;

           __u32      dropcount;

        };

     

        __u16         vlan_tci;

    #ifndef __GENKSYMS__

        __u16         rxhash;

    #endif

        sk_buff_data_t       transport_header;

        sk_buff_data_t       network_header;

        sk_buff_data_t       mac_header;

        /* These elements must be at the end,see alloc_skb() for details.  */

        sk_buff_data_t       tail;

        sk_buff_data_t       end;

        unsigned char     *head,

                  *data;

        unsigned int      truesize;

        atomic_t      users;

    };

    4.16  sk_buff_head

    数据包队列结构

    structsk_buff_head {

        /* These two members must be first.*/

        struct sk_buff    *next;

        struct sk_buff    *prev;

     

        __u32      qlen;

        spinlock_t lock;

    };

    4.17  net_device

    这个巨大的结构体描述一个网络设备的所有属性,数据等信息。

    /*

     *  TheDEVICE structure.

     *  Actually,this whole structure is a big mistake. It mixes I/O

     *  datawith strictly "high-level" data, and it has to know about

     *  almostevery data structure used in the INET module.

     *

     *  FIXME:cleanup struct net_device such that network protocol info

     *  movesout.

     */

     

    structnet_device

    {

     

        /*

         * This is the first field of the"visible" part of this structure

         * (i.e. as seen by users in the"Space.c" file).  It is thename

         * the interface.

         */

        char          name[IFNAMSIZ];

        /* device name hash chain */

        struct hlist_node name_hlist;

        /* snmp alias */

        char          *ifalias;

     

        /*

         *  I/Ospecific fields

         *  FIXME:Merge these and struct ifmap into one

         */

        unsigned long     mem_end;   /* shared mem end */

        unsigned long     mem_start; /* shared mem start  */

        unsigned long     base_addr; /* device I/Oaddress    */

        unsigned int      irq;       /* device IRQ number */

     

        /*

         *  Somehardware also needs these fields, but they are not

         *  partof the usual set specified in Space.c.

         */

     

        unsigned char     if_port;   /* Selectable AUI,TP,..*/

        unsigned char     dma;       /* DMA channel       */

     

        unsigned long     state;

     

        struct list_head  dev_list;

        struct list_head  napi_list;

     

        /* Net device features */

        unsigned long     features;

    #define NETIF_F_SG       1   /* Scatter/gather IO. */

    #define NETIF_F_IP_CSUM     2  /* Can checksum TCP/UDP over IPv4. */

    #define NETIF_F_NO_CSUM     4  /* Does not require checksum. F.e. loopack. */

    #define NETIF_F_HW_CSUM     8  /* Can checksum all the packets. */

    #define NETIF_F_IPV6_CSUM   16 /* Can checksum TCP/UDP over IPV6 */

    #define NETIF_F_HIGHDMA     32 /* Can DMA to high memory. */

    #define NETIF_F_FRAGLIST 64  /* Scatter/gather IO. */

    #define NETIF_F_HW_VLAN_TX  128/* Transmit VLAN hw acceleration */

    #define NETIF_F_HW_VLAN_RX  256/* Receive VLAN hw acceleration */

    #define NETIF_F_HW_VLAN_FILTER  512/* Receive filtering on VLAN */

    #define NETIF_F_VLAN_CHALLENGED 1024  /* Device cannot handle VLAN packets */

    #define NETIF_F_GSO      2048  /* Enable software GSO. */

    #define NETIF_F_LLTX     4096  /* LockLess TX - deprecated. Please */

                      /* do not use LLTXin new drivers */

    #define NETIF_F_NETNS_LOCAL 8192  /* Does not change network namespaces */

    #define NETIF_F_GRO      16384 /* Generic receive offload */

    #define NETIF_F_LRO      32768 /* large receive offload */

     

    /* the GSO_MASK reserves bits 16 through 23 */

    #define NETIF_F_FCOE_CRC (1 <<24)/* FCoECRC32 */

    #define NETIF_F_SCTP_CSUM   (1<< 25)/* SCTPchecksum offload */

    #define NETIF_F_FCOE_MTU (1 <<26)/*Supports max FCoE MTU, 2158 bytes*/

    #define NETIF_F_NTUPLE      (1<< 27)/*N-tuple filters supported */

    #define NETIF_F_RXHASH      (1<< 28)/*Receive hashing offload */

    #define NETIF_F_RXCSUM      (1<< 29)/*Receive checksumming offload */

     

        /* Segmentation offload features */

    #define NETIF_F_GSO_SHIFT   16

    #define NETIF_F_GSO_MASK 0x00ff0000

    #define NETIF_F_TSO      (SKB_GSO_TCPV4<< NETIF_F_GSO_SHIFT)

    #define NETIF_F_UFO      (SKB_GSO_UDP<< NETIF_F_GSO_SHIFT)

    #define NETIF_F_GSO_ROBUST  (SKB_GSO_DODGY<< NETIF_F_GSO_SHIFT)

    #define NETIF_F_TSO_ECN     (SKB_GSO_TCP_ECN<< NETIF_F_GSO_SHIFT)

    #define NETIF_F_TSO6     (SKB_GSO_TCPV6<< NETIF_F_GSO_SHIFT)

    #define NETIF_F_FSO      (SKB_GSO_FCOE<< NETIF_F_GSO_SHIFT)

    #define NETIF_F_ALL_TSO (NETIF_F_TSO| NETIF_F_TSO6 | NETIF_F_TSO_ECN)

     

        /* List of features with softwarefallbacks. */

    #define NETIF_F_GSO_SOFTWARE    (NETIF_F_TSO| NETIF_F_TSO_ECN | \

                   NETIF_F_TSO6 | NETIF_F_UFO)

     

     

    #define NETIF_F_GEN_CSUM (NETIF_F_NO_CSUM| NETIF_F_HW_CSUM)

    #define NETIF_F_V4_CSUM     (NETIF_F_GEN_CSUM| NETIF_F_IP_CSUM)

    #define NETIF_F_V6_CSUM     (NETIF_F_GEN_CSUM| NETIF_F_IPV6_CSUM)

    #define NETIF_F_ALL_CSUM (NETIF_F_V4_CSUM| NETIF_F_V6_CSUM)

     

        /*

         * If one device supports one of thesefeatures, then enable them

         * for all in netdev_increment_features.

         */

    #define NETIF_F_ONE_FOR_ALL (NETIF_F_GSO_SOFTWARE| NETIF_F_GSO_ROBUST | \

                   NETIF_F_SG | NETIF_F_HIGHDMA |    \

                   NETIF_F_FRAGLIST)

     

        /* Interface index. Unique deviceidentifier  */

        int        ifindex;

        int        iflink;

     

        struct net_device_stats  stats;

     

    #ifdef CONFIG_WIRELESS_EXT

        /* List of functions to handleWireless Extensions (instead of ioctl).

         * See <net/iw_handler.h> for details.Jean II */

        const struct iw_handler_def *   wireless_handlers;

        /* Instance data managed by the coreof Wireless Extensions. */

        struct iw_public_data*  wireless_data;

    #endif

        /* Management operations */

        const struct net_device_ops *netdev_ops;

        const struct ethtool_ops *ethtool_ops;

     

        /* Hardware header description */

        const struct header_ops *header_ops;

     

        unsigned int      flags; /* interface flags(a la BSD)   */

        unsigned short       gflags;

            unsigned short          priv_flags;/* Like 'flags' but invisible touserspace. */

        unsigned short       padded;    /* How much paddingadded by alloc_netdev() */

     

        unsigned char     operstate; /* RFC2863 operstate */

        unsigned char     link_mode; /* mapping policy to operstate */

     

        unsigned      mtu;  /* interface MTUvalue      */

        unsigned short       type;  /* interfacehardware type  */

        unsigned short       hard_header_len; /* hardware hdr length   */

     

        /* extra head- and tailroom thehardware may need, but not in all cases

         * can this be guaranteed, especially tailroom.Some cases also use

         * LL_MAX_HEADER instead to allocate the skb.

         */

        unsigned short       needed_headroom;

        unsigned short       needed_tailroom;

     

        struct net_device *master;/* Pointer to masterdevice of a group,

                        * which this device is member of.

                        */

     

        /* Interface address info. */

        unsigned char     perm_addr[MAX_ADDR_LEN];/* permanent hwaddress */

        unsigned char     addr_assign_type;/* hw address assignment type */

        unsigned char     addr_len;  /* hardware addresslength  */

        unsigned short          dev_id;      /* for sharednetwork cards */

     

        struct netdev_hw_addr_list  uc;/* Secondary unicast

                            mac addresses */

        int        uc_promisc;

        spinlock_t    addr_list_lock;

        struct dev_addr_list*mc_list; /* Multicast mac addresses  */

        int        mc_count; /* Number of installed mcasts   */

        unsigned int      promiscuity;

        unsigned int      allmulti;

     

     

        /* Protocol specific pointers */

       

    #ifdef CONFIG_NET_DSA

        void          *dsa_ptr; /* dsa specific data */

    #endif

        void          *atalk_ptr;  /* AppleTalk link    */

        void          *ip_ptr;  /* IPv4 specific data    */

        void                   *dn_ptr;       /* DECnet specific data */

        void                   *ip6_ptr;      /* IPv6specific data */

        void          *ec_ptr;  /* Econet specific data  */

        void          *ax25_ptr;/* AX.25 specific data

                            also used by openvswitch */

        struct wireless_dev *ieee80211_ptr;  /* IEEE 802.11 specific data,

                            assign before registering */

     

    /*

     * Cache line mostly used on receivepath (including eth_type_trans())

     */

        unsigned long     last_rx;   /* Time of last Rx   */

        /* Interface address info used ineth_type_trans() */

        unsigned char     *dev_addr;/* hw address,(before bcast

                            because most packets are

                            unicast) */

     

        struct netdev_hw_addr_list  dev_addrs;/* list of device

                               hw addresses */

     

        unsigned char     broadcast[MAX_ADDR_LEN];/* hw bcast add   */

     

        struct netdev_queue  rx_queue;

     

        struct netdev_queue *_tx____cacheline_aligned_in_smp;

     

        /* Number of TX queues allocated atalloc_netdev_mq() time  */

        unsigned int      num_tx_queues;

     

        /* Number of TX queues currentlyactive in device  */

        unsigned int      real_num_tx_queues;

     

        /* root qdisc from userspace point ofview */

        struct Qdisc      *qdisc;

     

        unsigned long     tx_queue_len; /* Max frames perqueue allowed */

        spinlock_t    tx_global_lock;

    /*

     * One part is mostly used on xmitpath (device)

     */

        /* These may be needed for futurenetwork-power-down code. */

     

        /*

         * trans_start here is expensive for high speeddevices on SMP,

         * please use netdev_queue->trans_startinstead.

         */

        unsigned long     trans_start;  /* Time (in jiffies)of last Tx */

     

        int        watchdog_timeo;/* used bydev_watchdog() */

        struct timer_list watchdog_timer;

     

        /* Number of references to thisdevice */

        atomic_t      refcnt ____cacheline_aligned_in_smp;

     

        /* delayed register/unregister */

        struct list_head  todo_list;

        /* device index hash chain */

        struct hlist_node index_hlist;

     

        struct net_device *link_watch_next;

     

        /* register/unregister state machine*/

        enum { NETREG_UNINITIALIZED=0,

              NETREG_REGISTERED,/* completedregister_netdevice */

               NETREG_UNREGISTERING, /* called unregister_netdevice */

               NETREG_UNREGISTERED,  /* completed unregister todo */

               NETREG_RELEASED,      /* called free_netdev */

               NETREG_DUMMY,     /* dummy device forNAPI poll */

        } reg_state;

     

        /* Called from unregister, can beused to call free_netdev */

        void (*destructor)(struct net_device*dev);

     

    #ifdef CONFIG_NETPOLL

        struct netpoll_info *npinfo;

    #endif

     

    #ifdef CONFIG_NET_NS

        /* Network namespace this networkdevice is inside */

        struct net    *nd_net;

    #endif

     

        /* mid-layer private */

        void          *ml_priv;

     

        /* bridge stuff */

        struct net_bridge_port  *br_port;

        /* macvlan */

        struct macvlan_port *macvlan_port;

        /* GARP */

        struct garp_port  *garp_port;

     

        /* class/net/name entry */

        struct device     dev;

        /* space for optional statistics andwireless sysfs groups */

        const struct attribute_group *sysfs_groups[3];

     

        /* rtnetlink link ops */

        const struct rtnl_link_ops *rtnl_link_ops;

     

        /* VLAN feature mask */

        unsigned long vlan_features;

     

        /* for setting kernel sock attributeon TCP connection setup */

    #define GSO_MAX_SIZE     65536

        unsigned int      gso_max_size;

     

    #ifdef CONFIG_DCB

        /* Data Center Bridging netlink ops*/

        const struct dcbnl_rtnl_ops *dcbnl_ops;

    #endif

     

    #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)

        /* max exchange id for FCoE LRO byddp */

        unsigned int      fcoe_ddp_xid;

    #endif

    };

     

     

    4.18  inet_protosw

    向IP层注册socket层的调用操作接口

    /* This is used to register socket interfaces for IP protocols.  */

    structinet_protosw {

        struct list_head list;

     

            /* These two fields form the lookupkey.  */

        unsigned short    type;    /* This is the 2ndargument to socket(2). */

        unsigned short    protocol; /* This is the L4protocol number.  */

     

        struct proto*prot;

       const struct proto_ops *ops;

     

        char             no_check;  /* checksum on rcv/xmit/none? */

        unsigned char flags;     /* SeeINET_PROTOSW_* below.  */

    };

     

    4.19  inetsw_array

    socket层调用IP层操作接口都在这个数组中注册。

    /* Upon startup we insert all the elements in inetsw_array[] into

     * the linked list inetsw.

     */

    static struct inet_protoswinetsw_array[] =

    {

        {

           .type =      SOCK_STREAM,

           .protocol=  IPPROTO_TCP,

           .prot =      &tcp_prot,

           .ops =        &inet_stream_ops,

           .no_check=  0,

           .flags =     INET_PROTOSW_PERMANENT |

                     INET_PROTOSW_ICSK,

        },

     

        {

           .type =      SOCK_DGRAM,

           .protocol =  IPPROTO_UDP,

           .prot =       &udp_prot,

           .ops =        &inet_dgram_ops,

           .no_check=  UDP_CSUM_DEFAULT,

           .flags =     INET_PROTOSW_PERMANENT,

           },

     

           {

           .type =      SOCK_DGRAM,

           .protocol=  IPPROTO_ICMP,

           .prot =      &ping_prot,

           .ops =        &inet_dgram_ops,

           .no_check=  UDP_CSUM_DEFAULT,

           .flags =     INET_PROTOSW_REUSE,

           },

     

           {

               .type=      SOCK_RAW,

               .protocol=  IPPROTO_IP, /* wild card */

               .prot=      &raw_prot,

               .ops =        &inet_sockraw_ops,

               .no_check=  UDP_CSUM_DEFAULT,

               .flags=     INET_PROTOSW_REUSE,

           }

    };

    4.20  sock_type

    socket类型

    /**

     * enum sock_type - Socket types

     * @SOCK_STREAM: stream (connection)socket

     * @SOCK_DGRAM: datagram (conn.less)socket

     * @SOCK_RAW: raw socket

     * @SOCK_RDM: reliably-deliveredmessage

     * @SOCK_SEQPACKET: sequentialpacket socket

     * @SOCK_DCCP: Datagram CongestionControl Protocol socket

     * @SOCK_PACKET: linux specific wayof getting packets at the dev level.

     *       For writing rarp and other similar things onthe user level.

     *

     * When adding some new socket typeplease

     * grep ARCH_HAS_SOCKET_TYPEinclude/asm-* /socket.h, at least MIPS

     * overrides this enum for binarycompat reasons.

     */

    enumsock_type {

        SOCK_STREAM   =1,

        SOCK_DGRAM = 2,

        SOCK_RAW   =3,

        SOCK_RDM   =4,

        SOCK_SEQPACKET    =5,

        SOCK_DCCP  =6,

        SOCK_PACKET   =10,

    };

    4.21  IPPROTO

    传输层协议类型ID

    /* Standard well-defined IP protocols. */

    enum {

      IPPROTO_IP = 0,     /* Dummy protocol for TCP       */

      IPPROTO_ICMP =1,     /* Internet Control Message Protocol   */

      IPPROTO_IGMP =2,     /* Internet Group Management Protocol  */

      IPPROTO_IPIP =4,     /* IPIP tunnels (older KA9Q tunnels use 94) */

      IPPROTO_TCP = 6,       /* Transmission Control Protocol   */

      IPPROTO_EGP = 8,       /* Exterior Gateway Protocol       */

      IPPROTO_PUP = 12,      /* PUP protocol             */

      IPPROTO_UDP = 17,      /* User Datagram Protocol       */

      IPPROTO_IDP = 22,      /* XNS IDP protocol         */

      IPPROTO_DCCP =33,    /* Datagram Congestion Control Protocol */

      IPPROTO_RSVP =46,    /* RSVP protocol         */

      IPPROTO_GRE = 47,      /* Cisco GRE tunnels (rfc 1701,1702)   */

     

      IPPROTO_IPV6 =41,    /* IPv6-in-IPv4tunnelling      */

     

      IPPROTO_ESP = 50,            /* Encapsulation Security Payloadprotocol */

      IPPROTO_AH = 51,             /* Authentication Headerprotocol       */

      IPPROTO_BEETPH =94,         /* IP option pseudoheader for BEET */

      IPPROTO_PIM    =103,      /* ProtocolIndependent Multicast  */

     

      IPPROTO_COMP   =108,               /* CompressionHeader protocol */

      IPPROTO_SCTP   =132,     /* Stream ControlTransport Protocol   */

      IPPROTO_UDPLITE =136,/* UDP-Lite (RFC 3828)          */

     

      IPPROTO_RAW  =255,   /* Raw IP packets        */

      IPPROTO_MAX

    };

     

    /* The inetsw table contains everything that inet_create needs to

     * build a new socket.

     */

    static struct list_head inetsw[SOCK_MAX];

     

     

    4.22  net_protocol

    用于传输层协议向IP层注册收包的接口

    /* This is used to register protocols. */

    struct net_protocol{

             int                     (*handler)(structsk_buff*skb);

        void          (*err_handler)(struct sk_buff*skb, u32 info);

        int        (*gso_send_check)(struct sk_buff*skb);

        struct sk_buff          *(*gso_segment)(struct sk_buff*skb,

                             int features);

        struct sk_buff         **(*gro_receive)(struct sk_buff**head,

                             struct sk_buff*skb);

        int        (*gro_complete)(struct sk_buff*skb);

        unsigned int      no_policy:1,

                  netns_ok:1;

    };

     

    实例,UDP向IP层注册的接口

    static const struct net_protocoludp_protocol={

        .handler = udp_rcv,

        .err_handler=    udp_err,

        .gso_send_check= udp4_ufo_send_check,

        .gso_segment= udp4_ufo_fragment,

        .no_policy =  1,

        .netns_ok =   1,

    };

     

    IP层收包的接口都在这个数组中注册。

    externconst struct net_protocol *inet_protos[MAX_INET_PROTOS];

    4.23  packet_type

    以太网数据包的结构,包括了以太网帧类型,包处理方法等。

    structpacket_type {

        __be16        type;  /* This is really htons(ether_type). */

        struct net_device *dev; /* NULL is wildcarded here       */

        int        (*func) (struct sk_buff*,

                       struct net_device*,

                       struct packet_type*,

                       struct net_device*);

        struct sk_buff      *(*gso_segment)(struct sk_buff*skb,

                         int features);

        int        (*gso_send_check)(struct sk_buff*skb);

        struct sk_buff      **(*gro_receive)(struct sk_buff**head,

                             struct sk_buff*skb);

        int        (*gro_complete)(struct sk_buff*skb);

        void          *af_packet_priv;

        struct list_head  list;

    };

     

    IP协议向链路层注册的包处理接口。

    /*

     *  IPprotocol layer initialiser

     */

    static struct packet_typeip_packet_type  ={

        .type = cpu_to_be16(ETH_P_IP),

        .func = ip_rcv,

        .gso_send_check= inet_gso_send_check,

        .gso_segment= inet_gso_segment,

        .gro_receive= inet_gro_receive,

        .gro_complete= inet_gro_complete,

    };

    /*

     *  Theseare the defined Ethernet Protocol ID's.

     */

     

    #define ETH_P_LOOP   0x0060    /* Ethernet Loopback packet */

    #define ETH_P_PUP 0x0200     /* Xerox PUP packet      */

    #define ETH_P_PUPAT  0x0201    /* Xerox PUP Addr Trans packet  */

    #defineETH_P_IP  0x0800    /*Internet Protocol packet */

    #define ETH_P_X25 0x0805     /* CCITT X.25        */

    #define ETH_P_ARP 0x0806     /* Address Resolution packet    */

    #define    ETH_P_BPQ  0x08FF    /* G8BPQ AX.25Ethernet Packet  [ NOT AN OFFICIALLYREGISTERED ID ] */

    #define ETH_P_IEEEPUP    0x0a00    /* Xerox IEEE802.3 PUP packet */

    #define ETH_P_IEEEPUPAT  0x0a01    /* Xerox IEEE802.3 PUP Addr Trans packet */

    #define ETH_P_DEC       0x6000         /* DEC Assigned proto           */

    #define ETH_P_DNA_DL    0x6001         /* DEC DNA Dump/Load            */

    #define ETH_P_DNA_RC    0x6002         /* DEC DNA Remote Console       */

    #define ETH_P_DNA_RT    0x6003         /* DEC DNA Routing              */

    #define ETH_P_LAT       0x6004         /* DEC LAT                      */

    #define ETH_P_DIAG      0x6005         /* DEC Diagnostics              */

    #define ETH_P_CUST      0x6006         /* DEC Customer use             */

    #define ETH_P_SCA       0x6007         /* DEC Systems Comms Arch       */

    #define ETH_P_TEB 0x6558     /* Trans Ether Bridging     */

    #define ETH_P_RARP      0x8035      /* Reverse Addr Res packet  */

    #define ETH_P_ATALK  0x809B    /* Appletalk DDP     */

    #define ETH_P_AARP   0x80F3    /* Appletalk AARP    */

    #define ETH_P_8021Q  0x8100         /* 802.1Q VLAN Extended Header  */

    #define ETH_P_IPX 0x8137     /* IPX over DIX          */

    #define ETH_P_IPV6   0x86DD    /* IPv6 over bluebook       */

    #define ETH_P_PAUSE  0x8808    /* IEEE Pause frames. See 802.3 31B */

    #define ETH_P_SLOW   0x8809    /* Slow Protocol. See 802.3ad 43B */

    #define ETH_P_WCCP   0x883E    /* Web-cache coordination protocol

                       * defined in draft-wilson-wrec-wccp-v2-00.txt*/

    #define ETH_P_PPP_DISC   0x8863    /* PPPoE discovery messages     */

    #define ETH_P_PPP_SES    0x8864    /* PPPoE session messages   */

    #define ETH_P_MPLS_UC    0x8847    /* MPLS Unicast traffic     */

    #define ETH_P_MPLS_MC    0x8848    /* MPLS Multicast traffic   */

    #define ETH_P_ATMMPOA    0x884c    /* MultiProtocol Over ATM   */

    #define ETH_P_ATMFATE    0x8884    /* Frame-based ATM Transport

                       * over Ethernet

                       */

    #define ETH_P_PAE 0x888E     /* Port Access Entity (IEEE 802.1X) */

    #define ETH_P_AOE 0x88A2     /* ATA over Ethernet     */

    #define ETH_P_TIPC   0x88CA    /* TIPC           */

    #define ETH_P_1588   0x88F7    /* IEEE 1588 Timesync */

    #define ETH_P_FCOE   0x8906    /* Fibre Channel over Ethernet  */

    #define ETH_P_TDLS   0x890D    /* TDLS */

    #define ETH_P_FIP 0x8914     /* FCoE Initialization Protocol */

    #define ETH_P_EDSA   0xDADA    /* Ethertype DSA [ NOT AN OFFICIALLY REGISTERED ID] */

    #define ETH_P_AF_IUCV   0xFBFB     /* IBM af_iucv [ NOT AN OFFICIALLY REGISTERED ID ]*/


     

    网络层向链路层注册操作函数集合在此数据。

    static struct list_head ptype_base[PTYPE_HASH_SIZE];

    4.24  rtable

    路由表结构,描述一个路由表的完整形态。

    struct rtable {

        union

        {

           struct dst_entry  dst;

        } u;

     

        /* Cache lookup keys */

        struct flowi      fl;

     

        struct in_device  *idev;

       

        int        rt_genid;

        unsigned      rt_flags;

        __u16         rt_type;

     

        __be32        rt_dst;   /* Path destination  */

        __be32        rt_src;   /* Path source       */

        int        rt_iif;

     

        /* Info on neighbour */

        __be32        rt_gateway;

     

        /* Miscellaneous cached information*/

        __be32        rt_spec_dst;/* RFC1122 specific destination */

        struct inet_peer  *peer;/* long-living peerinfo */

    };

     

    4.25  rt_hash_bucket

    路由表缓存

    /*

     * Route cache.

     */

     

    /* The locking scheme is rather straight forward:

     *

     * 1) Read-Copy Update protects thebuckets of the central route hash.

     * 2) Only writers remove entries,and they hold the lock

     *   as they look at rtable reference counts.

     * 3) Only readers acquirereferences to rtable entries,

     *   they do so with atomic increments and with the

     *   lock held.

     */

     

    structrt_hash_bucket {

        struct rtable *chain;

    };

     

    4.26  dst_entry

    包的去向接口,描述了包的去留,下一跳等路由关键信息。

    /* Each dst_entry has reference count and sits in some parent list(s).

     * When it is removed from parentlist, it is "freed" (dst_free).

     * After this it enters dead state(dst->obsolete > 0) and if its refcnt

     * is zero, it can be destroyedimmediately, otherwise it is added

     * to gc list and garbage collectorperiodically checks the refcnt.

     */

    structdst_entry

    {

        struct rcu_head      rcu_head;

        struct dst_entry  *child;

        struct net_device      *dev;

        short         error;

        short         obsolete;

        int        flags;

    #define DST_HOST     1

    #define DST_NOXFRM       2

    #define DST_NOPOLICY     4

    #define DST_NOHASH       8

        unsigned long     expires;

     

        unsigned short       header_len;  /* more space athead required */

        unsigned short       trailer_len; /* space to reserveat tail */

     

        unsigned int      rate_tokens;

        unsigned long     rate_last; /* rate limiting forICMP */

     

        struct dst_entry  *path;

     

        struct neighbour  *neighbour;

        struct hh_cache     *hh;

    #ifdef CONFIG_XFRM

        struct xfrm_state *xfrm;

    #else

        void          *__pad1;

    #endif

        int        (*input)(struct sk_buff*);

        int        (*output)(struct sk_buff*);

     

        struct dst_ops          *ops;

     

    /* This Red Hat kABI workaround will shift tclassid 32 bit, while we

     * still keep the original size ofdst_entry and assures alignment

     * (see further down).

     */

    #ifdef __GENKSYMS__

        u32        metrics[RTAX_MAX_ORIG];

    #else

        u32        metrics[RTAX_MAX];

    #endif

     

    #ifdef CONFIG_NET_CLS_ROUTE

        __u32         tclassid;

    #else

        __u32         __pad2;

    #endif

     

     

        /*

         * Align __refcnt to a 64 bytes alignment

         * (L1_CACHE_SIZE would be too much)

         */

    /* Red Hat kABI workaround to assure aligning __refcnt, while

     * consuming 32 bit of padding forour metrics expansion above.

     * On 32bit archs not padding remains.

     */

    #ifdef __GENKSYMS__

    #ifdef CONFIG_64BIT

        long          __pad_to_align_refcnt[2];

    #else

        long          __pad_to_align_refcnt[1];

    #endif

    #else  /* __GENKSYMS__ */

    #ifdef CONFIG_64BIT

        u32        __pad_hole_in_struct;

        long          __pad_to_align_refcnt[1];

    #endif

    #endif /*__GENKSYMS__ */

     

        /*

         * __refcnt wants to be on a different cacheline from

         * input/output/ops or performance tanks badly

         */

        atomic_t      __refcnt; /* client references */

        int        __use;

        unsigned long     lastuse;

        union {

           struct dst_entry*next;

           struct rtable   *rt_next;

           struct rt6_info  *rt6_next;

           struct dn_route *dn_next;

        };

    };

     

    4.27  napi_struct

    NAPI调度的结构

    NAPI: NAPI是LINUX上采用的一种提高网络处理效率的技术,它的核心概念就是不采用中断的方式读取数据,而代之以首先采用中断唤醒数据接收服务,然后采用poll的方法来轮询数据。NAPI技术适用于高速率的短长度数据包的处理。

    /*

     * Structure for NAPI schedulingsimilar to tasklet but with weighting

     */

    structnapi_struct {

        /* The poll_list must only be managedby the entity which

         * changes the state of the NAPI_STATE_SCHEDbit.  This means

         * whoever atomically sets that bit can addthis napi_struct

         * to the per-cpu poll_list, and whoever clearsthat bit

         * can remove from the list right beforeclearing the bit.

         */

        struct list_head  poll_list;

     

        unsigned long     state;

        int        weight;

        int        (*poll)(structnapi_struct*,int);

    #ifdef CONFIG_NETPOLL

        spinlock_t    poll_lock;

        int        poll_owner;

    #endif

     

        unsigned int      gro_count;

     

        struct net_device *dev;

        struct list_head  dev_list;

        struct sk_buff      *gro_list;

        struct sk_buff      *skb;

    };

    5       数据结构类图

    图2  数据结构

    6       协议栈注册流程

    6.1内核启动流程

    当内核完成自解压过程后进入内核启动,这一过程先在arch/mips/kernel/head.S 程序中,这个程序负责数据区(BBS)、中断描述表(IDT)、段描述表(GDT)、页表和寄存器的初始化,程序中定义了内核的入口函数 kernel_entry( ) , kernel_entry( )函数是体系结构相关的汇编代码,它首先初始化内核堆栈段为创建系统中的第一过程进行准备,接着用一段循环将内核映像的未初始化的数据段清零,最后跳到 start_kernel()函数中初始化硬件相关的代码,完成Linux核心环境的建立。

     

    start_kenrel()定义在init/main.c中,真正的内核初始化过程就是从这里才开始。函数start_kerenl()将会调用一系列的初始化函数,用来完成内核本身的各方面设置,如中断,内存管理,进程管理,信号,文件系统,目的是最终建立起基本完整的Linux核心环境

     

    start_kernel()函数中主要函数及调用关系如下:

     

     

    start_kernel

     

    setup_arch

     

    sched_init

     

    init_IRQ

     

    proc_root_init

     

    mm_init

     

    console_init

     

    rest_init

     

    cpu_probe

     

    prom_init

     

    cpu_report

     

    arch_mem_init

     

    resource_init

     

    kernel_init

     

    cpu_idle

     

    do_basic_setup

     

    init_post

     

    init_tmpfs

     

    driver_init

     

    do_initcalls

    6.2协议栈初始化流程

     

    sock_init:  Initializesk_buff SLAB cache注册socket文件系统

    net_inuse_init:         为每个CPU分配缓存。

    proto_init:        在/proc/net域下建立protocols文件,注册相关文件操作函数

    net_dev_init:   建立netdevice在/proc/sys相关的数据结构,并且开启网卡收发中断。

    为每个CPU初始化一个数据包接收队列(softnet_data),包接收的回调。注册本地回环操作,注册默认网络设备操作。 驱动层

    Inet_init:   注册Inet协议族的socket创建方法,注册tcp,udp,icmp,igmp 接口基本的收包方法。为IPv4协议族创建proc文件。

    此函数为协议栈主要的注册函数:

    1.        rc = proto_register(&udp_prot, 1); 注册inet层udp协议,为其分配快速缓存。

    2.        (void)sock_register(&inet_family_ops); 向static const struct net_proto_family *net_families[NPROTO] ; 结构注册inet协议族的操作集合(主要是协议族inetsocket的创建操作)。Inet socket层

    3.        inet_add_protocol(&udp_protocol, IPPROTO_UDP) < 0,  向externconst struct net_protocol *inet_protos[MAX_INET_PROTOS];(网络层)注册传输层UDP的操作集合。网络层

    4.        static struct list_head inetsw[SOCK_MAX];    for (r = &inetsw[0]; r < &inetsw[SOCK_MAX];++r)    INIT_LIST_HEAD(r);   初始化SOCKET类型数组,其中保存了这是个链表数组,每个元素是一个链表,连接使用同种socket类型的协议和操作集合。

    5.        for (q = inetsw_array; q < &inetsw_array[INETSW_ARRAY_LEN];++q)

    a)        inet_register_protosw(q);

    向sock层注册协议的的调用操作集合   bsd socket层和 inet socket层

    6.        arp_init(); 启动arp协议支持

    7.        ip_init(); 启动Ip协议支持

    8.        udp_init(); 启动UDP协议支持

    9.        dev_add_pack(&ip_packet_type);  向 ptype_base[PTYPE_HASH_SIZE] ; 注册ip 协议的操作集合。 协议无关层

    10.    系统调用层:  socket.c中提供的系统调用接口。

     

    7      socket创建流程

             本章主要介绍socket创建的流程,参数传递过程。fd = socket(family, type, protocol); 创建后,内存中的数据结构的组织结构。

     

    图3  socket创建流程

    8      协议栈收包流程

    以UDP协议为例

    图  收发流程页


     

    8.1驱动收包流程

    以UDP协议为例

     

    图         内核收包流程页

    8.2应用层收包流程

    以UDP协议为例

     

    图        应用层收包流程页

    9      协议栈发包流程

    以UDP协议为例

     

    图    UDP发包流程

     

    10            总结

    本文只是对协议栈流程做了些粗略的分析,里面涉及到大量的技术思想没有办法传达,要深入理解可先参考csdn博主yming0221的关于协议栈的文章,链接为  http://blog.csdn.net/column/details/linux-kernel-net.html。或者直接阅读linux内核协议栈源码。

    1.       TCP/IP详解卷一

    2 .博客 http://blog.csdn.net/column/details/linux-kernel-net.html

     

    图1    初始化流程

     

     

     

    图2   分层数据结构

     

    图3  socket 创建流程

     

    图4 收发流程 

     

    图 5  内核收包流程细化 (中断收包)

     

    图6 应用层收包流程   

     

    图7  UDP发包流程

     

     .

    转载于:https://www.cnblogs.com/liuhongru/p/11412363.html

    展开全文
  • Host 上面的应用层就是各种Profiles 服务了,BLE 协议架构图示如下(Core_V5.2 为LE Audio 服务新增了等时同步信道,没有在下图显式展示): BLE 协议栈各层功能描述如下: Physical Layer(PHY):指定BLE 所用的无线...

    前言

    前篇博文Bluetooth 协议栈设计与演进已经分别介绍了蓝牙协议的四大应用场景及对应的技术解决方案,为满足物联网设备的需求,蓝牙协议新增了室内精准定位技术、基于MESH 的大规模自组网技术和基于6LoWPAN 的IPv6 组网技术,逐渐在物联网无线技术中占稳短距离低速率无线通信的生态位,未来前景可期。
    Bluetooth 5.2 协议架构
    蓝牙技术联盟SIG 已经将重心放到BLE 低功耗协议上,为满足物联网设备需求新推出的技术方案也都是基于BLE 协议的,随着LE Audio 技术的发布,蓝牙设备的主要应用场景都可以在BLE 协议上承载,而不再依赖于BR/EDR 协议。由于BR/EDR 协议即将迟暮,且与LE 协议是相对独立的,二者并没有继承关系,后续将基于BLE 协议介绍蓝牙技术。

    一、BLE System Architecture

    对照上面的Bluetooth 协议结构图,屏蔽掉左边的BR/EDR Controller和右边的AMP Controller,只保留中间的LE Controller,将LE Controller 抽象为Physical Layer 和Logic Link Layer 两个层级(如果要进行LE Audio 开发,需要突出 Isochronous Adaptation Layer,本文就将其折叠进抽象的Link Layer了)。

    LE Controller 与Host 之间有一个HCI 主机控制器接口层,该层定义了Host 与Controller 之间的通信接口规范。最早蓝牙是跟随手机发展的,蓝牙模块和手机处理器芯片都是一个独立的芯片,而且各自都有很多种,为了保证蓝牙模块与CPU 芯片之间通信的兼容性,SIG 就定义了一套统一的通信接口规范HCI,只要符合HCI 标准,不同的CPU 芯片与不同的蓝牙Controller 模块之间就能顺畅的通过HCI over UART/USB 接口完成通信(下图中间的方案,比如 CPU 芯片常采用Bluez 来实现Host 功能)。在低功耗低成本的物联网设备中,通常把Host 与Controller 放到同一个Soc 芯片上,这时物理的HCI 就没有存在的必要了,Host 与Controller 之间直接通过API 来交互(下图左边的方案,比如Nordic的蓝牙协议栈Softdevice 实现了整个蓝牙协议栈的功能)。下图右边的方案需要使用蓝牙芯片供应商提供的专有通信协议,通用性和兼容性受限。
    蓝牙协议栈方案

    Host 部分直接与Controller Link Layer 通信的是L2CAP (Logical Link Control and Adaptation Protocol) Layer,像音频这种ISO 数据流不经过L2CAP 处理,直接与ISO Adaptation Layer 通信更高效。BLE 协议的GATT 已经将所有服务信息都放到ATT 中了,因此不再需要单独的SDP 服务发现协议。Host 上面的应用层就是各种Profiles 服务了,BLE 协议架构图示如下(Core_V5.2 为LE Audio 服务新增了等时同步信道,没有在下图显式展示):
    BLE 协议栈结构
    BLE 协议栈各层功能描述如下:

    • Physical Layer(PHY):指定BLE 所用的无线频段(ISM 频段被分成40个channel,每个channel 占用2M Hz频宽,比特速率可支持到 2 Mbps,40个信道分为 3 个广播信道和37 个数据信道,为避开同频干扰采用跳频技术切换信道)、调制解调方式(BLE 采用GFSK 高斯频移键控调制)、射频性能(比如发射功率、接收灵敏度)等;
    • Link Layer(LL):该层要做的事情非常多,比如具体选择哪个射频通道进行通信,怎么识别空中数据包,具体在哪个时间点把数据包发送出去,怎么保证数据的完整性,ACK如何接收,如何进行重传,以及如何对链路进行管理和控制等等。LL层只负责把数据发出去或者收回来,对数据进行怎样的解析则交给上面的GAP或者ATT;
    • Host Controller Interface(HCI) :定义Host 与Controller 模块之间的通信接口规范,HCI 主要用于Host 模块与Controller 模块分别在2 颗芯片上实现BLE协议栈的场合,用来规范两者之间的通信协议和通信命令等;
    • L2CAP(Logic link control and adaptation protocol):对Link Layer 进行了简单封装,LL只关心传输的数据本身,L2CAP就要区分是加密通道还是普通通道,同时还要对连接间隔进行管理。同时为上层应用提供多路复用、分片重组、流量控制等机制,有点类似TCP 协议Port 的概念;
    • SMP(Security Manage Protocol) :用于管理BLE 连接通信的加密、认证和安全,比如密钥生成、信息加密、数字签名、认证鉴权、安全配对等,类似于TLS/SSL 协议的功能;
    • ATT(Attribute Protocol):“Attribute”是被编址并打上标签的一小块数据,属性协议提供一些方法供对端设备读取、修改这些属性的值(Attribute value),每个属性由四个元素构成:Attribute Handle用来唯一标识该属性、Attribute Type(UUID)用来标识存储数据的类型、Attribute Value用来存储数据的值、Attribute Permissions用来定义属性的访问权限(比如一个属性值为“25” 、属性类型为“℃”的数据,可能放在句柄标识为0x01DE 的属性中,客户端对该属性有只读权限);
    • GATT(Generic Attribute Profile):引入了“Characteristic”、“Service”、服务之间的“Include”关系、特性的“Descriptor”等概念,还定义了一些规范用来发现服务、特性、服务之间的关系,并读取、修改这些特性值。Profile 可以看作一种应用规范或者一组相关服务的集合,BLE 是面向服务的模块化设计,每个服务封装一组相关的“Attribute”及其访问方法(可以把每个“Service”类比为面向对象编程中的“class”,两者都是对一组元素据及其操作方法的封装,且都尽量封装为可重用的);
    • GAP(Generic Access Profile) :定义了设备如何发现其它设备、连接到其它设备、读取其它设备的信息并和它们进行绑定的相关Profile,以及设备如何实现可发现、可连接、可绑定的相关Profile;
    • Profiles :根据业务需求提供的一个个应用服务,比如血压、心率、温度、电量、接近检测和HID人机交互设备等,每个Profile 包含一个或多个Service(BLE 采用Client/Server架构,Server 实现并对外提供相应的应用服务,Client 可以发现并访问相应的服务数据);

    BLE 引入的一些新概念,比如Profile、Service、Characteristic、Descriptor、Attribute 之间的关系如下图所示(右图每一行对应一个Attribute,四列分别对应每个Attribute 的四个元素):
    Profile/Service/Characteristic/Attribute之间的关系

    二、LE Physical Layer

    BLE 低功耗蓝牙使用2.4 GHz ISM(Industrial Scientific Medical) 频段传输信息,这个频段是唯一一个在所有国家都无需授权的频段,Wi-Fi、Bluetooth、Zigbee 等无线局域网协议都选择该频段进行通信。ISM 2.4 GHz 频段范围是2400 – 2483.5 MHz,BLE 使用的频率范围是2402 - 2480 MHz,BLE 低频与高频部分与ISM 2.4 GHz 频段边界分别保留2 MHz 和3.5 MHz 的间隙。

    BLE 频段共分为40个信道,每个信道的频宽为2 MHz,其中37、38、39三个信道为广播信道(频率选择刻意避开了Wi-Fi 最常用的1、6、11三个信道以减少干扰),剩余37个信道为数据信道(为提高广播能力,Bluetooth 5.0 新增了扩展广播功能,也即将数据信道作为第二广播信道使用),信道分布如下图示:
    BLE 物理广播信道与数据信道频率分配
    BLE 选择的 ISM 频段虽然免授权,但也意味着面临严重的同频干扰(Wi-Fi、Zigbee等无线局域网技术都使用该频段),为了增强抗干扰性能,ISM 为BLE 做了如下设计:

    • 广播信道频点的选择避开了Wi-Fi 常用的信道,同时三个固定广播信道之间频率至少相差24 MHz,避免因为某个频段受干扰严重而影响所有广播信道通信;
    • 采用跳频技术在多个数据信道间有规律的切换,比如跳频算法 fn+1 = (fn + hop) mod 37 其中hop 是一个 5 – 16 范围内的值,当检测到到在某数据信道通信受影响时,按调频算法切换到下一个信道继续通信,由于跳频算法切换的前后信道并不连续,可以避开某频段集中干扰;
    • 采用自适应跳频技术避开受干扰的信道,当检测到受干扰信道时会将其标记为坏信道,并将已知坏信道映射到已知好信道,降低跳频算法跳到坏信道的概率,从而减少对数据信道通信的干扰;
    • GFSK 频移键控有个缺点,接收连续相同比特的能力比较差,如果遇到全0 或全 1 的比特序列,接收机会认为发射机频率偏移了,为了避免该问题,BLE 使用了“白化器”来随机化要发送的数据,接收端也使用“白化器”恢复原数据,避免传输连续相同的比特序列。

    BLE 采用GFSK(Gauss frequency Shift Keying) 高斯频移键控对传输数据进行调制,前面介绍的信道频率都是指中心频率,相对中心频率负频偏的代表bit 0,相对中心频率正频偏的代表bit 1,BLE 4.x 的调制比特率为 1 Mbps,Bluetooth 5.x 版本又新增了 2 Mbps 可选项,为支持LE Audio 音频传输打下基础。FSK 频移键控中的最小频偏随调制比特率提升而增大,调制比特率为1 Mbps 时的最小频偏约为 185 KHz,调制比特率为2 Mbps 时的最小频偏约为 370 KHz。
    BLE使用的GFSK 调制技术
    BLE 侧重于低功耗,如何实现低功耗呢?功耗跟数据的传输速率、传输时间、发射功率、调制效率等因素正相关,要想降低功耗,可以从降低传输速率、减少传输时间、降低非传输时间的待机功耗、降低传输时的发射功率、提高调制效率等方面着手,BLE 也正是依靠长时间深度睡眠、周期性唤醒并传输数据实现大幅降低平均功耗、延长续航时间的。BLE 规定的最大发射功率为 +20 dBm,最小发射功率为 -20 dBm,分为四个功率等级,根据业务对传输速率和功耗的需求选择相应的功率等级。

    BLE 要顺利解调出有效信号,对接收到的最小信号也有规定,BLE 针对不同的调制方法规定的接收灵敏度上限也不相同。在功耗不变的情况下,信号传输速率与传输距离呈负相关,也即信号传输速率越高对应的最小解调信号强度越大(接收灵敏度上限越大),想增大传输距离可以使用传输速率更低的调制技术实现(接收灵敏度上限越小)。电磁波在空气中传播是存在路径损耗的,BLE 在空气中传播允许的最大损耗功率 = 发射功率 - 接收灵敏度,对照BLE 频段电磁波的路径损耗与距离关系曲线就可以获知BLE 正常通信允许的最大距离,比如Bluetooth 5.0 宣称LE Coded PHY with S=8(每个数据位由 8 个符号表示)调制方式的传输距离可以达到LE Uncoded 1M PHY 的 4 倍。
    LE Tx Power / Rx Sensitivity / Path loss 关系
    LE Link Layer 状态机与数据报文结构见下一篇博文:LE Link Layer States + Air Interface Packets(Core_v5.2)

    更多文章:

    展开全文
  • 谈谈我对协议栈设计和架构的理解

    千次阅读 2017-04-13 16:46:00
    因为工作的关系,有幸接触到一种不那么复杂的2G通信技术的协议栈(终端)和基带两方面的内容,经过一段较长时间的摸索和思考,再加上和终端厂商一线开发人员的的讨论深化,到现在总算对协议栈设计和架构方面有了一些...
  • 一、BLE协议栈架构 BLE 协议栈(简称“协议”)由两部分组成:控制器 和 主机。控制器与主机分离的形式来自标准的蓝牙 BR / EDR设备,这两个部分通常分别描述。任何 profiles(配置文件)和应用程序都是使用 GAP ...
  • 吐血推荐历史最全的蓝牙协议栈介绍

    万次阅读 多人点赞 2020-07-21 18:29:00
    第二篇:Transport层介绍,主要介绍蓝牙协议栈跟蓝牙芯片之前的硬件传输协议,比如基于UART的H4,H5,BCSP,基于USB的H2等 第三篇:传统蓝牙controller介绍,主要介绍传统蓝牙芯片的介绍,包括射频层(RF),基带层...
  • 转载_蓝牙协议栈架构

    2015-07-30 13:56:05
    蓝牙协议栈架构     Channel manager 负责创建,管理和销毁用于传输服务协议和用户数据流的 L2CAP 频道。 Channel manager 使用 L2CAP 协议来同远端的 channel manager 交互,来创建 L2CAP 频道...
  • 蓝牙协议栈(Bluetooth stack)简介

    千次阅读 2020-08-07 11:13:35
    本文只要对蓝牙协议栈做一个简单介绍,包含hci层、acl链路、 1 l2cap层,sdp服务及几个常见的profile,让初学蓝牙协议栈的人 对整个蓝牙协议栈有一个整体框架的了解。 2 HCI层 2.1 Hci命令及应答的控制 ...
  • 蓝牙协议栈架构

    千次阅读 2011-04-08 19:41:00
    bluetooth 协议栈架构,bt各模块功能
  • 详解BLE连接建立过程https://www.cnblogs.com/iini/p/8972635.html详解BLE 空中包格式—兼BLE Link layer协议解析https://www.cnblogs.com/iini/p/8977806.html开发你的第一个BLE应用程序—Blinkyhttps://...
  • BLE协议栈为什么要分层?怎么理解BLE“连接”?如果BLE协议只有ATT层没有GATT层会发生什么?
  • 参考:千锋教育嗨哥_JDY-10M蓝牙模块教学视频 ...seid=539420550276958520&spm_id_from=333.337.0.0 JDY-10M蓝牙模块 ...使用AT指令,隐藏了底层的蓝牙通信协议栈 控制功能数据AT指令 手机APP通信 ...
  • Iptables与网络协议栈

    2019-01-18 16:05:15
    网卡->协议栈->用户空间的web服务 网卡->协议栈->其他主机 每个链上的规则都存在于一些表中。 一共有四种表:filter表、nat表、mangle表和raw表。 规则由匹配条件和处理动作组成。 匹配条件: 基本匹配...
  • 蓝牙基础(三):蓝牙协议栈总体认知 0 前言 初入门经典蓝牙学习,网上资料参差不齐,本博客旨在整理自己的一些总结内容,建立整体功能认识,以便后续深入学习。 1 蓝牙整体架构 蓝牙的整体核心架构如下图 1.1 蓝牙...
  • 1.BLE协议栈架构 从协议栈中,可以看出,BLE HOST主要有 GAP、GATT、ATT、L2CAP、SM。 2.BLE HOST层简介 2.1 GAP通用访问协议 GAP是与app或者profiles的通信接口,处理设备发现和连接的相关服务。 GAP控制...
  • ble协议栈从零开始一(学习方法和基本概念)

    万次阅读 多人点赞 2018-06-09 01:41:06
    单纯的ble的开发其实并不需要对协议栈有多了解,只需要了解上层的GAP,GATT,一些profile,和 SM即可。哈哈既然你进来了,协议栈还是了解一下。   一、学习途径: 1)www.bluetooth.org(ble的官网) 2...
  • 协议栈

    万次阅读 2014-07-12 21:41:59
    协议栈概述 ·协议栈简介 ·协议栈构建 协议栈应用资料 ·数据进入协议栈时的封装过程 ·uIP协议栈分析 ·通信协议栈中内存和时间管... ·蓝牙协议栈介绍 ·开源TCP/IP协议栈分析 ·lwIP(TCP/...
  • (4)CC254x的BLE协议栈内部通过使用HCI层来实现高层与底层之间的通讯。Host通过HCI API与低层通信     Host 逻辑链路控制与适应协议层(L2CAP) 对下,他抽象出和具体技术无关的数据传输通道,至此用户...
  • 蓝牙解析(3):BLE协议栈解析

    千次阅读 2018-09-28 10:09:45
    本文从协议栈设计者的角度,思考如下问题: 为什么会有蓝牙协议栈(Why)? 怎样实现蓝牙协议栈(How)? 蓝牙协议栈的最终样子是什么(What)? 我们知道,当前的蓝牙协议包含BR/EDR、AMP、LE三种技术,为了...
  • BLE 协议栈介绍

    万次阅读 多人点赞 2016-10-11 11:33:18
    通过“蓝牙协议分析(2)_协议架构”的介绍,大家对蓝牙协议栈应该有了简单的了解,但是,肯定还有“似懂非懂、欲说还休”的感觉。有这种感觉太正常了,毕竟蓝牙协议是一个历史悠久又比较庞大的协议,没那么容易理解。...
  • BR\EDR核心层controller中Baseband Conformance协议栈测试截图 BR\EDR核心层controller中Link Manager的协议栈测试截图 BLE核心层controller中Link Layer协议栈测试截图 (5)审核和产品宣告 Review &Product ...
  • 蓝牙BLE协议栈解析

    2019-04-28 08:59:04
    蓝牙BLE协议栈解析
  • 本文代码基于linux3.14  Vlan即虚拟局域网,一个vlan能够模拟一个常规的交换网络,实现了将一个物理的交换机划分成...而不同的vlan之间如果要进行通信就要通过三层协议来实现。  在linux中vlan的配置使用vconfig
  • 我对协议栈设计和架构的理解 转自:http://blog.csdn.net/findaway123/article/details/18097273 转载于:http://www.52rd.com/bbs/Archive_Thread.asp?SID=54542&TID=2 因为工作的关系,有幸接触到...
  • 1.4 蓝牙芯片方案的实现 结合蓝牙协议栈的内容,配合上面的推荐文章《三种蓝牙架构实现方案(蓝牙协议栈方案)》,我们可以来说明一下,一般厂家蓝牙方案是怎么设计的: 对于BR/EDR 蓝牙设备类型,Controller 通常...
  • BR 基本速率 EDR 增强数据速率 同时支持BLE和BR / EDR的设备称为双模式设备。 通常,除非另有特别说明,否则在蓝牙生态系统内部,移动电话或便携式计算机被视为双模式设备。 仅支持BLE的设备称为单模设备。 单模...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,298
精华内容 1,319
关键字:

br 协议栈架构