@@ -45,6 +45,90 @@ static u32 sockopt_seq_reset(const struct sock *sk)
4545 return (u32 )sk -> sk_state << 24u ;
4646}
4747
48+ static void sockopt_seq_inc (struct mptcp_sock * msk )
49+ {
50+ u32 seq = (msk -> setsockopt_seq + 1 ) & 0x00ffffff ;
51+
52+ msk -> setsockopt_seq = sockopt_seq_reset ((struct sock * )msk ) + seq ;
53+ }
54+
55+ static int mptcp_get_int_option (struct mptcp_sock * msk , sockptr_t optval ,
56+ unsigned int optlen , int * val )
57+ {
58+ if (optlen < sizeof (int ))
59+ return - EINVAL ;
60+
61+ if (copy_from_sockptr (val , optval , sizeof (* val )))
62+ return - EFAULT ;
63+
64+ return 0 ;
65+ }
66+
67+ static void mptcp_sol_socket_sync_intval (struct mptcp_sock * msk , int optname , int val )
68+ {
69+ struct mptcp_subflow_context * subflow ;
70+ struct sock * sk = (struct sock * )msk ;
71+
72+ lock_sock (sk );
73+ sockopt_seq_inc (msk );
74+
75+ mptcp_for_each_subflow (msk , subflow ) {
76+ struct sock * ssk = mptcp_subflow_tcp_sock (subflow );
77+ bool slow = lock_sock_fast (ssk );
78+
79+ switch (optname ) {
80+ case SO_KEEPALIVE :
81+ if (ssk -> sk_prot -> keepalive )
82+ ssk -> sk_prot -> keepalive (ssk , !!val );
83+ sock_valbool_flag (ssk , SOCK_KEEPOPEN , !!val );
84+ break ;
85+ case SO_PRIORITY :
86+ ssk -> sk_priority = val ;
87+ break ;
88+ }
89+
90+ subflow -> setsockopt_seq = msk -> setsockopt_seq ;
91+ unlock_sock_fast (ssk , slow );
92+ }
93+
94+ release_sock (sk );
95+ }
96+
97+ static int mptcp_sol_socket_intval (struct mptcp_sock * msk , int optname , int val )
98+ {
99+ sockptr_t optval = KERNEL_SOCKPTR (& val );
100+ struct sock * sk = (struct sock * )msk ;
101+ int ret ;
102+
103+ ret = sock_setsockopt (sk -> sk_socket , SOL_SOCKET , optname ,
104+ optval , sizeof (val ));
105+ if (ret )
106+ return ret ;
107+
108+ mptcp_sol_socket_sync_intval (msk , optname , val );
109+ return 0 ;
110+ }
111+
112+ static int mptcp_setsockopt_sol_socket_int (struct mptcp_sock * msk , int optname ,
113+ sockptr_t optval , unsigned int optlen )
114+ {
115+ int val , ret ;
116+
117+ ret = mptcp_get_int_option (msk , optval , optlen , & val );
118+ if (ret )
119+ return ret ;
120+
121+ switch (optname ) {
122+ case SO_KEEPALIVE :
123+ mptcp_sol_socket_sync_intval (msk , optname , val );
124+ return 0 ;
125+ case SO_PRIORITY :
126+ return mptcp_sol_socket_intval (msk , optname , val );
127+ }
128+
129+ return - ENOPROTOOPT ;
130+ }
131+
48132static int mptcp_setsockopt_sol_socket (struct mptcp_sock * msk , int optname ,
49133 sockptr_t optval , unsigned int optlen )
50134{
@@ -71,6 +155,9 @@ static int mptcp_setsockopt_sol_socket(struct mptcp_sock *msk, int optname,
71155 }
72156 release_sock (sk );
73157 return ret ;
158+ case SO_KEEPALIVE :
159+ case SO_PRIORITY :
160+ return mptcp_setsockopt_sol_socket_int (msk , optname , optval , optlen );
74161 }
75162
76163 return sock_setsockopt (sk -> sk_socket , SOL_SOCKET , optname , optval , optlen );
@@ -371,8 +458,27 @@ int mptcp_getsockopt(struct sock *sk, int level, int optname,
371458 return - EOPNOTSUPP ;
372459}
373460
461+ static void sync_socket_options (struct mptcp_sock * msk , struct sock * ssk )
462+ {
463+ struct sock * sk = (struct sock * )msk ;
464+
465+ if (ssk -> sk_prot -> keepalive ) {
466+ if (sock_flag (sk , SOCK_KEEPOPEN ))
467+ ssk -> sk_prot -> keepalive (ssk , 1 );
468+ else
469+ ssk -> sk_prot -> keepalive (ssk , 0 );
470+ }
471+
472+ ssk -> sk_priority = sk -> sk_priority ;
473+ }
474+
374475static void __mptcp_sockopt_sync (struct mptcp_sock * msk , struct sock * ssk )
375476{
477+ bool slow = lock_sock_fast (ssk );
478+
479+ sync_socket_options (msk , ssk );
480+
481+ unlock_sock_fast (ssk , slow );
376482}
377483
378484void mptcp_sockopt_sync (struct mptcp_sock * msk , struct sock * ssk )
0 commit comments