blob: 017f0629cd25e10abc62bdcf8a6b31f8185e4422 [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#
Neale Rannscf3561b2017-12-13 01:44:25 -080017# The number of packets sent is set to 91 so that when we replicate more than 3
Neale Ranns9bea8fb2017-02-03 04:34:01 -080018# 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
Neale Rannscf3561b2017-12-13 01:44:25 -080020# correctness handling this over-flow.
21# It's also an odd number so we hit any single loops.
Neale Ranns9bea8fb2017-02-03 04:34:01 -080022#
Neale Rannscf3561b2017-12-13 01:44:25 -080023N_PKTS_IN_STREAM = 91
Neale Ranns9bea8fb2017-02-03 04:34:01 -080024
Neale Ranns32e1c012016-11-22 17:07:28 +000025
Neale Ranns5a8123b2017-01-26 01:18:23 -080026class TestMFIB(VppTestCase):
27 """ MFIB Test Case """
28
29 def setUp(self):
30 super(TestMFIB, self).setUp()
31
32 def test_mfib(self):
33 """ MFIB Unit Tests """
34 error = self.vapi.cli("test mfib")
35
36 if error:
37 self.logger.critical(error)
38 self.assertEqual(error.find("Failed"), -1)
39
40
Neale Ranns32e1c012016-11-22 17:07:28 +000041class TestIPMcast(VppTestCase):
42 """ IP Multicast Test Case """
43
44 def setUp(self):
45 super(TestIPMcast, self).setUp()
46
Neale Ranns37be7362017-02-21 17:30:26 -080047 # create 8 pg interfaces
Neale Ranns15002542017-09-10 04:39:11 -070048 self.create_pg_interfaces(range(9))
Neale Ranns32e1c012016-11-22 17:07:28 +000049
50 # setup interfaces
Neale Ranns15002542017-09-10 04:39:11 -070051 for i in self.pg_interfaces[:8]:
Neale Ranns32e1c012016-11-22 17:07:28 +000052 i.admin_up()
53 i.config_ip4()
54 i.config_ip6()
55 i.resolve_arp()
56 i.resolve_ndp()
57
Neale Ranns15002542017-09-10 04:39:11 -070058 # one more in a vrf
59 tbl4 = VppIpTable(self, 10)
60 tbl4.add_vpp_config()
61 self.pg8.set_table_ip4(10)
62 self.pg8.config_ip4()
63
64 tbl6 = VppIpTable(self, 10, is_ip6=1)
65 tbl6.add_vpp_config()
66 self.pg8.set_table_ip6(10)
67 self.pg8.config_ip6()
68
69 def tearDown(self):
70 for i in self.pg_interfaces:
71 i.unconfig_ip4()
72 i.unconfig_ip6()
73 i.admin_down()
74
75 self.pg8.set_table_ip4(0)
76 self.pg8.set_table_ip6(0)
77 super(TestIPMcast, self).tearDown()
78
Neale Ranns9d676af2017-03-15 01:28:31 -070079 def create_stream_ip4(self, src_if, src_ip, dst_ip, payload_size=0):
Neale Ranns32e1c012016-11-22 17:07:28 +000080 pkts = []
Neale Ranns9d676af2017-03-15 01:28:31 -070081 # default to small packet sizes
82 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
83 IP(src=src_ip, dst=dst_ip) /
84 UDP(sport=1234, dport=1234))
85 if not payload_size:
86 payload_size = 64 - len(p)
87 p = p / Raw('\xa5' * payload_size)
88
Neale Ranns9bea8fb2017-02-03 04:34:01 -080089 for i in range(0, N_PKTS_IN_STREAM):
Neale Ranns32e1c012016-11-22 17:07:28 +000090 pkts.append(p)
91 return pkts
92
93 def create_stream_ip6(self, src_if, src_ip, dst_ip):
94 pkts = []
Neale Ranns9bea8fb2017-02-03 04:34:01 -080095 for i in range(0, N_PKTS_IN_STREAM):
Neale Ranns32e1c012016-11-22 17:07:28 +000096 info = self.create_packet_info(src_if, src_if)
97 payload = self.info_to_payload(info)
98 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
99 IPv6(src=src_ip, dst=dst_ip) /
100 UDP(sport=1234, dport=1234) /
101 Raw(payload))
102 info.data = p.copy()
103 pkts.append(p)
104 return pkts
105
106 def verify_filter(self, capture, sent):
107 if not len(capture) == len(sent):
108 # filter out any IPv6 RAs from the captur
109 for p in capture:
110 if (p.haslayer(IPv6)):
111 capture.remove(p)
112 return capture
113
Neale Rannse821ab12017-06-01 07:45:05 -0700114 def verify_capture_ip4(self, rx_if, sent, dst_mac=None):
Neale Rannsc2aad532017-05-30 09:53:52 -0700115 rxd = rx_if.get_capture(len(sent))
Neale Ranns32e1c012016-11-22 17:07:28 +0000116
117 try:
118 capture = self.verify_filter(rxd, sent)
119
120 self.assertEqual(len(capture), len(sent))
121
122 for i in range(len(capture)):
123 tx = sent[i]
124 rx = capture[i]
125
Neale Ranns32e1c012016-11-22 17:07:28 +0000126 eth = rx[Ether]
127 self.assertEqual(eth.type, 0x800)
128
129 tx_ip = tx[IP]
130 rx_ip = rx[IP]
131
Neale Rannse821ab12017-06-01 07:45:05 -0700132 if dst_mac is None:
133 dst_mac = getmacbyip(rx_ip.dst)
134
Neale Ranns32e1c012016-11-22 17:07:28 +0000135 # check the MAC address on the RX'd packet is correctly formed
Neale Rannse821ab12017-06-01 07:45:05 -0700136 self.assertEqual(eth.dst, dst_mac)
Neale Ranns32e1c012016-11-22 17:07:28 +0000137
138 self.assertEqual(rx_ip.src, tx_ip.src)
139 self.assertEqual(rx_ip.dst, tx_ip.dst)
140 # IP processing post pop has decremented the TTL
141 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
142
143 except:
144 raise
145
Neale Rannsc2aad532017-05-30 09:53:52 -0700146 def verify_capture_ip6(self, rx_if, sent):
147 capture = rx_if.get_capture(len(sent))
Neale Ranns32e1c012016-11-22 17:07:28 +0000148
149 self.assertEqual(len(capture), len(sent))
150
151 for i in range(len(capture)):
152 tx = sent[i]
153 rx = capture[i]
154
Neale Ranns32e1c012016-11-22 17:07:28 +0000155 eth = rx[Ether]
156 self.assertEqual(eth.type, 0x86DD)
157
158 tx_ip = tx[IPv6]
159 rx_ip = rx[IPv6]
160
161 # check the MAC address on the RX'd packet is correctly formed
162 self.assertEqual(eth.dst, getmacbyip6(rx_ip.dst))
163
164 self.assertEqual(rx_ip.src, tx_ip.src)
165 self.assertEqual(rx_ip.dst, tx_ip.dst)
166 # IP processing post pop has decremented the TTL
167 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
168
169 def test_ip_mcast(self):
170 """ IP Multicast Replication """
171
172 #
173 # a stream that matches the default route. gets dropped.
174 #
175 self.vapi.cli("clear trace")
176 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.1")
177 self.pg0.add_stream(tx)
178
179 self.pg_enable_capture(self.pg_interfaces)
180 self.pg_start()
181
182 self.pg0.assert_nothing_captured(
183 remark="IP multicast packets forwarded on default route")
184
185 #
186 # A (*,G).
Neale Ranns37be7362017-02-21 17:30:26 -0800187 # one accepting interface, pg0, 7 forwarding interfaces
188 # many forwarding interfaces test the case where the replicare DPO
189 # needs to use extra cache lines for the buckets.
Neale Ranns32e1c012016-11-22 17:07:28 +0000190 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800191 route_232_1_1_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000192 self,
193 "0.0.0.0",
194 "232.1.1.1", 32,
195 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800196 [VppMRoutePath(self.pg0.sw_if_index,
197 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
198 VppMRoutePath(self.pg1.sw_if_index,
199 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
200 VppMRoutePath(self.pg2.sw_if_index,
201 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
202 VppMRoutePath(self.pg3.sw_if_index,
Neale Ranns37be7362017-02-21 17:30:26 -0800203 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
204 VppMRoutePath(self.pg4.sw_if_index,
205 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
206 VppMRoutePath(self.pg5.sw_if_index,
207 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
208 VppMRoutePath(self.pg6.sw_if_index,
209 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
210 VppMRoutePath(self.pg7.sw_if_index,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800211 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
Neale Ranns32e1c012016-11-22 17:07:28 +0000212 route_232_1_1_1.add_vpp_config()
213
214 #
215 # An (S,G).
216 # one accepting interface, pg0, 2 forwarding interfaces
217 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800218 route_1_1_1_1_232_1_1_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000219 self,
220 "1.1.1.1",
221 "232.1.1.1", 64,
222 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800223 [VppMRoutePath(self.pg0.sw_if_index,
224 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
225 VppMRoutePath(self.pg1.sw_if_index,
226 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
227 VppMRoutePath(self.pg2.sw_if_index,
228 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
Neale Ranns32e1c012016-11-22 17:07:28 +0000229 route_1_1_1_1_232_1_1_1.add_vpp_config()
230
231 #
Neale Rannse821ab12017-06-01 07:45:05 -0700232 # An (S,G).
233 # one accepting interface, pg0, 2 forwarding interfaces
234 # that use unicast next-hops
235 #
236 route_1_1_1_1_232_1_1_2 = VppIpMRoute(
237 self,
238 "1.1.1.1",
239 "232.1.1.2", 64,
240 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
241 [VppMRoutePath(self.pg0.sw_if_index,
242 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
243 VppMRoutePath(self.pg1.sw_if_index,
244 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
245 nh=self.pg1.remote_ip4),
246 VppMRoutePath(self.pg2.sw_if_index,
247 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
248 nh=self.pg2.remote_ip4)])
249 route_1_1_1_1_232_1_1_2.add_vpp_config()
250
251 #
Neale Ranns32e1c012016-11-22 17:07:28 +0000252 # An (*,G/m).
253 # one accepting interface, pg0, 1 forwarding interfaces
254 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800255 route_232 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000256 self,
257 "0.0.0.0",
258 "232.0.0.0", 8,
259 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800260 [VppMRoutePath(self.pg0.sw_if_index,
261 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
262 VppMRoutePath(self.pg1.sw_if_index,
263 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
Neale Ranns32e1c012016-11-22 17:07:28 +0000264 route_232.add_vpp_config()
265
266 #
267 # a stream that matches the route for (1.1.1.1,232.1.1.1)
Neale Ranns9d676af2017-03-15 01:28:31 -0700268 # small packets
Neale Ranns32e1c012016-11-22 17:07:28 +0000269 #
270 self.vapi.cli("clear trace")
271 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.1")
272 self.pg0.add_stream(tx)
273
274 self.pg_enable_capture(self.pg_interfaces)
275 self.pg_start()
276
Neale Ranns37be7362017-02-21 17:30:26 -0800277 # We expect replications on Pg1->7
Neale Ranns32e1c012016-11-22 17:07:28 +0000278 self.verify_capture_ip4(self.pg1, tx)
279 self.verify_capture_ip4(self.pg2, tx)
280
281 # no replications on Pg0
282 self.pg0.assert_nothing_captured(
283 remark="IP multicast packets forwarded on PG0")
284 self.pg3.assert_nothing_captured(
285 remark="IP multicast packets forwarded on PG3")
286
287 #
Neale Ranns9d676af2017-03-15 01:28:31 -0700288 # a stream that matches the route for (1.1.1.1,232.1.1.1)
289 # large packets
290 #
291 self.vapi.cli("clear trace")
292 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.1",
293 payload_size=1024)
294 self.pg0.add_stream(tx)
295
296 self.pg_enable_capture(self.pg_interfaces)
297 self.pg_start()
298
299 # We expect replications on Pg1->7
300 self.verify_capture_ip4(self.pg1, tx)
301 self.verify_capture_ip4(self.pg2, tx)
Neale Ranns9d676af2017-03-15 01:28:31 -0700302
303 # no replications on Pg0
304 self.pg0.assert_nothing_captured(
305 remark="IP multicast packets forwarded on PG0")
306 self.pg3.assert_nothing_captured(
307 remark="IP multicast packets forwarded on PG3")
308
309 #
Neale Rannse821ab12017-06-01 07:45:05 -0700310 # a stream to the unicast next-hops
311 #
312 self.vapi.cli("clear trace")
313 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.2")
314 self.pg0.add_stream(tx)
315
316 self.pg_enable_capture(self.pg_interfaces)
317 self.pg_start()
318
319 # We expect replications on Pg1->7
320 self.verify_capture_ip4(self.pg1, tx, dst_mac=self.pg1.remote_mac)
321 self.verify_capture_ip4(self.pg2, tx, dst_mac=self.pg2.remote_mac)
322
323 # no replications on Pg0 nor pg3
324 self.pg0.assert_nothing_captured(
325 remark="IP multicast packets forwarded on PG0")
326 self.pg3.assert_nothing_captured(
327 remark="IP multicast packets forwarded on PG3")
328
329 #
Neale Ranns32e1c012016-11-22 17:07:28 +0000330 # a stream that matches the route for (*,232.0.0.0/8)
331 # Send packets with the 9th bit set so we test the correct clearing
332 # of that bit in the mac rewrite
333 #
334 self.vapi.cli("clear trace")
335 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.255.255.255")
336 self.pg0.add_stream(tx)
337
338 self.pg_enable_capture(self.pg_interfaces)
339 self.pg_start()
340
341 # We expect replications on Pg1 only
342 self.verify_capture_ip4(self.pg1, tx)
343
344 # no replications on Pg0, Pg2 not Pg3
345 self.pg0.assert_nothing_captured(
346 remark="IP multicast packets forwarded on PG0")
347 self.pg2.assert_nothing_captured(
348 remark="IP multicast packets forwarded on PG2")
349 self.pg3.assert_nothing_captured(
350 remark="IP multicast packets forwarded on PG3")
351
352 #
353 # a stream that matches the route for (*,232.1.1.1)
354 #
355 self.vapi.cli("clear trace")
356 tx = self.create_stream_ip4(self.pg0, "1.1.1.2", "232.1.1.1")
357 self.pg0.add_stream(tx)
358
359 self.pg_enable_capture(self.pg_interfaces)
360 self.pg_start()
361
Neale Rannse821ab12017-06-01 07:45:05 -0700362 # We expect replications on Pg1->7
Neale Ranns32e1c012016-11-22 17:07:28 +0000363 self.verify_capture_ip4(self.pg1, tx)
364 self.verify_capture_ip4(self.pg2, tx)
365 self.verify_capture_ip4(self.pg3, tx)
Neale Rannsc2aad532017-05-30 09:53:52 -0700366 self.verify_capture_ip4(self.pg4, tx)
367 self.verify_capture_ip4(self.pg5, tx)
368 self.verify_capture_ip4(self.pg6, tx)
369 self.verify_capture_ip4(self.pg7, tx)
Neale Ranns32e1c012016-11-22 17:07:28 +0000370
Neale Rannse821ab12017-06-01 07:45:05 -0700371 # no replications on Pg0
372 self.pg0.assert_nothing_captured(
373 remark="IP multicast packets forwarded on PG0")
374
Neale Ranns32e1c012016-11-22 17:07:28 +0000375 def test_ip6_mcast(self):
376 """ IPv6 Multicast Replication """
377
378 #
379 # a stream that matches the default route. gets dropped.
380 #
381 self.vapi.cli("clear trace")
382 tx = self.create_stream_ip6(self.pg0, "2001::1", "ff01::1")
383 self.pg0.add_stream(tx)
384
385 self.pg_enable_capture(self.pg_interfaces)
386 self.pg_start()
387
388 self.pg0.assert_nothing_captured(
389 remark="IPv6 multicast packets forwarded on default route")
390
391 #
392 # A (*,G).
393 # one accepting interface, pg0, 3 forwarding interfaces
394 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800395 route_ff01_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000396 self,
397 "::",
398 "ff01::1", 128,
399 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800400 [VppMRoutePath(self.pg0.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700401 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT,
402 proto=DpoProto.DPO_PROTO_IP6),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800403 VppMRoutePath(self.pg1.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700404 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
405 proto=DpoProto.DPO_PROTO_IP6),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800406 VppMRoutePath(self.pg2.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700407 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
408 proto=DpoProto.DPO_PROTO_IP6),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800409 VppMRoutePath(self.pg3.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700410 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
411 proto=DpoProto.DPO_PROTO_IP6)],
Neale Ranns32e1c012016-11-22 17:07:28 +0000412 is_ip6=1)
413 route_ff01_1.add_vpp_config()
414
415 #
416 # An (S,G).
417 # one accepting interface, pg0, 2 forwarding interfaces
418 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800419 route_2001_ff01_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000420 self,
421 "2001::1",
422 "ff01::1", 256,
423 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800424 [VppMRoutePath(self.pg0.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700425 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT,
426 proto=DpoProto.DPO_PROTO_IP6),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800427 VppMRoutePath(self.pg1.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700428 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
429 proto=DpoProto.DPO_PROTO_IP6),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800430 VppMRoutePath(self.pg2.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700431 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
432 proto=DpoProto.DPO_PROTO_IP6)],
Neale Ranns32e1c012016-11-22 17:07:28 +0000433 is_ip6=1)
434 route_2001_ff01_1.add_vpp_config()
435
436 #
437 # An (*,G/m).
438 # one accepting interface, pg0, 1 forwarding interface
439 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800440 route_ff01 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000441 self,
442 "::",
443 "ff01::", 16,
444 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800445 [VppMRoutePath(self.pg0.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700446 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT,
447 proto=DpoProto.DPO_PROTO_IP6),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800448 VppMRoutePath(self.pg1.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700449 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
450 proto=DpoProto.DPO_PROTO_IP6)],
Neale Ranns32e1c012016-11-22 17:07:28 +0000451 is_ip6=1)
452 route_ff01.add_vpp_config()
453
454 #
455 # a stream that matches the route for (*, ff01::/16)
Neale Rannsce111d22018-01-23 08:38:50 -0800456 # sent on the non-accepting interface
457 #
458 self.vapi.cli("clear trace")
459 tx = self.create_stream_ip6(self.pg1, "2002::1", "ff01:2::255")
460 self.send_and_assert_no_replies(self.pg1, tx, "RPF miss")
461
462 #
463 # a stream that matches the route for (*, ff01::/16)
464 # sent on the accepting interface
Neale Ranns32e1c012016-11-22 17:07:28 +0000465 #
466 self.vapi.cli("clear trace")
467 tx = self.create_stream_ip6(self.pg0, "2002::1", "ff01:2::255")
468 self.pg0.add_stream(tx)
469
470 self.pg_enable_capture(self.pg_interfaces)
471 self.pg_start()
472
473 # We expect replications on Pg1
474 self.verify_capture_ip6(self.pg1, tx)
475
476 # no replications on Pg0, Pg3
477 self.pg0.assert_nothing_captured(
478 remark="IP multicast packets forwarded on PG0")
479 self.pg2.assert_nothing_captured(
480 remark="IP multicast packets forwarded on PG2")
481 self.pg3.assert_nothing_captured(
482 remark="IP multicast packets forwarded on PG3")
483
484 #
Neale Rannsc2aad532017-05-30 09:53:52 -0700485 # Bounce the interface and it should still work
486 #
487 self.pg1.admin_down()
488 self.pg0.add_stream(tx)
489 self.pg_enable_capture(self.pg_interfaces)
490 self.pg_start()
491 self.pg1.assert_nothing_captured(
492 remark="IP multicast packets forwarded on down PG1")
493
494 self.pg1.admin_up()
495 self.pg0.add_stream(tx)
496 self.pg_enable_capture(self.pg_interfaces)
497 self.pg_start()
498 self.verify_capture_ip6(self.pg1, tx)
499
500 #
Neale Ranns32e1c012016-11-22 17:07:28 +0000501 # a stream that matches the route for (*,ff01::1)
502 #
503 self.vapi.cli("clear trace")
504 tx = self.create_stream_ip6(self.pg0, "2002::2", "ff01::1")
505 self.pg0.add_stream(tx)
506
507 self.pg_enable_capture(self.pg_interfaces)
508 self.pg_start()
509
510 # We expect replications on Pg1, 2, 3.
511 self.verify_capture_ip6(self.pg1, tx)
512 self.verify_capture_ip6(self.pg2, tx)
513 self.verify_capture_ip6(self.pg3, tx)
514
515 # no replications on Pg0
516 self.pg0.assert_nothing_captured(
517 remark="IPv6 multicast packets forwarded on PG0")
518
519 #
520 # a stream that matches the route for (2001::1, ff00::1)
521 #
522 self.vapi.cli("clear trace")
523 tx = self.create_stream_ip6(self.pg0, "2001::1", "ff01::1")
524 self.pg0.add_stream(tx)
525
526 self.pg_enable_capture(self.pg_interfaces)
527 self.pg_start()
528
529 # We expect replications on Pg1, 2,
530 self.verify_capture_ip6(self.pg1, tx)
531 self.verify_capture_ip6(self.pg2, tx)
532
533 # no replications on Pg0, Pg3
534 self.pg0.assert_nothing_captured(
535 remark="IP multicast packets forwarded on PG0")
536 self.pg3.assert_nothing_captured(
537 remark="IP multicast packets forwarded on PG3")
538
Neale Ranns32e1c012016-11-22 17:07:28 +0000539 def _mcast_connected_send_stream(self, dst_ip):
540 self.vapi.cli("clear trace")
541 tx = self.create_stream_ip4(self.pg0,
542 self.pg0.remote_ip4,
543 dst_ip)
544 self.pg0.add_stream(tx)
545
546 self.pg_enable_capture(self.pg_interfaces)
547 self.pg_start()
548
549 # We expect replications on Pg1.
550 self.verify_capture_ip4(self.pg1, tx)
551
552 return tx
553
554 def test_ip_mcast_connected(self):
555 """ IP Multicast Connected Source check """
556
557 #
558 # A (*,G).
559 # one accepting interface, pg0, 1 forwarding interfaces
560 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800561 route_232_1_1_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000562 self,
563 "0.0.0.0",
564 "232.1.1.1", 32,
565 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800566 [VppMRoutePath(self.pg0.sw_if_index,
567 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
568 VppMRoutePath(self.pg1.sw_if_index,
569 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
Neale Ranns32e1c012016-11-22 17:07:28 +0000570
571 route_232_1_1_1.add_vpp_config()
572 route_232_1_1_1.update_entry_flags(
573 MRouteEntryFlags.MFIB_ENTRY_FLAG_CONNECTED)
574
575 #
576 # Now the (*,G) is present, send from connected source
577 #
578 tx = self._mcast_connected_send_stream("232.1.1.1")
579
580 #
581 # Constrct a representation of the signal we expect on pg0
582 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800583 signal_232_1_1_1_itf_0 = VppMFibSignal(self,
584 route_232_1_1_1,
585 self.pg0.sw_if_index,
586 tx[0])
Neale Ranns32e1c012016-11-22 17:07:28 +0000587
588 #
589 # read the only expected signal
590 #
591 signals = self.vapi.mfib_signal_dump()
592
593 self.assertEqual(1, len(signals))
594
595 signal_232_1_1_1_itf_0.compare(signals[0])
596
597 #
598 # reading the signal allows for the generation of another
599 # so send more packets and expect the next signal
600 #
601 tx = self._mcast_connected_send_stream("232.1.1.1")
602
603 signals = self.vapi.mfib_signal_dump()
604 self.assertEqual(1, len(signals))
605 signal_232_1_1_1_itf_0.compare(signals[0])
606
607 #
608 # A Second entry with connected check
609 # one accepting interface, pg0, 1 forwarding interfaces
610 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800611 route_232_1_1_2 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000612 self,
613 "0.0.0.0",
614 "232.1.1.2", 32,
615 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800616 [VppMRoutePath(self.pg0.sw_if_index,
617 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
618 VppMRoutePath(self.pg1.sw_if_index,
619 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
Neale Ranns32e1c012016-11-22 17:07:28 +0000620
621 route_232_1_1_2.add_vpp_config()
622 route_232_1_1_2.update_entry_flags(
623 MRouteEntryFlags.MFIB_ENTRY_FLAG_CONNECTED)
624
625 #
626 # Send traffic to both entries. One read should net us two signals
627 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800628 signal_232_1_1_2_itf_0 = VppMFibSignal(self,
629 route_232_1_1_2,
630 self.pg0.sw_if_index,
631 tx[0])
Neale Ranns32e1c012016-11-22 17:07:28 +0000632 tx = self._mcast_connected_send_stream("232.1.1.1")
633 tx2 = self._mcast_connected_send_stream("232.1.1.2")
634
635 #
636 # read the only expected signal
637 #
638 signals = self.vapi.mfib_signal_dump()
639
640 self.assertEqual(2, len(signals))
641
642 signal_232_1_1_1_itf_0.compare(signals[1])
643 signal_232_1_1_2_itf_0.compare(signals[0])
644
Neale Rannsd792d9c2017-10-21 10:53:20 -0700645 route_232_1_1_1.update_entry_flags(
646 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE)
647 route_232_1_1_2.update_entry_flags(
648 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE)
Neale Ranns32e1c012016-11-22 17:07:28 +0000649
650 def test_ip_mcast_signal(self):
651 """ IP Multicast Signal """
652
653 #
654 # A (*,G).
655 # one accepting interface, pg0, 1 forwarding interfaces
656 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800657 route_232_1_1_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000658 self,
659 "0.0.0.0",
660 "232.1.1.1", 32,
661 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800662 [VppMRoutePath(self.pg0.sw_if_index,
663 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
664 VppMRoutePath(self.pg1.sw_if_index,
665 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
Neale Ranns32e1c012016-11-22 17:07:28 +0000666
667 route_232_1_1_1.add_vpp_config()
668 route_232_1_1_1.update_entry_flags(
669 MRouteEntryFlags.MFIB_ENTRY_FLAG_SIGNAL)
670
671 #
672 # Now the (*,G) is present, send from connected source
673 #
674 tx = self._mcast_connected_send_stream("232.1.1.1")
675
676 #
677 # Constrct a representation of the signal we expect on pg0
678 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800679 signal_232_1_1_1_itf_0 = VppMFibSignal(self,
680 route_232_1_1_1,
681 self.pg0.sw_if_index,
682 tx[0])
Neale Ranns32e1c012016-11-22 17:07:28 +0000683
684 #
685 # read the only expected signal
686 #
687 signals = self.vapi.mfib_signal_dump()
688
689 self.assertEqual(1, len(signals))
690
691 signal_232_1_1_1_itf_0.compare(signals[0])
692
693 #
694 # reading the signal allows for the generation of another
695 # so send more packets and expect the next signal
696 #
697 tx = self._mcast_connected_send_stream("232.1.1.1")
698
699 signals = self.vapi.mfib_signal_dump()
700 self.assertEqual(1, len(signals))
701 signal_232_1_1_1_itf_0.compare(signals[0])
702
703 #
704 # Set the negate-signal on the accepting interval - the signals
705 # should stop
706 #
707 route_232_1_1_1.update_path_flags(
708 self.pg0.sw_if_index,
709 (MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT |
710 MRouteItfFlags.MFIB_ITF_FLAG_NEGATE_SIGNAL))
711
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800712 self.vapi.cli("clear trace")
Neale Ranns32e1c012016-11-22 17:07:28 +0000713 tx = self._mcast_connected_send_stream("232.1.1.1")
714
715 signals = self.vapi.mfib_signal_dump()
716 self.assertEqual(0, len(signals))
717
718 #
719 # Clear the SIGNAL flag on the entry and the signals should
720 # come back since the interface is still NEGATE-SIGNAL
721 #
722 route_232_1_1_1.update_entry_flags(
723 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE)
724
725 tx = self._mcast_connected_send_stream("232.1.1.1")
726
727 signals = self.vapi.mfib_signal_dump()
728 self.assertEqual(1, len(signals))
729 signal_232_1_1_1_itf_0.compare(signals[0])
730
731 #
732 # Lastly remove the NEGATE-SIGNAL from the interface and the
733 # signals should stop
734 #
735 route_232_1_1_1.update_path_flags(self.pg0.sw_if_index,
736 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT)
737
738 tx = self._mcast_connected_send_stream("232.1.1.1")
739 signals = self.vapi.mfib_signal_dump()
740 self.assertEqual(0, len(signals))
741
Neale Ranns15002542017-09-10 04:39:11 -0700742 def test_ip_mcast_vrf(self):
743 """ IP Multicast Replication in non-default table"""
744
745 #
746 # An (S,G).
747 # one accepting interface, pg0, 2 forwarding interfaces
748 #
749 route_1_1_1_1_232_1_1_1 = VppIpMRoute(
750 self,
751 "1.1.1.1",
752 "232.1.1.1", 64,
753 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
754 [VppMRoutePath(self.pg8.sw_if_index,
755 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
756 VppMRoutePath(self.pg1.sw_if_index,
757 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
758 VppMRoutePath(self.pg2.sw_if_index,
759 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)],
760 table_id=10)
761 route_1_1_1_1_232_1_1_1.add_vpp_config()
762
763 #
764 # a stream that matches the route for (1.1.1.1,232.1.1.1)
765 # small packets
766 #
767 self.vapi.cli("clear trace")
768 tx = self.create_stream_ip4(self.pg8, "1.1.1.1", "232.1.1.1")
769 self.pg8.add_stream(tx)
770
771 self.pg_enable_capture(self.pg_interfaces)
772 self.pg_start()
773
774 # We expect replications on Pg1 & 2
775 self.verify_capture_ip4(self.pg1, tx)
776 self.verify_capture_ip4(self.pg2, tx)
777
778 def test_ip6_mcast_vrf(self):
779 """ IPv6 Multicast Replication in non-default table"""
780
781 #
782 # An (S,G).
783 # one accepting interface, pg0, 2 forwarding interfaces
784 #
785 route_2001_ff01_1 = VppIpMRoute(
786 self,
787 "2001::1",
788 "ff01::1", 256,
789 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
790 [VppMRoutePath(self.pg8.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700791 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT,
792 proto=DpoProto.DPO_PROTO_IP6),
Neale Ranns15002542017-09-10 04:39:11 -0700793 VppMRoutePath(self.pg1.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700794 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
795 proto=DpoProto.DPO_PROTO_IP6),
Neale Ranns15002542017-09-10 04:39:11 -0700796 VppMRoutePath(self.pg2.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700797 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
798 proto=DpoProto.DPO_PROTO_IP6)],
Neale Ranns15002542017-09-10 04:39:11 -0700799 table_id=10,
800 is_ip6=1)
801 route_2001_ff01_1.add_vpp_config()
802
803 #
804 # a stream that matches the route for (2001::1, ff00::1)
805 #
806 self.vapi.cli("clear trace")
807 tx = self.create_stream_ip6(self.pg8, "2001::1", "ff01::1")
808 self.pg8.add_stream(tx)
809
810 self.pg_enable_capture(self.pg_interfaces)
811 self.pg_start()
812
813 # We expect replications on Pg1, 2,
814 self.verify_capture_ip6(self.pg1, tx)
815 self.verify_capture_ip6(self.pg2, tx)
Neale Ranns32e1c012016-11-22 17:07:28 +0000816
Neale Rannscf3561b2017-12-13 01:44:25 -0800817 def test_bidir(self):
818 """ IP Multicast Bi-directional """
819
820 #
821 # A (*,G). The set of accepting interfaces matching the forwarding
822 #
823 route_232_1_1_1 = VppIpMRoute(
824 self,
825 "0.0.0.0",
826 "232.1.1.1", 32,
827 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
828 [VppMRoutePath(self.pg0.sw_if_index,
829 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT |
830 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
831 VppMRoutePath(self.pg1.sw_if_index,
832 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT |
833 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
834 VppMRoutePath(self.pg2.sw_if_index,
835 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT |
836 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
837 VppMRoutePath(self.pg3.sw_if_index,
838 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT |
839 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
840 route_232_1_1_1.add_vpp_config()
841
842 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.1")
843 self.pg0.add_stream(tx)
844
845 self.pg_enable_capture(self.pg_interfaces)
846 self.pg_start()
847
848 # We expect replications on Pg1, 2, 3, but not on pg0
849 self.verify_capture_ip4(self.pg1, tx)
850 self.verify_capture_ip4(self.pg2, tx)
851 self.verify_capture_ip4(self.pg3, tx)
852 self.pg0.assert_nothing_captured(
853 remark="IP multicast packets forwarded on PG0")
854
855
Neale Ranns32e1c012016-11-22 17:07:28 +0000856if __name__ == '__main__':
857 unittest.main(testRunner=VppTestRunner)