PageRenderTime 59ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 0ms

/core/net/ipv6/multicast/smrf.c

https://gitlab.com/rdeterre/contiki
C | 214 lines | 110 code | 17 blank | 87 comment | 14 complexity | 97f0fb06b2257725de5cb31db8239b33 MD5 | raw 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. * \addtogroup smrf-multicast
  33. * @{
  34. */
  35. /**
  36. * \file
  37. * This file implements 'Stateless Multicast RPL Forwarding' (SMRF)
  38. *
  39. * \author
  40. * George Oikonomou - <oikonomou@users.sourceforge.net>
  41. */
  42. #include "contiki.h"
  43. #include "contiki-net.h"
  44. #include "net/ipv6/multicast/uip-mcast6.h"
  45. #include "net/ipv6/multicast/uip-mcast6-route.h"
  46. #include "net/ipv6/multicast/uip-mcast6-stats.h"
  47. #include "net/ipv6/multicast/smrf.h"
  48. #include "net/rpl/rpl.h"
  49. #include "net/netstack.h"
  50. #include <string.h>
  51. #define DEBUG DEBUG_NONE
  52. #include "net/ip/uip-debug.h"
  53. /*---------------------------------------------------------------------------*/
  54. /* Macros */
  55. /*---------------------------------------------------------------------------*/
  56. /* CCI */
  57. #define SMRF_FWD_DELAY() NETSTACK_RDC.channel_check_interval()
  58. /* Number of slots in the next 500ms */
  59. #define SMRF_INTERVAL_COUNT ((CLOCK_SECOND >> 2) / fwd_delay)
  60. /*---------------------------------------------------------------------------*/
  61. /* Internal Data */
  62. /*---------------------------------------------------------------------------*/
  63. static struct ctimer mcast_periodic;
  64. static uint8_t mcast_len;
  65. static uip_buf_t mcast_buf;
  66. static uint8_t fwd_delay;
  67. static uint8_t fwd_spread;
  68. /*---------------------------------------------------------------------------*/
  69. /* uIPv6 Pointers */
  70. /*---------------------------------------------------------------------------*/
  71. #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
  72. /*---------------------------------------------------------------------------*/
  73. static void
  74. mcast_fwd(void *p)
  75. {
  76. memcpy(uip_buf, &mcast_buf, mcast_len);
  77. uip_len = mcast_len;
  78. UIP_IP_BUF->ttl--;
  79. tcpip_output(NULL);
  80. uip_clear_buf();
  81. }
  82. /*---------------------------------------------------------------------------*/
  83. static uint8_t
  84. in()
  85. {
  86. rpl_dag_t *d; /* Our DODAG */
  87. uip_ipaddr_t *parent_ipaddr; /* Our pref. parent's IPv6 address */
  88. const uip_lladdr_t *parent_lladdr; /* Our pref. parent's LL address */
  89. /*
  90. * Fetch a pointer to the LL address of our preferred parent
  91. *
  92. * ToDo: This rpl_get_any_dag() call is a dirty replacement of the previous
  93. * rpl_get_dag(RPL_DEFAULT_INSTANCE);
  94. * so that things can compile with the new RPL code. This needs updated to
  95. * read instance ID from the RPL HBHO and use the correct parent accordingly
  96. */
  97. d = rpl_get_any_dag();
  98. if(!d) {
  99. UIP_MCAST6_STATS_ADD(mcast_dropped);
  100. return UIP_MCAST6_DROP;
  101. }
  102. /* Retrieve our preferred parent's LL address */
  103. parent_ipaddr = rpl_get_parent_ipaddr(d->preferred_parent);
  104. parent_lladdr = uip_ds6_nbr_lladdr_from_ipaddr(parent_ipaddr);
  105. if(parent_lladdr == NULL) {
  106. UIP_MCAST6_STATS_ADD(mcast_dropped);
  107. return UIP_MCAST6_DROP;
  108. }
  109. /*
  110. * We accept a datagram if it arrived from our preferred parent, discard
  111. * otherwise.
  112. */
  113. if(memcmp(parent_lladdr, packetbuf_addr(PACKETBUF_ADDR_SENDER),
  114. UIP_LLADDR_LEN)) {
  115. PRINTF("SMRF: Routable in but SMRF ignored it\n");
  116. UIP_MCAST6_STATS_ADD(mcast_dropped);
  117. return UIP_MCAST6_DROP;
  118. }
  119. if(UIP_IP_BUF->ttl <= 1) {
  120. UIP_MCAST6_STATS_ADD(mcast_dropped);
  121. return UIP_MCAST6_DROP;
  122. }
  123. UIP_MCAST6_STATS_ADD(mcast_in_all);
  124. UIP_MCAST6_STATS_ADD(mcast_in_unique);
  125. /* If we have an entry in the mcast routing table, something with
  126. * a higher RPL rank (somewhere down the tree) is a group member */
  127. if(uip_mcast6_route_lookup(&UIP_IP_BUF->destipaddr)) {
  128. /* If we enter here, we will definitely forward */
  129. UIP_MCAST6_STATS_ADD(mcast_fwd);
  130. /*
  131. * Add a delay (D) of at least SMRF_FWD_DELAY() to compensate for how
  132. * contikimac handles broadcasts. We can't start our TX before the sender
  133. * has finished its own.
  134. */
  135. fwd_delay = SMRF_FWD_DELAY();
  136. /* Finalise D: D = min(SMRF_FWD_DELAY(), SMRF_MIN_FWD_DELAY) */
  137. #if SMRF_MIN_FWD_DELAY
  138. if(fwd_delay < SMRF_MIN_FWD_DELAY) {
  139. fwd_delay = SMRF_MIN_FWD_DELAY;
  140. }
  141. #endif
  142. if(fwd_delay == 0) {
  143. /* No delay required, send it, do it now, why wait? */
  144. UIP_IP_BUF->ttl--;
  145. tcpip_output(NULL);
  146. UIP_IP_BUF->ttl++; /* Restore before potential upstack delivery */
  147. } else {
  148. /* Randomise final delay in [D , D*Spread], step D */
  149. fwd_spread = SMRF_INTERVAL_COUNT;
  150. if(fwd_spread > SMRF_MAX_SPREAD) {
  151. fwd_spread = SMRF_MAX_SPREAD;
  152. }
  153. if(fwd_spread) {
  154. fwd_delay = fwd_delay * (1 + ((random_rand() >> 11) % fwd_spread));
  155. }
  156. memcpy(&mcast_buf, uip_buf, uip_len);
  157. mcast_len = uip_len;
  158. ctimer_set(&mcast_periodic, fwd_delay, mcast_fwd, NULL);
  159. }
  160. PRINTF("SMRF: %u bytes: fwd in %u [%u]\n",
  161. uip_len, fwd_delay, fwd_spread);
  162. }
  163. /* Done with this packet unless we are a member of the mcast group */
  164. if(!uip_ds6_is_my_maddr(&UIP_IP_BUF->destipaddr)) {
  165. PRINTF("SMRF: Not a group member. No further processing\n");
  166. return UIP_MCAST6_DROP;
  167. } else {
  168. PRINTF("SMRF: Ours. Deliver to upper layers\n");
  169. UIP_MCAST6_STATS_ADD(mcast_in_ours);
  170. return UIP_MCAST6_ACCEPT;
  171. }
  172. }
  173. /*---------------------------------------------------------------------------*/
  174. static void
  175. init()
  176. {
  177. UIP_MCAST6_STATS_INIT(NULL);
  178. uip_mcast6_route_init();
  179. }
  180. /*---------------------------------------------------------------------------*/
  181. static void
  182. out()
  183. {
  184. return;
  185. }
  186. /*---------------------------------------------------------------------------*/
  187. /**
  188. * \brief The SMRF engine driver
  189. */
  190. const struct uip_mcast6_driver smrf_driver = {
  191. "SMRF",
  192. init,
  193. out,
  194. in,
  195. };
  196. /*---------------------------------------------------------------------------*/
  197. /** @} */