lwIP TCP/IP 协议栈笔记之一:概述和目录结构详解

22 篇文章 1 订阅
21 篇文章 58 订阅

目录

1. lwIP概述

1.1 TCP/IP 协议简介

1.2 lwIP 简介

1.2.1 目录结构 lwip-2.1.2

1.2.2 lwip-2.1.2/src

2 目录结构详解

2.1 /doc

2.2 /test

2.3 /src

2.3.1 APIs

2.3.2 /src/api

2.3.3 /src/apps

2.3.4 /src/core

2.3.5 /src/include

2.3.6 /src/netif


1. lwIP概述

1.1 TCP/IP 协议简介

TCP/IP协议(传输控制协议/互联网协议)不是简单的一个协议,而是一组特别的协议,包括:TCP,IP,UDP,ARP等,这些被称为子协议。在这些协议中,最重要、最著名的就是TCP和IP。因此,大部分网络管理员称整个协议族为“TCP/IP”。

国际标准组织将整个以太网通信结构制定了OSI模型,总共分层七个层,分别为应用层、表示层、会话层、传输层、网络层、数据链路层以及物理层,每个层功能不同,通信中各司其职,整个模型包括硬件和软件定义。OSI模型是理想分层,一般的网络系统只是涉及其中几层。

TCP/IP是互联网最基本的协议,是互联网通信使用的网络协议,由网络层的IP协议和传输层的TCP协议组成。TCP/IP只有四个分层,分别为应用层、传输层、网络层以及网络访问层。虽然TCP/IP分层少了,但与OSI模型是不冲突的,它把OSI模型一些层次整合一起的,本质上可以实现相同功能。

 实际上,还有一个TCP/IP混合模型,分为五个层,参考下图 ,它实际与TCP/IP四层模型是相通的,只是把网络访问层拆成数据链路层和物理层。这种分层方法对我们学习理解更容易。

设计网络时,为了降低网络设计的复杂性,对组成网络的硬件、软件进行封装、分层,这些分层即构成了网络体系模型。在两个设备相同层之间的对话、通信约定,构成了层级协议。设备中使用的所有协议加起来统称协议栈。在这个网络模型中,每一层完成不同的 任务,都提供接口供上一层访问。而在每层的内部,可以使用不同的方式来实现接口,因而内部的改变不会影响其它层。

在TCP/IP混合参考模型中,数据链路层又被分为LLC层(逻辑链路层)和MAC层(媒体介质访问层)。目前,对于普通的接入网络终端的设备, LLC层和MAC层是软、硬件的分界线。

1.2 lwIP 简介

lwIP(A Lightweight TCP/IP stack)是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。LwIP是Light Weight (轻型)IP协议,有无操作系统的支持都可以运行。LwIP实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用,它只需十几KB的RAM和40K左右的ROM就可以运行。这样就可以让lwIP适用于资源有限的小型平台例如嵌入式系统。

目前 lwIP 最新版本 2.1.2

官网:http://savannah.nongnu.org/projects/lwip/

官方下载地址:http://download.savannah.nongnu.org/releases/lwip/

lwIP 主要特性:

  •   *IP(Internet协议,IPv4和IPv6),包括通过多个网络接口的数据包转发
  •   ICMP 用于网络维护和调试(Internet控制消息协议)
  •   IGMP 用于多播流量管理(因特网组管理协议)
  •   *MLD(IPv6的多播侦听器发现)。旨在符合RFC 2710.不支持MLDv2
  •   ND(IPv6的邻居发现和无状态地址自动配置)。旨在符合RFC 4861(邻居发现)和RFC 4862(地址自动配置)
  •   DHCP,AutoIP / APIPA(Zeroconf)和(无状态)DHCPv6
  •   UDP(用户数据报协议),包括UDP-lite扩展
  •    TCP(传输控制协议)具有拥塞控制,RTT估计快速恢复/快速重传和发送SACK
  •   RAW/NATIVE API以提高性能
  •   可选的Berkeley-socket API
  •    TLS:可选的分层TCP(“altcp”),用于任何基于TCP的协议(移植到mbedTLS)的近乎透明的TLS(有关详细信息,请参阅changelog)
  •    PPPoS和PPPoE(串口/以太网上的点对点协议)
  •   DNS(域名解析器,包括mDNS)
  •   6LoWPAN(通过IEEE 802.15.4,BLE或ZEP)

