blob: 831685150a2f6799efb929b983556593e81a92d5 [file] [log] [blame]
Damjan Marionf56b77a2016-10-03 19:44:57 +02001#!/usr/bin/env python
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -08002import binascii
Matej Klotton16a14cd2016-12-07 15:09:13 +01003import random
Klement Sekeraf62ae122016-10-11 11:47:09 +02004import socket
Matej Klotton16a14cd2016-12-07 15:09:13 +01005import unittest
Klement Sekeraf62ae122016-10-11 11:47:09 +02006
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07007import scapy.compat
Paul Vinciguerraa6fe4632018-11-25 11:21:50 -08008from scapy.contrib.mpls import MPLS
9from scapy.layers.inet import IP, UDP, TCP, ICMP, icmptypes, icmpcodes
10from scapy.layers.l2 import Ether, Dot1Q, ARP
11from scapy.packet import Raw
12from six import moves
13
Damjan Marionf56b77a2016-10-03 19:44:57 +020014from framework import VppTestCase, VppTestRunner
Paul Vinciguerraa6fe4632018-11-25 11:21:50 -080015from util import ppp
Jakub Grajciar053204a2019-03-18 13:17:53 +010016from vpp_ip import VppIpPrefix
Neale Ranns180279b2017-03-16 15:49:09 -040017from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpMRoute, \
Neale Ranns15002542017-09-10 04:39:11 -070018 VppMRoutePath, MRouteItfFlags, MRouteEntryFlags, VppMplsIpBind, \
Matthew Smith6c92f5b2019-08-07 11:46:30 -050019 VppMplsTable, VppIpTable, FibPathType, find_route, \
20 VppIpInterfaceAddress
21from vpp_ip import VppIpAddress
Paul Vinciguerraa6fe4632018-11-25 11:21:50 -080022from vpp_sub_interface import VppSubInterface, VppDot1QSubint, VppDot1ADSubint
Neale Ranns68577d22019-06-04 13:31:23 +000023from vpp_papi import VppEnum
Damjan Marionf56b77a2016-10-03 19:44:57 +020024
Paul Vinciguerra4271c972019-05-14 13:25:49 -040025NUM_PKTS = 67
26
Damjan Marionf56b77a2016-10-03 19:44:57 +020027
Klement Sekeraf62ae122016-10-11 11:47:09 +020028class TestIPv4(VppTestCase):
Damjan Marionf56b77a2016-10-03 19:44:57 +020029 """ IPv4 Test Case """
30
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070031 @classmethod
32 def setUpClass(cls):
33 super(TestIPv4, cls).setUpClass()
34
35 @classmethod
36 def tearDownClass(cls):
37 super(TestIPv4, cls).tearDownClass()
38
Klement Sekeraf62ae122016-10-11 11:47:09 +020039 def setUp(self):
Matej Klotton86d87c42016-11-11 11:38:55 +010040 """
41 Perform test setup before test case.
42
43 **Config:**
44 - create 3 pg interfaces
45 - untagged pg0 interface
46 - Dot1Q subinterface on pg1
47 - Dot1AD subinterface on pg2
48 - setup interfaces:
49 - put it into UP state
50 - set IPv4 addresses
51 - resolve neighbor address using ARP
52 - configure 200 fib entries
53
54 :ivar list interfaces: pg interfaces and subinterfaces.
55 :ivar dict flows: IPv4 packet flows in test.
Matej Klotton86d87c42016-11-11 11:38:55 +010056 """
Klement Sekeraf62ae122016-10-11 11:47:09 +020057 super(TestIPv4, self).setUp()
Damjan Marionf56b77a2016-10-03 19:44:57 +020058
Klement Sekeraf62ae122016-10-11 11:47:09 +020059 # create 3 pg interfaces
60 self.create_pg_interfaces(range(3))
Damjan Marionf56b77a2016-10-03 19:44:57 +020061
Klement Sekeraf62ae122016-10-11 11:47:09 +020062 # create 2 subinterfaces for pg1 and pg2
63 self.sub_interfaces = [
64 VppDot1QSubint(self, self.pg1, 100),
65 VppDot1ADSubint(self, self.pg2, 200, 300, 400)]
Damjan Marionf56b77a2016-10-03 19:44:57 +020066
Klement Sekeraf62ae122016-10-11 11:47:09 +020067 # packet flows mapping pg0 -> pg1.sub, pg2.sub, etc.
68 self.flows = dict()
69 self.flows[self.pg0] = [self.pg1.sub_if, self.pg2.sub_if]
70 self.flows[self.pg1.sub_if] = [self.pg0, self.pg2.sub_if]
71 self.flows[self.pg2.sub_if] = [self.pg0, self.pg1.sub_if]
Damjan Marionf56b77a2016-10-03 19:44:57 +020072
Klement Sekeraf62ae122016-10-11 11:47:09 +020073 # packet sizes
Jan Geletye6c78ee2018-06-26 12:24:03 +020074 self.pg_if_packet_sizes = [64, 1500, 9020]
Damjan Marionf56b77a2016-10-03 19:44:57 +020075
Klement Sekeraf62ae122016-10-11 11:47:09 +020076 self.interfaces = list(self.pg_interfaces)
77 self.interfaces.extend(self.sub_interfaces)
Damjan Marionf56b77a2016-10-03 19:44:57 +020078
Klement Sekeraf62ae122016-10-11 11:47:09 +020079 # setup all interfaces
80 for i in self.interfaces:
81 i.admin_up()
82 i.config_ip4()
83 i.resolve_arp()
84
Matej Klotton86d87c42016-11-11 11:38:55 +010085 # config 2M FIB entries
Damjan Marionf56b77a2016-10-03 19:44:57 +020086
87 def tearDown(self):
Matej Klotton86d87c42016-11-11 11:38:55 +010088 """Run standard test teardown and log ``show ip arp``."""
Klement Sekeraf62ae122016-10-11 11:47:09 +020089 super(TestIPv4, self).tearDown()
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -070090
91 def show_commands_at_teardown(self):
92 self.logger.info(self.vapi.cli("show ip arp"))
93 # info(self.vapi.cli("show ip fib")) # many entries
Damjan Marionf56b77a2016-10-03 19:44:57 +020094
Jan Geletye6c78ee2018-06-26 12:24:03 +020095 def modify_packet(self, src_if, packet_size, pkt):
96 """Add load, set destination IP and extend packet to required packet
97 size for defined interface.
98
99 :param VppInterface src_if: Interface to create packet for.
100 :param int packet_size: Required packet size.
101 :param Scapy pkt: Packet to be modified.
102 """
Ole Troan6ed154f2019-10-15 19:31:55 +0200103 dst_if_idx = int(packet_size / 10 % 2)
Jan Geletye6c78ee2018-06-26 12:24:03 +0200104 dst_if = self.flows[src_if][dst_if_idx]
105 info = self.create_packet_info(src_if, dst_if)
106 payload = self.info_to_payload(info)
107 p = pkt/Raw(payload)
108 p[IP].dst = dst_if.remote_ip4
109 info.data = p.copy()
110 if isinstance(src_if, VppSubInterface):
111 p = src_if.add_dot1_layer(p)
112 self.extend_packet(p, packet_size)
113
114 return p
115
116 def create_stream(self, src_if):
Matej Klotton86d87c42016-11-11 11:38:55 +0100117 """Create input packet stream for defined interface.
118
119 :param VppInterface src_if: Interface to create packet stream for.
Matej Klotton86d87c42016-11-11 11:38:55 +0100120 """
Jan Geletye6c78ee2018-06-26 12:24:03 +0200121 hdr_ext = 4 if isinstance(src_if, VppSubInterface) else 0
122 pkt_tmpl = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
123 IP(src=src_if.remote_ip4) /
124 UDP(sport=1234, dport=1234))
125
126 pkts = [self.modify_packet(src_if, i, pkt_tmpl)
Paul Vinciguerraa6fe4632018-11-25 11:21:50 -0800127 for i in moves.range(self.pg_if_packet_sizes[0],
128 self.pg_if_packet_sizes[1], 10)]
Jan Geletye6c78ee2018-06-26 12:24:03 +0200129 pkts_b = [self.modify_packet(src_if, i, pkt_tmpl)
Paul Vinciguerraa6fe4632018-11-25 11:21:50 -0800130 for i in moves.range(self.pg_if_packet_sizes[1] + hdr_ext,
131 self.pg_if_packet_sizes[2] + hdr_ext,
132 50)]
Jan Geletye6c78ee2018-06-26 12:24:03 +0200133 pkts.extend(pkts_b)
134
Damjan Marionf56b77a2016-10-03 19:44:57 +0200135 return pkts
136
Klement Sekeraf62ae122016-10-11 11:47:09 +0200137 def verify_capture(self, dst_if, capture):
Matej Klotton86d87c42016-11-11 11:38:55 +0100138 """Verify captured input packet stream for defined interface.
139
140 :param VppInterface dst_if: Interface to verify captured packet stream
Jan Geletye6c78ee2018-06-26 12:24:03 +0200141 for.
Matej Klotton86d87c42016-11-11 11:38:55 +0100142 :param list capture: Captured packet stream.
143 """
144 self.logger.info("Verifying capture on interface %s" % dst_if.name)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200145 last_info = dict()
Damjan Marionf56b77a2016-10-03 19:44:57 +0200146 for i in self.interfaces:
Klement Sekeraf62ae122016-10-11 11:47:09 +0200147 last_info[i.sw_if_index] = None
148 is_sub_if = False
149 dst_sw_if_index = dst_if.sw_if_index
150 if hasattr(dst_if, 'parent'):
151 is_sub_if = True
Damjan Marionf56b77a2016-10-03 19:44:57 +0200152 for packet in capture:
Klement Sekeraf62ae122016-10-11 11:47:09 +0200153 if is_sub_if:
154 # Check VLAN tags and Ethernet header
155 packet = dst_if.remove_dot1_layer(packet)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200156 self.assertTrue(Dot1Q not in packet)
157 try:
158 ip = packet[IP]
159 udp = packet[UDP]
Paul Vinciguerraeaea4212019-03-06 11:58:06 -0800160 payload_info = self.payload_to_info(packet[Raw])
Damjan Marionf56b77a2016-10-03 19:44:57 +0200161 packet_index = payload_info.index
Klement Sekeraf62ae122016-10-11 11:47:09 +0200162 self.assertEqual(payload_info.dst, dst_sw_if_index)
Klement Sekerada505f62017-01-04 12:58:53 +0100163 self.logger.debug(
164 "Got packet on port %s: src=%u (id=%u)" %
165 (dst_if.name, payload_info.src, packet_index))
Klement Sekeraf62ae122016-10-11 11:47:09 +0200166 next_info = self.get_next_packet_info_for_interface2(
167 payload_info.src, dst_sw_if_index,
168 last_info[payload_info.src])
169 last_info[payload_info.src] = next_info
Damjan Marionf56b77a2016-10-03 19:44:57 +0200170 self.assertTrue(next_info is not None)
171 self.assertEqual(packet_index, next_info.index)
172 saved_packet = next_info.data
173 # Check standard fields
174 self.assertEqual(ip.src, saved_packet[IP].src)
175 self.assertEqual(ip.dst, saved_packet[IP].dst)
176 self.assertEqual(udp.sport, saved_packet[UDP].sport)
177 self.assertEqual(udp.dport, saved_packet[UDP].dport)
178 except:
Klement Sekera7bb873a2016-11-18 07:38:42 +0100179 self.logger.error(ppp("Unexpected or invalid packet:", packet))
Damjan Marionf56b77a2016-10-03 19:44:57 +0200180 raise
181 for i in self.interfaces:
Klement Sekeraf62ae122016-10-11 11:47:09 +0200182 remaining_packet = self.get_next_packet_info_for_interface2(
183 i.sw_if_index, dst_sw_if_index, last_info[i.sw_if_index])
Klement Sekera7bb873a2016-11-18 07:38:42 +0100184 self.assertTrue(remaining_packet is None,
185 "Interface %s: Packet expected from interface %s "
186 "didn't arrive" % (dst_if.name, i.name))
Damjan Marionf56b77a2016-10-03 19:44:57 +0200187
188 def test_fib(self):
Matej Klotton86d87c42016-11-11 11:38:55 +0100189 """ IPv4 FIB test
190
191 Test scenario:
192
193 - Create IPv4 stream for pg0 interface
Jan Geletye6c78ee2018-06-26 12:24:03 +0200194 - Create IPv4 tagged streams for pg1's and pg2's sub-interface.
Matej Klotton86d87c42016-11-11 11:38:55 +0100195 - Send and verify received packets on each interface.
196 """
Damjan Marionf56b77a2016-10-03 19:44:57 +0200197
Jan Geletye6c78ee2018-06-26 12:24:03 +0200198 pkts = self.create_stream(self.pg0)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200199 self.pg0.add_stream(pkts)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200200
Klement Sekeraf62ae122016-10-11 11:47:09 +0200201 for i in self.sub_interfaces:
Jan Geletye6c78ee2018-06-26 12:24:03 +0200202 pkts = self.create_stream(i)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200203 i.parent.add_stream(pkts)
204
205 self.pg_enable_capture(self.pg_interfaces)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200206 self.pg_start()
207
Klement Sekeraf62ae122016-10-11 11:47:09 +0200208 pkts = self.pg0.get_capture()
209 self.verify_capture(self.pg0, pkts)
210
211 for i in self.sub_interfaces:
212 pkts = i.parent.get_capture()
213 self.verify_capture(i, pkts)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200214
215
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500216class TestIPv4IfAddrRoute(VppTestCase):
Matthew G Smith88d29a92019-07-17 10:01:17 -0500217 """ IPv4 Interface Addr Route Test Case """
218
219 @classmethod
220 def setUpClass(cls):
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500221 super(TestIPv4IfAddrRoute, cls).setUpClass()
Matthew G Smith88d29a92019-07-17 10:01:17 -0500222
223 @classmethod
224 def tearDownClass(cls):
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500225 super(TestIPv4IfAddrRoute, cls).tearDownClass()
Matthew G Smith88d29a92019-07-17 10:01:17 -0500226
227 def setUp(self):
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500228 super(TestIPv4IfAddrRoute, self).setUp()
Matthew G Smith88d29a92019-07-17 10:01:17 -0500229
230 # create 1 pg interface
231 self.create_pg_interfaces(range(1))
232
233 for i in self.pg_interfaces:
234 i.admin_up()
235 i.config_ip4()
236 i.resolve_arp()
237
238 def tearDown(self):
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500239 super(TestIPv4IfAddrRoute, self).tearDown()
Matthew G Smith88d29a92019-07-17 10:01:17 -0500240 for i in self.pg_interfaces:
241 i.unconfig_ip4()
242 i.admin_down()
243
Matthew Smith6c92f5b2019-08-07 11:46:30 -0500244 def test_ipv4_ifaddrs_same_prefix(self):
245 """ IPv4 Interface Addresses Same Prefix test
246
247 Test scenario:
248
249 - Verify no route in FIB for prefix 10.10.10.0/24
250 - Configure IPv4 address 10.10.10.10/24 on an interface
251 - Verify route in FIB for prefix 10.10.10.0/24
252 - Configure IPv4 address 10.10.10.20/24 on an interface
253 - Delete 10.10.10.10/24 from interface
254 - Verify route in FIB for prefix 10.10.10.0/24
255 - Delete 10.10.10.20/24 from interface
256 - Verify no route in FIB for prefix 10.10.10.0/24
257 """
258
259 # create two addresses, verify route not present
260 if_addr1 = VppIpInterfaceAddress(self, self.pg0,
261 VppIpAddress("10.10.10.10"), 24)
262 if_addr2 = VppIpInterfaceAddress(self, self.pg0,
263 VppIpAddress("10.10.10.20"), 24)
264 self.assertFalse(if_addr1.query_vpp_config()) # 10.10.10.0/24
265 self.assertFalse(find_route(self, "10.10.10.10", 32))
266 self.assertFalse(find_route(self, "10.10.10.20", 32))
267 self.assertFalse(find_route(self, "10.10.10.255", 32))
268 self.assertFalse(find_route(self, "10.10.10.0", 32))
269
270 # configure first address, verify route present
271 if_addr1.add_vpp_config()
272 self.assertTrue(if_addr1.query_vpp_config()) # 10.10.10.0/24
273 self.assertTrue(find_route(self, "10.10.10.10", 32))
274 self.assertFalse(find_route(self, "10.10.10.20", 32))
275 self.assertTrue(find_route(self, "10.10.10.255", 32))
276 self.assertTrue(find_route(self, "10.10.10.0", 32))
277
278 # configure second address, delete first, verify route not removed
279 if_addr2.add_vpp_config()
280 if_addr1.remove_vpp_config()
281 self.assertTrue(if_addr1.query_vpp_config()) # 10.10.10.0/24
282 self.assertFalse(find_route(self, "10.10.10.10", 32))
283 self.assertTrue(find_route(self, "10.10.10.20", 32))
284 self.assertTrue(find_route(self, "10.10.10.255", 32))
285 self.assertTrue(find_route(self, "10.10.10.0", 32))
286
287 # delete second address, verify route removed
288 if_addr2.remove_vpp_config()
289 self.assertFalse(if_addr1.query_vpp_config()) # 10.10.10.0/24
290 self.assertFalse(find_route(self, "10.10.10.10", 32))
291 self.assertFalse(find_route(self, "10.10.10.20", 32))
292 self.assertFalse(find_route(self, "10.10.10.255", 32))
293 self.assertFalse(find_route(self, "10.10.10.0", 32))
294
Matthew G Smith88d29a92019-07-17 10:01:17 -0500295 def test_ipv4_ifaddr_route(self):
296 """ IPv4 Interface Address Route test
297
298 Test scenario:
299
300 - Create loopback
301 - Configure IPv4 address on loopback
302 - Verify that address is not in the FIB
303 - Bring loopback up
304 - Verify that address is in the FIB now
305 - Bring loopback down
306 - Verify that address is not in the FIB anymore
307 - Bring loopback up
308 - Configure IPv4 address on loopback
309 - Verify that address is in the FIB now
310 """
311
312 # create a loopback and configure IPv4
313 loopbacks = self.create_loopback_interfaces(1)
314 lo_if = self.lo_interfaces[0]
315
316 lo_if.local_ip4_prefix_len = 32
317 lo_if.config_ip4()
318
319 # The intf was down when addr was added -> entry not in FIB
320 fib4_dump = self.vapi.ip_route_dump(0)
321 self.assertFalse(lo_if.is_ip4_entry_in_fib_dump(fib4_dump))
322
323 # When intf is brought up, entry is added
324 lo_if.admin_up()
325 fib4_dump = self.vapi.ip_route_dump(0)
326 self.assertTrue(lo_if.is_ip4_entry_in_fib_dump(fib4_dump))
327
328 # When intf is brought down, entry is removed
329 lo_if.admin_down()
330 fib4_dump = self.vapi.ip_route_dump(0)
331 self.assertFalse(lo_if.is_ip4_entry_in_fib_dump(fib4_dump))
332
333 # Remove addr, bring up interface, re-add -> entry in FIB
334 lo_if.unconfig_ip4()
335 lo_if.admin_up()
336 lo_if.config_ip4()
337 fib4_dump = self.vapi.ip_route_dump(0)
338 self.assertTrue(lo_if.is_ip4_entry_in_fib_dump(fib4_dump))
339
340
Jan Geletye6c78ee2018-06-26 12:24:03 +0200341class TestICMPEcho(VppTestCase):
342 """ ICMP Echo Test Case """
343
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700344 @classmethod
345 def setUpClass(cls):
346 super(TestICMPEcho, cls).setUpClass()
347
348 @classmethod
349 def tearDownClass(cls):
350 super(TestICMPEcho, cls).tearDownClass()
351
Jan Geletye6c78ee2018-06-26 12:24:03 +0200352 def setUp(self):
353 super(TestICMPEcho, self).setUp()
354
355 # create 1 pg interface
356 self.create_pg_interfaces(range(1))
357
358 for i in self.pg_interfaces:
359 i.admin_up()
360 i.config_ip4()
361 i.resolve_arp()
362
363 def tearDown(self):
364 super(TestICMPEcho, self).tearDown()
365 for i in self.pg_interfaces:
366 i.unconfig_ip4()
367 i.admin_down()
368
369 def test_icmp_echo(self):
370 """ VPP replies to ICMP Echo Request
371
372 Test scenario:
373
374 - Receive ICMP Echo Request message on pg0 interface.
375 - Check outgoing ICMP Echo Reply message on pg0 interface.
376 """
377
378 icmp_id = 0xb
379 icmp_seq = 5
Ole Troan6ed154f2019-10-15 19:31:55 +0200380 icmp_load = b'\x0a' * 18
Jan Geletye6c78ee2018-06-26 12:24:03 +0200381 p_echo_request = (Ether(src=self.pg0.remote_mac,
382 dst=self.pg0.local_mac) /
383 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
384 ICMP(id=icmp_id, seq=icmp_seq) /
385 Raw(load=icmp_load))
386
387 self.pg0.add_stream(p_echo_request)
388 self.pg_enable_capture(self.pg_interfaces)
389 self.pg_start()
390
391 rx = self.pg0.get_capture(1)
392 rx = rx[0]
393 ether = rx[Ether]
394 ipv4 = rx[IP]
395 icmp = rx[ICMP]
396
397 self.assertEqual(ether.src, self.pg0.local_mac)
398 self.assertEqual(ether.dst, self.pg0.remote_mac)
399
400 self.assertEqual(ipv4.src, self.pg0.local_ip4)
401 self.assertEqual(ipv4.dst, self.pg0.remote_ip4)
402
403 self.assertEqual(icmptypes[icmp.type], "echo-reply")
404 self.assertEqual(icmp.id, icmp_id)
405 self.assertEqual(icmp.seq, icmp_seq)
406 self.assertEqual(icmp[Raw].load, icmp_load)
407
408
Matej Klotton16a14cd2016-12-07 15:09:13 +0100409class TestIPv4FibCrud(VppTestCase):
410 """ FIB - add/update/delete - ip4 routes
411
412 Test scenario:
413 - add 1k,
414 - del 100,
415 - add new 1k,
416 - del 1.5k
417
Klement Sekerada505f62017-01-04 12:58:53 +0100418 ..note:: Python API is too slow to add many routes, needs replacement.
Matej Klotton16a14cd2016-12-07 15:09:13 +0100419 """
420
Neale Ranns097fa662018-05-01 05:17:55 -0700421 def config_fib_many_to_one(self, start_dest_addr, next_hop_addr,
422 count, start=0):
Matej Klotton16a14cd2016-12-07 15:09:13 +0100423 """
424
425 :param start_dest_addr:
426 :param next_hop_addr:
427 :param count:
428 :return list: added ips with 32 prefix
429 """
Neale Ranns097fa662018-05-01 05:17:55 -0700430 routes = []
431 for i in range(count):
432 r = VppIpRoute(self, start_dest_addr % (i + start), 32,
433 [VppRoutePath(next_hop_addr, 0xffffffff)])
434 r.add_vpp_config()
435 routes.append(r)
436 return routes
Matej Klotton16a14cd2016-12-07 15:09:13 +0100437
Neale Ranns097fa662018-05-01 05:17:55 -0700438 def unconfig_fib_many_to_one(self, start_dest_addr, next_hop_addr,
439 count, start=0):
Matej Klotton16a14cd2016-12-07 15:09:13 +0100440
Neale Ranns097fa662018-05-01 05:17:55 -0700441 routes = []
442 for i in range(count):
443 r = VppIpRoute(self, start_dest_addr % (i + start), 32,
444 [VppRoutePath(next_hop_addr, 0xffffffff)])
445 r.remove_vpp_config()
446 routes.append(r)
447 return routes
Matej Klotton16a14cd2016-12-07 15:09:13 +0100448
Neale Ranns097fa662018-05-01 05:17:55 -0700449 def create_stream(self, src_if, dst_if, routes, count):
Matej Klotton16a14cd2016-12-07 15:09:13 +0100450 pkts = []
451
452 for _ in range(count):
Neale Ranns097fa662018-05-01 05:17:55 -0700453 dst_addr = random.choice(routes).prefix.address
Klement Sekeradab231a2016-12-21 08:50:14 +0100454 info = self.create_packet_info(src_if, dst_if)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100455 payload = self.info_to_payload(info)
456 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
457 IP(src=src_if.remote_ip4, dst=dst_addr) /
458 UDP(sport=1234, dport=1234) /
459 Raw(payload))
460 info.data = p.copy()
Matej Klotton16a14cd2016-12-07 15:09:13 +0100461 self.extend_packet(p, random.choice(self.pg_if_packet_sizes))
462 pkts.append(p)
463
464 return pkts
465
466 def _find_ip_match(self, find_in, pkt):
467 for p in find_in:
Paul Vinciguerraeaea4212019-03-06 11:58:06 -0800468 if self.payload_to_info(p[Raw]) == \
469 self.payload_to_info(pkt[Raw]):
Matej Klotton16a14cd2016-12-07 15:09:13 +0100470 if p[IP].src != pkt[IP].src:
471 break
472 if p[IP].dst != pkt[IP].dst:
473 break
474 if p[UDP].sport != pkt[UDP].sport:
475 break
476 if p[UDP].dport != pkt[UDP].dport:
477 break
478 return p
479 return None
480
Matej Klotton16a14cd2016-12-07 15:09:13 +0100481 def verify_capture(self, dst_interface, received_pkts, expected_pkts):
482 self.assertEqual(len(received_pkts), len(expected_pkts))
483 to_verify = list(expected_pkts)
484 for p in received_pkts:
485 self.assertEqual(p.src, dst_interface.local_mac)
486 self.assertEqual(p.dst, dst_interface.remote_mac)
487 x = self._find_ip_match(to_verify, p)
488 to_verify.remove(x)
489 self.assertListEqual(to_verify, [])
490
Neale Ranns097fa662018-05-01 05:17:55 -0700491 def verify_route_dump(self, routes):
492 for r in routes:
493 self.assertTrue(find_route(self, r.prefix.address, r.prefix.len))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100494
Neale Ranns097fa662018-05-01 05:17:55 -0700495 def verify_not_in_route_dump(self, routes):
496 for r in routes:
497 self.assertFalse(find_route(self, r.prefix.address, r.prefix.len))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100498
499 @classmethod
500 def setUpClass(cls):
501 """
502 #. Create and initialize 3 pg interfaces.
503 #. initialize class attributes configured_routes and deleted_routes
504 to store information between tests.
505 """
506 super(TestIPv4FibCrud, cls).setUpClass()
507
508 try:
509 # create 3 pg interfaces
510 cls.create_pg_interfaces(range(3))
511
512 cls.interfaces = list(cls.pg_interfaces)
513
514 # setup all interfaces
515 for i in cls.interfaces:
516 i.admin_up()
517 i.config_ip4()
518 i.resolve_arp()
519
520 cls.configured_routes = []
521 cls.deleted_routes = []
522 cls.pg_if_packet_sizes = [64, 512, 1518, 9018]
523
524 except Exception:
525 super(TestIPv4FibCrud, cls).tearDownClass()
526 raise
527
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700528 @classmethod
529 def tearDownClass(cls):
530 super(TestIPv4FibCrud, cls).tearDownClass()
531
Matej Klotton16a14cd2016-12-07 15:09:13 +0100532 def setUp(self):
533 super(TestIPv4FibCrud, self).setUp()
Klement Sekeradab231a2016-12-21 08:50:14 +0100534 self.reset_packet_infos()
Matej Klotton16a14cd2016-12-07 15:09:13 +0100535
Paul Vinciguerra4eed7472018-12-16 14:52:36 -0800536 self.configured_routes = []
537 self.deleted_routes = []
538
Matej Klotton16a14cd2016-12-07 15:09:13 +0100539 def test_1_add_routes(self):
Neale Ranns097fa662018-05-01 05:17:55 -0700540 """ Add 1k routes """
Matej Klotton16a14cd2016-12-07 15:09:13 +0100541
Neale Ranns097fa662018-05-01 05:17:55 -0700542 # add 100 routes check with traffic script.
Matej Klotton16a14cd2016-12-07 15:09:13 +0100543 self.configured_routes.extend(self.config_fib_many_to_one(
Neale Ranns097fa662018-05-01 05:17:55 -0700544 "10.0.0.%d", self.pg0.remote_ip4, 100))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100545
Neale Ranns097fa662018-05-01 05:17:55 -0700546 self.verify_route_dump(self.configured_routes)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100547
548 self.stream_1 = self.create_stream(
549 self.pg1, self.pg0, self.configured_routes, 100)
550 self.stream_2 = self.create_stream(
551 self.pg2, self.pg0, self.configured_routes, 100)
552 self.pg1.add_stream(self.stream_1)
553 self.pg2.add_stream(self.stream_2)
554
555 self.pg_enable_capture(self.pg_interfaces)
556 self.pg_start()
557
Klement Sekeradab231a2016-12-21 08:50:14 +0100558 pkts = self.pg0.get_capture(len(self.stream_1) + len(self.stream_2))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100559 self.verify_capture(self.pg0, pkts, self.stream_1 + self.stream_2)
560
Matej Klotton16a14cd2016-12-07 15:09:13 +0100561 def test_2_del_routes(self):
562 """ Delete 100 routes
563
564 - delete 10 routes check with traffic script.
565 """
Paul Vinciguerra4eed7472018-12-16 14:52:36 -0800566 # config 1M FIB entries
567 self.configured_routes.extend(self.config_fib_many_to_one(
Neale Ranns097fa662018-05-01 05:17:55 -0700568 "10.0.0.%d", self.pg0.remote_ip4, 100))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100569 self.deleted_routes.extend(self.unconfig_fib_many_to_one(
Neale Ranns097fa662018-05-01 05:17:55 -0700570 "10.0.0.%d", self.pg0.remote_ip4, 10, start=10))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100571 for x in self.deleted_routes:
572 self.configured_routes.remove(x)
573
Neale Ranns097fa662018-05-01 05:17:55 -0700574 self.verify_route_dump(self.configured_routes)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100575
576 self.stream_1 = self.create_stream(
577 self.pg1, self.pg0, self.configured_routes, 100)
578 self.stream_2 = self.create_stream(
579 self.pg2, self.pg0, self.configured_routes, 100)
580 self.stream_3 = self.create_stream(
581 self.pg1, self.pg0, self.deleted_routes, 100)
582 self.stream_4 = self.create_stream(
583 self.pg2, self.pg0, self.deleted_routes, 100)
584 self.pg1.add_stream(self.stream_1 + self.stream_3)
585 self.pg2.add_stream(self.stream_2 + self.stream_4)
586 self.pg_enable_capture(self.pg_interfaces)
587 self.pg_start()
588
Klement Sekeradab231a2016-12-21 08:50:14 +0100589 pkts = self.pg0.get_capture(len(self.stream_1) + len(self.stream_2))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100590 self.verify_capture(self.pg0, pkts, self.stream_1 + self.stream_2)
591
592 def test_3_add_new_routes(self):
593 """ Add 1k routes
594
595 - re-add 5 routes check with traffic script.
596 - add 100 routes check with traffic script.
597 """
Paul Vinciguerra4eed7472018-12-16 14:52:36 -0800598 # config 1M FIB entries
599 self.configured_routes.extend(self.config_fib_many_to_one(
Neale Ranns097fa662018-05-01 05:17:55 -0700600 "10.0.0.%d", self.pg0.remote_ip4, 100))
Paul Vinciguerra4eed7472018-12-16 14:52:36 -0800601 self.deleted_routes.extend(self.unconfig_fib_many_to_one(
Neale Ranns097fa662018-05-01 05:17:55 -0700602 "10.0.0.%d", self.pg0.remote_ip4, 10, start=10))
Paul Vinciguerra4eed7472018-12-16 14:52:36 -0800603 for x in self.deleted_routes:
604 self.configured_routes.remove(x)
605
Matej Klotton16a14cd2016-12-07 15:09:13 +0100606 tmp = self.config_fib_many_to_one(
Neale Ranns097fa662018-05-01 05:17:55 -0700607 "10.0.0.%d", self.pg0.remote_ip4, 5, start=10)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100608 self.configured_routes.extend(tmp)
609 for x in tmp:
610 self.deleted_routes.remove(x)
611
612 self.configured_routes.extend(self.config_fib_many_to_one(
Neale Ranns097fa662018-05-01 05:17:55 -0700613 "10.0.1.%d", self.pg0.remote_ip4, 100))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100614
Neale Ranns097fa662018-05-01 05:17:55 -0700615 self.verify_route_dump(self.configured_routes)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100616
617 self.stream_1 = self.create_stream(
618 self.pg1, self.pg0, self.configured_routes, 300)
619 self.stream_2 = self.create_stream(
620 self.pg2, self.pg0, self.configured_routes, 300)
621 self.stream_3 = self.create_stream(
622 self.pg1, self.pg0, self.deleted_routes, 100)
623 self.stream_4 = self.create_stream(
624 self.pg2, self.pg0, self.deleted_routes, 100)
625
626 self.pg1.add_stream(self.stream_1 + self.stream_3)
627 self.pg2.add_stream(self.stream_2 + self.stream_4)
628 self.pg_enable_capture(self.pg_interfaces)
629 self.pg_start()
630
Klement Sekeradab231a2016-12-21 08:50:14 +0100631 pkts = self.pg0.get_capture(len(self.stream_1) + len(self.stream_2))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100632 self.verify_capture(self.pg0, pkts, self.stream_1 + self.stream_2)
633
Neale Ranns097fa662018-05-01 05:17:55 -0700634 # delete 5 routes check with traffic script.
635 # add 100 routes check with traffic script.
Matej Klotton16a14cd2016-12-07 15:09:13 +0100636 self.deleted_routes.extend(self.unconfig_fib_many_to_one(
Neale Ranns097fa662018-05-01 05:17:55 -0700637 "10.0.0.%d", self.pg0.remote_ip4, 15))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100638 self.deleted_routes.extend(self.unconfig_fib_many_to_one(
Neale Ranns097fa662018-05-01 05:17:55 -0700639 "10.0.0.%d", self.pg0.remote_ip4, 85))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100640 self.deleted_routes.extend(self.unconfig_fib_many_to_one(
Neale Ranns097fa662018-05-01 05:17:55 -0700641 "10.0.1.%d", self.pg0.remote_ip4, 100))
642 self.verify_not_in_route_dump(self.deleted_routes)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100643
644
Neale Ranns37be7362017-02-21 17:30:26 -0800645class TestIPNull(VppTestCase):
646 """ IPv4 routes via NULL """
647
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700648 @classmethod
649 def setUpClass(cls):
650 super(TestIPNull, cls).setUpClass()
651
652 @classmethod
653 def tearDownClass(cls):
654 super(TestIPNull, cls).tearDownClass()
655
Neale Ranns37be7362017-02-21 17:30:26 -0800656 def setUp(self):
657 super(TestIPNull, self).setUp()
658
659 # create 2 pg interfaces
Neale Ranns3b93be52018-09-07 01:48:54 -0700660 self.create_pg_interfaces(range(2))
Neale Ranns37be7362017-02-21 17:30:26 -0800661
662 for i in self.pg_interfaces:
663 i.admin_up()
664 i.config_ip4()
665 i.resolve_arp()
666
667 def tearDown(self):
668 super(TestIPNull, self).tearDown()
669 for i in self.pg_interfaces:
670 i.unconfig_ip4()
671 i.admin_down()
672
673 def test_ip_null(self):
674 """ IP NULL route """
675
676 #
677 # A route via IP NULL that will reply with ICMP unreachables
678 #
Neale Ranns097fa662018-05-01 05:17:55 -0700679 ip_unreach = VppIpRoute(
680 self, "10.0.0.1", 32,
681 [VppRoutePath("0.0.0.0",
682 0xffffffff,
683 type=FibPathType.FIB_PATH_TYPE_ICMP_UNREACH)])
Neale Ranns37be7362017-02-21 17:30:26 -0800684 ip_unreach.add_vpp_config()
685
686 p_unreach = (Ether(src=self.pg0.remote_mac,
687 dst=self.pg0.local_mac) /
688 IP(src=self.pg0.remote_ip4, dst="10.0.0.1") /
689 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +0200690 Raw(b'\xa5' * 100))
Neale Ranns37be7362017-02-21 17:30:26 -0800691 self.pg0.add_stream(p_unreach)
692 self.pg_enable_capture(self.pg_interfaces)
693 self.pg_start()
694
695 rx = self.pg0.get_capture(1)
696 rx = rx[0]
697 icmp = rx[ICMP]
698
699 self.assertEqual(icmptypes[icmp.type], "dest-unreach")
700 self.assertEqual(icmpcodes[icmp.type][icmp.code], "host-unreachable")
701 self.assertEqual(icmp.src, self.pg0.remote_ip4)
702 self.assertEqual(icmp.dst, "10.0.0.1")
703
704 #
705 # ICMP replies are rate limited. so sit and spin.
706 #
707 self.sleep(1)
708
709 #
710 # A route via IP NULL that will reply with ICMP prohibited
711 #
Neale Ranns097fa662018-05-01 05:17:55 -0700712 ip_prohibit = VppIpRoute(
713 self, "10.0.0.2", 32,
714 [VppRoutePath("0.0.0.0",
715 0xffffffff,
716 type=FibPathType.FIB_PATH_TYPE_ICMP_PROHIBIT)])
Neale Ranns37be7362017-02-21 17:30:26 -0800717 ip_prohibit.add_vpp_config()
718
719 p_prohibit = (Ether(src=self.pg0.remote_mac,
720 dst=self.pg0.local_mac) /
721 IP(src=self.pg0.remote_ip4, dst="10.0.0.2") /
722 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +0200723 Raw(b'\xa5' * 100))
Neale Ranns37be7362017-02-21 17:30:26 -0800724
725 self.pg0.add_stream(p_prohibit)
726 self.pg_enable_capture(self.pg_interfaces)
727 self.pg_start()
728
729 rx = self.pg0.get_capture(1)
730
731 rx = rx[0]
732 icmp = rx[ICMP]
733
734 self.assertEqual(icmptypes[icmp.type], "dest-unreach")
735 self.assertEqual(icmpcodes[icmp.type][icmp.code], "host-prohibited")
736 self.assertEqual(icmp.src, self.pg0.remote_ip4)
737 self.assertEqual(icmp.dst, "10.0.0.2")
738
Neale Ranns3b93be52018-09-07 01:48:54 -0700739 def test_ip_drop(self):
740 """ IP Drop Routes """
741
742 p = (Ether(src=self.pg0.remote_mac,
743 dst=self.pg0.local_mac) /
744 IP(src=self.pg0.remote_ip4, dst="1.1.1.1") /
745 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +0200746 Raw(b'\xa5' * 100))
Neale Ranns3b93be52018-09-07 01:48:54 -0700747
748 r1 = VppIpRoute(self, "1.1.1.0", 24,
749 [VppRoutePath(self.pg1.remote_ip4,
750 self.pg1.sw_if_index)])
751 r1.add_vpp_config()
752
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400753 rx = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1)
Neale Ranns3b93be52018-09-07 01:48:54 -0700754
755 #
756 # insert a more specific as a drop
757 #
Neale Ranns097fa662018-05-01 05:17:55 -0700758 r2 = VppIpRoute(self, "1.1.1.1", 32,
759 [VppRoutePath("0.0.0.0",
760 0xffffffff,
761 type=FibPathType.FIB_PATH_TYPE_DROP)])
Neale Ranns3b93be52018-09-07 01:48:54 -0700762 r2.add_vpp_config()
763
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400764 self.send_and_assert_no_replies(self.pg0, p * NUM_PKTS, "Drop Route")
Neale Ranns3b93be52018-09-07 01:48:54 -0700765 r2.remove_vpp_config()
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400766 rx = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1)
Neale Ranns3b93be52018-09-07 01:48:54 -0700767
Neale Ranns37be7362017-02-21 17:30:26 -0800768
Neale Ranns180279b2017-03-16 15:49:09 -0400769class TestIPDisabled(VppTestCase):
770 """ IPv4 disabled """
771
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700772 @classmethod
773 def setUpClass(cls):
774 super(TestIPDisabled, cls).setUpClass()
775
776 @classmethod
777 def tearDownClass(cls):
778 super(TestIPDisabled, cls).tearDownClass()
779
Neale Ranns180279b2017-03-16 15:49:09 -0400780 def setUp(self):
781 super(TestIPDisabled, self).setUp()
782
783 # create 2 pg interfaces
784 self.create_pg_interfaces(range(2))
785
786 # PG0 is IP enalbed
787 self.pg0.admin_up()
788 self.pg0.config_ip4()
789 self.pg0.resolve_arp()
790
791 # PG 1 is not IP enabled
792 self.pg1.admin_up()
793
794 def tearDown(self):
795 super(TestIPDisabled, self).tearDown()
796 for i in self.pg_interfaces:
797 i.unconfig_ip4()
798 i.admin_down()
799
Neale Ranns180279b2017-03-16 15:49:09 -0400800 def test_ip_disabled(self):
801 """ IP Disabled """
802
803 #
804 # An (S,G).
805 # one accepting interface, pg0, 2 forwarding interfaces
806 #
807 route_232_1_1_1 = VppIpMRoute(
808 self,
809 "0.0.0.0",
810 "232.1.1.1", 32,
811 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
812 [VppMRoutePath(self.pg1.sw_if_index,
813 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
814 VppMRoutePath(self.pg0.sw_if_index,
815 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
816 route_232_1_1_1.add_vpp_config()
817
818 pu = (Ether(src=self.pg1.remote_mac,
819 dst=self.pg1.local_mac) /
820 IP(src="10.10.10.10", dst=self.pg0.remote_ip4) /
821 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +0200822 Raw(b'\xa5' * 100))
Neale Ranns180279b2017-03-16 15:49:09 -0400823 pm = (Ether(src=self.pg1.remote_mac,
824 dst=self.pg1.local_mac) /
825 IP(src="10.10.10.10", dst="232.1.1.1") /
826 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +0200827 Raw(b'\xa5' * 100))
Neale Ranns180279b2017-03-16 15:49:09 -0400828
829 #
830 # PG1 does not forward IP traffic
831 #
832 self.send_and_assert_no_replies(self.pg1, pu, "IP disabled")
833 self.send_and_assert_no_replies(self.pg1, pm, "IP disabled")
834
835 #
836 # IP enable PG1
837 #
838 self.pg1.config_ip4()
839
840 #
841 # Now we get packets through
842 #
843 self.pg1.add_stream(pu)
844 self.pg_enable_capture(self.pg_interfaces)
845 self.pg_start()
846 rx = self.pg0.get_capture(1)
847
848 self.pg1.add_stream(pm)
849 self.pg_enable_capture(self.pg_interfaces)
850 self.pg_start()
851 rx = self.pg0.get_capture(1)
852
853 #
854 # Disable PG1
855 #
856 self.pg1.unconfig_ip4()
857
858 #
859 # PG1 does not forward IP traffic
860 #
861 self.send_and_assert_no_replies(self.pg1, pu, "IP disabled")
862 self.send_and_assert_no_replies(self.pg1, pm, "IP disabled")
863
864
Neale Ranns9a69a602017-03-26 10:56:33 -0700865class TestIPSubNets(VppTestCase):
866 """ IPv4 Subnets """
867
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700868 @classmethod
869 def setUpClass(cls):
870 super(TestIPSubNets, cls).setUpClass()
871
872 @classmethod
873 def tearDownClass(cls):
874 super(TestIPSubNets, cls).tearDownClass()
875
Neale Ranns9a69a602017-03-26 10:56:33 -0700876 def setUp(self):
877 super(TestIPSubNets, self).setUp()
878
879 # create a 2 pg interfaces
880 self.create_pg_interfaces(range(2))
881
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700882 # pg0 we will use to experiment
Neale Ranns9a69a602017-03-26 10:56:33 -0700883 self.pg0.admin_up()
884
885 # pg1 is setup normally
886 self.pg1.admin_up()
887 self.pg1.config_ip4()
888 self.pg1.resolve_arp()
889
890 def tearDown(self):
891 super(TestIPSubNets, self).tearDown()
892 for i in self.pg_interfaces:
893 i.admin_down()
894
Neale Ranns9a69a602017-03-26 10:56:33 -0700895 def test_ip_sub_nets(self):
896 """ IP Sub Nets """
897
898 #
899 # Configure a covering route to forward so we know
900 # when we are dropping
901 #
902 cover_route = VppIpRoute(self, "10.0.0.0", 8,
903 [VppRoutePath(self.pg1.remote_ip4,
904 self.pg1.sw_if_index)])
905 cover_route.add_vpp_config()
906
907 p = (Ether(src=self.pg1.remote_mac,
908 dst=self.pg1.local_mac) /
909 IP(dst="10.10.10.10", src=self.pg0.local_ip4) /
910 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +0200911 Raw(b'\xa5' * 100))
Neale Ranns9a69a602017-03-26 10:56:33 -0700912
913 self.pg1.add_stream(p)
914 self.pg_enable_capture(self.pg_interfaces)
915 self.pg_start()
916 rx = self.pg1.get_capture(1)
917
918 #
919 # Configure some non-/24 subnets on an IP interface
920 #
921 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.10.10.10")
922
Ole Troan9a475372019-03-05 16:58:24 +0100923 self.vapi.sw_interface_add_del_address(
Jakub Grajciar053204a2019-03-18 13:17:53 +0100924 sw_if_index=self.pg0.sw_if_index,
925 prefix=VppIpPrefix("10.10.10.10", 16).encode())
Neale Ranns9a69a602017-03-26 10:56:33 -0700926
927 pn = (Ether(src=self.pg1.remote_mac,
928 dst=self.pg1.local_mac) /
929 IP(dst="10.10.0.0", src=self.pg0.local_ip4) /
930 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +0200931 Raw(b'\xa5' * 100))
Neale Ranns9a69a602017-03-26 10:56:33 -0700932 pb = (Ether(src=self.pg1.remote_mac,
933 dst=self.pg1.local_mac) /
934 IP(dst="10.10.255.255", src=self.pg0.local_ip4) /
935 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +0200936 Raw(b'\xa5' * 100))
Neale Ranns9a69a602017-03-26 10:56:33 -0700937
938 self.send_and_assert_no_replies(self.pg1, pn, "IP Network address")
939 self.send_and_assert_no_replies(self.pg1, pb, "IP Broadcast address")
940
941 # remove the sub-net and we are forwarding via the cover again
Ole Troan9a475372019-03-05 16:58:24 +0100942 self.vapi.sw_interface_add_del_address(
Jakub Grajciar053204a2019-03-18 13:17:53 +0100943 sw_if_index=self.pg0.sw_if_index,
944 prefix=VppIpPrefix("10.10.10.10", 16).encode(), is_add=0)
945
Neale Ranns9a69a602017-03-26 10:56:33 -0700946 self.pg1.add_stream(pn)
947 self.pg_enable_capture(self.pg_interfaces)
948 self.pg_start()
949 rx = self.pg1.get_capture(1)
950 self.pg1.add_stream(pb)
951 self.pg_enable_capture(self.pg_interfaces)
952 self.pg_start()
953 rx = self.pg1.get_capture(1)
954
955 #
956 # A /31 is a special case where the 'other-side' is an attached host
957 # packets to that peer generate ARP requests
958 #
959 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.10.10.10")
960
Ole Troan9a475372019-03-05 16:58:24 +0100961 self.vapi.sw_interface_add_del_address(
Jakub Grajciar053204a2019-03-18 13:17:53 +0100962 sw_if_index=self.pg0.sw_if_index,
963 prefix=VppIpPrefix("10.10.10.10", 31).encode())
Neale Ranns9a69a602017-03-26 10:56:33 -0700964
965 pn = (Ether(src=self.pg1.remote_mac,
966 dst=self.pg1.local_mac) /
967 IP(dst="10.10.10.11", src=self.pg0.local_ip4) /
968 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +0200969 Raw(b'\xa5' * 100))
Neale Ranns9a69a602017-03-26 10:56:33 -0700970
971 self.pg1.add_stream(pn)
972 self.pg_enable_capture(self.pg_interfaces)
973 self.pg_start()
974 rx = self.pg0.get_capture(1)
975 rx[ARP]
976
977 # remove the sub-net and we are forwarding via the cover again
Ole Troan9a475372019-03-05 16:58:24 +0100978 self.vapi.sw_interface_add_del_address(
Jakub Grajciar053204a2019-03-18 13:17:53 +0100979 sw_if_index=self.pg0.sw_if_index,
980 prefix=VppIpPrefix("10.10.10.10", 31).encode(), is_add=0)
981
Neale Ranns9a69a602017-03-26 10:56:33 -0700982 self.pg1.add_stream(pn)
983 self.pg_enable_capture(self.pg_interfaces)
984 self.pg_start()
985 rx = self.pg1.get_capture(1)
986
987
Neale Ranns227038a2017-04-21 01:07:59 -0700988class TestIPLoadBalance(VppTestCase):
989 """ IPv4 Load-Balancing """
990
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700991 @classmethod
992 def setUpClass(cls):
993 super(TestIPLoadBalance, cls).setUpClass()
994
995 @classmethod
996 def tearDownClass(cls):
997 super(TestIPLoadBalance, cls).tearDownClass()
998
Neale Ranns227038a2017-04-21 01:07:59 -0700999 def setUp(self):
1000 super(TestIPLoadBalance, self).setUp()
1001
1002 self.create_pg_interfaces(range(5))
Neale Ranns15002542017-09-10 04:39:11 -07001003 mpls_tbl = VppMplsTable(self, 0)
1004 mpls_tbl.add_vpp_config()
Neale Ranns227038a2017-04-21 01:07:59 -07001005
1006 for i in self.pg_interfaces:
1007 i.admin_up()
1008 i.config_ip4()
1009 i.resolve_arp()
Neale Ranns71275e32017-05-25 12:38:58 -07001010 i.enable_mpls()
Neale Ranns227038a2017-04-21 01:07:59 -07001011
1012 def tearDown(self):
Neale Ranns227038a2017-04-21 01:07:59 -07001013 for i in self.pg_interfaces:
Neale Ranns71275e32017-05-25 12:38:58 -07001014 i.disable_mpls()
Neale Ranns227038a2017-04-21 01:07:59 -07001015 i.unconfig_ip4()
1016 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07001017 super(TestIPLoadBalance, self).tearDown()
Neale Ranns227038a2017-04-21 01:07:59 -07001018
1019 def send_and_expect_load_balancing(self, input, pkts, outputs):
1020 input.add_stream(pkts)
1021 self.pg_enable_capture(self.pg_interfaces)
1022 self.pg_start()
Neale Ranns63480742019-03-13 06:41:52 -07001023 rxs = []
Neale Ranns227038a2017-04-21 01:07:59 -07001024 for oo in outputs:
1025 rx = oo._get_capture(1)
1026 self.assertNotEqual(0, len(rx))
Neale Ranns63480742019-03-13 06:41:52 -07001027 for r in rx:
1028 rxs.append(r)
1029 return rxs
Neale Ranns227038a2017-04-21 01:07:59 -07001030
Neale Ranns42e6b092017-07-31 02:56:03 -07001031 def send_and_expect_one_itf(self, input, pkts, itf):
1032 input.add_stream(pkts)
1033 self.pg_enable_capture(self.pg_interfaces)
1034 self.pg_start()
1035 rx = itf.get_capture(len(pkts))
1036
Neale Ranns227038a2017-04-21 01:07:59 -07001037 def test_ip_load_balance(self):
1038 """ IP Load-Balancing """
1039
1040 #
1041 # An array of packets that differ only in the destination port
1042 #
Neale Ranns71275e32017-05-25 12:38:58 -07001043 port_ip_pkts = []
1044 port_mpls_pkts = []
Neale Ranns227038a2017-04-21 01:07:59 -07001045
1046 #
1047 # An array of packets that differ only in the source address
1048 #
Neale Ranns71275e32017-05-25 12:38:58 -07001049 src_ip_pkts = []
1050 src_mpls_pkts = []
Neale Ranns227038a2017-04-21 01:07:59 -07001051
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001052 for ii in range(NUM_PKTS):
Neale Ranns71275e32017-05-25 12:38:58 -07001053 port_ip_hdr = (IP(dst="10.0.0.1", src="20.0.0.1") /
1054 UDP(sport=1234, dport=1234 + ii) /
Ole Troan5e56f752019-10-21 21:06:52 +02001055 Raw(b'\xa5' * 100))
Neale Ranns71275e32017-05-25 12:38:58 -07001056 port_ip_pkts.append((Ether(src=self.pg0.remote_mac,
1057 dst=self.pg0.local_mac) /
1058 port_ip_hdr))
1059 port_mpls_pkts.append((Ether(src=self.pg0.remote_mac,
1060 dst=self.pg0.local_mac) /
1061 MPLS(label=66, ttl=2) /
1062 port_ip_hdr))
1063
1064 src_ip_hdr = (IP(dst="10.0.0.1", src="20.0.0.%d" % ii) /
1065 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +02001066 Raw(b'\xa5' * 100))
Neale Ranns71275e32017-05-25 12:38:58 -07001067 src_ip_pkts.append((Ether(src=self.pg0.remote_mac,
1068 dst=self.pg0.local_mac) /
1069 src_ip_hdr))
1070 src_mpls_pkts.append((Ether(src=self.pg0.remote_mac,
1071 dst=self.pg0.local_mac) /
1072 MPLS(label=66, ttl=2) /
1073 src_ip_hdr))
Neale Ranns227038a2017-04-21 01:07:59 -07001074
1075 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1076 [VppRoutePath(self.pg1.remote_ip4,
1077 self.pg1.sw_if_index),
1078 VppRoutePath(self.pg2.remote_ip4,
1079 self.pg2.sw_if_index)])
1080 route_10_0_0_1.add_vpp_config()
1081
Neale Ranns71275e32017-05-25 12:38:58 -07001082 binding = VppMplsIpBind(self, 66, "10.0.0.1", 32)
1083 binding.add_vpp_config()
1084
Neale Ranns227038a2017-04-21 01:07:59 -07001085 #
1086 # inject the packet on pg0 - expect load-balancing across the 2 paths
1087 # - since the default hash config is to use IP src,dst and port
1088 # src,dst
1089 # We are not going to ensure equal amounts of packets across each link,
1090 # since the hash algorithm is statistical and therefore this can never
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001091 # be guaranteed. But with 64 different packets we do expect some
Neale Ranns227038a2017-04-21 01:07:59 -07001092 # balancing. So instead just ensure there is traffic on each link.
1093 #
Neale Ranns71275e32017-05-25 12:38:58 -07001094 self.send_and_expect_load_balancing(self.pg0, port_ip_pkts,
Neale Ranns227038a2017-04-21 01:07:59 -07001095 [self.pg1, self.pg2])
Neale Ranns71275e32017-05-25 12:38:58 -07001096 self.send_and_expect_load_balancing(self.pg0, src_ip_pkts,
1097 [self.pg1, self.pg2])
1098 self.send_and_expect_load_balancing(self.pg0, port_mpls_pkts,
1099 [self.pg1, self.pg2])
1100 self.send_and_expect_load_balancing(self.pg0, src_mpls_pkts,
Neale Ranns227038a2017-04-21 01:07:59 -07001101 [self.pg1, self.pg2])
1102
1103 #
1104 # change the flow hash config so it's only IP src,dst
1105 # - now only the stream with differing source address will
1106 # load-balance
1107 #
Ole Troana5b2eec2019-03-11 19:23:25 +01001108 self.vapi.set_ip_flow_hash(vrf_id=0, src=1, dst=1, sport=0, dport=0)
Neale Ranns227038a2017-04-21 01:07:59 -07001109
Neale Ranns71275e32017-05-25 12:38:58 -07001110 self.send_and_expect_load_balancing(self.pg0, src_ip_pkts,
1111 [self.pg1, self.pg2])
1112 self.send_and_expect_load_balancing(self.pg0, src_mpls_pkts,
Neale Ranns227038a2017-04-21 01:07:59 -07001113 [self.pg1, self.pg2])
1114
Neale Ranns42e6b092017-07-31 02:56:03 -07001115 self.send_and_expect_one_itf(self.pg0, port_ip_pkts, self.pg2)
Neale Ranns227038a2017-04-21 01:07:59 -07001116
1117 #
1118 # change the flow hash config back to defaults
1119 #
Ole Troana5b2eec2019-03-11 19:23:25 +01001120 self.vapi.set_ip_flow_hash(vrf_id=0, src=1, dst=1, sport=1, dport=1)
Neale Ranns227038a2017-04-21 01:07:59 -07001121
1122 #
1123 # Recursive prefixes
1124 # - testing that 2 stages of load-balancing occurs and there is no
1125 # polarisation (i.e. only 2 of 4 paths are used)
1126 #
1127 port_pkts = []
1128 src_pkts = []
1129
1130 for ii in range(257):
1131 port_pkts.append((Ether(src=self.pg0.remote_mac,
1132 dst=self.pg0.local_mac) /
1133 IP(dst="1.1.1.1", src="20.0.0.1") /
1134 UDP(sport=1234, dport=1234 + ii) /
Ole Troan5e56f752019-10-21 21:06:52 +02001135 Raw(b'\xa5' * 100)))
Neale Ranns227038a2017-04-21 01:07:59 -07001136 src_pkts.append((Ether(src=self.pg0.remote_mac,
1137 dst=self.pg0.local_mac) /
1138 IP(dst="1.1.1.1", src="20.0.0.%d" % ii) /
1139 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +02001140 Raw(b'\xa5' * 100)))
Neale Ranns227038a2017-04-21 01:07:59 -07001141
1142 route_10_0_0_2 = VppIpRoute(self, "10.0.0.2", 32,
1143 [VppRoutePath(self.pg3.remote_ip4,
1144 self.pg3.sw_if_index),
1145 VppRoutePath(self.pg4.remote_ip4,
1146 self.pg4.sw_if_index)])
1147 route_10_0_0_2.add_vpp_config()
1148
1149 route_1_1_1_1 = VppIpRoute(self, "1.1.1.1", 32,
1150 [VppRoutePath("10.0.0.2", 0xffffffff),
1151 VppRoutePath("10.0.0.1", 0xffffffff)])
1152 route_1_1_1_1.add_vpp_config()
1153
1154 #
1155 # inject the packet on pg0 - expect load-balancing across all 4 paths
1156 #
1157 self.vapi.cli("clear trace")
1158 self.send_and_expect_load_balancing(self.pg0, port_pkts,
1159 [self.pg1, self.pg2,
1160 self.pg3, self.pg4])
1161 self.send_and_expect_load_balancing(self.pg0, src_pkts,
1162 [self.pg1, self.pg2,
1163 self.pg3, self.pg4])
1164
Neale Ranns42e6b092017-07-31 02:56:03 -07001165 #
Neale Ranns63480742019-03-13 06:41:52 -07001166 # bring down pg1 expect LB to adjust to use only those that are pu
1167 #
1168 self.pg1.link_down()
1169
1170 rx = self.send_and_expect_load_balancing(self.pg0, src_pkts,
1171 [self.pg2, self.pg3,
1172 self.pg4])
1173 self.assertEqual(len(src_pkts), len(rx))
1174
1175 #
1176 # bring down pg2 expect LB to adjust to use only those that are pu
1177 #
1178 self.pg2.link_down()
1179
1180 rx = self.send_and_expect_load_balancing(self.pg0, src_pkts,
1181 [self.pg3, self.pg4])
1182 self.assertEqual(len(src_pkts), len(rx))
1183
1184 #
1185 # bring the links back up - expect LB over all again
1186 #
1187 self.pg1.link_up()
1188 self.pg2.link_up()
1189
1190 rx = self.send_and_expect_load_balancing(self.pg0, src_pkts,
1191 [self.pg1, self.pg2,
1192 self.pg3, self.pg4])
1193 self.assertEqual(len(src_pkts), len(rx))
1194
1195 #
1196 # The same link-up/down but this time admin state
1197 #
1198 self.pg1.admin_down()
1199 self.pg2.admin_down()
1200 rx = self.send_and_expect_load_balancing(self.pg0, src_pkts,
1201 [self.pg3, self.pg4])
1202 self.assertEqual(len(src_pkts), len(rx))
1203 self.pg1.admin_up()
1204 self.pg2.admin_up()
1205 self.pg1.resolve_arp()
1206 self.pg2.resolve_arp()
1207 rx = self.send_and_expect_load_balancing(self.pg0, src_pkts,
1208 [self.pg1, self.pg2,
1209 self.pg3, self.pg4])
1210 self.assertEqual(len(src_pkts), len(rx))
1211
1212 #
Neale Ranns42e6b092017-07-31 02:56:03 -07001213 # Recursive prefixes
1214 # - testing that 2 stages of load-balancing, no choices
1215 #
1216 port_pkts = []
1217
1218 for ii in range(257):
1219 port_pkts.append((Ether(src=self.pg0.remote_mac,
1220 dst=self.pg0.local_mac) /
1221 IP(dst="1.1.1.2", src="20.0.0.2") /
1222 UDP(sport=1234, dport=1234 + ii) /
Ole Troan5e56f752019-10-21 21:06:52 +02001223 Raw(b'\xa5' * 100)))
Neale Ranns42e6b092017-07-31 02:56:03 -07001224
1225 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
1226 [VppRoutePath(self.pg3.remote_ip4,
1227 self.pg3.sw_if_index)])
1228 route_10_0_0_3.add_vpp_config()
1229
1230 route_1_1_1_2 = VppIpRoute(self, "1.1.1.2", 32,
1231 [VppRoutePath("10.0.0.3", 0xffffffff)])
1232 route_1_1_1_2.add_vpp_config()
1233
1234 #
Neale Ranns63480742019-03-13 06:41:52 -07001235 # inject the packet on pg0 - rx only on via routes output interface
Neale Ranns42e6b092017-07-31 02:56:03 -07001236 #
1237 self.vapi.cli("clear trace")
1238 self.send_and_expect_one_itf(self.pg0, port_pkts, self.pg3)
1239
Neale Ranns63480742019-03-13 06:41:52 -07001240 #
1241 # Add a LB route in the presence of a down link - expect no
1242 # packets over the down link
1243 #
1244 self.pg3.link_down()
1245
1246 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
1247 [VppRoutePath(self.pg3.remote_ip4,
1248 self.pg3.sw_if_index),
1249 VppRoutePath(self.pg4.remote_ip4,
1250 self.pg4.sw_if_index)])
1251 route_10_0_0_3.add_vpp_config()
1252
1253 port_pkts = []
1254 for ii in range(257):
1255 port_pkts.append(Ether(src=self.pg0.remote_mac,
1256 dst=self.pg0.local_mac) /
1257 IP(dst="10.0.0.3", src="20.0.0.2") /
1258 UDP(sport=1234, dport=1234 + ii) /
Ole Troan5e56f752019-10-21 21:06:52 +02001259 Raw(b'\xa5' * 100))
Neale Ranns63480742019-03-13 06:41:52 -07001260
1261 self.send_and_expect_one_itf(self.pg0, port_pkts, self.pg4)
1262
1263 # bring the link back up
1264 self.pg3.link_up()
1265
1266 rx = self.send_and_expect_load_balancing(self.pg0, port_pkts,
1267 [self.pg3, self.pg4])
1268 self.assertEqual(len(src_pkts), len(rx))
1269
Neale Ranns30d0fd42017-05-30 07:30:04 -07001270
1271class TestIPVlan0(VppTestCase):
1272 """ IPv4 VLAN-0 """
1273
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001274 @classmethod
1275 def setUpClass(cls):
1276 super(TestIPVlan0, cls).setUpClass()
1277
1278 @classmethod
1279 def tearDownClass(cls):
1280 super(TestIPVlan0, cls).tearDownClass()
1281
Neale Ranns30d0fd42017-05-30 07:30:04 -07001282 def setUp(self):
1283 super(TestIPVlan0, self).setUp()
1284
1285 self.create_pg_interfaces(range(2))
Neale Ranns15002542017-09-10 04:39:11 -07001286 mpls_tbl = VppMplsTable(self, 0)
1287 mpls_tbl.add_vpp_config()
Neale Ranns30d0fd42017-05-30 07:30:04 -07001288
1289 for i in self.pg_interfaces:
1290 i.admin_up()
1291 i.config_ip4()
1292 i.resolve_arp()
1293 i.enable_mpls()
1294
1295 def tearDown(self):
Neale Ranns30d0fd42017-05-30 07:30:04 -07001296 for i in self.pg_interfaces:
1297 i.disable_mpls()
1298 i.unconfig_ip4()
1299 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07001300 super(TestIPVlan0, self).tearDown()
Neale Ranns30d0fd42017-05-30 07:30:04 -07001301
Neale Ranns30d0fd42017-05-30 07:30:04 -07001302 def test_ip_vlan_0(self):
1303 """ IP VLAN-0 """
1304
1305 pkts = (Ether(src=self.pg0.remote_mac,
1306 dst=self.pg0.local_mac) /
1307 Dot1Q(vlan=0) /
1308 IP(dst=self.pg1.remote_ip4,
1309 src=self.pg0.remote_ip4) /
1310 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +02001311 Raw(b'\xa5' * 100)) * NUM_PKTS
Neale Ranns30d0fd42017-05-30 07:30:04 -07001312
1313 #
1314 # Expect that packets sent on VLAN-0 are forwarded on the
1315 # main interface.
1316 #
1317 self.send_and_expect(self.pg0, pkts, self.pg1)
1318
1319
Neale Rannsd91c1db2017-07-31 02:30:50 -07001320class TestIPPunt(VppTestCase):
1321 """ IPv4 Punt Police/Redirect """
1322
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001323 @classmethod
1324 def setUpClass(cls):
1325 super(TestIPPunt, cls).setUpClass()
1326
1327 @classmethod
1328 def tearDownClass(cls):
1329 super(TestIPPunt, cls).tearDownClass()
1330
Neale Rannsd91c1db2017-07-31 02:30:50 -07001331 def setUp(self):
1332 super(TestIPPunt, self).setUp()
1333
Pavel Kotucek609e1212018-11-27 09:59:44 +01001334 self.create_pg_interfaces(range(4))
Neale Rannsd91c1db2017-07-31 02:30:50 -07001335
1336 for i in self.pg_interfaces:
1337 i.admin_up()
1338 i.config_ip4()
1339 i.resolve_arp()
1340
1341 def tearDown(self):
1342 super(TestIPPunt, self).tearDown()
1343 for i in self.pg_interfaces:
1344 i.unconfig_ip4()
1345 i.admin_down()
1346
Neale Rannsd91c1db2017-07-31 02:30:50 -07001347 def test_ip_punt(self):
1348 """ IP punt police and redirect """
1349
Neale Ranns68577d22019-06-04 13:31:23 +00001350 # use UDP packet that have a port we need to explicitly
1351 # register to get punted.
1352 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
1353 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
1354 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
1355 punt_udp = {
1356 'type': pt_l4,
1357 'punt': {
1358 'l4': {
1359 'af': af_ip4,
1360 'protocol': udp_proto,
1361 'port': 1234,
1362 }
1363 }
1364 }
1365
1366 self.vapi.set_punt(is_add=1, punt=punt_udp)
1367
Neale Rannsd91c1db2017-07-31 02:30:50 -07001368 p = (Ether(src=self.pg0.remote_mac,
1369 dst=self.pg0.local_mac) /
1370 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
Neale Ranns68577d22019-06-04 13:31:23 +00001371 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +02001372 Raw(b'\xa5' * 100))
Neale Rannsd91c1db2017-07-31 02:30:50 -07001373
1374 pkts = p * 1025
1375
1376 #
1377 # Configure a punt redirect via pg1.
1378 #
Ole Troan0bcad322018-12-11 13:04:01 +01001379 nh_addr = self.pg1.remote_ip4
Neale Rannsd91c1db2017-07-31 02:30:50 -07001380 self.vapi.ip_punt_redirect(self.pg0.sw_if_index,
1381 self.pg1.sw_if_index,
1382 nh_addr)
1383
1384 self.send_and_expect(self.pg0, pkts, self.pg1)
1385
1386 #
1387 # add a policer
1388 #
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08001389 policer = self.vapi.policer_add_del(b"ip4-punt", 400, 0, 10, 0,
Neale Rannsd91c1db2017-07-31 02:30:50 -07001390 rate_type=1)
1391 self.vapi.ip_punt_police(policer.policer_index)
1392
1393 self.vapi.cli("clear trace")
1394 self.pg0.add_stream(pkts)
1395 self.pg_enable_capture(self.pg_interfaces)
1396 self.pg_start()
1397
1398 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001399 # the number of packet received should be greater than 0,
Neale Rannsd91c1db2017-07-31 02:30:50 -07001400 # but not equal to the number sent, since some were policed
1401 #
1402 rx = self.pg1._get_capture(1)
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001403 self.assertGreater(len(rx), 0)
1404 self.assertLess(len(rx), len(pkts))
Neale Rannsd91c1db2017-07-31 02:30:50 -07001405
1406 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001407 # remove the policer. back to full rx
Neale Rannsd91c1db2017-07-31 02:30:50 -07001408 #
1409 self.vapi.ip_punt_police(policer.policer_index, is_add=0)
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08001410 self.vapi.policer_add_del(b"ip4-punt", 400, 0, 10, 0,
Neale Rannsd91c1db2017-07-31 02:30:50 -07001411 rate_type=1, is_add=0)
1412 self.send_and_expect(self.pg0, pkts, self.pg1)
1413
1414 #
1415 # remove the redirect. expect full drop.
1416 #
1417 self.vapi.ip_punt_redirect(self.pg0.sw_if_index,
1418 self.pg1.sw_if_index,
1419 nh_addr,
1420 is_add=0)
1421 self.send_and_assert_no_replies(self.pg0, pkts,
1422 "IP no punt config")
1423
1424 #
1425 # Add a redirect that is not input port selective
1426 #
1427 self.vapi.ip_punt_redirect(0xffffffff,
1428 self.pg1.sw_if_index,
1429 nh_addr)
1430 self.send_and_expect(self.pg0, pkts, self.pg1)
1431
1432 self.vapi.ip_punt_redirect(0xffffffff,
1433 self.pg1.sw_if_index,
1434 nh_addr,
1435 is_add=0)
1436
Pavel Kotucek609e1212018-11-27 09:59:44 +01001437 def test_ip_punt_dump(self):
1438 """ IP4 punt redirect dump"""
1439
1440 #
1441 # Configure a punt redirects
1442 #
Ole Troan0bcad322018-12-11 13:04:01 +01001443 nh_address = self.pg3.remote_ip4
Pavel Kotucek609e1212018-11-27 09:59:44 +01001444 self.vapi.ip_punt_redirect(self.pg0.sw_if_index,
1445 self.pg3.sw_if_index,
1446 nh_address)
1447 self.vapi.ip_punt_redirect(self.pg1.sw_if_index,
1448 self.pg3.sw_if_index,
1449 nh_address)
1450 self.vapi.ip_punt_redirect(self.pg2.sw_if_index,
1451 self.pg3.sw_if_index,
Ole Troan0bcad322018-12-11 13:04:01 +01001452 '0.0.0.0')
Pavel Kotucek609e1212018-11-27 09:59:44 +01001453
1454 #
1455 # Dump pg0 punt redirects
1456 #
1457 punts = self.vapi.ip_punt_redirect_dump(self.pg0.sw_if_index)
1458 for p in punts:
1459 self.assertEqual(p.punt.rx_sw_if_index, self.pg0.sw_if_index)
1460
1461 #
1462 # Dump punt redirects for all interfaces
1463 #
1464 punts = self.vapi.ip_punt_redirect_dump(0xffffffff)
1465 self.assertEqual(len(punts), 3)
1466 for p in punts:
1467 self.assertEqual(p.punt.tx_sw_if_index, self.pg3.sw_if_index)
Ole Troan0bcad322018-12-11 13:04:01 +01001468 self.assertNotEqual(punts[1].punt.nh, self.pg3.remote_ip4)
1469 self.assertEqual(str(punts[2].punt.nh), '0.0.0.0')
Pavel Kotucek609e1212018-11-27 09:59:44 +01001470
Neale Rannsd91c1db2017-07-31 02:30:50 -07001471
Neale Ranns054c03a2017-10-13 05:15:07 -07001472class TestIPDeag(VppTestCase):
1473 """ IPv4 Deaggregate Routes """
1474
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001475 @classmethod
1476 def setUpClass(cls):
1477 super(TestIPDeag, cls).setUpClass()
1478
1479 @classmethod
1480 def tearDownClass(cls):
1481 super(TestIPDeag, cls).tearDownClass()
1482
Neale Ranns054c03a2017-10-13 05:15:07 -07001483 def setUp(self):
1484 super(TestIPDeag, self).setUp()
1485
1486 self.create_pg_interfaces(range(3))
1487
1488 for i in self.pg_interfaces:
1489 i.admin_up()
1490 i.config_ip4()
1491 i.resolve_arp()
1492
1493 def tearDown(self):
1494 super(TestIPDeag, self).tearDown()
1495 for i in self.pg_interfaces:
1496 i.unconfig_ip4()
1497 i.admin_down()
1498
Neale Ranns054c03a2017-10-13 05:15:07 -07001499 def test_ip_deag(self):
1500 """ IP Deag Routes """
1501
1502 #
1503 # Create a table to be used for:
1504 # 1 - another destination address lookup
1505 # 2 - a source address lookup
1506 #
1507 table_dst = VppIpTable(self, 1)
1508 table_src = VppIpTable(self, 2)
1509 table_dst.add_vpp_config()
1510 table_src.add_vpp_config()
1511
1512 #
1513 # Add a route in the default table to point to a deag/
1514 # second lookup in each of these tables
1515 #
1516 route_to_dst = VppIpRoute(self, "1.1.1.1", 32,
1517 [VppRoutePath("0.0.0.0",
1518 0xffffffff,
1519 nh_table_id=1)])
Neale Ranns097fa662018-05-01 05:17:55 -07001520 route_to_src = VppIpRoute(
1521 self, "1.1.1.2", 32,
1522 [VppRoutePath("0.0.0.0",
1523 0xffffffff,
1524 nh_table_id=2,
1525 type=FibPathType.FIB_PATH_TYPE_SOURCE_LOOKUP)])
Neale Ranns054c03a2017-10-13 05:15:07 -07001526 route_to_dst.add_vpp_config()
1527 route_to_src.add_vpp_config()
1528
1529 #
1530 # packets to these destination are dropped, since they'll
1531 # hit the respective default routes in the second table
1532 #
1533 p_dst = (Ether(src=self.pg0.remote_mac,
1534 dst=self.pg0.local_mac) /
1535 IP(src="5.5.5.5", dst="1.1.1.1") /
1536 TCP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +02001537 Raw(b'\xa5' * 100))
Neale Ranns054c03a2017-10-13 05:15:07 -07001538 p_src = (Ether(src=self.pg0.remote_mac,
1539 dst=self.pg0.local_mac) /
1540 IP(src="2.2.2.2", dst="1.1.1.2") /
1541 TCP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +02001542 Raw(b'\xa5' * 100))
Neale Ranns054c03a2017-10-13 05:15:07 -07001543 pkts_dst = p_dst * 257
1544 pkts_src = p_src * 257
1545
1546 self.send_and_assert_no_replies(self.pg0, pkts_dst,
1547 "IP in dst table")
1548 self.send_and_assert_no_replies(self.pg0, pkts_src,
1549 "IP in src table")
1550
1551 #
1552 # add a route in the dst table to forward via pg1
1553 #
1554 route_in_dst = VppIpRoute(self, "1.1.1.1", 32,
1555 [VppRoutePath(self.pg1.remote_ip4,
1556 self.pg1.sw_if_index)],
1557 table_id=1)
1558 route_in_dst.add_vpp_config()
Neale Ranns097fa662018-05-01 05:17:55 -07001559
Neale Ranns054c03a2017-10-13 05:15:07 -07001560 self.send_and_expect(self.pg0, pkts_dst, self.pg1)
1561
1562 #
1563 # add a route in the src table to forward via pg2
1564 #
1565 route_in_src = VppIpRoute(self, "2.2.2.2", 32,
1566 [VppRoutePath(self.pg2.remote_ip4,
1567 self.pg2.sw_if_index)],
1568 table_id=2)
1569 route_in_src.add_vpp_config()
1570 self.send_and_expect(self.pg0, pkts_src, self.pg2)
1571
Neale Rannsce9e0b42018-08-01 12:53:17 -07001572 #
1573 # loop in the lookup DP
1574 #
1575 route_loop = VppIpRoute(self, "2.2.2.3", 32,
1576 [VppRoutePath("0.0.0.0",
1577 0xffffffff,
1578 nh_table_id=0)])
1579 route_loop.add_vpp_config()
1580
1581 p_l = (Ether(src=self.pg0.remote_mac,
1582 dst=self.pg0.local_mac) /
1583 IP(src="2.2.2.4", dst="2.2.2.3") /
1584 TCP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +02001585 Raw(b'\xa5' * 100))
Neale Rannsce9e0b42018-08-01 12:53:17 -07001586
1587 self.send_and_assert_no_replies(self.pg0, p_l * 257,
1588 "IP lookup loop")
1589
Neale Ranns054c03a2017-10-13 05:15:07 -07001590
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001591class TestIPInput(VppTestCase):
1592 """ IPv4 Input Exceptions """
1593
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001594 @classmethod
1595 def setUpClass(cls):
1596 super(TestIPInput, cls).setUpClass()
1597
1598 @classmethod
1599 def tearDownClass(cls):
1600 super(TestIPInput, cls).tearDownClass()
1601
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001602 def setUp(self):
1603 super(TestIPInput, self).setUp()
1604
1605 self.create_pg_interfaces(range(2))
1606
1607 for i in self.pg_interfaces:
1608 i.admin_up()
1609 i.config_ip4()
1610 i.resolve_arp()
1611
1612 def tearDown(self):
1613 super(TestIPInput, self).tearDown()
1614 for i in self.pg_interfaces:
1615 i.unconfig_ip4()
1616 i.admin_down()
1617
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001618 def test_ip_input(self):
1619 """ IP Input Exceptions """
1620
1621 # i can't find a way in scapy to construct an IP packet
1622 # with a length less than the IP header length
1623
1624 #
1625 # Packet too short - this is forwarded
1626 #
1627 p_short = (Ether(src=self.pg0.remote_mac,
1628 dst=self.pg0.local_mac) /
1629 IP(src=self.pg0.remote_ip4,
1630 dst=self.pg1.remote_ip4,
1631 len=40) /
1632 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +02001633 Raw(b'\xa5' * 100))
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001634
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001635 rx = self.send_and_expect(self.pg0, p_short * NUM_PKTS, self.pg1)
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001636
1637 #
1638 # Packet too long - this is dropped
1639 #
1640 p_long = (Ether(src=self.pg0.remote_mac,
1641 dst=self.pg0.local_mac) /
1642 IP(src=self.pg0.remote_ip4,
1643 dst=self.pg1.remote_ip4,
1644 len=400) /
1645 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +02001646 Raw(b'\xa5' * 100))
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001647
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001648 rx = self.send_and_assert_no_replies(self.pg0, p_long * NUM_PKTS,
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001649 "too long")
1650
1651 #
1652 # bad chksum - this is dropped
1653 #
1654 p_chksum = (Ether(src=self.pg0.remote_mac,
1655 dst=self.pg0.local_mac) /
1656 IP(src=self.pg0.remote_ip4,
1657 dst=self.pg1.remote_ip4,
1658 chksum=400) /
1659 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +02001660 Raw(b'\xa5' * 100))
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001661
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001662 rx = self.send_and_assert_no_replies(self.pg0, p_chksum * NUM_PKTS,
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001663 "bad checksum")
1664
1665 #
1666 # bad version - this is dropped
1667 #
1668 p_ver = (Ether(src=self.pg0.remote_mac,
1669 dst=self.pg0.local_mac) /
1670 IP(src=self.pg0.remote_ip4,
1671 dst=self.pg1.remote_ip4,
1672 version=3) /
1673 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +02001674 Raw(b'\xa5' * 100))
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001675
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001676 rx = self.send_and_assert_no_replies(self.pg0, p_ver * NUM_PKTS,
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001677 "funky version")
1678
1679 #
1680 # fragment offset 1 - this is dropped
1681 #
1682 p_frag = (Ether(src=self.pg0.remote_mac,
1683 dst=self.pg0.local_mac) /
1684 IP(src=self.pg0.remote_ip4,
1685 dst=self.pg1.remote_ip4,
1686 frag=1) /
1687 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +02001688 Raw(b'\xa5' * 100))
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001689
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001690 rx = self.send_and_assert_no_replies(self.pg0, p_frag * NUM_PKTS,
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001691 "frag offset")
1692
1693 #
1694 # TTL expired packet
1695 #
1696 p_ttl = (Ether(src=self.pg0.remote_mac,
1697 dst=self.pg0.local_mac) /
1698 IP(src=self.pg0.remote_ip4,
1699 dst=self.pg1.remote_ip4,
1700 ttl=1) /
1701 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +02001702 Raw(b'\xa5' * 100))
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001703
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001704 rx = self.send_and_expect(self.pg0, p_ttl * NUM_PKTS, self.pg0)
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001705
1706 rx = rx[0]
1707 icmp = rx[ICMP]
1708
1709 self.assertEqual(icmptypes[icmp.type], "time-exceeded")
1710 self.assertEqual(icmpcodes[icmp.type][icmp.code],
1711 "ttl-zero-during-transit")
1712 self.assertEqual(icmp.src, self.pg0.remote_ip4)
1713 self.assertEqual(icmp.dst, self.pg1.remote_ip4)
1714
Neale Rannsffd78d12018-02-09 06:05:16 -08001715 #
1716 # MTU exceeded
1717 #
1718 p_mtu = (Ether(src=self.pg0.remote_mac,
1719 dst=self.pg0.local_mac) /
1720 IP(src=self.pg0.remote_ip4,
1721 dst=self.pg1.remote_ip4,
Ole Troan8a9c8f12018-05-18 11:01:31 +02001722 ttl=10, flags='DF') /
Neale Rannsffd78d12018-02-09 06:05:16 -08001723 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +02001724 Raw(b'\xa5' * 2000))
Neale Rannsffd78d12018-02-09 06:05:16 -08001725
Ole Troand7231612018-06-07 10:17:57 +02001726 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1500, 0, 0, 0])
Neale Rannsffd78d12018-02-09 06:05:16 -08001727
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001728 rx = self.send_and_expect(self.pg0, p_mtu * NUM_PKTS, self.pg0)
Neale Rannsffd78d12018-02-09 06:05:16 -08001729 rx = rx[0]
1730 icmp = rx[ICMP]
1731
1732 self.assertEqual(icmptypes[icmp.type], "dest-unreach")
1733 self.assertEqual(icmpcodes[icmp.type][icmp.code],
1734 "fragmentation-needed")
1735 self.assertEqual(icmp.src, self.pg0.remote_ip4)
1736 self.assertEqual(icmp.dst, self.pg1.remote_ip4)
1737
Ole Troand7231612018-06-07 10:17:57 +02001738 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [2500, 0, 0, 0])
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001739 rx = self.send_and_expect(self.pg0, p_mtu * NUM_PKTS, self.pg1)
Neale Rannsffd78d12018-02-09 06:05:16 -08001740
Ole Troand7231612018-06-07 10:17:57 +02001741 # Reset MTU for subsequent tests
1742 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [9000, 0, 0, 0])
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001743
Neale Rannsbe2286b2018-12-09 12:54:51 -08001744 #
1745 # source address 0.0.0.0 and 25.255.255.255 and for-us
1746 #
1747 p_s0 = (Ether(src=self.pg0.remote_mac,
1748 dst=self.pg0.local_mac) /
1749 IP(src="0.0.0.0",
1750 dst=self.pg0.local_ip4) /
1751 ICMP(id=4, seq=4) /
Ole Troan5e56f752019-10-21 21:06:52 +02001752 Raw(load=b'\x0a' * 18))
Neale Rannsbe2286b2018-12-09 12:54:51 -08001753 rx = self.send_and_assert_no_replies(self.pg0, p_s0 * 17)
1754
1755 p_s0 = (Ether(src=self.pg0.remote_mac,
1756 dst=self.pg0.local_mac) /
1757 IP(src="255.255.255.255",
1758 dst=self.pg0.local_ip4) /
1759 ICMP(id=4, seq=4) /
Ole Troan5e56f752019-10-21 21:06:52 +02001760 Raw(load=b'\x0a' * 18))
Neale Rannsbe2286b2018-12-09 12:54:51 -08001761 rx = self.send_and_assert_no_replies(self.pg0, p_s0 * 17)
1762
Neale Ranns1855b8e2018-07-11 10:31:26 -07001763
1764class TestIPDirectedBroadcast(VppTestCase):
1765 """ IPv4 Directed Broadcast """
1766
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001767 @classmethod
1768 def setUpClass(cls):
1769 super(TestIPDirectedBroadcast, cls).setUpClass()
1770
1771 @classmethod
1772 def tearDownClass(cls):
1773 super(TestIPDirectedBroadcast, cls).tearDownClass()
1774
Neale Ranns1855b8e2018-07-11 10:31:26 -07001775 def setUp(self):
1776 super(TestIPDirectedBroadcast, self).setUp()
1777
1778 self.create_pg_interfaces(range(2))
1779
1780 for i in self.pg_interfaces:
1781 i.admin_up()
1782
1783 def tearDown(self):
1784 super(TestIPDirectedBroadcast, self).tearDown()
1785 for i in self.pg_interfaces:
1786 i.admin_down()
1787
1788 def test_ip_input(self):
1789 """ IP Directed Broadcast """
1790
1791 #
1792 # set the directed broadcast on pg0 first, then config IP4 addresses
1793 # for pg1 directed broadcast is always disabled
1794 self.vapi.sw_interface_set_ip_directed_broadcast(
1795 self.pg0.sw_if_index, 1)
1796
1797 p0 = (Ether(src=self.pg1.remote_mac,
1798 dst=self.pg1.local_mac) /
1799 IP(src="1.1.1.1",
1800 dst=self.pg0._local_ip4_bcast) /
1801 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +02001802 Raw(b'\xa5' * 2000))
Neale Ranns1855b8e2018-07-11 10:31:26 -07001803 p1 = (Ether(src=self.pg0.remote_mac,
1804 dst=self.pg0.local_mac) /
1805 IP(src="1.1.1.1",
1806 dst=self.pg1._local_ip4_bcast) /
1807 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +02001808 Raw(b'\xa5' * 2000))
Neale Ranns1855b8e2018-07-11 10:31:26 -07001809
1810 self.pg0.config_ip4()
1811 self.pg0.resolve_arp()
1812 self.pg1.config_ip4()
1813 self.pg1.resolve_arp()
1814
1815 #
1816 # test packet is L2 broadcast
1817 #
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001818 rx = self.send_and_expect(self.pg1, p0 * NUM_PKTS, self.pg0)
Neale Ranns1855b8e2018-07-11 10:31:26 -07001819 self.assertTrue(rx[0][Ether].dst, "ff:ff:ff:ff:ff:ff")
1820
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001821 self.send_and_assert_no_replies(self.pg0, p1 * NUM_PKTS,
Neale Ranns1855b8e2018-07-11 10:31:26 -07001822 "directed broadcast disabled")
1823
1824 #
1825 # toggle directed broadcast on pg0
1826 #
1827 self.vapi.sw_interface_set_ip_directed_broadcast(
1828 self.pg0.sw_if_index, 0)
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001829 self.send_and_assert_no_replies(self.pg1, p0 * NUM_PKTS,
Neale Ranns1855b8e2018-07-11 10:31:26 -07001830 "directed broadcast disabled")
1831
1832 self.vapi.sw_interface_set_ip_directed_broadcast(
1833 self.pg0.sw_if_index, 1)
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001834 rx = self.send_and_expect(self.pg1, p0 * NUM_PKTS, self.pg0)
Neale Ranns1855b8e2018-07-11 10:31:26 -07001835
1836 self.pg0.unconfig_ip4()
1837 self.pg1.unconfig_ip4()
1838
1839
mu.duojiao59a82952018-10-11 14:27:30 +08001840class TestIPLPM(VppTestCase):
1841 """ IPv4 longest Prefix Match """
1842
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001843 @classmethod
1844 def setUpClass(cls):
1845 super(TestIPLPM, cls).setUpClass()
1846
1847 @classmethod
1848 def tearDownClass(cls):
1849 super(TestIPLPM, cls).tearDownClass()
1850
mu.duojiao59a82952018-10-11 14:27:30 +08001851 def setUp(self):
1852 super(TestIPLPM, self).setUp()
1853
1854 self.create_pg_interfaces(range(4))
1855
1856 for i in self.pg_interfaces:
1857 i.admin_up()
1858 i.config_ip4()
1859 i.resolve_arp()
1860
1861 def tearDown(self):
1862 super(TestIPLPM, self).tearDown()
1863 for i in self.pg_interfaces:
1864 i.admin_down()
1865 i.unconfig_ip4()
1866
1867 def test_ip_lpm(self):
1868 """ IP longest Prefix Match """
1869
1870 s_24 = VppIpRoute(self, "10.1.2.0", 24,
1871 [VppRoutePath(self.pg1.remote_ip4,
1872 self.pg1.sw_if_index)])
1873 s_24.add_vpp_config()
1874 s_8 = VppIpRoute(self, "10.0.0.0", 8,
1875 [VppRoutePath(self.pg2.remote_ip4,
1876 self.pg2.sw_if_index)])
1877 s_8.add_vpp_config()
1878
1879 p_8 = (Ether(src=self.pg0.remote_mac,
1880 dst=self.pg0.local_mac) /
1881 IP(src="1.1.1.1",
1882 dst="10.1.1.1") /
1883 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +02001884 Raw(b'\xa5' * 2000))
mu.duojiao59a82952018-10-11 14:27:30 +08001885 p_24 = (Ether(src=self.pg0.remote_mac,
1886 dst=self.pg0.local_mac) /
1887 IP(src="1.1.1.1",
1888 dst="10.1.2.1") /
1889 UDP(sport=1234, dport=1234) /
Ole Troan5e56f752019-10-21 21:06:52 +02001890 Raw(b'\xa5' * 2000))
mu.duojiao59a82952018-10-11 14:27:30 +08001891
1892 self.logger.info(self.vapi.cli("sh ip fib mtrie"))
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001893 rx = self.send_and_expect(self.pg0, p_8 * NUM_PKTS, self.pg2)
1894 rx = self.send_and_expect(self.pg0, p_24 * NUM_PKTS, self.pg1)
mu.duojiao59a82952018-10-11 14:27:30 +08001895
1896
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02001897class TestIPv4Frag(VppTestCase):
1898 """ IPv4 fragmentation """
1899
1900 @classmethod
1901 def setUpClass(cls):
1902 super(TestIPv4Frag, cls).setUpClass()
1903
1904 cls.create_pg_interfaces([0, 1])
1905 cls.src_if = cls.pg0
1906 cls.dst_if = cls.pg1
1907
1908 # setup all interfaces
1909 for i in cls.pg_interfaces:
1910 i.admin_up()
1911 i.config_ip4()
1912 i.resolve_arp()
1913
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001914 @classmethod
1915 def tearDownClass(cls):
1916 super(TestIPv4Frag, cls).tearDownClass()
1917
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02001918 def test_frag_large_packets(self):
1919 """ Fragmentation of large packets """
1920
1921 p = (Ether(dst=self.src_if.local_mac, src=self.src_if.remote_mac) /
1922 IP(src=self.src_if.remote_ip4, dst=self.dst_if.remote_ip4) /
1923 UDP(sport=1234, dport=5678) / Raw())
1924 self.extend_packet(p, 6000, "abcde")
1925 saved_payload = p[Raw].load
1926
1927 # Force fragmentation by setting MTU of output interface
1928 # lower than packet size
1929 self.vapi.sw_interface_set_mtu(self.dst_if.sw_if_index,
1930 [5000, 0, 0, 0])
1931
1932 self.pg_enable_capture()
1933 self.src_if.add_stream(p)
1934 self.pg_start()
1935
1936 # Expecting 3 fragments because size of created fragments currently
1937 # cannot be larger then VPP buffer size (which is 2048)
1938 packets = self.dst_if.get_capture(3)
1939
1940 # Assume VPP sends the fragments in order
Ole Troan6ed154f2019-10-15 19:31:55 +02001941 payload = b''
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02001942 for p in packets:
1943 payload_offset = p.frag * 8
1944 if payload_offset > 0:
1945 payload_offset -= 8 # UDP header is not in payload
1946 self.assert_equal(payload_offset, len(payload))
1947 payload += p[Raw].load
1948 self.assert_equal(payload, saved_payload, "payload")
1949
1950
Damjan Marionf56b77a2016-10-03 19:44:57 +02001951if __name__ == '__main__':
Klement Sekeraf62ae122016-10-11 11:47:09 +02001952 unittest.main(testRunner=VppTestRunner)