diff --git a/sys/include/net/gnrc/ipv6/netif.h b/sys/include/net/gnrc/ipv6/netif.h
index ac0e796b51496f80f1e29a0482cca596c34ec214..6ac08883979dd775c0801d8e4c1c28b0a48c1d1b 100644
--- a/sys/include/net/gnrc/ipv6/netif.h
+++ b/sys/include/net/gnrc/ipv6/netif.h
@@ -269,7 +269,7 @@ typedef struct {
     uint16_t flags;         /**< flags for 6LoWPAN and Neighbor Discovery */
     uint16_t mtu;           /**< Maximum Transmission Unit (MTU) of the interface */
     uint8_t cur_hl;         /**< current hop limit for the interface */
-#ifdef MODULE_GNRC_NDP_HOST
+#if defined(MODULE_GNRC_NDP_HOST) || defined(MODULE_GNRC_SIXLOWPAN_ND)
     /**
      * @brief   Counter for send router solicitations.
      */
diff --git a/sys/net/gnrc/network_layer/ipv6/gnrc_ipv6.c b/sys/net/gnrc/network_layer/ipv6/gnrc_ipv6.c
index 0f876f2425f52d7187f412e1486d57488c6964af..19edf024ff350be6d98f186ef362027e32b79f31 100644
--- a/sys/net/gnrc/network_layer/ipv6/gnrc_ipv6.c
+++ b/sys/net/gnrc/network_layer/ipv6/gnrc_ipv6.c
@@ -19,9 +19,11 @@
 #include "byteorder.h"
 #include "cpu_conf.h"
 #include "kernel_types.h"
-#include "net/gnrc/icmpv6.h"
 #include "net/gnrc.h"
+#include "net/gnrc/icmpv6.h"
 #include "net/gnrc/ndp.h"
+#include "net/gnrc/sixlowpan/ctx.h"
+#include "net/gnrc/sixlowpan/nd.h"
 #include "net/protnum.h"
 #include "thread.h"
 #include "utlist.h"
@@ -228,7 +230,21 @@ static void *_event_loop(void *args)
                 gnrc_ndp_host_retrans_rtr_sol((gnrc_ipv6_netif_t *)msg.content.ptr);
                 break;
 #endif
-
+#ifdef MODULE_GNRC_SIXLOWPAN_ND
+            case GNRC_SIXLOWPAN_ND_MSG_MC_RTR_SOL:
+                DEBUG("ipv6: Multicast router solicitation event received\n");
+                gnrc_sixlowpan_nd_mc_rtr_sol((gnrc_ipv6_netif_t *)msg.content.ptr);
+                break;
+            case GNRC_SIXLOWPAN_ND_MSG_UC_RTR_SOL:
+                DEBUG("ipv6: Unicast router solicitation event received\n");
+                gnrc_sixlowpan_nd_uc_rtr_sol((gnrc_ipv6_nc_t *)msg.content.ptr);
+                break;
+            case GNRC_SIXLOWPAN_ND_MSG_DELETE_CTX:
+                DEBUG("ipv6: Delete 6LoWPAN context event received\n");
+                gnrc_sixlowpan_ctx_remove(((((gnrc_sixlowpan_ctx_t *)msg.content.ptr)->flags_id) &
+                                           GNRC_SIXLOWPAN_CTX_FLAGS_CID_MASK));
+                break;
+#endif
             default:
                 break;
         }