1.2.1 目录结构 lwip-2.1.2

下载并解压,目录结构如下:

 

src/      -  lwIP TCP/IP 协议栈 源码.

doc/      -  lwIP 文档.

双击打开,既可以查看相关文档

test/      -  测试相关

1.2.2 lwip-2.1.2/src

  • api/        -  高级封装 API 的代码。如果您使用低级 回调/raw API ,则不需要。

  • apps/     - 使用lwIP低级Raw API专门编程的高层应用程序。

  • core/      - TCP/IP协议栈核心:协议实现,内存和缓冲区管理以及低级Raw API。

  • include/  - lwIP include files.

  • netif/      - 通用网络接口设备驱动程序保存在此处。

 

2 目录结构详解

2.1 /doc

lwIP 相关文档,简单描述一下.其中rawapi.txt 和 sys_arch.txt 描述了相关功能使用,需要的话可以去下载相应版本,2.1.2版本中已经被去除了。

├─doc
│  │  contrib.txt	// LwIP作为开源软件,如果想要为其做贡献,则需要遵循一定的准则,例如:提交代码的风格、报告Bug等。该文档给出了详细的贡献准则。
│  │  doxygen_docs.zip	// 用doxygen生成的LwIP的配套文档
│  │  FILES			// 其中说明了该目录下的每个文件的用途
│  │  mdns.txt		// MDNS的说明文档
│  │  mqtt_client.txt // MQTT 
│  │  NO_SYS_SampleCode.c // 无操作系统 简单示例代码
│  │  ppp.txt		// lwIP的PPP接口文档
│  │  savannah.txt	// 说明了如何获取当前的开发源代码
│  │  ZeroCopyRx.c  // 示例代码
│  │  *rawapi.txt	// 参照2.0.3 使用说明,协议栈的Raw/Callback API进行编程
│  │  *sys_arch.txt // 参照2.0.3 在有操作系统的移植的时候会被使用到,包含了移植说明,规定了移植者需要实现的函数、宏定义等,后面有详细说明。
│  └─doxygen		// doxygen脚本,主要用来维护LwIP的配套文档。对于使用LwIP来说用不到
│      │  generate.bat
│      │  generate.sh
│      │  lwip.Doxyfile
│      │  main_page.h
│      └─output

 

2.2 /test

协议栈内核测试程序.在实际使用时一般用不到!可直接删除

2.3 /src

lwIP 最新源码 相对之前的版本有不小的调整,着重说明该部分

2.3.1 APIs

须知,lwIP为程序提供三个应用程序接口(API),用于与TCP / IP代码进行通信:

  • low-level "core" / "callback" or "raw" APIs.
  • higher-level Sequential-style APIs.
  • BSD-style Socket API.

Raw TCP / IP接口允许应用程序更好地与TCP / IP代码集成。程序执行是基于事件的,通过从TCP / IP代码中调用回调函数。 TCP / IP代码和应用程​​序都在同一个线程中运行。sequential API具有更高的开销,并且不太适合小型系统,因为它强制应用程序上的多线程范例.

Raw TCP / IP接口不仅在代码执行时间方面更快,而且内存密集程度也更低。缺点是程序开发有点困难,为原始TCP / IP接口编写的应用程序更难以理解。尽管如此,这是编写代码大小和内存使用量较小的应用程序的首选方法。

所有API可以由不同的应用程序同时使用。事实上,sequential API 是使用 Raw TCP / IP 接口实现的应用程序。

