blob: 34eba377451745f232104920f15f385ae69ad6b6 [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 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500383 do
384 {
385 for (i = 0; i < iovcnt; ++i)
386 {
Florin Coras7baeb712019-01-04 17:05:43 -0800387 rv = vls_read (vlsh, iov[i].iov_base, iov[i].iov_len);
Dave Wallace048b1d62018-01-03 22:24:41 -0500388 if (rv < 0)
389 break;
390 else
391 {
392 total += rv;
393 if (rv < iov[i].iov_len)
Florin Coras7baeb712019-01-04 17:05:43 -0800394 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700395 }
396 }
397 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500398 while ((rv >= 0) && (total == 0));
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700399
Dave Wallace048b1d62018-01-03 22:24:41 -0500400 if (rv < 0)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700401 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500402 errno = -rv;
403 size = -1;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700404 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500405 else
406 size = total;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700407 }
408 else
409 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500410 size = libc_readv (fd, iov, iovcnt);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700411 }
412
Dave Wallace048b1d62018-01-03 22:24:41 -0500413 return size;
414}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700415
Dave Wallace048b1d62018-01-03 22:24:41 -0500416ssize_t
417write (int fd, const void *buf, size_t nbytes)
418{
Florin Coras7baeb712019-01-04 17:05:43 -0800419 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500420 ssize_t size = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500421
Dave Wallace2a865272018-02-07 21:00:42 -0500422 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500423 return -1;
424
Florin Coras7baeb712019-01-04 17:05:43 -0800425 vlsh = ldp_fd_to_vlsh (fd);
426 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500427 {
Florin Coras7baeb712019-01-04 17:05:43 -0800428 size = vls_write_msg (vlsh, (void *) buf, nbytes);
Dave Wallace048b1d62018-01-03 22:24:41 -0500429 if (size < 0)
430 {
431 errno = -size;
432 size = -1;
433 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700434 }
435 else
436 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500437 size = libc_write (fd, buf, nbytes);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700438 }
439
Dave Wallace048b1d62018-01-03 22:24:41 -0500440 return size;
441}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700442
Dave Wallace048b1d62018-01-03 22:24:41 -0500443ssize_t
444writev (int fd, const struct iovec * iov, int iovcnt)
445{
Dave Wallace048b1d62018-01-03 22:24:41 -0500446 ssize_t size = 0, total = 0;
Florin Coras7baeb712019-01-04 17:05:43 -0800447 vls_handle_t vlsh;
Dave Wallace8aaba562018-01-18 17:21:19 -0500448 int i, rv = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500449
Dave Wallace2a865272018-02-07 21:00:42 -0500450 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500451 return -1;
452
Florin Coras7baeb712019-01-04 17:05:43 -0800453 vlsh = ldp_fd_to_vlsh (fd);
454 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500455 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500456 do
457 {
458 for (i = 0; i < iovcnt; ++i)
459 {
Florin Coras7baeb712019-01-04 17:05:43 -0800460 rv = vls_write_msg (vlsh, iov[i].iov_base, iov[i].iov_len);
Dave Wallace048b1d62018-01-03 22:24:41 -0500461 if (rv < 0)
462 break;
463 else
464 {
465 total += rv;
466 if (rv < iov[i].iov_len)
Florin Corasb0f662f2018-12-27 14:51:46 -0800467 break;
Dave Wallace048b1d62018-01-03 22:24:41 -0500468 }
469 }
470 }
471 while ((rv >= 0) && (total == 0));
472
473 if (rv < 0)
474 {
475 errno = -rv;
476 size = -1;
477 }
478 else
479 size = total;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700480 }
481 else
482 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500483 size = libc_writev (fd, iov, iovcnt);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700484 }
485
Dave Wallace048b1d62018-01-03 22:24:41 -0500486 return size;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700487}
488
Carl Smithe16707b2019-11-13 14:37:39 +1300489#ifdef HAVE_FCNTL64
490int
491fcntl64 (int fd, int cmd, ...)
492#else
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700493int
Dave Wallace048b1d62018-01-03 22:24:41 -0500494fcntl (int fd, int cmd, ...)
Carl Smithe16707b2019-11-13 14:37:39 +1300495#endif
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700496{
Florin Coras7baeb712019-01-04 17:05:43 -0800497 vls_handle_t vlsh;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700498 int rv = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500499 va_list ap;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700500
Dave Wallace2a865272018-02-07 21:00:42 -0500501 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500502 return -1;
503
504 va_start (ap, cmd);
Florin Coras7baeb712019-01-04 17:05:43 -0800505
506 vlsh = ldp_fd_to_vlsh (fd);
507 LDBG (0, "fd %u vlsh %d, cmd %u", fd, vlsh, cmd);
508 if (vlsh != VLS_INVALID_HANDLE)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700509 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500510 int flags = va_arg (ap, int);
511 u32 size;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700512
Dave Wallace048b1d62018-01-03 22:24:41 -0500513 size = sizeof (flags);
514 rv = -EOPNOTSUPP;
515 switch (cmd)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700516 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500517 case F_SETFL:
Florin Coras7baeb712019-01-04 17:05:43 -0800518 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_FLAGS, &flags, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -0500519 break;
520
521 case F_GETFL:
Florin Coras7baeb712019-01-04 17:05:43 -0800522 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_FLAGS, &flags, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -0500523 if (rv == VPPCOM_OK)
Florin Coras7baeb712019-01-04 17:05:43 -0800524 rv = flags;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700525 break;
Florin Coras173bae32018-11-16 18:56:28 -0800526 case F_SETFD:
527 /* TODO handle this */
528 LDBG (0, "F_SETFD ignored flags %u", flags);
529 rv = 0;
530 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700531 default:
Dave Wallace048b1d62018-01-03 22:24:41 -0500532 rv = -EOPNOTSUPP;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700533 break;
534 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500535 if (rv < 0)
536 {
537 errno = -rv;
538 rv = -1;
539 }
540 }
541 else
542 {
Carl Smithe16707b2019-11-13 14:37:39 +1300543#ifdef HAVE_FCNTL64
544 rv = libc_vfcntl64 (fd, cmd, ap);
545#else
Dave Wallace048b1d62018-01-03 22:24:41 -0500546 rv = libc_vfcntl (fd, cmd, ap);
Carl Smithe16707b2019-11-13 14:37:39 +1300547#endif
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700548 }
549
Dave Wallace048b1d62018-01-03 22:24:41 -0500550 va_end (ap);
551
Dave Wallace048b1d62018-01-03 22:24:41 -0500552 return rv;
553}
554
555int
556ioctl (int fd, unsigned long int cmd, ...)
557{
Florin Coras7baeb712019-01-04 17:05:43 -0800558 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500559 va_list ap;
Florin Coras7baeb712019-01-04 17:05:43 -0800560 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -0500561
Dave Wallace2a865272018-02-07 21:00:42 -0500562 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500563 return -1;
564
565 va_start (ap, cmd);
Dave Wallace048b1d62018-01-03 22:24:41 -0500566
Florin Coras7baeb712019-01-04 17:05:43 -0800567 vlsh = ldp_fd_to_vlsh (fd);
568 if (vlsh != VLS_INVALID_HANDLE)
569 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500570 switch (cmd)
571 {
572 case FIONREAD:
Florin Coras7baeb712019-01-04 17:05:43 -0800573 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_NREAD, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -0500574 break;
575
576 case FIONBIO:
577 {
578 u32 flags = va_arg (ap, int) ? O_NONBLOCK : 0;
579 u32 size = sizeof (flags);
580
581 /* TBD: When VPPCOM_ATTR_[GS]ET_FLAGS supports flags other than
582 * non-blocking, the flags should be read here and merged
583 * with O_NONBLOCK.
584 */
Florin Coras7baeb712019-01-04 17:05:43 -0800585 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_FLAGS, &flags, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -0500586 }
587 break;
588
589 default:
590 rv = -EOPNOTSUPP;
591 break;
592 }
593 if (rv < 0)
594 {
595 errno = -rv;
596 rv = -1;
597 }
598 }
599 else
600 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500601 rv = libc_vioctl (fd, cmd, ap);
602 }
603
Dave Wallace048b1d62018-01-03 22:24:41 -0500604 va_end (ap);
605 return rv;
606}
607
Florin Coras294afe22019-01-07 17:49:17 -0800608always_inline void
609ldp_select_init_maps (fd_set * __restrict original,
610 clib_bitmap_t ** resultb, clib_bitmap_t ** libcb,
611 clib_bitmap_t ** vclb, int nfds, u32 minbits,
612 u32 n_bytes, uword * si_bits, uword * libc_bits)
613{
614 uword si_bits_set, libc_bits_set;
615 vls_handle_t vlsh;
616 int fd;
617
618 clib_bitmap_validate (*vclb, minbits);
619 clib_bitmap_validate (*libcb, minbits);
620 clib_bitmap_validate (*resultb, minbits);
621 clib_memcpy_fast (*resultb, original, n_bytes);
622 memset (original, 0, n_bytes);
623
624 /* *INDENT-OFF* */
625 clib_bitmap_foreach (fd, *resultb, ({
626 if (fd > nfds)
627 break;
628 vlsh = ldp_fd_to_vlsh (fd);
629 if (vlsh == VLS_INVALID_HANDLE)
630 clib_bitmap_set_no_check (*libcb, fd, 1);
631 else
632 clib_bitmap_set_no_check (*vclb, vlsh_to_session_index (vlsh), 1);
633 }));
634 /* *INDENT-ON* */
635
636 si_bits_set = clib_bitmap_last_set (*vclb) + 1;
637 *si_bits = (si_bits_set > *si_bits) ? si_bits_set : *si_bits;
638
639 libc_bits_set = clib_bitmap_last_set (*libcb) + 1;
640 *libc_bits = (libc_bits_set > *libc_bits) ? libc_bits_set : *libc_bits;
641}
642
643always_inline int
644ldp_select_vcl_map_to_libc (clib_bitmap_t * vclb, fd_set * __restrict libcb)
645{
646 vls_handle_t vlsh;
647 uword si;
648 int fd;
649
650 if (!libcb)
651 return 0;
652
653 /* *INDENT-OFF* */
654 clib_bitmap_foreach (si, vclb, ({
655 vlsh = vls_session_index_to_vlsh (si);
656 fd = ldp_vlsh_to_fd (vlsh);
657 if (PREDICT_FALSE (fd < 0))
658 {
659 errno = EBADFD;
660 return -1;
661 }
662 FD_SET (fd, libcb);
663 }));
664 /* *INDENT-ON* */
665
666 return 0;
667}
668
669always_inline void
670ldp_select_libc_map_merge (clib_bitmap_t * result, fd_set * __restrict libcb)
671{
672 uword fd;
673
Florin Coras78b5fa62019-02-21 20:04:15 -0800674 if (!libcb)
675 return;
676
Florin Coras294afe22019-01-07 17:49:17 -0800677 /* *INDENT-OFF* */
678 clib_bitmap_foreach (fd, result, ({
679 FD_SET ((int)fd, libcb);
680 }));
681 /* *INDENT-ON* */
682}
683
Dave Wallace048b1d62018-01-03 22:24:41 -0500684int
Dave Wallace2a865272018-02-07 21:00:42 -0500685ldp_pselect (int nfds, fd_set * __restrict readfds,
686 fd_set * __restrict writefds,
687 fd_set * __restrict exceptfds,
688 const struct timespec *__restrict timeout,
689 const __sigset_t * __restrict sigmask)
Dave Wallace048b1d62018-01-03 22:24:41 -0500690{
Florin Coras294afe22019-01-07 17:49:17 -0800691 u32 minbits = clib_max (nfds, BITS (uword)), n_bytes;
Florin Corasdfe4cf42018-11-28 22:13:45 -0800692 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras294afe22019-01-07 17:49:17 -0800693 struct timespec libc_tspec = { 0 };
694 f64 time_out, vcl_timeout = 0;
695 uword si_bits, libc_bits;
696 int rv, bits_set = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500697
698 if (nfds < 0)
699 {
700 errno = EINVAL;
701 return -1;
702 }
703
Florin Coras4dee8cd2019-01-29 21:28:16 -0800704 if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
705 clib_time_init (&ldpw->clib_time);
706
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500707 if (timeout)
708 {
709 time_out = (timeout->tv_sec == 0 && timeout->tv_nsec == 0) ?
Florin Coras7baeb712019-01-04 17:05:43 -0800710 (f64) 0 : (f64) timeout->tv_sec + (f64) timeout->tv_nsec / (f64) 1e9;
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500711
712 /* select as fine grained sleep */
713 if (!nfds)
714 {
Florin Corasdfe4cf42018-11-28 22:13:45 -0800715 time_out += clib_time_now (&ldpw->clib_time);
716 while (clib_time_now (&ldpw->clib_time) < time_out)
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500717 ;
718 return 0;
719 }
720 }
721 else if (!nfds)
722 {
723 errno = EINVAL;
724 return -1;
725 }
726 else
727 time_out = -1;
728
Florin Coras7baeb712019-01-04 17:05:43 -0800729 if (nfds <= ldp->vlsh_bit_val)
Dave Wallace048b1d62018-01-03 22:24:41 -0500730 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500731 rv = libc_pselect (nfds, readfds, writefds, exceptfds,
732 timeout, sigmask);
733 goto done;
734 }
735
Florin Coras294afe22019-01-07 17:49:17 -0800736 si_bits = libc_bits = 0;
737 n_bytes = nfds / 8 + ((nfds % 8) ? 1 : 0);
Florin Coras7baeb712019-01-04 17:05:43 -0800738
Dave Wallace048b1d62018-01-03 22:24:41 -0500739 if (readfds)
Florin Coras294afe22019-01-07 17:49:17 -0800740 ldp_select_init_maps (readfds, &ldpw->rd_bitmap, &ldpw->libc_rd_bitmap,
741 &ldpw->si_rd_bitmap, nfds, minbits, n_bytes,
742 &si_bits, &libc_bits);
Dave Wallace048b1d62018-01-03 22:24:41 -0500743 if (writefds)
Florin Coras294afe22019-01-07 17:49:17 -0800744 ldp_select_init_maps (writefds, &ldpw->wr_bitmap,
745 &ldpw->libc_wr_bitmap, &ldpw->si_wr_bitmap, nfds,
746 minbits, n_bytes, &si_bits, &libc_bits);
Dave Wallace048b1d62018-01-03 22:24:41 -0500747 if (exceptfds)
Florin Coras294afe22019-01-07 17:49:17 -0800748 ldp_select_init_maps (exceptfds, &ldpw->ex_bitmap,
749 &ldpw->libc_ex_bitmap, &ldpw->si_ex_bitmap, nfds,
750 minbits, n_bytes, &si_bits, &libc_bits);
Dave Wallace048b1d62018-01-03 22:24:41 -0500751
Florin Coras294afe22019-01-07 17:49:17 -0800752 if (PREDICT_FALSE (!si_bits && !libc_bits))
Dave Wallace048b1d62018-01-03 22:24:41 -0500753 {
754 errno = EINVAL;
755 rv = -1;
756 goto done;
757 }
758
Florin Coras78b5fa62019-02-21 20:04:15 -0800759 if (!si_bits)
760 libc_tspec = timeout ? *timeout : libc_tspec;
Florin Coras294afe22019-01-07 17:49:17 -0800761
Dave Wallace048b1d62018-01-03 22:24:41 -0500762 do
763 {
Florin Coras294afe22019-01-07 17:49:17 -0800764 if (si_bits)
Dave Wallace048b1d62018-01-03 22:24:41 -0500765 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500766 if (readfds)
Florin Coras294afe22019-01-07 17:49:17 -0800767 clib_memcpy_fast (ldpw->rd_bitmap, ldpw->si_rd_bitmap,
Florin Corasdfe4cf42018-11-28 22:13:45 -0800768 vec_len (ldpw->rd_bitmap) *
Dave Barach178cf492018-11-13 16:34:13 -0500769 sizeof (clib_bitmap_t));
Dave Wallace048b1d62018-01-03 22:24:41 -0500770 if (writefds)
Florin Coras294afe22019-01-07 17:49:17 -0800771 clib_memcpy_fast (ldpw->wr_bitmap, ldpw->si_wr_bitmap,
Florin Corasdfe4cf42018-11-28 22:13:45 -0800772 vec_len (ldpw->wr_bitmap) *
Dave Barach178cf492018-11-13 16:34:13 -0500773 sizeof (clib_bitmap_t));
Dave Wallace048b1d62018-01-03 22:24:41 -0500774 if (exceptfds)
Florin Coras294afe22019-01-07 17:49:17 -0800775 clib_memcpy_fast (ldpw->ex_bitmap, ldpw->si_ex_bitmap,
Florin Corasdfe4cf42018-11-28 22:13:45 -0800776 vec_len (ldpw->ex_bitmap) *
Dave Barach178cf492018-11-13 16:34:13 -0500777 sizeof (clib_bitmap_t));
Florin Coras294afe22019-01-07 17:49:17 -0800778
Florin Coras0ef8ef22019-01-18 08:37:13 -0800779 rv = vls_select (si_bits, readfds ? ldpw->rd_bitmap : NULL,
780 writefds ? ldpw->wr_bitmap : NULL,
781 exceptfds ? ldpw->ex_bitmap : NULL, vcl_timeout);
Florin Coras294afe22019-01-07 17:49:17 -0800782 if (rv < 0)
783 {
784 errno = -rv;
785 rv = -1;
786 }
787 else if (rv > 0)
788 {
789 if (ldp_select_vcl_map_to_libc (ldpw->rd_bitmap, readfds))
790 {
791 rv = -1;
792 goto done;
793 }
794
795 if (ldp_select_vcl_map_to_libc (ldpw->wr_bitmap, writefds))
796 {
797 rv = -1;
798 goto done;
799 }
800
801 if (ldp_select_vcl_map_to_libc (ldpw->ex_bitmap, exceptfds))
802 {
803 rv = -1;
804 goto done;
805 }
806 bits_set = rv;
807 }
808 }
809 if (libc_bits)
810 {
811 if (readfds)
812 clib_memcpy_fast (ldpw->rd_bitmap, ldpw->libc_rd_bitmap,
813 vec_len (ldpw->libc_rd_bitmap) *
814 sizeof (clib_bitmap_t));
815 if (writefds)
816 clib_memcpy_fast (ldpw->wr_bitmap, ldpw->libc_wr_bitmap,
817 vec_len (ldpw->libc_wr_bitmap) *
818 sizeof (clib_bitmap_t));
819 if (exceptfds)
820 clib_memcpy_fast (ldpw->ex_bitmap, ldpw->libc_ex_bitmap,
821 vec_len (ldpw->libc_ex_bitmap) *
822 sizeof (clib_bitmap_t));
823
Dave Wallace048b1d62018-01-03 22:24:41 -0500824 rv = libc_pselect (libc_bits,
Florin Coras294afe22019-01-07 17:49:17 -0800825 readfds ? (fd_set *) ldpw->rd_bitmap : NULL,
826 writefds ? (fd_set *) ldpw->wr_bitmap : NULL,
827 exceptfds ? (fd_set *) ldpw->ex_bitmap : NULL,
828 &libc_tspec, sigmask);
829 if (rv > 0)
830 {
831 ldp_select_libc_map_merge (ldpw->rd_bitmap, readfds);
832 ldp_select_libc_map_merge (ldpw->wr_bitmap, writefds);
833 ldp_select_libc_map_merge (ldpw->ex_bitmap, exceptfds);
834 bits_set += rv;
835 }
836 }
837
838 if (bits_set)
839 {
840 rv = bits_set;
841 goto done;
Dave Wallace048b1d62018-01-03 22:24:41 -0500842 }
843 }
Florin Corasdfe4cf42018-11-28 22:13:45 -0800844 while ((time_out == -1) || (clib_time_now (&ldpw->clib_time) < time_out));
Dave Wallace048b1d62018-01-03 22:24:41 -0500845 rv = 0;
846
847done:
848 /* TBD: set timeout to amount of time left */
Florin Corasdfe4cf42018-11-28 22:13:45 -0800849 clib_bitmap_zero (ldpw->rd_bitmap);
Florin Coras294afe22019-01-07 17:49:17 -0800850 clib_bitmap_zero (ldpw->si_rd_bitmap);
Florin Corasdfe4cf42018-11-28 22:13:45 -0800851 clib_bitmap_zero (ldpw->libc_rd_bitmap);
852 clib_bitmap_zero (ldpw->wr_bitmap);
Florin Coras294afe22019-01-07 17:49:17 -0800853 clib_bitmap_zero (ldpw->si_wr_bitmap);
Florin Corasdfe4cf42018-11-28 22:13:45 -0800854 clib_bitmap_zero (ldpw->libc_wr_bitmap);
855 clib_bitmap_zero (ldpw->ex_bitmap);
Florin Coras294afe22019-01-07 17:49:17 -0800856 clib_bitmap_zero (ldpw->si_ex_bitmap);
Florin Corasdfe4cf42018-11-28 22:13:45 -0800857 clib_bitmap_zero (ldpw->libc_ex_bitmap);
Dave Wallace048b1d62018-01-03 22:24:41 -0500858
Dave Wallace048b1d62018-01-03 22:24:41 -0500859 return rv;
860}
861
862int
863select (int nfds, fd_set * __restrict readfds,
864 fd_set * __restrict writefds,
865 fd_set * __restrict exceptfds, struct timeval *__restrict timeout)
866{
867 struct timespec tspec;
868
869 if (timeout)
870 {
871 tspec.tv_sec = timeout->tv_sec;
872 tspec.tv_nsec = timeout->tv_usec * 1000;
873 }
Dave Wallace2a865272018-02-07 21:00:42 -0500874 return ldp_pselect (nfds, readfds, writefds, exceptfds,
875 timeout ? &tspec : NULL, NULL);
Dave Wallace048b1d62018-01-03 22:24:41 -0500876}
877
878#ifdef __USE_XOPEN2K
879int
880pselect (int nfds, fd_set * __restrict readfds,
881 fd_set * __restrict writefds,
882 fd_set * __restrict exceptfds,
883 const struct timespec *__restrict timeout,
884 const __sigset_t * __restrict sigmask)
885{
Dave Wallace2a865272018-02-07 21:00:42 -0500886 return ldp_pselect (nfds, readfds, writefds, exceptfds, timeout, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -0500887}
888#endif
889
Yu Ping7b74b072019-05-08 00:40:24 +0800890/* If transparent TLS mode is turned on, then ldp will load key and cert.
891 */
892static int
893load_tls_cert (vls_handle_t vlsh)
894{
895 char *env_var_str = getenv (LDP_ENV_TLS_CERT);
896 char inbuf[4096];
897 char *tls_cert;
898 int cert_size;
899 FILE *fp;
900
901 if (env_var_str)
902 {
903 fp = fopen (env_var_str, "r");
904 if (fp == NULL)
905 {
906 LDBG (0, "ERROR: failed to open cert file %s \n", env_var_str);
907 return -1;
908 }
909 cert_size = fread (inbuf, sizeof (char), sizeof (inbuf), fp);
910 tls_cert = inbuf;
911 vppcom_session_tls_add_cert (vlsh_to_session_index (vlsh), tls_cert,
912 cert_size);
913 fclose (fp);
914 }
915 else
916 {
917 LDBG (0, "ERROR: failed to read LDP environment %s\n",
918 LDP_ENV_TLS_CERT);
919 return -1;
920 }
921 return 0;
922}
923
924static int
925load_tls_key (vls_handle_t vlsh)
926{
927 char *env_var_str = getenv (LDP_ENV_TLS_KEY);
928 char inbuf[4096];
929 char *tls_key;
930 int key_size;
931 FILE *fp;
932
933 if (env_var_str)
934 {
935 fp = fopen (env_var_str, "r");
936 if (fp == NULL)
937 {
938 LDBG (0, "ERROR: failed to open key file %s \n", env_var_str);
939 return -1;
940 }
941 key_size = fread (inbuf, sizeof (char), sizeof (inbuf), fp);
942 tls_key = inbuf;
943 vppcom_session_tls_add_key (vlsh_to_session_index (vlsh), tls_key,
944 key_size);
945 fclose (fp);
946 }
947 else
948 {
949 LDBG (0, "ERROR: failed to read LDP environment %s\n", LDP_ENV_TLS_KEY);
950 return -1;
951 }
952 return 0;
953}
954
Dave Wallace048b1d62018-01-03 22:24:41 -0500955int
956socket (int domain, int type, int protocol)
957{
Florin Coras7baeb712019-01-04 17:05:43 -0800958 int rv, sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
Dave Wallace048b1d62018-01-03 22:24:41 -0500959 u8 is_nonblocking = type & SOCK_NONBLOCK ? 1 : 0;
Florin Coras7baeb712019-01-04 17:05:43 -0800960 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500961
Dave Wallace2a865272018-02-07 21:00:42 -0500962 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500963 return -1;
964
965 if (((domain == AF_INET) || (domain == AF_INET6)) &&
966 ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM)))
967 {
Yu Ping7b74b072019-05-08 00:40:24 +0800968 u8 proto;
969 if (ldp->transparent_tls)
970 {
971 proto = VPPCOM_PROTO_TLS;
972 }
973 else
974 proto = ((sock_type == SOCK_DGRAM) ?
975 VPPCOM_PROTO_UDP : VPPCOM_PROTO_TCP);
Dave Wallace048b1d62018-01-03 22:24:41 -0500976
Florin Coras7baeb712019-01-04 17:05:43 -0800977 LDBG (0, "calling vls_create: proto %u (%s), is_nonblocking %u",
978 proto, vppcom_proto_str (proto), is_nonblocking);
Dave Wallace048b1d62018-01-03 22:24:41 -0500979
Florin Coras7baeb712019-01-04 17:05:43 -0800980 vlsh = vls_create (proto, is_nonblocking);
981 if (vlsh < 0)
Dave Wallace048b1d62018-01-03 22:24:41 -0500982 {
Florin Coras7baeb712019-01-04 17:05:43 -0800983 errno = -vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500984 rv = -1;
985 }
986 else
987 {
Yu Ping7b74b072019-05-08 00:40:24 +0800988 if (ldp->transparent_tls)
989 {
990 if (load_tls_cert (vlsh) < 0 || load_tls_key (vlsh) < 0)
991 {
992 return -1;
993 }
994 }
Florin Coras7baeb712019-01-04 17:05:43 -0800995 rv = ldp_vlsh_to_fd (vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -0500996 }
997 }
998 else
999 {
Florin Coras7baeb712019-01-04 17:05:43 -08001000 LDBG (0, "calling libc_socket");
Dave Wallace048b1d62018-01-03 22:24:41 -05001001 rv = libc_socket (domain, type, protocol);
1002 }
1003
Dave Wallace048b1d62018-01-03 22:24:41 -05001004 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001005}
1006
1007/*
1008 * Create two new sockets, of type TYPE in domain DOMAIN and using
1009 * protocol PROTOCOL, which are connected to each other, and put file
1010 * descriptors for them in FDS[0] and FDS[1]. If PROTOCOL is zero,
1011 * one will be chosen automatically.
1012 * Returns 0 on success, -1 for errors.
1013 * */
1014int
Dave Wallace048b1d62018-01-03 22:24:41 -05001015socketpair (int domain, int type, int protocol, int fds[2])
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001016{
Florin Coras7baeb712019-01-04 17:05:43 -08001017 int rv, sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
Dave Wallace048b1d62018-01-03 22:24:41 -05001018
Dave Wallace2a865272018-02-07 21:00:42 -05001019 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001020 return -1;
1021
1022 if (((domain == AF_INET) || (domain == AF_INET6)) &&
1023 ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM)))
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001024 {
Florin Coras7baeb712019-01-04 17:05:43 -08001025 LDBG (0, "LDP-TBD");
Dave Wallace048b1d62018-01-03 22:24:41 -05001026 errno = ENOSYS;
1027 rv = -1;
1028 }
1029 else
1030 {
Florin Coras7baeb712019-01-04 17:05:43 -08001031 LDBG (1, "calling libc_socketpair");
Florin Coras173bae32018-11-16 18:56:28 -08001032 rv = libc_socketpair (domain, type, protocol, fds);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001033 }
1034
Dave Wallace048b1d62018-01-03 22:24:41 -05001035 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001036}
1037
1038int
Dave Wallace048b1d62018-01-03 22:24:41 -05001039bind (int fd, __CONST_SOCKADDR_ARG addr, socklen_t len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001040{
Florin Coras7baeb712019-01-04 17:05:43 -08001041 vls_handle_t vlsh;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001042 int rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001043
Dave Wallace2a865272018-02-07 21:00:42 -05001044 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001045 return -1;
1046
Florin Coras7baeb712019-01-04 17:05:43 -08001047 vlsh = ldp_fd_to_vlsh (fd);
1048 if (vlsh != VLS_INVALID_HANDLE)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001049 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001050 vppcom_endpt_t ep;
1051
Dave Wallace048b1d62018-01-03 22:24:41 -05001052 switch (addr->sa_family)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001053 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001054 case AF_INET:
1055 if (len != sizeof (struct sockaddr_in))
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001056 {
Florin Coras7baeb712019-01-04 17:05:43 -08001057 LDBG (0, "ERROR: fd %d: vlsh %u: Invalid AF_INET addr len %u!",
1058 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001059 errno = EINVAL;
1060 rv = -1;
1061 goto done;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001062 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001063 ep.is_ip4 = VPPCOM_IS_IP4;
1064 ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr;
1065 ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port;
1066 break;
1067
1068 case AF_INET6:
1069 if (len != sizeof (struct sockaddr_in6))
1070 {
Florin Coras7baeb712019-01-04 17:05:43 -08001071 LDBG (0, "ERROR: fd %d: vlsh %u: Invalid AF_INET6 addr len %u!",
1072 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001073 errno = EINVAL;
1074 rv = -1;
1075 goto done;
1076 }
1077 ep.is_ip4 = VPPCOM_IS_IP6;
1078 ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
1079 ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001080 break;
1081
1082 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001083 LDBG (0, "ERROR: fd %d: vlsh %u: Unsupported address family %u!",
1084 fd, vlsh, addr->sa_family);
Dave Wallace048b1d62018-01-03 22:24:41 -05001085 errno = EAFNOSUPPORT;
1086 rv = -1;
1087 goto done;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001088 }
Florin Coras7baeb712019-01-04 17:05:43 -08001089 LDBG (0, "fd %d: calling vls_bind: vlsh %u, addr %p, len %u", fd, vlsh,
1090 addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001091
Florin Coras7baeb712019-01-04 17:05:43 -08001092 rv = vls_bind (vlsh, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001093 if (rv != VPPCOM_OK)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001094 {
1095 errno = -rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001096 rv = -1;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001097 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001098 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001099 else
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001100 {
Florin Coras7baeb712019-01-04 17:05:43 -08001101 LDBG (0, "fd %d: calling libc_bind: addr %p, len %u", fd, addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001102 rv = libc_bind (fd, addr, len);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001103 }
1104
Dave Wallace048b1d62018-01-03 22:24:41 -05001105done:
Florin Coras7baeb712019-01-04 17:05:43 -08001106 LDBG (1, "fd %d: returning %d", fd, rv);
Florin Coras05ecfcc2018-12-12 18:19:39 -08001107
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001108 return rv;
1109}
1110
1111static inline int
Dave Wallace2a865272018-02-07 21:00:42 -05001112ldp_copy_ep_to_sockaddr (__SOCKADDR_ARG addr, socklen_t * __restrict len,
1113 vppcom_endpt_t * ep)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001114{
Dave Wallace048b1d62018-01-03 22:24:41 -05001115 int rv = 0;
1116 int sa_len, copy_len;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001117
Dave Wallace2a865272018-02-07 21:00:42 -05001118 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001119 return -1;
1120
1121 if (addr && len && ep)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001122 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001123 addr->sa_family = (ep->is_ip4 == VPPCOM_IS_IP4) ? AF_INET : AF_INET6;
1124 switch (addr->sa_family)
1125 {
1126 case AF_INET:
1127 ((struct sockaddr_in *) addr)->sin_port = ep->port;
1128 if (*len > sizeof (struct sockaddr_in))
1129 *len = sizeof (struct sockaddr_in);
1130 sa_len = sizeof (struct sockaddr_in) - sizeof (struct in_addr);
1131 copy_len = *len - sa_len;
1132 if (copy_len > 0)
1133 memcpy (&((struct sockaddr_in *) addr)->sin_addr, ep->ip,
1134 copy_len);
1135 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001136
Dave Wallace048b1d62018-01-03 22:24:41 -05001137 case AF_INET6:
1138 ((struct sockaddr_in6 *) addr)->sin6_port = ep->port;
1139 if (*len > sizeof (struct sockaddr_in6))
1140 *len = sizeof (struct sockaddr_in6);
1141 sa_len = sizeof (struct sockaddr_in6) - sizeof (struct in6_addr);
1142 copy_len = *len - sa_len;
1143 if (copy_len > 0)
1144 memcpy (((struct sockaddr_in6 *) addr)->sin6_addr.
1145 __in6_u.__u6_addr8, ep->ip, copy_len);
1146 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001147
Dave Wallace048b1d62018-01-03 22:24:41 -05001148 default:
1149 /* Not possible */
1150 rv = -EAFNOSUPPORT;
1151 break;
1152 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001153 }
Dave Wallacee695cb42017-11-02 22:04:42 -04001154 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001155}
1156
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001157int
Dave Wallace048b1d62018-01-03 22:24:41 -05001158getsockname (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001159{
Florin Coras7baeb712019-01-04 17:05:43 -08001160 vls_handle_t vlsh;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001161 int rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001162
Dave Wallace2a865272018-02-07 21:00:42 -05001163 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001164 return -1;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001165
Florin Coras7baeb712019-01-04 17:05:43 -08001166 vlsh = ldp_fd_to_vlsh (fd);
1167 if (vlsh != VLS_INVALID_HANDLE)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001168 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001169 vppcom_endpt_t ep;
1170 u8 addr_buf[sizeof (struct in6_addr)];
1171 u32 size = sizeof (ep);
1172
1173 ep.ip = addr_buf;
Dave Wallace048b1d62018-01-03 22:24:41 -05001174
Florin Coras7baeb712019-01-04 17:05:43 -08001175 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_LCL_ADDR, &ep, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -05001176 if (rv != VPPCOM_OK)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001177 {
1178 errno = -rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001179 rv = -1;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001180 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001181 else
1182 {
Dave Wallace2a865272018-02-07 21:00:42 -05001183 rv = ldp_copy_ep_to_sockaddr (addr, len, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001184 if (rv != VPPCOM_OK)
1185 {
1186 errno = -rv;
1187 rv = -1;
1188 }
1189 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001190 }
1191 else
1192 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001193 rv = libc_getsockname (fd, addr, len);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001194 }
1195
Dave Wallace048b1d62018-01-03 22:24:41 -05001196 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001197}
1198
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001199int
Dave Wallace048b1d62018-01-03 22:24:41 -05001200connect (int fd, __CONST_SOCKADDR_ARG addr, socklen_t len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001201{
Florin Coras7baeb712019-01-04 17:05:43 -08001202 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001203 int rv;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001204
Dave Wallace2a865272018-02-07 21:00:42 -05001205 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001206 return -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001207
Dave Wallace048b1d62018-01-03 22:24:41 -05001208 if (!addr)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001209 {
Florin Coras7baeb712019-01-04 17:05:43 -08001210 LDBG (0, "ERROR: fd %d: NULL addr, len %u", fd, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001211 errno = EINVAL;
1212 rv = -1;
1213 goto done;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001214 }
1215
Florin Coras7baeb712019-01-04 17:05:43 -08001216 vlsh = ldp_fd_to_vlsh (fd);
1217 if (vlsh != VLS_INVALID_HANDLE)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001218 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001219 vppcom_endpt_t ep;
1220
Dave Wallace048b1d62018-01-03 22:24:41 -05001221 switch (addr->sa_family)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001222 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001223 case AF_INET:
1224 if (len != sizeof (struct sockaddr_in))
1225 {
Florin Coras7baeb712019-01-04 17:05:43 -08001226 LDBG (0, "fd %d: ERROR vlsh %u: Invalid AF_INET addr len %u!",
1227 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001228 errno = EINVAL;
1229 rv = -1;
1230 goto done;
1231 }
1232 ep.is_ip4 = VPPCOM_IS_IP4;
1233 ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr;
1234 ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port;
1235 break;
1236
1237 case AF_INET6:
1238 if (len != sizeof (struct sockaddr_in6))
1239 {
Florin Coras7baeb712019-01-04 17:05:43 -08001240 LDBG (0, "fd %d: ERROR vlsh %u: Invalid AF_INET6 addr len %u!",
1241 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001242 errno = EINVAL;
1243 rv = -1;
1244 goto done;
1245 }
1246 ep.is_ip4 = VPPCOM_IS_IP6;
1247 ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
1248 ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port;
1249 break;
1250
1251 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001252 LDBG (0, "fd %d: ERROR vlsh %u: Unsupported address family %u!",
1253 fd, vlsh, addr->sa_family);
Dave Wallace048b1d62018-01-03 22:24:41 -05001254 errno = EAFNOSUPPORT;
1255 rv = -1;
1256 goto done;
1257 }
Florin Coras7baeb712019-01-04 17:05:43 -08001258 LDBG (0, "fd %d: calling vls_connect(): vlsh %u addr %p len %u", fd,
1259 vlsh, addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001260
Florin Coras7baeb712019-01-04 17:05:43 -08001261 rv = vls_connect (vlsh, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001262 if (rv != VPPCOM_OK)
1263 {
1264 errno = -rv;
1265 rv = -1;
1266 }
1267 }
1268 else
1269 {
Florin Coras7baeb712019-01-04 17:05:43 -08001270 LDBG (0, "fd %d: calling libc_connect(): addr %p, len %u",
1271 fd, addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001272
1273 rv = libc_connect (fd, addr, len);
1274 }
1275
1276done:
Florin Coras7baeb712019-01-04 17:05:43 -08001277 LDBG (1, "fd %d: returning %d (0x%x)", fd, rv, rv);
Dave Wallace048b1d62018-01-03 22:24:41 -05001278 return rv;
1279}
1280
1281int
1282getpeername (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict len)
1283{
Florin Coras7baeb712019-01-04 17:05:43 -08001284 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001285 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001286
Dave Wallace2a865272018-02-07 21:00:42 -05001287 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001288 return -1;
1289
Florin Coras7baeb712019-01-04 17:05:43 -08001290 vlsh = ldp_fd_to_vlsh (fd);
1291 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001292 {
1293 vppcom_endpt_t ep;
1294 u8 addr_buf[sizeof (struct in6_addr)];
1295 u32 size = sizeof (ep);
1296
1297 ep.ip = addr_buf;
Florin Coras7baeb712019-01-04 17:05:43 -08001298 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_PEER_ADDR, &ep, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -05001299 if (rv != VPPCOM_OK)
1300 {
1301 errno = -rv;
1302 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001303 }
1304 else
1305 {
Dave Wallace2a865272018-02-07 21:00:42 -05001306 rv = ldp_copy_ep_to_sockaddr (addr, len, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001307 if (rv != VPPCOM_OK)
1308 {
1309 errno = -rv;
1310 rv = -1;
1311 }
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001312 }
1313 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001314 else
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001315 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001316 rv = libc_getpeername (fd, addr, len);
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001317 }
1318
Dave Wallace048b1d62018-01-03 22:24:41 -05001319 return rv;
1320}
1321
1322ssize_t
1323send (int fd, const void *buf, size_t n, int flags)
1324{
Florin Coras7baeb712019-01-04 17:05:43 -08001325 vls_handle_t vlsh = ldp_fd_to_vlsh (fd);
Dave Wallace048b1d62018-01-03 22:24:41 -05001326 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001327
Dave Wallace2a865272018-02-07 21:00:42 -05001328 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001329 return -1;
1330
Florin Coras7baeb712019-01-04 17:05:43 -08001331 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001332 {
Florin Coras7baeb712019-01-04 17:05:43 -08001333 size = vls_sendto (vlsh, (void *) buf, n, flags, NULL);
qchangaa8f63c2018-05-30 11:44:18 -07001334 if (size < VPPCOM_OK)
Dave Wallace048b1d62018-01-03 22:24:41 -05001335 {
1336 errno = -size;
1337 size = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001338 }
1339 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001340 else
1341 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001342 size = libc_send (fd, buf, n, flags);
1343 }
1344
Dave Wallace048b1d62018-01-03 22:24:41 -05001345 return size;
1346}
1347
1348ssize_t
1349sendfile (int out_fd, int in_fd, off_t * offset, size_t len)
1350{
Florin Corasdfe4cf42018-11-28 22:13:45 -08001351 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras7baeb712019-01-04 17:05:43 -08001352 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001353 ssize_t size = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -05001354
Dave Wallace2a865272018-02-07 21:00:42 -05001355 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001356 return -1;
1357
Florin Coras7baeb712019-01-04 17:05:43 -08001358 vlsh = ldp_fd_to_vlsh (out_fd);
1359 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001360 {
1361 int rv;
1362 ssize_t results = 0;
1363 size_t n_bytes_left = len;
1364 size_t bytes_to_read;
1365 int nbytes;
Dave Wallace048b1d62018-01-03 22:24:41 -05001366 u8 eagain = 0;
1367 u32 flags, flags_len = sizeof (flags);
1368
Florin Coras7baeb712019-01-04 17:05:43 -08001369 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_FLAGS, &flags, &flags_len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001370 if (PREDICT_FALSE (rv != VPPCOM_OK))
1371 {
Florin Coras7baeb712019-01-04 17:05:43 -08001372 LDBG (0, "ERROR: out fd %d: vls_attr: vlsh %u, returned %d (%s)!",
1373 out_fd, vlsh, rv, vppcom_retval_str (rv));
Dave Wallace048b1d62018-01-03 22:24:41 -05001374
Florin Corasdfe4cf42018-11-28 22:13:45 -08001375 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001376 errno = -rv;
1377 size = -1;
1378 goto done;
1379 }
1380
1381 if (offset)
1382 {
1383 off_t off = lseek (in_fd, *offset, SEEK_SET);
1384 if (PREDICT_FALSE (off == -1))
1385 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001386 size = -1;
1387 goto done;
1388 }
1389
1390 ASSERT (off == *offset);
1391 }
1392
1393 do
1394 {
Florin Coras7baeb712019-01-04 17:05:43 -08001395 size = vls_attr (vlsh, VPPCOM_ATTR_GET_NWRITE, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05001396 if (size < 0)
1397 {
Florin Coras7baeb712019-01-04 17:05:43 -08001398 LDBG (0, "ERROR: fd %d: vls_attr: vlsh %u returned %d (%s)!",
1399 out_fd, vlsh, size, vppcom_retval_str (size));
Florin Corasdfe4cf42018-11-28 22:13:45 -08001400 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001401 errno = -size;
1402 size = -1;
1403 goto done;
1404 }
1405
1406 bytes_to_read = size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001407 if (bytes_to_read == 0)
1408 {
1409 if (flags & O_NONBLOCK)
1410 {
1411 if (!results)
Florin Coras7baeb712019-01-04 17:05:43 -08001412 eagain = 1;
Dave Wallace048b1d62018-01-03 22:24:41 -05001413 goto update_offset;
1414 }
1415 else
1416 continue;
1417 }
1418 bytes_to_read = clib_min (n_bytes_left, bytes_to_read);
Florin Corasdfe4cf42018-11-28 22:13:45 -08001419 vec_validate (ldpw->io_buffer, bytes_to_read);
1420 nbytes = libc_read (in_fd, ldpw->io_buffer, bytes_to_read);
Dave Wallace048b1d62018-01-03 22:24:41 -05001421 if (nbytes < 0)
1422 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001423 if (results == 0)
1424 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08001425 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001426 size = -1;
1427 goto done;
1428 }
1429 goto update_offset;
1430 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001431
Florin Coras7baeb712019-01-04 17:05:43 -08001432 size = vls_write (vlsh, ldpw->io_buffer, nbytes);
Dave Wallace048b1d62018-01-03 22:24:41 -05001433 if (size < 0)
1434 {
1435 if (size == VPPCOM_EAGAIN)
1436 {
1437 if (flags & O_NONBLOCK)
1438 {
1439 if (!results)
Florin Coras7baeb712019-01-04 17:05:43 -08001440 eagain = 1;
Dave Wallace048b1d62018-01-03 22:24:41 -05001441 goto update_offset;
1442 }
1443 else
1444 continue;
1445 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001446 if (results == 0)
1447 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08001448 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001449 errno = -size;
1450 size = -1;
1451 goto done;
1452 }
1453 goto update_offset;
1454 }
1455
1456 results += nbytes;
1457 ASSERT (n_bytes_left >= nbytes);
1458 n_bytes_left = n_bytes_left - nbytes;
1459 }
1460 while (n_bytes_left > 0);
1461
1462 update_offset:
Florin Corasdfe4cf42018-11-28 22:13:45 -08001463 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001464 if (offset)
1465 {
1466 off_t off = lseek (in_fd, *offset, SEEK_SET);
1467 if (PREDICT_FALSE (off == -1))
1468 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001469 size = -1;
1470 goto done;
1471 }
1472
1473 ASSERT (off == *offset);
1474 *offset += results + 1;
1475 }
1476 if (eagain)
1477 {
1478 errno = EAGAIN;
1479 size = -1;
1480 }
1481 else
1482 size = results;
1483 }
1484 else
1485 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001486 size = libc_sendfile (out_fd, in_fd, offset, len);
1487 }
1488
1489done:
Dave Wallace048b1d62018-01-03 22:24:41 -05001490 return size;
1491}
1492
1493ssize_t
1494sendfile64 (int out_fd, int in_fd, off_t * offset, size_t len)
1495{
1496 return sendfile (out_fd, in_fd, offset, len);
1497}
1498
1499ssize_t
1500recv (int fd, void *buf, size_t n, int flags)
1501{
Florin Coras7baeb712019-01-04 17:05:43 -08001502 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001503 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001504
Dave Wallace2a865272018-02-07 21:00:42 -05001505 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001506 return -1;
1507
Florin Coras7baeb712019-01-04 17:05:43 -08001508 vlsh = ldp_fd_to_vlsh (fd);
1509 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001510 {
Florin Coras7baeb712019-01-04 17:05:43 -08001511 size = vls_recvfrom (vlsh, buf, n, flags, NULL);
Dave Wallace048b1d62018-01-03 22:24:41 -05001512 if (size < 0)
Florin Corasa7a1a222018-12-30 17:11:31 -08001513 errno = -size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001514 }
1515 else
1516 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001517 size = libc_recv (fd, buf, n, flags);
1518 }
1519
Dave Wallace048b1d62018-01-03 22:24:41 -05001520 return size;
1521}
1522
1523ssize_t
1524sendto (int fd, const void *buf, size_t n, int flags,
1525 __CONST_SOCKADDR_ARG addr, socklen_t addr_len)
1526{
Florin Coras7baeb712019-01-04 17:05:43 -08001527 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001528 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001529
Dave Wallace2a865272018-02-07 21:00:42 -05001530 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001531 return -1;
1532
Florin Coras7baeb712019-01-04 17:05:43 -08001533 vlsh = ldp_fd_to_vlsh (fd);
1534 if (vlsh != INVALID_SESSION_ID)
Dave Wallace048b1d62018-01-03 22:24:41 -05001535 {
1536 vppcom_endpt_t *ep = 0;
1537 vppcom_endpt_t _ep;
1538
1539 if (addr)
1540 {
1541 ep = &_ep;
Dave Wallace048b1d62018-01-03 22:24:41 -05001542 switch (addr->sa_family)
1543 {
1544 case AF_INET:
1545 ep->is_ip4 = VPPCOM_IS_IP4;
1546 ep->ip =
1547 (uint8_t *) & ((const struct sockaddr_in *) addr)->sin_addr;
1548 ep->port =
1549 (uint16_t) ((const struct sockaddr_in *) addr)->sin_port;
1550 break;
1551
1552 case AF_INET6:
1553 ep->is_ip4 = VPPCOM_IS_IP6;
1554 ep->ip =
1555 (uint8_t *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
1556 ep->port =
1557 (uint16_t) ((const struct sockaddr_in6 *) addr)->sin6_port;
1558 break;
1559
1560 default:
1561 errno = EAFNOSUPPORT;
1562 size = -1;
1563 goto done;
1564 }
1565 }
1566
Florin Coras7baeb712019-01-04 17:05:43 -08001567 size = vls_sendto (vlsh, (void *) buf, n, flags, ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001568 if (size < 0)
1569 {
1570 errno = -size;
1571 size = -1;
1572 }
1573 }
1574 else
1575 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001576 size = libc_sendto (fd, buf, n, flags, addr, addr_len);
1577 }
1578
1579done:
Dave Wallace048b1d62018-01-03 22:24:41 -05001580 return size;
1581}
1582
1583ssize_t
1584recvfrom (int fd, void *__restrict buf, size_t n, int flags,
1585 __SOCKADDR_ARG addr, socklen_t * __restrict addr_len)
1586{
Florin Coras7baeb712019-01-04 17:05:43 -08001587 vls_handle_t sid;
Haggai Eran46ae2ef2019-02-19 15:04:42 +02001588 ssize_t size, rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001589
Dave Wallace2a865272018-02-07 21:00:42 -05001590 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001591 return -1;
1592
Florin Coras7baeb712019-01-04 17:05:43 -08001593 sid = ldp_fd_to_vlsh (fd);
1594 if (sid != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001595 {
1596 vppcom_endpt_t ep;
1597 u8 src_addr[sizeof (struct sockaddr_in6)];
1598
Dave Wallace048b1d62018-01-03 22:24:41 -05001599 if (addr)
1600 {
1601 ep.ip = src_addr;
Florin Coras7baeb712019-01-04 17:05:43 -08001602 size = vls_recvfrom (sid, buf, n, flags, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001603
1604 if (size > 0)
Haggai Eran46ae2ef2019-02-19 15:04:42 +02001605 {
1606 rv = ldp_copy_ep_to_sockaddr (addr, addr_len, &ep);
1607 if (rv < 0)
1608 size = rv;
1609 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001610 }
1611 else
Florin Coras7baeb712019-01-04 17:05:43 -08001612 size = vls_recvfrom (sid, buf, n, flags, NULL);
Dave Wallace048b1d62018-01-03 22:24:41 -05001613
1614 if (size < 0)
1615 {
1616 errno = -size;
1617 size = -1;
1618 }
1619 }
1620 else
1621 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001622 size = libc_recvfrom (fd, buf, n, flags, addr, addr_len);
1623 }
1624
Dave Wallace048b1d62018-01-03 22:24:41 -05001625 return size;
1626}
1627
1628ssize_t
1629sendmsg (int fd, const struct msghdr * message, int flags)
1630{
Florin Coras7baeb712019-01-04 17:05:43 -08001631 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001632 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001633
Dave Wallace2a865272018-02-07 21:00:42 -05001634 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001635 return -1;
1636
Florin Coras7baeb712019-01-04 17:05:43 -08001637 vlsh = ldp_fd_to_vlsh (fd);
1638 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001639 {
Florin Coras7baeb712019-01-04 17:05:43 -08001640 LDBG (0, "LDP-TBD");
Dave Wallace048b1d62018-01-03 22:24:41 -05001641 errno = ENOSYS;
1642 size = -1;
1643 }
1644 else
1645 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001646 size = libc_sendmsg (fd, message, flags);
1647 }
1648
Dave Wallace048b1d62018-01-03 22:24:41 -05001649 return size;
1650}
1651
1652#ifdef USE_GNU
1653int
1654sendmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags)
1655{
1656 ssize_t size;
1657 const char *func_str;
Florin Coras7baeb712019-01-04 17:05:43 -08001658 u32 sh = ldp_fd_to_vlsh (fd);
Dave Wallace048b1d62018-01-03 22:24:41 -05001659
Dave Wallace2a865272018-02-07 21:00:42 -05001660 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001661 return -1;
1662
Florin Coras7baeb712019-01-04 17:05:43 -08001663 if (sh != INVALID_SESSION_ID)
Dave Wallace048b1d62018-01-03 22:24:41 -05001664 {
1665 clib_warning ("LDP<%d>: LDP-TBD", getpid ());
1666 errno = ENOSYS;
1667 size = -1;
1668 }
1669 else
1670 {
1671 func_str = "libc_sendmmsg";
1672
Dave Wallace2a865272018-02-07 21:00:42 -05001673 if (LDP_DEBUG > 2)
Dave Wallace048b1d62018-01-03 22:24:41 -05001674 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1675 "vmessages %p, vlen %u, flags 0x%x",
1676 getpid (), fd, fd, func_str, vmessages, vlen, flags);
1677
1678 size = libc_sendmmsg (fd, vmessages, vlen, flags);
1679 }
1680
Dave Wallace2a865272018-02-07 21:00:42 -05001681 if (LDP_DEBUG > 2)
Dave Wallace048b1d62018-01-03 22:24:41 -05001682 {
1683 if (size < 0)
1684 {
1685 int errno_val = errno;
1686 perror (func_str);
1687 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1688 "rv %d, errno = %d", getpid (), fd, fd,
1689 func_str, size, errno_val);
1690 errno = errno_val;
1691 }
1692 else
1693 clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1694 getpid (), fd, fd, size, size);
1695 }
1696 return size;
1697}
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001698#endif
1699
Dave Wallace048b1d62018-01-03 22:24:41 -05001700ssize_t
1701recvmsg (int fd, struct msghdr * message, int flags)
1702{
Florin Coras7baeb712019-01-04 17:05:43 -08001703 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001704 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001705
Dave Wallace2a865272018-02-07 21:00:42 -05001706 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001707 return -1;
1708
Florin Coras7baeb712019-01-04 17:05:43 -08001709 vlsh = ldp_fd_to_vlsh (fd);
1710 if (vlsh != VLS_INVALID_HANDLE)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001711 {
Florin Coras7baeb712019-01-04 17:05:43 -08001712 LDBG (0, "LDP-TBD");
Dave Wallace048b1d62018-01-03 22:24:41 -05001713 errno = ENOSYS;
1714 size = -1;
1715 }
1716 else
1717 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001718 size = libc_recvmsg (fd, message, flags);
1719 }
1720
Dave Wallace048b1d62018-01-03 22:24:41 -05001721 return size;
1722}
1723
1724#ifdef USE_GNU
1725int
1726recvmmsg (int fd, struct mmsghdr *vmessages,
1727 unsigned int vlen, int flags, struct timespec *tmo)
1728{
1729 ssize_t size;
1730 const char *func_str;
Florin Coras7baeb712019-01-04 17:05:43 -08001731 u32 sh = ldp_fd_to_vlsh (fd);
Dave Wallace048b1d62018-01-03 22:24:41 -05001732
Dave Wallace2a865272018-02-07 21:00:42 -05001733 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001734 return -1;
1735
Florin Coras7baeb712019-01-04 17:05:43 -08001736 if (sh != INVALID_SESSION_ID)
Dave Wallace048b1d62018-01-03 22:24:41 -05001737 {
1738 clib_warning ("LDP<%d>: LDP-TBD", getpid ());
1739 errno = ENOSYS;
1740 size = -1;
1741 }
1742 else
1743 {
1744 func_str = "libc_recvmmsg";
1745
Dave Wallace2a865272018-02-07 21:00:42 -05001746 if (LDP_DEBUG > 2)
Dave Wallace048b1d62018-01-03 22:24:41 -05001747 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1748 "vmessages %p, vlen %u, flags 0x%x, tmo %p",
1749 getpid (), fd, fd, func_str, vmessages, vlen,
1750 flags, tmo);
1751
1752 size = libc_recvmmsg (fd, vmessages, vlen, flags, tmo);
1753 }
1754
Dave Wallace2a865272018-02-07 21:00:42 -05001755 if (LDP_DEBUG > 2)
Dave Wallace048b1d62018-01-03 22:24:41 -05001756 {
1757 if (size < 0)
1758 {
1759 int errno_val = errno;
1760 perror (func_str);
1761 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1762 "rv %d, errno = %d", getpid (), fd, fd,
1763 func_str, size, errno_val);
1764 errno = errno_val;
1765 }
1766 else
1767 clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1768 getpid (), fd, fd, size, size);
1769 }
1770 return size;
1771}
1772#endif
1773
1774int
1775getsockopt (int fd, int level, int optname,
1776 void *__restrict optval, socklen_t * __restrict optlen)
1777{
Florin Coras7baeb712019-01-04 17:05:43 -08001778 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001779 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001780
Dave Wallace2a865272018-02-07 21:00:42 -05001781 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001782 return -1;
1783
Florin Coras7baeb712019-01-04 17:05:43 -08001784 vlsh = ldp_fd_to_vlsh (fd);
1785 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001786 {
1787 rv = -EOPNOTSUPP;
1788
1789 switch (level)
1790 {
1791 case SOL_TCP:
1792 switch (optname)
1793 {
1794 case TCP_NODELAY:
Florin Coras7baeb712019-01-04 17:05:43 -08001795 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_NODELAY,
1796 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001797 break;
1798 case TCP_MAXSEG:
Florin Coras7baeb712019-01-04 17:05:43 -08001799 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_USER_MSS,
1800 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001801 break;
1802 case TCP_KEEPIDLE:
Florin Coras7baeb712019-01-04 17:05:43 -08001803 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_KEEPIDLE,
1804 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001805 break;
1806 case TCP_KEEPINTVL:
Florin Coras7baeb712019-01-04 17:05:43 -08001807 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_KEEPINTVL,
1808 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001809 break;
1810 case TCP_INFO:
1811 if (optval && optlen && (*optlen == sizeof (struct tcp_info)))
1812 {
Florin Coras7baeb712019-01-04 17:05:43 -08001813 LDBG (1, "fd %d: vlsh %u SOL_TCP, TCP_INFO, optval %p, "
1814 "optlen %d: #LDP-NOP#", fd, vlsh, optval, *optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001815 memset (optval, 0, *optlen);
1816 rv = VPPCOM_OK;
1817 }
1818 else
1819 rv = -EFAULT;
1820 break;
Florin Coras0ed24e92019-01-21 09:03:10 -08001821 case TCP_CONGESTION:
1822 strcpy (optval, "cubic");
1823 *optlen = strlen ("cubic");
1824 rv = 0;
1825 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05001826 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001827 LDBG (0, "ERROR: fd %d: getsockopt SOL_TCP: sid %u, "
1828 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05001829 break;
1830 }
1831 break;
1832 case SOL_IPV6:
1833 switch (optname)
1834 {
1835 case IPV6_V6ONLY:
Florin Coras7baeb712019-01-04 17:05:43 -08001836 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_V6ONLY, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001837 break;
1838 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001839 LDBG (0, "ERROR: fd %d: getsockopt SOL_IPV6: vlsh %u "
1840 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05001841 break;
1842 }
1843 break;
1844 case SOL_SOCKET:
1845 switch (optname)
1846 {
1847 case SO_ACCEPTCONN:
Florin Coras7baeb712019-01-04 17:05:43 -08001848 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_LISTEN, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001849 break;
1850 case SO_KEEPALIVE:
Florin Coras7baeb712019-01-04 17:05:43 -08001851 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_KEEPALIVE, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001852 break;
1853 case SO_PROTOCOL:
Florin Coras7baeb712019-01-04 17:05:43 -08001854 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_PROTOCOL, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001855 *(int *) optval = *(int *) optval ? SOCK_DGRAM : SOCK_STREAM;
1856 break;
1857 case SO_SNDBUF:
Florin Coras7baeb712019-01-04 17:05:43 -08001858 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TX_FIFO_LEN,
1859 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001860 break;
1861 case SO_RCVBUF:
Florin Coras7baeb712019-01-04 17:05:43 -08001862 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_RX_FIFO_LEN,
1863 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001864 break;
1865 case SO_REUSEADDR:
Florin Coras7baeb712019-01-04 17:05:43 -08001866 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_REUSEADDR, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001867 break;
1868 case SO_BROADCAST:
Florin Coras7baeb712019-01-04 17:05:43 -08001869 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_BROADCAST, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001870 break;
1871 case SO_ERROR:
Florin Coras7baeb712019-01-04 17:05:43 -08001872 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_ERROR, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001873 break;
1874 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001875 LDBG (0, "ERROR: fd %d: getsockopt SOL_SOCKET: vlsh %u "
1876 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05001877 break;
1878 }
1879 break;
1880 default:
1881 break;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001882 }
1883
Dave Wallace048b1d62018-01-03 22:24:41 -05001884 if (rv != VPPCOM_OK)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001885 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001886 errno = -rv;
1887 rv = -1;
1888 }
1889 }
1890 else
1891 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001892 rv = libc_getsockopt (fd, level, optname, optval, optlen);
1893 }
1894
Dave Wallace048b1d62018-01-03 22:24:41 -05001895 return rv;
1896}
1897
1898int
1899setsockopt (int fd, int level, int optname,
1900 const void *optval, socklen_t optlen)
1901{
Florin Coras7baeb712019-01-04 17:05:43 -08001902 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001903 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001904
Dave Wallace2a865272018-02-07 21:00:42 -05001905 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001906 return -1;
1907
Florin Coras7baeb712019-01-04 17:05:43 -08001908 vlsh = ldp_fd_to_vlsh (fd);
1909 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001910 {
1911 rv = -EOPNOTSUPP;
1912
1913 switch (level)
1914 {
1915 case SOL_TCP:
1916 switch (optname)
1917 {
1918 case TCP_NODELAY:
Florin Coras7baeb712019-01-04 17:05:43 -08001919 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_NODELAY,
1920 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001921 break;
1922 case TCP_MAXSEG:
Florin Coras7baeb712019-01-04 17:05:43 -08001923 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_USER_MSS,
1924 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001925 break;
1926 case TCP_KEEPIDLE:
Florin Coras7baeb712019-01-04 17:05:43 -08001927 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_KEEPIDLE,
1928 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001929 break;
1930 case TCP_KEEPINTVL:
Florin Coras7baeb712019-01-04 17:05:43 -08001931 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_KEEPINTVL,
1932 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001933 break;
Florin Coras0ed24e92019-01-21 09:03:10 -08001934 case TCP_CONGESTION:
Florin Coras8509aa22019-04-04 12:55:30 -07001935 case TCP_CORK:
Florin Coras0ed24e92019-01-21 09:03:10 -08001936 /* Ignore */
1937 rv = 0;
1938 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05001939 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001940 LDBG (0, "ERROR: fd %d: setsockopt() SOL_TCP: vlsh %u"
1941 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05001942 break;
1943 }
1944 break;
1945 case SOL_IPV6:
1946 switch (optname)
1947 {
1948 case IPV6_V6ONLY:
Florin Coras7baeb712019-01-04 17:05:43 -08001949 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_V6ONLY,
1950 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001951 break;
1952 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001953 LDBG (0, "ERROR: fd %d: setsockopt SOL_IPV6: vlsh %u"
1954 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05001955 break;
1956 }
1957 break;
1958 case SOL_SOCKET:
1959 switch (optname)
1960 {
1961 case SO_KEEPALIVE:
Florin Coras7baeb712019-01-04 17:05:43 -08001962 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_KEEPALIVE,
1963 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001964 break;
1965 case SO_REUSEADDR:
Florin Coras7baeb712019-01-04 17:05:43 -08001966 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_REUSEADDR,
1967 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001968 break;
1969 case SO_BROADCAST:
Florin Coras7baeb712019-01-04 17:05:43 -08001970 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_BROADCAST,
1971 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001972 break;
1973 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001974 LDBG (0, "ERROR: fd %d: setsockopt SOL_SOCKET: vlsh %u "
1975 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05001976 break;
1977 }
1978 break;
1979 default:
1980 break;
1981 }
1982
1983 if (rv != VPPCOM_OK)
1984 {
1985 errno = -rv;
1986 rv = -1;
1987 }
1988 }
1989 else
1990 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001991 rv = libc_setsockopt (fd, level, optname, optval, optlen);
1992 }
1993
Dave Wallace048b1d62018-01-03 22:24:41 -05001994 return rv;
1995}
1996
1997int
1998listen (int fd, int n)
1999{
Florin Coras7baeb712019-01-04 17:05:43 -08002000 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002001 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05002002
Dave Wallace2a865272018-02-07 21:00:42 -05002003 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05002004 return -1;
2005
Florin Coras7baeb712019-01-04 17:05:43 -08002006 vlsh = ldp_fd_to_vlsh (fd);
2007 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05002008 {
Florin Coras7baeb712019-01-04 17:05:43 -08002009 LDBG (0, "fd %d: calling vls_listen: vlsh %u, n %d", fd, vlsh, n);
Dave Wallace048b1d62018-01-03 22:24:41 -05002010
Florin Coras7baeb712019-01-04 17:05:43 -08002011 rv = vls_listen (vlsh, n);
Dave Wallace048b1d62018-01-03 22:24:41 -05002012 if (rv != VPPCOM_OK)
2013 {
2014 errno = -rv;
2015 rv = -1;
2016 }
2017 }
2018 else
2019 {
Florin Coras7baeb712019-01-04 17:05:43 -08002020 LDBG (0, "fd %d: calling libc_listen(): n %d", fd, n);
Dave Wallace048b1d62018-01-03 22:24:41 -05002021 rv = libc_listen (fd, n);
2022 }
2023
Florin Coras7baeb712019-01-04 17:05:43 -08002024 LDBG (1, "fd %d: returning %d", fd, rv);
Dave Wallace048b1d62018-01-03 22:24:41 -05002025 return rv;
2026}
2027
2028static inline int
Dave Wallace2a865272018-02-07 21:00:42 -05002029ldp_accept4 (int listen_fd, __SOCKADDR_ARG addr,
2030 socklen_t * __restrict addr_len, int flags)
Dave Wallace048b1d62018-01-03 22:24:41 -05002031{
Florin Coras7baeb712019-01-04 17:05:43 -08002032 vls_handle_t listen_vlsh, accept_vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002033 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05002034
Dave Wallace2a865272018-02-07 21:00:42 -05002035 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05002036 return -1;
2037
Florin Coras7baeb712019-01-04 17:05:43 -08002038 listen_vlsh = ldp_fd_to_vlsh (listen_fd);
2039 if (listen_vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05002040 {
2041 vppcom_endpt_t ep;
2042 u8 src_addr[sizeof (struct sockaddr_in6)];
Dave Wallace8aaba562018-01-18 17:21:19 -05002043 memset (&ep, 0, sizeof (ep));
Dave Wallace048b1d62018-01-03 22:24:41 -05002044 ep.ip = src_addr;
2045
Florin Coras7baeb712019-01-04 17:05:43 -08002046 LDBG (0, "listen fd %d: calling vppcom_session_accept: listen sid %u,"
2047 " ep %p, flags 0x%x", listen_fd, listen_vlsh, ep, flags);
Dave Wallace048b1d62018-01-03 22:24:41 -05002048
Florin Coras7baeb712019-01-04 17:05:43 -08002049 accept_vlsh = vls_accept (listen_vlsh, &ep, flags);
2050 if (accept_vlsh < 0)
Dave Wallace048b1d62018-01-03 22:24:41 -05002051 {
Florin Coras7baeb712019-01-04 17:05:43 -08002052 errno = -accept_vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002053 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002054 }
2055 else
2056 {
Dave Wallace2a865272018-02-07 21:00:42 -05002057 rv = ldp_copy_ep_to_sockaddr (addr, addr_len, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05002058 if (rv != VPPCOM_OK)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002059 {
Florin Coras7baeb712019-01-04 17:05:43 -08002060 (void) vls_close (accept_vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05002061 errno = -rv;
2062 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002063 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002064 else
2065 {
Florin Coras7baeb712019-01-04 17:05:43 -08002066 rv = ldp_vlsh_to_fd (accept_vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05002067 }
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002068 }
2069 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002070 else
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002071 {
Florin Coras7baeb712019-01-04 17:05:43 -08002072 LDBG (0, "listen fd %d: calling libc_accept4(): addr %p, addr_len %p,"
2073 " flags 0x%x", listen_fd, addr, addr_len, flags);
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002074
Dave Wallace048b1d62018-01-03 22:24:41 -05002075 rv = libc_accept4 (listen_fd, addr, addr_len, flags);
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002076 }
2077
Florin Coras7baeb712019-01-04 17:05:43 -08002078 LDBG (1, "listen fd %d: accept returning %d", listen_fd, rv);
Florin Coras05ecfcc2018-12-12 18:19:39 -08002079
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002080 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002081}
2082
Dave Wallace048b1d62018-01-03 22:24:41 -05002083int
2084accept4 (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len,
2085 int flags)
2086{
Dave Wallace2a865272018-02-07 21:00:42 -05002087 return ldp_accept4 (fd, addr, addr_len, flags);
Dave Wallace048b1d62018-01-03 22:24:41 -05002088}
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002089
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002090int
Dave Wallace048b1d62018-01-03 22:24:41 -05002091accept (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002092{
Dave Wallace2a865272018-02-07 21:00:42 -05002093 return ldp_accept4 (fd, addr, addr_len, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002094}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002095
Dave Wallace048b1d62018-01-03 22:24:41 -05002096int
2097shutdown (int fd, int how)
2098{
Florin Coras7baeb712019-01-04 17:05:43 -08002099 vls_handle_t vlsh;
2100 int rv = 0, flags;
2101 u32 flags_len = sizeof (flags);
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002102
Dave Wallace2a865272018-02-07 21:00:42 -05002103 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05002104 return -1;
2105
Florin Coras7baeb712019-01-04 17:05:43 -08002106 vlsh = ldp_fd_to_vlsh (fd);
2107 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05002108 {
Florin Coras7baeb712019-01-04 17:05:43 -08002109 LDBG (0, "called shutdown: fd %u vlsh %u how %d", fd, vlsh, how);
Florin Corasa7a1a222018-12-30 17:11:31 -08002110
Florin Coras7baeb712019-01-04 17:05:43 -08002111 if (vls_attr (vlsh, VPPCOM_ATTR_SET_SHUT, &how, &flags_len))
Florin Corasa7a1a222018-12-30 17:11:31 -08002112 {
Florin Coras7baeb712019-01-04 17:05:43 -08002113 close (fd);
Florin Corasa7a1a222018-12-30 17:11:31 -08002114 return -1;
2115 }
2116
Florin Coras7baeb712019-01-04 17:05:43 -08002117 if (vls_attr (vlsh, VPPCOM_ATTR_GET_SHUT, &flags, &flags_len))
2118 {
2119 close (fd);
2120 return -1;
2121 }
Florin Corasa7a1a222018-12-30 17:11:31 -08002122
Florin Coras7baeb712019-01-04 17:05:43 -08002123 if (flags == SHUT_RDWR)
Florin Corasa7a1a222018-12-30 17:11:31 -08002124 rv = close (fd);
Dave Wallace048b1d62018-01-03 22:24:41 -05002125 }
2126 else
2127 {
Florin Coras7baeb712019-01-04 17:05:43 -08002128 LDBG (0, "fd %d: calling libc_shutdown: how %d", fd, how);
Dave Wallace048b1d62018-01-03 22:24:41 -05002129 rv = libc_shutdown (fd, how);
2130 }
2131
Dave Wallace048b1d62018-01-03 22:24:41 -05002132 return rv;
2133}
2134
2135int
2136epoll_create1 (int flags)
2137{
Florin Corasdfe4cf42018-11-28 22:13:45 -08002138 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras7baeb712019-01-04 17:05:43 -08002139 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002140 int rv;
2141
Dave Wallace2a865272018-02-07 21:00:42 -05002142 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05002143 return -1;
2144
Florin Coras99368312018-08-02 10:45:44 -07002145 if (ldp->vcl_needs_real_epoll)
2146 {
Florin Coras2d9b4272019-03-11 10:14:37 -07002147 /* Make sure workers have been allocated */
2148 if (!ldp->workers)
2149 {
2150 ldp_alloc_workers ();
2151 ldpw = ldp_worker_get_current ();
2152 }
Florin Coras99368312018-08-02 10:45:44 -07002153 rv = libc_epoll_create1 (flags);
2154 ldp->vcl_needs_real_epoll = 0;
Florin Corasdfe4cf42018-11-28 22:13:45 -08002155 ldpw->vcl_mq_epfd = rv;
Florin Coras05ecfcc2018-12-12 18:19:39 -08002156 LDBG (0, "created vcl epfd %u", rv);
Florin Coras99368312018-08-02 10:45:44 -07002157 return rv;
2158 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002159
Florin Coras7baeb712019-01-04 17:05:43 -08002160 vlsh = vls_epoll_create ();
2161 if (PREDICT_FALSE (vlsh == VLS_INVALID_HANDLE))
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002162 {
Florin Coras7baeb712019-01-04 17:05:43 -08002163 errno = -vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002164 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002165 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002166 else
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002167 {
Florin Coras7baeb712019-01-04 17:05:43 -08002168 rv = ldp_vlsh_to_fd (vlsh);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002169 }
Florin Coras7baeb712019-01-04 17:05:43 -08002170 LDBG (0, "epoll_create epfd %u vlsh %u", rv, vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05002171 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002172}
2173
2174int
Dave Wallace048b1d62018-01-03 22:24:41 -05002175epoll_create (int size)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002176{
Dave Wallace048b1d62018-01-03 22:24:41 -05002177 return epoll_create1 (0);
2178}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002179
Dave Wallace048b1d62018-01-03 22:24:41 -05002180int
2181epoll_ctl (int epfd, int op, int fd, struct epoll_event *event)
2182{
Florin Coras7baeb712019-01-04 17:05:43 -08002183 vls_handle_t vep_vlsh, vlsh;
Florin Coras99368312018-08-02 10:45:44 -07002184 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05002185
Dave Wallace2a865272018-02-07 21:00:42 -05002186 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05002187 return -1;
2188
Florin Coras7baeb712019-01-04 17:05:43 -08002189 vep_vlsh = ldp_fd_to_vlsh (epfd);
2190 if (PREDICT_FALSE (vep_vlsh == VLS_INVALID_HANDLE))
Dave Wallace048b1d62018-01-03 22:24:41 -05002191 {
Dave Wallace3ee1fe12018-02-23 01:09:11 -05002192 /* The LDP epoll_create1 always creates VCL epfd's.
2193 * The app should never have a kernel base epoll fd unless it
2194 * was acquired outside of the LD_PRELOAD process context.
2195 * In any case, if we get one, punt it to libc_epoll_ctl.
2196 */
Florin Coras7baeb712019-01-04 17:05:43 -08002197 LDBG (1, "epfd %d: calling libc_epoll_ctl: op %d, fd %d"
2198 " event %p", epfd, op, fd, event);
Dave Wallace048b1d62018-01-03 22:24:41 -05002199
2200 rv = libc_epoll_ctl (epfd, op, fd, event);
Florin Coras99368312018-08-02 10:45:44 -07002201 goto done;
2202 }
2203
Florin Coras7baeb712019-01-04 17:05:43 -08002204 vlsh = ldp_fd_to_vlsh (fd);
Florin Coras99368312018-08-02 10:45:44 -07002205
Florin Coras7baeb712019-01-04 17:05:43 -08002206 LDBG (0, "epfd %d ep_vlsh %d, fd %u vlsh %d, op %u", epfd, vep_vlsh, fd,
2207 vlsh, op);
Florin Coras99368312018-08-02 10:45:44 -07002208
Florin Coras7baeb712019-01-04 17:05:43 -08002209 if (vlsh != VLS_INVALID_HANDLE)
Florin Coras99368312018-08-02 10:45:44 -07002210 {
Florin Coras7baeb712019-01-04 17:05:43 -08002211 LDBG (1, "epfd %d: calling vls_epoll_ctl: ep_vlsh %d op %d, vlsh %u,"
2212 " event %p", epfd, vep_vlsh, vlsh, event);
Florin Coras99368312018-08-02 10:45:44 -07002213
Florin Coras7baeb712019-01-04 17:05:43 -08002214 rv = vls_epoll_ctl (vep_vlsh, op, vlsh, event);
Florin Coras99368312018-08-02 10:45:44 -07002215 if (rv != VPPCOM_OK)
2216 {
2217 errno = -rv;
2218 rv = -1;
2219 }
2220 }
2221 else
2222 {
2223 int libc_epfd;
2224 u32 size = sizeof (epfd);
2225
Florin Coras7baeb712019-01-04 17:05:43 -08002226 libc_epfd = vls_attr (vep_vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
Florin Coras99368312018-08-02 10:45:44 -07002227 if (!libc_epfd)
2228 {
Florin Coras7baeb712019-01-04 17:05:43 -08002229 LDBG (1, "epfd %d, vep_vlsh %d calling libc_epoll_create1: "
2230 "EPOLL_CLOEXEC", epfd, vep_vlsh);
Florin Coras99368312018-08-02 10:45:44 -07002231
2232 libc_epfd = libc_epoll_create1 (EPOLL_CLOEXEC);
2233 if (libc_epfd < 0)
2234 {
2235 rv = libc_epfd;
2236 goto done;
2237 }
2238
Florin Coras7baeb712019-01-04 17:05:43 -08002239 rv = vls_attr (vep_vlsh, VPPCOM_ATTR_SET_LIBC_EPFD, &libc_epfd,
2240 &size);
Florin Coras99368312018-08-02 10:45:44 -07002241 if (rv < 0)
2242 {
2243 errno = -rv;
2244 rv = -1;
2245 goto done;
2246 }
2247 }
2248 else if (PREDICT_FALSE (libc_epfd < 0))
2249 {
2250 errno = -epfd;
2251 rv = -1;
2252 goto done;
2253 }
2254
Florin Coras7baeb712019-01-04 17:05:43 -08002255 LDBG (1, "epfd %d: calling libc_epoll_ctl: libc_epfd %d, op %d, fd %d,"
2256 " event %p", epfd, libc_epfd, op, fd, event);
Florin Coras99368312018-08-02 10:45:44 -07002257
2258 rv = libc_epoll_ctl (libc_epfd, op, fd, event);
Dave Wallace048b1d62018-01-03 22:24:41 -05002259 }
2260
2261done:
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002262 return rv;
2263}
Dave Wallace048b1d62018-01-03 22:24:41 -05002264
2265static inline int
Florin Coras99368312018-08-02 10:45:44 -07002266ldp_epoll_pwait (int epfd, struct epoll_event *events, int maxevents,
2267 int timeout, const sigset_t * sigmask)
Dave Wallace048b1d62018-01-03 22:24:41 -05002268{
Florin Corasdfe4cf42018-11-28 22:13:45 -08002269 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras72f77822019-01-22 19:05:52 -08002270 double time_to_wait = (double) 0, max_time;
Florin Coras99368312018-08-02 10:45:44 -07002271 int libc_epfd, rv = 0;
Florin Coras7baeb712019-01-04 17:05:43 -08002272 vls_handle_t ep_vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002273
Dave Wallace2a865272018-02-07 21:00:42 -05002274 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05002275 return -1;
2276
2277 if (PREDICT_FALSE (!events || (timeout < -1)))
2278 {
2279 errno = EFAULT;
2280 return -1;
2281 }
2282
Florin Corasdfe4cf42018-11-28 22:13:45 -08002283 if (epfd == ldpw->vcl_mq_epfd)
Florin Coras99368312018-08-02 10:45:44 -07002284 return libc_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
2285
Florin Coras7baeb712019-01-04 17:05:43 -08002286 ep_vlsh = ldp_fd_to_vlsh (epfd);
2287 if (PREDICT_FALSE (ep_vlsh == VLS_INVALID_HANDLE))
Dave Wallace048b1d62018-01-03 22:24:41 -05002288 {
Florin Coras7baeb712019-01-04 17:05:43 -08002289 LDBG (0, "epfd %d: bad ep_vlsh %d!", epfd, ep_vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05002290 errno = EBADFD;
2291 return -1;
2292 }
2293
Florin Coras4dee8cd2019-01-29 21:28:16 -08002294 if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
2295 clib_time_init (&ldpw->clib_time);
Florin Corasb0f662f2018-12-27 14:51:46 -08002296 time_to_wait = ((timeout >= 0) ? (double) timeout / 1000 : 0);
Florin Coras72f77822019-01-22 19:05:52 -08002297 max_time = clib_time_now (&ldpw->clib_time) + time_to_wait;
Dave Wallace048b1d62018-01-03 22:24:41 -05002298
Florin Coras7baeb712019-01-04 17:05:43 -08002299 libc_epfd = vls_attr (ep_vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002300 if (PREDICT_FALSE (libc_epfd < 0))
2301 {
2302 errno = -libc_epfd;
2303 rv = -1;
2304 goto done;
2305 }
2306
Florin Coras7baeb712019-01-04 17:05:43 -08002307 LDBG (2, "epfd %d: vep_idx %d, libc_epfd %d, events %p, maxevents %d, "
2308 "timeout %d, sigmask %p: time_to_wait %.02f", epfd, ep_vlsh,
Florin Coras72f77822019-01-22 19:05:52 -08002309 libc_epfd, events, maxevents, timeout, sigmask, time_to_wait);
Dave Wallace048b1d62018-01-03 22:24:41 -05002310 do
2311 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002312 if (!ldpw->epoll_wait_vcl)
Dave Wallace048b1d62018-01-03 22:24:41 -05002313 {
Florin Coras7baeb712019-01-04 17:05:43 -08002314 rv = vls_epoll_wait (ep_vlsh, events, maxevents, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002315 if (rv > 0)
2316 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002317 ldpw->epoll_wait_vcl = 1;
Dave Wallace048b1d62018-01-03 22:24:41 -05002318 goto done;
2319 }
2320 else if (rv < 0)
2321 {
2322 errno = -rv;
2323 rv = -1;
2324 goto done;
2325 }
2326 }
2327 else
Florin Corasdfe4cf42018-11-28 22:13:45 -08002328 ldpw->epoll_wait_vcl = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -05002329
2330 if (libc_epfd > 0)
2331 {
Florin Corasb0f662f2018-12-27 14:51:46 -08002332 rv = libc_epoll_pwait (libc_epfd, events, maxevents, 0, sigmask);
Dave Wallace048b1d62018-01-03 22:24:41 -05002333 if (rv != 0)
2334 goto done;
2335 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002336 }
Florin Coras72f77822019-01-22 19:05:52 -08002337 while ((timeout == -1) || (clib_time_now (&ldpw->clib_time) < max_time));
Dave Wallace048b1d62018-01-03 22:24:41 -05002338
2339done:
Dave Wallace048b1d62018-01-03 22:24:41 -05002340 return rv;
2341}
2342
2343int
2344epoll_pwait (int epfd, struct epoll_event *events,
2345 int maxevents, int timeout, const sigset_t * sigmask)
2346{
Dave Wallace2a865272018-02-07 21:00:42 -05002347 return ldp_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
Dave Wallace048b1d62018-01-03 22:24:41 -05002348}
2349
2350int
2351epoll_wait (int epfd, struct epoll_event *events, int maxevents, int timeout)
2352{
Dave Wallace2a865272018-02-07 21:00:42 -05002353 return ldp_epoll_pwait (epfd, events, maxevents, timeout, NULL);
Dave Wallace048b1d62018-01-03 22:24:41 -05002354}
2355
2356int
2357poll (struct pollfd *fds, nfds_t nfds, int timeout)
2358{
Florin Corasdfe4cf42018-11-28 22:13:45 -08002359 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras6917b942018-11-13 22:44:54 -08002360 int rv, i, n_revents = 0;
Florin Coras7baeb712019-01-04 17:05:43 -08002361 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002362 vcl_poll_t *vp;
Florin Coras4dee8cd2019-01-29 21:28:16 -08002363 double max_time;
Dave Wallace048b1d62018-01-03 22:24:41 -05002364
Florin Coras05ecfcc2018-12-12 18:19:39 -08002365 LDBG (3, "fds %p, nfds %d, timeout %d", fds, nfds, timeout);
Dave Wallace048b1d62018-01-03 22:24:41 -05002366
Florin Coras4dee8cd2019-01-29 21:28:16 -08002367 if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
2368 clib_time_init (&ldpw->clib_time);
2369
2370 max_time = (timeout >= 0) ? (f64) timeout / 1000 : 0;
2371 max_time += clib_time_now (&ldpw->clib_time);
Dave Wallace048b1d62018-01-03 22:24:41 -05002372
Dave Wallace048b1d62018-01-03 22:24:41 -05002373 for (i = 0; i < nfds; i++)
2374 {
Florin Coras6917b942018-11-13 22:44:54 -08002375 if (fds[i].fd < 0)
2376 continue;
Dave Wallace048b1d62018-01-03 22:24:41 -05002377
Florin Coras7baeb712019-01-04 17:05:43 -08002378 vlsh = ldp_fd_to_vlsh (fds[i].fd);
2379 if (vlsh != VLS_INVALID_HANDLE)
Florin Coras6917b942018-11-13 22:44:54 -08002380 {
2381 fds[i].fd = -fds[i].fd;
Florin Corasdfe4cf42018-11-28 22:13:45 -08002382 vec_add2 (ldpw->vcl_poll, vp, 1);
Florin Coras6917b942018-11-13 22:44:54 -08002383 vp->fds_ndx = i;
Florin Coras7baeb712019-01-04 17:05:43 -08002384 vp->sh = vlsh_to_sh (vlsh);
Florin Coras6917b942018-11-13 22:44:54 -08002385 vp->events = fds[i].events;
Dave Wallace048b1d62018-01-03 22:24:41 -05002386#ifdef __USE_XOPEN2K
Florin Coras6917b942018-11-13 22:44:54 -08002387 if (fds[i].events & POLLRDNORM)
2388 vp->events |= POLLIN;
2389 if (fds[i].events & POLLWRNORM)
2390 vp->events |= POLLOUT;
Dave Wallace048b1d62018-01-03 22:24:41 -05002391#endif
Florin Coras6917b942018-11-13 22:44:54 -08002392 vp->revents = fds[i].revents;
2393 }
2394 else
2395 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002396 vec_add1 (ldpw->libc_poll, fds[i]);
2397 vec_add1 (ldpw->libc_poll_idxs, i);
Dave Wallace048b1d62018-01-03 22:24:41 -05002398 }
2399 }
2400
Dave Wallace048b1d62018-01-03 22:24:41 -05002401 do
2402 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002403 if (vec_len (ldpw->vcl_poll))
Dave Wallace048b1d62018-01-03 22:24:41 -05002404 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002405 rv = vppcom_poll (ldpw->vcl_poll, vec_len (ldpw->vcl_poll), 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002406 if (rv < 0)
2407 {
2408 errno = -rv;
2409 rv = -1;
2410 goto done;
2411 }
2412 else
2413 n_revents += rv;
2414 }
2415
Florin Corasdfe4cf42018-11-28 22:13:45 -08002416 if (vec_len (ldpw->libc_poll))
Dave Wallace048b1d62018-01-03 22:24:41 -05002417 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002418 rv = libc_poll (ldpw->libc_poll, vec_len (ldpw->libc_poll), 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002419 if (rv < 0)
2420 goto done;
2421 else
2422 n_revents += rv;
2423 }
2424
2425 if (n_revents)
2426 {
2427 rv = n_revents;
2428 goto done;
2429 }
2430 }
Florin Coras4dee8cd2019-01-29 21:28:16 -08002431 while ((timeout < 0) || (clib_time_now (&ldpw->clib_time) < max_time));
Dave Wallace048b1d62018-01-03 22:24:41 -05002432 rv = 0;
2433
2434done:
Florin Corasdfe4cf42018-11-28 22:13:45 -08002435 vec_foreach (vp, ldpw->vcl_poll)
Dave Wallace048b1d62018-01-03 22:24:41 -05002436 {
2437 fds[vp->fds_ndx].fd = -fds[vp->fds_ndx].fd;
Florin Coras6917b942018-11-13 22:44:54 -08002438 fds[vp->fds_ndx].revents = vp->revents;
Dave Wallace048b1d62018-01-03 22:24:41 -05002439#ifdef __USE_XOPEN2K
2440 if ((fds[vp->fds_ndx].revents & POLLIN) &&
2441 (fds[vp->fds_ndx].events & POLLRDNORM))
2442 fds[vp->fds_ndx].revents |= POLLRDNORM;
2443 if ((fds[vp->fds_ndx].revents & POLLOUT) &&
2444 (fds[vp->fds_ndx].events & POLLWRNORM))
2445 fds[vp->fds_ndx].revents |= POLLWRNORM;
2446#endif
2447 }
Florin Corasdfe4cf42018-11-28 22:13:45 -08002448 vec_reset_length (ldpw->vcl_poll);
Dave Wallace048b1d62018-01-03 22:24:41 -05002449
Florin Corasdfe4cf42018-11-28 22:13:45 -08002450 for (i = 0; i < vec_len (ldpw->libc_poll); i++)
Florin Coras6917b942018-11-13 22:44:54 -08002451 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002452 fds[ldpw->libc_poll_idxs[i]].revents = ldpw->libc_poll[i].revents;
Florin Coras6917b942018-11-13 22:44:54 -08002453 }
Florin Corasdfe4cf42018-11-28 22:13:45 -08002454 vec_reset_length (ldpw->libc_poll_idxs);
2455 vec_reset_length (ldpw->libc_poll);
Florin Coras6917b942018-11-13 22:44:54 -08002456
Dave Wallace048b1d62018-01-03 22:24:41 -05002457 return rv;
2458}
2459
2460#ifdef USE_GNU
2461int
2462ppoll (struct pollfd *fds, nfds_t nfds,
2463 const struct timespec *timeout, const sigset_t * sigmask)
2464{
Dave Wallace2a865272018-02-07 21:00:42 -05002465 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05002466 return -1;
2467
2468 clib_warning ("LDP<%d>: LDP-TBD", getpid ());
2469 errno = ENOSYS;
2470
2471
2472 return -1;
2473}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002474#endif
2475
Dave Wallace2a865272018-02-07 21:00:42 -05002476void CONSTRUCTOR_ATTRIBUTE ldp_constructor (void);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002477
Dave Wallace2a865272018-02-07 21:00:42 -05002478void DESTRUCTOR_ATTRIBUTE ldp_destructor (void);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002479
Dave Wallace048b1d62018-01-03 22:24:41 -05002480/*
2481 * This function is called when the library is loaded
2482 */
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002483void
Dave Wallace2a865272018-02-07 21:00:42 -05002484ldp_constructor (void)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002485{
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002486 swrap_constructor ();
Dave Wallace2a865272018-02-07 21:00:42 -05002487 if (ldp_init () != 0)
Florin Corasd89411e2019-03-19 19:44:51 -07002488 {
2489 fprintf (stderr, "\nLDP<%d>: ERROR: ldp_constructor: failed!\n",
2490 getpid ());
2491 _exit (1);
2492 }
Dave Wallace69d01192018-02-22 16:22:09 -05002493 else if (LDP_DEBUG > 0)
Dave Wallace2a865272018-02-07 21:00:42 -05002494 clib_warning ("LDP<%d>: LDP constructor: done!\n", getpid ());
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002495}
2496
2497/*
2498 * This function is called when the library is unloaded
2499 */
2500void
Dave Wallace2a865272018-02-07 21:00:42 -05002501ldp_destructor (void)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002502{
Florin Coras0ef8ef22019-01-18 08:37:13 -08002503 /*
2504 swrap_destructor ();
2505 if (ldp->init)
2506 ldp->init = 0;
2507 */
Dave Wallace048b1d62018-01-03 22:24:41 -05002508
2509 /* Don't use clib_warning() here because that calls writev()
Dave Wallace2a865272018-02-07 21:00:42 -05002510 * which will call ldp_init().
Dave Wallace048b1d62018-01-03 22:24:41 -05002511 */
Dave Wallace69d01192018-02-22 16:22:09 -05002512 if (LDP_DEBUG > 0)
Florin Coras0ef8ef22019-01-18 08:37:13 -08002513 fprintf (stderr, "%s:%d: LDP<%d>: LDP destructor: done!\n",
2514 __func__, __LINE__, getpid ());
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002515}
2516
2517
2518/*
2519 * fd.io coding-style-patch-verification: ON
2520 *
2521 * Local Variables:
2522 * eval: (c-set-style "gnu")
2523 * End:
2524 */