Пример #1
0
/**
 * Leave a group on a network interface.
 *
 * @param srcaddr ipv6 address of the network interface which should
 *                leave the group. If IP6_ISANY, leave on all netifs
 * @param groupaddr the ipv6 address of the group to leave
 * @return ERR_OK if group was left on the netif(s), an err_t otherwise
 */
err_t
mld6_leavegroup(const ip6_addr_t *srcaddr, const ip6_addr_t *groupaddr)
{
  err_t              err = ERR_VAL; /* no matching interface */
  struct mld_group  *group;
  struct netif      *netif;
  u8_t               match;
  u8_t               i;

  /* loop through netif's */
  netif = netif_list;
  while (netif != NULL) {
    /* Should we leave this interface ? */
    match = 0;
    if (ip6_addr_isany(srcaddr)) {
      match = 1;
    }
    else {
      for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
        if (!ip6_addr_isinvalid(netif_ip6_addr_state(netif, i)) &&
            ip6_addr_cmp(srcaddr, netif_ip6_addr(netif, i))) {
          match = 1;
          break;
        }
      }
    }
    if (match) {
      /* find group */
      group = mld6_lookfor_group(netif, groupaddr);

      if (group != NULL) {
        /* Leave if there is no other use of the group */
        if (group->use <= 1) {
          /* If we are the last reporter for this group */
          if (group->last_reporter_flag) {
            MLD6_STATS_INC(mld6.tx_leave);
            mld6_send(group, ICMP6_TYPE_MLD);
          }

          /* Disable the group at the MAC level */
          if (netif->mld_mac_filter != NULL) {
            netif->mld_mac_filter(netif, groupaddr, MLD6_DEL_MAC_FILTER);
          }

          /* Free the group */
          mld6_free_group(group);
        } else {
          /* Decrement group use */
          group->use--;
        }
        /* Leave on this interface */
        err = ERR_OK;
      }
    }
    /* proceed to next network interface */
    netif = netif->next;
  }

  return err;
}
Пример #2
0
/**
 * timer for mld processing. Must be called based on smallest
 * timer in group
 * When a delaying member expires, a membership report is sent.
 */
void
mld6_tmr(void)
{
  struct mld_group *group = mld_group_list;

  unsigned long curr_ticks = sys_arch_get_os_ticks() / MLD_TIMER_OFFSET;

  while (group != NULL) {
    if (group->timer <= curr_ticks
        && group->timer != 0) {
            group->timer = 0;
        /* If the state is MLD6_GROUP_DELAYING_MEMBER then we send a report for this group */
        if (group->group_state == MLD6_GROUP_DELAYING_MEMBER) {
          MLD6_STATS_INC(mld6.tx_report);
          mld6_send(group, ICMP6_TYPE_MLR);
          group->group_state = MLD6_GROUP_IDLE_MEMBER;
        }
      }
    group = group->next;
  }
  struct mld_group* min_timeout_grp = lwip_get_min_timeout_mld_grp();
  if (min_timeout_grp &&
      (min_timeout_grp->timer)  >  curr_ticks)  {
        unsigned int new_timer_val =
                ((min_timeout_grp->timer) - curr_ticks) * MLD_TIMER_OFFSET;
        sys_timeout(new_timer_val, mld6_timer, NULL);
   }
}
Пример #3
0
/**
 * Join a group on a network interface.
 *
 * @param srcaddr ipv6 address of the network interface which should
 *                join a new group. If IP6_ADDR_ANY, join on all netifs
 * @param groupaddr the ipv6 address of the group to join
 * @return ERR_OK if group was joined on the netif(s), an err_t otherwise
 */
err_t
mld6_joingroup(const ip6_addr_t *srcaddr, const ip6_addr_t *groupaddr)
{
  err_t              err = ERR_VAL; /* no matching interface */
  struct mld_group  *group;
  struct netif      *netif;
  u8_t               match;
  u8_t               i;

  /* loop through netif's */
  netif = netif_list;
  while (netif != NULL) {
    /* Should we join this interface ? */
    match = 0;
    if (ip6_addr_isany(srcaddr)) {
      match = 1;
    }
    else {
      for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
        if (!ip6_addr_isinvalid(netif_ip6_addr_state(netif, i)) &&
            ip6_addr_cmp(srcaddr, netif_ip6_addr(netif, i))) {
          match = 1;
          break;
        }
      }
    }
    if (match) {
      /* find group or create a new one if not found */
      group = mld6_lookfor_group(netif, groupaddr);

      if (group == NULL) {
        /* Joining a new group. Create a new group entry. */
        group = mld6_new_group(netif, groupaddr);
        if (group == NULL) {
          return ERR_MEM;
        }

        /* Activate this address on the MAC layer. */
        if (netif->mld_mac_filter != NULL) {
          netif->mld_mac_filter(netif, groupaddr, MLD6_ADD_MAC_FILTER);
        }

        /* Report our membership. */
        MLD6_STATS_INC(mld6.tx_report);
        mld6_send(group, ICMP6_TYPE_MLR);
        mld6_delayed_report(group, MLD6_JOIN_DELAYING_MEMBER_TMR_MS);
      }

      /* Increment group use */
      group->use++;
      err = ERR_OK;
    }

    /* proceed to next network interface */
    netif = netif->next;
  }

  return err;
}
Пример #4
0
/**
 * Periodic timer for mld processing. Must be called every
 * MLD6_TMR_INTERVAL milliseconds (100).
 *
 * When a delaying member expires, a membership report is sent.
 */
void
mld6_tmr(void)
{
  struct mld_group *group = mld_group_list;

  while (group != NULL) {
    if (group->timer > 0) {
      group->timer--;
      if (group->timer == 0) {
        /* If the state is MLD6_GROUP_DELAYING_MEMBER then we send a report for this group */
        if (group->group_state == MLD6_GROUP_DELAYING_MEMBER) {
          MLD6_STATS_INC(mld6.tx_report);
          mld6_send(group, ICMP6_TYPE_MLR);
          group->group_state = MLD6_GROUP_IDLE_MEMBER;
        }
      }
    }
    group = group->next;
  }
}