From 880e69f7703e2d046970e05cf8287658e83196da Mon Sep 17 00:00:00 2001 From: Simon Duquennoy Date: Wed, 17 May 2017 21:47:48 +0200 Subject: [PATCH] Merging csma and nullrdc --- core/net/mac/csma-output.c | 584 ++++++++++++++++++ core/net/mac/{nullrdc.h => csma-output.h} | 26 +- core/net/mac/csma.c | 448 ++------------ core/net/mac/csma.h | 43 +- core/net/mac/nullrdc.c | 312 ---------- drivers/cpu/cc26xx-cc13xx/rf-core/rf-ble.c | 2 +- drivers/dev/cc1200/cc1200-conf.h | 2 +- drivers/dev/cc1200/cc1200.c | 6 +- drivers/platform/cc2538dk/contiki-conf.h | 6 +- drivers/platform/cooja/contiki-conf.h | 8 +- drivers/platform/jn516x/contiki-conf.h | 4 +- .../platform/openmote-cc2538/contiki-conf.h | 6 +- drivers/platform/srf06-cc26xx/contiki-conf.h | 16 +- drivers/platform/zoul/contiki-conf.h | 16 +- examples/ipv6/json-ws/README-COSM.md | 2 +- examples/ipv6/json-ws/project-conf.h | 4 +- examples/ipv6/multicast/project-conf.h | 2 +- examples/ipv6/rpl-udp/project-conf.h | 4 +- .../jn516x/rpl/common-conf.h | 4 +- .../03-compile-nxp-ports/Makefile | 2 +- .../08-ipv6/code-slip-radio/project-conf.h | 2 +- 21 files changed, 738 insertions(+), 761 deletions(-) create mode 100644 core/net/mac/csma-output.c rename core/net/mac/{nullrdc.h => csma-output.h} (76%) delete mode 100644 core/net/mac/nullrdc.c diff --git a/core/net/mac/csma-output.c b/core/net/mac/csma-output.c new file mode 100644 index 000000000..e224825ed --- /dev/null +++ b/core/net/mac/csma-output.c @@ -0,0 +1,584 @@ +/* + * Copyright (c) 2010, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +/** + * \file + * The 802.15.4 standard CSMA protocol (nonbeacon-enabled). + * Output functions. + * \author + * Adam Dunkels + * Simon Duquennoy + */ + +#include "net/mac/csma.h" +#include "net/packetbuf.h" +#include "net/queuebuf.h" +#include "dev/watchdog.h" +#include "sys/ctimer.h" +#include "sys/clock.h" +#include "lib/random.h" +#include "net/netstack.h" +#include "lib/list.h" +#include "lib/memb.h" + +#include + +#include + +#if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 +#include "lib/simEnvChange.h" +#include "sys/cooja_mt.h" +#endif /* CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 */ + +#define DEBUG 0 +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#else /* DEBUG */ +#define PRINTF(...) +#endif /* DEBUG */ + +/* Constants of the IEEE 802.15.4 standard */ + +/* macMinBE: Initial backoff exponent. Range 0--CSMA_MAX_BE */ +#ifdef CSMA_CONF_MIN_BE +#define CSMA_MIN_BE CSMA_CONF_MIN_BE +#else +#define CSMA_MIN_BE 0 +#endif + +/* macMaxBE: Maximum backoff exponent. Range 3--8 */ +#ifdef CSMA_CONF_MAX_BE +#define CSMA_MAX_BE CSMA_CONF_MAX_BE +#else +#define CSMA_MAX_BE 4 +#endif + +/* macMaxCSMABackoffs: Maximum number of backoffs in case of channel busy/collision. Range 0--5 */ +#ifdef CSMA_CONF_MAX_BACKOFF +#define CSMA_MAX_BACKOFF CSMA_CONF_MAX_BACKOFF +#else +#define CSMA_MAX_BACKOFF 5 +#endif + +/* macMaxFrameRetries: Maximum number of re-transmissions attampts. Range 0--7 */ +#ifdef CSMA_CONF_MAX_FRAME_RETRIES +#define CSMA_MAX_MAX_FRAME_RETRIES CSMA_CONF_MAX_FRAME_RETRIES +#else +#define CSMA_MAX_MAX_FRAME_RETRIES 7 +#endif + +/* Packet metadata */ +struct qbuf_metadata { + mac_callback_t sent; + void *cptr; + uint8_t max_transmissions; +}; + +/* Every neighbor has its own packet queue */ +struct neighbor_queue { + struct neighbor_queue *next; + linkaddr_t addr; + struct ctimer transmit_timer; + uint8_t transmissions; + uint8_t collisions; + LIST_STRUCT(packet_queue); +}; + +/* The maximum number of co-existing neighbor queues */ +#ifdef CSMA_CONF_MAX_NEIGHBOR_QUEUES +#define CSMA_MAX_NEIGHBOR_QUEUES CSMA_CONF_MAX_NEIGHBOR_QUEUES +#else +#define CSMA_MAX_NEIGHBOR_QUEUES 2 +#endif /* CSMA_CONF_MAX_NEIGHBOR_QUEUES */ + +/* The maximum number of pending packet per neighbor */ +#ifdef CSMA_CONF_MAX_PACKET_PER_NEIGHBOR +#define CSMA_MAX_PACKET_PER_NEIGHBOR CSMA_CONF_MAX_PACKET_PER_NEIGHBOR +#else +#define CSMA_MAX_PACKET_PER_NEIGHBOR MAX_QUEUED_PACKETS +#endif /* CSMA_CONF_MAX_PACKET_PER_NEIGHBOR */ + +#define MAX_QUEUED_PACKETS QUEUEBUF_NUM + +/* Neighbor packet queue */ +struct packet_queue { + struct packet_queue *next; + struct queuebuf *buf; + void *ptr; +}; + +MEMB(neighbor_memb, struct neighbor_queue, CSMA_MAX_NEIGHBOR_QUEUES); +MEMB(packet_memb, struct packet_queue, MAX_QUEUED_PACKETS); +MEMB(metadata_memb, struct qbuf_metadata, MAX_QUEUED_PACKETS); +LIST(neighbor_list); + +static void packet_sent(void *ptr, int status, int num_transmissions); +static void transmit_from_queue(void *ptr); +/*---------------------------------------------------------------------------*/ +static struct neighbor_queue * +neighbor_queue_from_addr(const linkaddr_t *addr) +{ + struct neighbor_queue *n = list_head(neighbor_list); + while(n != NULL) { + if(linkaddr_cmp(&n->addr, addr)) { + return n; + } + n = list_item_next(n); + } + return NULL; +} +/*---------------------------------------------------------------------------*/ +static clock_time_t +backoff_period(void) +{ + /* Use the default in IEEE 802.15.4: aUnitBackoffPeriod which is + * 20 symbols i.e. 320 usec. That is, 1/3125 second. */ + return MAX(CLOCK_SECOND / 3125, 1); +} +/*---------------------------------------------------------------------------*/ +static int +send_one_packet(mac_callback_t sent, void *ptr) +{ + int ret; + int last_sent_ok = 0; + + packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &linkaddr_node_addr); +#if CSMA_802154_AUTOACK || CSMA_802154_AUTOACK_HW + packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1); +#endif /* CSMA_802154_AUTOACK || CSMA_802154_AUTOACK_HW */ + + if(NETSTACK_FRAMER.create() < 0) { + /* Failed to allocate space for headers */ + PRINTF("csma: send failed, too large header\n"); + ret = MAC_TX_ERR_FATAL; + } else { +#if CSMA_802154_AUTOACK + int is_broadcast; + uint8_t dsn; + dsn = ((uint8_t *)packetbuf_hdrptr())[2] & 0xff; + + NETSTACK_RADIO.prepare(packetbuf_hdrptr(), packetbuf_totlen()); + + is_broadcast = packetbuf_holds_broadcast(); + + if(NETSTACK_RADIO.receiving_packet() || + (!is_broadcast && NETSTACK_RADIO.pending_packet())) { + + /* Currently receiving a packet over air or the radio has + already received a packet that needs to be read before + sending with auto ack. */ + ret = MAC_TX_COLLISION; + } else { + if(!is_broadcast) { + RIMESTATS_ADD(reliabletx); + } + + switch(NETSTACK_RADIO.transmit(packetbuf_totlen())) { + case RADIO_TX_OK: + if(is_broadcast) { + ret = MAC_TX_OK; + } else { + rtimer_clock_t wt; + + /* Check for ack */ + wt = RTIMER_NOW(); + watchdog_periodic(); + while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + CSMA_ACK_WAIT_TIME)) { +#if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 + simProcessRunValue = 1; + cooja_mt_yield(); +#endif /* CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 */ + } + + ret = MAC_TX_NOACK; + if(NETSTACK_RADIO.receiving_packet() || + NETSTACK_RADIO.pending_packet() || + NETSTACK_RADIO.channel_clear() == 0) { + int len; + uint8_t ackbuf[CSMA_ACK_LEN]; + + if(CSMA_AFTER_ACK_DETECTED_WAIT_TIME > 0) { + wt = RTIMER_NOW(); + watchdog_periodic(); + while(RTIMER_CLOCK_LT(RTIMER_NOW(), + wt + CSMA_AFTER_ACK_DETECTED_WAIT_TIME)) { +#if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 + simProcessRunValue = 1; + cooja_mt_yield(); +#endif /* CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 */ + } + } + + if(NETSTACK_RADIO.pending_packet()) { + len = NETSTACK_RADIO.read(ackbuf, CSMA_ACK_LEN); + if(len == CSMA_ACK_LEN && ackbuf[2] == dsn) { + /* Ack received */ + RIMESTATS_ADD(ackrx); + ret = MAC_TX_OK; + } else { + /* Not an ack or ack not for us: collision */ + ret = MAC_TX_COLLISION; + } + } + } else { + PRINTF("csma tx noack\n"); + } + } + break; + case RADIO_TX_COLLISION: + ret = MAC_TX_COLLISION; + break; + default: + ret = MAC_TX_ERR; + break; + } + } + +#else /* !CSMA_802154_AUTOACK */ + + switch(NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen())) { + case RADIO_TX_OK: + ret = MAC_TX_OK; + break; + case RADIO_TX_COLLISION: + ret = MAC_TX_COLLISION; + break; + case RADIO_TX_NOACK: + ret = MAC_TX_NOACK; + break; + default: + ret = MAC_TX_ERR; + break; + } + +#endif /* !CSMA_802154_AUTOACK */ + } + if(ret == MAC_TX_OK) { + last_sent_ok = 1; + } + mac_call_sent_callback(sent, ptr, ret, 1); + return last_sent_ok; +} +/*---------------------------------------------------------------------------*/ +static void +transmit_from_queue(void *ptr) +{ + struct neighbor_queue *n = ptr; + if(n) { + struct packet_queue *q = list_head(n->packet_queue); + if(q != NULL) { + PRINTF("csma: preparing number %d %p, queue len %d\n", n->transmissions, q, + list_length(n->packet_queue)); + /* Send first packet in the neighbor queue */ + queuebuf_to_packetbuf(q->buf); + send_one_packet(packet_sent, n); + } + } +} +/*---------------------------------------------------------------------------*/ +static void +schedule_transmission(struct neighbor_queue *n) +{ + clock_time_t delay; + int backoff_exponent; /* BE in IEEE 802.15.4 */ + + backoff_exponent = MIN(n->collisions, CSMA_MAX_BE); + + /* Compute max delay as per IEEE 802.15.4: 2^BE-1 backoff periods */ + delay = ((1 << backoff_exponent) - 1) * backoff_period(); + if(delay > 0) { + /* Pick a time for next transmission */ + delay = random_rand() % delay; + } + + PRINTF("csma: scheduling transmission in %u ticks, NB=%u, BE=%u\n", + (unsigned)delay, n->collisions, backoff_exponent); + ctimer_set(&n->transmit_timer, delay, transmit_from_queue, n); +} +/*---------------------------------------------------------------------------*/ +static void +free_packet(struct neighbor_queue *n, struct packet_queue *p, int status) +{ + if(p != NULL) { + /* Remove packet from queue and deallocate */ + list_remove(n->packet_queue, p); + + queuebuf_free(p->buf); + memb_free(&metadata_memb, p->ptr); + memb_free(&packet_memb, p); + PRINTF("csma: free_queued_packet, queue length %d, free packets %d\n", + list_length(n->packet_queue), memb_numfree(&packet_memb)); + if(list_head(n->packet_queue) != NULL) { + /* There is a next packet. We reset current tx information */ + n->transmissions = 0; + n->collisions = CSMA_MIN_BE; + /* Schedule next transmissions */ + schedule_transmission(n); + } else { + /* This was the last packet in the queue, we free the neighbor */ + ctimer_stop(&n->transmit_timer); + list_remove(neighbor_list, n); + memb_free(&neighbor_memb, n); + } + } +} +/*---------------------------------------------------------------------------*/ +static void +tx_done(int status, struct packet_queue *q, struct neighbor_queue *n) +{ + mac_callback_t sent; + struct qbuf_metadata *metadata; + void *cptr; + uint8_t ntx; + + metadata = (struct qbuf_metadata *)q->ptr; + sent = metadata->sent; + cptr = metadata->cptr; + ntx = n->transmissions; + + switch(status) { + case MAC_TX_OK: + PRINTF("csma: rexmit ok %d\n", n->transmissions); + break; + case MAC_TX_COLLISION: + case MAC_TX_NOACK: + PRINTF("csma: drop with status %d after %d transmissions, %d collisions\n", + status, n->transmissions, n->collisions); + break; + default: + PRINTF("csma: rexmit failed %d: %d\n", n->transmissions, status); + break; + } + + free_packet(n, q, status); + mac_call_sent_callback(sent, cptr, status, ntx); +} +/*---------------------------------------------------------------------------*/ +static void +rexmit(struct packet_queue *q, struct neighbor_queue *n) +{ + schedule_transmission(n); + /* This is needed to correctly attribute energy that we spent + transmitting this packet. */ + queuebuf_update_attr_from_packetbuf(q->buf); +} +/*---------------------------------------------------------------------------*/ +static void +collision(struct packet_queue *q, struct neighbor_queue *n, + int num_transmissions) +{ + struct qbuf_metadata *metadata; + + metadata = (struct qbuf_metadata *)q->ptr; + + n->collisions += num_transmissions; + + if(n->collisions > CSMA_MAX_BACKOFF) { + n->collisions = CSMA_MIN_BE; + /* Increment to indicate a next retry */ + n->transmissions++; + } + + if(n->transmissions >= metadata->max_transmissions) { + tx_done(MAC_TX_COLLISION, q, n); + } else { + PRINTF("csma: rexmit collision %d\n", n->transmissions); + rexmit(q, n); + } +} +/*---------------------------------------------------------------------------*/ +static void +noack(struct packet_queue *q, struct neighbor_queue *n, int num_transmissions) +{ + struct qbuf_metadata *metadata; + + metadata = (struct qbuf_metadata *)q->ptr; + + n->collisions = CSMA_MIN_BE; + n->transmissions += num_transmissions; + + if(n->transmissions >= metadata->max_transmissions) { + tx_done(MAC_TX_NOACK, q, n); + } else { + PRINTF("csma: rexmit noack %d\n", n->transmissions); + rexmit(q, n); + } +} +/*---------------------------------------------------------------------------*/ +static void +tx_ok(struct packet_queue *q, struct neighbor_queue *n, int num_transmissions) +{ + n->collisions = CSMA_MIN_BE; + n->transmissions += num_transmissions; + tx_done(MAC_TX_OK, q, n); +} +/*---------------------------------------------------------------------------*/ +static void +packet_sent(void *ptr, int status, int num_transmissions) +{ + struct neighbor_queue *n; + struct packet_queue *q; + + n = ptr; + if(n == NULL) { + return; + } + + /* Find out what packet this callback refers to */ + for(q = list_head(n->packet_queue); + q != NULL; q = list_item_next(q)) { + if(queuebuf_attr(q->buf, PACKETBUF_ATTR_MAC_SEQNO) == + packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO)) { + break; + } + } + + if(q == NULL) { + PRINTF("csma: seqno %d not found\n", + packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO)); + return; + } else if(q->ptr == NULL) { + PRINTF("csma: no metadata\n"); + return; + } + + switch(status) { + case MAC_TX_OK: + tx_ok(q, n, num_transmissions); + break; + case MAC_TX_NOACK: + noack(q, n, num_transmissions); + break; + case MAC_TX_COLLISION: + collision(q, n, num_transmissions); + break; + case MAC_TX_DEFERRED: + break; + default: + tx_done(status, q, n); + break; + } +} +/*---------------------------------------------------------------------------*/ +void +csma_output_packet(mac_callback_t sent, void *ptr) +{ + struct packet_queue *q; + struct neighbor_queue *n; + static uint8_t initialized = 0; + static uint16_t seqno; + const linkaddr_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. */ + seqno++; + } + packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, seqno++); + packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, FRAME802154_DATAFRAME); + + /* Look for the neighbor entry */ + n = neighbor_queue_from_addr(addr); + if(n == NULL) { + /* Allocate a new neighbor entry */ + n = memb_alloc(&neighbor_memb); + if(n != NULL) { + /* Init neighbor entry */ + linkaddr_copy(&n->addr, addr); + n->transmissions = 0; + n->collisions = CSMA_MIN_BE; + /* Init packet queue for this neighbor */ + LIST_STRUCT_INIT(n, packet_queue); + /* Add neighbor to the neighbor list */ + list_add(neighbor_list, n); + } + } + + if(n != NULL) { + /* Add packet to the neighbor's queue */ + if(list_length(n->packet_queue) < CSMA_MAX_PACKET_PER_NEIGHBOR) { + q = memb_alloc(&packet_memb); + if(q != NULL) { + q->ptr = memb_alloc(&metadata_memb); + if(q->ptr != NULL) { + q->buf = queuebuf_new_from_packetbuf(); + if(q->buf != NULL) { + struct qbuf_metadata *metadata = (struct qbuf_metadata *)q->ptr; + /* Neighbor and packet successfully allocated */ + metadata->max_transmissions = CSMA_MAX_MAX_FRAME_RETRIES + 1; + metadata->sent = sent; + metadata->cptr = ptr; + list_add(n->packet_queue, q); + + PRINTF("csma: send_packet, queue length %d, free packets %d\n", + list_length(n->packet_queue), memb_numfree(&packet_memb)); + /* If q is the first packet in the neighbor's queue, send asap */ + if(list_head(n->packet_queue) == q) { + schedule_transmission(n); + } + return; + } + memb_free(&metadata_memb, q->ptr); + PRINTF("csma: could not allocate queuebuf, dropping packet\n"); + } + memb_free(&packet_memb, q); + PRINTF("csma: could not allocate queuebuf, dropping packet\n"); + } + /* The packet allocation failed. Remove and free neighbor entry if empty. */ + if(list_length(n->packet_queue) == 0) { + list_remove(neighbor_list, n); + memb_free(&neighbor_memb, n); + } + } else { + PRINTF("csma: Neighbor queue full\n"); + } + PRINTF("csma: could not allocate packet, dropping packet\n"); + } else { + PRINTF("csma: could not allocate neighbor, dropping packet\n"); + } + mac_call_sent_callback(sent, ptr, MAC_TX_ERR, 1); +} +/*---------------------------------------------------------------------------*/ +void +csma_output_init(void) +{ + memb_init(&packet_memb); + memb_init(&metadata_memb); + memb_init(&neighbor_memb); +} diff --git a/core/net/mac/nullrdc.h b/core/net/mac/csma-output.h similarity index 76% rename from core/net/mac/nullrdc.h rename to core/net/mac/csma-output.h index 0f524ddae..835685861 100644 --- a/core/net/mac/nullrdc.h +++ b/core/net/mac/csma-output.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Swedish Institute of Computer Science. + * Copyright (c) 2007, Swedish Institute of Computer Science. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,26 +32,20 @@ /** * \file - * A null RDC implementation that uses framer for headers. + * The 802.15.4 standard CSMA protocol (nonbeacon-enabled). + * Output functions. * \author - * Adam Dunkels - * Niclas Finne + + * Simon Duquennoy */ -#ifndef NULLRDC_H_ -#define NULLRDC_H_ +#ifndef CSMA_OUTPUT_H_ +#define CSMA_OUTPUT_H_ #include "contiki-conf.h" #include "net/mac/mac.h" -/* List of packets to be sent by RDC layer */ -struct rdc_buf_list { - struct rdc_buf_list *next; - struct queuebuf *buf; - void *ptr; -}; +void csma_output_packet(mac_callback_t sent, void *ptr); +void csma_output_init(void); -void nullrdc_send_list(mac_callback_t sent, void *ptr, struct rdc_buf_list *buf_list); -void nullrdc_packet_input(void); - -#endif /* NULLRDC_H_ */ +#endif /* CSMA_OUTPUT_H_ */ diff --git a/core/net/mac/csma.c b/core/net/mac/csma.c index 57e33081d..6f327546e 100644 --- a/core/net/mac/csma.c +++ b/core/net/mac/csma.c @@ -32,28 +32,19 @@ /** * \file - * A Carrier Sense Multiple Access (CSMA) MAC layer +* The 802.15.4 standard CSMA protocol (nonbeacon-enabled) * \author * Adam Dunkels + * Simon Duquennoy */ #include "net/mac/csma.h" -#include "net/mac/nullrdc.h" +#include "net/mac/csma-output.h" +#include "net/mac/mac-sequence.h" #include "net/packetbuf.h" -#include "net/queuebuf.h" - -#include "sys/ctimer.h" -#include "sys/clock.h" - -#include "lib/random.h" - #include "net/netstack.h" -#include "lib/list.h" -#include "lib/memb.h" - #include - #include #define DEBUG 0 @@ -64,385 +55,72 @@ #define PRINTF(...) #endif /* DEBUG */ -/* Constants of the IEEE 802.15.4 standard */ - -/* macMinBE: Initial backoff exponent. Range 0--CSMA_MAX_BE */ -#ifdef CSMA_CONF_MIN_BE -#define CSMA_MIN_BE CSMA_CONF_MIN_BE -#else -#define CSMA_MIN_BE 0 -#endif - -/* macMaxBE: Maximum backoff exponent. Range 3--8 */ -#ifdef CSMA_CONF_MAX_BE -#define CSMA_MAX_BE CSMA_CONF_MAX_BE -#else -#define CSMA_MAX_BE 4 -#endif - -/* macMaxCSMABackoffs: Maximum number of backoffs in case of channel busy/collision. Range 0--5 */ -#ifdef CSMA_CONF_MAX_BACKOFF -#define CSMA_MAX_BACKOFF CSMA_CONF_MAX_BACKOFF -#else -#define CSMA_MAX_BACKOFF 5 -#endif - -/* macMaxFrameRetries: Maximum number of re-transmissions attampts. Range 0--7 */ -#ifdef CSMA_CONF_MAX_FRAME_RETRIES -#define CSMA_MAX_MAX_FRAME_RETRIES CSMA_CONF_MAX_FRAME_RETRIES -#else -#define CSMA_MAX_MAX_FRAME_RETRIES 7 -#endif - -/* Packet metadata */ -struct qbuf_metadata { - mac_callback_t sent; - void *cptr; - uint8_t max_transmissions; -}; - -/* Every neighbor has its own packet queue */ -struct neighbor_queue { - struct neighbor_queue *next; - linkaddr_t addr; - struct ctimer transmit_timer; - uint8_t transmissions; - uint8_t collisions; - LIST_STRUCT(queued_packet_list); -}; - -/* The maximum number of co-existing neighbor queues */ -#ifdef CSMA_CONF_MAX_NEIGHBOR_QUEUES -#define CSMA_MAX_NEIGHBOR_QUEUES CSMA_CONF_MAX_NEIGHBOR_QUEUES -#else -#define CSMA_MAX_NEIGHBOR_QUEUES 2 -#endif /* CSMA_CONF_MAX_NEIGHBOR_QUEUES */ - -/* The maximum number of pending packet per neighbor */ -#ifdef CSMA_CONF_MAX_PACKET_PER_NEIGHBOR -#define CSMA_MAX_PACKET_PER_NEIGHBOR CSMA_CONF_MAX_PACKET_PER_NEIGHBOR -#else -#define CSMA_MAX_PACKET_PER_NEIGHBOR MAX_QUEUED_PACKETS -#endif /* CSMA_CONF_MAX_PACKET_PER_NEIGHBOR */ - -#define MAX_QUEUED_PACKETS QUEUEBUF_NUM -MEMB(neighbor_memb, struct neighbor_queue, CSMA_MAX_NEIGHBOR_QUEUES); -MEMB(packet_memb, struct rdc_buf_list, MAX_QUEUED_PACKETS); -MEMB(metadata_memb, struct qbuf_metadata, MAX_QUEUED_PACKETS); -LIST(neighbor_list); - -static void packet_sent(void *ptr, int status, int num_transmissions); -static void transmit_packet_list(void *ptr); -/*---------------------------------------------------------------------------*/ -static struct neighbor_queue * -neighbor_queue_from_addr(const linkaddr_t *addr) -{ - struct neighbor_queue *n = list_head(neighbor_list); - while(n != NULL) { - if(linkaddr_cmp(&n->addr, addr)) { - return n; - } - n = list_item_next(n); - } - return NULL; -} -/*---------------------------------------------------------------------------*/ -static clock_time_t -backoff_period(void) -{ - /* Use the default in IEEE 802.15.4: aUnitBackoffPeriod which is - * 20 symbols i.e. 320 usec. That is, 1/3125 second. */ - return MAX(CLOCK_SECOND / 3125, 1); -} -/*---------------------------------------------------------------------------*/ -static void -transmit_packet_list(void *ptr) -{ - struct neighbor_queue *n = ptr; - if(n) { - struct rdc_buf_list *q = list_head(n->queued_packet_list); - if(q != NULL) { - PRINTF("csma: preparing number %d %p, queue len %d\n", n->transmissions, q, - list_length(n->queued_packet_list)); - /* Send packets in the neighbor's list */ - nullrdc_send_list(packet_sent, n, q); - } - } -} -/*---------------------------------------------------------------------------*/ -static void -schedule_transmission(struct neighbor_queue *n) -{ - clock_time_t delay; - int backoff_exponent; /* BE in IEEE 802.15.4 */ - - backoff_exponent = MIN(n->collisions, CSMA_MAX_BE); - - /* Compute max delay as per IEEE 802.15.4: 2^BE-1 backoff periods */ - delay = ((1 << backoff_exponent) - 1) * backoff_period(); - if(delay > 0) { - /* Pick a time for next transmission */ - delay = random_rand() % delay; - } - - PRINTF("csma: scheduling transmission in %u ticks, NB=%u, BE=%u\n", - (unsigned)delay, n->collisions, backoff_exponent); - ctimer_set(&n->transmit_timer, delay, transmit_packet_list, n); -} -/*---------------------------------------------------------------------------*/ -static void -free_packet(struct neighbor_queue *n, struct rdc_buf_list *p, int status) -{ - if(p != NULL) { - /* Remove packet from list and deallocate */ - list_remove(n->queued_packet_list, p); - - queuebuf_free(p->buf); - memb_free(&metadata_memb, p->ptr); - memb_free(&packet_memb, p); - PRINTF("csma: free_queued_packet, queue length %d, free packets %d\n", - list_length(n->queued_packet_list), memb_numfree(&packet_memb)); - if(list_head(n->queued_packet_list) != NULL) { - /* There is a next packet. We reset current tx information */ - n->transmissions = 0; - n->collisions = CSMA_MIN_BE; - /* Schedule next transmissions */ - schedule_transmission(n); - } else { - /* This was the last packet in the queue, we free the neighbor */ - ctimer_stop(&n->transmit_timer); - list_remove(neighbor_list, n); - memb_free(&neighbor_memb, n); - } - } -} -/*---------------------------------------------------------------------------*/ -static void -tx_done(int status, struct rdc_buf_list *q, struct neighbor_queue *n) -{ - mac_callback_t sent; - struct qbuf_metadata *metadata; - void *cptr; - uint8_t ntx; - - metadata = (struct qbuf_metadata *)q->ptr; - sent = metadata->sent; - cptr = metadata->cptr; - ntx = n->transmissions; - - switch(status) { - case MAC_TX_OK: - PRINTF("csma: rexmit ok %d\n", n->transmissions); - break; - case MAC_TX_COLLISION: - case MAC_TX_NOACK: - PRINTF("csma: drop with status %d after %d transmissions, %d collisions\n", - status, n->transmissions, n->collisions); - break; - default: - PRINTF("csma: rexmit failed %d: %d\n", n->transmissions, status); - break; - } - - free_packet(n, q, status); - mac_call_sent_callback(sent, cptr, status, ntx); -} -/*---------------------------------------------------------------------------*/ -static void -rexmit(struct rdc_buf_list *q, struct neighbor_queue *n) -{ - schedule_transmission(n); - /* This is needed to correctly attribute energy that we spent - transmitting this packet. */ - queuebuf_update_attr_from_packetbuf(q->buf); -} -/*---------------------------------------------------------------------------*/ -static void -collision(struct rdc_buf_list *q, struct neighbor_queue *n, - int num_transmissions) -{ - struct qbuf_metadata *metadata; - - metadata = (struct qbuf_metadata *)q->ptr; - - n->collisions += num_transmissions; - - if(n->collisions > CSMA_MAX_BACKOFF) { - n->collisions = CSMA_MIN_BE; - /* Increment to indicate a next retry */ - n->transmissions++; - } - - if(n->transmissions >= metadata->max_transmissions) { - tx_done(MAC_TX_COLLISION, q, n); - } else { - PRINTF("csma: rexmit collision %d\n", n->transmissions); - rexmit(q, n); - } -} -/*---------------------------------------------------------------------------*/ -static void -noack(struct rdc_buf_list *q, struct neighbor_queue *n, int num_transmissions) -{ - struct qbuf_metadata *metadata; - - metadata = (struct qbuf_metadata *)q->ptr; - - n->collisions = CSMA_MIN_BE; - n->transmissions += num_transmissions; - - if(n->transmissions >= metadata->max_transmissions) { - tx_done(MAC_TX_NOACK, q, n); - } else { - PRINTF("csma: rexmit noack %d\n", n->transmissions); - rexmit(q, n); - } -} -/*---------------------------------------------------------------------------*/ -static void -tx_ok(struct rdc_buf_list *q, struct neighbor_queue *n, int num_transmissions) -{ - n->collisions = CSMA_MIN_BE; - n->transmissions += num_transmissions; - tx_done(MAC_TX_OK, q, n); -} -/*---------------------------------------------------------------------------*/ -static void -packet_sent(void *ptr, int status, int num_transmissions) -{ - struct neighbor_queue *n; - struct rdc_buf_list *q; - - n = ptr; - if(n == NULL) { - return; - } - - /* Find out what packet this callback refers to */ - for(q = list_head(n->queued_packet_list); - q != NULL; q = list_item_next(q)) { - if(queuebuf_attr(q->buf, PACKETBUF_ATTR_MAC_SEQNO) == - packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO)) { - break; - } - } - - if(q == NULL) { - PRINTF("csma: seqno %d not found\n", - packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO)); - return; - } else if(q->ptr == NULL) { - PRINTF("csma: no metadata\n"); - return; - } - - switch(status) { - case MAC_TX_OK: - tx_ok(q, n, num_transmissions); - break; - case MAC_TX_NOACK: - noack(q, n, num_transmissions); - break; - case MAC_TX_COLLISION: - collision(q, n, num_transmissions); - break; - case MAC_TX_DEFERRED: - break; - default: - tx_done(status, q, n); - break; - } -} /*---------------------------------------------------------------------------*/ static void 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 linkaddr_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. */ - seqno++; - } - packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, seqno++); - packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, FRAME802154_DATAFRAME); - - /* Look for the neighbor entry */ - n = neighbor_queue_from_addr(addr); - if(n == NULL) { - /* Allocate a new neighbor entry */ - n = memb_alloc(&neighbor_memb); - if(n != NULL) { - /* Init neighbor entry */ - linkaddr_copy(&n->addr, addr); - n->transmissions = 0; - n->collisions = CSMA_MIN_BE; - /* Init packet list for this neighbor */ - LIST_STRUCT_INIT(n, queued_packet_list); - /* Add neighbor to the list */ - list_add(neighbor_list, n); - } - } - - if(n != NULL) { - /* Add packet to the neighbor's queue */ - if(list_length(n->queued_packet_list) < CSMA_MAX_PACKET_PER_NEIGHBOR) { - q = memb_alloc(&packet_memb); - if(q != NULL) { - q->ptr = memb_alloc(&metadata_memb); - if(q->ptr != NULL) { - q->buf = queuebuf_new_from_packetbuf(); - if(q->buf != NULL) { - struct qbuf_metadata *metadata = (struct qbuf_metadata *)q->ptr; - /* Neighbor and packet successfully allocated */ - metadata->max_transmissions = CSMA_MAX_MAX_FRAME_RETRIES + 1; - metadata->sent = sent; - metadata->cptr = ptr; - list_add(n->queued_packet_list, q); - - PRINTF("csma: send_packet, queue length %d, free packets %d\n", - list_length(n->queued_packet_list), memb_numfree(&packet_memb)); - /* If q is the first packet in the neighbor's queue, send asap */ - if(list_head(n->queued_packet_list) == q) { - schedule_transmission(n); - } - return; - } - memb_free(&metadata_memb, q->ptr); - PRINTF("csma: could not allocate queuebuf, dropping packet\n"); - } - memb_free(&packet_memb, q); - PRINTF("csma: could not allocate queuebuf, dropping packet\n"); - } - /* The packet allocation failed. Remove and free neighbor entry if empty. */ - if(list_length(n->queued_packet_list) == 0) { - list_remove(neighbor_list, n); - memb_free(&neighbor_memb, n); - } - } else { - PRINTF("csma: Neighbor queue full\n"); - } - PRINTF("csma: could not allocate packet, dropping packet\n"); - } else { - PRINTF("csma: could not allocate neighbor, dropping packet\n"); - } - mac_call_sent_callback(sent, ptr, MAC_TX_ERR, 1); + csma_output_packet(sent, ptr); } /*---------------------------------------------------------------------------*/ static void input_packet(void) { - nullrdc_packet_input(); +#if CSMA_SEND_802154_ACK + int original_datalen; + uint8_t *original_dataptr; + + original_datalen = packetbuf_datalen(); + original_dataptr = packetbuf_dataptr(); +#endif + +#if CSMA_802154_AUTOACK + if(packetbuf_datalen() == CSMA_ACK_LEN) { + /* Ignore ack packets */ + PRINTF("csma: ignored ack\n"); + } else +#endif /* CSMA_802154_AUTOACK */ + if(NETSTACK_FRAMER.parse() < 0) { + PRINTF("csma: failed to parse %u\n", packetbuf_datalen()); + } else if(!linkaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), + &linkaddr_node_addr) && + !packetbuf_holds_broadcast()) { + PRINTF("csma: not for us\n"); + } else { + int duplicate = 0; + +#if CSMA_802154_AUTOACK || CSMA_802154_AUTOACK_HW + /* Check for duplicate packet. */ + duplicate = mac_sequence_is_duplicate(); + if(duplicate) { + /* Drop the packet. */ + PRINTF("csma: drop duplicate link layer packet %u\n", + packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO)); + } else { + mac_sequence_register_seqno(); + } +#endif /* CSMA_802154_AUTOACK */ + +#if CSMA_SEND_802154_ACK + { + frame802154_t info154; + frame802154_parse(original_dataptr, original_datalen, &info154); + if(info154.fcf.frame_type == FRAME802154_DATAFRAME && + info154.fcf.ack_required != 0 && + linkaddr_cmp((linkaddr_t *)&info154.dest_addr, + &linkaddr_node_addr)) { + uint8_t ackdata[CSMA_ACK_LEN] = {0, 0, 0}; + + ackdata[0] = FRAME802154_ACKFRAME; + ackdata[1] = 0; + ackdata[2] = info154.seq; + NETSTACK_RADIO.send(ackdata, CSMA_ACK_LEN); + } + } +#endif /* CSMA_SEND_802154_ACK */ + if(!duplicate) { + NETSTACK_NETWORK.input(); + } + } } /*---------------------------------------------------------------------------*/ static int @@ -460,9 +138,7 @@ off(void) static void init(void) { - memb_init(&packet_memb); - memb_init(&metadata_memb); - memb_init(&neighbor_memb); + csma_output_init(); on(); } /*---------------------------------------------------------------------------*/ diff --git a/core/net/mac/csma.h b/core/net/mac/csma.h index 456b828ce..f11c5541c 100644 --- a/core/net/mac/csma.h +++ b/core/net/mac/csma.h @@ -32,20 +32,55 @@ /** * \file - * A MAC stack protocol that performs retransmissions when the - * underlying MAC layer has problems with collisions + * The 802.15.4 standard CSMA protocol (nonbeacon-enabled) * \author * Adam Dunkels + * Simon Duquennoy */ #ifndef CSMA_H_ #define CSMA_H_ +#include "contiki-conf.h" #include "net/mac/mac.h" #include "dev/radio.h" +#ifndef CSMA_802154_AUTOACK +#ifdef CSMA_CONF_802154_AUTOACK +#define CSMA_802154_AUTOACK CSMA_CONF_802154_AUTOACK +#else +#define CSMA_802154_AUTOACK 0 +#endif /* CSMA_CONF_802154_AUTOACK */ +#endif /* CSMA_802154_AUTOACK */ + +#ifndef CSMA_802154_AUTOACK_HW +#ifdef CSMA_CONF_802154_AUTOACK_HW +#define CSMA_802154_AUTOACK_HW CSMA_CONF_802154_AUTOACK_HW +#else +#define CSMA_802154_AUTOACK_HW 0 +#endif /* CSMA_CONF_802154_AUTOACK_HW */ +#endif /* CSMA_802154_AUTOACK_HW */ + +#ifdef CSMA_CONF_ACK_WAIT_TIME +#define CSMA_ACK_WAIT_TIME CSMA_CONF_ACK_WAIT_TIME +#else /* CSMA_CONF_ACK_WAIT_TIME */ +#define CSMA_ACK_WAIT_TIME RTIMER_SECOND / 2500 +#endif /* CSMA_CONF_ACK_WAIT_TIME */ + +#ifdef CSMA_CONF_AFTER_ACK_DETECTED_WAIT_TIME +#define CSMA_AFTER_ACK_DETECTED_WAIT_TIME CSMA_CONF_AFTER_ACK_DETECTED_WAIT_TIME +#else /* CSMA_CONF_AFTER_ACK_DETECTED_WAIT_TIME */ +#define CSMA_AFTER_ACK_DETECTED_WAIT_TIME RTIMER_SECOND / 1500 +#endif /* CSMA_CONF_AFTER_ACK_DETECTED_WAIT_TIME */ + +#ifdef CSMA_CONF_SEND_802154_ACK +#define CSMA_SEND_802154_ACK CSMA_CONF_SEND_802154_ACK +#else /* CSMA_CONF_SEND_802154_ACK */ +#define CSMA_SEND_802154_ACK 0 +#endif /* CSMA_CONF_SEND_802154_ACK */ + +#define CSMA_ACK_LEN 3 + extern const struct mac_driver csma_driver; -const struct mac_driver *csma_init(const struct mac_driver *r); - #endif /* CSMA_H_ */ diff --git a/core/net/mac/nullrdc.c b/core/net/mac/nullrdc.c deleted file mode 100644 index 679b025cf..000000000 --- a/core/net/mac/nullrdc.c +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Copyright (c) 2010, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - * - */ - -/** - * \file - * A null RDC implementation that uses framer for headers. - * \author - * Adam Dunkels - * Niclas Finne - */ - -#include "net/mac/mac-sequence.h" -#include "net/mac/nullrdc.h" -#include "net/packetbuf.h" -#include "net/queuebuf.h" -#include "net/netstack.h" -#include - -#if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 -#include "lib/simEnvChange.h" -#include "sys/cooja_mt.h" -#endif /* CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 */ - -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) -#endif - -#ifndef NULLRDC_802154_AUTOACK -#ifdef NULLRDC_CONF_802154_AUTOACK -#define NULLRDC_802154_AUTOACK NULLRDC_CONF_802154_AUTOACK -#else -#define NULLRDC_802154_AUTOACK 0 -#endif /* NULLRDC_CONF_802154_AUTOACK */ -#endif /* NULLRDC_802154_AUTOACK */ - -#ifndef NULLRDC_802154_AUTOACK_HW -#ifdef NULLRDC_CONF_802154_AUTOACK_HW -#define NULLRDC_802154_AUTOACK_HW NULLRDC_CONF_802154_AUTOACK_HW -#else -#define NULLRDC_802154_AUTOACK_HW 0 -#endif /* NULLRDC_CONF_802154_AUTOACK_HW */ -#endif /* NULLRDC_802154_AUTOACK_HW */ - -#if NULLRDC_802154_AUTOACK -#include "sys/rtimer.h" -#include "dev/watchdog.h" - -#ifdef NULLRDC_CONF_ACK_WAIT_TIME -#define ACK_WAIT_TIME NULLRDC_CONF_ACK_WAIT_TIME -#else /* NULLRDC_CONF_ACK_WAIT_TIME */ -#define ACK_WAIT_TIME RTIMER_SECOND / 2500 -#endif /* NULLRDC_CONF_ACK_WAIT_TIME */ -#ifdef NULLRDC_CONF_AFTER_ACK_DETECTED_WAIT_TIME -#define AFTER_ACK_DETECTED_WAIT_TIME NULLRDC_CONF_AFTER_ACK_DETECTED_WAIT_TIME -#else /* NULLRDC_CONF_AFTER_ACK_DETECTED_WAIT_TIME */ -#define AFTER_ACK_DETECTED_WAIT_TIME RTIMER_SECOND / 1500 -#endif /* NULLRDC_CONF_AFTER_ACK_DETECTED_WAIT_TIME */ -#endif /* NULLRDC_802154_AUTOACK */ - -#ifdef NULLRDC_CONF_SEND_802154_ACK -#define NULLRDC_SEND_802154_ACK NULLRDC_CONF_SEND_802154_ACK -#else /* NULLRDC_CONF_SEND_802154_ACK */ -#define NULLRDC_SEND_802154_ACK 0 -#endif /* NULLRDC_CONF_SEND_802154_ACK */ - -#if NULLRDC_SEND_802154_ACK -#include "net/mac/framer/frame802154.h" -#endif /* NULLRDC_SEND_802154_ACK */ - -#define ACK_LEN 3 - -/*---------------------------------------------------------------------------*/ -static int -send_one_packet(mac_callback_t sent, void *ptr) -{ - int ret; - int last_sent_ok = 0; - - packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &linkaddr_node_addr); -#if NULLRDC_802154_AUTOACK || NULLRDC_802154_AUTOACK_HW - packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1); -#endif /* NULLRDC_802154_AUTOACK || NULLRDC_802154_AUTOACK_HW */ - - if(NETSTACK_FRAMER.create() < 0) { - /* Failed to allocate space for headers */ - PRINTF("nullrdc: send failed, too large header\n"); - ret = MAC_TX_ERR_FATAL; - } else { -#if NULLRDC_802154_AUTOACK - int is_broadcast; - uint8_t dsn; - dsn = ((uint8_t *)packetbuf_hdrptr())[2] & 0xff; - - NETSTACK_RADIO.prepare(packetbuf_hdrptr(), packetbuf_totlen()); - - is_broadcast = packetbuf_holds_broadcast(); - - if(NETSTACK_RADIO.receiving_packet() || - (!is_broadcast && NETSTACK_RADIO.pending_packet())) { - - /* Currently receiving a packet over air or the radio has - already received a packet that needs to be read before - sending with auto ack. */ - ret = MAC_TX_COLLISION; - } else { - if(!is_broadcast) { - RIMESTATS_ADD(reliabletx); - } - - switch(NETSTACK_RADIO.transmit(packetbuf_totlen())) { - case RADIO_TX_OK: - if(is_broadcast) { - ret = MAC_TX_OK; - } else { - rtimer_clock_t wt; - - /* Check for ack */ - wt = RTIMER_NOW(); - watchdog_periodic(); - while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + ACK_WAIT_TIME)) { -#if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 - simProcessRunValue = 1; - cooja_mt_yield(); -#endif /* CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 */ - } - - ret = MAC_TX_NOACK; - if(NETSTACK_RADIO.receiving_packet() || - NETSTACK_RADIO.pending_packet() || - NETSTACK_RADIO.channel_clear() == 0) { - int len; - uint8_t ackbuf[ACK_LEN]; - - if(AFTER_ACK_DETECTED_WAIT_TIME > 0) { - wt = RTIMER_NOW(); - watchdog_periodic(); - while(RTIMER_CLOCK_LT(RTIMER_NOW(), - wt + AFTER_ACK_DETECTED_WAIT_TIME)) { -#if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 - simProcessRunValue = 1; - cooja_mt_yield(); -#endif /* CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 */ - } - } - - if(NETSTACK_RADIO.pending_packet()) { - len = NETSTACK_RADIO.read(ackbuf, ACK_LEN); - if(len == ACK_LEN && ackbuf[2] == dsn) { - /* Ack received */ - RIMESTATS_ADD(ackrx); - ret = MAC_TX_OK; - } else { - /* Not an ack or ack not for us: collision */ - ret = MAC_TX_COLLISION; - } - } - } else { - PRINTF("nullrdc tx noack\n"); - } - } - break; - case RADIO_TX_COLLISION: - ret = MAC_TX_COLLISION; - break; - default: - ret = MAC_TX_ERR; - break; - } - } - -#else /* ! NULLRDC_802154_AUTOACK */ - - switch(NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen())) { - case RADIO_TX_OK: - ret = MAC_TX_OK; - break; - case RADIO_TX_COLLISION: - ret = MAC_TX_COLLISION; - break; - case RADIO_TX_NOACK: - ret = MAC_TX_NOACK; - break; - default: - ret = MAC_TX_ERR; - break; - } - -#endif /* ! NULLRDC_802154_AUTOACK */ - } - if(ret == MAC_TX_OK) { - last_sent_ok = 1; - } - mac_call_sent_callback(sent, ptr, ret, 1); - return last_sent_ok; -} -/*---------------------------------------------------------------------------*/ -void -nullrdc_send_list(mac_callback_t sent, void *ptr, struct rdc_buf_list *buf_list) -{ - while(buf_list != NULL) { - /* We backup the next pointer, as it may be nullified by - * mac_call_sent_callback() */ - struct rdc_buf_list *next = buf_list->next; - int last_sent_ok; - - queuebuf_to_packetbuf(buf_list->buf); - last_sent_ok = send_one_packet(sent, ptr); - - /* If packet transmission was not successful, we should back off and let - * upper layers retransmit, rather than potentially sending out-of-order - * packet fragments. */ - if(!last_sent_ok) { - return; - } - buf_list = next; - } -} -/*---------------------------------------------------------------------------*/ -void -nullrdc_packet_input(void) -{ -#if NULLRDC_SEND_802154_ACK - int original_datalen; - uint8_t *original_dataptr; - - original_datalen = packetbuf_datalen(); - original_dataptr = packetbuf_dataptr(); -#endif - -#if NULLRDC_802154_AUTOACK - if(packetbuf_datalen() == ACK_LEN) { - /* Ignore ack packets */ - PRINTF("nullrdc: ignored ack\n"); - } else -#endif /* NULLRDC_802154_AUTOACK */ - if(NETSTACK_FRAMER.parse() < 0) { - PRINTF("nullrdc: failed to parse %u\n", packetbuf_datalen()); - } else if(!linkaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), - &linkaddr_node_addr) && - !packetbuf_holds_broadcast()) { - PRINTF("nullrdc: not for us\n"); - } else { - int duplicate = 0; - -#if NULLRDC_802154_AUTOACK || NULLRDC_802154_AUTOACK_HW - /* 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_MAC_SEQNO)); - } else { - mac_sequence_register_seqno(); - } -#endif /* NULLRDC_802154_AUTOACK */ - -#if NULLRDC_SEND_802154_ACK - { - frame802154_t info154; - frame802154_parse(original_dataptr, original_datalen, &info154); - if(info154.fcf.frame_type == FRAME802154_DATAFRAME && - info154.fcf.ack_required != 0 && - linkaddr_cmp((linkaddr_t *)&info154.dest_addr, - &linkaddr_node_addr)) { - uint8_t ackdata[ACK_LEN] = {0, 0, 0}; - - ackdata[0] = FRAME802154_ACKFRAME; - ackdata[1] = 0; - ackdata[2] = info154.seq; - NETSTACK_RADIO.send(ackdata, ACK_LEN); - } - } -#endif /* NULLRDC_SEND_ACK */ - if(!duplicate) { - NETSTACK_NETWORK.input(); - } - } -} -/*---------------------------------------------------------------------------*/ diff --git a/drivers/cpu/cc26xx-cc13xx/rf-core/rf-ble.c b/drivers/cpu/cc26xx-cc13xx/rf-core/rf-ble.c index bceb9c138..bfa58c2d3 100644 --- a/drivers/cpu/cc26xx-cc13xx/rf-core/rf-ble.c +++ b/drivers/cpu/cc26xx-cc13xx/rf-core/rf-ble.c @@ -295,7 +295,7 @@ PROCESS_THREAD(rf_ble_beacon_process, ev, data) * * First, determine our state: * - * If we are running NullRDC, we are likely in IEEE RX mode. We need to + * If we are running CSMA, we are likely in IEEE RX mode. We need to * abort the IEEE BG Op before entering BLE mode. * If we are ContikiMAC, we are likely off, in which case we need to * boot the CPE before entering BLE mode diff --git a/drivers/dev/cc1200/cc1200-conf.h b/drivers/dev/cc1200/cc1200-conf.h index 27dc6eb6e..45517080f 100644 --- a/drivers/dev/cc1200/cc1200-conf.h +++ b/drivers/dev/cc1200/cc1200-conf.h @@ -76,7 +76,7 @@ /* * The RX watchdog is used to check whether the radio is in RX mode at regular * intervals (once per second). Can be used to improve reliability especially - * if NullRDC is used. Turned of by default. + * if CSMA is used. Turned of by default. */ #ifdef CC1200_CONF_USE_RX_WATCHDOG #define CC1200_USE_RX_WATCHDOG CC1200_CONF_USE_RX_WATCHDOG diff --git a/drivers/dev/cc1200/cc1200.c b/drivers/dev/cc1200/cc1200.c index 365735e2c..5d8b5969a 100644 --- a/drivers/dev/cc1200/cc1200.c +++ b/drivers/dev/cc1200/cc1200.c @@ -972,7 +972,7 @@ channel_clear(void) /* * Check if the radio driver is currently receiving a packet. * - * nullrdc uses this function + * CSMA uses this function * - to detect a collision before transmit() * - to detect an incoming ACK */ @@ -991,11 +991,11 @@ receiving_packet(void) * for this event might make it necessary to review the MAC timing * parameters! Instead of (or in addition to) using GPIO0 we could also * read out MODEM_STATUS1 (e.g. PQT reached), but this would not change - * the situation at least for nullrdc as it uses two "blocking" timers + * the situation at least for CSMA as it uses two "blocking" timers * (does not perform polling...). Therefore the overall timing * of the ACK handling wouldn't change. It would just allow to detect an * incoming packet a little bit earlier and help us with respect to - * collision avoidance (why not use channel_clear() in nullrdc + * collision avoidance (why not use channel_clear() * at this point?). */ diff --git a/drivers/platform/cc2538dk/contiki-conf.h b/drivers/platform/cc2538dk/contiki-conf.h index 9becf6fb1..d4c803b13 100644 --- a/drivers/platform/cc2538dk/contiki-conf.h +++ b/drivers/platform/cc2538dk/contiki-conf.h @@ -254,9 +254,9 @@ typedef uint32_t rtimer_clock_t; #include "board.h" /*---------------------------------------------------------------------------*/ -/* Configure NullRDC for when it's selected */ -#define NULLRDC_802154_AUTOACK 1 -#define NULLRDC_802154_AUTOACK_HW 1 +/* Configure CSMA for when it's selected */ +#define CSMA_802154_AUTOACK 1 +#define CSMA_802154_AUTOACK_HW 1 #define NETSTACK_CONF_RADIO cc2538_rf_driver /** @} */ diff --git a/drivers/platform/cooja/contiki-conf.h b/drivers/platform/cooja/contiki-conf.h index 4e77021ac..4091c99df 100644 --- a/drivers/platform/cooja/contiki-conf.h +++ b/drivers/platform/cooja/contiki-conf.h @@ -67,10 +67,10 @@ /* Default network config */ #if NETSTACK_CONF_WITH_IPV6 -#define NULLRDC_CONF_802154_AUTOACK 1 -#define NULLRDC_CONF_SEND_802154_ACK 1 -#define NULLRDC_CONF_ACK_WAIT_TIME RTIMER_SECOND / 500 -#define NULLRDC_CONF_AFTER_ACK_DETECTED_WAIT_TIME 0 +#define CSMA_CONF_802154_AUTOACK 1 +#define CSMA_CONF_SEND_802154_ACK 1 +#define CSMA_CONF_ACK_WAIT_TIME RTIMER_SECOND / 500 +#define CSMA_CONF_AFTER_ACK_DETECTED_WAIT_TIME 0 /* Radio setup */ #define NETSTACK_CONF_RADIO cooja_radio_driver diff --git a/drivers/platform/jn516x/contiki-conf.h b/drivers/platform/jn516x/contiki-conf.h index 0319f1c6d..07f4470e3 100644 --- a/drivers/platform/jn516x/contiki-conf.h +++ b/drivers/platform/jn516x/contiki-conf.h @@ -97,8 +97,8 @@ #define NETSTACK_CONF_NETWORK sicslowpan_driver #define UIP_CONF_BROADCAST 1 -/* Configure NullRDC for when it is selected */ -#define NULLRDC_CONF_802154_AUTOACK_HW 1 +/* Configure CSMA for when it is selected */ +#define CSMA_CONF_802154_AUTOACK_HW 1 #define RDC_CONF_HARDWARE_ACK 1 diff --git a/drivers/platform/openmote-cc2538/contiki-conf.h b/drivers/platform/openmote-cc2538/contiki-conf.h index 4976d1d6f..2b437190e 100644 --- a/drivers/platform/openmote-cc2538/contiki-conf.h +++ b/drivers/platform/openmote-cc2538/contiki-conf.h @@ -308,9 +308,9 @@ typedef uint32_t rtimer_clock_t; * @{ */ -/* Configure NullRDC for when it's selected */ -#define NULLRDC_802154_AUTOACK 1 -#define NULLRDC_802154_AUTOACK_HW 1 +/* Configure CSMA for when it's selected */ +#define CSMA_802154_AUTOACK 1 +#define CSMA_802154_AUTOACK_HW 1 #ifndef NETSTACK_CONF_RADIO #define NETSTACK_CONF_RADIO cc2538_rf_driver diff --git a/drivers/platform/srf06-cc26xx/contiki-conf.h b/drivers/platform/srf06-cc26xx/contiki-conf.h index 0844a3b4d..4bca708ef 100644 --- a/drivers/platform/srf06-cc26xx/contiki-conf.h +++ b/drivers/platform/srf06-cc26xx/contiki-conf.h @@ -61,8 +61,8 @@ #define CC2650_FAST_RADIO_STARTUP 0 #endif -/* Configure NullRDC for when it's selected */ -#define NULLRDC_CONF_802154_AUTOACK 1 +/* Configure CSMA for when it's selected */ +#define CSMA_CONF_802154_AUTOACK 1 #ifdef RF_CHANNEL #define RF_CORE_CONF_CHANNEL RF_CHANNEL @@ -91,10 +91,10 @@ #define RF_CORE_CONF_CHANNEL 0 #endif -#define NULLRDC_CONF_ACK_WAIT_TIME (RTIMER_SECOND / 400) -#define NULLRDC_CONF_AFTER_ACK_DETECTED_WAIT_TIME (RTIMER_SECOND / 1000) -#define NULLRDC_CONF_802154_AUTOACK_HW 0 -#define NULLRDC_CONF_SEND_802154_ACK 1 +#define CSMA_CONF_ACK_WAIT_TIME (RTIMER_SECOND / 400) +#define CSMA_CONF_AFTER_ACK_DETECTED_WAIT_TIME (RTIMER_SECOND / 1000) +#define CSMA_CONF_802154_AUTOACK_HW 0 +#define CSMA_CONF_SEND_802154_ACK 1 #else #define NETSTACK_CONF_RADIO ieee_mode_driver @@ -103,8 +103,8 @@ #define RF_CORE_CONF_CHANNEL 25 #endif -#define NULLRDC_CONF_802154_AUTOACK_HW 1 -#define NULLRDC_CONF_SEND_802154_ACK 0 +#define CSMA_CONF_802154_AUTOACK_HW 1 +#define CSMA_CONF_SEND_802154_ACK 0 #endif #define NETSTACK_RADIO_MAX_PAYLOAD_LEN 125 diff --git a/drivers/platform/zoul/contiki-conf.h b/drivers/platform/zoul/contiki-conf.h index 8d78129c2..e92e18d0d 100644 --- a/drivers/platform/zoul/contiki-conf.h +++ b/drivers/platform/zoul/contiki-conf.h @@ -305,9 +305,9 @@ typedef uint32_t rtimer_clock_t; * * @{ */ -/* Configure NullRDC for when it's selected */ -#define NULLRDC_CONF_802154_AUTOACK 1 -#define NULLRDC_CONF_802154_AUTOACK_HW 1 +/* Configure CSMA for when it's selected */ +#define CSMA_CONF_802154_AUTOACK 1 +#define CSMA_CONF_802154_AUTOACK_HW 1 #if CC1200_CONF_SUBGHZ_50KBPS_MODE #define NETSTACK_CONF_RADIO cc1200_driver @@ -316,11 +316,11 @@ typedef uint32_t rtimer_clock_t; #define CC1200_CONF_USE_GPIO2 0 #define CC1200_CONF_USE_RX_WATCHDOG 0 -#define NULLRDC_CONF_ACK_WAIT_TIME (RTIMER_SECOND / 200) -#define NULLRDC_CONF_AFTER_ACK_DETECTED_WAIT_TIME (RTIMER_SECOND / 1500) -#define NULLRDC_CONF_802154_AUTOACK 1 -#define NULLRDC_CONF_802154_AUTOACK_HW 1 -#define NULLRDC_CONF_SEND_802154_ACK 0 +#define CSMA_CONF_ACK_WAIT_TIME (RTIMER_SECOND / 200) +#define CSMA_CONF_AFTER_ACK_DETECTED_WAIT_TIME (RTIMER_SECOND / 1500) +#define CSMA_CONF_802154_AUTOACK 1 +#define CSMA_CONF_802154_AUTOACK_HW 1 +#define CSMA_CONF_SEND_802154_ACK 0 #endif diff --git a/examples/ipv6/json-ws/README-COSM.md b/examples/ipv6/json-ws/README-COSM.md index 8772cfb41..a13798302 100644 --- a/examples/ipv6/json-ws/README-COSM.md +++ b/examples/ipv6/json-ws/README-COSM.md @@ -34,7 +34,7 @@ TSP_PREFIX=2001:05c0:1517:e400 (prefixlen is 56). it with the RPL-border-router (assumes Z1 node). cd contiki/examples/ipv6/rpl-border-router - make DEFINES=DEFINES=NETSTACK_RDC=nullrdc_driver,NULLRDC_CONF_802154_AUTOACK=1 TARGET=z1 border-router.upload + make DEFINES=DEFINES=NETSTACK_RDC=nullrdc_driver,CSMA_CONF_802154_AUTOACK=1 TARGET=z1 border-router.upload 6. Run tunslip6 which will forward IP from the RPL network to the IPv6 tunnel (and to the Internet). diff --git a/examples/ipv6/json-ws/project-conf.h b/examples/ipv6/json-ws/project-conf.h index 2325e4791..69d9d0ee9 100644 --- a/examples/ipv6/json-ws/project-conf.h +++ b/examples/ipv6/json-ws/project-conf.h @@ -39,8 +39,8 @@ #define JSON_WS_CONF_CALLBACK_PORT 80 #define JSON_WS_CONF_CALLBACK_INTERVAL 120 -#undef NULLRDC_CONF_802154_AUTOACK -#define NULLRDC_CONF_802154_AUTOACK 1 +#undef CSMA_CONF_802154_AUTOACK +#define CSMA_CONF_802154_AUTOACK 1 /* Reduce code size */ #undef ENERGEST_CONF_ON diff --git a/examples/ipv6/multicast/project-conf.h b/examples/ipv6/multicast/project-conf.h index 0c47ab538..41a74824b 100644 --- a/examples/ipv6/multicast/project-conf.h +++ b/examples/ipv6/multicast/project-conf.h @@ -46,7 +46,7 @@ /* 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 */ +/* For Imin: Use 16 over CSMA, 64 over Contiki MAC */ #define ROLL_TM_CONF_IMIN_1 64 #undef UIP_CONF_IPV6_RPL diff --git a/examples/ipv6/rpl-udp/project-conf.h b/examples/ipv6/rpl-udp/project-conf.h index 4015e45d5..2967dab34 100644 --- a/examples/ipv6/rpl-udp/project-conf.h +++ b/examples/ipv6/rpl-udp/project-conf.h @@ -47,8 +47,8 @@ #define UIP_CONF_MAX_ROUTES 10 #endif /* TEST_MORE_ROUTES */ -#undef NULLRDC_CONF_802154_AUTOACK -#define NULLRDC_CONF_802154_AUTOACK 1 +#undef CSMA_CONF_802154_AUTOACK +#define CSMA_CONF_802154_AUTOACK 1 /* Define as minutes */ #define RPL_CONF_DEFAULT_LIFETIME_UNIT 60 diff --git a/examples/platform-specific/jn516x/rpl/common-conf.h b/examples/platform-specific/jn516x/rpl/common-conf.h index b93bdaf98..b9b480fe7 100644 --- a/examples/platform-specific/jn516x/rpl/common-conf.h +++ b/examples/platform-specific/jn516x/rpl/common-conf.h @@ -34,7 +34,7 @@ #ifndef __COMMON_CONF_H__ #define __COMMON_CONF_H__ -#define MAC_CONFIG_NULLRDC 0 +#define MAC_CONFIG_CSMA 0 #define MAC_CONFIG_TSCH 1 /* Select a MAC configuration */ #define MAC_CONFIG MAC_CONFIG_TSCH @@ -42,7 +42,7 @@ #undef NETSTACK_CONF_MAC #undef NETSTACK_CONF_FRAMER -#if MAC_CONFIG == MAC_CONFIG_NULLRDC +#if MAC_CONFIG == MAC_CONFIG_CSMA #elif MAC_CONFIG == MAC_CONFIG_TSCH diff --git a/regression-tests/03-compile-nxp-ports/Makefile b/regression-tests/03-compile-nxp-ports/Makefile index 278378109..78d5328ed 100644 --- a/regression-tests/03-compile-nxp-ports/Makefile +++ b/regression-tests/03-compile-nxp-ports/Makefile @@ -1,7 +1,7 @@ EXAMPLESDIR=../../examples TOOLSDIR=../../tools -# build jn516x examples, covering IPv6, RPL, CoAP, Rime, Nullrdc, Contikimac +# build jn516x examples, covering IPv6, RPL, CoAP EXAMPLES = \ hello-world/jn516x \ platform-specific/jn516x/dr1175-sensors/jn516x \ diff --git a/regression-tests/08-ipv6/code-slip-radio/project-conf.h b/regression-tests/08-ipv6/code-slip-radio/project-conf.h index 2d7316736..e23c1bf3f 100644 --- a/regression-tests/08-ipv6/code-slip-radio/project-conf.h +++ b/regression-tests/08-ipv6/code-slip-radio/project-conf.h @@ -1,7 +1,7 @@ #ifndef __PROJECT_CONF_H__ #define __PROJECT_CONF_H__ -#define NULLRDC_CONF_802154_AUTOACK 1 +#define CSMA_CONF_802154_AUTOACK 1 #define RPL_CONF_DAO_ACK 1