Skip to content

Commit eca745c

Browse files
Geliang Tangintel-lab-lkp
authored andcommitted
mptcp: add IPV6_UNICAST_HOPS sockopt support
Implement setsockopt/getsockopt support for IPV6_UNICAST_HOPS in MPTCP: 1. Adds mptcp_setsockopt_v6_set_hops() to handle IPV6_UNICAST_HOPS: - Applies hop limit to the MPTCP socket - Propagates hop limit to all IPv6 subflows - Uses conditional compilation for CONFIG_MPTCP_IPV6 2. Adds getsockopt handler for IPV6_UNICAST_HOPS: - Retrieves hop limit from inet6_sk(sk)->hop_limit - Falls back to net->ipv6.devconf_all->hop_limit when not set 3. Syncs hop limit to new subflows in sync_socket_options() 4. Maintains option sequence counter for consistency This enables applications to control IPv6 hop limits in MPTCP connections using standard IPv6 socket options, ensuring consistent behavior across all subflows. Closes: multipath-tcp/mptcp_net-next#296 Signed-off-by: Geliang Tang <[email protected]>
1 parent 64cfc1c commit eca745c

File tree

1 file changed

+37
-0
lines changed

1 file changed

+37
-0
lines changed

net/mptcp/sockopt.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,34 @@ static int mptcp_setsockopt_v6_set_tclass(struct mptcp_sock *msk, int optname,
413413
return 0;
414414
}
415415

416+
static int mptcp_setsockopt_v6_set_hops(struct mptcp_sock *msk, int optname,
417+
sockptr_t optval, unsigned int optlen)
418+
{
419+
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
420+
struct mptcp_subflow_context *subflow;
421+
struct sock *sk = (struct sock *)msk;
422+
int err, val;
423+
424+
err = ipv6_setsockopt(sk, SOL_IPV6, optname, optval, optlen);
425+
if (err)
426+
return err;
427+
428+
lock_sock(sk);
429+
sockopt_seq_inc(msk);
430+
val = READ_ONCE(inet6_sk(sk)->hop_limit);
431+
mptcp_for_each_subflow(msk, subflow) {
432+
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
433+
bool slow;
434+
435+
slow = lock_sock_fast(ssk);
436+
WRITE_ONCE(inet6_sk(ssk)->hop_limit, val);
437+
unlock_sock_fast(ssk, slow);
438+
}
439+
release_sock(sk);
440+
#endif
441+
442+
return 0;
443+
}
416444
static int mptcp_setsockopt_v6(struct mptcp_sock *msk, int optname,
417445
sockptr_t optval, unsigned int optlen)
418446
{
@@ -457,6 +485,8 @@ static int mptcp_setsockopt_v6(struct mptcp_sock *msk, int optname,
457485
break;
458486
case IPV6_TCLASS:
459487
return mptcp_setsockopt_v6_set_tclass(msk, optname, optval, optlen);
488+
case IPV6_UNICAST_HOPS:
489+
return mptcp_setsockopt_v6_set_hops(msk, optname, optval, optlen);
460490
}
461491

462492
return ret;
@@ -1530,6 +1560,7 @@ static int mptcp_getsockopt_v6(struct mptcp_sock *msk, int optname,
15301560
char __user *optval, int __user *optlen)
15311561
{
15321562
struct sock *sk = (void *)msk;
1563+
int val;
15331564

15341565
switch (optname) {
15351566
case IPV6_V6ONLY:
@@ -1544,6 +1575,11 @@ static int mptcp_getsockopt_v6(struct mptcp_sock *msk, int optname,
15441575
case IPV6_TCLASS:
15451576
return mptcp_put_int_option(msk, optval, optlen,
15461577
inet6_sk(sk)->tclass);
1578+
case IPV6_UNICAST_HOPS:
1579+
val = READ_ONCE(inet6_sk(sk)->hop_limit);
1580+
if (val < 0)
1581+
val = READ_ONCE(sock_net(sk)->ipv6.devconf_all->hop_limit);
1582+
return mptcp_put_int_option(msk, optval, optlen, val);
15471583
}
15481584

15491585
return -EOPNOTSUPP;
@@ -1616,6 +1652,7 @@ static void sync_socket_options(struct mptcp_sock *msk, struct sock *ssk)
16161652
__ip_sock_set_tos(ssk, inet_sk(sk)->tos);
16171653
WRITE_ONCE(inet6_sk(ssk)->tclass, inet6_sk(sk)->tclass);
16181654
WRITE_ONCE(inet_sk(ssk)->uc_ttl, inet_sk(sk)->uc_ttl);
1655+
WRITE_ONCE(inet6_sk(ssk)->hop_limit, inet6_sk(sk)->hop_limit);
16191656

16201657
if (sk->sk_userlocks & tx_rx_locks) {
16211658
ssk->sk_userlocks |= sk->sk_userlocks & tx_rx_locks;

0 commit comments

Comments
 (0)