blob: 8ca92df26b259b06671bc89bb2d33ba7415680cb [file] [log] [blame]
Neale Ranns32e1c012016-11-22 17:07:28 +00001#!/usr/bin/env python
2
3import unittest
4
5from framework import VppTestCase, VppTestRunner
6from vpp_sub_interface import VppSubInterface, VppDot1QSubint, VppDot1ADSubint
Neale Ranns180279b2017-03-16 15:49:09 -04007from vpp_ip_route import VppIpMRoute, VppMRoutePath, VppMFibSignal, \
Neale Rannsd792d9c2017-10-21 10:53:20 -07008 MRouteItfFlags, MRouteEntryFlags, VppIpTable, DpoProto
Neale Ranns32e1c012016-11-22 17:07:28 +00009
10from scapy.packet import Raw
11from scapy.layers.l2 import Ether
Neale Ranns9d676af2017-03-15 01:28:31 -070012from scapy.layers.inet import IP, UDP, getmacbyip, ICMP
Neale Ranns32e1c012016-11-22 17:07:28 +000013from scapy.layers.inet6 import IPv6, getmacbyip6
14from util import ppp
15
Neale Ranns9bea8fb2017-02-03 04:34:01 -080016#
17# The number of packets sent is set to 90 so that when we replicate more than 3
18# times, which we do for some entries, we will generate more than 256 packets
Neale Rannsaaa396a2017-02-05 09:12:02 -080019# to the next node in the VLIB graph. Thus we are testing the code's
20# correctness handling this over-flow
Neale Ranns9bea8fb2017-02-03 04:34:01 -080021#
22N_PKTS_IN_STREAM = 90
23
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 Rannsc2aad532017-05-30 09:53:52 -0700113 def verify_capture_ip4(self, rx_if, sent):
114 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
131 # check the MAC address on the RX'd packet is correctly formed
132 self.assertEqual(eth.dst, getmacbyip(rx_ip.dst))
133
134 self.assertEqual(rx_ip.src, tx_ip.src)
135 self.assertEqual(rx_ip.dst, tx_ip.dst)
136 # IP processing post pop has decremented the TTL
137 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
138
139 except:
140 raise
141
Neale Rannsc2aad532017-05-30 09:53:52 -0700142 def verify_capture_ip6(self, rx_if, sent):
143 capture = rx_if.get_capture(len(sent))
Neale Ranns32e1c012016-11-22 17:07:28 +0000144
145 self.assertEqual(len(capture), len(sent))
146
147 for i in range(len(capture)):
148 tx = sent[i]
149 rx = capture[i]
150
Neale Ranns32e1c012016-11-22 17:07:28 +0000151 eth = rx[Ether]
152 self.assertEqual(eth.type, 0x86DD)
153
154 tx_ip = tx[IPv6]
155 rx_ip = rx[IPv6]
156
157 # check the MAC address on the RX'd packet is correctly formed
158 self.assertEqual(eth.dst, getmacbyip6(rx_ip.dst))
159
160 self.assertEqual(rx_ip.src, tx_ip.src)
161 self.assertEqual(rx_ip.dst, tx_ip.dst)
162 # IP processing post pop has decremented the TTL
163 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
164
165 def test_ip_mcast(self):
166 """ IP Multicast Replication """
167
168 #
169 # a stream that matches the default route. gets dropped.
170 #
171 self.vapi.cli("clear trace")
172 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.1")
173 self.pg0.add_stream(tx)
174
175 self.pg_enable_capture(self.pg_interfaces)
176 self.pg_start()
177
178 self.pg0.assert_nothing_captured(
179 remark="IP multicast packets forwarded on default route")
180
181 #
182 # A (*,G).
Neale Ranns37be7362017-02-21 17:30:26 -0800183 # one accepting interface, pg0, 7 forwarding interfaces
184 # many forwarding interfaces test the case where the replicare DPO
185 # needs to use extra cache lines for the buckets.
Neale Ranns32e1c012016-11-22 17:07:28 +0000186 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800187 route_232_1_1_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000188 self,
189 "0.0.0.0",
190 "232.1.1.1", 32,
191 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800192 [VppMRoutePath(self.pg0.sw_if_index,
193 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
194 VppMRoutePath(self.pg1.sw_if_index,
195 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
196 VppMRoutePath(self.pg2.sw_if_index,
197 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
198 VppMRoutePath(self.pg3.sw_if_index,
Neale Ranns37be7362017-02-21 17:30:26 -0800199 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
200 VppMRoutePath(self.pg4.sw_if_index,
201 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
202 VppMRoutePath(self.pg5.sw_if_index,
203 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
204 VppMRoutePath(self.pg6.sw_if_index,
205 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
206 VppMRoutePath(self.pg7.sw_if_index,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800207 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
Neale Ranns32e1c012016-11-22 17:07:28 +0000208 route_232_1_1_1.add_vpp_config()
209
210 #
211 # An (S,G).
212 # one accepting interface, pg0, 2 forwarding interfaces
213 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800214 route_1_1_1_1_232_1_1_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000215 self,
216 "1.1.1.1",
217 "232.1.1.1", 64,
218 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800219 [VppMRoutePath(self.pg0.sw_if_index,
220 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
221 VppMRoutePath(self.pg1.sw_if_index,
222 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
223 VppMRoutePath(self.pg2.sw_if_index,
224 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
Neale Ranns32e1c012016-11-22 17:07:28 +0000225 route_1_1_1_1_232_1_1_1.add_vpp_config()
226
227 #
228 # An (*,G/m).
229 # one accepting interface, pg0, 1 forwarding interfaces
230 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800231 route_232 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000232 self,
233 "0.0.0.0",
234 "232.0.0.0", 8,
235 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800236 [VppMRoutePath(self.pg0.sw_if_index,
237 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
238 VppMRoutePath(self.pg1.sw_if_index,
239 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
Neale Ranns32e1c012016-11-22 17:07:28 +0000240 route_232.add_vpp_config()
241
242 #
243 # a stream that matches the route for (1.1.1.1,232.1.1.1)
Neale Ranns9d676af2017-03-15 01:28:31 -0700244 # small packets
Neale Ranns32e1c012016-11-22 17:07:28 +0000245 #
246 self.vapi.cli("clear trace")
247 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.1")
248 self.pg0.add_stream(tx)
249
250 self.pg_enable_capture(self.pg_interfaces)
251 self.pg_start()
252
Neale Ranns37be7362017-02-21 17:30:26 -0800253 # We expect replications on Pg1->7
Neale Ranns32e1c012016-11-22 17:07:28 +0000254 self.verify_capture_ip4(self.pg1, tx)
255 self.verify_capture_ip4(self.pg2, tx)
256
257 # no replications on Pg0
258 self.pg0.assert_nothing_captured(
259 remark="IP multicast packets forwarded on PG0")
260 self.pg3.assert_nothing_captured(
261 remark="IP multicast packets forwarded on PG3")
262
263 #
Neale Ranns9d676af2017-03-15 01:28:31 -0700264 # a stream that matches the route for (1.1.1.1,232.1.1.1)
265 # large packets
266 #
267 self.vapi.cli("clear trace")
268 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.1",
269 payload_size=1024)
270 self.pg0.add_stream(tx)
271
272 self.pg_enable_capture(self.pg_interfaces)
273 self.pg_start()
274
275 # We expect replications on Pg1->7
276 self.verify_capture_ip4(self.pg1, tx)
277 self.verify_capture_ip4(self.pg2, tx)
Neale Ranns9d676af2017-03-15 01:28:31 -0700278
279 # no replications on Pg0
280 self.pg0.assert_nothing_captured(
281 remark="IP multicast packets forwarded on PG0")
282 self.pg3.assert_nothing_captured(
283 remark="IP multicast packets forwarded on PG3")
284
285 #
Neale Ranns32e1c012016-11-22 17:07:28 +0000286 # a stream that matches the route for (*,232.0.0.0/8)
287 # Send packets with the 9th bit set so we test the correct clearing
288 # of that bit in the mac rewrite
289 #
290 self.vapi.cli("clear trace")
291 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.255.255.255")
292 self.pg0.add_stream(tx)
293
294 self.pg_enable_capture(self.pg_interfaces)
295 self.pg_start()
296
297 # We expect replications on Pg1 only
298 self.verify_capture_ip4(self.pg1, tx)
299
300 # no replications on Pg0, Pg2 not Pg3
301 self.pg0.assert_nothing_captured(
302 remark="IP multicast packets forwarded on PG0")
303 self.pg2.assert_nothing_captured(
304 remark="IP multicast packets forwarded on PG2")
305 self.pg3.assert_nothing_captured(
306 remark="IP multicast packets forwarded on PG3")
307
308 #
309 # a stream that matches the route for (*,232.1.1.1)
310 #
311 self.vapi.cli("clear trace")
312 tx = self.create_stream_ip4(self.pg0, "1.1.1.2", "232.1.1.1")
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, 2, 3.
319 self.verify_capture_ip4(self.pg1, tx)
320 self.verify_capture_ip4(self.pg2, tx)
321 self.verify_capture_ip4(self.pg3, tx)
Neale Rannsc2aad532017-05-30 09:53:52 -0700322 self.verify_capture_ip4(self.pg4, tx)
323 self.verify_capture_ip4(self.pg5, tx)
324 self.verify_capture_ip4(self.pg6, tx)
325 self.verify_capture_ip4(self.pg7, tx)
Neale Ranns32e1c012016-11-22 17:07:28 +0000326
Neale Ranns32e1c012016-11-22 17:07:28 +0000327 def test_ip6_mcast(self):
328 """ IPv6 Multicast Replication """
329
330 #
331 # a stream that matches the default route. gets dropped.
332 #
333 self.vapi.cli("clear trace")
334 tx = self.create_stream_ip6(self.pg0, "2001::1", "ff01::1")
335 self.pg0.add_stream(tx)
336
337 self.pg_enable_capture(self.pg_interfaces)
338 self.pg_start()
339
340 self.pg0.assert_nothing_captured(
341 remark="IPv6 multicast packets forwarded on default route")
342
343 #
344 # A (*,G).
345 # one accepting interface, pg0, 3 forwarding interfaces
346 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800347 route_ff01_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000348 self,
349 "::",
350 "ff01::1", 128,
351 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800352 [VppMRoutePath(self.pg0.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700353 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT,
354 proto=DpoProto.DPO_PROTO_IP6),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800355 VppMRoutePath(self.pg1.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700356 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
357 proto=DpoProto.DPO_PROTO_IP6),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800358 VppMRoutePath(self.pg2.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700359 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
360 proto=DpoProto.DPO_PROTO_IP6),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800361 VppMRoutePath(self.pg3.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700362 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
363 proto=DpoProto.DPO_PROTO_IP6)],
Neale Ranns32e1c012016-11-22 17:07:28 +0000364 is_ip6=1)
365 route_ff01_1.add_vpp_config()
366
367 #
368 # An (S,G).
369 # one accepting interface, pg0, 2 forwarding interfaces
370 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800371 route_2001_ff01_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000372 self,
373 "2001::1",
374 "ff01::1", 256,
375 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800376 [VppMRoutePath(self.pg0.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700377 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT,
378 proto=DpoProto.DPO_PROTO_IP6),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800379 VppMRoutePath(self.pg1.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700380 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
381 proto=DpoProto.DPO_PROTO_IP6),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800382 VppMRoutePath(self.pg2.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700383 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
384 proto=DpoProto.DPO_PROTO_IP6)],
Neale Ranns32e1c012016-11-22 17:07:28 +0000385 is_ip6=1)
386 route_2001_ff01_1.add_vpp_config()
387
388 #
389 # An (*,G/m).
390 # one accepting interface, pg0, 1 forwarding interface
391 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800392 route_ff01 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000393 self,
394 "::",
395 "ff01::", 16,
396 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800397 [VppMRoutePath(self.pg0.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700398 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT,
399 proto=DpoProto.DPO_PROTO_IP6),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800400 VppMRoutePath(self.pg1.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700401 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
402 proto=DpoProto.DPO_PROTO_IP6)],
Neale Ranns32e1c012016-11-22 17:07:28 +0000403 is_ip6=1)
404 route_ff01.add_vpp_config()
405
406 #
407 # a stream that matches the route for (*, ff01::/16)
408 #
409 self.vapi.cli("clear trace")
410 tx = self.create_stream_ip6(self.pg0, "2002::1", "ff01:2::255")
411 self.pg0.add_stream(tx)
412
413 self.pg_enable_capture(self.pg_interfaces)
414 self.pg_start()
415
416 # We expect replications on Pg1
417 self.verify_capture_ip6(self.pg1, tx)
418
419 # no replications on Pg0, Pg3
420 self.pg0.assert_nothing_captured(
421 remark="IP multicast packets forwarded on PG0")
422 self.pg2.assert_nothing_captured(
423 remark="IP multicast packets forwarded on PG2")
424 self.pg3.assert_nothing_captured(
425 remark="IP multicast packets forwarded on PG3")
426
427 #
Neale Rannsc2aad532017-05-30 09:53:52 -0700428 # Bounce the interface and it should still work
429 #
430 self.pg1.admin_down()
431 self.pg0.add_stream(tx)
432 self.pg_enable_capture(self.pg_interfaces)
433 self.pg_start()
434 self.pg1.assert_nothing_captured(
435 remark="IP multicast packets forwarded on down PG1")
436
437 self.pg1.admin_up()
438 self.pg0.add_stream(tx)
439 self.pg_enable_capture(self.pg_interfaces)
440 self.pg_start()
441 self.verify_capture_ip6(self.pg1, tx)
442
443 #
Neale Ranns32e1c012016-11-22 17:07:28 +0000444 # a stream that matches the route for (*,ff01::1)
445 #
446 self.vapi.cli("clear trace")
447 tx = self.create_stream_ip6(self.pg0, "2002::2", "ff01::1")
448 self.pg0.add_stream(tx)
449
450 self.pg_enable_capture(self.pg_interfaces)
451 self.pg_start()
452
453 # We expect replications on Pg1, 2, 3.
454 self.verify_capture_ip6(self.pg1, tx)
455 self.verify_capture_ip6(self.pg2, tx)
456 self.verify_capture_ip6(self.pg3, tx)
457
458 # no replications on Pg0
459 self.pg0.assert_nothing_captured(
460 remark="IPv6 multicast packets forwarded on PG0")
461
462 #
463 # a stream that matches the route for (2001::1, ff00::1)
464 #
465 self.vapi.cli("clear trace")
466 tx = self.create_stream_ip6(self.pg0, "2001::1", "ff01::1")
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, 2,
473 self.verify_capture_ip6(self.pg1, tx)
474 self.verify_capture_ip6(self.pg2, tx)
475
476 # no replications on Pg0, Pg3
477 self.pg0.assert_nothing_captured(
478 remark="IP multicast packets forwarded on PG0")
479 self.pg3.assert_nothing_captured(
480 remark="IP multicast packets forwarded on PG3")
481
Neale Ranns32e1c012016-11-22 17:07:28 +0000482 def _mcast_connected_send_stream(self, dst_ip):
483 self.vapi.cli("clear trace")
484 tx = self.create_stream_ip4(self.pg0,
485 self.pg0.remote_ip4,
486 dst_ip)
487 self.pg0.add_stream(tx)
488
489 self.pg_enable_capture(self.pg_interfaces)
490 self.pg_start()
491
492 # We expect replications on Pg1.
493 self.verify_capture_ip4(self.pg1, tx)
494
495 return tx
496
497 def test_ip_mcast_connected(self):
498 """ IP Multicast Connected Source check """
499
500 #
501 # A (*,G).
502 # one accepting interface, pg0, 1 forwarding interfaces
503 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800504 route_232_1_1_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000505 self,
506 "0.0.0.0",
507 "232.1.1.1", 32,
508 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800509 [VppMRoutePath(self.pg0.sw_if_index,
510 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
511 VppMRoutePath(self.pg1.sw_if_index,
512 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
Neale Ranns32e1c012016-11-22 17:07:28 +0000513
514 route_232_1_1_1.add_vpp_config()
515 route_232_1_1_1.update_entry_flags(
516 MRouteEntryFlags.MFIB_ENTRY_FLAG_CONNECTED)
517
518 #
519 # Now the (*,G) is present, send from connected source
520 #
521 tx = self._mcast_connected_send_stream("232.1.1.1")
522
523 #
524 # Constrct a representation of the signal we expect on pg0
525 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800526 signal_232_1_1_1_itf_0 = VppMFibSignal(self,
527 route_232_1_1_1,
528 self.pg0.sw_if_index,
529 tx[0])
Neale Ranns32e1c012016-11-22 17:07:28 +0000530
531 #
532 # read the only expected signal
533 #
534 signals = self.vapi.mfib_signal_dump()
535
536 self.assertEqual(1, len(signals))
537
538 signal_232_1_1_1_itf_0.compare(signals[0])
539
540 #
541 # reading the signal allows for the generation of another
542 # so send more packets and expect the next signal
543 #
544 tx = self._mcast_connected_send_stream("232.1.1.1")
545
546 signals = self.vapi.mfib_signal_dump()
547 self.assertEqual(1, len(signals))
548 signal_232_1_1_1_itf_0.compare(signals[0])
549
550 #
551 # A Second entry with connected check
552 # one accepting interface, pg0, 1 forwarding interfaces
553 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800554 route_232_1_1_2 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000555 self,
556 "0.0.0.0",
557 "232.1.1.2", 32,
558 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800559 [VppMRoutePath(self.pg0.sw_if_index,
560 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
561 VppMRoutePath(self.pg1.sw_if_index,
562 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
Neale Ranns32e1c012016-11-22 17:07:28 +0000563
564 route_232_1_1_2.add_vpp_config()
565 route_232_1_1_2.update_entry_flags(
566 MRouteEntryFlags.MFIB_ENTRY_FLAG_CONNECTED)
567
568 #
569 # Send traffic to both entries. One read should net us two signals
570 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800571 signal_232_1_1_2_itf_0 = VppMFibSignal(self,
572 route_232_1_1_2,
573 self.pg0.sw_if_index,
574 tx[0])
Neale Ranns32e1c012016-11-22 17:07:28 +0000575 tx = self._mcast_connected_send_stream("232.1.1.1")
576 tx2 = self._mcast_connected_send_stream("232.1.1.2")
577
578 #
579 # read the only expected signal
580 #
581 signals = self.vapi.mfib_signal_dump()
582
583 self.assertEqual(2, len(signals))
584
585 signal_232_1_1_1_itf_0.compare(signals[1])
586 signal_232_1_1_2_itf_0.compare(signals[0])
587
Neale Rannsd792d9c2017-10-21 10:53:20 -0700588 route_232_1_1_1.update_entry_flags(
589 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE)
590 route_232_1_1_2.update_entry_flags(
591 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE)
Neale Ranns32e1c012016-11-22 17:07:28 +0000592
593 def test_ip_mcast_signal(self):
594 """ IP Multicast Signal """
595
596 #
597 # A (*,G).
598 # one accepting interface, pg0, 1 forwarding interfaces
599 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800600 route_232_1_1_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000601 self,
602 "0.0.0.0",
603 "232.1.1.1", 32,
604 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800605 [VppMRoutePath(self.pg0.sw_if_index,
606 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
607 VppMRoutePath(self.pg1.sw_if_index,
608 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
Neale Ranns32e1c012016-11-22 17:07:28 +0000609
610 route_232_1_1_1.add_vpp_config()
611 route_232_1_1_1.update_entry_flags(
612 MRouteEntryFlags.MFIB_ENTRY_FLAG_SIGNAL)
613
614 #
615 # Now the (*,G) is present, send from connected source
616 #
617 tx = self._mcast_connected_send_stream("232.1.1.1")
618
619 #
620 # Constrct a representation of the signal we expect on pg0
621 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800622 signal_232_1_1_1_itf_0 = VppMFibSignal(self,
623 route_232_1_1_1,
624 self.pg0.sw_if_index,
625 tx[0])
Neale Ranns32e1c012016-11-22 17:07:28 +0000626
627 #
628 # read the only expected signal
629 #
630 signals = self.vapi.mfib_signal_dump()
631
632 self.assertEqual(1, len(signals))
633
634 signal_232_1_1_1_itf_0.compare(signals[0])
635
636 #
637 # reading the signal allows for the generation of another
638 # so send more packets and expect the next signal
639 #
640 tx = self._mcast_connected_send_stream("232.1.1.1")
641
642 signals = self.vapi.mfib_signal_dump()
643 self.assertEqual(1, len(signals))
644 signal_232_1_1_1_itf_0.compare(signals[0])
645
646 #
647 # Set the negate-signal on the accepting interval - the signals
648 # should stop
649 #
650 route_232_1_1_1.update_path_flags(
651 self.pg0.sw_if_index,
652 (MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT |
653 MRouteItfFlags.MFIB_ITF_FLAG_NEGATE_SIGNAL))
654
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800655 self.vapi.cli("clear trace")
Neale Ranns32e1c012016-11-22 17:07:28 +0000656 tx = self._mcast_connected_send_stream("232.1.1.1")
657
658 signals = self.vapi.mfib_signal_dump()
659 self.assertEqual(0, len(signals))
660
661 #
662 # Clear the SIGNAL flag on the entry and the signals should
663 # come back since the interface is still NEGATE-SIGNAL
664 #
665 route_232_1_1_1.update_entry_flags(
666 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE)
667
668 tx = self._mcast_connected_send_stream("232.1.1.1")
669
670 signals = self.vapi.mfib_signal_dump()
671 self.assertEqual(1, len(signals))
672 signal_232_1_1_1_itf_0.compare(signals[0])
673
674 #
675 # Lastly remove the NEGATE-SIGNAL from the interface and the
676 # signals should stop
677 #
678 route_232_1_1_1.update_path_flags(self.pg0.sw_if_index,
679 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT)
680
681 tx = self._mcast_connected_send_stream("232.1.1.1")
682 signals = self.vapi.mfib_signal_dump()
683 self.assertEqual(0, len(signals))
684
Neale Ranns15002542017-09-10 04:39:11 -0700685 def test_ip_mcast_vrf(self):
686 """ IP Multicast Replication in non-default table"""
687
688 #
689 # An (S,G).
690 # one accepting interface, pg0, 2 forwarding interfaces
691 #
692 route_1_1_1_1_232_1_1_1 = VppIpMRoute(
693 self,
694 "1.1.1.1",
695 "232.1.1.1", 64,
696 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
697 [VppMRoutePath(self.pg8.sw_if_index,
698 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
699 VppMRoutePath(self.pg1.sw_if_index,
700 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
701 VppMRoutePath(self.pg2.sw_if_index,
702 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)],
703 table_id=10)
704 route_1_1_1_1_232_1_1_1.add_vpp_config()
705
706 #
707 # a stream that matches the route for (1.1.1.1,232.1.1.1)
708 # small packets
709 #
710 self.vapi.cli("clear trace")
711 tx = self.create_stream_ip4(self.pg8, "1.1.1.1", "232.1.1.1")
712 self.pg8.add_stream(tx)
713
714 self.pg_enable_capture(self.pg_interfaces)
715 self.pg_start()
716
717 # We expect replications on Pg1 & 2
718 self.verify_capture_ip4(self.pg1, tx)
719 self.verify_capture_ip4(self.pg2, tx)
720
721 def test_ip6_mcast_vrf(self):
722 """ IPv6 Multicast Replication in non-default table"""
723
724 #
725 # An (S,G).
726 # one accepting interface, pg0, 2 forwarding interfaces
727 #
728 route_2001_ff01_1 = VppIpMRoute(
729 self,
730 "2001::1",
731 "ff01::1", 256,
732 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
733 [VppMRoutePath(self.pg8.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700734 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT,
735 proto=DpoProto.DPO_PROTO_IP6),
Neale Ranns15002542017-09-10 04:39:11 -0700736 VppMRoutePath(self.pg1.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700737 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
738 proto=DpoProto.DPO_PROTO_IP6),
Neale Ranns15002542017-09-10 04:39:11 -0700739 VppMRoutePath(self.pg2.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700740 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
741 proto=DpoProto.DPO_PROTO_IP6)],
Neale Ranns15002542017-09-10 04:39:11 -0700742 table_id=10,
743 is_ip6=1)
744 route_2001_ff01_1.add_vpp_config()
745
746 #
747 # a stream that matches the route for (2001::1, ff00::1)
748 #
749 self.vapi.cli("clear trace")
750 tx = self.create_stream_ip6(self.pg8, "2001::1", "ff01::1")
751 self.pg8.add_stream(tx)
752
753 self.pg_enable_capture(self.pg_interfaces)
754 self.pg_start()
755
756 # We expect replications on Pg1, 2,
757 self.verify_capture_ip6(self.pg1, tx)
758 self.verify_capture_ip6(self.pg2, tx)
Neale Ranns32e1c012016-11-22 17:07:28 +0000759
760if __name__ == '__main__':
761 unittest.main(testRunner=VppTestRunner)