mld_group.c 7.9 KB

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