Description
Solution
This article explains why multicast packets cannot pass through the FortiGate, when the FortiGate is the Last Hop Router and the RP is reachable through another interface than the multicast source.
This article focuses on the Last Hop Router (LHR) only and assumes that multicast/unicast routing is working properly on the others routers.
This article focuses on the Last Hop Router (LHR) only and assumes that multicast/unicast routing is working properly on the others routers.
Solution
Diagram

R3 is the FortiGate (LHR).
OSPF is the IGP and used default cost.
PIM spare mode is configured with R1 and R2
1. The receiver sends an IGMP join to group 239.1.1.1
2. The rendezvous point (RP) is reachable from R3
3. PIM neighbors are correct
4. The sniffer shows incoming multicast packets, but they are not forwarded
5. The multicast routing table displays only the (*,G) entry. The (S,G) entry is not created, meaning incoming multicast packets are rejected
6. Unfortunately the pim-sm debug does not report any issue
7. Looking at the unicast routing table, the source (10.118.9.126) can be seen to be reachable from another interface than the RP
Multicast packet are received on r2_r3_1
When incoming multicast packets reach r2_r3_1, they are silently dropped before reaching PIM daemon by RPF check.
By default the FortiGate performs a RPF check on incoming packets.
If the route back to the source does not match the path the packet is coming from, it is assumed to be fraudulent and dropped.
Solution
There are actually 2 workarounds available:
1. Add static routes to reach the source via r2_r3_1 and r1_r3_1
Both routes are installed in the routing table so the RPF check succeeds.
OR
2. Disable RPF check. The only way to disable RPF check is to disable asymmetric routing
Verification
1. (S,G) entry is now created
2. Packets are forwarded to port2
R3 is the FortiGate (LHR).
OSPF is the IGP and used default cost.
PIM spare mode is configured with R1 and R2
1. The receiver sends an IGMP join to group 239.1.1.1
(R3) # get router info multicast igmp groups
IGMP Connected Group Membership
Group Address Interface Uptime Expires Last Reporter
239.1.1.1 port2 00:01:10 00:03:34 10.144.9.118
2. The rendezvous point (RP) is reachable from R3
(R3) # get router info multicast pim sparse-mode rp-mapping
PIM Group-to-RP Mappings
Group(s): 224.0.0.0/4, Static
RP: 2.2.2.2
Uptime: 00:28:14
(R3) # exe ping 2.2.2.2
PING 2.2.2.2 (2.2.2.2): 56 data bytes
64 bytes from 2.2.2.2: icmp_seq=0 ttl=255 time=0.5 ms
64 bytes from 2.2.2.2: icmp_seq=1 ttl=255 time=0.0 ms
--- 2.2.2.2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.0/0.2/0.5 ms
3. PIM neighbors are correct
(R3) # get router info multicast pim sparse-mode neighbour
Neighbor Interface Uptime/Expires Ver DR
Address Priority/Mode
10.1.3.1 r1_r3_1 00:09:34/00:01:41 v2 1 /
10.2.3.2 r2_r3_1 00:09:35/00:01:41 v2 1 /
(R3) # get router info multicast pim sparse-mode next-hop
Flags: N = New, R = RP, S = Source, U = Unreachable
Destination Type Nexthop Nexthop Nexthop Nexthop Metric Pref Refcnt
Num Addr Ifindex Name
____________________________________________________________________________________
2.2.2.2 .R.. 1 10.2.3.2 24 200 110 4
10.1.3.1 ..S. 1 0.0.0.0 22 0 0 2
10.1.3.3 ..S. 1 0.0.0.0 22 0 0 2
10.2.3.2 ..S. 1 0.0.0.0 24 0 0 2
10.2.3.3 ..S. 1 0.0.0.0 24 0 0 2
10.144.10.33 ..S. 1 0.0.0.0 3 0 0 2
4. The sniffer shows incoming multicast packets, but they are not forwarded
(R3) # diag sniff packet any 'host 239.1.1.1' 4 0 a
2016-02-04 17:03:56.018248 r2_r3_1 in 10.118.9.126.8910 -> 239.1.1.1.8910: udp 32
2016-02-04 17:03:56.518055 r2_r3_1 in 10.118.9.126.8910 -> 239.1.1.1.8910: udp 32
5. The multicast routing table displays only the (*,G) entry. The (S,G) entry is not created, meaning incoming multicast packets are rejected
(R3) # get router info multicast pim sparse-mode table 239.1.1.1
IP Multicast Routing Table
(*,*,RP) Entries: 0
(*,G) Entries: 3
(S,G) Entries: 5
(S,G,rpt) Entries: 8
FCR Entries: 0
(*, 239.1.1.1)
RP: 2.2.2.2
RPF nbr: 10.2.3.2
RPF idx: r2_r3_1
Upstream State: JOINED
Local:
port2
Joined:
Asserted:
FCR:
6. Unfortunately the pim-sm debug does not report any issue
(R3) #diag ip router pim-sm level info
(R3) #diag ip router pim-sm all enable
(R3) #diag debug enable
id=20301 logdesc="Routing log" msg="PIM-SM: IGMP message for 239.1.1.1 on port2 received filter mode EXCL, num sources 0"
id=20301 logdesc="Routing log" msg="PIM-SM: Recv (*, 239.1.1.1) Include on port2"
id=20301 logdesc="Routing log" msg="PIM-SM: Apply (*, 239.1.1.1) Include on port2"
id=20301 logdesc="Routing log" msg="PIM-SM: Group 239.1.1.1 SPT threshold set"
id=20301 logdesc="Routing log" msg="PIM-SM: Nexthop 2.2.2.2: Increment refcnt 1"
id=20301 logdesc="Routing log" msg="PIM-SM: JoinDesired(*,G) => TRUE event for (*, 239.1.1.1)"
id=20301 logdesc="Routing log" msg="PIM-SM: MRIB.next_hop_rp(2.2.2.2): nexthop 10.2.3.2"
id=20301 logdesc="Routing log" msg="PIM-SM: Send Join/Prune message"
id=20301 logdesc="Routing log" msg="PIM-SM: Upstream: 10.2.3.2 (Family 1, Type 0)"
id=20301 logdesc="Routing log" msg="PIM-SM: Rserved: 0"
id=20301 logdesc="Routing log" msg="PIM-SM: Num groups: 1"
id=20301 logdesc="Routing log" msg="PIM-SM: Holdtime: 210"
id=20301 logdesc="Routing log" msg="PIM-SM: Multicast group: 239.1.1.1/32 (Family 1, Type 0)"
id=20301 logdesc="Routing log" msg="PIM-SM: Number of Join: 1"
id=20301 logdesc="Routing log" msg="PIM-SM: Number of Prune: 0"
id=20301 logdesc="Routing log" msg="PIM-SM: Join: (*,G) 2.2.2.2/32 (Family 1, Type 0)"
id=20301 logdesc="Routing log" msg="PIM-SM: US (*, 239.1.1.1): Starting JT timer with 60 secs timeout"
id=20301 logdesc="Routing log" msg="PIM-SM: US (*, 239.1.1.1): NOT JOINED to JOINED, JoinDesired(*,G) => TRUE "
id=20301 logdesc="Routing log" msg="PIM-SM: IGMP message for 239.1.1.1 on port2 received filter mode EXCL, num sources 0"
id=20301 logdesc="Routing log" msg="PIM-SM: Recv (*, 239.1.1.1) Include on port2"
7. Looking at the unicast routing table, the source (10.118.9.126) can be seen to be reachable from another interface than the RP
(R3) # get router info routing-table details 10.118.9.126
Routing entry for 10.118.0.0/20
Known via "ospf", distance 110, metric 101, best
Last update 04:23:00 ago
* 10.1.3.1, via r1_r3_1 <<<<
(R3) # get router info routing-table details 2.2.2.2
Routing entry for 2.2.2.2/32
Known via "ospf", distance 110, metric 200, best
Last update 00:30:56 ago
* 10.2.3.2, via r2_r3_1
Multicast packet are received on r2_r3_1
2016-02-04 17:03:56.518055 r2_r3_1 in 10.118.9.126.8910 -> 239.1.1.1.8910: udp 32
When incoming multicast packets reach r2_r3_1, they are silently dropped before reaching PIM daemon by RPF check.
By default the FortiGate performs a RPF check on incoming packets.
If the route back to the source does not match the path the packet is coming from, it is assumed to be fraudulent and dropped.
Solution
There are actually 2 workarounds available:
1. Add static routes to reach the source via r2_r3_1 and r1_r3_1
config router static
edit 1
set dst 10.118.9.126 255.255.255.255
set gateway 10.1.3.1
set device "r1_r3_1"
next
edit 2
set dst 10.118.9.126 255.255.255.255
set gateway 10.2.3.2
set priority 10 <<<<< higher priority to use it as backup route
set device "r2_r3_1"
next
end
(R3) # get router info routing-table de 10.118.9.126
Routing entry for 10.118.9.126/32
Known via "static", distance 10, metric 0, best
* 10.1.3.1, via r1_r3_1
* 10.2.3.2, via r2_r3_1
Both routes are installed in the routing table so the RPF check succeeds.
OR
2. Disable RPF check. The only way to disable RPF check is to disable asymmetric routing
config system settings
set asymroute enable
end
Verification
1. (S,G) entry is now created
(R3) # get router info multicast pim sparse-mode table 239.1.1.1
IP Multicast Routing Table
(*,*,RP) Entries: 0
(*,G) Entries: 3
(S,G) Entries: 6
(S,G,rpt) Entries: 6
FCR Entries: 0
(*, 239.1.1.1)
RP: 2.2.2.2
RPF nbr: 10.2.3.2
RPF idx: r2_r3_1
Upstream State: JOINED
Local:
port2
Joined:
Asserted:
FCR:
(10.118.9.126, 239.1.1.1)
RPF nbr: 10.1.3.1
RPF idx: r1_r3_1
SPT bit: 1
Upstream State: JOINED
Local:
Joined:
Asserted:
Outgoing:
port2
(10.118.9.126, 239.1.1.1, rpt)
RP: 2.2.2.2
RPF nbr: 10.2.3.2
RPF idx: r2_r3_1
Upstream State: PRUNED
Local:
Pruned:
Outgoing:
port2
2. Packets are forwarded to port2
(R3) # diag sniff packet any 'host 239.1.1.1' 4 0 a
2016-02-05 13:25:13.910440 r1_r3_1 in 10.118.9.126.8910 -> 239.1.1.1.8910: udp 32
2016-02-05 13:25:13.910466 port2 out 10.118.9.126.8910 -> 239.1.1.1.8910: udp 32