不要将lwIP Raw API与 Raw 以太网或IP套接字混淆。前者是连接lwIP网络堆栈(包括TCP和UDP)的一种方式,后者是指处理Raw 以太网或IP数据而不是TCP连接或UDP数据包。

Raw API应用程序可能永远不会阻塞,因为所有数据包处理(输入和输出)以及定时器处理(主要是TCP)都是在单个执行上下文中完成的。

  • RAW API

非线程安全的API,callback style,可实现最高性能和最小内存占用。程序执行由回调函数驱动,然后当与该应用程序相关的活动发生时,由 lwIP 核心调用。特定应用程序可以注册以通过回调函数通知诸如可用的传入数据,发送的传出数据,错误通知,轮询计时器到期,连接关闭等事件。应用程序可以提供回调函数以执行任何或所有的处理这些事件。每个回调都是从TCP/IP代码中调用的普通C函数。每个回调函数都作为参数传递当前的TCP或UDP连接状态。此外,为了能够保持程序特定状态,使用独立于 TCP/IP 状态的程序指定参数调用回调函数。Raw API(有时称为Native API)是一种事件驱动的API,旨在在没有实现零拷贝发送和接收的操作系统的情况下使用。核心堆栈还使用此API进行各种协议之间的交互。它是在没有操作系统的情况下运行lwIP时唯一可用的API.

上文提到的 rawapi.txt 说明了具体如何使用Raw API。

  • Sequential-style APIs

Netconn API  和 NETIF API

Sequential API,阻塞功能。 更多开销,但可以从除TCPIP线程之外的任何线程调用。 Sequential API为普通的顺序程序提供了一种使用lwIP堆栈的方法。 它与BSD套接字API非常相似。 执行模型基于阻塞 打开 - 读取 - 写入 - 关闭 范例。 由于TCP / IP堆栈本质上是基于事件的,因此TCP/IP代码和应用程序必须驻留在不同的执行上下文(线程)中。

Netconn API: 线程安全,仅从非TCPIP线程调用。 基于网络缓冲区(包含数据包缓冲区(PBUF))的TX / RX处理,以避免复制数据。

NETIF API: 从非TCPIP线程调用的线程安全函数

  • BSD-style Socket API

BSD类型的套接字API。线程安全,仅从非TCPIP线程调用。可以通过将LWIP_SOCKET定义为1来激活。头文件位于posix / sys / socket.h中。套接字API是现有应用程序的兼容性API,目前它是基于顺序API构建的。 它旨在提供运行在其他平台(例如unix / windows等)上运行的套接字API应用程序所需的所有功能。 但是,由于此API规范的限制,可能存在不兼容性,需要对现有程序进行少量修改。

2.3.2 /src/api

高级封装 API 的代码。如果使用低级回调/raw API ,则不需要。

  • api_lib.c

包含 对外提供的 sequential API 函数的实现。函数名均以netconn_开头。主要分为三组API:同时可用于TCP和UDP的API、只能用于TCP的API、只能用于UDP的API

  • api_msg.c

包含sequential API内部自己调用的函数的实现。主要包含API消息的封装和处理函数

  • err.c

错误管理模块

  • if_api.c

接口识别,IPv6的基本套接字接口扩展

  • netbuf.c

网络缓冲管理,包含了上层数据包管理函数的实现。应用程序描述待发送数据和已接收数据的基本结构。该结构只是对内核 pbuf 的简单封装,避免了数据的拷贝。缓冲区不能在多个线程之间共享。

  • netdb.c

包含与主机名字转换相关的函数,主要在 socket 中被使用到

  • netifapi.c

上层网络接口管理函数的实现

  • sockets.c

BSD Socket API 函数的实现

  • tcpip.c

Sequential API 主线程模块, 包含了上层 API 与协议栈内核交互的函数,它是整个上层 API 功能得以实现的一个枢纽,其实现的功能可以简单理解为:从 API 函数处接收消息,然后将消息递交给内核函数,内核函数根据消息做出相应的处理

