From: Geliang Tang <tanggeliang@kylinos.cn>
Implement setsockopt/getsockopt for IP_TTL in MPTCP:
1. setsockopt(IP_TTL):
- Applies TTL to MPTCP socket
- Propagates TTL to all subflows
2. getsockopt(IP_TTL):
- Returns current TTL from inet_sk(sk)->uc_ttl
- Falls back to sysctl_ip_default_ttl when unset
3. Syncs TTL to new subflows
4. Maintains option sequence counters
Enables applications to control IPv4 TTL settings consistently across
all subflows. Resolves outstanding requests for TTL support in MPTCP.
Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/296
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
net/mptcp/sockopt.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c
index bb296813c578..ae9b376071c9 100644
--- a/net/mptcp/sockopt.c
+++ b/net/mptcp/sockopt.c
@@ -776,7 +776,7 @@ static int mptcp_setsockopt_sol_ip_all_sf(struct mptcp_sock *msk, int level,
struct sock *sk = (struct sock *)msk;
int err, val;
- if (optname != IP_TOS &&
+ if (optname != IP_TOS && optname != IP_TTL &&
optname != IPV6_TCLASS)
return -EOPNOTSUPP;
@@ -794,6 +794,8 @@ static int mptcp_setsockopt_sol_ip_all_sf(struct mptcp_sock *msk, int level,
sockopt_seq_inc(msk);
if (optname == IP_TOS)
val = READ_ONCE(inet_sk(sk)->tos);
+ else if (optname == IP_TTL)
+ val = READ_ONCE(inet_sk(sk)->uc_ttl);
else if (optname == IPV6_TCLASS)
val = READ_ONCE(inet6_sk(sk)->tclass);
mptcp_for_each_subflow(msk, subflow) {
@@ -803,6 +805,8 @@ static int mptcp_setsockopt_sol_ip_all_sf(struct mptcp_sock *msk, int level,
slow = lock_sock_fast(ssk);
if (optname == IP_TOS)
__ip_sock_set_tos(ssk, val);
+ else if (optname == IP_TTL)
+ WRITE_ONCE(inet_sk(ssk)->uc_ttl, val);
else if (optname == IPV6_TCLASS)
WRITE_ONCE(inet6_sk(ssk)->tclass, val);
unlock_sock_fast(ssk, slow);
@@ -822,6 +826,7 @@ static int mptcp_setsockopt_v4(struct mptcp_sock *msk, int optname,
case IP_LOCAL_PORT_RANGE:
return mptcp_setsockopt_first_sf_only(msk, SOL_IP, optname, optval, optlen);
case IP_TOS:
+ case IP_TTL:
return mptcp_setsockopt_all_sf(msk, SOL_IP, optname, optval, optlen);
}
@@ -1547,6 +1552,7 @@ static int mptcp_getsockopt_v4(struct mptcp_sock *msk, int optname,
char __user *optval, int __user *optlen)
{
struct sock *sk = (void *)msk;
+ int val;
switch (optname) {
case IP_TOS:
@@ -1563,6 +1569,11 @@ static int mptcp_getsockopt_v4(struct mptcp_sock *msk, int optname,
case IP_LOCAL_PORT_RANGE:
return mptcp_put_int_option(msk, optval, optlen,
READ_ONCE(inet_sk(sk)->local_port_range));
+ case IP_TTL:
+ val = READ_ONCE(inet_sk(sk)->uc_ttl);
+ if (val < 0)
+ val = READ_ONCE(sock_net(sk)->ipv4.sysctl_ip_default_ttl);
+ return mptcp_put_int_option(msk, optval, optlen, val);
}
return -EOPNOTSUPP;
@@ -1694,6 +1705,7 @@ static void sync_socket_options(struct mptcp_sock *msk, struct sock *ssk)
inet_assign_bit(FREEBIND, ssk, inet_test_bit(FREEBIND, sk));
inet_assign_bit(BIND_ADDRESS_NO_PORT, ssk, inet_test_bit(BIND_ADDRESS_NO_PORT, sk));
WRITE_ONCE(inet_sk(ssk)->local_port_range, READ_ONCE(inet_sk(sk)->local_port_range));
+ WRITE_ONCE(inet_sk(ssk)->uc_ttl, READ_ONCE(inet_sk(sk)->uc_ttl));
if (ssk->sk_family == AF_INET6)
WRITE_ONCE(inet6_sk(ssk)->tclass, READ_ONCE(inet6_sk(sk)->tclass));
}
--
2.48.1
© 2016 - 2025 Red Hat, Inc.