blob: 2799218125cdc01e915d3f99959d82e539468102 [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 Ranns990f6942020-10-20 07:20:17 +00009 VppIpTable, FibPathProto
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
Klement Sekerab9ef2732018-06-24 22:49:33 +020015from scapy.layers.inet import IP, UDP, getmacbyip
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")
214
215 #
216 # A (*,G).
Neale Ranns37be7362017-02-21 17:30:26 -0800217 # one accepting interface, pg0, 7 forwarding interfaces
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700218 # many forwarding interfaces test the case where the replicate DPO
Neale Ranns37be7362017-02-21 17:30:26 -0800219 # needs to use extra cache lines for the buckets.
Neale Ranns32e1c012016-11-22 17:07:28 +0000220 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800221 route_232_1_1_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000222 self,
223 "0.0.0.0",
224 "232.1.1.1", 32,
Neale Ranns990f6942020-10-20 07:20:17 +0000225 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800226 [VppMRoutePath(self.pg0.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000227 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800228 VppMRoutePath(self.pg1.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000229 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800230 VppMRoutePath(self.pg2.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000231 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800232 VppMRoutePath(self.pg3.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000233 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD),
Neale Ranns37be7362017-02-21 17:30:26 -0800234 VppMRoutePath(self.pg4.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000235 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD),
Neale Ranns37be7362017-02-21 17:30:26 -0800236 VppMRoutePath(self.pg5.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000237 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD),
Neale Ranns37be7362017-02-21 17:30:26 -0800238 VppMRoutePath(self.pg6.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000239 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD),
Neale Ranns37be7362017-02-21 17:30:26 -0800240 VppMRoutePath(self.pg7.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000241 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)])
Neale Ranns32e1c012016-11-22 17:07:28 +0000242 route_232_1_1_1.add_vpp_config()
243
244 #
245 # An (S,G).
246 # one accepting interface, pg0, 2 forwarding interfaces
247 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800248 route_1_1_1_1_232_1_1_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000249 self,
250 "1.1.1.1",
Neale Ranns3e42ebe2018-10-04 08:36:56 -0700251 "232.1.1.1", 27, # any grp-len is ok when src is set
Neale Ranns990f6942020-10-20 07:20:17 +0000252 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800253 [VppMRoutePath(self.pg0.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000254 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800255 VppMRoutePath(self.pg1.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000256 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800257 VppMRoutePath(self.pg2.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000258 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)])
Neale Ranns32e1c012016-11-22 17:07:28 +0000259 route_1_1_1_1_232_1_1_1.add_vpp_config()
260
261 #
Neale Rannse821ab12017-06-01 07:45:05 -0700262 # An (S,G).
263 # one accepting interface, pg0, 2 forwarding interfaces
264 # that use unicast next-hops
265 #
266 route_1_1_1_1_232_1_1_2 = VppIpMRoute(
267 self,
268 "1.1.1.1",
269 "232.1.1.2", 64,
Neale Ranns990f6942020-10-20 07:20:17 +0000270 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Rannse821ab12017-06-01 07:45:05 -0700271 [VppMRoutePath(self.pg0.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000272 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT),
Neale Rannse821ab12017-06-01 07:45:05 -0700273 VppMRoutePath(self.pg1.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000274 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
Neale Rannse821ab12017-06-01 07:45:05 -0700275 nh=self.pg1.remote_ip4),
276 VppMRoutePath(self.pg2.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.pg2.remote_ip4)])
279 route_1_1_1_1_232_1_1_2.add_vpp_config()
280
281 #
Neale Ranns32e1c012016-11-22 17:07:28 +0000282 # An (*,G/m).
283 # one accepting interface, pg0, 1 forwarding interfaces
284 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800285 route_232 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000286 self,
287 "0.0.0.0",
288 "232.0.0.0", 8,
Neale Ranns990f6942020-10-20 07:20:17 +0000289 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800290 [VppMRoutePath(self.pg0.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000291 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800292 VppMRoutePath(self.pg1.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000293 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)])
Neale Ranns32e1c012016-11-22 17:07:28 +0000294 route_232.add_vpp_config()
295
296 #
297 # a stream that matches the route for (1.1.1.1,232.1.1.1)
Neale Ranns9d676af2017-03-15 01:28:31 -0700298 # small packets
Neale Ranns32e1c012016-11-22 17:07:28 +0000299 #
300 self.vapi.cli("clear trace")
301 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.1")
302 self.pg0.add_stream(tx)
303
304 self.pg_enable_capture(self.pg_interfaces)
305 self.pg_start()
306
Neale Ranns28c142e2018-09-07 09:37:07 -0700307 self.assertEqual(route_1_1_1_1_232_1_1_1.get_stats()['packets'],
308 len(tx))
309
Neale Ranns37be7362017-02-21 17:30:26 -0800310 # We expect replications on Pg1->7
Neale Ranns32e1c012016-11-22 17:07:28 +0000311 self.verify_capture_ip4(self.pg1, tx)
312 self.verify_capture_ip4(self.pg2, tx)
313
314 # no replications on Pg0
315 self.pg0.assert_nothing_captured(
316 remark="IP multicast packets forwarded on PG0")
317 self.pg3.assert_nothing_captured(
318 remark="IP multicast packets forwarded on PG3")
319
320 #
Neale Ranns9d676af2017-03-15 01:28:31 -0700321 # a stream that matches the route for (1.1.1.1,232.1.1.1)
322 # large packets
323 #
324 self.vapi.cli("clear trace")
325 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.1",
326 payload_size=1024)
327 self.pg0.add_stream(tx)
328
329 self.pg_enable_capture(self.pg_interfaces)
330 self.pg_start()
331
332 # We expect replications on Pg1->7
333 self.verify_capture_ip4(self.pg1, tx)
334 self.verify_capture_ip4(self.pg2, tx)
Neale Ranns9d676af2017-03-15 01:28:31 -0700335
Neale Ranns28c142e2018-09-07 09:37:07 -0700336 self.assertEqual(route_1_1_1_1_232_1_1_1.get_stats()['packets'],
337 2*len(tx))
338
Neale Ranns9d676af2017-03-15 01:28:31 -0700339 # no replications on Pg0
340 self.pg0.assert_nothing_captured(
341 remark="IP multicast packets forwarded on PG0")
342 self.pg3.assert_nothing_captured(
343 remark="IP multicast packets forwarded on PG3")
344
345 #
Neale Rannse821ab12017-06-01 07:45:05 -0700346 # a stream to the unicast next-hops
347 #
348 self.vapi.cli("clear trace")
349 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.2")
350 self.pg0.add_stream(tx)
351
352 self.pg_enable_capture(self.pg_interfaces)
353 self.pg_start()
354
355 # We expect replications on Pg1->7
356 self.verify_capture_ip4(self.pg1, tx, dst_mac=self.pg1.remote_mac)
357 self.verify_capture_ip4(self.pg2, tx, dst_mac=self.pg2.remote_mac)
358
359 # no replications on Pg0 nor pg3
360 self.pg0.assert_nothing_captured(
361 remark="IP multicast packets forwarded on PG0")
362 self.pg3.assert_nothing_captured(
363 remark="IP multicast packets forwarded on PG3")
364
365 #
Neale Ranns32e1c012016-11-22 17:07:28 +0000366 # a stream that matches the route for (*,232.0.0.0/8)
367 # Send packets with the 9th bit set so we test the correct clearing
368 # of that bit in the mac rewrite
369 #
370 self.vapi.cli("clear trace")
371 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.255.255.255")
372 self.pg0.add_stream(tx)
373
374 self.pg_enable_capture(self.pg_interfaces)
375 self.pg_start()
376
377 # We expect replications on Pg1 only
378 self.verify_capture_ip4(self.pg1, tx)
Neale Ranns28c142e2018-09-07 09:37:07 -0700379 self.assertEqual(route_232.get_stats()['packets'], len(tx))
Neale Ranns32e1c012016-11-22 17:07:28 +0000380
381 # no replications on Pg0, Pg2 not Pg3
382 self.pg0.assert_nothing_captured(
383 remark="IP multicast packets forwarded on PG0")
384 self.pg2.assert_nothing_captured(
385 remark="IP multicast packets forwarded on PG2")
386 self.pg3.assert_nothing_captured(
387 remark="IP multicast packets forwarded on PG3")
388
389 #
390 # a stream that matches the route for (*,232.1.1.1)
391 #
392 self.vapi.cli("clear trace")
393 tx = self.create_stream_ip4(self.pg0, "1.1.1.2", "232.1.1.1")
394 self.pg0.add_stream(tx)
395
396 self.pg_enable_capture(self.pg_interfaces)
397 self.pg_start()
398
Neale Rannse821ab12017-06-01 07:45:05 -0700399 # We expect replications on Pg1->7
Neale Ranns32e1c012016-11-22 17:07:28 +0000400 self.verify_capture_ip4(self.pg1, tx)
401 self.verify_capture_ip4(self.pg2, tx)
402 self.verify_capture_ip4(self.pg3, tx)
Neale Rannsc2aad532017-05-30 09:53:52 -0700403 self.verify_capture_ip4(self.pg4, tx)
404 self.verify_capture_ip4(self.pg5, tx)
405 self.verify_capture_ip4(self.pg6, tx)
406 self.verify_capture_ip4(self.pg7, tx)
Neale Ranns32e1c012016-11-22 17:07:28 +0000407
Neale Rannse821ab12017-06-01 07:45:05 -0700408 # no replications on Pg0
409 self.pg0.assert_nothing_captured(
410 remark="IP multicast packets forwarded on PG0")
411
Neale Ranns21fb4f72020-10-05 12:26:47 +0000412 self.vapi.cli("packet mac-filter pg0 off")
413 self.vapi.cli("packet mac-filter pg1 off")
414 self.vapi.cli("packet mac-filter pg2 off")
415 self.vapi.cli("packet mac-filter pg4 off")
416 self.vapi.cli("packet mac-filter pg5 off")
417 self.vapi.cli("packet mac-filter pg6 off")
418 self.vapi.cli("packet mac-filter pg7 off")
419
Neale Ranns32e1c012016-11-22 17:07:28 +0000420 def test_ip6_mcast(self):
421 """ IPv6 Multicast Replication """
422
Neale Ranns990f6942020-10-20 07:20:17 +0000423 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
424 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
425
Neale Ranns21fb4f72020-10-05 12:26:47 +0000426 self.vapi.cli("packet mac-filter pg0 on")
427 self.vapi.cli("packet mac-filter pg1 on")
428 self.vapi.cli("packet mac-filter pg2 on")
429 self.vapi.cli("packet mac-filter pg4 on")
430 self.vapi.cli("packet mac-filter pg5 on")
431 self.vapi.cli("packet mac-filter pg6 on")
432 self.vapi.cli("packet mac-filter pg7 on")
Neale Ranns32e1c012016-11-22 17:07:28 +0000433 #
434 # a stream that matches the default route. gets dropped.
435 #
436 self.vapi.cli("clear trace")
437 tx = self.create_stream_ip6(self.pg0, "2001::1", "ff01::1")
438 self.pg0.add_stream(tx)
439
440 self.pg_enable_capture(self.pg_interfaces)
441 self.pg_start()
442
443 self.pg0.assert_nothing_captured(
444 remark="IPv6 multicast packets forwarded on default route")
445
446 #
447 # A (*,G).
448 # one accepting interface, pg0, 3 forwarding interfaces
449 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800450 route_ff01_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000451 self,
452 "::",
453 "ff01::1", 128,
Neale Ranns990f6942020-10-20 07:20:17 +0000454 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800455 [VppMRoutePath(self.pg0.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000456 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT,
Neale Ranns097fa662018-05-01 05:17:55 -0700457 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800458 VppMRoutePath(self.pg1.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000459 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
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.pg2.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.pg3.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 Ranns32e1c012016-11-22 17:07:28 +0000467 route_ff01_1.add_vpp_config()
468
469 #
470 # An (S,G).
471 # one accepting interface, pg0, 2 forwarding interfaces
472 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800473 route_2001_ff01_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000474 self,
475 "2001::1",
Neale Ranns3e42ebe2018-10-04 08:36:56 -0700476 "ff01::1", 0, # any grp-len is ok when src is set
Neale Ranns990f6942020-10-20 07:20:17 +0000477 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800478 [VppMRoutePath(self.pg0.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000479 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT,
Neale Ranns097fa662018-05-01 05:17:55 -0700480 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800481 VppMRoutePath(self.pg1.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000482 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
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.pg2.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 Ranns32e1c012016-11-22 17:07:28 +0000487 route_2001_ff01_1.add_vpp_config()
488
489 #
490 # An (*,G/m).
491 # one accepting interface, pg0, 1 forwarding interface
492 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800493 route_ff01 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000494 self,
495 "::",
496 "ff01::", 16,
Neale Ranns990f6942020-10-20 07:20:17 +0000497 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800498 [VppMRoutePath(self.pg0.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000499 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT,
Neale Ranns097fa662018-05-01 05:17:55 -0700500 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800501 VppMRoutePath(self.pg1.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000502 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
Neale Ranns097fa662018-05-01 05:17:55 -0700503 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)])
Neale Ranns32e1c012016-11-22 17:07:28 +0000504 route_ff01.add_vpp_config()
505
506 #
507 # a stream that matches the route for (*, ff01::/16)
Neale Rannsce111d22018-01-23 08:38:50 -0800508 # sent on the non-accepting interface
509 #
510 self.vapi.cli("clear trace")
511 tx = self.create_stream_ip6(self.pg1, "2002::1", "ff01:2::255")
512 self.send_and_assert_no_replies(self.pg1, tx, "RPF miss")
513
514 #
515 # a stream that matches the route for (*, ff01::/16)
516 # sent on the accepting interface
Neale Ranns32e1c012016-11-22 17:07:28 +0000517 #
518 self.vapi.cli("clear trace")
519 tx = self.create_stream_ip6(self.pg0, "2002::1", "ff01:2::255")
520 self.pg0.add_stream(tx)
521
522 self.pg_enable_capture(self.pg_interfaces)
523 self.pg_start()
524
525 # We expect replications on Pg1
526 self.verify_capture_ip6(self.pg1, tx)
527
528 # no replications on Pg0, Pg3
529 self.pg0.assert_nothing_captured(
530 remark="IP multicast packets forwarded on PG0")
531 self.pg2.assert_nothing_captured(
532 remark="IP multicast packets forwarded on PG2")
533 self.pg3.assert_nothing_captured(
534 remark="IP multicast packets forwarded on PG3")
535
536 #
Neale Rannsc2aad532017-05-30 09:53:52 -0700537 # Bounce the interface and it should still work
538 #
539 self.pg1.admin_down()
540 self.pg0.add_stream(tx)
541 self.pg_enable_capture(self.pg_interfaces)
542 self.pg_start()
543 self.pg1.assert_nothing_captured(
544 remark="IP multicast packets forwarded on down PG1")
545
546 self.pg1.admin_up()
547 self.pg0.add_stream(tx)
548 self.pg_enable_capture(self.pg_interfaces)
549 self.pg_start()
550 self.verify_capture_ip6(self.pg1, tx)
551
552 #
Neale Ranns32e1c012016-11-22 17:07:28 +0000553 # a stream that matches the route for (*,ff01::1)
554 #
555 self.vapi.cli("clear trace")
556 tx = self.create_stream_ip6(self.pg0, "2002::2", "ff01::1")
557 self.pg0.add_stream(tx)
558
559 self.pg_enable_capture(self.pg_interfaces)
560 self.pg_start()
561
562 # We expect replications on Pg1, 2, 3.
563 self.verify_capture_ip6(self.pg1, tx)
564 self.verify_capture_ip6(self.pg2, tx)
565 self.verify_capture_ip6(self.pg3, tx)
566
567 # no replications on Pg0
568 self.pg0.assert_nothing_captured(
569 remark="IPv6 multicast packets forwarded on PG0")
570
571 #
572 # a stream that matches the route for (2001::1, ff00::1)
573 #
574 self.vapi.cli("clear trace")
575 tx = self.create_stream_ip6(self.pg0, "2001::1", "ff01::1")
576 self.pg0.add_stream(tx)
577
578 self.pg_enable_capture(self.pg_interfaces)
579 self.pg_start()
580
581 # We expect replications on Pg1, 2,
582 self.verify_capture_ip6(self.pg1, tx)
583 self.verify_capture_ip6(self.pg2, tx)
584
585 # no replications on Pg0, Pg3
586 self.pg0.assert_nothing_captured(
587 remark="IP multicast packets forwarded on PG0")
588 self.pg3.assert_nothing_captured(
589 remark="IP multicast packets forwarded on PG3")
590
Neale Ranns21fb4f72020-10-05 12:26:47 +0000591 self.vapi.cli("packet mac-filter pg0 off")
592 self.vapi.cli("packet mac-filter pg1 off")
593 self.vapi.cli("packet mac-filter pg2 off")
594 self.vapi.cli("packet mac-filter pg4 off")
595 self.vapi.cli("packet mac-filter pg5 off")
596 self.vapi.cli("packet mac-filter pg6 off")
597 self.vapi.cli("packet mac-filter pg7 off")
598
Neale Ranns32e1c012016-11-22 17:07:28 +0000599 def _mcast_connected_send_stream(self, dst_ip):
600 self.vapi.cli("clear trace")
601 tx = self.create_stream_ip4(self.pg0,
602 self.pg0.remote_ip4,
603 dst_ip)
604 self.pg0.add_stream(tx)
605
606 self.pg_enable_capture(self.pg_interfaces)
607 self.pg_start()
608
609 # We expect replications on Pg1.
610 self.verify_capture_ip4(self.pg1, tx)
611
612 return tx
613
614 def test_ip_mcast_connected(self):
615 """ IP Multicast Connected Source check """
616
Neale Ranns990f6942020-10-20 07:20:17 +0000617 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
618 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
619
Neale Ranns32e1c012016-11-22 17:07:28 +0000620 #
621 # A (*,G).
622 # one accepting interface, pg0, 1 forwarding interfaces
623 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800624 route_232_1_1_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000625 self,
626 "0.0.0.0",
627 "232.1.1.1", 32,
Neale Ranns990f6942020-10-20 07:20:17 +0000628 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800629 [VppMRoutePath(self.pg0.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000630 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800631 VppMRoutePath(self.pg1.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000632 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)])
Neale Ranns32e1c012016-11-22 17:07:28 +0000633
634 route_232_1_1_1.add_vpp_config()
635 route_232_1_1_1.update_entry_flags(
Neale Ranns990f6942020-10-20 07:20:17 +0000636 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_CONNECTED)
Neale Ranns32e1c012016-11-22 17:07:28 +0000637
638 #
639 # Now the (*,G) is present, send from connected source
640 #
641 tx = self._mcast_connected_send_stream("232.1.1.1")
642
643 #
644 # Constrct a representation of the signal we expect on pg0
645 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800646 signal_232_1_1_1_itf_0 = VppMFibSignal(self,
647 route_232_1_1_1,
648 self.pg0.sw_if_index,
649 tx[0])
Neale Ranns32e1c012016-11-22 17:07:28 +0000650
651 #
652 # read the only expected signal
653 #
654 signals = self.vapi.mfib_signal_dump()
655
656 self.assertEqual(1, len(signals))
657
658 signal_232_1_1_1_itf_0.compare(signals[0])
659
660 #
661 # reading the signal allows for the generation of another
662 # so send more packets and expect the next signal
663 #
664 tx = self._mcast_connected_send_stream("232.1.1.1")
665
666 signals = self.vapi.mfib_signal_dump()
667 self.assertEqual(1, len(signals))
668 signal_232_1_1_1_itf_0.compare(signals[0])
669
670 #
671 # A Second entry with connected check
672 # one accepting interface, pg0, 1 forwarding interfaces
673 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800674 route_232_1_1_2 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000675 self,
676 "0.0.0.0",
677 "232.1.1.2", 32,
Neale Ranns990f6942020-10-20 07:20:17 +0000678 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800679 [VppMRoutePath(self.pg0.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000680 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800681 VppMRoutePath(self.pg1.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000682 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)])
Neale Ranns32e1c012016-11-22 17:07:28 +0000683
684 route_232_1_1_2.add_vpp_config()
685 route_232_1_1_2.update_entry_flags(
Neale Ranns990f6942020-10-20 07:20:17 +0000686 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_CONNECTED)
Neale Ranns32e1c012016-11-22 17:07:28 +0000687
688 #
689 # Send traffic to both entries. One read should net us two signals
690 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800691 signal_232_1_1_2_itf_0 = VppMFibSignal(self,
692 route_232_1_1_2,
693 self.pg0.sw_if_index,
694 tx[0])
Neale Ranns32e1c012016-11-22 17:07:28 +0000695 tx = self._mcast_connected_send_stream("232.1.1.1")
696 tx2 = self._mcast_connected_send_stream("232.1.1.2")
697
698 #
699 # read the only expected signal
700 #
701 signals = self.vapi.mfib_signal_dump()
702
703 self.assertEqual(2, len(signals))
704
705 signal_232_1_1_1_itf_0.compare(signals[1])
706 signal_232_1_1_2_itf_0.compare(signals[0])
707
Neale Rannsd792d9c2017-10-21 10:53:20 -0700708 route_232_1_1_1.update_entry_flags(
Neale Ranns990f6942020-10-20 07:20:17 +0000709 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE)
Neale Rannsd792d9c2017-10-21 10:53:20 -0700710 route_232_1_1_2.update_entry_flags(
Neale Ranns990f6942020-10-20 07:20:17 +0000711 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE)
Neale Ranns32e1c012016-11-22 17:07:28 +0000712
713 def test_ip_mcast_signal(self):
714 """ IP Multicast Signal """
715
Neale Ranns990f6942020-10-20 07:20:17 +0000716 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
717 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
718
Neale Ranns32e1c012016-11-22 17:07:28 +0000719 #
720 # A (*,G).
721 # one accepting interface, pg0, 1 forwarding interfaces
722 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800723 route_232_1_1_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000724 self,
725 "0.0.0.0",
726 "232.1.1.1", 32,
Neale Ranns990f6942020-10-20 07:20:17 +0000727 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800728 [VppMRoutePath(self.pg0.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000729 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800730 VppMRoutePath(self.pg1.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000731 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)])
Neale Ranns32e1c012016-11-22 17:07:28 +0000732
733 route_232_1_1_1.add_vpp_config()
Neale Ranns097fa662018-05-01 05:17:55 -0700734
Neale Ranns32e1c012016-11-22 17:07:28 +0000735 route_232_1_1_1.update_entry_flags(
Neale Ranns990f6942020-10-20 07:20:17 +0000736 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_SIGNAL)
Neale Ranns32e1c012016-11-22 17:07:28 +0000737
738 #
739 # Now the (*,G) is present, send from connected source
740 #
741 tx = self._mcast_connected_send_stream("232.1.1.1")
742
743 #
744 # Constrct a representation of the signal we expect on pg0
745 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800746 signal_232_1_1_1_itf_0 = VppMFibSignal(self,
747 route_232_1_1_1,
748 self.pg0.sw_if_index,
749 tx[0])
Neale Ranns32e1c012016-11-22 17:07:28 +0000750
751 #
752 # read the only expected signal
753 #
754 signals = self.vapi.mfib_signal_dump()
755
756 self.assertEqual(1, len(signals))
757
758 signal_232_1_1_1_itf_0.compare(signals[0])
759
760 #
761 # reading the signal allows for the generation of another
762 # so send more packets and expect the next signal
763 #
764 tx = self._mcast_connected_send_stream("232.1.1.1")
765
766 signals = self.vapi.mfib_signal_dump()
767 self.assertEqual(1, len(signals))
768 signal_232_1_1_1_itf_0.compare(signals[0])
769
770 #
771 # Set the negate-signal on the accepting interval - the signals
772 # should stop
773 #
774 route_232_1_1_1.update_path_flags(
775 self.pg0.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000776 (MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT |
777 MRouteItfFlags.MFIB_API_ITF_FLAG_NEGATE_SIGNAL))
Neale Ranns32e1c012016-11-22 17:07:28 +0000778
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800779 self.vapi.cli("clear trace")
Neale Ranns32e1c012016-11-22 17:07:28 +0000780 tx = self._mcast_connected_send_stream("232.1.1.1")
781
782 signals = self.vapi.mfib_signal_dump()
783 self.assertEqual(0, len(signals))
784
785 #
786 # Clear the SIGNAL flag on the entry and the signals should
787 # come back since the interface is still NEGATE-SIGNAL
788 #
789 route_232_1_1_1.update_entry_flags(
Neale Ranns990f6942020-10-20 07:20:17 +0000790 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE)
Neale Ranns32e1c012016-11-22 17:07:28 +0000791
792 tx = self._mcast_connected_send_stream("232.1.1.1")
793
794 signals = self.vapi.mfib_signal_dump()
795 self.assertEqual(1, len(signals))
796 signal_232_1_1_1_itf_0.compare(signals[0])
797
798 #
799 # Lastly remove the NEGATE-SIGNAL from the interface and the
800 # signals should stop
801 #
Neale Ranns990f6942020-10-20 07:20:17 +0000802 route_232_1_1_1.update_path_flags(
803 self.pg0.sw_if_index,
804 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT)
Neale Ranns32e1c012016-11-22 17:07:28 +0000805
806 tx = self._mcast_connected_send_stream("232.1.1.1")
807 signals = self.vapi.mfib_signal_dump()
808 self.assertEqual(0, len(signals))
809
Neale Ranns15002542017-09-10 04:39:11 -0700810 def test_ip_mcast_vrf(self):
811 """ IP Multicast Replication in non-default table"""
812
Neale Ranns990f6942020-10-20 07:20:17 +0000813 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
814 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
815
Neale Ranns15002542017-09-10 04:39:11 -0700816 #
817 # An (S,G).
818 # one accepting interface, pg0, 2 forwarding interfaces
819 #
820 route_1_1_1_1_232_1_1_1 = VppIpMRoute(
821 self,
822 "1.1.1.1",
823 "232.1.1.1", 64,
Neale Ranns990f6942020-10-20 07:20:17 +0000824 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns15002542017-09-10 04:39:11 -0700825 [VppMRoutePath(self.pg8.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000826 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT),
Neale Ranns15002542017-09-10 04:39:11 -0700827 VppMRoutePath(self.pg1.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000828 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD),
Neale Ranns15002542017-09-10 04:39:11 -0700829 VppMRoutePath(self.pg2.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000830 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)],
Neale Ranns15002542017-09-10 04:39:11 -0700831 table_id=10)
832 route_1_1_1_1_232_1_1_1.add_vpp_config()
833
834 #
835 # a stream that matches the route for (1.1.1.1,232.1.1.1)
836 # small packets
837 #
838 self.vapi.cli("clear trace")
839 tx = self.create_stream_ip4(self.pg8, "1.1.1.1", "232.1.1.1")
840 self.pg8.add_stream(tx)
841
842 self.pg_enable_capture(self.pg_interfaces)
843 self.pg_start()
844
845 # We expect replications on Pg1 & 2
846 self.verify_capture_ip4(self.pg1, tx)
847 self.verify_capture_ip4(self.pg2, tx)
848
Neale Rannsadb17a82019-08-04 02:41:57 -0700849 def test_ip_mcast_gre(self):
850 """ IP Multicast Replication over GRE"""
851
Neale Ranns990f6942020-10-20 07:20:17 +0000852 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
853 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
854
Neale Rannsadb17a82019-08-04 02:41:57 -0700855 gre_if_1 = VppGreInterface(
856 self,
857 self.pg1.local_ip4,
858 self.pg1.remote_ip4).add_vpp_config()
859 gre_if_2 = VppGreInterface(
860 self,
861 self.pg2.local_ip4,
862 self.pg2.remote_ip4).add_vpp_config()
863 gre_if_3 = VppGreInterface(
864 self,
865 self.pg3.local_ip4,
866 self.pg3.remote_ip4).add_vpp_config()
867
868 gre_if_1.admin_up()
869 gre_if_1.config_ip4()
870 gre_if_2.admin_up()
871 gre_if_2.config_ip4()
872 gre_if_3.admin_up()
873 gre_if_3.config_ip4()
874
875 #
876 # An (S,G).
877 # one accepting interface, pg0, 2 forwarding interfaces
878 #
879 route_1_1_1_1_232_1_1_1 = VppIpMRoute(
880 self,
881 "1.1.1.1",
882 "232.2.2.2", 64,
Neale Ranns990f6942020-10-20 07:20:17 +0000883 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Rannsadb17a82019-08-04 02:41:57 -0700884 [VppMRoutePath(gre_if_1.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000885 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT),
Neale Rannsadb17a82019-08-04 02:41:57 -0700886 VppMRoutePath(gre_if_2.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000887 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD),
Neale Rannsadb17a82019-08-04 02:41:57 -0700888 VppMRoutePath(gre_if_3.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +0000889 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)])
Neale Rannsadb17a82019-08-04 02:41:57 -0700890 route_1_1_1_1_232_1_1_1.add_vpp_config()
891
892 #
893 # a stream that matches the route for (1.1.1.1,232.2.2.2)
894 # small packets
895 #
896 tx = (Ether(dst=self.pg1.local_mac,
897 src=self.pg1.remote_mac) /
898 IP(src=self.pg1.remote_ip4,
899 dst=self.pg1.local_ip4) /
900 GRE() /
901 IP(src="1.1.1.1", dst="232.2.2.2") /
902 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +0100903 Raw(b'\a5' * 64)) * 63
Neale Rannsadb17a82019-08-04 02:41:57 -0700904
905 self.vapi.cli("clear trace")
906 self.pg1.add_stream(tx)
907
908 self.pg_enable_capture(self.pg_interfaces)
909 self.pg_start()
910
911 # We expect replications on Pg2 & 3
912 # check the encap headers are as expected based on the egress tunnel
913 rxs = self.pg2.get_capture(len(tx))
914 for rx in rxs:
915 self.assertEqual(rx[IP].src, gre_if_2.t_src)
916 self.assertEqual(rx[IP].dst, gre_if_2.t_dst)
917 self.assert_packet_checksums_valid(rx)
918
919 rxs = self.pg3.get_capture(len(tx))
920 for rx in rxs:
921 self.assertEqual(rx[IP].src, gre_if_3.t_src)
922 self.assertEqual(rx[IP].dst, gre_if_3.t_dst)
923 self.assert_packet_checksums_valid(rx)
924
Neale Ranns7d8a9562020-11-20 14:32:56 +0000925 def test_ip6_mcast_gre(self):
926 """ IP6 Multicast Replication over GRE"""
927
928 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
929 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
930
931 gre_if_1 = VppGreInterface(
932 self,
933 self.pg1.local_ip4,
934 self.pg1.remote_ip4).add_vpp_config()
935 gre_if_2 = VppGreInterface(
936 self,
937 self.pg2.local_ip4,
938 self.pg2.remote_ip4).add_vpp_config()
939 gre_if_3 = VppGreInterface(
940 self,
941 self.pg3.local_ip4,
942 self.pg3.remote_ip4).add_vpp_config()
943
944 gre_if_1.admin_up()
945 gre_if_1.config_ip6()
946 gre_if_2.admin_up()
947 gre_if_2.config_ip6()
948 gre_if_3.admin_up()
949 gre_if_3.config_ip6()
950
951 #
952 # An (S,G).
953 # one accepting interface, pg0, 2 forwarding interfaces
954 #
955 route_1_1_FF_1 = VppIpMRoute(
956 self,
957 "1::1",
958 "FF00::1", 256,
959 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
960 [VppMRoutePath(gre_if_1.sw_if_index,
961 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT),
962 VppMRoutePath(gre_if_2.sw_if_index,
963 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD),
964 VppMRoutePath(gre_if_3.sw_if_index,
965 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)])
966 route_1_1_FF_1.add_vpp_config()
967
968 #
969 # a stream that matches the route for (1::1, FF::1)
970 # small packets
971 #
972 tx = (Ether(dst=self.pg1.local_mac,
973 src=self.pg1.remote_mac) /
974 IP(src=self.pg1.remote_ip4,
975 dst=self.pg1.local_ip4) /
976 GRE() /
977 IPv6(src="1::1", dst="FF00::1") /
978 UDP(sport=1234, dport=1234) /
979 Raw(b'\a5' * 64)) * 63
980
981 self.vapi.cli("clear trace")
982 self.pg1.add_stream(tx)
983
984 self.pg_enable_capture(self.pg_interfaces)
985 self.pg_start()
986
987 # We expect replications on Pg2 & 3
988 # check the encap headers are as expected based on the egress tunnel
989 rxs = self.pg2.get_capture(len(tx))
990 for rx in rxs:
991 self.assertEqual(rx[IP].src, gre_if_2.t_src)
992 self.assertEqual(rx[IP].dst, gre_if_2.t_dst)
993 self.assert_packet_checksums_valid(rx)
994
995 rxs = self.pg3.get_capture(len(tx))
996 for rx in rxs:
997 self.assertEqual(rx[IP].src, gre_if_3.t_src)
998 self.assertEqual(rx[IP].dst, gre_if_3.t_dst)
999 self.assert_packet_checksums_valid(rx)
1000
Neale Ranns15002542017-09-10 04:39:11 -07001001 def test_ip6_mcast_vrf(self):
1002 """ IPv6 Multicast Replication in non-default table"""
1003
Neale Ranns990f6942020-10-20 07:20:17 +00001004 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1005 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1006
Neale Ranns15002542017-09-10 04:39:11 -07001007 #
1008 # An (S,G).
1009 # one accepting interface, pg0, 2 forwarding interfaces
1010 #
1011 route_2001_ff01_1 = VppIpMRoute(
1012 self,
1013 "2001::1",
1014 "ff01::1", 256,
Neale Ranns990f6942020-10-20 07:20:17 +00001015 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Ranns15002542017-09-10 04:39:11 -07001016 [VppMRoutePath(self.pg8.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +00001017 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT,
Neale Ranns097fa662018-05-01 05:17:55 -07001018 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6),
Neale Ranns15002542017-09-10 04:39:11 -07001019 VppMRoutePath(self.pg1.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +00001020 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
Neale Ranns097fa662018-05-01 05:17:55 -07001021 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6),
Neale Ranns15002542017-09-10 04:39:11 -07001022 VppMRoutePath(self.pg2.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +00001023 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD,
Neale Ranns097fa662018-05-01 05:17:55 -07001024 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)],
1025 table_id=10)
Neale Ranns15002542017-09-10 04:39:11 -07001026 route_2001_ff01_1.add_vpp_config()
1027
1028 #
1029 # a stream that matches the route for (2001::1, ff00::1)
1030 #
1031 self.vapi.cli("clear trace")
1032 tx = self.create_stream_ip6(self.pg8, "2001::1", "ff01::1")
1033 self.pg8.add_stream(tx)
1034
1035 self.pg_enable_capture(self.pg_interfaces)
1036 self.pg_start()
1037
1038 # We expect replications on Pg1, 2,
1039 self.verify_capture_ip6(self.pg1, tx)
1040 self.verify_capture_ip6(self.pg2, tx)
Neale Ranns32e1c012016-11-22 17:07:28 +00001041
Neale Rannscf3561b2017-12-13 01:44:25 -08001042 def test_bidir(self):
1043 """ IP Multicast Bi-directional """
1044
Neale Ranns990f6942020-10-20 07:20:17 +00001045 MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t
1046 MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t
1047
Neale Rannscf3561b2017-12-13 01:44:25 -08001048 #
1049 # A (*,G). The set of accepting interfaces matching the forwarding
1050 #
1051 route_232_1_1_1 = VppIpMRoute(
1052 self,
1053 "0.0.0.0",
1054 "232.1.1.1", 32,
Neale Ranns990f6942020-10-20 07:20:17 +00001055 MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE,
Neale Rannscf3561b2017-12-13 01:44:25 -08001056 [VppMRoutePath(self.pg0.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +00001057 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT |
1058 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD),
Neale Rannscf3561b2017-12-13 01:44:25 -08001059 VppMRoutePath(self.pg1.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +00001060 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT |
1061 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD),
Neale Rannscf3561b2017-12-13 01:44:25 -08001062 VppMRoutePath(self.pg2.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +00001063 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT |
1064 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD),
Neale Rannscf3561b2017-12-13 01:44:25 -08001065 VppMRoutePath(self.pg3.sw_if_index,
Neale Ranns990f6942020-10-20 07:20:17 +00001066 MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT |
1067 MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)])
Neale Rannscf3561b2017-12-13 01:44:25 -08001068 route_232_1_1_1.add_vpp_config()
1069
1070 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.1")
1071 self.pg0.add_stream(tx)
1072
1073 self.pg_enable_capture(self.pg_interfaces)
1074 self.pg_start()
1075
1076 # We expect replications on Pg1, 2, 3, but not on pg0
1077 self.verify_capture_ip4(self.pg1, tx)
1078 self.verify_capture_ip4(self.pg2, tx)
1079 self.verify_capture_ip4(self.pg3, tx)
1080 self.pg0.assert_nothing_captured(
1081 remark="IP multicast packets forwarded on PG0")
1082
1083
Neale Ranns32e1c012016-11-22 17:07:28 +00001084if __name__ == '__main__':
1085 unittest.main(testRunner=VppTestRunner)