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,31 +118,200 @@ 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) {
flen->src_pid_len = 2;
} }
/* 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. */ /* 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 && if(p->fcf.dest_addr_mode & 3 && p->fcf.src_addr_mode & 3 &&
p->src_pid == p->dest_pid) { p->src_pid == p->dest_pid) {
p->fcf.panid_compression = 1; p->fcf.panid_compression = 1;
/* compressed header, only do dest pid */
flen->src_pid_len = 0;
} else { } else {
p->fcf.panid_compression = 0; 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;
}
if(has_dest_panid) {
flen->dest_pid_len = 2;
}
/* determine address lengths */ /* determine address lengths */
flen->dest_addr_len = addr_len(p->fcf.dest_addr_mode & 3); flen->dest_addr_len = addr_len(p->fcf.dest_addr_mode & 3);
@ -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,13 +344,13 @@ 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)
{ {
@ -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,7 +418,6 @@ 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) {
@ -238,9 +425,17 @@ frame802154_create(frame802154_t *p, uint8_t *buf)
#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)
; ;
if(p->aux_hdr.security_control.frame_counter_suppression == 0) {
/* We support only 4-byte counters */
memcpy(buf + pos, p->aux_hdr.frame_counter.u8, 4); memcpy(buf + pos, p->aux_hdr.frame_counter.u8, 4);
pos += 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) {
if(has_dest_panid) {
/* Destination PAN */ /* Destination PAN */
pf->dest_pid = p[0] + (p[1] << 8); pf->dest_pid = p[0] + (p[1] << 8);
p += 2; 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;
} }
@ -364,10 +576,17 @@ frame802154_parse(uint8_t *data, int len, frame802154_t *pf)
#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;
if(pf->aux_hdr.security_control.frame_counter_suppression == 0) {
memcpy(pf->aux_hdr.frame_counter.u8, p, 4); memcpy(pf->aux_hdr.frame_counter.u8, p, 4);
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;

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.
@ -99,6 +111,7 @@
#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);
@ -157,14 +146,13 @@ create_frame(int type, int do_create)
} 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());
@ -230,19 +217,23 @@ parse(void)
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);
if(frame.fcf.sequence_number_suppression == 0) {
packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, frame.seq); 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
@ -250,8 +241,10 @@ parse(void)
#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);