mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
Merge pull request #3362 from authmillenon/ng_neterr/feat/initial
[RFC] gnrc: initial import of an asynchronous error reporting API
This commit is contained in:
commit
131cae626c
@ -6,6 +6,7 @@ PSEUDOMODULES += gnrc_netif_default
|
||||
PSEUDOMODULES += gnrc_ipv6_default
|
||||
PSEUDOMODULES += gnrc_ipv6_router
|
||||
PSEUDOMODULES += gnrc_ipv6_router_default
|
||||
PSEUDOMODULES += gnrc_neterr
|
||||
PSEUDOMODULES += gnrc_sixlowpan_default
|
||||
PSEUDOMODULES += gnrc_sixlowpan_border_router_default
|
||||
PSEUDOMODULES += gnrc_sixlowpan_nd_border_router
|
||||
|
93
sys/include/net/gnrc/neterr.h
Normal file
93
sys/include/net/gnrc/neterr.h
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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_gnrc_neterr Error reporting
|
||||
* @ingroup net
|
||||
* @brief Allows for asynchronous error reporting in the network stack.
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Error reporting definitions.
|
||||
*
|
||||
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||
*/
|
||||
#ifndef GNRC_NETERR_H_
|
||||
#define GNRC_NETERR_H_
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "kernel_types.h"
|
||||
#include "msg.h"
|
||||
#include "net/gnrc/pkt.h"
|
||||
#include "thread.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief @ref core_msg type for reporting an error.
|
||||
*/
|
||||
#define GNRC_NETERR_MSG_TYPE (0x0206)
|
||||
|
||||
/**
|
||||
* @brief Error code to signalise success (no error occured) to an gnrc_neterr subscriber.
|
||||
*/
|
||||
#define GNRC_NETERR_SUCCESS (0)
|
||||
|
||||
/**
|
||||
* @brief Reports an error to all subscribers of errors to @p pkt.
|
||||
*
|
||||
* @param[in] pkt Packet snip to report on.
|
||||
* @param[in] err The error code for the packet.
|
||||
*/
|
||||
#ifdef MODULE_GNRC_NETERR
|
||||
static inline void gnrc_neterr_report(gnrc_pktsnip_t *pkt, uint32_t err)
|
||||
{
|
||||
if (pkt->err_sub != KERNEL_PID_UNDEF) {
|
||||
msg_t msg;
|
||||
|
||||
msg.type = GNRC_NETERR_MSG_TYPE;
|
||||
msg.content.value = err;
|
||||
|
||||
msg_send(&msg, pkt->err_sub);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define gnrc_neterr_report(pkt, err) (void)pkt; (void)err
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Registers the current thread for errors on a @ref gnrc_pktsnip_t.
|
||||
*
|
||||
* @param[in] pkt Packet snip to register for errors.
|
||||
*
|
||||
* @return 0, on success.
|
||||
* @return EALREADY, if there already someone registered to errors on @p pkt.
|
||||
*/
|
||||
#ifdef MODULE_GNRC_NETERR
|
||||
static inline int gnrc_neterr_reg(gnrc_pktsnip_t *pkt)
|
||||
{
|
||||
if (pkt->err_sub != KERNEL_PID_UNDEF) {
|
||||
return EALREADY;
|
||||
}
|
||||
pkt->err_sub = sched_active_pid;
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define gnrc_neterr_reg(pkt) (0)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* GNRC_NETERR_H_ */
|
||||
/** @} */
|
@ -25,6 +25,7 @@
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "kernel_types.h"
|
||||
#include "net/gnrc/nettype.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
@ -110,6 +111,10 @@ typedef struct gnrc_pktsnip {
|
||||
void *data; /**< pointer to the data of the snip */
|
||||
size_t size; /**< the length of the snip in byte */
|
||||
gnrc_nettype_t type; /**< protocol of the packet snip */
|
||||
#ifdef MODULE_GNRC_NETERR
|
||||
kernel_pid_t err_sub; /**< subscriber to errors related to this
|
||||
* packet snip */
|
||||
#endif
|
||||
} gnrc_pktsnip_t;
|
||||
|
||||
/**
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "atomic.h"
|
||||
#include "cpu_conf.h"
|
||||
#include "net/gnrc/pkt.h"
|
||||
#include "net/gnrc/neterr.h"
|
||||
#include "net/gnrc/nettype.h"
|
||||
#include "utlist.h"
|
||||
|
||||
@ -141,13 +142,26 @@ void gnrc_pktbuf_hold(gnrc_pktsnip_t *pkt, unsigned int num);
|
||||
|
||||
/**
|
||||
* @brief Decreases gnrc_pktsnip_t::users of @p pkt atomically and removes it if it
|
||||
* reaches 0.
|
||||
* reaches 0 and reports a possible error through an error code, if
|
||||
* @ref net_gnrc_neterr is included.
|
||||
*
|
||||
* @pre All snips of @p pkt must be in the packet buffer.
|
||||
*
|
||||
* @param[in] pkt A packet.
|
||||
* @param[in] err An error code.
|
||||
*/
|
||||
void gnrc_pktbuf_release(gnrc_pktsnip_t *pkt);
|
||||
void gnrc_pktbuf_release_error(gnrc_pktsnip_t *pkt, uint32_t err);
|
||||
|
||||
/**
|
||||
* @brief Decreases gnrc_pktsnip_t::users of @p pkt atomically and removes it if it
|
||||
* reaches 0 and reports @ref GNRC_NETERR_SUCCESS.
|
||||
*
|
||||
* @param[in] pkt A packet.
|
||||
*/
|
||||
static inline void gnrc_pktbuf_release(gnrc_pktsnip_t *pkt)
|
||||
{
|
||||
gnrc_pktbuf_release_error(pkt, GNRC_NETERR_SUCCESS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Must be called once before there is a write operation in a thread.
|
||||
@ -189,7 +203,7 @@ gnrc_pktsnip_t *gnrc_pktbuf_get_iovec(gnrc_pktsnip_t *pkt, size_t *len);
|
||||
* @return The new reference to @p pkt.
|
||||
*/
|
||||
static inline gnrc_pktsnip_t *gnrc_pktbuf_remove_snip(gnrc_pktsnip_t *pkt,
|
||||
gnrc_pktsnip_t *snip)
|
||||
gnrc_pktsnip_t *snip)
|
||||
{
|
||||
LL_DELETE(pkt, snip);
|
||||
snip->next = NULL;
|
||||
|
@ -64,9 +64,21 @@ static inline bool _pktbuf_contains(void *ptr)
|
||||
/* fits size to byte alignment */
|
||||
static inline size_t _align(size_t size)
|
||||
{
|
||||
return ((size + _ALIGNMENT_MASK) & ~(_ALIGNMENT_MASK));
|
||||
return (size + _ALIGNMENT_MASK) & ~(_ALIGNMENT_MASK);
|
||||
}
|
||||
|
||||
static inline void _set_pktsnip(gnrc_pktsnip_t *pkt, gnrc_pktsnip_t *next,
|
||||
void *data, size_t size, gnrc_nettype_t type)
|
||||
{
|
||||
pkt->next = next;
|
||||
pkt->data = data;
|
||||
pkt->size = size;
|
||||
pkt->type = type;
|
||||
pkt->users = 1;
|
||||
#ifdef MODULE_GNRC_NETERR
|
||||
pkt->err_sub = KERNEL_PID_UNDEF;
|
||||
#endif
|
||||
}
|
||||
|
||||
void gnrc_pktbuf_init(void)
|
||||
{
|
||||
@ -81,6 +93,7 @@ gnrc_pktsnip_t *gnrc_pktbuf_add(gnrc_pktsnip_t *next, void *data, size_t size,
|
||||
gnrc_nettype_t type)
|
||||
{
|
||||
gnrc_pktsnip_t *pkt;
|
||||
|
||||
if ((size == 0) || (size > GNRC_PKTBUF_SIZE)) {
|
||||
DEBUG("pktbuf: size (%u) == 0 || size == GNRC_PKTBUF_SIZE (%u)\n",
|
||||
(unsigned)size, GNRC_PKTBUF_SIZE);
|
||||
@ -98,6 +111,8 @@ gnrc_pktsnip_t *gnrc_pktbuf_mark(gnrc_pktsnip_t *pkt, size_t size, gnrc_nettype_
|
||||
/* size required for chunk */
|
||||
size_t required_new_size = (size < sizeof(_unused_t)) ?
|
||||
_align(sizeof(_unused_t)) : _align(size);
|
||||
void *new_data_marked;
|
||||
|
||||
mutex_lock(&_mutex);
|
||||
if ((size == 0) || (pkt == NULL) || (size > pkt->size) || (pkt->data == NULL)) {
|
||||
DEBUG("pktbuf: size == 0 (was %u) or pkt == NULL (was %p) or "
|
||||
@ -120,7 +135,7 @@ gnrc_pktsnip_t *gnrc_pktbuf_mark(gnrc_pktsnip_t *pkt, size_t size, gnrc_nettype_
|
||||
}
|
||||
/* would not fit unused marker => move data around */
|
||||
if ((size < required_new_size) || ((pkt->size - size) < sizeof(_unused_t))) {
|
||||
void *new_data_marked, *new_data_rest;
|
||||
void *new_data_rest;
|
||||
new_data_marked = _pktbuf_alloc(size);
|
||||
if (new_data_marked == NULL) {
|
||||
DEBUG("pktbuf: could not reallocate marked section.\n");
|
||||
@ -143,14 +158,11 @@ gnrc_pktsnip_t *gnrc_pktbuf_mark(gnrc_pktsnip_t *pkt, size_t size, gnrc_nettype_
|
||||
pkt->data = new_data_rest;
|
||||
}
|
||||
else {
|
||||
marked_snip->data = pkt->data;
|
||||
new_data_marked = pkt->data;
|
||||
pkt->data = ((uint8_t *)pkt->data) + size;
|
||||
}
|
||||
pkt->size -= size;
|
||||
marked_snip->next = pkt->next;
|
||||
marked_snip->size = size;
|
||||
marked_snip->type = type;
|
||||
marked_snip->users = 1;
|
||||
_set_pktsnip(marked_snip, pkt->next, new_data_marked, size, type);
|
||||
pkt->next = marked_snip;
|
||||
mutex_unlock(&_mutex);
|
||||
return marked_snip;
|
||||
@ -160,6 +172,7 @@ int gnrc_pktbuf_realloc_data(gnrc_pktsnip_t *pkt, size_t size)
|
||||
{
|
||||
size_t aligned_size = (size < sizeof(_unused_t)) ?
|
||||
_align(sizeof(_unused_t)) : _align(size);
|
||||
|
||||
mutex_lock(&_mutex);
|
||||
assert((pkt != NULL) && (pkt->data != NULL) && _pktbuf_contains(pkt->data));
|
||||
if (size == 0) {
|
||||
@ -204,7 +217,7 @@ void gnrc_pktbuf_hold(gnrc_pktsnip_t *pkt, unsigned int num)
|
||||
mutex_unlock(&_mutex);
|
||||
}
|
||||
|
||||
void gnrc_pktbuf_release(gnrc_pktsnip_t *pkt)
|
||||
void gnrc_pktbuf_release_error(gnrc_pktsnip_t *pkt, uint32_t err)
|
||||
{
|
||||
mutex_lock(&_mutex);
|
||||
while (pkt) {
|
||||
@ -219,6 +232,8 @@ void gnrc_pktbuf_release(gnrc_pktsnip_t *pkt)
|
||||
else {
|
||||
pkt->users--;
|
||||
}
|
||||
DEBUG("pktbuf: report status code %" PRIu32 "\n", err);
|
||||
gnrc_neterr_report(pkt, err);
|
||||
pkt = tmp;
|
||||
}
|
||||
mutex_unlock(&_mutex);
|
||||
@ -378,6 +393,7 @@ static gnrc_pktsnip_t *_create_snip(gnrc_pktsnip_t *next, void *data, size_t siz
|
||||
{
|
||||
gnrc_pktsnip_t *pkt = _pktbuf_alloc(sizeof(gnrc_pktsnip_t));
|
||||
void *_data;
|
||||
|
||||
if (pkt == NULL) {
|
||||
DEBUG("pktbuf: error allocating new packet snip\n");
|
||||
return NULL;
|
||||
@ -388,11 +404,7 @@ static gnrc_pktsnip_t *_create_snip(gnrc_pktsnip_t *next, void *data, size_t siz
|
||||
_pktbuf_free(pkt, sizeof(gnrc_pktsnip_t));
|
||||
return NULL;
|
||||
}
|
||||
pkt->next = next;
|
||||
pkt->size = size;
|
||||
pkt->data = _data;
|
||||
pkt->type = type;
|
||||
pkt->users = 1;
|
||||
_set_pktsnip(pkt, next, _data, size, type);
|
||||
if (data != NULL) {
|
||||
memcpy(_data, data, size);
|
||||
}
|
||||
@ -402,6 +414,7 @@ static gnrc_pktsnip_t *_create_snip(gnrc_pktsnip_t *next, void *data, size_t siz
|
||||
static void *_pktbuf_alloc(size_t size)
|
||||
{
|
||||
_unused_t *prev = NULL, *ptr = _first_unused;
|
||||
|
||||
size = (size < sizeof(_unused_t)) ? _align(sizeof(_unused_t)) : _align(size);
|
||||
while (ptr && (size > ptr->size)) {
|
||||
prev = ptr;
|
||||
@ -456,6 +469,7 @@ static inline _unused_t *_merge(_unused_t *a, _unused_t *b)
|
||||
static void _pktbuf_free(void *data, size_t size)
|
||||
{
|
||||
_unused_t *new = (_unused_t *)data, *prev = NULL, *ptr = _first_unused;
|
||||
|
||||
if (!_pktbuf_contains(data)) {
|
||||
return;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user