blob: d448a04d13c81b7359e297e3a229fc244b6f68f0 [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 +02009from logging import *
10
11from framework import VppTestCase, VppTestRunner
12from util import TestHost
Damjan Marionf56b77a2016-10-03 19:44:57 +020013
14
Damjan Marionf56b77a2016-10-03 19:44:57 +020015class TestL2xc(VppTestCase):
16 """ L2XC Test Case """
17
18 # Test variables
Damjan Marionf56b77a2016-10-03 19:44:57 +020019 hosts_nr = 10 # Number of hosts
20 pkts_per_burst = 257 # Number of packets per burst
21
Damjan Marionf56b77a2016-10-03 19:44:57 +020022 @classmethod
23 def setUpClass(cls):
24 super(TestL2xc, cls).setUpClass()
25
Klement Sekeraf62ae122016-10-11 11:47:09 +020026 def setUp(self):
27 super(TestL2xc, self).setUp()
Damjan Marionf56b77a2016-10-03 19:44:57 +020028
Klement Sekeraf62ae122016-10-11 11:47:09 +020029 # create 4 pg interfaces
30 self.create_pg_interfaces(range(4))
Damjan Marionf56b77a2016-10-03 19:44:57 +020031
Klement Sekeraf62ae122016-10-11 11:47:09 +020032 # packet flows mapping pg0 -> pg1, pg2 -> pg3, etc.
33 self.flows = dict()
34 self.flows[self.pg0] = [self.pg1]
35 self.flows[self.pg1] = [self.pg0]
36 self.flows[self.pg2] = [self.pg3]
37 self.flows[self.pg3] = [self.pg2]
Damjan Marionf56b77a2016-10-03 19:44:57 +020038
Klement Sekeraf62ae122016-10-11 11:47:09 +020039 # packet sizes
40 self.pg_if_packet_sizes = [64, 512, 1518, 9018]
Damjan Marionf56b77a2016-10-03 19:44:57 +020041
Klement Sekeraf62ae122016-10-11 11:47:09 +020042 self.interfaces = list(self.pg_interfaces)
Damjan Marionf56b77a2016-10-03 19:44:57 +020043
Klement Sekeraf62ae122016-10-11 11:47:09 +020044 # Create bi-directional cross-connects between pg0 and pg1
45 self.vapi.sw_interface_set_l2_xconnect(
46 self.pg0.sw_if_index, self.pg1.sw_if_index, enable=1)
47 self.vapi.sw_interface_set_l2_xconnect(
48 self.pg1.sw_if_index, self.pg0.sw_if_index, enable=1)
Damjan Marionf56b77a2016-10-03 19:44:57 +020049
Klement Sekeraf62ae122016-10-11 11:47:09 +020050 # Create bi-directional cross-connects between pg2 and pg3
51 self.vapi.sw_interface_set_l2_xconnect(
52 self.pg2.sw_if_index, self.pg3.sw_if_index, enable=1)
53 self.vapi.sw_interface_set_l2_xconnect(
54 self.pg3.sw_if_index, self.pg2.sw_if_index, enable=1)
55
56 info(self.vapi.cli("show l2patch"))
57
58 # mapping between packet-generator index and lists of test hosts
59 self.hosts_by_pg_idx = dict()
60
61 # Create host MAC and IPv4 lists
62 # self.MY_MACS = dict()
63 # self.MY_IP4S = dict()
64 self.create_host_lists(TestL2xc.hosts_nr)
65
66 # setup all interfaces
67 for i in self.interfaces:
68 i.admin_up()
69
Damjan Marionf56b77a2016-10-03 19:44:57 +020070 def tearDown(self):
Klement Sekeraf62ae122016-10-11 11:47:09 +020071 super(TestL2xc, self).tearDown()
72 if not self.vpp_dead:
73 info(self.vapi.cli("show l2patch"))
Damjan Marionf56b77a2016-10-03 19:44:57 +020074
Klement Sekeraf62ae122016-10-11 11:47:09 +020075 def create_host_lists(self, count):
76 """ Method to create required number of MAC and IPv4 addresses.
77 Create required number of host MAC addresses and distribute them among
78 interfaces. Create host IPv4 address for every host MAC address too.
79
80 :param count: Number of hosts to create MAC and IPv4 addresses for.
81 Type: int
82 """
83 for pg_if in self.pg_interfaces:
84 # self.MY_MACS[i.sw_if_index] = []
85 # self.MY_IP4S[i.sw_if_index] = []
86 self.hosts_by_pg_idx[pg_if.sw_if_index] = []
87 hosts = self.hosts_by_pg_idx[pg_if.sw_if_index]
Damjan Marionf56b77a2016-10-03 19:44:57 +020088 for j in range(0, count):
Klement Sekeraf62ae122016-10-11 11:47:09 +020089 host = TestHost(
90 "00:00:00:ff:%02x:%02x" % (pg_if.sw_if_index, j),
91 "172.17.1%02x.%u" % (pg_if.sw_if_index, j))
92 hosts.append(host)
Damjan Marionf56b77a2016-10-03 19:44:57 +020093
Klement Sekeraf62ae122016-10-11 11:47:09 +020094 def create_stream(self, src_if, packet_sizes):
Damjan Marionf56b77a2016-10-03 19:44:57 +020095 pkts = []
96 for i in range(0, TestL2xc.pkts_per_burst):
Klement Sekeraf62ae122016-10-11 11:47:09 +020097 dst_if = self.flows[src_if][0]
98 dst_host = random.choice(self.hosts_by_pg_idx[dst_if.sw_if_index])
99 src_host = random.choice(self.hosts_by_pg_idx[src_if.sw_if_index])
100 pkt_info = self.create_packet_info(
101 src_if.sw_if_index, dst_if.sw_if_index)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200102 payload = self.info_to_payload(pkt_info)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200103 p = (Ether(dst=dst_host.mac, src=src_host.mac) /
104 IP(src=src_host.ip4, dst=dst_host.ip4) /
Damjan Marionf56b77a2016-10-03 19:44:57 +0200105 UDP(sport=1234, dport=1234) /
106 Raw(payload))
107 pkt_info.data = p.copy()
Damjan Marionf56b77a2016-10-03 19:44:57 +0200108 size = packet_sizes[(i / 2) % len(packet_sizes)]
109 self.extend_packet(p, size)
110 pkts.append(p)
111 return pkts
Damjan Marionf56b77a2016-10-03 19:44:57 +0200112
Klement Sekeraf62ae122016-10-11 11:47:09 +0200113 def verify_capture(self, pg_if, capture):
114 last_info = dict()
Damjan Marionf56b77a2016-10-03 19:44:57 +0200115 for i in self.interfaces:
Klement Sekeraf62ae122016-10-11 11:47:09 +0200116 last_info[i.sw_if_index] = None
117 dst_sw_if_index = pg_if.sw_if_index
Damjan Marionf56b77a2016-10-03 19:44:57 +0200118 for packet in capture:
119 try:
120 ip = packet[IP]
121 udp = packet[UDP]
122 payload_info = self.payload_to_info(str(packet[Raw]))
Klement Sekeraf62ae122016-10-11 11:47:09 +0200123 packet_index = payload_info.index
124 self.assertEqual(payload_info.dst, dst_sw_if_index)
125 debug("Got packet on port %s: src=%u (id=%u)" %
126 (pg_if.name, payload_info.src, packet_index))
Damjan Marionf56b77a2016-10-03 19:44:57 +0200127 next_info = self.get_next_packet_info_for_interface2(
Klement Sekeraf62ae122016-10-11 11:47:09 +0200128 payload_info.src, dst_sw_if_index,
Damjan Marionf56b77a2016-10-03 19:44:57 +0200129 last_info[payload_info.src])
130 last_info[payload_info.src] = next_info
131 self.assertTrue(next_info is not None)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200132 self.assertEqual(packet_index, next_info.index)
133 saved_packet = next_info.data
Damjan Marionf56b77a2016-10-03 19:44:57 +0200134 # Check standard fields
Klement Sekeraf62ae122016-10-11 11:47:09 +0200135 self.assertEqual(ip.src, saved_packet[IP].src)
136 self.assertEqual(ip.dst, saved_packet[IP].dst)
137 self.assertEqual(udp.sport, saved_packet[UDP].sport)
138 self.assertEqual(udp.dport, saved_packet[UDP].dport)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200139 except:
Klement Sekeraf62ae122016-10-11 11:47:09 +0200140 error("Unexpected or invalid packet:")
Damjan Marionf56b77a2016-10-03 19:44:57 +0200141 packet.show()
142 raise
143 for i in self.interfaces:
144 remaining_packet = self.get_next_packet_info_for_interface2(
Klement Sekeraf62ae122016-10-11 11:47:09 +0200145 i, dst_sw_if_index, last_info[i.sw_if_index])
Damjan Marionf56b77a2016-10-03 19:44:57 +0200146 self.assertTrue(remaining_packet is None,
147 "Port %u: Packet expected from source %u didn't"
Klement Sekeraf62ae122016-10-11 11:47:09 +0200148 " arrive" % (dst_sw_if_index, i.sw_if_index))
Damjan Marionf56b77a2016-10-03 19:44:57 +0200149
Damjan Marionf56b77a2016-10-03 19:44:57 +0200150 def test_l2xc(self):
151 """ L2XC test
152
153 Test scenario:
154 1.config
155 2 pairs of 2 interfaces, l2xconnected
156
157 2.sending l2 eth packets between 4 interfaces
158 64B, 512B, 1518B, 9018B (ether_size)
159 burst of packets per interface
160 """
161
Klement Sekeraf62ae122016-10-11 11:47:09 +0200162 # Create incoming packet streams for packet-generator interfaces
Damjan Marionf56b77a2016-10-03 19:44:57 +0200163 for i in self.interfaces:
Klement Sekeraf62ae122016-10-11 11:47:09 +0200164 pkts = self.create_stream(i, self.pg_if_packet_sizes)
165 i.add_stream(pkts)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200166
Klement Sekeraf62ae122016-10-11 11:47:09 +0200167 # Enable packet capturing and start packet sending
168 self.pg_enable_capture(self.pg_interfaces)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200169 self.pg_start()
170
Klement Sekeraf62ae122016-10-11 11:47:09 +0200171 # Verify outgoing packet streams per packet-generator interface
172 for i in self.pg_interfaces:
173 capture = i.get_capture()
174 info("Verifying capture on interface %s" % i.name)
175 self.verify_capture(i, capture)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200176
177
178if __name__ == '__main__':
Klement Sekeraf62ae122016-10-11 11:47:09 +0200179 unittest.main(testRunner=VppTestRunner)