blob: 6dc44ece42fca6fee57b98551de565d32754e260 [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;
Florin Corasdfe4cf42018-11-28 22:13:45 -0800102
103 /** vcl needs next epoll_create to go to libc_epoll */
104 u8 vcl_needs_real_epoll;
Dave Wallace2a865272018-02-07 21:00:42 -0500105} ldp_main_t;
Florin Corasdfe4cf42018-11-28 22:13:45 -0800106
Dave Wallace2a865272018-02-07 21:00:42 -0500107#define LDP_DEBUG ldp->debug
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700108
Florin Coras99368312018-08-02 10:45:44 -0700109#define LDBG(_lvl, _fmt, _args...) \
110 if (ldp->debug > _lvl) \
Florin Coras05ecfcc2018-12-12 18:19:39 -0800111 clib_warning ("ldp<%d>: " _fmt, getpid(), ##_args)
Florin Coras99368312018-08-02 10:45:44 -0700112
Dave Wallace2a865272018-02-07 21:00:42 -0500113static ldp_main_t ldp_main = {
Florin Coras7baeb712019-01-04 17:05:43 -0800114 .vlsh_bit_val = (1 << LDP_SID_BIT_MIN),
115 .vlsh_bit_mask = (1 << LDP_SID_BIT_MIN) - 1,
Dave Wallace2a865272018-02-07 21:00:42 -0500116 .debug = LDP_DEBUG_INIT,
Dave Wallace048b1d62018-01-03 22:24:41 -0500117};
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700118
Dave Wallace2a865272018-02-07 21:00:42 -0500119static ldp_main_t *ldp = &ldp_main;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700120
Florin Corasdfe4cf42018-11-28 22:13:45 -0800121static inline ldp_worker_ctx_t *
122ldp_worker_get_current (void)
123{
124 return (ldp->workers + vppcom_worker_index ());
125}
126
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700127/*
128 * RETURN: 0 on success or -1 on error.
129 * */
Dave Wallace048b1d62018-01-03 22:24:41 -0500130static inline void
Dave Wallace2a865272018-02-07 21:00:42 -0500131ldp_set_app_name (char *app_name)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700132{
Dave Wallace2a865272018-02-07 21:00:42 -0500133 int rv = snprintf (ldp->app_name, LDP_APP_NAME_MAX,
134 "ldp-%d-%s", getpid (), app_name);
Dave Wallace048b1d62018-01-03 22:24:41 -0500135
Dave Wallace2a865272018-02-07 21:00:42 -0500136 if (rv >= LDP_APP_NAME_MAX)
137 app_name[LDP_APP_NAME_MAX - 1] = 0;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700138}
139
Dave Wallace048b1d62018-01-03 22:24:41 -0500140static inline char *
Dave Wallace2a865272018-02-07 21:00:42 -0500141ldp_get_app_name ()
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700142{
Dave Wallace2a865272018-02-07 21:00:42 -0500143 if (ldp->app_name[0] == '\0')
144 ldp_set_app_name ("app");
Dave Wallace048b1d62018-01-03 22:24:41 -0500145
Dave Wallace2a865272018-02-07 21:00:42 -0500146 return ldp->app_name;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700147}
148
Dave Wallace048b1d62018-01-03 22:24:41 -0500149static inline int
Florin Coras7baeb712019-01-04 17:05:43 -0800150ldp_vlsh_to_fd (vls_handle_t vlsh)
Dave Wallace048b1d62018-01-03 22:24:41 -0500151{
Florin Coras7baeb712019-01-04 17:05:43 -0800152 return (vlsh + ldp->vlsh_bit_val);
Dave Wallace048b1d62018-01-03 22:24:41 -0500153}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700154
Florin Coras7baeb712019-01-04 17:05:43 -0800155static inline vls_handle_t
156ldp_fd_to_vlsh (int fd)
Dave Wallace048b1d62018-01-03 22:24:41 -0500157{
Florin Coras7baeb712019-01-04 17:05:43 -0800158 if (fd < ldp->vlsh_bit_val)
159 return VLS_INVALID_HANDLE;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700160
Florin Coras7baeb712019-01-04 17:05:43 -0800161 return (fd - ldp->vlsh_bit_val);
Dave Wallace048b1d62018-01-03 22:24:41 -0500162}
163
Florin Coras2d9b4272019-03-11 10:14:37 -0700164static void
165ldp_alloc_workers (void)
166{
167 if (ldp->workers)
168 return;
169 pool_alloc (ldp->workers, LDP_MAX_NWORKERS);
170}
171
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700172static inline int
Dave Wallace2a865272018-02-07 21:00:42 -0500173ldp_init (void)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700174{
Florin Corasdfe4cf42018-11-28 22:13:45 -0800175 ldp_worker_ctx_t *ldpw;
Florin Coras99368312018-08-02 10:45:44 -0700176 int rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700177
Florin Coras99368312018-08-02 10:45:44 -0700178 if (PREDICT_TRUE (ldp->init))
179 return 0;
180
181 ldp->init = 1;
182 ldp->vcl_needs_real_epoll = 1;
Florin Coras7baeb712019-01-04 17:05:43 -0800183 rv = vls_app_create (ldp_get_app_name ());
Florin Coras99368312018-08-02 10:45:44 -0700184 if (rv != VPPCOM_OK)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700185 {
Florin Coras955bfbb2018-12-04 13:43:45 -0800186 ldp->vcl_needs_real_epoll = 0;
187 if (rv == VPPCOM_EEXIST)
188 return 0;
Florin Coras05ecfcc2018-12-12 18:19:39 -0800189 LDBG (2, "\nERROR: ldp_init: vppcom_app_create()"
190 " failed! rv = %d (%s)\n", rv, vppcom_retval_str (rv));
Florin Coras99368312018-08-02 10:45:44 -0700191 ldp->init = 0;
192 return rv;
193 }
194 ldp->vcl_needs_real_epoll = 0;
Florin Coras2d9b4272019-03-11 10:14:37 -0700195 ldp_alloc_workers ();
Florin Corasdfe4cf42018-11-28 22:13:45 -0800196 ldpw = ldp_worker_get_current ();
Florin Coras99368312018-08-02 10:45:44 -0700197
198 char *env_var_str = getenv (LDP_ENV_DEBUG);
199 if (env_var_str)
200 {
201 u32 tmp;
202 if (sscanf (env_var_str, "%u", &tmp) != 1)
203 clib_warning ("LDP<%d>: WARNING: Invalid LDP debug level specified in"
204 " the env var " LDP_ENV_DEBUG " (%s)!", getpid (),
205 env_var_str);
206 else
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700207 {
Florin Coras99368312018-08-02 10:45:44 -0700208 ldp->debug = tmp;
Florin Coras05ecfcc2018-12-12 18:19:39 -0800209 LDBG (0, "configured LDP debug level (%u) from env var "
210 LDP_ENV_DEBUG "!", ldp->debug);
Florin Coras99368312018-08-02 10:45:44 -0700211 }
212 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500213
Florin Coras99368312018-08-02 10:45:44 -0700214 env_var_str = getenv (LDP_ENV_APP_NAME);
215 if (env_var_str)
216 {
217 ldp_set_app_name (env_var_str);
Florin Coras05ecfcc2018-12-12 18:19:39 -0800218 LDBG (0, "configured LDP app name (%s) from the env var "
219 LDP_ENV_APP_NAME "!", ldp->app_name);
Florin Coras99368312018-08-02 10:45:44 -0700220 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500221
Florin Coras99368312018-08-02 10:45:44 -0700222 env_var_str = getenv (LDP_ENV_SID_BIT);
223 if (env_var_str)
224 {
225 u32 sb;
226 if (sscanf (env_var_str, "%u", &sb) != 1)
227 {
Florin Coras294afe22019-01-07 17:49:17 -0800228 LDBG (0, "WARNING: Invalid LDP sid bit specified in the env var "
229 LDP_ENV_SID_BIT " (%s)! sid bit value %d (0x%x)", env_var_str,
230 ldp->vlsh_bit_val, ldp->vlsh_bit_val);
Florin Coras99368312018-08-02 10:45:44 -0700231 }
232 else if (sb < LDP_SID_BIT_MIN)
233 {
Florin Coras7baeb712019-01-04 17:05:43 -0800234 ldp->vlsh_bit_val = (1 << LDP_SID_BIT_MIN);
235 ldp->vlsh_bit_mask = ldp->vlsh_bit_val - 1;
Dave Wallace048b1d62018-01-03 22:24:41 -0500236
Florin Coras294afe22019-01-07 17:49:17 -0800237 LDBG (0, "WARNING: LDP sid bit (%u) specified in the env var "
238 LDP_ENV_SID_BIT " (%s) is too small. Using LDP_SID_BIT_MIN"
239 " (%d)! sid bit value %d (0x%x)", sb, env_var_str,
240 LDP_SID_BIT_MIN, ldp->vlsh_bit_val, ldp->vlsh_bit_val);
Florin Coras99368312018-08-02 10:45:44 -0700241 }
242 else if (sb > LDP_SID_BIT_MAX)
243 {
Florin Coras7baeb712019-01-04 17:05:43 -0800244 ldp->vlsh_bit_val = (1 << LDP_SID_BIT_MAX);
245 ldp->vlsh_bit_mask = ldp->vlsh_bit_val - 1;
Dave Wallace048b1d62018-01-03 22:24:41 -0500246
Florin Coras294afe22019-01-07 17:49:17 -0800247 LDBG (0, "WARNING: LDP sid bit (%u) specified in the env var "
248 LDP_ENV_SID_BIT " (%s) is too big. Using LDP_SID_BIT_MAX"
249 " (%d)! sid bit value %d (0x%x)", sb, env_var_str,
250 LDP_SID_BIT_MAX, ldp->vlsh_bit_val, ldp->vlsh_bit_val);
Dave Wallace048b1d62018-01-03 22:24:41 -0500251 }
252 else
253 {
Florin Coras7baeb712019-01-04 17:05:43 -0800254 ldp->vlsh_bit_val = (1 << sb);
255 ldp->vlsh_bit_mask = ldp->vlsh_bit_val - 1;
Florin Coras99368312018-08-02 10:45:44 -0700256
Florin Coras05ecfcc2018-12-12 18:19:39 -0800257 LDBG (0, "configured LDP sid bit (%u) from "
258 LDP_ENV_SID_BIT "! sid bit value %d (0x%x)", sb,
Florin Coras7baeb712019-01-04 17:05:43 -0800259 ldp->vlsh_bit_val, ldp->vlsh_bit_val);
Dave Wallace048b1d62018-01-03 22:24:41 -0500260 }
Florin Coras294afe22019-01-07 17:49:17 -0800261
262 /* Make sure there are enough bits in the fd set for vcl sessions */
263 if (ldp->vlsh_bit_val > FD_SETSIZE / 2)
264 {
265 LDBG (0, "ERROR: LDP vlsh bit value %d > FD_SETSIZE/2 %d!",
266 ldp->vlsh_bit_val, FD_SETSIZE / 2);
267 ldp->init = 0;
268 return -1;
269 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500270 }
Florin Coras99368312018-08-02 10:45:44 -0700271
Florin Coras4dee8cd2019-01-29 21:28:16 -0800272 /* *INDENT-OFF* */
273 pool_foreach (ldpw, ldp->workers, ({
274 clib_memset (&ldpw->clib_time, 0, sizeof (ldpw->clib_time));
275 }));
276 /* *INDENT-ON* */
277
Florin Coras05ecfcc2018-12-12 18:19:39 -0800278 LDBG (0, "LDP initialization: done!");
Florin Coras99368312018-08-02 10:45:44 -0700279
280 return 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500281}
282
283int
284close (int fd)
285{
Florin Coras7baeb712019-01-04 17:05:43 -0800286 vls_handle_t vlsh;
287 int rv, epfd;
Dave Wallace048b1d62018-01-03 22:24:41 -0500288
Dave Wallace2a865272018-02-07 21:00:42 -0500289 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500290 return -1;
291
Florin Coras7baeb712019-01-04 17:05:43 -0800292 vlsh = ldp_fd_to_vlsh (fd);
293 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500294 {
Florin Coras7baeb712019-01-04 17:05:43 -0800295 epfd = vls_attr (vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -0500296 if (epfd > 0)
297 {
Florin Coras7baeb712019-01-04 17:05:43 -0800298 LDBG (0, "fd %d: calling libc_close: epfd %u", fd, epfd);
Dave Wallace048b1d62018-01-03 22:24:41 -0500299
300 rv = libc_close (epfd);
301 if (rv < 0)
302 {
303 u32 size = sizeof (epfd);
304 epfd = 0;
305
Florin Coras7baeb712019-01-04 17:05:43 -0800306 (void) vls_attr (vlsh, VPPCOM_ATTR_SET_LIBC_EPFD, &epfd, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -0500307 }
308 }
309 else if (PREDICT_FALSE (epfd < 0))
310 {
311 errno = -epfd;
312 rv = -1;
313 goto done;
314 }
315
Florin Coras7baeb712019-01-04 17:05:43 -0800316 LDBG (0, "fd %d: calling vls_close: vlsh %u", fd, vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -0500317
Florin Coras7baeb712019-01-04 17:05:43 -0800318 rv = vls_close (vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -0500319 if (rv != VPPCOM_OK)
320 {
321 errno = -rv;
322 rv = -1;
323 }
324 }
325 else
326 {
Florin Coras7baeb712019-01-04 17:05:43 -0800327 LDBG (0, "fd %d: calling libc_close", fd);
Dave Wallace048b1d62018-01-03 22:24:41 -0500328 rv = libc_close (fd);
329 }
330
331done:
Dave Wallace048b1d62018-01-03 22:24:41 -0500332 return rv;
333}
334
335ssize_t
336read (int fd, void *buf, size_t nbytes)
337{
Florin Coras7baeb712019-01-04 17:05:43 -0800338 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500339 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -0500340
Dave Wallace2a865272018-02-07 21:00:42 -0500341 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500342 return -1;
343
Florin Coras7baeb712019-01-04 17:05:43 -0800344 vlsh = ldp_fd_to_vlsh (fd);
345 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500346 {
Florin Coras7baeb712019-01-04 17:05:43 -0800347 size = vls_read (vlsh, buf, nbytes);
Dave Wallace048b1d62018-01-03 22:24:41 -0500348 if (size < 0)
349 {
350 errno = -size;
351 size = -1;
352 }
353 }
354 else
355 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500356 size = libc_read (fd, buf, nbytes);
357 }
358
Dave Wallace048b1d62018-01-03 22:24:41 -0500359 return size;
360}
361
362ssize_t
363readv (int fd, const struct iovec * iov, int iovcnt)
364{
Dave Wallace8aaba562018-01-18 17:21:19 -0500365 int rv = 0, i, total = 0;
Florin Coras7baeb712019-01-04 17:05:43 -0800366 vls_handle_t vlsh;
367 ssize_t size = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500368
Dave Wallace2a865272018-02-07 21:00:42 -0500369 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500370 return -1;
371
Florin Coras7baeb712019-01-04 17:05:43 -0800372 vlsh = ldp_fd_to_vlsh (fd);
373 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500374 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500375 do
376 {
377 for (i = 0; i < iovcnt; ++i)
378 {
Florin Coras7baeb712019-01-04 17:05:43 -0800379 rv = vls_read (vlsh, iov[i].iov_base, iov[i].iov_len);
Dave Wallace048b1d62018-01-03 22:24:41 -0500380 if (rv < 0)
381 break;
382 else
383 {
384 total += rv;
385 if (rv < iov[i].iov_len)
Florin Coras7baeb712019-01-04 17:05:43 -0800386 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700387 }
388 }
389 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500390 while ((rv >= 0) && (total == 0));
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700391
Dave Wallace048b1d62018-01-03 22:24:41 -0500392 if (rv < 0)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700393 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500394 errno = -rv;
395 size = -1;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700396 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500397 else
398 size = total;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700399 }
400 else
401 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500402 size = libc_readv (fd, iov, iovcnt);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700403 }
404
Dave Wallace048b1d62018-01-03 22:24:41 -0500405 return size;
406}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700407
Dave Wallace048b1d62018-01-03 22:24:41 -0500408ssize_t
409write (int fd, const void *buf, size_t nbytes)
410{
Florin Coras7baeb712019-01-04 17:05:43 -0800411 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500412 ssize_t size = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500413
Dave Wallace2a865272018-02-07 21:00:42 -0500414 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500415 return -1;
416
Florin Coras7baeb712019-01-04 17:05:43 -0800417 vlsh = ldp_fd_to_vlsh (fd);
418 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500419 {
Florin Coras7baeb712019-01-04 17:05:43 -0800420 size = vls_write_msg (vlsh, (void *) buf, nbytes);
Dave Wallace048b1d62018-01-03 22:24:41 -0500421 if (size < 0)
422 {
423 errno = -size;
424 size = -1;
425 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700426 }
427 else
428 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500429 size = libc_write (fd, buf, nbytes);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700430 }
431
Dave Wallace048b1d62018-01-03 22:24:41 -0500432 return size;
433}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700434
Dave Wallace048b1d62018-01-03 22:24:41 -0500435ssize_t
436writev (int fd, const struct iovec * iov, int iovcnt)
437{
Dave Wallace048b1d62018-01-03 22:24:41 -0500438 ssize_t size = 0, total = 0;
Florin Coras7baeb712019-01-04 17:05:43 -0800439 vls_handle_t vlsh;
Dave Wallace8aaba562018-01-18 17:21:19 -0500440 int i, rv = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500441
Dave Wallace2a865272018-02-07 21:00:42 -0500442 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500443 return -1;
444
Florin Coras7baeb712019-01-04 17:05:43 -0800445 vlsh = ldp_fd_to_vlsh (fd);
446 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500447 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500448 do
449 {
450 for (i = 0; i < iovcnt; ++i)
451 {
Florin Coras7baeb712019-01-04 17:05:43 -0800452 rv = vls_write_msg (vlsh, iov[i].iov_base, iov[i].iov_len);
Dave Wallace048b1d62018-01-03 22:24:41 -0500453 if (rv < 0)
454 break;
455 else
456 {
457 total += rv;
458 if (rv < iov[i].iov_len)
Florin Corasb0f662f2018-12-27 14:51:46 -0800459 break;
Dave Wallace048b1d62018-01-03 22:24:41 -0500460 }
461 }
462 }
463 while ((rv >= 0) && (total == 0));
464
465 if (rv < 0)
466 {
467 errno = -rv;
468 size = -1;
469 }
470 else
471 size = total;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700472 }
473 else
474 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500475 size = libc_writev (fd, iov, iovcnt);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700476 }
477
Dave Wallace048b1d62018-01-03 22:24:41 -0500478 return size;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700479}
480
481int
Dave Wallace048b1d62018-01-03 22:24:41 -0500482fcntl (int fd, int cmd, ...)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700483{
Florin Coras7baeb712019-01-04 17:05:43 -0800484 vls_handle_t vlsh;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700485 int rv = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500486 va_list ap;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700487
Dave Wallace2a865272018-02-07 21:00:42 -0500488 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500489 return -1;
490
491 va_start (ap, cmd);
Florin Coras7baeb712019-01-04 17:05:43 -0800492
493 vlsh = ldp_fd_to_vlsh (fd);
494 LDBG (0, "fd %u vlsh %d, cmd %u", fd, vlsh, cmd);
495 if (vlsh != VLS_INVALID_HANDLE)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700496 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500497 int flags = va_arg (ap, int);
498 u32 size;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700499
Dave Wallace048b1d62018-01-03 22:24:41 -0500500 size = sizeof (flags);
501 rv = -EOPNOTSUPP;
502 switch (cmd)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700503 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500504 case F_SETFL:
Florin Coras7baeb712019-01-04 17:05:43 -0800505 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_FLAGS, &flags, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -0500506 break;
507
508 case F_GETFL:
Florin Coras7baeb712019-01-04 17:05:43 -0800509 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_FLAGS, &flags, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -0500510 if (rv == VPPCOM_OK)
Florin Coras7baeb712019-01-04 17:05:43 -0800511 rv = flags;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700512 break;
Florin Coras173bae32018-11-16 18:56:28 -0800513 case F_SETFD:
514 /* TODO handle this */
515 LDBG (0, "F_SETFD ignored flags %u", flags);
516 rv = 0;
517 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700518 default:
Dave Wallace048b1d62018-01-03 22:24:41 -0500519 rv = -EOPNOTSUPP;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700520 break;
521 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500522 if (rv < 0)
523 {
524 errno = -rv;
525 rv = -1;
526 }
527 }
528 else
529 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500530 rv = libc_vfcntl (fd, cmd, ap);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700531 }
532
Dave Wallace048b1d62018-01-03 22:24:41 -0500533 va_end (ap);
534
Dave Wallace048b1d62018-01-03 22:24:41 -0500535 return rv;
536}
537
538int
539ioctl (int fd, unsigned long int cmd, ...)
540{
Florin Coras7baeb712019-01-04 17:05:43 -0800541 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500542 va_list ap;
Florin Coras7baeb712019-01-04 17:05:43 -0800543 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -0500544
Dave Wallace2a865272018-02-07 21:00:42 -0500545 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500546 return -1;
547
548 va_start (ap, cmd);
Dave Wallace048b1d62018-01-03 22:24:41 -0500549
Florin Coras7baeb712019-01-04 17:05:43 -0800550 vlsh = ldp_fd_to_vlsh (fd);
551 if (vlsh != VLS_INVALID_HANDLE)
552 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500553 switch (cmd)
554 {
555 case FIONREAD:
Florin Coras7baeb712019-01-04 17:05:43 -0800556 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_NREAD, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -0500557 break;
558
559 case FIONBIO:
560 {
561 u32 flags = va_arg (ap, int) ? O_NONBLOCK : 0;
562 u32 size = sizeof (flags);
563
564 /* TBD: When VPPCOM_ATTR_[GS]ET_FLAGS supports flags other than
565 * non-blocking, the flags should be read here and merged
566 * with O_NONBLOCK.
567 */
Florin Coras7baeb712019-01-04 17:05:43 -0800568 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_FLAGS, &flags, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -0500569 }
570 break;
571
572 default:
573 rv = -EOPNOTSUPP;
574 break;
575 }
576 if (rv < 0)
577 {
578 errno = -rv;
579 rv = -1;
580 }
581 }
582 else
583 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500584 rv = libc_vioctl (fd, cmd, ap);
585 }
586
Dave Wallace048b1d62018-01-03 22:24:41 -0500587 va_end (ap);
588 return rv;
589}
590
Florin Coras294afe22019-01-07 17:49:17 -0800591always_inline void
592ldp_select_init_maps (fd_set * __restrict original,
593 clib_bitmap_t ** resultb, clib_bitmap_t ** libcb,
594 clib_bitmap_t ** vclb, int nfds, u32 minbits,
595 u32 n_bytes, uword * si_bits, uword * libc_bits)
596{
597 uword si_bits_set, libc_bits_set;
598 vls_handle_t vlsh;
599 int fd;
600
601 clib_bitmap_validate (*vclb, minbits);
602 clib_bitmap_validate (*libcb, minbits);
603 clib_bitmap_validate (*resultb, minbits);
604 clib_memcpy_fast (*resultb, original, n_bytes);
605 memset (original, 0, n_bytes);
606
607 /* *INDENT-OFF* */
608 clib_bitmap_foreach (fd, *resultb, ({
609 if (fd > nfds)
610 break;
611 vlsh = ldp_fd_to_vlsh (fd);
612 if (vlsh == VLS_INVALID_HANDLE)
613 clib_bitmap_set_no_check (*libcb, fd, 1);
614 else
615 clib_bitmap_set_no_check (*vclb, vlsh_to_session_index (vlsh), 1);
616 }));
617 /* *INDENT-ON* */
618
619 si_bits_set = clib_bitmap_last_set (*vclb) + 1;
620 *si_bits = (si_bits_set > *si_bits) ? si_bits_set : *si_bits;
621
622 libc_bits_set = clib_bitmap_last_set (*libcb) + 1;
623 *libc_bits = (libc_bits_set > *libc_bits) ? libc_bits_set : *libc_bits;
624}
625
626always_inline int
627ldp_select_vcl_map_to_libc (clib_bitmap_t * vclb, fd_set * __restrict libcb)
628{
629 vls_handle_t vlsh;
630 uword si;
631 int fd;
632
633 if (!libcb)
634 return 0;
635
636 /* *INDENT-OFF* */
637 clib_bitmap_foreach (si, vclb, ({
638 vlsh = vls_session_index_to_vlsh (si);
639 fd = ldp_vlsh_to_fd (vlsh);
640 if (PREDICT_FALSE (fd < 0))
641 {
642 errno = EBADFD;
643 return -1;
644 }
645 FD_SET (fd, libcb);
646 }));
647 /* *INDENT-ON* */
648
649 return 0;
650}
651
652always_inline void
653ldp_select_libc_map_merge (clib_bitmap_t * result, fd_set * __restrict libcb)
654{
655 uword fd;
656
Florin Coras78b5fa62019-02-21 20:04:15 -0800657 if (!libcb)
658 return;
659
Florin Coras294afe22019-01-07 17:49:17 -0800660 /* *INDENT-OFF* */
661 clib_bitmap_foreach (fd, result, ({
662 FD_SET ((int)fd, libcb);
663 }));
664 /* *INDENT-ON* */
665}
666
Dave Wallace048b1d62018-01-03 22:24:41 -0500667int
Dave Wallace2a865272018-02-07 21:00:42 -0500668ldp_pselect (int nfds, fd_set * __restrict readfds,
669 fd_set * __restrict writefds,
670 fd_set * __restrict exceptfds,
671 const struct timespec *__restrict timeout,
672 const __sigset_t * __restrict sigmask)
Dave Wallace048b1d62018-01-03 22:24:41 -0500673{
Florin Coras294afe22019-01-07 17:49:17 -0800674 u32 minbits = clib_max (nfds, BITS (uword)), n_bytes;
Florin Corasdfe4cf42018-11-28 22:13:45 -0800675 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras294afe22019-01-07 17:49:17 -0800676 struct timespec libc_tspec = { 0 };
677 f64 time_out, vcl_timeout = 0;
678 uword si_bits, libc_bits;
679 int rv, bits_set = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500680
681 if (nfds < 0)
682 {
683 errno = EINVAL;
684 return -1;
685 }
686
Florin Coras4dee8cd2019-01-29 21:28:16 -0800687 if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
688 clib_time_init (&ldpw->clib_time);
689
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500690 if (timeout)
691 {
692 time_out = (timeout->tv_sec == 0 && timeout->tv_nsec == 0) ?
Florin Coras7baeb712019-01-04 17:05:43 -0800693 (f64) 0 : (f64) timeout->tv_sec + (f64) timeout->tv_nsec / (f64) 1e9;
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500694
695 /* select as fine grained sleep */
696 if (!nfds)
697 {
Florin Corasdfe4cf42018-11-28 22:13:45 -0800698 time_out += clib_time_now (&ldpw->clib_time);
699 while (clib_time_now (&ldpw->clib_time) < time_out)
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500700 ;
701 return 0;
702 }
703 }
704 else if (!nfds)
705 {
706 errno = EINVAL;
707 return -1;
708 }
709 else
710 time_out = -1;
711
Florin Coras7baeb712019-01-04 17:05:43 -0800712 if (nfds <= ldp->vlsh_bit_val)
Dave Wallace048b1d62018-01-03 22:24:41 -0500713 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500714 rv = libc_pselect (nfds, readfds, writefds, exceptfds,
715 timeout, sigmask);
716 goto done;
717 }
718
Florin Coras294afe22019-01-07 17:49:17 -0800719 si_bits = libc_bits = 0;
720 n_bytes = nfds / 8 + ((nfds % 8) ? 1 : 0);
Florin Coras7baeb712019-01-04 17:05:43 -0800721
Dave Wallace048b1d62018-01-03 22:24:41 -0500722 if (readfds)
Florin Coras294afe22019-01-07 17:49:17 -0800723 ldp_select_init_maps (readfds, &ldpw->rd_bitmap, &ldpw->libc_rd_bitmap,
724 &ldpw->si_rd_bitmap, nfds, minbits, n_bytes,
725 &si_bits, &libc_bits);
Dave Wallace048b1d62018-01-03 22:24:41 -0500726 if (writefds)
Florin Coras294afe22019-01-07 17:49:17 -0800727 ldp_select_init_maps (writefds, &ldpw->wr_bitmap,
728 &ldpw->libc_wr_bitmap, &ldpw->si_wr_bitmap, nfds,
729 minbits, n_bytes, &si_bits, &libc_bits);
Dave Wallace048b1d62018-01-03 22:24:41 -0500730 if (exceptfds)
Florin Coras294afe22019-01-07 17:49:17 -0800731 ldp_select_init_maps (exceptfds, &ldpw->ex_bitmap,
732 &ldpw->libc_ex_bitmap, &ldpw->si_ex_bitmap, nfds,
733 minbits, n_bytes, &si_bits, &libc_bits);
Dave Wallace048b1d62018-01-03 22:24:41 -0500734
Florin Coras294afe22019-01-07 17:49:17 -0800735 if (PREDICT_FALSE (!si_bits && !libc_bits))
Dave Wallace048b1d62018-01-03 22:24:41 -0500736 {
737 errno = EINVAL;
738 rv = -1;
739 goto done;
740 }
741
Florin Coras78b5fa62019-02-21 20:04:15 -0800742 if (!si_bits)
743 libc_tspec = timeout ? *timeout : libc_tspec;
Florin Coras294afe22019-01-07 17:49:17 -0800744
Dave Wallace048b1d62018-01-03 22:24:41 -0500745 do
746 {
Florin Coras294afe22019-01-07 17:49:17 -0800747 if (si_bits)
Dave Wallace048b1d62018-01-03 22:24:41 -0500748 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500749 if (readfds)
Florin Coras294afe22019-01-07 17:49:17 -0800750 clib_memcpy_fast (ldpw->rd_bitmap, ldpw->si_rd_bitmap,
Florin Corasdfe4cf42018-11-28 22:13:45 -0800751 vec_len (ldpw->rd_bitmap) *
Dave Barach178cf492018-11-13 16:34:13 -0500752 sizeof (clib_bitmap_t));
Dave Wallace048b1d62018-01-03 22:24:41 -0500753 if (writefds)
Florin Coras294afe22019-01-07 17:49:17 -0800754 clib_memcpy_fast (ldpw->wr_bitmap, ldpw->si_wr_bitmap,
Florin Corasdfe4cf42018-11-28 22:13:45 -0800755 vec_len (ldpw->wr_bitmap) *
Dave Barach178cf492018-11-13 16:34:13 -0500756 sizeof (clib_bitmap_t));
Dave Wallace048b1d62018-01-03 22:24:41 -0500757 if (exceptfds)
Florin Coras294afe22019-01-07 17:49:17 -0800758 clib_memcpy_fast (ldpw->ex_bitmap, ldpw->si_ex_bitmap,
Florin Corasdfe4cf42018-11-28 22:13:45 -0800759 vec_len (ldpw->ex_bitmap) *
Dave Barach178cf492018-11-13 16:34:13 -0500760 sizeof (clib_bitmap_t));
Florin Coras294afe22019-01-07 17:49:17 -0800761
Florin Coras0ef8ef22019-01-18 08:37:13 -0800762 rv = vls_select (si_bits, readfds ? ldpw->rd_bitmap : NULL,
763 writefds ? ldpw->wr_bitmap : NULL,
764 exceptfds ? ldpw->ex_bitmap : NULL, vcl_timeout);
Florin Coras294afe22019-01-07 17:49:17 -0800765 if (rv < 0)
766 {
767 errno = -rv;
768 rv = -1;
769 }
770 else if (rv > 0)
771 {
772 if (ldp_select_vcl_map_to_libc (ldpw->rd_bitmap, readfds))
773 {
774 rv = -1;
775 goto done;
776 }
777
778 if (ldp_select_vcl_map_to_libc (ldpw->wr_bitmap, writefds))
779 {
780 rv = -1;
781 goto done;
782 }
783
784 if (ldp_select_vcl_map_to_libc (ldpw->ex_bitmap, exceptfds))
785 {
786 rv = -1;
787 goto done;
788 }
789 bits_set = rv;
790 }
791 }
792 if (libc_bits)
793 {
794 if (readfds)
795 clib_memcpy_fast (ldpw->rd_bitmap, ldpw->libc_rd_bitmap,
796 vec_len (ldpw->libc_rd_bitmap) *
797 sizeof (clib_bitmap_t));
798 if (writefds)
799 clib_memcpy_fast (ldpw->wr_bitmap, ldpw->libc_wr_bitmap,
800 vec_len (ldpw->libc_wr_bitmap) *
801 sizeof (clib_bitmap_t));
802 if (exceptfds)
803 clib_memcpy_fast (ldpw->ex_bitmap, ldpw->libc_ex_bitmap,
804 vec_len (ldpw->libc_ex_bitmap) *
805 sizeof (clib_bitmap_t));
806
Dave Wallace048b1d62018-01-03 22:24:41 -0500807 rv = libc_pselect (libc_bits,
Florin Coras294afe22019-01-07 17:49:17 -0800808 readfds ? (fd_set *) ldpw->rd_bitmap : NULL,
809 writefds ? (fd_set *) ldpw->wr_bitmap : NULL,
810 exceptfds ? (fd_set *) ldpw->ex_bitmap : NULL,
811 &libc_tspec, sigmask);
812 if (rv > 0)
813 {
814 ldp_select_libc_map_merge (ldpw->rd_bitmap, readfds);
815 ldp_select_libc_map_merge (ldpw->wr_bitmap, writefds);
816 ldp_select_libc_map_merge (ldpw->ex_bitmap, exceptfds);
817 bits_set += rv;
818 }
819 }
820
821 if (bits_set)
822 {
823 rv = bits_set;
824 goto done;
Dave Wallace048b1d62018-01-03 22:24:41 -0500825 }
826 }
Florin Corasdfe4cf42018-11-28 22:13:45 -0800827 while ((time_out == -1) || (clib_time_now (&ldpw->clib_time) < time_out));
Dave Wallace048b1d62018-01-03 22:24:41 -0500828 rv = 0;
829
830done:
831 /* TBD: set timeout to amount of time left */
Florin Corasdfe4cf42018-11-28 22:13:45 -0800832 clib_bitmap_zero (ldpw->rd_bitmap);
Florin Coras294afe22019-01-07 17:49:17 -0800833 clib_bitmap_zero (ldpw->si_rd_bitmap);
Florin Corasdfe4cf42018-11-28 22:13:45 -0800834 clib_bitmap_zero (ldpw->libc_rd_bitmap);
835 clib_bitmap_zero (ldpw->wr_bitmap);
Florin Coras294afe22019-01-07 17:49:17 -0800836 clib_bitmap_zero (ldpw->si_wr_bitmap);
Florin Corasdfe4cf42018-11-28 22:13:45 -0800837 clib_bitmap_zero (ldpw->libc_wr_bitmap);
838 clib_bitmap_zero (ldpw->ex_bitmap);
Florin Coras294afe22019-01-07 17:49:17 -0800839 clib_bitmap_zero (ldpw->si_ex_bitmap);
Florin Corasdfe4cf42018-11-28 22:13:45 -0800840 clib_bitmap_zero (ldpw->libc_ex_bitmap);
Dave Wallace048b1d62018-01-03 22:24:41 -0500841
Dave Wallace048b1d62018-01-03 22:24:41 -0500842 return rv;
843}
844
845int
846select (int nfds, fd_set * __restrict readfds,
847 fd_set * __restrict writefds,
848 fd_set * __restrict exceptfds, struct timeval *__restrict timeout)
849{
850 struct timespec tspec;
851
852 if (timeout)
853 {
854 tspec.tv_sec = timeout->tv_sec;
855 tspec.tv_nsec = timeout->tv_usec * 1000;
856 }
Dave Wallace2a865272018-02-07 21:00:42 -0500857 return ldp_pselect (nfds, readfds, writefds, exceptfds,
858 timeout ? &tspec : NULL, NULL);
Dave Wallace048b1d62018-01-03 22:24:41 -0500859}
860
861#ifdef __USE_XOPEN2K
862int
863pselect (int nfds, fd_set * __restrict readfds,
864 fd_set * __restrict writefds,
865 fd_set * __restrict exceptfds,
866 const struct timespec *__restrict timeout,
867 const __sigset_t * __restrict sigmask)
868{
Dave Wallace2a865272018-02-07 21:00:42 -0500869 return ldp_pselect (nfds, readfds, writefds, exceptfds, timeout, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -0500870}
871#endif
872
873int
874socket (int domain, int type, int protocol)
875{
Florin Coras7baeb712019-01-04 17:05:43 -0800876 int rv, sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
Dave Wallace048b1d62018-01-03 22:24:41 -0500877 u8 is_nonblocking = type & SOCK_NONBLOCK ? 1 : 0;
Florin Coras7baeb712019-01-04 17:05:43 -0800878 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500879
Dave Wallace2a865272018-02-07 21:00:42 -0500880 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500881 return -1;
882
883 if (((domain == AF_INET) || (domain == AF_INET6)) &&
884 ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM)))
885 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500886 u8 proto = ((sock_type == SOCK_DGRAM) ?
887 VPPCOM_PROTO_UDP : VPPCOM_PROTO_TCP);
888
Florin Coras7baeb712019-01-04 17:05:43 -0800889 LDBG (0, "calling vls_create: proto %u (%s), is_nonblocking %u",
890 proto, vppcom_proto_str (proto), is_nonblocking);
Dave Wallace048b1d62018-01-03 22:24:41 -0500891
Florin Coras7baeb712019-01-04 17:05:43 -0800892 vlsh = vls_create (proto, is_nonblocking);
893 if (vlsh < 0)
Dave Wallace048b1d62018-01-03 22:24:41 -0500894 {
Florin Coras7baeb712019-01-04 17:05:43 -0800895 errno = -vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500896 rv = -1;
897 }
898 else
899 {
Florin Coras7baeb712019-01-04 17:05:43 -0800900 rv = ldp_vlsh_to_fd (vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -0500901 }
902 }
903 else
904 {
Florin Coras7baeb712019-01-04 17:05:43 -0800905 LDBG (0, "calling libc_socket");
Dave Wallace048b1d62018-01-03 22:24:41 -0500906 rv = libc_socket (domain, type, protocol);
907 }
908
Dave Wallace048b1d62018-01-03 22:24:41 -0500909 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700910}
911
912/*
913 * Create two new sockets, of type TYPE in domain DOMAIN and using
914 * protocol PROTOCOL, which are connected to each other, and put file
915 * descriptors for them in FDS[0] and FDS[1]. If PROTOCOL is zero,
916 * one will be chosen automatically.
917 * Returns 0 on success, -1 for errors.
918 * */
919int
Dave Wallace048b1d62018-01-03 22:24:41 -0500920socketpair (int domain, int type, int protocol, int fds[2])
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700921{
Florin Coras7baeb712019-01-04 17:05:43 -0800922 int rv, sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
Dave Wallace048b1d62018-01-03 22:24:41 -0500923
Dave Wallace2a865272018-02-07 21:00:42 -0500924 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500925 return -1;
926
927 if (((domain == AF_INET) || (domain == AF_INET6)) &&
928 ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM)))
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700929 {
Florin Coras7baeb712019-01-04 17:05:43 -0800930 LDBG (0, "LDP-TBD");
Dave Wallace048b1d62018-01-03 22:24:41 -0500931 errno = ENOSYS;
932 rv = -1;
933 }
934 else
935 {
Florin Coras7baeb712019-01-04 17:05:43 -0800936 LDBG (1, "calling libc_socketpair");
Florin Coras173bae32018-11-16 18:56:28 -0800937 rv = libc_socketpair (domain, type, protocol, fds);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700938 }
939
Dave Wallace048b1d62018-01-03 22:24:41 -0500940 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700941}
942
943int
Dave Wallace048b1d62018-01-03 22:24:41 -0500944bind (int fd, __CONST_SOCKADDR_ARG addr, socklen_t len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700945{
Florin Coras7baeb712019-01-04 17:05:43 -0800946 vls_handle_t vlsh;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700947 int rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700948
Dave Wallace2a865272018-02-07 21:00:42 -0500949 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500950 return -1;
951
Florin Coras7baeb712019-01-04 17:05:43 -0800952 vlsh = ldp_fd_to_vlsh (fd);
953 if (vlsh != VLS_INVALID_HANDLE)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700954 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500955 vppcom_endpt_t ep;
956
Dave Wallace048b1d62018-01-03 22:24:41 -0500957 switch (addr->sa_family)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700958 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500959 case AF_INET:
960 if (len != sizeof (struct sockaddr_in))
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700961 {
Florin Coras7baeb712019-01-04 17:05:43 -0800962 LDBG (0, "ERROR: fd %d: vlsh %u: Invalid AF_INET addr len %u!",
963 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -0500964 errno = EINVAL;
965 rv = -1;
966 goto done;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700967 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500968 ep.is_ip4 = VPPCOM_IS_IP4;
969 ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr;
970 ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port;
971 break;
972
973 case AF_INET6:
974 if (len != sizeof (struct sockaddr_in6))
975 {
Florin Coras7baeb712019-01-04 17:05:43 -0800976 LDBG (0, "ERROR: fd %d: vlsh %u: Invalid AF_INET6 addr len %u!",
977 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -0500978 errno = EINVAL;
979 rv = -1;
980 goto done;
981 }
982 ep.is_ip4 = VPPCOM_IS_IP6;
983 ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
984 ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700985 break;
986
987 default:
Florin Coras7baeb712019-01-04 17:05:43 -0800988 LDBG (0, "ERROR: fd %d: vlsh %u: Unsupported address family %u!",
989 fd, vlsh, addr->sa_family);
Dave Wallace048b1d62018-01-03 22:24:41 -0500990 errno = EAFNOSUPPORT;
991 rv = -1;
992 goto done;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700993 }
Florin Coras7baeb712019-01-04 17:05:43 -0800994 LDBG (0, "fd %d: calling vls_bind: vlsh %u, addr %p, len %u", fd, vlsh,
995 addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -0500996
Florin Coras7baeb712019-01-04 17:05:43 -0800997 rv = vls_bind (vlsh, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -0500998 if (rv != VPPCOM_OK)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700999 {
1000 errno = -rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001001 rv = -1;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001002 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001003 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001004 else
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001005 {
Florin Coras7baeb712019-01-04 17:05:43 -08001006 LDBG (0, "fd %d: calling libc_bind: addr %p, len %u", fd, addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001007 rv = libc_bind (fd, addr, len);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001008 }
1009
Dave Wallace048b1d62018-01-03 22:24:41 -05001010done:
Florin Coras7baeb712019-01-04 17:05:43 -08001011 LDBG (1, "fd %d: returning %d", fd, rv);
Florin Coras05ecfcc2018-12-12 18:19:39 -08001012
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001013 return rv;
1014}
1015
1016static inline int
Dave Wallace2a865272018-02-07 21:00:42 -05001017ldp_copy_ep_to_sockaddr (__SOCKADDR_ARG addr, socklen_t * __restrict len,
1018 vppcom_endpt_t * ep)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001019{
Dave Wallace048b1d62018-01-03 22:24:41 -05001020 int rv = 0;
1021 int sa_len, copy_len;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001022
Dave Wallace2a865272018-02-07 21:00:42 -05001023 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001024 return -1;
1025
1026 if (addr && len && ep)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001027 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001028 addr->sa_family = (ep->is_ip4 == VPPCOM_IS_IP4) ? AF_INET : AF_INET6;
1029 switch (addr->sa_family)
1030 {
1031 case AF_INET:
1032 ((struct sockaddr_in *) addr)->sin_port = ep->port;
1033 if (*len > sizeof (struct sockaddr_in))
1034 *len = sizeof (struct sockaddr_in);
1035 sa_len = sizeof (struct sockaddr_in) - sizeof (struct in_addr);
1036 copy_len = *len - sa_len;
1037 if (copy_len > 0)
1038 memcpy (&((struct sockaddr_in *) addr)->sin_addr, ep->ip,
1039 copy_len);
1040 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001041
Dave Wallace048b1d62018-01-03 22:24:41 -05001042 case AF_INET6:
1043 ((struct sockaddr_in6 *) addr)->sin6_port = ep->port;
1044 if (*len > sizeof (struct sockaddr_in6))
1045 *len = sizeof (struct sockaddr_in6);
1046 sa_len = sizeof (struct sockaddr_in6) - sizeof (struct in6_addr);
1047 copy_len = *len - sa_len;
1048 if (copy_len > 0)
1049 memcpy (((struct sockaddr_in6 *) addr)->sin6_addr.
1050 __in6_u.__u6_addr8, ep->ip, copy_len);
1051 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001052
Dave Wallace048b1d62018-01-03 22:24:41 -05001053 default:
1054 /* Not possible */
1055 rv = -EAFNOSUPPORT;
1056 break;
1057 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001058 }
Dave Wallacee695cb42017-11-02 22:04:42 -04001059 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001060}
1061
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001062int
Dave Wallace048b1d62018-01-03 22:24:41 -05001063getsockname (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001064{
Florin Coras7baeb712019-01-04 17:05:43 -08001065 vls_handle_t vlsh;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001066 int rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001067
Dave Wallace2a865272018-02-07 21:00:42 -05001068 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001069 return -1;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001070
Florin Coras7baeb712019-01-04 17:05:43 -08001071 vlsh = ldp_fd_to_vlsh (fd);
1072 if (vlsh != VLS_INVALID_HANDLE)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001073 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001074 vppcom_endpt_t ep;
1075 u8 addr_buf[sizeof (struct in6_addr)];
1076 u32 size = sizeof (ep);
1077
1078 ep.ip = addr_buf;
Dave Wallace048b1d62018-01-03 22:24:41 -05001079
Florin Coras7baeb712019-01-04 17:05:43 -08001080 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_LCL_ADDR, &ep, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -05001081 if (rv != VPPCOM_OK)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001082 {
1083 errno = -rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001084 rv = -1;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001085 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001086 else
1087 {
Dave Wallace2a865272018-02-07 21:00:42 -05001088 rv = ldp_copy_ep_to_sockaddr (addr, len, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001089 if (rv != VPPCOM_OK)
1090 {
1091 errno = -rv;
1092 rv = -1;
1093 }
1094 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001095 }
1096 else
1097 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001098 rv = libc_getsockname (fd, addr, len);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001099 }
1100
Dave Wallace048b1d62018-01-03 22:24:41 -05001101 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001102}
1103
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001104int
Dave Wallace048b1d62018-01-03 22:24:41 -05001105connect (int fd, __CONST_SOCKADDR_ARG addr, socklen_t len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001106{
Florin Coras7baeb712019-01-04 17:05:43 -08001107 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001108 int rv;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001109
Dave Wallace2a865272018-02-07 21:00:42 -05001110 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001111 return -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001112
Dave Wallace048b1d62018-01-03 22:24:41 -05001113 if (!addr)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001114 {
Florin Coras7baeb712019-01-04 17:05:43 -08001115 LDBG (0, "ERROR: fd %d: NULL addr, len %u", fd, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001116 errno = EINVAL;
1117 rv = -1;
1118 goto done;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001119 }
1120
Florin Coras7baeb712019-01-04 17:05:43 -08001121 vlsh = ldp_fd_to_vlsh (fd);
1122 if (vlsh != VLS_INVALID_HANDLE)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001123 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001124 vppcom_endpt_t ep;
1125
Dave Wallace048b1d62018-01-03 22:24:41 -05001126 switch (addr->sa_family)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001127 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001128 case AF_INET:
1129 if (len != sizeof (struct sockaddr_in))
1130 {
Florin Coras7baeb712019-01-04 17:05:43 -08001131 LDBG (0, "fd %d: ERROR vlsh %u: Invalid AF_INET addr len %u!",
1132 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001133 errno = EINVAL;
1134 rv = -1;
1135 goto done;
1136 }
1137 ep.is_ip4 = VPPCOM_IS_IP4;
1138 ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr;
1139 ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port;
1140 break;
1141
1142 case AF_INET6:
1143 if (len != sizeof (struct sockaddr_in6))
1144 {
Florin Coras7baeb712019-01-04 17:05:43 -08001145 LDBG (0, "fd %d: ERROR vlsh %u: Invalid AF_INET6 addr len %u!",
1146 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001147 errno = EINVAL;
1148 rv = -1;
1149 goto done;
1150 }
1151 ep.is_ip4 = VPPCOM_IS_IP6;
1152 ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
1153 ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port;
1154 break;
1155
1156 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001157 LDBG (0, "fd %d: ERROR vlsh %u: Unsupported address family %u!",
1158 fd, vlsh, addr->sa_family);
Dave Wallace048b1d62018-01-03 22:24:41 -05001159 errno = EAFNOSUPPORT;
1160 rv = -1;
1161 goto done;
1162 }
Florin Coras7baeb712019-01-04 17:05:43 -08001163 LDBG (0, "fd %d: calling vls_connect(): vlsh %u addr %p len %u", fd,
1164 vlsh, addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001165
Florin Coras7baeb712019-01-04 17:05:43 -08001166 rv = vls_connect (vlsh, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001167 if (rv != VPPCOM_OK)
1168 {
1169 errno = -rv;
1170 rv = -1;
1171 }
1172 }
1173 else
1174 {
Florin Coras7baeb712019-01-04 17:05:43 -08001175 LDBG (0, "fd %d: calling libc_connect(): addr %p, len %u",
1176 fd, addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001177
1178 rv = libc_connect (fd, addr, len);
1179 }
1180
1181done:
Florin Coras7baeb712019-01-04 17:05:43 -08001182 LDBG (1, "fd %d: returning %d (0x%x)", fd, rv, rv);
Dave Wallace048b1d62018-01-03 22:24:41 -05001183 return rv;
1184}
1185
1186int
1187getpeername (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict len)
1188{
Florin Coras7baeb712019-01-04 17:05:43 -08001189 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001190 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001191
Dave Wallace2a865272018-02-07 21:00:42 -05001192 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001193 return -1;
1194
Florin Coras7baeb712019-01-04 17:05:43 -08001195 vlsh = ldp_fd_to_vlsh (fd);
1196 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001197 {
1198 vppcom_endpt_t ep;
1199 u8 addr_buf[sizeof (struct in6_addr)];
1200 u32 size = sizeof (ep);
1201
1202 ep.ip = addr_buf;
Florin Coras7baeb712019-01-04 17:05:43 -08001203 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_PEER_ADDR, &ep, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -05001204 if (rv != VPPCOM_OK)
1205 {
1206 errno = -rv;
1207 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001208 }
1209 else
1210 {
Dave Wallace2a865272018-02-07 21:00:42 -05001211 rv = ldp_copy_ep_to_sockaddr (addr, len, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001212 if (rv != VPPCOM_OK)
1213 {
1214 errno = -rv;
1215 rv = -1;
1216 }
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001217 }
1218 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001219 else
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001220 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001221 rv = libc_getpeername (fd, addr, len);
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001222 }
1223
Dave Wallace048b1d62018-01-03 22:24:41 -05001224 return rv;
1225}
1226
1227ssize_t
1228send (int fd, const void *buf, size_t n, int flags)
1229{
Florin Coras7baeb712019-01-04 17:05:43 -08001230 vls_handle_t vlsh = ldp_fd_to_vlsh (fd);
Dave Wallace048b1d62018-01-03 22:24:41 -05001231 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001232
Dave Wallace2a865272018-02-07 21:00:42 -05001233 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001234 return -1;
1235
Florin Coras7baeb712019-01-04 17:05:43 -08001236 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001237 {
Florin Coras7baeb712019-01-04 17:05:43 -08001238 size = vls_sendto (vlsh, (void *) buf, n, flags, NULL);
qchangaa8f63c2018-05-30 11:44:18 -07001239 if (size < VPPCOM_OK)
Dave Wallace048b1d62018-01-03 22:24:41 -05001240 {
1241 errno = -size;
1242 size = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001243 }
1244 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001245 else
1246 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001247 size = libc_send (fd, buf, n, flags);
1248 }
1249
Dave Wallace048b1d62018-01-03 22:24:41 -05001250 return size;
1251}
1252
1253ssize_t
1254sendfile (int out_fd, int in_fd, off_t * offset, size_t len)
1255{
Florin Corasdfe4cf42018-11-28 22:13:45 -08001256 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras7baeb712019-01-04 17:05:43 -08001257 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001258 ssize_t size = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -05001259
Dave Wallace2a865272018-02-07 21:00:42 -05001260 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001261 return -1;
1262
Florin Coras7baeb712019-01-04 17:05:43 -08001263 vlsh = ldp_fd_to_vlsh (out_fd);
1264 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001265 {
1266 int rv;
1267 ssize_t results = 0;
1268 size_t n_bytes_left = len;
1269 size_t bytes_to_read;
1270 int nbytes;
Dave Wallace048b1d62018-01-03 22:24:41 -05001271 u8 eagain = 0;
1272 u32 flags, flags_len = sizeof (flags);
1273
Florin Coras7baeb712019-01-04 17:05:43 -08001274 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_FLAGS, &flags, &flags_len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001275 if (PREDICT_FALSE (rv != VPPCOM_OK))
1276 {
Florin Coras7baeb712019-01-04 17:05:43 -08001277 LDBG (0, "ERROR: out fd %d: vls_attr: vlsh %u, returned %d (%s)!",
1278 out_fd, vlsh, rv, vppcom_retval_str (rv));
Dave Wallace048b1d62018-01-03 22:24:41 -05001279
Florin Corasdfe4cf42018-11-28 22:13:45 -08001280 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001281 errno = -rv;
1282 size = -1;
1283 goto done;
1284 }
1285
1286 if (offset)
1287 {
1288 off_t off = lseek (in_fd, *offset, SEEK_SET);
1289 if (PREDICT_FALSE (off == -1))
1290 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001291 size = -1;
1292 goto done;
1293 }
1294
1295 ASSERT (off == *offset);
1296 }
1297
1298 do
1299 {
Florin Coras7baeb712019-01-04 17:05:43 -08001300 size = vls_attr (vlsh, VPPCOM_ATTR_GET_NWRITE, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05001301 if (size < 0)
1302 {
Florin Coras7baeb712019-01-04 17:05:43 -08001303 LDBG (0, "ERROR: fd %d: vls_attr: vlsh %u returned %d (%s)!",
1304 out_fd, vlsh, size, vppcom_retval_str (size));
Florin Corasdfe4cf42018-11-28 22:13:45 -08001305 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001306 errno = -size;
1307 size = -1;
1308 goto done;
1309 }
1310
1311 bytes_to_read = size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001312 if (bytes_to_read == 0)
1313 {
1314 if (flags & O_NONBLOCK)
1315 {
1316 if (!results)
Florin Coras7baeb712019-01-04 17:05:43 -08001317 eagain = 1;
Dave Wallace048b1d62018-01-03 22:24:41 -05001318 goto update_offset;
1319 }
1320 else
1321 continue;
1322 }
1323 bytes_to_read = clib_min (n_bytes_left, bytes_to_read);
Florin Corasdfe4cf42018-11-28 22:13:45 -08001324 vec_validate (ldpw->io_buffer, bytes_to_read);
1325 nbytes = libc_read (in_fd, ldpw->io_buffer, bytes_to_read);
Dave Wallace048b1d62018-01-03 22:24:41 -05001326 if (nbytes < 0)
1327 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001328 if (results == 0)
1329 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08001330 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001331 size = -1;
1332 goto done;
1333 }
1334 goto update_offset;
1335 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001336
Florin Coras7baeb712019-01-04 17:05:43 -08001337 size = vls_write (vlsh, ldpw->io_buffer, nbytes);
Dave Wallace048b1d62018-01-03 22:24:41 -05001338 if (size < 0)
1339 {
1340 if (size == VPPCOM_EAGAIN)
1341 {
1342 if (flags & O_NONBLOCK)
1343 {
1344 if (!results)
Florin Coras7baeb712019-01-04 17:05:43 -08001345 eagain = 1;
Dave Wallace048b1d62018-01-03 22:24:41 -05001346 goto update_offset;
1347 }
1348 else
1349 continue;
1350 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001351 if (results == 0)
1352 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08001353 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001354 errno = -size;
1355 size = -1;
1356 goto done;
1357 }
1358 goto update_offset;
1359 }
1360
1361 results += nbytes;
1362 ASSERT (n_bytes_left >= nbytes);
1363 n_bytes_left = n_bytes_left - nbytes;
1364 }
1365 while (n_bytes_left > 0);
1366
1367 update_offset:
Florin Corasdfe4cf42018-11-28 22:13:45 -08001368 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001369 if (offset)
1370 {
1371 off_t off = lseek (in_fd, *offset, SEEK_SET);
1372 if (PREDICT_FALSE (off == -1))
1373 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001374 size = -1;
1375 goto done;
1376 }
1377
1378 ASSERT (off == *offset);
1379 *offset += results + 1;
1380 }
1381 if (eagain)
1382 {
1383 errno = EAGAIN;
1384 size = -1;
1385 }
1386 else
1387 size = results;
1388 }
1389 else
1390 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001391 size = libc_sendfile (out_fd, in_fd, offset, len);
1392 }
1393
1394done:
Dave Wallace048b1d62018-01-03 22:24:41 -05001395 return size;
1396}
1397
1398ssize_t
1399sendfile64 (int out_fd, int in_fd, off_t * offset, size_t len)
1400{
1401 return sendfile (out_fd, in_fd, offset, len);
1402}
1403
1404ssize_t
1405recv (int fd, void *buf, size_t n, int flags)
1406{
Florin Coras7baeb712019-01-04 17:05:43 -08001407 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001408 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001409
Dave Wallace2a865272018-02-07 21:00:42 -05001410 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001411 return -1;
1412
Florin Coras7baeb712019-01-04 17:05:43 -08001413 vlsh = ldp_fd_to_vlsh (fd);
1414 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001415 {
Florin Coras7baeb712019-01-04 17:05:43 -08001416 size = vls_recvfrom (vlsh, buf, n, flags, NULL);
Dave Wallace048b1d62018-01-03 22:24:41 -05001417 if (size < 0)
Florin Corasa7a1a222018-12-30 17:11:31 -08001418 errno = -size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001419 }
1420 else
1421 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001422 size = libc_recv (fd, buf, n, flags);
1423 }
1424
Dave Wallace048b1d62018-01-03 22:24:41 -05001425 return size;
1426}
1427
1428ssize_t
1429sendto (int fd, const void *buf, size_t n, int flags,
1430 __CONST_SOCKADDR_ARG addr, socklen_t addr_len)
1431{
Florin Coras7baeb712019-01-04 17:05:43 -08001432 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001433 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001434
Dave Wallace2a865272018-02-07 21:00:42 -05001435 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001436 return -1;
1437
Florin Coras7baeb712019-01-04 17:05:43 -08001438 vlsh = ldp_fd_to_vlsh (fd);
1439 if (vlsh != INVALID_SESSION_ID)
Dave Wallace048b1d62018-01-03 22:24:41 -05001440 {
1441 vppcom_endpt_t *ep = 0;
1442 vppcom_endpt_t _ep;
1443
1444 if (addr)
1445 {
1446 ep = &_ep;
Dave Wallace048b1d62018-01-03 22:24:41 -05001447 switch (addr->sa_family)
1448 {
1449 case AF_INET:
1450 ep->is_ip4 = VPPCOM_IS_IP4;
1451 ep->ip =
1452 (uint8_t *) & ((const struct sockaddr_in *) addr)->sin_addr;
1453 ep->port =
1454 (uint16_t) ((const struct sockaddr_in *) addr)->sin_port;
1455 break;
1456
1457 case AF_INET6:
1458 ep->is_ip4 = VPPCOM_IS_IP6;
1459 ep->ip =
1460 (uint8_t *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
1461 ep->port =
1462 (uint16_t) ((const struct sockaddr_in6 *) addr)->sin6_port;
1463 break;
1464
1465 default:
1466 errno = EAFNOSUPPORT;
1467 size = -1;
1468 goto done;
1469 }
1470 }
1471
Florin Coras7baeb712019-01-04 17:05:43 -08001472 size = vls_sendto (vlsh, (void *) buf, n, flags, ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001473 if (size < 0)
1474 {
1475 errno = -size;
1476 size = -1;
1477 }
1478 }
1479 else
1480 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001481 size = libc_sendto (fd, buf, n, flags, addr, addr_len);
1482 }
1483
1484done:
Dave Wallace048b1d62018-01-03 22:24:41 -05001485 return size;
1486}
1487
1488ssize_t
1489recvfrom (int fd, void *__restrict buf, size_t n, int flags,
1490 __SOCKADDR_ARG addr, socklen_t * __restrict addr_len)
1491{
Florin Coras7baeb712019-01-04 17:05:43 -08001492 vls_handle_t sid;
Haggai Eran46ae2ef2019-02-19 15:04:42 +02001493 ssize_t size, rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001494
Dave Wallace2a865272018-02-07 21:00:42 -05001495 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001496 return -1;
1497
Florin Coras7baeb712019-01-04 17:05:43 -08001498 sid = ldp_fd_to_vlsh (fd);
1499 if (sid != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001500 {
1501 vppcom_endpt_t ep;
1502 u8 src_addr[sizeof (struct sockaddr_in6)];
1503
Dave Wallace048b1d62018-01-03 22:24:41 -05001504 if (addr)
1505 {
1506 ep.ip = src_addr;
Florin Coras7baeb712019-01-04 17:05:43 -08001507 size = vls_recvfrom (sid, buf, n, flags, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001508
1509 if (size > 0)
Haggai Eran46ae2ef2019-02-19 15:04:42 +02001510 {
1511 rv = ldp_copy_ep_to_sockaddr (addr, addr_len, &ep);
1512 if (rv < 0)
1513 size = rv;
1514 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001515 }
1516 else
Florin Coras7baeb712019-01-04 17:05:43 -08001517 size = vls_recvfrom (sid, buf, n, flags, NULL);
Dave Wallace048b1d62018-01-03 22:24:41 -05001518
1519 if (size < 0)
1520 {
1521 errno = -size;
1522 size = -1;
1523 }
1524 }
1525 else
1526 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001527 size = libc_recvfrom (fd, buf, n, flags, addr, addr_len);
1528 }
1529
Dave Wallace048b1d62018-01-03 22:24:41 -05001530 return size;
1531}
1532
1533ssize_t
1534sendmsg (int fd, const struct msghdr * message, int flags)
1535{
Florin Coras7baeb712019-01-04 17:05:43 -08001536 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001537 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001538
Dave Wallace2a865272018-02-07 21:00:42 -05001539 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001540 return -1;
1541
Florin Coras7baeb712019-01-04 17:05:43 -08001542 vlsh = ldp_fd_to_vlsh (fd);
1543 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001544 {
Florin Coras7baeb712019-01-04 17:05:43 -08001545 LDBG (0, "LDP-TBD");
Dave Wallace048b1d62018-01-03 22:24:41 -05001546 errno = ENOSYS;
1547 size = -1;
1548 }
1549 else
1550 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001551 size = libc_sendmsg (fd, message, flags);
1552 }
1553
Dave Wallace048b1d62018-01-03 22:24:41 -05001554 return size;
1555}
1556
1557#ifdef USE_GNU
1558int
1559sendmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags)
1560{
1561 ssize_t size;
1562 const char *func_str;
Florin Coras7baeb712019-01-04 17:05:43 -08001563 u32 sh = ldp_fd_to_vlsh (fd);
Dave Wallace048b1d62018-01-03 22:24:41 -05001564
Dave Wallace2a865272018-02-07 21:00:42 -05001565 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001566 return -1;
1567
Florin Coras7baeb712019-01-04 17:05:43 -08001568 if (sh != INVALID_SESSION_ID)
Dave Wallace048b1d62018-01-03 22:24:41 -05001569 {
1570 clib_warning ("LDP<%d>: LDP-TBD", getpid ());
1571 errno = ENOSYS;
1572 size = -1;
1573 }
1574 else
1575 {
1576 func_str = "libc_sendmmsg";
1577
Dave Wallace2a865272018-02-07 21:00:42 -05001578 if (LDP_DEBUG > 2)
Dave Wallace048b1d62018-01-03 22:24:41 -05001579 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1580 "vmessages %p, vlen %u, flags 0x%x",
1581 getpid (), fd, fd, func_str, vmessages, vlen, flags);
1582
1583 size = libc_sendmmsg (fd, vmessages, vlen, flags);
1584 }
1585
Dave Wallace2a865272018-02-07 21:00:42 -05001586 if (LDP_DEBUG > 2)
Dave Wallace048b1d62018-01-03 22:24:41 -05001587 {
1588 if (size < 0)
1589 {
1590 int errno_val = errno;
1591 perror (func_str);
1592 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1593 "rv %d, errno = %d", getpid (), fd, fd,
1594 func_str, size, errno_val);
1595 errno = errno_val;
1596 }
1597 else
1598 clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1599 getpid (), fd, fd, size, size);
1600 }
1601 return size;
1602}
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001603#endif
1604
Dave Wallace048b1d62018-01-03 22:24:41 -05001605ssize_t
1606recvmsg (int fd, struct msghdr * message, int flags)
1607{
Florin Coras7baeb712019-01-04 17:05:43 -08001608 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001609 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001610
Dave Wallace2a865272018-02-07 21:00:42 -05001611 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001612 return -1;
1613
Florin Coras7baeb712019-01-04 17:05:43 -08001614 vlsh = ldp_fd_to_vlsh (fd);
1615 if (vlsh != VLS_INVALID_HANDLE)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001616 {
Florin Coras7baeb712019-01-04 17:05:43 -08001617 LDBG (0, "LDP-TBD");
Dave Wallace048b1d62018-01-03 22:24:41 -05001618 errno = ENOSYS;
1619 size = -1;
1620 }
1621 else
1622 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001623 size = libc_recvmsg (fd, message, flags);
1624 }
1625
Dave Wallace048b1d62018-01-03 22:24:41 -05001626 return size;
1627}
1628
1629#ifdef USE_GNU
1630int
1631recvmmsg (int fd, struct mmsghdr *vmessages,
1632 unsigned int vlen, int flags, struct timespec *tmo)
1633{
1634 ssize_t size;
1635 const char *func_str;
Florin Coras7baeb712019-01-04 17:05:43 -08001636 u32 sh = ldp_fd_to_vlsh (fd);
Dave Wallace048b1d62018-01-03 22:24:41 -05001637
Dave Wallace2a865272018-02-07 21:00:42 -05001638 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001639 return -1;
1640
Florin Coras7baeb712019-01-04 17:05:43 -08001641 if (sh != INVALID_SESSION_ID)
Dave Wallace048b1d62018-01-03 22:24:41 -05001642 {
1643 clib_warning ("LDP<%d>: LDP-TBD", getpid ());
1644 errno = ENOSYS;
1645 size = -1;
1646 }
1647 else
1648 {
1649 func_str = "libc_recvmmsg";
1650
Dave Wallace2a865272018-02-07 21:00:42 -05001651 if (LDP_DEBUG > 2)
Dave Wallace048b1d62018-01-03 22:24:41 -05001652 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1653 "vmessages %p, vlen %u, flags 0x%x, tmo %p",
1654 getpid (), fd, fd, func_str, vmessages, vlen,
1655 flags, tmo);
1656
1657 size = libc_recvmmsg (fd, vmessages, vlen, flags, tmo);
1658 }
1659
Dave Wallace2a865272018-02-07 21:00:42 -05001660 if (LDP_DEBUG > 2)
Dave Wallace048b1d62018-01-03 22:24:41 -05001661 {
1662 if (size < 0)
1663 {
1664 int errno_val = errno;
1665 perror (func_str);
1666 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1667 "rv %d, errno = %d", getpid (), fd, fd,
1668 func_str, size, errno_val);
1669 errno = errno_val;
1670 }
1671 else
1672 clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1673 getpid (), fd, fd, size, size);
1674 }
1675 return size;
1676}
1677#endif
1678
1679int
1680getsockopt (int fd, int level, int optname,
1681 void *__restrict optval, socklen_t * __restrict optlen)
1682{
Florin Coras7baeb712019-01-04 17:05:43 -08001683 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001684 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001685
Dave Wallace2a865272018-02-07 21:00:42 -05001686 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001687 return -1;
1688
Florin Coras7baeb712019-01-04 17:05:43 -08001689 vlsh = ldp_fd_to_vlsh (fd);
1690 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001691 {
1692 rv = -EOPNOTSUPP;
1693
1694 switch (level)
1695 {
1696 case SOL_TCP:
1697 switch (optname)
1698 {
1699 case TCP_NODELAY:
Florin Coras7baeb712019-01-04 17:05:43 -08001700 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_NODELAY,
1701 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001702 break;
1703 case TCP_MAXSEG:
Florin Coras7baeb712019-01-04 17:05:43 -08001704 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_USER_MSS,
1705 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001706 break;
1707 case TCP_KEEPIDLE:
Florin Coras7baeb712019-01-04 17:05:43 -08001708 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_KEEPIDLE,
1709 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001710 break;
1711 case TCP_KEEPINTVL:
Florin Coras7baeb712019-01-04 17:05:43 -08001712 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_KEEPINTVL,
1713 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001714 break;
1715 case TCP_INFO:
1716 if (optval && optlen && (*optlen == sizeof (struct tcp_info)))
1717 {
Florin Coras7baeb712019-01-04 17:05:43 -08001718 LDBG (1, "fd %d: vlsh %u SOL_TCP, TCP_INFO, optval %p, "
1719 "optlen %d: #LDP-NOP#", fd, vlsh, optval, *optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001720 memset (optval, 0, *optlen);
1721 rv = VPPCOM_OK;
1722 }
1723 else
1724 rv = -EFAULT;
1725 break;
Florin Coras0ed24e92019-01-21 09:03:10 -08001726 case TCP_CONGESTION:
1727 strcpy (optval, "cubic");
1728 *optlen = strlen ("cubic");
1729 rv = 0;
1730 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05001731 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001732 LDBG (0, "ERROR: fd %d: getsockopt SOL_TCP: sid %u, "
1733 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05001734 break;
1735 }
1736 break;
1737 case SOL_IPV6:
1738 switch (optname)
1739 {
1740 case IPV6_V6ONLY:
Florin Coras7baeb712019-01-04 17:05:43 -08001741 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_V6ONLY, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001742 break;
1743 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001744 LDBG (0, "ERROR: fd %d: getsockopt SOL_IPV6: vlsh %u "
1745 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05001746 break;
1747 }
1748 break;
1749 case SOL_SOCKET:
1750 switch (optname)
1751 {
1752 case SO_ACCEPTCONN:
Florin Coras7baeb712019-01-04 17:05:43 -08001753 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_LISTEN, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001754 break;
1755 case SO_KEEPALIVE:
Florin Coras7baeb712019-01-04 17:05:43 -08001756 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_KEEPALIVE, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001757 break;
1758 case SO_PROTOCOL:
Florin Coras7baeb712019-01-04 17:05:43 -08001759 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_PROTOCOL, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001760 *(int *) optval = *(int *) optval ? SOCK_DGRAM : SOCK_STREAM;
1761 break;
1762 case SO_SNDBUF:
Florin Coras7baeb712019-01-04 17:05:43 -08001763 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TX_FIFO_LEN,
1764 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001765 break;
1766 case SO_RCVBUF:
Florin Coras7baeb712019-01-04 17:05:43 -08001767 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_RX_FIFO_LEN,
1768 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001769 break;
1770 case SO_REUSEADDR:
Florin Coras7baeb712019-01-04 17:05:43 -08001771 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_REUSEADDR, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001772 break;
1773 case SO_BROADCAST:
Florin Coras7baeb712019-01-04 17:05:43 -08001774 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_BROADCAST, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001775 break;
1776 case SO_ERROR:
Florin Coras7baeb712019-01-04 17:05:43 -08001777 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_ERROR, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001778 break;
1779 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001780 LDBG (0, "ERROR: fd %d: getsockopt SOL_SOCKET: vlsh %u "
1781 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05001782 break;
1783 }
1784 break;
1785 default:
1786 break;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001787 }
1788
Dave Wallace048b1d62018-01-03 22:24:41 -05001789 if (rv != VPPCOM_OK)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001790 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001791 errno = -rv;
1792 rv = -1;
1793 }
1794 }
1795 else
1796 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001797 rv = libc_getsockopt (fd, level, optname, optval, optlen);
1798 }
1799
Dave Wallace048b1d62018-01-03 22:24:41 -05001800 return rv;
1801}
1802
1803int
1804setsockopt (int fd, int level, int optname,
1805 const void *optval, socklen_t optlen)
1806{
Florin Coras7baeb712019-01-04 17:05:43 -08001807 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001808 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001809
Dave Wallace2a865272018-02-07 21:00:42 -05001810 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001811 return -1;
1812
Florin Coras7baeb712019-01-04 17:05:43 -08001813 vlsh = ldp_fd_to_vlsh (fd);
1814 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001815 {
1816 rv = -EOPNOTSUPP;
1817
1818 switch (level)
1819 {
1820 case SOL_TCP:
1821 switch (optname)
1822 {
1823 case TCP_NODELAY:
Florin Coras7baeb712019-01-04 17:05:43 -08001824 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_NODELAY,
1825 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001826 break;
1827 case TCP_MAXSEG:
Florin Coras7baeb712019-01-04 17:05:43 -08001828 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_USER_MSS,
1829 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001830 break;
1831 case TCP_KEEPIDLE:
Florin Coras7baeb712019-01-04 17:05:43 -08001832 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_KEEPIDLE,
1833 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001834 break;
1835 case TCP_KEEPINTVL:
Florin Coras7baeb712019-01-04 17:05:43 -08001836 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_KEEPINTVL,
1837 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001838 break;
Florin Coras0ed24e92019-01-21 09:03:10 -08001839 case TCP_CONGESTION:
Florin Coras8509aa22019-04-04 12:55:30 -07001840 case TCP_CORK:
Florin Coras0ed24e92019-01-21 09:03:10 -08001841 /* Ignore */
1842 rv = 0;
1843 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05001844 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001845 LDBG (0, "ERROR: fd %d: setsockopt() SOL_TCP: vlsh %u"
1846 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05001847 break;
1848 }
1849 break;
1850 case SOL_IPV6:
1851 switch (optname)
1852 {
1853 case IPV6_V6ONLY:
Florin Coras7baeb712019-01-04 17:05:43 -08001854 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_V6ONLY,
1855 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001856 break;
1857 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001858 LDBG (0, "ERROR: fd %d: setsockopt SOL_IPV6: vlsh %u"
1859 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05001860 break;
1861 }
1862 break;
1863 case SOL_SOCKET:
1864 switch (optname)
1865 {
1866 case SO_KEEPALIVE:
Florin Coras7baeb712019-01-04 17:05:43 -08001867 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_KEEPALIVE,
1868 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001869 break;
1870 case SO_REUSEADDR:
Florin Coras7baeb712019-01-04 17:05:43 -08001871 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_REUSEADDR,
1872 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001873 break;
1874 case SO_BROADCAST:
Florin Coras7baeb712019-01-04 17:05:43 -08001875 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_BROADCAST,
1876 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001877 break;
1878 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001879 LDBG (0, "ERROR: fd %d: setsockopt SOL_SOCKET: vlsh %u "
1880 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05001881 break;
1882 }
1883 break;
1884 default:
1885 break;
1886 }
1887
1888 if (rv != VPPCOM_OK)
1889 {
1890 errno = -rv;
1891 rv = -1;
1892 }
1893 }
1894 else
1895 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001896 rv = libc_setsockopt (fd, level, optname, optval, optlen);
1897 }
1898
Dave Wallace048b1d62018-01-03 22:24:41 -05001899 return rv;
1900}
1901
1902int
1903listen (int fd, int n)
1904{
Florin Coras7baeb712019-01-04 17:05:43 -08001905 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001906 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001907
Dave Wallace2a865272018-02-07 21:00:42 -05001908 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001909 return -1;
1910
Florin Coras7baeb712019-01-04 17:05:43 -08001911 vlsh = ldp_fd_to_vlsh (fd);
1912 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001913 {
Florin Coras7baeb712019-01-04 17:05:43 -08001914 LDBG (0, "fd %d: calling vls_listen: vlsh %u, n %d", fd, vlsh, n);
Dave Wallace048b1d62018-01-03 22:24:41 -05001915
Florin Coras7baeb712019-01-04 17:05:43 -08001916 rv = vls_listen (vlsh, n);
Dave Wallace048b1d62018-01-03 22:24:41 -05001917 if (rv != VPPCOM_OK)
1918 {
1919 errno = -rv;
1920 rv = -1;
1921 }
1922 }
1923 else
1924 {
Florin Coras7baeb712019-01-04 17:05:43 -08001925 LDBG (0, "fd %d: calling libc_listen(): n %d", fd, n);
Dave Wallace048b1d62018-01-03 22:24:41 -05001926 rv = libc_listen (fd, n);
1927 }
1928
Florin Coras7baeb712019-01-04 17:05:43 -08001929 LDBG (1, "fd %d: returning %d", fd, rv);
Dave Wallace048b1d62018-01-03 22:24:41 -05001930 return rv;
1931}
1932
1933static inline int
Dave Wallace2a865272018-02-07 21:00:42 -05001934ldp_accept4 (int listen_fd, __SOCKADDR_ARG addr,
1935 socklen_t * __restrict addr_len, int flags)
Dave Wallace048b1d62018-01-03 22:24:41 -05001936{
Florin Coras7baeb712019-01-04 17:05:43 -08001937 vls_handle_t listen_vlsh, accept_vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001938 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001939
Dave Wallace2a865272018-02-07 21:00:42 -05001940 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001941 return -1;
1942
Florin Coras7baeb712019-01-04 17:05:43 -08001943 listen_vlsh = ldp_fd_to_vlsh (listen_fd);
1944 if (listen_vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001945 {
1946 vppcom_endpt_t ep;
1947 u8 src_addr[sizeof (struct sockaddr_in6)];
Dave Wallace8aaba562018-01-18 17:21:19 -05001948 memset (&ep, 0, sizeof (ep));
Dave Wallace048b1d62018-01-03 22:24:41 -05001949 ep.ip = src_addr;
1950
Florin Coras7baeb712019-01-04 17:05:43 -08001951 LDBG (0, "listen fd %d: calling vppcom_session_accept: listen sid %u,"
1952 " ep %p, flags 0x%x", listen_fd, listen_vlsh, ep, flags);
Dave Wallace048b1d62018-01-03 22:24:41 -05001953
Florin Coras7baeb712019-01-04 17:05:43 -08001954 accept_vlsh = vls_accept (listen_vlsh, &ep, flags);
1955 if (accept_vlsh < 0)
Dave Wallace048b1d62018-01-03 22:24:41 -05001956 {
Florin Coras7baeb712019-01-04 17:05:43 -08001957 errno = -accept_vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001958 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001959 }
1960 else
1961 {
Dave Wallace2a865272018-02-07 21:00:42 -05001962 rv = ldp_copy_ep_to_sockaddr (addr, addr_len, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001963 if (rv != VPPCOM_OK)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001964 {
Florin Coras7baeb712019-01-04 17:05:43 -08001965 (void) vls_close (accept_vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05001966 errno = -rv;
1967 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001968 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001969 else
1970 {
Florin Coras7baeb712019-01-04 17:05:43 -08001971 rv = ldp_vlsh_to_fd (accept_vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05001972 }
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001973 }
1974 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001975 else
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001976 {
Florin Coras7baeb712019-01-04 17:05:43 -08001977 LDBG (0, "listen fd %d: calling libc_accept4(): addr %p, addr_len %p,"
1978 " flags 0x%x", listen_fd, addr, addr_len, flags);
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001979
Dave Wallace048b1d62018-01-03 22:24:41 -05001980 rv = libc_accept4 (listen_fd, addr, addr_len, flags);
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001981 }
1982
Florin Coras7baeb712019-01-04 17:05:43 -08001983 LDBG (1, "listen fd %d: accept returning %d", listen_fd, rv);
Florin Coras05ecfcc2018-12-12 18:19:39 -08001984
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001985 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001986}
1987
Dave Wallace048b1d62018-01-03 22:24:41 -05001988int
1989accept4 (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len,
1990 int flags)
1991{
Dave Wallace2a865272018-02-07 21:00:42 -05001992 return ldp_accept4 (fd, addr, addr_len, flags);
Dave Wallace048b1d62018-01-03 22:24:41 -05001993}
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001994
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001995int
Dave Wallace048b1d62018-01-03 22:24:41 -05001996accept (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001997{
Dave Wallace2a865272018-02-07 21:00:42 -05001998 return ldp_accept4 (fd, addr, addr_len, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05001999}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002000
Dave Wallace048b1d62018-01-03 22:24:41 -05002001int
2002shutdown (int fd, int how)
2003{
Florin Coras7baeb712019-01-04 17:05:43 -08002004 vls_handle_t vlsh;
2005 int rv = 0, flags;
2006 u32 flags_len = sizeof (flags);
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002007
Dave Wallace2a865272018-02-07 21:00:42 -05002008 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05002009 return -1;
2010
Florin Coras7baeb712019-01-04 17:05:43 -08002011 vlsh = ldp_fd_to_vlsh (fd);
2012 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05002013 {
Florin Coras7baeb712019-01-04 17:05:43 -08002014 LDBG (0, "called shutdown: fd %u vlsh %u how %d", fd, vlsh, how);
Florin Corasa7a1a222018-12-30 17:11:31 -08002015
Florin Coras7baeb712019-01-04 17:05:43 -08002016 if (vls_attr (vlsh, VPPCOM_ATTR_SET_SHUT, &how, &flags_len))
Florin Corasa7a1a222018-12-30 17:11:31 -08002017 {
Florin Coras7baeb712019-01-04 17:05:43 -08002018 close (fd);
Florin Corasa7a1a222018-12-30 17:11:31 -08002019 return -1;
2020 }
2021
Florin Coras7baeb712019-01-04 17:05:43 -08002022 if (vls_attr (vlsh, VPPCOM_ATTR_GET_SHUT, &flags, &flags_len))
2023 {
2024 close (fd);
2025 return -1;
2026 }
Florin Corasa7a1a222018-12-30 17:11:31 -08002027
Florin Coras7baeb712019-01-04 17:05:43 -08002028 if (flags == SHUT_RDWR)
Florin Corasa7a1a222018-12-30 17:11:31 -08002029 rv = close (fd);
Dave Wallace048b1d62018-01-03 22:24:41 -05002030 }
2031 else
2032 {
Florin Coras7baeb712019-01-04 17:05:43 -08002033 LDBG (0, "fd %d: calling libc_shutdown: how %d", fd, how);
Dave Wallace048b1d62018-01-03 22:24:41 -05002034 rv = libc_shutdown (fd, how);
2035 }
2036
Dave Wallace048b1d62018-01-03 22:24:41 -05002037 return rv;
2038}
2039
2040int
2041epoll_create1 (int flags)
2042{
Florin Corasdfe4cf42018-11-28 22:13:45 -08002043 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras7baeb712019-01-04 17:05:43 -08002044 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002045 int rv;
2046
Dave Wallace2a865272018-02-07 21:00:42 -05002047 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05002048 return -1;
2049
Florin Coras99368312018-08-02 10:45:44 -07002050 if (ldp->vcl_needs_real_epoll)
2051 {
Florin Coras2d9b4272019-03-11 10:14:37 -07002052 /* Make sure workers have been allocated */
2053 if (!ldp->workers)
2054 {
2055 ldp_alloc_workers ();
2056 ldpw = ldp_worker_get_current ();
2057 }
Florin Coras99368312018-08-02 10:45:44 -07002058 rv = libc_epoll_create1 (flags);
2059 ldp->vcl_needs_real_epoll = 0;
Florin Corasdfe4cf42018-11-28 22:13:45 -08002060 ldpw->vcl_mq_epfd = rv;
Florin Coras05ecfcc2018-12-12 18:19:39 -08002061 LDBG (0, "created vcl epfd %u", rv);
Florin Coras99368312018-08-02 10:45:44 -07002062 return rv;
2063 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002064
Florin Coras7baeb712019-01-04 17:05:43 -08002065 vlsh = vls_epoll_create ();
2066 if (PREDICT_FALSE (vlsh == VLS_INVALID_HANDLE))
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002067 {
Florin Coras7baeb712019-01-04 17:05:43 -08002068 errno = -vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002069 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002070 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002071 else
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002072 {
Florin Coras7baeb712019-01-04 17:05:43 -08002073 rv = ldp_vlsh_to_fd (vlsh);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002074 }
Florin Coras7baeb712019-01-04 17:05:43 -08002075 LDBG (0, "epoll_create epfd %u vlsh %u", rv, vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05002076 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002077}
2078
2079int
Dave Wallace048b1d62018-01-03 22:24:41 -05002080epoll_create (int size)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002081{
Dave Wallace048b1d62018-01-03 22:24:41 -05002082 return epoll_create1 (0);
2083}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002084
Dave Wallace048b1d62018-01-03 22:24:41 -05002085int
2086epoll_ctl (int epfd, int op, int fd, struct epoll_event *event)
2087{
Florin Coras7baeb712019-01-04 17:05:43 -08002088 vls_handle_t vep_vlsh, vlsh;
Florin Coras99368312018-08-02 10:45:44 -07002089 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05002090
Dave Wallace2a865272018-02-07 21:00:42 -05002091 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05002092 return -1;
2093
Florin Coras7baeb712019-01-04 17:05:43 -08002094 vep_vlsh = ldp_fd_to_vlsh (epfd);
2095 if (PREDICT_FALSE (vep_vlsh == VLS_INVALID_HANDLE))
Dave Wallace048b1d62018-01-03 22:24:41 -05002096 {
Dave Wallace3ee1fe12018-02-23 01:09:11 -05002097 /* The LDP epoll_create1 always creates VCL epfd's.
2098 * The app should never have a kernel base epoll fd unless it
2099 * was acquired outside of the LD_PRELOAD process context.
2100 * In any case, if we get one, punt it to libc_epoll_ctl.
2101 */
Florin Coras7baeb712019-01-04 17:05:43 -08002102 LDBG (1, "epfd %d: calling libc_epoll_ctl: op %d, fd %d"
2103 " event %p", epfd, op, fd, event);
Dave Wallace048b1d62018-01-03 22:24:41 -05002104
2105 rv = libc_epoll_ctl (epfd, op, fd, event);
Florin Coras99368312018-08-02 10:45:44 -07002106 goto done;
2107 }
2108
Florin Coras7baeb712019-01-04 17:05:43 -08002109 vlsh = ldp_fd_to_vlsh (fd);
Florin Coras99368312018-08-02 10:45:44 -07002110
Florin Coras7baeb712019-01-04 17:05:43 -08002111 LDBG (0, "epfd %d ep_vlsh %d, fd %u vlsh %d, op %u", epfd, vep_vlsh, fd,
2112 vlsh, op);
Florin Coras99368312018-08-02 10:45:44 -07002113
Florin Coras7baeb712019-01-04 17:05:43 -08002114 if (vlsh != VLS_INVALID_HANDLE)
Florin Coras99368312018-08-02 10:45:44 -07002115 {
Florin Coras7baeb712019-01-04 17:05:43 -08002116 LDBG (1, "epfd %d: calling vls_epoll_ctl: ep_vlsh %d op %d, vlsh %u,"
2117 " event %p", epfd, vep_vlsh, vlsh, event);
Florin Coras99368312018-08-02 10:45:44 -07002118
Florin Coras7baeb712019-01-04 17:05:43 -08002119 rv = vls_epoll_ctl (vep_vlsh, op, vlsh, event);
Florin Coras99368312018-08-02 10:45:44 -07002120 if (rv != VPPCOM_OK)
2121 {
2122 errno = -rv;
2123 rv = -1;
2124 }
2125 }
2126 else
2127 {
2128 int libc_epfd;
2129 u32 size = sizeof (epfd);
2130
Florin Coras7baeb712019-01-04 17:05:43 -08002131 libc_epfd = vls_attr (vep_vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
Florin Coras99368312018-08-02 10:45:44 -07002132 if (!libc_epfd)
2133 {
Florin Coras7baeb712019-01-04 17:05:43 -08002134 LDBG (1, "epfd %d, vep_vlsh %d calling libc_epoll_create1: "
2135 "EPOLL_CLOEXEC", epfd, vep_vlsh);
Florin Coras99368312018-08-02 10:45:44 -07002136
2137 libc_epfd = libc_epoll_create1 (EPOLL_CLOEXEC);
2138 if (libc_epfd < 0)
2139 {
2140 rv = libc_epfd;
2141 goto done;
2142 }
2143
Florin Coras7baeb712019-01-04 17:05:43 -08002144 rv = vls_attr (vep_vlsh, VPPCOM_ATTR_SET_LIBC_EPFD, &libc_epfd,
2145 &size);
Florin Coras99368312018-08-02 10:45:44 -07002146 if (rv < 0)
2147 {
2148 errno = -rv;
2149 rv = -1;
2150 goto done;
2151 }
2152 }
2153 else if (PREDICT_FALSE (libc_epfd < 0))
2154 {
2155 errno = -epfd;
2156 rv = -1;
2157 goto done;
2158 }
2159
Florin Coras7baeb712019-01-04 17:05:43 -08002160 LDBG (1, "epfd %d: calling libc_epoll_ctl: libc_epfd %d, op %d, fd %d,"
2161 " event %p", epfd, libc_epfd, op, fd, event);
Florin Coras99368312018-08-02 10:45:44 -07002162
2163 rv = libc_epoll_ctl (libc_epfd, op, fd, event);
Dave Wallace048b1d62018-01-03 22:24:41 -05002164 }
2165
2166done:
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002167 return rv;
2168}
Dave Wallace048b1d62018-01-03 22:24:41 -05002169
2170static inline int
Florin Coras99368312018-08-02 10:45:44 -07002171ldp_epoll_pwait (int epfd, struct epoll_event *events, int maxevents,
2172 int timeout, const sigset_t * sigmask)
Dave Wallace048b1d62018-01-03 22:24:41 -05002173{
Florin Corasdfe4cf42018-11-28 22:13:45 -08002174 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras72f77822019-01-22 19:05:52 -08002175 double time_to_wait = (double) 0, max_time;
Florin Coras99368312018-08-02 10:45:44 -07002176 int libc_epfd, rv = 0;
Florin Coras7baeb712019-01-04 17:05:43 -08002177 vls_handle_t ep_vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002178
Dave Wallace2a865272018-02-07 21:00:42 -05002179 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05002180 return -1;
2181
2182 if (PREDICT_FALSE (!events || (timeout < -1)))
2183 {
2184 errno = EFAULT;
2185 return -1;
2186 }
2187
Florin Corasdfe4cf42018-11-28 22:13:45 -08002188 if (epfd == ldpw->vcl_mq_epfd)
Florin Coras99368312018-08-02 10:45:44 -07002189 return libc_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
2190
Florin Coras7baeb712019-01-04 17:05:43 -08002191 ep_vlsh = ldp_fd_to_vlsh (epfd);
2192 if (PREDICT_FALSE (ep_vlsh == VLS_INVALID_HANDLE))
Dave Wallace048b1d62018-01-03 22:24:41 -05002193 {
Florin Coras7baeb712019-01-04 17:05:43 -08002194 LDBG (0, "epfd %d: bad ep_vlsh %d!", epfd, ep_vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05002195 errno = EBADFD;
2196 return -1;
2197 }
2198
Florin Coras4dee8cd2019-01-29 21:28:16 -08002199 if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
2200 clib_time_init (&ldpw->clib_time);
Florin Corasb0f662f2018-12-27 14:51:46 -08002201 time_to_wait = ((timeout >= 0) ? (double) timeout / 1000 : 0);
Florin Coras72f77822019-01-22 19:05:52 -08002202 max_time = clib_time_now (&ldpw->clib_time) + time_to_wait;
Dave Wallace048b1d62018-01-03 22:24:41 -05002203
Florin Coras7baeb712019-01-04 17:05:43 -08002204 libc_epfd = vls_attr (ep_vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002205 if (PREDICT_FALSE (libc_epfd < 0))
2206 {
2207 errno = -libc_epfd;
2208 rv = -1;
2209 goto done;
2210 }
2211
Florin Coras7baeb712019-01-04 17:05:43 -08002212 LDBG (2, "epfd %d: vep_idx %d, libc_epfd %d, events %p, maxevents %d, "
2213 "timeout %d, sigmask %p: time_to_wait %.02f", epfd, ep_vlsh,
Florin Coras72f77822019-01-22 19:05:52 -08002214 libc_epfd, events, maxevents, timeout, sigmask, time_to_wait);
Dave Wallace048b1d62018-01-03 22:24:41 -05002215 do
2216 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002217 if (!ldpw->epoll_wait_vcl)
Dave Wallace048b1d62018-01-03 22:24:41 -05002218 {
Florin Coras7baeb712019-01-04 17:05:43 -08002219 rv = vls_epoll_wait (ep_vlsh, events, maxevents, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002220 if (rv > 0)
2221 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002222 ldpw->epoll_wait_vcl = 1;
Dave Wallace048b1d62018-01-03 22:24:41 -05002223 goto done;
2224 }
2225 else if (rv < 0)
2226 {
2227 errno = -rv;
2228 rv = -1;
2229 goto done;
2230 }
2231 }
2232 else
Florin Corasdfe4cf42018-11-28 22:13:45 -08002233 ldpw->epoll_wait_vcl = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -05002234
2235 if (libc_epfd > 0)
2236 {
Florin Corasb0f662f2018-12-27 14:51:46 -08002237 rv = libc_epoll_pwait (libc_epfd, events, maxevents, 0, sigmask);
Dave Wallace048b1d62018-01-03 22:24:41 -05002238 if (rv != 0)
2239 goto done;
2240 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002241 }
Florin Coras72f77822019-01-22 19:05:52 -08002242 while ((timeout == -1) || (clib_time_now (&ldpw->clib_time) < max_time));
Dave Wallace048b1d62018-01-03 22:24:41 -05002243
2244done:
Dave Wallace048b1d62018-01-03 22:24:41 -05002245 return rv;
2246}
2247
2248int
2249epoll_pwait (int epfd, struct epoll_event *events,
2250 int maxevents, int timeout, const sigset_t * sigmask)
2251{
Dave Wallace2a865272018-02-07 21:00:42 -05002252 return ldp_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
Dave Wallace048b1d62018-01-03 22:24:41 -05002253}
2254
2255int
2256epoll_wait (int epfd, struct epoll_event *events, int maxevents, int timeout)
2257{
Dave Wallace2a865272018-02-07 21:00:42 -05002258 return ldp_epoll_pwait (epfd, events, maxevents, timeout, NULL);
Dave Wallace048b1d62018-01-03 22:24:41 -05002259}
2260
2261int
2262poll (struct pollfd *fds, nfds_t nfds, int timeout)
2263{
Florin Corasdfe4cf42018-11-28 22:13:45 -08002264 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras6917b942018-11-13 22:44:54 -08002265 int rv, i, n_revents = 0;
Florin Coras7baeb712019-01-04 17:05:43 -08002266 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002267 vcl_poll_t *vp;
Florin Coras4dee8cd2019-01-29 21:28:16 -08002268 double max_time;
Dave Wallace048b1d62018-01-03 22:24:41 -05002269
Florin Coras05ecfcc2018-12-12 18:19:39 -08002270 LDBG (3, "fds %p, nfds %d, timeout %d", fds, nfds, timeout);
Dave Wallace048b1d62018-01-03 22:24:41 -05002271
Florin Coras4dee8cd2019-01-29 21:28:16 -08002272 if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
2273 clib_time_init (&ldpw->clib_time);
2274
2275 max_time = (timeout >= 0) ? (f64) timeout / 1000 : 0;
2276 max_time += clib_time_now (&ldpw->clib_time);
Dave Wallace048b1d62018-01-03 22:24:41 -05002277
Dave Wallace048b1d62018-01-03 22:24:41 -05002278 for (i = 0; i < nfds; i++)
2279 {
Florin Coras6917b942018-11-13 22:44:54 -08002280 if (fds[i].fd < 0)
2281 continue;
Dave Wallace048b1d62018-01-03 22:24:41 -05002282
Florin Coras7baeb712019-01-04 17:05:43 -08002283 vlsh = ldp_fd_to_vlsh (fds[i].fd);
2284 if (vlsh != VLS_INVALID_HANDLE)
Florin Coras6917b942018-11-13 22:44:54 -08002285 {
2286 fds[i].fd = -fds[i].fd;
Florin Corasdfe4cf42018-11-28 22:13:45 -08002287 vec_add2 (ldpw->vcl_poll, vp, 1);
Florin Coras6917b942018-11-13 22:44:54 -08002288 vp->fds_ndx = i;
Florin Coras7baeb712019-01-04 17:05:43 -08002289 vp->sh = vlsh_to_sh (vlsh);
Florin Coras6917b942018-11-13 22:44:54 -08002290 vp->events = fds[i].events;
Dave Wallace048b1d62018-01-03 22:24:41 -05002291#ifdef __USE_XOPEN2K
Florin Coras6917b942018-11-13 22:44:54 -08002292 if (fds[i].events & POLLRDNORM)
2293 vp->events |= POLLIN;
2294 if (fds[i].events & POLLWRNORM)
2295 vp->events |= POLLOUT;
Dave Wallace048b1d62018-01-03 22:24:41 -05002296#endif
Florin Coras6917b942018-11-13 22:44:54 -08002297 vp->revents = fds[i].revents;
2298 }
2299 else
2300 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002301 vec_add1 (ldpw->libc_poll, fds[i]);
2302 vec_add1 (ldpw->libc_poll_idxs, i);
Dave Wallace048b1d62018-01-03 22:24:41 -05002303 }
2304 }
2305
Dave Wallace048b1d62018-01-03 22:24:41 -05002306 do
2307 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002308 if (vec_len (ldpw->vcl_poll))
Dave Wallace048b1d62018-01-03 22:24:41 -05002309 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002310 rv = vppcom_poll (ldpw->vcl_poll, vec_len (ldpw->vcl_poll), 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002311 if (rv < 0)
2312 {
2313 errno = -rv;
2314 rv = -1;
2315 goto done;
2316 }
2317 else
2318 n_revents += rv;
2319 }
2320
Florin Corasdfe4cf42018-11-28 22:13:45 -08002321 if (vec_len (ldpw->libc_poll))
Dave Wallace048b1d62018-01-03 22:24:41 -05002322 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002323 rv = libc_poll (ldpw->libc_poll, vec_len (ldpw->libc_poll), 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002324 if (rv < 0)
2325 goto done;
2326 else
2327 n_revents += rv;
2328 }
2329
2330 if (n_revents)
2331 {
2332 rv = n_revents;
2333 goto done;
2334 }
2335 }
Florin Coras4dee8cd2019-01-29 21:28:16 -08002336 while ((timeout < 0) || (clib_time_now (&ldpw->clib_time) < max_time));
Dave Wallace048b1d62018-01-03 22:24:41 -05002337 rv = 0;
2338
2339done:
Florin Corasdfe4cf42018-11-28 22:13:45 -08002340 vec_foreach (vp, ldpw->vcl_poll)
Dave Wallace048b1d62018-01-03 22:24:41 -05002341 {
2342 fds[vp->fds_ndx].fd = -fds[vp->fds_ndx].fd;
Florin Coras6917b942018-11-13 22:44:54 -08002343 fds[vp->fds_ndx].revents = vp->revents;
Dave Wallace048b1d62018-01-03 22:24:41 -05002344#ifdef __USE_XOPEN2K
2345 if ((fds[vp->fds_ndx].revents & POLLIN) &&
2346 (fds[vp->fds_ndx].events & POLLRDNORM))
2347 fds[vp->fds_ndx].revents |= POLLRDNORM;
2348 if ((fds[vp->fds_ndx].revents & POLLOUT) &&
2349 (fds[vp->fds_ndx].events & POLLWRNORM))
2350 fds[vp->fds_ndx].revents |= POLLWRNORM;
2351#endif
2352 }
Florin Corasdfe4cf42018-11-28 22:13:45 -08002353 vec_reset_length (ldpw->vcl_poll);
Dave Wallace048b1d62018-01-03 22:24:41 -05002354
Florin Corasdfe4cf42018-11-28 22:13:45 -08002355 for (i = 0; i < vec_len (ldpw->libc_poll); i++)
Florin Coras6917b942018-11-13 22:44:54 -08002356 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002357 fds[ldpw->libc_poll_idxs[i]].revents = ldpw->libc_poll[i].revents;
Florin Coras6917b942018-11-13 22:44:54 -08002358 }
Florin Corasdfe4cf42018-11-28 22:13:45 -08002359 vec_reset_length (ldpw->libc_poll_idxs);
2360 vec_reset_length (ldpw->libc_poll);
Florin Coras6917b942018-11-13 22:44:54 -08002361
Dave Wallace048b1d62018-01-03 22:24:41 -05002362 return rv;
2363}
2364
2365#ifdef USE_GNU
2366int
2367ppoll (struct pollfd *fds, nfds_t nfds,
2368 const struct timespec *timeout, const sigset_t * sigmask)
2369{
Dave Wallace2a865272018-02-07 21:00:42 -05002370 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05002371 return -1;
2372
2373 clib_warning ("LDP<%d>: LDP-TBD", getpid ());
2374 errno = ENOSYS;
2375
2376
2377 return -1;
2378}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002379#endif
2380
Dave Wallace2a865272018-02-07 21:00:42 -05002381void CONSTRUCTOR_ATTRIBUTE ldp_constructor (void);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002382
Dave Wallace2a865272018-02-07 21:00:42 -05002383void DESTRUCTOR_ATTRIBUTE ldp_destructor (void);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002384
Dave Wallace048b1d62018-01-03 22:24:41 -05002385/*
2386 * This function is called when the library is loaded
2387 */
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002388void
Dave Wallace2a865272018-02-07 21:00:42 -05002389ldp_constructor (void)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002390{
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002391 swrap_constructor ();
Dave Wallace2a865272018-02-07 21:00:42 -05002392 if (ldp_init () != 0)
Florin Corasd89411e2019-03-19 19:44:51 -07002393 {
2394 fprintf (stderr, "\nLDP<%d>: ERROR: ldp_constructor: failed!\n",
2395 getpid ());
2396 _exit (1);
2397 }
Dave Wallace69d01192018-02-22 16:22:09 -05002398 else if (LDP_DEBUG > 0)
Dave Wallace2a865272018-02-07 21:00:42 -05002399 clib_warning ("LDP<%d>: LDP constructor: done!\n", getpid ());
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002400}
2401
2402/*
2403 * This function is called when the library is unloaded
2404 */
2405void
Dave Wallace2a865272018-02-07 21:00:42 -05002406ldp_destructor (void)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002407{
Florin Coras0ef8ef22019-01-18 08:37:13 -08002408 /*
2409 swrap_destructor ();
2410 if (ldp->init)
2411 ldp->init = 0;
2412 */
Dave Wallace048b1d62018-01-03 22:24:41 -05002413
2414 /* Don't use clib_warning() here because that calls writev()
Dave Wallace2a865272018-02-07 21:00:42 -05002415 * which will call ldp_init().
Dave Wallace048b1d62018-01-03 22:24:41 -05002416 */
Dave Wallace69d01192018-02-22 16:22:09 -05002417 if (LDP_DEBUG > 0)
Florin Coras0ef8ef22019-01-18 08:37:13 -08002418 fprintf (stderr, "%s:%d: LDP<%d>: LDP destructor: done!\n",
2419 __func__, __LINE__, getpid ());
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002420}
2421
2422
2423/*
2424 * fd.io coding-style-patch-verification: ON
2425 *
2426 * Local Variables:
2427 * eval: (c-set-style "gnu")
2428 * End:
2429 */