From 28a563a24bd4f278e5d5833a7dafc147d8fb4947 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Tue, 26 Nov 2013 22:45:38 +0100 Subject: [PATCH 01/92] cc2538: clock: Request an etimer poll in clock_adjust() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During PM1+, the hardware timer used to implement the Contiki clock is frozen, so clock_adjust() needs to be called when exiting those modes in order to compensate for the clock ticks missed while the timer was frozen. Doing so changes the Contiki clock time, so etimer_request_poll() needs to be called in order to inform the etimer library that an etimer might have expired. Note that waiting for the next clock ISR to call etimer_request_poll() is unreliable because the system might go back to sleep beforehand. Signed-off-by: Benoît Thébaudeau --- cpu/cc2538/clock.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cpu/cc2538/clock.c b/cpu/cc2538/clock.c index d818362a9..20297e993 100644 --- a/cpu/cc2538/clock.c +++ b/cpu/cc2538/clock.c @@ -197,6 +197,14 @@ clock_adjust(clock_time_t ticks) /* Re-Start the SysTick */ REG(SYSTICK_STCTRL) |= SYSTICK_STCTRL_ENABLE; + + /* + * Inform the etimer library that the system clock has changed and that an + * etimer might have expired. + */ + if(etimer_pending()) { + etimer_request_poll(); + } } /*---------------------------------------------------------------------------*/ /** From b7515004daa687ff577514f89b0575df31a816e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Tue, 3 Dec 2013 18:09:07 +0100 Subject: [PATCH 02/92] cc2538: clock: Fix secs update in clock_adjust() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Whole elapsed seconds are added to secs first, so only the remaining subsecond ticks should then be subtracted from second_countdown in order to decide whether secs should be incremented again. Otherwise, secs is not correctly updated in some cases, typically if the bit 7 of ticks is 1. E.g., with ticks = 128 (i.e. exactly 1 s elapsed) and second_countdown = 128, secs was first incremented as expected, then 128 was subtracted from second_countdown, giving 0 and triggering an unwanted second increment of secs. Or with ticks = 129 (i.e. 1 s + 1 tick) and second_countdown = 1, secs was first incremented as expected, then 129 was subtracted from second_countdown, giving 128 and missing a second increment of secs that should have occurred because second_countdown wrapped around. Signed-off-by: Benoît Thébaudeau --- cpu/cc2538/clock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpu/cc2538/clock.c b/cpu/cc2538/clock.c index 20297e993..51f0c7990 100644 --- a/cpu/cc2538/clock.c +++ b/cpu/cc2538/clock.c @@ -188,7 +188,7 @@ clock_adjust(clock_time_t ticks) * Update internal second countdown so that next second change will actually * happen when it's meant to happen. */ - second_countdown -= ticks; + second_countdown -= ticks & 127; if(second_countdown == 0 || second_countdown > 128) { secs++; From d86b8275ec441cb8bbce2e1dae41269de416b1a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Wed, 4 Dec 2013 16:17:14 +0100 Subject: [PATCH 03/92] cc2538: clock: Fix time drift occurring with PM1/2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The clock adjustments made when waking up from PM1/2 were very inaccurate. If relying on ContikiMAC's rtimer to sleep, this led to Contiki's software clock time, seconds and etimers to be 2.5 s slower after each min, i.e. 1 hour slower after each day, which is a show stopper issue for most real-life applications. This was caused by a lack of accuracy in several pieces of code during sleep entry and wake-up: - It was difficult to synchronize the calls to RTIMER_NOW() before and after sleep with the deactivation and activation of the SysTick peripheral caused by PM1/2. This caused an inaccuracy in the corrective number of ticks passed to clock_adjust(). - The value passed to clock_adjust() was truncated from an rtimer_clock_t value, but the accumulated error caused by these truncated bits was ignored. - The SysTick peripheral had to be stopped during the call to clock_adjust(). Rather than creating even more complicated clock adjustment mechanisms that would probably still have mixed results as to accuracy, this change simply uses the Sleep Timer counter as a base value for Contiki's clock and seconds counters. The tick from the Systick peripheral is still used as the interrupt source to update Contiki's clocks and timers. When running, the SysTick peripheral and the Sleep Timer are synchronized, so combining both is not an issue, and this allows not to alter the rtimer interrupt mechanism using the Sleep Timer. The purpose of the Sleep Timer is to be an RTC, so it is the perfect fit for the clock module, all the more it can not be disturbed by PM1/2. If the 32-kHz XOSC is used, the Sleep Timer is also very accurate. If the 32-kHZ RCOSC is used, it is calibrated from the 32-MHz XOSC, so it is also accurate, and the 32753-Hz vs. 32768-Hz systematic error in that case is negligible, all the more one would use the 32-kHz XOSC for better accuracy. Besides fixing this time drift issue, this change has several benefits: - clock_time(), clock_seconds() and RTIMER_NOW() start synchronized, and they change at the same source pace. - If clock_set_seconds() is called, then clock_seconds() indicates one more second almost exactly one second later, then exactly each second. Before this change, clock_seconds() was not synchronized with clock_set_seconds(), so the value returned by the former could be incremented immediately after the call to the latter in some cases. - The code tied to the clock module is simpler and more robust. Signed-off-by: Benoît Thébaudeau --- cpu/cc2538/clock.c | 114 ++++++++++++++++++++++++++------------------- cpu/cc2538/lpm.c | 24 ++++------ 2 files changed, 74 insertions(+), 64 deletions(-) diff --git a/cpu/cc2538/clock.c b/cpu/cc2538/clock.c index 51f0c7990..98abdf2e3 100644 --- a/cpu/cc2538/clock.c +++ b/cpu/cc2538/clock.c @@ -38,7 +38,11 @@ * * To implement the clock functionality, we use the SysTick peripheral on the * cortex-M3. We run the system clock at 16 MHz and we set the SysTick to give - * us 128 interrupts / sec + * us 128 interrupts / sec. However, the Sleep Timer counter value is used for + * the number of elapsed ticks in order to avoid a significant time drift caused + * by PM1/2. Contrary to the Sleep Timer, the SysTick peripheral is indeed + * frozen during PM1/2, so adjusting upon wake-up a tick counter based on this + * peripheral would hardly be accurate. * @{ * * \file @@ -52,14 +56,15 @@ #include "dev/sys-ctrl.h" #include "sys/energest.h" +#include "sys/etimer.h" +#include "sys/rtimer.h" #include /*---------------------------------------------------------------------------*/ +#define RTIMER_CLOCK_TICK_RATIO (RTIMER_SECOND / CLOCK_SECOND) #define RELOAD_VALUE (125000 - 1) /** Fire 128 times / sec */ -static volatile clock_time_t count; -static volatile unsigned long secs = 0; -static volatile uint8_t second_countdown = CLOCK_SECOND; +static volatile uint64_t rt_ticks_startup = 0, rt_ticks_epoch = 0; /*---------------------------------------------------------------------------*/ /** * \brief Arch-specific implementation of clock_init for the cc2538 @@ -75,8 +80,6 @@ static volatile uint8_t second_countdown = CLOCK_SECOND; void clock_init(void) { - count = 0; - REG(SYSTICK_STRELOAD) = RELOAD_VALUE; /* System clock source, Enable */ @@ -109,19 +112,19 @@ clock_init(void) CCIF clock_time_t clock_time(void) { - return count; + return rt_ticks_startup / RTIMER_CLOCK_TICK_RATIO; } /*---------------------------------------------------------------------------*/ void clock_set_seconds(unsigned long sec) { - secs = sec; + rt_ticks_epoch = (uint64_t)sec * RTIMER_SECOND; } /*---------------------------------------------------------------------------*/ CCIF unsigned long clock_seconds(void) { - return secs; + return rt_ticks_epoch / RTIMER_SECOND; } /*---------------------------------------------------------------------------*/ void @@ -160,43 +163,40 @@ clock_delay(unsigned int i) } /*---------------------------------------------------------------------------*/ /** - * \brief Adjust the clock by moving it forward by a number of ticks - * \param ticks The number of ticks + * \brief Update the software clock ticks and seconds * - * This function is useful when coming out of PM1/2, during which the system - * clock is stopped. We adjust the clock by moving it forward by a number of - * ticks equal to the deep sleep duration. We update the seconds counter if - * we have to and we also do some housekeeping so that the next second will - * increment when it is meant to. + * This function is used to update the software tick counters whenever the + * system clock might have changed, which can occur upon a SysTick ISR or upon + * wake-up from PM1/2. * - * \note This function is only meant to be used by lpm_exit(). Applications - * should really avoid calling this + * For the software clock ticks counter, the Sleep Timer counter value is used + * as the base tick value, and extended to a 64-bit value thanks to a detection + * of wraparounds. + * + * For the seconds counter, the changes of the Sleep Timer counter value are + * added to the reference time, which is either the startup time or the value + * passed to clock_set_seconds(). + * + * This function polls the etimer process if an etimer has expired. */ -void -clock_adjust(clock_time_t ticks) +static void +update_ticks(void) { - /* Halt the SysTick while adjusting */ - REG(SYSTICK_STCTRL) &= ~SYSTICK_STCTRL_ENABLE; + rtimer_clock_t now; + uint64_t prev_rt_ticks_startup, cur_rt_ticks_startup; + uint32_t cur_rt_ticks_startup_hi; - /* Moving forward by more than a second? */ - secs += ticks >> 7; + now = RTIMER_NOW(); + prev_rt_ticks_startup = rt_ticks_startup; - /* Increment tick count */ - count += ticks; - - /* - * Update internal second countdown so that next second change will actually - * happen when it's meant to happen. - */ - second_countdown -= ticks & 127; - - if(second_countdown == 0 || second_countdown > 128) { - secs++; - second_countdown -= 128; + cur_rt_ticks_startup_hi = prev_rt_ticks_startup >> 32; + if(now < (rtimer_clock_t)prev_rt_ticks_startup) { + cur_rt_ticks_startup_hi++; } + cur_rt_ticks_startup = (uint64_t)cur_rt_ticks_startup_hi << 32 | now; + rt_ticks_startup = cur_rt_ticks_startup; - /* Re-Start the SysTick */ - REG(SYSTICK_STCTRL) |= SYSTICK_STCTRL_ENABLE; + rt_ticks_epoch += cur_rt_ticks_startup - prev_rt_ticks_startup; /* * Inform the etimer library that the system clock has changed and that an @@ -208,23 +208,39 @@ clock_adjust(clock_time_t ticks) } /*---------------------------------------------------------------------------*/ /** - * \brief The clock Interrupt Service Routine. It polls the etimer process - * if an etimer has expired. It also updates the software clock tick and - * seconds counter since reset. + * \brief Adjust the clock following missed SysTick ISRs + * + * This function is useful when coming out of PM1/2, during which the system + * clock is stopped. We adjust the clock counters like after any SysTick ISR. + * + * \note This function is only meant to be used by lpm_exit(). Applications + * should really avoid calling this + */ +void +clock_adjust(void) +{ + /* Halt the SysTick while adjusting */ + REG(SYSTICK_STCTRL) &= ~SYSTICK_STCTRL_ENABLE; + + update_ticks(); + + /* Re-Start the SysTick */ + REG(SYSTICK_STCTRL) |= SYSTICK_STCTRL_ENABLE; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief The clock Interrupt Service Routine + * + * It polls the etimer process if an etimer has expired. It also updates the + * software clock tick and seconds counter. */ void clock_isr(void) { ENERGEST_ON(ENERGEST_TYPE_IRQ); - count++; - if(etimer_pending()) { - etimer_request_poll(); - } - if(--second_countdown == 0) { - secs++; - second_countdown = CLOCK_SECOND; - } + update_ticks(); + ENERGEST_OFF(ENERGEST_TYPE_IRQ); } /*---------------------------------------------------------------------------*/ diff --git a/cpu/cc2538/lpm.c b/cpu/cc2538/lpm.c index 80b536998..0c017f371 100644 --- a/cpu/cc2538/lpm.c +++ b/cpu/cc2538/lpm.c @@ -86,14 +86,11 @@ rtimer_clock_t lpm_stats[3]; /*---------------------------------------------------------------------------*/ /* * Remembers what time it was when went to deep sleep - * This is used when coming out of PM1/2 to adjust the system clock, which - * stops ticking while in those PMs + * This is used when coming out of PM0/1/2 to keep stats */ static rtimer_clock_t sleep_enter_time; -#define RTIMER_CLOCK_TICK_RATIO (RTIMER_SECOND / CLOCK_SECOND) - -void clock_adjust(clock_time_t ticks); +void clock_adjust(void); /*---------------------------------------------------------------------------*/ /* Stores the currently specified MAX allowed PM */ static uint8_t max_pm; @@ -135,10 +132,7 @@ enter_pm0(void) /* We are only interested in IRQ energest while idle or in LPM */ ENERGEST_IRQ_RESTORE(irq_energest); - /* - * After PM0 we don't need to adjust the system clock. Thus, saving the time - * we enter Deep Sleep is only required if we are keeping stats. - */ + /* Remember the current time so we can keep stats when we wake up */ if(LPM_CONF_STATS) { sleep_enter_time = RTIMER_NOW(); } @@ -213,10 +207,8 @@ lpm_exit() RTIMER_NOW() - sleep_enter_time); /* Adjust the system clock, since it was not counting while we were sleeping - * We need to convert sleep duration from rtimer ticks to clock ticks and - * this will cost us some accuracy */ - clock_adjust((clock_time_t) - ((RTIMER_NOW() - sleep_enter_time) / RTIMER_CLOCK_TICK_RATIO)); + * We need to convert sleep duration from rtimer ticks to clock ticks */ + clock_adjust(); /* Restore system clock to the 32 MHz XOSC */ select_32_mhz_xosc(); @@ -304,8 +296,10 @@ lpm_enter() ENERGEST_OFF(ENERGEST_TYPE_CPU); ENERGEST_ON(ENERGEST_TYPE_LPM); - /* Remember the current time so we can adjust the clock when we wake up */ - sleep_enter_time = RTIMER_NOW(); + /* Remember the current time so we can keep stats when we wake up */ + if(LPM_CONF_STATS) { + sleep_enter_time = RTIMER_NOW(); + } /* * Last chance to abort entering Deep Sleep. From dbba311270c0deb94dc36f060a0991522a2768af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Mon, 4 Nov 2013 20:39:56 +0100 Subject: [PATCH 04/92] cc2538: Add adc driver and example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Benoît Thébaudeau --- cpu/cc2538/Makefile.cc2538 | 2 +- cpu/cc2538/dev/adc.c | 99 +++++++++++++++++++++ cpu/cc2538/dev/adc.h | 75 ++++++++++++++++ cpu/cc2538/dev/cctest.h | 92 ++++++++++++++++++++ cpu/cc2538/dev/rfcore-xreg.h | 2 + cpu/cc2538/dev/soc-adc.h | 28 ++++++ examples/cc2538dk/cc2538-demo.c | 17 +++- platform/cc2538dk/Makefile.cc2538dk | 3 +- platform/cc2538dk/README.md | 2 + platform/cc2538dk/dev/adc-sensor.c | 111 ++++++++++++++++++++++++ platform/cc2538dk/dev/adc-sensor.h | 67 ++++++++++++++ platform/cc2538dk/dev/board.h | 14 +++ platform/cc2538dk/dev/smartrf-sensors.c | 3 +- 13 files changed, 511 insertions(+), 4 deletions(-) create mode 100644 cpu/cc2538/dev/adc.c create mode 100644 cpu/cc2538/dev/adc.h create mode 100644 cpu/cc2538/dev/cctest.h create mode 100644 platform/cc2538dk/dev/adc-sensor.c create mode 100644 platform/cc2538dk/dev/adc-sensor.h diff --git a/cpu/cc2538/Makefile.cc2538 b/cpu/cc2538/Makefile.cc2538 index 103e177fc..5310994ce 100644 --- a/cpu/cc2538/Makefile.cc2538 +++ b/cpu/cc2538/Makefile.cc2538 @@ -43,7 +43,7 @@ CONTIKI_CPU_DIRS += ../cc253x/usb/common ../cc253x/usb/common/cdc-acm ### CPU-dependent source files CONTIKI_CPU_SOURCEFILES += clock.c rtimer-arch.c uart.c watchdog.c -CONTIKI_CPU_SOURCEFILES += nvic.c cpu.c sys-ctrl.c gpio.c ioc.c spi.c +CONTIKI_CPU_SOURCEFILES += nvic.c cpu.c sys-ctrl.c gpio.c ioc.c spi.c adc.c CONTIKI_CPU_SOURCEFILES += cc2538-rf.c udma.c lpm.c CONTIKI_CPU_SOURCEFILES += dbg.c ieee-addr.c CONTIKI_CPU_SOURCEFILES += slip-arch.c slip.c diff --git a/cpu/cc2538/dev/adc.c b/cpu/cc2538/dev/adc.c new file mode 100644 index 000000000..0cd2f5da8 --- /dev/null +++ b/cpu/cc2538/dev/adc.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2013, ADVANSEE - http://www.advansee.com/ + * Benoît Thébaudeau + * 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 copyright holder 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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. + */ +/** + * \addtogroup cc2538-adc + * @{ + * + * \file + * Implementation of the cc2538 ADC driver + */ +#include "contiki.h" +#include "dev/soc-adc.h" +#include "dev/cctest.h" +#include "dev/rfcore-xreg.h" +#include "dev/adc.h" +#include "reg.h" + +#include + +/*---------------------------------------------------------------------------*/ +void +adc_init(void) +{ + /* Start conversions only manually */ + REG(SOC_ADC_ADCCON1) |= SOC_ADC_ADCCON1_STSEL; +} +/*---------------------------------------------------------------------------*/ +int16_t +adc_get(uint8_t channel, uint8_t ref, uint8_t div) +{ + uint32_t cctest_tr0, rfcore_xreg_atest; + int16_t res; + + /* On-chip temperature sensor */ + if(channel == SOC_ADC_ADCCON_CH_TEMP) { + /* Connect the temperature sensor to the ADC */ + cctest_tr0 = REG(CCTEST_TR0); + REG(CCTEST_TR0) = cctest_tr0 | CCTEST_TR0_ADCTM; + + /* Enable the temperature sensor */ + rfcore_xreg_atest = REG(RFCORE_XREG_ATEST); + REG(RFCORE_XREG_ATEST) = (rfcore_xreg_atest & ~RFCORE_XREG_ATEST_ATEST_CTRL) | + RFCORE_XREG_ATEST_ATEST_CTRL_TEMP; + } + + /* Start a single extra conversion with the given parameters */ + REG(SOC_ADC_ADCCON3) = (REG(SOC_ADC_ADCCON3) & + ~(SOC_ADC_ADCCON3_EREF | SOC_ADC_ADCCON3_EDIV | SOC_ADC_ADCCON3_ECH)) | + ref | div | channel; + + /* Poll until end of conversion */ + while(!(REG(SOC_ADC_ADCCON1) & SOC_ADC_ADCCON1_EOC)); + + /* Read conversion result, reading SOC_ADC_ADCH last to clear + * SOC_ADC_ADCCON1.EOC */ + res = REG(SOC_ADC_ADCL) & 0xfc; + res |= REG(SOC_ADC_ADCH) << 8; + + /* On-chip temperature sensor */ + if(channel == SOC_ADC_ADCCON_CH_TEMP) { + /* Restore the initial temperature sensor state and connection (better for + * power consumption) */ + REG(RFCORE_XREG_ATEST) = rfcore_xreg_atest; + REG(CCTEST_TR0) = cctest_tr0; + } + + /* Return conversion result */ + return res; +} + +/** @} */ diff --git a/cpu/cc2538/dev/adc.h b/cpu/cc2538/dev/adc.h new file mode 100644 index 000000000..4610be4ae --- /dev/null +++ b/cpu/cc2538/dev/adc.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2013, ADVANSEE - http://www.advansee.com/ + * Benoît Thébaudeau + * 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 copyright holder 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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. + */ +/** + * \addtogroup cc2538 + * @{ + * + * \defgroup cc2538-adc cc2538 ADC + * + * Driver for the cc2538 ADC controller + * @{ + * + * \file + * Header file for the cc2538 ADC driver + */ +#ifndef ADC_H_ +#define ADC_H_ + +#include "contiki.h" +#include "dev/soc-adc.h" + +#include +/*---------------------------------------------------------------------------*/ +/** \name ADC functions + * @{ + */ + +/** \brief Initializes the ADC controller */ +void adc_init(void); + +/** \brief Performs a single conversion on a given ADC channel + * \param channel The channel used for the conversion: \c SOC_ADC_ADCCON_CH_x + * \param ref The reference voltage used for the conversion: \c SOC_ADC_ADCCON_REF_x + * \param div The decimation rate used for the conversion: \c SOC_ADC_ADCCON_DIV_x + * \return Signed 16-bit conversion result: 2's complement, ENOBs in MSBs + * \note PD[5:4] are not usable when the temperature sensor is selected. + */ +int16_t adc_get(uint8_t channel, uint8_t ref, uint8_t div); + +/** @} */ + +#endif /* ADC_H_ */ + +/** + * @} + * @} + */ diff --git a/cpu/cc2538/dev/cctest.h b/cpu/cc2538/dev/cctest.h new file mode 100644 index 000000000..4f540969a --- /dev/null +++ b/cpu/cc2538/dev/cctest.h @@ -0,0 +1,92 @@ +/* + * Original file: + * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/ + * All rights reserved. + * + * Port to Contiki: + * Copyright (c) 2013, ADVANSEE - http://www.advansee.com/ + * Benoît Thébaudeau + * 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 copyright holder 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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. + */ +/** + * \addtogroup cc2538-rfcore + * @{ + * + * \file + * Header with declarations of CCTEST module registers. + */ +#ifndef CCTEST_H +#define CCTEST_H + +/*---------------------------------------------------------------------------*/ +/** + * \name CCTEST register offsets + * @{ + */ +#define CCTEST_IO 0x44010000 /**< Output strength control */ +#define CCTEST_OBSSEL0 0x44010014 /**< Observation output 0 */ +#define CCTEST_OBSSEL1 0x44010018 /**< Observation output 1 */ +#define CCTEST_OBSSEL2 0x4401001C /**< Observation output 2 */ +#define CCTEST_OBSSEL3 0x44010020 /**< Observation output 3 */ +#define CCTEST_OBSSEL4 0x44010024 /**< Observation output 4 */ +#define CCTEST_OBSSEL5 0x44010028 /**< Observation output 5 */ +#define CCTEST_OBSSEL6 0x4401002C /**< Observation output 6 */ +#define CCTEST_OBSSEL7 0x44010030 /**< Observation output 7 */ +#define CCTEST_TR0 0x44010034 /**< Test register 0 */ +#define CCTEST_USBCTRL 0x44010050 /**< USB PHY stand-by control */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name CCTEST_IO register bit fields + * @{ + */ +#define CCTEST_IO_SC 0x00000001 /**< I/O strength control */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name CCTEST_OBSSELx registers bit fields + * @{ + */ +#define CCTEST_OBSSEL_EN 0x00000080 /**< Observation output enable */ +#define CCTEST_OBSSEL_SEL_M 0x0000007F /**< n - obs_sigs[n] output selection mask */ +#define CCTEST_OBSSEL_SEL_S 0 /**< n - obs_sigs[n] output selection shift */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name CCTEST_TR0 register bit fields + * @{ + */ +#define CCTEST_TR0_ADCTM 0x00000002 /**< Connect temperature sensor to ADC */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name CCTEST_USBCTRL register bit fields + * @{ + */ +#define CCTEST_USBCTRL_USB_STB 0x00000001 /**< USB PHY stand-by override */ +/** @} */ + +#endif /* CCTEST_H */ +/** @} */ diff --git a/cpu/cc2538/dev/rfcore-xreg.h b/cpu/cc2538/dev/rfcore-xreg.h index e75d447a9..7dc9ee815 100644 --- a/cpu/cc2538/dev/rfcore-xreg.h +++ b/cpu/cc2538/dev/rfcore-xreg.h @@ -575,6 +575,8 @@ * @{ */ #define RFCORE_XREG_ATEST_ATEST_CTRL 0x0000003F /**< Controls the analog test mode */ +#define RFCORE_XREG_ATEST_ATEST_CTRL_DIS 0x00000000 /**< Analog test mode: disabled */ +#define RFCORE_XREG_ATEST_ATEST_CTRL_TEMP 0x00000001 /**< Analog test mode: enable temperature sensor */ /** @} */ /*---------------------------------------------------------------------------*/ /** \name RFCORE_XREG_PTEST0 register bit masks diff --git a/cpu/cc2538/dev/soc-adc.h b/cpu/cc2538/dev/soc-adc.h index e498d34db..28bb508b3 100644 --- a/cpu/cc2538/dev/soc-adc.h +++ b/cpu/cc2538/dev/soc-adc.h @@ -83,6 +83,34 @@ #define SOC_ADC_ADCCON3_ECH 0x0000000F /**< Single channel select */ /** @} */ /*---------------------------------------------------------------------------*/ +/** \name SOC_ADC_ADCCONx registers field values + * @{ + */ +#define SOC_ADC_ADCCON_REF_INT (0 << 6) /**< Internal reference */ +#define SOC_ADC_ADCCON_REF_EXT_SINGLE (1 << 6) /**< External reference on AIN7 pin */ +#define SOC_ADC_ADCCON_REF_AVDD5 (2 << 6) /**< AVDD5 pin */ +#define SOC_ADC_ADCCON_REF_EXT_DIFF (3 << 6) /**< External reference on AIN6-AIN7 differential input */ +#define SOC_ADC_ADCCON_DIV_64 (0 << 4) /**< 64 decimation rate (7 bits ENOB) */ +#define SOC_ADC_ADCCON_DIV_128 (1 << 4) /**< 128 decimation rate (9 bits ENOB) */ +#define SOC_ADC_ADCCON_DIV_256 (2 << 4) /**< 256 decimation rate (10 bits ENOB) */ +#define SOC_ADC_ADCCON_DIV_512 (3 << 4) /**< 512 decimation rate (12 bits ENOB) */ +#define SOC_ADC_ADCCON_CH_AIN0 0x0 /**< AIN0 */ +#define SOC_ADC_ADCCON_CH_AIN1 0x1 /**< AIN1 */ +#define SOC_ADC_ADCCON_CH_AIN2 0x2 /**< AIN2 */ +#define SOC_ADC_ADCCON_CH_AIN3 0x3 /**< AIN3 */ +#define SOC_ADC_ADCCON_CH_AIN4 0x4 /**< AIN4 */ +#define SOC_ADC_ADCCON_CH_AIN5 0x5 /**< AIN5 */ +#define SOC_ADC_ADCCON_CH_AIN6 0x6 /**< AIN6 */ +#define SOC_ADC_ADCCON_CH_AIN7 0x7 /**< AIN7 */ +#define SOC_ADC_ADCCON_CH_AIN0_AIN1 0x8 /**< AIN0-AIN1 */ +#define SOC_ADC_ADCCON_CH_AIN2_AIN3 0x9 /**< AIN2-AIN3 */ +#define SOC_ADC_ADCCON_CH_AIN4_AIN5 0xA /**< AIN4-AIN5 */ +#define SOC_ADC_ADCCON_CH_AIN6_AIN7 0xB /**< AIN6-AIN7 */ +#define SOC_ADC_ADCCON_CH_GND 0xC /**< GND */ +#define SOC_ADC_ADCCON_CH_TEMP 0xE /**< Temperature sensor */ +#define SOC_ADC_ADCCON_CH_VDD_3 0xF /**< VDD/3 */ +/** @} */ +/*---------------------------------------------------------------------------*/ /** \name SOC_ADC_ADC[L:H] register bit masks * @{ */ diff --git a/examples/cc2538dk/cc2538-demo.c b/examples/cc2538dk/cc2538-demo.c index 268ea44f4..46b83bddf 100644 --- a/examples/cc2538dk/cc2538-demo.c +++ b/examples/cc2538dk/cc2538-demo.c @@ -50,6 +50,8 @@ * - BTN_DOWN turns on LEDS_REBOOT and causes a watchdog reboot * - BTN_UP to soft reset (SYS_CTRL_PWRDBG::FORCE_WARM_RESET) * - BTN_LEFT and BTN_RIGHT flash the LED defined as LEDS_BUTTON + * - ADC sensors : On-chip VDD / 3 and temperature, and ambient light sensor + * values are printed over UART periodically. * - UART : Every LOOP_INTERVAL the EM will print something over the * UART. Receiving an entire line of text over UART (ending * in \\r) will cause LEDS_SERIAL_IN to toggle @@ -68,6 +70,7 @@ #include "dev/leds.h" #include "dev/uart.h" #include "dev/button-sensor.h" +#include "dev/adc-sensor.h" #include "dev/watchdog.h" #include "dev/serial-line.h" #include "dev/sys-ctrl.h" @@ -111,6 +114,7 @@ rt_callback(struct rtimer *t, void *ptr) /*---------------------------------------------------------------------------*/ PROCESS_THREAD(cc2538_demo_process, ev, data) { + int16_t value; PROCESS_EXITHANDLER(broadcast_close(&bc)) @@ -126,7 +130,18 @@ PROCESS_THREAD(cc2538_demo_process, ev, data) if(ev == PROCESS_EVENT_TIMER) { leds_on(LEDS_PERIODIC); - printf("Counter = 0x%08x\n", counter); + printf("-----------------------------------------\n" + "Counter = 0x%08x\n", counter); + + value = adc_sensor.value(ADC_SENSOR_VDD_3); + printf("VDD = %d mV\n", value * (3 * 1190) / (2047 << 4)); + + value = adc_sensor.value(ADC_SENSOR_TEMP); + printf("Temperature = %d mC\n", + 25000 + ((value >> 4) - 1422) * 10000 / 42); + + value = adc_sensor.value(ADC_SENSOR_ALS); + printf("Ambient light sensor = %d raw\n", value); etimer_set(&et, CLOCK_SECOND); rtimer_set(&rt, RTIMER_NOW() + LEDS_OFF_HYSTERISIS, 1, diff --git a/platform/cc2538dk/Makefile.cc2538dk b/platform/cc2538dk/Makefile.cc2538dk index b350c2fc2..8ccfb3972 100644 --- a/platform/cc2538dk/Makefile.cc2538dk +++ b/platform/cc2538dk/Makefile.cc2538dk @@ -8,7 +8,8 @@ CONTIKI_TARGET_DIRS = . dev CONTIKI_TARGET_SOURCEFILES += leds.c leds-arch.c CONTIKI_TARGET_SOURCEFILES += contiki-main.c -CONTIKI_TARGET_SOURCEFILES += sensors.c smartrf-sensors.c button-sensor.c +CONTIKI_TARGET_SOURCEFILES += sensors.c smartrf-sensors.c +CONTIKI_TARGET_SOURCEFILES += button-sensor.c adc-sensor.c TARGET_START_SOURCEFILES += startup-gcc.c TARGET_STARTFILES = ${addprefix $(OBJECTDIR)/,${call oname, $(TARGET_START_SOURCEFILES)}} diff --git a/platform/cc2538dk/README.md b/platform/cc2538dk/README.md index 18273d2b6..152818560 100644 --- a/platform/cc2538dk/README.md +++ b/platform/cc2538dk/README.md @@ -28,9 +28,11 @@ In terms of hardware support, the following drivers have been implemented: * Random number generator * Low Power Modes * General-Purpose Timers. NB: GPT0 is in use by the platform code, the remaining GPTs are available for application development. + * ADC * SmartRF06 EB and BB peripherals * LEDs * Buttons + * ADC sensors (on-chip VDD / 3 and temperature, ambient light sensor) * UART connectivity over the XDS100v3 backchannel (EB only) Requirements diff --git a/platform/cc2538dk/dev/adc-sensor.c b/platform/cc2538dk/dev/adc-sensor.c new file mode 100644 index 000000000..4c2f1f853 --- /dev/null +++ b/platform/cc2538dk/dev/adc-sensor.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2013, ADVANSEE - http://www.advansee.com/ + * Benoît Thébaudeau + * 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 copyright holder 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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. + */ +/** + * \addtogroup cc2538dk-adc-sensor + * @{ + * + * \file + * Driver for the SmartRF06EB ADC + */ +#include "contiki.h" +#include "sys/clock.h" +#include "dev/ioc.h" +#include "dev/gpio.h" +#include "dev/adc.h" +#include "dev/adc-sensor.h" + +#include + +#define ADC_ALS_PWR_PORT_BASE GPIO_PORT_TO_BASE(ADC_ALS_PWR_PORT) +#define ADC_ALS_PWR_PIN_MASK GPIO_PIN_MASK(ADC_ALS_PWR_PIN) +#define ADC_ALS_OUT_PIN_MASK GPIO_PIN_MASK(ADC_ALS_OUT_PIN) +/*---------------------------------------------------------------------------*/ +static int +value(int type) +{ + uint8_t channel; + int16_t res; + + switch(type) { + case ADC_SENSOR_VDD_3: + channel = SOC_ADC_ADCCON_CH_VDD_3; + break; + case ADC_SENSOR_TEMP: + channel = SOC_ADC_ADCCON_CH_TEMP; + break; + case ADC_SENSOR_ALS: + channel = SOC_ADC_ADCCON_CH_AIN0 + ADC_ALS_OUT_PIN; + GPIO_SET_PIN(ADC_ALS_PWR_PORT_BASE, ADC_ALS_PWR_PIN_MASK); + clock_delay_usec(2000); + break; + default: + return 0; + } + + res = adc_get(channel, SOC_ADC_ADCCON_REF_INT, SOC_ADC_ADCCON_DIV_512); + + if(type == ADC_SENSOR_ALS) { + GPIO_CLR_PIN(ADC_ALS_PWR_PORT_BASE, ADC_ALS_PWR_PIN_MASK); + } + + return res; +} +/*---------------------------------------------------------------------------*/ +static int +configure(int type, int value) +{ + switch(type) { + case SENSORS_HW_INIT: + GPIO_SOFTWARE_CONTROL(ADC_ALS_PWR_PORT_BASE, ADC_ALS_PWR_PIN_MASK); + GPIO_SET_OUTPUT(ADC_ALS_PWR_PORT_BASE, ADC_ALS_PWR_PIN_MASK); + GPIO_CLR_PIN(ADC_ALS_PWR_PORT_BASE, ADC_ALS_PWR_PIN_MASK); + ioc_set_over(ADC_ALS_PWR_PORT, ADC_ALS_PWR_PIN, IOC_OVERRIDE_DIS); + + GPIO_SOFTWARE_CONTROL(GPIO_A_BASE, ADC_ALS_OUT_PIN_MASK); + GPIO_SET_INPUT(GPIO_A_BASE, ADC_ALS_OUT_PIN_MASK); + ioc_set_over(GPIO_A_NUM, ADC_ALS_OUT_PIN, IOC_OVERRIDE_ANA); + + adc_init(); + break; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +status(int type) +{ + return 1; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(adc_sensor, ADC_SENSOR, value, configure, status); + +/** @} */ diff --git a/platform/cc2538dk/dev/adc-sensor.h b/platform/cc2538dk/dev/adc-sensor.h new file mode 100644 index 000000000..b6d0efbdf --- /dev/null +++ b/platform/cc2538dk/dev/adc-sensor.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2013, ADVANSEE - http://www.advansee.com/ + * Benoît Thébaudeau + * 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 copyright holder 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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. + */ +/** + * \addtogroup cc2538-smartrf-sensors + * @{ + * + * \defgroup cc2538dk-adc-sensor cc2538dk ADC Driver + * + * Driver for the SmartRF06EB ADC sensors + * @{ + * + * \file + * Header file for the cc2538dk ADC Driver + */ +#ifndef ADC_SENSOR_H_ +#define ADC_SENSOR_H_ + +#include "lib/sensors.h" + +/*---------------------------------------------------------------------------*/ +/** \name ADC sensors + * @{ + */ +#define ADC_SENSOR "ADC" + +#define ADC_SENSOR_VDD_3 0 /**< On-chip VDD / 3 */ +#define ADC_SENSOR_TEMP 1 /**< On-chip temperature */ +#define ADC_SENSOR_ALS 2 /**< Ambient light sensor */ +/** @} */ + +extern const struct sensors_sensor adc_sensor; + +#endif /* ADC_SENSOR_H_ */ + +/** + * @} + * @} + */ diff --git a/platform/cc2538dk/dev/board.h b/platform/cc2538dk/dev/board.h index b36ce9bbb..98a297855 100644 --- a/platform/cc2538dk/dev/board.h +++ b/platform/cc2538dk/dev/board.h @@ -167,6 +167,20 @@ #define PLATFORM_HAS_BUTTON 1 /** @} */ /*---------------------------------------------------------------------------*/ +/** + * \name ADC configuration + * + * These values configure which CC2538 pins and ADC channels to use for the ADC + * inputs. + * + * ADC inputs can only be on port A. + * @{ + */ +#define ADC_ALS_PWR_PORT GPIO_A_NUM /**< ALS power GPIO control port */ +#define ADC_ALS_PWR_PIN 7 /**< ALS power GPIO control pin */ +#define ADC_ALS_OUT_PIN 6 /**< ALS output ADC input pin on port A */ +/** @} */ +/*---------------------------------------------------------------------------*/ /** * \name SPI configuration * diff --git a/platform/cc2538dk/dev/smartrf-sensors.c b/platform/cc2538dk/dev/smartrf-sensors.c index eaf6b90a9..41d977783 100644 --- a/platform/cc2538dk/dev/smartrf-sensors.c +++ b/platform/cc2538dk/dev/smartrf-sensors.c @@ -42,12 +42,13 @@ */ #include "contiki.h" #include "dev/button-sensor.h" +#include "dev/adc-sensor.h" #include /** \brief Exports a global symbol to be used by the sensor API */ SENSORS(&button_select_sensor, &button_left_sensor, &button_right_sensor, - &button_up_sensor, &button_down_sensor); + &button_up_sensor, &button_down_sensor, &adc_sensor); /** * @} From 10a73c938058971e6aa8a9a1cc5a29a1c84e953c Mon Sep 17 00:00:00 2001 From: George Oikonomou Date: Wed, 22 Jan 2014 17:32:08 +0000 Subject: [PATCH 05/92] Fix PCAP packet header timestamp --- .../org/contikios/cooja/plugins/analyzers/PcapExporter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/cooja/java/org/contikios/cooja/plugins/analyzers/PcapExporter.java b/tools/cooja/java/org/contikios/cooja/plugins/analyzers/PcapExporter.java index 0e8a4244a..d0fa0624f 100644 --- a/tools/cooja/java/org/contikios/cooja/plugins/analyzers/PcapExporter.java +++ b/tools/cooja/java/org/contikios/cooja/plugins/analyzers/PcapExporter.java @@ -46,7 +46,7 @@ public class PcapExporter { } try { /* pcap packet header */ - out.writeInt((int) System.currentTimeMillis() / 1000); + out.writeInt((int) (System.currentTimeMillis() / 1000)); out.writeInt((int) ((System.currentTimeMillis() % 1000) * 1000)); out.writeInt(data.length); out.writeInt(data.length); From d979e5b096773986e6ef4f0d35786f368418be66 Mon Sep 17 00:00:00 2001 From: LudovicW Date: Tue, 11 Feb 2014 15:40:42 +0100 Subject: [PATCH 06/92] CC2538: add support for UART baudrate 9600, 38400 and 57600 --- cpu/cc2538/dev/uart.h | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/cpu/cc2538/dev/uart.h b/cpu/cc2538/dev/uart.h index dfb54fc56..8ae5dc486 100644 --- a/cpu/cc2538/dev/uart.h +++ b/cpu/cc2538/dev/uart.h @@ -69,6 +69,12 @@ * clocked at 16MHz and that Clock Div is 16 (UART_CTL:HSE clear) * @{ */ +#define UART_IBRD_9600 104 /**< IBRD value for baud rate 9600 */ +#define UART_FBRD_9600 11 /**< FBRD value for baud rate 9600 */ +#define UART_IBRD_38400 26 /**< IBRD value for baud rate 38400 */ +#define UART_FBRD_38400 3 /**< FBRD value for baud rate 38400 */ +#define UART_IBRD_57600 17 /**< IBRD value for baud rate 57600 */ +#define UART_FBRD_57600 24 /**< FBRD value for baud rate 57600 */ #define UART_IBRD_115200 8 /**< IBRD value for baud rate 115200 */ #define UART_FBRD_115200 44 /**< FBRD value for baud rate 115200 */ #define UART_IBRD_230400 4 /**< IBRD value for baud rate 230400 */ @@ -76,7 +82,16 @@ #define UART_IBRD_460800 2 /**< IBRD value for baud rate 460800 */ #define UART_FBRD_460800 11 /**< FBRD value for baud rate 460800 */ -#if UART_CONF_BAUD_RATE==115200 +#if UART_CONF_BAUD_RATE==9600 +#define UART_CONF_IBRD UART_IBRD_9600 +#define UART_CONF_FBRD UART_FBRD_9600 +#elif UART_CONF_BAUD_RATE==38400 +#define UART_CONF_IBRD UART_IBRD_38400 +#define UART_CONF_FBRD UART_FBRD_38400 +#elif UART_CONF_BAUD_RATE==57600 +#define UART_CONF_IBRD UART_IBRD_57600 +#define UART_CONF_FBRD UART_FBRD_57600 +#elif UART_CONF_BAUD_RATE==115200 #define UART_CONF_IBRD UART_IBRD_115200 #define UART_CONF_FBRD UART_FBRD_115200 #elif UART_CONF_BAUD_RATE==230400 @@ -89,8 +104,9 @@ #if !(defined UART_CONF_IBRD && defined UART_CONF_FBRD) #error "UART baud rate misconfigured and custom IBRD/FBRD values not provided" #error "Check the value of UART_CONF_BAUD_RATE in contiki-conf.h or project-conf.h" -#error "Supported values are 115200, 230400 and 460800. Alternatively, you can" -#error "provide custom values for UART_CONF_IBRD and UART_CONF_FBRD" +#error "Supported values are 9600, 38400, 57600, 115200, 230400 and 460800." +#error "Alternatively, you can provide custom values for " +#error "UART_CONF_IBRD and UART_CONF_FBRD" #endif #endif /** @} */ From 8dd4025248a6f88267886a3c729943d5e5dfcc2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moritz=20=27Morty=27=20Str=C3=BCbe?= Date: Thu, 20 Feb 2014 12:59:30 +0100 Subject: [PATCH 07/92] Fix documentation --- .../contikios/cooja/contikimote/interfaces/ContikiRadio.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/cooja/java/org/contikios/cooja/contikimote/interfaces/ContikiRadio.java b/tools/cooja/java/org/contikios/cooja/contikimote/interfaces/ContikiRadio.java index 9e9ebb691..ebe24e52a 100644 --- a/tools/cooja/java/org/contikios/cooja/contikimote/interfaces/ContikiRadio.java +++ b/tools/cooja/java/org/contikios/cooja/contikimote/interfaces/ContikiRadio.java @@ -252,7 +252,7 @@ public class ContikiRadio extends Radio implements ContikiMoteInterface, PolledA /** Set LQI to a value between 0 and 255. * - * @see se.sics.cooja.interfaces.Radio#setLQI(int) + * @see org.contikios.cooja.interfaces.Radio#setLQI(int) */ public void setLQI(int lqi){ if(lqi<0) { From 19e7611061b640e517923c62d8fffa65da83ed58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moritz=20=27Morty=27=20Str=C3=BCbe?= Date: Thu, 20 Feb 2014 12:59:12 +0100 Subject: [PATCH 08/92] Fix backwards compatibility --- .../org/contikios/cooja/radiomediums/DirectedGraphMedium.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/cooja/java/org/contikios/cooja/radiomediums/DirectedGraphMedium.java b/tools/cooja/java/org/contikios/cooja/radiomediums/DirectedGraphMedium.java index c9bac3f0d..48d90a0f8 100644 --- a/tools/cooja/java/org/contikios/cooja/radiomediums/DirectedGraphMedium.java +++ b/tools/cooja/java/org/contikios/cooja/radiomediums/DirectedGraphMedium.java @@ -380,6 +380,9 @@ public void simulationFinishedLoading() { if (destClassName == null || destClassName.isEmpty()) { continue; } + /* Backwards compatibility: se.sics -> org.contikios */ + destClassName = destClassName.replaceFirst("^se\\.sics", "org.contikios"); + Class destClass = simulation.getCooja().tryLoadClass(this, DGRMDestinationRadio.class, destClassName); if (destClass == null) { From 90ab2e70514bc3e19ff22ab63ed8f5ad5c7da5dd Mon Sep 17 00:00:00 2001 From: Enrico Joerns Date: Thu, 6 Feb 2014 03:52:48 +0100 Subject: [PATCH 09/92] cooja: interfaces/RimeAddress: renamed rimeaddr_node_addr to linkaddr_node_addr --- .../org/contikios/cooja/interfaces/RimeAddress.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/cooja/java/org/contikios/cooja/interfaces/RimeAddress.java b/tools/cooja/java/org/contikios/cooja/interfaces/RimeAddress.java index 50ccf72fc..405aca506 100644 --- a/tools/cooja/java/org/contikios/cooja/interfaces/RimeAddress.java +++ b/tools/cooja/java/org/contikios/cooja/interfaces/RimeAddress.java @@ -48,7 +48,7 @@ import org.contikios.cooja.MoteMemory.MemoryEventType; import org.contikios.cooja.MoteMemory.MemoryMonitor; /** - * Read-only interface to Rime address read from Contiki variable: rimeaddr_node_addr. + * Read-only interface to Rime address read from Contiki variable: linkaddr_node_addr. * XXX Assuming Rime address is 2 bytes. * * @see #RIME_ADDR_LENGTH @@ -76,12 +76,12 @@ public class RimeAddress extends MoteInterface { } }; /* TODO XXX Timeout? */ - moteMem.addMemoryMonitor(moteMem.getVariableAddress("rimeaddr_node_addr"), RIME_ADDR_LENGTH, memMonitor); + moteMem.addMemoryMonitor(moteMem.getVariableAddress("linkaddr_node_addr"), RIME_ADDR_LENGTH, memMonitor); } } public boolean hasRimeAddress() { - return moteMem.variableExists("rimeaddr_node_addr"); + return moteMem.variableExists("linkaddr_node_addr"); } public String getAddressString() { @@ -90,7 +90,7 @@ public class RimeAddress extends MoteInterface { } String addrString = ""; - byte[] addr = moteMem.getByteArray("rimeaddr_node_addr", RIME_ADDR_LENGTH); + byte[] addr = moteMem.getByteArray("linkaddr_node_addr", RIME_ADDR_LENGTH); for (int i=0; i < RIME_ADDR_LENGTH-1; i++) { addrString += (0xFF & addr[i]) + "."; } @@ -131,7 +131,7 @@ public class RimeAddress extends MoteInterface { public void removed() { super.removed(); if (memMonitor != null) { - moteMem.removeMemoryMonitor(moteMem.getVariableAddress("rimeaddr_node_addr"), RIME_ADDR_LENGTH, memMonitor); + moteMem.removeMemoryMonitor(moteMem.getVariableAddress("linkaddr_node_addr"), RIME_ADDR_LENGTH, memMonitor); } } From 80b78ae6dd79367be4532c6c325ebce625916cf3 Mon Sep 17 00:00:00 2001 From: Enrico Joerns Date: Fri, 7 Feb 2014 23:16:34 +0100 Subject: [PATCH 10/92] cooja: plugins/Visualizer: Implemented mouse wheel zooming with mouse coordinates as center --- .../contikios/cooja/plugins/Visualizer.java | 28 +++++++++++++++---- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/tools/cooja/java/org/contikios/cooja/plugins/Visualizer.java b/tools/cooja/java/org/contikios/cooja/plugins/Visualizer.java index 69f5022e9..8926e9af7 100644 --- a/tools/cooja/java/org/contikios/cooja/plugins/Visualizer.java +++ b/tools/cooja/java/org/contikios/cooja/plugins/Visualizer.java @@ -56,6 +56,8 @@ import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionListener; +import java.awt.event.MouseWheelEvent; +import java.awt.event.MouseWheelListener; import java.awt.geom.AffineTransform; import java.io.File; import java.io.IOException; @@ -412,6 +414,20 @@ public class Visualizer extends VisPlugin implements HasQuickHelp { repaint(); } }); + canvas.addMouseWheelListener(new MouseWheelListener() { + public void mouseWheelMoved(MouseWheelEvent mwe) { + int x = mwe.getX(); + int y = mwe.getY(); + int rot = mwe.getWheelRotation(); + + if (rot > 0) { + zoomToFactor(zoomFactor() / 1.2, new Point(x, y)); + } else { + zoomToFactor(zoomFactor() * 1.2, new Point(x, y)); + } + + } + }); /* Register mote menu actions */ registerMoteMenuAction(MoveMoteMenuAction.class); @@ -855,16 +871,16 @@ public class Visualizer extends VisPlugin implements HasQuickHelp { } private void zoomToFactor(double newZoom) { - Position center = transformPixelToPosition( - new Point(canvas.getWidth()/2, canvas.getHeight()/2) - ); + zoomToFactor(newZoom, new Point(canvas.getWidth()/2, canvas.getHeight()/2)); + } + + private void zoomToFactor(double newZoom, Point zoomCenter) { + Position center = transformPixelToPosition(zoomCenter); viewportTransform.setToScale( newZoom, newZoom ); - Position newCenter = transformPixelToPosition( - new Point(canvas.getWidth()/2, canvas.getHeight()/2) - ); + Position newCenter = transformPixelToPosition(zoomCenter); viewportTransform.translate( newCenter.getXCoordinate() - center.getXCoordinate(), newCenter.getYCoordinate() - center.getYCoordinate() From 465b0ddfbe9618ef3fd8a7095d5347a09f260256 Mon Sep 17 00:00:00 2001 From: Enrico Joerns Date: Sun, 9 Feb 2014 03:11:48 +0100 Subject: [PATCH 11/92] [cooja] pluings/skings/UDGMVisualizerSkin: Replaced unclosable Box implementation of JSpinner menus by JInternalFrame based variant. --- .../plugins/skins/UDGMVisualizerSkin.java | 123 +++++++++++++----- 1 file changed, 94 insertions(+), 29 deletions(-) diff --git a/tools/cooja/java/org/contikios/cooja/plugins/skins/UDGMVisualizerSkin.java b/tools/cooja/java/org/contikios/cooja/plugins/skins/UDGMVisualizerSkin.java index 0c80c2075..26f66e3e7 100644 --- a/tools/cooja/java/org/contikios/cooja/plugins/skins/UDGMVisualizerSkin.java +++ b/tools/cooja/java/org/contikios/cooja/plugins/skins/UDGMVisualizerSkin.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Swedish Institute of Computer Science. + * Copyright (c) 2009-2013, Swedish Institute of Computer Science, TU Braunscheig * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -30,18 +30,28 @@ package org.contikios.cooja.plugins.skins; +import java.awt.BorderLayout; import java.awt.Color; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Point; +import java.beans.PropertyVetoException; import javax.swing.BorderFactory; import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.JInternalFrame; import javax.swing.JLabel; +import javax.swing.JLayeredPane; +import javax.swing.JPanel; import javax.swing.JSpinner; import javax.swing.SpinnerNumberModel; +import javax.swing.SwingUtilities; +import static javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; +import javax.swing.event.InternalFrameAdapter; +import javax.swing.event.InternalFrameEvent; import org.apache.log4j.Logger; @@ -68,21 +78,24 @@ import org.contikios.cooja.radiomediums.UDGM; * @see TrafficVisualizerSkin * @see UDGM * @author Fredrik Osterlind + * @author Enrico Joerns */ @ClassDescription("Radio environment (UDGM)") @SupportedArguments(radioMediums = {UDGM.class}) public class UDGMVisualizerSkin implements VisualizerSkin { - private static Logger logger = Logger.getLogger(UDGMVisualizerSkin.class); + private static final Logger logger = Logger.getLogger(UDGMVisualizerSkin.class); - private static Color COLOR_TX = new Color(0, 255, 0, 100); - private static Color COLOR_INT = new Color(50, 50, 50, 100); + private static final Color COLOR_TX = new Color(0, 255, 0, 100); + private static final Color COLOR_INT = new Color(50, 50, 50, 100); private Simulation simulation = null; private Visualizer visualizer = null; private UDGM radioMedium = null; - private Box top, ratioRX, ratioTX, rangeTX, rangeINT; + private JInternalFrame rrFrame; + private Box ratioRX, ratioTX, rangeTX, rangeINT; + @Override public void setActive(Simulation simulation, Visualizer vis) { if (!(simulation.getRadioMedium() instanceof UDGM)) { logger.fatal("Cannot activate UDGM skin for unknown radio medium: " + simulation.getRadioMedium()); @@ -139,6 +152,7 @@ public class UDGMVisualizerSkin implements VisualizerSkin { successRatioRxSpinner.setToolTipText("Reception success ratio (%)"); txRangeSpinner.addChangeListener(new ChangeListener() { + @Override public void stateChanged(ChangeEvent e) { radioMedium.setTxRange(((SpinnerNumberModel) txRangeSpinner.getModel()).getNumber().doubleValue()); @@ -147,6 +161,7 @@ public class UDGMVisualizerSkin implements VisualizerSkin { }); interferenceRangeSpinner.addChangeListener(new ChangeListener() { + @Override public void stateChanged(ChangeEvent e) { radioMedium.setInterferenceRange(((SpinnerNumberModel) interferenceRangeSpinner.getModel()).getNumber().doubleValue()); @@ -155,6 +170,7 @@ public class UDGMVisualizerSkin implements VisualizerSkin { }); successRatioTxSpinner.addChangeListener(new ChangeListener() { + @Override public void stateChanged(ChangeEvent e) { radioMedium.SUCCESS_RATIO_TX = ((SpinnerNumberModel) successRatioTxSpinner.getModel()).getNumber().doubleValue(); @@ -163,6 +179,7 @@ public class UDGMVisualizerSkin implements VisualizerSkin { }); successRatioRxSpinner.addChangeListener(new ChangeListener() { + @Override public void stateChanged(ChangeEvent e) { radioMedium.SUCCESS_RATIO_RX = ((SpinnerNumberModel) successRatioRxSpinner.getModel()).getNumber().doubleValue(); @@ -175,13 +192,10 @@ public class UDGMVisualizerSkin implements VisualizerSkin { visualizer.registerSimulationMenuAction(SuccessRatioMenuAction.class); /* UI components */ - top = Box.createVerticalBox(); - top.setBorder(BorderFactory.createCompoundBorder( - BorderFactory.createLineBorder(Color.BLACK), - BorderFactory.createEmptyBorder(0, 3, 0, 3))); - top.setOpaque(true); - top.setBackground(Color.LIGHT_GRAY); - + JPanel main = new JPanel(); + main.setLayout(new BoxLayout(main, BoxLayout.Y_AXIS)); + main.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); + rangeTX = Box.createHorizontalBox(); rangeTX.add(new JLabel("TX range:")); rangeTX.add(Box.createHorizontalStrut(5)); @@ -203,16 +217,32 @@ public class UDGMVisualizerSkin implements VisualizerSkin { rangeINT.setVisible(false); ratioTX.setVisible(false); ratioRX.setVisible(false); - top.setVisible(false); + + main.add(rangeTX); + main.add(rangeINT); + main.add(ratioTX); + main.add(ratioRX); + + rrFrame = new JInternalFrame("UDGM", false, true); + rrFrame.setVisible(false); + rrFrame.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); + rrFrame.addInternalFrameListener(new InternalFrameAdapter() { + @Override + public void internalFrameClosing(InternalFrameEvent ife) { + super.internalFrameClosed(ife); + rangeTX.setVisible(false); + rangeINT.setVisible(false); + ratioTX.setVisible(false); + ratioRX.setVisible(false); + rrFrame.setVisible(false); + } + }); - top.add(rangeTX); - top.add(rangeINT); - top.add(ratioTX); - top.add(ratioRX); - - visualizer.getCurrentCanvas().add(top); + rrFrame.getContentPane().add(BorderLayout.CENTER, main); + rrFrame.pack(); } + @Override public void setInactive() { if (simulation == null) { /* Skin was never activated */ @@ -220,13 +250,14 @@ public class UDGMVisualizerSkin implements VisualizerSkin { } /* Remove spinners etc */ - visualizer.getCurrentCanvas().remove(top); + visualizer.getCurrentCanvas().remove(rrFrame); /* Unregister menu actions */ visualizer.unregisterSimulationMenuAction(RangeMenuAction.class); visualizer.unregisterSimulationMenuAction(SuccessRatioMenuAction.class); } + @Override public Color[] getColorOf(Mote mote) { Mote selectedMote = visualizer.getSelectedMote(); if (mote == selectedMote) { @@ -235,6 +266,7 @@ public class UDGMVisualizerSkin implements VisualizerSkin { return null; } + @Override public void paintBeforeMotes(Graphics g) { Mote selectedMote = visualizer.getSelectedMote(); if (simulation == null @@ -334,53 +366,86 @@ public class UDGMVisualizerSkin implements VisualizerSkin { } + @Override public void paintAfterMotes(Graphics g) { } public static class RangeMenuAction implements SimulationMenuAction { + @Override public boolean isEnabled(Visualizer visualizer, Simulation simulation) { return true; } + @Override public String getDescription(Visualizer visualizer, Simulation simulation) { return "Change transmission ranges"; } + @Override public void doAction(Visualizer visualizer, Simulation simulation) { VisualizerSkin[] skins = visualizer.getCurrentSkins(); - for (VisualizerSkin skin: skins) { + for (VisualizerSkin skin : skins) { if (skin instanceof UDGMVisualizerSkin) { - ((UDGMVisualizerSkin)skin).rangeTX.setVisible(true); - ((UDGMVisualizerSkin)skin).rangeINT.setVisible(true); - ((UDGMVisualizerSkin)skin).top.setVisible(true); - visualizer.repaint(); + UDGMVisualizerSkin vskin = ((UDGMVisualizerSkin) skin); + vskin.rangeTX.setVisible(true); + vskin.rangeINT.setVisible(true); + vskin.updateRatioRangeFrame(); } } } }; public static class SuccessRatioMenuAction implements SimulationMenuAction { + @Override public boolean isEnabled(Visualizer visualizer, Simulation simulation) { return true; } + @Override public String getDescription(Visualizer visualizer, Simulation simulation) { return "Change TX/RX success ratio"; } + @Override public void doAction(Visualizer visualizer, Simulation simulation) { VisualizerSkin[] skins = visualizer.getCurrentSkins(); for (VisualizerSkin skin: skins) { if (skin instanceof UDGMVisualizerSkin) { - ((UDGMVisualizerSkin)skin).ratioTX.setVisible(true); - ((UDGMVisualizerSkin)skin).ratioRX.setVisible(true); - ((UDGMVisualizerSkin)skin).top.setVisible(true); - visualizer.repaint(); + UDGMVisualizerSkin vskin = ((UDGMVisualizerSkin) skin); + vskin.ratioTX.setVisible(true); + vskin.ratioRX.setVisible(true); + vskin.updateRatioRangeFrame(); } } } }; + private void updateRatioRangeFrame() { + if (rrFrame.getDesktopPane() == null) { + visualizer.getDesktopPane().add(rrFrame); + } + rrFrame.pack(); + /* Place frame at the upper right corner of the visualizer canvas */ + Point visCanvasPos = SwingUtilities.convertPoint( + visualizer.getCurrentCanvas(), + visualizer.getCurrentCanvas().getLocation(), + visualizer.getDesktopPane()); + rrFrame.setLocation( + visCanvasPos.x + visualizer.getCurrentCanvas().getWidth() - rrFrame.getWidth(), + visCanvasPos.y); + /* Try to place on top with focus */ + rrFrame.setLayer(JLayeredPane.MODAL_LAYER); + rrFrame.setVisible(true); + rrFrame.moveToFront(); + try { + rrFrame.setSelected(true); + } + catch (PropertyVetoException ex) { + logger.warn("Failed getting focus"); + } + } + + @Override public Visualizer getVisualizer() { return visualizer; } From 3062e9175f5151265f78b6aa7a32ed208dbec45f Mon Sep 17 00:00:00 2001 From: Luiz Eduardo Date: Mon, 24 Feb 2014 23:34:16 -0200 Subject: [PATCH 12/92] typo in event resource handler comment at line 531 says PERIODIC_RESOURCE, shouldn't it be EVENT_RESOURCE, since it's a EVENT_RESOURCE demo? --- examples/er-rest-example/er-example-server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/er-rest-example/er-example-server.c b/examples/er-rest-example/er-example-server.c index aae05acf9..f5d9ea9a6 100644 --- a/examples/er-rest-example/er-example-server.c +++ b/examples/er-rest-example/er-example-server.c @@ -528,7 +528,7 @@ event_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred /* A post_handler that handles subscriptions/observing will be called for periodic resources by the framework. */ } -/* Additionally, a handler function named [resource name]_event_handler must be implemented for each PERIODIC_RESOURCE defined. +/* Additionally, a handler function named [resource name]_event_handler must be implemented for each EVENT_RESOURCE defined. * It will be called by the REST manager process with the defined period. */ void event_event_handler(resource_t *r) From 5edd6bc75bbc53021d32b96fe5d3a18d4e633637 Mon Sep 17 00:00:00 2001 From: Nelson Kigen Date: Wed, 26 Feb 2014 19:38:10 +0100 Subject: [PATCH 13/92] New MACRO for creating jsontree_array This proposed MACRO simplifies jsontree_array declarations. It takes as arguments the name of the array and its size. ( I've modified the indention as requested ) --- apps/json/jsontree.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/apps/json/jsontree.h b/apps/json/jsontree.h index 476487183..491e29ac9 100644 --- a/apps/json/jsontree.h +++ b/apps/json/jsontree.h @@ -115,6 +115,13 @@ struct jsontree_array { JSON_TYPE_OBJECT, \ sizeof(jsontree_pair_##name)/sizeof(struct jsontree_pair), \ jsontree_pair_##name } + +#define JSONTREE_ARRAY(name, count) \ + static struct jsontree_value *jsontree_value##name[count]; \ + static struct jsontree_array name = { \ + JSON_TYPE_ARRAY, \ + count, \ + jsontree_value##name } void jsontree_setup(struct jsontree_context *js_ctx, struct jsontree_value *root, int (* putchar)(int)); From 3e5e054f2a71594f6aafc48bc97b98166cc57d9a Mon Sep 17 00:00:00 2001 From: Oliver Schmidt Date: Wed, 26 Feb 2014 20:23:09 +0100 Subject: [PATCH 14/92] Adjusted base address to final product. --- cpu/6502/ethconfig/ethconfig.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpu/6502/ethconfig/ethconfig.c b/cpu/6502/ethconfig/ethconfig.c index c710a7fa6..8dd9dba2f 100644 --- a/cpu/6502/ethconfig/ethconfig.c +++ b/cpu/6502/ethconfig/ethconfig.c @@ -11,7 +11,7 @@ static struct { } drivers[] = { #ifdef __APPLE2__ {"Uthernet", 0xC080, "cs8900a.eth" }, - {"Uthernet II", 0xC080, "w5100.eth" }, + {"Uthernet II", 0xC084, "w5100.eth" }, {"LANceGS", 0xC080, "lan91c96.eth"} #endif #ifdef __ATARI__ From b6c9950b94a52d8dbf4288d0eca37ba7b9e9aeb0 Mon Sep 17 00:00:00 2001 From: Oliver Schmidt Date: Thu, 27 Feb 2014 20:23:41 +0100 Subject: [PATCH 15/92] Adjust shadow register to full 8kB RX buffer. --- cpu/6502/net/w5100.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpu/6502/net/w5100.S b/cpu/6502/net/w5100.S index 2f5bb8ae7..3952c1121 100644 --- a/cpu/6502/net/w5100.S +++ b/cpu/6502/net/w5100.S @@ -202,8 +202,8 @@ fixup11:ora data ; Lobyte ; Calculate and set physical address jsr set_addrphysical - ; Move physical address shadow to $F000-$FFFF - ora #>$F000 + ; Move physical address shadow to $E000-$FFFF + ora #>$8000 tax ; Read MAC raw 2byte packet size header From aef0e9eae6c19c325a616e1f3ccdca862492e625 Mon Sep 17 00:00:00 2001 From: Nicolas Tsiftes Date: Mon, 24 Feb 2014 16:58:33 +0100 Subject: [PATCH 16/92] Ensure that the file end is updated in the original file extent if it has been overwritten through a micro log operation. --- core/cfs/cfs-coffee.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/core/cfs/cfs-coffee.c b/core/cfs/cfs-coffee.c index 668c5c83f..d760199a7 100644 --- a/core/cfs/cfs-coffee.c +++ b/core/cfs/cfs-coffee.c @@ -1155,6 +1155,7 @@ cfs_write(int fd, const void *buf, unsigned size) int i; struct log_param lp; cfs_offset_t bytes_left; + int8_t need_dummy_write; const char dummy[1] = { 0xff }; #endif @@ -1188,6 +1189,7 @@ cfs_write(int fd, const void *buf, unsigned size) #else if(FILE_MODIFIED(file) || fdp->offset < file->end) { #endif + need_dummy_write = 0; for(bytes_left = size; bytes_left > 0;) { lp.offset = fdp->offset; lp.buf = buf; @@ -1212,13 +1214,19 @@ cfs_write(int fd, const void *buf, unsigned size) occur while writing log records. */ if(fdp->offset > file->end) { file->end = fdp->offset; + need_dummy_write = 1; } } } - if(fdp->offset > file->end) { - /* Update the original file's end with a dummy write. */ - COFFEE_WRITE(dummy, 1, absolute_offset(file->page, fdp->offset)); + if(need_dummy_write) { + /* + * A log record has been written at an offset beyond the original + * extent's end. Consequently, we need to write a dummy value at the + * corresponding end offset in the original extent to ensure that + * the correct file size is calculated when opening the file again. + */ + COFFEE_WRITE(dummy, 1, absolute_offset(file->page, fdp->offset - 1)); } } else { #endif /* COFFEE_MICRO_LOGS */ From 067bbc9ee0a043d7cd3928b30058aab98f1dbe83 Mon Sep 17 00:00:00 2001 From: George Oikonomou Date: Wed, 28 Aug 2013 14:12:41 +0100 Subject: [PATCH 17/92] Check for DAO fwd loop early, before processing DAO options --- core/net/rpl/rpl-icmp6.c | 56 ++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/core/net/rpl/rpl-icmp6.c b/core/net/rpl/rpl-icmp6.c index 1ee1678b1..c7f950cbb 100644 --- a/core/net/rpl/rpl-icmp6.c +++ b/core/net/rpl/rpl-icmp6.c @@ -622,6 +622,34 @@ dao_input(void) /* Perhaps, there are verification to do but ... */ } + learned_from = uip_is_addr_mcast(&dao_sender_addr) ? + RPL_ROUTE_FROM_MULTICAST_DAO : RPL_ROUTE_FROM_UNICAST_DAO; + + PRINTF("RPL: DAO from %s\n", + learned_from == RPL_ROUTE_FROM_UNICAST_DAO? "unicast": "multicast"); + if(learned_from == RPL_ROUTE_FROM_UNICAST_DAO) { + /* Check whether this is a DAO forwarding loop. */ + p = rpl_find_parent(dag, &dao_sender_addr); + /* 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, instance), DAG_RANK(dag->rank, instance)); + p->rank = INFINITE_RANK; + p->updated = 1; + return; + } + + /* If we get the DAO from our parent, we also have a loop. */ + if(p != NULL && p == dag->preferred_parent) { + PRINTF("RPL: Loop detected when receiving a unicast DAO from our parent\n"); + p->rank = INFINITE_RANK; + p->updated = 1; + return; + } + } + /* Check if there are any RPL options present. */ for(i = pos; i < buffer_length; i += len) { subopt_type = buffer[i]; @@ -687,34 +715,6 @@ dao_input(void) return; } - learned_from = uip_is_addr_mcast(&dao_sender_addr) ? - RPL_ROUTE_FROM_MULTICAST_DAO : RPL_ROUTE_FROM_UNICAST_DAO; - - PRINTF("RPL: DAO from %s\n", - learned_from == RPL_ROUTE_FROM_UNICAST_DAO? "unicast": "multicast"); - if(learned_from == RPL_ROUTE_FROM_UNICAST_DAO) { - /* Check whether this is a DAO forwarding loop. */ - p = rpl_find_parent(dag, &dao_sender_addr); - /* 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, instance), DAG_RANK(dag->rank, instance)); - p->rank = INFINITE_RANK; - p->updated = 1; - return; - } - - /* If we get the DAO from our parent, we also have a loop. */ - if(p != NULL && p == dag->preferred_parent) { - PRINTF("RPL: Loop detected when receiving a unicast DAO from our parent\n"); - p->rank = INFINITE_RANK; - p->updated = 1; - return; - } - } - PRINTF("RPL: adding DAO route\n"); if((nbr = uip_ds6_nbr_lookup(&dao_sender_addr)) == NULL) { From be098f39e81fdfd75b75edd201e049aa1b8d6d78 Mon Sep 17 00:00:00 2001 From: George Oikonomou Date: Fri, 11 Nov 2011 11:32:18 +0000 Subject: [PATCH 18/92] Define a new ICMPv6 message type for Trickle Multicast Pending IANA allocation, we currently use private experimentation --- core/net/ipv6/uip-icmp6.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/net/ipv6/uip-icmp6.h b/core/net/ipv6/uip-icmp6.h index 9441cbc0e..fd5f7136f 100644 --- a/core/net/ipv6/uip-icmp6.h +++ b/core/net/ipv6/uip-icmp6.h @@ -65,6 +65,11 @@ #define ICMP6_REDIRECT 137 /**< Redirect */ #define ICMP6_RPL 155 /**< RPL */ +#define ICMP6_PRIV_EXP_100 100 /**< Private Experimentation */ +#define ICMP6_PRIV_EXP_101 101 /**< Private Experimentation */ +#define ICMP6_PRIV_EXP_200 200 /**< Private Experimentation */ +#define ICMP6_PRIV_EXP_201 201 /**< Private Experimentation */ +#define ICMP6_ROLL_TM ICMP6_PRIV_EXP_200 /**< ROLL Trickle Multicast */ /** @} */ From 68c5584488d7c45bfb23781552c6afce66c24fe2 Mon Sep 17 00:00:00 2001 From: George Oikonomou Date: Fri, 11 Nov 2011 11:34:05 +0000 Subject: [PATCH 19/92] New uip_is_addr macros for multicast addresses --- core/net/ip/uip.h | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/core/net/ip/uip.h b/core/net/ip/uip.h index 076734396..c6a50d699 100644 --- a/core/net/ip/uip.h +++ b/core/net/ip/uip.h @@ -2093,6 +2093,35 @@ CCIF extern uip_lladdr_t uip_lladdr; #define uip_is_addr_mcast(a) \ (((a)->u8[0]) == 0xFF) +/** + * \brief is address a global multicast address (FFxE::/16), + * a is of type uip_ip6addr_t* + * */ +#define uip_is_addr_mcast_global(a) \ + ((((a)->u8[0]) == 0xFF) && \ + (((a)->u8[1] & 0x0F) == 0x0E)) + +/** + * \brief is address a non-routable multicast address. + * Scopes 1 (interface-local) and 2 (link-local) are non-routable + * See RFC4291 and draft-ietf-6man-multicast-scopes + * a is of type uip_ip6addr_t* + * */ +#define uip_is_addr_mcast_non_routable(a) \ + ((((a)->u8[0]) == 0xFF) && \ + (((a)->u8[1] & 0x0F) <= 0x02)) + +/** + * \brief is address a routable multicast address. + * Scope 3 (Realm-Local) or higher are routable + * Realm-Local scope is defined in draft-ietf-6man-multicast-scopes + * See RFC4291 and draft-ietf-6man-multicast-scopes + * a is of type uip_ip6addr_t* + * */ +#define uip_is_addr_mcast_routable(a) \ + ((((a)->u8[0]) == 0xFF) && \ + (((a)->u8[1] & 0x0F) > 0x02)) + /** * \brief is group-id of multicast address a * the all nodes group-id From e85d935ccc1e1f95135f66cc431f87752ec4769b Mon Sep 17 00:00:00 2001 From: George Oikonomou Date: Fri, 11 Nov 2011 11:45:53 +0000 Subject: [PATCH 20/92] Multicast common header files --- core/net/ipv6/multicast/uip-mcast6-engines.h | 53 ++++++ core/net/ipv6/multicast/uip-mcast6.h | 175 +++++++++++++++++++ 2 files changed, 228 insertions(+) create mode 100644 core/net/ipv6/multicast/uip-mcast6-engines.h create mode 100644 core/net/ipv6/multicast/uip-mcast6.h diff --git a/core/net/ipv6/multicast/uip-mcast6-engines.h b/core/net/ipv6/multicast/uip-mcast6-engines.h new file mode 100644 index 000000000..3111b378f --- /dev/null +++ b/core/net/ipv6/multicast/uip-mcast6-engines.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2011, Loughborough University - 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 + * Header file with definition of multicast engine constants + * + * When writing a new engine, add it here with a unique number and + * then modify uip-mcast6.h accordingly + * + * \author + * George Oikonomou - + */ + +#ifndef UIP_MCAST6_ENGINES_H_ +#define UIP_MCAST6_ENGINES_H_ + +#include "net/ipv6/multicast/smrf.h" +#include "net/ipv6/multicast/roll-tm.h" + +#define UIP_MCAST6_ENGINE_NONE 0 /* Selecting this disables mcast */ +#define UIP_MCAST6_ENGINE_SMRF 1 +#define UIP_MCAST6_ENGINE_ROLL_TM 2 + +#endif /* UIP_MCAST6_ENGINES_H_ */ diff --git a/core/net/ipv6/multicast/uip-mcast6.h b/core/net/ipv6/multicast/uip-mcast6.h new file mode 100644 index 000000000..dade81aaa --- /dev/null +++ b/core/net/ipv6/multicast/uip-mcast6.h @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2011, Loughborough University - 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 + * This header file contains configuration directives for uIPv6 + * multicast support. + * + * We currently support 2 engines: + * - 'Stateless Multicast RPL Forwarding' (SMRF) + * RPL does group management as per the RPL docs, SMRF handles datagram + * forwarding + * - 'Multicast Forwarding with Trickle' according to the algorithm described + * in the internet draft: + * http://tools.ietf.org/html/draft-ietf-roll-trickle-mcast + * + * \author + * George Oikonomou - + */ + +#ifndef UIP_MCAST6_H_ +#define UIP_MCAST6_H_ + +#include "contiki-conf.h" +#include "net/ipv6/multicast/uip-mcast6-engines.h" +#include "net/ipv6/multicast/uip-mcast6-route.h" + +#include +/*---------------------------------------------------------------------------*/ +/* Constants */ +/*---------------------------------------------------------------------------*/ +#define UIP_MCAST6_DROP 0 +#define UIP_MCAST6_ACCEPT 1 +/*---------------------------------------------------------------------------*/ +/* Multicast Address Scopes (RFC 4291 & draft-ietf-6man-multicast-scopes) */ +#define UIP_MCAST6_SCOPE_INTERFACE 0x01 +#define UIP_MCAST6_SCOPE_LINK_LOCAL 0x02 +#define UIP_MCAST6_SCOPE_REALM_LOCAL 0x03 /* draft-ietf-6man-multicast-scopes */ +#define UIP_MCAST6_SCOPE_ADMIN_LOCAL 0x04 +#define UIP_MCAST6_SCOPE_SITE_LOCAL 0x05 +#define UIP_MCAST6_SCOPE_ORG_LOCAL 0x08 +#define UIP_MCAST6_SCOPE_GLOBAL 0x0E +/*---------------------------------------------------------------------------*/ +/* Choose an engine or turn off based on user configuration */ +/*---------------------------------------------------------------------------*/ +#ifdef UIP_MCAST6_CONF_ENGINE +#define UIP_MCAST6_ENGINE UIP_MCAST6_CONF_ENGINE +#else +#define UIP_MCAST6_ENGINE UIP_MCAST6_ENGINE_NONE +#endif +/*---------------------------------------------------------------------------*/ +/* + * Multicast API. Similar to NETSTACK, each engine must define a driver and + * populate the fields with suitable function pointers + */ +struct uip_mcast6_driver { + char *name; + + /** Initialize the multicast engine */ + void (* init)(void); + + /** + * \brief Process an outgoing datagram with a multicast IPv6 destination + * address + * + * This may be needed if the multicast engine needs to, for example, + * add IPv6 extension headers to the datagram, cache it, decide it + * needs dropped etc. + * + * It is sometimes desirable to let the engine handle datagram + * dispatch instead of letting the networking core do it. If the + * engine decides to send the datagram itself, it must afterwards + * set uip_len = 0 to prevent the networking core from sending too + */ + void (* out)(void); + + /** + * \brief Process an incoming multicast datagram and determine whether it + * should be delivered up the stack or not. + * + * \return 0: Drop, 1: Deliver + * + * When a datagram with a multicast destination address is received, + * the forwarding logic in core is bypassed. Instead, we let the + * multicast engine handle forwarding internally if and as necessary. + * This function is where forwarding logic must be hooked in. + * + * Once the engine is done with forwarding, it must signal via the + * return value whether the datagram needs delivered up the network + * stack. + */ + uint8_t (* in)(void); +}; +/*--------------------------------------------------------------------------- + * Multicast Statistics. + *---------------------------------------------------------------------------*/ +#ifndef UIP_MCAST6_CONF_STATS +#define UIP_MCAST6_CONF_STATS 0 +#endif +/*---------------------------------------------------------------------------*/ +/** + * \brief Get a multicast address' scope. + * a is of type uip_ip6addr_t* + */ +#define uip_mcast6_get_address_scope(a) ((a)->u8[1] & 0x0F) +/*---------------------------------------------------------------------------*/ +/* Configure multicast and core/net to play nicely with the selected engine */ +#if UIP_MCAST6_ENGINE + +/* Enable Multicast hooks in the uip6 core */ +#define UIP_CONF_IPV6_MULTICAST 1 + +#if UIP_MCAST6_ENGINE == UIP_MCAST6_ENGINE_ROLL_TM +#define RPL_CONF_MULTICAST 0 /* Not used by trickle */ +#define UIP_CONF_IPV6_ROLL_TM 1 /* ROLL Trickle ICMP type support */ + +typedef struct roll_tm_stats uip_mcast6_stats_t; +#define UIP_MCAST6_STATS roll_tm_stats +#define UIP_MCAST6 roll_tm_driver +#elif UIP_MCAST6_ENGINE == UIP_MCAST6_ENGINE_SMRF +#define RPL_CONF_MULTICAST 1 + +typedef struct smrf_stats uip_mcast6_stats_t; +#define UIP_MCAST6_STATS smrf_stats +#define UIP_MCAST6 smrf_driver +#else +#error "Multicast Enabled with an Unknown Engine." +#error "Check the value of UIP_MCAST6_CONF_ENGINE in conf files." +#endif + +extern const struct uip_mcast6_driver UIP_MCAST6; + +#if UIP_MCAST6_CONF_STATS +extern uip_mcast6_stats_t UIP_MCAST6_STATS; +#endif + +#endif /* UIP_IPV6_MULTICAST */ +/*---------------------------------------------------------------------------*/ +/* Configuration Checks */ +/*---------------------------------------------------------------------------*/ +#if RPL_CONF_MULTICAST && (!UIP_CONF_IPV6_RPL) +#error "The selected Multicast mode requires UIP_CONF_IPV6_RPL != 0" +#error "Check the value of UIP_CONF_IPV6_RPL in conf files." +#endif +/*---------------------------------------------------------------------------*/ + +#endif /* UIP_MCAST6_H_ */ From 64c21638cd4bba364042ffed3914ae0c12744183 Mon Sep 17 00:00:00 2001 From: George Oikonomou Date: Fri, 11 Nov 2011 11:48:44 +0000 Subject: [PATCH 21/92] Multicast routing table manipulation We store multicast routes in a separate table since we don't need as much information as we need for normal routes --- core/net/ipv6/multicast/uip-mcast6-route.c | 133 +++++++++++++++++++++ core/net/ipv6/multicast/uip-mcast6-route.h | 75 ++++++++++++ 2 files changed, 208 insertions(+) create mode 100644 core/net/ipv6/multicast/uip-mcast6-route.c create mode 100644 core/net/ipv6/multicast/uip-mcast6-route.h diff --git a/core/net/ipv6/multicast/uip-mcast6-route.c b/core/net/ipv6/multicast/uip-mcast6-route.c new file mode 100644 index 000000000..f99a92818 --- /dev/null +++ b/core/net/ipv6/multicast/uip-mcast6-route.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2011, Loughborough University - 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 copyright holder 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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. + */ +/** + * \file + * Multicast routing table manipulation + * + * \author + * George Oikonomou - + */ + +#include "contiki.h" +#include "lib/list.h" +#include "lib/memb.h" +#include "net/ip/uip.h" +#include "net/ipv6/multicast/uip-mcast6-route.h" + +#include +#include + +#if UIP_CONF_IPV6 +/*---------------------------------------------------------------------------*/ +/* Size of the multicast routing table */ +#ifdef UIP_MCAST6_ROUTE_CONF_ROUTES +#define UIP_MCAST6_ROUTE_ROUTES UIP_MCAST6_ROUTE_CONF_ROUTES +#else +#define UIP_MCAST6_ROUTE_ROUTES 1 +#endif /* UIP_CONF_DS6_MCAST_ROUTES */ +/*---------------------------------------------------------------------------*/ +LIST(mcast_route_list); +MEMB(mcast_route_memb, uip_mcast6_route_t, UIP_MCAST6_ROUTE_ROUTES); + +static uip_mcast6_route_t *locmcastrt; +/*---------------------------------------------------------------------------*/ +uip_mcast6_route_t * +uip_mcast6_route_lookup(uip_ipaddr_t *group) +{ + locmcastrt = NULL; + for(locmcastrt = list_head(mcast_route_list); + locmcastrt != NULL; + locmcastrt = list_item_next(locmcastrt)) { + if(uip_ipaddr_cmp(&locmcastrt->group, group)) { + return locmcastrt; + } + } + + return NULL; +} +/*---------------------------------------------------------------------------*/ +uip_mcast6_route_t * +uip_mcast6_route_add(uip_ipaddr_t *group) +{ + /* _lookup must return NULL, i.e. the prefix does not exist in our table */ + locmcastrt = uip_mcast6_route_lookup(group); + if(locmcastrt == NULL) { + /* Allocate an entry and add the group to the list */ + locmcastrt = memb_alloc(&mcast_route_memb); + if(locmcastrt == NULL) { + return NULL; + } + list_add(mcast_route_list, locmcastrt); + } + + /* Reaching here means we either found the prefix or allocated a new one */ + + uip_ipaddr_copy(&(locmcastrt->group), group); + + return locmcastrt; +} +/*---------------------------------------------------------------------------*/ +void +uip_mcast6_route_rm(uip_mcast6_route_t *route) +{ + /* Make sure it's actually in the list */ + for(locmcastrt = list_head(mcast_route_list); + locmcastrt != NULL; + locmcastrt = list_item_next(locmcastrt)) { + if(locmcastrt == route) { + list_remove(mcast_route_list, route); + memb_free(&mcast_route_memb, route); + return; + } + } +} +/*---------------------------------------------------------------------------*/ +uip_mcast6_route_t * +uip_mcast6_route_list_head(void) +{ + return list_head(mcast_route_list); +} +/*---------------------------------------------------------------------------*/ +int +uip_mcast6_route_count(void) +{ + return list_length(mcast_route_list); +} +/*---------------------------------------------------------------------------*/ +void +uip_mcast6_route_init() +{ + memb_init(&mcast_route_memb); + list_init(mcast_route_list); +} +/*---------------------------------------------------------------------------*/ + +#endif /* UIP_CONF_IPV6 */ diff --git a/core/net/ipv6/multicast/uip-mcast6-route.h b/core/net/ipv6/multicast/uip-mcast6-route.h new file mode 100644 index 000000000..ef5d43f77 --- /dev/null +++ b/core/net/ipv6/multicast/uip-mcast6-route.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2011, Loughborough University - 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 copyright holder 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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. + */ +/** + * \file + * Multicast routing table manipulation + * + * \author + * George Oikonomou - + */ +#ifndef UIP_MCAST6_ROUTE_H_ +#define UIP_MCAST6_ROUTE_H_ + +#include "contiki.h" +#include "net/ip/uip.h" + +#include +/*---------------------------------------------------------------------------*/ +/** \brief An entry in the multicast routing table */ +typedef struct uip_mcast6_route { + struct uip_mcast6_route *next; + uip_ipaddr_t group; + uint32_t lifetime; /* seconds */ + void *dag; /* Pointer to an rpl_dag_t struct */ +} uip_mcast6_route_t; +/*---------------------------------------------------------------------------*/ +/** \name Multicast Routing Table Manipulation */ +/** @{ */ +uip_mcast6_route_t *uip_mcast6_route_lookup(uip_ipaddr_t *group); +uip_mcast6_route_t *uip_mcast6_route_add(uip_ipaddr_t *group); +void uip_mcast6_route_rm(uip_mcast6_route_t *defrt); +int uip_mcast6_route_count(void); +uip_mcast6_route_t *uip_mcast6_route_list_head(void); +/*---------------------------------------------------------------------------*/ +/** + * \brief Multicast routing table init routine + * + * Multicast routing tables are not necessarily required by all + * multicast engines. For instance, trickle multicast does not rely on + * the existence of a routing table. Therefore, this function here + * should be invoked by each engine's init routine only if the relevant + * functionality is required. This is also why this function should not + * get hooked into the uip-ds6 core. + */ +void uip_mcast6_route_init(void); +/** @} */ + +#endif /* UIP_MCAST6_ROUTE_H_ */ From 0ad09aa842ab4619f8e978e8c268b74ad37b114b Mon Sep 17 00:00:00 2001 From: George Oikonomou Date: Fri, 11 Nov 2011 11:51:25 +0000 Subject: [PATCH 22/92] We now know how to select our source address for outgoing routable multicast datagrams --- core/net/ipv6/uip-ds6.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/net/ipv6/uip-ds6.c b/core/net/ipv6/uip-ds6.c index 3594f46e1..c5c169afe 100644 --- a/core/net/ipv6/uip-ds6.c +++ b/core/net/ipv6/uip-ds6.c @@ -512,6 +512,10 @@ uip_ds6_select_src(uip_ipaddr_t *src, uip_ipaddr_t *dst) } } } +#if UIP_IPV6_MULTICAST + } else if(uip_is_addr_mcast_routable(dst)) { + matchaddr = uip_ds6_get_global(ADDR_PREFERRED); +#endif } else { matchaddr = uip_ds6_get_link_local(ADDR_PREFERRED); } From da4ce5b54d1473fc28d3b2528c5b003af89f1882 Mon Sep 17 00:00:00 2001 From: George Oikonomou Date: Fri, 9 Dec 2011 12:15:04 +0000 Subject: [PATCH 23/92] RPL Multicast group management with MOP 3 --- core/net/rpl/rpl-dag.c | 8 ++++++++ core/net/rpl/rpl-icmp6.c | 20 ++++++++++++++++++++ core/net/rpl/rpl-private.h | 17 +++++++++++++++++ core/net/rpl/rpl-timers.c | 30 ++++++++++++++++++++++++++++++ core/net/rpl/rpl.c | 34 ++++++++++++++++++++++++++++++++++ 5 files changed, 109 insertions(+) diff --git a/core/net/rpl/rpl-dag.c b/core/net/rpl/rpl-dag.c index e83e790bc..e103d65f9 100644 --- a/core/net/rpl/rpl-dag.c +++ b/core/net/rpl/rpl-dag.c @@ -38,6 +38,7 @@ * Logic for Directed Acyclic Graphs in RPL. * * \author Joakim Eriksson , Nicolas Tsiftes + * Contributors: George Oikonomou (multicast) */ @@ -46,6 +47,7 @@ #include "net/ip/uip.h" #include "net/ipv6/uip-nd6.h" #include "net/nbr-table.h" +#include "net/ipv6/multicast/uip-mcast6.h" #include "lib/list.h" #include "lib/memb.h" #include "sys/ctimer.h" @@ -1147,7 +1149,13 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio) rpl_dag_t *dag, *previous_dag; rpl_parent_t *p; +#if RPL_CONF_MULTICAST + /* If the root is advertising MOP 2 but we support MOP 3 we can still join + * In that scenario, we suppress DAOs for multicast targets */ + if(dio->mop < RPL_MOP_STORING_NO_MULTICAST) { +#else if(dio->mop != RPL_MOP_DEFAULT) { +#endif PRINTF("RPL: Ignoring a DIO with an unsupported MOP: %d\n", dio->mop); return; } diff --git a/core/net/rpl/rpl-icmp6.c b/core/net/rpl/rpl-icmp6.c index c7f950cbb..c1cc6060b 100644 --- a/core/net/rpl/rpl-icmp6.c +++ b/core/net/rpl/rpl-icmp6.c @@ -40,6 +40,7 @@ * \author Joakim Eriksson , Nicolas Tsiftes * Contributors: Niclas Finne , Joel Hoglund , * Mathieu Pouillot + * George Oikonomou (multicast) */ #include "net/ip/tcpip.h" @@ -49,6 +50,7 @@ #include "net/ipv6/uip-icmp6.h" #include "net/rpl/rpl-private.h" #include "net/packetbuf.h" +#include "net/ipv6/multicast/uip-mcast6.h" #include #include @@ -86,6 +88,9 @@ static uint8_t dao_sequence = RPL_LOLLIPOP_INIT; extern rpl_of_t RPL_OF; +#if RPL_CONF_MULTICAST +static uip_mcast6_route_t *mcast_group; +#endif /*---------------------------------------------------------------------------*/ static int get_global_addr(uip_ipaddr_t *addr) @@ -682,6 +687,17 @@ dao_input(void) PRINT6ADDR(&prefix); PRINTF("\n"); +#if RPL_CONF_MULTICAST + if(uip_is_addr_mcast_global(&prefix)) { + mcast_group = uip_mcast6_route_add(&prefix); + if(mcast_group) { + mcast_group->dag = dag; + mcast_group->lifetime = RPL_LIFETIME(instance, lifetime); + } + goto fwd_dao; + } +#endif + rep = uip_ds6_route_lookup(&prefix); if(lifetime == RPL_ZERO_LIFETIME) { @@ -752,6 +768,10 @@ dao_input(void) rep->state.lifetime = RPL_LIFETIME(instance, lifetime); rep->state.learned_from = learned_from; +#if RPL_CONF_MULTICAST +fwd_dao: +#endif + if(learned_from == RPL_ROUTE_FROM_UNICAST_DAO) { if(dag->preferred_parent != NULL && rpl_get_parent_ipaddr(dag->preferred_parent) != NULL) { diff --git a/core/net/rpl/rpl-private.h b/core/net/rpl/rpl-private.h index acabda4b7..0df8a91ca 100644 --- a/core/net/rpl/rpl-private.h +++ b/core/net/rpl/rpl-private.h @@ -44,6 +44,7 @@ #include "sys/clock.h" #include "sys/ctimer.h" #include "net/ipv6/uip-ds6.h" +#include "net/ipv6/multicast/uip-mcast6.h" /*---------------------------------------------------------------------------*/ /** \brief Is IPv6 address addr the link-local, all-RPL-nodes @@ -177,8 +178,24 @@ #ifdef RPL_CONF_MOP #define RPL_MOP_DEFAULT RPL_CONF_MOP +#else /* RPL_CONF_MOP */ +#if RPL_CONF_MULTICAST +#define RPL_MOP_DEFAULT RPL_MOP_STORING_MULTICAST #else #define RPL_MOP_DEFAULT RPL_MOP_STORING_NO_MULTICAST +#endif /* UIP_IPV6_MULTICAST_RPL */ +#endif /* RPL_CONF_MOP */ + +/* Emit a pre-processor error if the user configured multicast with bad MOP */ +#if RPL_CONF_MULTICAST && (RPL_MOP_DEFAULT != RPL_MOP_STORING_MULTICAST) +#error "RPL Multicast requires RPL_MOP_DEFAULT==3. Check contiki-conf.h" +#endif + +/* Multicast Route Lifetime as a multiple of the lifetime unit */ +#ifdef RPL_CONF_MCAST_LIFETIME +#define RPL_MCAST_LIFETIME RPL_CONF_MCAST_LIFETIME +#else +#define RPL_MCAST_LIFETIME 3 #endif /* diff --git a/core/net/rpl/rpl-timers.c b/core/net/rpl/rpl-timers.c index 4465bd81b..b4c25df19 100644 --- a/core/net/rpl/rpl-timers.c +++ b/core/net/rpl/rpl-timers.c @@ -41,6 +41,7 @@ #include "contiki-conf.h" #include "net/rpl/rpl-private.h" +#include "net/ipv6/multicast/uip-mcast6.h" #include "lib/random.h" #include "sys/ctimer.h" @@ -220,6 +221,10 @@ static void handle_dao_timer(void *ptr) { rpl_instance_t *instance; +#if RPL_CONF_MULTICAST + uip_mcast6_route_t *mcast_route; + uint8_t i; +#endif instance = (rpl_instance_t *)ptr; @@ -234,6 +239,31 @@ handle_dao_timer(void *ptr) PRINTF("RPL: handle_dao_timer - sending DAO\n"); /* Set the route lifetime to the default value. */ dao_output(instance->current_dag->preferred_parent, instance->default_lifetime); + +#if RPL_CONF_MULTICAST + /* Send DAOs for multicast prefixes only if the instance is in MOP 3 */ + if(instance->mop == RPL_MOP_STORING_MULTICAST) { + /* Send a DAO for own multicast addresses */ + for(i = 0; i < UIP_DS6_MADDR_NB; i++) { + if(uip_ds6_if.maddr_list[i].isused + && uip_is_addr_mcast_global(&uip_ds6_if.maddr_list[i].ipaddr)) { + dao_output_target(instance->current_dag->preferred_parent, + &uip_ds6_if.maddr_list[i].ipaddr, RPL_MCAST_LIFETIME); + } + } + + /* Iterate over multicast routes and send DAOs */ + mcast_route = uip_mcast6_route_list_head(); + while(mcast_route != NULL) { + /* Don't send if it's also our own address, done that already */ + if(uip_ds6_maddr_lookup(&mcast_route->group) == NULL) { + dao_output_target(instance->current_dag->preferred_parent, + &mcast_route->group, RPL_MCAST_LIFETIME); + } + mcast_route = list_item_next(mcast_route); + } + } +#endif } else { PRINTF("RPL: No suitable DAO parent\n"); } diff --git a/core/net/rpl/rpl.c b/core/net/rpl/rpl.c index 574497235..9fca4c28e 100644 --- a/core/net/rpl/rpl.c +++ b/core/net/rpl/rpl.c @@ -44,6 +44,7 @@ #include "net/ip/tcpip.h" #include "net/ipv6/uip-ds6.h" #include "net/rpl/rpl-private.h" +#include "net/ipv6/multicast/uip-mcast6.h" #define DEBUG DEBUG_NONE #include "net/ip/uip-debug.h" @@ -105,6 +106,9 @@ rpl_purge_routes(void) uip_ds6_route_t *r; uip_ipaddr_t prefix; rpl_dag_t *dag; +#if RPL_CONF_MULTICAST + uip_mcast6_route_t *mcast_route; +#endif /* First pass, decrement lifetime */ r = uip_ds6_route_head(); @@ -146,12 +150,29 @@ rpl_purge_routes(void) r = uip_ds6_route_next(r); } } + +#if RPL_CONF_MULTICAST + mcast_route = uip_mcast6_route_list_head(); + + while(mcast_route != NULL) { + if(mcast_route->lifetime <= 1) { + uip_mcast6_route_rm(mcast_route); + mcast_route = uip_mcast6_route_list_head(); + } else { + mcast_route->lifetime--; + mcast_route = list_item_next(mcast_route); + } + } +#endif } /*---------------------------------------------------------------------------*/ void rpl_remove_routes(rpl_dag_t *dag) { uip_ds6_route_t *r; +#if RPL_CONF_MULTICAST + uip_mcast6_route_t *mcast_route; +#endif r = uip_ds6_route_head(); @@ -163,6 +184,19 @@ rpl_remove_routes(rpl_dag_t *dag) r = uip_ds6_route_next(r); } } + +#if RPL_CONF_MULTICAST + mcast_route = uip_mcast6_route_list_head(); + + while(mcast_route != NULL) { + if(mcast_route->dag == dag) { + uip_mcast6_route_rm(mcast_route); + mcast_route = uip_mcast6_route_list_head(); + } else { + mcast_route = list_item_next(mcast_route); + } + } +#endif } /*---------------------------------------------------------------------------*/ void From 6f3a1eb0324617900e2e05deeaa28d3ec91c7b12 Mon Sep 17 00:00:00 2001 From: George Oikonomou Date: Fri, 11 Nov 2011 12:06:03 +0000 Subject: [PATCH 24/92] Implementation of the SMRF multicast engine --- core/net/ipv6/multicast/smrf.c | 219 +++++++++++++++++++++++++++++++++ core/net/ipv6/multicast/smrf.h | 75 +++++++++++ 2 files changed, 294 insertions(+) create mode 100644 core/net/ipv6/multicast/smrf.c create mode 100644 core/net/ipv6/multicast/smrf.h diff --git a/core/net/ipv6/multicast/smrf.c b/core/net/ipv6/multicast/smrf.c new file mode 100644 index 000000000..b779b58e8 --- /dev/null +++ b/core/net/ipv6/multicast/smrf.c @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2010, Loughborough University - 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 + * This file implements 'Stateless Multicast RPL Forwarding' (SMRF) + * + * It will only work in RPL networks in MOP 3 "Storing with Multicast" + * + * \author + * George Oikonomou - + */ + +#include "contiki.h" +#include "contiki-net.h" +#include "net/ipv6/multicast/uip-mcast6.h" +#include "net/ipv6/multicast/uip-mcast6-route.h" +#include "net/ipv6/multicast/smrf.h" +#include "net/rpl/rpl.h" +#include "net/netstack.h" +#include + +#define DEBUG DEBUG_NONE +#include "net/ip/uip-debug.h" + +#if UIP_CONF_IPV6 +/*---------------------------------------------------------------------------*/ +/* Macros */ +/*---------------------------------------------------------------------------*/ +/* CCI */ +#define SMRF_FWD_DELAY() NETSTACK_RDC.channel_check_interval() +/* Number of slots in the next 500ms */ +#define SMRF_INTERVAL_COUNT ((CLOCK_SECOND >> 2) / fwd_delay) +/*---------------------------------------------------------------------------*/ +/* Internal Data */ +/*---------------------------------------------------------------------------*/ +static struct ctimer mcast_periodic; +static uint8_t mcast_len; +static uip_buf_t mcast_buf; +static uint8_t fwd_delay; +static uint8_t fwd_spread; + +/* Maintain Stats */ +#if UIP_MCAST6_CONF_STATS +struct smrf_stats smrf_stats; +#define STATS_ADD(x) smrf_stats.x++ +#define STATS_RESET() do { memset(&smrf_stats, 0, sizeof(smrf_stats)); } while(0) +#else +#define STATS_ADD(x) +#define STATS_RESET() +#endif +/*---------------------------------------------------------------------------*/ +/* uIPv6 Pointers */ +/*---------------------------------------------------------------------------*/ +#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) +/*---------------------------------------------------------------------------*/ +static void +mcast_fwd(void *p) +{ + memcpy(uip_buf, &mcast_buf, mcast_len); + uip_len = mcast_len; + UIP_IP_BUF->ttl--; + tcpip_output(NULL); + uip_len = 0; +} +/*---------------------------------------------------------------------------*/ +static uint8_t +in() +{ + rpl_dag_t *d; /* Our DODAG */ + uip_ipaddr_t *parent_ipaddr; /* Our pref. parent's IPv6 address */ + const uip_lladdr_t *parent_lladdr; /* Our pref. parent's LL address */ + + /* + * Fetch a pointer to the LL address of our preferred parent + * + * ToDo: This rpl_get_any_dag() call is a dirty replacement of the previous + * rpl_get_dag(RPL_DEFAULT_INSTANCE); + * so that things can compile with the new RPL code. This needs updated to + * read instance ID from the RPL HBHO and use the correct parent accordingly + */ + d = rpl_get_any_dag(); + if(!d) { + STATS_ADD(mcast_dropped); + return UIP_MCAST6_DROP; + } + + /* Retrieve our preferred parent's LL address */ + parent_ipaddr = rpl_get_parent_ipaddr(d->preferred_parent); + parent_lladdr = uip_ds6_nbr_lladdr_from_ipaddr(parent_ipaddr); + + if(parent_lladdr == NULL) { + STATS_ADD(mcast_dropped); + return UIP_MCAST6_DROP; + } + + /* + * We accept a datagram if it arrived from our preferred parent, discard + * otherwise. + */ + if(memcmp(parent_lladdr, packetbuf_addr(PACKETBUF_ADDR_SENDER), + UIP_LLADDR_LEN)) { + PRINTF("SMRF: Routable in but SMRF ignored it\n"); + STATS_ADD(mcast_dropped); + return UIP_MCAST6_DROP; + } + + if(UIP_IP_BUF->ttl <= 1) { + STATS_ADD(mcast_dropped); + return UIP_MCAST6_DROP; + } + + STATS_ADD(mcast_in_all); + STATS_ADD(mcast_in_unique); + + /* If we have an entry in the mcast routing table, something with + * a higher RPL rank (somewhere down the tree) is a group member */ + if(uip_mcast6_route_lookup(&UIP_IP_BUF->destipaddr)) { + /* If we enter here, we will definitely forward */ + STATS_ADD(mcast_fwd); + + /* + * Add a delay (D) of at least SMRF_FWD_DELAY() to compensate for how + * contikimac handles broadcasts. We can't start our TX before the sender + * has finished its own. + */ + fwd_delay = SMRF_FWD_DELAY(); + + /* Finalise D: D = min(SMRF_FWD_DELAY(), SMRF_MIN_FWD_DELAY) */ +#if SMRF_MIN_FWD_DELAY + if(fwd_delay < SMRF_MIN_FWD_DELAY) { + fwd_delay = SMRF_MIN_FWD_DELAY; + } +#endif + + if(fwd_delay == 0) { + /* No delay required, send it, do it now, why wait? */ + UIP_IP_BUF->ttl--; + tcpip_output(NULL); + UIP_IP_BUF->ttl++; /* Restore before potential upstack delivery */ + } else { + /* Randomise final delay in [D , D*Spread], step D */ + fwd_spread = SMRF_INTERVAL_COUNT; + if(fwd_spread > SMRF_MAX_SPREAD) { + fwd_spread = SMRF_MAX_SPREAD; + } + if(fwd_spread) { + fwd_delay = fwd_delay * (1 + ((random_rand() >> 11) % fwd_spread)); + } + + memcpy(&mcast_buf, uip_buf, uip_len); + mcast_len = uip_len; + ctimer_set(&mcast_periodic, fwd_delay, mcast_fwd, NULL); + } + PRINTF("SMRF: %u bytes: fwd in %u [%u]\n", + uip_len, fwd_delay, fwd_spread); + } + + /* Done with this packet unless we are a member of the mcast group */ + if(!uip_ds6_is_my_maddr(&UIP_IP_BUF->destipaddr)) { + PRINTF("SMRF: Not a group member. No further processing\n"); + return UIP_MCAST6_DROP; + } else { + PRINTF("SMRF: Ours. Deliver to upper layers\n"); + STATS_ADD(mcast_in_ours); + return UIP_MCAST6_ACCEPT; + } +} +/*---------------------------------------------------------------------------*/ +static void +init() +{ + STATS_RESET(); + uip_mcast6_route_init(); +} +/*---------------------------------------------------------------------------*/ +static void +out() +{ + return; +} +/*---------------------------------------------------------------------------*/ +const struct uip_mcast6_driver smrf_driver = { + "SMRF", + init, + out, + in, +}; +/*---------------------------------------------------------------------------*/ + +#endif /* UIP_CONF_IPV6 */ diff --git a/core/net/ipv6/multicast/smrf.h b/core/net/ipv6/multicast/smrf.h new file mode 100644 index 000000000..d19fd6de8 --- /dev/null +++ b/core/net/ipv6/multicast/smrf.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2011, Loughborough University - 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 + * Header file for 'Stateless Multicast RPL Forwarding' (SMRF) + * + * \author + * George Oikonomou - + */ + +#ifndef SMRF_H_ +#define SMRF_H_ + +#include "contiki-conf.h" + +#include +/*---------------------------------------------------------------------------*/ +/* Configuration */ +/*---------------------------------------------------------------------------*/ +/* Fmin */ +#ifdef SMRF_CONF_MIN_FWD_DELAY +#define SMRF_MIN_FWD_DELAY SMRF_CONF_MIN_FWD_DELAY +#else +#define SMRF_MIN_FWD_DELAY 4 +#endif + +/* Max Spread */ +#ifdef SMRF_CONF_MAX_SPREAD +#define SMRF_MAX_SPREAD SMRF_CONF_MAX_SPREAD +#else +#define SMRF_MAX_SPREAD 4 +#endif +/*---------------------------------------------------------------------------*/ +/* Stats datatype */ +/*---------------------------------------------------------------------------*/ +struct smrf_stats { + uint16_t mcast_in_unique; + uint16_t mcast_in_all; /* At layer 3 */ + uint16_t mcast_in_ours; /* Unique and we are a group member */ + uint16_t mcast_fwd; /* Forwarded by us but we are not the seed */ + uint16_t mcast_out; /* We are the seed */ + uint16_t mcast_bad; + uint16_t mcast_dropped; +}; + +#endif /* SMRF_H_ */ From 151533b9bc1de790449257d0f0682da6111d87a2 Mon Sep 17 00:00:00 2001 From: George Oikonomou Date: Fri, 11 Nov 2011 12:06:35 +0000 Subject: [PATCH 25/92] Implementation of the Trickle multicast engine --- core/net/ipv6/multicast/roll-tm.c | 1435 +++++++++++++++++++++++++++++ core/net/ipv6/multicast/roll-tm.h | 238 +++++ 2 files changed, 1673 insertions(+) create mode 100644 core/net/ipv6/multicast/roll-tm.c create mode 100644 core/net/ipv6/multicast/roll-tm.h diff --git a/core/net/ipv6/multicast/roll-tm.c b/core/net/ipv6/multicast/roll-tm.c new file mode 100644 index 000000000..37f14f457 --- /dev/null +++ b/core/net/ipv6/multicast/roll-tm.c @@ -0,0 +1,1435 @@ +/* + * Copyright (c) 2010, Loughborough University - 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 + * This file implements IPv6 MCAST forwarding according to the + * algorithm described in the "MCAST Forwarding Using Trickle" + * internet draft. + * + * The current version of the draft can always be found in + * http://tools.ietf.org/html/draft-ietf-roll-trickle-mcast + * + * This implementation is based on the draft version stored in + * ROLL_TM_VER + * + * \author + * George Oikonomou - + */ + +#include "contiki.h" +#include "contiki-lib.h" +#include "contiki-net.h" +#include "net/ipv6/multicast/uip-mcast6.h" +#include "net/ipv6/multicast/roll-tm.h" +#include "dev/watchdog.h" +#include + +#define DEBUG DEBUG_NONE +#include "net/ip/uip-debug.h" + +#define TRICKLE_VERBOSE 0 + +#if DEBUG && TRICKLE_VERBOSE +#define VERBOSE_PRINTF(...) PRINTF(__VA_ARGS__) +#define VERBOSE_PRINT_SEED(s) PRINT_SEED(s) +#else +#define VERBOSE_PRINTF(...) +#define VERBOSE_PRINT_SEED(...) +#endif + +#if UIP_CONF_IPV6 +/*---------------------------------------------------------------------------*/ +/* Data Representation */ +/*---------------------------------------------------------------------------*/ +#if ROLL_TM_SHORT_SEEDS +typedef union seed_id_u { + uint8_t u8[2]; + uint16_t id; /* Big Endian */ +} seed_id_t; + +#define seed_is_null(s) ((s)->id == 0) +#define PRINT_SEED(s) PRINTF("0x%02x%02x", (s)->u8[0], (s)->u8[1]) +#else /* ROLL_TM_SHORT_SEEDS */ +typedef uip_ip6addr_t seed_id_t; + +#define seed_is_null(s) uip_is_addr_unspecified(s) +#define PRINT_SEED(s) PRINT6ADDR(s) +#endif /* ROLL_TM_SHORT_SEEDS */ +#define seed_id_cmp(a, b) (memcmp((a), (b), sizeof(seed_id_t)) == 0) +#define seed_id_cpy(a, b) (memcpy((a), (b), sizeof(seed_id_t))) + +/* Trickle Timers */ +struct trickle_param { + clock_time_t i_min; /* Clock ticks */ + clock_time_t t_start; /* Start of the interval (absolute clock_time) */ + clock_time_t t_end; /* End of the interval (absolute clock_time) */ + clock_time_t t_next; /* Clock ticks, randomised in [I/2, I) */ + clock_time_t t_last_trigger; + struct ctimer ct; + uint8_t i_current; /* Current doublings from i_min */ + uint8_t i_max; /* Max number of doublings */ + uint8_t k; /* Redundancy Constant */ + uint8_t t_active; /* Units of Imax */ + uint8_t t_dwell; /* Units of Imax */ + uint8_t c; /* Consistency Counter */ + uint8_t inconsistency; +}; + +/** + * \brief Convert a timer to a sane clock_time_t value after d doublings + * m is a value of Imin, d is a number of doublings + * Careful of overflows + */ +#define TRICKLE_TIME(m, d) ((clock_time_t)((m) << (d))) + +/** + * \brief Convert Imax from number of doublings to clock_time_t units for + * trickle_param t. Again, watch out for overflows */ +#define TRICKLE_IMAX(t) ((uint32_t)((t)->i_min << (t)->i_max)) + +/** + * \brief Convert Tactive for a trickle timer to a sane clock_time_t value + * t is a pointer to the timer + * Careful of overflows + */ +#define TRICKLE_ACTIVE(t) ((uint32_t)(TRICKLE_IMAX(t) * t->t_active)) + +/** + * \brief Convert Tdwell for a trickle timer to a sane clock_time_t value + * t is a pointer to the timer + * Careful of overflows + */ +#define TRICKLE_DWELL(t) ((uint32_t)(TRICKLE_IMAX(t) * t->t_dwell)) + +/** + * \brief Check if suppression is enabled for trickle_param t + * t is a pointer to the timer + */ +#define SUPPRESSION_ENABLED(t) ((t)->k != ROLL_TM_INFINITE_REDUNDANCY) + +/** + * \brief Check if suppression is disabled for trickle_param t + * t is a pointer to the timer + */ +#define SUPPRESSION_DISABLED(t) ((t)->k == ROLL_TM_INFINITE_REDUNDANCY) + +/** + * \brief Init trickle_timer[m] + */ +#define TIMER_CONFIGURE(m) do { \ + t[m].i_min = ROLL_TM_IMIN_##m; \ + t[m].i_max = ROLL_TM_IMAX_##m; \ + t[m].k = ROLL_TM_K_##m; \ + t[m].t_active = ROLL_TM_T_ACTIVE_##m; \ + t[m].t_dwell = ROLL_TM_T_DWELL_##m; \ + t[m].t_last_trigger = clock_time(); \ +} while(0) +/*---------------------------------------------------------------------------*/ +/* Sequence Values and Serial Number Arithmetic + * + * Sequence Number Comparisons as per RFC1982 "Serial Number Arithmetic" + * Our 'SERIAL_BITS' value is 15 here + * + * NOTE: There can be pairs of sequence numbers s1 and s2 with an undefined + * ordering. All three macros would evaluate as 0, as in: + * SEQ_VAL_IS_EQUAL(s1, s2) == 0 and + * SEQ_VAL_IS_GT(s1, s2) == 0 and + * SEQ_VAL_IS_LT(s1, s2) == 0 + * + * This is not a bug of this implementation, it's an RFC design choice + */ + +/** + * \brief s1 is said to be equal s2 iif SEQ_VAL_IS_EQ(s1, s2) == 1 + */ +#define SEQ_VAL_IS_EQ(i1, i2) ((i1) == (i2)) + +/** + * \brief s1 is said to be less than s2 iif SEQ_VAL_IS_LT(s1, s2) == 1 + */ +#define SEQ_VAL_IS_LT(i1, i2) \ + ( \ + ((i1) != (i2)) && \ + ((((i1) < (i2)) && ((int16_t)((i2) - (i1)) < 0x4000)) || \ + (((i1) > (i2)) && ((int16_t)((i1) - (i2)) > 0x4000))) \ + ) + +/** + * \brief s1 is said to be greater than s2 iif SEQ_VAL_IS_LT(s1, s2) == 1 + */ +#define SEQ_VAL_IS_GT(i1, i2) \ +( \ + ((i1) != (i2)) && \ + ((((i1) < (i2)) && ((int16_t)((i2) - (i1)) > 0x4000)) || \ + (((i1) > (i2)) && ((int16_t)((i1) - (i2)) < 0x4000))) \ +) + +/** + * \brief Add n to s: (s + n) modulo (2 ^ SERIAL_BITS) => ((s + n) % 0x8000) + */ +#define SEQ_VAL_ADD(s, n) (((s) + (n)) % 0x8000) +/*---------------------------------------------------------------------------*/ +/* Sliding Windows */ +struct sliding_window { + seed_id_t seed_id; + int16_t lower_bound; /* lolipop */ + int16_t upper_bound; /* lolipop */ + int16_t min_listed; /* lolipop */ + uint8_t flags; /* Is used, Trickle param, Is listed */ + uint8_t count; +}; + +#define SLIDING_WINDOW_U_BIT 0x80 /* Is used */ +#define SLIDING_WINDOW_M_BIT 0x40 /* Window trickle parametrization */ +#define SLIDING_WINDOW_L_BIT 0x20 /* Current ICMP message lists us */ +#define SLIDING_WINDOW_B_BIT 0x10 /* Used when updating bounds */ + +/** + * \brief Is Occupied sliding window location w + * w: pointer to a sliding window + */ +#define SLIDING_WINDOW_IS_USED(w) ((w)->flags & SLIDING_WINDOW_U_BIT) + +/** + * \brief Set 'Is Used' bit for window w + * w: pointer to a sliding window + */ +#define SLIDING_WINDOW_IS_USED_SET(w) ((w)->flags |= SLIDING_WINDOW_U_BIT) + +/** + * \brief Clear 'Is Used' bit for window w + * w: pointer to a sliding window + */ +#define SLIDING_WINDOW_IS_USED_CLR(w) ((w)->flags &= ~SLIDING_WINDOW_U_BIT) +#define window_free(w) SLIDING_WINDOW_IS_USED_CLR(w) + +/** + * \brief Set 'Is Seen' bit for window w + * w: pointer to a sliding window + */ +#define SLIDING_WINDOW_LISTED_SET(w) ((w)->flags |= SLIDING_WINDOW_L_BIT) + +/** + * \brief Clear 'Is Seen' bit for window w + * w: pointer to a sliding window + */ +#define SLIDING_WINDOW_LISTED_CLR(w) ((w)->flags &= ~SLIDING_WINDOW_L_BIT) + +/** + * \brief Is the sliding window at location w listed in current ICMP message? + * w: pointer to a sliding window + */ +#define SLIDING_WINDOW_IS_LISTED(w) ((w)->flags & SLIDING_WINDOW_L_BIT) + +/** + * \brief Set M bit for window w + * w: pointer to a sliding window + */ +#define SLIDING_WINDOW_M_SET(w) ((w)->flags |= SLIDING_WINDOW_M_BIT) + +/** + * \brief Clear M bit for window w + * w: pointer to a sliding window + */ +#define SLIDING_WINDOW_M_CLR(w) ((w)->flags &= ~SLIDING_WINDOW_M_BIT) + +/** + * \brief Retrieve trickle parametrization for sliding window at location w + * w: pointer to a sliding window + */ +#define SLIDING_WINDOW_GET_M(w) \ + ((uint8_t)(((w)->flags & SLIDING_WINDOW_M_BIT) == SLIDING_WINDOW_M_BIT)) +/*---------------------------------------------------------------------------*/ +/* Multicast Packet Buffers */ +struct mcast_packet { +#if ROLL_TM_SHORT_SEEDS + /* Short seeds are stored inside the message */ + seed_id_t seed_id; +#endif + uint32_t active; /* Starts at 0 and increments */ + uint32_t dwell; /* Starts at 0 and increments */ + uint16_t buff_len; + uint16_t seq_val; /* host-byte order */ + struct sliding_window *sw; /* Pointer to the SW this packet belongs to */ + uint8_t flags; /* Is-Used, Must Send, Is Listed */ + uint8_t buff[UIP_BUFSIZE - UIP_LLH_LEN]; +}; + +/* Flag bits */ +#define MCAST_PACKET_U_BIT 0x80 /* Is Used */ +#define MCAST_PACKET_S_BIT 0x20 /* Must Send Next Pass */ +#define MCAST_PACKET_L_BIT 0x10 /* Is listed in ICMP message */ + +/* Fetch a pointer to the Seed ID of a buffered message p */ +#if ROLL_TM_SHORT_SEEDS +#define MCAST_PACKET_GET_SEED(p) ((seed_id_t *)&((p)->seed_id)) +#else +#define MCAST_PACKET_GET_SEED(p) \ + ((seed_id_t *)&((struct uip_ip_hdr *)&(p)->buff[UIP_LLH_LEN])->srcipaddr) +#endif + +/** + * \brief Get the TTL of a buffered packet + * p: pointer to a packet buffer + */ +#define MCAST_PACKET_TTL(p) \ + (((struct uip_ip_hdr *)(p)->buff)->ttl) + +/** + * \brief Set 'Is Used' bit for packet p + * p: pointer to a packet buffer + */ +#define MCAST_PACKET_USED_SET(p) ((p)->flags |= MCAST_PACKET_U_BIT) + +/** + * \brief Clear 'Is Used' bit for packet p + * p: pointer to a packet buffer + */ +#define MCAST_PACKET_USED_CLR(p) ((p)->flags &= ~MCAST_PACKET_U_BIT) + +/** + * \brief Is Occupied buffer location p + */ +#define MCAST_PACKET_IS_USED(p) ((p)->flags & MCAST_PACKET_U_BIT) + +/** + * \brief Must we send this message this pass? + */ +#define MCAST_PACKET_MUST_SEND(p) ((p)->flags & MCAST_PACKET_S_BIT) + +/** + * \brief Set 'Must Send' bit for message p + * p: pointer to a struct mcast_packet + */ +#define MCAST_PACKET_SEND_SET(p) ((p)->flags |= MCAST_PACKET_S_BIT) + +/** + * \brief Clear 'Must Send' bit for message p + * p: pointer to a struct mcast_packet + */ +#define MCAST_PACKET_SEND_CLR(p) ((p)->flags &= ~MCAST_PACKET_S_BIT) + +/** + * \brief Is the message p listed in current ICMP message? + * p: pointer to a struct mcast_packet + */ +#define MCAST_PACKET_IS_LISTED(p) ((p)->flags & MCAST_PACKET_L_BIT) + +/** + * \brief Set 'Is Listed' bit for message p + * p: pointer to a struct mcast_packet + */ +#define MCAST_PACKET_LISTED_SET(p) ((p)->flags |= MCAST_PACKET_L_BIT) + +/** + * \brief Clear 'Is Listed' bit for message p + * p: pointer to a struct mcast_packet + */ +#define MCAST_PACKET_LISTED_CLR(p) ((p)->flags &= ~MCAST_PACKET_L_BIT) + +/** + * \brief Free a multicast packet buffer + * p: pointer to a struct mcast_packet + */ +#define MCAST_PACKET_FREE(p) ((p)->flags = 0) +/*---------------------------------------------------------------------------*/ +/* Sequence Lists in Multicast Trickle ICMP messages */ +struct sequence_list_header { + uint8_t flags; /* S: Seed ID length, M: Trickle parametrization */ + uint8_t seq_len; + seed_id_t seed_id; +}; + +#define SEQUENCE_LIST_S_BIT 0x80 +#define SEQUENCE_LIST_M_BIT 0x40 +#define SEQUENCE_LIST_RES 0x3F + +/** + * \brief Get the Trickle Parametrization for an ICMPv6 sequence list + * l: pointer to a sequence list structure + */ +#define SEQUENCE_LIST_GET_M(l) \ + ((uint8_t)(((l)->flags & SEQUENCE_LIST_M_BIT) == SEQUENCE_LIST_M_BIT)) + +/** + * \brief Get the Seed ID Length for an ICMPv6 sequence list + * l: pointer to a sequence list structure + */ +#define SEQUENCE_LIST_GET_S(l) \ + ((uint8_t)(((l)->flags & SEQUENCE_LIST_S_BIT) == SEQUENCE_LIST_S_BIT)) +/*---------------------------------------------------------------------------*/ +/* Trickle Multicast HBH Option */ +struct hbho_mcast { + uint8_t type; + uint8_t len; +#if ROLL_TM_SHORT_SEEDS + seed_id_t seed_id; +#endif + uint8_t flags; /* M, Seq ID MSB */ + uint8_t seq_id_lsb; +#if !ROLL_TM_SHORT_SEEDS + /* Need to Pad to 8 bytes with PadN */ + uint8_t padn_type; /* 1: PadN */ + uint8_t padn_len; /* 0->2 bytes */ +#endif +}; + +#define HBHO_OPT_TYPE_TRICKLE 0x0C +#define HBHO_LEN_LONG_SEED 2 +#define HBHO_LEN_SHORT_SEED 4 +#define HBHO_TOTAL_LEN 8 +/** + * \brief Get the Trickle Parametrization for a multicast HBHO header + * m: pointer to the HBHO header + */ +#define HBH_GET_M(h) (((h)->flags & 0x80) == 0x80) + +/** + * \brief Set the Trickle Parametrization bit for a multicast HBHO header + * m: pointer to the HBHO header + */ +#define HBH_SET_M(h) ((h)->flags |= 0x80) + +/** + * \brief Retrieve the Sequence Value MSB from a multicast HBHO header + * m: pointer to the HBHO header + */ +#define HBH_GET_SV_MSB(h) ((h)->flags & 0x7F) +/*---------------------------------------------------------------------------*/ +/* Destination for our ICMPv6 datagrams */ +#if ROLL_TM_CONF_DEST_ALL_NODES +#define roll_tm_create_dest(a) uip_create_linklocal_allnodes_mcast(a) +#else +#define roll_tm_create_dest(a) uip_create_linklocal_allrouters_mcast(a) +#endif +/*---------------------------------------------------------------------------*/ +/* Maintain Stats */ +#if UIP_MCAST6_CONF_STATS +struct roll_tm_stats roll_tm_stats; + +#define STATS_ADD(x) roll_tm_stats.x++ +#define STATS_RESET() do { \ + memset(&roll_tm_stats, 0, sizeof(roll_tm_stats)); } while(0) +#else +#define STATS_ADD(x) +#define STATS_RESET() +#endif +/*---------------------------------------------------------------------------*/ +/* Internal Data Structures */ +/*---------------------------------------------------------------------------*/ +static struct trickle_param t[2]; +static struct sliding_window windows[ROLL_TM_WINS]; +static struct mcast_packet buffered_msgs[ROLL_TM_BUFF_NUM]; +/*---------------------------------------------------------------------------*/ +/* Temporary Stores */ +/*---------------------------------------------------------------------------*/ +static struct trickle_param *loctpptr; +static struct sequence_list_header *locslhptr; +static struct sliding_window *locswptr; +static struct sliding_window *iterswptr; +static struct mcast_packet *locmpptr; +static struct hbho_mcast *lochbhmptr; +static uint16_t last_seq; +/*---------------------------------------------------------------------------*/ +/* uIPv6 Pointers */ +/*---------------------------------------------------------------------------*/ +#define UIP_DATA_BUF ((uint8_t *)&uip_buf[uip_l2_l3_hdr_len + UIP_UDPH_LEN]) +#define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[uip_l2_l3_hdr_len]) +#define UIP_EXT_BUF ((struct uip_ext_hdr *)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN]) +#define UIP_EXT_BUF_NEXT ((uint8_t *)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN + HBHO_TOTAL_LEN]) +#define UIP_EXT_OPT_FIRST ((struct hbho_mcast *)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN + 2]) +#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_ICMP_PAYLOAD ((unsigned char *)&uip_buf[uip_l2_l3_icmp_hdr_len]) +extern uint16_t uip_slen; +/*---------------------------------------------------------------------------*/ +/* Local function prototypes */ +/*---------------------------------------------------------------------------*/ +static void icmp_output(); +static void window_update_bounds(); +static void reset_trickle_timer(uint8_t); +static void handle_timer(void *); +/*---------------------------------------------------------------------------*/ +/* Return a random number in [I/2, I), for a timer with Imin when the timer's + * current number of doublings is d */ +static clock_time_t +random_interval(clock_time_t i_min, uint8_t d) +{ + clock_time_t min = TRICKLE_TIME(i_min >> 1, d); + + VERBOSE_PRINTF("ROLL TM: Random [%lu, %lu)\n", (unsigned long)min, + (unsigned long)(TRICKLE_TIME(i_min, d))); + + return min + (random_rand() % (TRICKLE_TIME(i_min, d) - 1 - min)); +} +/*---------------------------------------------------------------------------*/ +/* Called at the end of the current interval for timer ptr */ +static void +double_interval(void *ptr) +{ + struct trickle_param *param = (struct trickle_param *)ptr; + int16_t offset; + clock_time_t next; + + /* + * If we got called long past our expiration, store the offset and try to + * compensate this period + */ + offset = (int16_t)(clock_time() - param->t_end); + + /* Calculate next interval */ + if(param->i_current < param->i_max) { + param->i_current++; + } + + param->t_start = param->t_end; + param->t_end = param->t_start + (param->i_min << param->i_current); + + next = random_interval(param->i_min, param->i_current); + if(next > offset) { + next -= offset; + } else { + next = 0; + } + param->t_next = next; + ctimer_set(¶m->ct, param->t_next, handle_timer, (void *)param); + + VERBOSE_PRINTF("ROLL TM: Doubling at %lu (offset %d), Start %lu, End %lu," + " Periodic in %lu\n", clock_time(), offset, + (unsigned long)param->t_start, + (unsigned long)param->t_end, (unsigned long)param->t_next); +} +/*---------------------------------------------------------------------------*/ +/* + * Called at a random point in [I/2,I) of the current interval for ptr + * PARAM is a pointer to the timer that triggered the callback (&t[index]) + */ +static void +handle_timer(void *ptr) +{ + struct trickle_param *param; + clock_time_t diff_last; /* Time diff from last pass */ + clock_time_t diff_start; /* Time diff from interval start */ + uint8_t m; + + param = (struct trickle_param *)ptr; + if(param == &t[0]) { + m = 0; + } else if(param == &t[1]) { + m = 1; + } else { + /* This is an ooops and a serious one too */ + return; + } + + /* Bail out pronto if our uIPv6 stack is not ready to send messages */ + if(uip_ds6_get_link_local(ADDR_PREFERRED) == NULL) { + VERBOSE_PRINTF + ("ROLL TM: Suppressing timer processing. Stack not ready\n"); + reset_trickle_timer(m); + return; + } + + VERBOSE_PRINTF("ROLL TM: M=%u Periodic at %lu, last=%lu\n", + m, (unsigned long)clock_time(), + (unsigned long)param->t_last_trigger); + + /* Temporarily store 'now' in t_next and calculate diffs */ + param->t_next = clock_time(); + diff_last = param->t_next - param->t_last_trigger; + diff_start = param->t_next - param->t_start; + param->t_last_trigger = param->t_next; + + VERBOSE_PRINTF + ("ROLL TM: M=%u Periodic diff from last %lu, from start %lu\n", m, + (unsigned long)diff_last, (unsigned long)diff_start); + + /* Handle all buffered messages */ + for(locmpptr = &buffered_msgs[ROLL_TM_BUFF_NUM - 1]; + locmpptr >= buffered_msgs; locmpptr--) { + if(MCAST_PACKET_IS_USED(locmpptr) + && (SLIDING_WINDOW_GET_M(locmpptr->sw) == m)) { + + /* + * if() + * If the packet was received during the last interval, its reception + * caused an inconsistency (and thus a timer reset). This means that + * the packet was received at about t_start, we increment by diff_start + * + * else() + * If the packet was not received during the last window, it is safe to + * increase its lifetime counters by the time diff from last pass + * + * if active == dwell == 0 but i_current != 0, this is an oops + * (new packet that didn't reset us). We don't handle it + */ + if(locmpptr->active == 0) { + locmpptr->active += diff_start; + locmpptr->dwell += diff_start; + } else { + locmpptr->active += diff_last; + locmpptr->dwell += diff_last; + } + + VERBOSE_PRINTF("ROLL TM: M=%u Packet %u active %lu of %lu\n", + m, locmpptr->seq_val, locmpptr->active, + TRICKLE_ACTIVE(param)); + + if(locmpptr->dwell > TRICKLE_DWELL(param)) { + locmpptr->sw->count--; + PRINTF("ROLL TM: M=%u Free Packet %u (%lu > %lu), Window now at %u\n", + m, locmpptr->seq_val, locmpptr->dwell, + TRICKLE_DWELL(param), locmpptr->sw->count); + if(locmpptr->sw->count == 0) { + PRINTF("ROLL TM: M=%u Free Window ", m); + PRINT_SEED(&locmpptr->sw->seed_id); + PRINTF("\n"); + window_free(locmpptr->sw); + } + MCAST_PACKET_FREE(locmpptr); + } else if(MCAST_PACKET_TTL(locmpptr) > 0) { + /* Handle multicast transmissions */ + if((SUPPRESSION_ENABLED(param) && MCAST_PACKET_MUST_SEND(locmpptr)) || + (SUPPRESSION_DISABLED(param) && + locmpptr->active < TRICKLE_ACTIVE(param))) { + PRINTF("ROLL TM: M=%u Periodic - Sending packet from Seed ", m); + PRINT_SEED(&locmpptr->sw->seed_id); + PRINTF(" seq %u\n", locmpptr->seq_val); + uip_len = locmpptr->buff_len; + memcpy(UIP_IP_BUF, &locmpptr->buff, uip_len); + + STATS_ADD(mcast_fwd); + tcpip_output(NULL); + MCAST_PACKET_SEND_CLR(locmpptr); + watchdog_periodic(); + } + } + } + } + + /* Suppression Enabled - Send an ICMP */ + if(SUPPRESSION_ENABLED(param)) { + if(param->c < param->k) { + icmp_output(); + } + } + + /* Done handling inconsistencies for this timer */ + param->inconsistency = 0; + param->c = 0; + + window_update_bounds(); + + /* Temporarily store 'now' in t_next */ + param->t_next = clock_time(); + if(param->t_next >= param->t_end) { + /* took us too long to process things, double interval asap */ + param->t_next = 0; + } else { + param->t_next = param->t_end - param->t_next; + } + VERBOSE_PRINTF + ("ROLL TM: M=%u Periodic at %lu, Interval End at %lu in %lu\n", m, + (unsigned long)clock_time(), (unsigned long)param->t_end, + (unsigned long)param->t_next); + ctimer_set(¶m->ct, param->t_next, double_interval, (void *)param); + + return; +} +/*---------------------------------------------------------------------------*/ +static void +reset_trickle_timer(uint8_t index) +{ + t[index].t_start = clock_time(); + t[index].t_end = t[index].t_start + (t[index].i_min); + t[index].i_current = 0; + t[index].c = 0; + t[index].t_next = random_interval(t[index].i_min, t[index].i_current); + + VERBOSE_PRINTF + ("ROLL TM: M=%u Reset at %lu, Start %lu, End %lu, New Interval %lu\n", + index, (unsigned long)t[index].t_start, (unsigned long)t[index].t_start, + (unsigned long)t[index].t_end, (unsigned long)t[index].t_next); + + ctimer_set(&t[index].ct, t[index].t_next, handle_timer, (void *)&t[index]); +} +/*---------------------------------------------------------------------------*/ +static struct sliding_window * +window_allocate() +{ + for(iterswptr = &windows[ROLL_TM_WINS - 1]; iterswptr >= windows; + iterswptr--) { + if(!SLIDING_WINDOW_IS_USED(iterswptr)) { + iterswptr->count = 0; + iterswptr->lower_bound = -1; + iterswptr->upper_bound = -1; + iterswptr->min_listed = -1; + return iterswptr; + } + } + return NULL; +} +/*---------------------------------------------------------------------------*/ +static struct sliding_window * +window_lookup(seed_id_t *s, uint8_t m) +{ + for(iterswptr = &windows[ROLL_TM_WINS - 1]; iterswptr >= windows; + iterswptr--) { + VERBOSE_PRINTF("ROLL TM: M=%u (%u) ", SLIDING_WINDOW_GET_M(iterswptr), m); + VERBOSE_PRINT_SEED(&iterswptr->seed_id); + VERBOSE_PRINTF("\n"); + if(seed_id_cmp(s, &iterswptr->seed_id) && + SLIDING_WINDOW_GET_M(iterswptr) == m) { + return iterswptr; + } + } + return NULL; +} +/*---------------------------------------------------------------------------*/ +static void +window_update_bounds() +{ + for(iterswptr = &windows[ROLL_TM_WINS - 1]; iterswptr >= windows; + iterswptr--) { + iterswptr->lower_bound = -1; + } + + for(locmpptr = &buffered_msgs[ROLL_TM_BUFF_NUM - 1]; + locmpptr >= buffered_msgs; locmpptr--) { + if(MCAST_PACKET_IS_USED(locmpptr)) { + iterswptr = locmpptr->sw; + VERBOSE_PRINTF("ROLL TM: Update Bounds: [%d - %d] vs %u\n", + iterswptr->lower_bound, iterswptr->upper_bound, + locmpptr->seq_val); + if(iterswptr->lower_bound < 0 + || SEQ_VAL_IS_LT(locmpptr->seq_val, iterswptr->lower_bound)) { + iterswptr->lower_bound = locmpptr->seq_val; + } + if(iterswptr->upper_bound < 0 || + SEQ_VAL_IS_GT(locmpptr->seq_val, iterswptr->upper_bound)) { + iterswptr->upper_bound = locmpptr->seq_val; + } + } + } +} +/*---------------------------------------------------------------------------*/ +static struct mcast_packet * +buffer_reclaim() +{ + struct sliding_window *largest = windows; + struct mcast_packet *rv; + + for(iterswptr = &windows[ROLL_TM_WINS - 1]; iterswptr >= windows; + iterswptr--) { + if(iterswptr->count > largest->count) { + largest = iterswptr; + } + } + + if(largest->count == 1) { + /* Can't reclaim last entry for a window and this is the largest window */ + return NULL; + } + + PRINTF("ROLL TM: Reclaim from Seed "); + PRINT_SEED(&largest->seed_id); + PRINTF(" M=%u, count was %u\n", + SLIDING_WINDOW_GET_M(largest), largest->count); + /* Find the packet at the lowest bound for the largest window */ + for(locmpptr = &buffered_msgs[ROLL_TM_BUFF_NUM - 1]; + locmpptr >= buffered_msgs; locmpptr--) { + if(MCAST_PACKET_IS_USED(locmpptr) && (locmpptr->sw == largest) && + SEQ_VAL_IS_EQ(locmpptr->seq_val, largest->lower_bound)) { + rv = locmpptr; + PRINTF("ROLL TM: Reclaim seq. val %u\n", locmpptr->seq_val); + MCAST_PACKET_FREE(rv); + largest->count--; + window_update_bounds(); + VERBOSE_PRINTF("ROLL TM: Reclaim - new bounds [%u , %u]\n", + largest->lower_bound, largest->upper_bound); + return rv; + } + } + + /* oops */ + return NULL; +} +/*---------------------------------------------------------------------------*/ +static struct mcast_packet * +buffer_allocate() +{ + for(locmpptr = &buffered_msgs[ROLL_TM_BUFF_NUM - 1]; + locmpptr >= buffered_msgs; locmpptr--) { + if(!MCAST_PACKET_IS_USED(locmpptr)) { + return locmpptr; + } + } + return NULL; +} +/*---------------------------------------------------------------------------*/ +static void +icmp_output() +{ + struct sequence_list_header *sl; + uint8_t *buffer; + uint16_t payload_len; + + PRINTF("ROLL TM: ICMPv6 Out\n"); + + UIP_IP_BUF->vtc = 0x60; + UIP_IP_BUF->tcflow = 0; + UIP_IP_BUF->flow = 0; + UIP_IP_BUF->proto = UIP_PROTO_ICMP6; + UIP_IP_BUF->ttl = ROLL_TM_IP_HOP_LIMIT; + + sl = (struct sequence_list_header *)UIP_ICMP_PAYLOAD; + payload_len = 0; + + VERBOSE_PRINTF("ROLL TM: ICMPv6 Out - Hdr @ %p, payload @ %p\n", UIP_ICMP_BUF, sl); + + for(iterswptr = &windows[ROLL_TM_WINS - 1]; iterswptr >= windows; + iterswptr--) { + if(SLIDING_WINDOW_IS_USED(iterswptr) && iterswptr->count > 0) { + memset(sl, 0, sizeof(struct sequence_list_header)); +#if ROLL_TM_SHORT_SEEDS + sl->flags = SEQUENCE_LIST_S_BIT; +#endif + if(SLIDING_WINDOW_GET_M(iterswptr)) { + sl->flags |= SEQUENCE_LIST_M_BIT; + } + sl->seq_len = iterswptr->count; + seed_id_cpy(&sl->seed_id, &iterswptr->seed_id); + + PRINTF("ROLL TM: ICMPv6 Out - Seq. F=0x%02x, L=%u, Seed ID=", sl->flags, + sl->seq_len); + PRINT_SEED(&sl->seed_id); + + buffer = (uint8_t *)sl + sizeof(struct sequence_list_header); + + payload_len += sizeof(struct sequence_list_header); + for(locmpptr = &buffered_msgs[ROLL_TM_BUFF_NUM - 1]; + locmpptr >= buffered_msgs; locmpptr--) { + if(MCAST_PACKET_IS_USED(locmpptr)) { + if(locmpptr->sw == iterswptr) { + PRINTF(", %u", locmpptr->seq_val); + *buffer = (uint8_t)(locmpptr->seq_val >> 8); + buffer++; + *buffer = (uint8_t)(locmpptr->seq_val & 0xFF); + buffer++; + } + } + } + PRINTF("\n"); + payload_len += sl->seq_len * 2; + sl = (struct sequence_list_header *)buffer; + } + } + + if(payload_len == 0) { + VERBOSE_PRINTF("ROLL TM: ICMPv6 Out - nothing to send\n"); + return; + } + + roll_tm_create_dest(&UIP_IP_BUF->destipaddr); + uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr); + + UIP_IP_BUF->len[0] = (UIP_ICMPH_LEN + payload_len) >> 8; + UIP_IP_BUF->len[1] = (UIP_ICMPH_LEN + payload_len) & 0xff; + + UIP_ICMP_BUF->type = ICMP6_ROLL_TM; + UIP_ICMP_BUF->icode = ROLL_TM_ICMP_CODE; + + UIP_ICMP_BUF->icmpchksum = 0; + UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum(); + + uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + payload_len; + + VERBOSE_PRINTF("ROLL TM: ICMPv6 Out - %u bytes\n", payload_len); + + tcpip_ipv6_output(); + STATS_ADD(icmp_out); + return; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Processes an incoming or outgoing multicast message and determines + * whether it should be dropped or accepted + * + * \param in 1: Incoming packet, 0: Outgoing (we are the seed) + * + * \return 0: Drop, 1: Accept + */ +static uint8_t +accept(uint8_t in) +{ + seed_id_t *seed_ptr; + uint8_t m; + uint16_t seq_val; + + PRINTF("ROLL TM: Multicast I/O\n"); + +#if UIP_CONF_IPV6_CHECKS + if(uip_is_addr_mcast_non_routable(&UIP_IP_BUF->destipaddr)) { + PRINTF("ROLL TM: Mcast I/O, bad destination\n"); + UIP_MCAST6_STATS_ADD(mcast_bad); + return UIP_MCAST6_DROP; + } + /* + * Abort transmission if the v6 src is unspecified. This may happen if the + * seed tries to TX while it's still performing DAD or waiting for a prefix + */ + if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) { + PRINTF("ROLL TM: Mcast I/O, bad source\n"); + STATS_ADD(mcast_bad); + return UIP_MCAST6_DROP; + } +#endif + + /* Check the Next Header field: Must be HBHO */ + if(UIP_IP_BUF->proto != UIP_PROTO_HBHO) { + PRINTF("ROLL TM: Mcast I/O, bad proto\n"); + STATS_ADD(mcast_bad); + return UIP_MCAST6_DROP; + } else { + /* Check the Option Type */ + if(UIP_EXT_OPT_FIRST->type != HBHO_OPT_TYPE_TRICKLE) { + PRINTF("ROLL TM: Mcast I/O, bad HBHO type\n"); + STATS_ADD(mcast_bad); + return UIP_MCAST6_DROP; + } + } + lochbhmptr = UIP_EXT_OPT_FIRST; + + PRINTF("ROLL TM: HBHO T=%u, L=%u, M=%u, S=0x%02x%02x\n", + lochbhmptr->type, lochbhmptr->len, HBH_GET_M(lochbhmptr), + HBH_GET_SV_MSB(lochbhmptr), lochbhmptr->seq_id_lsb); + + /* Drop unsupported Seed ID Lengths. S bit: 0->short, 1->long */ +#if ROLL_TM_SHORT_SEEDS + /* Short Seed ID: Len MUST be 4 */ + if(lochbhmptr->len != HBHO_LEN_SHORT_SEED) { + PRINTF("ROLL TM: Mcast I/O, bad length\n"); + STATS_ADD(mcast_bad); + return UIP_MCAST6_DROP; + } +#else + /* Long Seed ID: Len MUST be 2 (Seed ID is elided) */ + if(lochbhmptr->len != HBHO_LEN_LONG_SEED) { + PRINTF("ROLL TM: Mcast I/O, bad length\n"); + STATS_ADD(mcast_bad); + return UIP_MCAST6_DROP; + } +#endif + +#if UIP_MCAST6_CONF_STATS + if(in == ROLL_TM_DGRAM_IN) { + STATS_ADD(mcast_in_all); + } +#endif + + /* Is this for a known window? */ +#if ROLL_TM_SHORT_SEEDS + seed_ptr = &lochbhmptr->seed_id; +#else + seed_ptr = &UIP_IP_BUF->srcipaddr; +#endif + m = HBH_GET_M(lochbhmptr); + + locswptr = window_lookup(seed_ptr, m); + + seq_val = lochbhmptr->seq_id_lsb; + seq_val |= HBH_GET_SV_MSB(lochbhmptr) << 8; + + if(locswptr) { + if(SEQ_VAL_IS_LT(seq_val, locswptr->lower_bound)) { + /* Too old, drop */ + PRINTF("ROLL TM: Too old\n"); + STATS_ADD(mcast_dropped); + return UIP_MCAST6_DROP; + } + for(locmpptr = &buffered_msgs[ROLL_TM_BUFF_NUM - 1]; + locmpptr >= buffered_msgs; locmpptr--) { + if(MCAST_PACKET_IS_USED(locmpptr) && + locmpptr->sw == locswptr && + SLIDING_WINDOW_GET_M(locmpptr->sw) == m && + SEQ_VAL_IS_EQ(seq_val, locmpptr->seq_val)) { + /* Seen before , drop */ + PRINTF("ROLL TM: Seen before\n"); + STATS_ADD(mcast_dropped); + return UIP_MCAST6_DROP; + } + } + } + + PRINTF("ROLL TM: New message\n"); + + /* We have not seen this message before */ + /* Allocate a window if we have to */ + if(!locswptr) { + locswptr = window_allocate(); + PRINTF("ROLL TM: New seed\n"); + } + if(!locswptr) { + /* Couldn't allocate window, drop */ + PRINTF("ROLL TM: Failed to allocate window\n"); + STATS_ADD(mcast_dropped); + return UIP_MCAST6_DROP; + } + + /* Allocate a buffer */ + locmpptr = buffer_allocate(); + if(!locmpptr) { + PRINTF("ROLL TM: Buffer allocation failed, reclaiming\n"); + locmpptr = buffer_reclaim(); + } + + if(!locmpptr) { + /* Failed to allocate / reclaim a buffer. If the window has only just been + * allocated, free it before dropping */ + PRINTF("ROLL TM: Buffer reclaim failed\n"); + if(locswptr->count == 0) { + window_free(locswptr); + STATS_ADD(mcast_dropped); + return UIP_MCAST6_DROP; + } + } +#if UIP_MCAST6_CONF_STATS + if(in == ROLL_TM_DGRAM_IN) { + STATS_ADD(mcast_in_unique); + } +#endif + + /* We have a window and we have a buffer. Accept this message */ + /* Set the seed ID and correct M for this window */ + SLIDING_WINDOW_M_CLR(locswptr); + if(m) { + SLIDING_WINDOW_M_SET(locswptr); + } + SLIDING_WINDOW_IS_USED_SET(locswptr); + seed_id_cpy(&locswptr->seed_id, seed_ptr); + PRINTF("ROLL TM: Window for seed "); + PRINT_SEED(&locswptr->seed_id); + PRINTF(" M=%u, count=%u\n", + SLIDING_WINDOW_GET_M(locswptr), locswptr->count); + + /* If this window was previously empty, set its lower bound to this packet */ + if(locswptr->count == 0) { + locswptr->lower_bound = seq_val; + VERBOSE_PRINTF("ROLL TM: New Lower Bound %u\n", locswptr->lower_bound); + } + + /* If this is a new Seq Num, update the window upper bound */ + if(locswptr->count == 0 || SEQ_VAL_IS_GT(seq_val, locswptr->upper_bound)) { + locswptr->upper_bound = seq_val; + VERBOSE_PRINTF("ROLL TM: New Upper Bound %u\n", locswptr->upper_bound); + } + + locswptr->count++; + + memset(locmpptr, 0, sizeof(struct mcast_packet)); + memcpy(&locmpptr->buff, UIP_IP_BUF, uip_len); + locmpptr->sw = locswptr; + locmpptr->buff_len = uip_len; + locmpptr->seq_val = seq_val; + MCAST_PACKET_USED_SET(locmpptr); + + PRINTF("ROLL TM: Window for seed "); + PRINT_SEED(&locswptr->seed_id); + PRINTF(" M=%u, %u values within [%u , %u]\n", + SLIDING_WINDOW_GET_M(locswptr), locswptr->count, + locswptr->lower_bound, locswptr->upper_bound); + + /* + * If this is an incoming packet, it is inconsistent and we need to decrement + * its TTL before we start forwarding it. + * If on the other hand we are the seed, the caller will trigger a + * transmission so we don't flag inconsistency and we leave the TTL alone + */ + if(in == ROLL_TM_DGRAM_IN) { + MCAST_PACKET_SEND_SET(locmpptr); + MCAST_PACKET_TTL(locmpptr)--; + + t[m].inconsistency = 1; + + PRINTF("ROLL TM: Inconsistency. Reset T%u\n", m); + reset_trickle_timer(m); + } + + /* Deliver if necessary */ + return UIP_MCAST6_ACCEPT; +} +/*---------------------------------------------------------------------------*/ +void +roll_tm_icmp_input() +{ + uint8_t inconsistency; + uint16_t *seq_ptr; + uint16_t *end_ptr; + uint16_t val; + +#if UIP_CONF_IPV6_CHECKS + if(!uip_is_addr_link_local(&UIP_IP_BUF->srcipaddr)) { + PRINTF("ROLL TM: ICMPv6 In, bad source "); + PRINT6ADDR(&UIP_IP_BUF->srcipaddr); + PRINTF(" to "); + PRINT6ADDR(&UIP_IP_BUF->destipaddr); + PRINTF("\n"); + STATS_ADD(icmp_bad); + return; + } + + if(!uip_is_addr_linklocal_allnodes_mcast(&UIP_IP_BUF->destipaddr) + && !uip_is_addr_linklocal_allrouters_mcast(&UIP_IP_BUF->destipaddr)) { + PRINTF("ROLL TM: ICMPv6 In, bad destination\n"); + STATS_ADD(icmp_bad); + return; + } + + if(UIP_ICMP_BUF->icode != ROLL_TM_ICMP_CODE) { + PRINTF("ROLL TM: ICMPv6 In, bad ICMP code\n"); + STATS_ADD(icmp_bad); + return; + } + + if(UIP_IP_BUF->ttl != ROLL_TM_IP_HOP_LIMIT) { + PRINTF("ROLL TM: ICMPv6 In, bad TTL\n"); + STATS_ADD(icmp_bad); + return; + } +#endif + + PRINTF("ROLL TM: ICMPv6 In from "); + PRINT6ADDR(&UIP_IP_BUF->srcipaddr); + PRINTF(" len %u, ext %u\n", uip_len, uip_ext_len); + + STATS_ADD(icmp_in); + + /* Reset Is-Listed bit for all windows */ + for(iterswptr = &windows[ROLL_TM_WINS - 1]; iterswptr >= windows; + iterswptr--) { + SLIDING_WINDOW_LISTED_CLR(iterswptr); + } + + /* Reset Is-Listed bit for all cached packets */ + for(locmpptr = &buffered_msgs[ROLL_TM_BUFF_NUM - 1]; + locmpptr >= buffered_msgs; locmpptr--) { + MCAST_PACKET_LISTED_CLR(locmpptr); + } + + locslhptr = (struct sequence_list_header *)UIP_ICMP_PAYLOAD; + + VERBOSE_PRINTF("ROLL TM: ICMPv6 In, parse from %p to %p\n", + UIP_ICMP_PAYLOAD, + (uint8_t *)UIP_ICMP_PAYLOAD + uip_len - + uip_l2_l3_icmp_hdr_len); + while(locslhptr < + (struct sequence_list_header *)((uint8_t *)UIP_ICMP_PAYLOAD + + uip_len - uip_l2_l3_icmp_hdr_len)) { + VERBOSE_PRINTF("ROLL TM: ICMPv6 In, seq hdr @ %p\n", locslhptr); + + if((locslhptr->flags & SEQUENCE_LIST_RES) != 0) { + PRINTF("ROLL TM: ICMPv6 In, non-zero reserved bits\n"); + goto drop; + } + + /* Drop unsupported Seed ID Lengths. S bit: 0->short, 1->long */ +#if ROLL_TM_SHORT_SEEDS + if(!SEQUENCE_LIST_GET_S(locslhptr)) { + STATS_ADD(icmp_bad); + goto drop; + } +#else + if(SEQUENCE_LIST_GET_S(locslhptr)) { + STATS_ADD(icmp_bad); + goto drop; + } +#endif + + PRINTF("ROLL TM: ICMPv6 In, Sequence List for Seed ID "); + PRINT_SEED(&locslhptr->seed_id); + PRINTF(" M=%u, S=%u, Len=%u\n", SEQUENCE_LIST_GET_M(locslhptr), + SEQUENCE_LIST_GET_S(locslhptr), locslhptr->seq_len); + + seq_ptr = (uint16_t *)((uint8_t *)locslhptr + + sizeof(struct sequence_list_header)); + end_ptr = (uint16_t *)((uint8_t *)locslhptr + + sizeof(struct sequence_list_header) + + locslhptr->seq_len * 2); + + /* Fetch a pointer to the corresponding trickle timer */ + loctpptr = &t[SEQUENCE_LIST_GET_M(locslhptr)]; + + locswptr = NULL; + + /* Find the sliding window for this Seed ID */ + locswptr = window_lookup(&locslhptr->seed_id, + SEQUENCE_LIST_GET_M(locslhptr)); + + /* If we have a window, iterate sequence values and check consistency */ + if(locswptr) { + SLIDING_WINDOW_LISTED_SET(locswptr); + locswptr->min_listed = -1; + PRINTF("ROLL TM: ICMPv6 In, Window bounds [%u , %u]\n", + locswptr->lower_bound, locswptr->upper_bound); + for(; seq_ptr < end_ptr; seq_ptr++) { + /* Check for "They have new" */ + /* If an advertised seq. val is GT our upper bound */ + val = uip_htons(*seq_ptr); + PRINTF("ROLL TM: ICMPv6 In, Check seq %u @ %p\n", val, seq_ptr); + if(SEQ_VAL_IS_GT(val, locswptr->upper_bound)) { + PRINTF("ROLL TM: Inconsistency - Advertised Seq. ID %u GT upper" + " bound %u\n", val, locswptr->upper_bound); + loctpptr->inconsistency = 1; + } + + /* If an advertised seq. val is within our bounds */ + if((SEQ_VAL_IS_LT(val, locswptr->upper_bound) || + SEQ_VAL_IS_EQ(val, locswptr->upper_bound)) && + (SEQ_VAL_IS_GT(val, locswptr->lower_bound) || + SEQ_VAL_IS_EQ(val, locswptr->lower_bound))) { + + inconsistency = 1; + /* Check if the advertised sequence is in our buffer */ + for(locmpptr = &buffered_msgs[ROLL_TM_BUFF_NUM - 1]; + locmpptr >= buffered_msgs; locmpptr--) { + if(MCAST_PACKET_IS_USED(locmpptr) && locmpptr->sw == locswptr) { + if(SEQ_VAL_IS_EQ(locmpptr->seq_val, val)) { + + inconsistency = 0; + MCAST_PACKET_LISTED_SET(locmpptr); + PRINTF("ROLL TM: ICMPv6 In, %u listed\n", locmpptr->seq_val); + + /* Update lowest seq. num listed for this window + * We need this to check for "we have new" */ + if(locswptr->min_listed == -1 || + SEQ_VAL_IS_LT(val, locswptr->min_listed)) { + locswptr->min_listed = val; + } + break; + } + } + } + if(inconsistency) { + PRINTF("ROLL TM: Inconsistency - "); + PRINTF("Advertised Seq. ID %u within bounds", val); + PRINTF(" [%u, %u] but no matching entry\n", + locswptr->lower_bound, locswptr->upper_bound); + loctpptr->inconsistency = 1; + } + } + } + } else { + /* A new sliding window in an ICMP message is not explicitly stated + * in the draft as inconsistency. Until this is clarified, we consider + * this to be a point where we diverge from the draft for performance + * improvement reasons (or as some would say, 'this is an extension') */ + PRINTF("ROLL TM: Inconsistency - Advertised window unknown to us\n"); + loctpptr->inconsistency = 1; + } + locslhptr = (struct sequence_list_header *)(((uint8_t *)locslhptr) + + sizeof(struct sequence_list_header) + (2 * locslhptr->seq_len)); + } + /* Done parsing the message */ + + /* Check for "We have new */ + PRINTF("ROLL TM: ICMPv6 In, Check our buffer\n"); + for(locmpptr = &buffered_msgs[ROLL_TM_BUFF_NUM - 1]; + locmpptr >= buffered_msgs; locmpptr--) { + if(MCAST_PACKET_IS_USED(locmpptr)) { + locswptr = locmpptr->sw; + PRINTF("ROLL TM: ICMPv6 In, "); + PRINTF("Check %u, Seed L: %u, This L: %u Min L: %d\n", + locmpptr->seq_val, SLIDING_WINDOW_IS_LISTED(locswptr), + MCAST_PACKET_IS_LISTED(locmpptr), locswptr->min_listed); + if(!SLIDING_WINDOW_IS_LISTED(locswptr)) { + /* If a buffered packet's Seed ID was not listed */ + PRINTF("ROLL TM: Inconsistency - Seed ID "); + PRINT_SEED(&locswptr->seed_id); + PRINTF(" was not listed\n"); + loctpptr->inconsistency = 1; + MCAST_PACKET_SEND_SET(locmpptr); + } else { + /* This packet was not listed but a prior one was */ + if(!MCAST_PACKET_IS_LISTED(locmpptr) && + (locswptr->min_listed >= 0) && + SEQ_VAL_IS_GT(locmpptr->seq_val, locswptr->min_listed)) { + PRINTF("ROLL TM: Inconsistency - "); + PRINTF("Seq. %u was not listed but %u was\n", + locmpptr->seq_val, locswptr->min_listed); + loctpptr->inconsistency = 1; + MCAST_PACKET_SEND_SET(locmpptr); + } + } + } + } + +drop: + + if(t[0].inconsistency) { + reset_trickle_timer(0); + } else { + t[0].c++; + } + if(t[1].inconsistency) { + reset_trickle_timer(1); + } else { + t[1].c++; + } + + return; +} +/*---------------------------------------------------------------------------*/ +static void +out() +{ + + if(uip_len + HBHO_TOTAL_LEN > UIP_BUFSIZE) { + PRINTF("ROLL TM: Multicast Out can not add HBHO. Packet too long\n"); + goto drop; + } + + /* Slide 'right' by HBHO_TOTAL_LEN bytes */ + memmove(UIP_EXT_BUF_NEXT, UIP_EXT_BUF, uip_len - UIP_IPH_LEN); + memset(UIP_EXT_BUF, 0, HBHO_TOTAL_LEN); + + UIP_EXT_BUF->next = UIP_IP_BUF->proto; + UIP_EXT_BUF->len = 0; + + lochbhmptr = UIP_EXT_OPT_FIRST; + lochbhmptr->type = HBHO_OPT_TYPE_TRICKLE; + + /* Set the sequence ID */ + last_seq = SEQ_VAL_ADD(last_seq, 1); + lochbhmptr->flags = last_seq >> 8; + lochbhmptr->seq_id_lsb = last_seq & 0xFF; +#if ROLL_TM_SHORT_SEEDS + seed_id_cpy(&lochbhmptr->seed_id, &uip_lladdr.addr[UIP_LLADDR_LEN - 2]); + lochbhmptr->len = HBHO_LEN_SHORT_SEED; +#else + lochbhmptr->len = HBHO_LEN_LONG_SEED; + /* PadN */ + lochbhmptr->padn_type = UIP_EXT_HDR_OPT_PADN; + lochbhmptr->padn_len = 0; +#endif + + /* Set the M bit for our outgoing messages, if necessary */ +#if ROLL_TM_SET_M_BIT + HBH_SET_M(lochbhmptr); +#endif + + uip_ext_len += HBHO_TOTAL_LEN; + uip_len += HBHO_TOTAL_LEN; + + /* Update the proto and length field in the v6 header */ + UIP_IP_BUF->proto = UIP_PROTO_HBHO; + UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); + UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); + + PRINTF("ROLL TM: Multicast Out, HBHO: T=%u, L=%u, M=%u, S=0x%02x%02x\n", + lochbhmptr->type, lochbhmptr->len, HBH_GET_M(lochbhmptr), + HBH_GET_SV_MSB(lochbhmptr), lochbhmptr->seq_id_lsb); + + /* + * We need to remember this message and advertise it in subsequent ICMP + * messages. Otherwise, our neighs will think we are inconsistent and will + * bounce it back to us. + * + * Queue this message but don't set its MUST_SEND flag. We reset the trickle + * timer and we send it immediately. We then set uip_len = 0 to stop the core + * from re-sending it. + */ + if(accept(ROLL_TM_DGRAM_OUT)) { + tcpip_output(NULL); + STATS_ADD(mcast_out); + } + +drop: + uip_slen = 0; + uip_len = 0; + uip_ext_len = 0; +} +/*---------------------------------------------------------------------------*/ +static uint8_t +in() +{ + /* + * We call accept() which will sort out caching and forwarding. Depending + * on accept()'s return value, we then need to signal the core + * whether to deliver this to higher layers + */ + if(accept(ROLL_TM_DGRAM_IN) == UIP_MCAST6_DROP) { + return UIP_MCAST6_DROP; + } + + if(!uip_ds6_is_my_maddr(&UIP_IP_BUF->destipaddr)) { + PRINTF("ROLL TM: Not a group member. No further processing\n"); + return UIP_MCAST6_DROP; + } else { + PRINTF("ROLL TM: Ours. Deliver to upper layers\n"); + STATS_ADD(mcast_in_ours); + return UIP_MCAST6_ACCEPT; + } +} +/*---------------------------------------------------------------------------*/ +static void +init() +{ + PRINTF("ROLL TM: ROLL Multicast - Draft #%u\n", ROLL_TM_VER); + + memset(windows, 0, sizeof(windows)); + memset(buffered_msgs, 0, sizeof(buffered_msgs)); + memset(t, 0, sizeof(t)); + STATS_RESET(); + + for(iterswptr = &windows[ROLL_TM_WINS - 1]; iterswptr >= windows; + iterswptr--) { + iterswptr->lower_bound = -1; + iterswptr->upper_bound = -1; + iterswptr->min_listed = -1; + } + + TIMER_CONFIGURE(0); + reset_trickle_timer(0); + TIMER_CONFIGURE(1); + reset_trickle_timer(1); + return; +} +/*---------------------------------------------------------------------------*/ +const struct uip_mcast6_driver roll_tm_driver = { + "ROLL TM", + init, + out, + in, +}; +/*---------------------------------------------------------------------------*/ + +#endif /* UIP_CONF_IPV6 */ diff --git a/core/net/ipv6/multicast/roll-tm.h b/core/net/ipv6/multicast/roll-tm.h new file mode 100644 index 000000000..0eabe028c --- /dev/null +++ b/core/net/ipv6/multicast/roll-tm.h @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2011, Loughborough University - 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 + * Header file for IPv6 multicast according to the algorithm in the + * "MCAST Forwarding Using Trickle" internet draft. + * + * The current version of the draft can always be found in + * http://tools.ietf.org/html/draft-ietf-roll-trickle-mcast + * + * This implementation is based on the draft version stored in + * ROLL_TM_VER. + * + * In draft v2, the document was renamed to + * "Multicast Protocol for Low power and Lossy Networks (MPL)" + * Due to very significant changes between draft versions 1 and 2, + * MPL will be implemented as a separate engine and this file here + * will provide legacy support for Draft v1. + * + * \author + * George Oikonomou - + */ + +#ifndef ROLL_TM_H_ +#define ROLL_TM_H_ + +#include "contiki-conf.h" + +#include +/*---------------------------------------------------------------------------*/ +/* Protocol Constants */ +/*---------------------------------------------------------------------------*/ +#define ROLL_TM_VER 1 /* Supported Draft Version */ +#define ROLL_TM_ICMP_CODE 0 /* ICMPv6 code field */ +#define ROLL_TM_IP_HOP_LIMIT 0xFF /* Hop limit for ICMP messages */ +#define ROLL_TM_INFINITE_REDUNDANCY 0xFF +#define ROLL_TM_DGRAM_OUT 0 +#define ROLL_TM_DGRAM_IN 1 + +/* + * The draft does not currently specify a default number for the trickle + * interval nor a way to derive it. Examples however hint at 100 msec. + * + * In draft terminology, we use an 'aggressive' policy (M=0) and a conservative + * one (M=1). + * + * When experimenting with the two policies on the sky platform, + * an interval of 125ms proves to be way too low: When we have traffic, + * doublings happen after the interval end and periodics fire after point T + * within the interval (and sometimes even after interval end). When traffic + * settles down, the code compensates the offsets. + * + * We consider 125, 250ms etc because they are nice divisors of 1 sec + * (quotient is power of two). For some machines (e.g sky/msp430, + * sensinode/cc243x), this is also a nice number of clock ticks + * + * After experimentation, the values of Imin leading to best performance are: + * ContikiMAC: Imin=64 (500ms) + * Null RDC: imin=16 (125ms) + */ + +/* Configuration for Timer with M=0 (aggressive) */ +#ifdef ROLL_TM_CONF_IMIN_0 +#define ROLL_TM_IMIN_0 ROLL_TM_CONF_IMIN_0 +#else +#define ROLL_TM_IMIN_0 32 /* 250 msec */ +#endif + +#ifdef ROLL_TM_CONF_IMAX_0 +#define ROLL_TM_IMAX_0 ROLL_TM_CONF_IMAX_0 +#else +#define ROLL_TM_IMAX_0 1 /* Imax = 500ms */ +#endif + +#ifdef ROLL_TM_CONF_K_0 +#define ROLL_TM_K_0 ROLL_TM_CONF_K_0 +#else +#define ROLL_TM_K_0 ROLL_TM_INFINITE_REDUNDANCY +#endif + +#ifdef ROLL_TM_CONF_T_ACTIVE_0 +#define ROLL_TM_T_ACTIVE_0 ROLL_TM_CONF_T_ACTIVE_0 +#else +#define ROLL_TM_T_ACTIVE_0 3 +#endif + +#ifdef ROLL_TM_CONF_T_DWELL_0 +#define ROLL_TM_T_DWELL_0 ROLL_TM_CONF_T_DWELL_0 +#else +#define ROLL_TM_T_DWELL_0 11 +#endif + +/* Configuration for Timer with M=1 (conservative) */ +#ifdef ROLL_TM_CONF_IMIN_1 +#define ROLL_TM_IMIN_1 ROLL_TM_CONF_IMIN_1 +#else +#define ROLL_TM_IMIN_1 64 /* 500 msec */ +#endif + +#ifdef ROLL_TM_CONF_IMAX_1 +#define ROLL_TM_IMAX_1 ROLL_TM_CONF_IMAX_1 +#else +#define ROLL_TM_IMAX_1 9 /* Imax = 256 secs */ +#endif + +#ifdef ROLL_TM_CONF_K_1 +#define ROLL_TM_K_1 ROLL_TM_CONF_K_1 +#else +#define ROLL_TM_K_1 1 +#endif + +#ifdef ROLL_TM_CONF_T_ACTIVE_1 +#define ROLL_TM_T_ACTIVE_1 ROLL_TM_CONF_T_ACTIVE_1 +#else +#define ROLL_TM_T_ACTIVE_1 3 +#endif + +#ifdef ROLL_TM_CONF_T_DWELL_1 +#define ROLL_TM_T_DWELL_1 ROLL_TM_CONF_T_DWELL_1 +#else +#define ROLL_TM_T_DWELL_1 12 +#endif +/*---------------------------------------------------------------------------*/ +/* Configuration */ +/*---------------------------------------------------------------------------*/ +/* + * Number of Sliding Windows + * In essence: How many unique sources of simultaneous multicast traffic do we + * want to support for our lowpan + * If a node is seeding two multicast streams, parametrized on different M + * values, then this seed will occupy two different sliding windows + */ +#ifdef ROLL_TM_CONF_WINS +#define ROLL_TM_WINS ROLL_TM_CONF_WINS +#else +#define ROLL_TM_WINS 2 +#endif +/*---------------------------------------------------------------------------*/ +/* + * Maximum Number of Buffered Multicast Messages + * This buffer is shared across all Seed IDs, therefore a new very active Seed + * may eventually occupy all slots. It would make little sense (if any) to + * define support for fewer buffered messages than seeds*2 + */ +#ifdef ROLL_TM_CONF_BUFF_NUM +#define ROLL_TM_BUFF_NUM ROLL_TM_CONF_BUFF_NUM +#else +#define ROLL_TM_BUFF_NUM 6 +#endif +/*---------------------------------------------------------------------------*/ +/* + * Use Short Seed IDs [short: 2, long: 16 (default)] + * It can be argued that we should (and it would be easy to) support both at + * the same time but the draft doesn't list this as a MUST so we opt for + * code/ram savings + */ +#ifdef ROLL_TM_CONF_SHORT_SEEDS +#define ROLL_TM_SHORT_SEEDS ROLL_TM_CONF_SHORT_SEEDS +#else +#define ROLL_TM_SHORT_SEEDS 0 +#endif +/*---------------------------------------------------------------------------*/ +/* + * Destination address for our ICMPv6 advertisements. The draft gives us a + * choice between LL all-nodes or LL all-routers + * + * We use allrouters unless a conf directive chooses otherwise + */ +#ifdef ROLL_TM_CONF_DEST_ALL_NODES +#define ROLL_TM_DEST_ALL_NODES ROLL_TM_CONF_DEST_ALL_NODES +#else +#define ROLL_TM_DEST_ALL_NODES 0 +#endif +/*---------------------------------------------------------------------------*/ +/* + * M param for our outgoing messages + * By default, we set the M bit (conservative). Define this as 0 to clear the + * M bit in our outgoing messages (aggressive) + */ +#ifdef ROLL_TM_CONF_SET_M_BIT +#define ROLL_TM_SET_M_BIT ROLL_TM_CONF_SET_M_BIT +#else +#define ROLL_TM_SET_M_BIT 1 +#endif +/*---------------------------------------------------------------------------*/ +/* Prototypes of additional Trickle Multicast functions */ +/*---------------------------------------------------------------------------*/ +/** + * \brief Called by the uIPv6 engine when it receives a Trickle Multicast + * ICMPv6 datagram + */ +void roll_tm_icmp_input(); +/*---------------------------------------------------------------------------*/ +/* Stats datatype */ +/*---------------------------------------------------------------------------*/ +struct roll_tm_stats { + uint16_t mcast_in_unique; + uint16_t mcast_in_all; /* At layer 3 */ + uint16_t mcast_in_ours; /* Unique and we are a group member */ + uint16_t mcast_fwd; /* Forwarded by us but we are not the seed */ + uint16_t mcast_out; /* We are the seed */ + uint16_t mcast_bad; + uint16_t mcast_dropped; + uint16_t icmp_in; + uint16_t icmp_out; + uint16_t icmp_bad; +}; + +#endif /* ROLL_TM_H_ */ From 226701b098045c8dd32d35ab7dd3c0864b9b49f9 Mon Sep 17 00:00:00 2001 From: George Oikonomou Date: Fri, 11 Nov 2011 12:08:29 +0000 Subject: [PATCH 26/92] Implement multicast engine hooks in the uIPv6 core - init() - process incoming multicast datagram - Pass ICMPv6 trickle messages to the engine --- core/net/ip/uip-udp-packet.c | 9 +++++++++ core/net/ipv6/uip6.c | 37 ++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/core/net/ip/uip-udp-packet.c b/core/net/ip/uip-udp-packet.c index 5b03be54b..b327b652d 100644 --- a/core/net/ip/uip-udp-packet.c +++ b/core/net/ip/uip-udp-packet.c @@ -42,6 +42,7 @@ extern uint16_t uip_slen; #include "net/ip/uip-udp-packet.h" +#include "net/ipv6/multicast/uip-mcast6.h" #include @@ -57,6 +58,14 @@ uip_udp_packet_send(struct uip_udp_conn *c, const void *data, int len) len > UIP_BUFSIZE - UIP_LLH_LEN - UIP_IPUDPH_LEN? UIP_BUFSIZE - UIP_LLH_LEN - UIP_IPUDPH_LEN: len); uip_process(UIP_UDP_SEND_CONN); + +#if UIP_CONF_IPV6_MULTICAST + /* Let the multicast engine process the datagram before we send it */ + if(uip_is_addr_mcast_routable(&uip_udp_conn->ripaddr)) { + UIP_MCAST6.out(); + } +#endif /* UIP_IPV6_MULTICAST */ + #if UIP_CONF_IPV6 tcpip_ipv6_output(); #else diff --git a/core/net/ipv6/uip6.c b/core/net/ipv6/uip6.c index fc3d244d2..f8553a336 100644 --- a/core/net/ipv6/uip6.c +++ b/core/net/ipv6/uip6.c @@ -75,6 +75,7 @@ #include "net/ipv6/uip-icmp6.h" #include "net/ipv6/uip-nd6.h" #include "net/ipv6/uip-ds6.h" +#include "net/ipv6/multicast/uip-mcast6.h" #include @@ -429,6 +430,10 @@ uip_init(void) uip_udp_conns[c].lport = 0; } #endif /* UIP_UDP */ + +#if UIP_CONF_IPV6_MULTICAST + UIP_MCAST6.init(); +#endif } /*---------------------------------------------------------------------------*/ #if UIP_TCP && UIP_ACTIVE_OPEN @@ -1151,6 +1156,28 @@ uip_process(uint8_t flag) } } + /* + * Process Packets with a routable multicast destination: + * - We invoke the multicast engine and let it do its thing + * (cache, forward etc). + * - We never execute the datagram forwarding logic in this file here. When + * the engine returns, forwarding has been handled if and as required. + * - Depending on the return value, we either discard or deliver up the stack + * + * All multicast engines must hook in here. After this function returns, we + * expect UIP_BUF to be unmodified + */ +#if UIP_CONF_IPV6_MULTICAST + if(uip_is_addr_mcast_routable(&UIP_IP_BUF->destipaddr)) { + if(UIP_MCAST6.in() == UIP_MCAST6_ACCEPT) { + /* Deliver up the stack */ + goto process; + } else { + /* Don't deliver up the stack */ + goto drop; + } + } +#endif /* UIP_IPV6_CONF_MULTICAST */ /* TBD Some Parameter problem messages */ if(!uip_ds6_is_my_addr(&UIP_IP_BUF->destipaddr) && @@ -1220,6 +1247,10 @@ uip_process(uint8_t flag) uip_ext_bitmap = 0; #endif /* UIP_CONF_ROUTER */ +#if UIP_CONF_IPV6_MULTICAST + process: +#endif + while(1) { switch(*uip_next_hdr){ #if UIP_TCP @@ -1437,6 +1468,12 @@ uip_process(uint8_t flag) UIP_STAT(++uip_stat.icmp.recv); uip_len = 0; break; +#if UIP_CONF_IPV6_ROLL_TM + case ICMP6_ROLL_TM: + roll_tm_icmp_input(); + uip_len = 0; + break; +#endif default: PRINTF("Unknown icmp6 message type %d\n", UIP_ICMP_BUF->type); UIP_STAT(++uip_stat.icmp.drop); From 230881df445c8abc9a6fc192a0df22b5e12a1166 Mon Sep 17 00:00:00 2001 From: George Oikonomou Date: Fri, 11 Nov 2011 13:29:55 +0000 Subject: [PATCH 27/92] Multicast README --- core/net/ipv6/multicast/README.md | 111 ++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 core/net/ipv6/multicast/README.md diff --git a/core/net/ipv6/multicast/README.md b/core/net/ipv6/multicast/README.md new file mode 100644 index 000000000..f90c37d3e --- /dev/null +++ b/core/net/ipv6/multicast/README.md @@ -0,0 +1,111 @@ +README file for Contiki's IPv6 multicast core + +Author: George Oikonomou + +What does it do +=============== +These files, alongside some core modifications, add support for IPv6 multicast +to contiki's uIPv6 engine. + +Currently, two modes are supported: + +* 'Stateless Multicast RPL Forwarding' (SMRF) + RPL in MOP 3 handles group management as per the RPL docs, + SMRF is a lightweight engine which handles datagram forwarding. + SMRF is documented here: + http://dx.doi.org/10.1007/s11277-013-1250-5 + and here: + http://dx.doi.org/10.1109/PerComW.2012.6197494 +* 'Multicast Forwarding with Trickle' according to the algorithm described + in the internet draft: + http://tools.ietf.org/html/draft-ietf-roll-trickle-mcast + The version of this draft that's currently implementated is documented + in `roll-tm.h` + +More engines can (and hopefully will) be added in the future. The first +addition is most likely going to be an updated implementation of MPL + +The Big Gotcha +============== +Currently we only support traffic originating and destined inside a single 6LoWPAN +To be able to send multicast traffic from the internet to 6LoWPAN nodes or the other +way round, we need border routers or other gateway devices to be able to achieve +the following: + +* Add/Remove Trickle Multicast, RPL or other HBHO headers as necessary for datagrams + entering / exiting the 6LoWPAN +* Advertise multicast group membership to the internet (e.g. with MLD) + +These are currently not implemented and are in the ToDo list. Contributions welcome. + +Where to Start +============== +The best place in `examples/ipv6/multicast` + +There is a cooja example demonstrating basic functionality + +How to Use +========== +Look in `core/net/ipv6/multicast/uip-mcast6-engines.h` for a list of supported +multicast engines. + +To turn on multicast support, add this line in your `project-` or `contiki-conf.h` + + #define UIP_MCAST6_CONF_ENGINE xyz + + where xyz is a value from `uip-mcast6-engines.h` + +To disable: + + #define UIP_MCAST6_CONF_ENGINE 0 + +You also need to make sure the multicast code gets built. Your example's +(or platform's) Makefile should include this: + + MODULES += core/net/ipv6/multicast + +How to extend +============= +Let's assume you want to write an engine called foo. +The multicast API defines a multicast engine driver in a fashion similar to +the various NETSTACK layer drivers. This API defines functions for basic +multicast operations (init, in, out). +In order to extend multicast with a new engine, perform the following steps: + +- Open `uip-mcast6-engines.h` and assign a unique integer code to your engine + + #define UIP_MCAST6_ENGINE_FOO xyz + + - Include your engine's `foo.h` + +- In `foo.c`, implement: + * `init()` + * `in()` + * `out()` + * Define your driver like so: + + `const struct uip_mcast6_driver foo_driver = { ... }` + +- If you want to maintain stats: + * Declare a `struct foo_stats` in `foo.h` + * Define a variable of type `struct foo_stats` called `foo_stats` in `foo.c` + The names `foo_stats` for the stats variable and stats datatype are only + examples. You can assign different names + +- Open `uip-mcast6.h` and add a section in the `#if` spree. This aims to + configure the uIPv6 core. More specifically, you need to: + * Specify if you want to put RPL in MOP3 by defining + `RPL_CONF_MULTICAST`: 1: MOP 3, 0: non-multicast MOP + * Define your engine details + + #define UIP_MCAST6 foo_driver + #define UIP_MCAST6_STATS foo_stats + typedef struct foo_stats uip_mcast6_stats_t; + + * Optionally, add a configuration check block to stop builds when the + configuration is not sane. + +If you need your engine to perform operations not supported by the generic +UIP_MCAST6 API, you will have to hook those in the uip core manually. As an +example, see how the core is modified so that it can deliver ICMPv6 datagrams +to the ROLL TM engine. From 0bbb574689f77bb23936e9348d49f858c5cf9f6d Mon Sep 17 00:00:00 2001 From: George Oikonomou Date: Fri, 14 Dec 2012 15:44:46 +0000 Subject: [PATCH 28/92] IPv6 Multicast Example --- examples/ipv6/multicast/Makefile | 11 ++ examples/ipv6/multicast/intermediate.c | 64 ++++++ examples/ipv6/multicast/multicast.csc | 257 +++++++++++++++++++++++++ examples/ipv6/multicast/project-conf.h | 69 +++++++ examples/ipv6/multicast/root.c | 171 ++++++++++++++++ examples/ipv6/multicast/sink.c | 136 +++++++++++++ 6 files changed, 708 insertions(+) create mode 100644 examples/ipv6/multicast/Makefile create mode 100644 examples/ipv6/multicast/intermediate.c create mode 100644 examples/ipv6/multicast/multicast.csc create mode 100644 examples/ipv6/multicast/project-conf.h create mode 100644 examples/ipv6/multicast/root.c create mode 100644 examples/ipv6/multicast/sink.c diff --git a/examples/ipv6/multicast/Makefile b/examples/ipv6/multicast/Makefile new file mode 100644 index 000000000..4bd9ce515 --- /dev/null +++ b/examples/ipv6/multicast/Makefile @@ -0,0 +1,11 @@ +DEFINES+=PROJECT_CONF_H=\"project-conf.h\" +UIP_CONF_IPV6=1 + +CONTIKI_PROJECT = root intermediate sink +all: $(CONTIKI_PROJECT) + +CONTIKI = ../../.. + +MODULES += core/net/ipv6/multicast + +include $(CONTIKI)/Makefile.include diff --git a/examples/ipv6/multicast/intermediate.c b/examples/ipv6/multicast/intermediate.c new file mode 100644 index 000000000..6d8f27284 --- /dev/null +++ b/examples/ipv6/multicast/intermediate.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2010, Loughborough University - 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 + * This node is part of the RPL multicast example. It basically + * represents a node that does not join the multicast group + * but still knows how to forward multicast packets + * The example will work with or without any number of these nodes + * + * Also, performs some sanity checks for the contiki configuration + * and generates an error if the conf is bad + * + * \author + * George Oikonomou - + */ + +#include "contiki.h" +#include "contiki-net.h" +#include "net/ipv6/multicast/uip-mcast6.h" + +#if !UIP_CONF_IPV6 || !UIP_CONF_ROUTER || !UIP_CONF_IPV6_MULTICAST || !UIP_CONF_IPV6_RPL +#error "This example can not work with the current contiki configuration" +#error "Check the values of: UIP_CONF_IPV6, UIP_CONF_ROUTER, UIP_CONF_IPV6_RPL" +#endif +/*---------------------------------------------------------------------------*/ +PROCESS(mcast_intermediate_process, "Intermediate Process"); +AUTOSTART_PROCESSES(&mcast_intermediate_process); +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(mcast_intermediate_process, ev, data) +{ + PROCESS_BEGIN(); + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/ipv6/multicast/multicast.csc b/examples/ipv6/multicast/multicast.csc new file mode 100644 index 000000000..5339f0351 --- /dev/null +++ b/examples/ipv6/multicast/multicast.csc @@ -0,0 +1,257 @@ + + + [APPS_DIR]/mrm + [APPS_DIR]/mspsim + [APPS_DIR]/avrora + [APPS_DIR]/serial_socket + [APPS_DIR]/collect-view + [APPS_DIR]/powertracker + + Example of a uIPv6 network with multicast support + 123456 + 1000000 + + org.contikios.cooja.radiomediums.UDGM + 50.0 + 50.0 + 1.0 + 1.0 + + + 40000 + + + org.contikios.cooja.mspmote.SkyMoteType + sky1 + root + [CONTIKI_DIR]/examples/ipv6/multicast/root.c + make root.sky TARGET=sky + [CONTIKI_DIR]/examples/ipv6/multicast/root.sky + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.interfaces.IPAddress + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + org.contikios.cooja.mspmote.interfaces.MspClock + org.contikios.cooja.mspmote.interfaces.MspMoteID + org.contikios.cooja.mspmote.interfaces.SkyButton + org.contikios.cooja.mspmote.interfaces.SkyFlash + org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem + org.contikios.cooja.mspmote.interfaces.Msp802154Radio + org.contikios.cooja.mspmote.interfaces.MspSerial + org.contikios.cooja.mspmote.interfaces.SkyLED + org.contikios.cooja.mspmote.interfaces.MspDebugOutput + org.contikios.cooja.mspmote.interfaces.SkyTemperature + + + org.contikios.cooja.mspmote.SkyMoteType + sky2 + intermediate + [CONTIKI_DIR]/examples/ipv6/multicast/intermediate.c + make intermediate.sky TARGET=sky + [CONTIKI_DIR]/examples/ipv6/multicast/intermediate.sky + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.interfaces.IPAddress + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + org.contikios.cooja.mspmote.interfaces.MspClock + org.contikios.cooja.mspmote.interfaces.MspMoteID + org.contikios.cooja.mspmote.interfaces.SkyButton + org.contikios.cooja.mspmote.interfaces.SkyFlash + org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem + org.contikios.cooja.mspmote.interfaces.Msp802154Radio + org.contikios.cooja.mspmote.interfaces.MspSerial + org.contikios.cooja.mspmote.interfaces.SkyLED + org.contikios.cooja.mspmote.interfaces.MspDebugOutput + org.contikios.cooja.mspmote.interfaces.SkyTemperature + + + org.contikios.cooja.mspmote.SkyMoteType + sky3 + sink + [CONTIKI_DIR]/examples/ipv6/multicast/sink.c + make sink.sky TARGET=sky + [CONTIKI_DIR]/examples/ipv6/multicast/sink.sky + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.interfaces.IPAddress + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + org.contikios.cooja.mspmote.interfaces.MspClock + org.contikios.cooja.mspmote.interfaces.MspMoteID + org.contikios.cooja.mspmote.interfaces.SkyButton + org.contikios.cooja.mspmote.interfaces.SkyFlash + org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem + org.contikios.cooja.mspmote.interfaces.Msp802154Radio + org.contikios.cooja.mspmote.interfaces.MspSerial + org.contikios.cooja.mspmote.interfaces.SkyLED + org.contikios.cooja.mspmote.interfaces.MspDebugOutput + org.contikios.cooja.mspmote.interfaces.SkyTemperature + + + + + org.contikios.cooja.interfaces.Position + 5.995813174969022 + 34.43129455447824 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 1 + + sky1 + + + + + org.contikios.cooja.interfaces.Position + 40.70237155931961 + 16.396742420332068 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 2 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 100.3720728044051 + 70.93197095432518 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 3 + + sky3 + + + + + org.contikios.cooja.interfaces.Position + 81.7376718406712 + 28.854291358797 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 4 + + sky3 + + + + + org.contikios.cooja.interfaces.Position + -26.161520836433183 + 8.116006415286686 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 5 + + sky3 + + + + + org.contikios.cooja.interfaces.Position + -34.57705675553882 + 92.87247531485058 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 6 + + sky3 + + + + + org.contikios.cooja.interfaces.Position + 39.86312587077661 + 59.603125741056246 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 7 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 1.4345607604759194 + 75.2481773153879 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 8 + + sky2 + + + + org.contikios.cooja.plugins.SimControl + 318 + 0 + 192 + 0 + 0 + + + org.contikios.cooja.plugins.Visualizer + + org.contikios.cooja.plugins.skins.IDVisualizerSkin + org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin + org.contikios.cooja.plugins.skins.UDGMVisualizerSkin + org.contikios.cooja.plugins.skins.AddressVisualizerSkin + 3.914959956760176 0.0 0.0 3.914959956760176 300.2075734071477 -15.682931033747009 + + 869 + 3 + 441 + 320 + 3 + + + org.contikios.cooja.plugins.LogListener + + + + + + 1281 + 2 + 213 + -1 + 714 + + + org.contikios.cooja.plugins.RadioLogger + + 117 + + false + false + + + 1280 + 1 + 268 + 0 + 445 + + + diff --git a/examples/ipv6/multicast/project-conf.h b/examples/ipv6/multicast/project-conf.h new file mode 100644 index 000000000..84686ce21 --- /dev/null +++ b/examples/ipv6/multicast/project-conf.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2010, Loughborough University - 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 + * Project specific configuration defines for the RPl multicast + * example. + * + * \author + * George Oikonomou - + */ + +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ + +#include "net/ipv6/multicast/uip-mcast6-engines.h" + +/* Change this to switch engines. Engine codes in uip-mcast6-engines.h */ +#define UIP_MCAST6_CONF_ENGINE UIP_MCAST6_ENGINE_ROLL_TM + +/* For Imin: Use 16 over NullRDC, 64 over Contiki MAC */ +#define ROLL_TM_CONF_IMIN_1 64 + +#undef UIP_CONF_IPV6_RPL +#undef UIP_CONF_ND6_SEND_RA +#undef UIP_CONF_ROUTER +#define UIP_CONF_IPV6_RPL 1 +#define UIP_CONF_ND6_SEND_RA 0 +#define UIP_CONF_ROUTER 1 +#define UIP_MCAST6_ROUTE_CONF_ROUTES 1 + +#undef UIP_CONF_TCP +#define UIP_CONF_TCP 0 + +/* Code/RAM footprint savings so that things will fit on our device */ +#undef UIP_CONF_DS6_NBR_NBU +#undef UIP_CONF_DS6_ROUTE_NBU +#define UIP_CONF_DS6_NBR_NBU 10 +#define UIP_CONF_DS6_ROUTE_NBU 10 + +#endif /* PROJECT_CONF_H_ */ diff --git a/examples/ipv6/multicast/root.c b/examples/ipv6/multicast/root.c new file mode 100644 index 000000000..2601d71a8 --- /dev/null +++ b/examples/ipv6/multicast/root.c @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2010, Loughborough University - 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 + * This node is part of the RPL multicast example. It is an RPL root + * and sends a multicast message periodically. For the example to work, + * we need one of those nodes. + * + * \author + * George Oikonomou - + */ + +#include "contiki.h" +#include "contiki-lib.h" +#include "contiki-net.h" +#include "net/ipv6/multicast/uip-mcast6.h" + +#include + +#define DEBUG DEBUG_PRINT +#include "net/ip/uip-debug.h" +#include "net/rpl/rpl.h" + +#define MAX_PAYLOAD_LEN 120 +#define MCAST_SINK_UDP_PORT 3001 /* Host byte order */ +#define SEND_INTERVAL CLOCK_SECOND /* clock ticks */ +#define ITERATIONS 100 /* messages */ + +/* Start sending messages START_DELAY secs after we start so that routing can + * converge */ +#define START_DELAY 60 + +static struct uip_udp_conn * mcast_conn; +static char buf[MAX_PAYLOAD_LEN]; +static uint32_t seq_id; + +#if !UIP_CONF_IPV6 || !UIP_CONF_ROUTER || !UIP_CONF_IPV6_MULTICAST || !UIP_CONF_IPV6_RPL +#error "This example can not work with the current contiki configuration" +#error "Check the values of: UIP_CONF_IPV6, UIP_CONF_ROUTER, UIP_CONF_IPV6_RPL" +#endif +/*---------------------------------------------------------------------------*/ +PROCESS(rpl_root_process, "RPL ROOT, Multicast Sender"); +AUTOSTART_PROCESSES(&rpl_root_process); +/*---------------------------------------------------------------------------*/ +static void +multicast_send() +{ + uint32_t id; + + id = uip_htonl(seq_id); + memset(buf, 0, MAX_PAYLOAD_LEN); + memcpy(buf, &id, sizeof(seq_id)); + + PRINTF("Send to: "); + PRINT6ADDR(&mcast_conn->ripaddr); + PRINTF(" Remote Port %u,", uip_ntohs(mcast_conn->rport)); + PRINTF(" (msg=0x%08lx)", (unsigned long)uip_ntohl(*((uint32_t *)buf))); + PRINTF(" %lu bytes\n", (unsigned long)sizeof(id)); + + seq_id++; + uip_udp_packet_send(mcast_conn, buf, sizeof(id)); +} +/*---------------------------------------------------------------------------*/ +static void +prepare_mcast() +{ + uip_ipaddr_t ipaddr; + + /* + * IPHC will use stateless multicast compression for this destination + * (M=1, DAC=0), with 32 inline bits (1E 89 AB CD) + */ + uip_ip6addr(&ipaddr,0xFF1E,0,0,0,0,0,0x89,0xABCD); + mcast_conn = udp_new(&ipaddr, UIP_HTONS(MCAST_SINK_UDP_PORT), NULL); +} +/*---------------------------------------------------------------------------*/ +static void +set_own_addresses() +{ + int i; + uint8_t state; + rpl_dag_t *dag; + uip_ipaddr_t ipaddr; + + uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); + uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); + + PRINTF("Our IPv6 addresses:\n"); + for(i = 0; i < UIP_DS6_ADDR_NB; i++) { + state = uip_ds6_if.addr_list[i].state; + if(uip_ds6_if.addr_list[i].isused && (state == ADDR_TENTATIVE || state + == ADDR_PREFERRED)) { + PRINTF(" "); + PRINT6ADDR(&uip_ds6_if.addr_list[i].ipaddr); + PRINTF("\n"); + if (state == ADDR_TENTATIVE) { + uip_ds6_if.addr_list[i].state = ADDR_PREFERRED; + } + } + } + + /* Become root of a new DODAG with ID our global v6 address */ + dag = rpl_set_root(RPL_DEFAULT_INSTANCE, &ipaddr); + if(dag != NULL) { + rpl_set_prefix(dag, &ipaddr, 64); + PRINTF("Created a new RPL dag with ID: "); + PRINT6ADDR(&dag->dag_id); + PRINTF("\n"); + } +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(rpl_root_process, ev, data) +{ + static struct etimer et; + + PROCESS_BEGIN(); + + PRINTF("Multicast Engine: '%s'\n", UIP_MCAST6.name); + + NETSTACK_MAC.off(1); + + set_own_addresses(); + + prepare_mcast(); + + etimer_set(&et, START_DELAY * CLOCK_SECOND); + while(1) { + PROCESS_YIELD(); + if(etimer_expired(&et)) { + if(seq_id == ITERATIONS) { + etimer_stop(&et); + } else { + multicast_send(); + etimer_set(&et, SEND_INTERVAL); + } + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/ipv6/multicast/sink.c b/examples/ipv6/multicast/sink.c new file mode 100644 index 000000000..c062d2f69 --- /dev/null +++ b/examples/ipv6/multicast/sink.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2010, Loughborough University - 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 + * This node is part of the RPL multicast example. It is a node that + * joins a multicast group and listens for messages. It also knows how + * to forward messages down the tree. + * For the example to work, we need one or more of those nodes. + * + * \author + * George Oikonomou - + */ + +#include "contiki.h" +#include "contiki-lib.h" +#include "contiki-net.h" +#include "net/ipv6/multicast/uip-mcast6.h" + +#include + +#define DEBUG DEBUG_PRINT +#include "net/ip/uip-debug.h" + +#define MCAST_SINK_UDP_PORT 3001 /* Host byte order */ + +static struct uip_udp_conn *sink_conn; +static uint16_t count; + +#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) + +#if !UIP_CONF_IPV6 || !UIP_CONF_ROUTER || !UIP_CONF_IPV6_MULTICAST || !UIP_CONF_IPV6_RPL +#error "This example can not work with the current contiki configuration" +#error "Check the values of: UIP_CONF_IPV6, UIP_CONF_ROUTER, UIP_CONF_IPV6_RPL" +#endif +/*---------------------------------------------------------------------------*/ +PROCESS(mcast_sink_process, "Multicast Sink"); +AUTOSTART_PROCESSES(&mcast_sink_process); +/*---------------------------------------------------------------------------*/ +static void +tcpip_handler(void) +{ + if(uip_newdata()) { + count++; + PRINTF("In: [0x%08lx], TTL %u, total %u\n", + uip_ntohl((unsigned long) *((uint32_t *)(uip_appdata))), + UIP_IP_BUF->ttl, count); + } + return; +} +/*---------------------------------------------------------------------------*/ +static uip_ds6_maddr_t * +join_mcast_group() +{ + uip_ipaddr_t addr; + uip_ds6_maddr_t *rv; + + /* First, set our v6 global */ + uip_ip6addr(&addr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ds6_set_addr_iid(&addr, &uip_lladdr); + uip_ds6_addr_add(&addr, 0, ADDR_AUTOCONF); + + /* + * IPHC will use stateless multicast compression for this destination + * (M=1, DAC=0), with 32 inline bits (1E 89 AB CD) + */ + uip_ip6addr(&addr,0xFF1E,0,0,0,0,0,0x89,0xABCD); + rv = uip_ds6_maddr_add(&addr); + + if(rv) { + PRINTF("Joined multicast group "); + PRINT6ADDR(&uip_ds6_maddr_lookup(&addr)->ipaddr); + PRINTF("\n"); + } + return rv; +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(mcast_sink_process, ev, data) +{ + PROCESS_BEGIN(); + + PRINTF("Multicast Engine: '%s'\n", UIP_MCAST6.name); + + if(join_mcast_group() == NULL) { + PRINTF("Failed to join multicast group\n"); + PROCESS_EXIT(); + } + + count = 0; + + sink_conn = udp_new(NULL, UIP_HTONS(0), NULL); + udp_bind(sink_conn, UIP_HTONS(MCAST_SINK_UDP_PORT)); + + PRINTF("Listening: "); + PRINT6ADDR(&sink_conn->ripaddr); + PRINTF(" local/remote port %u/%u\n", + UIP_HTONS(sink_conn->lport), UIP_HTONS(sink_conn->rport)); + + while(1) { + PROCESS_YIELD(); + if(ev == tcpip_event) { + tcpip_handler(); + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ From 55f1f01a9848a374623679cb3b88c327bba8be9e Mon Sep 17 00:00:00 2001 From: George Oikonomou Date: Sun, 16 Dec 2012 23:33:27 +0000 Subject: [PATCH 29/92] Multicast compile regression tests --- regression-tests/01-compile-base/Makefile | 1 + regression-tests/14-compile-8051-ports/Makefile | 1 + regression-tests/15-compile-arm-ports/Makefile | 2 ++ 3 files changed, 4 insertions(+) diff --git a/regression-tests/01-compile-base/Makefile b/regression-tests/01-compile-base/Makefile index 1252097b5..093dcfa2f 100644 --- a/regression-tests/01-compile-base/Makefile +++ b/regression-tests/01-compile-base/Makefile @@ -34,6 +34,7 @@ webserver-ipv6/eval-adf7xxxmb4z \ wget/minimal-net \ z1/z1 \ settings-example/avr-raven \ +ipv6/multicast/sky \ TOOLS= diff --git a/regression-tests/14-compile-8051-ports/Makefile b/regression-tests/14-compile-8051-ports/Makefile index 004c37d52..974e74df2 100644 --- a/regression-tests/14-compile-8051-ports/Makefile +++ b/regression-tests/14-compile-8051-ports/Makefile @@ -7,6 +7,7 @@ cc2530dk/cc2530dk \ cc2530dk/border-router/cc2530dk \ cc2530dk/udp-ipv6/cc2530dk \ cc2530dk/sniffer/cc2530dk \ +ipv6/multicast/cc2530dk \ TOOLS= diff --git a/regression-tests/15-compile-arm-ports/Makefile b/regression-tests/15-compile-arm-ports/Makefile index 4115ab780..572489d8a 100644 --- a/regression-tests/15-compile-arm-ports/Makefile +++ b/regression-tests/15-compile-arm-ports/Makefile @@ -14,6 +14,8 @@ webserver-ipv6/cc2538dk \ cc2538dk/cc2538dk \ cc2538dk/udp-ipv6-echo-server/cc2538dk \ cc2538dk/sniffer/cc2538dk \ +ipv6/multicast/econotag \ +ipv6/multicast/cc2538dk \ TOOLS= From d397e97e748fdc0a0e806a053dc7d51bcc6e8016 Mon Sep 17 00:00:00 2001 From: Adam Dunkels Date: Sat, 5 Oct 2013 11:25:58 +0200 Subject: [PATCH 30/92] Minor code style fixes --- examples/ipv6/multicast/root.c | 10 +++++----- examples/ipv6/multicast/sink.c | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/ipv6/multicast/root.c b/examples/ipv6/multicast/root.c index 2601d71a8..1c70ed388 100644 --- a/examples/ipv6/multicast/root.c +++ b/examples/ipv6/multicast/root.c @@ -72,7 +72,7 @@ PROCESS(rpl_root_process, "RPL ROOT, Multicast Sender"); AUTOSTART_PROCESSES(&rpl_root_process); /*---------------------------------------------------------------------------*/ static void -multicast_send() +multicast_send(void) { uint32_t id; @@ -91,7 +91,7 @@ multicast_send() } /*---------------------------------------------------------------------------*/ static void -prepare_mcast() +prepare_mcast(void) { uip_ipaddr_t ipaddr; @@ -99,12 +99,12 @@ prepare_mcast() * IPHC will use stateless multicast compression for this destination * (M=1, DAC=0), with 32 inline bits (1E 89 AB CD) */ - uip_ip6addr(&ipaddr,0xFF1E,0,0,0,0,0,0x89,0xABCD); + uip_ip6addr(&ipaddr, 0xFF1E,0,0,0,0,0,0x89,0xABCD); mcast_conn = udp_new(&ipaddr, UIP_HTONS(MCAST_SINK_UDP_PORT), NULL); } /*---------------------------------------------------------------------------*/ static void -set_own_addresses() +set_own_addresses(void) { int i; uint8_t state; @@ -123,7 +123,7 @@ set_own_addresses() PRINTF(" "); PRINT6ADDR(&uip_ds6_if.addr_list[i].ipaddr); PRINTF("\n"); - if (state == ADDR_TENTATIVE) { + if(state == ADDR_TENTATIVE) { uip_ds6_if.addr_list[i].state = ADDR_PREFERRED; } } diff --git a/examples/ipv6/multicast/sink.c b/examples/ipv6/multicast/sink.c index c062d2f69..455e94441 100644 --- a/examples/ipv6/multicast/sink.c +++ b/examples/ipv6/multicast/sink.c @@ -78,7 +78,7 @@ tcpip_handler(void) } /*---------------------------------------------------------------------------*/ static uip_ds6_maddr_t * -join_mcast_group() +join_mcast_group(void) { uip_ipaddr_t addr; uip_ds6_maddr_t *rv; @@ -92,7 +92,7 @@ join_mcast_group() * IPHC will use stateless multicast compression for this destination * (M=1, DAC=0), with 32 inline bits (1E 89 AB CD) */ - uip_ip6addr(&addr,0xFF1E,0,0,0,0,0,0x89,0xABCD); + uip_ip6addr(&addr, 0xFF1E,0,0,0,0,0,0x89,0xABCD); rv = uip_ds6_maddr_add(&addr); if(rv) { From a05d68a0fa095bf120db663cd64ee2ab922b1271 Mon Sep 17 00:00:00 2001 From: Adam Dunkels Date: Sat, 5 Oct 2013 11:26:49 +0200 Subject: [PATCH 31/92] Simple regression test for the IPv6 multicast code with 12 nodes (11 hops) in a line configuration --- .../11-ipv6/17-cooja-multicast-11-hops.csc | 367 ++++++++++++++++++ 1 file changed, 367 insertions(+) create mode 100644 regression-tests/11-ipv6/17-cooja-multicast-11-hops.csc diff --git a/regression-tests/11-ipv6/17-cooja-multicast-11-hops.csc b/regression-tests/11-ipv6/17-cooja-multicast-11-hops.csc new file mode 100644 index 000000000..ec01dd722 --- /dev/null +++ b/regression-tests/11-ipv6/17-cooja-multicast-11-hops.csc @@ -0,0 +1,367 @@ + + + [APPS_DIR]/mrm + [APPS_DIR]/mspsim + [APPS_DIR]/avrora + [APPS_DIR]/serial_socket + [APPS_DIR]/collect-view + [APPS_DIR]/powertracker + + Multicast regression test + 123456 + 1000000 + + se.sics.cooja.radiomediums.UDGM + 15.0 + 0.0 + 1.0 + 1.0 + + + 40000 + + + se.sics.cooja.contikimote.ContikiMoteType + mtype612 + Root/sender + [CONTIKI_DIR]/examples/ipv6/multicast/root.c + make root.cooja TARGET=cooja + se.sics.cooja.interfaces.Position + se.sics.cooja.interfaces.Battery + se.sics.cooja.contikimote.interfaces.ContikiVib + se.sics.cooja.contikimote.interfaces.ContikiMoteID + se.sics.cooja.contikimote.interfaces.ContikiRS232 + se.sics.cooja.contikimote.interfaces.ContikiBeeper + se.sics.cooja.interfaces.RimeAddress + se.sics.cooja.contikimote.interfaces.ContikiIPAddress + se.sics.cooja.contikimote.interfaces.ContikiRadio + se.sics.cooja.contikimote.interfaces.ContikiButton + se.sics.cooja.contikimote.interfaces.ContikiPIR + se.sics.cooja.contikimote.interfaces.ContikiClock + se.sics.cooja.contikimote.interfaces.ContikiLED + se.sics.cooja.contikimote.interfaces.ContikiCFS + se.sics.cooja.interfaces.Mote2MoteRelations + se.sics.cooja.interfaces.MoteAttributes + false + + + se.sics.cooja.contikimote.ContikiMoteType + mtype890 + Intermediate + [CONTIKI_DIR]/examples/ipv6/multicast/intermediate.c + make intermediate.cooja TARGET=cooja + se.sics.cooja.interfaces.Position + se.sics.cooja.interfaces.Battery + se.sics.cooja.contikimote.interfaces.ContikiVib + se.sics.cooja.contikimote.interfaces.ContikiMoteID + se.sics.cooja.contikimote.interfaces.ContikiRS232 + se.sics.cooja.contikimote.interfaces.ContikiBeeper + se.sics.cooja.interfaces.RimeAddress + se.sics.cooja.contikimote.interfaces.ContikiIPAddress + se.sics.cooja.contikimote.interfaces.ContikiRadio + se.sics.cooja.contikimote.interfaces.ContikiButton + se.sics.cooja.contikimote.interfaces.ContikiPIR + se.sics.cooja.contikimote.interfaces.ContikiClock + se.sics.cooja.contikimote.interfaces.ContikiLED + se.sics.cooja.contikimote.interfaces.ContikiCFS + se.sics.cooja.interfaces.Mote2MoteRelations + se.sics.cooja.interfaces.MoteAttributes + false + + + se.sics.cooja.contikimote.ContikiMoteType + mtype956 + Receiver + [CONTIKI_DIR]/examples/ipv6/multicast/sink.c + make sink.cooja TARGET=cooja + se.sics.cooja.interfaces.Position + se.sics.cooja.interfaces.Battery + se.sics.cooja.contikimote.interfaces.ContikiVib + se.sics.cooja.contikimote.interfaces.ContikiMoteID + se.sics.cooja.contikimote.interfaces.ContikiRS232 + se.sics.cooja.contikimote.interfaces.ContikiBeeper + se.sics.cooja.interfaces.RimeAddress + se.sics.cooja.contikimote.interfaces.ContikiIPAddress + se.sics.cooja.contikimote.interfaces.ContikiRadio + se.sics.cooja.contikimote.interfaces.ContikiButton + se.sics.cooja.contikimote.interfaces.ContikiPIR + se.sics.cooja.contikimote.interfaces.ContikiClock + se.sics.cooja.contikimote.interfaces.ContikiLED + se.sics.cooja.contikimote.interfaces.ContikiCFS + se.sics.cooja.interfaces.Mote2MoteRelations + se.sics.cooja.interfaces.MoteAttributes + false + + + + se.sics.cooja.interfaces.Position + -7.983976888750106 + 0.37523218201044733 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 1 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype612 + + + + se.sics.cooja.interfaces.Position + 0.0 + 0.0 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 2 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype890 + + + + se.sics.cooja.interfaces.Position + 10.0 + 0.0 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 3 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype890 + + + + se.sics.cooja.interfaces.Position + 20.0 + 0.0 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 4 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype890 + + + + se.sics.cooja.interfaces.Position + 30.0 + 0.0 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 5 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype890 + + + + se.sics.cooja.interfaces.Position + 40.0 + 0.0 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 6 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype890 + + + + se.sics.cooja.interfaces.Position + 50.0 + 0.0 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 7 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype890 + + + + se.sics.cooja.interfaces.Position + 60.0 + 0.0 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 8 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype890 + + + + se.sics.cooja.interfaces.Position + 70.0 + 0.0 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 9 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype890 + + + + se.sics.cooja.interfaces.Position + 79.93950307524713 + -0.043451055913349 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 10 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype890 + + + + se.sics.cooja.interfaces.Position + 90.0 + 0.0 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 11 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype890 + + + + se.sics.cooja.interfaces.Position + 99.61761525766555 + 0.37523218201044733 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 12 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype956 + + + + se.sics.cooja.plugins.SimControl + 280 + 1 + 160 + 400 + 0 + + + se.sics.cooja.plugins.Visualizer + + true + se.sics.cooja.plugins.skins.IDVisualizerSkin + se.sics.cooja.plugins.skins.GridVisualizerSkin + se.sics.cooja.plugins.skins.TrafficVisualizerSkin + se.sics.cooja.plugins.skins.UDGMVisualizerSkin + se.sics.cooja.plugins.skins.MoteTypeVisualizerSkin + 2.388440494916608 0.0 0.0 2.388440494916608 109.06925371156906 149.10378026149033 + + 400 + 3 + 400 + 1 + 1 + + + se.sics.cooja.plugins.LogListener + + + + + + 1200 + 2 + 240 + 400 + 160 + + + se.sics.cooja.plugins.Notes + + Enter notes here + true + + 920 + 4 + 160 + 680 + 0 + + + se.sics.cooja.plugins.ScriptRunner + + + true + + 600 + 0 + 700 + 843 + 77 + + + From 925f98728fb4ff8938a0aa7f6cae2c3e81daca73 Mon Sep 17 00:00:00 2001 From: Adam Dunkels Date: Sat, 5 Oct 2013 11:28:29 +0200 Subject: [PATCH 32/92] Simple regression test for the IPv6 multicast code with 32 nodes (31 hops) in a line configuration --- .../11-ipv6/18-cooja-multicast-31-hops.csc | 707 ++++++++++++++++++ 1 file changed, 707 insertions(+) create mode 100644 regression-tests/11-ipv6/18-cooja-multicast-31-hops.csc diff --git a/regression-tests/11-ipv6/18-cooja-multicast-31-hops.csc b/regression-tests/11-ipv6/18-cooja-multicast-31-hops.csc new file mode 100644 index 000000000..89626ddb6 --- /dev/null +++ b/regression-tests/11-ipv6/18-cooja-multicast-31-hops.csc @@ -0,0 +1,707 @@ + + + [APPS_DIR]/mrm + [APPS_DIR]/mspsim + [APPS_DIR]/avrora + [APPS_DIR]/serial_socket + [APPS_DIR]/collect-view + [APPS_DIR]/powertracker + + Multicast regression test + 123456 + 1000000 + + se.sics.cooja.radiomediums.UDGM + 15.0 + 0.0 + 1.0 + 1.0 + + + 40000 + + + se.sics.cooja.contikimote.ContikiMoteType + mtype816 + Root/sender + [CONTIKI_DIR]/examples/ipv6/multicast/root.c + make root.cooja TARGET=cooja + se.sics.cooja.interfaces.Position + se.sics.cooja.interfaces.Battery + se.sics.cooja.contikimote.interfaces.ContikiVib + se.sics.cooja.contikimote.interfaces.ContikiMoteID + se.sics.cooja.contikimote.interfaces.ContikiRS232 + se.sics.cooja.contikimote.interfaces.ContikiBeeper + se.sics.cooja.interfaces.RimeAddress + se.sics.cooja.contikimote.interfaces.ContikiIPAddress + se.sics.cooja.contikimote.interfaces.ContikiRadio + se.sics.cooja.contikimote.interfaces.ContikiButton + se.sics.cooja.contikimote.interfaces.ContikiPIR + se.sics.cooja.contikimote.interfaces.ContikiClock + se.sics.cooja.contikimote.interfaces.ContikiLED + se.sics.cooja.contikimote.interfaces.ContikiCFS + se.sics.cooja.interfaces.Mote2MoteRelations + se.sics.cooja.interfaces.MoteAttributes + false + + + se.sics.cooja.contikimote.ContikiMoteType + mtype53 + Intermediate + [CONTIKI_DIR]/examples/ipv6/multicast/intermediate.c + make intermediate.cooja TARGET=cooja + se.sics.cooja.interfaces.Position + se.sics.cooja.interfaces.Battery + se.sics.cooja.contikimote.interfaces.ContikiVib + se.sics.cooja.contikimote.interfaces.ContikiMoteID + se.sics.cooja.contikimote.interfaces.ContikiRS232 + se.sics.cooja.contikimote.interfaces.ContikiBeeper + se.sics.cooja.interfaces.RimeAddress + se.sics.cooja.contikimote.interfaces.ContikiIPAddress + se.sics.cooja.contikimote.interfaces.ContikiRadio + se.sics.cooja.contikimote.interfaces.ContikiButton + se.sics.cooja.contikimote.interfaces.ContikiPIR + se.sics.cooja.contikimote.interfaces.ContikiClock + se.sics.cooja.contikimote.interfaces.ContikiLED + se.sics.cooja.contikimote.interfaces.ContikiCFS + se.sics.cooja.interfaces.Mote2MoteRelations + se.sics.cooja.interfaces.MoteAttributes + false + + + se.sics.cooja.contikimote.ContikiMoteType + mtype191 + Receiver + [CONTIKI_DIR]/examples/ipv6/multicast/sink.c + make sink.cooja TARGET=cooja + se.sics.cooja.interfaces.Position + se.sics.cooja.interfaces.Battery + se.sics.cooja.contikimote.interfaces.ContikiVib + se.sics.cooja.contikimote.interfaces.ContikiMoteID + se.sics.cooja.contikimote.interfaces.ContikiRS232 + se.sics.cooja.contikimote.interfaces.ContikiBeeper + se.sics.cooja.interfaces.RimeAddress + se.sics.cooja.contikimote.interfaces.ContikiIPAddress + se.sics.cooja.contikimote.interfaces.ContikiRadio + se.sics.cooja.contikimote.interfaces.ContikiButton + se.sics.cooja.contikimote.interfaces.ContikiPIR + se.sics.cooja.contikimote.interfaces.ContikiClock + se.sics.cooja.contikimote.interfaces.ContikiLED + se.sics.cooja.contikimote.interfaces.ContikiCFS + se.sics.cooja.interfaces.Mote2MoteRelations + se.sics.cooja.interfaces.MoteAttributes + false + + + + se.sics.cooja.interfaces.Position + -7.983976888750106 + 0.37523218201044733 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 1 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype816 + + + + se.sics.cooja.interfaces.Position + 0.0 + 0.0 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 2 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype53 + + + + se.sics.cooja.interfaces.Position + 10.0 + 0.0 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 3 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype53 + + + + se.sics.cooja.interfaces.Position + 20.0 + 0.0 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 4 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype53 + + + + se.sics.cooja.interfaces.Position + 30.0 + 0.0 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 5 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype53 + + + + se.sics.cooja.interfaces.Position + 40.0 + 0.0 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 6 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype53 + + + + se.sics.cooja.interfaces.Position + 50.0 + 0.0 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 7 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype53 + + + + se.sics.cooja.interfaces.Position + 60.0 + 0.0 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 8 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype53 + + + + se.sics.cooja.interfaces.Position + 70.0 + 0.0 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 9 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype53 + + + + se.sics.cooja.interfaces.Position + 79.93950307524713 + -0.043451055913349 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 10 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype53 + + + + se.sics.cooja.interfaces.Position + 90.0 + 0.0 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 11 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype53 + + + + se.sics.cooja.interfaces.Position + 299.830399237567 + 0.21169609213234786 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 12 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype191 + + + + se.sics.cooja.interfaces.Position + 100.0 + 0.0 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 13 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype53 + + + + se.sics.cooja.interfaces.Position + 110.0 + 0.0 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 14 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype53 + + + + se.sics.cooja.interfaces.Position + 120.0 + 0.0 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 15 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype53 + + + + se.sics.cooja.interfaces.Position + 130.0 + 0.0 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 16 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype53 + + + + se.sics.cooja.interfaces.Position + 140.0 + 0.0 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 17 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype53 + + + + se.sics.cooja.interfaces.Position + 150.0 + 0.0 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 18 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype53 + + + + se.sics.cooja.interfaces.Position + 160.0 + 0.0 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 19 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype53 + + + + se.sics.cooja.interfaces.Position + 170.0 + 0.0 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 20 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype53 + + + + se.sics.cooja.interfaces.Position + 180.0 + 0.0 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 21 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype53 + + + + se.sics.cooja.interfaces.Position + 190.0 + 0.0 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 22 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype53 + + + + se.sics.cooja.interfaces.Position + 200.0 + 0.0 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 23 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype53 + + + + se.sics.cooja.interfaces.Position + 210.0 + 0.0 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 24 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype53 + + + + se.sics.cooja.interfaces.Position + 220.0 + 0.0 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 25 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype53 + + + + se.sics.cooja.interfaces.Position + 230.0 + 0.0 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 26 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype53 + + + + se.sics.cooja.interfaces.Position + 240.0 + 0.0 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 27 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype53 + + + + se.sics.cooja.interfaces.Position + 250.0 + 0.0 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 28 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype53 + + + + se.sics.cooja.interfaces.Position + 260.0 + 0.0 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 29 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype53 + + + + se.sics.cooja.interfaces.Position + 270.0 + 0.0 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 30 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype53 + + + + se.sics.cooja.interfaces.Position + 280.0 + 0.0 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 31 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype53 + + + + se.sics.cooja.interfaces.Position + 290.0 + 0.0 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 32 + + + se.sics.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype53 + + + + se.sics.cooja.plugins.SimControl + 280 + 1 + 160 + 400 + 0 + + + se.sics.cooja.plugins.Visualizer + + true + se.sics.cooja.plugins.skins.IDVisualizerSkin + se.sics.cooja.plugins.skins.GridVisualizerSkin + se.sics.cooja.plugins.skins.TrafficVisualizerSkin + se.sics.cooja.plugins.skins.UDGMVisualizerSkin + se.sics.cooja.plugins.skins.MoteTypeVisualizerSkin + 1.1837122130192945 0.0 0.0 1.1837122130192945 27.087094588040927 150.74941275029448 + + 400 + 2 + 400 + 1 + 1 + + + se.sics.cooja.plugins.LogListener + + + + + + 1200 + 3 + 240 + 400 + 160 + + + se.sics.cooja.plugins.Notes + + Enter notes here + true + + 920 + 4 + 160 + 680 + 0 + + + se.sics.cooja.plugins.ScriptRunner + + + true + + 600 + 0 + 700 + 843 + 77 + + + From 38a0c867f276404d12477cfd277e99d0466b59a9 Mon Sep 17 00:00:00 2001 From: Adam Dunkels Date: Sat, 5 Oct 2013 18:04:08 +0200 Subject: [PATCH 33/92] Don't wait for a specific packet (which may not arrive) - instead, wait for any packet to arrive. --- regression-tests/11-ipv6/17-cooja-multicast-11-hops.csc | 2 +- regression-tests/11-ipv6/18-cooja-multicast-31-hops.csc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/regression-tests/11-ipv6/17-cooja-multicast-11-hops.csc b/regression-tests/11-ipv6/17-cooja-multicast-11-hops.csc index ec01dd722..b98f77678 100644 --- a/regression-tests/11-ipv6/17-cooja-multicast-11-hops.csc +++ b/regression-tests/11-ipv6/17-cooja-multicast-11-hops.csc @@ -352,7 +352,7 @@ true diff --git a/regression-tests/11-ipv6/18-cooja-multicast-31-hops.csc b/regression-tests/11-ipv6/18-cooja-multicast-31-hops.csc index 89626ddb6..f65f929cb 100644 --- a/regression-tests/11-ipv6/18-cooja-multicast-31-hops.csc +++ b/regression-tests/11-ipv6/18-cooja-multicast-31-hops.csc @@ -692,7 +692,7 @@ true From 7fb99ed7c2637d88ad8751e26cc509b905b68508 Mon Sep 17 00:00:00 2001 From: George Oikonomou Date: Thu, 20 Feb 2014 15:52:34 +0000 Subject: [PATCH 34/92] Point to the correct trickle param --- core/net/ipv6/multicast/roll-tm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/net/ipv6/multicast/roll-tm.c b/core/net/ipv6/multicast/roll-tm.c index 37f14f457..75ce897ed 100644 --- a/core/net/ipv6/multicast/roll-tm.c +++ b/core/net/ipv6/multicast/roll-tm.c @@ -1270,6 +1270,9 @@ roll_tm_icmp_input() PRINTF("Check %u, Seed L: %u, This L: %u Min L: %d\n", locmpptr->seq_val, SLIDING_WINDOW_IS_LISTED(locswptr), MCAST_PACKET_IS_LISTED(locmpptr), locswptr->min_listed); + + /* Point to the sliding window's trickle param */ + loctpptr = &t[SLIDING_WINDOW_GET_M(locswptr)]; if(!SLIDING_WINDOW_IS_LISTED(locswptr)) { /* If a buffered packet's Seed ID was not listed */ PRINTF("ROLL TM: Inconsistency - Seed ID "); From 775928fa3fc435b79e629dced4663d5af0c797c0 Mon Sep 17 00:00:00 2001 From: George Oikonomou Date: Thu, 20 Feb 2014 15:53:34 +0000 Subject: [PATCH 35/92] Improve sliding window inclusion in ICMPv6 messages Don't include a sliding window in the ICMPv6 datagram unless the window has at least one active datagram associated with it --- core/net/ipv6/multicast/roll-tm.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/core/net/ipv6/multicast/roll-tm.c b/core/net/ipv6/multicast/roll-tm.c index 75ce897ed..715032936 100644 --- a/core/net/ipv6/multicast/roll-tm.c +++ b/core/net/ipv6/multicast/roll-tm.c @@ -826,20 +826,18 @@ icmp_output() if(SLIDING_WINDOW_GET_M(iterswptr)) { sl->flags |= SEQUENCE_LIST_M_BIT; } - sl->seq_len = iterswptr->count; seed_id_cpy(&sl->seed_id, &iterswptr->seed_id); - PRINTF("ROLL TM: ICMPv6 Out - Seq. F=0x%02x, L=%u, Seed ID=", sl->flags, - sl->seq_len); + PRINTF("ROLL TM: ICMPv6 Out - Seq. F=0x%02x, Seed ID=", sl->flags); PRINT_SEED(&sl->seed_id); buffer = (uint8_t *)sl + sizeof(struct sequence_list_header); - payload_len += sizeof(struct sequence_list_header); for(locmpptr = &buffered_msgs[ROLL_TM_BUFF_NUM - 1]; locmpptr >= buffered_msgs; locmpptr--) { if(MCAST_PACKET_IS_USED(locmpptr)) { if(locmpptr->sw == iterswptr) { + sl->seq_len++; PRINTF(", %u", locmpptr->seq_val); *buffer = (uint8_t)(locmpptr->seq_val >> 8); buffer++; @@ -848,9 +846,13 @@ icmp_output() } } } - PRINTF("\n"); - payload_len += sl->seq_len * 2; - sl = (struct sequence_list_header *)buffer; + PRINTF(", Len=%u\n", sl->seq_len); + + /* Scrap the entire window if it has no content */ + if(sl->seq_len > 0) { + payload_len += sizeof(struct sequence_list_header) + sl->seq_len * 2; + sl = (struct sequence_list_header *)buffer; + } } } From 9f4cdab1fb28191c9ef9fd5f3880cae126fa75dc Mon Sep 17 00:00:00 2001 From: George Oikonomou Date: Thu, 20 Feb 2014 15:55:12 +0000 Subject: [PATCH 36/92] Don't advertise datagrams older than Tactive --- core/net/ipv6/multicast/roll-tm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/net/ipv6/multicast/roll-tm.c b/core/net/ipv6/multicast/roll-tm.c index 715032936..e8aa863c0 100644 --- a/core/net/ipv6/multicast/roll-tm.c +++ b/core/net/ipv6/multicast/roll-tm.c @@ -835,7 +835,8 @@ icmp_output() for(locmpptr = &buffered_msgs[ROLL_TM_BUFF_NUM - 1]; locmpptr >= buffered_msgs; locmpptr--) { - if(MCAST_PACKET_IS_USED(locmpptr)) { + if(MCAST_PACKET_IS_USED(locmpptr) && + locmpptr->active < TRICKLE_ACTIVE((&t[SLIDING_WINDOW_GET_M(iterswptr)]))) { if(locmpptr->sw == iterswptr) { sl->seq_len++; PRINTF(", %u", locmpptr->seq_val); From 54b55e96c4eeca71d7eca48b4098a6a6a087b5a9 Mon Sep 17 00:00:00 2001 From: George Oikonomou Date: Thu, 20 Feb 2014 15:48:21 +0000 Subject: [PATCH 37/92] Check Tactive irrespective of suppression --- core/net/ipv6/multicast/roll-tm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/net/ipv6/multicast/roll-tm.c b/core/net/ipv6/multicast/roll-tm.c index e8aa863c0..d41b065d2 100644 --- a/core/net/ipv6/multicast/roll-tm.c +++ b/core/net/ipv6/multicast/roll-tm.c @@ -618,9 +618,9 @@ handle_timer(void *ptr) MCAST_PACKET_FREE(locmpptr); } else if(MCAST_PACKET_TTL(locmpptr) > 0) { /* Handle multicast transmissions */ - if((SUPPRESSION_ENABLED(param) && MCAST_PACKET_MUST_SEND(locmpptr)) || - (SUPPRESSION_DISABLED(param) && - locmpptr->active < TRICKLE_ACTIVE(param))) { + if(locmpptr->active < TRICKLE_ACTIVE(param) && + ((SUPPRESSION_ENABLED(param) && MCAST_PACKET_MUST_SEND(locmpptr)) || + SUPPRESSION_DISABLED(param))) { PRINTF("ROLL TM: M=%u Periodic - Sending packet from Seed ", m); PRINT_SEED(&locmpptr->sw->seed_id); PRINTF(" seq %u\n", locmpptr->seq_val); From cc41efaadd7cba5d79f5256ff1b783a9a6c6424a Mon Sep 17 00:00:00 2001 From: George Oikonomou Date: Mon, 24 Feb 2014 12:59:46 +0000 Subject: [PATCH 38/92] Update regression sims to org.contikios --- .../11-ipv6/17-cooja-multicast-11-hops.csc | 196 +++++------ .../11-ipv6/18-cooja-multicast-31-hops.csc | 316 +++++++++--------- 2 files changed, 256 insertions(+), 256 deletions(-) diff --git a/regression-tests/11-ipv6/17-cooja-multicast-11-hops.csc b/regression-tests/11-ipv6/17-cooja-multicast-11-hops.csc index b98f77678..da90cb72b 100644 --- a/regression-tests/11-ipv6/17-cooja-multicast-11-hops.csc +++ b/regression-tests/11-ipv6/17-cooja-multicast-11-hops.csc @@ -11,7 +11,7 @@ 123456 1000000 - se.sics.cooja.radiomediums.UDGM + org.contikios.cooja.radiomediums.UDGM 15.0 0.0 1.0 @@ -21,284 +21,284 @@ 40000 - se.sics.cooja.contikimote.ContikiMoteType + org.contikios.cooja.contikimote.ContikiMoteType mtype612 Root/sender [CONTIKI_DIR]/examples/ipv6/multicast/root.c make root.cooja TARGET=cooja - se.sics.cooja.interfaces.Position - se.sics.cooja.interfaces.Battery - se.sics.cooja.contikimote.interfaces.ContikiVib - se.sics.cooja.contikimote.interfaces.ContikiMoteID - se.sics.cooja.contikimote.interfaces.ContikiRS232 - se.sics.cooja.contikimote.interfaces.ContikiBeeper - se.sics.cooja.interfaces.RimeAddress - se.sics.cooja.contikimote.interfaces.ContikiIPAddress - se.sics.cooja.contikimote.interfaces.ContikiRadio - se.sics.cooja.contikimote.interfaces.ContikiButton - se.sics.cooja.contikimote.interfaces.ContikiPIR - se.sics.cooja.contikimote.interfaces.ContikiClock - se.sics.cooja.contikimote.interfaces.ContikiLED - se.sics.cooja.contikimote.interfaces.ContikiCFS - se.sics.cooja.interfaces.Mote2MoteRelations - se.sics.cooja.interfaces.MoteAttributes + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes false - se.sics.cooja.contikimote.ContikiMoteType + org.contikios.cooja.contikimote.ContikiMoteType mtype890 Intermediate [CONTIKI_DIR]/examples/ipv6/multicast/intermediate.c make intermediate.cooja TARGET=cooja - se.sics.cooja.interfaces.Position - se.sics.cooja.interfaces.Battery - se.sics.cooja.contikimote.interfaces.ContikiVib - se.sics.cooja.contikimote.interfaces.ContikiMoteID - se.sics.cooja.contikimote.interfaces.ContikiRS232 - se.sics.cooja.contikimote.interfaces.ContikiBeeper - se.sics.cooja.interfaces.RimeAddress - se.sics.cooja.contikimote.interfaces.ContikiIPAddress - se.sics.cooja.contikimote.interfaces.ContikiRadio - se.sics.cooja.contikimote.interfaces.ContikiButton - se.sics.cooja.contikimote.interfaces.ContikiPIR - se.sics.cooja.contikimote.interfaces.ContikiClock - se.sics.cooja.contikimote.interfaces.ContikiLED - se.sics.cooja.contikimote.interfaces.ContikiCFS - se.sics.cooja.interfaces.Mote2MoteRelations - se.sics.cooja.interfaces.MoteAttributes + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes false - se.sics.cooja.contikimote.ContikiMoteType + org.contikios.cooja.contikimote.ContikiMoteType mtype956 Receiver [CONTIKI_DIR]/examples/ipv6/multicast/sink.c make sink.cooja TARGET=cooja - se.sics.cooja.interfaces.Position - se.sics.cooja.interfaces.Battery - se.sics.cooja.contikimote.interfaces.ContikiVib - se.sics.cooja.contikimote.interfaces.ContikiMoteID - se.sics.cooja.contikimote.interfaces.ContikiRS232 - se.sics.cooja.contikimote.interfaces.ContikiBeeper - se.sics.cooja.interfaces.RimeAddress - se.sics.cooja.contikimote.interfaces.ContikiIPAddress - se.sics.cooja.contikimote.interfaces.ContikiRadio - se.sics.cooja.contikimote.interfaces.ContikiButton - se.sics.cooja.contikimote.interfaces.ContikiPIR - se.sics.cooja.contikimote.interfaces.ContikiClock - se.sics.cooja.contikimote.interfaces.ContikiLED - se.sics.cooja.contikimote.interfaces.ContikiCFS - se.sics.cooja.interfaces.Mote2MoteRelations - se.sics.cooja.interfaces.MoteAttributes + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes false - se.sics.cooja.interfaces.Position + org.contikios.cooja.interfaces.Position -7.983976888750106 0.37523218201044733 0.0 - se.sics.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiMoteID 1 - se.sics.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiRadio 250.0 mtype612 - se.sics.cooja.interfaces.Position + org.contikios.cooja.interfaces.Position 0.0 0.0 0.0 - se.sics.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiMoteID 2 - se.sics.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiRadio 250.0 mtype890 - se.sics.cooja.interfaces.Position + org.contikios.cooja.interfaces.Position 10.0 0.0 0.0 - se.sics.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiMoteID 3 - se.sics.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiRadio 250.0 mtype890 - se.sics.cooja.interfaces.Position + org.contikios.cooja.interfaces.Position 20.0 0.0 0.0 - se.sics.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiMoteID 4 - se.sics.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiRadio 250.0 mtype890 - se.sics.cooja.interfaces.Position + org.contikios.cooja.interfaces.Position 30.0 0.0 0.0 - se.sics.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiMoteID 5 - se.sics.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiRadio 250.0 mtype890 - se.sics.cooja.interfaces.Position + org.contikios.cooja.interfaces.Position 40.0 0.0 0.0 - se.sics.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiMoteID 6 - se.sics.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiRadio 250.0 mtype890 - se.sics.cooja.interfaces.Position + org.contikios.cooja.interfaces.Position 50.0 0.0 0.0 - se.sics.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiMoteID 7 - se.sics.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiRadio 250.0 mtype890 - se.sics.cooja.interfaces.Position + org.contikios.cooja.interfaces.Position 60.0 0.0 0.0 - se.sics.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiMoteID 8 - se.sics.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiRadio 250.0 mtype890 - se.sics.cooja.interfaces.Position + org.contikios.cooja.interfaces.Position 70.0 0.0 0.0 - se.sics.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiMoteID 9 - se.sics.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiRadio 250.0 mtype890 - se.sics.cooja.interfaces.Position + org.contikios.cooja.interfaces.Position 79.93950307524713 -0.043451055913349 0.0 - se.sics.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiMoteID 10 - se.sics.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiRadio 250.0 mtype890 - se.sics.cooja.interfaces.Position + org.contikios.cooja.interfaces.Position 90.0 0.0 0.0 - se.sics.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiMoteID 11 - se.sics.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiRadio 250.0 mtype890 - se.sics.cooja.interfaces.Position + org.contikios.cooja.interfaces.Position 99.61761525766555 0.37523218201044733 0.0 - se.sics.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiMoteID 12 - se.sics.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiRadio 250.0 mtype956 - se.sics.cooja.plugins.SimControl + org.contikios.cooja.plugins.SimControl 280 1 160 @@ -306,14 +306,14 @@ 0 - se.sics.cooja.plugins.Visualizer + org.contikios.cooja.plugins.Visualizer true - se.sics.cooja.plugins.skins.IDVisualizerSkin - se.sics.cooja.plugins.skins.GridVisualizerSkin - se.sics.cooja.plugins.skins.TrafficVisualizerSkin - se.sics.cooja.plugins.skins.UDGMVisualizerSkin - se.sics.cooja.plugins.skins.MoteTypeVisualizerSkin + org.contikios.cooja.plugins.skins.IDVisualizerSkin + org.contikios.cooja.plugins.skins.GridVisualizerSkin + org.contikios.cooja.plugins.skins.TrafficVisualizerSkin + org.contikios.cooja.plugins.skins.UDGMVisualizerSkin + org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin 2.388440494916608 0.0 0.0 2.388440494916608 109.06925371156906 149.10378026149033 400 @@ -323,7 +323,7 @@ 1 - se.sics.cooja.plugins.LogListener + org.contikios.cooja.plugins.LogListener @@ -336,7 +336,7 @@ 160 - se.sics.cooja.plugins.Notes + org.contikios.cooja.plugins.Notes Enter notes here true @@ -348,7 +348,7 @@ 0 - se.sics.cooja.plugins.ScriptRunner + org.contikios.cooja.plugins.ScriptRunner