トップ 追記

本 日 の h o g e

hogeとはワイルドカードのようなものです。日々起こった、さまざまなこと −すなわちワイルドカード− を取り上げて日記を書く、という意味で名付けたのかというとそうでもありません。適当に決めたらこんな理由が浮かんできました。

更新情報の取得には rdflirs を使ってもらえると嬉しいです.


05/13/2012 ふむ [長年日記]

tDiary 3489日目

[Linux][Py] Ethernet over WebSocket

TAP を使って L2 フレームを WebSocket でトンネリングしてみた. 名付けて EtherWebSocket. そのまんま.

こないだの TAP は C で直接書いたけど,WebSocket を C でほげほげするのは面倒なので Python で.

そうなると TAP の Python インタフェースが必要になるのだけれど,python-pytun なるものがあったのでそれを使った. 正直に言うとこの TAP for Python は最初探しもせずに自分で書いてた. 2/3 くらい書いたところで「そういえば」と思ってぐぐったら出てきて,嬉しいような悲しいような気分になりましたとさ. 一応 自分が書いてたものの残骸はここに置いてある けど,python-pytun 使った方が良いでしょう. 中身の方向性は大体同じで,python-pytun の方が完成度が高い.

さて本題の EtherWebSocket のコード. まあ何のことはない,TAP から流れてきたフレームを WebSocket に,WebSocket から流れてきたフレームを TAP に流すだけの単純なもの. 一応 Hub and Spoke 型で動くように書いたつもりではあるけど,試してないから知らない.

で,手元でこれを使って KVM の VM を 2 台繋げてみたけど,だいぶきもいね.大体こんなイメージで本当に動いてしまった.びっくりだね.

+-----+                +-----+
| VM1 |                | VM2 |
+--+--+                +--+--+
   | (vnet0)      (vnet1) |
+--+--+                +--+--+
| br0 |                | br1 |
+--+--+                +--+--+
   |      (WebSocket)     |
(ethws0) <===========> (ethws1)
// サーバ側起動.デフォルトだと 0.0.0.0:80 で待機する
# python etherws.py server

// クライアント側起動.サーバの URL を指定して繋ぎに行く
# python etherws.py client --uri ws://localhost/

// デフォルトだと ethws0 とかいうインタフェースが生えるので,
// ブリッジに繋いでやる
# brctl addbr br0
# brctl addbr br1
# ifconfig br0 up
# ifconfig br1 up
# brctl addif br0 ethws0
# brctl addif br0 vnet0
# brctl addif br1 ethws1
# brctl addif br1 vnet1
# brctl show
bridge name     bridge id               STP enabled     interfaces
br0             xxxx.xxxxxxxxxxxx       no              ethws0
                                                        vnet0
br1             xxxx.xxxxxxxxxxxx       no              ethws1
                                                        vnet1

ちなみに VM の MTU が 1500 だとよく刺さる.1400 とかにしてやると刺さらなくなる.

# ifconfig ethX mtu 1400

これは EtherWebSocket 側でどうにかできんこともないと思うんだけど,まだちょっと試行錯誤中というか何というか.

追記

なんかタイミング系のバグがあったくさいので直した.たぶん.

ついでにフレーム転送方法をバイナリ転送に変更. 少しパフォーマンス上がった. 手元で試した感じだと scp arc4 で 1.2MB/s くらい.テキスト転送で 900KB/s くらいだったのでまずまず.

それにしても,もっと全然うんこみたいなパフォーマンスしか出ないだろうと思ってたんだけど,意外と頑張っててちょっと驚いた. まあ CPU ブン回りまくりだけど.

追記2

動かしたまま 2 日放置して,死ぬようなこともないようなので pypi に登録しておいた

初 pypi. pypi バージンを失いました.

追記3

SSL/TLS 接続と Basic 認証を付けておいた. これで簡単な L2-VPN としても使える気がしないでもない.


05/10/2012 ふむ [長年日記]

tDiary 3486日目

[Linux] TAP を使ってみる

L2 な仮想デバイスを作れ,そのデバイスに対する入出力をファイルディスクリプタ経由で行うことのできる TAP を使ってみる.

Linux の Documentation/networking/tuntap.txt に色々書いてあるので,適当に読みつつ tapcap なるものを書いてみた.

$ gcc -o tapcap tapcap.c
$ sudo ./tapcap tapcap0

引数にデバイス名を渡して実行してやると,仮想デバイスが出来上がる.

$ ifconfig tapcap0
tapcap0   Link encap:Ethernet  HWaddr xx:xx:xx:xx:xx:xx  
          inet6 addr: fe80::xxxx:xxxx:xxxx:xxxx/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:500 
          RX bytes:0 (0.0 B)  TX bytes:328 (328.0 B)

一方,プロセス側ではこのデバイスがファイルディスクリプタとして見えている. tapcap は fd をひたすら read して hexdump するだけの小さなブツなので,ブリッジに繋ぐなど殴る蹴るの暴行を加えると,

$ sudo brctl addif br0 tapcap0
$ brctl show
bridge name     bridge id               STP enabled     interfaces
br0             xxxx.xxxxxxxxxxxx       no              eth0
                                                        tapcap0

L2 フレームがべろべろと流れ始める.ちなみにこいつは IPv4/ICMP/ブロードキャスト.

