blob: 4b21c7d3c7a19a51fa169a954bbeac9ae1c94229 [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 */
15#include <unistd.h>
16#include <stdio.h>
17#include <signal.h>
18#include <dlfcn.h>
19#include <pthread.h>
20#include <time.h>
21#include <stdarg.h>
shrinivasan ganapathy1d359632017-10-15 15:46:09 -070022#include <sys/resource.h>
Dave Wallace048b1d62018-01-03 22:24:41 -050023#include <netinet/tcp.h>
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -070024
Dave Wallace2a865272018-02-07 21:00:42 -050025#include <vcl/ldp_socket_wrapper.h>
26#include <vcl/ldp.h>
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -070027#include <sys/time.h>
28
Florin Coras7baeb712019-01-04 17:05:43 -080029#include <vcl/vcl_locked.h>
Dave Wallace048b1d62018-01-03 22:24:41 -050030#include <vppinfra/time.h>
31#include <vppinfra/bitmap.h>
Florin Coras30e273b2018-11-27 00:04:59 -080032#include <vppinfra/lock.h>
33#include <vppinfra/pool.h>
34#include <vppinfra/hash.h>
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -070035
36#define HAVE_CONSTRUCTOR_ATTRIBUTE
37#ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
38#define CONSTRUCTOR_ATTRIBUTE \
39 __attribute__ ((constructor))
40#else
41#define CONSTRUCTOR_ATTRIBUTE
42#endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
43
44#define HAVE_DESTRUCTOR_ATTRIBUTE
45#ifdef HAVE_DESTRUCTOR_ATTRIBUTE
46#define DESTRUCTOR_ATTRIBUTE \
47 __attribute__ ((destructor))
48#else
49#define DESTRUCTOR_ATTRIBUTE
50#endif
51
Florin Corasdfe4cf42018-11-28 22:13:45 -080052#define LDP_MAX_NWORKERS 32
53
Florin Corasdfe4cf42018-11-28 22:13:45 -080054typedef struct ldp_worker_ctx_
Dave Wallace048b1d62018-01-03 22:24:41 -050055{
Dave Wallace048b1d62018-01-03 22:24:41 -050056 u8 *io_buffer;
57 clib_time_t clib_time;
Florin Corasdfe4cf42018-11-28 22:13:45 -080058
59 /*
60 * Select state
61 */
Dave Wallace048b1d62018-01-03 22:24:41 -050062 clib_bitmap_t *rd_bitmap;
63 clib_bitmap_t *wr_bitmap;
64 clib_bitmap_t *ex_bitmap;
Florin Coras294afe22019-01-07 17:49:17 -080065 clib_bitmap_t *si_rd_bitmap;
66 clib_bitmap_t *si_wr_bitmap;
67 clib_bitmap_t *si_ex_bitmap;
Dave Wallace048b1d62018-01-03 22:24:41 -050068 clib_bitmap_t *libc_rd_bitmap;
69 clib_bitmap_t *libc_wr_bitmap;
70 clib_bitmap_t *libc_ex_bitmap;
Florin Corasdfe4cf42018-11-28 22:13:45 -080071
72 /*
73 * Poll state
74 */
Dave Wallace048b1d62018-01-03 22:24:41 -050075 vcl_poll_t *vcl_poll;
Florin Coras6917b942018-11-13 22:44:54 -080076 struct pollfd *libc_poll;
77 u16 *libc_poll_idxs;
Florin Corasdfe4cf42018-11-28 22:13:45 -080078
79 /*
80 * Epoll state
81 */
Dave Wallace048b1d62018-01-03 22:24:41 -050082 u8 epoll_wait_vcl;
hanlin4266d4d2020-05-19 17:34:17 +080083 u8 mq_epfd_added;
Florin Coras99368312018-08-02 10:45:44 -070084 int vcl_mq_epfd;
Florin Corasdfe4cf42018-11-28 22:13:45 -080085
86} ldp_worker_ctx_t;
87
Florin Coras294afe22019-01-07 17:49:17 -080088/* clib_bitmap_t, fd_mask and vcl_si_set are used interchangeably. Make sure
89 * they are the same size */
90STATIC_ASSERT (sizeof (clib_bitmap_t) == sizeof (fd_mask),
91 "ldp bitmap size mismatch");
92STATIC_ASSERT (sizeof (vcl_si_set) == sizeof (fd_mask),
93 "ldp bitmap size mismatch");
94
Florin Corasdfe4cf42018-11-28 22:13:45 -080095typedef struct
96{
97 ldp_worker_ctx_t *workers;
98 int init;
99 char app_name[LDP_APP_NAME_MAX];
Florin Coras7baeb712019-01-04 17:05:43 -0800100 u32 vlsh_bit_val;
101 u32 vlsh_bit_mask;
Florin Corasdfe4cf42018-11-28 22:13:45 -0800102 u32 debug;
Florin Corasdfe4cf42018-11-28 22:13:45 -0800103
104 /** vcl needs next epoll_create to go to libc_epoll */
105 u8 vcl_needs_real_epoll;
Florin Corasa5a9efd2021-01-05 17:03:29 -0800106
107 /**
108 * crypto state used only for testing
109 */
110 u8 transparent_tls;
111 u32 ckpair_index;
Dave Wallace2a865272018-02-07 21:00:42 -0500112} ldp_main_t;
Florin Corasdfe4cf42018-11-28 22:13:45 -0800113
Dave Wallace2a865272018-02-07 21:00:42 -0500114#define LDP_DEBUG ldp->debug
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700115
Florin Coras99368312018-08-02 10:45:44 -0700116#define LDBG(_lvl, _fmt, _args...) \
117 if (ldp->debug > _lvl) \
hanlin9f3f18f2019-12-30 16:25:20 +0800118 { \
119 int errno_saved = errno; \
Florin Coras585c86a2020-10-16 17:57:36 -0700120 fprintf (stderr, "ldp<%d>: " _fmt "\n", getpid(), ##_args); \
hanlin9f3f18f2019-12-30 16:25:20 +0800121 errno = errno_saved; \
122 }
Florin Coras99368312018-08-02 10:45:44 -0700123
Dave Wallace2a865272018-02-07 21:00:42 -0500124static ldp_main_t ldp_main = {
Florin Coras7baeb712019-01-04 17:05:43 -0800125 .vlsh_bit_val = (1 << LDP_SID_BIT_MIN),
126 .vlsh_bit_mask = (1 << LDP_SID_BIT_MIN) - 1,
Dave Wallace2a865272018-02-07 21:00:42 -0500127 .debug = LDP_DEBUG_INIT,
Yu Ping7b74b072019-05-08 00:40:24 +0800128 .transparent_tls = 0,
Florin Corasa5a9efd2021-01-05 17:03:29 -0800129 .ckpair_index = ~0,
Dave Wallace048b1d62018-01-03 22:24:41 -0500130};
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700131
Dave Wallace2a865272018-02-07 21:00:42 -0500132static ldp_main_t *ldp = &ldp_main;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700133
Florin Corasdfe4cf42018-11-28 22:13:45 -0800134static inline ldp_worker_ctx_t *
135ldp_worker_get_current (void)
136{
137 return (ldp->workers + vppcom_worker_index ());
138}
139
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700140/*
141 * RETURN: 0 on success or -1 on error.
142 * */
Dave Wallace048b1d62018-01-03 22:24:41 -0500143static inline void
Dave Wallace2a865272018-02-07 21:00:42 -0500144ldp_set_app_name (char *app_name)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700145{
Benoît Ganne747b3d82019-08-21 18:27:23 +0200146 snprintf (ldp->app_name, LDP_APP_NAME_MAX,
147 "ldp-%d-%s", getpid (), app_name);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700148}
149
Dave Wallace048b1d62018-01-03 22:24:41 -0500150static inline char *
Dave Wallace2a865272018-02-07 21:00:42 -0500151ldp_get_app_name ()
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700152{
Dave Wallace2a865272018-02-07 21:00:42 -0500153 if (ldp->app_name[0] == '\0')
154 ldp_set_app_name ("app");
Dave Wallace048b1d62018-01-03 22:24:41 -0500155
Dave Wallace2a865272018-02-07 21:00:42 -0500156 return ldp->app_name;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700157}
158
Dave Wallace048b1d62018-01-03 22:24:41 -0500159static inline int
Florin Coras7baeb712019-01-04 17:05:43 -0800160ldp_vlsh_to_fd (vls_handle_t vlsh)
Dave Wallace048b1d62018-01-03 22:24:41 -0500161{
Florin Coras7baeb712019-01-04 17:05:43 -0800162 return (vlsh + ldp->vlsh_bit_val);
Dave Wallace048b1d62018-01-03 22:24:41 -0500163}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700164
Florin Coras7baeb712019-01-04 17:05:43 -0800165static inline vls_handle_t
166ldp_fd_to_vlsh (int fd)
Dave Wallace048b1d62018-01-03 22:24:41 -0500167{
Florin Coras7baeb712019-01-04 17:05:43 -0800168 if (fd < ldp->vlsh_bit_val)
169 return VLS_INVALID_HANDLE;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700170
Florin Coras7baeb712019-01-04 17:05:43 -0800171 return (fd - ldp->vlsh_bit_val);
Dave Wallace048b1d62018-01-03 22:24:41 -0500172}
173
Florin Coras2d9b4272019-03-11 10:14:37 -0700174static void
175ldp_alloc_workers (void)
176{
177 if (ldp->workers)
178 return;
179 pool_alloc (ldp->workers, LDP_MAX_NWORKERS);
180}
181
Florin Coras5f33d0d2021-06-02 21:22:21 -0700182static int
Dave Wallace2a865272018-02-07 21:00:42 -0500183ldp_init (void)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700184{
Florin Corasdfe4cf42018-11-28 22:13:45 -0800185 ldp_worker_ctx_t *ldpw;
Florin Coras99368312018-08-02 10:45:44 -0700186 int rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700187
Florin Coras5f33d0d2021-06-02 21:22:21 -0700188 ASSERT (!ldp->init);
Florin Coras99368312018-08-02 10:45:44 -0700189
190 ldp->init = 1;
191 ldp->vcl_needs_real_epoll = 1;
Florin Coras7baeb712019-01-04 17:05:43 -0800192 rv = vls_app_create (ldp_get_app_name ());
Florin Coras99368312018-08-02 10:45:44 -0700193 if (rv != VPPCOM_OK)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700194 {
Florin Coras955bfbb2018-12-04 13:43:45 -0800195 ldp->vcl_needs_real_epoll = 0;
196 if (rv == VPPCOM_EEXIST)
197 return 0;
Florin Coras05ecfcc2018-12-12 18:19:39 -0800198 LDBG (2, "\nERROR: ldp_init: vppcom_app_create()"
199 " failed! rv = %d (%s)\n", rv, vppcom_retval_str (rv));
Florin Coras99368312018-08-02 10:45:44 -0700200 ldp->init = 0;
201 return rv;
202 }
203 ldp->vcl_needs_real_epoll = 0;
Florin Coras2d9b4272019-03-11 10:14:37 -0700204 ldp_alloc_workers ();
Florin Corasdfe4cf42018-11-28 22:13:45 -0800205 ldpw = ldp_worker_get_current ();
Florin Coras99368312018-08-02 10:45:44 -0700206
207 char *env_var_str = getenv (LDP_ENV_DEBUG);
208 if (env_var_str)
209 {
210 u32 tmp;
211 if (sscanf (env_var_str, "%u", &tmp) != 1)
212 clib_warning ("LDP<%d>: WARNING: Invalid LDP debug level specified in"
213 " the env var " LDP_ENV_DEBUG " (%s)!", getpid (),
214 env_var_str);
215 else
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700216 {
Florin Coras99368312018-08-02 10:45:44 -0700217 ldp->debug = tmp;
Florin Coras05ecfcc2018-12-12 18:19:39 -0800218 LDBG (0, "configured LDP debug level (%u) from env var "
219 LDP_ENV_DEBUG "!", ldp->debug);
Florin Coras99368312018-08-02 10:45:44 -0700220 }
221 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500222
Florin Coras99368312018-08-02 10:45:44 -0700223 env_var_str = getenv (LDP_ENV_APP_NAME);
224 if (env_var_str)
225 {
226 ldp_set_app_name (env_var_str);
Florin Coras05ecfcc2018-12-12 18:19:39 -0800227 LDBG (0, "configured LDP app name (%s) from the env var "
228 LDP_ENV_APP_NAME "!", ldp->app_name);
Florin Coras99368312018-08-02 10:45:44 -0700229 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500230
Florin Coras99368312018-08-02 10:45:44 -0700231 env_var_str = getenv (LDP_ENV_SID_BIT);
232 if (env_var_str)
233 {
234 u32 sb;
235 if (sscanf (env_var_str, "%u", &sb) != 1)
236 {
Florin Coras294afe22019-01-07 17:49:17 -0800237 LDBG (0, "WARNING: Invalid LDP sid bit specified in the env var "
238 LDP_ENV_SID_BIT " (%s)! sid bit value %d (0x%x)", env_var_str,
239 ldp->vlsh_bit_val, ldp->vlsh_bit_val);
Florin Coras99368312018-08-02 10:45:44 -0700240 }
241 else if (sb < LDP_SID_BIT_MIN)
242 {
Florin Coras7baeb712019-01-04 17:05:43 -0800243 ldp->vlsh_bit_val = (1 << LDP_SID_BIT_MIN);
244 ldp->vlsh_bit_mask = ldp->vlsh_bit_val - 1;
Dave Wallace048b1d62018-01-03 22:24:41 -0500245
Florin Coras294afe22019-01-07 17:49:17 -0800246 LDBG (0, "WARNING: LDP sid bit (%u) specified in the env var "
247 LDP_ENV_SID_BIT " (%s) is too small. Using LDP_SID_BIT_MIN"
248 " (%d)! sid bit value %d (0x%x)", sb, env_var_str,
249 LDP_SID_BIT_MIN, ldp->vlsh_bit_val, ldp->vlsh_bit_val);
Florin Coras99368312018-08-02 10:45:44 -0700250 }
251 else if (sb > LDP_SID_BIT_MAX)
252 {
Florin Coras7baeb712019-01-04 17:05:43 -0800253 ldp->vlsh_bit_val = (1 << LDP_SID_BIT_MAX);
254 ldp->vlsh_bit_mask = ldp->vlsh_bit_val - 1;
Dave Wallace048b1d62018-01-03 22:24:41 -0500255
Florin Coras294afe22019-01-07 17:49:17 -0800256 LDBG (0, "WARNING: LDP sid bit (%u) specified in the env var "
257 LDP_ENV_SID_BIT " (%s) is too big. Using LDP_SID_BIT_MAX"
258 " (%d)! sid bit value %d (0x%x)", sb, env_var_str,
259 LDP_SID_BIT_MAX, ldp->vlsh_bit_val, ldp->vlsh_bit_val);
Dave Wallace048b1d62018-01-03 22:24:41 -0500260 }
261 else
262 {
Florin Coras7baeb712019-01-04 17:05:43 -0800263 ldp->vlsh_bit_val = (1 << sb);
264 ldp->vlsh_bit_mask = ldp->vlsh_bit_val - 1;
Florin Coras99368312018-08-02 10:45:44 -0700265
Florin Coras05ecfcc2018-12-12 18:19:39 -0800266 LDBG (0, "configured LDP sid bit (%u) from "
267 LDP_ENV_SID_BIT "! sid bit value %d (0x%x)", sb,
Florin Coras7baeb712019-01-04 17:05:43 -0800268 ldp->vlsh_bit_val, ldp->vlsh_bit_val);
Dave Wallace048b1d62018-01-03 22:24:41 -0500269 }
Florin Coras294afe22019-01-07 17:49:17 -0800270
271 /* Make sure there are enough bits in the fd set for vcl sessions */
272 if (ldp->vlsh_bit_val > FD_SETSIZE / 2)
273 {
274 LDBG (0, "ERROR: LDP vlsh bit value %d > FD_SETSIZE/2 %d!",
275 ldp->vlsh_bit_val, FD_SETSIZE / 2);
276 ldp->init = 0;
277 return -1;
278 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500279 }
Yu Ping7b74b072019-05-08 00:40:24 +0800280 env_var_str = getenv (LDP_ENV_TLS_TRANS);
281 if (env_var_str)
282 {
283 ldp->transparent_tls = 1;
284 }
Florin Coras99368312018-08-02 10:45:44 -0700285
Florin Coras4dee8cd2019-01-29 21:28:16 -0800286 /* *INDENT-OFF* */
Damjan Marionb2c31b62020-12-13 21:47:40 +0100287 pool_foreach (ldpw, ldp->workers) {
Florin Coras4dee8cd2019-01-29 21:28:16 -0800288 clib_memset (&ldpw->clib_time, 0, sizeof (ldpw->clib_time));
Damjan Marionb2c31b62020-12-13 21:47:40 +0100289 }
Florin Coras4dee8cd2019-01-29 21:28:16 -0800290 /* *INDENT-ON* */
291
Florin Coras05ecfcc2018-12-12 18:19:39 -0800292 LDBG (0, "LDP initialization: done!");
Florin Coras99368312018-08-02 10:45:44 -0700293
294 return 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500295}
296
Florin Coras5f33d0d2021-06-02 21:22:21 -0700297#define ldp_init_check() \
298 if (PREDICT_FALSE (!ldp->init)) \
299 { \
300 if ((errno = -ldp_init ())) \
301 return -1; \
302 }
303
Dave Wallace048b1d62018-01-03 22:24:41 -0500304int
305close (int fd)
306{
Florin Coras7baeb712019-01-04 17:05:43 -0800307 vls_handle_t vlsh;
308 int rv, epfd;
Dave Wallace048b1d62018-01-03 22:24:41 -0500309
Florin Coras5f33d0d2021-06-02 21:22:21 -0700310 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -0500311
Florin Coras7baeb712019-01-04 17:05:43 -0800312 vlsh = ldp_fd_to_vlsh (fd);
313 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500314 {
Florin Coras7baeb712019-01-04 17:05:43 -0800315 epfd = vls_attr (vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -0500316 if (epfd > 0)
317 {
Florin Coras7baeb712019-01-04 17:05:43 -0800318 LDBG (0, "fd %d: calling libc_close: epfd %u", fd, epfd);
Dave Wallace048b1d62018-01-03 22:24:41 -0500319
320 rv = libc_close (epfd);
321 if (rv < 0)
322 {
323 u32 size = sizeof (epfd);
324 epfd = 0;
325
Florin Coras7baeb712019-01-04 17:05:43 -0800326 (void) vls_attr (vlsh, VPPCOM_ATTR_SET_LIBC_EPFD, &epfd, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -0500327 }
328 }
329 else if (PREDICT_FALSE (epfd < 0))
330 {
331 errno = -epfd;
332 rv = -1;
333 goto done;
334 }
335
Florin Coras7baeb712019-01-04 17:05:43 -0800336 LDBG (0, "fd %d: calling vls_close: vlsh %u", fd, vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -0500337
Florin Coras7baeb712019-01-04 17:05:43 -0800338 rv = vls_close (vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -0500339 if (rv != VPPCOM_OK)
340 {
341 errno = -rv;
342 rv = -1;
343 }
344 }
345 else
346 {
Florin Coras7baeb712019-01-04 17:05:43 -0800347 LDBG (0, "fd %d: calling libc_close", fd);
Dave Wallace048b1d62018-01-03 22:24:41 -0500348 rv = libc_close (fd);
349 }
350
351done:
Dave Wallace048b1d62018-01-03 22:24:41 -0500352 return rv;
353}
354
355ssize_t
356read (int fd, void *buf, size_t nbytes)
357{
Florin Coras7baeb712019-01-04 17:05:43 -0800358 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500359 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -0500360
Florin Coras5f33d0d2021-06-02 21:22:21 -0700361 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -0500362
Florin Coras7baeb712019-01-04 17:05:43 -0800363 vlsh = ldp_fd_to_vlsh (fd);
364 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500365 {
Florin Coras7baeb712019-01-04 17:05:43 -0800366 size = vls_read (vlsh, buf, nbytes);
Dave Wallace048b1d62018-01-03 22:24:41 -0500367 if (size < 0)
368 {
369 errno = -size;
370 size = -1;
371 }
372 }
373 else
374 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500375 size = libc_read (fd, buf, nbytes);
376 }
377
Dave Wallace048b1d62018-01-03 22:24:41 -0500378 return size;
379}
380
381ssize_t
382readv (int fd, const struct iovec * iov, int iovcnt)
383{
Dave Wallace8aaba562018-01-18 17:21:19 -0500384 int rv = 0, i, total = 0;
Florin Coras7baeb712019-01-04 17:05:43 -0800385 vls_handle_t vlsh;
386 ssize_t size = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500387
Florin Coras5f33d0d2021-06-02 21:22:21 -0700388 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -0500389
Florin Coras7baeb712019-01-04 17:05:43 -0800390 vlsh = ldp_fd_to_vlsh (fd);
391 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500392 {
Florin Coras067f9542020-02-14 05:33:46 +0000393 for (i = 0; i < iovcnt; ++i)
Dave Wallace048b1d62018-01-03 22:24:41 -0500394 {
Florin Coras067f9542020-02-14 05:33:46 +0000395 rv = vls_read (vlsh, iov[i].iov_base, iov[i].iov_len);
396 if (rv <= 0)
397 break;
398 else
Dave Wallace048b1d62018-01-03 22:24:41 -0500399 {
Florin Coras067f9542020-02-14 05:33:46 +0000400 total += rv;
401 if (rv < iov[i].iov_len)
Dave Wallace048b1d62018-01-03 22:24:41 -0500402 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700403 }
404 }
Florin Coras067f9542020-02-14 05:33:46 +0000405 if (rv < 0 && total == 0)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700406 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500407 errno = -rv;
408 size = -1;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700409 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500410 else
411 size = total;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700412 }
413 else
414 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500415 size = libc_readv (fd, iov, iovcnt);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700416 }
417
Dave Wallace048b1d62018-01-03 22:24:41 -0500418 return size;
419}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700420
Dave Wallace048b1d62018-01-03 22:24:41 -0500421ssize_t
422write (int fd, const void *buf, size_t nbytes)
423{
Florin Coras7baeb712019-01-04 17:05:43 -0800424 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500425 ssize_t size = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500426
Florin Coras5f33d0d2021-06-02 21:22:21 -0700427 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -0500428
Florin Coras7baeb712019-01-04 17:05:43 -0800429 vlsh = ldp_fd_to_vlsh (fd);
430 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500431 {
Florin Coras7baeb712019-01-04 17:05:43 -0800432 size = vls_write_msg (vlsh, (void *) buf, nbytes);
Dave Wallace048b1d62018-01-03 22:24:41 -0500433 if (size < 0)
434 {
435 errno = -size;
436 size = -1;
437 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700438 }
439 else
440 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500441 size = libc_write (fd, buf, nbytes);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700442 }
443
Dave Wallace048b1d62018-01-03 22:24:41 -0500444 return size;
445}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700446
Dave Wallace048b1d62018-01-03 22:24:41 -0500447ssize_t
448writev (int fd, const struct iovec * iov, int iovcnt)
449{
Dave Wallace048b1d62018-01-03 22:24:41 -0500450 ssize_t size = 0, total = 0;
Florin Coras7baeb712019-01-04 17:05:43 -0800451 vls_handle_t vlsh;
Dave Wallace8aaba562018-01-18 17:21:19 -0500452 int i, rv = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500453
Florin Coras5f33d0d2021-06-02 21:22:21 -0700454 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -0500455
Florin Coras7baeb712019-01-04 17:05:43 -0800456 vlsh = ldp_fd_to_vlsh (fd);
457 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500458 {
Florin Coraseda1b8c2020-03-23 16:00:35 +0000459 for (i = 0; i < iovcnt; ++i)
Dave Wallace048b1d62018-01-03 22:24:41 -0500460 {
Florin Coraseda1b8c2020-03-23 16:00:35 +0000461 rv = vls_write_msg (vlsh, iov[i].iov_base, iov[i].iov_len);
462 if (rv < 0)
463 break;
464 else
Dave Wallace048b1d62018-01-03 22:24:41 -0500465 {
Florin Coraseda1b8c2020-03-23 16:00:35 +0000466 total += rv;
467 if (rv < iov[i].iov_len)
Dave Wallace048b1d62018-01-03 22:24:41 -0500468 break;
Dave Wallace048b1d62018-01-03 22:24:41 -0500469 }
470 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500471
Florin Coraseda1b8c2020-03-23 16:00:35 +0000472 if (rv < 0 && total == 0)
Dave Wallace048b1d62018-01-03 22:24:41 -0500473 {
474 errno = -rv;
475 size = -1;
476 }
477 else
478 size = total;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700479 }
480 else
481 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500482 size = libc_writev (fd, iov, iovcnt);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700483 }
484
Dave Wallace048b1d62018-01-03 22:24:41 -0500485 return size;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700486}
487
Florin Coras0ab36f52020-05-26 19:45:45 +0000488static int
489fcntl_internal (int fd, int cmd, va_list ap)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700490{
Florin Coras7baeb712019-01-04 17:05:43 -0800491 vls_handle_t vlsh;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700492 int rv = 0;
Florin Coras7baeb712019-01-04 17:05:43 -0800493
494 vlsh = ldp_fd_to_vlsh (fd);
495 LDBG (0, "fd %u vlsh %d, cmd %u", fd, vlsh, cmd);
496 if (vlsh != VLS_INVALID_HANDLE)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700497 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500498 int flags = va_arg (ap, int);
499 u32 size;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700500
Dave Wallace048b1d62018-01-03 22:24:41 -0500501 size = sizeof (flags);
502 rv = -EOPNOTSUPP;
503 switch (cmd)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700504 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500505 case F_SETFL:
Florin Coras7baeb712019-01-04 17:05:43 -0800506 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_FLAGS, &flags, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -0500507 break;
508
509 case F_GETFL:
Florin Coras7baeb712019-01-04 17:05:43 -0800510 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_FLAGS, &flags, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -0500511 if (rv == VPPCOM_OK)
Florin Coras7baeb712019-01-04 17:05:43 -0800512 rv = flags;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700513 break;
Florin Coras173bae32018-11-16 18:56:28 -0800514 case F_SETFD:
515 /* TODO handle this */
516 LDBG (0, "F_SETFD ignored flags %u", flags);
517 rv = 0;
518 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700519 default:
Dave Wallace048b1d62018-01-03 22:24:41 -0500520 rv = -EOPNOTSUPP;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700521 break;
522 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500523 if (rv < 0)
524 {
525 errno = -rv;
526 rv = -1;
527 }
528 }
529 else
530 {
Carl Smithe16707b2019-11-13 14:37:39 +1300531#ifdef HAVE_FCNTL64
532 rv = libc_vfcntl64 (fd, cmd, ap);
533#else
Dave Wallace048b1d62018-01-03 22:24:41 -0500534 rv = libc_vfcntl (fd, cmd, ap);
Carl Smithe16707b2019-11-13 14:37:39 +1300535#endif
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700536 }
537
Florin Coras0ab36f52020-05-26 19:45:45 +0000538 return rv;
539}
540
541int
542fcntl (int fd, int cmd, ...)
543{
544 va_list ap;
545 int rv;
546
Florin Coras5f33d0d2021-06-02 21:22:21 -0700547 ldp_init_check ();
Florin Coras0ab36f52020-05-26 19:45:45 +0000548
549 va_start (ap, cmd);
550 rv = fcntl_internal (fd, cmd, ap);
Dave Wallace048b1d62018-01-03 22:24:41 -0500551 va_end (ap);
552
Dave Wallace048b1d62018-01-03 22:24:41 -0500553 return rv;
554}
555
556int
Florin Corasd7586d52020-04-29 02:19:51 +0000557fcntl64 (int fd, int cmd, ...)
558{
559 va_list ap;
560 int rv;
561
Florin Coras5f33d0d2021-06-02 21:22:21 -0700562 ldp_init_check ();
Florin Coras0ab36f52020-05-26 19:45:45 +0000563
Florin Corasd7586d52020-04-29 02:19:51 +0000564 va_start (ap, cmd);
Florin Coras0ab36f52020-05-26 19:45:45 +0000565 rv = fcntl_internal (fd, cmd, ap);
Florin Corasd7586d52020-04-29 02:19:51 +0000566 va_end (ap);
567 return rv;
568}
569
570int
Dave Wallace048b1d62018-01-03 22:24:41 -0500571ioctl (int fd, unsigned long int cmd, ...)
572{
Florin Coras7baeb712019-01-04 17:05:43 -0800573 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500574 va_list ap;
Florin Coras7baeb712019-01-04 17:05:43 -0800575 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -0500576
Florin Coras5f33d0d2021-06-02 21:22:21 -0700577 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -0500578
579 va_start (ap, cmd);
Dave Wallace048b1d62018-01-03 22:24:41 -0500580
Florin Coras7baeb712019-01-04 17:05:43 -0800581 vlsh = ldp_fd_to_vlsh (fd);
582 if (vlsh != VLS_INVALID_HANDLE)
583 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500584 switch (cmd)
585 {
586 case FIONREAD:
Florin Coras7baeb712019-01-04 17:05:43 -0800587 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_NREAD, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -0500588 break;
589
590 case FIONBIO:
591 {
592 u32 flags = va_arg (ap, int) ? O_NONBLOCK : 0;
593 u32 size = sizeof (flags);
594
595 /* TBD: When VPPCOM_ATTR_[GS]ET_FLAGS supports flags other than
596 * non-blocking, the flags should be read here and merged
597 * with O_NONBLOCK.
598 */
Florin Coras7baeb712019-01-04 17:05:43 -0800599 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_FLAGS, &flags, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -0500600 }
601 break;
602
603 default:
604 rv = -EOPNOTSUPP;
605 break;
606 }
607 if (rv < 0)
608 {
609 errno = -rv;
610 rv = -1;
611 }
612 }
613 else
614 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500615 rv = libc_vioctl (fd, cmd, ap);
616 }
617
Dave Wallace048b1d62018-01-03 22:24:41 -0500618 va_end (ap);
619 return rv;
620}
621
Florin Coras294afe22019-01-07 17:49:17 -0800622always_inline void
623ldp_select_init_maps (fd_set * __restrict original,
624 clib_bitmap_t ** resultb, clib_bitmap_t ** libcb,
625 clib_bitmap_t ** vclb, int nfds, u32 minbits,
626 u32 n_bytes, uword * si_bits, uword * libc_bits)
627{
628 uword si_bits_set, libc_bits_set;
629 vls_handle_t vlsh;
630 int fd;
631
632 clib_bitmap_validate (*vclb, minbits);
633 clib_bitmap_validate (*libcb, minbits);
634 clib_bitmap_validate (*resultb, minbits);
635 clib_memcpy_fast (*resultb, original, n_bytes);
636 memset (original, 0, n_bytes);
637
638 /* *INDENT-OFF* */
Damjan Marionf0ca1e82020-12-13 23:26:56 +0100639 clib_bitmap_foreach (fd, *resultb) {
Florin Coras294afe22019-01-07 17:49:17 -0800640 if (fd > nfds)
641 break;
642 vlsh = ldp_fd_to_vlsh (fd);
643 if (vlsh == VLS_INVALID_HANDLE)
644 clib_bitmap_set_no_check (*libcb, fd, 1);
645 else
Florin Corascbce80a2020-04-20 01:32:38 +0000646 *vclb = clib_bitmap_set (*vclb, vlsh_to_session_index (vlsh), 1);
Damjan Marionf0ca1e82020-12-13 23:26:56 +0100647 }
Florin Coras294afe22019-01-07 17:49:17 -0800648 /* *INDENT-ON* */
649
650 si_bits_set = clib_bitmap_last_set (*vclb) + 1;
651 *si_bits = (si_bits_set > *si_bits) ? si_bits_set : *si_bits;
Florin Corascbce80a2020-04-20 01:32:38 +0000652 clib_bitmap_validate (*resultb, *si_bits);
Florin Coras294afe22019-01-07 17:49:17 -0800653
654 libc_bits_set = clib_bitmap_last_set (*libcb) + 1;
655 *libc_bits = (libc_bits_set > *libc_bits) ? libc_bits_set : *libc_bits;
656}
657
658always_inline int
659ldp_select_vcl_map_to_libc (clib_bitmap_t * vclb, fd_set * __restrict libcb)
660{
661 vls_handle_t vlsh;
662 uword si;
663 int fd;
664
665 if (!libcb)
666 return 0;
667
668 /* *INDENT-OFF* */
Damjan Marionf0ca1e82020-12-13 23:26:56 +0100669 clib_bitmap_foreach (si, vclb) {
Florin Coras294afe22019-01-07 17:49:17 -0800670 vlsh = vls_session_index_to_vlsh (si);
Florin Coras54140622020-02-04 19:04:34 +0000671 ASSERT (vlsh != VLS_INVALID_HANDLE);
Florin Coras294afe22019-01-07 17:49:17 -0800672 fd = ldp_vlsh_to_fd (vlsh);
673 if (PREDICT_FALSE (fd < 0))
674 {
675 errno = EBADFD;
676 return -1;
677 }
678 FD_SET (fd, libcb);
Damjan Marionf0ca1e82020-12-13 23:26:56 +0100679 }
Florin Coras294afe22019-01-07 17:49:17 -0800680 /* *INDENT-ON* */
681
682 return 0;
683}
684
685always_inline void
686ldp_select_libc_map_merge (clib_bitmap_t * result, fd_set * __restrict libcb)
687{
688 uword fd;
689
Florin Coras78b5fa62019-02-21 20:04:15 -0800690 if (!libcb)
691 return;
692
Florin Coras294afe22019-01-07 17:49:17 -0800693 /* *INDENT-OFF* */
Damjan Marionf0ca1e82020-12-13 23:26:56 +0100694 clib_bitmap_foreach (fd, result)
Florin Coras294afe22019-01-07 17:49:17 -0800695 FD_SET ((int)fd, libcb);
Florin Coras294afe22019-01-07 17:49:17 -0800696 /* *INDENT-ON* */
697}
698
Dave Wallace048b1d62018-01-03 22:24:41 -0500699int
Dave Wallace2a865272018-02-07 21:00:42 -0500700ldp_pselect (int nfds, fd_set * __restrict readfds,
701 fd_set * __restrict writefds,
702 fd_set * __restrict exceptfds,
703 const struct timespec *__restrict timeout,
704 const __sigset_t * __restrict sigmask)
Dave Wallace048b1d62018-01-03 22:24:41 -0500705{
Florin Coras294afe22019-01-07 17:49:17 -0800706 u32 minbits = clib_max (nfds, BITS (uword)), n_bytes;
Florin Corasdfe4cf42018-11-28 22:13:45 -0800707 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras294afe22019-01-07 17:49:17 -0800708 struct timespec libc_tspec = { 0 };
709 f64 time_out, vcl_timeout = 0;
710 uword si_bits, libc_bits;
711 int rv, bits_set = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500712
713 if (nfds < 0)
714 {
715 errno = EINVAL;
716 return -1;
717 }
718
Florin Coras4dee8cd2019-01-29 21:28:16 -0800719 if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
720 clib_time_init (&ldpw->clib_time);
721
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500722 if (timeout)
723 {
724 time_out = (timeout->tv_sec == 0 && timeout->tv_nsec == 0) ?
Florin Coras7baeb712019-01-04 17:05:43 -0800725 (f64) 0 : (f64) timeout->tv_sec + (f64) timeout->tv_nsec / (f64) 1e9;
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500726
liuyacanf71796e2021-08-02 10:01:39 +0800727 time_out += clib_time_now (&ldpw->clib_time);
728
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500729 /* select as fine grained sleep */
730 if (!nfds)
731 {
Florin Corasdfe4cf42018-11-28 22:13:45 -0800732 while (clib_time_now (&ldpw->clib_time) < time_out)
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500733 ;
734 return 0;
735 }
736 }
737 else if (!nfds)
738 {
739 errno = EINVAL;
740 return -1;
741 }
742 else
743 time_out = -1;
744
Florin Coras7baeb712019-01-04 17:05:43 -0800745 if (nfds <= ldp->vlsh_bit_val)
Dave Wallace048b1d62018-01-03 22:24:41 -0500746 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500747 rv = libc_pselect (nfds, readfds, writefds, exceptfds,
748 timeout, sigmask);
749 goto done;
750 }
751
Florin Coras294afe22019-01-07 17:49:17 -0800752 si_bits = libc_bits = 0;
753 n_bytes = nfds / 8 + ((nfds % 8) ? 1 : 0);
Florin Coras7baeb712019-01-04 17:05:43 -0800754
Dave Wallace048b1d62018-01-03 22:24:41 -0500755 if (readfds)
Florin Coras294afe22019-01-07 17:49:17 -0800756 ldp_select_init_maps (readfds, &ldpw->rd_bitmap, &ldpw->libc_rd_bitmap,
757 &ldpw->si_rd_bitmap, nfds, minbits, n_bytes,
758 &si_bits, &libc_bits);
Dave Wallace048b1d62018-01-03 22:24:41 -0500759 if (writefds)
Florin Coras294afe22019-01-07 17:49:17 -0800760 ldp_select_init_maps (writefds, &ldpw->wr_bitmap,
761 &ldpw->libc_wr_bitmap, &ldpw->si_wr_bitmap, nfds,
762 minbits, n_bytes, &si_bits, &libc_bits);
Dave Wallace048b1d62018-01-03 22:24:41 -0500763 if (exceptfds)
Florin Coras294afe22019-01-07 17:49:17 -0800764 ldp_select_init_maps (exceptfds, &ldpw->ex_bitmap,
765 &ldpw->libc_ex_bitmap, &ldpw->si_ex_bitmap, nfds,
766 minbits, n_bytes, &si_bits, &libc_bits);
Dave Wallace048b1d62018-01-03 22:24:41 -0500767
Florin Coras294afe22019-01-07 17:49:17 -0800768 if (PREDICT_FALSE (!si_bits && !libc_bits))
Dave Wallace048b1d62018-01-03 22:24:41 -0500769 {
770 errno = EINVAL;
771 rv = -1;
772 goto done;
773 }
774
Florin Coras78b5fa62019-02-21 20:04:15 -0800775 if (!si_bits)
776 libc_tspec = timeout ? *timeout : libc_tspec;
Florin Coras294afe22019-01-07 17:49:17 -0800777
Dave Wallace048b1d62018-01-03 22:24:41 -0500778 do
779 {
Florin Coras294afe22019-01-07 17:49:17 -0800780 if (si_bits)
Dave Wallace048b1d62018-01-03 22:24:41 -0500781 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500782 if (readfds)
Florin Coras294afe22019-01-07 17:49:17 -0800783 clib_memcpy_fast (ldpw->rd_bitmap, ldpw->si_rd_bitmap,
Florin Corascbce80a2020-04-20 01:32:38 +0000784 vec_len (ldpw->si_rd_bitmap) *
Dave Barach178cf492018-11-13 16:34:13 -0500785 sizeof (clib_bitmap_t));
Dave Wallace048b1d62018-01-03 22:24:41 -0500786 if (writefds)
Florin Coras294afe22019-01-07 17:49:17 -0800787 clib_memcpy_fast (ldpw->wr_bitmap, ldpw->si_wr_bitmap,
Florin Corascbce80a2020-04-20 01:32:38 +0000788 vec_len (ldpw->si_wr_bitmap) *
Dave Barach178cf492018-11-13 16:34:13 -0500789 sizeof (clib_bitmap_t));
Dave Wallace048b1d62018-01-03 22:24:41 -0500790 if (exceptfds)
Florin Coras294afe22019-01-07 17:49:17 -0800791 clib_memcpy_fast (ldpw->ex_bitmap, ldpw->si_ex_bitmap,
Florin Corascbce80a2020-04-20 01:32:38 +0000792 vec_len (ldpw->si_ex_bitmap) *
Dave Barach178cf492018-11-13 16:34:13 -0500793 sizeof (clib_bitmap_t));
Florin Coras294afe22019-01-07 17:49:17 -0800794
Florin Coras0ef8ef22019-01-18 08:37:13 -0800795 rv = vls_select (si_bits, readfds ? ldpw->rd_bitmap : NULL,
796 writefds ? ldpw->wr_bitmap : NULL,
797 exceptfds ? ldpw->ex_bitmap : NULL, vcl_timeout);
Florin Coras294afe22019-01-07 17:49:17 -0800798 if (rv < 0)
799 {
800 errno = -rv;
801 rv = -1;
Florin Coras5e6222a2020-04-24 17:09:25 +0000802 goto done;
Florin Coras294afe22019-01-07 17:49:17 -0800803 }
804 else if (rv > 0)
805 {
806 if (ldp_select_vcl_map_to_libc (ldpw->rd_bitmap, readfds))
807 {
808 rv = -1;
809 goto done;
810 }
811
812 if (ldp_select_vcl_map_to_libc (ldpw->wr_bitmap, writefds))
813 {
814 rv = -1;
815 goto done;
816 }
817
818 if (ldp_select_vcl_map_to_libc (ldpw->ex_bitmap, exceptfds))
819 {
820 rv = -1;
821 goto done;
822 }
823 bits_set = rv;
824 }
825 }
826 if (libc_bits)
827 {
828 if (readfds)
829 clib_memcpy_fast (ldpw->rd_bitmap, ldpw->libc_rd_bitmap,
830 vec_len (ldpw->libc_rd_bitmap) *
831 sizeof (clib_bitmap_t));
832 if (writefds)
833 clib_memcpy_fast (ldpw->wr_bitmap, ldpw->libc_wr_bitmap,
834 vec_len (ldpw->libc_wr_bitmap) *
835 sizeof (clib_bitmap_t));
836 if (exceptfds)
837 clib_memcpy_fast (ldpw->ex_bitmap, ldpw->libc_ex_bitmap,
838 vec_len (ldpw->libc_ex_bitmap) *
839 sizeof (clib_bitmap_t));
840
Dave Wallace048b1d62018-01-03 22:24:41 -0500841 rv = libc_pselect (libc_bits,
Florin Coras294afe22019-01-07 17:49:17 -0800842 readfds ? (fd_set *) ldpw->rd_bitmap : NULL,
843 writefds ? (fd_set *) ldpw->wr_bitmap : NULL,
844 exceptfds ? (fd_set *) ldpw->ex_bitmap : NULL,
845 &libc_tspec, sigmask);
846 if (rv > 0)
847 {
848 ldp_select_libc_map_merge (ldpw->rd_bitmap, readfds);
849 ldp_select_libc_map_merge (ldpw->wr_bitmap, writefds);
850 ldp_select_libc_map_merge (ldpw->ex_bitmap, exceptfds);
851 bits_set += rv;
852 }
853 }
854
855 if (bits_set)
856 {
857 rv = bits_set;
858 goto done;
Dave Wallace048b1d62018-01-03 22:24:41 -0500859 }
860 }
Florin Corasdfe4cf42018-11-28 22:13:45 -0800861 while ((time_out == -1) || (clib_time_now (&ldpw->clib_time) < time_out));
Dave Wallace048b1d62018-01-03 22:24:41 -0500862 rv = 0;
863
864done:
865 /* TBD: set timeout to amount of time left */
Florin Corasdfe4cf42018-11-28 22:13:45 -0800866 clib_bitmap_zero (ldpw->rd_bitmap);
Florin Coras294afe22019-01-07 17:49:17 -0800867 clib_bitmap_zero (ldpw->si_rd_bitmap);
Florin Corasdfe4cf42018-11-28 22:13:45 -0800868 clib_bitmap_zero (ldpw->libc_rd_bitmap);
869 clib_bitmap_zero (ldpw->wr_bitmap);
Florin Coras294afe22019-01-07 17:49:17 -0800870 clib_bitmap_zero (ldpw->si_wr_bitmap);
Florin Corasdfe4cf42018-11-28 22:13:45 -0800871 clib_bitmap_zero (ldpw->libc_wr_bitmap);
872 clib_bitmap_zero (ldpw->ex_bitmap);
Florin Coras294afe22019-01-07 17:49:17 -0800873 clib_bitmap_zero (ldpw->si_ex_bitmap);
Florin Corasdfe4cf42018-11-28 22:13:45 -0800874 clib_bitmap_zero (ldpw->libc_ex_bitmap);
Dave Wallace048b1d62018-01-03 22:24:41 -0500875
Dave Wallace048b1d62018-01-03 22:24:41 -0500876 return rv;
877}
878
879int
880select (int nfds, fd_set * __restrict readfds,
881 fd_set * __restrict writefds,
882 fd_set * __restrict exceptfds, struct timeval *__restrict timeout)
883{
884 struct timespec tspec;
885
886 if (timeout)
887 {
888 tspec.tv_sec = timeout->tv_sec;
889 tspec.tv_nsec = timeout->tv_usec * 1000;
890 }
Dave Wallace2a865272018-02-07 21:00:42 -0500891 return ldp_pselect (nfds, readfds, writefds, exceptfds,
892 timeout ? &tspec : NULL, NULL);
Dave Wallace048b1d62018-01-03 22:24:41 -0500893}
894
895#ifdef __USE_XOPEN2K
896int
897pselect (int nfds, fd_set * __restrict readfds,
898 fd_set * __restrict writefds,
899 fd_set * __restrict exceptfds,
900 const struct timespec *__restrict timeout,
901 const __sigset_t * __restrict sigmask)
902{
Dave Wallace2a865272018-02-07 21:00:42 -0500903 return ldp_pselect (nfds, readfds, writefds, exceptfds, timeout, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -0500904}
905#endif
906
Yu Ping7b74b072019-05-08 00:40:24 +0800907/* If transparent TLS mode is turned on, then ldp will load key and cert.
908 */
909static int
Florin Corasa5a9efd2021-01-05 17:03:29 -0800910load_cert_key_pair (void)
Yu Ping7b74b072019-05-08 00:40:24 +0800911{
Florin Corasa5a9efd2021-01-05 17:03:29 -0800912 char *cert_str = getenv (LDP_ENV_TLS_CERT);
913 char *key_str = getenv (LDP_ENV_TLS_KEY);
914 char cert_buf[4096], key_buf[4096];
915 int cert_size, key_size;
916 vppcom_cert_key_pair_t crypto;
917 int ckp_index;
Yu Ping7b74b072019-05-08 00:40:24 +0800918 FILE *fp;
919
Florin Corasa5a9efd2021-01-05 17:03:29 -0800920 if (!cert_str || !key_str)
Yu Ping7b74b072019-05-08 00:40:24 +0800921 {
922 LDBG (0, "ERROR: failed to read LDP environment %s\n",
923 LDP_ENV_TLS_CERT);
924 return -1;
925 }
Florin Corasa5a9efd2021-01-05 17:03:29 -0800926
927 fp = fopen (cert_str, "r");
928 if (fp == NULL)
929 {
930 LDBG (0, "ERROR: failed to open cert file %s \n", cert_str);
931 return -1;
932 }
933 cert_size = fread (cert_buf, sizeof (char), sizeof (cert_buf), fp);
934 fclose (fp);
935
936 fp = fopen (key_str, "r");
937 if (fp == NULL)
938 {
939 LDBG (0, "ERROR: failed to open key file %s \n", key_str);
940 return -1;
941 }
942 key_size = fread (key_buf, sizeof (char), sizeof (key_buf), fp);
943 fclose (fp);
944
945 crypto.cert = cert_buf;
946 crypto.key = key_buf;
947 crypto.cert_len = cert_size;
948 crypto.key_len = key_size;
949 ckp_index = vppcom_add_cert_key_pair (&crypto);
950 if (ckp_index < 0)
951 {
952 LDBG (0, "ERROR: failed to add cert key pair\n");
953 return -1;
954 }
955
956 ldp->ckpair_index = ckp_index;
957
Yu Ping7b74b072019-05-08 00:40:24 +0800958 return 0;
959}
960
961static int
Florin Corasa5a9efd2021-01-05 17:03:29 -0800962assign_cert_key_pair (vls_handle_t vlsh)
Yu Ping7b74b072019-05-08 00:40:24 +0800963{
Florin Corasa5a9efd2021-01-05 17:03:29 -0800964 uint32_t ckp_len;
Yu Ping7b74b072019-05-08 00:40:24 +0800965
Florin Corasa5a9efd2021-01-05 17:03:29 -0800966 if (ldp->ckpair_index == ~0 && load_cert_key_pair () < 0)
967 return -1;
968
969 ckp_len = sizeof (ldp->ckpair_index);
970 return vppcom_session_attr (vlsh_to_session_index (vlsh),
971 VPPCOM_ATTR_SET_CKPAIR, &ldp->ckpair_index,
972 &ckp_len);
Yu Ping7b74b072019-05-08 00:40:24 +0800973}
974
Dave Wallace048b1d62018-01-03 22:24:41 -0500975int
976socket (int domain, int type, int protocol)
977{
Florin Coras7baeb712019-01-04 17:05:43 -0800978 int rv, sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
Dave Wallace048b1d62018-01-03 22:24:41 -0500979 u8 is_nonblocking = type & SOCK_NONBLOCK ? 1 : 0;
Florin Coras7baeb712019-01-04 17:05:43 -0800980 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500981
Florin Coras5f33d0d2021-06-02 21:22:21 -0700982 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -0500983
984 if (((domain == AF_INET) || (domain == AF_INET6)) &&
985 ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM)))
986 {
Yu Ping7b74b072019-05-08 00:40:24 +0800987 u8 proto;
988 if (ldp->transparent_tls)
989 {
990 proto = VPPCOM_PROTO_TLS;
991 }
992 else
993 proto = ((sock_type == SOCK_DGRAM) ?
994 VPPCOM_PROTO_UDP : VPPCOM_PROTO_TCP);
Dave Wallace048b1d62018-01-03 22:24:41 -0500995
Florin Coras7baeb712019-01-04 17:05:43 -0800996 LDBG (0, "calling vls_create: proto %u (%s), is_nonblocking %u",
997 proto, vppcom_proto_str (proto), is_nonblocking);
Dave Wallace048b1d62018-01-03 22:24:41 -0500998
Florin Coras7baeb712019-01-04 17:05:43 -0800999 vlsh = vls_create (proto, is_nonblocking);
1000 if (vlsh < 0)
Dave Wallace048b1d62018-01-03 22:24:41 -05001001 {
Florin Coras7baeb712019-01-04 17:05:43 -08001002 errno = -vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001003 rv = -1;
1004 }
1005 else
1006 {
Yu Ping7b74b072019-05-08 00:40:24 +08001007 if (ldp->transparent_tls)
1008 {
Florin Corasa5a9efd2021-01-05 17:03:29 -08001009 if (assign_cert_key_pair (vlsh) < 0)
1010 return -1;
Yu Ping7b74b072019-05-08 00:40:24 +08001011 }
Florin Coras7baeb712019-01-04 17:05:43 -08001012 rv = ldp_vlsh_to_fd (vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05001013 }
1014 }
1015 else
1016 {
Florin Coras7baeb712019-01-04 17:05:43 -08001017 LDBG (0, "calling libc_socket");
Dave Wallace048b1d62018-01-03 22:24:41 -05001018 rv = libc_socket (domain, type, protocol);
1019 }
1020
Dave Wallace048b1d62018-01-03 22:24:41 -05001021 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001022}
1023
1024/*
1025 * Create two new sockets, of type TYPE in domain DOMAIN and using
1026 * protocol PROTOCOL, which are connected to each other, and put file
1027 * descriptors for them in FDS[0] and FDS[1]. If PROTOCOL is zero,
1028 * one will be chosen automatically.
1029 * Returns 0 on success, -1 for errors.
1030 * */
1031int
Dave Wallace048b1d62018-01-03 22:24:41 -05001032socketpair (int domain, int type, int protocol, int fds[2])
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001033{
Florin Coras7baeb712019-01-04 17:05:43 -08001034 int rv, sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
Dave Wallace048b1d62018-01-03 22:24:41 -05001035
Florin Coras5f33d0d2021-06-02 21:22:21 -07001036 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001037
1038 if (((domain == AF_INET) || (domain == AF_INET6)) &&
1039 ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM)))
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001040 {
Florin Coras7baeb712019-01-04 17:05:43 -08001041 LDBG (0, "LDP-TBD");
Dave Wallace048b1d62018-01-03 22:24:41 -05001042 errno = ENOSYS;
1043 rv = -1;
1044 }
1045 else
1046 {
Florin Coras7baeb712019-01-04 17:05:43 -08001047 LDBG (1, "calling libc_socketpair");
Florin Coras173bae32018-11-16 18:56:28 -08001048 rv = libc_socketpair (domain, type, protocol, fds);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001049 }
1050
Dave Wallace048b1d62018-01-03 22:24:41 -05001051 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001052}
1053
1054int
Dave Wallace048b1d62018-01-03 22:24:41 -05001055bind (int fd, __CONST_SOCKADDR_ARG addr, socklen_t len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001056{
Florin Coras7baeb712019-01-04 17:05:43 -08001057 vls_handle_t vlsh;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001058 int rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001059
Florin Coras5f33d0d2021-06-02 21:22:21 -07001060 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001061
Florin Coras7baeb712019-01-04 17:05:43 -08001062 vlsh = ldp_fd_to_vlsh (fd);
1063 if (vlsh != VLS_INVALID_HANDLE)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001064 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001065 vppcom_endpt_t ep;
1066
Dave Wallace048b1d62018-01-03 22:24:41 -05001067 switch (addr->sa_family)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001068 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001069 case AF_INET:
1070 if (len != sizeof (struct sockaddr_in))
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001071 {
Florin Coras7baeb712019-01-04 17:05:43 -08001072 LDBG (0, "ERROR: fd %d: vlsh %u: Invalid AF_INET addr len %u!",
1073 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001074 errno = EINVAL;
1075 rv = -1;
1076 goto done;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001077 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001078 ep.is_ip4 = VPPCOM_IS_IP4;
1079 ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr;
1080 ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port;
1081 break;
1082
1083 case AF_INET6:
1084 if (len != sizeof (struct sockaddr_in6))
1085 {
Florin Coras7baeb712019-01-04 17:05:43 -08001086 LDBG (0, "ERROR: fd %d: vlsh %u: Invalid AF_INET6 addr len %u!",
1087 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001088 errno = EINVAL;
1089 rv = -1;
1090 goto done;
1091 }
1092 ep.is_ip4 = VPPCOM_IS_IP6;
1093 ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
1094 ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001095 break;
1096
1097 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001098 LDBG (0, "ERROR: fd %d: vlsh %u: Unsupported address family %u!",
1099 fd, vlsh, addr->sa_family);
Dave Wallace048b1d62018-01-03 22:24:41 -05001100 errno = EAFNOSUPPORT;
1101 rv = -1;
1102 goto done;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001103 }
Florin Coras7baeb712019-01-04 17:05:43 -08001104 LDBG (0, "fd %d: calling vls_bind: vlsh %u, addr %p, len %u", fd, vlsh,
1105 addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001106
Florin Coras7baeb712019-01-04 17:05:43 -08001107 rv = vls_bind (vlsh, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001108 if (rv != VPPCOM_OK)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001109 {
1110 errno = -rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001111 rv = -1;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001112 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001113 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001114 else
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001115 {
Florin Coras7baeb712019-01-04 17:05:43 -08001116 LDBG (0, "fd %d: calling libc_bind: addr %p, len %u", fd, addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001117 rv = libc_bind (fd, addr, len);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001118 }
1119
Dave Wallace048b1d62018-01-03 22:24:41 -05001120done:
Florin Coras7baeb712019-01-04 17:05:43 -08001121 LDBG (1, "fd %d: returning %d", fd, rv);
Florin Coras05ecfcc2018-12-12 18:19:39 -08001122
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001123 return rv;
1124}
1125
1126static inline int
Dave Wallace2a865272018-02-07 21:00:42 -05001127ldp_copy_ep_to_sockaddr (__SOCKADDR_ARG addr, socklen_t * __restrict len,
1128 vppcom_endpt_t * ep)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001129{
Dave Wallace048b1d62018-01-03 22:24:41 -05001130 int rv = 0;
1131 int sa_len, copy_len;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001132
Florin Coras5f33d0d2021-06-02 21:22:21 -07001133 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001134
1135 if (addr && len && ep)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001136 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001137 addr->sa_family = (ep->is_ip4 == VPPCOM_IS_IP4) ? AF_INET : AF_INET6;
1138 switch (addr->sa_family)
1139 {
1140 case AF_INET:
1141 ((struct sockaddr_in *) addr)->sin_port = ep->port;
1142 if (*len > sizeof (struct sockaddr_in))
1143 *len = sizeof (struct sockaddr_in);
1144 sa_len = sizeof (struct sockaddr_in) - sizeof (struct in_addr);
1145 copy_len = *len - sa_len;
1146 if (copy_len > 0)
1147 memcpy (&((struct sockaddr_in *) addr)->sin_addr, ep->ip,
1148 copy_len);
1149 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001150
Dave Wallace048b1d62018-01-03 22:24:41 -05001151 case AF_INET6:
1152 ((struct sockaddr_in6 *) addr)->sin6_port = ep->port;
1153 if (*len > sizeof (struct sockaddr_in6))
1154 *len = sizeof (struct sockaddr_in6);
1155 sa_len = sizeof (struct sockaddr_in6) - sizeof (struct in6_addr);
1156 copy_len = *len - sa_len;
1157 if (copy_len > 0)
1158 memcpy (((struct sockaddr_in6 *) addr)->sin6_addr.
1159 __in6_u.__u6_addr8, ep->ip, copy_len);
1160 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001161
Dave Wallace048b1d62018-01-03 22:24:41 -05001162 default:
1163 /* Not possible */
1164 rv = -EAFNOSUPPORT;
1165 break;
1166 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001167 }
Dave Wallacee695cb42017-11-02 22:04:42 -04001168 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001169}
1170
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001171int
Dave Wallace048b1d62018-01-03 22:24:41 -05001172getsockname (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001173{
Florin Coras7baeb712019-01-04 17:05:43 -08001174 vls_handle_t vlsh;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001175 int rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001176
Florin Coras5f33d0d2021-06-02 21:22:21 -07001177 ldp_init_check ();
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001178
Florin Coras7baeb712019-01-04 17:05:43 -08001179 vlsh = ldp_fd_to_vlsh (fd);
1180 if (vlsh != VLS_INVALID_HANDLE)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001181 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001182 vppcom_endpt_t ep;
1183 u8 addr_buf[sizeof (struct in6_addr)];
1184 u32 size = sizeof (ep);
1185
1186 ep.ip = addr_buf;
Dave Wallace048b1d62018-01-03 22:24:41 -05001187
Florin Coras7baeb712019-01-04 17:05:43 -08001188 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_LCL_ADDR, &ep, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -05001189 if (rv != VPPCOM_OK)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001190 {
1191 errno = -rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001192 rv = -1;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001193 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001194 else
1195 {
Dave Wallace2a865272018-02-07 21:00:42 -05001196 rv = ldp_copy_ep_to_sockaddr (addr, len, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001197 if (rv != VPPCOM_OK)
1198 {
1199 errno = -rv;
1200 rv = -1;
1201 }
1202 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001203 }
1204 else
1205 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001206 rv = libc_getsockname (fd, addr, len);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001207 }
1208
Dave Wallace048b1d62018-01-03 22:24:41 -05001209 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001210}
1211
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001212int
Dave Wallace048b1d62018-01-03 22:24:41 -05001213connect (int fd, __CONST_SOCKADDR_ARG addr, socklen_t len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001214{
Florin Coras7baeb712019-01-04 17:05:43 -08001215 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001216 int rv;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001217
Florin Coras5f33d0d2021-06-02 21:22:21 -07001218 ldp_init_check ();
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001219
Dave Wallace048b1d62018-01-03 22:24:41 -05001220 if (!addr)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001221 {
Florin Coras7baeb712019-01-04 17:05:43 -08001222 LDBG (0, "ERROR: fd %d: NULL addr, len %u", fd, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001223 errno = EINVAL;
1224 rv = -1;
1225 goto done;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001226 }
1227
Florin Coras7baeb712019-01-04 17:05:43 -08001228 vlsh = ldp_fd_to_vlsh (fd);
1229 if (vlsh != VLS_INVALID_HANDLE)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001230 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001231 vppcom_endpt_t ep;
1232
Dave Wallace048b1d62018-01-03 22:24:41 -05001233 switch (addr->sa_family)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001234 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001235 case AF_INET:
1236 if (len != sizeof (struct sockaddr_in))
1237 {
Florin Coras7baeb712019-01-04 17:05:43 -08001238 LDBG (0, "fd %d: ERROR vlsh %u: Invalid AF_INET addr len %u!",
1239 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001240 errno = EINVAL;
1241 rv = -1;
1242 goto done;
1243 }
1244 ep.is_ip4 = VPPCOM_IS_IP4;
1245 ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr;
1246 ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port;
1247 break;
1248
1249 case AF_INET6:
1250 if (len != sizeof (struct sockaddr_in6))
1251 {
Florin Coras7baeb712019-01-04 17:05:43 -08001252 LDBG (0, "fd %d: ERROR vlsh %u: Invalid AF_INET6 addr len %u!",
1253 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001254 errno = EINVAL;
1255 rv = -1;
1256 goto done;
1257 }
1258 ep.is_ip4 = VPPCOM_IS_IP6;
1259 ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
1260 ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port;
1261 break;
1262
1263 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001264 LDBG (0, "fd %d: ERROR vlsh %u: Unsupported address family %u!",
1265 fd, vlsh, addr->sa_family);
Dave Wallace048b1d62018-01-03 22:24:41 -05001266 errno = EAFNOSUPPORT;
1267 rv = -1;
1268 goto done;
1269 }
Florin Coras7baeb712019-01-04 17:05:43 -08001270 LDBG (0, "fd %d: calling vls_connect(): vlsh %u addr %p len %u", fd,
1271 vlsh, addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001272
Florin Coras7baeb712019-01-04 17:05:43 -08001273 rv = vls_connect (vlsh, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001274 if (rv != VPPCOM_OK)
1275 {
1276 errno = -rv;
1277 rv = -1;
1278 }
1279 }
1280 else
1281 {
Florin Coras7baeb712019-01-04 17:05:43 -08001282 LDBG (0, "fd %d: calling libc_connect(): addr %p, len %u",
1283 fd, addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001284
1285 rv = libc_connect (fd, addr, len);
1286 }
1287
1288done:
Florin Coras7baeb712019-01-04 17:05:43 -08001289 LDBG (1, "fd %d: returning %d (0x%x)", fd, rv, rv);
Dave Wallace048b1d62018-01-03 22:24:41 -05001290 return rv;
1291}
1292
1293int
1294getpeername (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict len)
1295{
Florin Coras7baeb712019-01-04 17:05:43 -08001296 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001297 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001298
Florin Coras5f33d0d2021-06-02 21:22:21 -07001299 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001300
Florin Coras7baeb712019-01-04 17:05:43 -08001301 vlsh = ldp_fd_to_vlsh (fd);
1302 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001303 {
1304 vppcom_endpt_t ep;
1305 u8 addr_buf[sizeof (struct in6_addr)];
1306 u32 size = sizeof (ep);
1307
1308 ep.ip = addr_buf;
Florin Coras7baeb712019-01-04 17:05:43 -08001309 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_PEER_ADDR, &ep, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -05001310 if (rv != VPPCOM_OK)
1311 {
1312 errno = -rv;
1313 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001314 }
1315 else
1316 {
Dave Wallace2a865272018-02-07 21:00:42 -05001317 rv = ldp_copy_ep_to_sockaddr (addr, len, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001318 if (rv != VPPCOM_OK)
1319 {
1320 errno = -rv;
1321 rv = -1;
1322 }
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001323 }
1324 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001325 else
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001326 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001327 rv = libc_getpeername (fd, addr, len);
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001328 }
1329
Dave Wallace048b1d62018-01-03 22:24:41 -05001330 return rv;
1331}
1332
1333ssize_t
1334send (int fd, const void *buf, size_t n, int flags)
1335{
Florin Coras7baeb712019-01-04 17:05:43 -08001336 vls_handle_t vlsh = ldp_fd_to_vlsh (fd);
Dave Wallace048b1d62018-01-03 22:24:41 -05001337 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001338
Florin Coras5f33d0d2021-06-02 21:22:21 -07001339 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001340
Florin Coras7baeb712019-01-04 17:05:43 -08001341 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001342 {
Florin Coras7baeb712019-01-04 17:05:43 -08001343 size = vls_sendto (vlsh, (void *) buf, n, flags, NULL);
qchangaa8f63c2018-05-30 11:44:18 -07001344 if (size < VPPCOM_OK)
Dave Wallace048b1d62018-01-03 22:24:41 -05001345 {
1346 errno = -size;
1347 size = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001348 }
1349 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001350 else
1351 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001352 size = libc_send (fd, buf, n, flags);
1353 }
1354
Dave Wallace048b1d62018-01-03 22:24:41 -05001355 return size;
1356}
1357
1358ssize_t
1359sendfile (int out_fd, int in_fd, off_t * offset, size_t len)
1360{
Florin Corasdfe4cf42018-11-28 22:13:45 -08001361 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras7baeb712019-01-04 17:05:43 -08001362 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001363 ssize_t size = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -05001364
Florin Coras5f33d0d2021-06-02 21:22:21 -07001365 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001366
Florin Coras7baeb712019-01-04 17:05:43 -08001367 vlsh = ldp_fd_to_vlsh (out_fd);
1368 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001369 {
1370 int rv;
1371 ssize_t results = 0;
1372 size_t n_bytes_left = len;
1373 size_t bytes_to_read;
1374 int nbytes;
Dave Wallace048b1d62018-01-03 22:24:41 -05001375 u8 eagain = 0;
1376 u32 flags, flags_len = sizeof (flags);
1377
Florin Coras7baeb712019-01-04 17:05:43 -08001378 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_FLAGS, &flags, &flags_len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001379 if (PREDICT_FALSE (rv != VPPCOM_OK))
1380 {
Florin Coras7baeb712019-01-04 17:05:43 -08001381 LDBG (0, "ERROR: out fd %d: vls_attr: vlsh %u, returned %d (%s)!",
1382 out_fd, vlsh, rv, vppcom_retval_str (rv));
Dave Wallace048b1d62018-01-03 22:24:41 -05001383
Florin Corasdfe4cf42018-11-28 22:13:45 -08001384 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001385 errno = -rv;
1386 size = -1;
1387 goto done;
1388 }
1389
1390 if (offset)
1391 {
1392 off_t off = lseek (in_fd, *offset, SEEK_SET);
1393 if (PREDICT_FALSE (off == -1))
1394 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001395 size = -1;
1396 goto done;
1397 }
1398
1399 ASSERT (off == *offset);
1400 }
1401
1402 do
1403 {
Florin Coras7baeb712019-01-04 17:05:43 -08001404 size = vls_attr (vlsh, VPPCOM_ATTR_GET_NWRITE, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05001405 if (size < 0)
1406 {
Florin Coraseb801d02020-09-16 17:44:58 -07001407 LDBG (0, "ERROR: fd %d: vls_attr: vlsh %u returned %ld (%s)!",
Florin Coras7baeb712019-01-04 17:05:43 -08001408 out_fd, vlsh, size, vppcom_retval_str (size));
Florin Corasdfe4cf42018-11-28 22:13:45 -08001409 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001410 errno = -size;
1411 size = -1;
1412 goto done;
1413 }
1414
1415 bytes_to_read = size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001416 if (bytes_to_read == 0)
1417 {
1418 if (flags & O_NONBLOCK)
1419 {
1420 if (!results)
Florin Coras7baeb712019-01-04 17:05:43 -08001421 eagain = 1;
Dave Wallace048b1d62018-01-03 22:24:41 -05001422 goto update_offset;
1423 }
1424 else
1425 continue;
1426 }
1427 bytes_to_read = clib_min (n_bytes_left, bytes_to_read);
Florin Corasdfe4cf42018-11-28 22:13:45 -08001428 vec_validate (ldpw->io_buffer, bytes_to_read);
1429 nbytes = libc_read (in_fd, ldpw->io_buffer, bytes_to_read);
Dave Wallace048b1d62018-01-03 22:24:41 -05001430 if (nbytes < 0)
1431 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001432 if (results == 0)
1433 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08001434 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001435 size = -1;
1436 goto done;
1437 }
1438 goto update_offset;
1439 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001440
Florin Coras7baeb712019-01-04 17:05:43 -08001441 size = vls_write (vlsh, ldpw->io_buffer, nbytes);
Dave Wallace048b1d62018-01-03 22:24:41 -05001442 if (size < 0)
1443 {
1444 if (size == VPPCOM_EAGAIN)
1445 {
1446 if (flags & O_NONBLOCK)
1447 {
1448 if (!results)
Florin Coras7baeb712019-01-04 17:05:43 -08001449 eagain = 1;
Dave Wallace048b1d62018-01-03 22:24:41 -05001450 goto update_offset;
1451 }
1452 else
1453 continue;
1454 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001455 if (results == 0)
1456 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08001457 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001458 errno = -size;
1459 size = -1;
1460 goto done;
1461 }
1462 goto update_offset;
1463 }
1464
1465 results += nbytes;
1466 ASSERT (n_bytes_left >= nbytes);
1467 n_bytes_left = n_bytes_left - nbytes;
1468 }
1469 while (n_bytes_left > 0);
1470
1471 update_offset:
Florin Corasdfe4cf42018-11-28 22:13:45 -08001472 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001473 if (offset)
1474 {
1475 off_t off = lseek (in_fd, *offset, SEEK_SET);
1476 if (PREDICT_FALSE (off == -1))
1477 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001478 size = -1;
1479 goto done;
1480 }
1481
1482 ASSERT (off == *offset);
1483 *offset += results + 1;
1484 }
1485 if (eagain)
1486 {
1487 errno = EAGAIN;
1488 size = -1;
1489 }
1490 else
1491 size = results;
1492 }
1493 else
1494 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001495 size = libc_sendfile (out_fd, in_fd, offset, len);
1496 }
1497
1498done:
Dave Wallace048b1d62018-01-03 22:24:41 -05001499 return size;
1500}
1501
1502ssize_t
1503sendfile64 (int out_fd, int in_fd, off_t * offset, size_t len)
1504{
1505 return sendfile (out_fd, in_fd, offset, len);
1506}
1507
1508ssize_t
1509recv (int fd, void *buf, size_t n, int flags)
1510{
Florin Coras7baeb712019-01-04 17:05:43 -08001511 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001512 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001513
Florin Coras5f33d0d2021-06-02 21:22:21 -07001514 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001515
Florin Coras7baeb712019-01-04 17:05:43 -08001516 vlsh = ldp_fd_to_vlsh (fd);
1517 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001518 {
Florin Coras7baeb712019-01-04 17:05:43 -08001519 size = vls_recvfrom (vlsh, buf, n, flags, NULL);
Dave Wallace048b1d62018-01-03 22:24:41 -05001520 if (size < 0)
Florin Coras2a6642e2020-03-24 15:24:29 +00001521 {
1522 errno = -size;
1523 size = -1;
1524 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001525 }
1526 else
1527 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001528 size = libc_recv (fd, buf, n, flags);
1529 }
1530
Dave Wallace048b1d62018-01-03 22:24:41 -05001531 return size;
1532}
1533
Sivaprasad Tummalafdcbd382021-07-31 21:38:19 +05301534ssize_t
1535__recv_chk (int fd, void *buf, size_t n, size_t buflen, int flags)
1536{
1537 if (n > buflen)
1538 return -1;
1539
1540 return recv (fd, buf, n, flags);
1541}
1542
Florin Corasce17f462020-05-22 20:36:29 +00001543static int
1544ldp_vls_sendo (vls_handle_t vlsh, const void *buf, size_t n, int flags,
1545 __CONST_SOCKADDR_ARG addr, socklen_t addr_len)
1546{
1547 vppcom_endpt_t *ep = 0;
1548 vppcom_endpt_t _ep;
1549
1550 if (addr)
1551 {
1552 ep = &_ep;
1553 switch (addr->sa_family)
1554 {
1555 case AF_INET:
1556 ep->is_ip4 = VPPCOM_IS_IP4;
1557 ep->ip =
1558 (uint8_t *) & ((const struct sockaddr_in *) addr)->sin_addr;
1559 ep->port = (uint16_t) ((const struct sockaddr_in *) addr)->sin_port;
1560 break;
1561
1562 case AF_INET6:
1563 ep->is_ip4 = VPPCOM_IS_IP6;
1564 ep->ip =
1565 (uint8_t *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
1566 ep->port =
1567 (uint16_t) ((const struct sockaddr_in6 *) addr)->sin6_port;
1568 break;
1569
1570 default:
1571 return EAFNOSUPPORT;
1572 }
1573 }
1574
1575 return vls_sendto (vlsh, (void *) buf, n, flags, ep);
1576}
1577
1578static int
1579ldp_vls_recvfrom (vls_handle_t vlsh, void *__restrict buf, size_t n,
1580 int flags, __SOCKADDR_ARG addr,
1581 socklen_t * __restrict addr_len)
1582{
1583 u8 src_addr[sizeof (struct sockaddr_in6)];
1584 vppcom_endpt_t ep;
1585 ssize_t size;
1586 int rv;
1587
1588 if (addr)
1589 {
1590 ep.ip = src_addr;
1591 size = vls_recvfrom (vlsh, buf, n, flags, &ep);
1592
1593 if (size > 0)
1594 {
1595 rv = ldp_copy_ep_to_sockaddr (addr, addr_len, &ep);
1596 if (rv < 0)
1597 size = rv;
1598 }
1599 }
1600 else
1601 size = vls_recvfrom (vlsh, buf, n, flags, NULL);
1602
1603 return size;
1604}
1605
Dave Wallace048b1d62018-01-03 22:24:41 -05001606ssize_t
1607sendto (int fd, const void *buf, size_t n, int flags,
1608 __CONST_SOCKADDR_ARG addr, socklen_t addr_len)
1609{
Florin Coras7baeb712019-01-04 17:05:43 -08001610 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001611 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001612
Florin Coras5f33d0d2021-06-02 21:22:21 -07001613 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001614
Florin Coras7baeb712019-01-04 17:05:43 -08001615 vlsh = ldp_fd_to_vlsh (fd);
wanghanlin97c6e0d2021-07-06 15:01:48 +08001616 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001617 {
Florin Corasce17f462020-05-22 20:36:29 +00001618 size = ldp_vls_sendo (vlsh, buf, n, flags, addr, addr_len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001619 if (size < 0)
1620 {
1621 errno = -size;
1622 size = -1;
1623 }
1624 }
1625 else
1626 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001627 size = libc_sendto (fd, buf, n, flags, addr, addr_len);
1628 }
1629
Dave Wallace048b1d62018-01-03 22:24:41 -05001630 return size;
1631}
1632
1633ssize_t
1634recvfrom (int fd, void *__restrict buf, size_t n, int flags,
1635 __SOCKADDR_ARG addr, socklen_t * __restrict addr_len)
1636{
Florin Corasce17f462020-05-22 20:36:29 +00001637 vls_handle_t vlsh;
1638 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001639
Florin Coras5f33d0d2021-06-02 21:22:21 -07001640 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001641
Florin Corasce17f462020-05-22 20:36:29 +00001642 vlsh = ldp_fd_to_vlsh (fd);
1643 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001644 {
Florin Corasce17f462020-05-22 20:36:29 +00001645 size = ldp_vls_recvfrom (vlsh, buf, n, flags, addr, addr_len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001646 if (size < 0)
1647 {
1648 errno = -size;
1649 size = -1;
1650 }
1651 }
1652 else
1653 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001654 size = libc_recvfrom (fd, buf, n, flags, addr, addr_len);
1655 }
1656
Dave Wallace048b1d62018-01-03 22:24:41 -05001657 return size;
1658}
1659
1660ssize_t
Florin Corasce17f462020-05-22 20:36:29 +00001661sendmsg (int fd, const struct msghdr * msg, int flags)
Dave Wallace048b1d62018-01-03 22:24:41 -05001662{
Florin Coras7baeb712019-01-04 17:05:43 -08001663 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001664 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001665
Florin Coras5f33d0d2021-06-02 21:22:21 -07001666 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001667
Florin Coras7baeb712019-01-04 17:05:43 -08001668 vlsh = ldp_fd_to_vlsh (fd);
1669 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001670 {
Florin Corasce17f462020-05-22 20:36:29 +00001671 struct iovec *iov = msg->msg_iov;
1672 ssize_t total = 0;
1673 int i, rv;
1674
1675 for (i = 0; i < msg->msg_iovlen; ++i)
1676 {
1677 rv = ldp_vls_sendo (vlsh, iov[i].iov_base, iov[i].iov_len, flags,
1678 msg->msg_name, msg->msg_namelen);
1679 if (rv < 0)
1680 break;
1681 else
1682 {
1683 total += rv;
1684 if (rv < iov[i].iov_len)
1685 break;
1686 }
1687 }
1688
1689 if (rv < 0 && total == 0)
1690 {
1691 errno = -rv;
1692 size = -1;
1693 }
1694 else
1695 size = total;
Dave Wallace048b1d62018-01-03 22:24:41 -05001696 }
1697 else
1698 {
Florin Corasce17f462020-05-22 20:36:29 +00001699 size = libc_sendmsg (fd, msg, flags);
Dave Wallace048b1d62018-01-03 22:24:41 -05001700 }
1701
Dave Wallace048b1d62018-01-03 22:24:41 -05001702 return size;
1703}
1704
1705#ifdef USE_GNU
1706int
1707sendmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags)
1708{
1709 ssize_t size;
1710 const char *func_str;
Florin Coras7baeb712019-01-04 17:05:43 -08001711 u32 sh = ldp_fd_to_vlsh (fd);
Dave Wallace048b1d62018-01-03 22:24:41 -05001712
Florin Coras5f33d0d2021-06-02 21:22:21 -07001713 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001714
wanghanlin97c6e0d2021-07-06 15:01:48 +08001715 if (sh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001716 {
1717 clib_warning ("LDP<%d>: LDP-TBD", getpid ());
1718 errno = ENOSYS;
1719 size = -1;
1720 }
1721 else
1722 {
1723 func_str = "libc_sendmmsg";
1724
Dave Wallace2a865272018-02-07 21:00:42 -05001725 if (LDP_DEBUG > 2)
Dave Wallace048b1d62018-01-03 22:24:41 -05001726 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1727 "vmessages %p, vlen %u, flags 0x%x",
1728 getpid (), fd, fd, func_str, vmessages, vlen, flags);
1729
1730 size = libc_sendmmsg (fd, vmessages, vlen, flags);
1731 }
1732
Dave Wallace2a865272018-02-07 21:00:42 -05001733 if (LDP_DEBUG > 2)
Dave Wallace048b1d62018-01-03 22:24:41 -05001734 {
1735 if (size < 0)
1736 {
1737 int errno_val = errno;
1738 perror (func_str);
1739 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1740 "rv %d, errno = %d", getpid (), fd, fd,
1741 func_str, size, errno_val);
1742 errno = errno_val;
1743 }
1744 else
1745 clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1746 getpid (), fd, fd, size, size);
1747 }
1748 return size;
1749}
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001750#endif
1751
Dave Wallace048b1d62018-01-03 22:24:41 -05001752ssize_t
Florin Corasce17f462020-05-22 20:36:29 +00001753recvmsg (int fd, struct msghdr * msg, int flags)
Dave Wallace048b1d62018-01-03 22:24:41 -05001754{
Florin Coras7baeb712019-01-04 17:05:43 -08001755 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001756 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001757
Florin Coras5f33d0d2021-06-02 21:22:21 -07001758 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001759
Florin Coras7baeb712019-01-04 17:05:43 -08001760 vlsh = ldp_fd_to_vlsh (fd);
1761 if (vlsh != VLS_INVALID_HANDLE)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001762 {
Florin Corasce17f462020-05-22 20:36:29 +00001763 struct iovec *iov = msg->msg_iov;
1764 ssize_t max_deq, total = 0;
1765 int i, rv;
1766
1767 max_deq = vls_attr (vlsh, VPPCOM_ATTR_GET_NREAD, 0, 0);
1768 if (!max_deq)
1769 return 0;
1770
1771 for (i = 0; i < msg->msg_iovlen; i++)
1772 {
1773 rv = ldp_vls_recvfrom (vlsh, iov[i].iov_base, iov[i].iov_len, flags,
1774 (i == 0 ? msg->msg_name : NULL),
1775 (i == 0 ? &msg->msg_namelen : NULL));
1776 if (rv <= 0)
1777 break;
1778 else
1779 {
1780 total += rv;
1781 if (rv < iov[i].iov_len)
1782 break;
1783 }
1784 if (total >= max_deq)
1785 break;
1786 }
1787
1788 if (rv < 0 && total == 0)
1789 {
1790 errno = -rv;
1791 size = -1;
1792 }
1793 else
1794 size = total;
Dave Wallace048b1d62018-01-03 22:24:41 -05001795 }
1796 else
1797 {
Florin Corasce17f462020-05-22 20:36:29 +00001798 size = libc_recvmsg (fd, msg, flags);
Dave Wallace048b1d62018-01-03 22:24:41 -05001799 }
1800
Dave Wallace048b1d62018-01-03 22:24:41 -05001801 return size;
1802}
1803
1804#ifdef USE_GNU
1805int
1806recvmmsg (int fd, struct mmsghdr *vmessages,
1807 unsigned int vlen, int flags, struct timespec *tmo)
1808{
1809 ssize_t size;
1810 const char *func_str;
Florin Coras7baeb712019-01-04 17:05:43 -08001811 u32 sh = ldp_fd_to_vlsh (fd);
Dave Wallace048b1d62018-01-03 22:24:41 -05001812
Florin Coras5f33d0d2021-06-02 21:22:21 -07001813 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001814
wanghanlin97c6e0d2021-07-06 15:01:48 +08001815 if (sh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001816 {
1817 clib_warning ("LDP<%d>: LDP-TBD", getpid ());
1818 errno = ENOSYS;
1819 size = -1;
1820 }
1821 else
1822 {
1823 func_str = "libc_recvmmsg";
1824
Dave Wallace2a865272018-02-07 21:00:42 -05001825 if (LDP_DEBUG > 2)
Dave Wallace048b1d62018-01-03 22:24:41 -05001826 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1827 "vmessages %p, vlen %u, flags 0x%x, tmo %p",
1828 getpid (), fd, fd, func_str, vmessages, vlen,
1829 flags, tmo);
1830
1831 size = libc_recvmmsg (fd, vmessages, vlen, flags, tmo);
1832 }
1833
Dave Wallace2a865272018-02-07 21:00:42 -05001834 if (LDP_DEBUG > 2)
Dave Wallace048b1d62018-01-03 22:24:41 -05001835 {
1836 if (size < 0)
1837 {
1838 int errno_val = errno;
1839 perror (func_str);
1840 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1841 "rv %d, errno = %d", getpid (), fd, fd,
1842 func_str, size, errno_val);
1843 errno = errno_val;
1844 }
1845 else
1846 clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1847 getpid (), fd, fd, size, size);
1848 }
1849 return size;
1850}
1851#endif
1852
1853int
1854getsockopt (int fd, int level, int optname,
1855 void *__restrict optval, socklen_t * __restrict optlen)
1856{
Florin Coras7baeb712019-01-04 17:05:43 -08001857 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001858 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001859
Florin Coras5f33d0d2021-06-02 21:22:21 -07001860 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001861
Florin Coras7baeb712019-01-04 17:05:43 -08001862 vlsh = ldp_fd_to_vlsh (fd);
1863 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001864 {
1865 rv = -EOPNOTSUPP;
1866
1867 switch (level)
1868 {
1869 case SOL_TCP:
1870 switch (optname)
1871 {
1872 case TCP_NODELAY:
Florin Coras7baeb712019-01-04 17:05:43 -08001873 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_NODELAY,
1874 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001875 break;
1876 case TCP_MAXSEG:
Florin Coras7baeb712019-01-04 17:05:43 -08001877 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_USER_MSS,
1878 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001879 break;
1880 case TCP_KEEPIDLE:
Florin Coras7baeb712019-01-04 17:05:43 -08001881 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_KEEPIDLE,
1882 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001883 break;
1884 case TCP_KEEPINTVL:
Florin Coras7baeb712019-01-04 17:05:43 -08001885 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_KEEPINTVL,
1886 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001887 break;
1888 case TCP_INFO:
1889 if (optval && optlen && (*optlen == sizeof (struct tcp_info)))
1890 {
Florin Coras7baeb712019-01-04 17:05:43 -08001891 LDBG (1, "fd %d: vlsh %u SOL_TCP, TCP_INFO, optval %p, "
1892 "optlen %d: #LDP-NOP#", fd, vlsh, optval, *optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001893 memset (optval, 0, *optlen);
1894 rv = VPPCOM_OK;
1895 }
1896 else
1897 rv = -EFAULT;
1898 break;
Florin Coras0ed24e92019-01-21 09:03:10 -08001899 case TCP_CONGESTION:
Florin Coras0ed24e92019-01-21 09:03:10 -08001900 *optlen = strlen ("cubic");
Dave Barach02500902020-04-04 18:34:41 -04001901 strncpy (optval, "cubic", *optlen + 1);
Florin Coras0ed24e92019-01-21 09:03:10 -08001902 rv = 0;
1903 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05001904 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001905 LDBG (0, "ERROR: fd %d: getsockopt SOL_TCP: sid %u, "
1906 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05001907 break;
1908 }
1909 break;
1910 case SOL_IPV6:
1911 switch (optname)
1912 {
1913 case IPV6_V6ONLY:
Florin Coras7baeb712019-01-04 17:05:43 -08001914 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_V6ONLY, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001915 break;
1916 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001917 LDBG (0, "ERROR: fd %d: getsockopt SOL_IPV6: vlsh %u "
1918 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05001919 break;
1920 }
1921 break;
1922 case SOL_SOCKET:
1923 switch (optname)
1924 {
1925 case SO_ACCEPTCONN:
Florin Coras7baeb712019-01-04 17:05:43 -08001926 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_LISTEN, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001927 break;
1928 case SO_KEEPALIVE:
Florin Coras7baeb712019-01-04 17:05:43 -08001929 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_KEEPALIVE, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001930 break;
1931 case SO_PROTOCOL:
Florin Coras7baeb712019-01-04 17:05:43 -08001932 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_PROTOCOL, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001933 *(int *) optval = *(int *) optval ? SOCK_DGRAM : SOCK_STREAM;
1934 break;
1935 case SO_SNDBUF:
Florin Coras7baeb712019-01-04 17:05:43 -08001936 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TX_FIFO_LEN,
1937 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001938 break;
1939 case SO_RCVBUF:
Florin Coras7baeb712019-01-04 17:05:43 -08001940 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_RX_FIFO_LEN,
1941 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001942 break;
1943 case SO_REUSEADDR:
Florin Coras7baeb712019-01-04 17:05:43 -08001944 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_REUSEADDR, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001945 break;
wanghanlin0674f852021-02-22 10:38:36 +08001946 case SO_REUSEPORT:
1947 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_REUSEPORT, optval, optlen);
1948 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05001949 case SO_BROADCAST:
Florin Coras7baeb712019-01-04 17:05:43 -08001950 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_BROADCAST, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001951 break;
wanghanlin0674f852021-02-22 10:38:36 +08001952 case SO_DOMAIN:
1953 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_DOMAIN, optval, optlen);
1954 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05001955 case SO_ERROR:
Florin Coras7baeb712019-01-04 17:05:43 -08001956 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_ERROR, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001957 break;
Florin Coras8eb8d502021-06-16 14:46:57 -07001958 case SO_BINDTODEVICE:
1959 rv = 0;
1960 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05001961 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001962 LDBG (0, "ERROR: fd %d: getsockopt SOL_SOCKET: vlsh %u "
1963 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05001964 break;
1965 }
1966 break;
1967 default:
1968 break;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001969 }
1970
Dave Wallace048b1d62018-01-03 22:24:41 -05001971 if (rv != VPPCOM_OK)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001972 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001973 errno = -rv;
1974 rv = -1;
1975 }
1976 }
1977 else
1978 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001979 rv = libc_getsockopt (fd, level, optname, optval, optlen);
1980 }
1981
Dave Wallace048b1d62018-01-03 22:24:41 -05001982 return rv;
1983}
1984
1985int
1986setsockopt (int fd, int level, int optname,
1987 const void *optval, socklen_t optlen)
1988{
Florin Coras7baeb712019-01-04 17:05:43 -08001989 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001990 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001991
Florin Coras5f33d0d2021-06-02 21:22:21 -07001992 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001993
Florin Coras7baeb712019-01-04 17:05:43 -08001994 vlsh = ldp_fd_to_vlsh (fd);
1995 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001996 {
1997 rv = -EOPNOTSUPP;
1998
1999 switch (level)
2000 {
2001 case SOL_TCP:
2002 switch (optname)
2003 {
2004 case TCP_NODELAY:
Florin Coras7baeb712019-01-04 17:05:43 -08002005 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_NODELAY,
2006 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002007 break;
2008 case TCP_MAXSEG:
Florin Coras7baeb712019-01-04 17:05:43 -08002009 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_USER_MSS,
2010 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002011 break;
2012 case TCP_KEEPIDLE:
Florin Coras7baeb712019-01-04 17:05:43 -08002013 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_KEEPIDLE,
2014 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002015 break;
2016 case TCP_KEEPINTVL:
Florin Coras7baeb712019-01-04 17:05:43 -08002017 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_KEEPINTVL,
2018 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002019 break;
Florin Coras0ed24e92019-01-21 09:03:10 -08002020 case TCP_CONGESTION:
Florin Coras8509aa22019-04-04 12:55:30 -07002021 case TCP_CORK:
Florin Coras0ed24e92019-01-21 09:03:10 -08002022 /* Ignore */
2023 rv = 0;
2024 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05002025 default:
Florin Coras7baeb712019-01-04 17:05:43 -08002026 LDBG (0, "ERROR: fd %d: setsockopt() SOL_TCP: vlsh %u"
2027 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05002028 break;
2029 }
2030 break;
2031 case SOL_IPV6:
2032 switch (optname)
2033 {
2034 case IPV6_V6ONLY:
Florin Coras7baeb712019-01-04 17:05:43 -08002035 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_V6ONLY,
2036 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002037 break;
2038 default:
Florin Coras7baeb712019-01-04 17:05:43 -08002039 LDBG (0, "ERROR: fd %d: setsockopt SOL_IPV6: vlsh %u"
2040 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05002041 break;
2042 }
2043 break;
2044 case SOL_SOCKET:
2045 switch (optname)
2046 {
2047 case SO_KEEPALIVE:
Florin Coras7baeb712019-01-04 17:05:43 -08002048 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_KEEPALIVE,
2049 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002050 break;
2051 case SO_REUSEADDR:
Florin Coras7baeb712019-01-04 17:05:43 -08002052 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_REUSEADDR,
2053 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002054 break;
wanghanlin0674f852021-02-22 10:38:36 +08002055 case SO_REUSEPORT:
2056 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_REUSEPORT, (void *) optval,
2057 &optlen);
2058 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05002059 case SO_BROADCAST:
Florin Coras7baeb712019-01-04 17:05:43 -08002060 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_BROADCAST,
2061 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002062 break;
Florin Coras2f647902021-06-02 08:23:50 -07002063 case SO_LINGER:
2064 rv = 0;
2065 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05002066 default:
Florin Coras7baeb712019-01-04 17:05:43 -08002067 LDBG (0, "ERROR: fd %d: setsockopt SOL_SOCKET: vlsh %u "
2068 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05002069 break;
2070 }
2071 break;
2072 default:
2073 break;
2074 }
2075
2076 if (rv != VPPCOM_OK)
2077 {
2078 errno = -rv;
2079 rv = -1;
2080 }
2081 }
2082 else
2083 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002084 rv = libc_setsockopt (fd, level, optname, optval, optlen);
2085 }
2086
Dave Wallace048b1d62018-01-03 22:24:41 -05002087 return rv;
2088}
2089
2090int
2091listen (int fd, int n)
2092{
Florin Coras7baeb712019-01-04 17:05:43 -08002093 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002094 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05002095
Florin Coras5f33d0d2021-06-02 21:22:21 -07002096 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05002097
Florin Coras7baeb712019-01-04 17:05:43 -08002098 vlsh = ldp_fd_to_vlsh (fd);
2099 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05002100 {
Florin Coras7baeb712019-01-04 17:05:43 -08002101 LDBG (0, "fd %d: calling vls_listen: vlsh %u, n %d", fd, vlsh, n);
Dave Wallace048b1d62018-01-03 22:24:41 -05002102
Florin Coras7baeb712019-01-04 17:05:43 -08002103 rv = vls_listen (vlsh, n);
Dave Wallace048b1d62018-01-03 22:24:41 -05002104 if (rv != VPPCOM_OK)
2105 {
2106 errno = -rv;
2107 rv = -1;
2108 }
2109 }
2110 else
2111 {
Florin Coras7baeb712019-01-04 17:05:43 -08002112 LDBG (0, "fd %d: calling libc_listen(): n %d", fd, n);
Dave Wallace048b1d62018-01-03 22:24:41 -05002113 rv = libc_listen (fd, n);
2114 }
2115
Florin Coras7baeb712019-01-04 17:05:43 -08002116 LDBG (1, "fd %d: returning %d", fd, rv);
Dave Wallace048b1d62018-01-03 22:24:41 -05002117 return rv;
2118}
2119
2120static inline int
Dave Wallace2a865272018-02-07 21:00:42 -05002121ldp_accept4 (int listen_fd, __SOCKADDR_ARG addr,
2122 socklen_t * __restrict addr_len, int flags)
Dave Wallace048b1d62018-01-03 22:24:41 -05002123{
Florin Coras7baeb712019-01-04 17:05:43 -08002124 vls_handle_t listen_vlsh, accept_vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002125 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05002126
Florin Coras5f33d0d2021-06-02 21:22:21 -07002127 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05002128
Florin Coras7baeb712019-01-04 17:05:43 -08002129 listen_vlsh = ldp_fd_to_vlsh (listen_fd);
2130 if (listen_vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05002131 {
2132 vppcom_endpt_t ep;
2133 u8 src_addr[sizeof (struct sockaddr_in6)];
Dave Wallace8aaba562018-01-18 17:21:19 -05002134 memset (&ep, 0, sizeof (ep));
Dave Wallace048b1d62018-01-03 22:24:41 -05002135 ep.ip = src_addr;
2136
Florin Coras7baeb712019-01-04 17:05:43 -08002137 LDBG (0, "listen fd %d: calling vppcom_session_accept: listen sid %u,"
Florin Coraseb801d02020-09-16 17:44:58 -07002138 " ep %p, flags 0x%x", listen_fd, listen_vlsh, &ep, flags);
Dave Wallace048b1d62018-01-03 22:24:41 -05002139
Florin Coras7baeb712019-01-04 17:05:43 -08002140 accept_vlsh = vls_accept (listen_vlsh, &ep, flags);
2141 if (accept_vlsh < 0)
Dave Wallace048b1d62018-01-03 22:24:41 -05002142 {
Florin Coras7baeb712019-01-04 17:05:43 -08002143 errno = -accept_vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002144 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002145 }
2146 else
2147 {
Dave Wallace2a865272018-02-07 21:00:42 -05002148 rv = ldp_copy_ep_to_sockaddr (addr, addr_len, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05002149 if (rv != VPPCOM_OK)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002150 {
Florin Coras7baeb712019-01-04 17:05:43 -08002151 (void) vls_close (accept_vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05002152 errno = -rv;
2153 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002154 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002155 else
2156 {
Florin Coras7baeb712019-01-04 17:05:43 -08002157 rv = ldp_vlsh_to_fd (accept_vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05002158 }
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002159 }
2160 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002161 else
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002162 {
Florin Coras7baeb712019-01-04 17:05:43 -08002163 LDBG (0, "listen fd %d: calling libc_accept4(): addr %p, addr_len %p,"
2164 " flags 0x%x", listen_fd, addr, addr_len, flags);
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002165
Dave Wallace048b1d62018-01-03 22:24:41 -05002166 rv = libc_accept4 (listen_fd, addr, addr_len, flags);
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002167 }
2168
Florin Coras7baeb712019-01-04 17:05:43 -08002169 LDBG (1, "listen fd %d: accept returning %d", listen_fd, rv);
Florin Coras05ecfcc2018-12-12 18:19:39 -08002170
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002171 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002172}
2173
Dave Wallace048b1d62018-01-03 22:24:41 -05002174int
2175accept4 (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len,
2176 int flags)
2177{
Dave Wallace2a865272018-02-07 21:00:42 -05002178 return ldp_accept4 (fd, addr, addr_len, flags);
Dave Wallace048b1d62018-01-03 22:24:41 -05002179}
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002180
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002181int
Dave Wallace048b1d62018-01-03 22:24:41 -05002182accept (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002183{
Dave Wallace2a865272018-02-07 21:00:42 -05002184 return ldp_accept4 (fd, addr, addr_len, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002185}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002186
Dave Wallace048b1d62018-01-03 22:24:41 -05002187int
2188shutdown (int fd, int how)
2189{
Florin Coras7baeb712019-01-04 17:05:43 -08002190 vls_handle_t vlsh;
liuyacan55c952e2021-06-13 14:54:55 +08002191 int rv = 0;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002192
Florin Coras5f33d0d2021-06-02 21:22:21 -07002193 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05002194
Florin Coras7baeb712019-01-04 17:05:43 -08002195 vlsh = ldp_fd_to_vlsh (fd);
2196 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05002197 {
Florin Coras7baeb712019-01-04 17:05:43 -08002198 LDBG (0, "called shutdown: fd %u vlsh %u how %d", fd, vlsh, how);
liuyacan55c952e2021-06-13 14:54:55 +08002199 rv = vls_shutdown (vlsh, how);
Dave Wallace048b1d62018-01-03 22:24:41 -05002200 }
2201 else
2202 {
Florin Coras7baeb712019-01-04 17:05:43 -08002203 LDBG (0, "fd %d: calling libc_shutdown: how %d", fd, how);
Dave Wallace048b1d62018-01-03 22:24:41 -05002204 rv = libc_shutdown (fd, how);
2205 }
2206
Dave Wallace048b1d62018-01-03 22:24:41 -05002207 return rv;
2208}
2209
2210int
2211epoll_create1 (int flags)
2212{
Florin Corasdfe4cf42018-11-28 22:13:45 -08002213 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras7baeb712019-01-04 17:05:43 -08002214 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002215 int rv;
2216
Florin Coras5f33d0d2021-06-02 21:22:21 -07002217 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05002218
hanlina3a48962020-07-13 11:09:15 +08002219 if (ldp->vcl_needs_real_epoll || vls_use_real_epoll ())
Florin Coras99368312018-08-02 10:45:44 -07002220 {
Florin Coras2d9b4272019-03-11 10:14:37 -07002221 /* Make sure workers have been allocated */
2222 if (!ldp->workers)
2223 {
2224 ldp_alloc_workers ();
2225 ldpw = ldp_worker_get_current ();
2226 }
Florin Coras99368312018-08-02 10:45:44 -07002227 rv = libc_epoll_create1 (flags);
2228 ldp->vcl_needs_real_epoll = 0;
Florin Corasdfe4cf42018-11-28 22:13:45 -08002229 ldpw->vcl_mq_epfd = rv;
Florin Coras05ecfcc2018-12-12 18:19:39 -08002230 LDBG (0, "created vcl epfd %u", rv);
Florin Coras99368312018-08-02 10:45:44 -07002231 return rv;
2232 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002233
Florin Coras7baeb712019-01-04 17:05:43 -08002234 vlsh = vls_epoll_create ();
2235 if (PREDICT_FALSE (vlsh == VLS_INVALID_HANDLE))
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002236 {
Florin Coras7baeb712019-01-04 17:05:43 -08002237 errno = -vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002238 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002239 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002240 else
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002241 {
Florin Coras7baeb712019-01-04 17:05:43 -08002242 rv = ldp_vlsh_to_fd (vlsh);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002243 }
Florin Coras7baeb712019-01-04 17:05:43 -08002244 LDBG (0, "epoll_create epfd %u vlsh %u", rv, vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05002245 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002246}
2247
2248int
Dave Wallace048b1d62018-01-03 22:24:41 -05002249epoll_create (int size)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002250{
Dave Wallace048b1d62018-01-03 22:24:41 -05002251 return epoll_create1 (0);
2252}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002253
Dave Wallace048b1d62018-01-03 22:24:41 -05002254int
2255epoll_ctl (int epfd, int op, int fd, struct epoll_event *event)
2256{
Florin Coras7baeb712019-01-04 17:05:43 -08002257 vls_handle_t vep_vlsh, vlsh;
Florin Coras99368312018-08-02 10:45:44 -07002258 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05002259
Florin Coras5f33d0d2021-06-02 21:22:21 -07002260 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05002261
Florin Coras7baeb712019-01-04 17:05:43 -08002262 vep_vlsh = ldp_fd_to_vlsh (epfd);
2263 if (PREDICT_FALSE (vep_vlsh == VLS_INVALID_HANDLE))
Dave Wallace048b1d62018-01-03 22:24:41 -05002264 {
Dave Wallace3ee1fe12018-02-23 01:09:11 -05002265 /* The LDP epoll_create1 always creates VCL epfd's.
2266 * The app should never have a kernel base epoll fd unless it
2267 * was acquired outside of the LD_PRELOAD process context.
2268 * In any case, if we get one, punt it to libc_epoll_ctl.
2269 */
Florin Coras7baeb712019-01-04 17:05:43 -08002270 LDBG (1, "epfd %d: calling libc_epoll_ctl: op %d, fd %d"
2271 " event %p", epfd, op, fd, event);
Dave Wallace048b1d62018-01-03 22:24:41 -05002272
2273 rv = libc_epoll_ctl (epfd, op, fd, event);
Florin Coras99368312018-08-02 10:45:44 -07002274 goto done;
2275 }
2276
Florin Coras7baeb712019-01-04 17:05:43 -08002277 vlsh = ldp_fd_to_vlsh (fd);
Florin Coras99368312018-08-02 10:45:44 -07002278
Florin Coras7baeb712019-01-04 17:05:43 -08002279 LDBG (0, "epfd %d ep_vlsh %d, fd %u vlsh %d, op %u", epfd, vep_vlsh, fd,
2280 vlsh, op);
Florin Coras99368312018-08-02 10:45:44 -07002281
Florin Coras7baeb712019-01-04 17:05:43 -08002282 if (vlsh != VLS_INVALID_HANDLE)
Florin Coras99368312018-08-02 10:45:44 -07002283 {
Florin Coras7baeb712019-01-04 17:05:43 -08002284 LDBG (1, "epfd %d: calling vls_epoll_ctl: ep_vlsh %d op %d, vlsh %u,"
Florin Coraseb801d02020-09-16 17:44:58 -07002285 " event %p", epfd, vep_vlsh, op, vlsh, event);
Florin Coras99368312018-08-02 10:45:44 -07002286
Florin Coras7baeb712019-01-04 17:05:43 -08002287 rv = vls_epoll_ctl (vep_vlsh, op, vlsh, event);
Florin Coras99368312018-08-02 10:45:44 -07002288 if (rv != VPPCOM_OK)
2289 {
2290 errno = -rv;
2291 rv = -1;
2292 }
2293 }
2294 else
2295 {
2296 int libc_epfd;
2297 u32 size = sizeof (epfd);
2298
Florin Coras7baeb712019-01-04 17:05:43 -08002299 libc_epfd = vls_attr (vep_vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
Florin Coras99368312018-08-02 10:45:44 -07002300 if (!libc_epfd)
2301 {
Florin Coras7baeb712019-01-04 17:05:43 -08002302 LDBG (1, "epfd %d, vep_vlsh %d calling libc_epoll_create1: "
2303 "EPOLL_CLOEXEC", epfd, vep_vlsh);
Florin Coras99368312018-08-02 10:45:44 -07002304
2305 libc_epfd = libc_epoll_create1 (EPOLL_CLOEXEC);
2306 if (libc_epfd < 0)
2307 {
2308 rv = libc_epfd;
2309 goto done;
2310 }
2311
Florin Coras7baeb712019-01-04 17:05:43 -08002312 rv = vls_attr (vep_vlsh, VPPCOM_ATTR_SET_LIBC_EPFD, &libc_epfd,
2313 &size);
Florin Coras99368312018-08-02 10:45:44 -07002314 if (rv < 0)
2315 {
2316 errno = -rv;
2317 rv = -1;
2318 goto done;
2319 }
2320 }
2321 else if (PREDICT_FALSE (libc_epfd < 0))
2322 {
2323 errno = -epfd;
2324 rv = -1;
2325 goto done;
2326 }
2327
Florin Coras7baeb712019-01-04 17:05:43 -08002328 LDBG (1, "epfd %d: calling libc_epoll_ctl: libc_epfd %d, op %d, fd %d,"
2329 " event %p", epfd, libc_epfd, op, fd, event);
Florin Coras99368312018-08-02 10:45:44 -07002330
2331 rv = libc_epoll_ctl (libc_epfd, op, fd, event);
Dave Wallace048b1d62018-01-03 22:24:41 -05002332 }
2333
2334done:
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002335 return rv;
2336}
Dave Wallace048b1d62018-01-03 22:24:41 -05002337
2338static inline int
Florin Coras99368312018-08-02 10:45:44 -07002339ldp_epoll_pwait (int epfd, struct epoll_event *events, int maxevents,
2340 int timeout, const sigset_t * sigmask)
Dave Wallace048b1d62018-01-03 22:24:41 -05002341{
Florin Corasdfe4cf42018-11-28 22:13:45 -08002342 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras72f77822019-01-22 19:05:52 -08002343 double time_to_wait = (double) 0, max_time;
Florin Coras99368312018-08-02 10:45:44 -07002344 int libc_epfd, rv = 0;
Florin Coras7baeb712019-01-04 17:05:43 -08002345 vls_handle_t ep_vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002346
Florin Coras5f33d0d2021-06-02 21:22:21 -07002347 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05002348
2349 if (PREDICT_FALSE (!events || (timeout < -1)))
2350 {
2351 errno = EFAULT;
2352 return -1;
2353 }
2354
Florin Corasdfe4cf42018-11-28 22:13:45 -08002355 if (epfd == ldpw->vcl_mq_epfd)
Florin Coras99368312018-08-02 10:45:44 -07002356 return libc_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
2357
Florin Coras7baeb712019-01-04 17:05:43 -08002358 ep_vlsh = ldp_fd_to_vlsh (epfd);
2359 if (PREDICT_FALSE (ep_vlsh == VLS_INVALID_HANDLE))
Dave Wallace048b1d62018-01-03 22:24:41 -05002360 {
Florin Coras7baeb712019-01-04 17:05:43 -08002361 LDBG (0, "epfd %d: bad ep_vlsh %d!", epfd, ep_vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05002362 errno = EBADFD;
2363 return -1;
2364 }
2365
Florin Coras4dee8cd2019-01-29 21:28:16 -08002366 if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
2367 clib_time_init (&ldpw->clib_time);
Florin Corasb0f662f2018-12-27 14:51:46 -08002368 time_to_wait = ((timeout >= 0) ? (double) timeout / 1000 : 0);
Florin Coras72f77822019-01-22 19:05:52 -08002369 max_time = clib_time_now (&ldpw->clib_time) + time_to_wait;
Dave Wallace048b1d62018-01-03 22:24:41 -05002370
Florin Coras7baeb712019-01-04 17:05:43 -08002371 libc_epfd = vls_attr (ep_vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002372 if (PREDICT_FALSE (libc_epfd < 0))
2373 {
2374 errno = -libc_epfd;
2375 rv = -1;
2376 goto done;
2377 }
2378
Florin Coras7baeb712019-01-04 17:05:43 -08002379 LDBG (2, "epfd %d: vep_idx %d, libc_epfd %d, events %p, maxevents %d, "
2380 "timeout %d, sigmask %p: time_to_wait %.02f", epfd, ep_vlsh,
Florin Coras72f77822019-01-22 19:05:52 -08002381 libc_epfd, events, maxevents, timeout, sigmask, time_to_wait);
Dave Wallace048b1d62018-01-03 22:24:41 -05002382 do
2383 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002384 if (!ldpw->epoll_wait_vcl)
Dave Wallace048b1d62018-01-03 22:24:41 -05002385 {
Florin Coras7baeb712019-01-04 17:05:43 -08002386 rv = vls_epoll_wait (ep_vlsh, events, maxevents, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002387 if (rv > 0)
2388 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002389 ldpw->epoll_wait_vcl = 1;
Dave Wallace048b1d62018-01-03 22:24:41 -05002390 goto done;
2391 }
2392 else if (rv < 0)
2393 {
2394 errno = -rv;
2395 rv = -1;
2396 goto done;
2397 }
2398 }
2399 else
Florin Corasdfe4cf42018-11-28 22:13:45 -08002400 ldpw->epoll_wait_vcl = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -05002401
2402 if (libc_epfd > 0)
2403 {
Florin Corasb0f662f2018-12-27 14:51:46 -08002404 rv = libc_epoll_pwait (libc_epfd, events, maxevents, 0, sigmask);
Dave Wallace048b1d62018-01-03 22:24:41 -05002405 if (rv != 0)
2406 goto done;
2407 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002408 }
Florin Coras72f77822019-01-22 19:05:52 -08002409 while ((timeout == -1) || (clib_time_now (&ldpw->clib_time) < max_time));
Dave Wallace048b1d62018-01-03 22:24:41 -05002410
2411done:
Dave Wallace048b1d62018-01-03 22:24:41 -05002412 return rv;
2413}
2414
hanlin4266d4d2020-05-19 17:34:17 +08002415static inline int
2416ldp_epoll_pwait_eventfd (int epfd, struct epoll_event *events,
2417 int maxevents, int timeout, const sigset_t * sigmask)
2418{
hanlina3a48962020-07-13 11:09:15 +08002419 ldp_worker_ctx_t *ldpw;
hanlin4266d4d2020-05-19 17:34:17 +08002420 int libc_epfd, rv = 0, num_ev;
2421 vls_handle_t ep_vlsh;
2422
Florin Coras5f33d0d2021-06-02 21:22:21 -07002423 ldp_init_check ();
hanlin4266d4d2020-05-19 17:34:17 +08002424
2425 if (PREDICT_FALSE (!events || (timeout < -1)))
2426 {
2427 errno = EFAULT;
2428 return -1;
2429 }
2430
Florin Corasff40d8f2020-08-11 22:05:28 -07002431 /* Make sure the vcl worker is valid. Could be that epoll fd was created on
2432 * one thread but it is now used on another */
2433 if (PREDICT_FALSE (vppcom_worker_index () == ~0))
2434 vls_register_vcl_worker ();
hanlina3a48962020-07-13 11:09:15 +08002435
2436 ldpw = ldp_worker_get_current ();
hanlin4266d4d2020-05-19 17:34:17 +08002437 if (epfd == ldpw->vcl_mq_epfd)
2438 return libc_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
2439
2440 ep_vlsh = ldp_fd_to_vlsh (epfd);
2441 if (PREDICT_FALSE (ep_vlsh == VLS_INVALID_HANDLE))
2442 {
2443 LDBG (0, "epfd %d: bad ep_vlsh %d!", epfd, ep_vlsh);
2444 errno = EBADFD;
2445 return -1;
2446 }
2447
2448 libc_epfd = vls_attr (ep_vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
2449 if (PREDICT_FALSE (!libc_epfd))
2450 {
2451 u32 size = sizeof (epfd);
2452
2453 LDBG (1, "epfd %d, vep_vlsh %d calling libc_epoll_create1: "
2454 "EPOLL_CLOEXEC", epfd, ep_vlsh);
2455 libc_epfd = libc_epoll_create1 (EPOLL_CLOEXEC);
2456 if (libc_epfd < 0)
2457 {
2458 rv = libc_epfd;
2459 goto done;
2460 }
2461
2462 rv = vls_attr (ep_vlsh, VPPCOM_ATTR_SET_LIBC_EPFD, &libc_epfd, &size);
2463 if (rv < 0)
2464 {
2465 errno = -rv;
2466 rv = -1;
2467 goto done;
2468 }
2469 }
2470 if (PREDICT_FALSE (libc_epfd <= 0))
2471 {
2472 errno = -libc_epfd;
2473 rv = -1;
2474 goto done;
2475 }
2476
2477 if (PREDICT_FALSE (!ldpw->mq_epfd_added))
2478 {
2479 struct epoll_event e = { 0 };
2480 e.events = EPOLLIN;
2481 e.data.fd = ldpw->vcl_mq_epfd;
2482 if (libc_epoll_ctl (libc_epfd, EPOLL_CTL_ADD, ldpw->vcl_mq_epfd, &e) <
2483 0)
2484 {
2485 LDBG (0, "epfd %d, add libc mq epoll fd %d to libc epoll fd %d",
2486 epfd, ldpw->vcl_mq_epfd, libc_epfd);
2487 rv = -1;
2488 goto done;
2489 }
2490 ldpw->mq_epfd_added = 1;
2491 }
2492
wanghanlin8919fec2021-03-18 20:00:41 +08002493 /* Request to only drain unhandled to prevent libc_epoll_wait starved */
2494 rv = vls_epoll_wait (ep_vlsh, events, maxevents, -2);
hanlin4266d4d2020-05-19 17:34:17 +08002495 if (rv > 0)
2496 goto done;
hanlina3a48962020-07-13 11:09:15 +08002497 else if (PREDICT_FALSE (rv < 0))
hanlin4266d4d2020-05-19 17:34:17 +08002498 {
2499 errno = -rv;
2500 rv = -1;
2501 goto done;
2502 }
2503
2504 rv = libc_epoll_pwait (libc_epfd, events, maxevents, timeout, sigmask);
2505 if (rv <= 0)
2506 goto done;
2507 for (int i = 0; i < rv; i++)
2508 {
2509 if (events[i].data.fd == ldpw->vcl_mq_epfd)
2510 {
2511 /* We should remove mq epoll fd from events. */
2512 rv--;
2513 if (i != rv)
2514 {
2515 events[i].events = events[rv].events;
2516 events[i].data.u64 = events[rv].data.u64;
2517 }
2518 num_ev = vls_epoll_wait (ep_vlsh, &events[rv], maxevents - rv, 0);
2519 if (PREDICT_TRUE (num_ev > 0))
2520 rv += num_ev;
2521 break;
2522 }
2523 }
2524
2525done:
2526 return rv;
2527}
2528
Dave Wallace048b1d62018-01-03 22:24:41 -05002529int
2530epoll_pwait (int epfd, struct epoll_event *events,
2531 int maxevents, int timeout, const sigset_t * sigmask)
2532{
hanlin4266d4d2020-05-19 17:34:17 +08002533 if (vls_use_eventfd ())
2534 return ldp_epoll_pwait_eventfd (epfd, events, maxevents, timeout,
2535 sigmask);
2536 else
2537 return ldp_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
Dave Wallace048b1d62018-01-03 22:24:41 -05002538}
2539
2540int
2541epoll_wait (int epfd, struct epoll_event *events, int maxevents, int timeout)
2542{
hanlin4266d4d2020-05-19 17:34:17 +08002543 if (vls_use_eventfd ())
2544 return ldp_epoll_pwait_eventfd (epfd, events, maxevents, timeout, NULL);
2545 else
2546 return ldp_epoll_pwait (epfd, events, maxevents, timeout, NULL);
Dave Wallace048b1d62018-01-03 22:24:41 -05002547}
2548
2549int
2550poll (struct pollfd *fds, nfds_t nfds, int timeout)
2551{
Florin Corasdfe4cf42018-11-28 22:13:45 -08002552 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras6917b942018-11-13 22:44:54 -08002553 int rv, i, n_revents = 0;
Florin Coras7baeb712019-01-04 17:05:43 -08002554 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002555 vcl_poll_t *vp;
Florin Coras4dee8cd2019-01-29 21:28:16 -08002556 double max_time;
Dave Wallace048b1d62018-01-03 22:24:41 -05002557
Florin Coraseb801d02020-09-16 17:44:58 -07002558 LDBG (3, "fds %p, nfds %ld, timeout %d", fds, nfds, timeout);
Dave Wallace048b1d62018-01-03 22:24:41 -05002559
Florin Coras4dee8cd2019-01-29 21:28:16 -08002560 if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
2561 clib_time_init (&ldpw->clib_time);
2562
2563 max_time = (timeout >= 0) ? (f64) timeout / 1000 : 0;
2564 max_time += clib_time_now (&ldpw->clib_time);
Dave Wallace048b1d62018-01-03 22:24:41 -05002565
Dave Wallace048b1d62018-01-03 22:24:41 -05002566 for (i = 0; i < nfds; i++)
2567 {
Florin Coras6917b942018-11-13 22:44:54 -08002568 if (fds[i].fd < 0)
2569 continue;
Dave Wallace048b1d62018-01-03 22:24:41 -05002570
Florin Coras7baeb712019-01-04 17:05:43 -08002571 vlsh = ldp_fd_to_vlsh (fds[i].fd);
2572 if (vlsh != VLS_INVALID_HANDLE)
Florin Coras6917b942018-11-13 22:44:54 -08002573 {
2574 fds[i].fd = -fds[i].fd;
Florin Corasdfe4cf42018-11-28 22:13:45 -08002575 vec_add2 (ldpw->vcl_poll, vp, 1);
Florin Coras6917b942018-11-13 22:44:54 -08002576 vp->fds_ndx = i;
Florin Coras7baeb712019-01-04 17:05:43 -08002577 vp->sh = vlsh_to_sh (vlsh);
Florin Coras6917b942018-11-13 22:44:54 -08002578 vp->events = fds[i].events;
Dave Wallace048b1d62018-01-03 22:24:41 -05002579#ifdef __USE_XOPEN2K
Florin Coras6917b942018-11-13 22:44:54 -08002580 if (fds[i].events & POLLRDNORM)
2581 vp->events |= POLLIN;
2582 if (fds[i].events & POLLWRNORM)
2583 vp->events |= POLLOUT;
Dave Wallace048b1d62018-01-03 22:24:41 -05002584#endif
Florin Coras6917b942018-11-13 22:44:54 -08002585 vp->revents = fds[i].revents;
2586 }
2587 else
2588 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002589 vec_add1 (ldpw->libc_poll, fds[i]);
2590 vec_add1 (ldpw->libc_poll_idxs, i);
Dave Wallace048b1d62018-01-03 22:24:41 -05002591 }
2592 }
2593
Dave Wallace048b1d62018-01-03 22:24:41 -05002594 do
2595 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002596 if (vec_len (ldpw->vcl_poll))
Dave Wallace048b1d62018-01-03 22:24:41 -05002597 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002598 rv = vppcom_poll (ldpw->vcl_poll, vec_len (ldpw->vcl_poll), 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002599 if (rv < 0)
2600 {
2601 errno = -rv;
2602 rv = -1;
2603 goto done;
2604 }
2605 else
2606 n_revents += rv;
2607 }
2608
Florin Corasdfe4cf42018-11-28 22:13:45 -08002609 if (vec_len (ldpw->libc_poll))
Dave Wallace048b1d62018-01-03 22:24:41 -05002610 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002611 rv = libc_poll (ldpw->libc_poll, vec_len (ldpw->libc_poll), 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002612 if (rv < 0)
2613 goto done;
2614 else
2615 n_revents += rv;
2616 }
2617
2618 if (n_revents)
2619 {
2620 rv = n_revents;
2621 goto done;
2622 }
2623 }
Florin Coras4dee8cd2019-01-29 21:28:16 -08002624 while ((timeout < 0) || (clib_time_now (&ldpw->clib_time) < max_time));
Dave Wallace048b1d62018-01-03 22:24:41 -05002625 rv = 0;
2626
2627done:
Florin Corasdfe4cf42018-11-28 22:13:45 -08002628 vec_foreach (vp, ldpw->vcl_poll)
Dave Wallace048b1d62018-01-03 22:24:41 -05002629 {
2630 fds[vp->fds_ndx].fd = -fds[vp->fds_ndx].fd;
Florin Coras6917b942018-11-13 22:44:54 -08002631 fds[vp->fds_ndx].revents = vp->revents;
Dave Wallace048b1d62018-01-03 22:24:41 -05002632#ifdef __USE_XOPEN2K
2633 if ((fds[vp->fds_ndx].revents & POLLIN) &&
2634 (fds[vp->fds_ndx].events & POLLRDNORM))
2635 fds[vp->fds_ndx].revents |= POLLRDNORM;
2636 if ((fds[vp->fds_ndx].revents & POLLOUT) &&
2637 (fds[vp->fds_ndx].events & POLLWRNORM))
2638 fds[vp->fds_ndx].revents |= POLLWRNORM;
2639#endif
2640 }
Florin Corasdfe4cf42018-11-28 22:13:45 -08002641 vec_reset_length (ldpw->vcl_poll);
Dave Wallace048b1d62018-01-03 22:24:41 -05002642
Florin Corasdfe4cf42018-11-28 22:13:45 -08002643 for (i = 0; i < vec_len (ldpw->libc_poll); i++)
Florin Coras6917b942018-11-13 22:44:54 -08002644 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002645 fds[ldpw->libc_poll_idxs[i]].revents = ldpw->libc_poll[i].revents;
Florin Coras6917b942018-11-13 22:44:54 -08002646 }
Florin Corasdfe4cf42018-11-28 22:13:45 -08002647 vec_reset_length (ldpw->libc_poll_idxs);
2648 vec_reset_length (ldpw->libc_poll);
Florin Coras6917b942018-11-13 22:44:54 -08002649
Dave Wallace048b1d62018-01-03 22:24:41 -05002650 return rv;
2651}
2652
2653#ifdef USE_GNU
2654int
2655ppoll (struct pollfd *fds, nfds_t nfds,
2656 const struct timespec *timeout, const sigset_t * sigmask)
2657{
Florin Coras5f33d0d2021-06-02 21:22:21 -07002658 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05002659
2660 clib_warning ("LDP<%d>: LDP-TBD", getpid ());
2661 errno = ENOSYS;
2662
2663
2664 return -1;
2665}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002666#endif
2667
Dave Wallace2a865272018-02-07 21:00:42 -05002668void CONSTRUCTOR_ATTRIBUTE ldp_constructor (void);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002669
Dave Wallace2a865272018-02-07 21:00:42 -05002670void DESTRUCTOR_ATTRIBUTE ldp_destructor (void);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002671
Dave Wallace048b1d62018-01-03 22:24:41 -05002672/*
2673 * This function is called when the library is loaded
2674 */
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002675void
Dave Wallace2a865272018-02-07 21:00:42 -05002676ldp_constructor (void)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002677{
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002678 swrap_constructor ();
Dave Wallace2a865272018-02-07 21:00:42 -05002679 if (ldp_init () != 0)
Florin Corasd89411e2019-03-19 19:44:51 -07002680 {
2681 fprintf (stderr, "\nLDP<%d>: ERROR: ldp_constructor: failed!\n",
2682 getpid ());
2683 _exit (1);
2684 }
Dave Wallace69d01192018-02-22 16:22:09 -05002685 else if (LDP_DEBUG > 0)
Dave Wallace2a865272018-02-07 21:00:42 -05002686 clib_warning ("LDP<%d>: LDP constructor: done!\n", getpid ());
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002687}
2688
2689/*
2690 * This function is called when the library is unloaded
2691 */
2692void
Dave Wallace2a865272018-02-07 21:00:42 -05002693ldp_destructor (void)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002694{
Florin Coras0ef8ef22019-01-18 08:37:13 -08002695 /*
2696 swrap_destructor ();
2697 if (ldp->init)
2698 ldp->init = 0;
2699 */
Dave Wallace048b1d62018-01-03 22:24:41 -05002700
2701 /* Don't use clib_warning() here because that calls writev()
Dave Wallace2a865272018-02-07 21:00:42 -05002702 * which will call ldp_init().
Dave Wallace048b1d62018-01-03 22:24:41 -05002703 */
Dave Wallace69d01192018-02-22 16:22:09 -05002704 if (LDP_DEBUG > 0)
Florin Coras0ef8ef22019-01-18 08:37:13 -08002705 fprintf (stderr, "%s:%d: LDP<%d>: LDP destructor: done!\n",
2706 __func__, __LINE__, getpid ());
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002707}
2708
2709
2710/*
2711 * fd.io coding-style-patch-verification: ON
2712 *
2713 * Local Variables:
2714 * eval: (c-set-style "gnu")
2715 * End:
2716 */