blob: 7aa38305249db4dfac1b46392c75275aa1c97c0d [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;
Florin Coras99368312018-08-02 10:45:44 -070083 int vcl_mq_epfd;
Florin Corasdfe4cf42018-11-28 22:13:45 -080084
85} ldp_worker_ctx_t;
86
Florin Coras294afe22019-01-07 17:49:17 -080087/* clib_bitmap_t, fd_mask and vcl_si_set are used interchangeably. Make sure
88 * they are the same size */
89STATIC_ASSERT (sizeof (clib_bitmap_t) == sizeof (fd_mask),
90 "ldp bitmap size mismatch");
91STATIC_ASSERT (sizeof (vcl_si_set) == sizeof (fd_mask),
92 "ldp bitmap size mismatch");
93
Florin Corasdfe4cf42018-11-28 22:13:45 -080094typedef struct
95{
96 ldp_worker_ctx_t *workers;
97 int init;
98 char app_name[LDP_APP_NAME_MAX];
Florin Coras7baeb712019-01-04 17:05:43 -080099 u32 vlsh_bit_val;
100 u32 vlsh_bit_mask;
Florin Corasdfe4cf42018-11-28 22:13:45 -0800101 u32 debug;
Yu Ping7b74b072019-05-08 00:40:24 +0800102 u8 transparent_tls;
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;
Dave Wallace2a865272018-02-07 21:00:42 -0500106} ldp_main_t;
Florin Corasdfe4cf42018-11-28 22:13:45 -0800107
Dave Wallace2a865272018-02-07 21:00:42 -0500108#define LDP_DEBUG ldp->debug
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700109
Florin Coras99368312018-08-02 10:45:44 -0700110#define LDBG(_lvl, _fmt, _args...) \
111 if (ldp->debug > _lvl) \
Florin Coras05ecfcc2018-12-12 18:19:39 -0800112 clib_warning ("ldp<%d>: " _fmt, getpid(), ##_args)
Florin Coras99368312018-08-02 10:45:44 -0700113
Dave Wallace2a865272018-02-07 21:00:42 -0500114static ldp_main_t ldp_main = {
Florin Coras7baeb712019-01-04 17:05:43 -0800115 .vlsh_bit_val = (1 << LDP_SID_BIT_MIN),
116 .vlsh_bit_mask = (1 << LDP_SID_BIT_MIN) - 1,
Dave Wallace2a865272018-02-07 21:00:42 -0500117 .debug = LDP_DEBUG_INIT,
Yu Ping7b74b072019-05-08 00:40:24 +0800118 .transparent_tls = 0,
Dave Wallace048b1d62018-01-03 22:24:41 -0500119};
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700120
Dave Wallace2a865272018-02-07 21:00:42 -0500121static ldp_main_t *ldp = &ldp_main;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700122
Florin Corasdfe4cf42018-11-28 22:13:45 -0800123static inline ldp_worker_ctx_t *
124ldp_worker_get_current (void)
125{
126 return (ldp->workers + vppcom_worker_index ());
127}
128
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700129/*
130 * RETURN: 0 on success or -1 on error.
131 * */
Dave Wallace048b1d62018-01-03 22:24:41 -0500132static inline void
Dave Wallace2a865272018-02-07 21:00:42 -0500133ldp_set_app_name (char *app_name)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700134{
Benoît Ganne747b3d82019-08-21 18:27:23 +0200135 snprintf (ldp->app_name, LDP_APP_NAME_MAX,
136 "ldp-%d-%s", getpid (), app_name);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700137}
138
Dave Wallace048b1d62018-01-03 22:24:41 -0500139static inline char *
Dave Wallace2a865272018-02-07 21:00:42 -0500140ldp_get_app_name ()
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700141{
Dave Wallace2a865272018-02-07 21:00:42 -0500142 if (ldp->app_name[0] == '\0')
143 ldp_set_app_name ("app");
Dave Wallace048b1d62018-01-03 22:24:41 -0500144
Dave Wallace2a865272018-02-07 21:00:42 -0500145 return ldp->app_name;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700146}
147
Dave Wallace048b1d62018-01-03 22:24:41 -0500148static inline int
Florin Coras7baeb712019-01-04 17:05:43 -0800149ldp_vlsh_to_fd (vls_handle_t vlsh)
Dave Wallace048b1d62018-01-03 22:24:41 -0500150{
Florin Coras7baeb712019-01-04 17:05:43 -0800151 return (vlsh + ldp->vlsh_bit_val);
Dave Wallace048b1d62018-01-03 22:24:41 -0500152}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700153
Florin Coras7baeb712019-01-04 17:05:43 -0800154static inline vls_handle_t
155ldp_fd_to_vlsh (int fd)
Dave Wallace048b1d62018-01-03 22:24:41 -0500156{
Florin Coras7baeb712019-01-04 17:05:43 -0800157 if (fd < ldp->vlsh_bit_val)
158 return VLS_INVALID_HANDLE;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700159
Florin Coras7baeb712019-01-04 17:05:43 -0800160 return (fd - ldp->vlsh_bit_val);
Dave Wallace048b1d62018-01-03 22:24:41 -0500161}
162
Florin Coras2d9b4272019-03-11 10:14:37 -0700163static void
164ldp_alloc_workers (void)
165{
166 if (ldp->workers)
167 return;
168 pool_alloc (ldp->workers, LDP_MAX_NWORKERS);
169}
170
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700171static inline int
Dave Wallace2a865272018-02-07 21:00:42 -0500172ldp_init (void)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700173{
Florin Corasdfe4cf42018-11-28 22:13:45 -0800174 ldp_worker_ctx_t *ldpw;
Florin Coras99368312018-08-02 10:45:44 -0700175 int rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700176
Florin Coras99368312018-08-02 10:45:44 -0700177 if (PREDICT_TRUE (ldp->init))
178 return 0;
179
180 ldp->init = 1;
181 ldp->vcl_needs_real_epoll = 1;
Florin Coras7baeb712019-01-04 17:05:43 -0800182 rv = vls_app_create (ldp_get_app_name ());
Florin Coras99368312018-08-02 10:45:44 -0700183 if (rv != VPPCOM_OK)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700184 {
Florin Coras955bfbb2018-12-04 13:43:45 -0800185 ldp->vcl_needs_real_epoll = 0;
186 if (rv == VPPCOM_EEXIST)
187 return 0;
Florin Coras05ecfcc2018-12-12 18:19:39 -0800188 LDBG (2, "\nERROR: ldp_init: vppcom_app_create()"
189 " failed! rv = %d (%s)\n", rv, vppcom_retval_str (rv));
Florin Coras99368312018-08-02 10:45:44 -0700190 ldp->init = 0;
191 return rv;
192 }
193 ldp->vcl_needs_real_epoll = 0;
Florin Coras2d9b4272019-03-11 10:14:37 -0700194 ldp_alloc_workers ();
Florin Corasdfe4cf42018-11-28 22:13:45 -0800195 ldpw = ldp_worker_get_current ();
Florin Coras99368312018-08-02 10:45:44 -0700196
197 char *env_var_str = getenv (LDP_ENV_DEBUG);
198 if (env_var_str)
199 {
200 u32 tmp;
201 if (sscanf (env_var_str, "%u", &tmp) != 1)
202 clib_warning ("LDP<%d>: WARNING: Invalid LDP debug level specified in"
203 " the env var " LDP_ENV_DEBUG " (%s)!", getpid (),
204 env_var_str);
205 else
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700206 {
Florin Coras99368312018-08-02 10:45:44 -0700207 ldp->debug = tmp;
Florin Coras05ecfcc2018-12-12 18:19:39 -0800208 LDBG (0, "configured LDP debug level (%u) from env var "
209 LDP_ENV_DEBUG "!", ldp->debug);
Florin Coras99368312018-08-02 10:45:44 -0700210 }
211 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500212
Florin Coras99368312018-08-02 10:45:44 -0700213 env_var_str = getenv (LDP_ENV_APP_NAME);
214 if (env_var_str)
215 {
216 ldp_set_app_name (env_var_str);
Florin Coras05ecfcc2018-12-12 18:19:39 -0800217 LDBG (0, "configured LDP app name (%s) from the env var "
218 LDP_ENV_APP_NAME "!", ldp->app_name);
Florin Coras99368312018-08-02 10:45:44 -0700219 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500220
Florin Coras99368312018-08-02 10:45:44 -0700221 env_var_str = getenv (LDP_ENV_SID_BIT);
222 if (env_var_str)
223 {
224 u32 sb;
225 if (sscanf (env_var_str, "%u", &sb) != 1)
226 {
Florin Coras294afe22019-01-07 17:49:17 -0800227 LDBG (0, "WARNING: Invalid LDP sid bit specified in the env var "
228 LDP_ENV_SID_BIT " (%s)! sid bit value %d (0x%x)", env_var_str,
229 ldp->vlsh_bit_val, ldp->vlsh_bit_val);
Florin Coras99368312018-08-02 10:45:44 -0700230 }
231 else if (sb < LDP_SID_BIT_MIN)
232 {
Florin Coras7baeb712019-01-04 17:05:43 -0800233 ldp->vlsh_bit_val = (1 << LDP_SID_BIT_MIN);
234 ldp->vlsh_bit_mask = ldp->vlsh_bit_val - 1;
Dave Wallace048b1d62018-01-03 22:24:41 -0500235
Florin Coras294afe22019-01-07 17:49:17 -0800236 LDBG (0, "WARNING: LDP sid bit (%u) specified in the env var "
237 LDP_ENV_SID_BIT " (%s) is too small. Using LDP_SID_BIT_MIN"
238 " (%d)! sid bit value %d (0x%x)", sb, env_var_str,
239 LDP_SID_BIT_MIN, ldp->vlsh_bit_val, ldp->vlsh_bit_val);
Florin Coras99368312018-08-02 10:45:44 -0700240 }
241 else if (sb > LDP_SID_BIT_MAX)
242 {
Florin Coras7baeb712019-01-04 17:05:43 -0800243 ldp->vlsh_bit_val = (1 << LDP_SID_BIT_MAX);
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 big. Using LDP_SID_BIT_MAX"
248 " (%d)! sid bit value %d (0x%x)", sb, env_var_str,
249 LDP_SID_BIT_MAX, ldp->vlsh_bit_val, ldp->vlsh_bit_val);
Dave Wallace048b1d62018-01-03 22:24:41 -0500250 }
251 else
252 {
Florin Coras7baeb712019-01-04 17:05:43 -0800253 ldp->vlsh_bit_val = (1 << sb);
254 ldp->vlsh_bit_mask = ldp->vlsh_bit_val - 1;
Florin Coras99368312018-08-02 10:45:44 -0700255
Florin Coras05ecfcc2018-12-12 18:19:39 -0800256 LDBG (0, "configured LDP sid bit (%u) from "
257 LDP_ENV_SID_BIT "! sid bit value %d (0x%x)", sb,
Florin Coras7baeb712019-01-04 17:05:43 -0800258 ldp->vlsh_bit_val, ldp->vlsh_bit_val);
Dave Wallace048b1d62018-01-03 22:24:41 -0500259 }
Florin Coras294afe22019-01-07 17:49:17 -0800260
261 /* Make sure there are enough bits in the fd set for vcl sessions */
262 if (ldp->vlsh_bit_val > FD_SETSIZE / 2)
263 {
264 LDBG (0, "ERROR: LDP vlsh bit value %d > FD_SETSIZE/2 %d!",
265 ldp->vlsh_bit_val, FD_SETSIZE / 2);
266 ldp->init = 0;
267 return -1;
268 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500269 }
Yu Ping7b74b072019-05-08 00:40:24 +0800270 env_var_str = getenv (LDP_ENV_TLS_TRANS);
271 if (env_var_str)
272 {
273 ldp->transparent_tls = 1;
274 }
Florin Coras99368312018-08-02 10:45:44 -0700275
Florin Coras4dee8cd2019-01-29 21:28:16 -0800276 /* *INDENT-OFF* */
277 pool_foreach (ldpw, ldp->workers, ({
278 clib_memset (&ldpw->clib_time, 0, sizeof (ldpw->clib_time));
279 }));
280 /* *INDENT-ON* */
281
Florin Coras05ecfcc2018-12-12 18:19:39 -0800282 LDBG (0, "LDP initialization: done!");
Florin Coras99368312018-08-02 10:45:44 -0700283
284 return 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500285}
286
287int
288close (int fd)
289{
Florin Coras7baeb712019-01-04 17:05:43 -0800290 vls_handle_t vlsh;
291 int rv, epfd;
Dave Wallace048b1d62018-01-03 22:24:41 -0500292
Dave Wallace2a865272018-02-07 21:00:42 -0500293 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500294 return -1;
295
Florin Coras7baeb712019-01-04 17:05:43 -0800296 vlsh = ldp_fd_to_vlsh (fd);
297 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500298 {
Florin Coras7baeb712019-01-04 17:05:43 -0800299 epfd = vls_attr (vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -0500300 if (epfd > 0)
301 {
Florin Coras7baeb712019-01-04 17:05:43 -0800302 LDBG (0, "fd %d: calling libc_close: epfd %u", fd, epfd);
Dave Wallace048b1d62018-01-03 22:24:41 -0500303
304 rv = libc_close (epfd);
305 if (rv < 0)
306 {
307 u32 size = sizeof (epfd);
308 epfd = 0;
309
Florin Coras7baeb712019-01-04 17:05:43 -0800310 (void) vls_attr (vlsh, VPPCOM_ATTR_SET_LIBC_EPFD, &epfd, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -0500311 }
312 }
313 else if (PREDICT_FALSE (epfd < 0))
314 {
315 errno = -epfd;
316 rv = -1;
317 goto done;
318 }
319
Florin Coras7baeb712019-01-04 17:05:43 -0800320 LDBG (0, "fd %d: calling vls_close: vlsh %u", fd, vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -0500321
Florin Coras7baeb712019-01-04 17:05:43 -0800322 rv = vls_close (vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -0500323 if (rv != VPPCOM_OK)
324 {
325 errno = -rv;
326 rv = -1;
327 }
328 }
329 else
330 {
Florin Coras7baeb712019-01-04 17:05:43 -0800331 LDBG (0, "fd %d: calling libc_close", fd);
Dave Wallace048b1d62018-01-03 22:24:41 -0500332 rv = libc_close (fd);
333 }
334
335done:
Dave Wallace048b1d62018-01-03 22:24:41 -0500336 return rv;
337}
338
339ssize_t
340read (int fd, void *buf, size_t nbytes)
341{
Florin Coras7baeb712019-01-04 17:05:43 -0800342 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500343 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -0500344
Dave Wallace2a865272018-02-07 21:00:42 -0500345 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500346 return -1;
347
Florin Coras7baeb712019-01-04 17:05:43 -0800348 vlsh = ldp_fd_to_vlsh (fd);
349 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500350 {
Florin Coras7baeb712019-01-04 17:05:43 -0800351 size = vls_read (vlsh, buf, nbytes);
Dave Wallace048b1d62018-01-03 22:24:41 -0500352 if (size < 0)
353 {
354 errno = -size;
355 size = -1;
356 }
357 }
358 else
359 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500360 size = libc_read (fd, buf, nbytes);
361 }
362
Dave Wallace048b1d62018-01-03 22:24:41 -0500363 return size;
364}
365
366ssize_t
367readv (int fd, const struct iovec * iov, int iovcnt)
368{
Dave Wallace8aaba562018-01-18 17:21:19 -0500369 int rv = 0, i, total = 0;
Florin Coras7baeb712019-01-04 17:05:43 -0800370 vls_handle_t vlsh;
371 ssize_t size = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500372
Dave Wallace2a865272018-02-07 21:00:42 -0500373 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500374 return -1;
375
Florin Coras7baeb712019-01-04 17:05:43 -0800376 vlsh = ldp_fd_to_vlsh (fd);
377 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500378 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500379 do
380 {
381 for (i = 0; i < iovcnt; ++i)
382 {
Florin Coras7baeb712019-01-04 17:05:43 -0800383 rv = vls_read (vlsh, iov[i].iov_base, iov[i].iov_len);
Dave Wallace048b1d62018-01-03 22:24:41 -0500384 if (rv < 0)
385 break;
386 else
387 {
388 total += rv;
389 if (rv < iov[i].iov_len)
Florin Coras7baeb712019-01-04 17:05:43 -0800390 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700391 }
392 }
393 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500394 while ((rv >= 0) && (total == 0));
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700395
Dave Wallace048b1d62018-01-03 22:24:41 -0500396 if (rv < 0)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700397 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500398 errno = -rv;
399 size = -1;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700400 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500401 else
402 size = total;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700403 }
404 else
405 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500406 size = libc_readv (fd, iov, iovcnt);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700407 }
408
Dave Wallace048b1d62018-01-03 22:24:41 -0500409 return size;
410}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700411
Dave Wallace048b1d62018-01-03 22:24:41 -0500412ssize_t
413write (int fd, const void *buf, size_t nbytes)
414{
Florin Coras7baeb712019-01-04 17:05:43 -0800415 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500416 ssize_t size = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500417
Dave Wallace2a865272018-02-07 21:00:42 -0500418 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500419 return -1;
420
Florin Coras7baeb712019-01-04 17:05:43 -0800421 vlsh = ldp_fd_to_vlsh (fd);
422 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500423 {
Florin Coras7baeb712019-01-04 17:05:43 -0800424 size = vls_write_msg (vlsh, (void *) buf, nbytes);
Dave Wallace048b1d62018-01-03 22:24:41 -0500425 if (size < 0)
426 {
427 errno = -size;
428 size = -1;
429 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700430 }
431 else
432 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500433 size = libc_write (fd, buf, nbytes);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700434 }
435
Dave Wallace048b1d62018-01-03 22:24:41 -0500436 return size;
437}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700438
Dave Wallace048b1d62018-01-03 22:24:41 -0500439ssize_t
440writev (int fd, const struct iovec * iov, int iovcnt)
441{
Dave Wallace048b1d62018-01-03 22:24:41 -0500442 ssize_t size = 0, total = 0;
Florin Coras7baeb712019-01-04 17:05:43 -0800443 vls_handle_t vlsh;
Dave Wallace8aaba562018-01-18 17:21:19 -0500444 int i, rv = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500445
Dave Wallace2a865272018-02-07 21:00:42 -0500446 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500447 return -1;
448
Florin Coras7baeb712019-01-04 17:05:43 -0800449 vlsh = ldp_fd_to_vlsh (fd);
450 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500451 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500452 do
453 {
454 for (i = 0; i < iovcnt; ++i)
455 {
Florin Coras7baeb712019-01-04 17:05:43 -0800456 rv = vls_write_msg (vlsh, iov[i].iov_base, iov[i].iov_len);
Dave Wallace048b1d62018-01-03 22:24:41 -0500457 if (rv < 0)
458 break;
459 else
460 {
461 total += rv;
462 if (rv < iov[i].iov_len)
Florin Corasb0f662f2018-12-27 14:51:46 -0800463 break;
Dave Wallace048b1d62018-01-03 22:24:41 -0500464 }
465 }
466 }
467 while ((rv >= 0) && (total == 0));
468
469 if (rv < 0)
470 {
471 errno = -rv;
472 size = -1;
473 }
474 else
475 size = total;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700476 }
477 else
478 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500479 size = libc_writev (fd, iov, iovcnt);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700480 }
481
Dave Wallace048b1d62018-01-03 22:24:41 -0500482 return size;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700483}
484
485int
Dave Wallace048b1d62018-01-03 22:24:41 -0500486fcntl (int fd, int cmd, ...)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700487{
Florin Coras7baeb712019-01-04 17:05:43 -0800488 vls_handle_t vlsh;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700489 int rv = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500490 va_list ap;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700491
Dave Wallace2a865272018-02-07 21:00:42 -0500492 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500493 return -1;
494
495 va_start (ap, cmd);
Florin Coras7baeb712019-01-04 17:05:43 -0800496
497 vlsh = ldp_fd_to_vlsh (fd);
498 LDBG (0, "fd %u vlsh %d, cmd %u", fd, vlsh, cmd);
499 if (vlsh != VLS_INVALID_HANDLE)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700500 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500501 int flags = va_arg (ap, int);
502 u32 size;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700503
Dave Wallace048b1d62018-01-03 22:24:41 -0500504 size = sizeof (flags);
505 rv = -EOPNOTSUPP;
506 switch (cmd)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700507 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500508 case F_SETFL:
Florin Coras7baeb712019-01-04 17:05:43 -0800509 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_FLAGS, &flags, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -0500510 break;
511
512 case F_GETFL:
Florin Coras7baeb712019-01-04 17:05:43 -0800513 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_FLAGS, &flags, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -0500514 if (rv == VPPCOM_OK)
Florin Coras7baeb712019-01-04 17:05:43 -0800515 rv = flags;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700516 break;
Florin Coras173bae32018-11-16 18:56:28 -0800517 case F_SETFD:
518 /* TODO handle this */
519 LDBG (0, "F_SETFD ignored flags %u", flags);
520 rv = 0;
521 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700522 default:
Dave Wallace048b1d62018-01-03 22:24:41 -0500523 rv = -EOPNOTSUPP;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700524 break;
525 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500526 if (rv < 0)
527 {
528 errno = -rv;
529 rv = -1;
530 }
531 }
532 else
533 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500534 rv = libc_vfcntl (fd, cmd, ap);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700535 }
536
Dave Wallace048b1d62018-01-03 22:24:41 -0500537 va_end (ap);
538
Dave Wallace048b1d62018-01-03 22:24:41 -0500539 return rv;
540}
541
542int
543ioctl (int fd, unsigned long int cmd, ...)
544{
Florin Coras7baeb712019-01-04 17:05:43 -0800545 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500546 va_list ap;
Florin Coras7baeb712019-01-04 17:05:43 -0800547 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -0500548
Dave Wallace2a865272018-02-07 21:00:42 -0500549 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500550 return -1;
551
552 va_start (ap, cmd);
Dave Wallace048b1d62018-01-03 22:24:41 -0500553
Florin Coras7baeb712019-01-04 17:05:43 -0800554 vlsh = ldp_fd_to_vlsh (fd);
555 if (vlsh != VLS_INVALID_HANDLE)
556 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500557 switch (cmd)
558 {
559 case FIONREAD:
Florin Coras7baeb712019-01-04 17:05:43 -0800560 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_NREAD, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -0500561 break;
562
563 case FIONBIO:
564 {
565 u32 flags = va_arg (ap, int) ? O_NONBLOCK : 0;
566 u32 size = sizeof (flags);
567
568 /* TBD: When VPPCOM_ATTR_[GS]ET_FLAGS supports flags other than
569 * non-blocking, the flags should be read here and merged
570 * with O_NONBLOCK.
571 */
Florin Coras7baeb712019-01-04 17:05:43 -0800572 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_FLAGS, &flags, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -0500573 }
574 break;
575
576 default:
577 rv = -EOPNOTSUPP;
578 break;
579 }
580 if (rv < 0)
581 {
582 errno = -rv;
583 rv = -1;
584 }
585 }
586 else
587 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500588 rv = libc_vioctl (fd, cmd, ap);
589 }
590
Dave Wallace048b1d62018-01-03 22:24:41 -0500591 va_end (ap);
592 return rv;
593}
594
Florin Coras294afe22019-01-07 17:49:17 -0800595always_inline void
596ldp_select_init_maps (fd_set * __restrict original,
597 clib_bitmap_t ** resultb, clib_bitmap_t ** libcb,
598 clib_bitmap_t ** vclb, int nfds, u32 minbits,
599 u32 n_bytes, uword * si_bits, uword * libc_bits)
600{
601 uword si_bits_set, libc_bits_set;
602 vls_handle_t vlsh;
603 int fd;
604
605 clib_bitmap_validate (*vclb, minbits);
606 clib_bitmap_validate (*libcb, minbits);
607 clib_bitmap_validate (*resultb, minbits);
608 clib_memcpy_fast (*resultb, original, n_bytes);
609 memset (original, 0, n_bytes);
610
611 /* *INDENT-OFF* */
612 clib_bitmap_foreach (fd, *resultb, ({
613 if (fd > nfds)
614 break;
615 vlsh = ldp_fd_to_vlsh (fd);
616 if (vlsh == VLS_INVALID_HANDLE)
617 clib_bitmap_set_no_check (*libcb, fd, 1);
618 else
619 clib_bitmap_set_no_check (*vclb, vlsh_to_session_index (vlsh), 1);
620 }));
621 /* *INDENT-ON* */
622
623 si_bits_set = clib_bitmap_last_set (*vclb) + 1;
624 *si_bits = (si_bits_set > *si_bits) ? si_bits_set : *si_bits;
625
626 libc_bits_set = clib_bitmap_last_set (*libcb) + 1;
627 *libc_bits = (libc_bits_set > *libc_bits) ? libc_bits_set : *libc_bits;
628}
629
630always_inline int
631ldp_select_vcl_map_to_libc (clib_bitmap_t * vclb, fd_set * __restrict libcb)
632{
633 vls_handle_t vlsh;
634 uword si;
635 int fd;
636
637 if (!libcb)
638 return 0;
639
640 /* *INDENT-OFF* */
641 clib_bitmap_foreach (si, vclb, ({
642 vlsh = vls_session_index_to_vlsh (si);
643 fd = ldp_vlsh_to_fd (vlsh);
644 if (PREDICT_FALSE (fd < 0))
645 {
646 errno = EBADFD;
647 return -1;
648 }
649 FD_SET (fd, libcb);
650 }));
651 /* *INDENT-ON* */
652
653 return 0;
654}
655
656always_inline void
657ldp_select_libc_map_merge (clib_bitmap_t * result, fd_set * __restrict libcb)
658{
659 uword fd;
660
Florin Coras78b5fa62019-02-21 20:04:15 -0800661 if (!libcb)
662 return;
663
Florin Coras294afe22019-01-07 17:49:17 -0800664 /* *INDENT-OFF* */
665 clib_bitmap_foreach (fd, result, ({
666 FD_SET ((int)fd, libcb);
667 }));
668 /* *INDENT-ON* */
669}
670
Dave Wallace048b1d62018-01-03 22:24:41 -0500671int
Dave Wallace2a865272018-02-07 21:00:42 -0500672ldp_pselect (int nfds, fd_set * __restrict readfds,
673 fd_set * __restrict writefds,
674 fd_set * __restrict exceptfds,
675 const struct timespec *__restrict timeout,
676 const __sigset_t * __restrict sigmask)
Dave Wallace048b1d62018-01-03 22:24:41 -0500677{
Florin Coras294afe22019-01-07 17:49:17 -0800678 u32 minbits = clib_max (nfds, BITS (uword)), n_bytes;
Florin Corasdfe4cf42018-11-28 22:13:45 -0800679 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras294afe22019-01-07 17:49:17 -0800680 struct timespec libc_tspec = { 0 };
681 f64 time_out, vcl_timeout = 0;
682 uword si_bits, libc_bits;
683 int rv, bits_set = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500684
685 if (nfds < 0)
686 {
687 errno = EINVAL;
688 return -1;
689 }
690
Florin Coras4dee8cd2019-01-29 21:28:16 -0800691 if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
692 clib_time_init (&ldpw->clib_time);
693
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500694 if (timeout)
695 {
696 time_out = (timeout->tv_sec == 0 && timeout->tv_nsec == 0) ?
Florin Coras7baeb712019-01-04 17:05:43 -0800697 (f64) 0 : (f64) timeout->tv_sec + (f64) timeout->tv_nsec / (f64) 1e9;
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500698
699 /* select as fine grained sleep */
700 if (!nfds)
701 {
Florin Corasdfe4cf42018-11-28 22:13:45 -0800702 time_out += clib_time_now (&ldpw->clib_time);
703 while (clib_time_now (&ldpw->clib_time) < time_out)
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500704 ;
705 return 0;
706 }
707 }
708 else if (!nfds)
709 {
710 errno = EINVAL;
711 return -1;
712 }
713 else
714 time_out = -1;
715
Florin Coras7baeb712019-01-04 17:05:43 -0800716 if (nfds <= ldp->vlsh_bit_val)
Dave Wallace048b1d62018-01-03 22:24:41 -0500717 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500718 rv = libc_pselect (nfds, readfds, writefds, exceptfds,
719 timeout, sigmask);
720 goto done;
721 }
722
Florin Coras294afe22019-01-07 17:49:17 -0800723 si_bits = libc_bits = 0;
724 n_bytes = nfds / 8 + ((nfds % 8) ? 1 : 0);
Florin Coras7baeb712019-01-04 17:05:43 -0800725
Dave Wallace048b1d62018-01-03 22:24:41 -0500726 if (readfds)
Florin Coras294afe22019-01-07 17:49:17 -0800727 ldp_select_init_maps (readfds, &ldpw->rd_bitmap, &ldpw->libc_rd_bitmap,
728 &ldpw->si_rd_bitmap, nfds, minbits, n_bytes,
729 &si_bits, &libc_bits);
Dave Wallace048b1d62018-01-03 22:24:41 -0500730 if (writefds)
Florin Coras294afe22019-01-07 17:49:17 -0800731 ldp_select_init_maps (writefds, &ldpw->wr_bitmap,
732 &ldpw->libc_wr_bitmap, &ldpw->si_wr_bitmap, nfds,
733 minbits, n_bytes, &si_bits, &libc_bits);
Dave Wallace048b1d62018-01-03 22:24:41 -0500734 if (exceptfds)
Florin Coras294afe22019-01-07 17:49:17 -0800735 ldp_select_init_maps (exceptfds, &ldpw->ex_bitmap,
736 &ldpw->libc_ex_bitmap, &ldpw->si_ex_bitmap, nfds,
737 minbits, n_bytes, &si_bits, &libc_bits);
Dave Wallace048b1d62018-01-03 22:24:41 -0500738
Florin Coras294afe22019-01-07 17:49:17 -0800739 if (PREDICT_FALSE (!si_bits && !libc_bits))
Dave Wallace048b1d62018-01-03 22:24:41 -0500740 {
741 errno = EINVAL;
742 rv = -1;
743 goto done;
744 }
745
Florin Coras78b5fa62019-02-21 20:04:15 -0800746 if (!si_bits)
747 libc_tspec = timeout ? *timeout : libc_tspec;
Florin Coras294afe22019-01-07 17:49:17 -0800748
Dave Wallace048b1d62018-01-03 22:24:41 -0500749 do
750 {
Florin Coras294afe22019-01-07 17:49:17 -0800751 if (si_bits)
Dave Wallace048b1d62018-01-03 22:24:41 -0500752 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500753 if (readfds)
Florin Coras294afe22019-01-07 17:49:17 -0800754 clib_memcpy_fast (ldpw->rd_bitmap, ldpw->si_rd_bitmap,
Florin Corasdfe4cf42018-11-28 22:13:45 -0800755 vec_len (ldpw->rd_bitmap) *
Dave Barach178cf492018-11-13 16:34:13 -0500756 sizeof (clib_bitmap_t));
Dave Wallace048b1d62018-01-03 22:24:41 -0500757 if (writefds)
Florin Coras294afe22019-01-07 17:49:17 -0800758 clib_memcpy_fast (ldpw->wr_bitmap, ldpw->si_wr_bitmap,
Florin Corasdfe4cf42018-11-28 22:13:45 -0800759 vec_len (ldpw->wr_bitmap) *
Dave Barach178cf492018-11-13 16:34:13 -0500760 sizeof (clib_bitmap_t));
Dave Wallace048b1d62018-01-03 22:24:41 -0500761 if (exceptfds)
Florin Coras294afe22019-01-07 17:49:17 -0800762 clib_memcpy_fast (ldpw->ex_bitmap, ldpw->si_ex_bitmap,
Florin Corasdfe4cf42018-11-28 22:13:45 -0800763 vec_len (ldpw->ex_bitmap) *
Dave Barach178cf492018-11-13 16:34:13 -0500764 sizeof (clib_bitmap_t));
Florin Coras294afe22019-01-07 17:49:17 -0800765
Florin Coras0ef8ef22019-01-18 08:37:13 -0800766 rv = vls_select (si_bits, readfds ? ldpw->rd_bitmap : NULL,
767 writefds ? ldpw->wr_bitmap : NULL,
768 exceptfds ? ldpw->ex_bitmap : NULL, vcl_timeout);
Florin Coras294afe22019-01-07 17:49:17 -0800769 if (rv < 0)
770 {
771 errno = -rv;
772 rv = -1;
773 }
774 else if (rv > 0)
775 {
776 if (ldp_select_vcl_map_to_libc (ldpw->rd_bitmap, readfds))
777 {
778 rv = -1;
779 goto done;
780 }
781
782 if (ldp_select_vcl_map_to_libc (ldpw->wr_bitmap, writefds))
783 {
784 rv = -1;
785 goto done;
786 }
787
788 if (ldp_select_vcl_map_to_libc (ldpw->ex_bitmap, exceptfds))
789 {
790 rv = -1;
791 goto done;
792 }
793 bits_set = rv;
794 }
795 }
796 if (libc_bits)
797 {
798 if (readfds)
799 clib_memcpy_fast (ldpw->rd_bitmap, ldpw->libc_rd_bitmap,
800 vec_len (ldpw->libc_rd_bitmap) *
801 sizeof (clib_bitmap_t));
802 if (writefds)
803 clib_memcpy_fast (ldpw->wr_bitmap, ldpw->libc_wr_bitmap,
804 vec_len (ldpw->libc_wr_bitmap) *
805 sizeof (clib_bitmap_t));
806 if (exceptfds)
807 clib_memcpy_fast (ldpw->ex_bitmap, ldpw->libc_ex_bitmap,
808 vec_len (ldpw->libc_ex_bitmap) *
809 sizeof (clib_bitmap_t));
810
Dave Wallace048b1d62018-01-03 22:24:41 -0500811 rv = libc_pselect (libc_bits,
Florin Coras294afe22019-01-07 17:49:17 -0800812 readfds ? (fd_set *) ldpw->rd_bitmap : NULL,
813 writefds ? (fd_set *) ldpw->wr_bitmap : NULL,
814 exceptfds ? (fd_set *) ldpw->ex_bitmap : NULL,
815 &libc_tspec, sigmask);
816 if (rv > 0)
817 {
818 ldp_select_libc_map_merge (ldpw->rd_bitmap, readfds);
819 ldp_select_libc_map_merge (ldpw->wr_bitmap, writefds);
820 ldp_select_libc_map_merge (ldpw->ex_bitmap, exceptfds);
821 bits_set += rv;
822 }
823 }
824
825 if (bits_set)
826 {
827 rv = bits_set;
828 goto done;
Dave Wallace048b1d62018-01-03 22:24:41 -0500829 }
830 }
Florin Corasdfe4cf42018-11-28 22:13:45 -0800831 while ((time_out == -1) || (clib_time_now (&ldpw->clib_time) < time_out));
Dave Wallace048b1d62018-01-03 22:24:41 -0500832 rv = 0;
833
834done:
835 /* TBD: set timeout to amount of time left */
Florin Corasdfe4cf42018-11-28 22:13:45 -0800836 clib_bitmap_zero (ldpw->rd_bitmap);
Florin Coras294afe22019-01-07 17:49:17 -0800837 clib_bitmap_zero (ldpw->si_rd_bitmap);
Florin Corasdfe4cf42018-11-28 22:13:45 -0800838 clib_bitmap_zero (ldpw->libc_rd_bitmap);
839 clib_bitmap_zero (ldpw->wr_bitmap);
Florin Coras294afe22019-01-07 17:49:17 -0800840 clib_bitmap_zero (ldpw->si_wr_bitmap);
Florin Corasdfe4cf42018-11-28 22:13:45 -0800841 clib_bitmap_zero (ldpw->libc_wr_bitmap);
842 clib_bitmap_zero (ldpw->ex_bitmap);
Florin Coras294afe22019-01-07 17:49:17 -0800843 clib_bitmap_zero (ldpw->si_ex_bitmap);
Florin Corasdfe4cf42018-11-28 22:13:45 -0800844 clib_bitmap_zero (ldpw->libc_ex_bitmap);
Dave Wallace048b1d62018-01-03 22:24:41 -0500845
Dave Wallace048b1d62018-01-03 22:24:41 -0500846 return rv;
847}
848
849int
850select (int nfds, fd_set * __restrict readfds,
851 fd_set * __restrict writefds,
852 fd_set * __restrict exceptfds, struct timeval *__restrict timeout)
853{
854 struct timespec tspec;
855
856 if (timeout)
857 {
858 tspec.tv_sec = timeout->tv_sec;
859 tspec.tv_nsec = timeout->tv_usec * 1000;
860 }
Dave Wallace2a865272018-02-07 21:00:42 -0500861 return ldp_pselect (nfds, readfds, writefds, exceptfds,
862 timeout ? &tspec : NULL, NULL);
Dave Wallace048b1d62018-01-03 22:24:41 -0500863}
864
865#ifdef __USE_XOPEN2K
866int
867pselect (int nfds, fd_set * __restrict readfds,
868 fd_set * __restrict writefds,
869 fd_set * __restrict exceptfds,
870 const struct timespec *__restrict timeout,
871 const __sigset_t * __restrict sigmask)
872{
Dave Wallace2a865272018-02-07 21:00:42 -0500873 return ldp_pselect (nfds, readfds, writefds, exceptfds, timeout, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -0500874}
875#endif
876
Yu Ping7b74b072019-05-08 00:40:24 +0800877/* If transparent TLS mode is turned on, then ldp will load key and cert.
878 */
879static int
880load_tls_cert (vls_handle_t vlsh)
881{
882 char *env_var_str = getenv (LDP_ENV_TLS_CERT);
883 char inbuf[4096];
884 char *tls_cert;
885 int cert_size;
886 FILE *fp;
887
888 if (env_var_str)
889 {
890 fp = fopen (env_var_str, "r");
891 if (fp == NULL)
892 {
893 LDBG (0, "ERROR: failed to open cert file %s \n", env_var_str);
894 return -1;
895 }
896 cert_size = fread (inbuf, sizeof (char), sizeof (inbuf), fp);
897 tls_cert = inbuf;
898 vppcom_session_tls_add_cert (vlsh_to_session_index (vlsh), tls_cert,
899 cert_size);
900 fclose (fp);
901 }
902 else
903 {
904 LDBG (0, "ERROR: failed to read LDP environment %s\n",
905 LDP_ENV_TLS_CERT);
906 return -1;
907 }
908 return 0;
909}
910
911static int
912load_tls_key (vls_handle_t vlsh)
913{
914 char *env_var_str = getenv (LDP_ENV_TLS_KEY);
915 char inbuf[4096];
916 char *tls_key;
917 int key_size;
918 FILE *fp;
919
920 if (env_var_str)
921 {
922 fp = fopen (env_var_str, "r");
923 if (fp == NULL)
924 {
925 LDBG (0, "ERROR: failed to open key file %s \n", env_var_str);
926 return -1;
927 }
928 key_size = fread (inbuf, sizeof (char), sizeof (inbuf), fp);
929 tls_key = inbuf;
930 vppcom_session_tls_add_key (vlsh_to_session_index (vlsh), tls_key,
931 key_size);
932 fclose (fp);
933 }
934 else
935 {
936 LDBG (0, "ERROR: failed to read LDP environment %s\n", LDP_ENV_TLS_KEY);
937 return -1;
938 }
939 return 0;
940}
941
Dave Wallace048b1d62018-01-03 22:24:41 -0500942int
943socket (int domain, int type, int protocol)
944{
Florin Coras7baeb712019-01-04 17:05:43 -0800945 int rv, sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
Dave Wallace048b1d62018-01-03 22:24:41 -0500946 u8 is_nonblocking = type & SOCK_NONBLOCK ? 1 : 0;
Florin Coras7baeb712019-01-04 17:05:43 -0800947 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500948
Dave Wallace2a865272018-02-07 21:00:42 -0500949 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500950 return -1;
951
952 if (((domain == AF_INET) || (domain == AF_INET6)) &&
953 ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM)))
954 {
Yu Ping7b74b072019-05-08 00:40:24 +0800955 u8 proto;
956 if (ldp->transparent_tls)
957 {
958 proto = VPPCOM_PROTO_TLS;
959 }
960 else
961 proto = ((sock_type == SOCK_DGRAM) ?
962 VPPCOM_PROTO_UDP : VPPCOM_PROTO_TCP);
Dave Wallace048b1d62018-01-03 22:24:41 -0500963
Florin Coras7baeb712019-01-04 17:05:43 -0800964 LDBG (0, "calling vls_create: proto %u (%s), is_nonblocking %u",
965 proto, vppcom_proto_str (proto), is_nonblocking);
Dave Wallace048b1d62018-01-03 22:24:41 -0500966
Florin Coras7baeb712019-01-04 17:05:43 -0800967 vlsh = vls_create (proto, is_nonblocking);
968 if (vlsh < 0)
Dave Wallace048b1d62018-01-03 22:24:41 -0500969 {
Florin Coras7baeb712019-01-04 17:05:43 -0800970 errno = -vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500971 rv = -1;
972 }
973 else
974 {
Yu Ping7b74b072019-05-08 00:40:24 +0800975 if (ldp->transparent_tls)
976 {
977 if (load_tls_cert (vlsh) < 0 || load_tls_key (vlsh) < 0)
978 {
979 return -1;
980 }
981 }
Florin Coras7baeb712019-01-04 17:05:43 -0800982 rv = ldp_vlsh_to_fd (vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -0500983 }
984 }
985 else
986 {
Florin Coras7baeb712019-01-04 17:05:43 -0800987 LDBG (0, "calling libc_socket");
Dave Wallace048b1d62018-01-03 22:24:41 -0500988 rv = libc_socket (domain, type, protocol);
989 }
990
Dave Wallace048b1d62018-01-03 22:24:41 -0500991 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700992}
993
994/*
995 * Create two new sockets, of type TYPE in domain DOMAIN and using
996 * protocol PROTOCOL, which are connected to each other, and put file
997 * descriptors for them in FDS[0] and FDS[1]. If PROTOCOL is zero,
998 * one will be chosen automatically.
999 * Returns 0 on success, -1 for errors.
1000 * */
1001int
Dave Wallace048b1d62018-01-03 22:24:41 -05001002socketpair (int domain, int type, int protocol, int fds[2])
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001003{
Florin Coras7baeb712019-01-04 17:05:43 -08001004 int rv, sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
Dave Wallace048b1d62018-01-03 22:24:41 -05001005
Dave Wallace2a865272018-02-07 21:00:42 -05001006 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001007 return -1;
1008
1009 if (((domain == AF_INET) || (domain == AF_INET6)) &&
1010 ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM)))
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001011 {
Florin Coras7baeb712019-01-04 17:05:43 -08001012 LDBG (0, "LDP-TBD");
Dave Wallace048b1d62018-01-03 22:24:41 -05001013 errno = ENOSYS;
1014 rv = -1;
1015 }
1016 else
1017 {
Florin Coras7baeb712019-01-04 17:05:43 -08001018 LDBG (1, "calling libc_socketpair");
Florin Coras173bae32018-11-16 18:56:28 -08001019 rv = libc_socketpair (domain, type, protocol, fds);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001020 }
1021
Dave Wallace048b1d62018-01-03 22:24:41 -05001022 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001023}
1024
1025int
Dave Wallace048b1d62018-01-03 22:24:41 -05001026bind (int fd, __CONST_SOCKADDR_ARG addr, socklen_t len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001027{
Florin Coras7baeb712019-01-04 17:05:43 -08001028 vls_handle_t vlsh;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001029 int rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001030
Dave Wallace2a865272018-02-07 21:00:42 -05001031 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001032 return -1;
1033
Florin Coras7baeb712019-01-04 17:05:43 -08001034 vlsh = ldp_fd_to_vlsh (fd);
1035 if (vlsh != VLS_INVALID_HANDLE)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001036 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001037 vppcom_endpt_t ep;
1038
Dave Wallace048b1d62018-01-03 22:24:41 -05001039 switch (addr->sa_family)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001040 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001041 case AF_INET:
1042 if (len != sizeof (struct sockaddr_in))
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001043 {
Florin Coras7baeb712019-01-04 17:05:43 -08001044 LDBG (0, "ERROR: fd %d: vlsh %u: Invalid AF_INET addr len %u!",
1045 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001046 errno = EINVAL;
1047 rv = -1;
1048 goto done;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001049 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001050 ep.is_ip4 = VPPCOM_IS_IP4;
1051 ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr;
1052 ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port;
1053 break;
1054
1055 case AF_INET6:
1056 if (len != sizeof (struct sockaddr_in6))
1057 {
Florin Coras7baeb712019-01-04 17:05:43 -08001058 LDBG (0, "ERROR: fd %d: vlsh %u: Invalid AF_INET6 addr len %u!",
1059 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001060 errno = EINVAL;
1061 rv = -1;
1062 goto done;
1063 }
1064 ep.is_ip4 = VPPCOM_IS_IP6;
1065 ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
1066 ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001067 break;
1068
1069 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001070 LDBG (0, "ERROR: fd %d: vlsh %u: Unsupported address family %u!",
1071 fd, vlsh, addr->sa_family);
Dave Wallace048b1d62018-01-03 22:24:41 -05001072 errno = EAFNOSUPPORT;
1073 rv = -1;
1074 goto done;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001075 }
Florin Coras7baeb712019-01-04 17:05:43 -08001076 LDBG (0, "fd %d: calling vls_bind: vlsh %u, addr %p, len %u", fd, vlsh,
1077 addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001078
Florin Coras7baeb712019-01-04 17:05:43 -08001079 rv = vls_bind (vlsh, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001080 if (rv != VPPCOM_OK)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001081 {
1082 errno = -rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001083 rv = -1;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001084 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001085 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001086 else
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001087 {
Florin Coras7baeb712019-01-04 17:05:43 -08001088 LDBG (0, "fd %d: calling libc_bind: addr %p, len %u", fd, addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001089 rv = libc_bind (fd, addr, len);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001090 }
1091
Dave Wallace048b1d62018-01-03 22:24:41 -05001092done:
Florin Coras7baeb712019-01-04 17:05:43 -08001093 LDBG (1, "fd %d: returning %d", fd, rv);
Florin Coras05ecfcc2018-12-12 18:19:39 -08001094
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001095 return rv;
1096}
1097
1098static inline int
Dave Wallace2a865272018-02-07 21:00:42 -05001099ldp_copy_ep_to_sockaddr (__SOCKADDR_ARG addr, socklen_t * __restrict len,
1100 vppcom_endpt_t * ep)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001101{
Dave Wallace048b1d62018-01-03 22:24:41 -05001102 int rv = 0;
1103 int sa_len, copy_len;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001104
Dave Wallace2a865272018-02-07 21:00:42 -05001105 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001106 return -1;
1107
1108 if (addr && len && ep)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001109 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001110 addr->sa_family = (ep->is_ip4 == VPPCOM_IS_IP4) ? AF_INET : AF_INET6;
1111 switch (addr->sa_family)
1112 {
1113 case AF_INET:
1114 ((struct sockaddr_in *) addr)->sin_port = ep->port;
1115 if (*len > sizeof (struct sockaddr_in))
1116 *len = sizeof (struct sockaddr_in);
1117 sa_len = sizeof (struct sockaddr_in) - sizeof (struct in_addr);
1118 copy_len = *len - sa_len;
1119 if (copy_len > 0)
1120 memcpy (&((struct sockaddr_in *) addr)->sin_addr, ep->ip,
1121 copy_len);
1122 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001123
Dave Wallace048b1d62018-01-03 22:24:41 -05001124 case AF_INET6:
1125 ((struct sockaddr_in6 *) addr)->sin6_port = ep->port;
1126 if (*len > sizeof (struct sockaddr_in6))
1127 *len = sizeof (struct sockaddr_in6);
1128 sa_len = sizeof (struct sockaddr_in6) - sizeof (struct in6_addr);
1129 copy_len = *len - sa_len;
1130 if (copy_len > 0)
1131 memcpy (((struct sockaddr_in6 *) addr)->sin6_addr.
1132 __in6_u.__u6_addr8, ep->ip, copy_len);
1133 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001134
Dave Wallace048b1d62018-01-03 22:24:41 -05001135 default:
1136 /* Not possible */
1137 rv = -EAFNOSUPPORT;
1138 break;
1139 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001140 }
Dave Wallacee695cb42017-11-02 22:04:42 -04001141 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001142}
1143
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001144int
Dave Wallace048b1d62018-01-03 22:24:41 -05001145getsockname (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001146{
Florin Coras7baeb712019-01-04 17:05:43 -08001147 vls_handle_t vlsh;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001148 int rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001149
Dave Wallace2a865272018-02-07 21:00:42 -05001150 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001151 return -1;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001152
Florin Coras7baeb712019-01-04 17:05:43 -08001153 vlsh = ldp_fd_to_vlsh (fd);
1154 if (vlsh != VLS_INVALID_HANDLE)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001155 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001156 vppcom_endpt_t ep;
1157 u8 addr_buf[sizeof (struct in6_addr)];
1158 u32 size = sizeof (ep);
1159
1160 ep.ip = addr_buf;
Dave Wallace048b1d62018-01-03 22:24:41 -05001161
Florin Coras7baeb712019-01-04 17:05:43 -08001162 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_LCL_ADDR, &ep, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -05001163 if (rv != VPPCOM_OK)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001164 {
1165 errno = -rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001166 rv = -1;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001167 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001168 else
1169 {
Dave Wallace2a865272018-02-07 21:00:42 -05001170 rv = ldp_copy_ep_to_sockaddr (addr, len, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001171 if (rv != VPPCOM_OK)
1172 {
1173 errno = -rv;
1174 rv = -1;
1175 }
1176 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001177 }
1178 else
1179 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001180 rv = libc_getsockname (fd, addr, len);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001181 }
1182
Dave Wallace048b1d62018-01-03 22:24:41 -05001183 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001184}
1185
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001186int
Dave Wallace048b1d62018-01-03 22:24:41 -05001187connect (int fd, __CONST_SOCKADDR_ARG addr, socklen_t len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001188{
Florin Coras7baeb712019-01-04 17:05:43 -08001189 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001190 int rv;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001191
Dave Wallace2a865272018-02-07 21:00:42 -05001192 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001193 return -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001194
Dave Wallace048b1d62018-01-03 22:24:41 -05001195 if (!addr)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001196 {
Florin Coras7baeb712019-01-04 17:05:43 -08001197 LDBG (0, "ERROR: fd %d: NULL addr, len %u", fd, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001198 errno = EINVAL;
1199 rv = -1;
1200 goto done;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001201 }
1202
Florin Coras7baeb712019-01-04 17:05:43 -08001203 vlsh = ldp_fd_to_vlsh (fd);
1204 if (vlsh != VLS_INVALID_HANDLE)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001205 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001206 vppcom_endpt_t ep;
1207
Dave Wallace048b1d62018-01-03 22:24:41 -05001208 switch (addr->sa_family)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001209 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001210 case AF_INET:
1211 if (len != sizeof (struct sockaddr_in))
1212 {
Florin Coras7baeb712019-01-04 17:05:43 -08001213 LDBG (0, "fd %d: ERROR vlsh %u: Invalid AF_INET addr len %u!",
1214 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001215 errno = EINVAL;
1216 rv = -1;
1217 goto done;
1218 }
1219 ep.is_ip4 = VPPCOM_IS_IP4;
1220 ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr;
1221 ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port;
1222 break;
1223
1224 case AF_INET6:
1225 if (len != sizeof (struct sockaddr_in6))
1226 {
Florin Coras7baeb712019-01-04 17:05:43 -08001227 LDBG (0, "fd %d: ERROR vlsh %u: Invalid AF_INET6 addr len %u!",
1228 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001229 errno = EINVAL;
1230 rv = -1;
1231 goto done;
1232 }
1233 ep.is_ip4 = VPPCOM_IS_IP6;
1234 ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
1235 ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port;
1236 break;
1237
1238 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001239 LDBG (0, "fd %d: ERROR vlsh %u: Unsupported address family %u!",
1240 fd, vlsh, addr->sa_family);
Dave Wallace048b1d62018-01-03 22:24:41 -05001241 errno = EAFNOSUPPORT;
1242 rv = -1;
1243 goto done;
1244 }
Florin Coras7baeb712019-01-04 17:05:43 -08001245 LDBG (0, "fd %d: calling vls_connect(): vlsh %u addr %p len %u", fd,
1246 vlsh, addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001247
Florin Coras7baeb712019-01-04 17:05:43 -08001248 rv = vls_connect (vlsh, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001249 if (rv != VPPCOM_OK)
1250 {
1251 errno = -rv;
1252 rv = -1;
1253 }
1254 }
1255 else
1256 {
Florin Coras7baeb712019-01-04 17:05:43 -08001257 LDBG (0, "fd %d: calling libc_connect(): addr %p, len %u",
1258 fd, addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001259
1260 rv = libc_connect (fd, addr, len);
1261 }
1262
1263done:
Florin Coras7baeb712019-01-04 17:05:43 -08001264 LDBG (1, "fd %d: returning %d (0x%x)", fd, rv, rv);
Dave Wallace048b1d62018-01-03 22:24:41 -05001265 return rv;
1266}
1267
1268int
1269getpeername (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict len)
1270{
Florin Coras7baeb712019-01-04 17:05:43 -08001271 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001272 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001273
Dave Wallace2a865272018-02-07 21:00:42 -05001274 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001275 return -1;
1276
Florin Coras7baeb712019-01-04 17:05:43 -08001277 vlsh = ldp_fd_to_vlsh (fd);
1278 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001279 {
1280 vppcom_endpt_t ep;
1281 u8 addr_buf[sizeof (struct in6_addr)];
1282 u32 size = sizeof (ep);
1283
1284 ep.ip = addr_buf;
Florin Coras7baeb712019-01-04 17:05:43 -08001285 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_PEER_ADDR, &ep, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -05001286 if (rv != VPPCOM_OK)
1287 {
1288 errno = -rv;
1289 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001290 }
1291 else
1292 {
Dave Wallace2a865272018-02-07 21:00:42 -05001293 rv = ldp_copy_ep_to_sockaddr (addr, len, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001294 if (rv != VPPCOM_OK)
1295 {
1296 errno = -rv;
1297 rv = -1;
1298 }
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001299 }
1300 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001301 else
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001302 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001303 rv = libc_getpeername (fd, addr, len);
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001304 }
1305
Dave Wallace048b1d62018-01-03 22:24:41 -05001306 return rv;
1307}
1308
1309ssize_t
1310send (int fd, const void *buf, size_t n, int flags)
1311{
Florin Coras7baeb712019-01-04 17:05:43 -08001312 vls_handle_t vlsh = ldp_fd_to_vlsh (fd);
Dave Wallace048b1d62018-01-03 22:24:41 -05001313 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001314
Dave Wallace2a865272018-02-07 21:00:42 -05001315 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001316 return -1;
1317
Florin Coras7baeb712019-01-04 17:05:43 -08001318 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001319 {
Florin Coras7baeb712019-01-04 17:05:43 -08001320 size = vls_sendto (vlsh, (void *) buf, n, flags, NULL);
qchangaa8f63c2018-05-30 11:44:18 -07001321 if (size < VPPCOM_OK)
Dave Wallace048b1d62018-01-03 22:24:41 -05001322 {
1323 errno = -size;
1324 size = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001325 }
1326 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001327 else
1328 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001329 size = libc_send (fd, buf, n, flags);
1330 }
1331
Dave Wallace048b1d62018-01-03 22:24:41 -05001332 return size;
1333}
1334
1335ssize_t
1336sendfile (int out_fd, int in_fd, off_t * offset, size_t len)
1337{
Florin Corasdfe4cf42018-11-28 22:13:45 -08001338 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras7baeb712019-01-04 17:05:43 -08001339 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001340 ssize_t size = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -05001341
Dave Wallace2a865272018-02-07 21:00:42 -05001342 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001343 return -1;
1344
Florin Coras7baeb712019-01-04 17:05:43 -08001345 vlsh = ldp_fd_to_vlsh (out_fd);
1346 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001347 {
1348 int rv;
1349 ssize_t results = 0;
1350 size_t n_bytes_left = len;
1351 size_t bytes_to_read;
1352 int nbytes;
Dave Wallace048b1d62018-01-03 22:24:41 -05001353 u8 eagain = 0;
1354 u32 flags, flags_len = sizeof (flags);
1355
Florin Coras7baeb712019-01-04 17:05:43 -08001356 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_FLAGS, &flags, &flags_len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001357 if (PREDICT_FALSE (rv != VPPCOM_OK))
1358 {
Florin Coras7baeb712019-01-04 17:05:43 -08001359 LDBG (0, "ERROR: out fd %d: vls_attr: vlsh %u, returned %d (%s)!",
1360 out_fd, vlsh, rv, vppcom_retval_str (rv));
Dave Wallace048b1d62018-01-03 22:24:41 -05001361
Florin Corasdfe4cf42018-11-28 22:13:45 -08001362 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001363 errno = -rv;
1364 size = -1;
1365 goto done;
1366 }
1367
1368 if (offset)
1369 {
1370 off_t off = lseek (in_fd, *offset, SEEK_SET);
1371 if (PREDICT_FALSE (off == -1))
1372 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001373 size = -1;
1374 goto done;
1375 }
1376
1377 ASSERT (off == *offset);
1378 }
1379
1380 do
1381 {
Florin Coras7baeb712019-01-04 17:05:43 -08001382 size = vls_attr (vlsh, VPPCOM_ATTR_GET_NWRITE, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05001383 if (size < 0)
1384 {
Florin Coras7baeb712019-01-04 17:05:43 -08001385 LDBG (0, "ERROR: fd %d: vls_attr: vlsh %u returned %d (%s)!",
1386 out_fd, vlsh, size, vppcom_retval_str (size));
Florin Corasdfe4cf42018-11-28 22:13:45 -08001387 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001388 errno = -size;
1389 size = -1;
1390 goto done;
1391 }
1392
1393 bytes_to_read = size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001394 if (bytes_to_read == 0)
1395 {
1396 if (flags & O_NONBLOCK)
1397 {
1398 if (!results)
Florin Coras7baeb712019-01-04 17:05:43 -08001399 eagain = 1;
Dave Wallace048b1d62018-01-03 22:24:41 -05001400 goto update_offset;
1401 }
1402 else
1403 continue;
1404 }
1405 bytes_to_read = clib_min (n_bytes_left, bytes_to_read);
Florin Corasdfe4cf42018-11-28 22:13:45 -08001406 vec_validate (ldpw->io_buffer, bytes_to_read);
1407 nbytes = libc_read (in_fd, ldpw->io_buffer, bytes_to_read);
Dave Wallace048b1d62018-01-03 22:24:41 -05001408 if (nbytes < 0)
1409 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001410 if (results == 0)
1411 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08001412 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001413 size = -1;
1414 goto done;
1415 }
1416 goto update_offset;
1417 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001418
Florin Coras7baeb712019-01-04 17:05:43 -08001419 size = vls_write (vlsh, ldpw->io_buffer, nbytes);
Dave Wallace048b1d62018-01-03 22:24:41 -05001420 if (size < 0)
1421 {
1422 if (size == VPPCOM_EAGAIN)
1423 {
1424 if (flags & O_NONBLOCK)
1425 {
1426 if (!results)
Florin Coras7baeb712019-01-04 17:05:43 -08001427 eagain = 1;
Dave Wallace048b1d62018-01-03 22:24:41 -05001428 goto update_offset;
1429 }
1430 else
1431 continue;
1432 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001433 if (results == 0)
1434 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08001435 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001436 errno = -size;
1437 size = -1;
1438 goto done;
1439 }
1440 goto update_offset;
1441 }
1442
1443 results += nbytes;
1444 ASSERT (n_bytes_left >= nbytes);
1445 n_bytes_left = n_bytes_left - nbytes;
1446 }
1447 while (n_bytes_left > 0);
1448
1449 update_offset:
Florin Corasdfe4cf42018-11-28 22:13:45 -08001450 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001451 if (offset)
1452 {
1453 off_t off = lseek (in_fd, *offset, SEEK_SET);
1454 if (PREDICT_FALSE (off == -1))
1455 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001456 size = -1;
1457 goto done;
1458 }
1459
1460 ASSERT (off == *offset);
1461 *offset += results + 1;
1462 }
1463 if (eagain)
1464 {
1465 errno = EAGAIN;
1466 size = -1;
1467 }
1468 else
1469 size = results;
1470 }
1471 else
1472 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001473 size = libc_sendfile (out_fd, in_fd, offset, len);
1474 }
1475
1476done:
Dave Wallace048b1d62018-01-03 22:24:41 -05001477 return size;
1478}
1479
1480ssize_t
1481sendfile64 (int out_fd, int in_fd, off_t * offset, size_t len)
1482{
1483 return sendfile (out_fd, in_fd, offset, len);
1484}
1485
1486ssize_t
1487recv (int fd, void *buf, size_t n, int flags)
1488{
Florin Coras7baeb712019-01-04 17:05:43 -08001489 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001490 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001491
Dave Wallace2a865272018-02-07 21:00:42 -05001492 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001493 return -1;
1494
Florin Coras7baeb712019-01-04 17:05:43 -08001495 vlsh = ldp_fd_to_vlsh (fd);
1496 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001497 {
Florin Coras7baeb712019-01-04 17:05:43 -08001498 size = vls_recvfrom (vlsh, buf, n, flags, NULL);
Dave Wallace048b1d62018-01-03 22:24:41 -05001499 if (size < 0)
Florin Corasa7a1a222018-12-30 17:11:31 -08001500 errno = -size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001501 }
1502 else
1503 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001504 size = libc_recv (fd, buf, n, flags);
1505 }
1506
Dave Wallace048b1d62018-01-03 22:24:41 -05001507 return size;
1508}
1509
1510ssize_t
1511sendto (int fd, const void *buf, size_t n, int flags,
1512 __CONST_SOCKADDR_ARG addr, socklen_t addr_len)
1513{
Florin Coras7baeb712019-01-04 17:05:43 -08001514 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001515 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001516
Dave Wallace2a865272018-02-07 21:00:42 -05001517 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001518 return -1;
1519
Florin Coras7baeb712019-01-04 17:05:43 -08001520 vlsh = ldp_fd_to_vlsh (fd);
1521 if (vlsh != INVALID_SESSION_ID)
Dave Wallace048b1d62018-01-03 22:24:41 -05001522 {
1523 vppcom_endpt_t *ep = 0;
1524 vppcom_endpt_t _ep;
1525
1526 if (addr)
1527 {
1528 ep = &_ep;
Dave Wallace048b1d62018-01-03 22:24:41 -05001529 switch (addr->sa_family)
1530 {
1531 case AF_INET:
1532 ep->is_ip4 = VPPCOM_IS_IP4;
1533 ep->ip =
1534 (uint8_t *) & ((const struct sockaddr_in *) addr)->sin_addr;
1535 ep->port =
1536 (uint16_t) ((const struct sockaddr_in *) addr)->sin_port;
1537 break;
1538
1539 case AF_INET6:
1540 ep->is_ip4 = VPPCOM_IS_IP6;
1541 ep->ip =
1542 (uint8_t *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
1543 ep->port =
1544 (uint16_t) ((const struct sockaddr_in6 *) addr)->sin6_port;
1545 break;
1546
1547 default:
1548 errno = EAFNOSUPPORT;
1549 size = -1;
1550 goto done;
1551 }
1552 }
1553
Florin Coras7baeb712019-01-04 17:05:43 -08001554 size = vls_sendto (vlsh, (void *) buf, n, flags, ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001555 if (size < 0)
1556 {
1557 errno = -size;
1558 size = -1;
1559 }
1560 }
1561 else
1562 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001563 size = libc_sendto (fd, buf, n, flags, addr, addr_len);
1564 }
1565
1566done:
Dave Wallace048b1d62018-01-03 22:24:41 -05001567 return size;
1568}
1569
1570ssize_t
1571recvfrom (int fd, void *__restrict buf, size_t n, int flags,
1572 __SOCKADDR_ARG addr, socklen_t * __restrict addr_len)
1573{
Florin Coras7baeb712019-01-04 17:05:43 -08001574 vls_handle_t sid;
Haggai Eran46ae2ef2019-02-19 15:04:42 +02001575 ssize_t size, rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001576
Dave Wallace2a865272018-02-07 21:00:42 -05001577 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001578 return -1;
1579
Florin Coras7baeb712019-01-04 17:05:43 -08001580 sid = ldp_fd_to_vlsh (fd);
1581 if (sid != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001582 {
1583 vppcom_endpt_t ep;
1584 u8 src_addr[sizeof (struct sockaddr_in6)];
1585
Dave Wallace048b1d62018-01-03 22:24:41 -05001586 if (addr)
1587 {
1588 ep.ip = src_addr;
Florin Coras7baeb712019-01-04 17:05:43 -08001589 size = vls_recvfrom (sid, buf, n, flags, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001590
1591 if (size > 0)
Haggai Eran46ae2ef2019-02-19 15:04:42 +02001592 {
1593 rv = ldp_copy_ep_to_sockaddr (addr, addr_len, &ep);
1594 if (rv < 0)
1595 size = rv;
1596 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001597 }
1598 else
Florin Coras7baeb712019-01-04 17:05:43 -08001599 size = vls_recvfrom (sid, buf, n, flags, NULL);
Dave Wallace048b1d62018-01-03 22:24:41 -05001600
1601 if (size < 0)
1602 {
1603 errno = -size;
1604 size = -1;
1605 }
1606 }
1607 else
1608 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001609 size = libc_recvfrom (fd, buf, n, flags, addr, addr_len);
1610 }
1611
Dave Wallace048b1d62018-01-03 22:24:41 -05001612 return size;
1613}
1614
1615ssize_t
1616sendmsg (int fd, const struct msghdr * message, int flags)
1617{
Florin Coras7baeb712019-01-04 17:05:43 -08001618 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001619 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001620
Dave Wallace2a865272018-02-07 21:00:42 -05001621 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001622 return -1;
1623
Florin Coras7baeb712019-01-04 17:05:43 -08001624 vlsh = ldp_fd_to_vlsh (fd);
1625 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001626 {
Florin Coras7baeb712019-01-04 17:05:43 -08001627 LDBG (0, "LDP-TBD");
Dave Wallace048b1d62018-01-03 22:24:41 -05001628 errno = ENOSYS;
1629 size = -1;
1630 }
1631 else
1632 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001633 size = libc_sendmsg (fd, message, flags);
1634 }
1635
Dave Wallace048b1d62018-01-03 22:24:41 -05001636 return size;
1637}
1638
1639#ifdef USE_GNU
1640int
1641sendmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags)
1642{
1643 ssize_t size;
1644 const char *func_str;
Florin Coras7baeb712019-01-04 17:05:43 -08001645 u32 sh = ldp_fd_to_vlsh (fd);
Dave Wallace048b1d62018-01-03 22:24:41 -05001646
Dave Wallace2a865272018-02-07 21:00:42 -05001647 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001648 return -1;
1649
Florin Coras7baeb712019-01-04 17:05:43 -08001650 if (sh != INVALID_SESSION_ID)
Dave Wallace048b1d62018-01-03 22:24:41 -05001651 {
1652 clib_warning ("LDP<%d>: LDP-TBD", getpid ());
1653 errno = ENOSYS;
1654 size = -1;
1655 }
1656 else
1657 {
1658 func_str = "libc_sendmmsg";
1659
Dave Wallace2a865272018-02-07 21:00:42 -05001660 if (LDP_DEBUG > 2)
Dave Wallace048b1d62018-01-03 22:24:41 -05001661 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1662 "vmessages %p, vlen %u, flags 0x%x",
1663 getpid (), fd, fd, func_str, vmessages, vlen, flags);
1664
1665 size = libc_sendmmsg (fd, vmessages, vlen, flags);
1666 }
1667
Dave Wallace2a865272018-02-07 21:00:42 -05001668 if (LDP_DEBUG > 2)
Dave Wallace048b1d62018-01-03 22:24:41 -05001669 {
1670 if (size < 0)
1671 {
1672 int errno_val = errno;
1673 perror (func_str);
1674 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1675 "rv %d, errno = %d", getpid (), fd, fd,
1676 func_str, size, errno_val);
1677 errno = errno_val;
1678 }
1679 else
1680 clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1681 getpid (), fd, fd, size, size);
1682 }
1683 return size;
1684}
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001685#endif
1686
Dave Wallace048b1d62018-01-03 22:24:41 -05001687ssize_t
1688recvmsg (int fd, struct msghdr * message, int flags)
1689{
Florin Coras7baeb712019-01-04 17:05:43 -08001690 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001691 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001692
Dave Wallace2a865272018-02-07 21:00:42 -05001693 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001694 return -1;
1695
Florin Coras7baeb712019-01-04 17:05:43 -08001696 vlsh = ldp_fd_to_vlsh (fd);
1697 if (vlsh != VLS_INVALID_HANDLE)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001698 {
Florin Coras7baeb712019-01-04 17:05:43 -08001699 LDBG (0, "LDP-TBD");
Dave Wallace048b1d62018-01-03 22:24:41 -05001700 errno = ENOSYS;
1701 size = -1;
1702 }
1703 else
1704 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001705 size = libc_recvmsg (fd, message, flags);
1706 }
1707
Dave Wallace048b1d62018-01-03 22:24:41 -05001708 return size;
1709}
1710
1711#ifdef USE_GNU
1712int
1713recvmmsg (int fd, struct mmsghdr *vmessages,
1714 unsigned int vlen, int flags, struct timespec *tmo)
1715{
1716 ssize_t size;
1717 const char *func_str;
Florin Coras7baeb712019-01-04 17:05:43 -08001718 u32 sh = ldp_fd_to_vlsh (fd);
Dave Wallace048b1d62018-01-03 22:24:41 -05001719
Dave Wallace2a865272018-02-07 21:00:42 -05001720 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001721 return -1;
1722
Florin Coras7baeb712019-01-04 17:05:43 -08001723 if (sh != INVALID_SESSION_ID)
Dave Wallace048b1d62018-01-03 22:24:41 -05001724 {
1725 clib_warning ("LDP<%d>: LDP-TBD", getpid ());
1726 errno = ENOSYS;
1727 size = -1;
1728 }
1729 else
1730 {
1731 func_str = "libc_recvmmsg";
1732
Dave Wallace2a865272018-02-07 21:00:42 -05001733 if (LDP_DEBUG > 2)
Dave Wallace048b1d62018-01-03 22:24:41 -05001734 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1735 "vmessages %p, vlen %u, flags 0x%x, tmo %p",
1736 getpid (), fd, fd, func_str, vmessages, vlen,
1737 flags, tmo);
1738
1739 size = libc_recvmmsg (fd, vmessages, vlen, flags, tmo);
1740 }
1741
Dave Wallace2a865272018-02-07 21:00:42 -05001742 if (LDP_DEBUG > 2)
Dave Wallace048b1d62018-01-03 22:24:41 -05001743 {
1744 if (size < 0)
1745 {
1746 int errno_val = errno;
1747 perror (func_str);
1748 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1749 "rv %d, errno = %d", getpid (), fd, fd,
1750 func_str, size, errno_val);
1751 errno = errno_val;
1752 }
1753 else
1754 clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1755 getpid (), fd, fd, size, size);
1756 }
1757 return size;
1758}
1759#endif
1760
1761int
1762getsockopt (int fd, int level, int optname,
1763 void *__restrict optval, socklen_t * __restrict optlen)
1764{
Florin Coras7baeb712019-01-04 17:05:43 -08001765 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001766 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001767
Dave Wallace2a865272018-02-07 21:00:42 -05001768 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001769 return -1;
1770
Florin Coras7baeb712019-01-04 17:05:43 -08001771 vlsh = ldp_fd_to_vlsh (fd);
1772 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001773 {
1774 rv = -EOPNOTSUPP;
1775
1776 switch (level)
1777 {
1778 case SOL_TCP:
1779 switch (optname)
1780 {
1781 case TCP_NODELAY:
Florin Coras7baeb712019-01-04 17:05:43 -08001782 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_NODELAY,
1783 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001784 break;
1785 case TCP_MAXSEG:
Florin Coras7baeb712019-01-04 17:05:43 -08001786 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_USER_MSS,
1787 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001788 break;
1789 case TCP_KEEPIDLE:
Florin Coras7baeb712019-01-04 17:05:43 -08001790 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_KEEPIDLE,
1791 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001792 break;
1793 case TCP_KEEPINTVL:
Florin Coras7baeb712019-01-04 17:05:43 -08001794 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_KEEPINTVL,
1795 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001796 break;
1797 case TCP_INFO:
1798 if (optval && optlen && (*optlen == sizeof (struct tcp_info)))
1799 {
Florin Coras7baeb712019-01-04 17:05:43 -08001800 LDBG (1, "fd %d: vlsh %u SOL_TCP, TCP_INFO, optval %p, "
1801 "optlen %d: #LDP-NOP#", fd, vlsh, optval, *optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001802 memset (optval, 0, *optlen);
1803 rv = VPPCOM_OK;
1804 }
1805 else
1806 rv = -EFAULT;
1807 break;
Florin Coras0ed24e92019-01-21 09:03:10 -08001808 case TCP_CONGESTION:
1809 strcpy (optval, "cubic");
1810 *optlen = strlen ("cubic");
1811 rv = 0;
1812 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05001813 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001814 LDBG (0, "ERROR: fd %d: getsockopt SOL_TCP: sid %u, "
1815 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05001816 break;
1817 }
1818 break;
1819 case SOL_IPV6:
1820 switch (optname)
1821 {
1822 case IPV6_V6ONLY:
Florin Coras7baeb712019-01-04 17:05:43 -08001823 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_V6ONLY, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001824 break;
1825 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001826 LDBG (0, "ERROR: fd %d: getsockopt SOL_IPV6: vlsh %u "
1827 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05001828 break;
1829 }
1830 break;
1831 case SOL_SOCKET:
1832 switch (optname)
1833 {
1834 case SO_ACCEPTCONN:
Florin Coras7baeb712019-01-04 17:05:43 -08001835 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_LISTEN, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001836 break;
1837 case SO_KEEPALIVE:
Florin Coras7baeb712019-01-04 17:05:43 -08001838 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_KEEPALIVE, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001839 break;
1840 case SO_PROTOCOL:
Florin Coras7baeb712019-01-04 17:05:43 -08001841 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_PROTOCOL, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001842 *(int *) optval = *(int *) optval ? SOCK_DGRAM : SOCK_STREAM;
1843 break;
1844 case SO_SNDBUF:
Florin Coras7baeb712019-01-04 17:05:43 -08001845 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TX_FIFO_LEN,
1846 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001847 break;
1848 case SO_RCVBUF:
Florin Coras7baeb712019-01-04 17:05:43 -08001849 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_RX_FIFO_LEN,
1850 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001851 break;
1852 case SO_REUSEADDR:
Florin Coras7baeb712019-01-04 17:05:43 -08001853 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_REUSEADDR, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001854 break;
1855 case SO_BROADCAST:
Florin Coras7baeb712019-01-04 17:05:43 -08001856 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_BROADCAST, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001857 break;
1858 case SO_ERROR:
Florin Coras7baeb712019-01-04 17:05:43 -08001859 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_ERROR, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001860 break;
1861 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001862 LDBG (0, "ERROR: fd %d: getsockopt SOL_SOCKET: vlsh %u "
1863 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05001864 break;
1865 }
1866 break;
1867 default:
1868 break;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001869 }
1870
Dave Wallace048b1d62018-01-03 22:24:41 -05001871 if (rv != VPPCOM_OK)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001872 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001873 errno = -rv;
1874 rv = -1;
1875 }
1876 }
1877 else
1878 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001879 rv = libc_getsockopt (fd, level, optname, optval, optlen);
1880 }
1881
Dave Wallace048b1d62018-01-03 22:24:41 -05001882 return rv;
1883}
1884
1885int
1886setsockopt (int fd, int level, int optname,
1887 const void *optval, socklen_t optlen)
1888{
Florin Coras7baeb712019-01-04 17:05:43 -08001889 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001890 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001891
Dave Wallace2a865272018-02-07 21:00:42 -05001892 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001893 return -1;
1894
Florin Coras7baeb712019-01-04 17:05:43 -08001895 vlsh = ldp_fd_to_vlsh (fd);
1896 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001897 {
1898 rv = -EOPNOTSUPP;
1899
1900 switch (level)
1901 {
1902 case SOL_TCP:
1903 switch (optname)
1904 {
1905 case TCP_NODELAY:
Florin Coras7baeb712019-01-04 17:05:43 -08001906 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_NODELAY,
1907 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001908 break;
1909 case TCP_MAXSEG:
Florin Coras7baeb712019-01-04 17:05:43 -08001910 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_USER_MSS,
1911 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001912 break;
1913 case TCP_KEEPIDLE:
Florin Coras7baeb712019-01-04 17:05:43 -08001914 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_KEEPIDLE,
1915 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001916 break;
1917 case TCP_KEEPINTVL:
Florin Coras7baeb712019-01-04 17:05:43 -08001918 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_KEEPINTVL,
1919 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001920 break;
Florin Coras0ed24e92019-01-21 09:03:10 -08001921 case TCP_CONGESTION:
Florin Coras8509aa22019-04-04 12:55:30 -07001922 case TCP_CORK:
Florin Coras0ed24e92019-01-21 09:03:10 -08001923 /* Ignore */
1924 rv = 0;
1925 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05001926 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001927 LDBG (0, "ERROR: fd %d: setsockopt() SOL_TCP: vlsh %u"
1928 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05001929 break;
1930 }
1931 break;
1932 case SOL_IPV6:
1933 switch (optname)
1934 {
1935 case IPV6_V6ONLY:
Florin Coras7baeb712019-01-04 17:05:43 -08001936 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_V6ONLY,
1937 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001938 break;
1939 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001940 LDBG (0, "ERROR: fd %d: setsockopt SOL_IPV6: vlsh %u"
1941 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05001942 break;
1943 }
1944 break;
1945 case SOL_SOCKET:
1946 switch (optname)
1947 {
1948 case SO_KEEPALIVE:
Florin Coras7baeb712019-01-04 17:05:43 -08001949 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_KEEPALIVE,
1950 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001951 break;
1952 case SO_REUSEADDR:
Florin Coras7baeb712019-01-04 17:05:43 -08001953 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_REUSEADDR,
1954 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001955 break;
1956 case SO_BROADCAST:
Florin Coras7baeb712019-01-04 17:05:43 -08001957 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_BROADCAST,
1958 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001959 break;
1960 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001961 LDBG (0, "ERROR: fd %d: setsockopt SOL_SOCKET: vlsh %u "
1962 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05001963 break;
1964 }
1965 break;
1966 default:
1967 break;
1968 }
1969
1970 if (rv != VPPCOM_OK)
1971 {
1972 errno = -rv;
1973 rv = -1;
1974 }
1975 }
1976 else
1977 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001978 rv = libc_setsockopt (fd, level, optname, optval, optlen);
1979 }
1980
Dave Wallace048b1d62018-01-03 22:24:41 -05001981 return rv;
1982}
1983
1984int
1985listen (int fd, int n)
1986{
Florin Coras7baeb712019-01-04 17:05:43 -08001987 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001988 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001989
Dave Wallace2a865272018-02-07 21:00:42 -05001990 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001991 return -1;
1992
Florin Coras7baeb712019-01-04 17:05:43 -08001993 vlsh = ldp_fd_to_vlsh (fd);
1994 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001995 {
Florin Coras7baeb712019-01-04 17:05:43 -08001996 LDBG (0, "fd %d: calling vls_listen: vlsh %u, n %d", fd, vlsh, n);
Dave Wallace048b1d62018-01-03 22:24:41 -05001997
Florin Coras7baeb712019-01-04 17:05:43 -08001998 rv = vls_listen (vlsh, n);
Dave Wallace048b1d62018-01-03 22:24:41 -05001999 if (rv != VPPCOM_OK)
2000 {
2001 errno = -rv;
2002 rv = -1;
2003 }
2004 }
2005 else
2006 {
Florin Coras7baeb712019-01-04 17:05:43 -08002007 LDBG (0, "fd %d: calling libc_listen(): n %d", fd, n);
Dave Wallace048b1d62018-01-03 22:24:41 -05002008 rv = libc_listen (fd, n);
2009 }
2010
Florin Coras7baeb712019-01-04 17:05:43 -08002011 LDBG (1, "fd %d: returning %d", fd, rv);
Dave Wallace048b1d62018-01-03 22:24:41 -05002012 return rv;
2013}
2014
2015static inline int
Dave Wallace2a865272018-02-07 21:00:42 -05002016ldp_accept4 (int listen_fd, __SOCKADDR_ARG addr,
2017 socklen_t * __restrict addr_len, int flags)
Dave Wallace048b1d62018-01-03 22:24:41 -05002018{
Florin Coras7baeb712019-01-04 17:05:43 -08002019 vls_handle_t listen_vlsh, accept_vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002020 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05002021
Dave Wallace2a865272018-02-07 21:00:42 -05002022 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05002023 return -1;
2024
Florin Coras7baeb712019-01-04 17:05:43 -08002025 listen_vlsh = ldp_fd_to_vlsh (listen_fd);
2026 if (listen_vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05002027 {
2028 vppcom_endpt_t ep;
2029 u8 src_addr[sizeof (struct sockaddr_in6)];
Dave Wallace8aaba562018-01-18 17:21:19 -05002030 memset (&ep, 0, sizeof (ep));
Dave Wallace048b1d62018-01-03 22:24:41 -05002031 ep.ip = src_addr;
2032
Florin Coras7baeb712019-01-04 17:05:43 -08002033 LDBG (0, "listen fd %d: calling vppcom_session_accept: listen sid %u,"
2034 " ep %p, flags 0x%x", listen_fd, listen_vlsh, ep, flags);
Dave Wallace048b1d62018-01-03 22:24:41 -05002035
Florin Coras7baeb712019-01-04 17:05:43 -08002036 accept_vlsh = vls_accept (listen_vlsh, &ep, flags);
2037 if (accept_vlsh < 0)
Dave Wallace048b1d62018-01-03 22:24:41 -05002038 {
Florin Coras7baeb712019-01-04 17:05:43 -08002039 errno = -accept_vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002040 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002041 }
2042 else
2043 {
Dave Wallace2a865272018-02-07 21:00:42 -05002044 rv = ldp_copy_ep_to_sockaddr (addr, addr_len, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05002045 if (rv != VPPCOM_OK)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002046 {
Florin Coras7baeb712019-01-04 17:05:43 -08002047 (void) vls_close (accept_vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05002048 errno = -rv;
2049 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002050 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002051 else
2052 {
Florin Coras7baeb712019-01-04 17:05:43 -08002053 rv = ldp_vlsh_to_fd (accept_vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05002054 }
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002055 }
2056 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002057 else
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002058 {
Florin Coras7baeb712019-01-04 17:05:43 -08002059 LDBG (0, "listen fd %d: calling libc_accept4(): addr %p, addr_len %p,"
2060 " flags 0x%x", listen_fd, addr, addr_len, flags);
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002061
Dave Wallace048b1d62018-01-03 22:24:41 -05002062 rv = libc_accept4 (listen_fd, addr, addr_len, flags);
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002063 }
2064
Florin Coras7baeb712019-01-04 17:05:43 -08002065 LDBG (1, "listen fd %d: accept returning %d", listen_fd, rv);
Florin Coras05ecfcc2018-12-12 18:19:39 -08002066
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002067 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002068}
2069
Dave Wallace048b1d62018-01-03 22:24:41 -05002070int
2071accept4 (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len,
2072 int flags)
2073{
Dave Wallace2a865272018-02-07 21:00:42 -05002074 return ldp_accept4 (fd, addr, addr_len, flags);
Dave Wallace048b1d62018-01-03 22:24:41 -05002075}
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002076
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002077int
Dave Wallace048b1d62018-01-03 22:24:41 -05002078accept (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002079{
Dave Wallace2a865272018-02-07 21:00:42 -05002080 return ldp_accept4 (fd, addr, addr_len, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002081}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002082
Dave Wallace048b1d62018-01-03 22:24:41 -05002083int
2084shutdown (int fd, int how)
2085{
Florin Coras7baeb712019-01-04 17:05:43 -08002086 vls_handle_t vlsh;
2087 int rv = 0, flags;
2088 u32 flags_len = sizeof (flags);
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002089
Dave Wallace2a865272018-02-07 21:00:42 -05002090 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05002091 return -1;
2092
Florin Coras7baeb712019-01-04 17:05:43 -08002093 vlsh = ldp_fd_to_vlsh (fd);
2094 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05002095 {
Florin Coras7baeb712019-01-04 17:05:43 -08002096 LDBG (0, "called shutdown: fd %u vlsh %u how %d", fd, vlsh, how);
Florin Corasa7a1a222018-12-30 17:11:31 -08002097
Florin Coras7baeb712019-01-04 17:05:43 -08002098 if (vls_attr (vlsh, VPPCOM_ATTR_SET_SHUT, &how, &flags_len))
Florin Corasa7a1a222018-12-30 17:11:31 -08002099 {
Florin Coras7baeb712019-01-04 17:05:43 -08002100 close (fd);
Florin Corasa7a1a222018-12-30 17:11:31 -08002101 return -1;
2102 }
2103
Florin Coras7baeb712019-01-04 17:05:43 -08002104 if (vls_attr (vlsh, VPPCOM_ATTR_GET_SHUT, &flags, &flags_len))
2105 {
2106 close (fd);
2107 return -1;
2108 }
Florin Corasa7a1a222018-12-30 17:11:31 -08002109
Florin Coras7baeb712019-01-04 17:05:43 -08002110 if (flags == SHUT_RDWR)
Florin Corasa7a1a222018-12-30 17:11:31 -08002111 rv = close (fd);
Dave Wallace048b1d62018-01-03 22:24:41 -05002112 }
2113 else
2114 {
Florin Coras7baeb712019-01-04 17:05:43 -08002115 LDBG (0, "fd %d: calling libc_shutdown: how %d", fd, how);
Dave Wallace048b1d62018-01-03 22:24:41 -05002116 rv = libc_shutdown (fd, how);
2117 }
2118
Dave Wallace048b1d62018-01-03 22:24:41 -05002119 return rv;
2120}
2121
2122int
2123epoll_create1 (int flags)
2124{
Florin Corasdfe4cf42018-11-28 22:13:45 -08002125 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras7baeb712019-01-04 17:05:43 -08002126 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002127 int rv;
2128
Dave Wallace2a865272018-02-07 21:00:42 -05002129 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05002130 return -1;
2131
Florin Coras99368312018-08-02 10:45:44 -07002132 if (ldp->vcl_needs_real_epoll)
2133 {
Florin Coras2d9b4272019-03-11 10:14:37 -07002134 /* Make sure workers have been allocated */
2135 if (!ldp->workers)
2136 {
2137 ldp_alloc_workers ();
2138 ldpw = ldp_worker_get_current ();
2139 }
Florin Coras99368312018-08-02 10:45:44 -07002140 rv = libc_epoll_create1 (flags);
2141 ldp->vcl_needs_real_epoll = 0;
Florin Corasdfe4cf42018-11-28 22:13:45 -08002142 ldpw->vcl_mq_epfd = rv;
Florin Coras05ecfcc2018-12-12 18:19:39 -08002143 LDBG (0, "created vcl epfd %u", rv);
Florin Coras99368312018-08-02 10:45:44 -07002144 return rv;
2145 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002146
Florin Coras7baeb712019-01-04 17:05:43 -08002147 vlsh = vls_epoll_create ();
2148 if (PREDICT_FALSE (vlsh == VLS_INVALID_HANDLE))
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002149 {
Florin Coras7baeb712019-01-04 17:05:43 -08002150 errno = -vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002151 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002152 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002153 else
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002154 {
Florin Coras7baeb712019-01-04 17:05:43 -08002155 rv = ldp_vlsh_to_fd (vlsh);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002156 }
Florin Coras7baeb712019-01-04 17:05:43 -08002157 LDBG (0, "epoll_create epfd %u vlsh %u", rv, vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05002158 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002159}
2160
2161int
Dave Wallace048b1d62018-01-03 22:24:41 -05002162epoll_create (int size)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002163{
Dave Wallace048b1d62018-01-03 22:24:41 -05002164 return epoll_create1 (0);
2165}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002166
Dave Wallace048b1d62018-01-03 22:24:41 -05002167int
2168epoll_ctl (int epfd, int op, int fd, struct epoll_event *event)
2169{
Florin Coras7baeb712019-01-04 17:05:43 -08002170 vls_handle_t vep_vlsh, vlsh;
Florin Coras99368312018-08-02 10:45:44 -07002171 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05002172
Dave Wallace2a865272018-02-07 21:00:42 -05002173 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05002174 return -1;
2175
Florin Coras7baeb712019-01-04 17:05:43 -08002176 vep_vlsh = ldp_fd_to_vlsh (epfd);
2177 if (PREDICT_FALSE (vep_vlsh == VLS_INVALID_HANDLE))
Dave Wallace048b1d62018-01-03 22:24:41 -05002178 {
Dave Wallace3ee1fe12018-02-23 01:09:11 -05002179 /* The LDP epoll_create1 always creates VCL epfd's.
2180 * The app should never have a kernel base epoll fd unless it
2181 * was acquired outside of the LD_PRELOAD process context.
2182 * In any case, if we get one, punt it to libc_epoll_ctl.
2183 */
Florin Coras7baeb712019-01-04 17:05:43 -08002184 LDBG (1, "epfd %d: calling libc_epoll_ctl: op %d, fd %d"
2185 " event %p", epfd, op, fd, event);
Dave Wallace048b1d62018-01-03 22:24:41 -05002186
2187 rv = libc_epoll_ctl (epfd, op, fd, event);
Florin Coras99368312018-08-02 10:45:44 -07002188 goto done;
2189 }
2190
Florin Coras7baeb712019-01-04 17:05:43 -08002191 vlsh = ldp_fd_to_vlsh (fd);
Florin Coras99368312018-08-02 10:45:44 -07002192
Florin Coras7baeb712019-01-04 17:05:43 -08002193 LDBG (0, "epfd %d ep_vlsh %d, fd %u vlsh %d, op %u", epfd, vep_vlsh, fd,
2194 vlsh, op);
Florin Coras99368312018-08-02 10:45:44 -07002195
Florin Coras7baeb712019-01-04 17:05:43 -08002196 if (vlsh != VLS_INVALID_HANDLE)
Florin Coras99368312018-08-02 10:45:44 -07002197 {
Florin Coras7baeb712019-01-04 17:05:43 -08002198 LDBG (1, "epfd %d: calling vls_epoll_ctl: ep_vlsh %d op %d, vlsh %u,"
2199 " event %p", epfd, vep_vlsh, vlsh, event);
Florin Coras99368312018-08-02 10:45:44 -07002200
Florin Coras7baeb712019-01-04 17:05:43 -08002201 rv = vls_epoll_ctl (vep_vlsh, op, vlsh, event);
Florin Coras99368312018-08-02 10:45:44 -07002202 if (rv != VPPCOM_OK)
2203 {
2204 errno = -rv;
2205 rv = -1;
2206 }
2207 }
2208 else
2209 {
2210 int libc_epfd;
2211 u32 size = sizeof (epfd);
2212
Florin Coras7baeb712019-01-04 17:05:43 -08002213 libc_epfd = vls_attr (vep_vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
Florin Coras99368312018-08-02 10:45:44 -07002214 if (!libc_epfd)
2215 {
Florin Coras7baeb712019-01-04 17:05:43 -08002216 LDBG (1, "epfd %d, vep_vlsh %d calling libc_epoll_create1: "
2217 "EPOLL_CLOEXEC", epfd, vep_vlsh);
Florin Coras99368312018-08-02 10:45:44 -07002218
2219 libc_epfd = libc_epoll_create1 (EPOLL_CLOEXEC);
2220 if (libc_epfd < 0)
2221 {
2222 rv = libc_epfd;
2223 goto done;
2224 }
2225
Florin Coras7baeb712019-01-04 17:05:43 -08002226 rv = vls_attr (vep_vlsh, VPPCOM_ATTR_SET_LIBC_EPFD, &libc_epfd,
2227 &size);
Florin Coras99368312018-08-02 10:45:44 -07002228 if (rv < 0)
2229 {
2230 errno = -rv;
2231 rv = -1;
2232 goto done;
2233 }
2234 }
2235 else if (PREDICT_FALSE (libc_epfd < 0))
2236 {
2237 errno = -epfd;
2238 rv = -1;
2239 goto done;
2240 }
2241
Florin Coras7baeb712019-01-04 17:05:43 -08002242 LDBG (1, "epfd %d: calling libc_epoll_ctl: libc_epfd %d, op %d, fd %d,"
2243 " event %p", epfd, libc_epfd, op, fd, event);
Florin Coras99368312018-08-02 10:45:44 -07002244
2245 rv = libc_epoll_ctl (libc_epfd, op, fd, event);
Dave Wallace048b1d62018-01-03 22:24:41 -05002246 }
2247
2248done:
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002249 return rv;
2250}
Dave Wallace048b1d62018-01-03 22:24:41 -05002251
2252static inline int
Florin Coras99368312018-08-02 10:45:44 -07002253ldp_epoll_pwait (int epfd, struct epoll_event *events, int maxevents,
2254 int timeout, const sigset_t * sigmask)
Dave Wallace048b1d62018-01-03 22:24:41 -05002255{
Florin Corasdfe4cf42018-11-28 22:13:45 -08002256 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras72f77822019-01-22 19:05:52 -08002257 double time_to_wait = (double) 0, max_time;
Florin Coras99368312018-08-02 10:45:44 -07002258 int libc_epfd, rv = 0;
Florin Coras7baeb712019-01-04 17:05:43 -08002259 vls_handle_t ep_vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002260
Dave Wallace2a865272018-02-07 21:00:42 -05002261 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05002262 return -1;
2263
2264 if (PREDICT_FALSE (!events || (timeout < -1)))
2265 {
2266 errno = EFAULT;
2267 return -1;
2268 }
2269
Florin Corasdfe4cf42018-11-28 22:13:45 -08002270 if (epfd == ldpw->vcl_mq_epfd)
Florin Coras99368312018-08-02 10:45:44 -07002271 return libc_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
2272
Florin Coras7baeb712019-01-04 17:05:43 -08002273 ep_vlsh = ldp_fd_to_vlsh (epfd);
2274 if (PREDICT_FALSE (ep_vlsh == VLS_INVALID_HANDLE))
Dave Wallace048b1d62018-01-03 22:24:41 -05002275 {
Florin Coras7baeb712019-01-04 17:05:43 -08002276 LDBG (0, "epfd %d: bad ep_vlsh %d!", epfd, ep_vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05002277 errno = EBADFD;
2278 return -1;
2279 }
2280
Florin Coras4dee8cd2019-01-29 21:28:16 -08002281 if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
2282 clib_time_init (&ldpw->clib_time);
Florin Corasb0f662f2018-12-27 14:51:46 -08002283 time_to_wait = ((timeout >= 0) ? (double) timeout / 1000 : 0);
Florin Coras72f77822019-01-22 19:05:52 -08002284 max_time = clib_time_now (&ldpw->clib_time) + time_to_wait;
Dave Wallace048b1d62018-01-03 22:24:41 -05002285
Florin Coras7baeb712019-01-04 17:05:43 -08002286 libc_epfd = vls_attr (ep_vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002287 if (PREDICT_FALSE (libc_epfd < 0))
2288 {
2289 errno = -libc_epfd;
2290 rv = -1;
2291 goto done;
2292 }
2293
Florin Coras7baeb712019-01-04 17:05:43 -08002294 LDBG (2, "epfd %d: vep_idx %d, libc_epfd %d, events %p, maxevents %d, "
2295 "timeout %d, sigmask %p: time_to_wait %.02f", epfd, ep_vlsh,
Florin Coras72f77822019-01-22 19:05:52 -08002296 libc_epfd, events, maxevents, timeout, sigmask, time_to_wait);
Dave Wallace048b1d62018-01-03 22:24:41 -05002297 do
2298 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002299 if (!ldpw->epoll_wait_vcl)
Dave Wallace048b1d62018-01-03 22:24:41 -05002300 {
Florin Coras7baeb712019-01-04 17:05:43 -08002301 rv = vls_epoll_wait (ep_vlsh, events, maxevents, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002302 if (rv > 0)
2303 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002304 ldpw->epoll_wait_vcl = 1;
Dave Wallace048b1d62018-01-03 22:24:41 -05002305 goto done;
2306 }
2307 else if (rv < 0)
2308 {
2309 errno = -rv;
2310 rv = -1;
2311 goto done;
2312 }
2313 }
2314 else
Florin Corasdfe4cf42018-11-28 22:13:45 -08002315 ldpw->epoll_wait_vcl = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -05002316
2317 if (libc_epfd > 0)
2318 {
Florin Corasb0f662f2018-12-27 14:51:46 -08002319 rv = libc_epoll_pwait (libc_epfd, events, maxevents, 0, sigmask);
Dave Wallace048b1d62018-01-03 22:24:41 -05002320 if (rv != 0)
2321 goto done;
2322 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002323 }
Florin Coras72f77822019-01-22 19:05:52 -08002324 while ((timeout == -1) || (clib_time_now (&ldpw->clib_time) < max_time));
Dave Wallace048b1d62018-01-03 22:24:41 -05002325
2326done:
Dave Wallace048b1d62018-01-03 22:24:41 -05002327 return rv;
2328}
2329
2330int
2331epoll_pwait (int epfd, struct epoll_event *events,
2332 int maxevents, int timeout, const sigset_t * sigmask)
2333{
Dave Wallace2a865272018-02-07 21:00:42 -05002334 return ldp_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
Dave Wallace048b1d62018-01-03 22:24:41 -05002335}
2336
2337int
2338epoll_wait (int epfd, struct epoll_event *events, int maxevents, int timeout)
2339{
Dave Wallace2a865272018-02-07 21:00:42 -05002340 return ldp_epoll_pwait (epfd, events, maxevents, timeout, NULL);
Dave Wallace048b1d62018-01-03 22:24:41 -05002341}
2342
2343int
2344poll (struct pollfd *fds, nfds_t nfds, int timeout)
2345{
Florin Corasdfe4cf42018-11-28 22:13:45 -08002346 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras6917b942018-11-13 22:44:54 -08002347 int rv, i, n_revents = 0;
Florin Coras7baeb712019-01-04 17:05:43 -08002348 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002349 vcl_poll_t *vp;
Florin Coras4dee8cd2019-01-29 21:28:16 -08002350 double max_time;
Dave Wallace048b1d62018-01-03 22:24:41 -05002351
Florin Coras05ecfcc2018-12-12 18:19:39 -08002352 LDBG (3, "fds %p, nfds %d, timeout %d", fds, nfds, timeout);
Dave Wallace048b1d62018-01-03 22:24:41 -05002353
Florin Coras4dee8cd2019-01-29 21:28:16 -08002354 if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
2355 clib_time_init (&ldpw->clib_time);
2356
2357 max_time = (timeout >= 0) ? (f64) timeout / 1000 : 0;
2358 max_time += clib_time_now (&ldpw->clib_time);
Dave Wallace048b1d62018-01-03 22:24:41 -05002359
Dave Wallace048b1d62018-01-03 22:24:41 -05002360 for (i = 0; i < nfds; i++)
2361 {
Florin Coras6917b942018-11-13 22:44:54 -08002362 if (fds[i].fd < 0)
2363 continue;
Dave Wallace048b1d62018-01-03 22:24:41 -05002364
Florin Coras7baeb712019-01-04 17:05:43 -08002365 vlsh = ldp_fd_to_vlsh (fds[i].fd);
2366 if (vlsh != VLS_INVALID_HANDLE)
Florin Coras6917b942018-11-13 22:44:54 -08002367 {
2368 fds[i].fd = -fds[i].fd;
Florin Corasdfe4cf42018-11-28 22:13:45 -08002369 vec_add2 (ldpw->vcl_poll, vp, 1);
Florin Coras6917b942018-11-13 22:44:54 -08002370 vp->fds_ndx = i;
Florin Coras7baeb712019-01-04 17:05:43 -08002371 vp->sh = vlsh_to_sh (vlsh);
Florin Coras6917b942018-11-13 22:44:54 -08002372 vp->events = fds[i].events;
Dave Wallace048b1d62018-01-03 22:24:41 -05002373#ifdef __USE_XOPEN2K
Florin Coras6917b942018-11-13 22:44:54 -08002374 if (fds[i].events & POLLRDNORM)
2375 vp->events |= POLLIN;
2376 if (fds[i].events & POLLWRNORM)
2377 vp->events |= POLLOUT;
Dave Wallace048b1d62018-01-03 22:24:41 -05002378#endif
Florin Coras6917b942018-11-13 22:44:54 -08002379 vp->revents = fds[i].revents;
2380 }
2381 else
2382 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002383 vec_add1 (ldpw->libc_poll, fds[i]);
2384 vec_add1 (ldpw->libc_poll_idxs, i);
Dave Wallace048b1d62018-01-03 22:24:41 -05002385 }
2386 }
2387
Dave Wallace048b1d62018-01-03 22:24:41 -05002388 do
2389 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002390 if (vec_len (ldpw->vcl_poll))
Dave Wallace048b1d62018-01-03 22:24:41 -05002391 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002392 rv = vppcom_poll (ldpw->vcl_poll, vec_len (ldpw->vcl_poll), 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002393 if (rv < 0)
2394 {
2395 errno = -rv;
2396 rv = -1;
2397 goto done;
2398 }
2399 else
2400 n_revents += rv;
2401 }
2402
Florin Corasdfe4cf42018-11-28 22:13:45 -08002403 if (vec_len (ldpw->libc_poll))
Dave Wallace048b1d62018-01-03 22:24:41 -05002404 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002405 rv = libc_poll (ldpw->libc_poll, vec_len (ldpw->libc_poll), 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002406 if (rv < 0)
2407 goto done;
2408 else
2409 n_revents += rv;
2410 }
2411
2412 if (n_revents)
2413 {
2414 rv = n_revents;
2415 goto done;
2416 }
2417 }
Florin Coras4dee8cd2019-01-29 21:28:16 -08002418 while ((timeout < 0) || (clib_time_now (&ldpw->clib_time) < max_time));
Dave Wallace048b1d62018-01-03 22:24:41 -05002419 rv = 0;
2420
2421done:
Florin Corasdfe4cf42018-11-28 22:13:45 -08002422 vec_foreach (vp, ldpw->vcl_poll)
Dave Wallace048b1d62018-01-03 22:24:41 -05002423 {
2424 fds[vp->fds_ndx].fd = -fds[vp->fds_ndx].fd;
Florin Coras6917b942018-11-13 22:44:54 -08002425 fds[vp->fds_ndx].revents = vp->revents;
Dave Wallace048b1d62018-01-03 22:24:41 -05002426#ifdef __USE_XOPEN2K
2427 if ((fds[vp->fds_ndx].revents & POLLIN) &&
2428 (fds[vp->fds_ndx].events & POLLRDNORM))
2429 fds[vp->fds_ndx].revents |= POLLRDNORM;
2430 if ((fds[vp->fds_ndx].revents & POLLOUT) &&
2431 (fds[vp->fds_ndx].events & POLLWRNORM))
2432 fds[vp->fds_ndx].revents |= POLLWRNORM;
2433#endif
2434 }
Florin Corasdfe4cf42018-11-28 22:13:45 -08002435 vec_reset_length (ldpw->vcl_poll);
Dave Wallace048b1d62018-01-03 22:24:41 -05002436
Florin Corasdfe4cf42018-11-28 22:13:45 -08002437 for (i = 0; i < vec_len (ldpw->libc_poll); i++)
Florin Coras6917b942018-11-13 22:44:54 -08002438 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002439 fds[ldpw->libc_poll_idxs[i]].revents = ldpw->libc_poll[i].revents;
Florin Coras6917b942018-11-13 22:44:54 -08002440 }
Florin Corasdfe4cf42018-11-28 22:13:45 -08002441 vec_reset_length (ldpw->libc_poll_idxs);
2442 vec_reset_length (ldpw->libc_poll);
Florin Coras6917b942018-11-13 22:44:54 -08002443
Dave Wallace048b1d62018-01-03 22:24:41 -05002444 return rv;
2445}
2446
2447#ifdef USE_GNU
2448int
2449ppoll (struct pollfd *fds, nfds_t nfds,
2450 const struct timespec *timeout, const sigset_t * sigmask)
2451{
Dave Wallace2a865272018-02-07 21:00:42 -05002452 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05002453 return -1;
2454
2455 clib_warning ("LDP<%d>: LDP-TBD", getpid ());
2456 errno = ENOSYS;
2457
2458
2459 return -1;
2460}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002461#endif
2462
Dave Wallace2a865272018-02-07 21:00:42 -05002463void CONSTRUCTOR_ATTRIBUTE ldp_constructor (void);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002464
Dave Wallace2a865272018-02-07 21:00:42 -05002465void DESTRUCTOR_ATTRIBUTE ldp_destructor (void);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002466
Dave Wallace048b1d62018-01-03 22:24:41 -05002467/*
2468 * This function is called when the library is loaded
2469 */
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002470void
Dave Wallace2a865272018-02-07 21:00:42 -05002471ldp_constructor (void)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002472{
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002473 swrap_constructor ();
Dave Wallace2a865272018-02-07 21:00:42 -05002474 if (ldp_init () != 0)
Florin Corasd89411e2019-03-19 19:44:51 -07002475 {
2476 fprintf (stderr, "\nLDP<%d>: ERROR: ldp_constructor: failed!\n",
2477 getpid ());
2478 _exit (1);
2479 }
Dave Wallace69d01192018-02-22 16:22:09 -05002480 else if (LDP_DEBUG > 0)
Dave Wallace2a865272018-02-07 21:00:42 -05002481 clib_warning ("LDP<%d>: LDP constructor: done!\n", getpid ());
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002482}
2483
2484/*
2485 * This function is called when the library is unloaded
2486 */
2487void
Dave Wallace2a865272018-02-07 21:00:42 -05002488ldp_destructor (void)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002489{
Florin Coras0ef8ef22019-01-18 08:37:13 -08002490 /*
2491 swrap_destructor ();
2492 if (ldp->init)
2493 ldp->init = 0;
2494 */
Dave Wallace048b1d62018-01-03 22:24:41 -05002495
2496 /* Don't use clib_warning() here because that calls writev()
Dave Wallace2a865272018-02-07 21:00:42 -05002497 * which will call ldp_init().
Dave Wallace048b1d62018-01-03 22:24:41 -05002498 */
Dave Wallace69d01192018-02-22 16:22:09 -05002499 if (LDP_DEBUG > 0)
Florin Coras0ef8ef22019-01-18 08:37:13 -08002500 fprintf (stderr, "%s:%d: LDP<%d>: LDP destructor: done!\n",
2501 __func__, __LINE__, getpid ());
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002502}
2503
2504
2505/*
2506 * fd.io coding-style-patch-verification: ON
2507 *
2508 * Local Variables:
2509 * eval: (c-set-style "gnu")
2510 * End:
2511 */