2010年12月22日水曜日

FreeBSD用virtioドライバ ステータスアップデート (2010/12/21)

10月頃に作成したFreeBSD用virtioドライバですが、その後もボチボチと作業を続けております。

これまで開発した範囲では性能問題なども一通り解決しているので、
もうすこしコードを整理して、 -STABLE 品質として必要な機能を追加したら
ドライバをメーリングリストなどに投稿したいと思っています。

各ドライバのステータスなどについて紹介します。



■ 機能ドライバのステータス


  • virtio-net


    • vCPU = 1, 2の場合に e1000 エミュレーションよりスループットが高くなるよう改善

    • シャドウページテーブル環境下におけるパフォーマンス悪化を改善

    • メモリ管理方式の変更(malloc→bus_dmaによる連続したGuest-Physicalメモリ空間の確保)

    • OSにより確保されるmbufへの直接データ受信、バッファの再利用による高速化

    • 途中: Merged RX Buffers

    • 未: Hardware Checksum Offload

    • 未: GSO

    • 未: TSO

    • 未: Promiscous mode support, MAC Address filtering, Tagged VLAN Support

    • 未: MSI-X support

    • 未: Driver Media Status/Statics support

  • virtio-blk (新たに実装)


    • vCPU = 1, 2 の場合に SCSI Emulation よりも高性能、かつ CPU 負荷が低下するよう実装

      ※ qemu-kvm + FreeBSD は相性が悪いらしく、これだけでは性能は不十分

    • 済: VIRTIO_BLK_T オペレーション (ディスクへの単純読み書き)

    • 済: FLUSH オペレーション

    • 未: SCSI Device Passthrough

その他 Memory Balloon, Console は未着手

テープデバイス/dev/rmt/Xのデバイス番号をリセットする

Solaris 環境でテープデバイスを認識させる場合、基本的には /dev/rmt/0 から 1, 2, 3, ... と順番に番号が振られます。

しかし、機器移設時にテープドライブの接続先ポートを間違えたり、テープドライバの個体 ID が変わったりすると、「それまではとは違うテープドライブ」と認識され、意図せず /dev/rmt/1, /dev/rmt/2, ... とデバイス番号が進んでしまう場合があります。

このような場合には、まず /dev/rmt/ 以下にあるデバイスファイルを削除した後にテープドライブを接続して再起動すると、 Solaris 起動時にドライバ?がテープのデバイスファイルを適切に作成しなおしてくれます。



# cd /dev/rmt
# rm 0*                     ※チキンなので * ではなく 0* などとしました:p
# rm 1*
# shutdown -y -g0 -i6

システム起動時のテープドライブがどのデバイス名で認識されているかは cfgadm -al コマンドにて確認できます。

2010年12月5日日曜日

FreeBSD + KVMの環境でちょっと過ごしてみてわかってきたノウハウ(1)

最近 FreeBSD 用の virtio ドライバに割と情熱を注いでいるのですが(そろそろ公開したい!)、
ドライバの性能が出ないという状況になって調査したときに多少ノウハウが得られたのでメモがてら掲載しておきます。

まずの一つ目のネタ。kvm_statコマンド。

kvm statistics

 efer_reload                  0       0
 exits                401230913    2152
 fpu_reload               52997       0
 halt_exits           133189538     757
 halt_wakeup            5259576      15
 host_state_reload    170030018     977
 hypercalls                   0       0
 insn_emulation       252392427    1359
 insn_emulation_fail          0       0
 invlpg                 2684292       0
 io_exits               4130425      17
 irq_exits              8935347      39
 irq_injections         3195682       0
 irq_window                   0       0
 largepages                   0       0
 mmio_exits            28482276     179
 mmu_cache_miss          698023       0
 mmu_flooded              40079       0
 mmu_pde_zapped          216076       0
 mmu_pte_updated         180285       0
 mmu_pte_write          1931218       0
 mmu_recycled                 0       0
 mmu_shadow_zapped       696204       0
 mmu_unsync                 877       0
 nmi_injections               0       0
 nmi_window                   0       0
 pf_fixed               4719781       0
 pf_guest                817765       0
 remote_tlb_flush        234452       0
 request_irq                  0       0
 signal_exits                 0       0
 tlb_flush              4903428       0

性能が出ていない場合には非常に参考になる内容です。ソースコードなどを見て何をしてくれているのか調査したわけではないのですが・・・





exits
発生したVMEXITすべての回数を示します。VMEXITとはIntel VT/AMD-VのCPU仮想化支援技術においてVMを実行し、何らかの理由(I/Oとかメモリ管理で何かがおきてVMMの介入が必要になったとか、タイムスライスを使い切ったとか色々)によりゲストを停止させた回数になります。仮想化支援技術があったとしてもVMMモード/ゲストモードの切り替えは非常にコストの高いものなので、これをいかに削減するかがポイントになります。



insn_emulation
それまでに発生したハードウェアエミュレーションの回数?を示しているようですが、細かいことは未調査。

io_exits

I/Oポートに対するアクセスで発生したVMEXITの回数を示します。
この値が大きくなる場合はハードウェアへのI/Oが頻発しており
性能劣化につながっていることが予想されます。
このような操作は全てVMEXITを引き起こしますので、いかにI/Oポートアクセスなどを少ない回数で済まさせるかが、VMの実質実効時間をのばすためにVMEXIT回数を削減するという観点で気になる数字です。

