VT-xとかAMD-Vとかって,なんでいるん?
VMX(VT-xとかAMD-Vとか)ってなんで必要なのか,わからなかったので,調べてた.
仮想マシンモニタは,効率的に処理したいので,仮想プロセッサで処理する内容を実プロセッサでそのまま処理したい.そうしたときに,単に加算するとかならいいとしても,レジスタとか触るとかいくつかの命令には問題があるらしい.
プロセッサのPSW触るとかは,OSがトラップして特権で動かすのでOK.
センシティブ命令ってのがヤバイらしい.例えばレジスタ触るPOP, PUSHとかの命令らしくて,CPUの状態を触るのに特権じゃなくてOKなので困る.どうヤバイかというと,仮想プロセッサなんて実はないので,あるかのようにゲストOSがCPUに命令を発行しても実行できない.しかもセンシティブ命令は特権じゃなくてOKで,ユーザモードで動くので,仮想マシンモニタがトラップできない.(仮想マシンモニタ的には,加算命令とかと区別がつかない)
なのでこれを解決しようとすると,(1)センシティブ命令を事前に書き換えるか,(2)実行時に書き換えるか,(3)センシティブ命令を特権命令にする(仮想マシンモニタでトラップしてエミュレートする)かの3択で,あとはよくある話.
結局のところ,仮想プロセッサなんて無いのに,ゲストOSがマジで存在しているかのように使ってくるので(当然のことだけれど),整合性が取れるようにしなきゃいけないので出来るようにしたって話.
と思った.
見てたページ:
Kernel/VM Advent Calendar 38日目: 仮想化可能なアーキテクチャの要件とx86 - yuyarinの日記
第4回 x86プロセッサにおけるプロセッサ仮想化:エンジニアなら知っておきたい仮想マシンのしくみ|gihyo.jp … 技術評論社
第5回 x86プロセッサの仮想化支援機能Intel VT & AMD-V:エンジニアなら知っておきたい仮想マシンのしくみ|gihyo.jp … 技術評論社
env EDITOR=vipw vipwしたらエラーになる件について
面白いこと聞いたので調べてみた.
# env EDITOR=vipw vipw usage: vipw [-d directory] vipw: pw_edit(): No such file or directory
この2行のエラーについて.環境はFreeBSD 9.0-RELEASE.
vipwのソースコードは/usr/src/usr.sbin/vipw
# wc vipw.c 137 566 3804 vipw.c
なんとお手軽……(ゴクリ
vipw の概要は,初期化 → pw_init() → pw_lock() → pw_tmp() → pw_edit() -> pw_mkdb() → pw_fini() な感じ.vipw.c では EDITOR 環境変数を読まない.pw_hoge() は /usr/src/lib/libutil/pw_util.cにあるのでそっちをみる.
見てみると,EDITOR環境変数を読み込んで,無ければviを設定してる.
/usr/src/lib/libutil/pw_util.c 289 pw_edit(int notsetuid) 290 { ... 297 if ((editor = getenv("EDITOR")) == NULL) 298 editor = _PATH_VI;
その次はパスワードファイルを編集するプロセスを fork する.321 行目でエディタを起動.env EDITOR=vipw してるので,vipwに tempname を引数として与えて起動することになる.man vipw すれば分かる通り,vipw に -d オプション以外の引数はエラーになる.
これが1行目のエラー.
このときに errno が -1 になって,_exit() で子プロセス(env EDITORの方)の戻り値は -1 に.
/usr/src/lib/libutil/pw_util.c 289 pw_edit(int notsetuid) 290 { ... 309 switch ((editpid = fork())) { 310 case -1: 311 return (-1); 312 case 0: 313 sigaction(SIGINT, &sa_int, NULL); 314 sigaction(SIGQUIT, &sa_quit, NULL); 315 sigprocmask(SIG_SETMASK, &oldsigset, NULL); 316 if (notsetuid) { 317 (void)setgid(getgid()); 318 (void)setuid(getuid()); 319 } 320 errno = 0; 321 execlp(editor, basename(editor), tempname, (char *)NULL); 322 _exit(errno); 323 default: 324 /* parent */ 325 break; 326 }
vipw に戻って,switch(pw_edit(0)) してるところを見ると,子プロセス(env EDITORの方)の戻り値が -1 だったので, err(1, "pw_edit()") になる.
これが2行目のエラー.
/usr/src/usr.sbin/vipw/vipw.c 103 for (;;) { 104 switch (pw_edit(0)) { 105 case -1: 106 pw_fini(); 107 err(1, "pw_edit()"); 108 case 0: 109 pw_fini(); 110 errx(0, "no changes made"); 111 default: 112 break; 113 } 114 if (pw_mkdb(NULL) == 0) { 115 pw_fini(); 116 errx(0, "password list updated"); 117 } 118 printf("re-edit the password file? "); 119 fflush(stdout); 120 if ((line = fgetln(stdin, &len)) == NULL) { 121 pw_fini(); 122 err(1, "fgetln()"); 123 } 124 if (len > 0 && (*line == 'N' || *line == 'n')) 125 break; 126 }
tempname は masterpasswd から生成してて,masterpasswd と同じディレクトリに,ファイル名を pw.XXXXXX にして一時ファイルを作成する.
/usr/src/usr.sbin/vipw/vipw.c 213 int 214 pw_tmp(int mfd) 215 { ... 221 if (*masterpasswd == '\0') 222 return (-1); 223 if ((p = strrchr(masterpasswd, '/'))) 224 ++p; 225 else 226 p = masterpasswd; 227 if (snprintf(tempname, sizeof(tempname), "%.*spw.XXXXXX", 228 (int)(p - masterpasswd), masterpasswd) >= (int)sizeof(tempname)) { 229 errno = ENAMETOOLONG; 230 return (-1); 231 }
masterpasswd は _PATH_MASTERPASSWD から生成してる._PATH_MASTERPASSWD は/usr/include/pwd.h に書いてある.
93 int 94 pw_init(const char *dir, const char *master) 95 { ... 110 if (master == NULL) { 111 if (dir == NULL) { 112 strcpy(masterpasswd, _PATH_MASTERPASSWD); 113 } else if (snprintf(masterpasswd, sizeof(masterpasswd), "%s/%s", 114 passwd_dir, _MASTERPASSWD) > (int)sizeof(masterpasswd)) { 115 errno = ENAMETOOLONG; 116 return (-1); 117 } 118 } else { 119 if (strlen(master) >= sizeof(masterpasswd)) { 120 errno = ENAMETOOLONG; 121 return (-1); 122 } 123 strcpy(masterpasswd, master); 124 }
/usr/include/pwd.h 64 #define _PATH_PWD "/etc" 65 #define _PATH_PASSWD "/etc/passwd" 66 #define _PASSWD "passwd" 67 #define _PATH_MASTERPASSWD "/etc/master.passwd" 68 #define _MASTERPASSWD "master.passwd"
ip_fastforward
FreeBSD5.3からIP Fastforward(IPv4)という機能があるらしく,これを有効にすると早く処理できるらしい.
http://people.freebsd.org/~andre/FreeBSD-5.3-Networking.pdf
# sysctl net.inet.ip.fastforwarding=1
ソースはsys/netinet/ip_fastforward.cで,コメントが非常に丁寧なので中身見ればOK.あとはしゅううさんの記事見ればOK.http://d.hatena.ne.jp/syuu1228/20081020
やっていることは,パケットの正常性確認,自宛処理,NAT/FW,ネクストホップ探索,TTL減算・チェックサム更新とか.
この内,NAT/FWはpfil_run_hooks()に,ネクストホップ探索はip_findroute()に丸投げ.
あと,自宛確認をin_localip()でやってたりもする.
Nested virtualization on Mac (using VMware Fusion and ESXi)
Macでの多段仮想化(VM on VM/Nested Virtualization)について.
「Macでの」というのはVMware Fusionを使うということです.Type2 VMMでVT-x/EPTを透過できるので有名なVMware Fusionを使いました.VirtualBoxだとVt-x/EPTを透過できないみたいなことを聞いたことがあるので,そちらではやっていません.
最終的には Gentoo/Linux over ESXi over VMware Fusion over Mac OS X になりました.Gentoo/LinuxでKVMを動かせば3段階のNestedになります.
下から順に設定を記載します.
VMware Fusion
ゲストOSへVT-x/EPTを透過させるには設定ファイルの書き換えが必要です.
ESXiの設定ファイル(例:~/Documents/Virtual Machines.localized/VMware ESXi 5.vmwarevm/VMware ESXi 5.vmx)に以下を追記しました.この項目は無いので新規追加です.
vhv.enable = "TRUE"
Fusionの各ゲストOS設定のOther→AdvancedにVT-x/EPTを有効にするかどうかの項目がありますが,これはデフォルトで自動設定になっているので設定不要でした.
ESXi
こちらもゲストOSへVT-x/EPTを透過させるには設定ファイルの変更が書き換えです.まずは設定ファイルを変更できるようにESXiへSSHでログイン出来るように設定を変更しました.ESXi(vSphere経由ではなく直接)のトラブルシュートの項目からESXiからSSHログインとシェルの有効化を行いました.ちなみに,この設定はvSphere経由でも出来るようです.
ログイン出来るようになったら/etc/vmware/configに以下を追記しました.この項目は無いので新規追加です.
vhv.allow = "TRUE"
実は設定はこれだけでは終わらず,ESXiのゲストOS個別設定が少し必要です.
一番上のOS(今回だとGentoo/Linux)
ESXi上にインストールするのでWindows+vSphere Clientが必要です.今回はWindowsをVMware Fusion上にインストールしました.全部VMware Fusion上にあることになります.
一番上のOSはなんでもよくて,今回はGentoo/LinuxのインストールCDを使いました.
ESXiがVT-x/EPTを透過させるにはゲストOSにも設定が必要です.この設定はvSphere Clientからは行えず,ESXiにSSHログインしてエディタで設定ファイルを直接編集する必要があります.
そのため,一旦ESXi上で動かすLinuxを作ったのちに,SSHログインしてVMの設定ファイルを修正します(例:/vmfs/volumes/datastore1/[仮想マシン名]/[仮想マシン名].vmx).上述のvhv.allow等とは異なり,項目はありますが右辺が違うのでそこを修正します.
guestOS = "vmkernel" または guestOS = "vmkernel5"
LinuxだからといってLinux2.6(64bit)等を選択するとVT-x/EPTが透過されません.vmkernel (ESXi4.0) / vmkernel5 (ESXi5.x) に設定する必要があるようです.
(これを入れると,仮想マシンのプロパティ→オプション→ゲストOS→バージョン:→VMware ESXi 4.0/5.xが選べるようになるので,以降はvSphereから設定することも可能です)
あとは grep vmx /proc/cpuinfo とかすれば vmx が有効になっていることがわかります.
NPUのお仕事(Intel IXP 1200の場合)
2001年ぐらいにリリースされたNPU,Intel IXP1200の場合.
資料はこのへん.
- http://www.tu-ilmenau.de/fileadmin/public/iks/files/lehre/wi/WI-IXP.pdf
- http://www.cs.cmu.edu/~rajesh/papers/15740f00-ixp1200.pdf
- http://web.ict.kth.se/~mahidell/pubs/networking04_tutorial_final.pdf
NPUの制御はイーサネットコントローラ上部.
1番目の資料に全て書いてあるので,それをメモする.
NPUの構成については,マッチングを行うMicroEngine(ME),SRAM/DRAMおよびそれらのUnit,MAC層と接続しているIX Bus Unit,StrongARM(CPU)がある.
- イーサネットコントローラまで上がってきたフレームはRxFIFO(IX Bus Unitの一部)に格納される.
- MEが定期的にRxFIFOを監視していて(6MEx4Thread=24threadのうち2threadが監視用っぽい),フレームを見つけるまで監視し続ける
- RxFIFOにフレームを発見したMEは,フレーム全体をSDRAMにコピーするようにIX Bus Unitに指示する.そうすると後はIX Bus Unitが勝手にRxFIFOからSDRAMにコピーしてくれる.並行してMEは転送先を探索すべく,RxFIFOからフレームヘッダだけを取得してME内部のTransport Registerにコピーする.MEはこれとSRAMにあるテーブルとマッチングを行う.
- MEは必要に応じてSDRAM上のフレームのヘッダ情報を書き換える.
- 転送先の探索結果に基づいて転送する準備をする.MEがSDRAM UnitにIX Bus UnitのTxFIFOへコピーするように指示する.あとは勝手にSDRAM Unitがやってくれる.
- コピーが終わったらSDRAM UnitがMEに通知するので,それを持ってMEがIX Bus UnitへMAC層へ渡すように指示する.
マッチングに引っかからなかった時はStrongARMにあげて処理を決める.その結果(転送先情報)はStrongARMがSRAMに書き込む.
vyattaのイメージをcloneしてからすること
sudo -s して /opt/vyatta/etc/config/config.boot から ethX を削除
Network Algorighmics - まえがき
ネットワークには2種類のボトルネックがある
- リソース ... スケールアウト,スケールアップ
- 実装 ... 本書の対象
エンドノードのボトルネック
転送ノードのボトルネック
- 転送ルックアップ
- パケットクラシフィケーション
- スイッチ
- 計測
- セキュリティ
各章の概要
- 第一部 network algorithmicsの方法の概要
- 1章 Network Algorithmicsとは
- 2章 Network Algorithmicsを考える前提条件・モデル
- 3章 Network Algorithmicsの15の実装の基本的な考え方
- 4章 Network Algorithmicsの15の実装詳細
- 第二部 エンドノードに適用する場合
- 第三部 ルータ,スイッチに適用する場合
- 10章 exact-match
- 11章 prefix-match
- 12章 packet classification(security+QoS)
- 13章 スイッチング
- 14章 パケットスケジューリング
- 15章 ルータ
- 第四部 network algorithmicsをセキュリティ・計測に使う場合
- 16章 計測機能の実装方式
- 17章 セキュリティ機能の実装方式
- 18章 実例