blob: ab4cfbfa25774f7291540715e996d9e684456c33 [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 Corasdfe4cf42018-11-28 22:13:45 -0800264 clib_time_init (&ldpw->clib_time);
Florin Coras05ecfcc2018-12-12 18:19:39 -0800265 LDBG (0, "LDP initialization: done!");
Florin Coras99368312018-08-02 10:45:44 -0700266
267 return 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500268}
269
270int
271close (int fd)
272{
Florin Coras7baeb712019-01-04 17:05:43 -0800273 vls_handle_t vlsh;
274 int rv, epfd;
Dave Wallace048b1d62018-01-03 22:24:41 -0500275
Dave Wallace2a865272018-02-07 21:00:42 -0500276 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500277 return -1;
278
Florin Coras7baeb712019-01-04 17:05:43 -0800279 vlsh = ldp_fd_to_vlsh (fd);
280 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500281 {
Florin Coras7baeb712019-01-04 17:05:43 -0800282 epfd = vls_attr (vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -0500283 if (epfd > 0)
284 {
Florin Coras7baeb712019-01-04 17:05:43 -0800285 LDBG (0, "fd %d: calling libc_close: epfd %u", fd, epfd);
Dave Wallace048b1d62018-01-03 22:24:41 -0500286
287 rv = libc_close (epfd);
288 if (rv < 0)
289 {
290 u32 size = sizeof (epfd);
291 epfd = 0;
292
Florin Coras7baeb712019-01-04 17:05:43 -0800293 (void) vls_attr (vlsh, VPPCOM_ATTR_SET_LIBC_EPFD, &epfd, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -0500294 }
295 }
296 else if (PREDICT_FALSE (epfd < 0))
297 {
298 errno = -epfd;
299 rv = -1;
300 goto done;
301 }
302
Florin Coras7baeb712019-01-04 17:05:43 -0800303 LDBG (0, "fd %d: calling vls_close: vlsh %u", fd, vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -0500304
Florin Coras7baeb712019-01-04 17:05:43 -0800305 rv = vls_close (vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -0500306 if (rv != VPPCOM_OK)
307 {
308 errno = -rv;
309 rv = -1;
310 }
311 }
312 else
313 {
Florin Coras7baeb712019-01-04 17:05:43 -0800314 LDBG (0, "fd %d: calling libc_close", fd);
Dave Wallace048b1d62018-01-03 22:24:41 -0500315 rv = libc_close (fd);
316 }
317
318done:
Dave Wallace048b1d62018-01-03 22:24:41 -0500319 return rv;
320}
321
322ssize_t
323read (int fd, void *buf, size_t nbytes)
324{
Florin Coras7baeb712019-01-04 17:05:43 -0800325 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500326 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -0500327
Dave Wallace2a865272018-02-07 21:00:42 -0500328 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500329 return -1;
330
Florin Coras7baeb712019-01-04 17:05:43 -0800331 vlsh = ldp_fd_to_vlsh (fd);
332 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500333 {
Florin Coras7baeb712019-01-04 17:05:43 -0800334 size = vls_read (vlsh, buf, nbytes);
Dave Wallace048b1d62018-01-03 22:24:41 -0500335 if (size < 0)
336 {
337 errno = -size;
338 size = -1;
339 }
340 }
341 else
342 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500343 size = libc_read (fd, buf, nbytes);
344 }
345
Dave Wallace048b1d62018-01-03 22:24:41 -0500346 return size;
347}
348
349ssize_t
350readv (int fd, const struct iovec * iov, int iovcnt)
351{
Dave Wallace8aaba562018-01-18 17:21:19 -0500352 int rv = 0, i, total = 0;
Florin Coras7baeb712019-01-04 17:05:43 -0800353 vls_handle_t vlsh;
354 ssize_t size = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500355
Dave Wallace2a865272018-02-07 21:00:42 -0500356 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500357 return -1;
358
Florin Coras7baeb712019-01-04 17:05:43 -0800359 vlsh = ldp_fd_to_vlsh (fd);
360 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500361 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500362 do
363 {
364 for (i = 0; i < iovcnt; ++i)
365 {
Florin Coras7baeb712019-01-04 17:05:43 -0800366 rv = vls_read (vlsh, iov[i].iov_base, iov[i].iov_len);
Dave Wallace048b1d62018-01-03 22:24:41 -0500367 if (rv < 0)
368 break;
369 else
370 {
371 total += rv;
372 if (rv < iov[i].iov_len)
Florin Coras7baeb712019-01-04 17:05:43 -0800373 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700374 }
375 }
376 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500377 while ((rv >= 0) && (total == 0));
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700378
Dave Wallace048b1d62018-01-03 22:24:41 -0500379 if (rv < 0)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700380 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500381 errno = -rv;
382 size = -1;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700383 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500384 else
385 size = total;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700386 }
387 else
388 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500389 size = libc_readv (fd, iov, iovcnt);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700390 }
391
Dave Wallace048b1d62018-01-03 22:24:41 -0500392 return size;
393}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700394
Dave Wallace048b1d62018-01-03 22:24:41 -0500395ssize_t
396write (int fd, const void *buf, size_t nbytes)
397{
Florin Coras7baeb712019-01-04 17:05:43 -0800398 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500399 ssize_t size = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500400
Dave Wallace2a865272018-02-07 21:00:42 -0500401 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500402 return -1;
403
Florin Coras7baeb712019-01-04 17:05:43 -0800404 vlsh = ldp_fd_to_vlsh (fd);
405 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500406 {
Florin Coras7baeb712019-01-04 17:05:43 -0800407 size = vls_write_msg (vlsh, (void *) buf, nbytes);
Dave Wallace048b1d62018-01-03 22:24:41 -0500408 if (size < 0)
409 {
410 errno = -size;
411 size = -1;
412 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700413 }
414 else
415 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500416 size = libc_write (fd, buf, nbytes);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700417 }
418
Dave Wallace048b1d62018-01-03 22:24:41 -0500419 return size;
420}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700421
Dave Wallace048b1d62018-01-03 22:24:41 -0500422ssize_t
423writev (int fd, const struct iovec * iov, int iovcnt)
424{
Dave Wallace048b1d62018-01-03 22:24:41 -0500425 ssize_t size = 0, total = 0;
Florin Coras7baeb712019-01-04 17:05:43 -0800426 vls_handle_t vlsh;
Dave Wallace8aaba562018-01-18 17:21:19 -0500427 int i, rv = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500428
Dave Wallace2a865272018-02-07 21:00:42 -0500429 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500430 return -1;
431
Florin Coras7baeb712019-01-04 17:05:43 -0800432 vlsh = ldp_fd_to_vlsh (fd);
433 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500434 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500435 do
436 {
437 for (i = 0; i < iovcnt; ++i)
438 {
Florin Coras7baeb712019-01-04 17:05:43 -0800439 rv = vls_write_msg (vlsh, iov[i].iov_base, iov[i].iov_len);
Dave Wallace048b1d62018-01-03 22:24:41 -0500440 if (rv < 0)
441 break;
442 else
443 {
444 total += rv;
445 if (rv < iov[i].iov_len)
Florin Corasb0f662f2018-12-27 14:51:46 -0800446 break;
Dave Wallace048b1d62018-01-03 22:24:41 -0500447 }
448 }
449 }
450 while ((rv >= 0) && (total == 0));
451
452 if (rv < 0)
453 {
454 errno = -rv;
455 size = -1;
456 }
457 else
458 size = total;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700459 }
460 else
461 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500462 size = libc_writev (fd, iov, iovcnt);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700463 }
464
Dave Wallace048b1d62018-01-03 22:24:41 -0500465 return size;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700466}
467
468int
Dave Wallace048b1d62018-01-03 22:24:41 -0500469fcntl (int fd, int cmd, ...)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700470{
Florin Coras7baeb712019-01-04 17:05:43 -0800471 vls_handle_t vlsh;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700472 int rv = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500473 va_list ap;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700474
Dave Wallace2a865272018-02-07 21:00:42 -0500475 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500476 return -1;
477
478 va_start (ap, cmd);
Florin Coras7baeb712019-01-04 17:05:43 -0800479
480 vlsh = ldp_fd_to_vlsh (fd);
481 LDBG (0, "fd %u vlsh %d, cmd %u", fd, vlsh, cmd);
482 if (vlsh != VLS_INVALID_HANDLE)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700483 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500484 int flags = va_arg (ap, int);
485 u32 size;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700486
Dave Wallace048b1d62018-01-03 22:24:41 -0500487 size = sizeof (flags);
488 rv = -EOPNOTSUPP;
489 switch (cmd)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700490 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500491 case F_SETFL:
Florin Coras7baeb712019-01-04 17:05:43 -0800492 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_FLAGS, &flags, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -0500493 break;
494
495 case F_GETFL:
Florin Coras7baeb712019-01-04 17:05:43 -0800496 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_FLAGS, &flags, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -0500497 if (rv == VPPCOM_OK)
Florin Coras7baeb712019-01-04 17:05:43 -0800498 rv = flags;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700499 break;
Florin Coras173bae32018-11-16 18:56:28 -0800500 case F_SETFD:
501 /* TODO handle this */
502 LDBG (0, "F_SETFD ignored flags %u", flags);
503 rv = 0;
504 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700505 default:
Dave Wallace048b1d62018-01-03 22:24:41 -0500506 rv = -EOPNOTSUPP;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700507 break;
508 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500509 if (rv < 0)
510 {
511 errno = -rv;
512 rv = -1;
513 }
514 }
515 else
516 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500517 rv = libc_vfcntl (fd, cmd, ap);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700518 }
519
Dave Wallace048b1d62018-01-03 22:24:41 -0500520 va_end (ap);
521
Dave Wallace048b1d62018-01-03 22:24:41 -0500522 return rv;
523}
524
525int
526ioctl (int fd, unsigned long int cmd, ...)
527{
Florin Coras7baeb712019-01-04 17:05:43 -0800528 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500529 va_list ap;
Florin Coras7baeb712019-01-04 17:05:43 -0800530 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -0500531
Dave Wallace2a865272018-02-07 21:00:42 -0500532 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500533 return -1;
534
535 va_start (ap, cmd);
Dave Wallace048b1d62018-01-03 22:24:41 -0500536
Florin Coras7baeb712019-01-04 17:05:43 -0800537 vlsh = ldp_fd_to_vlsh (fd);
538 if (vlsh != VLS_INVALID_HANDLE)
539 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500540 switch (cmd)
541 {
542 case FIONREAD:
Florin Coras7baeb712019-01-04 17:05:43 -0800543 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_NREAD, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -0500544 break;
545
546 case FIONBIO:
547 {
548 u32 flags = va_arg (ap, int) ? O_NONBLOCK : 0;
549 u32 size = sizeof (flags);
550
551 /* TBD: When VPPCOM_ATTR_[GS]ET_FLAGS supports flags other than
552 * non-blocking, the flags should be read here and merged
553 * with O_NONBLOCK.
554 */
Florin Coras7baeb712019-01-04 17:05:43 -0800555 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_FLAGS, &flags, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -0500556 }
557 break;
558
559 default:
560 rv = -EOPNOTSUPP;
561 break;
562 }
563 if (rv < 0)
564 {
565 errno = -rv;
566 rv = -1;
567 }
568 }
569 else
570 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500571 rv = libc_vioctl (fd, cmd, ap);
572 }
573
Dave Wallace048b1d62018-01-03 22:24:41 -0500574 va_end (ap);
575 return rv;
576}
577
Florin Coras294afe22019-01-07 17:49:17 -0800578always_inline void
579ldp_select_init_maps (fd_set * __restrict original,
580 clib_bitmap_t ** resultb, clib_bitmap_t ** libcb,
581 clib_bitmap_t ** vclb, int nfds, u32 minbits,
582 u32 n_bytes, uword * si_bits, uword * libc_bits)
583{
584 uword si_bits_set, libc_bits_set;
585 vls_handle_t vlsh;
586 int fd;
587
588 clib_bitmap_validate (*vclb, minbits);
589 clib_bitmap_validate (*libcb, minbits);
590 clib_bitmap_validate (*resultb, minbits);
591 clib_memcpy_fast (*resultb, original, n_bytes);
592 memset (original, 0, n_bytes);
593
594 /* *INDENT-OFF* */
595 clib_bitmap_foreach (fd, *resultb, ({
596 if (fd > nfds)
597 break;
598 vlsh = ldp_fd_to_vlsh (fd);
599 if (vlsh == VLS_INVALID_HANDLE)
600 clib_bitmap_set_no_check (*libcb, fd, 1);
601 else
602 clib_bitmap_set_no_check (*vclb, vlsh_to_session_index (vlsh), 1);
603 }));
604 /* *INDENT-ON* */
605
606 si_bits_set = clib_bitmap_last_set (*vclb) + 1;
607 *si_bits = (si_bits_set > *si_bits) ? si_bits_set : *si_bits;
608
609 libc_bits_set = clib_bitmap_last_set (*libcb) + 1;
610 *libc_bits = (libc_bits_set > *libc_bits) ? libc_bits_set : *libc_bits;
611}
612
613always_inline int
614ldp_select_vcl_map_to_libc (clib_bitmap_t * vclb, fd_set * __restrict libcb)
615{
616 vls_handle_t vlsh;
617 uword si;
618 int fd;
619
620 if (!libcb)
621 return 0;
622
623 /* *INDENT-OFF* */
624 clib_bitmap_foreach (si, vclb, ({
625 vlsh = vls_session_index_to_vlsh (si);
626 fd = ldp_vlsh_to_fd (vlsh);
627 if (PREDICT_FALSE (fd < 0))
628 {
629 errno = EBADFD;
630 return -1;
631 }
632 FD_SET (fd, libcb);
633 }));
634 /* *INDENT-ON* */
635
636 return 0;
637}
638
639always_inline void
640ldp_select_libc_map_merge (clib_bitmap_t * result, fd_set * __restrict libcb)
641{
642 uword fd;
643
644 /* *INDENT-OFF* */
645 clib_bitmap_foreach (fd, result, ({
646 FD_SET ((int)fd, libcb);
647 }));
648 /* *INDENT-ON* */
649}
650
Dave Wallace048b1d62018-01-03 22:24:41 -0500651int
Dave Wallace2a865272018-02-07 21:00:42 -0500652ldp_pselect (int nfds, fd_set * __restrict readfds,
653 fd_set * __restrict writefds,
654 fd_set * __restrict exceptfds,
655 const struct timespec *__restrict timeout,
656 const __sigset_t * __restrict sigmask)
Dave Wallace048b1d62018-01-03 22:24:41 -0500657{
Florin Coras294afe22019-01-07 17:49:17 -0800658 u32 minbits = clib_max (nfds, BITS (uword)), n_bytes;
Florin Corasdfe4cf42018-11-28 22:13:45 -0800659 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras294afe22019-01-07 17:49:17 -0800660 struct timespec libc_tspec = { 0 };
661 f64 time_out, vcl_timeout = 0;
662 uword si_bits, libc_bits;
663 int rv, bits_set = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500664
665 if (nfds < 0)
666 {
667 errno = EINVAL;
668 return -1;
669 }
670
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500671 if (timeout)
672 {
673 time_out = (timeout->tv_sec == 0 && timeout->tv_nsec == 0) ?
Florin Coras7baeb712019-01-04 17:05:43 -0800674 (f64) 0 : (f64) timeout->tv_sec + (f64) timeout->tv_nsec / (f64) 1e9;
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500675
676 /* select as fine grained sleep */
677 if (!nfds)
678 {
Florin Corasdfe4cf42018-11-28 22:13:45 -0800679 time_out += clib_time_now (&ldpw->clib_time);
680 while (clib_time_now (&ldpw->clib_time) < time_out)
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500681 ;
682 return 0;
683 }
684 }
685 else if (!nfds)
686 {
687 errno = EINVAL;
688 return -1;
689 }
690 else
691 time_out = -1;
692
Florin Coras7baeb712019-01-04 17:05:43 -0800693 if (nfds <= ldp->vlsh_bit_val)
Dave Wallace048b1d62018-01-03 22:24:41 -0500694 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500695 rv = libc_pselect (nfds, readfds, writefds, exceptfds,
696 timeout, sigmask);
697 goto done;
698 }
699
Florin Coras294afe22019-01-07 17:49:17 -0800700 si_bits = libc_bits = 0;
701 n_bytes = nfds / 8 + ((nfds % 8) ? 1 : 0);
Florin Coras7baeb712019-01-04 17:05:43 -0800702
Dave Wallace048b1d62018-01-03 22:24:41 -0500703 if (readfds)
Florin Coras294afe22019-01-07 17:49:17 -0800704 ldp_select_init_maps (readfds, &ldpw->rd_bitmap, &ldpw->libc_rd_bitmap,
705 &ldpw->si_rd_bitmap, nfds, minbits, n_bytes,
706 &si_bits, &libc_bits);
Dave Wallace048b1d62018-01-03 22:24:41 -0500707 if (writefds)
Florin Coras294afe22019-01-07 17:49:17 -0800708 ldp_select_init_maps (writefds, &ldpw->wr_bitmap,
709 &ldpw->libc_wr_bitmap, &ldpw->si_wr_bitmap, nfds,
710 minbits, n_bytes, &si_bits, &libc_bits);
Dave Wallace048b1d62018-01-03 22:24:41 -0500711 if (exceptfds)
Florin Coras294afe22019-01-07 17:49:17 -0800712 ldp_select_init_maps (exceptfds, &ldpw->ex_bitmap,
713 &ldpw->libc_ex_bitmap, &ldpw->si_ex_bitmap, nfds,
714 minbits, n_bytes, &si_bits, &libc_bits);
Dave Wallace048b1d62018-01-03 22:24:41 -0500715
Florin Coras294afe22019-01-07 17:49:17 -0800716 if (PREDICT_FALSE (!si_bits && !libc_bits))
Dave Wallace048b1d62018-01-03 22:24:41 -0500717 {
718 errno = EINVAL;
719 rv = -1;
720 goto done;
721 }
722
Florin Coras294afe22019-01-07 17:49:17 -0800723 libc_tspec = si_bits ? libc_tspec : *timeout;
724
Dave Wallace048b1d62018-01-03 22:24:41 -0500725 do
726 {
Florin Coras294afe22019-01-07 17:49:17 -0800727 if (si_bits)
Dave Wallace048b1d62018-01-03 22:24:41 -0500728 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500729 if (readfds)
Florin Coras294afe22019-01-07 17:49:17 -0800730 clib_memcpy_fast (ldpw->rd_bitmap, ldpw->si_rd_bitmap,
Florin Corasdfe4cf42018-11-28 22:13:45 -0800731 vec_len (ldpw->rd_bitmap) *
Dave Barach178cf492018-11-13 16:34:13 -0500732 sizeof (clib_bitmap_t));
Dave Wallace048b1d62018-01-03 22:24:41 -0500733 if (writefds)
Florin Coras294afe22019-01-07 17:49:17 -0800734 clib_memcpy_fast (ldpw->wr_bitmap, ldpw->si_wr_bitmap,
Florin Corasdfe4cf42018-11-28 22:13:45 -0800735 vec_len (ldpw->wr_bitmap) *
Dave Barach178cf492018-11-13 16:34:13 -0500736 sizeof (clib_bitmap_t));
Dave Wallace048b1d62018-01-03 22:24:41 -0500737 if (exceptfds)
Florin Coras294afe22019-01-07 17:49:17 -0800738 clib_memcpy_fast (ldpw->ex_bitmap, ldpw->si_ex_bitmap,
Florin Corasdfe4cf42018-11-28 22:13:45 -0800739 vec_len (ldpw->ex_bitmap) *
Dave Barach178cf492018-11-13 16:34:13 -0500740 sizeof (clib_bitmap_t));
Florin Coras294afe22019-01-07 17:49:17 -0800741
Florin Coras0ef8ef22019-01-18 08:37:13 -0800742 rv = vls_select (si_bits, readfds ? ldpw->rd_bitmap : NULL,
743 writefds ? ldpw->wr_bitmap : NULL,
744 exceptfds ? ldpw->ex_bitmap : NULL, vcl_timeout);
Florin Coras294afe22019-01-07 17:49:17 -0800745 if (rv < 0)
746 {
747 errno = -rv;
748 rv = -1;
749 }
750 else if (rv > 0)
751 {
752 if (ldp_select_vcl_map_to_libc (ldpw->rd_bitmap, readfds))
753 {
754 rv = -1;
755 goto done;
756 }
757
758 if (ldp_select_vcl_map_to_libc (ldpw->wr_bitmap, writefds))
759 {
760 rv = -1;
761 goto done;
762 }
763
764 if (ldp_select_vcl_map_to_libc (ldpw->ex_bitmap, exceptfds))
765 {
766 rv = -1;
767 goto done;
768 }
769 bits_set = rv;
770 }
771 }
772 if (libc_bits)
773 {
774 if (readfds)
775 clib_memcpy_fast (ldpw->rd_bitmap, ldpw->libc_rd_bitmap,
776 vec_len (ldpw->libc_rd_bitmap) *
777 sizeof (clib_bitmap_t));
778 if (writefds)
779 clib_memcpy_fast (ldpw->wr_bitmap, ldpw->libc_wr_bitmap,
780 vec_len (ldpw->libc_wr_bitmap) *
781 sizeof (clib_bitmap_t));
782 if (exceptfds)
783 clib_memcpy_fast (ldpw->ex_bitmap, ldpw->libc_ex_bitmap,
784 vec_len (ldpw->libc_ex_bitmap) *
785 sizeof (clib_bitmap_t));
786
Dave Wallace048b1d62018-01-03 22:24:41 -0500787 rv = libc_pselect (libc_bits,
Florin Coras294afe22019-01-07 17:49:17 -0800788 readfds ? (fd_set *) ldpw->rd_bitmap : NULL,
789 writefds ? (fd_set *) ldpw->wr_bitmap : NULL,
790 exceptfds ? (fd_set *) ldpw->ex_bitmap : NULL,
791 &libc_tspec, sigmask);
792 if (rv > 0)
793 {
794 ldp_select_libc_map_merge (ldpw->rd_bitmap, readfds);
795 ldp_select_libc_map_merge (ldpw->wr_bitmap, writefds);
796 ldp_select_libc_map_merge (ldpw->ex_bitmap, exceptfds);
797 bits_set += rv;
798 }
799 }
800
801 if (bits_set)
802 {
803 rv = bits_set;
804 goto done;
Dave Wallace048b1d62018-01-03 22:24:41 -0500805 }
806 }
Florin Corasdfe4cf42018-11-28 22:13:45 -0800807 while ((time_out == -1) || (clib_time_now (&ldpw->clib_time) < time_out));
Dave Wallace048b1d62018-01-03 22:24:41 -0500808 rv = 0;
809
810done:
811 /* TBD: set timeout to amount of time left */
Florin Corasdfe4cf42018-11-28 22:13:45 -0800812 clib_bitmap_zero (ldpw->rd_bitmap);
Florin Coras294afe22019-01-07 17:49:17 -0800813 clib_bitmap_zero (ldpw->si_rd_bitmap);
Florin Corasdfe4cf42018-11-28 22:13:45 -0800814 clib_bitmap_zero (ldpw->libc_rd_bitmap);
815 clib_bitmap_zero (ldpw->wr_bitmap);
Florin Coras294afe22019-01-07 17:49:17 -0800816 clib_bitmap_zero (ldpw->si_wr_bitmap);
Florin Corasdfe4cf42018-11-28 22:13:45 -0800817 clib_bitmap_zero (ldpw->libc_wr_bitmap);
818 clib_bitmap_zero (ldpw->ex_bitmap);
Florin Coras294afe22019-01-07 17:49:17 -0800819 clib_bitmap_zero (ldpw->si_ex_bitmap);
Florin Corasdfe4cf42018-11-28 22:13:45 -0800820 clib_bitmap_zero (ldpw->libc_ex_bitmap);
Dave Wallace048b1d62018-01-03 22:24:41 -0500821
Dave Wallace048b1d62018-01-03 22:24:41 -0500822 return rv;
823}
824
825int
826select (int nfds, fd_set * __restrict readfds,
827 fd_set * __restrict writefds,
828 fd_set * __restrict exceptfds, struct timeval *__restrict timeout)
829{
830 struct timespec tspec;
831
832 if (timeout)
833 {
834 tspec.tv_sec = timeout->tv_sec;
835 tspec.tv_nsec = timeout->tv_usec * 1000;
836 }
Dave Wallace2a865272018-02-07 21:00:42 -0500837 return ldp_pselect (nfds, readfds, writefds, exceptfds,
838 timeout ? &tspec : NULL, NULL);
Dave Wallace048b1d62018-01-03 22:24:41 -0500839}
840
841#ifdef __USE_XOPEN2K
842int
843pselect (int nfds, fd_set * __restrict readfds,
844 fd_set * __restrict writefds,
845 fd_set * __restrict exceptfds,
846 const struct timespec *__restrict timeout,
847 const __sigset_t * __restrict sigmask)
848{
Dave Wallace2a865272018-02-07 21:00:42 -0500849 return ldp_pselect (nfds, readfds, writefds, exceptfds, timeout, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -0500850}
851#endif
852
853int
854socket (int domain, int type, int protocol)
855{
Florin Coras7baeb712019-01-04 17:05:43 -0800856 int rv, sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
Dave Wallace048b1d62018-01-03 22:24:41 -0500857 u8 is_nonblocking = type & SOCK_NONBLOCK ? 1 : 0;
Florin Coras7baeb712019-01-04 17:05:43 -0800858 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500859
Dave Wallace2a865272018-02-07 21:00:42 -0500860 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500861 return -1;
862
863 if (((domain == AF_INET) || (domain == AF_INET6)) &&
864 ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM)))
865 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500866 u8 proto = ((sock_type == SOCK_DGRAM) ?
867 VPPCOM_PROTO_UDP : VPPCOM_PROTO_TCP);
868
Florin Coras7baeb712019-01-04 17:05:43 -0800869 LDBG (0, "calling vls_create: proto %u (%s), is_nonblocking %u",
870 proto, vppcom_proto_str (proto), is_nonblocking);
Dave Wallace048b1d62018-01-03 22:24:41 -0500871
Florin Coras7baeb712019-01-04 17:05:43 -0800872 vlsh = vls_create (proto, is_nonblocking);
873 if (vlsh < 0)
Dave Wallace048b1d62018-01-03 22:24:41 -0500874 {
Florin Coras7baeb712019-01-04 17:05:43 -0800875 errno = -vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500876 rv = -1;
877 }
878 else
879 {
Florin Coras7baeb712019-01-04 17:05:43 -0800880 rv = ldp_vlsh_to_fd (vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -0500881 }
882 }
883 else
884 {
Florin Coras7baeb712019-01-04 17:05:43 -0800885 LDBG (0, "calling libc_socket");
Dave Wallace048b1d62018-01-03 22:24:41 -0500886 rv = libc_socket (domain, type, protocol);
887 }
888
Dave Wallace048b1d62018-01-03 22:24:41 -0500889 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700890}
891
892/*
893 * Create two new sockets, of type TYPE in domain DOMAIN and using
894 * protocol PROTOCOL, which are connected to each other, and put file
895 * descriptors for them in FDS[0] and FDS[1]. If PROTOCOL is zero,
896 * one will be chosen automatically.
897 * Returns 0 on success, -1 for errors.
898 * */
899int
Dave Wallace048b1d62018-01-03 22:24:41 -0500900socketpair (int domain, int type, int protocol, int fds[2])
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700901{
Florin Coras7baeb712019-01-04 17:05:43 -0800902 int rv, sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
Dave Wallace048b1d62018-01-03 22:24:41 -0500903
Dave Wallace2a865272018-02-07 21:00:42 -0500904 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500905 return -1;
906
907 if (((domain == AF_INET) || (domain == AF_INET6)) &&
908 ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM)))
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700909 {
Florin Coras7baeb712019-01-04 17:05:43 -0800910 LDBG (0, "LDP-TBD");
Dave Wallace048b1d62018-01-03 22:24:41 -0500911 errno = ENOSYS;
912 rv = -1;
913 }
914 else
915 {
Florin Coras7baeb712019-01-04 17:05:43 -0800916 LDBG (1, "calling libc_socketpair");
Florin Coras173bae32018-11-16 18:56:28 -0800917 rv = libc_socketpair (domain, type, protocol, fds);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700918 }
919
Dave Wallace048b1d62018-01-03 22:24:41 -0500920 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700921}
922
923int
Dave Wallace048b1d62018-01-03 22:24:41 -0500924bind (int fd, __CONST_SOCKADDR_ARG addr, socklen_t len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700925{
Florin Coras7baeb712019-01-04 17:05:43 -0800926 vls_handle_t vlsh;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700927 int rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700928
Dave Wallace2a865272018-02-07 21:00:42 -0500929 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -0500930 return -1;
931
Florin Coras7baeb712019-01-04 17:05:43 -0800932 vlsh = ldp_fd_to_vlsh (fd);
933 if (vlsh != VLS_INVALID_HANDLE)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700934 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500935 vppcom_endpt_t ep;
936
Dave Wallace048b1d62018-01-03 22:24:41 -0500937 switch (addr->sa_family)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700938 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500939 case AF_INET:
940 if (len != sizeof (struct sockaddr_in))
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700941 {
Florin Coras7baeb712019-01-04 17:05:43 -0800942 LDBG (0, "ERROR: fd %d: vlsh %u: Invalid AF_INET addr len %u!",
943 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -0500944 errno = EINVAL;
945 rv = -1;
946 goto done;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700947 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500948 ep.is_ip4 = VPPCOM_IS_IP4;
949 ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr;
950 ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port;
951 break;
952
953 case AF_INET6:
954 if (len != sizeof (struct sockaddr_in6))
955 {
Florin Coras7baeb712019-01-04 17:05:43 -0800956 LDBG (0, "ERROR: fd %d: vlsh %u: Invalid AF_INET6 addr len %u!",
957 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -0500958 errno = EINVAL;
959 rv = -1;
960 goto done;
961 }
962 ep.is_ip4 = VPPCOM_IS_IP6;
963 ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
964 ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700965 break;
966
967 default:
Florin Coras7baeb712019-01-04 17:05:43 -0800968 LDBG (0, "ERROR: fd %d: vlsh %u: Unsupported address family %u!",
969 fd, vlsh, addr->sa_family);
Dave Wallace048b1d62018-01-03 22:24:41 -0500970 errno = EAFNOSUPPORT;
971 rv = -1;
972 goto done;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700973 }
Florin Coras7baeb712019-01-04 17:05:43 -0800974 LDBG (0, "fd %d: calling vls_bind: vlsh %u, addr %p, len %u", fd, vlsh,
975 addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -0500976
Florin Coras7baeb712019-01-04 17:05:43 -0800977 rv = vls_bind (vlsh, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -0500978 if (rv != VPPCOM_OK)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700979 {
980 errno = -rv;
Dave Wallace048b1d62018-01-03 22:24:41 -0500981 rv = -1;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700982 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700983 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500984 else
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700985 {
Florin Coras7baeb712019-01-04 17:05:43 -0800986 LDBG (0, "fd %d: calling libc_bind: addr %p, len %u", fd, addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -0500987 rv = libc_bind (fd, addr, len);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700988 }
989
Dave Wallace048b1d62018-01-03 22:24:41 -0500990done:
Florin Coras7baeb712019-01-04 17:05:43 -0800991 LDBG (1, "fd %d: returning %d", fd, rv);
Florin Coras05ecfcc2018-12-12 18:19:39 -0800992
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700993 return rv;
994}
995
996static inline int
Dave Wallace2a865272018-02-07 21:00:42 -0500997ldp_copy_ep_to_sockaddr (__SOCKADDR_ARG addr, socklen_t * __restrict len,
998 vppcom_endpt_t * ep)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700999{
Dave Wallace048b1d62018-01-03 22:24:41 -05001000 int rv = 0;
1001 int sa_len, copy_len;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001002
Dave Wallace2a865272018-02-07 21:00:42 -05001003 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001004 return -1;
1005
1006 if (addr && len && ep)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001007 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001008 addr->sa_family = (ep->is_ip4 == VPPCOM_IS_IP4) ? AF_INET : AF_INET6;
1009 switch (addr->sa_family)
1010 {
1011 case AF_INET:
1012 ((struct sockaddr_in *) addr)->sin_port = ep->port;
1013 if (*len > sizeof (struct sockaddr_in))
1014 *len = sizeof (struct sockaddr_in);
1015 sa_len = sizeof (struct sockaddr_in) - sizeof (struct in_addr);
1016 copy_len = *len - sa_len;
1017 if (copy_len > 0)
1018 memcpy (&((struct sockaddr_in *) addr)->sin_addr, ep->ip,
1019 copy_len);
1020 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001021
Dave Wallace048b1d62018-01-03 22:24:41 -05001022 case AF_INET6:
1023 ((struct sockaddr_in6 *) addr)->sin6_port = ep->port;
1024 if (*len > sizeof (struct sockaddr_in6))
1025 *len = sizeof (struct sockaddr_in6);
1026 sa_len = sizeof (struct sockaddr_in6) - sizeof (struct in6_addr);
1027 copy_len = *len - sa_len;
1028 if (copy_len > 0)
1029 memcpy (((struct sockaddr_in6 *) addr)->sin6_addr.
1030 __in6_u.__u6_addr8, ep->ip, copy_len);
1031 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001032
Dave Wallace048b1d62018-01-03 22:24:41 -05001033 default:
1034 /* Not possible */
1035 rv = -EAFNOSUPPORT;
1036 break;
1037 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001038 }
Dave Wallacee695cb42017-11-02 22:04:42 -04001039 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001040}
1041
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001042int
Dave Wallace048b1d62018-01-03 22:24:41 -05001043getsockname (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001044{
Florin Coras7baeb712019-01-04 17:05:43 -08001045 vls_handle_t vlsh;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001046 int rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001047
Dave Wallace2a865272018-02-07 21:00:42 -05001048 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001049 return -1;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001050
Florin Coras7baeb712019-01-04 17:05:43 -08001051 vlsh = ldp_fd_to_vlsh (fd);
1052 if (vlsh != VLS_INVALID_HANDLE)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001053 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001054 vppcom_endpt_t ep;
1055 u8 addr_buf[sizeof (struct in6_addr)];
1056 u32 size = sizeof (ep);
1057
1058 ep.ip = addr_buf;
Dave Wallace048b1d62018-01-03 22:24:41 -05001059
Florin Coras7baeb712019-01-04 17:05:43 -08001060 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_LCL_ADDR, &ep, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -05001061 if (rv != VPPCOM_OK)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001062 {
1063 errno = -rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001064 rv = -1;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001065 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001066 else
1067 {
Dave Wallace2a865272018-02-07 21:00:42 -05001068 rv = ldp_copy_ep_to_sockaddr (addr, len, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001069 if (rv != VPPCOM_OK)
1070 {
1071 errno = -rv;
1072 rv = -1;
1073 }
1074 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001075 }
1076 else
1077 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001078 rv = libc_getsockname (fd, addr, len);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001079 }
1080
Dave Wallace048b1d62018-01-03 22:24:41 -05001081 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001082}
1083
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001084int
Dave Wallace048b1d62018-01-03 22:24:41 -05001085connect (int fd, __CONST_SOCKADDR_ARG addr, socklen_t len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001086{
Florin Coras7baeb712019-01-04 17:05:43 -08001087 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001088 int rv;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001089
Dave Wallace2a865272018-02-07 21:00:42 -05001090 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001091 return -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001092
Dave Wallace048b1d62018-01-03 22:24:41 -05001093 if (!addr)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001094 {
Florin Coras7baeb712019-01-04 17:05:43 -08001095 LDBG (0, "ERROR: fd %d: NULL addr, len %u", fd, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001096 errno = EINVAL;
1097 rv = -1;
1098 goto done;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001099 }
1100
Florin Coras7baeb712019-01-04 17:05:43 -08001101 vlsh = ldp_fd_to_vlsh (fd);
1102 if (vlsh != VLS_INVALID_HANDLE)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001103 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001104 vppcom_endpt_t ep;
1105
Dave Wallace048b1d62018-01-03 22:24:41 -05001106 switch (addr->sa_family)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001107 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001108 case AF_INET:
1109 if (len != sizeof (struct sockaddr_in))
1110 {
Florin Coras7baeb712019-01-04 17:05:43 -08001111 LDBG (0, "fd %d: ERROR vlsh %u: Invalid AF_INET addr len %u!",
1112 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001113 errno = EINVAL;
1114 rv = -1;
1115 goto done;
1116 }
1117 ep.is_ip4 = VPPCOM_IS_IP4;
1118 ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr;
1119 ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port;
1120 break;
1121
1122 case AF_INET6:
1123 if (len != sizeof (struct sockaddr_in6))
1124 {
Florin Coras7baeb712019-01-04 17:05:43 -08001125 LDBG (0, "fd %d: ERROR vlsh %u: Invalid AF_INET6 addr len %u!",
1126 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001127 errno = EINVAL;
1128 rv = -1;
1129 goto done;
1130 }
1131 ep.is_ip4 = VPPCOM_IS_IP6;
1132 ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
1133 ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port;
1134 break;
1135
1136 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001137 LDBG (0, "fd %d: ERROR vlsh %u: Unsupported address family %u!",
1138 fd, vlsh, addr->sa_family);
Dave Wallace048b1d62018-01-03 22:24:41 -05001139 errno = EAFNOSUPPORT;
1140 rv = -1;
1141 goto done;
1142 }
Florin Coras7baeb712019-01-04 17:05:43 -08001143 LDBG (0, "fd %d: calling vls_connect(): vlsh %u addr %p len %u", fd,
1144 vlsh, addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001145
Florin Coras7baeb712019-01-04 17:05:43 -08001146 rv = vls_connect (vlsh, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001147 if (rv != VPPCOM_OK)
1148 {
1149 errno = -rv;
1150 rv = -1;
1151 }
1152 }
1153 else
1154 {
Florin Coras7baeb712019-01-04 17:05:43 -08001155 LDBG (0, "fd %d: calling libc_connect(): addr %p, len %u",
1156 fd, addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001157
1158 rv = libc_connect (fd, addr, len);
1159 }
1160
1161done:
Florin Coras7baeb712019-01-04 17:05:43 -08001162 LDBG (1, "fd %d: returning %d (0x%x)", fd, rv, rv);
Dave Wallace048b1d62018-01-03 22:24:41 -05001163 return rv;
1164}
1165
1166int
1167getpeername (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict len)
1168{
Florin Coras7baeb712019-01-04 17:05:43 -08001169 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001170 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001171
Dave Wallace2a865272018-02-07 21:00:42 -05001172 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001173 return -1;
1174
Florin Coras7baeb712019-01-04 17:05:43 -08001175 vlsh = ldp_fd_to_vlsh (fd);
1176 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001177 {
1178 vppcom_endpt_t ep;
1179 u8 addr_buf[sizeof (struct in6_addr)];
1180 u32 size = sizeof (ep);
1181
1182 ep.ip = addr_buf;
Florin Coras7baeb712019-01-04 17:05:43 -08001183 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_PEER_ADDR, &ep, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -05001184 if (rv != VPPCOM_OK)
1185 {
1186 errno = -rv;
1187 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001188 }
1189 else
1190 {
Dave Wallace2a865272018-02-07 21:00:42 -05001191 rv = ldp_copy_ep_to_sockaddr (addr, len, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001192 if (rv != VPPCOM_OK)
1193 {
1194 errno = -rv;
1195 rv = -1;
1196 }
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001197 }
1198 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001199 else
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001200 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001201 rv = libc_getpeername (fd, addr, len);
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001202 }
1203
Dave Wallace048b1d62018-01-03 22:24:41 -05001204 return rv;
1205}
1206
1207ssize_t
1208send (int fd, const void *buf, size_t n, int flags)
1209{
Florin Coras7baeb712019-01-04 17:05:43 -08001210 vls_handle_t vlsh = ldp_fd_to_vlsh (fd);
Dave Wallace048b1d62018-01-03 22:24:41 -05001211 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001212
Dave Wallace2a865272018-02-07 21:00:42 -05001213 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001214 return -1;
1215
Florin Coras7baeb712019-01-04 17:05:43 -08001216 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001217 {
Florin Coras7baeb712019-01-04 17:05:43 -08001218 size = vls_sendto (vlsh, (void *) buf, n, flags, NULL);
qchangaa8f63c2018-05-30 11:44:18 -07001219 if (size < VPPCOM_OK)
Dave Wallace048b1d62018-01-03 22:24:41 -05001220 {
1221 errno = -size;
1222 size = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001223 }
1224 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001225 else
1226 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001227 size = libc_send (fd, buf, n, flags);
1228 }
1229
Dave Wallace048b1d62018-01-03 22:24:41 -05001230 return size;
1231}
1232
1233ssize_t
1234sendfile (int out_fd, int in_fd, off_t * offset, size_t len)
1235{
Florin Corasdfe4cf42018-11-28 22:13:45 -08001236 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras7baeb712019-01-04 17:05:43 -08001237 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001238 ssize_t size = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -05001239
Dave Wallace2a865272018-02-07 21:00:42 -05001240 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001241 return -1;
1242
Florin Coras7baeb712019-01-04 17:05:43 -08001243 vlsh = ldp_fd_to_vlsh (out_fd);
1244 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001245 {
1246 int rv;
1247 ssize_t results = 0;
1248 size_t n_bytes_left = len;
1249 size_t bytes_to_read;
1250 int nbytes;
Dave Wallace048b1d62018-01-03 22:24:41 -05001251 u8 eagain = 0;
1252 u32 flags, flags_len = sizeof (flags);
1253
Florin Coras7baeb712019-01-04 17:05:43 -08001254 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_FLAGS, &flags, &flags_len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001255 if (PREDICT_FALSE (rv != VPPCOM_OK))
1256 {
Florin Coras7baeb712019-01-04 17:05:43 -08001257 LDBG (0, "ERROR: out fd %d: vls_attr: vlsh %u, returned %d (%s)!",
1258 out_fd, vlsh, rv, vppcom_retval_str (rv));
Dave Wallace048b1d62018-01-03 22:24:41 -05001259
Florin Corasdfe4cf42018-11-28 22:13:45 -08001260 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001261 errno = -rv;
1262 size = -1;
1263 goto done;
1264 }
1265
1266 if (offset)
1267 {
1268 off_t off = lseek (in_fd, *offset, SEEK_SET);
1269 if (PREDICT_FALSE (off == -1))
1270 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001271 size = -1;
1272 goto done;
1273 }
1274
1275 ASSERT (off == *offset);
1276 }
1277
1278 do
1279 {
Florin Coras7baeb712019-01-04 17:05:43 -08001280 size = vls_attr (vlsh, VPPCOM_ATTR_GET_NWRITE, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05001281 if (size < 0)
1282 {
Florin Coras7baeb712019-01-04 17:05:43 -08001283 LDBG (0, "ERROR: fd %d: vls_attr: vlsh %u returned %d (%s)!",
1284 out_fd, vlsh, size, vppcom_retval_str (size));
Florin Corasdfe4cf42018-11-28 22:13:45 -08001285 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001286 errno = -size;
1287 size = -1;
1288 goto done;
1289 }
1290
1291 bytes_to_read = size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001292 if (bytes_to_read == 0)
1293 {
1294 if (flags & O_NONBLOCK)
1295 {
1296 if (!results)
Florin Coras7baeb712019-01-04 17:05:43 -08001297 eagain = 1;
Dave Wallace048b1d62018-01-03 22:24:41 -05001298 goto update_offset;
1299 }
1300 else
1301 continue;
1302 }
1303 bytes_to_read = clib_min (n_bytes_left, bytes_to_read);
Florin Corasdfe4cf42018-11-28 22:13:45 -08001304 vec_validate (ldpw->io_buffer, bytes_to_read);
1305 nbytes = libc_read (in_fd, ldpw->io_buffer, bytes_to_read);
Dave Wallace048b1d62018-01-03 22:24:41 -05001306 if (nbytes < 0)
1307 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001308 if (results == 0)
1309 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08001310 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001311 size = -1;
1312 goto done;
1313 }
1314 goto update_offset;
1315 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001316
Florin Coras7baeb712019-01-04 17:05:43 -08001317 size = vls_write (vlsh, ldpw->io_buffer, nbytes);
Dave Wallace048b1d62018-01-03 22:24:41 -05001318 if (size < 0)
1319 {
1320 if (size == VPPCOM_EAGAIN)
1321 {
1322 if (flags & O_NONBLOCK)
1323 {
1324 if (!results)
Florin Coras7baeb712019-01-04 17:05:43 -08001325 eagain = 1;
Dave Wallace048b1d62018-01-03 22:24:41 -05001326 goto update_offset;
1327 }
1328 else
1329 continue;
1330 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001331 if (results == 0)
1332 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08001333 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001334 errno = -size;
1335 size = -1;
1336 goto done;
1337 }
1338 goto update_offset;
1339 }
1340
1341 results += nbytes;
1342 ASSERT (n_bytes_left >= nbytes);
1343 n_bytes_left = n_bytes_left - nbytes;
1344 }
1345 while (n_bytes_left > 0);
1346
1347 update_offset:
Florin Corasdfe4cf42018-11-28 22:13:45 -08001348 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001349 if (offset)
1350 {
1351 off_t off = lseek (in_fd, *offset, SEEK_SET);
1352 if (PREDICT_FALSE (off == -1))
1353 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001354 size = -1;
1355 goto done;
1356 }
1357
1358 ASSERT (off == *offset);
1359 *offset += results + 1;
1360 }
1361 if (eagain)
1362 {
1363 errno = EAGAIN;
1364 size = -1;
1365 }
1366 else
1367 size = results;
1368 }
1369 else
1370 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001371 size = libc_sendfile (out_fd, in_fd, offset, len);
1372 }
1373
1374done:
Dave Wallace048b1d62018-01-03 22:24:41 -05001375 return size;
1376}
1377
1378ssize_t
1379sendfile64 (int out_fd, int in_fd, off_t * offset, size_t len)
1380{
1381 return sendfile (out_fd, in_fd, offset, len);
1382}
1383
1384ssize_t
1385recv (int fd, void *buf, size_t n, int flags)
1386{
Florin Coras7baeb712019-01-04 17:05:43 -08001387 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001388 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001389
Dave Wallace2a865272018-02-07 21:00:42 -05001390 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001391 return -1;
1392
Florin Coras7baeb712019-01-04 17:05:43 -08001393 vlsh = ldp_fd_to_vlsh (fd);
1394 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001395 {
Florin Coras7baeb712019-01-04 17:05:43 -08001396 size = vls_recvfrom (vlsh, buf, n, flags, NULL);
Dave Wallace048b1d62018-01-03 22:24:41 -05001397 if (size < 0)
Florin Corasa7a1a222018-12-30 17:11:31 -08001398 errno = -size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001399 }
1400 else
1401 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001402 size = libc_recv (fd, buf, n, flags);
1403 }
1404
Dave Wallace048b1d62018-01-03 22:24:41 -05001405 return size;
1406}
1407
1408ssize_t
1409sendto (int fd, const void *buf, size_t n, int flags,
1410 __CONST_SOCKADDR_ARG addr, socklen_t addr_len)
1411{
Florin Coras7baeb712019-01-04 17:05:43 -08001412 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001413 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001414
Dave Wallace2a865272018-02-07 21:00:42 -05001415 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001416 return -1;
1417
Florin Coras7baeb712019-01-04 17:05:43 -08001418 vlsh = ldp_fd_to_vlsh (fd);
1419 if (vlsh != INVALID_SESSION_ID)
Dave Wallace048b1d62018-01-03 22:24:41 -05001420 {
1421 vppcom_endpt_t *ep = 0;
1422 vppcom_endpt_t _ep;
1423
1424 if (addr)
1425 {
1426 ep = &_ep;
Dave Wallace048b1d62018-01-03 22:24:41 -05001427 switch (addr->sa_family)
1428 {
1429 case AF_INET:
1430 ep->is_ip4 = VPPCOM_IS_IP4;
1431 ep->ip =
1432 (uint8_t *) & ((const struct sockaddr_in *) addr)->sin_addr;
1433 ep->port =
1434 (uint16_t) ((const struct sockaddr_in *) addr)->sin_port;
1435 break;
1436
1437 case AF_INET6:
1438 ep->is_ip4 = VPPCOM_IS_IP6;
1439 ep->ip =
1440 (uint8_t *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
1441 ep->port =
1442 (uint16_t) ((const struct sockaddr_in6 *) addr)->sin6_port;
1443 break;
1444
1445 default:
1446 errno = EAFNOSUPPORT;
1447 size = -1;
1448 goto done;
1449 }
1450 }
1451
Florin Coras7baeb712019-01-04 17:05:43 -08001452 size = vls_sendto (vlsh, (void *) buf, n, flags, ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001453 if (size < 0)
1454 {
1455 errno = -size;
1456 size = -1;
1457 }
1458 }
1459 else
1460 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001461 size = libc_sendto (fd, buf, n, flags, addr, addr_len);
1462 }
1463
1464done:
Dave Wallace048b1d62018-01-03 22:24:41 -05001465 return size;
1466}
1467
1468ssize_t
1469recvfrom (int fd, void *__restrict buf, size_t n, int flags,
1470 __SOCKADDR_ARG addr, socklen_t * __restrict addr_len)
1471{
Florin Coras7baeb712019-01-04 17:05:43 -08001472 vls_handle_t sid;
Dave Wallace048b1d62018-01-03 22:24:41 -05001473 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001474
Dave Wallace2a865272018-02-07 21:00:42 -05001475 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001476 return -1;
1477
Florin Coras7baeb712019-01-04 17:05:43 -08001478 sid = ldp_fd_to_vlsh (fd);
1479 if (sid != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001480 {
1481 vppcom_endpt_t ep;
1482 u8 src_addr[sizeof (struct sockaddr_in6)];
1483
Dave Wallace048b1d62018-01-03 22:24:41 -05001484 if (addr)
1485 {
1486 ep.ip = src_addr;
Florin Coras7baeb712019-01-04 17:05:43 -08001487 size = vls_recvfrom (sid, buf, n, flags, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001488
1489 if (size > 0)
Dave Wallace2a865272018-02-07 21:00:42 -05001490 size = ldp_copy_ep_to_sockaddr (addr, addr_len, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001491 }
1492 else
Florin Coras7baeb712019-01-04 17:05:43 -08001493 size = vls_recvfrom (sid, buf, n, flags, NULL);
Dave Wallace048b1d62018-01-03 22:24:41 -05001494
1495 if (size < 0)
1496 {
1497 errno = -size;
1498 size = -1;
1499 }
1500 }
1501 else
1502 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001503 size = libc_recvfrom (fd, buf, n, flags, addr, addr_len);
1504 }
1505
Dave Wallace048b1d62018-01-03 22:24:41 -05001506 return size;
1507}
1508
1509ssize_t
1510sendmsg (int fd, const struct msghdr * message, int flags)
1511{
Florin Coras7baeb712019-01-04 17:05:43 -08001512 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001513 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001514
Dave Wallace2a865272018-02-07 21:00:42 -05001515 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001516 return -1;
1517
Florin Coras7baeb712019-01-04 17:05:43 -08001518 vlsh = ldp_fd_to_vlsh (fd);
1519 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001520 {
Florin Coras7baeb712019-01-04 17:05:43 -08001521 LDBG (0, "LDP-TBD");
Dave Wallace048b1d62018-01-03 22:24:41 -05001522 errno = ENOSYS;
1523 size = -1;
1524 }
1525 else
1526 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001527 size = libc_sendmsg (fd, message, flags);
1528 }
1529
Dave Wallace048b1d62018-01-03 22:24:41 -05001530 return size;
1531}
1532
1533#ifdef USE_GNU
1534int
1535sendmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags)
1536{
1537 ssize_t size;
1538 const char *func_str;
Florin Coras7baeb712019-01-04 17:05:43 -08001539 u32 sh = ldp_fd_to_vlsh (fd);
Dave Wallace048b1d62018-01-03 22:24:41 -05001540
Dave Wallace2a865272018-02-07 21:00:42 -05001541 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001542 return -1;
1543
Florin Coras7baeb712019-01-04 17:05:43 -08001544 if (sh != INVALID_SESSION_ID)
Dave Wallace048b1d62018-01-03 22:24:41 -05001545 {
1546 clib_warning ("LDP<%d>: LDP-TBD", getpid ());
1547 errno = ENOSYS;
1548 size = -1;
1549 }
1550 else
1551 {
1552 func_str = "libc_sendmmsg";
1553
Dave Wallace2a865272018-02-07 21:00:42 -05001554 if (LDP_DEBUG > 2)
Dave Wallace048b1d62018-01-03 22:24:41 -05001555 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1556 "vmessages %p, vlen %u, flags 0x%x",
1557 getpid (), fd, fd, func_str, vmessages, vlen, flags);
1558
1559 size = libc_sendmmsg (fd, vmessages, vlen, flags);
1560 }
1561
Dave Wallace2a865272018-02-07 21:00:42 -05001562 if (LDP_DEBUG > 2)
Dave Wallace048b1d62018-01-03 22:24:41 -05001563 {
1564 if (size < 0)
1565 {
1566 int errno_val = errno;
1567 perror (func_str);
1568 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1569 "rv %d, errno = %d", getpid (), fd, fd,
1570 func_str, size, errno_val);
1571 errno = errno_val;
1572 }
1573 else
1574 clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1575 getpid (), fd, fd, size, size);
1576 }
1577 return size;
1578}
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001579#endif
1580
Dave Wallace048b1d62018-01-03 22:24:41 -05001581ssize_t
1582recvmsg (int fd, struct msghdr * message, int flags)
1583{
Florin Coras7baeb712019-01-04 17:05:43 -08001584 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001585 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001586
Dave Wallace2a865272018-02-07 21:00:42 -05001587 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001588 return -1;
1589
Florin Coras7baeb712019-01-04 17:05:43 -08001590 vlsh = ldp_fd_to_vlsh (fd);
1591 if (vlsh != VLS_INVALID_HANDLE)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001592 {
Florin Coras7baeb712019-01-04 17:05:43 -08001593 LDBG (0, "LDP-TBD");
Dave Wallace048b1d62018-01-03 22:24:41 -05001594 errno = ENOSYS;
1595 size = -1;
1596 }
1597 else
1598 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001599 size = libc_recvmsg (fd, message, flags);
1600 }
1601
Dave Wallace048b1d62018-01-03 22:24:41 -05001602 return size;
1603}
1604
1605#ifdef USE_GNU
1606int
1607recvmmsg (int fd, struct mmsghdr *vmessages,
1608 unsigned int vlen, int flags, struct timespec *tmo)
1609{
1610 ssize_t size;
1611 const char *func_str;
Florin Coras7baeb712019-01-04 17:05:43 -08001612 u32 sh = ldp_fd_to_vlsh (fd);
Dave Wallace048b1d62018-01-03 22:24:41 -05001613
Dave Wallace2a865272018-02-07 21:00:42 -05001614 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001615 return -1;
1616
Florin Coras7baeb712019-01-04 17:05:43 -08001617 if (sh != INVALID_SESSION_ID)
Dave Wallace048b1d62018-01-03 22:24:41 -05001618 {
1619 clib_warning ("LDP<%d>: LDP-TBD", getpid ());
1620 errno = ENOSYS;
1621 size = -1;
1622 }
1623 else
1624 {
1625 func_str = "libc_recvmmsg";
1626
Dave Wallace2a865272018-02-07 21:00:42 -05001627 if (LDP_DEBUG > 2)
Dave Wallace048b1d62018-01-03 22:24:41 -05001628 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1629 "vmessages %p, vlen %u, flags 0x%x, tmo %p",
1630 getpid (), fd, fd, func_str, vmessages, vlen,
1631 flags, tmo);
1632
1633 size = libc_recvmmsg (fd, vmessages, vlen, flags, tmo);
1634 }
1635
Dave Wallace2a865272018-02-07 21:00:42 -05001636 if (LDP_DEBUG > 2)
Dave Wallace048b1d62018-01-03 22:24:41 -05001637 {
1638 if (size < 0)
1639 {
1640 int errno_val = errno;
1641 perror (func_str);
1642 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1643 "rv %d, errno = %d", getpid (), fd, fd,
1644 func_str, size, errno_val);
1645 errno = errno_val;
1646 }
1647 else
1648 clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1649 getpid (), fd, fd, size, size);
1650 }
1651 return size;
1652}
1653#endif
1654
1655int
1656getsockopt (int fd, int level, int optname,
1657 void *__restrict optval, socklen_t * __restrict optlen)
1658{
Florin Coras7baeb712019-01-04 17:05:43 -08001659 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001660 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001661
Dave Wallace2a865272018-02-07 21:00:42 -05001662 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001663 return -1;
1664
Florin Coras7baeb712019-01-04 17:05:43 -08001665 vlsh = ldp_fd_to_vlsh (fd);
1666 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001667 {
1668 rv = -EOPNOTSUPP;
1669
1670 switch (level)
1671 {
1672 case SOL_TCP:
1673 switch (optname)
1674 {
1675 case TCP_NODELAY:
Florin Coras7baeb712019-01-04 17:05:43 -08001676 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_NODELAY,
1677 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001678 break;
1679 case TCP_MAXSEG:
Florin Coras7baeb712019-01-04 17:05:43 -08001680 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_USER_MSS,
1681 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001682 break;
1683 case TCP_KEEPIDLE:
Florin Coras7baeb712019-01-04 17:05:43 -08001684 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_KEEPIDLE,
1685 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001686 break;
1687 case TCP_KEEPINTVL:
Florin Coras7baeb712019-01-04 17:05:43 -08001688 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_KEEPINTVL,
1689 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001690 break;
1691 case TCP_INFO:
1692 if (optval && optlen && (*optlen == sizeof (struct tcp_info)))
1693 {
Florin Coras7baeb712019-01-04 17:05:43 -08001694 LDBG (1, "fd %d: vlsh %u SOL_TCP, TCP_INFO, optval %p, "
1695 "optlen %d: #LDP-NOP#", fd, vlsh, optval, *optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001696 memset (optval, 0, *optlen);
1697 rv = VPPCOM_OK;
1698 }
1699 else
1700 rv = -EFAULT;
1701 break;
Florin Coras0ed24e92019-01-21 09:03:10 -08001702 case TCP_CONGESTION:
1703 strcpy (optval, "cubic");
1704 *optlen = strlen ("cubic");
1705 rv = 0;
1706 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05001707 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001708 LDBG (0, "ERROR: fd %d: getsockopt SOL_TCP: sid %u, "
1709 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05001710 break;
1711 }
1712 break;
1713 case SOL_IPV6:
1714 switch (optname)
1715 {
1716 case IPV6_V6ONLY:
Florin Coras7baeb712019-01-04 17:05:43 -08001717 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_V6ONLY, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001718 break;
1719 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001720 LDBG (0, "ERROR: fd %d: getsockopt SOL_IPV6: vlsh %u "
1721 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05001722 break;
1723 }
1724 break;
1725 case SOL_SOCKET:
1726 switch (optname)
1727 {
1728 case SO_ACCEPTCONN:
Florin Coras7baeb712019-01-04 17:05:43 -08001729 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_LISTEN, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001730 break;
1731 case SO_KEEPALIVE:
Florin Coras7baeb712019-01-04 17:05:43 -08001732 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_KEEPALIVE, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001733 break;
1734 case SO_PROTOCOL:
Florin Coras7baeb712019-01-04 17:05:43 -08001735 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_PROTOCOL, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001736 *(int *) optval = *(int *) optval ? SOCK_DGRAM : SOCK_STREAM;
1737 break;
1738 case SO_SNDBUF:
Florin Coras7baeb712019-01-04 17:05:43 -08001739 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TX_FIFO_LEN,
1740 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001741 break;
1742 case SO_RCVBUF:
Florin Coras7baeb712019-01-04 17:05:43 -08001743 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_RX_FIFO_LEN,
1744 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001745 break;
1746 case SO_REUSEADDR:
Florin Coras7baeb712019-01-04 17:05:43 -08001747 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_REUSEADDR, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001748 break;
1749 case SO_BROADCAST:
Florin Coras7baeb712019-01-04 17:05:43 -08001750 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_BROADCAST, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001751 break;
1752 case SO_ERROR:
Florin Coras7baeb712019-01-04 17:05:43 -08001753 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_ERROR, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001754 break;
1755 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001756 LDBG (0, "ERROR: fd %d: getsockopt SOL_SOCKET: vlsh %u "
1757 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05001758 break;
1759 }
1760 break;
1761 default:
1762 break;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001763 }
1764
Dave Wallace048b1d62018-01-03 22:24:41 -05001765 if (rv != VPPCOM_OK)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001766 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001767 errno = -rv;
1768 rv = -1;
1769 }
1770 }
1771 else
1772 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001773 rv = libc_getsockopt (fd, level, optname, optval, optlen);
1774 }
1775
Dave Wallace048b1d62018-01-03 22:24:41 -05001776 return rv;
1777}
1778
1779int
1780setsockopt (int fd, int level, int optname,
1781 const void *optval, socklen_t optlen)
1782{
Florin Coras7baeb712019-01-04 17:05:43 -08001783 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001784 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001785
Dave Wallace2a865272018-02-07 21:00:42 -05001786 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001787 return -1;
1788
Florin Coras7baeb712019-01-04 17:05:43 -08001789 vlsh = ldp_fd_to_vlsh (fd);
1790 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001791 {
1792 rv = -EOPNOTSUPP;
1793
1794 switch (level)
1795 {
1796 case SOL_TCP:
1797 switch (optname)
1798 {
1799 case TCP_NODELAY:
Florin Coras7baeb712019-01-04 17:05:43 -08001800 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_NODELAY,
1801 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001802 break;
1803 case TCP_MAXSEG:
Florin Coras7baeb712019-01-04 17:05:43 -08001804 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_USER_MSS,
1805 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001806 break;
1807 case TCP_KEEPIDLE:
Florin Coras7baeb712019-01-04 17:05:43 -08001808 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_KEEPIDLE,
1809 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001810 break;
1811 case TCP_KEEPINTVL:
Florin Coras7baeb712019-01-04 17:05:43 -08001812 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_KEEPINTVL,
1813 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001814 break;
Florin Coras0ed24e92019-01-21 09:03:10 -08001815 case TCP_CONGESTION:
1816 /* Ignore */
1817 rv = 0;
1818 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05001819 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001820 LDBG (0, "ERROR: fd %d: setsockopt() SOL_TCP: vlsh %u"
1821 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05001822 break;
1823 }
1824 break;
1825 case SOL_IPV6:
1826 switch (optname)
1827 {
1828 case IPV6_V6ONLY:
Florin Coras7baeb712019-01-04 17:05:43 -08001829 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_V6ONLY,
1830 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001831 break;
1832 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001833 LDBG (0, "ERROR: fd %d: setsockopt SOL_IPV6: vlsh %u"
1834 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05001835 break;
1836 }
1837 break;
1838 case SOL_SOCKET:
1839 switch (optname)
1840 {
1841 case SO_KEEPALIVE:
Florin Coras7baeb712019-01-04 17:05:43 -08001842 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_KEEPALIVE,
1843 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001844 break;
1845 case SO_REUSEADDR:
Florin Coras7baeb712019-01-04 17:05:43 -08001846 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_REUSEADDR,
1847 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001848 break;
1849 case SO_BROADCAST:
Florin Coras7baeb712019-01-04 17:05:43 -08001850 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_BROADCAST,
1851 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05001852 break;
1853 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001854 LDBG (0, "ERROR: fd %d: setsockopt SOL_SOCKET: vlsh %u "
1855 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05001856 break;
1857 }
1858 break;
1859 default:
1860 break;
1861 }
1862
1863 if (rv != VPPCOM_OK)
1864 {
1865 errno = -rv;
1866 rv = -1;
1867 }
1868 }
1869 else
1870 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001871 rv = libc_setsockopt (fd, level, optname, optval, optlen);
1872 }
1873
Dave Wallace048b1d62018-01-03 22:24:41 -05001874 return rv;
1875}
1876
1877int
1878listen (int fd, int n)
1879{
Florin Coras7baeb712019-01-04 17:05:43 -08001880 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001881 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001882
Dave Wallace2a865272018-02-07 21:00:42 -05001883 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001884 return -1;
1885
Florin Coras7baeb712019-01-04 17:05:43 -08001886 vlsh = ldp_fd_to_vlsh (fd);
1887 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001888 {
Florin Coras7baeb712019-01-04 17:05:43 -08001889 LDBG (0, "fd %d: calling vls_listen: vlsh %u, n %d", fd, vlsh, n);
Dave Wallace048b1d62018-01-03 22:24:41 -05001890
Florin Coras7baeb712019-01-04 17:05:43 -08001891 rv = vls_listen (vlsh, n);
Dave Wallace048b1d62018-01-03 22:24:41 -05001892 if (rv != VPPCOM_OK)
1893 {
1894 errno = -rv;
1895 rv = -1;
1896 }
1897 }
1898 else
1899 {
Florin Coras7baeb712019-01-04 17:05:43 -08001900 LDBG (0, "fd %d: calling libc_listen(): n %d", fd, n);
Dave Wallace048b1d62018-01-03 22:24:41 -05001901 rv = libc_listen (fd, n);
1902 }
1903
Florin Coras7baeb712019-01-04 17:05:43 -08001904 LDBG (1, "fd %d: returning %d", fd, rv);
Dave Wallace048b1d62018-01-03 22:24:41 -05001905 return rv;
1906}
1907
1908static inline int
Dave Wallace2a865272018-02-07 21:00:42 -05001909ldp_accept4 (int listen_fd, __SOCKADDR_ARG addr,
1910 socklen_t * __restrict addr_len, int flags)
Dave Wallace048b1d62018-01-03 22:24:41 -05001911{
Florin Coras7baeb712019-01-04 17:05:43 -08001912 vls_handle_t listen_vlsh, accept_vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001913 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001914
Dave Wallace2a865272018-02-07 21:00:42 -05001915 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001916 return -1;
1917
Florin Coras7baeb712019-01-04 17:05:43 -08001918 listen_vlsh = ldp_fd_to_vlsh (listen_fd);
1919 if (listen_vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001920 {
1921 vppcom_endpt_t ep;
1922 u8 src_addr[sizeof (struct sockaddr_in6)];
Dave Wallace8aaba562018-01-18 17:21:19 -05001923 memset (&ep, 0, sizeof (ep));
Dave Wallace048b1d62018-01-03 22:24:41 -05001924 ep.ip = src_addr;
1925
Florin Coras7baeb712019-01-04 17:05:43 -08001926 LDBG (0, "listen fd %d: calling vppcom_session_accept: listen sid %u,"
1927 " ep %p, flags 0x%x", listen_fd, listen_vlsh, ep, flags);
Dave Wallace048b1d62018-01-03 22:24:41 -05001928
Florin Coras7baeb712019-01-04 17:05:43 -08001929 accept_vlsh = vls_accept (listen_vlsh, &ep, flags);
1930 if (accept_vlsh < 0)
Dave Wallace048b1d62018-01-03 22:24:41 -05001931 {
Florin Coras7baeb712019-01-04 17:05:43 -08001932 errno = -accept_vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001933 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001934 }
1935 else
1936 {
Dave Wallace2a865272018-02-07 21:00:42 -05001937 rv = ldp_copy_ep_to_sockaddr (addr, addr_len, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001938 if (rv != VPPCOM_OK)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001939 {
Florin Coras7baeb712019-01-04 17:05:43 -08001940 (void) vls_close (accept_vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05001941 errno = -rv;
1942 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001943 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001944 else
1945 {
Florin Coras7baeb712019-01-04 17:05:43 -08001946 rv = ldp_vlsh_to_fd (accept_vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05001947 }
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001948 }
1949 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001950 else
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001951 {
Florin Coras7baeb712019-01-04 17:05:43 -08001952 LDBG (0, "listen fd %d: calling libc_accept4(): addr %p, addr_len %p,"
1953 " flags 0x%x", listen_fd, addr, addr_len, flags);
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001954
Dave Wallace048b1d62018-01-03 22:24:41 -05001955 rv = libc_accept4 (listen_fd, addr, addr_len, flags);
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001956 }
1957
Florin Coras7baeb712019-01-04 17:05:43 -08001958 LDBG (1, "listen fd %d: accept returning %d", listen_fd, rv);
Florin Coras05ecfcc2018-12-12 18:19:39 -08001959
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001960 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001961}
1962
Dave Wallace048b1d62018-01-03 22:24:41 -05001963int
1964accept4 (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len,
1965 int flags)
1966{
Dave Wallace2a865272018-02-07 21:00:42 -05001967 return ldp_accept4 (fd, addr, addr_len, flags);
Dave Wallace048b1d62018-01-03 22:24:41 -05001968}
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001969
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001970int
Dave Wallace048b1d62018-01-03 22:24:41 -05001971accept (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001972{
Dave Wallace2a865272018-02-07 21:00:42 -05001973 return ldp_accept4 (fd, addr, addr_len, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05001974}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001975
Dave Wallace048b1d62018-01-03 22:24:41 -05001976int
1977shutdown (int fd, int how)
1978{
Florin Coras7baeb712019-01-04 17:05:43 -08001979 vls_handle_t vlsh;
1980 int rv = 0, flags;
1981 u32 flags_len = sizeof (flags);
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001982
Dave Wallace2a865272018-02-07 21:00:42 -05001983 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05001984 return -1;
1985
Florin Coras7baeb712019-01-04 17:05:43 -08001986 vlsh = ldp_fd_to_vlsh (fd);
1987 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001988 {
Florin Coras7baeb712019-01-04 17:05:43 -08001989 LDBG (0, "called shutdown: fd %u vlsh %u how %d", fd, vlsh, how);
Florin Corasa7a1a222018-12-30 17:11:31 -08001990
Florin Coras7baeb712019-01-04 17:05:43 -08001991 if (vls_attr (vlsh, VPPCOM_ATTR_SET_SHUT, &how, &flags_len))
Florin Corasa7a1a222018-12-30 17:11:31 -08001992 {
Florin Coras7baeb712019-01-04 17:05:43 -08001993 close (fd);
Florin Corasa7a1a222018-12-30 17:11:31 -08001994 return -1;
1995 }
1996
Florin Coras7baeb712019-01-04 17:05:43 -08001997 if (vls_attr (vlsh, VPPCOM_ATTR_GET_SHUT, &flags, &flags_len))
1998 {
1999 close (fd);
2000 return -1;
2001 }
Florin Corasa7a1a222018-12-30 17:11:31 -08002002
Florin Coras7baeb712019-01-04 17:05:43 -08002003 if (flags == SHUT_RDWR)
Florin Corasa7a1a222018-12-30 17:11:31 -08002004 rv = close (fd);
Dave Wallace048b1d62018-01-03 22:24:41 -05002005 }
2006 else
2007 {
Florin Coras7baeb712019-01-04 17:05:43 -08002008 LDBG (0, "fd %d: calling libc_shutdown: how %d", fd, how);
Dave Wallace048b1d62018-01-03 22:24:41 -05002009 rv = libc_shutdown (fd, how);
2010 }
2011
Dave Wallace048b1d62018-01-03 22:24:41 -05002012 return rv;
2013}
2014
2015int
2016epoll_create1 (int flags)
2017{
Florin Corasdfe4cf42018-11-28 22:13:45 -08002018 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras7baeb712019-01-04 17:05:43 -08002019 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002020 int rv;
2021
Dave Wallace2a865272018-02-07 21:00:42 -05002022 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05002023 return -1;
2024
Florin Coras99368312018-08-02 10:45:44 -07002025 if (ldp->vcl_needs_real_epoll)
2026 {
2027 rv = libc_epoll_create1 (flags);
2028 ldp->vcl_needs_real_epoll = 0;
Florin Corasdfe4cf42018-11-28 22:13:45 -08002029 ldpw->vcl_mq_epfd = rv;
Florin Coras05ecfcc2018-12-12 18:19:39 -08002030 LDBG (0, "created vcl epfd %u", rv);
Florin Coras99368312018-08-02 10:45:44 -07002031 return rv;
2032 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002033
Florin Coras7baeb712019-01-04 17:05:43 -08002034 vlsh = vls_epoll_create ();
2035 if (PREDICT_FALSE (vlsh == VLS_INVALID_HANDLE))
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002036 {
Florin Coras7baeb712019-01-04 17:05:43 -08002037 errno = -vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002038 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002039 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002040 else
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002041 {
Florin Coras7baeb712019-01-04 17:05:43 -08002042 rv = ldp_vlsh_to_fd (vlsh);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002043 }
Florin Coras7baeb712019-01-04 17:05:43 -08002044 LDBG (0, "epoll_create epfd %u vlsh %u", rv, vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05002045 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002046}
2047
2048int
Dave Wallace048b1d62018-01-03 22:24:41 -05002049epoll_create (int size)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002050{
Dave Wallace048b1d62018-01-03 22:24:41 -05002051 return epoll_create1 (0);
2052}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002053
Dave Wallace048b1d62018-01-03 22:24:41 -05002054int
2055epoll_ctl (int epfd, int op, int fd, struct epoll_event *event)
2056{
Florin Coras7baeb712019-01-04 17:05:43 -08002057 vls_handle_t vep_vlsh, vlsh;
Florin Coras99368312018-08-02 10:45:44 -07002058 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05002059
Dave Wallace2a865272018-02-07 21:00:42 -05002060 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05002061 return -1;
2062
Florin Coras7baeb712019-01-04 17:05:43 -08002063 vep_vlsh = ldp_fd_to_vlsh (epfd);
2064 if (PREDICT_FALSE (vep_vlsh == VLS_INVALID_HANDLE))
Dave Wallace048b1d62018-01-03 22:24:41 -05002065 {
Dave Wallace3ee1fe12018-02-23 01:09:11 -05002066 /* The LDP epoll_create1 always creates VCL epfd's.
2067 * The app should never have a kernel base epoll fd unless it
2068 * was acquired outside of the LD_PRELOAD process context.
2069 * In any case, if we get one, punt it to libc_epoll_ctl.
2070 */
Florin Coras7baeb712019-01-04 17:05:43 -08002071 LDBG (1, "epfd %d: calling libc_epoll_ctl: op %d, fd %d"
2072 " event %p", epfd, op, fd, event);
Dave Wallace048b1d62018-01-03 22:24:41 -05002073
2074 rv = libc_epoll_ctl (epfd, op, fd, event);
Florin Coras99368312018-08-02 10:45:44 -07002075 goto done;
2076 }
2077
Florin Coras7baeb712019-01-04 17:05:43 -08002078 vlsh = ldp_fd_to_vlsh (fd);
Florin Coras99368312018-08-02 10:45:44 -07002079
Florin Coras7baeb712019-01-04 17:05:43 -08002080 LDBG (0, "epfd %d ep_vlsh %d, fd %u vlsh %d, op %u", epfd, vep_vlsh, fd,
2081 vlsh, op);
Florin Coras99368312018-08-02 10:45:44 -07002082
Florin Coras7baeb712019-01-04 17:05:43 -08002083 if (vlsh != VLS_INVALID_HANDLE)
Florin Coras99368312018-08-02 10:45:44 -07002084 {
Florin Coras7baeb712019-01-04 17:05:43 -08002085 LDBG (1, "epfd %d: calling vls_epoll_ctl: ep_vlsh %d op %d, vlsh %u,"
2086 " event %p", epfd, vep_vlsh, vlsh, event);
Florin Coras99368312018-08-02 10:45:44 -07002087
Florin Coras7baeb712019-01-04 17:05:43 -08002088 rv = vls_epoll_ctl (vep_vlsh, op, vlsh, event);
Florin Coras99368312018-08-02 10:45:44 -07002089 if (rv != VPPCOM_OK)
2090 {
2091 errno = -rv;
2092 rv = -1;
2093 }
2094 }
2095 else
2096 {
2097 int libc_epfd;
2098 u32 size = sizeof (epfd);
2099
Florin Coras7baeb712019-01-04 17:05:43 -08002100 libc_epfd = vls_attr (vep_vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
Florin Coras99368312018-08-02 10:45:44 -07002101 if (!libc_epfd)
2102 {
Florin Coras7baeb712019-01-04 17:05:43 -08002103 LDBG (1, "epfd %d, vep_vlsh %d calling libc_epoll_create1: "
2104 "EPOLL_CLOEXEC", epfd, vep_vlsh);
Florin Coras99368312018-08-02 10:45:44 -07002105
2106 libc_epfd = libc_epoll_create1 (EPOLL_CLOEXEC);
2107 if (libc_epfd < 0)
2108 {
2109 rv = libc_epfd;
2110 goto done;
2111 }
2112
Florin Coras7baeb712019-01-04 17:05:43 -08002113 rv = vls_attr (vep_vlsh, VPPCOM_ATTR_SET_LIBC_EPFD, &libc_epfd,
2114 &size);
Florin Coras99368312018-08-02 10:45:44 -07002115 if (rv < 0)
2116 {
2117 errno = -rv;
2118 rv = -1;
2119 goto done;
2120 }
2121 }
2122 else if (PREDICT_FALSE (libc_epfd < 0))
2123 {
2124 errno = -epfd;
2125 rv = -1;
2126 goto done;
2127 }
2128
Florin Coras7baeb712019-01-04 17:05:43 -08002129 LDBG (1, "epfd %d: calling libc_epoll_ctl: libc_epfd %d, op %d, fd %d,"
2130 " event %p", epfd, libc_epfd, op, fd, event);
Florin Coras99368312018-08-02 10:45:44 -07002131
2132 rv = libc_epoll_ctl (libc_epfd, op, fd, event);
Dave Wallace048b1d62018-01-03 22:24:41 -05002133 }
2134
2135done:
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002136 return rv;
2137}
Dave Wallace048b1d62018-01-03 22:24:41 -05002138
2139static inline int
Florin Coras99368312018-08-02 10:45:44 -07002140ldp_epoll_pwait (int epfd, struct epoll_event *events, int maxevents,
2141 int timeout, const sigset_t * sigmask)
Dave Wallace048b1d62018-01-03 22:24:41 -05002142{
Florin Corasdfe4cf42018-11-28 22:13:45 -08002143 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras72f77822019-01-22 19:05:52 -08002144 double time_to_wait = (double) 0, max_time;
Florin Coras99368312018-08-02 10:45:44 -07002145 int libc_epfd, rv = 0;
Florin Coras7baeb712019-01-04 17:05:43 -08002146 vls_handle_t ep_vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002147
Dave Wallace2a865272018-02-07 21:00:42 -05002148 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05002149 return -1;
2150
2151 if (PREDICT_FALSE (!events || (timeout < -1)))
2152 {
2153 errno = EFAULT;
2154 return -1;
2155 }
2156
Florin Corasdfe4cf42018-11-28 22:13:45 -08002157 if (epfd == ldpw->vcl_mq_epfd)
Florin Coras99368312018-08-02 10:45:44 -07002158 return libc_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
2159
Florin Coras7baeb712019-01-04 17:05:43 -08002160 ep_vlsh = ldp_fd_to_vlsh (epfd);
2161 if (PREDICT_FALSE (ep_vlsh == VLS_INVALID_HANDLE))
Dave Wallace048b1d62018-01-03 22:24:41 -05002162 {
Florin Coras7baeb712019-01-04 17:05:43 -08002163 LDBG (0, "epfd %d: bad ep_vlsh %d!", epfd, ep_vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05002164 errno = EBADFD;
2165 return -1;
2166 }
2167
Florin Corasb0f662f2018-12-27 14:51:46 -08002168 time_to_wait = ((timeout >= 0) ? (double) timeout / 1000 : 0);
Florin Coras72f77822019-01-22 19:05:52 -08002169 max_time = clib_time_now (&ldpw->clib_time) + time_to_wait;
Dave Wallace048b1d62018-01-03 22:24:41 -05002170
Florin Coras7baeb712019-01-04 17:05:43 -08002171 libc_epfd = vls_attr (ep_vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002172 if (PREDICT_FALSE (libc_epfd < 0))
2173 {
2174 errno = -libc_epfd;
2175 rv = -1;
2176 goto done;
2177 }
2178
Florin Coras7baeb712019-01-04 17:05:43 -08002179 LDBG (2, "epfd %d: vep_idx %d, libc_epfd %d, events %p, maxevents %d, "
2180 "timeout %d, sigmask %p: time_to_wait %.02f", epfd, ep_vlsh,
Florin Coras72f77822019-01-22 19:05:52 -08002181 libc_epfd, events, maxevents, timeout, sigmask, time_to_wait);
Dave Wallace048b1d62018-01-03 22:24:41 -05002182 do
2183 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002184 if (!ldpw->epoll_wait_vcl)
Dave Wallace048b1d62018-01-03 22:24:41 -05002185 {
Florin Coras7baeb712019-01-04 17:05:43 -08002186 rv = vls_epoll_wait (ep_vlsh, events, maxevents, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002187 if (rv > 0)
2188 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002189 ldpw->epoll_wait_vcl = 1;
Dave Wallace048b1d62018-01-03 22:24:41 -05002190 goto done;
2191 }
2192 else if (rv < 0)
2193 {
2194 errno = -rv;
2195 rv = -1;
2196 goto done;
2197 }
2198 }
2199 else
Florin Corasdfe4cf42018-11-28 22:13:45 -08002200 ldpw->epoll_wait_vcl = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -05002201
2202 if (libc_epfd > 0)
2203 {
Florin Corasb0f662f2018-12-27 14:51:46 -08002204 rv = libc_epoll_pwait (libc_epfd, events, maxevents, 0, sigmask);
Dave Wallace048b1d62018-01-03 22:24:41 -05002205 if (rv != 0)
2206 goto done;
2207 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002208 }
Florin Coras72f77822019-01-22 19:05:52 -08002209 while ((timeout == -1) || (clib_time_now (&ldpw->clib_time) < max_time));
Dave Wallace048b1d62018-01-03 22:24:41 -05002210
2211done:
Dave Wallace048b1d62018-01-03 22:24:41 -05002212 return rv;
2213}
2214
2215int
2216epoll_pwait (int epfd, struct epoll_event *events,
2217 int maxevents, int timeout, const sigset_t * sigmask)
2218{
Dave Wallace2a865272018-02-07 21:00:42 -05002219 return ldp_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
Dave Wallace048b1d62018-01-03 22:24:41 -05002220}
2221
2222int
2223epoll_wait (int epfd, struct epoll_event *events, int maxevents, int timeout)
2224{
Dave Wallace2a865272018-02-07 21:00:42 -05002225 return ldp_epoll_pwait (epfd, events, maxevents, timeout, NULL);
Dave Wallace048b1d62018-01-03 22:24:41 -05002226}
2227
2228int
2229poll (struct pollfd *fds, nfds_t nfds, int timeout)
2230{
Florin Corasdfe4cf42018-11-28 22:13:45 -08002231 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras6917b942018-11-13 22:44:54 -08002232 int rv, i, n_revents = 0;
Florin Coras7baeb712019-01-04 17:05:43 -08002233 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002234 vcl_poll_t *vp;
2235 double wait_for_time;
2236
Florin Coras05ecfcc2018-12-12 18:19:39 -08002237 LDBG (3, "fds %p, nfds %d, timeout %d", fds, nfds, timeout);
Dave Wallace048b1d62018-01-03 22:24:41 -05002238
2239 if (timeout >= 0)
2240 wait_for_time = (f64) timeout / 1000;
2241 else
2242 wait_for_time = -1;
2243
Dave Wallace048b1d62018-01-03 22:24:41 -05002244 for (i = 0; i < nfds; i++)
2245 {
Florin Coras6917b942018-11-13 22:44:54 -08002246 if (fds[i].fd < 0)
2247 continue;
Dave Wallace048b1d62018-01-03 22:24:41 -05002248
Florin Coras7baeb712019-01-04 17:05:43 -08002249 vlsh = ldp_fd_to_vlsh (fds[i].fd);
2250 if (vlsh != VLS_INVALID_HANDLE)
Florin Coras6917b942018-11-13 22:44:54 -08002251 {
2252 fds[i].fd = -fds[i].fd;
Florin Corasdfe4cf42018-11-28 22:13:45 -08002253 vec_add2 (ldpw->vcl_poll, vp, 1);
Florin Coras6917b942018-11-13 22:44:54 -08002254 vp->fds_ndx = i;
Florin Coras7baeb712019-01-04 17:05:43 -08002255 vp->sh = vlsh_to_sh (vlsh);
Florin Coras6917b942018-11-13 22:44:54 -08002256 vp->events = fds[i].events;
Dave Wallace048b1d62018-01-03 22:24:41 -05002257#ifdef __USE_XOPEN2K
Florin Coras6917b942018-11-13 22:44:54 -08002258 if (fds[i].events & POLLRDNORM)
2259 vp->events |= POLLIN;
2260 if (fds[i].events & POLLWRNORM)
2261 vp->events |= POLLOUT;
Dave Wallace048b1d62018-01-03 22:24:41 -05002262#endif
Florin Coras6917b942018-11-13 22:44:54 -08002263 vp->revents = fds[i].revents;
2264 }
2265 else
2266 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002267 vec_add1 (ldpw->libc_poll, fds[i]);
2268 vec_add1 (ldpw->libc_poll_idxs, i);
Dave Wallace048b1d62018-01-03 22:24:41 -05002269 }
2270 }
2271
Dave Wallace048b1d62018-01-03 22:24:41 -05002272 do
2273 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002274 if (vec_len (ldpw->vcl_poll))
Dave Wallace048b1d62018-01-03 22:24:41 -05002275 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002276 rv = vppcom_poll (ldpw->vcl_poll, vec_len (ldpw->vcl_poll), 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002277 if (rv < 0)
2278 {
2279 errno = -rv;
2280 rv = -1;
2281 goto done;
2282 }
2283 else
2284 n_revents += rv;
2285 }
2286
Florin Corasdfe4cf42018-11-28 22:13:45 -08002287 if (vec_len (ldpw->libc_poll))
Dave Wallace048b1d62018-01-03 22:24:41 -05002288 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002289 rv = libc_poll (ldpw->libc_poll, vec_len (ldpw->libc_poll), 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002290 if (rv < 0)
2291 goto done;
2292 else
2293 n_revents += rv;
2294 }
2295
2296 if (n_revents)
2297 {
2298 rv = n_revents;
2299 goto done;
2300 }
2301 }
2302 while ((wait_for_time == -1) ||
Florin Corasdfe4cf42018-11-28 22:13:45 -08002303 (clib_time_now (&ldpw->clib_time) < wait_for_time));
Dave Wallace048b1d62018-01-03 22:24:41 -05002304 rv = 0;
2305
2306done:
Florin Corasdfe4cf42018-11-28 22:13:45 -08002307 vec_foreach (vp, ldpw->vcl_poll)
Dave Wallace048b1d62018-01-03 22:24:41 -05002308 {
2309 fds[vp->fds_ndx].fd = -fds[vp->fds_ndx].fd;
Florin Coras6917b942018-11-13 22:44:54 -08002310 fds[vp->fds_ndx].revents = vp->revents;
Dave Wallace048b1d62018-01-03 22:24:41 -05002311#ifdef __USE_XOPEN2K
2312 if ((fds[vp->fds_ndx].revents & POLLIN) &&
2313 (fds[vp->fds_ndx].events & POLLRDNORM))
2314 fds[vp->fds_ndx].revents |= POLLRDNORM;
2315 if ((fds[vp->fds_ndx].revents & POLLOUT) &&
2316 (fds[vp->fds_ndx].events & POLLWRNORM))
2317 fds[vp->fds_ndx].revents |= POLLWRNORM;
2318#endif
2319 }
Florin Corasdfe4cf42018-11-28 22:13:45 -08002320 vec_reset_length (ldpw->vcl_poll);
Dave Wallace048b1d62018-01-03 22:24:41 -05002321
Florin Corasdfe4cf42018-11-28 22:13:45 -08002322 for (i = 0; i < vec_len (ldpw->libc_poll); i++)
Florin Coras6917b942018-11-13 22:44:54 -08002323 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002324 fds[ldpw->libc_poll_idxs[i]].revents = ldpw->libc_poll[i].revents;
Florin Coras6917b942018-11-13 22:44:54 -08002325 }
Florin Corasdfe4cf42018-11-28 22:13:45 -08002326 vec_reset_length (ldpw->libc_poll_idxs);
2327 vec_reset_length (ldpw->libc_poll);
Florin Coras6917b942018-11-13 22:44:54 -08002328
Dave Wallace048b1d62018-01-03 22:24:41 -05002329 return rv;
2330}
2331
2332#ifdef USE_GNU
2333int
2334ppoll (struct pollfd *fds, nfds_t nfds,
2335 const struct timespec *timeout, const sigset_t * sigmask)
2336{
Dave Wallace2a865272018-02-07 21:00:42 -05002337 if ((errno = -ldp_init ()))
Dave Wallace048b1d62018-01-03 22:24:41 -05002338 return -1;
2339
2340 clib_warning ("LDP<%d>: LDP-TBD", getpid ());
2341 errno = ENOSYS;
2342
2343
2344 return -1;
2345}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002346#endif
2347
Dave Wallace2a865272018-02-07 21:00:42 -05002348void CONSTRUCTOR_ATTRIBUTE ldp_constructor (void);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002349
Dave Wallace2a865272018-02-07 21:00:42 -05002350void DESTRUCTOR_ATTRIBUTE ldp_destructor (void);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002351
Dave Wallace048b1d62018-01-03 22:24:41 -05002352/*
2353 * This function is called when the library is loaded
2354 */
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002355void
Dave Wallace2a865272018-02-07 21:00:42 -05002356ldp_constructor (void)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002357{
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002358 swrap_constructor ();
Dave Wallace2a865272018-02-07 21:00:42 -05002359 if (ldp_init () != 0)
2360 fprintf (stderr, "\nLDP<%d>: ERROR: ldp_constructor: failed!\n",
Dave Wallace048b1d62018-01-03 22:24:41 -05002361 getpid ());
Dave Wallace69d01192018-02-22 16:22:09 -05002362 else if (LDP_DEBUG > 0)
Dave Wallace2a865272018-02-07 21:00:42 -05002363 clib_warning ("LDP<%d>: LDP constructor: done!\n", getpid ());
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002364}
2365
2366/*
2367 * This function is called when the library is unloaded
2368 */
2369void
Dave Wallace2a865272018-02-07 21:00:42 -05002370ldp_destructor (void)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002371{
Florin Coras0ef8ef22019-01-18 08:37:13 -08002372 /*
2373 swrap_destructor ();
2374 if (ldp->init)
2375 ldp->init = 0;
2376 */
Dave Wallace048b1d62018-01-03 22:24:41 -05002377
2378 /* Don't use clib_warning() here because that calls writev()
Dave Wallace2a865272018-02-07 21:00:42 -05002379 * which will call ldp_init().
Dave Wallace048b1d62018-01-03 22:24:41 -05002380 */
Dave Wallace69d01192018-02-22 16:22:09 -05002381 if (LDP_DEBUG > 0)
Florin Coras0ef8ef22019-01-18 08:37:13 -08002382 fprintf (stderr, "%s:%d: LDP<%d>: LDP destructor: done!\n",
2383 __func__, __LINE__, getpid ());
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002384}
2385
2386
2387/*
2388 * fd.io coding-style-patch-verification: ON
2389 *
2390 * Local Variables:
2391 * eval: (c-set-style "gnu")
2392 * End:
2393 */