mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-01-17 05:12:57 +01:00
sys: net: gnrc: add basic netdev2 support
This commit is contained in:
parent
076e9db374
commit
78b4bf6f58
@ -276,6 +276,10 @@ ifneq (,$(filter gnrc,$(USEMODULE)))
|
||||
USEMODULE += gnrc_pktbuf
|
||||
endif
|
||||
|
||||
ifneq (,$(filter gnrc_netdev2,$(USEMODULE)))
|
||||
USEMODULE += netopt
|
||||
endif
|
||||
|
||||
ifneq (,$(filter hih6130,$(USEMODULE)))
|
||||
USEMODULE += vtimer
|
||||
endif
|
||||
|
@ -40,6 +40,9 @@ endif
|
||||
ifneq (,$(filter nhdp,$(USEMODULE)))
|
||||
DIRS += net/routing/nhdp
|
||||
endif
|
||||
ifneq (,$(filter gnrc_netdev2,$(USEMODULE)))
|
||||
DIRS += net/gnrc/link_layer/netdev2
|
||||
endif
|
||||
ifneq (,$(filter fib,$(USEMODULE)))
|
||||
DIRS += net/network_layer/fib
|
||||
endif
|
||||
|
99
sys/include/net/gnrc/gnrc_netdev2.h
Normal file
99
sys/include/net/gnrc/gnrc_netdev2.h
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup net_gnrc
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief netdev2 gnrc glue code interface
|
||||
*
|
||||
* This interface is supposed to provide common adaption code between the
|
||||
* low-level network device interface "netdev2" and the gnrc network stack.
|
||||
*
|
||||
* GNRC sends around "gnrc_pktsnip_t" structures, but netdev can only handle
|
||||
* "struct iovec" structures when sending, or a flat buffer when receiving.
|
||||
*
|
||||
* The purpose of gnrc_netdev is to bring these two interfaces together.
|
||||
*
|
||||
* @author Kaspar Schleiser <kaspar@schleiser.de>
|
||||
*/
|
||||
|
||||
#ifndef GNRC_NETDEV2_H
|
||||
#define GNRC_NETDEV2_H
|
||||
|
||||
#include "kernel_types.h"
|
||||
#include "net/netdev2.h"
|
||||
#include "net/gnrc.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define NETDEV2_MSG_TYPE_EVENT 0x1234
|
||||
|
||||
typedef struct gnrc_netdev2 gnrc_netdev2_t;
|
||||
|
||||
/**
|
||||
* @brief Structure holding gnrc netdev2 adapter state
|
||||
*
|
||||
* This structure is supposed to hold any state parameters needed
|
||||
* to use a netdev2 device from gnrc.
|
||||
*
|
||||
* It can be extended
|
||||
*/
|
||||
struct gnrc_netdev2 {
|
||||
/**
|
||||
* @brief Send a pktsnip using this device
|
||||
*
|
||||
* This function should convert the pktsnip into a format
|
||||
* the underlying device understands and send it.
|
||||
*/
|
||||
int (*send)(gnrc_netdev2_t *dev, gnrc_pktsnip_t *snip);
|
||||
|
||||
/**
|
||||
* @brief Receive a pktsnip from this device
|
||||
*
|
||||
* This function should receive a raw frame from the underlying
|
||||
* device and convert it into a pktsnip while adding a netif header
|
||||
* and possibly marking out higher-layer headers.
|
||||
*/
|
||||
gnrc_pktsnip_t * (*recv)(gnrc_netdev2_t *dev);
|
||||
|
||||
/**
|
||||
* @brief netdev2 handle this adapter is working with
|
||||
*/
|
||||
netdev2_t *dev;
|
||||
|
||||
/**
|
||||
* @brief PID of this adapter for netapi messages
|
||||
*/
|
||||
kernel_pid_t pid;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Initialize gnrc netdev2 handler thread
|
||||
*
|
||||
* @param[in] stack ptr to preallocated stack buffer
|
||||
* @param[in] stacksize size of stack buffer
|
||||
* @param[in] priority priority of thread
|
||||
* @param[in] name name of thread
|
||||
* @param[in] gnrc_netdev2 ptr to netdev2 device to handle in created thread
|
||||
*
|
||||
* @return pid of created thread
|
||||
* @return KERNEL_PID_UNDEF on error
|
||||
*/
|
||||
kernel_pid_t gnrc_netdev2_init(char *stack, int stacksize, char priority,
|
||||
const char *name, gnrc_netdev2_t *gnrc_netdev2);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* GNRC_NETDEV2_H */
|
||||
/** @} */
|
44
sys/include/net/gnrc/gnrc_netdev2_eth.h
Normal file
44
sys/include/net/gnrc/gnrc_netdev2_eth.h
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup net_gnrc
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief netdev2 gnrc ethernet glue code interface
|
||||
*
|
||||
* @author Kaspar Schleiser <kaspar@schleiser.de>
|
||||
*/
|
||||
|
||||
#ifndef GNRC_NETDEV2_ETH_H
|
||||
#define GNRC_NETDEV2_ETH_H
|
||||
|
||||
#include "net/gnrc/gnrc_netdev2.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Initialize gnrc handler thread for netdev2 ethernet device
|
||||
*
|
||||
* @param[in] gnrc_netdev2 gnrc_netdev2 struct to initialize
|
||||
* @param[in] dev netdev2 device to handle
|
||||
*
|
||||
* @return 1 on success
|
||||
* @return <=0 on error
|
||||
*/
|
||||
int gnrc_netdev2_eth_init(gnrc_netdev2_t *gnrc_netdev2, netdev2_t *dev);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* GNRC_NETDEV2_ETH_H */
|
||||
/** @} */
|
@ -172,6 +172,11 @@ typedef enum {
|
||||
*/
|
||||
NETOPT_IS_WIRED,
|
||||
|
||||
/**
|
||||
* @brief get a device's "type", e.g., ethernet, 802.15.4, ...
|
||||
*/
|
||||
NETOPT_DEVICE_TYPE,
|
||||
|
||||
/* add more options if needed */
|
||||
|
||||
/**
|
||||
|
@ -49,6 +49,7 @@ static const char *_netopt_strmap[] = {
|
||||
[NETOPT_CSMA] = "NETOPT_CSMA",
|
||||
[NETOPT_CSMA_RETRIES] = "NETOPT_CSMA_RETRIES",
|
||||
[NETOPT_IS_WIRED] = "NETOPT_IS_WIRED",
|
||||
[NETOPT_DEVICE_TYPE] = "NETOPT_DEVICE_TYPE",
|
||||
[NETOPT_NUMOF] = "NETOPT_NUMOF",
|
||||
};
|
||||
|
||||
|
3
sys/net/gnrc/link_layer/netdev2/Makefile
Normal file
3
sys/net/gnrc/link_layer/netdev2/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
MODULE = gnrc_netdev2
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
209
sys/net/gnrc/link_layer/netdev2/gnrc_netdev2.c
Normal file
209
sys/net/gnrc/link_layer/netdev2/gnrc_netdev2.c
Normal file
@ -0,0 +1,209 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Freie Universität Berlin
|
||||
* 2015 Kaspar Schleiser <kaspar@schleiser.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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @{
|
||||
* @ingroup net
|
||||
* @file
|
||||
* @brief Glue for netdev2 devices to netapi
|
||||
*
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
* @author Kaspar Schleiser <kaspar@schleiser.de>
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "kernel.h"
|
||||
#include "msg.h"
|
||||
#include "thread.h"
|
||||
|
||||
#include "net/gnrc.h"
|
||||
#include "net/gnrc/nettype.h"
|
||||
#include "net/netdev2.h"
|
||||
|
||||
#include "net/gnrc/gnrc_netdev2.h"
|
||||
#include "net/ethernet/hdr.h"
|
||||
|
||||
#define ENABLE_DEBUG (0)
|
||||
#include "debug.h"
|
||||
|
||||
#if defined(MODULE_OD) && ENABLE_DEBUG
|
||||
#include "od.h"
|
||||
#endif
|
||||
|
||||
#define NETDEV2_NETAPI_MSG_QUEUE_SIZE 8
|
||||
|
||||
static void _pass_on_packet(gnrc_pktsnip_t *pkt);
|
||||
|
||||
/**
|
||||
* @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(netdev2_t *dev, netdev2_event_t event, void *data)
|
||||
{
|
||||
(void) data;
|
||||
gnrc_netdev2_t *gnrc_netdev2 = (gnrc_netdev2_t*) dev->isr_arg;
|
||||
|
||||
if (event == NETDEV2_EVENT_ISR) {
|
||||
msg_t msg;
|
||||
|
||||
msg.type = NETDEV2_MSG_TYPE_EVENT;
|
||||
msg.content.ptr = (void*) gnrc_netdev2;
|
||||
|
||||
if (msg_send(&msg, gnrc_netdev2->pid) <= 0) {
|
||||
puts("gnrc_netdev2: possibly lost interrupt.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
DEBUG("gnrc_netdev2: event triggered -> %i\n", event);
|
||||
switch(event) {
|
||||
case NETDEV2_EVENT_RX_COMPLETE:
|
||||
{
|
||||
gnrc_pktsnip_t *pkt = gnrc_netdev2->recv(gnrc_netdev2);
|
||||
|
||||
if (pkt) {
|
||||
_pass_on_packet(pkt);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
DEBUG("gnrc_netdev2: warning: unhandled event %u.\n", event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void _pass_on_packet(gnrc_pktsnip_t *pkt)
|
||||
{
|
||||
gnrc_netreg_entry_t *sendto;
|
||||
|
||||
/* find out, who to send the packet to */
|
||||
sendto = gnrc_netreg_lookup(pkt->type, GNRC_NETREG_DEMUX_CTX_ALL);
|
||||
|
||||
/* throw away packet if no one is interested */
|
||||
if (sendto == NULL) {
|
||||
DEBUG("gnrc_netdev2: unable to forward packet of type %i\n", pkt->type);
|
||||
gnrc_pktbuf_release(pkt);
|
||||
return;
|
||||
}
|
||||
|
||||
/* send the packet to everyone interested in it's type */
|
||||
gnrc_pktbuf_hold(pkt, gnrc_netreg_num(pkt->type, GNRC_NETREG_DEMUX_CTX_ALL) - 1);
|
||||
while (sendto != NULL) {
|
||||
DEBUG("gnrc_netdev2: sending pkt %p to PID %u\n", (void*)pkt, sendto->pid);
|
||||
gnrc_netapi_receive(sendto->pid, pkt);
|
||||
sendto = gnrc_netreg_getnext(sendto);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Startup code and event loop of the gnrc_netdev2 layer
|
||||
*
|
||||
* @param[in] args expects a pointer to the underlying netdev device
|
||||
*
|
||||
* @return never returns
|
||||
*/
|
||||
static void *_gnrc_netdev2_thread(void *args)
|
||||
{
|
||||
DEBUG("gnrc_netdev2: starting thread\n");
|
||||
|
||||
gnrc_netdev2_t *gnrc_netdev2 = (gnrc_netdev2_t*) args;
|
||||
netdev2_t *dev = gnrc_netdev2->dev;
|
||||
|
||||
gnrc_netdev2->pid = thread_getpid();
|
||||
|
||||
gnrc_netapi_opt_t *opt;
|
||||
int res;
|
||||
msg_t msg, reply, msg_queue[NETDEV2_NETAPI_MSG_QUEUE_SIZE];
|
||||
|
||||
/* setup the MAC layers message queue */
|
||||
msg_init_queue(msg_queue, NETDEV2_NETAPI_MSG_QUEUE_SIZE);
|
||||
|
||||
/* register the event callback with the device driver */
|
||||
dev->event_callback = _event_cb;
|
||||
dev->isr_arg = (void*) gnrc_netdev2;
|
||||
|
||||
/* register the device to the network stack*/
|
||||
gnrc_netif_add(thread_getpid());
|
||||
|
||||
/* initialize low-level driver */
|
||||
dev->driver->init(dev);
|
||||
|
||||
/* start the event loop */
|
||||
while (1) {
|
||||
DEBUG("gnrc_netdev2: waiting for incoming messages\n");
|
||||
msg_receive(&msg);
|
||||
/* dispatch NETDEV and NETAPI messages */
|
||||
switch (msg.type) {
|
||||
case NETDEV2_MSG_TYPE_EVENT:
|
||||
DEBUG("gnrc_netdev2: GNRC_NETDEV_MSG_TYPE_EVENT received\n");
|
||||
dev->driver->isr(dev);
|
||||
break;
|
||||
case GNRC_NETAPI_MSG_TYPE_SND:
|
||||
DEBUG("gnrc_netdev2: GNRC_NETAPI_MSG_TYPE_SND received\n");
|
||||
gnrc_pktsnip_t *pkt = (gnrc_pktsnip_t *)msg.content.ptr;
|
||||
gnrc_netdev2->send(gnrc_netdev2, pkt);
|
||||
break;
|
||||
case GNRC_NETAPI_MSG_TYPE_SET:
|
||||
/* read incoming options */
|
||||
opt = (gnrc_netapi_opt_t *)msg.content.ptr;
|
||||
DEBUG("gnrc_netdev2: GNRC_NETAPI_MSG_TYPE_SET received. opt=%s\n",
|
||||
netopt2str(opt->opt));
|
||||
/* set option for device driver */
|
||||
res = dev->driver->set(dev, opt->opt, opt->data, opt->data_len);
|
||||
DEBUG("gnrc_netdev2: response of netdev->set: %i\n", res);
|
||||
/* send reply to calling thread */
|
||||
reply.type = GNRC_NETAPI_MSG_TYPE_ACK;
|
||||
reply.content.value = (uint32_t)res;
|
||||
msg_reply(&msg, &reply);
|
||||
break;
|
||||
case GNRC_NETAPI_MSG_TYPE_GET:
|
||||
/* read incoming options */
|
||||
opt = (gnrc_netapi_opt_t *)msg.content.ptr;
|
||||
DEBUG("gnrc_netdev2: GNRC_NETAPI_MSG_TYPE_GET received. opt=%s\n",
|
||||
netopt2str(opt->opt));
|
||||
/* get option from device driver */
|
||||
res = dev->driver->get(dev, opt->opt, opt->data, opt->data_len);
|
||||
DEBUG("gnrc_netdev2: response of netdev->get: %i\n", res);
|
||||
/* send reply to calling thread */
|
||||
reply.type = GNRC_NETAPI_MSG_TYPE_ACK;
|
||||
reply.content.value = (uint32_t)res;
|
||||
msg_reply(&msg, &reply);
|
||||
break;
|
||||
default:
|
||||
DEBUG("gnrc_netdev2: Unknown command %" PRIu16 "\n", msg.type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* never reached */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
kernel_pid_t gnrc_netdev2_init(char *stack, int stacksize, char priority,
|
||||
const char *name, gnrc_netdev2_t *gnrc_netdev2)
|
||||
{
|
||||
kernel_pid_t res;
|
||||
|
||||
/* check if given netdev device is defined and the driver is set */
|
||||
if (gnrc_netdev2 == NULL || gnrc_netdev2->dev == NULL) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* create new gnrc_netdev2 thread */
|
||||
res = thread_create(stack, stacksize, priority, CREATE_STACKTEST,
|
||||
_gnrc_netdev2_thread, (void *)gnrc_netdev2, name);
|
||||
if (res <= 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
207
sys/net/gnrc/link_layer/netdev2/gnrc_netdev2_eth.c
Normal file
207
sys/net/gnrc/link_layer/netdev2/gnrc_netdev2_eth.c
Normal file
@ -0,0 +1,207 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @{
|
||||
* @ingroup net
|
||||
* @file
|
||||
* @brief gnrc netdev2 ethernet glue code
|
||||
*
|
||||
* @author Kaspar Schleiser <kaspar@schleiser.de>
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "net/gnrc.h"
|
||||
#include "net/gnrc/gnrc_netdev2.h"
|
||||
#include "net/ethernet/hdr.h"
|
||||
|
||||
#include "od.h"
|
||||
|
||||
#define ENABLE_DEBUG (0)
|
||||
#include "debug.h"
|
||||
|
||||
static gnrc_pktsnip_t *_recv(gnrc_netdev2_t *gnrc_netdev2)
|
||||
{
|
||||
netdev2_t *dev = gnrc_netdev2->dev;
|
||||
int bytes_expected = dev->driver->recv(dev, NULL, 0);
|
||||
gnrc_pktsnip_t *pkt = NULL;
|
||||
|
||||
if (bytes_expected) {
|
||||
pkt = gnrc_pktbuf_add(NULL, NULL,
|
||||
bytes_expected,
|
||||
GNRC_NETTYPE_UNDEF);
|
||||
|
||||
if(!pkt) {
|
||||
DEBUG("_recv_ethernet_packet: cannot allocate pktsnip.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
int nread = dev->driver->recv(dev, pkt->data, bytes_expected);
|
||||
if(nread <= 0) {
|
||||
DEBUG("_recv_ethernet_packet: read error.\n");
|
||||
goto safe_out;
|
||||
}
|
||||
|
||||
if (nread < bytes_expected) {
|
||||
/* we've got less then the expected packet size,
|
||||
* so free the unused space.*/
|
||||
|
||||
DEBUG("_recv_ethernet_packet: reallocating.\n");
|
||||
gnrc_pktbuf_realloc_data(pkt, nread);
|
||||
}
|
||||
|
||||
/* mark ethernet header */
|
||||
gnrc_pktsnip_t *eth_hdr = gnrc_pktbuf_mark(pkt, sizeof(ethernet_hdr_t), GNRC_NETTYPE_UNDEF);
|
||||
if (!eth_hdr) {
|
||||
DEBUG("gnrc_netdev2_eth: no space left in packet buffer\n");
|
||||
goto safe_out;
|
||||
}
|
||||
|
||||
ethernet_hdr_t *hdr = (ethernet_hdr_t *)eth_hdr->data;
|
||||
|
||||
/* set payload type from ethertype */
|
||||
pkt->type = gnrc_nettype_from_ethertype(byteorder_ntohs(hdr->type));
|
||||
|
||||
/* create netif header */
|
||||
gnrc_pktsnip_t *netif_hdr;
|
||||
netif_hdr = gnrc_pktbuf_add(NULL, NULL,
|
||||
sizeof(gnrc_netif_hdr_t) + (2 * ETHERNET_ADDR_LEN),
|
||||
GNRC_NETTYPE_NETIF);
|
||||
|
||||
if (netif_hdr == NULL) {
|
||||
DEBUG("gnrc_netdev2_eth: no space left in packet buffer\n");
|
||||
pkt = eth_hdr;
|
||||
goto safe_out;
|
||||
}
|
||||
|
||||
gnrc_netif_hdr_init(netif_hdr->data, ETHERNET_ADDR_LEN, ETHERNET_ADDR_LEN);
|
||||
gnrc_netif_hdr_set_src_addr(netif_hdr->data, hdr->src, ETHERNET_ADDR_LEN);
|
||||
gnrc_netif_hdr_set_dst_addr(netif_hdr->data, hdr->dst, ETHERNET_ADDR_LEN);
|
||||
((gnrc_netif_hdr_t *)netif_hdr->data)->if_pid = thread_getpid();
|
||||
|
||||
DEBUG("gnrc_netdev2_eth: received packet from %02x:%02x:%02x:%02x:%02x:%02x "
|
||||
"of length %zu\n",
|
||||
hdr->src[0], hdr->src[1], hdr->src[2], hdr->src[3], hdr->src[4],
|
||||
hdr->src[5], nread);
|
||||
#if defined(MODULE_OD) && ENABLE_DEBUG
|
||||
od_hex_dump(hdr, nread, OD_WIDTH_DEFAULT);
|
||||
#endif
|
||||
|
||||
gnrc_pktbuf_remove_snip(pkt, eth_hdr);
|
||||
LL_APPEND(pkt, netif_hdr);
|
||||
}
|
||||
|
||||
out:
|
||||
return pkt;
|
||||
|
||||
safe_out:
|
||||
gnrc_pktbuf_release(pkt);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void _addr_set_broadcast(uint8_t *dst)
|
||||
{
|
||||
memset(dst, 0xff, ETHERNET_ADDR_LEN);
|
||||
}
|
||||
|
||||
#define _IPV6_DST_OFFSET (36) /* sizeof(ipv6_hdr_t) - 4 */
|
||||
|
||||
static inline void _addr_set_multicast(uint8_t *dst, gnrc_pktsnip_t *payload)
|
||||
{
|
||||
switch (payload->type) {
|
||||
#ifdef MODULE_IPV6
|
||||
case GNRC_NETTYPE_IPV6:
|
||||
dst[0] = 0x33;
|
||||
dst[1] = 0x33;
|
||||
memcpy(dst + 2, ((uint8_t *)payload->data) + _IPV6_DST_OFFSET, 4);
|
||||
/* TODO change to proper types when gnrc_ipv6_hdr_t got merged */
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
_addr_set_broadcast(dst);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int _send(gnrc_netdev2_t *gnrc_netdev2, gnrc_pktsnip_t *pkt)
|
||||
{
|
||||
ethernet_hdr_t hdr;
|
||||
gnrc_netif_hdr_t *netif_hdr;
|
||||
gnrc_pktsnip_t *payload;
|
||||
|
||||
netdev2_t *dev = gnrc_netdev2->dev;
|
||||
|
||||
if (pkt == NULL) {
|
||||
DEBUG("gnrc_netdev2_eth: pkt was NULL");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
payload = pkt->next;
|
||||
|
||||
if (pkt->type != GNRC_NETTYPE_NETIF) {
|
||||
DEBUG("gnrc_netdev2_eth: First header was not generic netif header\n");
|
||||
return -EBADMSG;
|
||||
}
|
||||
|
||||
if (payload) {
|
||||
hdr.type = byteorder_htons(gnrc_nettype_to_ethertype(payload->type));
|
||||
}
|
||||
else {
|
||||
hdr.type = byteorder_htons(ETHERTYPE_UNKNOWN);
|
||||
}
|
||||
|
||||
netif_hdr = pkt->data;
|
||||
|
||||
/* set ethernet header */
|
||||
if (netif_hdr->src_l2addr_len == ETHERNET_ADDR_LEN) {
|
||||
memcpy(hdr.dst, gnrc_netif_hdr_get_src_addr(netif_hdr),
|
||||
netif_hdr->src_l2addr_len);
|
||||
}
|
||||
else {
|
||||
dev->driver->get(dev, NETOPT_ADDRESS, hdr.src, ETHERNET_ADDR_LEN);
|
||||
}
|
||||
|
||||
if (netif_hdr->flags & GNRC_NETIF_HDR_FLAGS_BROADCAST) {
|
||||
_addr_set_broadcast(hdr.dst);
|
||||
}
|
||||
else if (netif_hdr->flags & GNRC_NETIF_HDR_FLAGS_MULTICAST) {
|
||||
_addr_set_multicast(hdr.dst, payload);
|
||||
}
|
||||
else if (netif_hdr->dst_l2addr_len == ETHERNET_ADDR_LEN) {
|
||||
memcpy(hdr.dst, gnrc_netif_hdr_get_dst_addr(netif_hdr),
|
||||
ETHERNET_ADDR_LEN);
|
||||
}
|
||||
else {
|
||||
DEBUG("gnrc_netdev2_eth: destination address had unexpected format\n");
|
||||
return -EBADMSG;
|
||||
}
|
||||
|
||||
DEBUG("gnrc_netdev2_eth: send to %02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
hdr.dst[0], hdr.dst[1], hdr.dst[2],
|
||||
hdr.dst[3], hdr.dst[4], hdr.dst[5]);
|
||||
|
||||
size_t n;
|
||||
pkt = gnrc_pktbuf_get_iovec(pkt, &n);
|
||||
struct iovec *vector = (struct iovec *)pkt->data;
|
||||
vector[0].iov_base = (char*)&hdr;
|
||||
vector[0].iov_len = sizeof(ethernet_hdr_t);
|
||||
dev->driver->send(dev, vector, n);
|
||||
|
||||
gnrc_pktbuf_release(pkt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gnrc_netdev2_eth_init(gnrc_netdev2_t *gnrc_netdev2, netdev2_t *dev)
|
||||
{
|
||||
gnrc_netdev2->send = _send;
|
||||
gnrc_netdev2->recv = _recv;
|
||||
gnrc_netdev2->dev = dev;
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user