blob: ca461f1d2760281454f92d28302b00f5cac092a3 [file] [log] [blame]
Damjan Marionf56b77a2016-10-03 19:44:57 +02001#!/usr/bin/env python
Matej Klotton16a14cd2016-12-07 15:09:13 +01002import random
Klement Sekeraf62ae122016-10-11 11:47:09 +02003import socket
Matej Klotton16a14cd2016-12-07 15:09:13 +01004import unittest
Klement Sekeraf62ae122016-10-11 11:47:09 +02005
Damjan Marionf56b77a2016-10-03 19:44:57 +02006from framework import VppTestCase, VppTestRunner
Klement Sekeraf62ae122016-10-11 11:47:09 +02007from vpp_sub_interface import VppSubInterface, VppDot1QSubint, VppDot1ADSubint
Neale Ranns180279b2017-03-16 15:49:09 -04008from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpMRoute, \
Neale Ranns15002542017-09-10 04:39:11 -07009 VppMRoutePath, MRouteItfFlags, MRouteEntryFlags, VppMplsIpBind, \
Neale Ranns054c03a2017-10-13 05:15:07 -070010 VppMplsTable, VppIpTable
Damjan Marionf56b77a2016-10-03 19:44:57 +020011
12from scapy.packet import Raw
Neale Ranns9a69a602017-03-26 10:56:33 -070013from scapy.layers.l2 import Ether, Dot1Q, ARP
Neale Rannsd91c1db2017-07-31 02:30:50 -070014from scapy.layers.inet import IP, UDP, TCP, ICMP, icmptypes, icmpcodes
Klement Sekera7bb873a2016-11-18 07:38:42 +010015from util import ppp
Neale Ranns71275e32017-05-25 12:38:58 -070016from scapy.contrib.mpls import MPLS
Damjan Marionf56b77a2016-10-03 19:44:57 +020017
18
Klement Sekeraf62ae122016-10-11 11:47:09 +020019class TestIPv4(VppTestCase):
Damjan Marionf56b77a2016-10-03 19:44:57 +020020 """ IPv4 Test Case """
21
Klement Sekeraf62ae122016-10-11 11:47:09 +020022 def setUp(self):
Matej Klotton86d87c42016-11-11 11:38:55 +010023 """
24 Perform test setup before test case.
25
26 **Config:**
27 - create 3 pg interfaces
28 - untagged pg0 interface
29 - Dot1Q subinterface on pg1
30 - Dot1AD subinterface on pg2
31 - setup interfaces:
32 - put it into UP state
33 - set IPv4 addresses
34 - resolve neighbor address using ARP
35 - configure 200 fib entries
36
37 :ivar list interfaces: pg interfaces and subinterfaces.
38 :ivar dict flows: IPv4 packet flows in test.
Matej Klotton86d87c42016-11-11 11:38:55 +010039 """
Klement Sekeraf62ae122016-10-11 11:47:09 +020040 super(TestIPv4, self).setUp()
Damjan Marionf56b77a2016-10-03 19:44:57 +020041
Klement Sekeraf62ae122016-10-11 11:47:09 +020042 # create 3 pg interfaces
43 self.create_pg_interfaces(range(3))
Damjan Marionf56b77a2016-10-03 19:44:57 +020044
Klement Sekeraf62ae122016-10-11 11:47:09 +020045 # create 2 subinterfaces for pg1 and pg2
46 self.sub_interfaces = [
47 VppDot1QSubint(self, self.pg1, 100),
48 VppDot1ADSubint(self, self.pg2, 200, 300, 400)]
Damjan Marionf56b77a2016-10-03 19:44:57 +020049
Klement Sekeraf62ae122016-10-11 11:47:09 +020050 # packet flows mapping pg0 -> pg1.sub, pg2.sub, etc.
51 self.flows = dict()
52 self.flows[self.pg0] = [self.pg1.sub_if, self.pg2.sub_if]
53 self.flows[self.pg1.sub_if] = [self.pg0, self.pg2.sub_if]
54 self.flows[self.pg2.sub_if] = [self.pg0, self.pg1.sub_if]
Damjan Marionf56b77a2016-10-03 19:44:57 +020055
Klement Sekeraf62ae122016-10-11 11:47:09 +020056 # packet sizes
Jan Geletye6c78ee2018-06-26 12:24:03 +020057 self.pg_if_packet_sizes = [64, 1500, 9020]
Damjan Marionf56b77a2016-10-03 19:44:57 +020058
Klement Sekeraf62ae122016-10-11 11:47:09 +020059 self.interfaces = list(self.pg_interfaces)
60 self.interfaces.extend(self.sub_interfaces)
Damjan Marionf56b77a2016-10-03 19:44:57 +020061
Klement Sekeraf62ae122016-10-11 11:47:09 +020062 # setup all interfaces
63 for i in self.interfaces:
64 i.admin_up()
65 i.config_ip4()
66 i.resolve_arp()
67
Matej Klotton86d87c42016-11-11 11:38:55 +010068 # config 2M FIB entries
Klement Sekeraf62ae122016-10-11 11:47:09 +020069 self.config_fib_entries(200)
Damjan Marionf56b77a2016-10-03 19:44:57 +020070
71 def tearDown(self):
Matej Klotton86d87c42016-11-11 11:38:55 +010072 """Run standard test teardown and log ``show ip arp``."""
Klement Sekeraf62ae122016-10-11 11:47:09 +020073 super(TestIPv4, self).tearDown()
74 if not self.vpp_dead:
Matej Klotton86d87c42016-11-11 11:38:55 +010075 self.logger.info(self.vapi.cli("show ip arp"))
Klement Sekeraf62ae122016-10-11 11:47:09 +020076 # info(self.vapi.cli("show ip fib")) # many entries
Damjan Marionf56b77a2016-10-03 19:44:57 +020077
Klement Sekeraf62ae122016-10-11 11:47:09 +020078 def config_fib_entries(self, count):
Matej Klotton86d87c42016-11-11 11:38:55 +010079 """For each interface add to the FIB table *count* routes to
80 "10.0.0.1/32" destination with interface's local address as next-hop
81 address.
82
83 :param int count: Number of FIB entries.
84
85 - *TODO:* check if the next-hop address shouldn't be remote address
86 instead of local address.
87 """
Klement Sekeraf62ae122016-10-11 11:47:09 +020088 n_int = len(self.interfaces)
89 percent = 0
90 counter = 0.0
91 dest_addr = socket.inet_pton(socket.AF_INET, "10.0.0.1")
92 dest_addr_len = 32
93 for i in self.interfaces:
94 next_hop_address = i.local_ip4n
95 for j in range(count / n_int):
96 self.vapi.ip_add_del_route(
97 dest_addr, dest_addr_len, next_hop_address)
Matej Klotton86d87c42016-11-11 11:38:55 +010098 counter += 1
Klement Sekeraf62ae122016-10-11 11:47:09 +020099 if counter / count * 100 > percent:
Matej Klotton86d87c42016-11-11 11:38:55 +0100100 self.logger.info("Configure %d FIB entries .. %d%% done" %
101 (count, percent))
102 percent += 1
Damjan Marionf56b77a2016-10-03 19:44:57 +0200103
Jan Geletye6c78ee2018-06-26 12:24:03 +0200104 def modify_packet(self, src_if, packet_size, pkt):
105 """Add load, set destination IP and extend packet to required packet
106 size for defined interface.
107
108 :param VppInterface src_if: Interface to create packet for.
109 :param int packet_size: Required packet size.
110 :param Scapy pkt: Packet to be modified.
111 """
112 dst_if_idx = packet_size / 10 % 2
113 dst_if = self.flows[src_if][dst_if_idx]
114 info = self.create_packet_info(src_if, dst_if)
115 payload = self.info_to_payload(info)
116 p = pkt/Raw(payload)
117 p[IP].dst = dst_if.remote_ip4
118 info.data = p.copy()
119 if isinstance(src_if, VppSubInterface):
120 p = src_if.add_dot1_layer(p)
121 self.extend_packet(p, packet_size)
122
123 return p
124
125 def create_stream(self, src_if):
Matej Klotton86d87c42016-11-11 11:38:55 +0100126 """Create input packet stream for defined interface.
127
128 :param VppInterface src_if: Interface to create packet stream for.
Matej Klotton86d87c42016-11-11 11:38:55 +0100129 """
Jan Geletye6c78ee2018-06-26 12:24:03 +0200130 hdr_ext = 4 if isinstance(src_if, VppSubInterface) else 0
131 pkt_tmpl = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
132 IP(src=src_if.remote_ip4) /
133 UDP(sport=1234, dport=1234))
134
135 pkts = [self.modify_packet(src_if, i, pkt_tmpl)
136 for i in xrange(self.pg_if_packet_sizes[0],
137 self.pg_if_packet_sizes[1], 10)]
138 pkts_b = [self.modify_packet(src_if, i, pkt_tmpl)
139 for i in xrange(self.pg_if_packet_sizes[1] + hdr_ext,
140 self.pg_if_packet_sizes[2] + hdr_ext, 50)]
141 pkts.extend(pkts_b)
142
Damjan Marionf56b77a2016-10-03 19:44:57 +0200143 return pkts
144
Klement Sekeraf62ae122016-10-11 11:47:09 +0200145 def verify_capture(self, dst_if, capture):
Matej Klotton86d87c42016-11-11 11:38:55 +0100146 """Verify captured input packet stream for defined interface.
147
148 :param VppInterface dst_if: Interface to verify captured packet stream
Jan Geletye6c78ee2018-06-26 12:24:03 +0200149 for.
Matej Klotton86d87c42016-11-11 11:38:55 +0100150 :param list capture: Captured packet stream.
151 """
152 self.logger.info("Verifying capture on interface %s" % dst_if.name)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200153 last_info = dict()
Damjan Marionf56b77a2016-10-03 19:44:57 +0200154 for i in self.interfaces:
Klement Sekeraf62ae122016-10-11 11:47:09 +0200155 last_info[i.sw_if_index] = None
156 is_sub_if = False
157 dst_sw_if_index = dst_if.sw_if_index
158 if hasattr(dst_if, 'parent'):
159 is_sub_if = True
Damjan Marionf56b77a2016-10-03 19:44:57 +0200160 for packet in capture:
Klement Sekeraf62ae122016-10-11 11:47:09 +0200161 if is_sub_if:
162 # Check VLAN tags and Ethernet header
163 packet = dst_if.remove_dot1_layer(packet)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200164 self.assertTrue(Dot1Q not in packet)
165 try:
166 ip = packet[IP]
167 udp = packet[UDP]
168 payload_info = self.payload_to_info(str(packet[Raw]))
169 packet_index = payload_info.index
Klement Sekeraf62ae122016-10-11 11:47:09 +0200170 self.assertEqual(payload_info.dst, dst_sw_if_index)
Klement Sekerada505f62017-01-04 12:58:53 +0100171 self.logger.debug(
172 "Got packet on port %s: src=%u (id=%u)" %
173 (dst_if.name, payload_info.src, packet_index))
Klement Sekeraf62ae122016-10-11 11:47:09 +0200174 next_info = self.get_next_packet_info_for_interface2(
175 payload_info.src, dst_sw_if_index,
176 last_info[payload_info.src])
177 last_info[payload_info.src] = next_info
Damjan Marionf56b77a2016-10-03 19:44:57 +0200178 self.assertTrue(next_info is not None)
179 self.assertEqual(packet_index, next_info.index)
180 saved_packet = next_info.data
181 # Check standard fields
182 self.assertEqual(ip.src, saved_packet[IP].src)
183 self.assertEqual(ip.dst, saved_packet[IP].dst)
184 self.assertEqual(udp.sport, saved_packet[UDP].sport)
185 self.assertEqual(udp.dport, saved_packet[UDP].dport)
186 except:
Klement Sekera7bb873a2016-11-18 07:38:42 +0100187 self.logger.error(ppp("Unexpected or invalid packet:", packet))
Damjan Marionf56b77a2016-10-03 19:44:57 +0200188 raise
189 for i in self.interfaces:
Klement Sekeraf62ae122016-10-11 11:47:09 +0200190 remaining_packet = self.get_next_packet_info_for_interface2(
191 i.sw_if_index, dst_sw_if_index, last_info[i.sw_if_index])
Klement Sekera7bb873a2016-11-18 07:38:42 +0100192 self.assertTrue(remaining_packet is None,
193 "Interface %s: Packet expected from interface %s "
194 "didn't arrive" % (dst_if.name, i.name))
Damjan Marionf56b77a2016-10-03 19:44:57 +0200195
196 def test_fib(self):
Matej Klotton86d87c42016-11-11 11:38:55 +0100197 """ IPv4 FIB test
198
199 Test scenario:
200
201 - Create IPv4 stream for pg0 interface
Jan Geletye6c78ee2018-06-26 12:24:03 +0200202 - Create IPv4 tagged streams for pg1's and pg2's sub-interface.
Matej Klotton86d87c42016-11-11 11:38:55 +0100203 - Send and verify received packets on each interface.
204 """
Damjan Marionf56b77a2016-10-03 19:44:57 +0200205
Jan Geletye6c78ee2018-06-26 12:24:03 +0200206 pkts = self.create_stream(self.pg0)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200207 self.pg0.add_stream(pkts)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200208
Klement Sekeraf62ae122016-10-11 11:47:09 +0200209 for i in self.sub_interfaces:
Jan Geletye6c78ee2018-06-26 12:24:03 +0200210 pkts = self.create_stream(i)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200211 i.parent.add_stream(pkts)
212
213 self.pg_enable_capture(self.pg_interfaces)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200214 self.pg_start()
215
Klement Sekeraf62ae122016-10-11 11:47:09 +0200216 pkts = self.pg0.get_capture()
217 self.verify_capture(self.pg0, pkts)
218
219 for i in self.sub_interfaces:
220 pkts = i.parent.get_capture()
221 self.verify_capture(i, pkts)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200222
223
Jan Geletye6c78ee2018-06-26 12:24:03 +0200224class TestICMPEcho(VppTestCase):
225 """ ICMP Echo Test Case """
226
227 def setUp(self):
228 super(TestICMPEcho, self).setUp()
229
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):
239 super(TestICMPEcho, self).tearDown()
240 for i in self.pg_interfaces:
241 i.unconfig_ip4()
242 i.admin_down()
243
244 def test_icmp_echo(self):
245 """ VPP replies to ICMP Echo Request
246
247 Test scenario:
248
249 - Receive ICMP Echo Request message on pg0 interface.
250 - Check outgoing ICMP Echo Reply message on pg0 interface.
251 """
252
253 icmp_id = 0xb
254 icmp_seq = 5
255 icmp_load = '\x0a' * 18
256 p_echo_request = (Ether(src=self.pg0.remote_mac,
257 dst=self.pg0.local_mac) /
258 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
259 ICMP(id=icmp_id, seq=icmp_seq) /
260 Raw(load=icmp_load))
261
262 self.pg0.add_stream(p_echo_request)
263 self.pg_enable_capture(self.pg_interfaces)
264 self.pg_start()
265
266 rx = self.pg0.get_capture(1)
267 rx = rx[0]
268 ether = rx[Ether]
269 ipv4 = rx[IP]
270 icmp = rx[ICMP]
271
272 self.assertEqual(ether.src, self.pg0.local_mac)
273 self.assertEqual(ether.dst, self.pg0.remote_mac)
274
275 self.assertEqual(ipv4.src, self.pg0.local_ip4)
276 self.assertEqual(ipv4.dst, self.pg0.remote_ip4)
277
278 self.assertEqual(icmptypes[icmp.type], "echo-reply")
279 self.assertEqual(icmp.id, icmp_id)
280 self.assertEqual(icmp.seq, icmp_seq)
281 self.assertEqual(icmp[Raw].load, icmp_load)
282
283
Matej Klotton16a14cd2016-12-07 15:09:13 +0100284class TestIPv4FibCrud(VppTestCase):
285 """ FIB - add/update/delete - ip4 routes
286
287 Test scenario:
288 - add 1k,
289 - del 100,
290 - add new 1k,
291 - del 1.5k
292
Klement Sekerada505f62017-01-04 12:58:53 +0100293 ..note:: Python API is too slow to add many routes, needs replacement.
Matej Klotton16a14cd2016-12-07 15:09:13 +0100294 """
295
296 def config_fib_many_to_one(self, start_dest_addr, next_hop_addr, count):
297 """
298
299 :param start_dest_addr:
300 :param next_hop_addr:
301 :param count:
302 :return list: added ips with 32 prefix
303 """
304 added_ips = []
Klement Sekerada505f62017-01-04 12:58:53 +0100305 dest_addr = int(socket.inet_pton(socket.AF_INET,
306 start_dest_addr).encode('hex'),
307 16)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100308 dest_addr_len = 32
309 n_next_hop_addr = socket.inet_pton(socket.AF_INET, next_hop_addr)
310 for _ in range(count):
311 n_dest_addr = '{:08x}'.format(dest_addr).decode('hex')
312 self.vapi.ip_add_del_route(n_dest_addr, dest_addr_len,
313 n_next_hop_addr)
314 added_ips.append(socket.inet_ntoa(n_dest_addr))
315 dest_addr += 1
316 return added_ips
317
318 def unconfig_fib_many_to_one(self, start_dest_addr, next_hop_addr, count):
319
320 removed_ips = []
Klement Sekerada505f62017-01-04 12:58:53 +0100321 dest_addr = int(socket.inet_pton(socket.AF_INET,
322 start_dest_addr).encode('hex'),
323 16)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100324 dest_addr_len = 32
325 n_next_hop_addr = socket.inet_pton(socket.AF_INET, next_hop_addr)
326 for _ in range(count):
327 n_dest_addr = '{:08x}'.format(dest_addr).decode('hex')
328 self.vapi.ip_add_del_route(n_dest_addr, dest_addr_len,
329 n_next_hop_addr, is_add=0)
330 removed_ips.append(socket.inet_ntoa(n_dest_addr))
331 dest_addr += 1
332 return removed_ips
333
334 def create_stream(self, src_if, dst_if, dst_ips, count):
335 pkts = []
336
337 for _ in range(count):
338 dst_addr = random.choice(dst_ips)
Klement Sekeradab231a2016-12-21 08:50:14 +0100339 info = self.create_packet_info(src_if, dst_if)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100340 payload = self.info_to_payload(info)
341 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
342 IP(src=src_if.remote_ip4, dst=dst_addr) /
343 UDP(sport=1234, dport=1234) /
344 Raw(payload))
345 info.data = p.copy()
Matej Klotton16a14cd2016-12-07 15:09:13 +0100346 self.extend_packet(p, random.choice(self.pg_if_packet_sizes))
347 pkts.append(p)
348
349 return pkts
350
351 def _find_ip_match(self, find_in, pkt):
352 for p in find_in:
Klement Sekeradab231a2016-12-21 08:50:14 +0100353 if self.payload_to_info(str(p[Raw])) == \
354 self.payload_to_info(str(pkt[Raw])):
Matej Klotton16a14cd2016-12-07 15:09:13 +0100355 if p[IP].src != pkt[IP].src:
356 break
357 if p[IP].dst != pkt[IP].dst:
358 break
359 if p[UDP].sport != pkt[UDP].sport:
360 break
361 if p[UDP].dport != pkt[UDP].dport:
362 break
363 return p
364 return None
365
366 @staticmethod
367 def _match_route_detail(route_detail, ip, address_length=32, table_id=0):
368 if route_detail.address == socket.inet_pton(socket.AF_INET, ip):
369 if route_detail.table_id != table_id:
370 return False
371 elif route_detail.address_length != address_length:
372 return False
373 else:
374 return True
375 else:
376 return False
377
378 def verify_capture(self, dst_interface, received_pkts, expected_pkts):
379 self.assertEqual(len(received_pkts), len(expected_pkts))
380 to_verify = list(expected_pkts)
381 for p in received_pkts:
382 self.assertEqual(p.src, dst_interface.local_mac)
383 self.assertEqual(p.dst, dst_interface.remote_mac)
384 x = self._find_ip_match(to_verify, p)
385 to_verify.remove(x)
386 self.assertListEqual(to_verify, [])
387
388 def verify_route_dump(self, fib_dump, ips):
389
390 def _ip_in_route_dump(ip, fib_dump):
391 return next((route for route in fib_dump
392 if self._match_route_detail(route, ip)),
393 False)
394
395 for ip in ips:
396 self.assertTrue(_ip_in_route_dump(ip, fib_dump),
397 'IP {} is not in fib dump.'.format(ip))
398
399 def verify_not_in_route_dump(self, fib_dump, ips):
400
401 def _ip_in_route_dump(ip, fib_dump):
402 return next((route for route in fib_dump
403 if self._match_route_detail(route, ip)),
404 False)
405
406 for ip in ips:
407 self.assertFalse(_ip_in_route_dump(ip, fib_dump),
408 'IP {} is in fib dump.'.format(ip))
409
410 @classmethod
411 def setUpClass(cls):
412 """
413 #. Create and initialize 3 pg interfaces.
414 #. initialize class attributes configured_routes and deleted_routes
415 to store information between tests.
416 """
417 super(TestIPv4FibCrud, cls).setUpClass()
418
419 try:
420 # create 3 pg interfaces
421 cls.create_pg_interfaces(range(3))
422
423 cls.interfaces = list(cls.pg_interfaces)
424
425 # setup all interfaces
426 for i in cls.interfaces:
427 i.admin_up()
428 i.config_ip4()
429 i.resolve_arp()
430
431 cls.configured_routes = []
432 cls.deleted_routes = []
433 cls.pg_if_packet_sizes = [64, 512, 1518, 9018]
434
435 except Exception:
436 super(TestIPv4FibCrud, cls).tearDownClass()
437 raise
438
439 def setUp(self):
440 super(TestIPv4FibCrud, self).setUp()
Klement Sekeradab231a2016-12-21 08:50:14 +0100441 self.reset_packet_infos()
Matej Klotton16a14cd2016-12-07 15:09:13 +0100442
443 def test_1_add_routes(self):
444 """ Add 1k routes
445
446 - add 100 routes check with traffic script.
447 """
448 # config 1M FIB entries
449 self.configured_routes.extend(self.config_fib_many_to_one(
450 "10.0.0.0", self.pg0.remote_ip4, 100))
451
452 fib_dump = self.vapi.ip_fib_dump()
453 self.verify_route_dump(fib_dump, self.configured_routes)
454
455 self.stream_1 = self.create_stream(
456 self.pg1, self.pg0, self.configured_routes, 100)
457 self.stream_2 = self.create_stream(
458 self.pg2, self.pg0, self.configured_routes, 100)
459 self.pg1.add_stream(self.stream_1)
460 self.pg2.add_stream(self.stream_2)
461
462 self.pg_enable_capture(self.pg_interfaces)
463 self.pg_start()
464
Klement Sekeradab231a2016-12-21 08:50:14 +0100465 pkts = self.pg0.get_capture(len(self.stream_1) + len(self.stream_2))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100466 self.verify_capture(self.pg0, pkts, self.stream_1 + self.stream_2)
467
Matej Klotton16a14cd2016-12-07 15:09:13 +0100468 def test_2_del_routes(self):
469 """ Delete 100 routes
470
471 - delete 10 routes check with traffic script.
472 """
473 self.deleted_routes.extend(self.unconfig_fib_many_to_one(
474 "10.0.0.10", self.pg0.remote_ip4, 10))
475 for x in self.deleted_routes:
476 self.configured_routes.remove(x)
477
478 fib_dump = self.vapi.ip_fib_dump()
479 self.verify_route_dump(fib_dump, self.configured_routes)
480
481 self.stream_1 = self.create_stream(
482 self.pg1, self.pg0, self.configured_routes, 100)
483 self.stream_2 = self.create_stream(
484 self.pg2, self.pg0, self.configured_routes, 100)
485 self.stream_3 = self.create_stream(
486 self.pg1, self.pg0, self.deleted_routes, 100)
487 self.stream_4 = self.create_stream(
488 self.pg2, self.pg0, self.deleted_routes, 100)
489 self.pg1.add_stream(self.stream_1 + self.stream_3)
490 self.pg2.add_stream(self.stream_2 + self.stream_4)
491 self.pg_enable_capture(self.pg_interfaces)
492 self.pg_start()
493
Klement Sekeradab231a2016-12-21 08:50:14 +0100494 pkts = self.pg0.get_capture(len(self.stream_1) + len(self.stream_2))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100495 self.verify_capture(self.pg0, pkts, self.stream_1 + self.stream_2)
496
497 def test_3_add_new_routes(self):
498 """ Add 1k routes
499
500 - re-add 5 routes check with traffic script.
501 - add 100 routes check with traffic script.
502 """
503 tmp = self.config_fib_many_to_one(
504 "10.0.0.10", self.pg0.remote_ip4, 5)
505 self.configured_routes.extend(tmp)
506 for x in tmp:
507 self.deleted_routes.remove(x)
508
509 self.configured_routes.extend(self.config_fib_many_to_one(
510 "10.0.1.0", self.pg0.remote_ip4, 100))
511
512 fib_dump = self.vapi.ip_fib_dump()
513 self.verify_route_dump(fib_dump, self.configured_routes)
514
515 self.stream_1 = self.create_stream(
516 self.pg1, self.pg0, self.configured_routes, 300)
517 self.stream_2 = self.create_stream(
518 self.pg2, self.pg0, self.configured_routes, 300)
519 self.stream_3 = self.create_stream(
520 self.pg1, self.pg0, self.deleted_routes, 100)
521 self.stream_4 = self.create_stream(
522 self.pg2, self.pg0, self.deleted_routes, 100)
523
524 self.pg1.add_stream(self.stream_1 + self.stream_3)
525 self.pg2.add_stream(self.stream_2 + self.stream_4)
526 self.pg_enable_capture(self.pg_interfaces)
527 self.pg_start()
528
Klement Sekeradab231a2016-12-21 08:50:14 +0100529 pkts = self.pg0.get_capture(len(self.stream_1) + len(self.stream_2))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100530 self.verify_capture(self.pg0, pkts, self.stream_1 + self.stream_2)
531
532 def test_4_del_routes(self):
533 """ Delete 1.5k routes
534
535 - delete 5 routes check with traffic script.
536 - add 100 routes check with traffic script.
537 """
538 self.deleted_routes.extend(self.unconfig_fib_many_to_one(
539 "10.0.0.0", self.pg0.remote_ip4, 15))
540 self.deleted_routes.extend(self.unconfig_fib_many_to_one(
541 "10.0.0.20", self.pg0.remote_ip4, 85))
542 self.deleted_routes.extend(self.unconfig_fib_many_to_one(
543 "10.0.1.0", self.pg0.remote_ip4, 100))
544 fib_dump = self.vapi.ip_fib_dump()
545 self.verify_not_in_route_dump(fib_dump, self.deleted_routes)
546
547
Neale Ranns37be7362017-02-21 17:30:26 -0800548class TestIPNull(VppTestCase):
549 """ IPv4 routes via NULL """
550
551 def setUp(self):
552 super(TestIPNull, self).setUp()
553
554 # create 2 pg interfaces
Neale Ranns3b93be52018-09-07 01:48:54 -0700555 self.create_pg_interfaces(range(2))
Neale Ranns37be7362017-02-21 17:30:26 -0800556
557 for i in self.pg_interfaces:
558 i.admin_up()
559 i.config_ip4()
560 i.resolve_arp()
561
562 def tearDown(self):
563 super(TestIPNull, self).tearDown()
564 for i in self.pg_interfaces:
565 i.unconfig_ip4()
566 i.admin_down()
567
568 def test_ip_null(self):
569 """ IP NULL route """
570
571 #
572 # A route via IP NULL that will reply with ICMP unreachables
573 #
574 ip_unreach = VppIpRoute(self, "10.0.0.1", 32, [], is_unreach=1)
575 ip_unreach.add_vpp_config()
576
577 p_unreach = (Ether(src=self.pg0.remote_mac,
578 dst=self.pg0.local_mac) /
579 IP(src=self.pg0.remote_ip4, dst="10.0.0.1") /
580 UDP(sport=1234, dport=1234) /
581 Raw('\xa5' * 100))
582
583 self.pg0.add_stream(p_unreach)
584 self.pg_enable_capture(self.pg_interfaces)
585 self.pg_start()
586
587 rx = self.pg0.get_capture(1)
588 rx = rx[0]
589 icmp = rx[ICMP]
590
591 self.assertEqual(icmptypes[icmp.type], "dest-unreach")
592 self.assertEqual(icmpcodes[icmp.type][icmp.code], "host-unreachable")
593 self.assertEqual(icmp.src, self.pg0.remote_ip4)
594 self.assertEqual(icmp.dst, "10.0.0.1")
595
596 #
597 # ICMP replies are rate limited. so sit and spin.
598 #
599 self.sleep(1)
600
601 #
602 # A route via IP NULL that will reply with ICMP prohibited
603 #
604 ip_prohibit = VppIpRoute(self, "10.0.0.2", 32, [], is_prohibit=1)
605 ip_prohibit.add_vpp_config()
606
607 p_prohibit = (Ether(src=self.pg0.remote_mac,
608 dst=self.pg0.local_mac) /
609 IP(src=self.pg0.remote_ip4, dst="10.0.0.2") /
610 UDP(sport=1234, dport=1234) /
611 Raw('\xa5' * 100))
612
613 self.pg0.add_stream(p_prohibit)
614 self.pg_enable_capture(self.pg_interfaces)
615 self.pg_start()
616
617 rx = self.pg0.get_capture(1)
618
619 rx = rx[0]
620 icmp = rx[ICMP]
621
622 self.assertEqual(icmptypes[icmp.type], "dest-unreach")
623 self.assertEqual(icmpcodes[icmp.type][icmp.code], "host-prohibited")
624 self.assertEqual(icmp.src, self.pg0.remote_ip4)
625 self.assertEqual(icmp.dst, "10.0.0.2")
626
Neale Ranns3b93be52018-09-07 01:48:54 -0700627 def test_ip_drop(self):
628 """ IP Drop Routes """
629
630 p = (Ether(src=self.pg0.remote_mac,
631 dst=self.pg0.local_mac) /
632 IP(src=self.pg0.remote_ip4, dst="1.1.1.1") /
633 UDP(sport=1234, dport=1234) /
634 Raw('\xa5' * 100))
635
636 r1 = VppIpRoute(self, "1.1.1.0", 24,
637 [VppRoutePath(self.pg1.remote_ip4,
638 self.pg1.sw_if_index)])
639 r1.add_vpp_config()
640
641 rx = self.send_and_expect(self.pg0, p * 65, self.pg1)
642
643 #
644 # insert a more specific as a drop
645 #
646 r2 = VppIpRoute(self, "1.1.1.1", 32, [], is_drop=1)
647 r2.add_vpp_config()
648
649 self.send_and_assert_no_replies(self.pg0, p * 65, "Drop Route")
650 r2.remove_vpp_config()
651 rx = self.send_and_expect(self.pg0, p * 65, self.pg1)
652
Neale Ranns37be7362017-02-21 17:30:26 -0800653
Neale Ranns180279b2017-03-16 15:49:09 -0400654class TestIPDisabled(VppTestCase):
655 """ IPv4 disabled """
656
657 def setUp(self):
658 super(TestIPDisabled, self).setUp()
659
660 # create 2 pg interfaces
661 self.create_pg_interfaces(range(2))
662
663 # PG0 is IP enalbed
664 self.pg0.admin_up()
665 self.pg0.config_ip4()
666 self.pg0.resolve_arp()
667
668 # PG 1 is not IP enabled
669 self.pg1.admin_up()
670
671 def tearDown(self):
672 super(TestIPDisabled, self).tearDown()
673 for i in self.pg_interfaces:
674 i.unconfig_ip4()
675 i.admin_down()
676
Neale Ranns180279b2017-03-16 15:49:09 -0400677 def test_ip_disabled(self):
678 """ IP Disabled """
679
680 #
681 # An (S,G).
682 # one accepting interface, pg0, 2 forwarding interfaces
683 #
684 route_232_1_1_1 = VppIpMRoute(
685 self,
686 "0.0.0.0",
687 "232.1.1.1", 32,
688 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
689 [VppMRoutePath(self.pg1.sw_if_index,
690 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
691 VppMRoutePath(self.pg0.sw_if_index,
692 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
693 route_232_1_1_1.add_vpp_config()
694
695 pu = (Ether(src=self.pg1.remote_mac,
696 dst=self.pg1.local_mac) /
697 IP(src="10.10.10.10", dst=self.pg0.remote_ip4) /
698 UDP(sport=1234, dport=1234) /
699 Raw('\xa5' * 100))
700 pm = (Ether(src=self.pg1.remote_mac,
701 dst=self.pg1.local_mac) /
702 IP(src="10.10.10.10", dst="232.1.1.1") /
703 UDP(sport=1234, dport=1234) /
704 Raw('\xa5' * 100))
705
706 #
707 # PG1 does not forward IP traffic
708 #
709 self.send_and_assert_no_replies(self.pg1, pu, "IP disabled")
710 self.send_and_assert_no_replies(self.pg1, pm, "IP disabled")
711
712 #
713 # IP enable PG1
714 #
715 self.pg1.config_ip4()
716
717 #
718 # Now we get packets through
719 #
720 self.pg1.add_stream(pu)
721 self.pg_enable_capture(self.pg_interfaces)
722 self.pg_start()
723 rx = self.pg0.get_capture(1)
724
725 self.pg1.add_stream(pm)
726 self.pg_enable_capture(self.pg_interfaces)
727 self.pg_start()
728 rx = self.pg0.get_capture(1)
729
730 #
731 # Disable PG1
732 #
733 self.pg1.unconfig_ip4()
734
735 #
736 # PG1 does not forward IP traffic
737 #
738 self.send_and_assert_no_replies(self.pg1, pu, "IP disabled")
739 self.send_and_assert_no_replies(self.pg1, pm, "IP disabled")
740
741
Neale Ranns9a69a602017-03-26 10:56:33 -0700742class TestIPSubNets(VppTestCase):
743 """ IPv4 Subnets """
744
745 def setUp(self):
746 super(TestIPSubNets, self).setUp()
747
748 # create a 2 pg interfaces
749 self.create_pg_interfaces(range(2))
750
751 # pg0 we will use to experiemnt
752 self.pg0.admin_up()
753
754 # pg1 is setup normally
755 self.pg1.admin_up()
756 self.pg1.config_ip4()
757 self.pg1.resolve_arp()
758
759 def tearDown(self):
760 super(TestIPSubNets, self).tearDown()
761 for i in self.pg_interfaces:
762 i.admin_down()
763
Neale Ranns9a69a602017-03-26 10:56:33 -0700764 def test_ip_sub_nets(self):
765 """ IP Sub Nets """
766
767 #
768 # Configure a covering route to forward so we know
769 # when we are dropping
770 #
771 cover_route = VppIpRoute(self, "10.0.0.0", 8,
772 [VppRoutePath(self.pg1.remote_ip4,
773 self.pg1.sw_if_index)])
774 cover_route.add_vpp_config()
775
776 p = (Ether(src=self.pg1.remote_mac,
777 dst=self.pg1.local_mac) /
778 IP(dst="10.10.10.10", src=self.pg0.local_ip4) /
779 UDP(sport=1234, dport=1234) /
780 Raw('\xa5' * 100))
781
782 self.pg1.add_stream(p)
783 self.pg_enable_capture(self.pg_interfaces)
784 self.pg_start()
785 rx = self.pg1.get_capture(1)
786
787 #
788 # Configure some non-/24 subnets on an IP interface
789 #
790 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.10.10.10")
791
792 self.vapi.sw_interface_add_del_address(self.pg0.sw_if_index,
793 ip_addr_n,
794 16)
795
796 pn = (Ether(src=self.pg1.remote_mac,
797 dst=self.pg1.local_mac) /
798 IP(dst="10.10.0.0", src=self.pg0.local_ip4) /
799 UDP(sport=1234, dport=1234) /
800 Raw('\xa5' * 100))
801 pb = (Ether(src=self.pg1.remote_mac,
802 dst=self.pg1.local_mac) /
803 IP(dst="10.10.255.255", src=self.pg0.local_ip4) /
804 UDP(sport=1234, dport=1234) /
805 Raw('\xa5' * 100))
806
807 self.send_and_assert_no_replies(self.pg1, pn, "IP Network address")
808 self.send_and_assert_no_replies(self.pg1, pb, "IP Broadcast address")
809
810 # remove the sub-net and we are forwarding via the cover again
811 self.vapi.sw_interface_add_del_address(self.pg0.sw_if_index,
812 ip_addr_n,
813 16,
814 is_add=0)
815 self.pg1.add_stream(pn)
816 self.pg_enable_capture(self.pg_interfaces)
817 self.pg_start()
818 rx = self.pg1.get_capture(1)
819 self.pg1.add_stream(pb)
820 self.pg_enable_capture(self.pg_interfaces)
821 self.pg_start()
822 rx = self.pg1.get_capture(1)
823
824 #
825 # A /31 is a special case where the 'other-side' is an attached host
826 # packets to that peer generate ARP requests
827 #
828 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.10.10.10")
829
830 self.vapi.sw_interface_add_del_address(self.pg0.sw_if_index,
831 ip_addr_n,
832 31)
833
834 pn = (Ether(src=self.pg1.remote_mac,
835 dst=self.pg1.local_mac) /
836 IP(dst="10.10.10.11", src=self.pg0.local_ip4) /
837 UDP(sport=1234, dport=1234) /
838 Raw('\xa5' * 100))
839
840 self.pg1.add_stream(pn)
841 self.pg_enable_capture(self.pg_interfaces)
842 self.pg_start()
843 rx = self.pg0.get_capture(1)
844 rx[ARP]
845
846 # remove the sub-net and we are forwarding via the cover again
847 self.vapi.sw_interface_add_del_address(self.pg0.sw_if_index,
848 ip_addr_n,
849 31,
850 is_add=0)
851 self.pg1.add_stream(pn)
852 self.pg_enable_capture(self.pg_interfaces)
853 self.pg_start()
854 rx = self.pg1.get_capture(1)
855
856
Neale Ranns227038a2017-04-21 01:07:59 -0700857class TestIPLoadBalance(VppTestCase):
858 """ IPv4 Load-Balancing """
859
860 def setUp(self):
861 super(TestIPLoadBalance, self).setUp()
862
863 self.create_pg_interfaces(range(5))
Neale Ranns15002542017-09-10 04:39:11 -0700864 mpls_tbl = VppMplsTable(self, 0)
865 mpls_tbl.add_vpp_config()
Neale Ranns227038a2017-04-21 01:07:59 -0700866
867 for i in self.pg_interfaces:
868 i.admin_up()
869 i.config_ip4()
870 i.resolve_arp()
Neale Ranns71275e32017-05-25 12:38:58 -0700871 i.enable_mpls()
Neale Ranns227038a2017-04-21 01:07:59 -0700872
873 def tearDown(self):
Neale Ranns227038a2017-04-21 01:07:59 -0700874 for i in self.pg_interfaces:
Neale Ranns71275e32017-05-25 12:38:58 -0700875 i.disable_mpls()
Neale Ranns227038a2017-04-21 01:07:59 -0700876 i.unconfig_ip4()
877 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -0700878 super(TestIPLoadBalance, self).tearDown()
Neale Ranns227038a2017-04-21 01:07:59 -0700879
880 def send_and_expect_load_balancing(self, input, pkts, outputs):
881 input.add_stream(pkts)
882 self.pg_enable_capture(self.pg_interfaces)
883 self.pg_start()
884 for oo in outputs:
885 rx = oo._get_capture(1)
886 self.assertNotEqual(0, len(rx))
887
Neale Ranns42e6b092017-07-31 02:56:03 -0700888 def send_and_expect_one_itf(self, input, pkts, itf):
889 input.add_stream(pkts)
890 self.pg_enable_capture(self.pg_interfaces)
891 self.pg_start()
892 rx = itf.get_capture(len(pkts))
893
Neale Ranns227038a2017-04-21 01:07:59 -0700894 def test_ip_load_balance(self):
895 """ IP Load-Balancing """
896
897 #
898 # An array of packets that differ only in the destination port
899 #
Neale Ranns71275e32017-05-25 12:38:58 -0700900 port_ip_pkts = []
901 port_mpls_pkts = []
Neale Ranns227038a2017-04-21 01:07:59 -0700902
903 #
904 # An array of packets that differ only in the source address
905 #
Neale Ranns71275e32017-05-25 12:38:58 -0700906 src_ip_pkts = []
907 src_mpls_pkts = []
Neale Ranns227038a2017-04-21 01:07:59 -0700908
909 for ii in range(65):
Neale Ranns71275e32017-05-25 12:38:58 -0700910 port_ip_hdr = (IP(dst="10.0.0.1", src="20.0.0.1") /
911 UDP(sport=1234, dport=1234 + ii) /
912 Raw('\xa5' * 100))
913 port_ip_pkts.append((Ether(src=self.pg0.remote_mac,
914 dst=self.pg0.local_mac) /
915 port_ip_hdr))
916 port_mpls_pkts.append((Ether(src=self.pg0.remote_mac,
917 dst=self.pg0.local_mac) /
918 MPLS(label=66, ttl=2) /
919 port_ip_hdr))
920
921 src_ip_hdr = (IP(dst="10.0.0.1", src="20.0.0.%d" % ii) /
922 UDP(sport=1234, dport=1234) /
923 Raw('\xa5' * 100))
924 src_ip_pkts.append((Ether(src=self.pg0.remote_mac,
925 dst=self.pg0.local_mac) /
926 src_ip_hdr))
927 src_mpls_pkts.append((Ether(src=self.pg0.remote_mac,
928 dst=self.pg0.local_mac) /
929 MPLS(label=66, ttl=2) /
930 src_ip_hdr))
Neale Ranns227038a2017-04-21 01:07:59 -0700931
932 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
933 [VppRoutePath(self.pg1.remote_ip4,
934 self.pg1.sw_if_index),
935 VppRoutePath(self.pg2.remote_ip4,
936 self.pg2.sw_if_index)])
937 route_10_0_0_1.add_vpp_config()
938
Neale Ranns71275e32017-05-25 12:38:58 -0700939 binding = VppMplsIpBind(self, 66, "10.0.0.1", 32)
940 binding.add_vpp_config()
941
Neale Ranns227038a2017-04-21 01:07:59 -0700942 #
943 # inject the packet on pg0 - expect load-balancing across the 2 paths
944 # - since the default hash config is to use IP src,dst and port
945 # src,dst
946 # We are not going to ensure equal amounts of packets across each link,
947 # since the hash algorithm is statistical and therefore this can never
948 # be guaranteed. But wuth 64 different packets we do expect some
949 # balancing. So instead just ensure there is traffic on each link.
950 #
Neale Ranns71275e32017-05-25 12:38:58 -0700951 self.send_and_expect_load_balancing(self.pg0, port_ip_pkts,
Neale Ranns227038a2017-04-21 01:07:59 -0700952 [self.pg1, self.pg2])
Neale Ranns71275e32017-05-25 12:38:58 -0700953 self.send_and_expect_load_balancing(self.pg0, src_ip_pkts,
954 [self.pg1, self.pg2])
955 self.send_and_expect_load_balancing(self.pg0, port_mpls_pkts,
956 [self.pg1, self.pg2])
957 self.send_and_expect_load_balancing(self.pg0, src_mpls_pkts,
Neale Ranns227038a2017-04-21 01:07:59 -0700958 [self.pg1, self.pg2])
959
960 #
961 # change the flow hash config so it's only IP src,dst
962 # - now only the stream with differing source address will
963 # load-balance
964 #
965 self.vapi.set_ip_flow_hash(0, src=1, dst=1, sport=0, dport=0)
966
Neale Ranns71275e32017-05-25 12:38:58 -0700967 self.send_and_expect_load_balancing(self.pg0, src_ip_pkts,
968 [self.pg1, self.pg2])
969 self.send_and_expect_load_balancing(self.pg0, src_mpls_pkts,
Neale Ranns227038a2017-04-21 01:07:59 -0700970 [self.pg1, self.pg2])
971
Neale Ranns42e6b092017-07-31 02:56:03 -0700972 self.send_and_expect_one_itf(self.pg0, port_ip_pkts, self.pg2)
Neale Ranns227038a2017-04-21 01:07:59 -0700973
974 #
975 # change the flow hash config back to defaults
976 #
977 self.vapi.set_ip_flow_hash(0, src=1, dst=1, sport=1, dport=1)
978
979 #
980 # Recursive prefixes
981 # - testing that 2 stages of load-balancing occurs and there is no
982 # polarisation (i.e. only 2 of 4 paths are used)
983 #
984 port_pkts = []
985 src_pkts = []
986
987 for ii in range(257):
988 port_pkts.append((Ether(src=self.pg0.remote_mac,
989 dst=self.pg0.local_mac) /
990 IP(dst="1.1.1.1", src="20.0.0.1") /
991 UDP(sport=1234, dport=1234 + ii) /
992 Raw('\xa5' * 100)))
993 src_pkts.append((Ether(src=self.pg0.remote_mac,
994 dst=self.pg0.local_mac) /
995 IP(dst="1.1.1.1", src="20.0.0.%d" % ii) /
996 UDP(sport=1234, dport=1234) /
997 Raw('\xa5' * 100)))
998
999 route_10_0_0_2 = VppIpRoute(self, "10.0.0.2", 32,
1000 [VppRoutePath(self.pg3.remote_ip4,
1001 self.pg3.sw_if_index),
1002 VppRoutePath(self.pg4.remote_ip4,
1003 self.pg4.sw_if_index)])
1004 route_10_0_0_2.add_vpp_config()
1005
1006 route_1_1_1_1 = VppIpRoute(self, "1.1.1.1", 32,
1007 [VppRoutePath("10.0.0.2", 0xffffffff),
1008 VppRoutePath("10.0.0.1", 0xffffffff)])
1009 route_1_1_1_1.add_vpp_config()
1010
1011 #
1012 # inject the packet on pg0 - expect load-balancing across all 4 paths
1013 #
1014 self.vapi.cli("clear trace")
1015 self.send_and_expect_load_balancing(self.pg0, port_pkts,
1016 [self.pg1, self.pg2,
1017 self.pg3, self.pg4])
1018 self.send_and_expect_load_balancing(self.pg0, src_pkts,
1019 [self.pg1, self.pg2,
1020 self.pg3, self.pg4])
1021
Neale Ranns42e6b092017-07-31 02:56:03 -07001022 #
1023 # Recursive prefixes
1024 # - testing that 2 stages of load-balancing, no choices
1025 #
1026 port_pkts = []
1027
1028 for ii in range(257):
1029 port_pkts.append((Ether(src=self.pg0.remote_mac,
1030 dst=self.pg0.local_mac) /
1031 IP(dst="1.1.1.2", src="20.0.0.2") /
1032 UDP(sport=1234, dport=1234 + ii) /
1033 Raw('\xa5' * 100)))
1034
1035 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
1036 [VppRoutePath(self.pg3.remote_ip4,
1037 self.pg3.sw_if_index)])
1038 route_10_0_0_3.add_vpp_config()
1039
1040 route_1_1_1_2 = VppIpRoute(self, "1.1.1.2", 32,
1041 [VppRoutePath("10.0.0.3", 0xffffffff)])
1042 route_1_1_1_2.add_vpp_config()
1043
1044 #
1045 # inject the packet on pg0 - expect load-balancing across all 4 paths
1046 #
1047 self.vapi.cli("clear trace")
1048 self.send_and_expect_one_itf(self.pg0, port_pkts, self.pg3)
1049
Neale Ranns30d0fd42017-05-30 07:30:04 -07001050
1051class TestIPVlan0(VppTestCase):
1052 """ IPv4 VLAN-0 """
1053
1054 def setUp(self):
1055 super(TestIPVlan0, self).setUp()
1056
1057 self.create_pg_interfaces(range(2))
Neale Ranns15002542017-09-10 04:39:11 -07001058 mpls_tbl = VppMplsTable(self, 0)
1059 mpls_tbl.add_vpp_config()
Neale Ranns30d0fd42017-05-30 07:30:04 -07001060
1061 for i in self.pg_interfaces:
1062 i.admin_up()
1063 i.config_ip4()
1064 i.resolve_arp()
1065 i.enable_mpls()
1066
1067 def tearDown(self):
Neale Ranns30d0fd42017-05-30 07:30:04 -07001068 for i in self.pg_interfaces:
1069 i.disable_mpls()
1070 i.unconfig_ip4()
1071 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07001072 super(TestIPVlan0, self).tearDown()
Neale Ranns30d0fd42017-05-30 07:30:04 -07001073
Neale Ranns30d0fd42017-05-30 07:30:04 -07001074 def test_ip_vlan_0(self):
1075 """ IP VLAN-0 """
1076
1077 pkts = (Ether(src=self.pg0.remote_mac,
1078 dst=self.pg0.local_mac) /
1079 Dot1Q(vlan=0) /
1080 IP(dst=self.pg1.remote_ip4,
1081 src=self.pg0.remote_ip4) /
1082 UDP(sport=1234, dport=1234) /
1083 Raw('\xa5' * 100)) * 65
1084
1085 #
1086 # Expect that packets sent on VLAN-0 are forwarded on the
1087 # main interface.
1088 #
1089 self.send_and_expect(self.pg0, pkts, self.pg1)
1090
1091
Neale Rannsd91c1db2017-07-31 02:30:50 -07001092class TestIPPunt(VppTestCase):
1093 """ IPv4 Punt Police/Redirect """
1094
1095 def setUp(self):
1096 super(TestIPPunt, self).setUp()
1097
1098 self.create_pg_interfaces(range(2))
1099
1100 for i in self.pg_interfaces:
1101 i.admin_up()
1102 i.config_ip4()
1103 i.resolve_arp()
1104
1105 def tearDown(self):
1106 super(TestIPPunt, self).tearDown()
1107 for i in self.pg_interfaces:
1108 i.unconfig_ip4()
1109 i.admin_down()
1110
Neale Rannsd91c1db2017-07-31 02:30:50 -07001111 def test_ip_punt(self):
1112 """ IP punt police and redirect """
1113
1114 p = (Ether(src=self.pg0.remote_mac,
1115 dst=self.pg0.local_mac) /
1116 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
1117 TCP(sport=1234, dport=1234) /
1118 Raw('\xa5' * 100))
1119
1120 pkts = p * 1025
1121
1122 #
1123 # Configure a punt redirect via pg1.
1124 #
1125 nh_addr = socket.inet_pton(socket.AF_INET,
1126 self.pg1.remote_ip4)
1127 self.vapi.ip_punt_redirect(self.pg0.sw_if_index,
1128 self.pg1.sw_if_index,
1129 nh_addr)
1130
1131 self.send_and_expect(self.pg0, pkts, self.pg1)
1132
1133 #
1134 # add a policer
1135 #
1136 policer = self.vapi.policer_add_del("ip4-punt", 400, 0, 10, 0,
1137 rate_type=1)
1138 self.vapi.ip_punt_police(policer.policer_index)
1139
1140 self.vapi.cli("clear trace")
1141 self.pg0.add_stream(pkts)
1142 self.pg_enable_capture(self.pg_interfaces)
1143 self.pg_start()
1144
1145 #
1146 # the number of packet recieved should be greater than 0,
1147 # but not equal to the number sent, since some were policed
1148 #
1149 rx = self.pg1._get_capture(1)
1150 self.assertTrue(len(rx) > 0)
1151 self.assertTrue(len(rx) < len(pkts))
1152
1153 #
1154 # remove the poilcer. back to full rx
1155 #
1156 self.vapi.ip_punt_police(policer.policer_index, is_add=0)
1157 self.vapi.policer_add_del("ip4-punt", 400, 0, 10, 0,
1158 rate_type=1, is_add=0)
1159 self.send_and_expect(self.pg0, pkts, self.pg1)
1160
1161 #
1162 # remove the redirect. expect full drop.
1163 #
1164 self.vapi.ip_punt_redirect(self.pg0.sw_if_index,
1165 self.pg1.sw_if_index,
1166 nh_addr,
1167 is_add=0)
1168 self.send_and_assert_no_replies(self.pg0, pkts,
1169 "IP no punt config")
1170
1171 #
1172 # Add a redirect that is not input port selective
1173 #
1174 self.vapi.ip_punt_redirect(0xffffffff,
1175 self.pg1.sw_if_index,
1176 nh_addr)
1177 self.send_and_expect(self.pg0, pkts, self.pg1)
1178
1179 self.vapi.ip_punt_redirect(0xffffffff,
1180 self.pg1.sw_if_index,
1181 nh_addr,
1182 is_add=0)
1183
1184
Neale Ranns054c03a2017-10-13 05:15:07 -07001185class TestIPDeag(VppTestCase):
1186 """ IPv4 Deaggregate Routes """
1187
1188 def setUp(self):
1189 super(TestIPDeag, self).setUp()
1190
1191 self.create_pg_interfaces(range(3))
1192
1193 for i in self.pg_interfaces:
1194 i.admin_up()
1195 i.config_ip4()
1196 i.resolve_arp()
1197
1198 def tearDown(self):
1199 super(TestIPDeag, self).tearDown()
1200 for i in self.pg_interfaces:
1201 i.unconfig_ip4()
1202 i.admin_down()
1203
Neale Ranns054c03a2017-10-13 05:15:07 -07001204 def test_ip_deag(self):
1205 """ IP Deag Routes """
1206
1207 #
1208 # Create a table to be used for:
1209 # 1 - another destination address lookup
1210 # 2 - a source address lookup
1211 #
1212 table_dst = VppIpTable(self, 1)
1213 table_src = VppIpTable(self, 2)
1214 table_dst.add_vpp_config()
1215 table_src.add_vpp_config()
1216
1217 #
1218 # Add a route in the default table to point to a deag/
1219 # second lookup in each of these tables
1220 #
1221 route_to_dst = VppIpRoute(self, "1.1.1.1", 32,
1222 [VppRoutePath("0.0.0.0",
1223 0xffffffff,
1224 nh_table_id=1)])
1225 route_to_src = VppIpRoute(self, "1.1.1.2", 32,
1226 [VppRoutePath("0.0.0.0",
1227 0xffffffff,
1228 nh_table_id=2,
1229 is_source_lookup=1)])
1230 route_to_dst.add_vpp_config()
1231 route_to_src.add_vpp_config()
1232
1233 #
1234 # packets to these destination are dropped, since they'll
1235 # hit the respective default routes in the second table
1236 #
1237 p_dst = (Ether(src=self.pg0.remote_mac,
1238 dst=self.pg0.local_mac) /
1239 IP(src="5.5.5.5", dst="1.1.1.1") /
1240 TCP(sport=1234, dport=1234) /
1241 Raw('\xa5' * 100))
1242 p_src = (Ether(src=self.pg0.remote_mac,
1243 dst=self.pg0.local_mac) /
1244 IP(src="2.2.2.2", dst="1.1.1.2") /
1245 TCP(sport=1234, dport=1234) /
1246 Raw('\xa5' * 100))
1247 pkts_dst = p_dst * 257
1248 pkts_src = p_src * 257
1249
1250 self.send_and_assert_no_replies(self.pg0, pkts_dst,
1251 "IP in dst table")
1252 self.send_and_assert_no_replies(self.pg0, pkts_src,
1253 "IP in src table")
1254
1255 #
1256 # add a route in the dst table to forward via pg1
1257 #
1258 route_in_dst = VppIpRoute(self, "1.1.1.1", 32,
1259 [VppRoutePath(self.pg1.remote_ip4,
1260 self.pg1.sw_if_index)],
1261 table_id=1)
1262 route_in_dst.add_vpp_config()
1263 self.send_and_expect(self.pg0, pkts_dst, self.pg1)
1264
1265 #
1266 # add a route in the src table to forward via pg2
1267 #
1268 route_in_src = VppIpRoute(self, "2.2.2.2", 32,
1269 [VppRoutePath(self.pg2.remote_ip4,
1270 self.pg2.sw_if_index)],
1271 table_id=2)
1272 route_in_src.add_vpp_config()
1273 self.send_and_expect(self.pg0, pkts_src, self.pg2)
1274
Neale Rannsce9e0b42018-08-01 12:53:17 -07001275 #
1276 # loop in the lookup DP
1277 #
1278 route_loop = VppIpRoute(self, "2.2.2.3", 32,
1279 [VppRoutePath("0.0.0.0",
1280 0xffffffff,
1281 nh_table_id=0)])
1282 route_loop.add_vpp_config()
1283
1284 p_l = (Ether(src=self.pg0.remote_mac,
1285 dst=self.pg0.local_mac) /
1286 IP(src="2.2.2.4", dst="2.2.2.3") /
1287 TCP(sport=1234, dport=1234) /
1288 Raw('\xa5' * 100))
1289
1290 self.send_and_assert_no_replies(self.pg0, p_l * 257,
1291 "IP lookup loop")
1292
Neale Ranns054c03a2017-10-13 05:15:07 -07001293
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001294class TestIPInput(VppTestCase):
1295 """ IPv4 Input Exceptions """
1296
1297 def setUp(self):
1298 super(TestIPInput, self).setUp()
1299
1300 self.create_pg_interfaces(range(2))
1301
1302 for i in self.pg_interfaces:
1303 i.admin_up()
1304 i.config_ip4()
1305 i.resolve_arp()
1306
1307 def tearDown(self):
1308 super(TestIPInput, self).tearDown()
1309 for i in self.pg_interfaces:
1310 i.unconfig_ip4()
1311 i.admin_down()
1312
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001313 def test_ip_input(self):
1314 """ IP Input Exceptions """
1315
1316 # i can't find a way in scapy to construct an IP packet
1317 # with a length less than the IP header length
1318
1319 #
1320 # Packet too short - this is forwarded
1321 #
1322 p_short = (Ether(src=self.pg0.remote_mac,
1323 dst=self.pg0.local_mac) /
1324 IP(src=self.pg0.remote_ip4,
1325 dst=self.pg1.remote_ip4,
1326 len=40) /
1327 UDP(sport=1234, dport=1234) /
1328 Raw('\xa5' * 100))
1329
1330 rx = self.send_and_expect(self.pg0, p_short * 65, self.pg1)
1331
1332 #
1333 # Packet too long - this is dropped
1334 #
1335 p_long = (Ether(src=self.pg0.remote_mac,
1336 dst=self.pg0.local_mac) /
1337 IP(src=self.pg0.remote_ip4,
1338 dst=self.pg1.remote_ip4,
1339 len=400) /
1340 UDP(sport=1234, dport=1234) /
1341 Raw('\xa5' * 100))
1342
1343 rx = self.send_and_assert_no_replies(self.pg0, p_long * 65,
1344 "too long")
1345
1346 #
1347 # bad chksum - this is dropped
1348 #
1349 p_chksum = (Ether(src=self.pg0.remote_mac,
1350 dst=self.pg0.local_mac) /
1351 IP(src=self.pg0.remote_ip4,
1352 dst=self.pg1.remote_ip4,
1353 chksum=400) /
1354 UDP(sport=1234, dport=1234) /
1355 Raw('\xa5' * 100))
1356
1357 rx = self.send_and_assert_no_replies(self.pg0, p_chksum * 65,
1358 "bad checksum")
1359
1360 #
1361 # bad version - this is dropped
1362 #
1363 p_ver = (Ether(src=self.pg0.remote_mac,
1364 dst=self.pg0.local_mac) /
1365 IP(src=self.pg0.remote_ip4,
1366 dst=self.pg1.remote_ip4,
1367 version=3) /
1368 UDP(sport=1234, dport=1234) /
1369 Raw('\xa5' * 100))
1370
1371 rx = self.send_and_assert_no_replies(self.pg0, p_ver * 65,
1372 "funky version")
1373
1374 #
1375 # fragment offset 1 - this is dropped
1376 #
1377 p_frag = (Ether(src=self.pg0.remote_mac,
1378 dst=self.pg0.local_mac) /
1379 IP(src=self.pg0.remote_ip4,
1380 dst=self.pg1.remote_ip4,
1381 frag=1) /
1382 UDP(sport=1234, dport=1234) /
1383 Raw('\xa5' * 100))
1384
1385 rx = self.send_and_assert_no_replies(self.pg0, p_frag * 65,
1386 "frag offset")
1387
1388 #
1389 # TTL expired packet
1390 #
1391 p_ttl = (Ether(src=self.pg0.remote_mac,
1392 dst=self.pg0.local_mac) /
1393 IP(src=self.pg0.remote_ip4,
1394 dst=self.pg1.remote_ip4,
1395 ttl=1) /
1396 UDP(sport=1234, dport=1234) /
1397 Raw('\xa5' * 100))
1398
1399 rx = self.send_and_expect(self.pg0, p_ttl * 65, self.pg0)
1400
1401 rx = rx[0]
1402 icmp = rx[ICMP]
1403
1404 self.assertEqual(icmptypes[icmp.type], "time-exceeded")
1405 self.assertEqual(icmpcodes[icmp.type][icmp.code],
1406 "ttl-zero-during-transit")
1407 self.assertEqual(icmp.src, self.pg0.remote_ip4)
1408 self.assertEqual(icmp.dst, self.pg1.remote_ip4)
1409
Neale Rannsffd78d12018-02-09 06:05:16 -08001410 #
1411 # MTU exceeded
1412 #
1413 p_mtu = (Ether(src=self.pg0.remote_mac,
1414 dst=self.pg0.local_mac) /
1415 IP(src=self.pg0.remote_ip4,
1416 dst=self.pg1.remote_ip4,
Ole Troan8a9c8f12018-05-18 11:01:31 +02001417 ttl=10, flags='DF') /
Neale Rannsffd78d12018-02-09 06:05:16 -08001418 UDP(sport=1234, dport=1234) /
1419 Raw('\xa5' * 2000))
1420
Ole Troand7231612018-06-07 10:17:57 +02001421 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1500, 0, 0, 0])
Neale Rannsffd78d12018-02-09 06:05:16 -08001422
1423 rx = self.send_and_expect(self.pg0, p_mtu * 65, self.pg0)
1424 rx = rx[0]
1425 icmp = rx[ICMP]
1426
1427 self.assertEqual(icmptypes[icmp.type], "dest-unreach")
1428 self.assertEqual(icmpcodes[icmp.type][icmp.code],
1429 "fragmentation-needed")
1430 self.assertEqual(icmp.src, self.pg0.remote_ip4)
1431 self.assertEqual(icmp.dst, self.pg1.remote_ip4)
1432
Ole Troand7231612018-06-07 10:17:57 +02001433 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [2500, 0, 0, 0])
Neale Rannsffd78d12018-02-09 06:05:16 -08001434 rx = self.send_and_expect(self.pg0, p_mtu * 65, self.pg1)
1435
Ole Troand7231612018-06-07 10:17:57 +02001436 # Reset MTU for subsequent tests
1437 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [9000, 0, 0, 0])
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001438
Neale Ranns1855b8e2018-07-11 10:31:26 -07001439
1440class TestIPDirectedBroadcast(VppTestCase):
1441 """ IPv4 Directed Broadcast """
1442
1443 def setUp(self):
1444 super(TestIPDirectedBroadcast, self).setUp()
1445
1446 self.create_pg_interfaces(range(2))
1447
1448 for i in self.pg_interfaces:
1449 i.admin_up()
1450
1451 def tearDown(self):
1452 super(TestIPDirectedBroadcast, self).tearDown()
1453 for i in self.pg_interfaces:
1454 i.admin_down()
1455
1456 def test_ip_input(self):
1457 """ IP Directed Broadcast """
1458
1459 #
1460 # set the directed broadcast on pg0 first, then config IP4 addresses
1461 # for pg1 directed broadcast is always disabled
1462 self.vapi.sw_interface_set_ip_directed_broadcast(
1463 self.pg0.sw_if_index, 1)
1464
1465 p0 = (Ether(src=self.pg1.remote_mac,
1466 dst=self.pg1.local_mac) /
1467 IP(src="1.1.1.1",
1468 dst=self.pg0._local_ip4_bcast) /
1469 UDP(sport=1234, dport=1234) /
1470 Raw('\xa5' * 2000))
1471 p1 = (Ether(src=self.pg0.remote_mac,
1472 dst=self.pg0.local_mac) /
1473 IP(src="1.1.1.1",
1474 dst=self.pg1._local_ip4_bcast) /
1475 UDP(sport=1234, dport=1234) /
1476 Raw('\xa5' * 2000))
1477
1478 self.pg0.config_ip4()
1479 self.pg0.resolve_arp()
1480 self.pg1.config_ip4()
1481 self.pg1.resolve_arp()
1482
1483 #
1484 # test packet is L2 broadcast
1485 #
1486 rx = self.send_and_expect(self.pg1, p0 * 65, self.pg0)
1487 self.assertTrue(rx[0][Ether].dst, "ff:ff:ff:ff:ff:ff")
1488
1489 self.send_and_assert_no_replies(self.pg0, p1 * 65,
1490 "directed broadcast disabled")
1491
1492 #
1493 # toggle directed broadcast on pg0
1494 #
1495 self.vapi.sw_interface_set_ip_directed_broadcast(
1496 self.pg0.sw_if_index, 0)
1497 self.send_and_assert_no_replies(self.pg1, p0 * 65,
1498 "directed broadcast disabled")
1499
1500 self.vapi.sw_interface_set_ip_directed_broadcast(
1501 self.pg0.sw_if_index, 1)
1502 rx = self.send_and_expect(self.pg1, p0 * 65, self.pg0)
1503
1504 self.pg0.unconfig_ip4()
1505 self.pg1.unconfig_ip4()
1506
1507
mu.duojiao59a82952018-10-11 14:27:30 +08001508class TestIPLPM(VppTestCase):
1509 """ IPv4 longest Prefix Match """
1510
1511 def setUp(self):
1512 super(TestIPLPM, self).setUp()
1513
1514 self.create_pg_interfaces(range(4))
1515
1516 for i in self.pg_interfaces:
1517 i.admin_up()
1518 i.config_ip4()
1519 i.resolve_arp()
1520
1521 def tearDown(self):
1522 super(TestIPLPM, self).tearDown()
1523 for i in self.pg_interfaces:
1524 i.admin_down()
1525 i.unconfig_ip4()
1526
1527 def test_ip_lpm(self):
1528 """ IP longest Prefix Match """
1529
1530 s_24 = VppIpRoute(self, "10.1.2.0", 24,
1531 [VppRoutePath(self.pg1.remote_ip4,
1532 self.pg1.sw_if_index)])
1533 s_24.add_vpp_config()
1534 s_8 = VppIpRoute(self, "10.0.0.0", 8,
1535 [VppRoutePath(self.pg2.remote_ip4,
1536 self.pg2.sw_if_index)])
1537 s_8.add_vpp_config()
1538
1539 p_8 = (Ether(src=self.pg0.remote_mac,
1540 dst=self.pg0.local_mac) /
1541 IP(src="1.1.1.1",
1542 dst="10.1.1.1") /
1543 UDP(sport=1234, dport=1234) /
1544 Raw('\xa5' * 2000))
1545 p_24 = (Ether(src=self.pg0.remote_mac,
1546 dst=self.pg0.local_mac) /
1547 IP(src="1.1.1.1",
1548 dst="10.1.2.1") /
1549 UDP(sport=1234, dport=1234) /
1550 Raw('\xa5' * 2000))
1551
1552 self.logger.info(self.vapi.cli("sh ip fib mtrie"))
1553 rx = self.send_and_expect(self.pg0, p_8 * 65, self.pg2)
1554 rx = self.send_and_expect(self.pg0, p_24 * 65, self.pg1)
1555
1556
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02001557class TestIPv4Frag(VppTestCase):
1558 """ IPv4 fragmentation """
1559
1560 @classmethod
1561 def setUpClass(cls):
1562 super(TestIPv4Frag, cls).setUpClass()
1563
1564 cls.create_pg_interfaces([0, 1])
1565 cls.src_if = cls.pg0
1566 cls.dst_if = cls.pg1
1567
1568 # setup all interfaces
1569 for i in cls.pg_interfaces:
1570 i.admin_up()
1571 i.config_ip4()
1572 i.resolve_arp()
1573
1574 def test_frag_large_packets(self):
1575 """ Fragmentation of large packets """
1576
1577 p = (Ether(dst=self.src_if.local_mac, src=self.src_if.remote_mac) /
1578 IP(src=self.src_if.remote_ip4, dst=self.dst_if.remote_ip4) /
1579 UDP(sport=1234, dport=5678) / Raw())
1580 self.extend_packet(p, 6000, "abcde")
1581 saved_payload = p[Raw].load
1582
1583 # Force fragmentation by setting MTU of output interface
1584 # lower than packet size
1585 self.vapi.sw_interface_set_mtu(self.dst_if.sw_if_index,
1586 [5000, 0, 0, 0])
1587
1588 self.pg_enable_capture()
1589 self.src_if.add_stream(p)
1590 self.pg_start()
1591
1592 # Expecting 3 fragments because size of created fragments currently
1593 # cannot be larger then VPP buffer size (which is 2048)
1594 packets = self.dst_if.get_capture(3)
1595
1596 # Assume VPP sends the fragments in order
1597 payload = ''
1598 for p in packets:
1599 payload_offset = p.frag * 8
1600 if payload_offset > 0:
1601 payload_offset -= 8 # UDP header is not in payload
1602 self.assert_equal(payload_offset, len(payload))
1603 payload += p[Raw].load
1604 self.assert_equal(payload, saved_payload, "payload")
1605
1606
Damjan Marionf56b77a2016-10-03 19:44:57 +02001607if __name__ == '__main__':
Klement Sekeraf62ae122016-10-11 11:47:09 +02001608 unittest.main(testRunner=VppTestRunner)