blob: 2ec4af9288ee348e5c3ce588f5a9bfdf7b020c6c [file] [log] [blame]
Damjan Marionf56b77a2016-10-03 19:44:57 +02001#!/usr/bin/env python
Damjan Marionf56b77a2016-10-03 19:44:57 +02002
3import unittest
4import random
Klement Sekeraf62ae122016-10-11 11:47:09 +02005
6from scapy.packet import Raw
7from scapy.layers.l2 import Ether
Damjan Marionf56b77a2016-10-03 19:44:57 +02008from scapy.layers.inet import IP, UDP
Klement Sekeraf62ae122016-10-11 11:47:09 +02009
10from framework import VppTestCase, VppTestRunner
Klement Sekera7bb873a2016-11-18 07:38:42 +010011from util import Host, ppp
Damjan Marionf56b77a2016-10-03 19:44:57 +020012
13
Damjan Marionf56b77a2016-10-03 19:44:57 +020014class TestL2xc(VppTestCase):
15 """ L2XC Test Case """
16
Damjan Marionf56b77a2016-10-03 19:44:57 +020017 @classmethod
18 def setUpClass(cls):
Jan49c0fca2016-10-26 15:44:27 +020019 """
20 Perform standard class setup (defined by class method setUpClass in
21 class VppTestCase) before running the test case, set test case related
22 variables and configure VPP.
23
24 :var int hosts_nr: Number of hosts to be created.
25 :var int dl_pkts_per_burst: Number of packets in burst for dual-loop
26 test.
27 :var int sl_pkts_per_burst: Number of packets in burst for single-loop
28 test.
29 """
Damjan Marionf56b77a2016-10-03 19:44:57 +020030 super(TestL2xc, cls).setUpClass()
31
Jan49c0fca2016-10-26 15:44:27 +020032 # Test variables
33 cls.hosts_nr = 10
34 cls.dl_pkts_per_burst = 257
35 cls.sl_pkts_per_burst = 2
36
37 try:
38 # create 4 pg interfaces
39 cls.create_pg_interfaces(range(4))
40
41 # packet flows mapping pg0 -> pg1, pg2 -> pg3, etc.
42 cls.flows = dict()
43 cls.flows[cls.pg0] = [cls.pg1]
44 cls.flows[cls.pg1] = [cls.pg0]
45 cls.flows[cls.pg2] = [cls.pg3]
46 cls.flows[cls.pg3] = [cls.pg2]
47
48 # packet sizes
49 cls.pg_if_packet_sizes = [64, 512, 1518, 9018]
50
51 cls.interfaces = list(cls.pg_interfaces)
52
53 # Create bi-directional cross-connects between pg0 and pg1
54 cls.vapi.sw_interface_set_l2_xconnect(
55 cls.pg0.sw_if_index, cls.pg1.sw_if_index, enable=1)
56 cls.vapi.sw_interface_set_l2_xconnect(
57 cls.pg1.sw_if_index, cls.pg0.sw_if_index, enable=1)
58
59 # Create bi-directional cross-connects between pg2 and pg3
60 cls.vapi.sw_interface_set_l2_xconnect(
61 cls.pg2.sw_if_index, cls.pg3.sw_if_index, enable=1)
62 cls.vapi.sw_interface_set_l2_xconnect(
63 cls.pg3.sw_if_index, cls.pg2.sw_if_index, enable=1)
64
65 # mapping between packet-generator index and lists of test hosts
66 cls.hosts_by_pg_idx = dict()
67
68 # Create host MAC and IPv4 lists
69 cls.create_host_lists(cls.hosts_nr)
70
71 # setup all interfaces
72 for i in cls.interfaces:
73 i.admin_up()
74
75 except Exception:
76 super(TestL2xc, cls).tearDownClass()
77 raise
78
Klement Sekeraf62ae122016-10-11 11:47:09 +020079 def setUp(self):
80 super(TestL2xc, self).setUp()
Klement Sekeradab231a2016-12-21 08:50:14 +010081 self.reset_packet_infos()
Klement Sekeraf62ae122016-10-11 11:47:09 +020082
Damjan Marionf56b77a2016-10-03 19:44:57 +020083 def tearDown(self):
Jan49c0fca2016-10-26 15:44:27 +020084 """
85 Show various debug prints after each test.
86 """
Klement Sekeraf62ae122016-10-11 11:47:09 +020087 super(TestL2xc, self).tearDown()
88 if not self.vpp_dead:
Jan49c0fca2016-10-26 15:44:27 +020089 self.logger.info(self.vapi.ppcli("show l2patch"))
Damjan Marionf56b77a2016-10-03 19:44:57 +020090
Jan49c0fca2016-10-26 15:44:27 +020091 @classmethod
92 def create_host_lists(cls, count):
93 """
94 Method to create required number of MAC and IPv4 addresses.
Klement Sekeraf62ae122016-10-11 11:47:09 +020095 Create required number of host MAC addresses and distribute them among
96 interfaces. Create host IPv4 address for every host MAC address too.
97
98 :param count: Number of hosts to create MAC and IPv4 addresses for.
Klement Sekeraf62ae122016-10-11 11:47:09 +020099 """
Jan49c0fca2016-10-26 15:44:27 +0200100 for pg_if in cls.pg_interfaces:
101 cls.hosts_by_pg_idx[pg_if.sw_if_index] = []
102 hosts = cls.hosts_by_pg_idx[pg_if.sw_if_index]
Damjan Marionf56b77a2016-10-03 19:44:57 +0200103 for j in range(0, count):
Matej Klotton0178d522016-11-04 11:11:44 +0100104 host = Host(
Klement Sekeraf62ae122016-10-11 11:47:09 +0200105 "00:00:00:ff:%02x:%02x" % (pg_if.sw_if_index, j),
106 "172.17.1%02x.%u" % (pg_if.sw_if_index, j))
107 hosts.append(host)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200108
Jan49c0fca2016-10-26 15:44:27 +0200109 def create_stream(self, src_if, packet_sizes, packets_per_burst):
110 """
111 Create input packet stream for defined interface.
112
113 :param object src_if: Interface to create packet stream for.
114 :param list packet_sizes: List of required packet sizes.
115 :param int packets_per_burst: Number of packets in burst.
116 :return: Stream of packets.
117 """
Damjan Marionf56b77a2016-10-03 19:44:57 +0200118 pkts = []
Jan49c0fca2016-10-26 15:44:27 +0200119 for i in range(0, packets_per_burst):
Klement Sekeraf62ae122016-10-11 11:47:09 +0200120 dst_if = self.flows[src_if][0]
121 dst_host = random.choice(self.hosts_by_pg_idx[dst_if.sw_if_index])
122 src_host = random.choice(self.hosts_by_pg_idx[src_if.sw_if_index])
Klement Sekeradab231a2016-12-21 08:50:14 +0100123 pkt_info = self.create_packet_info(src_if, dst_if)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200124 payload = self.info_to_payload(pkt_info)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200125 p = (Ether(dst=dst_host.mac, src=src_host.mac) /
126 IP(src=src_host.ip4, dst=dst_host.ip4) /
Damjan Marionf56b77a2016-10-03 19:44:57 +0200127 UDP(sport=1234, dport=1234) /
128 Raw(payload))
129 pkt_info.data = p.copy()
Jan49c0fca2016-10-26 15:44:27 +0200130 size = random.choice(packet_sizes)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200131 self.extend_packet(p, size)
132 pkts.append(p)
133 return pkts
Damjan Marionf56b77a2016-10-03 19:44:57 +0200134
Klement Sekeraf62ae122016-10-11 11:47:09 +0200135 def verify_capture(self, pg_if, capture):
Jan49c0fca2016-10-26 15:44:27 +0200136 """
137 Verify captured input packet stream for defined interface.
138
139 :param object pg_if: Interface to verify captured packet stream for.
140 :param list capture: Captured packet stream.
141 """
Klement Sekeraf62ae122016-10-11 11:47:09 +0200142 last_info = dict()
Damjan Marionf56b77a2016-10-03 19:44:57 +0200143 for i in self.interfaces:
Klement Sekeraf62ae122016-10-11 11:47:09 +0200144 last_info[i.sw_if_index] = None
145 dst_sw_if_index = pg_if.sw_if_index
Damjan Marionf56b77a2016-10-03 19:44:57 +0200146 for packet in capture:
147 try:
148 ip = packet[IP]
149 udp = packet[UDP]
150 payload_info = self.payload_to_info(str(packet[Raw]))
Klement Sekeraf62ae122016-10-11 11:47:09 +0200151 packet_index = payload_info.index
152 self.assertEqual(payload_info.dst, dst_sw_if_index)
Jan49c0fca2016-10-26 15:44:27 +0200153 self.logger.debug("Got packet on port %s: src=%u (id=%u)" %
154 (pg_if.name, payload_info.src, packet_index))
Damjan Marionf56b77a2016-10-03 19:44:57 +0200155 next_info = self.get_next_packet_info_for_interface2(
Klement Sekeraf62ae122016-10-11 11:47:09 +0200156 payload_info.src, dst_sw_if_index,
Damjan Marionf56b77a2016-10-03 19:44:57 +0200157 last_info[payload_info.src])
158 last_info[payload_info.src] = next_info
159 self.assertTrue(next_info is not None)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200160 self.assertEqual(packet_index, next_info.index)
161 saved_packet = next_info.data
Damjan Marionf56b77a2016-10-03 19:44:57 +0200162 # Check standard fields
Klement Sekeraf62ae122016-10-11 11:47:09 +0200163 self.assertEqual(ip.src, saved_packet[IP].src)
164 self.assertEqual(ip.dst, saved_packet[IP].dst)
165 self.assertEqual(udp.sport, saved_packet[UDP].sport)
166 self.assertEqual(udp.dport, saved_packet[UDP].dport)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200167 except:
Klement Sekera7bb873a2016-11-18 07:38:42 +0100168 self.logger.error(ppp("Unexpected or invalid packet:", packet))
Damjan Marionf56b77a2016-10-03 19:44:57 +0200169 raise
170 for i in self.interfaces:
171 remaining_packet = self.get_next_packet_info_for_interface2(
Klement Sekeraf62ae122016-10-11 11:47:09 +0200172 i, dst_sw_if_index, last_info[i.sw_if_index])
Damjan Marionf56b77a2016-10-03 19:44:57 +0200173 self.assertTrue(remaining_packet is None,
174 "Port %u: Packet expected from source %u didn't"
Klement Sekeraf62ae122016-10-11 11:47:09 +0200175 " arrive" % (dst_sw_if_index, i.sw_if_index))
Damjan Marionf56b77a2016-10-03 19:44:57 +0200176
Jan49c0fca2016-10-26 15:44:27 +0200177 def run_l2xc_test(self, pkts_per_burst):
178 """ L2XC test """
Damjan Marionf56b77a2016-10-03 19:44:57 +0200179
Klement Sekeraf62ae122016-10-11 11:47:09 +0200180 # Create incoming packet streams for packet-generator interfaces
Damjan Marionf56b77a2016-10-03 19:44:57 +0200181 for i in self.interfaces:
Jan49c0fca2016-10-26 15:44:27 +0200182 pkts = self.create_stream(i, self.pg_if_packet_sizes,
183 pkts_per_burst)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200184 i.add_stream(pkts)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200185
Klement Sekeraf62ae122016-10-11 11:47:09 +0200186 # Enable packet capturing and start packet sending
187 self.pg_enable_capture(self.pg_interfaces)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200188 self.pg_start()
189
Klement Sekeraf62ae122016-10-11 11:47:09 +0200190 # Verify outgoing packet streams per packet-generator interface
191 for i in self.pg_interfaces:
192 capture = i.get_capture()
Jan49c0fca2016-10-26 15:44:27 +0200193 self.logger.info("Verifying capture on interface %s" % i.name)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200194 self.verify_capture(i, capture)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200195
Jan49c0fca2016-10-26 15:44:27 +0200196 def test_l2xc_sl(self):
197 """ L2XC single-loop test
198
199 Test scenario:
200 1. config
201 2 pairs of 2 interfaces, l2xconnected
202
203 2. sending l2 eth packets between 4 interfaces
204 64B, 512B, 1518B, 9018B (ether_size)
205 burst of 2 packets per interface
206 """
207
208 self.run_l2xc_test(self.sl_pkts_per_burst)
209
210 def test_l2xc_dl(self):
211 """ L2XC dual-loop test
212
213 Test scenario:
214 1. config
215 2 pairs of 2 interfaces, l2xconnected
216
217 2. sending l2 eth packets between 4 interfaces
218 64B, 512B, 1518B, 9018B (ether_size)
219 burst of 257 packets per interface
220 """
221
222 self.run_l2xc_test(self.dl_pkts_per_burst)
223
Damjan Marionf56b77a2016-10-03 19:44:57 +0200224
225if __name__ == '__main__':
Klement Sekeraf62ae122016-10-11 11:47:09 +0200226 unittest.main(testRunner=VppTestRunner)