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