2.3.3 /src/apps

使用lwIP低级Raw API 专门编程的 高层应用程序

2.3.4 /src/core

TCP/IP协议栈核心:协议实现,内存和缓冲区管理以及低级Raw API。它包含了IP、ICMP、IGMP、TCP、UDP 等核 心协议以及建立在它们基础上的DNS、DHCP、SNMP 等上层应用协议。内核源代码可以单独运行,且不需要操作系统的支持。即:直接使用raw API编程。

  • /ipv4目录

IPv4 标准中与IP层数据包处理相关的所有代码

-- autoip.c

   lwIP TCP/IP协议栈的AutoIP实现。 它旨在符合RFC 3927

-- dhcp.c

   实现了DHCP 客户端的所有代码,DHCP 称为动态主机配置协议,DHCP 可以使计算机使用者不必为主机的IP 地址的分配问题而烦恼。DHCP 也是一个上层应 用程序, 通常 DHCP 客户端通过使用UDP提供的功能来实现与DHCP服务器的通信, 从DHCP 服务器处获得一个有效的IP 地址

-- etharp.c

   ARP(地址解析协议) 协议是以太网通信中的重要部分, 主要用来实现主机以太网物理地址到 IP 地址的映射。以太网中底层数据包的发送是基于网卡物理地址的,而不是主机的IP地址。 通过ARP协议, 主机可以发送请求, 得到邻居节点的IP 地址与物理地址等信息,为以太网数据包交互提供保证。

   功能上,ARP分为两部分。 第一部分在发送数据包时将IP地址映射到物理地址,第二部分响应来自其他机器的请求以获取我们的物理地址。

-- icmp.c

  ICMP(Internet Control Message Protocol)Internet控制报文协议。

  包含了ICMP 协议实现的相关函数,ICMP 协议为IP 数据包传递过程中的差错 报告、差错纠正以及目的地址可达性测试提供了支持,常见的Ping 命令就属于ICMP 应用的一种

-- igmp.c

   IGMP(Internet Group Management Protocol)Internet 组管理协议

  包含了网络组管理协议IGMP 的实现,IGMP 为网络中的多播数据传输提供了 支持,主机加入某个多播组后,可以接收到该组的UDP 多播数据

-- ip4.c

   包含了IPv4 协议实现的相关函数,如数据包的接收、递交、发送等

-- ip4_addr.c

   实现了几个比较简单 的IP 地址处理函数,如判断一个IP 地址是否为广播地址的函数,以及32 位IP 地址与点分十 进制地址间的转换函数等

-- ip4_frag.c

   提供了IPv4数据包分段和重组实现

  • /ipv6目录

IPv6 标准中和IP层数据包处理相关的所有代码

-- mld6.c

   IPv6的多播侦听器发现(Multicast listener discovery)。旨在符合RFC 2710。

-- nd6.c

    IPv6的邻居发现和无状态地址自动配置。 旨在符合RFC 4861(邻居发现)和RFC 4862(地址自动配置)。

其他文件与IPv4目录下的功能相同,仅是在IPv6版上的实现

  • altcp.c

altcp (application layered TCP connection API; to be used from TCPIP thread)  Application layered TCP Functions

后续补充。。。

  • altcp_alloc.c

altcp (application layered TCP connection API; to be used from TCPIP thread)  此文件包含组合多个层的分配实现。

后续补充。。。

  • altcp_tcp.c

此文件包含调用tcp的基本实现。

后续补充。。。

  • def.c

协议栈常用的功能函数,地址的转换、网络字节序与 主机字节序转换等

  • dns.c

实现了DNS 客户端的所有代码,DNS 称为域名系统.通常用户要访问某个外 部的主机时,可能只知道该主机的名字,而不知道该主机的IP 地址

  • inet_chksum.c

