Blame view

RIOT/sys/include/net/gnrc/rpl.h 18.4 KB
a752c7ab   elopes   add first test an...
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
  /*
   * 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 NET_GNRC_RPL_H
  #define NET_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
   */
  #define GNRC_RPL_MSG_TYPE_TRICKLE_MSG         (0x0901)
  
  /**
   * @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 /* NET_GNRC_RPL_H */
  /** @} */