blob: 564b4231da9ee802ffdfc7c8ead27f5b3983ede3 [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
Neale Ranns32e1c012016-11-22 17:07:28 +000017
18from scapy.packet import Raw
Neale Rannsadb17a82019-08-04 02:41:57 -070019from scapy.layers.l2 import Ether, GRE
Neale Ranns13721782021-05-13 15:28:27 +000020from scapy.layers.inet import IP, UDP, getmacbyip, ICMP
Neale Ranns32e1c012016-11-22 17:07:28 +000021from scapy.layers.inet6 import IPv6, getmacbyip6
Neale Ranns32e1c012016-11-22 17:07:28 +000022
Neale Ranns9bea8fb2017-02-03 04:34:01 -080023#
Neale Rannscf3561b2017-12-13 01:44:25 -080024# The number of packets sent is set to 91 so that when we replicate more than 3
Neale Ranns9bea8fb2017-02-03 04:34:01 -080025# times, which we do for some entries, we will generate more than 256 packets
Neale Rannsaaa396a2017-02-05 09:12:02 -080026# to the next node in the VLIB graph. Thus we are testing the code's
Neale Rannscf3561b2017-12-13 01:44:25 -080027# correctness handling this over-flow.
28# It's also an odd number so we hit any single loops.
Neale Ranns9bea8fb2017-02-03 04:34:01 -080029#
Neale Rannscf3561b2017-12-13 01:44:25 -080030N_PKTS_IN_STREAM = 91
Neale Ranns9bea8fb2017-02-03 04:34:01 -080031
Neale Ranns32e1c012016-11-22 17:07:28 +000032
Neale Ranns5a8123b2017-01-26 01:18:23 -080033class TestMFIB(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020034 """MFIB Test Case"""
Neale Ranns5a8123b2017-01-26 01:18:23 -080035
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070036 @classmethod
37 def setUpClass(cls):
38 super(TestMFIB, cls).setUpClass()
39
40 @classmethod
41 def tearDownClass(cls):
42 super(TestMFIB, cls).tearDownClass()
43
Neale Ranns5a8123b2017-01-26 01:18:23 -080044 def setUp(self):
45 super(TestMFIB, self).setUp()
46
47 def test_mfib(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020048 """MFIB Unit Tests"""
Neale Ranns5a8123b2017-01-26 01:18:23 -080049 error = self.vapi.cli("test mfib")
50
51 if error:
52 self.logger.critical(error)
Paul Vinciguerra9a6dafd2019-03-06 15:11:28 -080053 self.assertNotIn("Failed", error)
Neale Ranns5a8123b2017-01-26 01:18:23 -080054
55
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +000056@tag_fixme_vpp_workers
Neale Ranns32e1c012016-11-22 17:07:28 +000057class TestIPMcast(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020058 """IP Multicast Test Case"""
Neale Ranns32e1c012016-11-22 17:07:28 +000059
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070060 @classmethod
61 def setUpClass(cls):
62 super(TestIPMcast, cls).setUpClass()
63
64 @classmethod
65 def tearDownClass(cls):
66 super(TestIPMcast, cls).tearDownClass()
67
Neale Ranns32e1c012016-11-22 17:07:28 +000068 def setUp(self):
69 super(TestIPMcast, self).setUp()
70
Neale Ranns37be7362017-02-21 17:30:26 -080071 # create 8 pg interfaces
Neale Ranns15002542017-09-10 04:39:11 -070072 self.create_pg_interfaces(range(9))
Neale Ranns32e1c012016-11-22 17:07:28 +000073
74 # setup interfaces
Neale Ranns15002542017-09-10 04:39:11 -070075 for i in self.pg_interfaces[:8]:
Neale Ranns32e1c012016-11-22 17:07:28 +000076 i.admin_up()
77 i.config_ip4()
78 i.config_ip6()
79 i.resolve_arp()
80 i.resolve_ndp()
81
Neale Ranns15002542017-09-10 04:39:11 -070082 # one more in a vrf
83 tbl4 = VppIpTable(self, 10)
84 tbl4.add_vpp_config()
85 self.pg8.set_table_ip4(10)
86 self.pg8.config_ip4()
87
88 tbl6 = VppIpTable(self, 10, is_ip6=1)
89 tbl6.add_vpp_config()
90 self.pg8.set_table_ip6(10)
91 self.pg8.config_ip6()
92
93 def tearDown(self):
94 for i in self.pg_interfaces:
95 i.unconfig_ip4()
96 i.unconfig_ip6()
97 i.admin_down()
98
99 self.pg8.set_table_ip4(0)
100 self.pg8.set_table_ip6(0)
101 super(TestIPMcast, self).tearDown()
102
Neale Ranns9d676af2017-03-15 01:28:31 -0700103 def create_stream_ip4(self, src_if, src_ip, dst_ip, payload_size=0):
Neale Ranns32e1c012016-11-22 17:07:28 +0000104 pkts = []
Neale Ranns9d676af2017-03-15 01:28:31 -0700105 # default to small packet sizes
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200106 p = (
107 Ether(dst=getmacbyip(dst_ip), src=src_if.remote_mac)
108 / IP(src=src_ip, dst=dst_ip)
109 / UDP(sport=1234, dport=1234)
110 )
Neale Ranns9d676af2017-03-15 01:28:31 -0700111 if not payload_size:
112 payload_size = 64 - len(p)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200113 p = p / Raw(b"\xa5" * payload_size)
Neale Ranns9d676af2017-03-15 01:28:31 -0700114
Neale Ranns9bea8fb2017-02-03 04:34:01 -0800115 for i in range(0, N_PKTS_IN_STREAM):
Neale Ranns32e1c012016-11-22 17:07:28 +0000116 pkts.append(p)
117 return pkts
118
119 def create_stream_ip6(self, src_if, src_ip, dst_ip):
120 pkts = []
Neale Ranns9bea8fb2017-02-03 04:34:01 -0800121 for i in range(0, N_PKTS_IN_STREAM):
Neale Ranns32e1c012016-11-22 17:07:28 +0000122 info = self.create_packet_info(src_if, src_if)
123 payload = self.info_to_payload(info)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200124 p = (
125 Ether(dst=getmacbyip6(dst_ip), src=src_if.remote_mac)
126 / IPv6(src=src_ip, dst=dst_ip)
127 / UDP(sport=1234, dport=1234)
128 / Raw(payload)
129 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000130 info.data = p.copy()
131 pkts.append(p)
132 return pkts
133
134 def verify_filter(self, capture, sent):
135 if not len(capture) == len(sent):
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700136 # filter out any IPv6 RAs from the capture
Neale Ranns32e1c012016-11-22 17:07:28 +0000137 for p in capture:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200138 if p.haslayer(IPv6):
Neale Ranns32e1c012016-11-22 17:07:28 +0000139 capture.remove(p)
140 return capture
141
Neale Rannse821ab12017-06-01 07:45:05 -0700142 def verify_capture_ip4(self, rx_if, sent, dst_mac=None):
Neale Rannsc2aad532017-05-30 09:53:52 -0700143 rxd = rx_if.get_capture(len(sent))
Neale Ranns32e1c012016-11-22 17:07:28 +0000144
145 try:
146 capture = self.verify_filter(rxd, sent)
147
148 self.assertEqual(len(capture), len(sent))
149
150 for i in range(len(capture)):
151 tx = sent[i]
152 rx = capture[i]
153
Neale Ranns32e1c012016-11-22 17:07:28 +0000154 eth = rx[Ether]
155 self.assertEqual(eth.type, 0x800)
156
157 tx_ip = tx[IP]
158 rx_ip = rx[IP]
159
Neale Rannse821ab12017-06-01 07:45:05 -0700160 if dst_mac is None:
161 dst_mac = getmacbyip(rx_ip.dst)
162
Neale Ranns32e1c012016-11-22 17:07:28 +0000163 # check the MAC address on the RX'd packet is correctly formed
Neale Rannse821ab12017-06-01 07:45:05 -0700164 self.assertEqual(eth.dst, dst_mac)
Neale Ranns32e1c012016-11-22 17:07:28 +0000165
166 self.assertEqual(rx_ip.src, tx_ip.src)
167 self.assertEqual(rx_ip.dst, tx_ip.dst)
168 # IP processing post pop has decremented the TTL
169 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
170
171 except:
172 raise
173
Neale Rannsc2aad532017-05-30 09:53:52 -0700174 def verify_capture_ip6(self, rx_if, sent):
175 capture = rx_if.get_capture(len(sent))
Neale Ranns32e1c012016-11-22 17:07:28 +0000176
177 self.assertEqual(len(capture), len(sent))
178
179 for i in range(len(capture)):
180 tx = sent[i]
181 rx = capture[i]
182
Neale Ranns32e1c012016-11-22 17:07:28 +0000183 eth = rx[Ether]
184 self.assertEqual(eth.type, 0x86DD)
185
186 tx_ip = tx[IPv6]
187 rx_ip = rx[IPv6]
188
189 # check the MAC address on the RX'd packet is correctly formed
190 self.assertEqual(eth.dst, getmacbyip6(rx_ip.dst))
191
192 self.assertEqual(rx_ip.src, tx_ip.src)
193 self.assertEqual(rx_ip.dst, tx_ip.dst)
194 # IP processing post pop has decremented the TTL
195 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
196
197 def test_ip_mcast(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200198 """IP Multicast Replication"""
Neale Ranns32e1c012016-11-22 17:07:28 +0000199
Neale Ranns990f6942020-10-20 07:20:17 +0000200 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
201 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
202
Neale Ranns32e1c012016-11-22 17:07:28 +0000203 #
204 # a stream that matches the default route. gets dropped.
205 #
206 self.vapi.cli("clear trace")
Neale Ranns21fb4f72020-10-05 12:26:47 +0000207 self.vapi.cli("packet mac-filter pg0 on")
208 self.vapi.cli("packet mac-filter pg1 on")
209 self.vapi.cli("packet mac-filter pg2 on")
210 self.vapi.cli("packet mac-filter pg4 on")
211 self.vapi.cli("packet mac-filter pg5 on")
212 self.vapi.cli("packet mac-filter pg6 on")
213 self.vapi.cli("packet mac-filter pg7 on")
214
Neale Ranns32e1c012016-11-22 17:07:28 +0000215 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.1")
216 self.pg0.add_stream(tx)
217
218 self.pg_enable_capture(self.pg_interfaces)
219 self.pg_start()
220
221 self.pg0.assert_nothing_captured(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200222 remark="IP multicast packets forwarded on default route"
223 )
Neale Rannse22a7042022-08-09 03:03:29 +0000224 count = self.statistics.get_err_counter("/err/ip4-input/rpf_failure")
Neale Rannse8f57d52021-10-12 07:49:37 +0000225 self.assertEqual(count, len(tx))
Neale Ranns32e1c012016-11-22 17:07:28 +0000226
227 #
228 # A (*,G).
Neale Ranns37be7362017-02-21 17:30:26 -0800229 # one accepting interface, pg0, 7 forwarding interfaces
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700230 # many forwarding interfaces test the case where the replicate DPO
Neale Ranns37be7362017-02-21 17:30:26 -0800231 # needs to use extra cache lines for the buckets.
Neale Ranns32e1c012016-11-22 17:07:28 +0000232 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800233 route_232_1_1_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000234 self,
235 "0.0.0.0",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200236 "232.1.1.1",
237 32,
Neale Ranns990f6942020-10-20 07:20:17 +0000238 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200239 [
240 VppMRoutePath(
241 self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
242 ),
243 VppMRoutePath(
244 self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
245 ),
246 VppMRoutePath(
247 self.pg2.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
248 ),
249 VppMRoutePath(
250 self.pg3.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
251 ),
252 VppMRoutePath(
253 self.pg4.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
254 ),
255 VppMRoutePath(
256 self.pg5.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
257 ),
258 VppMRoutePath(
259 self.pg6.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
260 ),
261 VppMRoutePath(
262 self.pg7.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
263 ),
264 ],
265 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000266 route_232_1_1_1.add_vpp_config()
267
268 #
269 # An (S,G).
270 # one accepting interface, pg0, 2 forwarding interfaces
271 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800272 route_1_1_1_1_232_1_1_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000273 self,
274 "1.1.1.1",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200275 "232.1.1.1",
276 27, # any grp-len is ok when src is set
Neale Ranns990f6942020-10-20 07:20:17 +0000277 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200278 [
279 VppMRoutePath(
280 self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
281 ),
282 VppMRoutePath(
283 self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
284 ),
285 VppMRoutePath(
286 self.pg2.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
287 ),
288 ],
289 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000290 route_1_1_1_1_232_1_1_1.add_vpp_config()
291
292 #
Neale Rannse821ab12017-06-01 07:45:05 -0700293 # An (S,G).
294 # one accepting interface, pg0, 2 forwarding interfaces
295 # that use unicast next-hops
296 #
297 route_1_1_1_1_232_1_1_2 = VppIpMRoute(
298 self,
299 "1.1.1.1",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200300 "232.1.1.2",
301 64,
Neale Ranns990f6942020-10-20 07:20:17 +0000302 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200303 [
304 VppMRoutePath(
305 self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
306 ),
307 VppMRoutePath(
308 self.pg1.sw_if_index,
309 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
310 nh=self.pg1.remote_ip4,
311 ),
312 VppMRoutePath(
313 self.pg2.sw_if_index,
314 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
315 nh=self.pg2.remote_ip4,
316 ),
317 ],
318 )
Neale Rannse821ab12017-06-01 07:45:05 -0700319 route_1_1_1_1_232_1_1_2.add_vpp_config()
320
321 #
Neale Ranns32e1c012016-11-22 17:07:28 +0000322 # An (*,G/m).
323 # one accepting interface, pg0, 1 forwarding interfaces
324 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800325 route_232 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000326 self,
327 "0.0.0.0",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200328 "232.0.0.0",
329 8,
Neale Ranns990f6942020-10-20 07:20:17 +0000330 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200331 [
332 VppMRoutePath(
333 self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
334 ),
335 VppMRoutePath(
336 self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
337 ),
338 ],
339 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000340 route_232.add_vpp_config()
341
342 #
343 # a stream that matches the route for (1.1.1.1,232.1.1.1)
Neale Ranns9d676af2017-03-15 01:28:31 -0700344 # small packets
Neale Ranns32e1c012016-11-22 17:07:28 +0000345 #
346 self.vapi.cli("clear trace")
347 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.1")
348 self.pg0.add_stream(tx)
349
350 self.pg_enable_capture(self.pg_interfaces)
351 self.pg_start()
352
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200353 self.assertEqual(route_1_1_1_1_232_1_1_1.get_stats()["packets"], len(tx))
Neale Ranns28c142e2018-09-07 09:37:07 -0700354
Neale Ranns37be7362017-02-21 17:30:26 -0800355 # We expect replications on Pg1->7
Neale Ranns32e1c012016-11-22 17:07:28 +0000356 self.verify_capture_ip4(self.pg1, tx)
357 self.verify_capture_ip4(self.pg2, tx)
358
359 # no replications on Pg0
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200360 self.pg0.assert_nothing_captured(remark="IP multicast packets forwarded on PG0")
361 self.pg3.assert_nothing_captured(remark="IP multicast packets forwarded on PG3")
Neale Ranns32e1c012016-11-22 17:07:28 +0000362
363 #
Neale Ranns9d676af2017-03-15 01:28:31 -0700364 # a stream that matches the route for (1.1.1.1,232.1.1.1)
365 # large packets
366 #
367 self.vapi.cli("clear trace")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200368 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 -0700369 self.pg0.add_stream(tx)
370
371 self.pg_enable_capture(self.pg_interfaces)
372 self.pg_start()
373
374 # We expect replications on Pg1->7
375 self.verify_capture_ip4(self.pg1, tx)
376 self.verify_capture_ip4(self.pg2, tx)
Neale Ranns9d676af2017-03-15 01:28:31 -0700377
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200378 self.assertEqual(route_1_1_1_1_232_1_1_1.get_stats()["packets"], 2 * len(tx))
Neale Ranns28c142e2018-09-07 09:37:07 -0700379
Neale Ranns9d676af2017-03-15 01:28:31 -0700380 # no replications on Pg0
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200381 self.pg0.assert_nothing_captured(remark="IP multicast packets forwarded on PG0")
382 self.pg3.assert_nothing_captured(remark="IP multicast packets forwarded on PG3")
Neale Ranns9d676af2017-03-15 01:28:31 -0700383
384 #
Neale Rannse821ab12017-06-01 07:45:05 -0700385 # a stream to the unicast next-hops
386 #
387 self.vapi.cli("clear trace")
388 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.2")
389 self.pg0.add_stream(tx)
390
391 self.pg_enable_capture(self.pg_interfaces)
392 self.pg_start()
393
394 # We expect replications on Pg1->7
395 self.verify_capture_ip4(self.pg1, tx, dst_mac=self.pg1.remote_mac)
396 self.verify_capture_ip4(self.pg2, tx, dst_mac=self.pg2.remote_mac)
397
398 # no replications on Pg0 nor pg3
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200399 self.pg0.assert_nothing_captured(remark="IP multicast packets forwarded on PG0")
400 self.pg3.assert_nothing_captured(remark="IP multicast packets forwarded on PG3")
Neale Rannse821ab12017-06-01 07:45:05 -0700401
402 #
Neale Ranns32e1c012016-11-22 17:07:28 +0000403 # a stream that matches the route for (*,232.0.0.0/8)
404 # Send packets with the 9th bit set so we test the correct clearing
405 # of that bit in the mac rewrite
406 #
407 self.vapi.cli("clear trace")
408 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.255.255.255")
409 self.pg0.add_stream(tx)
410
411 self.pg_enable_capture(self.pg_interfaces)
412 self.pg_start()
413
414 # We expect replications on Pg1 only
415 self.verify_capture_ip4(self.pg1, tx)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200416 self.assertEqual(route_232.get_stats()["packets"], len(tx))
Neale Ranns32e1c012016-11-22 17:07:28 +0000417
418 # no replications on Pg0, Pg2 not Pg3
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200419 self.pg0.assert_nothing_captured(remark="IP multicast packets forwarded on PG0")
420 self.pg2.assert_nothing_captured(remark="IP multicast packets forwarded on PG2")
421 self.pg3.assert_nothing_captured(remark="IP multicast packets forwarded on PG3")
Neale Ranns32e1c012016-11-22 17:07:28 +0000422
423 #
424 # a stream that matches the route for (*,232.1.1.1)
425 #
426 self.vapi.cli("clear trace")
427 tx = self.create_stream_ip4(self.pg0, "1.1.1.2", "232.1.1.1")
428 self.pg0.add_stream(tx)
429
430 self.pg_enable_capture(self.pg_interfaces)
431 self.pg_start()
432
Neale Rannse821ab12017-06-01 07:45:05 -0700433 # We expect replications on Pg1->7
Neale Ranns32e1c012016-11-22 17:07:28 +0000434 self.verify_capture_ip4(self.pg1, tx)
435 self.verify_capture_ip4(self.pg2, tx)
436 self.verify_capture_ip4(self.pg3, tx)
Neale Rannsc2aad532017-05-30 09:53:52 -0700437 self.verify_capture_ip4(self.pg4, tx)
438 self.verify_capture_ip4(self.pg5, tx)
439 self.verify_capture_ip4(self.pg6, tx)
440 self.verify_capture_ip4(self.pg7, tx)
Neale Ranns32e1c012016-11-22 17:07:28 +0000441
Neale Rannse821ab12017-06-01 07:45:05 -0700442 # no replications on Pg0
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200443 self.pg0.assert_nothing_captured(remark="IP multicast packets forwarded on PG0")
Neale Rannse821ab12017-06-01 07:45:05 -0700444
Neale Ranns21fb4f72020-10-05 12:26:47 +0000445 self.vapi.cli("packet mac-filter pg0 off")
446 self.vapi.cli("packet mac-filter pg1 off")
447 self.vapi.cli("packet mac-filter pg2 off")
448 self.vapi.cli("packet mac-filter pg4 off")
449 self.vapi.cli("packet mac-filter pg5 off")
450 self.vapi.cli("packet mac-filter pg6 off")
451 self.vapi.cli("packet mac-filter pg7 off")
452
Neale Ranns32e1c012016-11-22 17:07:28 +0000453 def test_ip6_mcast(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200454 """IPv6 Multicast Replication"""
Neale Ranns32e1c012016-11-22 17:07:28 +0000455
Neale Ranns990f6942020-10-20 07:20:17 +0000456 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
457 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
458
Neale Ranns21fb4f72020-10-05 12:26:47 +0000459 self.vapi.cli("packet mac-filter pg0 on")
460 self.vapi.cli("packet mac-filter pg1 on")
461 self.vapi.cli("packet mac-filter pg2 on")
462 self.vapi.cli("packet mac-filter pg4 on")
463 self.vapi.cli("packet mac-filter pg5 on")
464 self.vapi.cli("packet mac-filter pg6 on")
465 self.vapi.cli("packet mac-filter pg7 on")
Neale Ranns32e1c012016-11-22 17:07:28 +0000466 #
467 # a stream that matches the default route. gets dropped.
468 #
469 self.vapi.cli("clear trace")
470 tx = self.create_stream_ip6(self.pg0, "2001::1", "ff01::1")
471 self.pg0.add_stream(tx)
472
473 self.pg_enable_capture(self.pg_interfaces)
474 self.pg_start()
475
476 self.pg0.assert_nothing_captured(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200477 remark="IPv6 multicast packets forwarded on default route"
478 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000479
480 #
481 # A (*,G).
482 # one accepting interface, pg0, 3 forwarding interfaces
483 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800484 route_ff01_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000485 self,
486 "::",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200487 "ff01::1",
488 128,
Neale Ranns990f6942020-10-20 07:20:17 +0000489 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200490 [
491 VppMRoutePath(
492 self.pg0.sw_if_index,
493 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT,
494 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
495 ),
496 VppMRoutePath(
497 self.pg1.sw_if_index,
498 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
499 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
500 ),
501 VppMRoutePath(
502 self.pg2.sw_if_index,
503 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
504 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
505 ),
506 VppMRoutePath(
507 self.pg3.sw_if_index,
508 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
509 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
510 ),
511 ],
512 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000513 route_ff01_1.add_vpp_config()
514
515 #
516 # An (S,G).
517 # one accepting interface, pg0, 2 forwarding interfaces
518 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800519 route_2001_ff01_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000520 self,
521 "2001::1",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200522 "ff01::1",
523 0, # any grp-len is ok when src is set
Neale Ranns990f6942020-10-20 07:20:17 +0000524 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200525 [
526 VppMRoutePath(
527 self.pg0.sw_if_index,
528 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT,
529 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
530 ),
531 VppMRoutePath(
532 self.pg1.sw_if_index,
533 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
534 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
535 ),
536 VppMRoutePath(
537 self.pg2.sw_if_index,
538 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
539 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
540 ),
541 ],
542 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000543 route_2001_ff01_1.add_vpp_config()
544
545 #
546 # An (*,G/m).
547 # one accepting interface, pg0, 1 forwarding interface
548 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800549 route_ff01 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000550 self,
551 "::",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200552 "ff01::",
553 16,
Neale Ranns990f6942020-10-20 07:20:17 +0000554 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200555 [
556 VppMRoutePath(
557 self.pg0.sw_if_index,
558 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT,
559 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
560 ),
561 VppMRoutePath(
562 self.pg1.sw_if_index,
563 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
564 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
565 ),
566 ],
567 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000568 route_ff01.add_vpp_config()
569
570 #
571 # a stream that matches the route for (*, ff01::/16)
Neale Rannsce111d22018-01-23 08:38:50 -0800572 # sent on the non-accepting interface
573 #
574 self.vapi.cli("clear trace")
575 tx = self.create_stream_ip6(self.pg1, "2002::1", "ff01:2::255")
576 self.send_and_assert_no_replies(self.pg1, tx, "RPF miss")
Neale Rannse22a7042022-08-09 03:03:29 +0000577 count = self.statistics.get_err_counter("/err/ip6-input/rpf_failure")
Neale Rannse8f57d52021-10-12 07:49:37 +0000578 self.assertEqual(count, 2 * len(tx))
Neale Rannsce111d22018-01-23 08:38:50 -0800579
580 #
581 # a stream that matches the route for (*, ff01::/16)
582 # sent on the accepting interface
Neale Ranns32e1c012016-11-22 17:07:28 +0000583 #
584 self.vapi.cli("clear trace")
585 tx = self.create_stream_ip6(self.pg0, "2002::1", "ff01:2::255")
586 self.pg0.add_stream(tx)
587
588 self.pg_enable_capture(self.pg_interfaces)
589 self.pg_start()
590
591 # We expect replications on Pg1
592 self.verify_capture_ip6(self.pg1, tx)
593
594 # no replications on Pg0, Pg3
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200595 self.pg0.assert_nothing_captured(remark="IP multicast packets forwarded on PG0")
596 self.pg2.assert_nothing_captured(remark="IP multicast packets forwarded on PG2")
597 self.pg3.assert_nothing_captured(remark="IP multicast packets forwarded on PG3")
Neale Ranns32e1c012016-11-22 17:07:28 +0000598
599 #
Neale Rannsc2aad532017-05-30 09:53:52 -0700600 # Bounce the interface and it should still work
601 #
602 self.pg1.admin_down()
603 self.pg0.add_stream(tx)
604 self.pg_enable_capture(self.pg_interfaces)
605 self.pg_start()
606 self.pg1.assert_nothing_captured(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200607 remark="IP multicast packets forwarded on down PG1"
608 )
Neale Rannsc2aad532017-05-30 09:53:52 -0700609
610 self.pg1.admin_up()
611 self.pg0.add_stream(tx)
612 self.pg_enable_capture(self.pg_interfaces)
613 self.pg_start()
614 self.verify_capture_ip6(self.pg1, tx)
615
616 #
Neale Ranns32e1c012016-11-22 17:07:28 +0000617 # a stream that matches the route for (*,ff01::1)
618 #
619 self.vapi.cli("clear trace")
620 tx = self.create_stream_ip6(self.pg0, "2002::2", "ff01::1")
621 self.pg0.add_stream(tx)
622
623 self.pg_enable_capture(self.pg_interfaces)
624 self.pg_start()
625
626 # We expect replications on Pg1, 2, 3.
627 self.verify_capture_ip6(self.pg1, tx)
628 self.verify_capture_ip6(self.pg2, tx)
629 self.verify_capture_ip6(self.pg3, tx)
630
631 # no replications on Pg0
632 self.pg0.assert_nothing_captured(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200633 remark="IPv6 multicast packets forwarded on PG0"
634 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000635
636 #
637 # a stream that matches the route for (2001::1, ff00::1)
638 #
639 self.vapi.cli("clear trace")
640 tx = self.create_stream_ip6(self.pg0, "2001::1", "ff01::1")
641 self.pg0.add_stream(tx)
642
643 self.pg_enable_capture(self.pg_interfaces)
644 self.pg_start()
645
646 # We expect replications on Pg1, 2,
647 self.verify_capture_ip6(self.pg1, tx)
648 self.verify_capture_ip6(self.pg2, tx)
649
650 # no replications on Pg0, Pg3
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200651 self.pg0.assert_nothing_captured(remark="IP multicast packets forwarded on PG0")
652 self.pg3.assert_nothing_captured(remark="IP multicast packets forwarded on PG3")
Neale Ranns32e1c012016-11-22 17:07:28 +0000653
Neale Ranns21fb4f72020-10-05 12:26:47 +0000654 self.vapi.cli("packet mac-filter pg0 off")
655 self.vapi.cli("packet mac-filter pg1 off")
656 self.vapi.cli("packet mac-filter pg2 off")
657 self.vapi.cli("packet mac-filter pg4 off")
658 self.vapi.cli("packet mac-filter pg5 off")
659 self.vapi.cli("packet mac-filter pg6 off")
660 self.vapi.cli("packet mac-filter pg7 off")
661
Neale Ranns32e1c012016-11-22 17:07:28 +0000662 def _mcast_connected_send_stream(self, dst_ip):
663 self.vapi.cli("clear trace")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200664 tx = self.create_stream_ip4(self.pg0, self.pg0.remote_ip4, dst_ip)
Neale Ranns32e1c012016-11-22 17:07:28 +0000665 self.pg0.add_stream(tx)
666
667 self.pg_enable_capture(self.pg_interfaces)
668 self.pg_start()
669
670 # We expect replications on Pg1.
671 self.verify_capture_ip4(self.pg1, tx)
672
673 return tx
674
675 def test_ip_mcast_connected(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200676 """IP Multicast Connected Source check"""
Neale Ranns32e1c012016-11-22 17:07:28 +0000677
Neale Ranns990f6942020-10-20 07:20:17 +0000678 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
679 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
680
Neale Ranns32e1c012016-11-22 17:07:28 +0000681 #
682 # A (*,G).
683 # one accepting interface, pg0, 1 forwarding interfaces
684 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800685 route_232_1_1_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000686 self,
687 "0.0.0.0",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200688 "232.1.1.1",
689 32,
Neale Ranns990f6942020-10-20 07:20:17 +0000690 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200691 [
692 VppMRoutePath(
693 self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
694 ),
695 VppMRoutePath(
696 self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
697 ),
698 ],
699 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000700
701 route_232_1_1_1.add_vpp_config()
702 route_232_1_1_1.update_entry_flags(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200703 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_CONNECTED
704 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000705
706 #
707 # Now the (*,G) is present, send from connected source
708 #
709 tx = self._mcast_connected_send_stream("232.1.1.1")
710
711 #
712 # Constrct a representation of the signal we expect on pg0
713 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200714 signal_232_1_1_1_itf_0 = VppMFibSignal(
715 self, route_232_1_1_1, self.pg0.sw_if_index, tx[0]
716 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000717
718 #
719 # read the only expected signal
720 #
721 signals = self.vapi.mfib_signal_dump()
722
723 self.assertEqual(1, len(signals))
724
725 signal_232_1_1_1_itf_0.compare(signals[0])
726
727 #
728 # reading the signal allows for the generation of another
729 # so send more packets and expect the next signal
730 #
731 tx = self._mcast_connected_send_stream("232.1.1.1")
732
733 signals = self.vapi.mfib_signal_dump()
734 self.assertEqual(1, len(signals))
735 signal_232_1_1_1_itf_0.compare(signals[0])
736
737 #
738 # A Second entry with connected check
739 # one accepting interface, pg0, 1 forwarding interfaces
740 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800741 route_232_1_1_2 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000742 self,
743 "0.0.0.0",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200744 "232.1.1.2",
745 32,
Neale Ranns990f6942020-10-20 07:20:17 +0000746 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200747 [
748 VppMRoutePath(
749 self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
750 ),
751 VppMRoutePath(
752 self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
753 ),
754 ],
755 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000756
757 route_232_1_1_2.add_vpp_config()
758 route_232_1_1_2.update_entry_flags(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200759 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_CONNECTED
760 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000761
762 #
763 # Send traffic to both entries. One read should net us two signals
764 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200765 signal_232_1_1_2_itf_0 = VppMFibSignal(
766 self, route_232_1_1_2, self.pg0.sw_if_index, tx[0]
767 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000768 tx = self._mcast_connected_send_stream("232.1.1.1")
769 tx2 = self._mcast_connected_send_stream("232.1.1.2")
770
771 #
772 # read the only expected signal
773 #
774 signals = self.vapi.mfib_signal_dump()
775
776 self.assertEqual(2, len(signals))
777
778 signal_232_1_1_1_itf_0.compare(signals[1])
779 signal_232_1_1_2_itf_0.compare(signals[0])
780
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200781 route_232_1_1_1.update_entry_flags(MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE)
782 route_232_1_1_2.update_entry_flags(MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE)
Neale Ranns32e1c012016-11-22 17:07:28 +0000783
784 def test_ip_mcast_signal(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200785 """IP Multicast Signal"""
Neale Ranns32e1c012016-11-22 17:07:28 +0000786
Neale Ranns990f6942020-10-20 07:20:17 +0000787 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
788 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
789
Neale Ranns32e1c012016-11-22 17:07:28 +0000790 #
791 # A (*,G).
792 # one accepting interface, pg0, 1 forwarding interfaces
793 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800794 route_232_1_1_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000795 self,
796 "0.0.0.0",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200797 "232.1.1.1",
798 32,
Neale Ranns990f6942020-10-20 07:20:17 +0000799 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200800 [
801 VppMRoutePath(
802 self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
803 ),
804 VppMRoutePath(
805 self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
806 ),
807 ],
808 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000809
810 route_232_1_1_1.add_vpp_config()
Neale Ranns097fa662018-05-01 05:17:55 -0700811
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200812 route_232_1_1_1.update_entry_flags(MRouteEntryFlags.MFIB_API_ENTRY_FLAG_SIGNAL)
Neale Ranns32e1c012016-11-22 17:07:28 +0000813
814 #
815 # Now the (*,G) is present, send from connected source
816 #
817 tx = self._mcast_connected_send_stream("232.1.1.1")
818
819 #
820 # Constrct a representation of the signal we expect on pg0
821 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200822 signal_232_1_1_1_itf_0 = VppMFibSignal(
823 self, route_232_1_1_1, self.pg0.sw_if_index, tx[0]
824 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000825
826 #
827 # read the only expected signal
828 #
829 signals = self.vapi.mfib_signal_dump()
830
831 self.assertEqual(1, len(signals))
832
833 signal_232_1_1_1_itf_0.compare(signals[0])
834
835 #
836 # reading the signal allows for the generation of another
837 # so send more packets and expect the next signal
838 #
839 tx = self._mcast_connected_send_stream("232.1.1.1")
840
841 signals = self.vapi.mfib_signal_dump()
842 self.assertEqual(1, len(signals))
843 signal_232_1_1_1_itf_0.compare(signals[0])
844
845 #
846 # Set the negate-signal on the accepting interval - the signals
847 # should stop
848 #
849 route_232_1_1_1.update_path_flags(
850 self.pg0.sw_if_index,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200851 (
852 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
853 | MRouteItfFlags.MFIB_API_ITF_FLAG_NEGATE_SIGNAL
854 ),
855 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000856
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800857 self.vapi.cli("clear trace")
Neale Ranns32e1c012016-11-22 17:07:28 +0000858 tx = self._mcast_connected_send_stream("232.1.1.1")
859
860 signals = self.vapi.mfib_signal_dump()
861 self.assertEqual(0, len(signals))
862
863 #
864 # Clear the SIGNAL flag on the entry and the signals should
865 # come back since the interface is still NEGATE-SIGNAL
866 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200867 route_232_1_1_1.update_entry_flags(MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE)
Neale Ranns32e1c012016-11-22 17:07:28 +0000868
869 tx = self._mcast_connected_send_stream("232.1.1.1")
870
871 signals = self.vapi.mfib_signal_dump()
872 self.assertEqual(1, len(signals))
873 signal_232_1_1_1_itf_0.compare(signals[0])
874
875 #
876 # Lastly remove the NEGATE-SIGNAL from the interface and the
877 # signals should stop
878 #
Neale Ranns990f6942020-10-20 07:20:17 +0000879 route_232_1_1_1.update_path_flags(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200880 self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
881 )
Neale Ranns32e1c012016-11-22 17:07:28 +0000882
883 tx = self._mcast_connected_send_stream("232.1.1.1")
884 signals = self.vapi.mfib_signal_dump()
885 self.assertEqual(0, len(signals))
886
Neale Ranns15002542017-09-10 04:39:11 -0700887 def test_ip_mcast_vrf(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200888 """IP Multicast Replication in non-default table"""
Neale Ranns15002542017-09-10 04:39:11 -0700889
Neale Ranns990f6942020-10-20 07:20:17 +0000890 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
891 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
892
Neale Ranns15002542017-09-10 04:39:11 -0700893 #
894 # An (S,G).
895 # one accepting interface, pg0, 2 forwarding interfaces
896 #
897 route_1_1_1_1_232_1_1_1 = VppIpMRoute(
898 self,
899 "1.1.1.1",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200900 "232.1.1.1",
901 64,
Neale Ranns990f6942020-10-20 07:20:17 +0000902 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200903 [
904 VppMRoutePath(
905 self.pg8.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
906 ),
907 VppMRoutePath(
908 self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
909 ),
910 VppMRoutePath(
911 self.pg2.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
912 ),
913 ],
914 table_id=10,
915 )
Neale Ranns15002542017-09-10 04:39:11 -0700916 route_1_1_1_1_232_1_1_1.add_vpp_config()
917
918 #
919 # a stream that matches the route for (1.1.1.1,232.1.1.1)
920 # small packets
921 #
922 self.vapi.cli("clear trace")
923 tx = self.create_stream_ip4(self.pg8, "1.1.1.1", "232.1.1.1")
924 self.pg8.add_stream(tx)
925
926 self.pg_enable_capture(self.pg_interfaces)
927 self.pg_start()
928
929 # We expect replications on Pg1 & 2
930 self.verify_capture_ip4(self.pg1, tx)
931 self.verify_capture_ip4(self.pg2, tx)
932
Neale Ranns13721782021-05-13 15:28:27 +0000933 #
934 # An (S,G). for for-us
935 #
936 route_0_0_0_0_224_0_0_5 = VppIpMRoute(
937 self,
938 "0.0.0.0",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200939 "224.0.0.5",
940 32,
Neale Ranns13721782021-05-13 15:28:27 +0000941 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200942 [
943 VppMRoutePath(
944 self.pg8.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
945 ),
946 VppMRoutePath(
947 0xFFFFFFFF,
948 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
949 type=FibPathType.FIB_PATH_TYPE_LOCAL,
950 ),
951 ],
952 table_id=10,
953 )
Neale Ranns13721782021-05-13 15:28:27 +0000954 route_0_0_0_0_224_0_0_5.add_vpp_config()
955
956 #
957 # a stream that matches the route for (0.0.0.0, 224.0.0.5)
958 # small packets
959 #
960 self.vapi.cli("clear trace")
961 self.pg8.resolve_arp()
962
963 #
964 # send a ping to mcast address from peer on pg8
965 # expect a response
966 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200967 icmp_id = 0xB
Neale Ranns13721782021-05-13 15:28:27 +0000968 icmp_seq = 5
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200969 icmp_load = b"\x0a" * 18
970 tx = (
971 Ether(dst=getmacbyip("224.0.0.5"), src=self.pg8.remote_mac)
972 / IP(src=self.pg8.remote_ip4, dst="224.0.0.5")
973 / ICMP(id=icmp_id, seq=icmp_seq)
974 / Raw(load=icmp_load)
975 ) * 2
Neale Ranns13721782021-05-13 15:28:27 +0000976
977 self.send_and_expect(self.pg8, tx, self.pg8)
978
Neale Rannsadb17a82019-08-04 02:41:57 -0700979 def test_ip_mcast_gre(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200980 """IP Multicast Replication over GRE"""
Neale Rannsadb17a82019-08-04 02:41:57 -0700981
Neale Ranns990f6942020-10-20 07:20:17 +0000982 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
983 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
984
Neale Rannsadb17a82019-08-04 02:41:57 -0700985 gre_if_1 = VppGreInterface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200986 self, self.pg1.local_ip4, self.pg1.remote_ip4
987 ).add_vpp_config()
Neale Rannsadb17a82019-08-04 02:41:57 -0700988 gre_if_2 = VppGreInterface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200989 self, self.pg2.local_ip4, self.pg2.remote_ip4
990 ).add_vpp_config()
Neale Rannsadb17a82019-08-04 02:41:57 -0700991 gre_if_3 = VppGreInterface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200992 self, self.pg3.local_ip4, self.pg3.remote_ip4
993 ).add_vpp_config()
Neale Rannsadb17a82019-08-04 02:41:57 -0700994
995 gre_if_1.admin_up()
996 gre_if_1.config_ip4()
997 gre_if_2.admin_up()
998 gre_if_2.config_ip4()
999 gre_if_3.admin_up()
1000 gre_if_3.config_ip4()
1001
1002 #
1003 # An (S,G).
1004 # one accepting interface, pg0, 2 forwarding interfaces
1005 #
1006 route_1_1_1_1_232_1_1_1 = VppIpMRoute(
1007 self,
1008 "1.1.1.1",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001009 "232.2.2.2",
1010 64,
Neale Ranns990f6942020-10-20 07:20:17 +00001011 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001012 [
1013 VppMRoutePath(
1014 gre_if_1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
1015 ),
1016 VppMRoutePath(
1017 gre_if_2.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
1018 ),
1019 VppMRoutePath(
1020 gre_if_3.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
1021 ),
1022 ],
1023 )
Neale Rannsadb17a82019-08-04 02:41:57 -07001024 route_1_1_1_1_232_1_1_1.add_vpp_config()
1025
1026 #
1027 # a stream that matches the route for (1.1.1.1,232.2.2.2)
1028 # small packets
1029 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001030 tx = (
1031 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
1032 / IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4)
1033 / GRE()
1034 / IP(src="1.1.1.1", dst="232.2.2.2")
1035 / UDP(sport=1234, dport=1234)
1036 / Raw(b"\a5" * 64)
1037 ) * 63
Neale Rannsadb17a82019-08-04 02:41:57 -07001038
1039 self.vapi.cli("clear trace")
1040 self.pg1.add_stream(tx)
1041
1042 self.pg_enable_capture(self.pg_interfaces)
1043 self.pg_start()
1044
1045 # We expect replications on Pg2 & 3
1046 # check the encap headers are as expected based on the egress tunnel
1047 rxs = self.pg2.get_capture(len(tx))
1048 for rx in rxs:
1049 self.assertEqual(rx[IP].src, gre_if_2.t_src)
1050 self.assertEqual(rx[IP].dst, gre_if_2.t_dst)
1051 self.assert_packet_checksums_valid(rx)
1052
1053 rxs = self.pg3.get_capture(len(tx))
1054 for rx in rxs:
1055 self.assertEqual(rx[IP].src, gre_if_3.t_src)
1056 self.assertEqual(rx[IP].dst, gre_if_3.t_dst)
1057 self.assert_packet_checksums_valid(rx)
1058
Neale Ranns7d8a9562020-11-20 14:32:56 +00001059 def test_ip6_mcast_gre(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001060 """IP6 Multicast Replication over GRE"""
Neale Ranns7d8a9562020-11-20 14:32:56 +00001061
1062 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1063 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1064
1065 gre_if_1 = VppGreInterface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001066 self, self.pg1.local_ip4, self.pg1.remote_ip4
1067 ).add_vpp_config()
Neale Ranns7d8a9562020-11-20 14:32:56 +00001068 gre_if_2 = VppGreInterface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001069 self, self.pg2.local_ip4, self.pg2.remote_ip4
1070 ).add_vpp_config()
Neale Ranns7d8a9562020-11-20 14:32:56 +00001071 gre_if_3 = VppGreInterface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001072 self, self.pg3.local_ip4, self.pg3.remote_ip4
1073 ).add_vpp_config()
Neale Ranns7d8a9562020-11-20 14:32:56 +00001074
1075 gre_if_1.admin_up()
1076 gre_if_1.config_ip6()
1077 gre_if_2.admin_up()
1078 gre_if_2.config_ip6()
1079 gre_if_3.admin_up()
1080 gre_if_3.config_ip6()
1081
1082 #
1083 # An (S,G).
1084 # one accepting interface, pg0, 2 forwarding interfaces
1085 #
1086 route_1_1_FF_1 = VppIpMRoute(
1087 self,
1088 "1::1",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001089 "FF00::1",
1090 256,
Neale Ranns7d8a9562020-11-20 14:32:56 +00001091 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001092 [
1093 VppMRoutePath(
1094 gre_if_1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
1095 ),
1096 VppMRoutePath(
1097 gre_if_2.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
1098 ),
1099 VppMRoutePath(
1100 gre_if_3.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD
1101 ),
1102 ],
1103 )
Neale Ranns7d8a9562020-11-20 14:32:56 +00001104 route_1_1_FF_1.add_vpp_config()
1105
1106 #
1107 # a stream that matches the route for (1::1, FF::1)
1108 # small packets
1109 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001110 tx = (
1111 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
1112 / IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4)
1113 / GRE()
1114 / IPv6(src="1::1", dst="FF00::1")
1115 / UDP(sport=1234, dport=1234)
1116 / Raw(b"\a5" * 64)
1117 ) * 63
Neale Ranns7d8a9562020-11-20 14:32:56 +00001118
1119 self.vapi.cli("clear trace")
1120 self.pg1.add_stream(tx)
1121
1122 self.pg_enable_capture(self.pg_interfaces)
1123 self.pg_start()
1124
1125 # We expect replications on Pg2 & 3
1126 # check the encap headers are as expected based on the egress tunnel
1127 rxs = self.pg2.get_capture(len(tx))
1128 for rx in rxs:
1129 self.assertEqual(rx[IP].src, gre_if_2.t_src)
1130 self.assertEqual(rx[IP].dst, gre_if_2.t_dst)
1131 self.assert_packet_checksums_valid(rx)
1132
1133 rxs = self.pg3.get_capture(len(tx))
1134 for rx in rxs:
1135 self.assertEqual(rx[IP].src, gre_if_3.t_src)
1136 self.assertEqual(rx[IP].dst, gre_if_3.t_dst)
1137 self.assert_packet_checksums_valid(rx)
1138
Neale Ranns15002542017-09-10 04:39:11 -07001139 def test_ip6_mcast_vrf(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001140 """IPv6 Multicast Replication in non-default table"""
Neale Ranns15002542017-09-10 04:39:11 -07001141
Neale Ranns990f6942020-10-20 07:20:17 +00001142 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1143 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1144
Neale Ranns15002542017-09-10 04:39:11 -07001145 #
1146 # An (S,G).
1147 # one accepting interface, pg0, 2 forwarding interfaces
1148 #
1149 route_2001_ff01_1 = VppIpMRoute(
1150 self,
1151 "2001::1",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001152 "ff01::1",
1153 256,
Neale Ranns990f6942020-10-20 07:20:17 +00001154 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001155 [
1156 VppMRoutePath(
1157 self.pg8.sw_if_index,
1158 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT,
1159 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
1160 ),
1161 VppMRoutePath(
1162 self.pg1.sw_if_index,
1163 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
1164 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
1165 ),
1166 VppMRoutePath(
1167 self.pg2.sw_if_index,
1168 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
1169 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6,
1170 ),
1171 ],
1172 table_id=10,
1173 )
Neale Ranns15002542017-09-10 04:39:11 -07001174 route_2001_ff01_1.add_vpp_config()
1175
1176 #
1177 # a stream that matches the route for (2001::1, ff00::1)
1178 #
1179 self.vapi.cli("clear trace")
1180 tx = self.create_stream_ip6(self.pg8, "2001::1", "ff01::1")
1181 self.pg8.add_stream(tx)
1182
1183 self.pg_enable_capture(self.pg_interfaces)
1184 self.pg_start()
1185
1186 # We expect replications on Pg1, 2,
1187 self.verify_capture_ip6(self.pg1, tx)
1188 self.verify_capture_ip6(self.pg2, tx)
Neale Ranns32e1c012016-11-22 17:07:28 +00001189
Neale Rannscf3561b2017-12-13 01:44:25 -08001190 def test_bidir(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001191 """IP Multicast Bi-directional"""
Neale Rannscf3561b2017-12-13 01:44:25 -08001192
Neale Ranns990f6942020-10-20 07:20:17 +00001193 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1194 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1195
Neale Rannscf3561b2017-12-13 01:44:25 -08001196 #
1197 # A (*,G). The set of accepting interfaces matching the forwarding
1198 #
1199 route_232_1_1_1 = VppIpMRoute(
1200 self,
1201 "0.0.0.0",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001202 "232.1.1.1",
1203 32,
Neale Ranns990f6942020-10-20 07:20:17 +00001204 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001205 [
1206 VppMRoutePath(
1207 self.pg0.sw_if_index,
1208 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
1209 | MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
1210 ),
1211 VppMRoutePath(
1212 self.pg1.sw_if_index,
1213 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
1214 | MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
1215 ),
1216 VppMRoutePath(
1217 self.pg2.sw_if_index,
1218 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
1219 | MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
1220 ),
1221 VppMRoutePath(
1222 self.pg3.sw_if_index,
1223 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT
1224 | MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
1225 ),
1226 ],
1227 )
Neale Rannscf3561b2017-12-13 01:44:25 -08001228 route_232_1_1_1.add_vpp_config()
1229
1230 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.1")
1231 self.pg0.add_stream(tx)
1232
1233 self.pg_enable_capture(self.pg_interfaces)
1234 self.pg_start()
1235
1236 # We expect replications on Pg1, 2, 3, but not on pg0
1237 self.verify_capture_ip4(self.pg1, tx)
1238 self.verify_capture_ip4(self.pg2, tx)
1239 self.verify_capture_ip4(self.pg3, tx)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001240 self.pg0.assert_nothing_captured(remark="IP multicast packets forwarded on PG0")
Neale Rannscf3561b2017-12-13 01:44:25 -08001241
1242
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001243if __name__ == "__main__":
Neale Ranns32e1c012016-11-22 17:07:28 +00001244 unittest.main(testRunner=VppTestRunner)