* [ECOS] Re: DHCP over multiple interfaces
2008-01-23 18:38 ` Andrew Lunn
@ 2008-01-25 17:14 ` Dave Lawrence
0 siblings, 0 replies; 4+ messages in thread
From: Dave Lawrence @ 2008-01-25 17:14 UTC (permalink / raw)
To: ecos-discuss
[-- Attachment #1: Type: text/plain, Size: 1466 bytes --]
Andrew Lunn wrote:
> On Wed, Jan 23, 2008 at 04:11:11PM +0000, Dave Lawrence wrote:
>> I can't seem to get DHCP work over multiple interfaces.
>
> The eCos DHCP client used to work with multiple interfaces. This is
> why there is the half up states, so that it can force the packet out
> the correct interface and the clearing of routes when performing DHCP
> transactions.
>
> If it does not work, i suggest you work your way back and see which
> patch broke it.
>
> Andrew
>
I had a look on an older platform that uses an older ecos tree. It does
work but there were some problems:
* Packets could come out on the wrong interface if two threads were
simultaneously calling do_dhcp (on different interfaces)
* Our application was also interfering with the routing tables in
response to detecting devices going up / down
So I don't have any opinion about whether my fixes are of use to the
wider ecos world but I've attached a patch in case. It does the following:
* Provide dhcp_get_lock and dhcp_release_lock as global functions which
the application can use to ensure interference is avoided
* Use these functions at the entry and exit points of do_dhcp to prevent
it functioning reetrantly (is that a word?)
Unfortunately I'm no closer to fixing the original problem - on my new
platform packets for 255.255.255.255 *always* come out on eth1.
Was I correct to continue with this thread or should I have switched to
the patches list?
[-- Attachment #2: dhcp.patch --]
[-- Type: text/plain, Size: 4376 bytes --]
Index: net/common/current/include/dhcp.h
===================================================================
RCS file: /cvs/ecos/ecos-opt/net/net/common/current/include/dhcp.h,v
retrieving revision 1.2
diff -u -5 -r1.2 dhcp.h
--- net/common/current/include/dhcp.h 16 Oct 2003 08:13:46 -0000 1.2
+++ net/common/current/include/dhcp.h 25 Jan 2008 17:02:34 -0000
@@ -241,9 +241,15 @@
extern int
do_dhcp_release(const char *intf, struct bootp *res,
cyg_uint8 *pstate, struct dhcp_lease *lease);
+extern void
+ dhcp_get_lock (void);
+
+extern void
+ dhcp_release_lock (void);
+
#endif // CYGPKG_NET_DHCP
#endif // CYGONCE_NET_TCPIP_DHCP_H
// EOF dhcp.h
Index: net/common/current/src/dhcp_prot.c
===================================================================
RCS file: /cvs/ecos/ecos-opt/net/net/common/current/src/dhcp_prot.c,v
retrieving revision 1.20
diff -u -5 -r1.20 dhcp_prot.c
--- net/common/current/src/dhcp_prot.c 5 Mar 2006 12:48:37 -0000 1.20
+++ net/common/current/src/dhcp_prot.c 25 Jan 2008 17:02:35 -0000
@@ -88,10 +88,12 @@
CYG_ASSERT( (strlen(hostname)<=CYGNUM_NET_DHCP_OPTION_HOST_NAME_LEN), "dhcp hostname too long" );
strncpy(dhcp_hostname, hostname, CYGNUM_NET_DHCP_OPTION_HOST_NAME_LEN);
}
#endif
+static cyg_sem_t dhcp_sem;
+
/* Forward reference prototypes. */
static int unset_tag( struct bootp *ppkt, unsigned char tag );
// ------------------------------------------------------------------------
// Returns a pointer to the end of dhcp message (or NULL if invalid)
@@ -691,10 +693,12 @@
struct bootp *received = &rx_local;
struct bootp *xmit = res;
struct bootp xmit2;
int xlen;
+ dhcp_get_lock ();
+
// First, get a socket on the interface in question. But Zeroth, if
// needs be, bring it to the half-up broadcast only state if needs be.
if ( DHCPSTATE_INIT == oldstate
|| DHCPSTATE_FAILED == oldstate
@@ -1044,10 +1048,11 @@
}
}
}
// Otherwise, nothing whatsoever to do...
+ dhcp_release_lock ();
return true;
case DHCPSTATE_RENEWING:
// Just send what you got with a DHCPREQUEST in the message
// type UNICAST straight to the server. Then wait for an ACK.
@@ -1295,27 +1300,30 @@
}
}
}
// Otherwise, nothing whatsoever to do...
+ dhcp_release_lock ();
return true;
case DHCPSTATE_NOTBOUND:
// All done with socket
close(s);
// No lease active
no_lease( lease );
// Leave interface up so app can tidy.
+ dhcp_release_lock ();
return true;
case DHCPSTATE_FAILED:
// All done with socket
close(s);
// No lease active
no_lease( lease );
// Unconditionally down the interface.
do_dhcp_down_net( intf, res, &oldstate, lease );
+ dhcp_release_lock ();
return false;
case DHCPSTATE_DO_RELEASE:
// We have been forced here by external means, to release the
// lease for graceful shutdown.
@@ -1362,17 +1370,19 @@
break;
default:
no_lease( lease );
close(s);
+ dhcp_release_lock ();
return false;
}
}
out:
if (s != -1)
close (s);
+ dhcp_release_lock ();
return false;
}
// ------------------------------------------------------------------------
// Bring an interface down, failed to initialize it or lease is expired
@@ -1484,10 +1494,33 @@
cyg_thread_delay( 100 ); // to let it leave the building
}
return true;
}
+void dhcp_get_lock (void)
+{
+ static int dhcp_sem_initialised;
+
+ cyg_scheduler_lock ();
+
+ if (!dhcp_sem_initialised)
+ {
+ cyg_semaphore_init (&dhcp_sem, 1);
+ dhcp_sem_initialised = true;
+ }
+
+ cyg_scheduler_unlock ();
+
+ cyg_semaphore_wait (&dhcp_sem);
+}
+
+void dhcp_release_lock (void)
+{
+ cyg_semaphore_post (&dhcp_sem);
+}
+
+
// ------------------------------------------------------------------------
#endif // CYGPKG_NET_DHCP
// EOF dhcp_prot.c
[-- Attachment #3: Type: text/plain, Size: 148 bytes --]
--
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss
^ permalink raw reply [flat|nested] 4+ messages in thread