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