44#include "contiki-net.h"
53#if ROUTING_CONF_RPL_LITE
54#include "net/routing/rpl-lite/rpl.h"
57#if ROUTING_CONF_RPL_CLASSIC
58#include "net/routing/rpl-classic/rpl.h"
59#include "net/routing/rpl-classic/rpl-private.h"
63extern uint16_t uip_slen;
68#define ESMRF_VERBOSE NONE
70#if DEBUG && ESMRF_VERBOSE
71#define VERBOSE_PRINTF(...) PRINTF(__VA_ARGS__)
72#define VERBOSE_PRINT_SEED(s) PRINT_SEED(s)
74#define VERBOSE_PRINTF(...)
75#define VERBOSE_PRINT_SEED(...)
81static struct esmrf_stats stats;
83#define ESMRF_STATS_ADD(x) stats.x++
84#define ESMRF_STATS_INIT() do { memset(&stats, 0, sizeof(stats)); } while(0)
86#define ESMRF_STATS_ADD(x)
87#define ESMRF_STATS_INIT()
93#define ESMRF_FWD_DELAY() (CLOCK_SECOND / 8)
95#define ESMRF_INTERVAL_COUNT ((CLOCK_SECOND >> 2) / fwd_delay)
99static struct ctimer mcast_periodic;
100static uint8_t mcast_len;
102static uint8_t fwd_delay;
103static uint8_t fwd_spread;
105static uip_ipaddr_t src_ip;
106static uip_ipaddr_t des_ip;
110static void icmp_input(
void);
111static void icmp_output(
void);
112static void mcast_fwd(
void *p);
116struct multicast_on_behalf{
118 uip_ipaddr_t mcast_ip;
119 uint8_t mcast_payload[
UIP_BUFSIZE - UIP_IPUDPH_LEN];
121#define UIP_ICMP_MOB 18
125static struct multicast_on_behalf *locmobptr;
130 UIP_ICMP6_HANDLER_CODE_ANY, icmp_input);
135 uint16_t payload_len=0;
138 struct multicast_on_behalf *mob;
139 mob = (
struct multicast_on_behalf *)UIP_ICMP_PAYLOAD;
140 memmove(&mob->mcast_payload, &
uip_buf[UIP_IPUDPH_LEN], uip_slen);
151 payload_len = UIP_ICMP_MOB + uip_slen;
153 dag_t = rpl_get_any_dag();
155 PRINTF(
"ESMRF: No DODAG\n");
162 VERBOSE_PRINTF(
"ESMRF: ICMPv6 Out - Hdr @ %p, payload @ %p to: ",
UIP_ICMP_BUF, mob);
166 uipbuf_set_len_field(
UIP_IP_BUF, UIP_ICMPH_LEN + payload_len);
174 uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + payload_len;
176 VERBOSE_PRINTF(
"ESMRF: ICMPv6 Out - %u bytes, uip_len %u bytes, uip_ext_len %u bytes\n",
180 ESMRF_STATS_ADD(icmp_out);
187#if UIP_CONF_IPV6_CHECKS
189 PRINTF(
"ESMRF: ICMPv6 In, bad ICMP code\n");
190 ESMRF_STATS_ADD(icmp_bad);
194 PRINTF(
"ESMRF: ICMPv6 In, bad TTL\n");
195 ESMRF_STATS_ADD(icmp_bad);
202 PRINTF(
"ESMRF: ICMPv6 In from ");
208 VERBOSE_PRINTF(
"ESMRF: ICMPv6 In, parse from %p to %p\n",
210 (uint8_t *)UIP_ICMP_PAYLOAD +
uip_len -
211 uip_l3_icmp_hdr_len);
214 locmobptr = (
struct multicast_on_behalf *) UIP_ICMP_PAYLOAD;
215 loclen =
uip_len - (uip_l3_icmp_hdr_len + UIP_ICMP_MOB);
222 c->
rport = locmobptr->mcast_port;
225 memmove(&
uip_buf[UIP_IPUDPH_LEN], locmobptr->mcast_payload,
229 uip_process(UIP_UDP_SEND_CONN);
237 UIP_UDP_BUF->udpchksum = 0;
239 uip_process(UIP_DATA);
241 memcpy(
uip_buf, &mcast_buf, mcast_len);
245 UIP_UDP_BUF->udpchksum = 0;
249 PRINTF(
"ESMRF: Forward this packet\n");
259 memcpy(
uip_buf, &mcast_buf, mcast_len);
270 uip_ipaddr_t *parent_ipaddr;
271 const uip_lladdr_t *parent_lladdr;
281 d = rpl_get_any_dag();
283 PRINTF(
"ESMRF: No DODAG\n");
284 UIP_MCAST6_STATS_ADD(mcast_dropped);
285 return UIP_MCAST6_DROP;
289 parent_ipaddr = rpl_parent_get_ipaddr(d->preferred_parent);
292 if(parent_lladdr == NULL) {
293 PRINTF(
"ESMRF: No Parent found\n");
294 UIP_MCAST6_STATS_ADD(mcast_dropped);
295 return UIP_MCAST6_DROP;
302 if(memcmp(parent_lladdr, packetbuf_addr(PACKETBUF_ADDR_SENDER),
304 PRINTF(
"ESMRF: Routable in but ESMRF ignored it\n");
305 UIP_MCAST6_STATS_ADD(mcast_dropped);
306 return UIP_MCAST6_DROP;
310 UIP_MCAST6_STATS_ADD(mcast_dropped);
311 PRINTF(
"ESMRF: TTL too low\n");
312 return UIP_MCAST6_DROP;
315 UIP_MCAST6_STATS_ADD(mcast_in_all);
316 UIP_MCAST6_STATS_ADD(mcast_in_unique);
322 UIP_MCAST6_STATS_ADD(mcast_fwd);
329 fwd_delay = ESMRF_FWD_DELAY();
332#if ESMRF_MIN_FWD_DELAY
333 if(fwd_delay < ESMRF_MIN_FWD_DELAY) {
334 fwd_delay = ESMRF_MIN_FWD_DELAY;
345 fwd_spread = ESMRF_INTERVAL_COUNT;
346 if(fwd_spread > ESMRF_MAX_SPREAD) {
347 fwd_spread = ESMRF_MAX_SPREAD;
350 fwd_delay = fwd_delay * (1 + ((
random_rand() >> 11) % fwd_spread));
355 ctimer_set(&mcast_periodic, fwd_delay, mcast_fwd, NULL);
357 PRINTF(
"ESMRF: %u bytes: fwd in %u [%u]\n",
358 uip_len, fwd_delay, fwd_spread);
360 PRINTF(
"ESMRF: Group unknown, dropping\n");
364 if(!uip_ds6_is_my_maddr(&
UIP_IP_BUF->destipaddr)) {
365 PRINTF(
"ESMRF: Not a group member. No further processing\n");
366 return UIP_MCAST6_DROP;
368 PRINTF(
"ESMRF: Ours. Deliver to upper layers\n");
369 UIP_MCAST6_STATS_ADD(mcast_in_ours);
370 return UIP_MCAST6_ACCEPT;
378 UIP_MCAST6_STATS_INIT(&stats);
385 PRINTF(
"ESMRF: No UDP connection available\n");
393 dag_t = rpl_get_any_dag();
395 PRINTF(
"ESMRF: There is no DODAG\n");
398 if(dag_t->rank == RPL_MIN_HOPRANKINC){
399 PRINTF(
"ESMRF: I am the Root, thus send the multicast packet normally. \n");
403 PRINTF(
"ESMRF: I am not the Root\n");
404 PRINTF(
"Send multicast-on-befalf message (ICMPv6) instead to ");
405 PRINT6ADDR(&dag_t->dag_id);
Header file for the Enhanced Stateless Multicast RPL Forwarding (ESMRF)
unsigned short random_rand(void)
Generates a new random number using the cc2538 RNG.
static void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
static void icmp_in(void)
struct uip_udp_conn * udp_new(const uip_ipaddr_t *ripaddr, uint16_t port, void *appstate)
Create a new UDP connection.
uint8_t tcpip_output(const uip_lladdr_t *a)
Output packet to layer 2 The eventual parameter is the MAC address of the destination.
void tcpip_ipv6_output(void)
This function does address resolution and then calls tcpip_output.
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.
#define UIP_ICMP_BUF
Direct access to ICMP, UDP, and TCP headers and payload, with implicit ext header offset (global uip_...
#define UIP_LLADDR_LEN
802.15.4 address
bool uip_remove_ext_hdr(void)
Removes all IPv6 extension headers from uip_buf, updates length fields (uip_len and uip_ext_len)
void uip_ds6_select_src(uip_ipaddr_t *src, uip_ipaddr_t *dst)
Source address selection, see RFC 3484.
void uip_icmp6_register_input_handler(uip_icmp6_input_handler_t *handler)
Register a handler which can handle a specific ICMPv6 message type.
#define ICMP6_ESMRF
ESMRF Multicast.
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.
#define UIP_IP_BUF
Direct access to IPv6 header.
#define uip_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
#define uip_buf
Macro to access uip_aligned_buf as an array of bytes.
uint16_t uip_ext_len
The length of the extension headers.
uint16_t uip_len
The length of the packet in the uip_buf buffer.
#define UIP_BUFSIZE
The size of the uIP packet buffer.
Include file for the Contiki low-layer network stack (NETSTACK)
Header file for the Packet buffer (packetbuf) management.
Routing driver header file.
Public configuration and API declarations for ContikiRPL.
The data structure used to represent a multicast engine.
void(* out)(void)
Process an outgoing datagram with a multicast IPv6 destination address.
uint8_t(* in)(void)
Process an incoming multicast datagram and determine whether it should be delivered up the stack or n...
void(* init)(void)
Initialize the multicast engine.
Representation of a uIP UDP connection.
uip_ipaddr_t ripaddr
The IP address of the remote peer.
uint16_t rport
The remote port number in network byte order.
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.
Header file for the uIP TCP/IP stack.