« WindowsでTCP/IPのプログラムを作ったときに名前解決を早くする | トップページ | ZYNQのLinuxのハードウェア初期化用にsystemdで起動するサービスを作る »

2021.09.11

WindowsがLinuxマシンのMDNSで遅くなる原因?

組み込みLinuxのマシンの名前を「ホスト名.local」で解決しようとして1秒待たされる原因は、どうやらLinuxが返すMDNSのパケットの違いにあることがわかってきました。

 

ZYNQの組み込みLinuxに対するPINGを無線LANでやってみしたところ、なんと、この1秒待たされる現象が発生しないことがわかりました。次の図はPINGを打ったときのパケットの解析です。Windowsマシンは最初、IPv4とIPv6の双方で、IPv4アドレスとIPv6アドレスを調べようとして4個のqueryを出しています。

Avahiwifi0

それに対してLinuxマシンは

  • IPv4パケットに乗せたIPv4アドレス
  • IPv4パケットに乗せたIPv6アドレス
  • IPv6パケットに載せたIPv6アドレス

という3つのresponseを返しています。

この3つ目のレスポンスが帰ると即座にPINGのパケットが出始めます。

 

一方、同じ組み込みLinuxのマシンでも有線LANでつないだ場合は、「IPv6パケットに乗せたIPv6アドレス」の応答が出てこないのです。

Wiredlanresponse

これゆえWindowsはgetaddrinfo()で1秒間のタイムアウトをするまで待たされるのだと思われます。

 

では、Linuxのavahi-daemonが有線LANでバグっているのかというと、そういうわけではなさそうです。Linux側でtcpdumpをしてみると、

01:20:38.768658 IP 192.168.1.4.mdns > 224.0.0.251.mdns: 0 A (QM)? cszmini.local. (31)
01:20:38.770990 IP cszmini.mdns > 224.0.0.251.mdns: 0*- [0q] 1/0/0 (Cache flush) A 192.168.1.12 (41)
01:20:38.771974 IP6 fe80::***************.mdns > ff02::fb.mdns: 0 A (QM)? cszmini.local. (31)
01:20:38.774358 IP 192.168.1.4.mdns > 224.0.0.251.mdns: 0 AAAA (QM)? cszmini.local. (31)
01:20:38.776324 IP6 fe80::***************.mdns > ff02::fb.mdns: 0 AAAA (QM)? cszmini.local. (31)
01:20:38.777309 IP cszmini.mdns > 224.0.0.251.mdns: 0*- [0q] 1/0/0 (Cache flush) AAAA fe80::11:10ff:fe00:2201 (53)
01:20:38.789419 IP 192.168.1.4.mdns > 224.0.0.251.mdns: 0 A (QM)? cszmini.local. (31)
01:20:38.792155 IP6 fe80::***************.mdns > ff02::fb.mdns: 0 A (QM)? cszmini.local. (31)
01:20:38.794569 IP 192.168.1.4.mdns > 224.0.0.251.mdns: 0 AAAA (QM)? cszmini.local. (31)
01:20:38.796814 IP6 fe80::***************.mdns > ff02::fb.mdns: 0 AAAA (QM)? cszmini.local. (31)
01:20:39.803426 IP 192.168.1.4.mdns > 224.0.0.251.mdns: 0 A (QM)? cszmini.local. (31)
01:20:39.805998 IP cszmini.mdns > 224.0.0.251.mdns: 0*- [0q] 1/0/0 (Cache flush) A 192.168.1.12 (41)
01:20:39.809007 IP6 fe80::***************.mdns > ff02::fb.mdns: 0 A (QM)? cszmini.local. (31)
01:20:39.811748 IP 192.168.1.4.mdns > 224.0.0.251.mdns: 0 AAAA (QM)? cszmini.local. (31)
01:20:39.813931 IP6 fe80::***************.mdns > ff02::fb.mdns: 0 AAAA (QM)? cszmini.local. (31)
01:20:39.816796 IP 192.168.1.4 > cszmini: ICMP echo request, id 1, seq 16515, length 40
01:20:39.818957 IP cszmini.mdns > 224.0.0.251.mdns: 0*- [0q] 1/0/0 (Cache flush) AAAA fe80::11:10ff:fe00:2201 (53)
01:20:39.821750 IP cszmini > 192.168.1.4: ICMP echo reply, id 1, seq 16515, length 40

