GoでTFTPサーバ自作(blksize, ロールオーバー編)
この記事の内容
この記事ではRFC 2347およびRFC 2348に従ってTFTPサーバを拡張します
また、ロールオーバー機能を追加します
ただし、ロールオーバー機能に対応するRFCは存在しません(2025年3月現在)
学習目的の記事なのでAIは使用しません
TFTPのオプション
RFC 2347ではTFTPのオプションが定義されています
オプションはRRQのフォーマットを変更することで実現されます
クライアントはオプションを付与してサーバにRRQを送ります
サーバはオプションを受け入れる場合はこのRFCで定義されるOACKを送ります
クライアントはOACKに対してブロック番号0番のACKを送ります
以降の挙動はオプションにより異なります
詳細
RFC 2347では新しい一つのOpcodeと一つのErrorCodeが追加されています
それぞれ以下です
種類 | Opcode | 内容 |
---|---|---|
OACK | 06 | サーバが受け入れるオプションと具体的な値 |
ErrorCode | 内容 |
---|---|
8 | the request has been denied. |
オプションを付与する場合のRRQおよびOACKのフォーマットは以下です
種類 | フォーマット |
---|---|
RRQ | Opcode: 2 bytes Filename: string 0: 1 byte Mode: string 0: 1 byte opt1: string 0: 1 byte value1: string 0: 1 byte ... optN: string 0: 1 byte valueN: string 0: 1 byte |
OACK | Opcode: 2 bytes opt1: string 0: 1 byte value1: string 0: 1 byte ... optN: string 0: 1 byte valueN: string 0: 1 byte |
blksize
RFC 2348ではオプションとしてblksizeが定義されています
このオプションで指定したブロックサイズでファイルを転送します
名前 | 有効な値 |
---|---|
blksize | 8-65464 |
ロールオーバー
TFTPで転送できるファイルサイズはブロックサイズ×65536が限界です
ブロックサイズは512 bytesの場合は32MBです
この限界を解決するための機能がロールオーバーです
中身は簡単で65536番目のブロック送信後に0番目のブロックを送信するだけです
実装
概要
大雑把なシーケンスは以下です
おまけ:速度比較
blksize=512,1468,8192で速度比較します
参考にscp(sftp)も加えます
測定環境
測定手順
ファイルの生成
head -c 1000000000 /dev/urandom > file1g
tftp blksize=512
$ curl tftp://192.168.1.101/file1g --tftp-blksize 512 -o file1g
tftp blksize=1468
$ curl tftp://192.168.1.101/file1g --tftp-blksize 1468 -o file1g
tftp blksize=8192
$ curl tftp://192.168.1.101/file1g --tftp-blksize 8192 -o file1g
scp(sftp)
$ scp -v 192.168.1.101:/home/ubuntu/file1g .
結果
ブロックサイズを大きくすることで性能低下する様子が確認できます
これはパケットの往復回数が減ることによる効果なはずなのでそれも確かめておきます
パケットの往復回数の削減率と転送時間の削減率を比較すると以下です
パケットの往復回数の削減が転送時間の削減に影響しているといってよさそうです
おまけのおまけ
ブロックの読み込みはブロックを送信するタイミングで別にいい気がしたので変更してみました
若干転送時間の増加が見えます
微妙なところですが許容範囲かなと思います
メモリ使用量の観点から今後はこちらの実装で進めていきます
Discussion