udp: modify ipv4 multicast to allow different conn to join simultaneously
add ref count for ipv4 multicast and leave the multicast group when close behavior alignment with linux. Signed-off-by: zhanghongyu <zhanghongyu@xiaomi.com>
This commit is contained in:
parent
7c322c250a
commit
43ecf36d78
@ -117,6 +117,7 @@ struct igmp_group_s
|
||||
uint8_t ifindex; /* Interface index */
|
||||
uint8_t flags; /* See IGMP_ flags definitions */
|
||||
uint8_t msgid; /* Pending message ID (if non-zero) */
|
||||
uint8_t njoins; /* Number of joins from this host */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -160,12 +160,12 @@ int igmp_joingroup(struct net_driver_s *dev,
|
||||
/* Add the group (MAC) address to the ether drivers MAC filter list */
|
||||
|
||||
igmp_addmcastmac(dev, (FAR in_addr_t *)&grpaddr->s_addr);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Return EEXIST if the address is already a member of the group */
|
||||
DEBUGASSERT(group->njoins < UINT8_MAX);
|
||||
group->njoins++;
|
||||
|
||||
return -EEXIST;
|
||||
return OK;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NET_IGMP */
|
||||
|
@ -138,6 +138,18 @@ int igmp_leavegroup(struct net_driver_s *dev,
|
||||
ninfo("Leaving group: %p\n", group);
|
||||
if (group)
|
||||
{
|
||||
DEBUGASSERT(group->njoins > 0);
|
||||
group->njoins--;
|
||||
|
||||
/* Take no further actions if there are other members of this group
|
||||
* on this host.
|
||||
*/
|
||||
|
||||
if (group->njoins > 0)
|
||||
{
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Cancel the timer and discard any queued Membership Reports.
|
||||
* Canceling the timer will prevent any new Membership Reports from
|
||||
* being sent; clearing the flags will discard any pending Membership
|
||||
|
@ -126,6 +126,7 @@ int ipv4_setsockopt(FAR struct socket *psock, int option,
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef NET_UDP_HAVE_STACK
|
||||
case IP_ADD_MEMBERSHIP: /* Join a multicast group */
|
||||
case IP_DROP_MEMBERSHIP: /* Leave a multicast group */
|
||||
{
|
||||
@ -142,6 +143,8 @@ int ipv4_setsockopt(FAR struct socket *psock, int option,
|
||||
}
|
||||
else
|
||||
{
|
||||
FAR struct udp_conn_s *conn = psock->s_conn;
|
||||
|
||||
/* Use the default network device is imr_interface is
|
||||
* INADDRY_ANY.
|
||||
*/
|
||||
@ -166,17 +169,33 @@ int ipv4_setsockopt(FAR struct socket *psock, int option,
|
||||
}
|
||||
else if (option == IP_ADD_MEMBERSHIP)
|
||||
{
|
||||
ret = igmp_joingroup(dev, &mrec->imr_multiaddr);
|
||||
if (conn->mreq.imr_multiaddr.s_addr != 0)
|
||||
{
|
||||
ret = -EADDRINUSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = igmp_joingroup(dev, &mrec->imr_multiaddr);
|
||||
if (ret == OK)
|
||||
{
|
||||
conn->mreq.imr_multiaddr = mrec->imr_multiaddr;
|
||||
conn->mreq.imr_ifindex = dev->d_ifindex;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = igmp_leavegroup(dev, &mrec->imr_multiaddr);
|
||||
if (ret == OK)
|
||||
{
|
||||
conn->mreq.imr_multiaddr.s_addr = 0;
|
||||
conn->mreq.imr_ifindex = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef NET_UDP_HAVE_STACK
|
||||
case IP_MULTICAST_TTL: /* Set/read the time-to-live value of
|
||||
* outgoing multicast packets */
|
||||
#endif
|
||||
|
@ -1207,6 +1207,8 @@ static int netdev_imsf_ioctl(FAR struct socket *psock, int cmd,
|
||||
|
||||
ninfo("cmd: %d\n", cmd);
|
||||
|
||||
net_lock();
|
||||
|
||||
/* Execute the command */
|
||||
|
||||
switch (cmd)
|
||||
@ -1235,6 +1237,7 @@ static int netdev_imsf_ioctl(FAR struct socket *psock, int cmd,
|
||||
break;
|
||||
}
|
||||
|
||||
net_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
@ -310,6 +310,28 @@ int udp_bind(FAR struct udp_conn_s *conn, FAR const struct sockaddr *addr);
|
||||
int udp_connect(FAR struct udp_conn_s *conn,
|
||||
FAR const struct sockaddr *addr);
|
||||
|
||||
#if defined(CONFIG_NET_IGMP)
|
||||
/****************************************************************************
|
||||
* Name: udp_leavegroup
|
||||
*
|
||||
* Description:
|
||||
* This function leaves the multicast group to which the conn belongs.
|
||||
*
|
||||
* Input Parameters:
|
||||
* conn - A reference to UDP connection structure. A value of NULL will
|
||||
* disconnect from any previously connected address.
|
||||
*
|
||||
* Assumptions:
|
||||
* This function is called (indirectly) from user code. Interrupts may
|
||||
* be enabled.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void udp_leavegroup(FAR struct udp_conn_s *conn);
|
||||
#else
|
||||
#define udp_leavegroup(c)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: udp_close
|
||||
*
|
||||
|
@ -103,6 +103,8 @@ int udp_close(FAR struct socket *psock)
|
||||
nerr("ERROR: udp_txdrain() failed: %d\n", ret);
|
||||
}
|
||||
|
||||
udp_leavegroup(conn);
|
||||
|
||||
#ifdef CONFIG_NET_UDP_WRITE_BUFFERS
|
||||
/* Free any semi-permanent write buffer callback in place. */
|
||||
|
||||
|
@ -68,6 +68,7 @@
|
||||
#include "nat/nat.h"
|
||||
#include "netdev/netdev.h"
|
||||
#include "socket/socket.h"
|
||||
#include "igmp/igmp.h"
|
||||
#include "udp/udp.h"
|
||||
|
||||
/****************************************************************************
|
||||
@ -1080,4 +1081,35 @@ int udp_connect(FAR struct udp_conn_s *conn, FAR const struct sockaddr *addr)
|
||||
return OK;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_IGMP)
|
||||
/****************************************************************************
|
||||
* Name: udp_leavegroup
|
||||
*
|
||||
* Description:
|
||||
* This function leaves the multicast group to which the conn belongs.
|
||||
*
|
||||
* Input Parameters:
|
||||
* conn - A reference to UDP connection structure. A value of NULL will
|
||||
* disconnect from any previously connected address.
|
||||
*
|
||||
* Assumptions:
|
||||
* This function is called (indirectly) from user code. Interrupts may
|
||||
* be enabled.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void udp_leavegroup(FAR struct udp_conn_s *conn)
|
||||
{
|
||||
if (conn->mreq.imr_multiaddr.s_addr != 0)
|
||||
{
|
||||
FAR struct net_driver_s *dev;
|
||||
|
||||
if ((dev = netdev_findbyindex(conn->mreq.imr_ifindex)) != NULL)
|
||||
{
|
||||
igmp_leavegroup(dev, &conn->mreq.imr_multiaddr);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_NET && CONFIG_NET_UDP */
|
||||
|
Loading…
Reference in New Issue
Block a user