|  | 
| 46 | 46 | 
 | 
| 47 | 47 | static void accept_connection(h2o_socket_t *listener, const char *err); | 
| 48 | 48 | static void accept_http_connection(h2o_socket_t *listener, const char *err); | 
| 49 |  | -static int get_listener_socket(const char *bind_address, uint16_t port); | 
|  | 49 | +static int get_listener_socket(bool is_main_thread, | 
|  | 50 | +                               int bpf_fd, | 
|  | 51 | +                               const char *bind_address, | 
|  | 52 | +                               uint16_t port); | 
| 50 | 53 | static void on_close_connection(void *data); | 
| 51 | 54 | static void process_messages(h2o_multithread_receiver_t *receiver, h2o_linklist_t *messages); | 
| 52 | 55 | static void shutdown_server(h2o_socket_t *listener, const char *err); | 
| 53 |  | -static void start_accept_polling(const config_t *config, | 
|  | 56 | +static void start_accept_polling(bool is_main_thread, | 
|  | 57 | +                                 int bpf_fd, | 
|  | 58 | +                                 const config_t *config, | 
| 54 | 59 |                                  h2o_socket_cb accept_cb, | 
| 55 | 60 |                                  bool is_https, | 
| 56 | 61 |                                  event_loop_t *loop); | 
| @@ -98,7 +103,10 @@ static void accept_http_connection(h2o_socket_t *listener, const char *err) | 
| 98 | 103 | 	ctx->event_loop.h2o_accept_ctx.ssl_ctx = ssl_ctx; | 
| 99 | 104 | } | 
| 100 | 105 | 
 | 
| 101 |  | -static int get_listener_socket(const char *bind_address, uint16_t port) | 
|  | 106 | +static int get_listener_socket(bool is_main_thread, | 
|  | 107 | +                               int bpf_fd, | 
|  | 108 | +                               const char *bind_address, | 
|  | 109 | +                               uint16_t port) | 
| 102 | 110 | { | 
| 103 | 111 | 	int ret = -1; | 
| 104 | 112 | 	char buf[16]; | 
| @@ -148,6 +156,15 @@ static int get_listener_socket(const char *bind_address, uint16_t port) | 
| 148 | 156 | 		LOCAL_CHECK_ERRNO(setsockopt, s, IPPROTO_TCP, TCP_FASTOPEN, &option, sizeof(option)); | 
| 149 | 157 | 		LOCAL_CHECK_ERRNO(bind, s, iter->ai_addr, iter->ai_addrlen); | 
| 150 | 158 | 		LOCAL_CHECK_ERRNO(listen, s, INT_MAX); | 
|  | 159 | + | 
|  | 160 | +		if (is_main_thread && bpf_fd >= 0) | 
|  | 161 | +			LOCAL_CHECK_ERRNO(setsockopt, | 
|  | 162 | +			                  s, | 
|  | 163 | +			                  SOL_SOCKET, | 
|  | 164 | +			                  SO_ATTACH_REUSEPORT_EBPF, | 
|  | 165 | +			                  &bpf_fd, | 
|  | 166 | +			                  sizeof(bpf_fd)); | 
|  | 167 | + | 
| 151 | 168 | 		ret = s; | 
| 152 | 169 | 		break; | 
| 153 | 170 | 
 | 
| @@ -256,16 +273,17 @@ static void shutdown_server(h2o_socket_t *listener, const char *err) | 
| 256 | 273 | 	} | 
| 257 | 274 | } | 
| 258 | 275 | 
 | 
| 259 |  | -static void start_accept_polling(const config_t *config, | 
|  | 276 | +static void start_accept_polling(bool is_main_thread, | 
|  | 277 | +                                 int bpf_fd, | 
|  | 278 | +                                 const config_t *config, | 
| 260 | 279 |                                  h2o_socket_cb accept_cb, | 
| 261 | 280 |                                  bool is_https, | 
| 262 | 281 |                                  event_loop_t *loop) | 
| 263 | 282 | { | 
| 264 |  | -	const int listener_sd = get_listener_socket(config->bind_address, | 
|  | 283 | +	const int listener_sd = get_listener_socket(is_main_thread, | 
|  | 284 | +	                                            bpf_fd, | 
|  | 285 | +	                                            config->bind_address, | 
| 265 | 286 | 	                                            is_https ? config->https_port : config->port); | 
| 266 |  | -	// Let all the threads race to call accept() on the socket; since the latter is | 
| 267 |  | -	// non-blocking, that will virtually act as load balancing, and SO_REUSEPORT | 
| 268 |  | -	// will make it efficient. | 
| 269 | 287 | 	h2o_socket_t * const h2o_socket = h2o_evloop_socket_create(loop->h2o_ctx.loop, | 
| 270 | 288 | 	                                                           listener_sd, | 
| 271 | 289 | 	                                                           H2O_SOCKET_FLAG_DONT_READ); | 
| @@ -345,13 +363,18 @@ void initialize_event_loop(bool is_main_thread, | 
| 345 | 363 | 
 | 
| 346 | 364 | 	if (global_data->ssl_ctx) { | 
| 347 | 365 | 		loop->h2o_accept_ctx.ssl_ctx = global_data->ssl_ctx; | 
| 348 |  | -		start_accept_polling(config, accept_connection, true, loop); | 
|  | 366 | +		start_accept_polling(is_main_thread, | 
|  | 367 | +		                     global_data->bpf_fd, | 
|  | 368 | +		                     config, | 
|  | 369 | +		                     accept_connection, | 
|  | 370 | +		                     true, | 
|  | 371 | +		                     loop); | 
| 349 | 372 | 		// Assume that the majority of the connections use HTTPS, | 
| 350 | 373 | 		// so HTTP can take a few extra operations. | 
| 351 | 374 | 		accept_cb = accept_http_connection; | 
| 352 | 375 | 	} | 
| 353 | 376 | 
 | 
| 354 |  | -	start_accept_polling(config, accept_cb, false, loop); | 
|  | 377 | +	start_accept_polling(is_main_thread, global_data->bpf_fd, config, accept_cb, false, loop); | 
| 355 | 378 | 	h2o_multithread_register_receiver(loop->h2o_ctx.queue, | 
| 356 | 379 | 	                                  h2o_receiver, | 
| 357 | 380 | 	                                  process_messages); | 
|  | 
0 commit comments