diff --git a/Makefile.dep b/Makefile.dep
index 96202e7fd7e86c2b847d550bfe526c0b3154cc8b..178b3c9a52807e267dfd997215da7e2fa6fbe823 100644
--- a/Makefile.dep
+++ b/Makefile.dep
@@ -357,6 +357,29 @@ ifneq (,$(filter posix_semaphore,$(USEMODULE)))
   USEMODULE += xtimer
 endif
 
+ifneq (,$(filter emb6_conn_udp,$(USEMODULE)))
+  USEMODULE += emb6_sock
+endif
+
+ifneq (,$(filter emb6_%,$(USEMODULE)))
+  USEMODULE += emb6
+endif
+
+ifneq (,$(filter emb6,$(USEMODULE)))
+  USEPKG += emb6
+  USEMODULE += emb6_bsp
+  USEMODULE += emb6_common
+  USEMODULE += emb6_contrib
+  USEMODULE += emb6_ipv6
+  USEMODULE += emb6_ipv6_multicast
+  USEMODULE += emb6_llsec
+  USEMODULE += emb6_mac
+  USEMODULE += emb6_netdev2
+  USEMODULE += emb6_rpl
+  USEMODULE += emb6_sicslowpan
+  USEMODULE += emb6_utils
+endif
+
 ifneq (,$(filter lwip_sixlowpan,$(USEMODULE)))
   USEMODULE += lwip_ipv6_autoconfig
 endif
@@ -411,6 +434,25 @@ ifneq (,$(filter lwip_contrib,$(USEMODULE)))
   USEMODULE += sema
 endif
 
+ifneq (,$(filter emb6_%,$(USEMODULE)))
+  USEMODULE += emb6
+endif
+
+ifneq (,$(filter emb6,$(USEMODULE)))
+  USEPKG += emb6
+  USEMODULE += emb6_bsp
+  USEMODULE += emb6_common
+  USEMODULE += emb6_contrib
+  USEMODULE += emb6_ipv6
+  USEMODULE += emb6_ipv6_multicast
+  USEMODULE += emb6_llsec
+  USEMODULE += emb6_mac
+  USEMODULE += emb6_netdev2
+  USEMODULE += emb6_rpl
+  USEMODULE += emb6_sicslowpan
+  USEMODULE += emb6_utils
+endif
+
 ifneq (,$(filter sema,$(USEMODULE)))
   USEMODULE += xtimer
 endif
diff --git a/Makefile.pseudomodules b/Makefile.pseudomodules
index 8886d73da234f2b7d5c2af77af4681d8f7879e48..1a45bacc107a8157bf3e9a6590639ac81ab99b0f 100644
--- a/Makefile.pseudomodules
+++ b/Makefile.pseudomodules
@@ -4,6 +4,7 @@ PSEUDOMODULES += conn_tcp
 PSEUDOMODULES += conn_udp
 PSEUDOMODULES += core_msg
 PSEUDOMODULES += core_thread_flags
+PSEUDOMODULES += emb6_router
 PSEUDOMODULES += gnrc_netdev_default
 PSEUDOMODULES += gnrc_ipv6_default
 PSEUDOMODULES += gnrc_ipv6_router
