blob: d94af3f718e492a2a6e3e4cd34a5e49330db7795 [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
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200107 cls.vapi.bridge_domain_add_del(bd_id=cls.bd_id, uu_flood=1, learn=1)
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100108 for pg_if in cls.pg_interfaces:
Ole Troana5b2eec2019-03-11 19:23:25 +0100109 cls.vapi.sw_interface_set_l2_bridge(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200110 rx_sw_if_index=pg_if.sw_if_index, bd_id=cls.bd_id
111 )
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100112
113 # Set up all interfaces
114 for i in cls.pg_interfaces:
115 i.admin_up()
116
117 # Mapping between packet-generator index and lists of test hosts
118 cls.hosts_by_pg_idx = dict()
119 for pg_if in cls.pg_interfaces:
120 cls.hosts_by_pg_idx[pg_if.sw_if_index] = []
121
122 # Create list of deleted hosts
123 cls.deleted_hosts_by_pg_idx = dict()
124 for pg_if in cls.pg_interfaces:
125 cls.deleted_hosts_by_pg_idx[pg_if.sw_if_index] = []
126
127 # warm-up the mac address tables
128 # self.warmup_test()
129
Jan Gelety059d1d02018-07-03 13:58:24 +0200130 # Holder of the active classify table key
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200131 cls.acl_active_table = ""
Jan Gelety059d1d02018-07-03 13:58:24 +0200132
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100133 except Exception:
134 super(TestClassifyAcl, cls).tearDownClass()
135 raise
136
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700137 @classmethod
138 def tearDownClass(cls):
139 super(TestClassifyAcl, cls).tearDownClass()
140
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100141 def setUp(self):
142 super(TestClassifyAcl, self).setUp()
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100143 self.acl_tbl_idx = {}
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100144
145 def tearDown(self):
146 """
147 Show various debug prints after each test.
148 """
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100149 if not self.vpp_dead:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200150 if self.acl_active_table == "mac_inout":
Jan Gelety059d1d02018-07-03 13:58:24 +0200151 self.output_acl_set_interface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200152 self.pg1, self.acl_tbl_idx.get(self.acl_active_table), 0
153 )
Jan Gelety059d1d02018-07-03 13:58:24 +0200154 self.input_acl_set_interface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200155 self.pg0, self.acl_tbl_idx.get(self.acl_active_table), 0
156 )
157 self.acl_active_table = ""
158 elif self.acl_active_table == "mac_out":
Jan Gelety059d1d02018-07-03 13:58:24 +0200159 self.output_acl_set_interface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200160 self.pg1, self.acl_tbl_idx.get(self.acl_active_table), 0
161 )
162 self.acl_active_table = ""
163 elif self.acl_active_table == "mac_in":
Jan Gelety059d1d02018-07-03 13:58:24 +0200164 self.input_acl_set_interface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200165 self.pg0, self.acl_tbl_idx.get(self.acl_active_table), 0
166 )
167 self.acl_active_table = ""
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100168
Jan Gelety059d1d02018-07-03 13:58:24 +0200169 super(TestClassifyAcl, self).tearDown()
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100170
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200171 def create_classify_session(
172 self, intf, table_index, match, hit_next_index=0xFFFFFFFF, is_add=1
173 ):
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100174 """Create Classify Session
175
176 :param VppInterface intf: Interface to apply classify session.
177 :param int table_index: table index to identify classify table.
178 :param str match: matched value for interested traffic.
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100179 :param int is_add: option to configure classify session.
180 - create(1) or delete(0)
181 """
Jakub Grajciar692bfc82019-08-27 10:16:44 +0200182 mask_match, mask_match_len = self._resolve_mask_match(match)
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100183 r = self.vapi.classify_add_del_session(
Jakub Grajciar692bfc82019-08-27 10:16:44 +0200184 is_add=is_add,
185 table_index=table_index,
186 match=mask_match,
187 match_len=mask_match_len,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200188 hit_next_index=hit_next_index,
189 )
190 self.assertIsNotNone(r, "No response msg for add_del_session")
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100191
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100192 def create_hosts(self, count, start=0):
193 """
194 Create required number of host MAC addresses and distribute them among
195 interfaces. Create host IPv4 address for every host MAC address.
196
197 :param int count: Number of hosts to create MAC/IPv4 addresses for.
198 :param int start: Number to start numbering from.
199 """
200 n_int = len(self.pg_interfaces)
Ole Troan203bf042019-10-21 20:39:45 +0200201 macs_per_if = count // n_int
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100202 i = -1
203 for pg_if in self.pg_interfaces:
204 i += 1
205 start_nr = macs_per_if * i + start
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200206 end_nr = (
207 count + start if i == (n_int - 1) else macs_per_if * (i + 1) + start
208 )
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100209 hosts = self.hosts_by_pg_idx[pg_if.sw_if_index]
210 for j in range(start_nr, end_nr):
211 host = Host(
212 "00:00:00:ff:%02x:%02x" % (pg_if.sw_if_index, j),
213 "172.17.1%02x.%u" % (pg_if.sw_if_index, j),
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200214 "2017:dead:%02x::%u" % (pg_if.sw_if_index, j),
215 )
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100216 hosts.append(host)
217
218 def create_upper_layer(self, packet_index, proto, ports=0):
219 p = self.proto_map[proto]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200220 if p == "UDP":
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100221 if ports == 0:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200222 return UDP(
223 sport=random.randint(self.udp_sport_from, self.udp_sport_to),
224 dport=random.randint(self.udp_dport_from, self.udp_dport_to),
225 )
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100226 else:
227 return UDP(sport=ports, dport=ports)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200228 elif p == "TCP":
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100229 if ports == 0:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200230 return TCP(
231 sport=random.randint(self.tcp_sport_from, self.tcp_sport_to),
232 dport=random.randint(self.tcp_dport_from, self.tcp_dport_to),
233 )
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100234 else:
235 return TCP(sport=ports, dport=ports)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200236 return ""
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100237
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200238 def create_stream(
239 self,
240 src_if,
241 packet_sizes,
242 traffic_type=0,
243 ipv6=0,
244 proto=-1,
245 ports=0,
246 fragments=False,
247 pkt_raw=True,
248 etype=-1,
249 ):
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100250 """
251 Create input packet stream for defined interface using hosts or
252 deleted_hosts list.
253
254 :param object src_if: Interface to create packet stream for.
255 :param list packet_sizes: List of required packet sizes.
256 :param traffic_type: 1: ICMP packet, 2: IPv6 with EH, 0: otherwise.
257 :return: Stream of packets.
258 """
259 pkts = []
260 if self.flows.__contains__(src_if):
261 src_hosts = self.hosts_by_pg_idx[src_if.sw_if_index]
262 for dst_if in self.flows[src_if]:
263 dst_hosts = self.hosts_by_pg_idx[dst_if.sw_if_index]
264 n_int = len(dst_hosts) * len(src_hosts)
265 for i in range(0, n_int):
Ole Troan203bf042019-10-21 20:39:45 +0200266 dst_host = dst_hosts[i // len(src_hosts)]
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100267 src_host = src_hosts[i % len(src_hosts)]
268 pkt_info = self.create_packet_info(src_if, dst_if)
269 if ipv6 == 1:
270 pkt_info.ip = 1
271 elif ipv6 == 0:
272 pkt_info.ip = 0
273 else:
274 pkt_info.ip = random.choice([0, 1])
275 if proto == -1:
276 pkt_info.proto = random.choice(self.proto[self.IP])
277 else:
278 pkt_info.proto = proto
279 payload = self.info_to_payload(pkt_info)
280 p = Ether(dst=dst_host.mac, src=src_host.mac)
281 if etype > 0:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200282 p = Ether(dst=dst_host.mac, src=src_host.mac, type=etype)
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100283 if pkt_info.ip:
284 p /= IPv6(dst=dst_host.ip6, src=src_host.ip6)
285 if fragments:
286 p /= IPv6ExtHdrFragment(offset=64, m=1)
287 else:
288 if fragments:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200289 p /= IP(
290 src=src_host.ip4, dst=dst_host.ip4, flags=1, frag=64
291 )
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100292 else:
293 p /= IP(src=src_host.ip4, dst=dst_host.ip4)
294 if traffic_type == self.ICMP:
295 if pkt_info.ip:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200296 p /= ICMPv6EchoRequest(
297 type=self.icmp6_type, code=self.icmp6_code
298 )
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100299 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200300 p /= ICMP(type=self.icmp4_type, code=self.icmp4_code)
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100301 else:
302 p /= self.create_upper_layer(i, pkt_info.proto, ports)
303 if pkt_raw:
304 p /= Raw(payload)
305 pkt_info.data = p.copy()
306 if pkt_raw:
307 size = random.choice(packet_sizes)
308 self.extend_packet(p, size)
309 pkts.append(p)
310 return pkts
311
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200312 def verify_capture(self, pg_if, capture, traffic_type=0, ip_type=0, etype=-1):
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100313 """
314 Verify captured input packet stream for defined interface.
315
316 :param object pg_if: Interface to verify captured packet stream for.
317 :param list capture: Captured packet stream.
318 :param traffic_type: 1: ICMP packet, 2: IPv6 with EH, 0: otherwise.
319 """
320 last_info = dict()
321 for i in self.pg_interfaces:
322 last_info[i.sw_if_index] = None
323 dst_sw_if_index = pg_if.sw_if_index
324 for packet in capture:
325 if etype > 0:
326 if packet[Ether].type != etype:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200327 self.logger.error(ppp("Unexpected ethertype in packet:", packet))
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100328 else:
329 continue
330 try:
331 # Raw data for ICMPv6 are stored in ICMPv6EchoRequest.data
332 if traffic_type == self.ICMP and ip_type == self.IPV6:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200333 payload_info = self.payload_to_info(packet[ICMPv6EchoRequest].data)
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100334 payload = packet[ICMPv6EchoRequest]
335 else:
Paul Vinciguerraeaea4212019-03-06 11:58:06 -0800336 payload_info = self.payload_to_info(packet[Raw])
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100337 payload = packet[self.proto_map[payload_info.proto]]
338 except:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200339 self.logger.error(
340 ppp("Unexpected or invalid packet (outside network):", packet)
341 )
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100342 raise
343
344 if ip_type != 0:
345 self.assertEqual(payload_info.ip, ip_type)
346 if traffic_type == self.ICMP:
347 try:
348 if payload_info.ip == 0:
349 self.assertEqual(payload.type, self.icmp4_type)
350 self.assertEqual(payload.code, self.icmp4_code)
351 else:
352 self.assertEqual(payload.type, self.icmp6_type)
353 self.assertEqual(payload.code, self.icmp6_code)
354 except:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200355 self.logger.error(
356 ppp("Unexpected or invalid packet (outside network):", packet)
357 )
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100358 raise
359 else:
360 try:
361 ip_version = IPv6 if payload_info.ip == 1 else IP
362
363 ip = packet[ip_version]
364 packet_index = payload_info.index
365
366 self.assertEqual(payload_info.dst, dst_sw_if_index)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200367 self.logger.debug(
368 "Got packet on port %s: src=%u (id=%u)"
369 % (pg_if.name, payload_info.src, packet_index)
370 )
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100371 next_info = self.get_next_packet_info_for_interface2(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200372 payload_info.src, dst_sw_if_index, last_info[payload_info.src]
373 )
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100374 last_info[payload_info.src] = next_info
375 self.assertTrue(next_info is not None)
376 self.assertEqual(packet_index, next_info.index)
377 saved_packet = next_info.data
378 # Check standard fields
379 self.assertEqual(ip.src, saved_packet[ip_version].src)
380 self.assertEqual(ip.dst, saved_packet[ip_version].dst)
381 p = self.proto_map[payload_info.proto]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200382 if p == "TCP":
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100383 tcp = packet[TCP]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200384 self.assertEqual(tcp.sport, saved_packet[TCP].sport)
385 self.assertEqual(tcp.dport, saved_packet[TCP].dport)
386 elif p == "UDP":
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100387 udp = packet[UDP]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200388 self.assertEqual(udp.sport, saved_packet[UDP].sport)
389 self.assertEqual(udp.dport, saved_packet[UDP].dport)
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100390 except:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200391 self.logger.error(ppp("Unexpected or invalid packet:", packet))
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100392 raise
393 for i in self.pg_interfaces:
394 remaining_packet = self.get_next_packet_info_for_interface2(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200395 i, dst_sw_if_index, last_info[i.sw_if_index]
396 )
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100397 self.assertTrue(
398 remaining_packet is None,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200399 "Port %u: Packet expected from source %u didn't arrive"
400 % (dst_sw_if_index, i.sw_if_index),
401 )
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100402
403 def run_traffic_no_check(self):
404 # Test
405 # Create incoming packet streams for packet-generator interfaces
406 for i in self.pg_interfaces:
407 if self.flows.__contains__(i):
408 pkts = self.create_stream(i, self.pg_if_packet_sizes)
409 if len(pkts) > 0:
410 i.add_stream(pkts)
411
412 # Enable packet capture and start packet sending
413 self.pg_enable_capture(self.pg_interfaces)
414 self.pg_start()
415
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200416 def run_verify_test(
417 self,
418 traffic_type=0,
419 ip_type=0,
420 proto=-1,
421 ports=0,
422 frags=False,
423 pkt_raw=True,
424 etype=-1,
425 ):
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100426 # Test
427 # Create incoming packet streams for packet-generator interfaces
428 pkts_cnt = 0
429 for i in self.pg_interfaces:
430 if self.flows.__contains__(i):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200431 pkts = self.create_stream(
432 i,
433 self.pg_if_packet_sizes,
434 traffic_type,
435 ip_type,
436 proto,
437 ports,
438 frags,
439 pkt_raw,
440 etype,
441 )
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100442 if len(pkts) > 0:
443 i.add_stream(pkts)
444 pkts_cnt += len(pkts)
445
446 # Enable packet capture and start packet sendingself.IPV
447 self.pg_enable_capture(self.pg_interfaces)
448 self.pg_start()
449
450 # Verify
451 # Verify outgoing packet streams per packet-generator interface
452 for src_if in self.pg_interfaces:
453 if self.flows.__contains__(src_if):
454 for dst_if in self.flows[src_if]:
455 capture = dst_if.get_capture(pkts_cnt)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200456 self.logger.info("Verifying capture on interface %s" % dst_if.name)
457 self.verify_capture(dst_if, capture, traffic_type, ip_type, etype)
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100458
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200459 def run_verify_negat_test(
460 self, traffic_type=0, ip_type=0, proto=-1, ports=0, frags=False, etype=-1
461 ):
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100462 # Test
463 self.reset_packet_infos()
464 for i in self.pg_interfaces:
465 if self.flows.__contains__(i):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200466 pkts = self.create_stream(
467 i,
468 self.pg_if_packet_sizes,
469 traffic_type,
470 ip_type,
471 proto,
472 ports,
473 frags,
474 True,
475 etype,
476 )
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100477 if len(pkts) > 0:
478 i.add_stream(pkts)
479
480 # Enable packet capture and start packet sending
481 self.pg_enable_capture(self.pg_interfaces)
482 self.pg_start()
483
484 # Verify
485 # Verify outgoing packet streams per packet-generator interface
486 for src_if in self.pg_interfaces:
487 if self.flows.__contains__(src_if):
488 for dst_if in self.flows[src_if]:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200489 self.logger.info("Verifying capture on interface %s" % dst_if.name)
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100490 capture = dst_if.get_capture(0)
491 self.assertEqual(len(capture), 0)
492
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200493 def build_classify_table(
494 self,
495 src_mac="",
496 dst_mac="",
497 ether_type="",
498 etype="",
499 key="mac",
500 hit_next_index=0xFFFFFFFF,
501 ):
Jan Gelety059d1d02018-07-03 13:58:24 +0200502 # Basic ACL testing
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200503 a_mask = self.build_mac_mask(
504 src_mac=src_mac, dst_mac=dst_mac, ether_type=ether_type
505 )
Jan Gelety059d1d02018-07-03 13:58:24 +0200506 self.create_classify_table(key, a_mask)
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100507 for host in self.hosts_by_pg_idx[self.pg0.sw_if_index]:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200508 s_mac = host.mac if src_mac else ""
Jan Gelety059d1d02018-07-03 13:58:24 +0200509 if dst_mac:
510 for dst_if in self.flows[self.pg0]:
511 for dst_host in self.hosts_by_pg_idx[dst_if.sw_if_index]:
512 self.create_classify_session(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200513 self.pg0,
514 self.acl_tbl_idx.get(key),
515 self.build_mac_match(
516 src_mac=s_mac, dst_mac=dst_host.mac, ether_type=etype
517 ),
518 hit_next_index=hit_next_index,
519 )
Jan Gelety059d1d02018-07-03 13:58:24 +0200520 else:
521 self.create_classify_session(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200522 self.pg0,
523 self.acl_tbl_idx.get(key),
524 self.build_mac_match(src_mac=s_mac, dst_mac="", ether_type=etype),
525 hit_next_index=hit_next_index,
526 )
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100527
528 def test_0000_warmup_test(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200529 """Learn the MAC addresses"""
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100530 self.create_hosts(2)
531 self.run_traffic_no_check()
532
Jan Gelety059d1d02018-07-03 13:58:24 +0200533 def test_0010_inacl_permit_src_mac(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200534 """Input L2 ACL test - permit source MAC
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100535
536 Test scenario for basic IP ACL with source IP
537 - Create IPv4 stream for pg0 -> pg1 interface.
538 - Create ACL with source MAC address.
539 - Send and verify received packets on pg1 interface.
540 """
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200541 key = "mac_in"
542 self.build_classify_table(src_mac="ffffffffffff", key=key)
Jan Gelety059d1d02018-07-03 13:58:24 +0200543 self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key))
544 self.acl_active_table = key
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100545 self.run_verify_test(self.IP, self.IPV4, -1)
Jan Gelety059d1d02018-07-03 13:58:24 +0200546
547 def test_0011_inacl_permit_dst_mac(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200548 """Input L2 ACL test - permit destination MAC
Jan Gelety059d1d02018-07-03 13:58:24 +0200549
550 Test scenario for basic IP ACL with source IP
551 - Create IPv4 stream for pg0 -> pg1 interface.
552 - Create ACL with destination MAC address.
553 - Send and verify received packets on pg1 interface.
554 """
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200555 key = "mac_in"
556 self.build_classify_table(dst_mac="ffffffffffff", key=key)
Jan Gelety059d1d02018-07-03 13:58:24 +0200557 self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key))
558 self.acl_active_table = key
559 self.run_verify_test(self.IP, self.IPV4, -1)
560
561 def test_0012_inacl_permit_src_dst_mac(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200562 """Input L2 ACL test - permit source and destination MAC
Jan Gelety059d1d02018-07-03 13:58:24 +0200563
564 Test scenario for basic IP ACL with source IP
565 - Create IPv4 stream for pg0 -> pg1 interface.
566 - Create ACL with source and destination MAC addresses.
567 - Send and verify received packets on pg1 interface.
568 """
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200569 key = "mac_in"
Jan Gelety059d1d02018-07-03 13:58:24 +0200570 self.build_classify_table(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200571 src_mac="ffffffffffff", dst_mac="ffffffffffff", key=key
572 )
Jan Gelety059d1d02018-07-03 13:58:24 +0200573 self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key))
574 self.acl_active_table = key
575 self.run_verify_test(self.IP, self.IPV4, -1)
576
577 def test_0013_inacl_permit_ether_type(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200578 """Input L2 ACL test - permit ether_type
Jan Gelety059d1d02018-07-03 13:58:24 +0200579
580 Test scenario for basic IP ACL with source IP
581 - Create IPv4 stream for pg0 -> pg1 interface.
582 - Create ACL with destination MAC address.
583 - Send and verify received packets on pg1 interface.
584 """
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200585 key = "mac_in"
586 self.build_classify_table(ether_type="ffff", etype=hex(ETH_P_IP)[2:], key=key)
Jan Gelety059d1d02018-07-03 13:58:24 +0200587 self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key))
588 self.acl_active_table = key
589 self.run_verify_test(self.IP, self.IPV4, -1)
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100590
591 def test_0015_inacl_deny(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200592 """Input L2 ACL test - deny
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100593
594 Test scenario for basic IP ACL with source IP
595 - Create IPv4 stream for pg0 -> pg1 interface.
Jan Gelety059d1d02018-07-03 13:58:24 +0200596
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100597 - Create ACL with source MAC address.
598 - Send and verify no received packets on pg1 interface.
599 """
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200600 key = "mac_in"
601 self.build_classify_table(src_mac="ffffffffffff", hit_next_index=0, key=key)
Jan Gelety059d1d02018-07-03 13:58:24 +0200602 self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key))
603 self.acl_active_table = key
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100604 self.run_verify_negat_test(self.IP, self.IPV4, -1)
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100605
606 def test_0020_outacl_permit(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200607 """Output L2 ACL test - permit
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100608
609 Test scenario for basic IP ACL with source IP
610 - Create IPv4 stream for pg0 -> pg1 interface.
611 - Create ACL with source MAC address.
612 - Send and verify received packets on pg1 interface.
613 """
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200614 key = "mac_out"
615 self.build_classify_table(src_mac="ffffffffffff", key=key)
Jan Gelety059d1d02018-07-03 13:58:24 +0200616 self.output_acl_set_interface(self.pg1, self.acl_tbl_idx.get(key))
617 self.acl_active_table = key
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100618 self.run_verify_test(self.IP, self.IPV4, -1)
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100619
620 def test_0025_outacl_deny(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200621 """Output L2 ACL test - deny
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100622
623 Test scenario for basic IP ACL with source IP
624 - Create IPv4 stream for pg0 -> pg1 interface.
625 - Create ACL with source MAC address.
626 - Send and verify no received packets on pg1 interface.
627 """
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200628 key = "mac_out"
629 self.build_classify_table(src_mac="ffffffffffff", hit_next_index=0, key=key)
Jan Gelety059d1d02018-07-03 13:58:24 +0200630 self.output_acl_set_interface(self.pg1, self.acl_tbl_idx.get(key))
631 self.acl_active_table = key
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100632 self.run_verify_negat_test(self.IP, self.IPV4, -1)
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100633
634 def test_0030_inoutacl_permit(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200635 """Input+Output L2 ACL test - permit
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100636
637 Test scenario for basic IP ACL with source IP
638 - Create IPv4 stream for pg0 -> pg1 interface.
639 - Create ACLs with source MAC address.
640 - Send and verify received packets on pg1 interface.
641 """
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200642 key = "mac_inout"
643 self.build_classify_table(src_mac="ffffffffffff", key=key)
Jan Gelety059d1d02018-07-03 13:58:24 +0200644 self.output_acl_set_interface(self.pg1, self.acl_tbl_idx.get(key))
645 self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key))
646 self.acl_active_table = key
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100647 self.run_verify_test(self.IP, self.IPV4, -1)
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100648
Jakub Grajciar2f8cd912020-03-27 06:55:06 +0100649
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200650if __name__ == "__main__":
Andrew Yourtchenko08118f02018-02-08 21:45:08 +0100651 unittest.main(testRunner=VppTestRunner)