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:
parent
74fc23872d
commit
9fb09da21a
3 changed files with 87 additions and 0 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue