blob: 35c7a818414a38d61e1fe5db77f98439cf2a6e1a [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.
Klement Sekeraf62ae122016-10-11 11:47:09 +020081 """
82 for pg_if in self.pg_interfaces:
83 # self.MY_MACS[i.sw_if_index] = []
84 # self.MY_IP4S[i.sw_if_index] = []
85 self.hosts_by_pg_idx[pg_if.sw_if_index] = []
86 hosts = self.hosts_by_pg_idx[pg_if.sw_if_index]
Damjan Marionf56b77a2016-10-03 19:44:57 +020087 for j in range(0, count):
Klement Sekeraf62ae122016-10-11 11:47:09 +020088 host = TestHost(
89 "00:00:00:ff:%02x:%02x" % (pg_if.sw_if_index, j),
90 "172.17.1%02x.%u" % (pg_if.sw_if_index, j))
91 hosts.append(host)
Damjan Marionf56b77a2016-10-03 19:44:57 +020092
Klement Sekeraf62ae122016-10-11 11:47:09 +020093 def create_stream(self, src_if, packet_sizes):
Damjan Marionf56b77a2016-10-03 19:44:57 +020094 pkts = []
95 for i in range(0, TestL2xc.pkts_per_burst):
Klement Sekeraf62ae122016-10-11 11:47:09 +020096 dst_if = self.flows[src_if][0]
97 dst_host = random.choice(self.hosts_by_pg_idx[dst_if.sw_if_index])
98 src_host = random.choice(self.hosts_by_pg_idx[src_if.sw_if_index])
99 pkt_info = self.create_packet_info(
100 src_if.sw_if_index, dst_if.sw_if_index)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200101 payload = self.info_to_payload(pkt_info)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200102 p = (Ether(dst=dst_host.mac, src=src_host.mac) /
103 IP(src=src_host.ip4, dst=dst_host.ip4) /
Damjan Marionf56b77a2016-10-03 19:44:57 +0200104 UDP(sport=1234, dport=1234) /
105 Raw(payload))
106 pkt_info.data = p.copy()
Damjan Marionf56b77a2016-10-03 19:44:57 +0200107 size = packet_sizes[(i / 2) % len(packet_sizes)]
108 self.extend_packet(p, size)
109 pkts.append(p)
110 return pkts
Damjan Marionf56b77a2016-10-03 19:44:57 +0200111
Klement Sekeraf62ae122016-10-11 11:47:09 +0200112 def verify_capture(self, pg_if, capture):
113 last_info = dict()
Damjan Marionf56b77a2016-10-03 19:44:57 +0200114 for i in self.interfaces:
Klement Sekeraf62ae122016-10-11 11:47:09 +0200115 last_info[i.sw_if_index] = None
116 dst_sw_if_index = pg_if.sw_if_index
Damjan Marionf56b77a2016-10-03 19:44:57 +0200117 for packet in capture:
118 try:
119 ip = packet[IP]
120 udp = packet[UDP]
121 payload_info = self.payload_to_info(str(packet[Raw]))
Klement Sekeraf62ae122016-10-11 11:47:09 +0200122 packet_index = payload_info.index
123 self.assertEqual(payload_info.dst, dst_sw_if_index)
124 debug("Got packet on port %s: src=%u (id=%u)" %
125 (pg_if.name, payload_info.src, packet_index))
Damjan Marionf56b77a2016-10-03 19:44:57 +0200126 next_info = self.get_next_packet_info_for_interface2(
Klement Sekeraf62ae122016-10-11 11:47:09 +0200127 payload_info.src, dst_sw_if_index,
Damjan Marionf56b77a2016-10-03 19:44:57 +0200128 last_info[payload_info.src])
129 last_info[payload_info.src] = next_info
130 self.assertTrue(next_info is not None)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200131 self.assertEqual(packet_index, next_info.index)
132 saved_packet = next_info.data
Damjan Marionf56b77a2016-10-03 19:44:57 +0200133 # Check standard fields
Klement Sekeraf62ae122016-10-11 11:47:09 +0200134 self.assertEqual(ip.src, saved_packet[IP].src)
135 self.assertEqual(ip.dst, saved_packet[IP].dst)
136 self.assertEqual(udp.sport, saved_packet[UDP].sport)
137 self.assertEqual(udp.dport, saved_packet[UDP].dport)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200138 except:
Klement Sekeraf62ae122016-10-11 11:47:09 +0200139 error("Unexpected or invalid packet:")
Damjan Marionf56b77a2016-10-03 19:44:57 +0200140 packet.show()
141 raise
142 for i in self.interfaces:
143 remaining_packet = self.get_next_packet_info_for_interface2(
Klement Sekeraf62ae122016-10-11 11:47:09 +0200144 i, dst_sw_if_index, last_info[i.sw_if_index])
Damjan Marionf56b77a2016-10-03 19:44:57 +0200145 self.assertTrue(remaining_packet is None,
146 "Port %u: Packet expected from source %u didn't"
Klement Sekeraf62ae122016-10-11 11:47:09 +0200147 " arrive" % (dst_sw_if_index, i.sw_if_index))
Damjan Marionf56b77a2016-10-03 19:44:57 +0200148
Damjan Marionf56b77a2016-10-03 19:44:57 +0200149 def test_l2xc(self):
150 """ L2XC test
151
152 Test scenario:
Klement Sekera277b89c2016-10-28 13:20:27 +0200153 1. config
154 2 pairs of 2 interfaces, l2xconnected
155 2. sending l2 eth packets between 4 interfaces
156 64B, 512B, 1518B, 9018B (ether_size)
157 burst of packets per interface
Damjan Marionf56b77a2016-10-03 19:44:57 +0200158 """
159
Klement Sekeraf62ae122016-10-11 11:47:09 +0200160 # Create incoming packet streams for packet-generator interfaces
Damjan Marionf56b77a2016-10-03 19:44:57 +0200161 for i in self.interfaces:
Klement Sekeraf62ae122016-10-11 11:47:09 +0200162 pkts = self.create_stream(i, self.pg_if_packet_sizes)
163 i.add_stream(pkts)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200164
Klement Sekeraf62ae122016-10-11 11:47:09 +0200165 # Enable packet capturing and start packet sending
166 self.pg_enable_capture(self.pg_interfaces)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200167 self.pg_start()
168
Klement Sekeraf62ae122016-10-11 11:47:09 +0200169 # Verify outgoing packet streams per packet-generator interface
170 for i in self.pg_interfaces:
171 capture = i.get_capture()
172 info("Verifying capture on interface %s" % i.name)
173 self.verify_capture(i, capture)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200174
175
176if __name__ == '__main__':
Klement Sekeraf62ae122016-10-11 11:47:09 +0200177 unittest.main(testRunner=VppTestRunner)