irq_exits

VMの実行中、物理ハードウェアにからの割り込みによってVMEXITした回数を示しているようです。この数字が大きい場合は物理ハードウェア側のIRQ割り込みをいかに減らすかの検討が必要になりそうです……。

irq_injections

ハードウェアエミュレータ(qemu-kvm)がVMに対して発行した割り込みの回数を示します。
IRQを使用している場合、IRQが発生すると、IRQをシェアするデバイスドライバ群が
ISR(Interrupt Status Register)をポーリングします。
このため割り込み回数×IRQ・・・と、共有するデバイス数が多いほどVMEXITの発生回数も増加にも繋がることから、ドライバを作るのであればこれをいかに低く抑えるかがポイントになります。

mmio_exits

メモリマップドI/OのためのVMEXIT回数です。

mmu_pte_write

シャドウページテーブル利用時、VM内のページテーブルのエントリ(Page Table Entry)を更新した数を示すようです。この値は、たとえばゲストOS上でmalloc()やfree()を行った場合にも実装次第で発生します。値が大きい場合は仮想マシン上のメモリ管理機構について再検討する余地があると言えます。この値はEPT/NPTが利用できないハードウェアでシャドウページテーブルによる負荷を見るのに利用できます。ここはゲスト内のプログラムのメモリ管理を工夫することで削減が可能です。ドライバなどであれば普段利用中にゼロから動かさせない、ぐらい高い目標を持ってもよいでしょう。


2010年10月20日水曜日

virtio for FreeBSD: Current Status (2010/10/20)

Hello World!
I decided to write virtio frontend drivers for FreeBSD because I wanted to understand how virtio works.
My virtio-net drivers began to work in the middle of October, so I'm guessing that I would offer the driver for FreeBSD community.
Actually there are some tasks to do before release it, so I need some time (and some help:).


Current Status (virtio-net)

  • virtio-net driver is working on a 1vCPU virtual machine. Tested more than 300GB of TX and RX.

  • almost same performance with e1000 (check out the graph below)

  • no offload functions provided (I think it is not so needed now)


Development Environment

  • Host: Fedora 14 alpha x86_64

  • Guest: FreeBSD 8.1-RELEASE, amd64


Least Required Tasks to offer this

  • non-indirect table mode support (needs test and debug)

  • split virtio PCI device framework and virtio-net driver

  • SMP support


If you're interested in development of virtio drivers in FreeBSD, please
contact me. I'm not a good kernel-hacker (actually this is my first
work for kernel mode program and also my first C work), so any help are
welcome.

vm162# ifconfig
em0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
        options=209b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,WOL_MAGIC>
        ether 52:54:00:1f:61:0d
        inet 192.168.44.162 netmask 0xfffffe00 broadcast 192.168.45.255
        media: Ethernet autoselect (1000baseT <full-duplex>)
        status: active
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
        options=3<RXCSUM,TXCSUM>
        inet6 fe80::1%lo0 prefixlen 64 scopeid 0x2
        inet6 ::1 prefixlen 128
        inet 127.0.0.1 netmask 0xff000000
        nd6 options=3<PERFORMNUD,ACCEPT_RTADV>

vm162# make load
/sbin/kldload -v /usr/src/sys/dev/xen/virtio/virtio_pci.ko
virtio_pci0: <virtio-net Virtual Network Interface> port 0xcb00-0xcb1f mem 0xf2054000-0xf2054fff irq 11 at device 8.0 on pci0
virtio_pci0: assigning PCI resouces: <1>mem <0>ioport <0>irq callback
virtio_pci0: [GIANT-LOCKED]
virtio_pci0: [ITHREAD]
vn0: Ethernet address: 52:54:00:1f:61:0e
Loaded /usr/src/sys/dev/xen/virtio/virtio_pci.ko, id=2

vm162# ifconfig vn0 up
vm162# ifconfig vn0 192.168.90.1 255.255.255.0
vm162# ifconfig
em0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
        options=209b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,WOL_MAGIC>
        ether 52:54:00:1f:61:0d
        inet 192.168.44.162 netmask 0xfffffe00 broadcast 192.168.45.255
        media: Ethernet autoselect (1000baseT <full-duplex>)
        status: active
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
        options=3<RXCSUM,TXCSUM>
        inet6 fe80::1%lo0 prefixlen 64 scopeid 0x2
        inet6 ::1 prefixlen 128
        inet 127.0.0.1 netmask 0xff000000
        nd6 options=3<PERFORMNUD,ACCEPT_RTADV>
vn0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
        ether 52:54:00:1f:61:0e
        inet 192.168.90.1 netmask 0xffffff00 broadcast 255.255.255.0

