blob: 9c216d5657d0ae4a3154df27623dfa5e020c8337 [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 Ranns180279b2017-03-16 15:49:09 -04006from vpp_ip_route import VppIpMRoute, VppMRoutePath, VppMFibSignal, \
Neale Rannsd792d9c2017-10-21 10:53:20 -07007 MRouteItfFlags, MRouteEntryFlags, VppIpTable, DpoProto
Neale Ranns32e1c012016-11-22 17:07:28 +00008
9from scapy.packet import Raw
10from scapy.layers.l2 import Ether
Klement Sekerab9ef2732018-06-24 22:49:33 +020011from scapy.layers.inet import IP, UDP, getmacbyip
Neale Ranns32e1c012016-11-22 17:07:28 +000012from scapy.layers.inet6 import IPv6, getmacbyip6
Neale Ranns32e1c012016-11-22 17:07:28 +000013
Neale Ranns9bea8fb2017-02-03 04:34:01 -080014#
Neale Rannscf3561b2017-12-13 01:44:25 -080015# The number of packets sent is set to 91 so that when we replicate more than 3
Neale Ranns9bea8fb2017-02-03 04:34:01 -080016# times, which we do for some entries, we will generate more than 256 packets
Neale Rannsaaa396a2017-02-05 09:12:02 -080017# to the next node in the VLIB graph. Thus we are testing the code's
Neale Rannscf3561b2017-12-13 01:44:25 -080018# correctness handling this over-flow.
19# It's also an odd number so we hit any single loops.
Neale Ranns9bea8fb2017-02-03 04:34:01 -080020#
Neale Rannscf3561b2017-12-13 01:44:25 -080021N_PKTS_IN_STREAM = 91
Neale Ranns9bea8fb2017-02-03 04:34:01 -080022
Neale Ranns32e1c012016-11-22 17:07:28 +000023
Neale Ranns5a8123b2017-01-26 01:18:23 -080024class TestMFIB(VppTestCase):
25 """ MFIB Test Case """
26
27 def setUp(self):
28 super(TestMFIB, self).setUp()
29
30 def test_mfib(self):
31 """ MFIB Unit Tests """
32 error = self.vapi.cli("test mfib")
33
34 if error:
35 self.logger.critical(error)
36 self.assertEqual(error.find("Failed"), -1)
37
38
Neale Ranns32e1c012016-11-22 17:07:28 +000039class TestIPMcast(VppTestCase):
40 """ IP Multicast Test Case """
41
42 def setUp(self):
43 super(TestIPMcast, self).setUp()
44
Neale Ranns37be7362017-02-21 17:30:26 -080045 # create 8 pg interfaces
Neale Ranns15002542017-09-10 04:39:11 -070046 self.create_pg_interfaces(range(9))
Neale Ranns32e1c012016-11-22 17:07:28 +000047
48 # setup interfaces
Neale Ranns15002542017-09-10 04:39:11 -070049 for i in self.pg_interfaces[:8]:
Neale Ranns32e1c012016-11-22 17:07:28 +000050 i.admin_up()
51 i.config_ip4()
52 i.config_ip6()
53 i.resolve_arp()
54 i.resolve_ndp()
55
Neale Ranns15002542017-09-10 04:39:11 -070056 # one more in a vrf
57 tbl4 = VppIpTable(self, 10)
58 tbl4.add_vpp_config()
59 self.pg8.set_table_ip4(10)
60 self.pg8.config_ip4()
61
62 tbl6 = VppIpTable(self, 10, is_ip6=1)
63 tbl6.add_vpp_config()
64 self.pg8.set_table_ip6(10)
65 self.pg8.config_ip6()
66
67 def tearDown(self):
68 for i in self.pg_interfaces:
69 i.unconfig_ip4()
70 i.unconfig_ip6()
71 i.admin_down()
72
73 self.pg8.set_table_ip4(0)
74 self.pg8.set_table_ip6(0)
75 super(TestIPMcast, self).tearDown()
76
Neale Ranns9d676af2017-03-15 01:28:31 -070077 def create_stream_ip4(self, src_if, src_ip, dst_ip, payload_size=0):
Neale Ranns32e1c012016-11-22 17:07:28 +000078 pkts = []
Neale Ranns9d676af2017-03-15 01:28:31 -070079 # default to small packet sizes
80 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
81 IP(src=src_ip, dst=dst_ip) /
82 UDP(sport=1234, dport=1234))
83 if not payload_size:
84 payload_size = 64 - len(p)
85 p = p / Raw('\xa5' * payload_size)
86
Neale Ranns9bea8fb2017-02-03 04:34:01 -080087 for i in range(0, N_PKTS_IN_STREAM):
Neale Ranns32e1c012016-11-22 17:07:28 +000088 pkts.append(p)
89 return pkts
90
91 def create_stream_ip6(self, src_if, src_ip, dst_ip):
92 pkts = []
Neale Ranns9bea8fb2017-02-03 04:34:01 -080093 for i in range(0, N_PKTS_IN_STREAM):
Neale Ranns32e1c012016-11-22 17:07:28 +000094 info = self.create_packet_info(src_if, src_if)
95 payload = self.info_to_payload(info)
96 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
97 IPv6(src=src_ip, dst=dst_ip) /
98 UDP(sport=1234, dport=1234) /
99 Raw(payload))
100 info.data = p.copy()
101 pkts.append(p)
102 return pkts
103
104 def verify_filter(self, capture, sent):
105 if not len(capture) == len(sent):
106 # filter out any IPv6 RAs from the captur
107 for p in capture:
108 if (p.haslayer(IPv6)):
109 capture.remove(p)
110 return capture
111
Neale Rannse821ab12017-06-01 07:45:05 -0700112 def verify_capture_ip4(self, rx_if, sent, dst_mac=None):
Neale Rannsc2aad532017-05-30 09:53:52 -0700113 rxd = rx_if.get_capture(len(sent))
Neale Ranns32e1c012016-11-22 17:07:28 +0000114
115 try:
116 capture = self.verify_filter(rxd, sent)
117
118 self.assertEqual(len(capture), len(sent))
119
120 for i in range(len(capture)):
121 tx = sent[i]
122 rx = capture[i]
123
Neale Ranns32e1c012016-11-22 17:07:28 +0000124 eth = rx[Ether]
125 self.assertEqual(eth.type, 0x800)
126
127 tx_ip = tx[IP]
128 rx_ip = rx[IP]
129
Neale Rannse821ab12017-06-01 07:45:05 -0700130 if dst_mac is None:
131 dst_mac = getmacbyip(rx_ip.dst)
132
Neale Ranns32e1c012016-11-22 17:07:28 +0000133 # check the MAC address on the RX'd packet is correctly formed
Neale Rannse821ab12017-06-01 07:45:05 -0700134 self.assertEqual(eth.dst, dst_mac)
Neale Ranns32e1c012016-11-22 17:07:28 +0000135
136 self.assertEqual(rx_ip.src, tx_ip.src)
137 self.assertEqual(rx_ip.dst, tx_ip.dst)
138 # IP processing post pop has decremented the TTL
139 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
140
141 except:
142 raise
143
Neale Rannsc2aad532017-05-30 09:53:52 -0700144 def verify_capture_ip6(self, rx_if, sent):
145 capture = rx_if.get_capture(len(sent))
Neale Ranns32e1c012016-11-22 17:07:28 +0000146
147 self.assertEqual(len(capture), len(sent))
148
149 for i in range(len(capture)):
150 tx = sent[i]
151 rx = capture[i]
152
Neale Ranns32e1c012016-11-22 17:07:28 +0000153 eth = rx[Ether]
154 self.assertEqual(eth.type, 0x86DD)
155
156 tx_ip = tx[IPv6]
157 rx_ip = rx[IPv6]
158
159 # check the MAC address on the RX'd packet is correctly formed
160 self.assertEqual(eth.dst, getmacbyip6(rx_ip.dst))
161
162 self.assertEqual(rx_ip.src, tx_ip.src)
163 self.assertEqual(rx_ip.dst, tx_ip.dst)
164 # IP processing post pop has decremented the TTL
165 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
166
167 def test_ip_mcast(self):
168 """ IP Multicast Replication """
169
170 #
171 # a stream that matches the default route. gets dropped.
172 #
173 self.vapi.cli("clear trace")
174 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.1")
175 self.pg0.add_stream(tx)
176
177 self.pg_enable_capture(self.pg_interfaces)
178 self.pg_start()
179
180 self.pg0.assert_nothing_captured(
181 remark="IP multicast packets forwarded on default route")
182
183 #
184 # A (*,G).
Neale Ranns37be7362017-02-21 17:30:26 -0800185 # one accepting interface, pg0, 7 forwarding interfaces
186 # many forwarding interfaces test the case where the replicare DPO
187 # needs to use extra cache lines for the buckets.
Neale Ranns32e1c012016-11-22 17:07:28 +0000188 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800189 route_232_1_1_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000190 self,
191 "0.0.0.0",
192 "232.1.1.1", 32,
193 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800194 [VppMRoutePath(self.pg0.sw_if_index,
195 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
196 VppMRoutePath(self.pg1.sw_if_index,
197 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
198 VppMRoutePath(self.pg2.sw_if_index,
199 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
200 VppMRoutePath(self.pg3.sw_if_index,
Neale Ranns37be7362017-02-21 17:30:26 -0800201 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
202 VppMRoutePath(self.pg4.sw_if_index,
203 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
204 VppMRoutePath(self.pg5.sw_if_index,
205 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
206 VppMRoutePath(self.pg6.sw_if_index,
207 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
208 VppMRoutePath(self.pg7.sw_if_index,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800209 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
Neale Ranns32e1c012016-11-22 17:07:28 +0000210 route_232_1_1_1.add_vpp_config()
211
212 #
213 # An (S,G).
214 # one accepting interface, pg0, 2 forwarding interfaces
215 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800216 route_1_1_1_1_232_1_1_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000217 self,
218 "1.1.1.1",
219 "232.1.1.1", 64,
220 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800221 [VppMRoutePath(self.pg0.sw_if_index,
222 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
223 VppMRoutePath(self.pg1.sw_if_index,
224 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
225 VppMRoutePath(self.pg2.sw_if_index,
226 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
Neale Ranns32e1c012016-11-22 17:07:28 +0000227 route_1_1_1_1_232_1_1_1.add_vpp_config()
228
229 #
Neale Rannse821ab12017-06-01 07:45:05 -0700230 # An (S,G).
231 # one accepting interface, pg0, 2 forwarding interfaces
232 # that use unicast next-hops
233 #
234 route_1_1_1_1_232_1_1_2 = VppIpMRoute(
235 self,
236 "1.1.1.1",
237 "232.1.1.2", 64,
238 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
239 [VppMRoutePath(self.pg0.sw_if_index,
240 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
241 VppMRoutePath(self.pg1.sw_if_index,
242 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
243 nh=self.pg1.remote_ip4),
244 VppMRoutePath(self.pg2.sw_if_index,
245 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
246 nh=self.pg2.remote_ip4)])
247 route_1_1_1_1_232_1_1_2.add_vpp_config()
248
249 #
Neale Ranns32e1c012016-11-22 17:07:28 +0000250 # An (*,G/m).
251 # one accepting interface, pg0, 1 forwarding interfaces
252 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800253 route_232 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000254 self,
255 "0.0.0.0",
256 "232.0.0.0", 8,
257 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800258 [VppMRoutePath(self.pg0.sw_if_index,
259 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
260 VppMRoutePath(self.pg1.sw_if_index,
261 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
Neale Ranns32e1c012016-11-22 17:07:28 +0000262 route_232.add_vpp_config()
263
264 #
265 # a stream that matches the route for (1.1.1.1,232.1.1.1)
Neale Ranns9d676af2017-03-15 01:28:31 -0700266 # small packets
Neale Ranns32e1c012016-11-22 17:07:28 +0000267 #
268 self.vapi.cli("clear trace")
269 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.1")
270 self.pg0.add_stream(tx)
271
272 self.pg_enable_capture(self.pg_interfaces)
273 self.pg_start()
274
Neale Ranns37be7362017-02-21 17:30:26 -0800275 # We expect replications on Pg1->7
Neale Ranns32e1c012016-11-22 17:07:28 +0000276 self.verify_capture_ip4(self.pg1, tx)
277 self.verify_capture_ip4(self.pg2, tx)
278
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 Ranns9d676af2017-03-15 01:28:31 -0700286 # a stream that matches the route for (1.1.1.1,232.1.1.1)
287 # large packets
288 #
289 self.vapi.cli("clear trace")
290 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.1",
291 payload_size=1024)
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->7
298 self.verify_capture_ip4(self.pg1, tx)
299 self.verify_capture_ip4(self.pg2, tx)
Neale Ranns9d676af2017-03-15 01:28:31 -0700300
301 # no replications on Pg0
302 self.pg0.assert_nothing_captured(
303 remark="IP multicast packets forwarded on PG0")
304 self.pg3.assert_nothing_captured(
305 remark="IP multicast packets forwarded on PG3")
306
307 #
Neale Rannse821ab12017-06-01 07:45:05 -0700308 # a stream to the unicast next-hops
309 #
310 self.vapi.cli("clear trace")
311 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.2")
312 self.pg0.add_stream(tx)
313
314 self.pg_enable_capture(self.pg_interfaces)
315 self.pg_start()
316
317 # We expect replications on Pg1->7
318 self.verify_capture_ip4(self.pg1, tx, dst_mac=self.pg1.remote_mac)
319 self.verify_capture_ip4(self.pg2, tx, dst_mac=self.pg2.remote_mac)
320
321 # no replications on Pg0 nor pg3
322 self.pg0.assert_nothing_captured(
323 remark="IP multicast packets forwarded on PG0")
324 self.pg3.assert_nothing_captured(
325 remark="IP multicast packets forwarded on PG3")
326
327 #
Neale Ranns32e1c012016-11-22 17:07:28 +0000328 # a stream that matches the route for (*,232.0.0.0/8)
329 # Send packets with the 9th bit set so we test the correct clearing
330 # of that bit in the mac rewrite
331 #
332 self.vapi.cli("clear trace")
333 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.255.255.255")
334 self.pg0.add_stream(tx)
335
336 self.pg_enable_capture(self.pg_interfaces)
337 self.pg_start()
338
339 # We expect replications on Pg1 only
340 self.verify_capture_ip4(self.pg1, tx)
341
342 # no replications on Pg0, Pg2 not Pg3
343 self.pg0.assert_nothing_captured(
344 remark="IP multicast packets forwarded on PG0")
345 self.pg2.assert_nothing_captured(
346 remark="IP multicast packets forwarded on PG2")
347 self.pg3.assert_nothing_captured(
348 remark="IP multicast packets forwarded on PG3")
349
350 #
351 # a stream that matches the route for (*,232.1.1.1)
352 #
353 self.vapi.cli("clear trace")
354 tx = self.create_stream_ip4(self.pg0, "1.1.1.2", "232.1.1.1")
355 self.pg0.add_stream(tx)
356
357 self.pg_enable_capture(self.pg_interfaces)
358 self.pg_start()
359
Neale Rannse821ab12017-06-01 07:45:05 -0700360 # We expect replications on Pg1->7
Neale Ranns32e1c012016-11-22 17:07:28 +0000361 self.verify_capture_ip4(self.pg1, tx)
362 self.verify_capture_ip4(self.pg2, tx)
363 self.verify_capture_ip4(self.pg3, tx)
Neale Rannsc2aad532017-05-30 09:53:52 -0700364 self.verify_capture_ip4(self.pg4, tx)
365 self.verify_capture_ip4(self.pg5, tx)
366 self.verify_capture_ip4(self.pg6, tx)
367 self.verify_capture_ip4(self.pg7, tx)
Neale Ranns32e1c012016-11-22 17:07:28 +0000368
Neale Rannse821ab12017-06-01 07:45:05 -0700369 # no replications on Pg0
370 self.pg0.assert_nothing_captured(
371 remark="IP multicast packets forwarded on PG0")
372
Neale Ranns32e1c012016-11-22 17:07:28 +0000373 def test_ip6_mcast(self):
374 """ IPv6 Multicast Replication """
375
376 #
377 # a stream that matches the default route. gets dropped.
378 #
379 self.vapi.cli("clear trace")
380 tx = self.create_stream_ip6(self.pg0, "2001::1", "ff01::1")
381 self.pg0.add_stream(tx)
382
383 self.pg_enable_capture(self.pg_interfaces)
384 self.pg_start()
385
386 self.pg0.assert_nothing_captured(
387 remark="IPv6 multicast packets forwarded on default route")
388
389 #
390 # A (*,G).
391 # one accepting interface, pg0, 3 forwarding interfaces
392 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800393 route_ff01_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000394 self,
395 "::",
396 "ff01::1", 128,
397 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800398 [VppMRoutePath(self.pg0.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700399 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT,
400 proto=DpoProto.DPO_PROTO_IP6),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800401 VppMRoutePath(self.pg1.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700402 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
403 proto=DpoProto.DPO_PROTO_IP6),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800404 VppMRoutePath(self.pg2.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700405 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
406 proto=DpoProto.DPO_PROTO_IP6),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800407 VppMRoutePath(self.pg3.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700408 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
409 proto=DpoProto.DPO_PROTO_IP6)],
Neale Ranns32e1c012016-11-22 17:07:28 +0000410 is_ip6=1)
411 route_ff01_1.add_vpp_config()
412
413 #
414 # An (S,G).
415 # one accepting interface, pg0, 2 forwarding interfaces
416 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800417 route_2001_ff01_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000418 self,
419 "2001::1",
420 "ff01::1", 256,
421 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800422 [VppMRoutePath(self.pg0.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700423 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT,
424 proto=DpoProto.DPO_PROTO_IP6),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800425 VppMRoutePath(self.pg1.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700426 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
427 proto=DpoProto.DPO_PROTO_IP6),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800428 VppMRoutePath(self.pg2.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700429 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
430 proto=DpoProto.DPO_PROTO_IP6)],
Neale Ranns32e1c012016-11-22 17:07:28 +0000431 is_ip6=1)
432 route_2001_ff01_1.add_vpp_config()
433
434 #
435 # An (*,G/m).
436 # one accepting interface, pg0, 1 forwarding interface
437 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800438 route_ff01 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000439 self,
440 "::",
441 "ff01::", 16,
442 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800443 [VppMRoutePath(self.pg0.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700444 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT,
445 proto=DpoProto.DPO_PROTO_IP6),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800446 VppMRoutePath(self.pg1.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700447 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
448 proto=DpoProto.DPO_PROTO_IP6)],
Neale Ranns32e1c012016-11-22 17:07:28 +0000449 is_ip6=1)
450 route_ff01.add_vpp_config()
451
452 #
453 # a stream that matches the route for (*, ff01::/16)
Neale Rannsce111d22018-01-23 08:38:50 -0800454 # sent on the non-accepting interface
455 #
456 self.vapi.cli("clear trace")
457 tx = self.create_stream_ip6(self.pg1, "2002::1", "ff01:2::255")
458 self.send_and_assert_no_replies(self.pg1, tx, "RPF miss")
459
460 #
461 # a stream that matches the route for (*, ff01::/16)
462 # sent on the accepting interface
Neale Ranns32e1c012016-11-22 17:07:28 +0000463 #
464 self.vapi.cli("clear trace")
465 tx = self.create_stream_ip6(self.pg0, "2002::1", "ff01:2::255")
466 self.pg0.add_stream(tx)
467
468 self.pg_enable_capture(self.pg_interfaces)
469 self.pg_start()
470
471 # We expect replications on Pg1
472 self.verify_capture_ip6(self.pg1, tx)
473
474 # no replications on Pg0, Pg3
475 self.pg0.assert_nothing_captured(
476 remark="IP multicast packets forwarded on PG0")
477 self.pg2.assert_nothing_captured(
478 remark="IP multicast packets forwarded on PG2")
479 self.pg3.assert_nothing_captured(
480 remark="IP multicast packets forwarded on PG3")
481
482 #
Neale Rannsc2aad532017-05-30 09:53:52 -0700483 # Bounce the interface and it should still work
484 #
485 self.pg1.admin_down()
486 self.pg0.add_stream(tx)
487 self.pg_enable_capture(self.pg_interfaces)
488 self.pg_start()
489 self.pg1.assert_nothing_captured(
490 remark="IP multicast packets forwarded on down PG1")
491
492 self.pg1.admin_up()
493 self.pg0.add_stream(tx)
494 self.pg_enable_capture(self.pg_interfaces)
495 self.pg_start()
496 self.verify_capture_ip6(self.pg1, tx)
497
498 #
Neale Ranns32e1c012016-11-22 17:07:28 +0000499 # a stream that matches the route for (*,ff01::1)
500 #
501 self.vapi.cli("clear trace")
502 tx = self.create_stream_ip6(self.pg0, "2002::2", "ff01::1")
503 self.pg0.add_stream(tx)
504
505 self.pg_enable_capture(self.pg_interfaces)
506 self.pg_start()
507
508 # We expect replications on Pg1, 2, 3.
509 self.verify_capture_ip6(self.pg1, tx)
510 self.verify_capture_ip6(self.pg2, tx)
511 self.verify_capture_ip6(self.pg3, tx)
512
513 # no replications on Pg0
514 self.pg0.assert_nothing_captured(
515 remark="IPv6 multicast packets forwarded on PG0")
516
517 #
518 # a stream that matches the route for (2001::1, ff00::1)
519 #
520 self.vapi.cli("clear trace")
521 tx = self.create_stream_ip6(self.pg0, "2001::1", "ff01::1")
522 self.pg0.add_stream(tx)
523
524 self.pg_enable_capture(self.pg_interfaces)
525 self.pg_start()
526
527 # We expect replications on Pg1, 2,
528 self.verify_capture_ip6(self.pg1, tx)
529 self.verify_capture_ip6(self.pg2, tx)
530
531 # no replications on Pg0, Pg3
532 self.pg0.assert_nothing_captured(
533 remark="IP multicast packets forwarded on PG0")
534 self.pg3.assert_nothing_captured(
535 remark="IP multicast packets forwarded on PG3")
536
Neale Ranns32e1c012016-11-22 17:07:28 +0000537 def _mcast_connected_send_stream(self, dst_ip):
538 self.vapi.cli("clear trace")
539 tx = self.create_stream_ip4(self.pg0,
540 self.pg0.remote_ip4,
541 dst_ip)
542 self.pg0.add_stream(tx)
543
544 self.pg_enable_capture(self.pg_interfaces)
545 self.pg_start()
546
547 # We expect replications on Pg1.
548 self.verify_capture_ip4(self.pg1, tx)
549
550 return tx
551
552 def test_ip_mcast_connected(self):
553 """ IP Multicast Connected Source check """
554
555 #
556 # A (*,G).
557 # one accepting interface, pg0, 1 forwarding interfaces
558 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800559 route_232_1_1_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000560 self,
561 "0.0.0.0",
562 "232.1.1.1", 32,
563 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800564 [VppMRoutePath(self.pg0.sw_if_index,
565 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
566 VppMRoutePath(self.pg1.sw_if_index,
567 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
Neale Ranns32e1c012016-11-22 17:07:28 +0000568
569 route_232_1_1_1.add_vpp_config()
570 route_232_1_1_1.update_entry_flags(
571 MRouteEntryFlags.MFIB_ENTRY_FLAG_CONNECTED)
572
573 #
574 # Now the (*,G) is present, send from connected source
575 #
576 tx = self._mcast_connected_send_stream("232.1.1.1")
577
578 #
579 # Constrct a representation of the signal we expect on pg0
580 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800581 signal_232_1_1_1_itf_0 = VppMFibSignal(self,
582 route_232_1_1_1,
583 self.pg0.sw_if_index,
584 tx[0])
Neale Ranns32e1c012016-11-22 17:07:28 +0000585
586 #
587 # read the only expected signal
588 #
589 signals = self.vapi.mfib_signal_dump()
590
591 self.assertEqual(1, len(signals))
592
593 signal_232_1_1_1_itf_0.compare(signals[0])
594
595 #
596 # reading the signal allows for the generation of another
597 # so send more packets and expect the next signal
598 #
599 tx = self._mcast_connected_send_stream("232.1.1.1")
600
601 signals = self.vapi.mfib_signal_dump()
602 self.assertEqual(1, len(signals))
603 signal_232_1_1_1_itf_0.compare(signals[0])
604
605 #
606 # A Second entry with connected check
607 # one accepting interface, pg0, 1 forwarding interfaces
608 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800609 route_232_1_1_2 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000610 self,
611 "0.0.0.0",
612 "232.1.1.2", 32,
613 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800614 [VppMRoutePath(self.pg0.sw_if_index,
615 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
616 VppMRoutePath(self.pg1.sw_if_index,
617 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
Neale Ranns32e1c012016-11-22 17:07:28 +0000618
619 route_232_1_1_2.add_vpp_config()
620 route_232_1_1_2.update_entry_flags(
621 MRouteEntryFlags.MFIB_ENTRY_FLAG_CONNECTED)
622
623 #
624 # Send traffic to both entries. One read should net us two signals
625 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800626 signal_232_1_1_2_itf_0 = VppMFibSignal(self,
627 route_232_1_1_2,
628 self.pg0.sw_if_index,
629 tx[0])
Neale Ranns32e1c012016-11-22 17:07:28 +0000630 tx = self._mcast_connected_send_stream("232.1.1.1")
631 tx2 = self._mcast_connected_send_stream("232.1.1.2")
632
633 #
634 # read the only expected signal
635 #
636 signals = self.vapi.mfib_signal_dump()
637
638 self.assertEqual(2, len(signals))
639
640 signal_232_1_1_1_itf_0.compare(signals[1])
641 signal_232_1_1_2_itf_0.compare(signals[0])
642
Neale Rannsd792d9c2017-10-21 10:53:20 -0700643 route_232_1_1_1.update_entry_flags(
644 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE)
645 route_232_1_1_2.update_entry_flags(
646 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE)
Neale Ranns32e1c012016-11-22 17:07:28 +0000647
648 def test_ip_mcast_signal(self):
649 """ IP Multicast Signal """
650
651 #
652 # A (*,G).
653 # one accepting interface, pg0, 1 forwarding interfaces
654 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800655 route_232_1_1_1 = VppIpMRoute(
Neale Ranns32e1c012016-11-22 17:07:28 +0000656 self,
657 "0.0.0.0",
658 "232.1.1.1", 32,
659 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800660 [VppMRoutePath(self.pg0.sw_if_index,
661 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
662 VppMRoutePath(self.pg1.sw_if_index,
663 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
Neale Ranns32e1c012016-11-22 17:07:28 +0000664
665 route_232_1_1_1.add_vpp_config()
666 route_232_1_1_1.update_entry_flags(
667 MRouteEntryFlags.MFIB_ENTRY_FLAG_SIGNAL)
668
669 #
670 # Now the (*,G) is present, send from connected source
671 #
672 tx = self._mcast_connected_send_stream("232.1.1.1")
673
674 #
675 # Constrct a representation of the signal we expect on pg0
676 #
Neale Ranns5a8123b2017-01-26 01:18:23 -0800677 signal_232_1_1_1_itf_0 = VppMFibSignal(self,
678 route_232_1_1_1,
679 self.pg0.sw_if_index,
680 tx[0])
Neale Ranns32e1c012016-11-22 17:07:28 +0000681
682 #
683 # read the only expected signal
684 #
685 signals = self.vapi.mfib_signal_dump()
686
687 self.assertEqual(1, len(signals))
688
689 signal_232_1_1_1_itf_0.compare(signals[0])
690
691 #
692 # reading the signal allows for the generation of another
693 # so send more packets and expect the next signal
694 #
695 tx = self._mcast_connected_send_stream("232.1.1.1")
696
697 signals = self.vapi.mfib_signal_dump()
698 self.assertEqual(1, len(signals))
699 signal_232_1_1_1_itf_0.compare(signals[0])
700
701 #
702 # Set the negate-signal on the accepting interval - the signals
703 # should stop
704 #
705 route_232_1_1_1.update_path_flags(
706 self.pg0.sw_if_index,
707 (MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT |
708 MRouteItfFlags.MFIB_ITF_FLAG_NEGATE_SIGNAL))
709
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800710 self.vapi.cli("clear trace")
Neale Ranns32e1c012016-11-22 17:07:28 +0000711 tx = self._mcast_connected_send_stream("232.1.1.1")
712
713 signals = self.vapi.mfib_signal_dump()
714 self.assertEqual(0, len(signals))
715
716 #
717 # Clear the SIGNAL flag on the entry and the signals should
718 # come back since the interface is still NEGATE-SIGNAL
719 #
720 route_232_1_1_1.update_entry_flags(
721 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE)
722
723 tx = self._mcast_connected_send_stream("232.1.1.1")
724
725 signals = self.vapi.mfib_signal_dump()
726 self.assertEqual(1, len(signals))
727 signal_232_1_1_1_itf_0.compare(signals[0])
728
729 #
730 # Lastly remove the NEGATE-SIGNAL from the interface and the
731 # signals should stop
732 #
733 route_232_1_1_1.update_path_flags(self.pg0.sw_if_index,
734 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT)
735
736 tx = self._mcast_connected_send_stream("232.1.1.1")
737 signals = self.vapi.mfib_signal_dump()
738 self.assertEqual(0, len(signals))
739
Neale Ranns15002542017-09-10 04:39:11 -0700740 def test_ip_mcast_vrf(self):
741 """ IP Multicast Replication in non-default table"""
742
743 #
744 # An (S,G).
745 # one accepting interface, pg0, 2 forwarding interfaces
746 #
747 route_1_1_1_1_232_1_1_1 = VppIpMRoute(
748 self,
749 "1.1.1.1",
750 "232.1.1.1", 64,
751 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
752 [VppMRoutePath(self.pg8.sw_if_index,
753 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
754 VppMRoutePath(self.pg1.sw_if_index,
755 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
756 VppMRoutePath(self.pg2.sw_if_index,
757 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)],
758 table_id=10)
759 route_1_1_1_1_232_1_1_1.add_vpp_config()
760
761 #
762 # a stream that matches the route for (1.1.1.1,232.1.1.1)
763 # small packets
764 #
765 self.vapi.cli("clear trace")
766 tx = self.create_stream_ip4(self.pg8, "1.1.1.1", "232.1.1.1")
767 self.pg8.add_stream(tx)
768
769 self.pg_enable_capture(self.pg_interfaces)
770 self.pg_start()
771
772 # We expect replications on Pg1 & 2
773 self.verify_capture_ip4(self.pg1, tx)
774 self.verify_capture_ip4(self.pg2, tx)
775
776 def test_ip6_mcast_vrf(self):
777 """ IPv6 Multicast Replication in non-default table"""
778
779 #
780 # An (S,G).
781 # one accepting interface, pg0, 2 forwarding interfaces
782 #
783 route_2001_ff01_1 = VppIpMRoute(
784 self,
785 "2001::1",
786 "ff01::1", 256,
787 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
788 [VppMRoutePath(self.pg8.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700789 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT,
790 proto=DpoProto.DPO_PROTO_IP6),
Neale Ranns15002542017-09-10 04:39:11 -0700791 VppMRoutePath(self.pg1.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700792 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
793 proto=DpoProto.DPO_PROTO_IP6),
Neale Ranns15002542017-09-10 04:39:11 -0700794 VppMRoutePath(self.pg2.sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700795 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
796 proto=DpoProto.DPO_PROTO_IP6)],
Neale Ranns15002542017-09-10 04:39:11 -0700797 table_id=10,
798 is_ip6=1)
799 route_2001_ff01_1.add_vpp_config()
800
801 #
802 # a stream that matches the route for (2001::1, ff00::1)
803 #
804 self.vapi.cli("clear trace")
805 tx = self.create_stream_ip6(self.pg8, "2001::1", "ff01::1")
806 self.pg8.add_stream(tx)
807
808 self.pg_enable_capture(self.pg_interfaces)
809 self.pg_start()
810
811 # We expect replications on Pg1, 2,
812 self.verify_capture_ip6(self.pg1, tx)
813 self.verify_capture_ip6(self.pg2, tx)
Neale Ranns32e1c012016-11-22 17:07:28 +0000814
Neale Rannscf3561b2017-12-13 01:44:25 -0800815 def test_bidir(self):
816 """ IP Multicast Bi-directional """
817
818 #
819 # A (*,G). The set of accepting interfaces matching the forwarding
820 #
821 route_232_1_1_1 = VppIpMRoute(
822 self,
823 "0.0.0.0",
824 "232.1.1.1", 32,
825 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
826 [VppMRoutePath(self.pg0.sw_if_index,
827 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT |
828 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
829 VppMRoutePath(self.pg1.sw_if_index,
830 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT |
831 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
832 VppMRoutePath(self.pg2.sw_if_index,
833 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT |
834 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
835 VppMRoutePath(self.pg3.sw_if_index,
836 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT |
837 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
838 route_232_1_1_1.add_vpp_config()
839
840 tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.1")
841 self.pg0.add_stream(tx)
842
843 self.pg_enable_capture(self.pg_interfaces)
844 self.pg_start()
845
846 # We expect replications on Pg1, 2, 3, but not on pg0
847 self.verify_capture_ip4(self.pg1, tx)
848 self.verify_capture_ip4(self.pg2, tx)
849 self.verify_capture_ip4(self.pg3, tx)
850 self.pg0.assert_nothing_captured(
851 remark="IP multicast packets forwarded on PG0")
852
853
Neale Ranns32e1c012016-11-22 17:07:28 +0000854if __name__ == '__main__':
855 unittest.main(testRunner=VppTestRunner)