Skip to content

Commit b117036

Browse files
Abd002kartben
authored andcommitted
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 <[email protected]>
1 parent 58d5e35 commit b117036

File tree

6 files changed

+153
-16
lines changed

6 files changed

+153
-16
lines changed

include/zephyr/net/net_context.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,7 @@ __net_socket struct net_context {
394394
/** Flag to enable/disable multicast loop */
395395
union {
396396
bool ipv6_mcast_loop; /**< IPv6 multicast loop */
397+
bool ipv4_mcast_loop; /**< IPv4 multicast loop */
397398
};
398399
#endif /* CONFIG_NET_IPV6 || CONFIG_NET_IPV4 */
399400

@@ -843,6 +844,38 @@ static inline void net_context_set_ipv4_mcast_ttl(struct net_context *context,
843844
context->ipv4_mcast_ttl = ttl;
844845
}
845846

847+
#if defined(CONFIG_NET_IPV4)
848+
/**
849+
* @brief Get IPv4 multicast loop value for this context.
850+
*
851+
* @details This function returns the IPv4 multicast loop value
852+
* that is set to this context.
853+
*
854+
* @param context Network context.
855+
*
856+
* @return IPv4 multicast loop value
857+
*/
858+
static inline bool net_context_get_ipv4_mcast_loop(struct net_context *context)
859+
{
860+
return context->options.ipv4_mcast_loop;
861+
}
862+
863+
/**
864+
* @brief Set IPv4 multicast loop value for this context.
865+
*
866+
* @details This function sets the IPv4 multicast loop value for
867+
* this context.
868+
*
869+
* @param context Network context.
870+
* @param ipv4_mcast_loop IPv4 multicast loop value.
871+
*/
872+
static inline void net_context_set_ipv4_mcast_loop(struct net_context *context,
873+
bool ipv4_mcast_loop)
874+
{
875+
context->options.ipv4_mcast_loop = ipv4_mcast_loop;
876+
}
877+
#endif
878+
846879
/**
847880
* @brief Get IPv6 hop limit value for this context.
848881
*
@@ -1365,6 +1398,7 @@ enum net_context_option {
13651398
NET_OPT_MTU = 20, /**< IPv4 socket path MTU */
13661399
NET_OPT_LOCAL_PORT_RANGE = 21, /**< Clamp local port range */
13671400
NET_OPT_IPV6_MCAST_LOOP = 22, /**< IPV6 multicast loop */
1401+
NET_OPT_IPV4_MCAST_LOOP = 23, /**< IPV4 multicast loop */
13681402
};
13691403

13701404
/**

include/zephyr/net/socket.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -965,6 +965,8 @@ struct in_pktinfo {
965965
#define IP_MULTICAST_IF 32
966966
/** Set IPv4 multicast TTL value. */
967967
#define IP_MULTICAST_TTL 33
968+
/** Set IPv4 multicast loop value. */
969+
#define IP_MULTICAST_LOOP 34
968970
/** Join IPv4 multicast group. */
969971
#define IP_ADD_MEMBERSHIP 35
970972
/** Leave IPv4 multicast group. */

subsys/net/ip/Kconfig.ipv4

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,13 @@ config NET_INITIAL_MCAST_TTL
7373
don't leave the local network unless the application explicitly
7474
requests it.
7575

76+
config NET_INITIAL_IPV4_MCAST_LOOP
77+
bool "Control whether the socket sees multicast packets sent by itself"
78+
default y
79+
help
80+
Assign initial value to IPV4_MULTICAST_LOOP in socket options,
81+
if not set by the user using setsockopt().
82+
7683
config NET_IF_MCAST_IPV4_SOURCE_COUNT
7784
int "Max number of IPv4 sources per mcast address to be included or excluded"
7885
default 1

