From 4541d3e85bf69871da3db1adf8e0ccab11fb1c28 Mon Sep 17 00:00:00 2001 From: Adam Dunkels Date: Sun, 17 Mar 2013 23:42:06 +0100 Subject: [PATCH 1/4] Let the framer functions use ints instead of uint8_t to make them more generic --- core/net/mac/frame802154.c | 16 ++++++++-------- core/net/mac/frame802154.h | 6 +++--- core/net/mac/framer-802154.c | 4 ++-- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/core/net/mac/frame802154.c b/core/net/mac/frame802154.c index 345a779db..7807c4392 100644 --- a/core/net/mac/frame802154.c +++ b/core/net/mac/frame802154.c @@ -153,7 +153,7 @@ field_len(frame802154_t *p, field_length_t *flen) * * \return The length of the frame header. */ -uint8_t +int frame802154_hdrlen(frame802154_t *p) { field_length_t flen; @@ -176,8 +176,8 @@ frame802154_hdrlen(frame802154_t *p) * \return The length of the frame header or 0 if there was * insufficient space in the buffer for the frame headers. */ -uint8_t -frame802154_create(frame802154_t *p, uint8_t *buf, uint8_t buf_len) +int +frame802154_create(frame802154_t *p, uint8_t *buf, int buf_len) { int c; field_length_t flen; @@ -236,7 +236,7 @@ frame802154_create(frame802154_t *p, uint8_t *buf, uint8_t buf_len) /* pos += flen.aux_sec_len; */ } - return pos; + return (int)pos; } /*----------------------------------------------------------------------------*/ /** @@ -248,12 +248,12 @@ frame802154_create(frame802154_t *p, uint8_t *buf, uint8_t buf_len) * \param len The size of the input data * \param pf The frame802154_t struct to store the parsed frame information. */ -uint8_t -frame802154_parse(uint8_t *data, uint8_t len, frame802154_t *pf) +int +frame802154_parse(uint8_t *data, int len, frame802154_t *pf) { uint8_t *p; frame802154_fcf_t fcf; - uint8_t c; + int c; if(len < 3) { return 0; @@ -345,7 +345,7 @@ frame802154_parse(uint8_t *data, uint8_t len, frame802154_t *pf) /* header length */ c = p - data; /* payload length */ - pf->payload_len = len - c; + pf->payload_len = (uint8_t)(0xff & (len - c)); /* payload */ pf->payload = p; diff --git a/core/net/mac/frame802154.h b/core/net/mac/frame802154.h index 861b646a4..4d72ea15f 100644 --- a/core/net/mac/frame802154.h +++ b/core/net/mac/frame802154.h @@ -160,9 +160,9 @@ typedef struct { /* Prototypes */ -uint8_t frame802154_hdrlen(frame802154_t *p); -uint8_t frame802154_create(frame802154_t *p, uint8_t *buf, uint8_t buf_len); -uint8_t frame802154_parse(uint8_t *data, uint8_t length, frame802154_t *pf); +int frame802154_hdrlen(frame802154_t *p); +int frame802154_create(frame802154_t *p, uint8_t *buf, int buf_len); +int frame802154_parse(uint8_t *data, int length, frame802154_t *pf); /** @} */ #endif /* FRAME_802154_H */ diff --git a/core/net/mac/framer-802154.c b/core/net/mac/framer-802154.c index 67a7a700a..46c633d60 100644 --- a/core/net/mac/framer-802154.c +++ b/core/net/mac/framer-802154.c @@ -90,7 +90,7 @@ static int create(void) { frame802154_t params; - uint8_t len; + int len; /* init to zeros */ memset(¶ms, 0, sizeof(params)); @@ -174,7 +174,7 @@ create(void) PRINTF("15.4-OUT: %2X", params.fcf.frame_type); PRINTADDR(params.dest_addr.u8); - PRINTF("%u %u (%u)\n", len, packetbuf_datalen(), packetbuf_totlen()); + PRINTF("%d %u (%u)\n", len, packetbuf_datalen(), packetbuf_totlen()); return len; } else { From 5993595a8f42f5c09e9b64e842f530008e3b4c42 Mon Sep 17 00:00:00 2001 From: Adam Dunkels Date: Sun, 17 Mar 2013 23:47:00 +0100 Subject: [PATCH 2/4] A number of updates to nullrdc * add a few rimestats to keep track of sent and received acks * made a number of configuration options possible to override (ack timing) * added the logic for sending 802.15.4 link layer ack packets, despite not being able to guarentee the 802.15.4 MAC timing * increased the number of sequence numbers to keep track of for duplicate filtering --- core/net/mac/nullrdc.c | 54 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/core/net/mac/nullrdc.c b/core/net/mac/nullrdc.c index 1ba5d939b..41ab60ab8 100644 --- a/core/net/mac/nullrdc.c +++ b/core/net/mac/nullrdc.c @@ -42,6 +42,7 @@ #include "net/packetbuf.h" #include "net/queuebuf.h" #include "net/netstack.h" +#include "net/rime/rimestats.h" #include #define DEBUG 0 @@ -78,11 +79,30 @@ #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 -#define ACK_LEN 3 +#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/frame802154.h" +#endif /* NULLRDC_SEND_802154_ACK */ + +#define ACK_LEN 3 + #if NULLRDC_802154_AUTOACK || NULLRDC_802154_AUTOACK_HW struct seqno { rimeaddr_t sender; @@ -92,7 +112,7 @@ struct 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 +#define MAX_SEQNOS 8 #endif /* NETSTACK_CONF_MAC_SEQNO_HISTORY */ static struct seqno received_seqnos[MAX_SEQNOS]; @@ -135,8 +155,11 @@ send_packet(mac_callback_t sent, void *ptr) 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) { @@ -165,13 +188,16 @@ send_packet(mac_callback_t sent, void *ptr) 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: @@ -224,7 +250,7 @@ packet_input(void) #if NULLRDC_802154_AUTOACK if(packetbuf_datalen() == ACK_LEN) { /* Ignore ack packets */ - /* PRINTF("nullrdc: ignored ack\n"); */ + PRINTF("nullrdc: ignored ack\n"); } else #endif /* NULLRDC_802154_AUTOACK */ if(NETSTACK_FRAMER.parse() < 0) { @@ -259,6 +285,24 @@ packet_input(void) rimeaddr_copy(&received_seqnos[0].sender, packetbuf_addr(PACKETBUF_ADDR_SENDER)); #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 && + rimeaddr_cmp((rimeaddr_t *)&info154.dest_addr, + &rimeaddr_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 */ NETSTACK_MAC.input(); } } From cb2336a322d456be031636a7302ff643973a3c3a Mon Sep 17 00:00:00 2001 From: Adam Dunkels Date: Sun, 17 Mar 2013 23:52:42 +0100 Subject: [PATCH 3/4] Send announcements only if the node is configured to be a router --- core/net/rime/collect.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/core/net/rime/collect.c b/core/net/rime/collect.c index 0b226af14..0c743f388 100644 --- a/core/net/rime/collect.c +++ b/core/net/rime/collect.c @@ -641,8 +641,10 @@ send_queued_packet(struct collect_conn *c) ctimer_set(&c->transmit_after_scan_timer, ANNOUNCEMENT_SCAN_TIME, send_queued_packet, c); #else /* COLLECT_CONF_WITH_LISTEN */ - announcement_set_value(&c->announcement, RTMETRIC_MAX); - announcement_bump(&c->announcement); + if(c->is_router) { + announcement_set_value(&c->announcement, RTMETRIC_MAX); + announcement_bump(&c->announcement); + } #endif /* COLLECT_CONF_WITH_LISTEN */ #endif /* COLLECT_ANNOUNCEMENTS */ } @@ -1256,7 +1258,9 @@ received_announcement(struct announcement *a, const rimeaddr_t *from, #if ! COLLECT_CONF_WITH_LISTEN if(value == RTMETRIC_MAX && tc->rtmetric != RTMETRIC_MAX) { - announcement_bump(&tc->announcement); + if(tc->is_router) { + announcement_bump(&tc->announcement); + } } #endif /* COLLECT_CONF_WITH_LISTEN */ } @@ -1302,7 +1306,9 @@ collect_open(struct collect_conn *tc, uint16_t channels, announcement_register(&tc->announcement, channels, received_announcement); #if ! COLLECT_CONF_WITH_LISTEN - announcement_set_value(&tc->announcement, RTMETRIC_MAX); + if(tc->is_router) { + announcement_set_value(&tc->announcement, RTMETRIC_MAX); + } #endif /* COLLECT_CONF_WITH_LISTEN */ #endif /* !COLLECT_ANNOUNCEMENTS */ @@ -1470,8 +1476,10 @@ collect_send(struct collect_conn *tc, int rexmits) ctimer_set(&tc->transmit_after_scan_timer, ANNOUNCEMENT_SCAN_TIME, send_queued_packet, tc); #else /* COLLECT_CONF_WITH_LISTEN */ - announcement_set_value(&tc->announcement, RTMETRIC_MAX); - announcement_bump(&tc->announcement); + if(tc->is_router) { + announcement_set_value(&tc->announcement, RTMETRIC_MAX); + announcement_bump(&tc->announcement); + } #endif /* COLLECT_CONF_WITH_LISTEN */ #endif /* COLLECT_ANNOUNCEMENTS */ From 3efa84ecc81e6b925e67350e82a8441f3931c45b Mon Sep 17 00:00:00 2001 From: Adam Dunkels Date: Sun, 17 Mar 2013 23:55:01 +0100 Subject: [PATCH 4/4] New mechanism for computing the 6lowpan header length dynamically, depending on how large header the framer creates. Also check the incoming packet for buffer overflow. --- core/net/sicslowpan.c | 46 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/core/net/sicslowpan.c b/core/net/sicslowpan.c index 2bb94574f..1f196c304 100644 --- a/core/net/sicslowpan.c +++ b/core/net/sicslowpan.c @@ -163,7 +163,11 @@ void uip_log(char *msg); /** \brief Size of the 802.15.4 payload (127byte - 25 for MAC header) */ +#ifdef SICSLOWPAN_CONF_MAC_MAX_PAYLOAD +#define MAC_MAX_PAYLOAD SICSLOWPAN_CONF_MAC_MAX_PAYLOAD +#else /* SICSLOWPAN_CONF_MAC_MAX_PAYLOAD */ #define MAC_MAX_PAYLOAD 102 +#endif /* SICSLOWPAN_CONF_MAC_MAX_PAYLOAD */ /** \brief Some MAC layers need a minimum payload, which is @@ -1355,6 +1359,8 @@ send_packet(rimeaddr_t *dest) static uint8_t output(uip_lladdr_t *localdest) { + int framer_hdrlen; + /* The MAC address of the destination of the packet */ rimeaddr_t dest; @@ -1422,7 +1428,24 @@ output(uip_lladdr_t *localdest) } PRINTFO("sicslowpan output: header of len %d\n", rime_hdr_len); - if(uip_len - uncomp_hdr_len > MAC_MAX_PAYLOAD - rime_hdr_len) { + /* Calculate NETSTACK_FRAMER's header length, that will be added in the NETSTACK_RDC. + * We calculate it here only to make a better decision of whether the outgoing packet + * needs to be fragmented or not. */ +#define USE_FRAMER_HDRLEN 1 +#if USE_FRAMER_HDRLEN + packetbuf_clear(); + packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &dest); + framer_hdrlen = NETSTACK_FRAMER.create(); + if(framer_hdrlen < 0) { + /* Framing failed, we assume the maximum header length */ + framer_hdrlen = 21; + } + packetbuf_clear(); +#else /* USE_FRAMER_HDRLEN */ + framer_hdrlen = 21; +#endif /* USE_FRAMER_HDRLEN */ + + if((int)uip_len - (int)uncomp_hdr_len > (int)MAC_MAX_PAYLOAD - framer_hdrlen - (int)rime_hdr_len) { #if SICSLOWPAN_CONF_FRAG struct queuebuf *q; /* @@ -1434,7 +1457,7 @@ output(uip_lladdr_t *localdest) */ PRINTFO("Fragmentation sending packet len %d\n", uip_len); - + /* Create 1st Fragment */ PRINTFO("sicslowpan output: 1rst fragment "); @@ -1455,7 +1478,7 @@ output(uip_lladdr_t *localdest) /* Copy payload and send */ rime_hdr_len += SICSLOWPAN_FRAG1_HDR_LEN; - rime_payload_len = (MAC_MAX_PAYLOAD - rime_hdr_len) & 0xf8; + rime_payload_len = (MAC_MAX_PAYLOAD - framer_hdrlen - rime_hdr_len) & 0xf8; PRINTFO("(len %d, tag %d)\n", rime_payload_len, my_tag); memcpy(rime_ptr + rime_hdr_len, (uint8_t *)UIP_IP_BUF + uncomp_hdr_len, rime_payload_len); @@ -1491,7 +1514,7 @@ output(uip_lladdr_t *localdest) /* uip_htons((SICSLOWPAN_DISPATCH_FRAGN << 8) | uip_len); */ SET16(RIME_FRAG_PTR, RIME_FRAG_DISPATCH_SIZE, ((SICSLOWPAN_DISPATCH_FRAGN << 8) | uip_len)); - rime_payload_len = (MAC_MAX_PAYLOAD - rime_hdr_len) & 0xf8; + rime_payload_len = (MAC_MAX_PAYLOAD - framer_hdrlen - rime_hdr_len) & 0xf8; while(processed_ip_out_len < uip_len) { PRINTFO("sicslowpan output: fragment "); RIME_FRAG_PTR[RIME_FRAG_OFFSET] = processed_ip_out_len >> 3; @@ -1530,6 +1553,7 @@ output(uip_lladdr_t *localdest) return 0; #endif /* SICSLOWPAN_CONF_FRAG */ } else { + /* * The packet does not need to be fragmented * copy "payload" and send @@ -1709,6 +1733,20 @@ input(void) return; } rime_payload_len = packetbuf_datalen() - rime_hdr_len; + + /* Sanity-check size of incoming packet to avoid buffer overflow */ + { + int req_size = UIP_LLH_LEN + uncomp_hdr_len + (uint16_t)(frag_offset << 3) + + rime_payload_len; + if(req_size > sizeof(sicslowpan_buf)) { + PRINTF( + "SICSLOWPAN: packet dropped, minimum required SICSLOWPAN_IP_BUF size: %d+%d+%d+%d=%d (current size: %d)\n", + UIP_LLH_LEN, uncomp_hdr_len, (uint16_t)(frag_offset << 3), + rime_payload_len, req_size, sizeof(sicslowpan_buf)); + return; + } + } + memcpy((uint8_t *)SICSLOWPAN_IP_BUF + uncomp_hdr_len + (uint16_t)(frag_offset << 3), rime_ptr + rime_hdr_len, rime_payload_len); /* update processed_ip_in_len if fragment, sicslowpan_len otherwise */