tests: replace pycodestyle with black
[vpp.git] / test / test_p2p_ethernet.py
1 #!/usr/bin/env python3
2 import random
3 import unittest
4 import datetime
5 import re
6
7 from scapy.packet import Raw
8 from scapy.layers.l2 import Ether
9 from scapy.layers.inet import IP, UDP
10 from scapy.layers.inet6 import IPv6
11
12 from framework import VppTestCase, VppTestRunner
13 from vpp_sub_interface import VppP2PSubint
14 from vpp_ip import DpoProto
15 from vpp_ip_route import VppIpRoute, VppRoutePath
16 from vpp_papi import mac_pton
17
18
19 class P2PEthernetAPI(VppTestCase):
20     """P2P Ethernet tests"""
21
22     p2p_sub_ifs = []
23
24     @classmethod
25     def setUpClass(cls):
26         super(P2PEthernetAPI, cls).setUpClass()
27
28         # Create pg interfaces
29         cls.create_pg_interfaces(range(4))
30
31         # Set up all interfaces
32         for i in cls.pg_interfaces:
33             i.admin_up()
34
35     @classmethod
36     def tearDownClass(cls):
37         super(P2PEthernetAPI, cls).tearDownClass()
38
39     def create_p2p_ethernet(self, parent_if, sub_id, remote_mac):
40         p2p = VppP2PSubint(self, parent_if, sub_id, mac_pton(remote_mac))
41         self.p2p_sub_ifs.append(p2p)
42
43     def delete_p2p_ethernet(self, parent_if, remote_mac):
44         self.vapi.p2p_ethernet_del(parent_if.sw_if_index, mac_pton(remote_mac))
45
46     def test_api(self):
47         """delete/create p2p subif"""
48         self.logger.info("FFP_TEST_START_0000")
49
50         self.create_p2p_ethernet(self.pg0, 1, "de:ad:00:00:00:01")
51         self.create_p2p_ethernet(self.pg0, 2, "de:ad:00:00:00:02")
52         intfs = self.vapi.cli("show interface")
53
54         self.assertIn("pg0.1", intfs)
55         self.assertIn("pg0.2", intfs)
56         self.assertNotIn("pg0.5", intfs)
57
58         # create pg2.5 subif
59         self.create_p2p_ethernet(self.pg0, 5, "de:ad:00:00:00:ff")
60         intfs = self.vapi.cli("show interface")
61         self.assertIn("pg0.5", intfs)
62         # delete pg2.5 subif
63         self.delete_p2p_ethernet(self.pg0, "de:ad:00:00:00:ff")
64
65         intfs = self.vapi.cli("show interface")
66
67         self.assertIn("pg0.1", intfs)
68         self.assertIn("pg0.2", intfs)
69         self.assertNotIn("pg0.5", intfs)
70
71         self.logger.info("FFP_TEST_FINISH_0000")
72
73     def test_p2p_subif_creation_1k(self):
74         """create 1k of p2p subifs"""
75         self.logger.info("FFP_TEST_START_0001")
76
77         macs = []
78         clients = 1000
79         mac = int("dead00000000", 16)
80
81         for i in range(1, clients + 1):
82             try:
83                 macs.append(":".join(re.findall("..", "{:02x}".format(mac + i))))
84                 self.vapi.p2p_ethernet_add(
85                     self.pg2.sw_if_index, mac_pton(macs[i - 1]), i
86                 )
87             except Exception:
88                 self.logger.info("Failed to create subif %d %s" % (i, macs[i - 1]))
89                 raise
90
91         intfs = self.vapi.cli("show interface").split("\n")
92         count = 0
93         for intf in intfs:
94             if intf.startswith("pg2."):
95                 count += 1
96         self.assertEqual(count, clients)
97
98         self.logger.info("FFP_TEST_FINISH_0001")
99
100
101 class P2PEthernetIPV6(VppTestCase):
102     """P2P Ethernet IPv6 tests"""
103
104     p2p_sub_ifs = []
105     packets = []
106
107     @classmethod
108     def setUpClass(cls):
109         super(P2PEthernetIPV6, cls).setUpClass()
110
111         # Create pg interfaces
112         cls.create_pg_interfaces(range(3))
113
114         # Packet sizes
115         cls.pg_if_packet_sizes = [64, 512, 1518, 9018]
116
117         # Set up all interfaces
118         for i in cls.pg_interfaces:
119             i.admin_up()
120
121         cls.pg0.generate_remote_hosts(3)
122         cls.pg0.configure_ipv6_neighbors()
123
124         cls.pg1.config_ip6()
125         cls.pg1.generate_remote_hosts(3)
126         cls.pg1.configure_ipv6_neighbors()
127         cls.pg1.disable_ipv6_ra()
128
129     @classmethod
130     def tearDownClass(cls):
131         super(P2PEthernetIPV6, cls).tearDownClass()
132
133     def setUp(self):
134         super(P2PEthernetIPV6, self).setUp()
135         for p in self.packets:
136             self.packets.remove(p)
137         self.p2p_sub_ifs.append(
138             self.create_p2p_ethernet(self.pg0, 1, self.pg0._remote_hosts[0].mac)
139         )
140         self.p2p_sub_ifs.append(
141             self.create_p2p_ethernet(self.pg0, 2, self.pg0._remote_hosts[1].mac)
142         )
143         self.vapi.cli("trace add p2p-ethernet-input 50")
144
145     def tearDown(self):
146         while len(self.p2p_sub_ifs):
147             p2p = self.p2p_sub_ifs.pop()
148             self.delete_p2p_ethernet(p2p)
149
150         super(P2PEthernetIPV6, self).tearDown()
151
152     def create_p2p_ethernet(self, parent_if, sub_id, remote_mac):
153         p2p = VppP2PSubint(self, parent_if, sub_id, mac_pton(remote_mac))
154         p2p.admin_up()
155         p2p.config_ip6()
156         p2p.disable_ipv6_ra()
157         return p2p
158
159     def delete_p2p_ethernet(self, p2p):
160         p2p.unconfig_ip6()
161         p2p.admin_down()
162         self.vapi.p2p_ethernet_del(p2p.parent.sw_if_index, p2p.p2p_remote_mac)
163
164     def create_stream(
165         self, src_mac=None, dst_mac=None, src_ip=None, dst_ip=None, size=None
166     ):
167         pkt_size = size
168         if size is None:
169             pkt_size = random.choice(self.pg_if_packet_sizes)
170         p = Ether(src=src_mac, dst=dst_mac)
171         p /= IPv6(src=src_ip, dst=dst_ip)
172         p /= UDP(sport=1234, dport=4321) / Raw(b"\xa5" * 20)
173         self.extend_packet(p, pkt_size)
174         return p
175
176     def send_packets(self, src_if=None, dst_if=None, packets=None, count=None):
177         self.pg_enable_capture([dst_if])
178         if packets is None:
179             packets = self.packets
180         src_if.add_stream(packets)
181         self.pg_start()
182         if count is None:
183             count = len(packets)
184         return dst_if.get_capture(count)
185
186     def test_no_p2p_subif(self):
187         """standard routing without p2p subinterfaces"""
188         self.logger.info("FFP_TEST_START_0001")
189
190         self.pg0.config_ip6()
191         route_8000 = VppIpRoute(
192             self,
193             "8000::",
194             64,
195             [VppRoutePath(self.pg0.remote_ip6, self.pg0.sw_if_index)],
196         )
197         route_8000.add_vpp_config()
198
199         self.packets = [
200             (
201                 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
202                 / IPv6(src="3001::1", dst="8000::100")
203                 / UDP(sport=1234, dport=1234)
204                 / Raw(b"\xa5" * 100)
205             )
206         ]
207         self.send_packets(self.pg1, self.pg0)
208
209         self.pg0.unconfig_ip6()
210         self.logger.info("FFP_TEST_FINISH_0001")
211
212     def test_ip6_rx_p2p_subif(self):
213         """receive ipv6 packet via p2p subinterface"""
214         self.logger.info("FFP_TEST_START_0002")
215
216         route_9001 = VppIpRoute(
217             self,
218             "9001::",
219             64,
220             [VppRoutePath(self.pg1.remote_ip6, self.pg1.sw_if_index)],
221         )
222         route_9001.add_vpp_config()
223
224         self.packets.append(
225             self.create_stream(
226                 src_mac=self.pg0._remote_hosts[0].mac,
227                 dst_mac=self.pg0.local_mac,
228                 src_ip=self.p2p_sub_ifs[0].remote_ip6,
229                 dst_ip="9001::100",
230             )
231         )
232
233         self.send_packets(self.pg0, self.pg1, self.packets)
234         self.assert_packet_counter_equal("p2p-ethernet-input", 1)
235
236         route_9001.remove_vpp_config()
237         self.logger.info("FFP_TEST_FINISH_0002")
238
239     def test_ip6_rx_p2p_subif_route(self):
240         """route rx ip6 packet not matching p2p subinterface"""
241         self.logger.info("FFP_TEST_START_0003")
242
243         self.pg0.config_ip6()
244
245         route_3 = VppIpRoute(
246             self,
247             "9000::",
248             64,
249             [VppRoutePath(self.pg1._remote_hosts[0].ip6, self.pg1.sw_if_index)],
250         )
251         route_3.add_vpp_config()
252
253         self.packets.append(
254             self.create_stream(
255                 src_mac="02:03:00:00:ff:ff",
256                 dst_mac=self.pg0.local_mac,
257                 src_ip="a000::100",
258                 dst_ip="9000::100",
259             )
260         )
261
262         self.send_packets(self.pg0, self.pg1)
263
264         self.pg0.unconfig_ip6()
265
266         route_3.remove_vpp_config()
267
268         self.logger.info("FFP_TEST_FINISH_0003")
269
270     def test_ip6_rx_p2p_subif_drop(self):
271         """drop rx packet not matching p2p subinterface"""
272         self.logger.info("FFP_TEST_START_0004")
273
274         route_9001 = VppIpRoute(
275             self,
276             "9000::",
277             64,
278             [VppRoutePath(self.pg1._remote_hosts[0].ip6, self.pg1.sw_if_index)],
279         )
280         route_9001.add_vpp_config()
281
282         self.packets.append(
283             self.create_stream(
284                 src_mac="02:03:00:00:ff:ff",
285                 dst_mac=self.pg0.local_mac,
286                 src_ip="a000::100",
287                 dst_ip="9000::100",
288             )
289         )
290
291         # no packet received
292         self.send_packets(self.pg0, self.pg1, count=0)
293         self.logger.info("FFP_TEST_FINISH_0004")
294
295     def test_ip6_tx_p2p_subif(self):
296         """send packet via p2p subinterface"""
297         self.logger.info("FFP_TEST_START_0005")
298
299         self.pg0.config_ip6()
300
301         route_8000 = VppIpRoute(
302             self,
303             "8000::",
304             64,
305             [VppRoutePath(self.pg0.remote_hosts[0].ip6, self.pg0.sw_if_index)],
306         )
307         route_8000.add_vpp_config()
308         route_8001 = VppIpRoute(
309             self,
310             "8001::",
311             64,
312             [
313                 VppRoutePath(
314                     self.p2p_sub_ifs[0].remote_ip6, self.p2p_sub_ifs[0].sw_if_index
315                 )
316             ],
317         )
318         route_8001.add_vpp_config()
319         route_8002 = VppIpRoute(
320             self,
321             "8002::",
322             64,
323             [
324                 VppRoutePath(
325                     self.p2p_sub_ifs[1].remote_ip6, self.p2p_sub_ifs[1].sw_if_index
326                 )
327             ],
328         )
329         route_8002.add_vpp_config()
330
331         for i in range(0, 3):
332             self.packets.append(
333                 self.create_stream(
334                     src_mac=self.pg1.remote_mac,
335                     dst_mac=self.pg1.local_mac,
336                     src_ip=self.pg1.remote_ip6,
337                     dst_ip="800%d::100" % i,
338                 )
339             )
340
341         self.send_packets(self.pg1, self.pg0, count=3)
342
343         route_8000.remove_vpp_config()
344         route_8001.remove_vpp_config()
345         route_8002.remove_vpp_config()
346
347         self.pg0.unconfig_ip6()
348         self.logger.info("FFP_TEST_FINISH_0005")
349
350     def test_ip6_tx_p2p_subif_drop(self):
351         """drop tx ip6 packet not matching p2p subinterface"""
352         self.logger.info("FFP_TEST_START_0006")
353
354         self.packets.append(
355             self.create_stream(
356                 src_mac="02:03:00:00:ff:ff",
357                 dst_mac=self.pg0.local_mac,
358                 src_ip="a000::100",
359                 dst_ip="9000::100",
360             )
361         )
362
363         # no packet received
364         self.send_packets(self.pg0, self.pg1, count=0)
365         self.logger.info("FFP_TEST_FINISH_0006")
366
367
368 class P2PEthernetIPV4(VppTestCase):
369     """P2P Ethernet IPv4 tests"""
370
371     p2p_sub_ifs = []
372     packets = []
373
374     @classmethod
375     def setUpClass(cls):
376         super(P2PEthernetIPV4, cls).setUpClass()
377
378         # Create pg interfaces
379         cls.create_pg_interfaces(range(3))
380
381         # Packet sizes
382         cls.pg_if_packet_sizes = [64, 512, 1518, 9018]
383
384         # Set up all interfaces
385         for i in cls.pg_interfaces:
386             i.admin_up()
387
388         cls.pg0.config_ip4()
389         cls.pg0.generate_remote_hosts(5)
390         cls.pg0.configure_ipv4_neighbors()
391
392         cls.pg1.config_ip4()
393         cls.pg1.generate_remote_hosts(5)
394         cls.pg1.configure_ipv4_neighbors()
395
396     @classmethod
397     def tearDownClass(cls):
398         super(P2PEthernetIPV4, cls).tearDownClass()
399
400     def setUp(self):
401         super(P2PEthernetIPV4, self).setUp()
402         for p in self.packets:
403             self.packets.remove(p)
404         self.p2p_sub_ifs.append(
405             self.create_p2p_ethernet(self.pg0, 1, self.pg0._remote_hosts[0].mac)
406         )
407         self.p2p_sub_ifs.append(
408             self.create_p2p_ethernet(self.pg0, 2, self.pg0._remote_hosts[1].mac)
409         )
410         self.vapi.cli("trace add p2p-ethernet-input 50")
411
412     def tearDown(self):
413         while len(self.p2p_sub_ifs):
414             p2p = self.p2p_sub_ifs.pop()
415             self.delete_p2p_ethernet(p2p)
416         super(P2PEthernetIPV4, self).tearDown()
417
418     def create_stream(
419         self, src_mac=None, dst_mac=None, src_ip=None, dst_ip=None, size=None
420     ):
421         pkt_size = size
422         if size is None:
423             pkt_size = random.choice(self.pg_if_packet_sizes)
424         p = Ether(src=src_mac, dst=dst_mac)
425         p /= IP(src=src_ip, dst=dst_ip)
426         p /= UDP(sport=1234, dport=4321) / Raw(b"\xa5" * 20)
427         self.extend_packet(p, pkt_size)
428         return p
429
430     def send_packets(self, src_if=None, dst_if=None, packets=None, count=None):
431         self.pg_enable_capture([dst_if])
432         if packets is None:
433             packets = self.packets
434         src_if.add_stream(packets)
435         self.pg_start()
436         if count is None:
437             count = len(packets)
438         return dst_if.get_capture(count)
439
440     def create_p2p_ethernet(self, parent_if, sub_id, remote_mac):
441         p2p = VppP2PSubint(self, parent_if, sub_id, mac_pton(remote_mac))
442         p2p.admin_up()
443         p2p.config_ip4()
444         return p2p
445
446     def delete_p2p_ethernet(self, p2p):
447         p2p.unconfig_ip4()
448         p2p.admin_down()
449         self.vapi.p2p_ethernet_del(p2p.parent.sw_if_index, p2p.p2p_remote_mac)
450
451     def test_ip4_rx_p2p_subif(self):
452         """receive ipv4 packet via p2p subinterface"""
453         self.logger.info("FFP_TEST_START_0002")
454
455         route_9000 = VppIpRoute(
456             self,
457             "9.0.0.0",
458             16,
459             [VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index)],
460         )
461         route_9000.add_vpp_config()
462
463         self.packets.append(
464             self.create_stream(
465                 src_mac=self.pg0._remote_hosts[0].mac,
466                 dst_mac=self.pg0.local_mac,
467                 src_ip=self.p2p_sub_ifs[0].remote_ip4,
468                 dst_ip="9.0.0.100",
469             )
470         )
471
472         self.send_packets(self.pg0, self.pg1, self.packets)
473
474         self.assert_packet_counter_equal("p2p-ethernet-input", 1)
475
476         route_9000.remove_vpp_config()
477         self.logger.info("FFP_TEST_FINISH_0002")
478
479     def test_ip4_rx_p2p_subif_route(self):
480         """route rx packet not matching p2p subinterface"""
481         self.logger.info("FFP_TEST_START_0003")
482
483         route_9001 = VppIpRoute(
484             self,
485             "9.0.0.0",
486             24,
487             [VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index)],
488         )
489         route_9001.add_vpp_config()
490
491         self.packets.append(
492             self.create_stream(
493                 src_mac="02:01:00:00:ff:ff",
494                 dst_mac=self.pg0.local_mac,
495                 src_ip="8.0.0.100",
496                 dst_ip="9.0.0.100",
497             )
498         )
499
500         self.send_packets(self.pg0, self.pg1)
501
502         route_9001.remove_vpp_config()
503
504         self.logger.info("FFP_TEST_FINISH_0003")
505
506     def test_ip4_tx_p2p_subif(self):
507         """send ip4 packet via p2p subinterface"""
508         self.logger.info("FFP_TEST_START_0005")
509
510         route_9100 = VppIpRoute(
511             self,
512             "9.1.0.100",
513             24,
514             [
515                 VppRoutePath(
516                     self.pg0.remote_ip4,
517                     self.pg0.sw_if_index,
518                 )
519             ],
520         )
521         route_9100.add_vpp_config()
522         route_9200 = VppIpRoute(
523             self,
524             "9.2.0.100",
525             24,
526             [
527                 VppRoutePath(
528                     self.p2p_sub_ifs[0].remote_ip4,
529                     self.p2p_sub_ifs[0].sw_if_index,
530                 )
531             ],
532         )
533         route_9200.add_vpp_config()
534         route_9300 = VppIpRoute(
535             self,
536             "9.3.0.100",
537             24,
538             [
539                 VppRoutePath(
540                     self.p2p_sub_ifs[1].remote_ip4, self.p2p_sub_ifs[1].sw_if_index
541                 )
542             ],
543         )
544         route_9300.add_vpp_config()
545
546         for i in range(0, 3):
547             self.packets.append(
548                 self.create_stream(
549                     src_mac=self.pg1.remote_mac,
550                     dst_mac=self.pg1.local_mac,
551                     src_ip=self.pg1.remote_ip4,
552                     dst_ip="9.%d.0.100" % (i + 1),
553                 )
554             )
555
556         self.send_packets(self.pg1, self.pg0)
557
558         # route_7000.remove_vpp_config()
559         route_9100.remove_vpp_config()
560         route_9200.remove_vpp_config()
561         route_9300.remove_vpp_config()
562
563         self.logger.info("FFP_TEST_FINISH_0005")
564
565     def test_ip4_tx_p2p_subif_drop(self):
566         """drop tx ip4 packet not matching p2p subinterface"""
567         self.logger.info("FFP_TEST_START_0006")
568
569         self.packets.append(
570             self.create_stream(
571                 src_mac="02:01:00:00:ff:ff",
572                 dst_mac=self.pg0.local_mac,
573                 src_ip="8.0.0.100",
574                 dst_ip="9.0.0.100",
575             )
576         )
577
578         # no packet received
579         self.send_packets(self.pg0, self.pg1, count=0)
580         self.logger.info("FFP_TEST_FINISH_0006")
581
582
583 if __name__ == "__main__":
584     unittest.main(testRunner=VppTestRunner)