diff --git a/Makefile.dep b/Makefile.dep
index 6dafb9f0e139866ebcf53a826ecbb8a1530f8502..9d00969c133f3b39150f1c8f157fb5c94277bcc1 100644
--- a/Makefile.dep
+++ b/Makefile.dep
@@ -53,6 +53,10 @@ ifneq (,$(filter gnrc_tftp,$(USEMODULE)))
   USEMODULE += xtimer
 endif
 
+ifneq (,$(filter gnrc_rpl_p2p,$(USEMODULE)))
+  USEMODULE += gnrc_rpl
+endif
+
 ifneq (,$(filter gnrc_rpl,$(USEMODULE)))
   USEMODULE += fib
   USEMODULE += gnrc_ipv6_router_default
diff --git a/sys/include/net/gnrc/rpl/p2p.h b/sys/include/net/gnrc/rpl/p2p.h
new file mode 100644
index 0000000000000000000000000000000000000000..05d3f588b60091ab23851a699b1fba692269e728
--- /dev/null
+++ b/sys/include/net/gnrc/rpl/p2p.h
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2016 Cenk Gündoğan <mail@cgundogan.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.
+ */
+
+/**
+ * @defgroup    net_rpl_p2p Reactive Discovery of P2P Routes in LLNs
+ * @ingroup     net_gnrc_rpl
+ * @brief       Implementation of P2P-RPL
+ * @see <a href="https://tools.ietf.org/html/rfc6997">
+ *          RFC 6997
+ *      </a>
+ * @{
+ *
+ * @file
+ * @brief       Definititions for P2P-RPL
+ *
+ * @author  Cenk Gündoğan <mail@cgundogan.de>
+ */
+#ifndef GNRC_RPL_P2P_H_
+#define GNRC_RPL_P2P_H_
+
+#include "net/ipv6/addr.h"
+#include "net/gnrc.h"
+#include "net/gnrc/rpl/structs.h"
+#include "net/gnrc/rpl/p2p_structs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief   P2P-RPL Mode of Operation
+ */
+#define GNRC_RPL_P2P_MOP        (0x04)
+
+/**
+ * @brief   Default lifetime of the P2P-RPL DODAG, encoded
+ * @see <a href="https://tools.ietf.org/html/rfc6997#section-7">
+ *          RFC 6997, section 7, P2P Route Discovery Option (P2P-RDO)
+ *      </a>
+ */
+#define GNRC_RPL_P2P_LIFETIME   (0x02)
+
+/**
+ * @brief   Number of elided prefix octets from the target field and address vector
+ * @see <a href="https://tools.ietf.org/html/rfc6997#section-7">
+ *          RFC 6997, section 7, P2P Route Discovery Option (P2P-RDO)
+ *      </a>
+ */
+#define GNRC_RPL_P2P_COMPR      (0)
+
+/**
+ * @brief   Maximum rank in the DODAG during the route discovery
+ * @see <a href="https://tools.ietf.org/html/rfc6997#section-7">
+ *          RFC 6997, section 7, P2P Route Discovery Option (P2P-RDO)
+ *      </a>
+ */
+#define GNRC_RPL_P2P_MAX_RANK   (0)
+
+/**
+ * @name Trickle parameters
+ * @see <a href="https://tools.ietf.org/html/rfc6997#section-6.1">
+ *          RFC 6997, section 6.1, Setting a P2P Mode DIO
+ *      </a>
+ * @{
+ */
+#define GNRC_RPL_P2P_DEFAULT_DIO_INTERVAL_MIN           (6)
+#define GNRC_RPL_P2P_DEFAULT_DIO_REDUNDANCY_CONSTANT    (1)
+/** @} */
+
+/**
+ * @name Default parent and route entry lifetime
+ * default lifetime will be multiplied by the lifetime unit to obtain the resulting lifetime
+ * @{
+ */
+#define GNRC_RPL_P2P_DEFAULT_LIFETIME   (0xFF)
+#define GNRC_RPL_P2P_LIFETIME_UNIT      (0xFFFF)
+/** @} */
+
+/**
+ * @brief   P2P-RPL RDO DIO option type
+ * @see     <a href="https://tools.ietf.org/html/rfc6997#section-7">
+ *              RFC 6997, section 7, P2P Route Discovery Option (P2P-RDO)
+ *          </a>
+ */
+#define GNRC_RPL_P2P_OPT_RDO    (0x0A)
+
+/**
+ *  @brief  DRO ICMPv6 code
+ *  @see <a href="https://tools.ietf.org/html/rfc6997#section-8">
+ *          RFC 6997, section 8, The P2P Discovery Reply Object (P2P-DRO)
+ *      </a>
+ */
+#define GNRC_RPL_P2P_ICMPV6_CODE_DRO    (0x04)
+
+/**
+ *  @brief  DRO-ACK ICMPv6 code
+ *  @see <a href="https://tools.ietf.org/html/rfc6997#section-10">
+ *          RFC 6997, section 10, The P2P Discovery Reply Object Acknowledgement (P2P-DRO-ACK)
+ *      </a>
+ */
+#define GNRC_RPL_P2P_ICMPV6_CODE_DRO_ACK    (0x05)
+
+/**
+ *  @brief  Time in seconds to wait before sending a DRO
+ */
+#define GNRC_RPL_P2P_DRO_DELAY  (4)
+
+/**
+ *  @brief  Message type for handling DRO sending
+ */
+#define GNRC_RPL_P2P_MSG_TYPE_DRO_HANDLE    (0x09A0)
+
+/**
+ *  @brief  Lookup table used to decode/encode the lifetime values
+ */
+extern const uint8_t gnrc_rpl_p2p_lifetime_lookup[4];
+
+/**
+ * @brief Initialization of a P2P-RPL Instance as root node.
+ *
+ * @param[in] instance_id       Id of the instance
+ * @param[in] dodag_id          Id of the DODAG
+ * @param[in] target            Target of the P2P-RPL routes discovery
+ * @param[in] gen_inst_id       Flag indicating whether to generate a local isntance id.
+ *                              If true, @p instance_id will be ignored
+ *
+ * @return  Pointer to the new Instance, on success.
+ * @return  NULL, otherwise.
+ */
+gnrc_rpl_instance_t *gnrc_rpl_p2p_root_init(uint8_t instance_id, ipv6_addr_t *dodag_id,
+                                            ipv6_addr_t *target, bool gen_inst_id);
+
+/**
+ * @brief Build an RDO
+ *
+ * @param[in,out] pkt           The RDO will be added to the @p pkt
+ * @param[in] p2p_ext           Pointer to the P2P-RPL DODAG extension
+ */
+gnrc_pktsnip_t *gnrc_rpl_p2p_rdo_build(gnrc_pktsnip_t *pkt, gnrc_rpl_p2p_ext_t *p2p_ext);
+
+/**
+ * @brief Parse an RDO
+ *
+ * @param[in] rdo               The RDO to parse from.
+ * @param[in] p2p_ext           Pointer to the P2P-RPL DODAG extension
+ */
+void gnrc_rpl_p2p_rdo_parse(gnrc_rpl_p2p_opt_rdo_t *rdo, gnrc_rpl_p2p_ext_t *p2p_ext);
+
+/**
+ * @brief Send a DRO control message
+ *
+ * @param[in] pkt               The ICMPv6 packet to send. Can be NULL.
+ * @param[in] p2p_ext           Pointer to the P2P-RPL DODAG extension
+ */
+void gnrc_rpl_p2p_send_DRO(gnrc_pktsnip_t *pkt, gnrc_rpl_p2p_ext_t *p2p_ext);
+
+/**
+ * @brief Receive and parse a DRO control message
+ *
+ * @param[in] pkt               The ICMPv6 packet to parse.
+ * @param[in] src               The source address of the IPv6 packet.
+ */
+void gnrc_rpl_p2p_recv_DRO(gnrc_pktsnip_t *pkt, ipv6_addr_t *src);
+
+/**
+ * @brief Updates the lifetime of the P2P Dodag and the delay of the DRO
+ */
+void gnrc_rpl_p2p_update(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GNRC_RPL_P2P_H_ */
+/** @} */
diff --git a/sys/include/net/gnrc/rpl/p2p_dodag.h b/sys/include/net/gnrc/rpl/p2p_dodag.h
new file mode 100644
index 0000000000000000000000000000000000000000..466c7b71a9252a661e4344ea12a3d2f7bef59677
--- /dev/null
+++ b/sys/include/net/gnrc/rpl/p2p_dodag.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2016 Cenk Gündoğan <mail@cgundogan.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 net_gnrc_rpl_p2p
+ * @{
+ *
+ * @file
+ * @brief       DODAG-related functions for P2P-RPL
+ *
+ * Header file, which defines all public known DODAG-related functions for P2P-RPL.
+ *
+ * @author      Cenk Gündoğan <mail@cgundogan.de>
+ */
+
+#ifndef GNRC_RPL_P2P_DODAG_H_
+#define GNRC_RPL_P2P_DODAG_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "net/gnrc/rpl/p2p_structs.h"
+
+/**
+ * @brief   Number of P2P RPL DODAG extensions
+ */
+#ifndef GNRC_RPL_P2P_EXTS_NUMOF
+#define GNRC_RPL_P2P_EXTS_NUMOF (1)
+#endif
+
+/**
+ * @brief   P2P-RPL DODAG extensions table
+ */
+extern gnrc_rpl_p2p_ext_t gnrc_rpl_p2p_exts[GNRC_RPL_P2P_EXTS_NUMOF];
+
+/**
+ * @brief   Allocate a free P2P-RPL DODAG extension
+ *
+ * @return  Pointer to a free P2P-RPL DODAG extension
+ * @return  NULL, if no free P2P-RPL DODAG extension is available
+ */
+gnrc_rpl_p2p_ext_t *gnrc_rpl_p2p_ext_new(gnrc_rpl_dodag_t *dodag);
+
+/**
+ * @brief   Free the P2P-RPL DODAG extension of @p dodag
+ *
+ * @param[in] dodag     Pointer to a P2P-RPL DODAG
+ */
+void gnrc_rpl_p2p_ext_remove(gnrc_rpl_dodag_t *dodag);
+
+/**
+ * @brief   Get the appropriate P2P-RPL DODAG extension of the @p dodag
+ *
+ * @param[in] dodag     Pointer to a P2P-RPL DODAG
+ *
+ * @return  Pointer to a P2P-RPL DODAG extension
+ * @return  NULL, if no P2P-RPL DODAG extension is available for @p dodag
+ */
+gnrc_rpl_p2p_ext_t *gnrc_rpl_p2p_ext_get(gnrc_rpl_dodag_t *dodag);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GNRC_RPL_P2P_DODAG_H_ */
+/**
+ * @}
+ */
diff --git a/sys/include/net/gnrc/rpl/p2p_structs.h b/sys/include/net/gnrc/rpl/p2p_structs.h
new file mode 100644
index 0000000000000000000000000000000000000000..69602baf456b9e43ef49ab1477718f06cc110c57
--- /dev/null
+++ b/sys/include/net/gnrc/rpl/p2p_structs.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2016 Cenk Gündoğan <mail@cgundogan.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 net_gnrc_rpl_p2p
+ * @{
+ *
+ * @file
+ * @brief       P2P-RPL data structs
+ *
+ * Header file, which defines all structs used by P2P-RPL.
+ *
+ * @author      Cenk Gündoğan <mail@cgundogan.de>
+ */
+
+#ifndef GNRC_RPL_P2P_STRUCTS_H_
+#define GNRC_RPL_P2P_STRUCTS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "net/ipv6/addr.h"
+#include "net/gnrc/rpl/structs.h"
+
+/**
+ * @brief   Address vector length in RDO DIO options and maximal hop count for the P2P-DODAG
+ */
+#define GNRC_RPL_P2P_ADDR_VEC_NUMOF    (8)
+
+/**
+ * @brief P2P Route Discovery Object (RDO) Option
+ * @see <a href="https://tools.ietf.org/html/rfc6997#section-7">
+ *          RFC 6997, section 7, P2P Route Discovery Option (P2P-RDO)
+ *      </a>
+ */
+typedef struct __attribute__((packed)) {
+    uint8_t type;                       /**< Option Type: 0x0a */
+    uint8_t length;                     /**< length of option, not including first two bytes */
+    uint8_t compr_flags;                /**< flags and number of elided prefix octets */
+    uint8_t lmn;                        /**< lifetime, maxrank/nexthop */
+    ipv6_addr_t target;                 /**< target address */
+} gnrc_rpl_p2p_opt_rdo_t;
+
+/**
+ * @brief P2P Discovery Reply Object (P2P-DRO)
+ * @see <a href="https://tools.ietf.org/html/rfc6997#section-8">
+ *          RFC 6997, section 8, P2P Discovery Reply Object (P2P-DRO)
+ *      </a>
+ */
+typedef struct __attribute__((packed)) {
+    uint8_t instance_id;        /**< id of the instance */
+    uint8_t version_number;     /**< version number of the DODAG */
+    network_uint16_t flags_rev; /**< flags and reserved */
+    ipv6_addr_t dodag_id;       /**< id of the dodag */
+} gnrc_rpl_p2p_dro_t;
+
+/**
+ * @brief P2P Discovery Reply Object Acknowledgement (P2P-DRO-ACK)
+ * @see <a href="https://tools.ietf.org/html/rfc6997#section-10">
+ *          RFC 6997, section 10, P2P Discovery Reply Object Acknowledgement (P2P-DRO-ACK)
+ *      </a>
+ */
+typedef struct __attribute__((packed)) {
+    uint8_t instance_id;        /**< id of the instance */
+    uint8_t version_number;     /**< version number of the DODAG */
+    network_uint16_t seq_rev;   /**< sequence number and reserved */
+    ipv6_addr_t dodag_id;       /**< id of the dodag */
+} gnrc_rpl_p2p_dro_ack_t;
+
+/**
+ * @brief Extended DODAG information for P2P-RPL
+ */
+typedef struct {
+    bool state;             /**< state: used / unused */
+    gnrc_rpl_dodag_t *dodag;/**< DODAG, which owns this P2P extension */
+    uint8_t compr;          /**< number of elided prefix octets */
+    uint8_t routes_numof;   /**< number of requested routes */
+    bool hop_by_hop;        /**< request hop-by-hop routes or source routes */
+    bool stop;              /**< stop route discovery */
+    bool reply;             /**< request P2P-DRO */
+    bool dro_ack;           /**< request P2P-DRO-ACK */
+    uint8_t lifetime_enc;   /**< encoded lifetime of the P2P-DODAG */
+    int8_t lifetime_sec;    /**< lifetime of the P2P-DODAG in seconds */
+    uint8_t maxrank;        /**< maximum rank the P2P-DODAG should span */
+    uint8_t dro_seq;        /**< sequence number of the P2P-DRO */
+    ipv6_addr_t target;     /**< target of the P2P route discovery */
+    bool for_me;            /**< true if this node is the target */
+    uint8_t addr_numof;     /**< number of addresses in the address vector */
+    int8_t dro_delay;       /**< delay DRO after it was requested in seconds */
+    ipv6_addr_t addr_vec[GNRC_RPL_P2P_ADDR_VEC_NUMOF];   /**< address vector */
+} gnrc_rpl_p2p_ext_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GNRC_RPL_P2P_STRUCTS_H_ */
+/**
+ * @}
+ */
diff --git a/sys/net/gnrc/Makefile b/sys/net/gnrc/Makefile
index e21de28ed5ea358b9874ac98904592cdd151d935..a4b69955ff01a060914103bb24ed56087544e2ad 100644
--- a/sys/net/gnrc/Makefile
+++ b/sys/net/gnrc/Makefile
@@ -85,6 +85,9 @@ endif
 ifneq (,$(filter gnrc_rpl_srh,$(USEMODULE)))
     DIRS += routing/rpl/srh
 endif
+ifneq (,$(filter gnrc_rpl_p2p,$(USEMODULE)))
+    DIRS += routing/rpl/p2p
+endif
 ifneq (,$(filter gnrc_sixlowpan,$(USEMODULE)))
     DIRS += network_layer/sixlowpan
 endif
diff --git a/sys/net/gnrc/routing/rpl/gnrc_rpl.c b/sys/net/gnrc/routing/rpl/gnrc_rpl.c
index 6acd978c2851f11a0a02016e31ca1dee2bcf8f79..f3420d9e412b8de736a1e9337dce989521b00984 100644
--- a/sys/net/gnrc/routing/rpl/gnrc_rpl.c
+++ b/sys/net/gnrc/routing/rpl/gnrc_rpl.c
@@ -21,6 +21,10 @@
 #include "mutex.h"
 
 #include "net/gnrc/rpl.h"
+#ifdef MODULE_GNRC_RPL_P2P
+#include "net/gnrc/rpl/p2p.h"
+#include "net/gnrc/rpl/p2p_dodag.h"
+#endif
 
 #define ENABLE_DEBUG    (0)
 #include "debug.h"
@@ -157,6 +161,24 @@ static void _receive(gnrc_pktsnip_t *icmpv6)
             gnrc_rpl_recv_DAO_ACK((gnrc_rpl_dao_ack_t *)(icmpv6_hdr + 1), iface,
                                   byteorder_ntohs(ipv6_hdr->len));
             break;
+#ifdef MODULE_GNRC_RPL_P2P
+        case GNRC_RPL_P2P_ICMPV6_CODE_DRO:
+            DEBUG("RPL: P2P DRO received\n");
+            gnrc_pktsnip_t *icmpv6_snip = gnrc_pktbuf_add(NULL, NULL, icmpv6->size,
+                                                          GNRC_NETTYPE_ICMPV6);
+            if (icmpv6_snip == NULL) {
+                DEBUG("RPL-P2P: cannot copy ICMPv6 packet\n");
+                break;
+            }
+
+            memcpy(icmpv6_snip->data, icmpv6->data, icmpv6->size);
+
+            gnrc_rpl_p2p_recv_DRO(icmpv6_snip, &ipv6_hdr->src);
+            break;
+        case GNRC_RPL_P2P_ICMPV6_CODE_DRO_ACK:
+            DEBUG("RPL: P2P DRO-ACK received\n");
+            break;
+#endif
         default:
             DEBUG("RPL: Unknown ICMPV6 code received\n");
             break;
@@ -265,6 +287,10 @@ void _update_lifetime(void)
         }
     }
 
+#ifdef MODULE_GNRC_RPL_P2P
+    gnrc_rpl_p2p_update();
+#endif
+
     xtimer_set_msg(&_lt_timer, _lt_time, &_lt_msg, gnrc_rpl_pid);
 }
 
