Posts tagged plc
zero-configuration connectivity on embedded computers
Our device is networked. It is supposed to:
- Work when you plug it into any traditional Ethernet network (i.e. with router with embedded DHCP server).
- It is also supposed to work when you directly connect it to another node (i.e. a computer which you’re want to configure the device with — where no DHCP server is available).
So our goal is:
- Zero-configuration connectivity on above two scenarios.
Our requirement:
- Severely scarce resources. Firmware should fit in a 64kb space.
Most such networked devices comes with a static IP already set and the node which is supposed to configure them (usually a PC) is supposed to be set to a specific IP address in the same subnet to configure them. This has several drawbacks:
- Users need to have administration privilleges
- Users need to have experience with computers
- And this is OS dependent.
There are other zero-configuration technology stacks, even though I don’t have a scientific fact, from their specs I think they’d take up significant code space.
So here’s what I’ve did
- During device boot I assign it a link-local IP address (i.e. AUTOIP or http://tools.ietf.org/html/rfc3927). I did not implement RFC3927 and just generated a fixed IP address according to MAC of the device — partly because I don’t have a quality random number generator, as there’s no clock on most of the devices and reading analog inputs often give same results.
- Then I start DHCP negotiations
With the scenario the device is able to communicate with another node which also have been assigned to a link-local address without waiting for a DHCP timeout. So when you plug your device directly to your computer you can communicate with the device as soon as your computer also assigned itself a link-local address. This varies from OS to OS but we’re pleased with the results. Our customers are able to connect to their devices without any configuration.
But there’s a problem! Even though this configuration worked on our network at the office and many other places where we sold the devices to, it didn’t work on my home network. It turned out that my linksys router in my home network does not honor DHCP DISCOVER requests if their source IP addresses are not 0.0.0.0
Problem:
- Some DHCP servers does not honor DHCP DISCOVER requests from 169.254.C.D. They strictly require source IP of the requests to be 0.0.0.0
To solve this problem I could either
- First assign my device IP address 0.0.0.0 and then wait for DHCP timeout, then fallback to AUTO IP. This way DHCP DISCOVER request would work with all routers but other party would have to wait for my device to timeout DHCP and fallback to link-local IP before starting communicating with it — this is a serious tradeoff.
- Or Add UDP IP Spoofing on top of our current implementation hence just make the DHCP DISCOVER source IP 0.0.0.0 and keep the rest the same.
Obviously I chose the second approach and patched uIP with the following code:
$ svn diff
Index: uip/uip.c
===================================================================
--- uip/uip.c (revision 226)
+++ uip/uip.c (working copy)
@@ -1181,7 +1181,17 @@
BUF->srcport = uip_udp_conn->lport;
BUF->destport = uip_udp_conn->rport;
- uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
+ extern int g_udp_spoof;
+ extern uip_ipaddr_t g_udp_spoof_ip;
+ if(!g_udp_spoof)
+ {
+ uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
+ }
+ else
+ {
+ g_udp_spoof = 0;
+ uip_ipaddr_copy(BUF->srcipaddr, g_udp_spoof_ip);
+ }
uip_ipaddr_copy(BUF->destipaddr, uip_udp_conn->ripaddr);
uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPTCPH_LEN];
Now our device apparently has best of both worlds.
- It can communicate with any node with link-local IP address right away at boot time — without waiting for any sort of (DHCP) timeout.
- While link-local communication is working, it tries to acquire an IP address from DHCP server in parallel — thanks to source IP “spoofing”.
I’ll see if further testing will reveal any side effects.
See also:
DHCP RFC: http://tools.ietf.org/html/rfc2131
Link-local IP Address (AUTO IP): http://tools.ietf.org/html/rfc3927