52
« on: October 14, 2009, 07:57:53 PM »
Well here is what I found, and did.
Change in application.c in #USE_DHCP:
fnStartDHCP((UTASK_TASK)(FORCE_INIT | OWN_TASK)); // activate DHCP
to
fnStartDHCP((UTASK_TASK)(OWN_TASK));
I found that the FORCE_INIT would clear out the default IP address.
The next step was to handle the case of no network cable plugged in for a while (longer than the 2 minute timeout) after power is applied.
in dhcp.c
extern int fnStartDHCP(UTASK_TASK Task){
if (usConnectedToBB & LINK_STATUS){ //only do this if the link is up. {AL}
if ((DHCPSocketNr >= 0) || ((DHCPSocketNr = fnGetUDP_socket(TOS_MINIMISE_DELAY, fnDHCPListner, (UDP_OPT_SEND_CS | UDP_OPT_CHECK_CS))) >= 0)) {
fnBindSocket(DHCPSocketNr, DHCP_CLIENT_PORT);
MasterTask = (Task & ~FORCE_INIT);
if (!(Task & FORCE_INIT) && (uMemcmp(&network.ucOurIP[0], cucNullMACIP, IPV4_LENGTH))) { // if we have a non-zero IP address we will try to re-obtain it
uMemcpy(ucDHCP_IP, &network.ucOurIP[0], IPV4_LENGTH); // copy our IP address to the DHCP preferred address
uMemset(&network.ucOurIP[0], 0, IPV4_LENGTH); // remove the local IP since it may only be used after being validated
ucDHCP_state = DHCP_STATE_INIT_REBOOT; // we already have a previous value - we will try to obtain it again
}
else {
ucDHCP_state = DHCP_STATE_INIT; // we have none so we must start fresh
}
fnRandomise((4*SEC), E_START_DHCP); // perform DHCP state/event after short delay
return 0; // OK
}
return NO_UDP_SOCKET_FOR_DHCP; // error
} else {
uTaskerGlobalMonoTimer( OWN_TASK, (DELAY_LIMIT)(2*SEC), E_RETRY_DHCP); // try again in 2 seconds{AL}
return LINK_NOT_READY; // return this if the link is not up yet
}
}
// DHCP task
//
extern void fnDHCP(TTASKTABLE *ptrTaskTable)
{
QUEUE_HANDLE PortIDInternal = ptrTaskTable->TaskID; // queue ID for task input
unsigned char ucInputMessage[SMALL_QUEUE]; // reserve space for receiving messages
if ( fnRead( PortIDInternal, ucInputMessage, HEADER_LENGTH )) { // check input queue
//if ( ucInputMessage[ MSG_SOURCE_TASK ] == TASK_ARP) {
switch (ucInputMessage[ MSG_SOURCE_TASK ]) { //check which type of message we have {AL}
case TASK_ARP:
// Note that we receive ARP messages only on our attempt to send a test message to a node with our allocated IP address.
// Since DHCP uses broadcast messages until this point there can be no ARP errors
fnRead( PortIDInternal, ucInputMessage, ucInputMessage[MSG_CONTENT_LENGTH]); // read the contents
if (ARP_RESOLUTION_SUCCESS == ucInputMessage[ 0 ]) {
if (ucResendAfterArp) {
fnSendDHCP(ucResendAfterArp);
}
else {
fnStateEventDHCP(E_DHCP_COLLISION); // this is bad news. We have received IP data from DHCP server but found that someone is already using the address. We have to try again
}
}
else if (ARP_RESOLUTION_FAILED == ucInputMessage[ 0 ]) {
// we have probed to ensure than no one else has the IP address which we have received
// the probing failed which means we can use it - inform application...
fnStateEventDHCP(E_DHCP_BIND_NOW);
}
ucResendAfterArp = 0;
break;
case INTERRUPT_EVENT: //Here is where the dhcp failure is reported {AL}
switch (ucInputMessage[MSG_INTERRUPT_EVENT]) {
case DHCP_SUCCESSFUL: // we can now use the network connection
break;
case DHCP_MISSING_SERVER:
fnStopDHCP(); // DHCP server is missing so stop and continue with backup address (if available)
break;
}
break;
case TIMER_EVENT:
if (ucInputMessage[ MSG_TIMER_EVENT ] == E_RETRY_DHCP) { //{AL} retry DHCP if LINK was down
fnStartDHCP((UTASK_TASK)(OWN_TASK));
} else {
fnStateEventDHCP(ucInputMessage[ MSG_TIMER_EVENT ]); // timer event
}
break;
}
}
}
Then in NetworkIndicators.c I set or clear the bit LINK_STATUS, for link up or link down.
So the operation is now:
If link is down check again in 2 seconds.
If link is up and dhcp responds, use that IP (IP is 0.0.0.0 while waiting for dhcp).
if link is up and dhcp isn't responding (IP is 0.0.0.0 while waiting for dhcp), timeout and use default IP
if link is up and static IP is assigned, use that.
I hope this helps someone.
Aaron
UPDATE:Since everything waits for link to be stable, this does take longer for the system to start. About 30 seconds, as opposed to the original 10s.