【Ethernet】車載ネットワーク その43【lwIP疑似受信⑥】

【Ethernet】車載ネットワーク その43【lwIP疑似受信⑥】 車載ネットワーク

バックナンバーはこちら。
https://www.simulationroom999.com/blog/In-vehicle-network-backnumber/

はじめに

IPフラグメントの受信フレーム順違いに対応するための設計手法。

登場人物

博識フクロウのフクさん

イラストACにて公開の「kino_k」さんのイラストを使用しています。
https://www.ac-illust.com/main/profile.php?id=iKciwKA9&area=1

エンジニア歴8年の太郎くん

イラストACにて公開の「しのみ」さんのイラストを使用しています。
https://www.ac-illust.com/main/profile.php?id=uCKphAW2&area=1

IPフラグメントの順番入れ替えの判定をどこでやっているのか?

太郎くん
太郎くん

じゃー、IPフラグメントの順番違いをどう対応してるのか説明よろしくー。

フクさん
フクさん

はいよー。

フクさん
フクさん

まずは、全部のフレームが揃ったかどうかチェックしているのは
ip_reass_chain_frag_into_datagram_and_validate
って関数になる。
core/ipv4/ip4_frag.c
で定義されてる関数になるね。

太郎くん
太郎くん

ip4_frag.c?
そのまんまな名前のソースコードがあったとは・・・。

ip_reass_chain_frag_into_datagram_and_validateの中の完了判定部分

フクさん
フクさん

さらに、ip_reass_chain_frag_into_datagram_and_validateの中で完了判定をしている箇所がある。
そこだけのコードを切り抜いてきた。

  /* At this point, the validation part begins: */
  /* If we already received the last fragment */
  if (is_last || ((ipr->flags & IP_REASS_FLAG_LASTFRAG) != 0)) {
    /* and had no holes so far */
    if (valid) {
      /* then check if the rest of the fragments is here */
      /* Check if the queue starts with the first datagram */
      if ((ipr->p == NULL) || (((struct ip_reass_helper *)ipr->p->payload)->start != 0)) {
        valid = 0;
      } else {
        /* and check that there are no holes after this datagram */
        iprh_prev = iprh;
        q = iprh->next_pbuf;
        while (q != NULL) {
          iprh = (struct ip_reass_helper *)q->payload;
          if (iprh_prev->end != iprh->start) {
            valid = 0;
            break;
          }
          iprh_prev = iprh;
          q = iprh->next_pbuf;
        }
        /* if still valid, all fragments are received
         * (because to the MF==0 already arrived */
        if (valid) {
          LWIP_ASSERT("sanity check", ipr->p != NULL);
          LWIP_ASSERT("sanity check",
                      ((struct ip_reass_helper *)ipr->p->payload) != iprh);
          LWIP_ASSERT("validate_datagram:next_pbuf!=NULL",
                      iprh->next_pbuf == NULL);
        }
      }
    }
    /* If valid is 0 here, there are some fragments missing in the middle
     * (since MF == 0 has already arrived). Such datagrams simply time out if
     * no more fragments are received... */
    return valid ? IP_REASS_VALIDATE_TELEGRAM_FINISHED : IP_REASS_VALIDATE_PBUF_QUEUED;
  }

完了判定部分解説

太郎くん
太郎くん

うーん・・・。
何やってるかわからん!!

フクさん
フクさん

簡単に説明すると、以下の仕組みになってる。

  • 各EthernetFrameは連結リストで連結されている。
  • 各EthernetFrameはIPパケット上の開始位置と終了位置を保持している。
  • 各EthernetFrameは開始位置順にソートされている。
  • 各EthernetFrameの終了位置は次のEthernetFrameの開始位置のはずである。
太郎くん
太郎くん

んー?
うーん?

フクさん
フクさん

(わからんか・・・。)

フクさん
フクさん

図解するとこうだな。

太郎くん
太郎くん

おー!
そういう関係性かー!

太郎くん
太郎くん

そういえば、連結リストって前にも出てきたね。

太郎くん
太郎くん

あれ?
Ethnertフレーム自体が連結リストだったと思うのだけど、
今回のEthnertフレームがさらに連結されてる???

フクさん
フクさん

そうそう。
そこが話がややこしくなってるところで、
構造上は連結リストを連結リストで連結している。

太郎くん
太郎くん

また、ややこしいことに・・・。

フクさん
フクさん

まぁEthernet層の話はIP層には直接関係ないんで、
一旦気にしないって方が良いかもねー。

太郎くん
太郎くん

とりあえず、いろいろ工夫されてるという事実はわかった。

 

まとめ

フクさん
フクさん

まとめだよ。

  • IPフラグメントの順番入れ替えの判定のソースコードと該当関数説明。
    • Ethnertフレームを連結リストで管理。
    • 連結は常にソートされた状態。
    • 開始位置と完了位置を持ってパケットの完全性を評価している。

使用したコードはこちら。

GitHub - KEIKEI999/lwip_dummy_recv: lwIPで疑似受信
lwIPで疑似受信. Contribute to KEIKEI999/lwip_dummy_recv development by creating an account on GitHub.

バックナンバーはこちら。

コメント

タイトルとURLをコピーしました