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
19 from vpp_sub_interface import VppSubInterface, VppDot1QSubint, VppDot1ADSubint
22 class TestIPv4(VppTestCase):
23 """ IPv4 Test Case """
27 super(TestIPv4, cls).setUpClass()
30 def tearDownClass(cls):
31 super(TestIPv4, cls).tearDownClass()
35 Perform test setup before test case.
38 - create 3 pg interfaces
39 - untagged pg0 interface
40 - Dot1Q subinterface on pg1
41 - Dot1AD subinterface on pg2
43 - put it into UP state
45 - resolve neighbor address using ARP
46 - configure 200 fib entries
48 :ivar list interfaces: pg interfaces and subinterfaces.
49 :ivar dict flows: IPv4 packet flows in test.
51 super(TestIPv4, self).setUp()
53 # create 3 pg interfaces
54 self.create_pg_interfaces(range(3))
56 # create 2 subinterfaces for pg1 and pg2
57 self.sub_interfaces = [
58 VppDot1QSubint(self, self.pg1, 100),
59 VppDot1ADSubint(self, self.pg2, 200, 300, 400)]
61 # packet flows mapping pg0 -> pg1.sub, pg2.sub, etc.
63 self.flows[self.pg0] = [self.pg1.sub_if, self.pg2.sub_if]
64 self.flows[self.pg1.sub_if] = [self.pg0, self.pg2.sub_if]
65 self.flows[self.pg2.sub_if] = [self.pg0, self.pg1.sub_if]
68 self.pg_if_packet_sizes = [64, 1500, 9020]
70 self.interfaces = list(self.pg_interfaces)
71 self.interfaces.extend(self.sub_interfaces)
73 # setup all interfaces
74 for i in self.interfaces:
79 # config 2M FIB entries
80 self.config_fib_entries(200)
83 """Run standard test teardown and log ``show ip arp``."""
84 super(TestIPv4, self).tearDown()
86 self.logger.info(self.vapi.cli("show ip arp"))
87 # info(self.vapi.cli("show ip fib")) # many entries
89 def config_fib_entries(self, count):
90 """For each interface add to the FIB table *count* routes to
91 "10.0.0.1/32" destination with interface's local address as next-hop
94 :param int count: Number of FIB entries.
96 - *TODO:* check if the next-hop address shouldn't be remote address
97 instead of local address.
99 n_int = len(self.interfaces)
102 dest_addr = socket.inet_pton(socket.AF_INET, "10.0.0.1")
104 for i in self.interfaces:
105 next_hop_address = i.local_ip4n
106 for j in range(count / n_int):
107 self.vapi.ip_add_del_route(dst_address=dest_addr,
108 dst_address_length=dest_addr_len,
109 next_hop_address=next_hop_address)
111 if counter / count * 100 > percent:
112 self.logger.info("Configure %d FIB entries .. %d%% done" %
116 def modify_packet(self, src_if, packet_size, pkt):
117 """Add load, set destination IP and extend packet to required packet
118 size for defined interface.
120 :param VppInterface src_if: Interface to create packet for.
121 :param int packet_size: Required packet size.
122 :param Scapy pkt: Packet to be modified.
124 dst_if_idx = packet_size / 10 % 2
125 dst_if = self.flows[src_if][dst_if_idx]
126 info = self.create_packet_info(src_if, dst_if)
127 payload = self.info_to_payload(info)
129 p[IP].dst = dst_if.remote_ip4
131 if isinstance(src_if, VppSubInterface):
132 p = src_if.add_dot1_layer(p)
133 self.extend_packet(p, packet_size)
137 def create_stream(self, src_if):
138 """Create input packet stream for defined interface.
140 :param VppInterface src_if: Interface to create packet stream for.
142 hdr_ext = 4 if isinstance(src_if, VppSubInterface) else 0
143 pkt_tmpl = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
144 IP(src=src_if.remote_ip4) /
145 UDP(sport=1234, dport=1234))
147 pkts = [self.modify_packet(src_if, i, pkt_tmpl)
148 for i in moves.range(self.pg_if_packet_sizes[0],
149 self.pg_if_packet_sizes[1], 10)]
150 pkts_b = [self.modify_packet(src_if, i, pkt_tmpl)
151 for i in moves.range(self.pg_if_packet_sizes[1] + hdr_ext,
152 self.pg_if_packet_sizes[2] + hdr_ext,
158 def verify_capture(self, dst_if, capture):
159 """Verify captured input packet stream for defined interface.
161 :param VppInterface dst_if: Interface to verify captured packet stream
163 :param list capture: Captured packet stream.
165 self.logger.info("Verifying capture on interface %s" % dst_if.name)
167 for i in self.interfaces:
168 last_info[i.sw_if_index] = None
170 dst_sw_if_index = dst_if.sw_if_index
171 if hasattr(dst_if, 'parent'):
173 for packet in capture:
175 # Check VLAN tags and Ethernet header
176 packet = dst_if.remove_dot1_layer(packet)
177 self.assertTrue(Dot1Q not in packet)
181 payload_info = self.payload_to_info(packet[Raw])
182 packet_index = payload_info.index
183 self.assertEqual(payload_info.dst, dst_sw_if_index)
185 "Got packet on port %s: src=%u (id=%u)" %
186 (dst_if.name, payload_info.src, packet_index))
187 next_info = self.get_next_packet_info_for_interface2(
188 payload_info.src, dst_sw_if_index,
189 last_info[payload_info.src])
190 last_info[payload_info.src] = next_info
191 self.assertTrue(next_info is not None)
192 self.assertEqual(packet_index, next_info.index)
193 saved_packet = next_info.data
194 # Check standard fields
195 self.assertEqual(ip.src, saved_packet[IP].src)
196 self.assertEqual(ip.dst, saved_packet[IP].dst)
197 self.assertEqual(udp.sport, saved_packet[UDP].sport)
198 self.assertEqual(udp.dport, saved_packet[UDP].dport)
200 self.logger.error(ppp("Unexpected or invalid packet:", packet))
202 for i in self.interfaces:
203 remaining_packet = self.get_next_packet_info_for_interface2(
204 i.sw_if_index, dst_sw_if_index, last_info[i.sw_if_index])
205 self.assertTrue(remaining_packet is None,
206 "Interface %s: Packet expected from interface %s "
207 "didn't arrive" % (dst_if.name, i.name))
214 - Create IPv4 stream for pg0 interface
215 - Create IPv4 tagged streams for pg1's and pg2's sub-interface.
216 - Send and verify received packets on each interface.
219 pkts = self.create_stream(self.pg0)
220 self.pg0.add_stream(pkts)
222 for i in self.sub_interfaces:
223 pkts = self.create_stream(i)
224 i.parent.add_stream(pkts)
226 self.pg_enable_capture(self.pg_interfaces)
229 pkts = self.pg0.get_capture()
230 self.verify_capture(self.pg0, pkts)
232 for i in self.sub_interfaces:
233 pkts = i.parent.get_capture()
234 self.verify_capture(i, pkts)
237 class TestICMPEcho(VppTestCase):
238 """ ICMP Echo Test Case """
242 super(TestICMPEcho, cls).setUpClass()
245 def tearDownClass(cls):
246 super(TestICMPEcho, cls).tearDownClass()
249 super(TestICMPEcho, self).setUp()
251 # create 1 pg interface
252 self.create_pg_interfaces(range(1))
254 for i in self.pg_interfaces:
260 super(TestICMPEcho, self).tearDown()
261 for i in self.pg_interfaces:
265 def test_icmp_echo(self):
266 """ VPP replies to ICMP Echo Request
270 - Receive ICMP Echo Request message on pg0 interface.
271 - Check outgoing ICMP Echo Reply message on pg0 interface.
276 icmp_load = '\x0a' * 18
277 p_echo_request = (Ether(src=self.pg0.remote_mac,
278 dst=self.pg0.local_mac) /
279 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
280 ICMP(id=icmp_id, seq=icmp_seq) /
283 self.pg0.add_stream(p_echo_request)
284 self.pg_enable_capture(self.pg_interfaces)
287 rx = self.pg0.get_capture(1)
293 self.assertEqual(ether.src, self.pg0.local_mac)
294 self.assertEqual(ether.dst, self.pg0.remote_mac)
296 self.assertEqual(ipv4.src, self.pg0.local_ip4)
297 self.assertEqual(ipv4.dst, self.pg0.remote_ip4)
299 self.assertEqual(icmptypes[icmp.type], "echo-reply")
300 self.assertEqual(icmp.id, icmp_id)
301 self.assertEqual(icmp.seq, icmp_seq)
302 self.assertEqual(icmp[Raw].load, icmp_load)
305 class TestIPv4FibCrud(VppTestCase):
306 """ FIB - add/update/delete - ip4 routes
314 ..note:: Python API is too slow to add many routes, needs replacement.
317 def config_fib_many_to_one(self, start_dest_addr, next_hop_addr, count):
320 :param start_dest_addr:
321 :param next_hop_addr:
323 :return list: added ips with 32 prefix
326 dest_addr = int(binascii.hexlify(socket.inet_pton(socket.AF_INET,
327 start_dest_addr)), 16)
329 n_next_hop_addr = socket.inet_pton(socket.AF_INET, next_hop_addr)
330 for _ in range(count):
331 n_dest_addr = binascii.unhexlify('{:08x}'.format(dest_addr))
332 self.vapi.ip_add_del_route(dst_address=n_dest_addr,
333 dst_address_length=dest_addr_len,
334 next_hop_address=n_next_hop_addr)
335 added_ips.append(socket.inet_ntoa(n_dest_addr))
339 def unconfig_fib_many_to_one(self, start_dest_addr, next_hop_addr, count):
342 dest_addr = int(binascii.hexlify(socket.inet_pton(socket.AF_INET,
343 start_dest_addr)), 16)
345 n_next_hop_addr = socket.inet_pton(socket.AF_INET, next_hop_addr)
346 for _ in range(count):
347 n_dest_addr = binascii.unhexlify('{:08x}'.format(dest_addr))
348 self.vapi.ip_add_del_route(dst_address=n_dest_addr,
349 dst_address_length=dest_addr_len,
350 next_hop_address=n_next_hop_addr,
352 removed_ips.append(socket.inet_ntoa(n_dest_addr))
356 def create_stream(self, src_if, dst_if, dst_ips, count):
359 for _ in range(count):
360 dst_addr = random.choice(dst_ips)
361 info = self.create_packet_info(src_if, dst_if)
362 payload = self.info_to_payload(info)
363 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
364 IP(src=src_if.remote_ip4, dst=dst_addr) /
365 UDP(sport=1234, dport=1234) /
368 self.extend_packet(p, random.choice(self.pg_if_packet_sizes))
373 def _find_ip_match(self, find_in, pkt):
375 if self.payload_to_info(p[Raw]) == \
376 self.payload_to_info(pkt[Raw]):
377 if p[IP].src != pkt[IP].src:
379 if p[IP].dst != pkt[IP].dst:
381 if p[UDP].sport != pkt[UDP].sport:
383 if p[UDP].dport != pkt[UDP].dport:
389 def _match_route_detail(route_detail, ip, address_length=32, table_id=0):
390 if route_detail.address == socket.inet_pton(socket.AF_INET, ip):
391 if route_detail.table_id != table_id:
393 elif route_detail.address_length != address_length:
400 def verify_capture(self, dst_interface, received_pkts, expected_pkts):
401 self.assertEqual(len(received_pkts), len(expected_pkts))
402 to_verify = list(expected_pkts)
403 for p in received_pkts:
404 self.assertEqual(p.src, dst_interface.local_mac)
405 self.assertEqual(p.dst, dst_interface.remote_mac)
406 x = self._find_ip_match(to_verify, p)
408 self.assertListEqual(to_verify, [])
410 def verify_route_dump(self, fib_dump, ips):
412 def _ip_in_route_dump(ip, fib_dump):
413 return next((route for route in fib_dump
414 if self._match_route_detail(route, ip)),
418 self.assertTrue(_ip_in_route_dump(ip, fib_dump),
419 'IP {!s} is not in fib dump.'.format(ip))
421 def verify_not_in_route_dump(self, fib_dump, ips):
423 def _ip_in_route_dump(ip, fib_dump):
424 return next((route for route in fib_dump
425 if self._match_route_detail(route, ip)),
429 self.assertFalse(_ip_in_route_dump(ip, fib_dump),
430 'IP {!s} is in fib dump.'.format(ip))
435 #. Create and initialize 3 pg interfaces.
436 #. initialize class attributes configured_routes and deleted_routes
437 to store information between tests.
439 super(TestIPv4FibCrud, cls).setUpClass()
442 # create 3 pg interfaces
443 cls.create_pg_interfaces(range(3))
445 cls.interfaces = list(cls.pg_interfaces)
447 # setup all interfaces
448 for i in cls.interfaces:
453 cls.configured_routes = []
454 cls.deleted_routes = []
455 cls.pg_if_packet_sizes = [64, 512, 1518, 9018]
458 super(TestIPv4FibCrud, cls).tearDownClass()
462 def tearDownClass(cls):
463 super(TestIPv4FibCrud, cls).tearDownClass()
466 super(TestIPv4FibCrud, self).setUp()
467 self.reset_packet_infos()
469 self.configured_routes = []
470 self.deleted_routes = []
472 def test_1_add_routes(self):
475 - add 100 routes check with traffic script.
477 # config 1M FIB entries
478 self.configured_routes.extend(self.config_fib_many_to_one(
479 "10.0.0.0", self.pg0.remote_ip4, 100))
481 fib_dump = self.vapi.ip_fib_dump()
482 self.verify_route_dump(fib_dump, self.configured_routes)
484 self.stream_1 = self.create_stream(
485 self.pg1, self.pg0, self.configured_routes, 100)
486 self.stream_2 = self.create_stream(
487 self.pg2, self.pg0, self.configured_routes, 100)
488 self.pg1.add_stream(self.stream_1)
489 self.pg2.add_stream(self.stream_2)
491 self.pg_enable_capture(self.pg_interfaces)
494 pkts = self.pg0.get_capture(len(self.stream_1) + len(self.stream_2))
495 self.verify_capture(self.pg0, pkts, self.stream_1 + self.stream_2)
497 def test_2_del_routes(self):
498 """ Delete 100 routes
500 - delete 10 routes check with traffic script.
502 # config 1M FIB entries
503 self.configured_routes.extend(self.config_fib_many_to_one(
504 "10.0.0.0", self.pg0.remote_ip4, 100))
505 self.deleted_routes.extend(self.unconfig_fib_many_to_one(
506 "10.0.0.10", self.pg0.remote_ip4, 10))
507 for x in self.deleted_routes:
508 self.configured_routes.remove(x)
510 fib_dump = self.vapi.ip_fib_dump()
511 self.verify_route_dump(fib_dump, self.configured_routes)
513 self.stream_1 = self.create_stream(
514 self.pg1, self.pg0, self.configured_routes, 100)
515 self.stream_2 = self.create_stream(
516 self.pg2, self.pg0, self.configured_routes, 100)
517 self.stream_3 = self.create_stream(
518 self.pg1, self.pg0, self.deleted_routes, 100)
519 self.stream_4 = self.create_stream(
520 self.pg2, self.pg0, self.deleted_routes, 100)
521 self.pg1.add_stream(self.stream_1 + self.stream_3)
522 self.pg2.add_stream(self.stream_2 + self.stream_4)
523 self.pg_enable_capture(self.pg_interfaces)
526 pkts = self.pg0.get_capture(len(self.stream_1) + len(self.stream_2))
527 self.verify_capture(self.pg0, pkts, self.stream_1 + self.stream_2)
529 def test_3_add_new_routes(self):
532 - re-add 5 routes check with traffic script.
533 - add 100 routes check with traffic script.
535 # config 1M FIB entries
536 self.configured_routes.extend(self.config_fib_many_to_one(
537 "10.0.0.0", self.pg0.remote_ip4, 100))
538 self.deleted_routes.extend(self.unconfig_fib_many_to_one(
539 "10.0.0.10", self.pg0.remote_ip4, 10))
540 for x in self.deleted_routes:
541 self.configured_routes.remove(x)
543 tmp = self.config_fib_many_to_one(
544 "10.0.0.10", self.pg0.remote_ip4, 5)
545 self.configured_routes.extend(tmp)
547 self.deleted_routes.remove(x)
549 self.configured_routes.extend(self.config_fib_many_to_one(
550 "10.0.1.0", self.pg0.remote_ip4, 100))
552 fib_dump = self.vapi.ip_fib_dump()
553 self.verify_route_dump(fib_dump, self.configured_routes)
555 self.stream_1 = self.create_stream(
556 self.pg1, self.pg0, self.configured_routes, 300)
557 self.stream_2 = self.create_stream(
558 self.pg2, self.pg0, self.configured_routes, 300)
559 self.stream_3 = self.create_stream(
560 self.pg1, self.pg0, self.deleted_routes, 100)
561 self.stream_4 = self.create_stream(
562 self.pg2, self.pg0, self.deleted_routes, 100)
564 self.pg1.add_stream(self.stream_1 + self.stream_3)
565 self.pg2.add_stream(self.stream_2 + self.stream_4)
566 self.pg_enable_capture(self.pg_interfaces)
569 pkts = self.pg0.get_capture(len(self.stream_1) + len(self.stream_2))
570 self.verify_capture(self.pg0, pkts, self.stream_1 + self.stream_2)
572 def test_4_del_routes(self):
573 """ Delete 1.5k routes
575 - delete 5 routes check with traffic script.
576 - add 100 routes check with traffic script.
578 self.deleted_routes.extend(self.unconfig_fib_many_to_one(
579 "10.0.0.0", self.pg0.remote_ip4, 15))
580 self.deleted_routes.extend(self.unconfig_fib_many_to_one(
581 "10.0.0.20", self.pg0.remote_ip4, 85))
582 self.deleted_routes.extend(self.unconfig_fib_many_to_one(
583 "10.0.1.0", self.pg0.remote_ip4, 100))
584 fib_dump = self.vapi.ip_fib_dump()
585 self.verify_not_in_route_dump(fib_dump, self.deleted_routes)
588 class TestIPNull(VppTestCase):
589 """ IPv4 routes via NULL """
593 super(TestIPNull, cls).setUpClass()
596 def tearDownClass(cls):
597 super(TestIPNull, cls).tearDownClass()
600 super(TestIPNull, self).setUp()
602 # create 2 pg interfaces
603 self.create_pg_interfaces(range(2))
605 for i in self.pg_interfaces:
611 super(TestIPNull, self).tearDown()
612 for i in self.pg_interfaces:
616 def test_ip_null(self):
617 """ IP NULL route """
620 # A route via IP NULL that will reply with ICMP unreachables
622 ip_unreach = VppIpRoute(self, "10.0.0.1", 32, [], is_unreach=1)
623 ip_unreach.add_vpp_config()
625 p_unreach = (Ether(src=self.pg0.remote_mac,
626 dst=self.pg0.local_mac) /
627 IP(src=self.pg0.remote_ip4, dst="10.0.0.1") /
628 UDP(sport=1234, dport=1234) /
631 self.pg0.add_stream(p_unreach)
632 self.pg_enable_capture(self.pg_interfaces)
635 rx = self.pg0.get_capture(1)
639 self.assertEqual(icmptypes[icmp.type], "dest-unreach")
640 self.assertEqual(icmpcodes[icmp.type][icmp.code], "host-unreachable")
641 self.assertEqual(icmp.src, self.pg0.remote_ip4)
642 self.assertEqual(icmp.dst, "10.0.0.1")
645 # ICMP replies are rate limited. so sit and spin.
650 # A route via IP NULL that will reply with ICMP prohibited
652 ip_prohibit = VppIpRoute(self, "10.0.0.2", 32, [], is_prohibit=1)
653 ip_prohibit.add_vpp_config()
655 p_prohibit = (Ether(src=self.pg0.remote_mac,
656 dst=self.pg0.local_mac) /
657 IP(src=self.pg0.remote_ip4, dst="10.0.0.2") /
658 UDP(sport=1234, dport=1234) /
661 self.pg0.add_stream(p_prohibit)
662 self.pg_enable_capture(self.pg_interfaces)
665 rx = self.pg0.get_capture(1)
670 self.assertEqual(icmptypes[icmp.type], "dest-unreach")
671 self.assertEqual(icmpcodes[icmp.type][icmp.code], "host-prohibited")
672 self.assertEqual(icmp.src, self.pg0.remote_ip4)
673 self.assertEqual(icmp.dst, "10.0.0.2")
675 def test_ip_drop(self):
676 """ IP Drop Routes """
678 p = (Ether(src=self.pg0.remote_mac,
679 dst=self.pg0.local_mac) /
680 IP(src=self.pg0.remote_ip4, dst="1.1.1.1") /
681 UDP(sport=1234, dport=1234) /
684 r1 = VppIpRoute(self, "1.1.1.0", 24,
685 [VppRoutePath(self.pg1.remote_ip4,
686 self.pg1.sw_if_index)])
689 rx = self.send_and_expect(self.pg0, p * 65, self.pg1)
692 # insert a more specific as a drop
694 r2 = VppIpRoute(self, "1.1.1.1", 32, [], is_drop=1)
697 self.send_and_assert_no_replies(self.pg0, p * 65, "Drop Route")
698 r2.remove_vpp_config()
699 rx = self.send_and_expect(self.pg0, p * 65, self.pg1)
702 class TestIPDisabled(VppTestCase):
703 """ IPv4 disabled """
707 super(TestIPDisabled, cls).setUpClass()
710 def tearDownClass(cls):
711 super(TestIPDisabled, cls).tearDownClass()
714 super(TestIPDisabled, self).setUp()
716 # create 2 pg interfaces
717 self.create_pg_interfaces(range(2))
721 self.pg0.config_ip4()
722 self.pg0.resolve_arp()
724 # PG 1 is not IP enabled
728 super(TestIPDisabled, self).tearDown()
729 for i in self.pg_interfaces:
733 def test_ip_disabled(self):
738 # one accepting interface, pg0, 2 forwarding interfaces
740 route_232_1_1_1 = VppIpMRoute(
744 MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
745 [VppMRoutePath(self.pg1.sw_if_index,
746 MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
747 VppMRoutePath(self.pg0.sw_if_index,
748 MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
749 route_232_1_1_1.add_vpp_config()
751 pu = (Ether(src=self.pg1.remote_mac,
752 dst=self.pg1.local_mac) /
753 IP(src="10.10.10.10", dst=self.pg0.remote_ip4) /
754 UDP(sport=1234, dport=1234) /
756 pm = (Ether(src=self.pg1.remote_mac,
757 dst=self.pg1.local_mac) /
758 IP(src="10.10.10.10", dst="232.1.1.1") /
759 UDP(sport=1234, dport=1234) /
763 # PG1 does not forward IP traffic
765 self.send_and_assert_no_replies(self.pg1, pu, "IP disabled")
766 self.send_and_assert_no_replies(self.pg1, pm, "IP disabled")
771 self.pg1.config_ip4()
774 # Now we get packets through
776 self.pg1.add_stream(pu)
777 self.pg_enable_capture(self.pg_interfaces)
779 rx = self.pg0.get_capture(1)
781 self.pg1.add_stream(pm)
782 self.pg_enable_capture(self.pg_interfaces)
784 rx = self.pg0.get_capture(1)
789 self.pg1.unconfig_ip4()
792 # PG1 does not forward IP traffic
794 self.send_and_assert_no_replies(self.pg1, pu, "IP disabled")
795 self.send_and_assert_no_replies(self.pg1, pm, "IP disabled")
798 class TestIPSubNets(VppTestCase):
803 super(TestIPSubNets, cls).setUpClass()
806 def tearDownClass(cls):
807 super(TestIPSubNets, cls).tearDownClass()
810 super(TestIPSubNets, self).setUp()
812 # create a 2 pg interfaces
813 self.create_pg_interfaces(range(2))
815 # pg0 we will use to experiment
818 # pg1 is setup normally
820 self.pg1.config_ip4()
821 self.pg1.resolve_arp()
824 super(TestIPSubNets, self).tearDown()
825 for i in self.pg_interfaces:
828 def test_ip_sub_nets(self):
832 # Configure a covering route to forward so we know
833 # when we are dropping
835 cover_route = VppIpRoute(self, "10.0.0.0", 8,
836 [VppRoutePath(self.pg1.remote_ip4,
837 self.pg1.sw_if_index)])
838 cover_route.add_vpp_config()
840 p = (Ether(src=self.pg1.remote_mac,
841 dst=self.pg1.local_mac) /
842 IP(dst="10.10.10.10", src=self.pg0.local_ip4) /
843 UDP(sport=1234, dport=1234) /
846 self.pg1.add_stream(p)
847 self.pg_enable_capture(self.pg_interfaces)
849 rx = self.pg1.get_capture(1)
852 # Configure some non-/24 subnets on an IP interface
854 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.10.10.10")
856 self.vapi.sw_interface_add_del_address(
857 sw_if_index=self.pg0.sw_if_index, address=ip_addr_n,
860 pn = (Ether(src=self.pg1.remote_mac,
861 dst=self.pg1.local_mac) /
862 IP(dst="10.10.0.0", src=self.pg0.local_ip4) /
863 UDP(sport=1234, dport=1234) /
865 pb = (Ether(src=self.pg1.remote_mac,
866 dst=self.pg1.local_mac) /
867 IP(dst="10.10.255.255", src=self.pg0.local_ip4) /
868 UDP(sport=1234, dport=1234) /
871 self.send_and_assert_no_replies(self.pg1, pn, "IP Network address")
872 self.send_and_assert_no_replies(self.pg1, pb, "IP Broadcast address")
874 # remove the sub-net and we are forwarding via the cover again
875 self.vapi.sw_interface_add_del_address(
876 sw_if_index=self.pg0.sw_if_index, address=ip_addr_n,
877 address_length=16, is_add=0)
878 self.pg1.add_stream(pn)
879 self.pg_enable_capture(self.pg_interfaces)
881 rx = self.pg1.get_capture(1)
882 self.pg1.add_stream(pb)
883 self.pg_enable_capture(self.pg_interfaces)
885 rx = self.pg1.get_capture(1)
888 # A /31 is a special case where the 'other-side' is an attached host
889 # packets to that peer generate ARP requests
891 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.10.10.10")
893 self.vapi.sw_interface_add_del_address(
894 sw_if_index=self.pg0.sw_if_index, address=ip_addr_n,
897 pn = (Ether(src=self.pg1.remote_mac,
898 dst=self.pg1.local_mac) /
899 IP(dst="10.10.10.11", src=self.pg0.local_ip4) /
900 UDP(sport=1234, dport=1234) /
903 self.pg1.add_stream(pn)
904 self.pg_enable_capture(self.pg_interfaces)
906 rx = self.pg0.get_capture(1)
909 # remove the sub-net and we are forwarding via the cover again
910 self.vapi.sw_interface_add_del_address(
911 sw_if_index=self.pg0.sw_if_index, address=ip_addr_n,
912 address_length=31, is_add=0)
913 self.pg1.add_stream(pn)
914 self.pg_enable_capture(self.pg_interfaces)
916 rx = self.pg1.get_capture(1)
919 class TestIPLoadBalance(VppTestCase):
920 """ IPv4 Load-Balancing """
924 super(TestIPLoadBalance, cls).setUpClass()
927 def tearDownClass(cls):
928 super(TestIPLoadBalance, cls).tearDownClass()
931 super(TestIPLoadBalance, self).setUp()
933 self.create_pg_interfaces(range(5))
934 mpls_tbl = VppMplsTable(self, 0)
935 mpls_tbl.add_vpp_config()
937 for i in self.pg_interfaces:
944 for i in self.pg_interfaces:
948 super(TestIPLoadBalance, self).tearDown()
950 def send_and_expect_load_balancing(self, input, pkts, outputs):
951 input.add_stream(pkts)
952 self.pg_enable_capture(self.pg_interfaces)
956 rx = oo._get_capture(1)
957 self.assertNotEqual(0, len(rx))
962 def send_and_expect_one_itf(self, input, pkts, itf):
963 input.add_stream(pkts)
964 self.pg_enable_capture(self.pg_interfaces)
966 rx = itf.get_capture(len(pkts))
968 def test_ip_load_balance(self):
969 """ IP Load-Balancing """
972 # An array of packets that differ only in the destination port
978 # An array of packets that differ only in the source address
984 port_ip_hdr = (IP(dst="10.0.0.1", src="20.0.0.1") /
985 UDP(sport=1234, dport=1234 + ii) /
987 port_ip_pkts.append((Ether(src=self.pg0.remote_mac,
988 dst=self.pg0.local_mac) /
990 port_mpls_pkts.append((Ether(src=self.pg0.remote_mac,
991 dst=self.pg0.local_mac) /
992 MPLS(label=66, ttl=2) /
995 src_ip_hdr = (IP(dst="10.0.0.1", src="20.0.0.%d" % ii) /
996 UDP(sport=1234, dport=1234) /
998 src_ip_pkts.append((Ether(src=self.pg0.remote_mac,
999 dst=self.pg0.local_mac) /
1001 src_mpls_pkts.append((Ether(src=self.pg0.remote_mac,
1002 dst=self.pg0.local_mac) /
1003 MPLS(label=66, ttl=2) /
1006 route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1007 [VppRoutePath(self.pg1.remote_ip4,
1008 self.pg1.sw_if_index),
1009 VppRoutePath(self.pg2.remote_ip4,
1010 self.pg2.sw_if_index)])
1011 route_10_0_0_1.add_vpp_config()
1013 binding = VppMplsIpBind(self, 66, "10.0.0.1", 32)
1014 binding.add_vpp_config()
1017 # inject the packet on pg0 - expect load-balancing across the 2 paths
1018 # - since the default hash config is to use IP src,dst and port
1020 # We are not going to ensure equal amounts of packets across each link,
1021 # since the hash algorithm is statistical and therefore this can never
1022 # be guaranteed. But with 64 different packets we do expect some
1023 # balancing. So instead just ensure there is traffic on each link.
1025 self.send_and_expect_load_balancing(self.pg0, port_ip_pkts,
1026 [self.pg1, self.pg2])
1027 self.send_and_expect_load_balancing(self.pg0, src_ip_pkts,
1028 [self.pg1, self.pg2])
1029 self.send_and_expect_load_balancing(self.pg0, port_mpls_pkts,
1030 [self.pg1, self.pg2])
1031 self.send_and_expect_load_balancing(self.pg0, src_mpls_pkts,
1032 [self.pg1, self.pg2])
1035 # change the flow hash config so it's only IP src,dst
1036 # - now only the stream with differing source address will
1039 self.vapi.set_ip_flow_hash(vrf_id=0, src=1, dst=1, sport=0, dport=0)
1041 self.send_and_expect_load_balancing(self.pg0, src_ip_pkts,
1042 [self.pg1, self.pg2])
1043 self.send_and_expect_load_balancing(self.pg0, src_mpls_pkts,
1044 [self.pg1, self.pg2])
1046 self.send_and_expect_one_itf(self.pg0, port_ip_pkts, self.pg2)
1049 # change the flow hash config back to defaults
1051 self.vapi.set_ip_flow_hash(vrf_id=0, src=1, dst=1, sport=1, dport=1)
1054 # Recursive prefixes
1055 # - testing that 2 stages of load-balancing occurs and there is no
1056 # polarisation (i.e. only 2 of 4 paths are used)
1061 for ii in range(257):
1062 port_pkts.append((Ether(src=self.pg0.remote_mac,
1063 dst=self.pg0.local_mac) /
1064 IP(dst="1.1.1.1", src="20.0.0.1") /
1065 UDP(sport=1234, dport=1234 + ii) /
1067 src_pkts.append((Ether(src=self.pg0.remote_mac,
1068 dst=self.pg0.local_mac) /
1069 IP(dst="1.1.1.1", src="20.0.0.%d" % ii) /
1070 UDP(sport=1234, dport=1234) /
1073 route_10_0_0_2 = VppIpRoute(self, "10.0.0.2", 32,
1074 [VppRoutePath(self.pg3.remote_ip4,
1075 self.pg3.sw_if_index),
1076 VppRoutePath(self.pg4.remote_ip4,
1077 self.pg4.sw_if_index)])
1078 route_10_0_0_2.add_vpp_config()
1080 route_1_1_1_1 = VppIpRoute(self, "1.1.1.1", 32,
1081 [VppRoutePath("10.0.0.2", 0xffffffff),
1082 VppRoutePath("10.0.0.1", 0xffffffff)])
1083 route_1_1_1_1.add_vpp_config()
1086 # inject the packet on pg0 - expect load-balancing across all 4 paths
1088 self.vapi.cli("clear trace")
1089 self.send_and_expect_load_balancing(self.pg0, port_pkts,
1090 [self.pg1, self.pg2,
1091 self.pg3, self.pg4])
1092 self.send_and_expect_load_balancing(self.pg0, src_pkts,
1093 [self.pg1, self.pg2,
1094 self.pg3, self.pg4])
1097 # bring down pg1 expect LB to adjust to use only those that are pu
1099 self.pg1.link_down()
1101 rx = self.send_and_expect_load_balancing(self.pg0, src_pkts,
1102 [self.pg2, self.pg3,
1104 self.assertEqual(len(src_pkts), len(rx))
1107 # bring down pg2 expect LB to adjust to use only those that are pu
1109 self.pg2.link_down()
1111 rx = self.send_and_expect_load_balancing(self.pg0, src_pkts,
1112 [self.pg3, self.pg4])
1113 self.assertEqual(len(src_pkts), len(rx))
1116 # bring the links back up - expect LB over all again
1121 rx = self.send_and_expect_load_balancing(self.pg0, src_pkts,
1122 [self.pg1, self.pg2,
1123 self.pg3, self.pg4])
1124 self.assertEqual(len(src_pkts), len(rx))
1127 # The same link-up/down but this time admin state
1129 self.pg1.admin_down()
1130 self.pg2.admin_down()
1131 rx = self.send_and_expect_load_balancing(self.pg0, src_pkts,
1132 [self.pg3, self.pg4])
1133 self.assertEqual(len(src_pkts), len(rx))
1136 self.pg1.resolve_arp()
1137 self.pg2.resolve_arp()
1138 rx = self.send_and_expect_load_balancing(self.pg0, src_pkts,
1139 [self.pg1, self.pg2,
1140 self.pg3, self.pg4])
1141 self.assertEqual(len(src_pkts), len(rx))
1144 # Recursive prefixes
1145 # - testing that 2 stages of load-balancing, no choices
1149 for ii in range(257):
1150 port_pkts.append((Ether(src=self.pg0.remote_mac,
1151 dst=self.pg0.local_mac) /
1152 IP(dst="1.1.1.2", src="20.0.0.2") /
1153 UDP(sport=1234, dport=1234 + ii) /
1156 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
1157 [VppRoutePath(self.pg3.remote_ip4,
1158 self.pg3.sw_if_index)])
1159 route_10_0_0_3.add_vpp_config()
1161 route_1_1_1_2 = VppIpRoute(self, "1.1.1.2", 32,
1162 [VppRoutePath("10.0.0.3", 0xffffffff)])
1163 route_1_1_1_2.add_vpp_config()
1166 # inject the packet on pg0 - rx only on via routes output interface
1168 self.vapi.cli("clear trace")
1169 self.send_and_expect_one_itf(self.pg0, port_pkts, self.pg3)
1172 # Add a LB route in the presence of a down link - expect no
1173 # packets over the down link
1175 self.pg3.link_down()
1177 route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32,
1178 [VppRoutePath(self.pg3.remote_ip4,
1179 self.pg3.sw_if_index),
1180 VppRoutePath(self.pg4.remote_ip4,
1181 self.pg4.sw_if_index)])
1182 route_10_0_0_3.add_vpp_config()
1185 for ii in range(257):
1186 port_pkts.append(Ether(src=self.pg0.remote_mac,
1187 dst=self.pg0.local_mac) /
1188 IP(dst="10.0.0.3", src="20.0.0.2") /
1189 UDP(sport=1234, dport=1234 + ii) /
1192 self.send_and_expect_one_itf(self.pg0, port_pkts, self.pg4)
1194 # bring the link back up
1197 rx = self.send_and_expect_load_balancing(self.pg0, port_pkts,
1198 [self.pg3, self.pg4])
1199 self.assertEqual(len(src_pkts), len(rx))
1202 class TestIPVlan0(VppTestCase):
1206 def setUpClass(cls):
1207 super(TestIPVlan0, cls).setUpClass()
1210 def tearDownClass(cls):
1211 super(TestIPVlan0, cls).tearDownClass()
1214 super(TestIPVlan0, self).setUp()
1216 self.create_pg_interfaces(range(2))
1217 mpls_tbl = VppMplsTable(self, 0)
1218 mpls_tbl.add_vpp_config()
1220 for i in self.pg_interfaces:
1227 for i in self.pg_interfaces:
1231 super(TestIPVlan0, self).tearDown()
1233 def test_ip_vlan_0(self):
1236 pkts = (Ether(src=self.pg0.remote_mac,
1237 dst=self.pg0.local_mac) /
1239 IP(dst=self.pg1.remote_ip4,
1240 src=self.pg0.remote_ip4) /
1241 UDP(sport=1234, dport=1234) /
1242 Raw('\xa5' * 100)) * 65
1245 # Expect that packets sent on VLAN-0 are forwarded on the
1248 self.send_and_expect(self.pg0, pkts, self.pg1)
1251 class TestIPPunt(VppTestCase):
1252 """ IPv4 Punt Police/Redirect """
1255 def setUpClass(cls):
1256 super(TestIPPunt, cls).setUpClass()
1259 def tearDownClass(cls):
1260 super(TestIPPunt, cls).tearDownClass()
1263 super(TestIPPunt, self).setUp()
1265 self.create_pg_interfaces(range(4))
1267 for i in self.pg_interfaces:
1273 super(TestIPPunt, self).tearDown()
1274 for i in self.pg_interfaces:
1278 def test_ip_punt(self):
1279 """ IP punt police and redirect """
1281 p = (Ether(src=self.pg0.remote_mac,
1282 dst=self.pg0.local_mac) /
1283 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
1284 TCP(sport=1234, dport=1234) /
1290 # Configure a punt redirect via pg1.
1292 nh_addr = self.pg1.remote_ip4
1293 self.vapi.ip_punt_redirect(self.pg0.sw_if_index,
1294 self.pg1.sw_if_index,
1297 self.send_and_expect(self.pg0, pkts, self.pg1)
1302 policer = self.vapi.policer_add_del(b"ip4-punt", 400, 0, 10, 0,
1304 self.vapi.ip_punt_police(policer.policer_index)
1306 self.vapi.cli("clear trace")
1307 self.pg0.add_stream(pkts)
1308 self.pg_enable_capture(self.pg_interfaces)
1312 # the number of packet received should be greater than 0,
1313 # but not equal to the number sent, since some were policed
1315 rx = self.pg1._get_capture(1)
1316 self.assertGreater(len(rx), 0)
1317 self.assertLess(len(rx), len(pkts))
1320 # remove the policer. back to full rx
1322 self.vapi.ip_punt_police(policer.policer_index, is_add=0)
1323 self.vapi.policer_add_del(b"ip4-punt", 400, 0, 10, 0,
1324 rate_type=1, is_add=0)
1325 self.send_and_expect(self.pg0, pkts, self.pg1)
1328 # remove the redirect. expect full drop.
1330 self.vapi.ip_punt_redirect(self.pg0.sw_if_index,
1331 self.pg1.sw_if_index,
1334 self.send_and_assert_no_replies(self.pg0, pkts,
1335 "IP no punt config")
1338 # Add a redirect that is not input port selective
1340 self.vapi.ip_punt_redirect(0xffffffff,
1341 self.pg1.sw_if_index,
1343 self.send_and_expect(self.pg0, pkts, self.pg1)
1345 self.vapi.ip_punt_redirect(0xffffffff,
1346 self.pg1.sw_if_index,
1350 def test_ip_punt_dump(self):
1351 """ IP4 punt redirect dump"""
1354 # Configure a punt redirects
1356 nh_address = self.pg3.remote_ip4
1357 self.vapi.ip_punt_redirect(self.pg0.sw_if_index,
1358 self.pg3.sw_if_index,
1360 self.vapi.ip_punt_redirect(self.pg1.sw_if_index,
1361 self.pg3.sw_if_index,
1363 self.vapi.ip_punt_redirect(self.pg2.sw_if_index,
1364 self.pg3.sw_if_index,
1368 # Dump pg0 punt redirects
1370 punts = self.vapi.ip_punt_redirect_dump(self.pg0.sw_if_index)
1372 self.assertEqual(p.punt.rx_sw_if_index, self.pg0.sw_if_index)
1375 # Dump punt redirects for all interfaces
1377 punts = self.vapi.ip_punt_redirect_dump(0xffffffff)
1378 self.assertEqual(len(punts), 3)
1380 self.assertEqual(p.punt.tx_sw_if_index, self.pg3.sw_if_index)
1381 self.assertNotEqual(punts[1].punt.nh, self.pg3.remote_ip4)
1382 self.assertEqual(str(punts[2].punt.nh), '0.0.0.0')
1385 class TestIPDeag(VppTestCase):
1386 """ IPv4 Deaggregate Routes """
1389 def setUpClass(cls):
1390 super(TestIPDeag, cls).setUpClass()
1393 def tearDownClass(cls):
1394 super(TestIPDeag, cls).tearDownClass()
1397 super(TestIPDeag, self).setUp()
1399 self.create_pg_interfaces(range(3))
1401 for i in self.pg_interfaces:
1407 super(TestIPDeag, self).tearDown()
1408 for i in self.pg_interfaces:
1412 def test_ip_deag(self):
1413 """ IP Deag Routes """
1416 # Create a table to be used for:
1417 # 1 - another destination address lookup
1418 # 2 - a source address lookup
1420 table_dst = VppIpTable(self, 1)
1421 table_src = VppIpTable(self, 2)
1422 table_dst.add_vpp_config()
1423 table_src.add_vpp_config()
1426 # Add a route in the default table to point to a deag/
1427 # second lookup in each of these tables
1429 route_to_dst = VppIpRoute(self, "1.1.1.1", 32,
1430 [VppRoutePath("0.0.0.0",
1433 route_to_src = VppIpRoute(self, "1.1.1.2", 32,
1434 [VppRoutePath("0.0.0.0",
1437 is_source_lookup=1)])
1438 route_to_dst.add_vpp_config()
1439 route_to_src.add_vpp_config()
1442 # packets to these destination are dropped, since they'll
1443 # hit the respective default routes in the second table
1445 p_dst = (Ether(src=self.pg0.remote_mac,
1446 dst=self.pg0.local_mac) /
1447 IP(src="5.5.5.5", dst="1.1.1.1") /
1448 TCP(sport=1234, dport=1234) /
1450 p_src = (Ether(src=self.pg0.remote_mac,
1451 dst=self.pg0.local_mac) /
1452 IP(src="2.2.2.2", dst="1.1.1.2") /
1453 TCP(sport=1234, dport=1234) /
1455 pkts_dst = p_dst * 257
1456 pkts_src = p_src * 257
1458 self.send_and_assert_no_replies(self.pg0, pkts_dst,
1460 self.send_and_assert_no_replies(self.pg0, pkts_src,
1464 # add a route in the dst table to forward via pg1
1466 route_in_dst = VppIpRoute(self, "1.1.1.1", 32,
1467 [VppRoutePath(self.pg1.remote_ip4,
1468 self.pg1.sw_if_index)],
1470 route_in_dst.add_vpp_config()
1471 self.send_and_expect(self.pg0, pkts_dst, self.pg1)
1474 # add a route in the src table to forward via pg2
1476 route_in_src = VppIpRoute(self, "2.2.2.2", 32,
1477 [VppRoutePath(self.pg2.remote_ip4,
1478 self.pg2.sw_if_index)],
1480 route_in_src.add_vpp_config()
1481 self.send_and_expect(self.pg0, pkts_src, self.pg2)
1484 # loop in the lookup DP
1486 route_loop = VppIpRoute(self, "2.2.2.3", 32,
1487 [VppRoutePath("0.0.0.0",
1490 route_loop.add_vpp_config()
1492 p_l = (Ether(src=self.pg0.remote_mac,
1493 dst=self.pg0.local_mac) /
1494 IP(src="2.2.2.4", dst="2.2.2.3") /
1495 TCP(sport=1234, dport=1234) /
1498 self.send_and_assert_no_replies(self.pg0, p_l * 257,
1502 class TestIPInput(VppTestCase):
1503 """ IPv4 Input Exceptions """
1506 def setUpClass(cls):
1507 super(TestIPInput, cls).setUpClass()
1510 def tearDownClass(cls):
1511 super(TestIPInput, cls).tearDownClass()
1514 super(TestIPInput, self).setUp()
1516 self.create_pg_interfaces(range(2))
1518 for i in self.pg_interfaces:
1524 super(TestIPInput, self).tearDown()
1525 for i in self.pg_interfaces:
1529 def test_ip_input(self):
1530 """ IP Input Exceptions """
1532 # i can't find a way in scapy to construct an IP packet
1533 # with a length less than the IP header length
1536 # Packet too short - this is forwarded
1538 p_short = (Ether(src=self.pg0.remote_mac,
1539 dst=self.pg0.local_mac) /
1540 IP(src=self.pg0.remote_ip4,
1541 dst=self.pg1.remote_ip4,
1543 UDP(sport=1234, dport=1234) /
1546 rx = self.send_and_expect(self.pg0, p_short * 65, self.pg1)
1549 # Packet too long - this is dropped
1551 p_long = (Ether(src=self.pg0.remote_mac,
1552 dst=self.pg0.local_mac) /
1553 IP(src=self.pg0.remote_ip4,
1554 dst=self.pg1.remote_ip4,
1556 UDP(sport=1234, dport=1234) /
1559 rx = self.send_and_assert_no_replies(self.pg0, p_long * 65,
1563 # bad chksum - this is dropped
1565 p_chksum = (Ether(src=self.pg0.remote_mac,
1566 dst=self.pg0.local_mac) /
1567 IP(src=self.pg0.remote_ip4,
1568 dst=self.pg1.remote_ip4,
1570 UDP(sport=1234, dport=1234) /
1573 rx = self.send_and_assert_no_replies(self.pg0, p_chksum * 65,
1577 # bad version - this is dropped
1579 p_ver = (Ether(src=self.pg0.remote_mac,
1580 dst=self.pg0.local_mac) /
1581 IP(src=self.pg0.remote_ip4,
1582 dst=self.pg1.remote_ip4,
1584 UDP(sport=1234, dport=1234) /
1587 rx = self.send_and_assert_no_replies(self.pg0, p_ver * 65,
1591 # fragment offset 1 - this is dropped
1593 p_frag = (Ether(src=self.pg0.remote_mac,
1594 dst=self.pg0.local_mac) /
1595 IP(src=self.pg0.remote_ip4,
1596 dst=self.pg1.remote_ip4,
1598 UDP(sport=1234, dport=1234) /
1601 rx = self.send_and_assert_no_replies(self.pg0, p_frag * 65,
1605 # TTL expired packet
1607 p_ttl = (Ether(src=self.pg0.remote_mac,
1608 dst=self.pg0.local_mac) /
1609 IP(src=self.pg0.remote_ip4,
1610 dst=self.pg1.remote_ip4,
1612 UDP(sport=1234, dport=1234) /
1615 rx = self.send_and_expect(self.pg0, p_ttl * 65, self.pg0)
1620 self.assertEqual(icmptypes[icmp.type], "time-exceeded")
1621 self.assertEqual(icmpcodes[icmp.type][icmp.code],
1622 "ttl-zero-during-transit")
1623 self.assertEqual(icmp.src, self.pg0.remote_ip4)
1624 self.assertEqual(icmp.dst, self.pg1.remote_ip4)
1629 p_mtu = (Ether(src=self.pg0.remote_mac,
1630 dst=self.pg0.local_mac) /
1631 IP(src=self.pg0.remote_ip4,
1632 dst=self.pg1.remote_ip4,
1633 ttl=10, flags='DF') /
1634 UDP(sport=1234, dport=1234) /
1637 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1500, 0, 0, 0])
1639 rx = self.send_and_expect(self.pg0, p_mtu * 65, self.pg0)
1643 self.assertEqual(icmptypes[icmp.type], "dest-unreach")
1644 self.assertEqual(icmpcodes[icmp.type][icmp.code],
1645 "fragmentation-needed")
1646 self.assertEqual(icmp.src, self.pg0.remote_ip4)
1647 self.assertEqual(icmp.dst, self.pg1.remote_ip4)
1649 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [2500, 0, 0, 0])
1650 rx = self.send_and_expect(self.pg0, p_mtu * 65, self.pg1)
1652 # Reset MTU for subsequent tests
1653 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [9000, 0, 0, 0])
1656 # source address 0.0.0.0 and 25.255.255.255 and for-us
1658 p_s0 = (Ether(src=self.pg0.remote_mac,
1659 dst=self.pg0.local_mac) /
1661 dst=self.pg0.local_ip4) /
1663 Raw(load='\x0a' * 18))
1664 rx = self.send_and_assert_no_replies(self.pg0, p_s0 * 17)
1666 p_s0 = (Ether(src=self.pg0.remote_mac,
1667 dst=self.pg0.local_mac) /
1668 IP(src="255.255.255.255",
1669 dst=self.pg0.local_ip4) /
1671 Raw(load='\x0a' * 18))
1672 rx = self.send_and_assert_no_replies(self.pg0, p_s0 * 17)
1675 class TestIPDirectedBroadcast(VppTestCase):
1676 """ IPv4 Directed Broadcast """
1679 def setUpClass(cls):
1680 super(TestIPDirectedBroadcast, cls).setUpClass()
1683 def tearDownClass(cls):
1684 super(TestIPDirectedBroadcast, cls).tearDownClass()
1687 super(TestIPDirectedBroadcast, self).setUp()
1689 self.create_pg_interfaces(range(2))
1691 for i in self.pg_interfaces:
1695 super(TestIPDirectedBroadcast, self).tearDown()
1696 for i in self.pg_interfaces:
1699 def test_ip_input(self):
1700 """ IP Directed Broadcast """
1703 # set the directed broadcast on pg0 first, then config IP4 addresses
1704 # for pg1 directed broadcast is always disabled
1705 self.vapi.sw_interface_set_ip_directed_broadcast(
1706 self.pg0.sw_if_index, 1)
1708 p0 = (Ether(src=self.pg1.remote_mac,
1709 dst=self.pg1.local_mac) /
1711 dst=self.pg0._local_ip4_bcast) /
1712 UDP(sport=1234, dport=1234) /
1714 p1 = (Ether(src=self.pg0.remote_mac,
1715 dst=self.pg0.local_mac) /
1717 dst=self.pg1._local_ip4_bcast) /
1718 UDP(sport=1234, dport=1234) /
1721 self.pg0.config_ip4()
1722 self.pg0.resolve_arp()
1723 self.pg1.config_ip4()
1724 self.pg1.resolve_arp()
1727 # test packet is L2 broadcast
1729 rx = self.send_and_expect(self.pg1, p0 * 65, self.pg0)
1730 self.assertTrue(rx[0][Ether].dst, "ff:ff:ff:ff:ff:ff")
1732 self.send_and_assert_no_replies(self.pg0, p1 * 65,
1733 "directed broadcast disabled")
1736 # toggle directed broadcast on pg0
1738 self.vapi.sw_interface_set_ip_directed_broadcast(
1739 self.pg0.sw_if_index, 0)
1740 self.send_and_assert_no_replies(self.pg1, p0 * 65,
1741 "directed broadcast disabled")
1743 self.vapi.sw_interface_set_ip_directed_broadcast(
1744 self.pg0.sw_if_index, 1)
1745 rx = self.send_and_expect(self.pg1, p0 * 65, self.pg0)
1747 self.pg0.unconfig_ip4()
1748 self.pg1.unconfig_ip4()
1751 class TestIPLPM(VppTestCase):
1752 """ IPv4 longest Prefix Match """
1755 def setUpClass(cls):
1756 super(TestIPLPM, cls).setUpClass()
1759 def tearDownClass(cls):
1760 super(TestIPLPM, cls).tearDownClass()
1763 super(TestIPLPM, self).setUp()
1765 self.create_pg_interfaces(range(4))
1767 for i in self.pg_interfaces:
1773 super(TestIPLPM, self).tearDown()
1774 for i in self.pg_interfaces:
1778 def test_ip_lpm(self):
1779 """ IP longest Prefix Match """
1781 s_24 = VppIpRoute(self, "10.1.2.0", 24,
1782 [VppRoutePath(self.pg1.remote_ip4,
1783 self.pg1.sw_if_index)])
1784 s_24.add_vpp_config()
1785 s_8 = VppIpRoute(self, "10.0.0.0", 8,
1786 [VppRoutePath(self.pg2.remote_ip4,
1787 self.pg2.sw_if_index)])
1788 s_8.add_vpp_config()
1790 p_8 = (Ether(src=self.pg0.remote_mac,
1791 dst=self.pg0.local_mac) /
1794 UDP(sport=1234, dport=1234) /
1796 p_24 = (Ether(src=self.pg0.remote_mac,
1797 dst=self.pg0.local_mac) /
1800 UDP(sport=1234, dport=1234) /
1803 self.logger.info(self.vapi.cli("sh ip fib mtrie"))
1804 rx = self.send_and_expect(self.pg0, p_8 * 65, self.pg2)
1805 rx = self.send_and_expect(self.pg0, p_24 * 65, self.pg1)
1808 class TestIPv4Frag(VppTestCase):
1809 """ IPv4 fragmentation """
1812 def setUpClass(cls):
1813 super(TestIPv4Frag, cls).setUpClass()
1815 cls.create_pg_interfaces([0, 1])
1816 cls.src_if = cls.pg0
1817 cls.dst_if = cls.pg1
1819 # setup all interfaces
1820 for i in cls.pg_interfaces:
1826 def tearDownClass(cls):
1827 super(TestIPv4Frag, cls).tearDownClass()
1829 def test_frag_large_packets(self):
1830 """ Fragmentation of large packets """
1832 p = (Ether(dst=self.src_if.local_mac, src=self.src_if.remote_mac) /
1833 IP(src=self.src_if.remote_ip4, dst=self.dst_if.remote_ip4) /
1834 UDP(sport=1234, dport=5678) / Raw())
1835 self.extend_packet(p, 6000, "abcde")
1836 saved_payload = p[Raw].load
1838 # Force fragmentation by setting MTU of output interface
1839 # lower than packet size
1840 self.vapi.sw_interface_set_mtu(self.dst_if.sw_if_index,
1843 self.pg_enable_capture()
1844 self.src_if.add_stream(p)
1847 # Expecting 3 fragments because size of created fragments currently
1848 # cannot be larger then VPP buffer size (which is 2048)
1849 packets = self.dst_if.get_capture(3)
1851 # Assume VPP sends the fragments in order
1854 payload_offset = p.frag * 8
1855 if payload_offset > 0:
1856 payload_offset -= 8 # UDP header is not in payload
1857 self.assert_equal(payload_offset, len(payload))
1858 payload += p[Raw].load
1859 self.assert_equal(payload, saved_payload, "payload")
1862 if __name__ == '__main__':
1863 unittest.main(testRunner=VppTestRunner)