mld_group.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. /****************************************************************************
  2. * net/mld/mld_group.c
  3. *
  4. * Licensed to the Apache Software Foundation (ASF) under one or more
  5. * contributor license agreements. See the NOTICE file distributed with
  6. * this work for additional information regarding copyright ownership. The
  7. * ASF licenses this file to you under the Apache License, Version 2.0 (the
  8. * "License"); you may not use this file except in compliance with the
  9. * License. You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  15. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  16. * License for the specific language governing permissions and limitations
  17. * under the License.
  18. *
  19. ****************************************************************************/
  20. /****************************************************************************
  21. * Included Files
  22. ****************************************************************************/
  23. #include <nuttx/config.h>
  24. #include <nuttx/compiler.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <queue.h>
  28. #include <debug.h>
  29. #include <arch/irq.h>
  30. #include <nuttx/arch.h>
  31. #include <nuttx/wdog.h>
  32. #include <nuttx/kmalloc.h>
  33. #include <nuttx/net/net.h>
  34. #include <nuttx/net/netdev.h>
  35. #include <nuttx/net/ip.h>
  36. #include <nuttx/net/mld.h>
  37. #include "devif/devif.h"
  38. #include "mld/mld.h"
  39. #ifdef CONFIG_NET_MLD
  40. /****************************************************************************
  41. * Private Functions
  42. ****************************************************************************/
  43. /****************************************************************************
  44. * Name: mld_ngroups
  45. *
  46. * Description:
  47. * Return the number of groups joined by applications.
  48. *
  49. ****************************************************************************/
  50. static int mld_ngroups(FAR struct net_driver_s *dev)
  51. {
  52. FAR struct mld_group_s *group;
  53. int ngroups = 0;
  54. /* Count the number of groups in the group list */
  55. for (group = (FAR struct mld_group_s *)dev->d_mld.grplist.head;
  56. group != NULL;
  57. group = group->next)
  58. {
  59. ngroups++;
  60. }
  61. /* REVISIT: Subtract one for the IPv6 allnodes group. Why is this here?
  62. * what do we need it for? It was cloned from IGMP and is probably not
  63. * needed.
  64. */
  65. return ngroups > 0 ? ngroups - 1 : 0;
  66. }
  67. /****************************************************************************
  68. * Public Functions
  69. ****************************************************************************/
  70. /****************************************************************************
  71. * Name: mld_grpalloc
  72. *
  73. * Description:
  74. * Allocate a new group from heap memory.
  75. *
  76. * Assumptions:
  77. * The network is locked.
  78. *
  79. ****************************************************************************/
  80. FAR struct mld_group_s *mld_grpalloc(FAR struct net_driver_s *dev,
  81. FAR const net_ipv6addr_t addr)
  82. {
  83. FAR struct mld_group_s *group;
  84. mldinfo("addr: %08x dev: %p\n", *addr, dev);
  85. group = (FAR struct mld_group_s *)kmm_zalloc(sizeof(struct mld_group_s));
  86. mldinfo("group: %p\n", group);
  87. /* Check if we successfully allocated a group structure */
  88. if (group != NULL)
  89. {
  90. /* Initialize the non-zero elements of the group structure */
  91. net_ipv6addr_copy(group->grpaddr, addr);
  92. /* This semaphore is used for signaling and, hence, should not have
  93. * priority inheritance enabled.
  94. */
  95. nxsem_init(&group->sem, 0, 0);
  96. nxsem_set_protocol(&group->sem, SEM_PRIO_NONE);
  97. /* Save the interface index */
  98. group->ifindex = dev->d_ifindex;
  99. #ifndef CONFIG_NET_MLD_ROUTER
  100. /* Start the query timer if we are the Querier and this is the first
  101. * group member of the group.
  102. */
  103. if (mld_ngroups(dev) == 0)
  104. {
  105. mld_start_gentimer(dev, MSEC2TICK(MLD_QUERY_MSEC));
  106. }
  107. #endif
  108. /* Add the group structure to the list in the device structure */
  109. sq_addfirst((FAR sq_entry_t *)group, &dev->d_mld.grplist);
  110. }
  111. return group;
  112. }
  113. /****************************************************************************
  114. * Name: mld_grpfind
  115. *
  116. * Description:
  117. * Find an existing group.
  118. *
  119. * Assumptions:
  120. * The network is locked.
  121. *
  122. ****************************************************************************/
  123. FAR struct mld_group_s *mld_grpfind(FAR struct net_driver_s *dev,
  124. FAR const net_ipv6addr_t addr)
  125. {
  126. FAR struct mld_group_s *group;
  127. mldinfo("Searching for group: %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
  128. addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6],
  129. addr[7]);
  130. for (group = (FAR struct mld_group_s *)dev->d_mld.grplist.head;
  131. group;
  132. group = group->next)
  133. {
  134. mldinfo("Compare: %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
  135. group->grpaddr[0], group->grpaddr[1], group->grpaddr[2],
  136. group->grpaddr[3], group->grpaddr[4], group->grpaddr[5],
  137. group->grpaddr[6], group->grpaddr[7]);
  138. if (net_ipv6addr_cmp(group->grpaddr, addr))
  139. {
  140. mldinfo("Match!\n");
  141. DEBUGASSERT(group->ifindex == dev->d_ifindex);
  142. break;
  143. }
  144. }
  145. return group;
  146. }
  147. /****************************************************************************
  148. * Name: mld_grpallocfind
  149. *
  150. * Description:
  151. * Find an existing group. If not found, create a new group for the
  152. * address.
  153. *
  154. ****************************************************************************/
  155. FAR struct mld_group_s *mld_grpallocfind(FAR struct net_driver_s *dev,
  156. FAR const net_ipv6addr_t addr)
  157. {
  158. FAR struct mld_group_s *group = mld_grpfind(dev, addr);
  159. mldinfo("group: %p addr: %08x\n", group, (int)*addr);
  160. if (!group)
  161. {
  162. group = mld_grpalloc(dev, addr);
  163. }
  164. mldinfo("group: %p\n", group);
  165. return group;
  166. }
  167. /****************************************************************************
  168. * Name: mld_grpfree
  169. *
  170. * Description:
  171. * Release a previously allocated group.
  172. *
  173. * Assumptions:
  174. * The network is locked.
  175. *
  176. ****************************************************************************/
  177. void mld_grpfree(FAR struct net_driver_s *dev, FAR struct mld_group_s *group)
  178. {
  179. mldinfo("Free: %p flags: %02x\n", group, group->flags);
  180. /* Cancel the timers */
  181. wd_cancel(&group->polldog);
  182. /* Remove the group structure from the group list in the device structure */
  183. sq_rem((FAR sq_entry_t *)group, &dev->d_mld.grplist);
  184. /* Destroy the wait semaphore */
  185. nxsem_destroy(&group->sem);
  186. /* Cancel the watchdog timer */
  187. wd_cancel(&group->polldog);
  188. /* Then release the group structure resources. */
  189. mldinfo("Call kmm_free()\n");
  190. kmm_free(group);
  191. #ifndef CONFIG_NET_MLD_ROUTER
  192. /* If there are no longer any groups, then stop the general query and v1
  193. * compatibility timers.
  194. */
  195. if (mld_ngroups(dev) == 0)
  196. {
  197. wd_cancel(&dev->d_mld.gendog);
  198. wd_cancel(&dev->d_mld.v1dog);
  199. }
  200. #endif
  201. }
  202. /****************************************************************************
  203. * Name: mld_new_pollcycle
  204. *
  205. * Description:
  206. * Update accumulated membership at the beginning of each new poll cycle
  207. *
  208. ****************************************************************************/
  209. #ifdef CONFIG_NET_MLD_ROUTER
  210. void mld_new_pollcycle(FAR struct net_driver_s *dev)
  211. {
  212. FAR struct mld_group_s *member;
  213. /* Update member ship in every group */
  214. for (member = (FAR struct mld_group_s *)dev->d_mld.grplist.head;
  215. member;
  216. member = member->next)
  217. {
  218. /* Save the number of members that reported in the previous query
  219. * cycle; reset the number of members that have reported in the new
  220. * query cycle.
  221. */
  222. member->lstmbrs = member->members;
  223. member->members = 0;
  224. }
  225. }
  226. #endif
  227. #endif /* CONFIG_NET_MLD */