@@ -45,6 +45,90 @@ static u32 sockopt_seq_reset(const struct sock *sk)
45
45
return (u32 )sk -> sk_state << 24u ;
46
46
}
47
47
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
+
48
132
static int mptcp_setsockopt_sol_socket (struct mptcp_sock * msk , int optname ,
49
133
sockptr_t optval , unsigned int optlen )
50
134
{
@@ -71,6 +155,9 @@ static int mptcp_setsockopt_sol_socket(struct mptcp_sock *msk, int optname,
71
155
}
72
156
release_sock (sk );
73
157
return ret ;
158
+ case SO_KEEPALIVE :
159
+ case SO_PRIORITY :
160
+ return mptcp_setsockopt_sol_socket_int (msk , optname , optval , optlen );
74
161
}
75
162
76
163
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,
371
458
return - EOPNOTSUPP ;
372
459
}
373
460
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
+
374
475
static void __mptcp_sockopt_sync (struct mptcp_sock * msk , struct sock * ssk )
375
476
{
477
+ bool slow = lock_sock_fast (ssk );
478
+
479
+ sync_socket_options (msk , ssk );
480
+
481
+ unlock_sock_fast (ssk , slow );
376
482
}
377
483
378
484
void mptcp_sockopt_sync (struct mptcp_sock * msk , struct sock * ssk )
0 commit comments