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