DropbearでSCPが動作しない
ssh_scp_thread スレッドで、バッファサイズ(32KB)よりリモートウィンドウサイズ(c->remote_window)が いつまでも小さいままなので、ファイル送信できていなかった。
buflen = 8192*4; ↓ buflen = min(c->remote_window, 8192*4);
という修正でOKそう。
こちらでも確認しました。大丈夫そうですね。
送信が開始されないことはなくなったようですが、送信途中で
} while (ret > c->remote_window);
のループが終わらないことがあるようです。
maya への返信
送信が開始されないことはなくなったようですが、送信途中で {{{ } while (ret > c->remote_window); }}} のループが終わらないことがあるようです。
そのときの c->remote_window の値はいくつでしたでしょうか? 最初の 32KMB が大きすぎるのかもしれません。
c->remote_window = 24514
で始まって、止まったところでは
ret = 24514 c->remote_window = 16430となっています。
ちなみに、6,920,986 バイトのファイルの 6,520,724 バイトで止まっています。
buflen = 8192*4; ↓ buflen = 8192*2;
上記のように、ssh_scp_thread()において、初期バッファサイズを半分にしたら、 9MB程度のファイル転送に成功しました。 この処置ではいかがでしょうか?
いまはbuflenの調整が最初の1回だけですが、c->remote_windowにあわせてbufのほうを増減するのは難しいでしょうか。
今回は16KB前後がしきい値になっているようですが、16KBより小さいところから上に回復しない場合には同様の現象が起こりそうです。また、余裕があるときにbufが増えれば転送レートが改善されるような気がするのですが、どうでしょう。
送信しようとしているデータが、リモートウィンドウサイズ(c->remote_window)よりはみ出している場合、 はみ出した分は遅延送信するしくみにしていることを思い出しました。 下記のdoループ自体、削除してしまってもよいような気がしますが、その結果どうなるでしょうか?
do { // socket or channelがクローズされたらスレッドを終わる if (pvar->socket == INVALID_SOCKET || c->scp.state == SCP_CLOSING || c->used == 0) goto abort; if (ret > c->remote_window) { Sleep(100); } } while (ret > c->remote_window);
という動きになりました。
それではダメですね。 doループは残しつつ、無限ループに陥らなければよいので、doループの中でカウンタを 設け、上限を超えたらループを抜けるようなしくみにするのはどうでしょうか?
count = 0; do { // socket or channelがクローズされたらスレッドを終わる if (pvar->socket == INVALID_SOCKET || c->scp.state == SCP_CLOSING || c->used == 0) goto abort; if (ret > c->remote_window) { Sleep(100); } count++; if (count > 100) break; } while (ret > c->remote_window);
こんなふうにするのはどうでしょうか。
// ファイルから読み込んだデータはかならずサーバへ送信する。 readlen = max(4096, min(buflen, c->remote_window)); ret = fread(buf, 1, readlen, c->scp.localfp); if (ret == 0) break; // remote_window が回復するまで待つ do { // socket or channelがクローズされたらスレッドを終わる if (pvar->socket == INVALID_SOCKET || c->scp.state == SCP_CLOSING || c->used == 0) goto abort; if (ret > c->remote_window) { Sleep(100); } // 10秒抜けられなかったら抜けてしまう count++; if (count > 100) { break; } } while (ret > c->remote_window);
なるほど、それはよさそうですね。 SCPのスループットは下がってないでしょうか?
手元での計測では、openssh では 10% くらい、dropdear では 100% くらいスループットが上がりました。
maya への返信
手元での計測では、openssh では 10% くらい、dropdear では 100% くらいスループットが上がりました。
了解しました。 お手数ですが、修正のコミットをお願いできますでしょうか?
最先端で修正確認が取れましたので、本件はクローズとします。 ご協力どうもありがとうございました。>mayaさん
Dropbear 2012.55(SSHサーバ)に対して、32KBを超えるファイルがSCP送信できない。