L2 BD: introduce a BD interface on which to send UU packets
[vpp.git] / test / test_acl_plugin_l2l3.py
1 #!/usr/bin/env python
2 """ACL IRB Test Case HLD:
3
4 **config**
5     - L2 MAC learning enabled in l2bd
6     - 2 routed interfaces untagged, bvi (Bridge Virtual Interface)
7     - 2 bridged interfaces in l2bd with bvi
8
9 **test**
10     - sending ip4 eth pkts between routed interfaces
11         - 2 routed interfaces
12         - 2 bridged interfaces
13
14     - 64B, 512B, 1518B, 9200B (ether_size)
15
16     - burst of pkts per interface
17         - 257pkts per burst
18         - routed pkts hitting different FIB entries
19         - bridged pkts hitting different MAC entries
20
21 **verify**
22     - all packets received correctly
23
24 """
25
26 import unittest
27 from socket import inet_pton, AF_INET, AF_INET6
28 from random import choice, shuffle
29 from pprint import pprint
30
31 from scapy.packet import Raw
32 from scapy.layers.l2 import Ether
33 from scapy.layers.inet import IP, UDP, ICMP, TCP
34 from scapy.layers.inet6 import IPv6, ICMPv6Unknown, ICMPv6EchoRequest
35 from scapy.layers.inet6 import ICMPv6EchoReply, IPv6ExtHdrRouting
36 from scapy.layers.inet6 import IPv6ExtHdrFragment
37
38 from framework import VppTestCase, VppTestRunner
39 from vpp_papi_provider import L2_PORT_TYPE
40 import time
41
42
43 class TestIpIrb(VppTestCase):
44     """IRB Test Case"""
45
46     @classmethod
47     def setUpClass(cls):
48         """
49         #. Create BD with MAC learning enabled and put interfaces to this BD.
50         #. Configure IPv4 addresses on loopback interface and routed interface.
51         #. Configure MAC address binding to IPv4 neighbors on loop0.
52         #. Configure MAC address on pg2.
53         #. Loopback BVI interface has remote hosts, one half of hosts are
54            behind pg0 second behind pg1.
55         """
56         super(TestIpIrb, cls).setUpClass()
57
58         cls.pg_if_packet_sizes = [64, 512, 1518, 9018]  # packet sizes
59         cls.bd_id = 10
60         cls.remote_hosts_count = 250
61
62         # create 3 pg interfaces, 1 loopback interface
63         cls.create_pg_interfaces(range(3))
64         cls.create_loopback_interfaces(1)
65
66         cls.interfaces = list(cls.pg_interfaces)
67         cls.interfaces.extend(cls.lo_interfaces)
68
69         for i in cls.interfaces:
70             i.admin_up()
71
72         # Create BD with MAC learning enabled and put interfaces to this BD
73         cls.vapi.sw_interface_set_l2_bridge(
74             cls.loop0.sw_if_index, bd_id=cls.bd_id,
75             port_type=L2_PORT_TYPE.BVI)
76         cls.vapi.sw_interface_set_l2_bridge(
77             cls.pg0.sw_if_index, bd_id=cls.bd_id)
78         cls.vapi.sw_interface_set_l2_bridge(
79             cls.pg1.sw_if_index, bd_id=cls.bd_id)
80
81         # Configure IPv4 addresses on loopback interface and routed interface
82         cls.loop0.config_ip4()
83         cls.loop0.config_ip6()
84         cls.pg2.config_ip4()
85         cls.pg2.config_ip6()
86
87         # Configure MAC address binding to IPv4 neighbors on loop0
88         cls.loop0.generate_remote_hosts(cls.remote_hosts_count)
89         cls.loop0.configure_ipv4_neighbors()
90         cls.loop0.configure_ipv6_neighbors()
91         # configure MAC address on pg2
92         cls.pg2.resolve_arp()
93         cls.pg2.resolve_ndp()
94
95         cls.WITHOUT_EH = False
96         cls.WITH_EH = True
97
98         # Loopback BVI interface has remote hosts, one half of hosts are behind
99         # pg0 second behind pg1
100         half = cls.remote_hosts_count // 2
101         cls.pg0.remote_hosts = cls.loop0.remote_hosts[:half]
102         cls.pg1.remote_hosts = cls.loop0.remote_hosts[half:]
103
104     def tearDown(self):
105         """Run standard test teardown and log ``show l2patch``,
106         ``show l2fib verbose``,``show bridge-domain <bd_id> detail``,
107         ``show ip arp``.
108         """
109         super(TestIpIrb, self).tearDown()
110         if not self.vpp_dead:
111             self.logger.info(self.vapi.cli("show l2patch"))
112             self.logger.info(self.vapi.cli("show classify tables"))
113             self.logger.info(self.vapi.cli("show vlib graph"))
114             self.logger.info(self.vapi.cli("show l2fib verbose"))
115             self.logger.info(self.vapi.cli("show bridge-domain %s detail" %
116                                            self.bd_id))
117             self.logger.info(self.vapi.cli("show ip arp"))
118             self.logger.info(self.vapi.cli("show ip6 neighbors"))
119             self.logger.info(self.vapi.cli("show acl-plugin sessions"))
120             self.logger.info(self.vapi.cli("show acl-plugin acl"))
121             self.logger.info(self.vapi.cli("show acl-plugin interface"))
122             self.logger.info(self.vapi.cli("show acl-plugin tables"))
123
124     def create_stream(self, src_ip_if, dst_ip_if, reverse, packet_sizes,
125                       is_ip6, expect_blocked, expect_established,
126                       add_extension_header):
127         pkts = []
128         rules = []
129         permit_rules = []
130         permit_and_reflect_rules = []
131         total_packet_count = 8
132         for i in range(0, total_packet_count):
133             modulo = (i//2) % 2
134             can_reflect_this_packet = (modulo == 0)
135             is_permit = i % 2
136             remote_dst_index = i % len(dst_ip_if.remote_hosts)
137             remote_dst_host = dst_ip_if.remote_hosts[remote_dst_index]
138             if is_permit == 1:
139                 info = self.create_packet_info(src_ip_if, dst_ip_if)
140                 payload = self.info_to_payload(info)
141             else:
142                 to_be_blocked = False
143                 if (expect_blocked and not expect_established):
144                     to_be_blocked = True
145                 if (not can_reflect_this_packet):
146                     to_be_blocked = True
147                 if to_be_blocked:
148                     payload = "to be blocked"
149                 else:
150                     info = self.create_packet_info(src_ip_if, dst_ip_if)
151                     payload = self.info_to_payload(info)
152             if reverse:
153                 dst_mac = 'de:ad:00:00:00:00'
154                 src_mac = remote_dst_host._mac
155                 dst_ip6 = src_ip_if.remote_ip6
156                 src_ip6 = remote_dst_host.ip6
157                 dst_ip4 = src_ip_if.remote_ip4
158                 src_ip4 = remote_dst_host.ip4
159                 dst_l4 = 1234 + i
160                 src_l4 = 4321 + i
161             else:
162                 dst_mac = src_ip_if.local_mac
163                 src_mac = src_ip_if.remote_mac
164                 src_ip6 = src_ip_if.remote_ip6
165                 dst_ip6 = remote_dst_host.ip6
166                 src_ip4 = src_ip_if.remote_ip4
167                 dst_ip4 = remote_dst_host.ip4
168                 src_l4 = 1234 + i
169                 dst_l4 = 4321 + i
170
171             # default ULP should be something we do not use in tests
172             ulp_l4 = TCP(sport=src_l4, dport=dst_l4)
173             # potentially a chain of protocols leading to ULP
174             ulp = ulp_l4
175
176             if can_reflect_this_packet:
177                 if is_ip6:
178                     ulp_l4 = UDP(sport=src_l4, dport=dst_l4)
179                     if add_extension_header:
180                         # prepend some extension headers
181                         ulp = (IPv6ExtHdrRouting() / IPv6ExtHdrRouting() /
182                                IPv6ExtHdrFragment(offset=0, m=1) / ulp_l4)
183                         # uncomment below to test invalid ones
184                         # ulp = IPv6ExtHdrRouting(len = 200) / ulp_l4
185                     else:
186                         ulp = ulp_l4
187                     p = (Ether(dst=dst_mac, src=src_mac) /
188                          IPv6(src=src_ip6, dst=dst_ip6) /
189                          ulp /
190                          Raw(payload))
191                 else:
192                     ulp_l4 = UDP(sport=src_l4, dport=dst_l4)
193                     # IPv4 does not allow extension headers,
194                     # but we rather make it a first fragment
195                     flags = 1 if add_extension_header else 0
196                     ulp = ulp_l4
197                     p = (Ether(dst=dst_mac, src=src_mac) /
198                          IP(src=src_ip4, dst=dst_ip4, frag=0, flags=flags) /
199                          ulp /
200                          Raw(payload))
201             elif modulo == 1:
202                 if is_ip6:
203                     ulp_l4 = ICMPv6Unknown(type=128 + (i % 2), code=i % 2)
204                     ulp = ulp_l4
205                     p = (Ether(dst=dst_mac, src=src_mac) /
206                          IPv6(src=src_ip6, dst=dst_ip6) /
207                          ulp /
208                          Raw(payload))
209                 else:
210                     ulp_l4 = ICMP(type=8 + (i % 2), code=i % 2)
211                     ulp = ulp_l4
212                     p = (Ether(dst=dst_mac, src=src_mac) /
213                          IP(src=src_ip4, dst=dst_ip4) /
214                          ulp /
215                          Raw(payload))
216
217             if i % 2 == 1:
218                 info.data = p.copy()
219             size = packet_sizes[(i // 2) % len(packet_sizes)]
220             self.extend_packet(p, size)
221             pkts.append(p)
222
223             rule_family = AF_INET6 if p.haslayer(IPv6) else AF_INET
224             rule_prefix_len = 128 if p.haslayer(IPv6) else 32
225             rule_l3_layer = IPv6 if p.haslayer(IPv6) else IP
226
227             if p.haslayer(UDP):
228                 rule_l4_sport = p[UDP].sport
229                 rule_l4_dport = p[UDP].dport
230             else:
231                 if p.haslayer(ICMP):
232                     rule_l4_sport = p[ICMP].type
233                     rule_l4_dport = p[ICMP].code
234                 else:
235                     rule_l4_sport = p[ICMPv6Unknown].type
236                     rule_l4_dport = p[ICMPv6Unknown].code
237             if p.haslayer(IPv6):
238                 rule_l4_proto = ulp_l4.overload_fields[IPv6]['nh']
239             else:
240                 rule_l4_proto = p[IP].proto
241
242             new_rule = {
243                         'is_permit': is_permit,
244                         'is_ipv6': p.haslayer(IPv6),
245                         'src_ip_addr': inet_pton(rule_family,
246                                                  p[rule_l3_layer].src),
247                         'src_ip_prefix_len': rule_prefix_len,
248                         'dst_ip_addr': inet_pton(rule_family,
249                                                  p[rule_l3_layer].dst),
250                         'dst_ip_prefix_len': rule_prefix_len,
251                         'srcport_or_icmptype_first': rule_l4_sport,
252                         'srcport_or_icmptype_last': rule_l4_sport,
253                         'dstport_or_icmpcode_first': rule_l4_dport,
254                         'dstport_or_icmpcode_last': rule_l4_dport,
255                         'proto': rule_l4_proto,
256                        }
257             rules.append(new_rule)
258             new_rule_permit = new_rule.copy()
259             new_rule_permit['is_permit'] = 1
260             permit_rules.append(new_rule_permit)
261
262             new_rule_permit_and_reflect = new_rule.copy()
263             if can_reflect_this_packet:
264                 new_rule_permit_and_reflect['is_permit'] = 2
265             else:
266                 new_rule_permit_and_reflect['is_permit'] = is_permit
267             permit_and_reflect_rules.append(new_rule_permit_and_reflect)
268
269         return {'stream': pkts,
270                 'rules': rules,
271                 'permit_rules': permit_rules,
272                 'permit_and_reflect_rules': permit_and_reflect_rules}
273
274     def verify_capture(self, dst_ip_if, src_ip_if, capture, reverse):
275         last_info = dict()
276         for i in self.interfaces:
277             last_info[i.sw_if_index] = None
278
279         dst_ip_sw_if_index = dst_ip_if.sw_if_index
280         return
281
282         for packet in capture:
283             l3 = IP if packet.haslayer(IP) else IPv6
284             ip = packet[l3]
285             if packet.haslayer(UDP):
286                 l4 = UDP
287             else:
288                 if packet.haslayer(ICMP):
289                     l4 = ICMP
290                 else:
291                     l4 = ICMPv6Unknown
292
293             # Scapy IPv6 stuff is too smart for its own good.
294             # So we do this and coerce the ICMP into unknown type
295             if packet.haslayer(UDP):
296                 data = str(packet[UDP][Raw])
297             else:
298                 if l3 == IP:
299                     data = str(ICMP(str(packet[l3].payload))[Raw])
300                 else:
301                     data = str(ICMPv6Unknown(str(packet[l3].payload)).msgbody)
302             udp_or_icmp = packet[l3].payload
303             payload_info = self.payload_to_info(data)
304             packet_index = payload_info.index
305
306             self.assertEqual(payload_info.dst, dst_ip_sw_if_index)
307
308             next_info = self.get_next_packet_info_for_interface2(
309                 payload_info.src, dst_ip_sw_if_index,
310                 last_info[payload_info.src])
311             last_info[payload_info.src] = next_info
312             self.assertTrue(next_info is not None)
313             self.assertEqual(packet_index, next_info.index)
314             saved_packet = next_info.data
315             self.assertTrue(next_info is not None)
316
317             # MAC: src, dst
318             if not reverse:
319                 self.assertEqual(packet.src, dst_ip_if.local_mac)
320                 host = dst_ip_if.host_by_mac(packet.dst)
321
322             # IP: src, dst
323             # self.assertEqual(ip.src, src_ip_if.remote_ip4)
324             if saved_packet is not None:
325                 self.assertEqual(ip.src, saved_packet[l3].src)
326                 self.assertEqual(ip.dst, saved_packet[l3].dst)
327                 if l4 == UDP:
328                     self.assertEqual(udp_or_icmp.sport, saved_packet[l4].sport)
329                     self.assertEqual(udp_or_icmp.dport, saved_packet[l4].dport)
330             else:
331                 print("Saved packet is none")
332             # self.assertEqual(ip.dst, host.ip4)
333
334             # UDP:
335
336     def applied_acl_shuffle(self, sw_if_index):
337         # first collect what ACLs are applied and what they look like
338         r = self.vapi.acl_interface_list_dump(sw_if_index=sw_if_index)
339         orig_applied_acls = r[0]
340
341         # we will collect these just to save and generate additional rulesets
342         orig_acls = []
343         for acl_num in orig_applied_acls.acls:
344             rr = self.vapi.acl_dump(acl_num)
345             orig_acls.append(rr[0])
346
347         # now create a list of all the rules in all ACLs
348         all_rules = []
349         for old_acl in orig_acls:
350             for rule in old_acl.r:
351                 all_rules.append(dict(rule._asdict()))
352
353         # Add a few ACLs made from shuffled rules
354         shuffle(all_rules)
355         reply = self.vapi.acl_add_replace(acl_index=4294967295,
356                                           r=all_rules[::2],
357                                           tag="shuffle 1. acl")
358         shuffle_acl_1 = reply.acl_index
359         shuffle(all_rules)
360         reply = self.vapi.acl_add_replace(acl_index=4294967295,
361                                           r=all_rules[::3],
362                                           tag="shuffle 2. acl")
363         shuffle_acl_2 = reply.acl_index
364         shuffle(all_rules)
365         reply = self.vapi.acl_add_replace(acl_index=4294967295,
366                                           r=all_rules[::2],
367                                           tag="shuffle 3. acl")
368         shuffle_acl_3 = reply.acl_index
369
370         # apply the shuffle ACLs in front
371         input_acls = [shuffle_acl_1, shuffle_acl_2]
372         output_acls = [shuffle_acl_1, shuffle_acl_2]
373
374         # add the currently applied ACLs
375         n_input = orig_applied_acls.n_input
376         input_acls.extend(orig_applied_acls.acls[:n_input])
377         output_acls.extend(orig_applied_acls.acls[n_input:])
378
379         # and the trailing shuffle ACL(s)
380         input_acls.extend([shuffle_acl_3])
381         output_acls.extend([shuffle_acl_3])
382
383         # set the interface ACL list to the result
384         self.vapi.acl_interface_set_acl_list(sw_if_index=sw_if_index,
385                                              n_input=len(input_acls),
386                                              acls=input_acls + output_acls)
387         # change the ACLs a few times
388         for i in range(1, 10):
389             shuffle(all_rules)
390             reply = self.vapi.acl_add_replace(acl_index=shuffle_acl_1,
391                                               r=all_rules[::1+(i % 2)],
392                                               tag="shuffle 1. acl")
393             shuffle(all_rules)
394             reply = self.vapi.acl_add_replace(acl_index=shuffle_acl_2,
395                                               r=all_rules[::1+(i % 3)],
396                                               tag="shuffle 2. acl")
397             shuffle(all_rules)
398             reply = self.vapi.acl_add_replace(acl_index=shuffle_acl_2,
399                                               r=all_rules[::1+(i % 5)],
400                                               tag="shuffle 3. acl")
401
402         # restore to how it was before and clean up
403         self.vapi.acl_interface_set_acl_list(sw_if_index=sw_if_index,
404                                              n_input=orig_applied_acls.n_input,
405                                              acls=orig_applied_acls.acls)
406         reply = self.vapi.acl_del(acl_index=shuffle_acl_1)
407         reply = self.vapi.acl_del(acl_index=shuffle_acl_2)
408         reply = self.vapi.acl_del(acl_index=shuffle_acl_3)
409
410     def create_acls_for_a_stream(self, stream_dict,
411                                  test_l2_action, is_reflect):
412         r = stream_dict['rules']
413         r_permit = stream_dict['permit_rules']
414         r_permit_reflect = stream_dict['permit_and_reflect_rules']
415         r_action = r_permit_reflect if is_reflect else r
416         reply = self.vapi.acl_add_replace(acl_index=4294967295, r=r_action,
417                                           tag="act. acl")
418         action_acl_index = reply.acl_index
419         reply = self.vapi.acl_add_replace(acl_index=4294967295, r=r_permit,
420                                           tag="perm. acl")
421         permit_acl_index = reply.acl_index
422         return {'L2': action_acl_index if test_l2_action else permit_acl_index,
423                 'L3': permit_acl_index if test_l2_action else action_acl_index,
424                 'permit': permit_acl_index, 'action': action_acl_index}
425
426     def apply_acl_ip46_x_to_y(self, bridged_to_routed, test_l2_deny,
427                               is_ip6, is_reflect, add_eh):
428         """ Apply the ACLs
429         """
430         self.reset_packet_infos()
431         stream_dict = self.create_stream(
432                                          self.pg2, self.loop0,
433                                          bridged_to_routed,
434                                          self.pg_if_packet_sizes, is_ip6,
435                                          not is_reflect, False, add_eh)
436         stream = stream_dict['stream']
437         acl_idx = self.create_acls_for_a_stream(stream_dict, test_l2_deny,
438                                                 is_reflect)
439         n_input_l3 = 0 if bridged_to_routed else 1
440         n_input_l2 = 1 if bridged_to_routed else 0
441         self.vapi.acl_interface_set_acl_list(sw_if_index=self.pg2.sw_if_index,
442                                              n_input=n_input_l3,
443                                              acls=[acl_idx['L3']])
444         self.vapi.acl_interface_set_acl_list(sw_if_index=self.pg0.sw_if_index,
445                                              n_input=n_input_l2,
446                                              acls=[acl_idx['L2']])
447         self.vapi.acl_interface_set_acl_list(sw_if_index=self.pg1.sw_if_index,
448                                              n_input=n_input_l2,
449                                              acls=[acl_idx['L2']])
450         self.applied_acl_shuffle(self.pg0.sw_if_index)
451         self.applied_acl_shuffle(self.pg2.sw_if_index)
452
453     def apply_acl_ip46_both_directions_reflect(self,
454                                                primary_is_bridged_to_routed,
455                                                reflect_on_l2, is_ip6, add_eh):
456         primary_is_routed_to_bridged = not primary_is_bridged_to_routed
457         self.reset_packet_infos()
458         stream_dict_fwd = self.create_stream(self.pg2, self.loop0,
459                                              primary_is_bridged_to_routed,
460                                              self.pg_if_packet_sizes, is_ip6,
461                                              False, False, add_eh)
462         acl_idx_fwd = self.create_acls_for_a_stream(stream_dict_fwd,
463                                                     reflect_on_l2, True)
464
465         stream_dict_rev = self.create_stream(self.pg2, self.loop0,
466                                              not primary_is_bridged_to_routed,
467                                              self.pg_if_packet_sizes, is_ip6,
468                                              True, True, add_eh)
469         # We want the primary action to be "deny" rather than reflect
470         acl_idx_rev = self.create_acls_for_a_stream(stream_dict_rev,
471                                                     reflect_on_l2, False)
472
473         if primary_is_bridged_to_routed:
474             inbound_l2_acl = acl_idx_fwd['L2']
475         else:
476             inbound_l2_acl = acl_idx_rev['L2']
477
478         if primary_is_routed_to_bridged:
479             outbound_l2_acl = acl_idx_fwd['L2']
480         else:
481             outbound_l2_acl = acl_idx_rev['L2']
482
483         if primary_is_routed_to_bridged:
484             inbound_l3_acl = acl_idx_fwd['L3']
485         else:
486             inbound_l3_acl = acl_idx_rev['L3']
487
488         if primary_is_bridged_to_routed:
489             outbound_l3_acl = acl_idx_fwd['L3']
490         else:
491             outbound_l3_acl = acl_idx_rev['L3']
492
493         self.vapi.acl_interface_set_acl_list(sw_if_index=self.pg2.sw_if_index,
494                                              n_input=1,
495                                              acls=[inbound_l3_acl,
496                                                    outbound_l3_acl])
497         self.vapi.acl_interface_set_acl_list(sw_if_index=self.pg0.sw_if_index,
498                                              n_input=1,
499                                              acls=[inbound_l2_acl,
500                                                    outbound_l2_acl])
501         self.vapi.acl_interface_set_acl_list(sw_if_index=self.pg1.sw_if_index,
502                                              n_input=1,
503                                              acls=[inbound_l2_acl,
504                                                    outbound_l2_acl])
505         self.applied_acl_shuffle(self.pg0.sw_if_index)
506         self.applied_acl_shuffle(self.pg2.sw_if_index)
507
508     def apply_acl_ip46_routed_to_bridged(self, test_l2_deny, is_ip6,
509                                          is_reflect, add_eh):
510         self.apply_acl_ip46_x_to_y(False, test_l2_deny, is_ip6,
511                                    is_reflect, add_eh)
512
513     def apply_acl_ip46_bridged_to_routed(self, test_l2_deny, is_ip6,
514                                          is_reflect, add_eh):
515         self.apply_acl_ip46_x_to_y(True, test_l2_deny, is_ip6,
516                                    is_reflect, add_eh)
517
518     def run_traffic_ip46_x_to_y(self, bridged_to_routed,
519                                 test_l2_deny, is_ip6,
520                                 is_reflect, is_established, add_eh):
521         self.reset_packet_infos()
522         stream_dict = self.create_stream(self.pg2, self.loop0,
523                                          bridged_to_routed,
524                                          self.pg_if_packet_sizes, is_ip6,
525                                          not is_reflect, is_established,
526                                          add_eh)
527         stream = stream_dict['stream']
528
529         tx_if = self.pg0 if bridged_to_routed else self.pg2
530         rx_if = self.pg2 if bridged_to_routed else self.pg0
531
532         tx_if.add_stream(stream)
533         self.pg_enable_capture(self.pg_interfaces)
534         self.pg_start()
535         packet_count = self.get_packet_count_for_if_idx(self.loop0.sw_if_index)
536         rcvd1 = rx_if.get_capture(packet_count)
537         self.verify_capture(self.loop0, self.pg2, rcvd1, bridged_to_routed)
538
539     def run_traffic_ip46_routed_to_bridged(self, test_l2_deny, is_ip6,
540                                            is_reflect, is_established, add_eh):
541         self.run_traffic_ip46_x_to_y(False, test_l2_deny, is_ip6,
542                                      is_reflect, is_established, add_eh)
543
544     def run_traffic_ip46_bridged_to_routed(self, test_l2_deny, is_ip6,
545                                            is_reflect, is_established, add_eh):
546         self.run_traffic_ip46_x_to_y(True, test_l2_deny, is_ip6,
547                                      is_reflect, is_established, add_eh)
548
549     def run_test_ip46_routed_to_bridged(self, test_l2_deny,
550                                         is_ip6, is_reflect, add_eh):
551         self.apply_acl_ip46_routed_to_bridged(test_l2_deny,
552                                               is_ip6, is_reflect, add_eh)
553         self.run_traffic_ip46_routed_to_bridged(test_l2_deny, is_ip6,
554                                                 is_reflect, False, add_eh)
555
556     def run_test_ip46_bridged_to_routed(self, test_l2_deny,
557                                         is_ip6, is_reflect, add_eh):
558         self.apply_acl_ip46_bridged_to_routed(test_l2_deny,
559                                               is_ip6, is_reflect, add_eh)
560         self.run_traffic_ip46_bridged_to_routed(test_l2_deny, is_ip6,
561                                                 is_reflect, False, add_eh)
562
563     def run_test_ip46_routed_to_bridged_and_back(self, test_l2_action,
564                                                  is_ip6, add_eh):
565         self.apply_acl_ip46_both_directions_reflect(False, test_l2_action,
566                                                     is_ip6, add_eh)
567         self.run_traffic_ip46_routed_to_bridged(test_l2_action, is_ip6,
568                                                 True, False, add_eh)
569         self.run_traffic_ip46_bridged_to_routed(test_l2_action, is_ip6,
570                                                 False, True, add_eh)
571
572     def run_test_ip46_bridged_to_routed_and_back(self, test_l2_action,
573                                                  is_ip6, add_eh):
574         self.apply_acl_ip46_both_directions_reflect(True, test_l2_action,
575                                                     is_ip6, add_eh)
576         self.run_traffic_ip46_bridged_to_routed(test_l2_action, is_ip6,
577                                                 True, False, add_eh)
578         self.run_traffic_ip46_routed_to_bridged(test_l2_action, is_ip6,
579                                                 False, True, add_eh)
580
581     def test_0000_ip6_irb_1(self):
582         """ ACL plugin prepare"""
583         if not self.vpp_dead:
584             cmd = "set acl-plugin session timeout udp idle 2000"
585             self.logger.info(self.vapi.ppcli(cmd))
586             # uncomment to not skip past the routing header
587             # and watch the EH tests fail
588             # self.logger.info(self.vapi.ppcli(
589             #    "set acl-plugin skip-ipv6-extension-header 43 0"))
590             # uncomment to test the session limit (stateful tests will fail)
591             # self.logger.info(self.vapi.ppcli(
592             #    "set acl-plugin session table max-entries 1"))
593             # new datapath is the default, but just in case
594             # self.logger.info(self.vapi.ppcli(
595             #    "set acl-plugin l2-datapath new"))
596             # If you want to see some tests fail, uncomment the next line
597             # self.logger.info(self.vapi.ppcli(
598             #    "set acl-plugin l2-datapath old"))
599
600     def test_0001_ip6_irb_1(self):
601         """ ACL IPv6 routed -> bridged, L2 ACL deny"""
602         self.run_test_ip46_routed_to_bridged(True, True, False,
603                                              self.WITHOUT_EH)
604
605     def test_0002_ip6_irb_1(self):
606         """ ACL IPv6 routed -> bridged, L3 ACL deny"""
607         self.run_test_ip46_routed_to_bridged(False, True, False,
608                                              self.WITHOUT_EH)
609
610     def test_0003_ip4_irb_1(self):
611         """ ACL IPv4 routed -> bridged, L2 ACL deny"""
612         self.run_test_ip46_routed_to_bridged(True, False, False,
613                                              self.WITHOUT_EH)
614
615     def test_0004_ip4_irb_1(self):
616         """ ACL IPv4 routed -> bridged, L3 ACL deny"""
617         self.run_test_ip46_routed_to_bridged(False, False, False,
618                                              self.WITHOUT_EH)
619
620     def test_0005_ip6_irb_1(self):
621         """ ACL IPv6 bridged -> routed, L2 ACL deny """
622         self.run_test_ip46_bridged_to_routed(True, True, False,
623                                              self.WITHOUT_EH)
624
625     def test_0006_ip6_irb_1(self):
626         """ ACL IPv6 bridged -> routed, L3 ACL deny """
627         self.run_test_ip46_bridged_to_routed(False, True, False,
628                                              self.WITHOUT_EH)
629
630     def test_0007_ip6_irb_1(self):
631         """ ACL IPv4 bridged -> routed, L2 ACL deny """
632         self.run_test_ip46_bridged_to_routed(True, False, False,
633                                              self.WITHOUT_EH)
634
635     def test_0008_ip6_irb_1(self):
636         """ ACL IPv4 bridged -> routed, L3 ACL deny """
637         self.run_test_ip46_bridged_to_routed(False, False, False,
638                                              self.WITHOUT_EH)
639
640     # Stateful ACL tests
641     def test_0101_ip6_irb_1(self):
642         """ ACL IPv6 routed -> bridged, L2 ACL permit+reflect"""
643         self.run_test_ip46_routed_to_bridged_and_back(True, True,
644                                                       self.WITHOUT_EH)
645
646     def test_0102_ip6_irb_1(self):
647         """ ACL IPv6 bridged -> routed, L2 ACL permit+reflect"""
648         self.run_test_ip46_bridged_to_routed_and_back(True, True,
649                                                       self.WITHOUT_EH)
650
651     def test_0103_ip6_irb_1(self):
652         """ ACL IPv4 routed -> bridged, L2 ACL permit+reflect"""
653         self.run_test_ip46_routed_to_bridged_and_back(True, False,
654                                                       self.WITHOUT_EH)
655
656     def test_0104_ip6_irb_1(self):
657         """ ACL IPv4 bridged -> routed, L2 ACL permit+reflect"""
658         self.run_test_ip46_bridged_to_routed_and_back(True, False,
659                                                       self.WITHOUT_EH)
660
661     def test_0111_ip6_irb_1(self):
662         """ ACL IPv6 routed -> bridged, L3 ACL permit+reflect"""
663         self.run_test_ip46_routed_to_bridged_and_back(False, True,
664                                                       self.WITHOUT_EH)
665
666     def test_0112_ip6_irb_1(self):
667         """ ACL IPv6 bridged -> routed, L3 ACL permit+reflect"""
668         self.run_test_ip46_bridged_to_routed_and_back(False, True,
669                                                       self.WITHOUT_EH)
670
671     def test_0113_ip6_irb_1(self):
672         """ ACL IPv4 routed -> bridged, L3 ACL permit+reflect"""
673         self.run_test_ip46_routed_to_bridged_and_back(False, False,
674                                                       self.WITHOUT_EH)
675
676     def test_0114_ip6_irb_1(self):
677         """ ACL IPv4 bridged -> routed, L3 ACL permit+reflect"""
678         self.run_test_ip46_bridged_to_routed_and_back(False, False,
679                                                       self.WITHOUT_EH)
680
681     # A block of tests with extension headers
682
683     def test_1001_ip6_irb_1(self):
684         """ ACL IPv6+EH routed -> bridged, L2 ACL deny"""
685         self.run_test_ip46_routed_to_bridged(True, True, False,
686                                              self.WITH_EH)
687
688     def test_1002_ip6_irb_1(self):
689         """ ACL IPv6+EH routed -> bridged, L3 ACL deny"""
690         self.run_test_ip46_routed_to_bridged(False, True, False,
691                                              self.WITH_EH)
692
693     def test_1005_ip6_irb_1(self):
694         """ ACL IPv6+EH bridged -> routed, L2 ACL deny """
695         self.run_test_ip46_bridged_to_routed(True, True, False,
696                                              self.WITH_EH)
697
698     def test_1006_ip6_irb_1(self):
699         """ ACL IPv6+EH bridged -> routed, L3 ACL deny """
700         self.run_test_ip46_bridged_to_routed(False, True, False,
701                                              self.WITH_EH)
702
703     def test_1101_ip6_irb_1(self):
704         """ ACL IPv6+EH routed -> bridged, L2 ACL permit+reflect"""
705         self.run_test_ip46_routed_to_bridged_and_back(True, True,
706                                                       self.WITH_EH)
707
708     def test_1102_ip6_irb_1(self):
709         """ ACL IPv6+EH bridged -> routed, L2 ACL permit+reflect"""
710         self.run_test_ip46_bridged_to_routed_and_back(True, True,
711                                                       self.WITH_EH)
712
713     def test_1111_ip6_irb_1(self):
714         """ ACL IPv6+EH routed -> bridged, L3 ACL permit+reflect"""
715         self.run_test_ip46_routed_to_bridged_and_back(False, True,
716                                                       self.WITH_EH)
717
718     def test_1112_ip6_irb_1(self):
719         """ ACL IPv6+EH bridged -> routed, L3 ACL permit+reflect"""
720         self.run_test_ip46_bridged_to_routed_and_back(False, True,
721                                                       self.WITH_EH)
722
723     # IPv4 with "MF" bit set
724
725     def test_1201_ip6_irb_1(self):
726         """ ACL IPv4+MF routed -> bridged, L2 ACL deny"""
727         self.run_test_ip46_routed_to_bridged(True, False, False,
728                                              self.WITH_EH)
729
730     def test_1202_ip6_irb_1(self):
731         """ ACL IPv4+MF routed -> bridged, L3 ACL deny"""
732         self.run_test_ip46_routed_to_bridged(False, False, False,
733                                              self.WITH_EH)
734
735     def test_1205_ip6_irb_1(self):
736         """ ACL IPv4+MF bridged -> routed, L2 ACL deny """
737         self.run_test_ip46_bridged_to_routed(True, False, False,
738                                              self.WITH_EH)
739
740     def test_1206_ip6_irb_1(self):
741         """ ACL IPv4+MF bridged -> routed, L3 ACL deny """
742         self.run_test_ip46_bridged_to_routed(False, False, False,
743                                              self.WITH_EH)
744
745     def test_1301_ip6_irb_1(self):
746         """ ACL IPv4+MF routed -> bridged, L2 ACL permit+reflect"""
747         self.run_test_ip46_routed_to_bridged_and_back(True, False,
748                                                       self.WITH_EH)
749
750     def test_1302_ip6_irb_1(self):
751         """ ACL IPv4+MF bridged -> routed, L2 ACL permit+reflect"""
752         self.run_test_ip46_bridged_to_routed_and_back(True, False,
753                                                       self.WITH_EH)
754
755     def test_1311_ip6_irb_1(self):
756         """ ACL IPv4+MF routed -> bridged, L3 ACL permit+reflect"""
757         self.run_test_ip46_routed_to_bridged_and_back(False, False,
758                                                       self.WITH_EH)
759
760     def test_1312_ip6_irb_1(self):
761         """ ACL IPv4+MF bridged -> routed, L3 ACL permit+reflect"""
762         self.run_test_ip46_bridged_to_routed_and_back(False, False,
763                                                       self.WITH_EH)
764
765 if __name__ == '__main__':
766     unittest.main(testRunner=VppTestRunner)