Added support for IEEE 802.15.4 frame version 2
This commit is contained in:
parent
f86494c6aa
commit
5cf9871d5b
4 changed files with 338 additions and 89 deletions
|
@ -85,6 +85,12 @@
|
|||
#define LLSEC802154_USES_EXPLICIT_KEYS 0
|
||||
#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
|
||||
#define LLSEC802154_HTONS(n) (n)
|
||||
#define LLSEC802154_HTONL(n) (n)
|
||||
|
|
|
@ -44,11 +44,11 @@
|
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
*/
|
||||
/*
|
||||
* \brief This file is where the main functions that relate to frame
|
||||
* manipulation will reside.
|
||||
*/
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
|
@ -61,7 +61,7 @@
|
|||
/**
|
||||
* \addtogroup frame802154
|
||||
* @{
|
||||
*/
|
||||
*/
|
||||
|
||||
#include "sys/cc.h"
|
||||
#include "net/mac/frame802154.h"
|
||||
|
@ -69,11 +69,18 @@
|
|||
#include "net/linkaddr.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
|
||||
* in the 802.15.4 header. This structure is used in \ref frame802154_create()
|
||||
*/
|
||||
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_addr_len; /**< Length (in bytes) of destination address 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 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* 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
|
||||
field_len(frame802154_t *p, field_length_t *flen)
|
||||
{
|
||||
int has_src_panid;
|
||||
int has_dest_panid;
|
||||
|
||||
/* init flen to zeros */
|
||||
memset(flen, 0, sizeof(field_length_t));
|
||||
|
||||
/* Determine lengths of each field based on fcf and other args */
|
||||
if(p->fcf.dest_addr_mode & 3) {
|
||||
flen->dest_pid_len = 2;
|
||||
if((p->fcf.sequence_number_suppression & 1) == 0) {
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
/* compressed header, only do dest pid */
|
||||
flen->src_pid_len = 0;
|
||||
} else {
|
||||
p->fcf.panid_compression = 0;
|
||||
if(has_dest_panid) {
|
||||
flen->dest_pid_len = 2;
|
||||
}
|
||||
|
||||
/* determine address lengths */
|
||||
|
@ -144,9 +320,16 @@ field_len(frame802154_t *p, field_length_t *flen)
|
|||
#if LLSEC802154_SECURITY_LEVEL
|
||||
/* Aux security header */
|
||||
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
|
||||
+ 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 */
|
||||
;
|
||||
}
|
||||
|
@ -161,14 +344,14 @@ field_len(frame802154_t *p, field_length_t *flen)
|
|||
* frame to send.
|
||||
*
|
||||
* \return The length of the frame header.
|
||||
*/
|
||||
*/
|
||||
int
|
||||
frame802154_hdrlen(frame802154_t *p)
|
||||
{
|
||||
field_length_t flen;
|
||||
field_len(p, &flen);
|
||||
return 3 + flen.dest_pid_len + flen.dest_addr_len +
|
||||
flen.src_pid_len + flen.src_addr_len + flen.aux_sec_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;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**
|
||||
|
@ -181,7 +364,7 @@ frame802154_hdrlen(frame802154_t *p)
|
|||
* \param buf Pointer to the buffer to use for the frame.
|
||||
*
|
||||
* \return The length of the frame header
|
||||
*/
|
||||
*/
|
||||
int
|
||||
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 */
|
||||
|
||||
field_len(p, &flen);
|
||||
|
||||
|
||||
/* OK, now we have field lengths. Time to actually construct */
|
||||
/* the outgoing frame, and store it in buf */
|
||||
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.ack_required & 1) << 5) |
|
||||
((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.src_addr_mode & 3) << 6);
|
||||
|
||||
/* sequence number */
|
||||
buf[2] = p->seq;
|
||||
pos = 3;
|
||||
pos = 2;
|
||||
|
||||
/* Sequence number */
|
||||
if(flen.seqno_len == 1) {
|
||||
buf[pos++] = p->seq;
|
||||
}
|
||||
|
||||
/* Destination PAN ID */
|
||||
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--) {
|
||||
buf[pos++] = p->src_addr[c - 1];
|
||||
}
|
||||
|
||||
#if LLSEC802154_SECURITY_LEVEL
|
||||
/* Aux header */
|
||||
if(flen.aux_sec_len) {
|
||||
buf[pos++] = p->aux_hdr.security_control.security_level
|
||||
#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 */
|
||||
| (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);
|
||||
pos += 4;
|
||||
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);
|
||||
pos += 4;
|
||||
if(p->aux_hdr.security_control.frame_counter_size == 1) {
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
|
||||
#if LLSEC802154_USES_EXPLICIT_KEYS
|
||||
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;
|
||||
frame802154_fcf_t fcf;
|
||||
int c;
|
||||
int has_src_panid;
|
||||
int has_dest_panid;
|
||||
#if LLSEC802154_USES_EXPLICIT_KEYS
|
||||
uint8_t key_id_mode;
|
||||
#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
|
||||
|
||||
if(len < 3) {
|
||||
if(len < 2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -289,20 +486,32 @@ frame802154_parse(uint8_t *data, int len, frame802154_t *pf)
|
|||
fcf.ack_required = (p[0] >> 5) & 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.frame_version = (p[1] >> 4) & 3;
|
||||
fcf.src_addr_mode = (p[1] >> 6) & 3;
|
||||
|
||||
/* copy fcf and seqNum */
|
||||
memcpy(&pf->fcf, &fcf, sizeof(frame802154_fcf_t));
|
||||
pf->seq = p[2];
|
||||
p += 3; /* Skip first three bytes */
|
||||
p += 2; /* Skip first two 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 */
|
||||
if(fcf.dest_addr_mode) {
|
||||
/* Destination PAN */
|
||||
pf->dest_pid = p[0] + (p[1] << 8);
|
||||
p += 2;
|
||||
if(has_dest_panid) {
|
||||
/* Destination PAN */
|
||||
pf->dest_pid = p[0] + (p[1] << 8);
|
||||
p += 2;
|
||||
} else {
|
||||
pf->dest_pid = 0;
|
||||
}
|
||||
|
||||
/* Destination address */
|
||||
/* 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 */
|
||||
if(fcf.src_addr_mode) {
|
||||
/* Source PAN */
|
||||
if(!fcf.panid_compression) {
|
||||
if(has_src_panid) {
|
||||
pf->src_pid = p[0] + (p[1] << 8);
|
||||
p += 2;
|
||||
if(!has_dest_panid) {
|
||||
pf->dest_pid = pf->src_pid;
|
||||
}
|
||||
} else {
|
||||
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);
|
||||
pf->src_pid = 0;
|
||||
}
|
||||
|
||||
|
||||
#if LLSEC802154_SECURITY_LEVEL
|
||||
if(fcf.security_enabled) {
|
||||
pf->aux_hdr.security_control.security_level = p[0] & 7;
|
||||
#if LLSEC802154_USES_EXPLICIT_KEYS
|
||||
pf->aux_hdr.security_control.key_id_mode = (p[0] >> 3) & 3;
|
||||
#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;
|
||||
|
||||
memcpy(pf->aux_hdr.frame_counter.u8, p, 4);
|
||||
p += 4;
|
||||
|
||||
|
||||
if(pf->aux_hdr.security_control.frame_counter_suppression == 0) {
|
||||
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
|
||||
key_id_mode = pf->aux_hdr.security_control.key_id_mode;
|
||||
if(key_id_mode) {
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
* 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.
|
||||
*/
|
||||
*/
|
||||
|
||||
/**
|
||||
* \addtogroup net
|
||||
|
@ -59,14 +59,14 @@
|
|||
* This file converts to and from a structure to a packed 802.15.4
|
||||
* frame.
|
||||
*
|
||||
*/
|
||||
|
||||
*/
|
||||
|
||||
/* Includes */
|
||||
#ifndef FRAME_802154_H
|
||||
#define FRAME_802154_H
|
||||
|
||||
#include "contiki-conf.h"
|
||||
#include "net/linkaddr.h"
|
||||
|
||||
#ifdef IEEE802154_CONF_PANID
|
||||
#define IEEE802154_PANID IEEE802154_CONF_PANID
|
||||
|
@ -74,6 +74,18 @@
|
|||
#define IEEE802154_PANID 0xABCD
|
||||
#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 */
|
||||
|
||||
/** \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_BROADCASTPANDID (0xFFFF)
|
||||
|
||||
#define FRAME802154_IEEE802154_2003 (0x00)
|
||||
#define FRAME802154_IEEE802154_2006 (0x01)
|
||||
#define FRAME802154_IEEE802154_2003 (0x00)
|
||||
#define FRAME802154_IEEE802154_2006 (0x01)
|
||||
#define FRAME802154_IEEE802154E_2012 (0x02)
|
||||
|
||||
#define FRAME802154_SECURITY_LEVEL_NONE (0)
|
||||
#define FRAME802154_SECURITY_LEVEL_MIC_32 (1)
|
||||
|
@ -125,7 +138,7 @@
|
|||
* 3. Addressing fields - 4 - 20 bytes - Variable
|
||||
* 4. Aux security header - 0 - 14 bytes - Variable
|
||||
* 5. CRC - 2 bytes - Fixed
|
||||
*/
|
||||
*/
|
||||
|
||||
/**
|
||||
* \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 ack_required; /**< 1 bit. Is an ack frame required? */
|
||||
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 frame_version; /**< 2 bit. 802.15.4 frame version */
|
||||
uint8_t src_addr_mode; /**< 2 bit. Source address mode, see 802.15.4 */
|
||||
|
@ -146,6 +161,8 @@ typedef struct {
|
|||
typedef struct {
|
||||
uint8_t security_level; /**< 3 bit. security level */
|
||||
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 */
|
||||
} frame802154_scf_t;
|
||||
|
||||
|
@ -193,6 +210,20 @@ int frame802154_hdrlen(frame802154_t *p);
|
|||
int frame802154_create(frame802154_t *p, uint8_t *buf);
|
||||
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 */
|
||||
/** @} */
|
||||
|
|
|
@ -62,30 +62,6 @@ static uint8_t mac_dsn;
|
|||
|
||||
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
|
||||
create_frame(int type, int do_create)
|
||||
|
@ -93,6 +69,10 @@ create_frame(int type, int do_create)
|
|||
frame802154_t params;
|
||||
int hdr_len;
|
||||
|
||||
if(frame802154_get_pan_id() == 0xffff) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* init to zeros */
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
|
||||
|
@ -109,10 +89,14 @@ create_frame(int type, int do_create)
|
|||
} else {
|
||||
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.sequence_number_suppression = FRAME802154_SUPPR_SEQNO;
|
||||
|
||||
/* Insert IEEE 802.15.4 (2006) version bits. */
|
||||
params.fcf.frame_version = FRAME802154_IEEE802154_2006;
|
||||
/* Insert IEEE 802.15.4 version bits. */
|
||||
params.fcf.frame_version = FRAME802154_VERSION;
|
||||
|
||||
#if LLSEC802154_SECURITY_LEVEL
|
||||
if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL)) {
|
||||
|
@ -120,8 +104,13 @@ create_frame(int type, int do_create)
|
|||
}
|
||||
/* Setting security-related attributes */
|
||||
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[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
|
||||
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);
|
||||
|
@ -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
|
||||
in the rime attributes to tell the mac to use long or short for phase 2.
|
||||
*/
|
||||
*/
|
||||
if(LINKADDR_SIZE == 2) {
|
||||
/* Use short address mode if linkaddr size is short. */
|
||||
params.fcf.src_addr_mode = FRAME802154_SHORTADDRMODE;
|
||||
} else {
|
||||
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()) {
|
||||
/* Broadcast requires short address mode. */
|
||||
params.fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE;
|
||||
params.dest_addr[0] = 0xFF;
|
||||
params.dest_addr[1] = 0xFF;
|
||||
|
||||
} else {
|
||||
linkaddr_copy((linkaddr_t *)¶ms.dest_addr,
|
||||
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. */
|
||||
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
|
||||
|
@ -191,7 +179,6 @@ create_frame(int type, int do_create)
|
|||
if(!do_create) {
|
||||
/* Only calculate header length */
|
||||
return hdr_len;
|
||||
|
||||
} else if(packetbuf_hdralloc(hdr_len)) {
|
||||
frame802154_create(¶ms, packetbuf_hdrptr());
|
||||
|
||||
|
@ -223,35 +210,41 @@ parse(void)
|
|||
{
|
||||
frame802154_t frame;
|
||||
int hdr_len;
|
||||
|
||||
|
||||
hdr_len = frame802154_parse(packetbuf_dataptr(), packetbuf_datalen(), &frame);
|
||||
|
||||
|
||||
if(hdr_len && packetbuf_hdrreduce(hdr_len)) {
|
||||
packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, frame.fcf.frame_type);
|
||||
|
||||
|
||||
if(frame.fcf.dest_addr_mode) {
|
||||
if(frame.dest_pid != mac_src_pan_id &&
|
||||
frame.dest_pid != FRAME802154_BROADCASTPANDID) {
|
||||
if(frame.dest_pid != frame802154_get_pan_id() &&
|
||||
frame.dest_pid != FRAME802154_BROADCASTPANDID) {
|
||||
/* Packet to another PAN */
|
||||
PRINTF("15.4: for another pan %u\n", frame.dest_pid);
|
||||
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_SENDER, (linkaddr_t *)&frame.src_addr);
|
||||
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
|
||||
packetbuf_set_attr(PACKETBUF_ATTR_PACKET_ID, frame.seq);
|
||||
#endif
|
||||
|
||||
|
||||
#if LLSEC802154_SECURITY_LEVEL
|
||||
if(frame.fcf.security_enabled) {
|
||||
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_2_3, frame.aux_hdr.frame_counter.u16[1]);
|
||||
#endif /* LLSEC802154_USES_FRAME_COUNTER */
|
||||
#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_INDEX, frame.aux_hdr.key_index);
|
||||
|
@ -264,7 +257,7 @@ parse(void)
|
|||
PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_SENDER));
|
||||
PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
|
||||
PRINTF("%d %u (%u)\n", hdr_len, packetbuf_datalen(), packetbuf_totlen());
|
||||
|
||||
|
||||
return hdr_len;
|
||||
}
|
||||
return FRAMER_FAILED;
|
||||
|
|
Loading…
Reference in a new issue