From 14db3382af50cefc02069f9c2e178284ae9257da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Fri, 15 Nov 2013 19:05:52 +0100 Subject: [PATCH 1/3] csma: Initialize sequence number with random value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to IEEE 802.15.4 (§5.1.6.1, §6.4.2), the MAC sequence numbers should be initialized to random values. This was already the case in framer-802154.c:create(), but not in csma.c:send_packet(), sometimes causing false detections of duplicate MAC-layer packets in other devices when a device was restarted too quickly. This patch decreases the probability of such an event. Signed-off-by: Benoît Thébaudeau --- core/net/mac/csma.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/core/net/mac/csma.c b/core/net/mac/csma.c index 66528e542..b75a812ca 100644 --- a/core/net/mac/csma.c +++ b/core/net/mac/csma.c @@ -306,9 +306,16 @@ send_packet(mac_callback_t sent, void *ptr) { struct rdc_buf_list *q; struct neighbor_queue *n; + static uint8_t initialized = 0; static uint16_t seqno; const rimeaddr_t *addr = packetbuf_addr(PACKETBUF_ADDR_RECEIVER); + if(!initialized) { + initialized = 1; + /* Initialize the sequence number to a random value as per 802.15.4. */ + seqno = random_rand(); + } + if(seqno == 0) { /* PACKETBUF_ATTR_MAC_SEQNO cannot be zero, due to a pecuilarity in framer-802154.c. */ From 477a4a71785b4aaa7264b4b06628b9824d386f96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Fri, 15 Nov 2013 19:21:41 +0100 Subject: [PATCH 2/3] rdc: duplicate packets: Factor out detection code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The code detecting duplicate packets in the RDC layer had been copied into most RDC implementations. Factor it out into a new mac-sequence module in order to have a single instance of this code. Signed-off-by: Benoît Thébaudeau --- core/net/mac/Makefile.mac | 2 +- core/net/mac/contikimac.c | 39 +++------------ core/net/mac/mac-sequence.c | 97 +++++++++++++++++++++++++++++++++++++ core/net/mac/mac-sequence.h | 66 +++++++++++++++++++++++++ core/net/mac/nullrdc.c | 45 ++++------------- core/net/mac/xmac.c | 33 +++---------- 6 files changed, 186 insertions(+), 96 deletions(-) create mode 100644 core/net/mac/mac-sequence.c create mode 100644 core/net/mac/mac-sequence.h diff --git a/core/net/mac/Makefile.mac b/core/net/mac/Makefile.mac index 91cff524e..1d80a7fa3 100644 --- a/core/net/mac/Makefile.mac +++ b/core/net/mac/Makefile.mac @@ -1,2 +1,2 @@ CONTIKI_SOURCEFILES += cxmac.c xmac.c nullmac.c lpp.c frame802154.c sicslowmac.c nullrdc.c nullrdc-noframer.c mac.c -CONTIKI_SOURCEFILES += framer-nullmac.c framer-802154.c csma.c contikimac.c phase.c +CONTIKI_SOURCEFILES += framer-nullmac.c framer-802154.c csma.c contikimac.c phase.c mac-sequence.c diff --git a/core/net/mac/contikimac.c b/core/net/mac/contikimac.c index 66faafa5f..626a9daca 100644 --- a/core/net/mac/contikimac.c +++ b/core/net/mac/contikimac.c @@ -44,6 +44,7 @@ #include "dev/radio.h" #include "dev/watchdog.h" #include "lib/random.h" +#include "net/mac/mac-sequence.h" #include "net/mac/contikimac.h" #include "net/netstack.h" #include "net/rime.h" @@ -263,18 +264,6 @@ static struct compower_activity current_packet; #define MIN(a, b) ((a) < (b)? (a) : (b)) #endif /* MIN */ -struct seqno { - rimeaddr_t sender; - uint8_t seqno; -}; - -#ifdef NETSTACK_CONF_MAC_SEQNO_HISTORY -#define MAX_SEQNOS NETSTACK_CONF_MAC_SEQNO_HISTORY -#else /* NETSTACK_CONF_MAC_SEQNO_HISTORY */ -#define MAX_SEQNOS 16 -#endif /* NETSTACK_CONF_MAC_SEQNO_HISTORY */ -static struct seqno received_seqnos[MAX_SEQNOS]; - #if CONTIKIMAC_CONF_BROADCAST_RATE_LIMIT static struct timer broadcast_rate_timer; static int broadcast_rate_counter; @@ -980,27 +969,13 @@ input_packet(void) ctimer_stop(&ct); } - /* Check for duplicate packet by comparing the sequence number - of the incoming packet with the last few ones we saw. */ - { - int i; - for(i = 0; i < MAX_SEQNOS; ++i) { - if(packetbuf_attr(PACKETBUF_ATTR_PACKET_ID) == received_seqnos[i].seqno && - rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_SENDER), - &received_seqnos[i].sender)) { - /* Drop the packet. */ - /* printf("Drop duplicate ContikiMAC layer packet\n");*/ - return; - } - } - for(i = MAX_SEQNOS - 1; i > 0; --i) { - memcpy(&received_seqnos[i], &received_seqnos[i - 1], - sizeof(struct seqno)); - } - received_seqnos[0].seqno = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID); - rimeaddr_copy(&received_seqnos[0].sender, - packetbuf_addr(PACKETBUF_ADDR_SENDER)); + /* Check for duplicate packet. */ + if(mac_sequence_is_duplicate()) { + /* Drop the packet. */ + /* printf("Drop duplicate ContikiMAC layer packet\n");*/ + return; } + mac_sequence_register_seqno(); #if CONTIKIMAC_CONF_COMPOWER /* Accumulate the power consumption for the packet reception. */ diff --git a/core/net/mac/mac-sequence.c b/core/net/mac/mac-sequence.c new file mode 100644 index 000000000..5b6502aa6 --- /dev/null +++ b/core/net/mac/mac-sequence.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2010, Swedish Institute of Computer Science. + * All rights reserved. + * + * 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 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 + * MAC sequence numbers management + * \author + * Adam Dunkels + * Benoît Thébaudeau + */ + +#include + +#include "contiki-net.h" +#include "net/mac/mac-sequence.h" +#include "net/packetbuf.h" +#include "net/rime.h" + +struct seqno { + rimeaddr_t sender; + uint8_t seqno; +}; + +#ifdef NETSTACK_CONF_MAC_SEQNO_HISTORY +#define MAX_SEQNOS NETSTACK_CONF_MAC_SEQNO_HISTORY +#else /* NETSTACK_CONF_MAC_SEQNO_HISTORY */ +#define MAX_SEQNOS 16 +#endif /* NETSTACK_CONF_MAC_SEQNO_HISTORY */ +static struct seqno received_seqnos[MAX_SEQNOS]; + +/*---------------------------------------------------------------------------*/ +int +mac_sequence_is_duplicate(void) +{ + int i; + + /* + * Check for duplicate packet by comparing the sequence number of the incoming + * packet with the last few ones we saw. + */ + for(i = 0; i < MAX_SEQNOS; ++i) { + if(packetbuf_attr(PACKETBUF_ATTR_PACKET_ID) == received_seqnos[i].seqno && + rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_SENDER), + &received_seqnos[i].sender)) { + /* Duplicate packet. */ + return 1; + } + } + return 0; +} +/*---------------------------------------------------------------------------*/ +void +mac_sequence_register_seqno(void) +{ + int i; + + for(i = MAX_SEQNOS - 1; i > 0; --i) { + memcpy(&received_seqnos[i], &received_seqnos[i - 1], sizeof(struct seqno)); + } + received_seqnos[0].seqno = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID); + rimeaddr_copy(&received_seqnos[0].sender, + packetbuf_addr(PACKETBUF_ADDR_SENDER)); +} +/*---------------------------------------------------------------------------*/ diff --git a/core/net/mac/mac-sequence.h b/core/net/mac/mac-sequence.h new file mode 100644 index 000000000..455160c2d --- /dev/null +++ b/core/net/mac/mac-sequence.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2010, Swedish Institute of Computer Science. + * All rights reserved. + * + * 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 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 MAC sequence numbers management + * \author + * Adam Dunkels + * Benoît Thébaudeau + */ + +#ifndef MAC_SEQUENCE_H +#define MAC_SEQUENCE_H + +/** + * \brief Tell whether the packetbuf is a duplicate packet + * \return Non-zero if the packetbuf is a duplicate packet, zero otherwise + * + * This function is used to check for duplicate packet by comparing + * the sequence number of the incoming packet with the last few ones + * we saw, filtering with the Rime address. + */ +int mac_sequence_is_duplicate(void); + +/** + * \brief Register the sequence number of the packetbuf + * + * This function is used to add the sequence number of the incoming + * packet to the history. + */ +void mac_sequence_register_seqno(void); + +#endif /* MAC_SEQUENCE_H */ diff --git a/core/net/mac/nullrdc.c b/core/net/mac/nullrdc.c index 6d4117953..d4ffd6833 100644 --- a/core/net/mac/nullrdc.c +++ b/core/net/mac/nullrdc.c @@ -38,6 +38,7 @@ * Niclas Finne */ +#include "net/mac/mac-sequence.h" #include "net/mac/nullrdc.h" #include "net/packetbuf.h" #include "net/queuebuf.h" @@ -107,21 +108,6 @@ #define ACK_LEN 3 -#if NULLRDC_802154_AUTOACK || NULLRDC_802154_AUTOACK_HW -struct seqno { - rimeaddr_t sender; - uint8_t seqno; -}; - -#ifdef NETSTACK_CONF_MAC_SEQNO_HISTORY -#define MAX_SEQNOS NETSTACK_CONF_MAC_SEQNO_HISTORY -#else /* NETSTACK_CONF_MAC_SEQNO_HISTORY */ -#define MAX_SEQNOS 8 -#endif /* NETSTACK_CONF_MAC_SEQNO_HISTORY */ - -static struct seqno received_seqnos[MAX_SEQNOS]; -#endif /* NULLRDC_802154_AUTOACK || NULLRDC_802154_AUTOACK_HW */ - /*---------------------------------------------------------------------------*/ static int send_one_packet(mac_callback_t sent, void *ptr) @@ -312,27 +298,14 @@ packet_input(void) int duplicate = 0; #if NULLRDC_802154_AUTOACK || NULLRDC_802154_AUTOACK_HW - /* Check for duplicate packet by comparing the sequence number - of the incoming packet with the last few ones we saw. */ - int i; - for(i = 0; i < MAX_SEQNOS; ++i) { - if(packetbuf_attr(PACKETBUF_ATTR_PACKET_ID) == received_seqnos[i].seqno && - rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_SENDER), - &received_seqnos[i].sender)) { - /* Drop the packet. */ - PRINTF("nullrdc: drop duplicate link layer packet %u\n", - packetbuf_attr(PACKETBUF_ATTR_PACKET_ID)); - duplicate = 1; - } - } - if(!duplicate) { - for(i = MAX_SEQNOS - 1; i > 0; --i) { - memcpy(&received_seqnos[i], &received_seqnos[i - 1], - sizeof(struct seqno)); - } - received_seqnos[0].seqno = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID); - rimeaddr_copy(&received_seqnos[0].sender, - packetbuf_addr(PACKETBUF_ADDR_SENDER)); + /* Check for duplicate packet. */ + duplicate = mac_sequence_is_duplicate(); + if(duplicate) { + /* Drop the packet. */ + PRINTF("nullrdc: drop duplicate link layer packet %u\n", + packetbuf_attr(PACKETBUF_ATTR_PACKET_ID)); + } else { + mac_sequence_register_seqno(); } #endif /* NULLRDC_802154_AUTOACK */ diff --git a/core/net/mac/xmac.c b/core/net/mac/xmac.c index 71027ad69..94dab9734 100644 --- a/core/net/mac/xmac.c +++ b/core/net/mac/xmac.c @@ -44,6 +44,7 @@ #include "dev/watchdog.h" #include "lib/random.h" #include "net/netstack.h" +#include "net/mac/mac-sequence.h" #include "net/mac/xmac.h" #include "net/rime.h" #include "net/rime/timesynch.h" @@ -219,14 +220,6 @@ static rtimer_clock_t stream_until; #define MIN(a, b) ((a) < (b)? (a) : (b)) #endif /* MIN */ -struct seqno { - rimeaddr_t sender; - uint8_t seqno; -}; - -#define MAX_SEQNOS 8 -static struct seqno received_seqnos[MAX_SEQNOS]; - /*---------------------------------------------------------------------------*/ static void @@ -807,26 +800,12 @@ input_packet(void) asleep. */ off(); - /* Check for duplicate packet by comparing the sequence number - of the incoming packet with the last few ones we saw. */ - { - int i; - for(i = 0; i < MAX_SEQNOS; ++i) { - if(packetbuf_attr(PACKETBUF_ATTR_PACKET_ID) == received_seqnos[i].seqno && - rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_SENDER), - &received_seqnos[i].sender)) { - /* Drop the packet. */ - return; - } - } - for(i = MAX_SEQNOS - 1; i > 0; --i) { - memcpy(&received_seqnos[i], &received_seqnos[i - 1], - sizeof(struct seqno)); - } - received_seqnos[0].seqno = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID); - rimeaddr_copy(&received_seqnos[0].sender, - packetbuf_addr(PACKETBUF_ADDR_SENDER)); + /* Check for duplicate packet. */ + if(mac_sequence_is_duplicate()) { + /* Drop the packet. */ + return; } + mac_sequence_register_seqno(); #if XMAC_CONF_COMPOWER /* Accumulate the power consumption for the packet reception. */ From 4deba89f81105114a08383b0b2a65cd6f8bb045b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Fri, 15 Nov 2013 19:31:02 +0100 Subject: [PATCH 3/3] rdc: duplicate packets: Keep only the last sequence number for each address MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to IEEE 802.15.4e (§6.4.3.9), in order to detect duplicate received MAC-layer frames, only the most recently received frame's sequence number needs to be stored for each unique device address. Doing so limits the possible false duplicate packet detections to a single sequence number. This also allows to keep the last sequence number of more device addresses for the same value of MAX_SEQNOS. Signed-off-by: Benoît Thébaudeau --- core/net/mac/mac-sequence.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/core/net/mac/mac-sequence.c b/core/net/mac/mac-sequence.c index 5b6502aa6..be646607f 100644 --- a/core/net/mac/mac-sequence.c +++ b/core/net/mac/mac-sequence.c @@ -72,11 +72,13 @@ mac_sequence_is_duplicate(void) * packet with the last few ones we saw. */ for(i = 0; i < MAX_SEQNOS; ++i) { - if(packetbuf_attr(PACKETBUF_ATTR_PACKET_ID) == received_seqnos[i].seqno && - rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_SENDER), + if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_SENDER), &received_seqnos[i].sender)) { - /* Duplicate packet. */ - return 1; + if(packetbuf_attr(PACKETBUF_ATTR_PACKET_ID) == received_seqnos[i].seqno) { + /* Duplicate packet. */ + return 1; + } + break; } } return 0; @@ -85,10 +87,20 @@ mac_sequence_is_duplicate(void) void mac_sequence_register_seqno(void) { - int i; + int i, j; - for(i = MAX_SEQNOS - 1; i > 0; --i) { - memcpy(&received_seqnos[i], &received_seqnos[i - 1], sizeof(struct seqno)); + /* Locate possible previous sequence number for this address. */ + for(i = 0; i < MAX_SEQNOS; ++i) { + if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_SENDER), + &received_seqnos[i].sender)) { + i++; + break; + } + } + + /* Keep the last sequence number for each address as per 802.15.4e. */ + for(j = i - 1; j > 0; --j) { + memcpy(&received_seqnos[j], &received_seqnos[j - 1], sizeof(struct seqno)); } received_seqnos[0].seqno = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID); rimeaddr_copy(&received_seqnos[0].sender,