Browse Source

net: Add support for IPv4_MULTICAST_LOOP in net_context

Add support for the IP_MULTICAST_LOOP socket option to control
multicast packet loopback.

Signed-off-by: AbdElRahman Khalifa <abdelrahman.5alifa@gmail.com>
pull/87253/head
AbdElRahman Khalifa 4 months ago committed by Benjamin Cabé
parent
commit
b11703623c
  1. 34
      include/zephyr/net/net_context.h
  2. 2
      include/zephyr/net/socket.h
  3. 7
      subsys/net/ip/Kconfig.ipv4
  4. 37
      subsys/net/ip/net_context.c
  5. 65
      subsys/net/ip/net_core.c
  6. 24
      subsys/net/lib/sockets/sockets_inet.c

34
include/zephyr/net/net_context.h

@ -394,6 +394,7 @@ __net_socket struct net_context { @@ -394,6 +394,7 @@ __net_socket struct net_context {
/** Flag to enable/disable multicast loop */
union {
bool ipv6_mcast_loop; /**< IPv6 multicast loop */
bool ipv4_mcast_loop; /**< IPv4 multicast loop */
};
#endif /* CONFIG_NET_IPV6 || CONFIG_NET_IPV4 */
@ -843,6 +844,38 @@ static inline void net_context_set_ipv4_mcast_ttl(struct net_context *context, @@ -843,6 +844,38 @@ static inline void net_context_set_ipv4_mcast_ttl(struct net_context *context,
context->ipv4_mcast_ttl = ttl;
}
#if defined(CONFIG_NET_IPV4)
/**
* @brief Get IPv4 multicast loop value for this context.
*
* @details This function returns the IPv4 multicast loop value
* that is set to this context.
*
* @param context Network context.
*
* @return IPv4 multicast loop value
*/
static inline bool net_context_get_ipv4_mcast_loop(struct net_context *context)
{
return context->options.ipv4_mcast_loop;
}
/**
* @brief Set IPv4 multicast loop value for this context.
*
* @details This function sets the IPv4 multicast loop value for
* this context.
*
* @param context Network context.
* @param ipv4_mcast_loop IPv4 multicast loop value.
*/
static inline void net_context_set_ipv4_mcast_loop(struct net_context *context,
bool ipv4_mcast_loop)
{
context->options.ipv4_mcast_loop = ipv4_mcast_loop;
}
#endif
/**
* @brief Get IPv6 hop limit value for this context.
*
@ -1365,6 +1398,7 @@ enum net_context_option { @@ -1365,6 +1398,7 @@ enum net_context_option {
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 */
NET_OPT_IPV4_MCAST_LOOP = 23, /**< IPV4 multicast loop */
};
/**

2
include/zephyr/net/socket.h

@ -965,6 +965,8 @@ struct in_pktinfo { @@ -965,6 +965,8 @@ struct in_pktinfo {
#define IP_MULTICAST_IF 32
/** Set IPv4 multicast TTL value. */
#define IP_MULTICAST_TTL 33
/** Set IPv4 multicast loop value. */
#define IP_MULTICAST_LOOP 34
/** Join IPv4 multicast group. */
#define IP_ADD_MEMBERSHIP 35
/** Leave IPv4 multicast group. */

7
subsys/net/ip/Kconfig.ipv4

@ -73,6 +73,13 @@ config NET_INITIAL_MCAST_TTL @@ -73,6 +73,13 @@ config NET_INITIAL_MCAST_TTL
don't leave the local network unless the application explicitly
requests it.
config NET_INITIAL_IPV4_MCAST_LOOP
bool "Control whether the socket sees multicast packets sent by itself"
default y
help
Assign initial value to IPV4_MULTICAST_LOOP in socket options,
if not set by the user using setsockopt().
config NET_IF_MCAST_IPV4_SOURCE_COUNT
int "Max number of IPv4 sources per mcast address to be included or excluded"
default 1

37
subsys/net/ip/net_context.c

@ -566,6 +566,10 @@ int net_context_get(sa_family_t family, enum net_sock_type type, uint16_t proto, @@ -566,6 +566,10 @@ int net_context_get(sa_family_t family, enum net_sock_type type, uint16_t proto,
#if defined(CONFIG_NET_IPV4_MAPPING_TO_IPV6)
/* By default IPv4 and IPv6 are in different port spaces */
contexts[i].options.ipv6_v6only = true;
#endif
#if defined(CONFIG_NET_IPV4)
contexts[i].options.ipv4_mcast_loop =
IS_ENABLED(CONFIG_NET_INITIAL_IPV4_MCAST_LOOP);
#endif
if (IS_ENABLED(CONFIG_NET_IP)) {
(void)memset(&contexts[i].remote, 0, sizeof(struct sockaddr));
@ -1783,6 +1787,19 @@ static int get_context_mcast_ttl(struct net_context *context, @@ -1783,6 +1787,19 @@ static int get_context_mcast_ttl(struct net_context *context,
#endif
}
static int get_context_ipv4_mcast_loop(struct net_context *context,
void *value, size_t *len)
{
#if defined(CONFIG_NET_IPV4)
return get_bool_option(context->options.ipv4_mcast_loop, value, len);
#else
ARG_UNUSED(context);
ARG_UNUSED(value);
ARG_UNUSED(len);
return -ENOTSUP;
#endif
}
static int get_context_mcast_hop_limit(struct net_context *context,
void *value, size_t *len)
{
@ -3293,6 +3310,20 @@ static int set_context_mcast_ttl(struct net_context *context, @@ -3293,6 +3310,20 @@ static int set_context_mcast_ttl(struct net_context *context,
#endif
}
static int set_context_ipv4_mcast_loop(struct net_context *context,
const void *value, size_t len)
{
#if defined(CONFIG_NET_IPV4)
return set_bool_option(&context->options.ipv4_mcast_loop, value, len);
#else
ARG_UNUSED(context);
ARG_UNUSED(value);
ARG_UNUSED(len);
return -ENOTSUP;
#endif
}
static int set_context_mcast_hop_limit(struct net_context *context,
const void *value, size_t len)
{
@ -3688,6 +3719,9 @@ int net_context_set_option(struct net_context *context, @@ -3688,6 +3719,9 @@ int net_context_set_option(struct net_context *context,
case NET_OPT_IPV6_MCAST_LOOP:
ret = set_context_ipv6_mcast_loop(context, value, len);
break;
case NET_OPT_IPV4_MCAST_LOOP:
ret = set_context_ipv4_mcast_loop(context, value, len);
break;
}
k_mutex_unlock(&context->lock);
@ -3776,6 +3810,9 @@ int net_context_get_option(struct net_context *context, @@ -3776,6 +3810,9 @@ int net_context_get_option(struct net_context *context,
case NET_OPT_IPV6_MCAST_LOOP:
ret = get_context_ipv6_mcast_loop(context, value, len);
break;
case NET_OPT_IPV4_MCAST_LOOP:
ret = get_context_ipv4_mcast_loop(context, value, len);
break;
}
k_mutex_unlock(&context->lock);

65
subsys/net/ip/net_core.c

@ -366,6 +366,34 @@ drop: @@ -366,6 +366,34 @@ drop:
return ret;
}
#if defined(CONFIG_NET_IPV4) || defined(CONFIG_NET_IPV6)
static inline bool process_multicast(struct net_pkt *pkt)
{
struct net_context *ctx = net_pkt_context(pkt);
sa_family_t family = net_pkt_family(pkt);
if (ctx == NULL) {
return false;
}
#if defined(CONFIG_NET_IPV4)
if (family == AF_INET) {
const struct in_addr *dst = (const struct in_addr *)&NET_IPV4_HDR(pkt)->dst;
return net_ipv4_is_addr_mcast(dst) && net_context_get_ipv4_mcast_loop(ctx);
}
#endif
#if defined(CONFIG_NET_IPV6)
if (family == AF_INET6) {
const struct in6_addr *dst = (const struct in6_addr *)&NET_IPV6_HDR(pkt)->dst;
return net_ipv6_is_addr_mcast(dst) && net_context_get_ipv6_mcast_loop(ctx);
}
#endif
return false;
}
#endif
int net_try_send_data(struct net_pkt *pkt, k_timeout_t timeout)
{
int status;
@ -410,26 +438,31 @@ int net_try_send_data(struct net_pkt *pkt, k_timeout_t timeout) @@ -410,26 +438,31 @@ int net_try_send_data(struct net_pkt *pkt, k_timeout_t timeout)
goto err;
}
#if defined(CONFIG_NET_IPV4) || defined(CONFIG_NET_IPV6)
if (process_multicast(pkt)) {
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)) {
switch (net_pkt_family(pkt)) {
#if defined(CONFIG_NET_IPV4)
case AF_INET:
net_stats_update_ipv4_sent(net_pkt_iface(pkt));
break;
#endif
#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));
case AF_INET6:
net_stats_update_ipv6_sent(net_pkt_iface(pkt));
break;
#endif
}
net_pkt_unref(clone);
}
} else {
NET_DBG("Failed to clone multicast packet");
net_pkt_unref(clone);
}
} else {
NET_DBG("Failed to clone multicast packet");
}
}
#endif

24
subsys/net/lib/sockets/sockets_inet.c

@ -1974,6 +1974,18 @@ int zsock_getsockopt_ctx(struct net_context *ctx, int level, int optname, @@ -1974,6 +1974,18 @@ int zsock_getsockopt_ctx(struct net_context *ctx, int level, int optname,
}
break;
#if defined(CONFIG_NET_IPV4)
case IP_MULTICAST_LOOP:
ret = net_context_get_option(ctx,
NET_OPT_IPV4_MCAST_LOOP,
optval, optlen);
if (ret < 0) {
errno = -ret;
return -1;
}
return 0;
#endif
}
break;
@ -2604,6 +2616,18 @@ int zsock_setsockopt_ctx(struct net_context *ctx, int level, int optname, @@ -2604,6 +2616,18 @@ int zsock_setsockopt_ctx(struct net_context *ctx, int level, int optname,
}
break;
#if defined(CONFIG_NET_IPV4)
case IP_MULTICAST_LOOP:
ret = net_context_set_option(ctx,
NET_OPT_IPV4_MCAST_LOOP,
optval, optlen);
if (ret < 0) {
errno = -ret;
return -1;
}
return 0;
#endif
}
break;

Loading…
Cancel
Save