LoginSignup
3
5

More than 5 years have passed since last update.

ZephyrのTCP/IP実装 メインループを読む

Posted at

ZephyrのTCP/IPプロトコルスタックのメインループを読んでみました。

ZephyrはLinux Foundationが開発しているRTOSです。

ソース
* https://gerrit.zephyrproject.org/r/gitweb?p=zephyr.git

ZephyrのTCP/IPプロトコルスタックはContiki OSのuIPを使っています。そのスタックをZephyrのスタイルに合わせるためにラッピングしています。

プロトコルスタックのループは3つあります。
* 送信パケットのループ (by Zephyr)
* 受信パケットのループ (by Zephyr)
* uIPのループ (by Contiki)

送信パケットのループ

  • 送信パケットのループはfiberで実装しています。net/ip/net_core.c にあります。
  • nano_fifo_get()で送信キューから送信パケットを取り出す。
  • check_and_send_packet()で送信します。送信データはTCP, UDP, ARPの処理を行い、process_post_synch()でuIPのループに渡されます。
  • check_and_send_packet() の戻り値rが0であるなら、process_run()でバッファの状態を監視し、処理が完了したらbufを解放する。
  • check_and_send_packet() の戻り値rが負なら、bufを解放して次のループに移動する。
  • check_and_send_packet() の戻り値rが正なら、次のループに移動する。
net_core.c
static void net_tx_fiber(void)
{
    NET_DBG("Starting TX fiber (stack %d bytes)\n",
        sizeof(tx_fiber_stack));

    while (1) {
        struct net_buf *buf;
        int ret;

        /* Get next packet from application - wait if necessary */
        buf = nano_fifo_get(&netdev.tx_queue, TICKS_UNLIMITED);

        NET_DBG("Sending (buf %p, len %u) to IP stack\n",
            buf, buf->len);

        /* What to do with the buffer:
         *  <0: error, release the buffer
         *   0: message was discarded by uIP, release the buffer here
         *  >0: message was sent ok, buffer released already
         */
        ret = check_and_send_packet(buf);
        if (ret < 0) {
            ip_buf_unref(buf);
            goto wait_next;
        } else if (ret > 0) {
            goto wait_next;
        }

        NET_BUF_CHECK_IF_NOT_IN_USE(buf);

        /* Check for any events that we might need to process */
        do {
            ret = process_run(buf);
        } while (ret > 0);

        ip_buf_unref(buf);

    wait_next:
        /* Check stack usage (no-op if not enabled) */
        net_analyze_stack("TX fiber", tx_fiber_stack,
                  sizeof(tx_fiber_stack));

        net_print_statistics();
    }
}

受信パケットのループ

  • 受信パケットのループはfiberで実装しています。net/ip/net_core.c にあります。
  • 受信パケットはネットワークデバイスのドライバで受信キューに登録されます。
  • nano_fifo_get()で受信キューを読み出す。
  • tcpip_input()で、process_post_synch()でuIPのループに渡されて、TCP/IPの処理を行う。
  • tcpip_input()の戻り値が0なら、bufを解放する。
net_core.c

static void net_rx_fiber(void)
{
    struct net_buf *buf;

    NET_DBG("Starting RX fiber (stack %d bytes)\n",
        sizeof(rx_fiber_stack));

    while (1) {
        buf = nano_fifo_get(&netdev.rx_queue, TICKS_UNLIMITED);

        /* Check stack usage (no-op if not enabled) */
        net_analyze_stack("RX fiber", rx_fiber_stack,
                  sizeof(rx_fiber_stack));

        NET_DBG("Received buf %p\n", buf);

        if (!tcpip_input(buf)) {
            ip_buf_unref(buf);
        }
        /* The buffer is on to its way to receiver at this
         * point. We must not remove it here.
         */

        net_print_statistics();
    }
}

uIPのループ

tcpip.c
PROCESS_THREAD(tcpip_process, ev, data, buf, user_data)
{
  PROCESS_BEGIN();

  • 初期化
tcpip.c

#if UIP_TCP
 {
   static unsigned char i;

   for(i = 0; i < UIP_LISTENPORTS; ++i) {
     s.listenports[i].port = 0;
   }
   s.p = PROCESS_CURRENT();
 }
#endif

  tcpip_event = process_alloc_event();
#if UIP_CONF_ICMP6
  tcpip_icmp6_event = process_alloc_event();
#endif /* UIP_CONF_ICMP6 */
  etimer_set(&periodic, CLOCK_SECOND / 2, &tcpip_process);

  uip_init();
#ifdef UIP_FALLBACK_INTERFACE
  UIP_FALLBACK_INTERFACE.init();
#endif
/* initialize RPL if configured for using RPL */
#if NETSTACK_CONF_WITH_IPV6 && UIP_CONF_IPV6_RPL
  rpl_init();
#endif /* UIP_CONF_IPV6_RPL */

  • 送信イベント、受信イベント、タイマイベントを処理する。
    • イベント:PROCESS_EVENT_EXITED PROCESS_EVENT_TIMER TCP_POLL UDP_POLL PACKET_INPUT
tcpip.c
  while(1) {
    PROCESS_YIELD();
    eventhandler(ev, data, buf);
  }

  PROCESS_END();
}

参考

3
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
5