LWIP学习笔记-链路层

网络接口


运行LWIP协议栈的嵌入式设备有多个网络接口,接口类型是各不相同,如以太网接口、串行链路接口等。为实现对所有接口进行有效管理,协议栈内部用一个netif的网络接口结构描述各个网络设。内核将所有网络接口的netif结构组织在一个叫做netif_list的链表上。当IP发送数据时,IP层会根据数据包的目的地址,在链表上选一个最合适的网络接口,并调用注册的数据包发送函数将数据发送出去;当接收数据包时,注册的输入函数被调用,将数据包递交给IP层。
网络接口旨在堆具体的网络硬件、软件进行统一的封装,并为协议栈IP层提供统一的接口服务。

数据结构

struct netif {
  /** pointer to next in linked list */
  struct netif *next;

  /** IP address configuration in network byte order */
  ip_addr_t ip_addr;
  ip_addr_t netmask;
  ip_addr_t gw;

  /** This function is called by the network device driver
   *  to pass a packet up the TCP/IP stack. */
  netif_input_fn input;
  /** This function is called by the IP module when it wants
   *  to send a packet on the interface. This function typically
   *  first resolves the hardware address, then sends the packet. */
  netif_output_fn output;
  /** This function is called by the ARP module when it wants
   *  to send a packet on the interface. This function outputs
   *  the pbuf as-is on the link medium. */
  netif_linkoutput_fn linkoutput;
  /** maximum transfer unit (in bytes) */
  u16_t mtu;
  /** number of bytes used in hwaddr */
  u8_t hwaddr_len;
  /** link level hardware address of this interface */
  u8_t hwaddr[NETIF_MAX_HWADDR_LEN];
  /** flags (see NETIF_FLAG_ above) */
  u8_t flags;
  /** descriptive abbreviation */
  char name[2];
  /** number of this interface */
  u8_t num;
#if LWIP_NETIF_HWADDRHINT
  u8_t *addr_hint;
#endif /* LWIP_NETIF_HWADDRHINT */
#if ENABLE_LOOPBACK
  /* List of packets to be queued for ourselves. */
  struct pbuf *loop_first;
  struct pbuf *loop_last;
#if LWIP_LOOPBACK_MAX_PBUFS
  u16_t loop_cnt_current;
#endif /* LWIP_LOOPBACK_MAX_PBUFS */
#endif /* ENABLE_LOOPBACK */
};

上面的源码不是完整的,把一些协议类数据结构省略了,比如SNMP、IGMP等。

next是指向下一个netif结构的指针,一个给设备可能会有多个网络接口及(路由器),LWIP会把所有网络接口的netif结构组成一个链表进行管理;
ip_addr、netmask、gw三个字段用于描述网络接口的网络地址属性,分别是IP地址、子网掩码和网关地址;
iput是一个函数指针,函数功能是将网络设备接收对的数据包提交给IP层,函数的输入参数分别是pbuf(待提交的数据包)、另一个为netif类型(网络设备);
output是一个函数指针,与具体网络接口设备驱动密切相关,功能是将IP层发送数据包到目的地址;
linkoutput和output功能相似,只是更加底层了,主要在以太网卡中被ARP模块中调用,完成以太网数据帧的发送;
state用于记录设备信息;
hwaddr_len和hwaddr[]表示网卡的物理地址长度和具体MAC地址信息;
mtu表示网络接口可传达的最大数据包长度,一般设为1500;
name[]用于保存每一个网络接口的名字,在一些统计信息输出时,用它表示对应的 网络接口;

函数实现

最主要的网络接口管理函数netif_add,看看如何在系统中中注册一个网络接口设备。

struct netif * netif_add(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask,
  ip_addr_t *gw, void *state, netif_init_fn init, netif_input_fn input)
{
  static u8_t netifnum = 0;
  /* reset new interface configuration state */
  ip_addr_set_zero(&netif->ip_addr);
  ip_addr_set_zero(&netif->netmask);
  ip_addr_set_zero(&netif->gw);
  netif->flags = 0;
  /* remember netif specific state information data */
  netif->state = state;
  netif->num = netifnum++;
  netif->input = input;
  netif_set_addr(netif, ipaddr, netmask, gw);
  /* call user specified initialization function for netif */
  if (init(netif) != ERR_OK) {
    return NULL;
  }
  /* add this netif to the list */
  netif->next = netif_list;
  netif_list = netif;
  return netif;
}

netif_add函数功能是注册网络接口,同时将网络接口加入到接口链表中。

上一篇:Django 序列化中的局部钩子和全局钩子


下一篇:parseaddr函数和formataddr函数的用法