@@ -497,16 +513,24 @@ static inline kernel_pid_t _next_hop_l2addr(uint8_t *l2addr, uint8_t *l2addr_len
                                             kernel_pid_t iface, ipv6_addr_t *dst,
                                             gnrc_pktsnip_t *pkt)
 {
-#ifdef MODULE_GNRC_NDP_NODE
-    return gnrc_ndp_node_next_hop_l2addr(l2addr, l2addr_len, iface, dst, pkt);
-#else
+#if defined(MODULE_GNRC_SIXLOWPAN_ND)
+    (void)pkt;
+    iface = gnrc_sixlowpan_nd_next_hop_l2addr(l2addr, l2addr_len, iface, dst);
+    if (iface <= KERNEL_PID_UNDEF) {
+        return iface;
+    }
+#endif
+#if defined(MODULE_GNRC_NDP_NODE)
+    iface = gnrc_ndp_node_next_hop_l2addr(l2addr, l2addr_len, iface, dst, pkt);
+#elif !defined(MODULE_GNRC_SIXLOWPAN_ND)
+    iface = KERNEL_PID_UNDEF;
     (void)l2addr;
     (void)iface;
     (void)dst;
     (void)pkt;
     *l2addr_len = 0;
-    return KERNEL_PID_UNDEF;
 #endif
+    return iface;
 }
 
 static void _send(gnrc_pktsnip_t *pkt, bool prep_hdr)
diff --git a/sys/net/gnrc/network_layer/ipv6/netif/gnrc_ipv6_netif.c b/sys/net/gnrc/network_layer/ipv6/netif/gnrc_ipv6_netif.c
index 2967a07962d269a0aa86e92bf0888fe47c897722..cc7d7fb9f5660c22dabd0390dd7357865708ceb7 100644
--- a/sys/net/gnrc/network_layer/ipv6/netif/gnrc_ipv6_netif.c
+++ b/sys/net/gnrc/network_layer/ipv6/netif/gnrc_ipv6_netif.c
@@ -29,6 +29,7 @@
 #include "net/gnrc/netapi.h"
 #include "net/gnrc/netif.h"
 #include "net/gnrc/netif/hdr.h"
+#include "net/gnrc/sixlowpan/nd.h"
 #include "net/gnrc/sixlowpan/netif.h"
 
 #include "net/gnrc/ipv6/netif.h"
