From 60f33bbbf52b57ceb84b02087b4247b66261ad6b Mon Sep 17 00:00:00 2001 From: "Martine S. Lenders" Date: Wed, 25 Sep 2019 16:52:57 +0200 Subject: [PATCH] sixlowpan_sfr: initial import Selective Fragment Recovery definitions --- sys/include/net/sixlowpan.h | 21 ++ sys/include/net/sixlowpan/sfr.h | 381 ++++++++++++++++++++++++++++++++ 2 files changed, 402 insertions(+) create mode 100644 sys/include/net/sixlowpan/sfr.h diff --git a/sys/include/net/sixlowpan.h b/sys/include/net/sixlowpan.h index 083f4adb56..97b7a714bd 100644 --- a/sys/include/net/sixlowpan.h +++ b/sys/include/net/sixlowpan.h @@ -61,6 +61,27 @@ extern "C" { */ #define SIXLOWPAN_IPHC1_DISP (0x60) +/** + * @brief Dispatch mask for 6LoWPAN selective fragment recovery + * @see [draft-ietf-6lo-fragment-recovery-05, + * section 5](https://tools.ietf.org/html/draft-ietf-6lo-fragment-recovery-05#section-5) + */ +#define SIXLOWPAN_SFR_DISP_MASK (0xfe) + +/** + * @brief Dispatch for 6LoWPAN recoverable fragment + * @see [draft-ietf-6lo-fragment-recovery-05, section + * 5.1](https://tools.ietf.org/html/draft-ietf-6lo-fragment-recovery-05#section-5.1) + */ +#define SIXLOWPAN_SFR_RFRAG_DISP (0xe8) + +/** + * @brief Dispatch for 6LoWPAN recoverable fragment acknowledgment + * @see [draft-ietf-6lo-fragment-recovery-05, section + * 5.2](https://tools.ietf.org/html/draft-ietf-6lo-fragment-recovery-05#section-5.2) + */ +#define SIXLOWPAN_SFR_ACK_DISP (0xea) + /** * @brief Checks if dispatch indicates that frame is not a 6LoWPAN (NALP) frame. * diff --git a/sys/include/net/sixlowpan/sfr.h b/sys/include/net/sixlowpan/sfr.h new file mode 100644 index 0000000000..b2a2fe21b2 --- /dev/null +++ b/sys/include/net/sixlowpan/sfr.h @@ -0,0 +1,381 @@ +/* + * Copyright (C) 2019 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @defgroup net_sixlowpan_sfr 6LoWPAN selective fragment recovery + * @ingroup net_sixlowpan + * @brief Provides dispatches for 6LoWPAN selective fragment recovery and + * helper functions + * @{ + * + * @file + * @brief 6LoWPAN selective fragment recovery dispatch type and helper + * function definitions. + * + * @author Martine Lenders + */ +#ifndef NET_SIXLOWPAN_SFR_H +#define NET_SIXLOWPAN_SFR_H + +#include +#include +#include + +#include "bitfield.h" +#include "byteorder.h" +#include "net/sixlowpan.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Mask for generic dispatch of both selective fragment recovery + * headers + * + * @see SIXLOWPAN_SFR_GEN_DISP + * @see SIXLOWPAN_SFR_DISP_MASK + * @see SIXLOWPAN_SFR_RFRAG_DISP + * @see SIXLOWPAN_SFR_ACK_DISP + */ +#define SIXLOWPAN_SFR_GEN_DISP_MASK (0xfc) +#define SIXLOWPAN_SFR_GEN_DISP (0xe8) /**< generic dispatch for both SFR headers */ +#define SIXLOWPAN_SFR_ECN (0x01U) /**< explicit congestion notification flag */ +#define SIXLOWPAN_SFR_ACK_REQ (0x80U) /**< Acknowledgment request flag (for 8 MSB) */ +#define SIXLOWPAN_SFR_SEQ_MASK (0x7cU) /**< Sequence number mask (for 8 MSB) */ +#define SIXLOWPAN_SFR_SEQ_POS (2U) /**< Sequence number position (for 8 MSB) */ +#define SIXLOWPAN_SFR_SEQ_MAX (0x1fU) /**< Maximum value for sequence number */ +#define SIXLOWPAN_SFR_FRAG_SIZE_MASK (0x03ffU) /**< Fragment size mask */ +#define SIXLOWPAN_SFR_FRAG_SIZE_MAX (0x03ffU) /**< Maximum value for fragment size */ +#define SIXLOWPAN_SFR_ACK_BITMAP_SIZE (32U) /**< Acknowledgment bitmap size in bits */ + +/** + * @brief Generic type for selective fragment recovery headers + * + * @see [draft-ietf-6lo-fragment-recovery-05, section + * 5](https://tools.ietf.org/html/draft-ietf-6lo-fragment-recovery-05#section-5) + */ +typedef struct __attribute__((packed)) { + /** + * @brief Dispatch and explicit congestion notification (ECN) flag + * + * In network byte-order the 7 most significant bits are the dispatch (7 + * bits) and the least significant bit is the ECN flag: + * + * +-+-+-+-+-+-+-+-+ + * | Dispatch |E| + * +-+-+-+-+-+-+-+-+ + * + * For @ref sixlowpan_sfr_ack_t the ECN flag represents the ECN echo flag. + * + * This module provides helper functions to set, get, check these fields + * accordingly: + * + * - sixlowpan_sfr_is() + * - sixlowpan_sfr_set_ecn() + * - sixlowpan_sfr_clear_ecn() + * - sixlowpan_sfr_ecn() + * - sixlowpan_sfr_rfrag_set_disp() + * - sixlowpan_sfr_rfrag_is() + * - sixlowpan_sfr_ack_set_disp() + * - sixlowpan_sfr_ack_is() + */ + uint8_t disp_ecn; + uint8_t tag; /**< Datagram tag */ +} sixlowpan_sfr_t; + +/** + * @brief Recoverable fragment header + * + * @see [draft-ietf-6lo-fragment-recovery-05, section + * 5.1](https://tools.ietf.org/html/draft-ietf-6lo-fragment-recovery-05#section-5.1) + */ +typedef struct __attribute__((packed)) { + sixlowpan_sfr_t base; /**< generic part */ + /** + * @brief Acknowledgment request flag, sequence number, and fragment size + * + * In network byte-order the most significant bit is the acknowledgment + * request flag, the second to sixth most significant bits are the sequence + * number (5 bits), and the 10 least significant bits are the fragment size + * (10 bits): + * + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |X| sequence| fragment_size | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * This module provides helper functions to set, get, check these fields + * accordingly: + * + * - sixlowpan_sfr_rfrag_set_ack_req() + * - sixlowpan_sfr_rfrag_clear_ack_req() + * - sixlowpan_sfr_rfrag_ack_req() + * - sixlowpan_sfr_rfrag_set_seq() + * - sixlowpan_sfr_rfrag_get_seq() + * - sixlowpan_sfr_rfrag_set_frag_size() + * - sixlowpan_sfr_rfrag_get_frag_size() + */ + network_uint16_t ar_seq_fs; + + /** + * @brief Fragment offset + * + * This module provides helper functions to set, get, check these fields + * accordingly: + * + * - sixlowpan_sfr_rfrag_set_offset() + * - sixlowpan_sfr_rfrag_get_offset() + */ + network_uint16_t offset; +} sixlowpan_sfr_rfrag_t; + +/** + * @brief Recoverable fragment (RFRAG) acknowledgment header + * + * @see [draft-ietf-6lo-fragment-recovery-05, section + * 5.2](https://tools.ietf.org/html/draft-ietf-6lo-fragment-recovery-05#section-5.2) + */ +typedef struct __attribute__((packed)) { + sixlowpan_sfr_t base; /**< generic part */ + /** + * @brief RFRAG acknowledgment bitmap + */ + BITFIELD(bitmap, SIXLOWPAN_SFR_ACK_BITMAP_SIZE); +} sixlowpan_sfr_ack_t; + +/** + * @brief Check if given header is a 6LoWPAN selective fragment recovery + * header (either RFRAG or RFRAG ACK) + * + * @see @ref SIXLOWPAN_SFR_RFRAG_DISP + * + * @param[in] hdr The 6LoWPAN selective fragment recovery header to check + * + * return true, if @p hdr is a 6LoWPAN selective fragment recovery header + * return false, if @p hdr is not a 6LoWPAN selective fragment recovery header + */ +static inline bool sixlowpan_sfr_is(sixlowpan_sfr_t *hdr) +{ + return ((hdr->disp_ecn & SIXLOWPAN_SFR_GEN_DISP_MASK) == SIXLOWPAN_SFR_GEN_DISP); +} + +/** + * @brief Set the ECN flag in a 6LoWPAN selective fragment recovery header + * + * @param[in,out] hdr A 6LoWPAN selective fragment recovery header + */ +static inline void sixlowpan_sfr_set_ecn(sixlowpan_sfr_t *hdr) +{ + hdr->disp_ecn |= SIXLOWPAN_SFR_ECN; +} + +/** + * @brief Clear the ECN flag in a 6LoWPAN recoverable fragment header + * + * @param[in,out] hdr A 6LoWPAN selective fragment recovery header + */ +static inline void sixlowpan_sfr_clear_ecn(sixlowpan_sfr_t *hdr) +{ + hdr->disp_ecn &= ~SIXLOWPAN_SFR_ECN; +} + +/** + * @brief Check if the ECN flag in a 6LoWPAN recoverable fragment header is + * set + * + * @param[in] hdr A 6LoWPAN selective fragment recovery header + * + * return true, if ECN flag in @p hdr is set + * return false, if ECN flag in @p hdr is cleared + */ +static inline bool sixlowpan_sfr_ecn(const sixlowpan_sfr_t *hdr) +{ + return (hdr->disp_ecn & SIXLOWPAN_SFR_ECN); +} + +/** + * @brief Initialize 6LoWPAN recoverable fragment dispatch + * + * @see @ref SIXLOWPAN_SFR_RFRAG_DISP + * + * @param[in,out] hdr A 6LoWPAN selective fragment recovery header + */ +static inline void sixlowpan_sfr_rfrag_set_disp(sixlowpan_sfr_t *hdr) +{ + hdr->disp_ecn &= ~SIXLOWPAN_SFR_DISP_MASK; + hdr->disp_ecn |= SIXLOWPAN_SFR_RFRAG_DISP; +} + +/** + * @brief Check if given header is a 6LoWPAN recoverable fragment header + * + * @see @ref SIXLOWPAN_SFR_RFRAG_DISP + * + * @param[in] hdr The 6LoWPAN selective fragment recovery header to check + * + * return true, if @p hdr is a 6LoWPAN recoverable fragment header + * return false, if @p hdr is not a 6LoWPAN recoverable fragment header + */ +static inline bool sixlowpan_sfr_rfrag_is(const sixlowpan_sfr_t *hdr) +{ + return ((hdr->disp_ecn & SIXLOWPAN_SFR_DISP_MASK) == SIXLOWPAN_SFR_RFRAG_DISP); +} + +/** + * @brief Set the Acknowledgment request flag in a 6LoWPAN recoverable + * fragment header + * + * @param[in,out] hdr A 6LoWPAN recoverable fragment header + */ +static inline void sixlowpan_sfr_rfrag_set_ack_req(sixlowpan_sfr_rfrag_t *hdr) +{ + hdr->ar_seq_fs.u8[0] |= SIXLOWPAN_SFR_ACK_REQ; +} + +/** + * @brief Clear the Acknowledgment request flag in a 6LoWPAN recoverable + * fragment header + * + * @param[in,out] hdr A 6LoWPAN recoverable fragment header + */ +static inline void sixlowpan_sfr_rfrag_clear_ack_req(sixlowpan_sfr_rfrag_t *hdr) +{ + hdr->ar_seq_fs.u8[0] &= ~SIXLOWPAN_SFR_ACK_REQ; +} + +/** + * @brief Check if the Acknowledgment request flag in a 6LoWPAN recoverable + * fragment header is set + * + * @param[in] hdr A 6LoWPAN recoverable fragment header + * + * return true, if Acknowledgment request flag in @p hdr is set + * return false, if Acknowledgment request flag in @p hdr is cleared + */ +static inline bool sixlowpan_sfr_rfrag_ack_req(sixlowpan_sfr_rfrag_t *hdr) +{ + return (hdr->ar_seq_fs.u8[0] & SIXLOWPAN_SFR_ACK_REQ); +} + +/** + * @brief Set sequence number in a 6LoWPAN recoverable fragment header + * + * @pre `seq <= SIXLOWPAN_SFR_SEQ_MAX` + * + * @param[in,out] hdr A 6LoWPAN recoverable fragment header + * @param[in] seq The sequence number to set. Must be lesser or equal + * to @ref SIXLOWPAN_SFR_SEQ_MAX. + */ +static inline void sixlowpan_sfr_rfrag_set_seq(sixlowpan_sfr_rfrag_t *hdr, + uint8_t seq) +{ + assert(seq <= SIXLOWPAN_SFR_SEQ_MAX); + hdr->ar_seq_fs.u8[0] &= ~SIXLOWPAN_SFR_SEQ_MASK; + hdr->ar_seq_fs.u8[0] |= (seq << SIXLOWPAN_SFR_SEQ_POS); +} + +/** + * @brief Get sequence number from a 6LoWPAN recoverable fragment header + * + * @param[in] hdr A 6LoWPAN recoverable fragment header + * + * @return The sequence number of the 6LoWPAN recoverable fragment + */ +static inline uint8_t sixlowpan_sfr_rfrag_get_seq(const sixlowpan_sfr_rfrag_t *hdr) +{ + return ((hdr->ar_seq_fs.u8[0] & SIXLOWPAN_SFR_SEQ_MASK) >> + SIXLOWPAN_SFR_SEQ_POS); +} + +/** + * @brief Set fragment size in a 6LoWPAN recoverable fragment header + * + * @pre `frag_size <= SIXLOWPAN_SFR_FRAG_SIZE_MAX` + * + * @param[in,out] hdr A 6LoWPAN recoverable fragment header + * @param[in] frag_size The fragment size to set. Must be lesser or equal to + * @ref SIXLOWPAN_SFR_FRAG_SIZE_MAX. + */ +static inline void sixlowpan_sfr_rfrag_set_frag_size(sixlowpan_sfr_rfrag_t *hdr, + uint16_t frag_size) +{ + assert(frag_size <= SIXLOWPAN_SFR_FRAG_SIZE_MAX); + hdr->ar_seq_fs.u16 &= ~htons(SIXLOWPAN_SFR_FRAG_SIZE_MASK); + hdr->ar_seq_fs.u16 |= htons(frag_size); +} + +/** + * @brief Get fragment size from a 6LoWPAN recoverable fragment header + * + * @param[in] hdr A 6LoWPAN recoverable fragment header + * + * @return The fragment size of the 6LoWPAN recoverable fragment + */ +static inline uint16_t sixlowpan_sfr_rfrag_get_frag_size(const sixlowpan_sfr_rfrag_t *hdr) +{ + return (byteorder_ntohs(hdr->ar_seq_fs) & SIXLOWPAN_SFR_FRAG_SIZE_MASK); +} + +/** + * @brief Set fragment offset in a 6LoWPAN recoverable fragment header + * + * @param[in,out] hdr A 6LoWPAN recoverable fragment header + * @param[in] offset The fragment offset to set. + */ +static inline void sixlowpan_sfr_rfrag_set_offset(sixlowpan_sfr_rfrag_t *hdr, + uint16_t offset) +{ + hdr->offset = byteorder_htons(offset); +} + +/** + * @brief Get fragment offset from a 6LoWPAN recoverable fragment header + * + * @param[in] hdr A 6LoWPAN recoverable fragment header + * + * @return The fragment offset of the 6LoWPAN recoverable fragment + */ +static inline uint16_t sixlowpan_sfr_rfrag_get_offset(const sixlowpan_sfr_rfrag_t *hdr) +{ + return byteorder_ntohs(hdr->offset); +} + +/** + * @brief Initialize 6LoWPAN RFRAG acknowledgment dispatch + * + * @see @ref SIXLOWPAN_SFR_ACK_DISP + * + * @param[in,out] hdr A 6LoWPAN selective fragment recovery header + */ +static inline void sixlowpan_sfr_ack_set_disp(sixlowpan_sfr_t *hdr) +{ + hdr->disp_ecn &= ~SIXLOWPAN_SFR_DISP_MASK; + hdr->disp_ecn |= SIXLOWPAN_SFR_ACK_DISP; +} + +/** + * @brief Check if given header is a 6LoWPAN RFRAG acknowledgment header + * + * @see @ref SIXLOWPAN_SFR_ACK_DISP + * + * @param[in] hdr The 6LoWPAN selective fragment recovery header to check + * + * return true, if @p hdr is a 6LoWPAN RFRAG acknowledgment header + * return false, if @p hdr is not a 6LoWPAN RFRAG acknowledgment header + */ +static inline bool sixlowpan_sfr_ack_is(const sixlowpan_sfr_t *hdr) +{ + return ((hdr->disp_ecn & SIXLOWPAN_SFR_DISP_MASK) == SIXLOWPAN_SFR_ACK_DISP); +} + +#ifdef __cplusplus +} +#endif + +#endif /* NET_SIXLOWPAN_SFR_H */ +/** @} */