vm162# ping 192.168.90.2
PING 192.168.90.2 (192.168.90.2): 56 data bytes
64 bytes from 192.168.90.2: icmp_seq=0 ttl=64 time=3.696 ms
64 bytes from 192.168.90.2: icmp_seq=1 ttl=64 time=1.004 ms
64 bytes from 192.168.90.2: icmp_seq=2 ttl=64 time=1.051 ms
64 bytes from 192.168.90.2: icmp_seq=3 ttl=64 time=1.044 ms
64 bytes from 192.168.90.2: icmp_seq=4 ttl=64 time=1.218 ms
64 bytes from 192.168.90.2: icmp_seq=5 ttl=64 time=0.970 ms
^C
--- 192.168.90.2 ping statistics ---
6 packets transmitted, 6 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.970/1.497/3.696/0.986 ms

vm162# iperf -c 192.168.90.2
------------------------------------------------------------
Client connecting to 192.168.90.2, TCP port 5001
TCP window size: 32.5 KByte (default)
------------------------------------------------------------
[  3] local 192.168.90.1 port 15185 connected with 192.168.90.2 port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0-10.7 sec   142 MBytes   112 Mbits/sec
vm162#


performance comparison between fxp(e1000) and vn(virtio)


2010年10月12日火曜日

FreeBSD用virtioドライバを作ってみた

なんとなくノリで「virtioのドライバを書いてみたくなった」ので9月末から作業を開始したのですが、この週末で大体動くようになりました。


コードが整理できたら、FreeBSDソースツリーへのコミット目指して頑張ってみますかねぇ。まぁ、予定は未定です。また、実際にドライバが書ける程度まではvirtioを研究したので、また機会を見て情報共有できればと思っています。


■ どんなかんじ?



見てもらうのが早いですよね。こんなかんじ。

vm162# ifconfig
em0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
        options=209b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,WOL_MAGIC>
        ether 52:54:00:1f:61:0d
        inet 192.168.44.162 netmask 0xfffffe00 broadcast 192.168.45.255
        media: Ethernet autoselect (1000baseT <full-duplex>)
        status: active
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
        options=3<RXCSUM,TXCSUM>
        inet6 fe80::1%lo0 prefixlen 64 scopeid 0x2
        inet6 ::1 prefixlen 128
        inet 127.0.0.1 netmask 0xff000000
        nd6 options=3<PERFORMNUD,ACCEPT_RTADV>

vm162# make load
/sbin/kldload -v /usr/src/sys/dev/xen/virtio/virtio_pci.ko
virtio_pci0: <virtio-net Virtual Network Interface> port 0xcb00-0xcb1f mem 0xf2054000-0xf2054fff irq 11 at device 8.0 on pci0
virtio_pci0: assigning PCI resouces: <1>mem <0>ioport <0>irq callback
virtio_pci0: [GIANT-LOCKED]
virtio_pci0: [ITHREAD]
vn0: Ethernet address: 52:54:00:1f:61:0e
Loaded /usr/src/sys/dev/xen/virtio/virtio_pci.ko, id=2

vm162# ifconfig vn0 up
vm162# ifconfig vn0 192.168.90.1 255.255.255.0
vm162# ifconfig
em0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
        options=209b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,WOL_MAGIC>
        ether 52:54:00:1f:61:0d
        inet 192.168.44.162 netmask 0xfffffe00 broadcast 192.168.45.255
        media: Ethernet autoselect (1000baseT <full-duplex>)
        status: active
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
        options=3<RXCSUM,TXCSUM>
        inet6 fe80::1%lo0 prefixlen 64 scopeid 0x2
        inet6 ::1 prefixlen 128
        inet 127.0.0.1 netmask 0xff000000
        nd6 options=3<PERFORMNUD,ACCEPT_RTADV>
vn0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
        ether 52:54:00:1f:61:0e
        inet 192.168.90.1 netmask 0xffffff00 broadcast 255.255.255.0

vm162# ping 192.168.90.2
PING 192.168.90.2 (192.168.90.2): 56 data bytes
64 bytes from 192.168.90.2: icmp_seq=0 ttl=64 time=3.696 ms
64 bytes from 192.168.90.2: icmp_seq=1 ttl=64 time=1.004 ms
64 bytes from 192.168.90.2: icmp_seq=2 ttl=64 time=1.051 ms
64 bytes from 192.168.90.2: icmp_seq=3 ttl=64 time=1.044 ms
64 bytes from 192.168.90.2: icmp_seq=4 ttl=64 time=1.218 ms
64 bytes from 192.168.90.2: icmp_seq=5 ttl=64 time=0.970 ms
^C
--- 192.168.90.2 ping statistics ---
6 packets transmitted, 6 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.970/1.497/3.696/0.986 ms

vm162# iperf -c 192.168.90.2
------------------------------------------------------------
Client connecting to 192.168.90.2, TCP port 5001
TCP window size: 32.5 KByte (default)
------------------------------------------------------------
[  3] local 192.168.90.1 port 15185 connected with 192.168.90.2 port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0-10.7 sec   142 MBytes   112 Mbits/sec
vm162#


■ ベンチマーク

非常にいい加減なベンチマークですが、デフォルト設定の e1000 エミュレーションより微妙に速いようです。





e1000 オフロードエンジン等を ON/OFF すると性能が変わるようなので、まぁだいたい同じぐらいのパフォーマンスが出ていると考えればよさそうです。

