Revert "MTU: Setting of MTU on software interface (instead of hardware interface)"
[vpp.git] / test / test_ip4.py
1 #!/usr/bin/env python
2 import random
3 import socket
4 import unittest
5
6 from framework import VppTestCase, VppTestRunner
7 from vpp_sub_interface import VppSubInterface, VppDot1QSubint, VppDot1ADSubint
8 from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpMRoute, \
9     VppMRoutePath, MRouteItfFlags, MRouteEntryFlags, VppMplsIpBind, \
10     VppMplsTable, VppIpTable
11
12 from scapy.packet import Raw
13 from scapy.layers.l2 import Ether, Dot1Q, ARP
14 from scapy.layers.inet import IP, UDP, TCP, ICMP, icmptypes, icmpcodes
15 from util import ppp
16 from scapy.contrib.mpls import MPLS
17
18
19 class TestIPv4(VppTestCase):
20     """ IPv4 Test Case """
21
22     def setUp(self):
23         """
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.
39         :ivar list pg_if_packet_sizes: packet sizes in test.
40         """
41         super(TestIPv4, self).setUp()
42
43         # create 3 pg interfaces
44         self.create_pg_interfaces(range(3))
45
46         # create 2 subinterfaces for pg1 and pg2
47         self.sub_interfaces = [
48             VppDot1QSubint(self, self.pg1, 100),
49             VppDot1ADSubint(self, self.pg2, 200, 300, 400)]
50
51         # packet flows mapping pg0 -> pg1.sub, pg2.sub, etc.
52         self.flows = dict()
53         self.flows[self.pg0] = [self.pg1.sub_if, self.pg2.sub_if]
54         self.flows[self.pg1.sub_if] = [self.pg0, self.pg2.sub_if]
55         self.flows[self.pg2.sub_if] = [self.pg0, self.pg1.sub_if]
56
57         # packet sizes
58         self.pg_if_packet_sizes = [64, 512, 1518, 9018]
59         self.sub_if_packet_sizes = [64, 512, 1518 + 4, 9018 + 4]
60
61         self.interfaces = list(self.pg_interfaces)
62         self.interfaces.extend(self.sub_interfaces)
63
64         # setup all interfaces
65         for i in self.interfaces:
66             i.admin_up()
67             i.config_ip4()
68             i.resolve_arp()
69
70         # config 2M FIB entries
71         self.config_fib_entries(200)
72
73     def tearDown(self):
74         """Run standard test teardown and log ``show ip arp``."""
75         super(TestIPv4, self).tearDown()
76         if not self.vpp_dead:
77             self.logger.info(self.vapi.cli("show ip arp"))
78             # info(self.vapi.cli("show ip fib"))  # many entries
79
80     def config_fib_entries(self, count):
81         """For each interface add to the FIB table *count* routes to
82         "10.0.0.1/32" destination with interface's local address as next-hop
83         address.
84
85         :param int count: Number of FIB entries.
86
87         - *TODO:* check if the next-hop address shouldn't be remote address
88           instead of local address.
89         """
90         n_int = len(self.interfaces)
91         percent = 0
92         counter = 0.0
93         dest_addr = socket.inet_pton(socket.AF_INET, "10.0.0.1")
94         dest_addr_len = 32
95         for i in self.interfaces:
96             next_hop_address = i.local_ip4n
97             for j in range(count / n_int):
98                 self.vapi.ip_add_del_route(
99                     dest_addr, dest_addr_len, next_hop_address)
100                 counter += 1
101                 if counter / count * 100 > percent:
102                     self.logger.info("Configure %d FIB entries .. %d%% done" %
103                                      (count, percent))
104                     percent += 1
105
106     def create_stream(self, src_if, packet_sizes):
107         """Create input packet stream for defined interface.
108
109         :param VppInterface src_if: Interface to create packet stream for.
110         :param list packet_sizes: Required packet sizes.
111         """
112         pkts = []
113         for i in range(0, 257):
114             dst_if = self.flows[src_if][i % 2]
115             info = self.create_packet_info(src_if, dst_if)
116             payload = self.info_to_payload(info)
117             p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
118                  IP(src=src_if.remote_ip4, dst=dst_if.remote_ip4) /
119                  UDP(sport=1234, dport=1234) /
120                  Raw(payload))
121             info.data = p.copy()
122             if isinstance(src_if, VppSubInterface):
123                 p = src_if.add_dot1_layer(p)
124             size = packet_sizes[(i // 2) % len(packet_sizes)]
125             self.extend_packet(p, size)
126             pkts.append(p)
127         return pkts
128
129     def verify_capture(self, dst_if, capture):
130         """Verify captured input packet stream for defined interface.
131
132         :param VppInterface dst_if: Interface to verify captured packet stream
133                                     for.
134         :param list capture: Captured packet stream.
135         """
136         self.logger.info("Verifying capture on interface %s" % dst_if.name)
137         last_info = dict()
138         for i in self.interfaces:
139             last_info[i.sw_if_index] = None
140         is_sub_if = False
141         dst_sw_if_index = dst_if.sw_if_index
142         if hasattr(dst_if, 'parent'):
143             is_sub_if = True
144         for packet in capture:
145             if is_sub_if:
146                 # Check VLAN tags and Ethernet header
147                 packet = dst_if.remove_dot1_layer(packet)
148             self.assertTrue(Dot1Q not in packet)
149             try:
150                 ip = packet[IP]
151                 udp = packet[UDP]
152                 payload_info = self.payload_to_info(str(packet[Raw]))
153                 packet_index = payload_info.index
154                 self.assertEqual(payload_info.dst, dst_sw_if_index)
155                 self.logger.debug(
156                     "Got packet on port %s: src=%u (id=%u)" %
157                     (dst_if.name, payload_info.src, packet_index))
158                 next_info = self.get_next_packet_info_for_interface2(
159                     payload_info.src, dst_sw_if_index,
160                     last_info[payload_info.src])
161                 last_info[payload_info.src] = next_info
162                 self.assertTrue(next_info is not None)
163                 self.assertEqual(packet_index, next_info.index)
164                 saved_packet = next_info.data
165                 # Check standard fields
166                 self.assertEqual(ip.src, saved_packet[IP].src)
167                 self.assertEqual(ip.dst, saved_packet[IP].dst)
168                 self.assertEqual(udp.sport, saved_packet[UDP].sport)
169                 self.assertEqual(udp.dport, saved_packet[UDP].dport)
170             except:
171                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
172                 raise
173         for i in self.interfaces:
174             remaining_packet = self.get_next_packet_info_for_interface2(
175                 i.sw_if_index, dst_sw_if_index, last_info[i.sw_if_index])
176             self.assertTrue(remaining_packet is None,
177                             "Interface %s: Packet expected from interface %s "
178                             "didn't arrive" % (dst_if.name, i.name))
179
180     def test_fib(self):
181         """ IPv4 FIB test
182
183         Test scenario:
184
185             - Create IPv4 stream for pg0 interface
186             - Create IPv4 tagged streams for pg1's and pg2's subinterface.
187             - Send and verify received packets on each interface.
188         """
189
190         pkts = self.create_stream(self.pg0, self.pg_if_packet_sizes)
191         self.pg0.add_stream(pkts)
192
193         for i in self.sub_interfaces:
194             pkts = self.create_stream(i, self.sub_if_packet_sizes)
195             i.parent.add_stream(pkts)
196
197         self.pg_enable_capture(self.pg_interfaces)
198         self.pg_start()
199
200         pkts = self.pg0.get_capture()
201         self.verify_capture(self.pg0, pkts)
202
203         for i in self.sub_interfaces:
204             pkts = i.parent.get_capture()
205             self.verify_capture(i, pkts)
206
207
208 class TestIPv4FibCrud(VppTestCase):
209     """ FIB - add/update/delete - ip4 routes
210
211     Test scenario:
212         - add 1k,
213         - del 100,
214         - add new 1k,
215         - del 1.5k
216
217     ..note:: Python API is too slow to add many routes, needs replacement.
218     """
219
220     def config_fib_many_to_one(self, start_dest_addr, next_hop_addr, count):
221         """
222
223         :param start_dest_addr:
224         :param next_hop_addr:
225         :param count:
226         :return list: added ips with 32 prefix
227         """
228         added_ips = []
229         dest_addr = int(socket.inet_pton(socket.AF_INET,
230                                          start_dest_addr).encode('hex'),
231                         16)
232         dest_addr_len = 32
233         n_next_hop_addr = socket.inet_pton(socket.AF_INET, next_hop_addr)
234         for _ in range(count):
235             n_dest_addr = '{:08x}'.format(dest_addr).decode('hex')
236             self.vapi.ip_add_del_route(n_dest_addr, dest_addr_len,
237                                        n_next_hop_addr)
238             added_ips.append(socket.inet_ntoa(n_dest_addr))
239             dest_addr += 1
240         return added_ips
241
242     def unconfig_fib_many_to_one(self, start_dest_addr, next_hop_addr, count):
243
244         removed_ips = []
245         dest_addr = int(socket.inet_pton(socket.AF_INET,
246                                          start_dest_addr).encode('hex'),
247                         16)
248         dest_addr_len = 32
249         n_next_hop_addr = socket.inet_pton(socket.AF_INET, next_hop_addr)
250         for _ in range(count):
251             n_dest_addr = '{:08x}'.format(dest_addr).decode('hex')
252             self.vapi.ip_add_del_route(n_dest_addr, dest_addr_len,
253                                        n_next_hop_addr, is_add=0)
254             removed_ips.append(socket.inet_ntoa(n_dest_addr))
255             dest_addr += 1
256         return removed_ips
257
258     def create_stream(self, src_if, dst_if, dst_ips, count):
259         pkts = []
260
261         for _ in range(count):
262             dst_addr = random.choice(dst_ips)
263             info = self.create_packet_info(src_if, dst_if)
264             payload = self.info_to_payload(info)
265             p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
266                  IP(src=src_if.remote_ip4, dst=dst_addr) /
267                  UDP(sport=1234, dport=1234) /
268                  Raw(payload))
269             info.data = p.copy()
270             self.extend_packet(p, random.choice(self.pg_if_packet_sizes))
271             pkts.append(p)
272
273         return pkts
274
275     def _find_ip_match(self, find_in, pkt):
276         for p in find_in:
277             if self.payload_to_info(str(p[Raw])) == \
278                     self.payload_to_info(str(pkt[Raw])):
279                 if p[IP].src != pkt[IP].src:
280                     break
281                 if p[IP].dst != pkt[IP].dst:
282                     break
283                 if p[UDP].sport != pkt[UDP].sport:
284                     break
285                 if p[UDP].dport != pkt[UDP].dport:
286                     break
287                 return p
288         return None
289
290     @staticmethod
291     def _match_route_detail(route_detail, ip, address_length=32, table_id=0):
292         if route_detail.address == socket.inet_pton(socket.AF_INET, ip):
293             if route_detail.table_id != table_id:
294                 return False
295             elif route_detail.address_length != address_length:
296                 return False
297             else:
298                 return True
299         else:
300             return False
301
302     def verify_capture(self, dst_interface, received_pkts, expected_pkts):
303         self.assertEqual(len(received_pkts), len(expected_pkts))
304         to_verify = list(expected_pkts)
305         for p in received_pkts:
306             self.assertEqual(p.src, dst_interface.local_mac)
307             self.assertEqual(p.dst, dst_interface.remote_mac)
308             x = self._find_ip_match(to_verify, p)
309             to_verify.remove(x)
310         self.assertListEqual(to_verify, [])
311
312     def verify_route_dump(self, fib_dump, ips):
313
314         def _ip_in_route_dump(ip, fib_dump):
315             return next((route for route in fib_dump
316                          if self._match_route_detail(route, ip)),
317                         False)
318
319         for ip in ips:
320             self.assertTrue(_ip_in_route_dump(ip, fib_dump),
321                             'IP {} is not in fib dump.'.format(ip))
322
323     def verify_not_in_route_dump(self, fib_dump, ips):
324
325         def _ip_in_route_dump(ip, fib_dump):
326             return next((route for route in fib_dump
327                          if self._match_route_detail(route, ip)),
328                         False)
329
330         for ip in ips:
331             self.assertFalse(_ip_in_route_dump(ip, fib_dump),
332                              'IP {} is in fib dump.'.format(ip))
333
334     @classmethod
335     def setUpClass(cls):
336         """
337         #. Create and initialize 3 pg interfaces.
338         #. initialize class attributes configured_routes and deleted_routes
339            to store information between tests.
340         """
341         super(TestIPv4FibCrud, cls).setUpClass()
342
343         try:
344             # create 3 pg interfaces
345             cls.create_pg_interfaces(range(3))
346
347             cls.interfaces = list(cls.pg_interfaces)
348
349             # setup all interfaces
350             for i in cls.interfaces:
351                 i.admin_up()
352                 i.config_ip4()
353                 i.resolve_arp()
354
355             cls.configured_routes = []
356             cls.deleted_routes = []
357             cls.pg_if_packet_sizes = [64, 512, 1518, 9018]
358
359         except Exception:
360             super(TestIPv4FibCrud, cls).tearDownClass()
361             raise
362
363     def setUp(self):
364         super(TestIPv4FibCrud, self).setUp()
365         self.reset_packet_infos()
366
367     def test_1_add_routes(self):
368         """ Add 1k routes
369
370         - add 100 routes check with traffic script.
371         """
372         # config 1M FIB entries
373         self.configured_routes.extend(self.config_fib_many_to_one(
374             "10.0.0.0", self.pg0.remote_ip4, 100))
375
376         fib_dump = self.vapi.ip_fib_dump()
377         self.verify_route_dump(fib_dump, self.configured_routes)
378
379         self.stream_1 = self.create_stream(
380             self.pg1, self.pg0, self.configured_routes, 100)
381         self.stream_2 = self.create_stream(
382             self.pg2, self.pg0, self.configured_routes, 100)
383         self.pg1.add_stream(self.stream_1)
384         self.pg2.add_stream(self.stream_2)
385
386         self.pg_enable_capture(self.pg_interfaces)
387         self.pg_start()
388
389         pkts = self.pg0.get_capture(len(self.stream_1) + len(self.stream_2))
390         self.verify_capture(self.pg0, pkts, self.stream_1 + self.stream_2)
391
392     def test_2_del_routes(self):
393         """ Delete 100 routes
394
395         - delete 10 routes check with traffic script.
396         """
397         self.deleted_routes.extend(self.unconfig_fib_many_to_one(
398             "10.0.0.10", self.pg0.remote_ip4, 10))
399         for x in self.deleted_routes:
400             self.configured_routes.remove(x)
401
402         fib_dump = self.vapi.ip_fib_dump()
403         self.verify_route_dump(fib_dump, self.configured_routes)
404
405         self.stream_1 = self.create_stream(
406             self.pg1, self.pg0, self.configured_routes, 100)
407         self.stream_2 = self.create_stream(
408             self.pg2, self.pg0, self.configured_routes, 100)
409         self.stream_3 = self.create_stream(
410             self.pg1, self.pg0, self.deleted_routes, 100)
411         self.stream_4 = self.create_stream(
412             self.pg2, self.pg0, self.deleted_routes, 100)
413         self.pg1.add_stream(self.stream_1 + self.stream_3)
414         self.pg2.add_stream(self.stream_2 + self.stream_4)
415         self.pg_enable_capture(self.pg_interfaces)
416         self.pg_start()
417
418         pkts = self.pg0.get_capture(len(self.stream_1) + len(self.stream_2))
419         self.verify_capture(self.pg0, pkts, self.stream_1 + self.stream_2)
420
421     def test_3_add_new_routes(self):
422         """ Add 1k routes
423
424         - re-add 5 routes check with traffic script.
425         - add 100 routes check with traffic script.
426         """
427         tmp = self.config_fib_many_to_one(
428             "10.0.0.10", self.pg0.remote_ip4, 5)
429         self.configured_routes.extend(tmp)
430         for x in tmp:
431             self.deleted_routes.remove(x)
432
433         self.configured_routes.extend(self.config_fib_many_to_one(
434             "10.0.1.0", self.pg0.remote_ip4, 100))
435
436         fib_dump = self.vapi.ip_fib_dump()
437         self.verify_route_dump(fib_dump, self.configured_routes)
438
439         self.stream_1 = self.create_stream(
440             self.pg1, self.pg0, self.configured_routes, 300)
441         self.stream_2 = self.create_stream(
442             self.pg2, self.pg0, self.configured_routes, 300)
443         self.stream_3 = self.create_stream(
444             self.pg1, self.pg0, self.deleted_routes, 100)
445         self.stream_4 = self.create_stream(
446             self.pg2, self.pg0, self.deleted_routes, 100)
447
448         self.pg1.add_stream(self.stream_1 + self.stream_3)
449         self.pg2.add_stream(self.stream_2 + self.stream_4)
450         self.pg_enable_capture(self.pg_interfaces)
451         self.pg_start()
452
453         pkts = self.pg0.get_capture(len(self.stream_1) + len(self.stream_2))
454         self.verify_capture(self.pg0, pkts, self.stream_1 + self.stream_2)
455
456     def test_4_del_routes(self):
457         """ Delete 1.5k routes
458
459         - delete 5 routes check with traffic script.
460         - add 100 routes check with traffic script.
461         """
462         self.deleted_routes.extend(self.unconfig_fib_many_to_one(
463             "10.0.0.0", self.pg0.remote_ip4, 15))
464         self.deleted_routes.extend(self.unconfig_fib_many_to_one(
465             "10.0.0.20", self.pg0.remote_ip4, 85))
466         self.deleted_routes.extend(self.unconfig_fib_many_to_one(
467             "10.0.1.0", self.pg0.remote_ip4, 100))
468         fib_dump = self.vapi.ip_fib_dump()
469         self.verify_not_in_route_dump(fib_dump, self.deleted_routes)
470
471
472 class TestIPNull(VppTestCase):
473     """ IPv4 routes via NULL """
474
475     def setUp(self):
476         super(TestIPNull, self).setUp()
477
478         # create 2 pg interfaces
479         self.create_pg_interfaces(range(1))
480
481         for i in self.pg_interfaces:
482             i.admin_up()
483             i.config_ip4()
484             i.resolve_arp()
485
486     def tearDown(self):
487         super(TestIPNull, self).tearDown()
488         for i in self.pg_interfaces:
489             i.unconfig_ip4()
490             i.admin_down()
491
492     def test_ip_null(self):
493         """ IP NULL route """
494
495         #
496         # A route via IP NULL that will reply with ICMP unreachables
497         #
498         ip_unreach = VppIpRoute(self, "10.0.0.1", 32, [], is_unreach=1)
499         ip_unreach.add_vpp_config()
500
501         p_unreach = (Ether(src=self.pg0.remote_mac,
502                            dst=self.pg0.local_mac) /
503                      IP(src=self.pg0.remote_ip4, dst="10.0.0.1") /
504                      UDP(sport=1234, dport=1234) /
505                      Raw('\xa5' * 100))
506
507         self.pg0.add_stream(p_unreach)
508         self.pg_enable_capture(self.pg_interfaces)
509         self.pg_start()
510
511         rx = self.pg0.get_capture(1)
512         rx = rx[0]
513         icmp = rx[ICMP]
514
515         self.assertEqual(icmptypes[icmp.type], "dest-unreach")
516         self.assertEqual(icmpcodes[icmp.type][icmp.code], "host-unreachable")
517         self.assertEqual(icmp.src, self.pg0.remote_ip4)
518         self.assertEqual(icmp.dst, "10.0.0.1")
519
520         #
521         # ICMP replies are rate limited. so sit and spin.
522         #
523         self.sleep(1)
524
525         #
526         # A route via IP NULL that will reply with ICMP prohibited
527         #
528         ip_prohibit = VppIpRoute(self, "10.0.0.2", 32, [], is_prohibit=1)
529         ip_prohibit.add_vpp_config()
530
531         p_prohibit = (Ether(src=self.pg0.remote_mac,
532                             dst=self.pg0.local_mac) /
533                       IP(src=self.pg0.remote_ip4, dst="10.0.0.2") /
534                       UDP(sport=1234, dport=1234) /
535                       Raw('\xa5' * 100))
536
537         self.pg0.add_stream(p_prohibit)
538         self.pg_enable_capture(self.pg_interfaces)
539         self.pg_start()
540
541         rx = self.pg0.get_capture(1)
542
543         rx = rx[0]
544         icmp = rx[ICMP]
545
546         self.assertEqual(icmptypes[icmp.type], "dest-unreach")
547         self.assertEqual(icmpcodes[icmp.type][icmp.code], "host-prohibited")
548         self.assertEqual(icmp.src, self.pg0.remote_ip4)
549         self.assertEqual(icmp.dst, "10.0.0.2")
550
551
552 class TestIPDisabled(VppTestCase):
553     """ IPv4 disabled """
554
555     def setUp(self):
556         super(TestIPDisabled, self).setUp()
557
558         # create 2 pg interfaces
559         self.create_pg_interfaces(range(2))
560
561         # PG0 is IP enalbed
562         self.pg0.admin_up()
563         self.pg0.config_ip4()
564         self.pg0.resolve_arp()
565
566         # PG 1 is not IP enabled
567         self.pg1.admin_up()
568
569     def tearDown(self):
570         super(TestIPDisabled, self).tearDown()
571         for i in self.pg_interfaces:
572             i.unconfig_ip4()
573             i.admin_down()
574
575     def test_ip_disabled(self):
576         """ IP Disabled """
577
578         #
579         # An (S,G).
580         # one accepting interface, pg0, 2 forwarding interfaces
581         #
582         route_232_1_1_1 = VppIpMRoute(
583             self,
584             "0.0.0.0",
585             "232.1.1.1", 32,
586             MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
587             [VppMRoutePath(self.pg1.sw_if_index,
588                            MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
589              VppMRoutePath(self.pg0.sw_if_index,
590                            MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
591         route_232_1_1_1.add_vpp_config()
592
593         pu = (Ether(src=self.pg1.remote_mac,
594                     dst=self.pg1.local_mac) /
595               IP(src="10.10.10.10", dst=self.pg0.remote_ip4) /
596               UDP(sport=1234, dport=1234) /
597               Raw('\xa5' * 100))
598         pm = (Ether(src=self.pg1.remote_mac,
599                     dst=self.pg1.local_mac) /
600               IP(src="10.10.10.10", dst="232.1.1.1") /
601               UDP(sport=1234, dport=1234) /
602               Raw('\xa5' * 100))
603
604         #
605         # PG1 does not forward IP traffic
606         #
607         self.send_and_assert_no_replies(self.pg1, pu, "IP disabled")
608         self.send_and_assert_no_replies(self.pg1, pm, "IP disabled")
609
610         #
611         # IP enable PG1
612         #
613         self.pg1.config_ip4()
614
615         #
616         # Now we get packets through
617         #
618         self.pg1.add_stream(pu)
619         self.pg_enable_capture(self.pg_interfaces)
620         self.pg_start()
621         rx = self.pg0.get_capture(1)
622
623         self.pg1.add_stream(pm)
624         self.pg_enable_capture(self.pg_interfaces)
625         self.pg_start()
626         rx = self.pg0.get_capture(1)
627
628         #
629         # Disable PG1
630         #
631         self.pg1.unconfig_ip4()
632
633         #
634         # PG1 does not forward IP traffic
635         #
636         self.send_and_assert_no_replies(self.pg1, pu, "IP disabled")
637         self.send_and_assert_no_replies(self.pg1, pm, "IP disabled")
638
639
640 class TestIPSubNets(VppTestCase):
641     """ IPv4 Subnets """
642
643     def setUp(self):
644         super(TestIPSubNets, self).setUp()
645
646         # create a 2 pg interfaces
647         self.create_pg_interfaces(range(2))
648
649         # pg0 we will use to experiemnt
650         self.pg0.admin_up()
651
652         # pg1 is setup normally
653         self.pg1.admin_up()
654         self.pg1.config_ip4()
655         self.pg1.resolve_arp()
656
657     def tearDown(self):
658         super(TestIPSubNets, self).tearDown()
659         for i in self.pg_interfaces:
660             i.admin_down()
661
662     def test_ip_sub_nets(self):
663         """ IP Sub Nets """
664
665         #
666         # Configure a covering route to forward so we know
667         # when we are dropping
668         #
669         cover_route = VppIpRoute(self, "10.0.0.0", 8,
670                                  [VppRoutePath(self.pg1.remote_ip4,
671                                                self.pg1.sw_if_index)])
672         cover_route.add_vpp_config()
673
674         p = (Ether(src=self.pg1.remote_mac,
675                    dst=self.pg1.local_mac) /
676              IP(dst="10.10.10.10", src=self.pg0.local_ip4) /
677              UDP(sport=1234, dport=1234) /
678              Raw('\xa5' * 100))
679
680         self.pg1.add_stream(p)
681         self.pg_enable_capture(self.pg_interfaces)
682         self.pg_start()
683         rx = self.pg1.get_capture(1)
684
685         #
686         # Configure some non-/24 subnets on an IP interface
687         #
688         ip_addr_n = socket.inet_pton(socket.AF_INET, "10.10.10.10")
689
690         self.vapi.sw_interface_add_del_address(self.pg0.sw_if_index,
691                                                ip_addr_n,
692                                                16)
693
694         pn = (Ether(src=self.pg1.remote_mac,
695                     dst=self.pg1.local_mac) /
696               IP(dst="10.10.0.0", src=self.pg0.local_ip4) /
697               UDP(sport=1234, dport=1234) /
698               Raw('\xa5' * 100))
699         pb = (Ether(src=self.pg1.remote_mac,
700                     dst=self.pg1.local_mac) /
701               IP(dst="10.10.255.255", src=self.pg0.local_ip4) /
702               UDP(sport=1234, dport=1234) /
703               Raw('\xa5' * 100))
704
705         self.send_and_assert_no_replies(self.pg1, pn, "IP Network address")
706         self.send_and_assert_no_replies(self.pg1, pb, "IP Broadcast address")
707
708         # remove the sub-net and we are forwarding via the cover again
709         self.vapi.sw_interface_add_del_address(self.pg0.sw_if_index,
710                                                ip_addr_n,
711                                                16,
712                                                is_add=0)
713         self.pg1.add_stream(pn)
714         self.pg_enable_capture(self.pg_interfaces)
715         self.pg_start()
716         rx = self.pg1.get_capture(1)
717         self.pg1.add_stream(pb)
718         self.pg_enable_capture(self.pg_interfaces)
719         self.pg_start()
720         rx = self.pg1.get_capture(1)
721
722         #
723         # A /31 is a special case where the 'other-side' is an attached host
724         # packets to that peer generate ARP requests
725         #
726         ip_addr_n = socket.inet_pton(socket.AF_INET, "10.10.10.10")
727
728         self.vapi.sw_interface_add_del_address(self.pg0.sw_if_index,
729                                                ip_addr_n,
730                                                31)
731
732         pn = (Ether(src=self.pg1.remote_mac,
733                     dst=self.pg1.local_mac) /
734               IP(dst="10.10.10.11", src=self.pg0.local_ip4) /
735               UDP(sport=1234, dport=1234) /
736               Raw('\xa5' * 100))
737
738         self.pg1.add_stream(pn)
739         self.pg_enable_capture(self.pg_interfaces)
740         self.pg_start()
741         rx = self.pg0.get_capture(1)
742         rx[ARP]
743
744         # remove the sub-net and we are forwarding via the cover again
745         self.vapi.sw_interface_add_del_address(self.pg0.sw_if_index,
746                                                ip_addr_n,
747                                                31,
748                                                is_add=0)
749         self.pg1.add_stream(pn)
750         self.pg_enable_capture(self.pg_interfaces)
751         self.pg_start()
752         rx = self.pg1.get_capture(1)
753
754
755 class TestIPLoadBalance(VppTestCase):
756     """ IPv4 Load-Balancing """
757
758     def setUp(self):
759         super(TestIPLoadBalance, self).setUp()
760
761         self.create_pg_interfaces(range(5))
762         mpls_tbl = VppMplsTable(self, 0)
763         mpls_tbl.add_vpp_config()
764
765         for i in self.pg_interfaces:
766             i.admin_up()
767             i.config_ip4()
768             i.resolve_arp()
769             i.enable_mpls()
770
771     def tearDown(self):
772         for i in self.pg_interfaces:
773             i.disable_mpls()
774             i.unconfig_ip4()
775             i.admin_down()
776         super(TestIPLoadBalance, self).tearDown()
777
778     def send_and_expect_load_balancing(self, input, pkts, outputs):
779         input.add_stream(pkts)
780         self.pg_enable_capture(self.pg_interfaces)
781         self.pg_start()
782         for oo in outputs:
783             rx = oo._get_capture(1)
784             self.assertNotEqual(0, len(rx))
785
786     def send_and_expect_one_itf(self, input, pkts, itf):
787         input.add_stream(pkts)
788         self.pg_enable_capture(self.pg_interfaces)
789         self.pg_start()
790         rx = itf.get_capture(len(pkts))
791
792     def test_ip_load_balance(self):
793         """ IP Load-Balancing """
794
795         #
796         # An array of packets that differ only in the destination port
797         #
798         port_ip_pkts = []
799         port_mpls_pkts = []
800
801         #
802         # An array of packets that differ only in the source address
803         #
804         src_ip_pkts = []
805         src_mpls_pkts = []
806
807         for ii in range(65):
808             port_ip_hdr = (IP(dst="10.0.0.1", src="20.0.0.1") /
809                            UDP(sport=1234, dport=1234 + ii) /
810                            Raw('\xa5' * 100))
811             port_ip_pkts.append((Ether(src=self.pg0.remote_mac,
812                                        dst=self.pg0.local_mac) /
813                                  port_ip_hdr))
814             port_mpls_pkts.append((Ether(src=self.pg0.remote_mac,
815                                          dst=self.pg0.local_mac) /
816                                    MPLS(label=66, ttl=2) /
817                                    port_ip_hdr))
818
819             src_ip_hdr = (IP(dst="10.0.0.1", src="20.0.0.%d" % ii) /
820                           UDP(sport=1234, dport=1234) /
821                           Raw('\xa5' * 100))
822             src_ip_pkts.append((Ether(src=self.pg0.remote_mac,
823                                       dst=self.pg0.local_mac) /
824                                 src_ip_hdr))
825             src_mpls_pkts.append((Ether(src=self.pg0.remote_mac,
826                                         dst=self.pg0.local_mac) /
827                                   MPLS(label=66, ttl=2) /
828                                   src_ip_hdr))
829
830         route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
831                                     [VppRoutePath(self.pg1.remote_ip4,
832                                                   self.pg1.sw_if_index),
833                                      VppRoutePath(self.pg2.remote_ip4,
834                                                   self.pg2.sw_if_index)])
835         route_10_0_0_1.add_vpp_config()
836
837         binding = VppMplsIpBind(self, 66, "10.0.0.1", 32)
838         binding.add_vpp_config()
839
840         #
841         # inject the packet on pg0 - expect load-balancing across the 2 paths
842         #  - since the default hash config is to use IP src,dst and port
843         #    src,dst
844         # We are not going to ensure equal amounts of packets across each link,
845         # since the hash algorithm is statistical and therefore this can never
846         # be guaranteed. But wuth 64 different packets we do expect some
847         # balancing. So instead just ensure there is traffic on each link.
848         #
849         self.send_and_expect_load_balancing(self.pg0, port_ip_pkts,
850                                             [self.pg1, self.pg2])
851         self.send_and_expect_load_balancing(self.pg0, src_ip_pkts,
852                                             [self.pg1, self.pg2])
853         self.send_and_expect_load_balancing(self.pg0, port_mpls_pkts,
854                                             [self.pg1, self.pg2])
855         self.send_and_expect_load_balancing(self.pg0, src_mpls_pkts,
856                                             [self.pg1, self.pg2])
857
858         #
859         # change the flow hash config so it's only IP src,dst
860         #  - now only the stream with differing source address will
861         #    load-balance
862         #
863         self.vapi.set_ip_flow_hash(0, src=1, dst=1, sport=0, dport=0)
864
865         self.send_and_expect_load_balancing(self.pg0, src_ip_pkts,
866                                             [self.pg1, self.pg2])
867         self.send_and_expect_load_balancing(self.pg0, src_mpls_pkts,
868                                             [self.pg1, self.pg2])
869
870         self.send_and_expect_one_itf(self.pg0, port_ip_pkts, self.pg2)
871
872         #
873         # change the flow hash config back to defaults
874         #
875         self.vapi.set_ip_flow_hash(0, src=1, dst=1, sport=1, dport=1)
876
877         #
878         # Recursive prefixes
879         #  - testing that 2 stages of load-balancing occurs and there is no
880         #    polarisation (i.e. only 2 of 4 paths are used)
881         #
882         port_pkts = []
883         src_pkts = []
884
885         for ii in range(257):
886             port_pkts.append((Ether(src=self.pg0.remote_mac,
887                                     dst=self.pg0.local_mac) /
888                               IP(dst="1.1.1.1", src="20.0.0.1") /
889                               UDP(sport=1234, dport=1234 + ii) /
890                               Raw('\xa5' * 100)))
891             src_pkts.append((Ether(src=self.pg0.remote_mac,
892                                    dst=self.pg0.local_mac) /
893                              IP(dst="1.1.1.1", src="20.0.0.%d" % ii) /
894                              UDP(sport=1234, dport=1234) /
895                              Raw('\xa5' * 100)))
896
897         route_10_0_0_2 = VppIpRoute(self, "10.0.0.2", 32,
898                                     [VppRoutePath(self.pg3.remote_ip4,
899                                                   self.pg3.sw_if_index),
900                                      VppRoutePath(self.pg4.remote_ip4,
901                                                   self.pg4.sw_if_index)])
902         route_10_0_0_2.add_vpp_config()
903
904         route_1_1_1_1 = VppIpRoute(self, "1.1.1.1", 32,
905                                    [VppRoutePath("10.0.0.2", 0xffffffff),
906                                     VppRoutePath("10.0.0.1", 0xffffffff)])
907         route_1_1_1_1.add_vpp_config()
908
909         #
910         # inject the packet on pg0 - expect load-balancing across all 4 paths
911         #
912         self.vapi.cli("clear trace")
913         self.send_and_expect_load_balancing(self.pg0, port_pkts,
914                                             [self.pg1, self.pg2,
915                                              self.pg3, self.pg4])
916         self.send_and_expect_load_balancing(self.pg0, src_pkts,
917                                             [self.pg1, self.pg2,
918                                              self.pg3, self.pg4])
919
920         #
921         # Recursive prefixes
922         #  - testing that 2 stages of load-balancing, no choices
923         #
924         port_pkts = []
925
926         for ii in range(257):
927             port_pkts.append((Ether(src=self.pg0.remote_mac,
928                                     dst=self.pg0.local_mac) /
929                               IP(dst="1.1.1.2", src="20.0.0.2") /
930                               UDP(sport=1234, dport=1234 + ii) /
931                               Raw('\xa5' * 100)))
932
933         route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
934                                     [VppRoutePath(self.pg3.remote_ip4,
935                                                   self.pg3.sw_if_index)])
936         route_10_0_0_3.add_vpp_config()
937
938         route_1_1_1_2 = VppIpRoute(self, "1.1.1.2", 32,
939                                    [VppRoutePath("10.0.0.3", 0xffffffff)])
940         route_1_1_1_2.add_vpp_config()
941
942         #
943         # inject the packet on pg0 - expect load-balancing across all 4 paths
944         #
945         self.vapi.cli("clear trace")
946         self.send_and_expect_one_itf(self.pg0, port_pkts, self.pg3)
947
948
949 class TestIPVlan0(VppTestCase):
950     """ IPv4 VLAN-0 """
951
952     def setUp(self):
953         super(TestIPVlan0, self).setUp()
954
955         self.create_pg_interfaces(range(2))
956         mpls_tbl = VppMplsTable(self, 0)
957         mpls_tbl.add_vpp_config()
958
959         for i in self.pg_interfaces:
960             i.admin_up()
961             i.config_ip4()
962             i.resolve_arp()
963             i.enable_mpls()
964
965     def tearDown(self):
966         for i in self.pg_interfaces:
967             i.disable_mpls()
968             i.unconfig_ip4()
969             i.admin_down()
970         super(TestIPVlan0, self).tearDown()
971
972     def test_ip_vlan_0(self):
973         """ IP VLAN-0 """
974
975         pkts = (Ether(src=self.pg0.remote_mac,
976                       dst=self.pg0.local_mac) /
977                 Dot1Q(vlan=0) /
978                 IP(dst=self.pg1.remote_ip4,
979                    src=self.pg0.remote_ip4) /
980                 UDP(sport=1234, dport=1234) /
981                 Raw('\xa5' * 100)) * 65
982
983         #
984         # Expect that packets sent on VLAN-0 are forwarded on the
985         # main interface.
986         #
987         self.send_and_expect(self.pg0, pkts, self.pg1)
988
989
990 class TestIPPunt(VppTestCase):
991     """ IPv4 Punt Police/Redirect """
992
993     def setUp(self):
994         super(TestIPPunt, self).setUp()
995
996         self.create_pg_interfaces(range(2))
997
998         for i in self.pg_interfaces:
999             i.admin_up()
1000             i.config_ip4()
1001             i.resolve_arp()
1002
1003     def tearDown(self):
1004         super(TestIPPunt, self).tearDown()
1005         for i in self.pg_interfaces:
1006             i.unconfig_ip4()
1007             i.admin_down()
1008
1009     def test_ip_punt(self):
1010         """ IP punt police and redirect """
1011
1012         p = (Ether(src=self.pg0.remote_mac,
1013                    dst=self.pg0.local_mac) /
1014              IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
1015              TCP(sport=1234, dport=1234) /
1016              Raw('\xa5' * 100))
1017
1018         pkts = p * 1025
1019
1020         #
1021         # Configure a punt redirect via pg1.
1022         #
1023         nh_addr = socket.inet_pton(socket.AF_INET,
1024                                    self.pg1.remote_ip4)
1025         self.vapi.ip_punt_redirect(self.pg0.sw_if_index,
1026                                    self.pg1.sw_if_index,
1027                                    nh_addr)
1028
1029         self.send_and_expect(self.pg0, pkts, self.pg1)
1030
1031         #
1032         # add a policer
1033         #
1034         policer = self.vapi.policer_add_del("ip4-punt", 400, 0, 10, 0,
1035                                             rate_type=1)
1036         self.vapi.ip_punt_police(policer.policer_index)
1037
1038         self.vapi.cli("clear trace")
1039         self.pg0.add_stream(pkts)
1040         self.pg_enable_capture(self.pg_interfaces)
1041         self.pg_start()
1042
1043         #
1044         # the number of packet recieved should be greater than 0,
1045         # but not equal to the number sent, since some were policed
1046         #
1047         rx = self.pg1._get_capture(1)
1048         self.assertTrue(len(rx) > 0)
1049         self.assertTrue(len(rx) < len(pkts))
1050
1051         #
1052         # remove the poilcer. back to full rx
1053         #
1054         self.vapi.ip_punt_police(policer.policer_index, is_add=0)
1055         self.vapi.policer_add_del("ip4-punt", 400, 0, 10, 0,
1056                                   rate_type=1, is_add=0)
1057         self.send_and_expect(self.pg0, pkts, self.pg1)
1058
1059         #
1060         # remove the redirect. expect full drop.
1061         #
1062         self.vapi.ip_punt_redirect(self.pg0.sw_if_index,
1063                                    self.pg1.sw_if_index,
1064                                    nh_addr,
1065                                    is_add=0)
1066         self.send_and_assert_no_replies(self.pg0, pkts,
1067                                         "IP no punt config")
1068
1069         #
1070         # Add a redirect that is not input port selective
1071         #
1072         self.vapi.ip_punt_redirect(0xffffffff,
1073                                    self.pg1.sw_if_index,
1074                                    nh_addr)
1075         self.send_and_expect(self.pg0, pkts, self.pg1)
1076
1077         self.vapi.ip_punt_redirect(0xffffffff,
1078                                    self.pg1.sw_if_index,
1079                                    nh_addr,
1080                                    is_add=0)
1081
1082
1083 class TestIPDeag(VppTestCase):
1084     """ IPv4 Deaggregate Routes """
1085
1086     def setUp(self):
1087         super(TestIPDeag, self).setUp()
1088
1089         self.create_pg_interfaces(range(3))
1090
1091         for i in self.pg_interfaces:
1092             i.admin_up()
1093             i.config_ip4()
1094             i.resolve_arp()
1095
1096     def tearDown(self):
1097         super(TestIPDeag, self).tearDown()
1098         for i in self.pg_interfaces:
1099             i.unconfig_ip4()
1100             i.admin_down()
1101
1102     def test_ip_deag(self):
1103         """ IP Deag Routes """
1104
1105         #
1106         # Create a table to be used for:
1107         #  1 - another destination address lookup
1108         #  2 - a source address lookup
1109         #
1110         table_dst = VppIpTable(self, 1)
1111         table_src = VppIpTable(self, 2)
1112         table_dst.add_vpp_config()
1113         table_src.add_vpp_config()
1114
1115         #
1116         # Add a route in the default table to point to a deag/
1117         # second lookup in each of these tables
1118         #
1119         route_to_dst = VppIpRoute(self, "1.1.1.1", 32,
1120                                   [VppRoutePath("0.0.0.0",
1121                                                 0xffffffff,
1122                                                 nh_table_id=1)])
1123         route_to_src = VppIpRoute(self, "1.1.1.2", 32,
1124                                   [VppRoutePath("0.0.0.0",
1125                                                 0xffffffff,
1126                                                 nh_table_id=2,
1127                                                 is_source_lookup=1)])
1128         route_to_dst.add_vpp_config()
1129         route_to_src.add_vpp_config()
1130
1131         #
1132         # packets to these destination are dropped, since they'll
1133         # hit the respective default routes in the second table
1134         #
1135         p_dst = (Ether(src=self.pg0.remote_mac,
1136                        dst=self.pg0.local_mac) /
1137                  IP(src="5.5.5.5", dst="1.1.1.1") /
1138                  TCP(sport=1234, dport=1234) /
1139                  Raw('\xa5' * 100))
1140         p_src = (Ether(src=self.pg0.remote_mac,
1141                        dst=self.pg0.local_mac) /
1142                  IP(src="2.2.2.2", dst="1.1.1.2") /
1143                  TCP(sport=1234, dport=1234) /
1144                  Raw('\xa5' * 100))
1145         pkts_dst = p_dst * 257
1146         pkts_src = p_src * 257
1147
1148         self.send_and_assert_no_replies(self.pg0, pkts_dst,
1149                                         "IP in dst table")
1150         self.send_and_assert_no_replies(self.pg0, pkts_src,
1151                                         "IP in src table")
1152
1153         #
1154         # add a route in the dst table to forward via pg1
1155         #
1156         route_in_dst = VppIpRoute(self, "1.1.1.1", 32,
1157                                   [VppRoutePath(self.pg1.remote_ip4,
1158                                                 self.pg1.sw_if_index)],
1159                                   table_id=1)
1160         route_in_dst.add_vpp_config()
1161         self.send_and_expect(self.pg0, pkts_dst, self.pg1)
1162
1163         #
1164         # add a route in the src table to forward via pg2
1165         #
1166         route_in_src = VppIpRoute(self, "2.2.2.2", 32,
1167                                   [VppRoutePath(self.pg2.remote_ip4,
1168                                                 self.pg2.sw_if_index)],
1169                                   table_id=2)
1170         route_in_src.add_vpp_config()
1171         self.send_and_expect(self.pg0, pkts_src, self.pg2)
1172
1173
1174 class TestIPInput(VppTestCase):
1175     """ IPv4 Input Exceptions """
1176
1177     def setUp(self):
1178         super(TestIPInput, self).setUp()
1179
1180         self.create_pg_interfaces(range(2))
1181
1182         for i in self.pg_interfaces:
1183             i.admin_up()
1184             i.config_ip4()
1185             i.resolve_arp()
1186
1187     def tearDown(self):
1188         super(TestIPInput, self).tearDown()
1189         for i in self.pg_interfaces:
1190             i.unconfig_ip4()
1191             i.admin_down()
1192
1193     def test_ip_input(self):
1194         """ IP Input Exceptions """
1195
1196         # i can't find a way in scapy to construct an IP packet
1197         # with a length less than the IP header length
1198
1199         #
1200         # Packet too short - this is forwarded
1201         #
1202         p_short = (Ether(src=self.pg0.remote_mac,
1203                          dst=self.pg0.local_mac) /
1204                    IP(src=self.pg0.remote_ip4,
1205                       dst=self.pg1.remote_ip4,
1206                       len=40) /
1207                    UDP(sport=1234, dport=1234) /
1208                    Raw('\xa5' * 100))
1209
1210         rx = self.send_and_expect(self.pg0, p_short * 65, self.pg1)
1211
1212         #
1213         # Packet too long - this is dropped
1214         #
1215         p_long = (Ether(src=self.pg0.remote_mac,
1216                         dst=self.pg0.local_mac) /
1217                   IP(src=self.pg0.remote_ip4,
1218                      dst=self.pg1.remote_ip4,
1219                      len=400) /
1220                   UDP(sport=1234, dport=1234) /
1221                   Raw('\xa5' * 100))
1222
1223         rx = self.send_and_assert_no_replies(self.pg0, p_long * 65,
1224                                              "too long")
1225
1226         #
1227         # bad chksum - this is dropped
1228         #
1229         p_chksum = (Ether(src=self.pg0.remote_mac,
1230                           dst=self.pg0.local_mac) /
1231                     IP(src=self.pg0.remote_ip4,
1232                        dst=self.pg1.remote_ip4,
1233                        chksum=400) /
1234                     UDP(sport=1234, dport=1234) /
1235                     Raw('\xa5' * 100))
1236
1237         rx = self.send_and_assert_no_replies(self.pg0, p_chksum * 65,
1238                                              "bad checksum")
1239
1240         #
1241         # bad version - this is dropped
1242         #
1243         p_ver = (Ether(src=self.pg0.remote_mac,
1244                        dst=self.pg0.local_mac) /
1245                  IP(src=self.pg0.remote_ip4,
1246                     dst=self.pg1.remote_ip4,
1247                     version=3) /
1248                  UDP(sport=1234, dport=1234) /
1249                  Raw('\xa5' * 100))
1250
1251         rx = self.send_and_assert_no_replies(self.pg0, p_ver * 65,
1252                                              "funky version")
1253
1254         #
1255         # fragment offset 1 - this is dropped
1256         #
1257         p_frag = (Ether(src=self.pg0.remote_mac,
1258                         dst=self.pg0.local_mac) /
1259                   IP(src=self.pg0.remote_ip4,
1260                      dst=self.pg1.remote_ip4,
1261                      frag=1) /
1262                   UDP(sport=1234, dport=1234) /
1263                   Raw('\xa5' * 100))
1264
1265         rx = self.send_and_assert_no_replies(self.pg0, p_frag * 65,
1266                                              "frag offset")
1267
1268         #
1269         # TTL expired packet
1270         #
1271         p_ttl = (Ether(src=self.pg0.remote_mac,
1272                        dst=self.pg0.local_mac) /
1273                  IP(src=self.pg0.remote_ip4,
1274                     dst=self.pg1.remote_ip4,
1275                     ttl=1) /
1276                  UDP(sport=1234, dport=1234) /
1277                  Raw('\xa5' * 100))
1278
1279         rx = self.send_and_expect(self.pg0, p_ttl * 65, self.pg0)
1280
1281         rx = rx[0]
1282         icmp = rx[ICMP]
1283
1284         self.assertEqual(icmptypes[icmp.type], "time-exceeded")
1285         self.assertEqual(icmpcodes[icmp.type][icmp.code],
1286                          "ttl-zero-during-transit")
1287         self.assertEqual(icmp.src, self.pg0.remote_ip4)
1288         self.assertEqual(icmp.dst, self.pg1.remote_ip4)
1289
1290         #
1291         # MTU exceeded
1292         #
1293         p_mtu = (Ether(src=self.pg0.remote_mac,
1294                        dst=self.pg0.local_mac) /
1295                  IP(src=self.pg0.remote_ip4,
1296                     dst=self.pg1.remote_ip4,
1297                     ttl=10) /
1298                  UDP(sport=1234, dport=1234) /
1299                  Raw('\xa5' * 2000))
1300
1301         self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, 1500)
1302
1303         rx = self.send_and_expect(self.pg0, p_mtu * 65, self.pg0)
1304         rx = rx[0]
1305         icmp = rx[ICMP]
1306
1307         self.assertEqual(icmptypes[icmp.type], "dest-unreach")
1308         self.assertEqual(icmpcodes[icmp.type][icmp.code],
1309                          "fragmentation-needed")
1310         self.assertEqual(icmp.src, self.pg0.remote_ip4)
1311         self.assertEqual(icmp.dst, self.pg1.remote_ip4)
1312
1313         self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, 2500)
1314         rx = self.send_and_expect(self.pg0, p_mtu * 65, self.pg1)
1315
1316
1317 if __name__ == '__main__':
1318     unittest.main(testRunner=VppTestRunner)