基于rt-thread+lwip源码分析-LWIP的IP层数据处理代码解析(lwip源码解析二)

LWIPIP层数据处理代码解析

继续分析rt-thread的网络接收数据部分的代码。。。。

上一章节我们介绍了数据如何从网卡接收到lwippbuf里面的,现在我们紧跟着上一章节的内容介绍下网络数据怎么交由lwip内的IP层处理数据的呢?

在上一章节中我们提到了在static void eth_rx_thread_entry(void* parameter)线程中接收网络数据的消息邮箱,然后调用struct pbuf *rt_stm32_eth_rx(rt_device_t dev)函数把数据存入到pbuf结构的链表中,后面有调用void ip_input(struct pbuf *p, struct netif *inp)函数(具体调用过程在static void eth_rx_thread_entry(void* parameter)线程里面的if( device->netif->input(p, device->netif) != ERR_OK )),这样数据就交由lwip的内核IP才去处理解析数据了,下面重点分析在IP层是怎么去处理解析数据的:

上代码:

void ip_input(struct pbuf *p, struct netif *inp) {
  struct ip_hdr *iphdr;
  struct netif *netif;
  PERF_START;
#if IP_DEBUG
  ip_debug_print(p);
#endif /* IP_DEBUG */
  IP_STATS_INC(ip.recv);
  /* identify the IP header */
  iphdr = p->payload;
  if (iphdr->v != 6) {
    LWIP_DEBUGF(IP_DEBUG, ("IP packet dropped due to bad version number\n"));
#if IP_DEBUG
    ip_debug_print(p);
#endif /* IP_DEBUG */
    pbuf_free(p);
    IP_STATS_INC(ip.err);
    IP_STATS_INC(ip.drop);
    return;
  }
  /* is this packet for us? */
  for(netif = netif_list; netif != NULL; netif = netif->next) {
#if IP_DEBUG
    LWIP_DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest "));
    ip_addr_debug_print(IP_DEBUG, ((struct ip_addr *)&(iphdr->dest)));
    LWIP_DEBUGF(IP_DEBUG, ("netif->ip_addr "));
    ip_addr_debug_print(IP_DEBUG, ((struct ip_addr *)&(iphdr->dest)));
    LWIP_DEBUGF(IP_DEBUG, ("\n"));
#endif /* IP_DEBUG */
    if (ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr))) {//目标IP和自己IP比较下,查看是否与自己IP一样,一样说明数据就是发送给自己的,就接着往下处理数据,不是则跳出。
      break;
    }
  }
  if (netif == NULL) {
    /* packet not for us, route or discard */
#if IP_FORWARD
    ip_forward(p, iphdr);
#endif
    pbuf_free(p);
    return;
  }
  pbuf_realloc(p, IP_HLEN + ntohs(iphdr->len));
  /* send to upper layers */
#if IP_DEBUG
  /*  LWIP_DEBUGF("ip_input: \n");
  ip_debug_print(p);
  LWIP_DEBUGF("ip_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len);*/
#endif /* IP_DEBUG */
  if(pbuf_header(p, -IP_HLEN)) {
    LWIP_ASSERT("Can't move over header in packet", 0);
    return;
  }
  switch (iphdr->nexthdr) {//这里就是判断数据是哪个协议层的数据,是UDP呢还是TCP等,然后数据就交由上一层协议去处理了。
  case IP_PROTO_UDP:
    udp_input(p, inp);
    break;
  case IP_PROTO_TCP:
    tcp_input(p, inp);
    break;
#if LWIP_ICMP
  case IP_PROTO_ICMP:
    icmp_input(p, inp);
    break;
#endif /* LWIP_ICMP */
  default:
#if LWIP_ICMP
    /* send ICMP destination protocol unreachable */
    icmp_dest_unreach(p, ICMP_DUR_PROTO);
#endif /* LWIP_ICMP */
    pbuf_free(p);
    LWIP_DEBUGF(IP_DEBUG, ("Unsupported transport protocol %"U16_F"\n",
          iphdr->nexthdr));

    IP_STATS_INC(ip.proterr);
    IP_STATS_INC(ip.drop);
  }
  PERF_STOP("ip_input");
}

这部分的代码还是很容易理解的,就是IP层处理数据,首先是目标IP与自己是不是相等,相等说明数据就是发给自己的,就往下处理。接着是判断数据的类型,然后在交由相应上层处理数据。好了这部分代码基本意思就是这样,中午不睡觉累,完工上班去了。


你可能感兴趣的:(rt-thread学习,lwip)