校验和算法的一些参考实现

  • init.c

LwIP 协议栈初始化密切相关的函数,以及一些 协议栈配置信息的检查与输出

  • ip.c

IPv4和IPv6共用的代码

  • mem.c

协议栈内存堆管理函数的实现

这是标准C库malloc()的轻量级替代品

此文件即LwIP实现的动态内存堆(Heap)分配策略

lwipopts.h使用宏值MEM_LIBC_MALLOC = 1选择使用C库自带内存分配策略

  • memp.c

协议栈内存池管理函数的实现, lwIP有许多结构的专用池(netconn,协议控制块,数据包缓冲区......)。 所有这些池都在这里管理。

(1)LwIP 支持的动态内存管理机制主要有三种:C库自带内存分配策略(malloc/free/realloc)、动态内存堆(HEAP)分配策略、动态内存池(POOL)分配策略。
(2)此文件即LwIP实现的动态内存池(POOL)分配策略
(3)默认不使用动态内存堆(HEAP)分配策略。 在lwipopts.h使用宏值MEMP_MEM_MALLOC = 1选择使用动态内存堆(HEAP)分配策略

 

  • netif.c

包含了协议栈网络接口管理的相关函数,协议栈支持多个网络接口

  • pbuf.c

包含了协议栈内核使用的数据包管理函数,数据包pbuf管理的实现是整个协议栈中很有特色的地方,采用特殊的数据包pbuf 结构,可以避免数据在各个层次之间递交时的拷贝,这既提高了数据递交效率,也节省了内存空间

  • raw.c

为应用层提供了一种直接和IP 数据包交互的方式,这类似于Socket 编程中原始套接字的概念,它同TCP、UDP 处于同一等级,享受IP 层提供的服务。使用原始套接字, 可以直接读取IP 层接收到的数据包,例如ICMP 包、UDP 包等,也可以自行构造ping包等, 为用户的程序编写提供了很大的方便。这是LwIP最底层的API部分。

  • stats.c

包含了协议栈内部数据统计与显示的相关函数,如内存使用状况、邮箱、信号量等信息

  • sys.c

