協力、強力
ワクチンソフトの無料期間が極僅かになってきた。契約しろ、契約しろと五月蝿い。
たまたま、メニューの右側に隠れているアイコンをクリックしたら、ご契約情報と 言う画面が現れて、そこには、
ご契約のキーカードをお送りいたしますので、送付先をお知らせください。 このカードには、製品のシリアル番号と、インストールまたは再インストールに 必要になるライセンス登録コードが記録されています。 メアドを教えてちょって書かれていた。
これだけ読むと、誤解しちゃうなーー。メアドを教えるとコードを送ってくれるって 一瞬思っちゃうぞ。こうやって、未契約ユーザーと、太いパイプを築くわけね。
そして、毎日、メール洪水が押し寄せてくるとな。
あんたが、一番迷惑者だわい。
OpenBSD in FreeBSD
前回は、OpenBSD内の仮想PCにOpenBSDを入れようとして、ネットからのkernel等の 取得で詰まってしまった。別の手を考えた。そんなのFreeBSDに強力なbhyveが居る んだから、協力して貰え。今風に言うと、BSD兄弟のコラボレーションです。
という事で、FreeBSDで、OpenBSD入りのDISKを作成して、それをscpな何かで OpenBSDに持って行こうと言う作戦発動です。
[sakae@fb11 ~/OB60]$ truncate -s 2G ob60.img
こんな具合に空DISKを作成。入れるのは、srcだけを予定してるんで、これだけ有れば 多分大丈夫(のはず)。
[sakae@fb11 ~/OB60]$ cat d.map (hd0) ./ob60.img (cd0) ./install60.iso
これ、grub-bhyveが使うデバイスマップ。そして起動。
# grub-bhyve -m d.map -r cd0 -M 256M OB60 grub> kopenbsd -h com0 (cd0)/6.0/amd64/bsd.rd grub> boot
インストール用bhyveスクリプト
bhyve \ -H -P -A \ -W -c 1 \ -m 256M \ -l com1,stdio \ -s 0:0,hostbridge \ -s 1:0,lpc \ -s 2:0,virtio-net,tap0 \ -s 3,ahci-cd,./install60.iso \ -s 4,virtio-blk,./ob60.img \ OB60
後は、普通にOpenBSDをインストールすればよい。但し、入れる物のうち、 X関係とゲームは今回は使う予定が無いので、 -x* -g* として、除外した。
インストールが終わったら、rebootすると、仮想PCが停止する。
次は、常時使う起動スクリプト
sudo bhyvectl --destroy --vm=OB60; printf "kopenbsd -h com0 -r sd0a (hd0,openbsd1)/bsd\nboot\n" | sudo grub-bhyve -m d.map -M 256M OB60; sudo bhyve -W -c 1 -m 256M -H -P -A -l com1,stdio \ -s 0:0,hostbridge -s 1:0,lpc -s 2:0,virtio-net,tap0 \ -s 3,virtio-blk,./ob60.img OB60; sudo bhyvectl --destroy --vm=OB60
これで、無事に起動してきた。入れる物をけちったせいで、dfでのdisk占有容量は、 411M になった。
カーネルとユーザーランドのソースを入れて、下記のようになった。
# df -k Filesystem 1K-blocks Used Avail Capacity Mounted on /dev/sd0a 1769710 1147894 533332 68% /
気のせいか、VMWARE上に入れた普通のOpenBSDよりも、きびきび動いているような気がする。 その後、いらないデーモンを殺して、
# ps awx PID TT STAT TIME COMMAND 1 ?? Is 0:01.02 /sbin/init 96486 ?? Is 0:00.00 dhclient: vio0 [priv] (dhclient) 59842 ?? Isp 0:00.03 dhclient: vio0 (dhclient) 58689 ?? Sp 0:00.03 /usr/sbin/syslogd 91516 ?? Isp 0:00.00 syslogd: [priv] (syslogd) 63822 ?? Is 0:00.00 /usr/sbin/sshd 36703 ?? Ssp 0:00.02 /usr/sbin/cron 96020 00 Ssp 0:00.23 -ksh (ksh) 58574 00 R+p 0:00.01 ps -awx
こんな状態にしたので、このDISKをOpenBSDに送っておいた。
ntpdが居なくなったせいか、時刻が9時間ずれてしまった。NetBSDではこういう時、 rc.confに補正値を設定しておけるんだけど、OpenBSDはそこまで親切に出来ていない。 下記のように、カーネルを直接書き換えてからrebootしろとな。
# config -ef /bsd OpenBSD 6.0 (GENERIC) #2148: Tue Jul 26 12:55:20 MDT 2016 deraadt@amd64.openbsd.org:/usr/src/sys/arch/amd64/compile/GENERIC Enter 'help' for information ukc> timezone timezone = 0, dst = 0 ukc> timezone -540 timezone = -540, dst = 0 ukc> quit Saving modified kernel.
bhyveによるオーバーヘッドがどれぐらいあるか、カーネルコンパイルで確認してみた。
text data bss dec hex 9093180 266328 663552 10023060 98f094 6m00.06s real 3m28.85s user 0m31.71s system
下記は、VMWARE上のOpenBSDでやった以前の結果
text data bss dec hex 9093180 266328 663552 10023060 98f094 3m57.33s real 1m01.10s user 2m50.59s system
体感的には、2/3ぐらいなパフォーマンスになったけど、その内訳は大幅に異なっていて 興味深い。コンパイル中にモニターしたTopの結果。100%を超えているのが面白い。
PID USERNAME THR PRI NICE SIZE RES STATE C TIME WCPU COMMAND 1279 root 11 20 0 288M 124M kqread 0 7:54 104.17% bhyve
また、OpenBSDの仮想PCで出てた、RTCエラーは、bhyve上のそれでは、発生していなかった。 BIOSも内蔵しているのだろうか? 時刻がどれぐらいズレるか、標準器に問い合わせて おいて、暫くしてから、もう一度、確認してみよう。
# rdate -ncv ntp.nict.jp fri Nov 4 16:31:45 JST 2016 rdate: adjust local clock by -0.019824 seconds
# rdate -ncv ntp.nict.jp Fri Nov 4 17:01:39 JST 2016 rdate: adjust local clock by -2.052748 seconds
30分で、2秒のずれか、親にしてるFreeBSDも全く時刻同期してないので、こんなもの なのだろうな。って、rdateのコードでも読んで、時刻の元を探っておけよ。
NICの2枚刺し
さて、新しい仮想Diskの受け入れ先であるOpenBSDで、準備をしておこう。 その前に、OpenBSDの時計のずれを計測しておく。
# rdate -ncv ntp.nict.jp Sat Nov 5 05:45:52 JST 2016 rdate: adjust local clock by 0.006544 seconds
# rdate -ncv ntp.nict.jp Sat Nov 5 06:16:05 JST 2016 rdate: adjust local clock by 0.042131 seconds
無負荷だと、時計が狂う事は無いのかな。まあ、参考値と言う事です。
じゃ、準備を始める。
[ob: vm]$ cat /etc/hostname.vether0 inet 10.0.0.1/24
これが、2枚目のNICの設定。ゲートウェイを担当させる。もう一枚のNICであるem0は 元々有ったもので、DHCPでアドレスを貰ってきている。
NATを構成する為、/etc/pf.conf の最後に、下記の1行を追加する。このファイルは 行の定義の順番が非常に重要。間違ったら、パケットフィルターの用を為さなかったり、 sshでログインすら出来なくなってしまう。
そんな時は、焦らず、コンソールから、pfctl -d として、パケットフィルターの 機能を殺せばよい。
match out on egress from !(egress) nat-to (egress)
egressって何かと思って調べてみたら、インターネットに面してるNICの事らしい。 単語の意味は、出入り口とか。オイラーの環境だと、em0が相当するんだな。
もう一つ、忘れてはならないのが、2枚のNIC間にパケットが行き来出来るように 設定しておく事だ。
[ob: vm]$ cat /etc/sysctl.conf net.inet.ip.forwarding=1
これで、host側の準備は整ったんで、取り合えずゲストが起動するか確認。 例によって、コンソールが上手く起動せずにめげたけど、何度かの失敗の後 ログイン出来た。
仮想PCで遊ぶ
NATになってるはずなんで、FreeBSD側の設定をきっぱりと忘れて、OpenBSD側に 馴染むようにしていく。
# cat /etc/hostname.vio0 inet 10.0.0.2/24 # cat /etc/mygate 10.0.0.1
こんな設定にする。仮想側のNICは1枚だけね。それから、resolv.confは、そのまま 流用出来る。
# cat /etc/resolv.conf # Generated by vio0 dhclient search localdomain nameserver xxx.xxx.xxx.2 lookup file bind
この仮想PCの起動に何度も失敗するので、一連の流れをスクリプトにまとめておいた。
# cat boot #!/bin/sh vmctl stop OB60 pkill vmd vmd vmctl start OB60 -k /bsd -m 256M -i 1 -d ob60.img sleep 5 vmctl status ifconfig bridge0 add vether0 add tap0 up
最初、vmd関係者を全部殺す。それからだえもん君に来てもらい、仮想PC名 OB60を起動。 起動がトロいので、暫く待って、ステータスを表示、続いて仮想HUB(bridge0)に、 ホスト側の端子tap0とゲスト側の端子vether0を差し込む。 ああ、端子なんて一般人の使う用語だな。専門家なら、RJ45って、言え!
じゃ、ついでに端子が付いているケーブルはどんなカテゴリーの物を使えばいいんでしょうか? そんなの、1000baseT full-duplex ですがな。そこまでスピード出るか知らないけど。
起動した頃を見計らって、sshでログイン(ログインまで結構待たされる)
[ob: vm]$ ssh 10.0.0.2 sakae@10.0.0.2's password: OpenBSD 6.0 (GENERIC.MP) #0: Wed Oct 19 06:38:40 JST 2016 : $
どうしてもssh出来ない時は、vmctl consloe OB60 で、コンソールからログイン出来る。 ただ、コンソールから入った場合、画面のrowsが24行になってるので、stty rows 42とか やって、一度viを起動すると、望みの行数になる。ちょっと面倒だ。
で、気になる時計の精度
# rdate -ncv ntp.nict.jp Sat Nov 5 07:10:49 JST 2016 rdate: adjust local clock by -3.742078 seconds # rdate -ncv ntp.nict.jp Sat Nov 5 07:10:52 JST 2016 rdate: adjust local clock by -3.213282 seconds # rdate -ncv ntp.nict.jp Sat Nov 5 07:10:57 JST 2016 rdate: adjust local clock by -3.698113 seconds
1秒間隔ぐらいで実行してみたんだけど、もうメタメタです。お子様の持ってる おもちゃの時計でも、ここまでは狂わないぞ。
仮想PCの中から、ftpを使って外部にファイルを取りに行った時、パケットフィルターの 状況をモニターしてみた。
bash-4.3# pfctl -s state all tcp xxx.xxx.xxx.130:29294 <- xxx.xxx.xxx.1:50043 ESTABLISHED:ESTABLISHED all tcp 10.0.0.1:22775 -> 10.0.0.2:22 ESTABLISHED:ESTABLISHED all tcp 202.232.140.70:21 <- 10.0.0.2:14760 ESTABLISHED:ESTABLISHED all tcp xxx.xxx.xxx.130:57663 (10.0.0.2:14760) -> 202.232.140.70:21 ESTABLISHED:ESTABLISHED all tcp 202.232.140.70:36618 <- 10.0.0.2:2704 ESTABLISHED:ESTABLISHED all tcp xxx.xxx.xxx.130:58299 (10.0.0.2:2704) -> 202.232.140.70:36618 ESTABLISHED:ESTABLISHED
こちらは、rdateを使って、日本時間製造所に時刻を請求した時のもの。どうやらntpって udpで素早くやり取りするようだな。
bash-4.3# pfctl -s state all tcp xxx.xxx.xxx.130:29294 <- xxx.xxx.xxx.1:50043 ESTABLISHED:ESTABLISHED all tcp 10.0.0.1:22775 -> 10.0.0.2:22 ESTABLISHED:ESTABLISHED all udp xxx.xxx.xxx.2:53 <- 10.0.0.2:29446 SINGLE:MULTIPLE all udp xxx.xxx.xxx.130:62450 (10.0.0.2:29446) -> xxx.xxx.xxx.2:53 MULTIPLE:SINGLE all udp xxx.xxx.xxx.2:53 <- 10.0.0.2:46758 SINGLE:MULTIPLE all udp xxx.xxx.xxx.130:52229 (10.0.0.2:46758) -> xxx.xxx.xxx.2:53 MULTIPLE:SINGLE all udp 133.243.238.163:123 <- 10.0.0.2:6743 SINGLE:MULTIPLE all udp xxx.xxx.xxx.130:53517 (10.0.0.2:6743) -> 133.243.238.163:123 MULTIPLE:SINGLE
どうも、オペレーションがスムーズに出来ない(pingで、あらぬ時間待たされるとか)のは、 時計関係がめちゃめちゃになってると思われる。
OSの時計機構
ゲストOSの時計を使わない、host側からのping
bash-4.3# ping 10.0.0.2 PING 10.0.0.2 (10.0.0.2): 56 data bytes 64 bytes from 10.0.0.2: icmp_seq=0 ttl=255 time=0.678 ms 64 bytes from 10.0.0.2: icmp_seq=6 ttl=255 time=0.432 ms : 64 bytes from 10.0.0.2: icmp_seq=7 ttl=255 time=0.419 ms 64 bytes from 10.0.0.2: icmp_seq=8 ttl=255 time=0.429 ms --- 10.0.0.2 ping statistics --- 9 packets transmitted, 9 packets received, 0.0% packet loss round-trip min/avg/max/std-dev = 0.419/0.462/0.678/0.077 ms
今度は、その逆パターン。計時はゲスト側になってる仮想PCが担当
# ping xxx.xxx.xxx.130 PING xxx.xxx.xxx.130 (xxx.xxx.xxx.130): 56 data bytes 64 bytes from xxx.xxx.xxx.130: icmp_seq=0 ttl=255 time=22860.223 ms 64 bytes from xxx.xxx.xxx.130: icmp_seq=1 ttl=255 time=1.508 ms 64 bytes from xxx.xxx.xxx.130: icmp_seq=2 ttl=255 time=641.645 ms 64 bytes from xxx.xxx.xxx.130: icmp_seq=3 ttl=255 time=1.508 ms --- xxx.xxx.xxx.130 ping statistics --- 4 packets transmitted, 4 packets received, 0.0% packet loss round-trip min/avg/max/std-dev = 1.508/5876.221/22860.223/9809.200 ms
もう、めためたですよ。(毎度、こればっかりです)
代表例として、rdateを見る。コードは、/usr/src/usr.sbin/rdate/ 以下に置いてある。
rdate.cを見ると、ntpなり、隣のマシンから時刻を貰ってきて、
if (!slidetime) { logwtmp("|", "date", ""); if (settimeofday(&pdata.new, NULL) == -1) err(1, "Could not set time of day"); logwtmp("{", "date", ""); } else { if (adjtime(&pdata.adjust, NULL) == -1) err(1, "Could not adjust time of day"); }
一気に合わせるなら、settimeofdayを、ゆっくり合わせるなら、adjtimeを使うとな。 一気に合わせると、lastに記録が残るとな。見たら、本当に残っていた。そんな事は 今まで知らなかったぞ。
で、両手続き共、システムコールでしたよ。次はそれを探してみる。
[ob: sys]$ find . -name '*.[ch]' | xargs grep settimeofday ./arch/sparc64/sparc64/machdep.c: * to resettodr() (e.g. from settimeofday()). ./kern/init_sysent.c: { 2, s(struct sys_settimeofday_args), 0, ./kern/init_sysent.c: sys_settimeofday }, /* 68 = settimeofday */ ./kern/kern_pledge.c: [SYS_settimeofday] = PLEDGE_SETTIME, ./kern/kern_time.c:/* This function is used by clock_settime and settimeofday */ ./kern/kern_time.c:sys_settimeofday(struct proc *p, void *v, register_t *retval) ./kern/kern_time.c: struct sys_settimeofday_args /* { ./kern/syscalls.c: "settimeofday", /* 68 = settimeofday */ ./sys/syscall.h:/* syscall: "settimeofday" ret: "int" args: "const struct timeval *" "const struct timezone *" */ ./sys/syscall.h:#define SYS_settimeofday 68 ./sys/syscallargs.h:struct sys_settimeofday_args { ./sys/syscallargs.h:int sys_settimeofday(struct proc *, void *, register_t *); ./sys/time.h:int settimeofday(const struct timeval *, const struct timezone *);
kern_time.c あたりを見ると、settimeofdayの中からsettimeが呼ばれ、核心部分は、
nanotime(&now); if (securelevel > 1 && timespeccmp(ts, &now, <)) { printf("denied attempt to set clock back %lld seconds\n", (long long)now.tv_sec - ts->tv_sec); return (EPERM); } tc_setrealtimeclock(ts); resettodr();
このあたりのようだ。
tc_setrealtimeclock()は、kern_tc.c に有った。どうやら、CPUが持ってる タイマーを利用している模様。
resettodr()の方は、RTCをリセットするようだ。場所は、arch/amd64/isa/clock.cに 有った。ここで繋がったな。無いハードに対してアクセスしてて、無駄な時間を過ごすの だろう。
ちょっと、消化不良だな。 下記が参考になるかな。