マルチキャストにはRPFというループ防止機能が備わっています。パケットの重複や非効率なルーティングを避けるための機能ですが、これが思わぬ疎通不能を引き起こす事もあります。
このコンテンツはもともとはCCIEラボ試験向けの作成したものですが、RPFはLinuxサーバでも定番のハマりポイントです。知らないと、思わぬ疎通不能の解析に時間がかかってしまうので、ネットワークエンジニアに限らずサーバエンジニアも頑張って理解しましょう。
概要
RPF(Reverse Path Forwarding)についてまとめます。RPF checkは、送信元IPアドレスとユニキャストルーティングテーブルを照らし合わせ、最短ルートから来たと判断できないパケットを破棄する機能です。この機能によりマルチキャストパケットの重複を防ぐ事ができますが、時には転送して欲しいパケットまで破棄してしまう事もあります。
RPF 基本動作
動作確認
以下の構成で、Host 1からHost 2への通信について考察します。
なお、検証の都合上、一部のinterfaceのみマルチキャストを有効にしています。
[ip address] 192.168.12.0/24 e0/0 e0/0 .1 .2 e0/2+--------+ cost 10 +--------+e0/2 +--------+ .1| +----------+ | .2 +--------+ | Host 1 +------+ R1 | | R2 +------+ Host 3 + +--------+ | +----------+ | +--------+ 192.168.1.0/24 +--------+ cost 20 +--------+ 192.168.2.0/24 .1 .2 e0/1 e0/1 192.168.21.0/24 R1 Loopback0 R2 Loopback0 10.1.1.1/32 10.2.2.2/32 [multicast domain] e0/2+--------+ +--------+e0/0 +--------+ .1| | | | .3 +--------+ | Host 1 +------+ R1 | | R2 +------+ Host 3 + +--------+ | +----------+ | +--------+ 192.168.1.0/24 +--------+ cost 20 +--------+ 192.168.3.0/24 .1 .2 e0/1 e0/1 192.168.21.0/24
[R1] ip multicast-routing ! interface Loopback0 ip pim dense-mode ! interface Ethernet0/0 ip pim dense-mode ! interface Ethernet0/1 ip pim dense-mode ip ospf cost 20 ! interface Ethernet0/2 ip pim dense-mode [R2] ip multicast-routing ! interface Loopback0 ip pim dense-mode ! interface Ethernet0/0 ip pim dense-mode ! interface Ethernet0/1 ip pim dense-mode ip ospf cost 20 ! interface Ethernet0/2 ip pim dense-mode ip igmp join-group 239.1.1.1
設定全文は下記ファイルです。ルーティングなどの詳細設定は下記を参照ください。
疎通確認
Host 1からHost 2への疎通確認を行います。PIMやIGMPの設定に問題がないのにも関わらず、ping応答がない事が読み取れます。これはRPF checkによりパケットが破棄されているためです。
[R2] interface Ethernet 0/2 ip igmp join-group 239.1.1.1 [R1] R1#ping 239.1.1.1 source Ethernet 0/2 repeat 2 Type escape sequence to abort. Sending 2, 100-byte ICMP Echos to 239.1.1.1, timeout is 2 seconds: Packet sent with a source address of 192.168.1.1 .. R1#
経路確認
RPF checkはユニキャストルーティングテーブルから最短ルートを判断します。この場合、192.168.1.0/24のnext hopは192.168.12.1です。従って、Host 1からのパケットがe0/0以外のinterfaceから入ってきた場合、最短ルートではないと判断してパケットを破棄してしまいます。
R2#show ip route <omitted> Gateway of last resort is not set C 192.168.12.0/24 is directly connected, Ethernet0/0 C 192.168.21.0/24 is directly connected, Ethernet0/1 10.0.0.0/32 is subnetted, 2 subnets C 10.2.2.2 is directly connected, Loopback0 O 10.1.1.1 [110/11] via 192.168.12.1, 00:04:26, Ethernet0/0 O 192.168.1.0/24 [110/20] via 192.168.12.1, 00:04:27, Ethernet0/0 C 192.168.2.0/24 is directly connected, Ethernet0/2 R2#
RPF checkによりパケットが破棄されてしまった事は、マルチキャストルーティングテーブル上で、“Incomming interface: Null”と表記されている事から読み取る事ができます。
R2#show ip mroute 192.168.1.1 239.1.1.1 <omitted> (192.168.1.1, 239.1.1.1), 00:00:39/00:02:20, flags: L Incoming interface: Null, RPF nbr 192.168.12.1 Outgoing interface list: Ethernet0/1, Forward/Dense, 00:00:39/00:00:00 Ethernet0/2, Forward/Dense, 00:00:39/00:00:00 R2#
デバッグメッセージ 確認
RPF checkが行われたかどうかはデバッグメッセージでも確認する事ができます。以下のデバッグを有効にする事でRPF checkの様子を読み取る事ができますが、ログ出力されるのはプロセススイッチングされたパケットのみです。“no ip mroute-cache”も忘れないように注意しましょう。
R2#debug ip mpacket IP multicast packets debugging is on R2# R2(config)#interface Ethernet 0/1 R2(config-if)#no ip mroute-cache
Host 1からHost 2へのpingを送信すると、以下のようなメッセージが出力されます。
R2# *Mar 1 00:27:56.663: IP(0): s=192.168.1.1 (Ethernet0/1) d=239.1.1.1 id=13, ttl=254, prot=1, len=114(100), RPF lookup failed for source *Mar 1 00:27:56.675: IP(0): s=192.168.1.1 (Ethernet0/1) d=239.1.1.1 id=13, ttl=254, prot=1, len=114(100), not RPF interface *Mar 1 00:27:58.631: IP(0): s=192.168.1.1 (Ethernet0/1) d=239.1.1.1 id=14, ttl=254, prot=1, len=114(100), not RPF interface R2#
static mroute
基本設定
RPF checkにおいて、最短ルートであると判断するルータはRPF neighborと呼ばれます。RPF neighborはユニキャストルーティングテーブルを基に生成されますが、この挙動はstatic mrouteにより上書きする事ができます。
以下のコマンドで、送信元アドレスに対するRPF neighborを定義する事ができます。(point-to-point interfaceの場合は、RPF neighborのアドレスではなくマルチキャストパケットの入力interfaceを指定する事もできます)
Router(config)# ip mroute <source_addr> <source_mask> { <rpf_neighbor> | <interface> }
動作確認
R2に以下のstatic mrouteを定義し、Host 1からHost 2への疎通が可能になるようにします。
[R2] ip mroute 192.168.1.0 255.255.255.0 192.168.21.1
Host 1からHost 2へのpingに対し応答がある事を確認します。
[R1] R1#ping 239.1.1.1 source Ethernet 0/2 repeat 2 Type escape sequence to abort. Sending 2, 100-byte ICMP Echos to 239.1.1.1, timeout is 2 seconds: Packet sent with a source address of 192.168.1.1 Reply to request 0 from 192.168.21.2, 76 ms Reply to request 1 from 192.168.21.2, 16 ms R1#
(192.168.1.1, 239.1.1.1)のエントリに対するRPF neighborが192.168.12.1から192.168.21.1に変わった事が読み取れます。また、RPF neighborがstatic mrouteによって生成された場合は、マルチキャストルーティングテーブル上に”Mroute”と表記されます。
R2#show ip mroute <omitted> (192.168.1.1, 239.1.1.1), 00:00:45/00:02:28, flags: LT Incoming interface: Ethernet0/1, RPF nbr 192.168.21.1, Mroute Outgoing interface list: Ethernet0/2, Forward/Dense, 00:00:45/00:00:00
RPF チューニング
基本設定
RPF neighborはstatic mrouteとユニキャストルーティングテーブルにより生成されます。ユニキャストルーティングテーブルの変化に応じてRPF neighborも変化します。ユニキャストルーティングテーブルを参照する頻度を上げれば、それだけRPF neighborの変化も早くなりますが、CPUリソースも枯渇してしまいます。そこで、CPUリソースを節約したい場合は、RPF checkのチューニングをする事もできます。
以下のコマンドで、RPF neighborの定期的なチェックをする間隔を定義する事ができます。
Router(config)# ip multicast rpf interval <sec>
以下のコマンドで、ユニキャストルーティングテーブルが変化した後に、RPF neighborを計算するタイミングを定義する事ができます。<init_msec>はテーブルが変化してからRPF neighborの計算を開始するまでの時間で、<max_msec>はRPF neighborの計算が終わるまでの最大時間です。
Router(config)# ip multicast rpf backoff { <init_msec> <max_msec> | disable }