diff --git a/sys/Makefile b/sys/Makefile index b13309d055365242e2e01d0c66a915a37a6ae9e9..1a0761a737186ad33555aac48c2456cf0706a3ac 100644 --- a/sys/Makefile +++ b/sys/Makefile @@ -86,6 +86,9 @@ endif ifneq (,$(filter nhdp,$(USEMODULE))) DIRS += net/routing/nhdp endif +ifneq (,$(filter ng_nomac,$(USEMODULE))) + DIRS += net/link_layer/ng_nomac +endif DIRS += $(dir $(wildcard $(addsuffix /Makefile, ${USEMODULE}))) diff --git a/sys/include/net/ng_nomac.h b/sys/include/net/ng_nomac.h new file mode 100644 index 0000000000000000000000000000000000000000..70e483f7cf9b59d8eab5faf46b62621e2193e620 --- /dev/null +++ b/sys/include/net/ng_nomac.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2015 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_nomac Simplest possible MAC layer + * @ingroup net + * @brief Simplest possible MAC protocol that sends without considering + * the state of the medium + * @{ + * + * @file + * @brief Interface definition for the NOMAC MAC layer + * + * @author Hauke Petersen <hauke.petersen@fu-berlin.de> + */ + +#ifndef NG_NOMAC_H_ +#define NG_NOMAC_H_ + +#include "kernel.h" +#include "net/ng_netdev.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Set the default message queue size for NOMAC layers + */ +#ifndef NG_NOMAC_MSG_QUEUE_SIZE +#define NG_NOMAC_MSG_QUEUE_SIZE (8U) +#endif + +/** + * @brief Initialize an instance of the NOMAC layer + * + * The initialization starts a new thread that connects to the given netdev + * device and starts a link layer event loop. + * + * @param[in] stack stack for the control thread + * @param[in] stacksize size of *stack* + * @param[in] priority priority for the thread housing the NOMAC instance + * @param[in] name name of the thread housing the NOMAC instance + * @param[in] dev netdev device, needs to be already initialized + * + * @return PID of NOMAC thread on success + * @return -EINVAL if creation of thread fails + * @return -ENODEV if *dev* is invalid + */ +kernel_pid_t ng_nomac_init(char *stack, int stacksize, char priority, + const char *name, ng_netdev_t *dev); + +#ifdef __cplusplus +} +#endif + +#endif /* __NOMAC_H_ */ +/** @} */ diff --git a/sys/net/link_layer/ng_nomac/Makefile b/sys/net/link_layer/ng_nomac/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..48422e909a47d7cd428d10fa73825060ccc8d8c2 --- /dev/null +++ b/sys/net/link_layer/ng_nomac/Makefile @@ -0,0 +1 @@ +include $(RIOTBASE)/Makefile.base diff --git a/sys/net/link_layer/ng_nomac/ng_nomac.c b/sys/net/link_layer/ng_nomac/ng_nomac.c new file mode 100644 index 0000000000000000000000000000000000000000..e20fa77b26a2dbcacd350fd2e0226ebd0299adb4 --- /dev/null +++ b/sys/net/link_layer/ng_nomac/ng_nomac.c @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2015 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. + */ + +/** + * @{ + * @ingroup net_nomac + * @file + * @brief Implementation of the NOMAC MAC protocol + * + * @author Hauke Petersen <hauke.petersen@fu-berlin.de> + * @} + */ + +#include <errno.h> + +#include "kernel.h" +#include "msg.h" +#include "thread.h" +#include "net/ng_nomac.h" +#include "net/ng_netreg.h" +#include "net/ng_pkt.h" +#include "net/ng_nettype.h" +#include "net/ng_netdev.h" +#include "net/ng_netapi.h" +#include "net/ng_netif.h" +#include "net/ng_pktbuf.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +/** + * @brief Function called by the device driver on device events + * + * @param[in] event type of event + * @param[in] data optional parameter + */ +static void _event_cb(ng_netdev_event_t event, void *data) +{ + DEBUG("nomac: event triggered -> %i\n", event); + /* NOMAC only understands the RX_COMPLETE event... */ + if (event == NETDEV_EVENT_RX_COMPLETE) { + ng_pktsnip_t *pkt; + ng_netreg_entry_t *sendto; + + /* get pointer to the received packet */ + pkt = (ng_pktsnip_t *)data; + /* find out, who to send the packet to */ + sendto = ng_netreg_lookup(pkt->type, NG_NETREG_DEMUX_CTX_ALL); + /* throw away packet if no one is interested */ + if (sendto == NULL) { + DEBUG("nomac: unable to forward packet of type %i\n", pkt->type); + ng_pktbuf_release(pkt); + } + /* send the packet to everyone interested in it's type */ + ng_pktbuf_hold(pkt, ng_netreg_num(pkt->type, NG_NETREG_DEMUX_CTX_ALL) - 1); + while (sendto != NULL) { + DEBUG("nomac: sending pkt %p to PID %u\n", pkt, sendto->pid); + ng_netapi_send(sendto->pid, pkt); + sendto = ng_netreg_getnext(sendto); + } + } +} + +/** + * @brief Startup code and event loop of the NOMAC layer + * + * @param[in] args expects a pointer to the underlying netdev device + * + * @return never returns + */ +static void *_nomac_thread(void *args) +{ + ng_netdev_t *dev = (ng_netdev_t *)args; + ng_netapi_opt_t *opt; + int res; + msg_t msg, reply, msg_queue[NG_NOMAC_MSG_QUEUE_SIZE]; + + /* setup the MAC layers message queue */ + msg_init_queue(msg_queue, NG_NOMAC_MSG_QUEUE_SIZE); + /* save the PID to the device descriptor and register the device */ + dev->mac_pid = thread_getpid(); + ng_netif_add(dev->mac_pid); + /* register the event callback with the device driver */ + dev->driver->add_event_callback(dev, _event_cb); + + /* start the event loop */ + while (1) { + DEBUG("nomac: waiting for incoming messages\n"); + msg_receive(&msg); + /* dispatch NETDEV and NETAPI messages */ + switch (msg.type) { + case NG_NETDEV_MSG_TYPE_EVENT: + DEBUG("nomac: NG_NETDEV_MSG_TYPE_EVENT received\n"); + dev->driver->isr_event(dev, msg.content.value); + break; + case NG_NETAPI_MSG_TYPE_SND: + DEBUG("nomac: NG_NETAPI_MSG_TYPE_SND received\n"); + dev->driver->send_data(dev, (ng_pktsnip_t *)msg.content.ptr); + break; + case NG_NETAPI_MSG_TYPE_SET: + /* TODO: filter out MAC layer options -> for now forward + everything to the device driver */ + DEBUG("nomac: NG_NETAPI_MSG_TYPE_SET received\n"); + /* read incoming options */ + opt = (ng_netapi_opt_t *)msg.content.ptr; + /* set option for device driver */ + res = dev->driver->set(dev, opt->opt, opt->data, opt->data_len); + /* send reply to calling thread */ + reply.type = NG_NETAPI_MSG_TYPE_ACK; + reply.content.value = (uint32_t)res; + msg_reply(&msg, &reply); + break; + case NG_NETAPI_MSG_TYPE_GET: + /* TODO: filter out MAC layer options -> for now forward + everything to the device driver */ + DEBUG("nomac: NG_NETAPI_MSG_TYPE_GET received\n"); + /* read incoming options */ + opt = (ng_netapi_opt_t *)msg.content.ptr; + /* get option from device driver */ + res = dev->driver->get(dev, opt->opt, opt->data, + (size_t*)(&(opt->data_len))); + /* send reply to calling thread */ + reply.type = NG_NETAPI_MSG_TYPE_ACK; + reply.content.value = (uint32_t)res; + msg_reply(&msg, &reply); + break; + default: + DEBUG("nomac: Unknown command %" PRIu16 "\n", msg.type); + break; + } + } + /* never reached */ + return NULL; +} + +kernel_pid_t ng_nomac_init(char *stack, int stacksize, char priority, + const char *name, ng_netdev_t *dev) +{ + kernel_pid_t res; + + /* check if given netdev device is defined and the driver is set */ + if (dev == NULL || dev->driver == NULL) { + return -ENODEV; + } + /* create new NOMAC thread */ + res = thread_create(stack, stacksize, priority, CREATE_STACKTEST, + _nomac_thread, (void *)dev, name); + if (res <= 0) { + return -EINVAL; + } + return res; +}