1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

ng_sixlowpan: initial import

This commit is contained in:
Martine Lenders 2015-03-16 17:52:19 +01:00 committed by Martine Lenders
parent 07e2dbaf7e
commit 5412e0e68b
9 changed files with 402 additions and 3 deletions

View File

@ -48,6 +48,11 @@ ifneq (,$(filter sixlowpan,$(USEMODULE)))
USEMODULE += vtimer
endif
ifneq (,$(filter ng_sixlowpan,$(USEMODULE)))
USEMODULE += ng_sixlowpan_netif
USEMODULE += ng_netbase
endif
ifneq (,$(filter ng_sixlowpan_ctx,$(USEMODULE)))
USEMODULE += ng_ipv6_addr
USEMODULE += vtimer

View File

@ -95,6 +95,9 @@ endif
ifneq (,$(filter ng_pktbuf,$(USEMODULE)))
DIRS += net/crosslayer/ng_pktbuf
endif
ifneq (,$(filter ng_sixlowpan,$(USEMODULE)))
DIRS += net/network_layer/ng_sixlowpan
endif
ifneq (,$(filter ng_sixlowpan_ctx,$(USEMODULE)))
DIRS += net/network_layer/ng_sixlowpan/ctx
endif

View File

@ -82,6 +82,10 @@
#include "periph/cpuid.h"
#endif
#ifdef MODULE_NG_SIXLOWPAN
#include "net/ng_sixlowpan.h"
#endif
#ifdef MODULE_NG_IPV6
#include "net/ng_ipv6.h"
#endif
@ -284,6 +288,10 @@ void auto_init(void)
DEBUG("Auto init ng_pktdump module.\n");
ng_pktdump_init();
#endif
#ifdef MODULE_NG_SIXLOWPAN
DEBUG("Auto init ng_sixlowpan module.\n");
ng_sixlowpan_init();
#endif
#ifdef MODULE_NG_IPV6
DEBUG("Auto init ng_ipv6 module.\n");
ng_ipv6_init();

View File

@ -49,7 +49,7 @@ extern "C" {
#endif
/**
* @brief Default name for the IPv6 thread
* @brief Default priority for the IPv6 thread
*/
#ifndef NG_IPV6_PRIO
#define NG_IPV6_PRIO (PRIORITY_MAIN - 3)

View File

@ -83,6 +83,15 @@ extern "C" {
* @}
*/
/**
* @{
* @name Flags for the interfaces
*/
#define NG_IPV6_NETIF_FLAGS_SIXLOWPAN (0x01) /**< interface is 6LoWPAN interface */
/**
* @}
*/
/**
* @brief Type to represent an IPv6 address registered to an interface.
*/

View File

@ -0,0 +1,83 @@
/*
* 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_sixlowpan 6LoWPAN
* @ingroup net
* @brief 6LoWPAN implementation
* @{
*
* @file
* @brief Definitions for 6LoWPAN
*
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
*/
#ifndef NG_SIXLOWPAN_H_
#define NG_SIXLOWPAN_H_
#include <stdbool.h>
#include "kernel_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Default stack size to use for the 6LoWPAN thread
*/
#ifndef NG_SIXLOWPAN_STACK_SIZE
#define NG_SIXLOWPAN_STACK_SIZE (KERNEL_CONF_STACKSIZE_DEFAULT)
#endif
/**
* @brief Default priority for the 6LoWPAN thread
*/
#ifndef NG_SIXLOWPAN_PRIO
#define NG_SIXLOWPAN_PRIO (PRIORITY_MAIN - 4)
#endif
/**
* @brief Default message queue size to use for the 6LoWPAN thread.
*/
#ifndef NG_SIXLOWPAN_MSG_QUEUE_SIZE
#define NG_SIXLOWPAN_MSG_QUEUE_SIZE (8U)
#endif
/**
* @brief Dispatch for uncompressed 6LoWPAN frame.
*/
#define NG_SIXLOWPAN_UNCOMPRESSED (0x41)
/**
* @brief Checks if dispatch indicats that fram is not a 6LoWPAN (NALP) frame.
*
* @param[in] disp The first byte of a frame.
*
* @return true, if frame is a NALP.
* @return false, if frame is not a NALP.
*/
static inline bool ng_sixlowpan_nalp(uint8_t disp)
{
return (disp & 0x3f);
}
/**
* @brief Initialization of the 6LoWPAN thread.
*
* @return The PID to the 6LoWPAN thread, on success.
* @return -EOVERFLOW, if there are too many threads running already
*/
kernel_pid_t ng_sixlowpan_init(void);
#ifdef __cplusplus
}
#endif
#endif /* NG_SIXLOWPAN_H_ */
/** @} */

