Description
Solution
This article explains why multicast traffic over redundant interface ends up with duplicate packets on the receiver.
Solution
In the following diagram, the receiver retrieves multicast stream from the sender on multicast address 239.1.1.1.

Unicast routing can be either static or dynamic.
Multicast routing uses PIM sparse mode, FGT2 port9 is the RP.
PIM neighbor is running over redundant interface:
On the receiver, there are 2 copies of the same multicast packet:

Looking at a sniffer trace:
Ingress packet is received on port17:
The same packet is sent out on redundant interface port33,39, then physical interface port33:
The same packet is received on port39:
The reason why the packet is received on port39 is that the switch floods the multicast frames to all ports except the original one.
Remember that flooding of BUM (Broadcast, Unknown unicast and Multicast) is an inherent part of switching.
Focussing on FGT2:
Ingress packet is received on port2 and reaches the redundant interface:
The same packet is sent out on port9 :
In the meantime, the same packet is received on port1 (other member of redundant port1,2):
It is then sent out on port9 resulting in 2 copies of the same packet on the receiver:
The reason why the same packet is received on port1 and port2 is that the switch floods the multicast frames to all ports except the original one.
Hence it is not recommended to use redundant interface when there is multicast traffic on the network.
The only way to prevent the issue explained above is to enable PIM snooping on the switch in between the FortiGates so the switch will snoop the PIM join and PIM prune in order to forward the multicast traffic only to the proper interfaces instead of flooding it.
Unicast routing can be either static or dynamic.
Multicast routing uses PIM sparse mode, FGT2 port9 is the RP.
PIM neighbor is running over redundant interface:
Multicast routing is working properly:FGT1 # get router info multicast pim sparse-mode neighbour
Neighbor Interface Uptime/Expires Ver DR
Address Priority/Mode
192.168.1.19 port33,39 17:14:11/00:01:30 v2 1 / DR
FGT2 # get router info multicast pim sparse-mode neighbour
Neighbor Interface Uptime/Expires Ver DR
Address Priority/Mode
192.168.1.18 port1,2 17:15:05/00:01:39 v2 1 /
FGT1 # get router info multicast pim sparse-mode table 239.1.1.1
IP Multicast Routing Table
(*,*,RP) Entries: 0
(*,G) Entries: 1
(S,G) Entries: 2
(S,G,rpt) Entries: 1
FCR Entries: 0
(10.1.1.2, 239.1.1.1)
RPF nbr: 0.0.0.0
RPF idx: None
SPT bit: 1
Upstream State: JOINED
Local:
Joined:
port33,39
Asserted:
port33,39: winner
Outgoing:
port33,39
(10.1.1.2, 239.1.1.1, rpt)
RP: 0.0.0.0
RPF nbr: 192.168.1.19
RPF idx: port33,39
Upstream State: RPT NOT JOINED
Local:
Pruned:
Outgoing:
FGT2 # get router info multicast pim sparse-mode table 239.1.1.1
IP Multicast Routing Table
(*,*,RP) Entries: 0
(*,G) Entries: 4
(S,G) Entries: 2
(S,G,rpt) Entries: 2
FCR Entries: 0
(*, 239.1.1.1)
RP: 10.2.2.1
RPF nbr: 0.0.0.0
RPF idx: None
Upstream State: JOINED
Local:
port9
Joined:
Asserted:
FCR:
(10.1.1.2, 239.1.1.1)
RPF nbr: 192.168.1.18
RPF idx: port1,2
SPT bit: 1
Upstream State: JOINED
Local:
Joined:
Asserted:
port1,2: loser
Outgoing:
port9
(10.1.1.2, 239.1.1.1, rpt)
RP: 10.2.2.1
RPF nbr: 0.0.0.0
RPF idx: None
Upstream State: PRUNED
Local:
Pruned:
Outgoing:
port9
On the receiver, there are 2 copies of the same multicast packet:
Looking at a sniffer trace:
FGT1 # diag sniffer packet any 'host 239.1.1.1' 4 0Focussing on FGT1:
7.936514 port17 in 10.1.1.2 -> 239.1.1.1: icmp: echo request
7.936523 port33,39 out 10.1.1.2 -> 239.1.1.1: icmp: echo request
7.936524 port33 out 10.1.1.2 -> 239.1.1.1: icmp: echo request
7.936533 port39 in 10.1.1.2 -> 239.1.1.1: icmp: echo request
7.936533 port33,39 in 10.1.1.2 -> 239.1.1.1: icmp: echo request
FGT2 # diag sniffer packet any 'host 239.1.1.1' 4 0
8.665930 port2 in 10.1.1.2 -> 239.1.1.1: icmp: echo request
8.665931 port1,2 in 10.1.1.2 -> 239.1.1.1: icmp: echo request
8.665935 port9 out 10.1.1.2 -> 239.1.1.1: icmp: echo request
8.665936 port1 in 10.1.1.2 -> 239.1.1.1: icmp: echo request
8.665936 port1,2 in 10.1.1.2 -> 239.1.1.1: icmp: echo request
8.665938 port9 out 10.1.1.2 -> 239.1.1.1: icmp: echo request
Ingress packet is received on port17:
7.936514 port17 in 10.1.1.2 -> 239.1.1.1: icmp: echo request
The same packet is sent out on redundant interface port33,39, then physical interface port33:
7.936523 port33,39 out 10.1.1.2 -> 239.1.1.1: icmp: echo request
7.936524 port33 out 10.1.1.2 -> 239.1.1.1: icmp: echo request
The same packet is received on port39:
7.936533 port39 in 10.1.1.2 -> 239.1.1.1: icmp: echo request
The reason why the packet is received on port39 is that the switch floods the multicast frames to all ports except the original one.
Remember that flooding of BUM (Broadcast, Unknown unicast and Multicast) is an inherent part of switching.
Focussing on FGT2:
Ingress packet is received on port2 and reaches the redundant interface:
8.665930 port2 in 10.1.1.2 -> 239.1.1.1: icmp: echo request
8.665931 port1,2 in 10.1.1.2 -> 239.1.1.1: icmp: echo request
The same packet is sent out on port9 :
8.665935 port9 out 10.1.1.2 -> 239.1.1.1: icmp: echo request
In the meantime, the same packet is received on port1 (other member of redundant port1,2):
8.665936 port1 in 10.1.1.2 -> 239.1.1.1: icmp: echo request
8.665936 port1,2 in 10.1.1.2 -> 239.1.1.1: icmp: echo request
It is then sent out on port9 resulting in 2 copies of the same packet on the receiver:
8.665938 port9 out 10.1.1.2 -> 239.1.1.1: icmp: echo request
The reason why the same packet is received on port1 and port2 is that the switch floods the multicast frames to all ports except the original one.
Hence it is not recommended to use redundant interface when there is multicast traffic on the network.
The only way to prevent the issue explained above is to enable PIM snooping on the switch in between the FortiGates so the switch will snoop the PIM join and PIM prune in order to forward the multicast traffic only to the proper interfaces instead of flooding it.