diff --git a/core/net/ipv6/uip-ds6-nbr.h b/core/net/ipv6/uip-ds6-nbr.h index 5627f03aa..0c9b29128 100644 --- a/core/net/ipv6/uip-ds6-nbr.h +++ b/core/net/ipv6/uip-ds6-nbr.h @@ -74,6 +74,7 @@ typedef struct uip_ds6_nbr { uint8_t nscount; uint8_t isrouter; uint8_t state; + uint16_t link_metric; #if UIP_CONF_IPV6_QUEUE_PKT struct uip_packetqueue_handle packethandle; #define UIP_DS6_NBR_PACKET_LIFETIME CLOCK_SECOND * 4 diff --git a/core/net/ipv6/uip-ds6-route.c b/core/net/ipv6/uip-ds6-route.c index ecb7d354b..73a4ce9fa 100644 --- a/core/net/ipv6/uip-ds6-route.c +++ b/core/net/ipv6/uip-ds6-route.c @@ -269,9 +269,16 @@ uip_ds6_route_add(uip_ipaddr_t *ipaddr, uint8_t length, one first. */ r = uip_ds6_route_lookup(ipaddr); if(r != NULL) { + uip_ipaddr_t *current_nexthop; + current_nexthop = uip_ds6_route_nexthop(r); + if(uip_ipaddr_cmp(nexthop, current_nexthop)) { + /* no need to update route - already correct! */ + return r; + } PRINTF("uip_ds6_route_add: old route for "); PRINT6ADDR(ipaddr); PRINTF(" found, deleting it\n"); + uip_ds6_route_rm(r); } { diff --git a/core/net/rpl/rpl-dag.c b/core/net/rpl/rpl-dag.c index eb92e2f10..aaf75f1a4 100644 --- a/core/net/rpl/rpl-dag.c +++ b/core/net/rpl/rpl-dag.c @@ -47,6 +47,7 @@ #include "net/rpl/rpl-private.h" #include "net/ip/uip.h" #include "net/ipv6/uip-nd6.h" +#include "net/ipv6/uip-ds6-nbr.h" #include "net/nbr-table.h" #include "net/ipv6/multicast/uip-mcast6.h" #include "lib/list.h" @@ -79,6 +80,19 @@ NBR_TABLE(rpl_parent_t, rpl_parents); /* Allocate instance table. */ rpl_instance_t instance_table[RPL_MAX_INSTANCES]; rpl_instance_t *default_instance; + +/*---------------------------------------------------------------------------*/ +uip_ds6_nbr_t * +rpl_get_nbr(rpl_parent_t *parent) +{ + linkaddr_t *lladdr = NULL; + lladdr = nbr_table_get_lladdr(rpl_parents, parent); + if(lladdr != NULL) { + return nbr_table_get_from_lladdr(ds6_neighbors, lladdr); + } else { + return NULL; + } +} /*---------------------------------------------------------------------------*/ static void nbr_callback(void *ptr) @@ -113,9 +127,11 @@ rpl_get_parent_rank(uip_lladdr_t *addr) uint16_t rpl_get_parent_link_metric(const uip_lladdr_t *addr) { - rpl_parent_t *p = nbr_table_get_from_lladdr(rpl_parents, (const linkaddr_t *)addr); - if(p != NULL) { - return p->link_metric; + uip_ds6_nbr_t *nbr; + nbr = nbr_table_get_from_lladdr(ds6_neighbors, (const linkaddr_t *)addr); + + if(nbr != NULL) { + return nbr->link_metric; } else { return 0; } @@ -568,10 +584,17 @@ rpl_add_parent(rpl_dag_t *dag, rpl_dio_t *dio, uip_ipaddr_t *addr) if(p == NULL) { PRINTF("RPL: rpl_add_parent p NULL\n"); } else { + uip_ds6_nbr_t *nbr; + nbr = rpl_get_nbr(p); + p->dag = dag; p->rank = dio->rank; p->dtsn = dio->dtsn; - p->link_metric = RPL_INIT_LINK_METRIC * RPL_DAG_MC_ETX_DIVISOR; + + /* Check whether we have a neighbor that has not gotten a link metric yet */ + if(nbr != NULL && nbr->link_metric == 0) { + nbr->link_metric = RPL_INIT_LINK_METRIC * RPL_DAG_MC_ETX_DIVISOR; + } #if RPL_DAG_MC != RPL_DAG_MC_NONE memcpy(&p->mc, &dio->mc, sizeof(p->mc)); #endif /* RPL_DAG_MC != RPL_DAG_MC_NONE */ @@ -1037,6 +1060,14 @@ global_repair(uip_ipaddr_t *from, rpl_dag_t *dag, rpl_dio_t *dio) remove_parents(dag, 0); dag->version = dio->version; + + /* copy parts of the configuration so that it propagates in the network */ + dag->instance->dio_intdoubl = dio->dag_intdoubl; + dag->instance->dio_intmin = dio->dag_intmin; + dag->instance->dio_redundancy = dio->dag_redund; + dag->instance->default_lifetime = dio->default_lifetime; + dag->instance->lifetime_unit = dio->lifetime_unit; + dag->instance->of->reset(dag); dag->min_rank = INFINITE_RANK; RPL_LOLLIPOP_INCREMENT(dag->instance->dtsn_out); diff --git a/core/net/rpl/rpl-mrhof.c b/core/net/rpl/rpl-mrhof.c index 2d4c2109e..47314917f 100644 --- a/core/net/rpl/rpl-mrhof.c +++ b/core/net/rpl/rpl-mrhof.c @@ -90,16 +90,22 @@ typedef uint16_t rpl_path_metric_t; static rpl_path_metric_t calculate_path_metric(rpl_parent_t *p) { + uip_ds6_nbr_t *nbr; if(p == NULL) { return MAX_PATH_COST * RPL_DAG_MC_ETX_DIVISOR; } - + nbr = rpl_get_nbr(p); + if(nbr == NULL) { + return MAX_PATH_COST * RPL_DAG_MC_ETX_DIVISOR; + } #if RPL_DAG_MC == RPL_DAG_MC_NONE - return p->rank + (uint16_t)p->link_metric; + { + return p->rank + (uint16_t)nbr->link_metric; + } #elif RPL_DAG_MC == RPL_DAG_MC_ETX - return p->mc.obj.etx + (uint16_t)p->link_metric; + return p->mc.obj.etx + (uint16_t)nbr->link_metric; #elif RPL_DAG_MC == RPL_DAG_MC_ENERGY - return p->mc.obj.energy.energy_est + (uint16_t)p->link_metric; + return p->mc.obj.energy.energy_est + (uint16_t)nbr->link_metric; #else #error "Unsupported RPL_DAG_MC configured. See rpl.h." #endif /* RPL_DAG_MC */ @@ -114,9 +120,18 @@ reset(rpl_dag_t *dag) static void neighbor_link_callback(rpl_parent_t *p, int status, int numtx) { - uint16_t recorded_etx = p->link_metric; + uint16_t recorded_etx = 0; uint16_t packet_etx = numtx * RPL_DAG_MC_ETX_DIVISOR; uint16_t new_etx; + uip_ds6_nbr_t *nbr = NULL; + + nbr = rpl_get_nbr(p); + if(nbr == NULL) { + /* No neighbor for this parent - something bad has occurred */ + return; + } + + recorded_etx = nbr->link_metric; /* Do not penalize the ETX when collisions or transmission errors occur. */ if(status == MAC_TX_OK || status == MAC_TX_NOACK) { @@ -139,7 +154,8 @@ neighbor_link_callback(rpl_parent_t *p, int status, int numtx) (unsigned)(recorded_etx / RPL_DAG_MC_ETX_DIVISOR), (unsigned)(new_etx / RPL_DAG_MC_ETX_DIVISOR), (unsigned)(packet_etx / RPL_DAG_MC_ETX_DIVISOR)); - p->link_metric = new_etx; + /* update the link metric for this nbr */ + nbr->link_metric = new_etx; } } @@ -148,14 +164,15 @@ calculate_rank(rpl_parent_t *p, rpl_rank_t base_rank) { rpl_rank_t new_rank; rpl_rank_t rank_increase; + uip_ds6_nbr_t *nbr; - if(p == NULL) { + if(p == NULL || (nbr = rpl_get_nbr(p)) == NULL) { if(base_rank == 0) { return INFINITE_RANK; } rank_increase = RPL_INIT_LINK_METRIC * RPL_DAG_MC_ETX_DIVISOR; } else { - rank_increase = p->link_metric; + rank_increase = nbr->link_metric; if(base_rank == 0) { base_rank = p->rank; } diff --git a/core/net/rpl/rpl-of0.c b/core/net/rpl/rpl-of0.c index 0ad1d710e..ca73169fc 100644 --- a/core/net/rpl/rpl-of0.c +++ b/core/net/rpl/rpl-of0.c @@ -126,26 +126,34 @@ static rpl_parent_t * best_parent(rpl_parent_t *p1, rpl_parent_t *p2) { rpl_rank_t r1, r2; - rpl_dag_t *dag; + rpl_dag_t *dag; + uip_ds6_nbr_t *nbr1, *nbr2; + nbr1 = rpl_get_nbr(p1); + nbr2 = rpl_get_nbr(p2); + + dag = (rpl_dag_t *)p1->dag; /* Both parents must be in the same DAG. */ + + if(nbr1 == NULL || nbr2 == NULL) { + return dag->preferred_parent; + } PRINTF("RPL: Comparing parent "); PRINT6ADDR(rpl_get_parent_ipaddr(p1)); PRINTF(" (confidence %d, rank %d) with parent ", - p1->link_metric, p1->rank); + nbr1->link_metric, p1->rank); PRINT6ADDR(rpl_get_parent_ipaddr(p2)); PRINTF(" (confidence %d, rank %d)\n", - p2->link_metric, p2->rank); + nbr2->link_metric, p2->rank); r1 = DAG_RANK(p1->rank, p1->dag->instance) * RPL_MIN_HOPRANKINC + - p1->link_metric; + nbr1->link_metric; r2 = DAG_RANK(p2->rank, p1->dag->instance) * RPL_MIN_HOPRANKINC + - p2->link_metric; + nbr2->link_metric; /* Compare two parents by looking both and their rank and at the ETX for that parent. We choose the parent that has the most favourable combination. */ - dag = (rpl_dag_t *)p1->dag; /* Both parents must be in the same DAG. */ if(r1 < r2 + MIN_DIFFERENCE && r1 > r2 - MIN_DIFFERENCE) { return dag->preferred_parent; diff --git a/core/net/rpl/rpl.h b/core/net/rpl/rpl.h index 512c2f5f1..512c1a8f0 100644 --- a/core/net/rpl/rpl.h +++ b/core/net/rpl/rpl.h @@ -114,7 +114,6 @@ struct rpl_parent { rpl_metric_container_t mc; #endif /* RPL_DAG_MC != RPL_DAG_MC_NONE */ rpl_rank_t rank; - uint16_t link_metric; uint8_t dtsn; uint8_t flags; }; @@ -251,7 +250,7 @@ rpl_parent_t *rpl_get_parent(uip_lladdr_t *addr); rpl_rank_t rpl_get_parent_rank(uip_lladdr_t *addr); uint16_t rpl_get_parent_link_metric(const uip_lladdr_t *addr); void rpl_dag_init(void); - +uip_ds6_nbr_t *rpl_get_nbr(rpl_parent_t *parent); /** * RPL modes diff --git a/examples/ipv6/native-border-router/README.md b/examples/ipv6/native-border-router/README.md new file mode 100644 index 000000000..03174972f --- /dev/null +++ b/examples/ipv6/native-border-router/README.md @@ -0,0 +1,28 @@ +This code connects a 802.15.4 radio over TTY with the full uIPv6 stack of +Contiki including 6LoWPAN and 802.15.4 framing / parsing. The native border +router also acts as a RPL Root and handles the routing and maintains the RPL +network. Finally the native border router connects the full 6LoWPAN/RPL +network to the host (linux/os-x) network stack making it possible for +applications on the host to transparently reach all the nodes in the +6LoWPAN/RPL network. + +This is designed to interact with the a ../slip-radio example running on a +mote that is either directly USB/TTY connected, or is remote via a TCP +connect. What's on the SLIP interface is really not Serial Line IP, but SLIP +framed 15.4 packets. + +The border router supports a number of commands on it's stdin. +Each are prefixed by !: +* !G - global RPL repair root. +* !M - set MAC address (if coming from RADIO, i.e. SLIP link) +* !C - show channel (if coming from RADIO, i.e. SLIP link) +* !D - sensor data received +* !Q - exit + +Queries are prefixed by ?: +* ?M is used for requesting the MAC address from the radio in order to use it for uIP6 and its stateless address auto configuration of its IPv6 address. This will make the native border router have the address that correspond to the MAC address of the slip-radio. (response is !M from the slip-radio) + +* ?C is used for requesting the currently used channel for the slip-radio. The response is !C with a channel number (from the slip-radio). + +* !C is used for setting the channel of the slip-radio (useful if the motes are using another channel than the one used in the slip-radio). + diff --git a/examples/ipv6/slip-radio/README.md b/examples/ipv6/slip-radio/README.md new file mode 100644 index 000000000..5e3e0a5f6 --- /dev/null +++ b/examples/ipv6/slip-radio/README.md @@ -0,0 +1,6 @@ +This project is intended to run on a mode that is connected to a native host system +by SLIP. The SLIP is really SERIAL LINE 15.4, as this just turns the mote into a smart +radio, running the RPL and 6lowpan stack on the Host. This goes with native-border-router. + + + diff --git a/platform/avr-rcb/Makefile.avr-rcb b/platform/avr-rcb/Makefile.avr-rcb index 96dcd0cd3..5c14240b0 100644 --- a/platform/avr-rcb/Makefile.avr-rcb +++ b/platform/avr-rcb/Makefile.avr-rcb @@ -5,10 +5,14 @@ CONTIKI_TARGET_MAIN = ${CONTIKI_CORE}.o CONTIKI_TARGET_SOURCEFILES += rs232.c cfs-eeprom.c eeprom.c random.c \ mmem.c contiki-rcb-main.c +MODULES += core/net core/net/mac core/net/mac/sicslowmac core/net/mac/contikimac \ + core/net/mac/cxmac core/net/rime core/net/ipv4 core/net/ip \ + core/net/ipv6 core/net/rpl core/net/llsec + CONTIKIAVR=$(CONTIKI)/cpu/avr CONTIKIBOARD=. -CONTIKI_PLAT_DEFS = -DF_CPU=8000000UL -DAUTO_CRC_PADDING=2 +CONTIKI_PLAT_DEFS = -DF_CPU=8000000UL -DAUTO_CRC_PADDING=2 -DNETSTACK_CONF_WITH_RIME=1 -DNETSTACK_CONF_WITH_IPV6=1 MCU=atmega1281 AVRDUDE_PROGRAMMER=jtag2 diff --git a/platform/avr-rcb/contiki-conf.h b/platform/avr-rcb/contiki-conf.h index 2556c310b..3ecb788db 100644 --- a/platform/avr-rcb/contiki-conf.h +++ b/platform/avr-rcb/contiki-conf.h @@ -92,11 +92,24 @@ void clock_adjust_ticks(clock_time_t howmany); #define CCIF #define CLIF -//#define NETSTACK_CONF_WITH_IPV6 1 //Let makefile determine this so ipv4 hello-world will compile - #define LINKADDR_CONF_SIZE 8 -#define PACKETBUF_CONF_HDR_SIZE 0 +#define PACKETBUF_CONF_HDR_SIZE 48 /* Choose a buffersize != 0 for the messages which should be sended over the wireless interface */ +/* Uncomment this lines to activate the specific drivers */ +//#define NETSTACK_CONF_NETWORK rime_driver +//#define NETSTACK_CONF_MAC nullmac_driver +//#define NETSTACK_CONF_RDC sicslowmac_driver +//#define NETSTACK_CONF_FRAMER framer_802154 /* Framer for 802.15.4 Medium Access Control */ +#define NETSTACK_CONF_RADIO rf230_driver /* Select the wireless driver, otherwise contiki would operate with the "nulldriver" which does nothing */ + +#define RF230_CONF_AUTOACK 1 +#define CXMAC_CONF_ANNOUNCEMENTS 10 +#define NETSTACK_CONF_RDC_CHANNEL_CHECK_RATE 8 + +/* 211 bytes per queue buffer. Burst mode will need 15 for a 1280 byte MTU */ +#define QUEUEBUF_CONF_NUM 15 +/* 54 bytes per queue ref buffer */ +#define QUEUEBUF_CONF_REF_NUM 2 /* 0 for IPv6, or 1 for HC1, 2 for HC01 */ #define SICSLOWPAN_CONF_COMPRESSION_IPV6 0 #define SICSLOWPAN_CONF_COMPRESSION_HC1 1 @@ -124,18 +137,16 @@ void clock_adjust_ticks(clock_time_t howmany); #define UIP_CONF_NETIF_MAX_ADDRESSES 3 #define UIP_CONF_ND6_MAX_PREFIXES 3 #define UIP_CONF_ND6_MAX_DEFROUTERS 2 -#if NETSTACK_CONF_WITH_IPV6 //tcpip.c error on ipv4 build if UIP_CONF_ICMP6 defined -#define UIP_CONF_ICMP6 1 +#if NETSTACK_CONF_WITH_IPV6 //tcpip.c error on ipv4 build if UIP_CONF_ICMP6 defined +#define UIP_CONF_ICMP6 1 #endif #define UIP_CONF_UDP 1 #define UIP_CONF_UDP_CHECKSUMS 1 -#define UIP_CONF_TCP 0 +#define UIP_CONF_TCP 1 #define UIP_CONF_TCP_SPLIT 0 - - /* These names are deprecated, use C99 names. */ /*typedef unsigned char u8_t; typedef unsigned short u16_t; diff --git a/platform/avr-rcb/contiki-rcb-main.c b/platform/avr-rcb/contiki-rcb-main.c index 7516c27dc..bc7a08602 100644 --- a/platform/avr-rcb/contiki-rcb-main.c +++ b/platform/avr-rcb/contiki-rcb-main.c @@ -109,17 +109,18 @@ init_lowlevel(void) rs232_redirect_stdout(RS232_PORT_1); DDRE |= LED1 | LED2 | LED3; + + ctimer_init(); + } static struct etimer et; PROCESS_THREAD(rcb_leds, ev, data) { - uint8_t error; PROCESS_BEGIN(); - if((error = icmp6_new(NULL)) == 0) { while(1) { PROCESS_YIELD(); @@ -134,7 +135,6 @@ PROCESS_THREAD(rcb_leds, ev, data) LEDOff(LED2); } } - } PROCESS_END(); } @@ -142,14 +142,10 @@ PROCESS_THREAD(rcb_leds, ev, data) int main(void) { - //calibrate_rc_osc_32k(); //CO: Had to comment this out - /* Initialize hardware */ - init_lowlevel(); - + init_lowlevel(); /* Clock */ clock_init(); - LEDOff(LED1 | LED2); /* Process subsystem */ @@ -157,17 +153,29 @@ main(void) /* Register initial processes */ procinit_init(); + + /* It is very important to do the NETSTACK_* initializations right here + * to enable the PROCESS_YIELD** functionality. + * The receive process is an single protothread which handles the + * received packets. This process needs PROCESS_YIELD_UNTIL(). + **/ + /* Start radio and radio receive process */ + NETSTACK_RADIO.init(); + /* Initialize stack protocols */ + queuebuf_init(); + NETSTACK_RDC.init(); + NETSTACK_MAC.init(); + NETSTACK_NETWORK.init(); /* Autostart processes */ autostart_start(autostart_processes); printf_P(PSTR("\n********BOOTING CONTIKI*********\n")); - printf_P(PSTR("System online.\n")); /* Main scheduler loop */ while(1) { - process_run(); + process_run(); } return 0;