1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-01-18 12:52:44 +01:00

nativenet: Supply net_dev_t support for nativenet

This commit is contained in:
Martine Lenders 2014-08-06 15:51:46 +02:00
parent 333c49a344
commit 264785852e
7 changed files with 515 additions and 37 deletions

View File

@ -1,4 +1,6 @@
ifneq (,$(filter defaulttransceiver,$(USEMODULE)))
USEMODULE += nativenet
USEMODULE += transceiver
USEMODULE += nativenet
ifeq (,$(filter netdev_base,$(USEMODULE)))
USEMODULE += transceiver
endif
endif

View File

@ -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;

View File

@ -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
*/

View File

@ -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);

View File

@ -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,61 +79,63 @@ 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;
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);
@ -178,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) {
@ -211,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");
}
@ -221,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 */
/** @} */

View File

@ -127,7 +127,7 @@ void _native_handle_tap_input(void)
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);
extern ssize_t (*real_write)(int fd, const void *buf, size_t count);
real_write(_sig_pipefd[1], &sig, sizeof(int));
_native_sigpend++;
DEBUG("_native_handle_tap_input: sigpend++\n");
@ -215,7 +215,7 @@ int _native_marshall_ethernet(uint8_t *framebuf, radio_packet_t *packet)
* Linux does this on its own, but it doesn't hurt to do it here.
* As of now only tuntaposx needs this. */
if (data_len < ETHERMIN) {
DEBUG("padding data!(%d -> ", data_len);
DEBUG("padding data! (%d -> ", data_len);
data_len = ETHERMIN;
DEBUG("%d)\n", data_len);
}
@ -314,7 +314,7 @@ int tap_init(char *name)
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];
@ -338,7 +338,7 @@ int tap_init(char *name)
err(EXIT_FAILURE, "tap_init(): fcntl(F_SETOWN)");
}
/* set file access mode to nonblocking */
/* 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)");
}

View File

@ -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_ */