sys: net: Initial import of a basic MAC protocol layer
This commit is contained in:
parent
34908f11a9
commit
96502e2fd4
@ -16,6 +16,9 @@ endif
|
|||||||
ifneq (,$(filter l2_ping,$(USEMODULE)))
|
ifneq (,$(filter l2_ping,$(USEMODULE)))
|
||||||
DIRS += net/link_layer/ping
|
DIRS += net/link_layer/ping
|
||||||
endif
|
endif
|
||||||
|
ifneq (,$(filter nomac,$(USEMODULE)))
|
||||||
|
DIRS += net/link_layer/nomac
|
||||||
|
endif
|
||||||
ifneq (,$(filter transport_layer,$(USEMODULE)))
|
ifneq (,$(filter transport_layer,$(USEMODULE)))
|
||||||
USEMODULE += udp
|
USEMODULE += udp
|
||||||
USEMODULE += tcp
|
USEMODULE += tcp
|
||||||
|
|||||||
@ -1,3 +1,6 @@
|
|||||||
|
ifneq (,$(filter nomac,$(USEMODULE)))
|
||||||
|
USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include
|
||||||
|
endif
|
||||||
ifneq (,$(filter transport_layer,$(USEMODULE)))
|
ifneq (,$(filter transport_layer,$(USEMODULE)))
|
||||||
USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include
|
USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include
|
||||||
endif
|
endif
|
||||||
|
|||||||
@ -2,4 +2,8 @@ ifneq (,$(filter net_if,$(USEMODULE)))
|
|||||||
INCLUDES += -I$(RIOTBASE)/sys/net/include/
|
INCLUDES += -I$(RIOTBASE)/sys/net/include/
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifneq (,$(filter nomac,$(USEMODULE)))
|
||||||
|
INCLUDES += -I$(RIOTBASE)/sys/net/include/
|
||||||
|
endif
|
||||||
|
|
||||||
include $(RIOTBASE)/Makefile.base
|
include $(RIOTBASE)/Makefile.base
|
||||||
|
|||||||
@ -67,6 +67,10 @@
|
|||||||
#include "tcp.h"
|
#include "tcp.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MODULE_NOMAC
|
||||||
|
#include "nomac.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef MODULE_NET_IF
|
#ifdef MODULE_NET_IF
|
||||||
#include "cpu-conf.h"
|
#include "cpu-conf.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
@ -241,6 +245,10 @@ void auto_init(void)
|
|||||||
DEBUG("Auto init net_if module.\n");
|
DEBUG("Auto init net_if module.\n");
|
||||||
l2_ping_init();
|
l2_ping_init();
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef MODULE_NOMAC
|
||||||
|
DEBUG("Auto init nomac module.\n");
|
||||||
|
nomac_init_module();
|
||||||
|
#endif
|
||||||
#ifdef MODULE_NET_IF
|
#ifdef MODULE_NET_IF
|
||||||
DEBUG("Auto init net_if module.\n");
|
DEBUG("Auto init net_if module.\n");
|
||||||
auto_init_net_if();
|
auto_init_net_if();
|
||||||
|
|||||||
107
sys/net/include/nomac.h
Normal file
107
sys/net/include/nomac.h
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 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 nomac Link layer with no medium access
|
||||||
|
* @ingroup net
|
||||||
|
* @brief Link layer protocol to speak with any transceiver driver
|
||||||
|
* directly without any medium access.
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Link layer protocol to speak with any transceiver driver
|
||||||
|
* directly without any medium access.
|
||||||
|
*
|
||||||
|
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __NOMAC_H_
|
||||||
|
#define __NOMAC_H_
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "netdev/base.h"
|
||||||
|
#include "netapi.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef NOMAC_REGISTRY_SIZE
|
||||||
|
/**
|
||||||
|
* @brief The size of NOMAC's registry of receiving threads.
|
||||||
|
*/
|
||||||
|
#define NOMAC_REGISTRY_SIZE (1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Recommended stack size for a NOMAC thread
|
||||||
|
* TODO: determine real minimal size based on thread_print_all() output
|
||||||
|
*/
|
||||||
|
#define NOMAC_CONTROL_STACKSIZE (KERNEL_CONF_STACKSIZE_DEFAULT)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Basic configuration types
|
||||||
|
*
|
||||||
|
* @extends netapi_conf_type_t
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
NOMAC_PROTO = NETAPI_CONF_PROTO, /**< Set or get protocol */
|
||||||
|
NOMAC_CHANNEL = NETAPI_CONF_CARRIER, /**< Set or get channel */
|
||||||
|
NOMAC_ADDRESS = NETAPI_CONF_ADDRESS, /**< Set or get address */
|
||||||
|
NOMAC_NID = NETAPI_CONF_SUBNETS, /**< Set or get network id
|
||||||
|
* (e.g. PAN ID in 802.15.4)*/
|
||||||
|
NOMAC_MAX_PACKET_SIZE = NETAPI_CONF_MAX_PACKET_SIZE, /**< Set or get maximum
|
||||||
|
* packet size */
|
||||||
|
NOMAC_SRC_LEN = NETAPI_CONF_SRC_LEN, /**< Set or get default source length */
|
||||||
|
NOMAC_REGISTRY = NETAPI_CONF_REGISTRY, /**< get registered threads */
|
||||||
|
NOMAC_ADDRESS2 = NETDEV_OPT_ADDRESS_LONG, /**< Set or get alternative address
|
||||||
|
* format (e.g EUI-64 in 802.15.4) */
|
||||||
|
} nomac_conf_type_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initializes the module
|
||||||
|
*/
|
||||||
|
void nomac_init_module(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize new NOMAC layer.
|
||||||
|
*
|
||||||
|
* @param[in] stack Stack for the control thread
|
||||||
|
* @param[in] stacksize Size of *stack*
|
||||||
|
* @param[in] priority Priority for the control thread
|
||||||
|
* @param[in] name Name for the control thread
|
||||||
|
* @param[in] dev An *initialized* network device to use with this MAC
|
||||||
|
* layer
|
||||||
|
*
|
||||||
|
* @see @ref thread_create
|
||||||
|
*
|
||||||
|
* @return PID of NOMAC control thread on success
|
||||||
|
* @return -EINVAL if priority is invalid
|
||||||
|
* @return -EOVERFLOW if no slot for the new thread is available
|
||||||
|
*/
|
||||||
|
kernel_pid_t nomac_init(char *stack, int stacksize, char priority,
|
||||||
|
const char *name, netdev_t *dev);
|
||||||
|
|
||||||
|
#ifdef MODULE_NETDEV_DUMMY
|
||||||
|
/**
|
||||||
|
* @brief Re-updates the receive callback of a network device for testing
|
||||||
|
* purposes
|
||||||
|
*
|
||||||
|
* @param[in] dev A network device
|
||||||
|
*/
|
||||||
|
void nomac_update_callback(netdev_t *dev);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __NOMAC_H_ */
|
||||||
|
|
||||||
|
/** @} */
|
||||||
1
sys/net/link_layer/nomac/Makefile
Normal file
1
sys/net/link_layer/nomac/Makefile
Normal file
@ -0,0 +1 @@
|
|||||||
|
include $(RIOTBASE)/Makefile.base
|
||||||
295
sys/net/link_layer/nomac/nomac.c
Normal file
295
sys/net/link_layer/nomac/nomac.c
Normal file
@ -0,0 +1,295 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 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.
|
||||||
|
*/
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "netapi.h"
|
||||||
|
#include "msg.h"
|
||||||
|
#include "netdev/base.h"
|
||||||
|
#include "thread.h"
|
||||||
|
|
||||||
|
#include "nomac.h"
|
||||||
|
|
||||||
|
#ifdef MODULE_NETDEV_DUMMY
|
||||||
|
#include "netdev_dummy.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ENABLE_DEBUG (0)
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
#define NOMAC_MSG_QUEUE_SIZE (16)
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
kernel_pid_t registrar_pid; /**< Thread recipient is registered to */
|
||||||
|
kernel_pid_t recipient_pid; /**< Registered recipient thread */
|
||||||
|
} _nomac_registry[NOMAC_REGISTRY_SIZE];
|
||||||
|
|
||||||
|
static int _nomac_recv_cb(netdev_t *dev, void *src, size_t src_len, void *dest,
|
||||||
|
size_t dest_len, void *payload, size_t payload_len)
|
||||||
|
{
|
||||||
|
(void)dev;
|
||||||
|
kernel_pid_t current_pid = thread_getpid();
|
||||||
|
size_t offset;
|
||||||
|
netapi_rcv_pkt_t packet;
|
||||||
|
netapi_ack_t ack_mem;
|
||||||
|
msg_t msg_pkt, msg_ack;
|
||||||
|
|
||||||
|
packet.type = NETAPI_CMD_RCV;
|
||||||
|
packet.ack = &ack_mem;
|
||||||
|
packet.src = src;
|
||||||
|
packet.src_len = src_len;
|
||||||
|
packet.dest = dest;
|
||||||
|
packet.dest_len = dest_len;
|
||||||
|
msg_pkt.type = NETAPI_MSG_TYPE;
|
||||||
|
msg_pkt.content.ptr = (char *)(&packet);
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < NOMAC_REGISTRY_SIZE; i++) {
|
||||||
|
if (_nomac_registry[i].registrar_pid == current_pid) {
|
||||||
|
offset = 0;
|
||||||
|
|
||||||
|
while (offset < payload_len) {
|
||||||
|
netapi_ack_t *ack;
|
||||||
|
packet.data = (void *)(((char *)payload) + offset);
|
||||||
|
packet.data_len = payload_len - offset;
|
||||||
|
|
||||||
|
msg_send_receive(&msg_pkt, &msg_ack,
|
||||||
|
_nomac_registry[i].recipient_pid);
|
||||||
|
ack = (netapi_ack_t *)(msg_ack.content.ptr);
|
||||||
|
|
||||||
|
if ((msg_ack.type == NETAPI_MSG_TYPE) &&
|
||||||
|
(ack->type == NETAPI_CMD_ACK) &&
|
||||||
|
(ack->orig == NETAPI_CMD_RCV)) {
|
||||||
|
if (ack->result > 0) {
|
||||||
|
offset += (ack->result);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
DEBUG("Error code received for registrar %" PRIkernel_pid
|
||||||
|
" with recipient %" PRIkernel_pid ": %d",
|
||||||
|
_nomac_registry[i].registrar_pid,
|
||||||
|
_nomac_registry[i].recipient_pid,
|
||||||
|
-(ack->result));
|
||||||
|
|
||||||
|
return ack->result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
DEBUG("Unexpected msg instead of ACK. Abort for registrar "
|
||||||
|
"\"%s\" with recipient \"%s\": msg.type = %d, "
|
||||||
|
"ack->type = %d, ack->orig = %d",
|
||||||
|
thread_getname(_nomac_registry[i].registrar_pid),
|
||||||
|
thread_getname(_nomac_registry[i].recipient_pid),
|
||||||
|
msg_ack.type, ack->type, ack->orig);
|
||||||
|
|
||||||
|
return -ENOMSG;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return payload_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int _nomac_send(netdev_t *dev, netapi_snd_pkt_t *pkt)
|
||||||
|
{
|
||||||
|
return dev->driver->send_data(dev, pkt->dest, pkt->dest_len, pkt->ulh,
|
||||||
|
pkt->data, pkt->data_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _nomac_get_registry(netapi_conf_t *conf)
|
||||||
|
{
|
||||||
|
kernel_pid_t current_pid = thread_getpid();
|
||||||
|
kernel_pid_t registry[NOMAC_REGISTRY_SIZE];
|
||||||
|
uint8_t size = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < NOMAC_REGISTRY_SIZE; i++) {
|
||||||
|
if ((size * sizeof(kernel_pid_t)) > (conf->data_len)) {
|
||||||
|
return -EOVERFLOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_nomac_registry[i].registrar_pid == current_pid) {
|
||||||
|
registry[size++] = _nomac_registry[i].recipient_pid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
conf->data_len = size * sizeof(kernel_pid_t);
|
||||||
|
memcpy(conf->data, registry, conf->data_len);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _nomac_get_option(netdev_t *dev, netapi_conf_t *conf)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
|
||||||
|
switch ((nomac_conf_type_t)conf->param) {
|
||||||
|
case NOMAC_PROTO:
|
||||||
|
case NOMAC_CHANNEL:
|
||||||
|
case NOMAC_ADDRESS:
|
||||||
|
case NOMAC_NID:
|
||||||
|
case NOMAC_MAX_PACKET_SIZE:
|
||||||
|
case NOMAC_ADDRESS2:
|
||||||
|
if ((res = dev->driver->get_option(dev, (netdev_opt_t)conf->param,
|
||||||
|
conf->data, &(conf->data_len))
|
||||||
|
) == 0) {
|
||||||
|
return (int)conf->data_len;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
case NOMAC_REGISTRY:
|
||||||
|
return _nomac_get_registry(conf);
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _nomac_set_option(netdev_t *dev, netapi_conf_t *conf)
|
||||||
|
{
|
||||||
|
switch ((nomac_conf_type_t)(conf->param)) {
|
||||||
|
case NOMAC_PROTO:
|
||||||
|
case NOMAC_CHANNEL:
|
||||||
|
case NOMAC_ADDRESS:
|
||||||
|
case NOMAC_NID:
|
||||||
|
case NOMAC_ADDRESS2:
|
||||||
|
return dev->driver->set_option(dev, (netdev_opt_t)conf->param,
|
||||||
|
conf->data, conf->data_len);
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *_nomac_runner(void *args)
|
||||||
|
{
|
||||||
|
netdev_t *dev = (netdev_t *)args;
|
||||||
|
msg_t msg_cmd, msg_ack, msg_queue[NOMAC_MSG_QUEUE_SIZE];
|
||||||
|
|
||||||
|
netapi_cmd_t *cmd;
|
||||||
|
netapi_ack_t *ack;
|
||||||
|
|
||||||
|
msg_ack.type = NETAPI_MSG_TYPE;
|
||||||
|
|
||||||
|
msg_init_queue(msg_queue, NOMAC_MSG_QUEUE_SIZE);
|
||||||
|
|
||||||
|
dev->driver->init(dev);
|
||||||
|
dev->driver->add_receive_data_callback(dev, _nomac_recv_cb);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
msg_receive(&msg_cmd);
|
||||||
|
|
||||||
|
if (msg_cmd.type == NETDEV_MSG_EVENT_TYPE) {
|
||||||
|
dev->driver->event(dev, msg_cmd.content.value);
|
||||||
|
}
|
||||||
|
else if (msg_cmd.type == NETAPI_MSG_TYPE) {
|
||||||
|
cmd = (netapi_cmd_t *)(msg_cmd.content.ptr);
|
||||||
|
ack = cmd->ack;
|
||||||
|
msg_ack.content.ptr = (char *)ack;
|
||||||
|
|
||||||
|
switch (cmd->type) {
|
||||||
|
case NETAPI_CMD_SND:
|
||||||
|
ack->result = _nomac_send(dev, (netapi_snd_pkt_t *)cmd);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NETAPI_CMD_GET:
|
||||||
|
ack->result = _nomac_get_option(dev, (netapi_conf_t *)cmd);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NETAPI_CMD_SET:
|
||||||
|
ack->result = _nomac_set_option(dev, (netapi_conf_t *)cmd);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NETAPI_CMD_REG:
|
||||||
|
ack->result = -ENOBUFS;
|
||||||
|
|
||||||
|
for (int i = 0; i < NOMAC_REGISTRY_SIZE; i++) {
|
||||||
|
if (_nomac_registry[i].registrar_pid == KERNEL_PID_UNDEF) {
|
||||||
|
netapi_reg_t *reg = (netapi_reg_t *)cmd;
|
||||||
|
|
||||||
|
_nomac_registry[i].registrar_pid = thread_getpid();
|
||||||
|
_nomac_registry[i].recipient_pid = reg->reg_pid;
|
||||||
|
ack->result = NETAPI_STATUS_OK;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NETAPI_CMD_UNREG:
|
||||||
|
ack->result = NETAPI_STATUS_OK;
|
||||||
|
|
||||||
|
for (int i = 0; i < NOMAC_REGISTRY_SIZE; i++) {
|
||||||
|
netapi_reg_t *reg = (netapi_reg_t *)cmd;
|
||||||
|
|
||||||
|
if (_nomac_registry[i].registrar_pid == thread_getpid() &&
|
||||||
|
_nomac_registry[i].recipient_pid == reg->reg_pid) {
|
||||||
|
_nomac_registry[i].recipient_pid = KERNEL_PID_UNDEF;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
#ifdef MODULE_NETDEV_DUMMY
|
||||||
|
|
||||||
|
case NETAPI_CMD_FIRE_RCV:
|
||||||
|
ack->result = unittest_netdev_dummy_fire_rcv_event(dev,
|
||||||
|
((netapi_rcv_pkt_t *)cmd)->src,
|
||||||
|
((netapi_rcv_pkt_t *)cmd)->src_len,
|
||||||
|
((netapi_rcv_pkt_t *)cmd)->dest,
|
||||||
|
((netapi_rcv_pkt_t *)cmd)->dest_len,
|
||||||
|
((netapi_rcv_pkt_t *)cmd)->data,
|
||||||
|
((netapi_rcv_pkt_t *)cmd)->data_len);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default:
|
||||||
|
ack->result = -ENOTSUP;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ack->type = NETAPI_CMD_ACK;
|
||||||
|
ack->orig = cmd->type;
|
||||||
|
msg_reply(&msg_cmd, &msg_ack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* never reached */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nomac_init_module(void)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < NOMAC_REGISTRY_SIZE; i++) {
|
||||||
|
_nomac_registry[i].registrar_pid = KERNEL_PID_UNDEF;
|
||||||
|
_nomac_registry[i].recipient_pid = KERNEL_PID_UNDEF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
kernel_pid_t nomac_init(char *stack, int stacksize, char priority,
|
||||||
|
const char *name, netdev_t *dev)
|
||||||
|
{
|
||||||
|
return thread_create(stack, stacksize, priority, CREATE_STACKTEST,
|
||||||
|
_nomac_runner, (void *)dev, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef MODULE_NETDEV_DUMMY
|
||||||
|
void nomac_update_callback(netdev_t *dev)
|
||||||
|
{
|
||||||
|
dev->driver->add_receive_data_callback(dev, _nomac_recv_cb);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
Loading…
x
Reference in New Issue
Block a user