Added support for IEEE 802.15.4 frame version 2

This commit is contained in:
Simon Duquennoy 2015-09-21 18:39:30 +02:00
parent f86494c6aa
commit 5cf9871d5b
4 changed files with 338 additions and 89 deletions

View file

@ -85,6 +85,12 @@
#define LLSEC802154_USES_EXPLICIT_KEYS 0 #define LLSEC802154_USES_EXPLICIT_KEYS 0
#endif /* LLSEC802154_CONF_USES_EXPLICIT_KEYS */ #endif /* LLSEC802154_CONF_USES_EXPLICIT_KEYS */
#ifdef LLSEC802154_CONF_USES_FRAME_COUNTER
#define LLSEC802154_USES_FRAME_COUNTER LLSEC802154_CONF_USES_FRAME_COUNTER
#else /* LLSEC802154_CONF_USES_FRAME_COUNTER */
#define LLSEC802154_USES_FRAME_COUNTER (LLSEC802154_SECURITY_LEVEL != FRAME802154_SECURITY_LEVEL_NONE)
#endif /* LLSEC802154_CONF_USES_FRAME_COUNTER */
#if UIP_BYTE_ORDER == UIP_LITTLE_ENDIAN #if UIP_BYTE_ORDER == UIP_LITTLE_ENDIAN
#define LLSEC802154_HTONS(n) (n) #define LLSEC802154_HTONS(n) (n)
#define LLSEC802154_HTONL(n) (n) #define LLSEC802154_HTONL(n) (n)

View file

