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