blob: 64eb304a29ea66b188bc364ece438915e1fe14bb [file] [log] [blame]
Neale Ranns32e1c012016-11-22 17:07:28 +00001#!/usr/bin/env python
2
3import unittest
4
5from framework import VppTestCase, VppTestRunner
Neale Rannsc0a93142018-09-05 15:42:26 -07006from vpp_ip import DpoProto
Neale Ranns180279b2017-03-16 15:49:09 -04007from vpp_ip_route import VppIpMRoute, VppMRoutePath, VppMFibSignal, \
Neale Rannsc0a93142018-09-05 15:42:26 -07008 MRouteItfFlags, MRouteEntryFlags, VppIpTable
Neale Ranns32e1c012016-11-22 17:07:28 +00009
10from scapy.packet import Raw
11from scapy.layers.l2 import Ether
Klement Sekerab9ef2732018-06-24 22:49:33 +020012from scapy.layers.inet import IP, UDP, getmacbyip
Neale Ranns32e1c012016-11-22 17:07:28 +000013from scapy.layers.inet6 import IPv6, getmacbyip6
Neale Ranns32e1c012016-11-22 17:07:28 +000014
Neale Ranns9bea8fb2017-02-03 04:34:01 -080015#
Neale Rannscf3561b2017-12-13 01:44:25 -080016# The number of packets sent is set to 91 so that when we replicate more than 3
Neale Ranns9bea8fb2017-02-03 04:34:01 -080017# times, which we do for some entries, we will generate more than 256 packets
Neale Rannsaaa396a2017-02-05 09:12:02 -080018# to the next node in the VLIB graph. Thus we are testing the code's
Neale Rannscf3561b2017-12-13 01:44:25 -080019# correctness handling this over-flow.
20# It's also an odd number so we hit any single loops.
Neale Ranns9bea8fb2017-02-03 04:34:01 -080021#
Neale Rannscf3561b2017-12-13 01:44:25 -080022N_PKTS_IN_STREAM = 91
Neale Ranns9bea8fb2017-02-03 04:34:01 -080023
Neale Ranns32e1c012016-11-22 17:07:28 +000024
Neale Ranns5a8123b2017-01-26 01:18:23 -080025class TestMFIB(VppTestCase):
26 """ MFIB Test Case """
27
28 def setUp(self):
29 super(TestMFIB, self).setUp()
30
31 def test_mfib(self):
32 """ MFIB Unit Tests """
33 error = self.vapi.cli("test mfib")
34
35 if error:
36 self.logger.critical(error)
37 self.assertEqual(error.find("Failed"), -1)
38
39
Neale Ranns32e1c012016-11-22 17:07:28 +000040class TestIPMcast(VppTestCase):
41 """ IP Multicast Test Case """
42
43 def setUp(self):
44 super(TestIPMcast, self).setUp()
45
Neale Ranns37be7362017-02-21 17:30:26 -080046 # create 8 pg interfaces
Neale Ranns15002542017-09-10 04:39:11 -070047 self.create_pg_interfaces(range(9))
Neale Ranns32e1c012016-11-22 17:07:28 +000048
49 # setup interfaces
Neale Ranns15002542017-09-10 04:39:11 -070050 for i in self.pg_interfaces[:8]:
Neale Ranns32e1c012016-11-22 17:07:28 +000051 i.admin_up()
52 i.config_ip4()
53 i.config_ip6()
54 i.resolve_arp()
55 i.resolve_ndp()
56
Neale Ranns15002542017-09-10 04:39:11 -070057 # one more in a vrf
58 tbl4 = VppIpTable(self, 10)
59 tbl4.add_vpp_config()
60 self.pg8.set_table_ip4(10)
61 self.pg8.config_ip4()
62
63 tbl6 = VppIpTable(self, 10, is_ip6=1)
64 tbl6.add_vpp_config()
65 self.pg8.set_table_ip6(10)
66 self.pg8.config_ip6()
67
68 def tearDown(self):
69 for i in self.pg_interfaces:
70 i.unconfig_ip4()
71 i.unconfig_ip6()
72 i.admin_down()
73
74 self.pg8.set_table_ip4(0)
75 self.pg8.set_table_ip6(0)
76 super(TestIPMcast, self).tearDown()
77
Neale Ranns9d676af2017-03-15 01:28:31 -070078 def create_stream_ip4(self, src_if, src_ip, dst_ip, payload_size=0):
Neale Ranns32e1c012016-11-22 17:07:28 +000079 pkts = []
Neale Ranns9d676af2017-03-15 01:28:31 -070080 # default to small packet sizes
81 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
82 IP(src=src_ip, dst=dst_ip) /
83 UDP(sport=1234, dport=1234))
84 if not payload_size:
85 payload_size = 64 - len(p)
86 p = p / Raw('\xa5' * payload_size)
87
Neale Ranns9bea8fb2017-02-03 04:34:01 -080088 for i in range(0, N_PKTS_IN_STREAM):
Neale Ranns32e1c012016-11-22 17:07:28 +000089 pkts.append(p)
90 return pkts
91
92 def create_stream_ip6(self, src_if, src_ip, dst_ip):
93 pkts = []
Neale Ranns9bea8fb2017-02-03 04:34:01 -080094 for i in range(0, N_PKTS_IN_STREAM):
Neale Ranns32e1c012016-11-22 17:07:28 +000095 info = self.create_packet_info(src_if, src_if)
96 payload = self.info_to_payload(info)
97 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
98 IPv6(src=src_ip, dst=dst_ip) /
99 UDP(sport=1234, dport=1234) /
100 Raw(payload))
101 info.data = p.copy()
102 pkts.append(p)
103 return pkts
104
105 def verify_filter(self, capture, sent):
106 if not len(capture) == len(sent):
107 # filter out any IPv6 RAs from the captur
108 for p in capture:
109 if (p.haslayer(IPv6)):
110 capture.remove(p)
111 return capture
112
Neale Rannse821ab12017-06-01 07:45:05 -0700113 def verify_capture_ip4(self, rx_if, sent, dst_mac=None):
Neale Rannsc2aad532017-05-30 09:53:52 -0700114 rxd = rx_if.get_capture(len(sent))
Neale Ranns32e1c012016-11-22 17:07:28 +0000115
116 try:
117 capture = self.verify_filter(rxd, sent)
118
119 self.assertEqual(len(capture), len(sent))
120
121 for i in range(len(capture)):
122 tx = sent[i]
123 rx = capture[i]
124
Neale Ranns32e1c012016-11-22 17:07:28 +0000125 eth = rx[Ether]
126 self.assertEqual(eth.type, 0x800)
127
128 tx_ip = tx[IP]
129 rx_ip = rx[IP]
130
Neale Rannse821ab12017-06-01 07:45:05 -0700131 if dst_mac is None:
132 dst_mac = getmacbyip(rx_ip.dst)
133
Neale Ranns32e1c012016-11-22 17:07:28 +0000134 # check the MAC address on the RX'd packet is correctly formed
Neale Rannse821ab12017-06-01 07:45:05 -0700135 self.assertEqual(eth.dst, dst_mac)
Neale Ranns32e1c012016-11-22 17:07:28 +0000136
137 self.assertEqual(rx_ip.src, tx_ip.src)
138 self.assertEqual(rx_ip.dst, tx_ip.dst)
139 # IP processing post pop has decremented the TTL
140 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
141
142 except:
143 raise
144
Neale Rannsc2aad532017-05-30 09:53:52 -0700145 def verify_capture_ip6(self, rx_if, sent):
146 capture = rx_if.get_capture(len(sent))
Neale Ranns32e1c012016-11-22 17:07:28 +0000147
148 self.assertEqual(len(capture), len(sent))
149
150 for i in range(len(capture)):
151 tx = sent[i]
152 rx = capture[i]
153
Neale Ranns32e1c012016-11-22 17:07:28 +0000154 eth = rx[Ether]
155 self.assertEqual(eth.type, 0x86DD)
156
157 tx_ip = tx[IPv6]
158 rx_ip = rx[IPv6]
159
160 # check the MAC address on the RX'd packet is correctly formed
161 self.assertEqual(eth.dst, getmacbyip6(rx_ip.dst))
162
163 self.assertEqual(rx_ip.src, tx_ip.src)
164 self.assertEqual(rx_ip.dst, tx_ip.dst)
165 # IP processing post pop has decremented the TTL
166 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
167
168 def test_ip_mcast(self):
169 """ IP Multicast Replication """
170
171 #
172 # a stream that matches the default route. gets dropped.
173 #
174 self.vapi.cli("clear trace")
175 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.1")
176 self.pg0.add_stream(tx)
177
178 self.pg_enable_capture(self.pg_interfaces)
179 self.pg_start()
180
181 self.pg0.assert_nothing_captured(
182 remark="IP multicast packets forwarded on default route")
183
184 #
185 # A (*,G).
Neale Ranns37be7362017-02-21 17:30:26 -0800186 # one accepting interface, pg0, 7 forwarding interfaces
187 # many forwarding interfaces test the case where the replicare DPO
188 # needs to use extra cache lines for the buckets.
Neale Ranns32e1c012016-11-22 17:07:28 +0000189 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800190 route_232_1_1_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000191 self,
192 "0.0.0.0",
193 "232.1.1.1", 32,
194 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800195 [VppMRoutePath(self.pg0.sw_if_index,
196 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
197 VppMRoutePath(self.pg1.sw_if_index,
198 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
199 VppMRoutePath(self.pg2.sw_if_index,
200 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
201 VppMRoutePath(self.pg3.sw_if_index,
Neale Ranns37be7362017-02-21 17:30:26 -0800202 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
203 VppMRoutePath(self.pg4.sw_if_index,
204 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
205 VppMRoutePath(self.pg5.sw_if_index,
206 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
207 VppMRoutePath(self.pg6.sw_if_index,
208 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
209 VppMRoutePath(self.pg7.sw_if_index,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800210 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
Neale Ranns32e1c012016-11-22 17:07:28 +0000211 route_232_1_1_1.add_vpp_config()
212
213 #
214 # An (S,G).
215 # one accepting interface, pg0, 2 forwarding interfaces
216 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800217 route_1_1_1_1_232_1_1_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000218 self,
219 "1.1.1.1",
220 "232.1.1.1", 64,
221 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800222 [VppMRoutePath(self.pg0.sw_if_index,
223 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
224 VppMRoutePath(self.pg1.sw_if_index,
225 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
226 VppMRoutePath(self.pg2.sw_if_index,
227 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
Neale Ranns32e1c012016-11-22 17:07:28 +0000228 route_1_1_1_1_232_1_1_1.add_vpp_config()
229
230 #
Neale Rannse821ab12017-06-01 07:45:05 -0700231 # An (S,G).
232 # one accepting interface, pg0, 2 forwarding interfaces
233 # that use unicast next-hops
234 #
235 route_1_1_1_1_232_1_1_2 = VppIpMRoute(
236 self,
237 "1.1.1.1",
238 "232.1.1.2", 64,
239 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
240 [VppMRoutePath(self.pg0.sw_if_index,
241 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
242 VppMRoutePath(self.pg1.sw_if_index,
243 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
244 nh=self.pg1.remote_ip4),
245 VppMRoutePath(self.pg2.sw_if_index,
246 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
247 nh=self.pg2.remote_ip4)])
248 route_1_1_1_1_232_1_1_2.add_vpp_config()
249
250 #
Neale Ranns32e1c012016-11-22 17:07:28 +0000251 # An (*,G/m).
252 # one accepting interface, pg0, 1 forwarding interfaces
253 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800254 route_232 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000255 self,
256 "0.0.0.0",
257 "232.0.0.0", 8,
258 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800259 [VppMRoutePath(self.pg0.sw_if_index,
260 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
261 VppMRoutePath(self.pg1.sw_if_index,
262 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
Neale Ranns32e1c012016-11-22 17:07:28 +0000263 route_232.add_vpp_config()
264
265 #
266 # a stream that matches the route for (1.1.1.1,232.1.1.1)
Neale Ranns9d676af2017-03-15 01:28:31 -0700267 # small packets
Neale Ranns32e1c012016-11-22 17:07:28 +0000268 #
269 self.vapi.cli("clear trace")
270 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.1")
271 self.pg0.add_stream(tx)
272
273 self.pg_enable_capture(self.pg_interfaces)
274 self.pg_start()
275
Neale Ranns37be7362017-02-21 17:30:26 -0800276 # We expect replications on Pg1->7
Neale Ranns32e1c012016-11-22 17:07:28 +0000277 self.verify_capture_ip4(self.pg1, tx)
278 self.verify_capture_ip4(self.pg2, tx)
279
280 # no replications on Pg0
281 self.pg0.assert_nothing_captured(
282 remark="IP multicast packets forwarded on PG0")
283 self.pg3.assert_nothing_captured(
284 remark="IP multicast packets forwarded on PG3")
285
286 #
Neale Ranns9d676af2017-03-15 01:28:31 -0700287 # a stream that matches the route for (1.1.1.1,232.1.1.1)
288 # large packets
289 #
290 self.vapi.cli("clear trace")
291 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.1",
292 payload_size=1024)
293 self.pg0.add_stream(tx)
294
295 self.pg_enable_capture(self.pg_interfaces)
296 self.pg_start()
297
298 # We expect replications on Pg1->7
299 self.verify_capture_ip4(self.pg1, tx)
300 self.verify_capture_ip4(self.pg2, tx)
Neale Ranns9d676af2017-03-15 01:28:31 -0700301
302 # no replications on Pg0
303 self.pg0.assert_nothing_captured(
304 remark="IP multicast packets forwarded on PG0")
305 self.pg3.assert_nothing_captured(
306 remark="IP multicast packets forwarded on PG3")
307
308 #
Neale Rannse821ab12017-06-01 07:45:05 -0700309 # a stream to the unicast next-hops
310 #
311 self.vapi.cli("clear trace")
312 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.2")
313 self.pg0.add_stream(tx)
314
315 self.pg_enable_capture(self.pg_interfaces)
316 self.pg_start()
317
318 # We expect replications on Pg1->7
319 self.verify_capture_ip4(self.pg1, tx, dst_mac=self.pg1.remote_mac)
320 self.verify_capture_ip4(self.pg2, tx, dst_mac=self.pg2.remote_mac)
321
322 # no replications on Pg0 nor pg3
323 self.pg0.assert_nothing_captured(
324 remark="IP multicast packets forwarded on PG0")
325 self.pg3.assert_nothing_captured(
326 remark="IP multicast packets forwarded on PG3")
327
328 #
Neale Ranns32e1c012016-11-22 17:07:28 +0000329 # a stream that matches the route for (*,232.0.0.0/8)
330 # Send packets with the 9th bit set so we test the correct clearing
331 # of that bit in the mac rewrite
332 #
333 self.vapi.cli("clear trace")
334 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.255.255.255")
335 self.pg0.add_stream(tx)
336
337 self.pg_enable_capture(self.pg_interfaces)
338 self.pg_start()
339
340 # We expect replications on Pg1 only
341 self.verify_capture_ip4(self.pg1, tx)
342
343 # no replications on Pg0, Pg2 not Pg3
344 self.pg0.assert_nothing_captured(
345 remark="IP multicast packets forwarded on PG0")
346 self.pg2.assert_nothing_captured(
347 remark="IP multicast packets forwarded on PG2")
348 self.pg3.assert_nothing_captured(
349 remark="IP multicast packets forwarded on PG3")
350
351 #
352 # a stream that matches the route for (*,232.1.1.1)
353 #
354 self.vapi.cli("clear trace")
355 tx = self.create_stream_ip4(self.pg0, "1.1.1.2", "232.1.1.1")
356 self.pg0.add_stream(tx)
357
358 self.pg_enable_capture(self.pg_interfaces)
359 self.pg_start()
360
Neale Rannse821ab12017-06-01 07:45:05 -0700361 # We expect replications on Pg1->7
Neale Ranns32e1c012016-11-22 17:07:28 +0000362 self.verify_capture_ip4(self.pg1, tx)
363 self.verify_capture_ip4(self.pg2, tx)
364 self.verify_capture_ip4(self.pg3, tx)
Neale Rannsc2aad532017-05-30 09:53:52 -0700365 self.verify_capture_ip4(self.pg4, tx)
366 self.verify_capture_ip4(self.pg5, tx)
367 self.verify_capture_ip4(self.pg6, tx)
368 self.verify_capture_ip4(self.pg7, tx)
Neale Ranns32e1c012016-11-22 17:07:28 +0000369
Neale Rannse821ab12017-06-01 07:45:05 -0700370 # no replications on Pg0
371 self.pg0.assert_nothing_captured(
372 remark="IP multicast packets forwarded on PG0")
373
Neale Ranns32e1c012016-11-22 17:07:28 +0000374 def test_ip6_mcast(self):
375 """ IPv6 Multicast Replication """
376
377 #
378 # a stream that matches the default route. gets dropped.
379 #
380 self.vapi.cli("clear trace")
381 tx = self.create_stream_ip6(self.pg0, "2001::1", "ff01::1")
382 self.pg0.add_stream(tx)
383
384 self.pg_enable_capture(self.pg_interfaces)
385 self.pg_start()
386
387 self.pg0.assert_nothing_captured(
388 remark="IPv6 multicast packets forwarded on default route")
389
390 #
391 # A (*,G).
392 # one accepting interface, pg0, 3 forwarding interfaces
393 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800394 route_ff01_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000395 self,
396 "::",
397 "ff01::1", 128,
398 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800399 [VppMRoutePath(self.pg0.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700400 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT,
401 proto=DpoProto.DPO_PROTO_IP6),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800402 VppMRoutePath(self.pg1.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700403 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
404 proto=DpoProto.DPO_PROTO_IP6),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800405 VppMRoutePath(self.pg2.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700406 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
407 proto=DpoProto.DPO_PROTO_IP6),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800408 VppMRoutePath(self.pg3.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700409 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
410 proto=DpoProto.DPO_PROTO_IP6)],
Neale Ranns32e1c012016-11-22 17:07:28 +0000411 is_ip6=1)
412 route_ff01_1.add_vpp_config()
413
414 #
415 # An (S,G).
416 # one accepting interface, pg0, 2 forwarding interfaces
417 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800418 route_2001_ff01_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000419 self,
420 "2001::1",
421 "ff01::1", 256,
422 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800423 [VppMRoutePath(self.pg0.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700424 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT,
425 proto=DpoProto.DPO_PROTO_IP6),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800426 VppMRoutePath(self.pg1.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700427 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
428 proto=DpoProto.DPO_PROTO_IP6),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800429 VppMRoutePath(self.pg2.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700430 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
431 proto=DpoProto.DPO_PROTO_IP6)],
Neale Ranns32e1c012016-11-22 17:07:28 +0000432 is_ip6=1)
433 route_2001_ff01_1.add_vpp_config()
434
435 #
436 # An (*,G/m).
437 # one accepting interface, pg0, 1 forwarding interface
438 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800439 route_ff01 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000440 self,
441 "::",
442 "ff01::", 16,
443 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800444 [VppMRoutePath(self.pg0.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700445 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT,
446 proto=DpoProto.DPO_PROTO_IP6),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800447 VppMRoutePath(self.pg1.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700448 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
449 proto=DpoProto.DPO_PROTO_IP6)],
Neale Ranns32e1c012016-11-22 17:07:28 +0000450 is_ip6=1)
451 route_ff01.add_vpp_config()
452
453 #
454 # a stream that matches the route for (*, ff01::/16)
Neale Rannsce111d22018-01-23 08:38:50 -0800455 # sent on the non-accepting interface
456 #
457 self.vapi.cli("clear trace")
458 tx = self.create_stream_ip6(self.pg1, "2002::1", "ff01:2::255")
459 self.send_and_assert_no_replies(self.pg1, tx, "RPF miss")
460
461 #
462 # a stream that matches the route for (*, ff01::/16)
463 # sent on the accepting interface
Neale Ranns32e1c012016-11-22 17:07:28 +0000464 #
465 self.vapi.cli("clear trace")
466 tx = self.create_stream_ip6(self.pg0, "2002::1", "ff01:2::255")
467 self.pg0.add_stream(tx)
468
469 self.pg_enable_capture(self.pg_interfaces)
470 self.pg_start()
471
472 # We expect replications on Pg1
473 self.verify_capture_ip6(self.pg1, tx)
474
475 # no replications on Pg0, Pg3
476 self.pg0.assert_nothing_captured(
477 remark="IP multicast packets forwarded on PG0")
478 self.pg2.assert_nothing_captured(
479 remark="IP multicast packets forwarded on PG2")
480 self.pg3.assert_nothing_captured(
481 remark="IP multicast packets forwarded on PG3")
482
483 #
Neale Rannsc2aad532017-05-30 09:53:52 -0700484 # Bounce the interface and it should still work
485 #
486 self.pg1.admin_down()
487 self.pg0.add_stream(tx)
488 self.pg_enable_capture(self.pg_interfaces)
489 self.pg_start()
490 self.pg1.assert_nothing_captured(
491 remark="IP multicast packets forwarded on down PG1")
492
493 self.pg1.admin_up()
494 self.pg0.add_stream(tx)
495 self.pg_enable_capture(self.pg_interfaces)
496 self.pg_start()
497 self.verify_capture_ip6(self.pg1, tx)
498
499 #
Neale Ranns32e1c012016-11-22 17:07:28 +0000500 # a stream that matches the route for (*,ff01::1)
501 #
502 self.vapi.cli("clear trace")
503 tx = self.create_stream_ip6(self.pg0, "2002::2", "ff01::1")
504 self.pg0.add_stream(tx)
505
506 self.pg_enable_capture(self.pg_interfaces)
507 self.pg_start()
508
509 # We expect replications on Pg1, 2, 3.
510 self.verify_capture_ip6(self.pg1, tx)
511 self.verify_capture_ip6(self.pg2, tx)
512 self.verify_capture_ip6(self.pg3, tx)
513
514 # no replications on Pg0
515 self.pg0.assert_nothing_captured(
516 remark="IPv6 multicast packets forwarded on PG0")
517
518 #
519 # a stream that matches the route for (2001::1, ff00::1)
520 #
521 self.vapi.cli("clear trace")
522 tx = self.create_stream_ip6(self.pg0, "2001::1", "ff01::1")
523 self.pg0.add_stream(tx)
524
525 self.pg_enable_capture(self.pg_interfaces)
526 self.pg_start()
527
528 # We expect replications on Pg1, 2,
529 self.verify_capture_ip6(self.pg1, tx)
530 self.verify_capture_ip6(self.pg2, tx)
531
532 # no replications on Pg0, Pg3
533 self.pg0.assert_nothing_captured(
534 remark="IP multicast packets forwarded on PG0")
535 self.pg3.assert_nothing_captured(
536 remark="IP multicast packets forwarded on PG3")
537
Neale Ranns32e1c012016-11-22 17:07:28 +0000538 def _mcast_connected_send_stream(self, dst_ip):
539 self.vapi.cli("clear trace")
540 tx = self.create_stream_ip4(self.pg0,
541 self.pg0.remote_ip4,
542 dst_ip)
543 self.pg0.add_stream(tx)
544
545 self.pg_enable_capture(self.pg_interfaces)
546 self.pg_start()
547
548 # We expect replications on Pg1.
549 self.verify_capture_ip4(self.pg1, tx)
550
551 return tx
552
553 def test_ip_mcast_connected(self):
554 """ IP Multicast Connected Source check """
555
556 #
557 # A (*,G).
558 # one accepting interface, pg0, 1 forwarding interfaces
559 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800560 route_232_1_1_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000561 self,
562 "0.0.0.0",
563 "232.1.1.1", 32,
564 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800565 [VppMRoutePath(self.pg0.sw_if_index,
566 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
567 VppMRoutePath(self.pg1.sw_if_index,
568 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
Neale Ranns32e1c012016-11-22 17:07:28 +0000569
570 route_232_1_1_1.add_vpp_config()
571 route_232_1_1_1.update_entry_flags(
572 MRouteEntryFlags.MFIB_ENTRY_FLAG_CONNECTED)
573
574 #
575 # Now the (*,G) is present, send from connected source
576 #
577 tx = self._mcast_connected_send_stream("232.1.1.1")
578
579 #
580 # Constrct a representation of the signal we expect on pg0
581 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800582 signal_232_1_1_1_itf_0 = VppMFibSignal(self,
583 route_232_1_1_1,
584 self.pg0.sw_if_index,
585 tx[0])
Neale Ranns32e1c012016-11-22 17:07:28 +0000586
587 #
588 # read the only expected signal
589 #
590 signals = self.vapi.mfib_signal_dump()
591
592 self.assertEqual(1, len(signals))
593
594 signal_232_1_1_1_itf_0.compare(signals[0])
595
596 #
597 # reading the signal allows for the generation of another
598 # so send more packets and expect the next signal
599 #
600 tx = self._mcast_connected_send_stream("232.1.1.1")
601
602 signals = self.vapi.mfib_signal_dump()
603 self.assertEqual(1, len(signals))
604 signal_232_1_1_1_itf_0.compare(signals[0])
605
606 #
607 # A Second entry with connected check
608 # one accepting interface, pg0, 1 forwarding interfaces
609 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800610 route_232_1_1_2 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000611 self,
612 "0.0.0.0",
613 "232.1.1.2", 32,
614 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800615 [VppMRoutePath(self.pg0.sw_if_index,
616 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
617 VppMRoutePath(self.pg1.sw_if_index,
618 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
Neale Ranns32e1c012016-11-22 17:07:28 +0000619
620 route_232_1_1_2.add_vpp_config()
621 route_232_1_1_2.update_entry_flags(
622 MRouteEntryFlags.MFIB_ENTRY_FLAG_CONNECTED)
623
624 #
625 # Send traffic to both entries. One read should net us two signals
626 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800627 signal_232_1_1_2_itf_0 = VppMFibSignal(self,
628 route_232_1_1_2,
629 self.pg0.sw_if_index,
630 tx[0])
Neale Ranns32e1c012016-11-22 17:07:28 +0000631 tx = self._mcast_connected_send_stream("232.1.1.1")
632 tx2 = self._mcast_connected_send_stream("232.1.1.2")
633
634 #
635 # read the only expected signal
636 #
637 signals = self.vapi.mfib_signal_dump()
638
639 self.assertEqual(2, len(signals))
640
641 signal_232_1_1_1_itf_0.compare(signals[1])
642 signal_232_1_1_2_itf_0.compare(signals[0])
643
Neale Rannsd792d9c2017-10-21 10:53:20 -0700644 route_232_1_1_1.update_entry_flags(
645 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE)
646 route_232_1_1_2.update_entry_flags(
647 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE)
Neale Ranns32e1c012016-11-22 17:07:28 +0000648
649 def test_ip_mcast_signal(self):
650 """ IP Multicast Signal """
651
652 #
653 # A (*,G).
654 # one accepting interface, pg0, 1 forwarding interfaces
655 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800656 route_232_1_1_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000657 self,
658 "0.0.0.0",
659 "232.1.1.1", 32,
660 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800661 [VppMRoutePath(self.pg0.sw_if_index,
662 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
663 VppMRoutePath(self.pg1.sw_if_index,
664 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
Neale Ranns32e1c012016-11-22 17:07:28 +0000665
666 route_232_1_1_1.add_vpp_config()
667 route_232_1_1_1.update_entry_flags(
668 MRouteEntryFlags.MFIB_ENTRY_FLAG_SIGNAL)
669
670 #
671 # Now the (*,G) is present, send from connected source
672 #
673 tx = self._mcast_connected_send_stream("232.1.1.1")
674
675 #
676 # Constrct a representation of the signal we expect on pg0
677 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800678 signal_232_1_1_1_itf_0 = VppMFibSignal(self,
679 route_232_1_1_1,
680 self.pg0.sw_if_index,
681 tx[0])
Neale Ranns32e1c012016-11-22 17:07:28 +0000682
683 #
684 # read the only expected signal
685 #
686 signals = self.vapi.mfib_signal_dump()
687
688 self.assertEqual(1, len(signals))
689
690 signal_232_1_1_1_itf_0.compare(signals[0])
691
692 #
693 # reading the signal allows for the generation of another
694 # so send more packets and expect the next signal
695 #
696 tx = self._mcast_connected_send_stream("232.1.1.1")
697
698 signals = self.vapi.mfib_signal_dump()
699 self.assertEqual(1, len(signals))
700 signal_232_1_1_1_itf_0.compare(signals[0])
701
702 #
703 # Set the negate-signal on the accepting interval - the signals
704 # should stop
705 #
706 route_232_1_1_1.update_path_flags(
707 self.pg0.sw_if_index,
708 (MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT |
709 MRouteItfFlags.MFIB_ITF_FLAG_NEGATE_SIGNAL))
710
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800711 self.vapi.cli("clear trace")
Neale Ranns32e1c012016-11-22 17:07:28 +0000712 tx = self._mcast_connected_send_stream("232.1.1.1")
713
714 signals = self.vapi.mfib_signal_dump()
715 self.assertEqual(0, len(signals))
716
717 #
718 # Clear the SIGNAL flag on the entry and the signals should
719 # come back since the interface is still NEGATE-SIGNAL
720 #
721 route_232_1_1_1.update_entry_flags(
722 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE)
723
724 tx = self._mcast_connected_send_stream("232.1.1.1")
725
726 signals = self.vapi.mfib_signal_dump()
727 self.assertEqual(1, len(signals))
728 signal_232_1_1_1_itf_0.compare(signals[0])
729
730 #
731 # Lastly remove the NEGATE-SIGNAL from the interface and the
732 # signals should stop
733 #
734 route_232_1_1_1.update_path_flags(self.pg0.sw_if_index,
735 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT)
736
737 tx = self._mcast_connected_send_stream("232.1.1.1")
738 signals = self.vapi.mfib_signal_dump()
739 self.assertEqual(0, len(signals))
740
Neale Ranns15002542017-09-10 04:39:11 -0700741 def test_ip_mcast_vrf(self):
742 """ IP Multicast Replication in non-default table"""
743
744 #
745 # An (S,G).
746 # one accepting interface, pg0, 2 forwarding interfaces
747 #
748 route_1_1_1_1_232_1_1_1 = VppIpMRoute(
749 self,
750 "1.1.1.1",
751 "232.1.1.1", 64,
752 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
753 [VppMRoutePath(self.pg8.sw_if_index,
754 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
755 VppMRoutePath(self.pg1.sw_if_index,
756 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
757 VppMRoutePath(self.pg2.sw_if_index,
758 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)],
759 table_id=10)
760 route_1_1_1_1_232_1_1_1.add_vpp_config()
761
762 #
763 # a stream that matches the route for (1.1.1.1,232.1.1.1)
764 # small packets
765 #
766 self.vapi.cli("clear trace")
767 tx = self.create_stream_ip4(self.pg8, "1.1.1.1", "232.1.1.1")
768 self.pg8.add_stream(tx)
769
770 self.pg_enable_capture(self.pg_interfaces)
771 self.pg_start()
772
773 # We expect replications on Pg1 & 2
774 self.verify_capture_ip4(self.pg1, tx)
775 self.verify_capture_ip4(self.pg2, tx)
776
777 def test_ip6_mcast_vrf(self):
778 """ IPv6 Multicast Replication in non-default table"""
779
780 #
781 # An (S,G).
782 # one accepting interface, pg0, 2 forwarding interfaces
783 #
784 route_2001_ff01_1 = VppIpMRoute(
785 self,
786 "2001::1",
787 "ff01::1", 256,
788 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
789 [VppMRoutePath(self.pg8.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700790 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT,
791 proto=DpoProto.DPO_PROTO_IP6),
Neale Ranns15002542017-09-10 04:39:11 -0700792 VppMRoutePath(self.pg1.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700793 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
794 proto=DpoProto.DPO_PROTO_IP6),
Neale Ranns15002542017-09-10 04:39:11 -0700795 VppMRoutePath(self.pg2.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700796 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
797 proto=DpoProto.DPO_PROTO_IP6)],
Neale Ranns15002542017-09-10 04:39:11 -0700798 table_id=10,
799 is_ip6=1)
800 route_2001_ff01_1.add_vpp_config()
801
802 #
803 # a stream that matches the route for (2001::1, ff00::1)
804 #
805 self.vapi.cli("clear trace")
806 tx = self.create_stream_ip6(self.pg8, "2001::1", "ff01::1")
807 self.pg8.add_stream(tx)
808
809 self.pg_enable_capture(self.pg_interfaces)
810 self.pg_start()
811
812 # We expect replications on Pg1, 2,
813 self.verify_capture_ip6(self.pg1, tx)
814 self.verify_capture_ip6(self.pg2, tx)
Neale Ranns32e1c012016-11-22 17:07:28 +0000815
Neale Rannscf3561b2017-12-13 01:44:25 -0800816 def test_bidir(self):
817 """ IP Multicast Bi-directional """
818
819 #
820 # A (*,G). The set of accepting interfaces matching the forwarding
821 #
822 route_232_1_1_1 = VppIpMRoute(
823 self,
824 "0.0.0.0",
825 "232.1.1.1", 32,
826 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
827 [VppMRoutePath(self.pg0.sw_if_index,
828 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT |
829 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
830 VppMRoutePath(self.pg1.sw_if_index,
831 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT |
832 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
833 VppMRoutePath(self.pg2.sw_if_index,
834 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT |
835 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
836 VppMRoutePath(self.pg3.sw_if_index,
837 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT |
838 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
839 route_232_1_1_1.add_vpp_config()
840
841 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.1")
842 self.pg0.add_stream(tx)
843
844 self.pg_enable_capture(self.pg_interfaces)
845 self.pg_start()
846
847 # We expect replications on Pg1, 2, 3, but not on pg0
848 self.verify_capture_ip4(self.pg1, tx)
849 self.verify_capture_ip4(self.pg2, tx)
850 self.verify_capture_ip4(self.pg3, tx)
851 self.pg0.assert_nothing_captured(
852 remark="IP multicast packets forwarded on PG0")
853
854
Neale Ranns32e1c012016-11-22 17:07:28 +0000855if __name__ == '__main__':
856 unittest.main(testRunner=VppTestRunner)