X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=test%2Ftest_dhcp.py;h=bdc5df7a26731144d035a92b4025bb4383f752d4;hb=7f9b7f9f492d1748d8ba025b3a713058fdb1943d;hp=39133a35bd1321d7a03f0c1a28f67c0975ed075e;hpb=daff1784037376f4a5caec2f5975f9b5fc23d5a4;p=vpp.git diff --git a/test/test_dhcp.py b/test/test_dhcp.py index 39133a35bd1..bdc5df7a267 100644 --- a/test/test_dhcp.py +++ b/test/test_dhcp.py @@ -8,7 +8,7 @@ from framework import VppTestCase, VppTestRunner, running_extended_tests from vpp_neighbor import VppNeighbor from vpp_ip_route import find_route, VppIpTable from util import mk_ll_addr - +import scapy.compat from scapy.layers.l2 import Ether, getmacbyip, ARP from scapy.layers.inet import IP, UDP, ICMP from scapy.layers.inet6 import IPv6, in6_getnsmac @@ -20,7 +20,7 @@ from scapy.layers.dhcp6 import DHCP6, DHCP6_Solicit, DHCP6_RelayForward, \ from socket import AF_INET, AF_INET6 from scapy.utils import inet_pton, inet_ntop from scapy.utils6 import in6_ptop -from util import mactobinary +from vpp_papi import mac_pton DHCP4_CLIENT_PORT = 68 DHCP4_SERVER_PORT = 67 @@ -31,6 +31,14 @@ DHCP6_SERVER_PORT = 546 class TestDHCP(VppTestCase): """ DHCP Test Case """ + @classmethod + def setUpClass(cls): + super(TestDHCP, cls).setUpClass() + + @classmethod + def tearDownClass(cls): + super(TestDHCP, cls).tearDownClass() + def setUp(self): super(TestDHCP, self).setUp() @@ -361,6 +369,16 @@ class TestDHCP(VppTestCase): # not sure why this is not decoding # adv = pkt[DHCP6_Advertise] + def wait_for_no_route(self, address, length, + n_tries=50, s_time=1): + while (n_tries): + if not find_route(self, address, length): + return True + n_tries = n_tries - 1 + self.sleep(s_time) + + return False + def test_dhcp_proxy(self): """ DHCPv4 Proxy """ @@ -481,7 +499,7 @@ class TestDHCP(VppTestCase): # # 1. not our IP address = not checked by VPP? so offer is replayed # to client - bad_ip = option_82[0:8] + chr(33) + option_82[9:] + bad_ip = option_82[0:8] + scapy.compat.chb(33) + option_82[9:] p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) / @@ -495,7 +513,7 @@ class TestDHCP(VppTestCase): "DHCP offer option 82 bad address") # 2. Not a sw_if_index VPP knows - bad_if_index = option_82[0:2] + chr(33) + option_82[3:] + bad_if_index = option_82[0:2] + scapy.compat.chb(33) + option_82[3:] p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) / @@ -1053,8 +1071,7 @@ class TestDHCP(VppTestCase): nd_entry = VppNeighbor(self, self.pg1.sw_if_index, self.pg1.remote_hosts[1].mac, - self.pg1.remote_hosts[1].ip6, - af=AF_INET6) + self.pg1.remote_hosts[1].ip6) nd_entry.add_vpp_config() # @@ -1205,7 +1222,7 @@ class TestDHCP(VppTestCase): # # Configure DHCP client on PG3 and capture the discover sent # - self.vapi.dhcp_client(self.pg3.sw_if_index, hostname) + self.vapi.dhcp_client_config(self.pg3.sw_if_index, hostname) rx = self.pg3.get_capture(1) @@ -1219,10 +1236,10 @@ class TestDHCP(VppTestCase): UDP(sport=DHCP4_SERVER_PORT, dport=DHCP4_CLIENT_PORT) / BOOTP(op=1, yiaddr=self.pg3.local_ip4, - chaddr=mactobinary(self.pg3.local_mac)) / + chaddr=mac_pton(self.pg3.local_mac)) / DHCP(options=[('message-type', 'offer'), ('server_id', self.pg3.remote_ip4), - ('end')])) + 'end'])) self.pg3.add_stream(p_offer) self.pg_enable_capture(self.pg_interfaces) @@ -1233,19 +1250,19 @@ class TestDHCP(VppTestCase): self.pg3.local_ip4) # - # Send an acknowloedgement + # Send an acknowledgment # p_ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) / IP(src=self.pg3.remote_ip4, dst="255.255.255.255") / UDP(sport=DHCP4_SERVER_PORT, dport=DHCP4_CLIENT_PORT) / BOOTP(op=1, yiaddr=self.pg3.local_ip4, - chaddr=mactobinary(self.pg3.local_mac)) / + chaddr=mac_pton(self.pg3.local_mac)) / DHCP(options=[('message-type', 'ack'), ('subnet_mask', "255.255.255.0"), ('router', self.pg3.remote_ip4), ('server_id', self.pg3.remote_ip4), ('lease_time', 43200), - ('end')])) + 'end'])) self.pg3.add_stream(p_ack) self.pg_enable_capture(self.pg_interfaces) @@ -1268,13 +1285,14 @@ class TestDHCP(VppTestCase): # remove the left over ARP entry self.vapi.ip_neighbor_add_del(self.pg3.sw_if_index, - mactobinary(self.pg3.remote_mac), + self.pg3.remote_mac, self.pg3.remote_ip4, is_add=0) + # # remove the DHCP config # - self.vapi.dhcp_client(self.pg3.sw_if_index, hostname, is_add=0) + self.vapi.dhcp_client_config(self.pg3.sw_if_index, hostname, is_add=0) # # and now the route should be gone @@ -1288,14 +1306,19 @@ class TestDHCP(VppTestCase): self.pg3.admin_down() self.sleep(1) self.pg3.admin_up() - self.vapi.dhcp_client(self.pg3.sw_if_index, hostname, - client_id=self.pg3.local_mac) + self.vapi.dhcp_client_config(self.pg3.sw_if_index, hostname, + client_id=self.pg3.local_mac) rx = self.pg3.get_capture(1) self.verify_orig_dhcp_discover(rx[0], self.pg3, hostname, self.pg3.local_mac) + # TODO: VPP DHCP client should not accept DHCP OFFER message with + # the XID (Transaction ID) not matching the XID of the most recent + # DHCP DISCOVERY message. + # Such DHCP OFFER message must be silently discarded - RFC2131. + # Reported in Jira ticket: VPP-99 self.pg3.add_stream(p_offer) self.pg_enable_capture(self.pg_interfaces) self.pg_start() @@ -1311,13 +1334,13 @@ class TestDHCP(VppTestCase): IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) / UDP(sport=DHCP4_SERVER_PORT, dport=DHCP4_CLIENT_PORT) / BOOTP(op=1, yiaddr=self.pg3.local_ip4, - chaddr=mactobinary(self.pg3.local_mac)) / + chaddr=mac_pton(self.pg3.local_mac)) / DHCP(options=[('message-type', 'ack'), ('subnet_mask', "255.255.255.0"), ('router', self.pg3.remote_ip4), ('server_id', self.pg3.remote_ip4), ('lease_time', 43200), - ('end')])) + 'end'])) self.pg3.add_stream(p_ack) self.pg_enable_capture(self.pg_interfaces) @@ -1341,7 +1364,7 @@ class TestDHCP(VppTestCase): # # remove the DHCP config # - self.vapi.dhcp_client(self.pg3.sw_if_index, hostname, is_add=0) + self.vapi.dhcp_client_config(self.pg3.sw_if_index, hostname, is_add=0) self.assertFalse(find_route(self, self.pg3.local_ip4, 32)) self.assertFalse(find_route(self, self.pg3.local_ip4, 24)) @@ -1353,8 +1376,8 @@ class TestDHCP(VppTestCase): # # Configure DHCP client on PG3 and capture the discover sent # - self.vapi.dhcp_client(self.pg3.sw_if_index, hostname, - set_broadcast_flag=0) + self.vapi.dhcp_client_config(self.pg3.sw_if_index, hostname, + set_broadcast_flag=0) rx = self.pg3.get_capture(1) @@ -1369,10 +1392,10 @@ class TestDHCP(VppTestCase): IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) / UDP(sport=DHCP4_SERVER_PORT, dport=DHCP4_CLIENT_PORT) / BOOTP(op=1, yiaddr=self.pg3.local_ip4, - chaddr=mactobinary(self.pg3.local_mac)) / + chaddr=mac_pton(self.pg3.local_mac)) / DHCP(options=[('message-type', 'offer'), ('server_id', self.pg3.remote_ip4), - ('end')])) + 'end'])) self.pg3.add_stream(p_offer) self.pg_enable_capture(self.pg_interfaces) @@ -1384,19 +1407,19 @@ class TestDHCP(VppTestCase): broadcast=0) # - # Send an acknowloedgement + # Send an acknowledgment # p_ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) / IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) / UDP(sport=DHCP4_SERVER_PORT, dport=DHCP4_CLIENT_PORT) / BOOTP(op=1, yiaddr=self.pg3.local_ip4, - chaddr=mactobinary(self.pg3.local_mac)) / + chaddr=mac_pton(self.pg3.local_mac)) / DHCP(options=[('message-type', 'ack'), ('subnet_mask', "255.255.255.0"), ('router', self.pg3.remote_ip4), ('server_id', self.pg3.remote_ip4), ('lease_time', 43200), - ('end')])) + 'end'])) self.pg3.add_stream(p_ack) self.pg_enable_capture(self.pg_interfaces) @@ -1419,7 +1442,7 @@ class TestDHCP(VppTestCase): # remove the left over ARP entry self.vapi.ip_neighbor_add_del(self.pg3.sw_if_index, - mactobinary(self.pg3.remote_mac), + self.pg3.remote_mac, self.pg3.remote_ip4, is_add=0) @@ -1448,7 +1471,7 @@ class TestDHCP(VppTestCase): # # remove the DHCP config # - self.vapi.dhcp_client(self.pg3.sw_if_index, hostname, is_add=0) + self.vapi.dhcp_client_config(self.pg3.sw_if_index, hostname, is_add=0) # # and now the route should be gone @@ -1456,6 +1479,91 @@ class TestDHCP(VppTestCase): self.assertFalse(find_route(self, self.pg3.local_ip4, 32)) self.assertFalse(find_route(self, self.pg3.local_ip4, 24)) + # + # Start the procedure again. Use requested lease time option. + # + self.pg3.admin_down() + self.sleep(1) + self.pg3.admin_up() + self.vapi.dhcp_client_config(self.pg3.sw_if_index, hostname) + + rx = self.pg3.get_capture(1) + + self.verify_orig_dhcp_discover(rx[0], self.pg3, hostname) + + # + # Send back on offer with requested lease time, expect the request + # + lease_time = 1 + p_offer = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) / + IP(src=self.pg3.remote_ip4, dst='255.255.255.255') / + UDP(sport=DHCP4_SERVER_PORT, dport=DHCP4_CLIENT_PORT) / + BOOTP(op=1, + yiaddr=self.pg3.local_ip4, + chaddr=mac_pton(self.pg3.local_mac)) / + DHCP(options=[('message-type', 'offer'), + ('server_id', self.pg3.remote_ip4), + ('lease_time', lease_time), + 'end'])) + + self.pg3.add_stream(p_offer) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + + rx = self.pg3.get_capture(1) + self.verify_orig_dhcp_request(rx[0], self.pg3, hostname, + self.pg3.local_ip4) + + # + # Send an acknowledgment + # + p_ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) / + IP(src=self.pg3.remote_ip4, dst='255.255.255.255') / + UDP(sport=DHCP4_SERVER_PORT, dport=DHCP4_CLIENT_PORT) / + BOOTP(op=1, yiaddr=self.pg3.local_ip4, + chaddr=mac_pton(self.pg3.local_mac)) / + DHCP(options=[('message-type', 'ack'), + ('subnet_mask', '255.255.255.0'), + ('router', self.pg3.remote_ip4), + ('server_id', self.pg3.remote_ip4), + ('lease_time', lease_time), + 'end'])) + + self.pg3.add_stream(p_ack) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + + # + # We'll get an ARP request for the router address + # + rx = self.pg3.get_capture(1) + + self.assertEqual(rx[0][ARP].pdst, self.pg3.remote_ip4) + + # + # At the end of this procedure there should be a connected route + # in the FIB + # + self.assertTrue(find_route(self, self.pg3.local_ip4, 32)) + self.assertTrue(find_route(self, self.pg3.local_ip4, 24)) + + # remove the left over ARP entry + self.vapi.ip_neighbor_add_del(self.pg3.sw_if_index, + self.pg3.remote_mac, + self.pg3.remote_ip4, + is_add=0) + + # + # the route should be gone after the lease expires + # + self.assertTrue(self.wait_for_no_route(self.pg3.local_ip4, 32)) + self.assertTrue(self.wait_for_no_route(self.pg3.local_ip4, 24)) + + # + # remove the DHCP config + # + self.vapi.dhcp_client_config(self.pg3.sw_if_index, hostname, is_add=0) + if __name__ == '__main__': unittest.main(testRunner=VppTestRunner)