lwip协议之底层硬件数据交互

lwip协议之底层硬件数据交互

点对点数据在网络中传输,在不同系统中,如何保证数据传输的可靠性,可识别性,那就必须存在相应的标准,不论接收方,还是发送方,严格按照标准封装或者解封装数据,在网络中传输后,才能够正确有效的将数据提取出来,这个就依赖于tcpip协议,那么出来tcpip协议最底层的数据链路层是如何完成数据的收发呢?这里介绍下lwip链路层上网卡设备如何实现数据包的发送与接收。

在数据链路层,lwip源码中通过一个结构体netif来描述设备的网卡,结构体源码(部分成员,也是主要成员,网卡初始化不可缺少的)如下:

struct netif {
  /** pointer to next in linked list */
  struct netif *next;   //连接netif_list链表

#if LWIP_IPV4      //基于ipv4的互联网协议
  /** IP address configuration in network byte order */
  ip4_addr_t ip_addr;    // 网卡IP地址
  ip4_addr_t netmask;    // 子网掩码
  ip4_addr_t gw;         // 网关
#endif /* LWIP_IPV4 */
#if LWIP_IPV6       //基于ipv6的互联网协议
  /** Array of IPv6 addresses for this netif. */
  ip6_addr_t ip6_addr[LWIP_IPV6_NUM_ADDRESSES];
  /** The state of each IPv6 address (Tentative, Preferred, etc).
   * @see ip6_addr.h */
  u8_t ip6_addr_state[LWIP_IPV6_NUM_ADDRESSES];
#endif /* LWIP_IPV6 */
  /** This function is called by the network device driver
   *  to pass a packet up the TCP/IP stack. */
  netif_input_fn input;    //从网卡接口提取数据包送往tcpip协议栈
#if LWIP_IPV4
  /** 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;   //从ip层发送数据包到网络接口
#endif /* LWIP_IPV4 */
  /** 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;  //从arp层发送数据包到网络接口
  。。。
  /** maximum transfer unit (in bytes) */
  u16_t mtu;    //最大转发字节数,数据包最大长度
  /** number of bytes used in hwaddr */
  u8_t hwaddr_len;   //mac地址长度
  /** link level hardware address of this interface */
  u8_t hwaddr[NETIF_MAX_HWADDR_LEN];    //mac地址
  /** flags (see NETIF_FLAG_ above) */
  u8_t flags;     //网卡的功能定义
  /** descriptive abbreviation */
  char name[2];   //网卡的名字
  /** number of this interface */
  u8_t num;
  。。。
};

介绍完netif结构体成员,现在我们回到,lwip初始化上分析下netif_add函数(主要是对netif结构体的初始化,添加到netif_list)。
netif_add(&sta_if, sta_ip_addr, sta_net_mask, sta_gw, NULL, ethernetif_init1, tcpip_input);

struct netif *
netif_add(struct netif *netif,
#if LWIP_IPV4
          const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw,
#endif /* LWIP_IPV4 */
          void *state, netif_init_fn init, netif_input_fn input)
{
#if LWIP_IPV6
  u32_t i;
#endif

  LWIP_ASSERT("No init function given", init != NULL);

  /* reset new interface configuration state */
#if LWIP_IPV4
  ip4_addr_set_zero(&netif->ip_addr);
  ip4_addr_set_zero(&netif->netmask);
  ip4_addr_set_zero(&netif->gw);
#endif /* LWIP_IPV4 */    //复位网卡的各个参数值

#if LWIP_IPV6
  for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
    ip6_addr_set_zero(&netif->ip6_addr[i]);
    netif_ip6_addr_set_state(netif, i, IP6_ADDR_INVALID);
  }
  netif->output_ip6 = netif_null_output_ip6;
#endif /* LWIP_IPV6 */
  netif->flags = 0;   //使能网卡的功能
#if LWIP_DHCP
  /* netif not under DHCP control by default */
  netif->dhcp = NULL;
#endif /* LWIP_DHCP */
#if LWIP_AUTOIP
  /* netif not under AutoIP control by default */
  netif->autoip = NULL;
#endif /* LWIP_AUTOIP */
#if LWIP_IPV6_AUTOCONFIG
  /* IPv6 address autoconfiguration not enabled by default */
  netif->ip6_autoconfig_enabled = IPV6_AUTOCONFIG_DISENABLED;
#endif /* LWIP_IPV6_AUTOCONFIG */
#if LWIP_IPV6_SEND_ROUTER_SOLICIT
  netif->rs_count = LWIP_ND6_MAX_MULTICAST_SOLICIT;
  netif->rs_interval = LWIP_ND6_PTR_SOLICITATION_INTERVAL;
#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */
#if LWIP_IPV6_DHCP6
  /* netif not under DHCPv6 control by default */
  netif->dhcp6 = NULL;
