This is with MQX 4.0.1 on a MK60FN1M0VMD12. The best I can tell so far is the second time the Ethernet cable is unplugged it loops on this while (ipif->IGMP_MEMBER). The first time a cable is unplugged it breaks out on an error(RTCSERR_IGMP_INVALID_IP) returned from IGMP_leave_socket_all. The second time IGMP_leave_socket_all returns RTCS_OK but does not do anything and it continues to do this looping on while (ipif->IGMP_MEMBER). I am looking to find if I can see the problem but the first time through always returning an error make this loop not do much and I am thinking of taking it out or just forcing it to run IGMP_leave_socket_all on every member of the structure.
This problem is produced when remove the IP address from route tree. After, any call of IP_find_if() function returns error.
My solution is change the order of one line into IPIF_unbind() function. First, we call the IGMP_UNBIND function pointer, and after we remove the IP address.
I have obtained good results with this solution without need of a break variable.
void IPIF_unbind
(
IPIF_PARM_PTR parms
)
{ /* Body */
#if RTCSCFG_ENABLE_IP4
_ip_address mask;
// IP_route_remove_direct(parms->address, 0xFFFFFFFF, parms->ihandle); // move this line below
#if RTCSCFG_ENABLE_IGMP
if (parms->ihandle) {
((IP_IF_PTR)(parms->ihandle))->IGMP_UNBIND((IP_IF_PTR)parms->ihandle,
parms->address);
} /* Endif */
#endif
IP_route_remove_direct(parms->address, 0xFFFFFFFF, parms->ihandle); // this line was higher
IP_get_netmask(parms->ihandle, parms->address, &mask);
/* If mask is invalid do not try to remove direct route */
if (mask != 1)
{
IP_route_remove_direct(parms->address, mask, parms->ihandle);
}
RTCSCMD_complete(parms, RTCS_OK);
#else
RTCSCMD_complete(parms, RTCSERR_IP_IS_DISABLED);
#endif /* RTCSCFG_ENABLE_IP4 */
} /* Endbody */
FYI, I have run into this same problem with MQX4.2. It happens when I bind a socket to a multicast group, then unplug the ethernet cable.
The call stack looks like this:
ipcfg_unbind
ipcfg_unbind_internal
ipcfg_unbind_internal_actual
DHCPCLNT_release
DHCPCLNT_release_internal
IPIF_unbind
IGMP_ipif_unbind <----- infinite loop in here
Similar to tduncan, I have put my own exit case in the while loop.
Not anytime soon (deadlines and all). For now I have just put an exit case
if(loopbreak_m == ipif->IGMP_MEMBER && (memcmp(&loopbreak_i, &member->IGRP, sizeof(ip_mreq))==0))
return RTCSERR_IGMP_INVALID_IP;
loopbreak_m = ipif->IGMP_MEMBER;
loopbreak_i = member->IGRP;