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
34 from asfframework import VppTestRunner
35 from vpp_papi import MACAddress
36 from vpp_l2 import L2_PORT_TYPE
39 class TestIpIrb(VppTestCase):
45 #. Create BD with MAC learning enabled and put interfaces to this BD.
46 #. Configure IPv4 addresses on BVI interface and routed interface.
47 #. Configure MAC address binding to IPv4 neighbors on bvi0.
48 #. Configure MAC address on pg2.
49 #. BVI interface has remote hosts, one half of hosts are
50 behind pg0 second behind pg1.
52 super(TestIpIrb, cls).setUpClass()
54 cls.pg_if_packet_sizes = [64, 512, 1518, 9018] # packet sizes
56 cls.remote_hosts_count = 250
58 # create 3 pg interfaces, 1 BVI interface
59 cls.create_pg_interfaces(range(3))
60 cls.create_bvi_interfaces(1)
62 cls.interfaces = list(cls.pg_interfaces)
63 cls.interfaces.extend(cls.bvi_interfaces)
65 for i in cls.interfaces:
68 # Create BD with MAC learning enabled and put interfaces to this BD
69 cls.vapi.sw_interface_set_l2_bridge(
70 rx_sw_if_index=cls.bvi0.sw_if_index,
72 port_type=L2_PORT_TYPE.BVI,
74 cls.vapi.sw_interface_set_l2_bridge(
75 rx_sw_if_index=cls.pg0.sw_if_index, bd_id=cls.bd_id
77 cls.vapi.sw_interface_set_l2_bridge(
78 rx_sw_if_index=cls.pg1.sw_if_index, bd_id=cls.bd_id
81 # Configure IPv4 addresses on BVI interface and routed interface
85 # Configure MAC address binding to IPv4 neighbors on bvi0
86 cls.bvi0.generate_remote_hosts(cls.remote_hosts_count)
87 cls.bvi0.configure_ipv4_neighbors()
88 # configure MAC address on pg2
91 # BVI interface has remote hosts, one half of hosts are behind
92 # pg0 second behind pg1
93 half = cls.remote_hosts_count // 2
94 cls.pg0.remote_hosts = cls.bvi0.remote_hosts[:half]
95 cls.pg1.remote_hosts = cls.bvi0.remote_hosts[half:]
98 def tearDownClass(cls):
99 super(TestIpIrb, cls).tearDownClass()
102 """Run standard test teardown and log ``show l2patch``,
103 ``show l2fib verbose``,``show bridge-domain <bd_id> detail``,
104 ``show ip neighbors``.
106 super(TestIpIrb, self).tearDown()
108 def show_commands_at_teardown(self):
109 self.logger.info(self.vapi.cli("show l2patch"))
110 self.logger.info(self.vapi.cli("show l2fib verbose"))
111 self.logger.info(self.vapi.cli("show bridge-domain %s detail" % self.bd_id))
112 self.logger.info(self.vapi.cli("show ip neighbors"))
114 def create_stream(self, src_ip_if, dst_ip_if, packet_sizes):
116 for i in range(0, 257):
117 remote_dst_host = choice(dst_ip_if.remote_hosts)
118 info = self.create_packet_info(src_ip_if, dst_ip_if)
119 payload = self.info_to_payload(info)
121 Ether(dst=src_ip_if.local_mac, src=src_ip_if.remote_mac)
122 / IP(src=src_ip_if.remote_ip4, dst=remote_dst_host.ip4)
123 / UDP(sport=1234, dport=1234)
127 size = packet_sizes[(i // 2) % len(packet_sizes)]
128 self.extend_packet(p, size)
132 def create_stream_l2_to_ip(self, src_l2_if, src_ip_if, dst_ip_if, packet_sizes):
134 for i in range(0, 257):
135 info = self.create_packet_info(src_ip_if, dst_ip_if)
136 payload = self.info_to_payload(info)
138 host = choice(src_l2_if.remote_hosts)
141 Ether(src=host.mac, dst=src_ip_if.local_mac)
142 / IP(src=host.ip4, dst=dst_ip_if.remote_ip4)
143 / UDP(sport=1234, dport=1234)
148 size = packet_sizes[(i // 2) % len(packet_sizes)]
149 self.extend_packet(p, size)
154 def verify_capture_l2_to_ip(self, dst_ip_if, src_ip_if, capture):
156 for i in self.interfaces:
157 last_info[i.sw_if_index] = None
159 dst_ip_sw_if_index = dst_ip_if.sw_if_index
161 for packet in capture:
163 udp = packet[IP][UDP]
164 payload_info = self.payload_to_info(packet[IP][UDP][Raw])
166 self.assertEqual(payload_info.dst, dst_ip_sw_if_index)
168 next_info = self.get_next_packet_info_for_interface2(
169 payload_info.src, dst_ip_sw_if_index, last_info[payload_info.src]
171 last_info[payload_info.src] = next_info
172 self.assertTrue(next_info is not None)
173 saved_packet = next_info.data
174 self.assertTrue(next_info is not None)
177 self.assertEqual(packet.src, dst_ip_if.local_mac)
178 self.assertEqual(packet.dst, dst_ip_if.remote_mac)
181 host = src_ip_if.host_by_ip4(ip.src)
182 self.assertIsNotNone(host)
183 self.assertEqual(ip.dst, saved_packet[IP].dst)
184 self.assertEqual(ip.dst, dst_ip_if.remote_ip4)
187 self.assertEqual(udp.sport, saved_packet[UDP].sport)
188 self.assertEqual(udp.dport, saved_packet[UDP].dport)
190 def verify_capture(self, dst_ip_if, src_ip_if, capture):
192 for i in self.interfaces:
193 last_info[i.sw_if_index] = None
195 dst_ip_sw_if_index = dst_ip_if.sw_if_index
197 for packet in capture:
199 udp = packet[IP][UDP]
200 payload_info = self.payload_to_info(packet[IP][UDP][Raw])
201 packet_index = payload_info.index
203 self.assertEqual(payload_info.dst, dst_ip_sw_if_index)
205 next_info = self.get_next_packet_info_for_interface2(
206 payload_info.src, dst_ip_sw_if_index, last_info[payload_info.src]
208 last_info[payload_info.src] = next_info
209 self.assertTrue(next_info is not None)
210 self.assertEqual(packet_index, next_info.index)
211 saved_packet = next_info.data
212 self.assertTrue(next_info is not None)
215 self.assertEqual(packet.src, dst_ip_if.local_mac)
216 host = dst_ip_if.host_by_mac(packet.dst)
219 self.assertEqual(ip.src, src_ip_if.remote_ip4)
220 self.assertEqual(ip.dst, saved_packet[IP].dst)
221 self.assertEqual(ip.dst, host.ip4)
224 self.assertEqual(udp.sport, saved_packet[UDP].sport)
225 self.assertEqual(udp.dport, saved_packet[UDP].dport)
227 def test_ip4_irb_1(self):
231 - ip traffic from pg2 interface must ends in both pg0 and pg1
232 - arp entry present in bvi0 interface for destination IP
233 - no l2 entry configured, pg0 and pg1 are same
236 stream = self.create_stream(self.pg2, self.bvi0, self.pg_if_packet_sizes)
237 self.pg2.add_stream(stream)
239 self.pg_enable_capture(self.pg_interfaces)
242 packet_count = self.get_packet_count_for_if_idx(self.bvi0.sw_if_index)
244 rcvd1 = self.pg0.get_capture(packet_count)
245 rcvd2 = self.pg1.get_capture(packet_count)
247 self.verify_capture(self.bvi0, self.pg2, rcvd1)
248 self.verify_capture(self.bvi0, self.pg2, rcvd2)
250 self.assertListEqual(rcvd1.res, rcvd2.res)
252 def send_and_verify_l2_to_ip(self):
253 stream1 = self.create_stream_l2_to_ip(
254 self.pg0, self.bvi0, self.pg2, self.pg_if_packet_sizes
256 stream2 = self.create_stream_l2_to_ip(
257 self.pg1, self.bvi0, self.pg2, self.pg_if_packet_sizes
259 self.vapi.cli("clear trace")
260 self.pg0.add_stream(stream1)
261 self.pg1.add_stream(stream2)
263 self.pg_enable_capture(self.pg_interfaces)
266 rcvd = self.pg2.get_capture(514)
267 self.verify_capture_l2_to_ip(self.pg2, self.bvi0, rcvd)
269 def test_ip4_irb_2(self):
273 - ip traffic from pg0 and pg1 ends on pg2
275 self.send_and_verify_l2_to_ip()
277 # change the BVI's mac and resed traffic
278 self.bvi0.set_mac(MACAddress("00:00:00:11:11:33"))
280 self.send_and_verify_l2_to_ip()
281 # check it wasn't flooded
282 self.pg1.assert_nothing_captured(remark="UU Flood")
285 if __name__ == "__main__":
286 unittest.main(testRunner=VppTestRunner)