blob: 0f3147610d820b51c1bfcebb3ef8d634921ef523 [file] [log] [blame]
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001/*
Florin Coras5e062572019-03-14 19:07:51 -07002 * Copyright (c) 2016-2019 Cisco and/or its affiliates.
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07003 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
Florin Coras36847942023-02-02 12:56:16 -080015
16#ifdef HAVE_GNU_SOURCE
17#define _GNU_SOURCE
18#endif
19
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -070020#include <unistd.h>
21#include <stdio.h>
22#include <signal.h>
23#include <dlfcn.h>
24#include <pthread.h>
25#include <time.h>
26#include <stdarg.h>
shrinivasan ganapathy1d359632017-10-15 15:46:09 -070027#include <sys/resource.h>
Dave Wallace048b1d62018-01-03 22:24:41 -050028#include <netinet/tcp.h>
Florin Coraseff5f7a2023-02-07 17:36:17 -080029#include <netinet/udp.h>
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -070030
Dave Wallace2a865272018-02-07 21:00:42 -050031#include <vcl/ldp_socket_wrapper.h>
32#include <vcl/ldp.h>
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -070033#include <sys/time.h>
34
Florin Coras7baeb712019-01-04 17:05:43 -080035#include <vcl/vcl_locked.h>
Dave Wallace048b1d62018-01-03 22:24:41 -050036#include <vppinfra/time.h>
37#include <vppinfra/bitmap.h>
Florin Coras30e273b2018-11-27 00:04:59 -080038#include <vppinfra/lock.h>
39#include <vppinfra/pool.h>
40#include <vppinfra/hash.h>
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -070041
42#define HAVE_CONSTRUCTOR_ATTRIBUTE
43#ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
44#define CONSTRUCTOR_ATTRIBUTE \
45 __attribute__ ((constructor))
46#else
47#define CONSTRUCTOR_ATTRIBUTE
48#endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
49
50#define HAVE_DESTRUCTOR_ATTRIBUTE
51#ifdef HAVE_DESTRUCTOR_ATTRIBUTE
52#define DESTRUCTOR_ATTRIBUTE \
53 __attribute__ ((destructor))
54#else
55#define DESTRUCTOR_ATTRIBUTE
56#endif
57
Florin Corasdfe4cf42018-11-28 22:13:45 -080058#define LDP_MAX_NWORKERS 32
59
Florin Coras36847942023-02-02 12:56:16 -080060#ifdef HAVE_GNU_SOURCE
61#define SOCKADDR_GET_SA(__addr) __addr.__sockaddr__;
62#else
63#define SOCKADDR_GET_SA(__addr) _addr;
64#endif
65
Florin Corasdfe4cf42018-11-28 22:13:45 -080066typedef struct ldp_worker_ctx_
Dave Wallace048b1d62018-01-03 22:24:41 -050067{
Dave Wallace048b1d62018-01-03 22:24:41 -050068 u8 *io_buffer;
69 clib_time_t clib_time;
Florin Corasdfe4cf42018-11-28 22:13:45 -080070
71 /*
72 * Select state
73 */
Dave Wallace048b1d62018-01-03 22:24:41 -050074 clib_bitmap_t *rd_bitmap;
75 clib_bitmap_t *wr_bitmap;
76 clib_bitmap_t *ex_bitmap;
Florin Coras294afe22019-01-07 17:49:17 -080077 clib_bitmap_t *si_rd_bitmap;
78 clib_bitmap_t *si_wr_bitmap;
79 clib_bitmap_t *si_ex_bitmap;
Dave Wallace048b1d62018-01-03 22:24:41 -050080 clib_bitmap_t *libc_rd_bitmap;
81 clib_bitmap_t *libc_wr_bitmap;
82 clib_bitmap_t *libc_ex_bitmap;
Florin Corasdfe4cf42018-11-28 22:13:45 -080083
84 /*
85 * Poll state
86 */
Dave Wallace048b1d62018-01-03 22:24:41 -050087 vcl_poll_t *vcl_poll;
Florin Coras6917b942018-11-13 22:44:54 -080088 struct pollfd *libc_poll;
89 u16 *libc_poll_idxs;
Florin Corasdfe4cf42018-11-28 22:13:45 -080090
91 /*
92 * Epoll state
93 */
Dave Wallace048b1d62018-01-03 22:24:41 -050094 u8 epoll_wait_vcl;
hanlin4266d4d2020-05-19 17:34:17 +080095 u8 mq_epfd_added;
Florin Coras99368312018-08-02 10:45:44 -070096 int vcl_mq_epfd;
Florin Corasdfe4cf42018-11-28 22:13:45 -080097
98} ldp_worker_ctx_t;
99
Florin Coras294afe22019-01-07 17:49:17 -0800100/* clib_bitmap_t, fd_mask and vcl_si_set are used interchangeably. Make sure
101 * they are the same size */
102STATIC_ASSERT (sizeof (clib_bitmap_t) == sizeof (fd_mask),
103 "ldp bitmap size mismatch");
104STATIC_ASSERT (sizeof (vcl_si_set) == sizeof (fd_mask),
105 "ldp bitmap size mismatch");
106
Florin Corasdfe4cf42018-11-28 22:13:45 -0800107typedef struct
108{
109 ldp_worker_ctx_t *workers;
110 int init;
111 char app_name[LDP_APP_NAME_MAX];
Florin Coras7baeb712019-01-04 17:05:43 -0800112 u32 vlsh_bit_val;
113 u32 vlsh_bit_mask;
Florin Corasdfe4cf42018-11-28 22:13:45 -0800114 u32 debug;
Florin Corasdfe4cf42018-11-28 22:13:45 -0800115
116 /** vcl needs next epoll_create to go to libc_epoll */
117 u8 vcl_needs_real_epoll;
Florin Corasa5a9efd2021-01-05 17:03:29 -0800118
119 /**
120 * crypto state used only for testing
121 */
122 u8 transparent_tls;
123 u32 ckpair_index;
Dave Wallace2a865272018-02-07 21:00:42 -0500124} ldp_main_t;
Florin Corasdfe4cf42018-11-28 22:13:45 -0800125
Dave Wallace2a865272018-02-07 21:00:42 -0500126#define LDP_DEBUG ldp->debug
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700127
Florin Coras99368312018-08-02 10:45:44 -0700128#define LDBG(_lvl, _fmt, _args...) \
129 if (ldp->debug > _lvl) \
hanlin9f3f18f2019-12-30 16:25:20 +0800130 { \
131 int errno_saved = errno; \
Florin Coras585c86a2020-10-16 17:57:36 -0700132 fprintf (stderr, "ldp<%d>: " _fmt "\n", getpid(), ##_args); \
hanlin9f3f18f2019-12-30 16:25:20 +0800133 errno = errno_saved; \
134 }
Florin Coras99368312018-08-02 10:45:44 -0700135
Dave Wallace2a865272018-02-07 21:00:42 -0500136static ldp_main_t ldp_main = {
Florin Coras7baeb712019-01-04 17:05:43 -0800137 .vlsh_bit_val = (1 << LDP_SID_BIT_MIN),
138 .vlsh_bit_mask = (1 << LDP_SID_BIT_MIN) - 1,
Dave Wallace2a865272018-02-07 21:00:42 -0500139 .debug = LDP_DEBUG_INIT,
Yu Ping7b74b072019-05-08 00:40:24 +0800140 .transparent_tls = 0,
Florin Corasa5a9efd2021-01-05 17:03:29 -0800141 .ckpair_index = ~0,
Dave Wallace048b1d62018-01-03 22:24:41 -0500142};
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700143
Dave Wallace2a865272018-02-07 21:00:42 -0500144static ldp_main_t *ldp = &ldp_main;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700145
Florin Corasdfe4cf42018-11-28 22:13:45 -0800146static inline ldp_worker_ctx_t *
147ldp_worker_get_current (void)
148{
149 return (ldp->workers + vppcom_worker_index ());
150}
151
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700152/*
153 * RETURN: 0 on success or -1 on error.
154 * */
Dave Wallace048b1d62018-01-03 22:24:41 -0500155static inline void
Dave Wallace2a865272018-02-07 21:00:42 -0500156ldp_set_app_name (char *app_name)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700157{
Florin Coras729b9c92023-02-28 10:58:08 -0800158 snprintf (ldp->app_name, LDP_APP_NAME_MAX, "%s-ldp-%d", app_name, getpid ());
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700159}
160
Dave Wallace048b1d62018-01-03 22:24:41 -0500161static inline char *
Dave Wallace2a865272018-02-07 21:00:42 -0500162ldp_get_app_name ()
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700163{
Dave Wallace2a865272018-02-07 21:00:42 -0500164 if (ldp->app_name[0] == '\0')
Florin Coras729b9c92023-02-28 10:58:08 -0800165 ldp_set_app_name (program_invocation_short_name);
Dave Wallace048b1d62018-01-03 22:24:41 -0500166
Dave Wallace2a865272018-02-07 21:00:42 -0500167 return ldp->app_name;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700168}
169
Dave Wallace048b1d62018-01-03 22:24:41 -0500170static inline int
Florin Coras7baeb712019-01-04 17:05:43 -0800171ldp_vlsh_to_fd (vls_handle_t vlsh)
Dave Wallace048b1d62018-01-03 22:24:41 -0500172{
Florin Coras7baeb712019-01-04 17:05:43 -0800173 return (vlsh + ldp->vlsh_bit_val);
Dave Wallace048b1d62018-01-03 22:24:41 -0500174}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700175
Florin Coras7baeb712019-01-04 17:05:43 -0800176static inline vls_handle_t
177ldp_fd_to_vlsh (int fd)
Dave Wallace048b1d62018-01-03 22:24:41 -0500178{
Florin Coras7baeb712019-01-04 17:05:43 -0800179 if (fd < ldp->vlsh_bit_val)
180 return VLS_INVALID_HANDLE;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700181
Florin Coras7baeb712019-01-04 17:05:43 -0800182 return (fd - ldp->vlsh_bit_val);
Dave Wallace048b1d62018-01-03 22:24:41 -0500183}
184
Florin Coras2d9b4272019-03-11 10:14:37 -0700185static void
186ldp_alloc_workers (void)
187{
188 if (ldp->workers)
189 return;
190 pool_alloc (ldp->workers, LDP_MAX_NWORKERS);
191}
192
Florin Coras5f33d0d2021-06-02 21:22:21 -0700193static int
Dave Wallace2a865272018-02-07 21:00:42 -0500194ldp_init (void)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700195{
Florin Corasdfe4cf42018-11-28 22:13:45 -0800196 ldp_worker_ctx_t *ldpw;
Florin Coras99368312018-08-02 10:45:44 -0700197 int rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700198
Florin Coras5f33d0d2021-06-02 21:22:21 -0700199 ASSERT (!ldp->init);
Florin Coras99368312018-08-02 10:45:44 -0700200
201 ldp->init = 1;
202 ldp->vcl_needs_real_epoll = 1;
Florin Coras7baeb712019-01-04 17:05:43 -0800203 rv = vls_app_create (ldp_get_app_name ());
Florin Coras99368312018-08-02 10:45:44 -0700204 if (rv != VPPCOM_OK)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700205 {
Florin Coras955bfbb2018-12-04 13:43:45 -0800206 ldp->vcl_needs_real_epoll = 0;
207 if (rv == VPPCOM_EEXIST)
208 return 0;
Florin Coras05ecfcc2018-12-12 18:19:39 -0800209 LDBG (2, "\nERROR: ldp_init: vppcom_app_create()"
210 " failed! rv = %d (%s)\n", rv, vppcom_retval_str (rv));
Florin Coras99368312018-08-02 10:45:44 -0700211 ldp->init = 0;
212 return rv;
213 }
214 ldp->vcl_needs_real_epoll = 0;
Florin Coras2d9b4272019-03-11 10:14:37 -0700215 ldp_alloc_workers ();
Florin Corasdfe4cf42018-11-28 22:13:45 -0800216 ldpw = ldp_worker_get_current ();
Florin Coras99368312018-08-02 10:45:44 -0700217
218 char *env_var_str = getenv (LDP_ENV_DEBUG);
219 if (env_var_str)
220 {
221 u32 tmp;
222 if (sscanf (env_var_str, "%u", &tmp) != 1)
223 clib_warning ("LDP<%d>: WARNING: Invalid LDP debug level specified in"
224 " the env var " LDP_ENV_DEBUG " (%s)!", getpid (),
225 env_var_str);
226 else
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700227 {
Florin Coras99368312018-08-02 10:45:44 -0700228 ldp->debug = tmp;
Florin Coras05ecfcc2018-12-12 18:19:39 -0800229 LDBG (0, "configured LDP debug level (%u) from env var "
230 LDP_ENV_DEBUG "!", ldp->debug);
Florin Coras99368312018-08-02 10:45:44 -0700231 }
232 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500233
Florin Coras99368312018-08-02 10:45:44 -0700234 env_var_str = getenv (LDP_ENV_APP_NAME);
235 if (env_var_str)
236 {
237 ldp_set_app_name (env_var_str);
Florin Coras05ecfcc2018-12-12 18:19:39 -0800238 LDBG (0, "configured LDP app name (%s) from the env var "
239 LDP_ENV_APP_NAME "!", ldp->app_name);
Florin Coras99368312018-08-02 10:45:44 -0700240 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500241
Florin Coras99368312018-08-02 10:45:44 -0700242 env_var_str = getenv (LDP_ENV_SID_BIT);
243 if (env_var_str)
244 {
245 u32 sb;
246 if (sscanf (env_var_str, "%u", &sb) != 1)
247 {
Florin Coras294afe22019-01-07 17:49:17 -0800248 LDBG (0, "WARNING: Invalid LDP sid bit specified in the env var "
249 LDP_ENV_SID_BIT " (%s)! sid bit value %d (0x%x)", env_var_str,
250 ldp->vlsh_bit_val, ldp->vlsh_bit_val);
Florin Coras99368312018-08-02 10:45:44 -0700251 }
252 else if (sb < LDP_SID_BIT_MIN)
253 {
Florin Coras7baeb712019-01-04 17:05:43 -0800254 ldp->vlsh_bit_val = (1 << LDP_SID_BIT_MIN);
255 ldp->vlsh_bit_mask = ldp->vlsh_bit_val - 1;
Dave Wallace048b1d62018-01-03 22:24:41 -0500256
Florin Coras294afe22019-01-07 17:49:17 -0800257 LDBG (0, "WARNING: LDP sid bit (%u) specified in the env var "
258 LDP_ENV_SID_BIT " (%s) is too small. Using LDP_SID_BIT_MIN"
259 " (%d)! sid bit value %d (0x%x)", sb, env_var_str,
260 LDP_SID_BIT_MIN, ldp->vlsh_bit_val, ldp->vlsh_bit_val);
Florin Coras99368312018-08-02 10:45:44 -0700261 }
262 else if (sb > LDP_SID_BIT_MAX)
263 {
Florin Coras7baeb712019-01-04 17:05:43 -0800264 ldp->vlsh_bit_val = (1 << LDP_SID_BIT_MAX);
265 ldp->vlsh_bit_mask = ldp->vlsh_bit_val - 1;
Dave Wallace048b1d62018-01-03 22:24:41 -0500266
Florin Coras294afe22019-01-07 17:49:17 -0800267 LDBG (0, "WARNING: LDP sid bit (%u) specified in the env var "
268 LDP_ENV_SID_BIT " (%s) is too big. Using LDP_SID_BIT_MAX"
269 " (%d)! sid bit value %d (0x%x)", sb, env_var_str,
270 LDP_SID_BIT_MAX, ldp->vlsh_bit_val, ldp->vlsh_bit_val);
Dave Wallace048b1d62018-01-03 22:24:41 -0500271 }
272 else
273 {
Florin Coras7baeb712019-01-04 17:05:43 -0800274 ldp->vlsh_bit_val = (1 << sb);
275 ldp->vlsh_bit_mask = ldp->vlsh_bit_val - 1;
Florin Coras99368312018-08-02 10:45:44 -0700276
Florin Coras05ecfcc2018-12-12 18:19:39 -0800277 LDBG (0, "configured LDP sid bit (%u) from "
278 LDP_ENV_SID_BIT "! sid bit value %d (0x%x)", sb,
Florin Coras7baeb712019-01-04 17:05:43 -0800279 ldp->vlsh_bit_val, ldp->vlsh_bit_val);
Dave Wallace048b1d62018-01-03 22:24:41 -0500280 }
Florin Coras294afe22019-01-07 17:49:17 -0800281
282 /* Make sure there are enough bits in the fd set for vcl sessions */
283 if (ldp->vlsh_bit_val > FD_SETSIZE / 2)
284 {
wanghanlin1eb8fea2021-10-14 11:10:26 +0800285 /* Only valid for select/pselect, so just WARNING and not exit */
286 LDBG (0,
287 "WARNING: LDP vlsh bit value %d > FD_SETSIZE/2 %d, "
288 "select/pselect not supported now!",
Florin Coras294afe22019-01-07 17:49:17 -0800289 ldp->vlsh_bit_val, FD_SETSIZE / 2);
Florin Coras294afe22019-01-07 17:49:17 -0800290 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500291 }
Yu Ping7b74b072019-05-08 00:40:24 +0800292 env_var_str = getenv (LDP_ENV_TLS_TRANS);
293 if (env_var_str)
294 {
295 ldp->transparent_tls = 1;
296 }
Florin Coras99368312018-08-02 10:45:44 -0700297
Florin Coras4dee8cd2019-01-29 21:28:16 -0800298 /* *INDENT-OFF* */
Damjan Marionb2c31b62020-12-13 21:47:40 +0100299 pool_foreach (ldpw, ldp->workers) {
Florin Coras4dee8cd2019-01-29 21:28:16 -0800300 clib_memset (&ldpw->clib_time, 0, sizeof (ldpw->clib_time));
Damjan Marionb2c31b62020-12-13 21:47:40 +0100301 }
Florin Coras4dee8cd2019-01-29 21:28:16 -0800302 /* *INDENT-ON* */
303
Florin Coras05ecfcc2018-12-12 18:19:39 -0800304 LDBG (0, "LDP initialization: done!");
Florin Coras99368312018-08-02 10:45:44 -0700305
306 return 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500307}
308
Florin Coras5f33d0d2021-06-02 21:22:21 -0700309#define ldp_init_check() \
310 if (PREDICT_FALSE (!ldp->init)) \
311 { \
312 if ((errno = -ldp_init ())) \
313 return -1; \
314 }
315
Dave Wallace048b1d62018-01-03 22:24:41 -0500316int
317close (int fd)
318{
Florin Coras7baeb712019-01-04 17:05:43 -0800319 vls_handle_t vlsh;
320 int rv, epfd;
Dave Wallace048b1d62018-01-03 22:24:41 -0500321
Florin Coras5f33d0d2021-06-02 21:22:21 -0700322 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -0500323
Florin Coras7baeb712019-01-04 17:05:43 -0800324 vlsh = ldp_fd_to_vlsh (fd);
325 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500326 {
Florin Coras7baeb712019-01-04 17:05:43 -0800327 epfd = vls_attr (vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -0500328 if (epfd > 0)
329 {
Florin Coras7baeb712019-01-04 17:05:43 -0800330 LDBG (0, "fd %d: calling libc_close: epfd %u", fd, epfd);
Dave Wallace048b1d62018-01-03 22:24:41 -0500331
332 rv = libc_close (epfd);
333 if (rv < 0)
334 {
335 u32 size = sizeof (epfd);
336 epfd = 0;
337
Florin Coras7baeb712019-01-04 17:05:43 -0800338 (void) vls_attr (vlsh, VPPCOM_ATTR_SET_LIBC_EPFD, &epfd, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -0500339 }
340 }
341 else if (PREDICT_FALSE (epfd < 0))
342 {
343 errno = -epfd;
344 rv = -1;
345 goto done;
346 }
347
Florin Coras7baeb712019-01-04 17:05:43 -0800348 LDBG (0, "fd %d: calling vls_close: vlsh %u", fd, vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -0500349
Florin Coras7baeb712019-01-04 17:05:43 -0800350 rv = vls_close (vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -0500351 if (rv != VPPCOM_OK)
352 {
353 errno = -rv;
354 rv = -1;
355 }
356 }
357 else
358 {
Florin Coras7baeb712019-01-04 17:05:43 -0800359 LDBG (0, "fd %d: calling libc_close", fd);
Dave Wallace048b1d62018-01-03 22:24:41 -0500360 rv = libc_close (fd);
361 }
362
363done:
Dave Wallace048b1d62018-01-03 22:24:41 -0500364 return rv;
365}
366
367ssize_t
368read (int fd, void *buf, size_t nbytes)
369{
Florin Coras7baeb712019-01-04 17:05:43 -0800370 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500371 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -0500372
Florin Coras5f33d0d2021-06-02 21:22:21 -0700373 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -0500374
Florin Coras7baeb712019-01-04 17:05:43 -0800375 vlsh = ldp_fd_to_vlsh (fd);
376 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500377 {
Florin Coras7baeb712019-01-04 17:05:43 -0800378 size = vls_read (vlsh, buf, nbytes);
Dave Wallace048b1d62018-01-03 22:24:41 -0500379 if (size < 0)
380 {
381 errno = -size;
382 size = -1;
383 }
384 }
385 else
386 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500387 size = libc_read (fd, buf, nbytes);
388 }
389
Dave Wallace048b1d62018-01-03 22:24:41 -0500390 return size;
391}
392
393ssize_t
394readv (int fd, const struct iovec * iov, int iovcnt)
395{
Dave Wallace8aaba562018-01-18 17:21:19 -0500396 int rv = 0, i, total = 0;
Florin Coras7baeb712019-01-04 17:05:43 -0800397 vls_handle_t vlsh;
398 ssize_t size = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500399
Florin Coras5f33d0d2021-06-02 21:22:21 -0700400 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -0500401
Florin Coras7baeb712019-01-04 17:05:43 -0800402 vlsh = ldp_fd_to_vlsh (fd);
403 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500404 {
Florin Coras067f9542020-02-14 05:33:46 +0000405 for (i = 0; i < iovcnt; ++i)
Dave Wallace048b1d62018-01-03 22:24:41 -0500406 {
Florin Coras067f9542020-02-14 05:33:46 +0000407 rv = vls_read (vlsh, iov[i].iov_base, iov[i].iov_len);
408 if (rv <= 0)
409 break;
410 else
Dave Wallace048b1d62018-01-03 22:24:41 -0500411 {
Florin Coras067f9542020-02-14 05:33:46 +0000412 total += rv;
413 if (rv < iov[i].iov_len)
Dave Wallace048b1d62018-01-03 22:24:41 -0500414 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700415 }
416 }
Florin Coras067f9542020-02-14 05:33:46 +0000417 if (rv < 0 && total == 0)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700418 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500419 errno = -rv;
420 size = -1;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700421 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500422 else
423 size = total;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700424 }
425 else
426 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500427 size = libc_readv (fd, iov, iovcnt);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700428 }
429
Dave Wallace048b1d62018-01-03 22:24:41 -0500430 return size;
431}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700432
Dave Wallace048b1d62018-01-03 22:24:41 -0500433ssize_t
434write (int fd, const void *buf, size_t nbytes)
435{
Florin Coras7baeb712019-01-04 17:05:43 -0800436 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500437 ssize_t size = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500438
Florin Coras5f33d0d2021-06-02 21:22:21 -0700439 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -0500440
Florin Coras7baeb712019-01-04 17:05:43 -0800441 vlsh = ldp_fd_to_vlsh (fd);
442 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500443 {
Florin Coras7baeb712019-01-04 17:05:43 -0800444 size = vls_write_msg (vlsh, (void *) buf, nbytes);
Dave Wallace048b1d62018-01-03 22:24:41 -0500445 if (size < 0)
446 {
447 errno = -size;
448 size = -1;
449 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700450 }
451 else
452 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500453 size = libc_write (fd, buf, nbytes);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700454 }
455
Dave Wallace048b1d62018-01-03 22:24:41 -0500456 return size;
457}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700458
Dave Wallace048b1d62018-01-03 22:24:41 -0500459ssize_t
460writev (int fd, const struct iovec * iov, int iovcnt)
461{
Dave Wallace048b1d62018-01-03 22:24:41 -0500462 ssize_t size = 0, total = 0;
Florin Coras7baeb712019-01-04 17:05:43 -0800463 vls_handle_t vlsh;
Dave Wallace8aaba562018-01-18 17:21:19 -0500464 int i, rv = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500465
Florin Coras5f33d0d2021-06-02 21:22:21 -0700466 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -0500467
Florin Coras7baeb712019-01-04 17:05:43 -0800468 vlsh = ldp_fd_to_vlsh (fd);
469 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500470 {
Florin Coraseda1b8c2020-03-23 16:00:35 +0000471 for (i = 0; i < iovcnt; ++i)
Dave Wallace048b1d62018-01-03 22:24:41 -0500472 {
Florin Coraseda1b8c2020-03-23 16:00:35 +0000473 rv = vls_write_msg (vlsh, iov[i].iov_base, iov[i].iov_len);
474 if (rv < 0)
475 break;
476 else
Dave Wallace048b1d62018-01-03 22:24:41 -0500477 {
Florin Coraseda1b8c2020-03-23 16:00:35 +0000478 total += rv;
479 if (rv < iov[i].iov_len)
Dave Wallace048b1d62018-01-03 22:24:41 -0500480 break;
Dave Wallace048b1d62018-01-03 22:24:41 -0500481 }
482 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500483
Florin Coraseda1b8c2020-03-23 16:00:35 +0000484 if (rv < 0 && total == 0)
Dave Wallace048b1d62018-01-03 22:24:41 -0500485 {
486 errno = -rv;
487 size = -1;
488 }
489 else
490 size = total;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700491 }
492 else
493 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500494 size = libc_writev (fd, iov, iovcnt);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700495 }
496
Dave Wallace048b1d62018-01-03 22:24:41 -0500497 return size;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700498}
499
Florin Coras0ab36f52020-05-26 19:45:45 +0000500static int
501fcntl_internal (int fd, int cmd, va_list ap)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700502{
Florin Coras7baeb712019-01-04 17:05:43 -0800503 vls_handle_t vlsh;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700504 int rv = 0;
Florin Coras7baeb712019-01-04 17:05:43 -0800505
506 vlsh = ldp_fd_to_vlsh (fd);
507 LDBG (0, "fd %u vlsh %d, cmd %u", fd, vlsh, cmd);
508 if (vlsh != VLS_INVALID_HANDLE)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700509 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500510 int flags = va_arg (ap, int);
511 u32 size;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700512
Dave Wallace048b1d62018-01-03 22:24:41 -0500513 size = sizeof (flags);
514 rv = -EOPNOTSUPP;
515 switch (cmd)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700516 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500517 case F_SETFL:
Florin Coras7baeb712019-01-04 17:05:43 -0800518 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_FLAGS, &flags, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -0500519 break;
520
521 case F_GETFL:
Florin Coras7baeb712019-01-04 17:05:43 -0800522 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_FLAGS, &flags, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -0500523 if (rv == VPPCOM_OK)
Florin Coras7baeb712019-01-04 17:05:43 -0800524 rv = flags;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700525 break;
Florin Coras173bae32018-11-16 18:56:28 -0800526 case F_SETFD:
527 /* TODO handle this */
528 LDBG (0, "F_SETFD ignored flags %u", flags);
529 rv = 0;
530 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700531 default:
Dave Wallace048b1d62018-01-03 22:24:41 -0500532 rv = -EOPNOTSUPP;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700533 break;
534 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500535 if (rv < 0)
536 {
537 errno = -rv;
538 rv = -1;
539 }
540 }
541 else
542 {
Carl Smithe16707b2019-11-13 14:37:39 +1300543#ifdef HAVE_FCNTL64
544 rv = libc_vfcntl64 (fd, cmd, ap);
545#else
Dave Wallace048b1d62018-01-03 22:24:41 -0500546 rv = libc_vfcntl (fd, cmd, ap);
Carl Smithe16707b2019-11-13 14:37:39 +1300547#endif
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700548 }
549
Florin Coras0ab36f52020-05-26 19:45:45 +0000550 return rv;
551}
552
553int
554fcntl (int fd, int cmd, ...)
555{
556 va_list ap;
557 int rv;
558
Florin Coras5f33d0d2021-06-02 21:22:21 -0700559 ldp_init_check ();
Florin Coras0ab36f52020-05-26 19:45:45 +0000560
561 va_start (ap, cmd);
562 rv = fcntl_internal (fd, cmd, ap);
Dave Wallace048b1d62018-01-03 22:24:41 -0500563 va_end (ap);
564
Dave Wallace048b1d62018-01-03 22:24:41 -0500565 return rv;
566}
567
568int
Florin Corasd7586d52020-04-29 02:19:51 +0000569fcntl64 (int fd, int cmd, ...)
570{
571 va_list ap;
572 int rv;
573
Florin Coras5f33d0d2021-06-02 21:22:21 -0700574 ldp_init_check ();
Florin Coras0ab36f52020-05-26 19:45:45 +0000575
Florin Corasd7586d52020-04-29 02:19:51 +0000576 va_start (ap, cmd);
Florin Coras0ab36f52020-05-26 19:45:45 +0000577 rv = fcntl_internal (fd, cmd, ap);
Florin Corasd7586d52020-04-29 02:19:51 +0000578 va_end (ap);
579 return rv;
580}
581
582int
Dave Wallace048b1d62018-01-03 22:24:41 -0500583ioctl (int fd, unsigned long int cmd, ...)
584{
Florin Coras7baeb712019-01-04 17:05:43 -0800585 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500586 va_list ap;
Florin Coras7baeb712019-01-04 17:05:43 -0800587 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -0500588
Florin Coras5f33d0d2021-06-02 21:22:21 -0700589 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -0500590
591 va_start (ap, cmd);
Dave Wallace048b1d62018-01-03 22:24:41 -0500592
Florin Coras7baeb712019-01-04 17:05:43 -0800593 vlsh = ldp_fd_to_vlsh (fd);
594 if (vlsh != VLS_INVALID_HANDLE)
595 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500596 switch (cmd)
597 {
598 case FIONREAD:
Florin Coras7baeb712019-01-04 17:05:43 -0800599 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_NREAD, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -0500600 break;
601
602 case FIONBIO:
603 {
604 u32 flags = va_arg (ap, int) ? O_NONBLOCK : 0;
605 u32 size = sizeof (flags);
606
607 /* TBD: When VPPCOM_ATTR_[GS]ET_FLAGS supports flags other than
608 * non-blocking, the flags should be read here and merged
609 * with O_NONBLOCK.
610 */
Florin Coras7baeb712019-01-04 17:05:43 -0800611 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_FLAGS, &flags, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -0500612 }
613 break;
614
615 default:
616 rv = -EOPNOTSUPP;
617 break;
618 }
619 if (rv < 0)
620 {
621 errno = -rv;
622 rv = -1;
623 }
624 }
625 else
626 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500627 rv = libc_vioctl (fd, cmd, ap);
628 }
629
Dave Wallace048b1d62018-01-03 22:24:41 -0500630 va_end (ap);
631 return rv;
632}
633
Florin Coras294afe22019-01-07 17:49:17 -0800634always_inline void
635ldp_select_init_maps (fd_set * __restrict original,
636 clib_bitmap_t ** resultb, clib_bitmap_t ** libcb,
637 clib_bitmap_t ** vclb, int nfds, u32 minbits,
638 u32 n_bytes, uword * si_bits, uword * libc_bits)
639{
640 uword si_bits_set, libc_bits_set;
641 vls_handle_t vlsh;
642 int fd;
643
644 clib_bitmap_validate (*vclb, minbits);
645 clib_bitmap_validate (*libcb, minbits);
646 clib_bitmap_validate (*resultb, minbits);
647 clib_memcpy_fast (*resultb, original, n_bytes);
648 memset (original, 0, n_bytes);
649
650 /* *INDENT-OFF* */
Damjan Marionf0ca1e82020-12-13 23:26:56 +0100651 clib_bitmap_foreach (fd, *resultb) {
Florin Coras294afe22019-01-07 17:49:17 -0800652 if (fd > nfds)
653 break;
654 vlsh = ldp_fd_to_vlsh (fd);
655 if (vlsh == VLS_INVALID_HANDLE)
656 clib_bitmap_set_no_check (*libcb, fd, 1);
657 else
Florin Corascbce80a2020-04-20 01:32:38 +0000658 *vclb = clib_bitmap_set (*vclb, vlsh_to_session_index (vlsh), 1);
Damjan Marionf0ca1e82020-12-13 23:26:56 +0100659 }
Florin Coras294afe22019-01-07 17:49:17 -0800660 /* *INDENT-ON* */
661
662 si_bits_set = clib_bitmap_last_set (*vclb) + 1;
663 *si_bits = (si_bits_set > *si_bits) ? si_bits_set : *si_bits;
Florin Corascbce80a2020-04-20 01:32:38 +0000664 clib_bitmap_validate (*resultb, *si_bits);
Florin Coras294afe22019-01-07 17:49:17 -0800665
666 libc_bits_set = clib_bitmap_last_set (*libcb) + 1;
667 *libc_bits = (libc_bits_set > *libc_bits) ? libc_bits_set : *libc_bits;
668}
669
670always_inline int
671ldp_select_vcl_map_to_libc (clib_bitmap_t * vclb, fd_set * __restrict libcb)
672{
673 vls_handle_t vlsh;
674 uword si;
675 int fd;
676
677 if (!libcb)
678 return 0;
679
680 /* *INDENT-OFF* */
Damjan Marionf0ca1e82020-12-13 23:26:56 +0100681 clib_bitmap_foreach (si, vclb) {
Florin Coras294afe22019-01-07 17:49:17 -0800682 vlsh = vls_session_index_to_vlsh (si);
Florin Coras54140622020-02-04 19:04:34 +0000683 ASSERT (vlsh != VLS_INVALID_HANDLE);
Florin Coras294afe22019-01-07 17:49:17 -0800684 fd = ldp_vlsh_to_fd (vlsh);
685 if (PREDICT_FALSE (fd < 0))
686 {
687 errno = EBADFD;
688 return -1;
689 }
690 FD_SET (fd, libcb);
Damjan Marionf0ca1e82020-12-13 23:26:56 +0100691 }
Florin Coras294afe22019-01-07 17:49:17 -0800692 /* *INDENT-ON* */
693
694 return 0;
695}
696
697always_inline void
698ldp_select_libc_map_merge (clib_bitmap_t * result, fd_set * __restrict libcb)
699{
700 uword fd;
701
Florin Coras78b5fa62019-02-21 20:04:15 -0800702 if (!libcb)
703 return;
704
Florin Coras294afe22019-01-07 17:49:17 -0800705 /* *INDENT-OFF* */
Damjan Marionf0ca1e82020-12-13 23:26:56 +0100706 clib_bitmap_foreach (fd, result)
Florin Coras294afe22019-01-07 17:49:17 -0800707 FD_SET ((int)fd, libcb);
Florin Coras294afe22019-01-07 17:49:17 -0800708 /* *INDENT-ON* */
709}
710
Dave Wallace048b1d62018-01-03 22:24:41 -0500711int
Dave Wallace2a865272018-02-07 21:00:42 -0500712ldp_pselect (int nfds, fd_set * __restrict readfds,
713 fd_set * __restrict writefds,
714 fd_set * __restrict exceptfds,
715 const struct timespec *__restrict timeout,
716 const __sigset_t * __restrict sigmask)
Dave Wallace048b1d62018-01-03 22:24:41 -0500717{
Florin Coras294afe22019-01-07 17:49:17 -0800718 u32 minbits = clib_max (nfds, BITS (uword)), n_bytes;
Florin Corasdfe4cf42018-11-28 22:13:45 -0800719 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras294afe22019-01-07 17:49:17 -0800720 struct timespec libc_tspec = { 0 };
721 f64 time_out, vcl_timeout = 0;
722 uword si_bits, libc_bits;
723 int rv, bits_set = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500724
725 if (nfds < 0)
726 {
727 errno = EINVAL;
728 return -1;
729 }
730
Florin Coras4dee8cd2019-01-29 21:28:16 -0800731 if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
732 clib_time_init (&ldpw->clib_time);
733
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500734 if (timeout)
735 {
736 time_out = (timeout->tv_sec == 0 && timeout->tv_nsec == 0) ?
Florin Coras7baeb712019-01-04 17:05:43 -0800737 (f64) 0 : (f64) timeout->tv_sec + (f64) timeout->tv_nsec / (f64) 1e9;
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500738
liuyacanf71796e2021-08-02 10:01:39 +0800739 time_out += clib_time_now (&ldpw->clib_time);
740
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500741 /* select as fine grained sleep */
742 if (!nfds)
743 {
Florin Corasdfe4cf42018-11-28 22:13:45 -0800744 while (clib_time_now (&ldpw->clib_time) < time_out)
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500745 ;
746 return 0;
747 }
748 }
749 else if (!nfds)
750 {
751 errno = EINVAL;
752 return -1;
753 }
754 else
755 time_out = -1;
756
Florin Coras7baeb712019-01-04 17:05:43 -0800757 if (nfds <= ldp->vlsh_bit_val)
Dave Wallace048b1d62018-01-03 22:24:41 -0500758 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500759 rv = libc_pselect (nfds, readfds, writefds, exceptfds,
760 timeout, sigmask);
761 goto done;
762 }
763
Florin Coras294afe22019-01-07 17:49:17 -0800764 si_bits = libc_bits = 0;
765 n_bytes = nfds / 8 + ((nfds % 8) ? 1 : 0);
Florin Coras7baeb712019-01-04 17:05:43 -0800766
Dave Wallace048b1d62018-01-03 22:24:41 -0500767 if (readfds)
Florin Coras294afe22019-01-07 17:49:17 -0800768 ldp_select_init_maps (readfds, &ldpw->rd_bitmap, &ldpw->libc_rd_bitmap,
769 &ldpw->si_rd_bitmap, nfds, minbits, n_bytes,
770 &si_bits, &libc_bits);
Dave Wallace048b1d62018-01-03 22:24:41 -0500771 if (writefds)
Florin Coras294afe22019-01-07 17:49:17 -0800772 ldp_select_init_maps (writefds, &ldpw->wr_bitmap,
773 &ldpw->libc_wr_bitmap, &ldpw->si_wr_bitmap, nfds,
774 minbits, n_bytes, &si_bits, &libc_bits);
Dave Wallace048b1d62018-01-03 22:24:41 -0500775 if (exceptfds)
Florin Coras294afe22019-01-07 17:49:17 -0800776 ldp_select_init_maps (exceptfds, &ldpw->ex_bitmap,
777 &ldpw->libc_ex_bitmap, &ldpw->si_ex_bitmap, nfds,
778 minbits, n_bytes, &si_bits, &libc_bits);
Dave Wallace048b1d62018-01-03 22:24:41 -0500779
Florin Coras294afe22019-01-07 17:49:17 -0800780 if (PREDICT_FALSE (!si_bits && !libc_bits))
Dave Wallace048b1d62018-01-03 22:24:41 -0500781 {
782 errno = EINVAL;
783 rv = -1;
784 goto done;
785 }
786
Florin Coras78b5fa62019-02-21 20:04:15 -0800787 if (!si_bits)
788 libc_tspec = timeout ? *timeout : libc_tspec;
Florin Coras294afe22019-01-07 17:49:17 -0800789
Dave Wallace048b1d62018-01-03 22:24:41 -0500790 do
791 {
Florin Coras294afe22019-01-07 17:49:17 -0800792 if (si_bits)
Dave Wallace048b1d62018-01-03 22:24:41 -0500793 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500794 if (readfds)
Florin Coras294afe22019-01-07 17:49:17 -0800795 clib_memcpy_fast (ldpw->rd_bitmap, ldpw->si_rd_bitmap,
Florin Corascbce80a2020-04-20 01:32:38 +0000796 vec_len (ldpw->si_rd_bitmap) *
Dave Barach178cf492018-11-13 16:34:13 -0500797 sizeof (clib_bitmap_t));
Dave Wallace048b1d62018-01-03 22:24:41 -0500798 if (writefds)
Florin Coras294afe22019-01-07 17:49:17 -0800799 clib_memcpy_fast (ldpw->wr_bitmap, ldpw->si_wr_bitmap,
Florin Corascbce80a2020-04-20 01:32:38 +0000800 vec_len (ldpw->si_wr_bitmap) *
Dave Barach178cf492018-11-13 16:34:13 -0500801 sizeof (clib_bitmap_t));
Dave Wallace048b1d62018-01-03 22:24:41 -0500802 if (exceptfds)
Florin Coras294afe22019-01-07 17:49:17 -0800803 clib_memcpy_fast (ldpw->ex_bitmap, ldpw->si_ex_bitmap,
Florin Corascbce80a2020-04-20 01:32:38 +0000804 vec_len (ldpw->si_ex_bitmap) *
Dave Barach178cf492018-11-13 16:34:13 -0500805 sizeof (clib_bitmap_t));
Florin Coras294afe22019-01-07 17:49:17 -0800806
Florin Coras0ef8ef22019-01-18 08:37:13 -0800807 rv = vls_select (si_bits, readfds ? ldpw->rd_bitmap : NULL,
808 writefds ? ldpw->wr_bitmap : NULL,
809 exceptfds ? ldpw->ex_bitmap : NULL, vcl_timeout);
Florin Coras294afe22019-01-07 17:49:17 -0800810 if (rv < 0)
811 {
812 errno = -rv;
813 rv = -1;
Florin Coras5e6222a2020-04-24 17:09:25 +0000814 goto done;
Florin Coras294afe22019-01-07 17:49:17 -0800815 }
816 else if (rv > 0)
817 {
818 if (ldp_select_vcl_map_to_libc (ldpw->rd_bitmap, readfds))
819 {
820 rv = -1;
821 goto done;
822 }
823
824 if (ldp_select_vcl_map_to_libc (ldpw->wr_bitmap, writefds))
825 {
826 rv = -1;
827 goto done;
828 }
829
830 if (ldp_select_vcl_map_to_libc (ldpw->ex_bitmap, exceptfds))
831 {
832 rv = -1;
833 goto done;
834 }
835 bits_set = rv;
836 }
837 }
838 if (libc_bits)
839 {
840 if (readfds)
841 clib_memcpy_fast (ldpw->rd_bitmap, ldpw->libc_rd_bitmap,
842 vec_len (ldpw->libc_rd_bitmap) *
843 sizeof (clib_bitmap_t));
844 if (writefds)
845 clib_memcpy_fast (ldpw->wr_bitmap, ldpw->libc_wr_bitmap,
846 vec_len (ldpw->libc_wr_bitmap) *
847 sizeof (clib_bitmap_t));
848 if (exceptfds)
849 clib_memcpy_fast (ldpw->ex_bitmap, ldpw->libc_ex_bitmap,
850 vec_len (ldpw->libc_ex_bitmap) *
851 sizeof (clib_bitmap_t));
852
Dave Wallace048b1d62018-01-03 22:24:41 -0500853 rv = libc_pselect (libc_bits,
Florin Coras294afe22019-01-07 17:49:17 -0800854 readfds ? (fd_set *) ldpw->rd_bitmap : NULL,
855 writefds ? (fd_set *) ldpw->wr_bitmap : NULL,
856 exceptfds ? (fd_set *) ldpw->ex_bitmap : NULL,
857 &libc_tspec, sigmask);
858 if (rv > 0)
859 {
860 ldp_select_libc_map_merge (ldpw->rd_bitmap, readfds);
861 ldp_select_libc_map_merge (ldpw->wr_bitmap, writefds);
862 ldp_select_libc_map_merge (ldpw->ex_bitmap, exceptfds);
863 bits_set += rv;
864 }
865 }
866
867 if (bits_set)
868 {
869 rv = bits_set;
870 goto done;
Dave Wallace048b1d62018-01-03 22:24:41 -0500871 }
872 }
Florin Corasdfe4cf42018-11-28 22:13:45 -0800873 while ((time_out == -1) || (clib_time_now (&ldpw->clib_time) < time_out));
Dave Wallace048b1d62018-01-03 22:24:41 -0500874 rv = 0;
875
876done:
877 /* TBD: set timeout to amount of time left */
Florin Corasdfe4cf42018-11-28 22:13:45 -0800878 clib_bitmap_zero (ldpw->rd_bitmap);
Florin Coras294afe22019-01-07 17:49:17 -0800879 clib_bitmap_zero (ldpw->si_rd_bitmap);
Florin Corasdfe4cf42018-11-28 22:13:45 -0800880 clib_bitmap_zero (ldpw->libc_rd_bitmap);
881 clib_bitmap_zero (ldpw->wr_bitmap);
Florin Coras294afe22019-01-07 17:49:17 -0800882 clib_bitmap_zero (ldpw->si_wr_bitmap);
Florin Corasdfe4cf42018-11-28 22:13:45 -0800883 clib_bitmap_zero (ldpw->libc_wr_bitmap);
884 clib_bitmap_zero (ldpw->ex_bitmap);
Florin Coras294afe22019-01-07 17:49:17 -0800885 clib_bitmap_zero (ldpw->si_ex_bitmap);
Florin Corasdfe4cf42018-11-28 22:13:45 -0800886 clib_bitmap_zero (ldpw->libc_ex_bitmap);
Dave Wallace048b1d62018-01-03 22:24:41 -0500887
Dave Wallace048b1d62018-01-03 22:24:41 -0500888 return rv;
889}
890
891int
892select (int nfds, fd_set * __restrict readfds,
893 fd_set * __restrict writefds,
894 fd_set * __restrict exceptfds, struct timeval *__restrict timeout)
895{
896 struct timespec tspec;
897
898 if (timeout)
899 {
900 tspec.tv_sec = timeout->tv_sec;
901 tspec.tv_nsec = timeout->tv_usec * 1000;
902 }
Dave Wallace2a865272018-02-07 21:00:42 -0500903 return ldp_pselect (nfds, readfds, writefds, exceptfds,
904 timeout ? &tspec : NULL, NULL);
Dave Wallace048b1d62018-01-03 22:24:41 -0500905}
906
907#ifdef __USE_XOPEN2K
908int
909pselect (int nfds, fd_set * __restrict readfds,
910 fd_set * __restrict writefds,
911 fd_set * __restrict exceptfds,
912 const struct timespec *__restrict timeout,
913 const __sigset_t * __restrict sigmask)
914{
Dave Wallace2a865272018-02-07 21:00:42 -0500915 return ldp_pselect (nfds, readfds, writefds, exceptfds, timeout, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -0500916}
917#endif
918
Yu Ping7b74b072019-05-08 00:40:24 +0800919/* If transparent TLS mode is turned on, then ldp will load key and cert.
920 */
921static int
Florin Corasa5a9efd2021-01-05 17:03:29 -0800922load_cert_key_pair (void)
Yu Ping7b74b072019-05-08 00:40:24 +0800923{
Florin Corasa5a9efd2021-01-05 17:03:29 -0800924 char *cert_str = getenv (LDP_ENV_TLS_CERT);
925 char *key_str = getenv (LDP_ENV_TLS_KEY);
926 char cert_buf[4096], key_buf[4096];
927 int cert_size, key_size;
928 vppcom_cert_key_pair_t crypto;
929 int ckp_index;
Yu Ping7b74b072019-05-08 00:40:24 +0800930 FILE *fp;
931
Florin Corasa5a9efd2021-01-05 17:03:29 -0800932 if (!cert_str || !key_str)
Yu Ping7b74b072019-05-08 00:40:24 +0800933 {
934 LDBG (0, "ERROR: failed to read LDP environment %s\n",
935 LDP_ENV_TLS_CERT);
936 return -1;
937 }
Florin Corasa5a9efd2021-01-05 17:03:29 -0800938
939 fp = fopen (cert_str, "r");
940 if (fp == NULL)
941 {
942 LDBG (0, "ERROR: failed to open cert file %s \n", cert_str);
943 return -1;
944 }
945 cert_size = fread (cert_buf, sizeof (char), sizeof (cert_buf), fp);
946 fclose (fp);
947
948 fp = fopen (key_str, "r");
949 if (fp == NULL)
950 {
951 LDBG (0, "ERROR: failed to open key file %s \n", key_str);
952 return -1;
953 }
954 key_size = fread (key_buf, sizeof (char), sizeof (key_buf), fp);
955 fclose (fp);
956
957 crypto.cert = cert_buf;
958 crypto.key = key_buf;
959 crypto.cert_len = cert_size;
960 crypto.key_len = key_size;
961 ckp_index = vppcom_add_cert_key_pair (&crypto);
962 if (ckp_index < 0)
963 {
964 LDBG (0, "ERROR: failed to add cert key pair\n");
965 return -1;
966 }
967
968 ldp->ckpair_index = ckp_index;
969
Yu Ping7b74b072019-05-08 00:40:24 +0800970 return 0;
971}
972
973static int
Florin Corasa5a9efd2021-01-05 17:03:29 -0800974assign_cert_key_pair (vls_handle_t vlsh)
Yu Ping7b74b072019-05-08 00:40:24 +0800975{
Florin Corasa5a9efd2021-01-05 17:03:29 -0800976 uint32_t ckp_len;
Yu Ping7b74b072019-05-08 00:40:24 +0800977
Florin Corasa5a9efd2021-01-05 17:03:29 -0800978 if (ldp->ckpair_index == ~0 && load_cert_key_pair () < 0)
979 return -1;
980
981 ckp_len = sizeof (ldp->ckpair_index);
liuyacan276675e2021-08-30 13:24:53 +0800982 return vls_attr (vlsh, VPPCOM_ATTR_SET_CKPAIR, &ldp->ckpair_index, &ckp_len);
Yu Ping7b74b072019-05-08 00:40:24 +0800983}
984
Dave Wallace048b1d62018-01-03 22:24:41 -0500985int
986socket (int domain, int type, int protocol)
987{
Florin Coras7baeb712019-01-04 17:05:43 -0800988 int rv, sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
Dave Wallace048b1d62018-01-03 22:24:41 -0500989 u8 is_nonblocking = type & SOCK_NONBLOCK ? 1 : 0;
Florin Coras7baeb712019-01-04 17:05:43 -0800990 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500991
Florin Coras5f33d0d2021-06-02 21:22:21 -0700992 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -0500993
994 if (((domain == AF_INET) || (domain == AF_INET6)) &&
995 ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM)))
996 {
Yu Ping7b74b072019-05-08 00:40:24 +0800997 u8 proto;
998 if (ldp->transparent_tls)
999 {
1000 proto = VPPCOM_PROTO_TLS;
1001 }
1002 else
1003 proto = ((sock_type == SOCK_DGRAM) ?
1004 VPPCOM_PROTO_UDP : VPPCOM_PROTO_TCP);
Dave Wallace048b1d62018-01-03 22:24:41 -05001005
Florin Coras7baeb712019-01-04 17:05:43 -08001006 LDBG (0, "calling vls_create: proto %u (%s), is_nonblocking %u",
1007 proto, vppcom_proto_str (proto), is_nonblocking);
Dave Wallace048b1d62018-01-03 22:24:41 -05001008
Florin Coras7baeb712019-01-04 17:05:43 -08001009 vlsh = vls_create (proto, is_nonblocking);
1010 if (vlsh < 0)
Dave Wallace048b1d62018-01-03 22:24:41 -05001011 {
Florin Coras7baeb712019-01-04 17:05:43 -08001012 errno = -vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001013 rv = -1;
1014 }
1015 else
1016 {
Yu Ping7b74b072019-05-08 00:40:24 +08001017 if (ldp->transparent_tls)
1018 {
Florin Corasa5a9efd2021-01-05 17:03:29 -08001019 if (assign_cert_key_pair (vlsh) < 0)
1020 return -1;
Yu Ping7b74b072019-05-08 00:40:24 +08001021 }
Florin Coras7baeb712019-01-04 17:05:43 -08001022 rv = ldp_vlsh_to_fd (vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05001023 }
1024 }
1025 else
1026 {
Florin Coras7baeb712019-01-04 17:05:43 -08001027 LDBG (0, "calling libc_socket");
Dave Wallace048b1d62018-01-03 22:24:41 -05001028 rv = libc_socket (domain, type, protocol);
1029 }
1030
Dave Wallace048b1d62018-01-03 22:24:41 -05001031 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001032}
1033
1034/*
1035 * Create two new sockets, of type TYPE in domain DOMAIN and using
1036 * protocol PROTOCOL, which are connected to each other, and put file
1037 * descriptors for them in FDS[0] and FDS[1]. If PROTOCOL is zero,
1038 * one will be chosen automatically.
1039 * Returns 0 on success, -1 for errors.
1040 * */
1041int
Dave Wallace048b1d62018-01-03 22:24:41 -05001042socketpair (int domain, int type, int protocol, int fds[2])
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001043{
Florin Coras7baeb712019-01-04 17:05:43 -08001044 int rv, sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
Dave Wallace048b1d62018-01-03 22:24:41 -05001045
Florin Coras5f33d0d2021-06-02 21:22:21 -07001046 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001047
1048 if (((domain == AF_INET) || (domain == AF_INET6)) &&
1049 ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM)))
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001050 {
Florin Coras7baeb712019-01-04 17:05:43 -08001051 LDBG (0, "LDP-TBD");
Dave Wallace048b1d62018-01-03 22:24:41 -05001052 errno = ENOSYS;
1053 rv = -1;
1054 }
1055 else
1056 {
Florin Coras7baeb712019-01-04 17:05:43 -08001057 LDBG (1, "calling libc_socketpair");
Florin Coras173bae32018-11-16 18:56:28 -08001058 rv = libc_socketpair (domain, type, protocol, fds);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001059 }
1060
Dave Wallace048b1d62018-01-03 22:24:41 -05001061 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001062}
1063
1064int
Florin Coras36847942023-02-02 12:56:16 -08001065bind (int fd, __CONST_SOCKADDR_ARG _addr, socklen_t len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001066{
Florin Coras36847942023-02-02 12:56:16 -08001067 const struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
Florin Coras7baeb712019-01-04 17:05:43 -08001068 vls_handle_t vlsh;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001069 int rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001070
Florin Coras5f33d0d2021-06-02 21:22:21 -07001071 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001072
Florin Coras7baeb712019-01-04 17:05:43 -08001073 vlsh = ldp_fd_to_vlsh (fd);
1074 if (vlsh != VLS_INVALID_HANDLE)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001075 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001076 vppcom_endpt_t ep;
1077
Dave Wallace048b1d62018-01-03 22:24:41 -05001078 switch (addr->sa_family)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001079 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001080 case AF_INET:
1081 if (len != sizeof (struct sockaddr_in))
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001082 {
Florin Coras7baeb712019-01-04 17:05:43 -08001083 LDBG (0, "ERROR: fd %d: vlsh %u: Invalid AF_INET addr len %u!",
1084 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001085 errno = EINVAL;
1086 rv = -1;
1087 goto done;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001088 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001089 ep.is_ip4 = VPPCOM_IS_IP4;
1090 ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr;
1091 ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port;
1092 break;
1093
1094 case AF_INET6:
1095 if (len != sizeof (struct sockaddr_in6))
1096 {
Florin Coras7baeb712019-01-04 17:05:43 -08001097 LDBG (0, "ERROR: fd %d: vlsh %u: Invalid AF_INET6 addr len %u!",
1098 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001099 errno = EINVAL;
1100 rv = -1;
1101 goto done;
1102 }
1103 ep.is_ip4 = VPPCOM_IS_IP6;
1104 ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
1105 ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001106 break;
1107
1108 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001109 LDBG (0, "ERROR: fd %d: vlsh %u: Unsupported address family %u!",
1110 fd, vlsh, addr->sa_family);
Dave Wallace048b1d62018-01-03 22:24:41 -05001111 errno = EAFNOSUPPORT;
1112 rv = -1;
1113 goto done;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001114 }
Florin Coras7baeb712019-01-04 17:05:43 -08001115 LDBG (0, "fd %d: calling vls_bind: vlsh %u, addr %p, len %u", fd, vlsh,
1116 addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001117
Florin Coras7baeb712019-01-04 17:05:43 -08001118 rv = vls_bind (vlsh, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001119 if (rv != VPPCOM_OK)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001120 {
1121 errno = -rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001122 rv = -1;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001123 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001124 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001125 else
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001126 {
Florin Coras7baeb712019-01-04 17:05:43 -08001127 LDBG (0, "fd %d: calling libc_bind: addr %p, len %u", fd, addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001128 rv = libc_bind (fd, addr, len);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001129 }
1130
Dave Wallace048b1d62018-01-03 22:24:41 -05001131done:
Florin Coras7baeb712019-01-04 17:05:43 -08001132 LDBG (1, "fd %d: returning %d", fd, rv);
Florin Coras05ecfcc2018-12-12 18:19:39 -08001133
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001134 return rv;
1135}
1136
1137static inline int
Florin Coras36847942023-02-02 12:56:16 -08001138ldp_copy_ep_to_sockaddr (struct sockaddr *addr, socklen_t *__restrict len,
1139 vppcom_endpt_t *ep)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001140{
Florin Coras36847942023-02-02 12:56:16 -08001141 int rv = 0, sa_len, copy_len;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001142
Florin Coras5f33d0d2021-06-02 21:22:21 -07001143 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001144
1145 if (addr && len && ep)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001146 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001147 addr->sa_family = (ep->is_ip4 == VPPCOM_IS_IP4) ? AF_INET : AF_INET6;
1148 switch (addr->sa_family)
1149 {
1150 case AF_INET:
1151 ((struct sockaddr_in *) addr)->sin_port = ep->port;
1152 if (*len > sizeof (struct sockaddr_in))
1153 *len = sizeof (struct sockaddr_in);
1154 sa_len = sizeof (struct sockaddr_in) - sizeof (struct in_addr);
1155 copy_len = *len - sa_len;
1156 if (copy_len > 0)
1157 memcpy (&((struct sockaddr_in *) addr)->sin_addr, ep->ip,
1158 copy_len);
1159 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001160
Dave Wallace048b1d62018-01-03 22:24:41 -05001161 case AF_INET6:
1162 ((struct sockaddr_in6 *) addr)->sin6_port = ep->port;
1163 if (*len > sizeof (struct sockaddr_in6))
1164 *len = sizeof (struct sockaddr_in6);
1165 sa_len = sizeof (struct sockaddr_in6) - sizeof (struct in6_addr);
1166 copy_len = *len - sa_len;
1167 if (copy_len > 0)
1168 memcpy (((struct sockaddr_in6 *) addr)->sin6_addr.
1169 __in6_u.__u6_addr8, ep->ip, copy_len);
1170 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001171
Dave Wallace048b1d62018-01-03 22:24:41 -05001172 default:
1173 /* Not possible */
1174 rv = -EAFNOSUPPORT;
1175 break;
1176 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001177 }
Dave Wallacee695cb42017-11-02 22:04:42 -04001178 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001179}
1180
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001181int
Florin Coras36847942023-02-02 12:56:16 -08001182getsockname (int fd, __SOCKADDR_ARG _addr, socklen_t *__restrict len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001183{
Florin Coras36847942023-02-02 12:56:16 -08001184 struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
Florin Coras7baeb712019-01-04 17:05:43 -08001185 vls_handle_t vlsh;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001186 int rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001187
Florin Coras5f33d0d2021-06-02 21:22:21 -07001188 ldp_init_check ();
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001189
Florin Coras7baeb712019-01-04 17:05:43 -08001190 vlsh = ldp_fd_to_vlsh (fd);
1191 if (vlsh != VLS_INVALID_HANDLE)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001192 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001193 vppcom_endpt_t ep;
1194 u8 addr_buf[sizeof (struct in6_addr)];
1195 u32 size = sizeof (ep);
1196
1197 ep.ip = addr_buf;
Dave Wallace048b1d62018-01-03 22:24:41 -05001198
Florin Coras7baeb712019-01-04 17:05:43 -08001199 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_LCL_ADDR, &ep, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -05001200 if (rv != VPPCOM_OK)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001201 {
1202 errno = -rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001203 rv = -1;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001204 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001205 else
1206 {
Dave Wallace2a865272018-02-07 21:00:42 -05001207 rv = ldp_copy_ep_to_sockaddr (addr, len, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001208 if (rv != VPPCOM_OK)
1209 {
1210 errno = -rv;
1211 rv = -1;
1212 }
1213 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001214 }
1215 else
1216 {
Florin Coras36847942023-02-02 12:56:16 -08001217 rv = libc_getsockname (fd, _addr, len);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001218 }
1219
Dave Wallace048b1d62018-01-03 22:24:41 -05001220 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001221}
1222
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001223int
Florin Coras36847942023-02-02 12:56:16 -08001224connect (int fd, __CONST_SOCKADDR_ARG _addr, socklen_t len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001225{
Florin Coras36847942023-02-02 12:56:16 -08001226 const struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
Florin Coras7baeb712019-01-04 17:05:43 -08001227 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001228 int rv;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001229
Florin Coras5f33d0d2021-06-02 21:22:21 -07001230 ldp_init_check ();
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001231
Dave Wallace048b1d62018-01-03 22:24:41 -05001232 if (!addr)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001233 {
Florin Coras7baeb712019-01-04 17:05:43 -08001234 LDBG (0, "ERROR: fd %d: NULL addr, len %u", fd, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001235 errno = EINVAL;
1236 rv = -1;
1237 goto done;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001238 }
1239
Florin Coras7baeb712019-01-04 17:05:43 -08001240 vlsh = ldp_fd_to_vlsh (fd);
1241 if (vlsh != VLS_INVALID_HANDLE)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001242 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001243 vppcom_endpt_t ep;
1244
Dave Wallace048b1d62018-01-03 22:24:41 -05001245 switch (addr->sa_family)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001246 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001247 case AF_INET:
1248 if (len != sizeof (struct sockaddr_in))
1249 {
Florin Coras7baeb712019-01-04 17:05:43 -08001250 LDBG (0, "fd %d: ERROR vlsh %u: Invalid AF_INET addr len %u!",
1251 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001252 errno = EINVAL;
1253 rv = -1;
1254 goto done;
1255 }
1256 ep.is_ip4 = VPPCOM_IS_IP4;
1257 ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr;
1258 ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port;
1259 break;
1260
1261 case AF_INET6:
1262 if (len != sizeof (struct sockaddr_in6))
1263 {
Florin Coras7baeb712019-01-04 17:05:43 -08001264 LDBG (0, "fd %d: ERROR vlsh %u: Invalid AF_INET6 addr len %u!",
1265 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001266 errno = EINVAL;
1267 rv = -1;
1268 goto done;
1269 }
1270 ep.is_ip4 = VPPCOM_IS_IP6;
1271 ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
1272 ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port;
1273 break;
1274
1275 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001276 LDBG (0, "fd %d: ERROR vlsh %u: Unsupported address family %u!",
1277 fd, vlsh, addr->sa_family);
Dave Wallace048b1d62018-01-03 22:24:41 -05001278 errno = EAFNOSUPPORT;
1279 rv = -1;
1280 goto done;
1281 }
Florin Coras7baeb712019-01-04 17:05:43 -08001282 LDBG (0, "fd %d: calling vls_connect(): vlsh %u addr %p len %u", fd,
1283 vlsh, addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001284
Florin Coras7baeb712019-01-04 17:05:43 -08001285 rv = vls_connect (vlsh, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001286 if (rv != VPPCOM_OK)
1287 {
1288 errno = -rv;
1289 rv = -1;
1290 }
1291 }
1292 else
1293 {
Florin Coras7baeb712019-01-04 17:05:43 -08001294 LDBG (0, "fd %d: calling libc_connect(): addr %p, len %u",
1295 fd, addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001296
1297 rv = libc_connect (fd, addr, len);
1298 }
1299
1300done:
Florin Coras7baeb712019-01-04 17:05:43 -08001301 LDBG (1, "fd %d: returning %d (0x%x)", fd, rv, rv);
Dave Wallace048b1d62018-01-03 22:24:41 -05001302 return rv;
1303}
1304
1305int
Florin Coras36847942023-02-02 12:56:16 -08001306getpeername (int fd, __SOCKADDR_ARG _addr, socklen_t *__restrict len)
Dave Wallace048b1d62018-01-03 22:24:41 -05001307{
Florin Coras36847942023-02-02 12:56:16 -08001308 struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
Florin Coras7baeb712019-01-04 17:05:43 -08001309 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001310 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001311
Florin Coras5f33d0d2021-06-02 21:22:21 -07001312 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001313
Florin Coras7baeb712019-01-04 17:05:43 -08001314 vlsh = ldp_fd_to_vlsh (fd);
1315 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001316 {
1317 vppcom_endpt_t ep;
1318 u8 addr_buf[sizeof (struct in6_addr)];
1319 u32 size = sizeof (ep);
1320
1321 ep.ip = addr_buf;
Florin Coras7baeb712019-01-04 17:05:43 -08001322 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_PEER_ADDR, &ep, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -05001323 if (rv != VPPCOM_OK)
1324 {
1325 errno = -rv;
1326 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001327 }
1328 else
1329 {
Dave Wallace2a865272018-02-07 21:00:42 -05001330 rv = ldp_copy_ep_to_sockaddr (addr, len, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001331 if (rv != VPPCOM_OK)
1332 {
1333 errno = -rv;
1334 rv = -1;
1335 }
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001336 }
1337 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001338 else
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001339 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001340 rv = libc_getpeername (fd, addr, len);
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001341 }
1342
Dave Wallace048b1d62018-01-03 22:24:41 -05001343 return rv;
1344}
1345
1346ssize_t
1347send (int fd, const void *buf, size_t n, int flags)
1348{
Florin Coras7baeb712019-01-04 17:05:43 -08001349 vls_handle_t vlsh = ldp_fd_to_vlsh (fd);
Dave Wallace048b1d62018-01-03 22:24:41 -05001350 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001351
Florin Coras5f33d0d2021-06-02 21:22:21 -07001352 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001353
Florin Coras7baeb712019-01-04 17:05:43 -08001354 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001355 {
Florin Coras7baeb712019-01-04 17:05:43 -08001356 size = vls_sendto (vlsh, (void *) buf, n, flags, NULL);
qchangaa8f63c2018-05-30 11:44:18 -07001357 if (size < VPPCOM_OK)
Dave Wallace048b1d62018-01-03 22:24:41 -05001358 {
1359 errno = -size;
1360 size = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001361 }
1362 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001363 else
1364 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001365 size = libc_send (fd, buf, n, flags);
1366 }
1367
Dave Wallace048b1d62018-01-03 22:24:41 -05001368 return size;
1369}
1370
1371ssize_t
1372sendfile (int out_fd, int in_fd, off_t * offset, size_t len)
1373{
Florin Corasdfe4cf42018-11-28 22:13:45 -08001374 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras7baeb712019-01-04 17:05:43 -08001375 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001376 ssize_t size = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -05001377
Florin Coras5f33d0d2021-06-02 21:22:21 -07001378 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001379
Florin Coras7baeb712019-01-04 17:05:43 -08001380 vlsh = ldp_fd_to_vlsh (out_fd);
1381 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001382 {
1383 int rv;
1384 ssize_t results = 0;
1385 size_t n_bytes_left = len;
1386 size_t bytes_to_read;
1387 int nbytes;
Dave Wallace048b1d62018-01-03 22:24:41 -05001388 u8 eagain = 0;
1389 u32 flags, flags_len = sizeof (flags);
1390
Florin Coras7baeb712019-01-04 17:05:43 -08001391 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_FLAGS, &flags, &flags_len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001392 if (PREDICT_FALSE (rv != VPPCOM_OK))
1393 {
Florin Coras7baeb712019-01-04 17:05:43 -08001394 LDBG (0, "ERROR: out fd %d: vls_attr: vlsh %u, returned %d (%s)!",
1395 out_fd, vlsh, rv, vppcom_retval_str (rv));
Dave Wallace048b1d62018-01-03 22:24:41 -05001396
Florin Corasdfe4cf42018-11-28 22:13:45 -08001397 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001398 errno = -rv;
1399 size = -1;
1400 goto done;
1401 }
1402
1403 if (offset)
1404 {
1405 off_t off = lseek (in_fd, *offset, SEEK_SET);
1406 if (PREDICT_FALSE (off == -1))
1407 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001408 size = -1;
1409 goto done;
1410 }
1411
1412 ASSERT (off == *offset);
1413 }
1414
1415 do
1416 {
Florin Coras7baeb712019-01-04 17:05:43 -08001417 size = vls_attr (vlsh, VPPCOM_ATTR_GET_NWRITE, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05001418 if (size < 0)
1419 {
Florin Coraseb801d02020-09-16 17:44:58 -07001420 LDBG (0, "ERROR: fd %d: vls_attr: vlsh %u returned %ld (%s)!",
Florin Coras7baeb712019-01-04 17:05:43 -08001421 out_fd, vlsh, size, vppcom_retval_str (size));
Florin Corasdfe4cf42018-11-28 22:13:45 -08001422 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001423 errno = -size;
1424 size = -1;
1425 goto done;
1426 }
1427
1428 bytes_to_read = size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001429 if (bytes_to_read == 0)
1430 {
1431 if (flags & O_NONBLOCK)
1432 {
1433 if (!results)
Florin Coras7baeb712019-01-04 17:05:43 -08001434 eagain = 1;
Dave Wallace048b1d62018-01-03 22:24:41 -05001435 goto update_offset;
1436 }
1437 else
1438 continue;
1439 }
1440 bytes_to_read = clib_min (n_bytes_left, bytes_to_read);
Florin Corasdfe4cf42018-11-28 22:13:45 -08001441 vec_validate (ldpw->io_buffer, bytes_to_read);
1442 nbytes = libc_read (in_fd, ldpw->io_buffer, bytes_to_read);
Dave Wallace048b1d62018-01-03 22:24:41 -05001443 if (nbytes < 0)
1444 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001445 if (results == 0)
1446 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08001447 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001448 size = -1;
1449 goto done;
1450 }
1451 goto update_offset;
1452 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001453
Florin Coras7baeb712019-01-04 17:05:43 -08001454 size = vls_write (vlsh, ldpw->io_buffer, nbytes);
Dave Wallace048b1d62018-01-03 22:24:41 -05001455 if (size < 0)
1456 {
1457 if (size == VPPCOM_EAGAIN)
1458 {
1459 if (flags & O_NONBLOCK)
1460 {
1461 if (!results)
Florin Coras7baeb712019-01-04 17:05:43 -08001462 eagain = 1;
Dave Wallace048b1d62018-01-03 22:24:41 -05001463 goto update_offset;
1464 }
1465 else
1466 continue;
1467 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001468 if (results == 0)
1469 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08001470 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001471 errno = -size;
1472 size = -1;
1473 goto done;
1474 }
1475 goto update_offset;
1476 }
1477
1478 results += nbytes;
1479 ASSERT (n_bytes_left >= nbytes);
1480 n_bytes_left = n_bytes_left - nbytes;
1481 }
1482 while (n_bytes_left > 0);
1483
1484 update_offset:
Florin Corasdfe4cf42018-11-28 22:13:45 -08001485 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001486 if (offset)
1487 {
1488 off_t off = lseek (in_fd, *offset, SEEK_SET);
1489 if (PREDICT_FALSE (off == -1))
1490 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001491 size = -1;
1492 goto done;
1493 }
1494
1495 ASSERT (off == *offset);
1496 *offset += results + 1;
1497 }
1498 if (eagain)
1499 {
1500 errno = EAGAIN;
1501 size = -1;
1502 }
1503 else
1504 size = results;
1505 }
1506 else
1507 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001508 size = libc_sendfile (out_fd, in_fd, offset, len);
1509 }
1510
1511done:
Dave Wallace048b1d62018-01-03 22:24:41 -05001512 return size;
1513}
1514
1515ssize_t
1516sendfile64 (int out_fd, int in_fd, off_t * offset, size_t len)
1517{
1518 return sendfile (out_fd, in_fd, offset, len);
1519}
1520
1521ssize_t
1522recv (int fd, void *buf, size_t n, int flags)
1523{
Florin Coras7baeb712019-01-04 17:05:43 -08001524 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001525 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001526
Florin Coras5f33d0d2021-06-02 21:22:21 -07001527 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001528
Florin Coras7baeb712019-01-04 17:05:43 -08001529 vlsh = ldp_fd_to_vlsh (fd);
1530 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001531 {
Florin Coras7baeb712019-01-04 17:05:43 -08001532 size = vls_recvfrom (vlsh, buf, n, flags, NULL);
Dave Wallace048b1d62018-01-03 22:24:41 -05001533 if (size < 0)
Florin Coras2a6642e2020-03-24 15:24:29 +00001534 {
1535 errno = -size;
1536 size = -1;
1537 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001538 }
1539 else
1540 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001541 size = libc_recv (fd, buf, n, flags);
1542 }
1543
Dave Wallace048b1d62018-01-03 22:24:41 -05001544 return size;
1545}
1546
Sivaprasad Tummalafdcbd382021-07-31 21:38:19 +05301547ssize_t
1548__recv_chk (int fd, void *buf, size_t n, size_t buflen, int flags)
1549{
1550 if (n > buflen)
1551 return -1;
1552
1553 return recv (fd, buf, n, flags);
1554}
1555
Dou Chao243a0432022-11-29 19:41:34 +08001556static inline int
1557ldp_vls_sendo (vls_handle_t vlsh, const void *buf, size_t n,
Florin Coraseff5f7a2023-02-07 17:36:17 -08001558 vppcom_endpt_tlv_t *app_tlvs, int flags,
Florin Coras36847942023-02-02 12:56:16 -08001559 __CONST_SOCKADDR_ARG _addr, socklen_t addr_len)
Florin Corasce17f462020-05-22 20:36:29 +00001560{
Florin Coras36847942023-02-02 12:56:16 -08001561 const struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
Florin Corasce17f462020-05-22 20:36:29 +00001562 vppcom_endpt_t *ep = 0;
1563 vppcom_endpt_t _ep;
1564
Florin Coraseff5f7a2023-02-07 17:36:17 -08001565 _ep.app_tlvs = app_tlvs;
Dou Chao243a0432022-11-29 19:41:34 +08001566
Florin Corasce17f462020-05-22 20:36:29 +00001567 if (addr)
1568 {
1569 ep = &_ep;
1570 switch (addr->sa_family)
1571 {
1572 case AF_INET:
1573 ep->is_ip4 = VPPCOM_IS_IP4;
1574 ep->ip =
1575 (uint8_t *) & ((const struct sockaddr_in *) addr)->sin_addr;
1576 ep->port = (uint16_t) ((const struct sockaddr_in *) addr)->sin_port;
1577 break;
1578
1579 case AF_INET6:
1580 ep->is_ip4 = VPPCOM_IS_IP6;
1581 ep->ip =
1582 (uint8_t *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
1583 ep->port =
1584 (uint16_t) ((const struct sockaddr_in6 *) addr)->sin6_port;
1585 break;
1586
1587 default:
1588 return EAFNOSUPPORT;
1589 }
1590 }
1591
1592 return vls_sendto (vlsh, (void *) buf, n, flags, ep);
1593}
1594
1595static int
Florin Coras36847942023-02-02 12:56:16 -08001596ldp_vls_recvfrom (vls_handle_t vlsh, void *__restrict buf, size_t n, int flags,
1597 __SOCKADDR_ARG _addr, socklen_t *__restrict addr_len)
Florin Corasce17f462020-05-22 20:36:29 +00001598{
1599 u8 src_addr[sizeof (struct sockaddr_in6)];
Florin Coras36847942023-02-02 12:56:16 -08001600 struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
Florin Corasce17f462020-05-22 20:36:29 +00001601 vppcom_endpt_t ep;
1602 ssize_t size;
1603 int rv;
1604
1605 if (addr)
1606 {
1607 ep.ip = src_addr;
1608 size = vls_recvfrom (vlsh, buf, n, flags, &ep);
1609
1610 if (size > 0)
1611 {
1612 rv = ldp_copy_ep_to_sockaddr (addr, addr_len, &ep);
1613 if (rv < 0)
1614 size = rv;
1615 }
1616 }
1617 else
1618 size = vls_recvfrom (vlsh, buf, n, flags, NULL);
1619
1620 return size;
1621}
1622
Dave Wallace048b1d62018-01-03 22:24:41 -05001623ssize_t
1624sendto (int fd, const void *buf, size_t n, int flags,
Florin Coras36847942023-02-02 12:56:16 -08001625 __CONST_SOCKADDR_ARG _addr, socklen_t addr_len)
Dave Wallace048b1d62018-01-03 22:24:41 -05001626{
Florin Coras36847942023-02-02 12:56:16 -08001627 const struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
Florin Coras7baeb712019-01-04 17:05:43 -08001628 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001629 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001630
Florin Coras5f33d0d2021-06-02 21:22:21 -07001631 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001632
Florin Coras7baeb712019-01-04 17:05:43 -08001633 vlsh = ldp_fd_to_vlsh (fd);
wanghanlin97c6e0d2021-07-06 15:01:48 +08001634 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001635 {
Dou Chao243a0432022-11-29 19:41:34 +08001636 size = ldp_vls_sendo (vlsh, buf, n, NULL, flags, addr, addr_len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001637 if (size < 0)
1638 {
1639 errno = -size;
1640 size = -1;
1641 }
1642 }
1643 else
1644 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001645 size = libc_sendto (fd, buf, n, flags, addr, addr_len);
1646 }
1647
Dave Wallace048b1d62018-01-03 22:24:41 -05001648 return size;
1649}
1650
1651ssize_t
1652recvfrom (int fd, void *__restrict buf, size_t n, int flags,
1653 __SOCKADDR_ARG addr, socklen_t * __restrict addr_len)
1654{
Florin Corasce17f462020-05-22 20:36:29 +00001655 vls_handle_t vlsh;
1656 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001657
Florin Coras5f33d0d2021-06-02 21:22:21 -07001658 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001659
Florin Corasce17f462020-05-22 20:36:29 +00001660 vlsh = ldp_fd_to_vlsh (fd);
1661 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001662 {
Florin Corasce17f462020-05-22 20:36:29 +00001663 size = ldp_vls_recvfrom (vlsh, buf, n, flags, addr, addr_len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001664 if (size < 0)
1665 {
1666 errno = -size;
1667 size = -1;
1668 }
1669 }
1670 else
1671 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001672 size = libc_recvfrom (fd, buf, n, flags, addr, addr_len);
1673 }
1674
Dave Wallace048b1d62018-01-03 22:24:41 -05001675 return size;
1676}
1677
Florin Coraseff5f7a2023-02-07 17:36:17 -08001678static int
1679ldp_parse_cmsg (vls_handle_t vlsh, const struct msghdr *msg,
1680 vppcom_endpt_tlv_t **app_tlvs)
1681{
1682 uint8_t *ad, *at = (uint8_t *) *app_tlvs;
1683 vppcom_endpt_tlv_t *adh;
1684 struct in_pktinfo *pi;
1685 struct cmsghdr *cmsg;
1686
1687 cmsg = CMSG_FIRSTHDR (msg);
1688
1689 while (cmsg != NULL)
1690 {
1691 switch (cmsg->cmsg_level)
1692 {
1693 case SOL_UDP:
1694 switch (cmsg->cmsg_type)
1695 {
1696 case UDP_SEGMENT:
1697 vec_add2 (at, adh, sizeof (*adh));
1698 adh->data_type = VCL_UDP_SEGMENT;
1699 adh->data_len = sizeof (uint16_t);
1700 vec_add2 (at, ad, sizeof (uint16_t));
1701 *(uint16_t *) ad = *(uint16_t *) CMSG_DATA (cmsg);
1702 break;
1703 default:
1704 LDBG (1, "SOL_UDP cmsg_type %u not supported", cmsg->cmsg_type);
1705 break;
1706 }
1707 break;
1708 case SOL_IP:
1709 switch (cmsg->cmsg_type)
1710 {
1711 case IP_PKTINFO:
1712 vec_add2 (at, adh, sizeof (*adh));
1713 adh->data_type = VCL_IP_PKTINFO;
1714 adh->data_len = sizeof (struct in_addr);
1715 vec_add2 (at, ad, sizeof (struct in_addr));
1716 pi = (void *) CMSG_DATA (cmsg);
1717 clib_memcpy_fast (ad, &pi->ipi_spec_dst,
1718 sizeof (struct in_addr));
1719 break;
1720 default:
1721 LDBG (1, "SOL_IP cmsg_type %u not supported", cmsg->cmsg_type);
1722 break;
1723 }
1724 break;
1725 default:
1726 LDBG (1, "cmsg_level %u not supported", cmsg->cmsg_level);
1727 break;
1728 }
1729 cmsg = CMSG_NXTHDR ((struct msghdr *) msg, cmsg);
1730 }
1731 *app_tlvs = (vppcom_endpt_tlv_t *) at;
1732 return 0;
1733}
1734
1735static int
1736ldp_make_cmsg (vls_handle_t vlsh, struct msghdr *msg)
1737{
1738 u32 optval, optlen = sizeof (optval);
1739 struct cmsghdr *cmsg;
1740
1741 cmsg = CMSG_FIRSTHDR (msg);
1742
1743 if (!vls_attr (vlsh, VPPCOM_ATTR_GET_IP_PKTINFO, (void *) &optval, &optlen))
1744 return 0;
1745
1746 if (optval)
1747 {
1748 vppcom_endpt_t ep;
1749 u8 addr_buf[sizeof (struct in_addr)];
1750 u32 size = sizeof (ep);
1751
1752 ep.ip = addr_buf;
1753
1754 if (!vls_attr (vlsh, VPPCOM_ATTR_GET_LCL_ADDR, &ep, &size))
1755 {
1756 struct in_pktinfo pi = {};
1757
1758 clib_memcpy (&pi.ipi_addr, ep.ip, sizeof (struct in_addr));
1759 cmsg->cmsg_level = SOL_IP;
1760 cmsg->cmsg_type = IP_PKTINFO;
1761 cmsg->cmsg_len = CMSG_LEN (sizeof (pi));
1762 clib_memcpy (CMSG_DATA (cmsg), &pi, sizeof (pi));
1763 }
1764 }
1765
1766 return 0;
1767}
1768
Dave Wallace048b1d62018-01-03 22:24:41 -05001769ssize_t
Florin Corasce17f462020-05-22 20:36:29 +00001770sendmsg (int fd, const struct msghdr * msg, int flags)
Dave Wallace048b1d62018-01-03 22:24:41 -05001771{
Florin Coras7baeb712019-01-04 17:05:43 -08001772 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001773 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001774
Florin Coras5f33d0d2021-06-02 21:22:21 -07001775 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001776
Florin Coras7baeb712019-01-04 17:05:43 -08001777 vlsh = ldp_fd_to_vlsh (fd);
1778 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001779 {
Florin Coraseff5f7a2023-02-07 17:36:17 -08001780 vppcom_endpt_tlv_t *app_tlvs = 0;
Florin Corasce17f462020-05-22 20:36:29 +00001781 struct iovec *iov = msg->msg_iov;
1782 ssize_t total = 0;
Florin Corascba1c222021-11-29 08:12:27 -08001783 int i, rv = 0;
Dou Chao243a0432022-11-29 19:41:34 +08001784
Florin Coraseff5f7a2023-02-07 17:36:17 -08001785 ldp_parse_cmsg (vlsh, msg, &app_tlvs);
Florin Corasce17f462020-05-22 20:36:29 +00001786
1787 for (i = 0; i < msg->msg_iovlen; ++i)
1788 {
Florin Coraseff5f7a2023-02-07 17:36:17 -08001789 rv = ldp_vls_sendo (vlsh, iov[i].iov_base, iov[i].iov_len, app_tlvs,
1790 flags, msg->msg_name, msg->msg_namelen);
Florin Corasce17f462020-05-22 20:36:29 +00001791 if (rv < 0)
1792 break;
1793 else
1794 {
1795 total += rv;
1796 if (rv < iov[i].iov_len)
1797 break;
1798 }
1799 }
1800
Florin Coraseff5f7a2023-02-07 17:36:17 -08001801 vec_free (app_tlvs);
1802
Florin Corasce17f462020-05-22 20:36:29 +00001803 if (rv < 0 && total == 0)
1804 {
1805 errno = -rv;
1806 size = -1;
1807 }
1808 else
1809 size = total;
Dave Wallace048b1d62018-01-03 22:24:41 -05001810 }
1811 else
1812 {
Florin Corasce17f462020-05-22 20:36:29 +00001813 size = libc_sendmsg (fd, msg, flags);
Dave Wallace048b1d62018-01-03 22:24:41 -05001814 }
1815
Dave Wallace048b1d62018-01-03 22:24:41 -05001816 return size;
1817}
1818
Florin Coras36847942023-02-02 12:56:16 -08001819#ifdef _GNU_SOURCE
Dave Wallace048b1d62018-01-03 22:24:41 -05001820int
1821sendmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags)
1822{
1823 ssize_t size;
1824 const char *func_str;
Florin Coras7baeb712019-01-04 17:05:43 -08001825 u32 sh = ldp_fd_to_vlsh (fd);
Dave Wallace048b1d62018-01-03 22:24:41 -05001826
Florin Coras5f33d0d2021-06-02 21:22:21 -07001827 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001828
wanghanlin97c6e0d2021-07-06 15:01:48 +08001829 if (sh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001830 {
1831 clib_warning ("LDP<%d>: LDP-TBD", getpid ());
1832 errno = ENOSYS;
1833 size = -1;
1834 }
1835 else
1836 {
1837 func_str = "libc_sendmmsg";
1838
Dave Wallace2a865272018-02-07 21:00:42 -05001839 if (LDP_DEBUG > 2)
Dave Wallace048b1d62018-01-03 22:24:41 -05001840 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1841 "vmessages %p, vlen %u, flags 0x%x",
1842 getpid (), fd, fd, func_str, vmessages, vlen, flags);
1843
1844 size = libc_sendmmsg (fd, vmessages, vlen, flags);
1845 }
1846
Dave Wallace2a865272018-02-07 21:00:42 -05001847 if (LDP_DEBUG > 2)
Dave Wallace048b1d62018-01-03 22:24:41 -05001848 {
1849 if (size < 0)
1850 {
1851 int errno_val = errno;
1852 perror (func_str);
1853 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1854 "rv %d, errno = %d", getpid (), fd, fd,
1855 func_str, size, errno_val);
1856 errno = errno_val;
1857 }
1858 else
1859 clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1860 getpid (), fd, fd, size, size);
1861 }
1862 return size;
1863}
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001864#endif
1865
Dave Wallace048b1d62018-01-03 22:24:41 -05001866ssize_t
Florin Corasce17f462020-05-22 20:36:29 +00001867recvmsg (int fd, struct msghdr * msg, int flags)
Dave Wallace048b1d62018-01-03 22:24:41 -05001868{
Florin Coras7baeb712019-01-04 17:05:43 -08001869 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001870 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001871
Florin Coras5f33d0d2021-06-02 21:22:21 -07001872 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001873
Florin Coras7baeb712019-01-04 17:05:43 -08001874 vlsh = ldp_fd_to_vlsh (fd);
1875 if (vlsh != VLS_INVALID_HANDLE)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001876 {
Florin Corasce17f462020-05-22 20:36:29 +00001877 struct iovec *iov = msg->msg_iov;
1878 ssize_t max_deq, total = 0;
1879 int i, rv;
1880
1881 max_deq = vls_attr (vlsh, VPPCOM_ATTR_GET_NREAD, 0, 0);
1882 if (!max_deq)
1883 return 0;
1884
1885 for (i = 0; i < msg->msg_iovlen; i++)
1886 {
1887 rv = ldp_vls_recvfrom (vlsh, iov[i].iov_base, iov[i].iov_len, flags,
1888 (i == 0 ? msg->msg_name : NULL),
1889 (i == 0 ? &msg->msg_namelen : NULL));
1890 if (rv <= 0)
1891 break;
1892 else
1893 {
1894 total += rv;
1895 if (rv < iov[i].iov_len)
1896 break;
1897 }
1898 if (total >= max_deq)
1899 break;
1900 }
1901
1902 if (rv < 0 && total == 0)
1903 {
1904 errno = -rv;
1905 size = -1;
1906 }
1907 else
Florin Coraseff5f7a2023-02-07 17:36:17 -08001908 {
1909 if (msg->msg_controllen)
1910 ldp_make_cmsg (vlsh, msg);
1911 size = total;
1912 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001913 }
1914 else
1915 {
Florin Corasce17f462020-05-22 20:36:29 +00001916 size = libc_recvmsg (fd, msg, flags);
Dave Wallace048b1d62018-01-03 22:24:41 -05001917 }
1918
Dave Wallace048b1d62018-01-03 22:24:41 -05001919 return size;
1920}
1921
Florin Coras36847942023-02-02 12:56:16 -08001922#ifdef _GNU_SOURCE
Dave Wallace048b1d62018-01-03 22:24:41 -05001923int
1924recvmmsg (int fd, struct mmsghdr *vmessages,
1925 unsigned int vlen, int flags, struct timespec *tmo)
1926{
Florin Corasf1a232f2023-02-02 22:56:03 -08001927 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
1928 u32 sh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001929
Florin Coras5f33d0d2021-06-02 21:22:21 -07001930 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001931
Florin Corasf1a232f2023-02-02 22:56:03 -08001932 sh = ldp_fd_to_vlsh (fd);
1933
wanghanlin97c6e0d2021-07-06 15:01:48 +08001934 if (sh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001935 {
Florin Corasf1a232f2023-02-02 22:56:03 -08001936 struct mmsghdr *mh;
1937 ssize_t rv = 0;
1938 u32 nvecs = 0;
1939 f64 time_out;
1940
1941 if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
1942 clib_time_init (&ldpw->clib_time);
1943 if (tmo)
1944 {
1945 time_out = (f64) tmo->tv_sec + (f64) tmo->tv_nsec / (f64) 1e9;
1946 time_out += clib_time_now (&ldpw->clib_time);
1947 }
1948 else
1949 {
1950 time_out = (f64) ~0;
1951 }
1952
1953 while (nvecs < vlen)
1954 {
1955 mh = &vmessages[nvecs];
1956 rv = recvmsg (fd, &mh->msg_hdr, flags);
1957 if (rv > 0)
1958 {
1959 mh->msg_len = rv;
1960 nvecs += 1;
1961 continue;
1962 }
1963
1964 if (!time_out || clib_time_now (&ldpw->clib_time) >= time_out)
1965 break;
1966
1967 usleep (1);
1968 }
1969
1970 return nvecs > 0 ? nvecs : rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001971 }
1972 else
1973 {
Florin Corasf1a232f2023-02-02 22:56:03 -08001974 return libc_recvmmsg (fd, vmessages, vlen, flags, tmo);
Dave Wallace048b1d62018-01-03 22:24:41 -05001975 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001976}
1977#endif
1978
1979int
1980getsockopt (int fd, int level, int optname,
1981 void *__restrict optval, socklen_t * __restrict optlen)
1982{
Florin Coras7baeb712019-01-04 17:05:43 -08001983 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001984 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001985
Florin Coras5f33d0d2021-06-02 21:22:21 -07001986 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001987
Florin Coras7baeb712019-01-04 17:05:43 -08001988 vlsh = ldp_fd_to_vlsh (fd);
1989 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001990 {
1991 rv = -EOPNOTSUPP;
1992
1993 switch (level)
1994 {
1995 case SOL_TCP:
1996 switch (optname)
1997 {
1998 case TCP_NODELAY:
Florin Coras7baeb712019-01-04 17:05:43 -08001999 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_NODELAY,
2000 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002001 break;
2002 case TCP_MAXSEG:
Florin Coras7baeb712019-01-04 17:05:43 -08002003 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_USER_MSS,
2004 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002005 break;
2006 case TCP_KEEPIDLE:
Florin Coras7baeb712019-01-04 17:05:43 -08002007 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_KEEPIDLE,
2008 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002009 break;
2010 case TCP_KEEPINTVL:
Florin Coras7baeb712019-01-04 17:05:43 -08002011 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_KEEPINTVL,
2012 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002013 break;
2014 case TCP_INFO:
2015 if (optval && optlen && (*optlen == sizeof (struct tcp_info)))
2016 {
Florin Coras7baeb712019-01-04 17:05:43 -08002017 LDBG (1, "fd %d: vlsh %u SOL_TCP, TCP_INFO, optval %p, "
2018 "optlen %d: #LDP-NOP#", fd, vlsh, optval, *optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002019 memset (optval, 0, *optlen);
2020 rv = VPPCOM_OK;
2021 }
2022 else
2023 rv = -EFAULT;
2024 break;
Florin Coras0ed24e92019-01-21 09:03:10 -08002025 case TCP_CONGESTION:
Florin Coras0ed24e92019-01-21 09:03:10 -08002026 *optlen = strlen ("cubic");
Dave Barach02500902020-04-04 18:34:41 -04002027 strncpy (optval, "cubic", *optlen + 1);
Florin Coras0ed24e92019-01-21 09:03:10 -08002028 rv = 0;
2029 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05002030 default:
Florin Coras7baeb712019-01-04 17:05:43 -08002031 LDBG (0, "ERROR: fd %d: getsockopt SOL_TCP: sid %u, "
2032 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05002033 break;
2034 }
2035 break;
2036 case SOL_IPV6:
2037 switch (optname)
2038 {
2039 case IPV6_V6ONLY:
Florin Coras7baeb712019-01-04 17:05:43 -08002040 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_V6ONLY, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002041 break;
2042 default:
Florin Coras7baeb712019-01-04 17:05:43 -08002043 LDBG (0, "ERROR: fd %d: getsockopt SOL_IPV6: vlsh %u "
2044 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05002045 break;
2046 }
2047 break;
2048 case SOL_SOCKET:
2049 switch (optname)
2050 {
2051 case SO_ACCEPTCONN:
Florin Coras7baeb712019-01-04 17:05:43 -08002052 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_LISTEN, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002053 break;
2054 case SO_KEEPALIVE:
Florin Coras7baeb712019-01-04 17:05:43 -08002055 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_KEEPALIVE, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002056 break;
2057 case SO_PROTOCOL:
Florin Coras7baeb712019-01-04 17:05:43 -08002058 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_PROTOCOL, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002059 *(int *) optval = *(int *) optval ? SOCK_DGRAM : SOCK_STREAM;
2060 break;
2061 case SO_SNDBUF:
Florin Coras7baeb712019-01-04 17:05:43 -08002062 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TX_FIFO_LEN,
2063 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002064 break;
2065 case SO_RCVBUF:
Florin Coras7baeb712019-01-04 17:05:43 -08002066 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_RX_FIFO_LEN,
2067 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002068 break;
2069 case SO_REUSEADDR:
Florin Coras7baeb712019-01-04 17:05:43 -08002070 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_REUSEADDR, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002071 break;
wanghanlin0674f852021-02-22 10:38:36 +08002072 case SO_REUSEPORT:
2073 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_REUSEPORT, optval, optlen);
2074 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05002075 case SO_BROADCAST:
Florin Coras7baeb712019-01-04 17:05:43 -08002076 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_BROADCAST, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002077 break;
wanghanlin0674f852021-02-22 10:38:36 +08002078 case SO_DOMAIN:
2079 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_DOMAIN, optval, optlen);
2080 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05002081 case SO_ERROR:
Florin Coras7baeb712019-01-04 17:05:43 -08002082 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_ERROR, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002083 break;
Florin Coras8eb8d502021-06-16 14:46:57 -07002084 case SO_BINDTODEVICE:
2085 rv = 0;
2086 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05002087 default:
Florin Coras7baeb712019-01-04 17:05:43 -08002088 LDBG (0, "ERROR: fd %d: getsockopt SOL_SOCKET: vlsh %u "
2089 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05002090 break;
2091 }
2092 break;
2093 default:
2094 break;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002095 }
2096
Dave Wallace048b1d62018-01-03 22:24:41 -05002097 if (rv != VPPCOM_OK)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002098 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002099 errno = -rv;
2100 rv = -1;
2101 }
2102 }
2103 else
2104 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002105 rv = libc_getsockopt (fd, level, optname, optval, optlen);
2106 }
2107
Dave Wallace048b1d62018-01-03 22:24:41 -05002108 return rv;
2109}
2110
2111int
2112setsockopt (int fd, int level, int optname,
2113 const void *optval, socklen_t optlen)
2114{
Florin Coras7baeb712019-01-04 17:05:43 -08002115 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002116 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05002117
Florin Coras5f33d0d2021-06-02 21:22:21 -07002118 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05002119
Florin Coras7baeb712019-01-04 17:05:43 -08002120 vlsh = ldp_fd_to_vlsh (fd);
2121 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05002122 {
2123 rv = -EOPNOTSUPP;
2124
2125 switch (level)
2126 {
2127 case SOL_TCP:
2128 switch (optname)
2129 {
2130 case TCP_NODELAY:
Florin Coras7baeb712019-01-04 17:05:43 -08002131 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_NODELAY,
2132 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002133 break;
2134 case TCP_MAXSEG:
Florin Coras7baeb712019-01-04 17:05:43 -08002135 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_USER_MSS,
2136 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002137 break;
2138 case TCP_KEEPIDLE:
Florin Coras7baeb712019-01-04 17:05:43 -08002139 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_KEEPIDLE,
2140 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002141 break;
2142 case TCP_KEEPINTVL:
Florin Coras7baeb712019-01-04 17:05:43 -08002143 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_KEEPINTVL,
2144 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002145 break;
Florin Coras0ed24e92019-01-21 09:03:10 -08002146 case TCP_CONGESTION:
Florin Coras8509aa22019-04-04 12:55:30 -07002147 case TCP_CORK:
Florin Coras0ed24e92019-01-21 09:03:10 -08002148 /* Ignore */
2149 rv = 0;
2150 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05002151 default:
Florin Coras7baeb712019-01-04 17:05:43 -08002152 LDBG (0, "ERROR: fd %d: setsockopt() SOL_TCP: vlsh %u"
2153 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05002154 break;
2155 }
2156 break;
2157 case SOL_IPV6:
2158 switch (optname)
2159 {
2160 case IPV6_V6ONLY:
Florin Coras7baeb712019-01-04 17:05:43 -08002161 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_V6ONLY,
2162 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002163 break;
2164 default:
Florin Coras7baeb712019-01-04 17:05:43 -08002165 LDBG (0, "ERROR: fd %d: setsockopt SOL_IPV6: vlsh %u"
2166 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05002167 break;
2168 }
2169 break;
2170 case SOL_SOCKET:
2171 switch (optname)
2172 {
2173 case SO_KEEPALIVE:
Florin Coras7baeb712019-01-04 17:05:43 -08002174 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_KEEPALIVE,
2175 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002176 break;
2177 case SO_REUSEADDR:
Florin Coras7baeb712019-01-04 17:05:43 -08002178 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_REUSEADDR,
2179 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002180 break;
wanghanlin0674f852021-02-22 10:38:36 +08002181 case SO_REUSEPORT:
2182 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_REUSEPORT, (void *) optval,
2183 &optlen);
2184 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05002185 case SO_BROADCAST:
Florin Coras7baeb712019-01-04 17:05:43 -08002186 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_BROADCAST,
2187 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002188 break;
Florin Coras2f647902021-06-02 08:23:50 -07002189 case SO_LINGER:
2190 rv = 0;
2191 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05002192 default:
Florin Coras7baeb712019-01-04 17:05:43 -08002193 LDBG (0, "ERROR: fd %d: setsockopt SOL_SOCKET: vlsh %u "
2194 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05002195 break;
2196 }
2197 break;
Florin Coraseff5f7a2023-02-07 17:36:17 -08002198 case SOL_IP:
2199 switch (optname)
2200 {
2201 case IP_PKTINFO:
2202 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_IP_PKTINFO, (void *) optval,
2203 &optlen);
2204 break;
2205 default:
2206 LDBG (0,
2207 "ERROR: fd %d: setsockopt SOL_IP: vlsh %u optname %d"
2208 "unsupported!",
2209 fd, vlsh, optname);
2210 break;
2211 }
2212 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05002213 default:
2214 break;
2215 }
2216
2217 if (rv != VPPCOM_OK)
2218 {
2219 errno = -rv;
2220 rv = -1;
2221 }
2222 }
2223 else
2224 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002225 rv = libc_setsockopt (fd, level, optname, optval, optlen);
2226 }
2227
Dave Wallace048b1d62018-01-03 22:24:41 -05002228 return rv;
2229}
2230
2231int
2232listen (int fd, int n)
2233{
Florin Coras7baeb712019-01-04 17:05:43 -08002234 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002235 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05002236
Florin Coras5f33d0d2021-06-02 21:22:21 -07002237 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05002238
Florin Coras7baeb712019-01-04 17:05:43 -08002239 vlsh = ldp_fd_to_vlsh (fd);
2240 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05002241 {
Florin Coras7baeb712019-01-04 17:05:43 -08002242 LDBG (0, "fd %d: calling vls_listen: vlsh %u, n %d", fd, vlsh, n);
Dave Wallace048b1d62018-01-03 22:24:41 -05002243
Florin Coras7baeb712019-01-04 17:05:43 -08002244 rv = vls_listen (vlsh, n);
Dave Wallace048b1d62018-01-03 22:24:41 -05002245 if (rv != VPPCOM_OK)
2246 {
2247 errno = -rv;
2248 rv = -1;
2249 }
2250 }
2251 else
2252 {
Florin Coras7baeb712019-01-04 17:05:43 -08002253 LDBG (0, "fd %d: calling libc_listen(): n %d", fd, n);
Dave Wallace048b1d62018-01-03 22:24:41 -05002254 rv = libc_listen (fd, n);
2255 }
2256
Florin Coras7baeb712019-01-04 17:05:43 -08002257 LDBG (1, "fd %d: returning %d", fd, rv);
Dave Wallace048b1d62018-01-03 22:24:41 -05002258 return rv;
2259}
2260
2261static inline int
Florin Coras36847942023-02-02 12:56:16 -08002262ldp_accept4 (int listen_fd, __SOCKADDR_ARG _addr,
2263 socklen_t *__restrict addr_len, int flags)
Dave Wallace048b1d62018-01-03 22:24:41 -05002264{
Florin Coras36847942023-02-02 12:56:16 -08002265 struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
Florin Coras7baeb712019-01-04 17:05:43 -08002266 vls_handle_t listen_vlsh, accept_vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002267 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05002268
Florin Coras5f33d0d2021-06-02 21:22:21 -07002269 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05002270
Florin Coras7baeb712019-01-04 17:05:43 -08002271 listen_vlsh = ldp_fd_to_vlsh (listen_fd);
2272 if (listen_vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05002273 {
2274 vppcom_endpt_t ep;
2275 u8 src_addr[sizeof (struct sockaddr_in6)];
Dave Wallace8aaba562018-01-18 17:21:19 -05002276 memset (&ep, 0, sizeof (ep));
Dave Wallace048b1d62018-01-03 22:24:41 -05002277 ep.ip = src_addr;
2278
Florin Coras7baeb712019-01-04 17:05:43 -08002279 LDBG (0, "listen fd %d: calling vppcom_session_accept: listen sid %u,"
Florin Coraseb801d02020-09-16 17:44:58 -07002280 " ep %p, flags 0x%x", listen_fd, listen_vlsh, &ep, flags);
Dave Wallace048b1d62018-01-03 22:24:41 -05002281
Florin Coras7baeb712019-01-04 17:05:43 -08002282 accept_vlsh = vls_accept (listen_vlsh, &ep, flags);
2283 if (accept_vlsh < 0)
Dave Wallace048b1d62018-01-03 22:24:41 -05002284 {
Florin Coras7baeb712019-01-04 17:05:43 -08002285 errno = -accept_vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002286 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002287 }
2288 else
2289 {
Dave Wallace2a865272018-02-07 21:00:42 -05002290 rv = ldp_copy_ep_to_sockaddr (addr, addr_len, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05002291 if (rv != VPPCOM_OK)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002292 {
Florin Coras7baeb712019-01-04 17:05:43 -08002293 (void) vls_close (accept_vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05002294 errno = -rv;
2295 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002296 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002297 else
2298 {
Florin Coras7baeb712019-01-04 17:05:43 -08002299 rv = ldp_vlsh_to_fd (accept_vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05002300 }
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002301 }
2302 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002303 else
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002304 {
Florin Coras7baeb712019-01-04 17:05:43 -08002305 LDBG (0, "listen fd %d: calling libc_accept4(): addr %p, addr_len %p,"
2306 " flags 0x%x", listen_fd, addr, addr_len, flags);
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002307
Dave Wallace048b1d62018-01-03 22:24:41 -05002308 rv = libc_accept4 (listen_fd, addr, addr_len, flags);
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002309 }
2310
Florin Coras7baeb712019-01-04 17:05:43 -08002311 LDBG (1, "listen fd %d: accept returning %d", listen_fd, rv);
Florin Coras05ecfcc2018-12-12 18:19:39 -08002312
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002313 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002314}
2315
Dave Wallace048b1d62018-01-03 22:24:41 -05002316int
2317accept4 (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len,
2318 int flags)
2319{
Dave Wallace2a865272018-02-07 21:00:42 -05002320 return ldp_accept4 (fd, addr, addr_len, flags);
Dave Wallace048b1d62018-01-03 22:24:41 -05002321}
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002322
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002323int
Dave Wallace048b1d62018-01-03 22:24:41 -05002324accept (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002325{
Dave Wallace2a865272018-02-07 21:00:42 -05002326 return ldp_accept4 (fd, addr, addr_len, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002327}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002328
Dave Wallace048b1d62018-01-03 22:24:41 -05002329int
2330shutdown (int fd, int how)
2331{
Florin Coras7baeb712019-01-04 17:05:43 -08002332 vls_handle_t vlsh;
liuyacan55c952e2021-06-13 14:54:55 +08002333 int rv = 0;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002334
Florin Coras5f33d0d2021-06-02 21:22:21 -07002335 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05002336
Florin Coras7baeb712019-01-04 17:05:43 -08002337 vlsh = ldp_fd_to_vlsh (fd);
2338 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05002339 {
Florin Coras7baeb712019-01-04 17:05:43 -08002340 LDBG (0, "called shutdown: fd %u vlsh %u how %d", fd, vlsh, how);
liuyacan55c952e2021-06-13 14:54:55 +08002341 rv = vls_shutdown (vlsh, how);
Dave Wallace048b1d62018-01-03 22:24:41 -05002342 }
2343 else
2344 {
Florin Coras7baeb712019-01-04 17:05:43 -08002345 LDBG (0, "fd %d: calling libc_shutdown: how %d", fd, how);
Dave Wallace048b1d62018-01-03 22:24:41 -05002346 rv = libc_shutdown (fd, how);
2347 }
2348
Dave Wallace048b1d62018-01-03 22:24:41 -05002349 return rv;
2350}
2351
2352int
2353epoll_create1 (int flags)
2354{
Florin Corasdfe4cf42018-11-28 22:13:45 -08002355 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras7baeb712019-01-04 17:05:43 -08002356 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002357 int rv;
2358
Florin Coras5f33d0d2021-06-02 21:22:21 -07002359 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05002360
hanlina3a48962020-07-13 11:09:15 +08002361 if (ldp->vcl_needs_real_epoll || vls_use_real_epoll ())
Florin Coras99368312018-08-02 10:45:44 -07002362 {
Florin Coras2d9b4272019-03-11 10:14:37 -07002363 /* Make sure workers have been allocated */
2364 if (!ldp->workers)
2365 {
2366 ldp_alloc_workers ();
2367 ldpw = ldp_worker_get_current ();
2368 }
Florin Coras99368312018-08-02 10:45:44 -07002369 rv = libc_epoll_create1 (flags);
2370 ldp->vcl_needs_real_epoll = 0;
Florin Corasdfe4cf42018-11-28 22:13:45 -08002371 ldpw->vcl_mq_epfd = rv;
Florin Coras05ecfcc2018-12-12 18:19:39 -08002372 LDBG (0, "created vcl epfd %u", rv);
Florin Coras99368312018-08-02 10:45:44 -07002373 return rv;
2374 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002375
Florin Coras7baeb712019-01-04 17:05:43 -08002376 vlsh = vls_epoll_create ();
2377 if (PREDICT_FALSE (vlsh == VLS_INVALID_HANDLE))
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002378 {
Florin Coras7baeb712019-01-04 17:05:43 -08002379 errno = -vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002380 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002381 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002382 else
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002383 {
Florin Coras7baeb712019-01-04 17:05:43 -08002384 rv = ldp_vlsh_to_fd (vlsh);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002385 }
Florin Coras7baeb712019-01-04 17:05:43 -08002386 LDBG (0, "epoll_create epfd %u vlsh %u", rv, vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05002387 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002388}
2389
2390int
Dave Wallace048b1d62018-01-03 22:24:41 -05002391epoll_create (int size)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002392{
Dave Wallace048b1d62018-01-03 22:24:41 -05002393 return epoll_create1 (0);
2394}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002395
Dave Wallace048b1d62018-01-03 22:24:41 -05002396int
2397epoll_ctl (int epfd, int op, int fd, struct epoll_event *event)
2398{
Florin Coras7baeb712019-01-04 17:05:43 -08002399 vls_handle_t vep_vlsh, vlsh;
Florin Coras99368312018-08-02 10:45:44 -07002400 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05002401
Florin Coras5f33d0d2021-06-02 21:22:21 -07002402 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05002403
Florin Coras7baeb712019-01-04 17:05:43 -08002404 vep_vlsh = ldp_fd_to_vlsh (epfd);
2405 if (PREDICT_FALSE (vep_vlsh == VLS_INVALID_HANDLE))
Dave Wallace048b1d62018-01-03 22:24:41 -05002406 {
Dave Wallace3ee1fe12018-02-23 01:09:11 -05002407 /* The LDP epoll_create1 always creates VCL epfd's.
2408 * The app should never have a kernel base epoll fd unless it
2409 * was acquired outside of the LD_PRELOAD process context.
2410 * In any case, if we get one, punt it to libc_epoll_ctl.
2411 */
Florin Coras7baeb712019-01-04 17:05:43 -08002412 LDBG (1, "epfd %d: calling libc_epoll_ctl: op %d, fd %d"
2413 " event %p", epfd, op, fd, event);
Dave Wallace048b1d62018-01-03 22:24:41 -05002414
2415 rv = libc_epoll_ctl (epfd, op, fd, event);
Florin Coras99368312018-08-02 10:45:44 -07002416 goto done;
2417 }
2418
Florin Coras7baeb712019-01-04 17:05:43 -08002419 vlsh = ldp_fd_to_vlsh (fd);
Florin Coras99368312018-08-02 10:45:44 -07002420
Florin Coras7baeb712019-01-04 17:05:43 -08002421 LDBG (0, "epfd %d ep_vlsh %d, fd %u vlsh %d, op %u", epfd, vep_vlsh, fd,
2422 vlsh, op);
Florin Coras99368312018-08-02 10:45:44 -07002423
Florin Coras7baeb712019-01-04 17:05:43 -08002424 if (vlsh != VLS_INVALID_HANDLE)
Florin Coras99368312018-08-02 10:45:44 -07002425 {
Florin Coras7baeb712019-01-04 17:05:43 -08002426 LDBG (1, "epfd %d: calling vls_epoll_ctl: ep_vlsh %d op %d, vlsh %u,"
Florin Coraseb801d02020-09-16 17:44:58 -07002427 " event %p", epfd, vep_vlsh, op, vlsh, event);
Florin Coras99368312018-08-02 10:45:44 -07002428
Florin Coras7baeb712019-01-04 17:05:43 -08002429 rv = vls_epoll_ctl (vep_vlsh, op, vlsh, event);
Florin Coras99368312018-08-02 10:45:44 -07002430 if (rv != VPPCOM_OK)
2431 {
2432 errno = -rv;
2433 rv = -1;
2434 }
2435 }
2436 else
2437 {
2438 int libc_epfd;
2439 u32 size = sizeof (epfd);
2440
Florin Coras7baeb712019-01-04 17:05:43 -08002441 libc_epfd = vls_attr (vep_vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
Florin Coras99368312018-08-02 10:45:44 -07002442 if (!libc_epfd)
2443 {
Florin Coras7baeb712019-01-04 17:05:43 -08002444 LDBG (1, "epfd %d, vep_vlsh %d calling libc_epoll_create1: "
2445 "EPOLL_CLOEXEC", epfd, vep_vlsh);
Florin Coras99368312018-08-02 10:45:44 -07002446
2447 libc_epfd = libc_epoll_create1 (EPOLL_CLOEXEC);
2448 if (libc_epfd < 0)
2449 {
2450 rv = libc_epfd;
2451 goto done;
2452 }
2453
Florin Coras7baeb712019-01-04 17:05:43 -08002454 rv = vls_attr (vep_vlsh, VPPCOM_ATTR_SET_LIBC_EPFD, &libc_epfd,
2455 &size);
Florin Coras99368312018-08-02 10:45:44 -07002456 if (rv < 0)
2457 {
2458 errno = -rv;
2459 rv = -1;
2460 goto done;
2461 }
2462 }
2463 else if (PREDICT_FALSE (libc_epfd < 0))
2464 {
2465 errno = -epfd;
2466 rv = -1;
2467 goto done;
2468 }
2469
Florin Coras7baeb712019-01-04 17:05:43 -08002470 LDBG (1, "epfd %d: calling libc_epoll_ctl: libc_epfd %d, op %d, fd %d,"
2471 " event %p", epfd, libc_epfd, op, fd, event);
Florin Coras99368312018-08-02 10:45:44 -07002472
2473 rv = libc_epoll_ctl (libc_epfd, op, fd, event);
Dave Wallace048b1d62018-01-03 22:24:41 -05002474 }
2475
2476done:
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002477 return rv;
2478}
Dave Wallace048b1d62018-01-03 22:24:41 -05002479
2480static inline int
Florin Coras99368312018-08-02 10:45:44 -07002481ldp_epoll_pwait (int epfd, struct epoll_event *events, int maxevents,
2482 int timeout, const sigset_t * sigmask)
Dave Wallace048b1d62018-01-03 22:24:41 -05002483{
Liangxing Wang7c7231f2023-02-16 09:31:01 +00002484 ldp_worker_ctx_t *ldpw;
Florin Coras72f77822019-01-22 19:05:52 -08002485 double time_to_wait = (double) 0, max_time;
Florin Coras99368312018-08-02 10:45:44 -07002486 int libc_epfd, rv = 0;
Florin Coras7baeb712019-01-04 17:05:43 -08002487 vls_handle_t ep_vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002488
Florin Coras5f33d0d2021-06-02 21:22:21 -07002489 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05002490
2491 if (PREDICT_FALSE (!events || (timeout < -1)))
2492 {
2493 errno = EFAULT;
2494 return -1;
2495 }
2496
Liangxing Wang7c7231f2023-02-16 09:31:01 +00002497 if (PREDICT_FALSE (vppcom_worker_index () == ~0))
2498 vls_register_vcl_worker ();
2499
2500 ldpw = ldp_worker_get_current ();
Florin Corasdfe4cf42018-11-28 22:13:45 -08002501 if (epfd == ldpw->vcl_mq_epfd)
Florin Coras99368312018-08-02 10:45:44 -07002502 return libc_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
2503
Florin Coras7baeb712019-01-04 17:05:43 -08002504 ep_vlsh = ldp_fd_to_vlsh (epfd);
2505 if (PREDICT_FALSE (ep_vlsh == VLS_INVALID_HANDLE))
Dave Wallace048b1d62018-01-03 22:24:41 -05002506 {
Florin Coras7baeb712019-01-04 17:05:43 -08002507 LDBG (0, "epfd %d: bad ep_vlsh %d!", epfd, ep_vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05002508 errno = EBADFD;
2509 return -1;
2510 }
2511
Florin Coras4dee8cd2019-01-29 21:28:16 -08002512 if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
2513 clib_time_init (&ldpw->clib_time);
Florin Corasb0f662f2018-12-27 14:51:46 -08002514 time_to_wait = ((timeout >= 0) ? (double) timeout / 1000 : 0);
Florin Coras72f77822019-01-22 19:05:52 -08002515 max_time = clib_time_now (&ldpw->clib_time) + time_to_wait;
Dave Wallace048b1d62018-01-03 22:24:41 -05002516
Florin Coras7baeb712019-01-04 17:05:43 -08002517 libc_epfd = vls_attr (ep_vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002518 if (PREDICT_FALSE (libc_epfd < 0))
2519 {
2520 errno = -libc_epfd;
2521 rv = -1;
2522 goto done;
2523 }
2524
Florin Coras7baeb712019-01-04 17:05:43 -08002525 LDBG (2, "epfd %d: vep_idx %d, libc_epfd %d, events %p, maxevents %d, "
2526 "timeout %d, sigmask %p: time_to_wait %.02f", epfd, ep_vlsh,
Florin Coras72f77822019-01-22 19:05:52 -08002527 libc_epfd, events, maxevents, timeout, sigmask, time_to_wait);
Dave Wallace048b1d62018-01-03 22:24:41 -05002528 do
2529 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002530 if (!ldpw->epoll_wait_vcl)
Dave Wallace048b1d62018-01-03 22:24:41 -05002531 {
Florin Coras7baeb712019-01-04 17:05:43 -08002532 rv = vls_epoll_wait (ep_vlsh, events, maxevents, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002533 if (rv > 0)
2534 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002535 ldpw->epoll_wait_vcl = 1;
Dave Wallace048b1d62018-01-03 22:24:41 -05002536 goto done;
2537 }
2538 else if (rv < 0)
2539 {
2540 errno = -rv;
2541 rv = -1;
2542 goto done;
2543 }
2544 }
2545 else
Florin Corasdfe4cf42018-11-28 22:13:45 -08002546 ldpw->epoll_wait_vcl = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -05002547
2548 if (libc_epfd > 0)
2549 {
Florin Corasb0f662f2018-12-27 14:51:46 -08002550 rv = libc_epoll_pwait (libc_epfd, events, maxevents, 0, sigmask);
Dave Wallace048b1d62018-01-03 22:24:41 -05002551 if (rv != 0)
2552 goto done;
2553 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002554 }
Florin Coras72f77822019-01-22 19:05:52 -08002555 while ((timeout == -1) || (clib_time_now (&ldpw->clib_time) < max_time));
Dave Wallace048b1d62018-01-03 22:24:41 -05002556
2557done:
Dave Wallace048b1d62018-01-03 22:24:41 -05002558 return rv;
2559}
2560
hanlin4266d4d2020-05-19 17:34:17 +08002561static inline int
2562ldp_epoll_pwait_eventfd (int epfd, struct epoll_event *events,
2563 int maxevents, int timeout, const sigset_t * sigmask)
2564{
hanlina3a48962020-07-13 11:09:15 +08002565 ldp_worker_ctx_t *ldpw;
hanlin4266d4d2020-05-19 17:34:17 +08002566 int libc_epfd, rv = 0, num_ev;
2567 vls_handle_t ep_vlsh;
2568
Florin Coras5f33d0d2021-06-02 21:22:21 -07002569 ldp_init_check ();
hanlin4266d4d2020-05-19 17:34:17 +08002570
2571 if (PREDICT_FALSE (!events || (timeout < -1)))
2572 {
2573 errno = EFAULT;
2574 return -1;
2575 }
2576
Florin Corasff40d8f2020-08-11 22:05:28 -07002577 /* Make sure the vcl worker is valid. Could be that epoll fd was created on
2578 * one thread but it is now used on another */
2579 if (PREDICT_FALSE (vppcom_worker_index () == ~0))
2580 vls_register_vcl_worker ();
hanlina3a48962020-07-13 11:09:15 +08002581
2582 ldpw = ldp_worker_get_current ();
hanlin4266d4d2020-05-19 17:34:17 +08002583 if (epfd == ldpw->vcl_mq_epfd)
2584 return libc_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
2585
2586 ep_vlsh = ldp_fd_to_vlsh (epfd);
2587 if (PREDICT_FALSE (ep_vlsh == VLS_INVALID_HANDLE))
2588 {
2589 LDBG (0, "epfd %d: bad ep_vlsh %d!", epfd, ep_vlsh);
2590 errno = EBADFD;
2591 return -1;
2592 }
2593
2594 libc_epfd = vls_attr (ep_vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
2595 if (PREDICT_FALSE (!libc_epfd))
2596 {
2597 u32 size = sizeof (epfd);
2598
2599 LDBG (1, "epfd %d, vep_vlsh %d calling libc_epoll_create1: "
2600 "EPOLL_CLOEXEC", epfd, ep_vlsh);
2601 libc_epfd = libc_epoll_create1 (EPOLL_CLOEXEC);
2602 if (libc_epfd < 0)
2603 {
2604 rv = libc_epfd;
2605 goto done;
2606 }
2607
2608 rv = vls_attr (ep_vlsh, VPPCOM_ATTR_SET_LIBC_EPFD, &libc_epfd, &size);
2609 if (rv < 0)
2610 {
2611 errno = -rv;
2612 rv = -1;
2613 goto done;
2614 }
2615 }
2616 if (PREDICT_FALSE (libc_epfd <= 0))
2617 {
2618 errno = -libc_epfd;
2619 rv = -1;
2620 goto done;
2621 }
2622
2623 if (PREDICT_FALSE (!ldpw->mq_epfd_added))
2624 {
2625 struct epoll_event e = { 0 };
2626 e.events = EPOLLIN;
2627 e.data.fd = ldpw->vcl_mq_epfd;
2628 if (libc_epoll_ctl (libc_epfd, EPOLL_CTL_ADD, ldpw->vcl_mq_epfd, &e) <
2629 0)
2630 {
2631 LDBG (0, "epfd %d, add libc mq epoll fd %d to libc epoll fd %d",
2632 epfd, ldpw->vcl_mq_epfd, libc_epfd);
2633 rv = -1;
2634 goto done;
2635 }
2636 ldpw->mq_epfd_added = 1;
2637 }
2638
wanghanlin8919fec2021-03-18 20:00:41 +08002639 /* Request to only drain unhandled to prevent libc_epoll_wait starved */
2640 rv = vls_epoll_wait (ep_vlsh, events, maxevents, -2);
hanlin4266d4d2020-05-19 17:34:17 +08002641 if (rv > 0)
2642 goto done;
hanlina3a48962020-07-13 11:09:15 +08002643 else if (PREDICT_FALSE (rv < 0))
hanlin4266d4d2020-05-19 17:34:17 +08002644 {
2645 errno = -rv;
2646 rv = -1;
2647 goto done;
2648 }
2649
2650 rv = libc_epoll_pwait (libc_epfd, events, maxevents, timeout, sigmask);
2651 if (rv <= 0)
2652 goto done;
2653 for (int i = 0; i < rv; i++)
2654 {
2655 if (events[i].data.fd == ldpw->vcl_mq_epfd)
2656 {
2657 /* We should remove mq epoll fd from events. */
2658 rv--;
2659 if (i != rv)
2660 {
2661 events[i].events = events[rv].events;
2662 events[i].data.u64 = events[rv].data.u64;
2663 }
2664 num_ev = vls_epoll_wait (ep_vlsh, &events[rv], maxevents - rv, 0);
2665 if (PREDICT_TRUE (num_ev > 0))
2666 rv += num_ev;
2667 break;
2668 }
2669 }
2670
2671done:
2672 return rv;
2673}
2674
Dave Wallace048b1d62018-01-03 22:24:41 -05002675int
2676epoll_pwait (int epfd, struct epoll_event *events,
2677 int maxevents, int timeout, const sigset_t * sigmask)
2678{
hanlin4266d4d2020-05-19 17:34:17 +08002679 if (vls_use_eventfd ())
2680 return ldp_epoll_pwait_eventfd (epfd, events, maxevents, timeout,
2681 sigmask);
2682 else
2683 return ldp_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
Dave Wallace048b1d62018-01-03 22:24:41 -05002684}
2685
2686int
2687epoll_wait (int epfd, struct epoll_event *events, int maxevents, int timeout)
2688{
hanlin4266d4d2020-05-19 17:34:17 +08002689 if (vls_use_eventfd ())
2690 return ldp_epoll_pwait_eventfd (epfd, events, maxevents, timeout, NULL);
2691 else
2692 return ldp_epoll_pwait (epfd, events, maxevents, timeout, NULL);
Dave Wallace048b1d62018-01-03 22:24:41 -05002693}
2694
2695int
2696poll (struct pollfd *fds, nfds_t nfds, int timeout)
2697{
Florin Corasdfe4cf42018-11-28 22:13:45 -08002698 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras6917b942018-11-13 22:44:54 -08002699 int rv, i, n_revents = 0;
Florin Coras7baeb712019-01-04 17:05:43 -08002700 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002701 vcl_poll_t *vp;
Florin Coras4dee8cd2019-01-29 21:28:16 -08002702 double max_time;
Dave Wallace048b1d62018-01-03 22:24:41 -05002703
Florin Coraseb801d02020-09-16 17:44:58 -07002704 LDBG (3, "fds %p, nfds %ld, timeout %d", fds, nfds, timeout);
Dave Wallace048b1d62018-01-03 22:24:41 -05002705
Florin Coras4dee8cd2019-01-29 21:28:16 -08002706 if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
2707 clib_time_init (&ldpw->clib_time);
2708
2709 max_time = (timeout >= 0) ? (f64) timeout / 1000 : 0;
2710 max_time += clib_time_now (&ldpw->clib_time);
Dave Wallace048b1d62018-01-03 22:24:41 -05002711
Dave Wallace048b1d62018-01-03 22:24:41 -05002712 for (i = 0; i < nfds; i++)
2713 {
Florin Coras6917b942018-11-13 22:44:54 -08002714 if (fds[i].fd < 0)
2715 continue;
Dave Wallace048b1d62018-01-03 22:24:41 -05002716
Florin Coras7baeb712019-01-04 17:05:43 -08002717 vlsh = ldp_fd_to_vlsh (fds[i].fd);
2718 if (vlsh != VLS_INVALID_HANDLE)
Florin Coras6917b942018-11-13 22:44:54 -08002719 {
2720 fds[i].fd = -fds[i].fd;
Florin Corasdfe4cf42018-11-28 22:13:45 -08002721 vec_add2 (ldpw->vcl_poll, vp, 1);
Florin Coras6917b942018-11-13 22:44:54 -08002722 vp->fds_ndx = i;
Florin Coras7baeb712019-01-04 17:05:43 -08002723 vp->sh = vlsh_to_sh (vlsh);
Florin Coras6917b942018-11-13 22:44:54 -08002724 vp->events = fds[i].events;
Dave Wallace048b1d62018-01-03 22:24:41 -05002725#ifdef __USE_XOPEN2K
Florin Coras6917b942018-11-13 22:44:54 -08002726 if (fds[i].events & POLLRDNORM)
2727 vp->events |= POLLIN;
2728 if (fds[i].events & POLLWRNORM)
2729 vp->events |= POLLOUT;
Dave Wallace048b1d62018-01-03 22:24:41 -05002730#endif
Florin Coras6917b942018-11-13 22:44:54 -08002731 vp->revents = fds[i].revents;
2732 }
2733 else
2734 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002735 vec_add1 (ldpw->libc_poll, fds[i]);
2736 vec_add1 (ldpw->libc_poll_idxs, i);
Dave Wallace048b1d62018-01-03 22:24:41 -05002737 }
2738 }
2739
Dave Wallace048b1d62018-01-03 22:24:41 -05002740 do
2741 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002742 if (vec_len (ldpw->vcl_poll))
Dave Wallace048b1d62018-01-03 22:24:41 -05002743 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002744 rv = vppcom_poll (ldpw->vcl_poll, vec_len (ldpw->vcl_poll), 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002745 if (rv < 0)
2746 {
2747 errno = -rv;
2748 rv = -1;
2749 goto done;
2750 }
2751 else
2752 n_revents += rv;
2753 }
2754
Florin Corasdfe4cf42018-11-28 22:13:45 -08002755 if (vec_len (ldpw->libc_poll))
Dave Wallace048b1d62018-01-03 22:24:41 -05002756 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002757 rv = libc_poll (ldpw->libc_poll, vec_len (ldpw->libc_poll), 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002758 if (rv < 0)
2759 goto done;
2760 else
2761 n_revents += rv;
2762 }
2763
2764 if (n_revents)
2765 {
2766 rv = n_revents;
2767 goto done;
2768 }
2769 }
Florin Coras4dee8cd2019-01-29 21:28:16 -08002770 while ((timeout < 0) || (clib_time_now (&ldpw->clib_time) < max_time));
Dave Wallace048b1d62018-01-03 22:24:41 -05002771 rv = 0;
2772
2773done:
Florin Corasdfe4cf42018-11-28 22:13:45 -08002774 vec_foreach (vp, ldpw->vcl_poll)
Dave Wallace048b1d62018-01-03 22:24:41 -05002775 {
2776 fds[vp->fds_ndx].fd = -fds[vp->fds_ndx].fd;
Florin Coras6917b942018-11-13 22:44:54 -08002777 fds[vp->fds_ndx].revents = vp->revents;
Dave Wallace048b1d62018-01-03 22:24:41 -05002778#ifdef __USE_XOPEN2K
2779 if ((fds[vp->fds_ndx].revents & POLLIN) &&
2780 (fds[vp->fds_ndx].events & POLLRDNORM))
2781 fds[vp->fds_ndx].revents |= POLLRDNORM;
2782 if ((fds[vp->fds_ndx].revents & POLLOUT) &&
2783 (fds[vp->fds_ndx].events & POLLWRNORM))
2784 fds[vp->fds_ndx].revents |= POLLWRNORM;
2785#endif
2786 }
Florin Corasdfe4cf42018-11-28 22:13:45 -08002787 vec_reset_length (ldpw->vcl_poll);
Dave Wallace048b1d62018-01-03 22:24:41 -05002788
Florin Corasdfe4cf42018-11-28 22:13:45 -08002789 for (i = 0; i < vec_len (ldpw->libc_poll); i++)
Florin Coras6917b942018-11-13 22:44:54 -08002790 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002791 fds[ldpw->libc_poll_idxs[i]].revents = ldpw->libc_poll[i].revents;
Florin Coras6917b942018-11-13 22:44:54 -08002792 }
Florin Corasdfe4cf42018-11-28 22:13:45 -08002793 vec_reset_length (ldpw->libc_poll_idxs);
2794 vec_reset_length (ldpw->libc_poll);
Florin Coras6917b942018-11-13 22:44:54 -08002795
Dave Wallace048b1d62018-01-03 22:24:41 -05002796 return rv;
2797}
2798
Florin Coras36847942023-02-02 12:56:16 -08002799#ifdef _GNU_SOURCE
Dave Wallace048b1d62018-01-03 22:24:41 -05002800int
2801ppoll (struct pollfd *fds, nfds_t nfds,
2802 const struct timespec *timeout, const sigset_t * sigmask)
2803{
Florin Coras5f33d0d2021-06-02 21:22:21 -07002804 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05002805
2806 clib_warning ("LDP<%d>: LDP-TBD", getpid ());
2807 errno = ENOSYS;
2808
2809
2810 return -1;
2811}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002812#endif
2813
Dave Wallace2a865272018-02-07 21:00:42 -05002814void CONSTRUCTOR_ATTRIBUTE ldp_constructor (void);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002815
Dave Wallace2a865272018-02-07 21:00:42 -05002816void DESTRUCTOR_ATTRIBUTE ldp_destructor (void);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002817
Dave Wallace048b1d62018-01-03 22:24:41 -05002818/*
2819 * This function is called when the library is loaded
2820 */
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002821void
Dave Wallace2a865272018-02-07 21:00:42 -05002822ldp_constructor (void)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002823{
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002824 swrap_constructor ();
Dave Wallace2a865272018-02-07 21:00:42 -05002825 if (ldp_init () != 0)
Florin Corasd89411e2019-03-19 19:44:51 -07002826 {
2827 fprintf (stderr, "\nLDP<%d>: ERROR: ldp_constructor: failed!\n",
2828 getpid ());
2829 _exit (1);
2830 }
Dave Wallace69d01192018-02-22 16:22:09 -05002831 else if (LDP_DEBUG > 0)
Dave Wallace2a865272018-02-07 21:00:42 -05002832 clib_warning ("LDP<%d>: LDP constructor: done!\n", getpid ());
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002833}
2834
2835/*
2836 * This function is called when the library is unloaded
2837 */
2838void
Dave Wallace2a865272018-02-07 21:00:42 -05002839ldp_destructor (void)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002840{
Florin Coras0ef8ef22019-01-18 08:37:13 -08002841 /*
2842 swrap_destructor ();
2843 if (ldp->init)
2844 ldp->init = 0;
2845 */
Dave Wallace048b1d62018-01-03 22:24:41 -05002846
2847 /* Don't use clib_warning() here because that calls writev()
Dave Wallace2a865272018-02-07 21:00:42 -05002848 * which will call ldp_init().
Dave Wallace048b1d62018-01-03 22:24:41 -05002849 */
Dave Wallace69d01192018-02-22 16:22:09 -05002850 if (LDP_DEBUG > 0)
Florin Coras0ef8ef22019-01-18 08:37:13 -08002851 fprintf (stderr, "%s:%d: LDP<%d>: LDP destructor: done!\n",
2852 __func__, __LINE__, getpid ());
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002853}
2854
2855
2856/*
2857 * fd.io coding-style-patch-verification: ON
2858 *
2859 * Local Variables:
2860 * eval: (c-set-style "gnu")
2861 * End:
2862 */