と、IP6でcszminiがソースになっているものがありません。

一方、無線LANのほうもtcpdumpしてみると、

01:23:44.921998 IP 192.168.1.4.mdns > 224.0.0.251.mdns: 0 A (QM)? cszmini.local. (31)
01:23:44.924618 IP cszmini.mdns > 224.0.0.251.mdns: 0*- [0q] 1/0/0 (Cache flush) A 192.168.1.10 (41)
01:23:44.927949 IP6 fe80::***************.mdns > ff02::fb.mdns: 0 A (QM)? cszmini.local. (31)
01:23:44.930494 IP 192.168.1.4.mdns > 224.0.0.251.mdns: 0 AAAA (QM)? cszmini.local. (31)
01:23:44.933371 IP6 fe80::***************.mdns > ff02::fb.mdns: 0 AAAA (QM)? cszmini.local. (31)
01:23:44.934356 IP cszmini.mdns > 224.0.0.251.mdns: 0*- [0q] 2/0/0 (Cache flush) AAAA 240b:10:ae21:3f00*****, (Cache flush) AAAA 240b:10:ae21:3f00:***** (81)
01:23:44.936394 IP 192.168.1.4.mdns > 224.0.0.251.mdns: 0 A (QM)? cszmini.local. (31)
01:23:44.937727 IP6 cszmini.mdns > ff02::fb.mdns: 0*- [0q] 2/0/0 (Cache flush) AAAA 240b:10:ae21:3f00*****, (Cache flush) AAAA 240b:10:ae21:3f00:***** (81)
01:23:44.940091 IP6 fe80::***************.mdns > ff02::fb.mdns: 0 A (QM)? cszmini.local. (31)
01:23:44.942336 IP 192.168.1.4.mdns > 224.0.0.251.mdns: 0 AAAA (QM)? cszmini.local. (31)
01:23:44.944420 IP6 fe80::***************.mdns > ff02::fb.mdns: 0 AAAA (QM)? cszmini.local. (31)
01:23:44.946751 IP6 fe80::*************** > cszmini: ICMP6, neighbor solicitation, who has cszmini, length 32
01:23:44.949187 IP6 cszmini > fe80::***************: ICMP6, neighbor advertisement, tgt is cszmini, length 24

となっていて、IPv6のパケットでMDNSを返しているんですね。 

ネットワークの問題でパケットがロスしているわけではなくて、有線LANでは本当にIPv6のパケットが出ていなかったのです。

マジか?と思ってip aしてみると、

root@cszmini:~# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: sit0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1
link/sit 0.0.0.0 brd 0.0.0.0
3: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 02:11:10:00:22:01 brd ff:ff:ff:ff:ff:ff
inet 192.168.1.12/24 brd 192.168.1.255 scope global dynamic eth0
valid_lft 3069021764sec preferred_lft 3069021764sec
inet6 fe80::11:10ff:fe00:2201/64 scope link
valid_lft forever preferred_lft forever

特に問題はなさそうなのですが、MACアドレスがプライベートMACアドレスなのが気になります。そのせいかIPv6のアドレスにはリンクローカルなアドレスしかありません。試しに02:11:10:00:22:01という設定を00:11:10:00:22:01に変更してみたところ、リンクローカルではないIPv6アドレスが生成されるようになって、

root@cszmini:~# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: sit0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1
link/sit 0.0.0.0 brd 0.0.0.0
3: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 10:11:10:00:22:01 brd ff:ff:ff:ff:ff:ff
inet 192.168.1.14/24 brd 192.168.1.255 scope global dynamic eth0
valid_lft 3068829252sec preferred_lft 3068829252sec
inet6 240b:10:ae21:3f00:1211:10ff:fe00:2201/64 scope global dynamic mngtmpaddr noprefixroute
valid_lft 3068829252sec preferred_lft 3068829252sec
inet6 fe80::1211:10ff:fe00:2201/64 scope link
valid_lft forever preferred_lft forever