■ 実装状況


  • ロック皆無!たぶん……いや、間違いなく、SMPだと即死します。

  • virtio PCIインターフェイスとvirtio-netがまだ綺麗に分離できていない。

  • キャパビリティ (features bit)のほとんどは未実装

■ その他今後の課題


  • virtio デバイスを実装するためのフレームワーク検討

  • ハードウェア チェックサム、その他キャパビリティのサポート

  • 一部 GPL ライセンスされたコードが含まれるため除去

  • 安定性の向上

  • チューニング

■ 作業環境


  • Host: Fedora 14: Fedora release 14 (Branched) Alpha Release, x86_64

  • Guest: FreeBSD 8.1-RELEASE, amd64

2010年9月23日木曜日

shadow_memory

 シャドウページテーブルのサイズ(MB)を指定します。明示的に指定しない場合
は必要な容量が自働確保されます。


■ ドメイン


  • 完全仮想化ドメイン(HVM)


■ 書式

shadow_memory=<n>


■ 必要なシャドウメモリの容量


  • 準仮想化ドメイン …… 不要

  • HVM ドメイン(x86、x86_64)…… 256 ×仮想CPU 数+ 2 ×最大メモリ量(MB)ページ
      (1 ページ= 4KB)

  • HVM ドメイン(IA-64)…… 不要


■ 例

memory=1024
shadow_memory=8


■ 注意点


  • 本情報はXen 3.4.0時点の内容です



xen_platform_pci

Xen プラットフォームPCI デバイスの有効・無効を指定します。本デバイスは、Xenのパラバーチャルドライバの利用するために必要です。

■ ドメイン


  • 完全仮想化ドメイン(HVM)


■ 書式

xen_platform_pci=<n>

■ <n>の値


  • 1 …… 有効

  • 0 …… 無効


■ 例

xen_platform_pci=1


■ 注意点


  • Xen プラットフォームPCI デバイスは、HVM ドメイン上のゲストOS がXen ハイパーバ
    イザと通信するために使用するものです。



2010年9月22日水曜日

PyGRUBで快適!OpenSolaris on Xenライフ

PyGRUBとは、Xenの準仮想化ドメイン(PV)で利用できるブートローダです。PyGRUBを使用すると、ドメイン起動時にゲストOSのディスクイメージ上から必要なファイル(カーネルおよびRAMディスクイメージ)を読み出して起動することができます。これにより、ドメイン起動にあたりdomain-0のファイルシステム上へゲストのカーネルファイルなどに事前準備する必要がなくなりkernel行とextra行に具体的な値を記述する必要がなくなります。


PyGRUBは多数のファイルシステムをサポートしており、最近のバージョンでは、なんとOpenSolarisのZFS上のGRUB設定ファイルを使って純仮想化ドメインを起動できます。




■ PyGRUBとpv-grub

同種のツールとしてはpv-grubがあります。PyGRUBもpv-grubも基本的にやってくれる事は同じなのですが、PyGRUBはPythonベースのもどきスクリプトであるのに対してpv-grubは準仮想化ドメイン向けにportされたGRUB(つまり、ブートローダの機能としてはx86の物理マシンで使われているものをXenに対応させたもの)である、という違いがあります。ただ、Xen 3.4.2に含まれるpv-grubではZFSを扱えないようです(しっかり確認したわけではないのですが)。

なお、現在ではPyGRUBの利用は推奨されていません。なぜなら、PyGRUBはdomain-0上で動作するプログラムであり、細工されたdomain-Uイメージを処理させることによりdomain-0への干渉を許す可能性があるためです。pv-grubはブートローダの処理自体がDomain-U上で動作するため、いくらかセキュリティ面において優位性があります。


■ OpenSolaris のブートに必要なファイルとパラメータ


OpenSolarisをPVドメインとして動作させる際に必要なものとして、下記のファイルとパラメータがあります。


unix ファイル …… OpenSolarisのカーネル

boot_archive ファイル …… RAMイメージ
ルートファイルシステムとしてマウントするファイルシステムの位置情報


カーネル、およびRAMイメージのファイルはOpenSolarisのファイルシステム上にあるものですので、これをLinuxで動作するdomain-0のファイルシステム上にコピーするのはそれほど難しいことではありません。また、ルートファイルシステムの場所は、OpenSolarisのファイルシステム上にあるGRUBの設定ファイルを見れば解決可能です。


しかし、実際に運用をはじめると、カーネルやRAMイメージをゲストのファイルシステムから適宜抽出したり、もしくはBoot Environmentを作成/更新するたびにbootfsの値をドメインの定義ファイルに書くのは煩雑な作業となります。


■ PyGRUBを使ったOpenSolarisの起動


では早速PyGRUBを使ってOpenSolarisを起動してみましょう。以下にドメイン定義ファイルの記述例を示します。


PyGRUBを使用しない場合の例(参考)

kernel="/boot/os200811/unix"
ramdisk="/boot/os200811/boot_archive"
extra= '/platform/i86xpv/kernel/amd64/unix –B 
    zfs-bootfs=rpool/52,bootpath="/xpvd/xdf@0:a"’

PyGRUBを使用する場合の例

bootloader="/usr/bin/pygrub"


いかがでしょうか?ドメイン定義ファイルの内容が非常にすっきりしたことでしょう。

