blob: 0dbc6a51efcc5fbab3543383bc5e7f4d0f399e74 [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) \
hanlin9f3f18f2019-12-30 16:25:20 +0800112 { \
113 int errno_saved = errno; \
114 clib_warning ("ldp<%d>: " _fmt, getpid(), ##_args); \
115 errno = errno_saved; \
116 }
Florin Coras99368312018-08-02 10:45:44 -0700117
Dave Wallace2a865272018-02-07 21:00:42 -0500118static ldp_main_t ldp_main = {
Florin Coras7baeb712019-01-04 17:05:43 -0800119 .vlsh_bit_val = (1 << LDP_SID_BIT_MIN),
120 .vlsh_bit_mask = (1 << LDP_SID_BIT_MIN) - 1,
Dave Wallace2a865272018-02-07 21:00:42 -0500121 .debug = LDP_DEBUG_INIT,
Yu Ping7b74b072019-05-08 00:40:24 +0800122 .transparent_tls = 0,
Dave Wallace048b1d62018-01-03 22:24:41 -0500123};
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700124
Dave Wallace2a865272018-02-07 21:00:42 -0500125static ldp_main_t *ldp = &ldp_main;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700126
Florin Corasdfe4cf42018-11-28 22:13:45 -0800127static inline ldp_worker_ctx_t *
128ldp_worker_get_current (void)
129{
130 return (ldp->workers + vppcom_worker_index ());
131}
132
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700133/*
134 * RETURN: 0 on success or -1 on error.
135 * */
Dave Wallace048b1d62018-01-03 22:24:41 -0500136static inline void
Dave Wallace2a865272018-02-07 21:00:42 -0500137ldp_set_app_name (char *app_name)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700138{
Benoît Ganne747b3d82019-08-21 18:27:23 +0200139 snprintf (ldp->app_name, LDP_APP_NAME_MAX,
140 "ldp-%d-%s", getpid (), app_name);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700141}
142
Dave Wallace048b1d62018-01-03 22:24:41 -0500143static inline char *
Dave Wallace2a865272018-02-07 21:00:42 -0500144ldp_get_app_name ()
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700145{
Dave Wallace2a865272018-02-07 21:00:42 -0500146 if (ldp->app_name[0] == '\0')
147 ldp_set_app_name ("app");
Dave Wallace048b1d62018-01-03 22:24:41 -0500148
Dave Wallace2a865272018-02-07 21:00:42 -0500149 return ldp->app_name;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700150}
151
Dave Wallace048b1d62018-01-03 22:24:41 -0500152static inline int
Florin Coras7baeb712019-01-04 17:05:43 -0800153ldp_vlsh_to_fd (vls_handle_t vlsh)
Dave Wallace048b1d62018-01-03 22:24:41 -0500154{
Florin Coras7baeb712019-01-04 17:05:43 -0800155 return (vlsh + ldp->vlsh_bit_val);
Dave Wallace048b1d62018-01-03 22:24:41 -0500156}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700157
Florin Coras7baeb712019-01-04 17:05:43 -0800158static inline vls_handle_t
159ldp_fd_to_vlsh (int fd)
Dave Wallace048b1d62018-01-03 22:24:41 -0500160{
Florin Coras7baeb712019-01-04 17:05:43 -0800161 if (fd < ldp->vlsh_bit_val)
162 return VLS_INVALID_HANDLE;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700163
Florin Coras7baeb712019-01-04 17:05:43 -0800164 return (fd - ldp->vlsh_bit_val);
Dave Wallace048b1d62018-01-03 22:24:41 -0500165}
166
Florin Coras2d9b4272019-03-11 10:14:37 -0700167static void
168ldp_alloc_workers (void)
169{
170 if (ldp->workers)
171 return;
172 pool_alloc (ldp->workers, LDP_MAX_NWORKERS);
173}
174
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700175static inline int
Dave Wallace2a865272018-02-07 21:00:42 -0500176ldp_init (void)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700177{
Florin Corasdfe4cf42018-11-28 22:13:45 -0800178 ldp_worker_ctx_t *ldpw;
Florin Coras99368312018-08-02 10:45:44 -0700179 int rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700180
Florin Coras99368312018-08-02 10:45:44 -0700181 if (PREDICT_TRUE (ldp->init))
182 return 0;
183
184 ldp->init = 1;
185 ldp->vcl_needs_real_epoll = 1;
Florin Coras7baeb712019-01-04 17:05:43 -0800186 rv = vls_app_create (ldp_get_app_name ());
Florin Coras99368312018-08-02 10:45:44 -0700187 if (rv != VPPCOM_OK)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700188 {
Florin Coras955bfbb2018-12-04 13:43:45 -0800189 ldp->vcl_needs_real_epoll = 0;
190 if (rv == VPPCOM_EEXIST)
191 return 0;
Florin Coras05ecfcc2018-12-12 18:19:39 -0800192 LDBG (2, "\nERROR: ldp_init: vppcom_app_create()"
193 " failed! rv = %d (%s)\n", rv, vppcom_retval_str (rv));
Florin Coras99368312018-08-02 10:45:44 -0700194 ldp->init = 0;
195 return rv;
196 }
197 ldp->vcl_needs_real_epoll = 0;
Florin Coras2d9b4272019-03-11 10:14:37 -0700198 ldp_alloc_workers ();
Florin Corasdfe4cf42018-11-28 22:13:45 -0800199 ldpw = ldp_worker_get_current ();
Florin Coras99368312018-08-02 10:45:44 -0700200
201 char *env_var_str = getenv (LDP_ENV_DEBUG);
202 if (env_var_str)
203 {
204 u32 tmp;
205 if (sscanf (env_var_str, "%u", &tmp) != 1)
206 clib_warning ("LDP<%d>: WARNING: Invalid LDP debug level specified in"
207 " the env var " LDP_ENV_DEBUG " (%s)!", getpid (),
208 env_var_str);
209 else
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700210 {
Florin Coras99368312018-08-02 10:45:44 -0700211 ldp->debug = tmp;
Florin Coras05ecfcc2018-12-12 18:19:39 -0800212 LDBG (0, "configured LDP debug level (%u) from env var "
213 LDP_ENV_DEBUG "!", ldp->debug);
Florin Coras99368312018-08-02 10:45:44 -0700214 }
215 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500216
Florin Coras99368312018-08-02 10:45:44 -0700217 env_var_str = getenv (LDP_ENV_APP_NAME);
218 if (env_var_str)
219 {
220 ldp_set_app_name (env_var_str);
Florin Coras05ecfcc2018-12-12 18:19:39 -0800221 LDBG (0, "configured LDP app name (%s) from the env var "
222 LDP_ENV_APP_NAME "!", ldp->app_name);
Florin Coras99368312018-08-02 10:45:44 -0700223 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500224
Florin Coras99368312018-08-02 10:45:44 -0700225 env_var_str = getenv (LDP_ENV_SID_BIT);
226 if (env_var_str)
227 {
228 u32 sb;
229 if (sscanf (env_var_str, "%u", &sb) != 1)
230 {
Florin Coras294afe22019-01-07 17:49:17 -0800231 LDBG (0, "WARNING: Invalid LDP sid bit specified in the env var "
232 LDP_ENV_SID_BIT " (%s)! sid bit value %d (0x%x)", env_var_str,
233 ldp->vlsh_bit_val, ldp->vlsh_bit_val);
Florin Coras99368312018-08-02 10:45:44 -0700234 }
235 else if (sb < LDP_SID_BIT_MIN)
236 {
Florin Coras7baeb712019-01-04 17:05:43 -0800237 ldp->vlsh_bit_val = (1 << LDP_SID_BIT_MIN);
238 ldp->vlsh_bit_mask = ldp->vlsh_bit_val - 1;
Dave Wallace048b1d62018-01-03 22:24:41 -0500239
Florin Coras294afe22019-01-07 17:49:17 -0800240 LDBG (0, "WARNING: LDP sid bit (%u) specified in the env var "
241 LDP_ENV_SID_BIT " (%s) is too small. Using LDP_SID_BIT_MIN"
242 " (%d)! sid bit value %d (0x%x)", sb, env_var_str,
243 LDP_SID_BIT_MIN, ldp->vlsh_bit_val, ldp->vlsh_bit_val);
Florin Coras99368312018-08-02 10:45:44 -0700244 }
245 else if (sb > LDP_SID_BIT_MAX)
246 {
Florin Coras7baeb712019-01-04 17:05:43 -0800247 ldp->vlsh_bit_val = (1 << LDP_SID_BIT_MAX);
248 ldp->vlsh_bit_mask = ldp->vlsh_bit_val - 1;
Dave Wallace048b1d62018-01-03 22:24:41 -0500249
Florin Coras294afe22019-01-07 17:49:17 -0800250 LDBG (0, "WARNING: LDP sid bit (%u) specified in the env var "
251 LDP_ENV_SID_BIT " (%s) is too big. Using LDP_SID_BIT_MAX"
252 " (%d)! sid bit value %d (0x%x)", sb, env_var_str,
253 LDP_SID_BIT_MAX, ldp->vlsh_bit_val, ldp->vlsh_bit_val);
Dave Wallace048b1d62018-01-03 22:24:41 -0500254 }
255 else
256 {
Florin Coras7baeb712019-01-04 17:05:43 -0800257 ldp->vlsh_bit_val = (1 << sb);
258 ldp->vlsh_bit_mask = ldp->vlsh_bit_val - 1;
Florin Coras99368312018-08-02 10:45:44 -0700259
Florin Coras05ecfcc2018-12-12 18:19:39 -0800260 LDBG (0, "configured LDP sid bit (%u) from "
261 LDP_ENV_SID_BIT "! sid bit value %d (0x%x)", sb,
Florin Coras7baeb712019-01-04 17:05:43 -0800262 ldp->vlsh_bit_val, ldp->vlsh_bit_val);
Dave Wallace048b1d62018-01-03 22:24:41 -0500263 }
Florin Coras294afe22019-01-07 17:49:17 -0800264
265 /* Make sure there are enough bits in the fd set for vcl sessions */
266 if (ldp->vlsh_bit_val > FD_SETSIZE / 2)
267 {
268 LDBG (0, "ERROR: LDP vlsh bit value %d > FD_SETSIZE/2 %d!",
269 ldp->vlsh_bit_val, FD_SETSIZE / 2);
270 ldp->init = 0;
271 return -1;
272 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500273 }
Yu Ping7b74b072019-05-08 00:40:24 +0800274 env_var_str = getenv (LDP_ENV_TLS_TRANS);
275 if (env_var_str)
276 {
277 ldp->transparent_tls = 1;
278 }
Florin Coras99368312018-08-02 10:45:44 -0700279
Florin Coras4dee8cd2019-01-29 21:28:16 -0800280 /* *INDENT-OFF* */
281 pool_foreach (ldpw, ldp->workers, ({
282 clib_memset (&ldpw->clib_time, 0, sizeof (ldpw->clib_time));
283 }));
284 /* *INDENT-ON* */
285
Florin Coras05ecfcc2018-12-12 18:19:39 -0800286 LDBG (0, "LDP initialization: done!");
Florin Coras99368312018-08-02 10:45:44 -0700287
288 return 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500289}
290
291int
292close (int fd)
293{
Florin Coras7baeb712019-01-04 17:05:43 -0800294 vls_handle_t vlsh;
295 int rv, epfd;
Dave Wallace048b1d62018-01-03 22:24:41 -0500296
Dave Wallace2a865272018-02-07 21:00:42 -0500297 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500298 return -1;
299
Florin Coras7baeb712019-01-04 17:05:43 -0800300 vlsh = ldp_fd_to_vlsh (fd);
301 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500302 {
Florin Coras7baeb712019-01-04 17:05:43 -0800303 epfd = vls_attr (vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -0500304 if (epfd > 0)
305 {
Florin Coras7baeb712019-01-04 17:05:43 -0800306 LDBG (0, "fd %d: calling libc_close: epfd %u", fd, epfd);
Dave Wallace048b1d62018-01-03 22:24:41 -0500307
308 rv = libc_close (epfd);
309 if (rv < 0)
310 {
311 u32 size = sizeof (epfd);
312 epfd = 0;
313
Florin Coras7baeb712019-01-04 17:05:43 -0800314 (void) vls_attr (vlsh, VPPCOM_ATTR_SET_LIBC_EPFD, &epfd, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -0500315 }
316 }
317 else if (PREDICT_FALSE (epfd < 0))
318 {
319 errno = -epfd;
320 rv = -1;
321 goto done;
322 }
323
Florin Coras7baeb712019-01-04 17:05:43 -0800324 LDBG (0, "fd %d: calling vls_close: vlsh %u", fd, vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -0500325
Florin Coras7baeb712019-01-04 17:05:43 -0800326 rv = vls_close (vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -0500327 if (rv != VPPCOM_OK)
328 {
329 errno = -rv;
330 rv = -1;
331 }
332 }
333 else
334 {
Florin Coras7baeb712019-01-04 17:05:43 -0800335 LDBG (0, "fd %d: calling libc_close", fd);
Dave Wallace048b1d62018-01-03 22:24:41 -0500336 rv = libc_close (fd);
337 }
338
339done:
Dave Wallace048b1d62018-01-03 22:24:41 -0500340 return rv;
341}
342
343ssize_t
344read (int fd, void *buf, size_t nbytes)
345{
Florin Coras7baeb712019-01-04 17:05:43 -0800346 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500347 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -0500348
Dave Wallace2a865272018-02-07 21:00:42 -0500349 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500350 return -1;
351
Florin Coras7baeb712019-01-04 17:05:43 -0800352 vlsh = ldp_fd_to_vlsh (fd);
353 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500354 {
Florin Coras7baeb712019-01-04 17:05:43 -0800355 size = vls_read (vlsh, buf, nbytes);
Dave Wallace048b1d62018-01-03 22:24:41 -0500356 if (size < 0)
357 {
358 errno = -size;
359 size = -1;
360 }
361 }
362 else
363 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500364 size = libc_read (fd, buf, nbytes);
365 }
366
Dave Wallace048b1d62018-01-03 22:24:41 -0500367 return size;
368}
369
370ssize_t
371readv (int fd, const struct iovec * iov, int iovcnt)
372{
Dave Wallace8aaba562018-01-18 17:21:19 -0500373 int rv = 0, i, total = 0;
Florin Coras7baeb712019-01-04 17:05:43 -0800374 vls_handle_t vlsh;
375 ssize_t size = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500376
Dave Wallace2a865272018-02-07 21:00:42 -0500377 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500378 return -1;
379
Florin Coras7baeb712019-01-04 17:05:43 -0800380 vlsh = ldp_fd_to_vlsh (fd);
381 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500382 {
Florin Coras067f9542020-02-14 05:33:46 +0000383 for (i = 0; i < iovcnt; ++i)
Dave Wallace048b1d62018-01-03 22:24:41 -0500384 {
Florin Coras067f9542020-02-14 05:33:46 +0000385 rv = vls_read (vlsh, iov[i].iov_base, iov[i].iov_len);
386 if (rv <= 0)
387 break;
388 else
Dave Wallace048b1d62018-01-03 22:24:41 -0500389 {
Florin Coras067f9542020-02-14 05:33:46 +0000390 total += rv;
391 if (rv < iov[i].iov_len)
Dave Wallace048b1d62018-01-03 22:24:41 -0500392 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700393 }
394 }
Florin Coras067f9542020-02-14 05:33:46 +0000395 if (rv < 0 && total == 0)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700396 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500397 errno = -rv;
398 size = -1;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700399 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500400 else
401 size = total;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700402 }
403 else
404 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500405 size = libc_readv (fd, iov, iovcnt);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700406 }
407
Dave Wallace048b1d62018-01-03 22:24:41 -0500408 return size;
409}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700410
Dave Wallace048b1d62018-01-03 22:24:41 -0500411ssize_t
412write (int fd, const void *buf, size_t nbytes)
413{
Florin Coras7baeb712019-01-04 17:05:43 -0800414 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500415 ssize_t size = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500416
Dave Wallace2a865272018-02-07 21:00:42 -0500417 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500418 return -1;
419
Florin Coras7baeb712019-01-04 17:05:43 -0800420 vlsh = ldp_fd_to_vlsh (fd);
421 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500422 {
Florin Coras7baeb712019-01-04 17:05:43 -0800423 size = vls_write_msg (vlsh, (void *) buf, nbytes);
Dave Wallace048b1d62018-01-03 22:24:41 -0500424 if (size < 0)
425 {
426 errno = -size;
427 size = -1;
428 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700429 }
430 else
431 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500432 size = libc_write (fd, buf, nbytes);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700433 }
434
Dave Wallace048b1d62018-01-03 22:24:41 -0500435 return size;
436}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700437
Dave Wallace048b1d62018-01-03 22:24:41 -0500438ssize_t
439writev (int fd, const struct iovec * iov, int iovcnt)
440{
Dave Wallace048b1d62018-01-03 22:24:41 -0500441 ssize_t size = 0, total = 0;
Florin Coras7baeb712019-01-04 17:05:43 -0800442 vls_handle_t vlsh;
Dave Wallace8aaba562018-01-18 17:21:19 -0500443 int i, rv = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500444
Dave Wallace2a865272018-02-07 21:00:42 -0500445 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500446 return -1;
447
Florin Coras7baeb712019-01-04 17:05:43 -0800448 vlsh = ldp_fd_to_vlsh (fd);
449 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500450 {
Florin Coraseda1b8c2020-03-23 16:00:35 +0000451 for (i = 0; i < iovcnt; ++i)
Dave Wallace048b1d62018-01-03 22:24:41 -0500452 {
Florin Coraseda1b8c2020-03-23 16:00:35 +0000453 rv = vls_write_msg (vlsh, iov[i].iov_base, iov[i].iov_len);
454 if (rv < 0)
455 break;
456 else
Dave Wallace048b1d62018-01-03 22:24:41 -0500457 {
Florin Coraseda1b8c2020-03-23 16:00:35 +0000458 total += rv;
459 if (rv < iov[i].iov_len)
Dave Wallace048b1d62018-01-03 22:24:41 -0500460 break;
Dave Wallace048b1d62018-01-03 22:24:41 -0500461 }
462 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500463
Florin Coraseda1b8c2020-03-23 16:00:35 +0000464 if (rv < 0 && total == 0)
Dave Wallace048b1d62018-01-03 22:24:41 -0500465 {
466 errno = -rv;
467 size = -1;
468 }
469 else
470 size = total;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700471 }
472 else
473 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500474 size = libc_writev (fd, iov, iovcnt);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700475 }
476
Dave Wallace048b1d62018-01-03 22:24:41 -0500477 return size;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700478}
479
Carl Smithe16707b2019-11-13 14:37:39 +1300480#ifdef HAVE_FCNTL64
481int
482fcntl64 (int fd, int cmd, ...)
483#else
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700484int
Dave Wallace048b1d62018-01-03 22:24:41 -0500485fcntl (int fd, int cmd, ...)
Carl Smithe16707b2019-11-13 14:37:39 +1300486#endif
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 {
Carl Smithe16707b2019-11-13 14:37:39 +1300534#ifdef HAVE_FCNTL64
535 rv = libc_vfcntl64 (fd, cmd, ap);
536#else
Dave Wallace048b1d62018-01-03 22:24:41 -0500537 rv = libc_vfcntl (fd, cmd, ap);
Carl Smithe16707b2019-11-13 14:37:39 +1300538#endif
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700539 }
540
Dave Wallace048b1d62018-01-03 22:24:41 -0500541 va_end (ap);
542
Dave Wallace048b1d62018-01-03 22:24:41 -0500543 return rv;
544}
545
546int
547ioctl (int fd, unsigned long int cmd, ...)
548{
Florin Coras7baeb712019-01-04 17:05:43 -0800549 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500550 va_list ap;
Florin Coras7baeb712019-01-04 17:05:43 -0800551 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -0500552
Dave Wallace2a865272018-02-07 21:00:42 -0500553 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500554 return -1;
555
556 va_start (ap, cmd);
Dave Wallace048b1d62018-01-03 22:24:41 -0500557
Florin Coras7baeb712019-01-04 17:05:43 -0800558 vlsh = ldp_fd_to_vlsh (fd);
559 if (vlsh != VLS_INVALID_HANDLE)
560 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500561 switch (cmd)
562 {
563 case FIONREAD:
Florin Coras7baeb712019-01-04 17:05:43 -0800564 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_NREAD, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -0500565 break;
566
567 case FIONBIO:
568 {
569 u32 flags = va_arg (ap, int) ? O_NONBLOCK : 0;
570 u32 size = sizeof (flags);
571
572 /* TBD: When VPPCOM_ATTR_[GS]ET_FLAGS supports flags other than
573 * non-blocking, the flags should be read here and merged
574 * with O_NONBLOCK.
575 */
Florin Coras7baeb712019-01-04 17:05:43 -0800576 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_FLAGS, &flags, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -0500577 }
578 break;
579
580 default:
581 rv = -EOPNOTSUPP;
582 break;
583 }
584 if (rv < 0)
585 {
586 errno = -rv;
587 rv = -1;
588 }
589 }
590 else
591 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500592 rv = libc_vioctl (fd, cmd, ap);
593 }
594
Dave Wallace048b1d62018-01-03 22:24:41 -0500595 va_end (ap);
596 return rv;
597}
598
Florin Coras294afe22019-01-07 17:49:17 -0800599always_inline void
600ldp_select_init_maps (fd_set * __restrict original,
601 clib_bitmap_t ** resultb, clib_bitmap_t ** libcb,
602 clib_bitmap_t ** vclb, int nfds, u32 minbits,
603 u32 n_bytes, uword * si_bits, uword * libc_bits)
604{
605 uword si_bits_set, libc_bits_set;
606 vls_handle_t vlsh;
607 int fd;
608
609 clib_bitmap_validate (*vclb, minbits);
610 clib_bitmap_validate (*libcb, minbits);
611 clib_bitmap_validate (*resultb, minbits);
612 clib_memcpy_fast (*resultb, original, n_bytes);
613 memset (original, 0, n_bytes);
614
615 /* *INDENT-OFF* */
616 clib_bitmap_foreach (fd, *resultb, ({
617 if (fd > nfds)
618 break;
619 vlsh = ldp_fd_to_vlsh (fd);
620 if (vlsh == VLS_INVALID_HANDLE)
621 clib_bitmap_set_no_check (*libcb, fd, 1);
622 else
623 clib_bitmap_set_no_check (*vclb, vlsh_to_session_index (vlsh), 1);
624 }));
625 /* *INDENT-ON* */
626
627 si_bits_set = clib_bitmap_last_set (*vclb) + 1;
628 *si_bits = (si_bits_set > *si_bits) ? si_bits_set : *si_bits;
629
630 libc_bits_set = clib_bitmap_last_set (*libcb) + 1;
631 *libc_bits = (libc_bits_set > *libc_bits) ? libc_bits_set : *libc_bits;
632}
633
634always_inline int
635ldp_select_vcl_map_to_libc (clib_bitmap_t * vclb, fd_set * __restrict libcb)
636{
637 vls_handle_t vlsh;
638 uword si;
639 int fd;
640
641 if (!libcb)
642 return 0;
643
644 /* *INDENT-OFF* */
645 clib_bitmap_foreach (si, vclb, ({
646 vlsh = vls_session_index_to_vlsh (si);
Florin Coras54140622020-02-04 19:04:34 +0000647 ASSERT (vlsh != VLS_INVALID_HANDLE);
Florin Coras294afe22019-01-07 17:49:17 -0800648 fd = ldp_vlsh_to_fd (vlsh);
649 if (PREDICT_FALSE (fd < 0))
650 {
651 errno = EBADFD;
652 return -1;
653 }
654 FD_SET (fd, libcb);
655 }));
656 /* *INDENT-ON* */
657
658 return 0;
659}
660
661always_inline void
662ldp_select_libc_map_merge (clib_bitmap_t * result, fd_set * __restrict libcb)
663{
664 uword fd;
665
Florin Coras78b5fa62019-02-21 20:04:15 -0800666 if (!libcb)
667 return;
668
Florin Coras294afe22019-01-07 17:49:17 -0800669 /* *INDENT-OFF* */
670 clib_bitmap_foreach (fd, result, ({
671 FD_SET ((int)fd, libcb);
672 }));
673 /* *INDENT-ON* */
674}
675
Dave Wallace048b1d62018-01-03 22:24:41 -0500676int
Dave Wallace2a865272018-02-07 21:00:42 -0500677ldp_pselect (int nfds, fd_set * __restrict readfds,
678 fd_set * __restrict writefds,
679 fd_set * __restrict exceptfds,
680 const struct timespec *__restrict timeout,
681 const __sigset_t * __restrict sigmask)
Dave Wallace048b1d62018-01-03 22:24:41 -0500682{
Florin Coras294afe22019-01-07 17:49:17 -0800683 u32 minbits = clib_max (nfds, BITS (uword)), n_bytes;
Florin Corasdfe4cf42018-11-28 22:13:45 -0800684 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras294afe22019-01-07 17:49:17 -0800685 struct timespec libc_tspec = { 0 };
686 f64 time_out, vcl_timeout = 0;
687 uword si_bits, libc_bits;
688 int rv, bits_set = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500689
690 if (nfds < 0)
691 {
692 errno = EINVAL;
693 return -1;
694 }
695
Florin Coras4dee8cd2019-01-29 21:28:16 -0800696 if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
697 clib_time_init (&ldpw->clib_time);
698
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500699 if (timeout)
700 {
701 time_out = (timeout->tv_sec == 0 && timeout->tv_nsec == 0) ?
Florin Coras7baeb712019-01-04 17:05:43 -0800702 (f64) 0 : (f64) timeout->tv_sec + (f64) timeout->tv_nsec / (f64) 1e9;
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500703
704 /* select as fine grained sleep */
705 if (!nfds)
706 {
Florin Corasdfe4cf42018-11-28 22:13:45 -0800707 time_out += clib_time_now (&ldpw->clib_time);
708 while (clib_time_now (&ldpw->clib_time) < time_out)
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500709 ;
710 return 0;
711 }
712 }
713 else if (!nfds)
714 {
715 errno = EINVAL;
716 return -1;
717 }
718 else
719 time_out = -1;
720
Florin Coras7baeb712019-01-04 17:05:43 -0800721 if (nfds <= ldp->vlsh_bit_val)
Dave Wallace048b1d62018-01-03 22:24:41 -0500722 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500723 rv = libc_pselect (nfds, readfds, writefds, exceptfds,
724 timeout, sigmask);
725 goto done;
726 }
727
Florin Coras294afe22019-01-07 17:49:17 -0800728 si_bits = libc_bits = 0;
729 n_bytes = nfds / 8 + ((nfds % 8) ? 1 : 0);
Florin Coras7baeb712019-01-04 17:05:43 -0800730
Dave Wallace048b1d62018-01-03 22:24:41 -0500731 if (readfds)
Florin Coras294afe22019-01-07 17:49:17 -0800732 ldp_select_init_maps (readfds, &ldpw->rd_bitmap, &ldpw->libc_rd_bitmap,
733 &ldpw->si_rd_bitmap, nfds, minbits, n_bytes,
734 &si_bits, &libc_bits);
Dave Wallace048b1d62018-01-03 22:24:41 -0500735 if (writefds)
Florin Coras294afe22019-01-07 17:49:17 -0800736 ldp_select_init_maps (writefds, &ldpw->wr_bitmap,
737 &ldpw->libc_wr_bitmap, &ldpw->si_wr_bitmap, nfds,
738 minbits, n_bytes, &si_bits, &libc_bits);
Dave Wallace048b1d62018-01-03 22:24:41 -0500739 if (exceptfds)
Florin Coras294afe22019-01-07 17:49:17 -0800740 ldp_select_init_maps (exceptfds, &ldpw->ex_bitmap,
741 &ldpw->libc_ex_bitmap, &ldpw->si_ex_bitmap, nfds,
742 minbits, n_bytes, &si_bits, &libc_bits);
Dave Wallace048b1d62018-01-03 22:24:41 -0500743
Florin Coras294afe22019-01-07 17:49:17 -0800744 if (PREDICT_FALSE (!si_bits && !libc_bits))
Dave Wallace048b1d62018-01-03 22:24:41 -0500745 {
746 errno = EINVAL;
747 rv = -1;
748 goto done;
749 }
750
Florin Coras78b5fa62019-02-21 20:04:15 -0800751 if (!si_bits)
752 libc_tspec = timeout ? *timeout : libc_tspec;
Florin Coras294afe22019-01-07 17:49:17 -0800753
Dave Wallace048b1d62018-01-03 22:24:41 -0500754 do
755 {
Florin Coras294afe22019-01-07 17:49:17 -0800756 if (si_bits)
Dave Wallace048b1d62018-01-03 22:24:41 -0500757 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500758 if (readfds)
Florin Coras294afe22019-01-07 17:49:17 -0800759 clib_memcpy_fast (ldpw->rd_bitmap, ldpw->si_rd_bitmap,
Florin Corasdfe4cf42018-11-28 22:13:45 -0800760 vec_len (ldpw->rd_bitmap) *
Dave Barach178cf492018-11-13 16:34:13 -0500761 sizeof (clib_bitmap_t));
Dave Wallace048b1d62018-01-03 22:24:41 -0500762 if (writefds)
Florin Coras294afe22019-01-07 17:49:17 -0800763 clib_memcpy_fast (ldpw->wr_bitmap, ldpw->si_wr_bitmap,
Florin Corasdfe4cf42018-11-28 22:13:45 -0800764 vec_len (ldpw->wr_bitmap) *
Dave Barach178cf492018-11-13 16:34:13 -0500765 sizeof (clib_bitmap_t));
Dave Wallace048b1d62018-01-03 22:24:41 -0500766 if (exceptfds)
Florin Coras294afe22019-01-07 17:49:17 -0800767 clib_memcpy_fast (ldpw->ex_bitmap, ldpw->si_ex_bitmap,
Florin Corasdfe4cf42018-11-28 22:13:45 -0800768 vec_len (ldpw->ex_bitmap) *
Dave Barach178cf492018-11-13 16:34:13 -0500769 sizeof (clib_bitmap_t));
Florin Coras294afe22019-01-07 17:49:17 -0800770
Florin Coras0ef8ef22019-01-18 08:37:13 -0800771 rv = vls_select (si_bits, readfds ? ldpw->rd_bitmap : NULL,
772 writefds ? ldpw->wr_bitmap : NULL,
773 exceptfds ? ldpw->ex_bitmap : NULL, vcl_timeout);
Florin Coras294afe22019-01-07 17:49:17 -0800774 if (rv < 0)
775 {
776 errno = -rv;
777 rv = -1;
778 }
779 else if (rv > 0)
780 {
781 if (ldp_select_vcl_map_to_libc (ldpw->rd_bitmap, readfds))
782 {
783 rv = -1;
784 goto done;
785 }
786
787 if (ldp_select_vcl_map_to_libc (ldpw->wr_bitmap, writefds))
788 {
789 rv = -1;
790 goto done;
791 }
792
793 if (ldp_select_vcl_map_to_libc (ldpw->ex_bitmap, exceptfds))
794 {
795 rv = -1;
796 goto done;
797 }
798 bits_set = rv;
799 }
800 }
801 if (libc_bits)
802 {
803 if (readfds)
804 clib_memcpy_fast (ldpw->rd_bitmap, ldpw->libc_rd_bitmap,
805 vec_len (ldpw->libc_rd_bitmap) *
806 sizeof (clib_bitmap_t));
807 if (writefds)
808 clib_memcpy_fast (ldpw->wr_bitmap, ldpw->libc_wr_bitmap,
809 vec_len (ldpw->libc_wr_bitmap) *
810 sizeof (clib_bitmap_t));
811 if (exceptfds)
812 clib_memcpy_fast (ldpw->ex_bitmap, ldpw->libc_ex_bitmap,
813 vec_len (ldpw->libc_ex_bitmap) *
814 sizeof (clib_bitmap_t));
815
Dave Wallace048b1d62018-01-03 22:24:41 -0500816 rv = libc_pselect (libc_bits,
Florin Coras294afe22019-01-07 17:49:17 -0800817 readfds ? (fd_set *) ldpw->rd_bitmap : NULL,
818 writefds ? (fd_set *) ldpw->wr_bitmap : NULL,
819 exceptfds ? (fd_set *) ldpw->ex_bitmap : NULL,
820 &libc_tspec, sigmask);
821 if (rv > 0)
822 {
823 ldp_select_libc_map_merge (ldpw->rd_bitmap, readfds);
824 ldp_select_libc_map_merge (ldpw->wr_bitmap, writefds);
825 ldp_select_libc_map_merge (ldpw->ex_bitmap, exceptfds);
826 bits_set += rv;
827 }
828 }
829
830 if (bits_set)
831 {
832 rv = bits_set;
833 goto done;
Dave Wallace048b1d62018-01-03 22:24:41 -0500834 }
835 }
Florin Corasdfe4cf42018-11-28 22:13:45 -0800836 while ((time_out == -1) || (clib_time_now (&ldpw->clib_time) < time_out));
Dave Wallace048b1d62018-01-03 22:24:41 -0500837 rv = 0;
838
839done:
840 /* TBD: set timeout to amount of time left */
Florin Corasdfe4cf42018-11-28 22:13:45 -0800841 clib_bitmap_zero (ldpw->rd_bitmap);
Florin Coras294afe22019-01-07 17:49:17 -0800842 clib_bitmap_zero (ldpw->si_rd_bitmap);
Florin Corasdfe4cf42018-11-28 22:13:45 -0800843 clib_bitmap_zero (ldpw->libc_rd_bitmap);
844 clib_bitmap_zero (ldpw->wr_bitmap);
Florin Coras294afe22019-01-07 17:49:17 -0800845 clib_bitmap_zero (ldpw->si_wr_bitmap);
Florin Corasdfe4cf42018-11-28 22:13:45 -0800846 clib_bitmap_zero (ldpw->libc_wr_bitmap);
847 clib_bitmap_zero (ldpw->ex_bitmap);
Florin Coras294afe22019-01-07 17:49:17 -0800848 clib_bitmap_zero (ldpw->si_ex_bitmap);
Florin Corasdfe4cf42018-11-28 22:13:45 -0800849 clib_bitmap_zero (ldpw->libc_ex_bitmap);
Dave Wallace048b1d62018-01-03 22:24:41 -0500850
Dave Wallace048b1d62018-01-03 22:24:41 -0500851 return rv;
852}
853
854int
855select (int nfds, fd_set * __restrict readfds,
856 fd_set * __restrict writefds,
857 fd_set * __restrict exceptfds, struct timeval *__restrict timeout)
858{
859 struct timespec tspec;
860
861 if (timeout)
862 {
863 tspec.tv_sec = timeout->tv_sec;
864 tspec.tv_nsec = timeout->tv_usec * 1000;
865 }
Dave Wallace2a865272018-02-07 21:00:42 -0500866 return ldp_pselect (nfds, readfds, writefds, exceptfds,
867 timeout ? &tspec : NULL, NULL);
Dave Wallace048b1d62018-01-03 22:24:41 -0500868}
869
870#ifdef __USE_XOPEN2K
871int
872pselect (int nfds, fd_set * __restrict readfds,
873 fd_set * __restrict writefds,
874 fd_set * __restrict exceptfds,
875 const struct timespec *__restrict timeout,
876 const __sigset_t * __restrict sigmask)
877{
Dave Wallace2a865272018-02-07 21:00:42 -0500878 return ldp_pselect (nfds, readfds, writefds, exceptfds, timeout, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -0500879}
880#endif
881
Yu Ping7b74b072019-05-08 00:40:24 +0800882/* If transparent TLS mode is turned on, then ldp will load key and cert.
883 */
884static int
885load_tls_cert (vls_handle_t vlsh)
886{
887 char *env_var_str = getenv (LDP_ENV_TLS_CERT);
888 char inbuf[4096];
889 char *tls_cert;
890 int cert_size;
891 FILE *fp;
892
893 if (env_var_str)
894 {
895 fp = fopen (env_var_str, "r");
896 if (fp == NULL)
897 {
898 LDBG (0, "ERROR: failed to open cert file %s \n", env_var_str);
899 return -1;
900 }
901 cert_size = fread (inbuf, sizeof (char), sizeof (inbuf), fp);
902 tls_cert = inbuf;
903 vppcom_session_tls_add_cert (vlsh_to_session_index (vlsh), tls_cert,
904 cert_size);
905 fclose (fp);
906 }
907 else
908 {
909 LDBG (0, "ERROR: failed to read LDP environment %s\n",
910 LDP_ENV_TLS_CERT);
911 return -1;
912 }
913 return 0;
914}
915
916static int
917load_tls_key (vls_handle_t vlsh)
918{
919 char *env_var_str = getenv (LDP_ENV_TLS_KEY);
920 char inbuf[4096];
921 char *tls_key;
922 int key_size;
923 FILE *fp;
924
925 if (env_var_str)
926 {
927 fp = fopen (env_var_str, "r");
928 if (fp == NULL)
929 {
930 LDBG (0, "ERROR: failed to open key file %s \n", env_var_str);
931 return -1;
932 }
933 key_size = fread (inbuf, sizeof (char), sizeof (inbuf), fp);
934 tls_key = inbuf;
935 vppcom_session_tls_add_key (vlsh_to_session_index (vlsh), tls_key,
936 key_size);
937 fclose (fp);
938 }
939 else
940 {
941 LDBG (0, "ERROR: failed to read LDP environment %s\n", LDP_ENV_TLS_KEY);
942 return -1;
943 }
944 return 0;
945}
946
Dave Wallace048b1d62018-01-03 22:24:41 -0500947int
948socket (int domain, int type, int protocol)
949{
Florin Coras7baeb712019-01-04 17:05:43 -0800950 int rv, sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
Dave Wallace048b1d62018-01-03 22:24:41 -0500951 u8 is_nonblocking = type & SOCK_NONBLOCK ? 1 : 0;
Florin Coras7baeb712019-01-04 17:05:43 -0800952 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500953
Dave Wallace2a865272018-02-07 21:00:42 -0500954 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500955 return -1;
956
957 if (((domain == AF_INET) || (domain == AF_INET6)) &&
958 ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM)))
959 {
Yu Ping7b74b072019-05-08 00:40:24 +0800960 u8 proto;
961 if (ldp->transparent_tls)
962 {
963 proto = VPPCOM_PROTO_TLS;
964 }
965 else
966 proto = ((sock_type == SOCK_DGRAM) ?
967 VPPCOM_PROTO_UDP : VPPCOM_PROTO_TCP);
Dave Wallace048b1d62018-01-03 22:24:41 -0500968
Florin Coras7baeb712019-01-04 17:05:43 -0800969 LDBG (0, "calling vls_create: proto %u (%s), is_nonblocking %u",
970 proto, vppcom_proto_str (proto), is_nonblocking);
Dave Wallace048b1d62018-01-03 22:24:41 -0500971
Florin Coras7baeb712019-01-04 17:05:43 -0800972 vlsh = vls_create (proto, is_nonblocking);
973 if (vlsh < 0)
Dave Wallace048b1d62018-01-03 22:24:41 -0500974 {
Florin Coras7baeb712019-01-04 17:05:43 -0800975 errno = -vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500976 rv = -1;
977 }
978 else
979 {
Yu Ping7b74b072019-05-08 00:40:24 +0800980 if (ldp->transparent_tls)
981 {
982 if (load_tls_cert (vlsh) < 0 || load_tls_key (vlsh) < 0)
983 {
984 return -1;
985 }
986 }
Florin Coras7baeb712019-01-04 17:05:43 -0800987 rv = ldp_vlsh_to_fd (vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -0500988 }
989 }
990 else
991 {
Florin Coras7baeb712019-01-04 17:05:43 -0800992 LDBG (0, "calling libc_socket");
Dave Wallace048b1d62018-01-03 22:24:41 -0500993 rv = libc_socket (domain, type, protocol);
994 }
995
Dave Wallace048b1d62018-01-03 22:24:41 -0500996 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700997}
998
999/*
1000 * Create two new sockets, of type TYPE in domain DOMAIN and using
1001 * protocol PROTOCOL, which are connected to each other, and put file
1002 * descriptors for them in FDS[0] and FDS[1]. If PROTOCOL is zero,
1003 * one will be chosen automatically.
1004 * Returns 0 on success, -1 for errors.
1005 * */
1006int
Dave Wallace048b1d62018-01-03 22:24:41 -05001007socketpair (int domain, int type, int protocol, int fds[2])
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001008{
Florin Coras7baeb712019-01-04 17:05:43 -08001009 int rv, sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
Dave Wallace048b1d62018-01-03 22:24:41 -05001010
Dave Wallace2a865272018-02-07 21:00:42 -05001011 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001012 return -1;
1013
1014 if (((domain == AF_INET) || (domain == AF_INET6)) &&
1015 ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM)))
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001016 {
Florin Coras7baeb712019-01-04 17:05:43 -08001017 LDBG (0, "LDP-TBD");
Dave Wallace048b1d62018-01-03 22:24:41 -05001018 errno = ENOSYS;
1019 rv = -1;
1020 }
1021 else
1022 {
Florin Coras7baeb712019-01-04 17:05:43 -08001023 LDBG (1, "calling libc_socketpair");
Florin Coras173bae32018-11-16 18:56:28 -08001024 rv = libc_socketpair (domain, type, protocol, fds);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001025 }
1026
Dave Wallace048b1d62018-01-03 22:24:41 -05001027 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001028}
1029
1030int
Dave Wallace048b1d62018-01-03 22:24:41 -05001031bind (int fd, __CONST_SOCKADDR_ARG addr, socklen_t len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001032{
Florin Coras7baeb712019-01-04 17:05:43 -08001033 vls_handle_t vlsh;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001034 int rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001035
Dave Wallace2a865272018-02-07 21:00:42 -05001036 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001037 return -1;
1038
Florin Coras7baeb712019-01-04 17:05:43 -08001039 vlsh = ldp_fd_to_vlsh (fd);
1040 if (vlsh != VLS_INVALID_HANDLE)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001041 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001042 vppcom_endpt_t ep;
1043
Dave Wallace048b1d62018-01-03 22:24:41 -05001044 switch (addr->sa_family)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001045 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001046 case AF_INET:
1047 if (len != sizeof (struct sockaddr_in))
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001048 {
Florin Coras7baeb712019-01-04 17:05:43 -08001049 LDBG (0, "ERROR: fd %d: vlsh %u: Invalid AF_INET addr len %u!",
1050 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001051 errno = EINVAL;
1052 rv = -1;
1053 goto done;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001054 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001055 ep.is_ip4 = VPPCOM_IS_IP4;
1056 ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr;
1057 ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port;
1058 break;
1059
1060 case AF_INET6:
1061 if (len != sizeof (struct sockaddr_in6))
1062 {
Florin Coras7baeb712019-01-04 17:05:43 -08001063 LDBG (0, "ERROR: fd %d: vlsh %u: Invalid AF_INET6 addr len %u!",
1064 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001065 errno = EINVAL;
1066 rv = -1;
1067 goto done;
1068 }
1069 ep.is_ip4 = VPPCOM_IS_IP6;
1070 ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
1071 ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001072 break;
1073
1074 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001075 LDBG (0, "ERROR: fd %d: vlsh %u: Unsupported address family %u!",
1076 fd, vlsh, addr->sa_family);
Dave Wallace048b1d62018-01-03 22:24:41 -05001077 errno = EAFNOSUPPORT;
1078 rv = -1;
1079 goto done;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001080 }
Florin Coras7baeb712019-01-04 17:05:43 -08001081 LDBG (0, "fd %d: calling vls_bind: vlsh %u, addr %p, len %u", fd, vlsh,
1082 addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001083
Florin Coras7baeb712019-01-04 17:05:43 -08001084 rv = vls_bind (vlsh, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001085 if (rv != VPPCOM_OK)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001086 {
1087 errno = -rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001088 rv = -1;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001089 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001090 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001091 else
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001092 {
Florin Coras7baeb712019-01-04 17:05:43 -08001093 LDBG (0, "fd %d: calling libc_bind: addr %p, len %u", fd, addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001094 rv = libc_bind (fd, addr, len);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001095 }
1096
Dave Wallace048b1d62018-01-03 22:24:41 -05001097done:
Florin Coras7baeb712019-01-04 17:05:43 -08001098 LDBG (1, "fd %d: returning %d", fd, rv);
Florin Coras05ecfcc2018-12-12 18:19:39 -08001099
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001100 return rv;
1101}
1102
1103static inline int
Dave Wallace2a865272018-02-07 21:00:42 -05001104ldp_copy_ep_to_sockaddr (__SOCKADDR_ARG addr, socklen_t * __restrict len,
1105 vppcom_endpt_t * ep)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001106{
Dave Wallace048b1d62018-01-03 22:24:41 -05001107 int rv = 0;
1108 int sa_len, copy_len;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001109
Dave Wallace2a865272018-02-07 21:00:42 -05001110 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001111 return -1;
1112
1113 if (addr && len && ep)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001114 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001115 addr->sa_family = (ep->is_ip4 == VPPCOM_IS_IP4) ? AF_INET : AF_INET6;
1116 switch (addr->sa_family)
1117 {
1118 case AF_INET:
1119 ((struct sockaddr_in *) addr)->sin_port = ep->port;
1120 if (*len > sizeof (struct sockaddr_in))
1121 *len = sizeof (struct sockaddr_in);
1122 sa_len = sizeof (struct sockaddr_in) - sizeof (struct in_addr);
1123 copy_len = *len - sa_len;
1124 if (copy_len > 0)
1125 memcpy (&((struct sockaddr_in *) addr)->sin_addr, ep->ip,
1126 copy_len);
1127 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001128
Dave Wallace048b1d62018-01-03 22:24:41 -05001129 case AF_INET6:
1130 ((struct sockaddr_in6 *) addr)->sin6_port = ep->port;
1131 if (*len > sizeof (struct sockaddr_in6))
1132 *len = sizeof (struct sockaddr_in6);
1133 sa_len = sizeof (struct sockaddr_in6) - sizeof (struct in6_addr);
1134 copy_len = *len - sa_len;
1135 if (copy_len > 0)
1136 memcpy (((struct sockaddr_in6 *) addr)->sin6_addr.
1137 __in6_u.__u6_addr8, ep->ip, copy_len);
1138 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001139
Dave Wallace048b1d62018-01-03 22:24:41 -05001140 default:
1141 /* Not possible */
1142 rv = -EAFNOSUPPORT;
1143 break;
1144 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001145 }
Dave Wallacee695cb42017-11-02 22:04:42 -04001146 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001147}
1148
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001149int
Dave Wallace048b1d62018-01-03 22:24:41 -05001150getsockname (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001151{
Florin Coras7baeb712019-01-04 17:05:43 -08001152 vls_handle_t vlsh;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001153 int rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001154
Dave Wallace2a865272018-02-07 21:00:42 -05001155 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001156 return -1;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001157
Florin Coras7baeb712019-01-04 17:05:43 -08001158 vlsh = ldp_fd_to_vlsh (fd);
1159 if (vlsh != VLS_INVALID_HANDLE)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001160 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001161 vppcom_endpt_t ep;
1162 u8 addr_buf[sizeof (struct in6_addr)];
1163 u32 size = sizeof (ep);
1164
1165 ep.ip = addr_buf;
Dave Wallace048b1d62018-01-03 22:24:41 -05001166
Florin Coras7baeb712019-01-04 17:05:43 -08001167 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_LCL_ADDR, &ep, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -05001168 if (rv != VPPCOM_OK)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001169 {
1170 errno = -rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001171 rv = -1;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001172 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001173 else
1174 {
Dave Wallace2a865272018-02-07 21:00:42 -05001175 rv = ldp_copy_ep_to_sockaddr (addr, len, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001176 if (rv != VPPCOM_OK)
1177 {
1178 errno = -rv;
1179 rv = -1;
1180 }
1181 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001182 }
1183 else
1184 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001185 rv = libc_getsockname (fd, addr, len);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001186 }
1187
Dave Wallace048b1d62018-01-03 22:24:41 -05001188 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001189}
1190
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001191int
Dave Wallace048b1d62018-01-03 22:24:41 -05001192connect (int fd, __CONST_SOCKADDR_ARG addr, socklen_t len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001193{
Florin Coras7baeb712019-01-04 17:05:43 -08001194 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001195 int rv;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001196
Dave Wallace2a865272018-02-07 21:00:42 -05001197 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001198 return -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001199
Dave Wallace048b1d62018-01-03 22:24:41 -05001200 if (!addr)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001201 {
Florin Coras7baeb712019-01-04 17:05:43 -08001202 LDBG (0, "ERROR: fd %d: NULL addr, len %u", fd, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001203 errno = EINVAL;
1204 rv = -1;
1205 goto done;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001206 }
1207
Florin Coras7baeb712019-01-04 17:05:43 -08001208 vlsh = ldp_fd_to_vlsh (fd);
1209 if (vlsh != VLS_INVALID_HANDLE)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001210 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001211 vppcom_endpt_t ep;
1212
Dave Wallace048b1d62018-01-03 22:24:41 -05001213 switch (addr->sa_family)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001214 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001215 case AF_INET:
1216 if (len != sizeof (struct sockaddr_in))
1217 {
Florin Coras7baeb712019-01-04 17:05:43 -08001218 LDBG (0, "fd %d: ERROR vlsh %u: Invalid AF_INET addr len %u!",
1219 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001220 errno = EINVAL;
1221 rv = -1;
1222 goto done;
1223 }
1224 ep.is_ip4 = VPPCOM_IS_IP4;
1225 ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr;
1226 ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port;
1227 break;
1228
1229 case AF_INET6:
1230 if (len != sizeof (struct sockaddr_in6))
1231 {
Florin Coras7baeb712019-01-04 17:05:43 -08001232 LDBG (0, "fd %d: ERROR vlsh %u: Invalid AF_INET6 addr len %u!",
1233 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001234 errno = EINVAL;
1235 rv = -1;
1236 goto done;
1237 }
1238 ep.is_ip4 = VPPCOM_IS_IP6;
1239 ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
1240 ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port;
1241 break;
1242
1243 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001244 LDBG (0, "fd %d: ERROR vlsh %u: Unsupported address family %u!",
1245 fd, vlsh, addr->sa_family);
Dave Wallace048b1d62018-01-03 22:24:41 -05001246 errno = EAFNOSUPPORT;
1247 rv = -1;
1248 goto done;
1249 }
Florin Coras7baeb712019-01-04 17:05:43 -08001250 LDBG (0, "fd %d: calling vls_connect(): vlsh %u addr %p len %u", fd,
1251 vlsh, addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001252
Florin Coras7baeb712019-01-04 17:05:43 -08001253 rv = vls_connect (vlsh, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001254 if (rv != VPPCOM_OK)
1255 {
1256 errno = -rv;
1257 rv = -1;
1258 }
1259 }
1260 else
1261 {
Florin Coras7baeb712019-01-04 17:05:43 -08001262 LDBG (0, "fd %d: calling libc_connect(): addr %p, len %u",
1263 fd, addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001264
1265 rv = libc_connect (fd, addr, len);
1266 }
1267
1268done:
Florin Coras7baeb712019-01-04 17:05:43 -08001269 LDBG (1, "fd %d: returning %d (0x%x)", fd, rv, rv);
Dave Wallace048b1d62018-01-03 22:24:41 -05001270 return rv;
1271}
1272
1273int
1274getpeername (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict len)
1275{
Florin Coras7baeb712019-01-04 17:05:43 -08001276 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001277 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001278
Dave Wallace2a865272018-02-07 21:00:42 -05001279 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001280 return -1;
1281
Florin Coras7baeb712019-01-04 17:05:43 -08001282 vlsh = ldp_fd_to_vlsh (fd);
1283 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001284 {
1285 vppcom_endpt_t ep;
1286 u8 addr_buf[sizeof (struct in6_addr)];
1287 u32 size = sizeof (ep);
1288
1289 ep.ip = addr_buf;
Florin Coras7baeb712019-01-04 17:05:43 -08001290 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_PEER_ADDR, &ep, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -05001291 if (rv != VPPCOM_OK)
1292 {
1293 errno = -rv;
1294 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001295 }
1296 else
1297 {
Dave Wallace2a865272018-02-07 21:00:42 -05001298 rv = ldp_copy_ep_to_sockaddr (addr, len, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001299 if (rv != VPPCOM_OK)
1300 {
1301 errno = -rv;
1302 rv = -1;
1303 }
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001304 }
1305 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001306 else
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001307 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001308 rv = libc_getpeername (fd, addr, len);
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001309 }
1310
Dave Wallace048b1d62018-01-03 22:24:41 -05001311 return rv;
1312}
1313
1314ssize_t
1315send (int fd, const void *buf, size_t n, int flags)
1316{
Florin Coras7baeb712019-01-04 17:05:43 -08001317 vls_handle_t vlsh = ldp_fd_to_vlsh (fd);
Dave Wallace048b1d62018-01-03 22:24:41 -05001318 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001319
Dave Wallace2a865272018-02-07 21:00:42 -05001320 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001321 return -1;
1322
Florin Coras7baeb712019-01-04 17:05:43 -08001323 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001324 {
Florin Coras7baeb712019-01-04 17:05:43 -08001325 size = vls_sendto (vlsh, (void *) buf, n, flags, NULL);
qchangaa8f63c2018-05-30 11:44:18 -07001326 if (size < VPPCOM_OK)
Dave Wallace048b1d62018-01-03 22:24:41 -05001327 {
1328 errno = -size;
1329 size = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001330 }
1331 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001332 else
1333 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001334 size = libc_send (fd, buf, n, flags);
1335 }
1336
Dave Wallace048b1d62018-01-03 22:24:41 -05001337 return size;
1338}
1339
1340ssize_t
1341sendfile (int out_fd, int in_fd, off_t * offset, size_t len)
1342{
Florin Corasdfe4cf42018-11-28 22:13:45 -08001343 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras7baeb712019-01-04 17:05:43 -08001344 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001345 ssize_t size = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -05001346
Dave Wallace2a865272018-02-07 21:00:42 -05001347 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001348 return -1;
1349
Florin Coras7baeb712019-01-04 17:05:43 -08001350 vlsh = ldp_fd_to_vlsh (out_fd);
1351 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001352 {
1353 int rv;
1354 ssize_t results = 0;
1355 size_t n_bytes_left = len;
1356 size_t bytes_to_read;
1357 int nbytes;
Dave Wallace048b1d62018-01-03 22:24:41 -05001358 u8 eagain = 0;
1359 u32 flags, flags_len = sizeof (flags);
1360
Florin Coras7baeb712019-01-04 17:05:43 -08001361 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_FLAGS, &flags, &flags_len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001362 if (PREDICT_FALSE (rv != VPPCOM_OK))
1363 {
Florin Coras7baeb712019-01-04 17:05:43 -08001364 LDBG (0, "ERROR: out fd %d: vls_attr: vlsh %u, returned %d (%s)!",
1365 out_fd, vlsh, rv, vppcom_retval_str (rv));
Dave Wallace048b1d62018-01-03 22:24:41 -05001366
Florin Corasdfe4cf42018-11-28 22:13:45 -08001367 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001368 errno = -rv;
1369 size = -1;
1370 goto done;
1371 }
1372
1373 if (offset)
1374 {
1375 off_t off = lseek (in_fd, *offset, SEEK_SET);
1376 if (PREDICT_FALSE (off == -1))
1377 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001378 size = -1;
1379 goto done;
1380 }
1381
1382 ASSERT (off == *offset);
1383 }
1384
1385 do
1386 {
Florin Coras7baeb712019-01-04 17:05:43 -08001387 size = vls_attr (vlsh, VPPCOM_ATTR_GET_NWRITE, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05001388 if (size < 0)
1389 {
Florin Coras7baeb712019-01-04 17:05:43 -08001390 LDBG (0, "ERROR: fd %d: vls_attr: vlsh %u returned %d (%s)!",
1391 out_fd, vlsh, size, vppcom_retval_str (size));
Florin Corasdfe4cf42018-11-28 22:13:45 -08001392 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001393 errno = -size;
1394 size = -1;
1395 goto done;
1396 }
1397
1398 bytes_to_read = size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001399 if (bytes_to_read == 0)
1400 {
1401 if (flags & O_NONBLOCK)
1402 {
1403 if (!results)
Florin Coras7baeb712019-01-04 17:05:43 -08001404 eagain = 1;
Dave Wallace048b1d62018-01-03 22:24:41 -05001405 goto update_offset;
1406 }
1407 else
1408 continue;
1409 }
1410 bytes_to_read = clib_min (n_bytes_left, bytes_to_read);
Florin Corasdfe4cf42018-11-28 22:13:45 -08001411 vec_validate (ldpw->io_buffer, bytes_to_read);
1412 nbytes = libc_read (in_fd, ldpw->io_buffer, bytes_to_read);
Dave Wallace048b1d62018-01-03 22:24:41 -05001413 if (nbytes < 0)
1414 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001415 if (results == 0)
1416 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08001417 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001418 size = -1;
1419 goto done;
1420 }
1421 goto update_offset;
1422 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001423
Florin Coras7baeb712019-01-04 17:05:43 -08001424 size = vls_write (vlsh, ldpw->io_buffer, nbytes);
Dave Wallace048b1d62018-01-03 22:24:41 -05001425 if (size < 0)
1426 {
1427 if (size == VPPCOM_EAGAIN)
1428 {
1429 if (flags & O_NONBLOCK)
1430 {
1431 if (!results)
Florin Coras7baeb712019-01-04 17:05:43 -08001432 eagain = 1;
Dave Wallace048b1d62018-01-03 22:24:41 -05001433 goto update_offset;
1434 }
1435 else
1436 continue;
1437 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001438 if (results == 0)
1439 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08001440 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001441 errno = -size;
1442 size = -1;
1443 goto done;
1444 }
1445 goto update_offset;
1446 }
1447
1448 results += nbytes;
1449 ASSERT (n_bytes_left >= nbytes);
1450 n_bytes_left = n_bytes_left - nbytes;
1451 }
1452 while (n_bytes_left > 0);
1453
1454 update_offset:
Florin Corasdfe4cf42018-11-28 22:13:45 -08001455 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001456 if (offset)
1457 {
1458 off_t off = lseek (in_fd, *offset, SEEK_SET);
1459 if (PREDICT_FALSE (off == -1))
1460 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001461 size = -1;
1462 goto done;
1463 }
1464
1465 ASSERT (off == *offset);
1466 *offset += results + 1;
1467 }
1468 if (eagain)
1469 {
1470 errno = EAGAIN;
1471 size = -1;
1472 }
1473 else
1474 size = results;
1475 }
1476 else
1477 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001478 size = libc_sendfile (out_fd, in_fd, offset, len);
1479 }
1480
1481done:
Dave Wallace048b1d62018-01-03 22:24:41 -05001482 return size;
1483}
1484
1485ssize_t
1486sendfile64 (int out_fd, int in_fd, off_t * offset, size_t len)
1487{
1488 return sendfile (out_fd, in_fd, offset, len);
1489}
1490
1491ssize_t
1492recv (int fd, void *buf, size_t n, int flags)
1493{
Florin Coras7baeb712019-01-04 17:05:43 -08001494 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001495 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001496
Dave Wallace2a865272018-02-07 21:00:42 -05001497 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001498 return -1;
1499
Florin Coras7baeb712019-01-04 17:05:43 -08001500 vlsh = ldp_fd_to_vlsh (fd);
1501 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001502 {
Florin Coras7baeb712019-01-04 17:05:43 -08001503 size = vls_recvfrom (vlsh, buf, n, flags, NULL);
Dave Wallace048b1d62018-01-03 22:24:41 -05001504 if (size < 0)
Florin Coras2a6642e2020-03-24 15:24:29 +00001505 {
1506 errno = -size;
1507 size = -1;
1508 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001509 }
1510 else
1511 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001512 size = libc_recv (fd, buf, n, flags);
1513 }
1514
Dave Wallace048b1d62018-01-03 22:24:41 -05001515 return size;
1516}
1517
1518ssize_t
1519sendto (int fd, const void *buf, size_t n, int flags,
1520 __CONST_SOCKADDR_ARG addr, socklen_t addr_len)
1521{
Florin Coras7baeb712019-01-04 17:05:43 -08001522 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001523 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001524
Dave Wallace2a865272018-02-07 21:00:42 -05001525 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001526 return -1;
1527
Florin Coras7baeb712019-01-04 17:05:43 -08001528 vlsh = ldp_fd_to_vlsh (fd);
1529 if (vlsh != INVALID_SESSION_ID)
Dave Wallace048b1d62018-01-03 22:24:41 -05001530 {
1531 vppcom_endpt_t *ep = 0;
1532 vppcom_endpt_t _ep;
1533
1534 if (addr)
1535 {
1536 ep = &_ep;
Dave Wallace048b1d62018-01-03 22:24:41 -05001537 switch (addr->sa_family)
1538 {
1539 case AF_INET:
1540 ep->is_ip4 = VPPCOM_IS_IP4;
1541 ep->ip =
1542 (uint8_t *) & ((const struct sockaddr_in *) addr)->sin_addr;
1543 ep->port =
1544 (uint16_t) ((const struct sockaddr_in *) addr)->sin_port;
1545 break;
1546
1547 case AF_INET6:
1548 ep->is_ip4 = VPPCOM_IS_IP6;
1549 ep->ip =
1550 (uint8_t *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
1551 ep->port =
1552 (uint16_t) ((const struct sockaddr_in6 *) addr)->sin6_port;
1553 break;
1554
1555 default:
1556 errno = EAFNOSUPPORT;
1557 size = -1;
1558 goto done;
1559 }
1560 }
1561
Florin Coras7baeb712019-01-04 17:05:43 -08001562 size = vls_sendto (vlsh, (void *) buf, n, flags, ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001563 if (size < 0)
1564 {
1565 errno = -size;
1566 size = -1;
1567 }
1568 }
1569 else
1570 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001571 size = libc_sendto (fd, buf, n, flags, addr, addr_len);
1572 }
1573
1574done:
Dave Wallace048b1d62018-01-03 22:24:41 -05001575 return size;
1576}
1577
1578ssize_t
1579recvfrom (int fd, void *__restrict buf, size_t n, int flags,
1580 __SOCKADDR_ARG addr, socklen_t * __restrict addr_len)
1581{
Florin Coras7baeb712019-01-04 17:05:43 -08001582 vls_handle_t sid;
Haggai Eran46ae2ef2019-02-19 15:04:42 +02001583 ssize_t size, rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001584
Dave Wallace2a865272018-02-07 21:00:42 -05001585 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001586 return -1;
1587
Florin Coras7baeb712019-01-04 17:05:43 -08001588 sid = ldp_fd_to_vlsh (fd);
1589 if (sid != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001590 {
1591 vppcom_endpt_t ep;
1592 u8 src_addr[sizeof (struct sockaddr_in6)];
1593
Dave Wallace048b1d62018-01-03 22:24:41 -05001594 if (addr)
1595 {
1596 ep.ip = src_addr;
Florin Coras7baeb712019-01-04 17:05:43 -08001597 size = vls_recvfrom (sid, buf, n, flags, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001598
1599 if (size > 0)
Haggai Eran46ae2ef2019-02-19 15:04:42 +02001600 {
1601 rv = ldp_copy_ep_to_sockaddr (addr, addr_len, &ep);
1602 if (rv < 0)
1603 size = rv;
1604 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001605 }
1606 else
Florin Coras7baeb712019-01-04 17:05:43 -08001607 size = vls_recvfrom (sid, buf, n, flags, NULL);
Dave Wallace048b1d62018-01-03 22:24:41 -05001608
1609 if (size < 0)
1610 {
1611 errno = -size;
1612 size = -1;
1613 }
1614 }
1615 else
1616 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001617 size = libc_recvfrom (fd, buf, n, flags, addr, addr_len);
1618 }
1619
Dave Wallace048b1d62018-01-03 22:24:41 -05001620 return size;
1621}
1622
1623ssize_t
1624sendmsg (int fd, const struct msghdr * message, int flags)
1625{
Florin Coras7baeb712019-01-04 17:05:43 -08001626 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001627 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001628
Dave Wallace2a865272018-02-07 21:00:42 -05001629 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001630 return -1;
1631
Florin Coras7baeb712019-01-04 17:05:43 -08001632 vlsh = ldp_fd_to_vlsh (fd);
1633 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001634 {
Florin Coras7baeb712019-01-04 17:05:43 -08001635 LDBG (0, "LDP-TBD");
Dave Wallace048b1d62018-01-03 22:24:41 -05001636 errno = ENOSYS;
1637 size = -1;
1638 }
1639 else
1640 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001641 size = libc_sendmsg (fd, message, flags);
1642 }
1643
Dave Wallace048b1d62018-01-03 22:24:41 -05001644 return size;
1645}
1646
1647#ifdef USE_GNU
1648int
1649sendmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags)
1650{
1651 ssize_t size;
1652 const char *func_str;
Florin Coras7baeb712019-01-04 17:05:43 -08001653 u32 sh = ldp_fd_to_vlsh (fd);
Dave Wallace048b1d62018-01-03 22:24:41 -05001654
Dave Wallace2a865272018-02-07 21:00:42 -05001655 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001656 return -1;
1657
Florin Coras7baeb712019-01-04 17:05:43 -08001658 if (sh != INVALID_SESSION_ID)
Dave Wallace048b1d62018-01-03 22:24:41 -05001659 {
1660 clib_warning ("LDP<%d>: LDP-TBD", getpid ());
1661 errno = ENOSYS;
1662 size = -1;
1663 }
1664 else
1665 {
1666 func_str = "libc_sendmmsg";
1667
Dave Wallace2a865272018-02-07 21:00:42 -05001668 if (LDP_DEBUG > 2)
Dave Wallace048b1d62018-01-03 22:24:41 -05001669 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1670 "vmessages %p, vlen %u, flags 0x%x",
1671 getpid (), fd, fd, func_str, vmessages, vlen, flags);
1672
1673 size = libc_sendmmsg (fd, vmessages, vlen, flags);
1674 }
1675
Dave Wallace2a865272018-02-07 21:00:42 -05001676 if (LDP_DEBUG > 2)
Dave Wallace048b1d62018-01-03 22:24:41 -05001677 {
1678 if (size < 0)
1679 {
1680 int errno_val = errno;
1681 perror (func_str);
1682 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1683 "rv %d, errno = %d", getpid (), fd, fd,
1684 func_str, size, errno_val);
1685 errno = errno_val;
1686 }
1687 else
1688 clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1689 getpid (), fd, fd, size, size);
1690 }
1691 return size;
1692}
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001693#endif
1694
Dave Wallace048b1d62018-01-03 22:24:41 -05001695ssize_t
1696recvmsg (int fd, struct msghdr * message, int flags)
1697{
Florin Coras7baeb712019-01-04 17:05:43 -08001698 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001699 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001700
Dave Wallace2a865272018-02-07 21:00:42 -05001701 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001702 return -1;
1703
Florin Coras7baeb712019-01-04 17:05:43 -08001704 vlsh = ldp_fd_to_vlsh (fd);
1705 if (vlsh != VLS_INVALID_HANDLE)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001706 {
Florin Coras7baeb712019-01-04 17:05:43 -08001707 LDBG (0, "LDP-TBD");
Dave Wallace048b1d62018-01-03 22:24:41 -05001708 errno = ENOSYS;
1709 size = -1;
1710 }
1711 else
1712 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001713 size = libc_recvmsg (fd, message, flags);
1714 }
1715
Dave Wallace048b1d62018-01-03 22:24:41 -05001716 return size;
1717}
1718
1719#ifdef USE_GNU
1720int
1721recvmmsg (int fd, struct mmsghdr *vmessages,
1722 unsigned int vlen, int flags, struct timespec *tmo)
1723{
1724 ssize_t size;
1725 const char *func_str;
Florin Coras7baeb712019-01-04 17:05:43 -08001726 u32 sh = ldp_fd_to_vlsh (fd);
Dave Wallace048b1d62018-01-03 22:24:41 -05001727
Dave Wallace2a865272018-02-07 21:00:42 -05001728 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001729 return -1;
1730
Florin Coras7baeb712019-01-04 17:05:43 -08001731 if (sh != INVALID_SESSION_ID)
Dave Wallace048b1d62018-01-03 22:24:41 -05001732 {
1733 clib_warning ("LDP<%d>: LDP-TBD", getpid ());
1734 errno = ENOSYS;
1735 size = -1;
1736 }
1737 else
1738 {
1739 func_str = "libc_recvmmsg";
1740
Dave Wallace2a865272018-02-07 21:00:42 -05001741 if (LDP_DEBUG > 2)
Dave Wallace048b1d62018-01-03 22:24:41 -05001742 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1743 "vmessages %p, vlen %u, flags 0x%x, tmo %p",
1744 getpid (), fd, fd, func_str, vmessages, vlen,
1745 flags, tmo);
1746
1747 size = libc_recvmmsg (fd, vmessages, vlen, flags, tmo);
1748 }
1749
Dave Wallace2a865272018-02-07 21:00:42 -05001750 if (LDP_DEBUG > 2)
Dave Wallace048b1d62018-01-03 22:24:41 -05001751 {
1752 if (size < 0)
1753 {
1754 int errno_val = errno;
1755 perror (func_str);
1756 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1757 "rv %d, errno = %d", getpid (), fd, fd,
1758 func_str, size, errno_val);
1759 errno = errno_val;
1760 }
1761 else
1762 clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1763 getpid (), fd, fd, size, size);
1764 }
1765 return size;
1766}
1767#endif
1768
1769int
1770getsockopt (int fd, int level, int optname,
1771 void *__restrict optval, socklen_t * __restrict optlen)
1772{
Florin Coras7baeb712019-01-04 17:05:43 -08001773 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001774 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001775
Dave Wallace2a865272018-02-07 21:00:42 -05001776 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001777 return -1;
1778
Florin Coras7baeb712019-01-04 17:05:43 -08001779 vlsh = ldp_fd_to_vlsh (fd);
1780 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001781 {
1782 rv = -EOPNOTSUPP;
1783
1784 switch (level)
1785 {
1786 case SOL_TCP:
1787 switch (optname)
1788 {
1789 case TCP_NODELAY:
Florin Coras7baeb712019-01-04 17:05:43 -08001790 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_NODELAY,
1791 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001792 break;
1793 case TCP_MAXSEG:
Florin Coras7baeb712019-01-04 17:05:43 -08001794 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_USER_MSS,
1795 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001796 break;
1797 case TCP_KEEPIDLE:
Florin Coras7baeb712019-01-04 17:05:43 -08001798 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_KEEPIDLE,
1799 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001800 break;
1801 case TCP_KEEPINTVL:
Florin Coras7baeb712019-01-04 17:05:43 -08001802 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_KEEPINTVL,
1803 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001804 break;
1805 case TCP_INFO:
1806 if (optval && optlen && (*optlen == sizeof (struct tcp_info)))
1807 {
Florin Coras7baeb712019-01-04 17:05:43 -08001808 LDBG (1, "fd %d: vlsh %u SOL_TCP, TCP_INFO, optval %p, "
1809 "optlen %d: #LDP-NOP#", fd, vlsh, optval, *optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001810 memset (optval, 0, *optlen);
1811 rv = VPPCOM_OK;
1812 }
1813 else
1814 rv = -EFAULT;
1815 break;
Florin Coras0ed24e92019-01-21 09:03:10 -08001816 case TCP_CONGESTION:
1817 strcpy (optval, "cubic");
1818 *optlen = strlen ("cubic");
1819 rv = 0;
1820 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05001821 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001822 LDBG (0, "ERROR: fd %d: getsockopt SOL_TCP: sid %u, "
1823 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05001824 break;
1825 }
1826 break;
1827 case SOL_IPV6:
1828 switch (optname)
1829 {
1830 case IPV6_V6ONLY:
Florin Coras7baeb712019-01-04 17:05:43 -08001831 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_V6ONLY, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001832 break;
1833 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001834 LDBG (0, "ERROR: fd %d: getsockopt SOL_IPV6: vlsh %u "
1835 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05001836 break;
1837 }
1838 break;
1839 case SOL_SOCKET:
1840 switch (optname)
1841 {
1842 case SO_ACCEPTCONN:
Florin Coras7baeb712019-01-04 17:05:43 -08001843 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_LISTEN, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001844 break;
1845 case SO_KEEPALIVE:
Florin Coras7baeb712019-01-04 17:05:43 -08001846 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_KEEPALIVE, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001847 break;
1848 case SO_PROTOCOL:
Florin Coras7baeb712019-01-04 17:05:43 -08001849 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_PROTOCOL, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001850 *(int *) optval = *(int *) optval ? SOCK_DGRAM : SOCK_STREAM;
1851 break;
1852 case SO_SNDBUF:
Florin Coras7baeb712019-01-04 17:05:43 -08001853 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TX_FIFO_LEN,
1854 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001855 break;
1856 case SO_RCVBUF:
Florin Coras7baeb712019-01-04 17:05:43 -08001857 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_RX_FIFO_LEN,
1858 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001859 break;
1860 case SO_REUSEADDR:
Florin Coras7baeb712019-01-04 17:05:43 -08001861 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_REUSEADDR, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001862 break;
1863 case SO_BROADCAST:
Florin Coras7baeb712019-01-04 17:05:43 -08001864 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_BROADCAST, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001865 break;
1866 case SO_ERROR:
Florin Coras7baeb712019-01-04 17:05:43 -08001867 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_ERROR, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001868 break;
1869 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001870 LDBG (0, "ERROR: fd %d: getsockopt SOL_SOCKET: vlsh %u "
1871 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05001872 break;
1873 }
1874 break;
1875 default:
1876 break;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001877 }
1878
Dave Wallace048b1d62018-01-03 22:24:41 -05001879 if (rv != VPPCOM_OK)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001880 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001881 errno = -rv;
1882 rv = -1;
1883 }
1884 }
1885 else
1886 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001887 rv = libc_getsockopt (fd, level, optname, optval, optlen);
1888 }
1889
Dave Wallace048b1d62018-01-03 22:24:41 -05001890 return rv;
1891}
1892
1893int
1894setsockopt (int fd, int level, int optname,
1895 const void *optval, socklen_t optlen)
1896{
Florin Coras7baeb712019-01-04 17:05:43 -08001897 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001898 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001899
Dave Wallace2a865272018-02-07 21:00:42 -05001900 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001901 return -1;
1902
Florin Coras7baeb712019-01-04 17:05:43 -08001903 vlsh = ldp_fd_to_vlsh (fd);
1904 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001905 {
1906 rv = -EOPNOTSUPP;
1907
1908 switch (level)
1909 {
1910 case SOL_TCP:
1911 switch (optname)
1912 {
1913 case TCP_NODELAY:
Florin Coras7baeb712019-01-04 17:05:43 -08001914 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_NODELAY,
1915 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001916 break;
1917 case TCP_MAXSEG:
Florin Coras7baeb712019-01-04 17:05:43 -08001918 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_USER_MSS,
1919 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001920 break;
1921 case TCP_KEEPIDLE:
Florin Coras7baeb712019-01-04 17:05:43 -08001922 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_KEEPIDLE,
1923 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001924 break;
1925 case TCP_KEEPINTVL:
Florin Coras7baeb712019-01-04 17:05:43 -08001926 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_KEEPINTVL,
1927 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001928 break;
Florin Coras0ed24e92019-01-21 09:03:10 -08001929 case TCP_CONGESTION:
Florin Coras8509aa22019-04-04 12:55:30 -07001930 case TCP_CORK:
Florin Coras0ed24e92019-01-21 09:03:10 -08001931 /* Ignore */
1932 rv = 0;
1933 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05001934 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001935 LDBG (0, "ERROR: fd %d: setsockopt() SOL_TCP: vlsh %u"
1936 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05001937 break;
1938 }
1939 break;
1940 case SOL_IPV6:
1941 switch (optname)
1942 {
1943 case IPV6_V6ONLY:
Florin Coras7baeb712019-01-04 17:05:43 -08001944 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_V6ONLY,
1945 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001946 break;
1947 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001948 LDBG (0, "ERROR: fd %d: setsockopt SOL_IPV6: vlsh %u"
1949 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05001950 break;
1951 }
1952 break;
1953 case SOL_SOCKET:
1954 switch (optname)
1955 {
1956 case SO_KEEPALIVE:
Florin Coras7baeb712019-01-04 17:05:43 -08001957 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_KEEPALIVE,
1958 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001959 break;
1960 case SO_REUSEADDR:
Florin Coras7baeb712019-01-04 17:05:43 -08001961 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_REUSEADDR,
1962 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001963 break;
1964 case SO_BROADCAST:
Florin Coras7baeb712019-01-04 17:05:43 -08001965 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_BROADCAST,
1966 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001967 break;
1968 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001969 LDBG (0, "ERROR: fd %d: setsockopt SOL_SOCKET: vlsh %u "
1970 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05001971 break;
1972 }
1973 break;
1974 default:
1975 break;
1976 }
1977
1978 if (rv != VPPCOM_OK)
1979 {
1980 errno = -rv;
1981 rv = -1;
1982 }
1983 }
1984 else
1985 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001986 rv = libc_setsockopt (fd, level, optname, optval, optlen);
1987 }
1988
Dave Wallace048b1d62018-01-03 22:24:41 -05001989 return rv;
1990}
1991
1992int
1993listen (int fd, int n)
1994{
Florin Coras7baeb712019-01-04 17:05:43 -08001995 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001996 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001997
Dave Wallace2a865272018-02-07 21:00:42 -05001998 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001999 return -1;
2000
Florin Coras7baeb712019-01-04 17:05:43 -08002001 vlsh = ldp_fd_to_vlsh (fd);
2002 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05002003 {
Florin Coras7baeb712019-01-04 17:05:43 -08002004 LDBG (0, "fd %d: calling vls_listen: vlsh %u, n %d", fd, vlsh, n);
Dave Wallace048b1d62018-01-03 22:24:41 -05002005
Florin Coras7baeb712019-01-04 17:05:43 -08002006 rv = vls_listen (vlsh, n);
Dave Wallace048b1d62018-01-03 22:24:41 -05002007 if (rv != VPPCOM_OK)
2008 {
2009 errno = -rv;
2010 rv = -1;
2011 }
2012 }
2013 else
2014 {
Florin Coras7baeb712019-01-04 17:05:43 -08002015 LDBG (0, "fd %d: calling libc_listen(): n %d", fd, n);
Dave Wallace048b1d62018-01-03 22:24:41 -05002016 rv = libc_listen (fd, n);
2017 }
2018
Florin Coras7baeb712019-01-04 17:05:43 -08002019 LDBG (1, "fd %d: returning %d", fd, rv);
Dave Wallace048b1d62018-01-03 22:24:41 -05002020 return rv;
2021}
2022
2023static inline int
Dave Wallace2a865272018-02-07 21:00:42 -05002024ldp_accept4 (int listen_fd, __SOCKADDR_ARG addr,
2025 socklen_t * __restrict addr_len, int flags)
Dave Wallace048b1d62018-01-03 22:24:41 -05002026{
Florin Coras7baeb712019-01-04 17:05:43 -08002027 vls_handle_t listen_vlsh, accept_vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002028 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05002029
Dave Wallace2a865272018-02-07 21:00:42 -05002030 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05002031 return -1;
2032
Florin Coras7baeb712019-01-04 17:05:43 -08002033 listen_vlsh = ldp_fd_to_vlsh (listen_fd);
2034 if (listen_vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05002035 {
2036 vppcom_endpt_t ep;
2037 u8 src_addr[sizeof (struct sockaddr_in6)];
Dave Wallace8aaba562018-01-18 17:21:19 -05002038 memset (&ep, 0, sizeof (ep));
Dave Wallace048b1d62018-01-03 22:24:41 -05002039 ep.ip = src_addr;
2040
Florin Coras7baeb712019-01-04 17:05:43 -08002041 LDBG (0, "listen fd %d: calling vppcom_session_accept: listen sid %u,"
2042 " ep %p, flags 0x%x", listen_fd, listen_vlsh, ep, flags);
Dave Wallace048b1d62018-01-03 22:24:41 -05002043
Florin Coras7baeb712019-01-04 17:05:43 -08002044 accept_vlsh = vls_accept (listen_vlsh, &ep, flags);
2045 if (accept_vlsh < 0)
Dave Wallace048b1d62018-01-03 22:24:41 -05002046 {
Florin Coras7baeb712019-01-04 17:05:43 -08002047 errno = -accept_vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002048 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002049 }
2050 else
2051 {
Dave Wallace2a865272018-02-07 21:00:42 -05002052 rv = ldp_copy_ep_to_sockaddr (addr, addr_len, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05002053 if (rv != VPPCOM_OK)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002054 {
Florin Coras7baeb712019-01-04 17:05:43 -08002055 (void) vls_close (accept_vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05002056 errno = -rv;
2057 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002058 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002059 else
2060 {
Florin Coras7baeb712019-01-04 17:05:43 -08002061 rv = ldp_vlsh_to_fd (accept_vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05002062 }
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002063 }
2064 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002065 else
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002066 {
Florin Coras7baeb712019-01-04 17:05:43 -08002067 LDBG (0, "listen fd %d: calling libc_accept4(): addr %p, addr_len %p,"
2068 " flags 0x%x", listen_fd, addr, addr_len, flags);
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002069
Dave Wallace048b1d62018-01-03 22:24:41 -05002070 rv = libc_accept4 (listen_fd, addr, addr_len, flags);
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002071 }
2072
Florin Coras7baeb712019-01-04 17:05:43 -08002073 LDBG (1, "listen fd %d: accept returning %d", listen_fd, rv);
Florin Coras05ecfcc2018-12-12 18:19:39 -08002074
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002075 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002076}
2077
Dave Wallace048b1d62018-01-03 22:24:41 -05002078int
2079accept4 (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len,
2080 int flags)
2081{
Dave Wallace2a865272018-02-07 21:00:42 -05002082 return ldp_accept4 (fd, addr, addr_len, flags);
Dave Wallace048b1d62018-01-03 22:24:41 -05002083}
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002084
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002085int
Dave Wallace048b1d62018-01-03 22:24:41 -05002086accept (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002087{
Dave Wallace2a865272018-02-07 21:00:42 -05002088 return ldp_accept4 (fd, addr, addr_len, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002089}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002090
Dave Wallace048b1d62018-01-03 22:24:41 -05002091int
2092shutdown (int fd, int how)
2093{
Florin Coras7baeb712019-01-04 17:05:43 -08002094 vls_handle_t vlsh;
2095 int rv = 0, flags;
2096 u32 flags_len = sizeof (flags);
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002097
Dave Wallace2a865272018-02-07 21:00:42 -05002098 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05002099 return -1;
2100
Florin Coras7baeb712019-01-04 17:05:43 -08002101 vlsh = ldp_fd_to_vlsh (fd);
2102 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05002103 {
Florin Coras7baeb712019-01-04 17:05:43 -08002104 LDBG (0, "called shutdown: fd %u vlsh %u how %d", fd, vlsh, how);
Florin Corasa7a1a222018-12-30 17:11:31 -08002105
Florin Coras7baeb712019-01-04 17:05:43 -08002106 if (vls_attr (vlsh, VPPCOM_ATTR_SET_SHUT, &how, &flags_len))
Florin Corasa7a1a222018-12-30 17:11:31 -08002107 {
Florin Coras7baeb712019-01-04 17:05:43 -08002108 close (fd);
Florin Corasa7a1a222018-12-30 17:11:31 -08002109 return -1;
2110 }
2111
Florin Coras7baeb712019-01-04 17:05:43 -08002112 if (vls_attr (vlsh, VPPCOM_ATTR_GET_SHUT, &flags, &flags_len))
2113 {
2114 close (fd);
2115 return -1;
2116 }
Florin Corasa7a1a222018-12-30 17:11:31 -08002117
Florin Coras7baeb712019-01-04 17:05:43 -08002118 if (flags == SHUT_RDWR)
Florin Corasa7a1a222018-12-30 17:11:31 -08002119 rv = close (fd);
Dave Wallace048b1d62018-01-03 22:24:41 -05002120 }
2121 else
2122 {
Florin Coras7baeb712019-01-04 17:05:43 -08002123 LDBG (0, "fd %d: calling libc_shutdown: how %d", fd, how);
Dave Wallace048b1d62018-01-03 22:24:41 -05002124 rv = libc_shutdown (fd, how);
2125 }
2126
Dave Wallace048b1d62018-01-03 22:24:41 -05002127 return rv;
2128}
2129
2130int
2131epoll_create1 (int flags)
2132{
Florin Corasdfe4cf42018-11-28 22:13:45 -08002133 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras7baeb712019-01-04 17:05:43 -08002134 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002135 int rv;
2136
Dave Wallace2a865272018-02-07 21:00:42 -05002137 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05002138 return -1;
2139
Florin Coras99368312018-08-02 10:45:44 -07002140 if (ldp->vcl_needs_real_epoll)
2141 {
Florin Coras2d9b4272019-03-11 10:14:37 -07002142 /* Make sure workers have been allocated */
2143 if (!ldp->workers)
2144 {
2145 ldp_alloc_workers ();
2146 ldpw = ldp_worker_get_current ();
2147 }
Florin Coras99368312018-08-02 10:45:44 -07002148 rv = libc_epoll_create1 (flags);
2149 ldp->vcl_needs_real_epoll = 0;
Florin Corasdfe4cf42018-11-28 22:13:45 -08002150 ldpw->vcl_mq_epfd = rv;
Florin Coras05ecfcc2018-12-12 18:19:39 -08002151 LDBG (0, "created vcl epfd %u", rv);
Florin Coras99368312018-08-02 10:45:44 -07002152 return rv;
2153 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002154
Florin Coras7baeb712019-01-04 17:05:43 -08002155 vlsh = vls_epoll_create ();
2156 if (PREDICT_FALSE (vlsh == VLS_INVALID_HANDLE))
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002157 {
Florin Coras7baeb712019-01-04 17:05:43 -08002158 errno = -vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002159 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002160 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002161 else
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002162 {
Florin Coras7baeb712019-01-04 17:05:43 -08002163 rv = ldp_vlsh_to_fd (vlsh);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002164 }
Florin Coras7baeb712019-01-04 17:05:43 -08002165 LDBG (0, "epoll_create epfd %u vlsh %u", rv, vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05002166 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002167}
2168
2169int
Dave Wallace048b1d62018-01-03 22:24:41 -05002170epoll_create (int size)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002171{
Dave Wallace048b1d62018-01-03 22:24:41 -05002172 return epoll_create1 (0);
2173}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002174
Dave Wallace048b1d62018-01-03 22:24:41 -05002175int
2176epoll_ctl (int epfd, int op, int fd, struct epoll_event *event)
2177{
Florin Coras7baeb712019-01-04 17:05:43 -08002178 vls_handle_t vep_vlsh, vlsh;
Florin Coras99368312018-08-02 10:45:44 -07002179 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05002180
Dave Wallace2a865272018-02-07 21:00:42 -05002181 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05002182 return -1;
2183
Florin Coras7baeb712019-01-04 17:05:43 -08002184 vep_vlsh = ldp_fd_to_vlsh (epfd);
2185 if (PREDICT_FALSE (vep_vlsh == VLS_INVALID_HANDLE))
Dave Wallace048b1d62018-01-03 22:24:41 -05002186 {
Dave Wallace3ee1fe12018-02-23 01:09:11 -05002187 /* The LDP epoll_create1 always creates VCL epfd's.
2188 * The app should never have a kernel base epoll fd unless it
2189 * was acquired outside of the LD_PRELOAD process context.
2190 * In any case, if we get one, punt it to libc_epoll_ctl.
2191 */
Florin Coras7baeb712019-01-04 17:05:43 -08002192 LDBG (1, "epfd %d: calling libc_epoll_ctl: op %d, fd %d"
2193 " event %p", epfd, op, fd, event);
Dave Wallace048b1d62018-01-03 22:24:41 -05002194
2195 rv = libc_epoll_ctl (epfd, op, fd, event);
Florin Coras99368312018-08-02 10:45:44 -07002196 goto done;
2197 }
2198
Florin Coras7baeb712019-01-04 17:05:43 -08002199 vlsh = ldp_fd_to_vlsh (fd);
Florin Coras99368312018-08-02 10:45:44 -07002200
Florin Coras7baeb712019-01-04 17:05:43 -08002201 LDBG (0, "epfd %d ep_vlsh %d, fd %u vlsh %d, op %u", epfd, vep_vlsh, fd,
2202 vlsh, op);
Florin Coras99368312018-08-02 10:45:44 -07002203
Florin Coras7baeb712019-01-04 17:05:43 -08002204 if (vlsh != VLS_INVALID_HANDLE)
Florin Coras99368312018-08-02 10:45:44 -07002205 {
Florin Coras7baeb712019-01-04 17:05:43 -08002206 LDBG (1, "epfd %d: calling vls_epoll_ctl: ep_vlsh %d op %d, vlsh %u,"
2207 " event %p", epfd, vep_vlsh, vlsh, event);
Florin Coras99368312018-08-02 10:45:44 -07002208
Florin Coras7baeb712019-01-04 17:05:43 -08002209 rv = vls_epoll_ctl (vep_vlsh, op, vlsh, event);
Florin Coras99368312018-08-02 10:45:44 -07002210 if (rv != VPPCOM_OK)
2211 {
2212 errno = -rv;
2213 rv = -1;
2214 }
2215 }
2216 else
2217 {
2218 int libc_epfd;
2219 u32 size = sizeof (epfd);
2220
Florin Coras7baeb712019-01-04 17:05:43 -08002221 libc_epfd = vls_attr (vep_vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
Florin Coras99368312018-08-02 10:45:44 -07002222 if (!libc_epfd)
2223 {
Florin Coras7baeb712019-01-04 17:05:43 -08002224 LDBG (1, "epfd %d, vep_vlsh %d calling libc_epoll_create1: "
2225 "EPOLL_CLOEXEC", epfd, vep_vlsh);
Florin Coras99368312018-08-02 10:45:44 -07002226
2227 libc_epfd = libc_epoll_create1 (EPOLL_CLOEXEC);
2228 if (libc_epfd < 0)
2229 {
2230 rv = libc_epfd;
2231 goto done;
2232 }
2233
Florin Coras7baeb712019-01-04 17:05:43 -08002234 rv = vls_attr (vep_vlsh, VPPCOM_ATTR_SET_LIBC_EPFD, &libc_epfd,
2235 &size);
Florin Coras99368312018-08-02 10:45:44 -07002236 if (rv < 0)
2237 {
2238 errno = -rv;
2239 rv = -1;
2240 goto done;
2241 }
2242 }
2243 else if (PREDICT_FALSE (libc_epfd < 0))
2244 {
2245 errno = -epfd;
2246 rv = -1;
2247 goto done;
2248 }
2249
Florin Coras7baeb712019-01-04 17:05:43 -08002250 LDBG (1, "epfd %d: calling libc_epoll_ctl: libc_epfd %d, op %d, fd %d,"
2251 " event %p", epfd, libc_epfd, op, fd, event);
Florin Coras99368312018-08-02 10:45:44 -07002252
2253 rv = libc_epoll_ctl (libc_epfd, op, fd, event);
Dave Wallace048b1d62018-01-03 22:24:41 -05002254 }
2255
2256done:
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002257 return rv;
2258}
Dave Wallace048b1d62018-01-03 22:24:41 -05002259
2260static inline int
Florin Coras99368312018-08-02 10:45:44 -07002261ldp_epoll_pwait (int epfd, struct epoll_event *events, int maxevents,
2262 int timeout, const sigset_t * sigmask)
Dave Wallace048b1d62018-01-03 22:24:41 -05002263{
Florin Corasdfe4cf42018-11-28 22:13:45 -08002264 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras72f77822019-01-22 19:05:52 -08002265 double time_to_wait = (double) 0, max_time;
Florin Coras99368312018-08-02 10:45:44 -07002266 int libc_epfd, rv = 0;
Florin Coras7baeb712019-01-04 17:05:43 -08002267 vls_handle_t ep_vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002268
Dave Wallace2a865272018-02-07 21:00:42 -05002269 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05002270 return -1;
2271
2272 if (PREDICT_FALSE (!events || (timeout < -1)))
2273 {
2274 errno = EFAULT;
2275 return -1;
2276 }
2277
Florin Corasdfe4cf42018-11-28 22:13:45 -08002278 if (epfd == ldpw->vcl_mq_epfd)
Florin Coras99368312018-08-02 10:45:44 -07002279 return libc_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
2280
Florin Coras7baeb712019-01-04 17:05:43 -08002281 ep_vlsh = ldp_fd_to_vlsh (epfd);
2282 if (PREDICT_FALSE (ep_vlsh == VLS_INVALID_HANDLE))
Dave Wallace048b1d62018-01-03 22:24:41 -05002283 {
Florin Coras7baeb712019-01-04 17:05:43 -08002284 LDBG (0, "epfd %d: bad ep_vlsh %d!", epfd, ep_vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05002285 errno = EBADFD;
2286 return -1;
2287 }
2288
Florin Coras4dee8cd2019-01-29 21:28:16 -08002289 if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
2290 clib_time_init (&ldpw->clib_time);
Florin Corasb0f662f2018-12-27 14:51:46 -08002291 time_to_wait = ((timeout >= 0) ? (double) timeout / 1000 : 0);
Florin Coras72f77822019-01-22 19:05:52 -08002292 max_time = clib_time_now (&ldpw->clib_time) + time_to_wait;
Dave Wallace048b1d62018-01-03 22:24:41 -05002293
Florin Coras7baeb712019-01-04 17:05:43 -08002294 libc_epfd = vls_attr (ep_vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002295 if (PREDICT_FALSE (libc_epfd < 0))
2296 {
2297 errno = -libc_epfd;
2298 rv = -1;
2299 goto done;
2300 }
2301
Florin Coras7baeb712019-01-04 17:05:43 -08002302 LDBG (2, "epfd %d: vep_idx %d, libc_epfd %d, events %p, maxevents %d, "
2303 "timeout %d, sigmask %p: time_to_wait %.02f", epfd, ep_vlsh,
Florin Coras72f77822019-01-22 19:05:52 -08002304 libc_epfd, events, maxevents, timeout, sigmask, time_to_wait);
Dave Wallace048b1d62018-01-03 22:24:41 -05002305 do
2306 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002307 if (!ldpw->epoll_wait_vcl)
Dave Wallace048b1d62018-01-03 22:24:41 -05002308 {
Florin Coras7baeb712019-01-04 17:05:43 -08002309 rv = vls_epoll_wait (ep_vlsh, events, maxevents, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002310 if (rv > 0)
2311 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002312 ldpw->epoll_wait_vcl = 1;
Dave Wallace048b1d62018-01-03 22:24:41 -05002313 goto done;
2314 }
2315 else if (rv < 0)
2316 {
2317 errno = -rv;
2318 rv = -1;
2319 goto done;
2320 }
2321 }
2322 else
Florin Corasdfe4cf42018-11-28 22:13:45 -08002323 ldpw->epoll_wait_vcl = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -05002324
2325 if (libc_epfd > 0)
2326 {
Florin Corasb0f662f2018-12-27 14:51:46 -08002327 rv = libc_epoll_pwait (libc_epfd, events, maxevents, 0, sigmask);
Dave Wallace048b1d62018-01-03 22:24:41 -05002328 if (rv != 0)
2329 goto done;
2330 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002331 }
Florin Coras72f77822019-01-22 19:05:52 -08002332 while ((timeout == -1) || (clib_time_now (&ldpw->clib_time) < max_time));
Dave Wallace048b1d62018-01-03 22:24:41 -05002333
2334done:
Dave Wallace048b1d62018-01-03 22:24:41 -05002335 return rv;
2336}
2337
2338int
2339epoll_pwait (int epfd, struct epoll_event *events,
2340 int maxevents, int timeout, const sigset_t * sigmask)
2341{
Dave Wallace2a865272018-02-07 21:00:42 -05002342 return ldp_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
Dave Wallace048b1d62018-01-03 22:24:41 -05002343}
2344
2345int
2346epoll_wait (int epfd, struct epoll_event *events, int maxevents, int timeout)
2347{
Dave Wallace2a865272018-02-07 21:00:42 -05002348 return ldp_epoll_pwait (epfd, events, maxevents, timeout, NULL);
Dave Wallace048b1d62018-01-03 22:24:41 -05002349}
2350
2351int
2352poll (struct pollfd *fds, nfds_t nfds, int timeout)
2353{
Florin Corasdfe4cf42018-11-28 22:13:45 -08002354 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras6917b942018-11-13 22:44:54 -08002355 int rv, i, n_revents = 0;
Florin Coras7baeb712019-01-04 17:05:43 -08002356 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002357 vcl_poll_t *vp;
Florin Coras4dee8cd2019-01-29 21:28:16 -08002358 double max_time;
Dave Wallace048b1d62018-01-03 22:24:41 -05002359
Florin Coras05ecfcc2018-12-12 18:19:39 -08002360 LDBG (3, "fds %p, nfds %d, timeout %d", fds, nfds, timeout);
Dave Wallace048b1d62018-01-03 22:24:41 -05002361
Florin Coras4dee8cd2019-01-29 21:28:16 -08002362 if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
2363 clib_time_init (&ldpw->clib_time);
2364
2365 max_time = (timeout >= 0) ? (f64) timeout / 1000 : 0;
2366 max_time += clib_time_now (&ldpw->clib_time);
Dave Wallace048b1d62018-01-03 22:24:41 -05002367
Dave Wallace048b1d62018-01-03 22:24:41 -05002368 for (i = 0; i < nfds; i++)
2369 {
Florin Coras6917b942018-11-13 22:44:54 -08002370 if (fds[i].fd < 0)
2371 continue;
Dave Wallace048b1d62018-01-03 22:24:41 -05002372
Florin Coras7baeb712019-01-04 17:05:43 -08002373 vlsh = ldp_fd_to_vlsh (fds[i].fd);
2374 if (vlsh != VLS_INVALID_HANDLE)
Florin Coras6917b942018-11-13 22:44:54 -08002375 {
2376 fds[i].fd = -fds[i].fd;
Florin Corasdfe4cf42018-11-28 22:13:45 -08002377 vec_add2 (ldpw->vcl_poll, vp, 1);
Florin Coras6917b942018-11-13 22:44:54 -08002378 vp->fds_ndx = i;
Florin Coras7baeb712019-01-04 17:05:43 -08002379 vp->sh = vlsh_to_sh (vlsh);
Florin Coras6917b942018-11-13 22:44:54 -08002380 vp->events = fds[i].events;
Dave Wallace048b1d62018-01-03 22:24:41 -05002381#ifdef __USE_XOPEN2K
Florin Coras6917b942018-11-13 22:44:54 -08002382 if (fds[i].events & POLLRDNORM)
2383 vp->events |= POLLIN;
2384 if (fds[i].events & POLLWRNORM)
2385 vp->events |= POLLOUT;
Dave Wallace048b1d62018-01-03 22:24:41 -05002386#endif
Florin Coras6917b942018-11-13 22:44:54 -08002387 vp->revents = fds[i].revents;
2388 }
2389 else
2390 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002391 vec_add1 (ldpw->libc_poll, fds[i]);
2392 vec_add1 (ldpw->libc_poll_idxs, i);
Dave Wallace048b1d62018-01-03 22:24:41 -05002393 }
2394 }
2395
Dave Wallace048b1d62018-01-03 22:24:41 -05002396 do
2397 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002398 if (vec_len (ldpw->vcl_poll))
Dave Wallace048b1d62018-01-03 22:24:41 -05002399 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002400 rv = vppcom_poll (ldpw->vcl_poll, vec_len (ldpw->vcl_poll), 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002401 if (rv < 0)
2402 {
2403 errno = -rv;
2404 rv = -1;
2405 goto done;
2406 }
2407 else
2408 n_revents += rv;
2409 }
2410
Florin Corasdfe4cf42018-11-28 22:13:45 -08002411 if (vec_len (ldpw->libc_poll))
Dave Wallace048b1d62018-01-03 22:24:41 -05002412 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002413 rv = libc_poll (ldpw->libc_poll, vec_len (ldpw->libc_poll), 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002414 if (rv < 0)
2415 goto done;
2416 else
2417 n_revents += rv;
2418 }
2419
2420 if (n_revents)
2421 {
2422 rv = n_revents;
2423 goto done;
2424 }
2425 }
Florin Coras4dee8cd2019-01-29 21:28:16 -08002426 while ((timeout < 0) || (clib_time_now (&ldpw->clib_time) < max_time));
Dave Wallace048b1d62018-01-03 22:24:41 -05002427 rv = 0;
2428
2429done:
Florin Corasdfe4cf42018-11-28 22:13:45 -08002430 vec_foreach (vp, ldpw->vcl_poll)
Dave Wallace048b1d62018-01-03 22:24:41 -05002431 {
2432 fds[vp->fds_ndx].fd = -fds[vp->fds_ndx].fd;
Florin Coras6917b942018-11-13 22:44:54 -08002433 fds[vp->fds_ndx].revents = vp->revents;
Dave Wallace048b1d62018-01-03 22:24:41 -05002434#ifdef __USE_XOPEN2K
2435 if ((fds[vp->fds_ndx].revents & POLLIN) &&
2436 (fds[vp->fds_ndx].events & POLLRDNORM))
2437 fds[vp->fds_ndx].revents |= POLLRDNORM;
2438 if ((fds[vp->fds_ndx].revents & POLLOUT) &&
2439 (fds[vp->fds_ndx].events & POLLWRNORM))
2440 fds[vp->fds_ndx].revents |= POLLWRNORM;
2441#endif
2442 }
Florin Corasdfe4cf42018-11-28 22:13:45 -08002443 vec_reset_length (ldpw->vcl_poll);
Dave Wallace048b1d62018-01-03 22:24:41 -05002444
Florin Corasdfe4cf42018-11-28 22:13:45 -08002445 for (i = 0; i < vec_len (ldpw->libc_poll); i++)
Florin Coras6917b942018-11-13 22:44:54 -08002446 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002447 fds[ldpw->libc_poll_idxs[i]].revents = ldpw->libc_poll[i].revents;
Florin Coras6917b942018-11-13 22:44:54 -08002448 }
Florin Corasdfe4cf42018-11-28 22:13:45 -08002449 vec_reset_length (ldpw->libc_poll_idxs);
2450 vec_reset_length (ldpw->libc_poll);
Florin Coras6917b942018-11-13 22:44:54 -08002451
Dave Wallace048b1d62018-01-03 22:24:41 -05002452 return rv;
2453}
2454
2455#ifdef USE_GNU
2456int
2457ppoll (struct pollfd *fds, nfds_t nfds,
2458 const struct timespec *timeout, const sigset_t * sigmask)
2459{
Dave Wallace2a865272018-02-07 21:00:42 -05002460 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05002461 return -1;
2462
2463 clib_warning ("LDP<%d>: LDP-TBD", getpid ());
2464 errno = ENOSYS;
2465
2466
2467 return -1;
2468}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002469#endif
2470
Dave Wallace2a865272018-02-07 21:00:42 -05002471void CONSTRUCTOR_ATTRIBUTE ldp_constructor (void);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002472
Dave Wallace2a865272018-02-07 21:00:42 -05002473void DESTRUCTOR_ATTRIBUTE ldp_destructor (void);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002474
Dave Wallace048b1d62018-01-03 22:24:41 -05002475/*
2476 * This function is called when the library is loaded
2477 */
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002478void
Dave Wallace2a865272018-02-07 21:00:42 -05002479ldp_constructor (void)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002480{
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002481 swrap_constructor ();
Dave Wallace2a865272018-02-07 21:00:42 -05002482 if (ldp_init () != 0)
Florin Corasd89411e2019-03-19 19:44:51 -07002483 {
2484 fprintf (stderr, "\nLDP<%d>: ERROR: ldp_constructor: failed!\n",
2485 getpid ());
2486 _exit (1);
2487 }
Dave Wallace69d01192018-02-22 16:22:09 -05002488 else if (LDP_DEBUG > 0)
Dave Wallace2a865272018-02-07 21:00:42 -05002489 clib_warning ("LDP<%d>: LDP constructor: done!\n", getpid ());
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002490}
2491
2492/*
2493 * This function is called when the library is unloaded
2494 */
2495void
Dave Wallace2a865272018-02-07 21:00:42 -05002496ldp_destructor (void)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002497{
Florin Coras0ef8ef22019-01-18 08:37:13 -08002498 /*
2499 swrap_destructor ();
2500 if (ldp->init)
2501 ldp->init = 0;
2502 */
Dave Wallace048b1d62018-01-03 22:24:41 -05002503
2504 /* Don't use clib_warning() here because that calls writev()
Dave Wallace2a865272018-02-07 21:00:42 -05002505 * which will call ldp_init().
Dave Wallace048b1d62018-01-03 22:24:41 -05002506 */
Dave Wallace69d01192018-02-22 16:22:09 -05002507 if (LDP_DEBUG > 0)
Florin Coras0ef8ef22019-01-18 08:37:13 -08002508 fprintf (stderr, "%s:%d: LDP<%d>: LDP destructor: done!\n",
2509 __func__, __LINE__, getpid ());
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002510}
2511
2512
2513/*
2514 * fd.io coding-style-patch-verification: ON
2515 *
2516 * Local Variables:
2517 * eval: (c-set-style "gnu")
2518 * End:
2519 */