diff --git a/Makefile.dep b/Makefile.dep index b53388538123..71b871d5db1b 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -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 diff --git a/boards/native/Makefile.dep b/boards/native/Makefile.dep index 317b8d73dbc9..76c68a2dafe7 100644 --- a/boards/native/Makefile.dep +++ b/boards/native/Makefile.dep @@ -1,5 +1,4 @@ ifneq (,$(filter gnrc_netif_default,$(USEMODULE))) - USEMODULE += dev_eth_tap - USEMODULE += gnrc_netdev_eth - USEMODULE += gnrc_nomac + USEMODULE += netdev2_tap + USEMODULE += gnrc_netdev2 endif diff --git a/boards/native/Makefile.include b/boards/native/Makefile.include index 9f0ede99754c..670da457e3cd 100644 --- a/boards/native/Makefile.include +++ b/boards/native/Makefile.include @@ -72,7 +72,7 @@ export LINKFLAGS += -ldl endif # set the tap interface for term/valgrind -ifneq (,$(filter dev_eth_tap,$(USEMODULE))) +ifneq (,$(filter netdev2_tap,$(USEMODULE))) export PORT ?= tap0 else export PORT = diff --git a/cpu/native/Makefile b/cpu/native/Makefile index 7f538c1f419d..c601d3323e72 100644 --- a/cpu/native/Makefile +++ b/cpu/native/Makefile @@ -2,8 +2,8 @@ MODULE = cpu DIRS += periph -ifneq (,$(filter dev_eth_tap,$(USEMODULE))) - DIRS += dev_eth_tap +ifneq (,$(filter netdev2_tap,$(USEMODULE))) + DIRS += netdev2_tap endif include $(RIOTBASE)/Makefile.base diff --git a/cpu/native/include/native_internal.h b/cpu/native/include/native_internal.h index e51ddead5f6f..cc514c2192ce 100644 --- a/cpu/native/include/native_internal.h +++ b/cpu/native/include/native_internal.h @@ -47,6 +47,7 @@ #include #include #include +#include #include "kernel_types.h" @@ -123,6 +124,7 @@ extern long int (*real_random)(void); extern const char* (*real_gai_strerror)(int errcode); extern FILE* (*real_fopen)(const char *path, const char *mode); extern mode_t (*real_umask)(mode_t cmask); +extern ssize_t (*real_writev)(int fildes, const struct iovec *iov, int iovcnt); #ifdef __MACH__ #else @@ -160,6 +162,7 @@ extern fd_set _native_rfds; ssize_t _native_read(int fd, void *buf, size_t count); ssize_t _native_write(int fd, const void *buf, size_t count); +ssize_t _native_writev(int fildes, const struct iovec *iov, int iovcnt); /** * register interrupt handler handler for interrupt sig diff --git a/cpu/native/include/dev_eth_tap.h b/cpu/native/include/netdev2_tap.h similarity index 60% rename from cpu/native/include/dev_eth_tap.h rename to cpu/native/include/netdev2_tap.h index dcf707a848cd..b8f32e9bc9a4 100644 --- a/cpu/native/include/dev_eth_tap.h +++ b/cpu/native/include/netdev2_tap.h @@ -7,66 +7,67 @@ */ /** - * @defgroup dev_eth_tap Ethernet driver for TAP interfaces - * @ingroup native_cpu + * @ingroup netdev2 * @brief Low-level ethernet driver for native tap interfaces * @{ * * @file - * @brief Definitions for @ref net_dev_eth driver for host system's + * @brief Definitions for @ref netdev2 ethernet driver for host system's * TAP interfaces * * @author Kaspar Schleiser */ -#ifndef DEV_ETH_TAP_H -#define DEV_ETH_TAP_H +#ifndef NETDEV2_TAP_H +#define NETDEV2_TAP_H #ifdef __cplusplus extern "C" { #endif #include -#include "net/dev_eth.h" +#include "net/netdev2.h" -#include "net/if.h" +#include "net/ethernet/hdr.h" #ifdef __MACH__ #include "net/if_var.h" +#else +#include "net/if.h" #endif /** * @brief tap interface state */ -typedef struct dev_eth_tap { - dev_eth_t ethdev; /**< dev_eth internal member */ +typedef struct netdev2_tap { + netdev2_t netdev; /**< netdev2 internal member */ char tap_name[IFNAMSIZ]; /**< host dev file name */ int tap_fd; /**< host file descriptor for the TAP */ uint8_t addr[ETHERNET_ADDR_LEN]; /**< The MAC address of the TAP */ uint8_t promiscous; /**< Flag for promiscous mode */ -} dev_eth_tap_t; +} netdev2_tap_t; /** * @brief global device struct. driver only supports one tap device as of now. */ -extern dev_eth_tap_t dev_eth_tap; +extern netdev2_tap_t netdev2_tap; /** - * @brief Setup dev_eth_tap_t structure. + * @brief Setup netdev2_tap_t structure. * - * @param dev the preallocated dev_eth_tap device handle to setup + * @param dev the preallocated netdev2_tap device handle to setup * @param name Name of the host system's tap inteface to bind to. */ -void dev_eth_tap_setup(dev_eth_tap_t *dev, const char *name); +void netdev2_tap_setup(netdev2_tap_t *dev, const char *name); /** - * @brief Cleanup dev_eth_tap_t structure. + * @brief Cleanup tap resources * - * @param dev the dev_eth_tap device handle to cleanup + * @param dev the netdev2_tap device handle to cleanup */ -void dev_eth_tap_cleanup(dev_eth_tap_t *dev); +void netdev2_tap_cleanup(netdev2_tap_t *dev); #ifdef __cplusplus } #endif /** @} */ -#endif /* DEV_ETH_TAP_H */ +#endif /* NETDEV2_TAP_H */ diff --git a/cpu/native/native_cpu.c b/cpu/native/native_cpu.c index 0c6a9c4acf4e..366bbf002a00 100644 --- a/cpu/native/native_cpu.c +++ b/cpu/native/native_cpu.c @@ -49,9 +49,9 @@ #include "cpu.h" #include "cpu_conf.h" -#ifdef MODULE_DEV_ETH_TAP -#include "dev_eth_tap.h" -extern dev_eth_tap_t dev_eth_tap; +#ifdef MODULE_NETDEV2_TAP +#include "netdev2_tap.h" +extern netdev2_tap_t netdev2_tap; #endif #include "native_internal.h" @@ -75,8 +75,8 @@ int reboot_arch(int mode) /* TODO: close stdio fds */ #endif -#ifdef MODULE_DEV_ETH_TAP - dev_eth_tap_cleanup(&dev_eth_tap); +#ifdef MODULE_NETDEV2_TAP + netdev2_tap_cleanup(&netdev2_tap); #endif if (real_execve(_native_argv[0], _native_argv, NULL) == -1) { diff --git a/cpu/native/dev_eth_tap/Makefile b/cpu/native/netdev2_tap/Makefile similarity index 74% rename from cpu/native/dev_eth_tap/Makefile rename to cpu/native/netdev2_tap/Makefile index 655e12c6908d..7d178b617452 100644 --- a/cpu/native/dev_eth_tap/Makefile +++ b/cpu/native/netdev2_tap/Makefile @@ -1,5 +1,3 @@ -MODULE = dev_eth_tap - include $(RIOTBASE)/Makefile.base INCLUDES = $(NATIVEINCLUDES) diff --git a/cpu/native/dev_eth_tap/dev_eth_tap.c b/cpu/native/netdev2_tap/netdev2_tap.c similarity index 61% rename from cpu/native/dev_eth_tap/dev_eth_tap.c rename to cpu/native/netdev2_tap/netdev2_tap.c index 2cfbb3f9538b..6c25c8c6e06a 100644 --- a/cpu/native/dev_eth_tap/dev_eth_tap.c +++ b/cpu/native/netdev2_tap/netdev2_tap.c @@ -10,12 +10,13 @@ */ /* - * @ingroup net_dev_eth + * @ingroup netdev2 * @{ * @brief Low-level ethernet driver for tap interfaces * @author Kaspar Schleiser * @} */ +#include #include #include #include @@ -47,55 +48,157 @@ #include "native_internal.h" -#include "net/dev_eth.h" -#include "dev_eth_tap.h" +#include "net/eui64.h" +#include "net/netdev2.h" +#include "net/ethernet.h" +#include "net/ethernet/hdr.h" +#include "netdev2_tap.h" +#include "net/netopt.h" +#include "net/eui64.h" -#define ENABLE_DEBUG 0 +#define ENABLE_DEBUG (0) #include "debug.h" /* support one tap interface for now */ -dev_eth_tap_t dev_eth_tap; +netdev2_tap_t netdev2_tap; #ifdef __MACH__ pid_t _sigio_child_pid; -static void _sigio_child(dev_eth_tap_t *dev); +static void _sigio_child(netdev2_tap_t *dev); #endif -/* dev_eth interface */ -static int _init(dev_eth_t *ethdev); -static void _cleanup(dev_eth_t *ethdev); -static int _send(dev_eth_t *ethdev, char* buf, int n); -static int _recv(dev_eth_t *ethdev, char* buf, int n); +/* netdev2 interface */ +static int _init(netdev2_t *netdev); +static int _send(netdev2_t *netdev, const struct iovec *vector, int n); +static int _recv(netdev2_t *netdev, char* buf, int n); -static inline void _get_mac_addr(dev_eth_t *ethdev, uint8_t *dst) { - dev_eth_tap_t *dev = (dev_eth_tap_t*)ethdev; +static inline void _get_mac_addr(netdev2_t *netdev, uint8_t *dst) +{ + netdev2_tap_t *dev = (netdev2_tap_t*)netdev; memcpy(dst, dev->addr, ETHERNET_ADDR_LEN); } -static inline int _get_promiscous(dev_eth_t *ethdev) { - dev_eth_tap_t *dev = (dev_eth_tap_t*)ethdev; +static inline void _set_mac_addr(netdev2_t *netdev, uint8_t *src) +{ + netdev2_tap_t *dev = (netdev2_tap_t*)netdev; + memcpy(dev->addr, src, ETHERNET_ADDR_LEN); +} + +static inline int _get_promiscous(netdev2_t *netdev) +{ + netdev2_tap_t *dev = (netdev2_tap_t*)netdev; return dev->promiscous; } -static inline int _set_promiscous(dev_eth_t *ethdev, int value) { - dev_eth_tap_t *dev = (dev_eth_tap_t*)ethdev; +static inline int _set_promiscous(netdev2_t *netdev, int value) +{ + netdev2_tap_t *dev = (netdev2_tap_t*)netdev; dev->promiscous = value; return value; } -static inline void _isr(dev_eth_t *ethdev) { - dev_eth_rx_handler(ethdev); +static inline int _get_iid(netdev2_t *netdev, eui64_t *value, size_t max_len) +{ + if (max_len < sizeof(eui64_t)) { + return -EOVERFLOW; + } + + uint8_t addr[ETHERNET_ADDR_LEN]; + _get_mac_addr(netdev, addr); + ethernet_get_iid(value, addr); + + return sizeof(eui64_t); +} +static inline void _isr(netdev2_t *netdev) +{ + if (netdev->event_callback) { + netdev->event_callback(netdev, NETDEV2_EVENT_RX_COMPLETE, (void*)NETDEV2_TYPE_ETHERNET); + } +#if DEVELHELP + else { + puts("netdev2_tap: _isr(): no event_callback set."); + } +#endif } -static eth_driver_t eth_driver_tap = { - .init = _init, - .cleanup = _cleanup, +int _get(netdev2_t *dev, netopt_t opt, void *value, size_t max_len) +{ + if (dev != (netdev2_t *)&netdev2_tap) { + return -ENODEV; + } + + int res = 0; + + switch (opt) { + case NETOPT_DEVICE_TYPE: + { + uint16_t *tgt = (uint16_t *)value; + *tgt = NETDEV2_TYPE_ETHERNET; + res = 2; + break; + } + case NETOPT_ADDRESS: + if (max_len < ETHERNET_ADDR_LEN) { + res = -EINVAL; + } + else { + _get_mac_addr(dev, (uint8_t*)value); + res = ETHERNET_ADDR_LEN; + } + break; + case NETOPT_ADDR_LEN: + case NETOPT_SRC_LEN: + assert(max_len == 2); + uint16_t *tgt = (uint16_t*)value; + *tgt=6; + res = sizeof(uint16_t); + break; + case NETOPT_PROMISCUOUSMODE: + *((bool*)value) = (bool)_get_promiscous(dev); + res = sizeof(bool); + break; + case NETOPT_IPV6_IID: + return _get_iid(dev, value, max_len); + default: + res = -ENOTSUP; + break; + } + + return res; +} + +int _set(netdev2_t *dev, netopt_t opt, void *value, size_t value_len) +{ + (void)value_len; + + if (dev != (netdev2_t *)&netdev2_tap) { + return -ENODEV; + } + + int res = 0; + + switch (opt) { + case NETOPT_ADDRESS: + assert(value_len==ETHERNET_ADDR_LEN); + _set_mac_addr(dev, (uint8_t*)value); + break; + case NETOPT_PROMISCUOUSMODE: + _set_promiscous(dev, ((bool *)value)[0]); + break; + default: + return -ENOTSUP; + } + + return res; +} + +static netdev2_driver_t netdev2_driver_tap = { .send = _send, .recv = _recv, - .get_mac_addr = _get_mac_addr, - .get_promiscous = _get_promiscous, - .set_promiscous = _set_promiscous, + .init = _init, .isr = _isr, + .get = _get, + .set = _set, }; /* driver implementation */ @@ -111,18 +214,25 @@ static inline bool _is_addr_multicast(uint8_t *addr) return (addr[0] & 0x01); } -static int _recv(dev_eth_t *dev_eth, char *buf, int len) { - dev_eth_tap_t *dev = (dev_eth_tap_t*)dev_eth; +static int _recv(netdev2_t *netdev2, char *buf, int len) +{ + netdev2_tap_t *dev = (netdev2_tap_t*)netdev2; + + if (!buf) { + /* no way of figuring out packet size without racey buffering, + * so we return the maximum possible size */ + return 576; + } int nread = real_read(dev->tap_fd, buf, len); - DEBUG("gnrc_tapnet: read %d bytes\n", nread); + DEBUG("netdev2_tap: read %d bytes\n", nread); if (nread > 0) { ethernet_hdr_t *hdr = (ethernet_hdr_t *)buf; if (!(dev->promiscous) && !_is_addr_multicast(hdr->dst) && !_is_addr_broadcast(hdr->dst) && (memcmp(hdr->dst, dev->addr, ETHERNET_ADDR_LEN) != 0)) { - DEBUG("gnrc_eth_dev: received for %02x:%02x:%02x:%02x:%02x:%02x\n" + DEBUG("netdev2_tap: received for %02x:%02x:%02x:%02x:%02x:%02x\n" "That's not me => Dropped\n", hdr->dst[0], hdr->dst[1], hdr->dst[2], hdr->dst[3], hdr->dst[4], hdr->dst[5]); @@ -146,7 +256,7 @@ static int _recv(dev_eth_t *dev_eth, char *buf, int len) { extern ssize_t (*real_write)(int fd, const void * buf, size_t count); real_write(_sig_pipefd[1], &sig, sizeof(int)); _native_sigpend++; - DEBUG("dev_eth_tap: sigpend++\n"); + DEBUG("netdev2_tap: sigpend++\n"); } else { #ifdef __MACH__ @@ -162,7 +272,7 @@ static int _recv(dev_eth_t *dev_eth, char *buf, int len) { if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { } else { - err(EXIT_FAILURE, "dev_eth_tap: read"); + err(EXIT_FAILURE, "netdev2_tap: read"); } } else if (nread == 0) { @@ -175,30 +285,33 @@ static int _recv(dev_eth_t *dev_eth, char *buf, int len) { return -1; } -static int _send(dev_eth_t *ethdev, char* buf, int n) { - dev_eth_tap_t *dev = (dev_eth_tap_t*)ethdev; - return _native_write(dev->tap_fd, buf, n); +static int _send(netdev2_t *netdev, const struct iovec *vector, int n) +{ + netdev2_tap_t *dev = (netdev2_tap_t*)netdev; + return _native_writev(dev->tap_fd, vector, n); } -void dev_eth_tap_setup(dev_eth_tap_t *dev, const char *name) { - dev->ethdev.driver = ð_driver_tap; +void netdev2_tap_setup(netdev2_tap_t *dev, const char *name) { + dev->netdev.driver = &netdev2_driver_tap; strncpy(dev->tap_name, name, IFNAMSIZ); } -void dev_eth_tap_cleanup(dev_eth_tap_t *dev) { - if (!dev) { - return; - } - dev_eth_cleanup((dev_eth_t *) dev); -} - static void _tap_isr(void) { - dev_eth_isr(((dev_eth_t *) &dev_eth_tap)); + netdev2_t *netdev = (netdev2_t *)&netdev2_tap; + + if (netdev->event_callback) { + netdev->event_callback(netdev, NETDEV2_EVENT_ISR, netdev->isr_arg); + } + else { + puts("netdev2_tap: _isr: no event callback."); + } } -static int _init(dev_eth_t *ethdev) +static int _init(netdev2_t *netdev) { - dev_eth_tap_t *dev = (dev_eth_tap_t*)ethdev; + DEBUG("%s:%s:%u\n", RIOT_FILE_RELATIVE, __func__, __LINE__); + + netdev2_tap_t *dev = (netdev2_tap_t*)netdev; /* check device parametrs */ if (dev == NULL) { @@ -284,10 +397,8 @@ static int _init(dev_eth_t *ethdev) return 0; } -static void _cleanup(dev_eth_t *ethdev) +void netdev2_tap_cleanup(netdev2_tap_t *dev) { - dev_eth_tap_t *dev = (dev_eth_tap_t*)ethdev; - /* Do we have a device */ if (!dev) { return; @@ -304,7 +415,7 @@ static void _cleanup(dev_eth_t *ethdev) } #ifdef __MACH__ -static void _sigio_child(dev_eth_tap_t *dev) +static void _sigio_child(netdev2_tap_t *dev) { pid_t parent = _native_pid; if ((_sigio_child_pid = real_fork()) == -1) { diff --git a/cpu/native/startup.c b/cpu/native/startup.c index 0d46b540c6f7..b3add71f2618 100644 --- a/cpu/native/startup.c +++ b/cpu/native/startup.c @@ -46,9 +46,9 @@ unsigned _native_rng_seed = 0; int _native_rng_mode = 0; const char *_native_unix_socket_path = NULL; -#ifdef MODULE_DEV_ETH_TAP -#include "dev_eth_tap.h" -extern dev_eth_tap_t dev_eth_tap; +#ifdef MODULE_NETDEV2_TAP +#include "netdev2_tap.h" +extern netdev2_tap_t netdev2_tap; #endif /** @@ -196,7 +196,7 @@ void usage_exit(void) { real_printf("usage: %s", _progname); -#if defined(MODULE_DEV_ETH_TAP) +#if defined(MODULE_NETDEV2_TAP) real_printf(" "); #endif @@ -256,7 +256,7 @@ __attribute__((constructor)) static void startup(int argc, char **argv) int replay = 0; #endif -#if defined(MODULE_DEV_ETH_TAP) +#if defined(MODULE_NETDEV2_TAP) if ( (argc < 2) || ( @@ -367,8 +367,8 @@ __attribute__((constructor)) static void startup(int argc, char **argv) native_cpu_init(); native_interrupt_init(); -#ifdef MODULE_DEV_ETH_TAP - dev_eth_tap_setup(&dev_eth_tap, argv[1]); +#ifdef MODULE_NETDEV2_TAP + netdev2_tap_setup(&netdev2_tap, argv[1]); #endif board_init(); diff --git a/cpu/native/syscalls.c b/cpu/native/syscalls.c index 727d13d66f3e..a2cab09d5ca0 100644 --- a/cpu/native/syscalls.c +++ b/cpu/native/syscalls.c @@ -91,6 +91,7 @@ long int (*real_random)(void); const char* (*real_gai_strerror)(int errcode); FILE* (*real_fopen)(const char *path, const char *mode); mode_t (*real_umask)(mode_t cmask); +ssize_t (*real_writev)(int fildes, const struct iovec *iov, int iovcnt); #ifdef __MACH__ #else @@ -209,6 +210,17 @@ ssize_t _native_write(int fd, const void *buf, size_t count) return r; } +ssize_t _native_writev(int fd, const struct iovec *iov, int iovcnt) +{ + ssize_t r; + + _native_syscall_enter(); + r = real_writev(fd, iov, iovcnt); + _native_syscall_leave(); + + return r; +} + #if defined(__FreeBSD__) #undef putchar #endif @@ -424,6 +436,7 @@ void _native_init_syscalls(void) *(void **)(&real_ferror) = dlsym(RTLD_NEXT, "ferror"); *(void **)(&real_clearerr) = dlsym(RTLD_NEXT, "clearerr"); *(void **)(&real_umask) = dlsym(RTLD_NEXT, "umask"); + *(void **)(&real_writev) = dlsym(RTLD_NEXT, "writev"); #ifdef __MACH__ #else *(void **)(&real_clock_gettime) = dlsym(RTLD_NEXT, "clock_gettime"); diff --git a/sys/Makefile b/sys/Makefile index c25602c6374b..2a30486950f0 100644 --- a/sys/Makefile +++ b/sys/Makefile @@ -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 diff --git a/sys/auto_init/Makefile b/sys/auto_init/Makefile index 94641a8e4af1..a72b05b9eedc 100644 --- a/sys/auto_init/Makefile +++ b/sys/auto_init/Makefile @@ -4,8 +4,4 @@ ifneq (,$(filter auto_init_gnrc_netif,$(USEMODULE))) DIRS += netif endif -ifneq (,$(filter dev_eth_autoinit,$(USEMODULE))) -DIRS += $(RIOTBASE)/sys/auto_init/dev_eth -endif - include $(RIOTBASE)/Makefile.base diff --git a/sys/auto_init/auto_init.c b/sys/auto_init/auto_init.c index a4b0641ef79f..32692045fd64 100644 --- a/sys/auto_init/auto_init.c +++ b/sys/auto_init/auto_init.c @@ -84,9 +84,8 @@ #include "net/gnrc/udp.h" #endif -#ifdef MODULE_DEV_ETH_AUTOINIT -#include "net/dev_eth.h" -#include "dev_eth_autoinit.h" +#ifdef MODULE_FIB +#include "net/fib.h" #endif #define ENABLE_DEBUG (0) @@ -182,9 +181,9 @@ void auto_init(void) auto_init_kw2xrf(); #endif -#ifdef MODULE_GNRC_NETDEV_ETH - extern void auto_init_gnrc_netdev_eth(void); - auto_init_gnrc_netdev_eth(); +#ifdef MODULE_NETDEV2_TAP + extern void auto_init_netdev2_tap(void); + auto_init_netdev2_tap(); #endif #endif /* MODULE_AUTO_INIT_GNRC_NETIF */ diff --git a/sys/auto_init/dev_eth/Makefile b/sys/auto_init/dev_eth/Makefile deleted file mode 100644 index 347f229678e4..000000000000 --- a/sys/auto_init/dev_eth/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -MODULE = dev_eth_autoinit - -include $(RIOTBASE)/Makefile.base diff --git a/sys/auto_init/dev_eth/dev_eth_autoinit.c b/sys/auto_init/dev_eth/dev_eth_autoinit.c deleted file mode 100644 index b4b290b72fa7..000000000000 --- a/sys/auto_init/dev_eth/dev_eth_autoinit.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2015 Kaspar Schleiser - * - * 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 "net/dev_eth.h" -#include "dev_eth_autoinit.h" - -#ifdef MODULE_DEV_ETH_TAP -#include "dev_eth_tap.h" -#endif - -#ifdef MODULE_ENCX24J600 -#include "encx24j600.h" -encx24j600_t dev_eth_encx24j600; -#endif - -dev_eth_t * const dev_eth_devices[] = { -#ifdef MODULE_DEV_ETH_TAP - [DEV_ETH_TAP] = (dev_eth_t*)&dev_eth_tap, -#endif -#ifdef MODULE_ENCX24J600 - [DEV_ETH_ENCX24J600] = (dev_eth_t*)&dev_eth_encx24j600, -#endif -}; - -void dev_eth_autoinit(void) -{ -#ifdef MODULE_ENCX24J600 - /* TODO: use sensible defines */ - encx24j600_setup(&dev_eth_encx24j600, SPI_0, GPIO_1, GPIO_2); -#endif -} diff --git a/sys/auto_init/netif/auto_init_gnrc_netdev_eth.c b/sys/auto_init/netif/auto_init_gnrc_netdev_eth.c deleted file mode 100644 index b713c3329aed..000000000000 --- a/sys/auto_init/netif/auto_init_gnrc_netdev_eth.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2015 Kaspar Schleiser - * - * 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 auto_init_gnrc_netif - * @{ - * - * @file - * @brief Auto initialization for netdev Ethernet network interfaces - * - * @author Kaspar Schleiser - * @author Oliver Hahm - */ - -#ifdef MODULE_GNRC_NETDEV_ETH - -#include "board.h" -#include "net/gnrc/nomac.h" -#include "net/gnrc.h" - -#include "net/gnrc/netdev_eth.h" -#include "net/dev_eth.h" -#include "dev_eth_tap.h" - -#define ENABLE_DEBUG (0) -#include "debug.h" - -/** - * @brief Define stack parameters for the MAC layer thread - * @{ - */ -#define NETDEV_ETH_MAC_STACKSIZE (THREAD_STACKSIZE_DEFAULT) -#define NETDEV_ETH_MAC_PRIO (THREAD_PRIORITY_MAIN - 4) - -static char _nomac_stack[NETDEV_ETH_MAC_STACKSIZE]; - -void auto_init_gnrc_netdev_eth(void) -{ - DEBUG("Initializing NETDEV_ETH device\n"); - int res = gnrc_netdev_eth_init(&gnrc_netdev_eth, (dev_eth_t*)&dev_eth_tap); - - if (res < 0) { - DEBUG("Error initializing NETDEV_ETH device!"); - } - else { - gnrc_nomac_init(_nomac_stack, NETDEV_ETH_MAC_STACKSIZE, NETDEV_ETH_MAC_PRIO, - "tapnet", (gnrc_netdev_t *)&gnrc_netdev_eth); - } -} -#else -typedef int dont_be_pedantic; -#endif /* MODULE_GNRC_NETDEV_ETH */ - -/** @} */ diff --git a/sys/auto_init/netif/auto_init_netdev2_tap.c b/sys/auto_init/netif/auto_init_netdev2_tap.c new file mode 100644 index 000000000000..a6e02c67dc78 --- /dev/null +++ b/sys/auto_init/netif/auto_init_netdev2_tap.c @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2015 Kaspar Schleiser + * + * 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 auto_init_ng_netif + * @{ + * + * @file + * @brief Auto initialization for ethernet devices + * + * @author Kaspar Schleiser + */ + +#ifdef MODULE_NETDEV2_TAP + +#define ENABLE_DEBUG (1) +#include "debug.h" + +#include "netdev2_tap.h" +#include "net/gnrc/gnrc_netdev2_eth.h" + +extern netdev2_tap_t netdev2_tap; + +/** + * @brief Define stack parameters for the MAC layer thread + * @{ + */ +#define TAP_MAC_STACKSIZE (THREAD_STACKSIZE_DEFAULT + DEBUG_EXTRA_STACKSIZE) +#define TAP_MAC_PRIO (THREAD_PRIORITY_MAIN - 3) + +/** + * @brief Stacks for the MAC layer threads + */ +static char _netdev2_eth_stack[TAP_MAC_STACKSIZE + DEBUG_EXTRA_STACKSIZE]; +static gnrc_netdev2_t _gnrc_netdev2_tap; + +void auto_init_netdev2_tap(void) +{ + gnrc_netdev2_eth_init(&_gnrc_netdev2_tap, (netdev2_t*)&netdev2_tap); + + gnrc_netdev2_init(_netdev2_eth_stack, TAP_MAC_STACKSIZE, + TAP_MAC_PRIO, "gnrc_netdev2_tap", &_gnrc_netdev2_tap); +} + +#else +typedef int dont_be_pedantic; +#endif /* MODULE_NETDEV2_TAP */ +/** @} */ diff --git a/sys/include/dev_eth_autoinit.h b/sys/include/dev_eth_autoinit.h deleted file mode 100644 index a8d393be87b9..000000000000 --- a/sys/include/dev_eth_autoinit.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2015 Kaspar Schleiser - * - * 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 sys_net_dev_eth dev_eth auto setup - * @ingroup net_ethernet - * @file - * @brief Automatically setup available ethernet devices - * @{ - * - * @brief header for dev_eth automatic initialization - * - * @author Kaspar Schleiser - */ - -#ifndef DEV_ETH_AUTOINIT_H -#define DEV_ETH_AUTOINIT_H - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief enum for available ethernet devices - */ -enum { -#ifdef MODULE_DEV_ETH_TAP - DEV_ETH_TAP, -#endif -#ifdef MODULE_ENCX24J600 - DEV_ETH_ENCX24J600, -#endif - /* must be last: */ - NUM_DEV_ETH -}; - -/** - * @brief Array of const pointers to available ethernet devices - */ -extern dev_eth_t *const dev_eth_devices[]; - -/** - * @brief Automatically sets up available dev_eth ethernet devices - * - * ... by calling the respective *_setup() functions if available. - */ -void dev_eth_autoinit(void); - -#ifdef __cplusplus -} -#endif -/** @} */ -#endif /* DEV_ETH_AUTOINIT_H */ diff --git a/sys/include/net/dev_eth.h b/sys/include/net/dev_eth.h deleted file mode 100644 index 487d6e750a80..000000000000 --- a/sys/include/net/dev_eth.h +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (C) 2015 Kaspar Schleiser - * Ell-i open source co-operative - * - * 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_dev_eth Low-Level Driver Interface - * @ingroup net_ethernet - * @brief Low-level ethernet driver interface - * - * This interface is supposed to be a low-level interface for ethernet drivers. - * In order to be universally usable, it leaves out many implementation details - * to the implementation of an actual network stack using this interface. - * - * In order to write a driver for this interface, you have to - * - * 1. create a (possibly const) eth_driver_t structure for your device type, - * implement it's functions - * - * 2. create a dev_eth_t structure, used as device state and handle, for each device - * - * In order to use this interface, you have to - * - * 1. implement dev_eth_isr, dev_eth_rx_handler and dev_eth_linkstate_handler - * 2. run a loop that get's notified by dev_eth_isr - * - * A devices send function should always be able to send a frame (and make sure of proper locking). - * - * Receive packet flow: - * - * 1. Ethernet driver receives packet, executes driver's internal ISR. - * 2. driver's internal ISR should do minimal acknowledging and house keeping and then - * call dev_eth_isr - * 3. dev_eth_isr should notify a user of this API (e.g., the network stack's L2 thread) - * 4. That thread executes the driver's user-space isr (dev->driver->isr) - * 5. user space ISR handles less timing critical stuff, eventually calling - * dev_eth_linkstate_handler and / or dev_eth_rx_handler - * - * Check out the dev_eth test application as example. - * - * @{ - * - * @file - * @brief Definitions low-level ethernet driver interface - * - * @author Kaspar Schleiser - */ - -#ifndef DEV_ETH_H -#define DEV_ETH_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include "ethernet/hdr.h" - -/** - * @brief Structure to hold driver state - * - * Supposed to be extended by driver implementations. - * The extended structure should contain all variable driver state. - */ -typedef struct dev_eth { - const struct eth_driver *driver; /**< ptr to that driver's interface. - driver->init() expects this to be present, - so set this before using the device. */ -} dev_eth_t; - -/** - * @brief Structure to hold driver interface -> function mapping - * - * The send/receive functions expect/return a full ethernet - * frame (dst mac, src mac, ethertype, payload, no checksum). - */ -typedef struct eth_driver { - /** - * @brief Send ethernet frame - * - * Expects a full ethernet frame (dst mac, src mac, ethertype, payload, - * no checksum). - * - * @param buf buffer to read from - * @param len nr of bytes to send - * - * @return nr of bytes sent, or <=0 on error - */ - int (*send)(dev_eth_t *dev, char* buf, int len); - - /** - * @brief Get a received ethernet frame - * - * Supposed to be called from dev_eth_rx_handler(). - * - * Make sure buf can hold the maximum expected ethernet frame size. - * - * @param buf buffer to write to - * @param len maximum nr. of bytes to read - * - * @return nr of bytes read or <=0 on error - */ - int (*recv)(dev_eth_t *dev, char* buf, int len); - - /** - * @brief get the device's MAC address - * - * @param buf location to write to. Make sure this is can take least 6 bytes - */ - void (*get_mac_addr)(dev_eth_t *dev, uint8_t *buf); - - /** - * @brief get the device's promiscous status - * - * Default is not promiscous. - * Promiscous means, receive all ethernet frames. - * Not promiscous means only receive broadcast, multicast or frames with - * the device's MAC address as dst address. - * - * @return 1 for promiscous, 0 for not promiscous - */ - int (*get_promiscous)(dev_eth_t *dev); - /** - * @brief set the devices promiscous mode - * - * @param value 1 for promiscous, 0 for not promiscous - * @return the new value (device might not support wanted mode) - */ - int (*set_promiscous)(dev_eth_t *dev, int value); - /** - * @brief the driver's initialization function - * - * @return <=0 on error, >0 on success - */ - int (*init)(dev_eth_t *dev); - /** - * @brief the driver's cleanup function (optional) - */ - void (*cleanup)(dev_eth_t *dev); - /** - * @brief a driver's user-space ISR handler - * - * This function will be called from a network stack's loop when being notified - * by dev_eth_isr. - * - * It is supposed to call dev_eth_rx_handler for each available received packed, - * and dev_eth_linkstate_handler whenever a link state change event occurs. - * - * See receive packet flow description for details. - */ - void (*isr)(dev_eth_t *dev); -} eth_driver_t; - -/** - * @brief Initialize a device given by dev (convenience function) - * - * The device given as parameter *must* be previously setup by the - * drivers *_setup() function. - * - */ -static inline int dev_eth_init(dev_eth_t *dev) { - return dev->driver->init(dev); -} - -/** - * @brief Cleanup a device given by dev (convenience function) - * - * This function is to be called on reboot if the init function is not - * idempotent. - * - */ -static inline void dev_eth_cleanup(dev_eth_t *dev) { - if (dev->driver->cleanup) { - dev->driver->cleanup(dev); - } -} - -/** - * @brief global dev_eth interrupt handling function. - * - * This function should be called from your device's ISR from whithin ISR context. - * It is supposed to wake up a waiting user-space event loop. - */ -extern void dev_eth_isr(dev_eth_t *dev); - -/** - * @brief dev_eth event callback for packets that were received. - * - * This function should be called from whithin your driver's isr() - * (as defined in eth_driver_t), once for every packet that was received. - * - * It needs to call dev->driver->recv() in order to get received packet - * from the driver. - */ -extern void dev_eth_rx_handler(dev_eth_t *dev); - -/** - * @brief dev_eth ethernet link state handler - * - * This function should be called from whithin your driver's isr() - * (as defined in eth_driver_t) for every layer 2 link state change. - * - * @param dev device that triggered the event - * @param newstate 1 for "link established", 0 for "link down" - */ -extern void dev_eth_linkstate_handler(dev_eth_t *dev, int newstate); - -#ifdef __cplusplus -} -#endif -/** @} */ -#endif /* DEV_ETH_H */ diff --git a/sys/include/net/gnrc/gnrc_netdev2.h b/sys/include/net/gnrc/gnrc_netdev2.h new file mode 100644 index 000000000000..f0b388f8d06f --- /dev/null +++ b/sys/include/net/gnrc/gnrc_netdev2.h @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2015 Kaspar Schleiser + * + * 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 + */ + +#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 */ +/** @} */ diff --git a/sys/include/net/gnrc/gnrc_netdev2_eth.h b/sys/include/net/gnrc/gnrc_netdev2_eth.h new file mode 100644 index 000000000000..d14b4930c888 --- /dev/null +++ b/sys/include/net/gnrc/gnrc_netdev2_eth.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2015 Kaspar Schleiser + * + * 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 + */ + +#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 */ +/** @} */ diff --git a/sys/include/net/netopt.h b/sys/include/net/netopt.h index 21ba41dab954..ef9193128e77 100644 --- a/sys/include/net/netopt.h +++ b/sys/include/net/netopt.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 */ /** diff --git a/sys/net/crosslayer/netopt/netopt.c b/sys/net/crosslayer/netopt/netopt.c index 0841fe4a95ba..0106a3ce6073 100644 --- a/sys/net/crosslayer/netopt/netopt.c +++ b/sys/net/crosslayer/netopt/netopt.c @@ -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", }; diff --git a/sys/net/gnrc/link_layer/netdev_eth/Makefile b/sys/net/gnrc/link_layer/netdev2/Makefile similarity index 58% rename from sys/net/gnrc/link_layer/netdev_eth/Makefile rename to sys/net/gnrc/link_layer/netdev2/Makefile index 22db6eb87572..2cfcb37ec91e 100644 --- a/sys/net/gnrc/link_layer/netdev_eth/Makefile +++ b/sys/net/gnrc/link_layer/netdev2/Makefile @@ -1,3 +1,3 @@ -MODULE = gnrc_netdev_eth +MODULE = gnrc_netdev2 include $(RIOTBASE)/Makefile.base diff --git a/sys/net/gnrc/link_layer/netdev2/gnrc_netdev2.c b/sys/net/gnrc/link_layer/netdev2/gnrc_netdev2.c new file mode 100644 index 000000000000..320079cc37f6 --- /dev/null +++ b/sys/net/gnrc/link_layer/netdev2/gnrc_netdev2.c @@ -0,0 +1,209 @@ +/* + * Copyright (C) 2015 Freie Universität Berlin + * 2015 Kaspar Schleiser + * + * 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 + * @author Kaspar Schleiser + * @} + */ + +#include + +#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; +} diff --git a/sys/net/gnrc/link_layer/netdev2/gnrc_netdev2_eth.c b/sys/net/gnrc/link_layer/netdev2/gnrc_netdev2_eth.c new file mode 100644 index 000000000000..e63c09283c3a --- /dev/null +++ b/sys/net/gnrc/link_layer/netdev2/gnrc_netdev2_eth.c @@ -0,0 +1,207 @@ +/* + * Copyright (C) 2015 Kaspar Schleiser + * + * 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 + * @} + */ + +#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; +} diff --git a/sys/net/gnrc/link_layer/netdev_eth/gnrc_netdev_eth.c b/sys/net/gnrc/link_layer/netdev_eth/gnrc_netdev_eth.c deleted file mode 100644 index 2772c329b974..000000000000 --- a/sys/net/gnrc/link_layer/netdev_eth/gnrc_netdev_eth.c +++ /dev/null @@ -1,581 +0,0 @@ -/* - * Copyright (C) 2015 Ludwig Ortmann , - * Martine Lenders - * Kaspar Schleiser - * - * - * 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 sys_net_link_layer - * @{ - * - * @file - * - * @author Ludwig Ortmann - * @author Martine Lenders - * @author Kaspar Schleiser - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "byteorder.h" -#include "net/eui64.h" -#include "net/ethernet.h" -#include "net/ethertype.h" -#include "net/ipv6/hdr.h" -#include "net/gnrc/netdev.h" -#include "net/gnrc/netif/hdr.h" -#include "net/gnrc/pkt.h" -#include "net/gnrc/pktbuf.h" -#include "net/gnrc/netdev_eth.h" -#include "net/dev_eth.h" -#include "od.h" -#include "thread.h" -#include "utlist.h" - -#define ENABLE_DEBUG (0) -#include "debug.h" - -gnrc_netdev_eth_t gnrc_netdev_eth; - -static uint8_t send_buffer[ETHERNET_MAX_LEN]; -static uint8_t recv_buffer[ETHERNET_MAX_LEN]; - -#define _ISR_EVENT_RX (1U) - -/* driver function definitions */ -static int _send_data(gnrc_netdev_t *netdev, gnrc_pktsnip_t *pkt); -static int _add_event_callback(gnrc_netdev_t *dev, gnrc_netdev_event_cb_t cb); -static int _rem_event_callback(gnrc_netdev_t *dev, gnrc_netdev_event_cb_t cb); -static int _get(gnrc_netdev_t *dev, netopt_t opt, void *value, size_t max_len); -static int _set(gnrc_netdev_t *dev, netopt_t opt, void *value, size_t value_len); -static void _isr_event(gnrc_netdev_t *dev, uint32_t event_type); - -/* netdev driver struct */ -const gnrc_netdev_driver_t gnrc_netdev_eth_driver = { - _send_data, - _add_event_callback, - _rem_event_callback, - _get, - _set, - _isr_event, -}; - -/* These functions are not used */ -#if !(defined(__FreeBSD__) || defined(__MACH__)) -/* internal function definitions */ -static inline bool _is_addr_broadcast(uint8_t *addr) -{ - return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) && - (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff)); -} - -static inline bool _is_addr_multicast(uint8_t *addr) -{ - /* source: http://ieee802.org/secmail/pdfocSP2xXA6d.pdf */ - return (addr[0] & 0x01); -} -#endif /* !(defined(__FreeBSD__) || defined(__MACH__)) */ - - -/* build Ethernet packet from pkt */ -static int _marshall_ethernet(gnrc_netdev_eth_t *dev, uint8_t *buffer, gnrc_pktsnip_t *pkt); - -/* build ISR handler for ISR events */ -void _trigger_isr_event(void); - -static int _send_data(gnrc_netdev_t *netdev, gnrc_pktsnip_t *pkt) -{ - int nsent, to_send; - gnrc_netdev_eth_t *dev = (gnrc_netdev_eth_t *)netdev; - - DEBUG("gnrc_netdev_eth: send data "); - - if (pkt == NULL) { - return -EFAULT; - } - - if ((dev == NULL) || (netdev->driver != &gnrc_netdev_eth_driver)) { - DEBUG("[wrong device descriptor]\n"); - gnrc_pktbuf_release(pkt); - return -ENODEV; - } - - DEBUG("\n"); - - to_send = _marshall_ethernet(dev, send_buffer, pkt); - gnrc_pktbuf_release(pkt); - - if (to_send < 0) { - errno = -to_send; - DEBUG("marshall\n"); - return to_send; - } - - DEBUG("gnrc_netdev_eth: send %d bytes\n", to_send); -#if defined(MODULE_OD) && ENABLE_DEBUG - od_hex_dump(send_buffer, to_send, OD_WIDTH_DEFAULT); -#endif - - dev_eth_t *ethdev = dev->ethdev; - if ((nsent = ethdev->driver->send(ethdev, (char*)send_buffer, to_send)) < 0) { - DEBUG("write\n"); - return -EIO; - } - - return nsent; -} - -static int _add_event_callback(gnrc_netdev_t *dev, gnrc_netdev_event_cb_t cb) -{ - DEBUG("gnrc_netdev_eth: add event callback"); - - if ((dev == NULL) || (dev->driver != &gnrc_netdev_eth_driver)) { - DEBUG(" [wrong device descriptor]\n"); - return -ENODEV; - } - - if (dev->event_cb != NULL) { - DEBUG(" [no space left]\n"); - return -ENOBUFS; - } - - DEBUG("\n"); - dev->event_cb = cb; - - return 0; -} - -static int _rem_event_callback(gnrc_netdev_t *dev, gnrc_netdev_event_cb_t cb) -{ - DEBUG("gnrc_netdev_eth: remove event callback"); - - if ((dev == NULL) || (dev->driver != &gnrc_netdev_eth_driver)) { - DEBUG(" [wrong device descriptor]\n"); - return -ENODEV; - } - - if (dev->event_cb != cb) { - DEBUG(" [not found]\n"); - return -ENOENT; - } - - DEBUG("\n"); - dev->event_cb = NULL; - - return 0; -} - -/* individual option getters to be called by _get() */ -static inline int _get_addr(gnrc_netdev_eth_t *netdev, uint8_t *value, size_t max_len) -{ - if (max_len < ETHERNET_ADDR_LEN) { - /* value buffer not big enough */ - return -EOVERFLOW; - } - - dev_eth_t *dev = netdev->ethdev; - dev->driver->get_mac_addr(dev, value); - - return ETHERNET_ADDR_LEN; -} - -static inline int _get_addr_len(uint16_t *value, size_t max_len) -{ - if (max_len != sizeof(uint16_t)) { - /* value buffer not big enough */ - return -EOVERFLOW; - } - - *value = ETHERNET_ADDR_LEN; - - return sizeof(uint16_t); -} - -static inline int _get_iid(gnrc_netdev_eth_t *netdev, eui64_t *value, size_t max_len) -{ - if (max_len < sizeof(eui64_t)) { - /* value buffer not big enough */ - return -EOVERFLOW; - } - - dev_eth_t *dev = netdev->ethdev; - uint8_t addr[ETHERNET_ADDR_LEN]; - dev->driver->get_mac_addr(dev, addr); - ethernet_get_iid(value, addr); - - return sizeof(eui64_t); -} - -static inline int _get_max_pkt_sz(uint16_t *value, size_t max_len) -{ - if (max_len != sizeof(uint16_t)) { - /* value buffer not big enough */ - return -EOVERFLOW; - } - - *value = ETHERNET_DATA_LEN; - - return sizeof(uint16_t); -} - -static inline int _get_promiscousmode(gnrc_netdev_eth_t *netdev, netopt_enable_t *value, - size_t max_len) -{ - if (max_len != sizeof(netopt_enable_t)) { - /* value buffer not big enough */ - return -EOVERFLOW; - } - - - dev_eth_t *dev = netdev->ethdev; - *value = (netopt_enable_t)dev->driver->get_promiscous(dev); - - return sizeof(netopt_enable_t); -} - -static int _get(gnrc_netdev_t *dev, netopt_t opt, void *value, size_t max_len) -{ - DEBUG("gnrc_netdev_eth: get "); - - if ((dev == NULL) || (dev->driver != &gnrc_netdev_eth_driver)) { - DEBUG("[wrong device descriptor]\n"); - return -ENODEV; - } - - switch (opt) { - case NETOPT_ADDRESS: - DEBUG("address\n"); - return _get_addr((gnrc_netdev_eth_t *)dev, value, max_len); - - case NETOPT_ADDR_LEN: - DEBUG("address length\n"); - return _get_addr_len(value, max_len); - - case NETOPT_IPV6_IID: - DEBUG("IPv6 IID\n"); - return _get_iid((gnrc_netdev_eth_t *)dev, value, max_len); - - case NETOPT_MAX_PACKET_SIZE: - DEBUG("maximum packet size\n"); - return _get_max_pkt_sz(value, max_len); - - case NETOPT_PROMISCUOUSMODE: - DEBUG("promiscous mode\n"); - return _get_promiscousmode((gnrc_netdev_eth_t *)dev, value, max_len); - - case NETOPT_IS_WIRED: - DEBUG("is wired\n"); - return 1; - - default: - DEBUG("[not supported: %d]\n", opt); - return -ENOTSUP; - } -} - -/* individual option getters to be called by _get() */ -static inline int _set_promiscousmode(gnrc_netdev_eth_t *netdev, netopt_enable_t *value, - size_t value_len) -{ - if (value_len != sizeof(netopt_enable_t)) { - /* value buffer not big enough */ - return -EOVERFLOW; - } - - dev_eth_t *dev = netdev->ethdev; - - dev->driver->set_promiscous(dev, (uint8_t)*value); - - return sizeof(netopt_enable_t); -} - -static int _set(gnrc_netdev_t *dev, netopt_t opt, void *value, size_t value_len) -{ - DEBUG("gnrc_netdev_eth: set "); - - if ((dev == NULL) || (dev->driver != &gnrc_netdev_eth_driver)) { - DEBUG("[wrong device descriptor]\n"); - return -ENODEV; - } - - switch (opt) { - case NETOPT_PROMISCUOUSMODE: - DEBUG("promiscous mode\n"); - return _set_promiscousmode((gnrc_netdev_eth_t *)dev, value, value_len); - - default: - DEBUG("[not supported: %d]\n", opt); - return -ENOTSUP; - } -} - -/* individual event handlers called by _isr_event() */ -static void _rx_event(gnrc_netdev_eth_t *dev); - -static void _isr_event(gnrc_netdev_t *dev, uint32_t event_type) -{ - DEBUG("gnrc_netdev_eth: ISR event "); - - if ((dev == NULL) || (dev->driver != &gnrc_netdev_eth_driver)) { - return; - } - - gnrc_netdev_eth_t *netdev = (gnrc_netdev_eth_t*)dev; - - switch (event_type) { - case _ISR_EVENT_RX: - - DEBUG("[ISR]\n"); - -#ifdef NETDEV_ETH_DELAY_SEND - DEBUG("netdev_eth: delaying send...\n"); - volatile int i = NETDEV_ETH_DELAY_SEND; - while(i--); - DEBUG("netdev_eth: delay done.\n"); -#endif - - dev_eth_t *ethdev = netdev->ethdev; - ethdev->driver->isr(ethdev); - break; - - default: - DEBUG("[unknown event_type]\n"); - break; - } -} - -static inline void _addr_set_broadcast(uint8_t *dst) -{ - memset(dst, 0xff, ETHERNET_ADDR_LEN); -} - -static inline void _addr_set_multicast(uint8_t *dst, gnrc_pktsnip_t *payload) -{ - switch (payload->type) { -#ifdef MODULE_GNRC_IPV6 - case GNRC_NETTYPE_IPV6: - dst[0] = 0x33; - dst[1] = 0x33; - if (payload->data != NULL) { - ipv6_hdr_t *hdr = payload->data; - uint16_t *prefix = (uint16_t *)(&dst[2]); - prefix[0] = hdr->dst.u16[6].u16; - prefix[1] = hdr->dst.u16[7].u16; - } - break; -#endif - default: - _addr_set_broadcast(dst); - break; - } -} - -static int _marshall_ethernet(gnrc_netdev_eth_t *dev, uint8_t *buffer, gnrc_pktsnip_t *pkt) -{ - int data_len = 0; - ethernet_hdr_t *hdr = (ethernet_hdr_t *)buffer; - gnrc_netif_hdr_t *netif_hdr; - gnrc_pktsnip_t *payload; - - if (pkt == NULL) { - DEBUG("gnrc_netdev_eth: pkt was NULL"); - return -EINVAL; - } - - payload = pkt->next; - - if (pkt->type != GNRC_NETTYPE_NETIF) { - DEBUG("gnrc_netdev_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_eth_t *ethdev = dev->ethdev; - ethdev->driver->get_mac_addr(ethdev, hdr->src); - } - - if (netif_hdr->flags & GNRC_NETIF_HDR_FLAGS_BROADCAST) { - _addr_set_broadcast(hdr->dst); - } - else if (netif_hdr->flags & GNRC_NETIF_HDR_FLAGS_MULTICAST) { - if (payload == NULL) { - DEBUG("gnrc_netdev_eth: empty multicast packets over Ethernet are "\ - "not yet supported\n"); - return -ENOTSUP; - - } - _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_netdev_eth: destination address had unexpected format\n"); - return -EBADMSG; - } - - DEBUG("gnrc_netdev_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]); - - data_len += sizeof(ethernet_hdr_t); - - while (payload != NULL) { - if ((data_len + payload->size) > ETHERNET_MAX_LEN) { - DEBUG("gnrc_netdev_eth: Packet too big for ethernet frame\n"); - return -ENOBUFS; - } - - memcpy(send_buffer + data_len, payload->data, payload->size); - - data_len += payload->size; - payload = payload->next; - } - - /* Pad to minimum payload size. - * 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 < (ETHERNET_MIN_LEN)) { - DEBUG("gnrc_netdev_eth: padding data! (%d -> ", data_len); - memset(send_buffer + data_len, 0, ETHERNET_MIN_LEN - data_len); - data_len = ETHERNET_MIN_LEN; - DEBUG("%d)\n", data_len); - } - - return data_len; -} - -void dev_eth_isr(dev_eth_t* dev) -{ - (void)dev; - msg_t msg; - - DEBUG("gnrc_netdev_eth: Trigger ISR event\n"); - - /* TODO: check whether this is an input or an output event - TODO: refactor this into general io-signal multiplexer */ - - msg.type = GNRC_NETDEV_MSG_TYPE_EVENT; - msg.content.value = _ISR_EVENT_RX; - - if (msg_send(&msg, gnrc_netdev_eth.mac_pid) <= 0) { - puts("dev_eth_isr: possibly lost interrupt."); - } -} - -void dev_eth_rx_handler(dev_eth_t* dev) { - (void)dev; - _rx_event(&gnrc_netdev_eth); -} - -void dev_eth_linkstate_handler(dev_eth_t *dev, int newstate) -{ - DEBUG("gnrc_dev_eth: dev=0x%08x link %s\n", (unsigned)dev, newstate ? "UP" : "DOWN"); - (void)dev; (void)newstate; -} - -static void _rx_event(gnrc_netdev_eth_t *netdev) -{ - dev_eth_t *dev = netdev->ethdev; - int nread = dev->driver->recv(dev, (char*)recv_buffer, ETHERNET_MAX_LEN); - - DEBUG("gnrc_netdev_eth: read %d bytes\n", nread); - - if (nread > 0) { - ethernet_hdr_t *hdr = (ethernet_hdr_t *)recv_buffer; - gnrc_pktsnip_t *netif_hdr, *pkt; - gnrc_nettype_t receive_type = GNRC_NETTYPE_UNDEF; - size_t data_len = (nread - sizeof(ethernet_hdr_t)); - - /* TODO: implement multicast groups? */ - - 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_netdev_eth: no space left in packet buffer\n"); - return; - } - - 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(); - - receive_type = gnrc_nettype_from_ethertype(byteorder_ntohs(hdr->type)); - - DEBUG("gnrc_netdev_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], data_len); -#if defined(MODULE_OD) && ENABLE_DEBUG - od_hex_dump(hdr, nread, OD_WIDTH_DEFAULT); -#endif - - /* Mark netif header and payload for next layer */ - if ((pkt = gnrc_pktbuf_add(netif_hdr, recv_buffer + sizeof(ethernet_hdr_t), - data_len, receive_type)) == NULL) { - gnrc_pktbuf_release(netif_hdr); - DEBUG("gnrc_netdev_eth: no space left in packet buffer\n"); - return; - } - - if (netdev->event_cb != NULL) { - netdev->event_cb(NETDEV_EVENT_RX_COMPLETE, pkt); - } - else { - gnrc_pktbuf_release(pkt); /* netif_hdr is released automatically too */ - } - } - else { - DEBUG("gnrc_netdev_eth: spurious _rx_event: %d\n", nread); - } -} - -int gnrc_netdev_eth_init(gnrc_netdev_eth_t *netdev, dev_eth_t *ethdev) -{ - if ((netdev == NULL) || (ethdev == NULL) || (netdev != &gnrc_netdev_eth)) { - return -ENODEV; - } - - /* initialize low-level driver */ - dev_eth_init(ethdev); - - /* initialize device descriptor */ - netdev->driver = (gnrc_netdev_driver_t *)(&gnrc_netdev_eth_driver); - netdev->ethdev = ethdev; - - DEBUG("gnrc_netdev_eth: initialized.\n"); - - return 0; -} -/** - * @} - */ diff --git a/tests/dev_eth/Makefile b/tests/dev_eth/Makefile deleted file mode 100644 index ac9ca51a9a29..000000000000 --- a/tests/dev_eth/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -APPLICATION = dev_eth -include ../Makefile.tests_common - -BOARD_WHITELIST = native -FEATURES_REQUIRED += ethernet - -ifneq (,$(filter native,$(BOARD))) -USEMODULE += dev_eth_tap -endif - -USEMODULE += dev_eth_autoinit - -include $(RIOTBASE)/Makefile.include diff --git a/tests/dev_eth/main.c b/tests/dev_eth/main.c deleted file mode 100644 index ac59b67594fa..000000000000 --- a/tests/dev_eth/main.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2015 Kaspar Schleiser - * Ell-i open source co-operative - * - * 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 tests - * @{ - * - * @file - * @brief Test application for dev_eth low level ethernet drivers - * - * This test application will bounce back every received l2 ethernet - * frame by exchanging target and destination MAC addresses. - * - * @author Kaspar Schleiser - * - * @} - */ - -#include -#include - -#include "thread.h" -#include "board.h" -#include "vtimer.h" -#include "periph/spi.h" -#include "periph/gpio.h" - -#include "net/dev_eth.h" -#include "dev_eth_autoinit.h" - -#define ENABLE_DEBUG 0 -#include "debug.h" - -kernel_pid_t handler_pid = KERNEL_PID_UNDEF; - -char _rxbuf[2000]; - -/* reverse src/dst addresses in raw ethernet packet */ -void turn_packet(char *pkt) { - uint8_t mac[6]; - /* save old dst addr */ - memcpy(mac, pkt, 6); - - /* use sender MAC address as new destination */ - memcpy(pkt, pkt+6, 6); - - /* set our MAC address as sender */ - memcpy(pkt+6, mac, 6); -} - -void dev_eth_isr(dev_eth_t *dev) { - (void)dev; - thread_wakeup(handler_pid); -} - -void dev_eth_rx_handler(dev_eth_t *dev) { - DEBUG("dev_eth_rx_handler dev=0x%08x\n", (unsigned) dev); - - int n = dev->driver->recv(dev, _rxbuf, sizeof(_rxbuf)); - - DEBUG("handle_incoming: received %i bytes\n", n); - - if (n>0) { - turn_packet(_rxbuf); - dev->driver->send(dev, _rxbuf, n); - } -} - -void dev_eth_linkstate_handler(dev_eth_t *dev, int newstate) -{ - DEBUG("dev_eth: dev=0x%08x link %s\n", (unsigned)dev, newstate ? "UP" : "DOWN"); - (void)dev; (void)newstate; -} - -int main(void) -{ - handler_pid = thread_getpid(); - - /* always use first ethernet device for test */ - dev_eth_t *const dev = dev_eth_devices[0]; - - dev_eth_init(dev); - - while(1) { - dev->driver->isr(dev); - thread_sleep(); - DEBUG("main: woke up\n"); - } - - return 0; -} diff --git a/tests/driver_netdev_eth/Makefile b/tests/driver_netdev_eth/Makefile deleted file mode 100644 index 78b4b3823792..000000000000 --- a/tests/driver_netdev_eth/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -APPLICATION = driver_netdev_eth -include ../Makefile.tests_common - -BOARD_WHITELIST := native - -USEMODULE += dev_eth_tap -USEMODULE += gnrc -USEMODULE += gnrc_nomac -USEMODULE += gnrc_pktdump -USEMODULE += gnrc_netdev_eth -USEMODULE += auto_init_gnrc_netif -USEMODULE += shell -USEMODULE += shell_commands - -include $(RIOTBASE)/Makefile.include diff --git a/tests/driver_netdev_eth/main.c b/tests/driver_netdev_eth/main.c deleted file mode 100644 index f9dabde9ec07..000000000000 --- a/tests/driver_netdev_eth/main.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2015 Martine Lenders - * Kaspar Schleiser - * - * 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 tests - * @{ - * - * @file - * @brief Test application for netdev ethernet device driver - * - * @author Martine Lenders - * Kaspar Schleiser - * - * @} - */ - -#include - -#include "board.h" -#include "kernel.h" -#include "shell.h" -#include "shell_commands.h" -#include "net/gnrc.h" -#include "net/gnrc/nomac.h" -#include "net/gnrc/pktdump.h" -#include "net/gnrc/netdev_eth.h" -#include "net/dev_eth.h" -#include "dev_eth_tap.h" - -/** - * @brief Maybe you are a golfer?! - */ -int main(void) -{ - gnrc_netreg_entry_t dump; - - puts("netdev ethernet device driver test"); - - /* initialize and register pktdump */ - dump.pid = gnrc_pktdump_init(); - dump.demux_ctx = GNRC_NETREG_DEMUX_CTX_ALL; - - if (dump.pid <= KERNEL_PID_UNDEF) { - puts("Error starting pktdump thread"); - return -1; - } - - gnrc_netreg_register(GNRC_NETTYPE_UNDEF, &dump); - - /* start the shell */ - char line_buf[SHELL_DEFAULT_BUFSIZE]; - shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE); - - return 0; -}