blob: 52f139132dc59658afe0a7453b1845d5a83497c6 [file] [log] [blame]
Renato Botelho do Coutoead1e532019-10-31 13:31:07 -05001#!/usr/bin/env python3
Andrew Yourtchenko08118f02018-02-08 21:45:08 +01002""" Classifier-based L2 ACL Test Case HLD:
3"""
4
5import unittest
6import random
7import binascii
8import socket
9
10
11from scapy.packet import Raw
Jan Gelety059d1d02018-07-03 13:58:24 +020012from scapy.data import ETH_P_IP
Andrew Yourtchenko08118f02018-02-08 21:45:08 +010013from scapy.layers.l2 import Ether
14from scapy.layers.inet import IP, TCP, UDP, ICMP
15from scapy.layers.inet6 import IPv6, ICMPv6EchoRequest
16from scapy.layers.inet6 import IPv6ExtHdrFragment
17from framework import VppTestCase, VppTestRunner
18from util import Host, ppp
Jakub Grajciar692bfc82019-08-27 10:16:44 +020019from template_classifier import TestClassifier
Andrew Yourtchenko08118f02018-02-08 21:45:08 +010020
21
Jakub Grajciar692bfc82019-08-27 10:16:44 +020022class TestClassifyAcl(TestClassifier):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020023 """Classifier-based L2 input and output ACL Test Case"""
Andrew Yourtchenko08118f02018-02-08 21:45:08 +010024
25 # traffic types
26 IP = 0
27 ICMP = 1
28
29 # IP version
30 IPRANDOM = -1
31 IPV4 = 0
32 IPV6 = 1
33
34 # rule types
35 DENY = 0
36 PERMIT = 1
37
38 # supported protocols
39 proto = [[6, 17], [1, 58]]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020040 proto_map = {1: "ICMP", 58: "ICMPv6EchoRequest", 6: "TCP", 17: "UDP"}
Andrew Yourtchenko08118f02018-02-08 21:45:08 +010041 ICMPv4 = 0
42 ICMPv6 = 1
43 TCP = 0
44 UDP = 1
45 PROTO_ALL = 0
46
47 # port ranges
48 PORTS_ALL = -1
49 PORTS_RANGE = 0
50 PORTS_RANGE_2 = 1
51 udp_sport_from = 10
52 udp_sport_to = udp_sport_from + 5
53 udp_dport_from = 20000
54 udp_dport_to = udp_dport_from + 5000
55 tcp_sport_from = 30
56 tcp_sport_to = tcp_sport_from + 5
57 tcp_dport_from = 40000
58 tcp_dport_to = tcp_dport_from + 5000
59
60 udp_sport_from_2 = 90
61 udp_sport_to_2 = udp_sport_from_2 + 5
62 udp_dport_from_2 = 30000
63 udp_dport_to_2 = udp_dport_from_2 + 5000
64 tcp_sport_from_2 = 130
65 tcp_sport_to_2 = tcp_sport_from_2 + 5
66 tcp_dport_from_2 = 20000
67 tcp_dport_to_2 = tcp_dport_from_2 + 5000
68
69 icmp4_type = 8 # echo request
70 icmp4_code = 3
71 icmp6_type = 128 # echo request
72 icmp6_code = 3
73
74 icmp4_type_2 = 8
75 icmp4_code_from_2 = 5
76 icmp4_code_to_2 = 20
77 icmp6_type_2 = 128
78 icmp6_code_from_2 = 8
79 icmp6_code_to_2 = 42
80
81 # Test variables
82 bd_id = 1
83
84 @classmethod
85 def setUpClass(cls):
86 """
87 Perform standard class setup (defined by class method setUpClass in
88 class VppTestCase) before running the test case, set test case related
89 variables and configure VPP.
90 """
91 super(TestClassifyAcl, cls).setUpClass()
Jakub Grajciar692bfc82019-08-27 10:16:44 +020092 cls.af = None
Andrew Yourtchenko08118f02018-02-08 21:45:08 +010093
94 try:
95 # Create 2 pg interfaces
96 cls.create_pg_interfaces(range(2))
97
98 # Packet flows mapping pg0 -> pg1, pg2 etc.
99 cls.flows = dict()
100 cls.flows[cls.pg0] = [cls.pg1]
101
102 # Packet sizes
103 cls.pg_if_packet_sizes = [64, 512, 1518, 9018]
104
105 # Create BD with MAC learning and unknown unicast flooding disabled
106 # and put interfaces to this BD
Laszlo Kiraly0f8f4352022-09-16 13:20:07 +0200107 cls.vapi.bridge_domain_add_del_v2(
108 bd_id=cls.bd_id, uu_flood=1, learn=1, flood=1, forward=1, is_add=1
109 )
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100110 for pg_if in cls.pg_interfaces:
Ole Troana5b2eec2019-03-11 19:23:25 +0100111 cls.vapi.sw_interface_set_l2_bridge(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200112 rx_sw_if_index=pg_if.sw_if_index, bd_id=cls.bd_id
113 )
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100114
115 # Set up all interfaces
116 for i in cls.pg_interfaces:
117 i.admin_up()
118
119 # Mapping between packet-generator index and lists of test hosts
120 cls.hosts_by_pg_idx = dict()
121 for pg_if in cls.pg_interfaces:
122 cls.hosts_by_pg_idx[pg_if.sw_if_index] = []
123
124 # Create list of deleted hosts
125 cls.deleted_hosts_by_pg_idx = dict()
126 for pg_if in cls.pg_interfaces:
127 cls.deleted_hosts_by_pg_idx[pg_if.sw_if_index] = []
128
129 # warm-up the mac address tables
130 # self.warmup_test()
131
Jan Gelety059d1d02018-07-03 13:58:24 +0200132 # Holder of the active classify table key
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200133 cls.acl_active_table = ""
Jan Gelety059d1d02018-07-03 13:58:24 +0200134
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100135 except Exception:
136 super(TestClassifyAcl, cls).tearDownClass()
137 raise
138
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700139 @classmethod
140 def tearDownClass(cls):
141 super(TestClassifyAcl, cls).tearDownClass()
142
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100143 def setUp(self):
144 super(TestClassifyAcl, self).setUp()
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100145 self.acl_tbl_idx = {}
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100146
147 def tearDown(self):
148 """
149 Show various debug prints after each test.
150 """
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100151 if not self.vpp_dead:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200152 if self.acl_active_table == "mac_inout":
Jan Gelety059d1d02018-07-03 13:58:24 +0200153 self.output_acl_set_interface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200154 self.pg1, self.acl_tbl_idx.get(self.acl_active_table), 0
155 )
Jan Gelety059d1d02018-07-03 13:58:24 +0200156 self.input_acl_set_interface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200157 self.pg0, self.acl_tbl_idx.get(self.acl_active_table), 0
158 )
159 self.acl_active_table = ""
160 elif self.acl_active_table == "mac_out":
Jan Gelety059d1d02018-07-03 13:58:24 +0200161 self.output_acl_set_interface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200162 self.pg1, self.acl_tbl_idx.get(self.acl_active_table), 0
163 )
164 self.acl_active_table = ""
165 elif self.acl_active_table == "mac_in":
Jan Gelety059d1d02018-07-03 13:58:24 +0200166 self.input_acl_set_interface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200167 self.pg0, self.acl_tbl_idx.get(self.acl_active_table), 0
168 )
169 self.acl_active_table = ""
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100170
Jan Gelety059d1d02018-07-03 13:58:24 +0200171 super(TestClassifyAcl, self).tearDown()
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100172
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200173 def create_classify_session(
174 self, intf, table_index, match, hit_next_index=0xFFFFFFFF, is_add=1
175 ):
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100176 """Create Classify Session
177
178 :param VppInterface intf: Interface to apply classify session.
179 :param int table_index: table index to identify classify table.
180 :param str match: matched value for interested traffic.
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100181 :param int is_add: option to configure classify session.
182 - create(1) or delete(0)
183 """
Jakub Grajciar692bfc82019-08-27 10:16:44 +0200184 mask_match, mask_match_len = self._resolve_mask_match(match)
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100185 r = self.vapi.classify_add_del_session(
Jakub Grajciar692bfc82019-08-27 10:16:44 +0200186 is_add=is_add,
187 table_index=table_index,
188 match=mask_match,
189 match_len=mask_match_len,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200190 hit_next_index=hit_next_index,
191 )
192 self.assertIsNotNone(r, "No response msg for add_del_session")
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100193
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100194 def create_hosts(self, count, start=0):
195 """
196 Create required number of host MAC addresses and distribute them among
197 interfaces. Create host IPv4 address for every host MAC address.
198
199 :param int count: Number of hosts to create MAC/IPv4 addresses for.
200 :param int start: Number to start numbering from.
201 """
202 n_int = len(self.pg_interfaces)
Ole Troan203bf042019-10-21 20:39:45 +0200203 macs_per_if = count // n_int
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100204 i = -1
205 for pg_if in self.pg_interfaces:
206 i += 1
207 start_nr = macs_per_if * i + start
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200208 end_nr = (
209 count + start if i == (n_int - 1) else macs_per_if * (i + 1) + start
210 )
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100211 hosts = self.hosts_by_pg_idx[pg_if.sw_if_index]
212 for j in range(start_nr, end_nr):
213 host = Host(
214 "00:00:00:ff:%02x:%02x" % (pg_if.sw_if_index, j),
215 "172.17.1%02x.%u" % (pg_if.sw_if_index, j),
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200216 "2017:dead:%02x::%u" % (pg_if.sw_if_index, j),
217 )
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100218 hosts.append(host)
219
220 def create_upper_layer(self, packet_index, proto, ports=0):
221 p = self.proto_map[proto]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200222 if p == "UDP":
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100223 if ports == 0:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200224 return UDP(
225 sport=random.randint(self.udp_sport_from, self.udp_sport_to),
226 dport=random.randint(self.udp_dport_from, self.udp_dport_to),
227 )
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100228 else:
229 return UDP(sport=ports, dport=ports)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200230 elif p == "TCP":
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100231 if ports == 0:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200232 return TCP(
233 sport=random.randint(self.tcp_sport_from, self.tcp_sport_to),
234 dport=random.randint(self.tcp_dport_from, self.tcp_dport_to),
235 )
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100236 else:
237 return TCP(sport=ports, dport=ports)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200238 return ""
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100239
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200240 def create_stream(
241 self,
242 src_if,
243 packet_sizes,
244 traffic_type=0,
245 ipv6=0,
246 proto=-1,
247 ports=0,
248 fragments=False,
249 pkt_raw=True,
250 etype=-1,
251 ):
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100252 """
253 Create input packet stream for defined interface using hosts or
254 deleted_hosts list.
255
256 :param object src_if: Interface to create packet stream for.
257 :param list packet_sizes: List of required packet sizes.
258 :param traffic_type: 1: ICMP packet, 2: IPv6 with EH, 0: otherwise.
259 :return: Stream of packets.
260 """
261 pkts = []
262 if self.flows.__contains__(src_if):
263 src_hosts = self.hosts_by_pg_idx[src_if.sw_if_index]
264 for dst_if in self.flows[src_if]:
265 dst_hosts = self.hosts_by_pg_idx[dst_if.sw_if_index]
266 n_int = len(dst_hosts) * len(src_hosts)
267 for i in range(0, n_int):
Ole Troan203bf042019-10-21 20:39:45 +0200268 dst_host = dst_hosts[i // len(src_hosts)]
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100269 src_host = src_hosts[i % len(src_hosts)]
270 pkt_info = self.create_packet_info(src_if, dst_if)
271 if ipv6 == 1:
272 pkt_info.ip = 1
273 elif ipv6 == 0:
274 pkt_info.ip = 0
275 else:
276 pkt_info.ip = random.choice([0, 1])
277 if proto == -1:
278 pkt_info.proto = random.choice(self.proto[self.IP])
279 else:
280 pkt_info.proto = proto
281 payload = self.info_to_payload(pkt_info)
282 p = Ether(dst=dst_host.mac, src=src_host.mac)
283 if etype > 0:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200284 p = Ether(dst=dst_host.mac, src=src_host.mac, type=etype)
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100285 if pkt_info.ip:
286 p /= IPv6(dst=dst_host.ip6, src=src_host.ip6)
287 if fragments:
288 p /= IPv6ExtHdrFragment(offset=64, m=1)
289 else:
290 if fragments:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200291 p /= IP(
292 src=src_host.ip4, dst=dst_host.ip4, flags=1, frag=64
293 )
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100294 else:
295 p /= IP(src=src_host.ip4, dst=dst_host.ip4)
296 if traffic_type == self.ICMP:
297 if pkt_info.ip:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200298 p /= ICMPv6EchoRequest(
299 type=self.icmp6_type, code=self.icmp6_code
300 )
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100301 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200302 p /= ICMP(type=self.icmp4_type, code=self.icmp4_code)
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100303 else:
304 p /= self.create_upper_layer(i, pkt_info.proto, ports)
305 if pkt_raw:
306 p /= Raw(payload)
307 pkt_info.data = p.copy()
308 if pkt_raw:
309 size = random.choice(packet_sizes)
310 self.extend_packet(p, size)
311 pkts.append(p)
312 return pkts
313
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200314 def verify_capture(self, pg_if, capture, traffic_type=0, ip_type=0, etype=-1):
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100315 """
316 Verify captured input packet stream for defined interface.
317
318 :param object pg_if: Interface to verify captured packet stream for.
319 :param list capture: Captured packet stream.
320 :param traffic_type: 1: ICMP packet, 2: IPv6 with EH, 0: otherwise.
321 """
322 last_info = dict()
323 for i in self.pg_interfaces:
324 last_info[i.sw_if_index] = None
325 dst_sw_if_index = pg_if.sw_if_index
326 for packet in capture:
327 if etype > 0:
328 if packet[Ether].type != etype:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200329 self.logger.error(ppp("Unexpected ethertype in packet:", packet))
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100330 else:
331 continue
332 try:
333 # Raw data for ICMPv6 are stored in ICMPv6EchoRequest.data
334 if traffic_type == self.ICMP and ip_type == self.IPV6:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200335 payload_info = self.payload_to_info(packet[ICMPv6EchoRequest].data)
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100336 payload = packet[ICMPv6EchoRequest]
337 else:
Paul Vinciguerraeaea4212019-03-06 11:58:06 -0800338 payload_info = self.payload_to_info(packet[Raw])
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100339 payload = packet[self.proto_map[payload_info.proto]]
340 except:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200341 self.logger.error(
342 ppp("Unexpected or invalid packet (outside network):", packet)
343 )
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100344 raise
345
346 if ip_type != 0:
347 self.assertEqual(payload_info.ip, ip_type)
348 if traffic_type == self.ICMP:
349 try:
350 if payload_info.ip == 0:
351 self.assertEqual(payload.type, self.icmp4_type)
352 self.assertEqual(payload.code, self.icmp4_code)
353 else:
354 self.assertEqual(payload.type, self.icmp6_type)
355 self.assertEqual(payload.code, self.icmp6_code)
356 except:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200357 self.logger.error(
358 ppp("Unexpected or invalid packet (outside network):", packet)
359 )
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100360 raise
361 else:
362 try:
363 ip_version = IPv6 if payload_info.ip == 1 else IP
364
365 ip = packet[ip_version]
366 packet_index = payload_info.index
367
368 self.assertEqual(payload_info.dst, dst_sw_if_index)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200369 self.logger.debug(
370 "Got packet on port %s: src=%u (id=%u)"
371 % (pg_if.name, payload_info.src, packet_index)
372 )
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100373 next_info = self.get_next_packet_info_for_interface2(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200374 payload_info.src, dst_sw_if_index, last_info[payload_info.src]
375 )
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100376 last_info[payload_info.src] = next_info
377 self.assertTrue(next_info is not None)
378 self.assertEqual(packet_index, next_info.index)
379 saved_packet = next_info.data
380 # Check standard fields
381 self.assertEqual(ip.src, saved_packet[ip_version].src)
382 self.assertEqual(ip.dst, saved_packet[ip_version].dst)
383 p = self.proto_map[payload_info.proto]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200384 if p == "TCP":
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100385 tcp = packet[TCP]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200386 self.assertEqual(tcp.sport, saved_packet[TCP].sport)
387 self.assertEqual(tcp.dport, saved_packet[TCP].dport)
388 elif p == "UDP":
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100389 udp = packet[UDP]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200390 self.assertEqual(udp.sport, saved_packet[UDP].sport)
391 self.assertEqual(udp.dport, saved_packet[UDP].dport)
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100392 except:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200393 self.logger.error(ppp("Unexpected or invalid packet:", packet))
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100394 raise
395 for i in self.pg_interfaces:
396 remaining_packet = self.get_next_packet_info_for_interface2(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200397 i, dst_sw_if_index, last_info[i.sw_if_index]
398 )
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100399 self.assertTrue(
400 remaining_packet is None,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200401 "Port %u: Packet expected from source %u didn't arrive"
402 % (dst_sw_if_index, i.sw_if_index),
403 )
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100404
405 def run_traffic_no_check(self):
406 # Test
407 # Create incoming packet streams for packet-generator interfaces
408 for i in self.pg_interfaces:
409 if self.flows.__contains__(i):
410 pkts = self.create_stream(i, self.pg_if_packet_sizes)
411 if len(pkts) > 0:
412 i.add_stream(pkts)
413
414 # Enable packet capture and start packet sending
415 self.pg_enable_capture(self.pg_interfaces)
416 self.pg_start()
417
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200418 def run_verify_test(
419 self,
420 traffic_type=0,
421 ip_type=0,
422 proto=-1,
423 ports=0,
424 frags=False,
425 pkt_raw=True,
426 etype=-1,
427 ):
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100428 # Test
429 # Create incoming packet streams for packet-generator interfaces
430 pkts_cnt = 0
431 for i in self.pg_interfaces:
432 if self.flows.__contains__(i):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200433 pkts = self.create_stream(
434 i,
435 self.pg_if_packet_sizes,
436 traffic_type,
437 ip_type,
438 proto,
439 ports,
440 frags,
441 pkt_raw,
442 etype,
443 )
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100444 if len(pkts) > 0:
445 i.add_stream(pkts)
446 pkts_cnt += len(pkts)
447
448 # Enable packet capture and start packet sendingself.IPV
449 self.pg_enable_capture(self.pg_interfaces)
450 self.pg_start()
451
452 # Verify
453 # Verify outgoing packet streams per packet-generator interface
454 for src_if in self.pg_interfaces:
455 if self.flows.__contains__(src_if):
456 for dst_if in self.flows[src_if]:
457 capture = dst_if.get_capture(pkts_cnt)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200458 self.logger.info("Verifying capture on interface %s" % dst_if.name)
459 self.verify_capture(dst_if, capture, traffic_type, ip_type, etype)
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100460
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200461 def run_verify_negat_test(
462 self, traffic_type=0, ip_type=0, proto=-1, ports=0, frags=False, etype=-1
463 ):
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100464 # Test
465 self.reset_packet_infos()
466 for i in self.pg_interfaces:
467 if self.flows.__contains__(i):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200468 pkts = self.create_stream(
469 i,
470 self.pg_if_packet_sizes,
471 traffic_type,
472 ip_type,
473 proto,
474 ports,
475 frags,
476 True,
477 etype,
478 )
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100479 if len(pkts) > 0:
480 i.add_stream(pkts)
481
482 # Enable packet capture and start packet sending
483 self.pg_enable_capture(self.pg_interfaces)
484 self.pg_start()
485
486 # Verify
487 # Verify outgoing packet streams per packet-generator interface
488 for src_if in self.pg_interfaces:
489 if self.flows.__contains__(src_if):
490 for dst_if in self.flows[src_if]:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200491 self.logger.info("Verifying capture on interface %s" % dst_if.name)
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100492 capture = dst_if.get_capture(0)
493 self.assertEqual(len(capture), 0)
494
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200495 def build_classify_table(
496 self,
497 src_mac="",
498 dst_mac="",
499 ether_type="",
500 etype="",
501 key="mac",
502 hit_next_index=0xFFFFFFFF,
503 ):
Jan Gelety059d1d02018-07-03 13:58:24 +0200504 # Basic ACL testing
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200505 a_mask = self.build_mac_mask(
506 src_mac=src_mac, dst_mac=dst_mac, ether_type=ether_type
507 )
Jan Gelety059d1d02018-07-03 13:58:24 +0200508 self.create_classify_table(key, a_mask)
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100509 for host in self.hosts_by_pg_idx[self.pg0.sw_if_index]:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200510 s_mac = host.mac if src_mac else ""
Jan Gelety059d1d02018-07-03 13:58:24 +0200511 if dst_mac:
512 for dst_if in self.flows[self.pg0]:
513 for dst_host in self.hosts_by_pg_idx[dst_if.sw_if_index]:
514 self.create_classify_session(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200515 self.pg0,
516 self.acl_tbl_idx.get(key),
517 self.build_mac_match(
518 src_mac=s_mac, dst_mac=dst_host.mac, ether_type=etype
519 ),
520 hit_next_index=hit_next_index,
521 )
Jan Gelety059d1d02018-07-03 13:58:24 +0200522 else:
523 self.create_classify_session(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200524 self.pg0,
525 self.acl_tbl_idx.get(key),
526 self.build_mac_match(src_mac=s_mac, dst_mac="", ether_type=etype),
527 hit_next_index=hit_next_index,
528 )
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100529
530 def test_0000_warmup_test(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200531 """Learn the MAC addresses"""
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100532 self.create_hosts(2)
533 self.run_traffic_no_check()
534
Jan Gelety059d1d02018-07-03 13:58:24 +0200535 def test_0010_inacl_permit_src_mac(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200536 """Input L2 ACL test - permit source MAC
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100537
538 Test scenario for basic IP ACL with source IP
539 - Create IPv4 stream for pg0 -> pg1 interface.
540 - Create ACL with source MAC address.
541 - Send and verify received packets on pg1 interface.
542 """
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200543 key = "mac_in"
544 self.build_classify_table(src_mac="ffffffffffff", key=key)
Jan Gelety059d1d02018-07-03 13:58:24 +0200545 self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key))
546 self.acl_active_table = key
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100547 self.run_verify_test(self.IP, self.IPV4, -1)
Jan Gelety059d1d02018-07-03 13:58:24 +0200548
549 def test_0011_inacl_permit_dst_mac(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200550 """Input L2 ACL test - permit destination MAC
Jan Gelety059d1d02018-07-03 13:58:24 +0200551
552 Test scenario for basic IP ACL with source IP
553 - Create IPv4 stream for pg0 -> pg1 interface.
554 - Create ACL with destination MAC address.
555 - Send and verify received packets on pg1 interface.
556 """
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200557 key = "mac_in"
558 self.build_classify_table(dst_mac="ffffffffffff", key=key)
Jan Gelety059d1d02018-07-03 13:58:24 +0200559 self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key))
560 self.acl_active_table = key
561 self.run_verify_test(self.IP, self.IPV4, -1)
562
563 def test_0012_inacl_permit_src_dst_mac(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200564 """Input L2 ACL test - permit source and destination MAC
Jan Gelety059d1d02018-07-03 13:58:24 +0200565
566 Test scenario for basic IP ACL with source IP
567 - Create IPv4 stream for pg0 -> pg1 interface.
568 - Create ACL with source and destination MAC addresses.
569 - Send and verify received packets on pg1 interface.
570 """
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200571 key = "mac_in"
Jan Gelety059d1d02018-07-03 13:58:24 +0200572 self.build_classify_table(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200573 src_mac="ffffffffffff", dst_mac="ffffffffffff", key=key
574 )
Jan Gelety059d1d02018-07-03 13:58:24 +0200575 self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key))
576 self.acl_active_table = key
577 self.run_verify_test(self.IP, self.IPV4, -1)
578
579 def test_0013_inacl_permit_ether_type(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200580 """Input L2 ACL test - permit ether_type
Jan Gelety059d1d02018-07-03 13:58:24 +0200581
582 Test scenario for basic IP ACL with source IP
583 - Create IPv4 stream for pg0 -> pg1 interface.
584 - Create ACL with destination MAC address.
585 - Send and verify received packets on pg1 interface.
586 """
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200587 key = "mac_in"
588 self.build_classify_table(ether_type="ffff", etype=hex(ETH_P_IP)[2:], key=key)
Jan Gelety059d1d02018-07-03 13:58:24 +0200589 self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key))
590 self.acl_active_table = key
591 self.run_verify_test(self.IP, self.IPV4, -1)
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100592
593 def test_0015_inacl_deny(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200594 """Input L2 ACL test - deny
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100595
596 Test scenario for basic IP ACL with source IP
597 - Create IPv4 stream for pg0 -> pg1 interface.
Jan Gelety059d1d02018-07-03 13:58:24 +0200598
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100599 - Create ACL with source MAC address.
600 - Send and verify no received packets on pg1 interface.
601 """
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200602 key = "mac_in"
603 self.build_classify_table(src_mac="ffffffffffff", hit_next_index=0, key=key)
Jan Gelety059d1d02018-07-03 13:58:24 +0200604 self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key))
605 self.acl_active_table = key
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100606 self.run_verify_negat_test(self.IP, self.IPV4, -1)
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100607
608 def test_0020_outacl_permit(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200609 """Output L2 ACL test - permit
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100610
611 Test scenario for basic IP ACL with source IP
612 - Create IPv4 stream for pg0 -> pg1 interface.
613 - Create ACL with source MAC address.
614 - Send and verify received packets on pg1 interface.
615 """
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200616 key = "mac_out"
617 self.build_classify_table(src_mac="ffffffffffff", key=key)
Jan Gelety059d1d02018-07-03 13:58:24 +0200618 self.output_acl_set_interface(self.pg1, self.acl_tbl_idx.get(key))
619 self.acl_active_table = key
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100620 self.run_verify_test(self.IP, self.IPV4, -1)
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100621
622 def test_0025_outacl_deny(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200623 """Output L2 ACL test - deny
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100624
625 Test scenario for basic IP ACL with source IP
626 - Create IPv4 stream for pg0 -> pg1 interface.
627 - Create ACL with source MAC address.
628 - Send and verify no received packets on pg1 interface.
629 """
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200630 key = "mac_out"
631 self.build_classify_table(src_mac="ffffffffffff", hit_next_index=0, key=key)
Jan Gelety059d1d02018-07-03 13:58:24 +0200632 self.output_acl_set_interface(self.pg1, self.acl_tbl_idx.get(key))
633 self.acl_active_table = key
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100634 self.run_verify_negat_test(self.IP, self.IPV4, -1)
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100635
636 def test_0030_inoutacl_permit(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200637 """Input+Output L2 ACL test - permit
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100638
639 Test scenario for basic IP ACL with source IP
640 - Create IPv4 stream for pg0 -> pg1 interface.
641 - Create ACLs with source MAC address.
642 - Send and verify received packets on pg1 interface.
643 """
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200644 key = "mac_inout"
645 self.build_classify_table(src_mac="ffffffffffff", key=key)
Jan Gelety059d1d02018-07-03 13:58:24 +0200646 self.output_acl_set_interface(self.pg1, self.acl_tbl_idx.get(key))
647 self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key))
648 self.acl_active_table = key
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100649 self.run_verify_test(self.IP, self.IPV4, -1)
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100650
Jakub Grajciar2f8cd912020-03-27 06:55:06 +0100651
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200652if __name__ == "__main__":
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100653 unittest.main(testRunner=VppTestRunner)