7 from framework import VppTestCase, VppTestRunner
8 from vpp_sub_interface import VppSubInterface, VppDot1QSubint, VppDot1ADSubint
9 from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpMRoute, \
10 VppMRoutePath, MRouteItfFlags, MRouteEntryFlags, VppMplsIpBind, \
11 VppMplsTable, VppIpTable, VppIpAddress
13 from scapy.packet import Raw
14 from scapy.layers.l2 import Ether, Dot1Q, ARP
15 from scapy.layers.inet import IP, UDP, TCP, ICMP, icmptypes, icmpcodes
17 from scapy.contrib.mpls import MPLS
20 class TestIPv4(VppTestCase):
21 """ IPv4 Test Case """
25 Perform test setup before test case.
28 - create 3 pg interfaces
29 - untagged pg0 interface
30 - Dot1Q subinterface on pg1
31 - Dot1AD subinterface on pg2
33 - put it into UP state
35 - resolve neighbor address using ARP
36 - configure 200 fib entries
38 :ivar list interfaces: pg interfaces and subinterfaces.
39 :ivar dict flows: IPv4 packet flows in test.
41 super(TestIPv4, self).setUp()
43 # create 3 pg interfaces
44 self.create_pg_interfaces(range(3))
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)]
51 # packet flows mapping pg0 -> pg1.sub, pg2.sub, etc.
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]
58 self.pg_if_packet_sizes = [64, 1500, 9020]
60 self.interfaces = list(self.pg_interfaces)
61 self.interfaces.extend(self.sub_interfaces)
63 # setup all interfaces
64 for i in self.interfaces:
69 # config 2M FIB entries
70 self.config_fib_entries(200)
73 """Run standard test teardown and log ``show ip arp``."""
74 super(TestIPv4, self).tearDown()
76 self.logger.info(self.vapi.cli("show ip arp"))
77 # info(self.vapi.cli("show ip fib")) # many entries
79 def config_fib_entries(self, count):
80 """For each interface add to the FIB table *count* routes to
81 "10.0.0.1/32" destination with interface's local address as next-hop
84 :param int count: Number of FIB entries.
86 - *TODO:* check if the next-hop address shouldn't be remote address
87 instead of local address.
89 n_int = len(self.interfaces)
92 dest_addr = socket.inet_pton(socket.AF_INET, "10.0.0.1")
94 for i in self.interfaces:
95 next_hop_address = i.local_ip4n
96 for j in range(count / n_int):
97 self.vapi.ip_add_del_route(
98 dest_addr, dest_addr_len, next_hop_address)
100 if counter / count * 100 > percent:
101 self.logger.info("Configure %d FIB entries .. %d%% done" %
105 def modify_packet(self, src_if, packet_size, pkt):
106 """Add load, set destination IP and extend packet to required packet
107 size for defined interface.
109 :param VppInterface src_if: Interface to create packet for.
110 :param int packet_size: Required packet size.
111 :param Scapy pkt: Packet to be modified.
113 dst_if_idx = packet_size / 10 % 2
114 dst_if = self.flows[src_if][dst_if_idx]
115 info = self.create_packet_info(src_if, dst_if)
116 payload = self.info_to_payload(info)
118 p[IP].dst = dst_if.remote_ip4
120 if isinstance(src_if, VppSubInterface):
121 p = src_if.add_dot1_layer(p)
122 self.extend_packet(p, packet_size)
126 def create_stream(self, src_if):
127 """Create input packet stream for defined interface.
129 :param VppInterface src_if: Interface to create packet stream for.
131 hdr_ext = 4 if isinstance(src_if, VppSubInterface) else 0
132 pkt_tmpl = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
133 IP(src=src_if.remote_ip4) /
134 UDP(sport=1234, dport=1234))
136 pkts = [self.modify_packet(src_if, i, pkt_tmpl)
137 for i in xrange(self.pg_if_packet_sizes[0],
138 self.pg_if_packet_sizes[1], 10)]
139 pkts_b = [self.modify_packet(src_if, i, pkt_tmpl)
140 for i in xrange(self.pg_if_packet_sizes[1] + hdr_ext,
141 self.pg_if_packet_sizes[2] + hdr_ext, 50)]
146 def verify_capture(self, dst_if, capture):
147 """Verify captured input packet stream for defined interface.
149 :param VppInterface dst_if: Interface to verify captured packet stream
151 :param list capture: Captured packet stream.
153 self.logger.info("Verifying capture on interface %s" % dst_if.name)
155 for i in self.interfaces:
156 last_info[i.sw_if_index] = None
158 dst_sw_if_index = dst_if.sw_if_index
159 if hasattr(dst_if, 'parent'):
161 for packet in capture:
163 # Check VLAN tags and Ethernet header
164 packet = dst_if.remove_dot1_layer(packet)
165 self.assertTrue(Dot1Q not in packet)
169 payload_info = self.payload_to_info(str(packet[Raw]))
170 packet_index = payload_info.index
171 self.assertEqual(payload_info.dst, dst_sw_if_index)
173 "Got packet on port %s: src=%u (id=%u)" %
174 (dst_if.name, payload_info.src, packet_index))
175 next_info = self.get_next_packet_info_for_interface2(
176 payload_info.src, dst_sw_if_index,
177 last_info[payload_info.src])
178 last_info[payload_info.src] = next_info
179 self.assertTrue(next_info is not None)
180 self.assertEqual(packet_index, next_info.index)
181 saved_packet = next_info.data
182 # Check standard fields
183 self.assertEqual(ip.src, saved_packet[IP].src)
184 self.assertEqual(ip.dst, saved_packet[IP].dst)
185 self.assertEqual(udp.sport, saved_packet[UDP].sport)
186 self.assertEqual(udp.dport, saved_packet[UDP].dport)
188 self.logger.error(ppp("Unexpected or invalid packet:", packet))
190 for i in self.interfaces:
191 remaining_packet = self.get_next_packet_info_for_interface2(
192 i.sw_if_index, dst_sw_if_index, last_info[i.sw_if_index])
193 self.assertTrue(remaining_packet is None,
194 "Interface %s: Packet expected from interface %s "
195 "didn't arrive" % (dst_if.name, i.name))
202 - Create IPv4 stream for pg0 interface
203 - Create IPv4 tagged streams for pg1's and pg2's sub-interface.
204 - Send and verify received packets on each interface.
207 pkts = self.create_stream(self.pg0)
208 self.pg0.add_stream(pkts)
210 for i in self.sub_interfaces:
211 pkts = self.create_stream(i)
212 i.parent.add_stream(pkts)
214 self.pg_enable_capture(self.pg_interfaces)
217 pkts = self.pg0.get_capture()
218 self.verify_capture(self.pg0, pkts)
220 for i in self.sub_interfaces:
221 pkts = i.parent.get_capture()
222 self.verify_capture(i, pkts)
225 class TestICMPEcho(VppTestCase):
226 """ ICMP Echo Test Case """
229 super(TestICMPEcho, self).setUp()
231 # create 1 pg interface
232 self.create_pg_interfaces(range(1))
234 for i in self.pg_interfaces:
240 super(TestICMPEcho, self).tearDown()
241 for i in self.pg_interfaces:
245 def test_icmp_echo(self):
246 """ VPP replies to ICMP Echo Request
250 - Receive ICMP Echo Request message on pg0 interface.
251 - Check outgoing ICMP Echo Reply message on pg0 interface.
256 icmp_load = '\x0a' * 18
257 p_echo_request = (Ether(src=self.pg0.remote_mac,
258 dst=self.pg0.local_mac) /
259 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
260 ICMP(id=icmp_id, seq=icmp_seq) /
263 self.pg0.add_stream(p_echo_request)
264 self.pg_enable_capture(self.pg_interfaces)
267 rx = self.pg0.get_capture(1)
273 self.assertEqual(ether.src, self.pg0.local_mac)
274 self.assertEqual(ether.dst, self.pg0.remote_mac)
276 self.assertEqual(ipv4.src, self.pg0.local_ip4)
277 self.assertEqual(ipv4.dst, self.pg0.remote_ip4)
279 self.assertEqual(icmptypes[icmp.type], "echo-reply")
280 self.assertEqual(icmp.id, icmp_id)
281 self.assertEqual(icmp.seq, icmp_seq)
282 self.assertEqual(icmp[Raw].load, icmp_load)
285 class TestIPv4FibCrud(VppTestCase):
286 """ FIB - add/update/delete - ip4 routes
294 ..note:: Python API is too slow to add many routes, needs replacement.
297 def config_fib_many_to_one(self, start_dest_addr, next_hop_addr, count):
300 :param start_dest_addr:
301 :param next_hop_addr:
303 :return list: added ips with 32 prefix
306 dest_addr = int(binascii.hexlify(socket.inet_pton(socket.AF_INET,
307 start_dest_addr)), 16)
309 n_next_hop_addr = socket.inet_pton(socket.AF_INET, next_hop_addr)
310 for _ in range(count):
311 n_dest_addr = '{:08x}'.format(dest_addr).decode('hex')
312 self.vapi.ip_add_del_route(n_dest_addr, dest_addr_len,
314 added_ips.append(socket.inet_ntoa(n_dest_addr))
318 def unconfig_fib_many_to_one(self, start_dest_addr, next_hop_addr, count):
321 dest_addr = int(binascii.hexlify(socket.inet_pton(socket.AF_INET,
322 start_dest_addr)), 16)
324 n_next_hop_addr = socket.inet_pton(socket.AF_INET, next_hop_addr)
325 for _ in range(count):
326 n_dest_addr = '{:08x}'.format(dest_addr).decode('hex')
327 self.vapi.ip_add_del_route(n_dest_addr, dest_addr_len,
328 n_next_hop_addr, is_add=0)
329 removed_ips.append(socket.inet_ntoa(n_dest_addr))
333 def create_stream(self, src_if, dst_if, dst_ips, count):
336 for _ in range(count):
337 dst_addr = random.choice(dst_ips)
338 info = self.create_packet_info(src_if, dst_if)
339 payload = self.info_to_payload(info)
340 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
341 IP(src=src_if.remote_ip4, dst=dst_addr) /
342 UDP(sport=1234, dport=1234) /
345 self.extend_packet(p, random.choice(self.pg_if_packet_sizes))
350 def _find_ip_match(self, find_in, pkt):
352 if self.payload_to_info(str(p[Raw])) == \
353 self.payload_to_info(str(pkt[Raw])):
354 if p[IP].src != pkt[IP].src:
356 if p[IP].dst != pkt[IP].dst:
358 if p[UDP].sport != pkt[UDP].sport:
360 if p[UDP].dport != pkt[UDP].dport:
366 def _match_route_detail(route_detail, ip, address_length=32, table_id=0):
367 if route_detail.address == socket.inet_pton(socket.AF_INET, ip):
368 if route_detail.table_id != table_id:
370 elif route_detail.address_length != address_length:
377 def verify_capture(self, dst_interface, received_pkts, expected_pkts):
378 self.assertEqual(len(received_pkts), len(expected_pkts))
379 to_verify = list(expected_pkts)
380 for p in received_pkts:
381 self.assertEqual(p.src, dst_interface.local_mac)
382 self.assertEqual(p.dst, dst_interface.remote_mac)
383 x = self._find_ip_match(to_verify, p)
385 self.assertListEqual(to_verify, [])
387 def verify_route_dump(self, fib_dump, ips):
389 def _ip_in_route_dump(ip, fib_dump):
390 return next((route for route in fib_dump
391 if self._match_route_detail(route, ip)),
395 self.assertTrue(_ip_in_route_dump(ip, fib_dump),
396 'IP {} is not in fib dump.'.format(ip))
398 def verify_not_in_route_dump(self, fib_dump, ips):
400 def _ip_in_route_dump(ip, fib_dump):
401 return next((route for route in fib_dump
402 if self._match_route_detail(route, ip)),
406 self.assertFalse(_ip_in_route_dump(ip, fib_dump),
407 'IP {} is in fib dump.'.format(ip))
412 #. Create and initialize 3 pg interfaces.
413 #. initialize class attributes configured_routes and deleted_routes
414 to store information between tests.
416 super(TestIPv4FibCrud, cls).setUpClass()
419 # create 3 pg interfaces
420 cls.create_pg_interfaces(range(3))
422 cls.interfaces = list(cls.pg_interfaces)
424 # setup all interfaces
425 for i in cls.interfaces:
430 cls.configured_routes = []
431 cls.deleted_routes = []
432 cls.pg_if_packet_sizes = [64, 512, 1518, 9018]
435 super(TestIPv4FibCrud, cls).tearDownClass()
439 super(TestIPv4FibCrud, self).setUp()
440 self.reset_packet_infos()
442 def test_1_add_routes(self):
445 - add 100 routes check with traffic script.
447 # config 1M FIB entries
448 self.configured_routes.extend(self.config_fib_many_to_one(
449 "10.0.0.0", self.pg0.remote_ip4, 100))
451 fib_dump = self.vapi.ip_fib_dump()
452 self.verify_route_dump(fib_dump, self.configured_routes)
454 self.stream_1 = self.create_stream(
455 self.pg1, self.pg0, self.configured_routes, 100)
456 self.stream_2 = self.create_stream(
457 self.pg2, self.pg0, self.configured_routes, 100)
458 self.pg1.add_stream(self.stream_1)
459 self.pg2.add_stream(self.stream_2)
461 self.pg_enable_capture(self.pg_interfaces)
464 pkts = self.pg0.get_capture(len(self.stream_1) + len(self.stream_2))
465 self.verify_capture(self.pg0, pkts, self.stream_1 + self.stream_2)
467 def test_2_del_routes(self):
468 """ Delete 100 routes
470 - delete 10 routes check with traffic script.
472 self.deleted_routes.extend(self.unconfig_fib_many_to_one(
473 "10.0.0.10", self.pg0.remote_ip4, 10))
474 for x in self.deleted_routes:
475 self.configured_routes.remove(x)
477 fib_dump = self.vapi.ip_fib_dump()
478 self.verify_route_dump(fib_dump, self.configured_routes)
480 self.stream_1 = self.create_stream(
481 self.pg1, self.pg0, self.configured_routes, 100)
482 self.stream_2 = self.create_stream(
483 self.pg2, self.pg0, self.configured_routes, 100)
484 self.stream_3 = self.create_stream(
485 self.pg1, self.pg0, self.deleted_routes, 100)
486 self.stream_4 = self.create_stream(
487 self.pg2, self.pg0, self.deleted_routes, 100)
488 self.pg1.add_stream(self.stream_1 + self.stream_3)
489 self.pg2.add_stream(self.stream_2 + self.stream_4)
490 self.pg_enable_capture(self.pg_interfaces)
493 pkts = self.pg0.get_capture(len(self.stream_1) + len(self.stream_2))
494 self.verify_capture(self.pg0, pkts, self.stream_1 + self.stream_2)
496 def test_3_add_new_routes(self):
499 - re-add 5 routes check with traffic script.
500 - add 100 routes check with traffic script.
502 tmp = self.config_fib_many_to_one(
503 "10.0.0.10", self.pg0.remote_ip4, 5)
504 self.configured_routes.extend(tmp)
506 self.deleted_routes.remove(x)
508 self.configured_routes.extend(self.config_fib_many_to_one(
509 "10.0.1.0", self.pg0.remote_ip4, 100))
511 fib_dump = self.vapi.ip_fib_dump()
512 self.verify_route_dump(fib_dump, self.configured_routes)
514 self.stream_1 = self.create_stream(
515 self.pg1, self.pg0, self.configured_routes, 300)
516 self.stream_2 = self.create_stream(
517 self.pg2, self.pg0, self.configured_routes, 300)
518 self.stream_3 = self.create_stream(
519 self.pg1, self.pg0, self.deleted_routes, 100)
520 self.stream_4 = self.create_stream(
521 self.pg2, self.pg0, self.deleted_routes, 100)
523 self.pg1.add_stream(self.stream_1 + self.stream_3)
524 self.pg2.add_stream(self.stream_2 + self.stream_4)
525 self.pg_enable_capture(self.pg_interfaces)
528 pkts = self.pg0.get_capture(len(self.stream_1) + len(self.stream_2))
529 self.verify_capture(self.pg0, pkts, self.stream_1 + self.stream_2)
531 def test_4_del_routes(self):
532 """ Delete 1.5k routes
534 - delete 5 routes check with traffic script.
535 - add 100 routes check with traffic script.
537 self.deleted_routes.extend(self.unconfig_fib_many_to_one(
538 "10.0.0.0", self.pg0.remote_ip4, 15))
539 self.deleted_routes.extend(self.unconfig_fib_many_to_one(
540 "10.0.0.20", self.pg0.remote_ip4, 85))
541 self.deleted_routes.extend(self.unconfig_fib_many_to_one(
542 "10.0.1.0", self.pg0.remote_ip4, 100))
543 fib_dump = self.vapi.ip_fib_dump()
544 self.verify_not_in_route_dump(fib_dump, self.deleted_routes)
547 class TestIPNull(VppTestCase):
548 """ IPv4 routes via NULL """
551 super(TestIPNull, self).setUp()
553 # create 2 pg interfaces
554 self.create_pg_interfaces(range(2))
556 for i in self.pg_interfaces:
562 super(TestIPNull, self).tearDown()
563 for i in self.pg_interfaces:
567 def test_ip_null(self):
568 """ IP NULL route """
571 # A route via IP NULL that will reply with ICMP unreachables
573 ip_unreach = VppIpRoute(self, "10.0.0.1", 32, [], is_unreach=1)
574 ip_unreach.add_vpp_config()
576 p_unreach = (Ether(src=self.pg0.remote_mac,
577 dst=self.pg0.local_mac) /
578 IP(src=self.pg0.remote_ip4, dst="10.0.0.1") /
579 UDP(sport=1234, dport=1234) /
582 self.pg0.add_stream(p_unreach)
583 self.pg_enable_capture(self.pg_interfaces)
586 rx = self.pg0.get_capture(1)
590 self.assertEqual(icmptypes[icmp.type], "dest-unreach")
591 self.assertEqual(icmpcodes[icmp.type][icmp.code], "host-unreachable")
592 self.assertEqual(icmp.src, self.pg0.remote_ip4)
593 self.assertEqual(icmp.dst, "10.0.0.1")
596 # ICMP replies are rate limited. so sit and spin.
601 # A route via IP NULL that will reply with ICMP prohibited
603 ip_prohibit = VppIpRoute(self, "10.0.0.2", 32, [], is_prohibit=1)
604 ip_prohibit.add_vpp_config()
606 p_prohibit = (Ether(src=self.pg0.remote_mac,
607 dst=self.pg0.local_mac) /
608 IP(src=self.pg0.remote_ip4, dst="10.0.0.2") /
609 UDP(sport=1234, dport=1234) /
612 self.pg0.add_stream(p_prohibit)
613 self.pg_enable_capture(self.pg_interfaces)
616 rx = self.pg0.get_capture(1)
621 self.assertEqual(icmptypes[icmp.type], "dest-unreach")
622 self.assertEqual(icmpcodes[icmp.type][icmp.code], "host-prohibited")
623 self.assertEqual(icmp.src, self.pg0.remote_ip4)
624 self.assertEqual(icmp.dst, "10.0.0.2")
626 def test_ip_drop(self):
627 """ IP Drop Routes """
629 p = (Ether(src=self.pg0.remote_mac,
630 dst=self.pg0.local_mac) /
631 IP(src=self.pg0.remote_ip4, dst="1.1.1.1") /
632 UDP(sport=1234, dport=1234) /
635 r1 = VppIpRoute(self, "1.1.1.0", 24,
636 [VppRoutePath(self.pg1.remote_ip4,
637 self.pg1.sw_if_index)])
640 rx = self.send_and_expect(self.pg0, p * 65, self.pg1)
643 # insert a more specific as a drop
645 r2 = VppIpRoute(self, "1.1.1.1", 32, [], is_drop=1)
648 self.send_and_assert_no_replies(self.pg0, p * 65, "Drop Route")
649 r2.remove_vpp_config()
650 rx = self.send_and_expect(self.pg0, p * 65, self.pg1)
653 class TestIPDisabled(VppTestCase):
654 """ IPv4 disabled """
657 super(TestIPDisabled, self).setUp()
659 # create 2 pg interfaces
660 self.create_pg_interfaces(range(2))
664 self.pg0.config_ip4()
665 self.pg0.resolve_arp()
667 # PG 1 is not IP enabled
671 super(TestIPDisabled, self).tearDown()
672 for i in self.pg_interfaces:
676 def test_ip_disabled(self):
681 # one accepting interface, pg0, 2 forwarding interfaces
683 route_232_1_1_1 = VppIpMRoute(
687 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
688 [VppMRoutePath(self.pg1.sw_if_index,
689 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
690 VppMRoutePath(self.pg0.sw_if_index,
691 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
692 route_232_1_1_1.add_vpp_config()
694 pu = (Ether(src=self.pg1.remote_mac,
695 dst=self.pg1.local_mac) /
696 IP(src="10.10.10.10", dst=self.pg0.remote_ip4) /
697 UDP(sport=1234, dport=1234) /
699 pm = (Ether(src=self.pg1.remote_mac,
700 dst=self.pg1.local_mac) /
701 IP(src="10.10.10.10", dst="232.1.1.1") /
702 UDP(sport=1234, dport=1234) /
706 # PG1 does not forward IP traffic
708 self.send_and_assert_no_replies(self.pg1, pu, "IP disabled")
709 self.send_and_assert_no_replies(self.pg1, pm, "IP disabled")
714 self.pg1.config_ip4()
717 # Now we get packets through
719 self.pg1.add_stream(pu)
720 self.pg_enable_capture(self.pg_interfaces)
722 rx = self.pg0.get_capture(1)
724 self.pg1.add_stream(pm)
725 self.pg_enable_capture(self.pg_interfaces)
727 rx = self.pg0.get_capture(1)
732 self.pg1.unconfig_ip4()
735 # PG1 does not forward IP traffic
737 self.send_and_assert_no_replies(self.pg1, pu, "IP disabled")
738 self.send_and_assert_no_replies(self.pg1, pm, "IP disabled")
741 class TestIPSubNets(VppTestCase):
745 super(TestIPSubNets, self).setUp()
747 # create a 2 pg interfaces
748 self.create_pg_interfaces(range(2))
750 # pg0 we will use to experiemnt
753 # pg1 is setup normally
755 self.pg1.config_ip4()
756 self.pg1.resolve_arp()
759 super(TestIPSubNets, self).tearDown()
760 for i in self.pg_interfaces:
763 def test_ip_sub_nets(self):
767 # Configure a covering route to forward so we know
768 # when we are dropping
770 cover_route = VppIpRoute(self, "10.0.0.0", 8,
771 [VppRoutePath(self.pg1.remote_ip4,
772 self.pg1.sw_if_index)])
773 cover_route.add_vpp_config()
775 p = (Ether(src=self.pg1.remote_mac,
776 dst=self.pg1.local_mac) /
777 IP(dst="10.10.10.10", src=self.pg0.local_ip4) /
778 UDP(sport=1234, dport=1234) /
781 self.pg1.add_stream(p)
782 self.pg_enable_capture(self.pg_interfaces)
784 rx = self.pg1.get_capture(1)
787 # Configure some non-/24 subnets on an IP interface
789 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.10.10.10")
791 self.vapi.sw_interface_add_del_address(self.pg0.sw_if_index,
795 pn = (Ether(src=self.pg1.remote_mac,
796 dst=self.pg1.local_mac) /
797 IP(dst="10.10.0.0", src=self.pg0.local_ip4) /
798 UDP(sport=1234, dport=1234) /
800 pb = (Ether(src=self.pg1.remote_mac,
801 dst=self.pg1.local_mac) /
802 IP(dst="10.10.255.255", src=self.pg0.local_ip4) /
803 UDP(sport=1234, dport=1234) /
806 self.send_and_assert_no_replies(self.pg1, pn, "IP Network address")
807 self.send_and_assert_no_replies(self.pg1, pb, "IP Broadcast address")
809 # remove the sub-net and we are forwarding via the cover again
810 self.vapi.sw_interface_add_del_address(self.pg0.sw_if_index,
814 self.pg1.add_stream(pn)
815 self.pg_enable_capture(self.pg_interfaces)
817 rx = self.pg1.get_capture(1)
818 self.pg1.add_stream(pb)
819 self.pg_enable_capture(self.pg_interfaces)
821 rx = self.pg1.get_capture(1)
824 # A /31 is a special case where the 'other-side' is an attached host
825 # packets to that peer generate ARP requests
827 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.10.10.10")
829 self.vapi.sw_interface_add_del_address(self.pg0.sw_if_index,
833 pn = (Ether(src=self.pg1.remote_mac,
834 dst=self.pg1.local_mac) /
835 IP(dst="10.10.10.11", src=self.pg0.local_ip4) /
836 UDP(sport=1234, dport=1234) /
839 self.pg1.add_stream(pn)
840 self.pg_enable_capture(self.pg_interfaces)
842 rx = self.pg0.get_capture(1)
845 # remove the sub-net and we are forwarding via the cover again
846 self.vapi.sw_interface_add_del_address(self.pg0.sw_if_index,
850 self.pg1.add_stream(pn)
851 self.pg_enable_capture(self.pg_interfaces)
853 rx = self.pg1.get_capture(1)
856 class TestIPLoadBalance(VppTestCase):
857 """ IPv4 Load-Balancing """
860 super(TestIPLoadBalance, self).setUp()
862 self.create_pg_interfaces(range(5))
863 mpls_tbl = VppMplsTable(self, 0)
864 mpls_tbl.add_vpp_config()
866 for i in self.pg_interfaces:
873 for i in self.pg_interfaces:
877 super(TestIPLoadBalance, self).tearDown()
879 def send_and_expect_load_balancing(self, input, pkts, outputs):
880 input.add_stream(pkts)
881 self.pg_enable_capture(self.pg_interfaces)
884 rx = oo._get_capture(1)
885 self.assertNotEqual(0, len(rx))
887 def send_and_expect_one_itf(self, input, pkts, itf):
888 input.add_stream(pkts)
889 self.pg_enable_capture(self.pg_interfaces)
891 rx = itf.get_capture(len(pkts))
893 def test_ip_load_balance(self):
894 """ IP Load-Balancing """
897 # An array of packets that differ only in the destination port
903 # An array of packets that differ only in the source address
909 port_ip_hdr = (IP(dst="10.0.0.1", src="20.0.0.1") /
910 UDP(sport=1234, dport=1234 + ii) /
912 port_ip_pkts.append((Ether(src=self.pg0.remote_mac,
913 dst=self.pg0.local_mac) /
915 port_mpls_pkts.append((Ether(src=self.pg0.remote_mac,
916 dst=self.pg0.local_mac) /
917 MPLS(label=66, ttl=2) /
920 src_ip_hdr = (IP(dst="10.0.0.1", src="20.0.0.%d" % ii) /
921 UDP(sport=1234, dport=1234) /
923 src_ip_pkts.append((Ether(src=self.pg0.remote_mac,
924 dst=self.pg0.local_mac) /
926 src_mpls_pkts.append((Ether(src=self.pg0.remote_mac,
927 dst=self.pg0.local_mac) /
928 MPLS(label=66, ttl=2) /
931 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
932 [VppRoutePath(self.pg1.remote_ip4,
933 self.pg1.sw_if_index),
934 VppRoutePath(self.pg2.remote_ip4,
935 self.pg2.sw_if_index)])
936 route_10_0_0_1.add_vpp_config()
938 binding = VppMplsIpBind(self, 66, "10.0.0.1", 32)
939 binding.add_vpp_config()
942 # inject the packet on pg0 - expect load-balancing across the 2 paths
943 # - since the default hash config is to use IP src,dst and port
945 # We are not going to ensure equal amounts of packets across each link,
946 # since the hash algorithm is statistical and therefore this can never
947 # be guaranteed. But wuth 64 different packets we do expect some
948 # balancing. So instead just ensure there is traffic on each link.
950 self.send_and_expect_load_balancing(self.pg0, port_ip_pkts,
951 [self.pg1, self.pg2])
952 self.send_and_expect_load_balancing(self.pg0, src_ip_pkts,
953 [self.pg1, self.pg2])
954 self.send_and_expect_load_balancing(self.pg0, port_mpls_pkts,
955 [self.pg1, self.pg2])
956 self.send_and_expect_load_balancing(self.pg0, src_mpls_pkts,
957 [self.pg1, self.pg2])
960 # change the flow hash config so it's only IP src,dst
961 # - now only the stream with differing source address will
964 self.vapi.set_ip_flow_hash(0, src=1, dst=1, sport=0, dport=0)
966 self.send_and_expect_load_balancing(self.pg0, src_ip_pkts,
967 [self.pg1, self.pg2])
968 self.send_and_expect_load_balancing(self.pg0, src_mpls_pkts,
969 [self.pg1, self.pg2])
971 self.send_and_expect_one_itf(self.pg0, port_ip_pkts, self.pg2)
974 # change the flow hash config back to defaults
976 self.vapi.set_ip_flow_hash(0, src=1, dst=1, sport=1, dport=1)
980 # - testing that 2 stages of load-balancing occurs and there is no
981 # polarisation (i.e. only 2 of 4 paths are used)
986 for ii in range(257):
987 port_pkts.append((Ether(src=self.pg0.remote_mac,
988 dst=self.pg0.local_mac) /
989 IP(dst="1.1.1.1", src="20.0.0.1") /
990 UDP(sport=1234, dport=1234 + ii) /
992 src_pkts.append((Ether(src=self.pg0.remote_mac,
993 dst=self.pg0.local_mac) /
994 IP(dst="1.1.1.1", src="20.0.0.%d" % ii) /
995 UDP(sport=1234, dport=1234) /
998 route_10_0_0_2 = VppIpRoute(self, "10.0.0.2", 32,
999 [VppRoutePath(self.pg3.remote_ip4,
1000 self.pg3.sw_if_index),
1001 VppRoutePath(self.pg4.remote_ip4,
1002 self.pg4.sw_if_index)])
1003 route_10_0_0_2.add_vpp_config()
1005 route_1_1_1_1 = VppIpRoute(self, "1.1.1.1", 32,
1006 [VppRoutePath("10.0.0.2", 0xffffffff),
1007 VppRoutePath("10.0.0.1", 0xffffffff)])
1008 route_1_1_1_1.add_vpp_config()
1011 # inject the packet on pg0 - expect load-balancing across all 4 paths
1013 self.vapi.cli("clear trace")
1014 self.send_and_expect_load_balancing(self.pg0, port_pkts,
1015 [self.pg1, self.pg2,
1016 self.pg3, self.pg4])
1017 self.send_and_expect_load_balancing(self.pg0, src_pkts,
1018 [self.pg1, self.pg2,
1019 self.pg3, self.pg4])
1022 # Recursive prefixes
1023 # - testing that 2 stages of load-balancing, no choices
1027 for ii in range(257):
1028 port_pkts.append((Ether(src=self.pg0.remote_mac,
1029 dst=self.pg0.local_mac) /
1030 IP(dst="1.1.1.2", src="20.0.0.2") /
1031 UDP(sport=1234, dport=1234 + ii) /
1034 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
1035 [VppRoutePath(self.pg3.remote_ip4,
1036 self.pg3.sw_if_index)])
1037 route_10_0_0_3.add_vpp_config()
1039 route_1_1_1_2 = VppIpRoute(self, "1.1.1.2", 32,
1040 [VppRoutePath("10.0.0.3", 0xffffffff)])
1041 route_1_1_1_2.add_vpp_config()
1044 # inject the packet on pg0 - expect load-balancing across all 4 paths
1046 self.vapi.cli("clear trace")
1047 self.send_and_expect_one_itf(self.pg0, port_pkts, self.pg3)
1050 class TestIPVlan0(VppTestCase):
1054 super(TestIPVlan0, self).setUp()
1056 self.create_pg_interfaces(range(2))
1057 mpls_tbl = VppMplsTable(self, 0)
1058 mpls_tbl.add_vpp_config()
1060 for i in self.pg_interfaces:
1067 for i in self.pg_interfaces:
1071 super(TestIPVlan0, self).tearDown()
1073 def test_ip_vlan_0(self):
1076 pkts = (Ether(src=self.pg0.remote_mac,
1077 dst=self.pg0.local_mac) /
1079 IP(dst=self.pg1.remote_ip4,
1080 src=self.pg0.remote_ip4) /
1081 UDP(sport=1234, dport=1234) /
1082 Raw('\xa5' * 100)) * 65
1085 # Expect that packets sent on VLAN-0 are forwarded on the
1088 self.send_and_expect(self.pg0, pkts, self.pg1)
1091 class TestIPPunt(VppTestCase):
1092 """ IPv4 Punt Police/Redirect """
1095 super(TestIPPunt, self).setUp()
1097 self.create_pg_interfaces(range(4))
1099 for i in self.pg_interfaces:
1105 super(TestIPPunt, self).tearDown()
1106 for i in self.pg_interfaces:
1110 def test_ip_punt(self):
1111 """ IP punt police and redirect """
1113 p = (Ether(src=self.pg0.remote_mac,
1114 dst=self.pg0.local_mac) /
1115 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
1116 TCP(sport=1234, dport=1234) /
1122 # Configure a punt redirect via pg1.
1124 nh_addr = VppIpAddress(self.pg1.remote_ip4).encode()
1125 self.vapi.ip_punt_redirect(self.pg0.sw_if_index,
1126 self.pg1.sw_if_index,
1129 self.send_and_expect(self.pg0, pkts, self.pg1)
1134 policer = self.vapi.policer_add_del("ip4-punt", 400, 0, 10, 0,
1136 self.vapi.ip_punt_police(policer.policer_index)
1138 self.vapi.cli("clear trace")
1139 self.pg0.add_stream(pkts)
1140 self.pg_enable_capture(self.pg_interfaces)
1144 # the number of packet recieved should be greater than 0,
1145 # but not equal to the number sent, since some were policed
1147 rx = self.pg1._get_capture(1)
1148 self.assertGreater(len(rx), 0)
1149 self.assertLess(len(rx), len(pkts))
1152 # remove the poilcer. back to full rx
1154 self.vapi.ip_punt_police(policer.policer_index, is_add=0)
1155 self.vapi.policer_add_del("ip4-punt", 400, 0, 10, 0,
1156 rate_type=1, is_add=0)
1157 self.send_and_expect(self.pg0, pkts, self.pg1)
1160 # remove the redirect. expect full drop.
1162 self.vapi.ip_punt_redirect(self.pg0.sw_if_index,
1163 self.pg1.sw_if_index,
1166 self.send_and_assert_no_replies(self.pg0, pkts,
1167 "IP no punt config")
1170 # Add a redirect that is not input port selective
1172 self.vapi.ip_punt_redirect(0xffffffff,
1173 self.pg1.sw_if_index,
1175 self.send_and_expect(self.pg0, pkts, self.pg1)
1177 self.vapi.ip_punt_redirect(0xffffffff,
1178 self.pg1.sw_if_index,
1182 def test_ip_punt_dump(self):
1183 """ IP4 punt redirect dump"""
1186 # Configure a punt redirects
1188 nh_address = VppIpAddress(self.pg3.remote_ip4).encode()
1189 self.vapi.ip_punt_redirect(self.pg0.sw_if_index,
1190 self.pg3.sw_if_index,
1192 self.vapi.ip_punt_redirect(self.pg1.sw_if_index,
1193 self.pg3.sw_if_index,
1195 self.vapi.ip_punt_redirect(self.pg2.sw_if_index,
1196 self.pg3.sw_if_index,
1197 VppIpAddress('0.0.0.0').encode())
1200 # Dump pg0 punt redirects
1202 punts = self.vapi.ip_punt_redirect_dump(self.pg0.sw_if_index)
1204 self.assertEqual(p.punt.rx_sw_if_index, self.pg0.sw_if_index)
1207 # Dump punt redirects for all interfaces
1209 punts = self.vapi.ip_punt_redirect_dump(0xffffffff)
1210 self.assertEqual(len(punts), 3)
1212 self.assertEqual(p.punt.tx_sw_if_index, self.pg3.sw_if_index)
1213 self.assertNotEqual(punts[1].punt.nh.un.ip4, self.pg3.remote_ip4)
1214 self.assertEqual(punts[2].punt.nh.un.ip4.address, '\x00'*4)
1217 class TestIPDeag(VppTestCase):
1218 """ IPv4 Deaggregate Routes """
1221 super(TestIPDeag, self).setUp()
1223 self.create_pg_interfaces(range(3))
1225 for i in self.pg_interfaces:
1231 super(TestIPDeag, self).tearDown()
1232 for i in self.pg_interfaces:
1236 def test_ip_deag(self):
1237 """ IP Deag Routes """
1240 # Create a table to be used for:
1241 # 1 - another destination address lookup
1242 # 2 - a source address lookup
1244 table_dst = VppIpTable(self, 1)
1245 table_src = VppIpTable(self, 2)
1246 table_dst.add_vpp_config()
1247 table_src.add_vpp_config()
1250 # Add a route in the default table to point to a deag/
1251 # second lookup in each of these tables
1253 route_to_dst = VppIpRoute(self, "1.1.1.1", 32,
1254 [VppRoutePath("0.0.0.0",
1257 route_to_src = VppIpRoute(self, "1.1.1.2", 32,
1258 [VppRoutePath("0.0.0.0",
1261 is_source_lookup=1)])
1262 route_to_dst.add_vpp_config()
1263 route_to_src.add_vpp_config()
1266 # packets to these destination are dropped, since they'll
1267 # hit the respective default routes in the second table
1269 p_dst = (Ether(src=self.pg0.remote_mac,
1270 dst=self.pg0.local_mac) /
1271 IP(src="5.5.5.5", dst="1.1.1.1") /
1272 TCP(sport=1234, dport=1234) /
1274 p_src = (Ether(src=self.pg0.remote_mac,
1275 dst=self.pg0.local_mac) /
1276 IP(src="2.2.2.2", dst="1.1.1.2") /
1277 TCP(sport=1234, dport=1234) /
1279 pkts_dst = p_dst * 257
1280 pkts_src = p_src * 257
1282 self.send_and_assert_no_replies(self.pg0, pkts_dst,
1284 self.send_and_assert_no_replies(self.pg0, pkts_src,
1288 # add a route in the dst table to forward via pg1
1290 route_in_dst = VppIpRoute(self, "1.1.1.1", 32,
1291 [VppRoutePath(self.pg1.remote_ip4,
1292 self.pg1.sw_if_index)],
1294 route_in_dst.add_vpp_config()
1295 self.send_and_expect(self.pg0, pkts_dst, self.pg1)
1298 # add a route in the src table to forward via pg2
1300 route_in_src = VppIpRoute(self, "2.2.2.2", 32,
1301 [VppRoutePath(self.pg2.remote_ip4,
1302 self.pg2.sw_if_index)],
1304 route_in_src.add_vpp_config()
1305 self.send_and_expect(self.pg0, pkts_src, self.pg2)
1308 # loop in the lookup DP
1310 route_loop = VppIpRoute(self, "2.2.2.3", 32,
1311 [VppRoutePath("0.0.0.0",
1314 route_loop.add_vpp_config()
1316 p_l = (Ether(src=self.pg0.remote_mac,
1317 dst=self.pg0.local_mac) /
1318 IP(src="2.2.2.4", dst="2.2.2.3") /
1319 TCP(sport=1234, dport=1234) /
1322 self.send_and_assert_no_replies(self.pg0, p_l * 257,
1326 class TestIPInput(VppTestCase):
1327 """ IPv4 Input Exceptions """
1330 super(TestIPInput, self).setUp()
1332 self.create_pg_interfaces(range(2))
1334 for i in self.pg_interfaces:
1340 super(TestIPInput, self).tearDown()
1341 for i in self.pg_interfaces:
1345 def test_ip_input(self):
1346 """ IP Input Exceptions """
1348 # i can't find a way in scapy to construct an IP packet
1349 # with a length less than the IP header length
1352 # Packet too short - this is forwarded
1354 p_short = (Ether(src=self.pg0.remote_mac,
1355 dst=self.pg0.local_mac) /
1356 IP(src=self.pg0.remote_ip4,
1357 dst=self.pg1.remote_ip4,
1359 UDP(sport=1234, dport=1234) /
1362 rx = self.send_and_expect(self.pg0, p_short * 65, self.pg1)
1365 # Packet too long - this is dropped
1367 p_long = (Ether(src=self.pg0.remote_mac,
1368 dst=self.pg0.local_mac) /
1369 IP(src=self.pg0.remote_ip4,
1370 dst=self.pg1.remote_ip4,
1372 UDP(sport=1234, dport=1234) /
1375 rx = self.send_and_assert_no_replies(self.pg0, p_long * 65,
1379 # bad chksum - this is dropped
1381 p_chksum = (Ether(src=self.pg0.remote_mac,
1382 dst=self.pg0.local_mac) /
1383 IP(src=self.pg0.remote_ip4,
1384 dst=self.pg1.remote_ip4,
1386 UDP(sport=1234, dport=1234) /
1389 rx = self.send_and_assert_no_replies(self.pg0, p_chksum * 65,
1393 # bad version - this is dropped
1395 p_ver = (Ether(src=self.pg0.remote_mac,
1396 dst=self.pg0.local_mac) /
1397 IP(src=self.pg0.remote_ip4,
1398 dst=self.pg1.remote_ip4,
1400 UDP(sport=1234, dport=1234) /
1403 rx = self.send_and_assert_no_replies(self.pg0, p_ver * 65,
1407 # fragment offset 1 - this is dropped
1409 p_frag = (Ether(src=self.pg0.remote_mac,
1410 dst=self.pg0.local_mac) /
1411 IP(src=self.pg0.remote_ip4,
1412 dst=self.pg1.remote_ip4,
1414 UDP(sport=1234, dport=1234) /
1417 rx = self.send_and_assert_no_replies(self.pg0, p_frag * 65,
1421 # TTL expired packet
1423 p_ttl = (Ether(src=self.pg0.remote_mac,
1424 dst=self.pg0.local_mac) /
1425 IP(src=self.pg0.remote_ip4,
1426 dst=self.pg1.remote_ip4,
1428 UDP(sport=1234, dport=1234) /
1431 rx = self.send_and_expect(self.pg0, p_ttl * 65, self.pg0)
1436 self.assertEqual(icmptypes[icmp.type], "time-exceeded")
1437 self.assertEqual(icmpcodes[icmp.type][icmp.code],
1438 "ttl-zero-during-transit")
1439 self.assertEqual(icmp.src, self.pg0.remote_ip4)
1440 self.assertEqual(icmp.dst, self.pg1.remote_ip4)
1445 p_mtu = (Ether(src=self.pg0.remote_mac,
1446 dst=self.pg0.local_mac) /
1447 IP(src=self.pg0.remote_ip4,
1448 dst=self.pg1.remote_ip4,
1449 ttl=10, flags='DF') /
1450 UDP(sport=1234, dport=1234) /
1453 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1500, 0, 0, 0])
1455 rx = self.send_and_expect(self.pg0, p_mtu * 65, self.pg0)
1459 self.assertEqual(icmptypes[icmp.type], "dest-unreach")
1460 self.assertEqual(icmpcodes[icmp.type][icmp.code],
1461 "fragmentation-needed")
1462 self.assertEqual(icmp.src, self.pg0.remote_ip4)
1463 self.assertEqual(icmp.dst, self.pg1.remote_ip4)
1465 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [2500, 0, 0, 0])
1466 rx = self.send_and_expect(self.pg0, p_mtu * 65, self.pg1)
1468 # Reset MTU for subsequent tests
1469 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [9000, 0, 0, 0])
1472 class TestIPDirectedBroadcast(VppTestCase):
1473 """ IPv4 Directed Broadcast """
1476 super(TestIPDirectedBroadcast, self).setUp()
1478 self.create_pg_interfaces(range(2))
1480 for i in self.pg_interfaces:
1484 super(TestIPDirectedBroadcast, self).tearDown()
1485 for i in self.pg_interfaces:
1488 def test_ip_input(self):
1489 """ IP Directed Broadcast """
1492 # set the directed broadcast on pg0 first, then config IP4 addresses
1493 # for pg1 directed broadcast is always disabled
1494 self.vapi.sw_interface_set_ip_directed_broadcast(
1495 self.pg0.sw_if_index, 1)
1497 p0 = (Ether(src=self.pg1.remote_mac,
1498 dst=self.pg1.local_mac) /
1500 dst=self.pg0._local_ip4_bcast) /
1501 UDP(sport=1234, dport=1234) /
1503 p1 = (Ether(src=self.pg0.remote_mac,
1504 dst=self.pg0.local_mac) /
1506 dst=self.pg1._local_ip4_bcast) /
1507 UDP(sport=1234, dport=1234) /
1510 self.pg0.config_ip4()
1511 self.pg0.resolve_arp()
1512 self.pg1.config_ip4()
1513 self.pg1.resolve_arp()
1516 # test packet is L2 broadcast
1518 rx = self.send_and_expect(self.pg1, p0 * 65, self.pg0)
1519 self.assertTrue(rx[0][Ether].dst, "ff:ff:ff:ff:ff:ff")
1521 self.send_and_assert_no_replies(self.pg0, p1 * 65,
1522 "directed broadcast disabled")
1525 # toggle directed broadcast on pg0
1527 self.vapi.sw_interface_set_ip_directed_broadcast(
1528 self.pg0.sw_if_index, 0)
1529 self.send_and_assert_no_replies(self.pg1, p0 * 65,
1530 "directed broadcast disabled")
1532 self.vapi.sw_interface_set_ip_directed_broadcast(
1533 self.pg0.sw_if_index, 1)
1534 rx = self.send_and_expect(self.pg1, p0 * 65, self.pg0)
1536 self.pg0.unconfig_ip4()
1537 self.pg1.unconfig_ip4()
1540 class TestIPLPM(VppTestCase):
1541 """ IPv4 longest Prefix Match """
1544 super(TestIPLPM, self).setUp()
1546 self.create_pg_interfaces(range(4))
1548 for i in self.pg_interfaces:
1554 super(TestIPLPM, self).tearDown()
1555 for i in self.pg_interfaces:
1559 def test_ip_lpm(self):
1560 """ IP longest Prefix Match """
1562 s_24 = VppIpRoute(self, "10.1.2.0", 24,
1563 [VppRoutePath(self.pg1.remote_ip4,
1564 self.pg1.sw_if_index)])
1565 s_24.add_vpp_config()
1566 s_8 = VppIpRoute(self, "10.0.0.0", 8,
1567 [VppRoutePath(self.pg2.remote_ip4,
1568 self.pg2.sw_if_index)])
1569 s_8.add_vpp_config()
1571 p_8 = (Ether(src=self.pg0.remote_mac,
1572 dst=self.pg0.local_mac) /
1575 UDP(sport=1234, dport=1234) /
1577 p_24 = (Ether(src=self.pg0.remote_mac,
1578 dst=self.pg0.local_mac) /
1581 UDP(sport=1234, dport=1234) /
1584 self.logger.info(self.vapi.cli("sh ip fib mtrie"))
1585 rx = self.send_and_expect(self.pg0, p_8 * 65, self.pg2)
1586 rx = self.send_and_expect(self.pg0, p_24 * 65, self.pg1)
1589 class TestIPv4Frag(VppTestCase):
1590 """ IPv4 fragmentation """
1593 def setUpClass(cls):
1594 super(TestIPv4Frag, cls).setUpClass()
1596 cls.create_pg_interfaces([0, 1])
1597 cls.src_if = cls.pg0
1598 cls.dst_if = cls.pg1
1600 # setup all interfaces
1601 for i in cls.pg_interfaces:
1606 def test_frag_large_packets(self):
1607 """ Fragmentation of large packets """
1609 p = (Ether(dst=self.src_if.local_mac, src=self.src_if.remote_mac) /
1610 IP(src=self.src_if.remote_ip4, dst=self.dst_if.remote_ip4) /
1611 UDP(sport=1234, dport=5678) / Raw())
1612 self.extend_packet(p, 6000, "abcde")
1613 saved_payload = p[Raw].load
1615 # Force fragmentation by setting MTU of output interface
1616 # lower than packet size
1617 self.vapi.sw_interface_set_mtu(self.dst_if.sw_if_index,
1620 self.pg_enable_capture()
1621 self.src_if.add_stream(p)
1624 # Expecting 3 fragments because size of created fragments currently
1625 # cannot be larger then VPP buffer size (which is 2048)
1626 packets = self.dst_if.get_capture(3)
1628 # Assume VPP sends the fragments in order
1631 payload_offset = p.frag * 8
1632 if payload_offset > 0:
1633 payload_offset -= 8 # UDP header is not in payload
1634 self.assert_equal(payload_offset, len(payload))
1635 payload += p[Raw].load
1636 self.assert_equal(payload, saved_payload, "payload")
1639 if __name__ == '__main__':
1640 unittest.main(testRunner=VppTestRunner)