View File

@ -135,6 +135,43 @@ static void *_event_loop(void *args)
return NULL;
}
#ifdef MODULE_NG_SIXLOWPAN
static void _send_to_iface(kernel_pid_t iface, ng_pktsnip_t *pkt)
{
ng_ipv6_netif_t *if_entry = ng_ipv6_netif_get(iface);
((ng_netif_hdr_t *)pkt->data)->if_pid = iface;
if ((if_entry != NULL) && (if_entry->flags & NG_IPV6_NETIF_FLAGS_SIXLOWPAN)) {
DEBUG("ipv6: send to 6LoWPAN instead\n");
ng_netreg_entry_t *reg = ng_netreg_lookup(NG_NETTYPE_SIXLOWPAN,
NG_NETREG_DEMUX_CTX_ALL);
if (reg != NULL) {
ng_pktbuf_hold(pkt, ng_netreg_num(NG_NETTYPE_SIXLOWPAN,
NG_NETREG_DEMUX_CTX_ALL) - 1);
}
else {
DEBUG("ipv6: no 6LoWPAN thread found");
}
while (reg) {
ng_netapi_send(reg->pid, pkt);
reg = ng_netreg_getnext(reg);
}
}
else {
ng_netapi_send(iface, pkt);
}
}
#else
static inline void _send_to_iface(kernel_pid_t iface, ng_pktsnip_t *pkt)
{
((ng_netif_hdr_t *)pkt->data)->if_pid = iface;
ng_netapi_send(iface, pkt);
}
#endif
/* functions for sending */
static void _send_unicast(kernel_pid_t iface, uint8_t *dst_l2addr,
uint16_t dst_l2addr_len, ng_pktsnip_t *pkt)
@ -165,7 +202,7 @@ static void _send_unicast(kernel_pid_t iface, uint8_t *dst_l2addr,
DEBUG("ipv6: send unicast over interface %" PRIkernel_pid "\n", iface);
/* and send to interface */
ng_netapi_send(iface, pkt);
_send_to_iface(iface, pkt);
}
static int _fill_ipv6_hdr(kernel_pid_t iface, ng_pktsnip_t *ipv6,
@ -243,7 +280,7 @@ static inline void _send_multicast_over_iface(kernel_pid_t iface, ng_pktsnip_t *
/* mark as multicast */
((ng_netif_hdr_t *)netif->data)->flags |= NG_NETIF_HDR_FLAGS_MULTICAST;
/* and send to interface */
ng_netapi_send(iface, pkt);
_send_to_iface(iface, pkt);
}
static void _send_multicast(kernel_pid_t iface, ng_pktsnip_t *pkt,

View File

@ -0,0 +1 @@
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,253 @@
/*
* 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 "kernel_types.h"
#include "net/ng_netbase.h"
#include "thread.h"
#include "utlist.h"
#include "net/ng_sixlowpan.h"
#include "net/ng_sixlowpan/netif.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
static kernel_pid_t _pid = KERNEL_PID_UNDEF;
static char _stack[NG_SIXLOWPAN_STACK_SIZE];
/* handles NG_NETAPI_MSG_TYPE_RCV commands */
void _receive(ng_pktsnip_t *pkt);
/* handles NG_NETAPI_MSG_TYPE_SND commands */
void _send(ng_pktsnip_t *pkt);
/* Main event loop for 6LoWPAN */
static void *_event_loop(void *args);
kernel_pid_t ng_sixlowpan_init(void)
{
if (_pid > KERNEL_PID_UNDEF) {
return _pid;
}
_pid = thread_create(_stack, NG_SIXLOWPAN_STACK_SIZE, NG_SIXLOWPAN_PRIO,
CREATE_STACKTEST, _event_loop, NULL, "6lo");
return _pid;
}
void _receive(ng_pktsnip_t *pkt)
{
ng_pktsnip_t *payload;
uint8_t *dispatch;
ng_netreg_entry_t *entry;
LL_SEARCH_SCALAR(pkt, payload, type, NG_NETTYPE_SIXLOWPAN);
if ((payload == NULL) || (payload->size < 1)) {
DEBUG("6lo: Received packet has no 6LoWPAN payload\n");
ng_pktbuf_release(pkt);
}
dispatch = payload->data;
if (dispatch[0] == NG_SIXLOWPAN_UNCOMPRESSED) {
ng_pktsnip_t *sixlowpan;
DEBUG("6lo: received uncompressed IPv6 packet\n");
payload = ng_pktbuf_start_write(payload);
if (payload == NULL) {
DEBUG("6lo: can not get write access on received packet\n");
#if defined(DEVELHELP) && defined(ENABLE_DEBUG)
ng_pktbuf_stats();
#endif
ng_pktbuf_release(pkt);
return;
}
/* packet is uncompressed: just mark and remove the dispatch */
sixlowpan = ng_pktbuf_add(payload, payload->data, sizeof(uint8_t),
NG_NETTYPE_SIXLOWPAN);
LL_DELETE(pkt, sixlowpan);
ng_pktbuf_release(sixlowpan);
}
else {
DEBUG("6lo: dispatch %02x ... is not supported\n",
dispatch[0]);
ng_pktbuf_release(pkt);
return;
}
payload->type = NG_NETTYPE_IPV6;
entry = ng_netreg_lookup(NG_NETTYPE_IPV6, NG_NETREG_DEMUX_CTX_ALL);
if (entry == NULL) {
DEBUG("ipv6: No receivers for this packet found\n");
ng_pktbuf_release(pkt);
return;
}
ng_pktbuf_hold(pkt, ng_netreg_num(NG_NETTYPE_IPV6, NG_NETREG_DEMUX_CTX_ALL) - 1);
while (entry) {
DEBUG("6lo: Send receive command for %p to %" PRIu16 "\n",
(void *)pkt, entry->pid);
ng_netapi_receive(entry->pid, pkt);
entry = ng_netreg_getnext(entry);
}
}
void _send(ng_pktsnip_t *pkt)
{
ng_netif_hdr_t *hdr;
ng_pktsnip_t *ipv6, *sixlowpan;
ng_sixlowpan_netif_t *iface;
/* cppcheck: datagram_size will be read by frag */
/* cppcheck-suppress unreadVariable */
size_t payload_len, datagram_size;
uint16_t max_frag_size;
uint8_t *disp;
if ((pkt == NULL) || (pkt->size < sizeof(ng_netif_hdr_t))) {
DEBUG("6lo: Sending packet has no netif header\n");
ng_pktbuf_release(pkt);
return;
}
hdr = pkt->data;
ipv6 = pkt->next;
if ((ipv6 == NULL) || (ipv6->type != NG_NETTYPE_IPV6)) {
DEBUG("6lo: Sending packet has no IPv6 header\n");
ng_pktbuf_release(pkt);
return;
}
/* payload length and datagram size are different in that the payload
* length is the length of the IPv6 datagram + 6LoWPAN dispatches,
* while the datagram size is the size of only the IPv6 datagram */
payload_len = ng_pkt_len(ipv6);
/* cppcheck: datagram_size will be read by ng_sixlowpan_frag implementation */
/* cppcheck-suppress unreadVariable */
datagram_size = (uint16_t)payload_len;
/* use sixlowpan packet snip as temporary one */
sixlowpan = ng_pktbuf_start_write(pkt);
if (sixlowpan == NULL) {
DEBUG("6lo: no space left in packet buffer\n");
ng_pktbuf_release(pkt);
return;
}
pkt = sixlowpan;
DEBUG("6lo: Send uncompressed\n");
sixlowpan = ng_pktbuf_add(NULL, NULL, sizeof(uint8_t), NG_NETTYPE_SIXLOWPAN);
if (sixlowpan == NULL) {
DEBUG("6lo: no space left in packet buffer\n");
ng_pktbuf_release(pkt);
return;
}
sixlowpan->next = ipv6;
pkt->next = sixlowpan;
disp = sixlowpan->data;
disp[0] = NG_SIXLOWPAN_UNCOMPRESSED;
payload_len++;
iface = ng_sixlowpan_netif_get(hdr->if_pid);
if (iface == NULL) {
if (ng_netapi_get(hdr->if_pid, NETCONF_OPT_MAX_PACKET_SIZE,
0, &max_frag_size, sizeof(max_frag_size)) < 0) {
/* if error we assume it works */
DEBUG("6lo: can not get max packet size from interface %"
PRIkernel_pid "\n", hdr->if_pid);
max_frag_size = UINT16_MAX;
}
ng_sixlowpan_netif_add(hdr->if_pid, max_frag_size);
}
else {
max_frag_size = iface->max_frag_size;
}
DEBUG("6lo: max_frag_size = %" PRIu16 " for interface %"
PRIkernel_pid "\n", max_frag_size, hdr->if_pid);
/* IP should not send anything here if it is not a 6LoWPAN interface,
* so we don't need to check for NULL pointers */
if (payload_len <= max_frag_size) {
DEBUG("6lo: Send SND command for %p to %" PRIu16 "\n",
(void *)pkt, hdr->if_pid);
ng_netapi_send(hdr->if_pid, pkt);
return;
}
DEBUG("6lo: packet too big (%u> %" PRIu16 ")\n",
(unsigned int)payload_len, max_frag_size);
}
static void *_event_loop(void *args)
{
msg_t msg, reply, msg_q[NG_SIXLOWPAN_MSG_QUEUE_SIZE];
ng_netreg_entry_t me_reg;
(void)args;
msg_init_queue(msg_q, NG_SIXLOWPAN_MSG_QUEUE_SIZE);
me_reg.demux_ctx = NG_NETREG_DEMUX_CTX_ALL;
me_reg.pid = thread_getpid();
/* register interest in all 6LoWPAN packets */
ng_netreg_register(NG_NETTYPE_SIXLOWPAN, &me_reg);
/* preinitialize ACK */
reply.type = NG_NETAPI_MSG_TYPE_ACK;
/* start event loop */
while (1) {
DEBUG("6lo: waiting for incoming message.\n");
msg_receive(&msg);
switch (msg.type) {
case NG_NETAPI_MSG_TYPE_RCV:
DEBUG("6lo: NG_NETDEV_MSG_TYPE_RCV received\n");
_receive((ng_pktsnip_t *)msg.content.ptr);
break;
case NG_NETAPI_MSG_TYPE_SND:
DEBUG("6lo: NG_NETDEV_MSG_TYPE_SND received\n");
_send((ng_pktsnip_t *)msg.content.ptr);
break;
case NG_NETAPI_MSG_TYPE_GET:
case NG_NETAPI_MSG_TYPE_SET:
DEBUG("6lo: reply to unsupported get/set\n");
reply.content.value = -ENOTSUP;
msg_reply(&msg, &reply);
break;
default:
DEBUG("6lo: operation not supported\n");
break;
}
}
return NULL;
}
/** @} */