blob: 50ac01b884436c4ce7eb991eb4f0240d2be93bf5 [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
Neale Ranns180279b2017-03-16 15:49:09 -04008from vpp_ip_route import VppIpMRoute, VppMRoutePath, VppMFibSignal, \
Neale Ranns13721782021-05-13 15:28:27 +00009 VppIpTable, FibPathProto, FibPathType
Neale Rannsadb17a82019-08-04 02:41:57 -070010from vpp_gre_interface import VppGreInterface
Neale Ranns990f6942020-10-20 07:20:17 +000011from vpp_papi import VppEnum
Neale Ranns32e1c012016-11-22 17:07:28 +000012
13from scapy.packet import Raw
Neale Rannsadb17a82019-08-04 02:41:57 -070014from scapy.layers.l2 import Ether, GRE
Neale Ranns13721782021-05-13 15:28:27 +000015from scapy.layers.inet import IP, UDP, getmacbyip, ICMP
Neale Ranns32e1c012016-11-22 17:07:28 +000016from scapy.layers.inet6 import IPv6, getmacbyip6
Neale Ranns32e1c012016-11-22 17:07:28 +000017
Neale Ranns9bea8fb2017-02-03 04:34:01 -080018#
Neale Rannscf3561b2017-12-13 01:44:25 -080019# The number of packets sent is set to 91 so that when we replicate more than 3
Neale Ranns9bea8fb2017-02-03 04:34:01 -080020# times, which we do for some entries, we will generate more than 256 packets
Neale Rannsaaa396a2017-02-05 09:12:02 -080021# to the next node in the VLIB graph. Thus we are testing the code's
Neale Rannscf3561b2017-12-13 01:44:25 -080022# correctness handling this over-flow.
23# It's also an odd number so we hit any single loops.
Neale Ranns9bea8fb2017-02-03 04:34:01 -080024#
Neale Rannscf3561b2017-12-13 01:44:25 -080025N_PKTS_IN_STREAM = 91
Neale Ranns9bea8fb2017-02-03 04:34:01 -080026
Neale Ranns32e1c012016-11-22 17:07:28 +000027
Neale Ranns5a8123b2017-01-26 01:18:23 -080028class TestMFIB(VppTestCase):
29 """ MFIB Test Case """
30
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070031 @classmethod
32 def setUpClass(cls):
33 super(TestMFIB, cls).setUpClass()
34
35 @classmethod
36 def tearDownClass(cls):
37 super(TestMFIB, cls).tearDownClass()
38
Neale Ranns5a8123b2017-01-26 01:18:23 -080039 def setUp(self):
40 super(TestMFIB, self).setUp()
41
42 def test_mfib(self):
43 """ MFIB Unit Tests """
44 error = self.vapi.cli("test mfib")
45
46 if error:
47 self.logger.critical(error)
Paul Vinciguerra9a6dafd2019-03-06 15:11:28 -080048 self.assertNotIn("Failed", error)
Neale Ranns5a8123b2017-01-26 01:18:23 -080049
50
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +000051@tag_fixme_vpp_workers
Neale Ranns32e1c012016-11-22 17:07:28 +000052class TestIPMcast(VppTestCase):
53 """ IP Multicast Test Case """
54
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070055 @classmethod
56 def setUpClass(cls):
57 super(TestIPMcast, cls).setUpClass()
58
59 @classmethod
60 def tearDownClass(cls):
61 super(TestIPMcast, cls).tearDownClass()
62
Neale Ranns32e1c012016-11-22 17:07:28 +000063 def setUp(self):
64 super(TestIPMcast, self).setUp()
65
Neale Ranns37be7362017-02-21 17:30:26 -080066 # create 8 pg interfaces
Neale Ranns15002542017-09-10 04:39:11 -070067 self.create_pg_interfaces(range(9))
Neale Ranns32e1c012016-11-22 17:07:28 +000068
69 # setup interfaces
Neale Ranns15002542017-09-10 04:39:11 -070070 for i in self.pg_interfaces[:8]:
Neale Ranns32e1c012016-11-22 17:07:28 +000071 i.admin_up()
72 i.config_ip4()
73 i.config_ip6()
74 i.resolve_arp()
75 i.resolve_ndp()
76
Neale Ranns15002542017-09-10 04:39:11 -070077 # one more in a vrf
78 tbl4 = VppIpTable(self, 10)
79 tbl4.add_vpp_config()
80 self.pg8.set_table_ip4(10)
81 self.pg8.config_ip4()
82
83 tbl6 = VppIpTable(self, 10, is_ip6=1)
84 tbl6.add_vpp_config()
85 self.pg8.set_table_ip6(10)
86 self.pg8.config_ip6()
87
88 def tearDown(self):
89 for i in self.pg_interfaces:
90 i.unconfig_ip4()
91 i.unconfig_ip6()
92 i.admin_down()
93
94 self.pg8.set_table_ip4(0)
95 self.pg8.set_table_ip6(0)
96 super(TestIPMcast, self).tearDown()
97
Neale Ranns9d676af2017-03-15 01:28:31 -070098 def create_stream_ip4(self, src_if, src_ip, dst_ip, payload_size=0):
Neale Ranns32e1c012016-11-22 17:07:28 +000099 pkts = []
Neale Ranns9d676af2017-03-15 01:28:31 -0700100 # default to small packet sizes
Neale Ranns21fb4f72020-10-05 12:26:47 +0000101 p = (Ether(dst=getmacbyip(dst_ip), src=src_if.remote_mac) /
Neale Ranns9d676af2017-03-15 01:28:31 -0700102 IP(src=src_ip, dst=dst_ip) /
103 UDP(sport=1234, dport=1234))
104 if not payload_size:
105 payload_size = 64 - len(p)
Ole Troan770a0de2019-11-07 13:52:21 +0100106 p = p / Raw(b'\xa5' * payload_size)
Neale Ranns9d676af2017-03-15 01:28:31 -0700107
Neale Ranns9bea8fb2017-02-03 04:34:01 -0800108 for i in range(0, N_PKTS_IN_STREAM):
Neale Ranns32e1c012016-11-22 17:07:28 +0000109 pkts.append(p)
110 return pkts
111
112 def create_stream_ip6(self, src_if, src_ip, dst_ip):
113 pkts = []
Neale Ranns9bea8fb2017-02-03 04:34:01 -0800114 for i in range(0, N_PKTS_IN_STREAM):
Neale Ranns32e1c012016-11-22 17:07:28 +0000115 info = self.create_packet_info(src_if, src_if)
116 payload = self.info_to_payload(info)
Neale Ranns21fb4f72020-10-05 12:26:47 +0000117 p = (Ether(dst=getmacbyip6(dst_ip), src=src_if.remote_mac) /
Neale Ranns32e1c012016-11-22 17:07:28 +0000118 IPv6(src=src_ip, dst=dst_ip) /
119 UDP(sport=1234, dport=1234) /
120 Raw(payload))
121 info.data = p.copy()
122 pkts.append(p)
123 return pkts
124
125 def verify_filter(self, capture, sent):
126 if not len(capture) == len(sent):
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700127 # filter out any IPv6 RAs from the capture
Neale Ranns32e1c012016-11-22 17:07:28 +0000128 for p in capture:
129 if (p.haslayer(IPv6)):
130 capture.remove(p)
131 return capture
132
Neale Rannse821ab12017-06-01 07:45:05 -0700133 def verify_capture_ip4(self, rx_if, sent, dst_mac=None):
Neale Rannsc2aad532017-05-30 09:53:52 -0700134 rxd = rx_if.get_capture(len(sent))
Neale Ranns32e1c012016-11-22 17:07:28 +0000135
136 try:
137 capture = self.verify_filter(rxd, sent)
138
139 self.assertEqual(len(capture), len(sent))
140
141 for i in range(len(capture)):
142 tx = sent[i]
143 rx = capture[i]
144
Neale Ranns32e1c012016-11-22 17:07:28 +0000145 eth = rx[Ether]
146 self.assertEqual(eth.type, 0x800)
147
148 tx_ip = tx[IP]
149 rx_ip = rx[IP]
150
Neale Rannse821ab12017-06-01 07:45:05 -0700151 if dst_mac is None:
152 dst_mac = getmacbyip(rx_ip.dst)
153
Neale Ranns32e1c012016-11-22 17:07:28 +0000154 # check the MAC address on the RX'd packet is correctly formed
Neale Rannse821ab12017-06-01 07:45:05 -0700155 self.assertEqual(eth.dst, dst_mac)
Neale Ranns32e1c012016-11-22 17:07:28 +0000156
157 self.assertEqual(rx_ip.src, tx_ip.src)
158 self.assertEqual(rx_ip.dst, tx_ip.dst)
159 # IP processing post pop has decremented the TTL
160 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
161
162 except:
163 raise
164
Neale Rannsc2aad532017-05-30 09:53:52 -0700165 def verify_capture_ip6(self, rx_if, sent):
166 capture = rx_if.get_capture(len(sent))
Neale Ranns32e1c012016-11-22 17:07:28 +0000167
168 self.assertEqual(len(capture), len(sent))
169
170 for i in range(len(capture)):
171 tx = sent[i]
172 rx = capture[i]
173
Neale Ranns32e1c012016-11-22 17:07:28 +0000174 eth = rx[Ether]
175 self.assertEqual(eth.type, 0x86DD)
176
177 tx_ip = tx[IPv6]
178 rx_ip = rx[IPv6]
179
180 # check the MAC address on the RX'd packet is correctly formed
181 self.assertEqual(eth.dst, getmacbyip6(rx_ip.dst))
182
183 self.assertEqual(rx_ip.src, tx_ip.src)
184 self.assertEqual(rx_ip.dst, tx_ip.dst)
185 # IP processing post pop has decremented the TTL
186 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
187
188 def test_ip_mcast(self):
189 """ IP Multicast Replication """
190
Neale Ranns990f6942020-10-20 07:20:17 +0000191 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
192 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
193
Neale Ranns32e1c012016-11-22 17:07:28 +0000194 #
195 # a stream that matches the default route. gets dropped.
196 #
197 self.vapi.cli("clear trace")
Neale Ranns21fb4f72020-10-05 12:26:47 +0000198 self.vapi.cli("packet mac-filter pg0 on")
199 self.vapi.cli("packet mac-filter pg1 on")
200 self.vapi.cli("packet mac-filter pg2 on")
201 self.vapi.cli("packet mac-filter pg4 on")
202 self.vapi.cli("packet mac-filter pg5 on")
203 self.vapi.cli("packet mac-filter pg6 on")
204 self.vapi.cli("packet mac-filter pg7 on")
205
Neale Ranns32e1c012016-11-22 17:07:28 +0000206 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.1")
207 self.pg0.add_stream(tx)
208
209 self.pg_enable_capture(self.pg_interfaces)
210 self.pg_start()
211
212 self.pg0.assert_nothing_captured(
213 remark="IP multicast packets forwarded on default route")
Neale Rannse8f57d52021-10-12 07:49:37 +0000214 count = self.statistics.get_err_counter(
215 "/err/ip4-input/Multicast RPF check failed")
216 self.assertEqual(count, len(tx))
Neale Ranns32e1c012016-11-22 17:07:28 +0000217
218 #
219 # A (*,G).
Neale Ranns37be7362017-02-21 17:30:26 -0800220 # one accepting interface, pg0, 7 forwarding interfaces
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700221 # many forwarding interfaces test the case where the replicate DPO
Neale Ranns37be7362017-02-21 17:30:26 -0800222 # needs to use extra cache lines for the buckets.
Neale Ranns32e1c012016-11-22 17:07:28 +0000223 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800224 route_232_1_1_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000225 self,
226 "0.0.0.0",
227 "232.1.1.1", 32,
Neale Ranns990f6942020-10-20 07:20:17 +0000228 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800229 [VppMRoutePath(self.pg0.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000230 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800231 VppMRoutePath(self.pg1.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000232 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800233 VppMRoutePath(self.pg2.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000234 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800235 VppMRoutePath(self.pg3.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000236 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD),
Neale Ranns37be7362017-02-21 17:30:26 -0800237 VppMRoutePath(self.pg4.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000238 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD),
Neale Ranns37be7362017-02-21 17:30:26 -0800239 VppMRoutePath(self.pg5.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000240 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD),
Neale Ranns37be7362017-02-21 17:30:26 -0800241 VppMRoutePath(self.pg6.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000242 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD),
Neale Ranns37be7362017-02-21 17:30:26 -0800243 VppMRoutePath(self.pg7.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000244 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)])
Neale Ranns32e1c012016-11-22 17:07:28 +0000245 route_232_1_1_1.add_vpp_config()
246
247 #
248 # An (S,G).
249 # one accepting interface, pg0, 2 forwarding interfaces
250 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800251 route_1_1_1_1_232_1_1_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000252 self,
253 "1.1.1.1",
Neale Ranns3e42ebe2018-10-04 08:36:56 -0700254 "232.1.1.1", 27, # any grp-len is ok when src is set
Neale Ranns990f6942020-10-20 07:20:17 +0000255 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800256 [VppMRoutePath(self.pg0.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000257 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800258 VppMRoutePath(self.pg1.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000259 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800260 VppMRoutePath(self.pg2.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000261 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)])
Neale Ranns32e1c012016-11-22 17:07:28 +0000262 route_1_1_1_1_232_1_1_1.add_vpp_config()
263
264 #
Neale Rannse821ab12017-06-01 07:45:05 -0700265 # An (S,G).
266 # one accepting interface, pg0, 2 forwarding interfaces
267 # that use unicast next-hops
268 #
269 route_1_1_1_1_232_1_1_2 = VppIpMRoute(
270 self,
271 "1.1.1.1",
272 "232.1.1.2", 64,
Neale Ranns990f6942020-10-20 07:20:17 +0000273 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Rannse821ab12017-06-01 07:45:05 -0700274 [VppMRoutePath(self.pg0.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000275 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT),
Neale Rannse821ab12017-06-01 07:45:05 -0700276 VppMRoutePath(self.pg1.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000277 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
Neale Rannse821ab12017-06-01 07:45:05 -0700278 nh=self.pg1.remote_ip4),
279 VppMRoutePath(self.pg2.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000280 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
Neale Rannse821ab12017-06-01 07:45:05 -0700281 nh=self.pg2.remote_ip4)])
282 route_1_1_1_1_232_1_1_2.add_vpp_config()
283
284 #
Neale Ranns32e1c012016-11-22 17:07:28 +0000285 # An (*,G/m).
286 # one accepting interface, pg0, 1 forwarding interfaces
287 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800288 route_232 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000289 self,
290 "0.0.0.0",
291 "232.0.0.0", 8,
Neale Ranns990f6942020-10-20 07:20:17 +0000292 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800293 [VppMRoutePath(self.pg0.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000294 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800295 VppMRoutePath(self.pg1.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000296 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)])
Neale Ranns32e1c012016-11-22 17:07:28 +0000297 route_232.add_vpp_config()
298
299 #
300 # a stream that matches the route for (1.1.1.1,232.1.1.1)
Neale Ranns9d676af2017-03-15 01:28:31 -0700301 # small packets
Neale Ranns32e1c012016-11-22 17:07:28 +0000302 #
303 self.vapi.cli("clear trace")
304 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.1")
305 self.pg0.add_stream(tx)
306
307 self.pg_enable_capture(self.pg_interfaces)
308 self.pg_start()
309
Neale Ranns28c142e2018-09-07 09:37:07 -0700310 self.assertEqual(route_1_1_1_1_232_1_1_1.get_stats()['packets'],
311 len(tx))
312
Neale Ranns37be7362017-02-21 17:30:26 -0800313 # We expect replications on Pg1->7
Neale Ranns32e1c012016-11-22 17:07:28 +0000314 self.verify_capture_ip4(self.pg1, tx)
315 self.verify_capture_ip4(self.pg2, tx)
316
317 # no replications on Pg0
318 self.pg0.assert_nothing_captured(
319 remark="IP multicast packets forwarded on PG0")
320 self.pg3.assert_nothing_captured(
321 remark="IP multicast packets forwarded on PG3")
322
323 #
Neale Ranns9d676af2017-03-15 01:28:31 -0700324 # a stream that matches the route for (1.1.1.1,232.1.1.1)
325 # large packets
326 #
327 self.vapi.cli("clear trace")
328 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.1",
329 payload_size=1024)
330 self.pg0.add_stream(tx)
331
332 self.pg_enable_capture(self.pg_interfaces)
333 self.pg_start()
334
335 # We expect replications on Pg1->7
336 self.verify_capture_ip4(self.pg1, tx)
337 self.verify_capture_ip4(self.pg2, tx)
Neale Ranns9d676af2017-03-15 01:28:31 -0700338
Neale Ranns28c142e2018-09-07 09:37:07 -0700339 self.assertEqual(route_1_1_1_1_232_1_1_1.get_stats()['packets'],
340 2*len(tx))
341
Neale Ranns9d676af2017-03-15 01:28:31 -0700342 # no replications on Pg0
343 self.pg0.assert_nothing_captured(
344 remark="IP multicast packets forwarded on PG0")
345 self.pg3.assert_nothing_captured(
346 remark="IP multicast packets forwarded on PG3")
347
348 #
Neale Rannse821ab12017-06-01 07:45:05 -0700349 # a stream to the unicast next-hops
350 #
351 self.vapi.cli("clear trace")
352 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.2")
353 self.pg0.add_stream(tx)
354
355 self.pg_enable_capture(self.pg_interfaces)
356 self.pg_start()
357
358 # We expect replications on Pg1->7
359 self.verify_capture_ip4(self.pg1, tx, dst_mac=self.pg1.remote_mac)
360 self.verify_capture_ip4(self.pg2, tx, dst_mac=self.pg2.remote_mac)
361
362 # no replications on Pg0 nor pg3
363 self.pg0.assert_nothing_captured(
364 remark="IP multicast packets forwarded on PG0")
365 self.pg3.assert_nothing_captured(
366 remark="IP multicast packets forwarded on PG3")
367
368 #
Neale Ranns32e1c012016-11-22 17:07:28 +0000369 # a stream that matches the route for (*,232.0.0.0/8)
370 # Send packets with the 9th bit set so we test the correct clearing
371 # of that bit in the mac rewrite
372 #
373 self.vapi.cli("clear trace")
374 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.255.255.255")
375 self.pg0.add_stream(tx)
376
377 self.pg_enable_capture(self.pg_interfaces)
378 self.pg_start()
379
380 # We expect replications on Pg1 only
381 self.verify_capture_ip4(self.pg1, tx)
Neale Ranns28c142e2018-09-07 09:37:07 -0700382 self.assertEqual(route_232.get_stats()['packets'], len(tx))
Neale Ranns32e1c012016-11-22 17:07:28 +0000383
384 # no replications on Pg0, Pg2 not Pg3
385 self.pg0.assert_nothing_captured(
386 remark="IP multicast packets forwarded on PG0")
387 self.pg2.assert_nothing_captured(
388 remark="IP multicast packets forwarded on PG2")
389 self.pg3.assert_nothing_captured(
390 remark="IP multicast packets forwarded on PG3")
391
392 #
393 # a stream that matches the route for (*,232.1.1.1)
394 #
395 self.vapi.cli("clear trace")
396 tx = self.create_stream_ip4(self.pg0, "1.1.1.2", "232.1.1.1")
397 self.pg0.add_stream(tx)
398
399 self.pg_enable_capture(self.pg_interfaces)
400 self.pg_start()
401
Neale Rannse821ab12017-06-01 07:45:05 -0700402 # We expect replications on Pg1->7
Neale Ranns32e1c012016-11-22 17:07:28 +0000403 self.verify_capture_ip4(self.pg1, tx)
404 self.verify_capture_ip4(self.pg2, tx)
405 self.verify_capture_ip4(self.pg3, tx)
Neale Rannsc2aad532017-05-30 09:53:52 -0700406 self.verify_capture_ip4(self.pg4, tx)
407 self.verify_capture_ip4(self.pg5, tx)
408 self.verify_capture_ip4(self.pg6, tx)
409 self.verify_capture_ip4(self.pg7, tx)
Neale Ranns32e1c012016-11-22 17:07:28 +0000410
Neale Rannse821ab12017-06-01 07:45:05 -0700411 # no replications on Pg0
412 self.pg0.assert_nothing_captured(
413 remark="IP multicast packets forwarded on PG0")
414
Neale Ranns21fb4f72020-10-05 12:26:47 +0000415 self.vapi.cli("packet mac-filter pg0 off")
416 self.vapi.cli("packet mac-filter pg1 off")
417 self.vapi.cli("packet mac-filter pg2 off")
418 self.vapi.cli("packet mac-filter pg4 off")
419 self.vapi.cli("packet mac-filter pg5 off")
420 self.vapi.cli("packet mac-filter pg6 off")
421 self.vapi.cli("packet mac-filter pg7 off")
422
Neale Ranns32e1c012016-11-22 17:07:28 +0000423 def test_ip6_mcast(self):
424 """ IPv6 Multicast Replication """
425
Neale Ranns990f6942020-10-20 07:20:17 +0000426 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
427 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
428
Neale Ranns21fb4f72020-10-05 12:26:47 +0000429 self.vapi.cli("packet mac-filter pg0 on")
430 self.vapi.cli("packet mac-filter pg1 on")
431 self.vapi.cli("packet mac-filter pg2 on")
432 self.vapi.cli("packet mac-filter pg4 on")
433 self.vapi.cli("packet mac-filter pg5 on")
434 self.vapi.cli("packet mac-filter pg6 on")
435 self.vapi.cli("packet mac-filter pg7 on")
Neale Ranns32e1c012016-11-22 17:07:28 +0000436 #
437 # a stream that matches the default route. gets dropped.
438 #
439 self.vapi.cli("clear trace")
440 tx = self.create_stream_ip6(self.pg0, "2001::1", "ff01::1")
441 self.pg0.add_stream(tx)
442
443 self.pg_enable_capture(self.pg_interfaces)
444 self.pg_start()
445
446 self.pg0.assert_nothing_captured(
447 remark="IPv6 multicast packets forwarded on default route")
448
449 #
450 # A (*,G).
451 # one accepting interface, pg0, 3 forwarding interfaces
452 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800453 route_ff01_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000454 self,
455 "::",
456 "ff01::1", 128,
Neale Ranns990f6942020-10-20 07:20:17 +0000457 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800458 [VppMRoutePath(self.pg0.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000459 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT,
Neale Ranns097fa662018-05-01 05:17:55 -0700460 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800461 VppMRoutePath(self.pg1.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000462 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
Neale Ranns097fa662018-05-01 05:17:55 -0700463 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800464 VppMRoutePath(self.pg2.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000465 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
Neale Ranns097fa662018-05-01 05:17:55 -0700466 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800467 VppMRoutePath(self.pg3.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000468 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
Neale Ranns097fa662018-05-01 05:17:55 -0700469 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)])
Neale Ranns32e1c012016-11-22 17:07:28 +0000470 route_ff01_1.add_vpp_config()
471
472 #
473 # An (S,G).
474 # one accepting interface, pg0, 2 forwarding interfaces
475 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800476 route_2001_ff01_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000477 self,
478 "2001::1",
Neale Ranns3e42ebe2018-10-04 08:36:56 -0700479 "ff01::1", 0, # any grp-len is ok when src is set
Neale Ranns990f6942020-10-20 07:20:17 +0000480 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800481 [VppMRoutePath(self.pg0.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000482 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT,
Neale Ranns097fa662018-05-01 05:17:55 -0700483 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800484 VppMRoutePath(self.pg1.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000485 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
Neale Ranns097fa662018-05-01 05:17:55 -0700486 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800487 VppMRoutePath(self.pg2.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000488 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
Neale Ranns097fa662018-05-01 05:17:55 -0700489 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)])
Neale Ranns32e1c012016-11-22 17:07:28 +0000490 route_2001_ff01_1.add_vpp_config()
491
492 #
493 # An (*,G/m).
494 # one accepting interface, pg0, 1 forwarding interface
495 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800496 route_ff01 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000497 self,
498 "::",
499 "ff01::", 16,
Neale Ranns990f6942020-10-20 07:20:17 +0000500 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800501 [VppMRoutePath(self.pg0.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000502 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT,
Neale Ranns097fa662018-05-01 05:17:55 -0700503 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800504 VppMRoutePath(self.pg1.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000505 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
Neale Ranns097fa662018-05-01 05:17:55 -0700506 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)])
Neale Ranns32e1c012016-11-22 17:07:28 +0000507 route_ff01.add_vpp_config()
508
509 #
510 # a stream that matches the route for (*, ff01::/16)
Neale Rannsce111d22018-01-23 08:38:50 -0800511 # sent on the non-accepting interface
512 #
513 self.vapi.cli("clear trace")
514 tx = self.create_stream_ip6(self.pg1, "2002::1", "ff01:2::255")
515 self.send_and_assert_no_replies(self.pg1, tx, "RPF miss")
Neale Rannse8f57d52021-10-12 07:49:37 +0000516 count = self.statistics.get_err_counter(
517 "/err/ip6-input/Multicast RPF check failed")
518 self.assertEqual(count, 2 * len(tx))
Neale Rannsce111d22018-01-23 08:38:50 -0800519
520 #
521 # a stream that matches the route for (*, ff01::/16)
522 # sent on the accepting interface
Neale Ranns32e1c012016-11-22 17:07:28 +0000523 #
524 self.vapi.cli("clear trace")
525 tx = self.create_stream_ip6(self.pg0, "2002::1", "ff01:2::255")
526 self.pg0.add_stream(tx)
527
528 self.pg_enable_capture(self.pg_interfaces)
529 self.pg_start()
530
531 # We expect replications on Pg1
532 self.verify_capture_ip6(self.pg1, tx)
533
534 # no replications on Pg0, Pg3
535 self.pg0.assert_nothing_captured(
536 remark="IP multicast packets forwarded on PG0")
537 self.pg2.assert_nothing_captured(
538 remark="IP multicast packets forwarded on PG2")
539 self.pg3.assert_nothing_captured(
540 remark="IP multicast packets forwarded on PG3")
541
542 #
Neale Rannsc2aad532017-05-30 09:53:52 -0700543 # Bounce the interface and it should still work
544 #
545 self.pg1.admin_down()
546 self.pg0.add_stream(tx)
547 self.pg_enable_capture(self.pg_interfaces)
548 self.pg_start()
549 self.pg1.assert_nothing_captured(
550 remark="IP multicast packets forwarded on down PG1")
551
552 self.pg1.admin_up()
553 self.pg0.add_stream(tx)
554 self.pg_enable_capture(self.pg_interfaces)
555 self.pg_start()
556 self.verify_capture_ip6(self.pg1, tx)
557
558 #
Neale Ranns32e1c012016-11-22 17:07:28 +0000559 # a stream that matches the route for (*,ff01::1)
560 #
561 self.vapi.cli("clear trace")
562 tx = self.create_stream_ip6(self.pg0, "2002::2", "ff01::1")
563 self.pg0.add_stream(tx)
564
565 self.pg_enable_capture(self.pg_interfaces)
566 self.pg_start()
567
568 # We expect replications on Pg1, 2, 3.
569 self.verify_capture_ip6(self.pg1, tx)
570 self.verify_capture_ip6(self.pg2, tx)
571 self.verify_capture_ip6(self.pg3, tx)
572
573 # no replications on Pg0
574 self.pg0.assert_nothing_captured(
575 remark="IPv6 multicast packets forwarded on PG0")
576
577 #
578 # a stream that matches the route for (2001::1, ff00::1)
579 #
580 self.vapi.cli("clear trace")
581 tx = self.create_stream_ip6(self.pg0, "2001::1", "ff01::1")
582 self.pg0.add_stream(tx)
583
584 self.pg_enable_capture(self.pg_interfaces)
585 self.pg_start()
586
587 # We expect replications on Pg1, 2,
588 self.verify_capture_ip6(self.pg1, tx)
589 self.verify_capture_ip6(self.pg2, tx)
590
591 # no replications on Pg0, Pg3
592 self.pg0.assert_nothing_captured(
593 remark="IP multicast packets forwarded on PG0")
594 self.pg3.assert_nothing_captured(
595 remark="IP multicast packets forwarded on PG3")
596
Neale Ranns21fb4f72020-10-05 12:26:47 +0000597 self.vapi.cli("packet mac-filter pg0 off")
598 self.vapi.cli("packet mac-filter pg1 off")
599 self.vapi.cli("packet mac-filter pg2 off")
600 self.vapi.cli("packet mac-filter pg4 off")
601 self.vapi.cli("packet mac-filter pg5 off")
602 self.vapi.cli("packet mac-filter pg6 off")
603 self.vapi.cli("packet mac-filter pg7 off")
604
Neale Ranns32e1c012016-11-22 17:07:28 +0000605 def _mcast_connected_send_stream(self, dst_ip):
606 self.vapi.cli("clear trace")
607 tx = self.create_stream_ip4(self.pg0,
608 self.pg0.remote_ip4,
609 dst_ip)
610 self.pg0.add_stream(tx)
611
612 self.pg_enable_capture(self.pg_interfaces)
613 self.pg_start()
614
615 # We expect replications on Pg1.
616 self.verify_capture_ip4(self.pg1, tx)
617
618 return tx
619
620 def test_ip_mcast_connected(self):
621 """ IP Multicast Connected Source check """
622
Neale Ranns990f6942020-10-20 07:20:17 +0000623 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
624 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
625
Neale Ranns32e1c012016-11-22 17:07:28 +0000626 #
627 # A (*,G).
628 # one accepting interface, pg0, 1 forwarding interfaces
629 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800630 route_232_1_1_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000631 self,
632 "0.0.0.0",
633 "232.1.1.1", 32,
Neale Ranns990f6942020-10-20 07:20:17 +0000634 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800635 [VppMRoutePath(self.pg0.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000636 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800637 VppMRoutePath(self.pg1.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000638 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)])
Neale Ranns32e1c012016-11-22 17:07:28 +0000639
640 route_232_1_1_1.add_vpp_config()
641 route_232_1_1_1.update_entry_flags(
Neale Ranns990f6942020-10-20 07:20:17 +0000642 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_CONNECTED)
Neale Ranns32e1c012016-11-22 17:07:28 +0000643
644 #
645 # Now the (*,G) is present, send from connected source
646 #
647 tx = self._mcast_connected_send_stream("232.1.1.1")
648
649 #
650 # Constrct a representation of the signal we expect on pg0
651 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800652 signal_232_1_1_1_itf_0 = VppMFibSignal(self,
653 route_232_1_1_1,
654 self.pg0.sw_if_index,
655 tx[0])
Neale Ranns32e1c012016-11-22 17:07:28 +0000656
657 #
658 # read the only expected signal
659 #
660 signals = self.vapi.mfib_signal_dump()
661
662 self.assertEqual(1, len(signals))
663
664 signal_232_1_1_1_itf_0.compare(signals[0])
665
666 #
667 # reading the signal allows for the generation of another
668 # so send more packets and expect the next signal
669 #
670 tx = self._mcast_connected_send_stream("232.1.1.1")
671
672 signals = self.vapi.mfib_signal_dump()
673 self.assertEqual(1, len(signals))
674 signal_232_1_1_1_itf_0.compare(signals[0])
675
676 #
677 # A Second entry with connected check
678 # one accepting interface, pg0, 1 forwarding interfaces
679 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800680 route_232_1_1_2 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000681 self,
682 "0.0.0.0",
683 "232.1.1.2", 32,
Neale Ranns990f6942020-10-20 07:20:17 +0000684 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800685 [VppMRoutePath(self.pg0.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000686 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800687 VppMRoutePath(self.pg1.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000688 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)])
Neale Ranns32e1c012016-11-22 17:07:28 +0000689
690 route_232_1_1_2.add_vpp_config()
691 route_232_1_1_2.update_entry_flags(
Neale Ranns990f6942020-10-20 07:20:17 +0000692 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_CONNECTED)
Neale Ranns32e1c012016-11-22 17:07:28 +0000693
694 #
695 # Send traffic to both entries. One read should net us two signals
696 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800697 signal_232_1_1_2_itf_0 = VppMFibSignal(self,
698 route_232_1_1_2,
699 self.pg0.sw_if_index,
700 tx[0])
Neale Ranns32e1c012016-11-22 17:07:28 +0000701 tx = self._mcast_connected_send_stream("232.1.1.1")
702 tx2 = self._mcast_connected_send_stream("232.1.1.2")
703
704 #
705 # read the only expected signal
706 #
707 signals = self.vapi.mfib_signal_dump()
708
709 self.assertEqual(2, len(signals))
710
711 signal_232_1_1_1_itf_0.compare(signals[1])
712 signal_232_1_1_2_itf_0.compare(signals[0])
713
Neale Rannsd792d9c2017-10-21 10:53:20 -0700714 route_232_1_1_1.update_entry_flags(
Neale Ranns990f6942020-10-20 07:20:17 +0000715 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE)
Neale Rannsd792d9c2017-10-21 10:53:20 -0700716 route_232_1_1_2.update_entry_flags(
Neale Ranns990f6942020-10-20 07:20:17 +0000717 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE)
Neale Ranns32e1c012016-11-22 17:07:28 +0000718
719 def test_ip_mcast_signal(self):
720 """ IP Multicast Signal """
721
Neale Ranns990f6942020-10-20 07:20:17 +0000722 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
723 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
724
Neale Ranns32e1c012016-11-22 17:07:28 +0000725 #
726 # A (*,G).
727 # one accepting interface, pg0, 1 forwarding interfaces
728 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800729 route_232_1_1_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000730 self,
731 "0.0.0.0",
732 "232.1.1.1", 32,
Neale Ranns990f6942020-10-20 07:20:17 +0000733 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800734 [VppMRoutePath(self.pg0.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000735 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800736 VppMRoutePath(self.pg1.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000737 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)])
Neale Ranns32e1c012016-11-22 17:07:28 +0000738
739 route_232_1_1_1.add_vpp_config()
Neale Ranns097fa662018-05-01 05:17:55 -0700740
Neale Ranns32e1c012016-11-22 17:07:28 +0000741 route_232_1_1_1.update_entry_flags(
Neale Ranns990f6942020-10-20 07:20:17 +0000742 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_SIGNAL)
Neale Ranns32e1c012016-11-22 17:07:28 +0000743
744 #
745 # Now the (*,G) is present, send from connected source
746 #
747 tx = self._mcast_connected_send_stream("232.1.1.1")
748
749 #
750 # Constrct a representation of the signal we expect on pg0
751 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800752 signal_232_1_1_1_itf_0 = VppMFibSignal(self,
753 route_232_1_1_1,
754 self.pg0.sw_if_index,
755 tx[0])
Neale Ranns32e1c012016-11-22 17:07:28 +0000756
757 #
758 # read the only expected signal
759 #
760 signals = self.vapi.mfib_signal_dump()
761
762 self.assertEqual(1, len(signals))
763
764 signal_232_1_1_1_itf_0.compare(signals[0])
765
766 #
767 # reading the signal allows for the generation of another
768 # so send more packets and expect the next signal
769 #
770 tx = self._mcast_connected_send_stream("232.1.1.1")
771
772 signals = self.vapi.mfib_signal_dump()
773 self.assertEqual(1, len(signals))
774 signal_232_1_1_1_itf_0.compare(signals[0])
775
776 #
777 # Set the negate-signal on the accepting interval - the signals
778 # should stop
779 #
780 route_232_1_1_1.update_path_flags(
781 self.pg0.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000782 (MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT |
783 MRouteItfFlags.MFIB_API_ITF_FLAG_NEGATE_SIGNAL))
Neale Ranns32e1c012016-11-22 17:07:28 +0000784
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800785 self.vapi.cli("clear trace")
Neale Ranns32e1c012016-11-22 17:07:28 +0000786 tx = self._mcast_connected_send_stream("232.1.1.1")
787
788 signals = self.vapi.mfib_signal_dump()
789 self.assertEqual(0, len(signals))
790
791 #
792 # Clear the SIGNAL flag on the entry and the signals should
793 # come back since the interface is still NEGATE-SIGNAL
794 #
795 route_232_1_1_1.update_entry_flags(
Neale Ranns990f6942020-10-20 07:20:17 +0000796 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE)
Neale Ranns32e1c012016-11-22 17:07:28 +0000797
798 tx = self._mcast_connected_send_stream("232.1.1.1")
799
800 signals = self.vapi.mfib_signal_dump()
801 self.assertEqual(1, len(signals))
802 signal_232_1_1_1_itf_0.compare(signals[0])
803
804 #
805 # Lastly remove the NEGATE-SIGNAL from the interface and the
806 # signals should stop
807 #
Neale Ranns990f6942020-10-20 07:20:17 +0000808 route_232_1_1_1.update_path_flags(
809 self.pg0.sw_if_index,
810 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT)
Neale Ranns32e1c012016-11-22 17:07:28 +0000811
812 tx = self._mcast_connected_send_stream("232.1.1.1")
813 signals = self.vapi.mfib_signal_dump()
814 self.assertEqual(0, len(signals))
815
Neale Ranns15002542017-09-10 04:39:11 -0700816 def test_ip_mcast_vrf(self):
817 """ IP Multicast Replication in non-default table"""
818
Neale Ranns990f6942020-10-20 07:20:17 +0000819 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
820 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
821
Neale Ranns15002542017-09-10 04:39:11 -0700822 #
823 # An (S,G).
824 # one accepting interface, pg0, 2 forwarding interfaces
825 #
826 route_1_1_1_1_232_1_1_1 = VppIpMRoute(
827 self,
828 "1.1.1.1",
829 "232.1.1.1", 64,
Neale Ranns990f6942020-10-20 07:20:17 +0000830 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns15002542017-09-10 04:39:11 -0700831 [VppMRoutePath(self.pg8.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000832 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT),
Neale Ranns15002542017-09-10 04:39:11 -0700833 VppMRoutePath(self.pg1.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000834 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD),
Neale Ranns15002542017-09-10 04:39:11 -0700835 VppMRoutePath(self.pg2.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000836 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)],
Neale Ranns15002542017-09-10 04:39:11 -0700837 table_id=10)
838 route_1_1_1_1_232_1_1_1.add_vpp_config()
839
840 #
841 # a stream that matches the route for (1.1.1.1,232.1.1.1)
842 # small packets
843 #
844 self.vapi.cli("clear trace")
845 tx = self.create_stream_ip4(self.pg8, "1.1.1.1", "232.1.1.1")
846 self.pg8.add_stream(tx)
847
848 self.pg_enable_capture(self.pg_interfaces)
849 self.pg_start()
850
851 # We expect replications on Pg1 & 2
852 self.verify_capture_ip4(self.pg1, tx)
853 self.verify_capture_ip4(self.pg2, tx)
854
Neale Ranns13721782021-05-13 15:28:27 +0000855 #
856 # An (S,G). for for-us
857 #
858 route_0_0_0_0_224_0_0_5 = VppIpMRoute(
859 self,
860 "0.0.0.0",
861 "224.0.0.5", 32,
862 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
863 [VppMRoutePath(self.pg8.sw_if_index,
864 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT),
865 VppMRoutePath(0xffffffff,
866 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
867 type=FibPathType.FIB_PATH_TYPE_LOCAL)],
868 table_id=10)
869 route_0_0_0_0_224_0_0_5.add_vpp_config()
870
871 #
872 # a stream that matches the route for (0.0.0.0, 224.0.0.5)
873 # small packets
874 #
875 self.vapi.cli("clear trace")
876 self.pg8.resolve_arp()
877
878 #
879 # send a ping to mcast address from peer on pg8
880 # expect a response
881 #
882 icmp_id = 0xb
883 icmp_seq = 5
884 icmp_load = b'\x0a' * 18
885 tx = (Ether(dst=getmacbyip("224.0.0.5"), src=self.pg8.remote_mac) /
886 IP(src=self.pg8.remote_ip4, dst="224.0.0.5") /
887 ICMP(id=icmp_id, seq=icmp_seq) /
888 Raw(load=icmp_load)) * 2
889
890 self.send_and_expect(self.pg8, tx, self.pg8)
891
Neale Rannsadb17a82019-08-04 02:41:57 -0700892 def test_ip_mcast_gre(self):
893 """ IP Multicast Replication over GRE"""
894
Neale Ranns990f6942020-10-20 07:20:17 +0000895 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
896 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
897
Neale Rannsadb17a82019-08-04 02:41:57 -0700898 gre_if_1 = VppGreInterface(
899 self,
900 self.pg1.local_ip4,
901 self.pg1.remote_ip4).add_vpp_config()
902 gre_if_2 = VppGreInterface(
903 self,
904 self.pg2.local_ip4,
905 self.pg2.remote_ip4).add_vpp_config()
906 gre_if_3 = VppGreInterface(
907 self,
908 self.pg3.local_ip4,
909 self.pg3.remote_ip4).add_vpp_config()
910
911 gre_if_1.admin_up()
912 gre_if_1.config_ip4()
913 gre_if_2.admin_up()
914 gre_if_2.config_ip4()
915 gre_if_3.admin_up()
916 gre_if_3.config_ip4()
917
918 #
919 # An (S,G).
920 # one accepting interface, pg0, 2 forwarding interfaces
921 #
922 route_1_1_1_1_232_1_1_1 = VppIpMRoute(
923 self,
924 "1.1.1.1",
925 "232.2.2.2", 64,
Neale Ranns990f6942020-10-20 07:20:17 +0000926 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Rannsadb17a82019-08-04 02:41:57 -0700927 [VppMRoutePath(gre_if_1.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000928 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT),
Neale Rannsadb17a82019-08-04 02:41:57 -0700929 VppMRoutePath(gre_if_2.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000930 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD),
Neale Rannsadb17a82019-08-04 02:41:57 -0700931 VppMRoutePath(gre_if_3.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000932 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)])
Neale Rannsadb17a82019-08-04 02:41:57 -0700933 route_1_1_1_1_232_1_1_1.add_vpp_config()
934
935 #
936 # a stream that matches the route for (1.1.1.1,232.2.2.2)
937 # small packets
938 #
939 tx = (Ether(dst=self.pg1.local_mac,
940 src=self.pg1.remote_mac) /
941 IP(src=self.pg1.remote_ip4,
942 dst=self.pg1.local_ip4) /
943 GRE() /
944 IP(src="1.1.1.1", dst="232.2.2.2") /
945 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +0100946 Raw(b'\a5' * 64)) * 63
Neale Rannsadb17a82019-08-04 02:41:57 -0700947
948 self.vapi.cli("clear trace")
949 self.pg1.add_stream(tx)
950
951 self.pg_enable_capture(self.pg_interfaces)
952 self.pg_start()
953
954 # We expect replications on Pg2 & 3
955 # check the encap headers are as expected based on the egress tunnel
956 rxs = self.pg2.get_capture(len(tx))
957 for rx in rxs:
958 self.assertEqual(rx[IP].src, gre_if_2.t_src)
959 self.assertEqual(rx[IP].dst, gre_if_2.t_dst)
960 self.assert_packet_checksums_valid(rx)
961
962 rxs = self.pg3.get_capture(len(tx))
963 for rx in rxs:
964 self.assertEqual(rx[IP].src, gre_if_3.t_src)
965 self.assertEqual(rx[IP].dst, gre_if_3.t_dst)
966 self.assert_packet_checksums_valid(rx)
967
Neale Ranns7d8a9562020-11-20 14:32:56 +0000968 def test_ip6_mcast_gre(self):
969 """ IP6 Multicast Replication over GRE"""
970
971 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
972 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
973
974 gre_if_1 = VppGreInterface(
975 self,
976 self.pg1.local_ip4,
977 self.pg1.remote_ip4).add_vpp_config()
978 gre_if_2 = VppGreInterface(
979 self,
980 self.pg2.local_ip4,
981 self.pg2.remote_ip4).add_vpp_config()
982 gre_if_3 = VppGreInterface(
983 self,
984 self.pg3.local_ip4,
985 self.pg3.remote_ip4).add_vpp_config()
986
987 gre_if_1.admin_up()
988 gre_if_1.config_ip6()
989 gre_if_2.admin_up()
990 gre_if_2.config_ip6()
991 gre_if_3.admin_up()
992 gre_if_3.config_ip6()
993
994 #
995 # An (S,G).
996 # one accepting interface, pg0, 2 forwarding interfaces
997 #
998 route_1_1_FF_1 = VppIpMRoute(
999 self,
1000 "1::1",
1001 "FF00::1", 256,
1002 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
1003 [VppMRoutePath(gre_if_1.sw_if_index,
1004 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT),
1005 VppMRoutePath(gre_if_2.sw_if_index,
1006 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD),
1007 VppMRoutePath(gre_if_3.sw_if_index,
1008 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)])
1009 route_1_1_FF_1.add_vpp_config()
1010
1011 #
1012 # a stream that matches the route for (1::1, FF::1)
1013 # small packets
1014 #
1015 tx = (Ether(dst=self.pg1.local_mac,
1016 src=self.pg1.remote_mac) /
1017 IP(src=self.pg1.remote_ip4,
1018 dst=self.pg1.local_ip4) /
1019 GRE() /
1020 IPv6(src="1::1", dst="FF00::1") /
1021 UDP(sport=1234, dport=1234) /
1022 Raw(b'\a5' * 64)) * 63
1023
1024 self.vapi.cli("clear trace")
1025 self.pg1.add_stream(tx)
1026
1027 self.pg_enable_capture(self.pg_interfaces)
1028 self.pg_start()
1029
1030 # We expect replications on Pg2 & 3
1031 # check the encap headers are as expected based on the egress tunnel
1032 rxs = self.pg2.get_capture(len(tx))
1033 for rx in rxs:
1034 self.assertEqual(rx[IP].src, gre_if_2.t_src)
1035 self.assertEqual(rx[IP].dst, gre_if_2.t_dst)
1036 self.assert_packet_checksums_valid(rx)
1037
1038 rxs = self.pg3.get_capture(len(tx))
1039 for rx in rxs:
1040 self.assertEqual(rx[IP].src, gre_if_3.t_src)
1041 self.assertEqual(rx[IP].dst, gre_if_3.t_dst)
1042 self.assert_packet_checksums_valid(rx)
1043
Neale Ranns15002542017-09-10 04:39:11 -07001044 def test_ip6_mcast_vrf(self):
1045 """ IPv6 Multicast Replication in non-default table"""
1046
Neale Ranns990f6942020-10-20 07:20:17 +00001047 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1048 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1049
Neale Ranns15002542017-09-10 04:39:11 -07001050 #
1051 # An (S,G).
1052 # one accepting interface, pg0, 2 forwarding interfaces
1053 #
1054 route_2001_ff01_1 = VppIpMRoute(
1055 self,
1056 "2001::1",
1057 "ff01::1", 256,
Neale Ranns990f6942020-10-20 07:20:17 +00001058 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns15002542017-09-10 04:39:11 -07001059 [VppMRoutePath(self.pg8.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +00001060 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT,
Neale Ranns097fa662018-05-01 05:17:55 -07001061 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6),
Neale Ranns15002542017-09-10 04:39:11 -07001062 VppMRoutePath(self.pg1.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +00001063 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
Neale Ranns097fa662018-05-01 05:17:55 -07001064 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6),
Neale Ranns15002542017-09-10 04:39:11 -07001065 VppMRoutePath(self.pg2.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +00001066 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
Neale Ranns097fa662018-05-01 05:17:55 -07001067 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)],
1068 table_id=10)
Neale Ranns15002542017-09-10 04:39:11 -07001069 route_2001_ff01_1.add_vpp_config()
1070
1071 #
1072 # a stream that matches the route for (2001::1, ff00::1)
1073 #
1074 self.vapi.cli("clear trace")
1075 tx = self.create_stream_ip6(self.pg8, "2001::1", "ff01::1")
1076 self.pg8.add_stream(tx)
1077
1078 self.pg_enable_capture(self.pg_interfaces)
1079 self.pg_start()
1080
1081 # We expect replications on Pg1, 2,
1082 self.verify_capture_ip6(self.pg1, tx)
1083 self.verify_capture_ip6(self.pg2, tx)
Neale Ranns32e1c012016-11-22 17:07:28 +00001084
Neale Rannscf3561b2017-12-13 01:44:25 -08001085 def test_bidir(self):
1086 """ IP Multicast Bi-directional """
1087
Neale Ranns990f6942020-10-20 07:20:17 +00001088 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1089 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1090
Neale Rannscf3561b2017-12-13 01:44:25 -08001091 #
1092 # A (*,G). The set of accepting interfaces matching the forwarding
1093 #
1094 route_232_1_1_1 = VppIpMRoute(
1095 self,
1096 "0.0.0.0",
1097 "232.1.1.1", 32,
Neale Ranns990f6942020-10-20 07:20:17 +00001098 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Rannscf3561b2017-12-13 01:44:25 -08001099 [VppMRoutePath(self.pg0.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +00001100 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT |
1101 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD),
Neale Rannscf3561b2017-12-13 01:44:25 -08001102 VppMRoutePath(self.pg1.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +00001103 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT |
1104 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD),
Neale Rannscf3561b2017-12-13 01:44:25 -08001105 VppMRoutePath(self.pg2.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +00001106 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT |
1107 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD),
Neale Rannscf3561b2017-12-13 01:44:25 -08001108 VppMRoutePath(self.pg3.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +00001109 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT |
1110 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)])
Neale Rannscf3561b2017-12-13 01:44:25 -08001111 route_232_1_1_1.add_vpp_config()
1112
1113 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.1")
1114 self.pg0.add_stream(tx)
1115
1116 self.pg_enable_capture(self.pg_interfaces)
1117 self.pg_start()
1118
1119 # We expect replications on Pg1, 2, 3, but not on pg0
1120 self.verify_capture_ip4(self.pg1, tx)
1121 self.verify_capture_ip4(self.pg2, tx)
1122 self.verify_capture_ip4(self.pg3, tx)
1123 self.pg0.assert_nothing_captured(
1124 remark="IP multicast packets forwarded on PG0")
1125
1126
Neale Ranns32e1c012016-11-22 17:07:28 +00001127if __name__ == '__main__':
1128 unittest.main(testRunner=VppTestRunner)