From b0907f0344a6887935452e79e44d1862d84e9e3e Mon Sep 17 00:00:00 2001 From: Vincent Brillault Date: Mon, 11 Jul 2011 12:04:52 +0200 Subject: [PATCH 01/25] Cleaning old .h : - Delete unimplemented function and unused structures - Remove misleading configuration options - Transfer some comments from 6lowmac to framer-802154 (doc/uip6-doc.txt should be cleaned as well) --- core/net/mac/framer-802154.c | 17 ++- core/net/tcpip.c | 6 +- core/net/uip-nd6.h | 268 ++++++----------------------------- core/net/uipopt.h | 16 +-- 4 files changed, 67 insertions(+), 240 deletions(-) diff --git a/core/net/mac/framer-802154.c b/core/net/mac/framer-802154.c index ba566de78..a95685a8f 100644 --- a/core/net/mac/framer-802154.c +++ b/core/net/mac/framer-802154.c @@ -54,9 +54,24 @@ #define PRINTADDR(addr) #endif +/** \brief The sequence number (0x00 - 0xff) added to the transmitted + * data or MAC command frame. The default is a random value within + * the range. + */ static uint8_t mac_dsn; + static uint8_t initialized = 0; + +/** \brief The 16-bit identifier of the PAN on which the device is + * sending to. If this value is 0xffff, the device is not + * associated. + */ static const uint16_t mac_dst_pan_id = IEEE802154_PANID; + +/** \brief The 16-bit identifier of the PAN on which the device is + * operating. If this value is 0xffff, the device is not + * associated. + */ static const uint16_t mac_src_pan_id = IEEE802154_PANID; /*---------------------------------------------------------------------------*/ @@ -145,7 +160,7 @@ create(void) /* Set the source PAN ID to the global variable. */ params.src_pid = mac_src_pan_id; - + /* * Set up the source address using only the long address mode for * phase 1. diff --git a/core/net/tcpip.c b/core/net/tcpip.c index 79b01b895..bdb68fd4d 100644 --- a/core/net/tcpip.c +++ b/core/net/tcpip.c @@ -477,9 +477,9 @@ eventhandler(process_event_t ev, process_data_t data) * check the different timers for neighbor discovery and * stateless autoconfiguration */ - /*if(data == &uip_nd6_timer_periodic && - etimer_expired(&uip_nd6_timer_periodic)) { - uip_nd6_periodic(); + /*if(data == &uip_ds6_timer_periodic && + etimer_expired(&uip_ds6_timer_periodic)) { + uip_ds6_periodic(); tcpip_ipv6_output(); }*/ #if !UIP_CONF_ROUTER diff --git a/core/net/uip-nd6.h b/core/net/uip-nd6.h index 38597ae63..38bfd0727 100644 --- a/core/net/uip-nd6.h +++ b/core/net/uip-nd6.h @@ -48,8 +48,8 @@ #include "net/uip.h" #include "sys/stimer.h" /** - * \name General - * @{ + * \name General + * @{ */ /** \brief HOP LIMIT to be used when sending ND messages (255) */ #define UIP_ND6_HOP_LIMIT 255 @@ -59,27 +59,10 @@ #define UIP_ND6_DEF_MAXDADNS 1 -/** \name Configuration options */ -/** @{ */ -#ifndef UIP_CONF_ND6_MAX_NEIGHBORS -/** \brief max number of entries in the neighbor cache */ -#define UIP_CONF_ND6_MAX_NEIGHBORS 4 -#endif /*UIP_CONF_ND6_MAX_NEIGHBORS*/ -#ifndef UIP_CONF_ND6_MAX_DEFROUTERS -/** \brief max number of entries in the default router cache */ -#define UIP_CONF_ND6_MAX_DEFROUTERS 2 -#endif /*UIP_CONF_ND6_MAX_DEFROUTERS*/ -#ifndef UIP_CONF_ND6_MAX_PREFIXES -/** \brief max number of entries in the prefix list */ -#define UIP_CONF_ND6_MAX_PREFIXES 2 -#endif /*UIP_CONF_ND6_MAX_PREFIXES*/ -/** @} */ - - /** \name RFC 4861 Host constant */ /** @{ */ -#define UIP_ND6_MAX_RTR_SOLICITATION_DELAY 1 -#define UIP_ND6_RTR_SOLICITATION_INTERVAL 4 +#define UIP_ND6_MAX_RTR_SOLICITATION_DELAY 1 +#define UIP_ND6_RTR_SOLICITATION_INTERVAL 4 #define UIP_ND6_MAX_RTR_SOLICITATIONS 3 /** @} */ @@ -115,7 +98,7 @@ #ifdef UIP_CONF_ND6_RETRANS_TIMER #define UIP_ND6_RETRANS_TIMER UIP_CONF_ND6_RETRANS_TIMER #else -#define UIP_ND6_RETRANS_TIMER 1000 +#define UIP_ND6_RETRANS_TIMER 1000 #endif #define UIP_ND6_DELAY_FIRST_PROBE_TIME 5 #define UIP_ND6_MIN_RANDOM_FACTOR(x) (x / 2) @@ -140,8 +123,8 @@ /** \name ND6 message length (excluding options) */ /** @{ */ -#define UIP_ND6_NA_LEN 20 -#define UIP_ND6_NS_LEN 20 +#define UIP_ND6_NA_LEN 20 +#define UIP_ND6_NS_LEN 20 #define UIP_ND6_RA_LEN 12 #define UIP_ND6_RS_LEN 4 /** @} */ @@ -160,7 +143,7 @@ #define UIP_ND6_OPT_SHORT_LLAO_LEN 8 #define UIP_ND6_OPT_LONG_LLAO_LEN 16 /** \brief length of a ND6 LLAO option for 802.15.4 */ -#define UIP_ND6_OPT_LLAO_LEN UIP_ND6_OPT_LONG_LLAO_LEN +#define UIP_ND6_OPT_LLAO_LEN UIP_ND6_OPT_LONG_LLAO_LEN #else /*UIP_CONF_LL_802154*/ #if UIP_CONF_LL_80211 /* If the interface is 802.11 */ @@ -179,93 +162,18 @@ #define UIP_ND6_NA_FLAG_ROUTER 0x80 #define UIP_ND6_NA_FLAG_SOLICITED 0x40 #define UIP_ND6_NA_FLAG_OVERRIDE 0x20 -#define UIP_ND6_RA_FLAG_ONLINK 0x80 -#define UIP_ND6_RA_FLAG_AUTONOMOUS 0x40 +#define UIP_ND6_RA_FLAG_ONLINK 0x80 +#define UIP_ND6_RA_FLAG_AUTONOMOUS 0x40 /** @} */ - -/** - * \brief Possible states for the neighbor cache entries - * - * NO_STATE is for implementation purposes: a router entry contains a pointer - * to a neighbor entry, which holds its ip address. If we do not know the LL - * address of the router, we do not have to create a neighbor entry as per - * RFC 4861. However, we still need to have the IP of the router stored in a - * neighbor entry, hence we create an entry in the NO_STATE state - */ -typedef enum { - INCOMPLETE = 0, - REACHABLE = 1, - STALE = 2, - DELAY = 3, - PROBE = 4, - NO_STATE = 5 -} uip_neighbor_state; - -/** - * \name ND structures - * @{ - */ -/** \brief An entry in the neighbor cache */ -struct uip_nd6_neighbor { - uip_ipaddr_t ipaddr; - uip_lladdr_t lladdr; - u8_t isrouter; - uip_neighbor_state state; - struct stimer reachable; - struct stimer last_send; /**< last time a ND message was sent */ - u8_t count_send; /**< how many ND message were already sent */ - u8_t used; /**< brief is this neighbor currently used */ -#if UIP_CONF_IPV6_QUEUE_PKT - u8_t queue_buf[UIP_BUFSIZE - UIP_LLH_LEN]; - /**< buffer to hold one packet during address resolution */ - u8_t queue_buf_len; - /**< length of the pkt in buffer, used as "boolean" as well*/ -#endif /*UIP_CONF_QUEUE_PKT*/ -}; - - -/** \brief An entry in the default router list */ -struct uip_nd6_defrouter { - struct uip_nd6_neighbor *nb; - struct stimer lifetime; - /**< the lifetime contained in RA corresponds to the interval field - * of the timer - */ - u8_t used; /**< Is this default router entry currently used */ -}; - -/** \brief A prefix list entry */ -struct uip_nd6_prefix { - uip_ipaddr_t ipaddr; - u8_t length; - /**< we do not use preferred lifetime, which is always smaller than - * valid lifetime (for addr, preferred->deprecated) - */ - struct stimer vlifetime; - u8_t is_infinite; /**< Is the prefix lifetime INFINITE */ - u8_t used; /**< Is this prefix entry currently used */ -}; -/** @} */ - -extern struct etimer uip_nd6_timer_periodic; - -/** - * \note - * We do not use a destination cache, do next-hop determination each time - * a packet needs to be sent. (info such as rtt, path mtu could be stored - * in uip_conn) - * - */ - /** * \name ND message structures * @{ */ -/** +/** * \brief A neighbor solicitation constant part - * + * * Possible option is: SLLAO */ typedef struct uip_nd6_ns { @@ -275,19 +183,19 @@ typedef struct uip_nd6_ns { /** * \brief A neighbor advertisement constant part. - * + * * Possible option is: TLLAO - */ + */ typedef struct uip_nd6_na { uint8_t flagsreserved; uint8_t reserved[3]; uip_ipaddr_t tgtipaddr; } uip_nd6_na; -/** +/** * \brief A router solicitation constant part - * - * Possible option is: SLLAO + * + * Possible option is: SLLAO */ typedef struct uip_nd6_rs { uint32_t reserved; @@ -295,7 +203,7 @@ typedef struct uip_nd6_rs { /** * \brief A router advertisement constant part - * + * * Possible options are: SLLAO, MTU, Prefix Information */ typedef struct uip_nd6_ra { @@ -308,13 +216,13 @@ typedef struct uip_nd6_ra { /** * \brief A redirect message constant part - * + * * Possible options are: TLLAO, redirected header */ typedef struct uip_nd6_redirect { uint32_t reserved; - uip_ipaddr_t tgtipaddress; - uip_ipaddr_t destipaddress; + uip_ipaddr_t tgtipaddress; + uip_ipaddr_t destipaddress; } uip_nd6_redirect; /** @} */ @@ -357,102 +265,6 @@ typedef struct uip_nd6_opt_redirected_hdr { } uip_nd6_opt_redirected_hdr; /** @} */ -/** - * \name ND Neighbor Cache, Router List and Prefix List handling functions - * @{ - */ -/** - * \brief Initialize Neighbor Discovery structures - */ -void uip_nd6_init(void); - -/** - * \brief Periodic processing of Neighbor Discovery Structures - */ -void uip_nd6_periodic(void); - -/** - * \brief Look for a neighbor cache entry corresponding to a specific IP - * address - * \param ipaddr the specific IP address - * \return the corresponding neighbor cache entry - */ -struct uip_nd6_neighbor *uip_nd6_nbrcache_lookup(uip_ipaddr_t *ipaddr); - -/** - * \brief Add a neighbor cache entry - * \param ipaddr the IP address of the entry - * \param lladdr the layer 2 address of the entry - * \param isrouter true is the entry is a router - * \param state the state of the entry - * \return the new neighbor or updated cache entry - */ -struct uip_nd6_neighbor * uip_nd6_nbrcache_add(uip_ipaddr_t *ipaddr, - uip_lladdr_t *lladdr, - u8_t isrouter, - uip_neighbor_state state); -/** - * \brief Returns a default router - */ -struct uip_nd6_defrouter * uip_nd6_choose_defrouter(void); - -/** - * \brief Find a default router corresponding to a given neighbor cache entry - * \param neighbor the neighbor cache entry - * \return the corresponding router if any - */ -struct uip_nd6_defrouter * -uip_nd6_defrouter_lookup(struct uip_nd6_neighbor *neighbor); - -/** - * \brief Remove a default router - * \param router to be removed - */ -void uip_nd6_defrouter_rm(struct uip_nd6_defrouter *router); - -/** - * \brief Add a default router - * \param neighbor the corresponding neighbor cache entry - * \param interval the lifetime of the router - * \return the new or updated defrouter entry - */ -struct uip_nd6_defrouter * -uip_nd6_defrouter_add(struct uip_nd6_neighbor *neighbor, unsigned long interval); - -/** - * \brief Check if an IP address in on-link by looking at prefix list - * \param ipaddr an IP address - * \return true if on-link - */ -u8_t uip_nd6_is_addr_onlink(uip_ipaddr_t *ipaddr); - -/** - * \brief Find a given prefix - * \param ipaddr an IP address - * \return the corresponding prefix if any - */ -struct uip_nd6_prefix * -uip_nd6_prefix_lookup(uip_ipaddr_t *ipaddr); - -/** - * \brief Add a prefix - * \param ipaddr the IP address of the prefix - * \param length the length of the prefix - * \param interval the lifetime of the prefix - * \return the new or updated prefix entry - */ -struct uip_nd6_prefix * -uip_nd6_prefix_add(uip_ipaddr_t *ipaddr, u8_t length, unsigned long interval); - -/** - * \brief Remove a prefix from th eprefix list - * \param prefix pointer to the prefix to be removed - */ -void - uip_nd6_prefix_rm(struct uip_nd6_prefix *prefix); -/** @} */ - - /** * \name ND Messages Processing and Generation * @{ @@ -467,7 +279,7 @@ void * address) * * We do: - * - if the tgt belongs to me, reply, otherwise ignore + * - if the tgt belongs to me, reply, otherwise ignore * - if i was performing DAD for the same address, two cases: * -- I already sent a NS, hence I win * -- I did not send a NS yet, hence I lose @@ -476,13 +288,13 @@ void * address resolution, or DAD and there is a conflict), we do it in this * function: set src, dst, tgt address in the three cases, then for all cases * set the rest, including SLLAO - * + * */ void uip_nd6_ns_input(void); /** - * \brief Send a neighbor solicitation, send a Neighbor Advertisement + * \brief Send a neighbor solicitation, send a Neighbor Advertisement * \param src pointer to the src of the NS if known * \param dest pointer to ip address to send the NS, for DAD or ADDR Resol, * MUST be NULL, for NUD, must be correct unicast dest @@ -496,13 +308,13 @@ uip_nd6_ns_input(void); * solicitation. Otherwise, any one of the addresses assigned to the * interface should be used." * This is why we have a src ip address as argument. If NULL, we will do - * src address selection, otherwise we use the argument. - * + * src address selection, otherwise we use the argument. + * * - we check if it is a NS for Address resolution or NUD, if yes we include * a SLLAO option, otherwise no. */ void -uip_nd6_ns_output(uip_ipaddr_t *src, uip_ipaddr_t *dest, uip_ipaddr_t *tgt); +uip_nd6_ns_output(uip_ipaddr_t *src, uip_ipaddr_t *dest, uip_ipaddr_t *tgt); /** * \brief Process a Neighbor Advertisement @@ -528,7 +340,7 @@ uip_nd6_na_input(void); #if UIP_ND6_SEND_RA /** * \brief Process a Router Solicitation - * + * */ void uip_nd6_rs_input(void); @@ -543,12 +355,12 @@ void uip_nd6_ra_output(uip_ipaddr_t *dest); /** * \brief Send a Router Solicitation - * + * * src is chosen through the uip_netif_select_src function. If src is * unspecified (i.e. we do not have a preferred address yet), then we do not * put a SLLAO option (MUST NOT in RFC 4861). Otherwise we do. * - * RS message format, + * RS message format, * possible option is SLLAO, MUST NOT be included if source = unspecified * SHOULD be included otherwise */ @@ -559,7 +371,7 @@ void uip_nd6_rs_output(void); * \brief process a Router Advertisement * * - Possible actions when receiving a RA: add router to router list, - * recalculate reachable time, update link hop limit, update retrans timer. + * recalculate reachable time, update link hop limit, update retrans timer. * - If MTU option: update MTU. * - If SLLAO option: update entry in neighbor cache * - If prefix option: start autoconf, add prefix to prefix list @@ -570,13 +382,13 @@ uip_nd6_ra_input(void); void -uip_appserver_addr_get(uip_ipaddr_t *ipaddr); +uip_appserver_addr_get(uip_ipaddr_t *ipaddr); /*--------------------------------------*/ /******* ANNEX - message formats ********/ /*--------------------------------------*/ -/* - * RS format. possible option is SLLAO +/* + * RS format. possible option is SLLAO * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -644,7 +456,7 @@ uip_appserver_addr_get(uip_ipaddr_t *ipaddr); * | Options ... * +-+-+-+-+-+-+-+-+-+-+-+- * - * + * * Redirect message format. Possible options are TLLAO and Redirected header * * 0 1 2 3 @@ -673,7 +485,7 @@ uip_appserver_addr_get(uip_ipaddr_t *ipaddr); * | Options ... * +-+-+-+-+-+-+-+-+-+-+-+- * - * + * * SLLAO/TLLAO option: * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 @@ -681,7 +493,7 @@ uip_appserver_addr_get(uip_ipaddr_t *ipaddr); * | Type | Length | Link-Layer Address ... * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * - * + * * Prefix information option * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 @@ -712,8 +524,8 @@ uip_appserver_addr_get(uip_ipaddr_t *ipaddr); * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | MTU | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * + * + * * Redirected header option * * 0 1 2 3 @@ -728,7 +540,7 @@ uip_appserver_addr_get(uip_ipaddr_t *ipaddr); * | | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * - */ + */ #endif /* __UIP_ND6_H__ */ /** @} */ diff --git a/core/net/uipopt.h b/core/net/uipopt.h index b409bbd82..d36c1df59 100644 --- a/core/net/uipopt.h +++ b/core/net/uipopt.h @@ -194,12 +194,12 @@ #define UIP_CONF_IPV6_QUEUE_PKT 0 #endif -#ifndef UIP_CONF_IPV6_CHECKS +#ifndef UIP_CONF_IPV6_CHECKS /** Do we do IPv6 consistency checks (highly recommended, default: yes) */ #define UIP_CONF_IPV6_CHECKS 1 #endif -#ifndef UIP_CONF_IPV6_REASSEMBLY +#ifndef UIP_CONF_IPV6_REASSEMBLY /** Do we do IPv6 fragmentation (default: no) */ #define UIP_CONF_IPV6_REASSEMBLY 0 #endif @@ -209,19 +209,19 @@ #define UIP_CONF_NETIF_MAX_ADDRESSES 3 #endif -#ifndef UIP_CONF_ND6_MAX_PREFIXES +#ifndef UIP_CONF_DS6_PREFIX_NBU /** Default number of IPv6 prefixes associated to the node's interface */ -#define UIP_CONF_ND6_MAX_PREFIXES 3 +#define UIP_CONF_DS6_PREFIX_NBU 2 #endif -#ifndef UIP_CONF_ND6_MAX_NEIGHBORS +#ifndef UIP_CONF_DS6_NBR_NBU /** Default number of neighbors that can be stored in the %neighbor cache */ -#define UIP_CONF_ND6_MAX_NEIGHBORS 4 +#define UIP_CONF_DS6_NBR_NBU 4 #endif -#ifndef UIP_CONF_ND6_MAX_DEFROUTERS +#ifndef UIP_CONF_DS6_DEFRT_NBU /** Minimum number of default routers */ -#define UIP_CONF_ND6_MAX_DEFROUTERS 2 +#define UIP_CONF_DS6_DEFRT_NBU 2 #endif /** @} */ From 6ddd0bb190661fb971e5beb6a3167805272190fa Mon Sep 17 00:00:00 2001 From: Vincent Brillault Date: Mon, 11 Jul 2011 13:24:17 +0200 Subject: [PATCH 02/25] Allow to completely desactivate DAD (useless in route-over LLN as implemented, see http://tools.ietf.org/html/draft-ietf-6lowpan-nd-15#section-8.2) --- core/net/uip-ds6.c | 13 +++++++++++-- core/net/uip-ds6.h | 4 ++++ core/net/uip-nd6.c | 8 ++++++++ core/net/uip-nd6.h | 9 +++++++++ 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/core/net/uip-ds6.c b/core/net/uip-ds6.c index 7e3cf1882..cea431612 100644 --- a/core/net/uip-ds6.c +++ b/core/net/uip-ds6.c @@ -148,16 +148,19 @@ uip_ds6_init(void) void uip_ds6_periodic(void) { + /* Periodic processing on unicast addresses */ for(locaddr = uip_ds6_if.addr_list; locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) { if(locaddr->isused) { if((!locaddr->isinfinite) && (stimer_expired(&locaddr->vlifetime))) { uip_ds6_addr_rm(locaddr); +#if UIP_ND6_DEF_MAXDADNS > 0 } else if((locaddr->state == ADDR_TENTATIVE) && (locaddr->dadnscount <= uip_ds6_if.maxdadns) && (timer_expired(&locaddr->dadtimer))) { uip_ds6_dad(locaddr); +#endif /* UIP_ND6_DEF_MAXDADNS > 0 */ } } } @@ -549,7 +552,6 @@ uip_ds6_addr_add(uip_ipaddr_t *ipaddr, unsigned long vlifetime, uint8_t type) (uip_ds6_element_t **)&locaddr) == FREESPACE) { locaddr->isused = 1; uip_ipaddr_copy(&locaddr->ipaddr, ipaddr); - locaddr->state = ADDR_TENTATIVE; locaddr->type = type; if(vlifetime == 0) { locaddr->isinfinite = 1; @@ -557,10 +559,15 @@ uip_ds6_addr_add(uip_ipaddr_t *ipaddr, unsigned long vlifetime, uint8_t type) locaddr->isinfinite = 0; stimer_set(&(locaddr->vlifetime), vlifetime); } +#if UIP_ND6_DEF_MAXDADNS > 0 + locaddr->state = ADDR_TENTATIVE; timer_set(&locaddr->dadtimer, random_rand() % (UIP_ND6_MAX_RTR_SOLICITATION_DELAY * CLOCK_SECOND)); locaddr->dadnscount = 0; +#else /* UIP_ND6_DEF_MAXDADNS > 0 */ + locaddr->state = ADDR_PREFERRED; +#endif /* UIP_ND6_DEF_MAXDADNS > 0 */ uip_create_solicited_node(ipaddr, &loc_fipaddr); uip_ds6_maddr_add(&loc_fipaddr); return locaddr; @@ -884,6 +891,7 @@ get_match_length(uip_ipaddr_t *src, uip_ipaddr_t *dst) } /*---------------------------------------------------------------------------*/ +#if UIP_ND6_DEF_MAXDADNS > 0 void uip_ds6_dad(uip_ds6_addr_t *addr) { @@ -922,10 +930,11 @@ uip_ds6_dad_failed(uip_ds6_addr_t * addr) uip_ds6_addr_rm(addr); return 1; } +#endif /*UIP_ND6_DEF_MAXDADNS > 0 */ +/*---------------------------------------------------------------------------*/ #if UIP_CONF_ROUTER #if UIP_ND6_SEND_RA -/*---------------------------------------------------------------------------*/ void uip_ds6_send_ra_sollicited(void) { diff --git a/core/net/uip-ds6.h b/core/net/uip-ds6.h index 064587ac2..3b31d8315 100644 --- a/core/net/uip-ds6.h +++ b/core/net/uip-ds6.h @@ -209,8 +209,10 @@ typedef struct uip_ds6_addr { uint8_t type; uint8_t isinfinite; struct stimer vlifetime; +#if UIP_ND6_DEF_MAXDADNS > 0 struct timer dadtimer; uint8_t dadnscount; +#endif /* UIP_ND6_DEF_MAXDADNS > 0 */ } uip_ds6_addr_t; /** \brief Anycast address */ @@ -385,11 +387,13 @@ void uip_ds6_set_addr_iid(uip_ipaddr_t * ipaddr, uip_lladdr_t * lladdr); /** \brief Get the number of matching bits of two addresses */ uint8_t get_match_length(uip_ipaddr_t * src, uip_ipaddr_t * dst); +#if UIP_ND6_DEF_MAXDADNS >0 /** \brief Perform Duplicate Address Selection on one address */ void uip_ds6_dad(uip_ds6_addr_t * ifaddr); /** \brief Callback when DAD failed */ int uip_ds6_dad_failed(uip_ds6_addr_t * ifaddr); +#endif /* UIP_ND6_DEF_MAXDADNS */ /** \brief Source address selection, see RFC 3484 */ void uip_ds6_select_src(uip_ipaddr_t * src, uip_ipaddr_t * dst); diff --git a/core/net/uip-nd6.c b/core/net/uip-nd6.c index 1874cec51..f49fb9ed7 100644 --- a/core/net/uip-nd6.c +++ b/core/net/uip-nd6.c @@ -224,6 +224,7 @@ uip_nd6_ns_input(void) addr = uip_ds6_addr_lookup(&UIP_ND6_NS_BUF->tgtipaddr); if(addr != NULL) { +#if UIP_ND6_DEF_MAXDADNS > 0 if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) { /* DAD CASE */ #if UIP_CONF_IPV6_CHECKS @@ -242,6 +243,11 @@ uip_nd6_ns_input(void) uip_ds6_dad_failed(addr); goto discard; } +#else /* UIP_ND6_DEF_MAXDADNS > 0 */ + if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) { + /* DAD CASE */ + goto discard; +#endif /* UIP_ND6_DEF_MAXDADNS > 0 */ } #if UIP_CONF_IPV6_CHECKS if(uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr)) { @@ -441,9 +447,11 @@ uip_nd6_na_input(void) addr = uip_ds6_addr_lookup(&UIP_ND6_NA_BUF->tgtipaddr); /* Message processing, including TLLAO if any */ if(addr != NULL) { +#if UIP_ND6_DEF_MAXDADNS > 0 if(addr->state == ADDR_TENTATIVE) { uip_ds6_dad_failed(addr); } +#endif /*UIP_ND6_DEF_MAXDADNS > 0 */ PRINTF("NA received is bad\n"); goto discard; } else { diff --git a/core/net/uip-nd6.h b/core/net/uip-nd6.h index 38bfd0727..c62e0363e 100644 --- a/core/net/uip-nd6.h +++ b/core/net/uip-nd6.h @@ -57,7 +57,16 @@ #define UIP_ND6_INFINITE_LIFETIME 0xFFFFFFFF /** @} */ +#ifndef UIP_CONF_ND6_DEF_MAXDADNS +/** \brief Do not try DAD when using EUI-64 as allowed by draft-ietf-6lowpan-nd-15 section 8.2 */ +#if UIP_CONF_LL_802154 +#define UIP_ND6_DEF_MAXDADNS 0 +#else /* UIP_CONF_LL_802154 */ #define UIP_ND6_DEF_MAXDADNS 1 +#endif /* UIP_CONF_LL_802154 */ +#else /* UIP_CONF_ND6_DEF_MAXDADNS */ +#define UIP_ND6_DEF_MAXDADNS UIP_CONF_ND6_DEF_MAXDADNS +#endif /* UIP_CONF_ND6_DEF_MAXDADNS */ /** \name RFC 4861 Host constant */ /** @{ */ From 2ac91d53b573de66e6d473f0a8a74ea8ccc5e013 Mon Sep 17 00:00:00 2001 From: Vincent Brillault Date: Mon, 11 Jul 2011 14:19:14 +0200 Subject: [PATCH 03/25] Add (dangerous) feature : use layer 2 acks instead of NUD in the IPv6 layer. (Decrease packet numbers but dangerous if neighbors change their ips (not a problem in standard RPL with EUI-64 based addresses)) --- core/net/neighbor-info.c | 20 ++++++++++++++++++++ core/net/uip-ds6.c | 18 ++++++++++++++++++ core/net/uip-ds6.h | 8 ++++++++ 3 files changed, 46 insertions(+) diff --git a/core/net/neighbor-info.c b/core/net/neighbor-info.c index c36a2b8a5..f704073a1 100644 --- a/core/net/neighbor-info.c +++ b/core/net/neighbor-info.c @@ -39,6 +39,8 @@ #include "net/neighbor-info.h" #include "net/neighbor-attr.h" +#include "net/uip-ds6.h" +#include "net/uip-nd6.h" #define DEBUG DEBUG_NONE #include "net/uip-debug.h" @@ -104,6 +106,9 @@ neighbor_info_packet_sent(int status, int numtx) { const rimeaddr_t *dest; link_metric_t packet_metric; +#if UIP_DS6_LL_NUD + uip_ds6_nbr_t * nbr; +#endif /* UIP_DS6_LL_NUD */ dest = packetbuf_addr(PACKETBUF_ADDR_RECEIVER); if(rimeaddr_cmp(dest, &rimeaddr_null)) { @@ -118,6 +123,21 @@ neighbor_info_packet_sent(int status, int numtx) case MAC_TX_OK: packet_metric = numtx; add_neighbor(dest); +#if UIP_DS6_LL_NUD + nbr=uip_ds6_nbr_ll_lookup((uip_lladdr_t *) dest); + if (nbr!=NULL) { + PRINTF("neighbor-info : nbr state = %u\n",nbr->state); + } else { + PRINTF("neighbor-info : no nbr\n"); + } + if (nbr!=NULL && (nbr->state == STALE || nbr->state == DELAY || nbr->state == PROBE)) { + nbr->state = REACHABLE; + stimer_set(&nbr->reachable, UIP_ND6_REACHABLE_TIME / 1000); + PRINTF("neighbor-info : received a linklayer ack : "); + PRINTLLADDR((uip_lladdr_t *)dest); + PRINTF(" is reachable.\n"); + } +#endif /* UIP_DS6_LL_NUD */ break; case MAC_TX_COLLISION: packet_metric = numtx; diff --git a/core/net/uip-ds6.c b/core/net/uip-ds6.c index cea431612..6f11a5297 100644 --- a/core/net/uip-ds6.c +++ b/core/net/uip-ds6.c @@ -369,6 +369,24 @@ uip_ds6_nbr_lookup(uip_ipaddr_t *ipaddr) return NULL; } +/*---------------------------------------------------------------------------*/ +uip_ds6_nbr_t * +uip_ds6_nbr_ll_lookup(uip_lladdr_t *lladdr) +{ + uip_ds6_nbr_t *fin; + + for( locnbr=uip_ds6_nbr_cache, fin=locnbr + UIP_DS6_NBR_NB; + locnbrisused) { + if(!memcmp(lladdr,&locnbr->lladdr,UIP_LLADDR_LEN)) { + return locnbr; + } + } + } + return NULL; +} + /*---------------------------------------------------------------------------*/ uip_ds6_defrt_t * uip_ds6_defrt_add(uip_ipaddr_t *ipaddr, unsigned long interval) diff --git a/core/net/uip-ds6.h b/core/net/uip-ds6.h index 3b31d8315..dc608ef16 100644 --- a/core/net/uip-ds6.h +++ b/core/net/uip-ds6.h @@ -124,6 +124,13 @@ #endif #define UIP_DS6_AADDR_NB UIP_DS6_AADDR_NBS + UIP_DS6_AADDR_NBU +/*--------------------------------------------------*/ +/* Should we use LinkLayer acks in NUD ?*/ +#ifndef UIP_CONF_DS6_LL_NUD +#define UIP_DS6_LL_NUD 0 +#else +#define UIP_DS6_LL_NUD UIP_CONF_DS6_LL_NUD +#endif /*--------------------------------------------------*/ /** \brief Possible states for the nbr cache entries */ @@ -312,6 +319,7 @@ uip_ds6_nbr_t *uip_ds6_nbr_add(uip_ipaddr_t *ipaddr, uip_lladdr_t *lladdr, uint8_t isrouter, uint8_t state); void uip_ds6_nbr_rm(uip_ds6_nbr_t *nbr); uip_ds6_nbr_t *uip_ds6_nbr_lookup(uip_ipaddr_t *ipaddr); +uip_ds6_nbr_t *uip_ds6_nbr_ll_lookup(uip_lladdr_t *lladdr); /** @} */ From dc9cbe647de747247ecc0404383e572e9ac858d4 Mon Sep 17 00:00:00 2001 From: Vincent Brillault Date: Mon, 11 Jul 2011 15:50:51 +0200 Subject: [PATCH 04/25] Changes in RPL implementation : - Structural modification of RPL data storage. - Support multiple gateways (multiple DODAG-ID with a unique InstanceID) - Use Lollipop counters - Add leaf-only configuration option for RPL Bugfix : - Correctly send "Grounded" flag in DIO --- core/net/rpl/rpl-dag.c | 983 ++++++++++++------ core/net/rpl/rpl-icmp6.c | 206 ++-- core/net/rpl/rpl-of-etx.c | 78 +- core/net/rpl/rpl-of0.c | 32 +- core/net/rpl/rpl-private.h | 51 +- core/net/rpl/rpl-timers.c | 104 +- core/net/rpl/rpl.c | 405 +++++++- core/net/rpl/rpl.h | 161 ++- .../ipv6/rpl-border-router/border-router.c | 4 +- examples/ipv6/rpl-collect/udp-sender.c | 6 +- examples/ipv6/rpl-collect/udp-sink.c | 5 +- examples/ipv6/rpl-udp/udp-server.c | 5 +- platform/avr-ravenusb/cdc_task.c | 4 +- platform/avr-ravenusb/contiki-raven-main.c | 4 +- platform/mb851/contiki-init-net.c | 4 +- 15 files changed, 1497 insertions(+), 555 deletions(-) diff --git a/core/net/rpl/rpl-dag.c b/core/net/rpl/rpl-dag.c index 09b900a54..55dbc83b8 100644 --- a/core/net/rpl/rpl-dag.c +++ b/core/net/rpl/rpl-dag.c @@ -60,19 +60,14 @@ /************************************************************************/ extern rpl_of_t RPL_OF; static rpl_of_t * const objective_functions[] = {&RPL_OF}; + /************************************************************************/ - -#ifndef RPL_CONF_MAX_DAG_ENTRIES -#define RPL_MAX_DAG_ENTRIES 2 +#ifndef RPL_CONF_MAX_PARENTS_PER_DODAG +#define RPL_MAX_PARENTS_PER_DODAG 8 #else -#define RPL_MAX_DAG_ENTRIES RPL_CONF_MAX_DAG_ENTRIES -#endif /* !RPL_CONF_MAX_DAG_ENTRIES */ - -#ifndef RPL_CONF_MAX_PARENTS -#define RPL_MAX_PARENTS 8 -#else -#define RPL_MAX_PARENTS RPL_CONF_MAX_PARENTS +#define RPL_MAX_PARENTS_PER_DODAG RPL_CONF_MAX_PARENTS_PER_DODAG #endif /* !RPL_CONF_MAX_PARENTS */ + /************************************************************************/ /* RPL definitions. */ @@ -96,9 +91,12 @@ static rpl_of_t * const objective_functions[] = {&RPL_OF}; /************************************************************************/ /* Allocate parents from the same static MEMB chunk to reduce memory waste. */ -MEMB(parent_memb, struct rpl_parent, RPL_MAX_PARENTS); +MEMB(parent_memb, struct rpl_parent, RPL_MAX_PARENTS_PER_DODAG*RPL_MAX_INSTANCES*RPL_MAX_DODAG_PER_INSTANCE); + +/************************************************************************/ +/* Allocate instance table. */ +rpl_instance_t instance_table[RPL_MAX_INSTANCES]; -static rpl_dag_t dag_table[RPL_MAX_DAG_ENTRIES]; /************************************************************************/ /* Remove DAG parents with a rank that is at least the same as minimum_rank. */ static void @@ -118,6 +116,22 @@ remove_parents(rpl_dag_t *dag, rpl_rank_t minimum_rank) } /************************************************************************/ static void +nullify_parents(rpl_dag_t *dag, rpl_rank_t minimum_rank) +{ + rpl_parent_t *p, *p2; + + PRINTF("RPL: Removing parents (minimum rank %u)\n", + minimum_rank); + + for(p = list_head(dag->parents); p != NULL; p = p2) { + p2 = p->next; + if(p->rank >= minimum_rank) { + rpl_nullify_parent(dag, p); + } + } +} +/************************************************************************/ +static void remove_worst_parent(rpl_dag_t *dag, rpl_rank_t min_worst_rank) { rpl_parent_t *p, *worst; @@ -140,63 +154,81 @@ remove_worst_parent(rpl_dag_t *dag, rpl_rank_t min_worst_rank) } /************************************************************************/ static int -should_send_dao(rpl_dag_t *dag, rpl_dio_t *dio, rpl_parent_t *p) +should_send_dao(rpl_instance_t *instance, rpl_dio_t *dio, rpl_parent_t *p) { /* if MOP is set to no downward routes no DAO should be sent */ - if(dag->mop == RPL_MOP_NO_DOWNWARD_ROUTES) return 0; - return dio->dtsn > p->dtsn && p == dag->preferred_parent; + if(instance->mop == RPL_MOP_NO_DOWNWARD_ROUTES) return 0; + return (p == instance->current_dag->preferred_parent) && + (RPL_LOLLIPOP_GREATER_THAN(dio->dtsn,p->dtsn) || + ((RPL_LOLLIPOP_GREATER_THAN(p->dtsn,dio->dtsn))&&RPL_LOLLIPOP_IS_INIT(dio->dtsn))); } /************************************************************************/ static int acceptable_rank(rpl_dag_t *dag, rpl_rank_t rank) { return rank != INFINITE_RANK && - (dag->max_rankinc == 0 || - DAG_RANK(rank, dag) <= DAG_RANK(dag->min_rank + dag->max_rankinc, dag)); + ((dag->instance->max_rankinc == 0) || + DAG_RANK(rank, dag->instance) <= DAG_RANK(dag->min_rank + dag->instance->max_rankinc, dag->instance)); + } /************************************************************************/ rpl_dag_t * -rpl_set_root(uip_ipaddr_t *dag_id) +rpl_set_root(uint8_t instance_id, uip_ipaddr_t *dag_id) { rpl_dag_t *dag; - int version; + rpl_instance_t *instance; + uint8_t version; - version = -1; - dag = rpl_get_dag(RPL_DEFAULT_INSTANCE); + version = RPL_LOLLIPOP_INIT; + dag = rpl_get_dodag(instance_id, dag_id); if(dag != NULL) { - PRINTF("RPL: Dropping a joined DAG when setting this node as root"); version = dag->version; - rpl_free_dag(dag); + RPL_LOLLIPOP_INCREMENT(version); + PRINTF("RPL: Dropping a joined DAG when setting this node as root"); + if(dag == dag->instance->current_dag) { + dag->instance->current_dag = NULL; + } + rpl_free_dodag(dag); } - dag = rpl_alloc_dag(RPL_DEFAULT_INSTANCE); + dag = rpl_alloc_dodag(instance_id,dag_id); if(dag == NULL) { PRINTF("RPL: Failed to allocate a DAG\n"); return NULL; } + instance = dag->instance; + + dag->version = version; dag->joined = 1; - dag->version = version + 1; dag->grounded = RPL_GROUNDED; - dag->mop = RPL_MOP_DEFAULT; - dag->of = &RPL_OF; + instance->mop = RPL_MOP_DEFAULT; + instance->of = &RPL_OF; dag->preferred_parent = NULL; - dag->dtsn_out = 1; /* Trigger DAOs from the beginning. */ memcpy(&dag->dag_id, dag_id, sizeof(dag->dag_id)); - dag->dio_intdoubl = DEFAULT_DIO_INTERVAL_DOUBLINGS; - dag->dio_intmin = DEFAULT_DIO_INTERVAL_MIN; - dag->dio_redundancy = DEFAULT_DIO_REDUNDANCY; - dag->max_rankinc = DEFAULT_MAX_RANKINC; - dag->min_hoprankinc = DEFAULT_MIN_HOPRANKINC; + instance->dio_intdoubl = DEFAULT_DIO_INTERVAL_DOUBLINGS; + instance->dio_intmin = DEFAULT_DIO_INTERVAL_MIN; + instance->dio_redundancy = DEFAULT_DIO_REDUNDANCY; + instance->max_rankinc = DEFAULT_MAX_RANKINC; + instance->min_hoprankinc = DEFAULT_MIN_HOPRANKINC; + instance->default_lifetime = RPL_DEFAULT_LIFETIME; + instance->lifetime_unit = RPL_DEFAULT_LIFETIME_UNIT; - dag->default_lifetime = RPL_DEFAULT_LIFETIME; - dag->lifetime_unit = RPL_DEFAULT_LIFETIME_UNIT; + dag->rank = ROOT_RANK(instance); - dag->rank = ROOT_RANK(dag); + if(instance->current_dag != dag && instance->current_dag != NULL) { + /* Remove routes installed by DAOs. */ + rpl_remove_routes(instance->current_dag); - dag->of->update_metric_container(dag); + (instance->current_dag)->joined = 0; + } + + instance->current_dag = dag; + instance->dtsn_out = RPL_LOLLIPOP_INIT; + instance->of->update_metric_container(instance); + default_instance = instance; PRINTF("RPL: Node set to be a DAG root with DAG ID "); PRINT6ADDR(&dag->dag_id); @@ -204,13 +236,31 @@ rpl_set_root(uip_ipaddr_t *dag_id) ANNOTATE("#A root=%u\n",dag->dag_id.u8[sizeof(dag->dag_id) - 1]); - - rpl_reset_dio_timer(dag, 1); + rpl_reset_dio_timer(instance, 1); return dag; } /************************************************************************/ int +rpl_repair_root(uint8_t instance_id) +{ + rpl_instance_t * instance; + + instance = rpl_get_instance(instance_id); + if(instance == NULL) { + return 0; + } + + if(instance->current_dag->rank == ROOT_RANK(instance)) { + RPL_LOLLIPOP_INCREMENT(instance->current_dag->version); + RPL_LOLLIPOP_INCREMENT(instance->dtsn_out); + rpl_reset_dio_timer(instance, 1); + return 1; + } + return 0; +} +/************************************************************************/ +int rpl_set_prefix(rpl_dag_t *dag, uip_ipaddr_t *prefix, int len) { if(len <= 128) { @@ -225,72 +275,136 @@ rpl_set_prefix(rpl_dag_t *dag, uip_ipaddr_t *prefix, int len) } /************************************************************************/ int -rpl_set_default_route(rpl_dag_t *dag, uip_ipaddr_t *from) +rpl_set_default_route(rpl_instance_t *instance, uip_ipaddr_t *from) { - if(dag->def_route != NULL) { - PRINTF("RPL: Removing default route through "); - PRINT6ADDR(&dag->def_route->ipaddr); - PRINTF("\n"); - uip_ds6_defrt_rm(dag->def_route); + if(instance->def_route != NULL) { + if(instance->def_route->isused) { + PRINTF("RPL: Removing default route through "); + PRINT6ADDR(&instance->def_route->ipaddr); + PRINTF("\n"); + uip_ds6_defrt_rm(instance->def_route); + } + instance->def_route = NULL; } if(from != NULL) { PRINTF("RPL: Adding default route through "); PRINT6ADDR(from); PRINTF("\n"); - dag->def_route = uip_ds6_defrt_add(from, - RPL_LIFETIME(dag, - dag->default_lifetime)); - if(dag->def_route == NULL) { + instance->def_route = uip_ds6_defrt_add(from, + RPL_LIFETIME(instance, + instance->default_lifetime)); + if(instance->def_route == NULL) { return 0; } } - return 1; } /************************************************************************/ -rpl_dag_t * -rpl_alloc_dag(uint8_t instance_id) +rpl_instance_t * +rpl_alloc_instance(uint8_t instance_id) { - rpl_dag_t *dag; - rpl_dag_t *end; + rpl_instance_t *instance, *end; - for(dag = &dag_table[0], end = dag + RPL_MAX_DAG_ENTRIES; dag < end; dag++) { - if(dag->used == 0) { + for(instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES; instance < end; ++instance) { + if(instance->used == 0) { + memset(instance, 0, sizeof(*instance)); + instance->instance_id = instance_id; + instance->def_route = NULL; + instance->used = 1; + return instance; + } + } + return NULL; +} +/************************************************************************/ +rpl_dag_t * +rpl_alloc_dodag(uint8_t instance_id, uip_ipaddr_t *dag_id) +{ + rpl_dag_t *dag, *end; + rpl_instance_t *instance; + + instance = rpl_get_instance(instance_id); + if(instance == NULL ) { + instance = rpl_alloc_instance(instance_id); + if(instance == NULL ) { + RPL_STAT(rpl_stats.mem_overflows++); + return NULL; + } + dag = &instance->dag_table[0]; + dag->parents = &dag->parent_list; + list_init(dag->parents); + dag->used = 1; + dag->rank = INFINITE_RANK; + dag->min_rank = INFINITE_RANK; + dag->instance = instance; + instance->current_dag = dag; + return dag; + } + + for(dag = &instance->dag_table[0], end = dag + RPL_MAX_DODAG_PER_INSTANCE; dag < end; ++dag) { + if(!dag->used) { memset(dag, 0, sizeof(*dag)); dag->parents = &dag->parent_list; list_init(dag->parents); - dag->instance_id = instance_id; - dag->def_route = NULL; + dag->used = 1; dag->rank = INFINITE_RANK; dag->min_rank = INFINITE_RANK; + dag->instance = instance; return dag; } } - - RPL_STAT(rpl_stats.mem_overflows++); return NULL; } /************************************************************************/ void -rpl_free_dag(rpl_dag_t *dag) +rpl_set_default_instance(rpl_instance_t *instance) { - PRINTF("RPL: Leaving the DAG "); - PRINT6ADDR(&dag->dag_id); - PRINTF("\n"); + default_instance = instance; +} +/************************************************************************/ +void +rpl_free_instance(rpl_instance_t *instance) +{ + rpl_dag_t *dag; + rpl_dag_t *end; - /* Remove routes installed by DAOs. */ - rpl_remove_routes(dag); + PRINTF("RPL: Leaving the instance %u\n", instance->instance_id); - /* Remove parents and the default route. */ - remove_parents(dag, 0); - rpl_set_default_route(dag, NULL); + /* Remove any DODAG inside this instance */ + for(dag = &instance->dag_table[0], end = dag + RPL_MAX_DODAG_PER_INSTANCE; dag < end; ++dag) { + if(dag->used) { + rpl_free_dodag(dag); + } + } - ctimer_stop(&dag->dio_timer); - ctimer_stop(&dag->dao_timer); + rpl_set_default_route(instance, NULL); + ctimer_stop(&instance->dio_timer); + ctimer_stop(&instance->dao_timer); + + if(default_instance == instance) { + default_instance = NULL; + } + + instance->used = 0; +} +/************************************************************************/ +void +rpl_free_dodag(rpl_dag_t *dag) +{ + if(dag->joined) { + PRINTF("RPL: Leaving the DAG "); + PRINT6ADDR(&dag->dag_id); + PRINTF("\n"); + dag->joined = 0; + + /* Remove routes installed by DAOs. */ + rpl_remove_routes(dag); + + remove_parents(dag, 0); + } dag->used = 0; - dag->joined = 0; } /************************************************************************/ rpl_parent_t * @@ -303,17 +417,13 @@ rpl_add_parent(rpl_dag_t *dag, rpl_dio_t *dio, uip_ipaddr_t *addr) RPL_STAT(rpl_stats.mem_overflows++); return NULL; } - memcpy(&p->addr, addr, sizeof(p->addr)); p->dag = dag; p->rank = dio->rank; + p->dtsn = dio->dtsn; p->link_metric = INITIAL_LINK_METRIC; - p->dtsn = 0; - memcpy(&p->mc, &dio->mc, sizeof(p->mc)); - list_add(dag->parents, p); - return p; } /************************************************************************/ @@ -327,16 +437,138 @@ rpl_find_parent(rpl_dag_t *dag, uip_ipaddr_t *addr) return p; } } - return NULL; } +/************************************************************************/ +rpl_dag_t * +rpl_find_parent_dag(rpl_instance_t *instance, uip_ipaddr_t *addr) +{ + rpl_parent_t *p; + rpl_dag_t *dag, *end; + + for(dag = &instance->dag_table[0], end = dag + RPL_MAX_DODAG_PER_INSTANCE; dag < end; ++dag) { + if(dag->used) { + for(p = list_head(dag->parents); p != NULL; p = p->next) { + if(uip_ipaddr_cmp(&p->addr, addr)) { + return dag; + } + } + } + } + return NULL; +} +/************************************************************************/ +rpl_parent_t * +rpl_find_parent_any_dag(rpl_instance_t *instance, uip_ipaddr_t *addr) +{ + rpl_parent_t *p; + rpl_dag_t *dag, *end; + + for(dag = &instance->dag_table[0], end = dag + RPL_MAX_DODAG_PER_INSTANCE; dag < end; ++dag) { + if(dag->used) { + for(p = list_head(dag->parents); p != NULL; p = p->next) { + if(uip_ipaddr_cmp(&p->addr, addr)) { + return p; + } + } + } + } + return NULL; +} +/************************************************************************/ +rpl_dag_t * +rpl_select_dodag(rpl_instance_t * instance, rpl_parent_t *p) +{ + rpl_parent_t *last_parent; + rpl_dag_t *dag, *end, *best_dag; + rpl_rank_t old_rank; + + old_rank = instance->current_dag->rank; + last_parent = instance->current_dag->preferred_parent; + + best_dag = instance->current_dag; + if(best_dag->rank != ROOT_RANK(instance)) { + if(rpl_select_parent(p->dag) != NULL) { + if(p->dag != best_dag) { + best_dag = instance->of->best_dag(best_dag,p->dag); + } + } else if(p->dag == best_dag) { + best_dag = NULL; + for(dag = &instance->dag_table[0], end = dag + RPL_MAX_DODAG_PER_INSTANCE; dag < end; ++dag) { + if(dag->used && dag->preferred_parent != NULL && dag->preferred_parent->rank != INFINITE_RANK) { + if(best_dag == NULL) { + best_dag = dag; + } else { + best_dag = instance->of->best_dag(best_dag,dag); + } + } + } + } + } + + if(best_dag == NULL) { + /* No parent found : the calling function handle this problem. */ + return NULL; + } + + if(instance->current_dag != best_dag) { + /* Remove routes installed by DAOs. */ + rpl_remove_routes(instance->current_dag); + + PRINTF("RPL: New preferred DODAG : "); + PRINT6ADDR(&best_dag->dag_id); + PRINTF("\n"); + + best_dag->joined = 1; + instance->current_dag->joined = 0; + instance->current_dag = best_dag; + } + + instance->of->update_metric_container(instance); + /* Update the DAG rank. */ + best_dag->rank = instance->of->calculate_rank(best_dag->preferred_parent, 0); + if(best_dag->rank < best_dag->min_rank) { + best_dag->min_rank = best_dag->rank; + } else if(!acceptable_rank(best_dag,best_dag->rank)) { + PRINTF("RPL: New rank unacceptable !\n"); + instance->current_dag->preferred_parent = NULL; + if((instance->mop != RPL_MOP_NO_DOWNWARD_ROUTES) + && (last_parent != NULL)) { + /* Send a No-Path DAO to the removed preferred parent. */ + dao_output(last_parent, ZERO_LIFETIME); + } + return NULL; + } + + if(best_dag->preferred_parent != last_parent) { + rpl_set_default_route(instance, &best_dag->preferred_parent->addr); + PRINTF("RPL: Changed preferred parent, rank changed from %u to %u\n", + (unsigned)old_rank, best_dag->rank); + RPL_STAT(rpl_stats.parent_switch++); + if(instance->mop != RPL_MOP_NO_DOWNWARD_ROUTES) { + if(last_parent != NULL) { + /* Send a No-Path DAO to the removed preferred parent. */ + dao_output(last_parent, ZERO_LIFETIME); + } + /* The DAO parent set changed - schedule a DAO transmission. */ + RPL_LOLLIPOP_INCREMENT(instance->dtsn_out); + rpl_schedule_dao(instance); + } + rpl_reset_dio_timer(instance, 1); + } else if(best_dag->rank != old_rank) { + PRINTF("RPL: Preferred parent update, rank changed from %u to %u\n", + (unsigned)old_rank, best_dag->rank); + RPL_STAT(rpl_stats.parent_switch++); + rpl_reset_dio_timer(instance, 1); + } + return best_dag; +} /************************************************************************/ rpl_parent_t * rpl_select_parent(rpl_dag_t *dag) { - rpl_parent_t *p; - rpl_parent_t *best; + rpl_parent_t *p, *best; best = NULL; for(p = list_head(dag->parents); p != NULL; p = p->next) { @@ -345,86 +577,125 @@ rpl_select_parent(rpl_dag_t *dag) } else if(best == NULL) { best = p; } else { - best = dag->of->best_parent(best, p); + best = dag->instance->of->best_parent(best, p); } } - if(best == NULL) { - /* need to handle update of best... */ - return NULL; + if(best != NULL) { + dag->preferred_parent = best; + } else { + /* We should probably do something here .... */ } - - if(dag->preferred_parent != best) { - PRINTF("RPL: Sending a No-Path DAO to old DAO parent\n"); - dao_output(dag->preferred_parent, ZERO_LIFETIME); - - dag->preferred_parent = best; /* Cache the value. */ - dag->of->update_metric_container(dag); - rpl_set_default_route(dag, &best->addr); - /* The DAO parent set changed - schedule a DAO transmission. */ - if(dag->mop != RPL_MOP_NO_DOWNWARD_ROUTES) { - rpl_schedule_dao(dag); - } - rpl_reset_dio_timer(dag, 1); - PRINTF("RPL: New preferred parent, rank changed from %u to %u\n", - (unsigned)dag->rank, dag->of->calculate_rank(best, 0)); - RPL_STAT(rpl_stats.parent_switch++); - } - - /* Update the DAG rank, since link-layer information may have changed - the local confidence. */ - dag->rank = dag->of->calculate_rank(best, 0); - if(dag->rank < dag->min_rank) { - dag->min_rank = dag->rank; - } else if(!acceptable_rank(dag, best->rank)) { - /* Send a No-Path DAO to the soon-to-be-removed preferred parent. */ - dao_output(best, ZERO_LIFETIME); - - remove_parents(dag, 0); - return NULL; - } - return best; } /************************************************************************/ -int +void rpl_remove_parent(rpl_dag_t *dag, rpl_parent_t *parent) { - uip_ds6_defrt_t *defrt; - - /* Remove uIPv6 routes that have this parent as the next hop. **/ - uip_ds6_route_rm_by_nexthop(&parent->addr); - defrt = uip_ds6_defrt_lookup(&parent->addr); - if(defrt != NULL) { - PRINTF("RPL: Removing default route "); - PRINT6ADDR(&parent->addr); - PRINTF("\n"); - uip_ds6_defrt_rm(defrt); - dag->def_route = NULL; - } + rpl_nullify_parent(dag,parent); PRINTF("RPL: Removing parent "); PRINT6ADDR(&parent->addr); PRINTF("\n"); - if(parent == dag->preferred_parent) { - dag->preferred_parent = NULL; - } - list_remove(dag->parents, parent); memb_free(&parent_memb, parent); - return 0; +} +/************************************************************************/ +void +rpl_nullify_parent(rpl_dag_t *dag, rpl_parent_t *parent) +{ + if(parent == dag->preferred_parent) { + dag->preferred_parent = NULL; + dag->rank = INFINITE_RANK; + if(dag->joined) { + if(dag->instance->def_route != NULL) { + if(dag->instance->def_route->isused) { + PRINTF("RPL: Removing default route "); + PRINT6ADDR(&parent->addr); + PRINTF("\n"); + uip_ds6_defrt_rm(dag->instance->def_route); + } + dag->instance->def_route = NULL; + } + dao_output(parent, ZERO_LIFETIME); + } + } + + PRINTF("RPL: Nullifying parent "); + PRINT6ADDR(&parent->addr); + PRINTF("\n"); +} +/************************************************************************/ +void +rpl_move_parent(rpl_dag_t *dag_src, rpl_dag_t *dag_dst, rpl_parent_t *parent) +{ + if(parent == dag_src->preferred_parent) { + dag_src->preferred_parent = NULL; + dag_src->rank = INFINITE_RANK; + if(dag_src->joined + && dag_src->instance->def_route != NULL) { + if(dag_src->instance->def_route->isused) { + PRINTF("RPL: Removing default route "); + PRINT6ADDR(&parent->addr); + PRINTF("\n"); + uip_ds6_defrt_rm(dag_src->instance->def_route); + } + dag_src->instance->def_route = NULL; + } + } else if(dag_src->joined) { + /* Remove uIPv6 routes that have this parent as the next hop. */ + rpl_remove_routes_by_nexthop(&parent->addr,dag_src); + } + + PRINTF("RPL: Moving parent "); + PRINT6ADDR(&parent->addr); + PRINTF("\n"); + + list_remove(dag_src->parents, parent); + parent->dag = dag_dst; + list_add(dag_dst->parents, parent); } /************************************************************************/ rpl_dag_t * -rpl_get_dag(int instance_id) +rpl_get_any_dag(void) { int i; - for(i = 0; i < RPL_MAX_DAG_ENTRIES; i++) { - if(dag_table[i].joined && (instance_id == RPL_ANY_INSTANCE || - dag_table[i].instance_id == instance_id)) { - return &dag_table[i]; + for(i = 0; i < RPL_MAX_INSTANCES; ++i) { + if(instance_table[i].used && instance_table[i].current_dag->joined) { + return instance_table[i].current_dag; + } + } + return NULL; +} +/************************************************************************/ +rpl_instance_t * +rpl_get_instance(uint8_t instance_id) +{ + int i; + + for(i = 0; i < RPL_MAX_INSTANCES; ++i) { + if(instance_table[i].used && instance_table[i].instance_id == instance_id) { + return &instance_table[i]; + } + } + return NULL; +} +/************************************************************************/ +rpl_dag_t * +rpl_get_dodag(uint8_t instance_id, uip_ipaddr_t *dag_id) +{ + rpl_instance_t *instance, *end; + int i; + + for(instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES; instance < end; ++instance) { + if(instance->used && instance->instance_id == instance_id) { + for(i = 0; i < RPL_MAX_DODAG_PER_INSTANCE; ++i) { + if(instance->dag_table[i].used && (!memcmp(&instance->dag_table[i].dag_id, dag_id, sizeof(*dag_id)))) { + return &instance->dag_table[i]; + } + } } } return NULL; @@ -436,7 +707,7 @@ rpl_find_of(rpl_ocp_t ocp) unsigned int i; for(i = 0; - i < sizeof(objective_functions) / sizeof(objective_functions[0]); + i < sizeof(objective_functions) / sizeof(objective_functions[0]); i++) { if(objective_functions[i]->ocp == ocp) { return objective_functions[i]; @@ -446,27 +717,32 @@ rpl_find_of(rpl_ocp_t ocp) return NULL; } /************************************************************************/ -static void -join_dag(uip_ipaddr_t *from, rpl_dio_t *dio) +void +rpl_join_instance(uip_ipaddr_t *from, rpl_dio_t *dio) { + rpl_instance_t *instance; rpl_dag_t *dag; rpl_parent_t *p; rpl_of_t *of; - dag = rpl_alloc_dag(dio->instance_id); + dag = rpl_alloc_dodag(dio->instance_id, &dio->dag_id); if(dag == NULL) { PRINTF("RPL: Failed to allocate a DAG object!\n"); return; } + instance = dag->instance; + p = rpl_add_parent(dag, dio, from); PRINTF("RPL: Adding "); PRINT6ADDR(from); PRINTF(" as a parent: "); if(p == NULL) { PRINTF("failed\n"); + instance->used = 0; return; } + p->dtsn = dio->dtsn; PRINTF("succeeded\n"); /* Determine the objective function by using the @@ -475,6 +751,8 @@ join_dag(uip_ipaddr_t *from, rpl_dio_t *dio) if(of == NULL) { PRINTF("RPL: DIO for DAG instance %u does not specify a supported OF\n", dio->instance_id); + rpl_remove_parent(dag, p); + instance->used = 0; return; } @@ -494,30 +772,119 @@ join_dag(uip_ipaddr_t *from, rpl_dio_t *dio) } dag->joined = 1; - dag->used = 1; - dag->of = of; - dag->grounded = dio->grounded; - dag->mop = dio->mop; dag->preference = dio->preference; - dag->instance_id = dio->instance_id; - - dag->max_rankinc = dio->dag_max_rankinc; - dag->min_hoprankinc = dio->dag_min_hoprankinc; - + dag->grounded = dio->grounded; dag->version = dio->version; - dag->preferred_parent = p; - dag->of->update_metric_container(dag); - dag->dio_intdoubl = dio->dag_intdoubl; - dag->dio_intmin = dio->dag_intmin; - dag->dio_redundancy = dio->dag_redund; + instance->of = of; + instance->mop = dio->mop; + instance->dtsn_out = RPL_LOLLIPOP_INIT; + instance->instance_id = dio->instance_id; + + instance->max_rankinc = dio->dag_max_rankinc; + instance->min_hoprankinc = dio->dag_min_hoprankinc; + instance->dio_intdoubl = dio->dag_intdoubl; + instance->dio_intmin = dio->dag_intmin; + instance->dio_redundancy = dio->dag_redund; + instance->default_lifetime = dio->default_lifetime; + instance->lifetime_unit = dio->lifetime_unit; memcpy(&dag->dag_id, &dio->dag_id, sizeof(dio->dag_id)); /* copy prefix information into the dag */ memcpy(&dag->prefix_info, &dio->prefix_info, sizeof(rpl_prefix_t)); - dag->rank = dag->of->calculate_rank(p, dio->rank); + dag->preferred_parent = p; + instance->of->update_metric_container(instance); + dag->rank = instance->of->calculate_rank(p,0); + dag->min_rank = dag->rank; /* So far this is the lowest rank we know of. */ + + if(default_instance == NULL) { + default_instance = instance; + } + + PRINTF("RPL: Joined DAG with instance ID %u, rank %hu, DAG ID ", + dio->instance_id, dag->rank); + PRINT6ADDR(&dag->dag_id); + PRINTF("\n"); + + ANNOTATE("#A join=%u\n",dag->dag_id.u8[sizeof(dag->dag_id) - 1]); + + rpl_reset_dio_timer(instance, 1); + rpl_set_default_route(instance, from); + + if(instance->mop != RPL_MOP_NO_DOWNWARD_ROUTES) { + rpl_schedule_dao(instance); + } else { + PRINTF("RPL: The DIO does not meet the prerequisites for sending a DAO\n"); + } +} + +/************************************************************************/ +void +rpl_add_dodag(uip_ipaddr_t *from, rpl_dio_t *dio) +{ + rpl_instance_t *instance; + rpl_dag_t *dag, *previous_dag; + rpl_parent_t *p; + rpl_of_t *of; + + dag = rpl_alloc_dodag(dio->instance_id,&dio->dag_id); + if(dag == NULL) { + PRINTF("RPL: Failed to allocate a DAG object!\n"); + return; + } + + instance = dag->instance; + + previous_dag = rpl_find_parent_dag(instance, from); + if(previous_dag == NULL) { + p = rpl_add_parent(dag, dio, from); + PRINTF("RPL: Adding "); + PRINT6ADDR(from); + PRINTF(" as a parent: "); + if(p == NULL) { + PRINTF("failed\n"); + dag->used = 0; + return; + } + PRINTF("succeeded\n"); + } else { + p = rpl_find_parent(previous_dag, from); + rpl_move_parent(previous_dag,dag,p); + } + + /* Determine the objective function by using the + objective code point of the DIO. */ + of = rpl_find_of(dio->ocp); + if((of != instance->of) || + (instance->mop != dio->mop) || + (instance->max_rankinc != dio->dag_max_rankinc) || + (instance->min_hoprankinc != dio->dag_min_hoprankinc) || + (instance->dio_intdoubl != dio->dag_intdoubl) || + (instance->dio_intmin != dio->dag_intmin) || + (instance->dio_redundancy != dio->dag_redund) || + (instance->default_lifetime != dio->default_lifetime) || + (instance->lifetime_unit != dio->lifetime_unit)) { + PRINTF("RPL: DIO for DAG instance %u uncompatible with previos DIO\n", + dio->instance_id); + rpl_remove_parent(dag,p); + dag->used = 0; + return; + } + + dag->used = 1; + dag->grounded = dio->grounded; + dag->preference = dio->preference; + dag->version = dio->version; + + memcpy(&dag->dag_id, &dio->dag_id, sizeof(dio->dag_id)); + + /* copy prefix information into the dag */ + memcpy(&dag->prefix_info, &dio->prefix_info, sizeof(rpl_prefix_t)); + + dag->preferred_parent = p; + dag->rank = instance->of->calculate_rank(p,0); dag->min_rank = dag->rank; /* So far this is the lowest rank we know of. */ PRINTF("RPL: Joined DAG with instance ID %u, rank %hu, DAG ID ", @@ -527,19 +894,10 @@ join_dag(uip_ipaddr_t *from, rpl_dio_t *dio) ANNOTATE("#A join=%u\n",dag->dag_id.u8[sizeof(dag->dag_id) - 1]); - - dag->default_lifetime = dio->default_lifetime; - dag->lifetime_unit = dio->lifetime_unit; - - rpl_reset_dio_timer(dag, 1); - rpl_set_default_route(dag, from); - - if(should_send_dao(dag, dio, p)) { - rpl_schedule_dao(dag); - } else { - PRINTF("RPL: The DIO does not meet the prerequisites for sending a DAO\n"); - } + rpl_process_parent_event(instance,p); + p->dtsn = dio->dtsn; } + /************************************************************************/ static void global_repair(uip_ipaddr_t *from, rpl_dag_t *dag, rpl_dio_t *dio) @@ -548,19 +906,16 @@ global_repair(uip_ipaddr_t *from, rpl_dag_t *dag, rpl_dio_t *dio) remove_parents(dag, 0); dag->version = dio->version; - dag->dtsn_out = 1; - dag->of->reset(dag); + dag->instance->of->reset(dag); + dag->min_rank = INFINITE_RANK; + RPL_LOLLIPOP_INCREMENT(dag->instance->dtsn_out); if((p = rpl_add_parent(dag, dio, from)) == NULL) { PRINTF("RPL: Failed to add a parent during the global repair\n"); dag->rank = INFINITE_RANK; } else { - rpl_set_default_route(dag, from); - dag->rank = dag->of->calculate_rank(NULL, dio->rank); - dag->min_rank = dag->rank; - rpl_reset_dio_timer(dag, 1); - if(should_send_dao(dag, dio, p)) { - rpl_schedule_dao(dag); - } + dag->rank = dag->instance->of->calculate_rank(p,0); + dag->min_rank = dag->rank ; + rpl_process_parent_event(dag->instance,p); } PRINTF("RPL: Participating in a global repair (version=%u, rank=%hu)\n", dag->version, dag->rank); @@ -568,26 +923,20 @@ global_repair(uip_ipaddr_t *from, rpl_dag_t *dag, rpl_dio_t *dio) RPL_STAT(rpl_stats.global_repairs++); } /************************************************************************/ -int -rpl_repair_dag(rpl_dag_t *dag) -{ - if(dag->rank == ROOT_RANK(dag)) { - dag->version++; - dag->dtsn_out = 1; - rpl_reset_dio_timer(dag, 1); - return 1; - } - return 0; -} -/************************************************************************/ void -rpl_local_repair(rpl_dag_t *dag) +rpl_local_repair(rpl_instance_t *instance) { - PRINTF("RPL: Starting a local DAG repair\n"); + int i; - dag->rank = INFINITE_RANK; - remove_parents(dag, 0); - rpl_reset_dio_timer(dag, 1); + PRINTF("RPL: Starting a local instance repair\n"); + for(i = 0; i < RPL_MAX_DODAG_PER_INSTANCE; i++) { + if(instance->dag_table[i].used) { + instance->dag_table[i].rank = INFINITE_RANK; + nullify_parents(&instance->dag_table[i], 0); + } + } + + rpl_reset_dio_timer(instance,1); RPL_STAT(rpl_stats.local_repairs++); } @@ -595,75 +944,101 @@ rpl_local_repair(rpl_dag_t *dag) void rpl_recalculate_ranks(void) { - rpl_dag_t *dag; + rpl_instance_t *instance, *end; rpl_parent_t *p; + int i; /* * We recalculate ranks when we receive feedback from the system rather * than RPL protocol messages. This periodical recalculation is called * from a timer in order to keep the stack depth reasonably low. */ - dag = rpl_get_dag(RPL_ANY_INSTANCE); - if(dag != NULL) { - for(p = list_head(dag->parents); p != NULL; p = p->next) { - if(p->updated) { - p->updated = 0; - rpl_process_parent_event(dag, p); - /* - * Stop calculating here because the parent list may have changed. - * If more ranks need to be recalculated, it will be taken care of - * in subsequent calls to this functions. - */ - break; + for(instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES; instance < end; ++instance) { + if(instance->used) { + for(i = 0; i < RPL_MAX_DODAG_PER_INSTANCE; i++) { + if(instance->dag_table[i].used) { + for(p = list_head(instance->dag_table[i].parents); p != NULL; p = p->next) { + if(p->updated) { + p->updated = 0; + if(!rpl_process_parent_event(instance, p)) { + PRINTF("RPL: A parent was dropped\n"); + } + /* + * Stop calculating here because the parent list may have changed. + * If more ranks need to be recalculated, it will be taken care of + * in subsequent calls to this functions. + */ + break; + } + } + } } } } } /************************************************************************/ int -rpl_process_parent_event(rpl_dag_t *dag, rpl_parent_t *p) +rpl_process_parent_event(rpl_instance_t *instance, rpl_parent_t *p) { - rpl_rank_t parent_rank; rpl_rank_t old_rank; + int return_value; - /* Update the parent rank. */ - parent_rank = p->rank; - old_rank = dag->rank; + old_rank = instance->current_dag->rank; + return_value = 1; - if(rpl_select_parent(dag) == NULL) { - /* No suitable parent; trigger a local repair. */ - PRINTF("RPL: No parents found in a DAG\n"); - rpl_local_repair(dag); - return 1; - } - - if(DAG_RANK(old_rank, dag) != DAG_RANK(dag->rank, dag)) { - if(dag->rank < dag->min_rank) { - dag->min_rank = dag->rank; + if(p->rank == INFINITE_RANK) { + /* This parent is no longer valid */ + PRINTF("RPL: This parent is no longer valid \n"); + if(p != instance->current_dag->preferred_parent) { + rpl_nullify_parent(p->dag, p); + return 0; + } else { + rpl_nullify_parent(p->dag, p); + return_value = 0; } - PRINTF("RPL: Moving in the DAG from rank %hu to %hu\n", - DAG_RANK(old_rank, dag), DAG_RANK(dag->rank, dag)); - PRINTF("RPL: The preferred parent is "); - PRINT6ADDR(&dag->preferred_parent->addr); - PRINTF(" (rank %u)\n", - (unsigned)DAG_RANK(dag->preferred_parent->rank, dag)); - rpl_reset_dio_timer(dag, 1); - } - - if(parent_rank == INFINITE_RANK || - !acceptable_rank(dag, dag->of->calculate_rank(NULL, parent_rank))) { + } else if(!acceptable_rank(p->dag, p->rank)) { /* The candidate parent is no longer valid: the rank increase resulting from the choice of it as a parent would be too high. */ + PRINTF("RPL: Unacceptable rank\n"); + if(p != instance->current_dag->preferred_parent) { + rpl_nullify_parent(p->dag, p); + return 0; + } else { + rpl_nullify_parent(p->dag, p); + return_value = 0; + } + } + + if(rpl_select_dodag(instance, p) == NULL) { + /* No suitable parent; trigger a local repair. */ + PRINTF("RPL: No parents found in any DAG\n"); + rpl_local_repair(instance); return 0; } - return 1; +#if DEBUG + if(DAG_RANK(old_rank, instance) != DAG_RANK(instance->current_dag->rank, instance)) { + PRINTF("RPL: Moving in the Instance from rank %hu to %hu\n", + DAG_RANK(old_rank, instance), DAG_RANK(instance->current_dag->rank, instance)); + if(instance->current_dag->rank != INFINITE_RANK) { + PRINTF("RPL: The preferred parent is "); + PRINT6ADDR(&instance->current_dag->preferred_parent->addr); + PRINTF(" (rank %u)\n", + (unsigned)DAG_RANK(instance->current_dag->preferred_parent->rank, instance)); + } else { + PRINTF("RPL: We don't have any parent"); + } + } +#endif /* DEBUG */ + + return return_value; } /************************************************************************/ void rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio) { - rpl_dag_t *dag; + rpl_instance_t *instance; + rpl_dag_t *dag, *previous_dag; rpl_parent_t *p; if(dio->mop != RPL_MOP_DEFAULT) { @@ -671,51 +1046,61 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio) return; } - dag = rpl_get_dag(dio->instance_id); + if(dio->rank == INFINITE_RANK) { + PRINTF("RPL: Ignoring DIO from node with infinite rank: "); + PRINT6ADDR(from); + PRINTF("\n"); + return; + } + + instance = rpl_get_instance(dio->instance_id); + if(instance == NULL) { + PRINTF("RPL : New instance detected : Joining...\n"); + rpl_join_instance(from, dio); + return; + } + + dag = rpl_get_dodag(dio->instance_id,&dio->dag_id); if(dag == NULL) { - /* Join the first possible DAG of this RPL instance. */ - if(dio->rank != INFINITE_RANK) { - join_dag(from, dio); - } else { - PRINTF("RPL: Ignoring DIO from node with infinite rank: "); - PRINT6ADDR(from); - PRINTF("\n"); - } + PRINTF("RPL : Adding new dodag to known instance.\n"); + rpl_add_dodag(from,dio); return; } - if(memcmp(&dag->dag_id, &dio->dag_id, sizeof(dag->dag_id))) { - PRINTF("RPL: Ignoring DIO for another DAG within our instance\n"); - return; - } - - if(dio->version > dag->version) { - if(dag->rank == ROOT_RANK(dag)) { + if(RPL_LOLLIPOP_GREATER_THAN(dio->version,dag->version)) { + if(dag->rank == ROOT_RANK(instance)) { PRINTF("RPL: Root received inconsistent DIO version number\n"); - dag->version = dio->version + 1; - rpl_reset_dio_timer(dag, 1); + dag->version = dio->version; + RPL_LOLLIPOP_INCREMENT(dag->version); + rpl_reset_dio_timer(instance, 1); } else { global_repair(from, dag, dio); } return; - } else if(dio->version < dag->version) { - /* Inconsistency detected - someone is still on old version */ - PRINTF("RPL: old version received => inconsistency detected\n"); - rpl_reset_dio_timer(dag, 1); - return; + } else { + if(RPL_LOLLIPOP_GREATER_THAN(dag->version,dio->version)) { + /* Inconsistency detected - someone is still on old version */ + PRINTF("RPL: old version received => inconsistency detected\n"); + if(dag->joined) { + rpl_reset_dio_timer(instance, 1); + return; + } + } } if(dio->rank == INFINITE_RANK) { - rpl_reset_dio_timer(dag, 1); - } else if(dio->rank < ROOT_RANK(dag)) { + if(dag->joined) { + rpl_reset_dio_timer(instance, 1); + } + } else if(dio->rank < ROOT_RANK(instance)) { PRINTF("RPL: Ignoring DIO with too low rank: %u\n", (unsigned)dio->rank); return; } - if(dag->rank == ROOT_RANK(dag)) { + if(dag->rank == ROOT_RANK(instance)) { if(dio->rank != INFINITE_RANK) { - dag->dio_counter++; + instance->dio_counter++; } return; } @@ -729,42 +1114,58 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio) p = rpl_find_parent(dag, from); if(p == NULL) { - if(RPL_PARENT_COUNT(dag) == RPL_MAX_PARENTS) { - /* Make room for a new parent. */ - remove_worst_parent(dag, dio->rank); - } - - /* Add the DIO sender as a candidate parent. */ - p = rpl_add_parent(dag, dio, from); - if(p == NULL) { - PRINTF("RPL: Failed to add a new parent ("); + previous_dag = rpl_find_parent_dag(instance, from); + if(previous_dag == NULL) { + if(RPL_PARENT_COUNT(dag) == RPL_MAX_PARENTS_PER_DODAG) { + /* Make room for a new parent. */ + remove_worst_parent(dag, dio->rank); + } + /* Add the DIO sender as a candidate parent. */ + p = rpl_add_parent(dag, dio, from); + if(p == NULL) { + PRINTF("RPL: Failed to add a new parent ("); + PRINT6ADDR(from); + PRINTF(")\n"); + return; + } + PRINTF("RPL: New candidate parent with rank %u: ", (unsigned)p->rank); PRINT6ADDR(from); - PRINTF(")\n"); - return; + PRINTF("\n"); + } else { + p = rpl_find_parent(previous_dag, from); + rpl_move_parent(previous_dag,dag,p); + } + } else { + if(p->rank == dio->rank) { + PRINTF("RPL: Received consistent DIO\n"); + if(dag->joined) { + instance->dio_counter++; + } + } else { + p->rank=dio->rank; } - - PRINTF("RPL: New candidate parent with rank %u: ", (unsigned)p->rank); - PRINT6ADDR(from); - PRINTF("\n"); - } else if(DAG_RANK(p->rank, dag) == DAG_RANK(dio->rank, dag)) { - PRINTF("RPL: Received consistent DIO\n"); - dag->dio_counter++; } - + + PRINTF("RPL current state: Prefered DODAG: "); + PRINT6ADDR(&instance->current_dag->dag_id); + PRINTF(", rank: %u, min_rank: %u, ",instance->current_dag->rank,instance->current_dag->min_rank); + PRINTF("p->rank : %u, p->mc.obj.etx : %u, p->link_metric : %u, instance->mc.obj.etx %u\n", p->rank, p->mc.obj.etx, p->link_metric,instance->mc.obj.etx); + /* We have allocated a candidate parent; process the DIO further. */ - memcpy(&p->mc, &dio->mc, sizeof(p->mc)); - p->rank = dio->rank; - if(rpl_process_parent_event(dag, p) == 0) { - /* The candidate parent no longer exists. */ + memcpy(&p->mc, &dio->mc, sizeof(p->mc)); + if(rpl_process_parent_event(instance, p) == 0) { + PRINTF("RPL: The candidate parent is rejected\n"); return; } - - if(should_send_dao(dag, dio, p)) { - rpl_schedule_dao(dag); + + /* We don't use route control, so we can have only one official parent */ + if(dag->joined&&(p==dag->preferred_parent)) { + if(should_send_dao(instance, dio, p)) { + RPL_LOLLIPOP_INCREMENT(instance->dtsn_out); + rpl_schedule_dao(instance); + } } - p->dtsn = dio->dtsn; } /************************************************************************/ - diff --git a/core/net/rpl/rpl-icmp6.c b/core/net/rpl/rpl-icmp6.c index 76ae9eb59..f59125391 100644 --- a/core/net/rpl/rpl-icmp6.c +++ b/core/net/rpl/rpl-icmp6.c @@ -72,7 +72,7 @@ static void dio_input(void); static void dao_input(void); static void dao_ack_input(void); -static uint8_t dao_sequence; +static uint8_t dao_sequence = RPL_LOLLIPOP_INIT; /*---------------------------------------------------------------------------*/ static int get_global_addr(uip_ipaddr_t *addr) @@ -112,21 +112,27 @@ set32(uint8_t *buffer, int pos, uint32_t value) static void dis_input(void) { - rpl_dag_t *dag; + rpl_instance_t *instance; + rpl_instance_t *end; /* DAG Information Solicitation */ PRINTF("RPL: Received a DIS from "); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINTF("\n"); - dag = rpl_get_dag(RPL_ANY_INSTANCE); - if(dag != NULL) { - if(uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) { - PRINTF("RPL: Multicast DIS => reset DIO timer\n"); - rpl_reset_dio_timer(dag, 0); - } else { - PRINTF("RPL: Unicast DIS, reply to sender\n"); - dio_output(dag, &UIP_IP_BUF->srcipaddr); + for( instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES; instance < end; ++instance) { + if ( instance->used == 1 ) { +#if RPL_LEAF_ONLY + if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) { +#else /* !RPL_LEAF_ONLY */ + if(uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) { + PRINTF("RPL: Multicast DIS => reset DIO timer\n"); + rpl_reset_dio_timer(instance, 0); + } else { +#endif /* !RPL_LEAF_ONLY */ + PRINTF("RPL: Unicast DIS, reply to sender\n"); + dio_output(instance, &UIP_IP_BUF->srcipaddr); + } } } } @@ -199,7 +205,7 @@ dio_input(void) buffer_length = uip_len - uip_l2_l3_icmp_hdr_len; #if RPL_CONF_ADJUST_LLH_LEN - buffer_length+=UIP_LLH_LEN; //Add jackdaw, minimal-net ethernet header + buffer_length += UIP_LLH_LEN; /* Add jackdaw, minimal-net ethernet header */ #endif /* Process the DIO base option. */ @@ -211,6 +217,7 @@ dio_input(void) dio.rank = (buffer[i] << 8) | buffer[i + 1]; i += 2; + PRINTF("RPL: Incoming DIO InstanceID-Version %u-%u\n", (unsigned)dio.instance_id,(unsigned)dio.version); PRINTF("RPL: Incoming DIO rank %u\n", (unsigned)dio.rank); dio.grounded = buffer[i] & RPL_DIO_GROUNDED; @@ -224,6 +231,10 @@ dio_input(void) memcpy(&dio.dag_id, buffer + i, sizeof(dio.dag_id)); i += sizeof(dio.dag_id); + PRINTF("RPL: Incoming DIO DODAG "); + PRINT6ADDR(&dio.dag_id); + PRINTF(" preference : %u\n",dio.preference); + /* Check if there are any DIO suboptions. */ for(; i < buffer_length; i += len) { subopt_type = buffer[i]; @@ -249,7 +260,6 @@ dio_input(void) RPL_STAT(rpl_stats.malformed_msgs++); return; } - dio.mc.type = buffer[i + 2]; dio.mc.flags = buffer[i + 3] << 1; dio.mc.flags |= buffer[i + 4] >> 7; @@ -347,30 +357,50 @@ dio_input(void) } /*---------------------------------------------------------------------------*/ void -dio_output(rpl_dag_t *dag, uip_ipaddr_t *uc_addr) +dio_output(rpl_instance_t *instance, uip_ipaddr_t *uc_addr) { unsigned char *buffer; int pos; +#if !RPL_LEAF_ONLY uip_ipaddr_t addr; +#endif /* !RPL_LEAF_ONLY */ + +#if RPL_LEAF_ONLY + /* only respond to unicast DIS */ + if(uc_addr == NULL) { + return; + } +#endif /* RPL_LEAF_ONLY */ + + rpl_dag_t *dag = instance->current_dag; /* DAG Information Object */ pos = 0; buffer = UIP_ICMP_PAYLOAD; - buffer[pos++] = dag->instance_id; + buffer[pos++] = instance->instance_id; buffer[pos++] = dag->version; +#if RPL_LEAF_ONLY + buffer[pos++] = INFINITE_RANK >> 8; + buffer[pos++] = INFINITE_RANK & 0xff; +#else /* RPL_LEAF_ONLY */ buffer[pos++] = dag->rank >> 8; buffer[pos++] = dag->rank & 0xff; +#endif /* RPL_LEAF_ONLY */ buffer[pos] = 0; if(dag->grounded) { buffer[pos] |= RPL_DIO_GROUNDED; } - buffer[pos] = dag->mop << RPL_DIO_MOP_SHIFT; + buffer[pos] |= instance->mop << RPL_DIO_MOP_SHIFT; + buffer[pos] |= dag->preference & RPL_DIO_PREFERENCE_MASK; pos++; - buffer[pos++] = ++dag->dtsn_out; + buffer[pos++] = instance->dtsn_out; + + if (RPL_LOLLIPOP_IS_INIT(instance->dtsn_out)) + RPL_LOLLIPOP_INCREMENT(instance->dtsn_out); /* reserved 2 bytes */ buffer[pos++] = 0; /* flags */ @@ -379,49 +409,51 @@ dio_output(rpl_dag_t *dag, uip_ipaddr_t *uc_addr) memcpy(buffer + pos, &dag->dag_id, sizeof(dag->dag_id)); pos += 16; - if(dag->mc.type != RPL_DAG_MC_NONE) { - dag->of->update_metric_container(dag); +#if !RPL_LEAF_ONLY + if(instance->mc.type != RPL_DAG_MC_NONE) { + instance->of->update_metric_container(instance); buffer[pos++] = RPL_DIO_SUBOPT_DAG_METRIC_CONTAINER; buffer[pos++] = 6; - buffer[pos++] = dag->mc.type; - buffer[pos++] = dag->mc.flags >> 1; - buffer[pos] = (dag->mc.flags & 1) << 7; - buffer[pos++] |= (dag->mc.aggr << 4) | dag->mc.prec; - - if(dag->mc.type == RPL_DAG_MC_ETX) { + buffer[pos++] = instance->mc.type; + buffer[pos++] = instance->mc.flags >> 1; + buffer[pos] = (instance->mc.flags & 1) << 7; + buffer[pos++] |= (instance->mc.aggr << 4) | instance->mc.prec; + if(instance->mc.type == RPL_DAG_MC_ETX) { buffer[pos++] = 2; - buffer[pos++] = dag->mc.obj.etx >> 8; - buffer[pos++] = dag->mc.obj.etx & 0xff; - } else if(dag->mc.type == RPL_DAG_MC_ENERGY) { + buffer[pos++] = instance->mc.obj.etx >> 8; + buffer[pos++] = instance->mc.obj.etx & 0xff; + } else if(instance->mc.type == RPL_DAG_MC_ENERGY) { buffer[pos++] = 2; - buffer[pos++] = dag->mc.obj.energy.flags; - buffer[pos++] = dag->mc.obj.energy.energy_est; + buffer[pos++] = instance->mc.obj.energy.flags; + buffer[pos++] = instance->mc.obj.energy.energy_est; } else { PRINTF("RPL: Unable to send DIO because of unhandled DAG MC type %u\n", - (unsigned)dag->mc.type); + (unsigned)instance->mc.type); return; } } - /* Always add a sub-option for DAG configuration. */ +#endif /* RPL_LEAF_ONLY */ + + /* Always add a sub-option for DAG configuration */ buffer[pos++] = RPL_DIO_SUBOPT_DAG_CONF; buffer[pos++] = 14; buffer[pos++] = 0; /* No Auth, PCS = 0 */ - buffer[pos++] = dag->dio_intdoubl; - buffer[pos++] = dag->dio_intmin; - buffer[pos++] = dag->dio_redundancy; - buffer[pos++] = dag->max_rankinc >> 8; - buffer[pos++] = dag->max_rankinc & 0xff; - buffer[pos++] = dag->min_hoprankinc >> 8; - buffer[pos++] = dag->min_hoprankinc & 0xff; + buffer[pos++] = instance->dio_intdoubl; + buffer[pos++] = instance->dio_intmin; + buffer[pos++] = instance->dio_redundancy; + buffer[pos++] = instance->max_rankinc >> 8; + buffer[pos++] = instance->max_rankinc & 0xff; + buffer[pos++] = instance->min_hoprankinc >> 8; + buffer[pos++] = instance->min_hoprankinc & 0xff; /* OCP is in the DAG_CONF option */ - buffer[pos++] = dag->of->ocp >> 8; - buffer[pos++] = dag->of->ocp & 0xff; + buffer[pos++] = instance->of->ocp >> 8; + buffer[pos++] = instance->of->ocp & 0xff; buffer[pos++] = 0; /* reserved */ - buffer[pos++] = dag->default_lifetime; - buffer[pos++] = dag->lifetime_unit >> 8; - buffer[pos++] = dag->lifetime_unit & 0xff; + buffer[pos++] = instance->default_lifetime; + buffer[pos++] = instance->lifetime_unit >> 8; + buffer[pos++] = instance->lifetime_unit & 0xff; /* Check if we have a prefix to send also. */ if(dag->prefix_info.length > 0) { @@ -445,19 +477,27 @@ dio_output(rpl_dag_t *dag, uip_ipaddr_t *uc_addr) dag->prefix_info.length); } +#if RPL_LEAF_ONLY + PRINTF("RPL: Sending unicast-DIO with rank %u to ", + (unsigned)dag->rank); + PRINT6ADDR(uc_addr); + PRINTF("\n"); + uip_icmp6_send(uc_addr, ICMP6_RPL, RPL_CODE_DIO, pos); +#else /* RPL_LEAF_ONLY */ /* Unicast requests get unicast replies! */ if(uc_addr == NULL) { PRINTF("RPL: Sending a multicast-DIO with rank %u\n", - (unsigned)dag->rank); + (unsigned)instance->current_dag->rank); uip_create_linklocal_rplnodes_mcast(&addr); uip_icmp6_send(&addr, ICMP6_RPL, RPL_CODE_DIO, pos); } else { PRINTF("RPL: Sending unicast-DIO with rank %u to ", - (unsigned)dag->rank); + (unsigned)instance->current_dag->rank); PRINT6ADDR(uc_addr); PRINTF("\n"); uip_icmp6_send(uc_addr, ICMP6_RPL, RPL_CODE_DIO, pos); } +#endif /* RPL_LEAF_ONLY */ } /*---------------------------------------------------------------------------*/ static void @@ -465,10 +505,11 @@ dao_input(void) { uip_ipaddr_t dao_sender_addr; rpl_dag_t *dag; + rpl_instance_t *instance; unsigned char *buffer; uint16_t sequence; uint8_t instance_id; - rpl_lifetime_t lifetime; + uint8_t lifetime; uint8_t prefixlen; uint8_t flags; uint8_t subopt_type; @@ -494,32 +535,37 @@ dao_input(void) buffer = UIP_ICMP_PAYLOAD; buffer_length = uip_len - uip_l2_l3_icmp_hdr_len; + #if RPL_CONF_ADJUST_LLH_LEN buffer_length += UIP_LLH_LEN; /* Add jackdaw, minimal-net ethernet header */ #endif - pos = 0; instance_id = buffer[pos++]; - dag = rpl_get_dag(instance_id); - if(dag == NULL) { - PRINTF("RPL: Ignoring a DAO for a different RPL instance (%u)\n", + instance = rpl_get_instance(instance_id); + if(instance == NULL) { + PRINTF("RPL: Ignoring a DAO for an unknown RPL instance(%u)\n", instance_id); return; } - lifetime = dag->default_lifetime; + lifetime = instance->default_lifetime; flags = buffer[pos++]; /* reserved */ pos++; sequence = buffer[pos++]; + dag = instance->current_dag; /* Is the DAGID present? */ if(flags & RPL_DAO_D_FLAG) { - /* Currently the DAG ID is ignored since we only use global - RPL Instance IDs. */ + if(memcmp(&dag->dag_id, &buffer[pos], sizeof(dag->dag_id))) { + PRINTF("RPL: Ignoring a DAO for a DODAG different from ours\n"); + return; + } pos += 16; + } else { + /* Perhaps, there are verification to do but ... */ } /* Check if there are any DIO sub-options. */ @@ -529,7 +575,7 @@ dao_input(void) if(subopt_type == RPL_DIO_SUBOPT_PAD1) { len = 1; } else { - /* Sub-option with a two-byte header and payload */ + /* Sub-option with a two-byte header + payload */ len = 2 + buffer[i + 1]; } @@ -551,7 +597,7 @@ dao_input(void) } PRINTF("RPL: DAO lifetime: %u, prefix length: %u prefix: ", - (unsigned)lifetime, (unsigned)prefixlen); + (unsigned)lifetime, (unsigned)prefixlen); PRINT6ADDR(&prefix); PRINTF("\n"); @@ -559,7 +605,7 @@ dao_input(void) if(lifetime == ZERO_LIFETIME) { /* No-Path DAO received; invoke the route purging routine. */ - if(rep != NULL && rep->state.saved_lifetime == 0) { + if(rep != NULL && rep->state.saved_lifetime == 0 && rep->length==prefixlen) { PRINTF("RPL: Setting expiration timer for prefix "); PRINT6ADDR(&prefix); PRINTF("\n"); @@ -575,9 +621,11 @@ dao_input(void) if(learned_from == RPL_ROUTE_FROM_UNICAST_DAO) { /* Check whether this is a DAO forwarding loop. */ p = rpl_find_parent(dag, &dao_sender_addr); - if(p != NULL && DAG_RANK(p->rank, dag) < DAG_RANK(dag->rank, dag)) { + /* check if this is a new DAO registration with an "illegal" rank */ + /* if we already route to this node it is likely */ + if(p != NULL && DAG_RANK(p->rank, instance) < DAG_RANK(dag->rank, instance)) { PRINTF("RPL: Loop detected when receiving a unicast DAO from a node with a lower rank! (%u < %u)\n", - DAG_RANK(p->rank, dag), DAG_RANK(dag->rank, dag)); + DAG_RANK(p->rank, instance), DAG_RANK(dag->rank, instance)); p->rank = INFINITE_RANK; p->updated = 1; return; @@ -593,7 +641,7 @@ dao_input(void) } } - rep->state.lifetime = RPL_LIFETIME(dag, lifetime); + rep->state.lifetime = RPL_LIFETIME(instance, lifetime); rep->state.learned_from = learned_from; if(learned_from == RPL_ROUTE_FROM_UNICAST_DAO) { @@ -603,16 +651,18 @@ dao_input(void) PRINTF("\n"); uip_icmp6_send(&dag->preferred_parent->addr, ICMP6_RPL, RPL_CODE_DAO, buffer_length); - } else if(flags & RPL_DAO_K_FLAG) { - dao_ack_output(dag, &dao_sender_addr, sequence); + } + if(flags & RPL_DAO_K_FLAG) { + dao_ack_output(instance, &dao_sender_addr, sequence); } } } /*---------------------------------------------------------------------------*/ void -dao_output(rpl_parent_t *n, rpl_lifetime_t lifetime) +dao_output(rpl_parent_t *n, uint8_t lifetime) { rpl_dag_t *dag; + rpl_instance_t *instance; unsigned char *buffer; uint8_t prefixlen; uip_ipaddr_t addr; @@ -626,7 +676,7 @@ dao_output(rpl_parent_t *n, rpl_lifetime_t lifetime) } if(n == NULL) { - dag = rpl_get_dag(RPL_ANY_INSTANCE); + dag = rpl_get_any_dag(); if(dag == NULL) { PRINTF("RPL: Did not join a DAG before sending DAO\n"); return; @@ -635,19 +685,28 @@ dao_output(rpl_parent_t *n, rpl_lifetime_t lifetime) dag = n->dag; } + instance = dag->instance; + buffer = UIP_ICMP_PAYLOAD; - ++dao_sequence; + RPL_LOLLIPOP_INCREMENT(dao_sequence); pos = 0; - buffer[pos++] = dag->instance_id; + buffer[pos++] = instance->instance_id; + buffer[pos] = 0; +#if RPL_DAO_SPECIFY_DODAG + buffer[pos] |= RPL_DAO_D_FLAG; +#endif /* RPL_DAO_SPECIFY_DODAG */ #if RPL_CONF_DAO_ACK - buffer[pos++] = RPL_DAO_K_FLAG; /* DAO ACK request, no DODAGID */ -#else - buffer[pos++] = 0; /* No DAO ACK request, no DODAGID */ -#endif + buffer[pos] |= RPL_DAO_K_FLAG; +#endif /* RPL_CONF_DAO_ACK */ + ++pos; buffer[pos++] = 0; /* reserved */ - buffer[pos++] = dao_sequence & 0xff; + buffer[pos++] = dao_sequence; +#if RPL_DAO_SPECIFY_DODAG + memcpy(buffer + pos, &dag->dag_id, sizeof(dag->dag_id)); + pos+=sizeof(dag->dag_id); +#endif /* RPL_DAO_SPECIFY_DODAG */ /* create target subopt */ prefixlen = sizeof(prefix) * CHAR_BIT; @@ -696,9 +755,6 @@ dao_ack_input(void) buffer = UIP_ICMP_PAYLOAD; buffer_length = uip_len - uip_l2_l3_icmp_hdr_len; -#if RPL_CONF_ADJUST_LLH_LEN - buffer_length+=UIP_LLH_LEN; //Add jackdaw, minimal-net ethernet header -#endif instance_id = buffer[0]; sequence = buffer[2]; @@ -711,7 +767,7 @@ dao_ack_input(void) } /*---------------------------------------------------------------------------*/ void -dao_ack_output(rpl_dag_t *dag, uip_ipaddr_t *dest, uint8_t sequence) +dao_ack_output(rpl_instance_t *instance, uip_ipaddr_t *dest, uint8_t sequence) { unsigned char *buffer; @@ -721,7 +777,7 @@ dao_ack_output(rpl_dag_t *dag, uip_ipaddr_t *dest, uint8_t sequence) buffer = UIP_ICMP_PAYLOAD; - buffer[0] = dag->instance_id; + buffer[0] = instance->instance_id; buffer[1] = 0; buffer[2] = sequence; buffer[3] = 0; diff --git a/core/net/rpl/rpl-of-etx.c b/core/net/rpl/rpl-of-etx.c index 55bbadca4..dfa7cfbfd 100644 --- a/core/net/rpl/rpl-of-etx.c +++ b/core/net/rpl/rpl-of-etx.c @@ -46,19 +46,21 @@ #include "net/rpl/rpl-private.h" #include "net/neighbor-info.h" -#define DEBUG DEBUG_NONE +#define DEBUG 1 #include "net/uip-debug.h" static void reset(rpl_dag_t *); static void parent_state_callback(rpl_parent_t *, int, int); static rpl_parent_t *best_parent(rpl_parent_t *, rpl_parent_t *); +static rpl_dag_t *best_dag(rpl_dag_t *, rpl_dag_t *); static rpl_rank_t calculate_rank(rpl_parent_t *, rpl_rank_t); -static void update_metric_container(rpl_dag_t *); +static void update_metric_container(rpl_instance_t *); rpl_of_t rpl_of_etx = { reset, parent_state_callback, best_parent, + best_dag, calculate_rank, update_metric_container, 1 @@ -86,14 +88,14 @@ typedef uint16_t rpl_path_metric_t; static rpl_path_metric_t calculate_path_metric(rpl_parent_t *p) { - if(p == NULL || (p->mc.obj.etx == 0 && p->rank > ROOT_RANK(p->dag))) { + if(p == NULL || (p->mc.obj.etx == 0 && p->rank > ROOT_RANK(p->dag->instance))) { return MAX_PATH_COST * RPL_DAG_MC_ETX_DIVISOR; } return p->mc.obj.etx + NI_ETX_TO_RPL_ETX(p->link_metric); } static void -reset(rpl_dag_t *dag) +reset(rpl_dag_t *sag) { } @@ -114,7 +116,7 @@ calculate_rank(rpl_parent_t *p, rpl_rank_t base_rank) } rank_increase = NEIGHBOR_INFO_FIX2ETX(INITIAL_LINK_METRIC) * DEFAULT_MIN_HOPRANKINC; } else { - rank_increase = NEIGHBOR_INFO_FIX2ETX(p->link_metric) * p->dag->min_hoprankinc; + rank_increase = NEIGHBOR_INFO_FIX2ETX(p->link_metric) * p->dag->instance->min_hoprankinc; if(base_rank == 0) { base_rank = p->rank; } @@ -132,6 +134,32 @@ calculate_rank(rpl_parent_t *p, rpl_rank_t base_rank) return new_rank; } +static rpl_dag_t * +best_dag(rpl_dag_t *d1, rpl_dag_t *d2) +{ + if(d1->grounded) { + if (!d2->grounded) { + return d1; + } + } else if(d2->grounded) { + return d2; + } + + if(d1->preference < d2->preference) { + return d2; + } else { + if(d1->preference > d2->preference) { + return d1; + } + } + + if(d2->rank < d1->rank) { + return d2; + } else { + return d1; + } +} + static rpl_parent_t * best_parent(rpl_parent_t *p1, rpl_parent_t *p2) { @@ -142,7 +170,7 @@ best_parent(rpl_parent_t *p1, rpl_parent_t *p2) dag = p1->dag; /* Both parents must be in the same DAG. */ - min_diff = RPL_DAG_MC_ETX_DIVISOR / + min_diff = RPL_DAG_MC_ETX_DIVISOR / PARENT_SWITCH_THRESHOLD_DIV; p1_metric = calculate_path_metric(p1); @@ -164,18 +192,26 @@ best_parent(rpl_parent_t *p1, rpl_parent_t *p2) } static void -update_metric_container(rpl_dag_t *dag) +update_metric_container(rpl_instance_t *instance) { rpl_path_metric_t path_metric; + rpl_dag_t *dag; #if RPL_DAG_MC == RPL_DAG_MC_ENERGY uint8_t type; #endif - dag->mc.flags = RPL_DAG_MC_FLAG_P; - dag->mc.aggr = RPL_DAG_MC_AGGR_ADDITIVE; - dag->mc.prec = 0; + instance->mc.flags = RPL_DAG_MC_FLAG_P; + instance->mc.aggr = RPL_DAG_MC_AGGR_ADDITIVE; + instance->mc.prec = 0; - if(dag->rank == ROOT_RANK(dag)) { + dag = instance->current_dag; + + if (!dag->joined) { + /* We should probably do something here */ + return; + } + + if(dag->rank == ROOT_RANK(instance)) { path_metric = 0; } else { path_metric = calculate_path_metric(dag->preferred_parent); @@ -183,27 +219,27 @@ update_metric_container(rpl_dag_t *dag) #if RPL_DAG_MC == RPL_DAG_MC_ETX - dag->mc.type = RPL_DAG_MC_ETX; - dag->mc.length = sizeof(dag->mc.obj.etx); - dag->mc.obj.etx = path_metric; + instance->mc.type = RPL_DAG_MC_ETX; + instance->mc.length = sizeof(instance->mc.obj.etx); + instance->mc.obj.etx = path_metric; PRINTF("RPL: My path ETX to the root is %u.%u\n", - dag->mc.obj.etx / RPL_DAG_MC_ETX_DIVISOR, - (dag->mc.obj.etx % RPL_DAG_MC_ETX_DIVISOR * 100) / RPL_DAG_MC_ETX_DIVISOR); + instance->mc.obj.etx / RPL_DAG_MC_ETX_DIVISOR, + (instance->mc.obj.etx % RPL_DAG_MC_ETX_DIVISOR * 100) / RPL_DAG_MC_ETX_DIVISOR); #elif RPL_DAG_MC == RPL_DAG_MC_ENERGY - dag->mc.type = RPL_DAG_MC_ENERGY; - dag->mc.length = sizeof(dag->mc.obj.energy); + instance->mc.type = RPL_DAG_MC_ENERGY; + instance->mc.length = sizeof(instance->mc.obj.energy); - if(dag->rank == ROOT_RANK(dag)) { + if(dag->rank == ROOT_RANK(instance)) { type = RPL_DAG_MC_ENERGY_TYPE_MAINS; } else { type = RPL_DAG_MC_ENERGY_TYPE_BATTERY; } - dag->mc.obj.energy.flags = type << RPL_DAG_MC_ENERGY_TYPE; - dag->mc.obj.energy.energy_est = path_metric; + instance->mc.obj.energy.flags = type << RPL_DAG_MC_ENERGY_TYPE; + instance->mc.obj.energy.energy_est = path_metric; #else diff --git a/core/net/rpl/rpl-of0.c b/core/net/rpl/rpl-of0.c index b9ea90a83..19ea4277c 100644 --- a/core/net/rpl/rpl-of0.c +++ b/core/net/rpl/rpl-of0.c @@ -48,6 +48,7 @@ static void reset(rpl_dag_t *); static rpl_parent_t *best_parent(rpl_parent_t *, rpl_parent_t *); +static rpl_dag_t *best_dag(rpl_dag_t *, rpl_dag_t *); static rpl_rank_t calculate_rank(rpl_parent_t *, rpl_rank_t); static void update_metric_container(rpl_dag_t *); @@ -55,6 +56,7 @@ rpl_of_t rpl_of0 = { reset, NULL, best_parent, + best_dag, calculate_rank, update_metric_container, 0 @@ -92,6 +94,32 @@ calculate_rank(rpl_parent_t *p, rpl_rank_t base_rank) } +static rpl_dag_t * +best_dag(rpl_dag_t *d1, rpl_dag_t *d2) +{ + if(d1->grounded) { + if (!d2->grounded) { + return d1; + } + } else if(d2->grounded) { + return d2; + } + + if(d1->preference < d2->preference) { + return d2; + } else { + if(d1->preference > d2->preference) { + return d1; + } + } + + if(d2->rank < d1->rank) { + return d2; + } else { + return d1; + } +} + static rpl_parent_t * best_parent(rpl_parent_t *p1, rpl_parent_t *p2) { @@ -127,7 +155,7 @@ best_parent(rpl_parent_t *p1, rpl_parent_t *p2) } static void -update_metric_container(rpl_dag_t *dag) +update_metric_container(rpl_instance_t *instance) { - dag->mc.type = RPL_DAG_MC_NONE; + instance->mc.type = RPL_DAG_MC_NONE; } diff --git a/core/net/rpl/rpl-private.h b/core/net/rpl/rpl-private.h index db3ef8515..8d613330b 100644 --- a/core/net/rpl/rpl-private.h +++ b/core/net/rpl/rpl-private.h @@ -107,8 +107,8 @@ /* Default route lifetime as a multiple of the lifetime unit. */ #define RPL_DEFAULT_LIFETIME 0xff -#define RPL_LIFETIME(dag, lifetime) \ - ((unsigned long)(dag)->lifetime_unit * lifetime) +#define RPL_LIFETIME(instance, lifetime) \ + (((unsigned long)(instance)->lifetime_unit) * lifetime) #ifndef RPL_CONF_MIN_HOPRANKINC #define DEFAULT_MIN_HOPRANKINC 256 @@ -117,13 +117,13 @@ #endif #define DEFAULT_MAX_RANKINC (3 * DEFAULT_MIN_HOPRANKINC) -#define DAG_RANK(fixpt_rank, dag) ((fixpt_rank) / (dag)->min_hoprankinc) +#define DAG_RANK(fixpt_rank, instance) ((fixpt_rank) / (instance)->min_hoprankinc) /* Rank of a virtual root node that coordinates DAG root nodes. */ #define BASE_RANK 0 /* Rank of a root node. */ -#define ROOT_RANK(dag) (dag)->min_hoprankinc +#define ROOT_RANK(instance) (instance)->min_hoprankinc #define INFINITE_RANK 0xffff @@ -207,7 +207,7 @@ struct rpl_dio { uint8_t dag_intdoubl; uint8_t dag_intmin; uint8_t dag_redund; - rpl_lifetime_t default_lifetime; + uint8_t default_lifetime; uint16_t lifetime_unit; rpl_rank_t dag_max_rankinc; rpl_rank_t dag_min_hoprankinc; @@ -240,33 +240,50 @@ extern rpl_stats_t rpl_stats; #define RPL_STAT(code) #endif /* RPL_CONF_STATS */ /*---------------------------------------------------------------------------*/ +/* Instances */ +extern rpl_instance_t instance_table[]; +rpl_instance_t *default_instance; + /* ICMPv6 functions for RPL. */ void dis_output(uip_ipaddr_t *addr); -void dio_output(rpl_dag_t *, uip_ipaddr_t *uc_addr); -void dao_output(rpl_parent_t *, rpl_lifetime_t lifetime); -void dao_ack_output(rpl_dag_t *, uip_ipaddr_t *, uint8_t); +void dio_output(rpl_instance_t *, uip_ipaddr_t *uc_addr); +void dao_output(rpl_parent_t *, uint8_t lifetime); +void dao_ack_output(rpl_instance_t *, uip_ipaddr_t *, uint8_t); void uip_rpl_input(void); +/* RPL Header Option */ +int rpl_verify_header(int uip_ext_opt_offset); +void rpl_update_header_empty(); +int rpl_update_header_final(uip_ipaddr_t *addr); + /* RPL logic functions. */ -void rpl_join_dag(rpl_dag_t *); -void rpl_local_repair(rpl_dag_t *dag); -int rpl_set_default_route(rpl_dag_t *dag, uip_ipaddr_t *from); +void rpl_join_dag(uip_ipaddr_t *from, rpl_dio_t *dio); +void rpl_join_instance(uip_ipaddr_t *from, rpl_dio_t *dio); +void rpl_local_repair(rpl_instance_t *instance); void rpl_process_dio(uip_ipaddr_t *, rpl_dio_t *); -int rpl_process_parent_event(rpl_dag_t *, rpl_parent_t *); +int rpl_process_parent_event(rpl_instance_t *, rpl_parent_t *); /* DAG object management. */ -rpl_dag_t *rpl_alloc_dag(uint8_t); -void rpl_free_dag(rpl_dag_t *); +rpl_dag_t *rpl_alloc_dodag(uint8_t, uip_ipaddr_t *); +rpl_instance_t *rpl_alloc_instance(uint8_t); +void rpl_free_dodag(rpl_dag_t *); +void rpl_free_instance(rpl_instance_t *); /* DAG parent management function. */ rpl_parent_t *rpl_add_parent(rpl_dag_t *, rpl_dio_t *dio, uip_ipaddr_t *); rpl_parent_t *rpl_find_parent(rpl_dag_t *, uip_ipaddr_t *); -int rpl_remove_parent(rpl_dag_t *, rpl_parent_t *); +rpl_parent_t * rpl_find_parent_any_dag(rpl_instance_t *instance, uip_ipaddr_t *addr); +rpl_dag_t * rpl_find_parent_dag(rpl_instance_t *instance, uip_ipaddr_t *addr); +void rpl_nullify_parent(rpl_dag_t *, rpl_parent_t *); +void rpl_remove_parent(rpl_dag_t *, rpl_parent_t *); +void rpl_move_parent(rpl_dag_t *dag_src, rpl_dag_t *dag_dst, rpl_parent_t *parent); rpl_parent_t *rpl_select_parent(rpl_dag_t *dag); +rpl_dag_t *rpl_select_dodag(rpl_instance_t *instance,rpl_parent_t *parent); void rpl_recalculate_ranks(void); /* RPL routing table functions. */ void rpl_remove_routes(rpl_dag_t *dag); +void rpl_remove_routes_by_nexthop(uip_ipaddr_t *nexthop, rpl_dag_t *dag); uip_ds6_route_t *rpl_add_route(rpl_dag_t *dag, uip_ipaddr_t *prefix, int prefix_len, uip_ipaddr_t *next_hop); void rpl_purge_routes(void); @@ -275,8 +292,8 @@ void rpl_purge_routes(void); rpl_of_t *rpl_find_of(rpl_ocp_t); /* Timer functions. */ -void rpl_schedule_dao(rpl_dag_t *); -void rpl_reset_dio_timer(rpl_dag_t *, uint8_t); +void rpl_schedule_dao(rpl_instance_t *); +void rpl_reset_dio_timer(rpl_instance_t *, uint8_t); void rpl_reset_periodic_timer(void); /* Route poisoning. */ diff --git a/core/net/rpl/rpl-timers.c b/core/net/rpl/rpl-timers.c index dbb7d2392..c86618f3c 100644 --- a/core/net/rpl/rpl-timers.c +++ b/core/net/rpl/rpl-timers.c @@ -51,7 +51,7 @@ static struct ctimer periodic_timer; static void handle_periodic_timer(void *ptr); -static void new_dio_interval(rpl_dag_t *dag); +static void new_dio_interval(rpl_instance_t *instance); static void handle_dio_timer(void *ptr); static uint16_t next_dis; @@ -69,7 +69,7 @@ handle_periodic_timer(void *ptr) /* handle DIS */ #ifdef RPL_DIS_SEND next_dis++; - if(rpl_get_dag(RPL_ANY_INSTANCE) == NULL && next_dis >= RPL_DIS_INTERVAL) { + if(rpl_get_any_dag() == NULL && next_dis >= RPL_DIS_INTERVAL) { next_dis = 0; dis_output(NULL); } @@ -78,17 +78,17 @@ handle_periodic_timer(void *ptr) } /************************************************************************/ static void -new_dio_interval(rpl_dag_t *dag) +new_dio_interval(rpl_instance_t *instance) { uint32_t time; /* TODO: too small timer intervals for many cases */ - time = 1UL << dag->dio_intcurrent; + time = 1UL << instance->dio_intcurrent; /* Convert from milliseconds to CLOCK_TICKS. */ time = (time * CLOCK_SECOND) / 1000; - dag->dio_next_delay = time; + instance->dio_next_delay = time; /* random number between I/2 and I */ time = time >> 1; @@ -99,36 +99,36 @@ new_dio_interval(rpl_dag_t *dag) * operate efficiently. Therefore we need to calculate the delay between * the randomized time and the start time of the next interval. */ - dag->dio_next_delay -= time; - dag->dio_send = 1; + instance->dio_next_delay -= time; + instance->dio_send = 1; #if RPL_CONF_STATS /* keep some stats */ - dag->dio_totint++; - dag->dio_totrecv += dag->dio_counter; + instance->dio_totint++; + instance->dio_totrecv += instance->dio_counter; ANNOTATE("#A rank=%u.%u(%u),stats=%d %d %d %d,color=%s\n", - DAG_RANK(dag->rank, dag), - (10 * (dag->rank % dag->min_hoprankinc)) / dag->min_hoprankinc, - dag->version, - dag->dio_totint, dag->dio_totsend, - dag->dio_totrecv,dag->dio_intcurrent, - dag->rank == ROOT_RANK(dag) ? "BLUE" : "ORANGE"); + DAG_RANK(instance->current_dag->rank, instance), + (10 * (instance->current_dag->rank % instance->min_hoprankinc)) / instance->min_hoprankinc, + instance->current_dag->version, + instance->dio_totint, instance->dio_totsend, + instance->dio_totrecv,instance->dio_intcurrent, + instance->current_dag->rank == ROOT_RANK(instance) ? "BLUE" : "ORANGE"); #endif /* RPL_CONF_STATS */ /* reset the redundancy counter */ - dag->dio_counter = 0; + instance->dio_counter = 0; /* schedule the timer */ PRINTF("RPL: Scheduling DIO timer %lu ticks in future (Interval)\n", time); - ctimer_set(&dag->dio_timer, time, &handle_dio_timer, dag); + ctimer_set(&instance->dio_timer, time, &handle_dio_timer, instance); } /************************************************************************/ static void handle_dio_timer(void *ptr) { - rpl_dag_t *dag; + rpl_instance_t *instance; - dag = (rpl_dag_t *)ptr; + instance = (rpl_instance_t *)ptr; PRINTF("RPL: DIO Timer triggered\n"); if(!dio_send_ok) { @@ -136,33 +136,33 @@ handle_dio_timer(void *ptr) dio_send_ok = 1; } else { PRINTF("RPL: Postponing DIO transmission since link local address is not ok\n"); - ctimer_set(&dag->dio_timer, CLOCK_SECOND, &handle_dio_timer, dag); + ctimer_set(&instance->dio_timer, CLOCK_SECOND, &handle_dio_timer, instance); return; } } - if(dag->dio_send) { + if(instance->dio_send) { /* send DIO if counter is less than desired redundancy */ - if(dag->dio_counter < dag->dio_redundancy) { + if(instance->dio_counter < instance->dio_redundancy) { #if RPL_CONF_STATS - dag->dio_totsend++; + instance->dio_totsend++; #endif /* RPL_CONF_STATS */ - dio_output(dag, NULL); + dio_output(instance, NULL); } else { PRINTF("RPL: Supressing DIO transmission (%d >= %d)\n", - dag->dio_counter, dag->dio_redundancy); + instance->dio_counter, instance->dio_redundancy); } - dag->dio_send = 0; - PRINTF("RPL: Scheduling DIO timer %u ticks in future (sent)\n", - dag->dio_next_delay); - ctimer_set(&dag->dio_timer, dag->dio_next_delay, handle_dio_timer, dag); + instance->dio_send = 0; + PRINTF("RPL: Scheduling DIO timer %"PRIu32" ticks in future (sent)\n", + instance->dio_next_delay); + ctimer_set(&instance->dio_timer, instance->dio_next_delay, handle_dio_timer, instance); } else { /* check if we need to double interval */ - if(dag->dio_intcurrent < dag->dio_intmin + dag->dio_intdoubl) { - dag->dio_intcurrent++; - PRINTF("RPL: DIO Timer interval doubled %d\n", dag->dio_intcurrent); + if(instance->dio_intcurrent < instance->dio_intmin + instance->dio_intdoubl) { + instance->dio_intcurrent++; + PRINTF("RPL: DIO Timer interval doubled %d\n", instance->dio_intcurrent); } - new_dio_interval(dag); + new_dio_interval(instance); } } /************************************************************************/ @@ -173,61 +173,63 @@ rpl_reset_periodic_timer(void) ctimer_set(&periodic_timer, CLOCK_SECOND, handle_periodic_timer, NULL); } /************************************************************************/ -/* Resets the DIO timer in the DAG to its minimal interval. */ +/* Resets the DIO timer in the instance to its minimal interval. */ void -rpl_reset_dio_timer(rpl_dag_t *dag, uint8_t force) +rpl_reset_dio_timer(rpl_instance_t *instance, uint8_t force) { +#if !RPL_LEAF_ONLY /* only reset if not just reset or started */ - if(force || dag->dio_intcurrent > dag->dio_intmin) { - dag->dio_counter = 0; - dag->dio_intcurrent = dag->dio_intmin; - new_dio_interval(dag); + if(force || instance->dio_intcurrent > instance->dio_intmin) { + instance->dio_counter = 0; + instance->dio_intcurrent = instance->dio_intmin; + new_dio_interval(instance); } #if RPL_CONF_STATS rpl_stats.resets++; -#endif +#endif /* RPL_CONF_STATS */ +#endif /* RPL_LEAF_ONLY */ } /************************************************************************/ static void handle_dao_timer(void *ptr) { - rpl_dag_t *dag; + rpl_instance_t *instance; - dag = (rpl_dag_t *)ptr; + instance = (rpl_instance_t *)ptr; if (!dio_send_ok && uip_ds6_get_link_local(ADDR_PREFERRED) == NULL) { PRINTF("RPL: Postpone DAO transmission... \n"); - ctimer_set(&dag->dao_timer, CLOCK_SECOND, handle_dao_timer, dag); + ctimer_set(&instance->dao_timer, CLOCK_SECOND, handle_dao_timer, instance); return; } /* Send the DAO to the DAO parent set -- the preferred parent in our case. */ - if(dag->preferred_parent != NULL) { + if(instance->current_dag->preferred_parent != NULL) { PRINTF("RPL: handle_dao_timer - sending DAO\n"); /* Set the route lifetime to the default value. */ - dao_output(dag->preferred_parent, dag->default_lifetime); + dao_output(instance->current_dag->preferred_parent, instance->default_lifetime); } else { PRINTF("RPL: No suitable DAO parent\n"); } - ctimer_stop(&dag->dao_timer); + ctimer_stop(&instance->dao_timer); } /************************************************************************/ void -rpl_schedule_dao(rpl_dag_t *dag) +rpl_schedule_dao(rpl_instance_t *instance) { clock_time_t expiration_time; - expiration_time = etimer_expiration_time(&dag->dao_timer.etimer); + expiration_time = etimer_expiration_time(&instance->dao_timer.etimer); - if(!etimer_expired(&dag->dao_timer.etimer)) { + if(!etimer_expired(&instance->dao_timer.etimer)) { PRINTF("RPL: DAO timer already scheduled\n"); } else { expiration_time = DEFAULT_DAO_LATENCY / 2 + (random_rand() % (DEFAULT_DAO_LATENCY)); PRINTF("RPL: Scheduling DAO timer %u ticks in the future\n", (unsigned)expiration_time); - ctimer_set(&dag->dao_timer, expiration_time, - handle_dao_timer, dag); + ctimer_set(&instance->dao_timer, expiration_time, + handle_dao_timer, instance); } } /************************************************************************/ diff --git a/core/net/rpl/rpl.c b/core/net/rpl/rpl.c index 7c5e05d21..271136b62 100644 --- a/core/net/rpl/rpl.c +++ b/core/net/rpl/rpl.c @@ -57,6 +57,15 @@ rpl_stats_t rpl_stats; /************************************************************************/ extern uip_ds6_route_t uip_ds6_routing_table[UIP_DS6_ROUTE_NB]; + +#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) +#define UIP_EXT_BUF ((struct uip_ext_hdr *)&uip_buf[uip_l2_l3_hdr_len]) +#define UIP_HBHO_BUF ((struct uip_hbho_hdr *)&uip_buf[uip_l2_l3_hdr_len]) +#define UIP_HBHO_NEXT_BUF ((struct uip_ext_hdr *)&uip_buf[uip_l2_l3_hdr_len + RPL_OP_BY_OP_LEN]) +#define UIP_EXT_HDR_OPT_BUF ((struct uip_ext_hdr_opt *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) +#define UIP_EXT_HDR_OPT_PADN_BUF ((struct uip_ext_hdr_opt_padn *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) +#define UIP_EXT_HDR_OPT_RPL_BUF ((struct uip_ext_hdr_opt_rpl *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) + /************************************************************************/ void rpl_purge_routes(void) @@ -86,6 +95,23 @@ rpl_remove_routes(rpl_dag_t *dag) } } /************************************************************************/ +void +rpl_remove_routes_by_nexthop(uip_ipaddr_t *nexthop, rpl_dag_t *dag) +{ + uip_ds6_route_t *locroute; + + for(locroute = uip_ds6_routing_table; + locroute < uip_ds6_routing_table + UIP_DS6_ROUTE_NB; + locroute++) { + if(locroute->isused + && uip_ipaddr_cmp(&locroute->nexthop, nexthop) + && locroute->state.dag == dag) { + locroute->isused = 0; + } + } + ANNOTATE("#L %u 0\n",nexthop->u8[sizeof(uip_ipaddr_t) - 1]); +} +/************************************************************************/ uip_ds6_route_t * rpl_add_route(rpl_dag_t *dag, uip_ipaddr_t *prefix, int prefix_len, uip_ipaddr_t *next_hop) @@ -107,7 +133,7 @@ rpl_add_route(rpl_dag_t *dag, uip_ipaddr_t *prefix, int prefix_len, uip_ipaddr_copy(&rep->nexthop, next_hop); } rep->state.dag = dag; - rep->state.lifetime = RPL_LIFETIME(dag, dag->default_lifetime); + rep->state.lifetime = RPL_LIFETIME(dag->instance, dag->instance->default_lifetime); rep->state.learned_from = RPL_ROUTE_FROM_INTERNAL; PRINTF("RPL: Added a route to "); @@ -123,8 +149,9 @@ static void rpl_link_neighbor_callback(const rimeaddr_t *addr, int known, int etx) { uip_ipaddr_t ipaddr; - rpl_dag_t *dag; rpl_parent_t *parent; + rpl_instance_t *instance; + rpl_instance_t *end; uip_ip6addr(&ipaddr, 0xfe80, 0, 0, 0, 0, 0, 0, 0); uip_ds6_set_addr_iid(&ipaddr, (uip_lladdr_t *)addr); @@ -132,66 +159,55 @@ rpl_link_neighbor_callback(const rimeaddr_t *addr, int known, int etx) PRINT6ADDR(&ipaddr); PRINTF(" is %sknown. ETX = %u\n", known ? "" : "no longer ", NEIGHBOR_INFO_FIX2ETX(etx)); - dag = rpl_get_dag(RPL_DEFAULT_INSTANCE); - if(dag == NULL) { - return; - } + for( instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES; instance < end; ++instance) { + if ( instance->used == 1 ) { + parent = rpl_find_parent_any_dag(instance, &ipaddr); + if(!(parent == NULL)) { + /* Trigger DAG rank recalculation. */ + parent->updated = 1; + parent->link_metric = etx; - parent = rpl_find_parent(dag, &ipaddr); - if(parent == NULL) { - if(!known) { - PRINTF("RPL: Deleting routes installed by DAOs received from "); - PRINT6ADDR(&ipaddr); - PRINTF("\n"); - uip_ds6_route_rm_by_nexthop(&ipaddr); + if(instance->of->parent_state_callback != NULL) { + instance->of->parent_state_callback(parent, known, etx); + } + if(!known) { + PRINTF("RPL: Removing parent "); + PRINT6ADDR(&parent->addr); + PRINTF(" in instance %u because of bad connectivity (ETX %d)\n", instance->instance_id, etx); + parent->rank = INFINITE_RANK; + } + } } - return; } - /* Trigger DAG rank recalculation. */ - parent->updated = 1; - - parent->link_metric = etx; - - if(dag->of->parent_state_callback != NULL) { - dag->of->parent_state_callback(parent, known, etx); - } - - if(!known) { - PRINTF("RPL: Removing parent "); - PRINT6ADDR(&parent->addr); - PRINTF(" because of bad connectivity (ETX %d)\n", etx); - parent->rank = INFINITE_RANK; + if (!known) { + PRINTF("RPL: Deleting routes installed by DAOs received from "); + PRINT6ADDR(&ipaddr); + PRINTF("\n"); + uip_ds6_route_rm_by_nexthop(&ipaddr); } } /************************************************************************/ void rpl_ipv6_neighbor_callback(uip_ds6_nbr_t *nbr) { - rpl_dag_t *dag; rpl_parent_t *p; - - /* This only handles one DODAG - if multiple we need to check all */ - dag = rpl_get_dag(RPL_ANY_INSTANCE); - if(dag == NULL) { - return; - } - - /* if this is our default route then clean the dag->def_route state */ - if(dag->def_route != NULL && - uip_ipaddr_cmp(&dag->def_route->ipaddr, &nbr->ipaddr)) { - dag->def_route = NULL; - } + rpl_instance_t *instance; + rpl_instance_t *end; if(!nbr->isused) { PRINTF("RPL: Removing neighbor "); PRINT6ADDR(&nbr->ipaddr); PRINTF("\n"); - p = rpl_find_parent(dag, &nbr->ipaddr); - if(p != NULL) { - p->rank = INFINITE_RANK; - /* Trigger DAG rank recalculation. */ - p->updated = 1; + for( instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES; instance < end; ++instance) { + if ( instance->used == 1 ) { + p = rpl_find_parent_any_dag(instance, &nbr->ipaddr); + if(p != NULL) { + p->rank = INFINITE_RANK; + /* Trigger DAG rank recalculation. */ + p->updated = 1; + } + } } } } @@ -201,6 +217,7 @@ rpl_init(void) { uip_ipaddr_t rplmaddr; PRINTF("RPL started\n"); + default_instance=NULL; rpl_reset_periodic_timer(); neighbor_info_subscribe(rpl_link_neighbor_callback); @@ -214,3 +231,299 @@ rpl_init(void) #endif } /************************************************************************/ +int +rpl_verify_header(int uip_ext_opt_offset) +{ + rpl_instance_t *instance; + + if (UIP_EXT_HDR_OPT_RPL_BUF->opt_len != RPL_HDR_OPT_LEN) { + PRINTF("RPL: Bad header option (wrong length) !\n"); + return 1; + } + + if (UIP_EXT_HDR_OPT_RPL_BUF->flags&RPL_HDR_OPT_FWD_ERR) { + PRINTF("RPL: Forward error !\n"); + /* We should try to repair it, not implemented for the moment */ + return 2; + } + + instance = rpl_get_instance(UIP_EXT_HDR_OPT_RPL_BUF->instance); + + if (instance == NULL) { + PRINTF("RPL : Unknown instance : %u\n",UIP_EXT_HDR_OPT_RPL_BUF->instance); + return 1; + } + + if (!instance->current_dag->joined) { + PRINTF("RPL : No dag in the instance\n"); + return 1; + } + + if (UIP_EXT_HDR_OPT_RPL_BUF->flags&RPL_HDR_OPT_DOWN) { + PRINTF("RPL: Packet going down :\n"); + if (UIP_EXT_HDR_OPT_RPL_BUF->senderrank>instance->current_dag->rank) { + PRINTF("RPL: Loop detected : Sender rank > our rank\n"); + if (UIP_EXT_HDR_OPT_RPL_BUF->flags&RPL_HDR_OPT_RANK_ERR) { + PRINTF("RPL: Loop detected !\n"); + /* We should try to repair it, not implemented for the moment */ + return 3; + } + PRINTF("RPL: Single error tolerated\n"); + UIP_EXT_HDR_OPT_RPL_BUF->flags|=RPL_HDR_OPT_RANK_ERR; + return 0; + } + } else { + PRINTF("RPL: Packet going up :"); + if (UIP_EXT_HDR_OPT_RPL_BUF->senderrankcurrent_dag->rank) { + PRINTF("RPL: Rank error : Sender rank < our rank\n"); + if (UIP_EXT_HDR_OPT_RPL_BUF->flags&RPL_HDR_OPT_RANK_ERR) { + PRINTF("RPL: Loop detected !\n"); + /* We should try to repair it, not implemented for the moment */ + return 3; + } + PRINTF("RPL: Single error tolerated\n"); + UIP_EXT_HDR_OPT_RPL_BUF->flags|=RPL_HDR_OPT_RANK_ERR; + return 0; + } + } + PRINTF("RPL: rank Ok\n"); + return 0; +} +/************************************************************************/ +void +rpl_update_header_empty(void) +{ + rpl_instance_t *instance; + int uip_ext_opt_offset; + int last_uip_ext_len; + u8_t temp_len; + + last_uip_ext_len=uip_ext_len; + uip_ext_len=0; + uip_ext_opt_offset = 2; + + PRINTF("RPL: Verifying the presence of the RPL header option\n"); + switch(UIP_IP_BUF->proto){ + case UIP_PROTO_HBHO: + if (UIP_HBHO_BUF->len != RPL_OP_BY_OP_LEN - 8) { + PRINTF("RPL: Non RPL Hop-by-hop options support not implemented\n"); + uip_ext_len=last_uip_ext_len; + return; + } + instance = rpl_get_instance(UIP_EXT_HDR_OPT_RPL_BUF->instance); + if(instance == NULL || (!instance->used) || (!instance->current_dag->joined) ) { + PRINTF("Unable to add RPL hop-by-hop extension header : incorrect instance\n"); + return; + } + break; + default: + PRINTF("RPL: No Hop-by-Hop Option found, creating it\n"); + if(uip_len + RPL_OP_BY_OP_LEN >UIP_LINK_MTU) { + PRINTF("RPL: Packet too long : impossible to add rpl Hop-by-Hop option\n"); + uip_ext_len=last_uip_ext_len; + return; + } + memmove(UIP_HBHO_NEXT_BUF,UIP_EXT_BUF,uip_len-UIP_IPH_LEN); + memset(UIP_HBHO_BUF,0,RPL_OP_BY_OP_LEN); + UIP_HBHO_BUF->next=UIP_IP_BUF->proto; + UIP_IP_BUF->proto=UIP_PROTO_HBHO; + UIP_HBHO_BUF->len=RPL_OP_BY_OP_LEN - 8; + UIP_EXT_HDR_OPT_RPL_BUF->opt_type=UIP_EXT_HDR_OPT_RPL; + UIP_EXT_HDR_OPT_RPL_BUF->opt_len=RPL_HDR_OPT_LEN; + UIP_EXT_HDR_OPT_RPL_BUF->flags=0; + UIP_EXT_HDR_OPT_RPL_BUF->instance=0; + UIP_EXT_HDR_OPT_RPL_BUF->senderrank=0; + uip_len+=RPL_OP_BY_OP_LEN; + temp_len=UIP_IP_BUF->len[1]; + UIP_IP_BUF->len[1]+=(UIP_HBHO_BUF->len + 8); + if (UIP_IP_BUF->len[1]len[0]+=1; + } + uip_ext_len=last_uip_ext_len+RPL_OP_BY_OP_LEN; + return; + } + switch (UIP_EXT_HDR_OPT_BUF->type) { + case UIP_EXT_HDR_OPT_RPL: + PRINTF("RPL: Updating RPL option\n"); + UIP_EXT_HDR_OPT_RPL_BUF->senderrank=instance->current_dag->rank; + uip_ext_len=last_uip_ext_len; + return; + default: + PRINTF("RPL: Multi Hop-by-hop options not implemented\n"); + uip_ext_len=last_uip_ext_len; + return; + } +} +/************************************************************************/ +int +rpl_update_header_final(uip_ipaddr_t *addr) +{ + int uip_ext_opt_offset; + int last_uip_ext_len; + + last_uip_ext_len=uip_ext_len; + uip_ext_len=0; + uip_ext_opt_offset = 2; + rpl_parent_t *parent; + + if (UIP_IP_BUF->proto == UIP_PROTO_HBHO){ + if (UIP_HBHO_BUF->len != RPL_OP_BY_OP_LEN - 8) { + PRINTF("RPL: Non RPL Hop-by-hop options support not implemented\n"); + uip_ext_len=last_uip_ext_len; + return 0; + } + if (UIP_EXT_HDR_OPT_BUF->type == UIP_EXT_HDR_OPT_RPL) { + if (UIP_EXT_HDR_OPT_RPL_BUF->senderrank==0) { + PRINTF("RPL: Updating RPL option\n"); + if(default_instance == NULL || (!default_instance->used) || (!default_instance->current_dag->joined) ) { + PRINTF("Unable to add RPL hop-by-hop extension header : incorrect default instance\n"); + return 1; + } + parent=rpl_find_parent(default_instance->current_dag,addr); + if (parent == NULL || (parent != parent->dag->preferred_parent)) { + UIP_EXT_HDR_OPT_RPL_BUF->flags=RPL_HDR_OPT_DOWN; + } + UIP_EXT_HDR_OPT_RPL_BUF->instance=default_instance->instance_id; + UIP_EXT_HDR_OPT_RPL_BUF->senderrank=default_instance->current_dag->rank; + uip_ext_len=last_uip_ext_len; + } + } + } + return 0; +} +/************************************************************************/ +int +rpl_add_header(rpl_instance_t *instance,int down) +{ + int uip_ext_opt_offset; + int last_uip_ext_len; + u8_t temp_len; + + last_uip_ext_len = uip_ext_len; + uip_ext_len = 0; + uip_ext_opt_offset = 2; + + if(instance == NULL || (!instance->used) || (!instance->current_dag->joined) ) { + PRINTF("Unable to add RPL hop-by-hop extension header : incorrect instance\n"); + return 0; + } + + PRINTF("RPL: Verifying the presence of the RPL header option\n"); + switch(UIP_IP_BUF->proto){ + case UIP_PROTO_HBHO: + if (UIP_HBHO_BUF->len != RPL_OP_BY_OP_LEN - 8) { + PRINTF("RPL: Non RPL Hop-by-hop options support not implemented\n"); + uip_ext_len=last_uip_ext_len; + return 0; + } + break; + default: + PRINTF("RPL: No Hop-by-Hop Option found, creating it\n"); + if(uip_len + RPL_OP_BY_OP_LEN >UIP_LINK_MTU) { + PRINTF("RPL: Packet too long : impossible to add rpl Hop-by-Hop option\n"); + uip_ext_len=last_uip_ext_len; + return 0; + } + memmove(UIP_HBHO_NEXT_BUF,UIP_EXT_BUF,uip_len-UIP_IPH_LEN); + memset(UIP_HBHO_BUF,0,RPL_OP_BY_OP_LEN); + UIP_HBHO_BUF->next=UIP_IP_BUF->proto; + UIP_IP_BUF->proto=UIP_PROTO_HBHO; + UIP_HBHO_BUF->len=RPL_OP_BY_OP_LEN - 8; + UIP_EXT_HDR_OPT_RPL_BUF->opt_type=UIP_EXT_HDR_OPT_RPL; + UIP_EXT_HDR_OPT_RPL_BUF->opt_len=RPL_HDR_OPT_LEN; + UIP_EXT_HDR_OPT_RPL_BUF->flags=RPL_HDR_OPT_DOWN&(down<instance=instance->instance_id; + UIP_EXT_HDR_OPT_RPL_BUF->senderrank=instance->current_dag->rank; + uip_len+=RPL_OP_BY_OP_LEN; + temp_len=UIP_IP_BUF->len[1]; + UIP_IP_BUF->len[1]+=(UIP_HBHO_BUF->len + 8); + if (UIP_IP_BUF->len[1]len[0]+=1; + } + uip_ext_len=last_uip_ext_len+RPL_OP_BY_OP_LEN; + return 1; + } + switch (UIP_EXT_HDR_OPT_BUF->type) { + case UIP_EXT_HDR_OPT_RPL: + PRINTF("RPL: Updating RPL option\n"); + UIP_EXT_HDR_OPT_RPL_BUF->opt_type=UIP_EXT_HDR_OPT_RPL; + UIP_EXT_HDR_OPT_RPL_BUF->opt_len=RPL_HDR_OPT_LEN; + UIP_EXT_HDR_OPT_RPL_BUF->flags=RPL_HDR_OPT_DOWN&(down<instance=instance->instance_id; + UIP_EXT_HDR_OPT_RPL_BUF->senderrank=instance->current_dag->rank; + uip_ext_len=last_uip_ext_len; + return 1; + default: + PRINTF("RPL: Multi Hop-by-hop options not implemented\n"); + uip_ext_len=last_uip_ext_len; + return 0; + } +} +/************************************************************************/ +int +rpl_add_header_root(void) +{ + return rpl_add_header(default_instance,1); +} +/************************************************************************/ +void +rpl_remove_header() +{ + int last_uip_ext_len; + u8_t temp_len; + + last_uip_ext_len=uip_ext_len; + uip_ext_len=0; + + PRINTF("RPL: Verifying the presence of the RPL header option\n"); + switch(UIP_IP_BUF->proto){ + case UIP_PROTO_HBHO: + PRINTF("RPL: Removing the present RPL header option\n"); + UIP_IP_BUF->proto=UIP_HBHO_BUF->next; + temp_len=UIP_IP_BUF->len[1]; + uip_len-=UIP_HBHO_BUF->len + 8; + UIP_IP_BUF->len[1]-=(UIP_HBHO_BUF->len + 8); + if (UIP_IP_BUF->len[1]>temp_len) { + UIP_IP_BUF->len[0]-=1; + } + memmove(UIP_EXT_BUF, UIP_HBHO_NEXT_BUF, uip_len - UIP_IPH_LEN); + break; + default: + PRINTF("RPL: No Hop-by-Hop Option found\n"); + } +} +/************************************************************************/ +u8_t +rpl_invert_header() +{ + u8_t uip_ext_opt_offset; + u8_t last_uip_ext_len; + + last_uip_ext_len=uip_ext_len; + uip_ext_len=0; + uip_ext_opt_offset = 2; + + PRINTF("RPL: Verifying the presence of the RPL header option\n"); + switch(UIP_IP_BUF->proto){ + case UIP_PROTO_HBHO: + break; + default: + PRINTF("RPL: No Hop-by-Hop Option found\n"); + uip_ext_len=last_uip_ext_len; + return 0; + } + switch (UIP_EXT_HDR_OPT_BUF->type) { + case UIP_EXT_HDR_OPT_RPL: + PRINTF("RPL: Updating RPL option (Inverting Up<->Down)\n"); + UIP_EXT_HDR_OPT_RPL_BUF->flags&=RPL_HDR_OPT_DOWN; + UIP_EXT_HDR_OPT_RPL_BUF->flags^=RPL_HDR_OPT_DOWN; + UIP_EXT_HDR_OPT_RPL_BUF->senderrank=rpl_get_instance(UIP_EXT_HDR_OPT_RPL_BUF->instance)->current_dag->rank; + uip_ext_len=last_uip_ext_len; + return RPL_OP_BY_OP_LEN; + default: + PRINTF("RPL: Multi Hop-by-hop options not implemented\n"); + uip_ext_len=last_uip_ext_len; + return 0; + } +} +/************************************************************************/ diff --git a/core/net/rpl/rpl.h b/core/net/rpl/rpl.h index bcc600b48..d8f98c780 100644 --- a/core/net/rpl/rpl.h +++ b/core/net/rpl/rpl.h @@ -75,17 +75,86 @@ /* This value decides which DAG instance we should participate in by default. */ #define RPL_DEFAULT_INSTANCE 0 -/* This value is used to access an arbitrary DAG. It will likely be - replaced when we support multiple DAGs more. */ -#define RPL_ANY_INSTANCE -1 +/* + * This value decides if this node must stay as a leaf or not + * as allowed by draft-ietf-roll-rpl-19#section-8.5 + */ +#ifdef RPL_CONF_LEAF_ONLY +#define RPL_LEAF_ONLY RPL_CONF_LEAF_ONLY +#else +#define RPL_LEAF_ONLY 0 +#endif + +/* + * Maximum of concurent rpl-instances + */ +#ifndef RPL_CONF_MAX_INSTANCES +#define RPL_MAX_INSTANCES 1 +#else +#define RPL_MAX_INSTANCES RPL_CONF_MAX_INSTANCES +#endif /* !RPL_CONF_MAX_INSTANCES */ + +/* + * Maximum of concurent dodag inside an instance + */ +#ifndef RPL_CONF_MAX_DODAG_PER_INSTANCE +#define RPL_MAX_DODAG_PER_INSTANCE 2 +#else +#define RPL_MAX_DODAG_PER_INSTANCE RPL_CONF_MAX_DODAG_PER_INSTANCE +#endif /* !RPL_CONF_MAX_DODAG_PER_INSTANCE */ + +/* + * + */ +#ifndef RPL_CONF_DAO_SPECIFY_DODAG +#if RPL_MAX_DODAG_PER_INSTANCE > 1 +#define RPL_DAO_SPECIFY_DODAG 1 +#else /* RPL_MAX_DODAG_PER_INSTANCE > 1*/ +#define RPL__DAO_SPECIFY_DODAG 0 +#endif /* RPL_MAX_DODAG_PER_INSTANCE > 1 */ +#else /* RPL_CONF_DAO_SPECIFY_DODAG */ +#define RPL_DAO_SPECIFY_DODAG RPL_CONF_DAO_SPECIFY_DODAG +#endif /* RPL_CONF_DAO_SPECIFY_DODAG */ + + /*---------------------------------------------------------------------------*/ /* The amount of parents that this node has in a particular DAG. */ #define RPL_PARENT_COUNT(dag) list_length((dag)->parents) /*---------------------------------------------------------------------------*/ typedef uint16_t rpl_rank_t; -typedef uint8_t rpl_lifetime_t; typedef uint16_t rpl_ocp_t; +/*---------------------------------------------------------------------------*/ +/* Lollipop counters */ + +#define RPL_LOLLIPOP_MAX_VALUE 255 +#define RPL_LOLLIPOP_CIRCULAR_REGION 127 +#define RPL_LOLLIPOP_SEQUENCE_WINDOWS 16 +#define RPL_LOLLIPOP_INIT RPL_LOLLIPOP_MAX_VALUE - RPL_LOLLIPOP_SEQUENCE_WINDOWS + 1 +#define RPL_LOLLIPOP_INCREMENT(counter) (counter > RPL_LOLLIPOP_CIRCULAR_REGION ?\ + (counter == RPL_LOLLIPOP_MAX_VALUE ? counter=0 : ++counter):\ + (counter == RPL_LOLLIPOP_CIRCULAR_REGION ? counter=0 : ++counter)) +#define RPL_LOLLIPOP_IS_INIT(counter) (counter > RPL_LOLLIPOP_CIRCULAR_REGION) +#define RPL_LOLLIPOP_GREATER_THAN_LOCAL(A,B) (((A < B) && (RPL_LOLLIPOP_CIRCULAR_REGION + 1 - B + A < RPL_LOLLIPOP_SEQUENCE_WINDOWS)) || \ + ((A > B) && (A - B < RPL_LOLLIPOP_SEQUENCE_WINDOWS))) +#define RPL_LOLLIPOP_GREATER_THAN(A,B) ((A > RPL_LOLLIPOP_CIRCULAR_REGION )?\ + ((B > RPL_LOLLIPOP_CIRCULAR_REGION )?\ + RPL_LOLLIPOP_GREATER_THAN_LOCAL(A,B):\ + 0):\ + ((B > RPL_LOLLIPOP_CIRCULAR_REGION )?\ + 1:\ + RPL_LOLLIPOP_GREATER_THAN_LOCAL(A,B))) + +/*---------------------------------------------------------------------------*/ +/* RPL IPv6 extension header option. */ +#define RPL_HDR_OPT_LEN 4 +#define RPL_OP_BY_OP_LEN RPL_HDR_OPT_LEN+2+2 +#define RPL_HDR_OPT_DOWN 0x80 +#define RPL_HDR_OPT_DOWN_SHIFT 7 +#define RPL_HDR_OPT_RANK_ERR 0x40 +#define RPL_HDR_OPT_RANK_ERR_SHIFT 6 +#define RPL_HDR_OPT_FWD_ERR 0x20 +#define RPL_HDR_OPT_FWD_ERR_SHIFT 5 /*---------------------------------------------------------------------------*/ /* DAG Metric Container Object Types, to be confirmed by IANA. */ #define RPL_DAG_MC_NONE 0 /* Local identifier for empty MC */ @@ -139,6 +208,7 @@ struct rpl_metric_container { }; typedef struct rpl_metric_container rpl_metric_container_t; /*---------------------------------------------------------------------------*/ +struct rpl_instance; struct rpl_dag; /*---------------------------------------------------------------------------*/ struct rpl_parent { @@ -153,6 +223,35 @@ struct rpl_parent { }; typedef struct rpl_parent rpl_parent_t; /*---------------------------------------------------------------------------*/ +/* RPL DIO prefix suboption */ +struct rpl_prefix { + uip_ipaddr_t prefix; + uint32_t lifetime; + uint8_t length; + uint8_t flags; +}; +typedef struct rpl_prefix rpl_prefix_t; +/*---------------------------------------------------------------------------*/ +/* Directed Acyclic Graph */ +struct rpl_dag { + uip_ipaddr_t dag_id; + rpl_rank_t min_rank; /* should be reset per DODAG iteration! */ + uint8_t version; + uint8_t grounded; + uint8_t preference; + uint8_t used; + /* live data for the DAG */ + uint8_t joined; + rpl_parent_t *preferred_parent; + rpl_rank_t rank; + struct rpl_instance *instance; + void *parent_list; + list_t parents; + rpl_prefix_t prefix_info; +}; +typedef struct rpl_dag rpl_dag_t; +typedef struct rpl_instance rpl_instance_t; +/*---------------------------------------------------------------------------*/ /* * API for RPL objective functions (OF) * @@ -171,6 +270,10 @@ typedef struct rpl_parent rpl_parent_t; * * Compares two parents and returns the best one, according to the OF. * + * best_dag(dodag1, dodag2) + * + * Compares two dodags and returns the best one, according to the OF. + * * calculate_rank(parent, base_rank) * * Calculates a rank value using the parent rank and a base rank. @@ -188,47 +291,33 @@ struct rpl_of { void (*reset)(struct rpl_dag *); void (*parent_state_callback)(rpl_parent_t *, int, int); rpl_parent_t *(*best_parent)(rpl_parent_t *, rpl_parent_t *); + rpl_dag_t *(*best_dag)(rpl_dag_t *, rpl_dag_t *); rpl_rank_t (*calculate_rank)(rpl_parent_t *, rpl_rank_t); - void (*update_metric_container)(struct rpl_dag *); + void (*update_metric_container)( rpl_instance_t *); rpl_ocp_t ocp; }; typedef struct rpl_of rpl_of_t; /*---------------------------------------------------------------------------*/ -/* RPL DIO prefix suboption */ -struct rpl_prefix { - uip_ipaddr_t prefix; - uint32_t lifetime; - uint8_t length; - uint8_t flags; -}; -typedef struct rpl_prefix rpl_prefix_t; -/*---------------------------------------------------------------------------*/ -/* Directed Acyclic Graph */ -struct rpl_dag { +/* Instance */ +struct rpl_instance { /* DAG configuration */ rpl_metric_container_t mc; rpl_of_t *of; - uip_ipaddr_t dag_id; + uint8_t instance_id; + rpl_dag_t *current_dag; + uint8_t used; + rpl_dag_t dag_table[RPL_MAX_DODAG_PER_INSTANCE]; /* The current default router - used for routing "upwards" */ uip_ds6_defrt_t *def_route; - rpl_rank_t rank; - rpl_rank_t min_rank; /* should be reset per DODAG iteration! */ uint8_t dtsn_out; - uint8_t instance_id; - uint8_t version; - uint8_t grounded; uint8_t mop; - uint8_t preference; uint8_t dio_intdoubl; uint8_t dio_intmin; uint8_t dio_redundancy; rpl_rank_t max_rankinc; rpl_rank_t min_hoprankinc; - uint8_t used; uint8_t default_lifetime; uint16_t lifetime_unit; /* lifetime in seconds = l_u * d_l */ - /* live data for the DAG */ - uint8_t joined; uint8_t dio_intcurrent; uint8_t dio_send; /* for keeping track of which mode the timer is in */ @@ -241,19 +330,21 @@ struct rpl_dag { uint32_t dio_next_delay; /* delay for completion of dio interval */ struct ctimer dio_timer; struct ctimer dao_timer; - rpl_parent_t *preferred_parent; - void *parent_list; - list_t parents; - rpl_prefix_t prefix_info; }; -typedef struct rpl_dag rpl_dag_t; + /*---------------------------------------------------------------------------*/ /* Public RPL functions. */ void rpl_init(void); -rpl_dag_t *rpl_set_root(uip_ipaddr_t *); +rpl_dag_t *rpl_set_root(uint8_t instance_id, uip_ipaddr_t * dag_id); int rpl_set_prefix(rpl_dag_t *dag, uip_ipaddr_t *prefix, int len); -int rpl_repair_dag(rpl_dag_t *dag); -int rpl_set_default_route(rpl_dag_t *dag, uip_ipaddr_t *from); -rpl_dag_t *rpl_get_dag(int instance_id); +int rpl_repair_root(uint8_t instance_id); +int rpl_set_default_route(rpl_instance_t *instance, uip_ipaddr_t *from); +rpl_dag_t *rpl_get_any_dag(void); +rpl_dag_t *rpl_get_dodag(uint8_t instance_id,uip_ipaddr_t * dag_id); +rpl_instance_t *rpl_get_instance(uint8_t instance_id); +int rpl_add_header(rpl_instance_t *instance,int down); +int rpl_add_header_root(void); +void rpl_remove_header(void); +u8_t rpl_invert_header(void); /*---------------------------------------------------------------------------*/ #endif /* RPL_H */ diff --git a/examples/ipv6/rpl-border-router/border-router.c b/examples/ipv6/rpl-border-router/border-router.c index a7a31f48e..c3894b22f 100644 --- a/examples/ipv6/rpl-border-router/border-router.c +++ b/examples/ipv6/rpl-border-router/border-router.c @@ -227,7 +227,7 @@ PROCESS_THREAD(border_router_process, ev, data) PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); } - dag = rpl_set_root((uip_ip6addr_t *)dag_id); + dag = rpl_set_root(RPL_DEFAULT_INSTANCE,(uip_ip6addr_t *)dag_id); if(dag != NULL) { rpl_set_prefix(dag, &prefix, 64); PRINTF("created a new RPL dag\n"); @@ -245,7 +245,7 @@ PROCESS_THREAD(border_router_process, ev, data) PROCESS_YIELD(); if (ev == sensors_event && data == &button_sensor) { PRINTF("Initiating global repair\n"); - rpl_repair_dag(rpl_get_dag(RPL_ANY_INSTANCE)); + rpl_repair_root(RPL_DEFAULT_INSTANCE); } } diff --git a/examples/ipv6/rpl-collect/udp-sender.c b/examples/ipv6/rpl-collect/udp-sender.c index 6652f5f0b..0755bf1bb 100644 --- a/examples/ipv6/rpl-collect/udp-sender.c +++ b/examples/ipv6/rpl-collect/udp-sender.c @@ -71,7 +71,8 @@ collect_common_net_print(void) { rpl_dag_t *dag; int i; - dag = rpl_get_dag(RPL_ANY_INSTANCE); + /* Let's suppose we have only one instance */ + dag = rpl_get_any_dag(); if(dag->preferred_parent != NULL) { PRINTF("Preferred parent: "); PRINT6ADDR(&dag->preferred_parent->addr); @@ -128,7 +129,8 @@ collect_common_send(void) rimeaddr_copy(&parent, &rimeaddr_null); parent_etx = 0; - dag = rpl_get_dag(RPL_DEFAULT_INSTANCE); + /* Let's suppose we have only one instance */ + dag = rpl_get_any_dag(); if(dag != NULL) { preferred_parent = dag->preferred_parent; if(preferred_parent != NULL) { diff --git a/examples/ipv6/rpl-collect/udp-sink.c b/examples/ipv6/rpl-collect/udp-sink.c index 11a4f7346..b2251b4ff 100644 --- a/examples/ipv6/rpl-collect/udp-sink.c +++ b/examples/ipv6/rpl-collect/udp-sink.c @@ -151,8 +151,7 @@ PROCESS_THREAD(udp_server_process, ev, data) root_if = uip_ds6_addr_lookup(&ipaddr); if(root_if != NULL) { rpl_dag_t *dag; - rpl_set_root((uip_ip6addr_t *)&ipaddr); - dag = rpl_get_dag(RPL_ANY_INSTANCE); + dag = rpl_set_root(RPL_DEFAULT_INSTANCE,(uip_ip6addr_t *)&ipaddr); uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); rpl_set_prefix(dag, &ipaddr, 64); PRINTF("created a new RPL dag\n"); @@ -181,7 +180,7 @@ PROCESS_THREAD(udp_server_process, ev, data) tcpip_handler(); } else if (ev == sensors_event && data == &button_sensor) { PRINTF("Initiaing global repair\n"); - rpl_repair_dag(rpl_get_dag(RPL_ANY_INSTANCE)); + rpl_repair_root(RPL_DEFAULT_INSTANCE); } } diff --git a/examples/ipv6/rpl-udp/udp-server.c b/examples/ipv6/rpl-udp/udp-server.c index 2ce2a046d..36c9aa4ad 100644 --- a/examples/ipv6/rpl-udp/udp-server.c +++ b/examples/ipv6/rpl-udp/udp-server.c @@ -134,8 +134,7 @@ PROCESS_THREAD(udp_server_process, ev, data) root_if = uip_ds6_addr_lookup(&ipaddr); if(root_if != NULL) { rpl_dag_t *dag; - rpl_set_root((uip_ip6addr_t *)&ipaddr); - dag = rpl_get_dag(RPL_ANY_INSTANCE); + dag = rpl_set_root(RPL_DEFAULT_INSTANCE,(uip_ip6addr_t *)&ipaddr); uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); rpl_set_prefix(dag, &ipaddr, 64); PRINTF("created a new RPL dag\n"); @@ -164,7 +163,7 @@ PROCESS_THREAD(udp_server_process, ev, data) tcpip_handler(); } else if (ev == sensors_event && data == &button_sensor) { PRINTF("Initiaing global repair\n"); - rpl_repair_dag(rpl_get_dag(RPL_ANY_INSTANCE)); + rpl_repair_root(RPL_DEFAULT_INSTANCE); } } diff --git a/platform/avr-ravenusb/cdc_task.c b/platform/avr-ravenusb/cdc_task.c index a53b8e400..c39e6bf27 100644 --- a/platform/avr-ravenusb/cdc_task.c +++ b/platform/avr-ravenusb/cdc_task.c @@ -620,11 +620,11 @@ extern uip_ds6_netif_t uip_ds6_if; } case 'G': - PRINTF_P(PSTR("Global repair returns %d\n\r"),rpl_repair_dag(rpl_get_dag(RPL_ANY_INSTANCE))); + PRINTF_P(PSTR("Global repair returns %d\n\r"),rpl_repair_root(RPL_DEFAULT_INSTANCE)); break; case 'L': - rpl_local_repair(rpl_get_dag(RPL_ANY_INSTANCE)); + rpl_local_repair(rpl_get_any_dag()); PRINTF_P(PSTR("Local repair initiated\n\r")); break; diff --git a/platform/avr-ravenusb/contiki-raven-main.c b/platform/avr-ravenusb/contiki-raven-main.c index 9884a13da..f949765be 100644 --- a/platform/avr-ravenusb/contiki-raven-main.c +++ b/platform/avr-ravenusb/contiki-raven-main.c @@ -164,7 +164,7 @@ PROCESS_THREAD(border_router_process, ev, data) { rpl_dag_t *dag; char buf[sizeof(dag_id)]; memcpy_P(buf,dag_id,sizeof(dag_id)); - dag = rpl_set_root((uip_ip6addr_t *)buf); + dag = rpl_set_root(RPL_DEFAULT_INSTANCE,(uip_ip6addr_t *)buf); /* Assign separate addresses to the jackdaw uip stack and the host network interface, but with the same prefix */ /* E.g. bbbb::200 to the jackdaw and bbbb::1 to the host network interface with $ip -6 address add bbbb::1/64 dev usb0 */ @@ -192,8 +192,6 @@ PROCESS_THREAD(border_router_process, ev, data) while(1) { PROCESS_YIELD(); /* Local and global dag repair can be done from the jackdaw menu */ - // rpl_set_prefix(rpl_get_dag(RPL_ANY_INSTANCE), &ipaddr, 64); - // rpl_repair_dag(rpl_get_dag(RPL_ANY_INSTANCE)); } diff --git a/platform/mb851/contiki-init-net.c b/platform/mb851/contiki-init-net.c index f40513c88..4d81f9c58 100644 --- a/platform/mb851/contiki-init-net.c +++ b/platform/mb851/contiki-init-net.c @@ -120,7 +120,7 @@ void set_net_address(void) print_addresses(); #if RPL_BORDER_ROUTER - dag = rpl_set_root(&ipaddr); + dag = rpl_set_root(RPL_DEFAULT_INSTANCE,&ipaddr); if(dag != NULL) { PRINTF("This node is setted as root of a DAG.\r\n"); } @@ -133,4 +133,4 @@ void set_net_address(void) #endif /* FIXED_GLOBAL_ADDRESS */ -#endif /* UIP_CONF_IPV6 */ \ No newline at end of file +#endif /* UIP_CONF_IPV6 */ From f4b804ed9fce1d9876dee03869c218c1279de7a2 Mon Sep 17 00:00:00 2001 From: Vincent Brillault Date: Mon, 11 Jul 2011 16:53:02 +0200 Subject: [PATCH 05/25] =?UTF-8?q?Add=20support=20of=20RPL=20Option=20(http?= =?UTF-8?q?://tools.ietf.org/html/draft-ietf-6man-rpl-option-03):=20-=20Au?= =?UTF-8?q?to-insersion=20when=20forwarding=20messages=20-=20Delete=20mess?= =?UTF-8?q?ages=20with=202=20rank=20errors=20Not=20supported=20yet=20:=20-?= =?UTF-8?q?=20Routing=20depending=20on=20InstanceID=20-=20DAO=20inconsiste?= =?UTF-8?q?ncy=20loop=20recovery=20-=20Full=20UDP=20or=20TCP=20support=20(?= =?UTF-8?q?Bugs=20in=20=C2=B5IPv6)=20-=20Real=20Option=20Type=20(TBD=20by?= =?UTF-8?q?=20IANA)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/net/tcpip.c | 9 +++- core/net/uip-icmp6.c | 115 +++++++++++++++++++++++++++++++------------ core/net/uip.h | 15 ++++++ core/net/uip6.c | 52 ++++++++++++++++++- 4 files changed, 157 insertions(+), 34 deletions(-) diff --git a/core/net/tcpip.c b/core/net/tcpip.c index bdb68fd4d..52386e0a3 100644 --- a/core/net/tcpip.c +++ b/core/net/tcpip.c @@ -80,7 +80,8 @@ extern struct uip_fallback_interface UIP_FALLBACK_INTERFACE; #endif #if UIP_CONF_IPV6_RPL void rpl_init(void); -#endif +int rpl_update_header_final(uip_ipaddr_t *addr); +#endif /* UIP_CONF_IPV6_RPL */ process_event_t tcpip_event; #if UIP_CONF_ICMP6 process_event_t tcpip_icmp6_event; @@ -590,6 +591,12 @@ tcpip_ipv6_output(void) } } /* end of next hop determination */ +#if UIP_CONF_IPV6_RPL + if (rpl_update_header_final(nexthop)) { + uip_len = 0; + return; + } +#endif /* UIP_CONF_IPV6_RPL */ if((nbr = uip_ds6_nbr_lookup(nexthop)) == NULL) { // printf("add1 %d\n", nexthop->u8[15]); if((nbr = uip_ds6_nbr_add(nexthop, NULL, 0, NBR_INCOMPLETE)) == NULL) { diff --git a/core/net/uip-icmp6.c b/core/net/uip-icmp6.c index 3bb554461..fb2016b23 100644 --- a/core/net/uip-icmp6.c +++ b/core/net/uip-icmp6.c @@ -60,14 +60,25 @@ #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) #define UIP_ICMP_BUF ((struct uip_icmp_hdr *)&uip_buf[uip_l2_l3_hdr_len]) #define UIP_ICMP6_ERROR_BUF ((struct uip_icmp6_error *)&uip_buf[uip_l2_l3_icmp_hdr_len]) +#if UIP_CONF_IPV6_RPL +#define UIP_EXT_BUF ((struct uip_ext_hdr *)&uip_buf[uip_l2_l3_hdr_len]) +#define UIP_FIRST_EXT_BUF ((struct uip_ext_hdr *)&uip_buf[UIP_LLIPH_LEN]) +#endif /* UIP_CONF_IPV6_RPL */ /** \brief temporary IP address */ static uip_ipaddr_t tmp_ipaddr; +#if UIP_CONF_IPV6_RPL +int rpl_invert_header(void); +#endif /* UIP_CONF_IPV6_RPL */ + /*---------------------------------------------------------------------------*/ void uip_icmp6_echo_request_input(void) { +#if UIP_CONF_IPV6_RPL + u8_t temp_ext_len; +#endif /* UIP_CONF_IPV6_RPL */ /* * we send an echo reply. It is trivial if there was no extension * headers in the request otherwise we need to remove the extension @@ -78,7 +89,7 @@ uip_icmp6_echo_request_input(void) PRINTF("to"); PRINT6ADDR(&UIP_IP_BUF->destipaddr); PRINTF("\n"); - + /* IP header */ UIP_IP_BUF->ttl = uip_ds6_if.cur_hop_limit; @@ -92,30 +103,54 @@ uip_icmp6_echo_request_input(void) } if(uip_ext_len > 0) { - /* If there were extension headers*/ - UIP_IP_BUF->proto = UIP_PROTO_ICMP6; - uip_len -= uip_ext_len; - UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); - UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); - /* move the echo request payload (starting after the icmp header) - * to the new location in the reply. - * The shift is equal to the length of the extension headers present - * Note: UIP_ICMP_BUF still points to the echo request at this stage - */ - memmove((uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN - uip_ext_len, - (uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN, - (uip_len - UIP_IPH_LEN - UIP_ICMPH_LEN)); +#if UIP_CONF_IPV6_RPL + if ((temp_ext_len=rpl_invert_header())) { + /* If there were other extension headers*/ + UIP_FIRST_EXT_BUF->next = UIP_PROTO_ICMP6; + if (uip_ext_len != temp_ext_len) { + uip_len -= (uip_ext_len - temp_ext_len); + UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); + UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); + /* move the echo request payload (starting after the icmp header) + * to the new location in the reply. + * The shift is equal to the length of the remaining extension headers present + * Note: UIP_ICMP_BUF still points to the echo request at this stage + */ + memmove((uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN - (uip_ext_len - temp_ext_len), + (uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN, + (uip_len - UIP_IPH_LEN - temp_ext_len - UIP_ICMPH_LEN)); + } + uip_ext_len=temp_ext_len; + } else { +#endif /* UIP_CONF_IPV6_RPL */ + /* If there were extension headers*/ + UIP_IP_BUF->proto = UIP_PROTO_ICMP6; + uip_len -= uip_ext_len; + UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); + UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); + /* move the echo request payload (starting after the icmp header) + * to the new location in the reply. + * The shift is equal to the length of the extension headers present + * Note: UIP_ICMP_BUF still points to the echo request at this stage + */ + memmove((uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN - uip_ext_len, + (uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN, + (uip_len - UIP_IPH_LEN - UIP_ICMPH_LEN)); + uip_ext_len = 0; +#if UIP_CONF_IPV6_RPL + } +#endif /* UIP_CONF_IPV6_RPL */ } /* Below is important for the correctness of UIP_ICMP_BUF and the * checksum */ - uip_ext_len = 0; + /* Note: now UIP_ICMP_BUF points to the beginning of the echo reply */ UIP_ICMP_BUF->type = ICMP6_ECHO_REPLY; UIP_ICMP_BUF->icode = 0; UIP_ICMP_BUF->icmpchksum = 0; UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum(); - + PRINTF("Sending Echo Reply to"); PRINT6ADDR(&UIP_IP_BUF->destipaddr); PRINTF("from"); @@ -127,29 +162,45 @@ uip_icmp6_echo_request_input(void) /*---------------------------------------------------------------------------*/ void uip_icmp6_error_output(u8_t type, u8_t code, u32_t param) { - uip_ext_len = 0; /* check if originating packet is not an ICMP error*/ - if(UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type < 128){ - uip_len = 0; - return; + if (uip_ext_len) { + if(UIP_EXT_BUF->next == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type < 128){ + uip_len = 0; + return; + } + } else { + if(UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type < 128){ + uip_len = 0; + return; + } } - /* remember data of original packet before shifting */ - uip_ipaddr_copy(&tmp_ipaddr, &UIP_IP_BUF->destipaddr); - - uip_len += UIP_IPICMPH_LEN + UIP_ICMP6_ERROR_LEN; - - if(uip_len > UIP_LINK_MTU) - uip_len = UIP_LINK_MTU; +#if UIP_CONF_IPV6_RPL + uip_ext_len = rpl_invert_header(); +#else /* UIP_CONF_IPV6_RPL */ + uip_ext_len = 0; +#endif /* UIP_CONF_IPV6_RPL */ - memmove((uint8_t *)UIP_ICMP6_ERROR_BUF + UIP_ICMP6_ERROR_LEN, - (void *)UIP_IP_BUF, uip_len - UIP_IPICMPH_LEN - UIP_ICMP6_ERROR_LEN); + /* remember data of original packet before shifting */ + uip_ipaddr_copy(&tmp_ipaddr, &UIP_IP_BUF->destipaddr); + + uip_len += UIP_IPICMPH_LEN + UIP_ICMP6_ERROR_LEN; + + if(uip_len > UIP_LINK_MTU) + uip_len = UIP_LINK_MTU; + + memmove((uint8_t *)UIP_ICMP6_ERROR_BUF + uip_ext_len + UIP_ICMP6_ERROR_LEN, + (void *)UIP_IP_BUF, uip_len - UIP_IPICMPH_LEN - uip_ext_len - UIP_ICMP6_ERROR_LEN); UIP_IP_BUF->vtc = 0x60; UIP_IP_BUF->tcflow = 0; UIP_IP_BUF->flow = 0; - UIP_IP_BUF->proto = UIP_PROTO_ICMP6; + if (uip_ext_len) { + UIP_FIRST_EXT_BUF->next = UIP_PROTO_ICMP6; + } else { + UIP_IP_BUF->proto = UIP_PROTO_ICMP6; + } UIP_IP_BUF->ttl = uip_ds6_if.cur_hop_limit; /* the source should not be unspecified nor multicast, the check for @@ -158,7 +209,7 @@ uip_icmp6_error_output(u8_t type, u8_t code, u32_t param) { uip_len = 0; return; } - + uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &UIP_IP_BUF->srcipaddr); if(uip_is_addr_mcast(&tmp_ipaddr)){ @@ -176,7 +227,7 @@ uip_icmp6_error_output(u8_t type, u8_t code, u32_t param) { uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, &tmp_ipaddr); #endif } - + UIP_ICMP_BUF->type = type; UIP_ICMP_BUF->icode = code; UIP_ICMP6_ERROR_BUF->param = uip_htonl(param); diff --git a/core/net/uip.h b/core/net/uip.h index f04ebd0d9..d9bd88855 100644 --- a/core/net/uip.h +++ b/core/net/uip.h @@ -1770,6 +1770,17 @@ typedef struct uip_ext_hdr_opt_padn { u8_t opt_len; } uip_ext_hdr_opt_padn; +#if UIP_CONF_IPV6_RPL +/* RPL option */ +typedef struct uip_ext_hdr_opt_rpl { + u8_t opt_type; + u8_t opt_len; + u8_t flags; + u8_t instance; + u16_t senderrank; +} uip_ext_hdr_opt_rpl; +#endif /* UIP_CONF_IPV6_RPL */ + /* TCP header */ struct uip_tcp_hdr { u16_t srcport; @@ -1840,6 +1851,10 @@ struct uip_udp_hdr { /** \brief Destination and Hop By Hop extension headers option types */ #define UIP_EXT_HDR_OPT_PAD1 0 #define UIP_EXT_HDR_OPT_PADN 1 +#if UIP_CONF_IPV6_RPL +#define UIP_EXT_HDR_OPT_RPL 0x63 +#endif /* UIP_CONF_IPV6_RPL */ + /** @} */ /** @{ */ diff --git a/core/net/uip6.c b/core/net/uip6.c index 1ae674b3b..2c74d6e9a 100644 --- a/core/net/uip6.c +++ b/core/net/uip6.c @@ -96,6 +96,8 @@ #if UIP_CONF_IPV6_RPL void uip_rpl_input(void); +void rpl_update_header_empty(void); +int rpl_verify_header(int uip_ext_opt_offset); #endif /* UIP_CONF_IPV6_RPL */ #if UIP_LOGGING == 1 @@ -163,6 +165,9 @@ u8_t uip_ext_opt_offset = 0; #define UIP_DESTO_BUF ((struct uip_desto_hdr *)&uip_buf[uip_l2_l3_hdr_len]) #define UIP_EXT_HDR_OPT_BUF ((struct uip_ext_hdr_opt *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) #define UIP_EXT_HDR_OPT_PADN_BUF ((struct uip_ext_hdr_opt_padn *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) +#if UIP_CONF_IPV6_RPL +#define UIP_EXT_HDR_OPT_RPL_BUF ((struct uip_ext_hdr_opt_rpl *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) +#endif /* UIP_CONF_IPV6_RPL */ #define UIP_ICMP6_ERROR_BUF ((struct uip_icmp6_error *)&uip_buf[uip_l2_l3_icmp_hdr_len]) /** @} */ /** \name Buffer variables @@ -827,6 +832,16 @@ ext_hdr_options_process() { PRINTF("Processing PADN option\n"); uip_ext_opt_offset += UIP_EXT_HDR_OPT_PADN_BUF->opt_len + 2; break; +#if UIP_CONF_IPV6_RPL + case UIP_EXT_HDR_OPT_RPL: + PRINTF("Processing RPL option\n"); + if (rpl_verify_header(uip_ext_opt_offset)) { + PRINTF("RPL Option Error : Dropping Packet"); + return 1; + } + uip_ext_opt_offset += (UIP_EXT_HDR_OPT_RPL_BUF->opt_len) + 2; + return 0; +#endif /* UIP_CONF_IPV6_RPL */ default: /* * check the two highest order bits of the option @@ -1078,6 +1093,35 @@ uip_process(u8_t flag) } #if UIP_CONF_ROUTER + /* + * Next header field processing. In IPv6, we can have extension headers, + * if present, the Hop-by-Hop Option must be processed before forwarding + * the packet. + */ + uip_next_hdr = &UIP_IP_BUF->proto; + uip_ext_len = 0; + uip_ext_bitmap = 0; + if (*uip_next_hdr == UIP_PROTO_HBHO) { +#if UIP_CONF_IPV6_CHECKS + uip_ext_bitmap |= UIP_EXT_HDR_BITMAP_HBHO; +#endif /*UIP_CONF_IPV6_CHECKS*/ + switch(ext_hdr_options_process()) { + case 0: + /*continue*/ + uip_next_hdr = &UIP_EXT_BUF->next; + uip_ext_len += (UIP_EXT_BUF->len << 3) + 8; + break; + case 1: + /*silently discard*/ + goto drop; + case 2: + /* send icmp error message (created in ext_hdr_options_process) + * and discard*/ + goto send; + } + } + + /* TBD Some Parameter problem messages */ if(!uip_ds6_is_my_addr(&UIP_IP_BUF->destipaddr) && !uip_ds6_is_my_maddr(&UIP_IP_BUF->destipaddr)) { @@ -1101,6 +1145,11 @@ uip_process(u8_t flag) UIP_STAT(++uip_stat.ip.drop); goto send; } + +#if UIP_CONF_IPV6_RPL + rpl_update_header_empty(); +#endif /* UIP_CONF_IPV6_RPL */ + UIP_IP_BUF->ttl = UIP_IP_BUF->ttl - 1; PRINTF("Forwarding packet to "); PRINT6ADDR(&UIP_IP_BUF->destipaddr); @@ -1131,7 +1180,6 @@ uip_process(u8_t flag) UIP_STAT(++uip_stat.ip.drop); goto drop; } -#endif /* UIP_CONF_ROUTER */ /* * Next header field processing. In IPv6, we can have extension headers, @@ -1140,6 +1188,8 @@ uip_process(u8_t flag) uip_next_hdr = &UIP_IP_BUF->proto; uip_ext_len = 0; uip_ext_bitmap = 0; +#endif /* UIP_CONF_ROUTER */ + while(1) { switch(*uip_next_hdr){ #if UIP_TCP From 286cf002bcd2b7110b8ca8278731091bd2969309 Mon Sep 17 00:00:00 2001 From: Vincent Brillault Date: Mon, 11 Jul 2011 16:53:36 +0200 Subject: [PATCH 06/25] Clean nd6 debug output (use uip-debug instead of local code) --- core/net/uip-nd6.c | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/core/net/uip-nd6.c b/core/net/uip-nd6.c index f49fb9ed7..13b650064 100644 --- a/core/net/uip-nd6.c +++ b/core/net/uip-nd6.c @@ -76,16 +76,7 @@ /*------------------------------------------------------------------*/ #define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINT6ADDR(addr) PRINTF(" %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x ", ((u8_t *)addr)[0], ((u8_t *)addr)[1], ((u8_t *)addr)[2], ((u8_t *)addr)[3], ((u8_t *)addr)[4], ((u8_t *)addr)[5], ((u8_t *)addr)[6], ((u8_t *)addr)[7], ((u8_t *)addr)[8], ((u8_t *)addr)[9], ((u8_t *)addr)[10], ((u8_t *)addr)[11], ((u8_t *)addr)[12], ((u8_t *)addr)[13], ((u8_t *)addr)[14], ((u8_t *)addr)[15]) -#define PRINTLLADDR(lladdr) PRINTF(" %02x:%02x:%02x:%02x:%02x:%02x ",lladdr->addr[0], lladdr->addr[1], lladdr->addr[2], lladdr->addr[3],lladdr->addr[4], lladdr->addr[5]) -#else -#define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) -#endif +#include "net/uip-debug.h" #if UIP_LOGGING #include @@ -154,11 +145,11 @@ create_llao(uint8_t *llao, uint8_t type) { void uip_nd6_ns_input(void) { - PRINTF("Received NS from"); + PRINTF("Received NS from "); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); - PRINTF("to"); + PRINTF(" to "); PRINT6ADDR(&UIP_IP_BUF->destipaddr); - PRINTF("with target address"); + PRINTF(" with target address"); PRINT6ADDR((uip_ipaddr_t *) (&UIP_ND6_NS_BUF->tgtipaddr)); PRINTF("\n"); UIP_STAT(++uip_stat.nd6.recv); @@ -313,11 +304,11 @@ create_na: UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_NA_LEN + UIP_ND6_OPT_LLAO_LEN; UIP_STAT(++uip_stat.nd6.sent); - PRINTF("Sending NA to"); + PRINTF("Sending NA to "); PRINT6ADDR(&UIP_IP_BUF->destipaddr); - PRINTF("from"); + PRINTF(" from "); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); - PRINTF("with target address"); + PRINTF(" with target address "); PRINT6ADDR(&UIP_ND6_NA_BUF->tgtipaddr); PRINTF("\n"); return; From 4f76130a7710f8eaacdef316903aa2c92656fd92 Mon Sep 17 00:00:00 2001 From: Vincent Brillault Date: Wed, 13 Jul 2011 10:28:56 +0200 Subject: [PATCH 07/25] Changed Instance structure in order to decrease memory waste. --- core/net/rpl/rpl.h | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/core/net/rpl/rpl.h b/core/net/rpl/rpl.h index d8f98c780..b04e3c8ec 100644 --- a/core/net/rpl/rpl.h +++ b/core/net/rpl/rpl.h @@ -303,25 +303,24 @@ struct rpl_instance { /* DAG configuration */ rpl_metric_container_t mc; rpl_of_t *of; - uint8_t instance_id; rpl_dag_t *current_dag; - uint8_t used; rpl_dag_t dag_table[RPL_MAX_DODAG_PER_INSTANCE]; /* The current default router - used for routing "upwards" */ uip_ds6_defrt_t *def_route; + uint8_t instance_id; + uint8_t used; uint8_t dtsn_out; uint8_t mop; uint8_t dio_intdoubl; uint8_t dio_intmin; uint8_t dio_redundancy; + uint8_t default_lifetime; + uint8_t dio_intcurrent; + uint8_t dio_send; /* for keeping track of which mode the timer is in */ + uint8_t dio_counter; rpl_rank_t max_rankinc; rpl_rank_t min_hoprankinc; - uint8_t default_lifetime; uint16_t lifetime_unit; /* lifetime in seconds = l_u * d_l */ - uint8_t dio_intcurrent; - uint8_t dio_send; /* for keeping track of which mode the timer is in -*/ - uint8_t dio_counter; #if RPL_CONF_STATS uint16_t dio_totint; uint16_t dio_totsend; From d8d9494168e779398e128c99ce9f59f4d3b17d2c Mon Sep 17 00:00:00 2001 From: Vincent Brillault Date: Wed, 13 Jul 2011 10:31:22 +0200 Subject: [PATCH 08/25] uip : When creating a route with a "state" field, clear it (It's possible that the process responsible for this creation doesn't handle the state field) --- core/net/uip-ds6.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/net/uip-ds6.c b/core/net/uip-ds6.c index 6f11a5297..b30461bac 100644 --- a/core/net/uip-ds6.c +++ b/core/net/uip-ds6.c @@ -784,6 +784,10 @@ uip_ds6_route_add(uip_ipaddr_t *ipaddr, uint8_t length, uip_ipaddr_t *nexthop, uip_ipaddr_copy(&(locroute->nexthop), nexthop); locroute->metric = metric; +#ifdef UIP_DS6_ROUTE_STATE_TYPE + memset (&(locroute->state),0,sizeof(UIP_DS6_ROUTE_STATE_TYPE)); +#endif + PRINTF("DS6: adding route: "); PRINT6ADDR(ipaddr); PRINTF(" via "); From d7c114dbd87201dc2320764e1011b962eadd2749 Mon Sep 17 00:00:00 2001 From: Vincent Brillault Date: Wed, 13 Jul 2011 10:42:59 +0200 Subject: [PATCH 09/25] RPL prefix handling fix : Change IP on DODAG change, delete IP when leaving DODAG. --- core/net/rpl/rpl-dag.c | 67 +++++++++++++++++++++++++++++++++++------- 1 file changed, 57 insertions(+), 10 deletions(-) diff --git a/core/net/rpl/rpl-dag.c b/core/net/rpl/rpl-dag.c index 55dbc83b8..927272a70 100644 --- a/core/net/rpl/rpl-dag.c +++ b/core/net/rpl/rpl-dag.c @@ -260,6 +260,48 @@ rpl_repair_root(uint8_t instance_id) return 0; } /************************************************************************/ +inline void +allocate_ip_from_prefix(uip_ipaddr_t *ipaddr, rpl_prefix_t *prefix) +{ + memset(ipaddr, 0, sizeof(uip_ipaddr_t)); + memcpy(ipaddr, &prefix->prefix, prefix->length); + uip_ds6_set_addr_iid(ipaddr, &uip_lladdr); +} + +void +rpl_check_prefix(rpl_prefix_t *last_prefix, rpl_prefix_t *new_prefix) +{ + uip_ipaddr_t ipaddr; + uip_ds6_addr_t *rep; + uint8_t flag = 0; + + if((last_prefix != NULL) + && ((new_prefix == NULL) + || (flag = (last_prefix->length != new_prefix->length) + || (!uip_ipaddr_prefixcmp(&last_prefix->prefix, &new_prefix->prefix, new_prefix->length)) + || (last_prefix->flags != new_prefix->flags)))) { + allocate_ip_from_prefix(&ipaddr,last_prefix); + if((rep = uip_ds6_addr_lookup(&ipaddr)) != NULL) { + PRINTF("RPL: removing global IP address "); + PRINT6ADDR(&ipaddr); + PRINTF("\n"); + uip_ds6_addr_rm(rep); + } + } + + if(((last_prefix == NULL) + && (new_prefix != NULL)) + || flag) { + allocate_ip_from_prefix(&ipaddr,new_prefix); + if(uip_ds6_addr_lookup(&ipaddr) == NULL) { + PRINTF("RPL: adding global IP address "); + PRINT6ADDR(&ipaddr); + PRINTF("\n"); + uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); + } + } +} +/************************************************************************/ int rpl_set_prefix(rpl_dag_t *dag, uip_ipaddr_t *prefix, int len) { @@ -269,6 +311,9 @@ rpl_set_prefix(rpl_dag_t *dag, uip_ipaddr_t *prefix, int len) dag->prefix_info.length = len; dag->prefix_info.flags = UIP_ND6_RA_FLAG_AUTONOMOUS; PRINTF("RPL: Prefix set - will announce this in DIOs\n"); + /* Autoconfigure an address if this node does not already have an address + with this prefix. */ + rpl_check_prefix(NULL,&dag->prefix_info); return 1; } return 0; @@ -402,6 +447,11 @@ rpl_free_dodag(rpl_dag_t *dag) /* Remove routes installed by DAOs. */ rpl_remove_routes(dag); + /* Remove autoconfigured address */ + if((dag->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS)) { + rpl_check_prefix(&dag->prefix_info, NULL); + } + remove_parents(dag, 0); } dag->used = 0; @@ -520,6 +570,12 @@ rpl_select_dodag(rpl_instance_t * instance, rpl_parent_t *p) PRINT6ADDR(&best_dag->dag_id); PRINTF("\n"); + if(best_dag->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS) { + rpl_check_prefix(&instance->current_dag->prefix_info, &best_dag->prefix_info); + } else if(instance->current_dag->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS) { + rpl_check_prefix(&instance->current_dag->prefix_info, NULL); + } + best_dag->joined = 1; instance->current_dag->joined = 0; instance->current_dag = best_dag; @@ -759,16 +815,7 @@ rpl_join_instance(uip_ipaddr_t *from, rpl_dio_t *dio) /* Autoconfigure an address if this node does not already have an address with this prefix. */ if((dio->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS)) { - uip_ipaddr_t ipaddr; - /* assume that the prefix ends with zeros! */ - memcpy(&ipaddr, &dio->prefix_info.prefix, 16); - uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); - if(uip_ds6_addr_lookup(&ipaddr) == NULL) { - PRINTF("RPL: adding global IP address "); - PRINT6ADDR(&ipaddr); - PRINTF("\n"); - uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); - } + rpl_check_prefix(NULL, &dio->prefix_info); } dag->joined = 1; From ab049ec704b83b224d80b95e999115dad9cd18df Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Thu, 22 Sep 2011 17:22:59 +0200 Subject: [PATCH 10/25] some fixes to cut some extension headers before TCP processing --- core/net/rpl/rpl-dag.c | 5 ++- core/net/rpl/rpl-of-etx.c | 2 +- core/net/rpl/rpl.h | 2 +- core/net/tcpip.c | 9 +++++ core/net/uip.h | 5 +++ core/net/uip6.c | 74 ++++++++++++++++++++++++++------------- 6 files changed, 70 insertions(+), 27 deletions(-) diff --git a/core/net/rpl/rpl-dag.c b/core/net/rpl/rpl-dag.c index 927272a70..10ad983cc 100644 --- a/core/net/rpl/rpl-dag.c +++ b/core/net/rpl/rpl-dag.c @@ -264,7 +264,7 @@ inline void allocate_ip_from_prefix(uip_ipaddr_t *ipaddr, rpl_prefix_t *prefix) { memset(ipaddr, 0, sizeof(uip_ipaddr_t)); - memcpy(ipaddr, &prefix->prefix, prefix->length); + memcpy(ipaddr, &prefix->prefix, (prefix->length + 7) / 8); uip_ds6_set_addr_iid(ipaddr, &uip_lladdr); } @@ -306,8 +306,11 @@ int rpl_set_prefix(rpl_dag_t *dag, uip_ipaddr_t *prefix, int len) { if(len <= 128) { + printf("** memset\n"); memset(&dag->prefix_info.prefix, 0, 16); + printf("** memcpy\n"); memcpy(&dag->prefix_info.prefix, prefix, (len + 7) / 8); + printf("** done\n"); dag->prefix_info.length = len; dag->prefix_info.flags = UIP_ND6_RA_FLAG_AUTONOMOUS; PRINTF("RPL: Prefix set - will announce this in DIOs\n"); diff --git a/core/net/rpl/rpl-of-etx.c b/core/net/rpl/rpl-of-etx.c index dfa7cfbfd..6f82c1ad3 100644 --- a/core/net/rpl/rpl-of-etx.c +++ b/core/net/rpl/rpl-of-etx.c @@ -46,7 +46,7 @@ #include "net/rpl/rpl-private.h" #include "net/neighbor-info.h" -#define DEBUG 1 +#define DEBUG DEBUG_NONE #include "net/uip-debug.h" static void reset(rpl_dag_t *); diff --git a/core/net/rpl/rpl.h b/core/net/rpl/rpl.h index b04e3c8ec..4132d429c 100644 --- a/core/net/rpl/rpl.h +++ b/core/net/rpl/rpl.h @@ -73,7 +73,7 @@ #endif /* RPL_CONF_OF */ /* This value decides which DAG instance we should participate in by default. */ -#define RPL_DEFAULT_INSTANCE 0 +#define RPL_DEFAULT_INSTANCE 0x1e /* * This value decides if this node must stay as a leaf or not diff --git a/core/net/tcpip.c b/core/net/tcpip.c index 52386e0a3..552f6ccce 100644 --- a/core/net/tcpip.c +++ b/core/net/tcpip.c @@ -579,7 +579,16 @@ tcpip_ipv6_output(void) if(locrt == NULL) { if((nexthop = uip_ds6_defrt_choose()) == NULL) { #ifdef UIP_FALLBACK_INTERFACE + printf("FALLBACK: removing ext hdrs & setting proto %d %d\n", + uip_ext_len, *((uint8_t *)UIP_IP_BUF + 40)); + if(uip_ext_len > 0) { + uint8_t proto = *((uint8_t *)UIP_IP_BUF + 40); + remove_ext_hdr(); + /* this should be copied from the ext header... */ + UIP_IP_BUF->proto = proto; + } UIP_FALLBACK_INTERFACE.output(); + #else PRINTF("tcpip_ipv6_output: Destination off-link but no route\n"); #endif diff --git a/core/net/uip.h b/core/net/uip.h index d9bd88855..8589ae715 100644 --- a/core/net/uip.h +++ b/core/net/uip.h @@ -1912,8 +1912,13 @@ struct uip_udp_hdr { */ #define uip_l2_l3_hdr_len (UIP_LLH_LEN + UIP_IPH_LEN + uip_ext_len) #define uip_l2_l3_icmp_hdr_len (UIP_LLH_LEN + UIP_IPH_LEN + uip_ext_len + UIP_ICMPH_LEN) +#define uip_l2_l3_udp_hdr_len (UIP_LLH_LEN + UIP_IPH_LEN + uip_ext_len + UIP_UDPH_LEN) +#define uip_l2_l3_tcp_hdr_len (UIP_LLH_LEN + UIP_IPH_LEN + uip_ext_len + UIP_TCPH_LEN) + #define uip_l3_hdr_len (UIP_IPH_LEN + uip_ext_len) #define uip_l3_icmp_hdr_len (UIP_IPH_LEN + uip_ext_len + UIP_ICMPH_LEN) +#define uip_l3_udp_hdr_len (UIP_IPH_LEN + uip_ext_len + UIP_UDPH_LEN) +#define uip_l3_tcp_hdr_len (UIP_IPH_LEN + uip_ext_len + UIP_TCPH_LEN) #endif /*UIP_CONF_IPV6*/ diff --git a/core/net/uip6.c b/core/net/uip6.c index 2c74d6e9a..9800c7d97 100644 --- a/core/net/uip6.c +++ b/core/net/uip6.c @@ -83,7 +83,7 @@ /* For Debug, logging, statistics */ /*---------------------------------------------------------------------------*/ -#define DEBUG 0 +#define DEBUG 1 #if DEBUG #include #define PRINTF(...) printf(__VA_ARGS__) @@ -499,7 +499,29 @@ uip_connect(uip_ipaddr_t *ripaddr, u16_t rport) return conn; } #endif /* UIP_TCP && UIP_ACTIVE_OPEN */ +/*---------------------------------------------------------------------------*/ +void +remove_ext_hdr(void) { + /* remove ext header - before TCP/UDP processing */ + int i; + if(uip_ext_len > 0) { + PRINTF("Cutting ext-header before TCP send (%d)\n", uip_ext_len); + memmove(((uint8_t *)UIP_TCP_BUF) - uip_ext_len, (uint8_t *)UIP_TCP_BUF, + uip_len - UIP_IPH_LEN - uip_ext_len); + uip_len -= uip_ext_len; + + for(i = 0; i < uip_len - UIP_IPH_LEN; i++) { + printf("%02x ", uip_buf[uip_l2_l3_hdr_len + i]); + } + printf("\n"); + + /* update the IP length */ + UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); + UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); + uip_ext_len = 0; + } +} /*---------------------------------------------------------------------------*/ #if UIP_UDP @@ -1029,7 +1051,7 @@ uip_process(u8_t flag) if(flag == UIP_UDP_TIMER) { if(uip_udp_conn->lport != 0) { uip_conn = NULL; - uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN]; + uip_sappdata = uip_appdata = &uip_buf[uip_l2_l3_udp_hdr_len]; uip_len = uip_slen = 0; uip_flags = UIP_POLL; UIP_UDP_APPCALL(); @@ -1423,8 +1445,8 @@ uip_process(u8_t flag) work. If the application sets uip_slen, it has a packet to send. */ #if UIP_UDP_CHECKSUMS - uip_len = uip_len - UIP_IPUDPH_LEN; - uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN]; + uip_len = uip_len - uip_l3_udp_hdr_len; + uip_appdata = &uip_buf[uip_l2_l3_udp_hdr_len]; if(UIP_UDP_BUF->udpchksum != 0 && uip_udpchksum() != 0xffff) { UIP_STAT(++uip_stat.udp.drop); UIP_STAT(++uip_stat.udp.chkerr); @@ -1433,7 +1455,7 @@ uip_process(u8_t flag) goto drop; } #else /* UIP_UDP_CHECKSUMS */ - uip_len = uip_len - UIP_IPUDPH_LEN; + uip_len = uip_len - uip_l3_udp_hdr_len; #endif /* UIP_UDP_CHECKSUMS */ /* Make sure that the UDP destination port number is not zero. */ @@ -1477,7 +1499,7 @@ uip_process(u8_t flag) uip_conn = NULL; uip_flags = UIP_NEWDATA; - uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN]; + uip_sappdata = uip_appdata = &uip_buf[uip_l2_l3_udp_hdr_len]; uip_slen = 0; UIP_UDP_APPCALL(); @@ -1487,7 +1509,8 @@ uip_process(u8_t flag) if(uip_slen == 0) { goto drop; } - uip_len = uip_slen + UIP_IPUDPH_LEN; + /* TODO: ext_header len here ? */ + uip_len = uip_slen + uip_l3_udp_hdr_len; /* UIP_IPUDPH_LEN; */ /* For IPv6, the IP length field does not include the IPv6 IP header length. */ @@ -1523,6 +1546,8 @@ uip_process(u8_t flag) /* TCP input processing. */ tcp_input: + remove_ext_hdr(); + UIP_STAT(++uip_stat.tcp.recv); PRINTF("Receiving TCP packet\n"); /* Start of TCP input header processing code. */ @@ -1531,13 +1556,14 @@ uip_process(u8_t flag) checksum. */ UIP_STAT(++uip_stat.tcp.drop); UIP_STAT(++uip_stat.tcp.chkerr); - UIP_LOG("tcp: bad checksum."); + PRINTF("tcp: bad checksum 0x%04x 0x%04x\n", UIP_TCP_BUF->tcpchksum, + uip_tcpchksum()); goto drop; } /* Make sure that the TCP port number is not zero. */ if(UIP_TCP_BUF->destport == 0 || UIP_TCP_BUF->srcport == 0) { - UIP_LOG("tcp: zero port."); + PRINTF("tcp: zero port."); goto drop; } @@ -1685,7 +1711,7 @@ uip_process(u8_t flag) /* Parse the TCP MSS option, if present. */ if((UIP_TCP_BUF->tcpoffset & 0xf0) > 0x50) { for(c = 0; c < ((UIP_TCP_BUF->tcpoffset >> 4) - 5) << 2 ;) { - opt = uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + c]; + opt = uip_buf[UIP_TCPIP_HLEN + uip_ext_len + UIP_LLH_LEN + c]; if(opt == TCP_OPT_END) { /* End of options. */ break; @@ -1693,10 +1719,10 @@ uip_process(u8_t flag) ++c; /* NOP option. */ } else if(opt == TCP_OPT_MSS && - uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) { + uip_buf[UIP_TCPIP_HLEN + uip_ext_len + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) { /* An MSS option with the right option length. */ - tmp16 = ((u16_t)uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) | - (u16_t)uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + 3 + c]; + tmp16 = ((u16_t)uip_buf[UIP_TCPIP_HLEN + uip_ext_len + UIP_LLH_LEN + 2 + c] << 8) | + (u16_t)uip_buf[UIP_IPTCPH_LEN + uip_ext_len + UIP_LLH_LEN + 3 + c]; uip_connr->initialmss = uip_connr->mss = tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16; @@ -1705,12 +1731,12 @@ uip_process(u8_t flag) } else { /* All other options have a length field, so that we easily can skip past them. */ - if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) { + if(uip_buf[UIP_TCPIP_HLEN + uip_ext_len + UIP_LLH_LEN + 1 + c] == 0) { /* If the length field is zero, the options are malformed and we don't process them further. */ break; } - c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c]; + c += uip_buf[UIP_TCPIP_HLEN + uip_ext_len + UIP_LLH_LEN + 1 + c]; } } } @@ -1733,7 +1759,7 @@ uip_process(u8_t flag) UIP_TCP_BUF->optdata[1] = TCP_OPT_MSS_LEN; UIP_TCP_BUF->optdata[2] = (UIP_TCP_MSS) / 256; UIP_TCP_BUF->optdata[3] = (UIP_TCP_MSS) & 255; - uip_len = UIP_IPTCPH_LEN + TCP_OPT_MSS_LEN; + uip_len = UIP_IPTCPH_LEN + TCP_OPT_MSS_LEN + uip_ext_len; UIP_TCP_BUF->tcpoffset = ((UIP_TCPH_LEN + TCP_OPT_MSS_LEN) / 4) << 4; goto tcp_send; @@ -1759,7 +1785,7 @@ uip_process(u8_t flag) /* uip_len will contain the length of the actual TCP data. This is calculated by subtracing the length of the TCP header (in c) and the length of the IP header (20 bytes). */ - uip_len = uip_len - c - UIP_IPH_LEN; + uip_len = uip_len - c - UIP_IPH_LEN - uip_ext_len; /* First, check if the sequence number of the incoming packet is what we're expecting next. If not, we send out an ACK with the @@ -1866,7 +1892,7 @@ uip_process(u8_t flag) /* Parse the TCP MSS option, if present. */ if((UIP_TCP_BUF->tcpoffset & 0xf0) > 0x50) { for(c = 0; c < ((UIP_TCP_BUF->tcpoffset >> 4) - 5) << 2 ;) { - opt = uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + c]; + opt = uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + c + uip_ext_len]; if(opt == TCP_OPT_END) { /* End of options. */ break; @@ -1874,10 +1900,10 @@ uip_process(u8_t flag) ++c; /* NOP option. */ } else if(opt == TCP_OPT_MSS && - uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) { + uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c + uip_ext_len] == TCP_OPT_MSS_LEN) { /* An MSS option with the right option length. */ - tmp16 = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) | - uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c]; + tmp16 = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c + uip_ext_len] << 8) | + uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c + uip_ext_len]; uip_connr->initialmss = uip_connr->mss = tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16; @@ -1886,12 +1912,12 @@ uip_process(u8_t flag) } else { /* All other options have a length field, so that we easily can skip past them. */ - if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) { + if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c + uip_ext_len] == 0) { /* If the length field is zero, the options are malformed and we don't process them further. */ break; } - c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c]; + c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c + uip_ext_len]; } } } @@ -2162,7 +2188,7 @@ uip_process(u8_t flag) UIP_TCP_BUF->flags = TCP_ACK; tcp_send_nodata: - uip_len = UIP_IPTCPH_LEN; + uip_len = UIP_IPTCPH_LEN; /* TODO: maybe ext_len??? */ tcp_send_noopts: UIP_TCP_BUF->tcpoffset = (UIP_TCPH_LEN / 4) << 4; From e716ce25a184f96186f530e162cab5dbb9f8fad9 Mon Sep 17 00:00:00 2001 From: Nicolas Tsiftes Date: Wed, 16 Nov 2011 08:50:01 +0100 Subject: [PATCH 11/25] DEBUG off. --- core/net/uip6.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/net/uip6.c b/core/net/uip6.c index 9800c7d97..e3b497ba6 100644 --- a/core/net/uip6.c +++ b/core/net/uip6.c @@ -83,7 +83,7 @@ /* For Debug, logging, statistics */ /*---------------------------------------------------------------------------*/ -#define DEBUG 1 +#define DEBUG 0 #if DEBUG #include #define PRINTF(...) printf(__VA_ARGS__) From 63afff543662757e8cce81d7112efe34d9f43a3c Mon Sep 17 00:00:00 2001 From: Nicolas Tsiftes Date: Wed, 16 Nov 2011 08:56:56 +0100 Subject: [PATCH 12/25] Removed debug output and fixed coding style. --- core/net/uip6.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/core/net/uip6.c b/core/net/uip6.c index e3b497ba6..772272d3e 100644 --- a/core/net/uip6.c +++ b/core/net/uip6.c @@ -501,9 +501,9 @@ uip_connect(uip_ipaddr_t *ripaddr, u16_t rport) #endif /* UIP_TCP && UIP_ACTIVE_OPEN */ /*---------------------------------------------------------------------------*/ void -remove_ext_hdr(void) { - /* remove ext header - before TCP/UDP processing */ - int i; +remove_ext_hdr(void) +{ + /* Remove ext header before TCP/UDP processing. */ if(uip_ext_len > 0) { PRINTF("Cutting ext-header before TCP send (%d)\n", uip_ext_len); memmove(((uint8_t *)UIP_TCP_BUF) - uip_ext_len, (uint8_t *)UIP_TCP_BUF, @@ -511,14 +511,9 @@ remove_ext_hdr(void) { uip_len -= uip_ext_len; - for(i = 0; i < uip_len - UIP_IPH_LEN; i++) { - printf("%02x ", uip_buf[uip_l2_l3_hdr_len + i]); - } - printf("\n"); - - /* update the IP length */ - UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); - UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); + /* Update the IP length. */ + UIP_IP_BUF->len[0] = (uip_len - UIP_IPH_LEN) >> 8; + UIP_IP_BUF->len[1] = (uip_len - UIP_IPH_LEN) & 0xff; uip_ext_len = 0; } } From ef0ce944e5c9003760a1d56da6ba99c2971c4c43 Mon Sep 17 00:00:00 2001 From: Nicolas Tsiftes Date: Wed, 16 Nov 2011 09:00:19 +0100 Subject: [PATCH 13/25] Split management of extension headers into a separate file and fixed coding style. --- core/net/rpl/rpl-ext-header.c | 362 ++++++++++++++++++++++++++++++++++ core/net/rpl/rpl-icmp6.c | 6 +- core/net/rpl/rpl.c | 310 +---------------------------- 3 files changed, 372 insertions(+), 306 deletions(-) create mode 100644 core/net/rpl/rpl-ext-header.c diff --git a/core/net/rpl/rpl-ext-header.c b/core/net/rpl/rpl-ext-header.c new file mode 100644 index 000000000..9ff8385fc --- /dev/null +++ b/core/net/rpl/rpl-ext-header.c @@ -0,0 +1,362 @@ +/** + * \addtogroup uip6 + * @{ + */ +/* + * Copyright (c) 2009, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ +/** + * \file + * Management of extension headers for ContikiRPL. + * + * \author Vincent Brillault + */ + +#include "net/uip.h" +#include "net/tcpip.h" +#include "net/uip-ds6.h" +#include "net/rpl/rpl-private.h" + +#define DEBUG DEBUG_NONE +#include "net/uip-debug.h" + +#include +#include + +/************************************************************************/ +#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) +#define UIP_EXT_BUF ((struct uip_ext_hdr *)&uip_buf[uip_l2_l3_hdr_len]) +#define UIP_HBHO_BUF ((struct uip_hbho_hdr *)&uip_buf[uip_l2_l3_hdr_len]) +#define UIP_HBHO_NEXT_BUF ((struct uip_ext_hdr *)&uip_buf[uip_l2_l3_hdr_len + RPL_OP_BY_OP_LEN]) +#define UIP_EXT_HDR_OPT_BUF ((struct uip_ext_hdr_opt *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) +#define UIP_EXT_HDR_OPT_PADN_BUF ((struct uip_ext_hdr_opt_padn *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) +#define UIP_EXT_HDR_OPT_RPL_BUF ((struct uip_ext_hdr_opt_rpl *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) +/************************************************************************/ +int +rpl_verify_header(int uip_ext_opt_offset) +{ + rpl_instance_t *instance; + + if(UIP_EXT_HDR_OPT_RPL_BUF->opt_len != RPL_HDR_OPT_LEN) { + PRINTF("RPL: Bad header option! (wrong length)\n"); + return 1; + } + + if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_FWD_ERR) { + PRINTF("RPL: Forward error!\n"); + /* We should try to repair it, not implemented for the moment */ + return 2; + } + + instance = rpl_get_instance(UIP_EXT_HDR_OPT_RPL_BUF->instance); + if(instance == NULL) { + PRINTF("RPL: Unknown instance : %u\n", + UIP_EXT_HDR_OPT_RPL_BUF->instance); + return 1; + } + + if(!instance->current_dag->joined) { + PRINTF("RPL: No DAG in the instance\n"); + return 1; + } + + if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_DOWN) { + PRINTF("RPL: Packet going down :\n"); + if(UIP_EXT_HDR_OPT_RPL_BUF->senderrank > instance->current_dag->rank) { + PRINTF("RPL: Loop detected : Sender rank > our rank\n"); + if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_RANK_ERR) { + PRINTF("RPL: Loop detected !\n"); + /* We should try to repair it, not implemented for the moment */ + return 3; + } + PRINTF("RPL: Single error tolerated\n"); + UIP_EXT_HDR_OPT_RPL_BUF->flags |= RPL_HDR_OPT_RANK_ERR; + return 0; + } + } else { + PRINTF("RPL: Packet going up :"); + if(UIP_EXT_HDR_OPT_RPL_BUF->senderrank < instance->current_dag->rank) { + PRINTF("RPL: Rank error : Sender rank < our rank\n"); + if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_RANK_ERR) { + PRINTF("RPL: Loop detected !\n"); + /* We should try to repair it, not implemented for the moment */ + return 3; + } + PRINTF("RPL: Single error tolerated\n"); + UIP_EXT_HDR_OPT_RPL_BUF->flags |= RPL_HDR_OPT_RANK_ERR; + return 0; + } + } + + PRINTF("RPL: Rank OK\n"); + + return 0; +} +/************************************************************************/ +void +rpl_update_header_empty(void) +{ + rpl_instance_t *instance; + int uip_ext_opt_offset; + int last_uip_ext_len; + u8_t temp_len; + + last_uip_ext_len = uip_ext_len; + uip_ext_len = 0; + uip_ext_opt_offset = 2; + + PRINTF("RPL: Verifying the presence of the RPL header option\n"); + switch(UIP_IP_BUF->proto) { + case UIP_PROTO_HBHO: + if(UIP_HBHO_BUF->len != RPL_OP_BY_OP_LEN - 8) { + PRINTF("RPL: Non RPL Hop-by-hop options support not implemented\n"); + uip_ext_len = last_uip_ext_len; + return; + } + instance = rpl_get_instance(UIP_EXT_HDR_OPT_RPL_BUF->instance); + if(instance == NULL || !instance->used || !instance->current_dag->joined) { + PRINTF("RPL: Unable to add hop-by-hop extension header: incorrect instance\n"); + return; + } + break; + default: + PRINTF("RPL: No hop-by-hop option found, creating it\n"); + if(uip_len + RPL_OP_BY_OP_LEN > UIP_LINK_MTU) { + PRINTF("RPL: Packet too long: impossible to add hop-by-hop option\n"); + uip_ext_len = last_uip_ext_len; + return; + } + memmove(UIP_HBHO_NEXT_BUF, UIP_EXT_BUF, uip_len - UIP_IPH_LEN); + memset(UIP_HBHO_BUF, 0, RPL_OP_BY_OP_LEN); + UIP_HBHO_BUF->next = UIP_IP_BUF->proto; + UIP_IP_BUF->proto = UIP_PROTO_HBHO; + UIP_HBHO_BUF->len = RPL_OP_BY_OP_LEN - 8; + UIP_EXT_HDR_OPT_RPL_BUF->opt_type = UIP_EXT_HDR_OPT_RPL; + UIP_EXT_HDR_OPT_RPL_BUF->opt_len = RPL_HDR_OPT_LEN; + UIP_EXT_HDR_OPT_RPL_BUF->flags = 0; + UIP_EXT_HDR_OPT_RPL_BUF->instance = 0; + UIP_EXT_HDR_OPT_RPL_BUF->senderrank = 0; + uip_len += RPL_OP_BY_OP_LEN; + temp_len = UIP_IP_BUF->len[1]; + UIP_IP_BUF->len[1] += UIP_HBHO_BUF->len + 8; + if(UIP_IP_BUF->len[1] < temp_len) { + UIP_IP_BUF->len[0]++; + } + uip_ext_len = last_uip_ext_len + RPL_OP_BY_OP_LEN; + return; + } + + switch(UIP_EXT_HDR_OPT_BUF->type) { + case UIP_EXT_HDR_OPT_RPL: + PRINTF("RPL: Updating RPL option\n"); + UIP_EXT_HDR_OPT_RPL_BUF->senderrank=instance->current_dag->rank; + uip_ext_len = last_uip_ext_len; + return; + default: + PRINTF("RPL: Multi Hop-by-hop options not implemented\n"); + uip_ext_len = last_uip_ext_len; + return; + } +} +/************************************************************************/ +int +rpl_update_header_final(uip_ipaddr_t *addr) +{ + int uip_ext_opt_offset; + int last_uip_ext_len; + + last_uip_ext_len=uip_ext_len; + uip_ext_len=0; + uip_ext_opt_offset = 2; + rpl_parent_t *parent; + + if(UIP_IP_BUF->proto == UIP_PROTO_HBHO) { + if(UIP_HBHO_BUF->len != RPL_OP_BY_OP_LEN - 8) { + PRINTF("RPL: Non RPL Hop-by-hop options support not implemented\n"); + uip_ext_len = last_uip_ext_len; + return 0; + } + + if(UIP_EXT_HDR_OPT_BUF->type == UIP_EXT_HDR_OPT_RPL) { + if(UIP_EXT_HDR_OPT_RPL_BUF->senderrank == 0) { + PRINTF("RPL: Updating RPL option\n"); + if(default_instance == NULL || !default_instance->used || !default_instance->current_dag->joined) { + PRINTF("RPL: Unable to add hop-by-hop extension header: incorrect default instance\n"); + return 1; + } + parent = rpl_find_parent(default_instance->current_dag, addr); + if(parent == NULL || parent != parent->dag->preferred_parent) { + UIP_EXT_HDR_OPT_RPL_BUF->flags = RPL_HDR_OPT_DOWN; + } + UIP_EXT_HDR_OPT_RPL_BUF->instance = default_instance->instance_id; + UIP_EXT_HDR_OPT_RPL_BUF->senderrank = default_instance->current_dag->rank; + uip_ext_len = last_uip_ext_len; + } + } + } + return 0; +} +/************************************************************************/ +int +rpl_add_header(rpl_instance_t *instance, int down) +{ + int uip_ext_opt_offset; + int last_uip_ext_len; + u8_t temp_len; + + last_uip_ext_len = uip_ext_len; + uip_ext_len = 0; + uip_ext_opt_offset = 2; + + if(instance == NULL || !instance->used || !instance->current_dag->joined) { + PRINTF("Unable to add RPL hop-by-hop extension header : incorrect instance\n"); + return 0; + } + + PRINTF("RPL: Verifying the presence of the RPL header option\n"); + switch(UIP_IP_BUF->proto) { + case UIP_PROTO_HBHO: + if(UIP_HBHO_BUF->len != RPL_OP_BY_OP_LEN - 8) { + PRINTF("RPL: Non RPL Hop-by-hop options support not implemented\n"); + uip_ext_len = last_uip_ext_len; + return 0; + } + break; + default: + PRINTF("RPL: No hop-by-hop option found, creating it\n"); + if(uip_len + RPL_OP_BY_OP_LEN >UIP_LINK_MTU) { + PRINTF("RPL: Packet too long: impossible to add hop-by-hop option\n"); + uip_ext_len = last_uip_ext_len; + return 0; + } + memmove(UIP_HBHO_NEXT_BUF, UIP_EXT_BUF, uip_len - UIP_IPH_LEN); + memset(UIP_HBHO_BUF, 0, RPL_OP_BY_OP_LEN); + UIP_HBHO_BUF->next = UIP_IP_BUF->proto; + UIP_IP_BUF->proto = UIP_PROTO_HBHO; + UIP_HBHO_BUF->len = RPL_OP_BY_OP_LEN - 8; + UIP_EXT_HDR_OPT_RPL_BUF->opt_type = UIP_EXT_HDR_OPT_RPL; + UIP_EXT_HDR_OPT_RPL_BUF->opt_len = RPL_HDR_OPT_LEN; + UIP_EXT_HDR_OPT_RPL_BUF->flags = RPL_HDR_OPT_DOWN & (down << RPL_HDR_OPT_DOWN_SHIFT); + UIP_EXT_HDR_OPT_RPL_BUF->instance = instance->instance_id; + UIP_EXT_HDR_OPT_RPL_BUF->senderrank = instance->current_dag->rank; + uip_len += RPL_OP_BY_OP_LEN; + temp_len = UIP_IP_BUF->len[1]; + UIP_IP_BUF->len[1] += UIP_HBHO_BUF->len + 8; + if(UIP_IP_BUF->len[1] < temp_len) { + UIP_IP_BUF->len[0]++; + } + uip_ext_len = last_uip_ext_len + RPL_OP_BY_OP_LEN; + return 1; + } + + switch(UIP_EXT_HDR_OPT_BUF->type) { + case UIP_EXT_HDR_OPT_RPL: + PRINTF("RPL: Updating RPL option\n"); + UIP_EXT_HDR_OPT_RPL_BUF->opt_type = UIP_EXT_HDR_OPT_RPL; + UIP_EXT_HDR_OPT_RPL_BUF->opt_len = RPL_HDR_OPT_LEN; + UIP_EXT_HDR_OPT_RPL_BUF->flags = RPL_HDR_OPT_DOWN&(down<instance = instance->instance_id; + UIP_EXT_HDR_OPT_RPL_BUF->senderrank = instance->current_dag->rank; + uip_ext_len = last_uip_ext_len; + return 1; + default: + PRINTF("RPL: Multi Hop-by-hop options not implemented\n"); + uip_ext_len = last_uip_ext_len; + return 0; + } +} +/************************************************************************/ +int +rpl_add_header_root(void) +{ + return rpl_add_header(default_instance, 1); +} +/************************************************************************/ +void +rpl_remove_header(void) +{ + int last_uip_ext_len; + u8_t temp_len; + + last_uip_ext_len = uip_ext_len; + uip_ext_len = 0; + + PRINTF("RPL: Verifying the presence of the RPL header option\n"); + switch(UIP_IP_BUF->proto){ + case UIP_PROTO_HBHO: + PRINTF("RPL: Removing the present RPL header option\n"); + UIP_IP_BUF->proto = UIP_HBHO_BUF->next; + temp_len = UIP_IP_BUF->len[1]; + uip_len -= UIP_HBHO_BUF->len + 8; + UIP_IP_BUF->len[1] -= (UIP_HBHO_BUF->len + 8); + if(UIP_IP_BUF->len[1] > temp_len) { + UIP_IP_BUF->len[0]--; + } + memmove(UIP_EXT_BUF, UIP_HBHO_NEXT_BUF, uip_len - UIP_IPH_LEN); + break; + default: + PRINTF("RPL: No Hop-by-Hop Option found\n"); + } +} +/************************************************************************/ +u8_t +rpl_invert_header(void) +{ + u8_t uip_ext_opt_offset; + u8_t last_uip_ext_len; + + last_uip_ext_len = uip_ext_len; + uip_ext_len = 0; + uip_ext_opt_offset = 2; + + PRINTF("RPL: Verifying the presence of the RPL header option\n"); + switch(UIP_IP_BUF->proto) { + case UIP_PROTO_HBHO: + break; + default: + PRINTF("RPL: No Hop-by-Hop Option found\n"); + uip_ext_len = last_uip_ext_len; + return 0; + } + switch (UIP_EXT_HDR_OPT_BUF->type) { + case UIP_EXT_HDR_OPT_RPL: + PRINTF("RPL: Updating RPL option (Inverting Up<->Down)\n"); + UIP_EXT_HDR_OPT_RPL_BUF->flags &= RPL_HDR_OPT_DOWN; + UIP_EXT_HDR_OPT_RPL_BUF->flags ^= RPL_HDR_OPT_DOWN; + UIP_EXT_HDR_OPT_RPL_BUF->senderrank = rpl_get_instance(UIP_EXT_HDR_OPT_RPL_BUF->instance)->current_dag->rank; + uip_ext_len = last_uip_ext_len; + return RPL_OP_BY_OP_LEN; + default: + PRINTF("RPL: Multi Hop-by-hop options not implemented\n"); + uip_ext_len = last_uip_ext_len; + return 0; + } +} +/************************************************************************/ diff --git a/core/net/rpl/rpl-icmp6.c b/core/net/rpl/rpl-icmp6.c index f59125391..b00dcb32b 100644 --- a/core/net/rpl/rpl-icmp6.c +++ b/core/net/rpl/rpl-icmp6.c @@ -120,8 +120,8 @@ dis_input(void) PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINTF("\n"); - for( instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES; instance < end; ++instance) { - if ( instance->used == 1 ) { + for(instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES; instance < end; ++instance) { + if(instance->used == 1 ) { #if RPL_LEAF_ONLY if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) { #else /* !RPL_LEAF_ONLY */ @@ -399,7 +399,7 @@ dio_output(rpl_instance_t *instance, uip_ipaddr_t *uc_addr) buffer[pos++] = instance->dtsn_out; - if (RPL_LOLLIPOP_IS_INIT(instance->dtsn_out)) + if(RPL_LOLLIPOP_IS_INIT(instance->dtsn_out)) RPL_LOLLIPOP_INCREMENT(instance->dtsn_out); /* reserved 2 bytes */ diff --git a/core/net/rpl/rpl.c b/core/net/rpl/rpl.c index 271136b62..43e30ca06 100644 --- a/core/net/rpl/rpl.c +++ b/core/net/rpl/rpl.c @@ -159,10 +159,10 @@ rpl_link_neighbor_callback(const rimeaddr_t *addr, int known, int etx) PRINT6ADDR(&ipaddr); PRINTF(" is %sknown. ETX = %u\n", known ? "" : "no longer ", NEIGHBOR_INFO_FIX2ETX(etx)); - for( instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES; instance < end; ++instance) { - if ( instance->used == 1 ) { + for(instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES; instance < end; ++instance) { + if(instance->used == 1 ) { parent = rpl_find_parent_any_dag(instance, &ipaddr); - if(!(parent == NULL)) { + if(parent != NULL) { /* Trigger DAG rank recalculation. */ parent->updated = 1; parent->link_metric = etx; @@ -180,7 +180,7 @@ rpl_link_neighbor_callback(const rimeaddr_t *addr, int known, int etx) } } - if (!known) { + if(!known) { PRINTF("RPL: Deleting routes installed by DAOs received from "); PRINT6ADDR(&ipaddr); PRINTF("\n"); @@ -199,8 +199,8 @@ rpl_ipv6_neighbor_callback(uip_ds6_nbr_t *nbr) PRINTF("RPL: Removing neighbor "); PRINT6ADDR(&nbr->ipaddr); PRINTF("\n"); - for( instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES; instance < end; ++instance) { - if ( instance->used == 1 ) { + for(instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES; instance < end; ++instance) { + if(instance->used == 1 ) { p = rpl_find_parent_any_dag(instance, &nbr->ipaddr); if(p != NULL) { p->rank = INFINITE_RANK; @@ -217,7 +217,7 @@ rpl_init(void) { uip_ipaddr_t rplmaddr; PRINTF("RPL started\n"); - default_instance=NULL; + default_instance = NULL; rpl_reset_periodic_timer(); neighbor_info_subscribe(rpl_link_neighbor_callback); @@ -231,299 +231,3 @@ rpl_init(void) #endif } /************************************************************************/ -int -rpl_verify_header(int uip_ext_opt_offset) -{ - rpl_instance_t *instance; - - if (UIP_EXT_HDR_OPT_RPL_BUF->opt_len != RPL_HDR_OPT_LEN) { - PRINTF("RPL: Bad header option (wrong length) !\n"); - return 1; - } - - if (UIP_EXT_HDR_OPT_RPL_BUF->flags&RPL_HDR_OPT_FWD_ERR) { - PRINTF("RPL: Forward error !\n"); - /* We should try to repair it, not implemented for the moment */ - return 2; - } - - instance = rpl_get_instance(UIP_EXT_HDR_OPT_RPL_BUF->instance); - - if (instance == NULL) { - PRINTF("RPL : Unknown instance : %u\n",UIP_EXT_HDR_OPT_RPL_BUF->instance); - return 1; - } - - if (!instance->current_dag->joined) { - PRINTF("RPL : No dag in the instance\n"); - return 1; - } - - if (UIP_EXT_HDR_OPT_RPL_BUF->flags&RPL_HDR_OPT_DOWN) { - PRINTF("RPL: Packet going down :\n"); - if (UIP_EXT_HDR_OPT_RPL_BUF->senderrank>instance->current_dag->rank) { - PRINTF("RPL: Loop detected : Sender rank > our rank\n"); - if (UIP_EXT_HDR_OPT_RPL_BUF->flags&RPL_HDR_OPT_RANK_ERR) { - PRINTF("RPL: Loop detected !\n"); - /* We should try to repair it, not implemented for the moment */ - return 3; - } - PRINTF("RPL: Single error tolerated\n"); - UIP_EXT_HDR_OPT_RPL_BUF->flags|=RPL_HDR_OPT_RANK_ERR; - return 0; - } - } else { - PRINTF("RPL: Packet going up :"); - if (UIP_EXT_HDR_OPT_RPL_BUF->senderrankcurrent_dag->rank) { - PRINTF("RPL: Rank error : Sender rank < our rank\n"); - if (UIP_EXT_HDR_OPT_RPL_BUF->flags&RPL_HDR_OPT_RANK_ERR) { - PRINTF("RPL: Loop detected !\n"); - /* We should try to repair it, not implemented for the moment */ - return 3; - } - PRINTF("RPL: Single error tolerated\n"); - UIP_EXT_HDR_OPT_RPL_BUF->flags|=RPL_HDR_OPT_RANK_ERR; - return 0; - } - } - PRINTF("RPL: rank Ok\n"); - return 0; -} -/************************************************************************/ -void -rpl_update_header_empty(void) -{ - rpl_instance_t *instance; - int uip_ext_opt_offset; - int last_uip_ext_len; - u8_t temp_len; - - last_uip_ext_len=uip_ext_len; - uip_ext_len=0; - uip_ext_opt_offset = 2; - - PRINTF("RPL: Verifying the presence of the RPL header option\n"); - switch(UIP_IP_BUF->proto){ - case UIP_PROTO_HBHO: - if (UIP_HBHO_BUF->len != RPL_OP_BY_OP_LEN - 8) { - PRINTF("RPL: Non RPL Hop-by-hop options support not implemented\n"); - uip_ext_len=last_uip_ext_len; - return; - } - instance = rpl_get_instance(UIP_EXT_HDR_OPT_RPL_BUF->instance); - if(instance == NULL || (!instance->used) || (!instance->current_dag->joined) ) { - PRINTF("Unable to add RPL hop-by-hop extension header : incorrect instance\n"); - return; - } - break; - default: - PRINTF("RPL: No Hop-by-Hop Option found, creating it\n"); - if(uip_len + RPL_OP_BY_OP_LEN >UIP_LINK_MTU) { - PRINTF("RPL: Packet too long : impossible to add rpl Hop-by-Hop option\n"); - uip_ext_len=last_uip_ext_len; - return; - } - memmove(UIP_HBHO_NEXT_BUF,UIP_EXT_BUF,uip_len-UIP_IPH_LEN); - memset(UIP_HBHO_BUF,0,RPL_OP_BY_OP_LEN); - UIP_HBHO_BUF->next=UIP_IP_BUF->proto; - UIP_IP_BUF->proto=UIP_PROTO_HBHO; - UIP_HBHO_BUF->len=RPL_OP_BY_OP_LEN - 8; - UIP_EXT_HDR_OPT_RPL_BUF->opt_type=UIP_EXT_HDR_OPT_RPL; - UIP_EXT_HDR_OPT_RPL_BUF->opt_len=RPL_HDR_OPT_LEN; - UIP_EXT_HDR_OPT_RPL_BUF->flags=0; - UIP_EXT_HDR_OPT_RPL_BUF->instance=0; - UIP_EXT_HDR_OPT_RPL_BUF->senderrank=0; - uip_len+=RPL_OP_BY_OP_LEN; - temp_len=UIP_IP_BUF->len[1]; - UIP_IP_BUF->len[1]+=(UIP_HBHO_BUF->len + 8); - if (UIP_IP_BUF->len[1]len[0]+=1; - } - uip_ext_len=last_uip_ext_len+RPL_OP_BY_OP_LEN; - return; - } - switch (UIP_EXT_HDR_OPT_BUF->type) { - case UIP_EXT_HDR_OPT_RPL: - PRINTF("RPL: Updating RPL option\n"); - UIP_EXT_HDR_OPT_RPL_BUF->senderrank=instance->current_dag->rank; - uip_ext_len=last_uip_ext_len; - return; - default: - PRINTF("RPL: Multi Hop-by-hop options not implemented\n"); - uip_ext_len=last_uip_ext_len; - return; - } -} -/************************************************************************/ -int -rpl_update_header_final(uip_ipaddr_t *addr) -{ - int uip_ext_opt_offset; - int last_uip_ext_len; - - last_uip_ext_len=uip_ext_len; - uip_ext_len=0; - uip_ext_opt_offset = 2; - rpl_parent_t *parent; - - if (UIP_IP_BUF->proto == UIP_PROTO_HBHO){ - if (UIP_HBHO_BUF->len != RPL_OP_BY_OP_LEN - 8) { - PRINTF("RPL: Non RPL Hop-by-hop options support not implemented\n"); - uip_ext_len=last_uip_ext_len; - return 0; - } - if (UIP_EXT_HDR_OPT_BUF->type == UIP_EXT_HDR_OPT_RPL) { - if (UIP_EXT_HDR_OPT_RPL_BUF->senderrank==0) { - PRINTF("RPL: Updating RPL option\n"); - if(default_instance == NULL || (!default_instance->used) || (!default_instance->current_dag->joined) ) { - PRINTF("Unable to add RPL hop-by-hop extension header : incorrect default instance\n"); - return 1; - } - parent=rpl_find_parent(default_instance->current_dag,addr); - if (parent == NULL || (parent != parent->dag->preferred_parent)) { - UIP_EXT_HDR_OPT_RPL_BUF->flags=RPL_HDR_OPT_DOWN; - } - UIP_EXT_HDR_OPT_RPL_BUF->instance=default_instance->instance_id; - UIP_EXT_HDR_OPT_RPL_BUF->senderrank=default_instance->current_dag->rank; - uip_ext_len=last_uip_ext_len; - } - } - } - return 0; -} -/************************************************************************/ -int -rpl_add_header(rpl_instance_t *instance,int down) -{ - int uip_ext_opt_offset; - int last_uip_ext_len; - u8_t temp_len; - - last_uip_ext_len = uip_ext_len; - uip_ext_len = 0; - uip_ext_opt_offset = 2; - - if(instance == NULL || (!instance->used) || (!instance->current_dag->joined) ) { - PRINTF("Unable to add RPL hop-by-hop extension header : incorrect instance\n"); - return 0; - } - - PRINTF("RPL: Verifying the presence of the RPL header option\n"); - switch(UIP_IP_BUF->proto){ - case UIP_PROTO_HBHO: - if (UIP_HBHO_BUF->len != RPL_OP_BY_OP_LEN - 8) { - PRINTF("RPL: Non RPL Hop-by-hop options support not implemented\n"); - uip_ext_len=last_uip_ext_len; - return 0; - } - break; - default: - PRINTF("RPL: No Hop-by-Hop Option found, creating it\n"); - if(uip_len + RPL_OP_BY_OP_LEN >UIP_LINK_MTU) { - PRINTF("RPL: Packet too long : impossible to add rpl Hop-by-Hop option\n"); - uip_ext_len=last_uip_ext_len; - return 0; - } - memmove(UIP_HBHO_NEXT_BUF,UIP_EXT_BUF,uip_len-UIP_IPH_LEN); - memset(UIP_HBHO_BUF,0,RPL_OP_BY_OP_LEN); - UIP_HBHO_BUF->next=UIP_IP_BUF->proto; - UIP_IP_BUF->proto=UIP_PROTO_HBHO; - UIP_HBHO_BUF->len=RPL_OP_BY_OP_LEN - 8; - UIP_EXT_HDR_OPT_RPL_BUF->opt_type=UIP_EXT_HDR_OPT_RPL; - UIP_EXT_HDR_OPT_RPL_BUF->opt_len=RPL_HDR_OPT_LEN; - UIP_EXT_HDR_OPT_RPL_BUF->flags=RPL_HDR_OPT_DOWN&(down<instance=instance->instance_id; - UIP_EXT_HDR_OPT_RPL_BUF->senderrank=instance->current_dag->rank; - uip_len+=RPL_OP_BY_OP_LEN; - temp_len=UIP_IP_BUF->len[1]; - UIP_IP_BUF->len[1]+=(UIP_HBHO_BUF->len + 8); - if (UIP_IP_BUF->len[1]len[0]+=1; - } - uip_ext_len=last_uip_ext_len+RPL_OP_BY_OP_LEN; - return 1; - } - switch (UIP_EXT_HDR_OPT_BUF->type) { - case UIP_EXT_HDR_OPT_RPL: - PRINTF("RPL: Updating RPL option\n"); - UIP_EXT_HDR_OPT_RPL_BUF->opt_type=UIP_EXT_HDR_OPT_RPL; - UIP_EXT_HDR_OPT_RPL_BUF->opt_len=RPL_HDR_OPT_LEN; - UIP_EXT_HDR_OPT_RPL_BUF->flags=RPL_HDR_OPT_DOWN&(down<instance=instance->instance_id; - UIP_EXT_HDR_OPT_RPL_BUF->senderrank=instance->current_dag->rank; - uip_ext_len=last_uip_ext_len; - return 1; - default: - PRINTF("RPL: Multi Hop-by-hop options not implemented\n"); - uip_ext_len=last_uip_ext_len; - return 0; - } -} -/************************************************************************/ -int -rpl_add_header_root(void) -{ - return rpl_add_header(default_instance,1); -} -/************************************************************************/ -void -rpl_remove_header() -{ - int last_uip_ext_len; - u8_t temp_len; - - last_uip_ext_len=uip_ext_len; - uip_ext_len=0; - - PRINTF("RPL: Verifying the presence of the RPL header option\n"); - switch(UIP_IP_BUF->proto){ - case UIP_PROTO_HBHO: - PRINTF("RPL: Removing the present RPL header option\n"); - UIP_IP_BUF->proto=UIP_HBHO_BUF->next; - temp_len=UIP_IP_BUF->len[1]; - uip_len-=UIP_HBHO_BUF->len + 8; - UIP_IP_BUF->len[1]-=(UIP_HBHO_BUF->len + 8); - if (UIP_IP_BUF->len[1]>temp_len) { - UIP_IP_BUF->len[0]-=1; - } - memmove(UIP_EXT_BUF, UIP_HBHO_NEXT_BUF, uip_len - UIP_IPH_LEN); - break; - default: - PRINTF("RPL: No Hop-by-Hop Option found\n"); - } -} -/************************************************************************/ -u8_t -rpl_invert_header() -{ - u8_t uip_ext_opt_offset; - u8_t last_uip_ext_len; - - last_uip_ext_len=uip_ext_len; - uip_ext_len=0; - uip_ext_opt_offset = 2; - - PRINTF("RPL: Verifying the presence of the RPL header option\n"); - switch(UIP_IP_BUF->proto){ - case UIP_PROTO_HBHO: - break; - default: - PRINTF("RPL: No Hop-by-Hop Option found\n"); - uip_ext_len=last_uip_ext_len; - return 0; - } - switch (UIP_EXT_HDR_OPT_BUF->type) { - case UIP_EXT_HDR_OPT_RPL: - PRINTF("RPL: Updating RPL option (Inverting Up<->Down)\n"); - UIP_EXT_HDR_OPT_RPL_BUF->flags&=RPL_HDR_OPT_DOWN; - UIP_EXT_HDR_OPT_RPL_BUF->flags^=RPL_HDR_OPT_DOWN; - UIP_EXT_HDR_OPT_RPL_BUF->senderrank=rpl_get_instance(UIP_EXT_HDR_OPT_RPL_BUF->instance)->current_dag->rank; - uip_ext_len=last_uip_ext_len; - return RPL_OP_BY_OP_LEN; - default: - PRINTF("RPL: Multi Hop-by-hop options not implemented\n"); - uip_ext_len=last_uip_ext_len; - return 0; - } -} -/************************************************************************/ From b405571e32e15c7e98bc74a6e642fd179297a609 Mon Sep 17 00:00:00 2001 From: Nicolas Tsiftes Date: Wed, 16 Nov 2011 09:05:34 +0100 Subject: [PATCH 14/25] Update next-hop address for existing routes. --- core/net/rpl/rpl-icmp6.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/core/net/rpl/rpl-icmp6.c b/core/net/rpl/rpl-icmp6.c index b00dcb32b..54049b130 100644 --- a/core/net/rpl/rpl-icmp6.c +++ b/core/net/rpl/rpl-icmp6.c @@ -632,13 +632,11 @@ dao_input(void) } } + rep = rpl_add_route(dag, &prefix, prefixlen, &dao_sender_addr); if(rep == NULL) { - rep = rpl_add_route(dag, &prefix, prefixlen, &dao_sender_addr); - if(rep == NULL) { - RPL_STAT(rpl_stats.mem_overflows++); - PRINTF("RPL: Could not add a route after receiving a DAO\n"); - return; - } + RPL_STAT(rpl_stats.mem_overflows++); + PRINTF("RPL: Could not add a route after receiving a DAO\n"); + return; } rep->state.lifetime = RPL_LIFETIME(instance, lifetime); From ea73f1d76754f6c131d2e9f27935dfd4efac9989 Mon Sep 17 00:00:00 2001 From: Nicolas Tsiftes Date: Wed, 16 Nov 2011 09:49:22 +0100 Subject: [PATCH 15/25] Do not force DIO reset on certain events where it is not needed. --- core/net/rpl/rpl-dag.c | 20 ++++++++++---------- core/net/rpl/rpl-ext-header.c | 8 ++++---- core/net/rpl/rpl-icmp6.c | 2 +- core/net/rpl/rpl-timers.c | 7 ++++--- 4 files changed, 19 insertions(+), 18 deletions(-) diff --git a/core/net/rpl/rpl-dag.c b/core/net/rpl/rpl-dag.c index 10ad983cc..46b35e9a3 100644 --- a/core/net/rpl/rpl-dag.c +++ b/core/net/rpl/rpl-dag.c @@ -561,7 +561,7 @@ rpl_select_dodag(rpl_instance_t * instance, rpl_parent_t *p) } if(best_dag == NULL) { - /* No parent found : the calling function handle this problem. */ + /* No parent found: the calling function handle this problem. */ return NULL; } @@ -569,7 +569,7 @@ rpl_select_dodag(rpl_instance_t * instance, rpl_parent_t *p) /* Remove routes installed by DAOs. */ rpl_remove_routes(instance->current_dag); - PRINTF("RPL: New preferred DODAG : "); + PRINTF("RPL: New preferred DODAG: "); PRINT6ADDR(&best_dag->dag_id); PRINTF("\n"); @@ -986,7 +986,7 @@ rpl_local_repair(rpl_instance_t *instance) } } - rpl_reset_dio_timer(instance,1); + rpl_reset_dio_timer(instance, 0); RPL_STAT(rpl_stats.local_repairs++); } @@ -1105,14 +1105,14 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio) instance = rpl_get_instance(dio->instance_id); if(instance == NULL) { - PRINTF("RPL : New instance detected : Joining...\n"); + PRINTF("RPL: New instance detected: Joining...\n"); rpl_join_instance(from, dio); return; } dag = rpl_get_dodag(dio->instance_id,&dio->dag_id); if(dag == NULL) { - PRINTF("RPL : Adding new dodag to known instance.\n"); + PRINTF("RPL: Adding new dodag to known instance.\n"); rpl_add_dodag(from,dio); return; } @@ -1122,7 +1122,7 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio) PRINTF("RPL: Root received inconsistent DIO version number\n"); dag->version = dio->version; RPL_LOLLIPOP_INCREMENT(dag->version); - rpl_reset_dio_timer(instance, 1); + rpl_reset_dio_timer(instance, 0); } else { global_repair(from, dag, dio); } @@ -1132,7 +1132,7 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio) /* Inconsistency detected - someone is still on old version */ PRINTF("RPL: old version received => inconsistency detected\n"); if(dag->joined) { - rpl_reset_dio_timer(instance, 1); + rpl_reset_dio_timer(instance, 0); return; } } @@ -1140,7 +1140,7 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio) if(dio->rank == INFINITE_RANK) { if(dag->joined) { - rpl_reset_dio_timer(instance, 1); + rpl_reset_dio_timer(instance, 0); } } else if(dio->rank < ROOT_RANK(instance)) { PRINTF("RPL: Ignoring DIO with too low rank: %u\n", @@ -1150,7 +1150,7 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio) if(dag->rank == ROOT_RANK(instance)) { if(dio->rank != INFINITE_RANK) { - instance->dio_counter++; + instance->dio_counter++; } return; } @@ -1199,7 +1199,7 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio) PRINTF("RPL current state: Prefered DODAG: "); PRINT6ADDR(&instance->current_dag->dag_id); PRINTF(", rank: %u, min_rank: %u, ",instance->current_dag->rank,instance->current_dag->min_rank); - PRINTF("p->rank : %u, p->mc.obj.etx : %u, p->link_metric : %u, instance->mc.obj.etx %u\n", p->rank, p->mc.obj.etx, p->link_metric,instance->mc.obj.etx); + PRINTF("p->rank: %u, p->mc.obj.etx: %u, p->link_metric: %u, instance->mc.obj.etx %u\n", p->rank, p->mc.obj.etx, p->link_metric,instance->mc.obj.etx); /* We have allocated a candidate parent; process the DIO further. */ diff --git a/core/net/rpl/rpl-ext-header.c b/core/net/rpl/rpl-ext-header.c index 9ff8385fc..2f6dcfab0 100644 --- a/core/net/rpl/rpl-ext-header.c +++ b/core/net/rpl/rpl-ext-header.c @@ -77,7 +77,7 @@ rpl_verify_header(int uip_ext_opt_offset) instance = rpl_get_instance(UIP_EXT_HDR_OPT_RPL_BUF->instance); if(instance == NULL) { - PRINTF("RPL: Unknown instance : %u\n", + PRINTF("RPL: Unknown instance: %u\n", UIP_EXT_HDR_OPT_RPL_BUF->instance); return 1; } @@ -90,7 +90,7 @@ rpl_verify_header(int uip_ext_opt_offset) if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_DOWN) { PRINTF("RPL: Packet going down :\n"); if(UIP_EXT_HDR_OPT_RPL_BUF->senderrank > instance->current_dag->rank) { - PRINTF("RPL: Loop detected : Sender rank > our rank\n"); + PRINTF("RPL: Loop detected: Sender rank > our rank\n"); if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_RANK_ERR) { PRINTF("RPL: Loop detected !\n"); /* We should try to repair it, not implemented for the moment */ @@ -103,7 +103,7 @@ rpl_verify_header(int uip_ext_opt_offset) } else { PRINTF("RPL: Packet going up :"); if(UIP_EXT_HDR_OPT_RPL_BUF->senderrank < instance->current_dag->rank) { - PRINTF("RPL: Rank error : Sender rank < our rank\n"); + PRINTF("RPL: Rank error: Sender rank < our rank\n"); if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_RANK_ERR) { PRINTF("RPL: Loop detected !\n"); /* We should try to repair it, not implemented for the moment */ @@ -236,7 +236,7 @@ rpl_add_header(rpl_instance_t *instance, int down) uip_ext_opt_offset = 2; if(instance == NULL || !instance->used || !instance->current_dag->joined) { - PRINTF("Unable to add RPL hop-by-hop extension header : incorrect instance\n"); + PRINTF("Unable to add RPL hop-by-hop extension header: incorrect instance\n"); return 0; } diff --git a/core/net/rpl/rpl-icmp6.c b/core/net/rpl/rpl-icmp6.c index 54049b130..9414ae3dd 100644 --- a/core/net/rpl/rpl-icmp6.c +++ b/core/net/rpl/rpl-icmp6.c @@ -233,7 +233,7 @@ dio_input(void) PRINTF("RPL: Incoming DIO DODAG "); PRINT6ADDR(&dio.dag_id); - PRINTF(" preference : %u\n",dio.preference); + PRINTF(", preference: %u\n", dio.preference); /* Check if there are any DIO suboptions. */ for(; i < buffer_length; i += len) { diff --git a/core/net/rpl/rpl-timers.c b/core/net/rpl/rpl-timers.c index c86618f3c..aafd9e734 100644 --- a/core/net/rpl/rpl-timers.c +++ b/core/net/rpl/rpl-timers.c @@ -178,7 +178,8 @@ void rpl_reset_dio_timer(rpl_instance_t *instance, uint8_t force) { #if !RPL_LEAF_ONLY - /* only reset if not just reset or started */ + /* Do not reset if we are already on the minimum interval, + unless forced to do so. */ if(force || instance->dio_intcurrent > instance->dio_intmin) { instance->dio_counter = 0; instance->dio_intcurrent = instance->dio_intmin; @@ -197,8 +198,8 @@ handle_dao_timer(void *ptr) instance = (rpl_instance_t *)ptr; - if (!dio_send_ok && uip_ds6_get_link_local(ADDR_PREFERRED) == NULL) { - PRINTF("RPL: Postpone DAO transmission... \n"); + if(!dio_send_ok && uip_ds6_get_link_local(ADDR_PREFERRED) == NULL) { + PRINTF("RPL: Postpone DAO transmission\n"); ctimer_set(&instance->dao_timer, CLOCK_SECOND, handle_dao_timer, instance); return; } From 2b1549bfe8b3d58a5b7be38477eaf416fc19b4e4 Mon Sep 17 00:00:00 2001 From: Nicolas Tsiftes Date: Mon, 21 Nov 2011 15:09:19 +0100 Subject: [PATCH 16/25] Continued merge with sf master --- core/net/rpl/Makefile.rpl | 2 +- core/net/rpl/rpl-dag.c | 3 +-- core/net/rpl/rpl-icmp6.c | 12 ++++++++++++ core/net/rpl/rpl.h | 6 +++--- examples/ipv6/rpl-udp/Makefile | 1 + 5 files changed, 18 insertions(+), 6 deletions(-) mode change 100644 => 100755 core/net/rpl/rpl-dag.c mode change 100644 => 100755 core/net/rpl/rpl-icmp6.c diff --git a/core/net/rpl/Makefile.rpl b/core/net/rpl/Makefile.rpl index 68f67f2bc..88d5c4775 100644 --- a/core/net/rpl/Makefile.rpl +++ b/core/net/rpl/Makefile.rpl @@ -1,2 +1,2 @@ CONTIKI_SOURCEFILES += rpl.c rpl-dag.c rpl-icmp6.c rpl-timers.c \ - rpl-of-etx.c + rpl-of-etx.c rpl-ext-header.c diff --git a/core/net/rpl/rpl-dag.c b/core/net/rpl/rpl-dag.c old mode 100644 new mode 100755 index 7a96887cc..0310c1727 --- a/core/net/rpl/rpl-dag.c +++ b/core/net/rpl/rpl-dag.c @@ -567,7 +567,6 @@ rpl_select_dodag(rpl_instance_t * instance, rpl_parent_t *p) return NULL; } -<<<<<<< HEAD if(instance->current_dag != best_dag) { /* Remove routes installed by DAOs. */ rpl_remove_routes(instance->current_dag); @@ -758,7 +757,7 @@ rpl_get_dodag(uint8_t instance_id, uip_ipaddr_t *dag_id) for(i = 0; i < RPL_MAX_DODAG_PER_INSTANCE; ++i) { dag = &instance->dag_table[i]; - if(dag->used && !uip_ipaddr_cmp(dag->dag_id, dag_id)) { + if(dag->used && !uip_ipaddr_cmp(&dag->dag_id, dag_id)) { return dag; } } diff --git a/core/net/rpl/rpl-icmp6.c b/core/net/rpl/rpl-icmp6.c old mode 100644 new mode 100755 index fe496c928..2dcc33f8b --- a/core/net/rpl/rpl-icmp6.c +++ b/core/net/rpl/rpl-icmp6.c @@ -82,6 +82,16 @@ void RPL_DEBUG_DAO_OUTPUT(rpl_parent_t *); #endif static uint8_t dao_sequence = RPL_LOLLIPOP_INIT; + +/* some debug callbacks useful when debugging RPL networks */ +#ifdef RPL_DEBUG_DIO_INPUT +void RPL_DEBUG_DIO_INPUT(uip_ipaddr_t *, rpl_dio_t *); +#endif + +#ifdef RPL_DEBUG_DAO_OUTPUT +void RPL_DEBUG_DAO_OUTPUT(rpl_parent_t *); +#endif + /*---------------------------------------------------------------------------*/ static int get_global_addr(uip_ipaddr_t *addr) @@ -407,6 +417,7 @@ dio_output(rpl_instance_t *instance, uip_ipaddr_t *uc_addr) buffer = UIP_ICMP_PAYLOAD; buffer[pos++] = instance->instance_id; buffer[pos++] = dag->version; + #if RPL_LEAF_ONLY set16(buffer, pos, INFINITE_RANK); #else /* RPL_LEAF_ONLY */ @@ -460,6 +471,7 @@ dio_output(rpl_instance_t *instance, uip_ipaddr_t *uc_addr) return; } } +#endif /* !RPL_LEAF_ONLY */ /* Always add a DAG configuration option. */ buffer[pos++] = RPL_OPTION_DAG_CONF; diff --git a/core/net/rpl/rpl.h b/core/net/rpl/rpl.h index 4132d429c..9dcfba586 100644 --- a/core/net/rpl/rpl.h +++ b/core/net/rpl/rpl.h @@ -335,13 +335,13 @@ struct rpl_instance { /* Public RPL functions. */ void rpl_init(void); rpl_dag_t *rpl_set_root(uint8_t instance_id, uip_ipaddr_t * dag_id); -int rpl_set_prefix(rpl_dag_t *dag, uip_ipaddr_t *prefix, int len); +int rpl_set_prefix(rpl_dag_t *dag, uip_ipaddr_t *prefix, unsigned len); int rpl_repair_root(uint8_t instance_id); int rpl_set_default_route(rpl_instance_t *instance, uip_ipaddr_t *from); rpl_dag_t *rpl_get_any_dag(void); -rpl_dag_t *rpl_get_dodag(uint8_t instance_id,uip_ipaddr_t * dag_id); +rpl_dag_t *rpl_get_dodag(uint8_t instance_id, uip_ipaddr_t *dag_id); rpl_instance_t *rpl_get_instance(uint8_t instance_id); -int rpl_add_header(rpl_instance_t *instance,int down); +int rpl_add_header(rpl_instance_t *instance, int down); int rpl_add_header_root(void); void rpl_remove_header(void); u8_t rpl_invert_header(void); diff --git a/examples/ipv6/rpl-udp/Makefile b/examples/ipv6/rpl-udp/Makefile index 6c7e2cb7a..e4ea78e28 100644 --- a/examples/ipv6/rpl-udp/Makefile +++ b/examples/ipv6/rpl-udp/Makefile @@ -4,6 +4,7 @@ CONTIKI=../../.. WITH_UIP6=1 UIP_CONF_IPV6=1 + CFLAGS+= -DUIP_CONF_IPV6_RPL ifdef WITH_COMPOWER From cef95ebf9b2ca12ae3f2a7d9d972cf6f222d5bd3 Mon Sep 17 00:00:00 2001 From: Nicolas Tsiftes Date: Mon, 21 Nov 2011 15:50:19 +0100 Subject: [PATCH 17/25] Inverted DAG ID check --- core/net/rpl/rpl-dag.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/net/rpl/rpl-dag.c b/core/net/rpl/rpl-dag.c index 0310c1727..cc19eaf2f 100755 --- a/core/net/rpl/rpl-dag.c +++ b/core/net/rpl/rpl-dag.c @@ -592,7 +592,7 @@ rpl_select_dodag(rpl_instance_t * instance, rpl_parent_t *p) if(best_dag->rank < best_dag->min_rank) { best_dag->min_rank = best_dag->rank; } else if(!acceptable_rank(best_dag, best_dag->rank)) { - PRINTF("RPL: New rank unacceptable !\n"); + PRINTF("RPL: New rank unacceptable!\n"); instance->current_dag->preferred_parent = NULL; if(instance->mop != RPL_MOP_NO_DOWNWARD_ROUTES && last_parent != NULL) { /* Send a No-Path DAO to the removed preferred parent. */ @@ -757,7 +757,7 @@ rpl_get_dodag(uint8_t instance_id, uip_ipaddr_t *dag_id) for(i = 0; i < RPL_MAX_DODAG_PER_INSTANCE; ++i) { dag = &instance->dag_table[i]; - if(dag->used && !uip_ipaddr_cmp(&dag->dag_id, dag_id)) { + if(dag->used && uip_ipaddr_cmp(&dag->dag_id, dag_id)) { return dag; } } From e11b7d4fb69bd7aaf5530cb07b8a2f0b7a895d05 Mon Sep 17 00:00:00 2001 From: nvt Date: Tue, 22 Nov 2011 14:18:32 +0100 Subject: [PATCH 18/25] Removed redundant code --- core/net/rpl/rpl-dag.c | 16 ++++++++-------- core/net/rpl/rpl-ext-header.c | 14 +++++++------- core/net/rpl/rpl.c | 9 --------- 3 files changed, 15 insertions(+), 24 deletions(-) diff --git a/core/net/rpl/rpl-dag.c b/core/net/rpl/rpl-dag.c index cc19eaf2f..0ce3e0f87 100755 --- a/core/net/rpl/rpl-dag.c +++ b/core/net/rpl/rpl-dag.c @@ -533,7 +533,7 @@ rpl_find_parent_any_dag(rpl_instance_t *instance, uip_ipaddr_t *addr) } /************************************************************************/ rpl_dag_t * -rpl_select_dodag(rpl_instance_t * instance, rpl_parent_t *p) +rpl_select_dodag(rpl_instance_t *instance, rpl_parent_t *p) { rpl_parent_t *last_parent; rpl_dag_t *dag, *end, *best_dag; @@ -643,9 +643,8 @@ rpl_select_parent(rpl_dag_t *dag) if(best != NULL) { dag->preferred_parent = best; - } else { - /* We should probably do something here .... */ } + return best; } /************************************************************************/ @@ -693,8 +692,7 @@ rpl_move_parent(rpl_dag_t *dag_src, rpl_dag_t *dag_dst, rpl_parent_t *parent) if(parent == dag_src->preferred_parent) { dag_src->preferred_parent = NULL; dag_src->rank = INFINITE_RANK; - if(dag_src->joined - && dag_src->instance->def_route != NULL) { + if(dag_src->joined && dag_src->instance->def_route != NULL) { if(dag_src->instance->def_route->isused) { PRINTF("RPL: Removing default route "); PRINT6ADDR(&parent->addr); @@ -966,6 +964,7 @@ global_repair(uip_ipaddr_t *from, rpl_dag_t *dag, rpl_dio_t *dio) dag->instance->of->reset(dag); dag->min_rank = INFINITE_RANK; RPL_LOLLIPOP_INCREMENT(dag->instance->dtsn_out); + p = rpl_add_parent(dag, dio, from); if(p == NULL) { PRINTF("RPL: Failed to add a parent during the global repair\n"); @@ -975,6 +974,7 @@ global_repair(uip_ipaddr_t *from, rpl_dag_t *dag, rpl_dio_t *dio) dag->min_rank = dag->rank ; rpl_process_parent_event(dag->instance, p); } + PRINTF("RPL: Participating in a global repair (version=%u, rank=%hu)\n", dag->version, dag->rank); @@ -1137,7 +1137,7 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio) return; } else { if(RPL_LOLLIPOP_GREATER_THAN(dag->version, dio->version)) { - /* Inconsistency detected - someone is still on old version */ + /* The DIO sender is on an older version of the DAG. */ PRINTF("RPL: old version received => inconsistency detected\n"); if(dag->joined) { rpl_reset_dio_timer(instance, 0); @@ -1219,8 +1219,8 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio) return; } - /* We don't use route control, so we can have only one official parent */ - if(dag->joined&&(p==dag->preferred_parent)) { + /* We don't use route control, so we can have only one official parent. */ + if(dag->joined && p == dag->preferred_parent) { if(should_send_dao(instance, dio, p)) { RPL_LOLLIPOP_INCREMENT(instance->dtsn_out); rpl_schedule_dao(instance); diff --git a/core/net/rpl/rpl-ext-header.c b/core/net/rpl/rpl-ext-header.c index 2f6dcfab0..fa3ca57e3 100644 --- a/core/net/rpl/rpl-ext-header.c +++ b/core/net/rpl/rpl-ext-header.c @@ -51,13 +51,13 @@ #include /************************************************************************/ -#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) -#define UIP_EXT_BUF ((struct uip_ext_hdr *)&uip_buf[uip_l2_l3_hdr_len]) -#define UIP_HBHO_BUF ((struct uip_hbho_hdr *)&uip_buf[uip_l2_l3_hdr_len]) -#define UIP_HBHO_NEXT_BUF ((struct uip_ext_hdr *)&uip_buf[uip_l2_l3_hdr_len + RPL_OP_BY_OP_LEN]) -#define UIP_EXT_HDR_OPT_BUF ((struct uip_ext_hdr_opt *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) +#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) +#define UIP_EXT_BUF ((struct uip_ext_hdr *)&uip_buf[uip_l2_l3_hdr_len]) +#define UIP_HBHO_BUF ((struct uip_hbho_hdr *)&uip_buf[uip_l2_l3_hdr_len]) +#define UIP_HBHO_NEXT_BUF ((struct uip_ext_hdr *)&uip_buf[uip_l2_l3_hdr_len + RPL_OP_BY_OP_LEN]) +#define UIP_EXT_HDR_OPT_BUF ((struct uip_ext_hdr_opt *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) #define UIP_EXT_HDR_OPT_PADN_BUF ((struct uip_ext_hdr_opt_padn *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) -#define UIP_EXT_HDR_OPT_RPL_BUF ((struct uip_ext_hdr_opt_rpl *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) +#define UIP_EXT_HDR_OPT_RPL_BUF ((struct uip_ext_hdr_opt_rpl *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) /************************************************************************/ int rpl_verify_header(int uip_ext_opt_offset) @@ -315,7 +315,7 @@ rpl_remove_header(void) UIP_IP_BUF->proto = UIP_HBHO_BUF->next; temp_len = UIP_IP_BUF->len[1]; uip_len -= UIP_HBHO_BUF->len + 8; - UIP_IP_BUF->len[1] -= (UIP_HBHO_BUF->len + 8); + UIP_IP_BUF->len[1] -= UIP_HBHO_BUF->len + 8; if(UIP_IP_BUF->len[1] > temp_len) { UIP_IP_BUF->len[0]--; } diff --git a/core/net/rpl/rpl.c b/core/net/rpl/rpl.c index 43e30ca06..b58d8b04e 100644 --- a/core/net/rpl/rpl.c +++ b/core/net/rpl/rpl.c @@ -57,15 +57,6 @@ rpl_stats_t rpl_stats; /************************************************************************/ extern uip_ds6_route_t uip_ds6_routing_table[UIP_DS6_ROUTE_NB]; - -#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) -#define UIP_EXT_BUF ((struct uip_ext_hdr *)&uip_buf[uip_l2_l3_hdr_len]) -#define UIP_HBHO_BUF ((struct uip_hbho_hdr *)&uip_buf[uip_l2_l3_hdr_len]) -#define UIP_HBHO_NEXT_BUF ((struct uip_ext_hdr *)&uip_buf[uip_l2_l3_hdr_len + RPL_OP_BY_OP_LEN]) -#define UIP_EXT_HDR_OPT_BUF ((struct uip_ext_hdr_opt *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) -#define UIP_EXT_HDR_OPT_PADN_BUF ((struct uip_ext_hdr_opt_padn *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) -#define UIP_EXT_HDR_OPT_RPL_BUF ((struct uip_ext_hdr_opt_rpl *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) - /************************************************************************/ void rpl_purge_routes(void) From 7c808081d65da27061005c34affed82f1374f25b Mon Sep 17 00:00:00 2001 From: Nicolas Tsiftes Date: Wed, 23 Nov 2011 14:36:50 +0100 Subject: [PATCH 19/25] Coding style --- core/net/rpl/rpl-ext-header.c | 71 ++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 35 deletions(-) mode change 100644 => 100755 core/net/rpl/rpl-ext-header.c diff --git a/core/net/rpl/rpl-ext-header.c b/core/net/rpl/rpl-ext-header.c old mode 100644 new mode 100755 index fa3ca57e3..1c756a2f2 --- a/core/net/rpl/rpl-ext-header.c +++ b/core/net/rpl/rpl-ext-header.c @@ -133,6 +133,7 @@ rpl_update_header_empty(void) uip_ext_opt_offset = 2; PRINTF("RPL: Verifying the presence of the RPL header option\n"); + switch(UIP_IP_BUF->proto) { case UIP_PROTO_HBHO: if(UIP_HBHO_BUF->len != RPL_OP_BY_OP_LEN - 8) { @@ -189,13 +190,13 @@ rpl_update_header_empty(void) int rpl_update_header_final(uip_ipaddr_t *addr) { + rpl_parent_t *parent; int uip_ext_opt_offset; int last_uip_ext_len; - last_uip_ext_len=uip_ext_len; - uip_ext_len=0; + last_uip_ext_len = uip_ext_len; + uip_ext_len = 0; uip_ext_opt_offset = 2; - rpl_parent_t *parent; if(UIP_IP_BUF->proto == UIP_PROTO_HBHO) { if(UIP_HBHO_BUF->len != RPL_OP_BY_OP_LEN - 8) { @@ -277,19 +278,19 @@ rpl_add_header(rpl_instance_t *instance, int down) } switch(UIP_EXT_HDR_OPT_BUF->type) { - case UIP_EXT_HDR_OPT_RPL: - PRINTF("RPL: Updating RPL option\n"); - UIP_EXT_HDR_OPT_RPL_BUF->opt_type = UIP_EXT_HDR_OPT_RPL; - UIP_EXT_HDR_OPT_RPL_BUF->opt_len = RPL_HDR_OPT_LEN; - UIP_EXT_HDR_OPT_RPL_BUF->flags = RPL_HDR_OPT_DOWN&(down<instance = instance->instance_id; - UIP_EXT_HDR_OPT_RPL_BUF->senderrank = instance->current_dag->rank; - uip_ext_len = last_uip_ext_len; - return 1; - default: - PRINTF("RPL: Multi Hop-by-hop options not implemented\n"); - uip_ext_len = last_uip_ext_len; - return 0; + case UIP_EXT_HDR_OPT_RPL: + PRINTF("RPL: Updating RPL option\n"); + UIP_EXT_HDR_OPT_RPL_BUF->opt_type = UIP_EXT_HDR_OPT_RPL; + UIP_EXT_HDR_OPT_RPL_BUF->opt_len = RPL_HDR_OPT_LEN; + UIP_EXT_HDR_OPT_RPL_BUF->flags = RPL_HDR_OPT_DOWN&(down<instance = instance->instance_id; + UIP_EXT_HDR_OPT_RPL_BUF->senderrank = instance->current_dag->rank; + uip_ext_len = last_uip_ext_len; + return 1; + default: + PRINTF("RPL: Multi Hop-by-hop options not implemented\n"); + uip_ext_len = last_uip_ext_len; + return 0; } } /************************************************************************/ @@ -310,19 +311,19 @@ rpl_remove_header(void) PRINTF("RPL: Verifying the presence of the RPL header option\n"); switch(UIP_IP_BUF->proto){ - case UIP_PROTO_HBHO: - PRINTF("RPL: Removing the present RPL header option\n"); - UIP_IP_BUF->proto = UIP_HBHO_BUF->next; - temp_len = UIP_IP_BUF->len[1]; - uip_len -= UIP_HBHO_BUF->len + 8; - UIP_IP_BUF->len[1] -= UIP_HBHO_BUF->len + 8; - if(UIP_IP_BUF->len[1] > temp_len) { - UIP_IP_BUF->len[0]--; - } - memmove(UIP_EXT_BUF, UIP_HBHO_NEXT_BUF, uip_len - UIP_IPH_LEN); - break; - default: - PRINTF("RPL: No Hop-by-Hop Option found\n"); + case UIP_PROTO_HBHO: + PRINTF("RPL: Removing the present RPL header option\n"); + UIP_IP_BUF->proto = UIP_HBHO_BUF->next; + temp_len = UIP_IP_BUF->len[1]; + uip_len -= UIP_HBHO_BUF->len + 8; + UIP_IP_BUF->len[1] -= UIP_HBHO_BUF->len + 8; + if(UIP_IP_BUF->len[1] > temp_len) { + UIP_IP_BUF->len[0]--; + } + memmove(UIP_EXT_BUF, UIP_HBHO_NEXT_BUF, uip_len - UIP_IPH_LEN); + break; + default: + PRINTF("RPL: No Hop-by-Hop Option found\n"); } } /************************************************************************/ @@ -338,12 +339,12 @@ rpl_invert_header(void) PRINTF("RPL: Verifying the presence of the RPL header option\n"); switch(UIP_IP_BUF->proto) { - case UIP_PROTO_HBHO: - break; - default: - PRINTF("RPL: No Hop-by-Hop Option found\n"); - uip_ext_len = last_uip_ext_len; - return 0; + case UIP_PROTO_HBHO: + break; + default: + PRINTF("RPL: No Hop-by-Hop Option found\n"); + uip_ext_len = last_uip_ext_len; + return 0; } switch (UIP_EXT_HDR_OPT_BUF->type) { case UIP_EXT_HDR_OPT_RPL: From 5c0100c9799ae5b7f86848f0a52bd5c546378a6e Mon Sep 17 00:00:00 2001 From: Nicolas Tsiftes Date: Fri, 2 Dec 2011 15:54:49 +0100 Subject: [PATCH 20/25] Use rpl headers. --- core/net/tcpip.c | 13 +++++-------- core/net/uip6.c | 8 +++----- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/core/net/tcpip.c b/core/net/tcpip.c index 552f6ccce..4597d682a 100644 --- a/core/net/tcpip.c +++ b/core/net/tcpip.c @@ -78,17 +78,16 @@ void uip_log(char *msg); #ifdef UIP_FALLBACK_INTERFACE extern struct uip_fallback_interface UIP_FALLBACK_INTERFACE; #endif + #if UIP_CONF_IPV6_RPL -void rpl_init(void); -int rpl_update_header_final(uip_ipaddr_t *addr); -#endif /* UIP_CONF_IPV6_RPL */ +#include "rpl/rpl.h" +#endif + process_event_t tcpip_event; #if UIP_CONF_ICMP6 process_event_t tcpip_icmp6_event; #endif /* UIP_CONF_ICMP6 */ -/*static struct tcpip_event_args ev_args;*/ - /*periodic check of active connections*/ static struct etimer periodic; @@ -601,15 +600,13 @@ tcpip_ipv6_output(void) } /* end of next hop determination */ #if UIP_CONF_IPV6_RPL - if (rpl_update_header_final(nexthop)) { + if(rpl_update_header_final(nexthop)) { uip_len = 0; return; } #endif /* UIP_CONF_IPV6_RPL */ if((nbr = uip_ds6_nbr_lookup(nexthop)) == NULL) { - // printf("add1 %d\n", nexthop->u8[15]); if((nbr = uip_ds6_nbr_add(nexthop, NULL, 0, NBR_INCOMPLETE)) == NULL) { - // printf("add n\n"); uip_len = 0; return; } else { diff --git a/core/net/uip6.c b/core/net/uip6.c index 32c154d6a..9c121c3bd 100644 --- a/core/net/uip6.c +++ b/core/net/uip6.c @@ -95,9 +95,7 @@ #endif #if UIP_CONF_IPV6_RPL -void uip_rpl_input(void); -void rpl_update_header_empty(void); -int rpl_verify_header(int uip_ext_opt_offset); +#include "rpl/rpl.h" #endif /* UIP_CONF_IPV6_RPL */ #if UIP_LOGGING == 1 @@ -854,7 +852,7 @@ ext_hdr_options_process(void) #if UIP_CONF_IPV6_RPL case UIP_EXT_HDR_OPT_RPL: PRINTF("Processing RPL option\n"); - if (rpl_verify_header(uip_ext_opt_offset)) { + if(rpl_verify_header(uip_ext_opt_offset)) { PRINTF("RPL Option Error : Dropping Packet"); return 1; } @@ -1120,7 +1118,7 @@ uip_process(u8_t flag) uip_next_hdr = &UIP_IP_BUF->proto; uip_ext_len = 0; uip_ext_bitmap = 0; - if (*uip_next_hdr == UIP_PROTO_HBHO) { + if(*uip_next_hdr == UIP_PROTO_HBHO) { #if UIP_CONF_IPV6_CHECKS uip_ext_bitmap |= UIP_EXT_HDR_BITMAP_HBHO; #endif /*UIP_CONF_IPV6_CHECKS*/ From ac869185c0494af074f856c4e1498fb7ecb9450c Mon Sep 17 00:00:00 2001 From: Nicolas Tsiftes Date: Fri, 2 Dec 2011 15:55:07 +0100 Subject: [PATCH 21/25] Refactored header management. --- core/net/rpl/rpl-ext-header.c | 141 +++++++++------------------------- core/net/rpl/rpl-private.h | 16 ++-- core/net/rpl/rpl.h | 19 ++--- 3 files changed, 53 insertions(+), 123 deletions(-) diff --git a/core/net/rpl/rpl-ext-header.c b/core/net/rpl/rpl-ext-header.c index 1c756a2f2..5209aeff5 100755 --- a/core/net/rpl/rpl-ext-header.c +++ b/core/net/rpl/rpl-ext-header.c @@ -36,7 +36,10 @@ * \file * Management of extension headers for ContikiRPL. * - * \author Vincent Brillault + * \author Vincent Brillault , + * Joakim Eriksson , + * Niclas Finne , + * Nicolas Tsiftes . */ #include "net/uip.h" @@ -54,7 +57,7 @@ #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) #define UIP_EXT_BUF ((struct uip_ext_hdr *)&uip_buf[uip_l2_l3_hdr_len]) #define UIP_HBHO_BUF ((struct uip_hbho_hdr *)&uip_buf[uip_l2_l3_hdr_len]) -#define UIP_HBHO_NEXT_BUF ((struct uip_ext_hdr *)&uip_buf[uip_l2_l3_hdr_len + RPL_OP_BY_OP_LEN]) +#define UIP_HBHO_NEXT_BUF ((struct uip_ext_hdr *)&uip_buf[uip_l2_l3_hdr_len + RPL_HOP_BY_HOP_LEN]) #define UIP_EXT_HDR_OPT_BUF ((struct uip_ext_hdr_opt *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) #define UIP_EXT_HDR_OPT_PADN_BUF ((struct uip_ext_hdr_opt_padn *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) #define UIP_EXT_HDR_OPT_RPL_BUF ((struct uip_ext_hdr_opt_rpl *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) @@ -120,13 +123,35 @@ rpl_verify_header(int uip_ext_opt_offset) return 0; } /************************************************************************/ +static void +set_rpl_opt(unsigned uip_ext_opt_offset) +{ + uint8_t temp_len; + + memmove(UIP_HBHO_NEXT_BUF, UIP_EXT_BUF, uip_len - UIP_IPH_LEN); + memset(UIP_HBHO_BUF, 0, RPL_HOP_BY_HOP_LEN); + UIP_HBHO_BUF->next = UIP_IP_BUF->proto; + UIP_IP_BUF->proto = UIP_PROTO_HBHO; + UIP_HBHO_BUF->len = RPL_HOP_BY_HOP_LEN - 8; + UIP_EXT_HDR_OPT_RPL_BUF->opt_type = UIP_EXT_HDR_OPT_RPL; + UIP_EXT_HDR_OPT_RPL_BUF->opt_len = RPL_HDR_OPT_LEN; + UIP_EXT_HDR_OPT_RPL_BUF->flags = 0 ; + UIP_EXT_HDR_OPT_RPL_BUF->instance = 0 ; + UIP_EXT_HDR_OPT_RPL_BUF->senderrank = 0 ; + uip_len += RPL_HOP_BY_HOP_LEN; + temp_len = UIP_IP_BUF->len[1]; + UIP_IP_BUF->len[1] += UIP_HBHO_BUF->len + 8; + if(UIP_IP_BUF->len[1] < temp_len) { + UIP_IP_BUF->len[0]++; + } +} +/************************************************************************/ void rpl_update_header_empty(void) { rpl_instance_t *instance; int uip_ext_opt_offset; int last_uip_ext_len; - u8_t temp_len; last_uip_ext_len = uip_ext_len; uip_ext_len = 0; @@ -136,7 +161,7 @@ rpl_update_header_empty(void) switch(UIP_IP_BUF->proto) { case UIP_PROTO_HBHO: - if(UIP_HBHO_BUF->len != RPL_OP_BY_OP_LEN - 8) { + if(UIP_HBHO_BUF->len != RPL_HOP_BY_HOP_LEN - 8) { PRINTF("RPL: Non RPL Hop-by-hop options support not implemented\n"); uip_ext_len = last_uip_ext_len; return; @@ -149,28 +174,13 @@ rpl_update_header_empty(void) break; default: PRINTF("RPL: No hop-by-hop option found, creating it\n"); - if(uip_len + RPL_OP_BY_OP_LEN > UIP_LINK_MTU) { + if(uip_len + RPL_HOP_BY_HOP_LEN > UIP_LINK_MTU) { PRINTF("RPL: Packet too long: impossible to add hop-by-hop option\n"); uip_ext_len = last_uip_ext_len; return; } - memmove(UIP_HBHO_NEXT_BUF, UIP_EXT_BUF, uip_len - UIP_IPH_LEN); - memset(UIP_HBHO_BUF, 0, RPL_OP_BY_OP_LEN); - UIP_HBHO_BUF->next = UIP_IP_BUF->proto; - UIP_IP_BUF->proto = UIP_PROTO_HBHO; - UIP_HBHO_BUF->len = RPL_OP_BY_OP_LEN - 8; - UIP_EXT_HDR_OPT_RPL_BUF->opt_type = UIP_EXT_HDR_OPT_RPL; - UIP_EXT_HDR_OPT_RPL_BUF->opt_len = RPL_HDR_OPT_LEN; - UIP_EXT_HDR_OPT_RPL_BUF->flags = 0; - UIP_EXT_HDR_OPT_RPL_BUF->instance = 0; - UIP_EXT_HDR_OPT_RPL_BUF->senderrank = 0; - uip_len += RPL_OP_BY_OP_LEN; - temp_len = UIP_IP_BUF->len[1]; - UIP_IP_BUF->len[1] += UIP_HBHO_BUF->len + 8; - if(UIP_IP_BUF->len[1] < temp_len) { - UIP_IP_BUF->len[0]++; - } - uip_ext_len = last_uip_ext_len + RPL_OP_BY_OP_LEN; + set_rpl_opt(uip_ext_opt_offset); + uip_ext_len = last_uip_ext_len + RPL_HOP_BY_HOP_LEN; return; } @@ -199,7 +209,7 @@ rpl_update_header_final(uip_ipaddr_t *addr) uip_ext_opt_offset = 2; if(UIP_IP_BUF->proto == UIP_PROTO_HBHO) { - if(UIP_HBHO_BUF->len != RPL_OP_BY_OP_LEN - 8) { + if(UIP_HBHO_BUF->len != RPL_HOP_BY_HOP_LEN - 8) { PRINTF("RPL: Non RPL Hop-by-hop options support not implemented\n"); uip_ext_len = last_uip_ext_len; return 0; @@ -225,86 +235,11 @@ rpl_update_header_final(uip_ipaddr_t *addr) return 0; } /************************************************************************/ -int -rpl_add_header(rpl_instance_t *instance, int down) -{ - int uip_ext_opt_offset; - int last_uip_ext_len; - u8_t temp_len; - - last_uip_ext_len = uip_ext_len; - uip_ext_len = 0; - uip_ext_opt_offset = 2; - - if(instance == NULL || !instance->used || !instance->current_dag->joined) { - PRINTF("Unable to add RPL hop-by-hop extension header: incorrect instance\n"); - return 0; - } - - PRINTF("RPL: Verifying the presence of the RPL header option\n"); - switch(UIP_IP_BUF->proto) { - case UIP_PROTO_HBHO: - if(UIP_HBHO_BUF->len != RPL_OP_BY_OP_LEN - 8) { - PRINTF("RPL: Non RPL Hop-by-hop options support not implemented\n"); - uip_ext_len = last_uip_ext_len; - return 0; - } - break; - default: - PRINTF("RPL: No hop-by-hop option found, creating it\n"); - if(uip_len + RPL_OP_BY_OP_LEN >UIP_LINK_MTU) { - PRINTF("RPL: Packet too long: impossible to add hop-by-hop option\n"); - uip_ext_len = last_uip_ext_len; - return 0; - } - memmove(UIP_HBHO_NEXT_BUF, UIP_EXT_BUF, uip_len - UIP_IPH_LEN); - memset(UIP_HBHO_BUF, 0, RPL_OP_BY_OP_LEN); - UIP_HBHO_BUF->next = UIP_IP_BUF->proto; - UIP_IP_BUF->proto = UIP_PROTO_HBHO; - UIP_HBHO_BUF->len = RPL_OP_BY_OP_LEN - 8; - UIP_EXT_HDR_OPT_RPL_BUF->opt_type = UIP_EXT_HDR_OPT_RPL; - UIP_EXT_HDR_OPT_RPL_BUF->opt_len = RPL_HDR_OPT_LEN; - UIP_EXT_HDR_OPT_RPL_BUF->flags = RPL_HDR_OPT_DOWN & (down << RPL_HDR_OPT_DOWN_SHIFT); - UIP_EXT_HDR_OPT_RPL_BUF->instance = instance->instance_id; - UIP_EXT_HDR_OPT_RPL_BUF->senderrank = instance->current_dag->rank; - uip_len += RPL_OP_BY_OP_LEN; - temp_len = UIP_IP_BUF->len[1]; - UIP_IP_BUF->len[1] += UIP_HBHO_BUF->len + 8; - if(UIP_IP_BUF->len[1] < temp_len) { - UIP_IP_BUF->len[0]++; - } - uip_ext_len = last_uip_ext_len + RPL_OP_BY_OP_LEN; - return 1; - } - - switch(UIP_EXT_HDR_OPT_BUF->type) { - case UIP_EXT_HDR_OPT_RPL: - PRINTF("RPL: Updating RPL option\n"); - UIP_EXT_HDR_OPT_RPL_BUF->opt_type = UIP_EXT_HDR_OPT_RPL; - UIP_EXT_HDR_OPT_RPL_BUF->opt_len = RPL_HDR_OPT_LEN; - UIP_EXT_HDR_OPT_RPL_BUF->flags = RPL_HDR_OPT_DOWN&(down<instance = instance->instance_id; - UIP_EXT_HDR_OPT_RPL_BUF->senderrank = instance->current_dag->rank; - uip_ext_len = last_uip_ext_len; - return 1; - default: - PRINTF("RPL: Multi Hop-by-hop options not implemented\n"); - uip_ext_len = last_uip_ext_len; - return 0; - } -} -/************************************************************************/ -int -rpl_add_header_root(void) -{ - return rpl_add_header(default_instance, 1); -} -/************************************************************************/ void rpl_remove_header(void) { int last_uip_ext_len; - u8_t temp_len; + uint8_t temp_len; last_uip_ext_len = uip_ext_len; uip_ext_len = 0; @@ -327,11 +262,11 @@ rpl_remove_header(void) } } /************************************************************************/ -u8_t +uint8_t rpl_invert_header(void) { - u8_t uip_ext_opt_offset; - u8_t last_uip_ext_len; + uint8_t uip_ext_opt_offset; + uint8_t last_uip_ext_len; last_uip_ext_len = uip_ext_len; uip_ext_len = 0; @@ -353,7 +288,7 @@ rpl_invert_header(void) UIP_EXT_HDR_OPT_RPL_BUF->flags ^= RPL_HDR_OPT_DOWN; UIP_EXT_HDR_OPT_RPL_BUF->senderrank = rpl_get_instance(UIP_EXT_HDR_OPT_RPL_BUF->instance)->current_dag->rank; uip_ext_len = last_uip_ext_len; - return RPL_OP_BY_OP_LEN; + return RPL_HOP_BY_HOP_LEN; default: PRINTF("RPL: Multi Hop-by-hop options not implemented\n"); uip_ext_len = last_uip_ext_len; diff --git a/core/net/rpl/rpl-private.h b/core/net/rpl/rpl-private.h index 8b2f83dbb..1936c124a 100644 --- a/core/net/rpl/rpl-private.h +++ b/core/net/rpl/rpl-private.h @@ -94,6 +94,16 @@ #define RPL_DAO_K_FLAG 0x80 /* DAO ACK requested */ #define RPL_DAO_D_FLAG 0x40 /* DODAG ID present */ /*---------------------------------------------------------------------------*/ +/* RPL IPv6 extension header option. */ +#define RPL_HDR_OPT_LEN 4 +#define RPL_HOP_BY_HOP_LEN (RPL_HDR_OPT_LEN + 2 + 2) +#define RPL_HDR_OPT_DOWN 0x80 +#define RPL_HDR_OPT_DOWN_SHIFT 7 +#define RPL_HDR_OPT_RANK_ERR 0x40 +#define RPL_HDR_OPT_RANK_ERR_SHIFT 6 +#define RPL_HDR_OPT_FWD_ERR 0x20 +#define RPL_HDR_OPT_FWD_ERR_SHIFT 5 +/*---------------------------------------------------------------------------*/ /* Default values for RPL constants and variables. */ /* The default value for the DAO timer. */ @@ -250,12 +260,6 @@ void dis_output(uip_ipaddr_t *addr); void dio_output(rpl_instance_t *, uip_ipaddr_t *uc_addr); void dao_output(rpl_parent_t *, uint8_t lifetime); void dao_ack_output(rpl_instance_t *, uip_ipaddr_t *, uint8_t); -void uip_rpl_input(void); - -/* RPL Header Option */ -int rpl_verify_header(int uip_ext_opt_offset); -void rpl_update_header_empty(); -int rpl_update_header_final(uip_ipaddr_t *addr); /* RPL logic functions. */ void rpl_join_dag(uip_ipaddr_t *from, rpl_dio_t *dio); diff --git a/core/net/rpl/rpl.h b/core/net/rpl/rpl.h index 9dcfba586..77d577988 100644 --- a/core/net/rpl/rpl.h +++ b/core/net/rpl/rpl.h @@ -144,17 +144,6 @@ typedef uint16_t rpl_ocp_t; ((B > RPL_LOLLIPOP_CIRCULAR_REGION )?\ 1:\ RPL_LOLLIPOP_GREATER_THAN_LOCAL(A,B))) - -/*---------------------------------------------------------------------------*/ -/* RPL IPv6 extension header option. */ -#define RPL_HDR_OPT_LEN 4 -#define RPL_OP_BY_OP_LEN RPL_HDR_OPT_LEN+2+2 -#define RPL_HDR_OPT_DOWN 0x80 -#define RPL_HDR_OPT_DOWN_SHIFT 7 -#define RPL_HDR_OPT_RANK_ERR 0x40 -#define RPL_HDR_OPT_RANK_ERR_SHIFT 6 -#define RPL_HDR_OPT_FWD_ERR 0x20 -#define RPL_HDR_OPT_FWD_ERR_SHIFT 5 /*---------------------------------------------------------------------------*/ /* DAG Metric Container Object Types, to be confirmed by IANA. */ #define RPL_DAG_MC_NONE 0 /* Local identifier for empty MC */ @@ -334,6 +323,7 @@ struct rpl_instance { /*---------------------------------------------------------------------------*/ /* Public RPL functions. */ void rpl_init(void); +void uip_rpl_input(void); rpl_dag_t *rpl_set_root(uint8_t instance_id, uip_ipaddr_t * dag_id); int rpl_set_prefix(rpl_dag_t *dag, uip_ipaddr_t *prefix, unsigned len); int rpl_repair_root(uint8_t instance_id); @@ -341,9 +331,10 @@ int rpl_set_default_route(rpl_instance_t *instance, uip_ipaddr_t *from); rpl_dag_t *rpl_get_any_dag(void); rpl_dag_t *rpl_get_dodag(uint8_t instance_id, uip_ipaddr_t *dag_id); rpl_instance_t *rpl_get_instance(uint8_t instance_id); -int rpl_add_header(rpl_instance_t *instance, int down); -int rpl_add_header_root(void); +void rpl_update_header_empty(void); +int rpl_update_header_final(uip_ipaddr_t *addr); +int rpl_verify_header(int); void rpl_remove_header(void); -u8_t rpl_invert_header(void); +uint8_t rpl_invert_header(void); /*---------------------------------------------------------------------------*/ #endif /* RPL_H */ From 23a280e5eb67cfaadc0daf85b4529cfa1008cb29 Mon Sep 17 00:00:00 2001 From: Nicolas Tsiftes Date: Fri, 2 Dec 2011 16:16:42 +0100 Subject: [PATCH 22/25] Refactored loop detection. --- core/net/rpl/rpl-ext-header.c | 57 ++++++++++++++++------------------- 1 file changed, 26 insertions(+), 31 deletions(-) diff --git a/core/net/rpl/rpl-ext-header.c b/core/net/rpl/rpl-ext-header.c index 5209aeff5..827853b60 100755 --- a/core/net/rpl/rpl-ext-header.c +++ b/core/net/rpl/rpl-ext-header.c @@ -66,6 +66,8 @@ int rpl_verify_header(int uip_ext_opt_offset) { rpl_instance_t *instance; + long diff; + int down; if(UIP_EXT_HDR_OPT_RPL_BUF->opt_len != RPL_HDR_OPT_LEN) { PRINTF("RPL: Bad header option! (wrong length)\n"); @@ -90,32 +92,24 @@ rpl_verify_header(int uip_ext_opt_offset) return 1; } + down = 0; if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_DOWN) { - PRINTF("RPL: Packet going down :\n"); - if(UIP_EXT_HDR_OPT_RPL_BUF->senderrank > instance->current_dag->rank) { - PRINTF("RPL: Loop detected: Sender rank > our rank\n"); - if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_RANK_ERR) { - PRINTF("RPL: Loop detected !\n"); - /* We should try to repair it, not implemented for the moment */ - return 3; - } - PRINTF("RPL: Single error tolerated\n"); - UIP_EXT_HDR_OPT_RPL_BUF->flags |= RPL_HDR_OPT_RANK_ERR; - return 0; - } - } else { - PRINTF("RPL: Packet going up :"); - if(UIP_EXT_HDR_OPT_RPL_BUF->senderrank < instance->current_dag->rank) { - PRINTF("RPL: Rank error: Sender rank < our rank\n"); - if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_RANK_ERR) { - PRINTF("RPL: Loop detected !\n"); - /* We should try to repair it, not implemented for the moment */ - return 3; - } - PRINTF("RPL: Single error tolerated\n"); - UIP_EXT_HDR_OPT_RPL_BUF->flags |= RPL_HDR_OPT_RANK_ERR; - return 0; + down = 1; + } + + PRINTF("RPL: Packet going %s\n", down == 1 ? "down" : "up"); + + diff = UIP_EXT_HDR_OPT_RPL_BUF->senderrank - instance->current_dag->rank; + if((down && diff > 0) || (!down && diff < 0)) { + PRINTF("RPL: Loop detected\n"); + if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_RANK_ERR) { + PRINTF("RPL: Rank error signalled in RPL option!\n"); + /* We should try to repair it, not implemented for the moment */ + return 3; } + PRINTF("RPL: Single error tolerated\n"); + UIP_EXT_HDR_OPT_RPL_BUF->flags |= RPL_HDR_OPT_RANK_ERR; + return 0; } PRINTF("RPL: Rank OK\n"); @@ -135,9 +129,9 @@ set_rpl_opt(unsigned uip_ext_opt_offset) UIP_HBHO_BUF->len = RPL_HOP_BY_HOP_LEN - 8; UIP_EXT_HDR_OPT_RPL_BUF->opt_type = UIP_EXT_HDR_OPT_RPL; UIP_EXT_HDR_OPT_RPL_BUF->opt_len = RPL_HDR_OPT_LEN; - UIP_EXT_HDR_OPT_RPL_BUF->flags = 0 ; - UIP_EXT_HDR_OPT_RPL_BUF->instance = 0 ; - UIP_EXT_HDR_OPT_RPL_BUF->senderrank = 0 ; + UIP_EXT_HDR_OPT_RPL_BUF->flags = 0; + UIP_EXT_HDR_OPT_RPL_BUF->instance = 0; + UIP_EXT_HDR_OPT_RPL_BUF->senderrank = 0; uip_len += RPL_HOP_BY_HOP_LEN; temp_len = UIP_IP_BUF->len[1]; UIP_IP_BUF->len[1] += UIP_HBHO_BUF->len + 8; @@ -247,7 +241,7 @@ rpl_remove_header(void) PRINTF("RPL: Verifying the presence of the RPL header option\n"); switch(UIP_IP_BUF->proto){ case UIP_PROTO_HBHO: - PRINTF("RPL: Removing the present RPL header option\n"); + PRINTF("RPL: Removing the RPL header option\n"); UIP_IP_BUF->proto = UIP_HBHO_BUF->next; temp_len = UIP_IP_BUF->len[1]; uip_len -= UIP_HBHO_BUF->len + 8; @@ -258,7 +252,7 @@ rpl_remove_header(void) memmove(UIP_EXT_BUF, UIP_HBHO_NEXT_BUF, uip_len - UIP_IPH_LEN); break; default: - PRINTF("RPL: No Hop-by-Hop Option found\n"); + PRINTF("RPL: No hop-by-hop Option found\n"); } } /************************************************************************/ @@ -277,13 +271,14 @@ rpl_invert_header(void) case UIP_PROTO_HBHO: break; default: - PRINTF("RPL: No Hop-by-Hop Option found\n"); + PRINTF("RPL: No hop-by-hop Option found\n"); uip_ext_len = last_uip_ext_len; return 0; } + switch (UIP_EXT_HDR_OPT_BUF->type) { case UIP_EXT_HDR_OPT_RPL: - PRINTF("RPL: Updating RPL option (Inverting Up<->Down)\n"); + PRINTF("RPL: Updating RPL option (switching direction)\n"); UIP_EXT_HDR_OPT_RPL_BUF->flags &= RPL_HDR_OPT_DOWN; UIP_EXT_HDR_OPT_RPL_BUF->flags ^= RPL_HDR_OPT_DOWN; UIP_EXT_HDR_OPT_RPL_BUF->senderrank = rpl_get_instance(UIP_EXT_HDR_OPT_RPL_BUF->instance)->current_dag->rank; From 077eba80e194da5b9ee87077fc5f9b5f59da9a1d Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Fri, 2 Dec 2011 17:07:27 +0100 Subject: [PATCH 23/25] code style --- core/net/tcpip.c | 93 ++++++++++++++++++------------------------------ 1 file changed, 34 insertions(+), 59 deletions(-) diff --git a/core/net/tcpip.c b/core/net/tcpip.c index 4597d682a..305214f35 100644 --- a/core/net/tcpip.c +++ b/core/net/tcpip.c @@ -27,10 +27,8 @@ * SUCH DAMAGE. * * This file is part of the Contiki operating system. - * - * - * $Id: tcpip.c,v 1.30 2010/10/29 05:36:07 adamdunkels Exp $ */ + /** * \file * Code for tunnelling uIP packets over the Rime mesh routing module @@ -39,29 +37,20 @@ * \author Mathilde Durvy (IPv6 related code) * \author Julien Abeille (IPv6 related code) */ + #include "contiki-net.h" - #include "net/uip-split.h" - #include "net/uip-packetqueue.h" -#include - #if UIP_CONF_IPV6 #include "net/uip-nd6.h" #include "net/uip-ds6.h" #endif -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINT6ADDR(addr) PRINTF(" %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x ", ((u8_t *)addr)[0], ((u8_t *)addr)[1], ((u8_t *)addr)[2], ((u8_t *)addr)[3], ((u8_t *)addr)[4], ((u8_t *)addr)[5], ((u8_t *)addr)[6], ((u8_t *)addr)[7], ((u8_t *)addr)[8], ((u8_t *)addr)[9], ((u8_t *)addr)[10], ((u8_t *)addr)[11], ((u8_t *)addr)[12], ((u8_t *)addr)[13], ((u8_t *)addr)[14], ((u8_t *)addr)[15]) -#define PRINTLLADDR(lladdr) PRINTF(" %02x:%02x:%02x:%02x:%02x:%02x ",lladdr->addr[0], lladdr->addr[1], lladdr->addr[2], lladdr->addr[3],lladdr->addr[4], lladdr->addr[5]) -#else -#define PRINTF(...) -#define PRINT6ADDR(addr) -#endif +#include + +#define DEBUG DEBUG_NONE +#include "net/uip-debug.h" #if UIP_LOGGING #include @@ -88,11 +77,11 @@ process_event_t tcpip_event; process_event_t tcpip_icmp6_event; #endif /* UIP_CONF_ICMP6 */ -/*periodic check of active connections*/ +/* Periodic check of active connections. */ static struct etimer periodic; #if UIP_CONF_IPV6 && UIP_CONF_IPV6_REASSEMBLY -/*timer for reassembly*/ +/* Timer for reassembly. */ extern struct etimer uip_reass_timer; #endif @@ -412,21 +401,19 @@ eventhandler(process_event_t ev, process_data_t data) cptr->appstate.p = PROCESS_NONE; cptr->tcpstateflags = UIP_CLOSED; } - } - } #endif /* UIP_TCP */ #if UIP_UDP { register struct uip_udp_conn *cptr; + for(cptr = &uip_udp_conns[0]; cptr < &uip_udp_conns[UIP_UDP_CONNS]; ++cptr) { if(cptr->appstate.p == p) { cptr->lport = 0; } } - } #endif /* UIP_UDP */ break; @@ -482,7 +469,7 @@ eventhandler(process_event_t ev, process_data_t data) uip_ds6_periodic(); tcpip_ipv6_output(); }*/ -#if !UIP_CONF_ROUTER +#if !UIP_CONF_ROUTER if(data == &uip_ds6_timer_rs && etimer_expired(&uip_ds6_timer_rs)){ uip_ds6_send_rs(); @@ -551,22 +538,24 @@ void tcpip_ipv6_output(void) { uip_ds6_nbr_t *nbr = NULL; - uip_ipaddr_t* nexthop; - + uip_ipaddr_t *nexthop; + if(uip_len == 0) { return; } - + if(uip_len > UIP_LINK_MTU) { UIP_LOG("tcpip_ipv6_output: Packet to big"); uip_len = 0; return; } + if(uip_is_addr_unspecified(&UIP_IP_BUF->destipaddr)){ UIP_LOG("tcpip_ipv6_output: Destination address unspecified"); uip_len = 0; return; } + if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) { /* Next hop determination */ nbr = NULL; @@ -583,14 +572,13 @@ tcpip_ipv6_output(void) if(uip_ext_len > 0) { uint8_t proto = *((uint8_t *)UIP_IP_BUF + 40); remove_ext_hdr(); - /* this should be copied from the ext header... */ + /* This should be copied from the ext header... */ UIP_IP_BUF->proto = proto; } UIP_FALLBACK_INTERFACE.output(); - #else PRINTF("tcpip_ipv6_output: Destination off-link but no route\n"); -#endif +#endif /* !UIP_FALLBACK_INTERFACE */ uip_len = 0; return; } @@ -598,7 +586,7 @@ tcpip_ipv6_output(void) nexthop = &locrt->nexthop; } } - /* end of next hop determination */ + /* End of next hop determination */ #if UIP_CONF_IPV6_RPL if(rpl_update_header_final(nexthop)) { uip_len = 0; @@ -611,7 +599,7 @@ tcpip_ipv6_output(void) return; } else { #if UIP_CONF_IPV6_QUEUE_PKT - /* copy outgoing pkt in the queuing buffer for later transmmit */ + /* Copy outgoing pkt in the queuing buffer for later transmit. */ if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) { memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, uip_len); uip_packetqueue_set_buflen(&nbr->packethandle, uip_len); @@ -629,59 +617,47 @@ tcpip_ipv6_output(void) uip_nd6_ns_output(NULL, NULL, &nbr->ipaddr); } - stimer_set(&(nbr->sendns), uip_ds6_if.retrans_timer / 1000); + stimer_set(&nbr->sendns, uip_ds6_if.retrans_timer / 1000); nbr->nscount = 1; } } else { if(nbr->state == NBR_INCOMPLETE) { PRINTF("tcpip_ipv6_output: nbr cache entry incomplete\n"); #if UIP_CONF_IPV6_QUEUE_PKT - /* copy outgoing pkt in the queuing buffer for later transmmit and set - the destination nbr to nbr */ + /* Copy outgoing pkt in the queuing buffer for later transmit and set + the destination nbr to nbr. */ if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) { memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, uip_len); uip_packetqueue_set_buflen(&nbr->packethandle, uip_len); } - /* memcpy(nbr->queue_buf, UIP_IP_BUF, uip_len); - nbr->queue_buf_len = uip_len;*/ uip_len = 0; #endif /*UIP_CONF_IPV6_QUEUE_PKT*/ return; } - /* if running NUD (nbc->state == STALE, DELAY, or PROBE ) keep - sending in parallel see rfc 4861 Node behavior in section 7.7.3*/ - + /* Send in parallel if we are running NUD (nbc state is either STALE, + DELAY, or PROBE). See RFC 4861, section 7.7.3 on node behavior. */ if(nbr->state == NBR_STALE) { nbr->state = NBR_DELAY; - stimer_set(&(nbr->reachable), - UIP_ND6_DELAY_FIRST_PROBE_TIME); + stimer_set(&nbr->reachable, UIP_ND6_DELAY_FIRST_PROBE_TIME); nbr->nscount = 0; PRINTF("tcpip_ipv6_output: nbr cache entry stale moving to delay\n"); } - - stimer_set(&(nbr->sendns), - uip_ds6_if.retrans_timer / 1000); - - tcpip_output(&(nbr->lladdr)); + stimer_set(&nbr->sendns, uip_ds6_if.retrans_timer / 1000); + tcpip_output(&nbr->lladdr); #if UIP_CONF_IPV6_QUEUE_PKT - /* Send the queued packets from here, may not be 100% perfect though. + /* + * Send the queued packets from here, may not be 100% perfect though. * This happens in a few cases, for example when instead of receiving a * NA after sendiong a NS, you receive a NS with SLLAO: the entry moves - *to STALE, and you must both send a NA and the queued packet + * to STALE, and you must both send a NA and the queued packet. */ - /* if(nbr->queue_buf_len != 0) { - uip_len = nbr->queue_buf_len; - memcpy(UIP_IP_BUF, nbr->queue_buf, uip_len); - nbr->queue_buf_len = 0; - tcpip_output(&(nbr->lladdr)); - }*/ if(uip_packetqueue_buflen(&nbr->packethandle) != 0) { uip_len = uip_packetqueue_buflen(&nbr->packethandle); memcpy(UIP_IP_BUF, uip_packetqueue_buf(&nbr->packethandle), uip_len); uip_packetqueue_free(&nbr->packethandle); - tcpip_output(&(nbr->lladdr)); + tcpip_output(&nbr->lladdr); } #endif /*UIP_CONF_IPV6_QUEUE_PKT*/ @@ -689,14 +665,13 @@ tcpip_ipv6_output(void) return; } } - - /*multicast IP destination address */ + + /* Multicast IP destination address. */ tcpip_output(NULL); uip_len = 0; uip_ext_len = 0; - } -#endif +#endif /* UIP_CONF_IPV6 */ /*---------------------------------------------------------------------------*/ #if UIP_UDP void From 1e61fca653f882f2727c0fe19a761aad1f4417f1 Mon Sep 17 00:00:00 2001 From: Nicolas Tsiftes Date: Thu, 8 Dec 2011 15:38:35 +0100 Subject: [PATCH 24/25] Fix coding style. --- core/net/neighbor-info.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/core/net/neighbor-info.c b/core/net/neighbor-info.c index ff2a1c319..c9e8c4080 100644 --- a/core/net/neighbor-info.c +++ b/core/net/neighbor-info.c @@ -107,7 +107,7 @@ neighbor_info_packet_sent(int status, int numtx) const rimeaddr_t *dest; link_metric_t packet_metric; #if UIP_DS6_LL_NUD - uip_ds6_nbr_t * nbr; + uip_ds6_nbr_t *nbr; #endif /* UIP_DS6_LL_NUD */ dest = packetbuf_addr(PACKETBUF_ADDR_RECEIVER); @@ -125,16 +125,12 @@ neighbor_info_packet_sent(int status, int numtx) case MAC_TX_OK: add_neighbor(dest); #if UIP_DS6_LL_NUD - nbr=uip_ds6_nbr_ll_lookup((uip_lladdr_t *) dest); - if (nbr!=NULL) { - PRINTF("neighbor-info : nbr state = %u\n",nbr->state); - } else { - PRINTF("neighbor-info : no nbr\n"); - } - if (nbr!=NULL && (nbr->state == STALE || nbr->state == DELAY || nbr->state == PROBE)) { + nbr = uip_ds6_nbr_ll_lookup((uip_lladdr_t *)dest); + if(nbr != NULL && + (nbr->state == STALE || nbr->state == DELAY || nbr->state == PROBE)) { nbr->state = REACHABLE; stimer_set(&nbr->reachable, UIP_ND6_REACHABLE_TIME / 1000); - PRINTF("neighbor-info : received a linklayer ack : "); + PRINTF("neighbor-info : received a link layer ACK : "); PRINTLLADDR((uip_lladdr_t *)dest); PRINTF(" is reachable.\n"); } From a4a7fd7dc0475a007c197607ced9544da4f7d254 Mon Sep 17 00:00:00 2001 From: Nicolas Tsiftes Date: Thu, 8 Dec 2011 15:42:19 +0100 Subject: [PATCH 25/25] Fix coding style. --- core/net/uip-ds6.c | 12 ++++++------ core/net/uip-icmp6.c | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/core/net/uip-ds6.c b/core/net/uip-ds6.c index b30461bac..22ebea15a 100644 --- a/core/net/uip-ds6.c +++ b/core/net/uip-ds6.c @@ -5,9 +5,9 @@ /** * \file - * IPv6 data structures handling functions + * IPv6 data structures handling functions. * Comprises part of the Neighbor discovery (RFC 4861) - * and auto configuration (RFC 4862 )state machines + * and auto configuration (RFC 4862) state machines. * \author Mathilde Durvy * \author Julien Abeille */ @@ -375,11 +375,11 @@ uip_ds6_nbr_ll_lookup(uip_lladdr_t *lladdr) { uip_ds6_nbr_t *fin; - for( locnbr=uip_ds6_nbr_cache, fin=locnbr + UIP_DS6_NBR_NB; - locnbrisused) { - if(!memcmp(lladdr,&locnbr->lladdr,UIP_LLADDR_LEN)) { + if(!memcmp(lladdr, &locnbr->lladdr, UIP_LLADDR_LEN)) { return locnbr; } } @@ -785,7 +785,7 @@ uip_ds6_route_add(uip_ipaddr_t *ipaddr, uint8_t length, uip_ipaddr_t *nexthop, locroute->metric = metric; #ifdef UIP_DS6_ROUTE_STATE_TYPE - memset (&(locroute->state),0,sizeof(UIP_DS6_ROUTE_STATE_TYPE)); + memset(&locroute->state, 0, sizeof(UIP_DS6_ROUTE_STATE_TYPE)); #endif PRINTF("DS6: adding route: "); diff --git a/core/net/uip-icmp6.c b/core/net/uip-icmp6.c index fb2016b23..73aaf2a0b 100644 --- a/core/net/uip-icmp6.c +++ b/core/net/uip-icmp6.c @@ -69,7 +69,7 @@ static uip_ipaddr_t tmp_ipaddr; #if UIP_CONF_IPV6_RPL -int rpl_invert_header(void); +#include "rpl/rpl.h" #endif /* UIP_CONF_IPV6_RPL */ /*---------------------------------------------------------------------------*/