blob: 682e7699210af13c9674879947f575fa462bd4d7 [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
Dave Wallace8800f732023-08-31 00:47:44 -04005from framework import VppTestCase
6from asfframework import VppTestRunner, tag_fixme_vpp_workers
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02007from vpp_ip_route import (
8 VppIpMRoute,
9 VppMRoutePath,
10 VppMFibSignal,
11 VppIpTable,
12 FibPathProto,
13 FibPathType,
14)
Neale Rannsadb17a82019-08-04 02:41:57 -070015from vpp_gre_interface import VppGreInterface
Neale Ranns990f6942020-10-20 07:20:17 +000016from vpp_papi import VppEnum
Dmitry Valter34fa0ce2024-03-11 10:38:46 +000017from config import config
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 Rannse22a7042022-08-09 03:03:29 +0000225 count = self.statistics.get_err_counter("/err/ip4-input/rpf_failure")
Neale Rannse8f57d52021-10-12 07:49:37 +0000226 self.assertEqual(count, len(tx))
Neale Ranns32e1c012016-11-22 17:07:28 +0000227
228 #
229 # A (*,G).
Neale Ranns37be7362017-02-21 17:30:26 -0800230 # one accepting interface, pg0, 7 forwarding interfaces
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700231 # many forwarding interfaces test the case where the replicate DPO
Neale Ranns37be7362017-02-21 17:30:26 -0800232 # needs to use extra cache lines for the buckets.
Neale Ranns32e1c012016-11-22 17:07:28 +0000233 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800234 route_232_1_1_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000235 self,
236 "0.0.0.0",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200237 "232.1.1.1",
238 32,
Neale Ranns990f6942020-10-20 07:20:17 +0000239 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200240 [
241 VppMRoutePath(
242 self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
243 ),
244 VppMRoutePath(
245 self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
246 ),
247 VppMRoutePath(
248 self.pg2.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
249 ),
250 VppMRoutePath(
251 self.pg3.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
252 ),
253 VppMRoutePath(
254 self.pg4.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
255 ),
256 VppMRoutePath(
257 self.pg5.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
258 ),
259 VppMRoutePath(
260 self.pg6.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
261 ),
262 VppMRoutePath(
263 self.pg7.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
264 ),
265 ],
266 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000267 route_232_1_1_1.add_vpp_config()
268
269 #
270 # An (S,G).
271 # one accepting interface, pg0, 2 forwarding interfaces
272 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800273 route_1_1_1_1_232_1_1_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000274 self,
275 "1.1.1.1",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200276 "232.1.1.1",
277 27, # any grp-len is ok when src is set
Neale Ranns990f6942020-10-20 07:20:17 +0000278 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200279 [
280 VppMRoutePath(
281 self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
282 ),
283 VppMRoutePath(
284 self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
285 ),
286 VppMRoutePath(
287 self.pg2.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
288 ),
289 ],
290 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000291 route_1_1_1_1_232_1_1_1.add_vpp_config()
292
293 #
Neale Rannse821ab12017-06-01 07:45:05 -0700294 # An (S,G).
295 # one accepting interface, pg0, 2 forwarding interfaces
296 # that use unicast next-hops
297 #
298 route_1_1_1_1_232_1_1_2 = VppIpMRoute(
299 self,
300 "1.1.1.1",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200301 "232.1.1.2",
302 64,
Neale Ranns990f6942020-10-20 07:20:17 +0000303 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200304 [
305 VppMRoutePath(
306 self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
307 ),
308 VppMRoutePath(
309 self.pg1.sw_if_index,
310 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
311 nh=self.pg1.remote_ip4,
312 ),
313 VppMRoutePath(
314 self.pg2.sw_if_index,
315 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
316 nh=self.pg2.remote_ip4,
317 ),
318 ],
319 )
Neale Rannse821ab12017-06-01 07:45:05 -0700320 route_1_1_1_1_232_1_1_2.add_vpp_config()
321
322 #
Neale Ranns32e1c012016-11-22 17:07:28 +0000323 # An (*,G/m).
324 # one accepting interface, pg0, 1 forwarding interfaces
325 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800326 route_232 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000327 self,
328 "0.0.0.0",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200329 "232.0.0.0",
330 8,
Neale Ranns990f6942020-10-20 07:20:17 +0000331 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200332 [
333 VppMRoutePath(
334 self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
335 ),
336 VppMRoutePath(
337 self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
338 ),
339 ],
340 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000341 route_232.add_vpp_config()
342
343 #
344 # a stream that matches the route for (1.1.1.1,232.1.1.1)
Neale Ranns9d676af2017-03-15 01:28:31 -0700345 # small packets
Neale Ranns32e1c012016-11-22 17:07:28 +0000346 #
347 self.vapi.cli("clear trace")
348 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.1")
349 self.pg0.add_stream(tx)
350
351 self.pg_enable_capture(self.pg_interfaces)
352 self.pg_start()
353
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200354 self.assertEqual(route_1_1_1_1_232_1_1_1.get_stats()["packets"], len(tx))
Neale Ranns28c142e2018-09-07 09:37:07 -0700355
Neale Ranns37be7362017-02-21 17:30:26 -0800356 # We expect replications on Pg1->7
Neale Ranns32e1c012016-11-22 17:07:28 +0000357 self.verify_capture_ip4(self.pg1, tx)
358 self.verify_capture_ip4(self.pg2, tx)
359
360 # no replications on Pg0
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200361 self.pg0.assert_nothing_captured(remark="IP multicast packets forwarded on PG0")
362 self.pg3.assert_nothing_captured(remark="IP multicast packets forwarded on PG3")
Neale Ranns32e1c012016-11-22 17:07:28 +0000363
364 #
Neale Ranns9d676af2017-03-15 01:28:31 -0700365 # a stream that matches the route for (1.1.1.1,232.1.1.1)
366 # large packets
367 #
368 self.vapi.cli("clear trace")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200369 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 -0700370 self.pg0.add_stream(tx)
371
372 self.pg_enable_capture(self.pg_interfaces)
373 self.pg_start()
374
375 # We expect replications on Pg1->7
376 self.verify_capture_ip4(self.pg1, tx)
377 self.verify_capture_ip4(self.pg2, tx)
Neale Ranns9d676af2017-03-15 01:28:31 -0700378
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200379 self.assertEqual(route_1_1_1_1_232_1_1_1.get_stats()["packets"], 2 * len(tx))
Neale Ranns28c142e2018-09-07 09:37:07 -0700380
Neale Ranns9d676af2017-03-15 01:28:31 -0700381 # no replications on Pg0
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200382 self.pg0.assert_nothing_captured(remark="IP multicast packets forwarded on PG0")
383 self.pg3.assert_nothing_captured(remark="IP multicast packets forwarded on PG3")
Neale Ranns9d676af2017-03-15 01:28:31 -0700384
385 #
Neale Rannse821ab12017-06-01 07:45:05 -0700386 # a stream to the unicast next-hops
387 #
388 self.vapi.cli("clear trace")
389 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.2")
390 self.pg0.add_stream(tx)
391
392 self.pg_enable_capture(self.pg_interfaces)
393 self.pg_start()
394
395 # We expect replications on Pg1->7
396 self.verify_capture_ip4(self.pg1, tx, dst_mac=self.pg1.remote_mac)
397 self.verify_capture_ip4(self.pg2, tx, dst_mac=self.pg2.remote_mac)
398
399 # no replications on Pg0 nor pg3
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200400 self.pg0.assert_nothing_captured(remark="IP multicast packets forwarded on PG0")
401 self.pg3.assert_nothing_captured(remark="IP multicast packets forwarded on PG3")
Neale Rannse821ab12017-06-01 07:45:05 -0700402
403 #
Neale Ranns32e1c012016-11-22 17:07:28 +0000404 # a stream that matches the route for (*,232.0.0.0/8)
405 # Send packets with the 9th bit set so we test the correct clearing
406 # of that bit in the mac rewrite
407 #
408 self.vapi.cli("clear trace")
409 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.255.255.255")
410 self.pg0.add_stream(tx)
411
412 self.pg_enable_capture(self.pg_interfaces)
413 self.pg_start()
414
415 # We expect replications on Pg1 only
416 self.verify_capture_ip4(self.pg1, tx)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200417 self.assertEqual(route_232.get_stats()["packets"], len(tx))
Neale Ranns32e1c012016-11-22 17:07:28 +0000418
419 # no replications on Pg0, Pg2 not Pg3
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200420 self.pg0.assert_nothing_captured(remark="IP multicast packets forwarded on PG0")
421 self.pg2.assert_nothing_captured(remark="IP multicast packets forwarded on PG2")
422 self.pg3.assert_nothing_captured(remark="IP multicast packets forwarded on PG3")
Neale Ranns32e1c012016-11-22 17:07:28 +0000423
424 #
425 # a stream that matches the route for (*,232.1.1.1)
426 #
427 self.vapi.cli("clear trace")
428 tx = self.create_stream_ip4(self.pg0, "1.1.1.2", "232.1.1.1")
429 self.pg0.add_stream(tx)
430
431 self.pg_enable_capture(self.pg_interfaces)
432 self.pg_start()
433
Neale Rannse821ab12017-06-01 07:45:05 -0700434 # We expect replications on Pg1->7
Neale Ranns32e1c012016-11-22 17:07:28 +0000435 self.verify_capture_ip4(self.pg1, tx)
436 self.verify_capture_ip4(self.pg2, tx)
437 self.verify_capture_ip4(self.pg3, tx)
Neale Rannsc2aad532017-05-30 09:53:52 -0700438 self.verify_capture_ip4(self.pg4, tx)
439 self.verify_capture_ip4(self.pg5, tx)
440 self.verify_capture_ip4(self.pg6, tx)
441 self.verify_capture_ip4(self.pg7, tx)
Neale Ranns32e1c012016-11-22 17:07:28 +0000442
Neale Rannse821ab12017-06-01 07:45:05 -0700443 # no replications on Pg0
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200444 self.pg0.assert_nothing_captured(remark="IP multicast packets forwarded on PG0")
Neale Rannse821ab12017-06-01 07:45:05 -0700445
Neale Ranns21fb4f72020-10-05 12:26:47 +0000446 self.vapi.cli("packet mac-filter pg0 off")
447 self.vapi.cli("packet mac-filter pg1 off")
448 self.vapi.cli("packet mac-filter pg2 off")
449 self.vapi.cli("packet mac-filter pg4 off")
450 self.vapi.cli("packet mac-filter pg5 off")
451 self.vapi.cli("packet mac-filter pg6 off")
452 self.vapi.cli("packet mac-filter pg7 off")
453
Neale Ranns32e1c012016-11-22 17:07:28 +0000454 def test_ip6_mcast(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200455 """IPv6 Multicast Replication"""
Neale Ranns32e1c012016-11-22 17:07:28 +0000456
Neale Ranns990f6942020-10-20 07:20:17 +0000457 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
458 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
459
Neale Ranns21fb4f72020-10-05 12:26:47 +0000460 self.vapi.cli("packet mac-filter pg0 on")
461 self.vapi.cli("packet mac-filter pg1 on")
462 self.vapi.cli("packet mac-filter pg2 on")
463 self.vapi.cli("packet mac-filter pg4 on")
464 self.vapi.cli("packet mac-filter pg5 on")
465 self.vapi.cli("packet mac-filter pg6 on")
466 self.vapi.cli("packet mac-filter pg7 on")
Neale Ranns32e1c012016-11-22 17:07:28 +0000467 #
468 # a stream that matches the default route. gets dropped.
469 #
470 self.vapi.cli("clear trace")
471 tx = self.create_stream_ip6(self.pg0, "2001::1", "ff01::1")
472 self.pg0.add_stream(tx)
473
474 self.pg_enable_capture(self.pg_interfaces)
475 self.pg_start()
476
477 self.pg0.assert_nothing_captured(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200478 remark="IPv6 multicast packets forwarded on default route"
479 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000480
481 #
482 # A (*,G).
483 # one accepting interface, pg0, 3 forwarding interfaces
484 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800485 route_ff01_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000486 self,
487 "::",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200488 "ff01::1",
489 128,
Neale Ranns990f6942020-10-20 07:20:17 +0000490 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200491 [
492 VppMRoutePath(
493 self.pg0.sw_if_index,
494 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT,
495 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
496 ),
497 VppMRoutePath(
498 self.pg1.sw_if_index,
499 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
500 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
501 ),
502 VppMRoutePath(
503 self.pg2.sw_if_index,
504 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
505 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
506 ),
507 VppMRoutePath(
508 self.pg3.sw_if_index,
509 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
510 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
511 ),
512 ],
513 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000514 route_ff01_1.add_vpp_config()
515
516 #
517 # An (S,G).
518 # one accepting interface, pg0, 2 forwarding interfaces
519 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800520 route_2001_ff01_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000521 self,
522 "2001::1",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200523 "ff01::1",
524 0, # any grp-len is ok when src is set
Neale Ranns990f6942020-10-20 07:20:17 +0000525 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200526 [
527 VppMRoutePath(
528 self.pg0.sw_if_index,
529 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT,
530 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
531 ),
532 VppMRoutePath(
533 self.pg1.sw_if_index,
534 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
535 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
536 ),
537 VppMRoutePath(
538 self.pg2.sw_if_index,
539 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
540 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
541 ),
542 ],
543 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000544 route_2001_ff01_1.add_vpp_config()
545
546 #
547 # An (*,G/m).
548 # one accepting interface, pg0, 1 forwarding interface
549 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800550 route_ff01 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000551 self,
552 "::",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200553 "ff01::",
554 16,
Neale Ranns990f6942020-10-20 07:20:17 +0000555 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200556 [
557 VppMRoutePath(
558 self.pg0.sw_if_index,
559 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT,
560 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
561 ),
562 VppMRoutePath(
563 self.pg1.sw_if_index,
564 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
565 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
566 ),
567 ],
568 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000569 route_ff01.add_vpp_config()
570
571 #
572 # a stream that matches the route for (*, ff01::/16)
Neale Rannsce111d22018-01-23 08:38:50 -0800573 # sent on the non-accepting interface
574 #
575 self.vapi.cli("clear trace")
576 tx = self.create_stream_ip6(self.pg1, "2002::1", "ff01:2::255")
577 self.send_and_assert_no_replies(self.pg1, tx, "RPF miss")
Neale Rannse22a7042022-08-09 03:03:29 +0000578 count = self.statistics.get_err_counter("/err/ip6-input/rpf_failure")
Neale Rannse8f57d52021-10-12 07:49:37 +0000579 self.assertEqual(count, 2 * len(tx))
Neale Rannsce111d22018-01-23 08:38:50 -0800580
581 #
582 # a stream that matches the route for (*, ff01::/16)
583 # sent on the accepting interface
Neale Ranns32e1c012016-11-22 17:07:28 +0000584 #
585 self.vapi.cli("clear trace")
586 tx = self.create_stream_ip6(self.pg0, "2002::1", "ff01:2::255")
587 self.pg0.add_stream(tx)
588
589 self.pg_enable_capture(self.pg_interfaces)
590 self.pg_start()
591
592 # We expect replications on Pg1
593 self.verify_capture_ip6(self.pg1, tx)
594
595 # no replications on Pg0, Pg3
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200596 self.pg0.assert_nothing_captured(remark="IP multicast packets forwarded on PG0")
597 self.pg2.assert_nothing_captured(remark="IP multicast packets forwarded on PG2")
598 self.pg3.assert_nothing_captured(remark="IP multicast packets forwarded on PG3")
Neale Ranns32e1c012016-11-22 17:07:28 +0000599
600 #
Neale Rannsc2aad532017-05-30 09:53:52 -0700601 # Bounce the interface and it should still work
602 #
603 self.pg1.admin_down()
604 self.pg0.add_stream(tx)
605 self.pg_enable_capture(self.pg_interfaces)
606 self.pg_start()
607 self.pg1.assert_nothing_captured(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200608 remark="IP multicast packets forwarded on down PG1"
609 )
Neale Rannsc2aad532017-05-30 09:53:52 -0700610
611 self.pg1.admin_up()
612 self.pg0.add_stream(tx)
613 self.pg_enable_capture(self.pg_interfaces)
614 self.pg_start()
615 self.verify_capture_ip6(self.pg1, tx)
616
617 #
Neale Ranns32e1c012016-11-22 17:07:28 +0000618 # a stream that matches the route for (*,ff01::1)
619 #
620 self.vapi.cli("clear trace")
621 tx = self.create_stream_ip6(self.pg0, "2002::2", "ff01::1")
622 self.pg0.add_stream(tx)
623
624 self.pg_enable_capture(self.pg_interfaces)
625 self.pg_start()
626
627 # We expect replications on Pg1, 2, 3.
628 self.verify_capture_ip6(self.pg1, tx)
629 self.verify_capture_ip6(self.pg2, tx)
630 self.verify_capture_ip6(self.pg3, tx)
631
632 # no replications on Pg0
633 self.pg0.assert_nothing_captured(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200634 remark="IPv6 multicast packets forwarded on PG0"
635 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000636
637 #
638 # a stream that matches the route for (2001::1, ff00::1)
639 #
640 self.vapi.cli("clear trace")
641 tx = self.create_stream_ip6(self.pg0, "2001::1", "ff01::1")
642 self.pg0.add_stream(tx)
643
644 self.pg_enable_capture(self.pg_interfaces)
645 self.pg_start()
646
647 # We expect replications on Pg1, 2,
648 self.verify_capture_ip6(self.pg1, tx)
649 self.verify_capture_ip6(self.pg2, tx)
650
651 # no replications on Pg0, Pg3
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200652 self.pg0.assert_nothing_captured(remark="IP multicast packets forwarded on PG0")
653 self.pg3.assert_nothing_captured(remark="IP multicast packets forwarded on PG3")
Neale Ranns32e1c012016-11-22 17:07:28 +0000654
Neale Ranns21fb4f72020-10-05 12:26:47 +0000655 self.vapi.cli("packet mac-filter pg0 off")
656 self.vapi.cli("packet mac-filter pg1 off")
657 self.vapi.cli("packet mac-filter pg2 off")
658 self.vapi.cli("packet mac-filter pg4 off")
659 self.vapi.cli("packet mac-filter pg5 off")
660 self.vapi.cli("packet mac-filter pg6 off")
661 self.vapi.cli("packet mac-filter pg7 off")
662
Neale Ranns32e1c012016-11-22 17:07:28 +0000663 def _mcast_connected_send_stream(self, dst_ip):
664 self.vapi.cli("clear trace")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200665 tx = self.create_stream_ip4(self.pg0, self.pg0.remote_ip4, dst_ip)
Neale Ranns32e1c012016-11-22 17:07:28 +0000666 self.pg0.add_stream(tx)
667
668 self.pg_enable_capture(self.pg_interfaces)
669 self.pg_start()
670
671 # We expect replications on Pg1.
672 self.verify_capture_ip4(self.pg1, tx)
673
674 return tx
675
676 def test_ip_mcast_connected(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200677 """IP Multicast Connected Source check"""
Neale Ranns32e1c012016-11-22 17:07:28 +0000678
Neale Ranns990f6942020-10-20 07:20:17 +0000679 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
680 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
681
Neale Ranns32e1c012016-11-22 17:07:28 +0000682 #
683 # A (*,G).
684 # one accepting interface, pg0, 1 forwarding interfaces
685 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800686 route_232_1_1_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000687 self,
688 "0.0.0.0",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200689 "232.1.1.1",
690 32,
Neale Ranns990f6942020-10-20 07:20:17 +0000691 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200692 [
693 VppMRoutePath(
694 self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
695 ),
696 VppMRoutePath(
697 self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
698 ),
699 ],
700 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000701
702 route_232_1_1_1.add_vpp_config()
703 route_232_1_1_1.update_entry_flags(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200704 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_CONNECTED
705 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000706
707 #
708 # Now the (*,G) is present, send from connected source
709 #
710 tx = self._mcast_connected_send_stream("232.1.1.1")
711
712 #
713 # Constrct a representation of the signal we expect on pg0
714 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200715 signal_232_1_1_1_itf_0 = VppMFibSignal(
716 self, route_232_1_1_1, self.pg0.sw_if_index, tx[0]
717 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000718
719 #
720 # read the only expected signal
721 #
722 signals = self.vapi.mfib_signal_dump()
723
724 self.assertEqual(1, len(signals))
725
726 signal_232_1_1_1_itf_0.compare(signals[0])
727
728 #
729 # reading the signal allows for the generation of another
730 # so send more packets and expect the next signal
731 #
732 tx = self._mcast_connected_send_stream("232.1.1.1")
733
734 signals = self.vapi.mfib_signal_dump()
735 self.assertEqual(1, len(signals))
736 signal_232_1_1_1_itf_0.compare(signals[0])
737
738 #
739 # A Second entry with connected check
740 # one accepting interface, pg0, 1 forwarding interfaces
741 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800742 route_232_1_1_2 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000743 self,
744 "0.0.0.0",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200745 "232.1.1.2",
746 32,
Neale Ranns990f6942020-10-20 07:20:17 +0000747 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200748 [
749 VppMRoutePath(
750 self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
751 ),
752 VppMRoutePath(
753 self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
754 ),
755 ],
756 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000757
758 route_232_1_1_2.add_vpp_config()
759 route_232_1_1_2.update_entry_flags(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200760 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_CONNECTED
761 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000762
763 #
764 # Send traffic to both entries. One read should net us two signals
765 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200766 signal_232_1_1_2_itf_0 = VppMFibSignal(
767 self, route_232_1_1_2, self.pg0.sw_if_index, tx[0]
768 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000769 tx = self._mcast_connected_send_stream("232.1.1.1")
770 tx2 = self._mcast_connected_send_stream("232.1.1.2")
771
772 #
773 # read the only expected signal
774 #
775 signals = self.vapi.mfib_signal_dump()
776
777 self.assertEqual(2, len(signals))
778
779 signal_232_1_1_1_itf_0.compare(signals[1])
780 signal_232_1_1_2_itf_0.compare(signals[0])
781
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200782 route_232_1_1_1.update_entry_flags(MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE)
783 route_232_1_1_2.update_entry_flags(MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE)
Neale Ranns32e1c012016-11-22 17:07:28 +0000784
785 def test_ip_mcast_signal(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200786 """IP Multicast Signal"""
Neale Ranns32e1c012016-11-22 17:07:28 +0000787
Neale Ranns990f6942020-10-20 07:20:17 +0000788 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
789 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
790
Neale Ranns32e1c012016-11-22 17:07:28 +0000791 #
792 # A (*,G).
793 # one accepting interface, pg0, 1 forwarding interfaces
794 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800795 route_232_1_1_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000796 self,
797 "0.0.0.0",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200798 "232.1.1.1",
799 32,
Neale Ranns990f6942020-10-20 07:20:17 +0000800 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200801 [
802 VppMRoutePath(
803 self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
804 ),
805 VppMRoutePath(
806 self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
807 ),
808 ],
809 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000810
811 route_232_1_1_1.add_vpp_config()
Neale Ranns097fa662018-05-01 05:17:55 -0700812
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200813 route_232_1_1_1.update_entry_flags(MRouteEntryFlags.MFIB_API_ENTRY_FLAG_SIGNAL)
Neale Ranns32e1c012016-11-22 17:07:28 +0000814
815 #
816 # Now the (*,G) is present, send from connected source
817 #
818 tx = self._mcast_connected_send_stream("232.1.1.1")
819
820 #
821 # Constrct a representation of the signal we expect on pg0
822 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200823 signal_232_1_1_1_itf_0 = VppMFibSignal(
824 self, route_232_1_1_1, self.pg0.sw_if_index, tx[0]
825 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000826
827 #
828 # read the only expected signal
829 #
830 signals = self.vapi.mfib_signal_dump()
831
832 self.assertEqual(1, len(signals))
833
834 signal_232_1_1_1_itf_0.compare(signals[0])
835
836 #
837 # reading the signal allows for the generation of another
838 # so send more packets and expect the next signal
839 #
840 tx = self._mcast_connected_send_stream("232.1.1.1")
841
842 signals = self.vapi.mfib_signal_dump()
843 self.assertEqual(1, len(signals))
844 signal_232_1_1_1_itf_0.compare(signals[0])
845
846 #
847 # Set the negate-signal on the accepting interval - the signals
848 # should stop
849 #
850 route_232_1_1_1.update_path_flags(
851 self.pg0.sw_if_index,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200852 (
853 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
854 | MRouteItfFlags.MFIB_API_ITF_FLAG_NEGATE_SIGNAL
855 ),
856 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000857
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800858 self.vapi.cli("clear trace")
Neale Ranns32e1c012016-11-22 17:07:28 +0000859 tx = self._mcast_connected_send_stream("232.1.1.1")
860
861 signals = self.vapi.mfib_signal_dump()
862 self.assertEqual(0, len(signals))
863
864 #
865 # Clear the SIGNAL flag on the entry and the signals should
866 # come back since the interface is still NEGATE-SIGNAL
867 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200868 route_232_1_1_1.update_entry_flags(MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE)
Neale Ranns32e1c012016-11-22 17:07:28 +0000869
870 tx = self._mcast_connected_send_stream("232.1.1.1")
871
872 signals = self.vapi.mfib_signal_dump()
873 self.assertEqual(1, len(signals))
874 signal_232_1_1_1_itf_0.compare(signals[0])
875
876 #
877 # Lastly remove the NEGATE-SIGNAL from the interface and the
878 # signals should stop
879 #
Neale Ranns990f6942020-10-20 07:20:17 +0000880 route_232_1_1_1.update_path_flags(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200881 self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
882 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000883
884 tx = self._mcast_connected_send_stream("232.1.1.1")
885 signals = self.vapi.mfib_signal_dump()
886 self.assertEqual(0, len(signals))
887
Dmitry Valter34fa0ce2024-03-11 10:38:46 +0000888 @unittest.skipIf(
889 "ping" in config.excluded_plugins, "Exclude tests requiring Ping plugin"
890 )
Neale Ranns15002542017-09-10 04:39:11 -0700891 def test_ip_mcast_vrf(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200892 """IP Multicast Replication in non-default table"""
Neale Ranns15002542017-09-10 04:39:11 -0700893
Neale Ranns990f6942020-10-20 07:20:17 +0000894 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
895 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
896
Neale Ranns15002542017-09-10 04:39:11 -0700897 #
898 # An (S,G).
899 # one accepting interface, pg0, 2 forwarding interfaces
900 #
901 route_1_1_1_1_232_1_1_1 = VppIpMRoute(
902 self,
903 "1.1.1.1",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200904 "232.1.1.1",
905 64,
Neale Ranns990f6942020-10-20 07:20:17 +0000906 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200907 [
908 VppMRoutePath(
909 self.pg8.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
910 ),
911 VppMRoutePath(
912 self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
913 ),
914 VppMRoutePath(
915 self.pg2.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
916 ),
917 ],
918 table_id=10,
919 )
Neale Ranns15002542017-09-10 04:39:11 -0700920 route_1_1_1_1_232_1_1_1.add_vpp_config()
921
922 #
923 # a stream that matches the route for (1.1.1.1,232.1.1.1)
924 # small packets
925 #
926 self.vapi.cli("clear trace")
927 tx = self.create_stream_ip4(self.pg8, "1.1.1.1", "232.1.1.1")
928 self.pg8.add_stream(tx)
929
930 self.pg_enable_capture(self.pg_interfaces)
931 self.pg_start()
932
933 # We expect replications on Pg1 & 2
934 self.verify_capture_ip4(self.pg1, tx)
935 self.verify_capture_ip4(self.pg2, tx)
936
Neale Ranns13721782021-05-13 15:28:27 +0000937 #
938 # An (S,G). for for-us
939 #
940 route_0_0_0_0_224_0_0_5 = VppIpMRoute(
941 self,
942 "0.0.0.0",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200943 "224.0.0.5",
944 32,
Neale Ranns13721782021-05-13 15:28:27 +0000945 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200946 [
947 VppMRoutePath(
948 self.pg8.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
949 ),
950 VppMRoutePath(
951 0xFFFFFFFF,
952 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
953 type=FibPathType.FIB_PATH_TYPE_LOCAL,
954 ),
955 ],
956 table_id=10,
957 )
Neale Ranns13721782021-05-13 15:28:27 +0000958 route_0_0_0_0_224_0_0_5.add_vpp_config()
959
960 #
961 # a stream that matches the route for (0.0.0.0, 224.0.0.5)
962 # small packets
963 #
964 self.vapi.cli("clear trace")
965 self.pg8.resolve_arp()
966
967 #
968 # send a ping to mcast address from peer on pg8
969 # expect a response
970 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200971 icmp_id = 0xB
Neale Ranns13721782021-05-13 15:28:27 +0000972 icmp_seq = 5
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200973 icmp_load = b"\x0a" * 18
974 tx = (
975 Ether(dst=getmacbyip("224.0.0.5"), src=self.pg8.remote_mac)
976 / IP(src=self.pg8.remote_ip4, dst="224.0.0.5")
977 / ICMP(id=icmp_id, seq=icmp_seq)
978 / Raw(load=icmp_load)
979 ) * 2
Neale Ranns13721782021-05-13 15:28:27 +0000980
981 self.send_and_expect(self.pg8, tx, self.pg8)
982
Dmitry Valter34fa0ce2024-03-11 10:38:46 +0000983 @unittest.skipIf(
984 "gre" in config.excluded_plugins, "Exclude tests requiring GRE plugin"
985 )
Neale Rannsadb17a82019-08-04 02:41:57 -0700986 def test_ip_mcast_gre(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200987 """IP Multicast Replication over GRE"""
Neale Rannsadb17a82019-08-04 02:41:57 -0700988
Neale Ranns990f6942020-10-20 07:20:17 +0000989 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
990 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
991
Neale Rannsadb17a82019-08-04 02:41:57 -0700992 gre_if_1 = VppGreInterface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200993 self, self.pg1.local_ip4, self.pg1.remote_ip4
994 ).add_vpp_config()
Neale Rannsadb17a82019-08-04 02:41:57 -0700995 gre_if_2 = VppGreInterface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200996 self, self.pg2.local_ip4, self.pg2.remote_ip4
997 ).add_vpp_config()
Neale Rannsadb17a82019-08-04 02:41:57 -0700998 gre_if_3 = VppGreInterface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200999 self, self.pg3.local_ip4, self.pg3.remote_ip4
1000 ).add_vpp_config()
Neale Rannsadb17a82019-08-04 02:41:57 -07001001
1002 gre_if_1.admin_up()
1003 gre_if_1.config_ip4()
1004 gre_if_2.admin_up()
1005 gre_if_2.config_ip4()
1006 gre_if_3.admin_up()
1007 gre_if_3.config_ip4()
1008
1009 #
1010 # An (S,G).
1011 # one accepting interface, pg0, 2 forwarding interfaces
1012 #
1013 route_1_1_1_1_232_1_1_1 = VppIpMRoute(
1014 self,
1015 "1.1.1.1",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001016 "232.2.2.2",
1017 64,
Neale Ranns990f6942020-10-20 07:20:17 +00001018 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001019 [
1020 VppMRoutePath(
1021 gre_if_1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
1022 ),
1023 VppMRoutePath(
1024 gre_if_2.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
1025 ),
1026 VppMRoutePath(
1027 gre_if_3.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
1028 ),
1029 ],
1030 )
Neale Rannsadb17a82019-08-04 02:41:57 -07001031 route_1_1_1_1_232_1_1_1.add_vpp_config()
1032
1033 #
1034 # a stream that matches the route for (1.1.1.1,232.2.2.2)
1035 # small packets
1036 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001037 tx = (
1038 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
1039 / IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4)
1040 / GRE()
1041 / IP(src="1.1.1.1", dst="232.2.2.2")
1042 / UDP(sport=1234, dport=1234)
1043 / Raw(b"\a5" * 64)
1044 ) * 63
Neale Rannsadb17a82019-08-04 02:41:57 -07001045
1046 self.vapi.cli("clear trace")
1047 self.pg1.add_stream(tx)
1048
1049 self.pg_enable_capture(self.pg_interfaces)
1050 self.pg_start()
1051
1052 # We expect replications on Pg2 & 3
1053 # check the encap headers are as expected based on the egress tunnel
1054 rxs = self.pg2.get_capture(len(tx))
1055 for rx in rxs:
1056 self.assertEqual(rx[IP].src, gre_if_2.t_src)
1057 self.assertEqual(rx[IP].dst, gre_if_2.t_dst)
1058 self.assert_packet_checksums_valid(rx)
1059
1060 rxs = self.pg3.get_capture(len(tx))
1061 for rx in rxs:
1062 self.assertEqual(rx[IP].src, gre_if_3.t_src)
1063 self.assertEqual(rx[IP].dst, gre_if_3.t_dst)
1064 self.assert_packet_checksums_valid(rx)
1065
Dmitry Valter34fa0ce2024-03-11 10:38:46 +00001066 @unittest.skipIf(
1067 "gre" in config.excluded_plugins, "Exclude tests requiring GRE plugin"
1068 )
Neale Ranns7d8a9562020-11-20 14:32:56 +00001069 def test_ip6_mcast_gre(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001070 """IP6 Multicast Replication over GRE"""
Neale Ranns7d8a9562020-11-20 14:32:56 +00001071
1072 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1073 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1074
1075 gre_if_1 = VppGreInterface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001076 self, self.pg1.local_ip4, self.pg1.remote_ip4
1077 ).add_vpp_config()
Neale Ranns7d8a9562020-11-20 14:32:56 +00001078 gre_if_2 = VppGreInterface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001079 self, self.pg2.local_ip4, self.pg2.remote_ip4
1080 ).add_vpp_config()
Neale Ranns7d8a9562020-11-20 14:32:56 +00001081 gre_if_3 = VppGreInterface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001082 self, self.pg3.local_ip4, self.pg3.remote_ip4
1083 ).add_vpp_config()
Neale Ranns7d8a9562020-11-20 14:32:56 +00001084
1085 gre_if_1.admin_up()
1086 gre_if_1.config_ip6()
1087 gre_if_2.admin_up()
1088 gre_if_2.config_ip6()
1089 gre_if_3.admin_up()
1090 gre_if_3.config_ip6()
1091
1092 #
1093 # An (S,G).
1094 # one accepting interface, pg0, 2 forwarding interfaces
1095 #
1096 route_1_1_FF_1 = VppIpMRoute(
1097 self,
1098 "1::1",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001099 "FF00::1",
1100 256,
Neale Ranns7d8a9562020-11-20 14:32:56 +00001101 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001102 [
1103 VppMRoutePath(
1104 gre_if_1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
1105 ),
1106 VppMRoutePath(
1107 gre_if_2.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
1108 ),
1109 VppMRoutePath(
1110 gre_if_3.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
1111 ),
1112 ],
1113 )
Neale Ranns7d8a9562020-11-20 14:32:56 +00001114 route_1_1_FF_1.add_vpp_config()
1115
1116 #
1117 # a stream that matches the route for (1::1, FF::1)
1118 # small packets
1119 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001120 tx = (
1121 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
1122 / IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4)
1123 / GRE()
1124 / IPv6(src="1::1", dst="FF00::1")
1125 / UDP(sport=1234, dport=1234)
1126 / Raw(b"\a5" * 64)
1127 ) * 63
Neale Ranns7d8a9562020-11-20 14:32:56 +00001128
1129 self.vapi.cli("clear trace")
1130 self.pg1.add_stream(tx)
1131
1132 self.pg_enable_capture(self.pg_interfaces)
1133 self.pg_start()
1134
1135 # We expect replications on Pg2 & 3
1136 # check the encap headers are as expected based on the egress tunnel
1137 rxs = self.pg2.get_capture(len(tx))
1138 for rx in rxs:
1139 self.assertEqual(rx[IP].src, gre_if_2.t_src)
1140 self.assertEqual(rx[IP].dst, gre_if_2.t_dst)
1141 self.assert_packet_checksums_valid(rx)
1142
1143 rxs = self.pg3.get_capture(len(tx))
1144 for rx in rxs:
1145 self.assertEqual(rx[IP].src, gre_if_3.t_src)
1146 self.assertEqual(rx[IP].dst, gre_if_3.t_dst)
1147 self.assert_packet_checksums_valid(rx)
1148
Neale Ranns15002542017-09-10 04:39:11 -07001149 def test_ip6_mcast_vrf(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001150 """IPv6 Multicast Replication in non-default table"""
Neale Ranns15002542017-09-10 04:39:11 -07001151
Neale Ranns990f6942020-10-20 07:20:17 +00001152 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1153 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1154
Neale Ranns15002542017-09-10 04:39:11 -07001155 #
1156 # An (S,G).
1157 # one accepting interface, pg0, 2 forwarding interfaces
1158 #
1159 route_2001_ff01_1 = VppIpMRoute(
1160 self,
1161 "2001::1",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001162 "ff01::1",
1163 256,
Neale Ranns990f6942020-10-20 07:20:17 +00001164 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001165 [
1166 VppMRoutePath(
1167 self.pg8.sw_if_index,
1168 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT,
1169 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
1170 ),
1171 VppMRoutePath(
1172 self.pg1.sw_if_index,
1173 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
1174 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
1175 ),
1176 VppMRoutePath(
1177 self.pg2.sw_if_index,
1178 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
1179 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
1180 ),
1181 ],
1182 table_id=10,
1183 )
Neale Ranns15002542017-09-10 04:39:11 -07001184 route_2001_ff01_1.add_vpp_config()
1185
1186 #
1187 # a stream that matches the route for (2001::1, ff00::1)
1188 #
1189 self.vapi.cli("clear trace")
1190 tx = self.create_stream_ip6(self.pg8, "2001::1", "ff01::1")
1191 self.pg8.add_stream(tx)
1192
1193 self.pg_enable_capture(self.pg_interfaces)
1194 self.pg_start()
1195
1196 # We expect replications on Pg1, 2,
1197 self.verify_capture_ip6(self.pg1, tx)
1198 self.verify_capture_ip6(self.pg2, tx)
Neale Ranns32e1c012016-11-22 17:07:28 +00001199
Neale Rannscf3561b2017-12-13 01:44:25 -08001200 def test_bidir(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001201 """IP Multicast Bi-directional"""
Neale Rannscf3561b2017-12-13 01:44:25 -08001202
Neale Ranns990f6942020-10-20 07:20:17 +00001203 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1204 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1205
Neale Rannscf3561b2017-12-13 01:44:25 -08001206 #
1207 # A (*,G). The set of accepting interfaces matching the forwarding
1208 #
1209 route_232_1_1_1 = VppIpMRoute(
1210 self,
1211 "0.0.0.0",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001212 "232.1.1.1",
1213 32,
Neale Ranns990f6942020-10-20 07:20:17 +00001214 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001215 [
1216 VppMRoutePath(
1217 self.pg0.sw_if_index,
1218 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
1219 | MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
1220 ),
1221 VppMRoutePath(
1222 self.pg1.sw_if_index,
1223 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
1224 | MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
1225 ),
1226 VppMRoutePath(
1227 self.pg2.sw_if_index,
1228 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
1229 | MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
1230 ),
1231 VppMRoutePath(
1232 self.pg3.sw_if_index,
1233 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
1234 | MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
1235 ),
1236 ],
1237 )
Neale Rannscf3561b2017-12-13 01:44:25 -08001238 route_232_1_1_1.add_vpp_config()
1239
1240 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.1")
1241 self.pg0.add_stream(tx)
1242
1243 self.pg_enable_capture(self.pg_interfaces)
1244 self.pg_start()
1245
1246 # We expect replications on Pg1, 2, 3, but not on pg0
1247 self.verify_capture_ip4(self.pg1, tx)
1248 self.verify_capture_ip4(self.pg2, tx)
1249 self.verify_capture_ip4(self.pg3, tx)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001250 self.pg0.assert_nothing_captured(remark="IP multicast packets forwarded on PG0")
Neale Rannscf3561b2017-12-13 01:44:25 -08001251
1252
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001253if __name__ == "__main__":
Neale Ranns32e1c012016-11-22 17:07:28 +00001254 unittest.main(testRunner=VppTestRunner)