パケット遅延問題 原因判明

パケット遅延の原因が分かった。

  • QEMU が受信しているパケット
  • Mona が受信しているパケット

が異なっていたことが原因。


より正確には Mona が virtio queue 中の最新パケットではなく過去のパケットを参照していた。
過去のパケットではあるが、一度も受信したことのないパケットであるから、外から見える現象が一見すると矛盾がない。そのため原因に到達するのに時間がかかった。

  • Mona が受け取った ICMP Request
  • Mona が応答した ICMP Reply
  • QEMU が TAP に write する ICMP Reply

の3つは全て同一かつ、ほぼおなじタイミングで行われていて外から見ると正常に見える。
でも実は

  • QEMU が受け取った ICMP Request(ここと)
  • Mona が受け取った ICMP Request(ここの間に数秒の開きがある)
  • Mona が応答した ICMP Reply
  • QEMU が TAP に write する ICMP Reply

のような構造になっていた。


反省点としては、送信時のバッファリングを疑ったのに、受信時のバッファリングが発生しているかもしれないことを考慮できていなかった点。
QEMU に手を入れてログを吐かせたところまでは良かった。そのときに TAP の read もついでに出力していたらすぐに分かっていただろう。


コードで言うと

Ether::Frame* rframe = readFrames_[readVring_->avail->idx % numberOfReadDesc_];

が間違いで

uint32_t id = readVring_->used->ring[index].id;
Ether::Frame* rframe = readFrames_[id / 2];

が正解。