この方法を使うと、OpenSolarisのPVドメインを、ゲストのファイルシステム上にある最新カーネル、およびbeadmで実際にアクティブ化されているBEから自動的に起動することが可能です。

■ Live CDの起動にも使える

PyGRUBはZFSをサポートしていますが、そのほかISO9660もサポートしていますので OpenSolaris LiveCD をPVで起動するためにも使えます。

access_control

ドメインのセキュリティポリシーおよびラベルを指定します。


■ ドメイン


  • 準仮想化ドメイン(PV)

  • 完全仮想化ドメイン(HVM)


■ 書式

access_conrtol='policy=<policy>,label=<label>'


■ パラメータ


  • policy …… ドメインに割り当てるセキュリティポリシー

  • label …… ドメインのラベル名


■ 注意点


  • 本情報はXen 3.4.0時点の内容です


2010年8月9日月曜日

オープンソース系仮想マシンで利用できるお手軽なネットワーク高速化設定

■ QEMUには同じ目的の仮想デバイス実装が複数ある

オープンソースで VMware 同様に IA をエミュレーションできるソフトウェアとしては QEMU, Xen, KVM, VirtualBox など多くのものがありますが、これらのほとんどは QEMU 由来のデバイスエミュレータがベースとなっています。

QEMU にはタイマ、ディスクコントローラ、ビデオコントローラ、ネットワークコントローラ、シリアルインターフェイス、サウンドカード、タイマ… PC/AT 互換機をエミュレーションする上で必要となるハードウェアのエミュレーションが一通り揃っていますが、実はネットワークコントローラやサウンドカードは複数の実装があり、設定によって使い分けることができます。

今回は、その中でも実用面でもメリットが多いにあるネットワークコントローラを取り上げます。



■ Realtek 8139 とその功罪

QEMU 由来の仮想マシンソフトウェアのほとんどは、標準の設定では Realtek 8139 によって仮想ネットワークを提供します。

Realtek 8139 は2000年以前でも比較的安価に手に入るネットワークカードだったため広く流通しています(いました)。ただしハードウェアの性能としてはそれほど高い物ではなく、高トラフィックには耐えられないことが知られています。ハードウェアデザイン上の問題について興味があればFreeBSD の rl ドライバのソースコード に書かれたメッセージを見るとよいでしょう。

しかし、 Realtek 8139 は結果的に現在実行される IA 向けのほとんどの OS にドライバが含まれています(Solarisなど、標準でドライバを持たないOSも幾つかはあります)。また、PCIバスに対応した製品のため、ネットワークチップの元祖とも言える NE2000 系と違い面倒な設定も不要です。このため、「仮想マシンとして Realtek 8139 をエミュレートしておけば大抵の場合ゲスト OS が認識できる」という利点があるのです。ただ、この場合でもネットワークのパフォーマンスはそれほど期待できません。

具体的に Realtek 8139 をエミュレーションしたゲスト OS が出す性能を iperf で計ってみました。なお、この結果は Q8400 プロセッサ、 Xen 開発ツリー最新版の上で 1CPU 構成の Windows xp 環境を作って計測しています。仮想CPUの性能で頭打ちになっているため、この値が上限かどうかについては確認していません。

C:\>iperf -c 192.168.44.75 -w 4M
------------------------------------------------------------
Client connecting to 192.168.44.75, TCP port 5001
TCP window size: 4.00 MByte
------------------------------------------------------------
[1912] local 192.168.44.77 port 3318 connected with 192.168.44.75 port 5001
[ ID] Interval       Transfer     Bandwidth
[1912]  0.0-10.5 sec  73.1 MBytes  58.3 Mbits/sec

■ QEMU がエミュレートする Intel PRO/1000MT Desktop

QEMU がエミュレートできる他のネットワークコントローラとして Intel PRO/1000MT Desktop 相当、 PCI もしくは PCI-X に刺さる初期の Intel 製コントローラ 82540EM があります。このモデルも決してパフォーマンスが高いものではないのですが(ノートパソコンの GbE NIC が PCI Express 経由で接続されている現代としてはレガシなものといわざるを得ないでしょう)、 Realtek 8139 と比べると OS にかかる負荷が少ない設計になっています。これはつまり、仮想マシンでエミュレーションする場合に、 Realtek 8139 と比べるとゲスト OS の負荷を低減でき、当然ながらその相手となるハードウェアエミュレーションの負荷も低くなる、ということです。

C:\>iperf -c 192.168.44.25 -w 4M
------------------------------------------------------------
Client connecting to 192.168.44.25, TCP port 5001
TCP window size: 4.00 MByte
------------------------------------------------------------
[1912] local 192.168.44.77 port 3334 connected with 192.168.44.25 port 5001
[ ID] Interval       Transfer     Bandwidth
[1912]  0.0-10.1 sec   474 MBytes   394 Mbits/sec

iperf の結果(先ほどと同条件で、ネットワークカードのデバイスモデルのみ変更)を見ればそのパフォーマンス差は明らかです。

今回の検証に利用したゲストOS (Windows xp SP3)ではコントローラのドライバを標準で持っておらず認識できなかったため、 Intel PROSet のドライバをダウンロードしインストールしました。つまり OS によってはドライバを別途準備する必要がある、ということです。

