blob: de84eddcad9f4726623c681071b0cccb6f94714a [file] [log] [blame]
Eyal Baric86e5922017-07-02 18:33:16 +03001#!/usr/bin/env python
2""" L2BD ARP term Test """
3
4import unittest
5import random
6import copy
7
Eyal Bari20197482017-09-13 12:29:08 +03008from socket import AF_INET, AF_INET6
Eyal Bari758137a2017-07-05 14:31:30 +03009
Eyal Baric86e5922017-07-02 18:33:16 +030010from scapy.packet import Raw
11from scapy.layers.l2 import Ether, ARP
12from scapy.layers.inet import IP
Eyal Bari758137a2017-07-05 14:31:30 +030013from scapy.utils import inet_pton, inet_ntop
14from scapy.utils6 import in6_getnsma, in6_getnsmac, in6_ptop, in6_islladdr, \
15 in6_mactoifaceid, in6_ismaddr
16from scapy.layers.inet6 import IPv6, UDP, ICMPv6ND_NS, ICMPv6ND_RS, \
17 ICMPv6ND_RA, ICMPv6NDOptSrcLLAddr, getmacbyip6, ICMPv6MRD_Solicitation, \
18 ICMPv6NDOptMTU, ICMPv6NDOptSrcLLAddr, ICMPv6NDOptPrefixInfo, \
19 ICMPv6ND_NA, ICMPv6NDOptDstLLAddr, ICMPv6DestUnreach, icmp6types
Eyal Baric86e5922017-07-02 18:33:16 +030020
21from framework import VppTestCase, VppTestRunner
Ole Troan7f991832018-12-06 17:35:12 +010022from util import Host, ppp
Eyal Baric86e5922017-07-02 18:33:16 +030023
24
25class TestL2bdArpTerm(VppTestCase):
26 """ L2BD arp termination Test Case """
27
28 @classmethod
29 def setUpClass(cls):
30 """
31 Perform standard class setup (defined by class method setUpClass in
32 class VppTestCase) before running the test case, set test case related
33 variables and configure VPP.
34 """
35 super(TestL2bdArpTerm, cls).setUpClass()
36
37 try:
38 # Create pg interfaces
39 n_bd = 1
40 cls.ifs_per_bd = ifs_per_bd = 3
41 n_ifs = n_bd * ifs_per_bd
42 cls.create_pg_interfaces(range(n_ifs))
43
44 # Set up all interfaces
45 for i in cls.pg_interfaces:
46 i.admin_up()
47
48 cls.hosts = set()
49
50 except Exception:
51 super(TestL2bdArpTerm, cls).tearDownClass()
52 raise
53
54 def setUp(self):
55 """
56 Clear trace and packet infos before running each test.
57 """
58 self.reset_packet_infos()
59 super(TestL2bdArpTerm, self).setUp()
60
61 def tearDown(self):
62 """
63 Show various debug prints after each test.
64 """
65 super(TestL2bdArpTerm, self).tearDown()
66 if not self.vpp_dead:
67 self.logger.info(self.vapi.ppcli("show l2fib verbose"))
68 self.logger.info(self.vapi.ppcli("show bridge-domain 1 detail"))
69
Eyal Bari758137a2017-07-05 14:31:30 +030070 def add_del_arp_term_hosts(self, entries, bd_id=1, is_add=1, is_ipv6=0):
Eyal Baric86e5922017-07-02 18:33:16 +030071 for e in entries:
Neale Ranns4d5b9172018-10-24 02:57:49 -070072 ip = e.ip4 if is_ipv6 == 0 else e.ip6
Ole Troan9a475372019-03-05 16:58:24 +010073 self.vapi.bd_ip_mac_add_del(bd_id=bd_id, is_add=is_add, ip=ip,
74 mac=e.mac)
Eyal Baric86e5922017-07-02 18:33:16 +030075
76 @classmethod
77 def mac_list(cls, b6_range):
78 return ["00:00:ca:fe:00:%02x" % b6 for b6 in b6_range]
79
80 @classmethod
81 def ip4_host(cls, subnet, host, mac):
82 return Host(mac=mac,
83 ip4="172.17.1%02u.%u" % (subnet, host))
84
85 @classmethod
86 def ip4_hosts(cls, subnet, start, mac_list):
87 return {cls.ip4_host(subnet, start + j, mac_list[j])
88 for j in range(len(mac_list))}
89
90 @classmethod
Eyal Bari758137a2017-07-05 14:31:30 +030091 def ip6_host(cls, subnet, host, mac):
92 return Host(mac=mac,
93 ip6="fd01:%x::%x" % (subnet, host))
94
95 @classmethod
96 def ip6_hosts(cls, subnet, start, mac_list):
97 return {cls.ip6_host(subnet, start + j, mac_list[j])
98 for j in range(len(mac_list))}
99
100 @classmethod
Eyal Baric86e5922017-07-02 18:33:16 +0300101 def bd_swifs(cls, b):
102 n = cls.ifs_per_bd
103 start = (b - 1) * n
104 return [cls.pg_interfaces[j] for j in range(start, start + n)]
105
106 def bd_add_del(self, bd_id=1, is_add=1):
107 if is_add:
108 self.vapi.bridge_domain_add_del(bd_id=bd_id, is_add=is_add)
109 for swif in self.bd_swifs(bd_id):
110 swif_idx = swif.sw_if_index
Ole Troana5b2eec2019-03-11 19:23:25 +0100111 self.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=swif_idx,
112 bd_id=bd_id, enable=is_add)
Eyal Baric86e5922017-07-02 18:33:16 +0300113 if not is_add:
114 self.vapi.bridge_domain_add_del(bd_id=bd_id, is_add=is_add)
115
116 @classmethod
Eyal Bari20197482017-09-13 12:29:08 +0300117 def arp_req(cls, src_host, host):
Eyal Baric86e5922017-07-02 18:33:16 +0300118 return (Ether(dst="ff:ff:ff:ff:ff:ff", src=src_host.mac) /
119 ARP(op="who-has",
120 hwsrc=src_host.bin_mac,
121 pdst=host.ip4,
122 psrc=src_host.ip4))
123
124 @classmethod
125 def arp_reqs(cls, src_host, entries):
Eyal Bari20197482017-09-13 12:29:08 +0300126 return [cls.arp_req(src_host, e) for e in entries]
127
128 @classmethod
129 def garp_req(cls, host):
130 return cls.arp_req(host, host)
131
132 @classmethod
133 def garp_reqs(cls, entries):
134 return [cls.garp_req(e) for e in entries]
Eyal Baric86e5922017-07-02 18:33:16 +0300135
Eyal Bari758137a2017-07-05 14:31:30 +0300136 def arp_resp_host(self, src_host, arp_resp):
Eyal Baric86e5922017-07-02 18:33:16 +0300137 ether = arp_resp[Ether]
138 self.assertEqual(ether.dst, src_host.mac)
139
140 arp = arp_resp[ARP]
141 self.assertEqual(arp.hwtype, 1)
142 self.assertEqual(arp.ptype, 0x800)
143 self.assertEqual(arp.hwlen, 6)
144 self.assertEqual(arp.plen, 4)
145 arp_opts = {"who-has": 1, "is-at": 2}
146 self.assertEqual(arp.op, arp_opts["is-at"])
147 self.assertEqual(arp.hwdst, src_host.mac)
148 self.assertEqual(arp.pdst, src_host.ip4)
Eyal Bari758137a2017-07-05 14:31:30 +0300149 return Host(mac=arp.hwsrc, ip4=arp.psrc)
Eyal Baric86e5922017-07-02 18:33:16 +0300150
151 def arp_resp_hosts(self, src_host, pkts):
Eyal Bari758137a2017-07-05 14:31:30 +0300152 return {self.arp_resp_host(src_host, p) for p in pkts}
153
Paul Vinciguerra9db94452018-11-25 10:46:44 -0800154 @staticmethod
155 def inttoip4(ip):
Eyal Bari20197482017-09-13 12:29:08 +0300156 o1 = int(ip / 16777216) % 256
157 o2 = int(ip / 65536) % 256
158 o3 = int(ip / 256) % 256
159 o4 = int(ip) % 256
Paul Vinciguerra9db94452018-11-25 10:46:44 -0800160 return '%s.%s.%s.%s' % (o1, o2, o3, o4)
Eyal Bari20197482017-09-13 12:29:08 +0300161
162 def arp_event_host(self, e):
Neale Ranns37029302018-08-10 05:30:06 -0700163 return Host(str(e.mac), ip4=str(e.ip))
Eyal Bari20197482017-09-13 12:29:08 +0300164
165 def arp_event_hosts(self, evs):
166 return {self.arp_event_host(e) for e in evs}
167
Eyal Baric125ecc2017-09-20 11:29:17 +0300168 def nd_event_host(self, e):
Neale Ranns37029302018-08-10 05:30:06 -0700169 return Host(str(e.mac), ip6=str(e.ip))
Eyal Baric125ecc2017-09-20 11:29:17 +0300170
171 def nd_event_hosts(self, evs):
172 return {self.nd_event_host(e) for e in evs}
173
Eyal Bari758137a2017-07-05 14:31:30 +0300174 @classmethod
175 def ns_req(cls, src_host, host):
176 nsma = in6_getnsma(inet_pton(AF_INET6, "fd10::ffff"))
177 d = inet_ntop(AF_INET6, nsma)
178 return (Ether(dst="ff:ff:ff:ff:ff:ff", src=src_host.mac) /
179 IPv6(dst=d, src=src_host.ip6) /
180 ICMPv6ND_NS(tgt=host.ip6) /
181 ICMPv6NDOptSrcLLAddr(lladdr=src_host.mac))
182
183 @classmethod
Eyal Baric125ecc2017-09-20 11:29:17 +0300184 def ns_reqs_dst(cls, entries, dst_host):
185 return [cls.ns_req(e, dst_host) for e in entries]
186
187 @classmethod
188 def ns_reqs_src(cls, src_host, entries):
Eyal Bari758137a2017-07-05 14:31:30 +0300189 return [cls.ns_req(src_host, e) for e in entries]
190
191 def na_resp_host(self, src_host, rx):
192 self.assertEqual(rx[Ether].dst, src_host.mac)
193 self.assertEqual(in6_ptop(rx[IPv6].dst),
194 in6_ptop(src_host.ip6))
195
196 self.assertTrue(rx.haslayer(ICMPv6ND_NA))
197 self.assertTrue(rx.haslayer(ICMPv6NDOptDstLLAddr))
198
199 na = rx[ICMPv6ND_NA]
200 return Host(mac=na.lladdr, ip6=na.tgt)
201
202 def na_resp_hosts(self, src_host, pkts):
203 return {self.na_resp_host(src_host, p) for p in pkts}
Eyal Baric86e5922017-07-02 18:33:16 +0300204
205 def set_bd_flags(self, bd_id, **args):
206 """
207 Enable/disable defined feature(s) of the bridge domain.
208
209 :param int bd_id: Bridge domain ID.
210 :param list args: List of feature/status pairs. Allowed features: \
211 learn, forward, flood, uu_flood and arp_term. Status False means \
212 disable, status True means enable the feature.
213 :raise: ValueError in case of unknown feature in the input.
214 """
215 for flag in args:
216 if flag == "learn":
217 feature_bitmap = 1 << 0
218 elif flag == "forward":
219 feature_bitmap = 1 << 1
220 elif flag == "flood":
221 feature_bitmap = 1 << 2
222 elif flag == "uu_flood":
223 feature_bitmap = 1 << 3
224 elif flag == "arp_term":
225 feature_bitmap = 1 << 4
226 else:
227 raise ValueError("Unknown feature used: %s" % flag)
228 is_set = 1 if args[flag] else 0
Ole Troana5b2eec2019-03-11 19:23:25 +0100229 self.vapi.bridge_flags(bd_id=bd_id, is_set=is_set,
230 flags=feature_bitmap)
Eyal Baric86e5922017-07-02 18:33:16 +0300231 self.logger.info("Bridge domain ID %d updated" % bd_id)
232
233 def verify_arp(self, src_host, req_hosts, resp_hosts, bd_id=1):
234 reqs = self.arp_reqs(src_host, req_hosts)
235
236 for swif in self.bd_swifs(bd_id):
237 swif.add_stream(reqs)
238
239 self.pg_enable_capture(self.pg_interfaces)
240 self.pg_start()
241
242 for swif in self.bd_swifs(bd_id):
243 resp_pkts = swif.get_capture(len(resp_hosts))
244 resps = self.arp_resp_hosts(src_host, resp_pkts)
245 self.assertEqual(len(resps ^ resp_hosts), 0)
246
Eyal Bari758137a2017-07-05 14:31:30 +0300247 def verify_nd(self, src_host, req_hosts, resp_hosts, bd_id=1):
Eyal Baric125ecc2017-09-20 11:29:17 +0300248 reqs = self.ns_reqs_src(src_host, req_hosts)
Eyal Bari758137a2017-07-05 14:31:30 +0300249
250 for swif in self.bd_swifs(bd_id):
251 swif.add_stream(reqs)
252
253 self.pg_enable_capture(self.pg_interfaces)
254 self.pg_start()
255
256 for swif in self.bd_swifs(bd_id):
257 resp_pkts = swif.get_capture(len(resp_hosts))
258 resps = self.na_resp_hosts(src_host, resp_pkts)
259 self.assertEqual(len(resps ^ resp_hosts), 0)
260
Eyal Baric86e5922017-07-02 18:33:16 +0300261 def test_l2bd_arp_term_01(self):
262 """ L2BD arp term - add 5 hosts, verify arp responses
263 """
264 src_host = self.ip4_host(50, 50, "00:00:11:22:33:44")
265 self.bd_add_del(1, is_add=1)
266 self.set_bd_flags(1, arp_term=True, flood=False,
267 uu_flood=False, learn=False)
268 macs = self.mac_list(range(1, 5))
269 hosts = self.ip4_hosts(4, 1, macs)
270 self.add_del_arp_term_hosts(hosts, is_add=1)
Neale Ranns4d5b9172018-10-24 02:57:49 -0700271
Eyal Baric86e5922017-07-02 18:33:16 +0300272 self.verify_arp(src_host, hosts, hosts)
273 type(self).hosts = hosts
274
275 def test_l2bd_arp_term_02(self):
276 """ L2BD arp term - delete 3 hosts, verify arp responses
277 """
278 src_host = self.ip4_host(50, 50, "00:00:11:22:33:44")
279 macs = self.mac_list(range(1, 3))
280 deleted = self.ip4_hosts(4, 1, macs)
281 self.add_del_arp_term_hosts(deleted, is_add=0)
282 remaining = self.hosts - deleted
283 self.verify_arp(src_host, self.hosts, remaining)
284 type(self).hosts = remaining
285 self.bd_add_del(1, is_add=0)
286
287 def test_l2bd_arp_term_03(self):
288 """ L2BD arp term - recreate BD1, readd 3 hosts, verify arp responses
289 """
290 src_host = self.ip4_host(50, 50, "00:00:11:22:33:44")
291 self.bd_add_del(1, is_add=1)
292 self.set_bd_flags(1, arp_term=True, flood=False,
293 uu_flood=False, learn=False)
294 macs = self.mac_list(range(1, 3))
295 readded = self.ip4_hosts(4, 1, macs)
296 self.add_del_arp_term_hosts(readded, is_add=1)
297 self.verify_arp(src_host, self.hosts | readded, readded)
298 type(self).hosts = readded
299
300 def test_l2bd_arp_term_04(self):
301 """ L2BD arp term - 2 IP4 addrs per host
302 """
303 src_host = self.ip4_host(50, 50, "00:00:11:22:33:44")
304 macs = self.mac_list(range(1, 3))
305 sub5_hosts = self.ip4_hosts(5, 1, macs)
306 self.add_del_arp_term_hosts(sub5_hosts, is_add=1)
307 hosts = self.hosts | sub5_hosts
308 self.verify_arp(src_host, hosts, hosts)
309 type(self).hosts = hosts
310 self.bd_add_del(1, is_add=0)
311
312 def test_l2bd_arp_term_05(self):
313 """ L2BD arp term - create and update 10 IP4-mac pairs
314 """
315 src_host = self.ip4_host(50, 50, "00:00:11:22:33:44")
316 self.bd_add_del(1, is_add=1)
317 self.set_bd_flags(1, arp_term=True, flood=False,
318 uu_flood=False, learn=False)
319 macs1 = self.mac_list(range(10, 20))
320 hosts1 = self.ip4_hosts(5, 1, macs1)
321 self.add_del_arp_term_hosts(hosts1, is_add=1)
322 self.verify_arp(src_host, hosts1, hosts1)
323 macs2 = self.mac_list(range(20, 30))
324 hosts2 = self.ip4_hosts(5, 1, macs2)
325 self.add_del_arp_term_hosts(hosts2, is_add=1)
326 self.verify_arp(src_host, hosts1, hosts2)
327 self.bd_add_del(1, is_add=0)
328
Eyal Bari758137a2017-07-05 14:31:30 +0300329 def test_l2bd_arp_term_06(self):
330 """ L2BD arp/ND term - hosts with both ip4/ip6
331 """
332 src_host4 = self.ip4_host(50, 50, "00:00:11:22:33:44")
333 src_host6 = self.ip6_host(50, 50, "00:00:11:22:33:44")
334 self.bd_add_del(1, is_add=1)
335 # enable flood to make sure requests are not flooded
336 self.set_bd_flags(1, arp_term=True, flood=True,
337 uu_flood=False, learn=False)
338 macs = self.mac_list(range(10, 20))
339 hosts6 = self.ip6_hosts(5, 1, macs)
340 hosts4 = self.ip4_hosts(5, 1, macs)
341 self.add_del_arp_term_hosts(hosts4, is_add=1)
342 self.add_del_arp_term_hosts(hosts6, is_add=1, is_ipv6=1)
343 self.verify_arp(src_host4, hosts4, hosts4)
344 self.verify_nd(src_host6, hosts6, hosts6)
345 self.bd_add_del(1, is_add=0)
346
347 def test_l2bd_arp_term_07(self):
348 """ L2BD ND term - Add and Del hosts, verify ND replies
349 """
350 src_host6 = self.ip6_host(50, 50, "00:00:11:22:33:44")
351 self.bd_add_del(1, is_add=1)
352 self.set_bd_flags(1, arp_term=True, flood=False,
353 uu_flood=False, learn=False)
354 macs = self.mac_list(range(10, 20))
355 hosts6 = self.ip6_hosts(5, 1, macs)
356 self.add_del_arp_term_hosts(hosts6, is_add=1, is_ipv6=1)
357 self.verify_nd(src_host6, hosts6, hosts6)
358 del_macs = self.mac_list(range(10, 15))
359 deleted = self.ip6_hosts(5, 1, del_macs)
360 self.add_del_arp_term_hosts(deleted, is_add=0, is_ipv6=1)
361 self.verify_nd(src_host6, hosts6, hosts6 - deleted)
362 self.bd_add_del(1, is_add=0)
363
364 def test_l2bd_arp_term_08(self):
365 """ L2BD ND term - Add and update IP+mac, verify ND replies
366 """
367 src_host = self.ip6_host(50, 50, "00:00:11:22:33:44")
368 self.bd_add_del(1, is_add=1)
369 self.set_bd_flags(1, arp_term=True, flood=False,
370 uu_flood=False, learn=False)
371 macs1 = self.mac_list(range(10, 20))
372 hosts = self.ip6_hosts(5, 1, macs1)
373 self.add_del_arp_term_hosts(hosts, is_add=1, is_ipv6=1)
374 self.verify_nd(src_host, hosts, hosts)
375 macs2 = self.mac_list(range(20, 30))
376 updated = self.ip6_hosts(5, 1, macs2)
377 self.add_del_arp_term_hosts(updated, is_add=1, is_ipv6=1)
378 self.verify_nd(src_host, hosts, updated)
379 self.bd_add_del(1, is_add=0)
380
Eyal Bari20197482017-09-13 12:29:08 +0300381 def test_l2bd_arp_term_09(self):
382 """ L2BD arp term - send garps, verify arp event reports
383 """
384 self.vapi.want_ip4_arp_events()
385 self.bd_add_del(1, is_add=1)
386 self.set_bd_flags(1, arp_term=True, flood=False,
387 uu_flood=False, learn=False)
388 macs = self.mac_list(range(90, 95))
389 hosts = self.ip4_hosts(5, 1, macs)
390
391 garps = self.garp_reqs(hosts)
392 self.bd_swifs(1)[0].add_stream(garps)
393
394 self.pg_enable_capture(self.pg_interfaces)
395 self.pg_start()
396 evs = [self.vapi.wait_for_event(1, "ip4_arp_event")
397 for i in range(len(hosts))]
398 ev_hosts = self.arp_event_hosts(evs)
399 self.assertEqual(len(ev_hosts ^ hosts), 0)
400
401 def test_l2bd_arp_term_10(self):
402 """ L2BD arp term - send duplicate garps, verify suppression
403 """
404 macs = self.mac_list(range(70, 71))
405 hosts = self.ip4_hosts(6, 1, macs)
406
407 """ send the packet 5 times expect one event
408 """
409 garps = self.garp_reqs(hosts) * 5
410 self.bd_swifs(1)[0].add_stream(garps)
411
412 self.pg_enable_capture(self.pg_interfaces)
413 self.pg_start()
414 evs = [self.vapi.wait_for_event(1, "ip4_arp_event")
415 for i in range(len(hosts))]
416 ev_hosts = self.arp_event_hosts(evs)
417 self.assertEqual(len(ev_hosts ^ hosts), 0)
418
419 def test_l2bd_arp_term_11(self):
420 """ L2BD arp term - disable ip4 arp events,send garps, verify no events
421 """
422 self.vapi.want_ip4_arp_events(enable_disable=0)
423 macs = self.mac_list(range(90, 95))
424 hosts = self.ip4_hosts(5, 1, macs)
425
426 garps = self.garp_reqs(hosts)
427 self.bd_swifs(1)[0].add_stream(garps)
428
429 self.pg_enable_capture(self.pg_interfaces)
430 self.pg_start()
431 self.sleep(1)
432 self.assertEqual(len(self.vapi.collect_events()), 0)
433 self.bd_add_del(1, is_add=0)
434
Eyal Baric125ecc2017-09-20 11:29:17 +0300435 def test_l2bd_arp_term_12(self):
436 """ L2BD ND term - send NS packets verify reports
437 """
Neale Ranns37029302018-08-10 05:30:06 -0700438 self.vapi.want_ip6_nd_events(ip="::")
Eyal Baric125ecc2017-09-20 11:29:17 +0300439 dst_host = self.ip6_host(50, 50, "00:00:11:22:33:44")
440 self.bd_add_del(1, is_add=1)
441 self.set_bd_flags(1, arp_term=True, flood=False,
442 uu_flood=False, learn=False)
443 macs = self.mac_list(range(10, 15))
444 hosts = self.ip6_hosts(5, 1, macs)
445 reqs = self.ns_reqs_dst(hosts, dst_host)
446 self.bd_swifs(1)[0].add_stream(reqs)
447
448 self.pg_enable_capture(self.pg_interfaces)
449 self.pg_start()
450 evs = [self.vapi.wait_for_event(2, "ip6_nd_event")
451 for i in range(len(hosts))]
452 ev_hosts = self.nd_event_hosts(evs)
453 self.assertEqual(len(ev_hosts ^ hosts), 0)
454
455 def test_l2bd_arp_term_13(self):
456 """ L2BD ND term - send duplicate ns, verify suppression
457 """
458 dst_host = self.ip6_host(50, 50, "00:00:11:22:33:44")
459 macs = self.mac_list(range(10, 11))
460 hosts = self.ip6_hosts(5, 1, macs)
461 reqs = self.ns_reqs_dst(hosts, dst_host) * 5
462 self.bd_swifs(1)[0].add_stream(reqs)
463
464 self.pg_enable_capture(self.pg_interfaces)
465 self.pg_start()
466 evs = [self.vapi.wait_for_event(2, "ip6_nd_event")
467 for i in range(len(hosts))]
468 ev_hosts = self.nd_event_hosts(evs)
469 self.assertEqual(len(ev_hosts ^ hosts), 0)
470
471 def test_l2bd_arp_term_14(self):
472 """ L2BD ND term - disable ip4 arp events,send ns, verify no events
473 """
Neale Ranns37029302018-08-10 05:30:06 -0700474 self.vapi.want_ip6_nd_events(enable_disable=0, ip="::")
Eyal Baric125ecc2017-09-20 11:29:17 +0300475 dst_host = self.ip6_host(50, 50, "00:00:11:22:33:44")
476 macs = self.mac_list(range(10, 15))
477 hosts = self.ip6_hosts(5, 1, macs)
478 reqs = self.ns_reqs_dst(hosts, dst_host)
479 self.bd_swifs(1)[0].add_stream(reqs)
480
481 self.pg_enable_capture(self.pg_interfaces)
482 self.pg_start()
483 self.sleep(1)
484 self.assertEqual(len(self.vapi.collect_events()), 0)
485 self.bd_add_del(1, is_add=0)
486
Eyal Baric86e5922017-07-02 18:33:16 +0300487
488if __name__ == '__main__':
489 unittest.main(testRunner=VppTestRunner)