PING -6 cszmini.localとやってみたところ、IPv6でのMDNSもちゃんと返していることがわかりました。

02:43:58.853565 IP 192.168.1.4.mdns > 224.0.0.251.mdns: 0 AAAA (QM)? cszmini.local. (31) // 1度目のQUERY
02:43:58.855804 IP6 fe80::***************.mdns > ff02::fb.mdns: 0 AAAA (QM)? cszmini.local. (31)
02:43:58.855992 IP cszmini.mdns > 224.0.0.251.mdns: 0*- [0q] 1/0/0 (Cache flush) AAAA 240b:10:ae21:3f00:1211:10ff:fe00:2201 (53)
02:43:58.859651 IP6 cszmini.mdns > ff02::fb.mdns: 0*- [0q] 1/0/0 (Cache flush) AAAA 240b:10:ae21:3f00:1211:10ff:fe00:2201 (53)
02:43:58.888202 IP 192.168.1.4.mdns > 224.0.0.251.mdns: 0 AAAA (QM)? cszmini.local. (31) // 2度目のQUERY
02:43:58.890554 IP6 fe80::***************.mdns > ff02::fb.mdns: 0 AAAA (QM)? cszmini.local. (31)
02:43:59.893692 IP 192.168.1.4.mdns > 224.0.0.251.mdns: 0 AAAA (QM)? cszmini.local. (31) // 3度目のQUERY
02:43:59.896185 IP6 fe80::***************.mdns > ff02::fb.mdns: 0 AAAA (QM)? cszmini.local. (31)
02:43:59.898695 IP6 cszmini.mdns > ff02::fb.mdns: 0*- [0q] 1/0/0 (Cache flush) AAAA 240b:10:ae21:3f00:1211:10ff:fe00:2201 (53)
02:43:59.901480 IP6 240b:10:ae21:3f00:*************** > cszmini: ICMP6, echo request, seq 178, length 40
02:43:59.904150 IP6 cszmini > 240b:10:ae21:3f00:***************: ICMP6, echo reply, seq 178, length 40
02:43:59.907243 IP cszmini.mdns > 224.0.0.251.mdns: 0*- [0q] 1/0/0 (Cache flush) AAAA 240b:10:ae21:3f00:1211:10ff:fe00:2201 (53)
02:44:00.908804 IP6 240b:10:ae21:3f00:*************** > cszmini: ICMP6, echo request, seq 179, length 40
02:44:00.910919 IP6 cszmini > 240b:10:ae21:3f00:***************: ICMP6, echo reply, seq 179, length 40

ただし、これを直してもWindowsのgetaddrinfo()が1秒待つ動作は治りませんでした。上のパケットキャプチャを見てもQUERYを3回も発行しています。IPv6のMDNSが返らないからというわけではなさそうです。まだ何か見落としているところがあるのでしょう。

もしかすると、あまりにも早く返ってきたMDNSのレスポンスは見れないのかもしれません。

そしてMACアドレスがプライベートアドレスならIPv6のMDNSを返さないというavahi-daemonの動作も十分に怪しいのですが、Windowsのgetaddrinfo()はNETBIOSやIPv4のMDNSなど他の手段でアドレスが得られているのに、わざわざIPv6のMDNSレスポンスが得られるまで1秒待つ動作も相当にムダで謎であると思えます。

結局のところ根本原因はわかりませんでしたが、TCP/IPのプログラムを組む時にはIPv4しか使わないと決めているなら、getaddrinfo()の際にAF_INETを指定してIPV4に限定してしまったほうがよいでしょう。

 

|

« WindowsでTCP/IPのプログラムを作ったときに名前解決を早くする | トップページ | ZYNQのLinuxのハードウェア初期化用にsystemdで起動するサービスを作る »

コメント

コメントを書く



(ウェブ上には掲載しません)




« WindowsでTCP/IPのプログラムを作ったときに名前解決を早くする | トップページ | ZYNQのLinuxのハードウェア初期化用にsystemdで起動するサービスを作る »