Line data Source code
1 : #include "configure.h"
2 :
3 0 : #define NAME "sysctl"
4 :
5 : #include "../../../platform/fd_file_util.h"
6 :
7 : #include <errno.h>
8 : #include <stdio.h>
9 : #include <linux/capability.h>
10 :
11 : static void
12 : init_perm( fd_cap_chk_t * chk,
13 0 : config_t const * config FD_PARAM_UNUSED ) {
14 0 : fd_cap_chk_cap( chk, NAME, CAP_SYS_ADMIN, "set kernel parameters in `/proc/sys`" );
15 0 : }
16 :
17 0 : #define ENFORCE_MINIMUM 0
18 0 : #define WARN_MINIMUM 1
19 0 : #define WARN_EXACT 2
20 :
21 : typedef struct {
22 : char const * path;
23 : ulong value;
24 : int mode;
25 : int allow_missing;
26 : } sysctl_param_t;
27 :
28 : static const sysctl_param_t params[] = {
29 : {
30 : "/proc/sys/vm/max_map_count", /* int */
31 : 1000000,
32 : ENFORCE_MINIMUM,
33 : 0,
34 : },
35 : {
36 : "/proc/sys/fs/file-max", /* ulong */
37 : CONFIGURE_NR_OPEN_FILES,
38 : ENFORCE_MINIMUM,
39 : 0,
40 : },
41 : {
42 : "/proc/sys/fs/nr_open", /* uint */
43 : CONFIGURE_NR_OPEN_FILES,
44 : ENFORCE_MINIMUM,
45 : 0,
46 : },
47 : {
48 : "/proc/sys/kernel/numa_balancing", /* int? */
49 : 0,
50 : WARN_EXACT,
51 : 1,
52 : },
53 : {0}
54 : };
55 :
56 : static const sysctl_param_t xdp_params[] = {
57 : {
58 : "/proc/sys/net/ipv4/conf/lo/rp_filter",
59 : 2,
60 : ENFORCE_MINIMUM,
61 : 0,
62 : },
63 : {
64 : "/proc/sys/net/ipv4/conf/lo/accept_local",
65 : 1,
66 : ENFORCE_MINIMUM,
67 : 0,
68 : },
69 : {
70 : "/proc/sys/net/core/bpf_jit_enable",
71 : 1,
72 : WARN_MINIMUM,
73 : 0,
74 : },
75 : {
76 : "/proc/sys/net/ipv4/conf/lo/route_localnet",
77 : 1,
78 : ENFORCE_MINIMUM,
79 : 1,
80 : },
81 : {0}
82 : };
83 :
84 : static sysctl_param_t sock_params[] = {
85 : {
86 : "/proc/sys/net/core/rmem_max",
87 : 0,
88 : ENFORCE_MINIMUM,
89 : 0,
90 : },
91 : {
92 : "/proc/sys/net/core/wmem_max",
93 : 0,
94 : ENFORCE_MINIMUM,
95 : 0,
96 : },
97 : {0}
98 : };
99 :
100 : /* Some of these sysctl limits are needed for the Agave client, not
101 : Firedancer. We set them on their behalf to make configuration easier
102 : for users. */
103 :
104 : static void
105 0 : init_param_list( sysctl_param_t const * list ) {
106 0 : for( sysctl_param_t const * p=list; p->path; p++ ) {
107 0 : ulong param;
108 0 : if( FD_UNLIKELY( -1==fd_file_util_read_ulong( p->path, ¶m ) ) ) {
109 : /* If the syctl file does not exist in /proc/sys, it's likely it
110 : doesn't exist anywhere else */
111 0 : if( FD_UNLIKELY( p->allow_missing && errno==ENOENT ) ) continue;
112 :
113 0 : FD_LOG_ERR(( "could not read kernel parameter `%s`, system might not support configuring sysctl (%i-%s)", p->path, errno, fd_io_strerror( errno ) ));
114 0 : }
115 0 : switch( p->mode ) {
116 0 : case ENFORCE_MINIMUM:
117 0 : if( FD_UNLIKELY( param<(p->value) ) ) {
118 0 : FD_LOG_NOTICE(( "RUN: `echo \"%lu\" > %s`", p->value, p->path ) );
119 0 : if( FD_UNLIKELY( -1==fd_file_util_write_ulong( p->path, p->value ) ) )
120 0 : FD_LOG_ERR(( "could not set kernel parameter `%s` to %lu (%i-%s)", p->path, p->value, errno, fd_io_strerror( errno ) ));
121 0 : }
122 0 : break;
123 0 : default:
124 0 : break;
125 0 : }
126 0 : }
127 0 : }
128 :
129 : static void
130 0 : init( config_t const * config ) {
131 0 : init_param_list( params );
132 0 : if( 0==strcmp( config->net.provider, "xdp" ) ) {
133 0 : init_param_list( xdp_params );
134 0 : } else if( 0==strcmp( config->net.provider, "socket" ) ) {
135 0 : sock_params[ 0 ].value = config->net.socket.receive_buffer_size;
136 0 : sock_params[ 1 ].value = config->net.socket.send_buffer_size;
137 0 : init_param_list( sock_params );
138 0 : }
139 0 : }
140 :
141 : static configure_result_t
142 0 : check_param_list( sysctl_param_t const * list ) {
143 0 : static int has_warned = 0;
144 :
145 0 : for( sysctl_param_t const * p=list; p->path; p++ ) {
146 0 : ulong param;
147 0 : if( FD_UNLIKELY( -1==fd_file_util_read_ulong( p->path, ¶m ) ) ) {
148 0 : if( FD_UNLIKELY( p->allow_missing && errno==ENOENT ) ) continue;
149 0 : FD_LOG_ERR(( "could not read kernel parameter `%s`, system might not support configuring sysctl (%i-%s)", p->path, errno, fd_io_strerror( errno ) ));
150 0 : }
151 0 : switch( p->mode ) {
152 0 : case ENFORCE_MINIMUM:
153 0 : if( FD_UNLIKELY( param<(p->value) ) )
154 0 : NOT_CONFIGURED( "kernel parameter `%s` is too low (got %lu but expected at least %lu)", p->path, param, p->value );
155 0 : break;
156 0 : case WARN_MINIMUM:
157 0 : if( FD_UNLIKELY( !has_warned && param<(p->value) ) )
158 0 : FD_LOG_WARNING(( "kernel parameter `%s` is too low (got %lu but expected at least %lu). Proceeding but performance may be reduced.", p->path, param, p->value ));
159 0 : break;
160 0 : case WARN_EXACT:
161 0 : if( FD_UNLIKELY( !has_warned && param!=(p->value) ) )
162 0 : FD_LOG_WARNING(( "kernel parameter `%s` is set to %lu, not the expected value of %lu. Proceeding but performance may be reduced.", p->path, param, p->value ));
163 0 : break;
164 0 : }
165 0 : }
166 :
167 0 : has_warned = 1;
168 :
169 0 : CONFIGURE_OK();
170 0 : }
171 :
172 : static configure_result_t
173 0 : check( config_t const * config ) {
174 0 : configure_result_t r;
175 :
176 0 : r = check_param_list( params );
177 0 : if( r.result!=CONFIGURE_OK ) return r;
178 :
179 0 : if( 0==strcmp( config->net.provider, "xdp" ) ) {
180 0 : r = check_param_list( xdp_params );
181 0 : } else if( 0==strcmp( config->net.provider, "socket" ) ) {
182 0 : sock_params[ 0 ].value = config->net.socket.receive_buffer_size;
183 0 : sock_params[ 1 ].value = config->net.socket.send_buffer_size;
184 0 : r = check_param_list( sock_params );
185 0 : } else {
186 0 : FD_LOG_ERR(( "unknown net provider: %s", config->net.provider ));
187 0 : }
188 0 : if( r.result!=CONFIGURE_OK ) return r;
189 :
190 0 : CONFIGURE_OK();
191 0 : }
192 :
193 : configure_stage_t fd_cfg_stage_sysctl = {
194 : .name = NAME,
195 : .always_recreate = 0,
196 : .enabled = NULL,
197 : .init_perm = init_perm,
198 : .fini_perm = NULL,
199 : .init = init,
200 : .fini = NULL,
201 : .check = check,
202 : };
203 :
204 : #undef NAME
|