これは単なる手間の問題もありますが、もうひとつの問題としてドライバのライセンス問題もあります。たとえば今回ダウンロードした Intel のドライバは License Agreement において「 Intel のコンポーネントとの組み合わせでのみ使用を許可する」と明記されており、 QEMU との組み合わせは本当はライセンス違反です。とはいえ、では QEMU が他にエミュレーションする CirrusLogic のビデオカードは大丈夫なのかと言えば、確認してみれば、同じような問題を抱えている可能性は高いでしょう。

Linux や FreeBSD などでは、上記の問題は無視できると言えます。 GPL ないしは BSD ライセンスで自由に利用できるドライバが標準で付属されていますので、上記の問題はどちらも関係ないと言えるでしょう。

■ Xen の場合の設定方法

思いのほか前置きが長くなってしまいましたが、実際にデバイスモデルを切り替えるのは簡単です。 Xen の仮想マシン定義ファイルでデバイスモデルを変更する場合は、 vif 行の model= パラメータを指定します。

Realtek 8139 をエミュレーションする場合

vif = [ 'type=ioemu, bridge=xenbr0, model=rtl8139' ]

Intel 82540EM をエミュレーションする場合

vif = [ 'type=ioemu, bridge=xenbr0, model=e1000' ]

■ ちなみに....

Xen で利用できる GPLPV Drivers に含まれるネットワークドライバを利用した場合は、さらに高いパフォーマンスを、より低い CPU 負荷で達成できます。仮想マシン技術にあわせた専用インターフェイスにはさらなる性能面の優位点があるということがが判ります。

C:\>iperf -c 192.168.44.71 -w 4M
------------------------------------------------------------
Client connecting to 192.168.44.71, TCP port 5001
TCP window size: 4.00 MByte
------------------------------------------------------------
[1912] local 192.168.44.77 port 3277 connected with 192.168.44.71 port 5001
[ ID] Interval       Transfer     Bandwidth
[1912]  0.0-10.0 sec   518 MBytes   432 Mbits/sec

2010年6月14日月曜日

ユーザプロファイルが破損したWindows 7環境の復旧

Windows 7 + BitLocker 環境のユーザプロファイルが破損してログインできなくなったため、ユーザプロファイルを再作成して復旧しました。その時のメモ。

■ セーフモード + プロンプトで起動

BIOS POST画面から Windows 7 のスプラッシュロゴに切り替わる瞬間に F8 キーを押し起動画面を表示します。 BitLocker によりHDD 全体を保護している場合、このタイミングで BitLocker の回復キーを要求されます。

■ ログインし裏口ユーザを作成

コマンドプロンプトだけであればユーザプロファイルが破損していても問題なくログインできました。ここで DOS プロンプトより裏口ユーザを作成し、管理権限を与えておきます。

C:\Users\hasegaw>> net user hasegaw2 /add
C:\Users\hasegaw>> net user hasegaw2 password
C:\Users\hasegaw>> net localgroup administrators hasegaw2 /add

■ 普通に起動し、 hasegaw ユーザを再作成

この段階で、これまで使っていた hasegaw というユーザだけでなく hasegaw2 によるログインも可能な状態になっています。

hasegaw2 でログインした後に下記の順序で作業します。


  • C:\Users\hasegaw を C:\Users\hasegaw.old にリネーム

  • コントロールパネル(もしくはnet user)で hasegaw ユーザをいったん削除、再作成

  • hasegaw ユーザでログイン


  • 必要なファイルを hasegaw.old/ から移動などする

Windows xp ではユーザプロファイルのフォルダ自体がなくなっていれば自動的に再生成されたかと思いますが Windows 7 ではダメだったのでユーザごと再作成しました。 SID が変わってしまいますが、まぁローカルユーザですし特に問題はないでしょう。


■ プロファイル破損時に備えて

あらかじめ裏口ユーザは一つぐらい作っておいたほうがよいかもしれませんね。。。



2010年5月12日水曜日

PuTTYによるSSH接続でNATタイムアウトを防止するには

SSHクライアントを利用する場合に、しばらく放置すると接続が切れてしまう経験はありませんか?

IPマスカレードなどのNAT環境下にいる場合、もしくはそのようなホストへ接続する場合に、TCPセッションがNATテーブルから消えることによりセッションがリセットされる場合があります。これを防止する場合は PuTTY の場合「接続の設定」で下記設定を60秒などに設定します。

Keepalive の間隔 (0秒でオフ)

これにより、 PuTTY が定期的にダミーパケットを送出するため TCP セッション切れを防止できます。

2010年2月25日木曜日

autofsを使ってISOファイルを自動マウントする

Linux の autofs で、設定値を書いたファイルのほかにスクリプトが使えるということに2~3年ぐらい前に気づいたので、「ISOファイルを自動マウントする仕組みを作ってやろう」と思っていました。今頃ながら試しに実装してみましたので、ご紹介します。

/etc/auto.master

