net: Add support for IP_MTU IPv4 socket option

Add IP_MTU IPv4 socket option and implement getsockopt()
call for the option. The IP_MTU option does not support
setsockopt() call.

Signed-off-by: Jukka Rissanen <jukka.rissanen@nordicsemi.no>
This commit is contained in:
Jukka Rissanen 2024-11-12 18:18:44 +02:00 committed by Anas Nashif
commit a818839186
4 changed files with 72 additions and 0 deletions

View file

@ -1292,6 +1292,7 @@ enum net_context_option {
NET_OPT_TTL = 16, /**< IPv4 unicast TTL */
NET_OPT_ADDR_PREFERENCES = 17, /**< IPv6 address preference */
NET_OPT_TIMESTAMPING = 18, /**< Packet timestamping */
NET_OPT_MTU = 20, /**< IPv4 socket path MTU */
};
/**

View file

@ -1190,6 +1190,12 @@ struct in_pktinfo {
struct in_addr ipi_addr; /**< Header Destination address */
};
/** Retrieve the current known path MTU of the current socket. Returns an
* integer. IP_MTU is valid only for getsockopt and can be employed only when
* the socket has been connected.
*/
#define IP_MTU 14
/** Set IPv4 multicast TTL value. */
#define IP_MULTICAST_TTL 33
/** Join IPv4 multicast group. */

View file

@ -1788,6 +1788,48 @@ static int get_context_timestamping(struct net_context *context,
#endif
}
static int get_context_mtu(struct net_context *context,
void *value, size_t *len)
{
sa_family_t family = net_context_get_family(context);
struct net_if *iface = NULL;
int mtu;
if (IS_ENABLED(CONFIG_NET_PMTU)) {
mtu = net_pmtu_get_mtu(&context->remote);
if (mtu > 0) {
goto out;
}
}
if (net_context_is_bound_to_iface(context)) {
iface = net_context_get_iface(context);
mtu = net_if_get_mtu(iface);
} else {
if (IS_ENABLED(CONFIG_NET_IPV6) && family == AF_INET6) {
iface = net_if_ipv6_select_src_iface(
&net_sin6(&context->remote)->sin6_addr);
} else if (IS_ENABLED(CONFIG_NET_IPV4) && family == AF_INET) {
iface = net_if_ipv4_select_src_iface(
&net_sin(&context->remote)->sin_addr);
} else {
return -EAFNOSUPPORT;
}
mtu = net_if_get_mtu(iface);
}
out:
*((int *)value) = mtu;
if (len) {
*len = sizeof(int);
}
return 0;
}
/* If buf is not NULL, then use it. Otherwise read the data to be written
* to net_pkt from msghdr.
*/
@ -3188,6 +3230,14 @@ int net_context_set_option(struct net_context *context,
break;
case NET_OPT_TIMESTAMPING:
ret = set_context_timestamping(context, value, len);
break;
case NET_OPT_MTU:
/* IPv4 only supports getting the MTU */
if (IS_ENABLED(CONFIG_NET_IPV4) &&
net_context_get_family(context) == AF_INET) {
ret = -EOPNOTSUPP;
}
break;
}
@ -3265,6 +3315,9 @@ int net_context_get_option(struct net_context *context,
case NET_OPT_TIMESTAMPING:
ret = get_context_timestamping(context, value, len);
break;
case NET_OPT_MTU:
ret = get_context_mtu(context, value, len);
break;
}
k_mutex_unlock(&context->lock);

View file

@ -1840,6 +1840,18 @@ int zsock_getsockopt_ctx(struct net_context *ctx, int level, int optname,
}
return 0;
case IP_MTU:
if (IS_ENABLED(CONFIG_NET_IPV4)) {
ret = net_context_get_option(ctx, NET_OPT_MTU,
optval, optlen);
if (ret < 0) {
errno = -ret;
return -1;
}
return 0;
}
}
break;