rpl.h 18.5 KB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638
/*
 * Copyright (C) 2013 - 2014  INRIA.
 * Copyright (C) 2015 Martine Lenders <mlenders@inf.fu-berlin.de>
 * Copyright (C) 2015 Cenk Gündoğan <cnkgndgn@gmail.com>
 *
 * 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_gnrc_rpl  RPL
 * @ingroup     net_gnrc
 * @brief       RPL implementation for GNRC
 *
 * Configuration
 * =============
 *
 * USEMODULE
 * ---------
 *
 * - RPL (Storing Mode)
 *   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.mk}
 *   USEMODULE += gnrc_rpl
 *   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 * - RPL auto-initialization on interface
 *   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.mk}
 *   USEMODULE += auto_init_gnrc_rpl
 *   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 * Auto-Initialization
 * -------------------
 *
 * If the application defines only one interface (`GNRC_NETIF_NUMOF == 1`),
 * then RPL will be initialized on this interface.
 *
 * If the application defines several interfaces (`GNRC_NETIF_NUMOF > 1`),
 * then RPL will be initialized on the interface `GNRC_RPL_DEFAULT_NETIF`.
 * Your application is responsible for setting `GNRC_RPL_DEFAULT_NETIF` to a
 * valid interface PID, e.g. via `CFLAGS`.
 *
 * Initializing RPL on multiple interfaces automatically is currently not supported.
 * Call `gnrc_rpl_init()` manually from your application for the desired interfaces in this case.
 *
 * CFLAGS
 * ------
 *
 * - Exclude Prefix Information Options from DIOs
 *   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.mk}
 *   CFLAGS += -DGNRC_RPL_WITHOUT_PIO
 *   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 * - Modify trickle parameters
 *   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.mk}
 *   CFLAGS += -DGNRC_RPL_DEFAULT_DIO_INTERVAL_DOUBLINGS=20
 *   CFLAGS += -DGNRC_RPL_DEFAULT_DIO_INTERVAL_MIN=3
 *   CFLAGS += -DGNRC_RPL_DEFAULT_DIO_REDUNDANCY_CONSTANT=10
 *   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 * - Make reception of DODAG_CONF optional when joining a DODAG.
 *   This will use the default trickle parameters until a
 *   DODAG_CONF is received from the parent. The DODAG_CONF is
 *   requested once from the parent while joining the DODAG.
 *   The standard behaviour is to request a DODAG_CONF and join
 *   only a DODAG once a DODAG_CONF is received.
 *   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.mk}
 *   CFLAGS += -DGNRC_RPL_DODAG_CONF_OPTIONAL_ON_JOIN
 *   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 * - Set interface for auto-initialization if more than one
 *   interface exists (`GNRC_NETIF_NUMOF > 1`)
 *   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.mk}
 *   CFLAGS += -DGNRC_RPL_DEFAULT_NETIF=6
 *   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 * - By default, all incoming control messages get checked for validation.
 *   This validation can be disabled in case the involved RPL implementations
 *   are known to produce valid messages.
 *   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.mk}
 *   CFLAGS += -DGNRC_RPL_WITHOUT_VALIDATION
 *   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 * @{
 *
 * @file
 * @brief       RPL header. Declaration of global variables and functions needed for
 *              core functionality of RPL.
 *
 * Header which includes all core RPL-functions.
 *
 * @author      Eric Engel <eric.engel@fu-berlin.de>
 * @author      Fabian Brandt <fabianbr@zedat.fu-berlin.de>
 * @author      Martine Lenders <mlenders@inf.fu-berlin.de>
 * @author      Cenk Gündoğan <cnkgndgn@gmail.com>
 */

#ifndef GNRC_RPL_H_
#define GNRC_RPL_H_

#include <string.h>
#include <stdint.h>
#include "net/gnrc.h"
#include "net/gnrc/ipv6.h"
#include "net/ipv6/addr.h"
#include "net/gnrc/nettype.h"
#include "net/gnrc/rpl/structs.h"
#include "net/gnrc/rpl/dodag.h"
#include "net/gnrc/rpl/of_manager.h"
#include "net/fib.h"
#include "xtimer.h"
#include "trickle.h"

#ifdef MODULE_NETSTATS_RPL
#include "net/rpl/rpl_netstats.h"
#endif

#ifdef __cplusplus
extern "C" {
#endif

/**
 * @brief   Default stack size to use for the RPL thread
 */
#ifndef GNRC_RPL_STACK_SIZE
#define GNRC_RPL_STACK_SIZE     (THREAD_STACKSIZE_DEFAULT)
#endif

/**
 * @brief   Default priority for the RPL thread
 */
#ifndef GNRC_RPL_PRIO
#define GNRC_RPL_PRIO           (GNRC_IPV6_PRIO + 1)
#endif

/**
 * @brief   Default message queue size to use for the RPL thread.
 */
#ifndef GNRC_RPL_MSG_QUEUE_SIZE
#define GNRC_RPL_MSG_QUEUE_SIZE (8U)
#endif

/**
 * @brief   Static initializer for the all-RPL-nodes multicast IPv6
 *          address (ff02::1a)
 *
 * @see <a href="https://tools.ietf.org/html/rfc6550#section-6">
 *          RFC 6550, section 6
 *      </a>
 */
#define GNRC_RPL_ALL_NODES_ADDR {{ 0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1a }}

/**
 * @brief   Message type for lifetime updates
 */
#define GNRC_RPL_MSG_TYPE_LIFETIME_UPDATE     (0x0900)

/**
 * @brief   Message type for trickle intervals
 */
#define GNRC_RPL_MSG_TYPE_TRICKLE_INTERVAL    (0x0901)

/**
 * @brief   Message type for trickle callbacks
 */
#define GNRC_RPL_MSG_TYPE_TRICKLE_CALLBACK    (0x0902)

/**
 * @brief   Message type for handling DAO sending
 */
#define GNRC_RPL_MSG_TYPE_DAO_HANDLE  (0x0903)

/**
 * @brief   Infinite rank
 * @see <a href="https://tools.ietf.org/html/rfc6550#section-17">
 *          RFC 6550, section 17
 *      </a>
 */
#define GNRC_RPL_INFINITE_RANK (0xFFFF)

/**
 * @brief   Default minimum hop rank increase
 * @see <a href="https://tools.ietf.org/html/rfc6550#section-17">
 *          RFC 6550, section 17
 *      </a>
 */
#ifndef GNRC_RPL_DEFAULT_MIN_HOP_RANK_INCREASE
#define GNRC_RPL_DEFAULT_MIN_HOP_RANK_INCREASE (256)
#endif

/**
 * @brief   Maximum rank increase
 */
#ifndef GNRC_RPL_DEFAULT_MAX_RANK_INCREASE
#define GNRC_RPL_DEFAULT_MAX_RANK_INCREASE (0)
#endif

/**
 * @brief   Number of implemented Objective Functions
 */
#define GNRC_RPL_IMPLEMENTED_OFS_NUMOF (1)

/**
 * @brief   Default Objective Code Point (OF0)
 */
#define GNRC_RPL_DEFAULT_OCP (0)

/**
 * @brief   Default Instance ID
 */
#ifndef GNRC_RPL_DEFAULT_INSTANCE
#define GNRC_RPL_DEFAULT_INSTANCE (0)
#endif

/**
 * @name RPL Mode of Operations
 * @{
 */
#define GNRC_RPL_MOP_NO_DOWNWARD_ROUTES  (0x00)
#define GNRC_RPL_MOP_NON_STORING_MODE    (0x01)
#define GNRC_RPL_MOP_STORING_MODE_NO_MC  (0x02)
#define GNRC_RPL_MOP_STORING_MODE_MC     (0x03)

/** default MOP set on compile time */
#ifndef GNRC_RPL_DEFAULT_MOP
#define GNRC_RPL_DEFAULT_MOP GNRC_RPL_MOP_STORING_MODE_NO_MC
#endif
/** @} */

/**
 * @name Sequence counter handling
 * @see <a href="https://tools.ietf.org/html/rfc6550#section-7.2">
 *          Sequence Counter Operation
 *      </a>
 * @{
 */
#define GNRC_RPL_COUNTER_MAX                 (255)
#define GNRC_RPL_COUNTER_LOWER_REGION        (127)
#define GNRC_RPL_COUNTER_SEQ_WINDOW          (16)
#define GNRC_RPL_COUNTER_INIT                (GNRC_RPL_COUNTER_MAX - GNRC_RPL_COUNTER_SEQ_WINDOW + 1)

static inline uint8_t GNRC_RPL_COUNTER_INCREMENT(uint8_t counter)
{
    return ((counter > GNRC_RPL_COUNTER_LOWER_REGION) ?
            ((counter == GNRC_RPL_COUNTER_MAX) ? counter = 0 : ++counter) :
            ((counter == GNRC_RPL_COUNTER_LOWER_REGION) ? counter = 0 : ++counter));
}

static inline bool GNRC_RPL_COUNTER_IS_INIT(uint8_t counter)
{
    return (counter > GNRC_RPL_COUNTER_LOWER_REGION);
}

static inline bool GNRC_RPL_COUNTER_GREATER_THAN_LOCAL(uint8_t A, uint8_t B)
{
    return (((A < B) && (GNRC_RPL_COUNTER_LOWER_REGION + 1 - B + A < GNRC_RPL_COUNTER_SEQ_WINDOW))
            || ((A > B) && (A - B < GNRC_RPL_COUNTER_SEQ_WINDOW)));
}

static inline bool GNRC_RPL_COUNTER_GREATER_THAN(uint8_t A, uint8_t B)
{
    return ((A > GNRC_RPL_COUNTER_LOWER_REGION) ? ((B > GNRC_RPL_COUNTER_LOWER_REGION) ?
                GNRC_RPL_COUNTER_GREATER_THAN_LOCAL(A, B) : 0) :
            ((B > GNRC_RPL_COUNTER_LOWER_REGION) ? 1 : GNRC_RPL_COUNTER_GREATER_THAN_LOCAL(A, B)));
}
/** @} */

/**
 * @name Trickle parameters
 * @see <a href="https://tools.ietf.org/html/rfc6550#section-8.3.1">
 *          Trickle Parameters
 *      </a>
 * @{
 */
#ifndef GNRC_RPL_DEFAULT_DIO_INTERVAL_DOUBLINGS
#define GNRC_RPL_DEFAULT_DIO_INTERVAL_DOUBLINGS (20)
#endif

#ifndef GNRC_RPL_DEFAULT_DIO_INTERVAL_MIN
#define GNRC_RPL_DEFAULT_DIO_INTERVAL_MIN (3)
#endif

#ifndef GNRC_RPL_DEFAULT_DIO_REDUNDANCY_CONSTANT
#define GNRC_RPL_DEFAULT_DIO_REDUNDANCY_CONSTANT (10)
#endif
/** @} */

/**
 * @name Default parent and route entry lifetime
 * default lifetime will be multiplied by the lifetime unit to obtain the resulting lifetime
 * @see <a href="https://tools.ietf.org/html/rfc6550#section-6.7.6">
            DODAG Configuration
        </a>
 * @{
 */
#ifndef GNRC_RPL_DEFAULT_LIFETIME
#define GNRC_RPL_DEFAULT_LIFETIME (5)
#endif
#ifndef GNRC_RPL_LIFETIME_UNIT
#define GNRC_RPL_LIFETIME_UNIT (60)
#endif
/** @} */

/**
 * @brief Default prefix length for the DODAG id
 */
#define GNRC_RPL_DEFAULT_PREFIX_LEN   (64)

/**
 * @brief Default prefix valid and preferred time for the DODAG id
 * @note Currently not used, but needed for RIOs
 * @see <a href="https://tools.ietf.org/html/rfc6550#section-6.7.5">
 *          Route Information
 *      </a>
 */
#define GNRC_RPL_DEFAULT_PREFIX_LIFETIME  (0xFFFFFFFF)

/**
 * @brief A DODAG can be grounded or floating
 * @see <a href="https://tools.ietf.org/html/rfc6550#section-3.2.4">
 *          Grounded and Floating DODAGs
 *      </a>
 */
#define GNRC_RPL_GROUNDED (1)

/**
 * @name Parameters used for DAO handling
 * @see <a href="https://tools.ietf.org/html/rfc6550#section-17">
            RPL Constants and Variables
        </a>
 * @{
 */
#ifndef GNRC_RPL_DAO_SEND_RETRIES
#define GNRC_RPL_DAO_SEND_RETRIES (4)
#endif
#ifndef GNRC_RPL_DEFAULT_WAIT_FOR_DAO_ACK
#define GNRC_RPL_DEFAULT_WAIT_FOR_DAO_ACK (3)
#endif
#ifndef GNRC_RPL_REGULAR_DAO_INTERVAL
#define GNRC_RPL_REGULAR_DAO_INTERVAL (60)
#endif
#ifndef GNRC_RPL_DEFAULT_DAO_DELAY
#define GNRC_RPL_DEFAULT_DAO_DELAY (1)
#endif
/** @} */

/**
 * @brief Cleanup timeout in seconds
 */
#define GNRC_RPL_CLEANUP_TIME (5)

/**
 * @name Node Status
 * @{
 */
#define GNRC_RPL_NORMAL_NODE (0)
#define GNRC_RPL_ROOT_NODE (1)
#define GNRC_RPL_LEAF_NODE (2)
/** @} */


/**
 * @name RPL Control Message Options
 *  @see <a href="https://tools.ietf.org/html/rfc6550#section-6.7">
 *          RPL Control Message Options
 *      </a>
 * @{
 */
#define GNRC_RPL_OPT_PAD1                 (0)
#define GNRC_RPL_OPT_PADN                 (1)
#define GNRC_RPL_OPT_DAG_METRIC_CONTAINER (2)
#define GNRC_RPL_OPT_ROUTE_INFO           (3)
#define GNRC_RPL_OPT_DODAG_CONF           (4)
#define GNRC_RPL_OPT_TARGET               (5)
#define GNRC_RPL_OPT_TRANSIT              (6)
#define GNRC_RPL_OPT_SOLICITED_INFO       (7)
#define GNRC_RPL_OPT_PREFIX_INFO          (8)
#define GNRC_RPL_OPT_TARGET_DESC          (9)
/** @} */

/**
 * @brief Rank of the root node
 */
#define GNRC_RPL_ROOT_RANK (GNRC_RPL_DEFAULT_MIN_HOP_RANK_INCREASE)

/**
 *  @brief  DIS ICMPv6 code
 *  @see <a href="https://tools.ietf.org/html/rfc6550#section-6">
 *          RFC 6550, section 6
 *      </a>
 */
#define GNRC_RPL_ICMPV6_CODE_DIS (0x00)

/**
 *  @brief  DIO ICMPv6 code
 *  @see <a href="https://tools.ietf.org/html/rfc6550#section-6">
 *          RFC 6550, section 6
 *      </a>
 */
#define GNRC_RPL_ICMPV6_CODE_DIO (0x01)

/**
 *  @brief  DAO ICMPv6 code
 *  @see <a href="https://tools.ietf.org/html/rfc6550#section-6">
 *          RFC 6550, section 6
 *      </a>
 */
#define GNRC_RPL_ICMPV6_CODE_DAO (0x02)

/**
 *  @brief  DAO ACK ICMPv6 code
 *  @see <a href="https://tools.ietf.org/html/rfc6550#section-6">
 *          RFC 6550, section 6
 *      </a>
 */
#define GNRC_RPL_ICMPV6_CODE_DAO_ACK (0x03)

/**
 * @brief Update interval of the lifetime update function
 */
#define GNRC_RPL_LIFETIME_UPDATE_STEP (2)

/**
 *  @brief Rank part of the DODAG
 *  @see <a href="https://tools.ietf.org/html/rfc6550#section-3.5.1">
 *          RFC 6550, section 3.5.1, Rank Comparison (DAGRank())
 *      </a>
 */
#define DAGRANK(rank,mhri)   (rank/mhri)

/**
 *  @name   Global / Local instance id masks
 *  @see <a href="https://tools.ietf.org/html/rfc6550#section-5.1">
 *          RFC 6550, section 5.1, RPL Instance ID
 *      </a>
 *  @{
 */
#define GNRC_RPL_INSTANCE_ID_MSB      (1 << 7)
#define GNRC_RPL_GLOBAL_INSTANCE_MASK (0x7F)
#define GNRC_RPL_LOCAL_INSTANCE_MASK  (0x3F)
#define GNRC_RPL_INSTANCE_D_FLAG_MASK (1 << 6)
/** @} */

/**
 * @brief PID of the RPL thread.
 */
extern kernel_pid_t gnrc_rpl_pid;

/**
 * @brief @see @ref GNRC_RPL_ALL_NODES_ADDR
 */
extern const ipv6_addr_t ipv6_addr_all_rpl_nodes;

#ifdef MODULE_NETSTATS_RPL
/**
 * @brief Statistics for RPL control messages
 */
extern netstats_rpl_t gnrc_rpl_netstats;
#endif

/**
 * @brief Initialization of the RPL thread.
 *
 * @param[in] if_pid            PID of the interface
 *
 * @return  The PID of the RPL thread, on success.
 * @return  a negative errno on error.
 */
kernel_pid_t gnrc_rpl_init(kernel_pid_t if_pid);

/**
 * @brief Initialization of a node as root.
 *
 * @param[in] instance_id       Id of the instance
 * @param[in] dodag_id          Id of the DODAG
 * @param[in] gen_inst_id       Flag indicating whether to generate an instance id.
 *                              If true, @p instance_id will be ignored
 * @param[in] local_inst_id     Flag indicating whether a local or global instance id
 *                              should be generatad
 *
 * @return  Pointer to the new RPL Instance, on success.
 * @return  NULL, otherwise.
 */
gnrc_rpl_instance_t *gnrc_rpl_root_init(uint8_t instance_id, ipv6_addr_t *dodag_id,
                                        bool gen_inst_id, bool local_inst_id);

/**
 * @brief   Send a DIO of the @p instance to the @p destination.
 *
 * @param[in] instance          Pointer to the RPL instance.
 * @param[in] destination       IPv6 addres of the destination.
 */
void gnrc_rpl_send_DIO(gnrc_rpl_instance_t *instance, ipv6_addr_t *destination);

/**
 * @brief   Send a DIS of the @p instace to the @p destination.
 *
 * @param[in] instance          Pointer to the RPL instance, optional.
 * @param[in] destination       IPv6 addres of the destination.
 */
void gnrc_rpl_send_DIS(gnrc_rpl_instance_t *instance, ipv6_addr_t *destination);

/**
 * @brief   Send a DAO of the @p dodag to the @p destination.
 *
 * @param[in] instance          Pointer to the instance.
 * @param[in] destination       IPv6 addres of the destination.
 * @param[in] lifetime          Lifetime of the route to announce.
 */
void gnrc_rpl_send_DAO(gnrc_rpl_instance_t *instance, ipv6_addr_t *destination, uint8_t lifetime);

/**
 * @brief   Send a DAO-ACK of the @p instance to the @p destination.
 *
 * @param[in] instance          Pointer to the RPL instance.
 * @param[in] destination       IPv6 addres of the destination.
 * @param[in] seq				Sequence number to be acknowledged.
 */
void gnrc_rpl_send_DAO_ACK(gnrc_rpl_instance_t *instance, ipv6_addr_t *destination, uint8_t seq);

/**
 * @brief   Parse a DIS.
 *
 * @param[in] dis       Pointer to the DIS message.
 * @param[in] iface     Interface PID of the incoming DIS.
 * @param[in] src       Pointer to the source address of the IPv6 packet.
 * @param[in] dst       Pointer to the destination address of the IPv6 packet.
 * @param[in] len       Length of the IPv6 packet.
 */
void gnrc_rpl_recv_DIS(gnrc_rpl_dis_t *dis, kernel_pid_t iface, ipv6_addr_t *src,
                       ipv6_addr_t *dst, uint16_t len);

/**
 * @brief   Parse a DIO.
 *
 * @param[in] dio       Pointer to the DIO message.
 * @param[in] iface     Interface PID of the incoming DIO.
 * @param[in] src       Pointer to the source address of the IPv6 packet.
 * @param[in] dst       Pointer to the destination address of the IPv6 packet.
 * @param[in] len       Length of the IPv6 packet.
 */
void gnrc_rpl_recv_DIO(gnrc_rpl_dio_t *dio, kernel_pid_t iface, ipv6_addr_t *src, ipv6_addr_t *dst,
                       uint16_t len);

/**
 * @brief   Parse a DAO.
 *
 * @param[in] dao       Pointer to the DAO message.
 * @param[in] iface     Interface PID of the incoming DIO.
 * @param[in] src       Pointer to the source address of the IPv6 packet.
 * @param[in] dst       Pointer to the destination address of the IPv6 packet.
 * @param[in] len       Length of the IPv6 packet.
 */
void gnrc_rpl_recv_DAO(gnrc_rpl_dao_t *dao, kernel_pid_t iface, ipv6_addr_t *src, ipv6_addr_t *dst,
                       uint16_t len);

/**
 * @brief   Parse a DAO-ACK.
 *
 * @param[in] dao_ack   Pointer to the DAO-ACK message.
 * @param[in] iface     Interface PID of the incoming DIO.
 * @param[in] src       Pointer to the source address of the IPv6 packet.
 * @param[in] dst       Pointer to the destination address of the IPv6 packet.
 * @param[in] len       Length of the IPv6 packet.
 */
void gnrc_rpl_recv_DAO_ACK(gnrc_rpl_dao_ack_t *dao_ack, kernel_pid_t iface, ipv6_addr_t *src,
                           ipv6_addr_t *dst, uint16_t len);

/**
 * @brief   Delay the DAO sending interval
 *
 * @param[in] dodag     The DODAG of the DAO
 */
void gnrc_rpl_delay_dao(gnrc_rpl_dodag_t *dodag);

/**
 * @brief   Long delay the DAO sending interval
 *
 * @param[in] dodag     The DODAG of the DAO
 */
void gnrc_rpl_long_delay_dao(gnrc_rpl_dodag_t *dodag);

/**
 * @brief Create a new RPL instance and RPL DODAG.
 *
 * @param[in] instance_id       Id of the instance
 * @param[in] dodag_id          Id of the DODAG
 * @param[in] mop               Mode of Operation
 *
 * @return  Pointer to the new RPL instance, on success.
 * @return  NULL, otherwise.
 */
gnrc_rpl_instance_t *gnrc_rpl_root_instance_init(uint8_t instance_id, ipv6_addr_t *dodag_id,
                                                 uint8_t mop);

/**
 * @brief Send a control message
 *
 * @param[in] pkt               gnrc_pktnsip_t to send
 * @param[in] iface             Interface PID to send this pkt to
 * @param[in] src               Source address of the packet
 * @param[in] dst               Destination address of the packet
 * @param[in] dodag_id          Id of the DODAG
 */
void gnrc_rpl_send(gnrc_pktsnip_t *pkt, kernel_pid_t iface, ipv6_addr_t *src, ipv6_addr_t *dst,
                   ipv6_addr_t *dodag_id);

/**
 * @brief Generate a local or global instance id
 *
 * @param[in] local             flag to indicate whether a local or global instance id is requested
 *
 * @return  Local instance id, if @p local is true
 * @return  Global instance id, otherwise.
 */
uint8_t gnrc_rpl_gen_instance_id(bool local);

#ifndef GNRC_RPL_WITHOUT_PIO
/**
 * @brief (De-)Activate the transmission of Prefix Information Options within DIOs
 *        for a particular DODAG
 *
 * @param[in] dodag             Pointer to the DODAG
 * @param[in] status            true for activating PIOs and false for deactivating them
 */
static inline void gnrc_rpl_config_pio(gnrc_rpl_dodag_t *dodag, bool status)
{
    dodag->dio_opts = (dodag->dio_opts & ~GNRC_RPL_REQ_DIO_OPT_PREFIX_INFO) |
                      (status << GNRC_RPL_REQ_DIO_OPT_PREFIX_INFO_SHIFT);
}
#endif

#ifdef __cplusplus
}
#endif

#endif /* GNRC_RPL_H_ */
/** @} */