WiresharkでMTU超えの大きすぎるパケットがキャプチャーされてる!

Linux(CentOS on Let's note)上でRawソケットでキャプチャーをしていたら,64,294バイト(約64KB)とかMTUを軽く超えるパケットが送信されているのを発見!
いやいや,そんなバカな,と思いつつ,Wiresharkでも確認してみたらやっぱりありました.MTUを超えた大きなパケットが.
MTUを超えるサイズのパケットはIP層でフラグメントされてMTUサイズ以下にされるはずなのにおかしい.
RawソケットもWiresharkもIP層の下でパケットをキャプチャしているはずだから,フラグメント後のパケットをキャプチャーできるはずなのに・・・.
原因について,いろいろ調べてみると,分かりました.
「GSO(Generic Segmentation Offload)」でした.
パケットのフラグメントという,わりと重い処理をハードウェアであるNICにオフロードすることでCPU負荷を減らすあれです.


GSOが有効になっているかどうかは,ethtoolコマンドで確認できるようです.

$ ethtool -k eth0
Features for eth0:
rx-checksumming: on
tx-checksumming: on
scatter-gather: on
tcp-segmentation-offload: off
udp-fragmentation-offload: off
generic-segmentation-offload: on
generic-receive-offload: off
large-receive-offload: off
rx-vlan-offload: on
tx-vlan-offload: on
ntuple-filters: off
receive-hashing: off


試しに,
ethtool -K eth0 gso off
で,GSOをオフってみると,WiresharkのキャプチャーでのMTU超えのパケットがすっかりなくなった!
やったー!
GSOって,普通のノートPCのNICにもちゃんと実装されているもんなんですね.


--- 参考サイト ---
Seeing 25,000 byte packets in Wireshark Super packets Unleash Networks Blog
http://www.unleashnetworks.com/blog/?p=307

LinuxNICのオフロード機能のON/OFF - id:rx7(@namikawa)の技術メモ - 技術日記
http://tech.g.hatena.ne.jp/rx7/20130425/p1

【レポート】FreeBSD 10ギガビットネットワーク高速通信の秘密 (3) ハードウェアオフロードによる処理の高速化 | 開発・SE | マイナビニュース
http://news.mynavi.jp/articles/2008/10/29/bsdcon5/002.html

モーツァルトと同時代の作曲家:ボッケリーニのOctet

モーツァルトハイドンと同じ時代の作曲家,ルイジ・ボッケリーニさんです.
暖かみのある曲の雰囲気で,わりと好きかも.
そんなボッケリーニさんのVn,Va,Vc,Cbの弦楽とFl,Fg,Hrの編成の曲です.
たくさん曲書いているみたいなので,探せばいい曲出てきそう.演奏会にも使えるかも?

Boccherini / Octet (Notturno) in G major, Op. 38 No. 4 (G. 470) - YouTube
http://www.youtube.com/watch?v=wINglWDcV8E

qemu-kvmの仮想ハードディスクイメージへの読み書き・その1

ゲストOSが仮想HDDイメージにデータを書き込むまでのqemu-kvmの内部動作を追ってみる.

ゲストOSがI/O命令を実行すると,CPUの仮想化支援機能が命令をトラップし,ゲストモードからカーネルモードに移行(VMExit)する.
KVMカーネルモジュール内でVMExit要因の判定を行い,I/O命令の場合はユーザプロセスのqemu-kvmのハードウェアエミュレートが必要になるためカーネルモードからユーザモードへ移行する.
qemu-kvm側では,VMExit要因に応じてエミュレートを行なって,必要であればゲストOS(と言うか仮想マシン)のCPUコンテキストを書き換えたり,割り込みを挿入したり,メモリにデータを書き込んだり,必要な処理を行った後,再びKVMカーネルモジュールにお願いして,ゲストOSの実行を再開する.
というのが,おおまかな流れ.
とりあえず,KVMからqemu-kvmへ処理が戻ったあたりから追って見る.


各仮想CPUの実行は,qemu_kvm_cpu_thread_fn()で行われる.
この関数で実行されているkvm_cpu_exec()のdo-whileループ内で,KVMで仮想CPUの実行する,VMExitで戻ってきたらI/Oイベントを処理する,また仮想CPUを実行する・・・,をずっと繰り返してる.
[qemu-kvm1.2.0]
[cpus.c]

 732 static void *qemu_kvm_cpu_thread_fn(void *arg)
 733 {
 ...
 755     while (1) {
 756         if (cpu_can_run(env)) {
 757             r = kvm_cpu_exec(env);
 758             if (r == EXCP_DEBUG) {
 759                 cpu_handle_guest_debug(env);
 760             }
 761         }
 762         qemu_kvm_wait_io_event(env);
 763     }
 ...

[kvm-all.c]

1550 int kvm_cpu_exec(CPUArchState *env)
1551 {
....
1562     do {
....
1580         run_ret = kvm_vcpu_ioctl(env, KVM_RUN, 0);
....
1598         switch (run->exit_reason) {
1599         case KVM_EXIT_IO:
1601             kvm_handle_io(run->io.port,
1602                           (uint8_t *)run + run->io.data_offset,
1603                           run->io.direction,
1604                           run->io.size,
1605                           run->io.count);
....
1608         case KVM_EXIT_MMIO:
1610             cpu_physical_memory_rw(run->mmio.phys_addr,
1611                                    run->mmio.data,
1612                                    run->mmio.len,
1613                                    run->mmio.is_write);
....
1616         case KVM_EXIT_IRQ_WINDOW_OPEN:
....
1620         case KVM_EXIT_SHUTDOWN:
....
1625         case KVM_EXIT_UNKNOWN:
....
1630         case KVM_EXIT_INTERNAL_ERROR:
....
1633         default:
....
1638     } while (ret == 0);


今回はI/Oを追うので,VMExitの要因が「KVM_EXIT_IO」だった時に実行されるkvm_handle_io()を追う.
I/Oポートへの読み込みか,書き込みかを判定し,読み書きサイズでスイッチしてる.
[kvm-all.c]

1431 static void kvm_handle_io(uint16_t port, void *data, int direction, int size,
1432                           uint32_t count)
1433 {
1434     int i;
1435     uint8_t *ptr = data;
1436
1437     for (i = 0; i < count; i++) {
1438         if (direction == KVM_EXIT_IO_IN) {
1439             switch (size) {
1440             case 1:
1441                 stb_p(ptr, cpu_inb(port));
1442                 break;
1443             case 2:
....
1449             }
1450         } else {
1451             switch (size) {
1452             case 1:
1453                 cpu_outb(port, ldub_p(ptr));
1454                 break;
1443             case 2:
....
1461             }
1462         }
....


I/Oポートに対して,読み込みだった場合はioport_read(),書き込みだった場合はioport_write()が呼ばれ,各ポートのアドレスごとに関数テーブルに登録された関数が呼び出される.
[ioport.c]

 60 static uint32_t ioport_read(int index, uint32_t address)
 61 {
 62     static IOPortReadFunc * const default_func[3] = {
 63         default_ioport_readb,
 64         default_ioport_readw,
 65         default_ioport_readl
 66     };
 67     IOPortReadFunc *func = ioport_read_table[index][address];
 68     if (!func)
 69         func = default_func[index];
 70     return func(ioport_opaque[address], address);
 71 }
 72
 73 static void ioport_write(int index, uint32_t address, uint32_t data)
 74 {
 75     static IOPortWriteFunc * const default_func[3] = {
 76         default_ioport_writeb,
 77         default_ioport_writew,
 78         default_ioport_writel
 79     };
 80     IOPortWriteFunc *func = ioport_write_table[index][address];
 81     if (!func)
 82         func = default_func[index];
 83     func(ioport_opaque[address], address, data);
 84 }

この先は,各仮想ハードウェア(仮想HDD)ごとの処理に移るはず.
次回に続く.

無料ダイナミックDNSサービス

ddo.jpが無料ユーザ9ヶ月制限がかかってしまったので,乗り換え検討.

無料ダイナミックDNS(DDNS)サービス - ieServer.Net
http://ieserver.net/

ドメイン取るなら お名前.com - ドメイン取得 年間180円〜
http://onamae.com/

リアルタイムOSについての参考になる記事

技術の広場 - 高田広章のリアルタイムOS論---目次:ITpro
http://itpro.nikkeibp.co.jp/article/COLUMN/20060921/248659/?ST=ittrend


技術の広場 - 高田広章のリアルタイムOS論【第2回】(3):ITpro
http://itpro.nikkeibp.co.jp/article/COLUMN/20050908/220793/

LinuxのTCPのウィンドウサイズの設定値

Linux 3.3.4でのデフォルトの設定値をメモ.
数値は[min, default, max]の意味.
この値にから,TCPのウィンドウサイズは,デフォルトは16KBから始まって,4KBから4MBの間で調整される.
これより,TCPを用いて通信を行う場合,最大で4MBのバースト転送が発生することがわかる.


$ cat /proc/sys/net/ipv4/tcp_wmem
4096 16384 4194304

$ cat /proc/sys/net/ipv4/tcp_rmem
4096 87380 4194304


参考サイト
kernel/システムパラメタ - Linux Tips
http://linux.mini13i.com/?kernel%2F%A5%B7%A5%B9%A5%C6%A5%E0%A5%D1%A5%E9%A5%E1%A5%BF

Note - ソケットバッファのチューニング
http://www.anarg.jp/personal/t-tugawa/note/linux/sockbuf.html