blob: d15453d4f33575c3b989082275e51c17ccb82914 [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
555 self.create_pg_interfaces(range(1))
556
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
627
Neale Ranns180279b2017-03-16 15:49:09 -0400628class TestIPDisabled(VppTestCase):
629 """ IPv4 disabled """
630
631 def setUp(self):
632 super(TestIPDisabled, self).setUp()
633
634 # create 2 pg interfaces
635 self.create_pg_interfaces(range(2))
636
637 # PG0 is IP enalbed
638 self.pg0.admin_up()
639 self.pg0.config_ip4()
640 self.pg0.resolve_arp()
641
642 # PG 1 is not IP enabled
643 self.pg1.admin_up()
644
645 def tearDown(self):
646 super(TestIPDisabled, self).tearDown()
647 for i in self.pg_interfaces:
648 i.unconfig_ip4()
649 i.admin_down()
650
Neale Ranns180279b2017-03-16 15:49:09 -0400651 def test_ip_disabled(self):
652 """ IP Disabled """
653
654 #
655 # An (S,G).
656 # one accepting interface, pg0, 2 forwarding interfaces
657 #
658 route_232_1_1_1 = VppIpMRoute(
659 self,
660 "0.0.0.0",
661 "232.1.1.1", 32,
662 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
663 [VppMRoutePath(self.pg1.sw_if_index,
664 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
665 VppMRoutePath(self.pg0.sw_if_index,
666 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
667 route_232_1_1_1.add_vpp_config()
668
669 pu = (Ether(src=self.pg1.remote_mac,
670 dst=self.pg1.local_mac) /
671 IP(src="10.10.10.10", dst=self.pg0.remote_ip4) /
672 UDP(sport=1234, dport=1234) /
673 Raw('\xa5' * 100))
674 pm = (Ether(src=self.pg1.remote_mac,
675 dst=self.pg1.local_mac) /
676 IP(src="10.10.10.10", dst="232.1.1.1") /
677 UDP(sport=1234, dport=1234) /
678 Raw('\xa5' * 100))
679
680 #
681 # PG1 does not forward IP traffic
682 #
683 self.send_and_assert_no_replies(self.pg1, pu, "IP disabled")
684 self.send_and_assert_no_replies(self.pg1, pm, "IP disabled")
685
686 #
687 # IP enable PG1
688 #
689 self.pg1.config_ip4()
690
691 #
692 # Now we get packets through
693 #
694 self.pg1.add_stream(pu)
695 self.pg_enable_capture(self.pg_interfaces)
696 self.pg_start()
697 rx = self.pg0.get_capture(1)
698
699 self.pg1.add_stream(pm)
700 self.pg_enable_capture(self.pg_interfaces)
701 self.pg_start()
702 rx = self.pg0.get_capture(1)
703
704 #
705 # Disable PG1
706 #
707 self.pg1.unconfig_ip4()
708
709 #
710 # PG1 does not forward IP traffic
711 #
712 self.send_and_assert_no_replies(self.pg1, pu, "IP disabled")
713 self.send_and_assert_no_replies(self.pg1, pm, "IP disabled")
714
715
Neale Ranns9a69a602017-03-26 10:56:33 -0700716class TestIPSubNets(VppTestCase):
717 """ IPv4 Subnets """
718
719 def setUp(self):
720 super(TestIPSubNets, self).setUp()
721
722 # create a 2 pg interfaces
723 self.create_pg_interfaces(range(2))
724
725 # pg0 we will use to experiemnt
726 self.pg0.admin_up()
727
728 # pg1 is setup normally
729 self.pg1.admin_up()
730 self.pg1.config_ip4()
731 self.pg1.resolve_arp()
732
733 def tearDown(self):
734 super(TestIPSubNets, self).tearDown()
735 for i in self.pg_interfaces:
736 i.admin_down()
737
Neale Ranns9a69a602017-03-26 10:56:33 -0700738 def test_ip_sub_nets(self):
739 """ IP Sub Nets """
740
741 #
742 # Configure a covering route to forward so we know
743 # when we are dropping
744 #
745 cover_route = VppIpRoute(self, "10.0.0.0", 8,
746 [VppRoutePath(self.pg1.remote_ip4,
747 self.pg1.sw_if_index)])
748 cover_route.add_vpp_config()
749
750 p = (Ether(src=self.pg1.remote_mac,
751 dst=self.pg1.local_mac) /
752 IP(dst="10.10.10.10", src=self.pg0.local_ip4) /
753 UDP(sport=1234, dport=1234) /
754 Raw('\xa5' * 100))
755
756 self.pg1.add_stream(p)
757 self.pg_enable_capture(self.pg_interfaces)
758 self.pg_start()
759 rx = self.pg1.get_capture(1)
760
761 #
762 # Configure some non-/24 subnets on an IP interface
763 #
764 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.10.10.10")
765
766 self.vapi.sw_interface_add_del_address(self.pg0.sw_if_index,
767 ip_addr_n,
768 16)
769
770 pn = (Ether(src=self.pg1.remote_mac,
771 dst=self.pg1.local_mac) /
772 IP(dst="10.10.0.0", src=self.pg0.local_ip4) /
773 UDP(sport=1234, dport=1234) /
774 Raw('\xa5' * 100))
775 pb = (Ether(src=self.pg1.remote_mac,
776 dst=self.pg1.local_mac) /
777 IP(dst="10.10.255.255", src=self.pg0.local_ip4) /
778 UDP(sport=1234, dport=1234) /
779 Raw('\xa5' * 100))
780
781 self.send_and_assert_no_replies(self.pg1, pn, "IP Network address")
782 self.send_and_assert_no_replies(self.pg1, pb, "IP Broadcast address")
783
784 # remove the sub-net and we are forwarding via the cover again
785 self.vapi.sw_interface_add_del_address(self.pg0.sw_if_index,
786 ip_addr_n,
787 16,
788 is_add=0)
789 self.pg1.add_stream(pn)
790 self.pg_enable_capture(self.pg_interfaces)
791 self.pg_start()
792 rx = self.pg1.get_capture(1)
793 self.pg1.add_stream(pb)
794 self.pg_enable_capture(self.pg_interfaces)
795 self.pg_start()
796 rx = self.pg1.get_capture(1)
797
798 #
799 # A /31 is a special case where the 'other-side' is an attached host
800 # packets to that peer generate ARP requests
801 #
802 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.10.10.10")
803
804 self.vapi.sw_interface_add_del_address(self.pg0.sw_if_index,
805 ip_addr_n,
806 31)
807
808 pn = (Ether(src=self.pg1.remote_mac,
809 dst=self.pg1.local_mac) /
810 IP(dst="10.10.10.11", src=self.pg0.local_ip4) /
811 UDP(sport=1234, dport=1234) /
812 Raw('\xa5' * 100))
813
814 self.pg1.add_stream(pn)
815 self.pg_enable_capture(self.pg_interfaces)
816 self.pg_start()
817 rx = self.pg0.get_capture(1)
818 rx[ARP]
819
820 # remove the sub-net and we are forwarding via the cover again
821 self.vapi.sw_interface_add_del_address(self.pg0.sw_if_index,
822 ip_addr_n,
823 31,
824 is_add=0)
825 self.pg1.add_stream(pn)
826 self.pg_enable_capture(self.pg_interfaces)
827 self.pg_start()
828 rx = self.pg1.get_capture(1)
829
830
Neale Ranns227038a2017-04-21 01:07:59 -0700831class TestIPLoadBalance(VppTestCase):
832 """ IPv4 Load-Balancing """
833
834 def setUp(self):
835 super(TestIPLoadBalance, self).setUp()
836
837 self.create_pg_interfaces(range(5))
Neale Ranns15002542017-09-10 04:39:11 -0700838 mpls_tbl = VppMplsTable(self, 0)
839 mpls_tbl.add_vpp_config()
Neale Ranns227038a2017-04-21 01:07:59 -0700840
841 for i in self.pg_interfaces:
842 i.admin_up()
843 i.config_ip4()
844 i.resolve_arp()
Neale Ranns71275e32017-05-25 12:38:58 -0700845 i.enable_mpls()
Neale Ranns227038a2017-04-21 01:07:59 -0700846
847 def tearDown(self):
Neale Ranns227038a2017-04-21 01:07:59 -0700848 for i in self.pg_interfaces:
Neale Ranns71275e32017-05-25 12:38:58 -0700849 i.disable_mpls()
Neale Ranns227038a2017-04-21 01:07:59 -0700850 i.unconfig_ip4()
851 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -0700852 super(TestIPLoadBalance, self).tearDown()
Neale Ranns227038a2017-04-21 01:07:59 -0700853
854 def send_and_expect_load_balancing(self, input, pkts, outputs):
855 input.add_stream(pkts)
856 self.pg_enable_capture(self.pg_interfaces)
857 self.pg_start()
858 for oo in outputs:
859 rx = oo._get_capture(1)
860 self.assertNotEqual(0, len(rx))
861
Neale Ranns42e6b092017-07-31 02:56:03 -0700862 def send_and_expect_one_itf(self, input, pkts, itf):
863 input.add_stream(pkts)
864 self.pg_enable_capture(self.pg_interfaces)
865 self.pg_start()
866 rx = itf.get_capture(len(pkts))
867
Neale Ranns227038a2017-04-21 01:07:59 -0700868 def test_ip_load_balance(self):
869 """ IP Load-Balancing """
870
871 #
872 # An array of packets that differ only in the destination port
873 #
Neale Ranns71275e32017-05-25 12:38:58 -0700874 port_ip_pkts = []
875 port_mpls_pkts = []
Neale Ranns227038a2017-04-21 01:07:59 -0700876
877 #
878 # An array of packets that differ only in the source address
879 #
Neale Ranns71275e32017-05-25 12:38:58 -0700880 src_ip_pkts = []
881 src_mpls_pkts = []
Neale Ranns227038a2017-04-21 01:07:59 -0700882
883 for ii in range(65):
Neale Ranns71275e32017-05-25 12:38:58 -0700884 port_ip_hdr = (IP(dst="10.0.0.1", src="20.0.0.1") /
885 UDP(sport=1234, dport=1234 + ii) /
886 Raw('\xa5' * 100))
887 port_ip_pkts.append((Ether(src=self.pg0.remote_mac,
888 dst=self.pg0.local_mac) /
889 port_ip_hdr))
890 port_mpls_pkts.append((Ether(src=self.pg0.remote_mac,
891 dst=self.pg0.local_mac) /
892 MPLS(label=66, ttl=2) /
893 port_ip_hdr))
894
895 src_ip_hdr = (IP(dst="10.0.0.1", src="20.0.0.%d" % ii) /
896 UDP(sport=1234, dport=1234) /
897 Raw('\xa5' * 100))
898 src_ip_pkts.append((Ether(src=self.pg0.remote_mac,
899 dst=self.pg0.local_mac) /
900 src_ip_hdr))
901 src_mpls_pkts.append((Ether(src=self.pg0.remote_mac,
902 dst=self.pg0.local_mac) /
903 MPLS(label=66, ttl=2) /
904 src_ip_hdr))
Neale Ranns227038a2017-04-21 01:07:59 -0700905
906 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
907 [VppRoutePath(self.pg1.remote_ip4,
908 self.pg1.sw_if_index),
909 VppRoutePath(self.pg2.remote_ip4,
910 self.pg2.sw_if_index)])
911 route_10_0_0_1.add_vpp_config()
912
Neale Ranns71275e32017-05-25 12:38:58 -0700913 binding = VppMplsIpBind(self, 66, "10.0.0.1", 32)
914 binding.add_vpp_config()
915
Neale Ranns227038a2017-04-21 01:07:59 -0700916 #
917 # inject the packet on pg0 - expect load-balancing across the 2 paths
918 # - since the default hash config is to use IP src,dst and port
919 # src,dst
920 # We are not going to ensure equal amounts of packets across each link,
921 # since the hash algorithm is statistical and therefore this can never
922 # be guaranteed. But wuth 64 different packets we do expect some
923 # balancing. So instead just ensure there is traffic on each link.
924 #
Neale Ranns71275e32017-05-25 12:38:58 -0700925 self.send_and_expect_load_balancing(self.pg0, port_ip_pkts,
Neale Ranns227038a2017-04-21 01:07:59 -0700926 [self.pg1, self.pg2])
Neale Ranns71275e32017-05-25 12:38:58 -0700927 self.send_and_expect_load_balancing(self.pg0, src_ip_pkts,
928 [self.pg1, self.pg2])
929 self.send_and_expect_load_balancing(self.pg0, port_mpls_pkts,
930 [self.pg1, self.pg2])
931 self.send_and_expect_load_balancing(self.pg0, src_mpls_pkts,
Neale Ranns227038a2017-04-21 01:07:59 -0700932 [self.pg1, self.pg2])
933
934 #
935 # change the flow hash config so it's only IP src,dst
936 # - now only the stream with differing source address will
937 # load-balance
938 #
939 self.vapi.set_ip_flow_hash(0, src=1, dst=1, sport=0, dport=0)
940
Neale Ranns71275e32017-05-25 12:38:58 -0700941 self.send_and_expect_load_balancing(self.pg0, src_ip_pkts,
942 [self.pg1, self.pg2])
943 self.send_and_expect_load_balancing(self.pg0, src_mpls_pkts,
Neale Ranns227038a2017-04-21 01:07:59 -0700944 [self.pg1, self.pg2])
945
Neale Ranns42e6b092017-07-31 02:56:03 -0700946 self.send_and_expect_one_itf(self.pg0, port_ip_pkts, self.pg2)
Neale Ranns227038a2017-04-21 01:07:59 -0700947
948 #
949 # change the flow hash config back to defaults
950 #
951 self.vapi.set_ip_flow_hash(0, src=1, dst=1, sport=1, dport=1)
952
953 #
954 # Recursive prefixes
955 # - testing that 2 stages of load-balancing occurs and there is no
956 # polarisation (i.e. only 2 of 4 paths are used)
957 #
958 port_pkts = []
959 src_pkts = []
960
961 for ii in range(257):
962 port_pkts.append((Ether(src=self.pg0.remote_mac,
963 dst=self.pg0.local_mac) /
964 IP(dst="1.1.1.1", src="20.0.0.1") /
965 UDP(sport=1234, dport=1234 + ii) /
966 Raw('\xa5' * 100)))
967 src_pkts.append((Ether(src=self.pg0.remote_mac,
968 dst=self.pg0.local_mac) /
969 IP(dst="1.1.1.1", src="20.0.0.%d" % ii) /
970 UDP(sport=1234, dport=1234) /
971 Raw('\xa5' * 100)))
972
973 route_10_0_0_2 = VppIpRoute(self, "10.0.0.2", 32,
974 [VppRoutePath(self.pg3.remote_ip4,
975 self.pg3.sw_if_index),
976 VppRoutePath(self.pg4.remote_ip4,
977 self.pg4.sw_if_index)])
978 route_10_0_0_2.add_vpp_config()
979
980 route_1_1_1_1 = VppIpRoute(self, "1.1.1.1", 32,
981 [VppRoutePath("10.0.0.2", 0xffffffff),
982 VppRoutePath("10.0.0.1", 0xffffffff)])
983 route_1_1_1_1.add_vpp_config()
984
985 #
986 # inject the packet on pg0 - expect load-balancing across all 4 paths
987 #
988 self.vapi.cli("clear trace")
989 self.send_and_expect_load_balancing(self.pg0, port_pkts,
990 [self.pg1, self.pg2,
991 self.pg3, self.pg4])
992 self.send_and_expect_load_balancing(self.pg0, src_pkts,
993 [self.pg1, self.pg2,
994 self.pg3, self.pg4])
995
Neale Ranns42e6b092017-07-31 02:56:03 -0700996 #
997 # Recursive prefixes
998 # - testing that 2 stages of load-balancing, no choices
999 #
1000 port_pkts = []
1001
1002 for ii in range(257):
1003 port_pkts.append((Ether(src=self.pg0.remote_mac,
1004 dst=self.pg0.local_mac) /
1005 IP(dst="1.1.1.2", src="20.0.0.2") /
1006 UDP(sport=1234, dport=1234 + ii) /
1007 Raw('\xa5' * 100)))
1008
1009 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
1010 [VppRoutePath(self.pg3.remote_ip4,
1011 self.pg3.sw_if_index)])
1012 route_10_0_0_3.add_vpp_config()
1013
1014 route_1_1_1_2 = VppIpRoute(self, "1.1.1.2", 32,
1015 [VppRoutePath("10.0.0.3", 0xffffffff)])
1016 route_1_1_1_2.add_vpp_config()
1017
1018 #
1019 # inject the packet on pg0 - expect load-balancing across all 4 paths
1020 #
1021 self.vapi.cli("clear trace")
1022 self.send_and_expect_one_itf(self.pg0, port_pkts, self.pg3)
1023
Neale Ranns30d0fd42017-05-30 07:30:04 -07001024
1025class TestIPVlan0(VppTestCase):
1026 """ IPv4 VLAN-0 """
1027
1028 def setUp(self):
1029 super(TestIPVlan0, self).setUp()
1030
1031 self.create_pg_interfaces(range(2))
Neale Ranns15002542017-09-10 04:39:11 -07001032 mpls_tbl = VppMplsTable(self, 0)
1033 mpls_tbl.add_vpp_config()
Neale Ranns30d0fd42017-05-30 07:30:04 -07001034
1035 for i in self.pg_interfaces:
1036 i.admin_up()
1037 i.config_ip4()
1038 i.resolve_arp()
1039 i.enable_mpls()
1040
1041 def tearDown(self):
Neale Ranns30d0fd42017-05-30 07:30:04 -07001042 for i in self.pg_interfaces:
1043 i.disable_mpls()
1044 i.unconfig_ip4()
1045 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07001046 super(TestIPVlan0, self).tearDown()
Neale Ranns30d0fd42017-05-30 07:30:04 -07001047
Neale Ranns30d0fd42017-05-30 07:30:04 -07001048 def test_ip_vlan_0(self):
1049 """ IP VLAN-0 """
1050
1051 pkts = (Ether(src=self.pg0.remote_mac,
1052 dst=self.pg0.local_mac) /
1053 Dot1Q(vlan=0) /
1054 IP(dst=self.pg1.remote_ip4,
1055 src=self.pg0.remote_ip4) /
1056 UDP(sport=1234, dport=1234) /
1057 Raw('\xa5' * 100)) * 65
1058
1059 #
1060 # Expect that packets sent on VLAN-0 are forwarded on the
1061 # main interface.
1062 #
1063 self.send_and_expect(self.pg0, pkts, self.pg1)
1064
1065
Neale Rannsd91c1db2017-07-31 02:30:50 -07001066class TestIPPunt(VppTestCase):
1067 """ IPv4 Punt Police/Redirect """
1068
1069 def setUp(self):
1070 super(TestIPPunt, self).setUp()
1071
1072 self.create_pg_interfaces(range(2))
1073
1074 for i in self.pg_interfaces:
1075 i.admin_up()
1076 i.config_ip4()
1077 i.resolve_arp()
1078
1079 def tearDown(self):
1080 super(TestIPPunt, self).tearDown()
1081 for i in self.pg_interfaces:
1082 i.unconfig_ip4()
1083 i.admin_down()
1084
Neale Rannsd91c1db2017-07-31 02:30:50 -07001085 def test_ip_punt(self):
1086 """ IP punt police and redirect """
1087
1088 p = (Ether(src=self.pg0.remote_mac,
1089 dst=self.pg0.local_mac) /
1090 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
1091 TCP(sport=1234, dport=1234) /
1092 Raw('\xa5' * 100))
1093
1094 pkts = p * 1025
1095
1096 #
1097 # Configure a punt redirect via pg1.
1098 #
1099 nh_addr = socket.inet_pton(socket.AF_INET,
1100 self.pg1.remote_ip4)
1101 self.vapi.ip_punt_redirect(self.pg0.sw_if_index,
1102 self.pg1.sw_if_index,
1103 nh_addr)
1104
1105 self.send_and_expect(self.pg0, pkts, self.pg1)
1106
1107 #
1108 # add a policer
1109 #
1110 policer = self.vapi.policer_add_del("ip4-punt", 400, 0, 10, 0,
1111 rate_type=1)
1112 self.vapi.ip_punt_police(policer.policer_index)
1113
1114 self.vapi.cli("clear trace")
1115 self.pg0.add_stream(pkts)
1116 self.pg_enable_capture(self.pg_interfaces)
1117 self.pg_start()
1118
1119 #
1120 # the number of packet recieved should be greater than 0,
1121 # but not equal to the number sent, since some were policed
1122 #
1123 rx = self.pg1._get_capture(1)
1124 self.assertTrue(len(rx) > 0)
1125 self.assertTrue(len(rx) < len(pkts))
1126
1127 #
1128 # remove the poilcer. back to full rx
1129 #
1130 self.vapi.ip_punt_police(policer.policer_index, is_add=0)
1131 self.vapi.policer_add_del("ip4-punt", 400, 0, 10, 0,
1132 rate_type=1, is_add=0)
1133 self.send_and_expect(self.pg0, pkts, self.pg1)
1134
1135 #
1136 # remove the redirect. expect full drop.
1137 #
1138 self.vapi.ip_punt_redirect(self.pg0.sw_if_index,
1139 self.pg1.sw_if_index,
1140 nh_addr,
1141 is_add=0)
1142 self.send_and_assert_no_replies(self.pg0, pkts,
1143 "IP no punt config")
1144
1145 #
1146 # Add a redirect that is not input port selective
1147 #
1148 self.vapi.ip_punt_redirect(0xffffffff,
1149 self.pg1.sw_if_index,
1150 nh_addr)
1151 self.send_and_expect(self.pg0, pkts, self.pg1)
1152
1153 self.vapi.ip_punt_redirect(0xffffffff,
1154 self.pg1.sw_if_index,
1155 nh_addr,
1156 is_add=0)
1157
1158
Neale Ranns054c03a2017-10-13 05:15:07 -07001159class TestIPDeag(VppTestCase):
1160 """ IPv4 Deaggregate Routes """
1161
1162 def setUp(self):
1163 super(TestIPDeag, self).setUp()
1164
1165 self.create_pg_interfaces(range(3))
1166
1167 for i in self.pg_interfaces:
1168 i.admin_up()
1169 i.config_ip4()
1170 i.resolve_arp()
1171
1172 def tearDown(self):
1173 super(TestIPDeag, self).tearDown()
1174 for i in self.pg_interfaces:
1175 i.unconfig_ip4()
1176 i.admin_down()
1177
Neale Ranns054c03a2017-10-13 05:15:07 -07001178 def test_ip_deag(self):
1179 """ IP Deag Routes """
1180
1181 #
1182 # Create a table to be used for:
1183 # 1 - another destination address lookup
1184 # 2 - a source address lookup
1185 #
1186 table_dst = VppIpTable(self, 1)
1187 table_src = VppIpTable(self, 2)
1188 table_dst.add_vpp_config()
1189 table_src.add_vpp_config()
1190
1191 #
1192 # Add a route in the default table to point to a deag/
1193 # second lookup in each of these tables
1194 #
1195 route_to_dst = VppIpRoute(self, "1.1.1.1", 32,
1196 [VppRoutePath("0.0.0.0",
1197 0xffffffff,
1198 nh_table_id=1)])
1199 route_to_src = VppIpRoute(self, "1.1.1.2", 32,
1200 [VppRoutePath("0.0.0.0",
1201 0xffffffff,
1202 nh_table_id=2,
1203 is_source_lookup=1)])
1204 route_to_dst.add_vpp_config()
1205 route_to_src.add_vpp_config()
1206
1207 #
1208 # packets to these destination are dropped, since they'll
1209 # hit the respective default routes in the second table
1210 #
1211 p_dst = (Ether(src=self.pg0.remote_mac,
1212 dst=self.pg0.local_mac) /
1213 IP(src="5.5.5.5", dst="1.1.1.1") /
1214 TCP(sport=1234, dport=1234) /
1215 Raw('\xa5' * 100))
1216 p_src = (Ether(src=self.pg0.remote_mac,
1217 dst=self.pg0.local_mac) /
1218 IP(src="2.2.2.2", dst="1.1.1.2") /
1219 TCP(sport=1234, dport=1234) /
1220 Raw('\xa5' * 100))
1221 pkts_dst = p_dst * 257
1222 pkts_src = p_src * 257
1223
1224 self.send_and_assert_no_replies(self.pg0, pkts_dst,
1225 "IP in dst table")
1226 self.send_and_assert_no_replies(self.pg0, pkts_src,
1227 "IP in src table")
1228
1229 #
1230 # add a route in the dst table to forward via pg1
1231 #
1232 route_in_dst = VppIpRoute(self, "1.1.1.1", 32,
1233 [VppRoutePath(self.pg1.remote_ip4,
1234 self.pg1.sw_if_index)],
1235 table_id=1)
1236 route_in_dst.add_vpp_config()
1237 self.send_and_expect(self.pg0, pkts_dst, self.pg1)
1238
1239 #
1240 # add a route in the src table to forward via pg2
1241 #
1242 route_in_src = VppIpRoute(self, "2.2.2.2", 32,
1243 [VppRoutePath(self.pg2.remote_ip4,
1244 self.pg2.sw_if_index)],
1245 table_id=2)
1246 route_in_src.add_vpp_config()
1247 self.send_and_expect(self.pg0, pkts_src, self.pg2)
1248
Neale Rannsce9e0b42018-08-01 12:53:17 -07001249 #
1250 # loop in the lookup DP
1251 #
1252 route_loop = VppIpRoute(self, "2.2.2.3", 32,
1253 [VppRoutePath("0.0.0.0",
1254 0xffffffff,
1255 nh_table_id=0)])
1256 route_loop.add_vpp_config()
1257
1258 p_l = (Ether(src=self.pg0.remote_mac,
1259 dst=self.pg0.local_mac) /
1260 IP(src="2.2.2.4", dst="2.2.2.3") /
1261 TCP(sport=1234, dport=1234) /
1262 Raw('\xa5' * 100))
1263
1264 self.send_and_assert_no_replies(self.pg0, p_l * 257,
1265 "IP lookup loop")
1266
Neale Ranns054c03a2017-10-13 05:15:07 -07001267
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001268class TestIPInput(VppTestCase):
1269 """ IPv4 Input Exceptions """
1270
1271 def setUp(self):
1272 super(TestIPInput, self).setUp()
1273
1274 self.create_pg_interfaces(range(2))
1275
1276 for i in self.pg_interfaces:
1277 i.admin_up()
1278 i.config_ip4()
1279 i.resolve_arp()
1280
1281 def tearDown(self):
1282 super(TestIPInput, self).tearDown()
1283 for i in self.pg_interfaces:
1284 i.unconfig_ip4()
1285 i.admin_down()
1286
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001287 def test_ip_input(self):
1288 """ IP Input Exceptions """
1289
1290 # i can't find a way in scapy to construct an IP packet
1291 # with a length less than the IP header length
1292
1293 #
1294 # Packet too short - this is forwarded
1295 #
1296 p_short = (Ether(src=self.pg0.remote_mac,
1297 dst=self.pg0.local_mac) /
1298 IP(src=self.pg0.remote_ip4,
1299 dst=self.pg1.remote_ip4,
1300 len=40) /
1301 UDP(sport=1234, dport=1234) /
1302 Raw('\xa5' * 100))
1303
1304 rx = self.send_and_expect(self.pg0, p_short * 65, self.pg1)
1305
1306 #
1307 # Packet too long - this is dropped
1308 #
1309 p_long = (Ether(src=self.pg0.remote_mac,
1310 dst=self.pg0.local_mac) /
1311 IP(src=self.pg0.remote_ip4,
1312 dst=self.pg1.remote_ip4,
1313 len=400) /
1314 UDP(sport=1234, dport=1234) /
1315 Raw('\xa5' * 100))
1316
1317 rx = self.send_and_assert_no_replies(self.pg0, p_long * 65,
1318 "too long")
1319
1320 #
1321 # bad chksum - this is dropped
1322 #
1323 p_chksum = (Ether(src=self.pg0.remote_mac,
1324 dst=self.pg0.local_mac) /
1325 IP(src=self.pg0.remote_ip4,
1326 dst=self.pg1.remote_ip4,
1327 chksum=400) /
1328 UDP(sport=1234, dport=1234) /
1329 Raw('\xa5' * 100))
1330
1331 rx = self.send_and_assert_no_replies(self.pg0, p_chksum * 65,
1332 "bad checksum")
1333
1334 #
1335 # bad version - this is dropped
1336 #
1337 p_ver = (Ether(src=self.pg0.remote_mac,
1338 dst=self.pg0.local_mac) /
1339 IP(src=self.pg0.remote_ip4,
1340 dst=self.pg1.remote_ip4,
1341 version=3) /
1342 UDP(sport=1234, dport=1234) /
1343 Raw('\xa5' * 100))
1344
1345 rx = self.send_and_assert_no_replies(self.pg0, p_ver * 65,
1346 "funky version")
1347
1348 #
1349 # fragment offset 1 - this is dropped
1350 #
1351 p_frag = (Ether(src=self.pg0.remote_mac,
1352 dst=self.pg0.local_mac) /
1353 IP(src=self.pg0.remote_ip4,
1354 dst=self.pg1.remote_ip4,
1355 frag=1) /
1356 UDP(sport=1234, dport=1234) /
1357 Raw('\xa5' * 100))
1358
1359 rx = self.send_and_assert_no_replies(self.pg0, p_frag * 65,
1360 "frag offset")
1361
1362 #
1363 # TTL expired packet
1364 #
1365 p_ttl = (Ether(src=self.pg0.remote_mac,
1366 dst=self.pg0.local_mac) /
1367 IP(src=self.pg0.remote_ip4,
1368 dst=self.pg1.remote_ip4,
1369 ttl=1) /
1370 UDP(sport=1234, dport=1234) /
1371 Raw('\xa5' * 100))
1372
1373 rx = self.send_and_expect(self.pg0, p_ttl * 65, self.pg0)
1374
1375 rx = rx[0]
1376 icmp = rx[ICMP]
1377
1378 self.assertEqual(icmptypes[icmp.type], "time-exceeded")
1379 self.assertEqual(icmpcodes[icmp.type][icmp.code],
1380 "ttl-zero-during-transit")
1381 self.assertEqual(icmp.src, self.pg0.remote_ip4)
1382 self.assertEqual(icmp.dst, self.pg1.remote_ip4)
1383
Neale Rannsffd78d12018-02-09 06:05:16 -08001384 #
1385 # MTU exceeded
1386 #
1387 p_mtu = (Ether(src=self.pg0.remote_mac,
1388 dst=self.pg0.local_mac) /
1389 IP(src=self.pg0.remote_ip4,
1390 dst=self.pg1.remote_ip4,
Ole Troan8a9c8f12018-05-18 11:01:31 +02001391 ttl=10, flags='DF') /
Neale Rannsffd78d12018-02-09 06:05:16 -08001392 UDP(sport=1234, dport=1234) /
1393 Raw('\xa5' * 2000))
1394
Ole Troand7231612018-06-07 10:17:57 +02001395 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1500, 0, 0, 0])
Neale Rannsffd78d12018-02-09 06:05:16 -08001396
1397 rx = self.send_and_expect(self.pg0, p_mtu * 65, self.pg0)
1398 rx = rx[0]
1399 icmp = rx[ICMP]
1400
1401 self.assertEqual(icmptypes[icmp.type], "dest-unreach")
1402 self.assertEqual(icmpcodes[icmp.type][icmp.code],
1403 "fragmentation-needed")
1404 self.assertEqual(icmp.src, self.pg0.remote_ip4)
1405 self.assertEqual(icmp.dst, self.pg1.remote_ip4)
1406
Ole Troand7231612018-06-07 10:17:57 +02001407 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [2500, 0, 0, 0])
Neale Rannsffd78d12018-02-09 06:05:16 -08001408 rx = self.send_and_expect(self.pg0, p_mtu * 65, self.pg1)
1409
Ole Troand7231612018-06-07 10:17:57 +02001410 # Reset MTU for subsequent tests
1411 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [9000, 0, 0, 0])
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001412
Neale Ranns1855b8e2018-07-11 10:31:26 -07001413
1414class TestIPDirectedBroadcast(VppTestCase):
1415 """ IPv4 Directed Broadcast """
1416
1417 def setUp(self):
1418 super(TestIPDirectedBroadcast, self).setUp()
1419
1420 self.create_pg_interfaces(range(2))
1421
1422 for i in self.pg_interfaces:
1423 i.admin_up()
1424
1425 def tearDown(self):
1426 super(TestIPDirectedBroadcast, self).tearDown()
1427 for i in self.pg_interfaces:
1428 i.admin_down()
1429
1430 def test_ip_input(self):
1431 """ IP Directed Broadcast """
1432
1433 #
1434 # set the directed broadcast on pg0 first, then config IP4 addresses
1435 # for pg1 directed broadcast is always disabled
1436 self.vapi.sw_interface_set_ip_directed_broadcast(
1437 self.pg0.sw_if_index, 1)
1438
1439 p0 = (Ether(src=self.pg1.remote_mac,
1440 dst=self.pg1.local_mac) /
1441 IP(src="1.1.1.1",
1442 dst=self.pg0._local_ip4_bcast) /
1443 UDP(sport=1234, dport=1234) /
1444 Raw('\xa5' * 2000))
1445 p1 = (Ether(src=self.pg0.remote_mac,
1446 dst=self.pg0.local_mac) /
1447 IP(src="1.1.1.1",
1448 dst=self.pg1._local_ip4_bcast) /
1449 UDP(sport=1234, dport=1234) /
1450 Raw('\xa5' * 2000))
1451
1452 self.pg0.config_ip4()
1453 self.pg0.resolve_arp()
1454 self.pg1.config_ip4()
1455 self.pg1.resolve_arp()
1456
1457 #
1458 # test packet is L2 broadcast
1459 #
1460 rx = self.send_and_expect(self.pg1, p0 * 65, self.pg0)
1461 self.assertTrue(rx[0][Ether].dst, "ff:ff:ff:ff:ff:ff")
1462
1463 self.send_and_assert_no_replies(self.pg0, p1 * 65,
1464 "directed broadcast disabled")
1465
1466 #
1467 # toggle directed broadcast on pg0
1468 #
1469 self.vapi.sw_interface_set_ip_directed_broadcast(
1470 self.pg0.sw_if_index, 0)
1471 self.send_and_assert_no_replies(self.pg1, p0 * 65,
1472 "directed broadcast disabled")
1473
1474 self.vapi.sw_interface_set_ip_directed_broadcast(
1475 self.pg0.sw_if_index, 1)
1476 rx = self.send_and_expect(self.pg1, p0 * 65, self.pg0)
1477
1478 self.pg0.unconfig_ip4()
1479 self.pg1.unconfig_ip4()
1480
1481
Damjan Marionf56b77a2016-10-03 19:44:57 +02001482if __name__ == '__main__':
Klement Sekeraf62ae122016-10-11 11:47:09 +02001483 unittest.main(testRunner=VppTestRunner)