diff --git a/pkg/emb6/Makefile b/pkg/emb6/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..40d3bfaf07eb5957707c1ad51a82bcf68cbfd0fe
--- /dev/null
+++ b/pkg/emb6/Makefile
@@ -0,0 +1,11 @@
+PKG_NAME=emb6
+PKG_URL=https://github.com/hso-esk/emb6.git
+PKG_VERSION=14e4a3cfff01644e078870e14e16a1fe60dcc895
+PKG_BUILDDIR ?= $(BINDIRBASE)/pkg/$(BOARD)/$(PKG_NAME)
+
+.PHONY: all
+
+all: git-download
+	"$(MAKE)" -C $(PKG_BUILDDIR)
+
+include $(RIOTBASE)/pkg/pkg.mk
diff --git a/pkg/emb6/Makefile.include b/pkg/emb6/Makefile.include
new file mode 100644
index 0000000000000000000000000000000000000000..090cebac9c0a716af82dfd90b684e2629bef15af
--- /dev/null
+++ b/pkg/emb6/Makefile.include
@@ -0,0 +1,71 @@
+PKG_BUILDDIR ?= $(BINDIRBASE)/pkg/$(BOARD)/emb6
+EMB6_DIR := $(PKG_BUILDDIR)
+EMB6_CONTRIB := $(RIOTBASE)/pkg/emb6/contrib
+
+INCLUDES += -I$(PKG_BUILDDIR)/target
+INCLUDES += -I$(RIOTBASE)/pkg/emb6/include
+
+ifeq (,$(filter emb6_router,$(USEMODULE)))
+  CFLAGS += -DEMB6_CONF_ROUTER=FALSE
+endif
+
+ifneq (,$(filter emb6_bsp,$(USEMODULE)))
+  DIRS += $(EMB6_DIR)/target/bsp
+endif
+
+ifneq (,$(filter emb6_common,$(USEMODULE)))
+  DIRS += $(EMB6_DIR)/emb6
+  INCLUDES += -I$(EMB6_DIR)/emb6
+endif
+
+ifneq (,$(filter emb6_contrib,$(USEMODULE)))
+  DIRS += $(EMB6_CONTRIB)
+endif
+
+ifneq (,$(filter emb6_conn_udp,$(USEMODULE)))
+  DIRS += $(EMB6_CONTRIB)/conn/udp
+endif
+
+ifneq (,$(filter emb6_ipv6,$(USEMODULE)))
+  DIRS += $(EMB6_DIR)/emb6/src/net/ipv6
+  INCLUDES += -I$(EMB6_DIR)/emb6/inc/net/ipv6
+endif
+
+ifneq (,$(filter emb6_ipv6_multicast,$(USEMODULE)))
+  DIRS += $(EMB6_DIR)/emb6/src/net/ipv6/multicast
+  INCLUDES += -I$(EMB6_DIR)/emb6/inc/net/ipv6/multicast
+endif
+
+ifneq (,$(filter emb6_llsec,$(USEMODULE)))
+  DIRS += $(EMB6_DIR)/emb6/src/mac/llsec
+  INCLUDES += -I$(EMB6_DIR)/emb6/inc/mac/llsec
+endif
+
+ifneq (,$(filter emb6_mac,$(USEMODULE)))
+  DIRS += $(EMB6_DIR)/emb6/src/mac
+  INCLUDES += -I$(EMB6_DIR)/emb6/inc/mac
+endif
+
+ifneq (,$(filter emb6_netdev2,$(USEMODULE)))
+  DIRS += $(EMB6_CONTRIB)/netdev2
+endif
+
+ifneq (,$(filter emb6_rpl,$(USEMODULE)))
+  DIRS += $(EMB6_DIR)/emb6/src/net/rpl
+  INCLUDES += -I$(EMB6_DIR)/emb6/inc/net/rpl
+endif
+
+ifneq (,$(filter emb6_sicslowpan,$(USEMODULE)))
+  DIRS += $(EMB6_DIR)/emb6/src/net/sicslowpan
+  INCLUDES += -I$(EMB6_DIR)/emb6/inc/net/sicslowpan
+endif
+
+ifneq (,$(filter emb6_sock,$(USEMODULE)))
+  DIRS += $(EMB6_DIR)/emb6/src/tport
+  INCLUDES += -I$(EMB6_DIR)/emb6/inc/tport
+endif
+
+ifneq (,$(filter emb6_utils,$(USEMODULE)))
+  DIRS += $(EMB6_DIR)/utils/src
+  INCLUDES += -I$(EMB6_DIR)/utils/inc
+endif
diff --git a/pkg/emb6/contrib/Makefile b/pkg/emb6/contrib/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..600b0c807bb1c68b3910ffdad113e45d2cc77c28
--- /dev/null
+++ b/pkg/emb6/contrib/Makefile
@@ -0,0 +1,3 @@
+MODULE = emb6_contrib
+
+include $(RIOTBASE)/Makefile.base
diff --git a/pkg/emb6/contrib/board_conf.c b/pkg/emb6/contrib/board_conf.c
new file mode 100644
index 0000000000000000000000000000000000000000..1ba6463a688bb854119a8d39dcfe3abfde589395
--- /dev/null
+++ b/pkg/emb6/contrib/board_conf.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @{
+ *
+ * @file
+ * @author Martine Lenders <mlenders@inf.fu-berlin.de>
+ */
+
+#include "emb6/netdev2.h"
+
+#include "etimer.h"
+#include "board_conf.h"
+
+#define ENABLE_DEBUG    (0)
+#include "debug.h"
+
+uint8_t board_conf(s_ns_t *ps_nStack)
+{
+    if (ps_nStack != NULL) {
+        ps_nStack->inif = &emb6_netdev2_driver;
+        etimer_init();
+        return ps_nStack->inif->init(ps_nStack);
+    }
+    else {
+        DEBUG("Network stack pointer is NULL");
+        return 0;
+    }
+}
+
+/** @} */
diff --git a/pkg/emb6/contrib/conn/udp/Makefile b/pkg/emb6/contrib/conn/udp/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..e5dbafaedd9b426abbbf7df36189fb6c0895d9fe
--- /dev/null
+++ b/pkg/emb6/contrib/conn/udp/Makefile
@@ -0,0 +1,3 @@
+MODULE = emb6_conn_udp
+
+include $(RIOTBASE)/Makefile.base
diff --git a/pkg/emb6/contrib/conn/udp/emb6_conn_udp.c b/pkg/emb6/contrib/conn/udp/emb6_conn_udp.c
new file mode 100644
index 0000000000000000000000000000000000000000..bbd488edfe3f9ddb346037d8e52189883cac6eab
--- /dev/null
+++ b/pkg/emb6/contrib/conn/udp/emb6_conn_udp.c
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2016 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @{
+ *
+ * @file
+ * @author  Martine Lenders <mlenders@inf.fu-berlin.de>
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdbool.h>
+
+#include "evproc.h"
+#include "msg.h"
+#include "mutex.h"
+#include "net/af.h"
+#include "net/conn/udp.h"
+#include "net/ipv6/hdr.h"
+#include "sched.h"
+#include "uip.h"
+
+#define _MSG_TYPE_CLOSE     (0x4123)
+#define _MSG_TYPE_RCV       (0x4124)
+
+/* struct to describe a sendto command for emb6 thread */
+typedef struct {
+    struct udp_socket sock;
+    mutex_t mutex;
+    const void *data;
+    int res;
+    uint16_t data_len;
+} _send_cmd_t;
+
+extern uint16_t uip_slen;
+
+static bool send_registered = false;
+
+static void _input_callback(struct udp_socket *c, void *ptr,
+                            const uip_ipaddr_t *src_addr, uint16_t src_port,
+                            const uip_ipaddr_t *dst_addr, uint16_t dst_port,
+                            const uint8_t *data, uint16_t datalen);
+static void _output_callback(c_event_t c_event, p_data_t p_data);
+
+static int _reg_and_bind(struct udp_socket *c, void *ptr,
+                         udp_socket_input_callback_t cb, uint16_t port)
+{
+    if (udp_socket_register(c, ptr, cb) < 0) {
+        return -EMFILE;
+    }
+    if (udp_socket_bind(c, port) < 0) {
+        udp_socket_close(c);
+        return -EALREADY;
+    }
+    return 0;
+}
+
+int conn_udp_create(conn_udp_t *conn, const void *addr, size_t addr_len,
+                    int family, uint16_t port)
+{
+    int res;
+
+    (void)addr;
+    (void)addr_len;
+    if (family != AF_INET6) {
+        return -EAFNOSUPPORT;
+    }
+    if (conn->sock.input_callback != NULL) {
+        return -EINVAL;
+    }
+    mutex_init(&conn->mutex);
+    mutex_lock(&conn->mutex);
+    if ((res = _reg_and_bind(&conn->sock, conn, _input_callback, port)) < 0) {
+        conn->sock.input_callback = NULL;
+        mutex_unlock(&conn->mutex);
+        return res;
+    }
+    conn->waiting_thread = KERNEL_PID_UNDEF;
+    mutex_unlock(&conn->mutex);
+    return 0;
+}
+
+void conn_udp_close(conn_udp_t *conn)
+{
+    if (conn->sock.input_callback != NULL) {
+        mutex_lock(&conn->mutex);
+        if (conn->waiting_thread != KERNEL_PID_UNDEF) {
+            msg_t msg;
+            msg.type = _MSG_TYPE_CLOSE;
+            msg.content.ptr = (char *)conn;
+            mutex_unlock(&conn->mutex);
+            msg_send(&msg, conn->waiting_thread);
+            mutex_lock(&conn->mutex);
+        }
+        udp_socket_close(&conn->sock);
+        conn->sock.input_callback = NULL;
+        mutex_unlock(&conn->mutex);
+    }
+}
+
+int conn_udp_getlocaladdr(conn_udp_t *conn, void *addr, uint16_t *port)
+{
+    if (conn->sock.input_callback != NULL) {
+        mutex_lock(&conn->mutex);
+        memset(addr, 0, sizeof(ipv6_addr_t));
+        *port = NTOHS(conn->sock.udp_conn->lport);
+        mutex_unlock(&conn->mutex);
+        return sizeof(ipv6_addr_t);
+    }
+    return -EBADF;
+}
+
+int conn_udp_recvfrom(conn_udp_t *conn, void *data, size_t max_len, void *addr,
+                      size_t *addr_len, uint16_t *port)
+{
+    int res = -EIO;
+    msg_t msg;
+
+    if (conn->sock.input_callback == NULL) {
+        return -ENOTSOCK;
+    }
+    mutex_lock(&conn->mutex);
+    if (conn->waiting_thread != KERNEL_PID_UNDEF) {
+        mutex_unlock(&conn->mutex);
+        return -EALREADY;
+    }
+    conn->waiting_thread = sched_active_pid;
+    mutex_unlock(&conn->mutex);
+    msg_receive(&msg);
+    if (msg.type == _MSG_TYPE_CLOSE) {
+        conn->waiting_thread = KERNEL_PID_UNDEF;
+        return -EINTR;
+    }
+    else if (msg.type == _MSG_TYPE_RCV) {
+        mutex_lock(&conn->mutex);
+        if (msg.content.ptr == (char *)conn) {
+            if (max_len < conn->recv_info.datalen) {
+                conn->waiting_thread = KERNEL_PID_UNDEF;
+                mutex_unlock(&conn->mutex);
+                return -ENOBUFS;
+            }
+            memcpy(data, conn->recv_info.data, conn->recv_info.datalen);
+            memcpy(addr, conn->recv_info.src, sizeof(ipv6_addr_t));
+            *addr_len = sizeof(ipv6_addr_t);
+            *port = conn->recv_info.src_port;
+            res = (int)conn->recv_info.datalen;
+        }
+        conn->waiting_thread = KERNEL_PID_UNDEF;
+        mutex_unlock(&conn->mutex);
+    }
+    return res;
+}
+
+int conn_udp_sendto(const void *data, size_t len, const void *src, size_t src_len,
+                    const void *dst, size_t dst_len, int family, uint16_t sport,
+                    uint16_t dport)
+{
+    int res;
+    _send_cmd_t send_cmd;
+
+    if (!send_registered) {
+        if (evproc_regCallback(EVENT_TYPE_CONN_SEND, _output_callback) != E_SUCCESS) {
+            return -EIO;
+        }
+        else {
+            send_registered = true;
+        }
+    }
+    mutex_init(&send_cmd.mutex);
+    if ((len > (UIP_BUFSIZE - (UIP_LLH_LEN + UIP_IPUDPH_LEN))) ||
+        (len > UINT16_MAX)) {
+        return -EMSGSIZE;
+    }
+    if ((dst_len > sizeof(ipv6_addr_t)) || (family != AF_INET6)) {
+        return -EAFNOSUPPORT;
+    }
+    mutex_lock(&send_cmd.mutex);
+    send_cmd.data = data;
+    send_cmd.data_len = (uint16_t)len;
+    if ((res = _reg_and_bind(&send_cmd.sock, NULL, NULL, sport)) < 0) {
+        mutex_unlock(&send_cmd.mutex);
+        return res;
+    }
+    udp_socket_connect(&send_cmd.sock, (uip_ipaddr_t *)dst, dport); /* can't fail at this point */
+    /* change to emb6 thread context */
+    if (evproc_putEvent(E_EVPROC_TAIL, EVENT_TYPE_CONN_SEND, &send_cmd) != E_SUCCESS) {
+        udp_socket_close(&send_cmd.sock);
+        mutex_unlock(&send_cmd.mutex);
+        return -EIO;
+    }
+    /* block thread until data was send */
+    mutex_lock(&send_cmd.mutex);
+    udp_socket_close(&send_cmd.sock);
+    mutex_unlock(&send_cmd.mutex);
+
+    return send_cmd.res;
+}
+
+static void _input_callback(struct udp_socket *c, void *ptr,
+                            const uip_ipaddr_t *src_addr, uint16_t src_port,
+                            const uip_ipaddr_t *dst_addr, uint16_t dst_port,
+                            const uint8_t *data, uint16_t datalen)
+{
+    conn_udp_t *conn = ptr;
+
+    (void)dst_addr;
+    (void)dst_port;
+    mutex_lock(&conn->mutex);
+    if (conn->waiting_thread != KERNEL_PID_UNDEF) {
+        msg_t msg;
+        conn->recv_info.src_port = src_port;
+        conn->recv_info.src = (const ipv6_addr_t *)src_addr;
+        conn->recv_info.data = data;
+        conn->recv_info.datalen = datalen - sizeof(ipv6_hdr_t);
+        msg.type = _MSG_TYPE_RCV;
+        msg.content.ptr = (char *)conn;
+        mutex_unlock(&conn->mutex);
+        msg_send(&msg, conn->waiting_thread);
+    }
+    else {
+        mutex_unlock(&conn->mutex);
+    }
+}
+
+static void _output_callback(c_event_t c_event, p_data_t p_data)
+{
+    _send_cmd_t *send_cmd = (_send_cmd_t *)p_data;
+
+    if ((c_event != EVENT_TYPE_CONN_SEND) || (p_data == NULL)) {
+        return;
+    }
+    if ((send_cmd->res = udp_socket_send(&send_cmd->sock, send_cmd->data, send_cmd->data_len)) < 0) {
+        send_cmd->res = -EHOSTUNREACH;
+    }
+    mutex_unlock(&send_cmd->mutex);
+}
+
+/** @} */
diff --git a/pkg/emb6/contrib/netdev2/Makefile b/pkg/emb6/contrib/netdev2/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..bdc2e75de0764773d0f519ff415e212db5c40e89
--- /dev/null
+++ b/pkg/emb6/contrib/netdev2/Makefile
@@ -0,0 +1,3 @@
+MODULE = emb6_netdev2
+
+include $(RIOTBASE)/Makefile.base
diff --git a/pkg/emb6/contrib/netdev2/emb6_netdev2.c b/pkg/emb6/contrib/netdev2/emb6_netdev2.c
new file mode 100644
index 0000000000000000000000000000000000000000..039db6f7627b88806e7390cd75909919ab528f45
--- /dev/null
+++ b/pkg/emb6/contrib/netdev2/emb6_netdev2.c
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2016 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @{
+ *
+ * @file
+ * @author  Martine Lenders <mlenders@inf.fu-berlin.de>
+ */
+
+#include <assert.h>
+#include <stdint.h>
+#include <sys/uio.h>
+
+#include "msg.h"
+#include "net/netdev2.h"
+
+#include "evproc.h"
+#include "emb6.h"
+#include "linkaddr.h"
+#include "packetbuf.h"
+
+#define ENABLE_DEBUG    (0)
+#include "debug.h"
+
+extern uip_lladdr_t uip_lladdr;
+
+static netdev2_t *_dev = NULL;
+static s_nsLowMac_t *_lowmac = NULL;
+static int8_t _rssi_base_value = -100;
+static uint8_t _last_rssi;
+
+static int8_t _netdev2_init(s_ns_t *p_ns);
+static int8_t _netdev2_send(const void *pr_payload, uint8_t c_len);
+static int8_t _netdev2_on(void);
+static int8_t _netdev2_off(void);
+static void _netdev2_set_txpower(int8_t power);
+static int8_t _netdev2_get_txpower(void);
+static void _netdev2_set_sensitivity(int8_t sens);
+static int8_t _netdev2_get_sensitivity(void);
+static int8_t _netdev2_get_rssi(void);
+static void _netdev2_set_promisc(uint8_t c_on_off);
+
+const s_nsIf_t emb6_netdev2_driver = {
+    .name               = "netdev2",
+    .init               = &_netdev2_init,
+    .send               = &_netdev2_send,
+    .on                 = &_netdev2_on,
+    .off                = &_netdev2_off,
+    .set_txpower        = &_netdev2_set_txpower,
+    .get_txpower        = &_netdev2_get_txpower,
+    .set_sensitivity    = &_netdev2_set_sensitivity,
+    .get_sensitivity    = &_netdev2_get_sensitivity,
+    .get_rssi           = &_netdev2_get_rssi,
+    .ant_div            = NULL,
+    .ant_rf_switch      = NULL,
+    .set_promisc        = &_netdev2_set_promisc,
+};
+
+static void _get_recv_pkt(void)
+{
+    char *dataptr;
+    struct netdev2_radio_rx_info rx_info;
+    int8_t len;
+
+    packetbuf_clear();
+
+    dataptr = packetbuf_dataptr();
+    len = _dev->driver->recv(_dev, dataptr, PACKETBUF_SIZE, &rx_info);
+    _last_rssi = rx_info.rssi;
+
+    if ((len > 0) && (_lowmac != NULL)) {
+        packetbuf_set_datalen(len);
+        _lowmac->input();
+    }
+}
+
+static void _event_cb(netdev2_t *dev, netdev2_event_t event, void *arg)
+{
+    (void)arg;
+    if (event == NETDEV2_EVENT_ISR) {
+        /* EVENT_TYPE_PCK_LL is supposed to be used by drivers, so use it
+         * (though NETDEV2_EVENT_ISR technically doesn't only signify
+         * incoming packets) */
+        evproc_putEvent(E_EVPROC_HEAD, EVENT_TYPE_PCK_LL, NULL);
+    }
+    else {
+        switch (event) {
+            case NETDEV2_EVENT_RX_COMPLETE: {
+                _get_recv_pkt();
+            }
+            break;
+            default:
+                break;
+        }
+    }
+}
+
+static void _emb6_netdev2_callback(c_event_t c_event, p_data_t p_data)
+{
+    (void)p_data;
+    if (c_event == EVENT_TYPE_PCK_LL) {
+        _dev->driver->isr(_dev);
+    }
+}
+
+int emb6_netdev2_setup(netdev2_t *dev)
+{
+    if (_dev == NULL) {
+        _dev = dev;
+        return 0;
+    }
+    return -1;
+}
+
+static int8_t _netdev2_init(s_ns_t *p_ns)
+{
+    if ((_dev != NULL) && (p_ns != NULL) && (p_ns->lmac != NULL)) {
+        _dev->event_callback = _event_cb;
+        _dev->driver->get(_dev, NETOPT_ADDRESS_LONG, &mac_phy_config.mac_address,
+                          sizeof(mac_phy_config.mac_address));
+        memcpy(&uip_lladdr, mac_phy_config.mac_address,
+               sizeof(mac_phy_config.mac_address));
+        _dev->driver->get(_dev, NETOPT_NID, &mac_phy_config.pan_id,
+                          sizeof(mac_phy_config.pan_id));
+        linkaddr_set_node_addr((linkaddr_t *)&uip_lladdr);
+        _lowmac = p_ns->lmac;
+        evproc_regCallback(EVENT_TYPE_PCK_LL, _emb6_netdev2_callback);
+        return 1;
+    }
+    return 0;
+}
+
+static int8_t _netdev2_send(const void *pr_payload, uint8_t c_len)
+{
+    if (_dev != NULL) {
+        const struct iovec vector = {
+            .iov_base = (void *)pr_payload,
+            .iov_len = c_len
+        };
+        if (_dev->driver->send(_dev, &vector, 1) < 0) {
+            DEBUG("Error on send\n");
+            return RADIO_TX_ERR;
+        }
+        DEBUG("Packet of length %u was transmitted\n", (unsigned)c_len);
+        return RADIO_TX_OK;
+    }
+    DEBUG("Device was not initialized\n");
+    return RADIO_TX_ERR;
+}
+
+static int8_t _netdev2_on(void)
+{
+    /* TODO: turn netdev2 on */
+    return 1;
+}
+
+static int8_t _netdev2_off(void)
+{
+    /* TODO: turn netdev2 off */
+    return 1;
+}
+
+static void _netdev2_set_txpower(int8_t power)
+{
+    int16_t pwr = power;
+
+    _dev->driver->set(_dev, NETOPT_TX_POWER, &pwr, sizeof(pwr));
+}
+
+static int8_t _netdev2_get_txpower(void)
+{
+    int16_t power = 0;
+
+    _dev->driver->get(_dev, NETOPT_TX_POWER, &power, sizeof(power));
+    return (int8_t)power;
+}
+
+static void _netdev2_set_sensitivity(int8_t sens)
+{
+    /* TODO: set sensitivity */
+}
+
+static int8_t _netdev2_get_sensitivity(void)
+{
+    /* TODO: get sensitivity */
+    return 0;
+}
+
+static int8_t _netdev2_get_rssi(void)
+{
+    return (int8_t)(_rssi_base_value + 1.03 * _last_rssi);
+}
+
+static void _netdev2_set_promisc(uint8_t c_on_off)
+{
+    netopt_enable_t en = (c_on_off) ? NETOPT_ENABLE : NETOPT_DISABLE;
+
+    _dev->driver->set(_dev, NETOPT_PROMISCUOUSMODE, &en, sizeof(en));
+}
+
+/** @} */
diff --git a/pkg/emb6/contrib/target.c b/pkg/emb6/contrib/target.c
new file mode 100644
index 0000000000000000000000000000000000000000..ac256b4d670fa95672f9673b09d221ad4e3d778d
--- /dev/null
+++ b/pkg/emb6/contrib/target.c
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @{
+ *
+ * @file
+ * @author Martine Lenders <mlenders@inf.fu-berlin.de>
+ */
+
+#include <inttypes.h>
+
+#include "cpu.h"
+#include "led.h"
+#include "mutex.h"
+#include "periph/gpio.h"
+#include "periph/hwrng.h"
+#include "xtimer.h"
+
+#include "target.h"
+#include "bsp.h"
+
+static mutex_t critical_mutex = MUTEX_INIT;
+
+void hal_enterCritical(void)
+{
+    mutex_lock(&critical_mutex);
+}
+
+void hal_exitCritical(void)
+{
+    mutex_unlock(&critical_mutex);
+}
+
+int8_t hal_init(void)
+{
+    /* Should have happened long before emb6 started, so nothing to do */
+    return 1;
+}
+
+uint8_t hal_getrand(void)
+{
+#if RANDOM_NUMOF
+    uint8_t res;
+    hwnrg_read((char *)&res, sizeof(res));
+    return res;
+#elif defined(MODULE_RANDOM)
+    return (uint8_t)(genrand_uint32() % UINT8_MAX);
+#else
+    return 4;   /* keeping the meme alive ;-) */
+#endif
+}
+
+void hal_ledOn(uint16_t ui_led)
+{
+    switch (ui_led) {
+        case E_BSP_LED_RED:
+            LED0_ON;
+            break;
+        case E_BSP_LED_YELLOW:
+            LED1_ON;
+            break;
+        case E_BSP_LED_GREEN:
+            LED2_ON;
+            break;
+        default:
+            break;
+    }
+}
+
+void hal_ledOff(uint16_t ui_led)
+{
+    switch (ui_led) {
+        case E_BSP_LED_RED:
+            LED0_OFF;
+            break;
+        case E_BSP_LED_YELLOW:
+            LED1_OFF;
+            break;
+        case E_BSP_LED_GREEN:
+            LED2_OFF;
+            break;
+        default:
+            break;
+    }
+}
+
+uint8_t hal_extIntInit(en_targetExtInt_t e_extInt, pfn_intCallb_t pfn_intCallback)
+{
+    /* RIOT does this in netdev2 initialization so nothing to do here. */
+    return 0;
+}
+
+void hal_delay_us(uint32_t i_delay)
+{
+    xtimer_usleep(i_delay);
+}
+
+uint8_t hal_gpioPinInit(uint8_t c_pin, uint8_t c_dir, uint8_t c_initState)
+{
+    /* Only used in board init code => not needed */
+    (void)c_pin;
+    (void)c_dir;
+    (void)c_initState;
+    return 0;
+}
+
+void *hal_ctrlPinInit(en_targetExtPin_t e_pinType)
+{
+    (void)e_pinType;
+    return NULL;
+}
+
+void hal_pinSet(void *p_pin)
+{
+    /* Only used in board/driver-related code code => not needed */
+}
+
+void hal_pinClr(void *p_pin)
+{
+    /* Only used in board/driver-related code code => not needed */
+}
+
+uint8_t hal_pinGet(void *p_pin)
+{
+    /* Only used in board/driver-related code code => not needed */
+    return 0;
+}
+
+void *hal_spiInit(void)
+{
+    /* Only used in board/driver-related code code => not needed */
+    return 0;
+}
+
+/*----------------------------------------------------------------------------*/
+/** \brief  This function selects slave with which we will work
+ *  \param         p_spi    Pointer to spi description entity
+ *  \param        action    true or false
+ *
+ *  \return        0 if failed, 1 id ok
+ */
+/*---------------------------------------------------------------------------*/
+uint8_t hal_spiSlaveSel(void *p_spi, bool action)
+{
+    /* Only used in board/driver-related code code => not needed */
+    return 0;
+}
+
+uint8_t hal_spiTransceive( uint8_t *txData, uint8_t *p_reg)
+{
+    /* Only used in board/driver-related code code => not needed */
+    return 0;
+}
+
+uint8_t hal_spiRead(uint8_t *p_reg, uint16_t i_length)
+{
+    /* Only used in board/driver-related code code => not needed */
+    return 0;
+}
+
+
+/*----------------------------------------------------------------------------*/
+/** \brief  This function writes a new value via given SPI interface
+ *          registers.
+ *
+ *
+ *  \param  value         Pointer to a value.
+ *  \param  i_length     Length of a data to be received
+ */
+/*----------------------------------------------------------------------------*/
+void hal_spiWrite(uint8_t *value, uint16_t i_length)
+{
+    /* Only used in board/driver-related code code => not needed */
+}
+
+void hal_watchdogReset(void)
+{
+    /* WDT and tick-less scheduling don't make much sense */
+}
+
+void hal_watchdogStart(void)
+{
+    /* WDT and tick-less scheduling don't make much sense */
+}
+
+void     hal_watchdogStop(void)
+{
+    /* WDT and tick-less scheduling don't make much sense */
+}
+
+clock_time_t hal_getTick(void)
+{
+    return (clock_time_t)xtimer_now();
+}
+
+clock_time_t hal_getSec(void)
+{
+    return (clock_time_t)xtimer_now() / SEC_IN_USEC;
+}
+
+
+clock_time_t hal_getTRes(void)
+{
+    return SEC_IN_USEC;
+}
+
+/** @} */
diff --git a/pkg/emb6/doc.txt b/pkg/emb6/doc.txt
new file mode 100644
index 0000000000000000000000000000000000000000..8afb9ee9db05debcf5081a1b51223710b5a300f7
--- /dev/null
+++ b/pkg/emb6/doc.txt
@@ -0,0 +1,9 @@
+/**
+ * @defgroup pkg_emb6 emb6 network stack
+ * @ingroup pkg
+ * @brief   emb6 network stack
+ * @see     https://github.com/hso-esk/emb6/raw/develop/doc/pdf/emb6.pdf
+ *
+ * emb6 is a fork of Contiki's uIP network stack without its usage of
+ * proto-threads. It uses periodic event polling instead.
+ */
diff --git a/pkg/emb6/include/board_conf.h b/pkg/emb6/include/board_conf.h
new file mode 100644
index 0000000000000000000000000000000000000000..56c765618874e2714b9641de25a2c93bae1f0aaf
--- /dev/null
+++ b/pkg/emb6/include/board_conf.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2016 Freie Universität Berlin
+ *
+ * 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    emb6    emb6 network stack
+ * @ingroup pkg
+ * @brief
+ * @{
+ *
+ * @file
+ * @brief   "Board" configuration for emb6
+ *
+ * @author  Martine Lenders <mlenders@inf.fu-berlin.de>
+ */
+
+#ifndef EMB6_BOARD_CONF_H_
+#define EMB6_BOARD_CONF_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "emb6.h"
+
+/**
+ * @brief    emb6 board configuration function
+ *
+ * @param[in]   ps_nStack pointer to global netstack struct
+ *
+ * @return  success 1
+ * @return  failure 0
+ */
+uint8_t board_conf(s_ns_t *ps_nStack);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* EMB6_BOARD_CONF_H_ */
+/** @} */
+/** @} */
diff --git a/pkg/emb6/include/emb6/conn/udp.h b/pkg/emb6/include/emb6/conn/udp.h
new file mode 100644
index 0000000000000000000000000000000000000000..dc835ca06bd0e7cd6e9467e4deca5628ec9c4962
--- /dev/null
+++ b/pkg/emb6/include/emb6/conn/udp.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2016 Freie Universität Berlin
+ *
+ * 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    emb6_conn_udp   udp_conn wrapper for emb6
+ * @ingroup     emb6
+ * @brief       UDP conn for emb6
+ *
+ * For this implementation to receive with an open connection only with one
+ * thread at once. If you use @ref conn_udp_recvfrom() with more than one thread
+ * simultaneously, it will return `-EALREADY`.
+ *
+ * @{
+ *
+ * @file
+ * @brief   UDP conn definitions
+ *
+ * @author  Martine Lenders <mlenders@inf.fu-berlin.de>
+ */
+#ifndef EMB6_CONN_UDP_H_
+#define EMB6_CONN_UDP_H_
+
+#include <stdint.h>
+
+#include "kernel_types.h"
+#include "mutex.h"
+#include "net/ipv6/addr.h"
+
+#include "uip.h"
+#include "udp-socket.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief @ref net_conn_udp definition for emb6
+ */
+struct conn_udp {
+    struct udp_socket sock;         /**< emb6 internal socket */
+    mutex_t mutex;                  /**< mutex for the connection */
+    kernel_pid_t waiting_thread;    /**< thread waiting for an incoming packet
+                                     *   on this connection */
+    struct {
+        uint16_t src_port;          /**< source port */
+        const ipv6_addr_t *src;     /**< source address */
+        const void *data;           /**< data of received packet */
+        size_t datalen;             /**< length of received packet data */
+    } recv_info;                    /**< info on received packet */
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* EMB6_CONN_UDP_H_ */
+/** @} */
diff --git a/pkg/emb6/include/emb6/netdev2.h b/pkg/emb6/include/emb6/netdev2.h
new file mode 100644
index 0000000000000000000000000000000000000000..3076603ffcd7b66fad4ac7734934649a06597798
--- /dev/null
+++ b/pkg/emb6/include/emb6/netdev2.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2016 Freie Universität Berlin
+ *
+ * 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 pkgemb6_netdev2    netdev2 wrapper for emb6
+ * @ingroup pkg_emb6
+ * @brief
+ * @{
+ *
+ * @file
+ * @brief
+ *
+ * @author  Martine Lenders <mlenders@inf.fu-berlin.de>
+ */
+#ifndef EMB6_NETDEV2_H_
+#define EMB6_NETDEV2_H_
+
+#include "net/netdev2.h"
+
+#include "emb6.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief   The emb6 network interface.
+ *
+ * @note    emb6 only supports one network interface.
+ *
+ * This variable is used by @ref board_conf() to set the interface for the
+ * stack.
+ */
+extern const s_nsIf_t emb6_netdev2_driver;
+
+/**
+ * @brief   Setup a network device as the emb6 interface.
+ *
+ * @param[in] dev   The network device for the interface
+ *
+ * @return 0 on success.
+ * @return <= 0 on error.
+ */
+int emb6_netdev2_setup(netdev2_t *dev);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* EMB6_NETDEV2_H_ */
+/** @} */
diff --git a/pkg/emb6/patches/0001-Add-RIOT-Makefiles.patch b/pkg/emb6/patches/0001-Add-RIOT-Makefiles.patch
new file mode 100644
index 0000000000000000000000000000000000000000..7f92930002684c0c5f05740b1d91469f09d9f540
Binary files /dev/null and b/pkg/emb6/patches/0001-Add-RIOT-Makefiles.patch differ
diff --git a/pkg/emb6/patches/0002-Rename-colliding-files-and-functions.patch b/pkg/emb6/patches/0002-Rename-colliding-files-and-functions.patch
new file mode 100644
index 0000000000000000000000000000000000000000..5dfcfd962655f49f0be870ff2dbce066f41ddb3a
Binary files /dev/null and b/pkg/emb6/patches/0002-Rename-colliding-files-and-functions.patch differ
diff --git a/pkg/emb6/patches/0003-Fix-warnings.patch b/pkg/emb6/patches/0003-Fix-warnings.patch
new file mode 100644
index 0000000000000000000000000000000000000000..dfa59d43821b2bce8fb816fbc97422c39f9aeb0d
Binary files /dev/null and b/pkg/emb6/patches/0003-Fix-warnings.patch differ
diff --git a/pkg/emb6/patches/0004-Provide-event-type-for-RIOT-s-conn_.-_send.patch b/pkg/emb6/patches/0004-Provide-event-type-for-RIOT-s-conn_.-_send.patch
new file mode 100644
index 0000000000000000000000000000000000000000..ba76384872852942319836a2fde16d572ccb1d9c
Binary files /dev/null and b/pkg/emb6/patches/0004-Provide-event-type-for-RIOT-s-conn_.-_send.patch differ
diff --git a/sys/include/net/conn/udp.h b/sys/include/net/conn/udp.h
index 2e400a0cf7a269ed9997413d550d8913d327458f..b59ac07ce49d2066851641eeea1af06306611e13 100644
--- a/sys/include/net/conn/udp.h
+++ b/sys/include/net/conn/udp.h
@@ -31,6 +31,10 @@
 #include "lwip/conn.h"
 #endif
 
+#ifdef MODULE_EMB6_CONN_UDP
+#include "emb6/conn/udp.h"
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif
diff --git a/tests/emb6/Makefile b/tests/emb6/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..874ed139e15b2887adb468620bd8000828371a35
--- /dev/null
+++ b/tests/emb6/Makefile
@@ -0,0 +1,38 @@
+APPLICATION = emb6
+
+FEATURES_REQUIRED = periph_gpio periph_spi  # for at86rf231
+
+BOARD ?= samr21-xpro
+
+RIOTBASE ?= $(CURDIR)/../..
+
+BOARD_INSUFFICIENT_MEMORY := msb-430h stm32f0discovery weio z1
+
+USEMODULE += emb6_router
+USEMODULE += emb6_conn_udp
+USEMODULE += ipv6_addr
+USEMODULE += shell
+USEMODULE += shell_commands
+USEMODULE += ps
+USEMODULE += od
+
+# define the driver to be used for selected boards
+ifneq (,$(filter samr21-xpro,$(BOARD)))
+  DRIVER := at86rf233
+endif
+ifneq (,$(filter iotlab-m3 fox,$(BOARD)))
+  DRIVER := at86rf231
+endif
+ifneq (,$(filter mulle,$(BOARD)))
+  DRIVER := at86rf212b
+endif
+
+# use the at86rf231 as fallback device
+DRIVER ?= at86rf231
+
+# include the selected driver
+USEMODULE += $(DRIVER)
+
+QUIET ?= 1
+
+include $(RIOTBASE)/Makefile.include
diff --git a/tests/emb6/common.c b/tests/emb6/common.c
new file mode 100644
index 0000000000000000000000000000000000000000..ec50688980a225f408b26a0cc6f22b804eb28752
--- /dev/null
+++ b/tests/emb6/common.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @{
+ *
+ * @file
+ * @author Martine Lenders <mlenders@inf.fu-berlin.de>
+ */
+
+#include <stdbool.h>
+
+#include "common.h"
+
+size_t hex2ints(uint8_t *out, const char *in)
+{
+    bool upper = true;
+    size_t out_size = 0;
+
+    while (*in != '\0') {
+        char c;
+        if ((*in >= '0') && (*in <= '9')) {
+            c = '0';
+        }
+        else if ((*in >= 'a') && (*in <= 'f')) {
+            c = 'a' - 10;
+        }
+        else if ((*in >= 'A') && (*in <= 'F')) {
+            c = 'A' - 10;
+        }
+        else {
+            in++;
+            continue;
+        }
+        if (upper) {
+            *out = (char)(*in - c) << 4;
+        }
+        else {
+            *out |= (char)(*in - c);
+            out++;
+            out_size++;
+        }
+        upper = !upper;
+        in++;
+    }
+    if (!upper) {
+        out_size++;
+    }
+    return out_size;
+}
+
+/** @} */
diff --git a/tests/emb6/common.h b/tests/emb6/common.h
new file mode 100644
index 0000000000000000000000000000000000000000..0efd9e9afa1df0cece7f6e54d1460b04ab5efea8
--- /dev/null
+++ b/tests/emb6/common.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2016 Martine Lenders <mlenders@inf.fu-berlin.de>
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @ingroup     tests
+ * @{
+ *
+ * @file
+ * @brief   Definitions for tests/lwip/
+ *
+ * @author  Martine Lenders <mlenders@inf.fu-berlin.de>
+ */
+#ifndef MAIN_H_
+#define MAIN_H_
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief   Application configuration
+ * @{
+ */
+#define CONN_INBUF_SIZE         (256)
+#define SERVER_MSG_QUEUE_SIZE   (8)
+#define SERVER_BUFFER_SIZE      (64)
+/**
+ * @}
+ */
+
+/**
+ * @brief   Converts hex string to byte array.
+ *
+ * @param[out] out  Resulting byte array
+ * @param[in] in    `\0` terminated string. Non-hex characters (all except 0-9, a-f, A-F)
+ *                  will be ignored.
+ *
+ * @return  Length of @p out.
+ */
+size_t hex2ints(uint8_t *out, const char *in);
+
+/**
+ * @brief   Ping shell command
+ *
+ * @param[in] argc  number of arguments
+ * @param[in] argv  array of arguments
+ *
+ * @return  0 on success
+ * @return  other on error
+ */
+int ping_cmd(int argc, char **argv);
+
+#ifdef MODULE_CONN_UDP
+/**
+ * @brief   UDP IP shell command
+ *
+ * @param[in] argc  number of arguments
+ * @param[in] argv  array of arguments
+ *
+ * @return  0 on success
+ * @return  other on error
+ */
+int udp_cmd(int argc, char **argv);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MAIN_H_ */
+/** @} */
diff --git a/tests/emb6/main.c b/tests/emb6/main.c
new file mode 100644
index 0000000000000000000000000000000000000000..0929b4ef465f28317a99483f23c4fe5e636d9b8b
--- /dev/null
+++ b/tests/emb6/main.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2015 Martine Lenders <mlenders@inf.fu-berlin.de>
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @ingroup     examples
+ * @{
+ *
+ * @file
+ * @brief       Test for raw IPv6 connections
+ *
+ * @author      Martine Lenders <mlenders@inf.fu-berlin.de>
+ *
+ * This test application tests the gnrc_conn_ip module. If you select protocol 58 you can also
+ * test if gnrc is able to deal with multiple subscribers to ICMPv6 (gnrc_icmpv6 and this
+ * application).
+ *
+ * @}
+ */
+
+#include <errno.h>
+#include <stdio.h>
+
+#include "at86rf2xx.h"
+#include "at86rf2xx_params.h"
+#include "common.h"
+#include "emb6.h"
+#include "emb6/netdev2.h"
+#include "uip-ds6.h"
+#include "net/ipv6/addr.h"
+#include "shell.h"
+#include "thread.h"
+#include "xtimer.h"
+
+#define EMB6_STACKSIZE  (THREAD_STACKSIZE_DEFAULT)
+#define EMB6_PRIO       (THREAD_PRIORITY_MAIN - 3)
+#define EMB6_DELAY      (500)
+
+static at86rf2xx_t at86rf2xx;
+static s_ns_t emb6 = {
+    .hc = &sicslowpan_driver,
+    .llsec = &nullsec_driver,
+    .hmac = &nullmac_driver,
+    .lmac = &sicslowmac_driver,
+    .frame = &framer_802154,
+    .c_configured = 1,
+};
+static char emb6_stack[EMB6_STACKSIZE];
+
+static int ifconfig(int argc, char **argv)
+{
+    (void)argc;
+    (void)argv;
+    char addrstr[IPV6_ADDR_MAX_STR_LEN];
+    printf("0:  ");
+    for (int i = 0; i < UIP_DS6_ADDR_NB; i++) {
+        if (uip_ds6_if.addr_list[i].isused) {
+            printf("inet6 %s\n",
+                   ipv6_addr_to_str(addrstr,
+                                    (ipv6_addr_t *)&uip_ds6_if.addr_list[i].ipaddr,
+                                    sizeof(addrstr)));
+            if (i != 0) {
+                printf("    ");
+            }
+        }
+    }
+    puts("");
+    return 0;
+}
+
+static void *_emb6_thread(void *args)
+{
+    emb6_process(500);  /* never stops */
+    return NULL;
+}
+
+static const shell_command_t shell_commands[] = {
+    { "ping6", "Send pings and receive pongs", ping_cmd },
+#ifdef MODULE_CONN_UDP
+    { "udp", "Send UDP messages and listen for messages on UDP port", udp_cmd },
+#endif
+    { "ifconfig", "Shows assigned IPv6 addresses", ifconfig },
+    { NULL, NULL, NULL }
+};
+static char line_buf[SHELL_DEFAULT_BUFSIZE];
+
+char conn_inbuf[CONN_INBUF_SIZE];
+
+int main(void)
+{
+    netdev2_t *netdev = (netdev2_t *)&at86rf2xx;
+
+    puts("RIOT lwip test application");
+
+    at86rf2xx_setup(&at86rf2xx, at86rf2xx_params);
+    netdev->driver->init((netdev2_t *)&at86rf2xx);
+    emb6_netdev2_setup(netdev);
+    emb6_init(&emb6);
+    thread_create(emb6_stack, sizeof(emb6_stack), EMB6_PRIO,
+                  THREAD_CREATE_STACKTEST, _emb6_thread, NULL, "emb6");
+    shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE);
+
+    /* should be never reached */
+    return 0;
+}
diff --git a/tests/emb6/ping.c b/tests/emb6/ping.c
new file mode 100644
index 0000000000000000000000000000000000000000..73ffa5e4ce3ebda6db023aea02ab9f7fabbc6f2f
--- /dev/null
+++ b/tests/emb6/ping.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2015 Freie Universität Berlin
+ *
+ * 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     examples
+ * @{
+ *
+ * @file
+ * @brief       Demonstrating the sending and receiving of UDP data over POSIX sockets.
+ *
+ * @author      Martine Lenders <mlenders@inf.fu-berlin.de>
+ *
+ * @}
+ */
+
+#include <stdbool.h>
+#include <inttypes.h>
+#include <stdio.h>
+
+#include "atomic.h"
+#include "byteorder.h"
+#include "net/icmpv6.h"
+#include "net/ipv6.h"
+#include "xtimer.h"
+
+#include "uip.h"
+#include "uip-icmp6.h"
+
+#include "common.h"
+
+#define ECHO_ID     (0xd1e9)
+
+static struct uip_icmp6_echo_reply_notification recv_ntfy = { NULL, NULL };
+static uint16_t seq = 0;
+static atomic_int_t received, num;
+
+static bool _waiting = true;
+
+static inline icmpv6_echo_t *uip_icmp_buf(void)
+{
+    return ((icmpv6_echo_t *)&uip_buf[uip_l2_l3_hdr_len]);
+}
+
+static inline int max_len(void)
+{
+    return UIP_BUFSIZE - (((uint8_t *)uip_icmp_buf()) - uip_buf) -
+           sizeof(icmpv6_echo_t);
+}
+
+static int ping_send(const uip_ipaddr_t *dst, int payload_len)
+{
+    int len = payload_len;
+    icmpv6_echo_t *ping = uip_icmp_buf();
+
+    ping->id = byteorder_htons(ECHO_ID);
+
+    if (payload_len > max_len()) {
+        puts("Payload too long for buffer.");
+        return -1;
+    }
+
+    for (network_uint16_t *payload = (network_uint16_t *)(ping + 1);
+         len >= 0;
+         payload++, len -= 2) {
+        *payload = byteorder_htons(seq);
+    }
+
+    ping->seq = byteorder_htons(seq++);
+
+    uip_icmp6_send((const uip_ipaddr_t *)dst, ICMPV6_ECHO_REQ, 0,
+                   payload_len + (sizeof(icmpv6_echo_t) - sizeof(icmpv6_hdr_t)));
+
+    return 0;
+}
+
+static void handle_reply(uip_ipaddr_t *source, uint8_t ttl, uint8_t *data,
+                         uint16_t datalen)
+{
+    char addr_str[IPV6_ADDR_MAX_STR_LEN];
+    icmpv6_echo_t *ping = (icmpv6_echo_t *)data;
+
+    _waiting = false;
+
+    ipv6_addr_to_str(addr_str, (ipv6_addr_t *)source, sizeof(addr_str));
+
+    atomic_inc(&received);
+    printf("%" PRIu16 " bytes from %s: icmp_seq=%" PRIu16 " ttl=%u quota=%i/%i\n",
+           datalen, addr_str, byteorder_ntohs(ping->seq), (unsigned)ttl,
+           ATOMIC_VALUE(received), ATOMIC_VALUE(num));
+}
+
+void usage(char *cmd)
+{
+    printf("usage: %s <dst> [<num>] [<payload_len>]\n", cmd);
+}
+
+int ping_cmd(int argc, char **argv)
+{
+    ipv6_addr_t dst;
+    int payload_len, _num;
+
+    if ((argc < 2) || (ipv6_addr_from_str(&dst, argv[1]) == NULL)) {
+        usage(argv[0]);
+        return 1;
+    }
+    if ((argc < 3) || ((_num = atoi(argv[2])) == 0)) {
+        _num = 3;
+    }
+    if ((argc < 4) || ((payload_len = atoi(argv[3])) == 0)) {
+        payload_len = 16;
+    }
+    atomic_set_to_zero(&num);
+    atomic_cas(&num, 0, _num);
+    atomic_set_to_zero(&received);
+    seq = 0;
+    if (recv_ntfy.callback == NULL) {
+        uip_icmp6_echo_reply_callback_add(&recv_ntfy, handle_reply);
+    }
+    for (uint16_t i = 0; i < _num; i++) {
+        _waiting = true;
+        ping_send((uip_ipaddr_t *)&dst, payload_len);
+        xtimer_usleep(1000000);
+        if (_waiting) {
+            puts("Timeout");
+        }
+    }
+
+    return 0;
+}
+
+/** @} */
diff --git a/tests/emb6/udp.c b/tests/emb6/udp.c
new file mode 100644
index 0000000000000000000000000000000000000000..748110cc6eef71389d8f387fdc75283d10ec66e2
--- /dev/null
+++ b/tests/emb6/udp.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2015 Freie Universität Berlin
+ *
+ * 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     examples
+ * @{
+ *
+ * @file
+ * @brief       Demonstrating the sending and receiving of UDP data over POSIX sockets.
+ *
+ * @author      Martine Lenders <mlenders@inf.fu-berlin.de>
+ *
+ * @}
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include "common.h"
+#include "od.h"
+#include "net/af.h"
+#include "net/conn/udp.h"
+#include "net/ipv6.h"
+#include "thread.h"
+#include "xtimer.h"
+
+#ifdef MODULE_CONN_UDP
+static char conn_inbuf[CONN_INBUF_SIZE];
+static bool server_running;
+static conn_udp_t server_conn;
+static char server_stack[THREAD_STACKSIZE_DEFAULT];
+static msg_t server_msg_queue[SERVER_MSG_QUEUE_SIZE];
+
+static void *_server_thread(void *args)
+{
+    ipv6_addr_t server_addr = IPV6_ADDR_UNSPECIFIED;
+    uint16_t port;
+    int res;
+
+    msg_init_queue(server_msg_queue, SERVER_MSG_QUEUE_SIZE);
+    /* parse port */
+    port = (uint16_t)atoi((char *)args);
+    if ((res = conn_udp_create(&server_conn, &server_addr,
+                               sizeof(server_addr), AF_INET6, port)) < 0) {
+        printf("Unable to open UDP server on port %" PRIu16 " (error code %d)\n",
+               port, -res);
+        return NULL;
+    }
+    server_running = true;
+    printf("Success: started UDP server on port %" PRIu16 "\n", port);
+    while (1) {
+        int res;
+        ipv6_addr_t src;
+        size_t src_len = sizeof(ipv6_addr_t);
+        uint16_t sport;
+        if ((res = conn_udp_recvfrom(&server_conn, conn_inbuf, sizeof(conn_inbuf), &src,
+                                     &src_len, &sport)) < 0) {
+            puts("Error on receive");
+        }
+        else if (res == 0) {
+            puts("No data received");
+        }
+        else {
+            char addrstr[IPV6_ADDR_MAX_STR_LEN];
+            printf("Received from [%s]:%" PRIu16 ":\n", ipv6_addr_to_str(addrstr, &src,
+                                                                         sizeof(addrstr)), sport);
+            od_hex_dump(conn_inbuf, res, 0);
+        }
+    }
+    return NULL;
+}
+
+static int udp_send(char *addr_str, char *port_str, char *data, unsigned int num,
+                    unsigned int delay)
+{
+    ipv6_addr_t src = IPV6_ADDR_UNSPECIFIED, dst;
+    uint16_t port;
+    uint8_t byte_data[strlen(data) / 2];
+    size_t data_len;
+
+    /* parse destination address */
+    if (ipv6_addr_from_str(&dst, addr_str) == NULL) {
+        puts("Error: unable to parse destination address");
+        return 1;
+    }
+    /* parse port */
+    port = (uint16_t)atoi(port_str);
+    data_len = hex2ints(byte_data, data);
+    for (unsigned int i = 0; i < num; i++) {
+        if (conn_udp_sendto(byte_data, data_len, &src, sizeof(src), (struct sockaddr *)&dst,
+                            sizeof(dst), AF_INET6, port, port) < 0) {
+            puts("could not send");
+        }
+        else {
+            printf("Success: send %u byte to [%s]:%" PRIu16 ")\n",
+                   (unsigned)data_len, addr_str, port);
+        }
+        xtimer_usleep(delay);
+    }
+    return 0;
+}
+
+static int udp_start_server(char *port_str)
+{
+    if (thread_create(server_stack, sizeof(server_stack), THREAD_PRIORITY_MAIN - 1,
+                      THREAD_CREATE_STACKTEST, _server_thread, port_str,
+                      "UDP server") <= KERNEL_PID_UNDEF) {
+        return 1;
+    }
+    return 0;
+}
+
+int udp_cmd(int argc, char **argv)
+{
+    if (argc < 2) {
+        printf("usage: %s [send|server]\n", argv[0]);
+        return 1;
+    }
+
+    if (strcmp(argv[1], "send") == 0) {
+        uint32_t num = 1;
+        uint32_t delay = 1000000;
+        if (argc < 5) {
+            printf("usage: %s send <addr> <port> <hex data> [<num> [<delay in us>]]\n",
+                   argv[0]);
+            return 1;
+        }
+        if (argc > 5) {
+            num = (uint32_t)atoi(argv[5]);
+        }
+        if (argc > 6) {
+            delay = (uint32_t)atoi(argv[6]);
+        }
+        return udp_send(argv[2], argv[3], argv[4], num, delay);
+    }
+    else if (strcmp(argv[1], "server") == 0) {
+        if (argc < 3) {
+            printf("usage: %s server [start|stop]\n", argv[0]);
+            return 1;
+        }
+        if (strcmp(argv[2], "start") == 0) {
+            if (argc < 4) {
+                printf("usage %s server start <port>\n", argv[0]);
+                return 1;
+            }
+            return udp_start_server(argv[3]);
+        }
+        else {
+            puts("error: invalid command");
+            return 1;
+        }
+    }
+    else {
+        puts("error: invalid command");
+        return 1;
+    }
+}
+#else
+typedef int dont_be_pedantic;
+#endif
+
+/** @} */