@@ -90,8 +91,6 @@ static ipv6_addr_t *_add_addr_to_entry(gnrc_ipv6_netif_t *entry, const ipv6_addr
         tmp_addr->flags |= GNRC_IPV6_NETIF_ADDR_FLAGS_NON_UNICAST;
     }
     else {
-        ipv6_addr_t sol_node;
-
         if (!ipv6_addr_is_link_local(addr)) {
             /* add also corresponding link-local address */
             ipv6_addr_t ll_addr;
@@ -117,9 +116,18 @@ static ipv6_addr_t *_add_addr_to_entry(gnrc_ipv6_netif_t *entry, const ipv6_addr
         else {
             tmp_addr->flags |= GNRC_IPV6_NETIF_ADDR_FLAGS_NDP_ON_LINK;
         }
-
-        ipv6_addr_set_solicited_nodes(&sol_node, addr);
-        _add_addr_to_entry(entry, &sol_node, IPV6_ADDR_BIT_LEN, 0);
+#if defined(MODULE_GNRC_NDP_NODE) || defined(MODULE_GNRC_SIXLOWPAN_ND)
+        /* add solicited-nodes multicast address for new address if interface is not a
+         * 6LoWPAN host interface (see: https://tools.ietf.org/html/rfc6775#section-5.2) */
+        if (!(entry->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) ||
+            (entry->flags & GNRC_IPV6_NETIF_FLAGS_ROUTER)) {
+            ipv6_addr_t sol_node;
+            ipv6_addr_set_solicited_nodes(&sol_node, addr);
+            _add_addr_to_entry(entry, &sol_node, IPV6_ADDR_BIT_LEN, 0);
+        }
+#endif
+        /* TODO: send NS with ARO on 6LoWPAN interfaces, but not so many and only for the new
+         *       source address. */
     }
 
     return &(tmp_addr->addr);
@@ -804,6 +812,12 @@ void gnrc_ipv6_netif_init_by_dev(void)
 #if (defined(MODULE_GNRC_NDP_ROUTER) || defined(MODULE_GNRC_SIXLOWPAN_ND_ROUTER))
         gnrc_ipv6_netif_set_router(ipv6_if, true);
 #endif
+#ifdef MODULE_GNRC_SIXLOWPAN_ND
+        if (ipv6_if->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) {
+            gnrc_sixlowpan_nd_init(ipv6_if);
+            continue;   /* skip gnrc_ndp_host_init() */
+        }
+#endif
 #ifdef MODULE_GNRC_NDP_HOST
         /* start periodic router solicitations */
         gnrc_ndp_host_init(ipv6_if);
diff --git a/sys/net/gnrc/network_layer/ndp/gnrc_ndp.c b/sys/net/gnrc/network_layer/ndp/gnrc_ndp.c
index 42683a64698fdaaf8338ddbc3214e237dca3d170..4b246e9caef67a03b3a8efe88aa198fb2e98a774 100644
--- a/sys/net/gnrc/network_layer/ndp/gnrc_ndp.c
+++ b/sys/net/gnrc/network_layer/ndp/gnrc_ndp.c
@@ -23,7 +23,9 @@
 #include "net/ipv6/ext/rh.h"
 #include "net/gnrc/icmpv6.h"
 #include "net/gnrc/ipv6.h"
+#include "net/gnrc/sixlowpan/nd.h"
 #include "net/gnrc.h"
+#include "net/sixlowpan/nd.h"
 #include "random.h"
 #include "utlist.h"
 #include "thread.h"
@@ -175,9 +177,14 @@ void gnrc_ndp_nbr_adv_handle(kernel_pid_t iface, gnrc_pktsnip_t *pkt,
                     /* invalid target link-layer address option */
                     return;
                 }
-
                 break;
-
+#ifdef MODULE_GNRC_SIXLOWPAN_ND
+            case NDP_OPT_AR:
+                /* address registration option is always ignored when invalid */
+                gnrc_sixlowpan_nd_opt_ar_handle(iface, ipv6, nbr_adv->type,
+                                                (sixlowpan_nd_opt_ar_t *)opt, NULL, 0);
+                break;
+#endif
             default:
                 /* silently discard all other options */
                 break;
@@ -194,6 +201,13 @@ void gnrc_ndp_nbr_adv_handle(kernel_pid_t iface, gnrc_pktsnip_t *pkt,
     }
 
     if (l2tgt_len != -ENOTSUP) {
+#ifdef MODULE_GNRC_SIXLOWPAN_ND
+        /* check if entry wasn't removed by ARO, ideally there should not be any TL2A in here */
+        nc_entry = gnrc_ipv6_nc_get(iface, &nbr_adv->tgt);
+        if (nc_entry == NULL) {
+            return;
+        }
+#endif
         if (gnrc_ipv6_nc_get_state(nc_entry) == GNRC_IPV6_NC_STATE_INCOMPLETE) {
             if (_pkt_has_l2addr(netif_hdr) && (l2tgt_len == 0)) {
                 /* link-layer has addresses, but no TLLAO supplied: discard silently
@@ -358,6 +372,9 @@ void gnrc_ndp_rtr_adv_handle(kernel_pid_t iface, gnrc_pktsnip_t *pkt, ipv6_hdr_t
     gnrc_ipv6_nc_t *nc_entry = NULL;
     gnrc_ipv6_netif_t *if_entry = gnrc_ipv6_netif_get(iface);
     uint8_t l2src[GNRC_IPV6_NC_L2_ADDR_MAX];
+#ifdef MODULE_GNRC_SIXLOWPAN_ND
+    uint32_t next_rtr_sol = 0;
+#endif
     int sicmpv6_size = (int)icmpv6_size, l2src_len = 0;
     uint16_t opt_offset = 0;
 
@@ -388,9 +405,12 @@ void gnrc_ndp_rtr_adv_handle(kernel_pid_t iface, gnrc_pktsnip_t *pkt, ipv6_hdr_t
     }
     /* set router life timer */
     if (rtr_adv->ltime.u16 != 0) {
+        uint16_t ltime = byteorder_ntohs(rtr_adv->ltime);
+#ifdef MODULE_GNRC_SIXLOWPAN_ND
+        next_rtr_sol = ltime;
+#endif
         vtimer_remove(&nc_entry->rtr_timeout);
-        vtimer_set_msg(&nc_entry->rtr_timeout,
-                       timex_set(byteorder_ntohs(rtr_adv->ltime), 0),
+        vtimer_set_msg(&nc_entry->rtr_timeout, timex_set(ltime, 0),
                        thread_getpid(), GNRC_NDP_MSG_RTR_TIMEOUT, nc_entry);
     }
     /* set current hop limit from message if available */
@@ -437,10 +457,51 @@ void gnrc_ndp_rtr_adv_handle(kernel_pid_t iface, gnrc_pktsnip_t *pkt, ipv6_hdr_t
                     /* invalid prefix information option */
                     return;
                 }
+#ifdef MODULE_GNRC_SIXLOWPAN_ND
+                if (byteorder_ntohl(((ndp_opt_pi_t *)opt)->valid_ltime) <
+                    next_rtr_sol) {
+                    next_rtr_sol = byteorder_ntohl(((ndp_opt_pi_t *)opt)->valid_ltime);
+                }
+#endif
+                break;
+#ifdef MODULE_GNRC_SIXLOWPAN_ND
+            case NDP_OPT_6CTX:
+                if (!gnrc_sixlowpan_nd_opt_6ctx_handle(rtr_adv->type,
+                                                       (sixlowpan_nd_opt_6ctx_t *)opt)) {
+                    /* invalid 6LoWPAN context option */
+                    return;
+                }
+                if (byteorder_ntohs(((sixlowpan_nd_opt_6ctx_t *)opt)->ltime) <
+                    (next_rtr_sol / 60)) {
+                    next_rtr_sol = byteorder_ntohs(((sixlowpan_nd_opt_6ctx_t *)opt)->ltime) * 60;
+                }
+
                 break;
+#endif
         }
     }
+#if ENABLE_DEBUG && defined(MODULE_NG_SIXLOWPAN_ND)
+    if ((if_entry->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) && (l2src_len <= 0)) {
+        DEBUG("ndp: Router advertisement did not contain any source address information\n");
+    }
+#endif
     _stale_nc(iface, &ipv6->src, l2src, l2src_len);
+#ifdef MODULE_NG_SIXLOWPAN_ND
+    if (if_entry->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) {
+        timex_t t = { 0, GNRC_NDP_RETRANS_TIMER };
+        /* stop multicast router solicitation retransmission timer */
+        vtimer_remove(&if_entry->rtr_sol_timer);
+        /* 3/4 of the time should be "well before" enough the respective timeout
+         * not to run out; see https://tools.ietf.org/html/rfc6775#section-5.4.3 */
+        next_rtr_sol *= 3;
+        next_rtr_sol >>= 2;
+        gnrc_sixlowpan_nd_rtr_sol_reschedule(nc_entry, next_rtr_sol);
+        gnrc_ndp_internal_send_nbr_sol(ifs[i], &nc_entry->ipv6_addr, &nc_entry->ipv6_addr);
+        vtimer_remove(&nc_entry->nbr_sol_timer);
+        vtimer_set_msg(&nc_entry->nbr_sol_timer, t, gnrc_ipv6_pid, GNRC_NDP_MSG_NBR_SOL_RETRANS,
+                       nc_entry);
+    }
+#endif
 }
 
 void gnrc_ndp_retrans_nbr_sol(gnrc_ipv6_nc_t *nc_entry)
diff --git a/sys/net/gnrc/network_layer/ndp/internal/gnrc_ndp_internal.c b/sys/net/gnrc/network_layer/ndp/internal/gnrc_ndp_internal.c
index 9b68742da0dc8b6e360a13d0a5ed1904bad02c2a..0125611f899ae68e240c416b4984849311f8f3b0 100644
--- a/sys/net/gnrc/network_layer/ndp/internal/gnrc_ndp_internal.c
+++ b/sys/net/gnrc/network_layer/ndp/internal/gnrc_ndp_internal.c
@@ -14,8 +14,10 @@
 
 #include <stdlib.h>
 
+#include "net/eui64.h"
 #include "net/gnrc/ipv6.h"
 #include "net/gnrc/ndp.h"
+#include "net/gnrc/sixlowpan/nd.h"
 #include "random.h"
 #include "timex.h"
 #include "vtimer.h"
@@ -228,8 +230,17 @@ void gnrc_ndp_internal_send_nbr_adv(kernel_pid_t iface, ipv6_addr_t *tgt, ipv6_a
 void gnrc_ndp_internal_send_nbr_sol(kernel_pid_t iface, ipv6_addr_t *tgt,
                                     ipv6_addr_t *dst)
 {
+#ifdef MODULE_GNRC_SIXLOWPAN_ND
+    gnrc_ipv6_netif_t *ipv6_iface = gnrc_ipv6_netif_get(iface);
+    assert(ipv6_iface != NULL);
+#endif
     gnrc_pktsnip_t *hdr, *pkt = NULL;
     ipv6_addr_t *src = NULL;
+    /* both suppressions, since they are needed in the MODULE_GNRC_SIXLOWPAN_ND branch */
+    /* cppcheck-suppress variableScope */
+    uint8_t l2src[8];
+    /* cppcheck-suppress variableScope */
+    size_t l2src_len = 0;
 
     DEBUG("ndp internal: send neighbor solicitation (iface: %" PRIkernel_pid ", tgt: %s, ",
           iface, ipv6_addr_to_str(addr_str, tgt, sizeof(addr_str)));
@@ -237,8 +248,6 @@ void gnrc_ndp_internal_send_nbr_sol(kernel_pid_t iface, ipv6_addr_t *tgt,
 
     /* check if there is a fitting source address to target */
     if ((src = gnrc_ipv6_netif_find_best_src_addr(iface, tgt)) != NULL) {
-        uint8_t l2src[8];
-        size_t l2src_len;
         l2src_len = _get_l2src(iface, l2src, sizeof(l2src));
 
         if (l2src_len > 0) {
@@ -253,6 +262,27 @@ void gnrc_ndp_internal_send_nbr_sol(kernel_pid_t iface, ipv6_addr_t *tgt,
         }
     }
 
+#ifdef MODULE_GNRC_SIXLOWPAN_ND
+    if (ipv6_iface->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) {
+        if (l2src_len != sizeof(eui64_t)) {
+            l2src_len = (uint16_t)gnrc_netapi_get(iface, NETOPT_ADDRESS_LONG, 0, l2src,
+                                                  sizeof(l2src));
+            if (l2src_len != sizeof(eui64_t)) {
+                DEBUG("ndp internal: can't get EUI-64 of the interface\n");
+                gnrc_pktbuf_release(pkt);
+                return;
+            }
+        }
+        hdr = gnrc_sixlowpan_nd_opt_ar_build(0, GNRC_SIXLOWPAN_ND_AR_LTIME, (eui64_t *)l2src, pkt);
+        if (hdr == NULL) {
+            DEBUG("ndp internal: error allocatin Address Registration option.\n");
+            gnrc_pktbuf_release(pkt);
+            return;
+        }
+        pkt = hdr;
+    }
+#endif
+
     hdr = gnrc_ndp_nbr_sol_build(tgt, pkt);
 
     if (hdr == NULL) {
@@ -571,6 +601,13 @@ bool gnrc_ndp_internal_pi_opt_handle(kernel_pid_t iface, uint8_t icmpv6_type,
         /* else discard silently */
         return true;
     }
+#ifdef MODULE_GNRC_SIXLOWPAN_ND
+    if ((gnrc_ipv6_netif_get(iface)->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) &&
+        (pi_opt->flags & NDP_OPT_PI_FLAGS_L)) {
+        /* ignore: see https://tools.ietf.org/html/rfc6775#section-5.4 */
+        return true;
+    }
+#endif
     prefix = gnrc_ipv6_netif_find_addr(iface, &pi_opt->prefix);
     if (((prefix == NULL) ||
          (gnrc_ipv6_netif_addr_get(prefix)->prefix_len != pi_opt->prefix_len)) &&