blob: d99f66c991d0d7c4b493f42f230c0e9ef45481da [file] [log] [blame]
Renato Botelho do Coutoead1e532019-10-31 13:31:07 -05001#!/usr/bin/env python3
Steve Shin7957d6e2016-12-19 09:24:50 -08002
Steve Shin7957d6e2016-12-19 09:24:50 -08003import binascii
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -08004import socket
5import unittest
Steve Shin7957d6e2016-12-19 09:24:50 -08006
7from framework import VppTestCase, VppTestRunner
8
9from scapy.packet import Raw
10from scapy.layers.l2 import Ether
Jan Gelety059d1d02018-07-03 13:58:24 +020011from scapy.layers.inet import IP, UDP, TCP
Steve Shin7957d6e2016-12-19 09:24:50 -080012from util import ppp
Neale Ranns097fa662018-05-01 05:17:55 -070013from vpp_ip_route import VppIpRoute, VppRoutePath
14from vpp_ip import INVALID_INDEX
Steve Shin7957d6e2016-12-19 09:24:50 -080015
Klement Sekeradab231a2016-12-21 08:50:14 +010016
Steve Shin7957d6e2016-12-19 09:24:50 -080017class TestClassifier(VppTestCase):
18 """ Classifier Test Case """
19
Jan Gelety059d1d02018-07-03 13:58:24 +020020 @classmethod
21 def setUpClass(cls):
22 """
23 Perform standard class setup (defined by class method setUpClass in
24 class VppTestCase) before running the test case, set test case related
25 variables and configure VPP.
26 """
27 super(TestClassifier, cls).setUpClass()
28 cls.acl_active_table = ''
29
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070030 @classmethod
31 def tearDownClass(cls):
32 super(TestClassifier, cls).tearDownClass()
33
Steve Shin7957d6e2016-12-19 09:24:50 -080034 def setUp(self):
35 """
36 Perform test setup before test case.
37
38 **Config:**
39 - create 4 pg interfaces
40 - untagged pg0/pg1/pg2 interface
41 pg0 -------> pg1 (IP ACL)
42 \
43 ---> pg2 (MAC ACL))
44 \
45 -> pg3 (PBR)
46 - setup interfaces:
47 - put it into UP state
48 - set IPv4 addresses
49 - resolve neighbor address using ARP
50
51 :ivar list interfaces: pg interfaces.
52 :ivar list pg_if_packet_sizes: packet sizes in test.
53 :ivar dict acl_tbl_idx: ACL table index.
54 :ivar int pbr_vrfid: VRF id for PBR test.
55 """
Jan Gelety059d1d02018-07-03 13:58:24 +020056 self.reset_packet_infos()
Steve Shin7957d6e2016-12-19 09:24:50 -080057 super(TestClassifier, self).setUp()
58
59 # create 4 pg interfaces
60 self.create_pg_interfaces(range(4))
61
62 # packet sizes to test
63 self.pg_if_packet_sizes = [64, 9018]
64
65 self.interfaces = list(self.pg_interfaces)
66
67 # ACL & PBR vars
68 self.acl_tbl_idx = {}
69 self.pbr_vrfid = 200
70
71 # setup all interfaces
72 for intf in self.interfaces:
73 intf.admin_up()
74 intf.config_ip4()
75 intf.resolve_arp()
76
77 def tearDown(self):
78 """Run standard test teardown and acl related log."""
Steve Shin7957d6e2016-12-19 09:24:50 -080079 if not self.vpp_dead:
Jan Gelety059d1d02018-07-03 13:58:24 +020080 if self.acl_active_table == 'ip_out':
81 self.output_acl_set_interface(
82 self.pg0, self.acl_tbl_idx.get(self.acl_active_table), 0)
83 self.acl_active_table = ''
84 elif self.acl_active_table != '':
85 self.input_acl_set_interface(
86 self.pg0, self.acl_tbl_idx.get(self.acl_active_table), 0)
87 self.acl_active_table = ''
88 for intf in self.interfaces:
89 intf.unconfig_ip4()
90 intf.admin_down()
91
92 super(TestClassifier, self).tearDown()
Steve Shin7957d6e2016-12-19 09:24:50 -080093
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -070094 def show_commands_at_teardown(self):
95 self.logger.info(self.vapi.ppcli("show inacl type ip4"))
96 self.logger.info(self.vapi.ppcli("show outacl type ip4"))
97 self.logger.info(self.vapi.cli("show classify table verbose"))
98 self.logger.info(self.vapi.cli("show ip fib"))
99
Jan Gelety059d1d02018-07-03 13:58:24 +0200100 def create_stream(self, src_if, dst_if, packet_sizes,
101 proto_l=UDP(sport=1234, dport=5678)):
Steve Shin7957d6e2016-12-19 09:24:50 -0800102 """Create input packet stream for defined interfaces.
103
104 :param VppInterface src_if: Source Interface for packet stream.
105 :param VppInterface dst_if: Destination Interface for packet stream.
106 :param list packet_sizes: packet size to test.
Jan Gelety059d1d02018-07-03 13:58:24 +0200107 :param Scapy proto_l: Required IP protocol. Default protocol is UDP.
Steve Shin7957d6e2016-12-19 09:24:50 -0800108 """
109 pkts = []
Jan Gelety059d1d02018-07-03 13:58:24 +0200110
Steve Shin7957d6e2016-12-19 09:24:50 -0800111 for size in packet_sizes:
Klement Sekeradab231a2016-12-21 08:50:14 +0100112 info = self.create_packet_info(src_if, dst_if)
Steve Shin7957d6e2016-12-19 09:24:50 -0800113 payload = self.info_to_payload(info)
114 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
115 IP(src=src_if.remote_ip4, dst=dst_if.remote_ip4) /
Jan Gelety059d1d02018-07-03 13:58:24 +0200116 proto_l /
Steve Shin7957d6e2016-12-19 09:24:50 -0800117 Raw(payload))
118 info.data = p.copy()
119 self.extend_packet(p, size)
120 pkts.append(p)
121 return pkts
122
Jan Gelety059d1d02018-07-03 13:58:24 +0200123 def verify_capture(self, dst_if, capture, proto_l=UDP):
Steve Shin7957d6e2016-12-19 09:24:50 -0800124 """Verify captured input packet stream for defined interface.
125
126 :param VppInterface dst_if: Interface to verify captured packet stream.
127 :param list capture: Captured packet stream.
Jan Gelety059d1d02018-07-03 13:58:24 +0200128 :param Scapy proto_l: Required IP protocol. Default protocol is UDP.
Steve Shin7957d6e2016-12-19 09:24:50 -0800129 """
130 self.logger.info("Verifying capture on interface %s" % dst_if.name)
131 last_info = dict()
132 for i in self.interfaces:
133 last_info[i.sw_if_index] = None
134 dst_sw_if_index = dst_if.sw_if_index
135 for packet in capture:
136 try:
Jan Gelety059d1d02018-07-03 13:58:24 +0200137 ip_received = packet[IP]
138 proto_received = packet[proto_l]
Paul Vinciguerraeaea4212019-03-06 11:58:06 -0800139 payload_info = self.payload_to_info(packet[Raw])
Steve Shin7957d6e2016-12-19 09:24:50 -0800140 packet_index = payload_info.index
141 self.assertEqual(payload_info.dst, dst_sw_if_index)
Klement Sekerada505f62017-01-04 12:58:53 +0100142 self.logger.debug(
143 "Got packet on port %s: src=%u (id=%u)" %
144 (dst_if.name, payload_info.src, packet_index))
Steve Shin7957d6e2016-12-19 09:24:50 -0800145 next_info = self.get_next_packet_info_for_interface2(
146 payload_info.src, dst_sw_if_index,
147 last_info[payload_info.src])
148 last_info[payload_info.src] = next_info
149 self.assertTrue(next_info is not None)
150 self.assertEqual(packet_index, next_info.index)
151 saved_packet = next_info.data
Jan Gelety059d1d02018-07-03 13:58:24 +0200152 ip_saved = saved_packet[IP]
153 proto_saved = saved_packet[proto_l]
Steve Shin7957d6e2016-12-19 09:24:50 -0800154 # Check standard fields
Jan Gelety059d1d02018-07-03 13:58:24 +0200155 self.assertEqual(ip_received.src, ip_saved.src)
156 self.assertEqual(ip_received.dst, ip_saved.dst)
157 self.assertEqual(proto_received.sport, proto_saved.sport)
158 self.assertEqual(proto_received.dport, proto_saved.dport)
Steve Shin7957d6e2016-12-19 09:24:50 -0800159 except:
160 self.logger.error(ppp("Unexpected or invalid packet:", packet))
161 raise
162 for i in self.interfaces:
163 remaining_packet = self.get_next_packet_info_for_interface2(
164 i.sw_if_index, dst_sw_if_index, last_info[i.sw_if_index])
165 self.assertTrue(remaining_packet is None,
166 "Interface %s: Packet expected from interface %s "
167 "didn't arrive" % (dst_if.name, i.name))
168
Neale Ranns13eaf3e2017-05-23 06:10:33 -0700169 def verify_vrf(self, vrf_id):
170 """
171 Check if the FIB table / VRF ID is configured.
172
173 :param int vrf_id: The FIB table / VRF ID to be verified.
174 :return: 1 if the FIB table / VRF ID is configured, otherwise return 0.
175 """
Neale Ranns097fa662018-05-01 05:17:55 -0700176 ip_fib_dump = self.vapi.ip_route_dump(vrf_id, False)
177 vrf_count = len(ip_fib_dump)
178
Neale Ranns13eaf3e2017-05-23 06:10:33 -0700179 if vrf_count == 0:
180 self.logger.info("IPv4 VRF ID %d is not configured" % vrf_id)
181 return 0
182 else:
183 self.logger.info("IPv4 VRF ID %d is configured" % vrf_id)
184 return 1
185
Steve Shin7957d6e2016-12-19 09:24:50 -0800186 @staticmethod
187 def build_ip_mask(proto='', src_ip='', dst_ip='',
188 src_port='', dst_port=''):
Jan Gelety059d1d02018-07-03 13:58:24 +0200189 """Build IP ACL mask data with hexstring format.
Steve Shin7957d6e2016-12-19 09:24:50 -0800190
191 :param str proto: protocol number <0-ff>
192 :param str src_ip: source ip address <0-ffffffff>
193 :param str dst_ip: destination ip address <0-ffffffff>
194 :param str src_port: source port number <0-ffff>
195 :param str dst_port: destination port number <0-ffff>
196 """
197
Paul Vinciguerraea2450f2019-03-06 08:23:58 -0800198 return ('{!s:0>20}{!s:0>12}{!s:0>8}{!s:0>4}{!s:0>4}'.format(
Klement Sekeradab231a2016-12-21 08:50:14 +0100199 proto, src_ip, dst_ip, src_port, dst_port)).rstrip('0')
Steve Shin7957d6e2016-12-19 09:24:50 -0800200
201 @staticmethod
Jan Gelety059d1d02018-07-03 13:58:24 +0200202 def build_ip_match(proto=0, src_ip='', dst_ip='',
203 src_port=0, dst_port=0):
204 """Build IP ACL match data with hexstring format.
Steve Shin7957d6e2016-12-19 09:24:50 -0800205
Jan Gelety059d1d02018-07-03 13:58:24 +0200206 :param int proto: protocol number with valid option "x"
Steve Shin7957d6e2016-12-19 09:24:50 -0800207 :param str src_ip: source ip address with format of "x.x.x.x"
208 :param str dst_ip: destination ip address with format of "x.x.x.x"
Jan Gelety059d1d02018-07-03 13:58:24 +0200209 :param int src_port: source port number "x"
210 :param int dst_port: destination port number "x"
Steve Shin7957d6e2016-12-19 09:24:50 -0800211 """
Klement Sekeradab231a2016-12-21 08:50:14 +0100212 if src_ip:
Ole Troan19cb04d2019-10-17 20:44:25 +0200213 src_ip = binascii.hexlify(socket.inet_aton(src_ip)).decode('ascii')
Klement Sekeradab231a2016-12-21 08:50:14 +0100214 if dst_ip:
Ole Troan19cb04d2019-10-17 20:44:25 +0200215 dst_ip = binascii.hexlify(socket.inet_aton(dst_ip)).decode('ascii')
Steve Shin7957d6e2016-12-19 09:24:50 -0800216
Paul Vinciguerraea2450f2019-03-06 08:23:58 -0800217 return ('{!s:0>20}{!s:0>12}{!s:0>8}{!s:0>4}{!s:0>4}'.format(
Jan Gelety059d1d02018-07-03 13:58:24 +0200218 hex(proto)[2:], src_ip, dst_ip, hex(src_port)[2:],
219 hex(dst_port)[2:])).rstrip('0')
Steve Shin7957d6e2016-12-19 09:24:50 -0800220
221 @staticmethod
222 def build_mac_mask(dst_mac='', src_mac='', ether_type=''):
Jan Gelety059d1d02018-07-03 13:58:24 +0200223 """Build MAC ACL mask data with hexstring format.
Steve Shin7957d6e2016-12-19 09:24:50 -0800224
225 :param str dst_mac: source MAC address <0-ffffffffffff>
226 :param str src_mac: destination MAC address <0-ffffffffffff>
227 :param str ether_type: ethernet type <0-ffff>
228 """
229
Paul Vinciguerraea2450f2019-03-06 08:23:58 -0800230 return ('{!s:0>12}{!s:0>12}{!s:0>4}'.format(
231 dst_mac, src_mac, ether_type)).rstrip('0')
Steve Shin7957d6e2016-12-19 09:24:50 -0800232
233 @staticmethod
234 def build_mac_match(dst_mac='', src_mac='', ether_type=''):
Jan Gelety059d1d02018-07-03 13:58:24 +0200235 """Build MAC ACL match data with hexstring format.
Steve Shin7957d6e2016-12-19 09:24:50 -0800236
237 :param str dst_mac: source MAC address <x:x:x:x:x:x>
238 :param str src_mac: destination MAC address <x:x:x:x:x:x>
239 :param str ether_type: ethernet type <0-ffff>
240 """
Klement Sekeradab231a2016-12-21 08:50:14 +0100241 if dst_mac:
242 dst_mac = dst_mac.replace(':', '')
243 if src_mac:
244 src_mac = src_mac.replace(':', '')
Steve Shin7957d6e2016-12-19 09:24:50 -0800245
Paul Vinciguerraea2450f2019-03-06 08:23:58 -0800246 return ('{!s:0>12}{!s:0>12}{!s:0>4}'.format(
247 dst_mac, src_mac, ether_type)).rstrip('0')
Steve Shin7957d6e2016-12-19 09:24:50 -0800248
Jan Gelety059d1d02018-07-03 13:58:24 +0200249 def create_classify_table(self, key, mask, data_offset=0):
Steve Shin7957d6e2016-12-19 09:24:50 -0800250 """Create Classify Table
251
252 :param str key: key for classify table (ex, ACL name).
253 :param str mask: mask value for interested traffic.
Jan Gelety059d1d02018-07-03 13:58:24 +0200254 :param int data_offset:
Steve Shin7957d6e2016-12-19 09:24:50 -0800255 """
256 r = self.vapi.classify_add_del_table(
Jan Gelety059d1d02018-07-03 13:58:24 +0200257 is_add=1,
258 mask=binascii.unhexlify(mask),
Klement Sekeradab231a2016-12-21 08:50:14 +0100259 match_n_vectors=(len(mask) - 1) // 32 + 1,
260 miss_next_index=0,
261 current_data_flag=1,
262 current_data_offset=data_offset)
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800263 self.assertIsNotNone(r, 'No response msg for add_del_table')
Steve Shin7957d6e2016-12-19 09:24:50 -0800264 self.acl_tbl_idx[key] = r.new_table_index
265
Jan Gelety059d1d02018-07-03 13:58:24 +0200266 def create_classify_session(self, table_index, match, pbr_option=0,
267 vrfid=0, is_add=1):
Steve Shin7957d6e2016-12-19 09:24:50 -0800268 """Create Classify Session
269
Steve Shin7957d6e2016-12-19 09:24:50 -0800270 :param int table_index: table index to identify classify table.
271 :param str match: matched value for interested traffic.
Jan Gelety059d1d02018-07-03 13:58:24 +0200272 :param int pbr_option: enable/disable PBR feature.
Steve Shin7957d6e2016-12-19 09:24:50 -0800273 :param int vrfid: VRF id.
274 :param int is_add: option to configure classify session.
275 - create(1) or delete(0)
276 """
277 r = self.vapi.classify_add_del_session(
Klement Sekeradab231a2016-12-21 08:50:14 +0100278 is_add,
279 table_index,
280 binascii.unhexlify(match),
281 opaque_index=0,
282 action=pbr_option,
283 metadata=vrfid)
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800284 self.assertIsNotNone(r, 'No response msg for add_del_session')
Steve Shin7957d6e2016-12-19 09:24:50 -0800285
286 def input_acl_set_interface(self, intf, table_index, is_add=1):
287 """Configure Input ACL interface
288
289 :param VppInterface intf: Interface to apply Input ACL feature.
290 :param int table_index: table index to identify classify table.
291 :param int is_add: option to configure classify session.
292 - enable(1) or disable(0)
293 """
294 r = self.vapi.input_acl_set_interface(
Klement Sekeradab231a2016-12-21 08:50:14 +0100295 is_add,
296 intf.sw_if_index,
297 ip4_table_index=table_index)
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800298 self.assertIsNotNone(r, 'No response msg for acl_set_interface')
Steve Shin7957d6e2016-12-19 09:24:50 -0800299
Andrew Yourtchenko815d7d52018-02-07 11:37:02 +0100300 def output_acl_set_interface(self, intf, table_index, is_add=1):
301 """Configure Output ACL interface
302
303 :param VppInterface intf: Interface to apply Output ACL feature.
304 :param int table_index: table index to identify classify table.
305 :param int is_add: option to configure classify session.
306 - enable(1) or disable(0)
307 """
308 r = self.vapi.output_acl_set_interface(
309 is_add,
310 intf.sw_if_index,
311 ip4_table_index=table_index)
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800312 self.assertIsNotNone(r, 'No response msg for acl_set_interface')
Andrew Yourtchenko815d7d52018-02-07 11:37:02 +0100313
Jan Gelety059d1d02018-07-03 13:58:24 +0200314
315# Tests split to different test case classes because of issue reported in
316# ticket VPP-1336
317class TestClassifierIP(TestClassifier):
318 """ Classifier IP Test Case """
319
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700320 @classmethod
321 def setUpClass(cls):
322 super(TestClassifierIP, cls).setUpClass()
323
324 @classmethod
325 def tearDownClass(cls):
326 super(TestClassifierIP, cls).tearDownClass()
327
Jan Gelety059d1d02018-07-03 13:58:24 +0200328 def test_iacl_src_ip(self):
329 """ Source IP iACL test
Steve Shin7957d6e2016-12-19 09:24:50 -0800330
331 Test scenario for basic IP ACL with source IP
332 - Create IPv4 stream for pg0 -> pg1 interface.
Jan Gelety059d1d02018-07-03 13:58:24 +0200333 - Create iACL with source IP address.
Steve Shin7957d6e2016-12-19 09:24:50 -0800334 - Send and verify received packets on pg1 interface.
335 """
336
Jan Gelety059d1d02018-07-03 13:58:24 +0200337 # Basic iACL testing with source IP
Steve Shin7957d6e2016-12-19 09:24:50 -0800338 pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes)
339 self.pg0.add_stream(pkts)
340
Jan Gelety059d1d02018-07-03 13:58:24 +0200341 key = 'ip_src'
342 self.create_classify_table(key, self.build_ip_mask(src_ip='ffffffff'))
Klement Sekeradab231a2016-12-21 08:50:14 +0100343 self.create_classify_session(
Jan Gelety059d1d02018-07-03 13:58:24 +0200344 self.acl_tbl_idx.get(key),
Klement Sekeradab231a2016-12-21 08:50:14 +0100345 self.build_ip_match(src_ip=self.pg0.remote_ip4))
Jan Gelety059d1d02018-07-03 13:58:24 +0200346 self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key))
347 self.acl_active_table = key
Steve Shin7957d6e2016-12-19 09:24:50 -0800348
349 self.pg_enable_capture(self.pg_interfaces)
350 self.pg_start()
351
Klement Sekeradab231a2016-12-21 08:50:14 +0100352 pkts = self.pg1.get_capture(len(pkts))
Steve Shin7957d6e2016-12-19 09:24:50 -0800353 self.verify_capture(self.pg1, pkts)
Steve Shin7957d6e2016-12-19 09:24:50 -0800354 self.pg0.assert_nothing_captured(remark="packets forwarded")
355 self.pg2.assert_nothing_captured(remark="packets forwarded")
356 self.pg3.assert_nothing_captured(remark="packets forwarded")
357
Jan Gelety059d1d02018-07-03 13:58:24 +0200358 def test_iacl_dst_ip(self):
359 """ Destination IP iACL test
360
361 Test scenario for basic IP ACL with destination IP
362 - Create IPv4 stream for pg0 -> pg1 interface.
363 - Create iACL with destination IP address.
364 - Send and verify received packets on pg1 interface.
365 """
366
367 # Basic iACL testing with destination IP
368 pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes)
369 self.pg0.add_stream(pkts)
370
371 key = 'ip_dst'
372 self.create_classify_table(key, self.build_ip_mask(dst_ip='ffffffff'))
373 self.create_classify_session(
374 self.acl_tbl_idx.get(key),
375 self.build_ip_match(dst_ip=self.pg1.remote_ip4))
376 self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key))
377 self.acl_active_table = key
378
379 self.pg_enable_capture(self.pg_interfaces)
380 self.pg_start()
381
382 pkts = self.pg1.get_capture(len(pkts))
383 self.verify_capture(self.pg1, pkts)
384 self.pg0.assert_nothing_captured(remark="packets forwarded")
385 self.pg2.assert_nothing_captured(remark="packets forwarded")
386 self.pg3.assert_nothing_captured(remark="packets forwarded")
387
388 def test_iacl_src_dst_ip(self):
389 """ Source and destination IP iACL test
390
391 Test scenario for basic IP ACL with source and destination IP
392 - Create IPv4 stream for pg0 -> pg1 interface.
393 - Create iACL with source and destination IP addresses.
394 - Send and verify received packets on pg1 interface.
395 """
396
397 # Basic iACL testing with source and destination IP
398 pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes)
399 self.pg0.add_stream(pkts)
400
401 key = 'ip'
402 self.create_classify_table(
403 key, self.build_ip_mask(src_ip='ffffffff', dst_ip='ffffffff'))
404 self.create_classify_session(
405 self.acl_tbl_idx.get(key),
406 self.build_ip_match(src_ip=self.pg0.remote_ip4,
407 dst_ip=self.pg1.remote_ip4))
408 self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key))
409 self.acl_active_table = key
410
411 self.pg_enable_capture(self.pg_interfaces)
412 self.pg_start()
413
414 pkts = self.pg1.get_capture(len(pkts))
415 self.verify_capture(self.pg1, pkts)
416 self.pg0.assert_nothing_captured(remark="packets forwarded")
417 self.pg2.assert_nothing_captured(remark="packets forwarded")
418 self.pg3.assert_nothing_captured(remark="packets forwarded")
419
420
421class TestClassifierUDP(TestClassifier):
422 """ Classifier UDP proto Test Case """
423
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700424 @classmethod
425 def setUpClass(cls):
426 super(TestClassifierUDP, cls).setUpClass()
427
428 @classmethod
429 def tearDownClass(cls):
430 super(TestClassifierUDP, cls).tearDownClass()
431
Jan Gelety059d1d02018-07-03 13:58:24 +0200432 def test_iacl_proto_udp(self):
433 """ UDP protocol iACL test
434
435 Test scenario for basic protocol ACL with UDP protocol
436 - Create IPv4 stream for pg0 -> pg1 interface.
437 - Create iACL with UDP IP protocol.
438 - Send and verify received packets on pg1 interface.
439 """
440
441 # Basic iACL testing with UDP protocol
442 pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes)
443 self.pg0.add_stream(pkts)
444
445 key = 'proto_udp'
446 self.create_classify_table(key, self.build_ip_mask(proto='ff'))
447 self.create_classify_session(
448 self.acl_tbl_idx.get(key),
449 self.build_ip_match(proto=socket.IPPROTO_UDP))
450 self.input_acl_set_interface(
451 self.pg0, self.acl_tbl_idx.get(key))
452 self.acl_active_table = key
453
454 self.pg_enable_capture(self.pg_interfaces)
455 self.pg_start()
456
457 pkts = self.pg1.get_capture(len(pkts))
458 self.verify_capture(self.pg1, pkts)
459 self.pg0.assert_nothing_captured(remark="packets forwarded")
460 self.pg2.assert_nothing_captured(remark="packets forwarded")
461 self.pg3.assert_nothing_captured(remark="packets forwarded")
462
463 def test_iacl_proto_udp_sport(self):
464 """ UDP source port iACL test
465
466 Test scenario for basic protocol ACL with UDP and sport
467 - Create IPv4 stream for pg0 -> pg1 interface.
468 - Create iACL with UDP IP protocol and defined sport.
469 - Send and verify received packets on pg1 interface.
470 """
471
472 # Basic iACL testing with UDP and sport
473 sport = 38
474 pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes,
475 UDP(sport=sport, dport=5678))
476 self.pg0.add_stream(pkts)
477
478 key = 'proto_udp_sport'
479 self.create_classify_table(
480 key, self.build_ip_mask(proto='ff', src_port='ffff'))
481 self.create_classify_session(
482 self.acl_tbl_idx.get(key),
483 self.build_ip_match(proto=socket.IPPROTO_UDP, src_port=sport))
484 self.input_acl_set_interface(
485 self.pg0, self.acl_tbl_idx.get(key))
486 self.acl_active_table = key
487
488 self.pg_enable_capture(self.pg_interfaces)
489 self.pg_start()
490
491 pkts = self.pg1.get_capture(len(pkts))
492 self.verify_capture(self.pg1, pkts)
493 self.pg0.assert_nothing_captured(remark="packets forwarded")
494 self.pg2.assert_nothing_captured(remark="packets forwarded")
495 self.pg3.assert_nothing_captured(remark="packets forwarded")
496
497 def test_iacl_proto_udp_dport(self):
498 """ UDP destination port iACL test
499
500 Test scenario for basic protocol ACL with UDP and dport
501 - Create IPv4 stream for pg0 -> pg1 interface.
502 - Create iACL with UDP IP protocol and defined dport.
503 - Send and verify received packets on pg1 interface.
504 """
505
506 # Basic iACL testing with UDP and dport
507 dport = 427
508 pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes,
509 UDP(sport=1234, dport=dport))
510 self.pg0.add_stream(pkts)
511
512 key = 'proto_udp_dport'
513 self.create_classify_table(
514 key, self.build_ip_mask(proto='ff', dst_port='ffff'))
515 self.create_classify_session(
516 self.acl_tbl_idx.get(key),
517 self.build_ip_match(proto=socket.IPPROTO_UDP, dst_port=dport))
518 self.input_acl_set_interface(
519 self.pg0, self.acl_tbl_idx.get(key))
520 self.acl_active_table = key
521
522 self.pg_enable_capture(self.pg_interfaces)
523 self.pg_start()
524
525 pkts = self.pg1.get_capture(len(pkts))
526 self.verify_capture(self.pg1, pkts)
527 self.pg0.assert_nothing_captured(remark="packets forwarded")
528 self.pg2.assert_nothing_captured(remark="packets forwarded")
529 self.pg3.assert_nothing_captured(remark="packets forwarded")
530
531 def test_iacl_proto_udp_sport_dport(self):
532 """ UDP source and destination ports iACL test
533
534 Test scenario for basic protocol ACL with UDP and sport and dport
535 - Create IPv4 stream for pg0 -> pg1 interface.
536 - Create iACL with UDP IP protocol and defined sport and dport.
537 - Send and verify received packets on pg1 interface.
538 """
539
540 # Basic iACL testing with UDP and sport and dport
541 sport = 13720
542 dport = 9080
543 pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes,
544 UDP(sport=sport, dport=dport))
545 self.pg0.add_stream(pkts)
546
547 key = 'proto_udp_ports'
548 self.create_classify_table(
549 key,
550 self.build_ip_mask(proto='ff', src_port='ffff', dst_port='ffff'))
551 self.create_classify_session(
552 self.acl_tbl_idx.get(key),
553 self.build_ip_match(proto=socket.IPPROTO_UDP, src_port=sport,
554 dst_port=dport))
555 self.input_acl_set_interface(
556 self.pg0, self.acl_tbl_idx.get(key))
557 self.acl_active_table = key
558
559 self.pg_enable_capture(self.pg_interfaces)
560 self.pg_start()
561
562 pkts = self.pg1.get_capture(len(pkts))
563 self.verify_capture(self.pg1, pkts)
564 self.pg0.assert_nothing_captured(remark="packets forwarded")
565 self.pg2.assert_nothing_captured(remark="packets forwarded")
566 self.pg3.assert_nothing_captured(remark="packets forwarded")
567
568
569class TestClassifierTCP(TestClassifier):
570 """ Classifier TCP proto Test Case """
571
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700572 @classmethod
573 def setUpClass(cls):
574 super(TestClassifierTCP, cls).setUpClass()
575
576 @classmethod
577 def tearDownClass(cls):
578 super(TestClassifierTCP, cls).tearDownClass()
579
Jan Gelety059d1d02018-07-03 13:58:24 +0200580 def test_iacl_proto_tcp(self):
581 """ TCP protocol iACL test
582
583 Test scenario for basic protocol ACL with TCP protocol
584 - Create IPv4 stream for pg0 -> pg1 interface.
585 - Create iACL with TCP IP protocol.
586 - Send and verify received packets on pg1 interface.
587 """
588
589 # Basic iACL testing with TCP protocol
590 pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes,
591 TCP(sport=1234, dport=5678))
592 self.pg0.add_stream(pkts)
593
594 key = 'proto_tcp'
595 self.create_classify_table(key, self.build_ip_mask(proto='ff'))
596 self.create_classify_session(
597 self.acl_tbl_idx.get(key),
598 self.build_ip_match(proto=socket.IPPROTO_TCP))
599 self.input_acl_set_interface(
600 self.pg0, self.acl_tbl_idx.get(key))
601 self.acl_active_table = key
602
603 self.pg_enable_capture(self.pg_interfaces)
604 self.pg_start()
605
606 pkts = self.pg1.get_capture(len(pkts))
607 self.verify_capture(self.pg1, pkts, TCP)
608 self.pg0.assert_nothing_captured(remark="packets forwarded")
609 self.pg2.assert_nothing_captured(remark="packets forwarded")
610 self.pg3.assert_nothing_captured(remark="packets forwarded")
611
612 def test_iacl_proto_tcp_sport(self):
613 """ TCP source port iACL test
614
615 Test scenario for basic protocol ACL with TCP and sport
616 - Create IPv4 stream for pg0 -> pg1 interface.
617 - Create iACL with TCP IP protocol and defined sport.
618 - Send and verify received packets on pg1 interface.
619 """
620
621 # Basic iACL testing with TCP and sport
622 sport = 38
623 pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes,
624 TCP(sport=sport, dport=5678))
625 self.pg0.add_stream(pkts)
626
627 key = 'proto_tcp_sport'
628 self.create_classify_table(
629 key, self.build_ip_mask(proto='ff', src_port='ffff'))
630 self.create_classify_session(
631 self.acl_tbl_idx.get(key),
632 self.build_ip_match(proto=socket.IPPROTO_TCP, src_port=sport))
633 self.input_acl_set_interface(
634 self.pg0, self.acl_tbl_idx.get(key))
635 self.acl_active_table = key
636
637 self.pg_enable_capture(self.pg_interfaces)
638 self.pg_start()
639
640 pkts = self.pg1.get_capture(len(pkts))
641 self.verify_capture(self.pg1, pkts, TCP)
642 self.pg0.assert_nothing_captured(remark="packets forwarded")
643 self.pg2.assert_nothing_captured(remark="packets forwarded")
644 self.pg3.assert_nothing_captured(remark="packets forwarded")
645
646 def test_iacl_proto_tcp_dport(self):
647 """ TCP destination port iACL test
648
649 Test scenario for basic protocol ACL with TCP and dport
650 - Create IPv4 stream for pg0 -> pg1 interface.
651 - Create iACL with TCP IP protocol and defined dport.
652 - Send and verify received packets on pg1 interface.
653 """
654
655 # Basic iACL testing with TCP and dport
656 dport = 427
657 pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes,
658 TCP(sport=1234, dport=dport))
659 self.pg0.add_stream(pkts)
660
661 key = 'proto_tcp_sport'
662 self.create_classify_table(
663 key, self.build_ip_mask(proto='ff', dst_port='ffff'))
664 self.create_classify_session(
665 self.acl_tbl_idx.get(key),
666 self.build_ip_match(proto=socket.IPPROTO_TCP, dst_port=dport))
667 self.input_acl_set_interface(
668 self.pg0, self.acl_tbl_idx.get(key))
669 self.acl_active_table = key
670
671 self.pg_enable_capture(self.pg_interfaces)
672 self.pg_start()
673
674 pkts = self.pg1.get_capture(len(pkts))
675 self.verify_capture(self.pg1, pkts, TCP)
676 self.pg0.assert_nothing_captured(remark="packets forwarded")
677 self.pg2.assert_nothing_captured(remark="packets forwarded")
678 self.pg3.assert_nothing_captured(remark="packets forwarded")
679
680 def test_iacl_proto_tcp_sport_dport(self):
681 """ TCP source and destination ports iACL test
682
683 Test scenario for basic protocol ACL with TCP and sport and dport
684 - Create IPv4 stream for pg0 -> pg1 interface.
685 - Create iACL with TCP IP protocol and defined sport and dport.
686 - Send and verify received packets on pg1 interface.
687 """
688
689 # Basic iACL testing with TCP and sport and dport
690 sport = 13720
691 dport = 9080
692 pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes,
693 TCP(sport=sport, dport=dport))
694 self.pg0.add_stream(pkts)
695
696 key = 'proto_tcp_ports'
697 self.create_classify_table(
698 key,
699 self.build_ip_mask(proto='ff', src_port='ffff', dst_port='ffff'))
700 self.create_classify_session(
701 self.acl_tbl_idx.get(key),
702 self.build_ip_match(proto=socket.IPPROTO_TCP, src_port=sport,
703 dst_port=dport))
704 self.input_acl_set_interface(
705 self.pg0, self.acl_tbl_idx.get(key))
706 self.acl_active_table = key
707
708 self.pg_enable_capture(self.pg_interfaces)
709 self.pg_start()
710
711 pkts = self.pg1.get_capture(len(pkts))
712 self.verify_capture(self.pg1, pkts, TCP)
713 self.pg0.assert_nothing_captured(remark="packets forwarded")
714 self.pg2.assert_nothing_captured(remark="packets forwarded")
715 self.pg3.assert_nothing_captured(remark="packets forwarded")
716
717
718class TestClassifierIPOut(TestClassifier):
719 """ Classifier output IP Test Case """
720
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700721 @classmethod
722 def setUpClass(cls):
723 super(TestClassifierIPOut, cls).setUpClass()
724
725 @classmethod
726 def tearDownClass(cls):
727 super(TestClassifierIPOut, cls).tearDownClass()
728
Andrew Yourtchenko815d7d52018-02-07 11:37:02 +0100729 def test_acl_ip_out(self):
730 """ Output IP ACL test
731
732 Test scenario for basic IP ACL with source IP
733 - Create IPv4 stream for pg1 -> pg0 interface.
734 - Create ACL with source IP address.
735 - Send and verify received packets on pg0 interface.
736 """
737
Jan Gelety059d1d02018-07-03 13:58:24 +0200738 # Basic oACL testing with source IP
Andrew Yourtchenko815d7d52018-02-07 11:37:02 +0100739 pkts = self.create_stream(self.pg1, self.pg0, self.pg_if_packet_sizes)
740 self.pg1.add_stream(pkts)
741
Jan Gelety059d1d02018-07-03 13:58:24 +0200742 key = 'ip_out'
743 self.create_classify_table(
744 key, self.build_ip_mask(src_ip='ffffffff'), data_offset=0)
Andrew Yourtchenko815d7d52018-02-07 11:37:02 +0100745 self.create_classify_session(
Jan Gelety059d1d02018-07-03 13:58:24 +0200746 self.acl_tbl_idx.get(key),
Andrew Yourtchenko815d7d52018-02-07 11:37:02 +0100747 self.build_ip_match(src_ip=self.pg1.remote_ip4))
Jan Gelety059d1d02018-07-03 13:58:24 +0200748 self.output_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key))
749 self.acl_active_table = key
Andrew Yourtchenko815d7d52018-02-07 11:37:02 +0100750
751 self.pg_enable_capture(self.pg_interfaces)
752 self.pg_start()
753
754 pkts = self.pg0.get_capture(len(pkts))
755 self.verify_capture(self.pg0, pkts)
Andrew Yourtchenko815d7d52018-02-07 11:37:02 +0100756 self.pg1.assert_nothing_captured(remark="packets forwarded")
757 self.pg2.assert_nothing_captured(remark="packets forwarded")
758 self.pg3.assert_nothing_captured(remark="packets forwarded")
759
Jan Gelety059d1d02018-07-03 13:58:24 +0200760
761class TestClassifierMAC(TestClassifier):
762 """ Classifier MAC Test Case """
763
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700764 @classmethod
765 def setUpClass(cls):
766 super(TestClassifierMAC, cls).setUpClass()
767
768 @classmethod
769 def tearDownClass(cls):
770 super(TestClassifierMAC, cls).tearDownClass()
771
Steve Shin7957d6e2016-12-19 09:24:50 -0800772 def test_acl_mac(self):
773 """ MAC ACL test
774
775 Test scenario for basic MAC ACL with source MAC
776 - Create IPv4 stream for pg0 -> pg2 interface.
777 - Create ACL with source MAC address.
778 - Send and verify received packets on pg2 interface.
779 """
780
Jan Gelety059d1d02018-07-03 13:58:24 +0200781 # Basic iACL testing with source MAC
Steve Shin7957d6e2016-12-19 09:24:50 -0800782 pkts = self.create_stream(self.pg0, self.pg2, self.pg_if_packet_sizes)
783 self.pg0.add_stream(pkts)
784
Jan Gelety059d1d02018-07-03 13:58:24 +0200785 key = 'mac'
786 self.create_classify_table(
787 key, self.build_mac_mask(src_mac='ffffffffffff'), data_offset=-14)
Klement Sekeradab231a2016-12-21 08:50:14 +0100788 self.create_classify_session(
Jan Gelety059d1d02018-07-03 13:58:24 +0200789 self.acl_tbl_idx.get(key),
Klement Sekeradab231a2016-12-21 08:50:14 +0100790 self.build_mac_match(src_mac=self.pg0.remote_mac))
Jan Gelety059d1d02018-07-03 13:58:24 +0200791 self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key))
792 self.acl_active_table = key
Steve Shin7957d6e2016-12-19 09:24:50 -0800793
794 self.pg_enable_capture(self.pg_interfaces)
795 self.pg_start()
796
Klement Sekeradab231a2016-12-21 08:50:14 +0100797 pkts = self.pg2.get_capture(len(pkts))
Steve Shin7957d6e2016-12-19 09:24:50 -0800798 self.verify_capture(self.pg2, pkts)
Steve Shin7957d6e2016-12-19 09:24:50 -0800799 self.pg0.assert_nothing_captured(remark="packets forwarded")
800 self.pg1.assert_nothing_captured(remark="packets forwarded")
801 self.pg3.assert_nothing_captured(remark="packets forwarded")
802
Jan Gelety059d1d02018-07-03 13:58:24 +0200803
804class TestClassifierPBR(TestClassifier):
805 """ Classifier PBR Test Case """
806
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700807 @classmethod
808 def setUpClass(cls):
809 super(TestClassifierPBR, cls).setUpClass()
810
811 @classmethod
812 def tearDownClass(cls):
813 super(TestClassifierPBR, cls).tearDownClass()
814
Steve Shin7957d6e2016-12-19 09:24:50 -0800815 def test_acl_pbr(self):
816 """ IP PBR test
817
818 Test scenario for PBR with source IP
819 - Create IPv4 stream for pg0 -> pg3 interface.
820 - Configure PBR fib entry for packet forwarding.
821 - Send and verify received packets on pg3 interface.
822 """
823
824 # PBR testing with source IP
825 pkts = self.create_stream(self.pg0, self.pg3, self.pg_if_packet_sizes)
826 self.pg0.add_stream(pkts)
827
Jan Gelety059d1d02018-07-03 13:58:24 +0200828 key = 'pbr'
829 self.create_classify_table(key, self.build_ip_mask(src_ip='ffffffff'))
Steve Shin7957d6e2016-12-19 09:24:50 -0800830 pbr_option = 1
Neale Ranns13eaf3e2017-05-23 06:10:33 -0700831 # this will create the VRF/table in which we will insert the route
Klement Sekeradab231a2016-12-21 08:50:14 +0100832 self.create_classify_session(
Jan Gelety059d1d02018-07-03 13:58:24 +0200833 self.acl_tbl_idx.get(key),
Klement Sekeradab231a2016-12-21 08:50:14 +0100834 self.build_ip_match(src_ip=self.pg0.remote_ip4),
835 pbr_option, self.pbr_vrfid)
Neale Ranns13eaf3e2017-05-23 06:10:33 -0700836 self.assertTrue(self.verify_vrf(self.pbr_vrfid))
Neale Ranns097fa662018-05-01 05:17:55 -0700837 r = VppIpRoute(self, self.pg3.local_ip4, 24,
838 [VppRoutePath(self.pg3.remote_ip4,
839 INVALID_INDEX)],
840 table_id=self.pbr_vrfid)
841 r.add_vpp_config()
842
Jan Gelety059d1d02018-07-03 13:58:24 +0200843 self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key))
Steve Shin7957d6e2016-12-19 09:24:50 -0800844
845 self.pg_enable_capture(self.pg_interfaces)
846 self.pg_start()
847
Klement Sekeradab231a2016-12-21 08:50:14 +0100848 pkts = self.pg3.get_capture(len(pkts))
Steve Shin7957d6e2016-12-19 09:24:50 -0800849 self.verify_capture(self.pg3, pkts)
Jan Gelety059d1d02018-07-03 13:58:24 +0200850 self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key), 0)
Steve Shin7957d6e2016-12-19 09:24:50 -0800851 self.pg0.assert_nothing_captured(remark="packets forwarded")
852 self.pg1.assert_nothing_captured(remark="packets forwarded")
853 self.pg2.assert_nothing_captured(remark="packets forwarded")
854
Neale Ranns13eaf3e2017-05-23 06:10:33 -0700855 # remove the classify session and the route
Neale Ranns097fa662018-05-01 05:17:55 -0700856 r.remove_vpp_config()
Neale Ranns13eaf3e2017-05-23 06:10:33 -0700857 self.create_classify_session(
Jan Gelety059d1d02018-07-03 13:58:24 +0200858 self.acl_tbl_idx.get(key),
Neale Ranns13eaf3e2017-05-23 06:10:33 -0700859 self.build_ip_match(src_ip=self.pg0.remote_ip4),
860 pbr_option, self.pbr_vrfid, is_add=0)
861
862 # and the table should be gone.
863 self.assertFalse(self.verify_vrf(self.pbr_vrfid))
Steve Shin7957d6e2016-12-19 09:24:50 -0800864
865if __name__ == '__main__':
866 unittest.main(testRunner=VppTestRunner)