blob: 2468bcc475090297fdf8165fc1ff32a913d820d3 [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
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700164static inline int
Dave Wallace2a865272018-02-07 21:00:42 -0500165ldp_init (void)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700166{
Florin Corasdfe4cf42018-11-28 22:13:45 -0800167 ldp_worker_ctx_t *ldpw;
Florin Coras99368312018-08-02 10:45:44 -0700168 int rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700169
Florin Coras99368312018-08-02 10:45:44 -0700170 if (PREDICT_TRUE (ldp->init))
171 return 0;
172
173 ldp->init = 1;
174 ldp->vcl_needs_real_epoll = 1;
Florin Coras7baeb712019-01-04 17:05:43 -0800175 rv = vls_app_create (ldp_get_app_name ());
Florin Coras99368312018-08-02 10:45:44 -0700176 if (rv != VPPCOM_OK)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700177 {
Florin Coras955bfbb2018-12-04 13:43:45 -0800178 ldp->vcl_needs_real_epoll = 0;
179 if (rv == VPPCOM_EEXIST)
180 return 0;
Florin Coras05ecfcc2018-12-12 18:19:39 -0800181 LDBG (2, "\nERROR: ldp_init: vppcom_app_create()"
182 " failed! rv = %d (%s)\n", rv, vppcom_retval_str (rv));
Florin Coras99368312018-08-02 10:45:44 -0700183 ldp->init = 0;
184 return rv;
185 }
186 ldp->vcl_needs_real_epoll = 0;
Florin Corasdfe4cf42018-11-28 22:13:45 -0800187 pool_alloc (ldp->workers, LDP_MAX_NWORKERS);
188 ldpw = ldp_worker_get_current ();
Florin Coras99368312018-08-02 10:45:44 -0700189
190 char *env_var_str = getenv (LDP_ENV_DEBUG);
191 if (env_var_str)
192 {
193 u32 tmp;
194 if (sscanf (env_var_str, "%u", &tmp) != 1)
195 clib_warning ("LDP<%d>: WARNING: Invalid LDP debug level specified in"
196 " the env var " LDP_ENV_DEBUG " (%s)!", getpid (),
197 env_var_str);
198 else
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700199 {
Florin Coras99368312018-08-02 10:45:44 -0700200 ldp->debug = tmp;
Florin Coras05ecfcc2018-12-12 18:19:39 -0800201 LDBG (0, "configured LDP debug level (%u) from env var "
202 LDP_ENV_DEBUG "!", ldp->debug);
Florin Coras99368312018-08-02 10:45:44 -0700203 }
204 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500205
Florin Coras99368312018-08-02 10:45:44 -0700206 env_var_str = getenv (LDP_ENV_APP_NAME);
207 if (env_var_str)
208 {
209 ldp_set_app_name (env_var_str);
Florin Coras05ecfcc2018-12-12 18:19:39 -0800210 LDBG (0, "configured LDP app name (%s) from the env var "
211 LDP_ENV_APP_NAME "!", ldp->app_name);
Florin Coras99368312018-08-02 10:45:44 -0700212 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500213
Florin Coras99368312018-08-02 10:45:44 -0700214 env_var_str = getenv (LDP_ENV_SID_BIT);
215 if (env_var_str)
216 {
217 u32 sb;
218 if (sscanf (env_var_str, "%u", &sb) != 1)
219 {
Florin Coras294afe22019-01-07 17:49:17 -0800220 LDBG (0, "WARNING: Invalid LDP sid bit specified in the env var "
221 LDP_ENV_SID_BIT " (%s)! sid bit value %d (0x%x)", env_var_str,
222 ldp->vlsh_bit_val, ldp->vlsh_bit_val);
Florin Coras99368312018-08-02 10:45:44 -0700223 }
224 else if (sb < LDP_SID_BIT_MIN)
225 {
Florin Coras7baeb712019-01-04 17:05:43 -0800226 ldp->vlsh_bit_val = (1 << LDP_SID_BIT_MIN);
227 ldp->vlsh_bit_mask = ldp->vlsh_bit_val - 1;
Dave Wallace048b1d62018-01-03 22:24:41 -0500228
Florin Coras294afe22019-01-07 17:49:17 -0800229 LDBG (0, "WARNING: LDP sid bit (%u) specified in the env var "
230 LDP_ENV_SID_BIT " (%s) is too small. Using LDP_SID_BIT_MIN"
231 " (%d)! sid bit value %d (0x%x)", sb, env_var_str,
232 LDP_SID_BIT_MIN, ldp->vlsh_bit_val, ldp->vlsh_bit_val);
Florin Coras99368312018-08-02 10:45:44 -0700233 }
234 else if (sb > LDP_SID_BIT_MAX)
235 {
Florin Coras7baeb712019-01-04 17:05:43 -0800236 ldp->vlsh_bit_val = (1 << LDP_SID_BIT_MAX);
237 ldp->vlsh_bit_mask = ldp->vlsh_bit_val - 1;
Dave Wallace048b1d62018-01-03 22:24:41 -0500238
Florin Coras294afe22019-01-07 17:49:17 -0800239 LDBG (0, "WARNING: LDP sid bit (%u) specified in the env var "
240 LDP_ENV_SID_BIT " (%s) is too big. Using LDP_SID_BIT_MAX"
241 " (%d)! sid bit value %d (0x%x)", sb, env_var_str,
242 LDP_SID_BIT_MAX, ldp->vlsh_bit_val, ldp->vlsh_bit_val);
Dave Wallace048b1d62018-01-03 22:24:41 -0500243 }
244 else
245 {
Florin Coras7baeb712019-01-04 17:05:43 -0800246 ldp->vlsh_bit_val = (1 << sb);
247 ldp->vlsh_bit_mask = ldp->vlsh_bit_val - 1;
Florin Coras99368312018-08-02 10:45:44 -0700248
Florin Coras05ecfcc2018-12-12 18:19:39 -0800249 LDBG (0, "configured LDP sid bit (%u) from "
250 LDP_ENV_SID_BIT "! sid bit value %d (0x%x)", sb,
Florin Coras7baeb712019-01-04 17:05:43 -0800251 ldp->vlsh_bit_val, ldp->vlsh_bit_val);
Dave Wallace048b1d62018-01-03 22:24:41 -0500252 }
Florin Coras294afe22019-01-07 17:49:17 -0800253
254 /* Make sure there are enough bits in the fd set for vcl sessions */
255 if (ldp->vlsh_bit_val > FD_SETSIZE / 2)
256 {
257 LDBG (0, "ERROR: LDP vlsh bit value %d > FD_SETSIZE/2 %d!",
258 ldp->vlsh_bit_val, FD_SETSIZE / 2);
259 ldp->init = 0;
260 return -1;
261 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500262 }
Florin Coras99368312018-08-02 10:45:44 -0700263
Florin Coras4dee8cd2019-01-29 21:28:16 -0800264 /* *INDENT-OFF* */
265 pool_foreach (ldpw, ldp->workers, ({
266 clib_memset (&ldpw->clib_time, 0, sizeof (ldpw->clib_time));
267 }));
268 /* *INDENT-ON* */
269
Florin Coras05ecfcc2018-12-12 18:19:39 -0800270 LDBG (0, "LDP initialization: done!");
Florin Coras99368312018-08-02 10:45:44 -0700271
272 return 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500273}
274
275int
276close (int fd)
277{
Florin Coras7baeb712019-01-04 17:05:43 -0800278 vls_handle_t vlsh;
279 int rv, epfd;
Dave Wallace048b1d62018-01-03 22:24:41 -0500280
Dave Wallace2a865272018-02-07 21:00:42 -0500281 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500282 return -1;
283
Florin Coras7baeb712019-01-04 17:05:43 -0800284 vlsh = ldp_fd_to_vlsh (fd);
285 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500286 {
Florin Coras7baeb712019-01-04 17:05:43 -0800287 epfd = vls_attr (vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -0500288 if (epfd > 0)
289 {
Florin Coras7baeb712019-01-04 17:05:43 -0800290 LDBG (0, "fd %d: calling libc_close: epfd %u", fd, epfd);
Dave Wallace048b1d62018-01-03 22:24:41 -0500291
292 rv = libc_close (epfd);
293 if (rv < 0)
294 {
295 u32 size = sizeof (epfd);
296 epfd = 0;
297
Florin Coras7baeb712019-01-04 17:05:43 -0800298 (void) vls_attr (vlsh, VPPCOM_ATTR_SET_LIBC_EPFD, &epfd, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -0500299 }
300 }
301 else if (PREDICT_FALSE (epfd < 0))
302 {
303 errno = -epfd;
304 rv = -1;
305 goto done;
306 }
307
Florin Coras7baeb712019-01-04 17:05:43 -0800308 LDBG (0, "fd %d: calling vls_close: vlsh %u", fd, vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -0500309
Florin Coras7baeb712019-01-04 17:05:43 -0800310 rv = vls_close (vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -0500311 if (rv != VPPCOM_OK)
312 {
313 errno = -rv;
314 rv = -1;
315 }
316 }
317 else
318 {
Florin Coras7baeb712019-01-04 17:05:43 -0800319 LDBG (0, "fd %d: calling libc_close", fd);
Dave Wallace048b1d62018-01-03 22:24:41 -0500320 rv = libc_close (fd);
321 }
322
323done:
Dave Wallace048b1d62018-01-03 22:24:41 -0500324 return rv;
325}
326
327ssize_t
328read (int fd, void *buf, size_t nbytes)
329{
Florin Coras7baeb712019-01-04 17:05:43 -0800330 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500331 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -0500332
Dave Wallace2a865272018-02-07 21:00:42 -0500333 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500334 return -1;
335
Florin Coras7baeb712019-01-04 17:05:43 -0800336 vlsh = ldp_fd_to_vlsh (fd);
337 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500338 {
Florin Coras7baeb712019-01-04 17:05:43 -0800339 size = vls_read (vlsh, buf, nbytes);
Dave Wallace048b1d62018-01-03 22:24:41 -0500340 if (size < 0)
341 {
342 errno = -size;
343 size = -1;
344 }
345 }
346 else
347 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500348 size = libc_read (fd, buf, nbytes);
349 }
350
Dave Wallace048b1d62018-01-03 22:24:41 -0500351 return size;
352}
353
354ssize_t
355readv (int fd, const struct iovec * iov, int iovcnt)
356{
Dave Wallace8aaba562018-01-18 17:21:19 -0500357 int rv = 0, i, total = 0;
Florin Coras7baeb712019-01-04 17:05:43 -0800358 vls_handle_t vlsh;
359 ssize_t size = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500360
Dave Wallace2a865272018-02-07 21:00:42 -0500361 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500362 return -1;
363
Florin Coras7baeb712019-01-04 17:05:43 -0800364 vlsh = ldp_fd_to_vlsh (fd);
365 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500366 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500367 do
368 {
369 for (i = 0; i < iovcnt; ++i)
370 {
Florin Coras7baeb712019-01-04 17:05:43 -0800371 rv = vls_read (vlsh, iov[i].iov_base, iov[i].iov_len);
Dave Wallace048b1d62018-01-03 22:24:41 -0500372 if (rv < 0)
373 break;
374 else
375 {
376 total += rv;
377 if (rv < iov[i].iov_len)
Florin Coras7baeb712019-01-04 17:05:43 -0800378 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700379 }
380 }
381 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500382 while ((rv >= 0) && (total == 0));
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700383
Dave Wallace048b1d62018-01-03 22:24:41 -0500384 if (rv < 0)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700385 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500386 errno = -rv;
387 size = -1;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700388 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500389 else
390 size = total;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700391 }
392 else
393 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500394 size = libc_readv (fd, iov, iovcnt);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700395 }
396
Dave Wallace048b1d62018-01-03 22:24:41 -0500397 return size;
398}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700399
Dave Wallace048b1d62018-01-03 22:24:41 -0500400ssize_t
401write (int fd, const void *buf, size_t nbytes)
402{
Florin Coras7baeb712019-01-04 17:05:43 -0800403 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500404 ssize_t size = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500405
Dave Wallace2a865272018-02-07 21:00:42 -0500406 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500407 return -1;
408
Florin Coras7baeb712019-01-04 17:05:43 -0800409 vlsh = ldp_fd_to_vlsh (fd);
410 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500411 {
Florin Coras7baeb712019-01-04 17:05:43 -0800412 size = vls_write_msg (vlsh, (void *) buf, nbytes);
Dave Wallace048b1d62018-01-03 22:24:41 -0500413 if (size < 0)
414 {
415 errno = -size;
416 size = -1;
417 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700418 }
419 else
420 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500421 size = libc_write (fd, buf, nbytes);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700422 }
423
Dave Wallace048b1d62018-01-03 22:24:41 -0500424 return size;
425}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700426
Dave Wallace048b1d62018-01-03 22:24:41 -0500427ssize_t
428writev (int fd, const struct iovec * iov, int iovcnt)
429{
Dave Wallace048b1d62018-01-03 22:24:41 -0500430 ssize_t size = 0, total = 0;
Florin Coras7baeb712019-01-04 17:05:43 -0800431 vls_handle_t vlsh;
Dave Wallace8aaba562018-01-18 17:21:19 -0500432 int i, rv = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500433
Dave Wallace2a865272018-02-07 21:00:42 -0500434 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500435 return -1;
436
Florin Coras7baeb712019-01-04 17:05:43 -0800437 vlsh = ldp_fd_to_vlsh (fd);
438 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500439 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500440 do
441 {
442 for (i = 0; i < iovcnt; ++i)
443 {
Florin Coras7baeb712019-01-04 17:05:43 -0800444 rv = vls_write_msg (vlsh, iov[i].iov_base, iov[i].iov_len);
Dave Wallace048b1d62018-01-03 22:24:41 -0500445 if (rv < 0)
446 break;
447 else
448 {
449 total += rv;
450 if (rv < iov[i].iov_len)
Florin Corasb0f662f2018-12-27 14:51:46 -0800451 break;
Dave Wallace048b1d62018-01-03 22:24:41 -0500452 }
453 }
454 }
455 while ((rv >= 0) && (total == 0));
456
457 if (rv < 0)
458 {
459 errno = -rv;
460 size = -1;
461 }
462 else
463 size = total;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700464 }
465 else
466 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500467 size = libc_writev (fd, iov, iovcnt);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700468 }
469
Dave Wallace048b1d62018-01-03 22:24:41 -0500470 return size;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700471}
472
473int
Dave Wallace048b1d62018-01-03 22:24:41 -0500474fcntl (int fd, int cmd, ...)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700475{
Florin Coras7baeb712019-01-04 17:05:43 -0800476 vls_handle_t vlsh;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700477 int rv = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500478 va_list ap;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700479
Dave Wallace2a865272018-02-07 21:00:42 -0500480 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500481 return -1;
482
483 va_start (ap, cmd);
Florin Coras7baeb712019-01-04 17:05:43 -0800484
485 vlsh = ldp_fd_to_vlsh (fd);
486 LDBG (0, "fd %u vlsh %d, cmd %u", fd, vlsh, cmd);
487 if (vlsh != VLS_INVALID_HANDLE)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700488 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500489 int flags = va_arg (ap, int);
490 u32 size;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700491
Dave Wallace048b1d62018-01-03 22:24:41 -0500492 size = sizeof (flags);
493 rv = -EOPNOTSUPP;
494 switch (cmd)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700495 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500496 case F_SETFL:
Florin Coras7baeb712019-01-04 17:05:43 -0800497 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_FLAGS, &flags, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -0500498 break;
499
500 case F_GETFL:
Florin Coras7baeb712019-01-04 17:05:43 -0800501 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_FLAGS, &flags, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -0500502 if (rv == VPPCOM_OK)
Florin Coras7baeb712019-01-04 17:05:43 -0800503 rv = flags;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700504 break;
Florin Coras173bae32018-11-16 18:56:28 -0800505 case F_SETFD:
506 /* TODO handle this */
507 LDBG (0, "F_SETFD ignored flags %u", flags);
508 rv = 0;
509 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700510 default:
Dave Wallace048b1d62018-01-03 22:24:41 -0500511 rv = -EOPNOTSUPP;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700512 break;
513 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500514 if (rv < 0)
515 {
516 errno = -rv;
517 rv = -1;
518 }
519 }
520 else
521 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500522 rv = libc_vfcntl (fd, cmd, ap);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700523 }
524
Dave Wallace048b1d62018-01-03 22:24:41 -0500525 va_end (ap);
526
Dave Wallace048b1d62018-01-03 22:24:41 -0500527 return rv;
528}
529
530int
531ioctl (int fd, unsigned long int cmd, ...)
532{
Florin Coras7baeb712019-01-04 17:05:43 -0800533 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500534 va_list ap;
Florin Coras7baeb712019-01-04 17:05:43 -0800535 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -0500536
Dave Wallace2a865272018-02-07 21:00:42 -0500537 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500538 return -1;
539
540 va_start (ap, cmd);
Dave Wallace048b1d62018-01-03 22:24:41 -0500541
Florin Coras7baeb712019-01-04 17:05:43 -0800542 vlsh = ldp_fd_to_vlsh (fd);
543 if (vlsh != VLS_INVALID_HANDLE)
544 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500545 switch (cmd)
546 {
547 case FIONREAD:
Florin Coras7baeb712019-01-04 17:05:43 -0800548 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_NREAD, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -0500549 break;
550
551 case FIONBIO:
552 {
553 u32 flags = va_arg (ap, int) ? O_NONBLOCK : 0;
554 u32 size = sizeof (flags);
555
556 /* TBD: When VPPCOM_ATTR_[GS]ET_FLAGS supports flags other than
557 * non-blocking, the flags should be read here and merged
558 * with O_NONBLOCK.
559 */
Florin Coras7baeb712019-01-04 17:05:43 -0800560 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_FLAGS, &flags, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -0500561 }
562 break;
563
564 default:
565 rv = -EOPNOTSUPP;
566 break;
567 }
568 if (rv < 0)
569 {
570 errno = -rv;
571 rv = -1;
572 }
573 }
574 else
575 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500576 rv = libc_vioctl (fd, cmd, ap);
577 }
578
Dave Wallace048b1d62018-01-03 22:24:41 -0500579 va_end (ap);
580 return rv;
581}
582
Florin Coras294afe22019-01-07 17:49:17 -0800583always_inline void
584ldp_select_init_maps (fd_set * __restrict original,
585 clib_bitmap_t ** resultb, clib_bitmap_t ** libcb,
586 clib_bitmap_t ** vclb, int nfds, u32 minbits,
587 u32 n_bytes, uword * si_bits, uword * libc_bits)
588{
589 uword si_bits_set, libc_bits_set;
590 vls_handle_t vlsh;
591 int fd;
592
593 clib_bitmap_validate (*vclb, minbits);
594 clib_bitmap_validate (*libcb, minbits);
595 clib_bitmap_validate (*resultb, minbits);
596 clib_memcpy_fast (*resultb, original, n_bytes);
597 memset (original, 0, n_bytes);
598
599 /* *INDENT-OFF* */
600 clib_bitmap_foreach (fd, *resultb, ({
601 if (fd > nfds)
602 break;
603 vlsh = ldp_fd_to_vlsh (fd);
604 if (vlsh == VLS_INVALID_HANDLE)
605 clib_bitmap_set_no_check (*libcb, fd, 1);
606 else
607 clib_bitmap_set_no_check (*vclb, vlsh_to_session_index (vlsh), 1);
608 }));
609 /* *INDENT-ON* */
610
611 si_bits_set = clib_bitmap_last_set (*vclb) + 1;
612 *si_bits = (si_bits_set > *si_bits) ? si_bits_set : *si_bits;
613
614 libc_bits_set = clib_bitmap_last_set (*libcb) + 1;
615 *libc_bits = (libc_bits_set > *libc_bits) ? libc_bits_set : *libc_bits;
616}
617
618always_inline int
619ldp_select_vcl_map_to_libc (clib_bitmap_t * vclb, fd_set * __restrict libcb)
620{
621 vls_handle_t vlsh;
622 uword si;
623 int fd;
624
625 if (!libcb)
626 return 0;
627
628 /* *INDENT-OFF* */
629 clib_bitmap_foreach (si, vclb, ({
630 vlsh = vls_session_index_to_vlsh (si);
631 fd = ldp_vlsh_to_fd (vlsh);
632 if (PREDICT_FALSE (fd < 0))
633 {
634 errno = EBADFD;
635 return -1;
636 }
637 FD_SET (fd, libcb);
638 }));
639 /* *INDENT-ON* */
640
641 return 0;
642}
643
644always_inline void
645ldp_select_libc_map_merge (clib_bitmap_t * result, fd_set * __restrict libcb)
646{
647 uword fd;
648
Florin Coras78b5fa62019-02-21 20:04:15 -0800649 if (!libcb)
650 return;
651
Florin Coras294afe22019-01-07 17:49:17 -0800652 /* *INDENT-OFF* */
653 clib_bitmap_foreach (fd, result, ({
654 FD_SET ((int)fd, libcb);
655 }));
656 /* *INDENT-ON* */
657}
658
Dave Wallace048b1d62018-01-03 22:24:41 -0500659int
Dave Wallace2a865272018-02-07 21:00:42 -0500660ldp_pselect (int nfds, fd_set * __restrict readfds,
661 fd_set * __restrict writefds,
662 fd_set * __restrict exceptfds,
663 const struct timespec *__restrict timeout,
664 const __sigset_t * __restrict sigmask)
Dave Wallace048b1d62018-01-03 22:24:41 -0500665{
Florin Coras294afe22019-01-07 17:49:17 -0800666 u32 minbits = clib_max (nfds, BITS (uword)), n_bytes;
Florin Corasdfe4cf42018-11-28 22:13:45 -0800667 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras294afe22019-01-07 17:49:17 -0800668 struct timespec libc_tspec = { 0 };
669 f64 time_out, vcl_timeout = 0;
670 uword si_bits, libc_bits;
671 int rv, bits_set = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500672
673 if (nfds < 0)
674 {
675 errno = EINVAL;
676 return -1;
677 }
678
Florin Coras4dee8cd2019-01-29 21:28:16 -0800679 if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
680 clib_time_init (&ldpw->clib_time);
681
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500682 if (timeout)
683 {
684 time_out = (timeout->tv_sec == 0 && timeout->tv_nsec == 0) ?
Florin Coras7baeb712019-01-04 17:05:43 -0800685 (f64) 0 : (f64) timeout->tv_sec + (f64) timeout->tv_nsec / (f64) 1e9;
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500686
687 /* select as fine grained sleep */
688 if (!nfds)
689 {
Florin Corasdfe4cf42018-11-28 22:13:45 -0800690 time_out += clib_time_now (&ldpw->clib_time);
691 while (clib_time_now (&ldpw->clib_time) < time_out)
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500692 ;
693 return 0;
694 }
695 }
696 else if (!nfds)
697 {
698 errno = EINVAL;
699 return -1;
700 }
701 else
702 time_out = -1;
703
Florin Coras7baeb712019-01-04 17:05:43 -0800704 if (nfds <= ldp->vlsh_bit_val)
Dave Wallace048b1d62018-01-03 22:24:41 -0500705 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500706 rv = libc_pselect (nfds, readfds, writefds, exceptfds,
707 timeout, sigmask);
708 goto done;
709 }
710
Florin Coras294afe22019-01-07 17:49:17 -0800711 si_bits = libc_bits = 0;
712 n_bytes = nfds / 8 + ((nfds % 8) ? 1 : 0);
Florin Coras7baeb712019-01-04 17:05:43 -0800713
Dave Wallace048b1d62018-01-03 22:24:41 -0500714 if (readfds)
Florin Coras294afe22019-01-07 17:49:17 -0800715 ldp_select_init_maps (readfds, &ldpw->rd_bitmap, &ldpw->libc_rd_bitmap,
716 &ldpw->si_rd_bitmap, nfds, minbits, n_bytes,
717 &si_bits, &libc_bits);
Dave Wallace048b1d62018-01-03 22:24:41 -0500718 if (writefds)
Florin Coras294afe22019-01-07 17:49:17 -0800719 ldp_select_init_maps (writefds, &ldpw->wr_bitmap,
720 &ldpw->libc_wr_bitmap, &ldpw->si_wr_bitmap, nfds,
721 minbits, n_bytes, &si_bits, &libc_bits);
Dave Wallace048b1d62018-01-03 22:24:41 -0500722 if (exceptfds)
Florin Coras294afe22019-01-07 17:49:17 -0800723 ldp_select_init_maps (exceptfds, &ldpw->ex_bitmap,
724 &ldpw->libc_ex_bitmap, &ldpw->si_ex_bitmap, nfds,
725 minbits, n_bytes, &si_bits, &libc_bits);
Dave Wallace048b1d62018-01-03 22:24:41 -0500726
Florin Coras294afe22019-01-07 17:49:17 -0800727 if (PREDICT_FALSE (!si_bits && !libc_bits))
Dave Wallace048b1d62018-01-03 22:24:41 -0500728 {
729 errno = EINVAL;
730 rv = -1;
731 goto done;
732 }
733
Florin Coras78b5fa62019-02-21 20:04:15 -0800734 if (!si_bits)
735 libc_tspec = timeout ? *timeout : libc_tspec;
Florin Coras294afe22019-01-07 17:49:17 -0800736
Dave Wallace048b1d62018-01-03 22:24:41 -0500737 do
738 {
Florin Coras294afe22019-01-07 17:49:17 -0800739 if (si_bits)
Dave Wallace048b1d62018-01-03 22:24:41 -0500740 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500741 if (readfds)
Florin Coras294afe22019-01-07 17:49:17 -0800742 clib_memcpy_fast (ldpw->rd_bitmap, ldpw->si_rd_bitmap,
Florin Corasdfe4cf42018-11-28 22:13:45 -0800743 vec_len (ldpw->rd_bitmap) *
Dave Barach178cf492018-11-13 16:34:13 -0500744 sizeof (clib_bitmap_t));
Dave Wallace048b1d62018-01-03 22:24:41 -0500745 if (writefds)
Florin Coras294afe22019-01-07 17:49:17 -0800746 clib_memcpy_fast (ldpw->wr_bitmap, ldpw->si_wr_bitmap,
Florin Corasdfe4cf42018-11-28 22:13:45 -0800747 vec_len (ldpw->wr_bitmap) *
Dave Barach178cf492018-11-13 16:34:13 -0500748 sizeof (clib_bitmap_t));
Dave Wallace048b1d62018-01-03 22:24:41 -0500749 if (exceptfds)
Florin Coras294afe22019-01-07 17:49:17 -0800750 clib_memcpy_fast (ldpw->ex_bitmap, ldpw->si_ex_bitmap,
Florin Corasdfe4cf42018-11-28 22:13:45 -0800751 vec_len (ldpw->ex_bitmap) *
Dave Barach178cf492018-11-13 16:34:13 -0500752 sizeof (clib_bitmap_t));
Florin Coras294afe22019-01-07 17:49:17 -0800753
Florin Coras0ef8ef22019-01-18 08:37:13 -0800754 rv = vls_select (si_bits, readfds ? ldpw->rd_bitmap : NULL,
755 writefds ? ldpw->wr_bitmap : NULL,
756 exceptfds ? ldpw->ex_bitmap : NULL, vcl_timeout);
Florin Coras294afe22019-01-07 17:49:17 -0800757 if (rv < 0)
758 {
759 errno = -rv;
760 rv = -1;
761 }
762 else if (rv > 0)
763 {
764 if (ldp_select_vcl_map_to_libc (ldpw->rd_bitmap, readfds))
765 {
766 rv = -1;
767 goto done;
768 }
769
770 if (ldp_select_vcl_map_to_libc (ldpw->wr_bitmap, writefds))
771 {
772 rv = -1;
773 goto done;
774 }
775
776 if (ldp_select_vcl_map_to_libc (ldpw->ex_bitmap, exceptfds))
777 {
778 rv = -1;
779 goto done;
780 }
781 bits_set = rv;
782 }
783 }
784 if (libc_bits)
785 {
786 if (readfds)
787 clib_memcpy_fast (ldpw->rd_bitmap, ldpw->libc_rd_bitmap,
788 vec_len (ldpw->libc_rd_bitmap) *
789 sizeof (clib_bitmap_t));
790 if (writefds)
791 clib_memcpy_fast (ldpw->wr_bitmap, ldpw->libc_wr_bitmap,
792 vec_len (ldpw->libc_wr_bitmap) *
793 sizeof (clib_bitmap_t));
794 if (exceptfds)
795 clib_memcpy_fast (ldpw->ex_bitmap, ldpw->libc_ex_bitmap,
796 vec_len (ldpw->libc_ex_bitmap) *
797 sizeof (clib_bitmap_t));
798
Dave Wallace048b1d62018-01-03 22:24:41 -0500799 rv = libc_pselect (libc_bits,
Florin Coras294afe22019-01-07 17:49:17 -0800800 readfds ? (fd_set *) ldpw->rd_bitmap : NULL,
801 writefds ? (fd_set *) ldpw->wr_bitmap : NULL,
802 exceptfds ? (fd_set *) ldpw->ex_bitmap : NULL,
803 &libc_tspec, sigmask);
804 if (rv > 0)
805 {
806 ldp_select_libc_map_merge (ldpw->rd_bitmap, readfds);
807 ldp_select_libc_map_merge (ldpw->wr_bitmap, writefds);
808 ldp_select_libc_map_merge (ldpw->ex_bitmap, exceptfds);
809 bits_set += rv;
810 }
811 }
812
813 if (bits_set)
814 {
815 rv = bits_set;
816 goto done;
Dave Wallace048b1d62018-01-03 22:24:41 -0500817 }
818 }
Florin Corasdfe4cf42018-11-28 22:13:45 -0800819 while ((time_out == -1) || (clib_time_now (&ldpw->clib_time) < time_out));
Dave Wallace048b1d62018-01-03 22:24:41 -0500820 rv = 0;
821
822done:
823 /* TBD: set timeout to amount of time left */
Florin Corasdfe4cf42018-11-28 22:13:45 -0800824 clib_bitmap_zero (ldpw->rd_bitmap);
Florin Coras294afe22019-01-07 17:49:17 -0800825 clib_bitmap_zero (ldpw->si_rd_bitmap);
Florin Corasdfe4cf42018-11-28 22:13:45 -0800826 clib_bitmap_zero (ldpw->libc_rd_bitmap);
827 clib_bitmap_zero (ldpw->wr_bitmap);
Florin Coras294afe22019-01-07 17:49:17 -0800828 clib_bitmap_zero (ldpw->si_wr_bitmap);
Florin Corasdfe4cf42018-11-28 22:13:45 -0800829 clib_bitmap_zero (ldpw->libc_wr_bitmap);
830 clib_bitmap_zero (ldpw->ex_bitmap);
Florin Coras294afe22019-01-07 17:49:17 -0800831 clib_bitmap_zero (ldpw->si_ex_bitmap);
Florin Corasdfe4cf42018-11-28 22:13:45 -0800832 clib_bitmap_zero (ldpw->libc_ex_bitmap);
Dave Wallace048b1d62018-01-03 22:24:41 -0500833
Dave Wallace048b1d62018-01-03 22:24:41 -0500834 return rv;
835}
836
837int
838select (int nfds, fd_set * __restrict readfds,
839 fd_set * __restrict writefds,
840 fd_set * __restrict exceptfds, struct timeval *__restrict timeout)
841{
842 struct timespec tspec;
843
844 if (timeout)
845 {
846 tspec.tv_sec = timeout->tv_sec;
847 tspec.tv_nsec = timeout->tv_usec * 1000;
848 }
Dave Wallace2a865272018-02-07 21:00:42 -0500849 return ldp_pselect (nfds, readfds, writefds, exceptfds,
850 timeout ? &tspec : NULL, NULL);
Dave Wallace048b1d62018-01-03 22:24:41 -0500851}
852
853#ifdef __USE_XOPEN2K
854int
855pselect (int nfds, fd_set * __restrict readfds,
856 fd_set * __restrict writefds,
857 fd_set * __restrict exceptfds,
858 const struct timespec *__restrict timeout,
859 const __sigset_t * __restrict sigmask)
860{
Dave Wallace2a865272018-02-07 21:00:42 -0500861 return ldp_pselect (nfds, readfds, writefds, exceptfds, timeout, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -0500862}
863#endif
864
865int
866socket (int domain, int type, int protocol)
867{
Florin Coras7baeb712019-01-04 17:05:43 -0800868 int rv, sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
Dave Wallace048b1d62018-01-03 22:24:41 -0500869 u8 is_nonblocking = type & SOCK_NONBLOCK ? 1 : 0;
Florin Coras7baeb712019-01-04 17:05:43 -0800870 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500871
Dave Wallace2a865272018-02-07 21:00:42 -0500872 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500873 return -1;
874
875 if (((domain == AF_INET) || (domain == AF_INET6)) &&
876 ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM)))
877 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500878 u8 proto = ((sock_type == SOCK_DGRAM) ?
879 VPPCOM_PROTO_UDP : VPPCOM_PROTO_TCP);
880
Florin Coras7baeb712019-01-04 17:05:43 -0800881 LDBG (0, "calling vls_create: proto %u (%s), is_nonblocking %u",
882 proto, vppcom_proto_str (proto), is_nonblocking);
Dave Wallace048b1d62018-01-03 22:24:41 -0500883
Florin Coras7baeb712019-01-04 17:05:43 -0800884 vlsh = vls_create (proto, is_nonblocking);
885 if (vlsh < 0)
Dave Wallace048b1d62018-01-03 22:24:41 -0500886 {
Florin Coras7baeb712019-01-04 17:05:43 -0800887 errno = -vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500888 rv = -1;
889 }
890 else
891 {
Florin Coras7baeb712019-01-04 17:05:43 -0800892 rv = ldp_vlsh_to_fd (vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -0500893 }
894 }
895 else
896 {
Florin Coras7baeb712019-01-04 17:05:43 -0800897 LDBG (0, "calling libc_socket");
Dave Wallace048b1d62018-01-03 22:24:41 -0500898 rv = libc_socket (domain, type, protocol);
899 }
900
Dave Wallace048b1d62018-01-03 22:24:41 -0500901 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700902}
903
904/*
905 * Create two new sockets, of type TYPE in domain DOMAIN and using
906 * protocol PROTOCOL, which are connected to each other, and put file
907 * descriptors for them in FDS[0] and FDS[1]. If PROTOCOL is zero,
908 * one will be chosen automatically.
909 * Returns 0 on success, -1 for errors.
910 * */
911int
Dave Wallace048b1d62018-01-03 22:24:41 -0500912socketpair (int domain, int type, int protocol, int fds[2])
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700913{
Florin Coras7baeb712019-01-04 17:05:43 -0800914 int rv, sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
Dave Wallace048b1d62018-01-03 22:24:41 -0500915
Dave Wallace2a865272018-02-07 21:00:42 -0500916 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500917 return -1;
918
919 if (((domain == AF_INET) || (domain == AF_INET6)) &&
920 ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM)))
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700921 {
Florin Coras7baeb712019-01-04 17:05:43 -0800922 LDBG (0, "LDP-TBD");
Dave Wallace048b1d62018-01-03 22:24:41 -0500923 errno = ENOSYS;
924 rv = -1;
925 }
926 else
927 {
Florin Coras7baeb712019-01-04 17:05:43 -0800928 LDBG (1, "calling libc_socketpair");
Florin Coras173bae32018-11-16 18:56:28 -0800929 rv = libc_socketpair (domain, type, protocol, fds);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700930 }
931
Dave Wallace048b1d62018-01-03 22:24:41 -0500932 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700933}
934
935int
Dave Wallace048b1d62018-01-03 22:24:41 -0500936bind (int fd, __CONST_SOCKADDR_ARG addr, socklen_t len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700937{
Florin Coras7baeb712019-01-04 17:05:43 -0800938 vls_handle_t vlsh;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700939 int rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700940
Dave Wallace2a865272018-02-07 21:00:42 -0500941 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500942 return -1;
943
Florin Coras7baeb712019-01-04 17:05:43 -0800944 vlsh = ldp_fd_to_vlsh (fd);
945 if (vlsh != VLS_INVALID_HANDLE)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700946 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500947 vppcom_endpt_t ep;
948
Dave Wallace048b1d62018-01-03 22:24:41 -0500949 switch (addr->sa_family)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700950 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500951 case AF_INET:
952 if (len != sizeof (struct sockaddr_in))
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700953 {
Florin Coras7baeb712019-01-04 17:05:43 -0800954 LDBG (0, "ERROR: fd %d: vlsh %u: Invalid AF_INET addr len %u!",
955 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -0500956 errno = EINVAL;
957 rv = -1;
958 goto done;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700959 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500960 ep.is_ip4 = VPPCOM_IS_IP4;
961 ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr;
962 ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port;
963 break;
964
965 case AF_INET6:
966 if (len != sizeof (struct sockaddr_in6))
967 {
Florin Coras7baeb712019-01-04 17:05:43 -0800968 LDBG (0, "ERROR: fd %d: vlsh %u: Invalid AF_INET6 addr len %u!",
969 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -0500970 errno = EINVAL;
971 rv = -1;
972 goto done;
973 }
974 ep.is_ip4 = VPPCOM_IS_IP6;
975 ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
976 ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700977 break;
978
979 default:
Florin Coras7baeb712019-01-04 17:05:43 -0800980 LDBG (0, "ERROR: fd %d: vlsh %u: Unsupported address family %u!",
981 fd, vlsh, addr->sa_family);
Dave Wallace048b1d62018-01-03 22:24:41 -0500982 errno = EAFNOSUPPORT;
983 rv = -1;
984 goto done;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700985 }
Florin Coras7baeb712019-01-04 17:05:43 -0800986 LDBG (0, "fd %d: calling vls_bind: vlsh %u, addr %p, len %u", fd, vlsh,
987 addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -0500988
Florin Coras7baeb712019-01-04 17:05:43 -0800989 rv = vls_bind (vlsh, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -0500990 if (rv != VPPCOM_OK)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700991 {
992 errno = -rv;
Dave Wallace048b1d62018-01-03 22:24:41 -0500993 rv = -1;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700994 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700995 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500996 else
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700997 {
Florin Coras7baeb712019-01-04 17:05:43 -0800998 LDBG (0, "fd %d: calling libc_bind: addr %p, len %u", fd, addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -0500999 rv = libc_bind (fd, addr, len);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001000 }
1001
Dave Wallace048b1d62018-01-03 22:24:41 -05001002done:
Florin Coras7baeb712019-01-04 17:05:43 -08001003 LDBG (1, "fd %d: returning %d", fd, rv);
Florin Coras05ecfcc2018-12-12 18:19:39 -08001004
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001005 return rv;
1006}
1007
1008static inline int
Dave Wallace2a865272018-02-07 21:00:42 -05001009ldp_copy_ep_to_sockaddr (__SOCKADDR_ARG addr, socklen_t * __restrict len,
1010 vppcom_endpt_t * ep)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001011{
Dave Wallace048b1d62018-01-03 22:24:41 -05001012 int rv = 0;
1013 int sa_len, copy_len;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001014
Dave Wallace2a865272018-02-07 21:00:42 -05001015 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001016 return -1;
1017
1018 if (addr && len && ep)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001019 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001020 addr->sa_family = (ep->is_ip4 == VPPCOM_IS_IP4) ? AF_INET : AF_INET6;
1021 switch (addr->sa_family)
1022 {
1023 case AF_INET:
1024 ((struct sockaddr_in *) addr)->sin_port = ep->port;
1025 if (*len > sizeof (struct sockaddr_in))
1026 *len = sizeof (struct sockaddr_in);
1027 sa_len = sizeof (struct sockaddr_in) - sizeof (struct in_addr);
1028 copy_len = *len - sa_len;
1029 if (copy_len > 0)
1030 memcpy (&((struct sockaddr_in *) addr)->sin_addr, ep->ip,
1031 copy_len);
1032 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001033
Dave Wallace048b1d62018-01-03 22:24:41 -05001034 case AF_INET6:
1035 ((struct sockaddr_in6 *) addr)->sin6_port = ep->port;
1036 if (*len > sizeof (struct sockaddr_in6))
1037 *len = sizeof (struct sockaddr_in6);
1038 sa_len = sizeof (struct sockaddr_in6) - sizeof (struct in6_addr);
1039 copy_len = *len - sa_len;
1040 if (copy_len > 0)
1041 memcpy (((struct sockaddr_in6 *) addr)->sin6_addr.
1042 __in6_u.__u6_addr8, ep->ip, copy_len);
1043 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001044
Dave Wallace048b1d62018-01-03 22:24:41 -05001045 default:
1046 /* Not possible */
1047 rv = -EAFNOSUPPORT;
1048 break;
1049 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001050 }
Dave Wallacee695cb42017-11-02 22:04:42 -04001051 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001052}
1053
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001054int
Dave Wallace048b1d62018-01-03 22:24:41 -05001055getsockname (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001056{
Florin Coras7baeb712019-01-04 17:05:43 -08001057 vls_handle_t vlsh;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001058 int rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001059
Dave Wallace2a865272018-02-07 21:00:42 -05001060 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001061 return -1;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001062
Florin Coras7baeb712019-01-04 17:05:43 -08001063 vlsh = ldp_fd_to_vlsh (fd);
1064 if (vlsh != VLS_INVALID_HANDLE)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001065 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001066 vppcom_endpt_t ep;
1067 u8 addr_buf[sizeof (struct in6_addr)];
1068 u32 size = sizeof (ep);
1069
1070 ep.ip = addr_buf;
Dave Wallace048b1d62018-01-03 22:24:41 -05001071
Florin Coras7baeb712019-01-04 17:05:43 -08001072 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_LCL_ADDR, &ep, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -05001073 if (rv != VPPCOM_OK)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001074 {
1075 errno = -rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001076 rv = -1;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001077 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001078 else
1079 {
Dave Wallace2a865272018-02-07 21:00:42 -05001080 rv = ldp_copy_ep_to_sockaddr (addr, len, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001081 if (rv != VPPCOM_OK)
1082 {
1083 errno = -rv;
1084 rv = -1;
1085 }
1086 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001087 }
1088 else
1089 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001090 rv = libc_getsockname (fd, addr, len);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001091 }
1092
Dave Wallace048b1d62018-01-03 22:24:41 -05001093 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001094}
1095
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001096int
Dave Wallace048b1d62018-01-03 22:24:41 -05001097connect (int fd, __CONST_SOCKADDR_ARG addr, socklen_t len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001098{
Florin Coras7baeb712019-01-04 17:05:43 -08001099 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001100 int rv;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001101
Dave Wallace2a865272018-02-07 21:00:42 -05001102 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001103 return -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001104
Dave Wallace048b1d62018-01-03 22:24:41 -05001105 if (!addr)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001106 {
Florin Coras7baeb712019-01-04 17:05:43 -08001107 LDBG (0, "ERROR: fd %d: NULL addr, len %u", fd, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001108 errno = EINVAL;
1109 rv = -1;
1110 goto done;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001111 }
1112
Florin Coras7baeb712019-01-04 17:05:43 -08001113 vlsh = ldp_fd_to_vlsh (fd);
1114 if (vlsh != VLS_INVALID_HANDLE)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001115 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001116 vppcom_endpt_t ep;
1117
Dave Wallace048b1d62018-01-03 22:24:41 -05001118 switch (addr->sa_family)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001119 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001120 case AF_INET:
1121 if (len != sizeof (struct sockaddr_in))
1122 {
Florin Coras7baeb712019-01-04 17:05:43 -08001123 LDBG (0, "fd %d: ERROR vlsh %u: Invalid AF_INET addr len %u!",
1124 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001125 errno = EINVAL;
1126 rv = -1;
1127 goto done;
1128 }
1129 ep.is_ip4 = VPPCOM_IS_IP4;
1130 ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr;
1131 ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port;
1132 break;
1133
1134 case AF_INET6:
1135 if (len != sizeof (struct sockaddr_in6))
1136 {
Florin Coras7baeb712019-01-04 17:05:43 -08001137 LDBG (0, "fd %d: ERROR vlsh %u: Invalid AF_INET6 addr len %u!",
1138 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001139 errno = EINVAL;
1140 rv = -1;
1141 goto done;
1142 }
1143 ep.is_ip4 = VPPCOM_IS_IP6;
1144 ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
1145 ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port;
1146 break;
1147
1148 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001149 LDBG (0, "fd %d: ERROR vlsh %u: Unsupported address family %u!",
1150 fd, vlsh, addr->sa_family);
Dave Wallace048b1d62018-01-03 22:24:41 -05001151 errno = EAFNOSUPPORT;
1152 rv = -1;
1153 goto done;
1154 }
Florin Coras7baeb712019-01-04 17:05:43 -08001155 LDBG (0, "fd %d: calling vls_connect(): vlsh %u addr %p len %u", fd,
1156 vlsh, addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001157
Florin Coras7baeb712019-01-04 17:05:43 -08001158 rv = vls_connect (vlsh, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001159 if (rv != VPPCOM_OK)
1160 {
1161 errno = -rv;
1162 rv = -1;
1163 }
1164 }
1165 else
1166 {
Florin Coras7baeb712019-01-04 17:05:43 -08001167 LDBG (0, "fd %d: calling libc_connect(): addr %p, len %u",
1168 fd, addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001169
1170 rv = libc_connect (fd, addr, len);
1171 }
1172
1173done:
Florin Coras7baeb712019-01-04 17:05:43 -08001174 LDBG (1, "fd %d: returning %d (0x%x)", fd, rv, rv);
Dave Wallace048b1d62018-01-03 22:24:41 -05001175 return rv;
1176}
1177
1178int
1179getpeername (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict len)
1180{
Florin Coras7baeb712019-01-04 17:05:43 -08001181 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001182 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001183
Dave Wallace2a865272018-02-07 21:00:42 -05001184 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001185 return -1;
1186
Florin Coras7baeb712019-01-04 17:05:43 -08001187 vlsh = ldp_fd_to_vlsh (fd);
1188 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001189 {
1190 vppcom_endpt_t ep;
1191 u8 addr_buf[sizeof (struct in6_addr)];
1192 u32 size = sizeof (ep);
1193
1194 ep.ip = addr_buf;
Florin Coras7baeb712019-01-04 17:05:43 -08001195 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_PEER_ADDR, &ep, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -05001196 if (rv != VPPCOM_OK)
1197 {
1198 errno = -rv;
1199 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001200 }
1201 else
1202 {
Dave Wallace2a865272018-02-07 21:00:42 -05001203 rv = ldp_copy_ep_to_sockaddr (addr, len, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001204 if (rv != VPPCOM_OK)
1205 {
1206 errno = -rv;
1207 rv = -1;
1208 }
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001209 }
1210 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001211 else
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001212 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001213 rv = libc_getpeername (fd, addr, len);
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001214 }
1215
Dave Wallace048b1d62018-01-03 22:24:41 -05001216 return rv;
1217}
1218
1219ssize_t
1220send (int fd, const void *buf, size_t n, int flags)
1221{
Florin Coras7baeb712019-01-04 17:05:43 -08001222 vls_handle_t vlsh = ldp_fd_to_vlsh (fd);
Dave Wallace048b1d62018-01-03 22:24:41 -05001223 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001224
Dave Wallace2a865272018-02-07 21:00:42 -05001225 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001226 return -1;
1227
Florin Coras7baeb712019-01-04 17:05:43 -08001228 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001229 {
Florin Coras7baeb712019-01-04 17:05:43 -08001230 size = vls_sendto (vlsh, (void *) buf, n, flags, NULL);
qchangaa8f63c2018-05-30 11:44:18 -07001231 if (size < VPPCOM_OK)
Dave Wallace048b1d62018-01-03 22:24:41 -05001232 {
1233 errno = -size;
1234 size = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001235 }
1236 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001237 else
1238 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001239 size = libc_send (fd, buf, n, flags);
1240 }
1241
Dave Wallace048b1d62018-01-03 22:24:41 -05001242 return size;
1243}
1244
1245ssize_t
1246sendfile (int out_fd, int in_fd, off_t * offset, size_t len)
1247{
Florin Corasdfe4cf42018-11-28 22:13:45 -08001248 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras7baeb712019-01-04 17:05:43 -08001249 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001250 ssize_t size = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -05001251
Dave Wallace2a865272018-02-07 21:00:42 -05001252 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001253 return -1;
1254
Florin Coras7baeb712019-01-04 17:05:43 -08001255 vlsh = ldp_fd_to_vlsh (out_fd);
1256 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001257 {
1258 int rv;
1259 ssize_t results = 0;
1260 size_t n_bytes_left = len;
1261 size_t bytes_to_read;
1262 int nbytes;
Dave Wallace048b1d62018-01-03 22:24:41 -05001263 u8 eagain = 0;
1264 u32 flags, flags_len = sizeof (flags);
1265
Florin Coras7baeb712019-01-04 17:05:43 -08001266 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_FLAGS, &flags, &flags_len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001267 if (PREDICT_FALSE (rv != VPPCOM_OK))
1268 {
Florin Coras7baeb712019-01-04 17:05:43 -08001269 LDBG (0, "ERROR: out fd %d: vls_attr: vlsh %u, returned %d (%s)!",
1270 out_fd, vlsh, rv, vppcom_retval_str (rv));
Dave Wallace048b1d62018-01-03 22:24:41 -05001271
Florin Corasdfe4cf42018-11-28 22:13:45 -08001272 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001273 errno = -rv;
1274 size = -1;
1275 goto done;
1276 }
1277
1278 if (offset)
1279 {
1280 off_t off = lseek (in_fd, *offset, SEEK_SET);
1281 if (PREDICT_FALSE (off == -1))
1282 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001283 size = -1;
1284 goto done;
1285 }
1286
1287 ASSERT (off == *offset);
1288 }
1289
1290 do
1291 {
Florin Coras7baeb712019-01-04 17:05:43 -08001292 size = vls_attr (vlsh, VPPCOM_ATTR_GET_NWRITE, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05001293 if (size < 0)
1294 {
Florin Coras7baeb712019-01-04 17:05:43 -08001295 LDBG (0, "ERROR: fd %d: vls_attr: vlsh %u returned %d (%s)!",
1296 out_fd, vlsh, size, vppcom_retval_str (size));
Florin Corasdfe4cf42018-11-28 22:13:45 -08001297 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001298 errno = -size;
1299 size = -1;
1300 goto done;
1301 }
1302
1303 bytes_to_read = size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001304 if (bytes_to_read == 0)
1305 {
1306 if (flags & O_NONBLOCK)
1307 {
1308 if (!results)
Florin Coras7baeb712019-01-04 17:05:43 -08001309 eagain = 1;
Dave Wallace048b1d62018-01-03 22:24:41 -05001310 goto update_offset;
1311 }
1312 else
1313 continue;
1314 }
1315 bytes_to_read = clib_min (n_bytes_left, bytes_to_read);
Florin Corasdfe4cf42018-11-28 22:13:45 -08001316 vec_validate (ldpw->io_buffer, bytes_to_read);
1317 nbytes = libc_read (in_fd, ldpw->io_buffer, bytes_to_read);
Dave Wallace048b1d62018-01-03 22:24:41 -05001318 if (nbytes < 0)
1319 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001320 if (results == 0)
1321 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08001322 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001323 size = -1;
1324 goto done;
1325 }
1326 goto update_offset;
1327 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001328
Florin Coras7baeb712019-01-04 17:05:43 -08001329 size = vls_write (vlsh, ldpw->io_buffer, nbytes);
Dave Wallace048b1d62018-01-03 22:24:41 -05001330 if (size < 0)
1331 {
1332 if (size == VPPCOM_EAGAIN)
1333 {
1334 if (flags & O_NONBLOCK)
1335 {
1336 if (!results)
Florin Coras7baeb712019-01-04 17:05:43 -08001337 eagain = 1;
Dave Wallace048b1d62018-01-03 22:24:41 -05001338 goto update_offset;
1339 }
1340 else
1341 continue;
1342 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001343 if (results == 0)
1344 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08001345 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001346 errno = -size;
1347 size = -1;
1348 goto done;
1349 }
1350 goto update_offset;
1351 }
1352
1353 results += nbytes;
1354 ASSERT (n_bytes_left >= nbytes);
1355 n_bytes_left = n_bytes_left - nbytes;
1356 }
1357 while (n_bytes_left > 0);
1358
1359 update_offset:
Florin Corasdfe4cf42018-11-28 22:13:45 -08001360 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001361 if (offset)
1362 {
1363 off_t off = lseek (in_fd, *offset, SEEK_SET);
1364 if (PREDICT_FALSE (off == -1))
1365 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001366 size = -1;
1367 goto done;
1368 }
1369
1370 ASSERT (off == *offset);
1371 *offset += results + 1;
1372 }
1373 if (eagain)
1374 {
1375 errno = EAGAIN;
1376 size = -1;
1377 }
1378 else
1379 size = results;
1380 }
1381 else
1382 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001383 size = libc_sendfile (out_fd, in_fd, offset, len);
1384 }
1385
1386done:
Dave Wallace048b1d62018-01-03 22:24:41 -05001387 return size;
1388}
1389
1390ssize_t
1391sendfile64 (int out_fd, int in_fd, off_t * offset, size_t len)
1392{
1393 return sendfile (out_fd, in_fd, offset, len);
1394}
1395
1396ssize_t
1397recv (int fd, void *buf, size_t n, int flags)
1398{
Florin Coras7baeb712019-01-04 17:05:43 -08001399 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001400 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001401
Dave Wallace2a865272018-02-07 21:00:42 -05001402 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001403 return -1;
1404
Florin Coras7baeb712019-01-04 17:05:43 -08001405 vlsh = ldp_fd_to_vlsh (fd);
1406 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001407 {
Florin Coras7baeb712019-01-04 17:05:43 -08001408 size = vls_recvfrom (vlsh, buf, n, flags, NULL);
Dave Wallace048b1d62018-01-03 22:24:41 -05001409 if (size < 0)
Florin Corasa7a1a222018-12-30 17:11:31 -08001410 errno = -size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001411 }
1412 else
1413 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001414 size = libc_recv (fd, buf, n, flags);
1415 }
1416
Dave Wallace048b1d62018-01-03 22:24:41 -05001417 return size;
1418}
1419
1420ssize_t
1421sendto (int fd, const void *buf, size_t n, int flags,
1422 __CONST_SOCKADDR_ARG addr, socklen_t addr_len)
1423{
Florin Coras7baeb712019-01-04 17:05:43 -08001424 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001425 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001426
Dave Wallace2a865272018-02-07 21:00:42 -05001427 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001428 return -1;
1429
Florin Coras7baeb712019-01-04 17:05:43 -08001430 vlsh = ldp_fd_to_vlsh (fd);
1431 if (vlsh != INVALID_SESSION_ID)
Dave Wallace048b1d62018-01-03 22:24:41 -05001432 {
1433 vppcom_endpt_t *ep = 0;
1434 vppcom_endpt_t _ep;
1435
1436 if (addr)
1437 {
1438 ep = &_ep;
Dave Wallace048b1d62018-01-03 22:24:41 -05001439 switch (addr->sa_family)
1440 {
1441 case AF_INET:
1442 ep->is_ip4 = VPPCOM_IS_IP4;
1443 ep->ip =
1444 (uint8_t *) & ((const struct sockaddr_in *) addr)->sin_addr;
1445 ep->port =
1446 (uint16_t) ((const struct sockaddr_in *) addr)->sin_port;
1447 break;
1448
1449 case AF_INET6:
1450 ep->is_ip4 = VPPCOM_IS_IP6;
1451 ep->ip =
1452 (uint8_t *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
1453 ep->port =
1454 (uint16_t) ((const struct sockaddr_in6 *) addr)->sin6_port;
1455 break;
1456
1457 default:
1458 errno = EAFNOSUPPORT;
1459 size = -1;
1460 goto done;
1461 }
1462 }
1463
Florin Coras7baeb712019-01-04 17:05:43 -08001464 size = vls_sendto (vlsh, (void *) buf, n, flags, ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001465 if (size < 0)
1466 {
1467 errno = -size;
1468 size = -1;
1469 }
1470 }
1471 else
1472 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001473 size = libc_sendto (fd, buf, n, flags, addr, addr_len);
1474 }
1475
1476done:
Dave Wallace048b1d62018-01-03 22:24:41 -05001477 return size;
1478}
1479
1480ssize_t
1481recvfrom (int fd, void *__restrict buf, size_t n, int flags,
1482 __SOCKADDR_ARG addr, socklen_t * __restrict addr_len)
1483{
Florin Coras7baeb712019-01-04 17:05:43 -08001484 vls_handle_t sid;
Haggai Eran46ae2ef2019-02-19 15:04:42 +02001485 ssize_t size, rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001486
Dave Wallace2a865272018-02-07 21:00:42 -05001487 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001488 return -1;
1489
Florin Coras7baeb712019-01-04 17:05:43 -08001490 sid = ldp_fd_to_vlsh (fd);
1491 if (sid != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001492 {
1493 vppcom_endpt_t ep;
1494 u8 src_addr[sizeof (struct sockaddr_in6)];
1495
Dave Wallace048b1d62018-01-03 22:24:41 -05001496 if (addr)
1497 {
1498 ep.ip = src_addr;
Florin Coras7baeb712019-01-04 17:05:43 -08001499 size = vls_recvfrom (sid, buf, n, flags, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001500
1501 if (size > 0)
Haggai Eran46ae2ef2019-02-19 15:04:42 +02001502 {
1503 rv = ldp_copy_ep_to_sockaddr (addr, addr_len, &ep);
1504 if (rv < 0)
1505 size = rv;
1506 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001507 }
1508 else
Florin Coras7baeb712019-01-04 17:05:43 -08001509 size = vls_recvfrom (sid, buf, n, flags, NULL);
Dave Wallace048b1d62018-01-03 22:24:41 -05001510
1511 if (size < 0)
1512 {
1513 errno = -size;
1514 size = -1;
1515 }
1516 }
1517 else
1518 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001519 size = libc_recvfrom (fd, buf, n, flags, addr, addr_len);
1520 }
1521
Dave Wallace048b1d62018-01-03 22:24:41 -05001522 return size;
1523}
1524
1525ssize_t
1526sendmsg (int fd, const struct msghdr * message, int flags)
1527{
Florin Coras7baeb712019-01-04 17:05:43 -08001528 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001529 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001530
Dave Wallace2a865272018-02-07 21:00:42 -05001531 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001532 return -1;
1533
Florin Coras7baeb712019-01-04 17:05:43 -08001534 vlsh = ldp_fd_to_vlsh (fd);
1535 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001536 {
Florin Coras7baeb712019-01-04 17:05:43 -08001537 LDBG (0, "LDP-TBD");
Dave Wallace048b1d62018-01-03 22:24:41 -05001538 errno = ENOSYS;
1539 size = -1;
1540 }
1541 else
1542 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001543 size = libc_sendmsg (fd, message, flags);
1544 }
1545
Dave Wallace048b1d62018-01-03 22:24:41 -05001546 return size;
1547}
1548
1549#ifdef USE_GNU
1550int
1551sendmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags)
1552{
1553 ssize_t size;
1554 const char *func_str;
Florin Coras7baeb712019-01-04 17:05:43 -08001555 u32 sh = ldp_fd_to_vlsh (fd);
Dave Wallace048b1d62018-01-03 22:24:41 -05001556
Dave Wallace2a865272018-02-07 21:00:42 -05001557 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001558 return -1;
1559
Florin Coras7baeb712019-01-04 17:05:43 -08001560 if (sh != INVALID_SESSION_ID)
Dave Wallace048b1d62018-01-03 22:24:41 -05001561 {
1562 clib_warning ("LDP<%d>: LDP-TBD", getpid ());
1563 errno = ENOSYS;
1564 size = -1;
1565 }
1566 else
1567 {
1568 func_str = "libc_sendmmsg";
1569
Dave Wallace2a865272018-02-07 21:00:42 -05001570 if (LDP_DEBUG > 2)
Dave Wallace048b1d62018-01-03 22:24:41 -05001571 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1572 "vmessages %p, vlen %u, flags 0x%x",
1573 getpid (), fd, fd, func_str, vmessages, vlen, flags);
1574
1575 size = libc_sendmmsg (fd, vmessages, vlen, flags);
1576 }
1577
Dave Wallace2a865272018-02-07 21:00:42 -05001578 if (LDP_DEBUG > 2)
Dave Wallace048b1d62018-01-03 22:24:41 -05001579 {
1580 if (size < 0)
1581 {
1582 int errno_val = errno;
1583 perror (func_str);
1584 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1585 "rv %d, errno = %d", getpid (), fd, fd,
1586 func_str, size, errno_val);
1587 errno = errno_val;
1588 }
1589 else
1590 clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1591 getpid (), fd, fd, size, size);
1592 }
1593 return size;
1594}
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001595#endif
1596
Dave Wallace048b1d62018-01-03 22:24:41 -05001597ssize_t
1598recvmsg (int fd, struct msghdr * message, int flags)
1599{
Florin Coras7baeb712019-01-04 17:05:43 -08001600 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001601 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001602
Dave Wallace2a865272018-02-07 21:00:42 -05001603 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001604 return -1;
1605
Florin Coras7baeb712019-01-04 17:05:43 -08001606 vlsh = ldp_fd_to_vlsh (fd);
1607 if (vlsh != VLS_INVALID_HANDLE)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001608 {
Florin Coras7baeb712019-01-04 17:05:43 -08001609 LDBG (0, "LDP-TBD");
Dave Wallace048b1d62018-01-03 22:24:41 -05001610 errno = ENOSYS;
1611 size = -1;
1612 }
1613 else
1614 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001615 size = libc_recvmsg (fd, message, flags);
1616 }
1617
Dave Wallace048b1d62018-01-03 22:24:41 -05001618 return size;
1619}
1620
1621#ifdef USE_GNU
1622int
1623recvmmsg (int fd, struct mmsghdr *vmessages,
1624 unsigned int vlen, int flags, struct timespec *tmo)
1625{
1626 ssize_t size;
1627 const char *func_str;
Florin Coras7baeb712019-01-04 17:05:43 -08001628 u32 sh = ldp_fd_to_vlsh (fd);
Dave Wallace048b1d62018-01-03 22:24:41 -05001629
Dave Wallace2a865272018-02-07 21:00:42 -05001630 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001631 return -1;
1632
Florin Coras7baeb712019-01-04 17:05:43 -08001633 if (sh != INVALID_SESSION_ID)
Dave Wallace048b1d62018-01-03 22:24:41 -05001634 {
1635 clib_warning ("LDP<%d>: LDP-TBD", getpid ());
1636 errno = ENOSYS;
1637 size = -1;
1638 }
1639 else
1640 {
1641 func_str = "libc_recvmmsg";
1642
Dave Wallace2a865272018-02-07 21:00:42 -05001643 if (LDP_DEBUG > 2)
Dave Wallace048b1d62018-01-03 22:24:41 -05001644 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1645 "vmessages %p, vlen %u, flags 0x%x, tmo %p",
1646 getpid (), fd, fd, func_str, vmessages, vlen,
1647 flags, tmo);
1648
1649 size = libc_recvmmsg (fd, vmessages, vlen, flags, tmo);
1650 }
1651
Dave Wallace2a865272018-02-07 21:00:42 -05001652 if (LDP_DEBUG > 2)
Dave Wallace048b1d62018-01-03 22:24:41 -05001653 {
1654 if (size < 0)
1655 {
1656 int errno_val = errno;
1657 perror (func_str);
1658 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1659 "rv %d, errno = %d", getpid (), fd, fd,
1660 func_str, size, errno_val);
1661 errno = errno_val;
1662 }
1663 else
1664 clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1665 getpid (), fd, fd, size, size);
1666 }
1667 return size;
1668}
1669#endif
1670
1671int
1672getsockopt (int fd, int level, int optname,
1673 void *__restrict optval, socklen_t * __restrict optlen)
1674{
Florin Coras7baeb712019-01-04 17:05:43 -08001675 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001676 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001677
Dave Wallace2a865272018-02-07 21:00:42 -05001678 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001679 return -1;
1680
Florin Coras7baeb712019-01-04 17:05:43 -08001681 vlsh = ldp_fd_to_vlsh (fd);
1682 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001683 {
1684 rv = -EOPNOTSUPP;
1685
1686 switch (level)
1687 {
1688 case SOL_TCP:
1689 switch (optname)
1690 {
1691 case TCP_NODELAY:
Florin Coras7baeb712019-01-04 17:05:43 -08001692 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_NODELAY,
1693 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001694 break;
1695 case TCP_MAXSEG:
Florin Coras7baeb712019-01-04 17:05:43 -08001696 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_USER_MSS,
1697 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001698 break;
1699 case TCP_KEEPIDLE:
Florin Coras7baeb712019-01-04 17:05:43 -08001700 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_KEEPIDLE,
1701 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001702 break;
1703 case TCP_KEEPINTVL:
Florin Coras7baeb712019-01-04 17:05:43 -08001704 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_KEEPINTVL,
1705 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001706 break;
1707 case TCP_INFO:
1708 if (optval && optlen && (*optlen == sizeof (struct tcp_info)))
1709 {
Florin Coras7baeb712019-01-04 17:05:43 -08001710 LDBG (1, "fd %d: vlsh %u SOL_TCP, TCP_INFO, optval %p, "
1711 "optlen %d: #LDP-NOP#", fd, vlsh, optval, *optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001712 memset (optval, 0, *optlen);
1713 rv = VPPCOM_OK;
1714 }
1715 else
1716 rv = -EFAULT;
1717 break;
Florin Coras0ed24e92019-01-21 09:03:10 -08001718 case TCP_CONGESTION:
1719 strcpy (optval, "cubic");
1720 *optlen = strlen ("cubic");
1721 rv = 0;
1722 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05001723 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001724 LDBG (0, "ERROR: fd %d: getsockopt SOL_TCP: sid %u, "
1725 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05001726 break;
1727 }
1728 break;
1729 case SOL_IPV6:
1730 switch (optname)
1731 {
1732 case IPV6_V6ONLY:
Florin Coras7baeb712019-01-04 17:05:43 -08001733 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_V6ONLY, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001734 break;
1735 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001736 LDBG (0, "ERROR: fd %d: getsockopt SOL_IPV6: vlsh %u "
1737 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05001738 break;
1739 }
1740 break;
1741 case SOL_SOCKET:
1742 switch (optname)
1743 {
1744 case SO_ACCEPTCONN:
Florin Coras7baeb712019-01-04 17:05:43 -08001745 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_LISTEN, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001746 break;
1747 case SO_KEEPALIVE:
Florin Coras7baeb712019-01-04 17:05:43 -08001748 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_KEEPALIVE, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001749 break;
1750 case SO_PROTOCOL:
Florin Coras7baeb712019-01-04 17:05:43 -08001751 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_PROTOCOL, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001752 *(int *) optval = *(int *) optval ? SOCK_DGRAM : SOCK_STREAM;
1753 break;
1754 case SO_SNDBUF:
Florin Coras7baeb712019-01-04 17:05:43 -08001755 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TX_FIFO_LEN,
1756 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001757 break;
1758 case SO_RCVBUF:
Florin Coras7baeb712019-01-04 17:05:43 -08001759 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_RX_FIFO_LEN,
1760 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001761 break;
1762 case SO_REUSEADDR:
Florin Coras7baeb712019-01-04 17:05:43 -08001763 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_REUSEADDR, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001764 break;
1765 case SO_BROADCAST:
Florin Coras7baeb712019-01-04 17:05:43 -08001766 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_BROADCAST, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001767 break;
1768 case SO_ERROR:
Florin Coras7baeb712019-01-04 17:05:43 -08001769 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_ERROR, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001770 break;
1771 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001772 LDBG (0, "ERROR: fd %d: getsockopt SOL_SOCKET: vlsh %u "
1773 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05001774 break;
1775 }
1776 break;
1777 default:
1778 break;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001779 }
1780
Dave Wallace048b1d62018-01-03 22:24:41 -05001781 if (rv != VPPCOM_OK)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001782 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001783 errno = -rv;
1784 rv = -1;
1785 }
1786 }
1787 else
1788 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001789 rv = libc_getsockopt (fd, level, optname, optval, optlen);
1790 }
1791
Dave Wallace048b1d62018-01-03 22:24:41 -05001792 return rv;
1793}
1794
1795int
1796setsockopt (int fd, int level, int optname,
1797 const void *optval, socklen_t optlen)
1798{
Florin Coras7baeb712019-01-04 17:05:43 -08001799 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001800 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001801
Dave Wallace2a865272018-02-07 21:00:42 -05001802 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001803 return -1;
1804
Florin Coras7baeb712019-01-04 17:05:43 -08001805 vlsh = ldp_fd_to_vlsh (fd);
1806 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001807 {
1808 rv = -EOPNOTSUPP;
1809
1810 switch (level)
1811 {
1812 case SOL_TCP:
1813 switch (optname)
1814 {
1815 case TCP_NODELAY:
Florin Coras7baeb712019-01-04 17:05:43 -08001816 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_NODELAY,
1817 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001818 break;
1819 case TCP_MAXSEG:
Florin Coras7baeb712019-01-04 17:05:43 -08001820 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_USER_MSS,
1821 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001822 break;
1823 case TCP_KEEPIDLE:
Florin Coras7baeb712019-01-04 17:05:43 -08001824 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_KEEPIDLE,
1825 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001826 break;
1827 case TCP_KEEPINTVL:
Florin Coras7baeb712019-01-04 17:05:43 -08001828 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_KEEPINTVL,
1829 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001830 break;
Florin Coras0ed24e92019-01-21 09:03:10 -08001831 case TCP_CONGESTION:
1832 /* Ignore */
1833 rv = 0;
1834 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05001835 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001836 LDBG (0, "ERROR: fd %d: setsockopt() SOL_TCP: vlsh %u"
1837 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05001838 break;
1839 }
1840 break;
1841 case SOL_IPV6:
1842 switch (optname)
1843 {
1844 case IPV6_V6ONLY:
Florin Coras7baeb712019-01-04 17:05:43 -08001845 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_V6ONLY,
1846 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001847 break;
1848 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001849 LDBG (0, "ERROR: fd %d: setsockopt SOL_IPV6: vlsh %u"
1850 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05001851 break;
1852 }
1853 break;
1854 case SOL_SOCKET:
1855 switch (optname)
1856 {
1857 case SO_KEEPALIVE:
Florin Coras7baeb712019-01-04 17:05:43 -08001858 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_KEEPALIVE,
1859 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001860 break;
1861 case SO_REUSEADDR:
Florin Coras7baeb712019-01-04 17:05:43 -08001862 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_REUSEADDR,
1863 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001864 break;
1865 case SO_BROADCAST:
Florin Coras7baeb712019-01-04 17:05:43 -08001866 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_BROADCAST,
1867 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001868 break;
1869 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001870 LDBG (0, "ERROR: fd %d: setsockopt SOL_SOCKET: vlsh %u "
1871 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05001872 break;
1873 }
1874 break;
1875 default:
1876 break;
1877 }
1878
1879 if (rv != VPPCOM_OK)
1880 {
1881 errno = -rv;
1882 rv = -1;
1883 }
1884 }
1885 else
1886 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001887 rv = libc_setsockopt (fd, level, optname, optval, optlen);
1888 }
1889
Dave Wallace048b1d62018-01-03 22:24:41 -05001890 return rv;
1891}
1892
1893int
1894listen (int fd, int n)
1895{
Florin Coras7baeb712019-01-04 17:05:43 -08001896 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001897 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001898
Dave Wallace2a865272018-02-07 21:00:42 -05001899 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001900 return -1;
1901
Florin Coras7baeb712019-01-04 17:05:43 -08001902 vlsh = ldp_fd_to_vlsh (fd);
1903 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001904 {
Florin Coras7baeb712019-01-04 17:05:43 -08001905 LDBG (0, "fd %d: calling vls_listen: vlsh %u, n %d", fd, vlsh, n);
Dave Wallace048b1d62018-01-03 22:24:41 -05001906
Florin Coras7baeb712019-01-04 17:05:43 -08001907 rv = vls_listen (vlsh, n);
Dave Wallace048b1d62018-01-03 22:24:41 -05001908 if (rv != VPPCOM_OK)
1909 {
1910 errno = -rv;
1911 rv = -1;
1912 }
1913 }
1914 else
1915 {
Florin Coras7baeb712019-01-04 17:05:43 -08001916 LDBG (0, "fd %d: calling libc_listen(): n %d", fd, n);
Dave Wallace048b1d62018-01-03 22:24:41 -05001917 rv = libc_listen (fd, n);
1918 }
1919
Florin Coras7baeb712019-01-04 17:05:43 -08001920 LDBG (1, "fd %d: returning %d", fd, rv);
Dave Wallace048b1d62018-01-03 22:24:41 -05001921 return rv;
1922}
1923
1924static inline int
Dave Wallace2a865272018-02-07 21:00:42 -05001925ldp_accept4 (int listen_fd, __SOCKADDR_ARG addr,
1926 socklen_t * __restrict addr_len, int flags)
Dave Wallace048b1d62018-01-03 22:24:41 -05001927{
Florin Coras7baeb712019-01-04 17:05:43 -08001928 vls_handle_t listen_vlsh, accept_vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001929 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001930
Dave Wallace2a865272018-02-07 21:00:42 -05001931 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001932 return -1;
1933
Florin Coras7baeb712019-01-04 17:05:43 -08001934 listen_vlsh = ldp_fd_to_vlsh (listen_fd);
1935 if (listen_vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001936 {
1937 vppcom_endpt_t ep;
1938 u8 src_addr[sizeof (struct sockaddr_in6)];
Dave Wallace8aaba562018-01-18 17:21:19 -05001939 memset (&ep, 0, sizeof (ep));
Dave Wallace048b1d62018-01-03 22:24:41 -05001940 ep.ip = src_addr;
1941
Florin Coras7baeb712019-01-04 17:05:43 -08001942 LDBG (0, "listen fd %d: calling vppcom_session_accept: listen sid %u,"
1943 " ep %p, flags 0x%x", listen_fd, listen_vlsh, ep, flags);
Dave Wallace048b1d62018-01-03 22:24:41 -05001944
Florin Coras7baeb712019-01-04 17:05:43 -08001945 accept_vlsh = vls_accept (listen_vlsh, &ep, flags);
1946 if (accept_vlsh < 0)
Dave Wallace048b1d62018-01-03 22:24:41 -05001947 {
Florin Coras7baeb712019-01-04 17:05:43 -08001948 errno = -accept_vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001949 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001950 }
1951 else
1952 {
Dave Wallace2a865272018-02-07 21:00:42 -05001953 rv = ldp_copy_ep_to_sockaddr (addr, addr_len, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001954 if (rv != VPPCOM_OK)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001955 {
Florin Coras7baeb712019-01-04 17:05:43 -08001956 (void) vls_close (accept_vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05001957 errno = -rv;
1958 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001959 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001960 else
1961 {
Florin Coras7baeb712019-01-04 17:05:43 -08001962 rv = ldp_vlsh_to_fd (accept_vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05001963 }
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001964 }
1965 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001966 else
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001967 {
Florin Coras7baeb712019-01-04 17:05:43 -08001968 LDBG (0, "listen fd %d: calling libc_accept4(): addr %p, addr_len %p,"
1969 " flags 0x%x", listen_fd, addr, addr_len, flags);
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001970
Dave Wallace048b1d62018-01-03 22:24:41 -05001971 rv = libc_accept4 (listen_fd, addr, addr_len, flags);
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001972 }
1973
Florin Coras7baeb712019-01-04 17:05:43 -08001974 LDBG (1, "listen fd %d: accept returning %d", listen_fd, rv);
Florin Coras05ecfcc2018-12-12 18:19:39 -08001975
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001976 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001977}
1978
Dave Wallace048b1d62018-01-03 22:24:41 -05001979int
1980accept4 (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len,
1981 int flags)
1982{
Dave Wallace2a865272018-02-07 21:00:42 -05001983 return ldp_accept4 (fd, addr, addr_len, flags);
Dave Wallace048b1d62018-01-03 22:24:41 -05001984}
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001985
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001986int
Dave Wallace048b1d62018-01-03 22:24:41 -05001987accept (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001988{
Dave Wallace2a865272018-02-07 21:00:42 -05001989 return ldp_accept4 (fd, addr, addr_len, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05001990}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001991
Dave Wallace048b1d62018-01-03 22:24:41 -05001992int
1993shutdown (int fd, int how)
1994{
Florin Coras7baeb712019-01-04 17:05:43 -08001995 vls_handle_t vlsh;
1996 int rv = 0, flags;
1997 u32 flags_len = sizeof (flags);
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001998
Dave Wallace2a865272018-02-07 21:00:42 -05001999 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05002000 return -1;
2001
Florin Coras7baeb712019-01-04 17:05:43 -08002002 vlsh = ldp_fd_to_vlsh (fd);
2003 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05002004 {
Florin Coras7baeb712019-01-04 17:05:43 -08002005 LDBG (0, "called shutdown: fd %u vlsh %u how %d", fd, vlsh, how);
Florin Corasa7a1a222018-12-30 17:11:31 -08002006
Florin Coras7baeb712019-01-04 17:05:43 -08002007 if (vls_attr (vlsh, VPPCOM_ATTR_SET_SHUT, &how, &flags_len))
Florin Corasa7a1a222018-12-30 17:11:31 -08002008 {
Florin Coras7baeb712019-01-04 17:05:43 -08002009 close (fd);
Florin Corasa7a1a222018-12-30 17:11:31 -08002010 return -1;
2011 }
2012
Florin Coras7baeb712019-01-04 17:05:43 -08002013 if (vls_attr (vlsh, VPPCOM_ATTR_GET_SHUT, &flags, &flags_len))
2014 {
2015 close (fd);
2016 return -1;
2017 }
Florin Corasa7a1a222018-12-30 17:11:31 -08002018
Florin Coras7baeb712019-01-04 17:05:43 -08002019 if (flags == SHUT_RDWR)
Florin Corasa7a1a222018-12-30 17:11:31 -08002020 rv = close (fd);
Dave Wallace048b1d62018-01-03 22:24:41 -05002021 }
2022 else
2023 {
Florin Coras7baeb712019-01-04 17:05:43 -08002024 LDBG (0, "fd %d: calling libc_shutdown: how %d", fd, how);
Dave Wallace048b1d62018-01-03 22:24:41 -05002025 rv = libc_shutdown (fd, how);
2026 }
2027
Dave Wallace048b1d62018-01-03 22:24:41 -05002028 return rv;
2029}
2030
2031int
2032epoll_create1 (int flags)
2033{
Florin Corasdfe4cf42018-11-28 22:13:45 -08002034 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras7baeb712019-01-04 17:05:43 -08002035 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002036 int rv;
2037
Dave Wallace2a865272018-02-07 21:00:42 -05002038 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05002039 return -1;
2040
Florin Coras99368312018-08-02 10:45:44 -07002041 if (ldp->vcl_needs_real_epoll)
2042 {
2043 rv = libc_epoll_create1 (flags);
2044 ldp->vcl_needs_real_epoll = 0;
Florin Corasdfe4cf42018-11-28 22:13:45 -08002045 ldpw->vcl_mq_epfd = rv;
Florin Coras05ecfcc2018-12-12 18:19:39 -08002046 LDBG (0, "created vcl epfd %u", rv);
Florin Coras99368312018-08-02 10:45:44 -07002047 return rv;
2048 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002049
Florin Coras7baeb712019-01-04 17:05:43 -08002050 vlsh = vls_epoll_create ();
2051 if (PREDICT_FALSE (vlsh == VLS_INVALID_HANDLE))
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002052 {
Florin Coras7baeb712019-01-04 17:05:43 -08002053 errno = -vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002054 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002055 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002056 else
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002057 {
Florin Coras7baeb712019-01-04 17:05:43 -08002058 rv = ldp_vlsh_to_fd (vlsh);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002059 }
Florin Coras7baeb712019-01-04 17:05:43 -08002060 LDBG (0, "epoll_create epfd %u vlsh %u", rv, vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05002061 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002062}
2063
2064int
Dave Wallace048b1d62018-01-03 22:24:41 -05002065epoll_create (int size)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002066{
Dave Wallace048b1d62018-01-03 22:24:41 -05002067 return epoll_create1 (0);
2068}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002069
Dave Wallace048b1d62018-01-03 22:24:41 -05002070int
2071epoll_ctl (int epfd, int op, int fd, struct epoll_event *event)
2072{
Florin Coras7baeb712019-01-04 17:05:43 -08002073 vls_handle_t vep_vlsh, vlsh;
Florin Coras99368312018-08-02 10:45:44 -07002074 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05002075
Dave Wallace2a865272018-02-07 21:00:42 -05002076 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05002077 return -1;
2078
Florin Coras7baeb712019-01-04 17:05:43 -08002079 vep_vlsh = ldp_fd_to_vlsh (epfd);
2080 if (PREDICT_FALSE (vep_vlsh == VLS_INVALID_HANDLE))
Dave Wallace048b1d62018-01-03 22:24:41 -05002081 {
Dave Wallace3ee1fe12018-02-23 01:09:11 -05002082 /* The LDP epoll_create1 always creates VCL epfd's.
2083 * The app should never have a kernel base epoll fd unless it
2084 * was acquired outside of the LD_PRELOAD process context.
2085 * In any case, if we get one, punt it to libc_epoll_ctl.
2086 */
Florin Coras7baeb712019-01-04 17:05:43 -08002087 LDBG (1, "epfd %d: calling libc_epoll_ctl: op %d, fd %d"
2088 " event %p", epfd, op, fd, event);
Dave Wallace048b1d62018-01-03 22:24:41 -05002089
2090 rv = libc_epoll_ctl (epfd, op, fd, event);
Florin Coras99368312018-08-02 10:45:44 -07002091 goto done;
2092 }
2093
Florin Coras7baeb712019-01-04 17:05:43 -08002094 vlsh = ldp_fd_to_vlsh (fd);
Florin Coras99368312018-08-02 10:45:44 -07002095
Florin Coras7baeb712019-01-04 17:05:43 -08002096 LDBG (0, "epfd %d ep_vlsh %d, fd %u vlsh %d, op %u", epfd, vep_vlsh, fd,
2097 vlsh, op);
Florin Coras99368312018-08-02 10:45:44 -07002098
Florin Coras7baeb712019-01-04 17:05:43 -08002099 if (vlsh != VLS_INVALID_HANDLE)
Florin Coras99368312018-08-02 10:45:44 -07002100 {
Florin Coras7baeb712019-01-04 17:05:43 -08002101 LDBG (1, "epfd %d: calling vls_epoll_ctl: ep_vlsh %d op %d, vlsh %u,"
2102 " event %p", epfd, vep_vlsh, vlsh, event);
Florin Coras99368312018-08-02 10:45:44 -07002103
Florin Coras7baeb712019-01-04 17:05:43 -08002104 rv = vls_epoll_ctl (vep_vlsh, op, vlsh, event);
Florin Coras99368312018-08-02 10:45:44 -07002105 if (rv != VPPCOM_OK)
2106 {
2107 errno = -rv;
2108 rv = -1;
2109 }
2110 }
2111 else
2112 {
2113 int libc_epfd;
2114 u32 size = sizeof (epfd);
2115
Florin Coras7baeb712019-01-04 17:05:43 -08002116 libc_epfd = vls_attr (vep_vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
Florin Coras99368312018-08-02 10:45:44 -07002117 if (!libc_epfd)
2118 {
Florin Coras7baeb712019-01-04 17:05:43 -08002119 LDBG (1, "epfd %d, vep_vlsh %d calling libc_epoll_create1: "
2120 "EPOLL_CLOEXEC", epfd, vep_vlsh);
Florin Coras99368312018-08-02 10:45:44 -07002121
2122 libc_epfd = libc_epoll_create1 (EPOLL_CLOEXEC);
2123 if (libc_epfd < 0)
2124 {
2125 rv = libc_epfd;
2126 goto done;
2127 }
2128
Florin Coras7baeb712019-01-04 17:05:43 -08002129 rv = vls_attr (vep_vlsh, VPPCOM_ATTR_SET_LIBC_EPFD, &libc_epfd,
2130 &size);
Florin Coras99368312018-08-02 10:45:44 -07002131 if (rv < 0)
2132 {
2133 errno = -rv;
2134 rv = -1;
2135 goto done;
2136 }
2137 }
2138 else if (PREDICT_FALSE (libc_epfd < 0))
2139 {
2140 errno = -epfd;
2141 rv = -1;
2142 goto done;
2143 }
2144
Florin Coras7baeb712019-01-04 17:05:43 -08002145 LDBG (1, "epfd %d: calling libc_epoll_ctl: libc_epfd %d, op %d, fd %d,"
2146 " event %p", epfd, libc_epfd, op, fd, event);
Florin Coras99368312018-08-02 10:45:44 -07002147
2148 rv = libc_epoll_ctl (libc_epfd, op, fd, event);
Dave Wallace048b1d62018-01-03 22:24:41 -05002149 }
2150
2151done:
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002152 return rv;
2153}
Dave Wallace048b1d62018-01-03 22:24:41 -05002154
2155static inline int
Florin Coras99368312018-08-02 10:45:44 -07002156ldp_epoll_pwait (int epfd, struct epoll_event *events, int maxevents,
2157 int timeout, const sigset_t * sigmask)
Dave Wallace048b1d62018-01-03 22:24:41 -05002158{
Florin Corasdfe4cf42018-11-28 22:13:45 -08002159 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras72f77822019-01-22 19:05:52 -08002160 double time_to_wait = (double) 0, max_time;
Florin Coras99368312018-08-02 10:45:44 -07002161 int libc_epfd, rv = 0;
Florin Coras7baeb712019-01-04 17:05:43 -08002162 vls_handle_t ep_vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002163
Dave Wallace2a865272018-02-07 21:00:42 -05002164 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05002165 return -1;
2166
2167 if (PREDICT_FALSE (!events || (timeout < -1)))
2168 {
2169 errno = EFAULT;
2170 return -1;
2171 }
2172
Florin Corasdfe4cf42018-11-28 22:13:45 -08002173 if (epfd == ldpw->vcl_mq_epfd)
Florin Coras99368312018-08-02 10:45:44 -07002174 return libc_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
2175
Florin Coras7baeb712019-01-04 17:05:43 -08002176 ep_vlsh = ldp_fd_to_vlsh (epfd);
2177 if (PREDICT_FALSE (ep_vlsh == VLS_INVALID_HANDLE))
Dave Wallace048b1d62018-01-03 22:24:41 -05002178 {
Florin Coras7baeb712019-01-04 17:05:43 -08002179 LDBG (0, "epfd %d: bad ep_vlsh %d!", epfd, ep_vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05002180 errno = EBADFD;
2181 return -1;
2182 }
2183
Florin Coras4dee8cd2019-01-29 21:28:16 -08002184 if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
2185 clib_time_init (&ldpw->clib_time);
Florin Corasb0f662f2018-12-27 14:51:46 -08002186 time_to_wait = ((timeout >= 0) ? (double) timeout / 1000 : 0);
Florin Coras72f77822019-01-22 19:05:52 -08002187 max_time = clib_time_now (&ldpw->clib_time) + time_to_wait;
Dave Wallace048b1d62018-01-03 22:24:41 -05002188
Florin Coras7baeb712019-01-04 17:05:43 -08002189 libc_epfd = vls_attr (ep_vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002190 if (PREDICT_FALSE (libc_epfd < 0))
2191 {
2192 errno = -libc_epfd;
2193 rv = -1;
2194 goto done;
2195 }
2196
Florin Coras7baeb712019-01-04 17:05:43 -08002197 LDBG (2, "epfd %d: vep_idx %d, libc_epfd %d, events %p, maxevents %d, "
2198 "timeout %d, sigmask %p: time_to_wait %.02f", epfd, ep_vlsh,
Florin Coras72f77822019-01-22 19:05:52 -08002199 libc_epfd, events, maxevents, timeout, sigmask, time_to_wait);
Dave Wallace048b1d62018-01-03 22:24:41 -05002200 do
2201 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002202 if (!ldpw->epoll_wait_vcl)
Dave Wallace048b1d62018-01-03 22:24:41 -05002203 {
Florin Coras7baeb712019-01-04 17:05:43 -08002204 rv = vls_epoll_wait (ep_vlsh, events, maxevents, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002205 if (rv > 0)
2206 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002207 ldpw->epoll_wait_vcl = 1;
Dave Wallace048b1d62018-01-03 22:24:41 -05002208 goto done;
2209 }
2210 else if (rv < 0)
2211 {
2212 errno = -rv;
2213 rv = -1;
2214 goto done;
2215 }
2216 }
2217 else
Florin Corasdfe4cf42018-11-28 22:13:45 -08002218 ldpw->epoll_wait_vcl = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -05002219
2220 if (libc_epfd > 0)
2221 {
Florin Corasb0f662f2018-12-27 14:51:46 -08002222 rv = libc_epoll_pwait (libc_epfd, events, maxevents, 0, sigmask);
Dave Wallace048b1d62018-01-03 22:24:41 -05002223 if (rv != 0)
2224 goto done;
2225 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002226 }
Florin Coras72f77822019-01-22 19:05:52 -08002227 while ((timeout == -1) || (clib_time_now (&ldpw->clib_time) < max_time));
Dave Wallace048b1d62018-01-03 22:24:41 -05002228
2229done:
Dave Wallace048b1d62018-01-03 22:24:41 -05002230 return rv;
2231}
2232
2233int
2234epoll_pwait (int epfd, struct epoll_event *events,
2235 int maxevents, int timeout, const sigset_t * sigmask)
2236{
Dave Wallace2a865272018-02-07 21:00:42 -05002237 return ldp_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
Dave Wallace048b1d62018-01-03 22:24:41 -05002238}
2239
2240int
2241epoll_wait (int epfd, struct epoll_event *events, int maxevents, int timeout)
2242{
Dave Wallace2a865272018-02-07 21:00:42 -05002243 return ldp_epoll_pwait (epfd, events, maxevents, timeout, NULL);
Dave Wallace048b1d62018-01-03 22:24:41 -05002244}
2245
2246int
2247poll (struct pollfd *fds, nfds_t nfds, int timeout)
2248{
Florin Corasdfe4cf42018-11-28 22:13:45 -08002249 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras6917b942018-11-13 22:44:54 -08002250 int rv, i, n_revents = 0;
Florin Coras7baeb712019-01-04 17:05:43 -08002251 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002252 vcl_poll_t *vp;
Florin Coras4dee8cd2019-01-29 21:28:16 -08002253 double max_time;
Dave Wallace048b1d62018-01-03 22:24:41 -05002254
Florin Coras05ecfcc2018-12-12 18:19:39 -08002255 LDBG (3, "fds %p, nfds %d, timeout %d", fds, nfds, timeout);
Dave Wallace048b1d62018-01-03 22:24:41 -05002256
Florin Coras4dee8cd2019-01-29 21:28:16 -08002257 if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
2258 clib_time_init (&ldpw->clib_time);
2259
2260 max_time = (timeout >= 0) ? (f64) timeout / 1000 : 0;
2261 max_time += clib_time_now (&ldpw->clib_time);
Dave Wallace048b1d62018-01-03 22:24:41 -05002262
Dave Wallace048b1d62018-01-03 22:24:41 -05002263 for (i = 0; i < nfds; i++)
2264 {
Florin Coras6917b942018-11-13 22:44:54 -08002265 if (fds[i].fd < 0)
2266 continue;
Dave Wallace048b1d62018-01-03 22:24:41 -05002267
Florin Coras7baeb712019-01-04 17:05:43 -08002268 vlsh = ldp_fd_to_vlsh (fds[i].fd);
2269 if (vlsh != VLS_INVALID_HANDLE)
Florin Coras6917b942018-11-13 22:44:54 -08002270 {
2271 fds[i].fd = -fds[i].fd;
Florin Corasdfe4cf42018-11-28 22:13:45 -08002272 vec_add2 (ldpw->vcl_poll, vp, 1);
Florin Coras6917b942018-11-13 22:44:54 -08002273 vp->fds_ndx = i;
Florin Coras7baeb712019-01-04 17:05:43 -08002274 vp->sh = vlsh_to_sh (vlsh);
Florin Coras6917b942018-11-13 22:44:54 -08002275 vp->events = fds[i].events;
Dave Wallace048b1d62018-01-03 22:24:41 -05002276#ifdef __USE_XOPEN2K
Florin Coras6917b942018-11-13 22:44:54 -08002277 if (fds[i].events & POLLRDNORM)
2278 vp->events |= POLLIN;
2279 if (fds[i].events & POLLWRNORM)
2280 vp->events |= POLLOUT;
Dave Wallace048b1d62018-01-03 22:24:41 -05002281#endif
Florin Coras6917b942018-11-13 22:44:54 -08002282 vp->revents = fds[i].revents;
2283 }
2284 else
2285 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002286 vec_add1 (ldpw->libc_poll, fds[i]);
2287 vec_add1 (ldpw->libc_poll_idxs, i);
Dave Wallace048b1d62018-01-03 22:24:41 -05002288 }
2289 }
2290
Dave Wallace048b1d62018-01-03 22:24:41 -05002291 do
2292 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002293 if (vec_len (ldpw->vcl_poll))
Dave Wallace048b1d62018-01-03 22:24:41 -05002294 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002295 rv = vppcom_poll (ldpw->vcl_poll, vec_len (ldpw->vcl_poll), 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002296 if (rv < 0)
2297 {
2298 errno = -rv;
2299 rv = -1;
2300 goto done;
2301 }
2302 else
2303 n_revents += rv;
2304 }
2305
Florin Corasdfe4cf42018-11-28 22:13:45 -08002306 if (vec_len (ldpw->libc_poll))
Dave Wallace048b1d62018-01-03 22:24:41 -05002307 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002308 rv = libc_poll (ldpw->libc_poll, vec_len (ldpw->libc_poll), 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002309 if (rv < 0)
2310 goto done;
2311 else
2312 n_revents += rv;
2313 }
2314
2315 if (n_revents)
2316 {
2317 rv = n_revents;
2318 goto done;
2319 }
2320 }
Florin Coras4dee8cd2019-01-29 21:28:16 -08002321 while ((timeout < 0) || (clib_time_now (&ldpw->clib_time) < max_time));
Dave Wallace048b1d62018-01-03 22:24:41 -05002322 rv = 0;
2323
2324done:
Florin Corasdfe4cf42018-11-28 22:13:45 -08002325 vec_foreach (vp, ldpw->vcl_poll)
Dave Wallace048b1d62018-01-03 22:24:41 -05002326 {
2327 fds[vp->fds_ndx].fd = -fds[vp->fds_ndx].fd;
Florin Coras6917b942018-11-13 22:44:54 -08002328 fds[vp->fds_ndx].revents = vp->revents;
Dave Wallace048b1d62018-01-03 22:24:41 -05002329#ifdef __USE_XOPEN2K
2330 if ((fds[vp->fds_ndx].revents & POLLIN) &&
2331 (fds[vp->fds_ndx].events & POLLRDNORM))
2332 fds[vp->fds_ndx].revents |= POLLRDNORM;
2333 if ((fds[vp->fds_ndx].revents & POLLOUT) &&
2334 (fds[vp->fds_ndx].events & POLLWRNORM))
2335 fds[vp->fds_ndx].revents |= POLLWRNORM;
2336#endif
2337 }
Florin Corasdfe4cf42018-11-28 22:13:45 -08002338 vec_reset_length (ldpw->vcl_poll);
Dave Wallace048b1d62018-01-03 22:24:41 -05002339
Florin Corasdfe4cf42018-11-28 22:13:45 -08002340 for (i = 0; i < vec_len (ldpw->libc_poll); i++)
Florin Coras6917b942018-11-13 22:44:54 -08002341 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002342 fds[ldpw->libc_poll_idxs[i]].revents = ldpw->libc_poll[i].revents;
Florin Coras6917b942018-11-13 22:44:54 -08002343 }
Florin Corasdfe4cf42018-11-28 22:13:45 -08002344 vec_reset_length (ldpw->libc_poll_idxs);
2345 vec_reset_length (ldpw->libc_poll);
Florin Coras6917b942018-11-13 22:44:54 -08002346
Dave Wallace048b1d62018-01-03 22:24:41 -05002347 return rv;
2348}
2349
2350#ifdef USE_GNU
2351int
2352ppoll (struct pollfd *fds, nfds_t nfds,
2353 const struct timespec *timeout, const sigset_t * sigmask)
2354{
Dave Wallace2a865272018-02-07 21:00:42 -05002355 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05002356 return -1;
2357
2358 clib_warning ("LDP<%d>: LDP-TBD", getpid ());
2359 errno = ENOSYS;
2360
2361
2362 return -1;
2363}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002364#endif
2365
Dave Wallace2a865272018-02-07 21:00:42 -05002366void CONSTRUCTOR_ATTRIBUTE ldp_constructor (void);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002367
Dave Wallace2a865272018-02-07 21:00:42 -05002368void DESTRUCTOR_ATTRIBUTE ldp_destructor (void);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002369
Dave Wallace048b1d62018-01-03 22:24:41 -05002370/*
2371 * This function is called when the library is loaded
2372 */
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002373void
Dave Wallace2a865272018-02-07 21:00:42 -05002374ldp_constructor (void)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002375{
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002376 swrap_constructor ();
Dave Wallace2a865272018-02-07 21:00:42 -05002377 if (ldp_init () != 0)
2378 fprintf (stderr, "\nLDP<%d>: ERROR: ldp_constructor: failed!\n",
Dave Wallace048b1d62018-01-03 22:24:41 -05002379 getpid ());
Dave Wallace69d01192018-02-22 16:22:09 -05002380 else if (LDP_DEBUG > 0)
Dave Wallace2a865272018-02-07 21:00:42 -05002381 clib_warning ("LDP<%d>: LDP constructor: done!\n", getpid ());
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002382}
2383
2384/*
2385 * This function is called when the library is unloaded
2386 */
2387void
Dave Wallace2a865272018-02-07 21:00:42 -05002388ldp_destructor (void)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002389{
Florin Coras0ef8ef22019-01-18 08:37:13 -08002390 /*
2391 swrap_destructor ();
2392 if (ldp->init)
2393 ldp->init = 0;
2394 */
Dave Wallace048b1d62018-01-03 22:24:41 -05002395
2396 /* Don't use clib_warning() here because that calls writev()
Dave Wallace2a865272018-02-07 21:00:42 -05002397 * which will call ldp_init().
Dave Wallace048b1d62018-01-03 22:24:41 -05002398 */
Dave Wallace69d01192018-02-22 16:22:09 -05002399 if (LDP_DEBUG > 0)
Florin Coras0ef8ef22019-01-18 08:37:13 -08002400 fprintf (stderr, "%s:%d: LDP<%d>: LDP destructor: done!\n",
2401 __func__, __LINE__, getpid ());
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002402}
2403
2404
2405/*
2406 * fd.io coding-style-patch-verification: ON
2407 *
2408 * Local Variables:
2409 * eval: (c-set-style "gnu")
2410 * End:
2411 */