5 - L2 MAC learning enabled in l2bd
6 - 2 routed interfaces untagged, bvi (Bridge Virtual Interface)
7 - 2 bridged interfaces in l2bd with bvi
10 - sending ip4 eth pkts between routed interfaces
12 - 2 bridged interfaces
14 - 64B, 512B, 1518B, 9200B (ether_size)
16 - burst of pkts per interface
18 - routed pkts hitting different FIB entries
19 - bridged pkts hitting different MAC entries
22 - all packets received correctly
27 from random import choice
29 from scapy.packet import Raw
30 from scapy.layers.l2 import Ether
31 from scapy.layers.inet import IP, UDP
33 from framework import VppTestCase, VppTestRunner
34 from vpp_papi import MACAddress
35 from vpp_l2 import L2_PORT_TYPE
38 class TestIpIrb(VppTestCase):
44 #. Create BD with MAC learning enabled and put interfaces to this BD.
45 #. Configure IPv4 addresses on BVI interface and routed interface.
46 #. Configure MAC address binding to IPv4 neighbors on bvi0.
47 #. Configure MAC address on pg2.
48 #. BVI interface has remote hosts, one half of hosts are
49 behind pg0 second behind pg1.
51 super(TestIpIrb, cls).setUpClass()
53 cls.pg_if_packet_sizes = [64, 512, 1518, 9018] # packet sizes
55 cls.remote_hosts_count = 250
57 # create 3 pg interfaces, 1 BVI interface
58 cls.create_pg_interfaces(range(3))
59 cls.create_bvi_interfaces(1)
61 cls.interfaces = list(cls.pg_interfaces)
62 cls.interfaces.extend(cls.bvi_interfaces)
64 for i in cls.interfaces:
67 # Create BD with MAC learning enabled and put interfaces to this BD
68 cls.vapi.sw_interface_set_l2_bridge(
69 rx_sw_if_index=cls.bvi0.sw_if_index,
71 port_type=L2_PORT_TYPE.BVI,
73 cls.vapi.sw_interface_set_l2_bridge(
74 rx_sw_if_index=cls.pg0.sw_if_index, bd_id=cls.bd_id
76 cls.vapi.sw_interface_set_l2_bridge(
77 rx_sw_if_index=cls.pg1.sw_if_index, bd_id=cls.bd_id
80 # Configure IPv4 addresses on BVI interface and routed interface
84 # Configure MAC address binding to IPv4 neighbors on bvi0
85 cls.bvi0.generate_remote_hosts(cls.remote_hosts_count)
86 cls.bvi0.configure_ipv4_neighbors()
87 # configure MAC address on pg2
90 # BVI interface has remote hosts, one half of hosts are behind
91 # pg0 second behind pg1
92 half = cls.remote_hosts_count // 2
93 cls.pg0.remote_hosts = cls.bvi0.remote_hosts[:half]
94 cls.pg1.remote_hosts = cls.bvi0.remote_hosts[half:]
97 def tearDownClass(cls):
98 super(TestIpIrb, cls).tearDownClass()
101 """Run standard test teardown and log ``show l2patch``,
102 ``show l2fib verbose``,``show bridge-domain <bd_id> detail``,
103 ``show ip neighbors``.
105 super(TestIpIrb, self).tearDown()
107 def show_commands_at_teardown(self):
108 self.logger.info(self.vapi.cli("show l2patch"))
109 self.logger.info(self.vapi.cli("show l2fib verbose"))
110 self.logger.info(self.vapi.cli("show bridge-domain %s detail" % self.bd_id))
111 self.logger.info(self.vapi.cli("show ip neighbors"))
113 def create_stream(self, src_ip_if, dst_ip_if, packet_sizes):
115 for i in range(0, 257):
116 remote_dst_host = choice(dst_ip_if.remote_hosts)
117 info = self.create_packet_info(src_ip_if, dst_ip_if)
118 payload = self.info_to_payload(info)
120 Ether(dst=src_ip_if.local_mac, src=src_ip_if.remote_mac)
121 / IP(src=src_ip_if.remote_ip4, dst=remote_dst_host.ip4)
122 / UDP(sport=1234, dport=1234)
126 size = packet_sizes[(i // 2) % len(packet_sizes)]
127 self.extend_packet(p, size)
131 def create_stream_l2_to_ip(self, src_l2_if, src_ip_if, dst_ip_if, packet_sizes):
133 for i in range(0, 257):
134 info = self.create_packet_info(src_ip_if, dst_ip_if)
135 payload = self.info_to_payload(info)
137 host = choice(src_l2_if.remote_hosts)
140 Ether(src=host.mac, dst=src_ip_if.local_mac)
141 / IP(src=host.ip4, dst=dst_ip_if.remote_ip4)
142 / UDP(sport=1234, dport=1234)
147 size = packet_sizes[(i // 2) % len(packet_sizes)]
148 self.extend_packet(p, size)
153 def verify_capture_l2_to_ip(self, dst_ip_if, src_ip_if, capture):
155 for i in self.interfaces:
156 last_info[i.sw_if_index] = None
158 dst_ip_sw_if_index = dst_ip_if.sw_if_index
160 for packet in capture:
162 udp = packet[IP][UDP]
163 payload_info = self.payload_to_info(packet[IP][UDP][Raw])
165 self.assertEqual(payload_info.dst, dst_ip_sw_if_index)
167 next_info = self.get_next_packet_info_for_interface2(
168 payload_info.src, dst_ip_sw_if_index, last_info[payload_info.src]
170 last_info[payload_info.src] = next_info
171 self.assertTrue(next_info is not None)
172 saved_packet = next_info.data
173 self.assertTrue(next_info is not None)
176 self.assertEqual(packet.src, dst_ip_if.local_mac)
177 self.assertEqual(packet.dst, dst_ip_if.remote_mac)
180 host = src_ip_if.host_by_ip4(ip.src)
181 self.assertIsNotNone(host)
182 self.assertEqual(ip.dst, saved_packet[IP].dst)
183 self.assertEqual(ip.dst, dst_ip_if.remote_ip4)
186 self.assertEqual(udp.sport, saved_packet[UDP].sport)
187 self.assertEqual(udp.dport, saved_packet[UDP].dport)
189 def verify_capture(self, dst_ip_if, src_ip_if, capture):
191 for i in self.interfaces:
192 last_info[i.sw_if_index] = None
194 dst_ip_sw_if_index = dst_ip_if.sw_if_index
196 for packet in capture:
198 udp = packet[IP][UDP]
199 payload_info = self.payload_to_info(packet[IP][UDP][Raw])
200 packet_index = payload_info.index
202 self.assertEqual(payload_info.dst, dst_ip_sw_if_index)
204 next_info = self.get_next_packet_info_for_interface2(
205 payload_info.src, dst_ip_sw_if_index, last_info[payload_info.src]
207 last_info[payload_info.src] = next_info
208 self.assertTrue(next_info is not None)
209 self.assertEqual(packet_index, next_info.index)
210 saved_packet = next_info.data
211 self.assertTrue(next_info is not None)
214 self.assertEqual(packet.src, dst_ip_if.local_mac)
215 host = dst_ip_if.host_by_mac(packet.dst)
218 self.assertEqual(ip.src, src_ip_if.remote_ip4)
219 self.assertEqual(ip.dst, saved_packet[IP].dst)
220 self.assertEqual(ip.dst, host.ip4)
223 self.assertEqual(udp.sport, saved_packet[UDP].sport)
224 self.assertEqual(udp.dport, saved_packet[UDP].dport)
226 def test_ip4_irb_1(self):
230 - ip traffic from pg2 interface must ends in both pg0 and pg1
231 - arp entry present in bvi0 interface for destination IP
232 - no l2 entry configured, pg0 and pg1 are same
235 stream = self.create_stream(self.pg2, self.bvi0, self.pg_if_packet_sizes)
236 self.pg2.add_stream(stream)
238 self.pg_enable_capture(self.pg_interfaces)
241 packet_count = self.get_packet_count_for_if_idx(self.bvi0.sw_if_index)
243 rcvd1 = self.pg0.get_capture(packet_count)
244 rcvd2 = self.pg1.get_capture(packet_count)
246 self.verify_capture(self.bvi0, self.pg2, rcvd1)
247 self.verify_capture(self.bvi0, self.pg2, rcvd2)
249 self.assertListEqual(rcvd1.res, rcvd2.res)
251 def send_and_verify_l2_to_ip(self):
252 stream1 = self.create_stream_l2_to_ip(
253 self.pg0, self.bvi0, self.pg2, self.pg_if_packet_sizes
255 stream2 = self.create_stream_l2_to_ip(
256 self.pg1, self.bvi0, self.pg2, self.pg_if_packet_sizes
258 self.vapi.cli("clear trace")
259 self.pg0.add_stream(stream1)
260 self.pg1.add_stream(stream2)
262 self.pg_enable_capture(self.pg_interfaces)
265 rcvd = self.pg2.get_capture(514)
266 self.verify_capture_l2_to_ip(self.pg2, self.bvi0, rcvd)
268 def test_ip4_irb_2(self):
272 - ip traffic from pg0 and pg1 ends on pg2
274 self.send_and_verify_l2_to_ip()
276 # change the BVI's mac and resed traffic
277 self.bvi0.set_mac(MACAddress("00:00:00:11:11:33"))
279 self.send_and_verify_l2_to_ip()
280 # check it wasn't flooded
281 self.pg1.assert_nothing_captured(remark="UU Flood")
284 if __name__ == "__main__":
285 unittest.main(testRunner=VppTestRunner)