-- Thu May 10 23:41:49 2012

  0x0000: ffff ffff ffff 001c c039 0ceb 0800 4500
  0x0010: 0054 0000 4000 4001 155a ac10 e62e ac10
  0x0020: e6ff 0800 28eb 6108 0001 add3 ab4f 0000
  0x0030: 0000 5115 0500 0000 0000 1011 1213 1415
  0x0040: 1617 1819 1a1b 1c1d 1e1f 2021 2223 2425
  0x0050: 2627 2829 2a2b 2c2d 2e2f 3031 3233 3435
  0x0060: 3637 

ちなみにこのデバイスには tcpdump をかけることもできるのでプロセスによる hexdump はただのオマケ.

TAP 自体は write つまり送信もサポートしてるので色々遊べそう. 邪悪な意味も含めて.


05/02/2012 うむ [長年日記]

tDiary 3478日目

[JS][日記] Pyコードシューター を改造

パワーアップアイテムを実装してみた. それだけ.

微妙にバランスを壊した気がするけどまあいいや.

それにしてもコードがあまりに汚すぎてひどい. 何も考えず思いつきで書くとこうなるという反面教師だな.


04/22/2012 ふむ [長年日記]

tDiary 3468日目

[日記] KVM 上の Guest として Windows8 Consumer Preview をインストール

先日ようやく重い腰を上げて自宅デスクトップを KVM Ready にした (ハードはサポートしてたけど面倒でやってなかった). とりあえず Guest Linux はそれっぽく動いたので,今度は Windows を入れてみる.

Windows8 は標準では virtio をサポートしていないので,以下のように cdrom ドライブが 2 台あることにして起動すると楽.

// Fedora Project から Windows 用 virtio ドライバ ISO をダウンロード
// Windows7 用ドライバがそのまま使える
$ wget http://alt.fedoraproject.org/pub/alt/virtio-win/latest/images/bin/virtio-win-0.1-22.iso

// インストール先ディスクイメージ作成
$ sudo qemu-img create -f qcow2 /path/to/windows8.img 40G

// サウンドをチューニング
$ export QEMU_AUDIO_DRV=sdl
$ export QEMU_SDL_SAMPLES=8

// cdrom ドライブを 2 台積んでいることにして起動
$ sudo qemu-kvm \
   -name "Windows8" \
   -cpu host \
   -smp 2 \
   -m 2048 \
   -vga vmware \
   -soundhw all \
   -usb \
   -usbdevice tablet \
   -drive file=/path/to/windows8.img,if=virtio,media=disk,index=0 \
   -drive file=/path/to/Windows8-ConsumerPreview-64bit-Japanese.iso,media=cdrom,index=2 \
   -drive file=/path/to/virtio-win-0.1-22.iso,media=cdrom,index=3 \
   -net nic,macaddr=54:52:00:xx:yy:zz,model=virtio -net tap,ifname=vnet1,script=no \
   -boot d \
   -vnc :8 \
   -daemonize

ディスクを virtio で起動しているのでインストーラ起動直後はドライブがないと怒られる. ドライバを入れるぜボタンをクリックしてドライバをインストールしてやればドライブが見えるようになる.

ちなみに qcow2 イメージにインストールするのはかなり時間がかかる. インストールしてから思ったのだけれど,dd で raw イメージを作ってインストールした上で改めて qcow2 に convert すれば良かったかも知れない.

てかとりあえず vm をごりごり動かすにはメモリが足りないので足さないと...

追記

スペックが足りないのか何なのか,どうもサウンド関係がブツブツだったりと微妙なのでチューニングを入れた. 下記コマンドでサウンド関係の環境変数のヘルプを見ることができる.

$ qemu-kvm -audio-help

手元環境では下記くらいが最適で,いまいちよく分からないけれど QEMU_SDL_SAMPLES の値が小さい方が安定した. ちなみに alsa を使うとどう設定しても改善しなかった...

QEMU_AUDIO_DRV=sdl
QEMU_SDL_SAMPLES=8

てか Guest が Linux の場合はむしろいじらない方が安定していたので,Guest の OS やドライバによって最適な設定が異なる感じか.


04/16/2012 ふむ [長年日記]

tDiary 3462日目

[メモ][Linux] veth

通信できる Ether な仮想デバイスを Linux に生やすの巻.

用意するもの:
  1. 2.6.24 以降のカーネルを CONFIG_VETH=y でビルド
  2. type veth をサポートする iproute2 (具体的にどのバージョンからサポートしたのかは知らない.最近のは大体 OK)

以下を実行して試す.

// 足を生やす
# ip link add type veth

// 終端の 2 つの仮想デバイスができる
# ip link show veth0
8: veth0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN qlen 1000
    link/ether a6:50:34:b1:4e:a9 brd ff:ff:ff:ff:ff:ff

# ip link show veth1
9: veth1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN qlen 1000
    link/ether 06:91:65:3a:72:0d brd ff:ff:ff:ff:ff:ff

// データを流してみる
# ifconfig veth0 10.0.0.1 netmask 255.255.255.0
# ping 10.0.0.2

// 別の端末で対向の veth1 を観察
# ifconfig veth1 up
# tcpdump -i veth1
22:41:29.996627 arp who-has 10.0.0.2 tell 10.0.0.1
...

とりあえず ARP は流れるけど,10.0.0.2 なんてアドレスはないので当然 ping は DestUnreach.

じゃあ veth1 にアドレスを付ければ反応するかというとそうでもない.ARP に応答しないので,どっかに繋げてやるよろし.