实现了一个简单的函数void sys_msleep(u32_t ms);,它借助操作系统抽象层的信号量机制完成睡眠一定时间的功能,该函数主要在PPP 中使用。前面曾提到过,若需要使用协议栈的Sequential API和Socket API,则必须使用底层操作系统提供的邮箱与信号量机制,这时内核要求移植者提供一个称为sys_arch.c的操作系统模拟层文件,该文件主要完成对操作系统中邮箱与信号量函数的封装。需要注意,只有在提供文件sys_arch.c 的基础上,文件`sys.c 才有效,换句话说,在无操作系统环境下运行LwIP 时,sys.c文件都不会被编译。

  • tcp.c

包含了对TCP 控制块操作的函数,也包括了TCP 定时处理函数

  • tcp_in.c

包含了TCP 协议中数据接收、处理相关的函数,最重要的TCP 状态机函数也在这个文件中

  • tcp_out.c

含了TCP 中数据发送相关的函数,例如数据包发送函数、超时重传函数等

  • timeouts.c

统一完成了对内核各个协议定时事件处理函数的封装,同时对各个注册的定时事件进行处理。在有无操作系统模拟层的环境下,timeouts.c 采用不同的方法来实现定时:在无操作系统模拟层时,timeouts.c使用系统时钟函数sys_now(不同的平台的都需要移植该函数)来获得当前系统时间,从而可以判断出各个事件是否超时;在有操作系统模拟层时,timers.c 实现了对操作系统模拟层邮箱等待函数的再次封装,得到一个具有协议栈特色的邮箱操作函数。 所谓特色,就是在邮箱等待函数中加入一种机制,在邮箱上等待消息的同时,可以同时实现协议栈中各个定时事件的正确处理

  • udp.c

包含了实现UDP 协议的相关函数,包括UDP 控制块管理、UDP 数据包发送函数、UDP 数据包接收函数等

 

2.3.5 /src/include

  • /compat

/posix  主要是针对POSIX标准,进行的封装,里面的文件非常简单,基本都是对外部的引用。

  • /lwip

LwIP的各种头文件,其中需要注意的有opt.h 文件,它包含了所有LwIP内核参数的默认配置值;还有init.h 文件,它包含了与当前 LwIP 源代码信息相关的宏定义,如协议版本号、是否为官方版等

-- /apps

   主要是针对源码中 app目录的各头文件

-- /priv

   LwIP内部使用的头文件,禁止外部使用

-- /prot

   这个文件夹中主要是针对TCP/IP规约的各种定义。与netif文件夹中同名文件区别在于netif文件夹中的文件均为对外提供的API,本目录才是对规约层各种结构的定义。

  • /netif

主要是针对netif目录中源文件的各种头文件。

2.3.6 /src/netif

该目录下主要包含通用网络接口设备驱动程序。实现最底层的相关协议,该部分的多数源码基本与与硬件相关

  • /ppp

包含了PPP 协议实现的源代码。PPP 协议即点对点协议,它提供了 一种在点对点线路上传输多协议数据包的标准格式,PPP 协议为链路的建立、控制与认证提供 了标准。起初PPP 主要用来替代SLIP 这种简单的串行链路数据传输协议,但是由于其完整的认证机制,后来在以太网上也引入了PPP 机制,即PPPoE,它已成为近年来小区宽带拨号上网的主要方式。使用PPPoE,为用户的上网计费、配置、接入等提供了方便。LwIP 提供了对PPPoE 的支持,在ppp文件夹下的PPPoE.c文件中有相关的函数实现。

  • ethernet.c

以太网接口的共享代码。两个函数:用来从网卡接收以太网数据包的函数和在网卡上发送以太网数据包的函数

  • bridgeif.c 与 bridgeif_fdb.c

桥接相关,暂时未使用

  • lowpan6.c

6LoWPAN协议的实现文件

6LoWPAN是一种基于IPv6的低速无线个域网标准,即IPv6 over IEEE 802.15.4

  • lowpan6_ble.c

6LowPAN over BLE output for IPv6 (RFC7668).

  • lowpan6_common.c

Common 6LowPAN routines for IPv6

  • slipif.c

SLIP即串行链路IP,它提供了一种在串行链路上传送IP 数据包的函数定义。SLIP 协议比较简单,它只是定义了一系列的字符,以实现对链路上的IP数据包封装和发送,除此之外,它不提供任何寻址、错误检测、包类型识别机制,因此相关驱动程序的实现也比较简单.它需要一个sio(串行I/O)模块才能工作

开发者需要根据自己使用的串行线路特性(如串口)来实现 sio.h 中声明的函数

/* 自定义sio.c文件中实现  */
sio_fd_t sio_open(u8_t devnum);

void sio_send(u8_t c, sio_fd_t fd);

u8_t sio_recv(sio_fd_t fd);

u32_t sio_read(sio_fd_t fd, u8_t *data, u32_t len);

u32_t sio_tryread(sio_fd_t fd, u8_t *data, u32_t len);

u32_t sio_write(sio_fd_t fd, u8_t *data, u32_t len);

void sio_read_abort(sio_fd_t fd);
  • zepif.c

实现ZigBee封装协议(ZEP)的netif。

  • ethernetif.c

包含了与以太网网卡密切相关的初始化、发送、接收等函数的实现。

注意:此文件最该版本并没有被包含在源码中,需要去示例代码中拷贝,并且不能直接使用,需要开发者根据自己的需求修改。

 

 

  • 14
    点赞
  • 70
    收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:书香水墨 设计师:CSDN官方博客 返回首页
评论

打赏作者

专业游手好闲

分享知识,鼓励是一种力量!

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值