lwip网络协议基础介绍

lwip网络协议基础介绍

  • lwip网络接口
    • lwip的网络接口结构
    • lwip的网络接口相关函数
  • lwip网络数据包
    • lwip网络数据包结构
    • lwip网络数据包函数

lwip网络接口

lwip协议栈支持多种不同的网络接口,比如WiFi、以太网、4G等等,由于网卡是直接和硬件平台打交道,硬件不同则处理也是不同的,所以由用户提供最底层的接口函数,lwip提供统一的接口,但是底层的实现需要用户自己去完成,比如以太网的MAC接口,WiFi的RF接口等。

lwip的网络接口结构

lwip中的每一个网卡都由一个netif结构体表示,netif声明多个成员变量,这些变量是对网卡进行抽象,可以有多个网卡,多个网卡的存储为单向链表形式。用户需要实现网络的底层接口,例如数据input以及output等。

/** 以下是netif结构体的部分说明
 *  成员变量需要根据网卡特性,针对赋值 */
struct netif {
#if !LWIP_SINGLE_NETIF
  /** 指向下一个网卡的指针 */
  struct netif *next;
#endif

#if LWIP_IPV4
  /** IPv4的地址设置 */
  ip_addr_t ip_addr;
  ip_addr_t netmask;
  ip_addr_t gw;
#endif /* LWIP_IPV4 */

#if LWIP_IPV6
  /** IPv6的地址设置 */
  ip_addr_t ip6_addr[LWIP_IPV6_NUM_ADDRESSES];
  u8_t ip6_addr_state[LWIP_IPV6_NUM_ADDRESSES];
#if LWIP_IPV6_ADDRESS_LIFETIMES
  u32_t ip6_addr_valid_life[LWIP_IPV6_NUM_ADDRESSES];
  u32_t ip6_addr_pref_life[LWIP_IPV6_NUM_ADDRESSES];
#endif /* LWIP_IPV6_ADDRESS_LIFETIMES */
#endif /* LWIP_IPV6 */

  /** 网络数据的输入函数,由网络设备驱动调用并上传到TCP/IP堆栈 */
  netif_input_fn input;
#if LWIP_IPV4
  /** 网络数据待发送函数,由TCP/IP调用,包含检测目标IP地址的MAC地址等操作*/
  netif_output_fn output;
#endif /* LWIP_IPV4 */
  /** 网络数据的输出函数*/
  netif_linkoutput_fn linkoutput;
#if LWIP_IPV6
  /** 针对IPv6地址的网络数据待发送函数*/
  netif_output_ip6_fn output_ip6;
#endif /* LWIP_IPV6 */

#if LWIP_NETIF_STATUS_CALLBACK
  /** 网络状态回调函数 */
  netif_status_callback_fn status_callback;
#endif /* LWIP_NETIF_STATUS_CALLBACK */

#if LWIP_NETIF_LINK_CALLBACK
  /** 网卡链接状态回调函数 */
  netif_status_callback_fn link_callback;
#endif /* LWIP_NETIF_LINK_CALLBACK */

#if LWIP_NETIF_REMOVE_CALLBACK
  /** 网卡移除回调函数 */
  netif_status_callback_fn remove_callback;
#endif /* LWIP_NETIF_REMOVE_CALLBACK */

  /** 网卡状态 */
  void *state;

#if LWIP_NETIF_HOSTNAME
  /* 网卡主机名称,不能为NULL */
  const char*  hostname;
#endif /* LWIP_NETIF_HOSTNAME */

#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF*/
  /** 最大传输单元,最大为1500*/
  u16_t mtu;
  
#if LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES
  /** IPv6最大传输单元,最大为1500 */
  u16_t mtu6;
#endif /* LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES */

  /** 网卡的MAC地址 */
  u8_t hwaddr[NETIF_MAX_HWADDR_LEN];
  /** 网卡的MAC地址长度 */
  u8_t hwaddr_len;
  /**网卡标志符 */
  u8_t flags;
  /** 网卡名称 */
  char name[2];
  	........
};

lwip的网络接口相关函数

函数 功能
netif_init(void) 虚拟网卡初始化 ,调用netif_add添加默认网卡
netif_add() 添加一个虚拟网卡,配置netif结构体成员变量,将网卡加入到网卡链表
netif_remove() 移除一个虚拟网卡,将网卡从网卡链表中删除
netif_set_default() 设置默认虚拟网卡

具体函数源码可以参考lwip中的netif.c
源码下载可以点击文章底部链接

lwip网络数据包

TCP/IP协议栈的实现本质上就是对网络数据包进行封装,解析。在lwip中,使用pbuf结构进行数据包的管理。

lwip网络数据包结构

lwip网络数据包是由一个个pbuf组成的单向链表。pbuf在TCP/IP各层之间传递数据,每经过一层,都会增加响应的头部,因此在申请pbuf时会把头部的空间也一起申请。但是初始化时指针是指向payload的,在调用pbuf_header()添加头部信息时,指针会向上偏移。图中offset即是预留的头部空间lwip网络协议基础介绍_第1张图片

struct pbuf {
  /** 指向下一个pbuf */
  struct pbuf *next;

  /** 数据buffer */
  void *payload;

  /** 所有pubuf总长度*/
  u16_t tot_len;

  /** 当前pbuf的长度 */
  u16_t len;

  /** pbuf类型,4个*/
  u8_t type_internal;

  /** 引用计数 */
  LWIP_PBUF_REF_T ref;
  ...
};

lwip网络数据包函数

函数 功能
pbuf_alloc() 根据类型申请pbuf内存
pbuf_free() 释放pbuf内存
pbuf_header() 添加协议包头,本质上是调整payload指针向上偏移

具体函数源码可以参考lwip中的pbuf.c
源码下载可以点击文章底部链接

学习笔记,有问题欢迎指出
lwip官方源码:http://git.savannah.gnu.org/cgit/lwip.git

你可能感兴趣的:(网络协议,arm开发,网络)