blob: a6920f8dba543cdd7f443dfee52af6d5f28b38c4 [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
Neale Ranns180279b2017-03-16 15:49:09 -040016from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpMRoute, \
Neale Ranns15002542017-09-10 04:39:11 -070017 VppMRoutePath, MRouteItfFlags, MRouteEntryFlags, VppMplsIpBind, \
Neale Ranns097fa662018-05-01 05:17:55 -070018 VppMplsTable, VppIpTable, FibPathType, find_route
Paul Vinciguerraa6fe4632018-11-25 11:21:50 -080019from vpp_sub_interface import VppSubInterface, VppDot1QSubint, VppDot1ADSubint
Neale Ranns68577d22019-06-04 13:31:23 +000020from vpp_papi import VppEnum
Damjan Marionf56b77a2016-10-03 19:44:57 +020021
Paul Vinciguerra4271c972019-05-14 13:25:49 -040022NUM_PKTS = 67
23
Damjan Marionf56b77a2016-10-03 19:44:57 +020024
Klement Sekeraf62ae122016-10-11 11:47:09 +020025class TestIPv4(VppTestCase):
Damjan Marionf56b77a2016-10-03 19:44:57 +020026 """ IPv4 Test Case """
27
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070028 @classmethod
29 def setUpClass(cls):
30 super(TestIPv4, cls).setUpClass()
31
32 @classmethod
33 def tearDownClass(cls):
34 super(TestIPv4, cls).tearDownClass()
35
Klement Sekeraf62ae122016-10-11 11:47:09 +020036 def setUp(self):
Matej Klotton86d87c42016-11-11 11:38:55 +010037 """
38 Perform test setup before test case.
39
40 **Config:**
41 - create 3 pg interfaces
42 - untagged pg0 interface
43 - Dot1Q subinterface on pg1
44 - Dot1AD subinterface on pg2
45 - setup interfaces:
46 - put it into UP state
47 - set IPv4 addresses
48 - resolve neighbor address using ARP
49 - configure 200 fib entries
50
51 :ivar list interfaces: pg interfaces and subinterfaces.
52 :ivar dict flows: IPv4 packet flows in test.
Matej Klotton86d87c42016-11-11 11:38:55 +010053 """
Klement Sekeraf62ae122016-10-11 11:47:09 +020054 super(TestIPv4, self).setUp()
Damjan Marionf56b77a2016-10-03 19:44:57 +020055
Klement Sekeraf62ae122016-10-11 11:47:09 +020056 # create 3 pg interfaces
57 self.create_pg_interfaces(range(3))
Damjan Marionf56b77a2016-10-03 19:44:57 +020058
Klement Sekeraf62ae122016-10-11 11:47:09 +020059 # create 2 subinterfaces for pg1 and pg2
60 self.sub_interfaces = [
61 VppDot1QSubint(self, self.pg1, 100),
62 VppDot1ADSubint(self, self.pg2, 200, 300, 400)]
Damjan Marionf56b77a2016-10-03 19:44:57 +020063
Klement Sekeraf62ae122016-10-11 11:47:09 +020064 # packet flows mapping pg0 -> pg1.sub, pg2.sub, etc.
65 self.flows = dict()
66 self.flows[self.pg0] = [self.pg1.sub_if, self.pg2.sub_if]
67 self.flows[self.pg1.sub_if] = [self.pg0, self.pg2.sub_if]
68 self.flows[self.pg2.sub_if] = [self.pg0, self.pg1.sub_if]
Damjan Marionf56b77a2016-10-03 19:44:57 +020069
Klement Sekeraf62ae122016-10-11 11:47:09 +020070 # packet sizes
Jan Geletye6c78ee2018-06-26 12:24:03 +020071 self.pg_if_packet_sizes = [64, 1500, 9020]
Damjan Marionf56b77a2016-10-03 19:44:57 +020072
Klement Sekeraf62ae122016-10-11 11:47:09 +020073 self.interfaces = list(self.pg_interfaces)
74 self.interfaces.extend(self.sub_interfaces)
Damjan Marionf56b77a2016-10-03 19:44:57 +020075
Klement Sekeraf62ae122016-10-11 11:47:09 +020076 # setup all interfaces
77 for i in self.interfaces:
78 i.admin_up()
79 i.config_ip4()
80 i.resolve_arp()
81
Matej Klotton86d87c42016-11-11 11:38:55 +010082 # config 2M FIB entries
Damjan Marionf56b77a2016-10-03 19:44:57 +020083
84 def tearDown(self):
Matej Klotton86d87c42016-11-11 11:38:55 +010085 """Run standard test teardown and log ``show ip arp``."""
Klement Sekeraf62ae122016-10-11 11:47:09 +020086 super(TestIPv4, self).tearDown()
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -070087
88 def show_commands_at_teardown(self):
89 self.logger.info(self.vapi.cli("show ip arp"))
90 # info(self.vapi.cli("show ip fib")) # many entries
Damjan Marionf56b77a2016-10-03 19:44:57 +020091
Jan Geletye6c78ee2018-06-26 12:24:03 +020092 def modify_packet(self, src_if, packet_size, pkt):
93 """Add load, set destination IP and extend packet to required packet
94 size for defined interface.
95
96 :param VppInterface src_if: Interface to create packet for.
97 :param int packet_size: Required packet size.
98 :param Scapy pkt: Packet to be modified.
99 """
100 dst_if_idx = packet_size / 10 % 2
101 dst_if = self.flows[src_if][dst_if_idx]
102 info = self.create_packet_info(src_if, dst_if)
103 payload = self.info_to_payload(info)
104 p = pkt/Raw(payload)
105 p[IP].dst = dst_if.remote_ip4
106 info.data = p.copy()
107 if isinstance(src_if, VppSubInterface):
108 p = src_if.add_dot1_layer(p)
109 self.extend_packet(p, packet_size)
110
111 return p
112
113 def create_stream(self, src_if):
Matej Klotton86d87c42016-11-11 11:38:55 +0100114 """Create input packet stream for defined interface.
115
116 :param VppInterface src_if: Interface to create packet stream for.
Matej Klotton86d87c42016-11-11 11:38:55 +0100117 """
Jan Geletye6c78ee2018-06-26 12:24:03 +0200118 hdr_ext = 4 if isinstance(src_if, VppSubInterface) else 0
119 pkt_tmpl = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
120 IP(src=src_if.remote_ip4) /
121 UDP(sport=1234, dport=1234))
122
123 pkts = [self.modify_packet(src_if, i, pkt_tmpl)
Paul Vinciguerraa6fe4632018-11-25 11:21:50 -0800124 for i in moves.range(self.pg_if_packet_sizes[0],
125 self.pg_if_packet_sizes[1], 10)]
Jan Geletye6c78ee2018-06-26 12:24:03 +0200126 pkts_b = [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[1] + hdr_ext,
128 self.pg_if_packet_sizes[2] + hdr_ext,
129 50)]
Jan Geletye6c78ee2018-06-26 12:24:03 +0200130 pkts.extend(pkts_b)
131
Damjan Marionf56b77a2016-10-03 19:44:57 +0200132 return pkts
133
Klement Sekeraf62ae122016-10-11 11:47:09 +0200134 def verify_capture(self, dst_if, capture):
Matej Klotton86d87c42016-11-11 11:38:55 +0100135 """Verify captured input packet stream for defined interface.
136
137 :param VppInterface dst_if: Interface to verify captured packet stream
Jan Geletye6c78ee2018-06-26 12:24:03 +0200138 for.
Matej Klotton86d87c42016-11-11 11:38:55 +0100139 :param list capture: Captured packet stream.
140 """
141 self.logger.info("Verifying capture on interface %s" % dst_if.name)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200142 last_info = dict()
Damjan Marionf56b77a2016-10-03 19:44:57 +0200143 for i in self.interfaces:
Klement Sekeraf62ae122016-10-11 11:47:09 +0200144 last_info[i.sw_if_index] = None
145 is_sub_if = False
146 dst_sw_if_index = dst_if.sw_if_index
147 if hasattr(dst_if, 'parent'):
148 is_sub_if = True
Damjan Marionf56b77a2016-10-03 19:44:57 +0200149 for packet in capture:
Klement Sekeraf62ae122016-10-11 11:47:09 +0200150 if is_sub_if:
151 # Check VLAN tags and Ethernet header
152 packet = dst_if.remove_dot1_layer(packet)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200153 self.assertTrue(Dot1Q not in packet)
154 try:
155 ip = packet[IP]
156 udp = packet[UDP]
Paul Vinciguerraeaea4212019-03-06 11:58:06 -0800157 payload_info = self.payload_to_info(packet[Raw])
Damjan Marionf56b77a2016-10-03 19:44:57 +0200158 packet_index = payload_info.index
Klement Sekeraf62ae122016-10-11 11:47:09 +0200159 self.assertEqual(payload_info.dst, dst_sw_if_index)
Klement Sekerada505f62017-01-04 12:58:53 +0100160 self.logger.debug(
161 "Got packet on port %s: src=%u (id=%u)" %
162 (dst_if.name, payload_info.src, packet_index))
Klement Sekeraf62ae122016-10-11 11:47:09 +0200163 next_info = self.get_next_packet_info_for_interface2(
164 payload_info.src, dst_sw_if_index,
165 last_info[payload_info.src])
166 last_info[payload_info.src] = next_info
Damjan Marionf56b77a2016-10-03 19:44:57 +0200167 self.assertTrue(next_info is not None)
168 self.assertEqual(packet_index, next_info.index)
169 saved_packet = next_info.data
170 # Check standard fields
171 self.assertEqual(ip.src, saved_packet[IP].src)
172 self.assertEqual(ip.dst, saved_packet[IP].dst)
173 self.assertEqual(udp.sport, saved_packet[UDP].sport)
174 self.assertEqual(udp.dport, saved_packet[UDP].dport)
175 except:
Klement Sekera7bb873a2016-11-18 07:38:42 +0100176 self.logger.error(ppp("Unexpected or invalid packet:", packet))
Damjan Marionf56b77a2016-10-03 19:44:57 +0200177 raise
178 for i in self.interfaces:
Klement Sekeraf62ae122016-10-11 11:47:09 +0200179 remaining_packet = self.get_next_packet_info_for_interface2(
180 i.sw_if_index, dst_sw_if_index, last_info[i.sw_if_index])
Klement Sekera7bb873a2016-11-18 07:38:42 +0100181 self.assertTrue(remaining_packet is None,
182 "Interface %s: Packet expected from interface %s "
183 "didn't arrive" % (dst_if.name, i.name))
Damjan Marionf56b77a2016-10-03 19:44:57 +0200184
185 def test_fib(self):
Matej Klotton86d87c42016-11-11 11:38:55 +0100186 """ IPv4 FIB test
187
188 Test scenario:
189
190 - Create IPv4 stream for pg0 interface
Jan Geletye6c78ee2018-06-26 12:24:03 +0200191 - Create IPv4 tagged streams for pg1's and pg2's sub-interface.
Matej Klotton86d87c42016-11-11 11:38:55 +0100192 - Send and verify received packets on each interface.
193 """
Damjan Marionf56b77a2016-10-03 19:44:57 +0200194
Jan Geletye6c78ee2018-06-26 12:24:03 +0200195 pkts = self.create_stream(self.pg0)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200196 self.pg0.add_stream(pkts)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200197
Klement Sekeraf62ae122016-10-11 11:47:09 +0200198 for i in self.sub_interfaces:
Jan Geletye6c78ee2018-06-26 12:24:03 +0200199 pkts = self.create_stream(i)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200200 i.parent.add_stream(pkts)
201
202 self.pg_enable_capture(self.pg_interfaces)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200203 self.pg_start()
204
Klement Sekeraf62ae122016-10-11 11:47:09 +0200205 pkts = self.pg0.get_capture()
206 self.verify_capture(self.pg0, pkts)
207
208 for i in self.sub_interfaces:
209 pkts = i.parent.get_capture()
210 self.verify_capture(i, pkts)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200211
212
Matthew G Smith88d29a92019-07-17 10:01:17 -0500213class TestIPV4IfAddrRoute(VppTestCase):
214 """ IPv4 Interface Addr Route Test Case """
215
216 @classmethod
217 def setUpClass(cls):
218 super(TestIPV4IfAddrRoute, cls).setUpClass()
219
220 @classmethod
221 def tearDownClass(cls):
222 super(TestIPV4IfAddrRoute, cls).tearDownClass()
223
224 def setUp(self):
225 super(TestIPV4IfAddrRoute, self).setUp()
226
227 # create 1 pg interface
228 self.create_pg_interfaces(range(1))
229
230 for i in self.pg_interfaces:
231 i.admin_up()
232 i.config_ip4()
233 i.resolve_arp()
234
235 def tearDown(self):
236 super(TestIPV4IfAddrRoute, self).tearDown()
237 for i in self.pg_interfaces:
238 i.unconfig_ip4()
239 i.admin_down()
240
241 def test_ipv4_ifaddr_route(self):
242 """ IPv4 Interface Address Route test
243
244 Test scenario:
245
246 - Create loopback
247 - Configure IPv4 address on loopback
248 - Verify that address is not in the FIB
249 - Bring loopback up
250 - Verify that address is in the FIB now
251 - Bring loopback down
252 - Verify that address is not in the FIB anymore
253 - Bring loopback up
254 - Configure IPv4 address on loopback
255 - Verify that address is in the FIB now
256 """
257
258 # create a loopback and configure IPv4
259 loopbacks = self.create_loopback_interfaces(1)
260 lo_if = self.lo_interfaces[0]
261
262 lo_if.local_ip4_prefix_len = 32
263 lo_if.config_ip4()
264
265 # The intf was down when addr was added -> entry not in FIB
266 fib4_dump = self.vapi.ip_route_dump(0)
267 self.assertFalse(lo_if.is_ip4_entry_in_fib_dump(fib4_dump))
268
269 # When intf is brought up, entry is added
270 lo_if.admin_up()
271 fib4_dump = self.vapi.ip_route_dump(0)
272 self.assertTrue(lo_if.is_ip4_entry_in_fib_dump(fib4_dump))
273
274 # When intf is brought down, entry is removed
275 lo_if.admin_down()
276 fib4_dump = self.vapi.ip_route_dump(0)
277 self.assertFalse(lo_if.is_ip4_entry_in_fib_dump(fib4_dump))
278
279 # Remove addr, bring up interface, re-add -> entry in FIB
280 lo_if.unconfig_ip4()
281 lo_if.admin_up()
282 lo_if.config_ip4()
283 fib4_dump = self.vapi.ip_route_dump(0)
284 self.assertTrue(lo_if.is_ip4_entry_in_fib_dump(fib4_dump))
285
286
Jan Geletye6c78ee2018-06-26 12:24:03 +0200287class TestICMPEcho(VppTestCase):
288 """ ICMP Echo Test Case """
289
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700290 @classmethod
291 def setUpClass(cls):
292 super(TestICMPEcho, cls).setUpClass()
293
294 @classmethod
295 def tearDownClass(cls):
296 super(TestICMPEcho, cls).tearDownClass()
297
Jan Geletye6c78ee2018-06-26 12:24:03 +0200298 def setUp(self):
299 super(TestICMPEcho, self).setUp()
300
301 # create 1 pg interface
302 self.create_pg_interfaces(range(1))
303
304 for i in self.pg_interfaces:
305 i.admin_up()
306 i.config_ip4()
307 i.resolve_arp()
308
309 def tearDown(self):
310 super(TestICMPEcho, self).tearDown()
311 for i in self.pg_interfaces:
312 i.unconfig_ip4()
313 i.admin_down()
314
315 def test_icmp_echo(self):
316 """ VPP replies to ICMP Echo Request
317
318 Test scenario:
319
320 - Receive ICMP Echo Request message on pg0 interface.
321 - Check outgoing ICMP Echo Reply message on pg0 interface.
322 """
323
324 icmp_id = 0xb
325 icmp_seq = 5
326 icmp_load = '\x0a' * 18
327 p_echo_request = (Ether(src=self.pg0.remote_mac,
328 dst=self.pg0.local_mac) /
329 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
330 ICMP(id=icmp_id, seq=icmp_seq) /
331 Raw(load=icmp_load))
332
333 self.pg0.add_stream(p_echo_request)
334 self.pg_enable_capture(self.pg_interfaces)
335 self.pg_start()
336
337 rx = self.pg0.get_capture(1)
338 rx = rx[0]
339 ether = rx[Ether]
340 ipv4 = rx[IP]
341 icmp = rx[ICMP]
342
343 self.assertEqual(ether.src, self.pg0.local_mac)
344 self.assertEqual(ether.dst, self.pg0.remote_mac)
345
346 self.assertEqual(ipv4.src, self.pg0.local_ip4)
347 self.assertEqual(ipv4.dst, self.pg0.remote_ip4)
348
349 self.assertEqual(icmptypes[icmp.type], "echo-reply")
350 self.assertEqual(icmp.id, icmp_id)
351 self.assertEqual(icmp.seq, icmp_seq)
352 self.assertEqual(icmp[Raw].load, icmp_load)
353
354
Matej Klotton16a14cd2016-12-07 15:09:13 +0100355class TestIPv4FibCrud(VppTestCase):
356 """ FIB - add/update/delete - ip4 routes
357
358 Test scenario:
359 - add 1k,
360 - del 100,
361 - add new 1k,
362 - del 1.5k
363
Klement Sekerada505f62017-01-04 12:58:53 +0100364 ..note:: Python API is too slow to add many routes, needs replacement.
Matej Klotton16a14cd2016-12-07 15:09:13 +0100365 """
366
Neale Ranns097fa662018-05-01 05:17:55 -0700367 def config_fib_many_to_one(self, start_dest_addr, next_hop_addr,
368 count, start=0):
Matej Klotton16a14cd2016-12-07 15:09:13 +0100369 """
370
371 :param start_dest_addr:
372 :param next_hop_addr:
373 :param count:
374 :return list: added ips with 32 prefix
375 """
Neale Ranns097fa662018-05-01 05:17:55 -0700376 routes = []
377 for i in range(count):
378 r = VppIpRoute(self, start_dest_addr % (i + start), 32,
379 [VppRoutePath(next_hop_addr, 0xffffffff)])
380 r.add_vpp_config()
381 routes.append(r)
382 return routes
Matej Klotton16a14cd2016-12-07 15:09:13 +0100383
Neale Ranns097fa662018-05-01 05:17:55 -0700384 def unconfig_fib_many_to_one(self, start_dest_addr, next_hop_addr,
385 count, start=0):
Matej Klotton16a14cd2016-12-07 15:09:13 +0100386
Neale Ranns097fa662018-05-01 05:17:55 -0700387 routes = []
388 for i in range(count):
389 r = VppIpRoute(self, start_dest_addr % (i + start), 32,
390 [VppRoutePath(next_hop_addr, 0xffffffff)])
391 r.remove_vpp_config()
392 routes.append(r)
393 return routes
Matej Klotton16a14cd2016-12-07 15:09:13 +0100394
Neale Ranns097fa662018-05-01 05:17:55 -0700395 def create_stream(self, src_if, dst_if, routes, count):
Matej Klotton16a14cd2016-12-07 15:09:13 +0100396 pkts = []
397
398 for _ in range(count):
Neale Ranns097fa662018-05-01 05:17:55 -0700399 dst_addr = random.choice(routes).prefix.address
Klement Sekeradab231a2016-12-21 08:50:14 +0100400 info = self.create_packet_info(src_if, dst_if)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100401 payload = self.info_to_payload(info)
402 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
403 IP(src=src_if.remote_ip4, dst=dst_addr) /
404 UDP(sport=1234, dport=1234) /
405 Raw(payload))
406 info.data = p.copy()
Matej Klotton16a14cd2016-12-07 15:09:13 +0100407 self.extend_packet(p, random.choice(self.pg_if_packet_sizes))
408 pkts.append(p)
409
410 return pkts
411
412 def _find_ip_match(self, find_in, pkt):
413 for p in find_in:
Paul Vinciguerraeaea4212019-03-06 11:58:06 -0800414 if self.payload_to_info(p[Raw]) == \
415 self.payload_to_info(pkt[Raw]):
Matej Klotton16a14cd2016-12-07 15:09:13 +0100416 if p[IP].src != pkt[IP].src:
417 break
418 if p[IP].dst != pkt[IP].dst:
419 break
420 if p[UDP].sport != pkt[UDP].sport:
421 break
422 if p[UDP].dport != pkt[UDP].dport:
423 break
424 return p
425 return None
426
Matej Klotton16a14cd2016-12-07 15:09:13 +0100427 def verify_capture(self, dst_interface, received_pkts, expected_pkts):
428 self.assertEqual(len(received_pkts), len(expected_pkts))
429 to_verify = list(expected_pkts)
430 for p in received_pkts:
431 self.assertEqual(p.src, dst_interface.local_mac)
432 self.assertEqual(p.dst, dst_interface.remote_mac)
433 x = self._find_ip_match(to_verify, p)
434 to_verify.remove(x)
435 self.assertListEqual(to_verify, [])
436
Neale Ranns097fa662018-05-01 05:17:55 -0700437 def verify_route_dump(self, routes):
438 for r in routes:
439 self.assertTrue(find_route(self, r.prefix.address, r.prefix.len))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100440
Neale Ranns097fa662018-05-01 05:17:55 -0700441 def verify_not_in_route_dump(self, routes):
442 for r in routes:
443 self.assertFalse(find_route(self, r.prefix.address, r.prefix.len))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100444
445 @classmethod
446 def setUpClass(cls):
447 """
448 #. Create and initialize 3 pg interfaces.
449 #. initialize class attributes configured_routes and deleted_routes
450 to store information between tests.
451 """
452 super(TestIPv4FibCrud, cls).setUpClass()
453
454 try:
455 # create 3 pg interfaces
456 cls.create_pg_interfaces(range(3))
457
458 cls.interfaces = list(cls.pg_interfaces)
459
460 # setup all interfaces
461 for i in cls.interfaces:
462 i.admin_up()
463 i.config_ip4()
464 i.resolve_arp()
465
466 cls.configured_routes = []
467 cls.deleted_routes = []
468 cls.pg_if_packet_sizes = [64, 512, 1518, 9018]
469
470 except Exception:
471 super(TestIPv4FibCrud, cls).tearDownClass()
472 raise
473
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700474 @classmethod
475 def tearDownClass(cls):
476 super(TestIPv4FibCrud, cls).tearDownClass()
477
Matej Klotton16a14cd2016-12-07 15:09:13 +0100478 def setUp(self):
479 super(TestIPv4FibCrud, self).setUp()
Klement Sekeradab231a2016-12-21 08:50:14 +0100480 self.reset_packet_infos()
Matej Klotton16a14cd2016-12-07 15:09:13 +0100481
Paul Vinciguerra4eed7472018-12-16 14:52:36 -0800482 self.configured_routes = []
483 self.deleted_routes = []
484
Matej Klotton16a14cd2016-12-07 15:09:13 +0100485 def test_1_add_routes(self):
Neale Ranns097fa662018-05-01 05:17:55 -0700486 """ Add 1k routes """
Matej Klotton16a14cd2016-12-07 15:09:13 +0100487
Neale Ranns097fa662018-05-01 05:17:55 -0700488 # add 100 routes check with traffic script.
Matej Klotton16a14cd2016-12-07 15:09:13 +0100489 self.configured_routes.extend(self.config_fib_many_to_one(
Neale Ranns097fa662018-05-01 05:17:55 -0700490 "10.0.0.%d", self.pg0.remote_ip4, 100))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100491
Neale Ranns097fa662018-05-01 05:17:55 -0700492 self.verify_route_dump(self.configured_routes)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100493
494 self.stream_1 = self.create_stream(
495 self.pg1, self.pg0, self.configured_routes, 100)
496 self.stream_2 = self.create_stream(
497 self.pg2, self.pg0, self.configured_routes, 100)
498 self.pg1.add_stream(self.stream_1)
499 self.pg2.add_stream(self.stream_2)
500
501 self.pg_enable_capture(self.pg_interfaces)
502 self.pg_start()
503
Klement Sekeradab231a2016-12-21 08:50:14 +0100504 pkts = self.pg0.get_capture(len(self.stream_1) + len(self.stream_2))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100505 self.verify_capture(self.pg0, pkts, self.stream_1 + self.stream_2)
506
Matej Klotton16a14cd2016-12-07 15:09:13 +0100507 def test_2_del_routes(self):
508 """ Delete 100 routes
509
510 - delete 10 routes check with traffic script.
511 """
Paul Vinciguerra4eed7472018-12-16 14:52:36 -0800512 # config 1M FIB entries
513 self.configured_routes.extend(self.config_fib_many_to_one(
Neale Ranns097fa662018-05-01 05:17:55 -0700514 "10.0.0.%d", self.pg0.remote_ip4, 100))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100515 self.deleted_routes.extend(self.unconfig_fib_many_to_one(
Neale Ranns097fa662018-05-01 05:17:55 -0700516 "10.0.0.%d", self.pg0.remote_ip4, 10, start=10))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100517 for x in self.deleted_routes:
518 self.configured_routes.remove(x)
519
Neale Ranns097fa662018-05-01 05:17:55 -0700520 self.verify_route_dump(self.configured_routes)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100521
522 self.stream_1 = self.create_stream(
523 self.pg1, self.pg0, self.configured_routes, 100)
524 self.stream_2 = self.create_stream(
525 self.pg2, self.pg0, self.configured_routes, 100)
526 self.stream_3 = self.create_stream(
527 self.pg1, self.pg0, self.deleted_routes, 100)
528 self.stream_4 = self.create_stream(
529 self.pg2, self.pg0, self.deleted_routes, 100)
530 self.pg1.add_stream(self.stream_1 + self.stream_3)
531 self.pg2.add_stream(self.stream_2 + self.stream_4)
532 self.pg_enable_capture(self.pg_interfaces)
533 self.pg_start()
534
Klement Sekeradab231a2016-12-21 08:50:14 +0100535 pkts = self.pg0.get_capture(len(self.stream_1) + len(self.stream_2))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100536 self.verify_capture(self.pg0, pkts, self.stream_1 + self.stream_2)
537
538 def test_3_add_new_routes(self):
539 """ Add 1k routes
540
541 - re-add 5 routes check with traffic script.
542 - add 100 routes check with traffic script.
543 """
Paul Vinciguerra4eed7472018-12-16 14:52:36 -0800544 # config 1M FIB entries
545 self.configured_routes.extend(self.config_fib_many_to_one(
Neale Ranns097fa662018-05-01 05:17:55 -0700546 "10.0.0.%d", self.pg0.remote_ip4, 100))
Paul Vinciguerra4eed7472018-12-16 14:52:36 -0800547 self.deleted_routes.extend(self.unconfig_fib_many_to_one(
Neale Ranns097fa662018-05-01 05:17:55 -0700548 "10.0.0.%d", self.pg0.remote_ip4, 10, start=10))
Paul Vinciguerra4eed7472018-12-16 14:52:36 -0800549 for x in self.deleted_routes:
550 self.configured_routes.remove(x)
551
Matej Klotton16a14cd2016-12-07 15:09:13 +0100552 tmp = self.config_fib_many_to_one(
Neale Ranns097fa662018-05-01 05:17:55 -0700553 "10.0.0.%d", self.pg0.remote_ip4, 5, start=10)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100554 self.configured_routes.extend(tmp)
555 for x in tmp:
556 self.deleted_routes.remove(x)
557
558 self.configured_routes.extend(self.config_fib_many_to_one(
Neale Ranns097fa662018-05-01 05:17:55 -0700559 "10.0.1.%d", self.pg0.remote_ip4, 100))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100560
Neale Ranns097fa662018-05-01 05:17:55 -0700561 self.verify_route_dump(self.configured_routes)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100562
563 self.stream_1 = self.create_stream(
564 self.pg1, self.pg0, self.configured_routes, 300)
565 self.stream_2 = self.create_stream(
566 self.pg2, self.pg0, self.configured_routes, 300)
567 self.stream_3 = self.create_stream(
568 self.pg1, self.pg0, self.deleted_routes, 100)
569 self.stream_4 = self.create_stream(
570 self.pg2, self.pg0, self.deleted_routes, 100)
571
572 self.pg1.add_stream(self.stream_1 + self.stream_3)
573 self.pg2.add_stream(self.stream_2 + self.stream_4)
574 self.pg_enable_capture(self.pg_interfaces)
575 self.pg_start()
576
Klement Sekeradab231a2016-12-21 08:50:14 +0100577 pkts = self.pg0.get_capture(len(self.stream_1) + len(self.stream_2))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100578 self.verify_capture(self.pg0, pkts, self.stream_1 + self.stream_2)
579
Neale Ranns097fa662018-05-01 05:17:55 -0700580 # delete 5 routes check with traffic script.
581 # add 100 routes check with traffic script.
Matej Klotton16a14cd2016-12-07 15:09:13 +0100582 self.deleted_routes.extend(self.unconfig_fib_many_to_one(
Neale Ranns097fa662018-05-01 05:17:55 -0700583 "10.0.0.%d", self.pg0.remote_ip4, 15))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100584 self.deleted_routes.extend(self.unconfig_fib_many_to_one(
Neale Ranns097fa662018-05-01 05:17:55 -0700585 "10.0.0.%d", self.pg0.remote_ip4, 85))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100586 self.deleted_routes.extend(self.unconfig_fib_many_to_one(
Neale Ranns097fa662018-05-01 05:17:55 -0700587 "10.0.1.%d", self.pg0.remote_ip4, 100))
588 self.verify_not_in_route_dump(self.deleted_routes)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100589
590
Neale Ranns37be7362017-02-21 17:30:26 -0800591class TestIPNull(VppTestCase):
592 """ IPv4 routes via NULL """
593
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700594 @classmethod
595 def setUpClass(cls):
596 super(TestIPNull, cls).setUpClass()
597
598 @classmethod
599 def tearDownClass(cls):
600 super(TestIPNull, cls).tearDownClass()
601
Neale Ranns37be7362017-02-21 17:30:26 -0800602 def setUp(self):
603 super(TestIPNull, self).setUp()
604
605 # create 2 pg interfaces
Neale Ranns3b93be52018-09-07 01:48:54 -0700606 self.create_pg_interfaces(range(2))
Neale Ranns37be7362017-02-21 17:30:26 -0800607
608 for i in self.pg_interfaces:
609 i.admin_up()
610 i.config_ip4()
611 i.resolve_arp()
612
613 def tearDown(self):
614 super(TestIPNull, self).tearDown()
615 for i in self.pg_interfaces:
616 i.unconfig_ip4()
617 i.admin_down()
618
619 def test_ip_null(self):
620 """ IP NULL route """
621
622 #
623 # A route via IP NULL that will reply with ICMP unreachables
624 #
Neale Ranns097fa662018-05-01 05:17:55 -0700625 ip_unreach = VppIpRoute(
626 self, "10.0.0.1", 32,
627 [VppRoutePath("0.0.0.0",
628 0xffffffff,
629 type=FibPathType.FIB_PATH_TYPE_ICMP_UNREACH)])
Neale Ranns37be7362017-02-21 17:30:26 -0800630 ip_unreach.add_vpp_config()
631
632 p_unreach = (Ether(src=self.pg0.remote_mac,
633 dst=self.pg0.local_mac) /
634 IP(src=self.pg0.remote_ip4, dst="10.0.0.1") /
635 UDP(sport=1234, dport=1234) /
636 Raw('\xa5' * 100))
Neale Ranns37be7362017-02-21 17:30:26 -0800637 self.pg0.add_stream(p_unreach)
638 self.pg_enable_capture(self.pg_interfaces)
639 self.pg_start()
640
641 rx = self.pg0.get_capture(1)
642 rx = rx[0]
643 icmp = rx[ICMP]
644
645 self.assertEqual(icmptypes[icmp.type], "dest-unreach")
646 self.assertEqual(icmpcodes[icmp.type][icmp.code], "host-unreachable")
647 self.assertEqual(icmp.src, self.pg0.remote_ip4)
648 self.assertEqual(icmp.dst, "10.0.0.1")
649
650 #
651 # ICMP replies are rate limited. so sit and spin.
652 #
653 self.sleep(1)
654
655 #
656 # A route via IP NULL that will reply with ICMP prohibited
657 #
Neale Ranns097fa662018-05-01 05:17:55 -0700658 ip_prohibit = VppIpRoute(
659 self, "10.0.0.2", 32,
660 [VppRoutePath("0.0.0.0",
661 0xffffffff,
662 type=FibPathType.FIB_PATH_TYPE_ICMP_PROHIBIT)])
Neale Ranns37be7362017-02-21 17:30:26 -0800663 ip_prohibit.add_vpp_config()
664
665 p_prohibit = (Ether(src=self.pg0.remote_mac,
666 dst=self.pg0.local_mac) /
667 IP(src=self.pg0.remote_ip4, dst="10.0.0.2") /
668 UDP(sport=1234, dport=1234) /
669 Raw('\xa5' * 100))
670
671 self.pg0.add_stream(p_prohibit)
672 self.pg_enable_capture(self.pg_interfaces)
673 self.pg_start()
674
675 rx = self.pg0.get_capture(1)
676
677 rx = rx[0]
678 icmp = rx[ICMP]
679
680 self.assertEqual(icmptypes[icmp.type], "dest-unreach")
681 self.assertEqual(icmpcodes[icmp.type][icmp.code], "host-prohibited")
682 self.assertEqual(icmp.src, self.pg0.remote_ip4)
683 self.assertEqual(icmp.dst, "10.0.0.2")
684
Neale Ranns3b93be52018-09-07 01:48:54 -0700685 def test_ip_drop(self):
686 """ IP Drop Routes """
687
688 p = (Ether(src=self.pg0.remote_mac,
689 dst=self.pg0.local_mac) /
690 IP(src=self.pg0.remote_ip4, dst="1.1.1.1") /
691 UDP(sport=1234, dport=1234) /
692 Raw('\xa5' * 100))
693
694 r1 = VppIpRoute(self, "1.1.1.0", 24,
695 [VppRoutePath(self.pg1.remote_ip4,
696 self.pg1.sw_if_index)])
697 r1.add_vpp_config()
698
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400699 rx = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1)
Neale Ranns3b93be52018-09-07 01:48:54 -0700700
701 #
702 # insert a more specific as a drop
703 #
Neale Ranns097fa662018-05-01 05:17:55 -0700704 r2 = VppIpRoute(self, "1.1.1.1", 32,
705 [VppRoutePath("0.0.0.0",
706 0xffffffff,
707 type=FibPathType.FIB_PATH_TYPE_DROP)])
Neale Ranns3b93be52018-09-07 01:48:54 -0700708 r2.add_vpp_config()
709
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400710 self.send_and_assert_no_replies(self.pg0, p * NUM_PKTS, "Drop Route")
Neale Ranns3b93be52018-09-07 01:48:54 -0700711 r2.remove_vpp_config()
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400712 rx = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1)
Neale Ranns3b93be52018-09-07 01:48:54 -0700713
Neale Ranns37be7362017-02-21 17:30:26 -0800714
Neale Ranns180279b2017-03-16 15:49:09 -0400715class TestIPDisabled(VppTestCase):
716 """ IPv4 disabled """
717
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700718 @classmethod
719 def setUpClass(cls):
720 super(TestIPDisabled, cls).setUpClass()
721
722 @classmethod
723 def tearDownClass(cls):
724 super(TestIPDisabled, cls).tearDownClass()
725
Neale Ranns180279b2017-03-16 15:49:09 -0400726 def setUp(self):
727 super(TestIPDisabled, self).setUp()
728
729 # create 2 pg interfaces
730 self.create_pg_interfaces(range(2))
731
732 # PG0 is IP enalbed
733 self.pg0.admin_up()
734 self.pg0.config_ip4()
735 self.pg0.resolve_arp()
736
737 # PG 1 is not IP enabled
738 self.pg1.admin_up()
739
740 def tearDown(self):
741 super(TestIPDisabled, self).tearDown()
742 for i in self.pg_interfaces:
743 i.unconfig_ip4()
744 i.admin_down()
745
Neale Ranns180279b2017-03-16 15:49:09 -0400746 def test_ip_disabled(self):
747 """ IP Disabled """
748
749 #
750 # An (S,G).
751 # one accepting interface, pg0, 2 forwarding interfaces
752 #
753 route_232_1_1_1 = VppIpMRoute(
754 self,
755 "0.0.0.0",
756 "232.1.1.1", 32,
757 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
758 [VppMRoutePath(self.pg1.sw_if_index,
759 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
760 VppMRoutePath(self.pg0.sw_if_index,
761 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
762 route_232_1_1_1.add_vpp_config()
763
764 pu = (Ether(src=self.pg1.remote_mac,
765 dst=self.pg1.local_mac) /
766 IP(src="10.10.10.10", dst=self.pg0.remote_ip4) /
767 UDP(sport=1234, dport=1234) /
768 Raw('\xa5' * 100))
769 pm = (Ether(src=self.pg1.remote_mac,
770 dst=self.pg1.local_mac) /
771 IP(src="10.10.10.10", dst="232.1.1.1") /
772 UDP(sport=1234, dport=1234) /
773 Raw('\xa5' * 100))
774
775 #
776 # PG1 does not forward IP traffic
777 #
778 self.send_and_assert_no_replies(self.pg1, pu, "IP disabled")
779 self.send_and_assert_no_replies(self.pg1, pm, "IP disabled")
780
781 #
782 # IP enable PG1
783 #
784 self.pg1.config_ip4()
785
786 #
787 # Now we get packets through
788 #
789 self.pg1.add_stream(pu)
790 self.pg_enable_capture(self.pg_interfaces)
791 self.pg_start()
792 rx = self.pg0.get_capture(1)
793
794 self.pg1.add_stream(pm)
795 self.pg_enable_capture(self.pg_interfaces)
796 self.pg_start()
797 rx = self.pg0.get_capture(1)
798
799 #
800 # Disable PG1
801 #
802 self.pg1.unconfig_ip4()
803
804 #
805 # PG1 does not forward IP traffic
806 #
807 self.send_and_assert_no_replies(self.pg1, pu, "IP disabled")
808 self.send_and_assert_no_replies(self.pg1, pm, "IP disabled")
809
810
Neale Ranns9a69a602017-03-26 10:56:33 -0700811class TestIPSubNets(VppTestCase):
812 """ IPv4 Subnets """
813
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700814 @classmethod
815 def setUpClass(cls):
816 super(TestIPSubNets, cls).setUpClass()
817
818 @classmethod
819 def tearDownClass(cls):
820 super(TestIPSubNets, cls).tearDownClass()
821
Neale Ranns9a69a602017-03-26 10:56:33 -0700822 def setUp(self):
823 super(TestIPSubNets, self).setUp()
824
825 # create a 2 pg interfaces
826 self.create_pg_interfaces(range(2))
827
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700828 # pg0 we will use to experiment
Neale Ranns9a69a602017-03-26 10:56:33 -0700829 self.pg0.admin_up()
830
831 # pg1 is setup normally
832 self.pg1.admin_up()
833 self.pg1.config_ip4()
834 self.pg1.resolve_arp()
835
836 def tearDown(self):
837 super(TestIPSubNets, self).tearDown()
838 for i in self.pg_interfaces:
839 i.admin_down()
840
Neale Ranns9a69a602017-03-26 10:56:33 -0700841 def test_ip_sub_nets(self):
842 """ IP Sub Nets """
843
844 #
845 # Configure a covering route to forward so we know
846 # when we are dropping
847 #
848 cover_route = VppIpRoute(self, "10.0.0.0", 8,
849 [VppRoutePath(self.pg1.remote_ip4,
850 self.pg1.sw_if_index)])
851 cover_route.add_vpp_config()
852
853 p = (Ether(src=self.pg1.remote_mac,
854 dst=self.pg1.local_mac) /
855 IP(dst="10.10.10.10", src=self.pg0.local_ip4) /
856 UDP(sport=1234, dport=1234) /
857 Raw('\xa5' * 100))
858
859 self.pg1.add_stream(p)
860 self.pg_enable_capture(self.pg_interfaces)
861 self.pg_start()
862 rx = self.pg1.get_capture(1)
863
864 #
865 # Configure some non-/24 subnets on an IP interface
866 #
867 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.10.10.10")
868
Ole Troan9a475372019-03-05 16:58:24 +0100869 self.vapi.sw_interface_add_del_address(
Ole Trøan3b0d7e42019-03-15 16:14:41 +0000870 sw_if_index=self.pg0.sw_if_index, address=ip_addr_n,
871 address_length=16)
Neale Ranns9a69a602017-03-26 10:56:33 -0700872
873 pn = (Ether(src=self.pg1.remote_mac,
874 dst=self.pg1.local_mac) /
875 IP(dst="10.10.0.0", src=self.pg0.local_ip4) /
876 UDP(sport=1234, dport=1234) /
877 Raw('\xa5' * 100))
878 pb = (Ether(src=self.pg1.remote_mac,
879 dst=self.pg1.local_mac) /
880 IP(dst="10.10.255.255", src=self.pg0.local_ip4) /
881 UDP(sport=1234, dport=1234) /
882 Raw('\xa5' * 100))
883
884 self.send_and_assert_no_replies(self.pg1, pn, "IP Network address")
885 self.send_and_assert_no_replies(self.pg1, pb, "IP Broadcast address")
886
887 # remove the sub-net and we are forwarding via the cover again
Ole Troan9a475372019-03-05 16:58:24 +0100888 self.vapi.sw_interface_add_del_address(
Ole Trøan3b0d7e42019-03-15 16:14:41 +0000889 sw_if_index=self.pg0.sw_if_index, address=ip_addr_n,
890 address_length=16, is_add=0)
Neale Ranns9a69a602017-03-26 10:56:33 -0700891 self.pg1.add_stream(pn)
892 self.pg_enable_capture(self.pg_interfaces)
893 self.pg_start()
894 rx = self.pg1.get_capture(1)
895 self.pg1.add_stream(pb)
896 self.pg_enable_capture(self.pg_interfaces)
897 self.pg_start()
898 rx = self.pg1.get_capture(1)
899
900 #
901 # A /31 is a special case where the 'other-side' is an attached host
902 # packets to that peer generate ARP requests
903 #
904 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.10.10.10")
905
Ole Troan9a475372019-03-05 16:58:24 +0100906 self.vapi.sw_interface_add_del_address(
Ole Trøan3b0d7e42019-03-15 16:14:41 +0000907 sw_if_index=self.pg0.sw_if_index, address=ip_addr_n,
908 address_length=31)
Neale Ranns9a69a602017-03-26 10:56:33 -0700909
910 pn = (Ether(src=self.pg1.remote_mac,
911 dst=self.pg1.local_mac) /
912 IP(dst="10.10.10.11", src=self.pg0.local_ip4) /
913 UDP(sport=1234, dport=1234) /
914 Raw('\xa5' * 100))
915
916 self.pg1.add_stream(pn)
917 self.pg_enable_capture(self.pg_interfaces)
918 self.pg_start()
919 rx = self.pg0.get_capture(1)
920 rx[ARP]
921
922 # remove the sub-net and we are forwarding via the cover again
Ole Troan9a475372019-03-05 16:58:24 +0100923 self.vapi.sw_interface_add_del_address(
Ole Trøan3b0d7e42019-03-15 16:14:41 +0000924 sw_if_index=self.pg0.sw_if_index, address=ip_addr_n,
925 address_length=31, is_add=0)
Neale Ranns9a69a602017-03-26 10:56:33 -0700926 self.pg1.add_stream(pn)
927 self.pg_enable_capture(self.pg_interfaces)
928 self.pg_start()
929 rx = self.pg1.get_capture(1)
930
931
Neale Ranns227038a2017-04-21 01:07:59 -0700932class TestIPLoadBalance(VppTestCase):
933 """ IPv4 Load-Balancing """
934
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700935 @classmethod
936 def setUpClass(cls):
937 super(TestIPLoadBalance, cls).setUpClass()
938
939 @classmethod
940 def tearDownClass(cls):
941 super(TestIPLoadBalance, cls).tearDownClass()
942
Neale Ranns227038a2017-04-21 01:07:59 -0700943 def setUp(self):
944 super(TestIPLoadBalance, self).setUp()
945
946 self.create_pg_interfaces(range(5))
Neale Ranns15002542017-09-10 04:39:11 -0700947 mpls_tbl = VppMplsTable(self, 0)
948 mpls_tbl.add_vpp_config()
Neale Ranns227038a2017-04-21 01:07:59 -0700949
950 for i in self.pg_interfaces:
951 i.admin_up()
952 i.config_ip4()
953 i.resolve_arp()
Neale Ranns71275e32017-05-25 12:38:58 -0700954 i.enable_mpls()
Neale Ranns227038a2017-04-21 01:07:59 -0700955
956 def tearDown(self):
Neale Ranns227038a2017-04-21 01:07:59 -0700957 for i in self.pg_interfaces:
Neale Ranns71275e32017-05-25 12:38:58 -0700958 i.disable_mpls()
Neale Ranns227038a2017-04-21 01:07:59 -0700959 i.unconfig_ip4()
960 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -0700961 super(TestIPLoadBalance, self).tearDown()
Neale Ranns227038a2017-04-21 01:07:59 -0700962
963 def send_and_expect_load_balancing(self, input, pkts, outputs):
964 input.add_stream(pkts)
965 self.pg_enable_capture(self.pg_interfaces)
966 self.pg_start()
Neale Ranns63480742019-03-13 06:41:52 -0700967 rxs = []
Neale Ranns227038a2017-04-21 01:07:59 -0700968 for oo in outputs:
969 rx = oo._get_capture(1)
970 self.assertNotEqual(0, len(rx))
Neale Ranns63480742019-03-13 06:41:52 -0700971 for r in rx:
972 rxs.append(r)
973 return rxs
Neale Ranns227038a2017-04-21 01:07:59 -0700974
Neale Ranns42e6b092017-07-31 02:56:03 -0700975 def send_and_expect_one_itf(self, input, pkts, itf):
976 input.add_stream(pkts)
977 self.pg_enable_capture(self.pg_interfaces)
978 self.pg_start()
979 rx = itf.get_capture(len(pkts))
980
Neale Ranns227038a2017-04-21 01:07:59 -0700981 def test_ip_load_balance(self):
982 """ IP Load-Balancing """
983
984 #
985 # An array of packets that differ only in the destination port
986 #
Neale Ranns71275e32017-05-25 12:38:58 -0700987 port_ip_pkts = []
988 port_mpls_pkts = []
Neale Ranns227038a2017-04-21 01:07:59 -0700989
990 #
991 # An array of packets that differ only in the source address
992 #
Neale Ranns71275e32017-05-25 12:38:58 -0700993 src_ip_pkts = []
994 src_mpls_pkts = []
Neale Ranns227038a2017-04-21 01:07:59 -0700995
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400996 for ii in range(NUM_PKTS):
Neale Ranns71275e32017-05-25 12:38:58 -0700997 port_ip_hdr = (IP(dst="10.0.0.1", src="20.0.0.1") /
998 UDP(sport=1234, dport=1234 + ii) /
999 Raw('\xa5' * 100))
1000 port_ip_pkts.append((Ether(src=self.pg0.remote_mac,
1001 dst=self.pg0.local_mac) /
1002 port_ip_hdr))
1003 port_mpls_pkts.append((Ether(src=self.pg0.remote_mac,
1004 dst=self.pg0.local_mac) /
1005 MPLS(label=66, ttl=2) /
1006 port_ip_hdr))
1007
1008 src_ip_hdr = (IP(dst="10.0.0.1", src="20.0.0.%d" % ii) /
1009 UDP(sport=1234, dport=1234) /
1010 Raw('\xa5' * 100))
1011 src_ip_pkts.append((Ether(src=self.pg0.remote_mac,
1012 dst=self.pg0.local_mac) /
1013 src_ip_hdr))
1014 src_mpls_pkts.append((Ether(src=self.pg0.remote_mac,
1015 dst=self.pg0.local_mac) /
1016 MPLS(label=66, ttl=2) /
1017 src_ip_hdr))
Neale Ranns227038a2017-04-21 01:07:59 -07001018
1019 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1020 [VppRoutePath(self.pg1.remote_ip4,
1021 self.pg1.sw_if_index),
1022 VppRoutePath(self.pg2.remote_ip4,
1023 self.pg2.sw_if_index)])
1024 route_10_0_0_1.add_vpp_config()
1025
Neale Ranns71275e32017-05-25 12:38:58 -07001026 binding = VppMplsIpBind(self, 66, "10.0.0.1", 32)
1027 binding.add_vpp_config()
1028
Neale Ranns227038a2017-04-21 01:07:59 -07001029 #
1030 # inject the packet on pg0 - expect load-balancing across the 2 paths
1031 # - since the default hash config is to use IP src,dst and port
1032 # src,dst
1033 # We are not going to ensure equal amounts of packets across each link,
1034 # since the hash algorithm is statistical and therefore this can never
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001035 # be guaranteed. But with 64 different packets we do expect some
Neale Ranns227038a2017-04-21 01:07:59 -07001036 # balancing. So instead just ensure there is traffic on each link.
1037 #
Neale Ranns71275e32017-05-25 12:38:58 -07001038 self.send_and_expect_load_balancing(self.pg0, port_ip_pkts,
Neale Ranns227038a2017-04-21 01:07:59 -07001039 [self.pg1, self.pg2])
Neale Ranns71275e32017-05-25 12:38:58 -07001040 self.send_and_expect_load_balancing(self.pg0, src_ip_pkts,
1041 [self.pg1, self.pg2])
1042 self.send_and_expect_load_balancing(self.pg0, port_mpls_pkts,
1043 [self.pg1, self.pg2])
1044 self.send_and_expect_load_balancing(self.pg0, src_mpls_pkts,
Neale Ranns227038a2017-04-21 01:07:59 -07001045 [self.pg1, self.pg2])
1046
1047 #
1048 # change the flow hash config so it's only IP src,dst
1049 # - now only the stream with differing source address will
1050 # load-balance
1051 #
Ole Troana5b2eec2019-03-11 19:23:25 +01001052 self.vapi.set_ip_flow_hash(vrf_id=0, src=1, dst=1, sport=0, dport=0)
Neale Ranns227038a2017-04-21 01:07:59 -07001053
Neale Ranns71275e32017-05-25 12:38:58 -07001054 self.send_and_expect_load_balancing(self.pg0, src_ip_pkts,
1055 [self.pg1, self.pg2])
1056 self.send_and_expect_load_balancing(self.pg0, src_mpls_pkts,
Neale Ranns227038a2017-04-21 01:07:59 -07001057 [self.pg1, self.pg2])
1058
Neale Ranns42e6b092017-07-31 02:56:03 -07001059 self.send_and_expect_one_itf(self.pg0, port_ip_pkts, self.pg2)
Neale Ranns227038a2017-04-21 01:07:59 -07001060
1061 #
1062 # change the flow hash config back to defaults
1063 #
Ole Troana5b2eec2019-03-11 19:23:25 +01001064 self.vapi.set_ip_flow_hash(vrf_id=0, src=1, dst=1, sport=1, dport=1)
Neale Ranns227038a2017-04-21 01:07:59 -07001065
1066 #
1067 # Recursive prefixes
1068 # - testing that 2 stages of load-balancing occurs and there is no
1069 # polarisation (i.e. only 2 of 4 paths are used)
1070 #
1071 port_pkts = []
1072 src_pkts = []
1073
1074 for ii in range(257):
1075 port_pkts.append((Ether(src=self.pg0.remote_mac,
1076 dst=self.pg0.local_mac) /
1077 IP(dst="1.1.1.1", src="20.0.0.1") /
1078 UDP(sport=1234, dport=1234 + ii) /
1079 Raw('\xa5' * 100)))
1080 src_pkts.append((Ether(src=self.pg0.remote_mac,
1081 dst=self.pg0.local_mac) /
1082 IP(dst="1.1.1.1", src="20.0.0.%d" % ii) /
1083 UDP(sport=1234, dport=1234) /
1084 Raw('\xa5' * 100)))
1085
1086 route_10_0_0_2 = VppIpRoute(self, "10.0.0.2", 32,
1087 [VppRoutePath(self.pg3.remote_ip4,
1088 self.pg3.sw_if_index),
1089 VppRoutePath(self.pg4.remote_ip4,
1090 self.pg4.sw_if_index)])
1091 route_10_0_0_2.add_vpp_config()
1092
1093 route_1_1_1_1 = VppIpRoute(self, "1.1.1.1", 32,
1094 [VppRoutePath("10.0.0.2", 0xffffffff),
1095 VppRoutePath("10.0.0.1", 0xffffffff)])
1096 route_1_1_1_1.add_vpp_config()
1097
1098 #
1099 # inject the packet on pg0 - expect load-balancing across all 4 paths
1100 #
1101 self.vapi.cli("clear trace")
1102 self.send_and_expect_load_balancing(self.pg0, port_pkts,
1103 [self.pg1, self.pg2,
1104 self.pg3, self.pg4])
1105 self.send_and_expect_load_balancing(self.pg0, src_pkts,
1106 [self.pg1, self.pg2,
1107 self.pg3, self.pg4])
1108
Neale Ranns42e6b092017-07-31 02:56:03 -07001109 #
Neale Ranns63480742019-03-13 06:41:52 -07001110 # bring down pg1 expect LB to adjust to use only those that are pu
1111 #
1112 self.pg1.link_down()
1113
1114 rx = self.send_and_expect_load_balancing(self.pg0, src_pkts,
1115 [self.pg2, self.pg3,
1116 self.pg4])
1117 self.assertEqual(len(src_pkts), len(rx))
1118
1119 #
1120 # bring down pg2 expect LB to adjust to use only those that are pu
1121 #
1122 self.pg2.link_down()
1123
1124 rx = self.send_and_expect_load_balancing(self.pg0, src_pkts,
1125 [self.pg3, self.pg4])
1126 self.assertEqual(len(src_pkts), len(rx))
1127
1128 #
1129 # bring the links back up - expect LB over all again
1130 #
1131 self.pg1.link_up()
1132 self.pg2.link_up()
1133
1134 rx = self.send_and_expect_load_balancing(self.pg0, src_pkts,
1135 [self.pg1, self.pg2,
1136 self.pg3, self.pg4])
1137 self.assertEqual(len(src_pkts), len(rx))
1138
1139 #
1140 # The same link-up/down but this time admin state
1141 #
1142 self.pg1.admin_down()
1143 self.pg2.admin_down()
1144 rx = self.send_and_expect_load_balancing(self.pg0, src_pkts,
1145 [self.pg3, self.pg4])
1146 self.assertEqual(len(src_pkts), len(rx))
1147 self.pg1.admin_up()
1148 self.pg2.admin_up()
1149 self.pg1.resolve_arp()
1150 self.pg2.resolve_arp()
1151 rx = self.send_and_expect_load_balancing(self.pg0, src_pkts,
1152 [self.pg1, self.pg2,
1153 self.pg3, self.pg4])
1154 self.assertEqual(len(src_pkts), len(rx))
1155
1156 #
Neale Ranns42e6b092017-07-31 02:56:03 -07001157 # Recursive prefixes
1158 # - testing that 2 stages of load-balancing, no choices
1159 #
1160 port_pkts = []
1161
1162 for ii in range(257):
1163 port_pkts.append((Ether(src=self.pg0.remote_mac,
1164 dst=self.pg0.local_mac) /
1165 IP(dst="1.1.1.2", src="20.0.0.2") /
1166 UDP(sport=1234, dport=1234 + ii) /
1167 Raw('\xa5' * 100)))
1168
1169 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
1170 [VppRoutePath(self.pg3.remote_ip4,
1171 self.pg3.sw_if_index)])
1172 route_10_0_0_3.add_vpp_config()
1173
1174 route_1_1_1_2 = VppIpRoute(self, "1.1.1.2", 32,
1175 [VppRoutePath("10.0.0.3", 0xffffffff)])
1176 route_1_1_1_2.add_vpp_config()
1177
1178 #
Neale Ranns63480742019-03-13 06:41:52 -07001179 # inject the packet on pg0 - rx only on via routes output interface
Neale Ranns42e6b092017-07-31 02:56:03 -07001180 #
1181 self.vapi.cli("clear trace")
1182 self.send_and_expect_one_itf(self.pg0, port_pkts, self.pg3)
1183
Neale Ranns63480742019-03-13 06:41:52 -07001184 #
1185 # Add a LB route in the presence of a down link - expect no
1186 # packets over the down link
1187 #
1188 self.pg3.link_down()
1189
1190 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
1191 [VppRoutePath(self.pg3.remote_ip4,
1192 self.pg3.sw_if_index),
1193 VppRoutePath(self.pg4.remote_ip4,
1194 self.pg4.sw_if_index)])
1195 route_10_0_0_3.add_vpp_config()
1196
1197 port_pkts = []
1198 for ii in range(257):
1199 port_pkts.append(Ether(src=self.pg0.remote_mac,
1200 dst=self.pg0.local_mac) /
1201 IP(dst="10.0.0.3", src="20.0.0.2") /
1202 UDP(sport=1234, dport=1234 + ii) /
1203 Raw('\xa5' * 100))
1204
1205 self.send_and_expect_one_itf(self.pg0, port_pkts, self.pg4)
1206
1207 # bring the link back up
1208 self.pg3.link_up()
1209
1210 rx = self.send_and_expect_load_balancing(self.pg0, port_pkts,
1211 [self.pg3, self.pg4])
1212 self.assertEqual(len(src_pkts), len(rx))
1213
Neale Ranns30d0fd42017-05-30 07:30:04 -07001214
1215class TestIPVlan0(VppTestCase):
1216 """ IPv4 VLAN-0 """
1217
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001218 @classmethod
1219 def setUpClass(cls):
1220 super(TestIPVlan0, cls).setUpClass()
1221
1222 @classmethod
1223 def tearDownClass(cls):
1224 super(TestIPVlan0, cls).tearDownClass()
1225
Neale Ranns30d0fd42017-05-30 07:30:04 -07001226 def setUp(self):
1227 super(TestIPVlan0, self).setUp()
1228
1229 self.create_pg_interfaces(range(2))
Neale Ranns15002542017-09-10 04:39:11 -07001230 mpls_tbl = VppMplsTable(self, 0)
1231 mpls_tbl.add_vpp_config()
Neale Ranns30d0fd42017-05-30 07:30:04 -07001232
1233 for i in self.pg_interfaces:
1234 i.admin_up()
1235 i.config_ip4()
1236 i.resolve_arp()
1237 i.enable_mpls()
1238
1239 def tearDown(self):
Neale Ranns30d0fd42017-05-30 07:30:04 -07001240 for i in self.pg_interfaces:
1241 i.disable_mpls()
1242 i.unconfig_ip4()
1243 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07001244 super(TestIPVlan0, self).tearDown()
Neale Ranns30d0fd42017-05-30 07:30:04 -07001245
Neale Ranns30d0fd42017-05-30 07:30:04 -07001246 def test_ip_vlan_0(self):
1247 """ IP VLAN-0 """
1248
1249 pkts = (Ether(src=self.pg0.remote_mac,
1250 dst=self.pg0.local_mac) /
1251 Dot1Q(vlan=0) /
1252 IP(dst=self.pg1.remote_ip4,
1253 src=self.pg0.remote_ip4) /
1254 UDP(sport=1234, dport=1234) /
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001255 Raw('\xa5' * 100)) * NUM_PKTS
Neale Ranns30d0fd42017-05-30 07:30:04 -07001256
1257 #
1258 # Expect that packets sent on VLAN-0 are forwarded on the
1259 # main interface.
1260 #
1261 self.send_and_expect(self.pg0, pkts, self.pg1)
1262
1263
Neale Rannsd91c1db2017-07-31 02:30:50 -07001264class TestIPPunt(VppTestCase):
1265 """ IPv4 Punt Police/Redirect """
1266
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001267 @classmethod
1268 def setUpClass(cls):
1269 super(TestIPPunt, cls).setUpClass()
1270
1271 @classmethod
1272 def tearDownClass(cls):
1273 super(TestIPPunt, cls).tearDownClass()
1274
Neale Rannsd91c1db2017-07-31 02:30:50 -07001275 def setUp(self):
1276 super(TestIPPunt, self).setUp()
1277
Pavel Kotucek609e1212018-11-27 09:59:44 +01001278 self.create_pg_interfaces(range(4))
Neale Rannsd91c1db2017-07-31 02:30:50 -07001279
1280 for i in self.pg_interfaces:
1281 i.admin_up()
1282 i.config_ip4()
1283 i.resolve_arp()
1284
1285 def tearDown(self):
1286 super(TestIPPunt, self).tearDown()
1287 for i in self.pg_interfaces:
1288 i.unconfig_ip4()
1289 i.admin_down()
1290
Neale Rannsd91c1db2017-07-31 02:30:50 -07001291 def test_ip_punt(self):
1292 """ IP punt police and redirect """
1293
Neale Ranns68577d22019-06-04 13:31:23 +00001294 # use UDP packet that have a port we need to explicitly
1295 # register to get punted.
1296 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
1297 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
1298 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
1299 punt_udp = {
1300 'type': pt_l4,
1301 'punt': {
1302 'l4': {
1303 'af': af_ip4,
1304 'protocol': udp_proto,
1305 'port': 1234,
1306 }
1307 }
1308 }
1309
1310 self.vapi.set_punt(is_add=1, punt=punt_udp)
1311
Neale Rannsd91c1db2017-07-31 02:30:50 -07001312 p = (Ether(src=self.pg0.remote_mac,
1313 dst=self.pg0.local_mac) /
1314 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
Neale Ranns68577d22019-06-04 13:31:23 +00001315 UDP(sport=1234, dport=1234) /
Neale Rannsd91c1db2017-07-31 02:30:50 -07001316 Raw('\xa5' * 100))
1317
1318 pkts = p * 1025
1319
1320 #
1321 # Configure a punt redirect via pg1.
1322 #
Ole Troan0bcad322018-12-11 13:04:01 +01001323 nh_addr = self.pg1.remote_ip4
Neale Rannsd91c1db2017-07-31 02:30:50 -07001324 self.vapi.ip_punt_redirect(self.pg0.sw_if_index,
1325 self.pg1.sw_if_index,
1326 nh_addr)
1327
1328 self.send_and_expect(self.pg0, pkts, self.pg1)
1329
1330 #
1331 # add a policer
1332 #
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08001333 policer = self.vapi.policer_add_del(b"ip4-punt", 400, 0, 10, 0,
Neale Rannsd91c1db2017-07-31 02:30:50 -07001334 rate_type=1)
1335 self.vapi.ip_punt_police(policer.policer_index)
1336
1337 self.vapi.cli("clear trace")
1338 self.pg0.add_stream(pkts)
1339 self.pg_enable_capture(self.pg_interfaces)
1340 self.pg_start()
1341
1342 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001343 # the number of packet received should be greater than 0,
Neale Rannsd91c1db2017-07-31 02:30:50 -07001344 # but not equal to the number sent, since some were policed
1345 #
1346 rx = self.pg1._get_capture(1)
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001347 self.assertGreater(len(rx), 0)
1348 self.assertLess(len(rx), len(pkts))
Neale Rannsd91c1db2017-07-31 02:30:50 -07001349
1350 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001351 # remove the policer. back to full rx
Neale Rannsd91c1db2017-07-31 02:30:50 -07001352 #
1353 self.vapi.ip_punt_police(policer.policer_index, is_add=0)
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08001354 self.vapi.policer_add_del(b"ip4-punt", 400, 0, 10, 0,
Neale Rannsd91c1db2017-07-31 02:30:50 -07001355 rate_type=1, is_add=0)
1356 self.send_and_expect(self.pg0, pkts, self.pg1)
1357
1358 #
1359 # remove the redirect. expect full drop.
1360 #
1361 self.vapi.ip_punt_redirect(self.pg0.sw_if_index,
1362 self.pg1.sw_if_index,
1363 nh_addr,
1364 is_add=0)
1365 self.send_and_assert_no_replies(self.pg0, pkts,
1366 "IP no punt config")
1367
1368 #
1369 # Add a redirect that is not input port selective
1370 #
1371 self.vapi.ip_punt_redirect(0xffffffff,
1372 self.pg1.sw_if_index,
1373 nh_addr)
1374 self.send_and_expect(self.pg0, pkts, self.pg1)
1375
1376 self.vapi.ip_punt_redirect(0xffffffff,
1377 self.pg1.sw_if_index,
1378 nh_addr,
1379 is_add=0)
1380
Pavel Kotucek609e1212018-11-27 09:59:44 +01001381 def test_ip_punt_dump(self):
1382 """ IP4 punt redirect dump"""
1383
1384 #
1385 # Configure a punt redirects
1386 #
Ole Troan0bcad322018-12-11 13:04:01 +01001387 nh_address = self.pg3.remote_ip4
Pavel Kotucek609e1212018-11-27 09:59:44 +01001388 self.vapi.ip_punt_redirect(self.pg0.sw_if_index,
1389 self.pg3.sw_if_index,
1390 nh_address)
1391 self.vapi.ip_punt_redirect(self.pg1.sw_if_index,
1392 self.pg3.sw_if_index,
1393 nh_address)
1394 self.vapi.ip_punt_redirect(self.pg2.sw_if_index,
1395 self.pg3.sw_if_index,
Ole Troan0bcad322018-12-11 13:04:01 +01001396 '0.0.0.0')
Pavel Kotucek609e1212018-11-27 09:59:44 +01001397
1398 #
1399 # Dump pg0 punt redirects
1400 #
1401 punts = self.vapi.ip_punt_redirect_dump(self.pg0.sw_if_index)
1402 for p in punts:
1403 self.assertEqual(p.punt.rx_sw_if_index, self.pg0.sw_if_index)
1404
1405 #
1406 # Dump punt redirects for all interfaces
1407 #
1408 punts = self.vapi.ip_punt_redirect_dump(0xffffffff)
1409 self.assertEqual(len(punts), 3)
1410 for p in punts:
1411 self.assertEqual(p.punt.tx_sw_if_index, self.pg3.sw_if_index)
Ole Troan0bcad322018-12-11 13:04:01 +01001412 self.assertNotEqual(punts[1].punt.nh, self.pg3.remote_ip4)
1413 self.assertEqual(str(punts[2].punt.nh), '0.0.0.0')
Pavel Kotucek609e1212018-11-27 09:59:44 +01001414
Neale Rannsd91c1db2017-07-31 02:30:50 -07001415
Neale Ranns054c03a2017-10-13 05:15:07 -07001416class TestIPDeag(VppTestCase):
1417 """ IPv4 Deaggregate Routes """
1418
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001419 @classmethod
1420 def setUpClass(cls):
1421 super(TestIPDeag, cls).setUpClass()
1422
1423 @classmethod
1424 def tearDownClass(cls):
1425 super(TestIPDeag, cls).tearDownClass()
1426
Neale Ranns054c03a2017-10-13 05:15:07 -07001427 def setUp(self):
1428 super(TestIPDeag, self).setUp()
1429
1430 self.create_pg_interfaces(range(3))
1431
1432 for i in self.pg_interfaces:
1433 i.admin_up()
1434 i.config_ip4()
1435 i.resolve_arp()
1436
1437 def tearDown(self):
1438 super(TestIPDeag, self).tearDown()
1439 for i in self.pg_interfaces:
1440 i.unconfig_ip4()
1441 i.admin_down()
1442
Neale Ranns054c03a2017-10-13 05:15:07 -07001443 def test_ip_deag(self):
1444 """ IP Deag Routes """
1445
1446 #
1447 # Create a table to be used for:
1448 # 1 - another destination address lookup
1449 # 2 - a source address lookup
1450 #
1451 table_dst = VppIpTable(self, 1)
1452 table_src = VppIpTable(self, 2)
1453 table_dst.add_vpp_config()
1454 table_src.add_vpp_config()
1455
1456 #
1457 # Add a route in the default table to point to a deag/
1458 # second lookup in each of these tables
1459 #
1460 route_to_dst = VppIpRoute(self, "1.1.1.1", 32,
1461 [VppRoutePath("0.0.0.0",
1462 0xffffffff,
1463 nh_table_id=1)])
Neale Ranns097fa662018-05-01 05:17:55 -07001464 route_to_src = VppIpRoute(
1465 self, "1.1.1.2", 32,
1466 [VppRoutePath("0.0.0.0",
1467 0xffffffff,
1468 nh_table_id=2,
1469 type=FibPathType.FIB_PATH_TYPE_SOURCE_LOOKUP)])
Neale Ranns054c03a2017-10-13 05:15:07 -07001470 route_to_dst.add_vpp_config()
1471 route_to_src.add_vpp_config()
1472
1473 #
1474 # packets to these destination are dropped, since they'll
1475 # hit the respective default routes in the second table
1476 #
1477 p_dst = (Ether(src=self.pg0.remote_mac,
1478 dst=self.pg0.local_mac) /
1479 IP(src="5.5.5.5", dst="1.1.1.1") /
1480 TCP(sport=1234, dport=1234) /
1481 Raw('\xa5' * 100))
1482 p_src = (Ether(src=self.pg0.remote_mac,
1483 dst=self.pg0.local_mac) /
1484 IP(src="2.2.2.2", dst="1.1.1.2") /
1485 TCP(sport=1234, dport=1234) /
1486 Raw('\xa5' * 100))
1487 pkts_dst = p_dst * 257
1488 pkts_src = p_src * 257
1489
1490 self.send_and_assert_no_replies(self.pg0, pkts_dst,
1491 "IP in dst table")
1492 self.send_and_assert_no_replies(self.pg0, pkts_src,
1493 "IP in src table")
1494
1495 #
1496 # add a route in the dst table to forward via pg1
1497 #
1498 route_in_dst = VppIpRoute(self, "1.1.1.1", 32,
1499 [VppRoutePath(self.pg1.remote_ip4,
1500 self.pg1.sw_if_index)],
1501 table_id=1)
1502 route_in_dst.add_vpp_config()
Neale Ranns097fa662018-05-01 05:17:55 -07001503
Neale Ranns054c03a2017-10-13 05:15:07 -07001504 self.send_and_expect(self.pg0, pkts_dst, self.pg1)
1505
1506 #
1507 # add a route in the src table to forward via pg2
1508 #
1509 route_in_src = VppIpRoute(self, "2.2.2.2", 32,
1510 [VppRoutePath(self.pg2.remote_ip4,
1511 self.pg2.sw_if_index)],
1512 table_id=2)
1513 route_in_src.add_vpp_config()
1514 self.send_and_expect(self.pg0, pkts_src, self.pg2)
1515
Neale Rannsce9e0b42018-08-01 12:53:17 -07001516 #
1517 # loop in the lookup DP
1518 #
1519 route_loop = VppIpRoute(self, "2.2.2.3", 32,
1520 [VppRoutePath("0.0.0.0",
1521 0xffffffff,
1522 nh_table_id=0)])
1523 route_loop.add_vpp_config()
1524
1525 p_l = (Ether(src=self.pg0.remote_mac,
1526 dst=self.pg0.local_mac) /
1527 IP(src="2.2.2.4", dst="2.2.2.3") /
1528 TCP(sport=1234, dport=1234) /
1529 Raw('\xa5' * 100))
1530
1531 self.send_and_assert_no_replies(self.pg0, p_l * 257,
1532 "IP lookup loop")
1533
Neale Ranns054c03a2017-10-13 05:15:07 -07001534
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001535class TestIPInput(VppTestCase):
1536 """ IPv4 Input Exceptions """
1537
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001538 @classmethod
1539 def setUpClass(cls):
1540 super(TestIPInput, cls).setUpClass()
1541
1542 @classmethod
1543 def tearDownClass(cls):
1544 super(TestIPInput, cls).tearDownClass()
1545
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001546 def setUp(self):
1547 super(TestIPInput, self).setUp()
1548
1549 self.create_pg_interfaces(range(2))
1550
1551 for i in self.pg_interfaces:
1552 i.admin_up()
1553 i.config_ip4()
1554 i.resolve_arp()
1555
1556 def tearDown(self):
1557 super(TestIPInput, self).tearDown()
1558 for i in self.pg_interfaces:
1559 i.unconfig_ip4()
1560 i.admin_down()
1561
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001562 def test_ip_input(self):
1563 """ IP Input Exceptions """
1564
1565 # i can't find a way in scapy to construct an IP packet
1566 # with a length less than the IP header length
1567
1568 #
1569 # Packet too short - this is forwarded
1570 #
1571 p_short = (Ether(src=self.pg0.remote_mac,
1572 dst=self.pg0.local_mac) /
1573 IP(src=self.pg0.remote_ip4,
1574 dst=self.pg1.remote_ip4,
1575 len=40) /
1576 UDP(sport=1234, dport=1234) /
1577 Raw('\xa5' * 100))
1578
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001579 rx = self.send_and_expect(self.pg0, p_short * NUM_PKTS, self.pg1)
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001580
1581 #
1582 # Packet too long - this is dropped
1583 #
1584 p_long = (Ether(src=self.pg0.remote_mac,
1585 dst=self.pg0.local_mac) /
1586 IP(src=self.pg0.remote_ip4,
1587 dst=self.pg1.remote_ip4,
1588 len=400) /
1589 UDP(sport=1234, dport=1234) /
1590 Raw('\xa5' * 100))
1591
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001592 rx = self.send_and_assert_no_replies(self.pg0, p_long * NUM_PKTS,
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001593 "too long")
1594
1595 #
1596 # bad chksum - this is dropped
1597 #
1598 p_chksum = (Ether(src=self.pg0.remote_mac,
1599 dst=self.pg0.local_mac) /
1600 IP(src=self.pg0.remote_ip4,
1601 dst=self.pg1.remote_ip4,
1602 chksum=400) /
1603 UDP(sport=1234, dport=1234) /
1604 Raw('\xa5' * 100))
1605
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001606 rx = self.send_and_assert_no_replies(self.pg0, p_chksum * NUM_PKTS,
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001607 "bad checksum")
1608
1609 #
1610 # bad version - this is dropped
1611 #
1612 p_ver = (Ether(src=self.pg0.remote_mac,
1613 dst=self.pg0.local_mac) /
1614 IP(src=self.pg0.remote_ip4,
1615 dst=self.pg1.remote_ip4,
1616 version=3) /
1617 UDP(sport=1234, dport=1234) /
1618 Raw('\xa5' * 100))
1619
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001620 rx = self.send_and_assert_no_replies(self.pg0, p_ver * NUM_PKTS,
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001621 "funky version")
1622
1623 #
1624 # fragment offset 1 - this is dropped
1625 #
1626 p_frag = (Ether(src=self.pg0.remote_mac,
1627 dst=self.pg0.local_mac) /
1628 IP(src=self.pg0.remote_ip4,
1629 dst=self.pg1.remote_ip4,
1630 frag=1) /
1631 UDP(sport=1234, dport=1234) /
1632 Raw('\xa5' * 100))
1633
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001634 rx = self.send_and_assert_no_replies(self.pg0, p_frag * NUM_PKTS,
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001635 "frag offset")
1636
1637 #
1638 # TTL expired packet
1639 #
1640 p_ttl = (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 ttl=1) /
1645 UDP(sport=1234, dport=1234) /
1646 Raw('\xa5' * 100))
1647
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001648 rx = self.send_and_expect(self.pg0, p_ttl * NUM_PKTS, self.pg0)
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001649
1650 rx = rx[0]
1651 icmp = rx[ICMP]
1652
1653 self.assertEqual(icmptypes[icmp.type], "time-exceeded")
1654 self.assertEqual(icmpcodes[icmp.type][icmp.code],
1655 "ttl-zero-during-transit")
1656 self.assertEqual(icmp.src, self.pg0.remote_ip4)
1657 self.assertEqual(icmp.dst, self.pg1.remote_ip4)
1658
Neale Rannsffd78d12018-02-09 06:05:16 -08001659 #
1660 # MTU exceeded
1661 #
1662 p_mtu = (Ether(src=self.pg0.remote_mac,
1663 dst=self.pg0.local_mac) /
1664 IP(src=self.pg0.remote_ip4,
1665 dst=self.pg1.remote_ip4,
Ole Troan8a9c8f12018-05-18 11:01:31 +02001666 ttl=10, flags='DF') /
Neale Rannsffd78d12018-02-09 06:05:16 -08001667 UDP(sport=1234, dport=1234) /
1668 Raw('\xa5' * 2000))
1669
Ole Troand7231612018-06-07 10:17:57 +02001670 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1500, 0, 0, 0])
Neale Rannsffd78d12018-02-09 06:05:16 -08001671
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001672 rx = self.send_and_expect(self.pg0, p_mtu * NUM_PKTS, self.pg0)
Neale Rannsffd78d12018-02-09 06:05:16 -08001673 rx = rx[0]
1674 icmp = rx[ICMP]
1675
1676 self.assertEqual(icmptypes[icmp.type], "dest-unreach")
1677 self.assertEqual(icmpcodes[icmp.type][icmp.code],
1678 "fragmentation-needed")
1679 self.assertEqual(icmp.src, self.pg0.remote_ip4)
1680 self.assertEqual(icmp.dst, self.pg1.remote_ip4)
1681
Ole Troand7231612018-06-07 10:17:57 +02001682 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [2500, 0, 0, 0])
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001683 rx = self.send_and_expect(self.pg0, p_mtu * NUM_PKTS, self.pg1)
Neale Rannsffd78d12018-02-09 06:05:16 -08001684
Ole Troand7231612018-06-07 10:17:57 +02001685 # Reset MTU for subsequent tests
1686 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [9000, 0, 0, 0])
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001687
Neale Rannsbe2286b2018-12-09 12:54:51 -08001688 #
1689 # source address 0.0.0.0 and 25.255.255.255 and for-us
1690 #
1691 p_s0 = (Ether(src=self.pg0.remote_mac,
1692 dst=self.pg0.local_mac) /
1693 IP(src="0.0.0.0",
1694 dst=self.pg0.local_ip4) /
1695 ICMP(id=4, seq=4) /
1696 Raw(load='\x0a' * 18))
1697 rx = self.send_and_assert_no_replies(self.pg0, p_s0 * 17)
1698
1699 p_s0 = (Ether(src=self.pg0.remote_mac,
1700 dst=self.pg0.local_mac) /
1701 IP(src="255.255.255.255",
1702 dst=self.pg0.local_ip4) /
1703 ICMP(id=4, seq=4) /
1704 Raw(load='\x0a' * 18))
1705 rx = self.send_and_assert_no_replies(self.pg0, p_s0 * 17)
1706
Neale Ranns1855b8e2018-07-11 10:31:26 -07001707
1708class TestIPDirectedBroadcast(VppTestCase):
1709 """ IPv4 Directed Broadcast """
1710
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001711 @classmethod
1712 def setUpClass(cls):
1713 super(TestIPDirectedBroadcast, cls).setUpClass()
1714
1715 @classmethod
1716 def tearDownClass(cls):
1717 super(TestIPDirectedBroadcast, cls).tearDownClass()
1718
Neale Ranns1855b8e2018-07-11 10:31:26 -07001719 def setUp(self):
1720 super(TestIPDirectedBroadcast, self).setUp()
1721
1722 self.create_pg_interfaces(range(2))
1723
1724 for i in self.pg_interfaces:
1725 i.admin_up()
1726
1727 def tearDown(self):
1728 super(TestIPDirectedBroadcast, self).tearDown()
1729 for i in self.pg_interfaces:
1730 i.admin_down()
1731
1732 def test_ip_input(self):
1733 """ IP Directed Broadcast """
1734
1735 #
1736 # set the directed broadcast on pg0 first, then config IP4 addresses
1737 # for pg1 directed broadcast is always disabled
1738 self.vapi.sw_interface_set_ip_directed_broadcast(
1739 self.pg0.sw_if_index, 1)
1740
1741 p0 = (Ether(src=self.pg1.remote_mac,
1742 dst=self.pg1.local_mac) /
1743 IP(src="1.1.1.1",
1744 dst=self.pg0._local_ip4_bcast) /
1745 UDP(sport=1234, dport=1234) /
1746 Raw('\xa5' * 2000))
1747 p1 = (Ether(src=self.pg0.remote_mac,
1748 dst=self.pg0.local_mac) /
1749 IP(src="1.1.1.1",
1750 dst=self.pg1._local_ip4_bcast) /
1751 UDP(sport=1234, dport=1234) /
1752 Raw('\xa5' * 2000))
1753
1754 self.pg0.config_ip4()
1755 self.pg0.resolve_arp()
1756 self.pg1.config_ip4()
1757 self.pg1.resolve_arp()
1758
1759 #
1760 # test packet is L2 broadcast
1761 #
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001762 rx = self.send_and_expect(self.pg1, p0 * NUM_PKTS, self.pg0)
Neale Ranns1855b8e2018-07-11 10:31:26 -07001763 self.assertTrue(rx[0][Ether].dst, "ff:ff:ff:ff:ff:ff")
1764
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001765 self.send_and_assert_no_replies(self.pg0, p1 * NUM_PKTS,
Neale Ranns1855b8e2018-07-11 10:31:26 -07001766 "directed broadcast disabled")
1767
1768 #
1769 # toggle directed broadcast on pg0
1770 #
1771 self.vapi.sw_interface_set_ip_directed_broadcast(
1772 self.pg0.sw_if_index, 0)
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001773 self.send_and_assert_no_replies(self.pg1, p0 * NUM_PKTS,
Neale Ranns1855b8e2018-07-11 10:31:26 -07001774 "directed broadcast disabled")
1775
1776 self.vapi.sw_interface_set_ip_directed_broadcast(
1777 self.pg0.sw_if_index, 1)
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001778 rx = self.send_and_expect(self.pg1, p0 * NUM_PKTS, self.pg0)
Neale Ranns1855b8e2018-07-11 10:31:26 -07001779
1780 self.pg0.unconfig_ip4()
1781 self.pg1.unconfig_ip4()
1782
1783
mu.duojiao59a82952018-10-11 14:27:30 +08001784class TestIPLPM(VppTestCase):
1785 """ IPv4 longest Prefix Match """
1786
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001787 @classmethod
1788 def setUpClass(cls):
1789 super(TestIPLPM, cls).setUpClass()
1790
1791 @classmethod
1792 def tearDownClass(cls):
1793 super(TestIPLPM, cls).tearDownClass()
1794
mu.duojiao59a82952018-10-11 14:27:30 +08001795 def setUp(self):
1796 super(TestIPLPM, self).setUp()
1797
1798 self.create_pg_interfaces(range(4))
1799
1800 for i in self.pg_interfaces:
1801 i.admin_up()
1802 i.config_ip4()
1803 i.resolve_arp()
1804
1805 def tearDown(self):
1806 super(TestIPLPM, self).tearDown()
1807 for i in self.pg_interfaces:
1808 i.admin_down()
1809 i.unconfig_ip4()
1810
1811 def test_ip_lpm(self):
1812 """ IP longest Prefix Match """
1813
1814 s_24 = VppIpRoute(self, "10.1.2.0", 24,
1815 [VppRoutePath(self.pg1.remote_ip4,
1816 self.pg1.sw_if_index)])
1817 s_24.add_vpp_config()
1818 s_8 = VppIpRoute(self, "10.0.0.0", 8,
1819 [VppRoutePath(self.pg2.remote_ip4,
1820 self.pg2.sw_if_index)])
1821 s_8.add_vpp_config()
1822
1823 p_8 = (Ether(src=self.pg0.remote_mac,
1824 dst=self.pg0.local_mac) /
1825 IP(src="1.1.1.1",
1826 dst="10.1.1.1") /
1827 UDP(sport=1234, dport=1234) /
1828 Raw('\xa5' * 2000))
1829 p_24 = (Ether(src=self.pg0.remote_mac,
1830 dst=self.pg0.local_mac) /
1831 IP(src="1.1.1.1",
1832 dst="10.1.2.1") /
1833 UDP(sport=1234, dport=1234) /
1834 Raw('\xa5' * 2000))
1835
1836 self.logger.info(self.vapi.cli("sh ip fib mtrie"))
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001837 rx = self.send_and_expect(self.pg0, p_8 * NUM_PKTS, self.pg2)
1838 rx = self.send_and_expect(self.pg0, p_24 * NUM_PKTS, self.pg1)
mu.duojiao59a82952018-10-11 14:27:30 +08001839
1840
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02001841class TestIPv4Frag(VppTestCase):
1842 """ IPv4 fragmentation """
1843
1844 @classmethod
1845 def setUpClass(cls):
1846 super(TestIPv4Frag, cls).setUpClass()
1847
1848 cls.create_pg_interfaces([0, 1])
1849 cls.src_if = cls.pg0
1850 cls.dst_if = cls.pg1
1851
1852 # setup all interfaces
1853 for i in cls.pg_interfaces:
1854 i.admin_up()
1855 i.config_ip4()
1856 i.resolve_arp()
1857
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001858 @classmethod
1859 def tearDownClass(cls):
1860 super(TestIPv4Frag, cls).tearDownClass()
1861
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02001862 def test_frag_large_packets(self):
1863 """ Fragmentation of large packets """
1864
1865 p = (Ether(dst=self.src_if.local_mac, src=self.src_if.remote_mac) /
1866 IP(src=self.src_if.remote_ip4, dst=self.dst_if.remote_ip4) /
1867 UDP(sport=1234, dport=5678) / Raw())
1868 self.extend_packet(p, 6000, "abcde")
1869 saved_payload = p[Raw].load
1870
1871 # Force fragmentation by setting MTU of output interface
1872 # lower than packet size
1873 self.vapi.sw_interface_set_mtu(self.dst_if.sw_if_index,
1874 [5000, 0, 0, 0])
1875
1876 self.pg_enable_capture()
1877 self.src_if.add_stream(p)
1878 self.pg_start()
1879
1880 # Expecting 3 fragments because size of created fragments currently
1881 # cannot be larger then VPP buffer size (which is 2048)
1882 packets = self.dst_if.get_capture(3)
1883
1884 # Assume VPP sends the fragments in order
1885 payload = ''
1886 for p in packets:
1887 payload_offset = p.frag * 8
1888 if payload_offset > 0:
1889 payload_offset -= 8 # UDP header is not in payload
1890 self.assert_equal(payload_offset, len(payload))
1891 payload += p[Raw].load
1892 self.assert_equal(payload, saved_payload, "payload")
1893
1894
Damjan Marionf56b77a2016-10-03 19:44:57 +02001895if __name__ == '__main__':
Klement Sekeraf62ae122016-10-11 11:47:09 +02001896 unittest.main(testRunner=VppTestRunner)