Contiki-NG
smrf.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2010, Loughborough University - Computer Science
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the Institute nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * This file is part of the Contiki operating system.
30 */
31
32/**
33 * \addtogroup smrf-multicast
34 * @{
35 */
36/**
37 * \file
38 * This file implements 'Stateless Multicast RPL Forwarding' (SMRF)
39 *
40 * \author
41 * George Oikonomou - <oikonomou@users.sourceforge.net>
42 */
43
44#include "contiki.h"
45#include "contiki-net.h"
50#include "net/routing/routing.h"
51#include "net/netstack.h"
52#include "net/packetbuf.h"
53#if ROUTING_CONF_RPL_LITE
54#include "net/routing/rpl-lite/rpl.h"
55#endif /* ROUTING_CONF_RPL_LITE */
56#if ROUTING_CONF_RPL_CLASSIC
57#include "net/routing/rpl-classic/rpl.h"
58#endif /* ROUTING_CONF_RPL_CLASSIC */
59#include <string.h>
60
61#define DEBUG DEBUG_NONE
62#include "net/ipv6/uip-debug.h"
63
64/*---------------------------------------------------------------------------*/
65/* Macros */
66/*---------------------------------------------------------------------------*/
67/* CCI */
68#define SMRF_FWD_DELAY() (CLOCK_SECOND / 8)
69/* Number of slots in the next 500ms */
70#define SMRF_INTERVAL_COUNT ((CLOCK_SECOND >> 2) / fwd_delay)
71/*---------------------------------------------------------------------------*/
72/* Internal Data */
73/*---------------------------------------------------------------------------*/
74static struct ctimer mcast_periodic;
75static uint8_t mcast_len;
76static uip_buf_t mcast_buf;
77static uint8_t fwd_delay;
78static uint8_t fwd_spread;
79/*---------------------------------------------------------------------------*/
80static void
81mcast_fwd(void *p)
82{
83 memcpy(uip_buf, &mcast_buf, mcast_len);
84 uip_len = mcast_len;
85 UIP_IP_BUF->ttl--;
86 tcpip_output(NULL);
87 uipbuf_clear();
88}
89/*---------------------------------------------------------------------------*/
90static uint8_t
91in()
92{
93 rpl_dag_t *d; /* Our DODAG */
94 uip_ipaddr_t *parent_ipaddr; /* Our pref. parent's IPv6 address */
95 const uip_lladdr_t *parent_lladdr; /* Our pref. parent's LL address */
96
97 /*
98 * Fetch a pointer to the LL address of our preferred parent
99 *
100 * ToDo: This rpl_get_any_dag() call is a dirty replacement of the previous
101 * rpl_get_dag(RPL_DEFAULT_INSTANCE);
102 * so that things can compile with the new RPL code. This needs updated to
103 * read instance ID from the RPL HBHO and use the correct parent accordingly
104 */
105 d = rpl_get_any_dag();
106 if(!d) {
107 PRINTF("SMRF: No DODAG\n");
108 UIP_MCAST6_STATS_ADD(mcast_dropped);
109 return UIP_MCAST6_DROP;
110 }
111
112 /* Retrieve our preferred parent's LL address */
113 parent_ipaddr = rpl_parent_get_ipaddr(d->preferred_parent);
114 parent_lladdr = uip_ds6_nbr_lladdr_from_ipaddr(parent_ipaddr);
115
116 if(parent_lladdr == NULL) {
117 PRINTF("SMRF: No Parent found\n");
118 UIP_MCAST6_STATS_ADD(mcast_dropped);
119 return UIP_MCAST6_DROP;
120 }
121
122 /*
123 * We accept a datagram if it arrived from our preferred parent, discard
124 * otherwise.
125 */
126 if(memcmp(parent_lladdr, packetbuf_addr(PACKETBUF_ADDR_SENDER),
128 PRINTF("SMRF: Routable in but SMRF ignored it\n");
129 UIP_MCAST6_STATS_ADD(mcast_dropped);
130 return UIP_MCAST6_DROP;
131 }
132
133 if(UIP_IP_BUF->ttl <= 1) {
134 UIP_MCAST6_STATS_ADD(mcast_dropped);
135 PRINTF("SMRF: TTL too low\n");
136 return UIP_MCAST6_DROP;
137 }
138
139 UIP_MCAST6_STATS_ADD(mcast_in_all);
140 UIP_MCAST6_STATS_ADD(mcast_in_unique);
141
142 /* If we have an entry in the mcast routing table, something with
143 * a higher RPL rank (somewhere down the tree) is a group member */
144 if(uip_mcast6_route_lookup(&UIP_IP_BUF->destipaddr)) {
145 /* If we enter here, we will definitely forward */
146 UIP_MCAST6_STATS_ADD(mcast_fwd);
147
148 /*
149 * Add a delay (D) of at least SMRF_FWD_DELAY() to compensate for how
150 * contikimac handles broadcasts. We can't start our TX before the sender
151 * has finished its own.
152 */
153 fwd_delay = SMRF_FWD_DELAY();
154
155 /* Finalise D: D = min(SMRF_FWD_DELAY(), SMRF_MIN_FWD_DELAY) */
156#if SMRF_MIN_FWD_DELAY
157 if(fwd_delay < SMRF_MIN_FWD_DELAY) {
158 fwd_delay = SMRF_MIN_FWD_DELAY;
159 }
160#endif
161
162 if(fwd_delay == 0) {
163 /* No delay required, send it, do it now, why wait? */
164 UIP_IP_BUF->ttl--;
165 tcpip_output(NULL);
166 UIP_IP_BUF->ttl++; /* Restore before potential upstack delivery */
167 } else {
168 /* Randomise final delay in [D , D*Spread], step D */
169 fwd_spread = SMRF_INTERVAL_COUNT;
170 if(fwd_spread > SMRF_MAX_SPREAD) {
171 fwd_spread = SMRF_MAX_SPREAD;
172 }
173 if(fwd_spread) {
174 fwd_delay = fwd_delay * (1 + ((random_rand() >> 11) % fwd_spread));
175 }
176
177 memcpy(&mcast_buf, uip_buf, uip_len);
178 mcast_len = uip_len;
179 ctimer_set(&mcast_periodic, fwd_delay, mcast_fwd, NULL);
180 }
181 PRINTF("SMRF: %u bytes: fwd in %u [%u]\n",
182 uip_len, fwd_delay, fwd_spread);
183 } else {
184 PRINTF("SMRF: Group unknown, dropping\n");
185 }
186
187 /* Done with this packet unless we are a member of the mcast group */
188 if(!uip_ds6_is_my_maddr(&UIP_IP_BUF->destipaddr)) {
189 PRINTF("SMRF: Not a group member. No further processing\n");
190 return UIP_MCAST6_DROP;
191 } else {
192 PRINTF("SMRF: Ours. Deliver to upper layers\n");
193 UIP_MCAST6_STATS_ADD(mcast_in_ours);
194 return UIP_MCAST6_ACCEPT;
195 }
196}
197/*---------------------------------------------------------------------------*/
198static void
199init()
200{
201 UIP_MCAST6_STATS_INIT(NULL);
202
204}
205/*---------------------------------------------------------------------------*/
206static void
207out()
208{
209 return;
210}
211/*---------------------------------------------------------------------------*/
212/**
213 * \brief The SMRF engine driver
214 */
216 "SMRF",
217 init,
218 out,
219 in,
220};
221/*---------------------------------------------------------------------------*/
222/** @} */
unsigned short random_rand(void)
Generates a new random number using the cc2538 RNG.
Definition: random.c:58
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
Definition: ctimer.c:99
const struct uip_mcast6_driver smrf_driver
The SMRF engine driver.
Definition: smrf.c:215
uint8_t tcpip_output(const uip_lladdr_t *a)
Output packet to layer 2 The eventual parameter is the MAC address of the destination.
Definition: tcpip.c:106
uip_mcast6_route_t * uip_mcast6_route_lookup(uip_ipaddr_t *group)
Lookup a multicast route.
void uip_mcast6_route_init()
Multicast routing table init routine.
rpl_dag_t * rpl_get_any_dag(void)
Returns pointer to any DAG (for compatibility with legagy RPL code)
Definition: rpl-dag.c:1090
#define UIP_LLADDR_LEN
802.15.4 address
Definition: uip.h:145
const uip_lladdr_t * uip_ds6_nbr_lladdr_from_ipaddr(const uip_ipaddr_t *ipaddr)
Get the link-layer address associated with a specified IPv6 address.
Definition: uip-ds6-nbr.c:543
#define UIP_IP_BUF
Direct access to IPv6 header.
Definition: uip.h:71
#define uip_buf
Macro to access uip_aligned_buf as an array of bytes.
Definition: uip.h:465
uint16_t uip_len
The length of the packet in the uip_buf buffer.
Definition: uip6.c:159
Include file for the Contiki low-layer network stack (NETSTACK)
Header file for the Packet buffer (packetbuf) management.
Routing driver header file.
Header file for the SMRF forwarding engine.
RPL DAG structure.
Definition: rpl.h:138
The data structure used to represent a multicast engine.
Definition: uip-mcast6.h:101
void(* out)(void)
Process an outgoing datagram with a multicast IPv6 destination address.
Definition: uip-mcast6.h:121
uint8_t(* in)(void)
Process an incoming multicast datagram and determine whether it should be delivered up the stack or n...
Definition: uip-mcast6.h:139
void(* init)(void)
Initialize the multicast engine.
Definition: uip-mcast6.h:106
A set of debugging macros for the IP stack.
Header file for multicast routing table manipulation.
Header file for IPv6 multicast forwarding stats maintenance.
This header file contains configuration directives for uIPv6 multicast support.
The uIP packet buffer.
Definition: uip.h:457