ROS2ユーザー向けの要約
- FastDDSでデフォルトの
239.255.0.1
に対して、一般的に使われるであろう、239.0.0.0/8のプライベートスコープでMacアドレスが重複するマルチキャストグループは、239.127.0.1
となります。ROS2以外のアプリケーション(動画配信システム、TV会議システムなど)の動きにも注意して下さい。 - ROS2のQoS周りがIPネットワーク的には変化の余地がありそう。SHMとかの単一ホスト向けの改良の方が優先度高そうですが。
はじめに
先日、ROSアドベントカレンダーとして投稿した、AWS-VPC内でROS2(FastDDS-Multicast-UDP)を使ったPub/Subを実行する【相性良い/悪い!?】の補足として、FastDDSがどういったIGMPv2マルチキャストパケットを送出しているか!?
ROSアドカレではカットしたネタがちょっと勿体なかったので引っ張り出してきました。(かなり需要が低そうですが、一部、ROSクラスタの皆様にも役立ちそうなポイントがあったので。)
パケットを見てみる
まず、上記投稿時にAWS上でtcpdumpを実行し、Wiresharkを使って可視化しました。-w ${YOUR_FILE_NAME}.cap
で保存したファイルをインポートするだけです。
Pythonから使ってみて理解する
上記のパケットキャプチャ結果を、コードに落とし込んでみました。
ライブラリとしてScapyを使いました。大体のパケット操作が直感的に行えます。
IGMPについては、該当プロトコルに対する実装部にサンプルコードが記載されています。
from scapy.all import conf, sendp, ARP, Ether, ETHER_BROADCAST, IP, IPOption_Router_Alert
from scapy.contrib.igmp import IGMP
ether_part = Ether(src="0e:a2:67:9e:56:bf", dst="01:00:5e:7f:00:01")
ip_part = IP(src="192.168.110.169", dst="239.255.0.1", tos=0xc0, ttl=1, flags=2, id=0x00, options=[IPOption_Router_Alert()])
igmp_part = IGMP(type=0x17, gaddr="239.255.0.1", mrcode=0)
x = ether_part / ip_part / igmp_part
x[IGMP].igmpize()
sendp(ether_part / ip_part / igmp_part)
Etherヘッダ
scapy/l2.pyで定義される通り、L2(データリンク層)の設定を実施します。
dst=01:00:5e:7f:00:01
のMacアドレスは、マルチキャストグループ239.255.0.1
から求めることが出来ます。詳しくは以下の記事が非常にわかりやすかったです。
マルチキャスト編 マルチキャストアドレッシングとは? | 日経クロステック(xTECH)
IANA(Internet Assigned Numbers Authority)によって規定されているマルチキャスト用のMACアドレスは先頭の25ビットが固定値です。
ROS2で気をつけること
上記の引用元で指摘されていますが、このようなMacアドレスの採番方法を取っていますが、Macアドレス対マルチキャストグループとの関係性は1対1ではありません
今回の例では、
01:00:5e
までがマルチキャスト(224.0.0.0/4)の場合固定になります。これは、2進数表現で 上位25ビット分が固定であるRFC1112の規定によります。
後半7f:00:01
は、マルチキャストグループを示します。マルチキャストグループのIPアドレスの2進数表現で 下位23ビットをミラーしたものです。
完全なマルチキャストグループの情報のうち、9ビット分(32-9=23ビット)の情報が消えています。(第1オクテッドと、第2オクテッドの先頭1ビット)
そのため、Macアドレス対マルチキャストグループは実際には、32対1の関係になります。もしかするとこれが、何か制約となることもある!?!?!?!?という雰囲気を頭の隅っこに入れておくと救われる日が来るかもしれません。
※例えば、FastDDSでデフォルトの239.255.0.1
に対して、一般的に使われるであろう、239.0.0.0/8のプライベートスコープで重複するマルチキャストグループは、239.127.0.1
となります。ROS2以外のアプリケーション(動画配信システム、TV会議システムなど)の動きにも注意して下さい。
# 固定
01 00 5e
00000001 00000000 01011110
# マルチキャストグループ(全32ビットのうち、下位の23ビットがマルチキャストグループのMacアドレスとして採用)
239 255 0 1
|7f 00 01
11101111 1|1111111 00000000 00000001
#^^^^^^^^^情報落ちする
IPヘッダ
layers/inet.pyで定義されており、L3(ネットワーク層)の設定を実施します。
基本的には、IPv4 - Wikipediaの通りのヘッダ構造を埋めていく感じです。
指定されているオプションをざっくりと見てみます。
- src="192.168.110.169"
- 送信元のIPv4アドレス。(AWS Transit Gatewayでは特に使っていないようにも見える、Macアドレスを使っている??)
- tos
- Type of Service
- 転送の優先順位とかを示す。0xc0はInternetwork controlとして上から2番目の優先度(制御用パケットであるため)
- ttl
- Time to live
- マルチキャストの場合、トラフィックが輻輳しないように最小限に設定しておくのが一般的。1であれば同一サブネット内利用を想定している。
- flags
- フラグメント(断片化)の許可の有無。0x02として"禁止"設定されている。(近年は許可で使うことは稀)
- options(RouterAlert)
- RFC2113で定義。ルーターによるスヌーピング(盗み見、検査)を許可するために使用します。AWS Transit Gatewayや、近年発売されている中級機以上のスイッチングハブではこのフラグ有効にしておかないと期待した動作が得られない。
- (なお、筆者はこのオプションの指定の必要性に気がつくことが出来ず半日ほど、悪戦苦闘した。いらないオプションなんてこの世にないのだ。)
ROS2で気をつけること
IGMPとは直接関係ありませんが、IPヘッダという点で気がついたことを挙げておきます。
ROS2にはQoSという、通信品質とリアルタイム性能をコントロールするためのパラメータがありますが、IPヘッダで定義するToSという「DDS」より低いネットワークレイヤの部分では特にコントロールされていないという点が意外でした。その辺については、discourseでも議論されているみたいです。
試しにdemos/quality_of_service_demo at master · ros2/demosにあるデモを使って、各パラメータをいろいろな変えながら、FastDDSの通信をキャプチャしてみましたが、常に「ToS=0x00」と特に優先度の高い設定がせれている訳ではないことが分かりました。この辺が今後どう変わっていく可能性があるのか注目していきたいと思います。
ros2 run quality_of_service_demo_cpp interactive_publisher --delay 0.5 --deadline 1 --liveliness MANUAL_BY_TOPIC --lease 1
ros2 run quality_of_service_demo_cpp interactive_subscriber --deadline 1 --liveliness MANUAL_BY_TOPIC --lease 1
IGMPヘッダ
contrib/igmp.pyで定義されています。
指定されているオプションをざっくりと見てみます。
- type=0x17
- IGMPのタイプ。ホストがマルチキャストグループの参加、維持、離脱を表明するために使用します。
- 0x11:維持(メンバーシップ・クエリ)
- 0x16:参加(メンバーシップ・レポート)
- 0x17:離脱(リーブグループ・メッセージ)
- IGMPのタイプ。ホストがマルチキャストグループの参加、維持、離脱を表明するために使用します。
- mrcode=0
- IGMPメンバーシップ・クエリーに対する、最大応答待ち時間を指定します。
- なお、今回は「参加表明」のメンバーシップ・レポートであるため、ここの数字は意味が無い模様。
- スイッチングハブから送られてくるメンバーシップ・クエリの場合に使用される。
- IGMPメンバーシップ・クエリーに対する、最大応答待ち時間を指定します。
おわりに
今回は、IGMPv2マルチキャストパケットを追いかけることで、マルチキャストへの理解を少しだけ深めることができました。
補足として、FastDDSで送出するIGMP以外の他のパケットについては、4. Understanding the RTPS Packet Format — Using Wireshark with RTI Connext DDS Systems documentationに掲載されています。本記事と同様に、Wiresharkで可視化したものを題材として取り上げて、各メッセージがどういったことを表しているかを事細かに解説されています。マルチキャスト・ユニキャストを巧みに使い分けていて、すごい仕組みだなーと改めて感じました。(小並感)