DHCP initial timeout 0.25s from 4s
Connecting to wifi is very slow, there are several issues. Easiest to find and fis is that on my wifi DHCP always took 4s, as first request fails. Still investigating why.. Reducing timeout to 0.25s makes DHCP process fast. Moved timout handling into its own struct, and changed state timeout from max(remaing, 60s) to min(remaining, MAX_TIMEOUT) Not sure about that change, but why would you want a max value that is at least 60s?
This commit is contained in:
@@ -39,9 +39,11 @@
|
|||||||
#define DHCP_CLIENT_PORT 68
|
#define DHCP_CLIENT_PORT 68
|
||||||
#define DHCP_SERVER_PORT 67
|
#define DHCP_SERVER_PORT 67
|
||||||
|
|
||||||
#define DEFAULT_TIMEOUT 4 // secs
|
#define DEFAULT_TIMEOUT 0.25 // secs
|
||||||
#define MAX_TIMEOUT 64 // secs
|
#define MAX_TIMEOUT 64 // secs
|
||||||
|
|
||||||
|
#define AS_USECS(t) (1000000 * t)
|
||||||
|
|
||||||
#define MAX_RETRIES 5
|
#define MAX_RETRIES 5
|
||||||
|
|
||||||
enum message_opcode {
|
enum message_opcode {
|
||||||
@@ -152,6 +154,22 @@ struct dhcp_message {
|
|||||||
static const char* TypeToString(message_type type);
|
static const char* TypeToString(message_type type);
|
||||||
} _PACKED;
|
} _PACKED;
|
||||||
|
|
||||||
|
struct socket_timeout {
|
||||||
|
socket_timeout(int socket)
|
||||||
|
:
|
||||||
|
timeout((time_t)AS_USECS(DEFAULT_TIMEOUT)),
|
||||||
|
tries(0)
|
||||||
|
{
|
||||||
|
UpdateSocket(socket);
|
||||||
|
}
|
||||||
|
|
||||||
|
time_t timeout; // in micro secs
|
||||||
|
uint8 tries;
|
||||||
|
|
||||||
|
bool Shift(int socket, bigtime_t stateMaxTime, const char* device);
|
||||||
|
void UpdateSocket(int socket) const;
|
||||||
|
};
|
||||||
|
|
||||||
#define DHCP_FLAG_BROADCAST 0x8000
|
#define DHCP_FLAG_BROADCAST 0x8000
|
||||||
|
|
||||||
#define ARP_HARDWARE_TYPE_ETHER 1
|
#define ARP_HARDWARE_TYPE_ETHER 1
|
||||||
@@ -417,6 +435,39 @@ dhcp_message::TypeToString(message_type type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
socket_timeout::UpdateSocket(int socket) const
|
||||||
|
{
|
||||||
|
struct timeval value;
|
||||||
|
value.tv_sec = timeout / 1000000;
|
||||||
|
value.tv_usec = timeout % 1000000;
|
||||||
|
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, &value, sizeof(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
socket_timeout::Shift(int socket, bigtime_t stateMaxTime, const char* device)
|
||||||
|
{
|
||||||
|
tries++;
|
||||||
|
timeout += timeout;
|
||||||
|
if (timeout > AS_USECS(MAX_TIMEOUT))
|
||||||
|
timeout = AS_USECS(MAX_TIMEOUT);
|
||||||
|
|
||||||
|
if (tries > MAX_RETRIES) {
|
||||||
|
if (stateMaxTime == -1)
|
||||||
|
return false;
|
||||||
|
bigtime_t remaining = (stateMaxTime - system_time()) / 2 + 1;
|
||||||
|
timeout = std::min(remaining, (bigtime_t)AS_USECS(MAX_TIMEOUT));
|
||||||
|
}
|
||||||
|
|
||||||
|
syslog(LOG_DEBUG, "%s: Timeout shift: %lu secs (try %lu)\n",
|
||||||
|
device, timeout, tries);
|
||||||
|
|
||||||
|
UpdateSocket(socket);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
@@ -652,9 +703,7 @@ DHCPClient::_StateTransition(int socket, dhcp_state& state)
|
|||||||
BNetworkAddress broadcast;
|
BNetworkAddress broadcast;
|
||||||
broadcast.SetToBroadcast(AF_INET, DHCP_SERVER_PORT);
|
broadcast.SetToBroadcast(AF_INET, DHCP_SERVER_PORT);
|
||||||
|
|
||||||
time_t timeout;
|
socket_timeout timeout(socket);
|
||||||
uint32 tries;
|
|
||||||
_ResetTimeout(socket, state, timeout, tries);
|
|
||||||
|
|
||||||
dhcp_message discover(DHCP_DISCOVER);
|
dhcp_message discover(DHCP_DISCOVER);
|
||||||
_PrepareMessage(discover, state);
|
_PrepareMessage(discover, state);
|
||||||
@@ -679,12 +728,11 @@ DHCPClient::_StateTransition(int socket, dhcp_state& state)
|
|||||||
char buffer[2048];
|
char buffer[2048];
|
||||||
struct sockaddr_in from;
|
struct sockaddr_in from;
|
||||||
socklen_t fromLength = sizeof(from);
|
socklen_t fromLength = sizeof(from);
|
||||||
|
|
||||||
ssize_t bytesReceived = recvfrom(socket, buffer, sizeof(buffer),
|
ssize_t bytesReceived = recvfrom(socket, buffer, sizeof(buffer),
|
||||||
0, (struct sockaddr*)&from, &fromLength);
|
0, (struct sockaddr*)&from, &fromLength);
|
||||||
if (bytesReceived < 0 && errno == B_TIMED_OUT) {
|
if (bytesReceived < 0 && errno == B_TIMED_OUT) {
|
||||||
// depending on the state, we'll just try again
|
// depending on the state, we'll just try again
|
||||||
if (!_TimeoutShift(socket, state, timeout, tries))
|
if (!_TimeoutShift(socket, state, timeout))
|
||||||
return B_TIMED_OUT;
|
return B_TIMED_OUT;
|
||||||
skipRequest = false;
|
skipRequest = false;
|
||||||
continue;
|
continue;
|
||||||
@@ -893,60 +941,22 @@ DHCPClient::_PrepareMessage(dhcp_message& message, dhcp_state state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
DHCPClient::_ResetTimeout(int socket, dhcp_state& state, time_t& timeout,
|
|
||||||
uint32& tries)
|
|
||||||
{
|
|
||||||
timeout = DEFAULT_TIMEOUT;
|
|
||||||
tries = 0;
|
|
||||||
|
|
||||||
struct timeval value;
|
|
||||||
value.tv_sec = timeout;
|
|
||||||
value.tv_usec = rand() % 1000000;
|
|
||||||
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, &value, sizeof(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
DHCPClient::_TimeoutShift(int socket, dhcp_state& state, time_t& timeout,
|
DHCPClient::_TimeoutShift(int socket, dhcp_state& state,
|
||||||
uint32& tries)
|
socket_timeout& timeout)
|
||||||
{
|
{
|
||||||
if (state == RENEWING && system_time() > fRebindingTime) {
|
bigtime_t stateMaxTime = -1;
|
||||||
state = REBINDING;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state == REBINDING && system_time() > fLeaseTime) {
|
|
||||||
state = INIT;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
tries++;
|
|
||||||
timeout += timeout;
|
|
||||||
if (timeout > MAX_TIMEOUT)
|
|
||||||
timeout = MAX_TIMEOUT;
|
|
||||||
|
|
||||||
if (tries > MAX_RETRIES) {
|
|
||||||
bigtime_t remaining = 0;
|
|
||||||
if (state == RENEWING)
|
if (state == RENEWING)
|
||||||
remaining = (fRebindingTime - system_time()) / 2 + 1;
|
stateMaxTime = fRebindingTime;
|
||||||
else if (state == REBINDING)
|
else if (state == REBINDING)
|
||||||
remaining = (fLeaseTime - system_time()) / 2 + 1;
|
stateMaxTime = fLeaseTime;
|
||||||
else
|
|
||||||
return false;
|
|
||||||
|
|
||||||
timeout = std::max(remaining / 1000000, bigtime_t(60));
|
if (system_time() > stateMaxTime) {
|
||||||
|
state = state == REBINDING ? INIT : REBINDING;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
syslog(LOG_DEBUG, "%s: Timeout shift: %lu secs (try %lu)\n",
|
return timeout.Shift(socket, stateMaxTime, Device());
|
||||||
Device(), timeout, tries);
|
|
||||||
|
|
||||||
struct timeval value;
|
|
||||||
value.tv_sec = timeout;
|
|
||||||
value.tv_usec = rand() % 1000000;
|
|
||||||
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, &value, sizeof(value));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
class BMessageRunner;
|
class BMessageRunner;
|
||||||
class dhcp_message;
|
class dhcp_message;
|
||||||
|
class socket_timeout;
|
||||||
|
|
||||||
|
|
||||||
enum dhcp_state {
|
enum dhcp_state {
|
||||||
@@ -55,10 +56,8 @@ private:
|
|||||||
status_t _SendMessage(int socket, dhcp_message& message,
|
status_t _SendMessage(int socket, dhcp_message& message,
|
||||||
const BNetworkAddress& address) const;
|
const BNetworkAddress& address) const;
|
||||||
dhcp_state _CurrentState() const;
|
dhcp_state _CurrentState() const;
|
||||||
void _ResetTimeout(int socket, dhcp_state& state,
|
|
||||||
time_t& timeout, uint32& tries);
|
|
||||||
bool _TimeoutShift(int socket, dhcp_state& state,
|
bool _TimeoutShift(int socket, dhcp_state& state,
|
||||||
time_t& timeout, uint32& tries);
|
socket_timeout& timeout);
|
||||||
void _RestartLease(bigtime_t lease);
|
void _RestartLease(bigtime_t lease);
|
||||||
|
|
||||||
static BString _AddressToString(const uint8* data);
|
static BString _AddressToString(const uint8* data);
|
||||||
|
|||||||
Reference in New Issue
Block a user