subsys/net/ip/net_context.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,10 @@ int net_context_get(sa_family_t family, enum net_sock_type type, uint16_t proto,
566566
#if defined(CONFIG_NET_IPV4_MAPPING_TO_IPV6)
567567
/* By default IPv4 and IPv6 are in different port spaces */
568568
contexts[i].options.ipv6_v6only = true;
569+
#endif
570+
#if defined(CONFIG_NET_IPV4)
571+
contexts[i].options.ipv4_mcast_loop =
572+
IS_ENABLED(CONFIG_NET_INITIAL_IPV4_MCAST_LOOP);
569573
#endif
570574
if (IS_ENABLED(CONFIG_NET_IP)) {
571575
(void)memset(&contexts[i].remote, 0, sizeof(struct sockaddr));
@@ -1783,6 +1787,19 @@ static int get_context_mcast_ttl(struct net_context *context,
17831787
#endif
17841788
}
17851789

1790+
static int get_context_ipv4_mcast_loop(struct net_context *context,
1791+
void *value, size_t *len)
1792+
{
1793+
#if defined(CONFIG_NET_IPV4)
1794+
return get_bool_option(context->options.ipv4_mcast_loop, value, len);
1795+
#else
1796+
ARG_UNUSED(context);
1797+
ARG_UNUSED(value);
1798+
ARG_UNUSED(len);
1799+
return -ENOTSUP;
1800+
#endif
1801+
}
1802+
17861803
static int get_context_mcast_hop_limit(struct net_context *context,
17871804
void *value, size_t *len)
17881805
{
@@ -3293,6 +3310,20 @@ static int set_context_mcast_ttl(struct net_context *context,
32933310
#endif
32943311
}
32953312

3313+
static int set_context_ipv4_mcast_loop(struct net_context *context,
3314+
const void *value, size_t len)
3315+
{
3316+
#if defined(CONFIG_NET_IPV4)
3317+
return set_bool_option(&context->options.ipv4_mcast_loop, value, len);
3318+
#else
3319+
ARG_UNUSED(context);
3320+
ARG_UNUSED(value);
3321+
ARG_UNUSED(len);
3322+
3323+
return -ENOTSUP;
3324+
#endif
3325+
}
3326+
32963327
static int set_context_mcast_hop_limit(struct net_context *context,
32973328
const void *value, size_t len)
32983329
{
@@ -3688,6 +3719,9 @@ int net_context_set_option(struct net_context *context,
36883719
case NET_OPT_IPV6_MCAST_LOOP:
36893720
ret = set_context_ipv6_mcast_loop(context, value, len);
36903721
break;
3722+
case NET_OPT_IPV4_MCAST_LOOP:
3723+
ret = set_context_ipv4_mcast_loop(context, value, len);
3724+
break;
36913725
}
36923726

36933727
k_mutex_unlock(&context->lock);
@@ -3776,6 +3810,9 @@ int net_context_get_option(struct net_context *context,
37763810
case NET_OPT_IPV6_MCAST_LOOP:
37773811
ret = get_context_ipv6_mcast_loop(context, value, len);
37783812
break;
3813+
case NET_OPT_IPV4_MCAST_LOOP:
3814+
ret = get_context_ipv4_mcast_loop(context, value, len);
3815+
break;
37793816
}
37803817

37813818
k_mutex_unlock(&context->lock);

subsys/net/ip/net_core.c

Lines changed: 49 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,34 @@ static inline int check_ip(struct net_pkt *pkt)
366366
return ret;
367367
}
368368

369+
#if defined(CONFIG_NET_IPV4) || defined(CONFIG_NET_IPV6)
370+
static inline bool process_multicast(struct net_pkt *pkt)
371+
{
372+
struct net_context *ctx = net_pkt_context(pkt);
373+
sa_family_t family = net_pkt_family(pkt);
374+
375+
if (ctx == NULL) {
376+
return false;
377+
}
378+
379+
#if defined(CONFIG_NET_IPV4)
380+
if (family == AF_INET) {
381+
const struct in_addr *dst = (const struct in_addr *)&NET_IPV4_HDR(pkt)->dst;
382+
383+
return net_ipv4_is_addr_mcast(dst) && net_context_get_ipv4_mcast_loop(ctx);
384+
}
385+
#endif
386+
#if defined(CONFIG_NET_IPV6)
387+
if (family == AF_INET6) {
388+
const struct in6_addr *dst = (const struct in6_addr *)&NET_IPV6_HDR(pkt)->dst;
389+
390+
return net_ipv6_is_addr_mcast(dst) && net_context_get_ipv6_mcast_loop(ctx);
391+
}
392+
#endif
393+
return false;
394+
}
395+
#endif
396+
369397
int net_try_send_data(struct net_pkt *pkt, k_timeout_t timeout)
370398
{
371399
int status;
@@ -410,26 +438,31 @@ int net_try_send_data(struct net_pkt *pkt, k_timeout_t timeout)
410438
goto err;
411439
}
412440

441+
#if defined(CONFIG_NET_IPV4) || defined(CONFIG_NET_IPV6)
442+
if (process_multicast(pkt)) {
443+
struct net_pkt *clone = net_pkt_clone(pkt, K_NO_WAIT);
444+
445+
if (clone != NULL) {
446+
net_pkt_set_iface(clone, net_pkt_iface(pkt));
447+
if (net_recv_data(net_pkt_iface(clone), clone) < 0) {
448+
if (IS_ENABLED(CONFIG_NET_STATISTICS)) {
449+
switch (net_pkt_family(pkt)) {
450+
#if defined(CONFIG_NET_IPV4)
451+
case AF_INET:
452+
net_stats_update_ipv4_sent(net_pkt_iface(pkt));
453+
break;
454+
#endif
413455
#if defined(CONFIG_NET_IPV6)
414-
if (net_pkt_family(pkt) == AF_INET6) {
415-
const struct in6_addr *dest = (const struct in6_addr *)&NET_IPV6_HDR(pkt)->dst;
416-
struct net_context *ctx = net_pkt_context(pkt);
417-
418-
if (net_ipv6_is_addr_mcast(dest) && ctx != NULL &&
419-
net_context_get_ipv6_mcast_loop(ctx)) {
420-
struct net_pkt *clone = net_pkt_clone(pkt, K_NO_WAIT);
421-
422-
if (clone != NULL) {
423-
net_pkt_set_iface(clone, net_pkt_iface(pkt));
424-
if (net_recv_data(net_pkt_iface(clone), clone) < 0) {
425-
if (IS_ENABLED(CONFIG_NET_STATISTICS)) {
426-
net_stats_update_ipv6_drop(net_pkt_iface(pkt));
456+
case AF_INET6:
457+
net_stats_update_ipv6_sent(net_pkt_iface(pkt));
458+
break;
459+
#endif
427460
}
428-
net_pkt_unref(clone);
429461
}
430-
} else {
431-
NET_DBG("Failed to clone multicast packet");
462+
net_pkt_unref(clone);
432463
}
464+
} else {
465+
NET_DBG("Failed to clone multicast packet");
433466
}
434467
}
435468
#endif

subsys/net/lib/sockets/sockets_inet.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1974,6 +1974,18 @@ int zsock_getsockopt_ctx(struct net_context *ctx, int level, int optname,
19741974
}
19751975

19761976
break;
1977+
#if defined(CONFIG_NET_IPV4)
1978+
case IP_MULTICAST_LOOP:
1979+
ret = net_context_get_option(ctx,
1980+
NET_OPT_IPV4_MCAST_LOOP,
1981+
optval, optlen);
1982+
if (ret < 0) {
1983+
errno = -ret;
1984+
return -1;
1985+
}
1986+
1987+
return 0;
1988+
#endif
19771989
}
19781990

19791991
break;
@@ -2604,6 +2616,18 @@ int zsock_setsockopt_ctx(struct net_context *ctx, int level, int optname,
26042616
}
26052617

26062618
break;
2619+
#if defined(CONFIG_NET_IPV4)
2620+
case IP_MULTICAST_LOOP:
2621+
ret = net_context_set_option(ctx,
2622+
NET_OPT_IPV4_MCAST_LOOP,
2623+
optval, optlen);
2624+
if (ret < 0) {
2625+
errno = -ret;
2626+
return -1;
2627+
}
2628+
2629+
return 0;
2630+
#endif
26072631
}
26082632

26092633
break;

0 commit comments

Comments
 (0)