blob: 338c091754b913c2180e9360be6f16a63d1eddca [file] [log] [blame]
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001/*
2 * Copyright (c) 2016 Cisco and/or its affiliates.
3 * 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:
1840 /* Ignore */
1841 rv = 0;
1842 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05001843 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001844 LDBG (0, "ERROR: fd %d: setsockopt() SOL_TCP: vlsh %u"
1845 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05001846 break;
1847 }
1848 break;
1849 case SOL_IPV6:
1850 switch (optname)
1851 {
1852 case IPV6_V6ONLY:
Florin Coras7baeb712019-01-04 17:05:43 -08001853 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_V6ONLY,
1854 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001855 break;
1856 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001857 LDBG (0, "ERROR: fd %d: setsockopt SOL_IPV6: vlsh %u"
1858 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05001859 break;
1860 }
1861 break;
1862 case SOL_SOCKET:
1863 switch (optname)
1864 {
1865 case SO_KEEPALIVE:
Florin Coras7baeb712019-01-04 17:05:43 -08001866 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_KEEPALIVE,
1867 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001868 break;
1869 case SO_REUSEADDR:
Florin Coras7baeb712019-01-04 17:05:43 -08001870 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_REUSEADDR,
1871 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001872 break;
1873 case SO_BROADCAST:
Florin Coras7baeb712019-01-04 17:05:43 -08001874 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_BROADCAST,
1875 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001876 break;
1877 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001878 LDBG (0, "ERROR: fd %d: setsockopt SOL_SOCKET: vlsh %u "
1879 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05001880 break;
1881 }
1882 break;
1883 default:
1884 break;
1885 }
1886
1887 if (rv != VPPCOM_OK)
1888 {
1889 errno = -rv;
1890 rv = -1;
1891 }
1892 }
1893 else
1894 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001895 rv = libc_setsockopt (fd, level, optname, optval, optlen);
1896 }
1897
Dave Wallace048b1d62018-01-03 22:24:41 -05001898 return rv;
1899}
1900
1901int
1902listen (int fd, int n)
1903{
Florin Coras7baeb712019-01-04 17:05:43 -08001904 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001905 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001906
Dave Wallace2a865272018-02-07 21:00:42 -05001907 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001908 return -1;
1909
Florin Coras7baeb712019-01-04 17:05:43 -08001910 vlsh = ldp_fd_to_vlsh (fd);
1911 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001912 {
Florin Coras7baeb712019-01-04 17:05:43 -08001913 LDBG (0, "fd %d: calling vls_listen: vlsh %u, n %d", fd, vlsh, n);
Dave Wallace048b1d62018-01-03 22:24:41 -05001914
Florin Coras7baeb712019-01-04 17:05:43 -08001915 rv = vls_listen (vlsh, n);
Dave Wallace048b1d62018-01-03 22:24:41 -05001916 if (rv != VPPCOM_OK)
1917 {
1918 errno = -rv;
1919 rv = -1;
1920 }
1921 }
1922 else
1923 {
Florin Coras7baeb712019-01-04 17:05:43 -08001924 LDBG (0, "fd %d: calling libc_listen(): n %d", fd, n);
Dave Wallace048b1d62018-01-03 22:24:41 -05001925 rv = libc_listen (fd, n);
1926 }
1927
Florin Coras7baeb712019-01-04 17:05:43 -08001928 LDBG (1, "fd %d: returning %d", fd, rv);
Dave Wallace048b1d62018-01-03 22:24:41 -05001929 return rv;
1930}
1931
1932static inline int
Dave Wallace2a865272018-02-07 21:00:42 -05001933ldp_accept4 (int listen_fd, __SOCKADDR_ARG addr,
1934 socklen_t * __restrict addr_len, int flags)
Dave Wallace048b1d62018-01-03 22:24:41 -05001935{
Florin Coras7baeb712019-01-04 17:05:43 -08001936 vls_handle_t listen_vlsh, accept_vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001937 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001938
Dave Wallace2a865272018-02-07 21:00:42 -05001939 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001940 return -1;
1941
Florin Coras7baeb712019-01-04 17:05:43 -08001942 listen_vlsh = ldp_fd_to_vlsh (listen_fd);
1943 if (listen_vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001944 {
1945 vppcom_endpt_t ep;
1946 u8 src_addr[sizeof (struct sockaddr_in6)];
Dave Wallace8aaba562018-01-18 17:21:19 -05001947 memset (&ep, 0, sizeof (ep));
Dave Wallace048b1d62018-01-03 22:24:41 -05001948 ep.ip = src_addr;
1949
Florin Coras7baeb712019-01-04 17:05:43 -08001950 LDBG (0, "listen fd %d: calling vppcom_session_accept: listen sid %u,"
1951 " ep %p, flags 0x%x", listen_fd, listen_vlsh, ep, flags);
Dave Wallace048b1d62018-01-03 22:24:41 -05001952
Florin Coras7baeb712019-01-04 17:05:43 -08001953 accept_vlsh = vls_accept (listen_vlsh, &ep, flags);
1954 if (accept_vlsh < 0)
Dave Wallace048b1d62018-01-03 22:24:41 -05001955 {
Florin Coras7baeb712019-01-04 17:05:43 -08001956 errno = -accept_vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001957 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001958 }
1959 else
1960 {
Dave Wallace2a865272018-02-07 21:00:42 -05001961 rv = ldp_copy_ep_to_sockaddr (addr, addr_len, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001962 if (rv != VPPCOM_OK)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001963 {
Florin Coras7baeb712019-01-04 17:05:43 -08001964 (void) vls_close (accept_vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05001965 errno = -rv;
1966 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001967 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001968 else
1969 {
Florin Coras7baeb712019-01-04 17:05:43 -08001970 rv = ldp_vlsh_to_fd (accept_vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05001971 }
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001972 }
1973 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001974 else
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001975 {
Florin Coras7baeb712019-01-04 17:05:43 -08001976 LDBG (0, "listen fd %d: calling libc_accept4(): addr %p, addr_len %p,"
1977 " flags 0x%x", listen_fd, addr, addr_len, flags);
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001978
Dave Wallace048b1d62018-01-03 22:24:41 -05001979 rv = libc_accept4 (listen_fd, addr, addr_len, flags);
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001980 }
1981
Florin Coras7baeb712019-01-04 17:05:43 -08001982 LDBG (1, "listen fd %d: accept returning %d", listen_fd, rv);
Florin Coras05ecfcc2018-12-12 18:19:39 -08001983
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001984 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001985}
1986
Dave Wallace048b1d62018-01-03 22:24:41 -05001987int
1988accept4 (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len,
1989 int flags)
1990{
Dave Wallace2a865272018-02-07 21:00:42 -05001991 return ldp_accept4 (fd, addr, addr_len, flags);
Dave Wallace048b1d62018-01-03 22:24:41 -05001992}
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001993
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001994int
Dave Wallace048b1d62018-01-03 22:24:41 -05001995accept (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001996{
Dave Wallace2a865272018-02-07 21:00:42 -05001997 return ldp_accept4 (fd, addr, addr_len, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05001998}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001999
Dave Wallace048b1d62018-01-03 22:24:41 -05002000int
2001shutdown (int fd, int how)
2002{
Florin Coras7baeb712019-01-04 17:05:43 -08002003 vls_handle_t vlsh;
2004 int rv = 0, flags;
2005 u32 flags_len = sizeof (flags);
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002006
Dave Wallace2a865272018-02-07 21:00:42 -05002007 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05002008 return -1;
2009
Florin Coras7baeb712019-01-04 17:05:43 -08002010 vlsh = ldp_fd_to_vlsh (fd);
2011 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05002012 {
Florin Coras7baeb712019-01-04 17:05:43 -08002013 LDBG (0, "called shutdown: fd %u vlsh %u how %d", fd, vlsh, how);
Florin Corasa7a1a222018-12-30 17:11:31 -08002014
Florin Coras7baeb712019-01-04 17:05:43 -08002015 if (vls_attr (vlsh, VPPCOM_ATTR_SET_SHUT, &how, &flags_len))
Florin Corasa7a1a222018-12-30 17:11:31 -08002016 {
Florin Coras7baeb712019-01-04 17:05:43 -08002017 close (fd);
Florin Corasa7a1a222018-12-30 17:11:31 -08002018 return -1;
2019 }
2020
Florin Coras7baeb712019-01-04 17:05:43 -08002021 if (vls_attr (vlsh, VPPCOM_ATTR_GET_SHUT, &flags, &flags_len))
2022 {
2023 close (fd);
2024 return -1;
2025 }
Florin Corasa7a1a222018-12-30 17:11:31 -08002026
Florin Coras7baeb712019-01-04 17:05:43 -08002027 if (flags == SHUT_RDWR)
Florin Corasa7a1a222018-12-30 17:11:31 -08002028 rv = close (fd);
Dave Wallace048b1d62018-01-03 22:24:41 -05002029 }
2030 else
2031 {
Florin Coras7baeb712019-01-04 17:05:43 -08002032 LDBG (0, "fd %d: calling libc_shutdown: how %d", fd, how);
Dave Wallace048b1d62018-01-03 22:24:41 -05002033 rv = libc_shutdown (fd, how);
2034 }
2035
Dave Wallace048b1d62018-01-03 22:24:41 -05002036 return rv;
2037}
2038
2039int
2040epoll_create1 (int flags)
2041{
Florin Corasdfe4cf42018-11-28 22:13:45 -08002042 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras7baeb712019-01-04 17:05:43 -08002043 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002044 int rv;
2045
Dave Wallace2a865272018-02-07 21:00:42 -05002046 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05002047 return -1;
2048
Florin Coras99368312018-08-02 10:45:44 -07002049 if (ldp->vcl_needs_real_epoll)
2050 {
Florin Coras2d9b4272019-03-11 10:14:37 -07002051 /* Make sure workers have been allocated */
2052 if (!ldp->workers)
2053 {
2054 ldp_alloc_workers ();
2055 ldpw = ldp_worker_get_current ();
2056 }
Florin Coras99368312018-08-02 10:45:44 -07002057 rv = libc_epoll_create1 (flags);
2058 ldp->vcl_needs_real_epoll = 0;
Florin Corasdfe4cf42018-11-28 22:13:45 -08002059 ldpw->vcl_mq_epfd = rv;
Florin Coras05ecfcc2018-12-12 18:19:39 -08002060 LDBG (0, "created vcl epfd %u", rv);
Florin Coras99368312018-08-02 10:45:44 -07002061 return rv;
2062 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002063
Florin Coras7baeb712019-01-04 17:05:43 -08002064 vlsh = vls_epoll_create ();
2065 if (PREDICT_FALSE (vlsh == VLS_INVALID_HANDLE))
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002066 {
Florin Coras7baeb712019-01-04 17:05:43 -08002067 errno = -vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002068 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002069 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002070 else
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002071 {
Florin Coras7baeb712019-01-04 17:05:43 -08002072 rv = ldp_vlsh_to_fd (vlsh);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002073 }
Florin Coras7baeb712019-01-04 17:05:43 -08002074 LDBG (0, "epoll_create epfd %u vlsh %u", rv, vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05002075 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002076}
2077
2078int
Dave Wallace048b1d62018-01-03 22:24:41 -05002079epoll_create (int size)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002080{
Dave Wallace048b1d62018-01-03 22:24:41 -05002081 return epoll_create1 (0);
2082}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002083
Dave Wallace048b1d62018-01-03 22:24:41 -05002084int
2085epoll_ctl (int epfd, int op, int fd, struct epoll_event *event)
2086{
Florin Coras7baeb712019-01-04 17:05:43 -08002087 vls_handle_t vep_vlsh, vlsh;
Florin Coras99368312018-08-02 10:45:44 -07002088 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05002089
Dave Wallace2a865272018-02-07 21:00:42 -05002090 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05002091 return -1;
2092
Florin Coras7baeb712019-01-04 17:05:43 -08002093 vep_vlsh = ldp_fd_to_vlsh (epfd);
2094 if (PREDICT_FALSE (vep_vlsh == VLS_INVALID_HANDLE))
Dave Wallace048b1d62018-01-03 22:24:41 -05002095 {
Dave Wallace3ee1fe12018-02-23 01:09:11 -05002096 /* The LDP epoll_create1 always creates VCL epfd's.
2097 * The app should never have a kernel base epoll fd unless it
2098 * was acquired outside of the LD_PRELOAD process context.
2099 * In any case, if we get one, punt it to libc_epoll_ctl.
2100 */
Florin Coras7baeb712019-01-04 17:05:43 -08002101 LDBG (1, "epfd %d: calling libc_epoll_ctl: op %d, fd %d"
2102 " event %p", epfd, op, fd, event);
Dave Wallace048b1d62018-01-03 22:24:41 -05002103
2104 rv = libc_epoll_ctl (epfd, op, fd, event);
Florin Coras99368312018-08-02 10:45:44 -07002105 goto done;
2106 }
2107
Florin Coras7baeb712019-01-04 17:05:43 -08002108 vlsh = ldp_fd_to_vlsh (fd);
Florin Coras99368312018-08-02 10:45:44 -07002109
Florin Coras7baeb712019-01-04 17:05:43 -08002110 LDBG (0, "epfd %d ep_vlsh %d, fd %u vlsh %d, op %u", epfd, vep_vlsh, fd,
2111 vlsh, op);
Florin Coras99368312018-08-02 10:45:44 -07002112
Florin Coras7baeb712019-01-04 17:05:43 -08002113 if (vlsh != VLS_INVALID_HANDLE)
Florin Coras99368312018-08-02 10:45:44 -07002114 {
Florin Coras7baeb712019-01-04 17:05:43 -08002115 LDBG (1, "epfd %d: calling vls_epoll_ctl: ep_vlsh %d op %d, vlsh %u,"
2116 " event %p", epfd, vep_vlsh, vlsh, event);
Florin Coras99368312018-08-02 10:45:44 -07002117
Florin Coras7baeb712019-01-04 17:05:43 -08002118 rv = vls_epoll_ctl (vep_vlsh, op, vlsh, event);
Florin Coras99368312018-08-02 10:45:44 -07002119 if (rv != VPPCOM_OK)
2120 {
2121 errno = -rv;
2122 rv = -1;
2123 }
2124 }
2125 else
2126 {
2127 int libc_epfd;
2128 u32 size = sizeof (epfd);
2129
Florin Coras7baeb712019-01-04 17:05:43 -08002130 libc_epfd = vls_attr (vep_vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
Florin Coras99368312018-08-02 10:45:44 -07002131 if (!libc_epfd)
2132 {
Florin Coras7baeb712019-01-04 17:05:43 -08002133 LDBG (1, "epfd %d, vep_vlsh %d calling libc_epoll_create1: "
2134 "EPOLL_CLOEXEC", epfd, vep_vlsh);
Florin Coras99368312018-08-02 10:45:44 -07002135
2136 libc_epfd = libc_epoll_create1 (EPOLL_CLOEXEC);
2137 if (libc_epfd < 0)
2138 {
2139 rv = libc_epfd;
2140 goto done;
2141 }
2142
Florin Coras7baeb712019-01-04 17:05:43 -08002143 rv = vls_attr (vep_vlsh, VPPCOM_ATTR_SET_LIBC_EPFD, &libc_epfd,
2144 &size);
Florin Coras99368312018-08-02 10:45:44 -07002145 if (rv < 0)
2146 {
2147 errno = -rv;
2148 rv = -1;
2149 goto done;
2150 }
2151 }
2152 else if (PREDICT_FALSE (libc_epfd < 0))
2153 {
2154 errno = -epfd;
2155 rv = -1;
2156 goto done;
2157 }
2158
Florin Coras7baeb712019-01-04 17:05:43 -08002159 LDBG (1, "epfd %d: calling libc_epoll_ctl: libc_epfd %d, op %d, fd %d,"
2160 " event %p", epfd, libc_epfd, op, fd, event);
Florin Coras99368312018-08-02 10:45:44 -07002161
2162 rv = libc_epoll_ctl (libc_epfd, op, fd, event);
Dave Wallace048b1d62018-01-03 22:24:41 -05002163 }
2164
2165done:
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002166 return rv;
2167}
Dave Wallace048b1d62018-01-03 22:24:41 -05002168
2169static inline int
Florin Coras99368312018-08-02 10:45:44 -07002170ldp_epoll_pwait (int epfd, struct epoll_event *events, int maxevents,
2171 int timeout, const sigset_t * sigmask)
Dave Wallace048b1d62018-01-03 22:24:41 -05002172{
Florin Corasdfe4cf42018-11-28 22:13:45 -08002173 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras72f77822019-01-22 19:05:52 -08002174 double time_to_wait = (double) 0, max_time;
Florin Coras99368312018-08-02 10:45:44 -07002175 int libc_epfd, rv = 0;
Florin Coras7baeb712019-01-04 17:05:43 -08002176 vls_handle_t ep_vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002177
Dave Wallace2a865272018-02-07 21:00:42 -05002178 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05002179 return -1;
2180
2181 if (PREDICT_FALSE (!events || (timeout < -1)))
2182 {
2183 errno = EFAULT;
2184 return -1;
2185 }
2186
Florin Corasdfe4cf42018-11-28 22:13:45 -08002187 if (epfd == ldpw->vcl_mq_epfd)
Florin Coras99368312018-08-02 10:45:44 -07002188 return libc_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
2189
Florin Coras7baeb712019-01-04 17:05:43 -08002190 ep_vlsh = ldp_fd_to_vlsh (epfd);
2191 if (PREDICT_FALSE (ep_vlsh == VLS_INVALID_HANDLE))
Dave Wallace048b1d62018-01-03 22:24:41 -05002192 {
Florin Coras7baeb712019-01-04 17:05:43 -08002193 LDBG (0, "epfd %d: bad ep_vlsh %d!", epfd, ep_vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05002194 errno = EBADFD;
2195 return -1;
2196 }
2197
Florin Coras4dee8cd2019-01-29 21:28:16 -08002198 if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
2199 clib_time_init (&ldpw->clib_time);
Florin Corasb0f662f2018-12-27 14:51:46 -08002200 time_to_wait = ((timeout >= 0) ? (double) timeout / 1000 : 0);
Florin Coras72f77822019-01-22 19:05:52 -08002201 max_time = clib_time_now (&ldpw->clib_time) + time_to_wait;
Dave Wallace048b1d62018-01-03 22:24:41 -05002202
Florin Coras7baeb712019-01-04 17:05:43 -08002203 libc_epfd = vls_attr (ep_vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002204 if (PREDICT_FALSE (libc_epfd < 0))
2205 {
2206 errno = -libc_epfd;
2207 rv = -1;
2208 goto done;
2209 }
2210
Florin Coras7baeb712019-01-04 17:05:43 -08002211 LDBG (2, "epfd %d: vep_idx %d, libc_epfd %d, events %p, maxevents %d, "
2212 "timeout %d, sigmask %p: time_to_wait %.02f", epfd, ep_vlsh,
Florin Coras72f77822019-01-22 19:05:52 -08002213 libc_epfd, events, maxevents, timeout, sigmask, time_to_wait);
Dave Wallace048b1d62018-01-03 22:24:41 -05002214 do
2215 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002216 if (!ldpw->epoll_wait_vcl)
Dave Wallace048b1d62018-01-03 22:24:41 -05002217 {
Florin Coras7baeb712019-01-04 17:05:43 -08002218 rv = vls_epoll_wait (ep_vlsh, events, maxevents, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002219 if (rv > 0)
2220 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002221 ldpw->epoll_wait_vcl = 1;
Dave Wallace048b1d62018-01-03 22:24:41 -05002222 goto done;
2223 }
2224 else if (rv < 0)
2225 {
2226 errno = -rv;
2227 rv = -1;
2228 goto done;
2229 }
2230 }
2231 else
Florin Corasdfe4cf42018-11-28 22:13:45 -08002232 ldpw->epoll_wait_vcl = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -05002233
2234 if (libc_epfd > 0)
2235 {
Florin Corasb0f662f2018-12-27 14:51:46 -08002236 rv = libc_epoll_pwait (libc_epfd, events, maxevents, 0, sigmask);
Dave Wallace048b1d62018-01-03 22:24:41 -05002237 if (rv != 0)
2238 goto done;
2239 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002240 }
Florin Coras72f77822019-01-22 19:05:52 -08002241 while ((timeout == -1) || (clib_time_now (&ldpw->clib_time) < max_time));
Dave Wallace048b1d62018-01-03 22:24:41 -05002242
2243done:
Dave Wallace048b1d62018-01-03 22:24:41 -05002244 return rv;
2245}
2246
2247int
2248epoll_pwait (int epfd, struct epoll_event *events,
2249 int maxevents, int timeout, const sigset_t * sigmask)
2250{
Dave Wallace2a865272018-02-07 21:00:42 -05002251 return ldp_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
Dave Wallace048b1d62018-01-03 22:24:41 -05002252}
2253
2254int
2255epoll_wait (int epfd, struct epoll_event *events, int maxevents, int timeout)
2256{
Dave Wallace2a865272018-02-07 21:00:42 -05002257 return ldp_epoll_pwait (epfd, events, maxevents, timeout, NULL);
Dave Wallace048b1d62018-01-03 22:24:41 -05002258}
2259
2260int
2261poll (struct pollfd *fds, nfds_t nfds, int timeout)
2262{
Florin Corasdfe4cf42018-11-28 22:13:45 -08002263 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras6917b942018-11-13 22:44:54 -08002264 int rv, i, n_revents = 0;
Florin Coras7baeb712019-01-04 17:05:43 -08002265 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002266 vcl_poll_t *vp;
Florin Coras4dee8cd2019-01-29 21:28:16 -08002267 double max_time;
Dave Wallace048b1d62018-01-03 22:24:41 -05002268
Florin Coras05ecfcc2018-12-12 18:19:39 -08002269 LDBG (3, "fds %p, nfds %d, timeout %d", fds, nfds, timeout);
Dave Wallace048b1d62018-01-03 22:24:41 -05002270
Florin Coras4dee8cd2019-01-29 21:28:16 -08002271 if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
2272 clib_time_init (&ldpw->clib_time);
2273
2274 max_time = (timeout >= 0) ? (f64) timeout / 1000 : 0;
2275 max_time += clib_time_now (&ldpw->clib_time);
Dave Wallace048b1d62018-01-03 22:24:41 -05002276
Dave Wallace048b1d62018-01-03 22:24:41 -05002277 for (i = 0; i < nfds; i++)
2278 {
Florin Coras6917b942018-11-13 22:44:54 -08002279 if (fds[i].fd < 0)
2280 continue;
Dave Wallace048b1d62018-01-03 22:24:41 -05002281
Florin Coras7baeb712019-01-04 17:05:43 -08002282 vlsh = ldp_fd_to_vlsh (fds[i].fd);
2283 if (vlsh != VLS_INVALID_HANDLE)
Florin Coras6917b942018-11-13 22:44:54 -08002284 {
2285 fds[i].fd = -fds[i].fd;
Florin Corasdfe4cf42018-11-28 22:13:45 -08002286 vec_add2 (ldpw->vcl_poll, vp, 1);
Florin Coras6917b942018-11-13 22:44:54 -08002287 vp->fds_ndx = i;
Florin Coras7baeb712019-01-04 17:05:43 -08002288 vp->sh = vlsh_to_sh (vlsh);
Florin Coras6917b942018-11-13 22:44:54 -08002289 vp->events = fds[i].events;
Dave Wallace048b1d62018-01-03 22:24:41 -05002290#ifdef __USE_XOPEN2K
Florin Coras6917b942018-11-13 22:44:54 -08002291 if (fds[i].events & POLLRDNORM)
2292 vp->events |= POLLIN;
2293 if (fds[i].events & POLLWRNORM)
2294 vp->events |= POLLOUT;
Dave Wallace048b1d62018-01-03 22:24:41 -05002295#endif
Florin Coras6917b942018-11-13 22:44:54 -08002296 vp->revents = fds[i].revents;
2297 }
2298 else
2299 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002300 vec_add1 (ldpw->libc_poll, fds[i]);
2301 vec_add1 (ldpw->libc_poll_idxs, i);
Dave Wallace048b1d62018-01-03 22:24:41 -05002302 }
2303 }
2304
Dave Wallace048b1d62018-01-03 22:24:41 -05002305 do
2306 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002307 if (vec_len (ldpw->vcl_poll))
Dave Wallace048b1d62018-01-03 22:24:41 -05002308 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002309 rv = vppcom_poll (ldpw->vcl_poll, vec_len (ldpw->vcl_poll), 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002310 if (rv < 0)
2311 {
2312 errno = -rv;
2313 rv = -1;
2314 goto done;
2315 }
2316 else
2317 n_revents += rv;
2318 }
2319
Florin Corasdfe4cf42018-11-28 22:13:45 -08002320 if (vec_len (ldpw->libc_poll))
Dave Wallace048b1d62018-01-03 22:24:41 -05002321 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002322 rv = libc_poll (ldpw->libc_poll, vec_len (ldpw->libc_poll), 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002323 if (rv < 0)
2324 goto done;
2325 else
2326 n_revents += rv;
2327 }
2328
2329 if (n_revents)
2330 {
2331 rv = n_revents;
2332 goto done;
2333 }
2334 }
Florin Coras4dee8cd2019-01-29 21:28:16 -08002335 while ((timeout < 0) || (clib_time_now (&ldpw->clib_time) < max_time));
Dave Wallace048b1d62018-01-03 22:24:41 -05002336 rv = 0;
2337
2338done:
Florin Corasdfe4cf42018-11-28 22:13:45 -08002339 vec_foreach (vp, ldpw->vcl_poll)
Dave Wallace048b1d62018-01-03 22:24:41 -05002340 {
2341 fds[vp->fds_ndx].fd = -fds[vp->fds_ndx].fd;
Florin Coras6917b942018-11-13 22:44:54 -08002342 fds[vp->fds_ndx].revents = vp->revents;
Dave Wallace048b1d62018-01-03 22:24:41 -05002343#ifdef __USE_XOPEN2K
2344 if ((fds[vp->fds_ndx].revents & POLLIN) &&
2345 (fds[vp->fds_ndx].events & POLLRDNORM))
2346 fds[vp->fds_ndx].revents |= POLLRDNORM;
2347 if ((fds[vp->fds_ndx].revents & POLLOUT) &&
2348 (fds[vp->fds_ndx].events & POLLWRNORM))
2349 fds[vp->fds_ndx].revents |= POLLWRNORM;
2350#endif
2351 }
Florin Corasdfe4cf42018-11-28 22:13:45 -08002352 vec_reset_length (ldpw->vcl_poll);
Dave Wallace048b1d62018-01-03 22:24:41 -05002353
Florin Corasdfe4cf42018-11-28 22:13:45 -08002354 for (i = 0; i < vec_len (ldpw->libc_poll); i++)
Florin Coras6917b942018-11-13 22:44:54 -08002355 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002356 fds[ldpw->libc_poll_idxs[i]].revents = ldpw->libc_poll[i].revents;
Florin Coras6917b942018-11-13 22:44:54 -08002357 }
Florin Corasdfe4cf42018-11-28 22:13:45 -08002358 vec_reset_length (ldpw->libc_poll_idxs);
2359 vec_reset_length (ldpw->libc_poll);
Florin Coras6917b942018-11-13 22:44:54 -08002360
Dave Wallace048b1d62018-01-03 22:24:41 -05002361 return rv;
2362}
2363
2364#ifdef USE_GNU
2365int
2366ppoll (struct pollfd *fds, nfds_t nfds,
2367 const struct timespec *timeout, const sigset_t * sigmask)
2368{
Dave Wallace2a865272018-02-07 21:00:42 -05002369 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05002370 return -1;
2371
2372 clib_warning ("LDP<%d>: LDP-TBD", getpid ());
2373 errno = ENOSYS;
2374
2375
2376 return -1;
2377}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002378#endif
2379
Dave Wallace2a865272018-02-07 21:00:42 -05002380void CONSTRUCTOR_ATTRIBUTE ldp_constructor (void);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002381
Dave Wallace2a865272018-02-07 21:00:42 -05002382void DESTRUCTOR_ATTRIBUTE ldp_destructor (void);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002383
Dave Wallace048b1d62018-01-03 22:24:41 -05002384/*
2385 * This function is called when the library is loaded
2386 */
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002387void
Dave Wallace2a865272018-02-07 21:00:42 -05002388ldp_constructor (void)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002389{
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002390 swrap_constructor ();
Dave Wallace2a865272018-02-07 21:00:42 -05002391 if (ldp_init () != 0)
2392 fprintf (stderr, "\nLDP<%d>: ERROR: ldp_constructor: failed!\n",
Dave Wallace048b1d62018-01-03 22:24:41 -05002393 getpid ());
Dave Wallace69d01192018-02-22 16:22:09 -05002394 else if (LDP_DEBUG > 0)
Dave Wallace2a865272018-02-07 21:00:42 -05002395 clib_warning ("LDP<%d>: LDP constructor: done!\n", getpid ());
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002396}
2397
2398/*
2399 * This function is called when the library is unloaded
2400 */
2401void
Dave Wallace2a865272018-02-07 21:00:42 -05002402ldp_destructor (void)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002403{
Florin Coras0ef8ef22019-01-18 08:37:13 -08002404 /*
2405 swrap_destructor ();
2406 if (ldp->init)
2407 ldp->init = 0;
2408 */
Dave Wallace048b1d62018-01-03 22:24:41 -05002409
2410 /* Don't use clib_warning() here because that calls writev()
Dave Wallace2a865272018-02-07 21:00:42 -05002411 * which will call ldp_init().
Dave Wallace048b1d62018-01-03 22:24:41 -05002412 */
Dave Wallace69d01192018-02-22 16:22:09 -05002413 if (LDP_DEBUG > 0)
Florin Coras0ef8ef22019-01-18 08:37:13 -08002414 fprintf (stderr, "%s:%d: LDP<%d>: LDP destructor: done!\n",
2415 __func__, __LINE__, getpid ());
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002416}
2417
2418
2419/*
2420 * fd.io coding-style-patch-verification: ON
2421 *
2422 * Local Variables:
2423 * eval: (c-set-style "gnu")
2424 * End:
2425 */