@ -44,11 +44,11 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
* *
*/ */
/* /*
* \brief This file is where the main functions that relate to frame * \brief This file is where the main functions that relate to frame
* manipulation will reside. * manipulation will reside.
*/ */
/** /**
* \file * \file
@ -61,7 +61,7 @@
/** /**
* \addtogroup frame802154 * \addtogroup frame802154
* @{ * @{
*/ */
#include "sys/cc.h" #include "sys/cc.h"
#include "net/mac/frame802154.h" #include "net/mac/frame802154.h"
@ -69,11 +69,18 @@
#include "net/linkaddr.h" #include "net/linkaddr.h"
#include <string.h> #include <string.h>
/** \brief The 16-bit identifier of the PAN on which the device is
* operating. If this value is 0xffff, the device is not
* associated.
*/
static uint16_t mac_pan_id = IEEE802154_PANID;
/** /**
* \brief Structure that contains the lengths of the various addressing and security fields * \brief Structure that contains the lengths of the various addressing and security fields
* in the 802.15.4 header. This structure is used in \ref frame802154_create() * in the 802.15.4 header. This structure is used in \ref frame802154_create()
*/ */
typedef struct { typedef struct {
uint8_t seqno_len; /**< Length (in bytes) of sequence number field */
uint8_t dest_pid_len; /**< Length (in bytes) of destination PAN ID field */ uint8_t dest_pid_len; /**< Length (in bytes) of destination PAN ID field */
uint8_t dest_addr_len; /**< Length (in bytes) of destination address field */ uint8_t dest_addr_len; /**< Length (in bytes) of destination address field */
uint8_t src_pid_len; /**< Length (in bytes) of source PAN ID field */ uint8_t src_pid_len; /**< Length (in bytes) of source PAN ID field */
@ -111,30 +118,199 @@ get_key_id_len(uint8_t key_id_mode)
} }
} }
#endif /* LLSEC802154_USES_EXPLICIT_KEYS */ #endif /* LLSEC802154_USES_EXPLICIT_KEYS */
/*---------------------------------------------------------------------------*/
/* Get current PAN ID */
uint16_t
frame802154_get_pan_id(void)
{
return mac_pan_id;
}
/*---------------------------------------------------------------------------*/
/* Set current PAN ID */
void
frame802154_set_pan_id(uint16_t pan_id)
{
mac_pan_id = pan_id;
}
/*----------------------------------------------------------------------------*/
/* Tells whether a given Frame Control Field indicates a frame with
* source PANID and/or destination PANID */
void
frame802154_has_panid(frame802154_fcf_t *fcf, int *has_src_pan_id, int *has_dest_pan_id)
{
int src_pan_id = 0;
int dest_pan_id = 0;
if(fcf == NULL) {
return;
}
if(fcf->frame_version == FRAME802154_IEEE802154E_2012) {
if(!fcf->panid_compression) {
/* Compressed PAN ID == no PAN ID at all */
if(fcf->dest_addr_mode == fcf->dest_addr_mode) {
/* No address or both addresses: include destination PAN ID */
dest_pan_id = 1;
} else if(fcf->dest_addr_mode) {
/* Only dest address, include dest PAN ID */
dest_pan_id = 1;
} else if(fcf->src_addr_mode) {
/* Only src address, include src PAN ID */
src_pan_id = 1;
}
}
if(fcf->dest_addr_mode == 0 && fcf->dest_addr_mode == 1) {
/* No address included, include dest PAN ID conditionally */
if(!fcf->panid_compression) {
dest_pan_id = 1;
}
}
/* Remove the following rule the day rows 2 and 3 from table 2a are fixed: */
if(fcf->dest_addr_mode == 0 && fcf->dest_addr_mode == 0) {
/* Not meaningful, we include a PAN ID iff the compress flag is set, but
* this is what the standard currently stipulates */
dest_pan_id = fcf->panid_compression;
}
} else {
/* No PAN ID in ACK */
if(fcf->frame_type != FRAME802154_ACKFRAME) {
if(!fcf->panid_compression && fcf->src_addr_mode & 3) {
/* If compressed, don't inclue source PAN ID */
src_pan_id = 1;
}
if(fcf->dest_addr_mode & 3) {
dest_pan_id = 1;
}
}
}
if(has_src_pan_id != NULL) {
*has_src_pan_id = src_pan_id;
}
if(has_dest_pan_id != NULL) {
*has_dest_pan_id = dest_pan_id;
}
}
/*---------------------------------------------------------------------------*/
/* Check if the destination PAN ID, if any, matches ours */
int
frame802154_check_dest_panid(frame802154_t *frame)
{
int has_dest_panid;
if(frame == NULL) {
return 0;
}
frame802154_has_panid(&frame->fcf, NULL, &has_dest_panid);
if(has_dest_panid
&& frame->dest_pid != frame802154_get_pan_id()
&& frame->dest_pid != FRAME802154_BROADCASTPANDID) {
/* Packet to another PAN */
return 0;
}
return 1;
}
/*---------------------------------------------------------------------------*/
/* Check is the address is a broadcast address, whatever its size */
int
frame802154_is_broadcast_addr(uint8_t mode, uint8_t *addr)
{
int i = mode == FRAME802154_SHORTADDRMODE ? 2 : 8;
while(i-- > 0) {
if(addr[i] != 0xff) {
return 0;
}
}
return 1;
}
/*---------------------------------------------------------------------------*/
/* Check and extract source and destination linkaddr from frame */
int
frame802154_extract_linkaddr(frame802154_t *frame,
linkaddr_t *source_address, linkaddr_t *dest_address)
{
int src_addr_len;
int dest_addr_len;
if(frame == NULL) {
return 0;
}
/* Check and extract source address */
src_addr_len = frame->fcf.src_addr_mode ?
((frame->fcf.src_addr_mode == FRAME802154_SHORTADDRMODE) ? 2 : 8) : 0;
if(src_addr_len == 0 || frame802154_is_broadcast_addr(frame->fcf.src_addr_mode, frame->src_addr)) {
/* Broadcast address */
if(source_address != NULL) {
linkaddr_copy(source_address, &linkaddr_null);
}
} else {
/* Unicast address */
if(src_addr_len != LINKADDR_SIZE) {
/* Destination address has a size we can not handle */
return 0;
}
if(source_address != NULL) {
linkaddr_copy(source_address, (linkaddr_t *)frame->src_addr);
}
}
/* Check and extract destination address */
dest_addr_len = frame->fcf.dest_addr_mode ?
((frame->fcf.dest_addr_mode == FRAME802154_SHORTADDRMODE) ? 2 : 8) : 0;
if(dest_addr_len == 0 || frame802154_is_broadcast_addr(frame->fcf.dest_addr_mode, frame->dest_addr)) {
/* Broadcast address */
if(dest_address != NULL) {
linkaddr_copy(dest_address, &linkaddr_null);
}
} else {
/* Unicast address */
if(dest_addr_len != LINKADDR_SIZE) {
/* Destination address has a size we can not handle */
return 0;
}
if(dest_address != NULL) {
linkaddr_copy(dest_address, (linkaddr_t *)frame->dest_addr);
}
}
return 1;
}
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
static void static void
field_len(frame802154_t *p, field_length_t *flen) field_len(frame802154_t *p, field_length_t *flen)
{ {
int has_src_panid;
int has_dest_panid;
/* init flen to zeros */ /* init flen to zeros */
memset(flen, 0, sizeof(field_length_t)); memset(flen, 0, sizeof(field_length_t));
/* Determine lengths of each field based on fcf and other args */ /* Determine lengths of each field based on fcf and other args */
if(p->fcf.dest_addr_mode & 3) { if((p->fcf.sequence_number_suppression & 1) == 0) {
flen->dest_pid_len = 2; flen->seqno_len = 1;
} }
if(p->fcf.src_addr_mode & 3) {
/* IEEE802.15.4e changes the meaning of PAN ID Compression (see Table 2a).
* In this case, we leave the decision whether to compress PAN ID or not
* up to the caller. */
if(p->fcf.frame_version < FRAME802154_IEEE802154E_2012) {
/* Set PAN ID compression bit if src pan id matches dest pan id. */
if(p->fcf.dest_addr_mode & 3 && p->fcf.src_addr_mode & 3 &&
p->src_pid == p->dest_pid) {
p->fcf.panid_compression = 1;
} else {
p->fcf.panid_compression = 0;
}
}
frame802154_has_panid(&p->fcf, &has_src_panid, &has_dest_panid);
if(has_src_panid) {
flen->src_pid_len = 2; flen->src_pid_len = 2;
} }
/* Set PAN ID compression bit if src pan id matches dest pan id. */ if(has_dest_panid) {
if(p->fcf.dest_addr_mode & 3 && p->fcf.src_addr_mode & 3 && flen->dest_pid_len = 2;
p->src_pid == p->dest_pid) {
p->fcf.panid_compression = 1;
/* compressed header, only do dest pid */
flen->src_pid_len = 0;
} else {
p->fcf.panid_compression = 0;
} }
/* determine address lengths */ /* determine address lengths */
@ -144,9 +320,16 @@ field_len(frame802154_t *p, field_length_t *flen)
#if LLSEC802154_SECURITY_LEVEL #if LLSEC802154_SECURITY_LEVEL
/* Aux security header */ /* Aux security header */
if(p->fcf.security_enabled & 1) { if(p->fcf.security_enabled & 1) {
flen->aux_sec_len = 5 flen->aux_sec_len = 1; /* FCF + possibly frame counter and key ID */
if(p->aux_hdr.security_control.frame_counter_suppression == 0) {
if(p->aux_hdr.security_control.frame_counter_size == 1) {
flen->aux_sec_len += 5;
} else {
flen->aux_sec_len += 4;
}
}
#if LLSEC802154_USES_EXPLICIT_KEYS #if LLSEC802154_USES_EXPLICIT_KEYS
+ get_key_id_len(p->aux_hdr.security_control.key_id_mode); flen->aux_sec_len += get_key_id_len(p->aux_hdr.security_control.key_id_mode);
#endif /* LLSEC802154_USES_EXPLICIT_KEYS */ #endif /* LLSEC802154_USES_EXPLICIT_KEYS */
; ;
} }
@ -161,14 +344,14 @@ field_len(frame802154_t *p, field_length_t *flen)
* frame to send. * frame to send.
* *
* \return The length of the frame header. * \return The length of the frame header.
*/ */
int int
frame802154_hdrlen(frame802154_t *p) frame802154_hdrlen(frame802154_t *p)
{ {
field_length_t flen; field_length_t flen;
field_len(p, &flen); field_len(p, &flen);
return 3 + flen.dest_pid_len + flen.dest_addr_len + return 2 + flen.seqno_len + flen.dest_pid_len + flen.dest_addr_len +
flen.src_pid_len + flen.src_addr_len + flen.aux_sec_len; flen.src_pid_len + flen.src_addr_len + flen.aux_sec_len;
} }
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
/** /**
@ -181,7 +364,7 @@ frame802154_hdrlen(frame802154_t *p)
* \param buf Pointer to the buffer to use for the frame. * \param buf Pointer to the buffer to use for the frame.
* *
* \return The length of the frame header * \return The length of the frame header
*/ */
int int
frame802154_create(frame802154_t *p, uint8_t *buf) frame802154_create(frame802154_t *p, uint8_t *buf)
{ {
@ -193,7 +376,7 @@ frame802154_create(frame802154_t *p, uint8_t *buf)
#endif /* LLSEC802154_USES_EXPLICIT_KEYS */ #endif /* LLSEC802154_USES_EXPLICIT_KEYS */
field_len(p, &flen); field_len(p, &flen);
/* OK, now we have field lengths. Time to actually construct */ /* OK, now we have field lengths. Time to actually construct */
/* the outgoing frame, and store it in buf */ /* the outgoing frame, and store it in buf */
buf[0] = (p->fcf.frame_type & 7) | buf[0] = (p->fcf.frame_type & 7) |
@ -201,13 +384,18 @@ frame802154_create(frame802154_t *p, uint8_t *buf)
((p->fcf.frame_pending & 1) << 4) | ((p->fcf.frame_pending & 1) << 4) |
((p->fcf.ack_required & 1) << 5) | ((p->fcf.ack_required & 1) << 5) |
((p->fcf.panid_compression & 1) << 6); ((p->fcf.panid_compression & 1) << 6);
buf[1] = ((p->fcf.dest_addr_mode & 3) << 2) | buf[1] = ((p->fcf.sequence_number_suppression & 1)) |
((p->fcf.ie_list_present & 1)) << 1 |
((p->fcf.dest_addr_mode & 3) << 2) |
((p->fcf.frame_version & 3) << 4) | ((p->fcf.frame_version & 3) << 4) |
((p->fcf.src_addr_mode & 3) << 6); ((p->fcf.src_addr_mode & 3) << 6);
/* sequence number */ pos = 2;
buf[2] = p->seq;
pos = 3; /* Sequence number */
if(flen.seqno_len == 1) {
buf[pos++] = p->seq;
}
/* Destination PAN ID */ /* Destination PAN ID */
if(flen.dest_pid_len == 2) { if(flen.dest_pid_len == 2) {
@ -230,17 +418,24 @@ frame802154_create(frame802154_t *p, uint8_t *buf)
for(c = flen.src_addr_len; c > 0; c--) { for(c = flen.src_addr_len; c > 0; c--) {
buf[pos++] = p->src_addr[c - 1]; buf[pos++] = p->src_addr[c - 1];
} }
#if LLSEC802154_SECURITY_LEVEL #if LLSEC802154_SECURITY_LEVEL
/* Aux header */ /* Aux header */
if(flen.aux_sec_len) { if(flen.aux_sec_len) {
buf[pos++] = p->aux_hdr.security_control.security_level buf[pos++] = p->aux_hdr.security_control.security_level
#if LLSEC802154_USES_EXPLICIT_KEYS #if LLSEC802154_USES_EXPLICIT_KEYS
| (p->aux_hdr.security_control.key_id_mode << 3) | (p->aux_hdr.security_control.key_id_mode << 3)
#endif /* LLSEC802154_USES_EXPLICIT_KEYS */ #endif /* LLSEC802154_USES_EXPLICIT_KEYS */
| (p->aux_hdr.security_control.frame_counter_suppression << 5)
| (p->aux_hdr.security_control.frame_counter_size << 6)
; ;
memcpy(buf + pos, p->aux_hdr.frame_counter.u8, 4); if(p->aux_hdr.security_control.frame_counter_suppression == 0) {
pos += 4; /* We support only 4-byte counters */
memcpy(buf + pos, p->aux_hdr.frame_counter.u8, 4);
pos += 4;
if(p->aux_hdr.security_control.frame_counter_size == 1) {
pos++;
}
}
#if LLSEC802154_USES_EXPLICIT_KEYS #if LLSEC802154_USES_EXPLICIT_KEYS
key_id_mode = p->aux_hdr.security_control.key_id_mode; key_id_mode = p->aux_hdr.security_control.key_id_mode;
@ -272,11 +467,13 @@ frame802154_parse(uint8_t *data, int len, frame802154_t *pf)
uint8_t *p; uint8_t *p;
frame802154_fcf_t fcf; frame802154_fcf_t fcf;
int c; int c;
int has_src_panid;
int has_dest_panid;
#if LLSEC802154_USES_EXPLICIT_KEYS #if LLSEC802154_USES_EXPLICIT_KEYS
uint8_t key_id_mode; uint8_t key_id_mode;
#endif /* LLSEC802154_USES_EXPLICIT_KEYS */ #endif /* LLSEC802154_USES_EXPLICIT_KEYS */
if(len < 3) { if(len < 2) {
return 0; return 0;
} }
@ -289,20 +486,32 @@ frame802154_parse(uint8_t *data, int len, frame802154_t *pf)
fcf.ack_required = (p[0] >> 5) & 1; fcf.ack_required = (p[0] >> 5) & 1;
fcf.panid_compression = (p[0] >> 6) & 1; fcf.panid_compression = (p[0] >> 6) & 1;
fcf.sequence_number_suppression = p[1] & 1;
fcf.ie_list_present = (p[1] >> 1) & 1;
fcf.dest_addr_mode = (p[1] >> 2) & 3; fcf.dest_addr_mode = (p[1] >> 2) & 3;
fcf.frame_version = (p[1] >> 4) & 3; fcf.frame_version = (p[1] >> 4) & 3;
fcf.src_addr_mode = (p[1] >> 6) & 3; fcf.src_addr_mode = (p[1] >> 6) & 3;
/* copy fcf and seqNum */ /* copy fcf and seqNum */
memcpy(&pf->fcf, &fcf, sizeof(frame802154_fcf_t)); memcpy(&pf->fcf, &fcf, sizeof(frame802154_fcf_t));
pf->seq = p[2]; p += 2; /* Skip first two bytes */
p += 3; /* Skip first three bytes */
if(fcf.sequence_number_suppression == 0) {
pf->seq = p[0];
p++;
}
frame802154_has_panid(&fcf, &has_src_panid, &has_dest_panid);
/* Destination address, if any */ /* Destination address, if any */
if(fcf.dest_addr_mode) { if(fcf.dest_addr_mode) {
/* Destination PAN */ if(has_dest_panid) {
pf->dest_pid = p[0] + (p[1] << 8); /* Destination PAN */
p += 2; pf->dest_pid = p[0] + (p[1] << 8);
p += 2;
} else {
pf->dest_pid = 0;
}
/* Destination address */ /* Destination address */
/* l = addr_len(fcf.dest_addr_mode); */ /* l = addr_len(fcf.dest_addr_mode); */
@ -329,9 +538,12 @@ frame802154_parse(uint8_t *data, int len, frame802154_t *pf)
/* Source address, if any */ /* Source address, if any */
if(fcf.src_addr_mode) { if(fcf.src_addr_mode) {
/* Source PAN */ /* Source PAN */
if(!fcf.panid_compression) { if(has_src_panid) {
pf->src_pid = p[0] + (p[1] << 8); pf->src_pid = p[0] + (p[1] << 8);
p += 2; p += 2;
if(!has_dest_panid) {
pf->dest_pid = pf->src_pid;
}
} else { } else {
pf->src_pid = pf->dest_pid; pf->src_pid = pf->dest_pid;
} }
@ -357,18 +569,25 @@ frame802154_parse(uint8_t *data, int len, frame802154_t *pf)
linkaddr_copy((linkaddr_t *)&(pf->src_addr), &linkaddr_null); linkaddr_copy((linkaddr_t *)&(pf->src_addr), &linkaddr_null);
pf->src_pid = 0; pf->src_pid = 0;
} }
#if LLSEC802154_SECURITY_LEVEL #if LLSEC802154_SECURITY_LEVEL
if(fcf.security_enabled) { if(fcf.security_enabled) {
pf->aux_hdr.security_control.security_level = p[0] & 7; pf->aux_hdr.security_control.security_level = p[0] & 7;
#if LLSEC802154_USES_EXPLICIT_KEYS #if LLSEC802154_USES_EXPLICIT_KEYS
pf->aux_hdr.security_control.key_id_mode = (p[0] >> 3) & 3; pf->aux_hdr.security_control.key_id_mode = (p[0] >> 3) & 3;
#endif /* LLSEC802154_USES_EXPLICIT_KEYS */ #endif /* LLSEC802154_USES_EXPLICIT_KEYS */
pf->aux_hdr.security_control.frame_counter_suppression = p[0] >> 5;
pf->aux_hdr.security_control.frame_counter_size = p[0] >> 6;
p += 1; p += 1;
memcpy(pf->aux_hdr.frame_counter.u8, p, 4); if(pf->aux_hdr.security_control.frame_counter_suppression == 0) {
p += 4; memcpy(pf->aux_hdr.frame_counter.u8, p, 4);
p += 4;
if(pf->aux_hdr.security_control.frame_counter_size == 1) {
p ++;
}
}
#if LLSEC802154_USES_EXPLICIT_KEYS #if LLSEC802154_USES_EXPLICIT_KEYS
key_id_mode = pf->aux_hdr.security_control.key_id_mode; key_id_mode = pf->aux_hdr.security_control.key_id_mode;
if(key_id_mode) { if(key_id_mode) {

View file

@ -41,7 +41,7 @@
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * 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 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
/** /**
* \addtogroup net * \addtogroup net
@ -59,14 +59,14 @@
* This file converts to and from a structure to a packed 802.15.4 * This file converts to and from a structure to a packed 802.15.4
* frame. * frame.
* *
*/ */
/* Includes */ /* Includes */
#ifndef FRAME_802154_H #ifndef FRAME_802154_H
#define FRAME_802154_H #define FRAME_802154_H
#include "contiki-conf.h" #include "contiki-conf.h"
#include "net/linkaddr.h"
#ifdef IEEE802154_CONF_PANID #ifdef IEEE802154_CONF_PANID
#define IEEE802154_PANID IEEE802154_CONF_PANID #define IEEE802154_PANID IEEE802154_CONF_PANID
@ -74,6 +74,18 @@
#define IEEE802154_PANID 0xABCD #define IEEE802154_PANID 0xABCD
#endif /* IEEE802154_CONF_PANID */ #endif /* IEEE802154_CONF_PANID */
#ifdef FRAME802154_CONF_VERSION
#define FRAME802154_VERSION FRAME802154_CONF_VERSION
#else /* FRAME802154_CONF_VERSION */
#define FRAME802154_VERSION FRAME802154_IEEE802154_2006
#endif /* FRAME802154_CONF_VERSION */
#ifdef FRAME802154_CONF_SUPPR_SEQNO
#define FRAME802154_SUPPR_SEQNO FRAME802154_CONF_SUPPR_SEQNO
#else /* FRAME802154_CONF_SUPPR_SEQNO */
#define FRAME802154_SUPPR_SEQNO 0
#endif /* FRAME802154_CONF_SUPPR_SEQNO */
/* Macros & Defines */ /* Macros & Defines */
/** \brief These are some definitions of values used in the FCF. See the 802.15.4 spec for details. /** \brief These are some definitions of values used in the FCF. See the 802.15.4 spec for details.
@ -97,8 +109,9 @@
#define FRAME802154_BROADCASTADDR (0xFFFF) #define FRAME802154_BROADCASTADDR (0xFFFF)
#define FRAME802154_BROADCASTPANDID (0xFFFF) #define FRAME802154_BROADCASTPANDID (0xFFFF)
#define FRAME802154_IEEE802154_2003 (0x00) #define FRAME802154_IEEE802154_2003 (0x00)
#define FRAME802154_IEEE802154_2006 (0x01) #define FRAME802154_IEEE802154_2006 (0x01)
#define FRAME802154_IEEE802154E_2012 (0x02)
#define FRAME802154_SECURITY_LEVEL_NONE (0) #define FRAME802154_SECURITY_LEVEL_NONE (0)
#define FRAME802154_SECURITY_LEVEL_MIC_32 (1) #define FRAME802154_SECURITY_LEVEL_MIC_32 (1)
@ -125,7 +138,7 @@
* 3. Addressing fields - 4 - 20 bytes - Variable * 3. Addressing fields - 4 - 20 bytes - Variable
* 4. Aux security header - 0 - 14 bytes - Variable * 4. Aux security header - 0 - 14 bytes - Variable
* 5. CRC - 2 bytes - Fixed * 5. CRC - 2 bytes - Fixed
*/ */
/** /**
* \brief Defines the bitfields of the frame control field (FCF). * \brief Defines the bitfields of the frame control field (FCF).
@ -136,7 +149,9 @@ typedef struct {
uint8_t frame_pending; /**< 1 bit. True if sender has more data to send */ uint8_t frame_pending; /**< 1 bit. True if sender has more data to send */
uint8_t ack_required; /**< 1 bit. Is an ack frame required? */ uint8_t ack_required; /**< 1 bit. Is an ack frame required? */
uint8_t panid_compression; /**< 1 bit. Is this a compressed header? */ uint8_t panid_compression; /**< 1 bit. Is this a compressed header? */
/* uint8_t reserved; */ /**< 3 bit. Unused bits */ /* uint8_t reserved; */ /**< 1 bit. Unused bit */
uint8_t sequence_number_suppression; /**< 1 bit. Does the header omit sequence number?, see 802.15.4e */
uint8_t ie_list_present; /**< 1 bit. Does the header contain Information Elements?, see 802.15.4e */
uint8_t dest_addr_mode; /**< 2 bit. Destination address mode, see 802.15.4 */ uint8_t dest_addr_mode; /**< 2 bit. Destination address mode, see 802.15.4 */
uint8_t frame_version; /**< 2 bit. 802.15.4 frame version */ uint8_t frame_version; /**< 2 bit. 802.15.4 frame version */
uint8_t src_addr_mode; /**< 2 bit. Source address mode, see 802.15.4 */ uint8_t src_addr_mode; /**< 2 bit. Source address mode, see 802.15.4 */
@ -146,6 +161,8 @@ typedef struct {
typedef struct { typedef struct {
uint8_t security_level; /**< 3 bit. security level */ uint8_t security_level; /**< 3 bit. security level */
uint8_t key_id_mode; /**< 2 bit. Key identifier mode */ uint8_t key_id_mode; /**< 2 bit. Key identifier mode */
uint8_t frame_counter_suppression; /**< 1 bit. Frame counter suppression */
uint8_t frame_counter_size; /**< 1 bit. Frame counter size (0: 4 bytes, 1: 5 bytes) */
uint8_t reserved; /**< 3 bit. Reserved bits */ uint8_t reserved; /**< 3 bit. Reserved bits */
} frame802154_scf_t; } frame802154_scf_t;
@ -193,6 +210,20 @@ int frame802154_hdrlen(frame802154_t *p);
int frame802154_create(frame802154_t *p, uint8_t *buf); int frame802154_create(frame802154_t *p, uint8_t *buf);
int frame802154_parse(uint8_t *data, int length, frame802154_t *pf); int frame802154_parse(uint8_t *data, int length, frame802154_t *pf);
/* Get current PAN ID */
uint16_t frame802154_get_pan_id(void);
/* Set current PAN ID */
void frame802154_set_pan_id(uint16_t pan_id);
/* Tells whether a given Frame Control Field indicates a frame with
* source PANID and/or destination PANID */
void frame802154_has_panid(frame802154_fcf_t *fcf, int *has_src_pan_id, int *has_dest_pan_id);
/* Check if the destination PAN ID, if any, matches ours */
int frame802154_check_dest_panid(frame802154_t *frame);
/* Check is the address is a broadcast address, whatever its size */
int frame802154_is_broadcast_addr(uint8_t mode, uint8_t *addr);
/* Check and extract source and destination linkaddr from frame */
int frame802154_extract_linkaddr(frame802154_t *frame, linkaddr_t *source_address, linkaddr_t *dest_address);
/** @} */ /** @} */
#endif /* FRAME_802154_H */ #endif /* FRAME_802154_H */
/** @} */ /** @} */

View file

@ -62,30 +62,6 @@ static uint8_t mac_dsn;
static uint8_t initialized = 0; static uint8_t initialized = 0;
/** \brief The 16-bit identifier of the PAN on which the device is
* sending to. If this value is 0xffff, the device is not
* associated.
*/
static const uint16_t mac_dst_pan_id = IEEE802154_PANID;
/** \brief The 16-bit identifier of the PAN on which the device is
* operating. If this value is 0xffff, the device is not
* associated.
*/
static const uint16_t mac_src_pan_id = IEEE802154_PANID;
/*---------------------------------------------------------------------------*/
static int
is_broadcast_addr(uint8_t mode, uint8_t *addr)
{
int i = mode == FRAME802154_SHORTADDRMODE ? 2 : 8;
while(i-- > 0) {
if(addr[i] != 0xff) {
return 0;
}
}
return 1;
}
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static int static int
create_frame(int type, int do_create) create_frame(int type, int do_create)
@ -93,6 +69,10 @@ create_frame(int type, int do_create)
frame802154_t params; frame802154_t params;
int hdr_len; int hdr_len;
if(frame802154_get_pan_id() == 0xffff) {
return -1;
}
/* init to zeros */ /* init to zeros */
memset(&params, 0, sizeof(params)); memset(&params, 0, sizeof(params));
@ -109,10 +89,14 @@ create_frame(int type, int do_create)
} else { } else {
params.fcf.ack_required = packetbuf_attr(PACKETBUF_ATTR_MAC_ACK); params.fcf.ack_required = packetbuf_attr(PACKETBUF_ATTR_MAC_ACK);
} }
/* We do not compress PAN ID in outgoing frames, i.e. include one PAN ID (dest by default)
* There is one exception, seemingly a typo in Table 2a: rows 2 and 3: when there is no
* source nor destination address, we have dest PAN ID iff compression is *set*. */
params.fcf.panid_compression = 0; params.fcf.panid_compression = 0;
params.fcf.sequence_number_suppression = FRAME802154_SUPPR_SEQNO;
/* Insert IEEE 802.15.4 (2006) version bits. */ /* Insert IEEE 802.15.4 version bits. */
params.fcf.frame_version = FRAME802154_IEEE802154_2006; params.fcf.frame_version = FRAME802154_VERSION;
#if LLSEC802154_SECURITY_LEVEL #if LLSEC802154_SECURITY_LEVEL
if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL)) { if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL)) {
@ -120,8 +104,13 @@ create_frame(int type, int do_create)
} }
/* Setting security-related attributes */ /* Setting security-related attributes */
params.aux_hdr.security_control.security_level = packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL); params.aux_hdr.security_control.security_level = packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL);
#if LLSEC802154_USES_FRAME_COUNTER
params.aux_hdr.frame_counter.u16[0] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1); params.aux_hdr.frame_counter.u16[0] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1);
params.aux_hdr.frame_counter.u16[1] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3); params.aux_hdr.frame_counter.u16[1] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3);
#else /* LLSEC802154_USES_FRAME_COUNTER */
params.aux_hdr.security_control.frame_counter_suppression = 1;
params.aux_hdr.security_control.frame_counter_size = 1;
#endif /* LLSEC802154_USES_FRAME_COUNTER */
#if LLSEC802154_USES_EXPLICIT_KEYS #if LLSEC802154_USES_EXPLICIT_KEYS
params.aux_hdr.security_control.key_id_mode = packetbuf_attr(PACKETBUF_ATTR_KEY_ID_MODE); params.aux_hdr.security_control.key_id_mode = packetbuf_attr(PACKETBUF_ATTR_KEY_ID_MODE);
params.aux_hdr.key_index = packetbuf_attr(PACKETBUF_ATTR_KEY_INDEX); params.aux_hdr.key_index = packetbuf_attr(PACKETBUF_ATTR_KEY_INDEX);
@ -150,21 +139,20 @@ create_frame(int type, int do_create)
/** /**
\todo For phase 1 the addresses are all long. We'll need a mechanism \todo For phase 1 the addresses are all long. We'll need a mechanism
in the rime attributes to tell the mac to use long or short for phase 2. in the rime attributes to tell the mac to use long or short for phase 2.
*/ */
if(LINKADDR_SIZE == 2) { if(LINKADDR_SIZE == 2) {
/* Use short address mode if linkaddr size is short. */ /* Use short address mode if linkaddr size is short. */
params.fcf.src_addr_mode = FRAME802154_SHORTADDRMODE; params.fcf.src_addr_mode = FRAME802154_SHORTADDRMODE;
} else { } else {
params.fcf.src_addr_mode = FRAME802154_LONGADDRMODE; params.fcf.src_addr_mode = FRAME802154_LONGADDRMODE;
} }
params.dest_pid = mac_dst_pan_id; params.dest_pid = frame802154_get_pan_id();
if(packetbuf_holds_broadcast()) { if(packetbuf_holds_broadcast()) {
/* Broadcast requires short address mode. */ /* Broadcast requires short address mode. */
params.fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE; params.fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE;
params.dest_addr[0] = 0xFF; params.dest_addr[0] = 0xFF;
params.dest_addr[1] = 0xFF; params.dest_addr[1] = 0xFF;
} else { } else {
linkaddr_copy((linkaddr_t *)&params.dest_addr, linkaddr_copy((linkaddr_t *)&params.dest_addr,
packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
@ -177,7 +165,7 @@ create_frame(int type, int do_create)
} }
/* Set the source PAN ID to the global variable. */ /* Set the source PAN ID to the global variable. */
params.src_pid = mac_src_pan_id; params.src_pid = frame802154_get_pan_id();
/* /*
* Set up the source address using only the long address mode for * Set up the source address using only the long address mode for
@ -191,7 +179,6 @@ create_frame(int type, int do_create)
if(!do_create) { if(!do_create) {
/* Only calculate header length */ /* Only calculate header length */
return hdr_len; return hdr_len;
} else if(packetbuf_hdralloc(hdr_len)) { } else if(packetbuf_hdralloc(hdr_len)) {
frame802154_create(&params, packetbuf_hdrptr()); frame802154_create(&params, packetbuf_hdrptr());
@ -223,35 +210,41 @@ parse(void)
{ {
frame802154_t frame; frame802154_t frame;
int hdr_len; int hdr_len;
hdr_len = frame802154_parse(packetbuf_dataptr(), packetbuf_datalen(), &frame); hdr_len = frame802154_parse(packetbuf_dataptr(), packetbuf_datalen(), &frame);
if(hdr_len && packetbuf_hdrreduce(hdr_len)) { if(hdr_len && packetbuf_hdrreduce(hdr_len)) {
packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, frame.fcf.frame_type); packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, frame.fcf.frame_type);
if(frame.fcf.dest_addr_mode) { if(frame.fcf.dest_addr_mode) {
if(frame.dest_pid != mac_src_pan_id && if(frame.dest_pid != frame802154_get_pan_id() &&
frame.dest_pid != FRAME802154_BROADCASTPANDID) { frame.dest_pid != FRAME802154_BROADCASTPANDID) {
/* Packet to another PAN */ /* Packet to another PAN */
PRINTF("15.4: for another pan %u\n", frame.dest_pid); PRINTF("15.4: for another pan %u\n", frame.dest_pid);
return FRAMER_FAILED; return FRAMER_FAILED;
} }
if(!is_broadcast_addr(frame.fcf.dest_addr_mode, frame.dest_addr)) { if(!frame802154_is_broadcast_addr(frame.fcf.dest_addr_mode, frame.dest_addr)) {
packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, (linkaddr_t *)&frame.dest_addr); packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, (linkaddr_t *)&frame.dest_addr);
} }
} }
packetbuf_set_addr(PACKETBUF_ADDR_SENDER, (linkaddr_t *)&frame.src_addr); packetbuf_set_addr(PACKETBUF_ADDR_SENDER, (linkaddr_t *)&frame.src_addr);
packetbuf_set_attr(PACKETBUF_ATTR_PENDING, frame.fcf.frame_pending); packetbuf_set_attr(PACKETBUF_ATTR_PENDING, frame.fcf.frame_pending);
packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, frame.seq); if(frame.fcf.sequence_number_suppression == 0) {
packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, frame.seq);
} else {
packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, 0xffff);
}
#if NETSTACK_CONF_WITH_RIME #if NETSTACK_CONF_WITH_RIME
packetbuf_set_attr(PACKETBUF_ATTR_PACKET_ID, frame.seq); packetbuf_set_attr(PACKETBUF_ATTR_PACKET_ID, frame.seq);
#endif #endif
#if LLSEC802154_SECURITY_LEVEL #if LLSEC802154_SECURITY_LEVEL
if(frame.fcf.security_enabled) { if(frame.fcf.security_enabled) {
packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL, frame.aux_hdr.security_control.security_level); packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL, frame.aux_hdr.security_control.security_level);
#if LLSEC802154_USES_FRAME_COUNTER
packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1, frame.aux_hdr.frame_counter.u16[0]); packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1, frame.aux_hdr.frame_counter.u16[0]);
packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3, frame.aux_hdr.frame_counter.u16[1]); packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3, frame.aux_hdr.frame_counter.u16[1]);
#endif /* LLSEC802154_USES_FRAME_COUNTER */
#if LLSEC802154_USES_EXPLICIT_KEYS #if LLSEC802154_USES_EXPLICIT_KEYS
packetbuf_set_attr(PACKETBUF_ATTR_KEY_ID_MODE, frame.aux_hdr.security_control.key_id_mode); packetbuf_set_attr(PACKETBUF_ATTR_KEY_ID_MODE, frame.aux_hdr.security_control.key_id_mode);
packetbuf_set_attr(PACKETBUF_ATTR_KEY_INDEX, frame.aux_hdr.key_index); packetbuf_set_attr(PACKETBUF_ATTR_KEY_INDEX, frame.aux_hdr.key_index);
@ -264,7 +257,7 @@ parse(void)
PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_SENDER)); PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_SENDER));
PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
PRINTF("%d %u (%u)\n", hdr_len, packetbuf_datalen(), packetbuf_totlen()); PRINTF("%d %u (%u)\n", hdr_len, packetbuf_datalen(), packetbuf_totlen());
return hdr_len; return hdr_len;
} }
return FRAMER_FAILED; return FRAMER_FAILED;