70 #if LWIP_IPV6 && LWIP_IPV6_MLD 91 #define MLD6_JOIN_DELAYING_MEMBER_TMR_MS (500) 93 #define MLD6_GROUP_NON_MEMBER 0 94 #define MLD6_GROUP_DELAYING_MEMBER 1 95 #define MLD6_GROUP_IDLE_MEMBER 2 98 static struct mld_group *mld6_new_group(
struct netif *ifp,
const ip6_addr_t *addr);
99 static err_t mld6_remove_group(
struct netif *
netif,
struct mld_group *group);
100 static void mld6_delayed_report(
struct mld_group *group, u16_t maxresp);
101 static void mld6_send(
struct netif *
netif,
struct mld_group *group, u8_t type);
112 struct mld_group *group = netif_mld6_data(netif);
114 netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_MLD6, NULL);
116 while (group != NULL) {
117 struct mld_group *next = group->next;
120 if (netif->mld_mac_filter != NULL) {
139 mld6_report_groups(
struct netif *netif)
141 struct mld_group *group = netif_mld6_data(netif);
143 while (group != NULL) {
144 mld6_delayed_report(group, MLD6_JOIN_DELAYING_MEMBER_TMR_MS);
158 mld6_lookfor_group(
struct netif *ifp,
const ip6_addr_t *addr)
160 struct mld_group *group = netif_mld6_data(ifp);
162 while (group != NULL) {
163 if (ip6_addr_cmp(&(group->group_address), addr)) {
181 static struct mld_group *
182 mld6_new_group(
struct netif *ifp,
const ip6_addr_t *addr)
184 struct mld_group *group;
186 group = (
struct mld_group *)
memp_malloc(MEMP_MLD6_GROUP);
188 ip6_addr_set(&(group->group_address), addr);
190 group->group_state = MLD6_GROUP_IDLE_MEMBER;
191 group->last_reporter_flag = 0;
193 group->next = netif_mld6_data(ifp);
195 netif_set_client_data(ifp, LWIP_NETIF_CLIENT_DATA_INDEX_MLD6, group);
208 mld6_remove_group(
struct netif *netif,
struct mld_group *group)
213 if (netif_mld6_data(netif) == group) {
214 netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_MLD6, group->
next);
217 struct mld_group *tmpGroup;
218 for (tmpGroup = netif_mld6_data(netif); tmpGroup != NULL; tmpGroup = tmpGroup->next) {
219 if (tmpGroup->next == group) {
220 tmpGroup->next = group->next;
225 if (tmpGroup == NULL) {
241 mld6_input(
struct pbuf *p,
struct netif *inp)
244 struct mld_group *group;
246 MLD6_STATS_INC(mld6.recv);
252 MLD6_STATS_INC(mld6.lenerr);
253 MLD6_STATS_INC(mld6.drop);
259 switch (mld_hdr->type) {
262 if (ip6_addr_isallnodes_linklocal(ip6_current_dest_addr()) &&
263 ip6_addr_isany(&(mld_hdr->multicast_address))) {
264 MLD6_STATS_INC(mld6.rx_general);
266 group = netif_mld6_data(inp);
267 while (group != NULL) {
268 if ((!(ip6_addr_ismulticast_iflocal(&(group->group_address)))) &&
269 (!(ip6_addr_isallnodes_linklocal(&(group->group_address))))) {
270 mld6_delayed_report(group, mld_hdr->max_resp_delay);
278 MLD6_STATS_INC(mld6.rx_group);
279 group = mld6_lookfor_group(inp, ip6_current_dest_addr());
282 mld6_delayed_report(group, mld_hdr->max_resp_delay);
290 MLD6_STATS_INC(mld6.rx_report);
291 group = mld6_lookfor_group(inp, ip6_current_dest_addr());
294 if (group->group_state == MLD6_GROUP_DELAYING_MEMBER) {
296 group->group_state = MLD6_GROUP_IDLE_MEMBER;
297 group->last_reporter_flag = 0;
305 MLD6_STATS_INC(mld6.proterr);
306 MLD6_STATS_INC(mld6.drop);
323 mld6_joingroup(
const ip6_addr_t *srcaddr,
const ip6_addr_t *groupaddr)
330 while (netif != NULL) {
332 if (ip6_addr_isany(srcaddr) ||
333 netif_get_ip6_addr_match(netif, srcaddr) >= 0) {
334 err = mld6_joingroup_netif(netif, groupaddr);
356 mld6_joingroup_netif(
struct netif *netif,
const ip6_addr_t *groupaddr)
358 struct mld_group *group;
361 group = mld6_lookfor_group(netif, groupaddr);
365 group = mld6_new_group(netif, groupaddr);
371 if (netif->mld_mac_filter != NULL) {
376 MLD6_STATS_INC(mld6.tx_report);
378 mld6_delayed_report(group, MLD6_JOIN_DELAYING_MEMBER_TMR_MS);
396 mld6_leavegroup(
const ip6_addr_t *srcaddr,
const ip6_addr_t *groupaddr)
403 while (netif != NULL) {
405 if (ip6_addr_isany(srcaddr) ||
406 netif_get_ip6_addr_match(netif, srcaddr) >= 0) {
407 err_t res = mld6_leavegroup_netif(netif, groupaddr);
429 mld6_leavegroup_netif(
struct netif *netif,
const ip6_addr_t *groupaddr)
431 struct mld_group *group;
434 group = mld6_lookfor_group(netif, groupaddr);
438 if (group->use <= 1) {
440 mld6_remove_group(netif, group);
443 if (group->last_reporter_flag) {
444 MLD6_STATS_INC(mld6.tx_leave);
449 if (netif->mld_mac_filter != NULL) {
480 while (netif != NULL) {
481 struct mld_group *group = netif_mld6_data(netif);
483 while (group != NULL) {
484 if (group->timer > 0) {
486 if (group->timer == 0) {
488 if (group->group_state == MLD6_GROUP_DELAYING_MEMBER) {
489 MLD6_STATS_INC(mld6.tx_report);
491 group->group_state = MLD6_GROUP_IDLE_MEMBER;
509 mld6_delayed_report(
struct mld_group *group, u16_t maxresp)
512 maxresp = maxresp / MLD6_TMR_INTERVAL;
519 maxresp = LWIP_RAND() % maxresp;
526 if ((group->group_state == MLD6_GROUP_IDLE_MEMBER) ||
527 ((group->group_state == MLD6_GROUP_DELAYING_MEMBER) &&
528 ((group->timer == 0) || (maxresp < group->timer)))) {
529 group->timer = maxresp;
530 group->group_state = MLD6_GROUP_DELAYING_MEMBER;
544 mld6_send(
struct netif *netif,
struct mld_group *group, u8_t type)
548 const ip6_addr_t *src_addr;
553 MLD6_STATS_INC(mld6.memerr);
560 MLD6_STATS_INC(mld6.lenerr);
565 if (!ip6_addr_isvalid(netif_ip6_addr_state(netif, 0))) {
568 src_addr = IP6_ADDR_ANY6;
571 src_addr = netif_ip6_addr(netif, 0);
578 mld_hdr->type = type;
581 mld_hdr->max_resp_delay = 0;
582 mld_hdr->reserved = 0;
583 ip6_addr_set(&(mld_hdr->multicast_address), &(group->group_address));
585 #if CHECKSUM_GEN_ICMP6 586 IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) {
587 mld_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->
len,
588 src_addr, &(group->group_address));
593 ip6_options_add_hbh_ra(p, IP6_NEXTH_ICMP6, IP6_ROUTER_ALERT_VALUE_MLD);
597 group->last_reporter_flag = 1;
601 MLD6_STATS_INC(mld6.xmit);
602 ip6_output_if(p, (ip6_addr_isany(src_addr)) ? NULL : src_addr, &(group->group_address),
603 MLD6_HL, 0, IP6_NEXTH_HOPBYHOP, netif);
struct netif * netif_list
u8_t pbuf_header(struct pbuf *p, s16_t header_size_increment)
void memp_free(memp_t type, void *mem)
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
u8_t pbuf_free(struct pbuf *p)
void * memp_malloc(memp_t type)