[PATCH mptcp-next 4/6] mptcp: extract IPv6 socket option handling for first subflow

Geliang Tang posted 6 patches 1 month ago
[PATCH mptcp-next 4/6] mptcp: extract IPv6 socket option handling for first subflow
Posted by Geliang Tang 1 month ago
From: Geliang Tang <tanggeliang@kylinos.cn>

Extract IPv6 socket option logic into dedicated helper function
mptcp_setsockopt_sol_ipv6_first_sf_only(). This helper handles:

1. Options requiring first-subflow-only application:
   - IPV6_V6ONLY
   - IPV6_TRANSPARENT
   - IPV6_FREEBIND

2. Synchronization flow:
   a) Lock MPTCP socket
   b) Retrieve first subflow
   c) Apply option to subflow
   d) Update MPTCP socket state
   e) Increment option sequence counter

The refactoring provides:
- Clear separation of IPv6-specific logic
- Consistent error handling
- Reusable pattern for future IPv6 options
- Improved code maintainability

Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
 net/mptcp/sockopt.c | 80 ++++++++++++++++++++++++++-------------------
 1 file changed, 47 insertions(+), 33 deletions(-)

diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c
index 1ab3dbe5124e..964131ef82d8 100644
--- a/net/mptcp/sockopt.c
+++ b/net/mptcp/sockopt.c
@@ -401,51 +401,62 @@ static int mptcp_setsockopt_sol_socket(struct mptcp_sock *msk, int optname,
 	return -EOPNOTSUPP;
 }
 
-static int mptcp_setsockopt_v6(struct mptcp_sock *msk, int optname,
-			       sockptr_t optval, unsigned int optlen)
+static int mptcp_setsockopt_sol_ipv6_first_sf_only(struct mptcp_sock *msk, int optname,
+						   sockptr_t optval, unsigned int optlen)
 {
 	struct sock *sk = (struct sock *)msk;
-	int ret = -EOPNOTSUPP;
 	struct sock *ssk;
+	int ret;
+
+	if (optname != IPV6_V6ONLY && optname != IPV6_TRANSPARENT &&
+	    optname != IPV6_FREEBIND)
+		return -EOPNOTSUPP;
+
+	lock_sock(sk);
+	ssk = __mptcp_nmpc_sk(msk);
+	if (IS_ERR(ssk)) {
+		release_sock(sk);
+		return PTR_ERR(ssk);
+	}
+
+	ret = tcp_setsockopt(ssk, SOL_IPV6, optname, optval, optlen);
+	if (ret != 0) {
+		release_sock(sk);
+		return ret;
+	}
+
+	sockopt_seq_inc(msk);
 
 	switch (optname) {
 	case IPV6_V6ONLY:
+		sk->sk_ipv6only = ssk->sk_ipv6only;
+		break;
 	case IPV6_TRANSPARENT:
+		inet_assign_bit(TRANSPARENT, sk,
+				inet_test_bit(TRANSPARENT, ssk));
+		break;
 	case IPV6_FREEBIND:
-		lock_sock(sk);
-		ssk = __mptcp_nmpc_sk(msk);
-		if (IS_ERR(ssk)) {
-			release_sock(sk);
-			return PTR_ERR(ssk);
-		}
-
-		ret = tcp_setsockopt(ssk, SOL_IPV6, optname, optval, optlen);
-		if (ret != 0) {
-			release_sock(sk);
-			return ret;
-		}
-
-		sockopt_seq_inc(msk);
+		inet_assign_bit(FREEBIND, sk,
+				inet_test_bit(FREEBIND, ssk));
+		break;
+	}
 
-		switch (optname) {
-		case IPV6_V6ONLY:
-			sk->sk_ipv6only = ssk->sk_ipv6only;
-			break;
-		case IPV6_TRANSPARENT:
-			inet_assign_bit(TRANSPARENT, sk,
-					inet_test_bit(TRANSPARENT, ssk));
-			break;
-		case IPV6_FREEBIND:
-			inet_assign_bit(FREEBIND, sk,
-					inet_test_bit(FREEBIND, ssk));
-			break;
-		}
+	release_sock(sk);
+	return 0;
+}
 
-		release_sock(sk);
-		break;
+static int mptcp_setsockopt_v6(struct mptcp_sock *msk, int optname,
+			       sockptr_t optval, unsigned int optlen)
+{
+	switch (optname) {
+	case IPV6_V6ONLY:
+	case IPV6_TRANSPARENT:
+	case IPV6_FREEBIND:
+		return mptcp_setsockopt_first_sf_only(msk, SOL_IPV6, optname,
+						      optval, optlen);
 	}
 
-	return ret;
+	return -EOPNOTSUPP;
 }
 
 static bool mptcp_supported_sockopt(int level, int optname)
@@ -829,6 +840,9 @@ static int mptcp_setsockopt_first_sf_only(struct mptcp_sock *msk, int level,
 	case SOL_IP:
 		return mptcp_setsockopt_sol_ip_first_sf_only(msk, optname,
 							     optval, optlen);
+	case SOL_IPV6:
+		return mptcp_setsockopt_sol_ipv6_first_sf_only(msk, optname,
+							       optval, optlen);
 	}
 
 	return -EOPNOTSUPP;
-- 
2.48.1