net: sockets: IPv6_MULTICAST_LOOP Support
Add support for the IPV6_MULTICAST_LOOP socket option. This option allows enabling or disabling the consumption of multicast packets by the sender. By default, the socket option will be enabled. Co-authored-by: Pieter De Gendt <pieter.degendt@gmail.com> Signed-off-by: Sayooj K Karun <sayooj@aerlync.com>
This commit is contained in:
parent
a61287e876
commit
273d60164d
6 changed files with 140 additions and 0 deletions
|
@ -7,6 +7,7 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
* Copyright (c) 2021 Nordic Semiconductor
|
||||
* Copyright (c) 2025 Aerlync Labs Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -390,6 +391,10 @@ __net_socket struct net_context {
|
|||
*/
|
||||
uint8_t ipv4_mcast_ifindex;
|
||||
};
|
||||
/** Flag to enable/disable multicast loop */
|
||||
union {
|
||||
bool ipv6_mcast_loop; /**< IPv6 multicast loop */
|
||||
};
|
||||
#endif /* CONFIG_NET_IPV6 || CONFIG_NET_IPV4 */
|
||||
|
||||
#if defined(CONFIG_NET_CONTEXT_TIMESTAMPING)
|
||||
|
@ -897,6 +902,40 @@ static inline void net_context_set_ipv6_mcast_hop_limit(struct net_context *cont
|
|||
context->ipv6_mcast_hop_limit = hop_limit;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
|
||||
/**
|
||||
* @brief Get IPv6 multicast loop value for this context.
|
||||
*
|
||||
* @details This function returns the IPv6 multicast loop value
|
||||
* that is set to this context.
|
||||
*
|
||||
* @param context Network context.
|
||||
*
|
||||
* @return IPv6 multicast loop value
|
||||
*/
|
||||
static inline bool net_context_get_ipv6_mcast_loop(struct net_context *context)
|
||||
{
|
||||
return context->options.ipv6_mcast_loop;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set IPv6 multicast loop value for this context.
|
||||
*
|
||||
* @details This function sets the IPv6 multicast loop value for
|
||||
* this context.
|
||||
*
|
||||
* @param context Network context.
|
||||
* @param ipv6_mcast_loop IPv6 multicast loop value.
|
||||
*/
|
||||
static inline void net_context_set_ipv6_mcast_loop(struct net_context *context,
|
||||
bool ipv6_mcast_loop)
|
||||
{
|
||||
context->options.ipv6_mcast_loop = ipv6_mcast_loop;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enable or disable socks proxy support for this context.
|
||||
*
|
||||
|
@ -1325,6 +1364,7 @@ enum net_context_option {
|
|||
NET_OPT_MCAST_IFINDEX = 19, /**< IPv6 multicast output network interface index */
|
||||
NET_OPT_MTU = 20, /**< IPv4 socket path MTU */
|
||||
NET_OPT_LOCAL_PORT_RANGE = 21, /**< Clamp local port range */
|
||||
NET_OPT_IPV6_MCAST_LOOP = 22, /**< IPV6 multicast loop */
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2018 Linaro Limited
|
||||
* Copyright (c) 2021 Nordic Semiconductor
|
||||
* Copyright (c) 2025 Aerlync Labs Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -1005,6 +1006,9 @@ struct ip_mreq {
|
|||
/** Set the multicast hop limit for the socket. */
|
||||
#define IPV6_MULTICAST_HOPS 18
|
||||
|
||||
/** Set the multicast loop bit for the socket. */
|
||||
#define IPV6_MULTICAST_LOOP 19
|
||||
|
||||
/** Join IPv6 multicast group. */
|
||||
#define IPV6_ADD_MEMBERSHIP 20
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# IPv6 Options
|
||||
|
||||
# Copyright (c) 2016 Intel Corporation.
|
||||
# Copyright (c) 2025 Aerlync Labs Inc.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
menuconfig NET_IPV6
|
||||
|
@ -81,6 +82,13 @@ config NET_INITIAL_MCAST_HOP_LIMIT
|
|||
don't leave the local network unless the application explicitly
|
||||
requests it.
|
||||
|
||||
config NET_INITIAL_IPV6_MCAST_LOOP
|
||||
bool "Control whether the socket sees multicast packets sent by itself"
|
||||
default y
|
||||
help
|
||||
Assign initial value to IPV6_MULTICAST_LOOP in socket options,
|
||||
if not set by the user using setsockopt().
|
||||
|
||||
config NET_IPV6_MAX_NEIGHBORS
|
||||
int "How many IPv6 neighbors are supported"
|
||||
default 8
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
* Copyright (c) 2021 Nordic Semiconductor
|
||||
* Copyright (c) 2025 Aerlync Labs Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -583,6 +584,10 @@ int net_context_get(sa_family_t family, enum net_sock_type type, uint16_t proto,
|
|||
|
||||
contexts[i].ipv6_hop_limit = INITIAL_HOP_LIMIT;
|
||||
contexts[i].ipv6_mcast_hop_limit = INITIAL_MCAST_HOP_LIMIT;
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
contexts[i].options.ipv6_mcast_loop =
|
||||
IS_ENABLED(CONFIG_NET_INITIAL_IPV6_MCAST_LOOP);
|
||||
#endif
|
||||
}
|
||||
if (IS_ENABLED(CONFIG_NET_IPV4) && family == AF_INET) {
|
||||
struct sockaddr_in *addr = (struct sockaddr_in *)&contexts[i].local;
|
||||
|
@ -2033,6 +2038,20 @@ static int get_context_local_port_range(struct net_context *context,
|
|||
#endif
|
||||
}
|
||||
|
||||
static int get_context_ipv6_mcast_loop(struct net_context *context,
|
||||
void *value, size_t *len)
|
||||
{
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
return get_bool_option(context->options.ipv6_mcast_loop, value, len);
|
||||
#else
|
||||
ARG_UNUSED(context);
|
||||
ARG_UNUSED(value);
|
||||
ARG_UNUSED(len);
|
||||
|
||||
return -ENOTSUP;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* If buf is not NULL, then use it. Otherwise read the data to be written
|
||||
* to net_pkt from msghdr.
|
||||
*/
|
||||
|
@ -3329,6 +3348,20 @@ static int set_context_unicast_hop_limit(struct net_context *context,
|
|||
#endif
|
||||
}
|
||||
|
||||
static int set_context_ipv6_mcast_loop(struct net_context *context,
|
||||
const void *value, size_t len)
|
||||
{
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
return set_bool_option(&context->options.ipv6_mcast_loop, value, len);
|
||||
#else
|
||||
ARG_UNUSED(context);
|
||||
ARG_UNUSED(value);
|
||||
ARG_UNUSED(len);
|
||||
|
||||
return -ENOTSUP;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int set_context_reuseaddr(struct net_context *context,
|
||||
const void *value, size_t len)
|
||||
{
|
||||
|
@ -3652,6 +3685,9 @@ int net_context_set_option(struct net_context *context,
|
|||
case NET_OPT_LOCAL_PORT_RANGE:
|
||||
ret = set_context_local_port_range(context, value, len);
|
||||
break;
|
||||
case NET_OPT_IPV6_MCAST_LOOP:
|
||||
ret = set_context_ipv6_mcast_loop(context, value, len);
|
||||
break;
|
||||
}
|
||||
|
||||
k_mutex_unlock(&context->lock);
|
||||
|
@ -3737,6 +3773,9 @@ int net_context_get_option(struct net_context *context,
|
|||
case NET_OPT_LOCAL_PORT_RANGE:
|
||||
ret = get_context_local_port_range(context, value, len);
|
||||
break;
|
||||
case NET_OPT_IPV6_MCAST_LOOP:
|
||||
ret = get_context_ipv6_mcast_loop(context, value, len);
|
||||
break;
|
||||
}
|
||||
|
||||
k_mutex_unlock(&context->lock);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
* Copyright (c) 2025 Aerlync Labs Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -409,6 +410,30 @@ int net_try_send_data(struct net_pkt *pkt, k_timeout_t timeout)
|
|||
goto err;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
if (net_pkt_family(pkt) == AF_INET6) {
|
||||
const struct in6_addr *dest = (const struct in6_addr *)&NET_IPV6_HDR(pkt)->dst;
|
||||
struct net_context *ctx = net_pkt_context(pkt);
|
||||
|
||||
if (net_ipv6_is_addr_mcast(dest) && ctx != NULL &&
|
||||
net_context_get_ipv6_mcast_loop(ctx)) {
|
||||
struct net_pkt *clone = net_pkt_clone(pkt, K_NO_WAIT);
|
||||
|
||||
if (clone != NULL) {
|
||||
net_pkt_set_iface(clone, net_pkt_iface(pkt));
|
||||
if (net_recv_data(net_pkt_iface(clone), clone) < 0) {
|
||||
if (IS_ENABLED(CONFIG_NET_STATISTICS)) {
|
||||
net_stats_update_ipv6_drop(net_pkt_iface(pkt));
|
||||
}
|
||||
net_pkt_unref(clone);
|
||||
}
|
||||
} else {
|
||||
NET_DBG("Failed to clone multicast packet");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (net_if_try_send_data(net_pkt_iface(pkt), pkt, timeout) == NET_DROP) {
|
||||
ret = -EIO;
|
||||
goto err;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* Copyright (c) 2017 Linaro Limited
|
||||
* Copyright (c) 2021 Nordic Semiconductor
|
||||
* Copyright (c) 2023 Arm Limited (or its affiliates). All rights reserved.
|
||||
* Copyright (c) 2025 Aerlync Labs Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -2080,6 +2081,18 @@ int zsock_getsockopt_ctx(struct net_context *ctx, int level, int optname,
|
|||
}
|
||||
|
||||
return 0;
|
||||
|
||||
case IPV6_MULTICAST_LOOP:
|
||||
ret = net_context_get_option(ctx,
|
||||
NET_OPT_IPV6_MCAST_LOOP,
|
||||
optval, optlen);
|
||||
if (ret < 0) {
|
||||
errno = -ret;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -2722,6 +2735,17 @@ int zsock_setsockopt_ctx(struct net_context *ctx, int level, int optname,
|
|||
}
|
||||
|
||||
break;
|
||||
|
||||
case IPV6_MULTICAST_LOOP:
|
||||
ret = net_context_set_option(ctx,
|
||||
NET_OPT_IPV6_MCAST_LOOP,
|
||||
optval, optlen);
|
||||
if (ret < 0) {
|
||||
errno = -ret;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue