lwip初始化流程

lwip初始化流程

lwip初始化不同平台代码可能存在微弱差异,但是大体步骤还是一致的。

lwip_tcpip_init()其中包括tcpip_init,ethernetif_init

一.tcpip_init() 包括lwip_init,sys_thread_new

1.tcpip_init源码如下

void
tcpip_init(tcpip_init_done_fn initfunc, void *arg)
{
//创建一个邮箱,在freertos中,就是创建一个消息队列
  if(sys_mbox_new(&mbox, TCPIP_MBOX_SIZE) != ERR_OK) {
    LWIP_ASSERT("failed to create tcpip_thread mbox", 0);
  }
  lwip_init();    //lwip各模块的初始化

  tcpip_init_done = initfunc;
  tcpip_init_done_arg = arg;
#if LWIP_TCPIP_CORE_LOCKING
//创建一个锁
  if(sys_mutex_new(&lock_tcpip_core) != ERR_OK) {
    LWIP_ASSERT("failed to create lock_tcpip_core", 0);
  }
#endif /* LWIP_TCPIP_CORE_LOCKING */
//创建协议栈管理进程tcpip_thread
  sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE / sizeof(portSTACK_TYPE), TCPIP_THREAD_PRIO);
}

2 .lwip_init,初始化各种模块

/**
 * Initialize all modules.
 */
void
lwip_init(void)
{
  /* Modules initialization */
  stats_init();
#if !NO_SYS
  sys_init();
#endif /* !NO_SYS */
  mem_init();
  memp_init();
  pbuf_init();
  netif_init();
#if LWIP_IPV4
  ip_init();
#if LWIP_ARP
  etharp_init();
#endif /* LWIP_ARP */
#endif /* LWIP_IPV4 */
#if LWIP_RAW
  raw_init();
#endif /* LWIP_RAW */
#if LWIP_UDP
  udp_init();
#endif /* LWIP_UDP */
#if LWIP_TCP
  tcp_init();
#endif /* LWIP_TCP */
#if LWIP_SNMP
  snmp_init();
#endif /* LWIP_SNMP */
#if LWIP_AUTOIP
  autoip_init();
#endif /* LWIP_AUTOIP */
#if LWIP_IGMP
  igmp_init();
#endif /* LWIP_IGMP */
#if LWIP_DNS
  dns_init();
#endif /* LWIP_DNS */
#if PPP_SUPPORT
  ppp_init();
#endif

#if LWIP_TIMERS
  sys_timeouts_init();
#endif /* LWIP_TIMERS */
}

3.tcpip_thread分析

主要熟悉tcpip_thread对api msg和接收的数据包的处理

/**
 * The main lwIP thread. This thread has exclusive access to lwIP core functions
 * (unless access to them is not locked). Other threads communicate with this
 * thread using message boxes.
 *
 * It also starts all the timers to make sure they are running in the right
 * thread context.
 *
 * @param arg unused argument
 */
static void
tcpip_thread(void *arg)
{
  struct tcpip_msg *msg;
  LWIP_UNUSED_ARG(arg);

  if (tcpip_init_done != NULL) {
    tcpip_init_done(tcpip_init_done_arg);
  }

  LOCK_TCPIP_CORE();
  while (1) {                          /* MAIN Loop */
    UNLOCK_TCPIP_CORE();
    LWIP_TCPIP_THREAD_ALIVE();
    /* wait for a message, timeouts are processed while waiting */
    //阻塞等待mbox消息
    sys_timeouts_mbox_fetch(&mbox, (void **)&msg);
    LOCK_TCPIP_CORE();
    if (msg == NULL) {
      LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: NULL\n"));
      LWIP_ASSERT("tcpip_thread: invalid message", 0);
      continue;
    }
    //收到消息后判断消息类型分别做处理
    switch (msg->type) {
#if LWIP_NETCONN || LWIP_SOCKET
    case TCPIP_MSG_API:  //api消息,主要是api_msg.c中的函数接口,下面会做简要分析
      LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg));
      msg->msg.apimsg->function(&(msg->msg.apimsg->msg));
      break;
#endif /* LWIP_NETCONN || LWIP_SOCKET */

#if !LWIP_TCPIP_CORE_LOCKING_INPUT
    case TCPIP_MSG_INPKT://收到数据帧消息,解析消息,分析给arp或者IP处理
      LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: PACKET %p\n", (void *)msg));
#if LWIP_ETHERNET
      if (msg->msg.inp.netif->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) {
        ethernet_input(msg->msg.inp.p, msg->msg.inp.netif);
      } else
#endif /* LWIP_ETHERNET */
      ip_input(msg->msg.inp.p, msg->msg.inp.netif);  //直接上传给ip层处理
      memp_free(MEMP_TCPIP_MSG_INPKT, msg);
      break;

#if PPPOS_SUPPORT && !PPP_INPROC_IRQ_SAFE
    case TCPIP_MSG_INPKT_PPPOS:         //收到的ppp数据包
      pppos_input_sys(msg->msg.inp.p, msg->msg.inp.netif);
      memp_free(MEMP_TCPIP_MSG_INPKT, msg);
      break;
#endif /* PPPOS_SUPPORT && !PPP_INPROC_IRQ_SAFE */
#endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */

#if LWIP_NETIF_API
    case TCPIP_MSG_NETIFAPI:     //netif API消息
      LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: Netif API message %p\n", (void *)msg));
      msg->msg.netifapimsg->function(&(msg->msg.netifapimsg->msg));
      break;
#endif /* LWIP_NETIF_API */

#if LWIP_PPP_API 
    case TCPIP_MSG_PPPAPI:   //基于ppp 点对点协议的消息
      LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: PPP API message %p\n", (void *)msg));
      msg->msg.pppapimsg->function(&(msg->msg.pppapimsg->msg));
      break;
#endif /* LWIP_PPP_API */

#if LWIP_TCPIP_TIMEOUT
    case TCPIP_MSG_TIMEOUT:    //超时消息
      LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: TIMEOUT %p\n", (void *)msg));
      sys_timeout(msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg);
      memp_free(MEMP_TCPIP_MSG_API, msg);
      break;
    case TCPIP_MSG_UNTIMEOUT:   //超时消息
      LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: UNTIMEOUT %p\n", (void *)msg));
      sys_untimeout(msg->msg.tmo.h, msg->msg.tmo.arg);
      memp_free(MEMP_TCPIP_MSG_API, msg);
      break;
#endif /* LWIP_TCPIP_TIMEOUT */

    case TCPIP_MSG_CALLBACK:   //回调
      LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg));
      msg->msg.cb.function(msg->msg.cb.ctx);
      memp_free(MEMP_TCPIP_MSG_API, msg);
      break;

    case TCPIP_MSG_CALLBACK_STATIC: //回调
      LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK_STATIC %p\n", (void *)msg));
      msg->msg.cb.function(msg->msg.cb.ctx);
      break;

    case TCPIP_MSG_MODEM_DATA:
      LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: INPKT_CMUX %p\n", (void *)msg));
      msg->msg.cb.function(msg->msg.cb.ctx);
      memp_free(MEMP_TCPIP_MSG_INPKT, msg);
      break;
    case TCPIP_MSG_TIMER_ADD:
      LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip_thread: INPKT_CMUX %p\n", (void *)msg));
      sys_timeout_add((struct sys_timeo *)msg->msg.cb.ctx);
      memp_free(MEMP_TCPIP_MSG_INPKT, msg);
      break;
    default:
      LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: %d\n", msg->type));
      LWIP_ASSERT("tcpip_thread: invalid message", 0);
      break;
    }
  }
}

注意:在这里简单介绍下应用层数据—》网络,与网卡收到数据包处理过程
lwip初始化流程_第1张图片
应用程序数据—》tcpip_thread:
以netconn_connect函数为例,应用程序消息类型
api_lib.c中将数据封装成api_msg消息,调用TCPIP_APIMSG函数将数据传递给tcpip_apimsg处理,最终封装成tcpip_msg消息类型后交给tcpip_thread处理

err_t
tcpip_apimsg(struct api_msg *apimsg)
{
  TCPIP_MSG_VAR_DECLARE(msg);
#ifdef LWIP_DEBUG
  /* catch functions that don't set err */
  apimsg->msg.err = ERR_VAL;
#endif

  if (sys_mbox_valid_val(mbox)) {
    TCPIP_MSG_VAR_ALLOC(msg);
    TCPIP_MSG_VAR_REF(msg).type = TCPIP_MSG_API;   //赋值tcpip_msg类型
    TCPIP_MSG_VAR_REF(msg).msg.apimsg = apimsg;    //apimsg上层传递过来的,其中apimsg->function是上层的函数,与tcpip_thread中对应
#if LWIP_NETCONN_SEM_PER_THREAD
    apimsg->msg.op_completed_sem = LWIP_NETCONN_THREAD_SEM_GET();
    LWIP_ASSERT("netconn semaphore not initialized",
      sys_sem_valid(apimsg->msg.op_completed_sem));
#endif
    sys_mbox_post(&mbox, &TCPIP_MSG_VAR_REF(msg));  //发送mbox
    sys_arch_sem_wait(LWIP_API_MSG_SEM(&apimsg->msg), 0);
    TCPIP_MSG_VAR_FREE(msg);
    return apimsg->msg.err;
  }
  return ERR_VAL;
}

网卡数据–》tcpip_thread
网卡数据流向tcpip_input处理

/**
 * Pass a received packet to tcpip_thread for input processing
 *
 * @param p the received packet, p->payload pointing to the Ethernet header or
 *          to an IP header (if inp doesn't have NETIF_FLAG_ETHARP or
 *          NETIF_FLAG_ETHERNET flags)
 * @param inp the network interface on which the packet was received
 */
err_t
tcpip_input(struct pbuf *p, struct netif *inp)
{
#if LWIP_TCPIP_CORE_LOCKING_INPUT   //判断是否是active lwip,是就直接解析arp或者ip
  err_t ret;
  LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_input: PACKET %p/%p\n", (void *)p, (void *)inp));
  LOCK_TCPIP_CORE();
#if LWIP_ETHERNET
  if (inp->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) {
    ret = ethernet_input(p, inp);
  } else
#endif /* LWIP_ETHERNET */
  ret = ip_input(p, inp);
  UNLOCK_TCPIP_CORE();
  return ret;
#else /* LWIP_TCPIP_CORE_LOCKING_INPUT */  //否则传递给tcpip_thread处理
  struct tcpip_msg *msg;  //定义tcpip_msg消息

  if (!sys_mbox_valid_val(mbox)) {
    return ERR_VAL;
  }
  msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_INPKT);  //申请空间
  if (msg == NULL) {
    return ERR_MEM;
  }

  msg->type = TCPIP_MSG_INPKT;   //赋值tcpip_msg消息类型
  msg->msg.inp.p = p;
  msg->msg.inp.netif = inp;    
  if (sys_mbox_trypost(&mbox, msg) != ERR_OK) {  //发送mbox
    memp_free(MEMP_TCPIP_MSG_INPKT, msg);
    return ERR_MEM;
  }
  return ERR_OK;
#endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */
}

二.ethernetif_init初始化

void ethernetif_init(sta_ip_mode_t sta_ip_mode,
                     uint8_t *sta_mac_addr,
                     uint8_t *ap_mac_addr,
                     ip4_addr_t *sta_ip_addr, ip4_addr_t *sta_net_mask, ip4_addr_t *sta_gw,
                     ip4_addr_t *ap_ip_addr, ip4_addr_t *ap_net_mask, ip4_addr_t *ap_gw,
                     uint8_t opmode)
{
    uint8_t sta_mac_address[6];
    uint8_t ap_mac_address[6];

    /* for patch and fw download */
    ethernetif_init_callback();

    memset(&sta_if, 0, sizeof(sta_if));
    memset(&ap_if,  0, sizeof(ap_if));

    // Note: *MUST* first add AP, then STA interface, to make STA the first
    //       interface in the link-list: STA -> AP -> NULL.
    if (0 > wifi_config_get_mac_address(WIFI_PORT_STA, (uint8_t *)&sta_mac_address) ||
        0 > wifi_config_get_mac_address(WIFI_PORT_AP, (uint8_t *)&ap_mac_address)) {
        LOG_E(lwip, "get mac fail\n\r");
        return;
    }
   //将网卡添加到netif_list链表中,添加后由lwip管理网卡,网卡中有数据就会调用tcpip_input处理,这里关系一个网络接口结构体netif,ethernetif_init后期单独介绍
    netif_add(&ap_if, ap_ip_addr, ap_net_mask, ap_gw, NULL,
              ethernetif_init2, tcpip_input);  
    netif_add(&sta_if, sta_ip_addr, sta_net_mask, sta_gw,
              NULL, ethernetif_init1, tcpip_input);

    low_level_set_mac_addr(&ap_if,  ap_mac_address);
    low_level_set_mac_addr(&sta_if, sta_mac_address);
    //初始化缺省网络接口
    //netif_set_default(&sta_if);
    //使能网络接口
    netif_set_up(&sta_if);
    netif_set_up(&ap_if);

    //install default route
    switch (opmode) {
        case WIFI_MODE_AP_ONLY:
            netif_set_default(&ap_if);
            netif_set_link_down(&sta_if);
            break;
        case WIFI_MODE_STA_ONLY:
            netif_set_default(&sta_if);
            netif_set_link_down(&ap_if);
            wifi_config_set_ip_mode((uint8_t)sta_ip_mode);
            if(sta_ip_mode == STA_IP_MODE_DHCP)
                netif_set_wifi_callback(&sta_if, inform_ip_ready_callback);
            break;
        case WIFI_MODE_REPEATER:
            netif_set_default(&sta_if);
            break;
    }
}

至此,lwip初始化完成。

你可能感兴趣的:(lwip)