blob: 8a9841cb4f3f8dfa611e864199cba1e28d02d7e1 [file] [log] [blame]
Damjan Marionf56b77a2016-10-03 19:44:57 +02001#!/usr/bin/env python
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -08002import binascii
Matej Klotton16a14cd2016-12-07 15:09:13 +01003import random
Klement Sekeraf62ae122016-10-11 11:47:09 +02004import socket
Matej Klotton16a14cd2016-12-07 15:09:13 +01005import unittest
Klement Sekeraf62ae122016-10-11 11:47:09 +02006
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07007import scapy.compat
Paul Vinciguerraa6fe4632018-11-25 11:21:50 -08008from scapy.contrib.mpls import MPLS
9from scapy.layers.inet import IP, UDP, TCP, ICMP, icmptypes, icmpcodes
10from scapy.layers.l2 import Ether, Dot1Q, ARP
11from scapy.packet import Raw
12from six import moves
13
Damjan Marionf56b77a2016-10-03 19:44:57 +020014from framework import VppTestCase, VppTestRunner
Paul Vinciguerraa6fe4632018-11-25 11:21:50 -080015from util import ppp
Neale Ranns180279b2017-03-16 15:49:09 -040016from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpMRoute, \
Neale Ranns15002542017-09-10 04:39:11 -070017 VppMRoutePath, MRouteItfFlags, MRouteEntryFlags, VppMplsIpBind, \
Ole Troan0bcad322018-12-11 13:04:01 +010018 VppMplsTable, VppIpTable
Paul Vinciguerraa6fe4632018-11-25 11:21:50 -080019from vpp_sub_interface import VppSubInterface, VppDot1QSubint, VppDot1ADSubint
Damjan Marionf56b77a2016-10-03 19:44:57 +020020
21
Klement Sekeraf62ae122016-10-11 11:47:09 +020022class TestIPv4(VppTestCase):
Damjan Marionf56b77a2016-10-03 19:44:57 +020023 """ IPv4 Test Case """
24
Klement Sekeraf62ae122016-10-11 11:47:09 +020025 def setUp(self):
Matej Klotton86d87c42016-11-11 11:38:55 +010026 """
27 Perform test setup before test case.
28
29 **Config:**
30 - create 3 pg interfaces
31 - untagged pg0 interface
32 - Dot1Q subinterface on pg1
33 - Dot1AD subinterface on pg2
34 - setup interfaces:
35 - put it into UP state
36 - set IPv4 addresses
37 - resolve neighbor address using ARP
38 - configure 200 fib entries
39
40 :ivar list interfaces: pg interfaces and subinterfaces.
41 :ivar dict flows: IPv4 packet flows in test.
Matej Klotton86d87c42016-11-11 11:38:55 +010042 """
Klement Sekeraf62ae122016-10-11 11:47:09 +020043 super(TestIPv4, self).setUp()
Damjan Marionf56b77a2016-10-03 19:44:57 +020044
Klement Sekeraf62ae122016-10-11 11:47:09 +020045 # create 3 pg interfaces
46 self.create_pg_interfaces(range(3))
Damjan Marionf56b77a2016-10-03 19:44:57 +020047
Klement Sekeraf62ae122016-10-11 11:47:09 +020048 # create 2 subinterfaces for pg1 and pg2
49 self.sub_interfaces = [
50 VppDot1QSubint(self, self.pg1, 100),
51 VppDot1ADSubint(self, self.pg2, 200, 300, 400)]
Damjan Marionf56b77a2016-10-03 19:44:57 +020052
Klement Sekeraf62ae122016-10-11 11:47:09 +020053 # packet flows mapping pg0 -> pg1.sub, pg2.sub, etc.
54 self.flows = dict()
55 self.flows[self.pg0] = [self.pg1.sub_if, self.pg2.sub_if]
56 self.flows[self.pg1.sub_if] = [self.pg0, self.pg2.sub_if]
57 self.flows[self.pg2.sub_if] = [self.pg0, self.pg1.sub_if]
Damjan Marionf56b77a2016-10-03 19:44:57 +020058
Klement Sekeraf62ae122016-10-11 11:47:09 +020059 # packet sizes
Jan Geletye6c78ee2018-06-26 12:24:03 +020060 self.pg_if_packet_sizes = [64, 1500, 9020]
Damjan Marionf56b77a2016-10-03 19:44:57 +020061
Klement Sekeraf62ae122016-10-11 11:47:09 +020062 self.interfaces = list(self.pg_interfaces)
63 self.interfaces.extend(self.sub_interfaces)
Damjan Marionf56b77a2016-10-03 19:44:57 +020064
Klement Sekeraf62ae122016-10-11 11:47:09 +020065 # setup all interfaces
66 for i in self.interfaces:
67 i.admin_up()
68 i.config_ip4()
69 i.resolve_arp()
70
Matej Klotton86d87c42016-11-11 11:38:55 +010071 # config 2M FIB entries
Klement Sekeraf62ae122016-10-11 11:47:09 +020072 self.config_fib_entries(200)
Damjan Marionf56b77a2016-10-03 19:44:57 +020073
74 def tearDown(self):
Matej Klotton86d87c42016-11-11 11:38:55 +010075 """Run standard test teardown and log ``show ip arp``."""
Klement Sekeraf62ae122016-10-11 11:47:09 +020076 super(TestIPv4, self).tearDown()
77 if not self.vpp_dead:
Matej Klotton86d87c42016-11-11 11:38:55 +010078 self.logger.info(self.vapi.cli("show ip arp"))
Klement Sekeraf62ae122016-10-11 11:47:09 +020079 # info(self.vapi.cli("show ip fib")) # many entries
Damjan Marionf56b77a2016-10-03 19:44:57 +020080
Klement Sekeraf62ae122016-10-11 11:47:09 +020081 def config_fib_entries(self, count):
Matej Klotton86d87c42016-11-11 11:38:55 +010082 """For each interface add to the FIB table *count* routes to
83 "10.0.0.1/32" destination with interface's local address as next-hop
84 address.
85
86 :param int count: Number of FIB entries.
87
88 - *TODO:* check if the next-hop address shouldn't be remote address
89 instead of local address.
90 """
Klement Sekeraf62ae122016-10-11 11:47:09 +020091 n_int = len(self.interfaces)
92 percent = 0
93 counter = 0.0
94 dest_addr = socket.inet_pton(socket.AF_INET, "10.0.0.1")
95 dest_addr_len = 32
96 for i in self.interfaces:
97 next_hop_address = i.local_ip4n
98 for j in range(count / n_int):
Ole Troana5b2eec2019-03-11 19:23:25 +010099 self.vapi.ip_add_del_route(dst_address=dest_addr,
100 dst_address_length=dest_addr_len,
101 next_hop_address=next_hop_address)
Matej Klotton86d87c42016-11-11 11:38:55 +0100102 counter += 1
Klement Sekeraf62ae122016-10-11 11:47:09 +0200103 if counter / count * 100 > percent:
Matej Klotton86d87c42016-11-11 11:38:55 +0100104 self.logger.info("Configure %d FIB entries .. %d%% done" %
105 (count, percent))
106 percent += 1
Damjan Marionf56b77a2016-10-03 19:44:57 +0200107
Jan Geletye6c78ee2018-06-26 12:24:03 +0200108 def modify_packet(self, src_if, packet_size, pkt):
109 """Add load, set destination IP and extend packet to required packet
110 size for defined interface.
111
112 :param VppInterface src_if: Interface to create packet for.
113 :param int packet_size: Required packet size.
114 :param Scapy pkt: Packet to be modified.
115 """
116 dst_if_idx = packet_size / 10 % 2
117 dst_if = self.flows[src_if][dst_if_idx]
118 info = self.create_packet_info(src_if, dst_if)
119 payload = self.info_to_payload(info)
120 p = pkt/Raw(payload)
121 p[IP].dst = dst_if.remote_ip4
122 info.data = p.copy()
123 if isinstance(src_if, VppSubInterface):
124 p = src_if.add_dot1_layer(p)
125 self.extend_packet(p, packet_size)
126
127 return p
128
129 def create_stream(self, src_if):
Matej Klotton86d87c42016-11-11 11:38:55 +0100130 """Create input packet stream for defined interface.
131
132 :param VppInterface src_if: Interface to create packet stream for.
Matej Klotton86d87c42016-11-11 11:38:55 +0100133 """
Jan Geletye6c78ee2018-06-26 12:24:03 +0200134 hdr_ext = 4 if isinstance(src_if, VppSubInterface) else 0
135 pkt_tmpl = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
136 IP(src=src_if.remote_ip4) /
137 UDP(sport=1234, dport=1234))
138
139 pkts = [self.modify_packet(src_if, i, pkt_tmpl)
Paul Vinciguerraa6fe4632018-11-25 11:21:50 -0800140 for i in moves.range(self.pg_if_packet_sizes[0],
141 self.pg_if_packet_sizes[1], 10)]
Jan Geletye6c78ee2018-06-26 12:24:03 +0200142 pkts_b = [self.modify_packet(src_if, i, pkt_tmpl)
Paul Vinciguerraa6fe4632018-11-25 11:21:50 -0800143 for i in moves.range(self.pg_if_packet_sizes[1] + hdr_ext,
144 self.pg_if_packet_sizes[2] + hdr_ext,
145 50)]
Jan Geletye6c78ee2018-06-26 12:24:03 +0200146 pkts.extend(pkts_b)
147
Damjan Marionf56b77a2016-10-03 19:44:57 +0200148 return pkts
149
Klement Sekeraf62ae122016-10-11 11:47:09 +0200150 def verify_capture(self, dst_if, capture):
Matej Klotton86d87c42016-11-11 11:38:55 +0100151 """Verify captured input packet stream for defined interface.
152
153 :param VppInterface dst_if: Interface to verify captured packet stream
Jan Geletye6c78ee2018-06-26 12:24:03 +0200154 for.
Matej Klotton86d87c42016-11-11 11:38:55 +0100155 :param list capture: Captured packet stream.
156 """
157 self.logger.info("Verifying capture on interface %s" % dst_if.name)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200158 last_info = dict()
Damjan Marionf56b77a2016-10-03 19:44:57 +0200159 for i in self.interfaces:
Klement Sekeraf62ae122016-10-11 11:47:09 +0200160 last_info[i.sw_if_index] = None
161 is_sub_if = False
162 dst_sw_if_index = dst_if.sw_if_index
163 if hasattr(dst_if, 'parent'):
164 is_sub_if = True
Damjan Marionf56b77a2016-10-03 19:44:57 +0200165 for packet in capture:
Klement Sekeraf62ae122016-10-11 11:47:09 +0200166 if is_sub_if:
167 # Check VLAN tags and Ethernet header
168 packet = dst_if.remove_dot1_layer(packet)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200169 self.assertTrue(Dot1Q not in packet)
170 try:
171 ip = packet[IP]
172 udp = packet[UDP]
Paul Vinciguerraeaea4212019-03-06 11:58:06 -0800173 payload_info = self.payload_to_info(packet[Raw])
Damjan Marionf56b77a2016-10-03 19:44:57 +0200174 packet_index = payload_info.index
Klement Sekeraf62ae122016-10-11 11:47:09 +0200175 self.assertEqual(payload_info.dst, dst_sw_if_index)
Klement Sekerada505f62017-01-04 12:58:53 +0100176 self.logger.debug(
177 "Got packet on port %s: src=%u (id=%u)" %
178 (dst_if.name, payload_info.src, packet_index))
Klement Sekeraf62ae122016-10-11 11:47:09 +0200179 next_info = self.get_next_packet_info_for_interface2(
180 payload_info.src, dst_sw_if_index,
181 last_info[payload_info.src])
182 last_info[payload_info.src] = next_info
Damjan Marionf56b77a2016-10-03 19:44:57 +0200183 self.assertTrue(next_info is not None)
184 self.assertEqual(packet_index, next_info.index)
185 saved_packet = next_info.data
186 # Check standard fields
187 self.assertEqual(ip.src, saved_packet[IP].src)
188 self.assertEqual(ip.dst, saved_packet[IP].dst)
189 self.assertEqual(udp.sport, saved_packet[UDP].sport)
190 self.assertEqual(udp.dport, saved_packet[UDP].dport)
191 except:
Klement Sekera7bb873a2016-11-18 07:38:42 +0100192 self.logger.error(ppp("Unexpected or invalid packet:", packet))
Damjan Marionf56b77a2016-10-03 19:44:57 +0200193 raise
194 for i in self.interfaces:
Klement Sekeraf62ae122016-10-11 11:47:09 +0200195 remaining_packet = self.get_next_packet_info_for_interface2(
196 i.sw_if_index, dst_sw_if_index, last_info[i.sw_if_index])
Klement Sekera7bb873a2016-11-18 07:38:42 +0100197 self.assertTrue(remaining_packet is None,
198 "Interface %s: Packet expected from interface %s "
199 "didn't arrive" % (dst_if.name, i.name))
Damjan Marionf56b77a2016-10-03 19:44:57 +0200200
201 def test_fib(self):
Matej Klotton86d87c42016-11-11 11:38:55 +0100202 """ IPv4 FIB test
203
204 Test scenario:
205
206 - Create IPv4 stream for pg0 interface
Jan Geletye6c78ee2018-06-26 12:24:03 +0200207 - Create IPv4 tagged streams for pg1's and pg2's sub-interface.
Matej Klotton86d87c42016-11-11 11:38:55 +0100208 - Send and verify received packets on each interface.
209 """
Damjan Marionf56b77a2016-10-03 19:44:57 +0200210
Jan Geletye6c78ee2018-06-26 12:24:03 +0200211 pkts = self.create_stream(self.pg0)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200212 self.pg0.add_stream(pkts)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200213
Klement Sekeraf62ae122016-10-11 11:47:09 +0200214 for i in self.sub_interfaces:
Jan Geletye6c78ee2018-06-26 12:24:03 +0200215 pkts = self.create_stream(i)
Klement Sekeraf62ae122016-10-11 11:47:09 +0200216 i.parent.add_stream(pkts)
217
218 self.pg_enable_capture(self.pg_interfaces)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200219 self.pg_start()
220
Klement Sekeraf62ae122016-10-11 11:47:09 +0200221 pkts = self.pg0.get_capture()
222 self.verify_capture(self.pg0, pkts)
223
224 for i in self.sub_interfaces:
225 pkts = i.parent.get_capture()
226 self.verify_capture(i, pkts)
Damjan Marionf56b77a2016-10-03 19:44:57 +0200227
228
Jan Geletye6c78ee2018-06-26 12:24:03 +0200229class TestICMPEcho(VppTestCase):
230 """ ICMP Echo Test Case """
231
232 def setUp(self):
233 super(TestICMPEcho, self).setUp()
234
235 # create 1 pg interface
236 self.create_pg_interfaces(range(1))
237
238 for i in self.pg_interfaces:
239 i.admin_up()
240 i.config_ip4()
241 i.resolve_arp()
242
243 def tearDown(self):
244 super(TestICMPEcho, self).tearDown()
245 for i in self.pg_interfaces:
246 i.unconfig_ip4()
247 i.admin_down()
248
249 def test_icmp_echo(self):
250 """ VPP replies to ICMP Echo Request
251
252 Test scenario:
253
254 - Receive ICMP Echo Request message on pg0 interface.
255 - Check outgoing ICMP Echo Reply message on pg0 interface.
256 """
257
258 icmp_id = 0xb
259 icmp_seq = 5
260 icmp_load = '\x0a' * 18
261 p_echo_request = (Ether(src=self.pg0.remote_mac,
262 dst=self.pg0.local_mac) /
263 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
264 ICMP(id=icmp_id, seq=icmp_seq) /
265 Raw(load=icmp_load))
266
267 self.pg0.add_stream(p_echo_request)
268 self.pg_enable_capture(self.pg_interfaces)
269 self.pg_start()
270
271 rx = self.pg0.get_capture(1)
272 rx = rx[0]
273 ether = rx[Ether]
274 ipv4 = rx[IP]
275 icmp = rx[ICMP]
276
277 self.assertEqual(ether.src, self.pg0.local_mac)
278 self.assertEqual(ether.dst, self.pg0.remote_mac)
279
280 self.assertEqual(ipv4.src, self.pg0.local_ip4)
281 self.assertEqual(ipv4.dst, self.pg0.remote_ip4)
282
283 self.assertEqual(icmptypes[icmp.type], "echo-reply")
284 self.assertEqual(icmp.id, icmp_id)
285 self.assertEqual(icmp.seq, icmp_seq)
286 self.assertEqual(icmp[Raw].load, icmp_load)
287
288
Matej Klotton16a14cd2016-12-07 15:09:13 +0100289class TestIPv4FibCrud(VppTestCase):
290 """ FIB - add/update/delete - ip4 routes
291
292 Test scenario:
293 - add 1k,
294 - del 100,
295 - add new 1k,
296 - del 1.5k
297
Klement Sekerada505f62017-01-04 12:58:53 +0100298 ..note:: Python API is too slow to add many routes, needs replacement.
Matej Klotton16a14cd2016-12-07 15:09:13 +0100299 """
300
301 def config_fib_many_to_one(self, start_dest_addr, next_hop_addr, count):
302 """
303
304 :param start_dest_addr:
305 :param next_hop_addr:
306 :param count:
307 :return list: added ips with 32 prefix
308 """
309 added_ips = []
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800310 dest_addr = int(binascii.hexlify(socket.inet_pton(socket.AF_INET,
311 start_dest_addr)), 16)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100312 dest_addr_len = 32
313 n_next_hop_addr = socket.inet_pton(socket.AF_INET, next_hop_addr)
314 for _ in range(count):
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700315 n_dest_addr = binascii.unhexlify('{:08x}'.format(dest_addr))
Ole Troana5b2eec2019-03-11 19:23:25 +0100316 self.vapi.ip_add_del_route(dst_address=n_dest_addr,
317 dst_address_length=dest_addr_len,
318 next_hop_address=n_next_hop_addr)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100319 added_ips.append(socket.inet_ntoa(n_dest_addr))
320 dest_addr += 1
321 return added_ips
322
323 def unconfig_fib_many_to_one(self, start_dest_addr, next_hop_addr, count):
324
325 removed_ips = []
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800326 dest_addr = int(binascii.hexlify(socket.inet_pton(socket.AF_INET,
327 start_dest_addr)), 16)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100328 dest_addr_len = 32
329 n_next_hop_addr = socket.inet_pton(socket.AF_INET, next_hop_addr)
330 for _ in range(count):
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700331 n_dest_addr = binascii.unhexlify('{:08x}'.format(dest_addr))
Ole Troana5b2eec2019-03-11 19:23:25 +0100332 self.vapi.ip_add_del_route(dst_address=n_dest_addr,
333 dst_address_length=dest_addr_len,
334 next_hop_address=n_next_hop_addr,
335 is_add=0)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100336 removed_ips.append(socket.inet_ntoa(n_dest_addr))
337 dest_addr += 1
338 return removed_ips
339
340 def create_stream(self, src_if, dst_if, dst_ips, count):
341 pkts = []
342
343 for _ in range(count):
344 dst_addr = random.choice(dst_ips)
Klement Sekeradab231a2016-12-21 08:50:14 +0100345 info = self.create_packet_info(src_if, dst_if)
Matej Klotton16a14cd2016-12-07 15:09:13 +0100346 payload = self.info_to_payload(info)
347 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
348 IP(src=src_if.remote_ip4, dst=dst_addr) /
349 UDP(sport=1234, dport=1234) /
350 Raw(payload))
351 info.data = p.copy()
Matej Klotton16a14cd2016-12-07 15:09:13 +0100352 self.extend_packet(p, random.choice(self.pg_if_packet_sizes))
353 pkts.append(p)
354
355 return pkts
356
357 def _find_ip_match(self, find_in, pkt):
358 for p in find_in:
Paul Vinciguerraeaea4212019-03-06 11:58:06 -0800359 if self.payload_to_info(p[Raw]) == \
360 self.payload_to_info(pkt[Raw]):
Matej Klotton16a14cd2016-12-07 15:09:13 +0100361 if p[IP].src != pkt[IP].src:
362 break
363 if p[IP].dst != pkt[IP].dst:
364 break
365 if p[UDP].sport != pkt[UDP].sport:
366 break
367 if p[UDP].dport != pkt[UDP].dport:
368 break
369 return p
370 return None
371
372 @staticmethod
373 def _match_route_detail(route_detail, ip, address_length=32, table_id=0):
374 if route_detail.address == socket.inet_pton(socket.AF_INET, ip):
375 if route_detail.table_id != table_id:
376 return False
377 elif route_detail.address_length != address_length:
378 return False
379 else:
380 return True
381 else:
382 return False
383
384 def verify_capture(self, dst_interface, received_pkts, expected_pkts):
385 self.assertEqual(len(received_pkts), len(expected_pkts))
386 to_verify = list(expected_pkts)
387 for p in received_pkts:
388 self.assertEqual(p.src, dst_interface.local_mac)
389 self.assertEqual(p.dst, dst_interface.remote_mac)
390 x = self._find_ip_match(to_verify, p)
391 to_verify.remove(x)
392 self.assertListEqual(to_verify, [])
393
394 def verify_route_dump(self, fib_dump, ips):
395
396 def _ip_in_route_dump(ip, fib_dump):
397 return next((route for route in fib_dump
398 if self._match_route_detail(route, ip)),
399 False)
400
401 for ip in ips:
402 self.assertTrue(_ip_in_route_dump(ip, fib_dump),
Paul Vinciguerraea2450f2019-03-06 08:23:58 -0800403 'IP {!s} is not in fib dump.'.format(ip))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100404
405 def verify_not_in_route_dump(self, fib_dump, ips):
406
407 def _ip_in_route_dump(ip, fib_dump):
408 return next((route for route in fib_dump
409 if self._match_route_detail(route, ip)),
410 False)
411
412 for ip in ips:
413 self.assertFalse(_ip_in_route_dump(ip, fib_dump),
Paul Vinciguerraea2450f2019-03-06 08:23:58 -0800414 'IP {!s} is in fib dump.'.format(ip))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100415
416 @classmethod
417 def setUpClass(cls):
418 """
419 #. Create and initialize 3 pg interfaces.
420 #. initialize class attributes configured_routes and deleted_routes
421 to store information between tests.
422 """
423 super(TestIPv4FibCrud, cls).setUpClass()
424
425 try:
426 # create 3 pg interfaces
427 cls.create_pg_interfaces(range(3))
428
429 cls.interfaces = list(cls.pg_interfaces)
430
431 # setup all interfaces
432 for i in cls.interfaces:
433 i.admin_up()
434 i.config_ip4()
435 i.resolve_arp()
436
437 cls.configured_routes = []
438 cls.deleted_routes = []
439 cls.pg_if_packet_sizes = [64, 512, 1518, 9018]
440
441 except Exception:
442 super(TestIPv4FibCrud, cls).tearDownClass()
443 raise
444
445 def setUp(self):
446 super(TestIPv4FibCrud, self).setUp()
Klement Sekeradab231a2016-12-21 08:50:14 +0100447 self.reset_packet_infos()
Matej Klotton16a14cd2016-12-07 15:09:13 +0100448
Paul Vinciguerra4eed7472018-12-16 14:52:36 -0800449 self.configured_routes = []
450 self.deleted_routes = []
451
Matej Klotton16a14cd2016-12-07 15:09:13 +0100452 def test_1_add_routes(self):
453 """ Add 1k routes
454
455 - add 100 routes check with traffic script.
456 """
457 # config 1M FIB entries
458 self.configured_routes.extend(self.config_fib_many_to_one(
459 "10.0.0.0", self.pg0.remote_ip4, 100))
460
461 fib_dump = self.vapi.ip_fib_dump()
462 self.verify_route_dump(fib_dump, self.configured_routes)
463
464 self.stream_1 = self.create_stream(
465 self.pg1, self.pg0, self.configured_routes, 100)
466 self.stream_2 = self.create_stream(
467 self.pg2, self.pg0, self.configured_routes, 100)
468 self.pg1.add_stream(self.stream_1)
469 self.pg2.add_stream(self.stream_2)
470
471 self.pg_enable_capture(self.pg_interfaces)
472 self.pg_start()
473
Klement Sekeradab231a2016-12-21 08:50:14 +0100474 pkts = self.pg0.get_capture(len(self.stream_1) + len(self.stream_2))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100475 self.verify_capture(self.pg0, pkts, self.stream_1 + self.stream_2)
476
Matej Klotton16a14cd2016-12-07 15:09:13 +0100477 def test_2_del_routes(self):
478 """ Delete 100 routes
479
480 - delete 10 routes check with traffic script.
481 """
Paul Vinciguerra4eed7472018-12-16 14:52:36 -0800482 # config 1M FIB entries
483 self.configured_routes.extend(self.config_fib_many_to_one(
484 "10.0.0.0", self.pg0.remote_ip4, 100))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100485 self.deleted_routes.extend(self.unconfig_fib_many_to_one(
486 "10.0.0.10", self.pg0.remote_ip4, 10))
487 for x in self.deleted_routes:
488 self.configured_routes.remove(x)
489
490 fib_dump = self.vapi.ip_fib_dump()
491 self.verify_route_dump(fib_dump, self.configured_routes)
492
493 self.stream_1 = self.create_stream(
494 self.pg1, self.pg0, self.configured_routes, 100)
495 self.stream_2 = self.create_stream(
496 self.pg2, self.pg0, self.configured_routes, 100)
497 self.stream_3 = self.create_stream(
498 self.pg1, self.pg0, self.deleted_routes, 100)
499 self.stream_4 = self.create_stream(
500 self.pg2, self.pg0, self.deleted_routes, 100)
501 self.pg1.add_stream(self.stream_1 + self.stream_3)
502 self.pg2.add_stream(self.stream_2 + self.stream_4)
503 self.pg_enable_capture(self.pg_interfaces)
504 self.pg_start()
505
Klement Sekeradab231a2016-12-21 08:50:14 +0100506 pkts = self.pg0.get_capture(len(self.stream_1) + len(self.stream_2))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100507 self.verify_capture(self.pg0, pkts, self.stream_1 + self.stream_2)
508
509 def test_3_add_new_routes(self):
510 """ Add 1k routes
511
512 - re-add 5 routes check with traffic script.
513 - add 100 routes check with traffic script.
514 """
Paul Vinciguerra4eed7472018-12-16 14:52:36 -0800515 # config 1M FIB entries
516 self.configured_routes.extend(self.config_fib_many_to_one(
517 "10.0.0.0", self.pg0.remote_ip4, 100))
518 self.deleted_routes.extend(self.unconfig_fib_many_to_one(
519 "10.0.0.10", self.pg0.remote_ip4, 10))
520 for x in self.deleted_routes:
521 self.configured_routes.remove(x)
522
Matej Klotton16a14cd2016-12-07 15:09:13 +0100523 tmp = self.config_fib_many_to_one(
524 "10.0.0.10", self.pg0.remote_ip4, 5)
525 self.configured_routes.extend(tmp)
526 for x in tmp:
527 self.deleted_routes.remove(x)
528
529 self.configured_routes.extend(self.config_fib_many_to_one(
530 "10.0.1.0", self.pg0.remote_ip4, 100))
531
532 fib_dump = self.vapi.ip_fib_dump()
533 self.verify_route_dump(fib_dump, self.configured_routes)
534
535 self.stream_1 = self.create_stream(
536 self.pg1, self.pg0, self.configured_routes, 300)
537 self.stream_2 = self.create_stream(
538 self.pg2, self.pg0, self.configured_routes, 300)
539 self.stream_3 = self.create_stream(
540 self.pg1, self.pg0, self.deleted_routes, 100)
541 self.stream_4 = self.create_stream(
542 self.pg2, self.pg0, self.deleted_routes, 100)
543
544 self.pg1.add_stream(self.stream_1 + self.stream_3)
545 self.pg2.add_stream(self.stream_2 + self.stream_4)
546 self.pg_enable_capture(self.pg_interfaces)
547 self.pg_start()
548
Klement Sekeradab231a2016-12-21 08:50:14 +0100549 pkts = self.pg0.get_capture(len(self.stream_1) + len(self.stream_2))
Matej Klotton16a14cd2016-12-07 15:09:13 +0100550 self.verify_capture(self.pg0, pkts, self.stream_1 + self.stream_2)
551
552 def test_4_del_routes(self):
553 """ Delete 1.5k routes
554
555 - delete 5 routes check with traffic script.
556 - add 100 routes check with traffic script.
557 """
558 self.deleted_routes.extend(self.unconfig_fib_many_to_one(
559 "10.0.0.0", self.pg0.remote_ip4, 15))
560 self.deleted_routes.extend(self.unconfig_fib_many_to_one(
561 "10.0.0.20", self.pg0.remote_ip4, 85))
562 self.deleted_routes.extend(self.unconfig_fib_many_to_one(
563 "10.0.1.0", self.pg0.remote_ip4, 100))
564 fib_dump = self.vapi.ip_fib_dump()
565 self.verify_not_in_route_dump(fib_dump, self.deleted_routes)
566
567
Neale Ranns37be7362017-02-21 17:30:26 -0800568class TestIPNull(VppTestCase):
569 """ IPv4 routes via NULL """
570
571 def setUp(self):
572 super(TestIPNull, self).setUp()
573
574 # create 2 pg interfaces
Neale Ranns3b93be52018-09-07 01:48:54 -0700575 self.create_pg_interfaces(range(2))
Neale Ranns37be7362017-02-21 17:30:26 -0800576
577 for i in self.pg_interfaces:
578 i.admin_up()
579 i.config_ip4()
580 i.resolve_arp()
581
582 def tearDown(self):
583 super(TestIPNull, self).tearDown()
584 for i in self.pg_interfaces:
585 i.unconfig_ip4()
586 i.admin_down()
587
588 def test_ip_null(self):
589 """ IP NULL route """
590
591 #
592 # A route via IP NULL that will reply with ICMP unreachables
593 #
594 ip_unreach = VppIpRoute(self, "10.0.0.1", 32, [], is_unreach=1)
595 ip_unreach.add_vpp_config()
596
597 p_unreach = (Ether(src=self.pg0.remote_mac,
598 dst=self.pg0.local_mac) /
599 IP(src=self.pg0.remote_ip4, dst="10.0.0.1") /
600 UDP(sport=1234, dport=1234) /
601 Raw('\xa5' * 100))
602
603 self.pg0.add_stream(p_unreach)
604 self.pg_enable_capture(self.pg_interfaces)
605 self.pg_start()
606
607 rx = self.pg0.get_capture(1)
608 rx = rx[0]
609 icmp = rx[ICMP]
610
611 self.assertEqual(icmptypes[icmp.type], "dest-unreach")
612 self.assertEqual(icmpcodes[icmp.type][icmp.code], "host-unreachable")
613 self.assertEqual(icmp.src, self.pg0.remote_ip4)
614 self.assertEqual(icmp.dst, "10.0.0.1")
615
616 #
617 # ICMP replies are rate limited. so sit and spin.
618 #
619 self.sleep(1)
620
621 #
622 # A route via IP NULL that will reply with ICMP prohibited
623 #
624 ip_prohibit = VppIpRoute(self, "10.0.0.2", 32, [], is_prohibit=1)
625 ip_prohibit.add_vpp_config()
626
627 p_prohibit = (Ether(src=self.pg0.remote_mac,
628 dst=self.pg0.local_mac) /
629 IP(src=self.pg0.remote_ip4, dst="10.0.0.2") /
630 UDP(sport=1234, dport=1234) /
631 Raw('\xa5' * 100))
632
633 self.pg0.add_stream(p_prohibit)
634 self.pg_enable_capture(self.pg_interfaces)
635 self.pg_start()
636
637 rx = self.pg0.get_capture(1)
638
639 rx = rx[0]
640 icmp = rx[ICMP]
641
642 self.assertEqual(icmptypes[icmp.type], "dest-unreach")
643 self.assertEqual(icmpcodes[icmp.type][icmp.code], "host-prohibited")
644 self.assertEqual(icmp.src, self.pg0.remote_ip4)
645 self.assertEqual(icmp.dst, "10.0.0.2")
646
Neale Ranns3b93be52018-09-07 01:48:54 -0700647 def test_ip_drop(self):
648 """ IP Drop Routes """
649
650 p = (Ether(src=self.pg0.remote_mac,
651 dst=self.pg0.local_mac) /
652 IP(src=self.pg0.remote_ip4, dst="1.1.1.1") /
653 UDP(sport=1234, dport=1234) /
654 Raw('\xa5' * 100))
655
656 r1 = VppIpRoute(self, "1.1.1.0", 24,
657 [VppRoutePath(self.pg1.remote_ip4,
658 self.pg1.sw_if_index)])
659 r1.add_vpp_config()
660
661 rx = self.send_and_expect(self.pg0, p * 65, self.pg1)
662
663 #
664 # insert a more specific as a drop
665 #
666 r2 = VppIpRoute(self, "1.1.1.1", 32, [], is_drop=1)
667 r2.add_vpp_config()
668
669 self.send_and_assert_no_replies(self.pg0, p * 65, "Drop Route")
670 r2.remove_vpp_config()
671 rx = self.send_and_expect(self.pg0, p * 65, self.pg1)
672
Neale Ranns37be7362017-02-21 17:30:26 -0800673
Neale Ranns180279b2017-03-16 15:49:09 -0400674class TestIPDisabled(VppTestCase):
675 """ IPv4 disabled """
676
677 def setUp(self):
678 super(TestIPDisabled, self).setUp()
679
680 # create 2 pg interfaces
681 self.create_pg_interfaces(range(2))
682
683 # PG0 is IP enalbed
684 self.pg0.admin_up()
685 self.pg0.config_ip4()
686 self.pg0.resolve_arp()
687
688 # PG 1 is not IP enabled
689 self.pg1.admin_up()
690
691 def tearDown(self):
692 super(TestIPDisabled, self).tearDown()
693 for i in self.pg_interfaces:
694 i.unconfig_ip4()
695 i.admin_down()
696
Neale Ranns180279b2017-03-16 15:49:09 -0400697 def test_ip_disabled(self):
698 """ IP Disabled """
699
700 #
701 # An (S,G).
702 # one accepting interface, pg0, 2 forwarding interfaces
703 #
704 route_232_1_1_1 = VppIpMRoute(
705 self,
706 "0.0.0.0",
707 "232.1.1.1", 32,
708 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
709 [VppMRoutePath(self.pg1.sw_if_index,
710 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
711 VppMRoutePath(self.pg0.sw_if_index,
712 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
713 route_232_1_1_1.add_vpp_config()
714
715 pu = (Ether(src=self.pg1.remote_mac,
716 dst=self.pg1.local_mac) /
717 IP(src="10.10.10.10", dst=self.pg0.remote_ip4) /
718 UDP(sport=1234, dport=1234) /
719 Raw('\xa5' * 100))
720 pm = (Ether(src=self.pg1.remote_mac,
721 dst=self.pg1.local_mac) /
722 IP(src="10.10.10.10", dst="232.1.1.1") /
723 UDP(sport=1234, dport=1234) /
724 Raw('\xa5' * 100))
725
726 #
727 # PG1 does not forward IP traffic
728 #
729 self.send_and_assert_no_replies(self.pg1, pu, "IP disabled")
730 self.send_and_assert_no_replies(self.pg1, pm, "IP disabled")
731
732 #
733 # IP enable PG1
734 #
735 self.pg1.config_ip4()
736
737 #
738 # Now we get packets through
739 #
740 self.pg1.add_stream(pu)
741 self.pg_enable_capture(self.pg_interfaces)
742 self.pg_start()
743 rx = self.pg0.get_capture(1)
744
745 self.pg1.add_stream(pm)
746 self.pg_enable_capture(self.pg_interfaces)
747 self.pg_start()
748 rx = self.pg0.get_capture(1)
749
750 #
751 # Disable PG1
752 #
753 self.pg1.unconfig_ip4()
754
755 #
756 # PG1 does not forward IP traffic
757 #
758 self.send_and_assert_no_replies(self.pg1, pu, "IP disabled")
759 self.send_and_assert_no_replies(self.pg1, pm, "IP disabled")
760
761
Neale Ranns9a69a602017-03-26 10:56:33 -0700762class TestIPSubNets(VppTestCase):
763 """ IPv4 Subnets """
764
765 def setUp(self):
766 super(TestIPSubNets, self).setUp()
767
768 # create a 2 pg interfaces
769 self.create_pg_interfaces(range(2))
770
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700771 # pg0 we will use to experiment
Neale Ranns9a69a602017-03-26 10:56:33 -0700772 self.pg0.admin_up()
773
774 # pg1 is setup normally
775 self.pg1.admin_up()
776 self.pg1.config_ip4()
777 self.pg1.resolve_arp()
778
779 def tearDown(self):
780 super(TestIPSubNets, self).tearDown()
781 for i in self.pg_interfaces:
782 i.admin_down()
783
Neale Ranns9a69a602017-03-26 10:56:33 -0700784 def test_ip_sub_nets(self):
785 """ IP Sub Nets """
786
787 #
788 # Configure a covering route to forward so we know
789 # when we are dropping
790 #
791 cover_route = VppIpRoute(self, "10.0.0.0", 8,
792 [VppRoutePath(self.pg1.remote_ip4,
793 self.pg1.sw_if_index)])
794 cover_route.add_vpp_config()
795
796 p = (Ether(src=self.pg1.remote_mac,
797 dst=self.pg1.local_mac) /
798 IP(dst="10.10.10.10", src=self.pg0.local_ip4) /
799 UDP(sport=1234, dport=1234) /
800 Raw('\xa5' * 100))
801
802 self.pg1.add_stream(p)
803 self.pg_enable_capture(self.pg_interfaces)
804 self.pg_start()
805 rx = self.pg1.get_capture(1)
806
807 #
808 # Configure some non-/24 subnets on an IP interface
809 #
810 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.10.10.10")
811
Ole Troan9a475372019-03-05 16:58:24 +0100812 self.vapi.sw_interface_add_del_address(
Ole Trøan3b0d7e42019-03-15 16:14:41 +0000813 sw_if_index=self.pg0.sw_if_index, address=ip_addr_n,
814 address_length=16)
Neale Ranns9a69a602017-03-26 10:56:33 -0700815
816 pn = (Ether(src=self.pg1.remote_mac,
817 dst=self.pg1.local_mac) /
818 IP(dst="10.10.0.0", src=self.pg0.local_ip4) /
819 UDP(sport=1234, dport=1234) /
820 Raw('\xa5' * 100))
821 pb = (Ether(src=self.pg1.remote_mac,
822 dst=self.pg1.local_mac) /
823 IP(dst="10.10.255.255", src=self.pg0.local_ip4) /
824 UDP(sport=1234, dport=1234) /
825 Raw('\xa5' * 100))
826
827 self.send_and_assert_no_replies(self.pg1, pn, "IP Network address")
828 self.send_and_assert_no_replies(self.pg1, pb, "IP Broadcast address")
829
830 # remove the sub-net and we are forwarding via the cover again
Ole Troan9a475372019-03-05 16:58:24 +0100831 self.vapi.sw_interface_add_del_address(
Ole Trøan3b0d7e42019-03-15 16:14:41 +0000832 sw_if_index=self.pg0.sw_if_index, address=ip_addr_n,
833 address_length=16, is_add=0)
Neale Ranns9a69a602017-03-26 10:56:33 -0700834 self.pg1.add_stream(pn)
835 self.pg_enable_capture(self.pg_interfaces)
836 self.pg_start()
837 rx = self.pg1.get_capture(1)
838 self.pg1.add_stream(pb)
839 self.pg_enable_capture(self.pg_interfaces)
840 self.pg_start()
841 rx = self.pg1.get_capture(1)
842
843 #
844 # A /31 is a special case where the 'other-side' is an attached host
845 # packets to that peer generate ARP requests
846 #
847 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.10.10.10")
848
Ole Troan9a475372019-03-05 16:58:24 +0100849 self.vapi.sw_interface_add_del_address(
Ole Trøan3b0d7e42019-03-15 16:14:41 +0000850 sw_if_index=self.pg0.sw_if_index, address=ip_addr_n,
851 address_length=31)
Neale Ranns9a69a602017-03-26 10:56:33 -0700852
853 pn = (Ether(src=self.pg1.remote_mac,
854 dst=self.pg1.local_mac) /
855 IP(dst="10.10.10.11", src=self.pg0.local_ip4) /
856 UDP(sport=1234, dport=1234) /
857 Raw('\xa5' * 100))
858
859 self.pg1.add_stream(pn)
860 self.pg_enable_capture(self.pg_interfaces)
861 self.pg_start()
862 rx = self.pg0.get_capture(1)
863 rx[ARP]
864
865 # remove the sub-net and we are forwarding via the cover again
Ole Troan9a475372019-03-05 16:58:24 +0100866 self.vapi.sw_interface_add_del_address(
Ole Trøan3b0d7e42019-03-15 16:14:41 +0000867 sw_if_index=self.pg0.sw_if_index, address=ip_addr_n,
868 address_length=31, is_add=0)
Neale Ranns9a69a602017-03-26 10:56:33 -0700869 self.pg1.add_stream(pn)
870 self.pg_enable_capture(self.pg_interfaces)
871 self.pg_start()
872 rx = self.pg1.get_capture(1)
873
874
Neale Ranns227038a2017-04-21 01:07:59 -0700875class TestIPLoadBalance(VppTestCase):
876 """ IPv4 Load-Balancing """
877
878 def setUp(self):
879 super(TestIPLoadBalance, self).setUp()
880
881 self.create_pg_interfaces(range(5))
Neale Ranns15002542017-09-10 04:39:11 -0700882 mpls_tbl = VppMplsTable(self, 0)
883 mpls_tbl.add_vpp_config()
Neale Ranns227038a2017-04-21 01:07:59 -0700884
885 for i in self.pg_interfaces:
886 i.admin_up()
887 i.config_ip4()
888 i.resolve_arp()
Neale Ranns71275e32017-05-25 12:38:58 -0700889 i.enable_mpls()
Neale Ranns227038a2017-04-21 01:07:59 -0700890
891 def tearDown(self):
Neale Ranns227038a2017-04-21 01:07:59 -0700892 for i in self.pg_interfaces:
Neale Ranns71275e32017-05-25 12:38:58 -0700893 i.disable_mpls()
Neale Ranns227038a2017-04-21 01:07:59 -0700894 i.unconfig_ip4()
895 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -0700896 super(TestIPLoadBalance, self).tearDown()
Neale Ranns227038a2017-04-21 01:07:59 -0700897
898 def send_and_expect_load_balancing(self, input, pkts, outputs):
899 input.add_stream(pkts)
900 self.pg_enable_capture(self.pg_interfaces)
901 self.pg_start()
Neale Ranns63480742019-03-13 06:41:52 -0700902 rxs = []
Neale Ranns227038a2017-04-21 01:07:59 -0700903 for oo in outputs:
904 rx = oo._get_capture(1)
905 self.assertNotEqual(0, len(rx))
Neale Ranns63480742019-03-13 06:41:52 -0700906 for r in rx:
907 rxs.append(r)
908 return rxs
Neale Ranns227038a2017-04-21 01:07:59 -0700909
Neale Ranns42e6b092017-07-31 02:56:03 -0700910 def send_and_expect_one_itf(self, input, pkts, itf):
911 input.add_stream(pkts)
912 self.pg_enable_capture(self.pg_interfaces)
913 self.pg_start()
914 rx = itf.get_capture(len(pkts))
915
Neale Ranns227038a2017-04-21 01:07:59 -0700916 def test_ip_load_balance(self):
917 """ IP Load-Balancing """
918
919 #
920 # An array of packets that differ only in the destination port
921 #
Neale Ranns71275e32017-05-25 12:38:58 -0700922 port_ip_pkts = []
923 port_mpls_pkts = []
Neale Ranns227038a2017-04-21 01:07:59 -0700924
925 #
926 # An array of packets that differ only in the source address
927 #
Neale Ranns71275e32017-05-25 12:38:58 -0700928 src_ip_pkts = []
929 src_mpls_pkts = []
Neale Ranns227038a2017-04-21 01:07:59 -0700930
931 for ii in range(65):
Neale Ranns71275e32017-05-25 12:38:58 -0700932 port_ip_hdr = (IP(dst="10.0.0.1", src="20.0.0.1") /
933 UDP(sport=1234, dport=1234 + ii) /
934 Raw('\xa5' * 100))
935 port_ip_pkts.append((Ether(src=self.pg0.remote_mac,
936 dst=self.pg0.local_mac) /
937 port_ip_hdr))
938 port_mpls_pkts.append((Ether(src=self.pg0.remote_mac,
939 dst=self.pg0.local_mac) /
940 MPLS(label=66, ttl=2) /
941 port_ip_hdr))
942
943 src_ip_hdr = (IP(dst="10.0.0.1", src="20.0.0.%d" % ii) /
944 UDP(sport=1234, dport=1234) /
945 Raw('\xa5' * 100))
946 src_ip_pkts.append((Ether(src=self.pg0.remote_mac,
947 dst=self.pg0.local_mac) /
948 src_ip_hdr))
949 src_mpls_pkts.append((Ether(src=self.pg0.remote_mac,
950 dst=self.pg0.local_mac) /
951 MPLS(label=66, ttl=2) /
952 src_ip_hdr))
Neale Ranns227038a2017-04-21 01:07:59 -0700953
954 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
955 [VppRoutePath(self.pg1.remote_ip4,
956 self.pg1.sw_if_index),
957 VppRoutePath(self.pg2.remote_ip4,
958 self.pg2.sw_if_index)])
959 route_10_0_0_1.add_vpp_config()
960
Neale Ranns71275e32017-05-25 12:38:58 -0700961 binding = VppMplsIpBind(self, 66, "10.0.0.1", 32)
962 binding.add_vpp_config()
963
Neale Ranns227038a2017-04-21 01:07:59 -0700964 #
965 # inject the packet on pg0 - expect load-balancing across the 2 paths
966 # - since the default hash config is to use IP src,dst and port
967 # src,dst
968 # We are not going to ensure equal amounts of packets across each link,
969 # since the hash algorithm is statistical and therefore this can never
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700970 # be guaranteed. But with 64 different packets we do expect some
Neale Ranns227038a2017-04-21 01:07:59 -0700971 # balancing. So instead just ensure there is traffic on each link.
972 #
Neale Ranns71275e32017-05-25 12:38:58 -0700973 self.send_and_expect_load_balancing(self.pg0, port_ip_pkts,
Neale Ranns227038a2017-04-21 01:07:59 -0700974 [self.pg1, self.pg2])
Neale Ranns71275e32017-05-25 12:38:58 -0700975 self.send_and_expect_load_balancing(self.pg0, src_ip_pkts,
976 [self.pg1, self.pg2])
977 self.send_and_expect_load_balancing(self.pg0, port_mpls_pkts,
978 [self.pg1, self.pg2])
979 self.send_and_expect_load_balancing(self.pg0, src_mpls_pkts,
Neale Ranns227038a2017-04-21 01:07:59 -0700980 [self.pg1, self.pg2])
981
982 #
983 # change the flow hash config so it's only IP src,dst
984 # - now only the stream with differing source address will
985 # load-balance
986 #
Ole Troana5b2eec2019-03-11 19:23:25 +0100987 self.vapi.set_ip_flow_hash(vrf_id=0, src=1, dst=1, sport=0, dport=0)
Neale Ranns227038a2017-04-21 01:07:59 -0700988
Neale Ranns71275e32017-05-25 12:38:58 -0700989 self.send_and_expect_load_balancing(self.pg0, src_ip_pkts,
990 [self.pg1, self.pg2])
991 self.send_and_expect_load_balancing(self.pg0, src_mpls_pkts,
Neale Ranns227038a2017-04-21 01:07:59 -0700992 [self.pg1, self.pg2])
993
Neale Ranns42e6b092017-07-31 02:56:03 -0700994 self.send_and_expect_one_itf(self.pg0, port_ip_pkts, self.pg2)
Neale Ranns227038a2017-04-21 01:07:59 -0700995
996 #
997 # change the flow hash config back to defaults
998 #
Ole Troana5b2eec2019-03-11 19:23:25 +0100999 self.vapi.set_ip_flow_hash(vrf_id=0, src=1, dst=1, sport=1, dport=1)
Neale Ranns227038a2017-04-21 01:07:59 -07001000
1001 #
1002 # Recursive prefixes
1003 # - testing that 2 stages of load-balancing occurs and there is no
1004 # polarisation (i.e. only 2 of 4 paths are used)
1005 #
1006 port_pkts = []
1007 src_pkts = []
1008
1009 for ii in range(257):
1010 port_pkts.append((Ether(src=self.pg0.remote_mac,
1011 dst=self.pg0.local_mac) /
1012 IP(dst="1.1.1.1", src="20.0.0.1") /
1013 UDP(sport=1234, dport=1234 + ii) /
1014 Raw('\xa5' * 100)))
1015 src_pkts.append((Ether(src=self.pg0.remote_mac,
1016 dst=self.pg0.local_mac) /
1017 IP(dst="1.1.1.1", src="20.0.0.%d" % ii) /
1018 UDP(sport=1234, dport=1234) /
1019 Raw('\xa5' * 100)))
1020
1021 route_10_0_0_2 = VppIpRoute(self, "10.0.0.2", 32,
1022 [VppRoutePath(self.pg3.remote_ip4,
1023 self.pg3.sw_if_index),
1024 VppRoutePath(self.pg4.remote_ip4,
1025 self.pg4.sw_if_index)])
1026 route_10_0_0_2.add_vpp_config()
1027
1028 route_1_1_1_1 = VppIpRoute(self, "1.1.1.1", 32,
1029 [VppRoutePath("10.0.0.2", 0xffffffff),
1030 VppRoutePath("10.0.0.1", 0xffffffff)])
1031 route_1_1_1_1.add_vpp_config()
1032
1033 #
1034 # inject the packet on pg0 - expect load-balancing across all 4 paths
1035 #
1036 self.vapi.cli("clear trace")
1037 self.send_and_expect_load_balancing(self.pg0, port_pkts,
1038 [self.pg1, self.pg2,
1039 self.pg3, self.pg4])
1040 self.send_and_expect_load_balancing(self.pg0, src_pkts,
1041 [self.pg1, self.pg2,
1042 self.pg3, self.pg4])
1043
Neale Ranns42e6b092017-07-31 02:56:03 -07001044 #
Neale Ranns63480742019-03-13 06:41:52 -07001045 # bring down pg1 expect LB to adjust to use only those that are pu
1046 #
1047 self.pg1.link_down()
1048
1049 rx = self.send_and_expect_load_balancing(self.pg0, src_pkts,
1050 [self.pg2, self.pg3,
1051 self.pg4])
1052 self.assertEqual(len(src_pkts), len(rx))
1053
1054 #
1055 # bring down pg2 expect LB to adjust to use only those that are pu
1056 #
1057 self.pg2.link_down()
1058
1059 rx = self.send_and_expect_load_balancing(self.pg0, src_pkts,
1060 [self.pg3, self.pg4])
1061 self.assertEqual(len(src_pkts), len(rx))
1062
1063 #
1064 # bring the links back up - expect LB over all again
1065 #
1066 self.pg1.link_up()
1067 self.pg2.link_up()
1068
1069 rx = self.send_and_expect_load_balancing(self.pg0, src_pkts,
1070 [self.pg1, self.pg2,
1071 self.pg3, self.pg4])
1072 self.assertEqual(len(src_pkts), len(rx))
1073
1074 #
1075 # The same link-up/down but this time admin state
1076 #
1077 self.pg1.admin_down()
1078 self.pg2.admin_down()
1079 rx = self.send_and_expect_load_balancing(self.pg0, src_pkts,
1080 [self.pg3, self.pg4])
1081 self.assertEqual(len(src_pkts), len(rx))
1082 self.pg1.admin_up()
1083 self.pg2.admin_up()
1084 self.pg1.resolve_arp()
1085 self.pg2.resolve_arp()
1086 rx = self.send_and_expect_load_balancing(self.pg0, src_pkts,
1087 [self.pg1, self.pg2,
1088 self.pg3, self.pg4])
1089 self.assertEqual(len(src_pkts), len(rx))
1090
1091 #
Neale Ranns42e6b092017-07-31 02:56:03 -07001092 # Recursive prefixes
1093 # - testing that 2 stages of load-balancing, no choices
1094 #
1095 port_pkts = []
1096
1097 for ii in range(257):
1098 port_pkts.append((Ether(src=self.pg0.remote_mac,
1099 dst=self.pg0.local_mac) /
1100 IP(dst="1.1.1.2", src="20.0.0.2") /
1101 UDP(sport=1234, dport=1234 + ii) /
1102 Raw('\xa5' * 100)))
1103
1104 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
1105 [VppRoutePath(self.pg3.remote_ip4,
1106 self.pg3.sw_if_index)])
1107 route_10_0_0_3.add_vpp_config()
1108
1109 route_1_1_1_2 = VppIpRoute(self, "1.1.1.2", 32,
1110 [VppRoutePath("10.0.0.3", 0xffffffff)])
1111 route_1_1_1_2.add_vpp_config()
1112
1113 #
Neale Ranns63480742019-03-13 06:41:52 -07001114 # inject the packet on pg0 - rx only on via routes output interface
Neale Ranns42e6b092017-07-31 02:56:03 -07001115 #
1116 self.vapi.cli("clear trace")
1117 self.send_and_expect_one_itf(self.pg0, port_pkts, self.pg3)
1118
Neale Ranns63480742019-03-13 06:41:52 -07001119 #
1120 # Add a LB route in the presence of a down link - expect no
1121 # packets over the down link
1122 #
1123 self.pg3.link_down()
1124
1125 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
1126 [VppRoutePath(self.pg3.remote_ip4,
1127 self.pg3.sw_if_index),
1128 VppRoutePath(self.pg4.remote_ip4,
1129 self.pg4.sw_if_index)])
1130 route_10_0_0_3.add_vpp_config()
1131
1132 port_pkts = []
1133 for ii in range(257):
1134 port_pkts.append(Ether(src=self.pg0.remote_mac,
1135 dst=self.pg0.local_mac) /
1136 IP(dst="10.0.0.3", src="20.0.0.2") /
1137 UDP(sport=1234, dport=1234 + ii) /
1138 Raw('\xa5' * 100))
1139
1140 self.send_and_expect_one_itf(self.pg0, port_pkts, self.pg4)
1141
1142 # bring the link back up
1143 self.pg3.link_up()
1144
1145 rx = self.send_and_expect_load_balancing(self.pg0, port_pkts,
1146 [self.pg3, self.pg4])
1147 self.assertEqual(len(src_pkts), len(rx))
1148
Neale Ranns30d0fd42017-05-30 07:30:04 -07001149
1150class TestIPVlan0(VppTestCase):
1151 """ IPv4 VLAN-0 """
1152
1153 def setUp(self):
1154 super(TestIPVlan0, self).setUp()
1155
1156 self.create_pg_interfaces(range(2))
Neale Ranns15002542017-09-10 04:39:11 -07001157 mpls_tbl = VppMplsTable(self, 0)
1158 mpls_tbl.add_vpp_config()
Neale Ranns30d0fd42017-05-30 07:30:04 -07001159
1160 for i in self.pg_interfaces:
1161 i.admin_up()
1162 i.config_ip4()
1163 i.resolve_arp()
1164 i.enable_mpls()
1165
1166 def tearDown(self):
Neale Ranns30d0fd42017-05-30 07:30:04 -07001167 for i in self.pg_interfaces:
1168 i.disable_mpls()
1169 i.unconfig_ip4()
1170 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -07001171 super(TestIPVlan0, self).tearDown()
Neale Ranns30d0fd42017-05-30 07:30:04 -07001172
Neale Ranns30d0fd42017-05-30 07:30:04 -07001173 def test_ip_vlan_0(self):
1174 """ IP VLAN-0 """
1175
1176 pkts = (Ether(src=self.pg0.remote_mac,
1177 dst=self.pg0.local_mac) /
1178 Dot1Q(vlan=0) /
1179 IP(dst=self.pg1.remote_ip4,
1180 src=self.pg0.remote_ip4) /
1181 UDP(sport=1234, dport=1234) /
1182 Raw('\xa5' * 100)) * 65
1183
1184 #
1185 # Expect that packets sent on VLAN-0 are forwarded on the
1186 # main interface.
1187 #
1188 self.send_and_expect(self.pg0, pkts, self.pg1)
1189
1190
Neale Rannsd91c1db2017-07-31 02:30:50 -07001191class TestIPPunt(VppTestCase):
1192 """ IPv4 Punt Police/Redirect """
1193
1194 def setUp(self):
1195 super(TestIPPunt, self).setUp()
1196
Pavel Kotucek609e1212018-11-27 09:59:44 +01001197 self.create_pg_interfaces(range(4))
Neale Rannsd91c1db2017-07-31 02:30:50 -07001198
1199 for i in self.pg_interfaces:
1200 i.admin_up()
1201 i.config_ip4()
1202 i.resolve_arp()
1203
1204 def tearDown(self):
1205 super(TestIPPunt, self).tearDown()
1206 for i in self.pg_interfaces:
1207 i.unconfig_ip4()
1208 i.admin_down()
1209
Neale Rannsd91c1db2017-07-31 02:30:50 -07001210 def test_ip_punt(self):
1211 """ IP punt police and redirect """
1212
1213 p = (Ether(src=self.pg0.remote_mac,
1214 dst=self.pg0.local_mac) /
1215 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
1216 TCP(sport=1234, dport=1234) /
1217 Raw('\xa5' * 100))
1218
1219 pkts = p * 1025
1220
1221 #
1222 # Configure a punt redirect via pg1.
1223 #
Ole Troan0bcad322018-12-11 13:04:01 +01001224 nh_addr = self.pg1.remote_ip4
Neale Rannsd91c1db2017-07-31 02:30:50 -07001225 self.vapi.ip_punt_redirect(self.pg0.sw_if_index,
1226 self.pg1.sw_if_index,
1227 nh_addr)
1228
1229 self.send_and_expect(self.pg0, pkts, self.pg1)
1230
1231 #
1232 # add a policer
1233 #
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08001234 policer = self.vapi.policer_add_del(b"ip4-punt", 400, 0, 10, 0,
Neale Rannsd91c1db2017-07-31 02:30:50 -07001235 rate_type=1)
1236 self.vapi.ip_punt_police(policer.policer_index)
1237
1238 self.vapi.cli("clear trace")
1239 self.pg0.add_stream(pkts)
1240 self.pg_enable_capture(self.pg_interfaces)
1241 self.pg_start()
1242
1243 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001244 # the number of packet received should be greater than 0,
Neale Rannsd91c1db2017-07-31 02:30:50 -07001245 # but not equal to the number sent, since some were policed
1246 #
1247 rx = self.pg1._get_capture(1)
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001248 self.assertGreater(len(rx), 0)
1249 self.assertLess(len(rx), len(pkts))
Neale Rannsd91c1db2017-07-31 02:30:50 -07001250
1251 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001252 # remove the policer. back to full rx
Neale Rannsd91c1db2017-07-31 02:30:50 -07001253 #
1254 self.vapi.ip_punt_police(policer.policer_index, is_add=0)
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08001255 self.vapi.policer_add_del(b"ip4-punt", 400, 0, 10, 0,
Neale Rannsd91c1db2017-07-31 02:30:50 -07001256 rate_type=1, is_add=0)
1257 self.send_and_expect(self.pg0, pkts, self.pg1)
1258
1259 #
1260 # remove the redirect. expect full drop.
1261 #
1262 self.vapi.ip_punt_redirect(self.pg0.sw_if_index,
1263 self.pg1.sw_if_index,
1264 nh_addr,
1265 is_add=0)
1266 self.send_and_assert_no_replies(self.pg0, pkts,
1267 "IP no punt config")
1268
1269 #
1270 # Add a redirect that is not input port selective
1271 #
1272 self.vapi.ip_punt_redirect(0xffffffff,
1273 self.pg1.sw_if_index,
1274 nh_addr)
1275 self.send_and_expect(self.pg0, pkts, self.pg1)
1276
1277 self.vapi.ip_punt_redirect(0xffffffff,
1278 self.pg1.sw_if_index,
1279 nh_addr,
1280 is_add=0)
1281
Pavel Kotucek609e1212018-11-27 09:59:44 +01001282 def test_ip_punt_dump(self):
1283 """ IP4 punt redirect dump"""
1284
1285 #
1286 # Configure a punt redirects
1287 #
Ole Troan0bcad322018-12-11 13:04:01 +01001288 nh_address = self.pg3.remote_ip4
Pavel Kotucek609e1212018-11-27 09:59:44 +01001289 self.vapi.ip_punt_redirect(self.pg0.sw_if_index,
1290 self.pg3.sw_if_index,
1291 nh_address)
1292 self.vapi.ip_punt_redirect(self.pg1.sw_if_index,
1293 self.pg3.sw_if_index,
1294 nh_address)
1295 self.vapi.ip_punt_redirect(self.pg2.sw_if_index,
1296 self.pg3.sw_if_index,
Ole Troan0bcad322018-12-11 13:04:01 +01001297 '0.0.0.0')
Pavel Kotucek609e1212018-11-27 09:59:44 +01001298
1299 #
1300 # Dump pg0 punt redirects
1301 #
1302 punts = self.vapi.ip_punt_redirect_dump(self.pg0.sw_if_index)
1303 for p in punts:
1304 self.assertEqual(p.punt.rx_sw_if_index, self.pg0.sw_if_index)
1305
1306 #
1307 # Dump punt redirects for all interfaces
1308 #
1309 punts = self.vapi.ip_punt_redirect_dump(0xffffffff)
1310 self.assertEqual(len(punts), 3)
1311 for p in punts:
1312 self.assertEqual(p.punt.tx_sw_if_index, self.pg3.sw_if_index)
Ole Troan0bcad322018-12-11 13:04:01 +01001313 self.assertNotEqual(punts[1].punt.nh, self.pg3.remote_ip4)
1314 self.assertEqual(str(punts[2].punt.nh), '0.0.0.0')
Pavel Kotucek609e1212018-11-27 09:59:44 +01001315
Neale Rannsd91c1db2017-07-31 02:30:50 -07001316
Neale Ranns054c03a2017-10-13 05:15:07 -07001317class TestIPDeag(VppTestCase):
1318 """ IPv4 Deaggregate Routes """
1319
1320 def setUp(self):
1321 super(TestIPDeag, self).setUp()
1322
1323 self.create_pg_interfaces(range(3))
1324
1325 for i in self.pg_interfaces:
1326 i.admin_up()
1327 i.config_ip4()
1328 i.resolve_arp()
1329
1330 def tearDown(self):
1331 super(TestIPDeag, self).tearDown()
1332 for i in self.pg_interfaces:
1333 i.unconfig_ip4()
1334 i.admin_down()
1335
Neale Ranns054c03a2017-10-13 05:15:07 -07001336 def test_ip_deag(self):
1337 """ IP Deag Routes """
1338
1339 #
1340 # Create a table to be used for:
1341 # 1 - another destination address lookup
1342 # 2 - a source address lookup
1343 #
1344 table_dst = VppIpTable(self, 1)
1345 table_src = VppIpTable(self, 2)
1346 table_dst.add_vpp_config()
1347 table_src.add_vpp_config()
1348
1349 #
1350 # Add a route in the default table to point to a deag/
1351 # second lookup in each of these tables
1352 #
1353 route_to_dst = VppIpRoute(self, "1.1.1.1", 32,
1354 [VppRoutePath("0.0.0.0",
1355 0xffffffff,
1356 nh_table_id=1)])
1357 route_to_src = VppIpRoute(self, "1.1.1.2", 32,
1358 [VppRoutePath("0.0.0.0",
1359 0xffffffff,
1360 nh_table_id=2,
1361 is_source_lookup=1)])
1362 route_to_dst.add_vpp_config()
1363 route_to_src.add_vpp_config()
1364
1365 #
1366 # packets to these destination are dropped, since they'll
1367 # hit the respective default routes in the second table
1368 #
1369 p_dst = (Ether(src=self.pg0.remote_mac,
1370 dst=self.pg0.local_mac) /
1371 IP(src="5.5.5.5", dst="1.1.1.1") /
1372 TCP(sport=1234, dport=1234) /
1373 Raw('\xa5' * 100))
1374 p_src = (Ether(src=self.pg0.remote_mac,
1375 dst=self.pg0.local_mac) /
1376 IP(src="2.2.2.2", dst="1.1.1.2") /
1377 TCP(sport=1234, dport=1234) /
1378 Raw('\xa5' * 100))
1379 pkts_dst = p_dst * 257
1380 pkts_src = p_src * 257
1381
1382 self.send_and_assert_no_replies(self.pg0, pkts_dst,
1383 "IP in dst table")
1384 self.send_and_assert_no_replies(self.pg0, pkts_src,
1385 "IP in src table")
1386
1387 #
1388 # add a route in the dst table to forward via pg1
1389 #
1390 route_in_dst = VppIpRoute(self, "1.1.1.1", 32,
1391 [VppRoutePath(self.pg1.remote_ip4,
1392 self.pg1.sw_if_index)],
1393 table_id=1)
1394 route_in_dst.add_vpp_config()
1395 self.send_and_expect(self.pg0, pkts_dst, self.pg1)
1396
1397 #
1398 # add a route in the src table to forward via pg2
1399 #
1400 route_in_src = VppIpRoute(self, "2.2.2.2", 32,
1401 [VppRoutePath(self.pg2.remote_ip4,
1402 self.pg2.sw_if_index)],
1403 table_id=2)
1404 route_in_src.add_vpp_config()
1405 self.send_and_expect(self.pg0, pkts_src, self.pg2)
1406
Neale Rannsce9e0b42018-08-01 12:53:17 -07001407 #
1408 # loop in the lookup DP
1409 #
1410 route_loop = VppIpRoute(self, "2.2.2.3", 32,
1411 [VppRoutePath("0.0.0.0",
1412 0xffffffff,
1413 nh_table_id=0)])
1414 route_loop.add_vpp_config()
1415
1416 p_l = (Ether(src=self.pg0.remote_mac,
1417 dst=self.pg0.local_mac) /
1418 IP(src="2.2.2.4", dst="2.2.2.3") /
1419 TCP(sport=1234, dport=1234) /
1420 Raw('\xa5' * 100))
1421
1422 self.send_and_assert_no_replies(self.pg0, p_l * 257,
1423 "IP lookup loop")
1424
Neale Ranns054c03a2017-10-13 05:15:07 -07001425
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001426class TestIPInput(VppTestCase):
1427 """ IPv4 Input Exceptions """
1428
1429 def setUp(self):
1430 super(TestIPInput, self).setUp()
1431
1432 self.create_pg_interfaces(range(2))
1433
1434 for i in self.pg_interfaces:
1435 i.admin_up()
1436 i.config_ip4()
1437 i.resolve_arp()
1438
1439 def tearDown(self):
1440 super(TestIPInput, self).tearDown()
1441 for i in self.pg_interfaces:
1442 i.unconfig_ip4()
1443 i.admin_down()
1444
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001445 def test_ip_input(self):
1446 """ IP Input Exceptions """
1447
1448 # i can't find a way in scapy to construct an IP packet
1449 # with a length less than the IP header length
1450
1451 #
1452 # Packet too short - this is forwarded
1453 #
1454 p_short = (Ether(src=self.pg0.remote_mac,
1455 dst=self.pg0.local_mac) /
1456 IP(src=self.pg0.remote_ip4,
1457 dst=self.pg1.remote_ip4,
1458 len=40) /
1459 UDP(sport=1234, dport=1234) /
1460 Raw('\xa5' * 100))
1461
1462 rx = self.send_and_expect(self.pg0, p_short * 65, self.pg1)
1463
1464 #
1465 # Packet too long - this is dropped
1466 #
1467 p_long = (Ether(src=self.pg0.remote_mac,
1468 dst=self.pg0.local_mac) /
1469 IP(src=self.pg0.remote_ip4,
1470 dst=self.pg1.remote_ip4,
1471 len=400) /
1472 UDP(sport=1234, dport=1234) /
1473 Raw('\xa5' * 100))
1474
1475 rx = self.send_and_assert_no_replies(self.pg0, p_long * 65,
1476 "too long")
1477
1478 #
1479 # bad chksum - this is dropped
1480 #
1481 p_chksum = (Ether(src=self.pg0.remote_mac,
1482 dst=self.pg0.local_mac) /
1483 IP(src=self.pg0.remote_ip4,
1484 dst=self.pg1.remote_ip4,
1485 chksum=400) /
1486 UDP(sport=1234, dport=1234) /
1487 Raw('\xa5' * 100))
1488
1489 rx = self.send_and_assert_no_replies(self.pg0, p_chksum * 65,
1490 "bad checksum")
1491
1492 #
1493 # bad version - this is dropped
1494 #
1495 p_ver = (Ether(src=self.pg0.remote_mac,
1496 dst=self.pg0.local_mac) /
1497 IP(src=self.pg0.remote_ip4,
1498 dst=self.pg1.remote_ip4,
1499 version=3) /
1500 UDP(sport=1234, dport=1234) /
1501 Raw('\xa5' * 100))
1502
1503 rx = self.send_and_assert_no_replies(self.pg0, p_ver * 65,
1504 "funky version")
1505
1506 #
1507 # fragment offset 1 - this is dropped
1508 #
1509 p_frag = (Ether(src=self.pg0.remote_mac,
1510 dst=self.pg0.local_mac) /
1511 IP(src=self.pg0.remote_ip4,
1512 dst=self.pg1.remote_ip4,
1513 frag=1) /
1514 UDP(sport=1234, dport=1234) /
1515 Raw('\xa5' * 100))
1516
1517 rx = self.send_and_assert_no_replies(self.pg0, p_frag * 65,
1518 "frag offset")
1519
1520 #
1521 # TTL expired packet
1522 #
1523 p_ttl = (Ether(src=self.pg0.remote_mac,
1524 dst=self.pg0.local_mac) /
1525 IP(src=self.pg0.remote_ip4,
1526 dst=self.pg1.remote_ip4,
1527 ttl=1) /
1528 UDP(sport=1234, dport=1234) /
1529 Raw('\xa5' * 100))
1530
1531 rx = self.send_and_expect(self.pg0, p_ttl * 65, self.pg0)
1532
1533 rx = rx[0]
1534 icmp = rx[ICMP]
1535
1536 self.assertEqual(icmptypes[icmp.type], "time-exceeded")
1537 self.assertEqual(icmpcodes[icmp.type][icmp.code],
1538 "ttl-zero-during-transit")
1539 self.assertEqual(icmp.src, self.pg0.remote_ip4)
1540 self.assertEqual(icmp.dst, self.pg1.remote_ip4)
1541
Neale Rannsffd78d12018-02-09 06:05:16 -08001542 #
1543 # MTU exceeded
1544 #
1545 p_mtu = (Ether(src=self.pg0.remote_mac,
1546 dst=self.pg0.local_mac) /
1547 IP(src=self.pg0.remote_ip4,
1548 dst=self.pg1.remote_ip4,
Ole Troan8a9c8f12018-05-18 11:01:31 +02001549 ttl=10, flags='DF') /
Neale Rannsffd78d12018-02-09 06:05:16 -08001550 UDP(sport=1234, dport=1234) /
1551 Raw('\xa5' * 2000))
1552
Ole Troand7231612018-06-07 10:17:57 +02001553 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1500, 0, 0, 0])
Neale Rannsffd78d12018-02-09 06:05:16 -08001554
1555 rx = self.send_and_expect(self.pg0, p_mtu * 65, self.pg0)
1556 rx = rx[0]
1557 icmp = rx[ICMP]
1558
1559 self.assertEqual(icmptypes[icmp.type], "dest-unreach")
1560 self.assertEqual(icmpcodes[icmp.type][icmp.code],
1561 "fragmentation-needed")
1562 self.assertEqual(icmp.src, self.pg0.remote_ip4)
1563 self.assertEqual(icmp.dst, self.pg1.remote_ip4)
1564
Ole Troand7231612018-06-07 10:17:57 +02001565 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [2500, 0, 0, 0])
Neale Rannsffd78d12018-02-09 06:05:16 -08001566 rx = self.send_and_expect(self.pg0, p_mtu * 65, self.pg1)
1567
Ole Troand7231612018-06-07 10:17:57 +02001568 # Reset MTU for subsequent tests
1569 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [9000, 0, 0, 0])
Neale Ranns4c7c8e52017-10-21 09:37:55 -07001570
Neale Rannsbe2286b2018-12-09 12:54:51 -08001571 #
1572 # source address 0.0.0.0 and 25.255.255.255 and for-us
1573 #
1574 p_s0 = (Ether(src=self.pg0.remote_mac,
1575 dst=self.pg0.local_mac) /
1576 IP(src="0.0.0.0",
1577 dst=self.pg0.local_ip4) /
1578 ICMP(id=4, seq=4) /
1579 Raw(load='\x0a' * 18))
1580 rx = self.send_and_assert_no_replies(self.pg0, p_s0 * 17)
1581
1582 p_s0 = (Ether(src=self.pg0.remote_mac,
1583 dst=self.pg0.local_mac) /
1584 IP(src="255.255.255.255",
1585 dst=self.pg0.local_ip4) /
1586 ICMP(id=4, seq=4) /
1587 Raw(load='\x0a' * 18))
1588 rx = self.send_and_assert_no_replies(self.pg0, p_s0 * 17)
1589
Neale Ranns1855b8e2018-07-11 10:31:26 -07001590
1591class TestIPDirectedBroadcast(VppTestCase):
1592 """ IPv4 Directed Broadcast """
1593
1594 def setUp(self):
1595 super(TestIPDirectedBroadcast, self).setUp()
1596
1597 self.create_pg_interfaces(range(2))
1598
1599 for i in self.pg_interfaces:
1600 i.admin_up()
1601
1602 def tearDown(self):
1603 super(TestIPDirectedBroadcast, self).tearDown()
1604 for i in self.pg_interfaces:
1605 i.admin_down()
1606
1607 def test_ip_input(self):
1608 """ IP Directed Broadcast """
1609
1610 #
1611 # set the directed broadcast on pg0 first, then config IP4 addresses
1612 # for pg1 directed broadcast is always disabled
1613 self.vapi.sw_interface_set_ip_directed_broadcast(
1614 self.pg0.sw_if_index, 1)
1615
1616 p0 = (Ether(src=self.pg1.remote_mac,
1617 dst=self.pg1.local_mac) /
1618 IP(src="1.1.1.1",
1619 dst=self.pg0._local_ip4_bcast) /
1620 UDP(sport=1234, dport=1234) /
1621 Raw('\xa5' * 2000))
1622 p1 = (Ether(src=self.pg0.remote_mac,
1623 dst=self.pg0.local_mac) /
1624 IP(src="1.1.1.1",
1625 dst=self.pg1._local_ip4_bcast) /
1626 UDP(sport=1234, dport=1234) /
1627 Raw('\xa5' * 2000))
1628
1629 self.pg0.config_ip4()
1630 self.pg0.resolve_arp()
1631 self.pg1.config_ip4()
1632 self.pg1.resolve_arp()
1633
1634 #
1635 # test packet is L2 broadcast
1636 #
1637 rx = self.send_and_expect(self.pg1, p0 * 65, self.pg0)
1638 self.assertTrue(rx[0][Ether].dst, "ff:ff:ff:ff:ff:ff")
1639
1640 self.send_and_assert_no_replies(self.pg0, p1 * 65,
1641 "directed broadcast disabled")
1642
1643 #
1644 # toggle directed broadcast on pg0
1645 #
1646 self.vapi.sw_interface_set_ip_directed_broadcast(
1647 self.pg0.sw_if_index, 0)
1648 self.send_and_assert_no_replies(self.pg1, p0 * 65,
1649 "directed broadcast disabled")
1650
1651 self.vapi.sw_interface_set_ip_directed_broadcast(
1652 self.pg0.sw_if_index, 1)
1653 rx = self.send_and_expect(self.pg1, p0 * 65, self.pg0)
1654
1655 self.pg0.unconfig_ip4()
1656 self.pg1.unconfig_ip4()
1657
1658
mu.duojiao59a82952018-10-11 14:27:30 +08001659class TestIPLPM(VppTestCase):
1660 """ IPv4 longest Prefix Match """
1661
1662 def setUp(self):
1663 super(TestIPLPM, self).setUp()
1664
1665 self.create_pg_interfaces(range(4))
1666
1667 for i in self.pg_interfaces:
1668 i.admin_up()
1669 i.config_ip4()
1670 i.resolve_arp()
1671
1672 def tearDown(self):
1673 super(TestIPLPM, self).tearDown()
1674 for i in self.pg_interfaces:
1675 i.admin_down()
1676 i.unconfig_ip4()
1677
1678 def test_ip_lpm(self):
1679 """ IP longest Prefix Match """
1680
1681 s_24 = VppIpRoute(self, "10.1.2.0", 24,
1682 [VppRoutePath(self.pg1.remote_ip4,
1683 self.pg1.sw_if_index)])
1684 s_24.add_vpp_config()
1685 s_8 = VppIpRoute(self, "10.0.0.0", 8,
1686 [VppRoutePath(self.pg2.remote_ip4,
1687 self.pg2.sw_if_index)])
1688 s_8.add_vpp_config()
1689
1690 p_8 = (Ether(src=self.pg0.remote_mac,
1691 dst=self.pg0.local_mac) /
1692 IP(src="1.1.1.1",
1693 dst="10.1.1.1") /
1694 UDP(sport=1234, dport=1234) /
1695 Raw('\xa5' * 2000))
1696 p_24 = (Ether(src=self.pg0.remote_mac,
1697 dst=self.pg0.local_mac) /
1698 IP(src="1.1.1.1",
1699 dst="10.1.2.1") /
1700 UDP(sport=1234, dport=1234) /
1701 Raw('\xa5' * 2000))
1702
1703 self.logger.info(self.vapi.cli("sh ip fib mtrie"))
1704 rx = self.send_and_expect(self.pg0, p_8 * 65, self.pg2)
1705 rx = self.send_and_expect(self.pg0, p_24 * 65, self.pg1)
1706
1707
Juraj Sloboda68b7cb82018-10-16 12:18:21 +02001708class TestIPv4Frag(VppTestCase):
1709 """ IPv4 fragmentation """
1710
1711 @classmethod
1712 def setUpClass(cls):
1713 super(TestIPv4Frag, cls).setUpClass()
1714
1715 cls.create_pg_interfaces([0, 1])
1716 cls.src_if = cls.pg0
1717 cls.dst_if = cls.pg1
1718
1719 # setup all interfaces
1720 for i in cls.pg_interfaces:
1721 i.admin_up()
1722 i.config_ip4()
1723 i.resolve_arp()
1724
1725 def test_frag_large_packets(self):
1726 """ Fragmentation of large packets """
1727
1728 p = (Ether(dst=self.src_if.local_mac, src=self.src_if.remote_mac) /
1729 IP(src=self.src_if.remote_ip4, dst=self.dst_if.remote_ip4) /
1730 UDP(sport=1234, dport=5678) / Raw())
1731 self.extend_packet(p, 6000, "abcde")
1732 saved_payload = p[Raw].load
1733
1734 # Force fragmentation by setting MTU of output interface
1735 # lower than packet size
1736 self.vapi.sw_interface_set_mtu(self.dst_if.sw_if_index,
1737 [5000, 0, 0, 0])
1738
1739 self.pg_enable_capture()
1740 self.src_if.add_stream(p)
1741 self.pg_start()
1742
1743 # Expecting 3 fragments because size of created fragments currently
1744 # cannot be larger then VPP buffer size (which is 2048)
1745 packets = self.dst_if.get_capture(3)
1746
1747 # Assume VPP sends the fragments in order
1748 payload = ''
1749 for p in packets:
1750 payload_offset = p.frag * 8
1751 if payload_offset > 0:
1752 payload_offset -= 8 # UDP header is not in payload
1753 self.assert_equal(payload_offset, len(payload))
1754 payload += p[Raw].load
1755 self.assert_equal(payload, saved_payload, "payload")
1756
1757
Damjan Marionf56b77a2016-10-03 19:44:57 +02001758if __name__ == '__main__':
Klement Sekeraf62ae122016-10-11 11:47:09 +02001759 unittest.main(testRunner=VppTestRunner)