51 #if LWIP_IPV6 && LWIP_IPV6_MLD
72 #define MLD6_JOIN_DELAYING_MEMBER_TMR_MS (500)
74 #define MLD6_GROUP_NON_MEMBER 0
75 #define MLD6_GROUP_DELAYING_MEMBER 1
76 #define MLD6_GROUP_IDLE_MEMBER 2
79 static struct mld_group *mld6_new_group(
struct netif *ifp,
const ip6_addr_t *addr);
80 static err_t mld6_remove_group(
struct netif *
netif,
struct mld_group *group);
81 static void mld6_delayed_report(
struct mld_group *group,
u16_t maxresp);
82 static void mld6_send(
struct netif *
netif,
struct mld_group *group,
u8_t type);
93 struct mld_group *group = netif_mld6_data(
netif);
95 netif_set_client_data(
netif, LWIP_NETIF_CLIENT_DATA_INDEX_MLD6,
NULL);
97 while (group !=
NULL) {
98 struct mld_group *next = group->next;
122 struct mld_group *group = netif_mld6_data(
netif);
124 while (group !=
NULL) {
125 mld6_delayed_report(group, MLD6_JOIN_DELAYING_MEMBER_TMR_MS);
139 mld6_lookfor_group(
struct netif *ifp,
const ip6_addr_t *addr)
141 struct mld_group *group = netif_mld6_data(ifp);
143 while (group !=
NULL) {
144 if (ip6_addr_cmp(&(group->group_address), addr)) {
162 static struct mld_group *
163 mld6_new_group(
struct netif *ifp,
const ip6_addr_t *addr)
165 struct mld_group *group;
167 group = (
struct mld_group *)
memp_malloc(MEMP_MLD6_GROUP);
169 ip6_addr_set(&(group->group_address), addr);
171 group->group_state = MLD6_GROUP_IDLE_MEMBER;
172 group->last_reporter_flag = 0;
174 group->next = netif_mld6_data(ifp);
176 netif_set_client_data(ifp, LWIP_NETIF_CLIENT_DATA_INDEX_MLD6, group);
189 mld6_remove_group(
struct netif *
netif,
struct mld_group *group)
194 if (netif_mld6_data(
netif) == group) {
195 netif_set_client_data(
netif, LWIP_NETIF_CLIENT_DATA_INDEX_MLD6, group->
next);
198 struct mld_group *tmpGroup;
199 for (tmpGroup = netif_mld6_data(
netif); tmpGroup !=
NULL; tmpGroup = tmpGroup->next) {
200 if (tmpGroup->next == group) {
201 tmpGroup->next = group->next;
206 if (tmpGroup ==
NULL) {
222 mld6_input(
struct pbuf *p,
struct netif *inp)
225 struct mld_group *group;
240 switch (mld_hdr->type) {
243 if (ip6_addr_isallnodes_linklocal(ip6_current_dest_addr()) &&
244 ip6_addr_isany(&(mld_hdr->multicast_address))) {
247 group = netif_mld6_data(inp);
248 while (group !=
NULL) {
249 if ((!(ip6_addr_ismulticast_iflocal(&(group->group_address)))) &&
250 (!(ip6_addr_isallnodes_linklocal(&(group->group_address))))) {
251 mld6_delayed_report(group, mld_hdr->max_resp_delay);
260 group = mld6_lookfor_group(inp, ip6_current_dest_addr());
263 mld6_delayed_report(group, mld_hdr->max_resp_delay);
272 group = mld6_lookfor_group(inp, ip6_current_dest_addr());
275 if (group->group_state == MLD6_GROUP_DELAYING_MEMBER) {
277 group->group_state = MLD6_GROUP_IDLE_MEMBER;
278 group->last_reporter_flag = 0;
304 mld6_joingroup(
const ip6_addr_t *srcaddr,
const ip6_addr_t *groupaddr)
313 if (ip6_addr_isany(srcaddr) ||
314 netif_get_ip6_addr_match(
netif, srcaddr) >= 0) {
315 err = mld6_joingroup_netif(
netif, groupaddr);
337 mld6_joingroup_netif(
struct netif *
netif,
const ip6_addr_t *groupaddr)
339 struct mld_group *group;
342 group = mld6_lookfor_group(
netif, groupaddr);
346 group = mld6_new_group(
netif, groupaddr);
359 mld6_delayed_report(group, MLD6_JOIN_DELAYING_MEMBER_TMR_MS);
377 mld6_leavegroup(
const ip6_addr_t *srcaddr,
const ip6_addr_t *groupaddr)
386 if (ip6_addr_isany(srcaddr) ||
387 netif_get_ip6_addr_match(
netif, srcaddr) >= 0) {
388 err_t res = mld6_leavegroup_netif(
netif, groupaddr);
410 mld6_leavegroup_netif(
struct netif *
netif,
const ip6_addr_t *groupaddr)
412 struct mld_group *group;
415 group = mld6_lookfor_group(
netif, groupaddr);
419 if (group->use <= 1) {
421 mld6_remove_group(
netif, group);
424 if (group->last_reporter_flag) {
462 struct mld_group *group = netif_mld6_data(
netif);
464 while (group !=
NULL) {
465 if (group->timer > 0) {
467 if (group->timer == 0) {
469 if (group->group_state == MLD6_GROUP_DELAYING_MEMBER) {
472 group->group_state = MLD6_GROUP_IDLE_MEMBER;
490 mld6_delayed_report(
struct mld_group *group,
u16_t maxresp)
493 maxresp = maxresp / MLD6_TMR_INTERVAL;
500 maxresp = LWIP_RAND() % maxresp;
507 if ((group->group_state == MLD6_GROUP_IDLE_MEMBER) ||
508 ((group->group_state == MLD6_GROUP_DELAYING_MEMBER) &&
509 ((group->timer == 0) || (maxresp < group->timer)))) {
510 group->timer = maxresp;
511 group->group_state = MLD6_GROUP_DELAYING_MEMBER;
525 mld6_send(
struct netif *
netif,
struct mld_group *group,
u8_t type)
529 const ip6_addr_t *src_addr;
546 if (!ip6_addr_isvalid(netif_ip6_addr_state(
netif, 0))) {
549 src_addr = IP6_ADDR_ANY6;
552 src_addr = netif_ip6_addr(
netif, 0);
559 mld_hdr->type = type;
562 mld_hdr->max_resp_delay = 0;
563 mld_hdr->reserved = 0;
564 ip6_addr_set(&(mld_hdr->multicast_address), &(group->group_address));
566 #if CHECKSUM_GEN_ICMP6
569 src_addr, &(group->group_address));
578 group->last_reporter_flag = 1;
583 ip6_output_if(p, (ip6_addr_isany(src_addr)) ?
NULL : src_addr, &(group->group_address),