Comments前回に引き続き、Dockerのネットワーク周りです。socketで扱ってみようと思います。linkの関係にあり、対応するvethにパケットを送信するとコンテナ内のethに転送されます。ホストOS上で見えるvethは、通常のNICと同じように扱えます。bridgeであるdocker0というブリッジに接続されますが、前回はvethをdocker0から剥がしてOpenvSwitchに接続しました。これによりVLANが扱えたり、OpenFlowでパケット転送を制御したりが可能となりました。今回は、そのOpenvSwitchに当たる転送処理を自前で実装してみようというのが趣旨になります。簡単なバカハブ(リピーターハブ)を実装してみたいと思います。適当にコンテナを2つほど立てます。host1次に各コンテナのeth0に相当するvethを探します。毎回手で探すのは面倒なので、今後のためにこんなコードを書きました。2enp1s0ifindexからinterfaceの名前を取ってこれます。これをうまいこと利用して、こんな感じで。例によってデフォルトでvethはdocker0に接続されているので、接続を解除。yesあと、コンテナ内のNICのアドレスも確認しておきましょう。必要があればアドレスの変更も。(今回はハブを作るので、2つのコンテナは同じサブネット上にいる必要があります。172.17.0.3/16これで準備は完了です。socketプログラミングです。socketはイーサフレームを直接送受信できるとても便利な機能です。今勉強中であまり詳しくないので、コードが汚いのは許してください。J1900で動かしています。バイトオーダ等の違いで動かないとかあるかもしれませんが、そのあたりはご愛嬌。(ハードウェアを意識したプログラミングって難しい。'.');}printf("\n");}}ビルドはこんな感じで。l2hub.cこれがリピーターハブとして動作するコードになります。あるポートから受信したイーサフレームを、受信ポート以外のポートへフラッディングするだけです。引数でNICを渡すと、それらのNICの全通信を他のポートに送信します。作成したハブ動かしてない状態。vethがどこにも接続されていないため、当然通信はできませんし、ARPすら解決できてない。eth0そして次にハブを起動してみる。引数としてブリッジしたいインターフェース(今回はホストOS側で認識しているveth)を指定します。veth7d0cb2a再びPingを打つと正常に通信できていることが確認できました。eth0root@Capella:~#今回はデバッグのために通過したパケットの種別、受信インターフェイス、送信インターフェイスを標準出力するようにしています。2054[ARP][send]interface:veth7d0cb2a^Croot@Capella:~#この出力から分かるように、コンテナ内のeth0に送出されたICMPパケットが、ホストOS側のvethにやってきています。socketで吸い上げて、他のインターフェイス(veth)に送出し、それが再びコンテナ内のeth0に転送されています。socketが動作するのが非常に便利です。簡単に物理NICとDokcerのコンテナをブリッジできたりします。今回はハブを作りましたが、少し頭を良くしてスイッチにしたり、VLANを扱えるようにしたり、ルータを作ったり、色々楽しそうですね。フレーム単位でパケットを処理できて、TCP/UDPのペイロード等もその気になれば見れるので、DPIみたいな高度なものを実装するのもいいと思います。本気でやるならカーネルモジュールとして実装したり、netmapやDPDK等のフレームワークの使用を検討した方がいいでしょう。socketプログラミングやるためだけに、多ポートサーバを用意しなくていいので良いですね。(買ったあとにこの方法思いついて微妙に無駄な出費になった。)特にケーブルの繋ぎ変えもいらないのが気に入ってます。ホストを増やしたくなったらコンテナ立てるだけでいいですし、いらなくなったら消すだけ。サーバやトラフィック/パケットジェネレータもコンテナで立ててしまえば、試験が簡単にできます。