net: Add support for IPV6_MTU IPv6 socket option

Add IPV6_MTU IPv6 socket option and implement getsockopt() and
setsockopt() calls for the option.

Signed-off-by: Jukka Rissanen <jukka.rissanen@nordicsemi.no>
This commit is contained in:
Jukka Rissanen 2024-11-13 09:26:53 +02:00 committed by Anas Nashif
commit 9fb09da21a
3 changed files with 87 additions and 0 deletions

View file

@ -1248,6 +1248,13 @@ struct ipv6_mreq {
int ipv6mr_ifindex;
};
/** For getsockopt(), retrieve the current known IPv6 path MTU of the given socket.
* Valid only when the socket has been connected.
* For setsockopt(), set the MTU to be used for the socket. The MTU is limited by
* the device MTU or the path MTU when path MTU discovery is enabled.
*/
#define IPV6_MTU 24
/** Don't support IPv4 access */
#define IPV6_V6ONLY 26

View file

@ -3102,6 +3102,55 @@ static int set_context_reuseport(struct net_context *context,
#endif
}
static int set_context_ipv6_mtu(struct net_context *context,
const void *value, size_t len)
{
#if defined(CONFIG_NET_IPV6)
struct net_if *iface;
uint16_t mtu;
if (len != sizeof(int)) {
return -EINVAL;
}
mtu = *((int *)value);
if (IS_ENABLED(CONFIG_NET_IPV6_PMTU)) {
int ret;
ret = net_pmtu_update_mtu(&context->remote, mtu);
if (ret < 0) {
return ret;
}
return 0;
}
if (net_context_is_bound_to_iface(context)) {
iface = net_context_get_iface(context);
} else {
sa_family_t family = net_context_get_family(context);
if (IS_ENABLED(CONFIG_NET_IPV6) && family == AF_INET6) {
iface = net_if_ipv6_select_src_iface(
&net_sin6(&context->remote)->sin6_addr);
} else {
return -EAFNOSUPPORT;
}
}
net_if_set_mtu(iface, (uint16_t)mtu);
return 0;
#else
ARG_UNUSED(context);
ARG_UNUSED(value);
ARG_UNUSED(len);
return -ENOTSUP;
#endif
}
static int set_context_ipv6_v6only(struct net_context *context,
const void *value, size_t len)
{
@ -3236,6 +3285,9 @@ int net_context_set_option(struct net_context *context,
if (IS_ENABLED(CONFIG_NET_IPV4) &&
net_context_get_family(context) == AF_INET) {
ret = -EOPNOTSUPP;
} else if (IS_ENABLED(CONFIG_NET_IPV6) &&
net_context_get_family(context) == AF_INET6) {
ret = set_context_ipv6_mtu(context, value, len);
}
break;

View file

@ -1858,6 +1858,20 @@ int zsock_getsockopt_ctx(struct net_context *ctx, int level, int optname,
case IPPROTO_IPV6:
switch (optname) {
case IPV6_MTU:
if (IS_ENABLED(CONFIG_NET_IPV6)) {
ret = net_context_get_option(ctx, NET_OPT_MTU,
optval, optlen);
if (ret < 0) {
errno = -ret;
return -1;
}
return 0;
}
break;
case IPV6_V6ONLY:
if (IS_ENABLED(CONFIG_NET_IPV4_MAPPING_TO_IPV6)) {
ret = net_context_get_option(ctx,
@ -2422,6 +2436,20 @@ int zsock_setsockopt_ctx(struct net_context *ctx, int level, int optname,
case IPPROTO_IPV6:
switch (optname) {
case IPV6_MTU:
if (IS_ENABLED(CONFIG_NET_IPV6)) {
ret = net_context_set_option(ctx, NET_OPT_MTU,
optval, optlen);
if (ret < 0) {
errno = -ret;
return -1;
}
return 0;
}
break;
case IPV6_V6ONLY:
if (IS_ENABLED(CONFIG_NET_IPV4_MAPPING_TO_IPV6)) {
ret = net_context_set_option(ctx,