X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=test%2Ftest_ip4.py;h=a428db339f40d53f300c22df145091a0df562740;hb=f2984bbb0;hp=af0c319d4a120379ce3f14584931ebd0da431915;hpb=6ed154f779c765f38b61ed84349bd539287dd02b;p=vpp.git diff --git a/test/test_ip4.py b/test/test_ip4.py index af0c319d4a1..a428db339f4 100644 --- a/test/test_ip4.py +++ b/test/test_ip4.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import binascii import random import socket @@ -13,14 +13,16 @@ from six import moves from framework import VppTestCase, VppTestRunner from util import ppp -from vpp_ip import VppIpPrefix from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpMRoute, \ - VppMRoutePath, MRouteItfFlags, MRouteEntryFlags, VppMplsIpBind, \ + VppMRoutePath, VppMplsIpBind, \ VppMplsTable, VppIpTable, FibPathType, find_route, \ - VppIpInterfaceAddress -from vpp_ip import VppIpAddress + VppIpInterfaceAddress, find_route_in_dump, find_mroute_in_dump +from vpp_ip import VppIpPuntPolicer, VppIpPuntRedirect from vpp_sub_interface import VppSubInterface, VppDot1QSubint, VppDot1ADSubint from vpp_papi import VppEnum +from vpp_neighbor import VppNeighbor +from vpp_lo_interface import VppLoInterface +from vpp_policer import VppPolicer NUM_PKTS = 67 @@ -89,7 +91,7 @@ class TestIPv4(VppTestCase): super(TestIPv4, self).tearDown() def show_commands_at_teardown(self): - self.logger.info(self.vapi.cli("show ip arp")) + self.logger.info(self.vapi.cli("show ip4 neighbors")) # info(self.vapi.cli("show ip fib")) # many entries def modify_packet(self, src_if, packet_size, pkt): @@ -213,6 +215,80 @@ class TestIPv4(VppTestCase): self.verify_capture(i, pkts) +class TestIPv4RouteLookup(VppTestCase): + """ IPv4 Route Lookup Test Case """ + routes = [] + + def route_lookup(self, prefix, exact): + return self.vapi.api(self.vapi.papi.ip_route_lookup, + { + 'table_id': 0, + 'exact': exact, + 'prefix': prefix, + }) + + @classmethod + def setUpClass(cls): + super(TestIPv4RouteLookup, cls).setUpClass() + + @classmethod + def tearDownClass(cls): + super(TestIPv4RouteLookup, cls).tearDownClass() + + def setUp(self): + super(TestIPv4RouteLookup, self).setUp() + + drop_nh = VppRoutePath("127.0.0.1", 0xffffffff, + type=FibPathType.FIB_PATH_TYPE_DROP) + + # Add 3 routes + r = VppIpRoute(self, "1.1.0.0", 16, [drop_nh]) + r.add_vpp_config() + self.routes.append(r) + + r = VppIpRoute(self, "1.1.1.0", 24, [drop_nh]) + r.add_vpp_config() + self.routes.append(r) + + r = VppIpRoute(self, "1.1.1.1", 32, [drop_nh]) + r.add_vpp_config() + self.routes.append(r) + + def tearDown(self): + # Remove the routes we added + for r in self.routes: + r.remove_vpp_config() + + super(TestIPv4RouteLookup, self).tearDown() + + def test_exact_match(self): + # Verify we find the host route + prefix = "1.1.1.1/32" + result = self.route_lookup(prefix, True) + assert (prefix == str(result.route.prefix)) + + # Verify we find a middle prefix route + prefix = "1.1.1.0/24" + result = self.route_lookup(prefix, True) + assert (prefix == str(result.route.prefix)) + + # Verify we do not find an available LPM. + with self.vapi.assert_negative_api_retval(): + self.route_lookup("1.1.1.2/32", True) + + def test_longest_prefix_match(self): + # verify we find lpm + lpm_prefix = "1.1.1.0/24" + result = self.route_lookup("1.1.1.2/32", False) + assert (lpm_prefix == str(result.route.prefix)) + + # Verify we find the exact when not requested + result = self.route_lookup(lpm_prefix, False) + assert (lpm_prefix == str(result.route.prefix)) + + # Can't seem to delete the default route so no negative LPM test. + + class TestIPv4IfAddrRoute(VppTestCase): """ IPv4 Interface Addr Route Test Case """ @@ -257,11 +333,9 @@ class TestIPv4IfAddrRoute(VppTestCase): """ # create two addresses, verify route not present - if_addr1 = VppIpInterfaceAddress(self, self.pg0, - VppIpAddress("10.10.10.10"), 24) - if_addr2 = VppIpInterfaceAddress(self, self.pg0, - VppIpAddress("10.10.10.20"), 24) - self.assertFalse(if_addr1.query_vpp_config()) # 10.10.10.0/24 + if_addr1 = VppIpInterfaceAddress(self, self.pg0, "10.10.10.10", 24) + if_addr2 = VppIpInterfaceAddress(self, self.pg0, "10.10.10.20", 24) + self.assertFalse(if_addr1.query_vpp_config()) # 10.10.10.10/24 self.assertFalse(find_route(self, "10.10.10.10", 32)) self.assertFalse(find_route(self, "10.10.10.20", 32)) self.assertFalse(find_route(self, "10.10.10.255", 32)) @@ -269,7 +343,7 @@ class TestIPv4IfAddrRoute(VppTestCase): # configure first address, verify route present if_addr1.add_vpp_config() - self.assertTrue(if_addr1.query_vpp_config()) # 10.10.10.0/24 + self.assertTrue(if_addr1.query_vpp_config()) # 10.10.10.10/24 self.assertTrue(find_route(self, "10.10.10.10", 32)) self.assertFalse(find_route(self, "10.10.10.20", 32)) self.assertTrue(find_route(self, "10.10.10.255", 32)) @@ -278,7 +352,8 @@ class TestIPv4IfAddrRoute(VppTestCase): # configure second address, delete first, verify route not removed if_addr2.add_vpp_config() if_addr1.remove_vpp_config() - self.assertTrue(if_addr1.query_vpp_config()) # 10.10.10.0/24 + self.assertFalse(if_addr1.query_vpp_config()) # 10.10.10.10/24 + self.assertTrue(if_addr2.query_vpp_config()) # 10.10.10.20/24 self.assertFalse(find_route(self, "10.10.10.10", 32)) self.assertTrue(find_route(self, "10.10.10.20", 32)) self.assertTrue(find_route(self, "10.10.10.255", 32)) @@ -286,7 +361,7 @@ class TestIPv4IfAddrRoute(VppTestCase): # delete second address, verify route removed if_addr2.remove_vpp_config() - self.assertFalse(if_addr1.query_vpp_config()) # 10.10.10.0/24 + self.assertFalse(if_addr2.query_vpp_config()) # 10.10.10.20/24 self.assertFalse(find_route(self, "10.10.10.10", 32)) self.assertFalse(find_route(self, "10.10.10.20", 32)) self.assertFalse(find_route(self, "10.10.10.255", 32)) @@ -337,6 +412,24 @@ class TestIPv4IfAddrRoute(VppTestCase): fib4_dump = self.vapi.ip_route_dump(0) self.assertTrue(lo_if.is_ip4_entry_in_fib_dump(fib4_dump)) + def test_ipv4_ifaddr_del(self): + """ Delete an interface address that does not exist """ + + loopbacks = self.create_loopback_interfaces(1) + lo = self.lo_interfaces[0] + + lo.config_ip4() + lo.admin_up() + + # + # try and remove pg0's subnet from lo + # + with self.vapi.assert_negative_api_retval(): + self.vapi.sw_interface_add_del_address( + sw_if_index=lo.sw_if_index, + prefix=self.pg0.local_ip4_prefix, + is_add=0) + class TestICMPEcho(VppTestCase): """ ICMP Echo Test Case """ @@ -450,11 +543,11 @@ class TestIPv4FibCrud(VppTestCase): pkts = [] for _ in range(count): - dst_addr = random.choice(routes).prefix.address + dst_addr = random.choice(routes).prefix.network_address info = self.create_packet_info(src_if, dst_if) payload = self.info_to_payload(info) p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) / - IP(src=src_if.remote_ip4, dst=dst_addr) / + IP(src=src_if.remote_ip4, dst=str(dst_addr)) / UDP(sport=1234, dport=1234) / Raw(payload)) info.data = p.copy() @@ -490,11 +583,15 @@ class TestIPv4FibCrud(VppTestCase): def verify_route_dump(self, routes): for r in routes: - self.assertTrue(find_route(self, r.prefix.address, r.prefix.len)) + self.assertTrue(find_route(self, + r.prefix.network_address, + r.prefix.prefixlen)) def verify_not_in_route_dump(self, routes): for r in routes: - self.assertFalse(find_route(self, r.prefix.address, r.prefix.len)) + self.assertFalse(find_route(self, + r.prefix.network_address, + r.prefix.prefixlen)) @classmethod def setUpClass(cls): @@ -687,7 +784,7 @@ class TestIPNull(VppTestCase): dst=self.pg0.local_mac) / IP(src=self.pg0.remote_ip4, dst="10.0.0.1") / UDP(sport=1234, dport=1234) / - Raw('\xa5' * 100)) + Raw(b'\xa5' * 100)) self.pg0.add_stream(p_unreach) self.pg_enable_capture(self.pg_interfaces) self.pg_start() @@ -720,7 +817,7 @@ class TestIPNull(VppTestCase): dst=self.pg0.local_mac) / IP(src=self.pg0.remote_ip4, dst="10.0.0.2") / UDP(sport=1234, dport=1234) / - Raw('\xa5' * 100)) + Raw(b'\xa5' * 100)) self.pg0.add_stream(p_prohibit) self.pg_enable_capture(self.pg_interfaces) @@ -743,7 +840,7 @@ class TestIPNull(VppTestCase): dst=self.pg0.local_mac) / IP(src=self.pg0.remote_ip4, dst="1.1.1.1") / UDP(sport=1234, dport=1234) / - Raw('\xa5' * 100)) + Raw(b'\xa5' * 100)) r1 = VppIpRoute(self, "1.1.1.0", 24, [VppRoutePath(self.pg1.remote_ip4, @@ -800,6 +897,9 @@ class TestIPDisabled(VppTestCase): def test_ip_disabled(self): """ IP Disabled """ + MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t + MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t + # # An (S,G). # one accepting interface, pg0, 2 forwarding interfaces @@ -808,23 +908,23 @@ class TestIPDisabled(VppTestCase): self, "0.0.0.0", "232.1.1.1", 32, - MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE, + MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE, [VppMRoutePath(self.pg1.sw_if_index, - MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT), + MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT), VppMRoutePath(self.pg0.sw_if_index, - MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)]) + MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)]) route_232_1_1_1.add_vpp_config() pu = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) / IP(src="10.10.10.10", dst=self.pg0.remote_ip4) / UDP(sport=1234, dport=1234) / - Raw('\xa5' * 100)) + Raw(b'\xa5' * 100)) pm = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) / IP(src="10.10.10.10", dst="232.1.1.1") / UDP(sport=1234, dport=1234) / - Raw('\xa5' * 100)) + Raw(b'\xa5' * 100)) # # PG1 does not forward IP traffic @@ -908,7 +1008,7 @@ class TestIPSubNets(VppTestCase): dst=self.pg1.local_mac) / IP(dst="10.10.10.10", src=self.pg0.local_ip4) / UDP(sport=1234, dport=1234) / - Raw('\xa5' * 100)) + Raw(b'\xa5' * 100)) self.pg1.add_stream(p) self.pg_enable_capture(self.pg_interfaces) @@ -922,18 +1022,18 @@ class TestIPSubNets(VppTestCase): self.vapi.sw_interface_add_del_address( sw_if_index=self.pg0.sw_if_index, - prefix=VppIpPrefix("10.10.10.10", 16).encode()) + prefix="10.10.10.10/16") pn = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) / IP(dst="10.10.0.0", src=self.pg0.local_ip4) / UDP(sport=1234, dport=1234) / - Raw('\xa5' * 100)) + Raw(b'\xa5' * 100)) pb = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) / IP(dst="10.10.255.255", src=self.pg0.local_ip4) / UDP(sport=1234, dport=1234) / - Raw('\xa5' * 100)) + Raw(b'\xa5' * 100)) self.send_and_assert_no_replies(self.pg1, pn, "IP Network address") self.send_and_assert_no_replies(self.pg1, pb, "IP Broadcast address") @@ -941,7 +1041,8 @@ class TestIPSubNets(VppTestCase): # remove the sub-net and we are forwarding via the cover again self.vapi.sw_interface_add_del_address( sw_if_index=self.pg0.sw_if_index, - prefix=VppIpPrefix("10.10.10.10", 16).encode(), is_add=0) + prefix="10.10.10.10/16", + is_add=0) self.pg1.add_stream(pn) self.pg_enable_capture(self.pg_interfaces) @@ -960,13 +1061,13 @@ class TestIPSubNets(VppTestCase): self.vapi.sw_interface_add_del_address( sw_if_index=self.pg0.sw_if_index, - prefix=VppIpPrefix("10.10.10.10", 31).encode()) + prefix="10.10.10.10/31") pn = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) / IP(dst="10.10.10.11", src=self.pg0.local_ip4) / UDP(sport=1234, dport=1234) / - Raw('\xa5' * 100)) + Raw(b'\xa5' * 100)) self.pg1.add_stream(pn) self.pg_enable_capture(self.pg_interfaces) @@ -977,7 +1078,7 @@ class TestIPSubNets(VppTestCase): # remove the sub-net and we are forwarding via the cover again self.vapi.sw_interface_add_del_address( sw_if_index=self.pg0.sw_if_index, - prefix=VppIpPrefix("10.10.10.10", 31).encode(), is_add=0) + prefix="10.10.10.10/31", is_add=0) self.pg1.add_stream(pn) self.pg_enable_capture(self.pg_interfaces) @@ -1037,6 +1138,9 @@ class TestIPLoadBalance(VppTestCase): def test_ip_load_balance(self): """ IP Load-Balancing """ + fhc = VppEnum.vl_api_ip_flow_hash_config_t + af = VppEnum.vl_api_address_family_t + # # An array of packets that differ only in the destination port # @@ -1052,7 +1156,7 @@ class TestIPLoadBalance(VppTestCase): for ii in range(NUM_PKTS): port_ip_hdr = (IP(dst="10.0.0.1", src="20.0.0.1") / UDP(sport=1234, dport=1234 + ii) / - Raw('\xa5' * 100)) + Raw(b'\xa5' * 100)) port_ip_pkts.append((Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / port_ip_hdr)) @@ -1063,7 +1167,7 @@ class TestIPLoadBalance(VppTestCase): src_ip_hdr = (IP(dst="10.0.0.1", src="20.0.0.%d" % ii) / UDP(sport=1234, dport=1234) / - Raw('\xa5' * 100)) + Raw(b'\xa5' * 100)) src_ip_pkts.append((Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / src_ip_hdr)) @@ -1105,7 +1209,12 @@ class TestIPLoadBalance(VppTestCase): # - now only the stream with differing source address will # load-balance # - self.vapi.set_ip_flow_hash(vrf_id=0, src=1, dst=1, sport=0, dport=0) + self.vapi.set_ip_flow_hash_v2( + af=af.ADDRESS_IP4, + table_id=0, + flow_hash_config=(fhc.IP_API_FLOW_HASH_SRC_IP | + fhc.IP_API_FLOW_HASH_DST_IP | + fhc.IP_API_FLOW_HASH_PROTO)) self.send_and_expect_load_balancing(self.pg0, src_ip_pkts, [self.pg1, self.pg2]) @@ -1117,7 +1226,8 @@ class TestIPLoadBalance(VppTestCase): # # change the flow hash config back to defaults # - self.vapi.set_ip_flow_hash(vrf_id=0, src=1, dst=1, sport=1, dport=1) + self.vapi.set_ip_flow_hash(vrf_id=0, src=1, dst=1, + proto=1, sport=1, dport=1) # # Recursive prefixes @@ -1132,12 +1242,12 @@ class TestIPLoadBalance(VppTestCase): dst=self.pg0.local_mac) / IP(dst="1.1.1.1", src="20.0.0.1") / UDP(sport=1234, dport=1234 + ii) / - Raw('\xa5' * 100))) + Raw(b'\xa5' * 100))) src_pkts.append((Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IP(dst="1.1.1.1", src="20.0.0.%d" % ii) / UDP(sport=1234, dport=1234) / - Raw('\xa5' * 100))) + Raw(b'\xa5' * 100))) route_10_0_0_2 = VppIpRoute(self, "10.0.0.2", 32, [VppRoutePath(self.pg3.remote_ip4, @@ -1220,7 +1330,7 @@ class TestIPLoadBalance(VppTestCase): dst=self.pg0.local_mac) / IP(dst="1.1.1.2", src="20.0.0.2") / UDP(sport=1234, dport=1234 + ii) / - Raw('\xa5' * 100))) + Raw(b'\xa5' * 100))) route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32, [VppRoutePath(self.pg3.remote_ip4, @@ -1256,7 +1366,7 @@ class TestIPLoadBalance(VppTestCase): dst=self.pg0.local_mac) / IP(dst="10.0.0.3", src="20.0.0.2") / UDP(sport=1234, dport=1234 + ii) / - Raw('\xa5' * 100)) + Raw(b'\xa5' * 100)) self.send_and_expect_one_itf(self.pg0, port_pkts, self.pg4) @@ -1308,7 +1418,7 @@ class TestIPVlan0(VppTestCase): IP(dst=self.pg1.remote_ip4, src=self.pg0.remote_ip4) / UDP(sport=1234, dport=1234) / - Raw('\xa5' * 100)) * NUM_PKTS + Raw(b'\xa5' * 100)) * NUM_PKTS # # Expect that packets sent on VLAN-0 are forwarded on the @@ -1369,7 +1479,7 @@ class TestIPPunt(VppTestCase): dst=self.pg0.local_mac) / IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) / UDP(sport=1234, dport=1234) / - Raw('\xa5' * 100)) + Raw(b'\xa5' * 100)) pkts = p * 1025 @@ -1377,18 +1487,19 @@ class TestIPPunt(VppTestCase): # Configure a punt redirect via pg1. # nh_addr = self.pg1.remote_ip4 - self.vapi.ip_punt_redirect(self.pg0.sw_if_index, - self.pg1.sw_if_index, - nh_addr) + ip_punt_redirect = VppIpPuntRedirect(self, self.pg0.sw_if_index, + self.pg1.sw_if_index, nh_addr) + ip_punt_redirect.add_vpp_config() self.send_and_expect(self.pg0, pkts, self.pg1) # # add a policer # - policer = self.vapi.policer_add_del(b"ip4-punt", 400, 0, 10, 0, - rate_type=1) - self.vapi.ip_punt_police(policer.policer_index) + policer = VppPolicer(self, "ip4-punt", 400, 0, 10, 0, rate_type=1) + policer.add_vpp_config() + ip_punt_policer = VppIpPuntPolicer(self, policer.policer_index) + ip_punt_policer.add_vpp_config() self.vapi.cli("clear trace") self.pg0.add_stream(pkts) @@ -1406,33 +1517,25 @@ class TestIPPunt(VppTestCase): # # remove the policer. back to full rx # - self.vapi.ip_punt_police(policer.policer_index, is_add=0) - self.vapi.policer_add_del(b"ip4-punt", 400, 0, 10, 0, - rate_type=1, is_add=0) + ip_punt_policer.remove_vpp_config() + policer.remove_vpp_config() self.send_and_expect(self.pg0, pkts, self.pg1) # # remove the redirect. expect full drop. # - self.vapi.ip_punt_redirect(self.pg0.sw_if_index, - self.pg1.sw_if_index, - nh_addr, - is_add=0) + ip_punt_redirect.remove_vpp_config() self.send_and_assert_no_replies(self.pg0, pkts, "IP no punt config") # # Add a redirect that is not input port selective # - self.vapi.ip_punt_redirect(0xffffffff, - self.pg1.sw_if_index, - nh_addr) + ip_punt_redirect = VppIpPuntRedirect(self, 0xffffffff, + self.pg1.sw_if_index, nh_addr) + ip_punt_redirect.add_vpp_config() self.send_and_expect(self.pg0, pkts, self.pg1) - - self.vapi.ip_punt_redirect(0xffffffff, - self.pg1.sw_if_index, - nh_addr, - is_add=0) + ip_punt_redirect.remove_vpp_config() def test_ip_punt_dump(self): """ IP4 punt redirect dump""" @@ -1441,22 +1544,22 @@ class TestIPPunt(VppTestCase): # Configure a punt redirects # nh_address = self.pg3.remote_ip4 - self.vapi.ip_punt_redirect(self.pg0.sw_if_index, - self.pg3.sw_if_index, - nh_address) - self.vapi.ip_punt_redirect(self.pg1.sw_if_index, - self.pg3.sw_if_index, - nh_address) - self.vapi.ip_punt_redirect(self.pg2.sw_if_index, - self.pg3.sw_if_index, - '0.0.0.0') + ipr_03 = VppIpPuntRedirect(self, self.pg0.sw_if_index, + self.pg3.sw_if_index, nh_address) + ipr_13 = VppIpPuntRedirect(self, self.pg1.sw_if_index, + self.pg3.sw_if_index, nh_address) + ipr_23 = VppIpPuntRedirect(self, self.pg2.sw_if_index, + self.pg3.sw_if_index, "0.0.0.0") + ipr_03.add_vpp_config() + ipr_13.add_vpp_config() + ipr_23.add_vpp_config() # # Dump pg0 punt redirects # - punts = self.vapi.ip_punt_redirect_dump(self.pg0.sw_if_index) - for p in punts: - self.assertEqual(p.punt.rx_sw_if_index, self.pg0.sw_if_index) + self.assertTrue(ipr_03.query_vpp_config()) + self.assertTrue(ipr_13.query_vpp_config()) + self.assertTrue(ipr_23.query_vpp_config()) # # Dump punt redirects for all interfaces @@ -1534,12 +1637,12 @@ class TestIPDeag(VppTestCase): dst=self.pg0.local_mac) / IP(src="5.5.5.5", dst="1.1.1.1") / TCP(sport=1234, dport=1234) / - Raw('\xa5' * 100)) + Raw(b'\xa5' * 100)) p_src = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IP(src="2.2.2.2", dst="1.1.1.2") / TCP(sport=1234, dport=1234) / - Raw('\xa5' * 100)) + Raw(b'\xa5' * 100)) pkts_dst = p_dst * 257 pkts_src = p_src * 257 @@ -1582,7 +1685,7 @@ class TestIPDeag(VppTestCase): dst=self.pg0.local_mac) / IP(src="2.2.2.4", dst="2.2.2.3") / TCP(sport=1234, dport=1234) / - Raw('\xa5' * 100)) + Raw(b'\xa5' * 100)) self.send_and_assert_no_replies(self.pg0, p_l * 257, "IP lookup loop") @@ -1630,7 +1733,7 @@ class TestIPInput(VppTestCase): dst=self.pg1.remote_ip4, len=40) / UDP(sport=1234, dport=1234) / - Raw('\xa5' * 100)) + Raw(b'\xa5' * 100)) rx = self.send_and_expect(self.pg0, p_short * NUM_PKTS, self.pg1) @@ -1643,7 +1746,7 @@ class TestIPInput(VppTestCase): dst=self.pg1.remote_ip4, len=400) / UDP(sport=1234, dport=1234) / - Raw('\xa5' * 100)) + Raw(b'\xa5' * 100)) rx = self.send_and_assert_no_replies(self.pg0, p_long * NUM_PKTS, "too long") @@ -1657,7 +1760,7 @@ class TestIPInput(VppTestCase): dst=self.pg1.remote_ip4, chksum=400) / UDP(sport=1234, dport=1234) / - Raw('\xa5' * 100)) + Raw(b'\xa5' * 100)) rx = self.send_and_assert_no_replies(self.pg0, p_chksum * NUM_PKTS, "bad checksum") @@ -1671,7 +1774,7 @@ class TestIPInput(VppTestCase): dst=self.pg1.remote_ip4, version=3) / UDP(sport=1234, dport=1234) / - Raw('\xa5' * 100)) + Raw(b'\xa5' * 100)) rx = self.send_and_assert_no_replies(self.pg0, p_ver * NUM_PKTS, "funky version") @@ -1685,7 +1788,7 @@ class TestIPInput(VppTestCase): dst=self.pg1.remote_ip4, frag=1) / UDP(sport=1234, dport=1234) / - Raw('\xa5' * 100)) + Raw(b'\xa5' * 100)) rx = self.send_and_assert_no_replies(self.pg0, p_frag * NUM_PKTS, "frag offset") @@ -1699,7 +1802,7 @@ class TestIPInput(VppTestCase): dst=self.pg1.remote_ip4, ttl=1) / UDP(sport=1234, dport=1234) / - Raw('\xa5' * 100)) + Raw(b'\xa5' * 100)) rx = self.send_and_expect(self.pg0, p_ttl * NUM_PKTS, self.pg0) @@ -1721,7 +1824,7 @@ class TestIPInput(VppTestCase): dst=self.pg1.remote_ip4, ttl=10, flags='DF') / UDP(sport=1234, dport=1234) / - Raw('\xa5' * 2000)) + Raw(b'\xa5' * 2000)) self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1500, 0, 0, 0]) @@ -1749,7 +1852,7 @@ class TestIPInput(VppTestCase): IP(src="0.0.0.0", dst=self.pg0.local_ip4) / ICMP(id=4, seq=4) / - Raw(load='\x0a' * 18)) + Raw(load=b'\x0a' * 18)) rx = self.send_and_assert_no_replies(self.pg0, p_s0 * 17) p_s0 = (Ether(src=self.pg0.remote_mac, @@ -1757,7 +1860,7 @@ class TestIPInput(VppTestCase): IP(src="255.255.255.255", dst=self.pg0.local_ip4) / ICMP(id=4, seq=4) / - Raw(load='\x0a' * 18)) + Raw(load=b'\x0a' * 18)) rx = self.send_and_assert_no_replies(self.pg0, p_s0 * 17) @@ -1799,13 +1902,13 @@ class TestIPDirectedBroadcast(VppTestCase): IP(src="1.1.1.1", dst=self.pg0._local_ip4_bcast) / UDP(sport=1234, dport=1234) / - Raw('\xa5' * 2000)) + Raw(b'\xa5' * 2000)) p1 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IP(src="1.1.1.1", dst=self.pg1._local_ip4_bcast) / UDP(sport=1234, dport=1234) / - Raw('\xa5' * 2000)) + Raw(b'\xa5' * 2000)) self.pg0.config_ip4() self.pg0.resolve_arp() @@ -1881,13 +1984,13 @@ class TestIPLPM(VppTestCase): IP(src="1.1.1.1", dst="10.1.1.1") / UDP(sport=1234, dport=1234) / - Raw('\xa5' * 2000)) + Raw(b'\xa5' * 2000)) p_24 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IP(src="1.1.1.1", dst="10.1.2.1") / UDP(sport=1234, dport=1234) / - Raw('\xa5' * 2000)) + Raw(b'\xa5' * 2000)) self.logger.info(self.vapi.cli("sh ip fib mtrie")) rx = self.send_and_expect(self.pg0, p_8 * NUM_PKTS, self.pg2) @@ -1918,12 +2021,19 @@ class TestIPv4Frag(VppTestCase): def test_frag_large_packets(self): """ Fragmentation of large packets """ + self.vapi.cli("adjacency counters enable") + p = (Ether(dst=self.src_if.local_mac, src=self.src_if.remote_mac) / IP(src=self.src_if.remote_ip4, dst=self.dst_if.remote_ip4) / UDP(sport=1234, dport=5678) / Raw()) self.extend_packet(p, 6000, "abcde") saved_payload = p[Raw].load + nbr = VppNeighbor(self, + self.dst_if.sw_if_index, + self.dst_if.remote_mac, + self.dst_if.remote_ip4).add_vpp_config() + # Force fragmentation by setting MTU of output interface # lower than packet size self.vapi.sw_interface_set_mtu(self.dst_if.sw_if_index, @@ -1937,6 +2047,9 @@ class TestIPv4Frag(VppTestCase): # cannot be larger then VPP buffer size (which is 2048) packets = self.dst_if.get_capture(3) + # we should show 3 packets thru the neighbor + self.assertEqual(3, nbr.get_stats()['packets']) + # Assume VPP sends the fragments in order payload = b'' for p in packets: @@ -1948,5 +2061,366 @@ class TestIPv4Frag(VppTestCase): self.assert_equal(payload, saved_payload, "payload") +class TestIPReplace(VppTestCase): + """ IPv4 Table Replace """ + + @classmethod + def setUpClass(cls): + super(TestIPReplace, cls).setUpClass() + + @classmethod + def tearDownClass(cls): + super(TestIPReplace, cls).tearDownClass() + + def setUp(self): + super(TestIPReplace, self).setUp() + + self.create_pg_interfaces(range(4)) + + table_id = 1 + self.tables = [] + + for i in self.pg_interfaces: + i.admin_up() + i.config_ip4() + i.resolve_arp() + i.generate_remote_hosts(2) + self.tables.append(VppIpTable(self, table_id).add_vpp_config()) + table_id += 1 + + def tearDown(self): + super(TestIPReplace, self).tearDown() + for i in self.pg_interfaces: + i.admin_down() + i.unconfig_ip4() + + def test_replace(self): + """ IP Table Replace """ + + MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t + MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t + N_ROUTES = 20 + links = [self.pg0, self.pg1, self.pg2, self.pg3] + routes = [[], [], [], []] + + # load up the tables with some routes + for ii, t in enumerate(self.tables): + for jj in range(N_ROUTES): + uni = VppIpRoute( + self, "10.0.0.%d" % jj, 32, + [VppRoutePath(links[ii].remote_hosts[0].ip4, + links[ii].sw_if_index), + VppRoutePath(links[ii].remote_hosts[1].ip4, + links[ii].sw_if_index)], + table_id=t.table_id).add_vpp_config() + multi = VppIpMRoute( + self, "0.0.0.0", + "239.0.0.%d" % jj, 32, + MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE, + [VppMRoutePath(self.pg0.sw_if_index, + MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT), + VppMRoutePath(self.pg1.sw_if_index, + MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD), + VppMRoutePath(self.pg2.sw_if_index, + MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD), + VppMRoutePath(self.pg3.sw_if_index, + MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)], + table_id=t.table_id).add_vpp_config() + routes[ii].append({'uni': uni, + 'multi': multi}) + + # + # replace the tables a few times + # + for kk in range(3): + # replace_begin each table + for t in self.tables: + t.replace_begin() + + # all the routes are still there + for ii, t in enumerate(self.tables): + dump = t.dump() + mdump = t.mdump() + for r in routes[ii]: + self.assertTrue(find_route_in_dump(dump, r['uni'], t)) + self.assertTrue(find_mroute_in_dump(mdump, r['multi'], t)) + + # redownload the even numbered routes + for ii, t in enumerate(self.tables): + for jj in range(0, N_ROUTES, 2): + routes[ii][jj]['uni'].add_vpp_config() + routes[ii][jj]['multi'].add_vpp_config() + + # signal each table replace_end + for t in self.tables: + t.replace_end() + + # we should find the even routes, but not the odd + for ii, t in enumerate(self.tables): + dump = t.dump() + mdump = t.mdump() + for jj in range(0, N_ROUTES, 2): + self.assertTrue(find_route_in_dump( + dump, routes[ii][jj]['uni'], t)) + self.assertTrue(find_mroute_in_dump( + mdump, routes[ii][jj]['multi'], t)) + for jj in range(1, N_ROUTES - 1, 2): + self.assertFalse(find_route_in_dump( + dump, routes[ii][jj]['uni'], t)) + self.assertFalse(find_mroute_in_dump( + mdump, routes[ii][jj]['multi'], t)) + + # reload all the routes + for ii, t in enumerate(self.tables): + for r in routes[ii]: + r['uni'].add_vpp_config() + r['multi'].add_vpp_config() + + # all the routes are still there + for ii, t in enumerate(self.tables): + dump = t.dump() + mdump = t.mdump() + for r in routes[ii]: + self.assertTrue(find_route_in_dump(dump, r['uni'], t)) + self.assertTrue(find_mroute_in_dump(mdump, r['multi'], t)) + + # + # finally flush the tables for good measure + # + for t in self.tables: + t.flush() + self.assertEqual(len(t.dump()), 5) + self.assertEqual(len(t.mdump()), 3) + + +class TestIPCover(VppTestCase): + """ IPv4 Table Cover """ + + @classmethod + def setUpClass(cls): + super(TestIPCover, cls).setUpClass() + + @classmethod + def tearDownClass(cls): + super(TestIPCover, cls).tearDownClass() + + def setUp(self): + super(TestIPCover, self).setUp() + + self.create_pg_interfaces(range(4)) + + table_id = 1 + self.tables = [] + + for i in self.pg_interfaces: + i.admin_up() + i.config_ip4() + i.resolve_arp() + i.generate_remote_hosts(2) + self.tables.append(VppIpTable(self, table_id).add_vpp_config()) + table_id += 1 + + def tearDown(self): + super(TestIPCover, self).tearDown() + for i in self.pg_interfaces: + i.admin_down() + i.unconfig_ip4() + + def test_cover(self): + """ IP Table Cover """ + + # add a loop back with a /32 prefix + lo = VppLoInterface(self) + lo.admin_up() + a = VppIpInterfaceAddress(self, lo, "127.0.0.1", 32).add_vpp_config() + + # add a neighbour that matches the loopback's /32 + nbr = VppNeighbor(self, + lo.sw_if_index, + lo.remote_mac, + "127.0.0.1").add_vpp_config() + + # add the default route which will be the cover for /32 + r = VppIpRoute(self, "0.0.0.0", 0, + [VppRoutePath("127.0.0.1", + lo.sw_if_index)], + register=False).add_vpp_config() + + # add/remove/add a longer mask cover + r8 = VppIpRoute(self, "127.0.0.0", 8, + [VppRoutePath("127.0.0.1", + lo.sw_if_index)]).add_vpp_config() + r8.remove_vpp_config() + r8.add_vpp_config() + r8.remove_vpp_config() + + # remove the default route + r.remove_vpp_config() + + # remove the interface prefix + a.remove_vpp_config() + + +class TestIP4Replace(VppTestCase): + """ IPv4 Interface Address Replace """ + + @classmethod + def setUpClass(cls): + super(TestIP4Replace, cls).setUpClass() + + @classmethod + def tearDownClass(cls): + super(TestIP4Replace, cls).tearDownClass() + + def setUp(self): + super(TestIP4Replace, self).setUp() + + self.create_pg_interfaces(range(4)) + + for i in self.pg_interfaces: + i.admin_up() + + def tearDown(self): + super(TestIP4Replace, self).tearDown() + for i in self.pg_interfaces: + i.admin_down() + + def get_n_pfxs(self, intf): + return len(self.vapi.ip_address_dump(intf.sw_if_index)) + + def test_replace(self): + """ IP interface address replace """ + + intf_pfxs = [[], [], [], []] + + # add prefixes to each of the interfaces + for i in range(len(self.pg_interfaces)): + intf = self.pg_interfaces[i] + + # 172.16.x.1/24 + addr = "172.16.%d.1" % intf.sw_if_index + a = VppIpInterfaceAddress(self, intf, addr, 24).add_vpp_config() + intf_pfxs[i].append(a) + + # 172.16.x.2/24 - a different address in the same subnet as above + addr = "172.16.%d.2" % intf.sw_if_index + a = VppIpInterfaceAddress(self, intf, addr, 24).add_vpp_config() + intf_pfxs[i].append(a) + + # 172.15.x.2/24 - a different address and subnet + addr = "172.15.%d.2" % intf.sw_if_index + a = VppIpInterfaceAddress(self, intf, addr, 24).add_vpp_config() + intf_pfxs[i].append(a) + + # a dump should n_address in it + for intf in self.pg_interfaces: + self.assertEqual(self.get_n_pfxs(intf), 3) + + # + # remove all the address thru a replace + # + self.vapi.sw_interface_address_replace_begin() + self.vapi.sw_interface_address_replace_end() + for intf in self.pg_interfaces: + self.assertEqual(self.get_n_pfxs(intf), 0) + + # + # add all the interface addresses back + # + for p in intf_pfxs: + for v in p: + v.add_vpp_config() + for intf in self.pg_interfaces: + self.assertEqual(self.get_n_pfxs(intf), 3) + + # + # replace again, but this time update/re-add the address on the first + # two interfaces + # + self.vapi.sw_interface_address_replace_begin() + + for p in intf_pfxs[:2]: + for v in p: + v.add_vpp_config() + + self.vapi.sw_interface_address_replace_end() + + # on the first two the address still exist, + # on the other two they do not + for intf in self.pg_interfaces[:2]: + self.assertEqual(self.get_n_pfxs(intf), 3) + for p in intf_pfxs[:2]: + for v in p: + self.assertTrue(v.query_vpp_config()) + for intf in self.pg_interfaces[2:]: + self.assertEqual(self.get_n_pfxs(intf), 0) + + # + # add all the interface addresses back on the last two + # + for p in intf_pfxs[2:]: + for v in p: + v.add_vpp_config() + for intf in self.pg_interfaces: + self.assertEqual(self.get_n_pfxs(intf), 3) + + # + # replace again, this time add different prefixes on all the interfaces + # + self.vapi.sw_interface_address_replace_begin() + + pfxs = [] + for intf in self.pg_interfaces: + # 172.18.x.1/24 + addr = "172.18.%d.1" % intf.sw_if_index + pfxs.append(VppIpInterfaceAddress(self, intf, addr, + 24).add_vpp_config()) + + self.vapi.sw_interface_address_replace_end() + + # only .18 should exist on each interface + for intf in self.pg_interfaces: + self.assertEqual(self.get_n_pfxs(intf), 1) + for pfx in pfxs: + self.assertTrue(pfx.query_vpp_config()) + + # + # remove everything + # + self.vapi.sw_interface_address_replace_begin() + self.vapi.sw_interface_address_replace_end() + for intf in self.pg_interfaces: + self.assertEqual(self.get_n_pfxs(intf), 0) + + # + # add prefixes to each interface. post-begin add the prefix from + # interface X onto interface Y. this would normally be an error + # since it would generate a 'duplicate address' warning. but in + # this case, since what is newly downloaded is sane, it's ok + # + for intf in self.pg_interfaces: + # 172.18.x.1/24 + addr = "172.18.%d.1" % intf.sw_if_index + VppIpInterfaceAddress(self, intf, addr, 24).add_vpp_config() + + self.vapi.sw_interface_address_replace_begin() + + pfxs = [] + for intf in self.pg_interfaces: + # 172.18.x.1/24 + addr = "172.18.%d.1" % (intf.sw_if_index + 1) + pfxs.append(VppIpInterfaceAddress(self, intf, + addr, 24).add_vpp_config()) + + self.vapi.sw_interface_address_replace_end() + + self.logger.info(self.vapi.cli("sh int addr")) + + for intf in self.pg_interfaces: + self.assertEqual(self.get_n_pfxs(intf), 1) + for pfx in pfxs: + self.assertTrue(pfx.query_vpp_config()) + + if __name__ == '__main__': unittest.main(testRunner=VppTestRunner)