mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-12-24 22:13:52 +01:00
Merge pull request #1732 from authmillenon/netdev-nativenet
nativenet: Port nativenet for netdev
This commit is contained in:
commit
56f8de866e
@ -1,4 +1,6 @@
|
||||
ifneq (,$(filter defaulttransceiver,$(USEMODULE)))
|
||||
USEMODULE += nativenet
|
||||
USEMODULE += transceiver
|
||||
USEMODULE += nativenet
|
||||
ifeq (,$(filter netdev_base,$(USEMODULE)))
|
||||
USEMODULE += transceiver
|
||||
endif
|
||||
endif
|
||||
|
||||
@ -41,7 +41,7 @@ void config_load(void)
|
||||
sysconfig.id = _native_id;
|
||||
|
||||
#ifdef MODULE_NATIVENET
|
||||
_native_net_addr = _native_id;
|
||||
_nativenet_default_dev_more._radio_addr = _native_id;
|
||||
#endif
|
||||
|
||||
return;
|
||||
|
||||
@ -28,10 +28,17 @@
|
||||
#include <net/ethernet.h>
|
||||
|
||||
#include "kernel_types.h"
|
||||
#include "netdev/base.h"
|
||||
|
||||
#define RX_BUF_SIZE (10)
|
||||
#define TRANSCEIVER_BUFFER_SIZE (3)
|
||||
|
||||
/**
|
||||
* @brief Number of registrable netdev_rcv_data_cb_t callbacks per nativenet
|
||||
* device
|
||||
*/
|
||||
#define NATIVENET_DEV_CB_MAX (128)
|
||||
|
||||
#ifndef NATIVE_MAX_DATA_LENGTH
|
||||
#include "tap.h"
|
||||
#ifdef MODULE_SIXLOWPAN
|
||||
@ -44,7 +51,17 @@
|
||||
#endif /* NATIVE_MAX_DATA_LENGTH */
|
||||
|
||||
/**
|
||||
* Initialize transceiver
|
||||
* @brief Implementation of netdev_driver_t for nativenet
|
||||
*/
|
||||
extern const netdev_driver_t nativenet_driver;
|
||||
|
||||
/**
|
||||
* @brief Default @netdev API device
|
||||
*/
|
||||
extern netdev_t nativenet_default_dev;
|
||||
|
||||
/**
|
||||
* Initialize @ref sys_transceiver and @ref nativenet_default_dev
|
||||
*
|
||||
* @param transceiver_pid the pid of the transceiver thread
|
||||
*/
|
||||
|
||||
@ -32,14 +32,68 @@
|
||||
#define NNEV_SWTRX 0x0b
|
||||
#define NNEV_MAXEV 0x0b
|
||||
|
||||
#define _NATIVENET_DEV_MORE(dev) ((_nativenet_netdev_more_t *)dev->more)
|
||||
|
||||
struct rx_buffer_s {
|
||||
radio_packet_t packet;
|
||||
char data[NATIVE_MAX_DATA_LENGTH];
|
||||
};
|
||||
|
||||
extern struct rx_buffer_s _nativenet_rx_buffer[RX_BUF_SIZE];
|
||||
extern uint64_t _native_net_addr_long;
|
||||
extern radio_address_t _native_net_addr;
|
||||
|
||||
/**
|
||||
* @brief Definition of network device data.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief The channel assigned to this device
|
||||
*
|
||||
* @note For internal use only, do not change externally!
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
uint8_t _channel;
|
||||
|
||||
/**
|
||||
* @brief The PAN ID assigned to this device
|
||||
*
|
||||
* @note For internal use only, do not change externally!
|
||||
* @internal
|
||||
*/
|
||||
uint16_t _pan_id;
|
||||
|
||||
/**
|
||||
* @brief The short address assigned to this device
|
||||
*
|
||||
* @note For internal use only, do not change externally!
|
||||
* @internal
|
||||
*/
|
||||
radio_address_t _radio_addr;
|
||||
|
||||
/**
|
||||
* @brief The long address assigned to this device
|
||||
*
|
||||
* @note For internal use only, do not change externally!
|
||||
* @internal
|
||||
*/
|
||||
uint64_t _long_addr;
|
||||
|
||||
/**
|
||||
* @brief Flag to determine if device is in promiscuous mode
|
||||
*
|
||||
* @note For internal use only, do not change externally!
|
||||
* @internal
|
||||
*/
|
||||
uint8_t _is_monitoring;
|
||||
|
||||
/**
|
||||
* @brief Receive data callbacks for this device
|
||||
*/
|
||||
netdev_rcv_data_cb_t _callbacks[NATIVENET_DEV_CB_MAX];
|
||||
} _nativenet_netdev_more_t;
|
||||
|
||||
/* internal counterpart to nativenet_default_dev */
|
||||
extern _nativenet_netdev_more_t _nativenet_default_dev_more;
|
||||
|
||||
void _nativenet_handle_packet(radio_packet_t *packet);
|
||||
int8_t send_buf(radio_packet_t *packet);
|
||||
|
||||
@ -42,24 +42,32 @@ static struct nativenet_callback_s _nativenet_callbacks[255];
|
||||
struct rx_buffer_s _nativenet_rx_buffer[RX_BUF_SIZE];
|
||||
static volatile uint8_t rx_buffer_next;
|
||||
|
||||
uint8_t _native_net_chan;
|
||||
uint16_t _native_net_pan;
|
||||
uint8_t _native_net_monitor;
|
||||
static kernel_pid_t _native_net_tpid = KERNEL_PID_UNDEF;
|
||||
radio_address_t _native_net_addr;
|
||||
uint64_t _native_net_addr_long;
|
||||
|
||||
/************************************************************************/
|
||||
/* nativenet.h **********************************************************/
|
||||
/************************************************************************/
|
||||
|
||||
int _nativenet_init(netdev_t *dev)
|
||||
{
|
||||
if ((dev->type != NETDEV_TYPE_BASE) || (dev->more == NULL)) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
_NATIVENET_DEV_MORE(dev)->_channel = 0;
|
||||
_NATIVENET_DEV_MORE(dev)->_pan_id = 0;
|
||||
_NATIVENET_DEV_MORE(dev)->_is_monitoring = 0;
|
||||
memset(_NATIVENET_DEV_MORE(dev)->_callbacks, 0,
|
||||
sizeof((_NATIVENET_DEV_MORE(dev)->_callbacks)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nativenet_init(kernel_pid_t transceiver_pid)
|
||||
{
|
||||
DEBUG("nativenet_init(transceiver_pid=%" PRIkernel_pid ")\n", transceiver_pid);
|
||||
rx_buffer_next = 0;
|
||||
_native_net_pan = 0;
|
||||
_native_net_chan = 0;
|
||||
_native_net_monitor = 0;
|
||||
_nativenet_init((netdev_t *)(&nativenet_default_dev));
|
||||
_native_net_tpid = transceiver_pid;
|
||||
}
|
||||
|
||||
@ -71,62 +79,65 @@ void nativenet_powerdown(void)
|
||||
void nativenet_set_monitor(uint8_t mode)
|
||||
{
|
||||
DEBUG("nativenet_set_monitor(mode=%d)\n", mode);
|
||||
_native_net_monitor = mode;
|
||||
_nativenet_default_dev_more._is_monitoring = mode;
|
||||
}
|
||||
|
||||
int16_t nativenet_set_channel(uint8_t channel)
|
||||
{
|
||||
_native_net_chan = channel;
|
||||
return _native_net_chan;
|
||||
_nativenet_default_dev_more._channel = channel;
|
||||
return _nativenet_default_dev_more._channel;
|
||||
}
|
||||
|
||||
int16_t nativenet_get_channel(void)
|
||||
{
|
||||
return _native_net_chan;
|
||||
return _nativenet_default_dev_more._channel;
|
||||
}
|
||||
|
||||
uint16_t nativenet_set_pan(uint16_t pan)
|
||||
{
|
||||
_native_net_pan = pan;
|
||||
return _native_net_pan;
|
||||
_nativenet_default_dev_more._pan_id = pan;
|
||||
return _nativenet_default_dev_more._pan_id;
|
||||
}
|
||||
|
||||
uint16_t nativenet_get_pan(void)
|
||||
{
|
||||
return _native_net_pan;
|
||||
return _nativenet_default_dev_more._pan_id;
|
||||
}
|
||||
|
||||
radio_address_t nativenet_set_address(radio_address_t address)
|
||||
{
|
||||
DEBUG("nativenet_set_address(address=%d)\n", address);
|
||||
_native_net_addr = address;
|
||||
return _native_net_addr;
|
||||
_nativenet_default_dev_more._radio_addr = address;
|
||||
return _nativenet_default_dev_more._radio_addr;
|
||||
}
|
||||
|
||||
radio_address_t nativenet_get_address(void)
|
||||
{
|
||||
DEBUG("nativenet_get_address -> address = %d\n", _native_net_addr);
|
||||
return _native_net_addr;
|
||||
DEBUG("nativenet_get_address -> address = %d\n",
|
||||
_nativenet_default_dev_more._radio_addr);
|
||||
return _nativenet_default_dev_more._radio_addr;
|
||||
}
|
||||
|
||||
uint64_t nativenet_get_address_long(void)
|
||||
{
|
||||
DEBUG("nativenet_get_address_long -> address = %" PRIx64 "\n", _native_net_addr_long);
|
||||
return _native_net_addr_long;
|
||||
DEBUG("nativenet_get_address_long -> address = %" PRIx64 "\n",
|
||||
_nativenet_default_dev_more._long_addr);
|
||||
return _nativenet_default_dev_more._long_addr;
|
||||
}
|
||||
|
||||
uint64_t nativenet_set_address_long(uint64_t address)
|
||||
{
|
||||
DEBUG("nativenet_set_address_long(address=%" PRIx64 ")\n", address);
|
||||
warnx("nativenet_set_address_long: this does not actually change the interfaces address");
|
||||
_native_net_addr_long = address;
|
||||
return _native_net_addr_long;
|
||||
_nativenet_default_dev_more._long_addr = address;
|
||||
return _nativenet_default_dev_more._long_addr;
|
||||
}
|
||||
|
||||
int8_t nativenet_send(radio_packet_t *packet)
|
||||
{
|
||||
packet->src = _native_net_addr;
|
||||
DEBUG("nativenet_send: Sending packet of length %" PRIu16 " from %" PRIu16 " to %" PRIu16 "\n", packet->length, packet->src, packet->dst);
|
||||
packet->src = _nativenet_default_dev_more._radio_addr;
|
||||
DEBUG("nativenet_send: Sending packet of length %" PRIu16 " from %" PRIu16 " to %" PRIu16 "\n",
|
||||
packet->length, packet->src, packet->dst);
|
||||
|
||||
return send_buf(packet);
|
||||
}
|
||||
@ -177,14 +188,19 @@ void do_cb(int event)
|
||||
void _nativenet_handle_packet(radio_packet_t *packet)
|
||||
{
|
||||
radio_address_t dst_addr = packet->dst;
|
||||
int notified = 0;
|
||||
|
||||
/* TODO: find way to demultiplex reception from several taps and map them
|
||||
* to devices. */
|
||||
netdev_t *dev = &nativenet_default_dev;
|
||||
|
||||
/* address filter / monitor mode */
|
||||
if (_native_net_monitor == 1) {
|
||||
if (_nativenet_default_dev_more._is_monitoring == 1) {
|
||||
DEBUG("_nativenet_handle_packet: monitoring, not filtering address \n");
|
||||
}
|
||||
else {
|
||||
/* own addr check */
|
||||
if (dst_addr == _native_net_addr) {
|
||||
if (dst_addr == _nativenet_default_dev_more._radio_addr) {
|
||||
DEBUG("_nativenet_handle_packet: accept packet, addressed to us\n");
|
||||
}
|
||||
else if (dst_addr == 0) {
|
||||
@ -200,7 +216,8 @@ void _nativenet_handle_packet(radio_packet_t *packet)
|
||||
DEBUG("\n\t\trx_buffer_next: %i\n\n", rx_buffer_next);
|
||||
memcpy(&_nativenet_rx_buffer[rx_buffer_next].data, packet->data, packet->length);
|
||||
memcpy(&_nativenet_rx_buffer[rx_buffer_next].packet, packet, sizeof(radio_packet_t));
|
||||
_nativenet_rx_buffer[rx_buffer_next].packet.data = (uint8_t *) &_nativenet_rx_buffer[rx_buffer_next].data;
|
||||
_nativenet_rx_buffer[rx_buffer_next].packet.data = (uint8_t *)
|
||||
&_nativenet_rx_buffer[rx_buffer_next].data;
|
||||
|
||||
/* notify transceiver thread if any */
|
||||
if (_native_net_tpid != KERNEL_PID_UNDEF) {
|
||||
@ -209,8 +226,23 @@ void _nativenet_handle_packet(radio_packet_t *packet)
|
||||
m.type = (uint16_t) RCV_PKT_NATIVE;
|
||||
m.content.value = rx_buffer_next;
|
||||
msg_send_int(&m, _native_net_tpid);
|
||||
notified = 1;
|
||||
}
|
||||
else {
|
||||
|
||||
for (int i = 0; i < NATIVENET_DEV_CB_MAX; i++) {
|
||||
if (_NATIVENET_DEV_MORE(dev)->_callbacks[i]) {
|
||||
_NATIVENET_DEV_MORE(dev)->_callbacks[i]((netdev_t *)dev,
|
||||
&(_nativenet_rx_buffer[rx_buffer_next].packet.src),
|
||||
sizeof(uint16_t),
|
||||
&(_nativenet_rx_buffer[rx_buffer_next].packet.dst),
|
||||
sizeof(uint16_t),
|
||||
&(_nativenet_rx_buffer[rx_buffer_next].data),
|
||||
(size_t)_nativenet_rx_buffer[rx_buffer_next].packet.length);
|
||||
notified = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!notified) {
|
||||
DEBUG("_nativenet_handle_packet: no one to notify =(\n");
|
||||
}
|
||||
|
||||
@ -219,4 +251,370 @@ void _nativenet_handle_packet(radio_packet_t *packet)
|
||||
rx_buffer_next = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
* netdev_base wrapper
|
||||
***************************************************************/
|
||||
|
||||
#ifdef MODULE_NETDEV_BASE
|
||||
int _nativenet_send_data(netdev_t *dev, void *dest, size_t dest_len,
|
||||
netdev_hlist_t *upper_layer_hdrs, void *data,
|
||||
size_t data_len)
|
||||
{
|
||||
netdev_hlist_t *ptr = upper_layer_hdrs;
|
||||
uint8_t tx_buffer[data_len + netdev_get_hlist_len(upper_layer_hdrs)];
|
||||
size_t tx_ptr = 0;
|
||||
radio_packet_t pkt = {0, 0, 0, 0, 0, {0, 0}, sizeof(tx_buffer), tx_buffer};
|
||||
|
||||
if (dev->type != NETDEV_TYPE_BASE) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (dest_len > sizeof(uint16_t)) {
|
||||
return -EAFNOSUPPORT;
|
||||
}
|
||||
|
||||
if (sizeof(tx_buffer) > NATIVE_MAX_DATA_LENGTH) {
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
if (upper_layer_hdrs) {
|
||||
do {
|
||||
memcpy(&(tx_buffer[tx_ptr]), ptr->header, ptr->header_len);
|
||||
tx_ptr += ptr->header_len;
|
||||
netdev_hlist_advance(&ptr);
|
||||
} while (ptr != upper_layer_hdrs);
|
||||
}
|
||||
|
||||
memcpy(&(tx_buffer[tx_ptr]), data, data_len);
|
||||
|
||||
if (dest_len == sizeof(uint16_t)) {
|
||||
pkt.dst = *((uint16_t *)dest);
|
||||
}
|
||||
else {
|
||||
pkt.dst = (uint16_t)(*((uint8_t *)dest));
|
||||
}
|
||||
|
||||
return nativenet_send(&pkt);
|
||||
}
|
||||
|
||||
int _nativenet_add_rcv_data_cb(netdev_t *dev, netdev_rcv_data_cb_t cb)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
if (dev->type != NETDEV_TYPE_BASE) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
for (i = 0; i < NATIVENET_DEV_CB_MAX; i++) {
|
||||
if (_NATIVENET_DEV_MORE(dev)->_callbacks[i] == NULL ||
|
||||
_NATIVENET_DEV_MORE(dev)->_callbacks[i] == cb) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= NATIVENET_DEV_CB_MAX) {
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
_NATIVENET_DEV_MORE(dev)->_callbacks[i] = cb;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _nativenet_rem_rcv_data_cb(netdev_t *dev, netdev_rcv_data_cb_t cb)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
if (dev->type != NETDEV_TYPE_BASE) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
for (i = 0; i < NATIVENET_DEV_CB_MAX; i++) {
|
||||
if (_NATIVENET_DEV_MORE(dev)->_callbacks[i] == cb) {
|
||||
_NATIVENET_DEV_MORE(dev)->_callbacks[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _nativenet_get_option(netdev_t *dev, netdev_opt_t opt, void *value,
|
||||
size_t *value_len)
|
||||
{
|
||||
if (dev->type != NETDEV_TYPE_BASE) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
switch (opt) {
|
||||
case NETDEV_OPT_CHANNEL:
|
||||
if (*value_len == 0) {
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
|
||||
if (*value_len > sizeof(uint8_t)) {
|
||||
*value_len = sizeof(uint8_t);
|
||||
}
|
||||
|
||||
*((uint8_t *)value) = _NATIVENET_DEV_MORE(dev)->_channel;
|
||||
break;
|
||||
|
||||
case NETDEV_OPT_ADDRESS:
|
||||
if (*value_len < sizeof(radio_address_t)) {
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
|
||||
if (*value_len > sizeof(radio_address_t)) {
|
||||
*value_len = sizeof(radio_address_t);
|
||||
}
|
||||
|
||||
*((radio_address_t *)value) = _NATIVENET_DEV_MORE(dev)->_radio_addr;
|
||||
break;
|
||||
|
||||
case NETDEV_OPT_NID:
|
||||
if (*value_len < sizeof(uint16_t)) {
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
|
||||
if (*value_len > sizeof(uint16_t)) {
|
||||
*value_len = sizeof(uint16_t);
|
||||
}
|
||||
|
||||
*((uint16_t *)value) = _NATIVENET_DEV_MORE(dev)->_pan_id;
|
||||
break;
|
||||
|
||||
case NETDEV_OPT_ADDRESS_LONG:
|
||||
if (*value_len < sizeof(uint64_t)) {
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
|
||||
if (*value_len > sizeof(uint64_t)) {
|
||||
*value_len = sizeof(uint64_t);
|
||||
}
|
||||
|
||||
*((uint64_t *)value) = _NATIVENET_DEV_MORE(dev)->_long_addr;
|
||||
break;
|
||||
|
||||
case NETDEV_OPT_MAX_PACKET_SIZE:
|
||||
if (*value_len < sizeof(NATIVE_MAX_DATA_LENGTH)) {
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
|
||||
if (*value_len > sizeof(NATIVE_MAX_DATA_LENGTH)) {
|
||||
*value_len = sizeof(NATIVE_MAX_DATA_LENGTH);
|
||||
}
|
||||
|
||||
*((netdev_proto_t *)value) = NATIVE_MAX_DATA_LENGTH;
|
||||
break;
|
||||
|
||||
case NETDEV_OPT_PROTO:
|
||||
if (*value_len < sizeof(netdev_proto_t)) {
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
|
||||
if (*value_len > sizeof(netdev_proto_t)) {
|
||||
*value_len = sizeof(netdev_proto_t);
|
||||
}
|
||||
|
||||
*((netdev_proto_t *)value) = NETDEV_PROTO_RADIO;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _type_pun_up(void *value_out, size_t desired_len,
|
||||
void *value_in, size_t given_len)
|
||||
{
|
||||
if (given_len > desired_len) {
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
|
||||
/* XXX this is ugly, but bear with me */
|
||||
switch (given_len) {
|
||||
case 8:
|
||||
switch (desired_len) {
|
||||
case 8:
|
||||
*((uint64_t *)value_out) = (*((uint64_t *)value_in));
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
case 4:
|
||||
switch (desired_len) {
|
||||
case 8:
|
||||
*((uint64_t *)value_out) = (uint64_t)(*((uint32_t *)value_in));
|
||||
return 0;
|
||||
|
||||
case 4:
|
||||
*((uint32_t *)value_out) = (*((uint32_t *)value_in));
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
case 2:
|
||||
switch (desired_len) {
|
||||
case 8:
|
||||
*((uint64_t *)value_out) = (uint64_t)(*((uint16_t *)value_in));
|
||||
return 0;
|
||||
|
||||
case 4:
|
||||
*((uint32_t *)value_out) = (uint32_t)(*((uint16_t *)value_in));
|
||||
return 0;
|
||||
|
||||
case 2:
|
||||
*((uint16_t *)value_out) = (*((uint16_t *)value_in));
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
case 1:
|
||||
switch (desired_len) {
|
||||
case 8:
|
||||
*((uint64_t *)value_out) = (uint64_t)(*((uint8_t *)value_in));
|
||||
return 0;
|
||||
|
||||
case 4:
|
||||
*((uint32_t *)value_out) = (uint32_t)(*((uint8_t *)value_in));
|
||||
return 0;
|
||||
|
||||
case 2:
|
||||
*((uint16_t *)value_out) = (uint16_t)(*((uint8_t *)value_in));
|
||||
return 0;
|
||||
|
||||
case 1:
|
||||
*((uint8_t *)value_out) = (*((uint8_t *)value_in));
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int _nativenet_set_option(netdev_t *dev, netdev_opt_t opt, void *value,
|
||||
size_t value_len)
|
||||
{
|
||||
uint8_t set_value[sizeof(uint64_t)];
|
||||
int res = 0;
|
||||
|
||||
if (dev->type != NETDEV_TYPE_BASE) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
switch (opt) {
|
||||
case NETDEV_OPT_CHANNEL:
|
||||
if ((res = _type_pun_up(set_value, sizeof(uint8_t),
|
||||
value, value_len)) == 0) {
|
||||
_NATIVENET_DEV_MORE(dev)->_channel = *((uint8_t *)set_value);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case NETDEV_OPT_ADDRESS:
|
||||
if ((res = _type_pun_up(set_value, sizeof(radio_address_t),
|
||||
value, value_len)) == 0) {
|
||||
_NATIVENET_DEV_MORE(dev)->_radio_addr = *((radio_address_t *)set_value);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case NETDEV_OPT_NID:
|
||||
if ((res = _type_pun_up(set_value, sizeof(uint16_t),
|
||||
value, value_len)) == 0) {
|
||||
_NATIVENET_DEV_MORE(dev)->_pan_id = *((uint16_t *)set_value);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case NETDEV_OPT_PROTO:
|
||||
/* TODO: wouldn't this be awesome */
|
||||
return -ENOTSUP;
|
||||
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int _nativenet_get_state(netdev_t *dev, netdev_state_t *state)
|
||||
{
|
||||
if (dev->type != NETDEV_TYPE_BASE) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (_NATIVENET_DEV_MORE(dev)->_is_monitoring) {
|
||||
*state = NETDEV_STATE_PROMISCUOUS_MODE;
|
||||
}
|
||||
else {
|
||||
*state = NETDEV_STATE_RX_MODE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _nativenet_set_state(netdev_t *dev, netdev_state_t state)
|
||||
{
|
||||
if (state != NETDEV_STATE_PROMISCUOUS_MODE && _NATIVENET_DEV_MORE(dev)->_is_monitoring) {
|
||||
_NATIVENET_DEV_MORE(dev)->_is_monitoring = 0;
|
||||
}
|
||||
|
||||
switch (state) {
|
||||
case NETDEV_STATE_RX_MODE:
|
||||
nativenet_switch_to_rx();
|
||||
break;
|
||||
|
||||
case NETDEV_STATE_PROMISCUOUS_MODE:
|
||||
_NATIVENET_DEV_MORE(dev)->_is_monitoring = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void _nativenet_event(netdev_t *dev, uint32_t event_type)
|
||||
{
|
||||
(void)dev;
|
||||
(void)event_type;
|
||||
}
|
||||
|
||||
const netdev_driver_t nativenet_driver = {
|
||||
_nativenet_init,
|
||||
_nativenet_send_data,
|
||||
_nativenet_add_rcv_data_cb,
|
||||
_nativenet_rem_rcv_data_cb,
|
||||
_nativenet_get_option,
|
||||
_nativenet_set_option,
|
||||
_nativenet_get_state,
|
||||
_nativenet_set_state,
|
||||
_nativenet_event,
|
||||
};
|
||||
|
||||
_nativenet_netdev_more_t _nativenet_default_dev_more;
|
||||
netdev_t nativenet_default_dev = {NETDEV_TYPE_BASE, &nativenet_driver,
|
||||
&_nativenet_default_dev_more
|
||||
};
|
||||
#else
|
||||
_nativenet_netdev_more_t _nativenet_default_dev_more;
|
||||
netdev_t nativenet_default_dev = {NETDEV_TYPE_BASE, NULL,
|
||||
&_nativenet_default_dev_more
|
||||
};
|
||||
#endif /* MODULE_NETDEV_BASE */
|
||||
|
||||
/** @} */
|
||||
|
||||
@ -80,9 +80,11 @@ void _native_handle_tap_input(void)
|
||||
|
||||
nread = real_read(_native_tap_fd, &frame, sizeof(union eth_frame));
|
||||
DEBUG("_native_handle_tap_input - read %d bytes\n", nread);
|
||||
|
||||
if (nread > 0) {
|
||||
if (ntohs(frame.field.header.ether_type) == NATIVE_ETH_PROTO) {
|
||||
nread = nread - ETHER_HDR_LEN;
|
||||
|
||||
if ((nread - 1) <= 0) {
|
||||
DEBUG("_native_handle_tap_input: no payload\n");
|
||||
}
|
||||
@ -93,16 +95,18 @@ void _native_handle_tap_input(void)
|
||||
p.dst = ntohs(frame.field.payload.nn_header.dst);
|
||||
p.rssi = 0;
|
||||
p.lqi = 0;
|
||||
p.toa.seconds = HWTIMER_TICKS_TO_US(t)/1000000;
|
||||
p.toa.microseconds = HWTIMER_TICKS_TO_US(t)%1000000;
|
||||
p.toa.seconds = HWTIMER_TICKS_TO_US(t) / 1000000;
|
||||
p.toa.microseconds = HWTIMER_TICKS_TO_US(t) % 1000000;
|
||||
/* XXX: check overflow */
|
||||
p.length = ntohs(frame.field.payload.nn_header.length);
|
||||
p.data = frame.field.payload.data;
|
||||
|
||||
if (p.length > (nread - sizeof(struct nativenet_header))) {
|
||||
warnx("_native_handle_tap_input: packet with malicious length field received, discarding");
|
||||
}
|
||||
else {
|
||||
DEBUG("_native_handle_tap_input: received packet of length %" PRIu16 " for %" PRIu16 " from %" PRIu16 "\n", p.length, p.dst, p.src);
|
||||
DEBUG("_native_handle_tap_input: received packet of length %" PRIu16 " for %" PRIu16 " from %"
|
||||
PRIu16 "\n", p.length, p.dst, p.src);
|
||||
_nativenet_handle_packet(&p);
|
||||
}
|
||||
}
|
||||
@ -119,7 +123,8 @@ void _native_handle_tap_input(void)
|
||||
FD_SET(_native_tap_fd, &rfds);
|
||||
|
||||
_native_in_syscall++; // no switching here
|
||||
if (select(_native_tap_fd +1, &rfds, NULL, NULL, &t) == 1) {
|
||||
|
||||
if (select(_native_tap_fd + 1, &rfds, NULL, NULL, &t) == 1) {
|
||||
int sig = SIGIO;
|
||||
extern int _sig_pipefd[2];
|
||||
extern ssize_t (*real_write)(int fd, const void *buf, size_t count);
|
||||
@ -133,10 +138,11 @@ void _native_handle_tap_input(void)
|
||||
kill(sigio_child_pid, SIGCONT);
|
||||
#endif
|
||||
}
|
||||
|
||||
_native_in_syscall--;
|
||||
}
|
||||
else if (nread == -1) {
|
||||
if ((errno == EAGAIN ) || (errno == EWOULDBLOCK)) {
|
||||
if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
|
||||
//warn("read");
|
||||
}
|
||||
else {
|
||||
@ -166,16 +172,19 @@ void sigio_child(void)
|
||||
* available */
|
||||
|
||||
fd_set rfds;
|
||||
|
||||
while (1) {
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(_native_tap_fd, &rfds);
|
||||
if (select(_native_tap_fd +1, &rfds, NULL, NULL, NULL) == 1) {
|
||||
|
||||
if (select(_native_tap_fd + 1, &rfds, NULL, NULL, NULL) == 1) {
|
||||
kill(parent, SIGIO);
|
||||
}
|
||||
else {
|
||||
kill(parent, SIGKILL);
|
||||
err(EXIT_FAILURE, "osx_sigio_child: select");
|
||||
}
|
||||
|
||||
pause();
|
||||
}
|
||||
}
|
||||
@ -187,7 +196,7 @@ int _native_marshall_ethernet(uint8_t *framebuf, radio_packet_t *packet)
|
||||
union eth_frame *f;
|
||||
unsigned char addr[ETHER_ADDR_LEN];
|
||||
|
||||
f = (union eth_frame*)framebuf;
|
||||
f = (union eth_frame *)framebuf;
|
||||
addr[0] = addr[1] = addr[2] = addr[3] = addr[4] = addr[5] = 0xFF;
|
||||
|
||||
memcpy(f->field.header.ether_dhost, addr, ETHER_ADDR_LEN);
|
||||
@ -221,15 +230,17 @@ int8_t send_buf(radio_packet_t *packet)
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
DEBUG("send_buf: Sending packet of length %" PRIu16 " from %" PRIu16 " to %" PRIu16 "\n", packet->length, packet->src, packet->dst);
|
||||
DEBUG("send_buf: Sending packet of length %" PRIu16 " from %" PRIu16 " to %" PRIu16 "\n",
|
||||
packet->length, packet->src, packet->dst);
|
||||
to_send = _native_marshall_ethernet(buf, packet);
|
||||
|
||||
DEBUG("send_buf: trying to send %d bytes\n", to_send);
|
||||
|
||||
if ((nsent = _native_write(_native_tap_fd, buf, to_send)) == -1) {;
|
||||
if ((nsent = _native_write(_native_tap_fd, buf, to_send)) == -1) {
|
||||
warn("write");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (nsent > INT8_MAX ? INT8_MAX : nsent);
|
||||
}
|
||||
|
||||
@ -238,10 +249,10 @@ int tap_init(char *name)
|
||||
|
||||
#ifdef __MACH__ /* OSX */
|
||||
char clonedev[255] = "/dev/"; /* XXX bad size */
|
||||
strncpy(clonedev+5, name, 250);
|
||||
strncpy(clonedev + 5, name, 250);
|
||||
#elif defined(__FreeBSD__)
|
||||
char clonedev[255] = "/dev/"; /* XXX bad size */
|
||||
strncpy(clonedev+5, name, 250);
|
||||
strncpy(clonedev + 5, name, 250);
|
||||
#else /* Linux */
|
||||
struct ifreq ifr;
|
||||
const char *clonedev = "/dev/net/tun";
|
||||
@ -253,11 +264,12 @@ int tap_init(char *name)
|
||||
}
|
||||
|
||||
#if (defined(__MACH__) || defined(__FreeBSD__)) /* OSX/FreeBSD */
|
||||
struct ifaddrs* iflist;
|
||||
struct ifaddrs *iflist;
|
||||
|
||||
if (getifaddrs(&iflist) == 0) {
|
||||
for (struct ifaddrs *cur = iflist; cur; cur = cur->ifa_next) {
|
||||
if ((cur->ifa_addr->sa_family == AF_LINK) && (strcmp(cur->ifa_name, name) == 0) && cur->ifa_addr) {
|
||||
struct sockaddr_dl* sdl = (struct sockaddr_dl*)cur->ifa_addr;
|
||||
struct sockaddr_dl *sdl = (struct sockaddr_dl *)cur->ifa_addr;
|
||||
memcpy(_native_tap_mac, LLADDR(sdl), sdl->sdl_alen);
|
||||
break;
|
||||
}
|
||||
@ -265,6 +277,7 @@ int tap_init(char *name)
|
||||
|
||||
freeifaddrs(iflist);
|
||||
}
|
||||
|
||||
#else /* Linux */
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
|
||||
@ -282,21 +295,26 @@ int tap_init(char *name)
|
||||
|
||||
|
||||
/* get MAC address */
|
||||
memset (&ifr, 0, sizeof (ifr));
|
||||
snprintf (ifr.ifr_name, sizeof (ifr.ifr_name), "%s", name);
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", name);
|
||||
|
||||
if (ioctl(_native_tap_fd, SIOCGIFHWADDR, &ifr) == -1) {
|
||||
_native_in_syscall++;
|
||||
warn("ioctl SIOCGIFHWADDR");
|
||||
|
||||
if (real_close(_native_tap_fd) == -1) {
|
||||
warn("close");
|
||||
}
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
memcpy(_native_tap_mac, ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
|
||||
#endif
|
||||
DEBUG("_native_tap_mac: %02x:%02x:%02x:%02x:%02x:%02x\n", _native_tap_mac[0], _native_tap_mac[1], _native_tap_mac[2], _native_tap_mac[3], _native_tap_mac[4], _native_tap_mac[5]);
|
||||
DEBUG("_native_tap_mac: %02x:%02x:%02x:%02x:%02x:%02x\n", _native_tap_mac[0], _native_tap_mac[1],
|
||||
_native_tap_mac[2], _native_tap_mac[3], _native_tap_mac[4], _native_tap_mac[5]);
|
||||
|
||||
unsigned char *eui_64 = (unsigned char*)&_native_net_addr_long;
|
||||
unsigned char *eui_64 = (unsigned char *)(&(_nativenet_default_dev_more._long_addr));
|
||||
eui_64[0] = _native_tap_mac[0];
|
||||
eui_64[1] = _native_tap_mac[1];
|
||||
eui_64[2] = _native_tap_mac[2];
|
||||
@ -314,15 +332,17 @@ int tap_init(char *name)
|
||||
* check http://sourceforge.net/p/tuntaposx/bugs/17/ */
|
||||
sigio_child();
|
||||
#else
|
||||
|
||||
/* configure fds to send signals on io */
|
||||
if (fcntl(_native_tap_fd, F_SETOWN, _native_pid) == -1) {
|
||||
err(EXIT_FAILURE, "tap_init(): fcntl(F_SETOWN)");
|
||||
}
|
||||
|
||||
/* set file access mode to nonblocking */
|
||||
if (fcntl(_native_tap_fd, F_SETFL, O_NONBLOCK|O_ASYNC) == -1) {
|
||||
/* set file access mode to non-blocking */
|
||||
if (fcntl(_native_tap_fd, F_SETFL, O_NONBLOCK | O_ASYNC) == -1) {
|
||||
err(EXIT_FAILURE, "tap_init(): fcntl(F_SETFL)");
|
||||
}
|
||||
|
||||
#endif /* not OSX */
|
||||
|
||||
DEBUG("RIOT native tap initialized.\n");
|
||||
|
||||
@ -27,4 +27,13 @@
|
||||
*
|
||||
* @brief Default device as a pointer of netdev_t.
|
||||
*/
|
||||
|
||||
#ifdef MODULE_NATIVENET
|
||||
#include "nativenet.h"
|
||||
|
||||
#ifndef NETDEV_DEFAULT
|
||||
#define NETDEV_DEFAULT (&nativenet_default_dev)
|
||||
#endif /* NETDEV_DEFAULT */
|
||||
#endif /* MODULE_NATIVENET */
|
||||
|
||||
#endif /* __NETDEV_DEFAULT_H_ */
|
||||
|
||||
@ -34,14 +34,8 @@
|
||||
#ifdef NETDEV_DEFAULT
|
||||
#define SHELL_BUFSIZE (UART0_BUFSIZE)
|
||||
|
||||
#ifndef MODULE_NATIVENET
|
||||
static netdev_t dev_mem;
|
||||
static netdev_t *dev = &dev_mem;
|
||||
#else
|
||||
static netdev_t *dev = (netdev_t *) &nativenet_default_dev;
|
||||
#endif
|
||||
|
||||
static size_t dev_address_len = 0;
|
||||
static netdev_t *dev = NULL;
|
||||
|
||||
/***********************************
|
||||
* test channel *
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user