mirror of
https://github.com/apache/nuttx.git
synced 2026-05-28 20:08:15 +08:00
net/udp: Support deliver multicast packets back to local apps
Signed-off-by: Zhe Weng <wengzhe@xiaomi.com>
This commit is contained in:
@@ -305,10 +305,6 @@ int ipv4_setsockopt(FAR struct socket *psock, int option,
|
|||||||
|
|
||||||
/* The following IPv4 socket options are defined, but not implemented */
|
/* The following IPv4 socket options are defined, but not implemented */
|
||||||
|
|
||||||
case IP_MULTICAST_LOOP: /* Set/read boolean that determines
|
|
||||||
* whether sent multicast packets
|
|
||||||
* should be looped back to local
|
|
||||||
* sockets. */
|
|
||||||
case IP_UNBLOCK_SOURCE: /* Unblock previously blocked multicast
|
case IP_UNBLOCK_SOURCE: /* Unblock previously blocked multicast
|
||||||
* source */
|
* source */
|
||||||
case IP_BLOCK_SOURCE: /* Stop receiving multicast data from
|
case IP_BLOCK_SOURCE: /* Stop receiving multicast data from
|
||||||
@@ -327,8 +323,12 @@ int ipv4_setsockopt(FAR struct socket *psock, int option,
|
|||||||
nwarn("WARNING: Unimplemented IPv4 option: %d\n", option);
|
nwarn("WARNING: Unimplemented IPv4 option: %d\n", option);
|
||||||
ret = -ENOSYS;
|
ret = -ENOSYS;
|
||||||
break;
|
break;
|
||||||
#endif /* CONFIG_NET_IGMP */
|
|
||||||
|
|
||||||
|
case IP_MULTICAST_LOOP: /* Set/read boolean that determines
|
||||||
|
* whether sent multicast packets
|
||||||
|
* should be looped back to local
|
||||||
|
* sockets. */
|
||||||
|
#endif /* CONFIG_NET_IGMP */
|
||||||
case IP_PKTINFO:
|
case IP_PKTINFO:
|
||||||
{
|
{
|
||||||
FAR struct socket_conn_s *conn;
|
FAR struct socket_conn_s *conn;
|
||||||
|
|||||||
@@ -137,13 +137,11 @@ int ipv6_setsockopt(FAR struct socket *psock, int option,
|
|||||||
ret = OK;
|
ret = OK;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* NET_UDP_HAVE_STACK */
|
||||||
|
#endif /* CONFIG_NET_MLD */
|
||||||
|
|
||||||
/* The following IPv6 socket options are defined, but not implemented */
|
/* The following IPv6 socket options are defined, but not implemented */
|
||||||
|
|
||||||
case IPV6_MULTICAST_LOOP: /* Multicast packets are delivered back to
|
|
||||||
* the local application */
|
|
||||||
#endif
|
|
||||||
case IPV6_V6ONLY: /* Restrict AF_INET6 socket to IPv6
|
case IPV6_V6ONLY: /* Restrict AF_INET6 socket to IPv6
|
||||||
* communications only */
|
* communications only */
|
||||||
nwarn("WARNING: Unimplemented IPv6 option: %d\n", option);
|
nwarn("WARNING: Unimplemented IPv6 option: %d\n", option);
|
||||||
@@ -160,6 +158,10 @@ int ipv6_setsockopt(FAR struct socket *psock, int option,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#ifdef CONFIG_NET_MLD
|
||||||
|
case IPV6_MULTICAST_LOOP: /* Multicast packets are delivered back to
|
||||||
|
* the local application */
|
||||||
|
#endif
|
||||||
case IPV6_RECVPKTINFO:
|
case IPV6_RECVPKTINFO:
|
||||||
case IPV6_RECVHOPLIMIT:
|
case IPV6_RECVHOPLIMIT:
|
||||||
{
|
{
|
||||||
|
|||||||
+85
-3
@@ -58,9 +58,67 @@
|
|||||||
|
|
||||||
#include "devif/devif.h"
|
#include "devif/devif.h"
|
||||||
#include "inet/inet.h"
|
#include "inet/inet.h"
|
||||||
|
#include "socket/socket.h"
|
||||||
#include "utils/utils.h"
|
#include "utils/utils.h"
|
||||||
#include "udp/udp.h"
|
#include "udp/udp.h"
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: udp_send_loopback
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Send a copy of the UDP packet to ourself.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* dev - The device driver structure to use in the send operation
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#if defined(CONFIG_NET_SOCKOPTS) && \
|
||||||
|
(defined(CONFIG_NET_IGMP) || defined(CONFIG_NET_MLD))
|
||||||
|
static void udp_send_loopback(FAR struct net_driver_s *dev)
|
||||||
|
{
|
||||||
|
FAR struct iob_s *iob = netdev_iob_clone(dev, true);
|
||||||
|
if (iob == NULL)
|
||||||
|
{
|
||||||
|
nerr("ERROR: IOB clone failed when looping UDP.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_NET_IPv4
|
||||||
|
#ifdef CONFIG_NET_IPv6
|
||||||
|
if (IFF_IS_IPv4(dev->d_flags))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
ninfo("IPv4 frame\n");
|
||||||
|
NETDEV_RXIPV4(dev);
|
||||||
|
ipv4_input(dev);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_NET_IPv4 */
|
||||||
|
|
||||||
|
#ifdef CONFIG_NET_IPv6
|
||||||
|
#ifdef CONFIG_NET_IPv4
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
ninfo("IPv6 frame\n");
|
||||||
|
NETDEV_RXIPV6(dev);
|
||||||
|
ipv6_input(dev);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_NET_IPv6 */
|
||||||
|
|
||||||
|
/* Restore device IOB with backup IOB */
|
||||||
|
|
||||||
|
netdev_iob_replace(dev, iob);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -192,9 +250,7 @@ void udp_send(FAR struct net_driver_s *dev, FAR struct udp_conn_s *conn)
|
|||||||
|
|
||||||
#ifdef CONFIG_NET_IPv4
|
#ifdef CONFIG_NET_IPv4
|
||||||
#ifdef CONFIG_NET_IPv6
|
#ifdef CONFIG_NET_IPv6
|
||||||
if (conn->domain == PF_INET ||
|
if (IFF_IS_IPv4(dev->d_flags))
|
||||||
(conn->domain == PF_INET6 &&
|
|
||||||
ip6_is_ipv4addr((FAR struct in6_addr *)conn->u.ipv6.raddr)))
|
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
udp->udpchksum = ~udp_ipv4_chksum(dev);
|
udp->udpchksum = ~udp_ipv4_chksum(dev);
|
||||||
@@ -221,6 +277,32 @@ void udp_send(FAR struct net_driver_s *dev, FAR struct udp_conn_s *conn)
|
|||||||
#ifdef CONFIG_NET_STATISTICS
|
#ifdef CONFIG_NET_STATISTICS
|
||||||
g_netstats.udp.sent++;
|
g_netstats.udp.sent++;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_NET_SOCKOPTS
|
||||||
|
/* Try loopback multicast to ourself. */
|
||||||
|
|
||||||
|
#ifdef CONFIG_NET_IGMP
|
||||||
|
if (_SO_GETOPT(conn->sconn.s_options, IP_MULTICAST_LOOP) &&
|
||||||
|
#ifdef CONFIG_NET_IPv6
|
||||||
|
IFF_IS_IPv4(dev->d_flags) &&
|
||||||
|
#endif
|
||||||
|
IN_MULTICAST(NTOHL(raddr)))
|
||||||
|
{
|
||||||
|
udp_send_loopback(dev);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_NET_IGMP */
|
||||||
|
|
||||||
|
#ifdef CONFIG_NET_MLD
|
||||||
|
if (_SO_GETOPT(conn->sconn.s_options, IPV6_MULTICAST_LOOP) &&
|
||||||
|
#ifdef CONFIG_NET_IPv4
|
||||||
|
IFF_IS_IPv6(dev->d_flags) &&
|
||||||
|
#endif
|
||||||
|
IN6_IS_ADDR_MULTICAST((FAR struct in6_addr *)conn->u.ipv6.raddr))
|
||||||
|
{
|
||||||
|
udp_send_loopback(dev);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_NET_MLD */
|
||||||
|
#endif /* CONFIG_NET_SOCKOPTS */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user