From 092b6f3baa0c4605ac23a5a9dd9d5134497a5a46 Mon Sep 17 00:00:00 2001 From: Robert Quattlebaum Date: Thu, 17 May 2012 10:34:58 -0700 Subject: [PATCH 1/4] platform/minimal-net: Implement better idle behavior. The minimal-net target, as currently written, wakes up the CPU every millisecond to check for packets, and will only react in real-time to input from stdin. If you are running this on a laptop battery, your battery will quickly drain. This change allows the CPU to idle when there is literally nothing to do while still being responsive to input from stein and/or incoming packets. This fix should significantly improve performance while significantly improving power usage. Win-win. Also added `_xassert()` implementation so that the contiki- provided `assert()` macro will work properly when used on this platform. --- cpu/native/net/tapdev-drv.c | 1 - cpu/native/net/tapdev-drv.h | 1 + cpu/native/net/tapdev.c | 7 ++++ cpu/native/net/tapdev6.c | 8 ++++ platform/minimal-net/contiki-main.c | 63 +++++++++++++++++++++++++---- 5 files changed, 71 insertions(+), 9 deletions(-) diff --git a/cpu/native/net/tapdev-drv.c b/cpu/native/net/tapdev-drv.c index 0e4c0a29d..a4f50899e 100644 --- a/cpu/native/net/tapdev-drv.c +++ b/cpu/native/net/tapdev-drv.c @@ -59,7 +59,6 @@ tapdev_output(void) static void pollhandler(void) { - process_poll(&tapdev_process); uip_len = tapdev_poll(); if(uip_len > 0) { diff --git a/cpu/native/net/tapdev-drv.h b/cpu/native/net/tapdev-drv.h index 25014ea29..3241fc344 100644 --- a/cpu/native/net/tapdev-drv.h +++ b/cpu/native/net/tapdev-drv.h @@ -38,5 +38,6 @@ PROCESS_NAME(tapdev_process); uint8_t tapdev_output(void); +int tapdev_fd(void); #endif /* __TAPDEV_DRV_H__ */ diff --git a/cpu/native/net/tapdev.c b/cpu/native/net/tapdev.c index cc294d7a7..377b4c225 100644 --- a/cpu/native/net/tapdev.c +++ b/cpu/native/net/tapdev.c @@ -69,6 +69,13 @@ static unsigned long lasttime; #define BUF ((struct uip_eth_hdr *)&uip_buf[0]) +/*---------------------------------------------------------------------------*/ +int +tapdev_fd(void) +{ + return fd; +} + /*---------------------------------------------------------------------------*/ static void remove_route(void) diff --git a/cpu/native/net/tapdev6.c b/cpu/native/net/tapdev6.c index e687ada10..441d2fee5 100644 --- a/cpu/native/net/tapdev6.c +++ b/cpu/native/net/tapdev6.c @@ -85,6 +85,13 @@ static unsigned long lasttime; static void do_send(void); uint8_t tapdev_send(uip_lladdr_t *lladdr); +/*---------------------------------------------------------------------------*/ +int +tapdev_fd(void) +{ + return fd; +} + uint16_t tapdev_poll(void) @@ -161,6 +168,7 @@ tapdev_init(void) /* gdk_input_add(fd, GDK_INPUT_READ, read_callback, NULL);*/ + atexit(&tapdev_exit); } /*---------------------------------------------------------------------------*/ static void diff --git a/platform/minimal-net/contiki-main.c b/platform/minimal-net/contiki-main.c index 64301d38f..6562b3ecd 100644 --- a/platform/minimal-net/contiki-main.c +++ b/platform/minimal-net/contiki-main.c @@ -33,6 +33,8 @@ */ #include +#include +#include #include #include #include @@ -40,6 +42,7 @@ #include "contiki.h" #include "contiki-net.h" +#include "lib/assert.h" #include "dev/serial-line.h" @@ -267,9 +270,15 @@ main(void) (ipaddr.u16[2] != 0) || (ipaddr.u16[3] != 0)) { #if UIP_CONF_ROUTER - uip_ds6_prefix_add(&ipaddr, UIP_DEFAULT_PREFIX_LEN, 0, 0, 0, 0); + if(!uip_ds6_prefix_add(&ipaddr, UIP_DEFAULT_PREFIX_LEN, 0, 0, 0, 0)) { + fprintf(stderr,"uip_ds6_prefix_add() failed.\n"); + exit(EXIT_FAILURE); + } #else /* UIP_CONF_ROUTER */ - uip_ds6_prefix_add(&ipaddr, UIP_DEFAULT_PREFIX_LEN, 0); + if(!uip_ds6_prefix_add(&ipaddr, UIP_DEFAULT_PREFIX_LEN, 0)) { + fprintf(stderr,"uip_ds6_prefix_add() failed.\n"); + exit(EXIT_FAILURE); + } #endif /* UIP_CONF_ROUTER */ uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); @@ -290,14 +299,17 @@ main(void) #if UIP_CONF_IPV6 && !RPL_BORDER_ROUTER /* Border router process prints addresses later */ { - uint8_t i; + int i = 0; + int interface_count = 0; for(i = 0; i < UIP_DS6_ADDR_NB; i++) { if(uip_ds6_if.addr_list[i].isused) { - printf("IPV6 Addresss: "); - sprint_ip6(uip_ds6_if.addr_list[i].ipaddr); - printf("\n"); + printf("IPV6 Addresss: "); + sprint_ip6(uip_ds6_if.addr_list[i].ipaddr); + printf("\n"); + interface_count++; } } + assert(0 < interface_count); } #endif @@ -305,14 +317,40 @@ main(void) fd_set fds; int n; struct timeval tv; + clock_time_t next_event; n = process_run(); + next_event = etimer_next_expiration_time() - clock_time(); + +#if DEBUG_SLEEP + if(n > 0) + printf("sleep: %d events pending\n",n); + else + printf("sleep: next event @ T-%.03f\n",(double)next_event / (double)CLOCK_SECOND); +#endif + +#ifdef __CYGWIN__ + /* wpcap doesn't appear to support select, so + * we can't idle the process on windows. */ + next_event = 0; +#endif + + if(next_event > (CLOCK_SECOND * 2)) + next_event = CLOCK_SECOND * 2; + tv.tv_sec = n ? 0 : (next_event / CLOCK_SECOND); + tv.tv_usec = n ? 0 : ((next_event % 1000) * 1000); - tv.tv_sec = 0; - tv.tv_usec = 1000; FD_ZERO(&fds); FD_SET(STDIN_FILENO, &fds); +#ifdef __CYGWIN__ select(1, &fds, NULL, NULL, &tv); +#else + FD_SET(tapdev_fd(), &fds); + if(0 > select(tapdev_fd() + 1, &fds, NULL, NULL, &tv)) { + perror("Call to select() failed."); + exit(EXIT_FAILURE); + } +#endif if(FD_ISSET(STDIN_FILENO, &fds)) { char c; @@ -320,6 +358,7 @@ main(void) serial_line_input_byte(c); } } + process_poll(&tapdev_process); etimer_request_poll(); } @@ -338,6 +377,14 @@ uip_log(char *m) printf("uIP: '%s'\n", m); } /*---------------------------------------------------------------------------*/ +void +_xassert(const char *file, int line) +{ + fprintf(stderr, "%s:%u: failed assertion\n", file, line); + abort(); +} + + unsigned short sensors_light1(void) { From a571b663b07f05b65eafcc30b6213fc74d7a5283 Mon Sep 17 00:00:00 2001 From: Robert Quattlebaum Date: Thu, 17 May 2012 10:34:58 -0700 Subject: [PATCH 2/4] platform/minimal-net: Better, more seamless support for OS X. This patch enables automatic route setup and cleanup when starting and stopping the minimal-net target on OS X. Both IPv4 and IPv6 are supported. Using the minimal-net target on OS X was absolute hell before I came up with this patch. Now it is painless. --- cpu/native/Makefile.native | 11 +- cpu/native/net/tapdev.c | 8 +- cpu/native/net/tapdev6.c | 177 +++++++++++++++++++++++++++- platform/minimal-net/contiki-main.c | 6 +- 4 files changed, 191 insertions(+), 11 deletions(-) diff --git a/cpu/native/Makefile.native b/cpu/native/Makefile.native index 44be5be73..5b96fc187 100644 --- a/cpu/native/Makefile.native +++ b/cpu/native/Makefile.native @@ -18,10 +18,15 @@ CFLAGSWERROR=-Werror -pedantic -std=c99 -Werror endif CFLAGSNO = -Wall -g -I/usr/local/include $(CFLAGSWERROR) CFLAGS += $(CFLAGSNO) -O -ifeq ($(HOST_OS),Linux) - LDFLAGS += -Wl,-Map=contiki-$(TARGET).map,-export-dynamic + +ifeq ($(shell uname),Darwin) +AROPTS = -r +LDFLAGS += -Wl,-flat_namespace +CFLAGS += -DHAVE_SNPRINTF=1 -U__ASSERT_USE_STDERR else - LDFLAGS += -Wl +ifeq ($(HOST_OS),Linux) +LDFLAGS = -Wl,-Map=contiki-$(TARGET).map,-export-dynamic +endif endif ### Compilation rules diff --git a/cpu/native/net/tapdev.c b/cpu/native/net/tapdev.c index 377b4c225..ecf018fcc 100644 --- a/cpu/native/net/tapdev.c +++ b/cpu/native/net/tapdev.c @@ -81,7 +81,7 @@ static void remove_route(void) { char buf[1024]; - snprintf(buf, sizeof(buf), "route delete -net 172.16.0.0"); + snprintf(buf, sizeof(buf), "route delete -net 172.18.0.0"); system(buf); printf("%s\n", buf); @@ -110,15 +110,15 @@ tapdev_init(void) } #endif /* Linux */ - snprintf(buf, sizeof(buf), "ifconfig tap0 inet 192.168.1.1"); + snprintf(buf, sizeof(buf), "ifconfig tap0 inet 172.18.0.1/16"); system(buf); printf("%s\n", buf); #ifdef linux /* route add for linux */ - snprintf(buf, sizeof(buf), "route add -net 172.16.0.0/16 gw 192.168.1.2"); + snprintf(buf, sizeof(buf), "route add -net 172.18.0.0/16 dev tap0"); #else /* linux */ /* route add for freebsd */ - snprintf(buf, sizeof(buf), "route add -net 172.16.0.0/16 192.168.1.2"); + snprintf(buf, sizeof(buf), "route add -net 172.18.0.0/16 -iface tap0"); #endif /* linux */ system(buf); diff --git a/cpu/native/net/tapdev6.c b/cpu/native/net/tapdev6.c index 441d2fee5..9f85c47c2 100644 --- a/cpu/native/net/tapdev6.c +++ b/cpu/native/net/tapdev6.c @@ -56,6 +56,17 @@ #define DEVTAP "/dev/tap0" #endif /* linux */ +#ifdef __APPLE__ +#include +#include +#include +#include // ND6_INFINITE_LIFETIME +#include +#include +#include +#include // struct sockaddr_dl +#include // AF_ROUTE things +#endif #include "tapdev6.h" #include "contiki-net.h" @@ -66,7 +77,7 @@ static int drop = 0; #endif -static int fd; +static int fd = -1; static unsigned long lasttime; @@ -123,6 +134,159 @@ tapdev_poll(void) return ret; } /*---------------------------------------------------------------------------*/ +#if defined(__APPLE__) +static int reqfd = -1, sfd = -1, interface_index; + +static void +tapdev_init_darwin_routes(void) +{ + struct stat st; + + if(-1 == fstat(fd, &st)) { + perror("tapdev: fstat failed."); + exit(EXIT_FAILURE); + } + + /************* Add address *************/ + + struct in6_aliasreq addreq6 = { }; + reqfd = socket(AF_INET6, SOCK_DGRAM, 0); + + if(-1 == fcntl(reqfd, F_SETFD, FD_CLOEXEC)) { + perror("tapdev: fcntl failed."); + exit(EXIT_FAILURE); + } + + devname_r(st.st_rdev, S_IFCHR, addreq6.ifra_name, + sizeof(addreq6.ifra_name)); + + addreq6.ifra_addr.sin6_family = AF_INET6; + addreq6.ifra_addr.sin6_len = sizeof(addreq6.ifra_addr); + addreq6.ifra_addr.sin6_addr.__u6_addr.__u6_addr16[0] = UIP_HTONS(0xAAAA); + addreq6.ifra_addr.sin6_addr.__u6_addr.__u6_addr16[7] = UIP_HTONS(0x0001); + + addreq6.ifra_prefixmask.sin6_family = AF_INET6; + addreq6.ifra_prefixmask.sin6_len = sizeof(addreq6.ifra_prefixmask); + addreq6.ifra_prefixmask.sin6_addr.__u6_addr.__u6_addr16[0] = + UIP_HTONS(0xFFFF); + addreq6.ifra_prefixmask.sin6_addr.__u6_addr.__u6_addr16[1] = + UIP_HTONS(0xFFFF); + addreq6.ifra_prefixmask.sin6_addr.__u6_addr.__u6_addr16[2] = + UIP_HTONS(0xFFFF); + addreq6.ifra_prefixmask.sin6_addr.__u6_addr.__u6_addr16[3] = + UIP_HTONS(0xFFFF); + + addreq6.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; + addreq6.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME; + addreq6.ifra_lifetime.ia6t_expire = ND6_INFINITE_LIFETIME; + addreq6.ifra_lifetime.ia6t_preferred = ND6_INFINITE_LIFETIME; + + if(-1 == ioctl(reqfd, SIOCAIFADDR_IN6, &addreq6)) { + perror("tapdev: Uable to add address, call to ioctl failed."); + exit(EXIT_FAILURE); + } + + /************* Add route *************/ + + int s = socket(AF_ROUTE, SOCK_RAW, AF_INET6); + + if(s == -1) { + perror("tapdev: Unable to add route, call to socket() failed."); + + // Failing to add the route is not fatal, so just return. + return; + } + + sfd = s; + interface_index = if_nametoindex(devname(st.st_rdev, S_IFCHR)); + + PRINTF("tapdev: if_nametoindex(devname(st.st_rdev, S_IFCHR)) = %d\n", + interface_index); + PRINTF("tapdev: devname(st.st_rdev, S_IFCHR) = %s\n", + devname(st.st_rdev, S_IFCHR)); + + struct { + struct rt_msghdr hdr; + struct sockaddr_in6 dst; + struct sockaddr_dl gw; + struct sockaddr_in6 mask; + } msg = {}; + + msg.hdr.rtm_msglen = sizeof(msg); + msg.hdr.rtm_version = RTM_VERSION; + msg.hdr.rtm_type = RTM_ADD; + msg.hdr.rtm_index = interface_index; + msg.hdr.rtm_flags = RTF_UP | RTF_STATIC; + msg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK; + msg.hdr.rtm_pid = getpid(); + msg.hdr.rtm_seq = 0; + + msg.dst.sin6_family = AF_INET6; + msg.dst.sin6_len = sizeof(msg.dst); + msg.dst.sin6_addr.__u6_addr.__u6_addr16[0] = UIP_HTONS(0xAAAA); + + msg.gw.sdl_family = AF_LINK; + msg.gw.sdl_len = sizeof(msg.gw); + msg.gw.sdl_index = interface_index; + + msg.mask.sin6_family = AF_INET6; + msg.mask.sin6_len = sizeof(msg.mask); + msg.mask.sin6_addr.__u6_addr.__u6_addr16[0] = UIP_HTONS(0xFFFF); + msg.mask.sin6_addr.__u6_addr.__u6_addr16[1] = UIP_HTONS(0xFFFF); + msg.mask.sin6_addr.__u6_addr.__u6_addr16[2] = UIP_HTONS(0xFFFF); + msg.mask.sin6_addr.__u6_addr.__u6_addr16[3] = UIP_HTONS(0xFFFF); + + if(-1 == write(s, &msg, sizeof(msg))) { + perror("tapdev: Unable to add route, call to write() failed."); + + // Failing to add the route is not fatal, so just return. + return; + } +} +/*---------------------------------------------------------------------------*/ +static void +tapdev_cleanup_darwin_routes(void) +{ + struct { + struct rt_msghdr hdr; + struct sockaddr_in6 dst; + struct sockaddr_dl gw; + struct sockaddr_in6 mask; + } msg = {}; + + msg.hdr.rtm_msglen = sizeof(msg); + msg.hdr.rtm_version = RTM_VERSION; + msg.hdr.rtm_type = RTM_DELETE; + msg.hdr.rtm_index = interface_index; + msg.hdr.rtm_flags = RTF_UP | RTF_STATIC; + msg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK; + msg.hdr.rtm_pid = getpid(); + msg.hdr.rtm_seq = 0; + + msg.dst.sin6_family = AF_INET6; + msg.dst.sin6_len = sizeof(msg.dst); + msg.dst.sin6_addr.__u6_addr.__u6_addr16[0] = UIP_HTONS(0xAAAA); + + msg.gw.sdl_family = AF_LINK; + msg.gw.sdl_len = sizeof(msg.gw); + msg.gw.sdl_index = interface_index; + + msg.mask.sin6_family = AF_INET6; + msg.mask.sin6_len = sizeof(msg.mask); + msg.mask.sin6_addr.__u6_addr.__u6_addr16[0] = UIP_HTONS(0xFFFF); + msg.mask.sin6_addr.__u6_addr.__u6_addr16[1] = UIP_HTONS(0xFFFF); + msg.mask.sin6_addr.__u6_addr.__u6_addr16[2] = UIP_HTONS(0xFFFF); + msg.mask.sin6_addr.__u6_addr.__u6_addr16[3] = UIP_HTONS(0xFFFF); + if(-1 == write(sfd, &msg, sizeof(msg))) { + perror("tapdev: Unable to delete route"); + exit(EXIT_FAILURE); + } + + close(reqfd); + close(sfd); +} +#endif // defined(__APPLE__) +/*---------------------------------------------------------------------------*/ void tapdev_init(void) { @@ -146,6 +310,10 @@ tapdev_init(void) } #endif /* Linux */ +#ifdef __APPLE__ + tapdev_init_darwin_routes(); +#endif + /* Linux (ubuntu) snprintf(buf, sizeof(buf), "ip link set tap0 up"); system(buf); @@ -236,5 +404,12 @@ tapdev_do_send(void) void tapdev_exit(void) { + PRINTF("tapdev: Closing...\n"); + +#ifdef __APPLE__ + tapdev_cleanup_darwin_routes(); +#endif + + close(fd); } /*---------------------------------------------------------------------------*/ diff --git a/platform/minimal-net/contiki-main.c b/platform/minimal-net/contiki-main.c index 6562b3ecd..89ddf00f0 100644 --- a/platform/minimal-net/contiki-main.c +++ b/platform/minimal-net/contiki-main.c @@ -236,21 +236,21 @@ main(void) uip_gethostaddr(&addr); if(addr.u8[0] == 0) { - uip_ipaddr(&addr, 10,1,1,1); + uip_ipaddr(&addr, 172,18,0,2); } printf("IP Address: %d.%d.%d.%d\n", uip_ipaddr_to_quad(&addr)); uip_sethostaddr(&addr); uip_getnetmask(&addr); if(addr.u8[0] == 0) { - uip_ipaddr(&addr, 255,0,0,0); + uip_ipaddr(&addr, 255,255,0,0); uip_setnetmask(&addr); } printf("Subnet Mask: %d.%d.%d.%d\n", uip_ipaddr_to_quad(&addr)); uip_getdraddr(&addr); if(addr.u8[0] == 0) { - uip_ipaddr(&addr, 10,1,1,100); + uip_ipaddr(&addr, 172,18,0,1); uip_setdraddr(&addr); } printf("Def. Router: %d.%d.%d.%d\n", uip_ipaddr_to_quad(&addr)); From 0ca8a57f39457b3573b9ff82d19244e5c920ae80 Mon Sep 17 00:00:00 2001 From: Robert Quattlebaum Date: Wed, 13 Jun 2012 09:17:32 -0700 Subject: [PATCH 3/4] platform/minimal-net: Print out pseudo LED status. --- platform/minimal-net/leds-arch.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/platform/minimal-net/leds-arch.c b/platform/minimal-net/leds-arch.c index 1308c57dc..ca2245481 100644 --- a/platform/minimal-net/leds-arch.c +++ b/platform/minimal-net/leds-arch.c @@ -37,6 +37,7 @@ * Adam Dunkels */ +#include #include "dev/leds.h" static unsigned char leds; /*---------------------------------------------------------------------------*/ @@ -55,6 +56,15 @@ leds_arch_get(void) void leds_arch_set(unsigned char l) { + int i; + + for(i = 0; i < 8 && ((1 << i) & LEDS_ALL); i++) { + if(((1 << i) & leds) && !((1 << i) & l)) { + printf("LED %d OFF\n", i); + } else if(!((1 << i) & leds) && ((1 << i) & l)) { + printf("LED %d ON\n", i); + } + } leds = l; } /*---------------------------------------------------------------------------*/ From 38b286383121273ea4c51dddb3d7c6bff3628ca5 Mon Sep 17 00:00:00 2001 From: Robert Quattlebaum Date: Tue, 26 Feb 2013 11:29:04 -0800 Subject: [PATCH 4/4] Update cpu/native/Makefile.native --- cpu/native/Makefile.native | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpu/native/Makefile.native b/cpu/native/Makefile.native index 5b96fc187..eaf716424 100644 --- a/cpu/native/Makefile.native +++ b/cpu/native/Makefile.native @@ -19,7 +19,7 @@ endif CFLAGSNO = -Wall -g -I/usr/local/include $(CFLAGSWERROR) CFLAGS += $(CFLAGSNO) -O -ifeq ($(shell uname),Darwin) +ifeq ($(HOST_OS),Darwin) AROPTS = -r LDFLAGS += -Wl,-flat_namespace CFLAGS += -DHAVE_SNPRINTF=1 -U__ASSERT_USE_STDERR