#endif /* LWIP_IPV6_DHCP6 */
#if LWIP_NETIF_STATUS_CALLBACK
  netif->status_callback = NULL;
  netif->wifi_callback = NULL;
#endif /* LWIP_NETIF_STATUS_CALLBACK */
#if LWIP_NETIF_LINK_CALLBACK
  netif->link_callback = NULL;
#endif /* LWIP_NETIF_LINK_CALLBACK */
#if LWIP_IGMP
  netif->igmp_mac_filter = NULL;
#endif /* LWIP_IGMP */
#if LWIP_IPV6 && LWIP_IPV6_MLD
  netif->mld_mac_filter = NULL;
#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
#if ENABLE_LOOPBACK
  netif->loop_first = NULL;
  netif->loop_last = NULL;
#endif /* ENABLE_LOOPBACK */

  /* remember netif specific state information data */
  netif->state = state;
  netif->num = netif_num++;
  netif->input = input;   //给input函数赋值,netif结构体中有描述
  NETIF_SET_HWADDRHINT(netif, NULL);
#if ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS
  netif->loop_cnt_current = 0;
#endif /* ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS */

#if LWIP_IPV4
  netif_set_addr(netif, ipaddr, netmask, gw);   //设置网卡的参数
#endif /* LWIP_IPV4 */

  /* call user specified initialization function for netif */
  if (init(netif) != ERR_OK) {     //init(netif),主要函数传参,网卡的初始化函数被执行,下文解析
    return NULL;
  }

  /* add this netif to the list */    //将网卡加入到netif_list链表
  netif->next = netif_list;
  netif_list = netif;
  snmp_inc_iflist();

#if LWIP_IGMP
  /* start IGMP processing */
  if (netif->flags & NETIF_FLAG_IGMP) {
    igmp_start(netif);
  }
#endif /* LWIP_IGMP */

  LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP",
    netif->name[0], netif->name[1]));
#if LWIP_IPV4
  LWIP_DEBUGF(NETIF_DEBUG, (" addr "));
  ip4_addr_debug_print(NETIF_DEBUG, ipaddr);
  LWIP_DEBUGF(NETIF_DEBUG, (" netmask "));
  ip4_addr_debug_print(NETIF_DEBUG, netmask);
  LWIP_DEBUGF(NETIF_DEBUG, (" gw "));
  ip4_addr_debug_print(NETIF_DEBUG, gw);
#endif /* LWIP_IPV4 */
  LWIP_DEBUGF(NETIF_DEBUG, ("\n"));
  return netif;
}

下面解析下网卡初始化函数ethernetif_init1

err_t
ethernetif_init1(struct netif *netif)
{
  struct ethernetif *ethernetif;

  LWIP_ASSERT("netif != NULL", (netif != NULL));

  ethernetif = mem_malloc(sizeof(struct ethernetif));
  if (ethernetif == NULL) {
    LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n"));
    return ERR_MEM;
  }

#if LWIP_NETIF_HOSTNAME
  /* Initialize interface hostname */
  netif->hostname = "lwip";
#endif /* LWIP_NETIF_HOSTNAME */

  /*
   * Initialize the snmp variables and counters inside the struct netif.
   * The last argument should be replaced with your link speed, in units
   * of bits per second.
   */
  NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS);

  netif->state = ethernetif;
  netif->name[0] = IFNAME00;
  netif->name[1] = IFNAME01;
  /* We directly use etharp_output() here to save a function call.
   * You can instead declare your own function an call etharp_output()
   * from it if you have to do some checks before sending (e.g. if link
   * is available...) */
  netif->output = etharp_output;   //走ip层数据包,将ip层数据发送到网络接口
  #if LWIP_IPV6
  netif->output_ip6 = ethip6_output;
  #endif /* LWIP_IPV6 */
  netif->linkoutput = (netif_linkoutput_fn)low_level_output_scatter;  //走的arp层数据包,将arp层数据发送到网络接口

  ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);

  /* initialize the hardware */
  low_level_init1(netif);   //初始化硬件接口函数

#if 0
  /* Create a task that simulates an interrupt in a real system.  This will
  block waiting for packets, then send a message to the uIP task when data
  is available. */

  LOG_I(lwip, "Create RX task\n\r");
  xTaskCreate(InterruptSimulator, "RX", 400, (void *)netif, 3, NULL );
#endif
  return ERR_OK;
}

由此可以看出,lwip协议在底层通过一个netif结构体对网卡进行管理,多网卡就产生一个网卡链表,网卡的数据通过 netif->input,netif->output,netif->linkoutput函数指针,完成与ip层或arp层的数据交互。
在这里插入图片描述
netif->output最底层还是得调用netif->linkoutput接口发送数据包,两者区别在于知不知道目的mac地址,如果知道目的mac地址,就能直接调用netif->linkoutput把数据交给网卡,如果不知道,则需要走arp层,通过arp协议先找到目的mac地址才能够将数据传输出去。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值