#
# $Id: auto.master,v 1.4 2005/01/04 14:36:54 raven Exp $
#
# Sample auto.master file
# This is an automounter map and it has the following format
# key [ -mount-options-separated-by-comma ] location
# For details of the format look at autofs(5).
#/misc  /etc/auto.misc --timeout=60
#/smb   /etc/auto.smb
#/misc  /etc/auto.misc
#/net   /etc/auto.net
/export /etc/auto.export
/dvd    /etc/auto.dvd --timeout=60


/etc/auto.dvd (-r-xr-xr-x)

#!/usr/bin/perl

($key) = @ARGV;
$dvd = sprintf('/export/archives/ISO/%s.ISO', $key);

if (-e $dvd) {
        print "         -fstype=auto,ro,loop    :$dvd\n";
}


つかいかた。/dvd/≪ISOイメージのベースネーム≫ に cd すると、勝手にマウントされます。

hasegaw@vm245:~$ mount | grep dvd
automount(pid3743) on /dvd type autofs (rw,fd=4,pgrp=3743,minproto=2,maxproto=4)
hasegaw@vm245:~$ ls -l /dvd/MXXXXXX_FRONTIER_01
total 4
dr-xr-xr-x 2 4294967295 4294967295   40 2008-06-18 22:23 AUDIO_TS
dr-xr-xr-x 2 4294967295 4294967295 1028 2008-06-18 22:23 VIDEO_TS
hasegaw@vm245:~$ mount | grep dvd
automount(pid3743) on /dvd type autofs (rw,fd=4,pgrp=3743,minproto=2,maxproto=4)
/export/archives/ISO/MXXXXXX_FRONTIER_01.ISO on /dvd/MXXXXXX_FRONTIER_01 type udf (ro,loop=/dev/loop0)



用が済んだら --timeout 秒経過後、大体1分後にアンマウントされる。

hasegaw@vm245:~$ mount | grep dvd
automount(pid3743) on /dvd type autofs (rw,fd=4,pgrp=3743,minproto=2,maxproto=4)



この仕組みの利用例。HDD上にため込んだDVDイメージをiPodに変換する際に実際に入力したコマンドです。たくさんの ISO イメージをハシゴするような作業をバッチで仕掛る場合など、イメージのマウント・アンマウントが autofs が勝手に行うので意識する必要がありません。


$ for i in 01 02 03 04 05 06 07 08 09; do echo mkmp4_linux -d /dvd/MACROSS_FRONTIER_$i -p iPod; done

その他の応用としては Linux のインストール DVD をレポジトリにため込み、ディレクトリ移動のみで参照できる環境を提供を想定しています。

懸念事項としては、この仕組みの利用頻度が上がると loop デバイスを使い切ってしまい、自動マウントできなくなるトラブルが考えられます。その場合には /etc/modules.conf 等で loop デバイスの個数を増やすなどの対策が考えられます。



2010年1月24日日曜日

昼食の時間だけスクリーンセーバをデフラグツールに変更する(改良版)

昨日紹介したスクリーンセーバー切り替え VBScript をマイナーチェンジしました。

新しいスクリプトでは、すでにスクリーンセーバーが起動していた場合は、それを強制終了させます。ここれにより、以下のような挙動になります。(スクリーンセーバーの設定が10分の場合)


■ スクリーンセーバー切り替え時に、すでにスクリーンセーバーが動作している場合


  • 基準時間: スクリーンセーバーの変更、および既存スクリーンセーバの停止

    →画面がロックされる

  • +10分: 再度タイムアウトによりスクリーンセーバーが起動される


■ スクリーンセーバー切り替え時に、スクリーンセーバーが動作していない場合


  • ユーザーがロックもしくは放置してから 10 分後にタイムアウトによりスクリーンセーバーが起動される


これにより、タスク設定時間より早めに休憩に入ってしまったとしても、お昼には確実にデフラグスクリーンセーバーを起動するようになりました。

なお、前回は Auglogics Disk Defrag を使用していましたが、今回のスクリプトは MyDefrag (JkDefragの後継) 向けとしてあります。


MyDefrag
http://www.mydefrag.com/





'
' スクリーンセーバを auslogics disk defrag に設定する
'

SS_DEFRAG = "C:\WINDOWS\system32\MYDEFR~1.SCR"

HKEY_CURRENT_USER = &H80000001
strComputer = "."

Set objReg = GetObject("winmgmts:\\" & strComputer & "\root\default:StdRegProv")
strKeyPath = "Control Panel\Desktop"
objReg.CreateKey HKEY_CURRENT_USER, strKeyPath
objReg.SetStringValue HKEY_CURRENT_USER, strKeyPath, "SCRNSAVE.EXE", SS_DEFRAG

' すでに別のスクリーンセーバ(logon.scr)が動作していたら、そのスクリーンセーバーを
' ストップさせる。
Set objShell = CreateObject("Wscript.Shell")
r = objShell.Run("taskkill /F /IM logon.scr", 1, True)

昼食の時間だけスクリーンセーバをデフラグツールに変更する

こんにちわ。みなさんお仕事は順調でしょうか?

