lwip总体架构

lwipopts.h 就是用于配置 LwIP 的相关参数的
LwIP 默认会有参数的配置,存放在 opt.h 文件中

第一步是通过 netif_add() 函数将我们的网卡挂载到 netif_list链表上

与网卡驱动密切相关的函数有三个

//low_level_init() 为网卡初始化函数
static void low_level_init(struct netif *netif);
//low_level_output() 函数为网卡的发送函数,它主要将内核的数据包发送出去
static err_t low_level_output(struct netif *netif, struct pbuf *p);
//low_level_input() 函数为网卡的数据接收函数
static struct pbuf * low_level_input(struct netif *netif);
err_t ethernetif_init(struct netif *netif);
void ethernetif_input(void *pParams);

让协议栈内核与操作系统相互隔离,协议栈仅仅作为操作系统的一个独立线程存在
回调函数–》RAW API 编程
操作系统 IPC 通信机制—》NETCONN API 和 Socket API

pbuf学习

struct pbuf
{
    
    
    // 指向下一个 pbuf
    struct pbuf *next; (1)
    //指向数据区域的指针
    void *payload; (2)
    // 当前 pbuf 及其后续 pbuf 所有数据的长度
    u16_t tot_len; (3)
    // 当前 pbuf 中有效的数据长度
    u16_t len; (4)
    // pbuf 的类型 PBUF_RAM、PBUF_POOL 、PBUF_ROM、PBUF_REF
    u8_t type_internal; (5)
    /** misc flags */
    u8_t flags; (6)
    // 该 pbuf 被引用的次数
    LWIP_PBUF_REF_T ref; (7)
    // netif 的索引 那个网卡的数据
    u8_t if_idx; (8)
};

  • PBUF_RAM 类型的 pbuf 空间是通过内存堆分配而来的,申请的时候包含了协议首部
    *

  • PBUF_POOL 类型的 pbuf 与 PBUF_RAM 类型的 pbuf 都是差不多的,是通过内存池分配的,接收数据的时候用,只有第一个 pbuf 是有 layer 字段的,用于存放协议头部在这里插入图片描述*PBUF_ROM 和 PBUF_REF 类型的 pbuf 基本是一样的,它们在内存池申请的 pbuf 不包含数据区域,只包含 pbuf 结构体在这里插入图片描述

#define PBUF_TRANSPORT_HLEN 20
#define PBUF_IP_HLEN 20
typedef enum
{
    
    
//传输层协议首部内存空间,如 UDP、TCP 报文协议首部
PBUF_TRANSPORT = PBUF_LINK_ENCAPSULATION_HLEN +PBUF_LINK_HLEN + PBUF_IP_HLEN +PBUF_TRANSPORT_HLEN,
//网络层协议首部内存空间,如 IP 协议
PBUF_IP = PBUF_LINK_ENCAPSULATION_HLEN +PBUF_LINK_HLEN + PBUF_IP_HLEN, (2)
//链路层协议首部内存空间,如以太网
PBUF_LINK = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN, (3)
//原始层,不预留空间
PBUF_RAW_TX = PBUF_LINK_ENCAPSULATION_HLEN, (4)
//原始层,不预留空间
PBUF_RAW = 0 (5)
} pbuf_layer;

pbuf分配

struct pbuf *
pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
  1. pbuf_free() 内部引用技术为0时才会真正的释放内存
  2. pbuf_header() 函数用于调整 pbuf 的 payload 指针
  3. pbuf_take() 函数用于向 pbuf 的数据区域拷贝数据。
  4. pbuf_copy() 函数用于将一个任何类型的 pbuf中的数据拷贝到一个 PBUF_RAM 类型的 pbuf 中。
  5. pbuf_chain() 函数用于连接两个 pbuf(链表)为一个 pbuf 链表。pbuf_ref 函数用于将 pbuf 中的值加 1

lwip 数据处理流程

在这里插入图片描述

  1. ARP 缓存表项的时间管理
  2. IP 分片数据报的重装等待超时
  3. TCP 中的建立连接超时
  4. 重传超时机制
typedef void (* sys_timeout_handler)(void *arg);
struct sys_timeo
{
    
    
//超时链表的连接
struct sys_timeo *next; (1)
//的等待时间
u32_t time; (2)
//回调函数
sys_timeout_handler h; (3)
//传入参数
void *arg; (4)
};
//第一个超时事件
static struct sys_timeo *next_timeout; (5)

消息


enum tcpip_msg_type
{
    
    
  TCPIP_MSG_API,
  TCPIP_MSG_API_CALL,  //API 函数调用
  TCPIP_MSG_INPKT,     //底层数据包输入
  TCPIP_MSG_TIMEOUT,   //注册超时事件
  TCPIP_MSG_UNTIMEOUT, //删除超时事件
  TCPIP_MSG_CALLBACK,
  TCPIP_MSG_CALLBACK_STATIC //执行回调函数
};
struct tcpip_msg
{
    
    
  enum tcpip_msg_type type;
 //共用体内部的不同结构体对应 tcpip_msg_type  的不同消息
  union
  {
    
    
    struct
    {
    
    
      tcpip_callback_fn function;//回调函数
      void *msg;//回调函数参数
    } api_msg;
    struct
    {
    
    
      tcpip_api_call_fn function;//api 回调函数
      struct tcpip_api_call_data *arg;//回调函数参数
      sys_sem_t *sem;
    } api_call;
    struct
    {
    
    
      struct pbuf *p;//存放数据的pbuf
      struct netif *netif;//代处理数据的网卡
      netif_input_fn input_fn;//待处理数的函数指针,ARP处理函数还是,ip数据处理函数
    } inp;
    struct
    {
    
    
      tcpip_callback_fn function;
      void *ctx;
    } cb;
    struct
    {
    
    
      u32_t msecs;//超时时间
      sys_timeout_handler h;//超时处理函数
      void *arg;//函数参数
    } tmo;

  } msg;
};

API 消息的处理方式

用户层构建一个api消息通过发送邮箱的方式投递给内核,用户线程就等待(信号量)内核处理完成以后,就返回。
在这里插入图片描述

以太网的帧结构

在这里插入图片描述

Guess you like

Origin blog.csdn.net/u010261063/article/details/121294096