vring の仕組みを理解 - virtio

contrib/Misc (rev 5343) でいくつかの実験を行った。virio の ring の仕組みを理解した。
以下は思いついた実験とその結果のメモ。
実験は全て Ether Frame 受信。(ARP broadcast と static ARP + telnet による IP )

  • ring->avail->idx = 1 、つまり受信バッファ1つの場合の状態変化
    • Guest に見えるもの:used->idx 0 => 1
    • Guest に見えないもの VMM 上で last_avail_index 0 => 1
      • これは次回の受信が last_avail_index から ring->avail->idx の間にあるバッファで行われることを意味する
  • Guest が Host に新たにバッファが利用可能になったことを知らせるにはどうしたら良いか?
    • avail->idx を increment すれば良い。
    • notify は必須ではないように見える
  • 1つ目のバッファを再利用して2つ目のバッファにすることは可能か?
    • 可能。
    • 1つ目が不要になった時点で vring->avail->ring[1] = 0 と vring->avail->idx ++ をすれば良い。
    • vring->avail->ring[1] = 0 は vring の 1番目の要素は desc[0] にあるよと言う意味
  • 通常は 1 vring 要素は [hdr] [data] の 2つの desc を消費するが [hdr] [data1] [data2] のような形は利用可能か?
    • 不可能。
    • 一見するとデータが書き込まれたかのように見えるが、Wireshark 上では届いていない。
  • [hdr1] [data1], [hdr2] [data2] のようなものは可能か?
    • 可能。これが想定される使い方。
    • ちなみに [hdr1] [data1] を受信し、そのバッファが不要になった時点で、すぐに avai->ring[n] の末尾にバッファを返却する方が行儀がよい
    • vring.num を超えないように剰余で idx を指定することを忘れないように(剰余を使うのは avail->ring への index だけ。avai->idx では不要)
  • 1受信毎に割り込みが来るのか?
    • 確実に来る。
    • last_used_idx が avail->used->idx と等しいという条件でスピンロックも可能だが割り込みを使うべき。
  • vring->used->idx は 1 つずつインクリメントされていくのか?
    • 違う。混み合っているときは一気に +2 されたりする。それを考慮する仕組みが必要。


苦労した甲斐あって全容がきちんと把握できた。明日からはドライバの設計に入る。
しかし virtio を触っている人は本当に少ないだろうな。アカデミックな人たちが触りだして情報が増えると良いのだけど。n