50
50
* usage. The greater the value, the more accurate the end result. */
51
51
#define MAX_CONNECTIONS 1000
52
52
53
- /* This is roughly the current memory usage per connection, in KB */
54
- #ifdef __FreeBSD__
55
- #define MEM_PER_CONNECTION 57
56
- #elif defined(__OpenBSD__ )
57
- #define MEM_PER_CONNECTION 61
58
- #else
59
- #define MEM_PER_CONNECTION 51
60
- #endif
61
-
62
- /* This is the maximum memory per connection including 4KB of slack */
63
- #define TEST_SLACK 4
64
- #define MAX_MEM_PER_CONNECTION \
65
- ((MEM_PER_CONNECTION + TEST_SLACK) * 1024)
66
-
67
- /* This is the total maximum memory allowed */
68
- #define MAX_MEM_ALLOWED (num_connections ) \
69
- (2 * (num_connections) *MAX_MEM_PER_CONNECTION)
70
-
71
- /* This is the correct value of MEM_PER_CONNECTION based on test results.
72
- * Basically, this calculation should reverse MAX_MEM_ALLOWED */
73
- #define ACTUAL_MEM_PER_CONNECTION (num_connections , max_mem ) \
74
- ((((max_mem) / 2 / (num_connections)) / 1024) - TEST_SLACK)
75
-
76
53
ssize_t get_vm_data_size ()
77
54
{
78
- #ifdef __linux__
79
55
long page_size = 0 ;
80
56
ssize_t size = 0 , resident = 0 , share = 0 , text = 0 , lib = 0 , data = 0 , dt = 0 ;
81
57
@@ -92,57 +68,6 @@ ssize_t get_vm_data_size()
92
68
fclose (status_file );
93
69
94
70
return data * page_size ;
95
-
96
- #elif defined(__FreeBSD__ )
97
- pid_t ppid = getpid ();
98
- int pidinfo [4 ];
99
- pidinfo [0 ] = CTL_KERN ;
100
- pidinfo [1 ] = KERN_PROC ;
101
- pidinfo [2 ] = KERN_PROC_PID ;
102
- pidinfo [3 ] = (int ) ppid ;
103
-
104
- struct kinfo_proc procinfo = { 0 };
105
-
106
- size_t len = sizeof (procinfo );
107
-
108
- sysctl (pidinfo , nitems (pidinfo ), & procinfo , & len , NULL , 0 );
109
-
110
- /* Taken from linprocfs implementation
111
- * https://github.com/freebsd/freebsd-src/blob/779fd05344662aeec79c29470258bf657318eab3/sys/compat/linprocfs/linprocfs.c#L1019 */
112
- segsz_t lsize = (procinfo .ki_size >> PAGE_SHIFT ) - procinfo .ki_dsize - procinfo .ki_ssize - procinfo .ki_tsize - 1 ;
113
-
114
- return lsize << PAGE_SHIFT ;
115
-
116
- #elif defined(__OpenBSD__ )
117
- struct kinfo_proc * procinfo ;
118
- kvm_t * kd ;
119
- pid_t ppid ;
120
- long page_size ;
121
- ssize_t size ;
122
- int nentries ;
123
-
124
- kd = kvm_open (NULL , NULL , NULL , KVM_NO_FILES , NULL );
125
- ppid = getpid ();
126
- procinfo = kvm_getprocs (kd , KERN_PROC_PID , ppid , sizeof (* procinfo ), & nentries );
127
- if (procinfo == NULL || nentries == 0 ) {
128
- return -1 ;
129
- }
130
-
131
- /* Taken from ps(1)'s calculation of vsize
132
- * https://github.com/openbsd/src/blob/329e3480337617df4d195c9a400c3f186254b137/bin/ps/print.c#L603 */
133
- size = procinfo -> p_vm_dsize + procinfo -> p_vm_ssize + procinfo -> p_vm_tsize ;
134
-
135
- page_size = sysconf (_SC_PAGESIZE );
136
- if (page_size < 0 ) {
137
- return -1 ;
138
- }
139
- kvm_close (kd );
140
-
141
- return (size * page_size );
142
- #else
143
- /* Not implemented for other platforms */
144
- return 0 ;
145
- #endif
146
71
}
147
72
148
73
int main (int argc , char * * argv )
@@ -158,11 +83,16 @@ int main(int argc, char **argv)
158
83
DEFER_CLEANUP (struct s2n_test_io_pair io_pair = { 0 }, s2n_io_pair_close );
159
84
EXPECT_SUCCESS (s2n_io_pair_init_non_blocking (& io_pair ));
160
85
161
- /* Skip the test when running under valgrind or address sanitizer, as those tools
162
- * impact the memory usage. */
163
- if (getenv ("S2N_VALGRIND" ) != NULL || getenv ("S2N_ADDRESS_SANITIZER" ) != NULL ) {
86
+ /* Skip the test unless specifically enabled.
87
+ * This test is too unreliable to run in all customer environments.
88
+ * We should choose specific, known builds to run this test in.
89
+ */
90
+ const char * env_var = getenv ("S2N_EXPECTED_CONNECTION_MEMORY_KB" );
91
+ if (env_var == NULL ) {
164
92
END_TEST ();
165
93
}
94
+ const int expected_kbs_per_conn = atoi (env_var );
95
+ EXPECT_TRUE (expected_kbs_per_conn > 1 );
166
96
167
97
struct rlimit file_limit ;
168
98
EXPECT_SUCCESS (getrlimit (RLIMIT_NOFILE , & file_limit ));
@@ -172,9 +102,6 @@ int main(int argc, char **argv)
172
102
connectionsToUse = MAX (1 , (file_limit .rlim_cur - 16 ) / 4 );
173
103
}
174
104
175
- const ssize_t maxAllowedMemDiff = MAX_MEM_ALLOWED (connectionsToUse );
176
- const ssize_t minAllowedMemDiff = maxAllowedMemDiff * 0.75 ;
177
-
178
105
struct s2n_connection * * clients = calloc (connectionsToUse , sizeof (struct s2n_connection * ));
179
106
struct s2n_connection * * servers = calloc (connectionsToUse , sizeof (struct s2n_connection * ));
180
107
@@ -253,34 +180,31 @@ int main(int argc, char **argv)
253
180
free (clients );
254
181
free (servers );
255
182
256
- TEST_DEBUG_PRINT ("\n" );
257
- TEST_DEBUG_PRINT ("VmData initial: %10zd\n" , vm_data_initial );
258
- TEST_DEBUG_PRINT ("VmData after allocations: %10zd\n" , vm_data_after_allocation );
259
- TEST_DEBUG_PRINT ("VmData after handshakes: %10zd\n" , vm_data_after_handshakes );
260
- TEST_DEBUG_PRINT ("VmData after free handshake: %10zd\n" , vm_data_after_free_handshake );
261
- TEST_DEBUG_PRINT ("VmData after release: %10zd\n" , vm_data_after_release_buffers );
262
- TEST_DEBUG_PRINT ("Max VmData diff allowed: %10zd\n" , maxAllowedMemDiff );
263
- TEST_DEBUG_PRINT ("Number of connections used: %10zu\n" , connectionsToUse );
264
-
265
183
EXPECT_TRUE (vm_data_after_free_handshake <= vm_data_after_handshakes );
266
184
EXPECT_TRUE (vm_data_after_release_buffers <= vm_data_after_free_handshake );
267
185
268
186
ssize_t handshake_diff = (vm_data_after_handshakes - vm_data_initial );
269
187
ssize_t allocation_diff = (vm_data_after_allocation - vm_data_initial );
270
-
271
- /*
272
- * get_vm_data_size is required for this test to succeed.
273
- * Any platform that doesn't implement get_vm_data_size should be excluded here.
274
- */
275
- #ifndef __APPLE__
276
- if (allocation_diff > maxAllowedMemDiff
277
- || handshake_diff > maxAllowedMemDiff
278
- || handshake_diff < minAllowedMemDiff ) {
279
- fprintf (stdout , "\nActual KB per connection: %i\n" ,
280
- (int ) ACTUAL_MEM_PER_CONNECTION (connectionsToUse , handshake_diff ));
188
+ EXPECT_TRUE (allocation_diff <= handshake_diff );
189
+
190
+ ssize_t mem_per_conn = handshake_diff / (connectionsToUse * 2 );
191
+ ssize_t kbs_per_conn = mem_per_conn / 1024 ;
192
+
193
+ if (kbs_per_conn != expected_kbs_per_conn ) {
194
+ printf ("\nExpected KB per connection: %i\n" , expected_kbs_per_conn );
195
+ printf ("\nActual KB per connection: %li\n" , kbs_per_conn );
196
+ printf ("This is a %.2f%% change\n" ,
197
+ (kbs_per_conn - expected_kbs_per_conn ) * 100.0 / expected_kbs_per_conn );
198
+
199
+ printf ("\n" );
200
+ printf ("VmData initial: %10zd\n" , vm_data_initial );
201
+ printf ("VmData after allocations: %10zd\n" , vm_data_after_allocation );
202
+ printf ("VmData after handshakes: %10zd\n" , vm_data_after_handshakes );
203
+ printf ("VmData after free handshake: %10zd\n" , vm_data_after_free_handshake );
204
+ printf ("VmData after release: %10zd\n" , vm_data_after_release_buffers );
205
+ printf ("Number of connections used: %10zu\n" , connectionsToUse );
281
206
FAIL_MSG ("Unexpected memory usage. If expected, update MEM_PER_CONNECTION." );
282
207
}
283
- #endif
284
208
285
209
END_TEST ();
286
210
}
0 commit comments