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 memcpy(&mob->mcast_payload, &
uip_buf[UIP_IPUDPH_LEN], uip_slen);
151 payload_len = UIP_ICMP_MOB + uip_slen;
157 VERBOSE_PRINTF(
"ESMRF: ICMPv6 Out - Hdr @ %p, payload @ %p to: ",
UIP_ICMP_BUF, mob);
161 uipbuf_set_len_field(
UIP_IP_BUF, UIP_ICMPH_LEN + payload_len);
169 uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + payload_len;
171 VERBOSE_PRINTF(
"ESMRF: ICMPv6 Out - %u bytes, uip_len %u bytes, uip_ext_len %u bytes\n",
175 ESMRF_STATS_ADD(icmp_out);
182#if UIP_CONF_IPV6_CHECKS
184 PRINTF(
"ESMRF: ICMPv6 In, bad ICMP code\n");
185 ESMRF_STATS_ADD(icmp_bad);
189 PRINTF(
"ESMRF: ICMPv6 In, bad TTL\n");
190 ESMRF_STATS_ADD(icmp_bad);
197 PRINTF(
"ESMRF: ICMPv6 In from ");
203 VERBOSE_PRINTF(
"ESMRF: ICMPv6 In, parse from %p to %p\n",
205 (uint8_t *)UIP_ICMP_PAYLOAD +
uip_len -
206 uip_l3_icmp_hdr_len);
209 locmobptr = (
struct multicast_on_behalf *) UIP_ICMP_PAYLOAD;
210 loclen =
uip_len - (uip_l3_icmp_hdr_len + UIP_ICMP_MOB);
217 c->
rport = locmobptr->mcast_port;
220 memcpy(&
uip_buf[UIP_IPUDPH_LEN], locmobptr->mcast_payload,
224 uip_process(UIP_UDP_SEND_CONN);
232 UIP_UDP_BUF->udpchksum = 0;
234 uip_process(UIP_DATA);
236 memcpy(
uip_buf, &mcast_buf, mcast_len);
240 UIP_UDP_BUF->udpchksum = 0;
244 PRINTF(
"ESMRF: Forward this packet\n");
254 memcpy(
uip_buf, &mcast_buf, mcast_len);
265 uip_ipaddr_t *parent_ipaddr;
266 const uip_lladdr_t *parent_lladdr;
278 PRINTF(
"ESMRF: No DODAG\n");
279 UIP_MCAST6_STATS_ADD(mcast_dropped);
280 return UIP_MCAST6_DROP;
284 parent_ipaddr = rpl_parent_get_ipaddr(d->preferred_parent);
287 if(parent_lladdr == NULL) {
288 PRINTF(
"ESMRF: No Parent found\n");
289 UIP_MCAST6_STATS_ADD(mcast_dropped);
290 return UIP_MCAST6_DROP;
297 if(memcmp(parent_lladdr, packetbuf_addr(PACKETBUF_ADDR_SENDER),
299 PRINTF(
"ESMRF: Routable in but ESMRF ignored it\n");
300 UIP_MCAST6_STATS_ADD(mcast_dropped);
301 return UIP_MCAST6_DROP;
305 UIP_MCAST6_STATS_ADD(mcast_dropped);
306 PRINTF(
"ESMRF: TTL too low\n");
307 return UIP_MCAST6_DROP;
310 UIP_MCAST6_STATS_ADD(mcast_in_all);
311 UIP_MCAST6_STATS_ADD(mcast_in_unique);
317 UIP_MCAST6_STATS_ADD(mcast_fwd);
324 fwd_delay = ESMRF_FWD_DELAY();
327#if ESMRF_MIN_FWD_DELAY
328 if(fwd_delay < ESMRF_MIN_FWD_DELAY) {
329 fwd_delay = ESMRF_MIN_FWD_DELAY;
340 fwd_spread = ESMRF_INTERVAL_COUNT;
341 if(fwd_spread > ESMRF_MAX_SPREAD) {
342 fwd_spread = ESMRF_MAX_SPREAD;
345 fwd_delay = fwd_delay * (1 + ((
random_rand() >> 11) % fwd_spread));
350 ctimer_set(&mcast_periodic, fwd_delay, mcast_fwd, NULL);
352 PRINTF(
"ESMRF: %u bytes: fwd in %u [%u]\n",
353 uip_len, fwd_delay, fwd_spread);
355 PRINTF(
"ESMRF: Group unknown, dropping\n");
359 if(!uip_ds6_is_my_maddr(&
UIP_IP_BUF->destipaddr)) {
360 PRINTF(
"ESMRF: Not a group member. No further processing\n");
361 return UIP_MCAST6_DROP;
363 PRINTF(
"ESMRF: Ours. Deliver to upper layers\n");
364 UIP_MCAST6_STATS_ADD(mcast_in_ours);
365 return UIP_MCAST6_ACCEPT;
373 UIP_MCAST6_STATS_INIT(&stats);
387 PRINTF(
"ESMRF: There is no DODAG\n");
390 if(dag_t->rank == RPL_MIN_HOPRANKINC){
391 PRINTF(
"ESMRF: I am the Root, thus send the multicast packet normally. \n");
395 PRINTF(
"ESMRF: I am not the Root\n");
396 PRINTF(
"Send multicast-on-befalf message (ICMPv6) instead to ");
397 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.
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.
rpl_dag_t * rpl_get_any_dag(void)
Returns pointer to any DAG (for compatibility with legagy RPL code)
#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.