diff --git a/Makefile.pseudomodules b/Makefile.pseudomodules index 2f9c7da734a02d3d7fd1a1dd6d4ed5de6a7b6fa2..a770f74b881e6293243beb5f4c5299bf16fa9229 100644 --- a/Makefile.pseudomodules +++ b/Makefile.pseudomodules @@ -1,2 +1,3 @@ PSEUDOMODULES += defaulttransceiver PSEUDOMODULES += transport_layer +PSEUDOMODULES += pktqueue diff --git a/sys/Makefile.include b/sys/Makefile.include index 171a53d537df002d5a35a8f095304a74fba99ec8..827ec61aa4a4469bb1d0bdee2333bd3b0d8f96bc 100644 --- a/sys/Makefile.include +++ b/sys/Makefile.include @@ -18,6 +18,9 @@ endif ifneq (,$(filter net_if,$(USEMODULE))) USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include endif +ifneq (,$(filter pktqueue,$(USEMODULE))) + USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include +endif ifneq (,$(filter protocol_multiplex,$(USEMODULE))) USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include endif diff --git a/sys/net/include/pktqueue.h b/sys/net/include/pktqueue.h new file mode 100644 index 0000000000000000000000000000000000000000..d706a2d2cac9514ac739a2410a78e86ea2fafc8c --- /dev/null +++ b/sys/net/include/pktqueue.h @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2014 Martin 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 pktqueue + * @addtogroup net + * @{ + * + * @file pktqueue.h + * @brief Pointer-centric wrapper for @ref priority_queue + * + * @author Martine Lenders <mlenders@inf.fu-berlin.de> + */ + +#ifndef __PKTQUEUE_H_ +#define __PKTQUEUE_H_ + +#include <stdint.h> +#include <stdlib.h> + +#include "priority_queue.h" + +/** + * @brief data type for packet queue nodes + * + * @extends priority_queue_node_t + */ +typedef struct pktqueue_node_t { + struct pktqueue_node_t *next; /**< next node in queue */ + void *data; /**< pointer to the data */ + uint32_t priority; /**< priority of the node */ +} pktqueue_node_t; + +/** + * @brief data type for packet queues + * + * @extends prioriry_queue_t + */ +typedef struct { + pktqueue_node_t *first; /**< first node in the queue */ +} pktqueue_t; + +/** + * @brief Static initializer for pktqueue_node_t + */ +#define PKTQUEUE_NODE_INIT { NULL, NULL, 0 } + +/** + * @brief Initializes a packet queue node. + * @details For initialization of variables use PKTQUEUE_NODE_INIT instead. + * Only use this function for dynamically allocated packet queue nodes. + * + * @param[out] node pre-allocated pktqueue_node_t object. must not be NULL. + */ +static inline void pktqueue_node_init(pktqueue_node_t *node) +{ + priority_queue_node_init((priority_queue_node_t *)node); +} + +/** + * @brief Static initializer for pktqueue_t. + */ +#define PKTQUEUE_INIT PRIORITY_QUEUE_INIT + +/** + * @brief Initialize a packet queue object. + * @details For initialization of variables use PKTQUEUE_INIT + * instead. Only use this function for dynamically allocated + * packet queues. + * @param[out] queue pre-allocated pktqueue_t object, must not be NULL. + */ +static inline void pktqueue_init(pktqueue_t *queue) +{ + priority_queue_init((priority_queue_t *)queue); +} + +/** + * @brief get the packet queue's head without removing it + * + * @param[out] root the queue + * + * @return the head + */ +static inline pktqueue_node_t *pktqueue_get_head(pktqueue_t *queue) +{ + return queue->first; +} + +/** + * @brief remove the packet queue's head + * + * @param[in] root the queue + * + * @return the old head + */ +static inline pktqueue_node_t *pktqueue_remove_head(pktqueue_t *queue) +{ + return (pktqueue_node_t *)priority_queue_remove_head((priority_queue_t *)queue); +} + +/** + * @brief add *node* into *queue* based on its priority + * + * @details The new node will be appended after objects with the same + * priority. + * + * @param[in] queue the queue + * @param[in] node the node to add + */ +static inline void pktqueue_add(pktqueue_t *queue, pktqueue_node_t *node) +{ + priority_queue_add((priority_queue_t *)queue, (priority_queue_node_t *) node); +} + +/** + * @brief remove *node* from *queue* + * + * @param[in] queue the queue + * @param[in] node the node to remove + */ +static inline void pktqueue_remove(pktqueue_t *queue, pktqueue_node_t *node) +{ + priority_queue_remove((priority_queue_t *)queue, (priority_queue_node_t *) node); +} + +#endif /* __PKTQUEUE_H_ */ +/** + * @} + */ diff --git a/tests/unittests/tests-pktqueue/Makefile b/tests/unittests/tests-pktqueue/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..1c51296ceb6bc70cfde932c76b0a9ded33a80b97 --- /dev/null +++ b/tests/unittests/tests-pktqueue/Makefile @@ -0,0 +1,3 @@ +MODULE = tests-pktqueue + +include $(RIOTBASE)/Makefile.base diff --git a/tests/unittests/tests-pktqueue/Makefile.include b/tests/unittests/tests-pktqueue/Makefile.include new file mode 100644 index 0000000000000000000000000000000000000000..6d5bae66323c6c84ac62b753f11377c98c2b0c6f --- /dev/null +++ b/tests/unittests/tests-pktqueue/Makefile.include @@ -0,0 +1 @@ +USEMODULE += pktqueue diff --git a/tests/unittests/tests-pktqueue/tests-pktqueue.c b/tests/unittests/tests-pktqueue/tests-pktqueue.c new file mode 100644 index 0000000000000000000000000000000000000000..ebb9d2f3ac4977146721ba384a7b7cf88ec4c3b1 --- /dev/null +++ b/tests/unittests/tests-pktqueue/tests-pktqueue.c @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2014 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. + */ + +/** + * @{ + * + * @file tests-pktqueue.c + */ +#include <string.h> + +#include "embUnit/embUnit.h" + +#include "pktqueue.h" + +#include "tests-pktqueue.h" + +#define Q_LEN (4) + +static pktqueue_t q = PKTQUEUE_INIT; +static pktqueue_node_t qe[Q_LEN]; + +static void set_up(void) +{ + pktqueue_init(&q); + + for (unsigned i = 0; i < Q_LEN; ++i) { + pktqueue_node_init(&(qe[i])); + } +} + +static void test_pktqueue_remove_head_empty(void) +{ + pktqueue_t *root = &q; + pktqueue_node_t *res; + + res = pktqueue_remove_head(root); + + TEST_ASSERT_NULL(res); +} + +static void test_pktqueue_remove_head_one(void) +{ + pktqueue_t *root = &q; + pktqueue_node_t *elem = &(qe[1]), *res; + + elem->data = (void *)62801; + + pktqueue_add(root, elem); + + res = pktqueue_remove_head(root); + + TEST_ASSERT(res == elem); + TEST_ASSERT(((void *)62801) == res->data); + + res = pktqueue_remove_head(root); + + TEST_ASSERT_NULL(res); +} + +static void test_pktqueue_add_one(void) +{ + pktqueue_t *root = &q; + pktqueue_node_t *elem = &(qe[1]); + + elem->data = (void *)7317; + elem->priority = 713643658; + + pktqueue_add(root, elem); + + TEST_ASSERT(root->first == elem); + TEST_ASSERT(((void *)7317) == root->first->data); + TEST_ASSERT_EQUAL_INT(713643658, root->first->priority); + + TEST_ASSERT_NULL(root->first->next); +} + +static void test_pktqueue_add_two_equal(void) +{ + pktqueue_t *root = &q; + pktqueue_node_t *elem1 = &(qe[1]), *elem2 = &(qe[2]); + + elem1->data = (void *)27088; + elem1->priority = 14202; + + elem2->data = (void *)4356; + elem2->priority = 14202; + + pktqueue_add(root, elem1); + pktqueue_add(root, elem2); + + TEST_ASSERT(root->first == elem2); + TEST_ASSERT(((void *)4356) == root->first->data); + TEST_ASSERT_EQUAL_INT(14202, root->first->priority); + + TEST_ASSERT(root->first->next == elem1); + TEST_ASSERT(((void *)27088) == root->first->next->data); + TEST_ASSERT_EQUAL_INT(14202, root->first->next->priority); + + TEST_ASSERT_NULL(root->first->next->next); +} + +static void test_pktqueue_add_two_distinct(void) +{ + pktqueue_t *root = &q; + pktqueue_node_t *elem1 = &(qe[1]), *elem2 = &(qe[2]); + + elem1->data = (void *)46421; + elem1->priority = 4567; + + elem2->data = (void *)43088; + elem2->priority = 1234; + + pktqueue_add(root, elem1); + pktqueue_add(root, elem2); + + TEST_ASSERT(root->first == elem2); + TEST_ASSERT(((void *)43088) == root->first->data); + TEST_ASSERT_EQUAL_INT(1234, root->first->priority); + + TEST_ASSERT(root->first->next == elem1); + TEST_ASSERT(((void *)46421) == root->first->next->data); + TEST_ASSERT_EQUAL_INT(4567, root->first->next->priority); + + TEST_ASSERT_NULL(root->first->next->next); +} + +static void test_pktqueue_remove_one(void) +{ + pktqueue_t *root = &q; + pktqueue_node_t *elem1 = &(qe[1]), *elem2 = &(qe[2]), *elem3 = &(qe[3]); + + pktqueue_add(root, elem1); + pktqueue_add(root, elem2); + pktqueue_add(root, elem3); + pktqueue_remove(root, elem2); + + TEST_ASSERT(root->first == elem1); + TEST_ASSERT(root->first->next == elem3); + TEST_ASSERT_NULL(root->first->next->next); +} + +Test *tests_pktqueue_tests(void) +{ + EMB_UNIT_TESTFIXTURES(fixtures) { + new_TestFixture(test_pktqueue_remove_head_empty), + new_TestFixture(test_pktqueue_remove_head_one), + new_TestFixture(test_pktqueue_add_one), + new_TestFixture(test_pktqueue_add_two_equal), + new_TestFixture(test_pktqueue_add_two_distinct), + new_TestFixture(test_pktqueue_remove_one), + }; + + EMB_UNIT_TESTCALLER(pktqueue_tests, set_up, NULL, fixtures); + + return (Test *)&pktqueue_tests; +} + +void tests_pktqueue(void) +{ + TESTS_RUN(tests_pktqueue_tests()); +} +/** @} */ diff --git a/tests/unittests/tests-pktqueue/tests-pktqueue.h b/tests/unittests/tests-pktqueue/tests-pktqueue.h new file mode 100644 index 0000000000000000000000000000000000000000..340ba3f65732605d2897c1f1a7f809f5151cb818 --- /dev/null +++ b/tests/unittests/tests-pktqueue/tests-pktqueue.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2014 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-pktqueue.h + * @brief Unittests for the ``pktqueue`` module + * + * @author Martine Lenders <mlenders@inf.fu-berlin.de> + */ +#ifndef __TESTS_PKTQUEUE_H_ +#define __TESTS_PKTQUEUE_H_ + +#include "../unittests.h" + +/** + * @brief The entry point of this test suite. + */ +void tests_pktqueue(void); + +#endif /* __TESTS_PKTQUEUE_H_ */ +/** @} */