客先の業務量減少に伴い、残業規制やらお昼時間の消灯やらでテンションだだ下がりなブログ主です。お昼の時間 12:00 になるとオフィスの照明が強制消灯されるので、最近は時間どおりに食事に出ることが多くなりました。おかげでお陰で最近、体重がいいかんじにry(関係ない

ところで、お昼の時間って、PCの電源が入ったままなので、この間にデフラグを流してる人なども多いのではないでしょうか。私は別にデフラグジャンキーじゃないのですが、職場のセキュリティポリシーに準じて導入しているツールがファイルをズタズタにしてくれるので、昼休みはデフラグすることにしようと思いました。



  • 使用するデフラグツール

  • スクリプトの作成とテスト

  • タスクの設定

  • 問題が発生……



■ 使用するデフラグツール

ほかに JkDefrag などの選択肢もあるわけですが、Auslogics Disk Defrag が最近のお気に入りなので、このスクリーンセーバーを使いたいと思います。

Auslogics Disk Defrag Screen Saver

http://www.auslogics.com/en/software/disk-defrag-screen-saver/

ただ、私は普段からデフラグスクリーンセーバーを設定するほどのデフラグジャンキーではありませんし、外出先でデフラグがかかると鬱陶しいので、時間指定でスクリーンセーバーを変更することにしました。

■ スクリプトの作成とテスト

まず、スクリーンセーバーを変更する VBScript を 2 つ書きます。

C:\hasegaw\bin\TASK_SCREENSAVER_CHANGER_DEFRAG.vbs …… スクリーンセーバをデフラグツールに

C:\hasegaw\bin\TASK_SCREENSAVER_CHANGER_LOGON.vbs …… スクリーンセーバを普段のものに

以下にスクリプトの例を示します。

C:\hasegaw\bin\TASK_SCREENSAVER_CHANGER_DEFRAG.vbs

'
' スクリーンセーバを auslogics disk defrag に設定する
'

SS_DEFRAG = "C:\Windows\aus_ddss.scr"

HKEY_CURRENT_USER = &H80000001
strComputer = "."

Set objReg = GetObject("winmgmts:\\" & strComputer & "\root\default:StdRegProv")
strKeyPath = "Control Panel\Desktop"
objReg.CreateKey HKEY_CURRENT_USER, strKeyPath
objReg.SetStringValue HKEY_CURRENT_USER, strKeyPath, "SCRNSAVE.EXE", SS_DEFRAG

C:\hasegaw\bin\TASK_SCREENSAVER_CHANGER_LOGON.vbs

'
' スクリーンセーバを login.scr に設定する
'

SS_DEFRAG = "C:\Windows\SYSTEM32\logon.scr"

HKEY_CURRENT_USER = &H80000001
strComputer = "."

Set objReg = GetObject("winmgmts:\\" & strComputer & "\root\default:StdRegProv")
strKeyPath = "Control Panel\Desktop"
objReg.CreateKey HKEY_CURRENT_USER, strKeyPath
objReg.SetStringValue HKEY_CURRENT_USER, strKeyPath, "SCRNSAVE.EXE", SS_DEFRAG

これらのスクリプトを書いたら、スクリプトが期待通りに動作するかを確認します。


  • 画面のプロパティーを開き、スクリーンセーバーを なし に設定してプロパティを閉じる

  • TASK_SCREENSAVER_CHANGER_DEFRAG.vbs をダブルクリックする

  • 画面のプロパティーを開き、スクリーンセーバーがデフラグツールに設定されたことを確認

  • TASK_SCREENSAVER_CHANGER_LOGON.vbs をダブルクリックする

  • 画面のプロパティーを開き、スクリーンセーバーが普段のものに設定されたことを確認

■ タスクの設定

スクリプトが問題なく動作することを確認したら、続いて Windows のタスクとしてこれらのスクリプトを設定します。


  • TASK_SCREENSAVER_CHANGER_DEFRAG


    • 実行するプログラム …… TASK_SCREENSAVER_CHANGER_DEFRAG.vbs

    • 実行日時/頻度 …… 毎日11:50

    • その他設定 …… ログオン時以外は実行しない

  • TASK_SCREENSAVER_CHANGER_LOGON


    • 実行するプログラム …… TASK_SCREENSAVER_CHANGER_LOGON.vbs

    • 実行日時/頻度 …… 毎日13:00

    • その他設定 …… ログオン時以外は実行しない

  • TASK_SCREENSAVER_CHANGER_LOGON2


    • 実行するプログラム …… TASK_SCREENSAVER_CHANGER_LOGON.vbs

    • 実行日時/頻度 …… ログオン時

    • その他設定 …… ログオン時以外は実行しない

これで、毎日 11:50~13:00にスクリーンセーバが変わるようになりました。

■ 問題が発生……

その後、 Auglogic Disk Defrag のスクリーンセーバを実際に動かしてみて、問題が判明。

このデフラグスクリーンセーバー、実行中はデフラグ対象のファイルの名前がリアルタイムで表示されてしまいます。(^^;;;

この状態でついうっかり「...\秘蔵エロ\...」とか「履歴書.doc」※とかのファイル名を職場の人間に見られると大変なことになってしまうのでちょっと常用はきついなぁ……。スクリーンセーバの設定をみてもこの挙動は変えられないみたい。

※ エロとか履歴書とかはネタだとしても、顧客名などの情報を含むファイル名がスクリーンセーバーにより表示されている状態というのは、普通に考えてもちょっと……。開発元はどういう神経で作ってるんでしょうね。