ロバストプロコル？？？

この記事は，[大阪工業大学 Advent Calendar 2020](https://adventar.org/calendars/5332)の23日目の記事です.

##はじめに
誠に遺憾ながらほぼ去年のアドカレ以来の更新となりました...
では，今年のアドカレは何を書くかというとseccampで受けた講義について書こうと思います．

　今回記事を書く講義は"[A8]ロバストプロコル・オープンチャレンジ大会"です．物理的に通信が阻害される環境でも確実にファイル転送のできるプロトコルの設計・実装しろといったものでした．今回モブプロ形式での実装でドライバーを担当しましたが，結局最後は別の方に書いていただきました...
講義の概要としては物理的な通信障害が発生するLANにおいて通信が可能なプロトコルを設計・実装して競うといったものでした。
公式ページより引用
>一般にサイバーセキュリティとは悪意を持った第三者からの攻撃から情報通信機器やデータを守ることに重点が置かれがちですが、これ以外に事故や自然災害から通信を確保することもサイバーセキュリティの大事な要素と考えます。本講義では物理的な通信障害が発生するLAN（10BASE-T）をリモートで用意します。参加者はこれら障害のあるLANにおいて通信が可能な強靭なプロトコルを各自がデザインし実装しリモートの実機で様々な評価軸でプロトコルの強靭性を競います。 本講義の参加者はロバストプロコル　オープン　チャレンジ運営チーム（A1の受講者）が策定したレギュレーションで競技に参加し、各自が実装したプロトコルのプレゼンテーションを行います。 これを以下昨年ネクストで受講した修了生のブログです。参考まで。https://kawasin73.hatenablog.com/entry/2019/08/17/190025 A1の受講者に限らずセキュリティ・キャンプの参加者であればどなたでも参加可能です。

##概要
大会ドキュメントより
>***概要***
>物理的な通信障害が発⽣するLAN上で，多数のファイルを可能な限り正しく，⾼速に転送することができる強靭なプロトコルを各⾃がデザイン/実装してください．
>***ルール***
>・1ファイルのサイズは100kB．
・ファイルの転送は，必ずノイズが乗っているLANを⽤いて⾏ってください．
・ファイルを圧縮して送ることは禁⽌します．
・制限時間は60秒です．
・通信モードは10BASE-T/FULL Duplexです．
・ノイズによるEthernetパケット損失率は50%程度です．
>***採点基準***
>・制限時間の間に受信ファイルとして受信側に保存されたファイルをすべてチェックし，以下
のように採点します．
-正しいファイル1つにつき，10pts加点．
-誤を含むファイル1つにつき，10pts減点．
-重複ファイル(内容が等しいファイル)1つにつき，5pts減点

以上が大会の主なレギュレーションでした．
10BASE-Tで60秒間の通信で送れるデータ量は75MBで，送れるファイル数は750ファイルが限界でした．そのなかで何ファイル送信することができるかと，いかに***誤りなく送信することができる***のかを競いました．

##SITP(Split Into TCP Packets)
　私たちのグループはまず，TCPならどれだけ送れるか試しました．プログラムも特に変わった処理も書かずにそのままTCPで送信するプログラムを作成し実験しました．

結果は

| OK | FAILED | DUP |
|:--:|:------:|:---:|
| 18 |    0   |  0  |

おまけにジャマーがなしの時は

| OK | FAILED | DUP |
|:--:|:------:|:---:|
| 684|    0   |  0  |

##考察
　なんと18ファイルしか送れませんでした！1000ファイル中(実質750ファイル中)18ファイル．とてもじゃないですが，競技としてはTCPはまったく使い物になりませんでした．ジャマーなしの場合684ファイルのところジャマーが入るだけで1/38になってしまいました．これはおそらくTCPの再送タイムアウトのラウンドトリップが原因だと考えました．

　以上からTCPは使い物にならないと判断して、UDPが次に検討されました．

##SCU(Sequence Control on UDP)
　UDPで送信することが決まりましたが、1つ問題があります。UDPは基本投げっぱなしのため通信が遮断されている間のパケットが補完する必要があります．なので僕たちのチームはUDPにTCPの必要な機能だけを実装することにしました．
<dl>
<dt>必要な機能</dt>
<dd>再送処理</dd>
<dd>シーケンス制御</dd>
</dl>
以上の2つさえあれば最低限の信頼性が作れると判断しました．これらの情報をのせるためにUDPのペイロードの先頭に新しくSCUヘッダを追加して実装しました．UDPのペイロード長は64KBありますが，その下の下のEthernetパケットのペイロード長が1500byteしかないためUDPで64KB送信していても，内部で分割されて送信されています．そのためUDPで64KB送信してその一部がパケロスして再送要求した場合、64KBすべて再送信になりオーバーヘッドになるため一度に送るデータ量をEthernetパケット1パケットで済むようにサイズを調整しました.また，もとのUDPの性能をできるだけ生かすために，receiverは基本的にresponseを送信せず，必要な時のみresponseを生成するようにしました．
<br>
***ヘッダ***

* ***type*** &nbsp;&nbsp;&nbsp;1byte　 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;パケットの種類の判別
* ***id***   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2byte　　&nbsp;&nbsp;ファイル数目
* ***seq*** &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1byte　　&nbsp;&nbsp;ファイルの分割数目

typeは，senderはファイル送信がb'0'，ファイル終端がb'1'，receiverは再送要求がb'2'，ファイル生成の完了がb'3'の4種類で1byte
idは，送っているファイルの識別のための1-1000の2byte
seqは，100KBの何分割目の識別のための1byte

***ペイロード***
IPヘッダの20byte，UDPヘッダの8byte，SCUヘッダの4byteの計32byteを1500byteから引いた1468byte

<dl>
<dt>仕様</dt>
<dt>sender</dt>
<dd>senderはファイルを分割して送信しながら，receiverからの再送要求のパケットを受け取る必要があるため送信用のスレッドと受信用のスレッドを分けて通信を行います．パケットを生成する前にキューに再送要求が来ていないかを確認して，再送要求があればそのパケットから送信しなおし，なければそのままパケットを作成・送信します．receiver側がファイル生成の区切りのためにsend時のヘッダのtypeにファイル終端を示すDataendで送信します．
</dd>
<dt>receiver</dt>
<dd>receiverは基本的にパケットを受信し続けて必要な時だけresponseを生成します．パケットの完全性のために再送制御を実装しました．その再送制御のためにシーケンス制御を使いました．receiverは受け取ったパケットのSCUヘッダからシーケンス番号を保持しておき，受け取ったシーケンス番号と保持しておいたシーケンス番号が飛んでないかで、パケットの抜けを検知して再送要求のパケットを作成・送信します．ファイルが生成できたことをsenderに通知するためにファイル終端のヘッダを受け取って正常に処理を終えるとヘッダのtypeに終了のfinで送信します．
</dd>
そして結果は，
太郎から花子に送信(太郎から花子への***TXにジャマー***)

| OK | FAILED | DUP |
|:--:|:------:|:---:|
| 138|    0   |  0  |
花子から太郎に送信(花子から太郎への***RXにジャマー***)

| OK | FAILED | DUP |
|:--:|:------:|:---:|
| 328|    0   |  0  |

##考察
　以上の結果からUDPでも誤りなくファイルを送信できていると言える．SITPに比べ10倍程度送信できているため，UDPにした効果が認められた．次に上下に2倍以上の差がある．その理由はジャマーがsenderのTXとRXどちらに入るかによって変わっている．このプロトコルではsenderはreceiverからの受信が必須ではないため差が生まれた．今回の環境ではノードとノードが物理線で直接つながっているため基本的にパケットがロスすることがない．そのためTXにジャマーが入ると通信が阻害されて速度が遅くなるが．RXにジャマーが入っても再送要求，もしくはファイル生成の完了通知がロスだけでパケットの受信が阻害されることがないため，ほとんどUDPの速度で送信することができた．上下の結果で2倍以上差があるため，改善の余地があると考えられる．

***問題点・改善点***
　再送制御を送ってすぐ対応したパケットが送られてくるわけではないため，シーケンスが飛んで複数パケットを受け取っているが，これらを破棄しているためパケットが多重することになります．これを改善することによって速度が改善されることが期待されるのではないかと考えました．
　また、宛先をハードコードしているためそこの改善と、ファイルの数もハードコードしているため指定フォルダを使うなどして自動取得するなどの改善、つまり冗長化？出来たらいいなと思いました。

##まとめ
　チーム開発で自分がメインで仕様を決めていて，本来は自分で主にコーディングする予定だったが自分のコーディング力の低さによりチームリーダーの方にめちゃくちゃ書いてもらいました．ありがとうございました．ネットワーク学科に所属しているためTCPやUDPについて基本的なことは知っていても，プロトコルを自分で設計・実装するのは初めてググりまくりながら必要な機能を選定して，実装しました．どうやって通信しているか改めて学べて，ためになりました．
　2021年春季に[一般向けに開催](https://twitter.com/75u2u/status/1340164240087293953?s=19)されるため是非参加してﾎﾞｸﾉｻｲｷｮｳﾉﾛﾊﾞｽﾄﾌﾟﾛﾄｺﾙを発表してみてください！


<br>
※ソースコードはチームで作ったので今のところは公開の予定はないです...