commit
c94094529d
@ -0,0 +1,324 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||
*
|
||||
* 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_ng_ipv6_hdr IPv6 header defintions
|
||||
* @ingroup net_ng_ipv6
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief IPv6 header
|
||||
*
|
||||
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||
*/
|
||||
#ifndef NG_IPV6_HDR_H_
|
||||
#define NG_IPV6_HDR_H_
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "byteorder.h"
|
||||
#include "net/ng_ipv6/addr.h"
|
||||
#include "net/ng_inet_csum.h"
|
||||
#include "net/ng_pkt.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Data type to represent an IPv6 packet header
|
||||
*
|
||||
* @details The structure of the header is as follows:
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.unparsed}
|
||||
* 1 2 3
|
||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* |Version| Traffic Class | Flow Label |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Payload Length | Next Header | Hop Limit |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | |
|
||||
* + +
|
||||
* | |
|
||||
* + Source Address +
|
||||
* | |
|
||||
* + +
|
||||
* | |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | |
|
||||
* + +
|
||||
* | |
|
||||
* + Destination Address +
|
||||
* | |
|
||||
* + +
|
||||
* | |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* @see <a href="http://tools.ietf.org/html/rfc2460#section-3">
|
||||
* RFC 2460, section 3
|
||||
* </a>
|
||||
*/
|
||||
typedef struct __attribute__((packed)) {
|
||||
/**
|
||||
* @brief Version, traffic class, and flow label
|
||||
*
|
||||
* @details The version are the 4 most significant bits, the traffic class
|
||||
* the 8 next bit, and the remainding 20 bits are the flow label (see
|
||||
* above).
|
||||
*
|
||||
* This module provides helper functions to set, get, and check these
|
||||
* fields accordingly:
|
||||
* * ng_ipv6_hdr_set_version()
|
||||
* * ng_ipv6_hdr_get_version()
|
||||
* * ng_ipv6_hdr_is_ipv6_hdr()
|
||||
* * ng_ipv6_hdr_set_tc()
|
||||
* * ng_ipv6_hdr_set_tc_ecn()
|
||||
* * ng_ipv6_hdr_set_tc_dscp()
|
||||
* * ng_ipv6_hdr_get_tc()
|
||||
* * ng_ipv6_hdr_get_tc_ecn()
|
||||
* * ng_ipv6_hdr_get_tc_dscp()
|
||||
* * ng_ipv6_hdr_set_fl()
|
||||
* * ng_ipv6_hdr_get_fl()
|
||||
*/
|
||||
network_uint32_t v_tc_fl;
|
||||
network_uint16_t len; /**< payload length of this packet. */
|
||||
uint8_t nh; /**< type of next header in this packet. */
|
||||
uint8_t hl; /**< hop limit for this packet. */
|
||||
ng_ipv6_addr_t src; /**< source address of this packet. */
|
||||
ng_ipv6_addr_t dst; /**< destination address of this packet. */
|
||||
} ng_ipv6_hdr_t;
|
||||
|
||||
/**
|
||||
* @brief Sets the version field of @p hdr to 6
|
||||
*
|
||||
* @param[out] hdr Pointer to an IPv6 header.
|
||||
*/
|
||||
static inline void ng_ipv6_hdr_set_version(ng_ipv6_hdr_t *hdr)
|
||||
{
|
||||
hdr->v_tc_fl.u8[0] &= 0x0f;
|
||||
hdr->v_tc_fl.u8[0] |= 0x60;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the value of the version field of @p hdr
|
||||
*
|
||||
* @param[in] hdr Pointer to an IPv6 header.
|
||||
*
|
||||
* @return Value of the version field of @p hdr.
|
||||
*/
|
||||
static inline uint8_t ng_ipv6_hdr_get_version(const ng_ipv6_hdr_t *hdr)
|
||||
{
|
||||
return ((hdr->v_tc_fl.u8[0]) >> 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks if the version field is set to 6
|
||||
*
|
||||
* @param[in] hdr Pointer to an IPv6 header.
|
||||
*
|
||||
* @return true, if version field is 6
|
||||
* @return false, otherwise
|
||||
*/
|
||||
static inline bool ng_ipv6_hdr_is_ipv6_hdr(const ng_ipv6_hdr_t *hdr)
|
||||
{
|
||||
return (((hdr->v_tc_fl.u8[0]) & 0xf0) == 0x60);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the traffic class field of @p hdr
|
||||
*
|
||||
* @param[out] hdr Pointer to an IPv6 header.
|
||||
* @param[in] tc The new value for the traffic class field.
|
||||
*/
|
||||
static inline void ng_ipv6_hdr_set_tc(ng_ipv6_hdr_t *hdr, uint8_t tc)
|
||||
{
|
||||
hdr->v_tc_fl.u8[0] &= 0xf0;
|
||||
hdr->v_tc_fl.u8[0] |= (0x0f & (tc >> 4));
|
||||
hdr->v_tc_fl.u8[1] &= 0x0f;
|
||||
hdr->v_tc_fl.u8[1] |= (0xf0 & (tc << 4));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the value of the Explicit Congestion Notification (ECN) part
|
||||
* of the traffic class field of @p hdr
|
||||
*
|
||||
* @details The field is needed e.g. in context of 6LoWPAN header compression
|
||||
*
|
||||
* @see <a href="https://tools.ietf.org/html/rfc3168#section-5">
|
||||
* RFC 3168, section 5
|
||||
* </a>
|
||||
*
|
||||
* @param[out] hdr Pointer to an IPv6 header.
|
||||
* @param[in] ecn The new value for the 2-bit ECN part of the traffic class
|
||||
* field.
|
||||
*/
|
||||
static inline void ng_ipv6_hdr_set_tc_ecn(ng_ipv6_hdr_t *hdr, uint8_t ecn)
|
||||
{
|
||||
hdr->v_tc_fl.u8[0] &= 0xf3;
|
||||
hdr->v_tc_fl.u8[0] |= (0x0c & (ecn << 2));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the value of the Differentiated Service Codepoint (DSCP) part
|
||||
* of the traffic class field of @p hdr
|
||||
*
|
||||
* @details The field is needed e.g. in context of 6LoWPAN header compression
|
||||
*
|
||||
* @see <a href="https://tools.ietf.org/html/rfc2474#section-3">
|
||||
* RFC 2474, section 3
|
||||
* </a>
|
||||
*
|
||||
* @param[out] hdr Pointer to an IPv6 header.
|
||||
* @param[in] dscp The new value for the 6-bit DSCP ng_part of the traffic class
|
||||
* field.
|
||||
*/
|
||||
static inline void ng_ipv6_hdr_set_tc_dscp(ng_ipv6_hdr_t *hdr, uint8_t dscp)
|
||||
{
|
||||
hdr->v_tc_fl.u8[0] &= 0xfc;
|
||||
hdr->v_tc_fl.u8[0] |= (0x03 & (dscp >> 4));
|
||||
hdr->v_tc_fl.u8[1] &= 0x0f;
|
||||
hdr->v_tc_fl.u8[1] |= (0xf0 & (dscp << 4));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the value of the traffic class field of @p hdr
|
||||
*
|
||||
* @param[in] hdr Pointer to an IPv6 header.
|
||||
*
|
||||
* @return Value of the traffic class field of @p hdr.
|
||||
*/
|
||||
static inline uint8_t ng_ipv6_hdr_get_tc(const ng_ipv6_hdr_t *hdr)
|
||||
{
|
||||
return ((((hdr->v_tc_fl.u8[0]) & 0x0f) << 4) |
|
||||
((hdr->v_tc_fl.u8[1] & 0xf0) >> 4));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the value of the Explicit Congestion Notification (ECN) part
|
||||
* of the traffic class field of @p hdr
|
||||
*
|
||||
* @details The field is needed e.g. in context of 6LoWPAN header compression
|
||||
*
|
||||
* @see <a href="https://tools.ietf.org/html/rfc3168#section-5">
|
||||
* RFC 3168, section 5
|
||||
* </a>
|
||||
*
|
||||
* @param[in] hdr Pointer to an IPv6 header.
|
||||
*
|
||||
* @return Value of the ECN part of the traffic class field of @p hdr.
|
||||
*/
|
||||
static inline uint8_t ng_ipv6_hdr_get_tc_ecn(const ng_ipv6_hdr_t *hdr)
|
||||
{
|
||||
return (((hdr->v_tc_fl.u8[0]) & 0x0c) >> 2);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Gets the value of the Differentiated Service Codepoint (DSCP) part
|
||||
* of the traffic class field of @p hdr
|
||||
*
|
||||
* @details The field is needed e.g. in context of 6LoWPAN header compression
|
||||
*
|
||||
* @see <a href="https://tools.ietf.org/html/rfc2474#section-3">
|
||||
* RFC 2474, section 3
|
||||
* </a>
|
||||
*
|
||||
* @param[in] hdr Pointer to an IPv6 header.
|
||||
*
|
||||
* @return Value of the DSCP part of the traffic class field of @p hdr.
|
||||
*/
|
||||
static inline uint8_t ng_ipv6_hdr_get_tc_dscp(const ng_ipv6_hdr_t *hdr)
|
||||
{
|
||||
return ((((hdr->v_tc_fl.u8[0]) & 0x03) << 4) |
|
||||
((hdr->v_tc_fl.u8[1] & 0xf0) >> 4));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the flow label field of @p hdr
|
||||
*
|
||||
* @param[out] hdr Pointer to an IPv6 header.
|
||||
* @param[in] fl The new value for the flow label field in host byte order.
|
||||
*/
|
||||
static inline void ng_ipv6_hdr_set_fl(ng_ipv6_hdr_t *hdr, uint32_t fl)
|
||||
{
|
||||
hdr->v_tc_fl.u8[1] &= 0xf0;
|
||||
hdr->v_tc_fl.u8[1] |= (0x0f & (byteorder_htonl(fl).u8[1]));
|
||||
hdr->v_tc_fl.u16[1] = byteorder_htonl(fl).u16[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the value of the flow label field of @p hdr
|
||||
*
|
||||
* @param[in] hdr Pointer to an IPv6 header.
|
||||
*
|
||||
* @return Value of the flow label field of @p hdr.
|
||||
*/
|
||||
static inline uint32_t ng_ipv6_hdr_get_fl(const ng_ipv6_hdr_t *hdr)
|
||||
{
|
||||
return byteorder_ntohl(hdr->v_tc_fl) & 0x000fffff;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calculates the Internet Checksum for the IPv6 Pseudo Header.
|
||||
*
|
||||
* @see <a href="https://tools.ietf.org/html/rfc2460#section-8.1">
|
||||
* RFC 2460, section 8.1
|
||||
* </a>
|
||||
*
|
||||
* @param[in] sum Preinialized value of the sum.
|
||||
* @param[in] prot_num The @ref net_ng_protnum you want to calculate the
|
||||
* checksum for. Can not be inferred from
|
||||
* ng_ipv6_hdr_t::nh, since it can be an IPv6 exentension
|
||||
* header.
|
||||
* @param[in] hdr An IPv6 header to derive the Pseudo Header from.
|
||||
* @param[in] len The upper-layer packet length for the pseudo header.
|
||||
* Can not be inferred from ng_ipv6_hdr_t::len, since
|
||||
* there can be extension headers between the IPv6 header
|
||||
* and the payload.
|
||||
*
|
||||
* @return The non-normalized Internet Checksum of the given IPv6 pseudo header.
|
||||
*/
|
||||
static inline uint16_t ng_ipv6_hdr_inet_csum(uint16_t sum, ng_ipv6_hdr_t *hdr,
|
||||
uint8_t prot_num, uint16_t len)
|
||||
{
|
||||
return ng_inet_csum(sum + len + prot_num, hdr->src.u8,
|
||||
(2 * sizeof(ng_ipv6_addr_t)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Builds an IPv6 header for sending and adds it to the packet buffer.
|
||||
*
|
||||
* @details Initializes version field with 6, traffic class, flow label, and
|
||||
* hop limit with 0, and next header with @ref NG_PROTNUM_RESERVED.
|
||||
*
|
||||
* @param[in] payload Payload for the packet.
|
||||
* @param[in] src Source address for the header. Can be NULL if not
|
||||
* known or required.
|
||||
* @param[in] src_len Length of @p src. Can be 0 if not known or required or
|
||||
* must be `sizeof(ng_ipv6_addr_t)`.
|
||||
* @param[in] dst Destination address for the header. Can be NULL if not
|
||||
* known or required.
|
||||
* @param[in] dst_len Length of @p dst. Can be 0 if not known or required or
|
||||
* must be `sizeof(ng_ipv6_addr_t)`.
|
||||
*
|
||||
* @return The an IPv6 header in packet buffer on success.
|
||||
* @return NULL on error.
|
||||
*/
|
||||
ng_pktsnip_t *ng_ipv6_hdr_build(ng_pktsnip_t *payload,
|
||||
uint8_t *src, uint8_t src_len,
|
||||
uint8_t *dst, uint8_t dst_len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NG_IPV6_HDR_H_ */
|
||||
/** @} */
|
@ -0,0 +1,3 @@
|
||||
MODULE = ng_ipv6_hdr
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
*/
|
||||
|
||||
#include "net/ng_ipv6/addr.h"
|
||||
#include "net/ng_ipv6/hdr.h"
|
||||
#include "net/ng_nettype.h"
|
||||
#include "net/ng_pktbuf.h"
|
||||
#include "net/ng_protnum.h"
|
||||
|
||||
#define ENABLE_DEBUG (0)
|
||||
#include "debug.h"
|
||||
|
||||
#if ENABLE_DEBUG && defined(MODULE_NG_IPV6_ADDR)
|
||||
static char addr_str[NG_IPV6_ADDR_MAX_STR_LEN];
|
||||
#endif
|
||||
|
||||
/* For independent testing */
|
||||
#ifdef MODULE_NG_IPV6
|
||||
#define HDR_NETTYPE (NG_NETTYPE_IPV6)
|
||||
#else
|
||||
#define HDR_NETTYPE (NG_NETTYPE_UNDEF)
|
||||
#endif
|
||||
|
||||
ng_pktsnip_t *ng_ipv6_hdr_build(ng_pktsnip_t *payload,
|
||||
uint8_t *src, uint8_t src_len,
|
||||
uint8_t *dst, uint8_t dst_len)
|
||||
{
|
||||
ng_pktsnip_t *ipv6;
|
||||
ng_ipv6_hdr_t *hdr;
|
||||
|
||||
if (((src_len != 0) && (src_len != sizeof(ng_ipv6_addr_t))) ||
|
||||
((dst_len != 0) && (dst_len != sizeof(ng_ipv6_addr_t)))) {
|
||||
DEBUG("ipv6_hdr: Address length was not 0 or %zu byte.\n",
|
||||
sizeof(ng_ipv6_addr_t));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ipv6 = ng_pktbuf_add(payload, NULL, sizeof(ng_ipv6_hdr_t), HDR_NETTYPE);
|
||||
|
||||
if (ipv6 == NULL) {
|
||||
DEBUG("ipv6_hdr: no space left in packet buffer\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hdr = (ng_ipv6_hdr_t *)ipv6->data;
|
||||
|
||||
if ((src != NULL) && (src_len != 0)) {
|
||||
#ifdef MODULE_NG_IPV6_ADDR
|
||||
DEBUG("ipv6_hdr: set packet source to %s\n",
|
||||
ng_ipv6_addr_to_str(addr_str, (ng_ipv6_addr_t *)src,
|
||||
sizeof(addr_str)));
|
||||
#endif
|
||||
memcpy(&hdr->src, src, src_len);
|
||||
}
|
||||
|
||||
memset(&hdr->dst + dst_len, 0, sizeof(ng_ipv6_addr_t) - dst_len);
|
||||
|
||||
if ((dst != NULL) && (dst_len != 0)) {
|
||||
#ifdef MODULE_NG_IPV6_ADDR
|
||||
DEBUG("ipv6_hdr: set packet destination to %s\n",
|
||||
ng_ipv6_addr_to_str(addr_str, (ng_ipv6_addr_t *)dst,
|
||||
sizeof(addr_str)));
|
||||
#endif
|
||||
memcpy(&hdr->dst, dst, dst_len);
|
||||
}
|
||||
|
||||
hdr->v_tc_fl = byteorder_htonl(0x60000000); /* set version, tc and fl in one go*/
|
||||
hdr->nh = NG_PROTNUM_RESERVED;
|
||||
hdr->hl = 0;
|
||||
|
||||
return ipv6;
|
||||
}
|
||||
|
||||
/** @} */
|
@ -0,0 +1 @@
|
||||
include $(RIOTBASE)/Makefile.base
|
@ -0,0 +1 @@
|
||||
USEMODULE += ng_ipv6_hdr
|
@ -0,0 +1,406 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
*/
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "embUnit.h"
|
||||
|
||||
#include "net/ng_ipv6/addr.h"
|
||||
#include "net/ng_ipv6/hdr.h"
|
||||
#include "net/ng_pktbuf.h"
|
||||
#include "net/ng_protnum.h"
|
||||
#include "net/ng_inet_csum.h"
|
||||
|
||||
#include "unittests-constants.h"
|
||||
#include "tests-ipv6_hdr.h"
|
||||
|
||||
#define OTHER_BYTE (TEST_UINT16 >> 8)
|
||||
#define DEFAULT_TEST_SRC { { \
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, \
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f \
|
||||
} \
|
||||
}
|
||||
#define DEFAULT_TEST_DST { { \
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, \
|
||||
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f \
|
||||
} \
|
||||
}
|
||||
|
||||
static void test_ipv6_hdr_set_version(void)
|
||||
{
|
||||
uint8_t val[] = { TEST_UINT8 };
|
||||
|
||||
ng_ipv6_hdr_set_version((ng_ipv6_hdr_t *)val);
|
||||
|
||||
/*
|
||||
* Header format:
|
||||
* 1
|
||||
* +----+--
|
||||
* | 6 |
|
||||
* +----+--
|
||||
*/
|
||||
TEST_ASSERT_EQUAL_INT(0x60, val[0] & 0xf0);
|
||||
TEST_ASSERT_EQUAL_INT(TEST_UINT8 & 0x0f, val[0] & 0x0f);
|
||||
}
|
||||
|
||||
static void test_ipv6_hdr_get_version(void)
|
||||
{
|
||||
uint8_t val[] = { TEST_UINT8 };
|
||||
|
||||
/*
|
||||
* Header format:
|
||||
* 8
|
||||
* +----+----
|
||||
* | 6 |
|
||||
* +----+----
|
||||
*/
|
||||
TEST_ASSERT_EQUAL_INT(TEST_UINT8 >> 4,
|
||||
ng_ipv6_hdr_get_version((ng_ipv6_hdr_t *)val));
|
||||
}
|
||||
|
||||
static void test_ipv6_hdr_is_ipv6_hdr__false(void)
|
||||
{
|
||||
/*
|
||||
* Header format:
|
||||
* 8
|
||||
* +----+----
|
||||
* | 6 |
|
||||
* +----+----
|
||||
*/
|
||||
uint8_t val[] = { 0 };
|
||||
|
||||
TEST_ASSERT(!ng_ipv6_hdr_is_ipv6_hdr((ng_ipv6_hdr_t *)val));
|
||||
}
|
||||
|
||||
static void test_ipv6_hdr_is_ipv6_hdr__true(void)
|
||||
{
|
||||
/*
|
||||
* Header format:
|
||||
* 8
|
||||
* +----+----
|
||||
* | 6 |
|
||||
* +----+----
|
||||
*/
|
||||
uint8_t val[] = { 0x60 | (TEST_UINT8 & 0x0f) };
|
||||
|
||||
TEST_ASSERT(ng_ipv6_hdr_is_ipv6_hdr((ng_ipv6_hdr_t *)val));
|
||||
}
|
||||
|
||||
static void test_ipv6_hdr_set_tc(void)
|
||||
{
|
||||
uint8_t val[] = { TEST_UINT8, 0 };
|
||||
|
||||
ng_ipv6_hdr_set_tc((ng_ipv6_hdr_t *)val, OTHER_BYTE);
|
||||
|
||||
/*
|
||||
* Header format:
|
||||
* 8
|
||||
* +----+--------+--
|
||||
* | 6 | tc |
|
||||
* +----+--------+--
|
||||
*/
|
||||
TEST_ASSERT_EQUAL_INT((TEST_UINT8 & 0xf0) | (OTHER_BYTE >> 4), val[0]);
|
||||
TEST_ASSERT_EQUAL_INT((OTHER_BYTE << 4) & 0xf0, val[1]);
|
||||
}
|
||||
|
||||
static void test_ipv6_hdr_set_tc_ecn(void)
|
||||
{
|
||||
uint8_t val[] = { TEST_UINT8 };
|
||||
|
||||
ng_ipv6_hdr_set_tc_ecn((ng_ipv6_hdr_t *)val, OTHER_BYTE);
|
||||
|
||||
/*
|
||||
* Header format:
|
||||
* 8
|
||||
* +----+--------+--
|
||||
* | 6 | tc |
|
||||
* +----+--------+--
|
||||
* / \
|
||||
* 8 12
|
||||
* +----+------------+
|
||||
* | ecn| dscp |
|
||||
* +----+------------+
|
||||
*/
|
||||
TEST_ASSERT_EQUAL_INT((TEST_UINT8 & 0xf3) | ((OTHER_BYTE & 0x03) << 2), val[0]);
|
||||
}
|
||||
|
||||
static void test_ipv6_hdr_set_tc_dscp(void)
|
||||
{
|
||||
uint8_t val[] = { TEST_UINT8, 0 };
|
||||
|
||||
ng_ipv6_hdr_set_tc_dscp((ng_ipv6_hdr_t *)val, OTHER_BYTE);
|
||||
|
||||
/*
|
||||
* Header format:
|
||||
* 8
|
||||
* +----+--------+--
|
||||
* | 6 | tc |
|
||||
* +----+--------+--
|
||||
* / \
|
||||
* 8 12
|
||||
* +----+------------+
|
||||
* | ecn| dscp |
|
||||
* +----+------------+
|
||||
*/
|
||||
TEST_ASSERT_EQUAL_INT((TEST_UINT8 & 0xfc) | ((OTHER_BYTE & 0x30) >> 4), val[0]);
|
||||
TEST_ASSERT_EQUAL_INT((OTHER_BYTE & 0x0f) << 4, val[1]);
|
||||
}
|
||||
|
||||
static void test_ipv6_hdr_get_tc(void)
|
||||
{
|
||||
uint8_t val[] = { TEST_UINT8, OTHER_BYTE };
|
||||
|
||||
/*
|
||||
* Header format:
|
||||
* 8
|
||||
* +----+--------+--
|
||||
* | 6 | tc |
|
||||
* +----+--------+--
|
||||
*/
|
||||
TEST_ASSERT_EQUAL_INT(((TEST_UINT8 << 4) & 0xf0) | (OTHER_BYTE >> 4),
|
||||
ng_ipv6_hdr_get_tc((ng_ipv6_hdr_t *)val));
|
||||
}
|
||||
|
||||
static void test_ipv6_hdr_get_tc_ecn(void)
|
||||
{
|
||||
uint8_t val[] = { TEST_UINT8 };
|
||||
|
||||
/*
|
||||
* Header format:
|
||||
* 8
|
||||
* +----+--------+--
|
||||
* | 6 | tc |
|
||||
* +----+--------+--
|
||||
* / \
|
||||
* 8 12
|
||||
* +----+------------+
|
||||
* | ecn| dscp |
|
||||
* +----+------------+
|
||||
*/
|
||||
TEST_ASSERT_EQUAL_INT(TEST_UINT8 & 0x03,
|
||||
ng_ipv6_hdr_get_tc_ecn((ng_ipv6_hdr_t *)val));
|
||||
}
|
||||
|
||||
static void test_ipv6_hdr_get_tc_dscp(void)
|
||||
{
|
||||
uint8_t val[] = { TEST_UINT8, OTHER_BYTE };
|
||||
|
||||
/*
|
||||
* Header format:
|
||||
* 8
|
||||
* +----+--------+--
|
||||
* | 6 | tc |
|
||||
* +----+--------+--
|
||||
* / \
|
||||
* 8 12
|
||||
* +----+------------+
|
||||
* | ecn| dscp |
|
||||
* +----+------------+
|
||||
*/
|
||||
TEST_ASSERT_EQUAL_INT(((TEST_UINT8 & 0x03) << 4) | ((OTHER_BYTE & 0xf0) >> 4),
|
||||
ng_ipv6_hdr_get_tc_dscp((ng_ipv6_hdr_t *)val));
|
||||
}
|
||||
|
||||
static void test_ipv6_hdr_set_fl(void)
|
||||
{
|
||||
uint8_t val[] = { 0, TEST_UINT8, 0, 0 };
|
||||
|
||||
ng_ipv6_hdr_set_fl((ng_ipv6_hdr_t *)val, TEST_UINT32);
|
||||
|
||||
/*
|
||||
* Header format:
|
||||
* 8 16 24 32
|
||||
* +----+--------+--------------------+
|
||||
* | 6 | tc | flow label |
|
||||
* +----+--------+--------------------+
|
||||
*/
|
||||
TEST_ASSERT_EQUAL_INT(0, val[0]);
|
||||
TEST_ASSERT_EQUAL_INT((TEST_UINT8 & 0xf0) | ((TEST_UINT32 & 0x000f0000) >> 16),
|
||||
val[1]);
|
||||
TEST_ASSERT_EQUAL_INT((TEST_UINT32 & 0x0000ff00) >> 8,
|
||||
val[2]);
|
||||
TEST_ASSERT_EQUAL_INT((TEST_UINT32 & 0x000000ff), val[3]);
|
||||
}
|
||||
|
||||
static void test_ipv6_hdr_get_fl(void)
|
||||
{
|
||||
uint8_t val[] = { TEST_UINT8, OTHER_BYTE, 0, 0 };
|
||||
|
||||
/*
|
||||
* Header format:
|
||||
* 8 16 24 32
|
||||
* +----+--------+--------------------+
|
||||
* | 6 | tc | flow label |
|
||||
* +----+--------+--------------------+
|
||||
*/
|
||||
TEST_ASSERT_EQUAL_INT((OTHER_BYTE & 0x0f) << 16,
|
||||
ng_ipv6_hdr_get_fl((ng_ipv6_hdr_t *)val));
|
||||
}
|
||||
|
||||
static void test_ipv6_hdr_inet_csum(void)
|
||||
{
|
||||
/* source: https://www.cloudshark.org/captures/ea72fbab241b (No. 56) */
|
||||
uint16_t res = 0, payload_len;
|
||||
uint8_t val[] = {
|
||||
0x60, 0x00, 0x00, 0x00, 0x00, 0x38, 0x3a, 0xff, /* IPv6 header */
|
||||
0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x5a, 0x6d, 0x8f, 0xff, 0xfe, 0x56, 0x30, 0x09,
|
||||
0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||
0x86, 0x00, 0x00, 0x00, 0x40, 0x58, 0x07, 0x08, /* ICMPv6 payload */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* set checksum to 0 */
|
||||
0x03, 0x04, 0x40, 0xc0, 0x00, 0x00, 0x00, 0x1e,
|
||||
0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00,
|
||||
0x20, 0x02, 0x18, 0x3d, 0xdb, 0xa4, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0x01, 0x58, 0x6d, 0x8f, 0x56, 0x30, 0x09
|
||||
};
|
||||
|
||||
payload_len = sizeof(val) - sizeof(ng_ipv6_hdr_t);
|
||||
|
||||
/* calculate checksum of pseudo header */
|
||||
res = ng_ipv6_hdr_inet_csum(0, (ng_ipv6_hdr_t *)&val, NG_PROTNUM_ICMPV6,
|
||||
payload_len);
|
||||
/* calculate checksum of payload */
|
||||
res = ng_inet_csum(res, val + sizeof(ng_ipv6_hdr_t), payload_len);
|
||||
res = ~res; /* take 1's-complement for correct checksum */
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(0xab32, res);
|
||||
}
|
||||
|
||||
static void test_ipv6_hdr_build__wrong_src_len(void)
|
||||
{
|
||||
ng_ipv6_addr_t src = DEFAULT_TEST_SRC;
|
||||
ng_ipv6_addr_t dst = DEFAULT_TEST_DST;
|
||||
|
||||
TEST_ASSERT_NULL(ng_ipv6_hdr_build(NULL, (uint8_t *)&src,
|
||||
sizeof(ng_ipv6_addr_t) + TEST_UINT8,
|
||||
(uint8_t *)&dst,
|
||||
sizeof(ng_ipv6_addr_t)));
|
||||
TEST_ASSERT(ng_pktbuf_is_empty());
|
||||
}
|
||||
|
||||
static void test_ipv6_hdr_build__wrong_dst_len(void)
|
||||
{
|
||||
ng_ipv6_addr_t src = DEFAULT_TEST_SRC;
|
||||
ng_ipv6_addr_t dst = DEFAULT_TEST_DST;
|
||||
|
||||
TEST_ASSERT_NULL(ng_ipv6_hdr_build(NULL, (uint8_t *)&src,
|
||||
sizeof(ng_ipv6_addr_t),
|
||||
(uint8_t *)&dst,
|
||||
sizeof(ng_ipv6_addr_t) + TEST_UINT8));
|
||||
TEST_ASSERT(ng_pktbuf_is_empty());
|
||||
}
|
||||
|
||||
static void test_ipv6_hdr_build__src_NULL(void)
|
||||
{
|
||||
ng_ipv6_addr_t dst = DEFAULT_TEST_DST;
|
||||
ng_pktsnip_t *pkt;
|
||||
ng_ipv6_hdr_t *hdr;
|
||||
|
||||
TEST_ASSERT(ng_pktbuf_is_empty());
|
||||
TEST_ASSERT_NOT_NULL((pkt = ng_ipv6_hdr_build(NULL, NULL, 0, (uint8_t *)&dst,
|
||||
sizeof(ng_ipv6_addr_t))));
|
||||
hdr = pkt->data;
|
||||
TEST_ASSERT_NOT_NULL(hdr);
|
||||
TEST_ASSERT(ng_ipv6_hdr_is_ipv6_hdr(hdr));
|
||||
TEST_ASSERT_EQUAL_INT(0, ng_ipv6_hdr_get_tc(hdr));
|
||||
TEST_ASSERT_EQUAL_INT(0, ng_ipv6_hdr_get_fl(hdr));
|
||||
TEST_ASSERT_EQUAL_INT(NG_PROTNUM_RESERVED, hdr->nh);
|
||||
TEST_ASSERT_EQUAL_INT(0, hdr->hl);
|
||||
TEST_ASSERT(ng_ipv6_addr_equal(&dst, &hdr->dst));
|
||||
TEST_ASSERT(!ng_pktbuf_is_empty());
|
||||
ng_pktbuf_reset();
|
||||
}
|
||||
|
||||
static void test_ipv6_hdr_build__dst_NULL(void)
|
||||
{
|
||||
ng_ipv6_addr_t src = DEFAULT_TEST_SRC;
|
||||
ng_pktsnip_t *pkt;
|
||||
ng_ipv6_hdr_t *hdr;
|
||||
|
||||
TEST_ASSERT(ng_pktbuf_is_empty());
|
||||
TEST_ASSERT_NOT_NULL((pkt = ng_ipv6_hdr_build(NULL, (uint8_t *)&src,
|
||||
sizeof(ng_ipv6_addr_t),
|
||||
NULL, 0)));
|
||||
hdr = pkt->data;
|
||||
TEST_ASSERT_NOT_NULL(hdr);
|
||||
TEST_ASSERT(ng_ipv6_hdr_is_ipv6_hdr(hdr));
|
||||
TEST_ASSERT_EQUAL_INT(0, ng_ipv6_hdr_get_tc(hdr));
|
||||
TEST_ASSERT_EQUAL_INT(0, ng_ipv6_hdr_get_fl(hdr));
|
||||
TEST_ASSERT_EQUAL_INT(NG_PROTNUM_RESERVED, hdr->nh);
|
||||
TEST_ASSERT_EQUAL_INT(0, hdr->hl);
|
||||
TEST_ASSERT(ng_ipv6_addr_equal(&src, &hdr->src));
|
||||
TEST_ASSERT(!ng_pktbuf_is_empty());
|
||||
ng_pktbuf_reset();
|
||||
}
|
||||
|
||||
static void test_ipv6_hdr_build__complete(void)
|
||||
{
|
||||
ng_ipv6_addr_t src = DEFAULT_TEST_SRC;
|
||||
ng_ipv6_addr_t dst = DEFAULT_TEST_DST;
|
||||
ng_pktsnip_t *pkt;
|
||||
ng_ipv6_hdr_t *hdr;
|
||||
|
||||
TEST_ASSERT(ng_pktbuf_is_empty());
|
||||
TEST_ASSERT_NOT_NULL((pkt = ng_ipv6_hdr_build(NULL, (uint8_t *)&src,
|
||||
sizeof(ng_ipv6_addr_t),
|
||||
(uint8_t *)&dst,
|
||||
sizeof(ng_ipv6_addr_t))));
|
||||
hdr = pkt->data;
|
||||
TEST_ASSERT_NOT_NULL(hdr);
|
||||
TEST_ASSERT(ng_ipv6_hdr_is_ipv6_hdr(hdr));
|
||||
TEST_ASSERT_EQUAL_INT(0, ng_ipv6_hdr_get_tc(hdr));
|
||||
TEST_ASSERT_EQUAL_INT(0, ng_ipv6_hdr_get_fl(hdr));
|
||||
TEST_ASSERT_EQUAL_INT(NG_PROTNUM_RESERVED, hdr->nh);
|
||||
TEST_ASSERT_EQUAL_INT(0, hdr->hl);
|
||||
TEST_ASSERT(ng_ipv6_addr_equal(&src, &hdr->src));
|
||||
TEST_ASSERT(ng_ipv6_addr_equal(&dst, &hdr->dst));
|
||||
TEST_ASSERT(!ng_pktbuf_is_empty());
|
||||
ng_pktbuf_reset();
|
||||
}
|
||||
|
||||
Test *tests_ipv6_hdr_tests(void)
|
||||
{
|
||||
EMB_UNIT_TESTFIXTURES(fixtures) {
|
||||
new_TestFixture(test_ipv6_hdr_set_version),
|
||||
new_TestFixture(test_ipv6_hdr_get_version),
|
||||
new_TestFixture(test_ipv6_hdr_is_ipv6_hdr__false),
|
||||
new_TestFixture(test_ipv6_hdr_is_ipv6_hdr__true),
|
||||
new_TestFixture(test_ipv6_hdr_set_tc),
|
||||
new_TestFixture(test_ipv6_hdr_set_tc_ecn),
|
||||
new_TestFixture(test_ipv6_hdr_set_tc_dscp),
|
||||
new_TestFixture(test_ipv6_hdr_get_tc),
|
||||
new_TestFixture(test_ipv6_hdr_get_tc_ecn),
|
||||
new_TestFixture(test_ipv6_hdr_get_tc_dscp),
|
||||
new_TestFixture(test_ipv6_hdr_set_fl),
|
||||
new_TestFixture(test_ipv6_hdr_get_fl),
|
||||
new_TestFixture(test_ipv6_hdr_inet_csum),
|
||||
new_TestFixture(test_ipv6_hdr_build__wrong_src_len),
|
||||
new_TestFixture(test_ipv6_hdr_build__wrong_dst_len),
|
||||
new_TestFixture(test_ipv6_hdr_build__src_NULL),
|
||||
new_TestFixture(test_ipv6_hdr_build__dst_NULL),
|
||||
new_TestFixture(test_ipv6_hdr_build__complete),
|
||||
};
|
||||
|
||||
EMB_UNIT_TESTCALLER(ipv6_hdr_tests, NULL, NULL, fixtures);
|
||||
|
||||
return (Test *)&ipv6_hdr_tests;
|
||||
}
|
||||
|
||||
void tests_ipv6_hdr(void)
|
||||
{
|
||||
TESTS_RUN(tests_ipv6_hdr_tests());
|
||||
}
|
||||
/** @} */
|
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Martin Lenders
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup unittests
|
||||
* @{
|
||||
*
|
||||
* @file tests-ipv6_hdr.h
|
||||
* @brief Unittests for the ``ipv6_hdr`` module
|
||||
*
|
||||
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||
*/
|
||||
#ifndef TESTS_IPV6_HDR_H_
|
||||
#define TESTS_IPV6_HDR_H_
|
||||
|
||||
#include "embUnit.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief The entry point of this test suite.
|
||||
*/
|
||||
void tests_ipv6_hdr(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* TESTS_IPV6_HDR_H_ */
|
||||
/** @} */
|
Loading…
Reference in New Issue