1# Copyright (c) 2012 The Chromium OS Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5import logging 6import time 7 8from autotest_lib.client.common_lib import error 9from autotest_lib.client.cros import dhcp_handling_rule 10from autotest_lib.client.cros import dhcp_packet 11from autotest_lib.client.cros import dhcp_test_base 12 13# dhcpcd has a 20 second minimal accepted lease time 14LEASE_TIME_SECONDS = 20 15# dhcpcd should request a renewal after this many seconds. 16LEASE_T1_TIME = 10 17# dhcpcd will broadcast a REQUEST after this many seconds. 18LEASE_T2_TIME = 15 19# We had better have lost the lease 25 seconds after we gained it. 20DHCP_RENEWAL_TIMEOUT_SECONDS = 25 21# We'll fill in the subnet and give this address to the client. 22INTENDED_IP_SUFFIX = "0.0.0.101" 23# How far off the expected deadlines we'll accept the T1/T2 packets. 24RENEWAL_TIME_DELTA_SECONDS = 2.0 25# Time by which we are sure shill will give up on the DHCP client. 26DHCP_ATTEMPT_TIMEOUT_SECONDS = 40 27 28class network_DhcpRenew(dhcp_test_base.DhcpTestBase): 29 """Tests DHCP renewal process in the connection manager.""" 30 def test_body(self): 31 subnet_mask = self.ethernet_pair.interface_subnet_mask 32 intended_ip = dhcp_test_base.DhcpTestBase.rewrite_ip_suffix( 33 subnet_mask, 34 self.server_ip, 35 INTENDED_IP_SUFFIX) 36 # Two real name servers, and a bogus one to be unpredictable. 37 dns_servers = ["8.8.8.8", "8.8.4.4", "192.168.87.88"] 38 domain_name = "corp.google.com" 39 dns_search_list = [ 40 "corgie.google.com", 41 "lies.google.com", 42 "that.is.a.tasty.burger.google.com", 43 ] 44 # This is the pool of information the server will give out to the client 45 # upon request. 46 dhcp_options = { 47 dhcp_packet.OPTION_SERVER_ID : self.server_ip, 48 dhcp_packet.OPTION_SUBNET_MASK : subnet_mask, 49 dhcp_packet.OPTION_IP_LEASE_TIME : LEASE_TIME_SECONDS, 50 dhcp_packet.OPTION_REQUESTED_IP : intended_ip, 51 dhcp_packet.OPTION_DNS_SERVERS : dns_servers, 52 dhcp_packet.OPTION_DOMAIN_NAME : domain_name, 53 dhcp_packet.OPTION_DNS_DOMAIN_SEARCH_LIST : dns_search_list, 54 dhcp_packet.OPTION_RENEWAL_T1_TIME_VALUE : LEASE_T1_TIME, 55 dhcp_packet.OPTION_REBINDING_T2_TIME_VALUE : LEASE_T2_TIME, 56 } 57 self.negotiate_and_check_lease(dhcp_options) 58 # This is very imprecise, since there is some built in delay in 59 # negotiate_new_lease() for settings propagations, but we're not 60 # interested in microsecond timings anyway. 61 lease_start_time = time.time() 62 t1_deadline = lease_start_time + LEASE_T1_TIME 63 t2_deadline = lease_start_time + LEASE_T2_TIME 64 # DHCP standard forbids to include "server ID" and "requested IP" 65 # options during RENEW/REBIND (T1/T2 tiemouts) 66 dhcp_opts_rr = dhcp_options.copy() 67 del dhcp_opts_rr[dhcp_packet.OPTION_SERVER_ID] 68 del dhcp_opts_rr[dhcp_packet.OPTION_REQUESTED_IP] 69 # Ignore the T1 deadline packet. 70 t1_handler = dhcp_handling_rule.DhcpHandlingRule_RespondToRequest( 71 intended_ip, 72 self.server_ip, 73 dhcp_opts_rr, {}, 74 should_respond=False, 75 expect_server_ip_set=False) 76 t1_handler.target_time_seconds = t1_deadline 77 t1_handler.allowable_time_delta_seconds = RENEWAL_TIME_DELTA_SECONDS 78 t2_handler = dhcp_handling_rule.DhcpHandlingRule_RespondToPostT2Request( 79 intended_ip, 80 self.server_ip, 81 dhcp_opts_rr, {}, 82 should_respond=False) 83 t2_handler.target_time_seconds = t2_deadline 84 t2_handler.allowable_time_delta_seconds = RENEWAL_TIME_DELTA_SECONDS 85 discovery_handler = \ 86 dhcp_handling_rule.DhcpHandlingRule_RespondToDiscovery( 87 intended_ip, 88 self.server_ip, 89 dhcp_options, 90 {}, 91 should_respond=False) 92 rules = [t1_handler, t2_handler, discovery_handler] 93 rules[-1].is_final_handler = True 94 self.server.start_test(rules, DHCP_RENEWAL_TIMEOUT_SECONDS) 95 self.server.wait_for_test_to_finish() 96 if not self.server.last_test_passed: 97 raise error.TestFail("Test server didn't get all the messages it " 98 "was told to expect for renewal.") 99 100 # The service should leave the connected state after shill attempts 101 # one last DHCP attempt from scratch. We may miss the transition to the 102 # "idle" state since the system immediately attempts to re-connect, so 103 # we also test for the "configuration" state. 104 service = self.find_ethernet_service( 105 self.ethernet_pair.peer_interface_name) 106 (successful, state, duration) = self.shill_proxy.wait_for_property_in( 107 service, 108 self.shill_proxy.SERVICE_PROPERTY_STATE, 109 ('failure', 'idle', 'configuration'), 110 DHCP_ATTEMPT_TIMEOUT_SECONDS) 111 if not successful: 112 raise error.TestFail('Service failed to go idle in %ds (state %s)' % 113 (duration, state)) 114 logging.info('In state "%s" after %d seconds', state, duration) 115