blob: c3ac16c6d85ab501ab05f59ce62fb17d2c3dc2b2 [file] [log] [blame]
Renato Botelho do Coutoead1e532019-10-31 13:31:07 -05001#!/usr/bin/env python3
Neale Ranns32e1c012016-11-22 17:07:28 +00002
3import unittest
4
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00005from framework import tag_fixme_vpp_workers
Neale Ranns32e1c012016-11-22 17:07:28 +00006from framework import VppTestCase, VppTestRunner
Neale Rannsc0a93142018-09-05 15:42:26 -07007from vpp_ip import DpoProto
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02008from vpp_ip_route import (
9 VppIpMRoute,
10 VppMRoutePath,
11 VppMFibSignal,
12 VppIpTable,
13 FibPathProto,
14 FibPathType,
15)
Neale Rannsadb17a82019-08-04 02:41:57 -070016from vpp_gre_interface import VppGreInterface
Neale Ranns990f6942020-10-20 07:20:17 +000017from vpp_papi import VppEnum
Neale Ranns32e1c012016-11-22 17:07:28 +000018
19from scapy.packet import Raw
Neale Rannsadb17a82019-08-04 02:41:57 -070020from scapy.layers.l2 import Ether, GRE
Neale Ranns13721782021-05-13 15:28:27 +000021from scapy.layers.inet import IP, UDP, getmacbyip, ICMP
Neale Ranns32e1c012016-11-22 17:07:28 +000022from scapy.layers.inet6 import IPv6, getmacbyip6
Neale Ranns32e1c012016-11-22 17:07:28 +000023
Neale Ranns9bea8fb2017-02-03 04:34:01 -080024#
Neale Rannscf3561b2017-12-13 01:44:25 -080025# The number of packets sent is set to 91 so that when we replicate more than 3
Neale Ranns9bea8fb2017-02-03 04:34:01 -080026# times, which we do for some entries, we will generate more than 256 packets
Neale Rannsaaa396a2017-02-05 09:12:02 -080027# to the next node in the VLIB graph. Thus we are testing the code's
Neale Rannscf3561b2017-12-13 01:44:25 -080028# correctness handling this over-flow.
29# It's also an odd number so we hit any single loops.
Neale Ranns9bea8fb2017-02-03 04:34:01 -080030#
Neale Rannscf3561b2017-12-13 01:44:25 -080031N_PKTS_IN_STREAM = 91
Neale Ranns9bea8fb2017-02-03 04:34:01 -080032
Neale Ranns32e1c012016-11-22 17:07:28 +000033
Neale Ranns5a8123b2017-01-26 01:18:23 -080034class TestMFIB(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020035 """MFIB Test Case"""
Neale Ranns5a8123b2017-01-26 01:18:23 -080036
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070037 @classmethod
38 def setUpClass(cls):
39 super(TestMFIB, cls).setUpClass()
40
41 @classmethod
42 def tearDownClass(cls):
43 super(TestMFIB, cls).tearDownClass()
44
Neale Ranns5a8123b2017-01-26 01:18:23 -080045 def setUp(self):
46 super(TestMFIB, self).setUp()
47
48 def test_mfib(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020049 """MFIB Unit Tests"""
Neale Ranns5a8123b2017-01-26 01:18:23 -080050 error = self.vapi.cli("test mfib")
51
52 if error:
53 self.logger.critical(error)
Paul Vinciguerra9a6dafd2019-03-06 15:11:28 -080054 self.assertNotIn("Failed", error)
Neale Ranns5a8123b2017-01-26 01:18:23 -080055
56
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +000057@tag_fixme_vpp_workers
Neale Ranns32e1c012016-11-22 17:07:28 +000058class TestIPMcast(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020059 """IP Multicast Test Case"""
Neale Ranns32e1c012016-11-22 17:07:28 +000060
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070061 @classmethod
62 def setUpClass(cls):
63 super(TestIPMcast, cls).setUpClass()
64
65 @classmethod
66 def tearDownClass(cls):
67 super(TestIPMcast, cls).tearDownClass()
68
Neale Ranns32e1c012016-11-22 17:07:28 +000069 def setUp(self):
70 super(TestIPMcast, self).setUp()
71
Neale Ranns37be7362017-02-21 17:30:26 -080072 # create 8 pg interfaces
Neale Ranns15002542017-09-10 04:39:11 -070073 self.create_pg_interfaces(range(9))
Neale Ranns32e1c012016-11-22 17:07:28 +000074
75 # setup interfaces
Neale Ranns15002542017-09-10 04:39:11 -070076 for i in self.pg_interfaces[:8]:
Neale Ranns32e1c012016-11-22 17:07:28 +000077 i.admin_up()
78 i.config_ip4()
79 i.config_ip6()
80 i.resolve_arp()
81 i.resolve_ndp()
82
Neale Ranns15002542017-09-10 04:39:11 -070083 # one more in a vrf
84 tbl4 = VppIpTable(self, 10)
85 tbl4.add_vpp_config()
86 self.pg8.set_table_ip4(10)
87 self.pg8.config_ip4()
88
89 tbl6 = VppIpTable(self, 10, is_ip6=1)
90 tbl6.add_vpp_config()
91 self.pg8.set_table_ip6(10)
92 self.pg8.config_ip6()
93
94 def tearDown(self):
95 for i in self.pg_interfaces:
96 i.unconfig_ip4()
97 i.unconfig_ip6()
98 i.admin_down()
99
100 self.pg8.set_table_ip4(0)
101 self.pg8.set_table_ip6(0)
102 super(TestIPMcast, self).tearDown()
103
Neale Ranns9d676af2017-03-15 01:28:31 -0700104 def create_stream_ip4(self, src_if, src_ip, dst_ip, payload_size=0):
Neale Ranns32e1c012016-11-22 17:07:28 +0000105 pkts = []
Neale Ranns9d676af2017-03-15 01:28:31 -0700106 # default to small packet sizes
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200107 p = (
108 Ether(dst=getmacbyip(dst_ip), src=src_if.remote_mac)
109 / IP(src=src_ip, dst=dst_ip)
110 / UDP(sport=1234, dport=1234)
111 )
Neale Ranns9d676af2017-03-15 01:28:31 -0700112 if not payload_size:
113 payload_size = 64 - len(p)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200114 p = p / Raw(b"\xa5" * payload_size)
Neale Ranns9d676af2017-03-15 01:28:31 -0700115
Neale Ranns9bea8fb2017-02-03 04:34:01 -0800116 for i in range(0, N_PKTS_IN_STREAM):
Neale Ranns32e1c012016-11-22 17:07:28 +0000117 pkts.append(p)
118 return pkts
119
120 def create_stream_ip6(self, src_if, src_ip, dst_ip):
121 pkts = []
Neale Ranns9bea8fb2017-02-03 04:34:01 -0800122 for i in range(0, N_PKTS_IN_STREAM):
Neale Ranns32e1c012016-11-22 17:07:28 +0000123 info = self.create_packet_info(src_if, src_if)
124 payload = self.info_to_payload(info)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200125 p = (
126 Ether(dst=getmacbyip6(dst_ip), src=src_if.remote_mac)
127 / IPv6(src=src_ip, dst=dst_ip)
128 / UDP(sport=1234, dport=1234)
129 / Raw(payload)
130 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000131 info.data = p.copy()
132 pkts.append(p)
133 return pkts
134
135 def verify_filter(self, capture, sent):
136 if not len(capture) == len(sent):
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700137 # filter out any IPv6 RAs from the capture
Neale Ranns32e1c012016-11-22 17:07:28 +0000138 for p in capture:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200139 if p.haslayer(IPv6):
Neale Ranns32e1c012016-11-22 17:07:28 +0000140 capture.remove(p)
141 return capture
142
Neale Rannse821ab12017-06-01 07:45:05 -0700143 def verify_capture_ip4(self, rx_if, sent, dst_mac=None):
Neale Rannsc2aad532017-05-30 09:53:52 -0700144 rxd = rx_if.get_capture(len(sent))
Neale Ranns32e1c012016-11-22 17:07:28 +0000145
146 try:
147 capture = self.verify_filter(rxd, sent)
148
149 self.assertEqual(len(capture), len(sent))
150
151 for i in range(len(capture)):
152 tx = sent[i]
153 rx = capture[i]
154
Neale Ranns32e1c012016-11-22 17:07:28 +0000155 eth = rx[Ether]
156 self.assertEqual(eth.type, 0x800)
157
158 tx_ip = tx[IP]
159 rx_ip = rx[IP]
160
Neale Rannse821ab12017-06-01 07:45:05 -0700161 if dst_mac is None:
162 dst_mac = getmacbyip(rx_ip.dst)
163
Neale Ranns32e1c012016-11-22 17:07:28 +0000164 # check the MAC address on the RX'd packet is correctly formed
Neale Rannse821ab12017-06-01 07:45:05 -0700165 self.assertEqual(eth.dst, dst_mac)
Neale Ranns32e1c012016-11-22 17:07:28 +0000166
167 self.assertEqual(rx_ip.src, tx_ip.src)
168 self.assertEqual(rx_ip.dst, tx_ip.dst)
169 # IP processing post pop has decremented the TTL
170 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
171
172 except:
173 raise
174
Neale Rannsc2aad532017-05-30 09:53:52 -0700175 def verify_capture_ip6(self, rx_if, sent):
176 capture = rx_if.get_capture(len(sent))
Neale Ranns32e1c012016-11-22 17:07:28 +0000177
178 self.assertEqual(len(capture), len(sent))
179
180 for i in range(len(capture)):
181 tx = sent[i]
182 rx = capture[i]
183
Neale Ranns32e1c012016-11-22 17:07:28 +0000184 eth = rx[Ether]
185 self.assertEqual(eth.type, 0x86DD)
186
187 tx_ip = tx[IPv6]
188 rx_ip = rx[IPv6]
189
190 # check the MAC address on the RX'd packet is correctly formed
191 self.assertEqual(eth.dst, getmacbyip6(rx_ip.dst))
192
193 self.assertEqual(rx_ip.src, tx_ip.src)
194 self.assertEqual(rx_ip.dst, tx_ip.dst)
195 # IP processing post pop has decremented the TTL
196 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
197
198 def test_ip_mcast(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200199 """IP Multicast Replication"""
Neale Ranns32e1c012016-11-22 17:07:28 +0000200
Neale Ranns990f6942020-10-20 07:20:17 +0000201 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
202 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
203
Neale Ranns32e1c012016-11-22 17:07:28 +0000204 #
205 # a stream that matches the default route. gets dropped.
206 #
207 self.vapi.cli("clear trace")
Neale Ranns21fb4f72020-10-05 12:26:47 +0000208 self.vapi.cli("packet mac-filter pg0 on")
209 self.vapi.cli("packet mac-filter pg1 on")
210 self.vapi.cli("packet mac-filter pg2 on")
211 self.vapi.cli("packet mac-filter pg4 on")
212 self.vapi.cli("packet mac-filter pg5 on")
213 self.vapi.cli("packet mac-filter pg6 on")
214 self.vapi.cli("packet mac-filter pg7 on")
215
Neale Ranns32e1c012016-11-22 17:07:28 +0000216 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.1")
217 self.pg0.add_stream(tx)
218
219 self.pg_enable_capture(self.pg_interfaces)
220 self.pg_start()
221
222 self.pg0.assert_nothing_captured(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200223 remark="IP multicast packets forwarded on default route"
224 )
Neale Rannse8f57d52021-10-12 07:49:37 +0000225 count = self.statistics.get_err_counter(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200226 "/err/ip4-input/Multicast RPF check failed"
227 )
Neale Rannse8f57d52021-10-12 07:49:37 +0000228 self.assertEqual(count, len(tx))
Neale Ranns32e1c012016-11-22 17:07:28 +0000229
230 #
231 # A (*,G).
Neale Ranns37be7362017-02-21 17:30:26 -0800232 # one accepting interface, pg0, 7 forwarding interfaces
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700233 # many forwarding interfaces test the case where the replicate DPO
Neale Ranns37be7362017-02-21 17:30:26 -0800234 # needs to use extra cache lines for the buckets.
Neale Ranns32e1c012016-11-22 17:07:28 +0000235 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800236 route_232_1_1_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000237 self,
238 "0.0.0.0",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200239 "232.1.1.1",
240 32,
Neale Ranns990f6942020-10-20 07:20:17 +0000241 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200242 [
243 VppMRoutePath(
244 self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
245 ),
246 VppMRoutePath(
247 self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
248 ),
249 VppMRoutePath(
250 self.pg2.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
251 ),
252 VppMRoutePath(
253 self.pg3.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
254 ),
255 VppMRoutePath(
256 self.pg4.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
257 ),
258 VppMRoutePath(
259 self.pg5.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
260 ),
261 VppMRoutePath(
262 self.pg6.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
263 ),
264 VppMRoutePath(
265 self.pg7.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
266 ),
267 ],
268 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000269 route_232_1_1_1.add_vpp_config()
270
271 #
272 # An (S,G).
273 # one accepting interface, pg0, 2 forwarding interfaces
274 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800275 route_1_1_1_1_232_1_1_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000276 self,
277 "1.1.1.1",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200278 "232.1.1.1",
279 27, # any grp-len is ok when src is set
Neale Ranns990f6942020-10-20 07:20:17 +0000280 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200281 [
282 VppMRoutePath(
283 self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
284 ),
285 VppMRoutePath(
286 self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
287 ),
288 VppMRoutePath(
289 self.pg2.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
290 ),
291 ],
292 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000293 route_1_1_1_1_232_1_1_1.add_vpp_config()
294
295 #
Neale Rannse821ab12017-06-01 07:45:05 -0700296 # An (S,G).
297 # one accepting interface, pg0, 2 forwarding interfaces
298 # that use unicast next-hops
299 #
300 route_1_1_1_1_232_1_1_2 = VppIpMRoute(
301 self,
302 "1.1.1.1",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200303 "232.1.1.2",
304 64,
Neale Ranns990f6942020-10-20 07:20:17 +0000305 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200306 [
307 VppMRoutePath(
308 self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
309 ),
310 VppMRoutePath(
311 self.pg1.sw_if_index,
312 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
313 nh=self.pg1.remote_ip4,
314 ),
315 VppMRoutePath(
316 self.pg2.sw_if_index,
317 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
318 nh=self.pg2.remote_ip4,
319 ),
320 ],
321 )
Neale Rannse821ab12017-06-01 07:45:05 -0700322 route_1_1_1_1_232_1_1_2.add_vpp_config()
323
324 #
Neale Ranns32e1c012016-11-22 17:07:28 +0000325 # An (*,G/m).
326 # one accepting interface, pg0, 1 forwarding interfaces
327 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800328 route_232 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000329 self,
330 "0.0.0.0",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200331 "232.0.0.0",
332 8,
Neale Ranns990f6942020-10-20 07:20:17 +0000333 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200334 [
335 VppMRoutePath(
336 self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
337 ),
338 VppMRoutePath(
339 self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
340 ),
341 ],
342 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000343 route_232.add_vpp_config()
344
345 #
346 # a stream that matches the route for (1.1.1.1,232.1.1.1)
Neale Ranns9d676af2017-03-15 01:28:31 -0700347 # small packets
Neale Ranns32e1c012016-11-22 17:07:28 +0000348 #
349 self.vapi.cli("clear trace")
350 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.1")
351 self.pg0.add_stream(tx)
352
353 self.pg_enable_capture(self.pg_interfaces)
354 self.pg_start()
355
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200356 self.assertEqual(route_1_1_1_1_232_1_1_1.get_stats()["packets"], len(tx))
Neale Ranns28c142e2018-09-07 09:37:07 -0700357
Neale Ranns37be7362017-02-21 17:30:26 -0800358 # We expect replications on Pg1->7
Neale Ranns32e1c012016-11-22 17:07:28 +0000359 self.verify_capture_ip4(self.pg1, tx)
360 self.verify_capture_ip4(self.pg2, tx)
361
362 # no replications on Pg0
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200363 self.pg0.assert_nothing_captured(remark="IP multicast packets forwarded on PG0")
364 self.pg3.assert_nothing_captured(remark="IP multicast packets forwarded on PG3")
Neale Ranns32e1c012016-11-22 17:07:28 +0000365
366 #
Neale Ranns9d676af2017-03-15 01:28:31 -0700367 # a stream that matches the route for (1.1.1.1,232.1.1.1)
368 # large packets
369 #
370 self.vapi.cli("clear trace")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200371 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.1", payload_size=1024)
Neale Ranns9d676af2017-03-15 01:28:31 -0700372 self.pg0.add_stream(tx)
373
374 self.pg_enable_capture(self.pg_interfaces)
375 self.pg_start()
376
377 # We expect replications on Pg1->7
378 self.verify_capture_ip4(self.pg1, tx)
379 self.verify_capture_ip4(self.pg2, tx)
Neale Ranns9d676af2017-03-15 01:28:31 -0700380
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200381 self.assertEqual(route_1_1_1_1_232_1_1_1.get_stats()["packets"], 2 * len(tx))
Neale Ranns28c142e2018-09-07 09:37:07 -0700382
Neale Ranns9d676af2017-03-15 01:28:31 -0700383 # no replications on Pg0
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200384 self.pg0.assert_nothing_captured(remark="IP multicast packets forwarded on PG0")
385 self.pg3.assert_nothing_captured(remark="IP multicast packets forwarded on PG3")
Neale Ranns9d676af2017-03-15 01:28:31 -0700386
387 #
Neale Rannse821ab12017-06-01 07:45:05 -0700388 # a stream to the unicast next-hops
389 #
390 self.vapi.cli("clear trace")
391 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.2")
392 self.pg0.add_stream(tx)
393
394 self.pg_enable_capture(self.pg_interfaces)
395 self.pg_start()
396
397 # We expect replications on Pg1->7
398 self.verify_capture_ip4(self.pg1, tx, dst_mac=self.pg1.remote_mac)
399 self.verify_capture_ip4(self.pg2, tx, dst_mac=self.pg2.remote_mac)
400
401 # no replications on Pg0 nor pg3
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200402 self.pg0.assert_nothing_captured(remark="IP multicast packets forwarded on PG0")
403 self.pg3.assert_nothing_captured(remark="IP multicast packets forwarded on PG3")
Neale Rannse821ab12017-06-01 07:45:05 -0700404
405 #
Neale Ranns32e1c012016-11-22 17:07:28 +0000406 # a stream that matches the route for (*,232.0.0.0/8)
407 # Send packets with the 9th bit set so we test the correct clearing
408 # of that bit in the mac rewrite
409 #
410 self.vapi.cli("clear trace")
411 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.255.255.255")
412 self.pg0.add_stream(tx)
413
414 self.pg_enable_capture(self.pg_interfaces)
415 self.pg_start()
416
417 # We expect replications on Pg1 only
418 self.verify_capture_ip4(self.pg1, tx)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200419 self.assertEqual(route_232.get_stats()["packets"], len(tx))
Neale Ranns32e1c012016-11-22 17:07:28 +0000420
421 # no replications on Pg0, Pg2 not Pg3
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200422 self.pg0.assert_nothing_captured(remark="IP multicast packets forwarded on PG0")
423 self.pg2.assert_nothing_captured(remark="IP multicast packets forwarded on PG2")
424 self.pg3.assert_nothing_captured(remark="IP multicast packets forwarded on PG3")
Neale Ranns32e1c012016-11-22 17:07:28 +0000425
426 #
427 # a stream that matches the route for (*,232.1.1.1)
428 #
429 self.vapi.cli("clear trace")
430 tx = self.create_stream_ip4(self.pg0, "1.1.1.2", "232.1.1.1")
431 self.pg0.add_stream(tx)
432
433 self.pg_enable_capture(self.pg_interfaces)
434 self.pg_start()
435
Neale Rannse821ab12017-06-01 07:45:05 -0700436 # We expect replications on Pg1->7
Neale Ranns32e1c012016-11-22 17:07:28 +0000437 self.verify_capture_ip4(self.pg1, tx)
438 self.verify_capture_ip4(self.pg2, tx)
439 self.verify_capture_ip4(self.pg3, tx)
Neale Rannsc2aad532017-05-30 09:53:52 -0700440 self.verify_capture_ip4(self.pg4, tx)
441 self.verify_capture_ip4(self.pg5, tx)
442 self.verify_capture_ip4(self.pg6, tx)
443 self.verify_capture_ip4(self.pg7, tx)
Neale Ranns32e1c012016-11-22 17:07:28 +0000444
Neale Rannse821ab12017-06-01 07:45:05 -0700445 # no replications on Pg0
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200446 self.pg0.assert_nothing_captured(remark="IP multicast packets forwarded on PG0")
Neale Rannse821ab12017-06-01 07:45:05 -0700447
Neale Ranns21fb4f72020-10-05 12:26:47 +0000448 self.vapi.cli("packet mac-filter pg0 off")
449 self.vapi.cli("packet mac-filter pg1 off")
450 self.vapi.cli("packet mac-filter pg2 off")
451 self.vapi.cli("packet mac-filter pg4 off")
452 self.vapi.cli("packet mac-filter pg5 off")
453 self.vapi.cli("packet mac-filter pg6 off")
454 self.vapi.cli("packet mac-filter pg7 off")
455
Neale Ranns32e1c012016-11-22 17:07:28 +0000456 def test_ip6_mcast(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200457 """IPv6 Multicast Replication"""
Neale Ranns32e1c012016-11-22 17:07:28 +0000458
Neale Ranns990f6942020-10-20 07:20:17 +0000459 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
460 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
461
Neale Ranns21fb4f72020-10-05 12:26:47 +0000462 self.vapi.cli("packet mac-filter pg0 on")
463 self.vapi.cli("packet mac-filter pg1 on")
464 self.vapi.cli("packet mac-filter pg2 on")
465 self.vapi.cli("packet mac-filter pg4 on")
466 self.vapi.cli("packet mac-filter pg5 on")
467 self.vapi.cli("packet mac-filter pg6 on")
468 self.vapi.cli("packet mac-filter pg7 on")
Neale Ranns32e1c012016-11-22 17:07:28 +0000469 #
470 # a stream that matches the default route. gets dropped.
471 #
472 self.vapi.cli("clear trace")
473 tx = self.create_stream_ip6(self.pg0, "2001::1", "ff01::1")
474 self.pg0.add_stream(tx)
475
476 self.pg_enable_capture(self.pg_interfaces)
477 self.pg_start()
478
479 self.pg0.assert_nothing_captured(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200480 remark="IPv6 multicast packets forwarded on default route"
481 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000482
483 #
484 # A (*,G).
485 # one accepting interface, pg0, 3 forwarding interfaces
486 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800487 route_ff01_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000488 self,
489 "::",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200490 "ff01::1",
491 128,
Neale Ranns990f6942020-10-20 07:20:17 +0000492 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200493 [
494 VppMRoutePath(
495 self.pg0.sw_if_index,
496 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT,
497 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
498 ),
499 VppMRoutePath(
500 self.pg1.sw_if_index,
501 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
502 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
503 ),
504 VppMRoutePath(
505 self.pg2.sw_if_index,
506 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
507 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
508 ),
509 VppMRoutePath(
510 self.pg3.sw_if_index,
511 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
512 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
513 ),
514 ],
515 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000516 route_ff01_1.add_vpp_config()
517
518 #
519 # An (S,G).
520 # one accepting interface, pg0, 2 forwarding interfaces
521 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800522 route_2001_ff01_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000523 self,
524 "2001::1",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200525 "ff01::1",
526 0, # any grp-len is ok when src is set
Neale Ranns990f6942020-10-20 07:20:17 +0000527 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200528 [
529 VppMRoutePath(
530 self.pg0.sw_if_index,
531 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT,
532 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
533 ),
534 VppMRoutePath(
535 self.pg1.sw_if_index,
536 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
537 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
538 ),
539 VppMRoutePath(
540 self.pg2.sw_if_index,
541 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
542 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
543 ),
544 ],
545 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000546 route_2001_ff01_1.add_vpp_config()
547
548 #
549 # An (*,G/m).
550 # one accepting interface, pg0, 1 forwarding interface
551 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800552 route_ff01 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000553 self,
554 "::",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200555 "ff01::",
556 16,
Neale Ranns990f6942020-10-20 07:20:17 +0000557 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200558 [
559 VppMRoutePath(
560 self.pg0.sw_if_index,
561 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT,
562 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
563 ),
564 VppMRoutePath(
565 self.pg1.sw_if_index,
566 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
567 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
568 ),
569 ],
570 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000571 route_ff01.add_vpp_config()
572
573 #
574 # a stream that matches the route for (*, ff01::/16)
Neale Rannsce111d22018-01-23 08:38:50 -0800575 # sent on the non-accepting interface
576 #
577 self.vapi.cli("clear trace")
578 tx = self.create_stream_ip6(self.pg1, "2002::1", "ff01:2::255")
579 self.send_and_assert_no_replies(self.pg1, tx, "RPF miss")
Neale Rannse8f57d52021-10-12 07:49:37 +0000580 count = self.statistics.get_err_counter(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200581 "/err/ip6-input/Multicast RPF check failed"
582 )
Neale Rannse8f57d52021-10-12 07:49:37 +0000583 self.assertEqual(count, 2 * len(tx))
Neale Rannsce111d22018-01-23 08:38:50 -0800584
585 #
586 # a stream that matches the route for (*, ff01::/16)
587 # sent on the accepting interface
Neale Ranns32e1c012016-11-22 17:07:28 +0000588 #
589 self.vapi.cli("clear trace")
590 tx = self.create_stream_ip6(self.pg0, "2002::1", "ff01:2::255")
591 self.pg0.add_stream(tx)
592
593 self.pg_enable_capture(self.pg_interfaces)
594 self.pg_start()
595
596 # We expect replications on Pg1
597 self.verify_capture_ip6(self.pg1, tx)
598
599 # no replications on Pg0, Pg3
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200600 self.pg0.assert_nothing_captured(remark="IP multicast packets forwarded on PG0")
601 self.pg2.assert_nothing_captured(remark="IP multicast packets forwarded on PG2")
602 self.pg3.assert_nothing_captured(remark="IP multicast packets forwarded on PG3")
Neale Ranns32e1c012016-11-22 17:07:28 +0000603
604 #
Neale Rannsc2aad532017-05-30 09:53:52 -0700605 # Bounce the interface and it should still work
606 #
607 self.pg1.admin_down()
608 self.pg0.add_stream(tx)
609 self.pg_enable_capture(self.pg_interfaces)
610 self.pg_start()
611 self.pg1.assert_nothing_captured(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200612 remark="IP multicast packets forwarded on down PG1"
613 )
Neale Rannsc2aad532017-05-30 09:53:52 -0700614
615 self.pg1.admin_up()
616 self.pg0.add_stream(tx)
617 self.pg_enable_capture(self.pg_interfaces)
618 self.pg_start()
619 self.verify_capture_ip6(self.pg1, tx)
620
621 #
Neale Ranns32e1c012016-11-22 17:07:28 +0000622 # a stream that matches the route for (*,ff01::1)
623 #
624 self.vapi.cli("clear trace")
625 tx = self.create_stream_ip6(self.pg0, "2002::2", "ff01::1")
626 self.pg0.add_stream(tx)
627
628 self.pg_enable_capture(self.pg_interfaces)
629 self.pg_start()
630
631 # We expect replications on Pg1, 2, 3.
632 self.verify_capture_ip6(self.pg1, tx)
633 self.verify_capture_ip6(self.pg2, tx)
634 self.verify_capture_ip6(self.pg3, tx)
635
636 # no replications on Pg0
637 self.pg0.assert_nothing_captured(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200638 remark="IPv6 multicast packets forwarded on PG0"
639 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000640
641 #
642 # a stream that matches the route for (2001::1, ff00::1)
643 #
644 self.vapi.cli("clear trace")
645 tx = self.create_stream_ip6(self.pg0, "2001::1", "ff01::1")
646 self.pg0.add_stream(tx)
647
648 self.pg_enable_capture(self.pg_interfaces)
649 self.pg_start()
650
651 # We expect replications on Pg1, 2,
652 self.verify_capture_ip6(self.pg1, tx)
653 self.verify_capture_ip6(self.pg2, tx)
654
655 # no replications on Pg0, Pg3
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200656 self.pg0.assert_nothing_captured(remark="IP multicast packets forwarded on PG0")
657 self.pg3.assert_nothing_captured(remark="IP multicast packets forwarded on PG3")
Neale Ranns32e1c012016-11-22 17:07:28 +0000658
Neale Ranns21fb4f72020-10-05 12:26:47 +0000659 self.vapi.cli("packet mac-filter pg0 off")
660 self.vapi.cli("packet mac-filter pg1 off")
661 self.vapi.cli("packet mac-filter pg2 off")
662 self.vapi.cli("packet mac-filter pg4 off")
663 self.vapi.cli("packet mac-filter pg5 off")
664 self.vapi.cli("packet mac-filter pg6 off")
665 self.vapi.cli("packet mac-filter pg7 off")
666
Neale Ranns32e1c012016-11-22 17:07:28 +0000667 def _mcast_connected_send_stream(self, dst_ip):
668 self.vapi.cli("clear trace")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200669 tx = self.create_stream_ip4(self.pg0, self.pg0.remote_ip4, dst_ip)
Neale Ranns32e1c012016-11-22 17:07:28 +0000670 self.pg0.add_stream(tx)
671
672 self.pg_enable_capture(self.pg_interfaces)
673 self.pg_start()
674
675 # We expect replications on Pg1.
676 self.verify_capture_ip4(self.pg1, tx)
677
678 return tx
679
680 def test_ip_mcast_connected(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200681 """IP Multicast Connected Source check"""
Neale Ranns32e1c012016-11-22 17:07:28 +0000682
Neale Ranns990f6942020-10-20 07:20:17 +0000683 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
684 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
685
Neale Ranns32e1c012016-11-22 17:07:28 +0000686 #
687 # A (*,G).
688 # one accepting interface, pg0, 1 forwarding interfaces
689 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800690 route_232_1_1_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000691 self,
692 "0.0.0.0",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200693 "232.1.1.1",
694 32,
Neale Ranns990f6942020-10-20 07:20:17 +0000695 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200696 [
697 VppMRoutePath(
698 self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
699 ),
700 VppMRoutePath(
701 self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
702 ),
703 ],
704 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000705
706 route_232_1_1_1.add_vpp_config()
707 route_232_1_1_1.update_entry_flags(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200708 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_CONNECTED
709 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000710
711 #
712 # Now the (*,G) is present, send from connected source
713 #
714 tx = self._mcast_connected_send_stream("232.1.1.1")
715
716 #
717 # Constrct a representation of the signal we expect on pg0
718 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200719 signal_232_1_1_1_itf_0 = VppMFibSignal(
720 self, route_232_1_1_1, self.pg0.sw_if_index, tx[0]
721 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000722
723 #
724 # read the only expected signal
725 #
726 signals = self.vapi.mfib_signal_dump()
727
728 self.assertEqual(1, len(signals))
729
730 signal_232_1_1_1_itf_0.compare(signals[0])
731
732 #
733 # reading the signal allows for the generation of another
734 # so send more packets and expect the next signal
735 #
736 tx = self._mcast_connected_send_stream("232.1.1.1")
737
738 signals = self.vapi.mfib_signal_dump()
739 self.assertEqual(1, len(signals))
740 signal_232_1_1_1_itf_0.compare(signals[0])
741
742 #
743 # A Second entry with connected check
744 # one accepting interface, pg0, 1 forwarding interfaces
745 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800746 route_232_1_1_2 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000747 self,
748 "0.0.0.0",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200749 "232.1.1.2",
750 32,
Neale Ranns990f6942020-10-20 07:20:17 +0000751 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200752 [
753 VppMRoutePath(
754 self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
755 ),
756 VppMRoutePath(
757 self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
758 ),
759 ],
760 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000761
762 route_232_1_1_2.add_vpp_config()
763 route_232_1_1_2.update_entry_flags(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200764 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_CONNECTED
765 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000766
767 #
768 # Send traffic to both entries. One read should net us two signals
769 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200770 signal_232_1_1_2_itf_0 = VppMFibSignal(
771 self, route_232_1_1_2, self.pg0.sw_if_index, tx[0]
772 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000773 tx = self._mcast_connected_send_stream("232.1.1.1")
774 tx2 = self._mcast_connected_send_stream("232.1.1.2")
775
776 #
777 # read the only expected signal
778 #
779 signals = self.vapi.mfib_signal_dump()
780
781 self.assertEqual(2, len(signals))
782
783 signal_232_1_1_1_itf_0.compare(signals[1])
784 signal_232_1_1_2_itf_0.compare(signals[0])
785
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200786 route_232_1_1_1.update_entry_flags(MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE)
787 route_232_1_1_2.update_entry_flags(MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE)
Neale Ranns32e1c012016-11-22 17:07:28 +0000788
789 def test_ip_mcast_signal(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200790 """IP Multicast Signal"""
Neale Ranns32e1c012016-11-22 17:07:28 +0000791
Neale Ranns990f6942020-10-20 07:20:17 +0000792 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
793 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
794
Neale Ranns32e1c012016-11-22 17:07:28 +0000795 #
796 # A (*,G).
797 # one accepting interface, pg0, 1 forwarding interfaces
798 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800799 route_232_1_1_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000800 self,
801 "0.0.0.0",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200802 "232.1.1.1",
803 32,
Neale Ranns990f6942020-10-20 07:20:17 +0000804 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200805 [
806 VppMRoutePath(
807 self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
808 ),
809 VppMRoutePath(
810 self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
811 ),
812 ],
813 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000814
815 route_232_1_1_1.add_vpp_config()
Neale Ranns097fa662018-05-01 05:17:55 -0700816
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200817 route_232_1_1_1.update_entry_flags(MRouteEntryFlags.MFIB_API_ENTRY_FLAG_SIGNAL)
Neale Ranns32e1c012016-11-22 17:07:28 +0000818
819 #
820 # Now the (*,G) is present, send from connected source
821 #
822 tx = self._mcast_connected_send_stream("232.1.1.1")
823
824 #
825 # Constrct a representation of the signal we expect on pg0
826 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200827 signal_232_1_1_1_itf_0 = VppMFibSignal(
828 self, route_232_1_1_1, self.pg0.sw_if_index, tx[0]
829 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000830
831 #
832 # read the only expected signal
833 #
834 signals = self.vapi.mfib_signal_dump()
835
836 self.assertEqual(1, len(signals))
837
838 signal_232_1_1_1_itf_0.compare(signals[0])
839
840 #
841 # reading the signal allows for the generation of another
842 # so send more packets and expect the next signal
843 #
844 tx = self._mcast_connected_send_stream("232.1.1.1")
845
846 signals = self.vapi.mfib_signal_dump()
847 self.assertEqual(1, len(signals))
848 signal_232_1_1_1_itf_0.compare(signals[0])
849
850 #
851 # Set the negate-signal on the accepting interval - the signals
852 # should stop
853 #
854 route_232_1_1_1.update_path_flags(
855 self.pg0.sw_if_index,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200856 (
857 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
858 | MRouteItfFlags.MFIB_API_ITF_FLAG_NEGATE_SIGNAL
859 ),
860 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000861
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800862 self.vapi.cli("clear trace")
Neale Ranns32e1c012016-11-22 17:07:28 +0000863 tx = self._mcast_connected_send_stream("232.1.1.1")
864
865 signals = self.vapi.mfib_signal_dump()
866 self.assertEqual(0, len(signals))
867
868 #
869 # Clear the SIGNAL flag on the entry and the signals should
870 # come back since the interface is still NEGATE-SIGNAL
871 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200872 route_232_1_1_1.update_entry_flags(MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE)
Neale Ranns32e1c012016-11-22 17:07:28 +0000873
874 tx = self._mcast_connected_send_stream("232.1.1.1")
875
876 signals = self.vapi.mfib_signal_dump()
877 self.assertEqual(1, len(signals))
878 signal_232_1_1_1_itf_0.compare(signals[0])
879
880 #
881 # Lastly remove the NEGATE-SIGNAL from the interface and the
882 # signals should stop
883 #
Neale Ranns990f6942020-10-20 07:20:17 +0000884 route_232_1_1_1.update_path_flags(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200885 self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
886 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000887
888 tx = self._mcast_connected_send_stream("232.1.1.1")
889 signals = self.vapi.mfib_signal_dump()
890 self.assertEqual(0, len(signals))
891
Neale Ranns15002542017-09-10 04:39:11 -0700892 def test_ip_mcast_vrf(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200893 """IP Multicast Replication in non-default table"""
Neale Ranns15002542017-09-10 04:39:11 -0700894
Neale Ranns990f6942020-10-20 07:20:17 +0000895 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
896 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
897
Neale Ranns15002542017-09-10 04:39:11 -0700898 #
899 # An (S,G).
900 # one accepting interface, pg0, 2 forwarding interfaces
901 #
902 route_1_1_1_1_232_1_1_1 = VppIpMRoute(
903 self,
904 "1.1.1.1",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200905 "232.1.1.1",
906 64,
Neale Ranns990f6942020-10-20 07:20:17 +0000907 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200908 [
909 VppMRoutePath(
910 self.pg8.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
911 ),
912 VppMRoutePath(
913 self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
914 ),
915 VppMRoutePath(
916 self.pg2.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
917 ),
918 ],
919 table_id=10,
920 )
Neale Ranns15002542017-09-10 04:39:11 -0700921 route_1_1_1_1_232_1_1_1.add_vpp_config()
922
923 #
924 # a stream that matches the route for (1.1.1.1,232.1.1.1)
925 # small packets
926 #
927 self.vapi.cli("clear trace")
928 tx = self.create_stream_ip4(self.pg8, "1.1.1.1", "232.1.1.1")
929 self.pg8.add_stream(tx)
930
931 self.pg_enable_capture(self.pg_interfaces)
932 self.pg_start()
933
934 # We expect replications on Pg1 & 2
935 self.verify_capture_ip4(self.pg1, tx)
936 self.verify_capture_ip4(self.pg2, tx)
937
Neale Ranns13721782021-05-13 15:28:27 +0000938 #
939 # An (S,G). for for-us
940 #
941 route_0_0_0_0_224_0_0_5 = VppIpMRoute(
942 self,
943 "0.0.0.0",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200944 "224.0.0.5",
945 32,
Neale Ranns13721782021-05-13 15:28:27 +0000946 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200947 [
948 VppMRoutePath(
949 self.pg8.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
950 ),
951 VppMRoutePath(
952 0xFFFFFFFF,
953 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
954 type=FibPathType.FIB_PATH_TYPE_LOCAL,
955 ),
956 ],
957 table_id=10,
958 )
Neale Ranns13721782021-05-13 15:28:27 +0000959 route_0_0_0_0_224_0_0_5.add_vpp_config()
960
961 #
962 # a stream that matches the route for (0.0.0.0, 224.0.0.5)
963 # small packets
964 #
965 self.vapi.cli("clear trace")
966 self.pg8.resolve_arp()
967
968 #
969 # send a ping to mcast address from peer on pg8
970 # expect a response
971 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200972 icmp_id = 0xB
Neale Ranns13721782021-05-13 15:28:27 +0000973 icmp_seq = 5
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200974 icmp_load = b"\x0a" * 18
975 tx = (
976 Ether(dst=getmacbyip("224.0.0.5"), src=self.pg8.remote_mac)
977 / IP(src=self.pg8.remote_ip4, dst="224.0.0.5")
978 / ICMP(id=icmp_id, seq=icmp_seq)
979 / Raw(load=icmp_load)
980 ) * 2
Neale Ranns13721782021-05-13 15:28:27 +0000981
982 self.send_and_expect(self.pg8, tx, self.pg8)
983
Neale Rannsadb17a82019-08-04 02:41:57 -0700984 def test_ip_mcast_gre(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200985 """IP Multicast Replication over GRE"""
Neale Rannsadb17a82019-08-04 02:41:57 -0700986
Neale Ranns990f6942020-10-20 07:20:17 +0000987 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
988 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
989
Neale Rannsadb17a82019-08-04 02:41:57 -0700990 gre_if_1 = VppGreInterface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200991 self, self.pg1.local_ip4, self.pg1.remote_ip4
992 ).add_vpp_config()
Neale Rannsadb17a82019-08-04 02:41:57 -0700993 gre_if_2 = VppGreInterface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200994 self, self.pg2.local_ip4, self.pg2.remote_ip4
995 ).add_vpp_config()
Neale Rannsadb17a82019-08-04 02:41:57 -0700996 gre_if_3 = VppGreInterface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200997 self, self.pg3.local_ip4, self.pg3.remote_ip4
998 ).add_vpp_config()
Neale Rannsadb17a82019-08-04 02:41:57 -0700999
1000 gre_if_1.admin_up()
1001 gre_if_1.config_ip4()
1002 gre_if_2.admin_up()
1003 gre_if_2.config_ip4()
1004 gre_if_3.admin_up()
1005 gre_if_3.config_ip4()
1006
1007 #
1008 # An (S,G).
1009 # one accepting interface, pg0, 2 forwarding interfaces
1010 #
1011 route_1_1_1_1_232_1_1_1 = VppIpMRoute(
1012 self,
1013 "1.1.1.1",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001014 "232.2.2.2",
1015 64,
Neale Ranns990f6942020-10-20 07:20:17 +00001016 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001017 [
1018 VppMRoutePath(
1019 gre_if_1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
1020 ),
1021 VppMRoutePath(
1022 gre_if_2.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
1023 ),
1024 VppMRoutePath(
1025 gre_if_3.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
1026 ),
1027 ],
1028 )
Neale Rannsadb17a82019-08-04 02:41:57 -07001029 route_1_1_1_1_232_1_1_1.add_vpp_config()
1030
1031 #
1032 # a stream that matches the route for (1.1.1.1,232.2.2.2)
1033 # small packets
1034 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001035 tx = (
1036 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
1037 / IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4)
1038 / GRE()
1039 / IP(src="1.1.1.1", dst="232.2.2.2")
1040 / UDP(sport=1234, dport=1234)
1041 / Raw(b"\a5" * 64)
1042 ) * 63
Neale Rannsadb17a82019-08-04 02:41:57 -07001043
1044 self.vapi.cli("clear trace")
1045 self.pg1.add_stream(tx)
1046
1047 self.pg_enable_capture(self.pg_interfaces)
1048 self.pg_start()
1049
1050 # We expect replications on Pg2 & 3
1051 # check the encap headers are as expected based on the egress tunnel
1052 rxs = self.pg2.get_capture(len(tx))
1053 for rx in rxs:
1054 self.assertEqual(rx[IP].src, gre_if_2.t_src)
1055 self.assertEqual(rx[IP].dst, gre_if_2.t_dst)
1056 self.assert_packet_checksums_valid(rx)
1057
1058 rxs = self.pg3.get_capture(len(tx))
1059 for rx in rxs:
1060 self.assertEqual(rx[IP].src, gre_if_3.t_src)
1061 self.assertEqual(rx[IP].dst, gre_if_3.t_dst)
1062 self.assert_packet_checksums_valid(rx)
1063
Neale Ranns7d8a9562020-11-20 14:32:56 +00001064 def test_ip6_mcast_gre(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001065 """IP6 Multicast Replication over GRE"""
Neale Ranns7d8a9562020-11-20 14:32:56 +00001066
1067 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1068 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1069
1070 gre_if_1 = VppGreInterface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001071 self, self.pg1.local_ip4, self.pg1.remote_ip4
1072 ).add_vpp_config()
Neale Ranns7d8a9562020-11-20 14:32:56 +00001073 gre_if_2 = VppGreInterface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001074 self, self.pg2.local_ip4, self.pg2.remote_ip4
1075 ).add_vpp_config()
Neale Ranns7d8a9562020-11-20 14:32:56 +00001076 gre_if_3 = VppGreInterface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001077 self, self.pg3.local_ip4, self.pg3.remote_ip4
1078 ).add_vpp_config()
Neale Ranns7d8a9562020-11-20 14:32:56 +00001079
1080 gre_if_1.admin_up()
1081 gre_if_1.config_ip6()
1082 gre_if_2.admin_up()
1083 gre_if_2.config_ip6()
1084 gre_if_3.admin_up()
1085 gre_if_3.config_ip6()
1086
1087 #
1088 # An (S,G).
1089 # one accepting interface, pg0, 2 forwarding interfaces
1090 #
1091 route_1_1_FF_1 = VppIpMRoute(
1092 self,
1093 "1::1",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001094 "FF00::1",
1095 256,
Neale Ranns7d8a9562020-11-20 14:32:56 +00001096 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001097 [
1098 VppMRoutePath(
1099 gre_if_1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
1100 ),
1101 VppMRoutePath(
1102 gre_if_2.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
1103 ),
1104 VppMRoutePath(
1105 gre_if_3.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
1106 ),
1107 ],
1108 )
Neale Ranns7d8a9562020-11-20 14:32:56 +00001109 route_1_1_FF_1.add_vpp_config()
1110
1111 #
1112 # a stream that matches the route for (1::1, FF::1)
1113 # small packets
1114 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001115 tx = (
1116 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
1117 / IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4)
1118 / GRE()
1119 / IPv6(src="1::1", dst="FF00::1")
1120 / UDP(sport=1234, dport=1234)
1121 / Raw(b"\a5" * 64)
1122 ) * 63
Neale Ranns7d8a9562020-11-20 14:32:56 +00001123
1124 self.vapi.cli("clear trace")
1125 self.pg1.add_stream(tx)
1126
1127 self.pg_enable_capture(self.pg_interfaces)
1128 self.pg_start()
1129
1130 # We expect replications on Pg2 & 3
1131 # check the encap headers are as expected based on the egress tunnel
1132 rxs = self.pg2.get_capture(len(tx))
1133 for rx in rxs:
1134 self.assertEqual(rx[IP].src, gre_if_2.t_src)
1135 self.assertEqual(rx[IP].dst, gre_if_2.t_dst)
1136 self.assert_packet_checksums_valid(rx)
1137
1138 rxs = self.pg3.get_capture(len(tx))
1139 for rx in rxs:
1140 self.assertEqual(rx[IP].src, gre_if_3.t_src)
1141 self.assertEqual(rx[IP].dst, gre_if_3.t_dst)
1142 self.assert_packet_checksums_valid(rx)
1143
Neale Ranns15002542017-09-10 04:39:11 -07001144 def test_ip6_mcast_vrf(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001145 """IPv6 Multicast Replication in non-default table"""
Neale Ranns15002542017-09-10 04:39:11 -07001146
Neale Ranns990f6942020-10-20 07:20:17 +00001147 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1148 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1149
Neale Ranns15002542017-09-10 04:39:11 -07001150 #
1151 # An (S,G).
1152 # one accepting interface, pg0, 2 forwarding interfaces
1153 #
1154 route_2001_ff01_1 = VppIpMRoute(
1155 self,
1156 "2001::1",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001157 "ff01::1",
1158 256,
Neale Ranns990f6942020-10-20 07:20:17 +00001159 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001160 [
1161 VppMRoutePath(
1162 self.pg8.sw_if_index,
1163 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT,
1164 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
1165 ),
1166 VppMRoutePath(
1167 self.pg1.sw_if_index,
1168 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
1169 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
1170 ),
1171 VppMRoutePath(
1172 self.pg2.sw_if_index,
1173 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
1174 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
1175 ),
1176 ],
1177 table_id=10,
1178 )
Neale Ranns15002542017-09-10 04:39:11 -07001179 route_2001_ff01_1.add_vpp_config()
1180
1181 #
1182 # a stream that matches the route for (2001::1, ff00::1)
1183 #
1184 self.vapi.cli("clear trace")
1185 tx = self.create_stream_ip6(self.pg8, "2001::1", "ff01::1")
1186 self.pg8.add_stream(tx)
1187
1188 self.pg_enable_capture(self.pg_interfaces)
1189 self.pg_start()
1190
1191 # We expect replications on Pg1, 2,
1192 self.verify_capture_ip6(self.pg1, tx)
1193 self.verify_capture_ip6(self.pg2, tx)
Neale Ranns32e1c012016-11-22 17:07:28 +00001194
Neale Rannscf3561b2017-12-13 01:44:25 -08001195 def test_bidir(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001196 """IP Multicast Bi-directional"""
Neale Rannscf3561b2017-12-13 01:44:25 -08001197
Neale Ranns990f6942020-10-20 07:20:17 +00001198 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1199 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1200
Neale Rannscf3561b2017-12-13 01:44:25 -08001201 #
1202 # A (*,G). The set of accepting interfaces matching the forwarding
1203 #
1204 route_232_1_1_1 = VppIpMRoute(
1205 self,
1206 "0.0.0.0",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001207 "232.1.1.1",
1208 32,
Neale Ranns990f6942020-10-20 07:20:17 +00001209 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001210 [
1211 VppMRoutePath(
1212 self.pg0.sw_if_index,
1213 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
1214 | MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
1215 ),
1216 VppMRoutePath(
1217 self.pg1.sw_if_index,
1218 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
1219 | MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
1220 ),
1221 VppMRoutePath(
1222 self.pg2.sw_if_index,
1223 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
1224 | MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
1225 ),
1226 VppMRoutePath(
1227 self.pg3.sw_if_index,
1228 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
1229 | MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
1230 ),
1231 ],
1232 )
Neale Rannscf3561b2017-12-13 01:44:25 -08001233 route_232_1_1_1.add_vpp_config()
1234
1235 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.1")
1236 self.pg0.add_stream(tx)
1237
1238 self.pg_enable_capture(self.pg_interfaces)
1239 self.pg_start()
1240
1241 # We expect replications on Pg1, 2, 3, but not on pg0
1242 self.verify_capture_ip4(self.pg1, tx)
1243 self.verify_capture_ip4(self.pg2, tx)
1244 self.verify_capture_ip4(self.pg3, tx)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001245 self.pg0.assert_nothing_captured(remark="IP multicast packets forwarded on PG0")
Neale Rannscf3561b2017-12-13 01:44:25 -08001246
1247
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001248if __name__ == "__main__":
Neale Ranns32e1c012016-11-22 17:07:28 +00001249 unittest.main(testRunner=VppTestRunner)