No vector allocation during buffer copy
[vpp.git] / test / test_ip_mcast.py
1 #!/usr/bin/env python
2
3 import unittest
4
5 from framework import VppTestCase, VppTestRunner
6 from vpp_sub_interface import VppSubInterface, VppDot1QSubint, VppDot1ADSubint
7 from vpp_ip_route import VppIpMRoute, VppMRoutePath, VppMFibSignal
8
9 from scapy.packet import Raw
10 from scapy.layers.l2 import Ether
11 from scapy.layers.inet import IP, UDP, getmacbyip, ICMP
12 from scapy.layers.inet6 import IPv6, getmacbyip6
13 from util import ppp
14
15
16 class MRouteItfFlags:
17     MFIB_ITF_FLAG_NONE = 0
18     MFIB_ITF_FLAG_NEGATE_SIGNAL = 1
19     MFIB_ITF_FLAG_ACCEPT = 2
20     MFIB_ITF_FLAG_FORWARD = 4
21     MFIB_ITF_FLAG_SIGNAL_PRESENT = 8
22     MFIB_ITF_FLAG_INTERNAL_COPY = 16
23
24
25 class MRouteEntryFlags:
26     MFIB_ENTRY_FLAG_NONE = 0
27     MFIB_ENTRY_FLAG_SIGNAL = 1
28     MFIB_ENTRY_FLAG_DROP = 2
29     MFIB_ENTRY_FLAG_CONNECTED = 4
30     MFIB_ENTRY_FLAG_INHERIT_ACCEPT = 8
31
32 #
33 # The number of packets sent is set to 90 so that when we replicate more than 3
34 # times, which we do for some entries, we will generate more than 256 packets
35 # to the next node in the VLIB graph. Thus we are testing the code's
36 # correctness handling this over-flow
37 #
38 N_PKTS_IN_STREAM = 90
39
40
41 class TestMFIB(VppTestCase):
42     """ MFIB Test Case """
43
44     def setUp(self):
45         super(TestMFIB, self).setUp()
46
47     def test_mfib(self):
48         """ MFIB Unit Tests """
49         error = self.vapi.cli("test mfib")
50
51         if error:
52             self.logger.critical(error)
53         self.assertEqual(error.find("Failed"), -1)
54
55
56 class TestIPMcast(VppTestCase):
57     """ IP Multicast Test Case """
58
59     def setUp(self):
60         super(TestIPMcast, self).setUp()
61
62         # create 8 pg interfaces
63         self.create_pg_interfaces(range(8))
64
65         # setup interfaces
66         for i in self.pg_interfaces:
67             i.admin_up()
68             i.config_ip4()
69             i.config_ip6()
70             i.resolve_arp()
71             i.resolve_ndp()
72
73     def create_stream_ip4(self, src_if, src_ip, dst_ip, payload_size=0):
74         pkts = []
75         # default to small packet sizes
76         p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
77              IP(src=src_ip, dst=dst_ip) /
78              UDP(sport=1234, dport=1234))
79         if not payload_size:
80             payload_size = 64 - len(p)
81             p = p / Raw('\xa5' * payload_size)
82
83         for i in range(0, N_PKTS_IN_STREAM):
84             pkts.append(p)
85         return pkts
86
87     def create_stream_ip6(self, src_if, src_ip, dst_ip):
88         pkts = []
89         for i in range(0, N_PKTS_IN_STREAM):
90             info = self.create_packet_info(src_if, src_if)
91             payload = self.info_to_payload(info)
92             p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
93                  IPv6(src=src_ip, dst=dst_ip) /
94                  UDP(sport=1234, dport=1234) /
95                  Raw(payload))
96             info.data = p.copy()
97             pkts.append(p)
98         return pkts
99
100     def verify_filter(self, capture, sent):
101         if not len(capture) == len(sent):
102             # filter out any IPv6 RAs from the captur
103             for p in capture:
104                 if (p.haslayer(IPv6)):
105                     capture.remove(p)
106         return capture
107
108     def verify_capture_ip4(self, src_if, sent):
109         rxd = self.pg1.get_capture(N_PKTS_IN_STREAM)
110
111         try:
112             capture = self.verify_filter(rxd, sent)
113
114             self.assertEqual(len(capture), len(sent))
115
116             for i in range(len(capture)):
117                 tx = sent[i]
118                 rx = capture[i]
119
120                 # the rx'd packet has the MPLS label popped
121                 eth = rx[Ether]
122                 self.assertEqual(eth.type, 0x800)
123
124                 tx_ip = tx[IP]
125                 rx_ip = rx[IP]
126
127                 # check the MAC address on the RX'd packet is correctly formed
128                 self.assertEqual(eth.dst, getmacbyip(rx_ip.dst))
129
130                 self.assertEqual(rx_ip.src, tx_ip.src)
131                 self.assertEqual(rx_ip.dst, tx_ip.dst)
132                 # IP processing post pop has decremented the TTL
133                 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
134
135         except:
136             raise
137
138     def verify_capture_ip6(self, src_if, sent):
139         capture = self.pg1.get_capture(N_PKTS_IN_STREAM)
140
141         self.assertEqual(len(capture), len(sent))
142
143         for i in range(len(capture)):
144             tx = sent[i]
145             rx = capture[i]
146
147             # the rx'd packet has the MPLS label popped
148             eth = rx[Ether]
149             self.assertEqual(eth.type, 0x86DD)
150
151             tx_ip = tx[IPv6]
152             rx_ip = rx[IPv6]
153
154             # check the MAC address on the RX'd packet is correctly formed
155             self.assertEqual(eth.dst, getmacbyip6(rx_ip.dst))
156
157             self.assertEqual(rx_ip.src, tx_ip.src)
158             self.assertEqual(rx_ip.dst, tx_ip.dst)
159             # IP processing post pop has decremented the TTL
160             self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
161
162     def test_ip_mcast(self):
163         """ IP Multicast Replication """
164
165         #
166         # a stream that matches the default route. gets dropped.
167         #
168         self.vapi.cli("clear trace")
169         tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.1")
170         self.pg0.add_stream(tx)
171
172         self.pg_enable_capture(self.pg_interfaces)
173         self.pg_start()
174
175         self.pg0.assert_nothing_captured(
176             remark="IP multicast packets forwarded on default route")
177
178         #
179         # A (*,G).
180         # one accepting interface, pg0, 7 forwarding interfaces
181         #  many forwarding interfaces test the case where the replicare DPO
182         #  needs to use extra cache lines for the buckets.
183         #
184         route_232_1_1_1 = VppIpMRoute(
185             self,
186             "0.0.0.0",
187             "232.1.1.1", 32,
188             MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
189             [VppMRoutePath(self.pg0.sw_if_index,
190                            MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
191              VppMRoutePath(self.pg1.sw_if_index,
192                            MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
193              VppMRoutePath(self.pg2.sw_if_index,
194                            MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
195              VppMRoutePath(self.pg3.sw_if_index,
196                            MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
197              VppMRoutePath(self.pg4.sw_if_index,
198                            MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
199              VppMRoutePath(self.pg5.sw_if_index,
200                            MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
201              VppMRoutePath(self.pg6.sw_if_index,
202                            MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
203              VppMRoutePath(self.pg7.sw_if_index,
204                            MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
205         route_232_1_1_1.add_vpp_config()
206
207         #
208         # An (S,G).
209         # one accepting interface, pg0, 2 forwarding interfaces
210         #
211         route_1_1_1_1_232_1_1_1 = VppIpMRoute(
212             self,
213             "1.1.1.1",
214             "232.1.1.1", 64,
215             MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
216             [VppMRoutePath(self.pg0.sw_if_index,
217                            MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
218              VppMRoutePath(self.pg1.sw_if_index,
219                            MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
220              VppMRoutePath(self.pg2.sw_if_index,
221                            MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
222         route_1_1_1_1_232_1_1_1.add_vpp_config()
223
224         #
225         # An (*,G/m).
226         # one accepting interface, pg0, 1 forwarding interfaces
227         #
228         route_232 = VppIpMRoute(
229             self,
230             "0.0.0.0",
231             "232.0.0.0", 8,
232             MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
233             [VppMRoutePath(self.pg0.sw_if_index,
234                            MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
235              VppMRoutePath(self.pg1.sw_if_index,
236                            MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
237         route_232.add_vpp_config()
238
239         #
240         # a stream that matches the route for (1.1.1.1,232.1.1.1)
241         #  small packets
242         #
243         self.vapi.cli("clear trace")
244         tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.1")
245         self.pg0.add_stream(tx)
246
247         self.pg_enable_capture(self.pg_interfaces)
248         self.pg_start()
249
250         # We expect replications on Pg1->7
251         self.verify_capture_ip4(self.pg1, tx)
252         self.verify_capture_ip4(self.pg2, tx)
253         self.verify_capture_ip4(self.pg3, tx)
254         self.verify_capture_ip4(self.pg4, tx)
255         self.verify_capture_ip4(self.pg5, tx)
256         self.verify_capture_ip4(self.pg6, tx)
257         self.verify_capture_ip4(self.pg7, tx)
258
259         # no replications on Pg0
260         self.pg0.assert_nothing_captured(
261             remark="IP multicast packets forwarded on PG0")
262         self.pg3.assert_nothing_captured(
263             remark="IP multicast packets forwarded on PG3")
264
265         #
266         # a stream that matches the route for (1.1.1.1,232.1.1.1)
267         #  large packets
268         #
269         self.vapi.cli("clear trace")
270         tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.1",
271                                     payload_size=1024)
272         self.pg0.add_stream(tx)
273
274         self.pg_enable_capture(self.pg_interfaces)
275         self.pg_start()
276
277         # We expect replications on Pg1->7
278         self.verify_capture_ip4(self.pg1, tx)
279         self.verify_capture_ip4(self.pg2, tx)
280         self.verify_capture_ip4(self.pg3, tx)
281         self.verify_capture_ip4(self.pg4, tx)
282         self.verify_capture_ip4(self.pg5, tx)
283         self.verify_capture_ip4(self.pg6, tx)
284         self.verify_capture_ip4(self.pg7, tx)
285
286         # no replications on Pg0
287         self.pg0.assert_nothing_captured(
288             remark="IP multicast packets forwarded on PG0")
289         self.pg3.assert_nothing_captured(
290             remark="IP multicast packets forwarded on PG3")
291
292         #
293         # a stream that matches the route for (*,232.0.0.0/8)
294         # Send packets with the 9th bit set so we test the correct clearing
295         # of that bit in the mac rewrite
296         #
297         self.vapi.cli("clear trace")
298         tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.255.255.255")
299         self.pg0.add_stream(tx)
300
301         self.pg_enable_capture(self.pg_interfaces)
302         self.pg_start()
303
304         # We expect replications on Pg1 only
305         self.verify_capture_ip4(self.pg1, tx)
306
307         # no replications on Pg0, Pg2 not Pg3
308         self.pg0.assert_nothing_captured(
309             remark="IP multicast packets forwarded on PG0")
310         self.pg2.assert_nothing_captured(
311             remark="IP multicast packets forwarded on PG2")
312         self.pg3.assert_nothing_captured(
313             remark="IP multicast packets forwarded on PG3")
314
315         #
316         # a stream that matches the route for (*,232.1.1.1)
317         #
318         self.vapi.cli("clear trace")
319         tx = self.create_stream_ip4(self.pg0, "1.1.1.2", "232.1.1.1")
320         self.pg0.add_stream(tx)
321
322         self.pg_enable_capture(self.pg_interfaces)
323         self.pg_start()
324
325         # We expect replications on Pg1, 2, 3.
326         self.verify_capture_ip4(self.pg1, tx)
327         self.verify_capture_ip4(self.pg2, tx)
328         self.verify_capture_ip4(self.pg3, tx)
329
330         # no replications on Pg0
331         self.pg0.assert_nothing_captured(
332             remark="IP multicast packets forwarded on PG0")
333
334         route_232_1_1_1.remove_vpp_config()
335         route_1_1_1_1_232_1_1_1.remove_vpp_config()
336         route_232.remove_vpp_config()
337
338     def test_ip6_mcast(self):
339         """ IPv6 Multicast Replication """
340
341         #
342         # a stream that matches the default route. gets dropped.
343         #
344         self.vapi.cli("clear trace")
345         tx = self.create_stream_ip6(self.pg0, "2001::1", "ff01::1")
346         self.pg0.add_stream(tx)
347
348         self.pg_enable_capture(self.pg_interfaces)
349         self.pg_start()
350
351         self.pg0.assert_nothing_captured(
352             remark="IPv6 multicast packets forwarded on default route")
353
354         #
355         # A (*,G).
356         # one accepting interface, pg0, 3 forwarding interfaces
357         #
358         route_ff01_1 = VppIpMRoute(
359             self,
360             "::",
361             "ff01::1", 128,
362             MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
363             [VppMRoutePath(self.pg0.sw_if_index,
364                            MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
365              VppMRoutePath(self.pg1.sw_if_index,
366                            MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
367              VppMRoutePath(self.pg2.sw_if_index,
368                            MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
369              VppMRoutePath(self.pg3.sw_if_index,
370                            MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)],
371             is_ip6=1)
372         route_ff01_1.add_vpp_config()
373
374         #
375         # An (S,G).
376         # one accepting interface, pg0, 2 forwarding interfaces
377         #
378         route_2001_ff01_1 = VppIpMRoute(
379             self,
380             "2001::1",
381             "ff01::1", 256,
382             MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
383             [VppMRoutePath(self.pg0.sw_if_index,
384                            MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
385              VppMRoutePath(self.pg1.sw_if_index,
386                            MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
387              VppMRoutePath(self.pg2.sw_if_index,
388                            MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)],
389             is_ip6=1)
390         route_2001_ff01_1.add_vpp_config()
391
392         #
393         # An (*,G/m).
394         # one accepting interface, pg0, 1 forwarding interface
395         #
396         route_ff01 = VppIpMRoute(
397             self,
398             "::",
399             "ff01::", 16,
400             MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
401             [VppMRoutePath(self.pg0.sw_if_index,
402                            MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
403              VppMRoutePath(self.pg1.sw_if_index,
404                            MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)],
405             is_ip6=1)
406         route_ff01.add_vpp_config()
407
408         #
409         # a stream that matches the route for (*, ff01::/16)
410         #
411         self.vapi.cli("clear trace")
412         tx = self.create_stream_ip6(self.pg0, "2002::1", "ff01:2::255")
413         self.pg0.add_stream(tx)
414
415         self.pg_enable_capture(self.pg_interfaces)
416         self.pg_start()
417
418         # We expect replications on Pg1
419         self.verify_capture_ip6(self.pg1, tx)
420
421         # no replications on Pg0, Pg3
422         self.pg0.assert_nothing_captured(
423             remark="IP multicast packets forwarded on PG0")
424         self.pg2.assert_nothing_captured(
425             remark="IP multicast packets forwarded on PG2")
426         self.pg3.assert_nothing_captured(
427             remark="IP multicast packets forwarded on PG3")
428
429         #
430         # a stream that matches the route for (*,ff01::1)
431         #
432         self.vapi.cli("clear trace")
433         tx = self.create_stream_ip6(self.pg0, "2002::2", "ff01::1")
434         self.pg0.add_stream(tx)
435
436         self.pg_enable_capture(self.pg_interfaces)
437         self.pg_start()
438
439         # We expect replications on Pg1, 2, 3.
440         self.verify_capture_ip6(self.pg1, tx)
441         self.verify_capture_ip6(self.pg2, tx)
442         self.verify_capture_ip6(self.pg3, tx)
443
444         # no replications on Pg0
445         self.pg0.assert_nothing_captured(
446             remark="IPv6 multicast packets forwarded on PG0")
447
448         #
449         # a stream that matches the route for (2001::1, ff00::1)
450         #
451         self.vapi.cli("clear trace")
452         tx = self.create_stream_ip6(self.pg0, "2001::1", "ff01::1")
453         self.pg0.add_stream(tx)
454
455         self.pg_enable_capture(self.pg_interfaces)
456         self.pg_start()
457
458         # We expect replications on Pg1, 2,
459         self.verify_capture_ip6(self.pg1, tx)
460         self.verify_capture_ip6(self.pg2, tx)
461
462         # no replications on Pg0, Pg3
463         self.pg0.assert_nothing_captured(
464             remark="IP multicast packets forwarded on PG0")
465         self.pg3.assert_nothing_captured(
466             remark="IP multicast packets forwarded on PG3")
467
468         route_ff01.remove_vpp_config()
469         route_ff01_1.remove_vpp_config()
470         route_2001_ff01_1.remove_vpp_config()
471
472     def _mcast_connected_send_stream(self, dst_ip):
473         self.vapi.cli("clear trace")
474         tx = self.create_stream_ip4(self.pg0,
475                                     self.pg0.remote_ip4,
476                                     dst_ip)
477         self.pg0.add_stream(tx)
478
479         self.pg_enable_capture(self.pg_interfaces)
480         self.pg_start()
481
482         # We expect replications on Pg1.
483         self.verify_capture_ip4(self.pg1, tx)
484
485         return tx
486
487     def test_ip_mcast_connected(self):
488         """ IP Multicast Connected Source check """
489
490         #
491         # A (*,G).
492         # one accepting interface, pg0, 1 forwarding interfaces
493         #
494         route_232_1_1_1 = VppIpMRoute(
495             self,
496             "0.0.0.0",
497             "232.1.1.1", 32,
498             MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
499             [VppMRoutePath(self.pg0.sw_if_index,
500                            MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
501              VppMRoutePath(self.pg1.sw_if_index,
502                            MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
503
504         route_232_1_1_1.add_vpp_config()
505         route_232_1_1_1.update_entry_flags(
506             MRouteEntryFlags.MFIB_ENTRY_FLAG_CONNECTED)
507
508         #
509         # Now the (*,G) is present, send from connected source
510         #
511         tx = self._mcast_connected_send_stream("232.1.1.1")
512
513         #
514         # Constrct a representation of the signal we expect on pg0
515         #
516         signal_232_1_1_1_itf_0 = VppMFibSignal(self,
517                                                route_232_1_1_1,
518                                                self.pg0.sw_if_index,
519                                                tx[0])
520
521         #
522         # read the only expected signal
523         #
524         signals = self.vapi.mfib_signal_dump()
525
526         self.assertEqual(1, len(signals))
527
528         signal_232_1_1_1_itf_0.compare(signals[0])
529
530         #
531         # reading the signal allows for the generation of another
532         # so send more packets and expect the next signal
533         #
534         tx = self._mcast_connected_send_stream("232.1.1.1")
535
536         signals = self.vapi.mfib_signal_dump()
537         self.assertEqual(1, len(signals))
538         signal_232_1_1_1_itf_0.compare(signals[0])
539
540         #
541         # A Second entry with connected check
542         # one accepting interface, pg0, 1 forwarding interfaces
543         #
544         route_232_1_1_2 = VppIpMRoute(
545             self,
546             "0.0.0.0",
547             "232.1.1.2", 32,
548             MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
549             [VppMRoutePath(self.pg0.sw_if_index,
550                            MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
551              VppMRoutePath(self.pg1.sw_if_index,
552                            MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
553
554         route_232_1_1_2.add_vpp_config()
555         route_232_1_1_2.update_entry_flags(
556             MRouteEntryFlags.MFIB_ENTRY_FLAG_CONNECTED)
557
558         #
559         # Send traffic to both entries. One read should net us two signals
560         #
561         signal_232_1_1_2_itf_0 = VppMFibSignal(self,
562                                                route_232_1_1_2,
563                                                self.pg0.sw_if_index,
564                                                tx[0])
565         tx = self._mcast_connected_send_stream("232.1.1.1")
566         tx2 = self._mcast_connected_send_stream("232.1.1.2")
567
568         #
569         # read the only expected signal
570         #
571         signals = self.vapi.mfib_signal_dump()
572
573         self.assertEqual(2, len(signals))
574
575         signal_232_1_1_1_itf_0.compare(signals[1])
576         signal_232_1_1_2_itf_0.compare(signals[0])
577
578         route_232_1_1_1.remove_vpp_config()
579         route_232_1_1_2.remove_vpp_config()
580
581     def test_ip_mcast_signal(self):
582         """ IP Multicast Signal """
583
584         #
585         # A (*,G).
586         # one accepting interface, pg0, 1 forwarding interfaces
587         #
588         route_232_1_1_1 = VppIpMRoute(
589             self,
590             "0.0.0.0",
591             "232.1.1.1", 32,
592             MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
593             [VppMRoutePath(self.pg0.sw_if_index,
594                            MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
595              VppMRoutePath(self.pg1.sw_if_index,
596                            MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
597
598         route_232_1_1_1.add_vpp_config()
599         route_232_1_1_1.update_entry_flags(
600             MRouteEntryFlags.MFIB_ENTRY_FLAG_SIGNAL)
601
602         #
603         # Now the (*,G) is present, send from connected source
604         #
605         tx = self._mcast_connected_send_stream("232.1.1.1")
606
607         #
608         # Constrct a representation of the signal we expect on pg0
609         #
610         signal_232_1_1_1_itf_0 = VppMFibSignal(self,
611                                                route_232_1_1_1,
612                                                self.pg0.sw_if_index,
613                                                tx[0])
614
615         #
616         # read the only expected signal
617         #
618         signals = self.vapi.mfib_signal_dump()
619
620         self.assertEqual(1, len(signals))
621
622         signal_232_1_1_1_itf_0.compare(signals[0])
623
624         #
625         # reading the signal allows for the generation of another
626         # so send more packets and expect the next signal
627         #
628         tx = self._mcast_connected_send_stream("232.1.1.1")
629
630         signals = self.vapi.mfib_signal_dump()
631         self.assertEqual(1, len(signals))
632         signal_232_1_1_1_itf_0.compare(signals[0])
633
634         #
635         # Set the negate-signal on the accepting interval - the signals
636         # should stop
637         #
638         route_232_1_1_1.update_path_flags(
639             self.pg0.sw_if_index,
640             (MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT |
641              MRouteItfFlags.MFIB_ITF_FLAG_NEGATE_SIGNAL))
642
643         tx = self._mcast_connected_send_stream("232.1.1.1")
644
645         signals = self.vapi.mfib_signal_dump()
646         self.assertEqual(0, len(signals))
647
648         #
649         # Clear the SIGNAL flag on the entry and the signals should
650         # come back since the interface is still NEGATE-SIGNAL
651         #
652         route_232_1_1_1.update_entry_flags(
653             MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE)
654
655         tx = self._mcast_connected_send_stream("232.1.1.1")
656
657         signals = self.vapi.mfib_signal_dump()
658         self.assertEqual(1, len(signals))
659         signal_232_1_1_1_itf_0.compare(signals[0])
660
661         #
662         # Lastly remove the NEGATE-SIGNAL from the interface and the
663         # signals should stop
664         #
665         route_232_1_1_1.update_path_flags(self.pg0.sw_if_index,
666                                           MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT)
667
668         tx = self._mcast_connected_send_stream("232.1.1.1")
669         signals = self.vapi.mfib_signal_dump()
670         self.assertEqual(0, len(signals))
671
672         #
673         # Cleanup
674         #
675         route_232_1_1_1.remove_vpp_config()
676
677
678 if __name__ == '__main__':
679     unittest.main(testRunner=VppTestRunner)