5050 * usage. The greater the value, the more accurate the end result. */
5151#define MAX_CONNECTIONS 1000
5252
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-
7653ssize_t get_vm_data_size ()
7754{
78- #ifdef __linux__
7955 long page_size = 0 ;
8056 ssize_t size = 0 , resident = 0 , share = 0 , text = 0 , lib = 0 , data = 0 , dt = 0 ;
8157
@@ -92,57 +68,6 @@ ssize_t get_vm_data_size()
9268 fclose (status_file );
9369
9470 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
14671}
14772
14873int main (int argc , char * * argv )
@@ -158,11 +83,16 @@ int main(int argc, char **argv)
15883 DEFER_CLEANUP (struct s2n_test_io_pair io_pair = { 0 }, s2n_io_pair_close );
15984 EXPECT_SUCCESS (s2n_io_pair_init_non_blocking (& io_pair ));
16085
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 ) {
16492 END_TEST ();
16593 }
94+ const int expected_kbs_per_conn = atoi (env_var );
95+ EXPECT_TRUE (expected_kbs_per_conn > 1 );
16696
16797 struct rlimit file_limit ;
16898 EXPECT_SUCCESS (getrlimit (RLIMIT_NOFILE , & file_limit ));
@@ -172,9 +102,6 @@ int main(int argc, char **argv)
172102 connectionsToUse = MAX (1 , (file_limit .rlim_cur - 16 ) / 4 );
173103 }
174104
175- const ssize_t maxAllowedMemDiff = MAX_MEM_ALLOWED (connectionsToUse );
176- const ssize_t minAllowedMemDiff = maxAllowedMemDiff * 0.75 ;
177-
178105 struct s2n_connection * * clients = calloc (connectionsToUse , sizeof (struct s2n_connection * ));
179106 struct s2n_connection * * servers = calloc (connectionsToUse , sizeof (struct s2n_connection * ));
180107
@@ -253,34 +180,31 @@ int main(int argc, char **argv)
253180 free (clients );
254181 free (servers );
255182
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-
265183 EXPECT_TRUE (vm_data_after_free_handshake <= vm_data_after_handshakes );
266184 EXPECT_TRUE (vm_data_after_release_buffers <= vm_data_after_free_handshake );
267185
268186 ssize_t handshake_diff = (vm_data_after_handshakes - vm_data_initial );
269187 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 );
281206 FAIL_MSG ("Unexpected memory usage. If expected, update MEM_PER_CONNECTION." );
282207 }
283- #endif
284208
285209 END_TEST ();
286210}
0 commit comments