⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 igmp.c

📁 freescale k40/k60 freertos-lwip例程
💻 C
📖 第 1 页 / 共 2 页
字号:
    pbuf_free(p);    LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP frame not for us\n"));    return;  }  /* NOW ACT ON THE INCOMING MESSAGE TYPE... */  switch (igmp->igmp_msgtype) {   case IGMP_MEMB_QUERY: {     /* IGMP_MEMB_QUERY to the "all systems" address ? */     if ((ip_addr_cmp(dest, &allsystems)) && (igmp->igmp_group_address.addr == 0)) {       /* THIS IS THE GENERAL QUERY */       LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: General IGMP_MEMB_QUERY on \"ALL SYSTEMS\" address (224.0.0.1) [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp)));       if (igmp->igmp_maxresp == 0) {         IGMP_STATS_INC(igmp.v1_rxed);         LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: got an all hosts query with time== 0 - this is V1 and not implemented - treat as v2\n"));         igmp->igmp_maxresp = IGMP_V1_DELAYING_MEMBER_TMR;       }       IGMP_STATS_INC(igmp.group_query_rxed);       groupref = igmp_group_list;       while (groupref) {         /* Do not send messages on the all systems group address! */         if ((groupref->interface == inp) && (!(ip_addr_cmp(&(groupref->group_address), &allsystems)))) {           igmp_delaying_member( groupref, igmp->igmp_maxresp);         }         groupref = groupref->next;       }     } else {       /* IGMP_MEMB_QUERY to a specific group ? */       if (group->group_address.addr != 0) {         LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP_MEMB_QUERY to a specific group "));         ip_addr_debug_print(IGMP_DEBUG, &group->group_address);         if (ip_addr_cmp (dest, &allsystems)) {           LWIP_DEBUGF(IGMP_DEBUG, (" using \"ALL SYSTEMS\" address (224.0.0.1) [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp)));           /* we first need to re-lookfor the group since we used dest last time */           group = igmp_lookfor_group(inp, &igmp->igmp_group_address);         } else {           LWIP_DEBUGF(IGMP_DEBUG, (" with the group address as destination [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp)));         }         if (group != NULL) {           IGMP_STATS_INC(igmp.unicast_query);           igmp_delaying_member( group, igmp->igmp_maxresp);         }       }     }     break;   }   case IGMP_V2_MEMB_REPORT: {     LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP_V2_MEMB_REPORT\n"));     IGMP_STATS_INC(igmp.report_rxed);     if (group->group_state == IGMP_GROUP_DELAYING_MEMBER) {       /* This is on a specific group we have already looked up */       group->timer = 0; /* stopped */       group->group_state = IGMP_GROUP_IDLE_MEMBER;       group->last_reporter_flag = 0;     }     break;   }   default: {     LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: unexpected msg %d in state %d on group %p on if %p\n",       igmp->igmp_msgtype, group->group_state, &group, group->interface));     break;   }  }  pbuf_free(p);  return;}/** * Join a group on one network interface. * * @param ifaddr ip address of the network interface which should join a new group * @param groupaddr the ip address of the group which to join * @return ERR_OK if group was joined on the netif(s), an err_t otherwise */err_tigmp_joingroup(struct ip_addr *ifaddr, struct ip_addr *groupaddr){  err_t              err = ERR_VAL; /* no matching interface */  struct igmp_group *group;  struct netif      *netif;  /* make sure it is multicast address */  LWIP_ERROR("igmp_joingroup: attempt to join non-multicast address", ip_addr_ismulticast(groupaddr), return ERR_VAL;);  LWIP_ERROR("igmp_joingroup: attempt to join allsystems address", (!ip_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;);  /* loop through netif's */  netif = netif_list;  while (netif != NULL) {    /* Should we join this interface ? */    if ((netif->flags & NETIF_FLAG_IGMP) && ((ip_addr_isany(ifaddr) || ip_addr_cmp(&(netif->ip_addr), ifaddr)))) {      /* find group or create a new one if not found */      group = igmp_lookup_group(netif, groupaddr);      if (group != NULL) {        /* This should create a new group, check the state to make sure */        if (group->group_state != IGMP_GROUP_NON_MEMBER) {          LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: join to group not in state IGMP_GROUP_NON_MEMBER\n"));        } else {          /* OK - it was new group */          LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: join to new group: "));          ip_addr_debug_print(IGMP_DEBUG, groupaddr);          LWIP_DEBUGF(IGMP_DEBUG, ("\n"));          /* If first use of the group, allow the group at the MAC level */          if ((group->use==0) && (netif->igmp_mac_filter != NULL)) {            LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: igmp_mac_filter(ADD "));            ip_addr_debug_print(IGMP_DEBUG, groupaddr);            LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", netif));            netif->igmp_mac_filter(netif, groupaddr, IGMP_ADD_MAC_FILTER);          }          IGMP_STATS_INC(igmp.join_sent);          igmp_send(group, IGMP_V2_MEMB_REPORT);          igmp_start_timer(group, IGMP_JOIN_DELAYING_MEMBER_TMR);          /* Need to work out where this timer comes from */          group->group_state = IGMP_GROUP_DELAYING_MEMBER;        }        /* Increment group use */        group->use++;        /* Join on this interface */        err = ERR_OK;      } else {        /* Return an error even if some network interfaces are joined */        /** @todo undo any other netif already joined */        LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: Not enought memory to join to group\n"));        return ERR_MEM;      }    }    /* proceed to next network interface */    netif = netif->next;  }  return err;}/** * Leave a group on one network interface. * * @param ifaddr ip address of the network interface which should leave a group * @param groupaddr the ip address of the group which to leave * @return ERR_OK if group was left on the netif(s), an err_t otherwise */err_tigmp_leavegroup(struct ip_addr *ifaddr, struct ip_addr *groupaddr){  err_t              err = ERR_VAL; /* no matching interface */  struct igmp_group *group;  struct netif      *netif;  /* make sure it is multicast address */  LWIP_ERROR("igmp_leavegroup: attempt to leave non-multicast address", ip_addr_ismulticast(groupaddr), return ERR_VAL;);  LWIP_ERROR("igmp_leavegroup: attempt to leave allsystems address", (!ip_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;);  /* loop through netif's */  netif = netif_list;  while (netif != NULL) {    /* Should we leave this interface ? */    if ((netif->flags & NETIF_FLAG_IGMP) && ((ip_addr_isany(ifaddr) || ip_addr_cmp(&(netif->ip_addr), ifaddr)))) {      /* find group */      group = igmp_lookfor_group(netif, groupaddr);      if (group != NULL) {        /* Only send a leave if the flag is set according to the state diagram */        LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: Leaving group: "));        ip_addr_debug_print(IGMP_DEBUG, groupaddr);        LWIP_DEBUGF(IGMP_DEBUG, ("\n"));        /* 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) {            LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: sending leaving group\n"));            IGMP_STATS_INC(igmp.leave_sent);            igmp_send(group, IGMP_LEAVE_GROUP);          }                    /* Disable the group at the MAC level */          if (netif->igmp_mac_filter != NULL) {            LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: igmp_mac_filter(DEL "));            ip_addr_debug_print(IGMP_DEBUG, groupaddr);            LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", netif));            netif->igmp_mac_filter(netif, groupaddr, IGMP_DEL_MAC_FILTER);          }                    LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: remove group: "));          ip_addr_debug_print(IGMP_DEBUG, groupaddr);          LWIP_DEBUGF(IGMP_DEBUG, ("\n"));                              /* Free the group */          igmp_remove_group(group);        } else {          /* Decrement group use */          group->use--;        }        /* Leave on this interface */        err = ERR_OK;      } else {        /* It's not a fatal error on "leavegroup" */        LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: not member of group\n"));      }    }    /* proceed to next network interface */    netif = netif->next;  }  return err;}/** * The igmp timer function (both for NO_SYS=1 and =0) * Should be called every IGMP_TMR_INTERVAL milliseconds (100 ms is default). */voidigmp_tmr(void){  struct igmp_group *group = igmp_group_list;  while (group != NULL) {    if (group->timer != 0) {      group->timer -= 1;      if (group->timer == 0) {        igmp_timeout(group);      }    }    group = group->next;  }}/** * Called if a timeout for one group is reached. * Sends a report for this group. * * @param group an igmp_group for which a timeout is reached */voidigmp_timeout(struct igmp_group *group){  /* If the state is IGMP_GROUP_DELAYING_MEMBER then we send a report for this group */  if (group->group_state == IGMP_GROUP_DELAYING_MEMBER) {    LWIP_DEBUGF(IGMP_DEBUG, ("igmp_timeout: report membership for group with address "));    ip_addr_debug_print(IGMP_DEBUG, &(group->group_address));    LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", group->interface));    igmp_send(group, IGMP_V2_MEMB_REPORT);  }}/** * Start a timer for an igmp group * * @param group the igmp_group for which to start a timer * @param max_time the time in multiples of IGMP_TMR_INTERVAL (decrease with *        every call to igmp_tmr()) */voidigmp_start_timer(struct igmp_group *group, u8_t max_time){  /**   * @todo Important !! this should be random 0 -> max_time. Find out how to do this   */  group->timer = max_time;}/** * Stop a timer for an igmp_group * * @param group the igmp_group for which to stop the timer */voidigmp_stop_timer(struct igmp_group *group){  group->timer = 0;}/** * Delaying membership report for a group if necessary * * @param group the igmp_group for which "delaying" membership report * @param maxresp query delay */voidigmp_delaying_member( struct igmp_group *group, u8_t maxresp){  if ((group->group_state == IGMP_GROUP_IDLE_MEMBER) ||     ((group->group_state == IGMP_GROUP_DELAYING_MEMBER) && (maxresp > group->timer))) {    igmp_start_timer(group, (maxresp)/2);    group->group_state = IGMP_GROUP_DELAYING_MEMBER;  }}/** * Sends an IP packet on a network interface. This function constructs the IP header * and calculates the IP header checksum. If the source IP address is NULL, * the IP address of the outgoing network interface is filled in as source address. * * @param p the packet to send (p->payload points to the data, e.g. next            protocol header; if dest == IP_HDRINCL, p already includes an IP            header and p->payload points to that IP header) * @param src the source IP address to send from (if src == IP_ADDR_ANY, the *         IP  address of the netif used to send is used as source address) * @param dest the destination IP address to send the packet to * @param ttl the TTL value to be set in the IP header * @param proto the PROTOCOL to be set in the IP header * @param netif the netif on which to send this packet * @return ERR_OK if the packet was sent OK *         ERR_BUF if p doesn't have enough space for IP/LINK headers *         returns errors returned by netif->output */err_tigmp_ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,                  u8_t ttl, u8_t proto, struct netif *netif){  /* This is the "router alert" option */  u16_t ra[2];  ra[0] = htons (ROUTER_ALERT);  ra[1] = 0x0000; /* Router shall examine packet */  return ip_output_if_opt(p, src, dest, ttl, 0, proto, netif, ra, ROUTER_ALERTLEN);}/** * Send an igmp packet to a specific group. * * @param group the group to which to send the packet * @param type the type of igmp packet to send */voidigmp_send(struct igmp_group *group, u8_t type){  struct pbuf*     p    = NULL;  struct igmp_msg* igmp = NULL;  struct ip_addr   src  = {0};  struct ip_addr*  dest = NULL;  /* IP header + "router alert" option + IGMP header */  p = pbuf_alloc(PBUF_TRANSPORT, IGMP_MINLEN, PBUF_RAM);    if (p) {    igmp = p->payload;    LWIP_ASSERT("igmp_send: check that first pbuf can hold struct igmp_msg",               (p->len >= sizeof(struct igmp_msg)));    ip_addr_set(&src, &((group->interface)->ip_addr));         if (type == IGMP_V2_MEMB_REPORT) {      dest = &(group->group_address);      IGMP_STATS_INC(igmp.report_sent);      ip_addr_set(&(igmp->igmp_group_address), &(group->group_address));      group->last_reporter_flag = 1; /* Remember we were the last to report */    } else {      if (type == IGMP_LEAVE_GROUP) {        dest = &allrouters;        ip_addr_set(&(igmp->igmp_group_address), &(group->group_address));      }    }    if ((type == IGMP_V2_MEMB_REPORT) || (type == IGMP_LEAVE_GROUP)) {      igmp->igmp_msgtype  = type;      igmp->igmp_maxresp  = 0;      igmp->igmp_checksum = 0;      igmp->igmp_checksum = inet_chksum( igmp, IGMP_MINLEN);      igmp_ip_output_if(p, &src, dest, IGMP_TTL, IP_PROTO_IGMP, group->interface);    }    pbuf_free(p);  } else {    LWIP_DEBUGF(IGMP_DEBUG, ("igmp_send: not enough memory for igmp_send\n"));  }}#endif /* LWIP_IGMP */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -