8 from scapy.contrib.mpls import MPLS
9 from scapy.layers.inet import IP, UDP, TCP, ICMP, icmptypes, icmpcodes
10 from scapy.layers.l2 import Ether, Dot1Q, ARP
11 from scapy.packet import Raw
14 from framework import VppTestCase, VppTestRunner
16 from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpMRoute, \
17 VppMRoutePath, MRouteItfFlags, MRouteEntryFlags, VppMplsIpBind, \
18 VppMplsTable, VppIpTable, FibPathType, find_route
19 from vpp_sub_interface import VppSubInterface, VppDot1QSubint, VppDot1ADSubint
20 from vpp_papi import VppEnum
25 class TestIPv4(VppTestCase):
26 """ IPv4 Test Case """
30 super(TestIPv4, cls).setUpClass()
33 def tearDownClass(cls):
34 super(TestIPv4, cls).tearDownClass()
38 Perform test setup before test case.
41 - create 3 pg interfaces
42 - untagged pg0 interface
43 - Dot1Q subinterface on pg1
44 - Dot1AD subinterface on pg2
46 - put it into UP state
48 - resolve neighbor address using ARP
49 - configure 200 fib entries
51 :ivar list interfaces: pg interfaces and subinterfaces.
52 :ivar dict flows: IPv4 packet flows in test.
54 super(TestIPv4, self).setUp()
56 # create 3 pg interfaces
57 self.create_pg_interfaces(range(3))
59 # create 2 subinterfaces for pg1 and pg2
60 self.sub_interfaces = [
61 VppDot1QSubint(self, self.pg1, 100),
62 VppDot1ADSubint(self, self.pg2, 200, 300, 400)]
64 # packet flows mapping pg0 -> pg1.sub, pg2.sub, etc.
66 self.flows[self.pg0] = [self.pg1.sub_if, self.pg2.sub_if]
67 self.flows[self.pg1.sub_if] = [self.pg0, self.pg2.sub_if]
68 self.flows[self.pg2.sub_if] = [self.pg0, self.pg1.sub_if]
71 self.pg_if_packet_sizes = [64, 1500, 9020]
73 self.interfaces = list(self.pg_interfaces)
74 self.interfaces.extend(self.sub_interfaces)
76 # setup all interfaces
77 for i in self.interfaces:
82 # config 2M FIB entries
85 """Run standard test teardown and log ``show ip arp``."""
86 super(TestIPv4, self).tearDown()
88 def show_commands_at_teardown(self):
89 self.logger.info(self.vapi.cli("show ip arp"))
90 # info(self.vapi.cli("show ip fib")) # many entries
92 def modify_packet(self, src_if, packet_size, pkt):
93 """Add load, set destination IP and extend packet to required packet
94 size for defined interface.
96 :param VppInterface src_if: Interface to create packet for.
97 :param int packet_size: Required packet size.
98 :param Scapy pkt: Packet to be modified.
100 dst_if_idx = packet_size / 10 % 2
101 dst_if = self.flows[src_if][dst_if_idx]
102 info = self.create_packet_info(src_if, dst_if)
103 payload = self.info_to_payload(info)
105 p[IP].dst = dst_if.remote_ip4
107 if isinstance(src_if, VppSubInterface):
108 p = src_if.add_dot1_layer(p)
109 self.extend_packet(p, packet_size)
113 def create_stream(self, src_if):
114 """Create input packet stream for defined interface.
116 :param VppInterface src_if: Interface to create packet stream for.
118 hdr_ext = 4 if isinstance(src_if, VppSubInterface) else 0
119 pkt_tmpl = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
120 IP(src=src_if.remote_ip4) /
121 UDP(sport=1234, dport=1234))
123 pkts = [self.modify_packet(src_if, i, pkt_tmpl)
124 for i in moves.range(self.pg_if_packet_sizes[0],
125 self.pg_if_packet_sizes[1], 10)]
126 pkts_b = [self.modify_packet(src_if, i, pkt_tmpl)
127 for i in moves.range(self.pg_if_packet_sizes[1] + hdr_ext,
128 self.pg_if_packet_sizes[2] + hdr_ext,
134 def verify_capture(self, dst_if, capture):
135 """Verify captured input packet stream for defined interface.
137 :param VppInterface dst_if: Interface to verify captured packet stream
139 :param list capture: Captured packet stream.
141 self.logger.info("Verifying capture on interface %s" % dst_if.name)
143 for i in self.interfaces:
144 last_info[i.sw_if_index] = None
146 dst_sw_if_index = dst_if.sw_if_index
147 if hasattr(dst_if, 'parent'):
149 for packet in capture:
151 # Check VLAN tags and Ethernet header
152 packet = dst_if.remove_dot1_layer(packet)
153 self.assertTrue(Dot1Q not in packet)
157 payload_info = self.payload_to_info(packet[Raw])
158 packet_index = payload_info.index
159 self.assertEqual(payload_info.dst, dst_sw_if_index)
161 "Got packet on port %s: src=%u (id=%u)" %
162 (dst_if.name, payload_info.src, packet_index))
163 next_info = self.get_next_packet_info_for_interface2(
164 payload_info.src, dst_sw_if_index,
165 last_info[payload_info.src])
166 last_info[payload_info.src] = next_info
167 self.assertTrue(next_info is not None)
168 self.assertEqual(packet_index, next_info.index)
169 saved_packet = next_info.data
170 # Check standard fields
171 self.assertEqual(ip.src, saved_packet[IP].src)
172 self.assertEqual(ip.dst, saved_packet[IP].dst)
173 self.assertEqual(udp.sport, saved_packet[UDP].sport)
174 self.assertEqual(udp.dport, saved_packet[UDP].dport)
176 self.logger.error(ppp("Unexpected or invalid packet:", packet))
178 for i in self.interfaces:
179 remaining_packet = self.get_next_packet_info_for_interface2(
180 i.sw_if_index, dst_sw_if_index, last_info[i.sw_if_index])
181 self.assertTrue(remaining_packet is None,
182 "Interface %s: Packet expected from interface %s "
183 "didn't arrive" % (dst_if.name, i.name))
190 - Create IPv4 stream for pg0 interface
191 - Create IPv4 tagged streams for pg1's and pg2's sub-interface.
192 - Send and verify received packets on each interface.
195 pkts = self.create_stream(self.pg0)
196 self.pg0.add_stream(pkts)
198 for i in self.sub_interfaces:
199 pkts = self.create_stream(i)
200 i.parent.add_stream(pkts)
202 self.pg_enable_capture(self.pg_interfaces)
205 pkts = self.pg0.get_capture()
206 self.verify_capture(self.pg0, pkts)
208 for i in self.sub_interfaces:
209 pkts = i.parent.get_capture()
210 self.verify_capture(i, pkts)
213 class TestIPV4IfAddrRoute(VppTestCase):
214 """ IPv4 Interface Addr Route Test Case """
218 super(TestIPV4IfAddrRoute, cls).setUpClass()
221 def tearDownClass(cls):
222 super(TestIPV4IfAddrRoute, cls).tearDownClass()
225 super(TestIPV4IfAddrRoute, self).setUp()
227 # create 1 pg interface
228 self.create_pg_interfaces(range(1))
230 for i in self.pg_interfaces:
236 super(TestIPV4IfAddrRoute, self).tearDown()
237 for i in self.pg_interfaces:
241 def test_ipv4_ifaddr_route(self):
242 """ IPv4 Interface Address Route test
247 - Configure IPv4 address on loopback
248 - Verify that address is not in the FIB
250 - Verify that address is in the FIB now
251 - Bring loopback down
252 - Verify that address is not in the FIB anymore
254 - Configure IPv4 address on loopback
255 - Verify that address is in the FIB now
258 # create a loopback and configure IPv4
259 loopbacks = self.create_loopback_interfaces(1)
260 lo_if = self.lo_interfaces[0]
262 lo_if.local_ip4_prefix_len = 32
265 # The intf was down when addr was added -> entry not in FIB
266 fib4_dump = self.vapi.ip_route_dump(0)
267 self.assertFalse(lo_if.is_ip4_entry_in_fib_dump(fib4_dump))
269 # When intf is brought up, entry is added
271 fib4_dump = self.vapi.ip_route_dump(0)
272 self.assertTrue(lo_if.is_ip4_entry_in_fib_dump(fib4_dump))
274 # When intf is brought down, entry is removed
276 fib4_dump = self.vapi.ip_route_dump(0)
277 self.assertFalse(lo_if.is_ip4_entry_in_fib_dump(fib4_dump))
279 # Remove addr, bring up interface, re-add -> entry in FIB
283 fib4_dump = self.vapi.ip_route_dump(0)
284 self.assertTrue(lo_if.is_ip4_entry_in_fib_dump(fib4_dump))
287 class TestICMPEcho(VppTestCase):
288 """ ICMP Echo Test Case """
292 super(TestICMPEcho, cls).setUpClass()
295 def tearDownClass(cls):
296 super(TestICMPEcho, cls).tearDownClass()
299 super(TestICMPEcho, self).setUp()
301 # create 1 pg interface
302 self.create_pg_interfaces(range(1))
304 for i in self.pg_interfaces:
310 super(TestICMPEcho, self).tearDown()
311 for i in self.pg_interfaces:
315 def test_icmp_echo(self):
316 """ VPP replies to ICMP Echo Request
320 - Receive ICMP Echo Request message on pg0 interface.
321 - Check outgoing ICMP Echo Reply message on pg0 interface.
326 icmp_load = '\x0a' * 18
327 p_echo_request = (Ether(src=self.pg0.remote_mac,
328 dst=self.pg0.local_mac) /
329 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
330 ICMP(id=icmp_id, seq=icmp_seq) /
333 self.pg0.add_stream(p_echo_request)
334 self.pg_enable_capture(self.pg_interfaces)
337 rx = self.pg0.get_capture(1)
343 self.assertEqual(ether.src, self.pg0.local_mac)
344 self.assertEqual(ether.dst, self.pg0.remote_mac)
346 self.assertEqual(ipv4.src, self.pg0.local_ip4)
347 self.assertEqual(ipv4.dst, self.pg0.remote_ip4)
349 self.assertEqual(icmptypes[icmp.type], "echo-reply")
350 self.assertEqual(icmp.id, icmp_id)
351 self.assertEqual(icmp.seq, icmp_seq)
352 self.assertEqual(icmp[Raw].load, icmp_load)
355 class TestIPv4FibCrud(VppTestCase):
356 """ FIB - add/update/delete - ip4 routes
364 ..note:: Python API is too slow to add many routes, needs replacement.
367 def config_fib_many_to_one(self, start_dest_addr, next_hop_addr,
371 :param start_dest_addr:
372 :param next_hop_addr:
374 :return list: added ips with 32 prefix
377 for i in range(count):
378 r = VppIpRoute(self, start_dest_addr % (i + start), 32,
379 [VppRoutePath(next_hop_addr, 0xffffffff)])
384 def unconfig_fib_many_to_one(self, start_dest_addr, next_hop_addr,
388 for i in range(count):
389 r = VppIpRoute(self, start_dest_addr % (i + start), 32,
390 [VppRoutePath(next_hop_addr, 0xffffffff)])
391 r.remove_vpp_config()
395 def create_stream(self, src_if, dst_if, routes, count):
398 for _ in range(count):
399 dst_addr = random.choice(routes).prefix.address
400 info = self.create_packet_info(src_if, dst_if)
401 payload = self.info_to_payload(info)
402 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
403 IP(src=src_if.remote_ip4, dst=dst_addr) /
404 UDP(sport=1234, dport=1234) /
407 self.extend_packet(p, random.choice(self.pg_if_packet_sizes))
412 def _find_ip_match(self, find_in, pkt):
414 if self.payload_to_info(p[Raw]) == \
415 self.payload_to_info(pkt[Raw]):
416 if p[IP].src != pkt[IP].src:
418 if p[IP].dst != pkt[IP].dst:
420 if p[UDP].sport != pkt[UDP].sport:
422 if p[UDP].dport != pkt[UDP].dport:
427 def verify_capture(self, dst_interface, received_pkts, expected_pkts):
428 self.assertEqual(len(received_pkts), len(expected_pkts))
429 to_verify = list(expected_pkts)
430 for p in received_pkts:
431 self.assertEqual(p.src, dst_interface.local_mac)
432 self.assertEqual(p.dst, dst_interface.remote_mac)
433 x = self._find_ip_match(to_verify, p)
435 self.assertListEqual(to_verify, [])
437 def verify_route_dump(self, routes):
439 self.assertTrue(find_route(self, r.prefix.address, r.prefix.len))
441 def verify_not_in_route_dump(self, routes):
443 self.assertFalse(find_route(self, r.prefix.address, r.prefix.len))
448 #. Create and initialize 3 pg interfaces.
449 #. initialize class attributes configured_routes and deleted_routes
450 to store information between tests.
452 super(TestIPv4FibCrud, cls).setUpClass()
455 # create 3 pg interfaces
456 cls.create_pg_interfaces(range(3))
458 cls.interfaces = list(cls.pg_interfaces)
460 # setup all interfaces
461 for i in cls.interfaces:
466 cls.configured_routes = []
467 cls.deleted_routes = []
468 cls.pg_if_packet_sizes = [64, 512, 1518, 9018]
471 super(TestIPv4FibCrud, cls).tearDownClass()
475 def tearDownClass(cls):
476 super(TestIPv4FibCrud, cls).tearDownClass()
479 super(TestIPv4FibCrud, self).setUp()
480 self.reset_packet_infos()
482 self.configured_routes = []
483 self.deleted_routes = []
485 def test_1_add_routes(self):
486 """ Add 1k routes """
488 # add 100 routes check with traffic script.
489 self.configured_routes.extend(self.config_fib_many_to_one(
490 "10.0.0.%d", self.pg0.remote_ip4, 100))
492 self.verify_route_dump(self.configured_routes)
494 self.stream_1 = self.create_stream(
495 self.pg1, self.pg0, self.configured_routes, 100)
496 self.stream_2 = self.create_stream(
497 self.pg2, self.pg0, self.configured_routes, 100)
498 self.pg1.add_stream(self.stream_1)
499 self.pg2.add_stream(self.stream_2)
501 self.pg_enable_capture(self.pg_interfaces)
504 pkts = self.pg0.get_capture(len(self.stream_1) + len(self.stream_2))
505 self.verify_capture(self.pg0, pkts, self.stream_1 + self.stream_2)
507 def test_2_del_routes(self):
508 """ Delete 100 routes
510 - delete 10 routes check with traffic script.
512 # config 1M FIB entries
513 self.configured_routes.extend(self.config_fib_many_to_one(
514 "10.0.0.%d", self.pg0.remote_ip4, 100))
515 self.deleted_routes.extend(self.unconfig_fib_many_to_one(
516 "10.0.0.%d", self.pg0.remote_ip4, 10, start=10))
517 for x in self.deleted_routes:
518 self.configured_routes.remove(x)
520 self.verify_route_dump(self.configured_routes)
522 self.stream_1 = self.create_stream(
523 self.pg1, self.pg0, self.configured_routes, 100)
524 self.stream_2 = self.create_stream(
525 self.pg2, self.pg0, self.configured_routes, 100)
526 self.stream_3 = self.create_stream(
527 self.pg1, self.pg0, self.deleted_routes, 100)
528 self.stream_4 = self.create_stream(
529 self.pg2, self.pg0, self.deleted_routes, 100)
530 self.pg1.add_stream(self.stream_1 + self.stream_3)
531 self.pg2.add_stream(self.stream_2 + self.stream_4)
532 self.pg_enable_capture(self.pg_interfaces)
535 pkts = self.pg0.get_capture(len(self.stream_1) + len(self.stream_2))
536 self.verify_capture(self.pg0, pkts, self.stream_1 + self.stream_2)
538 def test_3_add_new_routes(self):
541 - re-add 5 routes check with traffic script.
542 - add 100 routes check with traffic script.
544 # config 1M FIB entries
545 self.configured_routes.extend(self.config_fib_many_to_one(
546 "10.0.0.%d", self.pg0.remote_ip4, 100))
547 self.deleted_routes.extend(self.unconfig_fib_many_to_one(
548 "10.0.0.%d", self.pg0.remote_ip4, 10, start=10))
549 for x in self.deleted_routes:
550 self.configured_routes.remove(x)
552 tmp = self.config_fib_many_to_one(
553 "10.0.0.%d", self.pg0.remote_ip4, 5, start=10)
554 self.configured_routes.extend(tmp)
556 self.deleted_routes.remove(x)
558 self.configured_routes.extend(self.config_fib_many_to_one(
559 "10.0.1.%d", self.pg0.remote_ip4, 100))
561 self.verify_route_dump(self.configured_routes)
563 self.stream_1 = self.create_stream(
564 self.pg1, self.pg0, self.configured_routes, 300)
565 self.stream_2 = self.create_stream(
566 self.pg2, self.pg0, self.configured_routes, 300)
567 self.stream_3 = self.create_stream(
568 self.pg1, self.pg0, self.deleted_routes, 100)
569 self.stream_4 = self.create_stream(
570 self.pg2, self.pg0, self.deleted_routes, 100)
572 self.pg1.add_stream(self.stream_1 + self.stream_3)
573 self.pg2.add_stream(self.stream_2 + self.stream_4)
574 self.pg_enable_capture(self.pg_interfaces)
577 pkts = self.pg0.get_capture(len(self.stream_1) + len(self.stream_2))
578 self.verify_capture(self.pg0, pkts, self.stream_1 + self.stream_2)
580 # delete 5 routes check with traffic script.
581 # add 100 routes check with traffic script.
582 self.deleted_routes.extend(self.unconfig_fib_many_to_one(
583 "10.0.0.%d", self.pg0.remote_ip4, 15))
584 self.deleted_routes.extend(self.unconfig_fib_many_to_one(
585 "10.0.0.%d", self.pg0.remote_ip4, 85))
586 self.deleted_routes.extend(self.unconfig_fib_many_to_one(
587 "10.0.1.%d", self.pg0.remote_ip4, 100))
588 self.verify_not_in_route_dump(self.deleted_routes)
591 class TestIPNull(VppTestCase):
592 """ IPv4 routes via NULL """
596 super(TestIPNull, cls).setUpClass()
599 def tearDownClass(cls):
600 super(TestIPNull, cls).tearDownClass()
603 super(TestIPNull, self).setUp()
605 # create 2 pg interfaces
606 self.create_pg_interfaces(range(2))
608 for i in self.pg_interfaces:
614 super(TestIPNull, self).tearDown()
615 for i in self.pg_interfaces:
619 def test_ip_null(self):
620 """ IP NULL route """
623 # A route via IP NULL that will reply with ICMP unreachables
625 ip_unreach = VppIpRoute(
626 self, "10.0.0.1", 32,
627 [VppRoutePath("0.0.0.0",
629 type=FibPathType.FIB_PATH_TYPE_ICMP_UNREACH)])
630 ip_unreach.add_vpp_config()
632 p_unreach = (Ether(src=self.pg0.remote_mac,
633 dst=self.pg0.local_mac) /
634 IP(src=self.pg0.remote_ip4, dst="10.0.0.1") /
635 UDP(sport=1234, dport=1234) /
637 self.pg0.add_stream(p_unreach)
638 self.pg_enable_capture(self.pg_interfaces)
641 rx = self.pg0.get_capture(1)
645 self.assertEqual(icmptypes[icmp.type], "dest-unreach")
646 self.assertEqual(icmpcodes[icmp.type][icmp.code], "host-unreachable")
647 self.assertEqual(icmp.src, self.pg0.remote_ip4)
648 self.assertEqual(icmp.dst, "10.0.0.1")
651 # ICMP replies are rate limited. so sit and spin.
656 # A route via IP NULL that will reply with ICMP prohibited
658 ip_prohibit = VppIpRoute(
659 self, "10.0.0.2", 32,
660 [VppRoutePath("0.0.0.0",
662 type=FibPathType.FIB_PATH_TYPE_ICMP_PROHIBIT)])
663 ip_prohibit.add_vpp_config()
665 p_prohibit = (Ether(src=self.pg0.remote_mac,
666 dst=self.pg0.local_mac) /
667 IP(src=self.pg0.remote_ip4, dst="10.0.0.2") /
668 UDP(sport=1234, dport=1234) /
671 self.pg0.add_stream(p_prohibit)
672 self.pg_enable_capture(self.pg_interfaces)
675 rx = self.pg0.get_capture(1)
680 self.assertEqual(icmptypes[icmp.type], "dest-unreach")
681 self.assertEqual(icmpcodes[icmp.type][icmp.code], "host-prohibited")
682 self.assertEqual(icmp.src, self.pg0.remote_ip4)
683 self.assertEqual(icmp.dst, "10.0.0.2")
685 def test_ip_drop(self):
686 """ IP Drop Routes """
688 p = (Ether(src=self.pg0.remote_mac,
689 dst=self.pg0.local_mac) /
690 IP(src=self.pg0.remote_ip4, dst="1.1.1.1") /
691 UDP(sport=1234, dport=1234) /
694 r1 = VppIpRoute(self, "1.1.1.0", 24,
695 [VppRoutePath(self.pg1.remote_ip4,
696 self.pg1.sw_if_index)])
699 rx = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1)
702 # insert a more specific as a drop
704 r2 = VppIpRoute(self, "1.1.1.1", 32,
705 [VppRoutePath("0.0.0.0",
707 type=FibPathType.FIB_PATH_TYPE_DROP)])
710 self.send_and_assert_no_replies(self.pg0, p * NUM_PKTS, "Drop Route")
711 r2.remove_vpp_config()
712 rx = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1)
715 class TestIPDisabled(VppTestCase):
716 """ IPv4 disabled """
720 super(TestIPDisabled, cls).setUpClass()
723 def tearDownClass(cls):
724 super(TestIPDisabled, cls).tearDownClass()
727 super(TestIPDisabled, self).setUp()
729 # create 2 pg interfaces
730 self.create_pg_interfaces(range(2))
734 self.pg0.config_ip4()
735 self.pg0.resolve_arp()
737 # PG 1 is not IP enabled
741 super(TestIPDisabled, self).tearDown()
742 for i in self.pg_interfaces:
746 def test_ip_disabled(self):
751 # one accepting interface, pg0, 2 forwarding interfaces
753 route_232_1_1_1 = VppIpMRoute(
757 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
758 [VppMRoutePath(self.pg1.sw_if_index,
759 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
760 VppMRoutePath(self.pg0.sw_if_index,
761 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
762 route_232_1_1_1.add_vpp_config()
764 pu = (Ether(src=self.pg1.remote_mac,
765 dst=self.pg1.local_mac) /
766 IP(src="10.10.10.10", dst=self.pg0.remote_ip4) /
767 UDP(sport=1234, dport=1234) /
769 pm = (Ether(src=self.pg1.remote_mac,
770 dst=self.pg1.local_mac) /
771 IP(src="10.10.10.10", dst="232.1.1.1") /
772 UDP(sport=1234, dport=1234) /
776 # PG1 does not forward IP traffic
778 self.send_and_assert_no_replies(self.pg1, pu, "IP disabled")
779 self.send_and_assert_no_replies(self.pg1, pm, "IP disabled")
784 self.pg1.config_ip4()
787 # Now we get packets through
789 self.pg1.add_stream(pu)
790 self.pg_enable_capture(self.pg_interfaces)
792 rx = self.pg0.get_capture(1)
794 self.pg1.add_stream(pm)
795 self.pg_enable_capture(self.pg_interfaces)
797 rx = self.pg0.get_capture(1)
802 self.pg1.unconfig_ip4()
805 # PG1 does not forward IP traffic
807 self.send_and_assert_no_replies(self.pg1, pu, "IP disabled")
808 self.send_and_assert_no_replies(self.pg1, pm, "IP disabled")
811 class TestIPSubNets(VppTestCase):
816 super(TestIPSubNets, cls).setUpClass()
819 def tearDownClass(cls):
820 super(TestIPSubNets, cls).tearDownClass()
823 super(TestIPSubNets, self).setUp()
825 # create a 2 pg interfaces
826 self.create_pg_interfaces(range(2))
828 # pg0 we will use to experiment
831 # pg1 is setup normally
833 self.pg1.config_ip4()
834 self.pg1.resolve_arp()
837 super(TestIPSubNets, self).tearDown()
838 for i in self.pg_interfaces:
841 def test_ip_sub_nets(self):
845 # Configure a covering route to forward so we know
846 # when we are dropping
848 cover_route = VppIpRoute(self, "10.0.0.0", 8,
849 [VppRoutePath(self.pg1.remote_ip4,
850 self.pg1.sw_if_index)])
851 cover_route.add_vpp_config()
853 p = (Ether(src=self.pg1.remote_mac,
854 dst=self.pg1.local_mac) /
855 IP(dst="10.10.10.10", src=self.pg0.local_ip4) /
856 UDP(sport=1234, dport=1234) /
859 self.pg1.add_stream(p)
860 self.pg_enable_capture(self.pg_interfaces)
862 rx = self.pg1.get_capture(1)
865 # Configure some non-/24 subnets on an IP interface
867 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.10.10.10")
869 self.vapi.sw_interface_add_del_address(
870 sw_if_index=self.pg0.sw_if_index, address=ip_addr_n,
873 pn = (Ether(src=self.pg1.remote_mac,
874 dst=self.pg1.local_mac) /
875 IP(dst="10.10.0.0", src=self.pg0.local_ip4) /
876 UDP(sport=1234, dport=1234) /
878 pb = (Ether(src=self.pg1.remote_mac,
879 dst=self.pg1.local_mac) /
880 IP(dst="10.10.255.255", src=self.pg0.local_ip4) /
881 UDP(sport=1234, dport=1234) /
884 self.send_and_assert_no_replies(self.pg1, pn, "IP Network address")
885 self.send_and_assert_no_replies(self.pg1, pb, "IP Broadcast address")
887 # remove the sub-net and we are forwarding via the cover again
888 self.vapi.sw_interface_add_del_address(
889 sw_if_index=self.pg0.sw_if_index, address=ip_addr_n,
890 address_length=16, is_add=0)
891 self.pg1.add_stream(pn)
892 self.pg_enable_capture(self.pg_interfaces)
894 rx = self.pg1.get_capture(1)
895 self.pg1.add_stream(pb)
896 self.pg_enable_capture(self.pg_interfaces)
898 rx = self.pg1.get_capture(1)
901 # A /31 is a special case where the 'other-side' is an attached host
902 # packets to that peer generate ARP requests
904 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.10.10.10")
906 self.vapi.sw_interface_add_del_address(
907 sw_if_index=self.pg0.sw_if_index, address=ip_addr_n,
910 pn = (Ether(src=self.pg1.remote_mac,
911 dst=self.pg1.local_mac) /
912 IP(dst="10.10.10.11", src=self.pg0.local_ip4) /
913 UDP(sport=1234, dport=1234) /
916 self.pg1.add_stream(pn)
917 self.pg_enable_capture(self.pg_interfaces)
919 rx = self.pg0.get_capture(1)
922 # remove the sub-net and we are forwarding via the cover again
923 self.vapi.sw_interface_add_del_address(
924 sw_if_index=self.pg0.sw_if_index, address=ip_addr_n,
925 address_length=31, is_add=0)
926 self.pg1.add_stream(pn)
927 self.pg_enable_capture(self.pg_interfaces)
929 rx = self.pg1.get_capture(1)
932 class TestIPLoadBalance(VppTestCase):
933 """ IPv4 Load-Balancing """
937 super(TestIPLoadBalance, cls).setUpClass()
940 def tearDownClass(cls):
941 super(TestIPLoadBalance, cls).tearDownClass()
944 super(TestIPLoadBalance, self).setUp()
946 self.create_pg_interfaces(range(5))
947 mpls_tbl = VppMplsTable(self, 0)
948 mpls_tbl.add_vpp_config()
950 for i in self.pg_interfaces:
957 for i in self.pg_interfaces:
961 super(TestIPLoadBalance, self).tearDown()
963 def send_and_expect_load_balancing(self, input, pkts, outputs):
964 input.add_stream(pkts)
965 self.pg_enable_capture(self.pg_interfaces)
969 rx = oo._get_capture(1)
970 self.assertNotEqual(0, len(rx))
975 def send_and_expect_one_itf(self, input, pkts, itf):
976 input.add_stream(pkts)
977 self.pg_enable_capture(self.pg_interfaces)
979 rx = itf.get_capture(len(pkts))
981 def test_ip_load_balance(self):
982 """ IP Load-Balancing """
985 # An array of packets that differ only in the destination port
991 # An array of packets that differ only in the source address
996 for ii in range(NUM_PKTS):
997 port_ip_hdr = (IP(dst="10.0.0.1", src="20.0.0.1") /
998 UDP(sport=1234, dport=1234 + ii) /
1000 port_ip_pkts.append((Ether(src=self.pg0.remote_mac,
1001 dst=self.pg0.local_mac) /
1003 port_mpls_pkts.append((Ether(src=self.pg0.remote_mac,
1004 dst=self.pg0.local_mac) /
1005 MPLS(label=66, ttl=2) /
1008 src_ip_hdr = (IP(dst="10.0.0.1", src="20.0.0.%d" % ii) /
1009 UDP(sport=1234, dport=1234) /
1011 src_ip_pkts.append((Ether(src=self.pg0.remote_mac,
1012 dst=self.pg0.local_mac) /
1014 src_mpls_pkts.append((Ether(src=self.pg0.remote_mac,
1015 dst=self.pg0.local_mac) /
1016 MPLS(label=66, ttl=2) /
1019 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1020 [VppRoutePath(self.pg1.remote_ip4,
1021 self.pg1.sw_if_index),
1022 VppRoutePath(self.pg2.remote_ip4,
1023 self.pg2.sw_if_index)])
1024 route_10_0_0_1.add_vpp_config()
1026 binding = VppMplsIpBind(self, 66, "10.0.0.1", 32)
1027 binding.add_vpp_config()
1030 # inject the packet on pg0 - expect load-balancing across the 2 paths
1031 # - since the default hash config is to use IP src,dst and port
1033 # We are not going to ensure equal amounts of packets across each link,
1034 # since the hash algorithm is statistical and therefore this can never
1035 # be guaranteed. But with 64 different packets we do expect some
1036 # balancing. So instead just ensure there is traffic on each link.
1038 self.send_and_expect_load_balancing(self.pg0, port_ip_pkts,
1039 [self.pg1, self.pg2])
1040 self.send_and_expect_load_balancing(self.pg0, src_ip_pkts,
1041 [self.pg1, self.pg2])
1042 self.send_and_expect_load_balancing(self.pg0, port_mpls_pkts,
1043 [self.pg1, self.pg2])
1044 self.send_and_expect_load_balancing(self.pg0, src_mpls_pkts,
1045 [self.pg1, self.pg2])
1048 # change the flow hash config so it's only IP src,dst
1049 # - now only the stream with differing source address will
1052 self.vapi.set_ip_flow_hash(vrf_id=0, src=1, dst=1, sport=0, dport=0)
1054 self.send_and_expect_load_balancing(self.pg0, src_ip_pkts,
1055 [self.pg1, self.pg2])
1056 self.send_and_expect_load_balancing(self.pg0, src_mpls_pkts,
1057 [self.pg1, self.pg2])
1059 self.send_and_expect_one_itf(self.pg0, port_ip_pkts, self.pg2)
1062 # change the flow hash config back to defaults
1064 self.vapi.set_ip_flow_hash(vrf_id=0, src=1, dst=1, sport=1, dport=1)
1067 # Recursive prefixes
1068 # - testing that 2 stages of load-balancing occurs and there is no
1069 # polarisation (i.e. only 2 of 4 paths are used)
1074 for ii in range(257):
1075 port_pkts.append((Ether(src=self.pg0.remote_mac,
1076 dst=self.pg0.local_mac) /
1077 IP(dst="1.1.1.1", src="20.0.0.1") /
1078 UDP(sport=1234, dport=1234 + ii) /
1080 src_pkts.append((Ether(src=self.pg0.remote_mac,
1081 dst=self.pg0.local_mac) /
1082 IP(dst="1.1.1.1", src="20.0.0.%d" % ii) /
1083 UDP(sport=1234, dport=1234) /
1086 route_10_0_0_2 = VppIpRoute(self, "10.0.0.2", 32,
1087 [VppRoutePath(self.pg3.remote_ip4,
1088 self.pg3.sw_if_index),
1089 VppRoutePath(self.pg4.remote_ip4,
1090 self.pg4.sw_if_index)])
1091 route_10_0_0_2.add_vpp_config()
1093 route_1_1_1_1 = VppIpRoute(self, "1.1.1.1", 32,
1094 [VppRoutePath("10.0.0.2", 0xffffffff),
1095 VppRoutePath("10.0.0.1", 0xffffffff)])
1096 route_1_1_1_1.add_vpp_config()
1099 # inject the packet on pg0 - expect load-balancing across all 4 paths
1101 self.vapi.cli("clear trace")
1102 self.send_and_expect_load_balancing(self.pg0, port_pkts,
1103 [self.pg1, self.pg2,
1104 self.pg3, self.pg4])
1105 self.send_and_expect_load_balancing(self.pg0, src_pkts,
1106 [self.pg1, self.pg2,
1107 self.pg3, self.pg4])
1110 # bring down pg1 expect LB to adjust to use only those that are pu
1112 self.pg1.link_down()
1114 rx = self.send_and_expect_load_balancing(self.pg0, src_pkts,
1115 [self.pg2, self.pg3,
1117 self.assertEqual(len(src_pkts), len(rx))
1120 # bring down pg2 expect LB to adjust to use only those that are pu
1122 self.pg2.link_down()
1124 rx = self.send_and_expect_load_balancing(self.pg0, src_pkts,
1125 [self.pg3, self.pg4])
1126 self.assertEqual(len(src_pkts), len(rx))
1129 # bring the links back up - expect LB over all again
1134 rx = self.send_and_expect_load_balancing(self.pg0, src_pkts,
1135 [self.pg1, self.pg2,
1136 self.pg3, self.pg4])
1137 self.assertEqual(len(src_pkts), len(rx))
1140 # The same link-up/down but this time admin state
1142 self.pg1.admin_down()
1143 self.pg2.admin_down()
1144 rx = self.send_and_expect_load_balancing(self.pg0, src_pkts,
1145 [self.pg3, self.pg4])
1146 self.assertEqual(len(src_pkts), len(rx))
1149 self.pg1.resolve_arp()
1150 self.pg2.resolve_arp()
1151 rx = self.send_and_expect_load_balancing(self.pg0, src_pkts,
1152 [self.pg1, self.pg2,
1153 self.pg3, self.pg4])
1154 self.assertEqual(len(src_pkts), len(rx))
1157 # Recursive prefixes
1158 # - testing that 2 stages of load-balancing, no choices
1162 for ii in range(257):
1163 port_pkts.append((Ether(src=self.pg0.remote_mac,
1164 dst=self.pg0.local_mac) /
1165 IP(dst="1.1.1.2", src="20.0.0.2") /
1166 UDP(sport=1234, dport=1234 + ii) /
1169 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
1170 [VppRoutePath(self.pg3.remote_ip4,
1171 self.pg3.sw_if_index)])
1172 route_10_0_0_3.add_vpp_config()
1174 route_1_1_1_2 = VppIpRoute(self, "1.1.1.2", 32,
1175 [VppRoutePath("10.0.0.3", 0xffffffff)])
1176 route_1_1_1_2.add_vpp_config()
1179 # inject the packet on pg0 - rx only on via routes output interface
1181 self.vapi.cli("clear trace")
1182 self.send_and_expect_one_itf(self.pg0, port_pkts, self.pg3)
1185 # Add a LB route in the presence of a down link - expect no
1186 # packets over the down link
1188 self.pg3.link_down()
1190 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
1191 [VppRoutePath(self.pg3.remote_ip4,
1192 self.pg3.sw_if_index),
1193 VppRoutePath(self.pg4.remote_ip4,
1194 self.pg4.sw_if_index)])
1195 route_10_0_0_3.add_vpp_config()
1198 for ii in range(257):
1199 port_pkts.append(Ether(src=self.pg0.remote_mac,
1200 dst=self.pg0.local_mac) /
1201 IP(dst="10.0.0.3", src="20.0.0.2") /
1202 UDP(sport=1234, dport=1234 + ii) /
1205 self.send_and_expect_one_itf(self.pg0, port_pkts, self.pg4)
1207 # bring the link back up
1210 rx = self.send_and_expect_load_balancing(self.pg0, port_pkts,
1211 [self.pg3, self.pg4])
1212 self.assertEqual(len(src_pkts), len(rx))
1215 class TestIPVlan0(VppTestCase):
1219 def setUpClass(cls):
1220 super(TestIPVlan0, cls).setUpClass()
1223 def tearDownClass(cls):
1224 super(TestIPVlan0, cls).tearDownClass()
1227 super(TestIPVlan0, self).setUp()
1229 self.create_pg_interfaces(range(2))
1230 mpls_tbl = VppMplsTable(self, 0)
1231 mpls_tbl.add_vpp_config()
1233 for i in self.pg_interfaces:
1240 for i in self.pg_interfaces:
1244 super(TestIPVlan0, self).tearDown()
1246 def test_ip_vlan_0(self):
1249 pkts = (Ether(src=self.pg0.remote_mac,
1250 dst=self.pg0.local_mac) /
1252 IP(dst=self.pg1.remote_ip4,
1253 src=self.pg0.remote_ip4) /
1254 UDP(sport=1234, dport=1234) /
1255 Raw('\xa5' * 100)) * NUM_PKTS
1258 # Expect that packets sent on VLAN-0 are forwarded on the
1261 self.send_and_expect(self.pg0, pkts, self.pg1)
1264 class TestIPPunt(VppTestCase):
1265 """ IPv4 Punt Police/Redirect """
1268 def setUpClass(cls):
1269 super(TestIPPunt, cls).setUpClass()
1272 def tearDownClass(cls):
1273 super(TestIPPunt, cls).tearDownClass()
1276 super(TestIPPunt, self).setUp()
1278 self.create_pg_interfaces(range(4))
1280 for i in self.pg_interfaces:
1286 super(TestIPPunt, self).tearDown()
1287 for i in self.pg_interfaces:
1291 def test_ip_punt(self):
1292 """ IP punt police and redirect """
1294 # use UDP packet that have a port we need to explicitly
1295 # register to get punted.
1296 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
1297 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
1298 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
1304 'protocol': udp_proto,
1310 self.vapi.set_punt(is_add=1, punt=punt_udp)
1312 p = (Ether(src=self.pg0.remote_mac,
1313 dst=self.pg0.local_mac) /
1314 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
1315 UDP(sport=1234, dport=1234) /
1321 # Configure a punt redirect via pg1.
1323 nh_addr = self.pg1.remote_ip4
1324 self.vapi.ip_punt_redirect(self.pg0.sw_if_index,
1325 self.pg1.sw_if_index,
1328 self.send_and_expect(self.pg0, pkts, self.pg1)
1333 policer = self.vapi.policer_add_del(b"ip4-punt", 400, 0, 10, 0,
1335 self.vapi.ip_punt_police(policer.policer_index)
1337 self.vapi.cli("clear trace")
1338 self.pg0.add_stream(pkts)
1339 self.pg_enable_capture(self.pg_interfaces)
1343 # the number of packet received should be greater than 0,
1344 # but not equal to the number sent, since some were policed
1346 rx = self.pg1._get_capture(1)
1347 self.assertGreater(len(rx), 0)
1348 self.assertLess(len(rx), len(pkts))
1351 # remove the policer. back to full rx
1353 self.vapi.ip_punt_police(policer.policer_index, is_add=0)
1354 self.vapi.policer_add_del(b"ip4-punt", 400, 0, 10, 0,
1355 rate_type=1, is_add=0)
1356 self.send_and_expect(self.pg0, pkts, self.pg1)
1359 # remove the redirect. expect full drop.
1361 self.vapi.ip_punt_redirect(self.pg0.sw_if_index,
1362 self.pg1.sw_if_index,
1365 self.send_and_assert_no_replies(self.pg0, pkts,
1366 "IP no punt config")
1369 # Add a redirect that is not input port selective
1371 self.vapi.ip_punt_redirect(0xffffffff,
1372 self.pg1.sw_if_index,
1374 self.send_and_expect(self.pg0, pkts, self.pg1)
1376 self.vapi.ip_punt_redirect(0xffffffff,
1377 self.pg1.sw_if_index,
1381 def test_ip_punt_dump(self):
1382 """ IP4 punt redirect dump"""
1385 # Configure a punt redirects
1387 nh_address = self.pg3.remote_ip4
1388 self.vapi.ip_punt_redirect(self.pg0.sw_if_index,
1389 self.pg3.sw_if_index,
1391 self.vapi.ip_punt_redirect(self.pg1.sw_if_index,
1392 self.pg3.sw_if_index,
1394 self.vapi.ip_punt_redirect(self.pg2.sw_if_index,
1395 self.pg3.sw_if_index,
1399 # Dump pg0 punt redirects
1401 punts = self.vapi.ip_punt_redirect_dump(self.pg0.sw_if_index)
1403 self.assertEqual(p.punt.rx_sw_if_index, self.pg0.sw_if_index)
1406 # Dump punt redirects for all interfaces
1408 punts = self.vapi.ip_punt_redirect_dump(0xffffffff)
1409 self.assertEqual(len(punts), 3)
1411 self.assertEqual(p.punt.tx_sw_if_index, self.pg3.sw_if_index)
1412 self.assertNotEqual(punts[1].punt.nh, self.pg3.remote_ip4)
1413 self.assertEqual(str(punts[2].punt.nh), '0.0.0.0')
1416 class TestIPDeag(VppTestCase):
1417 """ IPv4 Deaggregate Routes """
1420 def setUpClass(cls):
1421 super(TestIPDeag, cls).setUpClass()
1424 def tearDownClass(cls):
1425 super(TestIPDeag, cls).tearDownClass()
1428 super(TestIPDeag, self).setUp()
1430 self.create_pg_interfaces(range(3))
1432 for i in self.pg_interfaces:
1438 super(TestIPDeag, self).tearDown()
1439 for i in self.pg_interfaces:
1443 def test_ip_deag(self):
1444 """ IP Deag Routes """
1447 # Create a table to be used for:
1448 # 1 - another destination address lookup
1449 # 2 - a source address lookup
1451 table_dst = VppIpTable(self, 1)
1452 table_src = VppIpTable(self, 2)
1453 table_dst.add_vpp_config()
1454 table_src.add_vpp_config()
1457 # Add a route in the default table to point to a deag/
1458 # second lookup in each of these tables
1460 route_to_dst = VppIpRoute(self, "1.1.1.1", 32,
1461 [VppRoutePath("0.0.0.0",
1464 route_to_src = VppIpRoute(
1465 self, "1.1.1.2", 32,
1466 [VppRoutePath("0.0.0.0",
1469 type=FibPathType.FIB_PATH_TYPE_SOURCE_LOOKUP)])
1470 route_to_dst.add_vpp_config()
1471 route_to_src.add_vpp_config()
1474 # packets to these destination are dropped, since they'll
1475 # hit the respective default routes in the second table
1477 p_dst = (Ether(src=self.pg0.remote_mac,
1478 dst=self.pg0.local_mac) /
1479 IP(src="5.5.5.5", dst="1.1.1.1") /
1480 TCP(sport=1234, dport=1234) /
1482 p_src = (Ether(src=self.pg0.remote_mac,
1483 dst=self.pg0.local_mac) /
1484 IP(src="2.2.2.2", dst="1.1.1.2") /
1485 TCP(sport=1234, dport=1234) /
1487 pkts_dst = p_dst * 257
1488 pkts_src = p_src * 257
1490 self.send_and_assert_no_replies(self.pg0, pkts_dst,
1492 self.send_and_assert_no_replies(self.pg0, pkts_src,
1496 # add a route in the dst table to forward via pg1
1498 route_in_dst = VppIpRoute(self, "1.1.1.1", 32,
1499 [VppRoutePath(self.pg1.remote_ip4,
1500 self.pg1.sw_if_index)],
1502 route_in_dst.add_vpp_config()
1504 self.send_and_expect(self.pg0, pkts_dst, self.pg1)
1507 # add a route in the src table to forward via pg2
1509 route_in_src = VppIpRoute(self, "2.2.2.2", 32,
1510 [VppRoutePath(self.pg2.remote_ip4,
1511 self.pg2.sw_if_index)],
1513 route_in_src.add_vpp_config()
1514 self.send_and_expect(self.pg0, pkts_src, self.pg2)
1517 # loop in the lookup DP
1519 route_loop = VppIpRoute(self, "2.2.2.3", 32,
1520 [VppRoutePath("0.0.0.0",
1523 route_loop.add_vpp_config()
1525 p_l = (Ether(src=self.pg0.remote_mac,
1526 dst=self.pg0.local_mac) /
1527 IP(src="2.2.2.4", dst="2.2.2.3") /
1528 TCP(sport=1234, dport=1234) /
1531 self.send_and_assert_no_replies(self.pg0, p_l * 257,
1535 class TestIPInput(VppTestCase):
1536 """ IPv4 Input Exceptions """
1539 def setUpClass(cls):
1540 super(TestIPInput, cls).setUpClass()
1543 def tearDownClass(cls):
1544 super(TestIPInput, cls).tearDownClass()
1547 super(TestIPInput, self).setUp()
1549 self.create_pg_interfaces(range(2))
1551 for i in self.pg_interfaces:
1557 super(TestIPInput, self).tearDown()
1558 for i in self.pg_interfaces:
1562 def test_ip_input(self):
1563 """ IP Input Exceptions """
1565 # i can't find a way in scapy to construct an IP packet
1566 # with a length less than the IP header length
1569 # Packet too short - this is forwarded
1571 p_short = (Ether(src=self.pg0.remote_mac,
1572 dst=self.pg0.local_mac) /
1573 IP(src=self.pg0.remote_ip4,
1574 dst=self.pg1.remote_ip4,
1576 UDP(sport=1234, dport=1234) /
1579 rx = self.send_and_expect(self.pg0, p_short * NUM_PKTS, self.pg1)
1582 # Packet too long - this is dropped
1584 p_long = (Ether(src=self.pg0.remote_mac,
1585 dst=self.pg0.local_mac) /
1586 IP(src=self.pg0.remote_ip4,
1587 dst=self.pg1.remote_ip4,
1589 UDP(sport=1234, dport=1234) /
1592 rx = self.send_and_assert_no_replies(self.pg0, p_long * NUM_PKTS,
1596 # bad chksum - this is dropped
1598 p_chksum = (Ether(src=self.pg0.remote_mac,
1599 dst=self.pg0.local_mac) /
1600 IP(src=self.pg0.remote_ip4,
1601 dst=self.pg1.remote_ip4,
1603 UDP(sport=1234, dport=1234) /
1606 rx = self.send_and_assert_no_replies(self.pg0, p_chksum * NUM_PKTS,
1610 # bad version - this is dropped
1612 p_ver = (Ether(src=self.pg0.remote_mac,
1613 dst=self.pg0.local_mac) /
1614 IP(src=self.pg0.remote_ip4,
1615 dst=self.pg1.remote_ip4,
1617 UDP(sport=1234, dport=1234) /
1620 rx = self.send_and_assert_no_replies(self.pg0, p_ver * NUM_PKTS,
1624 # fragment offset 1 - this is dropped
1626 p_frag = (Ether(src=self.pg0.remote_mac,
1627 dst=self.pg0.local_mac) /
1628 IP(src=self.pg0.remote_ip4,
1629 dst=self.pg1.remote_ip4,
1631 UDP(sport=1234, dport=1234) /
1634 rx = self.send_and_assert_no_replies(self.pg0, p_frag * NUM_PKTS,
1638 # TTL expired packet
1640 p_ttl = (Ether(src=self.pg0.remote_mac,
1641 dst=self.pg0.local_mac) /
1642 IP(src=self.pg0.remote_ip4,
1643 dst=self.pg1.remote_ip4,
1645 UDP(sport=1234, dport=1234) /
1648 rx = self.send_and_expect(self.pg0, p_ttl * NUM_PKTS, self.pg0)
1653 self.assertEqual(icmptypes[icmp.type], "time-exceeded")
1654 self.assertEqual(icmpcodes[icmp.type][icmp.code],
1655 "ttl-zero-during-transit")
1656 self.assertEqual(icmp.src, self.pg0.remote_ip4)
1657 self.assertEqual(icmp.dst, self.pg1.remote_ip4)
1662 p_mtu = (Ether(src=self.pg0.remote_mac,
1663 dst=self.pg0.local_mac) /
1664 IP(src=self.pg0.remote_ip4,
1665 dst=self.pg1.remote_ip4,
1666 ttl=10, flags='DF') /
1667 UDP(sport=1234, dport=1234) /
1670 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1500, 0, 0, 0])
1672 rx = self.send_and_expect(self.pg0, p_mtu * NUM_PKTS, self.pg0)
1676 self.assertEqual(icmptypes[icmp.type], "dest-unreach")
1677 self.assertEqual(icmpcodes[icmp.type][icmp.code],
1678 "fragmentation-needed")
1679 self.assertEqual(icmp.src, self.pg0.remote_ip4)
1680 self.assertEqual(icmp.dst, self.pg1.remote_ip4)
1682 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [2500, 0, 0, 0])
1683 rx = self.send_and_expect(self.pg0, p_mtu * NUM_PKTS, self.pg1)
1685 # Reset MTU for subsequent tests
1686 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [9000, 0, 0, 0])
1689 # source address 0.0.0.0 and 25.255.255.255 and for-us
1691 p_s0 = (Ether(src=self.pg0.remote_mac,
1692 dst=self.pg0.local_mac) /
1694 dst=self.pg0.local_ip4) /
1696 Raw(load='\x0a' * 18))
1697 rx = self.send_and_assert_no_replies(self.pg0, p_s0 * 17)
1699 p_s0 = (Ether(src=self.pg0.remote_mac,
1700 dst=self.pg0.local_mac) /
1701 IP(src="255.255.255.255",
1702 dst=self.pg0.local_ip4) /
1704 Raw(load='\x0a' * 18))
1705 rx = self.send_and_assert_no_replies(self.pg0, p_s0 * 17)
1708 class TestIPDirectedBroadcast(VppTestCase):
1709 """ IPv4 Directed Broadcast """
1712 def setUpClass(cls):
1713 super(TestIPDirectedBroadcast, cls).setUpClass()
1716 def tearDownClass(cls):
1717 super(TestIPDirectedBroadcast, cls).tearDownClass()
1720 super(TestIPDirectedBroadcast, self).setUp()
1722 self.create_pg_interfaces(range(2))
1724 for i in self.pg_interfaces:
1728 super(TestIPDirectedBroadcast, self).tearDown()
1729 for i in self.pg_interfaces:
1732 def test_ip_input(self):
1733 """ IP Directed Broadcast """
1736 # set the directed broadcast on pg0 first, then config IP4 addresses
1737 # for pg1 directed broadcast is always disabled
1738 self.vapi.sw_interface_set_ip_directed_broadcast(
1739 self.pg0.sw_if_index, 1)
1741 p0 = (Ether(src=self.pg1.remote_mac,
1742 dst=self.pg1.local_mac) /
1744 dst=self.pg0._local_ip4_bcast) /
1745 UDP(sport=1234, dport=1234) /
1747 p1 = (Ether(src=self.pg0.remote_mac,
1748 dst=self.pg0.local_mac) /
1750 dst=self.pg1._local_ip4_bcast) /
1751 UDP(sport=1234, dport=1234) /
1754 self.pg0.config_ip4()
1755 self.pg0.resolve_arp()
1756 self.pg1.config_ip4()
1757 self.pg1.resolve_arp()
1760 # test packet is L2 broadcast
1762 rx = self.send_and_expect(self.pg1, p0 * NUM_PKTS, self.pg0)
1763 self.assertTrue(rx[0][Ether].dst, "ff:ff:ff:ff:ff:ff")
1765 self.send_and_assert_no_replies(self.pg0, p1 * NUM_PKTS,
1766 "directed broadcast disabled")
1769 # toggle directed broadcast on pg0
1771 self.vapi.sw_interface_set_ip_directed_broadcast(
1772 self.pg0.sw_if_index, 0)
1773 self.send_and_assert_no_replies(self.pg1, p0 * NUM_PKTS,
1774 "directed broadcast disabled")
1776 self.vapi.sw_interface_set_ip_directed_broadcast(
1777 self.pg0.sw_if_index, 1)
1778 rx = self.send_and_expect(self.pg1, p0 * NUM_PKTS, self.pg0)
1780 self.pg0.unconfig_ip4()
1781 self.pg1.unconfig_ip4()
1784 class TestIPLPM(VppTestCase):
1785 """ IPv4 longest Prefix Match """
1788 def setUpClass(cls):
1789 super(TestIPLPM, cls).setUpClass()
1792 def tearDownClass(cls):
1793 super(TestIPLPM, cls).tearDownClass()
1796 super(TestIPLPM, self).setUp()
1798 self.create_pg_interfaces(range(4))
1800 for i in self.pg_interfaces:
1806 super(TestIPLPM, self).tearDown()
1807 for i in self.pg_interfaces:
1811 def test_ip_lpm(self):
1812 """ IP longest Prefix Match """
1814 s_24 = VppIpRoute(self, "10.1.2.0", 24,
1815 [VppRoutePath(self.pg1.remote_ip4,
1816 self.pg1.sw_if_index)])
1817 s_24.add_vpp_config()
1818 s_8 = VppIpRoute(self, "10.0.0.0", 8,
1819 [VppRoutePath(self.pg2.remote_ip4,
1820 self.pg2.sw_if_index)])
1821 s_8.add_vpp_config()
1823 p_8 = (Ether(src=self.pg0.remote_mac,
1824 dst=self.pg0.local_mac) /
1827 UDP(sport=1234, dport=1234) /
1829 p_24 = (Ether(src=self.pg0.remote_mac,
1830 dst=self.pg0.local_mac) /
1833 UDP(sport=1234, dport=1234) /
1836 self.logger.info(self.vapi.cli("sh ip fib mtrie"))
1837 rx = self.send_and_expect(self.pg0, p_8 * NUM_PKTS, self.pg2)
1838 rx = self.send_and_expect(self.pg0, p_24 * NUM_PKTS, self.pg1)
1841 class TestIPv4Frag(VppTestCase):
1842 """ IPv4 fragmentation """
1845 def setUpClass(cls):
1846 super(TestIPv4Frag, cls).setUpClass()
1848 cls.create_pg_interfaces([0, 1])
1849 cls.src_if = cls.pg0
1850 cls.dst_if = cls.pg1
1852 # setup all interfaces
1853 for i in cls.pg_interfaces:
1859 def tearDownClass(cls):
1860 super(TestIPv4Frag, cls).tearDownClass()
1862 def test_frag_large_packets(self):
1863 """ Fragmentation of large packets """
1865 p = (Ether(dst=self.src_if.local_mac, src=self.src_if.remote_mac) /
1866 IP(src=self.src_if.remote_ip4, dst=self.dst_if.remote_ip4) /
1867 UDP(sport=1234, dport=5678) / Raw())
1868 self.extend_packet(p, 6000, "abcde")
1869 saved_payload = p[Raw].load
1871 # Force fragmentation by setting MTU of output interface
1872 # lower than packet size
1873 self.vapi.sw_interface_set_mtu(self.dst_if.sw_if_index,
1876 self.pg_enable_capture()
1877 self.src_if.add_stream(p)
1880 # Expecting 3 fragments because size of created fragments currently
1881 # cannot be larger then VPP buffer size (which is 2048)
1882 packets = self.dst_if.get_capture(3)
1884 # Assume VPP sends the fragments in order
1887 payload_offset = p.frag * 8
1888 if payload_offset > 0:
1889 payload_offset -= 8 # UDP header is not in payload
1890 self.assert_equal(payload_offset, len(payload))
1891 payload += p[Raw].load
1892 self.assert_equal(payload, saved_payload, "payload")
1895 if __name__ == '__main__':
1896 unittest.main(testRunner=VppTestRunner)