blob: bd3457fa8fdc621b3e83eeaa573ad6e8589ae14d [file] [log] [blame]
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001/*
Florin Coras5e062572019-03-14 19:07:51 -07002 * Copyright (c) 2016-2019 Cisco and/or its affiliates.
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07003 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
Florin Coras36847942023-02-02 12:56:16 -080015
16#ifdef HAVE_GNU_SOURCE
17#define _GNU_SOURCE
18#endif
19
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -070020#include <unistd.h>
21#include <stdio.h>
22#include <signal.h>
23#include <dlfcn.h>
24#include <pthread.h>
25#include <time.h>
26#include <stdarg.h>
shrinivasan ganapathy1d359632017-10-15 15:46:09 -070027#include <sys/resource.h>
Dave Wallace048b1d62018-01-03 22:24:41 -050028#include <netinet/tcp.h>
Florin Coraseff5f7a2023-02-07 17:36:17 -080029#include <netinet/udp.h>
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -070030
Dave Wallace2a865272018-02-07 21:00:42 -050031#include <vcl/ldp_socket_wrapper.h>
32#include <vcl/ldp.h>
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -070033#include <sys/time.h>
34
Florin Coras7baeb712019-01-04 17:05:43 -080035#include <vcl/vcl_locked.h>
Dave Wallace048b1d62018-01-03 22:24:41 -050036#include <vppinfra/time.h>
37#include <vppinfra/bitmap.h>
Florin Coras30e273b2018-11-27 00:04:59 -080038#include <vppinfra/lock.h>
39#include <vppinfra/pool.h>
40#include <vppinfra/hash.h>
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -070041
42#define HAVE_CONSTRUCTOR_ATTRIBUTE
43#ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
44#define CONSTRUCTOR_ATTRIBUTE \
45 __attribute__ ((constructor))
46#else
47#define CONSTRUCTOR_ATTRIBUTE
48#endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
49
50#define HAVE_DESTRUCTOR_ATTRIBUTE
51#ifdef HAVE_DESTRUCTOR_ATTRIBUTE
52#define DESTRUCTOR_ATTRIBUTE \
53 __attribute__ ((destructor))
54#else
55#define DESTRUCTOR_ATTRIBUTE
56#endif
57
Florin Corasdfe4cf42018-11-28 22:13:45 -080058#define LDP_MAX_NWORKERS 32
59
Florin Coras36847942023-02-02 12:56:16 -080060#ifdef HAVE_GNU_SOURCE
61#define SOCKADDR_GET_SA(__addr) __addr.__sockaddr__;
62#else
63#define SOCKADDR_GET_SA(__addr) _addr;
64#endif
65
Tianyu Li2073fe42023-02-27 09:14:34 +000066#ifndef UDP_SEGMENT
67#define UDP_SEGMENT 103
68#endif
69
qinyangaf9b7152023-06-27 01:11:53 -070070#ifndef SO_ORIGINAL_DST
71/* from <linux/netfilter_ipv4.h> */
72#define SO_ORIGINAL_DST 80
73#endif
Florin Corasdfe4cf42018-11-28 22:13:45 -080074typedef struct ldp_worker_ctx_
Dave Wallace048b1d62018-01-03 22:24:41 -050075{
Dave Wallace048b1d62018-01-03 22:24:41 -050076 u8 *io_buffer;
77 clib_time_t clib_time;
Florin Corasdfe4cf42018-11-28 22:13:45 -080078
79 /*
80 * Select state
81 */
Dave Wallace048b1d62018-01-03 22:24:41 -050082 clib_bitmap_t *rd_bitmap;
83 clib_bitmap_t *wr_bitmap;
84 clib_bitmap_t *ex_bitmap;
Florin Coras294afe22019-01-07 17:49:17 -080085 clib_bitmap_t *si_rd_bitmap;
86 clib_bitmap_t *si_wr_bitmap;
87 clib_bitmap_t *si_ex_bitmap;
Dave Wallace048b1d62018-01-03 22:24:41 -050088 clib_bitmap_t *libc_rd_bitmap;
89 clib_bitmap_t *libc_wr_bitmap;
90 clib_bitmap_t *libc_ex_bitmap;
Florin Corasdfe4cf42018-11-28 22:13:45 -080091
92 /*
93 * Poll state
94 */
Dave Wallace048b1d62018-01-03 22:24:41 -050095 vcl_poll_t *vcl_poll;
Florin Coras6917b942018-11-13 22:44:54 -080096 struct pollfd *libc_poll;
97 u16 *libc_poll_idxs;
Florin Corasdfe4cf42018-11-28 22:13:45 -080098
99 /*
100 * Epoll state
101 */
Dave Wallace048b1d62018-01-03 22:24:41 -0500102 u8 epoll_wait_vcl;
hanlin4266d4d2020-05-19 17:34:17 +0800103 u8 mq_epfd_added;
Florin Coras99368312018-08-02 10:45:44 -0700104 int vcl_mq_epfd;
Florin Corasdfe4cf42018-11-28 22:13:45 -0800105
106} ldp_worker_ctx_t;
107
Florin Coras294afe22019-01-07 17:49:17 -0800108/* clib_bitmap_t, fd_mask and vcl_si_set are used interchangeably. Make sure
109 * they are the same size */
110STATIC_ASSERT (sizeof (clib_bitmap_t) == sizeof (fd_mask),
111 "ldp bitmap size mismatch");
112STATIC_ASSERT (sizeof (vcl_si_set) == sizeof (fd_mask),
113 "ldp bitmap size mismatch");
114
Florin Corasdfe4cf42018-11-28 22:13:45 -0800115typedef struct
116{
117 ldp_worker_ctx_t *workers;
118 int init;
119 char app_name[LDP_APP_NAME_MAX];
Florin Coras7baeb712019-01-04 17:05:43 -0800120 u32 vlsh_bit_val;
121 u32 vlsh_bit_mask;
Florin Corasdfe4cf42018-11-28 22:13:45 -0800122 u32 debug;
Florin Corasdfe4cf42018-11-28 22:13:45 -0800123
124 /** vcl needs next epoll_create to go to libc_epoll */
125 u8 vcl_needs_real_epoll;
Florin Corasa5a9efd2021-01-05 17:03:29 -0800126
127 /**
128 * crypto state used only for testing
129 */
130 u8 transparent_tls;
131 u32 ckpair_index;
Dave Wallace2a865272018-02-07 21:00:42 -0500132} ldp_main_t;
Florin Corasdfe4cf42018-11-28 22:13:45 -0800133
Dave Wallace2a865272018-02-07 21:00:42 -0500134#define LDP_DEBUG ldp->debug
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700135
Florin Coras99368312018-08-02 10:45:44 -0700136#define LDBG(_lvl, _fmt, _args...) \
137 if (ldp->debug > _lvl) \
hanlin9f3f18f2019-12-30 16:25:20 +0800138 { \
139 int errno_saved = errno; \
Florin Coras585c86a2020-10-16 17:57:36 -0700140 fprintf (stderr, "ldp<%d>: " _fmt "\n", getpid(), ##_args); \
hanlin9f3f18f2019-12-30 16:25:20 +0800141 errno = errno_saved; \
142 }
Florin Coras99368312018-08-02 10:45:44 -0700143
Dave Wallace2a865272018-02-07 21:00:42 -0500144static ldp_main_t ldp_main = {
Florin Coras7baeb712019-01-04 17:05:43 -0800145 .vlsh_bit_val = (1 << LDP_SID_BIT_MIN),
146 .vlsh_bit_mask = (1 << LDP_SID_BIT_MIN) - 1,
Dave Wallace2a865272018-02-07 21:00:42 -0500147 .debug = LDP_DEBUG_INIT,
Yu Ping7b74b072019-05-08 00:40:24 +0800148 .transparent_tls = 0,
Florin Corasa5a9efd2021-01-05 17:03:29 -0800149 .ckpair_index = ~0,
Dave Wallace048b1d62018-01-03 22:24:41 -0500150};
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700151
Dave Wallace2a865272018-02-07 21:00:42 -0500152static ldp_main_t *ldp = &ldp_main;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700153
Florin Corasdfe4cf42018-11-28 22:13:45 -0800154static inline ldp_worker_ctx_t *
155ldp_worker_get_current (void)
156{
157 return (ldp->workers + vppcom_worker_index ());
158}
159
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700160/*
161 * RETURN: 0 on success or -1 on error.
162 * */
Dave Wallace048b1d62018-01-03 22:24:41 -0500163static inline void
Dave Wallace2a865272018-02-07 21:00:42 -0500164ldp_set_app_name (char *app_name)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700165{
Florin Coras729b9c92023-02-28 10:58:08 -0800166 snprintf (ldp->app_name, LDP_APP_NAME_MAX, "%s-ldp-%d", app_name, getpid ());
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700167}
168
Dave Wallace048b1d62018-01-03 22:24:41 -0500169static inline char *
Dave Wallace2a865272018-02-07 21:00:42 -0500170ldp_get_app_name ()
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700171{
Dave Wallace2a865272018-02-07 21:00:42 -0500172 if (ldp->app_name[0] == '\0')
Florin Coras729b9c92023-02-28 10:58:08 -0800173 ldp_set_app_name (program_invocation_short_name);
Dave Wallace048b1d62018-01-03 22:24:41 -0500174
Dave Wallace2a865272018-02-07 21:00:42 -0500175 return ldp->app_name;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700176}
177
Dave Wallace048b1d62018-01-03 22:24:41 -0500178static inline int
Florin Coras7baeb712019-01-04 17:05:43 -0800179ldp_vlsh_to_fd (vls_handle_t vlsh)
Dave Wallace048b1d62018-01-03 22:24:41 -0500180{
Florin Coras7baeb712019-01-04 17:05:43 -0800181 return (vlsh + ldp->vlsh_bit_val);
Dave Wallace048b1d62018-01-03 22:24:41 -0500182}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700183
Florin Coras7baeb712019-01-04 17:05:43 -0800184static inline vls_handle_t
185ldp_fd_to_vlsh (int fd)
Dave Wallace048b1d62018-01-03 22:24:41 -0500186{
Florin Coras7baeb712019-01-04 17:05:43 -0800187 if (fd < ldp->vlsh_bit_val)
188 return VLS_INVALID_HANDLE;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700189
Florin Coras7baeb712019-01-04 17:05:43 -0800190 return (fd - ldp->vlsh_bit_val);
Dave Wallace048b1d62018-01-03 22:24:41 -0500191}
192
Florin Coras2d9b4272019-03-11 10:14:37 -0700193static void
194ldp_alloc_workers (void)
195{
196 if (ldp->workers)
197 return;
Florin Coras1b75fdb2023-11-28 16:05:29 -0800198 ldp->workers = vec_new (ldp_worker_ctx_t, LDP_MAX_NWORKERS);
Florin Coras2d9b4272019-03-11 10:14:37 -0700199}
200
Florin Corasc6c4e862023-03-09 18:23:05 -0800201static void
202ldp_init_cfg (void)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700203{
Florin Coras99368312018-08-02 10:45:44 -0700204 char *env_var_str = getenv (LDP_ENV_DEBUG);
205 if (env_var_str)
206 {
207 u32 tmp;
208 if (sscanf (env_var_str, "%u", &tmp) != 1)
209 clib_warning ("LDP<%d>: WARNING: Invalid LDP debug level specified in"
210 " the env var " LDP_ENV_DEBUG " (%s)!", getpid (),
211 env_var_str);
212 else
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700213 {
Florin Coras99368312018-08-02 10:45:44 -0700214 ldp->debug = tmp;
Florin Coras05ecfcc2018-12-12 18:19:39 -0800215 LDBG (0, "configured LDP debug level (%u) from env var "
216 LDP_ENV_DEBUG "!", ldp->debug);
Florin Coras99368312018-08-02 10:45:44 -0700217 }
218 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500219
Florin Coras99368312018-08-02 10:45:44 -0700220 env_var_str = getenv (LDP_ENV_APP_NAME);
221 if (env_var_str)
222 {
223 ldp_set_app_name (env_var_str);
Florin Coras05ecfcc2018-12-12 18:19:39 -0800224 LDBG (0, "configured LDP app name (%s) from the env var "
225 LDP_ENV_APP_NAME "!", ldp->app_name);
Florin Coras99368312018-08-02 10:45:44 -0700226 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500227
Florin Coras99368312018-08-02 10:45:44 -0700228 env_var_str = getenv (LDP_ENV_SID_BIT);
229 if (env_var_str)
230 {
231 u32 sb;
232 if (sscanf (env_var_str, "%u", &sb) != 1)
233 {
Florin Coras294afe22019-01-07 17:49:17 -0800234 LDBG (0, "WARNING: Invalid LDP sid bit specified in the env var "
235 LDP_ENV_SID_BIT " (%s)! sid bit value %d (0x%x)", env_var_str,
236 ldp->vlsh_bit_val, ldp->vlsh_bit_val);
Florin Coras99368312018-08-02 10:45:44 -0700237 }
238 else if (sb < LDP_SID_BIT_MIN)
239 {
Florin Coras7baeb712019-01-04 17:05:43 -0800240 ldp->vlsh_bit_val = (1 << LDP_SID_BIT_MIN);
241 ldp->vlsh_bit_mask = ldp->vlsh_bit_val - 1;
Dave Wallace048b1d62018-01-03 22:24:41 -0500242
Florin Coras294afe22019-01-07 17:49:17 -0800243 LDBG (0, "WARNING: LDP sid bit (%u) specified in the env var "
244 LDP_ENV_SID_BIT " (%s) is too small. Using LDP_SID_BIT_MIN"
245 " (%d)! sid bit value %d (0x%x)", sb, env_var_str,
246 LDP_SID_BIT_MIN, ldp->vlsh_bit_val, ldp->vlsh_bit_val);
Florin Coras99368312018-08-02 10:45:44 -0700247 }
248 else if (sb > LDP_SID_BIT_MAX)
249 {
Florin Coras7baeb712019-01-04 17:05:43 -0800250 ldp->vlsh_bit_val = (1 << LDP_SID_BIT_MAX);
251 ldp->vlsh_bit_mask = ldp->vlsh_bit_val - 1;
Dave Wallace048b1d62018-01-03 22:24:41 -0500252
Florin Coras294afe22019-01-07 17:49:17 -0800253 LDBG (0, "WARNING: LDP sid bit (%u) specified in the env var "
254 LDP_ENV_SID_BIT " (%s) is too big. Using LDP_SID_BIT_MAX"
255 " (%d)! sid bit value %d (0x%x)", sb, env_var_str,
256 LDP_SID_BIT_MAX, ldp->vlsh_bit_val, ldp->vlsh_bit_val);
Dave Wallace048b1d62018-01-03 22:24:41 -0500257 }
258 else
259 {
Florin Coras7baeb712019-01-04 17:05:43 -0800260 ldp->vlsh_bit_val = (1 << sb);
261 ldp->vlsh_bit_mask = ldp->vlsh_bit_val - 1;
Florin Coras99368312018-08-02 10:45:44 -0700262
Florin Coras05ecfcc2018-12-12 18:19:39 -0800263 LDBG (0, "configured LDP sid bit (%u) from "
264 LDP_ENV_SID_BIT "! sid bit value %d (0x%x)", sb,
Florin Coras7baeb712019-01-04 17:05:43 -0800265 ldp->vlsh_bit_val, ldp->vlsh_bit_val);
Dave Wallace048b1d62018-01-03 22:24:41 -0500266 }
Florin Coras294afe22019-01-07 17:49:17 -0800267
268 /* Make sure there are enough bits in the fd set for vcl sessions */
269 if (ldp->vlsh_bit_val > FD_SETSIZE / 2)
270 {
wanghanlin1eb8fea2021-10-14 11:10:26 +0800271 /* Only valid for select/pselect, so just WARNING and not exit */
272 LDBG (0,
273 "WARNING: LDP vlsh bit value %d > FD_SETSIZE/2 %d, "
274 "select/pselect not supported now!",
Florin Coras294afe22019-01-07 17:49:17 -0800275 ldp->vlsh_bit_val, FD_SETSIZE / 2);
Florin Coras294afe22019-01-07 17:49:17 -0800276 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500277 }
Yu Ping7b74b072019-05-08 00:40:24 +0800278 env_var_str = getenv (LDP_ENV_TLS_TRANS);
279 if (env_var_str)
280 {
281 ldp->transparent_tls = 1;
282 }
Florin Corasc6c4e862023-03-09 18:23:05 -0800283}
Florin Coras99368312018-08-02 10:45:44 -0700284
Florin Corasc6c4e862023-03-09 18:23:05 -0800285static int
286ldp_init (void)
287{
288 ldp_worker_ctx_t *ldpw;
289 int rv;
290
Gao Feng96600f92023-07-17 22:19:32 +0800291 if (ldp->init)
292 {
293 LDBG (0, "LDP is initialized already");
294 return 0;
295 }
Florin Corasc6c4e862023-03-09 18:23:05 -0800296
297 ldp_init_cfg ();
298 ldp->init = 1;
299 ldp->vcl_needs_real_epoll = 1;
300 rv = vls_app_create (ldp_get_app_name ());
301 if (rv != VPPCOM_OK)
302 {
303 ldp->vcl_needs_real_epoll = 0;
304 if (rv == VPPCOM_EEXIST)
305 return 0;
306 LDBG (2,
307 "\nERROR: ldp_init: vppcom_app_create()"
308 " failed! rv = %d (%s)\n",
309 rv, vppcom_retval_str (rv));
310 ldp->init = 0;
311 return rv;
312 }
313 ldp->vcl_needs_real_epoll = 0;
314 ldp_alloc_workers ();
Florin Corasc6c4e862023-03-09 18:23:05 -0800315
Florin Coras1b75fdb2023-11-28 16:05:29 -0800316 vec_foreach (ldpw, ldp->workers)
Florin Coras4dee8cd2019-01-29 21:28:16 -0800317 clib_memset (&ldpw->clib_time, 0, sizeof (ldpw->clib_time));
Florin Coras4dee8cd2019-01-29 21:28:16 -0800318
Florin Coras05ecfcc2018-12-12 18:19:39 -0800319 LDBG (0, "LDP initialization: done!");
Florin Coras99368312018-08-02 10:45:44 -0700320
321 return 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500322}
323
Florin Coras5f33d0d2021-06-02 21:22:21 -0700324#define ldp_init_check() \
325 if (PREDICT_FALSE (!ldp->init)) \
326 { \
327 if ((errno = -ldp_init ())) \
328 return -1; \
329 }
330
Dave Wallace048b1d62018-01-03 22:24:41 -0500331int
332close (int fd)
333{
Florin Coras7baeb712019-01-04 17:05:43 -0800334 vls_handle_t vlsh;
335 int rv, epfd;
Dave Wallace048b1d62018-01-03 22:24:41 -0500336
Florin Coras5f33d0d2021-06-02 21:22:21 -0700337 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -0500338
Florin Coras7baeb712019-01-04 17:05:43 -0800339 vlsh = ldp_fd_to_vlsh (fd);
340 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500341 {
Florin Coras7baeb712019-01-04 17:05:43 -0800342 epfd = vls_attr (vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -0500343 if (epfd > 0)
344 {
Florin Coras06defbc2023-02-28 22:32:31 -0800345 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
346 u32 size = sizeof (epfd);
347
Florin Coras7baeb712019-01-04 17:05:43 -0800348 LDBG (0, "fd %d: calling libc_close: epfd %u", fd, epfd);
Dave Wallace048b1d62018-01-03 22:24:41 -0500349
Florin Coras06defbc2023-02-28 22:32:31 -0800350 libc_close (epfd);
351 ldpw->mq_epfd_added = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500352
Florin Coras06defbc2023-02-28 22:32:31 -0800353 epfd = 0;
354 (void) vls_attr (vlsh, VPPCOM_ATTR_SET_LIBC_EPFD, &epfd, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -0500355 }
356 else if (PREDICT_FALSE (epfd < 0))
357 {
358 errno = -epfd;
359 rv = -1;
360 goto done;
361 }
362
Florin Coras7baeb712019-01-04 17:05:43 -0800363 LDBG (0, "fd %d: calling vls_close: vlsh %u", fd, vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -0500364
Florin Coras7baeb712019-01-04 17:05:43 -0800365 rv = vls_close (vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -0500366 if (rv != VPPCOM_OK)
367 {
368 errno = -rv;
369 rv = -1;
370 }
371 }
372 else
373 {
Florin Coras7baeb712019-01-04 17:05:43 -0800374 LDBG (0, "fd %d: calling libc_close", fd);
Dave Wallace048b1d62018-01-03 22:24:41 -0500375 rv = libc_close (fd);
376 }
377
378done:
Dave Wallace048b1d62018-01-03 22:24:41 -0500379 return rv;
380}
381
382ssize_t
383read (int fd, void *buf, size_t nbytes)
384{
Florin Coras7baeb712019-01-04 17:05:43 -0800385 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500386 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -0500387
Florin Coras5f33d0d2021-06-02 21:22:21 -0700388 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -0500389
Florin Coras7baeb712019-01-04 17:05:43 -0800390 vlsh = ldp_fd_to_vlsh (fd);
391 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500392 {
Florin Coras7baeb712019-01-04 17:05:43 -0800393 size = vls_read (vlsh, buf, nbytes);
Dave Wallace048b1d62018-01-03 22:24:41 -0500394 if (size < 0)
395 {
396 errno = -size;
397 size = -1;
398 }
399 }
400 else
401 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500402 size = libc_read (fd, buf, nbytes);
403 }
404
Dave Wallace048b1d62018-01-03 22:24:41 -0500405 return size;
406}
407
408ssize_t
409readv (int fd, const struct iovec * iov, int iovcnt)
410{
Dave Wallace8aaba562018-01-18 17:21:19 -0500411 int rv = 0, i, total = 0;
Florin Coras7baeb712019-01-04 17:05:43 -0800412 vls_handle_t vlsh;
413 ssize_t size = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500414
Florin Coras5f33d0d2021-06-02 21:22:21 -0700415 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -0500416
Florin Coras7baeb712019-01-04 17:05:43 -0800417 vlsh = ldp_fd_to_vlsh (fd);
418 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500419 {
Florin Coras067f9542020-02-14 05:33:46 +0000420 for (i = 0; i < iovcnt; ++i)
Dave Wallace048b1d62018-01-03 22:24:41 -0500421 {
Florin Coras067f9542020-02-14 05:33:46 +0000422 rv = vls_read (vlsh, iov[i].iov_base, iov[i].iov_len);
423 if (rv <= 0)
424 break;
425 else
Dave Wallace048b1d62018-01-03 22:24:41 -0500426 {
Florin Coras067f9542020-02-14 05:33:46 +0000427 total += rv;
428 if (rv < iov[i].iov_len)
Dave Wallace048b1d62018-01-03 22:24:41 -0500429 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700430 }
431 }
Florin Coras067f9542020-02-14 05:33:46 +0000432 if (rv < 0 && total == 0)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700433 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500434 errno = -rv;
435 size = -1;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700436 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500437 else
438 size = total;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700439 }
440 else
441 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500442 size = libc_readv (fd, iov, iovcnt);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700443 }
444
Dave Wallace048b1d62018-01-03 22:24:41 -0500445 return size;
446}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700447
Dave Wallace048b1d62018-01-03 22:24:41 -0500448ssize_t
449write (int fd, const void *buf, size_t nbytes)
450{
Florin Coras7baeb712019-01-04 17:05:43 -0800451 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500452 ssize_t size = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500453
Florin Coras5f33d0d2021-06-02 21:22:21 -0700454 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -0500455
Florin Coras7baeb712019-01-04 17:05:43 -0800456 vlsh = ldp_fd_to_vlsh (fd);
457 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500458 {
Florin Coras7baeb712019-01-04 17:05:43 -0800459 size = vls_write_msg (vlsh, (void *) buf, nbytes);
Dave Wallace048b1d62018-01-03 22:24:41 -0500460 if (size < 0)
461 {
462 errno = -size;
463 size = -1;
464 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700465 }
466 else
467 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500468 size = libc_write (fd, buf, nbytes);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700469 }
470
Dave Wallace048b1d62018-01-03 22:24:41 -0500471 return size;
472}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700473
Dave Wallace048b1d62018-01-03 22:24:41 -0500474ssize_t
475writev (int fd, const struct iovec * iov, int iovcnt)
476{
Dave Wallace048b1d62018-01-03 22:24:41 -0500477 ssize_t size = 0, total = 0;
Florin Coras7baeb712019-01-04 17:05:43 -0800478 vls_handle_t vlsh;
Dave Wallace8aaba562018-01-18 17:21:19 -0500479 int i, rv = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500480
Florin Coras5f33d0d2021-06-02 21:22:21 -0700481 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -0500482
Florin Coras7baeb712019-01-04 17:05:43 -0800483 vlsh = ldp_fd_to_vlsh (fd);
484 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500485 {
Florin Coraseda1b8c2020-03-23 16:00:35 +0000486 for (i = 0; i < iovcnt; ++i)
Dave Wallace048b1d62018-01-03 22:24:41 -0500487 {
Florin Coraseda1b8c2020-03-23 16:00:35 +0000488 rv = vls_write_msg (vlsh, iov[i].iov_base, iov[i].iov_len);
489 if (rv < 0)
490 break;
491 else
Dave Wallace048b1d62018-01-03 22:24:41 -0500492 {
Florin Coraseda1b8c2020-03-23 16:00:35 +0000493 total += rv;
494 if (rv < iov[i].iov_len)
Dave Wallace048b1d62018-01-03 22:24:41 -0500495 break;
Dave Wallace048b1d62018-01-03 22:24:41 -0500496 }
497 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500498
Florin Coraseda1b8c2020-03-23 16:00:35 +0000499 if (rv < 0 && total == 0)
Dave Wallace048b1d62018-01-03 22:24:41 -0500500 {
501 errno = -rv;
502 size = -1;
503 }
504 else
505 size = total;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700506 }
507 else
508 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500509 size = libc_writev (fd, iov, iovcnt);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700510 }
511
Dave Wallace048b1d62018-01-03 22:24:41 -0500512 return size;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700513}
514
Florin Coras0ab36f52020-05-26 19:45:45 +0000515static int
516fcntl_internal (int fd, int cmd, va_list ap)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700517{
Florin Coras7baeb712019-01-04 17:05:43 -0800518 vls_handle_t vlsh;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700519 int rv = 0;
Florin Coras7baeb712019-01-04 17:05:43 -0800520
521 vlsh = ldp_fd_to_vlsh (fd);
522 LDBG (0, "fd %u vlsh %d, cmd %u", fd, vlsh, cmd);
523 if (vlsh != VLS_INVALID_HANDLE)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700524 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500525 int flags = va_arg (ap, int);
526 u32 size;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700527
Dave Wallace048b1d62018-01-03 22:24:41 -0500528 size = sizeof (flags);
529 rv = -EOPNOTSUPP;
530 switch (cmd)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700531 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500532 case F_SETFL:
Florin Coras7baeb712019-01-04 17:05:43 -0800533 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_FLAGS, &flags, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -0500534 break;
535
536 case F_GETFL:
Florin Coras7baeb712019-01-04 17:05:43 -0800537 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_FLAGS, &flags, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -0500538 if (rv == VPPCOM_OK)
Florin Coras7baeb712019-01-04 17:05:43 -0800539 rv = flags;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700540 break;
Florin Coras173bae32018-11-16 18:56:28 -0800541 case F_SETFD:
542 /* TODO handle this */
543 LDBG (0, "F_SETFD ignored flags %u", flags);
544 rv = 0;
545 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700546 default:
Dave Wallace048b1d62018-01-03 22:24:41 -0500547 rv = -EOPNOTSUPP;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700548 break;
549 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500550 if (rv < 0)
551 {
552 errno = -rv;
553 rv = -1;
554 }
555 }
556 else
557 {
Carl Smithe16707b2019-11-13 14:37:39 +1300558#ifdef HAVE_FCNTL64
559 rv = libc_vfcntl64 (fd, cmd, ap);
560#else
Dave Wallace048b1d62018-01-03 22:24:41 -0500561 rv = libc_vfcntl (fd, cmd, ap);
Carl Smithe16707b2019-11-13 14:37:39 +1300562#endif
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700563 }
564
Florin Coras0ab36f52020-05-26 19:45:45 +0000565 return rv;
566}
567
568int
569fcntl (int fd, int cmd, ...)
570{
571 va_list ap;
572 int rv;
573
Florin Coras5f33d0d2021-06-02 21:22:21 -0700574 ldp_init_check ();
Florin Coras0ab36f52020-05-26 19:45:45 +0000575
576 va_start (ap, cmd);
577 rv = fcntl_internal (fd, cmd, ap);
Dave Wallace048b1d62018-01-03 22:24:41 -0500578 va_end (ap);
579
Dave Wallace048b1d62018-01-03 22:24:41 -0500580 return rv;
581}
582
583int
Florin Corasd7586d52020-04-29 02:19:51 +0000584fcntl64 (int fd, int cmd, ...)
585{
586 va_list ap;
587 int rv;
588
Florin Coras5f33d0d2021-06-02 21:22:21 -0700589 ldp_init_check ();
Florin Coras0ab36f52020-05-26 19:45:45 +0000590
Florin Corasd7586d52020-04-29 02:19:51 +0000591 va_start (ap, cmd);
Florin Coras0ab36f52020-05-26 19:45:45 +0000592 rv = fcntl_internal (fd, cmd, ap);
Florin Corasd7586d52020-04-29 02:19:51 +0000593 va_end (ap);
594 return rv;
595}
596
597int
Dave Wallace048b1d62018-01-03 22:24:41 -0500598ioctl (int fd, unsigned long int cmd, ...)
599{
Florin Coras7baeb712019-01-04 17:05:43 -0800600 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500601 va_list ap;
Florin Coras7baeb712019-01-04 17:05:43 -0800602 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -0500603
Florin Coras5f33d0d2021-06-02 21:22:21 -0700604 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -0500605
606 va_start (ap, cmd);
Dave Wallace048b1d62018-01-03 22:24:41 -0500607
Florin Coras7baeb712019-01-04 17:05:43 -0800608 vlsh = ldp_fd_to_vlsh (fd);
609 if (vlsh != VLS_INVALID_HANDLE)
610 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500611 switch (cmd)
612 {
613 case FIONREAD:
Florin Coras7baeb712019-01-04 17:05:43 -0800614 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_NREAD, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -0500615 break;
Florin Coras8ae63db2024-03-18 12:25:38 -0700616 case TIOCOUTQ:
617 {
618 u32 *buf = va_arg (ap, void *);
619 u32 *buflen = va_arg (ap, u32 *);
620 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_NWRITEQ, buf, buflen);
621 }
622 break;
Dave Wallace048b1d62018-01-03 22:24:41 -0500623 case FIONBIO:
624 {
Florin Coras4a0e08e2023-05-11 11:45:34 -0700625 u32 flags = *(va_arg (ap, int *)) ? O_NONBLOCK : 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500626 u32 size = sizeof (flags);
627
628 /* TBD: When VPPCOM_ATTR_[GS]ET_FLAGS supports flags other than
629 * non-blocking, the flags should be read here and merged
630 * with O_NONBLOCK.
631 */
Florin Coras7baeb712019-01-04 17:05:43 -0800632 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_FLAGS, &flags, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -0500633 }
634 break;
635
636 default:
637 rv = -EOPNOTSUPP;
638 break;
639 }
640 if (rv < 0)
641 {
642 errno = -rv;
643 rv = -1;
644 }
645 }
646 else
647 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500648 rv = libc_vioctl (fd, cmd, ap);
649 }
650
Dave Wallace048b1d62018-01-03 22:24:41 -0500651 va_end (ap);
652 return rv;
653}
654
Florin Coras294afe22019-01-07 17:49:17 -0800655always_inline void
656ldp_select_init_maps (fd_set * __restrict original,
657 clib_bitmap_t ** resultb, clib_bitmap_t ** libcb,
658 clib_bitmap_t ** vclb, int nfds, u32 minbits,
659 u32 n_bytes, uword * si_bits, uword * libc_bits)
660{
661 uword si_bits_set, libc_bits_set;
662 vls_handle_t vlsh;
663 int fd;
664
665 clib_bitmap_validate (*vclb, minbits);
666 clib_bitmap_validate (*libcb, minbits);
667 clib_bitmap_validate (*resultb, minbits);
668 clib_memcpy_fast (*resultb, original, n_bytes);
669 memset (original, 0, n_bytes);
670
Damjan Marionf0ca1e82020-12-13 23:26:56 +0100671 clib_bitmap_foreach (fd, *resultb) {
Florin Coras294afe22019-01-07 17:49:17 -0800672 if (fd > nfds)
673 break;
674 vlsh = ldp_fd_to_vlsh (fd);
675 if (vlsh == VLS_INVALID_HANDLE)
676 clib_bitmap_set_no_check (*libcb, fd, 1);
677 else
Florin Corascbce80a2020-04-20 01:32:38 +0000678 *vclb = clib_bitmap_set (*vclb, vlsh_to_session_index (vlsh), 1);
Damjan Marionf0ca1e82020-12-13 23:26:56 +0100679 }
Florin Coras294afe22019-01-07 17:49:17 -0800680
681 si_bits_set = clib_bitmap_last_set (*vclb) + 1;
682 *si_bits = (si_bits_set > *si_bits) ? si_bits_set : *si_bits;
Florin Corascbce80a2020-04-20 01:32:38 +0000683 clib_bitmap_validate (*resultb, *si_bits);
Florin Coras294afe22019-01-07 17:49:17 -0800684
685 libc_bits_set = clib_bitmap_last_set (*libcb) + 1;
686 *libc_bits = (libc_bits_set > *libc_bits) ? libc_bits_set : *libc_bits;
687}
688
689always_inline int
690ldp_select_vcl_map_to_libc (clib_bitmap_t * vclb, fd_set * __restrict libcb)
691{
692 vls_handle_t vlsh;
693 uword si;
694 int fd;
695
696 if (!libcb)
697 return 0;
698
Damjan Marionf0ca1e82020-12-13 23:26:56 +0100699 clib_bitmap_foreach (si, vclb) {
Florin Coras294afe22019-01-07 17:49:17 -0800700 vlsh = vls_session_index_to_vlsh (si);
Florin Coras54140622020-02-04 19:04:34 +0000701 ASSERT (vlsh != VLS_INVALID_HANDLE);
Florin Coras294afe22019-01-07 17:49:17 -0800702 fd = ldp_vlsh_to_fd (vlsh);
703 if (PREDICT_FALSE (fd < 0))
704 {
705 errno = EBADFD;
706 return -1;
707 }
708 FD_SET (fd, libcb);
Damjan Marionf0ca1e82020-12-13 23:26:56 +0100709 }
Florin Coras294afe22019-01-07 17:49:17 -0800710
711 return 0;
712}
713
714always_inline void
715ldp_select_libc_map_merge (clib_bitmap_t * result, fd_set * __restrict libcb)
716{
717 uword fd;
718
Florin Coras78b5fa62019-02-21 20:04:15 -0800719 if (!libcb)
720 return;
721
Damjan Marionf0ca1e82020-12-13 23:26:56 +0100722 clib_bitmap_foreach (fd, result)
Florin Coras294afe22019-01-07 17:49:17 -0800723 FD_SET ((int)fd, libcb);
Florin Coras294afe22019-01-07 17:49:17 -0800724}
725
Dave Wallace048b1d62018-01-03 22:24:41 -0500726int
Dave Wallace2a865272018-02-07 21:00:42 -0500727ldp_pselect (int nfds, fd_set * __restrict readfds,
728 fd_set * __restrict writefds,
729 fd_set * __restrict exceptfds,
730 const struct timespec *__restrict timeout,
731 const __sigset_t * __restrict sigmask)
Dave Wallace048b1d62018-01-03 22:24:41 -0500732{
Florin Coras294afe22019-01-07 17:49:17 -0800733 u32 minbits = clib_max (nfds, BITS (uword)), n_bytes;
Florin Corasdfe4cf42018-11-28 22:13:45 -0800734 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras294afe22019-01-07 17:49:17 -0800735 struct timespec libc_tspec = { 0 };
736 f64 time_out, vcl_timeout = 0;
737 uword si_bits, libc_bits;
738 int rv, bits_set = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500739
740 if (nfds < 0)
741 {
742 errno = EINVAL;
743 return -1;
744 }
745
Florin Coras4dee8cd2019-01-29 21:28:16 -0800746 if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
747 clib_time_init (&ldpw->clib_time);
748
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500749 if (timeout)
750 {
751 time_out = (timeout->tv_sec == 0 && timeout->tv_nsec == 0) ?
Florin Coras7baeb712019-01-04 17:05:43 -0800752 (f64) 0 : (f64) timeout->tv_sec + (f64) timeout->tv_nsec / (f64) 1e9;
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500753
liuyacanf71796e2021-08-02 10:01:39 +0800754 time_out += clib_time_now (&ldpw->clib_time);
755
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500756 /* select as fine grained sleep */
757 if (!nfds)
758 {
Florin Corasdfe4cf42018-11-28 22:13:45 -0800759 while (clib_time_now (&ldpw->clib_time) < time_out)
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500760 ;
761 return 0;
762 }
763 }
764 else if (!nfds)
765 {
766 errno = EINVAL;
767 return -1;
768 }
769 else
770 time_out = -1;
771
Florin Coras7baeb712019-01-04 17:05:43 -0800772 if (nfds <= ldp->vlsh_bit_val)
Dave Wallace048b1d62018-01-03 22:24:41 -0500773 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500774 rv = libc_pselect (nfds, readfds, writefds, exceptfds,
775 timeout, sigmask);
776 goto done;
777 }
778
Florin Coras294afe22019-01-07 17:49:17 -0800779 si_bits = libc_bits = 0;
780 n_bytes = nfds / 8 + ((nfds % 8) ? 1 : 0);
Florin Coras7baeb712019-01-04 17:05:43 -0800781
Dave Wallace048b1d62018-01-03 22:24:41 -0500782 if (readfds)
Florin Coras294afe22019-01-07 17:49:17 -0800783 ldp_select_init_maps (readfds, &ldpw->rd_bitmap, &ldpw->libc_rd_bitmap,
784 &ldpw->si_rd_bitmap, nfds, minbits, n_bytes,
785 &si_bits, &libc_bits);
Dave Wallace048b1d62018-01-03 22:24:41 -0500786 if (writefds)
Florin Coras294afe22019-01-07 17:49:17 -0800787 ldp_select_init_maps (writefds, &ldpw->wr_bitmap,
788 &ldpw->libc_wr_bitmap, &ldpw->si_wr_bitmap, nfds,
789 minbits, n_bytes, &si_bits, &libc_bits);
Dave Wallace048b1d62018-01-03 22:24:41 -0500790 if (exceptfds)
Florin Coras294afe22019-01-07 17:49:17 -0800791 ldp_select_init_maps (exceptfds, &ldpw->ex_bitmap,
792 &ldpw->libc_ex_bitmap, &ldpw->si_ex_bitmap, nfds,
793 minbits, n_bytes, &si_bits, &libc_bits);
Dave Wallace048b1d62018-01-03 22:24:41 -0500794
Florin Coras294afe22019-01-07 17:49:17 -0800795 if (PREDICT_FALSE (!si_bits && !libc_bits))
Dave Wallace048b1d62018-01-03 22:24:41 -0500796 {
797 errno = EINVAL;
798 rv = -1;
799 goto done;
800 }
801
Florin Coras78b5fa62019-02-21 20:04:15 -0800802 if (!si_bits)
803 libc_tspec = timeout ? *timeout : libc_tspec;
Florin Coras294afe22019-01-07 17:49:17 -0800804
Dave Wallace048b1d62018-01-03 22:24:41 -0500805 do
806 {
Florin Coras294afe22019-01-07 17:49:17 -0800807 if (si_bits)
Dave Wallace048b1d62018-01-03 22:24:41 -0500808 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500809 if (readfds)
Florin Coras294afe22019-01-07 17:49:17 -0800810 clib_memcpy_fast (ldpw->rd_bitmap, ldpw->si_rd_bitmap,
Florin Corascbce80a2020-04-20 01:32:38 +0000811 vec_len (ldpw->si_rd_bitmap) *
Dave Barach178cf492018-11-13 16:34:13 -0500812 sizeof (clib_bitmap_t));
Dave Wallace048b1d62018-01-03 22:24:41 -0500813 if (writefds)
Florin Coras294afe22019-01-07 17:49:17 -0800814 clib_memcpy_fast (ldpw->wr_bitmap, ldpw->si_wr_bitmap,
Florin Corascbce80a2020-04-20 01:32:38 +0000815 vec_len (ldpw->si_wr_bitmap) *
Dave Barach178cf492018-11-13 16:34:13 -0500816 sizeof (clib_bitmap_t));
Dave Wallace048b1d62018-01-03 22:24:41 -0500817 if (exceptfds)
Florin Coras294afe22019-01-07 17:49:17 -0800818 clib_memcpy_fast (ldpw->ex_bitmap, ldpw->si_ex_bitmap,
Florin Corascbce80a2020-04-20 01:32:38 +0000819 vec_len (ldpw->si_ex_bitmap) *
Dave Barach178cf492018-11-13 16:34:13 -0500820 sizeof (clib_bitmap_t));
Florin Coras294afe22019-01-07 17:49:17 -0800821
Florin Coras0ef8ef22019-01-18 08:37:13 -0800822 rv = vls_select (si_bits, readfds ? ldpw->rd_bitmap : NULL,
823 writefds ? ldpw->wr_bitmap : NULL,
824 exceptfds ? ldpw->ex_bitmap : NULL, vcl_timeout);
Florin Coras294afe22019-01-07 17:49:17 -0800825 if (rv < 0)
826 {
827 errno = -rv;
828 rv = -1;
Florin Coras5e6222a2020-04-24 17:09:25 +0000829 goto done;
Florin Coras294afe22019-01-07 17:49:17 -0800830 }
831 else if (rv > 0)
832 {
833 if (ldp_select_vcl_map_to_libc (ldpw->rd_bitmap, readfds))
834 {
835 rv = -1;
836 goto done;
837 }
838
839 if (ldp_select_vcl_map_to_libc (ldpw->wr_bitmap, writefds))
840 {
841 rv = -1;
842 goto done;
843 }
844
845 if (ldp_select_vcl_map_to_libc (ldpw->ex_bitmap, exceptfds))
846 {
847 rv = -1;
848 goto done;
849 }
850 bits_set = rv;
851 }
852 }
853 if (libc_bits)
854 {
855 if (readfds)
856 clib_memcpy_fast (ldpw->rd_bitmap, ldpw->libc_rd_bitmap,
857 vec_len (ldpw->libc_rd_bitmap) *
858 sizeof (clib_bitmap_t));
859 if (writefds)
860 clib_memcpy_fast (ldpw->wr_bitmap, ldpw->libc_wr_bitmap,
861 vec_len (ldpw->libc_wr_bitmap) *
862 sizeof (clib_bitmap_t));
863 if (exceptfds)
864 clib_memcpy_fast (ldpw->ex_bitmap, ldpw->libc_ex_bitmap,
865 vec_len (ldpw->libc_ex_bitmap) *
866 sizeof (clib_bitmap_t));
867
Dave Wallace048b1d62018-01-03 22:24:41 -0500868 rv = libc_pselect (libc_bits,
Florin Coras294afe22019-01-07 17:49:17 -0800869 readfds ? (fd_set *) ldpw->rd_bitmap : NULL,
870 writefds ? (fd_set *) ldpw->wr_bitmap : NULL,
871 exceptfds ? (fd_set *) ldpw->ex_bitmap : NULL,
872 &libc_tspec, sigmask);
873 if (rv > 0)
874 {
875 ldp_select_libc_map_merge (ldpw->rd_bitmap, readfds);
876 ldp_select_libc_map_merge (ldpw->wr_bitmap, writefds);
877 ldp_select_libc_map_merge (ldpw->ex_bitmap, exceptfds);
878 bits_set += rv;
879 }
880 }
881
882 if (bits_set)
883 {
884 rv = bits_set;
885 goto done;
Dave Wallace048b1d62018-01-03 22:24:41 -0500886 }
887 }
Florin Corasdfe4cf42018-11-28 22:13:45 -0800888 while ((time_out == -1) || (clib_time_now (&ldpw->clib_time) < time_out));
Dave Wallace048b1d62018-01-03 22:24:41 -0500889 rv = 0;
890
891done:
892 /* TBD: set timeout to amount of time left */
Florin Corasdfe4cf42018-11-28 22:13:45 -0800893 clib_bitmap_zero (ldpw->rd_bitmap);
Florin Coras294afe22019-01-07 17:49:17 -0800894 clib_bitmap_zero (ldpw->si_rd_bitmap);
Florin Corasdfe4cf42018-11-28 22:13:45 -0800895 clib_bitmap_zero (ldpw->libc_rd_bitmap);
896 clib_bitmap_zero (ldpw->wr_bitmap);
Florin Coras294afe22019-01-07 17:49:17 -0800897 clib_bitmap_zero (ldpw->si_wr_bitmap);
Florin Corasdfe4cf42018-11-28 22:13:45 -0800898 clib_bitmap_zero (ldpw->libc_wr_bitmap);
899 clib_bitmap_zero (ldpw->ex_bitmap);
Florin Coras294afe22019-01-07 17:49:17 -0800900 clib_bitmap_zero (ldpw->si_ex_bitmap);
Florin Corasdfe4cf42018-11-28 22:13:45 -0800901 clib_bitmap_zero (ldpw->libc_ex_bitmap);
Dave Wallace048b1d62018-01-03 22:24:41 -0500902
Dave Wallace048b1d62018-01-03 22:24:41 -0500903 return rv;
904}
905
906int
907select (int nfds, fd_set * __restrict readfds,
908 fd_set * __restrict writefds,
909 fd_set * __restrict exceptfds, struct timeval *__restrict timeout)
910{
911 struct timespec tspec;
912
913 if (timeout)
914 {
915 tspec.tv_sec = timeout->tv_sec;
916 tspec.tv_nsec = timeout->tv_usec * 1000;
917 }
Dave Wallace2a865272018-02-07 21:00:42 -0500918 return ldp_pselect (nfds, readfds, writefds, exceptfds,
919 timeout ? &tspec : NULL, NULL);
Dave Wallace048b1d62018-01-03 22:24:41 -0500920}
921
922#ifdef __USE_XOPEN2K
923int
924pselect (int nfds, fd_set * __restrict readfds,
925 fd_set * __restrict writefds,
926 fd_set * __restrict exceptfds,
927 const struct timespec *__restrict timeout,
928 const __sigset_t * __restrict sigmask)
929{
Dave Wallace2a865272018-02-07 21:00:42 -0500930 return ldp_pselect (nfds, readfds, writefds, exceptfds, timeout, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -0500931}
932#endif
933
Yu Ping7b74b072019-05-08 00:40:24 +0800934/* If transparent TLS mode is turned on, then ldp will load key and cert.
935 */
936static int
Florin Corasa5a9efd2021-01-05 17:03:29 -0800937load_cert_key_pair (void)
Yu Ping7b74b072019-05-08 00:40:24 +0800938{
Florin Corasa5a9efd2021-01-05 17:03:29 -0800939 char *cert_str = getenv (LDP_ENV_TLS_CERT);
940 char *key_str = getenv (LDP_ENV_TLS_KEY);
941 char cert_buf[4096], key_buf[4096];
942 int cert_size, key_size;
943 vppcom_cert_key_pair_t crypto;
944 int ckp_index;
Yu Ping7b74b072019-05-08 00:40:24 +0800945 FILE *fp;
946
Florin Corasa5a9efd2021-01-05 17:03:29 -0800947 if (!cert_str || !key_str)
Yu Ping7b74b072019-05-08 00:40:24 +0800948 {
949 LDBG (0, "ERROR: failed to read LDP environment %s\n",
950 LDP_ENV_TLS_CERT);
951 return -1;
952 }
Florin Corasa5a9efd2021-01-05 17:03:29 -0800953
954 fp = fopen (cert_str, "r");
955 if (fp == NULL)
956 {
957 LDBG (0, "ERROR: failed to open cert file %s \n", cert_str);
958 return -1;
959 }
960 cert_size = fread (cert_buf, sizeof (char), sizeof (cert_buf), fp);
961 fclose (fp);
962
963 fp = fopen (key_str, "r");
964 if (fp == NULL)
965 {
966 LDBG (0, "ERROR: failed to open key file %s \n", key_str);
967 return -1;
968 }
969 key_size = fread (key_buf, sizeof (char), sizeof (key_buf), fp);
970 fclose (fp);
971
972 crypto.cert = cert_buf;
973 crypto.key = key_buf;
974 crypto.cert_len = cert_size;
975 crypto.key_len = key_size;
976 ckp_index = vppcom_add_cert_key_pair (&crypto);
977 if (ckp_index < 0)
978 {
979 LDBG (0, "ERROR: failed to add cert key pair\n");
980 return -1;
981 }
982
983 ldp->ckpair_index = ckp_index;
984
Yu Ping7b74b072019-05-08 00:40:24 +0800985 return 0;
986}
987
988static int
Florin Corasa5a9efd2021-01-05 17:03:29 -0800989assign_cert_key_pair (vls_handle_t vlsh)
Yu Ping7b74b072019-05-08 00:40:24 +0800990{
Florin Corasa5a9efd2021-01-05 17:03:29 -0800991 uint32_t ckp_len;
Yu Ping7b74b072019-05-08 00:40:24 +0800992
Florin Corasa5a9efd2021-01-05 17:03:29 -0800993 if (ldp->ckpair_index == ~0 && load_cert_key_pair () < 0)
994 return -1;
995
996 ckp_len = sizeof (ldp->ckpair_index);
liuyacan276675e2021-08-30 13:24:53 +0800997 return vls_attr (vlsh, VPPCOM_ATTR_SET_CKPAIR, &ldp->ckpair_index, &ckp_len);
Yu Ping7b74b072019-05-08 00:40:24 +0800998}
999
Dave Wallace048b1d62018-01-03 22:24:41 -05001000int
1001socket (int domain, int type, int protocol)
1002{
Florin Coras7baeb712019-01-04 17:05:43 -08001003 int rv, sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
Dave Wallace048b1d62018-01-03 22:24:41 -05001004 u8 is_nonblocking = type & SOCK_NONBLOCK ? 1 : 0;
Florin Coras7baeb712019-01-04 17:05:43 -08001005 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001006
Florin Coras5f33d0d2021-06-02 21:22:21 -07001007 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001008
1009 if (((domain == AF_INET) || (domain == AF_INET6)) &&
1010 ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM)))
1011 {
Yu Ping7b74b072019-05-08 00:40:24 +08001012 u8 proto;
1013 if (ldp->transparent_tls)
1014 {
1015 proto = VPPCOM_PROTO_TLS;
1016 }
1017 else
1018 proto = ((sock_type == SOCK_DGRAM) ?
1019 VPPCOM_PROTO_UDP : VPPCOM_PROTO_TCP);
Dave Wallace048b1d62018-01-03 22:24:41 -05001020
Florin Coras7baeb712019-01-04 17:05:43 -08001021 LDBG (0, "calling vls_create: proto %u (%s), is_nonblocking %u",
1022 proto, vppcom_proto_str (proto), is_nonblocking);
Dave Wallace048b1d62018-01-03 22:24:41 -05001023
Florin Coras7baeb712019-01-04 17:05:43 -08001024 vlsh = vls_create (proto, is_nonblocking);
1025 if (vlsh < 0)
Dave Wallace048b1d62018-01-03 22:24:41 -05001026 {
Florin Coras7baeb712019-01-04 17:05:43 -08001027 errno = -vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001028 rv = -1;
1029 }
1030 else
1031 {
Yu Ping7b74b072019-05-08 00:40:24 +08001032 if (ldp->transparent_tls)
1033 {
Florin Corasa5a9efd2021-01-05 17:03:29 -08001034 if (assign_cert_key_pair (vlsh) < 0)
1035 return -1;
Yu Ping7b74b072019-05-08 00:40:24 +08001036 }
Florin Coras7baeb712019-01-04 17:05:43 -08001037 rv = ldp_vlsh_to_fd (vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05001038 }
1039 }
1040 else
1041 {
Florin Coras7baeb712019-01-04 17:05:43 -08001042 LDBG (0, "calling libc_socket");
Dave Wallace048b1d62018-01-03 22:24:41 -05001043 rv = libc_socket (domain, type, protocol);
1044 }
1045
Dave Wallace048b1d62018-01-03 22:24:41 -05001046 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001047}
1048
1049/*
1050 * Create two new sockets, of type TYPE in domain DOMAIN and using
1051 * protocol PROTOCOL, which are connected to each other, and put file
1052 * descriptors for them in FDS[0] and FDS[1]. If PROTOCOL is zero,
1053 * one will be chosen automatically.
1054 * Returns 0 on success, -1 for errors.
1055 * */
1056int
Dave Wallace048b1d62018-01-03 22:24:41 -05001057socketpair (int domain, int type, int protocol, int fds[2])
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001058{
Florin Coras7baeb712019-01-04 17:05:43 -08001059 int rv, sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
Dave Wallace048b1d62018-01-03 22:24:41 -05001060
Florin Coras5f33d0d2021-06-02 21:22:21 -07001061 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001062
1063 if (((domain == AF_INET) || (domain == AF_INET6)) &&
1064 ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM)))
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001065 {
Florin Coras7baeb712019-01-04 17:05:43 -08001066 LDBG (0, "LDP-TBD");
Dave Wallace048b1d62018-01-03 22:24:41 -05001067 errno = ENOSYS;
1068 rv = -1;
1069 }
1070 else
1071 {
Florin Coras7baeb712019-01-04 17:05:43 -08001072 LDBG (1, "calling libc_socketpair");
Florin Coras173bae32018-11-16 18:56:28 -08001073 rv = libc_socketpair (domain, type, protocol, fds);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001074 }
1075
Dave Wallace048b1d62018-01-03 22:24:41 -05001076 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001077}
1078
1079int
Florin Coras36847942023-02-02 12:56:16 -08001080bind (int fd, __CONST_SOCKADDR_ARG _addr, socklen_t len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001081{
Florin Coras36847942023-02-02 12:56:16 -08001082 const struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
Florin Coras7baeb712019-01-04 17:05:43 -08001083 vls_handle_t vlsh;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001084 int rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001085
Florin Coras5f33d0d2021-06-02 21:22:21 -07001086 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001087
Florin Coras7baeb712019-01-04 17:05:43 -08001088 vlsh = ldp_fd_to_vlsh (fd);
1089 if (vlsh != VLS_INVALID_HANDLE)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001090 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001091 vppcom_endpt_t ep;
1092
Dave Wallace048b1d62018-01-03 22:24:41 -05001093 switch (addr->sa_family)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001094 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001095 case AF_INET:
1096 if (len != sizeof (struct sockaddr_in))
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001097 {
Florin Coras7baeb712019-01-04 17:05:43 -08001098 LDBG (0, "ERROR: fd %d: vlsh %u: Invalid AF_INET addr len %u!",
1099 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001100 errno = EINVAL;
1101 rv = -1;
1102 goto done;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001103 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001104 ep.is_ip4 = VPPCOM_IS_IP4;
1105 ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr;
1106 ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port;
1107 break;
1108
1109 case AF_INET6:
1110 if (len != sizeof (struct sockaddr_in6))
1111 {
Florin Coras7baeb712019-01-04 17:05:43 -08001112 LDBG (0, "ERROR: fd %d: vlsh %u: Invalid AF_INET6 addr len %u!",
1113 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001114 errno = EINVAL;
1115 rv = -1;
1116 goto done;
1117 }
1118 ep.is_ip4 = VPPCOM_IS_IP6;
1119 ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
1120 ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001121 break;
1122
1123 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001124 LDBG (0, "ERROR: fd %d: vlsh %u: Unsupported address family %u!",
1125 fd, vlsh, addr->sa_family);
Dave Wallace048b1d62018-01-03 22:24:41 -05001126 errno = EAFNOSUPPORT;
1127 rv = -1;
1128 goto done;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001129 }
Florin Coras7baeb712019-01-04 17:05:43 -08001130 LDBG (0, "fd %d: calling vls_bind: vlsh %u, addr %p, len %u", fd, vlsh,
1131 addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001132
Florin Coras7baeb712019-01-04 17:05:43 -08001133 rv = vls_bind (vlsh, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001134 if (rv != VPPCOM_OK)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001135 {
1136 errno = -rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001137 rv = -1;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001138 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001139 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001140 else
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001141 {
Florin Coras7baeb712019-01-04 17:05:43 -08001142 LDBG (0, "fd %d: calling libc_bind: addr %p, len %u", fd, addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001143 rv = libc_bind (fd, addr, len);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001144 }
1145
Dave Wallace048b1d62018-01-03 22:24:41 -05001146done:
Florin Coras7baeb712019-01-04 17:05:43 -08001147 LDBG (1, "fd %d: returning %d", fd, rv);
Florin Coras05ecfcc2018-12-12 18:19:39 -08001148
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001149 return rv;
1150}
1151
1152static inline int
Florin Coras36847942023-02-02 12:56:16 -08001153ldp_copy_ep_to_sockaddr (struct sockaddr *addr, socklen_t *__restrict len,
1154 vppcom_endpt_t *ep)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001155{
Florin Coras36847942023-02-02 12:56:16 -08001156 int rv = 0, sa_len, copy_len;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001157
Florin Coras5f33d0d2021-06-02 21:22:21 -07001158 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001159
1160 if (addr && len && ep)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001161 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001162 addr->sa_family = (ep->is_ip4 == VPPCOM_IS_IP4) ? AF_INET : AF_INET6;
1163 switch (addr->sa_family)
1164 {
1165 case AF_INET:
1166 ((struct sockaddr_in *) addr)->sin_port = ep->port;
1167 if (*len > sizeof (struct sockaddr_in))
1168 *len = sizeof (struct sockaddr_in);
1169 sa_len = sizeof (struct sockaddr_in) - sizeof (struct in_addr);
1170 copy_len = *len - sa_len;
1171 if (copy_len > 0)
1172 memcpy (&((struct sockaddr_in *) addr)->sin_addr, ep->ip,
1173 copy_len);
1174 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001175
Dave Wallace048b1d62018-01-03 22:24:41 -05001176 case AF_INET6:
1177 ((struct sockaddr_in6 *) addr)->sin6_port = ep->port;
1178 if (*len > sizeof (struct sockaddr_in6))
1179 *len = sizeof (struct sockaddr_in6);
1180 sa_len = sizeof (struct sockaddr_in6) - sizeof (struct in6_addr);
1181 copy_len = *len - sa_len;
1182 if (copy_len > 0)
1183 memcpy (((struct sockaddr_in6 *) addr)->sin6_addr.
1184 __in6_u.__u6_addr8, ep->ip, copy_len);
1185 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001186
Dave Wallace048b1d62018-01-03 22:24:41 -05001187 default:
1188 /* Not possible */
1189 rv = -EAFNOSUPPORT;
1190 break;
1191 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001192 }
Dave Wallacee695cb42017-11-02 22:04:42 -04001193 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001194}
1195
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001196int
Florin Coras36847942023-02-02 12:56:16 -08001197getsockname (int fd, __SOCKADDR_ARG _addr, socklen_t *__restrict len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001198{
Florin Coras36847942023-02-02 12:56:16 -08001199 struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
Florin Coras7baeb712019-01-04 17:05:43 -08001200 vls_handle_t vlsh;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001201 int rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001202
Florin Coras5f33d0d2021-06-02 21:22:21 -07001203 ldp_init_check ();
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001204
Florin Coras7baeb712019-01-04 17:05:43 -08001205 vlsh = ldp_fd_to_vlsh (fd);
1206 if (vlsh != VLS_INVALID_HANDLE)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001207 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001208 vppcom_endpt_t ep;
1209 u8 addr_buf[sizeof (struct in6_addr)];
1210 u32 size = sizeof (ep);
1211
1212 ep.ip = addr_buf;
Dave Wallace048b1d62018-01-03 22:24:41 -05001213
Florin Coras7baeb712019-01-04 17:05:43 -08001214 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_LCL_ADDR, &ep, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -05001215 if (rv != VPPCOM_OK)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001216 {
1217 errno = -rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001218 rv = -1;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001219 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001220 else
1221 {
Dave Wallace2a865272018-02-07 21:00:42 -05001222 rv = ldp_copy_ep_to_sockaddr (addr, len, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001223 if (rv != VPPCOM_OK)
1224 {
1225 errno = -rv;
1226 rv = -1;
1227 }
1228 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001229 }
1230 else
1231 {
Florin Coras36847942023-02-02 12:56:16 -08001232 rv = libc_getsockname (fd, _addr, len);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001233 }
1234
Dave Wallace048b1d62018-01-03 22:24:41 -05001235 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001236}
1237
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001238int
Florin Coras36847942023-02-02 12:56:16 -08001239connect (int fd, __CONST_SOCKADDR_ARG _addr, socklen_t len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001240{
Florin Coras36847942023-02-02 12:56:16 -08001241 const struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
Florin Coras7baeb712019-01-04 17:05:43 -08001242 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001243 int rv;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001244
Florin Coras5f33d0d2021-06-02 21:22:21 -07001245 ldp_init_check ();
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001246
Dave Wallace048b1d62018-01-03 22:24:41 -05001247 if (!addr)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001248 {
Florin Coras7baeb712019-01-04 17:05:43 -08001249 LDBG (0, "ERROR: fd %d: NULL addr, len %u", fd, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001250 errno = EINVAL;
1251 rv = -1;
1252 goto done;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001253 }
1254
Florin Coras7baeb712019-01-04 17:05:43 -08001255 vlsh = ldp_fd_to_vlsh (fd);
1256 if (vlsh != VLS_INVALID_HANDLE)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001257 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001258 vppcom_endpt_t ep;
1259
Dave Wallace048b1d62018-01-03 22:24:41 -05001260 switch (addr->sa_family)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001261 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001262 case AF_INET:
1263 if (len != sizeof (struct sockaddr_in))
1264 {
Florin Coras7baeb712019-01-04 17:05:43 -08001265 LDBG (0, "fd %d: ERROR vlsh %u: Invalid AF_INET addr len %u!",
1266 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001267 errno = EINVAL;
1268 rv = -1;
1269 goto done;
1270 }
1271 ep.is_ip4 = VPPCOM_IS_IP4;
1272 ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr;
1273 ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port;
1274 break;
1275
1276 case AF_INET6:
1277 if (len != sizeof (struct sockaddr_in6))
1278 {
Florin Coras7baeb712019-01-04 17:05:43 -08001279 LDBG (0, "fd %d: ERROR vlsh %u: Invalid AF_INET6 addr len %u!",
1280 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001281 errno = EINVAL;
1282 rv = -1;
1283 goto done;
1284 }
1285 ep.is_ip4 = VPPCOM_IS_IP6;
1286 ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
1287 ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port;
1288 break;
1289
1290 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001291 LDBG (0, "fd %d: ERROR vlsh %u: Unsupported address family %u!",
1292 fd, vlsh, addr->sa_family);
Dave Wallace048b1d62018-01-03 22:24:41 -05001293 errno = EAFNOSUPPORT;
1294 rv = -1;
1295 goto done;
1296 }
Florin Coras7baeb712019-01-04 17:05:43 -08001297 LDBG (0, "fd %d: calling vls_connect(): vlsh %u addr %p len %u", fd,
1298 vlsh, addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001299
Florin Coras7baeb712019-01-04 17:05:43 -08001300 rv = vls_connect (vlsh, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001301 if (rv != VPPCOM_OK)
1302 {
1303 errno = -rv;
1304 rv = -1;
1305 }
1306 }
1307 else
1308 {
Florin Coras7baeb712019-01-04 17:05:43 -08001309 LDBG (0, "fd %d: calling libc_connect(): addr %p, len %u",
1310 fd, addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001311
1312 rv = libc_connect (fd, addr, len);
1313 }
1314
1315done:
Florin Coras7baeb712019-01-04 17:05:43 -08001316 LDBG (1, "fd %d: returning %d (0x%x)", fd, rv, rv);
Dave Wallace048b1d62018-01-03 22:24:41 -05001317 return rv;
1318}
1319
1320int
Florin Coras36847942023-02-02 12:56:16 -08001321getpeername (int fd, __SOCKADDR_ARG _addr, socklen_t *__restrict len)
Dave Wallace048b1d62018-01-03 22:24:41 -05001322{
Florin Coras36847942023-02-02 12:56:16 -08001323 struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
Florin Coras7baeb712019-01-04 17:05:43 -08001324 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001325 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001326
Florin Coras5f33d0d2021-06-02 21:22:21 -07001327 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001328
Florin Coras7baeb712019-01-04 17:05:43 -08001329 vlsh = ldp_fd_to_vlsh (fd);
1330 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001331 {
1332 vppcom_endpt_t ep;
1333 u8 addr_buf[sizeof (struct in6_addr)];
1334 u32 size = sizeof (ep);
1335
1336 ep.ip = addr_buf;
Florin Coras7baeb712019-01-04 17:05:43 -08001337 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_PEER_ADDR, &ep, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -05001338 if (rv != VPPCOM_OK)
1339 {
1340 errno = -rv;
1341 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001342 }
1343 else
1344 {
Dave Wallace2a865272018-02-07 21:00:42 -05001345 rv = ldp_copy_ep_to_sockaddr (addr, len, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001346 if (rv != VPPCOM_OK)
1347 {
1348 errno = -rv;
1349 rv = -1;
1350 }
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001351 }
1352 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001353 else
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001354 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001355 rv = libc_getpeername (fd, addr, len);
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001356 }
1357
Dave Wallace048b1d62018-01-03 22:24:41 -05001358 return rv;
1359}
1360
1361ssize_t
1362send (int fd, const void *buf, size_t n, int flags)
1363{
Florin Coras7baeb712019-01-04 17:05:43 -08001364 vls_handle_t vlsh = ldp_fd_to_vlsh (fd);
Dave Wallace048b1d62018-01-03 22:24:41 -05001365 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001366
Florin Coras5f33d0d2021-06-02 21:22:21 -07001367 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001368
Florin Coras7baeb712019-01-04 17:05:43 -08001369 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001370 {
Florin Coras7baeb712019-01-04 17:05:43 -08001371 size = vls_sendto (vlsh, (void *) buf, n, flags, NULL);
qchangaa8f63c2018-05-30 11:44:18 -07001372 if (size < VPPCOM_OK)
Dave Wallace048b1d62018-01-03 22:24:41 -05001373 {
1374 errno = -size;
1375 size = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001376 }
1377 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001378 else
1379 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001380 size = libc_send (fd, buf, n, flags);
1381 }
1382
Dave Wallace048b1d62018-01-03 22:24:41 -05001383 return size;
1384}
1385
1386ssize_t
1387sendfile (int out_fd, int in_fd, off_t * offset, size_t len)
1388{
Florin Corasdfe4cf42018-11-28 22:13:45 -08001389 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras7baeb712019-01-04 17:05:43 -08001390 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001391 ssize_t size = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -05001392
Florin Coras5f33d0d2021-06-02 21:22:21 -07001393 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001394
Florin Coras7baeb712019-01-04 17:05:43 -08001395 vlsh = ldp_fd_to_vlsh (out_fd);
1396 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001397 {
1398 int rv;
1399 ssize_t results = 0;
1400 size_t n_bytes_left = len;
1401 size_t bytes_to_read;
1402 int nbytes;
Dave Wallace048b1d62018-01-03 22:24:41 -05001403 u8 eagain = 0;
1404 u32 flags, flags_len = sizeof (flags);
1405
Florin Coras7baeb712019-01-04 17:05:43 -08001406 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_FLAGS, &flags, &flags_len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001407 if (PREDICT_FALSE (rv != VPPCOM_OK))
1408 {
Florin Coras7baeb712019-01-04 17:05:43 -08001409 LDBG (0, "ERROR: out fd %d: vls_attr: vlsh %u, returned %d (%s)!",
1410 out_fd, vlsh, rv, vppcom_retval_str (rv));
Dave Wallace048b1d62018-01-03 22:24:41 -05001411
Florin Corasdfe4cf42018-11-28 22:13:45 -08001412 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001413 errno = -rv;
1414 size = -1;
1415 goto done;
1416 }
1417
1418 if (offset)
1419 {
1420 off_t off = lseek (in_fd, *offset, SEEK_SET);
1421 if (PREDICT_FALSE (off == -1))
1422 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001423 size = -1;
1424 goto done;
1425 }
1426
1427 ASSERT (off == *offset);
1428 }
1429
1430 do
1431 {
Florin Coras7baeb712019-01-04 17:05:43 -08001432 size = vls_attr (vlsh, VPPCOM_ATTR_GET_NWRITE, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05001433 if (size < 0)
1434 {
Florin Coraseb801d02020-09-16 17:44:58 -07001435 LDBG (0, "ERROR: fd %d: vls_attr: vlsh %u returned %ld (%s)!",
Florin Coras7baeb712019-01-04 17:05:43 -08001436 out_fd, vlsh, size, vppcom_retval_str (size));
Florin Corasdfe4cf42018-11-28 22:13:45 -08001437 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001438 errno = -size;
1439 size = -1;
1440 goto done;
1441 }
1442
1443 bytes_to_read = size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001444 if (bytes_to_read == 0)
1445 {
1446 if (flags & O_NONBLOCK)
1447 {
1448 if (!results)
Florin Coras7baeb712019-01-04 17:05:43 -08001449 eagain = 1;
Dave Wallace048b1d62018-01-03 22:24:41 -05001450 goto update_offset;
1451 }
1452 else
1453 continue;
1454 }
1455 bytes_to_read = clib_min (n_bytes_left, bytes_to_read);
Florin Corasdfe4cf42018-11-28 22:13:45 -08001456 vec_validate (ldpw->io_buffer, bytes_to_read);
1457 nbytes = libc_read (in_fd, ldpw->io_buffer, bytes_to_read);
Dave Wallace048b1d62018-01-03 22:24:41 -05001458 if (nbytes < 0)
1459 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001460 if (results == 0)
1461 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08001462 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001463 size = -1;
1464 goto done;
1465 }
1466 goto update_offset;
1467 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001468
Florin Coras7baeb712019-01-04 17:05:43 -08001469 size = vls_write (vlsh, ldpw->io_buffer, nbytes);
Dave Wallace048b1d62018-01-03 22:24:41 -05001470 if (size < 0)
1471 {
1472 if (size == VPPCOM_EAGAIN)
1473 {
1474 if (flags & O_NONBLOCK)
1475 {
1476 if (!results)
Florin Coras7baeb712019-01-04 17:05:43 -08001477 eagain = 1;
Dave Wallace048b1d62018-01-03 22:24:41 -05001478 goto update_offset;
1479 }
1480 else
1481 continue;
1482 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001483 if (results == 0)
1484 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08001485 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001486 errno = -size;
1487 size = -1;
1488 goto done;
1489 }
1490 goto update_offset;
1491 }
1492
1493 results += nbytes;
1494 ASSERT (n_bytes_left >= nbytes);
1495 n_bytes_left = n_bytes_left - nbytes;
1496 }
1497 while (n_bytes_left > 0);
1498
1499 update_offset:
Florin Corasdfe4cf42018-11-28 22:13:45 -08001500 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001501 if (offset)
1502 {
1503 off_t off = lseek (in_fd, *offset, SEEK_SET);
1504 if (PREDICT_FALSE (off == -1))
1505 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001506 size = -1;
1507 goto done;
1508 }
1509
1510 ASSERT (off == *offset);
1511 *offset += results + 1;
1512 }
1513 if (eagain)
1514 {
1515 errno = EAGAIN;
1516 size = -1;
1517 }
1518 else
1519 size = results;
1520 }
1521 else
1522 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001523 size = libc_sendfile (out_fd, in_fd, offset, len);
1524 }
1525
1526done:
Dave Wallace048b1d62018-01-03 22:24:41 -05001527 return size;
1528}
1529
1530ssize_t
1531sendfile64 (int out_fd, int in_fd, off_t * offset, size_t len)
1532{
1533 return sendfile (out_fd, in_fd, offset, len);
1534}
1535
1536ssize_t
1537recv (int fd, void *buf, size_t n, int flags)
1538{
Florin Coras7baeb712019-01-04 17:05:43 -08001539 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001540 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001541
Florin Coras5f33d0d2021-06-02 21:22:21 -07001542 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001543
Florin Coras7baeb712019-01-04 17:05:43 -08001544 vlsh = ldp_fd_to_vlsh (fd);
1545 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001546 {
Florin Coras7baeb712019-01-04 17:05:43 -08001547 size = vls_recvfrom (vlsh, buf, n, flags, NULL);
Dave Wallace048b1d62018-01-03 22:24:41 -05001548 if (size < 0)
Florin Coras2a6642e2020-03-24 15:24:29 +00001549 {
1550 errno = -size;
1551 size = -1;
1552 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001553 }
1554 else
1555 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001556 size = libc_recv (fd, buf, n, flags);
1557 }
1558
Dave Wallace048b1d62018-01-03 22:24:41 -05001559 return size;
1560}
1561
Sivaprasad Tummalafdcbd382021-07-31 21:38:19 +05301562ssize_t
1563__recv_chk (int fd, void *buf, size_t n, size_t buflen, int flags)
1564{
1565 if (n > buflen)
1566 return -1;
1567
1568 return recv (fd, buf, n, flags);
1569}
1570
Dou Chao243a0432022-11-29 19:41:34 +08001571static inline int
1572ldp_vls_sendo (vls_handle_t vlsh, const void *buf, size_t n,
Florin Coraseff5f7a2023-02-07 17:36:17 -08001573 vppcom_endpt_tlv_t *app_tlvs, int flags,
Florin Coras36847942023-02-02 12:56:16 -08001574 __CONST_SOCKADDR_ARG _addr, socklen_t addr_len)
Florin Corasce17f462020-05-22 20:36:29 +00001575{
Florin Coras36847942023-02-02 12:56:16 -08001576 const struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
Florin Corasce17f462020-05-22 20:36:29 +00001577 vppcom_endpt_t *ep = 0;
1578 vppcom_endpt_t _ep;
1579
Florin Coraseff5f7a2023-02-07 17:36:17 -08001580 _ep.app_tlvs = app_tlvs;
Dou Chao243a0432022-11-29 19:41:34 +08001581
Florin Corasce17f462020-05-22 20:36:29 +00001582 if (addr)
1583 {
1584 ep = &_ep;
1585 switch (addr->sa_family)
1586 {
1587 case AF_INET:
1588 ep->is_ip4 = VPPCOM_IS_IP4;
1589 ep->ip =
1590 (uint8_t *) & ((const struct sockaddr_in *) addr)->sin_addr;
1591 ep->port = (uint16_t) ((const struct sockaddr_in *) addr)->sin_port;
1592 break;
1593
1594 case AF_INET6:
1595 ep->is_ip4 = VPPCOM_IS_IP6;
1596 ep->ip =
1597 (uint8_t *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
1598 ep->port =
1599 (uint16_t) ((const struct sockaddr_in6 *) addr)->sin6_port;
1600 break;
1601
1602 default:
1603 return EAFNOSUPPORT;
1604 }
1605 }
1606
1607 return vls_sendto (vlsh, (void *) buf, n, flags, ep);
1608}
1609
1610static int
Florin Coras36847942023-02-02 12:56:16 -08001611ldp_vls_recvfrom (vls_handle_t vlsh, void *__restrict buf, size_t n, int flags,
1612 __SOCKADDR_ARG _addr, socklen_t *__restrict addr_len)
Florin Corasce17f462020-05-22 20:36:29 +00001613{
1614 u8 src_addr[sizeof (struct sockaddr_in6)];
Florin Coras36847942023-02-02 12:56:16 -08001615 struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
Florin Corasce17f462020-05-22 20:36:29 +00001616 vppcom_endpt_t ep;
1617 ssize_t size;
1618 int rv;
1619
1620 if (addr)
1621 {
1622 ep.ip = src_addr;
1623 size = vls_recvfrom (vlsh, buf, n, flags, &ep);
1624
1625 if (size > 0)
1626 {
1627 rv = ldp_copy_ep_to_sockaddr (addr, addr_len, &ep);
1628 if (rv < 0)
1629 size = rv;
1630 }
1631 }
1632 else
1633 size = vls_recvfrom (vlsh, buf, n, flags, NULL);
1634
1635 return size;
1636}
1637
Dave Wallace048b1d62018-01-03 22:24:41 -05001638ssize_t
1639sendto (int fd, const void *buf, size_t n, int flags,
Florin Coras36847942023-02-02 12:56:16 -08001640 __CONST_SOCKADDR_ARG _addr, socklen_t addr_len)
Dave Wallace048b1d62018-01-03 22:24:41 -05001641{
Florin Coras36847942023-02-02 12:56:16 -08001642 const struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
Florin Coras7baeb712019-01-04 17:05:43 -08001643 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001644 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001645
Florin Coras5f33d0d2021-06-02 21:22:21 -07001646 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001647
Florin Coras7baeb712019-01-04 17:05:43 -08001648 vlsh = ldp_fd_to_vlsh (fd);
wanghanlin97c6e0d2021-07-06 15:01:48 +08001649 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001650 {
Dou Chao243a0432022-11-29 19:41:34 +08001651 size = ldp_vls_sendo (vlsh, buf, n, NULL, flags, addr, addr_len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001652 if (size < 0)
1653 {
1654 errno = -size;
1655 size = -1;
1656 }
1657 }
1658 else
1659 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001660 size = libc_sendto (fd, buf, n, flags, addr, addr_len);
1661 }
1662
Dave Wallace048b1d62018-01-03 22:24:41 -05001663 return size;
1664}
1665
1666ssize_t
1667recvfrom (int fd, void *__restrict buf, size_t n, int flags,
1668 __SOCKADDR_ARG addr, socklen_t * __restrict addr_len)
1669{
Florin Corasce17f462020-05-22 20:36:29 +00001670 vls_handle_t vlsh;
1671 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001672
Florin Coras5f33d0d2021-06-02 21:22:21 -07001673 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001674
Florin Corasce17f462020-05-22 20:36:29 +00001675 vlsh = ldp_fd_to_vlsh (fd);
1676 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001677 {
Florin Corasce17f462020-05-22 20:36:29 +00001678 size = ldp_vls_recvfrom (vlsh, buf, n, flags, addr, addr_len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001679 if (size < 0)
1680 {
1681 errno = -size;
1682 size = -1;
1683 }
1684 }
1685 else
1686 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001687 size = libc_recvfrom (fd, buf, n, flags, addr, addr_len);
1688 }
1689
Dave Wallace048b1d62018-01-03 22:24:41 -05001690 return size;
1691}
1692
Florin Coraseff5f7a2023-02-07 17:36:17 -08001693static int
1694ldp_parse_cmsg (vls_handle_t vlsh, const struct msghdr *msg,
1695 vppcom_endpt_tlv_t **app_tlvs)
1696{
1697 uint8_t *ad, *at = (uint8_t *) *app_tlvs;
1698 vppcom_endpt_tlv_t *adh;
1699 struct in_pktinfo *pi;
1700 struct cmsghdr *cmsg;
1701
1702 cmsg = CMSG_FIRSTHDR (msg);
1703
1704 while (cmsg != NULL)
1705 {
1706 switch (cmsg->cmsg_level)
1707 {
1708 case SOL_UDP:
1709 switch (cmsg->cmsg_type)
1710 {
1711 case UDP_SEGMENT:
1712 vec_add2 (at, adh, sizeof (*adh));
1713 adh->data_type = VCL_UDP_SEGMENT;
1714 adh->data_len = sizeof (uint16_t);
1715 vec_add2 (at, ad, sizeof (uint16_t));
1716 *(uint16_t *) ad = *(uint16_t *) CMSG_DATA (cmsg);
1717 break;
1718 default:
1719 LDBG (1, "SOL_UDP cmsg_type %u not supported", cmsg->cmsg_type);
1720 break;
1721 }
1722 break;
1723 case SOL_IP:
1724 switch (cmsg->cmsg_type)
1725 {
1726 case IP_PKTINFO:
1727 vec_add2 (at, adh, sizeof (*adh));
1728 adh->data_type = VCL_IP_PKTINFO;
1729 adh->data_len = sizeof (struct in_addr);
1730 vec_add2 (at, ad, sizeof (struct in_addr));
1731 pi = (void *) CMSG_DATA (cmsg);
1732 clib_memcpy_fast (ad, &pi->ipi_spec_dst,
1733 sizeof (struct in_addr));
1734 break;
1735 default:
1736 LDBG (1, "SOL_IP cmsg_type %u not supported", cmsg->cmsg_type);
1737 break;
1738 }
1739 break;
1740 default:
1741 LDBG (1, "cmsg_level %u not supported", cmsg->cmsg_level);
1742 break;
1743 }
1744 cmsg = CMSG_NXTHDR ((struct msghdr *) msg, cmsg);
1745 }
1746 *app_tlvs = (vppcom_endpt_tlv_t *) at;
1747 return 0;
1748}
1749
1750static int
1751ldp_make_cmsg (vls_handle_t vlsh, struct msghdr *msg)
1752{
1753 u32 optval, optlen = sizeof (optval);
1754 struct cmsghdr *cmsg;
1755
1756 cmsg = CMSG_FIRSTHDR (msg);
Steven Luong2da272e2023-07-18 23:25:15 -07001757 memset (cmsg, 0, sizeof (*cmsg));
Florin Coraseff5f7a2023-02-07 17:36:17 -08001758
1759 if (!vls_attr (vlsh, VPPCOM_ATTR_GET_IP_PKTINFO, (void *) &optval, &optlen))
1760 return 0;
1761
1762 if (optval)
1763 {
1764 vppcom_endpt_t ep;
1765 u8 addr_buf[sizeof (struct in_addr)];
1766 u32 size = sizeof (ep);
1767
1768 ep.ip = addr_buf;
1769
1770 if (!vls_attr (vlsh, VPPCOM_ATTR_GET_LCL_ADDR, &ep, &size))
1771 {
1772 struct in_pktinfo pi = {};
1773
1774 clib_memcpy (&pi.ipi_addr, ep.ip, sizeof (struct in_addr));
1775 cmsg->cmsg_level = SOL_IP;
1776 cmsg->cmsg_type = IP_PKTINFO;
1777 cmsg->cmsg_len = CMSG_LEN (sizeof (pi));
1778 clib_memcpy (CMSG_DATA (cmsg), &pi, sizeof (pi));
1779 }
1780 }
1781
1782 return 0;
1783}
1784
Dave Wallace048b1d62018-01-03 22:24:41 -05001785ssize_t
Florin Corasce17f462020-05-22 20:36:29 +00001786sendmsg (int fd, const struct msghdr * msg, int flags)
Dave Wallace048b1d62018-01-03 22:24:41 -05001787{
Florin Coras7baeb712019-01-04 17:05:43 -08001788 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001789 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001790
Florin Coras5f33d0d2021-06-02 21:22:21 -07001791 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001792
Florin Coras7baeb712019-01-04 17:05:43 -08001793 vlsh = ldp_fd_to_vlsh (fd);
1794 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001795 {
Florin Coraseff5f7a2023-02-07 17:36:17 -08001796 vppcom_endpt_tlv_t *app_tlvs = 0;
Florin Corasce17f462020-05-22 20:36:29 +00001797 struct iovec *iov = msg->msg_iov;
1798 ssize_t total = 0;
Florin Corascba1c222021-11-29 08:12:27 -08001799 int i, rv = 0;
Dou Chao243a0432022-11-29 19:41:34 +08001800
Florin Coraseff5f7a2023-02-07 17:36:17 -08001801 ldp_parse_cmsg (vlsh, msg, &app_tlvs);
Florin Corasce17f462020-05-22 20:36:29 +00001802
1803 for (i = 0; i < msg->msg_iovlen; ++i)
1804 {
Florin Coraseff5f7a2023-02-07 17:36:17 -08001805 rv = ldp_vls_sendo (vlsh, iov[i].iov_base, iov[i].iov_len, app_tlvs,
1806 flags, msg->msg_name, msg->msg_namelen);
Florin Corasce17f462020-05-22 20:36:29 +00001807 if (rv < 0)
1808 break;
1809 else
1810 {
1811 total += rv;
1812 if (rv < iov[i].iov_len)
1813 break;
1814 }
1815 }
1816
Florin Coraseff5f7a2023-02-07 17:36:17 -08001817 vec_free (app_tlvs);
1818
Florin Corasce17f462020-05-22 20:36:29 +00001819 if (rv < 0 && total == 0)
1820 {
1821 errno = -rv;
1822 size = -1;
1823 }
1824 else
1825 size = total;
Dave Wallace048b1d62018-01-03 22:24:41 -05001826 }
1827 else
1828 {
Florin Corasce17f462020-05-22 20:36:29 +00001829 size = libc_sendmsg (fd, msg, flags);
Dave Wallace048b1d62018-01-03 22:24:41 -05001830 }
1831
Dave Wallace048b1d62018-01-03 22:24:41 -05001832 return size;
1833}
1834
Florin Coras36847942023-02-02 12:56:16 -08001835#ifdef _GNU_SOURCE
Dave Wallace048b1d62018-01-03 22:24:41 -05001836int
1837sendmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags)
1838{
1839 ssize_t size;
1840 const char *func_str;
Florin Coras7baeb712019-01-04 17:05:43 -08001841 u32 sh = ldp_fd_to_vlsh (fd);
Dave Wallace048b1d62018-01-03 22:24:41 -05001842
Florin Coras5f33d0d2021-06-02 21:22:21 -07001843 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001844
wanghanlin97c6e0d2021-07-06 15:01:48 +08001845 if (sh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001846 {
1847 clib_warning ("LDP<%d>: LDP-TBD", getpid ());
1848 errno = ENOSYS;
1849 size = -1;
1850 }
1851 else
1852 {
1853 func_str = "libc_sendmmsg";
1854
Dave Wallace2a865272018-02-07 21:00:42 -05001855 if (LDP_DEBUG > 2)
Dave Wallace048b1d62018-01-03 22:24:41 -05001856 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1857 "vmessages %p, vlen %u, flags 0x%x",
1858 getpid (), fd, fd, func_str, vmessages, vlen, flags);
1859
1860 size = libc_sendmmsg (fd, vmessages, vlen, flags);
1861 }
1862
Dave Wallace2a865272018-02-07 21:00:42 -05001863 if (LDP_DEBUG > 2)
Dave Wallace048b1d62018-01-03 22:24:41 -05001864 {
1865 if (size < 0)
1866 {
1867 int errno_val = errno;
Dave Wallace048b1d62018-01-03 22:24:41 -05001868 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1869 "rv %d, errno = %d", getpid (), fd, fd,
1870 func_str, size, errno_val);
1871 errno = errno_val;
1872 }
1873 else
1874 clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1875 getpid (), fd, fd, size, size);
1876 }
1877 return size;
1878}
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001879#endif
1880
Dave Wallace048b1d62018-01-03 22:24:41 -05001881ssize_t
Florin Corasce17f462020-05-22 20:36:29 +00001882recvmsg (int fd, struct msghdr * msg, int flags)
Dave Wallace048b1d62018-01-03 22:24:41 -05001883{
Florin Coras7baeb712019-01-04 17:05:43 -08001884 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001885 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001886
Florin Coras5f33d0d2021-06-02 21:22:21 -07001887 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001888
Florin Coras7baeb712019-01-04 17:05:43 -08001889 vlsh = ldp_fd_to_vlsh (fd);
1890 if (vlsh != VLS_INVALID_HANDLE)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001891 {
Florin Corasce17f462020-05-22 20:36:29 +00001892 struct iovec *iov = msg->msg_iov;
1893 ssize_t max_deq, total = 0;
Jieqiang Wang76d14b72023-07-24 16:52:06 +08001894 int i, rv = 0;
Florin Corasce17f462020-05-22 20:36:29 +00001895
1896 max_deq = vls_attr (vlsh, VPPCOM_ATTR_GET_NREAD, 0, 0);
1897 if (!max_deq)
1898 return 0;
1899
1900 for (i = 0; i < msg->msg_iovlen; i++)
1901 {
1902 rv = ldp_vls_recvfrom (vlsh, iov[i].iov_base, iov[i].iov_len, flags,
1903 (i == 0 ? msg->msg_name : NULL),
1904 (i == 0 ? &msg->msg_namelen : NULL));
1905 if (rv <= 0)
1906 break;
1907 else
1908 {
1909 total += rv;
1910 if (rv < iov[i].iov_len)
1911 break;
1912 }
1913 if (total >= max_deq)
1914 break;
1915 }
1916
1917 if (rv < 0 && total == 0)
1918 {
1919 errno = -rv;
1920 size = -1;
1921 }
1922 else
Florin Coraseff5f7a2023-02-07 17:36:17 -08001923 {
1924 if (msg->msg_controllen)
1925 ldp_make_cmsg (vlsh, msg);
1926 size = total;
1927 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001928 }
1929 else
1930 {
Florin Corasce17f462020-05-22 20:36:29 +00001931 size = libc_recvmsg (fd, msg, flags);
Dave Wallace048b1d62018-01-03 22:24:41 -05001932 }
1933
Dave Wallace048b1d62018-01-03 22:24:41 -05001934 return size;
1935}
1936
Florin Coras36847942023-02-02 12:56:16 -08001937#ifdef _GNU_SOURCE
Dave Wallace048b1d62018-01-03 22:24:41 -05001938int
1939recvmmsg (int fd, struct mmsghdr *vmessages,
1940 unsigned int vlen, int flags, struct timespec *tmo)
1941{
Florin Corasf1a232f2023-02-02 22:56:03 -08001942 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
1943 u32 sh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001944
Florin Coras5f33d0d2021-06-02 21:22:21 -07001945 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001946
Florin Corasf1a232f2023-02-02 22:56:03 -08001947 sh = ldp_fd_to_vlsh (fd);
1948
wanghanlin97c6e0d2021-07-06 15:01:48 +08001949 if (sh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001950 {
Florin Corasf1a232f2023-02-02 22:56:03 -08001951 struct mmsghdr *mh;
1952 ssize_t rv = 0;
1953 u32 nvecs = 0;
1954 f64 time_out;
1955
1956 if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
1957 clib_time_init (&ldpw->clib_time);
1958 if (tmo)
1959 {
1960 time_out = (f64) tmo->tv_sec + (f64) tmo->tv_nsec / (f64) 1e9;
1961 time_out += clib_time_now (&ldpw->clib_time);
1962 }
1963 else
1964 {
1965 time_out = (f64) ~0;
1966 }
1967
1968 while (nvecs < vlen)
1969 {
1970 mh = &vmessages[nvecs];
1971 rv = recvmsg (fd, &mh->msg_hdr, flags);
1972 if (rv > 0)
1973 {
1974 mh->msg_len = rv;
1975 nvecs += 1;
1976 continue;
1977 }
1978
1979 if (!time_out || clib_time_now (&ldpw->clib_time) >= time_out)
1980 break;
1981
1982 usleep (1);
1983 }
1984
1985 return nvecs > 0 ? nvecs : rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001986 }
1987 else
1988 {
Florin Corasf1a232f2023-02-02 22:56:03 -08001989 return libc_recvmmsg (fd, vmessages, vlen, flags, tmo);
Dave Wallace048b1d62018-01-03 22:24:41 -05001990 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001991}
1992#endif
1993
1994int
1995getsockopt (int fd, int level, int optname,
1996 void *__restrict optval, socklen_t * __restrict optlen)
1997{
Florin Coras7baeb712019-01-04 17:05:43 -08001998 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001999 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05002000
Florin Coras5f33d0d2021-06-02 21:22:21 -07002001 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05002002
Florin Coras7baeb712019-01-04 17:05:43 -08002003 vlsh = ldp_fd_to_vlsh (fd);
2004 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05002005 {
2006 rv = -EOPNOTSUPP;
2007
2008 switch (level)
2009 {
2010 case SOL_TCP:
2011 switch (optname)
2012 {
2013 case TCP_NODELAY:
Florin Coras7baeb712019-01-04 17:05:43 -08002014 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_NODELAY,
2015 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002016 break;
2017 case TCP_MAXSEG:
Florin Coras7baeb712019-01-04 17:05:43 -08002018 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_USER_MSS,
2019 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002020 break;
2021 case TCP_KEEPIDLE:
Florin Coras7baeb712019-01-04 17:05:43 -08002022 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_KEEPIDLE,
2023 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002024 break;
2025 case TCP_KEEPINTVL:
Florin Coras7baeb712019-01-04 17:05:43 -08002026 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_KEEPINTVL,
2027 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002028 break;
2029 case TCP_INFO:
2030 if (optval && optlen && (*optlen == sizeof (struct tcp_info)))
2031 {
Florin Coras7baeb712019-01-04 17:05:43 -08002032 LDBG (1, "fd %d: vlsh %u SOL_TCP, TCP_INFO, optval %p, "
2033 "optlen %d: #LDP-NOP#", fd, vlsh, optval, *optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002034 memset (optval, 0, *optlen);
2035 rv = VPPCOM_OK;
2036 }
2037 else
2038 rv = -EFAULT;
2039 break;
Florin Coras0ed24e92019-01-21 09:03:10 -08002040 case TCP_CONGESTION:
Florin Coras0ed24e92019-01-21 09:03:10 -08002041 *optlen = strlen ("cubic");
Dave Barach02500902020-04-04 18:34:41 -04002042 strncpy (optval, "cubic", *optlen + 1);
Florin Coras0ed24e92019-01-21 09:03:10 -08002043 rv = 0;
2044 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05002045 default:
Florin Coras7baeb712019-01-04 17:05:43 -08002046 LDBG (0, "ERROR: fd %d: getsockopt SOL_TCP: sid %u, "
2047 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05002048 break;
2049 }
2050 break;
qinyangaf9b7152023-06-27 01:11:53 -07002051 case SOL_IP:
2052 switch (optname)
2053 {
2054 case SO_ORIGINAL_DST:
2055 rv =
2056 vls_attr (vlsh, VPPCOM_ATTR_GET_ORIGINAL_DST, optval, optlen);
2057 break;
2058 default:
2059 LDBG (0,
2060 "ERROR: fd %d: getsockopt SOL_IP: vlsh %u "
2061 "optname %d unsupported!",
2062 fd, vlsh, optname);
2063 break;
2064 }
2065 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05002066 case SOL_IPV6:
2067 switch (optname)
2068 {
2069 case IPV6_V6ONLY:
Florin Coras7baeb712019-01-04 17:05:43 -08002070 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_V6ONLY, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002071 break;
2072 default:
Florin Coras7baeb712019-01-04 17:05:43 -08002073 LDBG (0, "ERROR: fd %d: getsockopt SOL_IPV6: vlsh %u "
2074 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05002075 break;
2076 }
2077 break;
2078 case SOL_SOCKET:
2079 switch (optname)
2080 {
2081 case SO_ACCEPTCONN:
Florin Coras7baeb712019-01-04 17:05:43 -08002082 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_LISTEN, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002083 break;
2084 case SO_KEEPALIVE:
Florin Coras7baeb712019-01-04 17:05:43 -08002085 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_KEEPALIVE, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002086 break;
2087 case SO_PROTOCOL:
Florin Coras7baeb712019-01-04 17:05:43 -08002088 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_PROTOCOL, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002089 *(int *) optval = *(int *) optval ? SOCK_DGRAM : SOCK_STREAM;
2090 break;
2091 case SO_SNDBUF:
Florin Coras7baeb712019-01-04 17:05:43 -08002092 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TX_FIFO_LEN,
2093 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002094 break;
2095 case SO_RCVBUF:
Florin Coras7baeb712019-01-04 17:05:43 -08002096 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_RX_FIFO_LEN,
2097 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002098 break;
2099 case SO_REUSEADDR:
Florin Coras7baeb712019-01-04 17:05:43 -08002100 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_REUSEADDR, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002101 break;
wanghanlin0674f852021-02-22 10:38:36 +08002102 case SO_REUSEPORT:
2103 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_REUSEPORT, optval, optlen);
2104 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05002105 case SO_BROADCAST:
Florin Coras7baeb712019-01-04 17:05:43 -08002106 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_BROADCAST, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002107 break;
wanghanlin0674f852021-02-22 10:38:36 +08002108 case SO_DOMAIN:
2109 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_DOMAIN, optval, optlen);
2110 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05002111 case SO_ERROR:
Florin Coras7baeb712019-01-04 17:05:43 -08002112 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_ERROR, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002113 break;
Florin Coras8eb8d502021-06-16 14:46:57 -07002114 case SO_BINDTODEVICE:
2115 rv = 0;
2116 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05002117 default:
Florin Coras7baeb712019-01-04 17:05:43 -08002118 LDBG (0, "ERROR: fd %d: getsockopt SOL_SOCKET: vlsh %u "
2119 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05002120 break;
2121 }
2122 break;
2123 default:
2124 break;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002125 }
2126
Dave Wallace048b1d62018-01-03 22:24:41 -05002127 if (rv != VPPCOM_OK)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002128 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002129 errno = -rv;
2130 rv = -1;
2131 }
2132 }
2133 else
2134 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002135 rv = libc_getsockopt (fd, level, optname, optval, optlen);
2136 }
2137
Dave Wallace048b1d62018-01-03 22:24:41 -05002138 return rv;
2139}
2140
2141int
2142setsockopt (int fd, int level, int optname,
2143 const void *optval, socklen_t optlen)
2144{
Florin Coras7baeb712019-01-04 17:05:43 -08002145 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002146 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05002147
Florin Coras5f33d0d2021-06-02 21:22:21 -07002148 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05002149
Florin Coras7baeb712019-01-04 17:05:43 -08002150 vlsh = ldp_fd_to_vlsh (fd);
2151 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05002152 {
2153 rv = -EOPNOTSUPP;
2154
2155 switch (level)
2156 {
2157 case SOL_TCP:
2158 switch (optname)
2159 {
2160 case TCP_NODELAY:
Florin Coras7baeb712019-01-04 17:05:43 -08002161 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_NODELAY,
2162 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002163 break;
2164 case TCP_MAXSEG:
Florin Coras7baeb712019-01-04 17:05:43 -08002165 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_USER_MSS,
2166 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002167 break;
2168 case TCP_KEEPIDLE:
Florin Coras7baeb712019-01-04 17:05:43 -08002169 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_KEEPIDLE,
2170 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002171 break;
2172 case TCP_KEEPINTVL:
Florin Coras7baeb712019-01-04 17:05:43 -08002173 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_KEEPINTVL,
2174 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002175 break;
Florin Coras0ed24e92019-01-21 09:03:10 -08002176 case TCP_CONGESTION:
Florin Coras8509aa22019-04-04 12:55:30 -07002177 case TCP_CORK:
Florin Coras0ed24e92019-01-21 09:03:10 -08002178 /* Ignore */
2179 rv = 0;
2180 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05002181 default:
Florin Coras7baeb712019-01-04 17:05:43 -08002182 LDBG (0, "ERROR: fd %d: setsockopt() SOL_TCP: vlsh %u"
2183 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05002184 break;
2185 }
2186 break;
2187 case SOL_IPV6:
2188 switch (optname)
2189 {
2190 case IPV6_V6ONLY:
Florin Coras7baeb712019-01-04 17:05:43 -08002191 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_V6ONLY,
2192 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002193 break;
2194 default:
Florin Coras7baeb712019-01-04 17:05:43 -08002195 LDBG (0, "ERROR: fd %d: setsockopt SOL_IPV6: vlsh %u"
2196 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05002197 break;
2198 }
2199 break;
2200 case SOL_SOCKET:
2201 switch (optname)
2202 {
2203 case SO_KEEPALIVE:
Florin Coras7baeb712019-01-04 17:05:43 -08002204 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_KEEPALIVE,
2205 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002206 break;
2207 case SO_REUSEADDR:
Florin Coras7baeb712019-01-04 17:05:43 -08002208 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_REUSEADDR,
2209 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002210 break;
wanghanlin0674f852021-02-22 10:38:36 +08002211 case SO_REUSEPORT:
2212 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_REUSEPORT, (void *) optval,
2213 &optlen);
2214 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05002215 case SO_BROADCAST:
Florin Coras7baeb712019-01-04 17:05:43 -08002216 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_BROADCAST,
2217 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002218 break;
Florin Coras2f647902021-06-02 08:23:50 -07002219 case SO_LINGER:
2220 rv = 0;
2221 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05002222 default:
Florin Coras7baeb712019-01-04 17:05:43 -08002223 LDBG (0, "ERROR: fd %d: setsockopt SOL_SOCKET: vlsh %u "
2224 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05002225 break;
2226 }
2227 break;
Florin Coraseff5f7a2023-02-07 17:36:17 -08002228 case SOL_IP:
2229 switch (optname)
2230 {
2231 case IP_PKTINFO:
2232 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_IP_PKTINFO, (void *) optval,
2233 &optlen);
2234 break;
2235 default:
2236 LDBG (0,
2237 "ERROR: fd %d: setsockopt SOL_IP: vlsh %u optname %d"
2238 "unsupported!",
2239 fd, vlsh, optname);
2240 break;
2241 }
2242 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05002243 default:
2244 break;
2245 }
2246
2247 if (rv != VPPCOM_OK)
2248 {
2249 errno = -rv;
2250 rv = -1;
2251 }
2252 }
2253 else
2254 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002255 rv = libc_setsockopt (fd, level, optname, optval, optlen);
2256 }
2257
Dave Wallace048b1d62018-01-03 22:24:41 -05002258 return rv;
2259}
2260
2261int
2262listen (int fd, int n)
2263{
Florin Coras7baeb712019-01-04 17:05:43 -08002264 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002265 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05002266
Florin Coras5f33d0d2021-06-02 21:22:21 -07002267 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05002268
Florin Coras7baeb712019-01-04 17:05:43 -08002269 vlsh = ldp_fd_to_vlsh (fd);
2270 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05002271 {
Florin Coras7baeb712019-01-04 17:05:43 -08002272 LDBG (0, "fd %d: calling vls_listen: vlsh %u, n %d", fd, vlsh, n);
Dave Wallace048b1d62018-01-03 22:24:41 -05002273
Florin Coras7baeb712019-01-04 17:05:43 -08002274 rv = vls_listen (vlsh, n);
Dave Wallace048b1d62018-01-03 22:24:41 -05002275 if (rv != VPPCOM_OK)
2276 {
2277 errno = -rv;
2278 rv = -1;
2279 }
2280 }
2281 else
2282 {
Florin Coras7baeb712019-01-04 17:05:43 -08002283 LDBG (0, "fd %d: calling libc_listen(): n %d", fd, n);
Dave Wallace048b1d62018-01-03 22:24:41 -05002284 rv = libc_listen (fd, n);
2285 }
2286
Florin Coras7baeb712019-01-04 17:05:43 -08002287 LDBG (1, "fd %d: returning %d", fd, rv);
Dave Wallace048b1d62018-01-03 22:24:41 -05002288 return rv;
2289}
2290
2291static inline int
Florin Coras36847942023-02-02 12:56:16 -08002292ldp_accept4 (int listen_fd, __SOCKADDR_ARG _addr,
2293 socklen_t *__restrict addr_len, int flags)
Dave Wallace048b1d62018-01-03 22:24:41 -05002294{
Florin Coras36847942023-02-02 12:56:16 -08002295 struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
Florin Coras7baeb712019-01-04 17:05:43 -08002296 vls_handle_t listen_vlsh, accept_vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002297 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05002298
Florin Coras5f33d0d2021-06-02 21:22:21 -07002299 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05002300
Florin Coras7baeb712019-01-04 17:05:43 -08002301 listen_vlsh = ldp_fd_to_vlsh (listen_fd);
2302 if (listen_vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05002303 {
2304 vppcom_endpt_t ep;
2305 u8 src_addr[sizeof (struct sockaddr_in6)];
Dave Wallace8aaba562018-01-18 17:21:19 -05002306 memset (&ep, 0, sizeof (ep));
Dave Wallace048b1d62018-01-03 22:24:41 -05002307 ep.ip = src_addr;
2308
Florin Coras7baeb712019-01-04 17:05:43 -08002309 LDBG (0, "listen fd %d: calling vppcom_session_accept: listen sid %u,"
Florin Coraseb801d02020-09-16 17:44:58 -07002310 " ep %p, flags 0x%x", listen_fd, listen_vlsh, &ep, flags);
Dave Wallace048b1d62018-01-03 22:24:41 -05002311
Florin Coras7baeb712019-01-04 17:05:43 -08002312 accept_vlsh = vls_accept (listen_vlsh, &ep, flags);
2313 if (accept_vlsh < 0)
Dave Wallace048b1d62018-01-03 22:24:41 -05002314 {
Florin Coras7baeb712019-01-04 17:05:43 -08002315 errno = -accept_vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002316 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002317 }
2318 else
2319 {
Dave Wallace2a865272018-02-07 21:00:42 -05002320 rv = ldp_copy_ep_to_sockaddr (addr, addr_len, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05002321 if (rv != VPPCOM_OK)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002322 {
Florin Coras7baeb712019-01-04 17:05:43 -08002323 (void) vls_close (accept_vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05002324 errno = -rv;
2325 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002326 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002327 else
2328 {
Florin Coras7baeb712019-01-04 17:05:43 -08002329 rv = ldp_vlsh_to_fd (accept_vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05002330 }
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002331 }
2332 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002333 else
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002334 {
Florin Coras7baeb712019-01-04 17:05:43 -08002335 LDBG (0, "listen fd %d: calling libc_accept4(): addr %p, addr_len %p,"
2336 " flags 0x%x", listen_fd, addr, addr_len, flags);
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002337
Dave Wallace048b1d62018-01-03 22:24:41 -05002338 rv = libc_accept4 (listen_fd, addr, addr_len, flags);
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002339 }
2340
Florin Coras7baeb712019-01-04 17:05:43 -08002341 LDBG (1, "listen fd %d: accept returning %d", listen_fd, rv);
Florin Coras05ecfcc2018-12-12 18:19:39 -08002342
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002343 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002344}
2345
Dave Wallace048b1d62018-01-03 22:24:41 -05002346int
2347accept4 (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len,
2348 int flags)
2349{
Dave Wallace2a865272018-02-07 21:00:42 -05002350 return ldp_accept4 (fd, addr, addr_len, flags);
Dave Wallace048b1d62018-01-03 22:24:41 -05002351}
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002352
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002353int
Dave Wallace048b1d62018-01-03 22:24:41 -05002354accept (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002355{
Dave Wallace2a865272018-02-07 21:00:42 -05002356 return ldp_accept4 (fd, addr, addr_len, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002357}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002358
Dave Wallace048b1d62018-01-03 22:24:41 -05002359int
2360shutdown (int fd, int how)
2361{
Florin Coras7baeb712019-01-04 17:05:43 -08002362 vls_handle_t vlsh;
liuyacan55c952e2021-06-13 14:54:55 +08002363 int rv = 0;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002364
Florin Coras5f33d0d2021-06-02 21:22:21 -07002365 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05002366
Florin Coras7baeb712019-01-04 17:05:43 -08002367 vlsh = ldp_fd_to_vlsh (fd);
2368 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05002369 {
Florin Coras7baeb712019-01-04 17:05:43 -08002370 LDBG (0, "called shutdown: fd %u vlsh %u how %d", fd, vlsh, how);
liuyacan55c952e2021-06-13 14:54:55 +08002371 rv = vls_shutdown (vlsh, how);
Dave Wallace048b1d62018-01-03 22:24:41 -05002372 }
2373 else
2374 {
Florin Coras7baeb712019-01-04 17:05:43 -08002375 LDBG (0, "fd %d: calling libc_shutdown: how %d", fd, how);
Dave Wallace048b1d62018-01-03 22:24:41 -05002376 rv = libc_shutdown (fd, how);
2377 }
2378
Dave Wallace048b1d62018-01-03 22:24:41 -05002379 return rv;
2380}
2381
2382int
2383epoll_create1 (int flags)
2384{
Florin Corasdfe4cf42018-11-28 22:13:45 -08002385 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras7baeb712019-01-04 17:05:43 -08002386 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002387 int rv;
2388
Florin Coras5f33d0d2021-06-02 21:22:21 -07002389 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05002390
hanlina3a48962020-07-13 11:09:15 +08002391 if (ldp->vcl_needs_real_epoll || vls_use_real_epoll ())
Florin Coras99368312018-08-02 10:45:44 -07002392 {
Florin Coras2d9b4272019-03-11 10:14:37 -07002393 /* Make sure workers have been allocated */
2394 if (!ldp->workers)
2395 {
2396 ldp_alloc_workers ();
2397 ldpw = ldp_worker_get_current ();
2398 }
Florin Coras99368312018-08-02 10:45:44 -07002399 rv = libc_epoll_create1 (flags);
2400 ldp->vcl_needs_real_epoll = 0;
Florin Corasdfe4cf42018-11-28 22:13:45 -08002401 ldpw->vcl_mq_epfd = rv;
Florin Coras05ecfcc2018-12-12 18:19:39 -08002402 LDBG (0, "created vcl epfd %u", rv);
Florin Coras99368312018-08-02 10:45:44 -07002403 return rv;
2404 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002405
Florin Coras7baeb712019-01-04 17:05:43 -08002406 vlsh = vls_epoll_create ();
2407 if (PREDICT_FALSE (vlsh == VLS_INVALID_HANDLE))
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002408 {
Florin Coras7baeb712019-01-04 17:05:43 -08002409 errno = -vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002410 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002411 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002412 else
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002413 {
Florin Coras7baeb712019-01-04 17:05:43 -08002414 rv = ldp_vlsh_to_fd (vlsh);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002415 }
Florin Coras7baeb712019-01-04 17:05:43 -08002416 LDBG (0, "epoll_create epfd %u vlsh %u", rv, vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05002417 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002418}
2419
2420int
Dave Wallace048b1d62018-01-03 22:24:41 -05002421epoll_create (int size)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002422{
Dave Wallace048b1d62018-01-03 22:24:41 -05002423 return epoll_create1 (0);
2424}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002425
Dave Wallace048b1d62018-01-03 22:24:41 -05002426int
2427epoll_ctl (int epfd, int op, int fd, struct epoll_event *event)
2428{
Florin Coras7baeb712019-01-04 17:05:43 -08002429 vls_handle_t vep_vlsh, vlsh;
Florin Coras99368312018-08-02 10:45:44 -07002430 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05002431
Florin Coras5f33d0d2021-06-02 21:22:21 -07002432 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05002433
Florin Coras7baeb712019-01-04 17:05:43 -08002434 vep_vlsh = ldp_fd_to_vlsh (epfd);
2435 if (PREDICT_FALSE (vep_vlsh == VLS_INVALID_HANDLE))
Dave Wallace048b1d62018-01-03 22:24:41 -05002436 {
Dave Wallace3ee1fe12018-02-23 01:09:11 -05002437 /* The LDP epoll_create1 always creates VCL epfd's.
2438 * The app should never have a kernel base epoll fd unless it
2439 * was acquired outside of the LD_PRELOAD process context.
2440 * In any case, if we get one, punt it to libc_epoll_ctl.
2441 */
Florin Corasc86662a2023-03-05 11:45:38 -08002442 LDBG (1,
2443 "epfd %d: calling libc_epoll_ctl: op %d, fd %d"
2444 " events 0x%x",
2445 epfd, op, fd, event ? event->events : 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002446
2447 rv = libc_epoll_ctl (epfd, op, fd, event);
Florin Coras99368312018-08-02 10:45:44 -07002448 goto done;
2449 }
2450
Florin Coras7baeb712019-01-04 17:05:43 -08002451 vlsh = ldp_fd_to_vlsh (fd);
Florin Coras99368312018-08-02 10:45:44 -07002452
Florin Coras7baeb712019-01-04 17:05:43 -08002453 LDBG (0, "epfd %d ep_vlsh %d, fd %u vlsh %d, op %u", epfd, vep_vlsh, fd,
2454 vlsh, op);
Florin Coras99368312018-08-02 10:45:44 -07002455
Florin Coras7baeb712019-01-04 17:05:43 -08002456 if (vlsh != VLS_INVALID_HANDLE)
Florin Coras99368312018-08-02 10:45:44 -07002457 {
Florin Corasc86662a2023-03-05 11:45:38 -08002458 LDBG (1,
2459 "epfd %d: calling vls_epoll_ctl: ep_vlsh %d op %d, vlsh %u,"
2460 " events 0x%x",
2461 epfd, vep_vlsh, op, vlsh, event ? event->events : 0);
Florin Coras99368312018-08-02 10:45:44 -07002462
Florin Coras7baeb712019-01-04 17:05:43 -08002463 rv = vls_epoll_ctl (vep_vlsh, op, vlsh, event);
Florin Coras99368312018-08-02 10:45:44 -07002464 if (rv != VPPCOM_OK)
2465 {
2466 errno = -rv;
2467 rv = -1;
2468 }
2469 }
2470 else
2471 {
2472 int libc_epfd;
2473 u32 size = sizeof (epfd);
2474
Florin Coras7baeb712019-01-04 17:05:43 -08002475 libc_epfd = vls_attr (vep_vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
Florin Coras99368312018-08-02 10:45:44 -07002476 if (!libc_epfd)
2477 {
Florin Coras7baeb712019-01-04 17:05:43 -08002478 LDBG (1, "epfd %d, vep_vlsh %d calling libc_epoll_create1: "
2479 "EPOLL_CLOEXEC", epfd, vep_vlsh);
Florin Coras99368312018-08-02 10:45:44 -07002480
2481 libc_epfd = libc_epoll_create1 (EPOLL_CLOEXEC);
2482 if (libc_epfd < 0)
2483 {
2484 rv = libc_epfd;
2485 goto done;
2486 }
2487
Florin Coras7baeb712019-01-04 17:05:43 -08002488 rv = vls_attr (vep_vlsh, VPPCOM_ATTR_SET_LIBC_EPFD, &libc_epfd,
2489 &size);
Florin Coras99368312018-08-02 10:45:44 -07002490 if (rv < 0)
2491 {
2492 errno = -rv;
2493 rv = -1;
2494 goto done;
2495 }
2496 }
2497 else if (PREDICT_FALSE (libc_epfd < 0))
2498 {
2499 errno = -epfd;
2500 rv = -1;
2501 goto done;
2502 }
2503
Florin Coras7baeb712019-01-04 17:05:43 -08002504 LDBG (1, "epfd %d: calling libc_epoll_ctl: libc_epfd %d, op %d, fd %d,"
2505 " event %p", epfd, libc_epfd, op, fd, event);
Florin Coras99368312018-08-02 10:45:44 -07002506
2507 rv = libc_epoll_ctl (libc_epfd, op, fd, event);
Dave Wallace048b1d62018-01-03 22:24:41 -05002508 }
2509
2510done:
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002511 return rv;
2512}
Dave Wallace048b1d62018-01-03 22:24:41 -05002513
2514static inline int
Florin Coras99368312018-08-02 10:45:44 -07002515ldp_epoll_pwait (int epfd, struct epoll_event *events, int maxevents,
2516 int timeout, const sigset_t * sigmask)
Dave Wallace048b1d62018-01-03 22:24:41 -05002517{
Liangxing Wang7c7231f2023-02-16 09:31:01 +00002518 ldp_worker_ctx_t *ldpw;
Florin Coras72f77822019-01-22 19:05:52 -08002519 double time_to_wait = (double) 0, max_time;
Florin Coras99368312018-08-02 10:45:44 -07002520 int libc_epfd, rv = 0;
Florin Coras7baeb712019-01-04 17:05:43 -08002521 vls_handle_t ep_vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002522
Florin Coras5f33d0d2021-06-02 21:22:21 -07002523 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05002524
2525 if (PREDICT_FALSE (!events || (timeout < -1)))
2526 {
2527 errno = EFAULT;
2528 return -1;
2529 }
2530
Liangxing Wang7c7231f2023-02-16 09:31:01 +00002531 if (PREDICT_FALSE (vppcom_worker_index () == ~0))
2532 vls_register_vcl_worker ();
2533
2534 ldpw = ldp_worker_get_current ();
Florin Corasdfe4cf42018-11-28 22:13:45 -08002535 if (epfd == ldpw->vcl_mq_epfd)
Florin Coras99368312018-08-02 10:45:44 -07002536 return libc_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
2537
Florin Coras7baeb712019-01-04 17:05:43 -08002538 ep_vlsh = ldp_fd_to_vlsh (epfd);
2539 if (PREDICT_FALSE (ep_vlsh == VLS_INVALID_HANDLE))
Dave Wallace048b1d62018-01-03 22:24:41 -05002540 {
Florin Coras7baeb712019-01-04 17:05:43 -08002541 LDBG (0, "epfd %d: bad ep_vlsh %d!", epfd, ep_vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05002542 errno = EBADFD;
2543 return -1;
2544 }
2545
Florin Coras4dee8cd2019-01-29 21:28:16 -08002546 if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
2547 clib_time_init (&ldpw->clib_time);
Florin Corasb0f662f2018-12-27 14:51:46 -08002548 time_to_wait = ((timeout >= 0) ? (double) timeout / 1000 : 0);
Florin Coras72f77822019-01-22 19:05:52 -08002549 max_time = clib_time_now (&ldpw->clib_time) + time_to_wait;
Dave Wallace048b1d62018-01-03 22:24:41 -05002550
Florin Coras7baeb712019-01-04 17:05:43 -08002551 libc_epfd = vls_attr (ep_vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002552 if (PREDICT_FALSE (libc_epfd < 0))
2553 {
2554 errno = -libc_epfd;
2555 rv = -1;
2556 goto done;
2557 }
2558
Florin Coras7baeb712019-01-04 17:05:43 -08002559 LDBG (2, "epfd %d: vep_idx %d, libc_epfd %d, events %p, maxevents %d, "
2560 "timeout %d, sigmask %p: time_to_wait %.02f", epfd, ep_vlsh,
Florin Coras72f77822019-01-22 19:05:52 -08002561 libc_epfd, events, maxevents, timeout, sigmask, time_to_wait);
Dave Wallace048b1d62018-01-03 22:24:41 -05002562 do
2563 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002564 if (!ldpw->epoll_wait_vcl)
Dave Wallace048b1d62018-01-03 22:24:41 -05002565 {
Florin Coras7baeb712019-01-04 17:05:43 -08002566 rv = vls_epoll_wait (ep_vlsh, events, maxevents, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002567 if (rv > 0)
2568 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002569 ldpw->epoll_wait_vcl = 1;
Dave Wallace048b1d62018-01-03 22:24:41 -05002570 goto done;
2571 }
2572 else if (rv < 0)
2573 {
2574 errno = -rv;
2575 rv = -1;
2576 goto done;
2577 }
2578 }
2579 else
Florin Corasdfe4cf42018-11-28 22:13:45 -08002580 ldpw->epoll_wait_vcl = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -05002581
2582 if (libc_epfd > 0)
2583 {
Florin Corasb0f662f2018-12-27 14:51:46 -08002584 rv = libc_epoll_pwait (libc_epfd, events, maxevents, 0, sigmask);
Dave Wallace048b1d62018-01-03 22:24:41 -05002585 if (rv != 0)
2586 goto done;
2587 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002588 }
Florin Coras72f77822019-01-22 19:05:52 -08002589 while ((timeout == -1) || (clib_time_now (&ldpw->clib_time) < max_time));
Dave Wallace048b1d62018-01-03 22:24:41 -05002590
2591done:
Dave Wallace048b1d62018-01-03 22:24:41 -05002592 return rv;
2593}
2594
hanlin4266d4d2020-05-19 17:34:17 +08002595static inline int
2596ldp_epoll_pwait_eventfd (int epfd, struct epoll_event *events,
2597 int maxevents, int timeout, const sigset_t * sigmask)
2598{
Florin Corasc86662a2023-03-05 11:45:38 -08002599 int libc_epfd, rv = 0, num_ev, libc_num_ev, vcl_wups = 0;
2600 struct epoll_event *libc_evts;
hanlina3a48962020-07-13 11:09:15 +08002601 ldp_worker_ctx_t *ldpw;
hanlin4266d4d2020-05-19 17:34:17 +08002602 vls_handle_t ep_vlsh;
2603
Florin Coras5f33d0d2021-06-02 21:22:21 -07002604 ldp_init_check ();
hanlin4266d4d2020-05-19 17:34:17 +08002605
2606 if (PREDICT_FALSE (!events || (timeout < -1)))
2607 {
2608 errno = EFAULT;
2609 return -1;
2610 }
2611
Florin Corasff40d8f2020-08-11 22:05:28 -07002612 /* Make sure the vcl worker is valid. Could be that epoll fd was created on
2613 * one thread but it is now used on another */
2614 if (PREDICT_FALSE (vppcom_worker_index () == ~0))
2615 vls_register_vcl_worker ();
hanlina3a48962020-07-13 11:09:15 +08002616
2617 ldpw = ldp_worker_get_current ();
hanlin4266d4d2020-05-19 17:34:17 +08002618 if (epfd == ldpw->vcl_mq_epfd)
2619 return libc_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
2620
2621 ep_vlsh = ldp_fd_to_vlsh (epfd);
2622 if (PREDICT_FALSE (ep_vlsh == VLS_INVALID_HANDLE))
2623 {
2624 LDBG (0, "epfd %d: bad ep_vlsh %d!", epfd, ep_vlsh);
2625 errno = EBADFD;
2626 return -1;
2627 }
2628
2629 libc_epfd = vls_attr (ep_vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
2630 if (PREDICT_FALSE (!libc_epfd))
2631 {
2632 u32 size = sizeof (epfd);
2633
2634 LDBG (1, "epfd %d, vep_vlsh %d calling libc_epoll_create1: "
2635 "EPOLL_CLOEXEC", epfd, ep_vlsh);
2636 libc_epfd = libc_epoll_create1 (EPOLL_CLOEXEC);
2637 if (libc_epfd < 0)
2638 {
2639 rv = libc_epfd;
2640 goto done;
2641 }
2642
2643 rv = vls_attr (ep_vlsh, VPPCOM_ATTR_SET_LIBC_EPFD, &libc_epfd, &size);
2644 if (rv < 0)
2645 {
2646 errno = -rv;
2647 rv = -1;
2648 goto done;
2649 }
2650 }
2651 if (PREDICT_FALSE (libc_epfd <= 0))
2652 {
2653 errno = -libc_epfd;
2654 rv = -1;
2655 goto done;
2656 }
2657
2658 if (PREDICT_FALSE (!ldpw->mq_epfd_added))
2659 {
2660 struct epoll_event e = { 0 };
2661 e.events = EPOLLIN;
2662 e.data.fd = ldpw->vcl_mq_epfd;
2663 if (libc_epoll_ctl (libc_epfd, EPOLL_CTL_ADD, ldpw->vcl_mq_epfd, &e) <
2664 0)
2665 {
2666 LDBG (0, "epfd %d, add libc mq epoll fd %d to libc epoll fd %d",
2667 epfd, ldpw->vcl_mq_epfd, libc_epfd);
2668 rv = -1;
2669 goto done;
2670 }
2671 ldpw->mq_epfd_added = 1;
2672 }
2673
wanghanlin8919fec2021-03-18 20:00:41 +08002674 /* Request to only drain unhandled to prevent libc_epoll_wait starved */
2675 rv = vls_epoll_wait (ep_vlsh, events, maxevents, -2);
hanlin4266d4d2020-05-19 17:34:17 +08002676 if (rv > 0)
Florin Corasc86662a2023-03-05 11:45:38 -08002677 {
2678 timeout = 0;
2679 if (rv >= maxevents)
2680 goto done;
Florin Coras55c699e2023-08-15 12:11:50 -07002681 maxevents -= rv;
Florin Corasc86662a2023-03-05 11:45:38 -08002682 }
hanlina3a48962020-07-13 11:09:15 +08002683 else if (PREDICT_FALSE (rv < 0))
hanlin4266d4d2020-05-19 17:34:17 +08002684 {
2685 errno = -rv;
2686 rv = -1;
2687 goto done;
2688 }
2689
Florin Coras7a1e95a2023-03-01 00:45:31 -08002690epoll_again:
Florin Corasc86662a2023-03-05 11:45:38 -08002691
2692 libc_evts = &events[rv];
2693 libc_num_ev =
Florin Coras55c699e2023-08-15 12:11:50 -07002694 libc_epoll_pwait (libc_epfd, libc_evts, maxevents, timeout, sigmask);
Florin Corasc86662a2023-03-05 11:45:38 -08002695 if (libc_num_ev <= 0)
hanlin4266d4d2020-05-19 17:34:17 +08002696 {
Florin Corasc86662a2023-03-05 11:45:38 -08002697 rv = rv >= 0 ? rv : -1;
2698 goto done;
2699 }
2700
2701 for (int i = 0; i < libc_num_ev; i++)
2702 {
2703 if (libc_evts[i].data.fd == ldpw->vcl_mq_epfd)
hanlin4266d4d2020-05-19 17:34:17 +08002704 {
2705 /* We should remove mq epoll fd from events. */
Florin Corasc86662a2023-03-05 11:45:38 -08002706 libc_num_ev--;
2707 if (i != libc_num_ev)
hanlin4266d4d2020-05-19 17:34:17 +08002708 {
Florin Corasc86662a2023-03-05 11:45:38 -08002709 libc_evts[i].events = libc_evts[libc_num_ev].events;
2710 libc_evts[i].data.u64 = libc_evts[libc_num_ev].data.u64;
hanlin4266d4d2020-05-19 17:34:17 +08002711 }
Florin Corasc86662a2023-03-05 11:45:38 -08002712 num_ev = vls_epoll_wait (ep_vlsh, &libc_evts[libc_num_ev],
2713 maxevents - libc_num_ev, 0);
hanlin4266d4d2020-05-19 17:34:17 +08002714 if (PREDICT_TRUE (num_ev > 0))
2715 rv += num_ev;
Florin Coras7a1e95a2023-03-01 00:45:31 -08002716 /* Woken up by vcl but no events generated. Accept it once */
Florin Corasc86662a2023-03-05 11:45:38 -08002717 if (rv == 0 && libc_num_ev == 0 && timeout && vcl_wups++ < 1)
Florin Coras7a1e95a2023-03-01 00:45:31 -08002718 goto epoll_again;
hanlin4266d4d2020-05-19 17:34:17 +08002719 break;
2720 }
2721 }
2722
Florin Corasc86662a2023-03-05 11:45:38 -08002723 rv += libc_num_ev;
2724
hanlin4266d4d2020-05-19 17:34:17 +08002725done:
2726 return rv;
2727}
2728
Dave Wallace048b1d62018-01-03 22:24:41 -05002729int
2730epoll_pwait (int epfd, struct epoll_event *events,
2731 int maxevents, int timeout, const sigset_t * sigmask)
2732{
hanlin4266d4d2020-05-19 17:34:17 +08002733 if (vls_use_eventfd ())
2734 return ldp_epoll_pwait_eventfd (epfd, events, maxevents, timeout,
2735 sigmask);
2736 else
2737 return ldp_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
Dave Wallace048b1d62018-01-03 22:24:41 -05002738}
2739
2740int
2741epoll_wait (int epfd, struct epoll_event *events, int maxevents, int timeout)
2742{
hanlin4266d4d2020-05-19 17:34:17 +08002743 if (vls_use_eventfd ())
2744 return ldp_epoll_pwait_eventfd (epfd, events, maxevents, timeout, NULL);
2745 else
2746 return ldp_epoll_pwait (epfd, events, maxevents, timeout, NULL);
Dave Wallace048b1d62018-01-03 22:24:41 -05002747}
2748
2749int
2750poll (struct pollfd *fds, nfds_t nfds, int timeout)
2751{
Florin Corasdfe4cf42018-11-28 22:13:45 -08002752 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras6917b942018-11-13 22:44:54 -08002753 int rv, i, n_revents = 0;
Florin Coras7baeb712019-01-04 17:05:43 -08002754 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002755 vcl_poll_t *vp;
Florin Coras4dee8cd2019-01-29 21:28:16 -08002756 double max_time;
Dave Wallace048b1d62018-01-03 22:24:41 -05002757
Florin Coraseb801d02020-09-16 17:44:58 -07002758 LDBG (3, "fds %p, nfds %ld, timeout %d", fds, nfds, timeout);
Dave Wallace048b1d62018-01-03 22:24:41 -05002759
Florin Coras4dee8cd2019-01-29 21:28:16 -08002760 if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
2761 clib_time_init (&ldpw->clib_time);
2762
2763 max_time = (timeout >= 0) ? (f64) timeout / 1000 : 0;
2764 max_time += clib_time_now (&ldpw->clib_time);
Dave Wallace048b1d62018-01-03 22:24:41 -05002765
Dave Wallace048b1d62018-01-03 22:24:41 -05002766 for (i = 0; i < nfds; i++)
2767 {
Florin Coras6917b942018-11-13 22:44:54 -08002768 if (fds[i].fd < 0)
2769 continue;
Dave Wallace048b1d62018-01-03 22:24:41 -05002770
Florin Coras7baeb712019-01-04 17:05:43 -08002771 vlsh = ldp_fd_to_vlsh (fds[i].fd);
2772 if (vlsh != VLS_INVALID_HANDLE)
Florin Coras6917b942018-11-13 22:44:54 -08002773 {
2774 fds[i].fd = -fds[i].fd;
Florin Corasdfe4cf42018-11-28 22:13:45 -08002775 vec_add2 (ldpw->vcl_poll, vp, 1);
Florin Coras6917b942018-11-13 22:44:54 -08002776 vp->fds_ndx = i;
Florin Coras7baeb712019-01-04 17:05:43 -08002777 vp->sh = vlsh_to_sh (vlsh);
Florin Coras6917b942018-11-13 22:44:54 -08002778 vp->events = fds[i].events;
Dave Wallace048b1d62018-01-03 22:24:41 -05002779#ifdef __USE_XOPEN2K
Florin Coras6917b942018-11-13 22:44:54 -08002780 if (fds[i].events & POLLRDNORM)
2781 vp->events |= POLLIN;
2782 if (fds[i].events & POLLWRNORM)
2783 vp->events |= POLLOUT;
Dave Wallace048b1d62018-01-03 22:24:41 -05002784#endif
Florin Coras6917b942018-11-13 22:44:54 -08002785 vp->revents = fds[i].revents;
2786 }
2787 else
2788 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002789 vec_add1 (ldpw->libc_poll, fds[i]);
2790 vec_add1 (ldpw->libc_poll_idxs, i);
Dave Wallace048b1d62018-01-03 22:24:41 -05002791 }
2792 }
2793
Dave Wallace048b1d62018-01-03 22:24:41 -05002794 do
2795 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002796 if (vec_len (ldpw->vcl_poll))
Dave Wallace048b1d62018-01-03 22:24:41 -05002797 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002798 rv = vppcom_poll (ldpw->vcl_poll, vec_len (ldpw->vcl_poll), 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002799 if (rv < 0)
2800 {
2801 errno = -rv;
2802 rv = -1;
2803 goto done;
2804 }
2805 else
2806 n_revents += rv;
2807 }
2808
Florin Corasdfe4cf42018-11-28 22:13:45 -08002809 if (vec_len (ldpw->libc_poll))
Dave Wallace048b1d62018-01-03 22:24:41 -05002810 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002811 rv = libc_poll (ldpw->libc_poll, vec_len (ldpw->libc_poll), 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002812 if (rv < 0)
2813 goto done;
2814 else
2815 n_revents += rv;
2816 }
2817
2818 if (n_revents)
2819 {
2820 rv = n_revents;
2821 goto done;
2822 }
2823 }
Florin Coras4dee8cd2019-01-29 21:28:16 -08002824 while ((timeout < 0) || (clib_time_now (&ldpw->clib_time) < max_time));
Dave Wallace048b1d62018-01-03 22:24:41 -05002825 rv = 0;
2826
2827done:
Florin Corasdfe4cf42018-11-28 22:13:45 -08002828 vec_foreach (vp, ldpw->vcl_poll)
Dave Wallace048b1d62018-01-03 22:24:41 -05002829 {
2830 fds[vp->fds_ndx].fd = -fds[vp->fds_ndx].fd;
Florin Coras6917b942018-11-13 22:44:54 -08002831 fds[vp->fds_ndx].revents = vp->revents;
Dave Wallace048b1d62018-01-03 22:24:41 -05002832#ifdef __USE_XOPEN2K
2833 if ((fds[vp->fds_ndx].revents & POLLIN) &&
2834 (fds[vp->fds_ndx].events & POLLRDNORM))
2835 fds[vp->fds_ndx].revents |= POLLRDNORM;
2836 if ((fds[vp->fds_ndx].revents & POLLOUT) &&
2837 (fds[vp->fds_ndx].events & POLLWRNORM))
2838 fds[vp->fds_ndx].revents |= POLLWRNORM;
2839#endif
2840 }
Florin Corasdfe4cf42018-11-28 22:13:45 -08002841 vec_reset_length (ldpw->vcl_poll);
Dave Wallace048b1d62018-01-03 22:24:41 -05002842
Florin Corasdfe4cf42018-11-28 22:13:45 -08002843 for (i = 0; i < vec_len (ldpw->libc_poll); i++)
Florin Coras6917b942018-11-13 22:44:54 -08002844 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002845 fds[ldpw->libc_poll_idxs[i]].revents = ldpw->libc_poll[i].revents;
Florin Coras6917b942018-11-13 22:44:54 -08002846 }
Florin Corasdfe4cf42018-11-28 22:13:45 -08002847 vec_reset_length (ldpw->libc_poll_idxs);
2848 vec_reset_length (ldpw->libc_poll);
Florin Coras6917b942018-11-13 22:44:54 -08002849
Dave Wallace048b1d62018-01-03 22:24:41 -05002850 return rv;
2851}
2852
Florin Coras36847942023-02-02 12:56:16 -08002853#ifdef _GNU_SOURCE
Dave Wallace048b1d62018-01-03 22:24:41 -05002854int
2855ppoll (struct pollfd *fds, nfds_t nfds,
2856 const struct timespec *timeout, const sigset_t * sigmask)
2857{
Florin Coras5f33d0d2021-06-02 21:22:21 -07002858 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05002859
2860 clib_warning ("LDP<%d>: LDP-TBD", getpid ());
2861 errno = ENOSYS;
2862
2863
2864 return -1;
2865}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002866#endif
2867
Dave Wallace2a865272018-02-07 21:00:42 -05002868void CONSTRUCTOR_ATTRIBUTE ldp_constructor (void);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002869
Dave Wallace2a865272018-02-07 21:00:42 -05002870void DESTRUCTOR_ATTRIBUTE ldp_destructor (void);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002871
Dave Wallace048b1d62018-01-03 22:24:41 -05002872/*
2873 * This function is called when the library is loaded
2874 */
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002875void
Dave Wallace2a865272018-02-07 21:00:42 -05002876ldp_constructor (void)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002877{
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002878 swrap_constructor ();
Dave Wallace2a865272018-02-07 21:00:42 -05002879 if (ldp_init () != 0)
Florin Corasd89411e2019-03-19 19:44:51 -07002880 {
2881 fprintf (stderr, "\nLDP<%d>: ERROR: ldp_constructor: failed!\n",
2882 getpid ());
2883 _exit (1);
2884 }
Dave Wallace69d01192018-02-22 16:22:09 -05002885 else if (LDP_DEBUG > 0)
Dave Wallace2a865272018-02-07 21:00:42 -05002886 clib_warning ("LDP<%d>: LDP constructor: done!\n", getpid ());
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002887}
2888
2889/*
2890 * This function is called when the library is unloaded
2891 */
2892void
Dave Wallace2a865272018-02-07 21:00:42 -05002893ldp_destructor (void)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002894{
Florin Coras0ef8ef22019-01-18 08:37:13 -08002895 /*
2896 swrap_destructor ();
2897 if (ldp->init)
2898 ldp->init = 0;
2899 */
Dave Wallace048b1d62018-01-03 22:24:41 -05002900
2901 /* Don't use clib_warning() here because that calls writev()
Dave Wallace2a865272018-02-07 21:00:42 -05002902 * which will call ldp_init().
Dave Wallace048b1d62018-01-03 22:24:41 -05002903 */
Dave Wallace69d01192018-02-22 16:22:09 -05002904 if (LDP_DEBUG > 0)
Florin Coras0ef8ef22019-01-18 08:37:13 -08002905 fprintf (stderr, "%s:%d: LDP<%d>: LDP destructor: done!\n",
2906 __func__, __LINE__, getpid ());
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002907}
2908
2909
2910/*
2911 * fd.io coding-style-patch-verification: ON
2912 *
2913 * Local Variables:
2914 * eval: (c-set-style "gnu")
2915 * End:
2916 */