blob: a8062b4ca8dbafbc0d2809b5faf2a168a0983ae7 [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;
198 pool_alloc (ldp->workers, LDP_MAX_NWORKERS);
199}
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
291 ASSERT (!ldp->init);
292
293 ldp_init_cfg ();
294 ldp->init = 1;
295 ldp->vcl_needs_real_epoll = 1;
296 rv = vls_app_create (ldp_get_app_name ());
297 if (rv != VPPCOM_OK)
298 {
299 ldp->vcl_needs_real_epoll = 0;
300 if (rv == VPPCOM_EEXIST)
301 return 0;
302 LDBG (2,
303 "\nERROR: ldp_init: vppcom_app_create()"
304 " failed! rv = %d (%s)\n",
305 rv, vppcom_retval_str (rv));
306 ldp->init = 0;
307 return rv;
308 }
309 ldp->vcl_needs_real_epoll = 0;
310 ldp_alloc_workers ();
311 ldpw = ldp_worker_get_current ();
312
Damjan Marionb2c31b62020-12-13 21:47:40 +0100313 pool_foreach (ldpw, ldp->workers) {
Florin Coras4dee8cd2019-01-29 21:28:16 -0800314 clib_memset (&ldpw->clib_time, 0, sizeof (ldpw->clib_time));
Damjan Marionb2c31b62020-12-13 21:47:40 +0100315 }
Florin Coras4dee8cd2019-01-29 21:28:16 -0800316
Florin Coras05ecfcc2018-12-12 18:19:39 -0800317 LDBG (0, "LDP initialization: done!");
Florin Coras99368312018-08-02 10:45:44 -0700318
319 return 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500320}
321
Florin Coras5f33d0d2021-06-02 21:22:21 -0700322#define ldp_init_check() \
323 if (PREDICT_FALSE (!ldp->init)) \
324 { \
325 if ((errno = -ldp_init ())) \
326 return -1; \
327 }
328
Dave Wallace048b1d62018-01-03 22:24:41 -0500329int
330close (int fd)
331{
Florin Coras7baeb712019-01-04 17:05:43 -0800332 vls_handle_t vlsh;
333 int rv, epfd;
Dave Wallace048b1d62018-01-03 22:24:41 -0500334
Florin Coras5f33d0d2021-06-02 21:22:21 -0700335 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -0500336
Florin Coras7baeb712019-01-04 17:05:43 -0800337 vlsh = ldp_fd_to_vlsh (fd);
338 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500339 {
Florin Coras7baeb712019-01-04 17:05:43 -0800340 epfd = vls_attr (vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -0500341 if (epfd > 0)
342 {
Florin Coras06defbc2023-02-28 22:32:31 -0800343 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
344 u32 size = sizeof (epfd);
345
Florin Coras7baeb712019-01-04 17:05:43 -0800346 LDBG (0, "fd %d: calling libc_close: epfd %u", fd, epfd);
Dave Wallace048b1d62018-01-03 22:24:41 -0500347
Florin Coras06defbc2023-02-28 22:32:31 -0800348 libc_close (epfd);
349 ldpw->mq_epfd_added = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500350
Florin Coras06defbc2023-02-28 22:32:31 -0800351 epfd = 0;
352 (void) vls_attr (vlsh, VPPCOM_ATTR_SET_LIBC_EPFD, &epfd, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -0500353 }
354 else if (PREDICT_FALSE (epfd < 0))
355 {
356 errno = -epfd;
357 rv = -1;
358 goto done;
359 }
360
Florin Coras7baeb712019-01-04 17:05:43 -0800361 LDBG (0, "fd %d: calling vls_close: vlsh %u", fd, vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -0500362
Florin Coras7baeb712019-01-04 17:05:43 -0800363 rv = vls_close (vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -0500364 if (rv != VPPCOM_OK)
365 {
366 errno = -rv;
367 rv = -1;
368 }
369 }
370 else
371 {
Florin Coras7baeb712019-01-04 17:05:43 -0800372 LDBG (0, "fd %d: calling libc_close", fd);
Dave Wallace048b1d62018-01-03 22:24:41 -0500373 rv = libc_close (fd);
374 }
375
376done:
Dave Wallace048b1d62018-01-03 22:24:41 -0500377 return rv;
378}
379
380ssize_t
381read (int fd, void *buf, size_t nbytes)
382{
Florin Coras7baeb712019-01-04 17:05:43 -0800383 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500384 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -0500385
Florin Coras5f33d0d2021-06-02 21:22:21 -0700386 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -0500387
Florin Coras7baeb712019-01-04 17:05:43 -0800388 vlsh = ldp_fd_to_vlsh (fd);
389 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500390 {
Florin Coras7baeb712019-01-04 17:05:43 -0800391 size = vls_read (vlsh, buf, nbytes);
Dave Wallace048b1d62018-01-03 22:24:41 -0500392 if (size < 0)
393 {
394 errno = -size;
395 size = -1;
396 }
397 }
398 else
399 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500400 size = libc_read (fd, buf, nbytes);
401 }
402
Dave Wallace048b1d62018-01-03 22:24:41 -0500403 return size;
404}
405
406ssize_t
407readv (int fd, const struct iovec * iov, int iovcnt)
408{
Dave Wallace8aaba562018-01-18 17:21:19 -0500409 int rv = 0, i, total = 0;
Florin Coras7baeb712019-01-04 17:05:43 -0800410 vls_handle_t vlsh;
411 ssize_t size = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500412
Florin Coras5f33d0d2021-06-02 21:22:21 -0700413 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -0500414
Florin Coras7baeb712019-01-04 17:05:43 -0800415 vlsh = ldp_fd_to_vlsh (fd);
416 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500417 {
Florin Coras067f9542020-02-14 05:33:46 +0000418 for (i = 0; i < iovcnt; ++i)
Dave Wallace048b1d62018-01-03 22:24:41 -0500419 {
Florin Coras067f9542020-02-14 05:33:46 +0000420 rv = vls_read (vlsh, iov[i].iov_base, iov[i].iov_len);
421 if (rv <= 0)
422 break;
423 else
Dave Wallace048b1d62018-01-03 22:24:41 -0500424 {
Florin Coras067f9542020-02-14 05:33:46 +0000425 total += rv;
426 if (rv < iov[i].iov_len)
Dave Wallace048b1d62018-01-03 22:24:41 -0500427 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700428 }
429 }
Florin Coras067f9542020-02-14 05:33:46 +0000430 if (rv < 0 && total == 0)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700431 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500432 errno = -rv;
433 size = -1;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700434 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500435 else
436 size = total;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700437 }
438 else
439 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500440 size = libc_readv (fd, iov, iovcnt);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700441 }
442
Dave Wallace048b1d62018-01-03 22:24:41 -0500443 return size;
444}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700445
Dave Wallace048b1d62018-01-03 22:24:41 -0500446ssize_t
447write (int fd, const void *buf, size_t nbytes)
448{
Florin Coras7baeb712019-01-04 17:05:43 -0800449 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500450 ssize_t size = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500451
Florin Coras5f33d0d2021-06-02 21:22:21 -0700452 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -0500453
Florin Coras7baeb712019-01-04 17:05:43 -0800454 vlsh = ldp_fd_to_vlsh (fd);
455 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500456 {
Florin Coras7baeb712019-01-04 17:05:43 -0800457 size = vls_write_msg (vlsh, (void *) buf, nbytes);
Dave Wallace048b1d62018-01-03 22:24:41 -0500458 if (size < 0)
459 {
460 errno = -size;
461 size = -1;
462 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700463 }
464 else
465 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500466 size = libc_write (fd, buf, nbytes);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700467 }
468
Dave Wallace048b1d62018-01-03 22:24:41 -0500469 return size;
470}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700471
Dave Wallace048b1d62018-01-03 22:24:41 -0500472ssize_t
473writev (int fd, const struct iovec * iov, int iovcnt)
474{
Dave Wallace048b1d62018-01-03 22:24:41 -0500475 ssize_t size = 0, total = 0;
Florin Coras7baeb712019-01-04 17:05:43 -0800476 vls_handle_t vlsh;
Dave Wallace8aaba562018-01-18 17:21:19 -0500477 int i, rv = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500478
Florin Coras5f33d0d2021-06-02 21:22:21 -0700479 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -0500480
Florin Coras7baeb712019-01-04 17:05:43 -0800481 vlsh = ldp_fd_to_vlsh (fd);
482 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500483 {
Florin Coraseda1b8c2020-03-23 16:00:35 +0000484 for (i = 0; i < iovcnt; ++i)
Dave Wallace048b1d62018-01-03 22:24:41 -0500485 {
Florin Coraseda1b8c2020-03-23 16:00:35 +0000486 rv = vls_write_msg (vlsh, iov[i].iov_base, iov[i].iov_len);
487 if (rv < 0)
488 break;
489 else
Dave Wallace048b1d62018-01-03 22:24:41 -0500490 {
Florin Coraseda1b8c2020-03-23 16:00:35 +0000491 total += rv;
492 if (rv < iov[i].iov_len)
Dave Wallace048b1d62018-01-03 22:24:41 -0500493 break;
Dave Wallace048b1d62018-01-03 22:24:41 -0500494 }
495 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500496
Florin Coraseda1b8c2020-03-23 16:00:35 +0000497 if (rv < 0 && total == 0)
Dave Wallace048b1d62018-01-03 22:24:41 -0500498 {
499 errno = -rv;
500 size = -1;
501 }
502 else
503 size = total;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700504 }
505 else
506 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500507 size = libc_writev (fd, iov, iovcnt);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700508 }
509
Dave Wallace048b1d62018-01-03 22:24:41 -0500510 return size;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700511}
512
Florin Coras0ab36f52020-05-26 19:45:45 +0000513static int
514fcntl_internal (int fd, int cmd, va_list ap)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700515{
Florin Coras7baeb712019-01-04 17:05:43 -0800516 vls_handle_t vlsh;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700517 int rv = 0;
Florin Coras7baeb712019-01-04 17:05:43 -0800518
519 vlsh = ldp_fd_to_vlsh (fd);
520 LDBG (0, "fd %u vlsh %d, cmd %u", fd, vlsh, cmd);
521 if (vlsh != VLS_INVALID_HANDLE)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700522 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500523 int flags = va_arg (ap, int);
524 u32 size;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700525
Dave Wallace048b1d62018-01-03 22:24:41 -0500526 size = sizeof (flags);
527 rv = -EOPNOTSUPP;
528 switch (cmd)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700529 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500530 case F_SETFL:
Florin Coras7baeb712019-01-04 17:05:43 -0800531 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_FLAGS, &flags, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -0500532 break;
533
534 case F_GETFL:
Florin Coras7baeb712019-01-04 17:05:43 -0800535 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_FLAGS, &flags, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -0500536 if (rv == VPPCOM_OK)
Florin Coras7baeb712019-01-04 17:05:43 -0800537 rv = flags;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700538 break;
Florin Coras173bae32018-11-16 18:56:28 -0800539 case F_SETFD:
540 /* TODO handle this */
541 LDBG (0, "F_SETFD ignored flags %u", flags);
542 rv = 0;
543 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700544 default:
Dave Wallace048b1d62018-01-03 22:24:41 -0500545 rv = -EOPNOTSUPP;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700546 break;
547 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500548 if (rv < 0)
549 {
550 errno = -rv;
551 rv = -1;
552 }
553 }
554 else
555 {
Carl Smithe16707b2019-11-13 14:37:39 +1300556#ifdef HAVE_FCNTL64
557 rv = libc_vfcntl64 (fd, cmd, ap);
558#else
Dave Wallace048b1d62018-01-03 22:24:41 -0500559 rv = libc_vfcntl (fd, cmd, ap);
Carl Smithe16707b2019-11-13 14:37:39 +1300560#endif
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700561 }
562
Florin Coras0ab36f52020-05-26 19:45:45 +0000563 return rv;
564}
565
566int
567fcntl (int fd, int cmd, ...)
568{
569 va_list ap;
570 int rv;
571
Florin Coras5f33d0d2021-06-02 21:22:21 -0700572 ldp_init_check ();
Florin Coras0ab36f52020-05-26 19:45:45 +0000573
574 va_start (ap, cmd);
575 rv = fcntl_internal (fd, cmd, ap);
Dave Wallace048b1d62018-01-03 22:24:41 -0500576 va_end (ap);
577
Dave Wallace048b1d62018-01-03 22:24:41 -0500578 return rv;
579}
580
581int
Florin Corasd7586d52020-04-29 02:19:51 +0000582fcntl64 (int fd, int cmd, ...)
583{
584 va_list ap;
585 int rv;
586
Florin Coras5f33d0d2021-06-02 21:22:21 -0700587 ldp_init_check ();
Florin Coras0ab36f52020-05-26 19:45:45 +0000588
Florin Corasd7586d52020-04-29 02:19:51 +0000589 va_start (ap, cmd);
Florin Coras0ab36f52020-05-26 19:45:45 +0000590 rv = fcntl_internal (fd, cmd, ap);
Florin Corasd7586d52020-04-29 02:19:51 +0000591 va_end (ap);
592 return rv;
593}
594
595int
Dave Wallace048b1d62018-01-03 22:24:41 -0500596ioctl (int fd, unsigned long int cmd, ...)
597{
Florin Coras7baeb712019-01-04 17:05:43 -0800598 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500599 va_list ap;
Florin Coras7baeb712019-01-04 17:05:43 -0800600 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -0500601
Florin Coras5f33d0d2021-06-02 21:22:21 -0700602 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -0500603
604 va_start (ap, cmd);
Dave Wallace048b1d62018-01-03 22:24:41 -0500605
Florin Coras7baeb712019-01-04 17:05:43 -0800606 vlsh = ldp_fd_to_vlsh (fd);
607 if (vlsh != VLS_INVALID_HANDLE)
608 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500609 switch (cmd)
610 {
611 case FIONREAD:
Florin Coras7baeb712019-01-04 17:05:43 -0800612 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_NREAD, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -0500613 break;
614
615 case FIONBIO:
616 {
Florin Coras4a0e08e2023-05-11 11:45:34 -0700617 u32 flags = *(va_arg (ap, int *)) ? O_NONBLOCK : 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500618 u32 size = sizeof (flags);
619
620 /* TBD: When VPPCOM_ATTR_[GS]ET_FLAGS supports flags other than
621 * non-blocking, the flags should be read here and merged
622 * with O_NONBLOCK.
623 */
Florin Coras7baeb712019-01-04 17:05:43 -0800624 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_FLAGS, &flags, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -0500625 }
626 break;
627
628 default:
629 rv = -EOPNOTSUPP;
630 break;
631 }
632 if (rv < 0)
633 {
634 errno = -rv;
635 rv = -1;
636 }
637 }
638 else
639 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500640 rv = libc_vioctl (fd, cmd, ap);
641 }
642
Dave Wallace048b1d62018-01-03 22:24:41 -0500643 va_end (ap);
644 return rv;
645}
646
Florin Coras294afe22019-01-07 17:49:17 -0800647always_inline void
648ldp_select_init_maps (fd_set * __restrict original,
649 clib_bitmap_t ** resultb, clib_bitmap_t ** libcb,
650 clib_bitmap_t ** vclb, int nfds, u32 minbits,
651 u32 n_bytes, uword * si_bits, uword * libc_bits)
652{
653 uword si_bits_set, libc_bits_set;
654 vls_handle_t vlsh;
655 int fd;
656
657 clib_bitmap_validate (*vclb, minbits);
658 clib_bitmap_validate (*libcb, minbits);
659 clib_bitmap_validate (*resultb, minbits);
660 clib_memcpy_fast (*resultb, original, n_bytes);
661 memset (original, 0, n_bytes);
662
663 /* *INDENT-OFF* */
Damjan Marionf0ca1e82020-12-13 23:26:56 +0100664 clib_bitmap_foreach (fd, *resultb) {
Florin Coras294afe22019-01-07 17:49:17 -0800665 if (fd > nfds)
666 break;
667 vlsh = ldp_fd_to_vlsh (fd);
668 if (vlsh == VLS_INVALID_HANDLE)
669 clib_bitmap_set_no_check (*libcb, fd, 1);
670 else
Florin Corascbce80a2020-04-20 01:32:38 +0000671 *vclb = clib_bitmap_set (*vclb, vlsh_to_session_index (vlsh), 1);
Damjan Marionf0ca1e82020-12-13 23:26:56 +0100672 }
Florin Coras294afe22019-01-07 17:49:17 -0800673 /* *INDENT-ON* */
674
675 si_bits_set = clib_bitmap_last_set (*vclb) + 1;
676 *si_bits = (si_bits_set > *si_bits) ? si_bits_set : *si_bits;
Florin Corascbce80a2020-04-20 01:32:38 +0000677 clib_bitmap_validate (*resultb, *si_bits);
Florin Coras294afe22019-01-07 17:49:17 -0800678
679 libc_bits_set = clib_bitmap_last_set (*libcb) + 1;
680 *libc_bits = (libc_bits_set > *libc_bits) ? libc_bits_set : *libc_bits;
681}
682
683always_inline int
684ldp_select_vcl_map_to_libc (clib_bitmap_t * vclb, fd_set * __restrict libcb)
685{
686 vls_handle_t vlsh;
687 uword si;
688 int fd;
689
690 if (!libcb)
691 return 0;
692
693 /* *INDENT-OFF* */
Damjan Marionf0ca1e82020-12-13 23:26:56 +0100694 clib_bitmap_foreach (si, vclb) {
Florin Coras294afe22019-01-07 17:49:17 -0800695 vlsh = vls_session_index_to_vlsh (si);
Florin Coras54140622020-02-04 19:04:34 +0000696 ASSERT (vlsh != VLS_INVALID_HANDLE);
Florin Coras294afe22019-01-07 17:49:17 -0800697 fd = ldp_vlsh_to_fd (vlsh);
698 if (PREDICT_FALSE (fd < 0))
699 {
700 errno = EBADFD;
701 return -1;
702 }
703 FD_SET (fd, libcb);
Damjan Marionf0ca1e82020-12-13 23:26:56 +0100704 }
Florin Coras294afe22019-01-07 17:49:17 -0800705 /* *INDENT-ON* */
706
707 return 0;
708}
709
710always_inline void
711ldp_select_libc_map_merge (clib_bitmap_t * result, fd_set * __restrict libcb)
712{
713 uword fd;
714
Florin Coras78b5fa62019-02-21 20:04:15 -0800715 if (!libcb)
716 return;
717
Florin Coras294afe22019-01-07 17:49:17 -0800718 /* *INDENT-OFF* */
Damjan Marionf0ca1e82020-12-13 23:26:56 +0100719 clib_bitmap_foreach (fd, result)
Florin Coras294afe22019-01-07 17:49:17 -0800720 FD_SET ((int)fd, libcb);
Florin Coras294afe22019-01-07 17:49:17 -0800721 /* *INDENT-ON* */
722}
723
Dave Wallace048b1d62018-01-03 22:24:41 -0500724int
Dave Wallace2a865272018-02-07 21:00:42 -0500725ldp_pselect (int nfds, fd_set * __restrict readfds,
726 fd_set * __restrict writefds,
727 fd_set * __restrict exceptfds,
728 const struct timespec *__restrict timeout,
729 const __sigset_t * __restrict sigmask)
Dave Wallace048b1d62018-01-03 22:24:41 -0500730{
Florin Coras294afe22019-01-07 17:49:17 -0800731 u32 minbits = clib_max (nfds, BITS (uword)), n_bytes;
Florin Corasdfe4cf42018-11-28 22:13:45 -0800732 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras294afe22019-01-07 17:49:17 -0800733 struct timespec libc_tspec = { 0 };
734 f64 time_out, vcl_timeout = 0;
735 uword si_bits, libc_bits;
736 int rv, bits_set = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500737
738 if (nfds < 0)
739 {
740 errno = EINVAL;
741 return -1;
742 }
743
Florin Coras4dee8cd2019-01-29 21:28:16 -0800744 if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
745 clib_time_init (&ldpw->clib_time);
746
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500747 if (timeout)
748 {
749 time_out = (timeout->tv_sec == 0 && timeout->tv_nsec == 0) ?
Florin Coras7baeb712019-01-04 17:05:43 -0800750 (f64) 0 : (f64) timeout->tv_sec + (f64) timeout->tv_nsec / (f64) 1e9;
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500751
liuyacanf71796e2021-08-02 10:01:39 +0800752 time_out += clib_time_now (&ldpw->clib_time);
753
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500754 /* select as fine grained sleep */
755 if (!nfds)
756 {
Florin Corasdfe4cf42018-11-28 22:13:45 -0800757 while (clib_time_now (&ldpw->clib_time) < time_out)
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500758 ;
759 return 0;
760 }
761 }
762 else if (!nfds)
763 {
764 errno = EINVAL;
765 return -1;
766 }
767 else
768 time_out = -1;
769
Florin Coras7baeb712019-01-04 17:05:43 -0800770 if (nfds <= ldp->vlsh_bit_val)
Dave Wallace048b1d62018-01-03 22:24:41 -0500771 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500772 rv = libc_pselect (nfds, readfds, writefds, exceptfds,
773 timeout, sigmask);
774 goto done;
775 }
776
Florin Coras294afe22019-01-07 17:49:17 -0800777 si_bits = libc_bits = 0;
778 n_bytes = nfds / 8 + ((nfds % 8) ? 1 : 0);
Florin Coras7baeb712019-01-04 17:05:43 -0800779
Dave Wallace048b1d62018-01-03 22:24:41 -0500780 if (readfds)
Florin Coras294afe22019-01-07 17:49:17 -0800781 ldp_select_init_maps (readfds, &ldpw->rd_bitmap, &ldpw->libc_rd_bitmap,
782 &ldpw->si_rd_bitmap, nfds, minbits, n_bytes,
783 &si_bits, &libc_bits);
Dave Wallace048b1d62018-01-03 22:24:41 -0500784 if (writefds)
Florin Coras294afe22019-01-07 17:49:17 -0800785 ldp_select_init_maps (writefds, &ldpw->wr_bitmap,
786 &ldpw->libc_wr_bitmap, &ldpw->si_wr_bitmap, nfds,
787 minbits, n_bytes, &si_bits, &libc_bits);
Dave Wallace048b1d62018-01-03 22:24:41 -0500788 if (exceptfds)
Florin Coras294afe22019-01-07 17:49:17 -0800789 ldp_select_init_maps (exceptfds, &ldpw->ex_bitmap,
790 &ldpw->libc_ex_bitmap, &ldpw->si_ex_bitmap, nfds,
791 minbits, n_bytes, &si_bits, &libc_bits);
Dave Wallace048b1d62018-01-03 22:24:41 -0500792
Florin Coras294afe22019-01-07 17:49:17 -0800793 if (PREDICT_FALSE (!si_bits && !libc_bits))
Dave Wallace048b1d62018-01-03 22:24:41 -0500794 {
795 errno = EINVAL;
796 rv = -1;
797 goto done;
798 }
799
Florin Coras78b5fa62019-02-21 20:04:15 -0800800 if (!si_bits)
801 libc_tspec = timeout ? *timeout : libc_tspec;
Florin Coras294afe22019-01-07 17:49:17 -0800802
Dave Wallace048b1d62018-01-03 22:24:41 -0500803 do
804 {
Florin Coras294afe22019-01-07 17:49:17 -0800805 if (si_bits)
Dave Wallace048b1d62018-01-03 22:24:41 -0500806 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500807 if (readfds)
Florin Coras294afe22019-01-07 17:49:17 -0800808 clib_memcpy_fast (ldpw->rd_bitmap, ldpw->si_rd_bitmap,
Florin Corascbce80a2020-04-20 01:32:38 +0000809 vec_len (ldpw->si_rd_bitmap) *
Dave Barach178cf492018-11-13 16:34:13 -0500810 sizeof (clib_bitmap_t));
Dave Wallace048b1d62018-01-03 22:24:41 -0500811 if (writefds)
Florin Coras294afe22019-01-07 17:49:17 -0800812 clib_memcpy_fast (ldpw->wr_bitmap, ldpw->si_wr_bitmap,
Florin Corascbce80a2020-04-20 01:32:38 +0000813 vec_len (ldpw->si_wr_bitmap) *
Dave Barach178cf492018-11-13 16:34:13 -0500814 sizeof (clib_bitmap_t));
Dave Wallace048b1d62018-01-03 22:24:41 -0500815 if (exceptfds)
Florin Coras294afe22019-01-07 17:49:17 -0800816 clib_memcpy_fast (ldpw->ex_bitmap, ldpw->si_ex_bitmap,
Florin Corascbce80a2020-04-20 01:32:38 +0000817 vec_len (ldpw->si_ex_bitmap) *
Dave Barach178cf492018-11-13 16:34:13 -0500818 sizeof (clib_bitmap_t));
Florin Coras294afe22019-01-07 17:49:17 -0800819
Florin Coras0ef8ef22019-01-18 08:37:13 -0800820 rv = vls_select (si_bits, readfds ? ldpw->rd_bitmap : NULL,
821 writefds ? ldpw->wr_bitmap : NULL,
822 exceptfds ? ldpw->ex_bitmap : NULL, vcl_timeout);
Florin Coras294afe22019-01-07 17:49:17 -0800823 if (rv < 0)
824 {
825 errno = -rv;
826 rv = -1;
Florin Coras5e6222a2020-04-24 17:09:25 +0000827 goto done;
Florin Coras294afe22019-01-07 17:49:17 -0800828 }
829 else if (rv > 0)
830 {
831 if (ldp_select_vcl_map_to_libc (ldpw->rd_bitmap, readfds))
832 {
833 rv = -1;
834 goto done;
835 }
836
837 if (ldp_select_vcl_map_to_libc (ldpw->wr_bitmap, writefds))
838 {
839 rv = -1;
840 goto done;
841 }
842
843 if (ldp_select_vcl_map_to_libc (ldpw->ex_bitmap, exceptfds))
844 {
845 rv = -1;
846 goto done;
847 }
848 bits_set = rv;
849 }
850 }
851 if (libc_bits)
852 {
853 if (readfds)
854 clib_memcpy_fast (ldpw->rd_bitmap, ldpw->libc_rd_bitmap,
855 vec_len (ldpw->libc_rd_bitmap) *
856 sizeof (clib_bitmap_t));
857 if (writefds)
858 clib_memcpy_fast (ldpw->wr_bitmap, ldpw->libc_wr_bitmap,
859 vec_len (ldpw->libc_wr_bitmap) *
860 sizeof (clib_bitmap_t));
861 if (exceptfds)
862 clib_memcpy_fast (ldpw->ex_bitmap, ldpw->libc_ex_bitmap,
863 vec_len (ldpw->libc_ex_bitmap) *
864 sizeof (clib_bitmap_t));
865
Dave Wallace048b1d62018-01-03 22:24:41 -0500866 rv = libc_pselect (libc_bits,
Florin Coras294afe22019-01-07 17:49:17 -0800867 readfds ? (fd_set *) ldpw->rd_bitmap : NULL,
868 writefds ? (fd_set *) ldpw->wr_bitmap : NULL,
869 exceptfds ? (fd_set *) ldpw->ex_bitmap : NULL,
870 &libc_tspec, sigmask);
871 if (rv > 0)
872 {
873 ldp_select_libc_map_merge (ldpw->rd_bitmap, readfds);
874 ldp_select_libc_map_merge (ldpw->wr_bitmap, writefds);
875 ldp_select_libc_map_merge (ldpw->ex_bitmap, exceptfds);
876 bits_set += rv;
877 }
878 }
879
880 if (bits_set)
881 {
882 rv = bits_set;
883 goto done;
Dave Wallace048b1d62018-01-03 22:24:41 -0500884 }
885 }
Florin Corasdfe4cf42018-11-28 22:13:45 -0800886 while ((time_out == -1) || (clib_time_now (&ldpw->clib_time) < time_out));
Dave Wallace048b1d62018-01-03 22:24:41 -0500887 rv = 0;
888
889done:
890 /* TBD: set timeout to amount of time left */
Florin Corasdfe4cf42018-11-28 22:13:45 -0800891 clib_bitmap_zero (ldpw->rd_bitmap);
Florin Coras294afe22019-01-07 17:49:17 -0800892 clib_bitmap_zero (ldpw->si_rd_bitmap);
Florin Corasdfe4cf42018-11-28 22:13:45 -0800893 clib_bitmap_zero (ldpw->libc_rd_bitmap);
894 clib_bitmap_zero (ldpw->wr_bitmap);
Florin Coras294afe22019-01-07 17:49:17 -0800895 clib_bitmap_zero (ldpw->si_wr_bitmap);
Florin Corasdfe4cf42018-11-28 22:13:45 -0800896 clib_bitmap_zero (ldpw->libc_wr_bitmap);
897 clib_bitmap_zero (ldpw->ex_bitmap);
Florin Coras294afe22019-01-07 17:49:17 -0800898 clib_bitmap_zero (ldpw->si_ex_bitmap);
Florin Corasdfe4cf42018-11-28 22:13:45 -0800899 clib_bitmap_zero (ldpw->libc_ex_bitmap);
Dave Wallace048b1d62018-01-03 22:24:41 -0500900
Dave Wallace048b1d62018-01-03 22:24:41 -0500901 return rv;
902}
903
904int
905select (int nfds, fd_set * __restrict readfds,
906 fd_set * __restrict writefds,
907 fd_set * __restrict exceptfds, struct timeval *__restrict timeout)
908{
909 struct timespec tspec;
910
911 if (timeout)
912 {
913 tspec.tv_sec = timeout->tv_sec;
914 tspec.tv_nsec = timeout->tv_usec * 1000;
915 }
Dave Wallace2a865272018-02-07 21:00:42 -0500916 return ldp_pselect (nfds, readfds, writefds, exceptfds,
917 timeout ? &tspec : NULL, NULL);
Dave Wallace048b1d62018-01-03 22:24:41 -0500918}
919
920#ifdef __USE_XOPEN2K
921int
922pselect (int nfds, fd_set * __restrict readfds,
923 fd_set * __restrict writefds,
924 fd_set * __restrict exceptfds,
925 const struct timespec *__restrict timeout,
926 const __sigset_t * __restrict sigmask)
927{
Dave Wallace2a865272018-02-07 21:00:42 -0500928 return ldp_pselect (nfds, readfds, writefds, exceptfds, timeout, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -0500929}
930#endif
931
Yu Ping7b74b072019-05-08 00:40:24 +0800932/* If transparent TLS mode is turned on, then ldp will load key and cert.
933 */
934static int
Florin Corasa5a9efd2021-01-05 17:03:29 -0800935load_cert_key_pair (void)
Yu Ping7b74b072019-05-08 00:40:24 +0800936{
Florin Corasa5a9efd2021-01-05 17:03:29 -0800937 char *cert_str = getenv (LDP_ENV_TLS_CERT);
938 char *key_str = getenv (LDP_ENV_TLS_KEY);
939 char cert_buf[4096], key_buf[4096];
940 int cert_size, key_size;
941 vppcom_cert_key_pair_t crypto;
942 int ckp_index;
Yu Ping7b74b072019-05-08 00:40:24 +0800943 FILE *fp;
944
Florin Corasa5a9efd2021-01-05 17:03:29 -0800945 if (!cert_str || !key_str)
Yu Ping7b74b072019-05-08 00:40:24 +0800946 {
947 LDBG (0, "ERROR: failed to read LDP environment %s\n",
948 LDP_ENV_TLS_CERT);
949 return -1;
950 }
Florin Corasa5a9efd2021-01-05 17:03:29 -0800951
952 fp = fopen (cert_str, "r");
953 if (fp == NULL)
954 {
955 LDBG (0, "ERROR: failed to open cert file %s \n", cert_str);
956 return -1;
957 }
958 cert_size = fread (cert_buf, sizeof (char), sizeof (cert_buf), fp);
959 fclose (fp);
960
961 fp = fopen (key_str, "r");
962 if (fp == NULL)
963 {
964 LDBG (0, "ERROR: failed to open key file %s \n", key_str);
965 return -1;
966 }
967 key_size = fread (key_buf, sizeof (char), sizeof (key_buf), fp);
968 fclose (fp);
969
970 crypto.cert = cert_buf;
971 crypto.key = key_buf;
972 crypto.cert_len = cert_size;
973 crypto.key_len = key_size;
974 ckp_index = vppcom_add_cert_key_pair (&crypto);
975 if (ckp_index < 0)
976 {
977 LDBG (0, "ERROR: failed to add cert key pair\n");
978 return -1;
979 }
980
981 ldp->ckpair_index = ckp_index;
982
Yu Ping7b74b072019-05-08 00:40:24 +0800983 return 0;
984}
985
986static int
Florin Corasa5a9efd2021-01-05 17:03:29 -0800987assign_cert_key_pair (vls_handle_t vlsh)
Yu Ping7b74b072019-05-08 00:40:24 +0800988{
Florin Corasa5a9efd2021-01-05 17:03:29 -0800989 uint32_t ckp_len;
Yu Ping7b74b072019-05-08 00:40:24 +0800990
Florin Corasa5a9efd2021-01-05 17:03:29 -0800991 if (ldp->ckpair_index == ~0 && load_cert_key_pair () < 0)
992 return -1;
993
994 ckp_len = sizeof (ldp->ckpair_index);
liuyacan276675e2021-08-30 13:24:53 +0800995 return vls_attr (vlsh, VPPCOM_ATTR_SET_CKPAIR, &ldp->ckpair_index, &ckp_len);
Yu Ping7b74b072019-05-08 00:40:24 +0800996}
997
Dave Wallace048b1d62018-01-03 22:24:41 -0500998int
999socket (int domain, int type, int protocol)
1000{
Florin Coras7baeb712019-01-04 17:05:43 -08001001 int rv, sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
Dave Wallace048b1d62018-01-03 22:24:41 -05001002 u8 is_nonblocking = type & SOCK_NONBLOCK ? 1 : 0;
Florin Coras7baeb712019-01-04 17:05:43 -08001003 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001004
Florin Coras5f33d0d2021-06-02 21:22:21 -07001005 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001006
1007 if (((domain == AF_INET) || (domain == AF_INET6)) &&
1008 ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM)))
1009 {
Yu Ping7b74b072019-05-08 00:40:24 +08001010 u8 proto;
1011 if (ldp->transparent_tls)
1012 {
1013 proto = VPPCOM_PROTO_TLS;
1014 }
1015 else
1016 proto = ((sock_type == SOCK_DGRAM) ?
1017 VPPCOM_PROTO_UDP : VPPCOM_PROTO_TCP);
Dave Wallace048b1d62018-01-03 22:24:41 -05001018
Florin Coras7baeb712019-01-04 17:05:43 -08001019 LDBG (0, "calling vls_create: proto %u (%s), is_nonblocking %u",
1020 proto, vppcom_proto_str (proto), is_nonblocking);
Dave Wallace048b1d62018-01-03 22:24:41 -05001021
Florin Coras7baeb712019-01-04 17:05:43 -08001022 vlsh = vls_create (proto, is_nonblocking);
1023 if (vlsh < 0)
Dave Wallace048b1d62018-01-03 22:24:41 -05001024 {
Florin Coras7baeb712019-01-04 17:05:43 -08001025 errno = -vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001026 rv = -1;
1027 }
1028 else
1029 {
Yu Ping7b74b072019-05-08 00:40:24 +08001030 if (ldp->transparent_tls)
1031 {
Florin Corasa5a9efd2021-01-05 17:03:29 -08001032 if (assign_cert_key_pair (vlsh) < 0)
1033 return -1;
Yu Ping7b74b072019-05-08 00:40:24 +08001034 }
Florin Coras7baeb712019-01-04 17:05:43 -08001035 rv = ldp_vlsh_to_fd (vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05001036 }
1037 }
1038 else
1039 {
Florin Coras7baeb712019-01-04 17:05:43 -08001040 LDBG (0, "calling libc_socket");
Dave Wallace048b1d62018-01-03 22:24:41 -05001041 rv = libc_socket (domain, type, protocol);
1042 }
1043
Dave Wallace048b1d62018-01-03 22:24:41 -05001044 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001045}
1046
1047/*
1048 * Create two new sockets, of type TYPE in domain DOMAIN and using
1049 * protocol PROTOCOL, which are connected to each other, and put file
1050 * descriptors for them in FDS[0] and FDS[1]. If PROTOCOL is zero,
1051 * one will be chosen automatically.
1052 * Returns 0 on success, -1 for errors.
1053 * */
1054int
Dave Wallace048b1d62018-01-03 22:24:41 -05001055socketpair (int domain, int type, int protocol, int fds[2])
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001056{
Florin Coras7baeb712019-01-04 17:05:43 -08001057 int rv, sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
Dave Wallace048b1d62018-01-03 22:24:41 -05001058
Florin Coras5f33d0d2021-06-02 21:22:21 -07001059 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001060
1061 if (((domain == AF_INET) || (domain == AF_INET6)) &&
1062 ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM)))
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001063 {
Florin Coras7baeb712019-01-04 17:05:43 -08001064 LDBG (0, "LDP-TBD");
Dave Wallace048b1d62018-01-03 22:24:41 -05001065 errno = ENOSYS;
1066 rv = -1;
1067 }
1068 else
1069 {
Florin Coras7baeb712019-01-04 17:05:43 -08001070 LDBG (1, "calling libc_socketpair");
Florin Coras173bae32018-11-16 18:56:28 -08001071 rv = libc_socketpair (domain, type, protocol, fds);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001072 }
1073
Dave Wallace048b1d62018-01-03 22:24:41 -05001074 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001075}
1076
1077int
Florin Coras36847942023-02-02 12:56:16 -08001078bind (int fd, __CONST_SOCKADDR_ARG _addr, socklen_t len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001079{
Florin Coras36847942023-02-02 12:56:16 -08001080 const struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
Florin Coras7baeb712019-01-04 17:05:43 -08001081 vls_handle_t vlsh;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001082 int rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001083
Florin Coras5f33d0d2021-06-02 21:22:21 -07001084 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001085
Florin Coras7baeb712019-01-04 17:05:43 -08001086 vlsh = ldp_fd_to_vlsh (fd);
1087 if (vlsh != VLS_INVALID_HANDLE)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001088 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001089 vppcom_endpt_t ep;
1090
Dave Wallace048b1d62018-01-03 22:24:41 -05001091 switch (addr->sa_family)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001092 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001093 case AF_INET:
1094 if (len != sizeof (struct sockaddr_in))
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001095 {
Florin Coras7baeb712019-01-04 17:05:43 -08001096 LDBG (0, "ERROR: fd %d: vlsh %u: Invalid AF_INET addr len %u!",
1097 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001098 errno = EINVAL;
1099 rv = -1;
1100 goto done;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001101 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001102 ep.is_ip4 = VPPCOM_IS_IP4;
1103 ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr;
1104 ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port;
1105 break;
1106
1107 case AF_INET6:
1108 if (len != sizeof (struct sockaddr_in6))
1109 {
Florin Coras7baeb712019-01-04 17:05:43 -08001110 LDBG (0, "ERROR: fd %d: vlsh %u: Invalid AF_INET6 addr len %u!",
1111 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001112 errno = EINVAL;
1113 rv = -1;
1114 goto done;
1115 }
1116 ep.is_ip4 = VPPCOM_IS_IP6;
1117 ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
1118 ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001119 break;
1120
1121 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001122 LDBG (0, "ERROR: fd %d: vlsh %u: Unsupported address family %u!",
1123 fd, vlsh, addr->sa_family);
Dave Wallace048b1d62018-01-03 22:24:41 -05001124 errno = EAFNOSUPPORT;
1125 rv = -1;
1126 goto done;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001127 }
Florin Coras7baeb712019-01-04 17:05:43 -08001128 LDBG (0, "fd %d: calling vls_bind: vlsh %u, addr %p, len %u", fd, vlsh,
1129 addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001130
Florin Coras7baeb712019-01-04 17:05:43 -08001131 rv = vls_bind (vlsh, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001132 if (rv != VPPCOM_OK)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001133 {
1134 errno = -rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001135 rv = -1;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001136 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001137 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001138 else
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001139 {
Florin Coras7baeb712019-01-04 17:05:43 -08001140 LDBG (0, "fd %d: calling libc_bind: addr %p, len %u", fd, addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001141 rv = libc_bind (fd, addr, len);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001142 }
1143
Dave Wallace048b1d62018-01-03 22:24:41 -05001144done:
Florin Coras7baeb712019-01-04 17:05:43 -08001145 LDBG (1, "fd %d: returning %d", fd, rv);
Florin Coras05ecfcc2018-12-12 18:19:39 -08001146
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001147 return rv;
1148}
1149
1150static inline int
Florin Coras36847942023-02-02 12:56:16 -08001151ldp_copy_ep_to_sockaddr (struct sockaddr *addr, socklen_t *__restrict len,
1152 vppcom_endpt_t *ep)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001153{
Florin Coras36847942023-02-02 12:56:16 -08001154 int rv = 0, sa_len, copy_len;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001155
Florin Coras5f33d0d2021-06-02 21:22:21 -07001156 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001157
1158 if (addr && len && ep)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001159 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001160 addr->sa_family = (ep->is_ip4 == VPPCOM_IS_IP4) ? AF_INET : AF_INET6;
1161 switch (addr->sa_family)
1162 {
1163 case AF_INET:
1164 ((struct sockaddr_in *) addr)->sin_port = ep->port;
1165 if (*len > sizeof (struct sockaddr_in))
1166 *len = sizeof (struct sockaddr_in);
1167 sa_len = sizeof (struct sockaddr_in) - sizeof (struct in_addr);
1168 copy_len = *len - sa_len;
1169 if (copy_len > 0)
1170 memcpy (&((struct sockaddr_in *) addr)->sin_addr, ep->ip,
1171 copy_len);
1172 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001173
Dave Wallace048b1d62018-01-03 22:24:41 -05001174 case AF_INET6:
1175 ((struct sockaddr_in6 *) addr)->sin6_port = ep->port;
1176 if (*len > sizeof (struct sockaddr_in6))
1177 *len = sizeof (struct sockaddr_in6);
1178 sa_len = sizeof (struct sockaddr_in6) - sizeof (struct in6_addr);
1179 copy_len = *len - sa_len;
1180 if (copy_len > 0)
1181 memcpy (((struct sockaddr_in6 *) addr)->sin6_addr.
1182 __in6_u.__u6_addr8, ep->ip, copy_len);
1183 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001184
Dave Wallace048b1d62018-01-03 22:24:41 -05001185 default:
1186 /* Not possible */
1187 rv = -EAFNOSUPPORT;
1188 break;
1189 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001190 }
Dave Wallacee695cb42017-11-02 22:04:42 -04001191 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001192}
1193
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001194int
Florin Coras36847942023-02-02 12:56:16 -08001195getsockname (int fd, __SOCKADDR_ARG _addr, socklen_t *__restrict len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001196{
Florin Coras36847942023-02-02 12:56:16 -08001197 struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
Florin Coras7baeb712019-01-04 17:05:43 -08001198 vls_handle_t vlsh;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001199 int rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001200
Florin Coras5f33d0d2021-06-02 21:22:21 -07001201 ldp_init_check ();
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001202
Florin Coras7baeb712019-01-04 17:05:43 -08001203 vlsh = ldp_fd_to_vlsh (fd);
1204 if (vlsh != VLS_INVALID_HANDLE)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001205 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001206 vppcom_endpt_t ep;
1207 u8 addr_buf[sizeof (struct in6_addr)];
1208 u32 size = sizeof (ep);
1209
1210 ep.ip = addr_buf;
Dave Wallace048b1d62018-01-03 22:24:41 -05001211
Florin Coras7baeb712019-01-04 17:05:43 -08001212 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_LCL_ADDR, &ep, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -05001213 if (rv != VPPCOM_OK)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001214 {
1215 errno = -rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001216 rv = -1;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001217 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001218 else
1219 {
Dave Wallace2a865272018-02-07 21:00:42 -05001220 rv = ldp_copy_ep_to_sockaddr (addr, len, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001221 if (rv != VPPCOM_OK)
1222 {
1223 errno = -rv;
1224 rv = -1;
1225 }
1226 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001227 }
1228 else
1229 {
Florin Coras36847942023-02-02 12:56:16 -08001230 rv = libc_getsockname (fd, _addr, len);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001231 }
1232
Dave Wallace048b1d62018-01-03 22:24:41 -05001233 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001234}
1235
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001236int
Florin Coras36847942023-02-02 12:56:16 -08001237connect (int fd, __CONST_SOCKADDR_ARG _addr, socklen_t len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001238{
Florin Coras36847942023-02-02 12:56:16 -08001239 const struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
Florin Coras7baeb712019-01-04 17:05:43 -08001240 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001241 int rv;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001242
Florin Coras5f33d0d2021-06-02 21:22:21 -07001243 ldp_init_check ();
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001244
Dave Wallace048b1d62018-01-03 22:24:41 -05001245 if (!addr)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001246 {
Florin Coras7baeb712019-01-04 17:05:43 -08001247 LDBG (0, "ERROR: fd %d: NULL addr, len %u", fd, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001248 errno = EINVAL;
1249 rv = -1;
1250 goto done;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001251 }
1252
Florin Coras7baeb712019-01-04 17:05:43 -08001253 vlsh = ldp_fd_to_vlsh (fd);
1254 if (vlsh != VLS_INVALID_HANDLE)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001255 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001256 vppcom_endpt_t ep;
1257
Dave Wallace048b1d62018-01-03 22:24:41 -05001258 switch (addr->sa_family)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001259 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001260 case AF_INET:
1261 if (len != sizeof (struct sockaddr_in))
1262 {
Florin Coras7baeb712019-01-04 17:05:43 -08001263 LDBG (0, "fd %d: ERROR vlsh %u: Invalid AF_INET addr len %u!",
1264 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001265 errno = EINVAL;
1266 rv = -1;
1267 goto done;
1268 }
1269 ep.is_ip4 = VPPCOM_IS_IP4;
1270 ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr;
1271 ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port;
1272 break;
1273
1274 case AF_INET6:
1275 if (len != sizeof (struct sockaddr_in6))
1276 {
Florin Coras7baeb712019-01-04 17:05:43 -08001277 LDBG (0, "fd %d: ERROR vlsh %u: Invalid AF_INET6 addr len %u!",
1278 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001279 errno = EINVAL;
1280 rv = -1;
1281 goto done;
1282 }
1283 ep.is_ip4 = VPPCOM_IS_IP6;
1284 ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
1285 ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port;
1286 break;
1287
1288 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001289 LDBG (0, "fd %d: ERROR vlsh %u: Unsupported address family %u!",
1290 fd, vlsh, addr->sa_family);
Dave Wallace048b1d62018-01-03 22:24:41 -05001291 errno = EAFNOSUPPORT;
1292 rv = -1;
1293 goto done;
1294 }
Florin Coras7baeb712019-01-04 17:05:43 -08001295 LDBG (0, "fd %d: calling vls_connect(): vlsh %u addr %p len %u", fd,
1296 vlsh, addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001297
Florin Coras7baeb712019-01-04 17:05:43 -08001298 rv = vls_connect (vlsh, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001299 if (rv != VPPCOM_OK)
1300 {
1301 errno = -rv;
1302 rv = -1;
1303 }
1304 }
1305 else
1306 {
Florin Coras7baeb712019-01-04 17:05:43 -08001307 LDBG (0, "fd %d: calling libc_connect(): addr %p, len %u",
1308 fd, addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001309
1310 rv = libc_connect (fd, addr, len);
1311 }
1312
1313done:
Florin Coras7baeb712019-01-04 17:05:43 -08001314 LDBG (1, "fd %d: returning %d (0x%x)", fd, rv, rv);
Dave Wallace048b1d62018-01-03 22:24:41 -05001315 return rv;
1316}
1317
1318int
Florin Coras36847942023-02-02 12:56:16 -08001319getpeername (int fd, __SOCKADDR_ARG _addr, socklen_t *__restrict len)
Dave Wallace048b1d62018-01-03 22:24:41 -05001320{
Florin Coras36847942023-02-02 12:56:16 -08001321 struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
Florin Coras7baeb712019-01-04 17:05:43 -08001322 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001323 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001324
Florin Coras5f33d0d2021-06-02 21:22:21 -07001325 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001326
Florin Coras7baeb712019-01-04 17:05:43 -08001327 vlsh = ldp_fd_to_vlsh (fd);
1328 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001329 {
1330 vppcom_endpt_t ep;
1331 u8 addr_buf[sizeof (struct in6_addr)];
1332 u32 size = sizeof (ep);
1333
1334 ep.ip = addr_buf;
Florin Coras7baeb712019-01-04 17:05:43 -08001335 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_PEER_ADDR, &ep, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -05001336 if (rv != VPPCOM_OK)
1337 {
1338 errno = -rv;
1339 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001340 }
1341 else
1342 {
Dave Wallace2a865272018-02-07 21:00:42 -05001343 rv = ldp_copy_ep_to_sockaddr (addr, len, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001344 if (rv != VPPCOM_OK)
1345 {
1346 errno = -rv;
1347 rv = -1;
1348 }
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001349 }
1350 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001351 else
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001352 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001353 rv = libc_getpeername (fd, addr, len);
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001354 }
1355
Dave Wallace048b1d62018-01-03 22:24:41 -05001356 return rv;
1357}
1358
1359ssize_t
1360send (int fd, const void *buf, size_t n, int flags)
1361{
Florin Coras7baeb712019-01-04 17:05:43 -08001362 vls_handle_t vlsh = ldp_fd_to_vlsh (fd);
Dave Wallace048b1d62018-01-03 22:24:41 -05001363 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001364
Florin Coras5f33d0d2021-06-02 21:22:21 -07001365 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001366
Florin Coras7baeb712019-01-04 17:05:43 -08001367 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001368 {
Florin Coras7baeb712019-01-04 17:05:43 -08001369 size = vls_sendto (vlsh, (void *) buf, n, flags, NULL);
qchangaa8f63c2018-05-30 11:44:18 -07001370 if (size < VPPCOM_OK)
Dave Wallace048b1d62018-01-03 22:24:41 -05001371 {
1372 errno = -size;
1373 size = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001374 }
1375 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001376 else
1377 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001378 size = libc_send (fd, buf, n, flags);
1379 }
1380
Dave Wallace048b1d62018-01-03 22:24:41 -05001381 return size;
1382}
1383
1384ssize_t
1385sendfile (int out_fd, int in_fd, off_t * offset, size_t len)
1386{
Florin Corasdfe4cf42018-11-28 22:13:45 -08001387 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras7baeb712019-01-04 17:05:43 -08001388 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001389 ssize_t size = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -05001390
Florin Coras5f33d0d2021-06-02 21:22:21 -07001391 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001392
Florin Coras7baeb712019-01-04 17:05:43 -08001393 vlsh = ldp_fd_to_vlsh (out_fd);
1394 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001395 {
1396 int rv;
1397 ssize_t results = 0;
1398 size_t n_bytes_left = len;
1399 size_t bytes_to_read;
1400 int nbytes;
Dave Wallace048b1d62018-01-03 22:24:41 -05001401 u8 eagain = 0;
1402 u32 flags, flags_len = sizeof (flags);
1403
Florin Coras7baeb712019-01-04 17:05:43 -08001404 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_FLAGS, &flags, &flags_len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001405 if (PREDICT_FALSE (rv != VPPCOM_OK))
1406 {
Florin Coras7baeb712019-01-04 17:05:43 -08001407 LDBG (0, "ERROR: out fd %d: vls_attr: vlsh %u, returned %d (%s)!",
1408 out_fd, vlsh, rv, vppcom_retval_str (rv));
Dave Wallace048b1d62018-01-03 22:24:41 -05001409
Florin Corasdfe4cf42018-11-28 22:13:45 -08001410 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001411 errno = -rv;
1412 size = -1;
1413 goto done;
1414 }
1415
1416 if (offset)
1417 {
1418 off_t off = lseek (in_fd, *offset, SEEK_SET);
1419 if (PREDICT_FALSE (off == -1))
1420 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001421 size = -1;
1422 goto done;
1423 }
1424
1425 ASSERT (off == *offset);
1426 }
1427
1428 do
1429 {
Florin Coras7baeb712019-01-04 17:05:43 -08001430 size = vls_attr (vlsh, VPPCOM_ATTR_GET_NWRITE, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05001431 if (size < 0)
1432 {
Florin Coraseb801d02020-09-16 17:44:58 -07001433 LDBG (0, "ERROR: fd %d: vls_attr: vlsh %u returned %ld (%s)!",
Florin Coras7baeb712019-01-04 17:05:43 -08001434 out_fd, vlsh, size, vppcom_retval_str (size));
Florin Corasdfe4cf42018-11-28 22:13:45 -08001435 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001436 errno = -size;
1437 size = -1;
1438 goto done;
1439 }
1440
1441 bytes_to_read = size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001442 if (bytes_to_read == 0)
1443 {
1444 if (flags & O_NONBLOCK)
1445 {
1446 if (!results)
Florin Coras7baeb712019-01-04 17:05:43 -08001447 eagain = 1;
Dave Wallace048b1d62018-01-03 22:24:41 -05001448 goto update_offset;
1449 }
1450 else
1451 continue;
1452 }
1453 bytes_to_read = clib_min (n_bytes_left, bytes_to_read);
Florin Corasdfe4cf42018-11-28 22:13:45 -08001454 vec_validate (ldpw->io_buffer, bytes_to_read);
1455 nbytes = libc_read (in_fd, ldpw->io_buffer, bytes_to_read);
Dave Wallace048b1d62018-01-03 22:24:41 -05001456 if (nbytes < 0)
1457 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001458 if (results == 0)
1459 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08001460 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001461 size = -1;
1462 goto done;
1463 }
1464 goto update_offset;
1465 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001466
Florin Coras7baeb712019-01-04 17:05:43 -08001467 size = vls_write (vlsh, ldpw->io_buffer, nbytes);
Dave Wallace048b1d62018-01-03 22:24:41 -05001468 if (size < 0)
1469 {
1470 if (size == VPPCOM_EAGAIN)
1471 {
1472 if (flags & O_NONBLOCK)
1473 {
1474 if (!results)
Florin Coras7baeb712019-01-04 17:05:43 -08001475 eagain = 1;
Dave Wallace048b1d62018-01-03 22:24:41 -05001476 goto update_offset;
1477 }
1478 else
1479 continue;
1480 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001481 if (results == 0)
1482 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08001483 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001484 errno = -size;
1485 size = -1;
1486 goto done;
1487 }
1488 goto update_offset;
1489 }
1490
1491 results += nbytes;
1492 ASSERT (n_bytes_left >= nbytes);
1493 n_bytes_left = n_bytes_left - nbytes;
1494 }
1495 while (n_bytes_left > 0);
1496
1497 update_offset:
Florin Corasdfe4cf42018-11-28 22:13:45 -08001498 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001499 if (offset)
1500 {
1501 off_t off = lseek (in_fd, *offset, SEEK_SET);
1502 if (PREDICT_FALSE (off == -1))
1503 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001504 size = -1;
1505 goto done;
1506 }
1507
1508 ASSERT (off == *offset);
1509 *offset += results + 1;
1510 }
1511 if (eagain)
1512 {
1513 errno = EAGAIN;
1514 size = -1;
1515 }
1516 else
1517 size = results;
1518 }
1519 else
1520 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001521 size = libc_sendfile (out_fd, in_fd, offset, len);
1522 }
1523
1524done:
Dave Wallace048b1d62018-01-03 22:24:41 -05001525 return size;
1526}
1527
1528ssize_t
1529sendfile64 (int out_fd, int in_fd, off_t * offset, size_t len)
1530{
1531 return sendfile (out_fd, in_fd, offset, len);
1532}
1533
1534ssize_t
1535recv (int fd, void *buf, size_t n, int flags)
1536{
Florin Coras7baeb712019-01-04 17:05:43 -08001537 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001538 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001539
Florin Coras5f33d0d2021-06-02 21:22:21 -07001540 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001541
Florin Coras7baeb712019-01-04 17:05:43 -08001542 vlsh = ldp_fd_to_vlsh (fd);
1543 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001544 {
Florin Coras7baeb712019-01-04 17:05:43 -08001545 size = vls_recvfrom (vlsh, buf, n, flags, NULL);
Dave Wallace048b1d62018-01-03 22:24:41 -05001546 if (size < 0)
Florin Coras2a6642e2020-03-24 15:24:29 +00001547 {
1548 errno = -size;
1549 size = -1;
1550 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001551 }
1552 else
1553 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001554 size = libc_recv (fd, buf, n, flags);
1555 }
1556
Dave Wallace048b1d62018-01-03 22:24:41 -05001557 return size;
1558}
1559
Sivaprasad Tummalafdcbd382021-07-31 21:38:19 +05301560ssize_t
1561__recv_chk (int fd, void *buf, size_t n, size_t buflen, int flags)
1562{
1563 if (n > buflen)
1564 return -1;
1565
1566 return recv (fd, buf, n, flags);
1567}
1568
Dou Chao243a0432022-11-29 19:41:34 +08001569static inline int
1570ldp_vls_sendo (vls_handle_t vlsh, const void *buf, size_t n,
Florin Coraseff5f7a2023-02-07 17:36:17 -08001571 vppcom_endpt_tlv_t *app_tlvs, int flags,
Florin Coras36847942023-02-02 12:56:16 -08001572 __CONST_SOCKADDR_ARG _addr, socklen_t addr_len)
Florin Corasce17f462020-05-22 20:36:29 +00001573{
Florin Coras36847942023-02-02 12:56:16 -08001574 const struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
Florin Corasce17f462020-05-22 20:36:29 +00001575 vppcom_endpt_t *ep = 0;
1576 vppcom_endpt_t _ep;
1577
Florin Coraseff5f7a2023-02-07 17:36:17 -08001578 _ep.app_tlvs = app_tlvs;
Dou Chao243a0432022-11-29 19:41:34 +08001579
Florin Corasce17f462020-05-22 20:36:29 +00001580 if (addr)
1581 {
1582 ep = &_ep;
1583 switch (addr->sa_family)
1584 {
1585 case AF_INET:
1586 ep->is_ip4 = VPPCOM_IS_IP4;
1587 ep->ip =
1588 (uint8_t *) & ((const struct sockaddr_in *) addr)->sin_addr;
1589 ep->port = (uint16_t) ((const struct sockaddr_in *) addr)->sin_port;
1590 break;
1591
1592 case AF_INET6:
1593 ep->is_ip4 = VPPCOM_IS_IP6;
1594 ep->ip =
1595 (uint8_t *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
1596 ep->port =
1597 (uint16_t) ((const struct sockaddr_in6 *) addr)->sin6_port;
1598 break;
1599
1600 default:
1601 return EAFNOSUPPORT;
1602 }
1603 }
1604
1605 return vls_sendto (vlsh, (void *) buf, n, flags, ep);
1606}
1607
1608static int
Florin Coras36847942023-02-02 12:56:16 -08001609ldp_vls_recvfrom (vls_handle_t vlsh, void *__restrict buf, size_t n, int flags,
1610 __SOCKADDR_ARG _addr, socklen_t *__restrict addr_len)
Florin Corasce17f462020-05-22 20:36:29 +00001611{
1612 u8 src_addr[sizeof (struct sockaddr_in6)];
Florin Coras36847942023-02-02 12:56:16 -08001613 struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
Florin Corasce17f462020-05-22 20:36:29 +00001614 vppcom_endpt_t ep;
1615 ssize_t size;
1616 int rv;
1617
1618 if (addr)
1619 {
1620 ep.ip = src_addr;
1621 size = vls_recvfrom (vlsh, buf, n, flags, &ep);
1622
1623 if (size > 0)
1624 {
1625 rv = ldp_copy_ep_to_sockaddr (addr, addr_len, &ep);
1626 if (rv < 0)
1627 size = rv;
1628 }
1629 }
1630 else
1631 size = vls_recvfrom (vlsh, buf, n, flags, NULL);
1632
1633 return size;
1634}
1635
Dave Wallace048b1d62018-01-03 22:24:41 -05001636ssize_t
1637sendto (int fd, const void *buf, size_t n, int flags,
Florin Coras36847942023-02-02 12:56:16 -08001638 __CONST_SOCKADDR_ARG _addr, socklen_t addr_len)
Dave Wallace048b1d62018-01-03 22:24:41 -05001639{
Florin Coras36847942023-02-02 12:56:16 -08001640 const struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
Florin Coras7baeb712019-01-04 17:05:43 -08001641 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001642 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001643
Florin Coras5f33d0d2021-06-02 21:22:21 -07001644 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001645
Florin Coras7baeb712019-01-04 17:05:43 -08001646 vlsh = ldp_fd_to_vlsh (fd);
wanghanlin97c6e0d2021-07-06 15:01:48 +08001647 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001648 {
Dou Chao243a0432022-11-29 19:41:34 +08001649 size = ldp_vls_sendo (vlsh, buf, n, NULL, flags, addr, addr_len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001650 if (size < 0)
1651 {
1652 errno = -size;
1653 size = -1;
1654 }
1655 }
1656 else
1657 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001658 size = libc_sendto (fd, buf, n, flags, addr, addr_len);
1659 }
1660
Dave Wallace048b1d62018-01-03 22:24:41 -05001661 return size;
1662}
1663
1664ssize_t
1665recvfrom (int fd, void *__restrict buf, size_t n, int flags,
1666 __SOCKADDR_ARG addr, socklen_t * __restrict addr_len)
1667{
Florin Corasce17f462020-05-22 20:36:29 +00001668 vls_handle_t vlsh;
1669 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001670
Florin Coras5f33d0d2021-06-02 21:22:21 -07001671 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001672
Florin Corasce17f462020-05-22 20:36:29 +00001673 vlsh = ldp_fd_to_vlsh (fd);
1674 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001675 {
Florin Corasce17f462020-05-22 20:36:29 +00001676 size = ldp_vls_recvfrom (vlsh, buf, n, flags, addr, addr_len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001677 if (size < 0)
1678 {
1679 errno = -size;
1680 size = -1;
1681 }
1682 }
1683 else
1684 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001685 size = libc_recvfrom (fd, buf, n, flags, addr, addr_len);
1686 }
1687
Dave Wallace048b1d62018-01-03 22:24:41 -05001688 return size;
1689}
1690
Florin Coraseff5f7a2023-02-07 17:36:17 -08001691static int
1692ldp_parse_cmsg (vls_handle_t vlsh, const struct msghdr *msg,
1693 vppcom_endpt_tlv_t **app_tlvs)
1694{
1695 uint8_t *ad, *at = (uint8_t *) *app_tlvs;
1696 vppcom_endpt_tlv_t *adh;
1697 struct in_pktinfo *pi;
1698 struct cmsghdr *cmsg;
1699
1700 cmsg = CMSG_FIRSTHDR (msg);
1701
1702 while (cmsg != NULL)
1703 {
1704 switch (cmsg->cmsg_level)
1705 {
1706 case SOL_UDP:
1707 switch (cmsg->cmsg_type)
1708 {
1709 case UDP_SEGMENT:
1710 vec_add2 (at, adh, sizeof (*adh));
1711 adh->data_type = VCL_UDP_SEGMENT;
1712 adh->data_len = sizeof (uint16_t);
1713 vec_add2 (at, ad, sizeof (uint16_t));
1714 *(uint16_t *) ad = *(uint16_t *) CMSG_DATA (cmsg);
1715 break;
1716 default:
1717 LDBG (1, "SOL_UDP cmsg_type %u not supported", cmsg->cmsg_type);
1718 break;
1719 }
1720 break;
1721 case SOL_IP:
1722 switch (cmsg->cmsg_type)
1723 {
1724 case IP_PKTINFO:
1725 vec_add2 (at, adh, sizeof (*adh));
1726 adh->data_type = VCL_IP_PKTINFO;
1727 adh->data_len = sizeof (struct in_addr);
1728 vec_add2 (at, ad, sizeof (struct in_addr));
1729 pi = (void *) CMSG_DATA (cmsg);
1730 clib_memcpy_fast (ad, &pi->ipi_spec_dst,
1731 sizeof (struct in_addr));
1732 break;
1733 default:
1734 LDBG (1, "SOL_IP cmsg_type %u not supported", cmsg->cmsg_type);
1735 break;
1736 }
1737 break;
1738 default:
1739 LDBG (1, "cmsg_level %u not supported", cmsg->cmsg_level);
1740 break;
1741 }
1742 cmsg = CMSG_NXTHDR ((struct msghdr *) msg, cmsg);
1743 }
1744 *app_tlvs = (vppcom_endpt_tlv_t *) at;
1745 return 0;
1746}
1747
1748static int
1749ldp_make_cmsg (vls_handle_t vlsh, struct msghdr *msg)
1750{
1751 u32 optval, optlen = sizeof (optval);
1752 struct cmsghdr *cmsg;
1753
1754 cmsg = CMSG_FIRSTHDR (msg);
Steven Luong2da272e2023-07-18 23:25:15 -07001755 memset (cmsg, 0, sizeof (*cmsg));
Florin Coraseff5f7a2023-02-07 17:36:17 -08001756
1757 if (!vls_attr (vlsh, VPPCOM_ATTR_GET_IP_PKTINFO, (void *) &optval, &optlen))
1758 return 0;
1759
1760 if (optval)
1761 {
1762 vppcom_endpt_t ep;
1763 u8 addr_buf[sizeof (struct in_addr)];
1764 u32 size = sizeof (ep);
1765
1766 ep.ip = addr_buf;
1767
1768 if (!vls_attr (vlsh, VPPCOM_ATTR_GET_LCL_ADDR, &ep, &size))
1769 {
1770 struct in_pktinfo pi = {};
1771
1772 clib_memcpy (&pi.ipi_addr, ep.ip, sizeof (struct in_addr));
1773 cmsg->cmsg_level = SOL_IP;
1774 cmsg->cmsg_type = IP_PKTINFO;
1775 cmsg->cmsg_len = CMSG_LEN (sizeof (pi));
1776 clib_memcpy (CMSG_DATA (cmsg), &pi, sizeof (pi));
1777 }
1778 }
1779
1780 return 0;
1781}
1782
Dave Wallace048b1d62018-01-03 22:24:41 -05001783ssize_t
Florin Corasce17f462020-05-22 20:36:29 +00001784sendmsg (int fd, const struct msghdr * msg, int flags)
Dave Wallace048b1d62018-01-03 22:24:41 -05001785{
Florin Coras7baeb712019-01-04 17:05:43 -08001786 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001787 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001788
Florin Coras5f33d0d2021-06-02 21:22:21 -07001789 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001790
Florin Coras7baeb712019-01-04 17:05:43 -08001791 vlsh = ldp_fd_to_vlsh (fd);
1792 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001793 {
Florin Coraseff5f7a2023-02-07 17:36:17 -08001794 vppcom_endpt_tlv_t *app_tlvs = 0;
Florin Corasce17f462020-05-22 20:36:29 +00001795 struct iovec *iov = msg->msg_iov;
1796 ssize_t total = 0;
Florin Corascba1c222021-11-29 08:12:27 -08001797 int i, rv = 0;
Dou Chao243a0432022-11-29 19:41:34 +08001798
Florin Coraseff5f7a2023-02-07 17:36:17 -08001799 ldp_parse_cmsg (vlsh, msg, &app_tlvs);
Florin Corasce17f462020-05-22 20:36:29 +00001800
1801 for (i = 0; i < msg->msg_iovlen; ++i)
1802 {
Florin Coraseff5f7a2023-02-07 17:36:17 -08001803 rv = ldp_vls_sendo (vlsh, iov[i].iov_base, iov[i].iov_len, app_tlvs,
1804 flags, msg->msg_name, msg->msg_namelen);
Florin Corasce17f462020-05-22 20:36:29 +00001805 if (rv < 0)
1806 break;
1807 else
1808 {
1809 total += rv;
1810 if (rv < iov[i].iov_len)
1811 break;
1812 }
1813 }
1814
Florin Coraseff5f7a2023-02-07 17:36:17 -08001815 vec_free (app_tlvs);
1816
Florin Corasce17f462020-05-22 20:36:29 +00001817 if (rv < 0 && total == 0)
1818 {
1819 errno = -rv;
1820 size = -1;
1821 }
1822 else
1823 size = total;
Dave Wallace048b1d62018-01-03 22:24:41 -05001824 }
1825 else
1826 {
Florin Corasce17f462020-05-22 20:36:29 +00001827 size = libc_sendmsg (fd, msg, flags);
Dave Wallace048b1d62018-01-03 22:24:41 -05001828 }
1829
Dave Wallace048b1d62018-01-03 22:24:41 -05001830 return size;
1831}
1832
Florin Coras36847942023-02-02 12:56:16 -08001833#ifdef _GNU_SOURCE
Dave Wallace048b1d62018-01-03 22:24:41 -05001834int
1835sendmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags)
1836{
1837 ssize_t size;
1838 const char *func_str;
Florin Coras7baeb712019-01-04 17:05:43 -08001839 u32 sh = ldp_fd_to_vlsh (fd);
Dave Wallace048b1d62018-01-03 22:24:41 -05001840
Florin Coras5f33d0d2021-06-02 21:22:21 -07001841 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001842
wanghanlin97c6e0d2021-07-06 15:01:48 +08001843 if (sh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001844 {
1845 clib_warning ("LDP<%d>: LDP-TBD", getpid ());
1846 errno = ENOSYS;
1847 size = -1;
1848 }
1849 else
1850 {
1851 func_str = "libc_sendmmsg";
1852
Dave Wallace2a865272018-02-07 21:00:42 -05001853 if (LDP_DEBUG > 2)
Dave Wallace048b1d62018-01-03 22:24:41 -05001854 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1855 "vmessages %p, vlen %u, flags 0x%x",
1856 getpid (), fd, fd, func_str, vmessages, vlen, flags);
1857
1858 size = libc_sendmmsg (fd, vmessages, vlen, flags);
1859 }
1860
Dave Wallace2a865272018-02-07 21:00:42 -05001861 if (LDP_DEBUG > 2)
Dave Wallace048b1d62018-01-03 22:24:41 -05001862 {
1863 if (size < 0)
1864 {
1865 int errno_val = errno;
1866 perror (func_str);
1867 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1868 "rv %d, errno = %d", getpid (), fd, fd,
1869 func_str, size, errno_val);
1870 errno = errno_val;
1871 }
1872 else
1873 clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1874 getpid (), fd, fd, size, size);
1875 }
1876 return size;
1877}
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001878#endif
1879
Dave Wallace048b1d62018-01-03 22:24:41 -05001880ssize_t
Florin Corasce17f462020-05-22 20:36:29 +00001881recvmsg (int fd, struct msghdr * msg, int flags)
Dave Wallace048b1d62018-01-03 22:24:41 -05001882{
Florin Coras7baeb712019-01-04 17:05:43 -08001883 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001884 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001885
Florin Coras5f33d0d2021-06-02 21:22:21 -07001886 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001887
Florin Coras7baeb712019-01-04 17:05:43 -08001888 vlsh = ldp_fd_to_vlsh (fd);
1889 if (vlsh != VLS_INVALID_HANDLE)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001890 {
Florin Corasce17f462020-05-22 20:36:29 +00001891 struct iovec *iov = msg->msg_iov;
1892 ssize_t max_deq, total = 0;
1893 int i, rv;
1894
1895 max_deq = vls_attr (vlsh, VPPCOM_ATTR_GET_NREAD, 0, 0);
1896 if (!max_deq)
1897 return 0;
1898
1899 for (i = 0; i < msg->msg_iovlen; i++)
1900 {
1901 rv = ldp_vls_recvfrom (vlsh, iov[i].iov_base, iov[i].iov_len, flags,
1902 (i == 0 ? msg->msg_name : NULL),
1903 (i == 0 ? &msg->msg_namelen : NULL));
1904 if (rv <= 0)
1905 break;
1906 else
1907 {
1908 total += rv;
1909 if (rv < iov[i].iov_len)
1910 break;
1911 }
1912 if (total >= max_deq)
1913 break;
1914 }
1915
1916 if (rv < 0 && total == 0)
1917 {
1918 errno = -rv;
1919 size = -1;
1920 }
1921 else
Florin Coraseff5f7a2023-02-07 17:36:17 -08001922 {
1923 if (msg->msg_controllen)
1924 ldp_make_cmsg (vlsh, msg);
1925 size = total;
1926 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001927 }
1928 else
1929 {
Florin Corasce17f462020-05-22 20:36:29 +00001930 size = libc_recvmsg (fd, msg, flags);
Dave Wallace048b1d62018-01-03 22:24:41 -05001931 }
1932
Dave Wallace048b1d62018-01-03 22:24:41 -05001933 return size;
1934}
1935
Florin Coras36847942023-02-02 12:56:16 -08001936#ifdef _GNU_SOURCE
Dave Wallace048b1d62018-01-03 22:24:41 -05001937int
1938recvmmsg (int fd, struct mmsghdr *vmessages,
1939 unsigned int vlen, int flags, struct timespec *tmo)
1940{
Florin Corasf1a232f2023-02-02 22:56:03 -08001941 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
1942 u32 sh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001943
Florin Coras5f33d0d2021-06-02 21:22:21 -07001944 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001945
Florin Corasf1a232f2023-02-02 22:56:03 -08001946 sh = ldp_fd_to_vlsh (fd);
1947
wanghanlin97c6e0d2021-07-06 15:01:48 +08001948 if (sh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001949 {
Florin Corasf1a232f2023-02-02 22:56:03 -08001950 struct mmsghdr *mh;
1951 ssize_t rv = 0;
1952 u32 nvecs = 0;
1953 f64 time_out;
1954
1955 if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
1956 clib_time_init (&ldpw->clib_time);
1957 if (tmo)
1958 {
1959 time_out = (f64) tmo->tv_sec + (f64) tmo->tv_nsec / (f64) 1e9;
1960 time_out += clib_time_now (&ldpw->clib_time);
1961 }
1962 else
1963 {
1964 time_out = (f64) ~0;
1965 }
1966
1967 while (nvecs < vlen)
1968 {
1969 mh = &vmessages[nvecs];
1970 rv = recvmsg (fd, &mh->msg_hdr, flags);
1971 if (rv > 0)
1972 {
1973 mh->msg_len = rv;
1974 nvecs += 1;
1975 continue;
1976 }
1977
1978 if (!time_out || clib_time_now (&ldpw->clib_time) >= time_out)
1979 break;
1980
1981 usleep (1);
1982 }
1983
1984 return nvecs > 0 ? nvecs : rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001985 }
1986 else
1987 {
Florin Corasf1a232f2023-02-02 22:56:03 -08001988 return libc_recvmmsg (fd, vmessages, vlen, flags, tmo);
Dave Wallace048b1d62018-01-03 22:24:41 -05001989 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001990}
1991#endif
1992
1993int
1994getsockopt (int fd, int level, int optname,
1995 void *__restrict optval, socklen_t * __restrict optlen)
1996{
Florin Coras7baeb712019-01-04 17:05:43 -08001997 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001998 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001999
Florin Coras5f33d0d2021-06-02 21:22:21 -07002000 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05002001
Florin Coras7baeb712019-01-04 17:05:43 -08002002 vlsh = ldp_fd_to_vlsh (fd);
2003 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05002004 {
2005 rv = -EOPNOTSUPP;
2006
2007 switch (level)
2008 {
2009 case SOL_TCP:
2010 switch (optname)
2011 {
2012 case TCP_NODELAY:
Florin Coras7baeb712019-01-04 17:05:43 -08002013 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_NODELAY,
2014 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002015 break;
2016 case TCP_MAXSEG:
Florin Coras7baeb712019-01-04 17:05:43 -08002017 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_USER_MSS,
2018 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002019 break;
2020 case TCP_KEEPIDLE:
Florin Coras7baeb712019-01-04 17:05:43 -08002021 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_KEEPIDLE,
2022 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002023 break;
2024 case TCP_KEEPINTVL:
Florin Coras7baeb712019-01-04 17:05:43 -08002025 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_KEEPINTVL,
2026 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002027 break;
2028 case TCP_INFO:
2029 if (optval && optlen && (*optlen == sizeof (struct tcp_info)))
2030 {
Florin Coras7baeb712019-01-04 17:05:43 -08002031 LDBG (1, "fd %d: vlsh %u SOL_TCP, TCP_INFO, optval %p, "
2032 "optlen %d: #LDP-NOP#", fd, vlsh, optval, *optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002033 memset (optval, 0, *optlen);
2034 rv = VPPCOM_OK;
2035 }
2036 else
2037 rv = -EFAULT;
2038 break;
Florin Coras0ed24e92019-01-21 09:03:10 -08002039 case TCP_CONGESTION:
Florin Coras0ed24e92019-01-21 09:03:10 -08002040 *optlen = strlen ("cubic");
Dave Barach02500902020-04-04 18:34:41 -04002041 strncpy (optval, "cubic", *optlen + 1);
Florin Coras0ed24e92019-01-21 09:03:10 -08002042 rv = 0;
2043 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05002044 default:
Florin Coras7baeb712019-01-04 17:05:43 -08002045 LDBG (0, "ERROR: fd %d: getsockopt SOL_TCP: sid %u, "
2046 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05002047 break;
2048 }
2049 break;
qinyangaf9b7152023-06-27 01:11:53 -07002050 case SOL_IP:
2051 switch (optname)
2052 {
2053 case SO_ORIGINAL_DST:
2054 rv =
2055 vls_attr (vlsh, VPPCOM_ATTR_GET_ORIGINAL_DST, optval, optlen);
2056 break;
2057 default:
2058 LDBG (0,
2059 "ERROR: fd %d: getsockopt SOL_IP: vlsh %u "
2060 "optname %d unsupported!",
2061 fd, vlsh, optname);
2062 break;
2063 }
2064 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05002065 case SOL_IPV6:
2066 switch (optname)
2067 {
2068 case IPV6_V6ONLY:
Florin Coras7baeb712019-01-04 17:05:43 -08002069 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_V6ONLY, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002070 break;
2071 default:
Florin Coras7baeb712019-01-04 17:05:43 -08002072 LDBG (0, "ERROR: fd %d: getsockopt SOL_IPV6: vlsh %u "
2073 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05002074 break;
2075 }
2076 break;
2077 case SOL_SOCKET:
2078 switch (optname)
2079 {
2080 case SO_ACCEPTCONN:
Florin Coras7baeb712019-01-04 17:05:43 -08002081 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_LISTEN, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002082 break;
2083 case SO_KEEPALIVE:
Florin Coras7baeb712019-01-04 17:05:43 -08002084 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_KEEPALIVE, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002085 break;
2086 case SO_PROTOCOL:
Florin Coras7baeb712019-01-04 17:05:43 -08002087 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_PROTOCOL, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002088 *(int *) optval = *(int *) optval ? SOCK_DGRAM : SOCK_STREAM;
2089 break;
2090 case SO_SNDBUF:
Florin Coras7baeb712019-01-04 17:05:43 -08002091 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TX_FIFO_LEN,
2092 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002093 break;
2094 case SO_RCVBUF:
Florin Coras7baeb712019-01-04 17:05:43 -08002095 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_RX_FIFO_LEN,
2096 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002097 break;
2098 case SO_REUSEADDR:
Florin Coras7baeb712019-01-04 17:05:43 -08002099 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_REUSEADDR, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002100 break;
wanghanlin0674f852021-02-22 10:38:36 +08002101 case SO_REUSEPORT:
2102 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_REUSEPORT, optval, optlen);
2103 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05002104 case SO_BROADCAST:
Florin Coras7baeb712019-01-04 17:05:43 -08002105 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_BROADCAST, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002106 break;
wanghanlin0674f852021-02-22 10:38:36 +08002107 case SO_DOMAIN:
2108 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_DOMAIN, optval, optlen);
2109 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05002110 case SO_ERROR:
Florin Coras7baeb712019-01-04 17:05:43 -08002111 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_ERROR, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002112 break;
Florin Coras8eb8d502021-06-16 14:46:57 -07002113 case SO_BINDTODEVICE:
2114 rv = 0;
2115 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05002116 default:
Florin Coras7baeb712019-01-04 17:05:43 -08002117 LDBG (0, "ERROR: fd %d: getsockopt SOL_SOCKET: vlsh %u "
2118 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05002119 break;
2120 }
2121 break;
2122 default:
2123 break;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002124 }
2125
Dave Wallace048b1d62018-01-03 22:24:41 -05002126 if (rv != VPPCOM_OK)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002127 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002128 errno = -rv;
2129 rv = -1;
2130 }
2131 }
2132 else
2133 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002134 rv = libc_getsockopt (fd, level, optname, optval, optlen);
2135 }
2136
Dave Wallace048b1d62018-01-03 22:24:41 -05002137 return rv;
2138}
2139
2140int
2141setsockopt (int fd, int level, int optname,
2142 const void *optval, socklen_t optlen)
2143{
Florin Coras7baeb712019-01-04 17:05:43 -08002144 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002145 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05002146
Florin Coras5f33d0d2021-06-02 21:22:21 -07002147 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05002148
Florin Coras7baeb712019-01-04 17:05:43 -08002149 vlsh = ldp_fd_to_vlsh (fd);
2150 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05002151 {
2152 rv = -EOPNOTSUPP;
2153
2154 switch (level)
2155 {
2156 case SOL_TCP:
2157 switch (optname)
2158 {
2159 case TCP_NODELAY:
Florin Coras7baeb712019-01-04 17:05:43 -08002160 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_NODELAY,
2161 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002162 break;
2163 case TCP_MAXSEG:
Florin Coras7baeb712019-01-04 17:05:43 -08002164 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_USER_MSS,
2165 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002166 break;
2167 case TCP_KEEPIDLE:
Florin Coras7baeb712019-01-04 17:05:43 -08002168 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_KEEPIDLE,
2169 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002170 break;
2171 case TCP_KEEPINTVL:
Florin Coras7baeb712019-01-04 17:05:43 -08002172 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_KEEPINTVL,
2173 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002174 break;
Florin Coras0ed24e92019-01-21 09:03:10 -08002175 case TCP_CONGESTION:
Florin Coras8509aa22019-04-04 12:55:30 -07002176 case TCP_CORK:
Florin Coras0ed24e92019-01-21 09:03:10 -08002177 /* Ignore */
2178 rv = 0;
2179 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05002180 default:
Florin Coras7baeb712019-01-04 17:05:43 -08002181 LDBG (0, "ERROR: fd %d: setsockopt() SOL_TCP: vlsh %u"
2182 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05002183 break;
2184 }
2185 break;
2186 case SOL_IPV6:
2187 switch (optname)
2188 {
2189 case IPV6_V6ONLY:
Florin Coras7baeb712019-01-04 17:05:43 -08002190 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_V6ONLY,
2191 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002192 break;
2193 default:
Florin Coras7baeb712019-01-04 17:05:43 -08002194 LDBG (0, "ERROR: fd %d: setsockopt SOL_IPV6: vlsh %u"
2195 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05002196 break;
2197 }
2198 break;
2199 case SOL_SOCKET:
2200 switch (optname)
2201 {
2202 case SO_KEEPALIVE:
Florin Coras7baeb712019-01-04 17:05:43 -08002203 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_KEEPALIVE,
2204 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002205 break;
2206 case SO_REUSEADDR:
Florin Coras7baeb712019-01-04 17:05:43 -08002207 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_REUSEADDR,
2208 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002209 break;
wanghanlin0674f852021-02-22 10:38:36 +08002210 case SO_REUSEPORT:
2211 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_REUSEPORT, (void *) optval,
2212 &optlen);
2213 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05002214 case SO_BROADCAST:
Florin Coras7baeb712019-01-04 17:05:43 -08002215 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_BROADCAST,
2216 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002217 break;
Florin Coras2f647902021-06-02 08:23:50 -07002218 case SO_LINGER:
2219 rv = 0;
2220 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05002221 default:
Florin Coras7baeb712019-01-04 17:05:43 -08002222 LDBG (0, "ERROR: fd %d: setsockopt SOL_SOCKET: vlsh %u "
2223 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05002224 break;
2225 }
2226 break;
Florin Coraseff5f7a2023-02-07 17:36:17 -08002227 case SOL_IP:
2228 switch (optname)
2229 {
2230 case IP_PKTINFO:
2231 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_IP_PKTINFO, (void *) optval,
2232 &optlen);
2233 break;
2234 default:
2235 LDBG (0,
2236 "ERROR: fd %d: setsockopt SOL_IP: vlsh %u optname %d"
2237 "unsupported!",
2238 fd, vlsh, optname);
2239 break;
2240 }
2241 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05002242 default:
2243 break;
2244 }
2245
2246 if (rv != VPPCOM_OK)
2247 {
2248 errno = -rv;
2249 rv = -1;
2250 }
2251 }
2252 else
2253 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002254 rv = libc_setsockopt (fd, level, optname, optval, optlen);
2255 }
2256
Dave Wallace048b1d62018-01-03 22:24:41 -05002257 return rv;
2258}
2259
2260int
2261listen (int fd, int n)
2262{
Florin Coras7baeb712019-01-04 17:05:43 -08002263 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002264 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05002265
Florin Coras5f33d0d2021-06-02 21:22:21 -07002266 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05002267
Florin Coras7baeb712019-01-04 17:05:43 -08002268 vlsh = ldp_fd_to_vlsh (fd);
2269 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05002270 {
Florin Coras7baeb712019-01-04 17:05:43 -08002271 LDBG (0, "fd %d: calling vls_listen: vlsh %u, n %d", fd, vlsh, n);
Dave Wallace048b1d62018-01-03 22:24:41 -05002272
Florin Coras7baeb712019-01-04 17:05:43 -08002273 rv = vls_listen (vlsh, n);
Dave Wallace048b1d62018-01-03 22:24:41 -05002274 if (rv != VPPCOM_OK)
2275 {
2276 errno = -rv;
2277 rv = -1;
2278 }
2279 }
2280 else
2281 {
Florin Coras7baeb712019-01-04 17:05:43 -08002282 LDBG (0, "fd %d: calling libc_listen(): n %d", fd, n);
Dave Wallace048b1d62018-01-03 22:24:41 -05002283 rv = libc_listen (fd, n);
2284 }
2285
Florin Coras7baeb712019-01-04 17:05:43 -08002286 LDBG (1, "fd %d: returning %d", fd, rv);
Dave Wallace048b1d62018-01-03 22:24:41 -05002287 return rv;
2288}
2289
2290static inline int
Florin Coras36847942023-02-02 12:56:16 -08002291ldp_accept4 (int listen_fd, __SOCKADDR_ARG _addr,
2292 socklen_t *__restrict addr_len, int flags)
Dave Wallace048b1d62018-01-03 22:24:41 -05002293{
Florin Coras36847942023-02-02 12:56:16 -08002294 struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
Florin Coras7baeb712019-01-04 17:05:43 -08002295 vls_handle_t listen_vlsh, accept_vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002296 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05002297
Florin Coras5f33d0d2021-06-02 21:22:21 -07002298 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05002299
Florin Coras7baeb712019-01-04 17:05:43 -08002300 listen_vlsh = ldp_fd_to_vlsh (listen_fd);
2301 if (listen_vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05002302 {
2303 vppcom_endpt_t ep;
2304 u8 src_addr[sizeof (struct sockaddr_in6)];
Dave Wallace8aaba562018-01-18 17:21:19 -05002305 memset (&ep, 0, sizeof (ep));
Dave Wallace048b1d62018-01-03 22:24:41 -05002306 ep.ip = src_addr;
2307
Florin Coras7baeb712019-01-04 17:05:43 -08002308 LDBG (0, "listen fd %d: calling vppcom_session_accept: listen sid %u,"
Florin Coraseb801d02020-09-16 17:44:58 -07002309 " ep %p, flags 0x%x", listen_fd, listen_vlsh, &ep, flags);
Dave Wallace048b1d62018-01-03 22:24:41 -05002310
Florin Coras7baeb712019-01-04 17:05:43 -08002311 accept_vlsh = vls_accept (listen_vlsh, &ep, flags);
2312 if (accept_vlsh < 0)
Dave Wallace048b1d62018-01-03 22:24:41 -05002313 {
Florin Coras7baeb712019-01-04 17:05:43 -08002314 errno = -accept_vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002315 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002316 }
2317 else
2318 {
Dave Wallace2a865272018-02-07 21:00:42 -05002319 rv = ldp_copy_ep_to_sockaddr (addr, addr_len, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05002320 if (rv != VPPCOM_OK)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002321 {
Florin Coras7baeb712019-01-04 17:05:43 -08002322 (void) vls_close (accept_vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05002323 errno = -rv;
2324 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002325 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002326 else
2327 {
Florin Coras7baeb712019-01-04 17:05:43 -08002328 rv = ldp_vlsh_to_fd (accept_vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05002329 }
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002330 }
2331 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002332 else
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002333 {
Florin Coras7baeb712019-01-04 17:05:43 -08002334 LDBG (0, "listen fd %d: calling libc_accept4(): addr %p, addr_len %p,"
2335 " flags 0x%x", listen_fd, addr, addr_len, flags);
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002336
Dave Wallace048b1d62018-01-03 22:24:41 -05002337 rv = libc_accept4 (listen_fd, addr, addr_len, flags);
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002338 }
2339
Florin Coras7baeb712019-01-04 17:05:43 -08002340 LDBG (1, "listen fd %d: accept returning %d", listen_fd, rv);
Florin Coras05ecfcc2018-12-12 18:19:39 -08002341
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002342 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002343}
2344
Dave Wallace048b1d62018-01-03 22:24:41 -05002345int
2346accept4 (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len,
2347 int flags)
2348{
Dave Wallace2a865272018-02-07 21:00:42 -05002349 return ldp_accept4 (fd, addr, addr_len, flags);
Dave Wallace048b1d62018-01-03 22:24:41 -05002350}
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002351
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002352int
Dave Wallace048b1d62018-01-03 22:24:41 -05002353accept (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002354{
Dave Wallace2a865272018-02-07 21:00:42 -05002355 return ldp_accept4 (fd, addr, addr_len, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002356}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002357
Dave Wallace048b1d62018-01-03 22:24:41 -05002358int
2359shutdown (int fd, int how)
2360{
Florin Coras7baeb712019-01-04 17:05:43 -08002361 vls_handle_t vlsh;
liuyacan55c952e2021-06-13 14:54:55 +08002362 int rv = 0;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002363
Florin Coras5f33d0d2021-06-02 21:22:21 -07002364 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05002365
Florin Coras7baeb712019-01-04 17:05:43 -08002366 vlsh = ldp_fd_to_vlsh (fd);
2367 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05002368 {
Florin Coras7baeb712019-01-04 17:05:43 -08002369 LDBG (0, "called shutdown: fd %u vlsh %u how %d", fd, vlsh, how);
liuyacan55c952e2021-06-13 14:54:55 +08002370 rv = vls_shutdown (vlsh, how);
Dave Wallace048b1d62018-01-03 22:24:41 -05002371 }
2372 else
2373 {
Florin Coras7baeb712019-01-04 17:05:43 -08002374 LDBG (0, "fd %d: calling libc_shutdown: how %d", fd, how);
Dave Wallace048b1d62018-01-03 22:24:41 -05002375 rv = libc_shutdown (fd, how);
2376 }
2377
Dave Wallace048b1d62018-01-03 22:24:41 -05002378 return rv;
2379}
2380
2381int
2382epoll_create1 (int flags)
2383{
Florin Corasdfe4cf42018-11-28 22:13:45 -08002384 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras7baeb712019-01-04 17:05:43 -08002385 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002386 int rv;
2387
Florin Coras5f33d0d2021-06-02 21:22:21 -07002388 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05002389
hanlina3a48962020-07-13 11:09:15 +08002390 if (ldp->vcl_needs_real_epoll || vls_use_real_epoll ())
Florin Coras99368312018-08-02 10:45:44 -07002391 {
Florin Coras2d9b4272019-03-11 10:14:37 -07002392 /* Make sure workers have been allocated */
2393 if (!ldp->workers)
2394 {
2395 ldp_alloc_workers ();
2396 ldpw = ldp_worker_get_current ();
2397 }
Florin Coras99368312018-08-02 10:45:44 -07002398 rv = libc_epoll_create1 (flags);
2399 ldp->vcl_needs_real_epoll = 0;
Florin Corasdfe4cf42018-11-28 22:13:45 -08002400 ldpw->vcl_mq_epfd = rv;
Florin Coras05ecfcc2018-12-12 18:19:39 -08002401 LDBG (0, "created vcl epfd %u", rv);
Florin Coras99368312018-08-02 10:45:44 -07002402 return rv;
2403 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002404
Florin Coras7baeb712019-01-04 17:05:43 -08002405 vlsh = vls_epoll_create ();
2406 if (PREDICT_FALSE (vlsh == VLS_INVALID_HANDLE))
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002407 {
Florin Coras7baeb712019-01-04 17:05:43 -08002408 errno = -vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002409 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002410 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002411 else
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002412 {
Florin Coras7baeb712019-01-04 17:05:43 -08002413 rv = ldp_vlsh_to_fd (vlsh);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002414 }
Florin Coras7baeb712019-01-04 17:05:43 -08002415 LDBG (0, "epoll_create epfd %u vlsh %u", rv, vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05002416 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002417}
2418
2419int
Dave Wallace048b1d62018-01-03 22:24:41 -05002420epoll_create (int size)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002421{
Dave Wallace048b1d62018-01-03 22:24:41 -05002422 return epoll_create1 (0);
2423}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002424
Dave Wallace048b1d62018-01-03 22:24:41 -05002425int
2426epoll_ctl (int epfd, int op, int fd, struct epoll_event *event)
2427{
Florin Coras7baeb712019-01-04 17:05:43 -08002428 vls_handle_t vep_vlsh, vlsh;
Florin Coras99368312018-08-02 10:45:44 -07002429 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05002430
Florin Coras5f33d0d2021-06-02 21:22:21 -07002431 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05002432
Florin Coras7baeb712019-01-04 17:05:43 -08002433 vep_vlsh = ldp_fd_to_vlsh (epfd);
2434 if (PREDICT_FALSE (vep_vlsh == VLS_INVALID_HANDLE))
Dave Wallace048b1d62018-01-03 22:24:41 -05002435 {
Dave Wallace3ee1fe12018-02-23 01:09:11 -05002436 /* The LDP epoll_create1 always creates VCL epfd's.
2437 * The app should never have a kernel base epoll fd unless it
2438 * was acquired outside of the LD_PRELOAD process context.
2439 * In any case, if we get one, punt it to libc_epoll_ctl.
2440 */
Florin Corasc86662a2023-03-05 11:45:38 -08002441 LDBG (1,
2442 "epfd %d: calling libc_epoll_ctl: op %d, fd %d"
2443 " events 0x%x",
2444 epfd, op, fd, event ? event->events : 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002445
2446 rv = libc_epoll_ctl (epfd, op, fd, event);
Florin Coras99368312018-08-02 10:45:44 -07002447 goto done;
2448 }
2449
Florin Coras7baeb712019-01-04 17:05:43 -08002450 vlsh = ldp_fd_to_vlsh (fd);
Florin Coras99368312018-08-02 10:45:44 -07002451
Florin Coras7baeb712019-01-04 17:05:43 -08002452 LDBG (0, "epfd %d ep_vlsh %d, fd %u vlsh %d, op %u", epfd, vep_vlsh, fd,
2453 vlsh, op);
Florin Coras99368312018-08-02 10:45:44 -07002454
Florin Coras7baeb712019-01-04 17:05:43 -08002455 if (vlsh != VLS_INVALID_HANDLE)
Florin Coras99368312018-08-02 10:45:44 -07002456 {
Florin Corasc86662a2023-03-05 11:45:38 -08002457 LDBG (1,
2458 "epfd %d: calling vls_epoll_ctl: ep_vlsh %d op %d, vlsh %u,"
2459 " events 0x%x",
2460 epfd, vep_vlsh, op, vlsh, event ? event->events : 0);
Florin Coras99368312018-08-02 10:45:44 -07002461
Florin Coras7baeb712019-01-04 17:05:43 -08002462 rv = vls_epoll_ctl (vep_vlsh, op, vlsh, event);
Florin Coras99368312018-08-02 10:45:44 -07002463 if (rv != VPPCOM_OK)
2464 {
2465 errno = -rv;
2466 rv = -1;
2467 }
2468 }
2469 else
2470 {
2471 int libc_epfd;
2472 u32 size = sizeof (epfd);
2473
Florin Coras7baeb712019-01-04 17:05:43 -08002474 libc_epfd = vls_attr (vep_vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
Florin Coras99368312018-08-02 10:45:44 -07002475 if (!libc_epfd)
2476 {
Florin Coras7baeb712019-01-04 17:05:43 -08002477 LDBG (1, "epfd %d, vep_vlsh %d calling libc_epoll_create1: "
2478 "EPOLL_CLOEXEC", epfd, vep_vlsh);
Florin Coras99368312018-08-02 10:45:44 -07002479
2480 libc_epfd = libc_epoll_create1 (EPOLL_CLOEXEC);
2481 if (libc_epfd < 0)
2482 {
2483 rv = libc_epfd;
2484 goto done;
2485 }
2486
Florin Coras7baeb712019-01-04 17:05:43 -08002487 rv = vls_attr (vep_vlsh, VPPCOM_ATTR_SET_LIBC_EPFD, &libc_epfd,
2488 &size);
Florin Coras99368312018-08-02 10:45:44 -07002489 if (rv < 0)
2490 {
2491 errno = -rv;
2492 rv = -1;
2493 goto done;
2494 }
2495 }
2496 else if (PREDICT_FALSE (libc_epfd < 0))
2497 {
2498 errno = -epfd;
2499 rv = -1;
2500 goto done;
2501 }
2502
Florin Coras7baeb712019-01-04 17:05:43 -08002503 LDBG (1, "epfd %d: calling libc_epoll_ctl: libc_epfd %d, op %d, fd %d,"
2504 " event %p", epfd, libc_epfd, op, fd, event);
Florin Coras99368312018-08-02 10:45:44 -07002505
2506 rv = libc_epoll_ctl (libc_epfd, op, fd, event);
Dave Wallace048b1d62018-01-03 22:24:41 -05002507 }
2508
2509done:
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002510 return rv;
2511}
Dave Wallace048b1d62018-01-03 22:24:41 -05002512
2513static inline int
Florin Coras99368312018-08-02 10:45:44 -07002514ldp_epoll_pwait (int epfd, struct epoll_event *events, int maxevents,
2515 int timeout, const sigset_t * sigmask)
Dave Wallace048b1d62018-01-03 22:24:41 -05002516{
Liangxing Wang7c7231f2023-02-16 09:31:01 +00002517 ldp_worker_ctx_t *ldpw;
Florin Coras72f77822019-01-22 19:05:52 -08002518 double time_to_wait = (double) 0, max_time;
Florin Coras99368312018-08-02 10:45:44 -07002519 int libc_epfd, rv = 0;
Florin Coras7baeb712019-01-04 17:05:43 -08002520 vls_handle_t ep_vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002521
Florin Coras5f33d0d2021-06-02 21:22:21 -07002522 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05002523
2524 if (PREDICT_FALSE (!events || (timeout < -1)))
2525 {
2526 errno = EFAULT;
2527 return -1;
2528 }
2529
Liangxing Wang7c7231f2023-02-16 09:31:01 +00002530 if (PREDICT_FALSE (vppcom_worker_index () == ~0))
2531 vls_register_vcl_worker ();
2532
2533 ldpw = ldp_worker_get_current ();
Florin Corasdfe4cf42018-11-28 22:13:45 -08002534 if (epfd == ldpw->vcl_mq_epfd)
Florin Coras99368312018-08-02 10:45:44 -07002535 return libc_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
2536
Florin Coras7baeb712019-01-04 17:05:43 -08002537 ep_vlsh = ldp_fd_to_vlsh (epfd);
2538 if (PREDICT_FALSE (ep_vlsh == VLS_INVALID_HANDLE))
Dave Wallace048b1d62018-01-03 22:24:41 -05002539 {
Florin Coras7baeb712019-01-04 17:05:43 -08002540 LDBG (0, "epfd %d: bad ep_vlsh %d!", epfd, ep_vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05002541 errno = EBADFD;
2542 return -1;
2543 }
2544
Florin Coras4dee8cd2019-01-29 21:28:16 -08002545 if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
2546 clib_time_init (&ldpw->clib_time);
Florin Corasb0f662f2018-12-27 14:51:46 -08002547 time_to_wait = ((timeout >= 0) ? (double) timeout / 1000 : 0);
Florin Coras72f77822019-01-22 19:05:52 -08002548 max_time = clib_time_now (&ldpw->clib_time) + time_to_wait;
Dave Wallace048b1d62018-01-03 22:24:41 -05002549
Florin Coras7baeb712019-01-04 17:05:43 -08002550 libc_epfd = vls_attr (ep_vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002551 if (PREDICT_FALSE (libc_epfd < 0))
2552 {
2553 errno = -libc_epfd;
2554 rv = -1;
2555 goto done;
2556 }
2557
Florin Coras7baeb712019-01-04 17:05:43 -08002558 LDBG (2, "epfd %d: vep_idx %d, libc_epfd %d, events %p, maxevents %d, "
2559 "timeout %d, sigmask %p: time_to_wait %.02f", epfd, ep_vlsh,
Florin Coras72f77822019-01-22 19:05:52 -08002560 libc_epfd, events, maxevents, timeout, sigmask, time_to_wait);
Dave Wallace048b1d62018-01-03 22:24:41 -05002561 do
2562 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002563 if (!ldpw->epoll_wait_vcl)
Dave Wallace048b1d62018-01-03 22:24:41 -05002564 {
Florin Coras7baeb712019-01-04 17:05:43 -08002565 rv = vls_epoll_wait (ep_vlsh, events, maxevents, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002566 if (rv > 0)
2567 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002568 ldpw->epoll_wait_vcl = 1;
Dave Wallace048b1d62018-01-03 22:24:41 -05002569 goto done;
2570 }
2571 else if (rv < 0)
2572 {
2573 errno = -rv;
2574 rv = -1;
2575 goto done;
2576 }
2577 }
2578 else
Florin Corasdfe4cf42018-11-28 22:13:45 -08002579 ldpw->epoll_wait_vcl = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -05002580
2581 if (libc_epfd > 0)
2582 {
Florin Corasb0f662f2018-12-27 14:51:46 -08002583 rv = libc_epoll_pwait (libc_epfd, events, maxevents, 0, sigmask);
Dave Wallace048b1d62018-01-03 22:24:41 -05002584 if (rv != 0)
2585 goto done;
2586 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002587 }
Florin Coras72f77822019-01-22 19:05:52 -08002588 while ((timeout == -1) || (clib_time_now (&ldpw->clib_time) < max_time));
Dave Wallace048b1d62018-01-03 22:24:41 -05002589
2590done:
Dave Wallace048b1d62018-01-03 22:24:41 -05002591 return rv;
2592}
2593
hanlin4266d4d2020-05-19 17:34:17 +08002594static inline int
2595ldp_epoll_pwait_eventfd (int epfd, struct epoll_event *events,
2596 int maxevents, int timeout, const sigset_t * sigmask)
2597{
Florin Corasc86662a2023-03-05 11:45:38 -08002598 int libc_epfd, rv = 0, num_ev, libc_num_ev, vcl_wups = 0;
2599 struct epoll_event *libc_evts;
hanlina3a48962020-07-13 11:09:15 +08002600 ldp_worker_ctx_t *ldpw;
hanlin4266d4d2020-05-19 17:34:17 +08002601 vls_handle_t ep_vlsh;
2602
Florin Coras5f33d0d2021-06-02 21:22:21 -07002603 ldp_init_check ();
hanlin4266d4d2020-05-19 17:34:17 +08002604
2605 if (PREDICT_FALSE (!events || (timeout < -1)))
2606 {
2607 errno = EFAULT;
2608 return -1;
2609 }
2610
Florin Corasff40d8f2020-08-11 22:05:28 -07002611 /* Make sure the vcl worker is valid. Could be that epoll fd was created on
2612 * one thread but it is now used on another */
2613 if (PREDICT_FALSE (vppcom_worker_index () == ~0))
2614 vls_register_vcl_worker ();
hanlina3a48962020-07-13 11:09:15 +08002615
2616 ldpw = ldp_worker_get_current ();
hanlin4266d4d2020-05-19 17:34:17 +08002617 if (epfd == ldpw->vcl_mq_epfd)
2618 return libc_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
2619
2620 ep_vlsh = ldp_fd_to_vlsh (epfd);
2621 if (PREDICT_FALSE (ep_vlsh == VLS_INVALID_HANDLE))
2622 {
2623 LDBG (0, "epfd %d: bad ep_vlsh %d!", epfd, ep_vlsh);
2624 errno = EBADFD;
2625 return -1;
2626 }
2627
2628 libc_epfd = vls_attr (ep_vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
2629 if (PREDICT_FALSE (!libc_epfd))
2630 {
2631 u32 size = sizeof (epfd);
2632
2633 LDBG (1, "epfd %d, vep_vlsh %d calling libc_epoll_create1: "
2634 "EPOLL_CLOEXEC", epfd, ep_vlsh);
2635 libc_epfd = libc_epoll_create1 (EPOLL_CLOEXEC);
2636 if (libc_epfd < 0)
2637 {
2638 rv = libc_epfd;
2639 goto done;
2640 }
2641
2642 rv = vls_attr (ep_vlsh, VPPCOM_ATTR_SET_LIBC_EPFD, &libc_epfd, &size);
2643 if (rv < 0)
2644 {
2645 errno = -rv;
2646 rv = -1;
2647 goto done;
2648 }
2649 }
2650 if (PREDICT_FALSE (libc_epfd <= 0))
2651 {
2652 errno = -libc_epfd;
2653 rv = -1;
2654 goto done;
2655 }
2656
2657 if (PREDICT_FALSE (!ldpw->mq_epfd_added))
2658 {
2659 struct epoll_event e = { 0 };
2660 e.events = EPOLLIN;
2661 e.data.fd = ldpw->vcl_mq_epfd;
2662 if (libc_epoll_ctl (libc_epfd, EPOLL_CTL_ADD, ldpw->vcl_mq_epfd, &e) <
2663 0)
2664 {
2665 LDBG (0, "epfd %d, add libc mq epoll fd %d to libc epoll fd %d",
2666 epfd, ldpw->vcl_mq_epfd, libc_epfd);
2667 rv = -1;
2668 goto done;
2669 }
2670 ldpw->mq_epfd_added = 1;
2671 }
2672
wanghanlin8919fec2021-03-18 20:00:41 +08002673 /* Request to only drain unhandled to prevent libc_epoll_wait starved */
2674 rv = vls_epoll_wait (ep_vlsh, events, maxevents, -2);
hanlin4266d4d2020-05-19 17:34:17 +08002675 if (rv > 0)
Florin Corasc86662a2023-03-05 11:45:38 -08002676 {
2677 timeout = 0;
2678 if (rv >= maxevents)
2679 goto done;
2680 }
hanlina3a48962020-07-13 11:09:15 +08002681 else if (PREDICT_FALSE (rv < 0))
hanlin4266d4d2020-05-19 17:34:17 +08002682 {
2683 errno = -rv;
2684 rv = -1;
2685 goto done;
2686 }
2687
Florin Coras7a1e95a2023-03-01 00:45:31 -08002688epoll_again:
Florin Corasc86662a2023-03-05 11:45:38 -08002689
2690 libc_evts = &events[rv];
2691 libc_num_ev =
2692 libc_epoll_pwait (libc_epfd, libc_evts, maxevents - rv, timeout, sigmask);
2693 if (libc_num_ev <= 0)
hanlin4266d4d2020-05-19 17:34:17 +08002694 {
Florin Corasc86662a2023-03-05 11:45:38 -08002695 rv = rv >= 0 ? rv : -1;
2696 goto done;
2697 }
2698
2699 for (int i = 0; i < libc_num_ev; i++)
2700 {
2701 if (libc_evts[i].data.fd == ldpw->vcl_mq_epfd)
hanlin4266d4d2020-05-19 17:34:17 +08002702 {
2703 /* We should remove mq epoll fd from events. */
Florin Corasc86662a2023-03-05 11:45:38 -08002704 libc_num_ev--;
2705 if (i != libc_num_ev)
hanlin4266d4d2020-05-19 17:34:17 +08002706 {
Florin Corasc86662a2023-03-05 11:45:38 -08002707 libc_evts[i].events = libc_evts[libc_num_ev].events;
2708 libc_evts[i].data.u64 = libc_evts[libc_num_ev].data.u64;
hanlin4266d4d2020-05-19 17:34:17 +08002709 }
Florin Corasc86662a2023-03-05 11:45:38 -08002710 num_ev = vls_epoll_wait (ep_vlsh, &libc_evts[libc_num_ev],
2711 maxevents - libc_num_ev, 0);
hanlin4266d4d2020-05-19 17:34:17 +08002712 if (PREDICT_TRUE (num_ev > 0))
2713 rv += num_ev;
Florin Coras7a1e95a2023-03-01 00:45:31 -08002714 /* Woken up by vcl but no events generated. Accept it once */
Florin Corasc86662a2023-03-05 11:45:38 -08002715 if (rv == 0 && libc_num_ev == 0 && timeout && vcl_wups++ < 1)
Florin Coras7a1e95a2023-03-01 00:45:31 -08002716 goto epoll_again;
hanlin4266d4d2020-05-19 17:34:17 +08002717 break;
2718 }
2719 }
2720
Florin Corasc86662a2023-03-05 11:45:38 -08002721 rv += libc_num_ev;
2722
hanlin4266d4d2020-05-19 17:34:17 +08002723done:
2724 return rv;
2725}
2726
Dave Wallace048b1d62018-01-03 22:24:41 -05002727int
2728epoll_pwait (int epfd, struct epoll_event *events,
2729 int maxevents, int timeout, const sigset_t * sigmask)
2730{
hanlin4266d4d2020-05-19 17:34:17 +08002731 if (vls_use_eventfd ())
2732 return ldp_epoll_pwait_eventfd (epfd, events, maxevents, timeout,
2733 sigmask);
2734 else
2735 return ldp_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
Dave Wallace048b1d62018-01-03 22:24:41 -05002736}
2737
2738int
2739epoll_wait (int epfd, struct epoll_event *events, int maxevents, int timeout)
2740{
hanlin4266d4d2020-05-19 17:34:17 +08002741 if (vls_use_eventfd ())
2742 return ldp_epoll_pwait_eventfd (epfd, events, maxevents, timeout, NULL);
2743 else
2744 return ldp_epoll_pwait (epfd, events, maxevents, timeout, NULL);
Dave Wallace048b1d62018-01-03 22:24:41 -05002745}
2746
2747int
2748poll (struct pollfd *fds, nfds_t nfds, int timeout)
2749{
Florin Corasdfe4cf42018-11-28 22:13:45 -08002750 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras6917b942018-11-13 22:44:54 -08002751 int rv, i, n_revents = 0;
Florin Coras7baeb712019-01-04 17:05:43 -08002752 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002753 vcl_poll_t *vp;
Florin Coras4dee8cd2019-01-29 21:28:16 -08002754 double max_time;
Dave Wallace048b1d62018-01-03 22:24:41 -05002755
Florin Coraseb801d02020-09-16 17:44:58 -07002756 LDBG (3, "fds %p, nfds %ld, timeout %d", fds, nfds, timeout);
Dave Wallace048b1d62018-01-03 22:24:41 -05002757
Florin Coras4dee8cd2019-01-29 21:28:16 -08002758 if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
2759 clib_time_init (&ldpw->clib_time);
2760
2761 max_time = (timeout >= 0) ? (f64) timeout / 1000 : 0;
2762 max_time += clib_time_now (&ldpw->clib_time);
Dave Wallace048b1d62018-01-03 22:24:41 -05002763
Dave Wallace048b1d62018-01-03 22:24:41 -05002764 for (i = 0; i < nfds; i++)
2765 {
Florin Coras6917b942018-11-13 22:44:54 -08002766 if (fds[i].fd < 0)
2767 continue;
Dave Wallace048b1d62018-01-03 22:24:41 -05002768
Florin Coras7baeb712019-01-04 17:05:43 -08002769 vlsh = ldp_fd_to_vlsh (fds[i].fd);
2770 if (vlsh != VLS_INVALID_HANDLE)
Florin Coras6917b942018-11-13 22:44:54 -08002771 {
2772 fds[i].fd = -fds[i].fd;
Florin Corasdfe4cf42018-11-28 22:13:45 -08002773 vec_add2 (ldpw->vcl_poll, vp, 1);
Florin Coras6917b942018-11-13 22:44:54 -08002774 vp->fds_ndx = i;
Florin Coras7baeb712019-01-04 17:05:43 -08002775 vp->sh = vlsh_to_sh (vlsh);
Florin Coras6917b942018-11-13 22:44:54 -08002776 vp->events = fds[i].events;
Dave Wallace048b1d62018-01-03 22:24:41 -05002777#ifdef __USE_XOPEN2K
Florin Coras6917b942018-11-13 22:44:54 -08002778 if (fds[i].events & POLLRDNORM)
2779 vp->events |= POLLIN;
2780 if (fds[i].events & POLLWRNORM)
2781 vp->events |= POLLOUT;
Dave Wallace048b1d62018-01-03 22:24:41 -05002782#endif
Florin Coras6917b942018-11-13 22:44:54 -08002783 vp->revents = fds[i].revents;
2784 }
2785 else
2786 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002787 vec_add1 (ldpw->libc_poll, fds[i]);
2788 vec_add1 (ldpw->libc_poll_idxs, i);
Dave Wallace048b1d62018-01-03 22:24:41 -05002789 }
2790 }
2791
Dave Wallace048b1d62018-01-03 22:24:41 -05002792 do
2793 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002794 if (vec_len (ldpw->vcl_poll))
Dave Wallace048b1d62018-01-03 22:24:41 -05002795 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002796 rv = vppcom_poll (ldpw->vcl_poll, vec_len (ldpw->vcl_poll), 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002797 if (rv < 0)
2798 {
2799 errno = -rv;
2800 rv = -1;
2801 goto done;
2802 }
2803 else
2804 n_revents += rv;
2805 }
2806
Florin Corasdfe4cf42018-11-28 22:13:45 -08002807 if (vec_len (ldpw->libc_poll))
Dave Wallace048b1d62018-01-03 22:24:41 -05002808 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002809 rv = libc_poll (ldpw->libc_poll, vec_len (ldpw->libc_poll), 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002810 if (rv < 0)
2811 goto done;
2812 else
2813 n_revents += rv;
2814 }
2815
2816 if (n_revents)
2817 {
2818 rv = n_revents;
2819 goto done;
2820 }
2821 }
Florin Coras4dee8cd2019-01-29 21:28:16 -08002822 while ((timeout < 0) || (clib_time_now (&ldpw->clib_time) < max_time));
Dave Wallace048b1d62018-01-03 22:24:41 -05002823 rv = 0;
2824
2825done:
Florin Corasdfe4cf42018-11-28 22:13:45 -08002826 vec_foreach (vp, ldpw->vcl_poll)
Dave Wallace048b1d62018-01-03 22:24:41 -05002827 {
2828 fds[vp->fds_ndx].fd = -fds[vp->fds_ndx].fd;
Florin Coras6917b942018-11-13 22:44:54 -08002829 fds[vp->fds_ndx].revents = vp->revents;
Dave Wallace048b1d62018-01-03 22:24:41 -05002830#ifdef __USE_XOPEN2K
2831 if ((fds[vp->fds_ndx].revents & POLLIN) &&
2832 (fds[vp->fds_ndx].events & POLLRDNORM))
2833 fds[vp->fds_ndx].revents |= POLLRDNORM;
2834 if ((fds[vp->fds_ndx].revents & POLLOUT) &&
2835 (fds[vp->fds_ndx].events & POLLWRNORM))
2836 fds[vp->fds_ndx].revents |= POLLWRNORM;
2837#endif
2838 }
Florin Corasdfe4cf42018-11-28 22:13:45 -08002839 vec_reset_length (ldpw->vcl_poll);
Dave Wallace048b1d62018-01-03 22:24:41 -05002840
Florin Corasdfe4cf42018-11-28 22:13:45 -08002841 for (i = 0; i < vec_len (ldpw->libc_poll); i++)
Florin Coras6917b942018-11-13 22:44:54 -08002842 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002843 fds[ldpw->libc_poll_idxs[i]].revents = ldpw->libc_poll[i].revents;
Florin Coras6917b942018-11-13 22:44:54 -08002844 }
Florin Corasdfe4cf42018-11-28 22:13:45 -08002845 vec_reset_length (ldpw->libc_poll_idxs);
2846 vec_reset_length (ldpw->libc_poll);
Florin Coras6917b942018-11-13 22:44:54 -08002847
Dave Wallace048b1d62018-01-03 22:24:41 -05002848 return rv;
2849}
2850
Florin Coras36847942023-02-02 12:56:16 -08002851#ifdef _GNU_SOURCE
Dave Wallace048b1d62018-01-03 22:24:41 -05002852int
2853ppoll (struct pollfd *fds, nfds_t nfds,
2854 const struct timespec *timeout, const sigset_t * sigmask)
2855{
Florin Coras5f33d0d2021-06-02 21:22:21 -07002856 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05002857
2858 clib_warning ("LDP<%d>: LDP-TBD", getpid ());
2859 errno = ENOSYS;
2860
2861
2862 return -1;
2863}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002864#endif
2865
Dave Wallace2a865272018-02-07 21:00:42 -05002866void CONSTRUCTOR_ATTRIBUTE ldp_constructor (void);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002867
Dave Wallace2a865272018-02-07 21:00:42 -05002868void DESTRUCTOR_ATTRIBUTE ldp_destructor (void);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002869
Dave Wallace048b1d62018-01-03 22:24:41 -05002870/*
2871 * This function is called when the library is loaded
2872 */
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002873void
Dave Wallace2a865272018-02-07 21:00:42 -05002874ldp_constructor (void)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002875{
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002876 swrap_constructor ();
Dave Wallace2a865272018-02-07 21:00:42 -05002877 if (ldp_init () != 0)
Florin Corasd89411e2019-03-19 19:44:51 -07002878 {
2879 fprintf (stderr, "\nLDP<%d>: ERROR: ldp_constructor: failed!\n",
2880 getpid ());
2881 _exit (1);
2882 }
Dave Wallace69d01192018-02-22 16:22:09 -05002883 else if (LDP_DEBUG > 0)
Dave Wallace2a865272018-02-07 21:00:42 -05002884 clib_warning ("LDP<%d>: LDP constructor: done!\n", getpid ());
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002885}
2886
2887/*
2888 * This function is called when the library is unloaded
2889 */
2890void
Dave Wallace2a865272018-02-07 21:00:42 -05002891ldp_destructor (void)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002892{
Florin Coras0ef8ef22019-01-18 08:37:13 -08002893 /*
2894 swrap_destructor ();
2895 if (ldp->init)
2896 ldp->init = 0;
2897 */
Dave Wallace048b1d62018-01-03 22:24:41 -05002898
2899 /* Don't use clib_warning() here because that calls writev()
Dave Wallace2a865272018-02-07 21:00:42 -05002900 * which will call ldp_init().
Dave Wallace048b1d62018-01-03 22:24:41 -05002901 */
Dave Wallace69d01192018-02-22 16:22:09 -05002902 if (LDP_DEBUG > 0)
Florin Coras0ef8ef22019-01-18 08:37:13 -08002903 fprintf (stderr, "%s:%d: LDP<%d>: LDP destructor: done!\n",
2904 __func__, __LINE__, getpid ());
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002905}
2906
2907
2908/*
2909 * fd.io coding-style-patch-verification: ON
2910 *
2911 * Local Variables:
2912 * eval: (c-set-style "gnu")
2913 * End:
2914 */