blob: b060e97ff9d14893b4949378e4c13bfdcc62e550 [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 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
Neale Ranns15002542017-09-10 04:39:11 -0700888 def test_ip_mcast_vrf(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200889 """IP Multicast Replication in non-default table"""
Neale Ranns15002542017-09-10 04:39:11 -0700890
Neale Ranns990f6942020-10-20 07:20:17 +0000891 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
892 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
893
Neale Ranns15002542017-09-10 04:39:11 -0700894 #
895 # An (S,G).
896 # one accepting interface, pg0, 2 forwarding interfaces
897 #
898 route_1_1_1_1_232_1_1_1 = VppIpMRoute(
899 self,
900 "1.1.1.1",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200901 "232.1.1.1",
902 64,
Neale Ranns990f6942020-10-20 07:20:17 +0000903 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200904 [
905 VppMRoutePath(
906 self.pg8.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
907 ),
908 VppMRoutePath(
909 self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
910 ),
911 VppMRoutePath(
912 self.pg2.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
913 ),
914 ],
915 table_id=10,
916 )
Neale Ranns15002542017-09-10 04:39:11 -0700917 route_1_1_1_1_232_1_1_1.add_vpp_config()
918
919 #
920 # a stream that matches the route for (1.1.1.1,232.1.1.1)
921 # small packets
922 #
923 self.vapi.cli("clear trace")
924 tx = self.create_stream_ip4(self.pg8, "1.1.1.1", "232.1.1.1")
925 self.pg8.add_stream(tx)
926
927 self.pg_enable_capture(self.pg_interfaces)
928 self.pg_start()
929
930 # We expect replications on Pg1 & 2
931 self.verify_capture_ip4(self.pg1, tx)
932 self.verify_capture_ip4(self.pg2, tx)
933
Neale Ranns13721782021-05-13 15:28:27 +0000934 #
935 # An (S,G). for for-us
936 #
937 route_0_0_0_0_224_0_0_5 = VppIpMRoute(
938 self,
939 "0.0.0.0",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200940 "224.0.0.5",
941 32,
Neale Ranns13721782021-05-13 15:28:27 +0000942 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200943 [
944 VppMRoutePath(
945 self.pg8.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
946 ),
947 VppMRoutePath(
948 0xFFFFFFFF,
949 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
950 type=FibPathType.FIB_PATH_TYPE_LOCAL,
951 ),
952 ],
953 table_id=10,
954 )
Neale Ranns13721782021-05-13 15:28:27 +0000955 route_0_0_0_0_224_0_0_5.add_vpp_config()
956
957 #
958 # a stream that matches the route for (0.0.0.0, 224.0.0.5)
959 # small packets
960 #
961 self.vapi.cli("clear trace")
962 self.pg8.resolve_arp()
963
964 #
965 # send a ping to mcast address from peer on pg8
966 # expect a response
967 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200968 icmp_id = 0xB
Neale Ranns13721782021-05-13 15:28:27 +0000969 icmp_seq = 5
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200970 icmp_load = b"\x0a" * 18
971 tx = (
972 Ether(dst=getmacbyip("224.0.0.5"), src=self.pg8.remote_mac)
973 / IP(src=self.pg8.remote_ip4, dst="224.0.0.5")
974 / ICMP(id=icmp_id, seq=icmp_seq)
975 / Raw(load=icmp_load)
976 ) * 2
Neale Ranns13721782021-05-13 15:28:27 +0000977
978 self.send_and_expect(self.pg8, tx, self.pg8)
979
Neale Rannsadb17a82019-08-04 02:41:57 -0700980 def test_ip_mcast_gre(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200981 """IP Multicast Replication over GRE"""
Neale Rannsadb17a82019-08-04 02:41:57 -0700982
Neale Ranns990f6942020-10-20 07:20:17 +0000983 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
984 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
985
Neale Rannsadb17a82019-08-04 02:41:57 -0700986 gre_if_1 = VppGreInterface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200987 self, self.pg1.local_ip4, self.pg1.remote_ip4
988 ).add_vpp_config()
Neale Rannsadb17a82019-08-04 02:41:57 -0700989 gre_if_2 = VppGreInterface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200990 self, self.pg2.local_ip4, self.pg2.remote_ip4
991 ).add_vpp_config()
Neale Rannsadb17a82019-08-04 02:41:57 -0700992 gre_if_3 = VppGreInterface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200993 self, self.pg3.local_ip4, self.pg3.remote_ip4
994 ).add_vpp_config()
Neale Rannsadb17a82019-08-04 02:41:57 -0700995
996 gre_if_1.admin_up()
997 gre_if_1.config_ip4()
998 gre_if_2.admin_up()
999 gre_if_2.config_ip4()
1000 gre_if_3.admin_up()
1001 gre_if_3.config_ip4()
1002
1003 #
1004 # An (S,G).
1005 # one accepting interface, pg0, 2 forwarding interfaces
1006 #
1007 route_1_1_1_1_232_1_1_1 = VppIpMRoute(
1008 self,
1009 "1.1.1.1",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001010 "232.2.2.2",
1011 64,
Neale Ranns990f6942020-10-20 07:20:17 +00001012 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001013 [
1014 VppMRoutePath(
1015 gre_if_1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
1016 ),
1017 VppMRoutePath(
1018 gre_if_2.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
1019 ),
1020 VppMRoutePath(
1021 gre_if_3.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
1022 ),
1023 ],
1024 )
Neale Rannsadb17a82019-08-04 02:41:57 -07001025 route_1_1_1_1_232_1_1_1.add_vpp_config()
1026
1027 #
1028 # a stream that matches the route for (1.1.1.1,232.2.2.2)
1029 # small packets
1030 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001031 tx = (
1032 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
1033 / IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4)
1034 / GRE()
1035 / IP(src="1.1.1.1", dst="232.2.2.2")
1036 / UDP(sport=1234, dport=1234)
1037 / Raw(b"\a5" * 64)
1038 ) * 63
Neale Rannsadb17a82019-08-04 02:41:57 -07001039
1040 self.vapi.cli("clear trace")
1041 self.pg1.add_stream(tx)
1042
1043 self.pg_enable_capture(self.pg_interfaces)
1044 self.pg_start()
1045
1046 # We expect replications on Pg2 & 3
1047 # check the encap headers are as expected based on the egress tunnel
1048 rxs = self.pg2.get_capture(len(tx))
1049 for rx in rxs:
1050 self.assertEqual(rx[IP].src, gre_if_2.t_src)
1051 self.assertEqual(rx[IP].dst, gre_if_2.t_dst)
1052 self.assert_packet_checksums_valid(rx)
1053
1054 rxs = self.pg3.get_capture(len(tx))
1055 for rx in rxs:
1056 self.assertEqual(rx[IP].src, gre_if_3.t_src)
1057 self.assertEqual(rx[IP].dst, gre_if_3.t_dst)
1058 self.assert_packet_checksums_valid(rx)
1059
Neale Ranns7d8a9562020-11-20 14:32:56 +00001060 def test_ip6_mcast_gre(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001061 """IP6 Multicast Replication over GRE"""
Neale Ranns7d8a9562020-11-20 14:32:56 +00001062
1063 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1064 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1065
1066 gre_if_1 = VppGreInterface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001067 self, self.pg1.local_ip4, self.pg1.remote_ip4
1068 ).add_vpp_config()
Neale Ranns7d8a9562020-11-20 14:32:56 +00001069 gre_if_2 = VppGreInterface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001070 self, self.pg2.local_ip4, self.pg2.remote_ip4
1071 ).add_vpp_config()
Neale Ranns7d8a9562020-11-20 14:32:56 +00001072 gre_if_3 = VppGreInterface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001073 self, self.pg3.local_ip4, self.pg3.remote_ip4
1074 ).add_vpp_config()
Neale Ranns7d8a9562020-11-20 14:32:56 +00001075
1076 gre_if_1.admin_up()
1077 gre_if_1.config_ip6()
1078 gre_if_2.admin_up()
1079 gre_if_2.config_ip6()
1080 gre_if_3.admin_up()
1081 gre_if_3.config_ip6()
1082
1083 #
1084 # An (S,G).
1085 # one accepting interface, pg0, 2 forwarding interfaces
1086 #
1087 route_1_1_FF_1 = VppIpMRoute(
1088 self,
1089 "1::1",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001090 "FF00::1",
1091 256,
Neale Ranns7d8a9562020-11-20 14:32:56 +00001092 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001093 [
1094 VppMRoutePath(
1095 gre_if_1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
1096 ),
1097 VppMRoutePath(
1098 gre_if_2.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
1099 ),
1100 VppMRoutePath(
1101 gre_if_3.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
1102 ),
1103 ],
1104 )
Neale Ranns7d8a9562020-11-20 14:32:56 +00001105 route_1_1_FF_1.add_vpp_config()
1106
1107 #
1108 # a stream that matches the route for (1::1, FF::1)
1109 # small packets
1110 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001111 tx = (
1112 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
1113 / IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4)
1114 / GRE()
1115 / IPv6(src="1::1", dst="FF00::1")
1116 / UDP(sport=1234, dport=1234)
1117 / Raw(b"\a5" * 64)
1118 ) * 63
Neale Ranns7d8a9562020-11-20 14:32:56 +00001119
1120 self.vapi.cli("clear trace")
1121 self.pg1.add_stream(tx)
1122
1123 self.pg_enable_capture(self.pg_interfaces)
1124 self.pg_start()
1125
1126 # We expect replications on Pg2 & 3
1127 # check the encap headers are as expected based on the egress tunnel
1128 rxs = self.pg2.get_capture(len(tx))
1129 for rx in rxs:
1130 self.assertEqual(rx[IP].src, gre_if_2.t_src)
1131 self.assertEqual(rx[IP].dst, gre_if_2.t_dst)
1132 self.assert_packet_checksums_valid(rx)
1133
1134 rxs = self.pg3.get_capture(len(tx))
1135 for rx in rxs:
1136 self.assertEqual(rx[IP].src, gre_if_3.t_src)
1137 self.assertEqual(rx[IP].dst, gre_if_3.t_dst)
1138 self.assert_packet_checksums_valid(rx)
1139
Neale Ranns15002542017-09-10 04:39:11 -07001140 def test_ip6_mcast_vrf(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001141 """IPv6 Multicast Replication in non-default table"""
Neale Ranns15002542017-09-10 04:39:11 -07001142
Neale Ranns990f6942020-10-20 07:20:17 +00001143 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1144 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1145
Neale Ranns15002542017-09-10 04:39:11 -07001146 #
1147 # An (S,G).
1148 # one accepting interface, pg0, 2 forwarding interfaces
1149 #
1150 route_2001_ff01_1 = VppIpMRoute(
1151 self,
1152 "2001::1",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001153 "ff01::1",
1154 256,
Neale Ranns990f6942020-10-20 07:20:17 +00001155 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001156 [
1157 VppMRoutePath(
1158 self.pg8.sw_if_index,
1159 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT,
1160 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
1161 ),
1162 VppMRoutePath(
1163 self.pg1.sw_if_index,
1164 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
1165 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
1166 ),
1167 VppMRoutePath(
1168 self.pg2.sw_if_index,
1169 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
1170 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
1171 ),
1172 ],
1173 table_id=10,
1174 )
Neale Ranns15002542017-09-10 04:39:11 -07001175 route_2001_ff01_1.add_vpp_config()
1176
1177 #
1178 # a stream that matches the route for (2001::1, ff00::1)
1179 #
1180 self.vapi.cli("clear trace")
1181 tx = self.create_stream_ip6(self.pg8, "2001::1", "ff01::1")
1182 self.pg8.add_stream(tx)
1183
1184 self.pg_enable_capture(self.pg_interfaces)
1185 self.pg_start()
1186
1187 # We expect replications on Pg1, 2,
1188 self.verify_capture_ip6(self.pg1, tx)
1189 self.verify_capture_ip6(self.pg2, tx)
Neale Ranns32e1c012016-11-22 17:07:28 +00001190
Neale Rannscf3561b2017-12-13 01:44:25 -08001191 def test_bidir(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001192 """IP Multicast Bi-directional"""
Neale Rannscf3561b2017-12-13 01:44:25 -08001193
Neale Ranns990f6942020-10-20 07:20:17 +00001194 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1195 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1196
Neale Rannscf3561b2017-12-13 01:44:25 -08001197 #
1198 # A (*,G). The set of accepting interfaces matching the forwarding
1199 #
1200 route_232_1_1_1 = VppIpMRoute(
1201 self,
1202 "0.0.0.0",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001203 "232.1.1.1",
1204 32,
Neale Ranns990f6942020-10-20 07:20:17 +00001205 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001206 [
1207 VppMRoutePath(
1208 self.pg0.sw_if_index,
1209 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
1210 | MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
1211 ),
1212 VppMRoutePath(
1213 self.pg1.sw_if_index,
1214 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
1215 | MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
1216 ),
1217 VppMRoutePath(
1218 self.pg2.sw_if_index,
1219 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
1220 | MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
1221 ),
1222 VppMRoutePath(
1223 self.pg3.sw_if_index,
1224 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
1225 | MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
1226 ),
1227 ],
1228 )
Neale Rannscf3561b2017-12-13 01:44:25 -08001229 route_232_1_1_1.add_vpp_config()
1230
1231 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.1")
1232 self.pg0.add_stream(tx)
1233
1234 self.pg_enable_capture(self.pg_interfaces)
1235 self.pg_start()
1236
1237 # We expect replications on Pg1, 2, 3, but not on pg0
1238 self.verify_capture_ip4(self.pg1, tx)
1239 self.verify_capture_ip4(self.pg2, tx)
1240 self.verify_capture_ip4(self.pg3, tx)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001241 self.pg0.assert_nothing_captured(remark="IP multicast packets forwarded on PG0")
Neale Rannscf3561b2017-12-13 01:44:25 -08001242
1243
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001244if __name__ == "__main__":
Neale Ranns32e1c012016-11-22 17:07:28 +00001245 unittest.main(testRunner=VppTestRunner)