@@ -284,6 +310,11 @@ void gnrc_rpl_long_delay_dao(gnrc_rpl_dodag_t *dodag)
 
 void _dao_handle_send(gnrc_rpl_dodag_t *dodag)
 {
+#ifdef MODULE_GNRC_RPL_P2P
+    if (dodag->instance->mop == GNRC_RPL_P2P_MOP) {
+        return;
+    }
+#endif
     if ((dodag->dao_ack_received == false) && (dodag->dao_counter < GNRC_RPL_DAO_SEND_RETRIES)) {
         dodag->dao_counter++;
         gnrc_rpl_send_DAO(dodag->instance, NULL, dodag->default_lifetime);
diff --git a/sys/net/gnrc/routing/rpl/gnrc_rpl_control_messages.c b/sys/net/gnrc/routing/rpl/gnrc_rpl_control_messages.c
index 472ad78c1d103965fb986fda52222290601e304c..e9bf29addd961324a10390c829127ef55f40cf89 100644
--- a/sys/net/gnrc/routing/rpl/gnrc_rpl_control_messages.c
+++ b/sys/net/gnrc/routing/rpl/gnrc_rpl_control_messages.c
@@ -25,6 +25,12 @@
 
 #include "net/gnrc/rpl.h"
 
+#ifdef MODULE_GNRC_RPL_P2P
+#include "net/gnrc/rpl/p2p_structs.h"
+#include "net/gnrc/rpl/p2p_dodag.h"
+#include "net/gnrc/rpl/p2p.h"
+#endif
+
 #define ENABLE_DEBUG    (0)
 #include "debug.h"
 
@@ -161,6 +167,18 @@ void gnrc_rpl_send_DIO(gnrc_rpl_instance_t *inst, ipv6_addr_t *destination)
     gnrc_pktsnip_t *pkt = NULL, *tmp;
     gnrc_rpl_dio_t *dio;
 
+#ifdef MODULE_GNRC_RPL_P2P
+    gnrc_rpl_p2p_ext_t *p2p_ext = gnrc_rpl_p2p_ext_get(dodag);
+    if (dodag->instance->mop == GNRC_RPL_P2P_MOP) {
+        if (!p2p_ext->for_me) {
+            if ((pkt = gnrc_rpl_p2p_rdo_build(pkt, p2p_ext)) == NULL) {
+                return;
+            }
+        }
+        dodag->dio_opts &= ~GNRC_RPL_REQ_DIO_OPT_PREFIX_INFO;
+    }
+#endif
+
 #ifndef GNRC_RPL_WITHOUT_PIO
     if (dodag->dio_opts & GNRC_RPL_REQ_DIO_OPT_PREFIX_INFO) {
         if ((pkt = _dio_prefix_info_build(pkt, dodag)) == NULL) {
@@ -265,6 +283,12 @@ void gnrc_rpl_recv_DIS(gnrc_rpl_dis_t *dis, kernel_pid_t iface, ipv6_addr_t *src
             if ((gnrc_rpl_instances[i].state != 0)
                 /* a leaf node should only react to unicast DIS */
                  && (gnrc_rpl_instances[i].dodag.node_status != GNRC_RPL_LEAF_NODE)) {
+#ifdef MODULE_GNRC_RPL_P2P
+                if (gnrc_rpl_instances[i].mop == GNRC_RPL_P2P_MOP) {
+                    DEBUG("RPL: Not responding to DIS for P2P-RPL DODAG\n");
+                    continue;
+                }
+#endif
                 trickle_reset_timer(&(gnrc_rpl_instances[i].dodag.trickle));
             }
         }
@@ -497,6 +521,11 @@ bool _parse_options(int msg_type, gnrc_rpl_instance_t *inst, gnrc_rpl_opt_t *opt
                 first_target = NULL;
                 break;
 
+#ifdef MODULE_GNRC_RPL_P2P
+            case (GNRC_RPL_P2P_OPT_RDO):
+                gnrc_rpl_p2p_rdo_parse((gnrc_rpl_p2p_opt_rdo_t *) opt, gnrc_rpl_p2p_ext_get(dodag));
+                break;
+#endif
         }
         l += opt->length + sizeof(gnrc_rpl_opt_t);
         opt = (gnrc_rpl_opt_t *) (((uint8_t *) (opt + 1)) + opt->length);
@@ -635,6 +664,13 @@ void gnrc_rpl_recv_DIO(gnrc_rpl_dio_t *dio, kernel_pid_t iface, ipv6_addr_t *src
         return;
     }
 
+#ifdef MODULE_GNRC_RPL_P2P
+    gnrc_rpl_p2p_ext_t *p2p_ext = gnrc_rpl_p2p_ext_get(dodag);
+    if ((dodag->instance->mop == GNRC_RPL_P2P_MOP) && (p2p_ext->lifetime_sec <= 0)) {
+        return;
+    }
+#endif
+
     if (GNRC_RPL_COUNTER_GREATER_THAN(dio->version_number, dodag->version)) {
         if (dodag->node_status == GNRC_RPL_ROOT_NODE) {
             dodag->version = GNRC_RPL_COUNTER_INCREMENT(dio->version_number);
@@ -760,6 +796,12 @@ void gnrc_rpl_send_DAO(gnrc_rpl_instance_t *inst, ipv6_addr_t *destination, uint
         return;
     }
 
+#ifdef MODULE_GNRC_RPL_P2P
+    if (dodag->instance->mop == GNRC_RPL_P2P_MOP) {
+        return;
+    }
+#endif
+
     if (destination == NULL) {
         if (dodag->parents == NULL) {
             DEBUG("RPL: dodag has no preferred parent\n");
@@ -781,14 +823,12 @@ void gnrc_rpl_send_DAO(gnrc_rpl_instance_t *inst, ipv6_addr_t *destination, uint
         return;
     }
 
-    fib_entry_t *fentry = NULL;
-    ipv6_addr_t *addr = NULL;
-
     mutex_lock(&(gnrc_ipv6_fib_table.mtx_access));
 
     /* add external and RPL FIB entries */
     for (size_t i = 0; i < gnrc_ipv6_fib_table.size; ++i) {
-        fentry = &gnrc_ipv6_fib_table.data.entries[i];
+        ipv6_addr_t *addr;
+        fib_entry_t *fentry = &gnrc_ipv6_fib_table.data.entries[i];
         if (fentry->lifetime != 0) {
             if (!(fentry->next_hop_flags & FIB_FLAG_RPL_ROUTE)) {
                 ptr = &tmp;
@@ -1003,6 +1043,12 @@ void gnrc_rpl_recv_DAO(gnrc_rpl_dao_t *dao, kernel_pid_t iface, ipv6_addr_t *src
         return;
     }
 
+#ifdef MODULE_GNRC_RPL_P2P
+    if (dodag->instance->mop == GNRC_RPL_P2P_MOP) {
+        return;
+    }
+#endif
+
     uint32_t included_opts = 0;
     if(!_parse_options(GNRC_RPL_ICMPV6_CODE_DAO, inst, opts, len, src, &included_opts)) {
         DEBUG("RPL: Error encountered during DAO option parsing - ignore DAO\n");
diff --git a/sys/net/gnrc/routing/rpl/gnrc_rpl_dodag.c b/sys/net/gnrc/routing/rpl/gnrc_rpl_dodag.c
index ec75700950d7f48df786439433f2eedfccd11b5d..e864f6c6161925e5204a764a08e2b9cbed50599f 100644
--- a/sys/net/gnrc/routing/rpl/gnrc_rpl_dodag.c
+++ b/sys/net/gnrc/routing/rpl/gnrc_rpl_dodag.c
@@ -24,6 +24,10 @@
 #include "utlist.h"
 
 #include "net/gnrc/rpl.h"
+#ifdef MODULE_GNRC_RPL_P2P
+#include "net/gnrc/rpl/p2p.h"
+#include "net/gnrc/rpl/p2p_dodag.h"
+#endif
 
 #define ENABLE_DEBUG    (0)
 #include "debug.h"
@@ -46,6 +50,16 @@ static void _rpl_trickle_send_dio(void *args)
         return;
     }
 
+#ifdef MODULE_GNRC_RPL_P2P
+    if (dodag->instance->mop == GNRC_RPL_P2P_MOP) {
+        gnrc_rpl_p2p_ext_t *p2p_ext = gnrc_rpl_p2p_ext_get(dodag);
+        if (p2p_ext && (p2p_ext->for_me || ((p2p_ext->lifetime_sec <= 0) || p2p_ext->stop))) {
+            trickle_stop(&dodag->trickle);
+            return;
+        }
+    }
+#endif
+
     gnrc_rpl_send_DIO(inst, (ipv6_addr_t *) &ipv6_addr_all_rpl_nodes);
     DEBUG("trickle callback: Instance (%d) | DODAG: (%s)\n", inst->id,
           ipv6_addr_to_str(addr_str,&dodag->dodag_id, sizeof(addr_str)));
@@ -97,6 +111,9 @@ bool gnrc_rpl_instance_remove_by_id(uint8_t instance_id)
 bool gnrc_rpl_instance_remove(gnrc_rpl_instance_t *inst)
 {
     gnrc_rpl_dodag_t *dodag = &inst->dodag;
+#ifdef MODULE_GNRC_RPL_P2P
+    gnrc_rpl_p2p_ext_remove(dodag);
+#endif
     gnrc_rpl_dodag_remove_all_parents(dodag);
     trickle_stop(&dodag->trickle);
     memset(inst, 0, sizeof(gnrc_rpl_instance_t));
@@ -140,6 +157,14 @@ bool gnrc_rpl_dodag_init(gnrc_rpl_instance_t *instance, ipv6_addr_t *dodag_id, k
     dodag->iface = iface;
     dodag->netif_addr = netif_addr;
 
+#ifdef MODULE_GNRC_RPL_P2P
+    if ((instance->mop == GNRC_RPL_P2P_MOP) && (gnrc_rpl_p2p_ext_new(dodag) == NULL)) {
+        DEBUG("RPL: could not allocate new P2P-RPL DODAG extension. Remove DODAG\n");
+        gnrc_rpl_instance_remove(instance);
+        return false;
+    }
+#endif
+
     return true;
 }
 
@@ -149,6 +174,7 @@ void gnrc_rpl_dodag_remove_all_parents(gnrc_rpl_dodag_t *dodag)
     LL_FOREACH_SAFE(dodag->parents, elt, tmp) {
         gnrc_rpl_parent_remove(elt);
     }
+    dodag->my_rank = GNRC_RPL_INFINITE_RANK;
 }
 
 bool gnrc_rpl_parent_add_by_addr(gnrc_rpl_dodag_t *dodag, ipv6_addr_t *addr,
@@ -243,6 +269,9 @@ void gnrc_rpl_parent_update(gnrc_rpl_dodag_t *dodag, gnrc_rpl_parent_t *parent)
     /* update Parent lifetime */
     if (parent != NULL) {
         parent->lifetime = (now / SEC_IN_USEC) + ((dodag->default_lifetime * dodag->lifetime_unit));
+#ifdef MODULE_GNRC_RPL_P2P
+        if (dodag->instance->mop != GNRC_RPL_P2P_MOP) {
+#endif
         if (parent == dodag->parents) {
             fib_add_entry(&gnrc_ipv6_fib_table,
                           dodag->iface,
@@ -254,6 +283,9 @@ void gnrc_rpl_parent_update(gnrc_rpl_dodag_t *dodag, gnrc_rpl_parent_t *parent)
                           FIB_FLAG_RPL_ROUTE,
                           (dodag->default_lifetime * dodag->lifetime_unit) * SEC_IN_MS);
         }
+#ifdef MODULE_GNRC_RPL_P2P
+        }
+#endif
     }
 
     if (_gnrc_rpl_find_preferred_parent(dodag) == NULL) {
@@ -291,11 +323,16 @@ static gnrc_rpl_parent_t *_gnrc_rpl_find_preferred_parent(gnrc_rpl_dodag_t *doda
     if (new_best != old_best) {
         LL_DELETE(dodag->parents, new_best);
         LL_PREPEND(dodag->parents, new_best);
-        if (dodag->instance->mop != GNRC_RPL_MOP_NO_DOWNWARD_ROUTES) {
+        /* no-path DAOs only for the storing mode */
+        if ((dodag->instance->mop == GNRC_RPL_MOP_STORING_MODE_NO_MC) ||
+            (dodag->instance->mop == GNRC_RPL_MOP_STORING_MODE_MC)) {
             gnrc_rpl_send_DAO(dodag->instance, &old_best->addr, 0);
             gnrc_rpl_delay_dao(dodag);
         }
 
+#ifdef MODULE_GNRC_RPL_P2P
+    if (dodag->instance->mop != GNRC_RPL_P2P_MOP) {
+#endif
         fib_add_entry(&gnrc_ipv6_fib_table,
                       dodag->iface,
                       (uint8_t *) ipv6_addr_unspecified.u8,
@@ -305,6 +342,10 @@ static gnrc_rpl_parent_t *_gnrc_rpl_find_preferred_parent(gnrc_rpl_dodag_t *doda
                       sizeof(ipv6_addr_t),
                       FIB_FLAG_RPL_ROUTE,
                       (dodag->default_lifetime * dodag->lifetime_unit) * SEC_IN_MS);
+#ifdef MODULE_GNRC_RPL_P2P
+    }
+#endif
+
     }
 
     dodag->my_rank = dodag->instance->of->calc_rank(dodag->parents, 0);
diff --git a/sys/net/gnrc/routing/rpl/p2p/Makefile b/sys/net/gnrc/routing/rpl/p2p/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..67dc94651fe669c491fc5d1445bdceac85386fb7
--- /dev/null
+++ b/sys/net/gnrc/routing/rpl/p2p/Makefile
@@ -0,0 +1,3 @@
+MODULE = gnrc_rpl_p2p
+
+include $(RIOTBASE)/Makefile.base
diff --git a/sys/net/gnrc/routing/rpl/p2p/gnrc_rpl_p2p.c b/sys/net/gnrc/routing/rpl/p2p/gnrc_rpl_p2p.c
new file mode 100644
index 0000000000000000000000000000000000000000..9899936bb38bec23120d9eed667014e808c151a4
--- /dev/null
+++ b/sys/net/gnrc/routing/rpl/p2p/gnrc_rpl_p2p.c
@@ -0,0 +1,386 @@
+/*
+ * Copyright (C) 2016 Cenk Gündoğan <mail@cgundogan.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.
+ */
+
+/**
+ * @{
+ *
+ * @file
+ *
+ * @author  Cenk Gündoğan <mail@cgundogan.de>
+ */
+
+#include "net/icmpv6.h"
+#include "net/gnrc/ipv6.h"
+#include "net/gnrc/icmpv6.h"
+#include "net/gnrc.h"
+#include "net/gnrc/rpl/structs.h"
+#include "net/gnrc/rpl/dodag.h"
+#include "net/gnrc/rpl/p2p.h"
+#include "net/gnrc/rpl/p2p_structs.h"
+#include "net/gnrc/rpl/p2p_dodag.h"
+
+#define ENABLE_DEBUG    (0)
+#include "debug.h"
+
+#if ENABLE_DEBUG
+static char addr_str[IPV6_ADDR_MAX_STR_LEN];
+#endif
+
+#define GNRC_RPL_P2P_RDO_LEN            (18)
+#define GNRC_RPL_P2P_RDO_FLAGS_LIFETIME (6)
+#define GNRC_RPL_P2P_RDO_FLAGS_HBH      (6)
+#define GNRC_RPL_P2P_RDO_FLAGS_REPLY    (7)
+#define GNRC_RPL_P2P_RDO_FLAGS_ADDRNUM  (4)
+#define GNRC_RPL_P2P_RDO_FLAGS_COMPR    (0x0F)
+#define GNRC_RPL_P2P_RDO_FLAGS_MAXRANK  (0x3F)
+#define GNRC_RPL_P2P_RDO_FLAGS_NEXT_HOP (GNRC_RPL_P2P_RDO_FLAGS_MAXRANK)
+#define GNRC_RPL_P2P_DRO_FLAGS_SEQ      (12)
+#define GNRC_RPL_P2P_DRO_FLAGS_ACK      (14)
+#define GNRC_RPL_P2P_DRO_FLAGS_STOP     (15)
+
+gnrc_rpl_p2p_ext_t gnrc_rpl_p2p_exts[GNRC_RPL_P2P_EXTS_NUMOF];
+const uint8_t gnrc_rpl_p2p_lifetime_lookup[4] = { 1, 4, 16, 64 };
+
+void gnrc_rpl_p2p_update(void)
+{
+    gnrc_rpl_p2p_ext_t *p2p_ext;
+    for (uint8_t i = 0; i < GNRC_RPL_P2P_EXTS_NUMOF; ++i) {
+        p2p_ext = &gnrc_rpl_p2p_exts[i];
+        if ((p2p_ext->state) && (p2p_ext->lifetime_sec > 0)) {
+            p2p_ext->lifetime_sec -= GNRC_RPL_LIFETIME_UPDATE_STEP;
+            if (p2p_ext->lifetime_sec <= 0) {
+                gnrc_rpl_dodag_remove_all_parents(p2p_ext->dodag);
+                p2p_ext->dodag->instance->cleanup = GNRC_RPL_CLEANUP_TIME;
+                continue;
+            }
+            p2p_ext->dro_delay -= GNRC_RPL_LIFETIME_UPDATE_STEP;
+            if (p2p_ext->reply && (p2p_ext->dro_delay < 0) && (p2p_ext->for_me)) {
+                gnrc_rpl_p2p_send_DRO(NULL, p2p_ext);
+            }
+        }
+    }
+}
+
+gnrc_rpl_instance_t *gnrc_rpl_p2p_root_init(uint8_t instance_id, ipv6_addr_t *dodag_id,
+                                            ipv6_addr_t *target, bool gen_inst_id)
+{
+    if (gen_inst_id) {
+        instance_id = gnrc_rpl_gen_instance_id(true);
+    }
+
+    gnrc_rpl_dodag_t *dodag = NULL;
+    gnrc_rpl_instance_t *instance = gnrc_rpl_root_instance_init(instance_id, dodag_id,
+                                                                GNRC_RPL_P2P_MOP);
+
+    if (!instance) {
+        return NULL;
+    }
+
+    dodag = &instance->dodag;
+
+    instance->max_rank_inc = 0;
+    dodag->dtsn = 0;
+    dodag->prf = 0;
+    dodag->dio_interval_doubl = GNRC_RPL_DEFAULT_DIO_INTERVAL_DOUBLINGS;
+    dodag->dio_min = GNRC_RPL_P2P_DEFAULT_DIO_INTERVAL_MIN;
+    dodag->dio_redun = GNRC_RPL_P2P_DEFAULT_DIO_REDUNDANCY_CONSTANT;
+    dodag->default_lifetime = GNRC_RPL_P2P_DEFAULT_LIFETIME;
+    dodag->lifetime_unit = GNRC_RPL_P2P_LIFETIME_UNIT;
+    dodag->version = 0;
+    dodag->grounded = 1;
+    dodag->node_status = GNRC_RPL_ROOT_NODE;
+    dodag->my_rank = GNRC_RPL_ROOT_RANK;
+    dodag->dio_opts |= GNRC_RPL_REQ_DIO_OPT_DODAG_CONF;
+    dodag->dio_opts &= ~GNRC_RPL_REQ_DIO_OPT_PREFIX_INFO;
+
+    gnrc_rpl_p2p_ext_t *p2p_ext = gnrc_rpl_p2p_ext_get(dodag);
+    p2p_ext->target = *target;
+    p2p_ext->compr = GNRC_RPL_P2P_COMPR;
+    p2p_ext->routes_numof = 0;
+    p2p_ext->hop_by_hop = true;
+    p2p_ext->reply = true;
+    p2p_ext->lifetime_enc = GNRC_RPL_P2P_LIFETIME;
+    p2p_ext->lifetime_sec = gnrc_rpl_p2p_lifetime_lookup[p2p_ext->lifetime_enc];
+    p2p_ext->maxrank = GNRC_RPL_P2P_MAX_RANK;
+    p2p_ext->dro_delay = -1;
+
+    trickle_start(gnrc_rpl_pid, &dodag->trickle, GNRC_RPL_MSG_TYPE_TRICKLE_INTERVAL,
+                  GNRC_RPL_MSG_TYPE_TRICKLE_CALLBACK, (1 << dodag->dio_min),
+                  dodag->dio_interval_doubl, dodag->dio_redun);
+
+    return instance;
+}
+
+gnrc_pktsnip_t *gnrc_rpl_p2p_rdo_build(gnrc_pktsnip_t *pkt, gnrc_rpl_p2p_ext_t *p2p_ext)
+{
+    gnrc_rpl_p2p_opt_rdo_t *rdo;
+    gnrc_pktsnip_t *opt_snip;
+    size_t addr_len = (sizeof(ipv6_addr_t) - p2p_ext->compr);
+    for (uint8_t i = p2p_ext->addr_numof; i > 0; i--) {
+        if ((opt_snip = gnrc_pktbuf_add(pkt, NULL, addr_len, GNRC_NETTYPE_UNDEF)) == NULL) {
+            DEBUG("RPL: BUILD RDO - no space left in packet buffer\n");
+            gnrc_pktbuf_release(pkt);
+            return NULL;
+        }
+        memcpy(opt_snip->data, &p2p_ext->addr_vec[i-1], addr_len);
+        pkt = opt_snip;
+    }
+
+    if ((opt_snip = gnrc_pktbuf_add(pkt, NULL, sizeof(gnrc_rpl_p2p_opt_rdo_t),
+                                    GNRC_NETTYPE_UNDEF)) == NULL) {
+        DEBUG("RPL: BUILD RDO - no space left in packet buffer\n");
+        gnrc_pktbuf_release(pkt);
+        return NULL;
+    }
+    rdo = opt_snip->data;
+    rdo->type = GNRC_RPL_P2P_OPT_RDO;
+    rdo->length = GNRC_RPL_P2P_RDO_LEN +
+                  p2p_ext->addr_numof * (sizeof(ipv6_addr_t) - p2p_ext->compr);
+    rdo->compr_flags = (p2p_ext->reply << GNRC_RPL_P2P_RDO_FLAGS_REPLY) |
+                        (p2p_ext->hop_by_hop << GNRC_RPL_P2P_RDO_FLAGS_HBH)
+                        | ((p2p_ext->routes_numof & 0x3) << GNRC_RPL_P2P_RDO_FLAGS_ADDRNUM)
+                        | (p2p_ext->compr & GNRC_RPL_P2P_RDO_FLAGS_COMPR);
+    rdo->lmn = ((p2p_ext->lifetime_enc & 0x3) << GNRC_RPL_P2P_RDO_FLAGS_LIFETIME) |
+                (p2p_ext->maxrank & GNRC_RPL_P2P_RDO_FLAGS_MAXRANK);
+    rdo->target = p2p_ext->target;
+    return opt_snip;
+}
+
+void gnrc_rpl_p2p_rdo_parse(gnrc_rpl_p2p_opt_rdo_t *rdo, gnrc_rpl_p2p_ext_t *p2p_ext)
+{
+    DEBUG("RPL: Route Discovery DIO option parsed\n");
+
+    uint8_t addr_num = (rdo->length - GNRC_RPL_P2P_RDO_LEN)
+                        / (sizeof(ipv6_addr_t) - p2p_ext->compr);
+    if (addr_num >= GNRC_RPL_P2P_ADDR_VEC_NUMOF) {
+        DEBUG("RPL: cannot parse RDO - too many hops\n");
+        return;
+    }
+
+    p2p_ext->for_me = (gnrc_ipv6_netif_find_by_addr(NULL, &rdo->target) != KERNEL_PID_UNDEF);
+
+    p2p_ext->reply = (rdo->compr_flags & (1 << GNRC_RPL_P2P_RDO_FLAGS_REPLY))
+                      >> GNRC_RPL_P2P_RDO_FLAGS_REPLY;
+    p2p_ext->hop_by_hop = (rdo->compr_flags & (1 << GNRC_RPL_P2P_RDO_FLAGS_HBH))
+                           >> GNRC_RPL_P2P_RDO_FLAGS_HBH;
+    p2p_ext->routes_numof = (rdo->compr_flags & (0x3 << GNRC_RPL_P2P_RDO_FLAGS_ADDRNUM))
+                             >> GNRC_RPL_P2P_RDO_FLAGS_ADDRNUM;
+    p2p_ext->compr = rdo->compr_flags & GNRC_RPL_P2P_RDO_FLAGS_COMPR;
+    p2p_ext->lifetime_enc = (rdo->lmn & (0x3 << GNRC_RPL_P2P_RDO_FLAGS_LIFETIME))
+                             >> GNRC_RPL_P2P_RDO_FLAGS_LIFETIME;
+    if (p2p_ext->lifetime_sec == INT8_MIN) {
+        p2p_ext->lifetime_sec = gnrc_rpl_p2p_lifetime_lookup[p2p_ext->lifetime_enc];
+    }
+    p2p_ext->maxrank = rdo->lmn & GNRC_RPL_P2P_RDO_FLAGS_MAXRANK;
+    p2p_ext->target = rdo->target;
+
+    memset(&p2p_ext->addr_vec, 0, sizeof(ipv6_addr_t) * GNRC_RPL_P2P_ADDR_VEC_NUMOF);
+    p2p_ext->addr_numof = 0;
+    uint8_t *tmp = (uint8_t *) (rdo + 1);
+    uint8_t *addr = NULL;
+    uint8_t addr_len = sizeof(ipv6_addr_t) - p2p_ext->compr;
+    uint8_t i = 0;
+    for (i = 0; i < addr_num; i++) {
+        addr = ((uint8_t *) &p2p_ext->addr_vec[i]) + p2p_ext->compr;
+        memcpy(addr, tmp, addr_len);
+        tmp += addr_len;
+        p2p_ext->addr_numof++;
+    }
+
+    if (!p2p_ext->for_me) {
+        ipv6_addr_t *me = NULL;
+        if(gnrc_ipv6_netif_find_by_prefix(&me, &p2p_ext->dodag->dodag_id) == KERNEL_PID_UNDEF) {
+            DEBUG("RPL: no address configured\n");
+            return;
+        }
+        addr = ((uint8_t *) &p2p_ext->addr_vec[i]) + p2p_ext->compr;
+        memcpy(addr, ((uint8_t *) me) + p2p_ext->compr, addr_len);
+        p2p_ext->addr_numof++;
+    }
+    else if (p2p_ext->reply) {
+        p2p_ext->stop = true;
+        p2p_ext->dro_ack = true;
+        p2p_ext->dro_delay = GNRC_RPL_P2P_DRO_DELAY;
+    }
+}
+
+static gnrc_pktsnip_t *_build_initial_DRO(gnrc_rpl_p2p_ext_t *p2p_ext)
+{
+    gnrc_pktsnip_t *pkt = NULL, *opt_snip = NULL;
+    gnrc_rpl_p2p_dro_t *dro = NULL;
+    gnrc_rpl_p2p_opt_rdo_t *rdo = NULL;
+    size_t addr_len = (sizeof(ipv6_addr_t) - p2p_ext->compr);
+    uint8_t addr_size = p2p_ext->addr_numof * addr_len;
+
+    for (uint8_t i = p2p_ext->addr_numof; i > 0; i--) {
+        if ((opt_snip = gnrc_pktbuf_add(pkt, NULL, addr_len, GNRC_NETTYPE_UNDEF)) == NULL) {
+            DEBUG("RPL-P2P: cannot add addresses to RDO - no space left in packet buffer\n");
+            gnrc_pktbuf_release(pkt);
+            return NULL;
+        }
+        memcpy(opt_snip->data, &p2p_ext->addr_vec[i-1], addr_len);
+        pkt = opt_snip;
+    }
+
+    if ((opt_snip = gnrc_pktbuf_add(pkt, NULL, sizeof(gnrc_rpl_p2p_opt_rdo_t),
+                                    GNRC_NETTYPE_UNDEF)) == NULL) {
+        DEBUG("RPL-P2P: cannot allocate DRO - no space left in packet buffer\n");
+        gnrc_pktbuf_release(pkt);
+        return NULL;
+    }
+
+    rdo = opt_snip->data;
+    rdo->type = GNRC_RPL_P2P_OPT_RDO;
+    rdo->length = GNRC_RPL_P2P_RDO_LEN + addr_size;
+    rdo->compr_flags = (p2p_ext->hop_by_hop << GNRC_RPL_P2P_RDO_FLAGS_HBH) |
+                       (p2p_ext->compr & GNRC_RPL_P2P_RDO_FLAGS_COMPR);
+    /* rdo->length does not include the first two bytes, thus we have to add them manually */
+    rdo->lmn = (((rdo->length + 2 - sizeof(*rdo)) / addr_len) & GNRC_RPL_P2P_RDO_FLAGS_NEXT_HOP);
+    rdo->target = p2p_ext->target;
+    pkt = opt_snip;
+
+    if ((opt_snip = gnrc_pktbuf_add(pkt, NULL, sizeof(gnrc_rpl_p2p_dro_t),
+                                    GNRC_NETTYPE_UNDEF)) == NULL) {
+        DEBUG("RPL-P2P: cannot allocate RDO - no space left in packet buffer\n");
+        gnrc_pktbuf_release(pkt);
+        return NULL;
+    }
+    dro = opt_snip->data;
+    dro->instance_id = p2p_ext->dodag->instance->id;
+    dro->version_number = 0;
+    dro->flags_rev = byteorder_htons((((p2p_ext->stop << 1) | (p2p_ext->dro_ack << 0))
+                                      << GNRC_RPL_P2P_DRO_FLAGS_ACK) |
+                                     ((p2p_ext->dro_seq & 0x3) << GNRC_RPL_P2P_DRO_FLAGS_SEQ));
+    dro->dodag_id = p2p_ext->dodag->dodag_id;
+    pkt = opt_snip;
+
+    if ((opt_snip = gnrc_icmpv6_build(pkt, ICMPV6_RPL_CTRL, GNRC_RPL_P2P_ICMPV6_CODE_DRO,
+                                      sizeof(icmpv6_hdr_t))) == NULL) {
+        DEBUG("RPL-P2P: cannot allocate ICMPv6 - no space left in packet buffer\n");
+        gnrc_pktbuf_release(pkt);
+        return NULL;
+    }
+
+    pkt = opt_snip;
+
+    return pkt;
+}
+
+void gnrc_rpl_p2p_send_DRO(gnrc_pktsnip_t *pkt, gnrc_rpl_p2p_ext_t *p2p_ext)
+{
+    assert(p2p_ext != NULL);
+
+    if (pkt == NULL) {
+        if ((pkt = _build_initial_DRO(p2p_ext)) == NULL) {
+            DEBUG("RPL-P2P: BUILD INITIAL DRO - no space left in packet buffer\n");
+            return;
+        }
+    }
+
+    gnrc_rpl_send(pkt, p2p_ext->dodag->iface, NULL, NULL, &p2p_ext->dodag->dodag_id);
+
+    return;
+}
+
+void gnrc_rpl_p2p_recv_DRO(gnrc_pktsnip_t *pkt, ipv6_addr_t *src)
+{
+    gnrc_pktsnip_t *icmpv6_snip = gnrc_pktbuf_mark(pkt, sizeof(icmpv6_hdr_t), GNRC_NETTYPE_ICMPV6);
+    gnrc_pktsnip_t *dro_snip = gnrc_pktbuf_mark(pkt, sizeof(gnrc_rpl_p2p_dro_t),
+                                                GNRC_NETTYPE_UNDEF);
+    gnrc_pktsnip_t *rdo_snip = gnrc_pktbuf_mark(pkt, sizeof(gnrc_rpl_p2p_opt_rdo_t),
+                                                GNRC_NETTYPE_UNDEF);
+    gnrc_pktsnip_t *addr_snip = pkt;
+    gnrc_rpl_instance_t *inst;
+    gnrc_rpl_dodag_t *dodag;
+    gnrc_rpl_p2p_ext_t *p2p_ext;
+    gnrc_rpl_p2p_dro_t *dro;
+    gnrc_rpl_p2p_opt_rdo_t *rdo;
+    uint8_t *addr_vec;
+    uint16_t flags;
+    size_t addr_len;
+
+    if (!rdo_snip || !dro_snip) {
+        DEBUG("RPL-P2P: Error - No DRO or RDO received\n");
+        gnrc_pktbuf_release(pkt);
+        return;
+    }
+
+    dro = dro_snip->data;
+
+    if ((inst = gnrc_rpl_instance_get(dro->instance_id)) == NULL) {
+        DEBUG("RPL-P2P: Error - Instance (%d) does not exist\n", dro->instance_id);
+        return;
+    }
+
+    dodag = &inst->dodag;
+
+    if ((p2p_ext = gnrc_rpl_p2p_ext_get(dodag)) == NULL) {
+        DEBUG("RPL-P2P: Error - No P2P-RPL DODAG extension found\n");
+        return;
+    }
+
+    if (p2p_ext->for_me) {
+        DEBUG("RPL-P2P: Ignore DRO\n");
+        return;
+    }
+
+    flags = byteorder_ntohs(dro->flags_rev);
+    p2p_ext->stop = (flags & (1 << GNRC_RPL_P2P_DRO_FLAGS_STOP)) >> GNRC_RPL_P2P_DRO_FLAGS_STOP;
+    p2p_ext->dro_ack = (flags & (1 << GNRC_RPL_P2P_DRO_FLAGS_ACK)) >> GNRC_RPL_P2P_DRO_FLAGS_ACK;
+    p2p_ext->dro_seq = (flags & (0x3 << GNRC_RPL_P2P_DRO_FLAGS_SEQ)) >> GNRC_RPL_P2P_DRO_FLAGS_SEQ;
+
+    addr_len = sizeof(ipv6_addr_t) - p2p_ext->compr;
+    ipv6_addr_t addr = p2p_ext->dodag->dodag_id;
+    ipv6_addr_t *me = NULL;
+    addr_vec = addr_snip->data;
+
+    rdo = rdo_snip->data;
+
+    if (rdo->lmn > 0) {
+        rdo->lmn--;
+        memcpy(&addr.u8[p2p_ext->compr], &addr_vec[addr_len * rdo->lmn], addr_len);
+    }
+
+    if (gnrc_ipv6_netif_find_by_addr(&me, &addr) == dodag->iface) {
+        fib_add_entry(&gnrc_ipv6_fib_table, dodag->iface, p2p_ext->target.u8,
+                      sizeof(ipv6_addr_t), FIB_FLAG_NET_PREFIX, src->u8,
+                      sizeof(ipv6_addr_t), FIB_FLAG_RPL_ROUTE,
+                      p2p_ext->dodag->default_lifetime *
+                      p2p_ext->dodag->lifetime_unit * SEC_IN_MS);
+
+        if (p2p_ext->dodag->node_status != GNRC_RPL_ROOT_NODE) {
+            if ((rdo_snip = gnrc_pktbuf_start_write(rdo_snip)) == NULL) {
+                DEBUG("RPL-P2P: Error - Cannot allocate new RDO\n");
+                return;
+            }
+
+            addr_snip->next = NULL;
+            rdo_snip->next = addr_snip;
+            dro_snip->next = rdo_snip;
+
+            icmpv6_snip = gnrc_icmpv6_build(dro_snip, ICMPV6_RPL_CTRL, GNRC_RPL_P2P_ICMPV6_CODE_DRO,
+                                            sizeof(icmpv6_hdr_t));
+            if (icmpv6_snip == NULL) {
+                DEBUG("RPL-P2P: cannot allocate ICMPv6 - no space left in packet buffer\n");
+                gnrc_pktbuf_release(pkt);
+                return;
+            }
+
+            gnrc_rpl_send(icmpv6_snip, p2p_ext->dodag->iface, NULL, NULL, &p2p_ext->dodag->dodag_id);
+            return;
+        }
+    }
+
+    gnrc_pktbuf_release(pkt);
+
+    return;
+}
+
+/**
+ * @}
+ */
diff --git a/sys/net/gnrc/routing/rpl/p2p/gnrc_rpl_p2p_dodag.c b/sys/net/gnrc/routing/rpl/p2p/gnrc_rpl_p2p_dodag.c
new file mode 100644
index 0000000000000000000000000000000000000000..3d4b93f9b59aed360a3f29d8c6662c27b2b7493a
--- /dev/null
+++ b/sys/net/gnrc/routing/rpl/p2p/gnrc_rpl_p2p_dodag.c
@@ -0,0 +1,63 @@
+/**
+ * Copyright (C) 2016 Cenk Gündoğan <mail@cgundogan.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.
+ */
+
+/**
+ * @{
+ *
+ * @file
+ * @author      Cenk Gündoğan <mail@cgundogan.de>
+ */
+
+#include <string.h>
+#include "net/gnrc/rpl/structs.h"
+#include "net/gnrc/rpl/p2p.h"
+#include "net/gnrc/rpl/p2p_dodag.h"
+#include "net/gnrc/rpl/p2p_structs.h"
+
+#define ENABLE_DEBUG    (0)
+#include "debug.h"
+
+gnrc_rpl_p2p_ext_t *gnrc_rpl_p2p_ext_new(gnrc_rpl_dodag_t *dodag)
+{
+    for (uint8_t i = 0; i < GNRC_RPL_P2P_EXTS_NUMOF; ++i) {
+        if (!gnrc_rpl_p2p_exts[i].state) {
+            gnrc_rpl_p2p_exts[i].state = true;
+            gnrc_rpl_p2p_exts[i].dodag = dodag;
+            gnrc_rpl_p2p_exts[i].dro_delay = -1;
+            gnrc_rpl_p2p_exts[i].lifetime_sec = INT8_MIN;
+            return &gnrc_rpl_p2p_exts[i];
+        }
+    }
+
+    /* no space available to allocate a P2P-RPL DODAG extension */
+    DEBUG("RPL-P2P: Could not a new P2P-RPL DODAG extension\n");
+    return NULL;
+}
+
+void gnrc_rpl_p2p_ext_remove(gnrc_rpl_dodag_t *dodag)
+{
+    for (uint8_t i = 0; i < GNRC_RPL_P2P_EXTS_NUMOF; ++i) {
+        if ((gnrc_rpl_p2p_exts[i].state) && (gnrc_rpl_p2p_exts[i].dodag == dodag)) {
+            memset(&gnrc_rpl_p2p_exts[i], 0, sizeof(gnrc_rpl_p2p_ext_t));
+            return;
+        }
+    }
+}
+
+gnrc_rpl_p2p_ext_t *gnrc_rpl_p2p_ext_get(gnrc_rpl_dodag_t *dodag)
+{
+    for (uint8_t i = 0; i < GNRC_RPL_P2P_EXTS_NUMOF; ++i) {
+        if ((gnrc_rpl_p2p_exts[i].state) && (gnrc_rpl_p2p_exts[i].dodag == dodag)) {
+            return &gnrc_rpl_p2p_exts[i];
+        }
+    }
+    return NULL;
+}
+/**
+ * @}
+ */
diff --git a/sys/shell/commands/sc_gnrc_rpl.c b/sys/shell/commands/sc_gnrc_rpl.c
index 33252d500a15f428ca8db4d92eb9a50bd906376d..c3fce2c68f1d67a98ed8c974601e8510ef65902f 100644
--- a/sys/shell/commands/sc_gnrc_rpl.c
+++ b/sys/shell/commands/sc_gnrc_rpl.c
@@ -63,6 +63,36 @@ int _gnrc_rpl_dodag_root(char *arg1, char *arg2)
     return 0;
 }
 
+#ifdef MODULE_GNRC_RPL_P2P
+int _gnrc_rpl_find(char *arg1, char *arg2)
+{
+    uint8_t instance_id = (uint8_t) atoi(arg1);
+    ipv6_addr_t dodag_id;
+    ipv6_addr_t target;
+
+    if (ipv6_addr_from_str(&dodag_id, arg1) == NULL) {
+        puts("<dodag_id> must be a valid IPv6 address");
+        return 1;
+    }
+
+    if (ipv6_addr_from_str(&target, arg2) == NULL) {
+        puts("<target> must be a valid IPv6 address");
+        return 1;
+    }
+
+    gnrc_rpl_instance_t *instance = NULL;
+    if ((instance = gnrc_rpl_p2p_root_init(0, &dodag_id, &target, true)) == NULL) {
+        char addr_str[IPV6_ADDR_MAX_STR_LEN];
+        printf("error: could not add DODAG (%s) to instance (%d)\n",
+                ipv6_addr_to_str(addr_str, &dodag_id, sizeof(addr_str)), instance_id);
+        return 1;
+    }
+
+    printf("successfully initiated a P2P-RPL Route Discovery\n");
+    return 0;
+}
+#endif
+
 int _gnrc_rpl_instance_remove(char *arg1)
 {
     uint8_t instance_id = (uint8_t) atoi(arg1);