blob: 79e7cf3ee3257830eeec1fbc8b3d48dbd205cb52 [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
Gao Feng96600f92023-07-17 22:19:32 +0800291 if (ldp->init)
292 {
293 LDBG (0, "LDP is initialized already");
294 return 0;
295 }
Florin Corasc6c4e862023-03-09 18:23:05 -0800296
297 ldp_init_cfg ();
298 ldp->init = 1;
299 ldp->vcl_needs_real_epoll = 1;
300 rv = vls_app_create (ldp_get_app_name ());
301 if (rv != VPPCOM_OK)
302 {
303 ldp->vcl_needs_real_epoll = 0;
304 if (rv == VPPCOM_EEXIST)
305 return 0;
306 LDBG (2,
307 "\nERROR: ldp_init: vppcom_app_create()"
308 " failed! rv = %d (%s)\n",
309 rv, vppcom_retval_str (rv));
310 ldp->init = 0;
311 return rv;
312 }
313 ldp->vcl_needs_real_epoll = 0;
314 ldp_alloc_workers ();
315 ldpw = ldp_worker_get_current ();
316
Damjan Marionb2c31b62020-12-13 21:47:40 +0100317 pool_foreach (ldpw, ldp->workers) {
Florin Coras4dee8cd2019-01-29 21:28:16 -0800318 clib_memset (&ldpw->clib_time, 0, sizeof (ldpw->clib_time));
Damjan Marionb2c31b62020-12-13 21:47:40 +0100319 }
Florin Coras4dee8cd2019-01-29 21:28:16 -0800320
Florin Coras05ecfcc2018-12-12 18:19:39 -0800321 LDBG (0, "LDP initialization: done!");
Florin Coras99368312018-08-02 10:45:44 -0700322
323 return 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500324}
325
Florin Coras5f33d0d2021-06-02 21:22:21 -0700326#define ldp_init_check() \
327 if (PREDICT_FALSE (!ldp->init)) \
328 { \
329 if ((errno = -ldp_init ())) \
330 return -1; \
331 }
332
Dave Wallace048b1d62018-01-03 22:24:41 -0500333int
334close (int fd)
335{
Florin Coras7baeb712019-01-04 17:05:43 -0800336 vls_handle_t vlsh;
337 int rv, epfd;
Dave Wallace048b1d62018-01-03 22:24:41 -0500338
Florin Coras5f33d0d2021-06-02 21:22:21 -0700339 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -0500340
Florin Coras7baeb712019-01-04 17:05:43 -0800341 vlsh = ldp_fd_to_vlsh (fd);
342 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500343 {
Florin Coras7baeb712019-01-04 17:05:43 -0800344 epfd = vls_attr (vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -0500345 if (epfd > 0)
346 {
Florin Coras06defbc2023-02-28 22:32:31 -0800347 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
348 u32 size = sizeof (epfd);
349
Florin Coras7baeb712019-01-04 17:05:43 -0800350 LDBG (0, "fd %d: calling libc_close: epfd %u", fd, epfd);
Dave Wallace048b1d62018-01-03 22:24:41 -0500351
Florin Coras06defbc2023-02-28 22:32:31 -0800352 libc_close (epfd);
353 ldpw->mq_epfd_added = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500354
Florin Coras06defbc2023-02-28 22:32:31 -0800355 epfd = 0;
356 (void) vls_attr (vlsh, VPPCOM_ATTR_SET_LIBC_EPFD, &epfd, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -0500357 }
358 else if (PREDICT_FALSE (epfd < 0))
359 {
360 errno = -epfd;
361 rv = -1;
362 goto done;
363 }
364
Florin Coras7baeb712019-01-04 17:05:43 -0800365 LDBG (0, "fd %d: calling vls_close: vlsh %u", fd, vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -0500366
Florin Coras7baeb712019-01-04 17:05:43 -0800367 rv = vls_close (vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -0500368 if (rv != VPPCOM_OK)
369 {
370 errno = -rv;
371 rv = -1;
372 }
373 }
374 else
375 {
Florin Coras7baeb712019-01-04 17:05:43 -0800376 LDBG (0, "fd %d: calling libc_close", fd);
Dave Wallace048b1d62018-01-03 22:24:41 -0500377 rv = libc_close (fd);
378 }
379
380done:
Dave Wallace048b1d62018-01-03 22:24:41 -0500381 return rv;
382}
383
384ssize_t
385read (int fd, void *buf, size_t nbytes)
386{
Florin Coras7baeb712019-01-04 17:05:43 -0800387 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500388 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -0500389
Florin Coras5f33d0d2021-06-02 21:22:21 -0700390 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -0500391
Florin Coras7baeb712019-01-04 17:05:43 -0800392 vlsh = ldp_fd_to_vlsh (fd);
393 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500394 {
Florin Coras7baeb712019-01-04 17:05:43 -0800395 size = vls_read (vlsh, buf, nbytes);
Dave Wallace048b1d62018-01-03 22:24:41 -0500396 if (size < 0)
397 {
398 errno = -size;
399 size = -1;
400 }
401 }
402 else
403 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500404 size = libc_read (fd, buf, nbytes);
405 }
406
Dave Wallace048b1d62018-01-03 22:24:41 -0500407 return size;
408}
409
410ssize_t
411readv (int fd, const struct iovec * iov, int iovcnt)
412{
Dave Wallace8aaba562018-01-18 17:21:19 -0500413 int rv = 0, i, total = 0;
Florin Coras7baeb712019-01-04 17:05:43 -0800414 vls_handle_t vlsh;
415 ssize_t size = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500416
Florin Coras5f33d0d2021-06-02 21:22:21 -0700417 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -0500418
Florin Coras7baeb712019-01-04 17:05:43 -0800419 vlsh = ldp_fd_to_vlsh (fd);
420 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500421 {
Florin Coras067f9542020-02-14 05:33:46 +0000422 for (i = 0; i < iovcnt; ++i)
Dave Wallace048b1d62018-01-03 22:24:41 -0500423 {
Florin Coras067f9542020-02-14 05:33:46 +0000424 rv = vls_read (vlsh, iov[i].iov_base, iov[i].iov_len);
425 if (rv <= 0)
426 break;
427 else
Dave Wallace048b1d62018-01-03 22:24:41 -0500428 {
Florin Coras067f9542020-02-14 05:33:46 +0000429 total += rv;
430 if (rv < iov[i].iov_len)
Dave Wallace048b1d62018-01-03 22:24:41 -0500431 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700432 }
433 }
Florin Coras067f9542020-02-14 05:33:46 +0000434 if (rv < 0 && total == 0)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700435 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500436 errno = -rv;
437 size = -1;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700438 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500439 else
440 size = total;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700441 }
442 else
443 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500444 size = libc_readv (fd, iov, iovcnt);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700445 }
446
Dave Wallace048b1d62018-01-03 22:24:41 -0500447 return size;
448}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700449
Dave Wallace048b1d62018-01-03 22:24:41 -0500450ssize_t
451write (int fd, const void *buf, size_t nbytes)
452{
Florin Coras7baeb712019-01-04 17:05:43 -0800453 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500454 ssize_t size = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500455
Florin Coras5f33d0d2021-06-02 21:22:21 -0700456 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -0500457
Florin Coras7baeb712019-01-04 17:05:43 -0800458 vlsh = ldp_fd_to_vlsh (fd);
459 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500460 {
Florin Coras7baeb712019-01-04 17:05:43 -0800461 size = vls_write_msg (vlsh, (void *) buf, nbytes);
Dave Wallace048b1d62018-01-03 22:24:41 -0500462 if (size < 0)
463 {
464 errno = -size;
465 size = -1;
466 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700467 }
468 else
469 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500470 size = libc_write (fd, buf, nbytes);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700471 }
472
Dave Wallace048b1d62018-01-03 22:24:41 -0500473 return size;
474}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700475
Dave Wallace048b1d62018-01-03 22:24:41 -0500476ssize_t
477writev (int fd, const struct iovec * iov, int iovcnt)
478{
Dave Wallace048b1d62018-01-03 22:24:41 -0500479 ssize_t size = 0, total = 0;
Florin Coras7baeb712019-01-04 17:05:43 -0800480 vls_handle_t vlsh;
Dave Wallace8aaba562018-01-18 17:21:19 -0500481 int i, rv = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500482
Florin Coras5f33d0d2021-06-02 21:22:21 -0700483 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -0500484
Florin Coras7baeb712019-01-04 17:05:43 -0800485 vlsh = ldp_fd_to_vlsh (fd);
486 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -0500487 {
Florin Coraseda1b8c2020-03-23 16:00:35 +0000488 for (i = 0; i < iovcnt; ++i)
Dave Wallace048b1d62018-01-03 22:24:41 -0500489 {
Florin Coraseda1b8c2020-03-23 16:00:35 +0000490 rv = vls_write_msg (vlsh, iov[i].iov_base, iov[i].iov_len);
491 if (rv < 0)
492 break;
493 else
Dave Wallace048b1d62018-01-03 22:24:41 -0500494 {
Florin Coraseda1b8c2020-03-23 16:00:35 +0000495 total += rv;
496 if (rv < iov[i].iov_len)
Dave Wallace048b1d62018-01-03 22:24:41 -0500497 break;
Dave Wallace048b1d62018-01-03 22:24:41 -0500498 }
499 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500500
Florin Coraseda1b8c2020-03-23 16:00:35 +0000501 if (rv < 0 && total == 0)
Dave Wallace048b1d62018-01-03 22:24:41 -0500502 {
503 errno = -rv;
504 size = -1;
505 }
506 else
507 size = total;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700508 }
509 else
510 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500511 size = libc_writev (fd, iov, iovcnt);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700512 }
513
Dave Wallace048b1d62018-01-03 22:24:41 -0500514 return size;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700515}
516
Florin Coras0ab36f52020-05-26 19:45:45 +0000517static int
518fcntl_internal (int fd, int cmd, va_list ap)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700519{
Florin Coras7baeb712019-01-04 17:05:43 -0800520 vls_handle_t vlsh;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700521 int rv = 0;
Florin Coras7baeb712019-01-04 17:05:43 -0800522
523 vlsh = ldp_fd_to_vlsh (fd);
524 LDBG (0, "fd %u vlsh %d, cmd %u", fd, vlsh, cmd);
525 if (vlsh != VLS_INVALID_HANDLE)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700526 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500527 int flags = va_arg (ap, int);
528 u32 size;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700529
Dave Wallace048b1d62018-01-03 22:24:41 -0500530 size = sizeof (flags);
531 rv = -EOPNOTSUPP;
532 switch (cmd)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700533 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500534 case F_SETFL:
Florin Coras7baeb712019-01-04 17:05:43 -0800535 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_FLAGS, &flags, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -0500536 break;
537
538 case F_GETFL:
Florin Coras7baeb712019-01-04 17:05:43 -0800539 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_FLAGS, &flags, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -0500540 if (rv == VPPCOM_OK)
Florin Coras7baeb712019-01-04 17:05:43 -0800541 rv = flags;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700542 break;
Florin Coras173bae32018-11-16 18:56:28 -0800543 case F_SETFD:
544 /* TODO handle this */
545 LDBG (0, "F_SETFD ignored flags %u", flags);
546 rv = 0;
547 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700548 default:
Dave Wallace048b1d62018-01-03 22:24:41 -0500549 rv = -EOPNOTSUPP;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700550 break;
551 }
Dave Wallace048b1d62018-01-03 22:24:41 -0500552 if (rv < 0)
553 {
554 errno = -rv;
555 rv = -1;
556 }
557 }
558 else
559 {
Carl Smithe16707b2019-11-13 14:37:39 +1300560#ifdef HAVE_FCNTL64
561 rv = libc_vfcntl64 (fd, cmd, ap);
562#else
Dave Wallace048b1d62018-01-03 22:24:41 -0500563 rv = libc_vfcntl (fd, cmd, ap);
Carl Smithe16707b2019-11-13 14:37:39 +1300564#endif
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -0700565 }
566
Florin Coras0ab36f52020-05-26 19:45:45 +0000567 return rv;
568}
569
570int
571fcntl (int fd, int cmd, ...)
572{
573 va_list ap;
574 int rv;
575
Florin Coras5f33d0d2021-06-02 21:22:21 -0700576 ldp_init_check ();
Florin Coras0ab36f52020-05-26 19:45:45 +0000577
578 va_start (ap, cmd);
579 rv = fcntl_internal (fd, cmd, ap);
Dave Wallace048b1d62018-01-03 22:24:41 -0500580 va_end (ap);
581
Dave Wallace048b1d62018-01-03 22:24:41 -0500582 return rv;
583}
584
585int
Florin Corasd7586d52020-04-29 02:19:51 +0000586fcntl64 (int fd, int cmd, ...)
587{
588 va_list ap;
589 int rv;
590
Florin Coras5f33d0d2021-06-02 21:22:21 -0700591 ldp_init_check ();
Florin Coras0ab36f52020-05-26 19:45:45 +0000592
Florin Corasd7586d52020-04-29 02:19:51 +0000593 va_start (ap, cmd);
Florin Coras0ab36f52020-05-26 19:45:45 +0000594 rv = fcntl_internal (fd, cmd, ap);
Florin Corasd7586d52020-04-29 02:19:51 +0000595 va_end (ap);
596 return rv;
597}
598
599int
Dave Wallace048b1d62018-01-03 22:24:41 -0500600ioctl (int fd, unsigned long int cmd, ...)
601{
Florin Coras7baeb712019-01-04 17:05:43 -0800602 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -0500603 va_list ap;
Florin Coras7baeb712019-01-04 17:05:43 -0800604 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -0500605
Florin Coras5f33d0d2021-06-02 21:22:21 -0700606 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -0500607
608 va_start (ap, cmd);
Dave Wallace048b1d62018-01-03 22:24:41 -0500609
Florin Coras7baeb712019-01-04 17:05:43 -0800610 vlsh = ldp_fd_to_vlsh (fd);
611 if (vlsh != VLS_INVALID_HANDLE)
612 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500613 switch (cmd)
614 {
615 case FIONREAD:
Florin Coras7baeb712019-01-04 17:05:43 -0800616 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_NREAD, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -0500617 break;
618
619 case FIONBIO:
620 {
Florin Coras4a0e08e2023-05-11 11:45:34 -0700621 u32 flags = *(va_arg (ap, int *)) ? O_NONBLOCK : 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500622 u32 size = sizeof (flags);
623
624 /* TBD: When VPPCOM_ATTR_[GS]ET_FLAGS supports flags other than
625 * non-blocking, the flags should be read here and merged
626 * with O_NONBLOCK.
627 */
Florin Coras7baeb712019-01-04 17:05:43 -0800628 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_FLAGS, &flags, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -0500629 }
630 break;
631
632 default:
633 rv = -EOPNOTSUPP;
634 break;
635 }
636 if (rv < 0)
637 {
638 errno = -rv;
639 rv = -1;
640 }
641 }
642 else
643 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500644 rv = libc_vioctl (fd, cmd, ap);
645 }
646
Dave Wallace048b1d62018-01-03 22:24:41 -0500647 va_end (ap);
648 return rv;
649}
650
Florin Coras294afe22019-01-07 17:49:17 -0800651always_inline void
652ldp_select_init_maps (fd_set * __restrict original,
653 clib_bitmap_t ** resultb, clib_bitmap_t ** libcb,
654 clib_bitmap_t ** vclb, int nfds, u32 minbits,
655 u32 n_bytes, uword * si_bits, uword * libc_bits)
656{
657 uword si_bits_set, libc_bits_set;
658 vls_handle_t vlsh;
659 int fd;
660
661 clib_bitmap_validate (*vclb, minbits);
662 clib_bitmap_validate (*libcb, minbits);
663 clib_bitmap_validate (*resultb, minbits);
664 clib_memcpy_fast (*resultb, original, n_bytes);
665 memset (original, 0, n_bytes);
666
667 /* *INDENT-OFF* */
Damjan Marionf0ca1e82020-12-13 23:26:56 +0100668 clib_bitmap_foreach (fd, *resultb) {
Florin Coras294afe22019-01-07 17:49:17 -0800669 if (fd > nfds)
670 break;
671 vlsh = ldp_fd_to_vlsh (fd);
672 if (vlsh == VLS_INVALID_HANDLE)
673 clib_bitmap_set_no_check (*libcb, fd, 1);
674 else
Florin Corascbce80a2020-04-20 01:32:38 +0000675 *vclb = clib_bitmap_set (*vclb, vlsh_to_session_index (vlsh), 1);
Damjan Marionf0ca1e82020-12-13 23:26:56 +0100676 }
Florin Coras294afe22019-01-07 17:49:17 -0800677 /* *INDENT-ON* */
678
679 si_bits_set = clib_bitmap_last_set (*vclb) + 1;
680 *si_bits = (si_bits_set > *si_bits) ? si_bits_set : *si_bits;
Florin Corascbce80a2020-04-20 01:32:38 +0000681 clib_bitmap_validate (*resultb, *si_bits);
Florin Coras294afe22019-01-07 17:49:17 -0800682
683 libc_bits_set = clib_bitmap_last_set (*libcb) + 1;
684 *libc_bits = (libc_bits_set > *libc_bits) ? libc_bits_set : *libc_bits;
685}
686
687always_inline int
688ldp_select_vcl_map_to_libc (clib_bitmap_t * vclb, fd_set * __restrict libcb)
689{
690 vls_handle_t vlsh;
691 uword si;
692 int fd;
693
694 if (!libcb)
695 return 0;
696
697 /* *INDENT-OFF* */
Damjan Marionf0ca1e82020-12-13 23:26:56 +0100698 clib_bitmap_foreach (si, vclb) {
Florin Coras294afe22019-01-07 17:49:17 -0800699 vlsh = vls_session_index_to_vlsh (si);
Florin Coras54140622020-02-04 19:04:34 +0000700 ASSERT (vlsh != VLS_INVALID_HANDLE);
Florin Coras294afe22019-01-07 17:49:17 -0800701 fd = ldp_vlsh_to_fd (vlsh);
702 if (PREDICT_FALSE (fd < 0))
703 {
704 errno = EBADFD;
705 return -1;
706 }
707 FD_SET (fd, libcb);
Damjan Marionf0ca1e82020-12-13 23:26:56 +0100708 }
Florin Coras294afe22019-01-07 17:49:17 -0800709 /* *INDENT-ON* */
710
711 return 0;
712}
713
714always_inline void
715ldp_select_libc_map_merge (clib_bitmap_t * result, fd_set * __restrict libcb)
716{
717 uword fd;
718
Florin Coras78b5fa62019-02-21 20:04:15 -0800719 if (!libcb)
720 return;
721
Florin Coras294afe22019-01-07 17:49:17 -0800722 /* *INDENT-OFF* */
Damjan Marionf0ca1e82020-12-13 23:26:56 +0100723 clib_bitmap_foreach (fd, result)
Florin Coras294afe22019-01-07 17:49:17 -0800724 FD_SET ((int)fd, libcb);
Florin Coras294afe22019-01-07 17:49:17 -0800725 /* *INDENT-ON* */
726}
727
Dave Wallace048b1d62018-01-03 22:24:41 -0500728int
Dave Wallace2a865272018-02-07 21:00:42 -0500729ldp_pselect (int nfds, fd_set * __restrict readfds,
730 fd_set * __restrict writefds,
731 fd_set * __restrict exceptfds,
732 const struct timespec *__restrict timeout,
733 const __sigset_t * __restrict sigmask)
Dave Wallace048b1d62018-01-03 22:24:41 -0500734{
Florin Coras294afe22019-01-07 17:49:17 -0800735 u32 minbits = clib_max (nfds, BITS (uword)), n_bytes;
Florin Corasdfe4cf42018-11-28 22:13:45 -0800736 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras294afe22019-01-07 17:49:17 -0800737 struct timespec libc_tspec = { 0 };
738 f64 time_out, vcl_timeout = 0;
739 uword si_bits, libc_bits;
740 int rv, bits_set = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -0500741
742 if (nfds < 0)
743 {
744 errno = EINVAL;
745 return -1;
746 }
747
Florin Coras4dee8cd2019-01-29 21:28:16 -0800748 if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
749 clib_time_init (&ldpw->clib_time);
750
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500751 if (timeout)
752 {
753 time_out = (timeout->tv_sec == 0 && timeout->tv_nsec == 0) ?
Florin Coras7baeb712019-01-04 17:05:43 -0800754 (f64) 0 : (f64) timeout->tv_sec + (f64) timeout->tv_nsec / (f64) 1e9;
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500755
liuyacanf71796e2021-08-02 10:01:39 +0800756 time_out += clib_time_now (&ldpw->clib_time);
757
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500758 /* select as fine grained sleep */
759 if (!nfds)
760 {
Florin Corasdfe4cf42018-11-28 22:13:45 -0800761 while (clib_time_now (&ldpw->clib_time) < time_out)
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500762 ;
763 return 0;
764 }
765 }
766 else if (!nfds)
767 {
768 errno = EINVAL;
769 return -1;
770 }
771 else
772 time_out = -1;
773
Florin Coras7baeb712019-01-04 17:05:43 -0800774 if (nfds <= ldp->vlsh_bit_val)
Dave Wallace048b1d62018-01-03 22:24:41 -0500775 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500776 rv = libc_pselect (nfds, readfds, writefds, exceptfds,
777 timeout, sigmask);
778 goto done;
779 }
780
Florin Coras294afe22019-01-07 17:49:17 -0800781 si_bits = libc_bits = 0;
782 n_bytes = nfds / 8 + ((nfds % 8) ? 1 : 0);
Florin Coras7baeb712019-01-04 17:05:43 -0800783
Dave Wallace048b1d62018-01-03 22:24:41 -0500784 if (readfds)
Florin Coras294afe22019-01-07 17:49:17 -0800785 ldp_select_init_maps (readfds, &ldpw->rd_bitmap, &ldpw->libc_rd_bitmap,
786 &ldpw->si_rd_bitmap, nfds, minbits, n_bytes,
787 &si_bits, &libc_bits);
Dave Wallace048b1d62018-01-03 22:24:41 -0500788 if (writefds)
Florin Coras294afe22019-01-07 17:49:17 -0800789 ldp_select_init_maps (writefds, &ldpw->wr_bitmap,
790 &ldpw->libc_wr_bitmap, &ldpw->si_wr_bitmap, nfds,
791 minbits, n_bytes, &si_bits, &libc_bits);
Dave Wallace048b1d62018-01-03 22:24:41 -0500792 if (exceptfds)
Florin Coras294afe22019-01-07 17:49:17 -0800793 ldp_select_init_maps (exceptfds, &ldpw->ex_bitmap,
794 &ldpw->libc_ex_bitmap, &ldpw->si_ex_bitmap, nfds,
795 minbits, n_bytes, &si_bits, &libc_bits);
Dave Wallace048b1d62018-01-03 22:24:41 -0500796
Florin Coras294afe22019-01-07 17:49:17 -0800797 if (PREDICT_FALSE (!si_bits && !libc_bits))
Dave Wallace048b1d62018-01-03 22:24:41 -0500798 {
799 errno = EINVAL;
800 rv = -1;
801 goto done;
802 }
803
Florin Coras78b5fa62019-02-21 20:04:15 -0800804 if (!si_bits)
805 libc_tspec = timeout ? *timeout : libc_tspec;
Florin Coras294afe22019-01-07 17:49:17 -0800806
Dave Wallace048b1d62018-01-03 22:24:41 -0500807 do
808 {
Florin Coras294afe22019-01-07 17:49:17 -0800809 if (si_bits)
Dave Wallace048b1d62018-01-03 22:24:41 -0500810 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500811 if (readfds)
Florin Coras294afe22019-01-07 17:49:17 -0800812 clib_memcpy_fast (ldpw->rd_bitmap, ldpw->si_rd_bitmap,
Florin Corascbce80a2020-04-20 01:32:38 +0000813 vec_len (ldpw->si_rd_bitmap) *
Dave Barach178cf492018-11-13 16:34:13 -0500814 sizeof (clib_bitmap_t));
Dave Wallace048b1d62018-01-03 22:24:41 -0500815 if (writefds)
Florin Coras294afe22019-01-07 17:49:17 -0800816 clib_memcpy_fast (ldpw->wr_bitmap, ldpw->si_wr_bitmap,
Florin Corascbce80a2020-04-20 01:32:38 +0000817 vec_len (ldpw->si_wr_bitmap) *
Dave Barach178cf492018-11-13 16:34:13 -0500818 sizeof (clib_bitmap_t));
Dave Wallace048b1d62018-01-03 22:24:41 -0500819 if (exceptfds)
Florin Coras294afe22019-01-07 17:49:17 -0800820 clib_memcpy_fast (ldpw->ex_bitmap, ldpw->si_ex_bitmap,
Florin Corascbce80a2020-04-20 01:32:38 +0000821 vec_len (ldpw->si_ex_bitmap) *
Dave Barach178cf492018-11-13 16:34:13 -0500822 sizeof (clib_bitmap_t));
Florin Coras294afe22019-01-07 17:49:17 -0800823
Florin Coras0ef8ef22019-01-18 08:37:13 -0800824 rv = vls_select (si_bits, readfds ? ldpw->rd_bitmap : NULL,
825 writefds ? ldpw->wr_bitmap : NULL,
826 exceptfds ? ldpw->ex_bitmap : NULL, vcl_timeout);
Florin Coras294afe22019-01-07 17:49:17 -0800827 if (rv < 0)
828 {
829 errno = -rv;
830 rv = -1;
Florin Coras5e6222a2020-04-24 17:09:25 +0000831 goto done;
Florin Coras294afe22019-01-07 17:49:17 -0800832 }
833 else if (rv > 0)
834 {
835 if (ldp_select_vcl_map_to_libc (ldpw->rd_bitmap, readfds))
836 {
837 rv = -1;
838 goto done;
839 }
840
841 if (ldp_select_vcl_map_to_libc (ldpw->wr_bitmap, writefds))
842 {
843 rv = -1;
844 goto done;
845 }
846
847 if (ldp_select_vcl_map_to_libc (ldpw->ex_bitmap, exceptfds))
848 {
849 rv = -1;
850 goto done;
851 }
852 bits_set = rv;
853 }
854 }
855 if (libc_bits)
856 {
857 if (readfds)
858 clib_memcpy_fast (ldpw->rd_bitmap, ldpw->libc_rd_bitmap,
859 vec_len (ldpw->libc_rd_bitmap) *
860 sizeof (clib_bitmap_t));
861 if (writefds)
862 clib_memcpy_fast (ldpw->wr_bitmap, ldpw->libc_wr_bitmap,
863 vec_len (ldpw->libc_wr_bitmap) *
864 sizeof (clib_bitmap_t));
865 if (exceptfds)
866 clib_memcpy_fast (ldpw->ex_bitmap, ldpw->libc_ex_bitmap,
867 vec_len (ldpw->libc_ex_bitmap) *
868 sizeof (clib_bitmap_t));
869
Dave Wallace048b1d62018-01-03 22:24:41 -0500870 rv = libc_pselect (libc_bits,
Florin Coras294afe22019-01-07 17:49:17 -0800871 readfds ? (fd_set *) ldpw->rd_bitmap : NULL,
872 writefds ? (fd_set *) ldpw->wr_bitmap : NULL,
873 exceptfds ? (fd_set *) ldpw->ex_bitmap : NULL,
874 &libc_tspec, sigmask);
875 if (rv > 0)
876 {
877 ldp_select_libc_map_merge (ldpw->rd_bitmap, readfds);
878 ldp_select_libc_map_merge (ldpw->wr_bitmap, writefds);
879 ldp_select_libc_map_merge (ldpw->ex_bitmap, exceptfds);
880 bits_set += rv;
881 }
882 }
883
884 if (bits_set)
885 {
886 rv = bits_set;
887 goto done;
Dave Wallace048b1d62018-01-03 22:24:41 -0500888 }
889 }
Florin Corasdfe4cf42018-11-28 22:13:45 -0800890 while ((time_out == -1) || (clib_time_now (&ldpw->clib_time) < time_out));
Dave Wallace048b1d62018-01-03 22:24:41 -0500891 rv = 0;
892
893done:
894 /* TBD: set timeout to amount of time left */
Florin Corasdfe4cf42018-11-28 22:13:45 -0800895 clib_bitmap_zero (ldpw->rd_bitmap);
Florin Coras294afe22019-01-07 17:49:17 -0800896 clib_bitmap_zero (ldpw->si_rd_bitmap);
Florin Corasdfe4cf42018-11-28 22:13:45 -0800897 clib_bitmap_zero (ldpw->libc_rd_bitmap);
898 clib_bitmap_zero (ldpw->wr_bitmap);
Florin Coras294afe22019-01-07 17:49:17 -0800899 clib_bitmap_zero (ldpw->si_wr_bitmap);
Florin Corasdfe4cf42018-11-28 22:13:45 -0800900 clib_bitmap_zero (ldpw->libc_wr_bitmap);
901 clib_bitmap_zero (ldpw->ex_bitmap);
Florin Coras294afe22019-01-07 17:49:17 -0800902 clib_bitmap_zero (ldpw->si_ex_bitmap);
Florin Corasdfe4cf42018-11-28 22:13:45 -0800903 clib_bitmap_zero (ldpw->libc_ex_bitmap);
Dave Wallace048b1d62018-01-03 22:24:41 -0500904
Dave Wallace048b1d62018-01-03 22:24:41 -0500905 return rv;
906}
907
908int
909select (int nfds, fd_set * __restrict readfds,
910 fd_set * __restrict writefds,
911 fd_set * __restrict exceptfds, struct timeval *__restrict timeout)
912{
913 struct timespec tspec;
914
915 if (timeout)
916 {
917 tspec.tv_sec = timeout->tv_sec;
918 tspec.tv_nsec = timeout->tv_usec * 1000;
919 }
Dave Wallace2a865272018-02-07 21:00:42 -0500920 return ldp_pselect (nfds, readfds, writefds, exceptfds,
921 timeout ? &tspec : NULL, NULL);
Dave Wallace048b1d62018-01-03 22:24:41 -0500922}
923
924#ifdef __USE_XOPEN2K
925int
926pselect (int nfds, fd_set * __restrict readfds,
927 fd_set * __restrict writefds,
928 fd_set * __restrict exceptfds,
929 const struct timespec *__restrict timeout,
930 const __sigset_t * __restrict sigmask)
931{
Dave Wallace2a865272018-02-07 21:00:42 -0500932 return ldp_pselect (nfds, readfds, writefds, exceptfds, timeout, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -0500933}
934#endif
935
Yu Ping7b74b072019-05-08 00:40:24 +0800936/* If transparent TLS mode is turned on, then ldp will load key and cert.
937 */
938static int
Florin Corasa5a9efd2021-01-05 17:03:29 -0800939load_cert_key_pair (void)
Yu Ping7b74b072019-05-08 00:40:24 +0800940{
Florin Corasa5a9efd2021-01-05 17:03:29 -0800941 char *cert_str = getenv (LDP_ENV_TLS_CERT);
942 char *key_str = getenv (LDP_ENV_TLS_KEY);
943 char cert_buf[4096], key_buf[4096];
944 int cert_size, key_size;
945 vppcom_cert_key_pair_t crypto;
946 int ckp_index;
Yu Ping7b74b072019-05-08 00:40:24 +0800947 FILE *fp;
948
Florin Corasa5a9efd2021-01-05 17:03:29 -0800949 if (!cert_str || !key_str)
Yu Ping7b74b072019-05-08 00:40:24 +0800950 {
951 LDBG (0, "ERROR: failed to read LDP environment %s\n",
952 LDP_ENV_TLS_CERT);
953 return -1;
954 }
Florin Corasa5a9efd2021-01-05 17:03:29 -0800955
956 fp = fopen (cert_str, "r");
957 if (fp == NULL)
958 {
959 LDBG (0, "ERROR: failed to open cert file %s \n", cert_str);
960 return -1;
961 }
962 cert_size = fread (cert_buf, sizeof (char), sizeof (cert_buf), fp);
963 fclose (fp);
964
965 fp = fopen (key_str, "r");
966 if (fp == NULL)
967 {
968 LDBG (0, "ERROR: failed to open key file %s \n", key_str);
969 return -1;
970 }
971 key_size = fread (key_buf, sizeof (char), sizeof (key_buf), fp);
972 fclose (fp);
973
974 crypto.cert = cert_buf;
975 crypto.key = key_buf;
976 crypto.cert_len = cert_size;
977 crypto.key_len = key_size;
978 ckp_index = vppcom_add_cert_key_pair (&crypto);
979 if (ckp_index < 0)
980 {
981 LDBG (0, "ERROR: failed to add cert key pair\n");
982 return -1;
983 }
984
985 ldp->ckpair_index = ckp_index;
986
Yu Ping7b74b072019-05-08 00:40:24 +0800987 return 0;
988}
989
990static int
Florin Corasa5a9efd2021-01-05 17:03:29 -0800991assign_cert_key_pair (vls_handle_t vlsh)
Yu Ping7b74b072019-05-08 00:40:24 +0800992{
Florin Corasa5a9efd2021-01-05 17:03:29 -0800993 uint32_t ckp_len;
Yu Ping7b74b072019-05-08 00:40:24 +0800994
Florin Corasa5a9efd2021-01-05 17:03:29 -0800995 if (ldp->ckpair_index == ~0 && load_cert_key_pair () < 0)
996 return -1;
997
998 ckp_len = sizeof (ldp->ckpair_index);
liuyacan276675e2021-08-30 13:24:53 +0800999 return vls_attr (vlsh, VPPCOM_ATTR_SET_CKPAIR, &ldp->ckpair_index, &ckp_len);
Yu Ping7b74b072019-05-08 00:40:24 +08001000}
1001
Dave Wallace048b1d62018-01-03 22:24:41 -05001002int
1003socket (int domain, int type, int protocol)
1004{
Florin Coras7baeb712019-01-04 17:05:43 -08001005 int rv, sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
Dave Wallace048b1d62018-01-03 22:24:41 -05001006 u8 is_nonblocking = type & SOCK_NONBLOCK ? 1 : 0;
Florin Coras7baeb712019-01-04 17:05:43 -08001007 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001008
Florin Coras5f33d0d2021-06-02 21:22:21 -07001009 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001010
1011 if (((domain == AF_INET) || (domain == AF_INET6)) &&
1012 ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM)))
1013 {
Yu Ping7b74b072019-05-08 00:40:24 +08001014 u8 proto;
1015 if (ldp->transparent_tls)
1016 {
1017 proto = VPPCOM_PROTO_TLS;
1018 }
1019 else
1020 proto = ((sock_type == SOCK_DGRAM) ?
1021 VPPCOM_PROTO_UDP : VPPCOM_PROTO_TCP);
Dave Wallace048b1d62018-01-03 22:24:41 -05001022
Florin Coras7baeb712019-01-04 17:05:43 -08001023 LDBG (0, "calling vls_create: proto %u (%s), is_nonblocking %u",
1024 proto, vppcom_proto_str (proto), is_nonblocking);
Dave Wallace048b1d62018-01-03 22:24:41 -05001025
Florin Coras7baeb712019-01-04 17:05:43 -08001026 vlsh = vls_create (proto, is_nonblocking);
1027 if (vlsh < 0)
Dave Wallace048b1d62018-01-03 22:24:41 -05001028 {
Florin Coras7baeb712019-01-04 17:05:43 -08001029 errno = -vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001030 rv = -1;
1031 }
1032 else
1033 {
Yu Ping7b74b072019-05-08 00:40:24 +08001034 if (ldp->transparent_tls)
1035 {
Florin Corasa5a9efd2021-01-05 17:03:29 -08001036 if (assign_cert_key_pair (vlsh) < 0)
1037 return -1;
Yu Ping7b74b072019-05-08 00:40:24 +08001038 }
Florin Coras7baeb712019-01-04 17:05:43 -08001039 rv = ldp_vlsh_to_fd (vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05001040 }
1041 }
1042 else
1043 {
Florin Coras7baeb712019-01-04 17:05:43 -08001044 LDBG (0, "calling libc_socket");
Dave Wallace048b1d62018-01-03 22:24:41 -05001045 rv = libc_socket (domain, type, protocol);
1046 }
1047
Dave Wallace048b1d62018-01-03 22:24:41 -05001048 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001049}
1050
1051/*
1052 * Create two new sockets, of type TYPE in domain DOMAIN and using
1053 * protocol PROTOCOL, which are connected to each other, and put file
1054 * descriptors for them in FDS[0] and FDS[1]. If PROTOCOL is zero,
1055 * one will be chosen automatically.
1056 * Returns 0 on success, -1 for errors.
1057 * */
1058int
Dave Wallace048b1d62018-01-03 22:24:41 -05001059socketpair (int domain, int type, int protocol, int fds[2])
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001060{
Florin Coras7baeb712019-01-04 17:05:43 -08001061 int rv, sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
Dave Wallace048b1d62018-01-03 22:24:41 -05001062
Florin Coras5f33d0d2021-06-02 21:22:21 -07001063 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001064
1065 if (((domain == AF_INET) || (domain == AF_INET6)) &&
1066 ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM)))
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001067 {
Florin Coras7baeb712019-01-04 17:05:43 -08001068 LDBG (0, "LDP-TBD");
Dave Wallace048b1d62018-01-03 22:24:41 -05001069 errno = ENOSYS;
1070 rv = -1;
1071 }
1072 else
1073 {
Florin Coras7baeb712019-01-04 17:05:43 -08001074 LDBG (1, "calling libc_socketpair");
Florin Coras173bae32018-11-16 18:56:28 -08001075 rv = libc_socketpair (domain, type, protocol, fds);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001076 }
1077
Dave Wallace048b1d62018-01-03 22:24:41 -05001078 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001079}
1080
1081int
Florin Coras36847942023-02-02 12:56:16 -08001082bind (int fd, __CONST_SOCKADDR_ARG _addr, socklen_t len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001083{
Florin Coras36847942023-02-02 12:56:16 -08001084 const struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
Florin Coras7baeb712019-01-04 17:05:43 -08001085 vls_handle_t vlsh;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001086 int rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001087
Florin Coras5f33d0d2021-06-02 21:22:21 -07001088 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001089
Florin Coras7baeb712019-01-04 17:05:43 -08001090 vlsh = ldp_fd_to_vlsh (fd);
1091 if (vlsh != VLS_INVALID_HANDLE)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001092 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001093 vppcom_endpt_t ep;
1094
Dave Wallace048b1d62018-01-03 22:24:41 -05001095 switch (addr->sa_family)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001096 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001097 case AF_INET:
1098 if (len != sizeof (struct sockaddr_in))
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001099 {
Florin Coras7baeb712019-01-04 17:05:43 -08001100 LDBG (0, "ERROR: fd %d: vlsh %u: Invalid AF_INET addr len %u!",
1101 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001102 errno = EINVAL;
1103 rv = -1;
1104 goto done;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001105 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001106 ep.is_ip4 = VPPCOM_IS_IP4;
1107 ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr;
1108 ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port;
1109 break;
1110
1111 case AF_INET6:
1112 if (len != sizeof (struct sockaddr_in6))
1113 {
Florin Coras7baeb712019-01-04 17:05:43 -08001114 LDBG (0, "ERROR: fd %d: vlsh %u: Invalid AF_INET6 addr len %u!",
1115 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001116 errno = EINVAL;
1117 rv = -1;
1118 goto done;
1119 }
1120 ep.is_ip4 = VPPCOM_IS_IP6;
1121 ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
1122 ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001123 break;
1124
1125 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001126 LDBG (0, "ERROR: fd %d: vlsh %u: Unsupported address family %u!",
1127 fd, vlsh, addr->sa_family);
Dave Wallace048b1d62018-01-03 22:24:41 -05001128 errno = EAFNOSUPPORT;
1129 rv = -1;
1130 goto done;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001131 }
Florin Coras7baeb712019-01-04 17:05:43 -08001132 LDBG (0, "fd %d: calling vls_bind: vlsh %u, addr %p, len %u", fd, vlsh,
1133 addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001134
Florin Coras7baeb712019-01-04 17:05:43 -08001135 rv = vls_bind (vlsh, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001136 if (rv != VPPCOM_OK)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001137 {
1138 errno = -rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001139 rv = -1;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001140 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001141 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001142 else
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001143 {
Florin Coras7baeb712019-01-04 17:05:43 -08001144 LDBG (0, "fd %d: calling libc_bind: addr %p, len %u", fd, addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001145 rv = libc_bind (fd, addr, len);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001146 }
1147
Dave Wallace048b1d62018-01-03 22:24:41 -05001148done:
Florin Coras7baeb712019-01-04 17:05:43 -08001149 LDBG (1, "fd %d: returning %d", fd, rv);
Florin Coras05ecfcc2018-12-12 18:19:39 -08001150
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001151 return rv;
1152}
1153
1154static inline int
Florin Coras36847942023-02-02 12:56:16 -08001155ldp_copy_ep_to_sockaddr (struct sockaddr *addr, socklen_t *__restrict len,
1156 vppcom_endpt_t *ep)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001157{
Florin Coras36847942023-02-02 12:56:16 -08001158 int rv = 0, sa_len, copy_len;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001159
Florin Coras5f33d0d2021-06-02 21:22:21 -07001160 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001161
1162 if (addr && len && ep)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001163 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001164 addr->sa_family = (ep->is_ip4 == VPPCOM_IS_IP4) ? AF_INET : AF_INET6;
1165 switch (addr->sa_family)
1166 {
1167 case AF_INET:
1168 ((struct sockaddr_in *) addr)->sin_port = ep->port;
1169 if (*len > sizeof (struct sockaddr_in))
1170 *len = sizeof (struct sockaddr_in);
1171 sa_len = sizeof (struct sockaddr_in) - sizeof (struct in_addr);
1172 copy_len = *len - sa_len;
1173 if (copy_len > 0)
1174 memcpy (&((struct sockaddr_in *) addr)->sin_addr, ep->ip,
1175 copy_len);
1176 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001177
Dave Wallace048b1d62018-01-03 22:24:41 -05001178 case AF_INET6:
1179 ((struct sockaddr_in6 *) addr)->sin6_port = ep->port;
1180 if (*len > sizeof (struct sockaddr_in6))
1181 *len = sizeof (struct sockaddr_in6);
1182 sa_len = sizeof (struct sockaddr_in6) - sizeof (struct in6_addr);
1183 copy_len = *len - sa_len;
1184 if (copy_len > 0)
1185 memcpy (((struct sockaddr_in6 *) addr)->sin6_addr.
1186 __in6_u.__u6_addr8, ep->ip, copy_len);
1187 break;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001188
Dave Wallace048b1d62018-01-03 22:24:41 -05001189 default:
1190 /* Not possible */
1191 rv = -EAFNOSUPPORT;
1192 break;
1193 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001194 }
Dave Wallacee695cb42017-11-02 22:04:42 -04001195 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001196}
1197
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001198int
Florin Coras36847942023-02-02 12:56:16 -08001199getsockname (int fd, __SOCKADDR_ARG _addr, socklen_t *__restrict len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001200{
Florin Coras36847942023-02-02 12:56:16 -08001201 struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
Florin Coras7baeb712019-01-04 17:05:43 -08001202 vls_handle_t vlsh;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001203 int rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001204
Florin Coras5f33d0d2021-06-02 21:22:21 -07001205 ldp_init_check ();
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001206
Florin Coras7baeb712019-01-04 17:05:43 -08001207 vlsh = ldp_fd_to_vlsh (fd);
1208 if (vlsh != VLS_INVALID_HANDLE)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001209 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001210 vppcom_endpt_t ep;
1211 u8 addr_buf[sizeof (struct in6_addr)];
1212 u32 size = sizeof (ep);
1213
1214 ep.ip = addr_buf;
Dave Wallace048b1d62018-01-03 22:24:41 -05001215
Florin Coras7baeb712019-01-04 17:05:43 -08001216 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_LCL_ADDR, &ep, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -05001217 if (rv != VPPCOM_OK)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001218 {
1219 errno = -rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001220 rv = -1;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001221 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001222 else
1223 {
Dave Wallace2a865272018-02-07 21:00:42 -05001224 rv = ldp_copy_ep_to_sockaddr (addr, len, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001225 if (rv != VPPCOM_OK)
1226 {
1227 errno = -rv;
1228 rv = -1;
1229 }
1230 }
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001231 }
1232 else
1233 {
Florin Coras36847942023-02-02 12:56:16 -08001234 rv = libc_getsockname (fd, _addr, len);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001235 }
1236
Dave Wallace048b1d62018-01-03 22:24:41 -05001237 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001238}
1239
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001240int
Florin Coras36847942023-02-02 12:56:16 -08001241connect (int fd, __CONST_SOCKADDR_ARG _addr, socklen_t len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001242{
Florin Coras36847942023-02-02 12:56:16 -08001243 const struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
Florin Coras7baeb712019-01-04 17:05:43 -08001244 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001245 int rv;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001246
Florin Coras5f33d0d2021-06-02 21:22:21 -07001247 ldp_init_check ();
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001248
Dave Wallace048b1d62018-01-03 22:24:41 -05001249 if (!addr)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001250 {
Florin Coras7baeb712019-01-04 17:05:43 -08001251 LDBG (0, "ERROR: fd %d: NULL addr, len %u", fd, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001252 errno = EINVAL;
1253 rv = -1;
1254 goto done;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07001255 }
1256
Florin Coras7baeb712019-01-04 17:05:43 -08001257 vlsh = ldp_fd_to_vlsh (fd);
1258 if (vlsh != VLS_INVALID_HANDLE)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001259 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001260 vppcom_endpt_t ep;
1261
Dave Wallace048b1d62018-01-03 22:24:41 -05001262 switch (addr->sa_family)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001263 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001264 case AF_INET:
1265 if (len != sizeof (struct sockaddr_in))
1266 {
Florin Coras7baeb712019-01-04 17:05:43 -08001267 LDBG (0, "fd %d: ERROR vlsh %u: Invalid AF_INET addr len %u!",
1268 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001269 errno = EINVAL;
1270 rv = -1;
1271 goto done;
1272 }
1273 ep.is_ip4 = VPPCOM_IS_IP4;
1274 ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr;
1275 ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port;
1276 break;
1277
1278 case AF_INET6:
1279 if (len != sizeof (struct sockaddr_in6))
1280 {
Florin Coras7baeb712019-01-04 17:05:43 -08001281 LDBG (0, "fd %d: ERROR vlsh %u: Invalid AF_INET6 addr len %u!",
1282 fd, vlsh, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001283 errno = EINVAL;
1284 rv = -1;
1285 goto done;
1286 }
1287 ep.is_ip4 = VPPCOM_IS_IP6;
1288 ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
1289 ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port;
1290 break;
1291
1292 default:
Florin Coras7baeb712019-01-04 17:05:43 -08001293 LDBG (0, "fd %d: ERROR vlsh %u: Unsupported address family %u!",
1294 fd, vlsh, addr->sa_family);
Dave Wallace048b1d62018-01-03 22:24:41 -05001295 errno = EAFNOSUPPORT;
1296 rv = -1;
1297 goto done;
1298 }
Florin Coras7baeb712019-01-04 17:05:43 -08001299 LDBG (0, "fd %d: calling vls_connect(): vlsh %u addr %p len %u", fd,
1300 vlsh, addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001301
Florin Coras7baeb712019-01-04 17:05:43 -08001302 rv = vls_connect (vlsh, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001303 if (rv != VPPCOM_OK)
1304 {
1305 errno = -rv;
1306 rv = -1;
1307 }
1308 }
1309 else
1310 {
Florin Coras7baeb712019-01-04 17:05:43 -08001311 LDBG (0, "fd %d: calling libc_connect(): addr %p, len %u",
1312 fd, addr, len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001313
1314 rv = libc_connect (fd, addr, len);
1315 }
1316
1317done:
Florin Coras7baeb712019-01-04 17:05:43 -08001318 LDBG (1, "fd %d: returning %d (0x%x)", fd, rv, rv);
Dave Wallace048b1d62018-01-03 22:24:41 -05001319 return rv;
1320}
1321
1322int
Florin Coras36847942023-02-02 12:56:16 -08001323getpeername (int fd, __SOCKADDR_ARG _addr, socklen_t *__restrict len)
Dave Wallace048b1d62018-01-03 22:24:41 -05001324{
Florin Coras36847942023-02-02 12:56:16 -08001325 struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
Florin Coras7baeb712019-01-04 17:05:43 -08001326 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001327 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001328
Florin Coras5f33d0d2021-06-02 21:22:21 -07001329 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001330
Florin Coras7baeb712019-01-04 17:05:43 -08001331 vlsh = ldp_fd_to_vlsh (fd);
1332 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001333 {
1334 vppcom_endpt_t ep;
1335 u8 addr_buf[sizeof (struct in6_addr)];
1336 u32 size = sizeof (ep);
1337
1338 ep.ip = addr_buf;
Florin Coras7baeb712019-01-04 17:05:43 -08001339 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_PEER_ADDR, &ep, &size);
Dave Wallace048b1d62018-01-03 22:24:41 -05001340 if (rv != VPPCOM_OK)
1341 {
1342 errno = -rv;
1343 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001344 }
1345 else
1346 {
Dave Wallace2a865272018-02-07 21:00:42 -05001347 rv = ldp_copy_ep_to_sockaddr (addr, len, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05001348 if (rv != VPPCOM_OK)
1349 {
1350 errno = -rv;
1351 rv = -1;
1352 }
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001353 }
1354 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001355 else
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001356 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001357 rv = libc_getpeername (fd, addr, len);
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001358 }
1359
Dave Wallace048b1d62018-01-03 22:24:41 -05001360 return rv;
1361}
1362
1363ssize_t
1364send (int fd, const void *buf, size_t n, int flags)
1365{
Florin Coras7baeb712019-01-04 17:05:43 -08001366 vls_handle_t vlsh = ldp_fd_to_vlsh (fd);
Dave Wallace048b1d62018-01-03 22:24:41 -05001367 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001368
Florin Coras5f33d0d2021-06-02 21:22:21 -07001369 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001370
Florin Coras7baeb712019-01-04 17:05:43 -08001371 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001372 {
Florin Coras7baeb712019-01-04 17:05:43 -08001373 size = vls_sendto (vlsh, (void *) buf, n, flags, NULL);
qchangaa8f63c2018-05-30 11:44:18 -07001374 if (size < VPPCOM_OK)
Dave Wallace048b1d62018-01-03 22:24:41 -05001375 {
1376 errno = -size;
1377 size = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001378 }
1379 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001380 else
1381 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001382 size = libc_send (fd, buf, n, flags);
1383 }
1384
Dave Wallace048b1d62018-01-03 22:24:41 -05001385 return size;
1386}
1387
1388ssize_t
1389sendfile (int out_fd, int in_fd, off_t * offset, size_t len)
1390{
Florin Corasdfe4cf42018-11-28 22:13:45 -08001391 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras7baeb712019-01-04 17:05:43 -08001392 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001393 ssize_t size = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -05001394
Florin Coras5f33d0d2021-06-02 21:22:21 -07001395 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001396
Florin Coras7baeb712019-01-04 17:05:43 -08001397 vlsh = ldp_fd_to_vlsh (out_fd);
1398 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001399 {
1400 int rv;
1401 ssize_t results = 0;
1402 size_t n_bytes_left = len;
1403 size_t bytes_to_read;
1404 int nbytes;
Dave Wallace048b1d62018-01-03 22:24:41 -05001405 u8 eagain = 0;
1406 u32 flags, flags_len = sizeof (flags);
1407
Florin Coras7baeb712019-01-04 17:05:43 -08001408 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_FLAGS, &flags, &flags_len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001409 if (PREDICT_FALSE (rv != VPPCOM_OK))
1410 {
Florin Coras7baeb712019-01-04 17:05:43 -08001411 LDBG (0, "ERROR: out fd %d: vls_attr: vlsh %u, returned %d (%s)!",
1412 out_fd, vlsh, rv, vppcom_retval_str (rv));
Dave Wallace048b1d62018-01-03 22:24:41 -05001413
Florin Corasdfe4cf42018-11-28 22:13:45 -08001414 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001415 errno = -rv;
1416 size = -1;
1417 goto done;
1418 }
1419
1420 if (offset)
1421 {
1422 off_t off = lseek (in_fd, *offset, SEEK_SET);
1423 if (PREDICT_FALSE (off == -1))
1424 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001425 size = -1;
1426 goto done;
1427 }
1428
1429 ASSERT (off == *offset);
1430 }
1431
1432 do
1433 {
Florin Coras7baeb712019-01-04 17:05:43 -08001434 size = vls_attr (vlsh, VPPCOM_ATTR_GET_NWRITE, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05001435 if (size < 0)
1436 {
Florin Coraseb801d02020-09-16 17:44:58 -07001437 LDBG (0, "ERROR: fd %d: vls_attr: vlsh %u returned %ld (%s)!",
Florin Coras7baeb712019-01-04 17:05:43 -08001438 out_fd, vlsh, size, vppcom_retval_str (size));
Florin Corasdfe4cf42018-11-28 22:13:45 -08001439 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001440 errno = -size;
1441 size = -1;
1442 goto done;
1443 }
1444
1445 bytes_to_read = size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001446 if (bytes_to_read == 0)
1447 {
1448 if (flags & O_NONBLOCK)
1449 {
1450 if (!results)
Florin Coras7baeb712019-01-04 17:05:43 -08001451 eagain = 1;
Dave Wallace048b1d62018-01-03 22:24:41 -05001452 goto update_offset;
1453 }
1454 else
1455 continue;
1456 }
1457 bytes_to_read = clib_min (n_bytes_left, bytes_to_read);
Florin Corasdfe4cf42018-11-28 22:13:45 -08001458 vec_validate (ldpw->io_buffer, bytes_to_read);
1459 nbytes = libc_read (in_fd, ldpw->io_buffer, bytes_to_read);
Dave Wallace048b1d62018-01-03 22:24:41 -05001460 if (nbytes < 0)
1461 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001462 if (results == 0)
1463 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08001464 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001465 size = -1;
1466 goto done;
1467 }
1468 goto update_offset;
1469 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001470
Florin Coras7baeb712019-01-04 17:05:43 -08001471 size = vls_write (vlsh, ldpw->io_buffer, nbytes);
Dave Wallace048b1d62018-01-03 22:24:41 -05001472 if (size < 0)
1473 {
1474 if (size == VPPCOM_EAGAIN)
1475 {
1476 if (flags & O_NONBLOCK)
1477 {
1478 if (!results)
Florin Coras7baeb712019-01-04 17:05:43 -08001479 eagain = 1;
Dave Wallace048b1d62018-01-03 22:24:41 -05001480 goto update_offset;
1481 }
1482 else
1483 continue;
1484 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001485 if (results == 0)
1486 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08001487 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001488 errno = -size;
1489 size = -1;
1490 goto done;
1491 }
1492 goto update_offset;
1493 }
1494
1495 results += nbytes;
1496 ASSERT (n_bytes_left >= nbytes);
1497 n_bytes_left = n_bytes_left - nbytes;
1498 }
1499 while (n_bytes_left > 0);
1500
1501 update_offset:
Florin Corasdfe4cf42018-11-28 22:13:45 -08001502 vec_reset_length (ldpw->io_buffer);
Dave Wallace048b1d62018-01-03 22:24:41 -05001503 if (offset)
1504 {
1505 off_t off = lseek (in_fd, *offset, SEEK_SET);
1506 if (PREDICT_FALSE (off == -1))
1507 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001508 size = -1;
1509 goto done;
1510 }
1511
1512 ASSERT (off == *offset);
1513 *offset += results + 1;
1514 }
1515 if (eagain)
1516 {
1517 errno = EAGAIN;
1518 size = -1;
1519 }
1520 else
1521 size = results;
1522 }
1523 else
1524 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001525 size = libc_sendfile (out_fd, in_fd, offset, len);
1526 }
1527
1528done:
Dave Wallace048b1d62018-01-03 22:24:41 -05001529 return size;
1530}
1531
1532ssize_t
1533sendfile64 (int out_fd, int in_fd, off_t * offset, size_t len)
1534{
1535 return sendfile (out_fd, in_fd, offset, len);
1536}
1537
1538ssize_t
1539recv (int fd, void *buf, size_t n, int flags)
1540{
Florin Coras7baeb712019-01-04 17:05:43 -08001541 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001542 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001543
Florin Coras5f33d0d2021-06-02 21:22:21 -07001544 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001545
Florin Coras7baeb712019-01-04 17:05:43 -08001546 vlsh = ldp_fd_to_vlsh (fd);
1547 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001548 {
Florin Coras7baeb712019-01-04 17:05:43 -08001549 size = vls_recvfrom (vlsh, buf, n, flags, NULL);
Dave Wallace048b1d62018-01-03 22:24:41 -05001550 if (size < 0)
Florin Coras2a6642e2020-03-24 15:24:29 +00001551 {
1552 errno = -size;
1553 size = -1;
1554 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001555 }
1556 else
1557 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001558 size = libc_recv (fd, buf, n, flags);
1559 }
1560
Dave Wallace048b1d62018-01-03 22:24:41 -05001561 return size;
1562}
1563
Sivaprasad Tummalafdcbd382021-07-31 21:38:19 +05301564ssize_t
1565__recv_chk (int fd, void *buf, size_t n, size_t buflen, int flags)
1566{
1567 if (n > buflen)
1568 return -1;
1569
1570 return recv (fd, buf, n, flags);
1571}
1572
Dou Chao243a0432022-11-29 19:41:34 +08001573static inline int
1574ldp_vls_sendo (vls_handle_t vlsh, const void *buf, size_t n,
Florin Coraseff5f7a2023-02-07 17:36:17 -08001575 vppcom_endpt_tlv_t *app_tlvs, int flags,
Florin Coras36847942023-02-02 12:56:16 -08001576 __CONST_SOCKADDR_ARG _addr, socklen_t addr_len)
Florin Corasce17f462020-05-22 20:36:29 +00001577{
Florin Coras36847942023-02-02 12:56:16 -08001578 const struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
Florin Corasce17f462020-05-22 20:36:29 +00001579 vppcom_endpt_t *ep = 0;
1580 vppcom_endpt_t _ep;
1581
Florin Coraseff5f7a2023-02-07 17:36:17 -08001582 _ep.app_tlvs = app_tlvs;
Dou Chao243a0432022-11-29 19:41:34 +08001583
Florin Corasce17f462020-05-22 20:36:29 +00001584 if (addr)
1585 {
1586 ep = &_ep;
1587 switch (addr->sa_family)
1588 {
1589 case AF_INET:
1590 ep->is_ip4 = VPPCOM_IS_IP4;
1591 ep->ip =
1592 (uint8_t *) & ((const struct sockaddr_in *) addr)->sin_addr;
1593 ep->port = (uint16_t) ((const struct sockaddr_in *) addr)->sin_port;
1594 break;
1595
1596 case AF_INET6:
1597 ep->is_ip4 = VPPCOM_IS_IP6;
1598 ep->ip =
1599 (uint8_t *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
1600 ep->port =
1601 (uint16_t) ((const struct sockaddr_in6 *) addr)->sin6_port;
1602 break;
1603
1604 default:
1605 return EAFNOSUPPORT;
1606 }
1607 }
1608
1609 return vls_sendto (vlsh, (void *) buf, n, flags, ep);
1610}
1611
1612static int
Florin Coras36847942023-02-02 12:56:16 -08001613ldp_vls_recvfrom (vls_handle_t vlsh, void *__restrict buf, size_t n, int flags,
1614 __SOCKADDR_ARG _addr, socklen_t *__restrict addr_len)
Florin Corasce17f462020-05-22 20:36:29 +00001615{
1616 u8 src_addr[sizeof (struct sockaddr_in6)];
Florin Coras36847942023-02-02 12:56:16 -08001617 struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
Florin Corasce17f462020-05-22 20:36:29 +00001618 vppcom_endpt_t ep;
1619 ssize_t size;
1620 int rv;
1621
1622 if (addr)
1623 {
1624 ep.ip = src_addr;
1625 size = vls_recvfrom (vlsh, buf, n, flags, &ep);
1626
1627 if (size > 0)
1628 {
1629 rv = ldp_copy_ep_to_sockaddr (addr, addr_len, &ep);
1630 if (rv < 0)
1631 size = rv;
1632 }
1633 }
1634 else
1635 size = vls_recvfrom (vlsh, buf, n, flags, NULL);
1636
1637 return size;
1638}
1639
Dave Wallace048b1d62018-01-03 22:24:41 -05001640ssize_t
1641sendto (int fd, const void *buf, size_t n, int flags,
Florin Coras36847942023-02-02 12:56:16 -08001642 __CONST_SOCKADDR_ARG _addr, socklen_t addr_len)
Dave Wallace048b1d62018-01-03 22:24:41 -05001643{
Florin Coras36847942023-02-02 12:56:16 -08001644 const struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
Florin Coras7baeb712019-01-04 17:05:43 -08001645 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001646 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001647
Florin Coras5f33d0d2021-06-02 21:22:21 -07001648 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001649
Florin Coras7baeb712019-01-04 17:05:43 -08001650 vlsh = ldp_fd_to_vlsh (fd);
wanghanlin97c6e0d2021-07-06 15:01:48 +08001651 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001652 {
Dou Chao243a0432022-11-29 19:41:34 +08001653 size = ldp_vls_sendo (vlsh, buf, n, NULL, flags, addr, addr_len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001654 if (size < 0)
1655 {
1656 errno = -size;
1657 size = -1;
1658 }
1659 }
1660 else
1661 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001662 size = libc_sendto (fd, buf, n, flags, addr, addr_len);
1663 }
1664
Dave Wallace048b1d62018-01-03 22:24:41 -05001665 return size;
1666}
1667
1668ssize_t
1669recvfrom (int fd, void *__restrict buf, size_t n, int flags,
1670 __SOCKADDR_ARG addr, socklen_t * __restrict addr_len)
1671{
Florin Corasce17f462020-05-22 20:36:29 +00001672 vls_handle_t vlsh;
1673 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001674
Florin Coras5f33d0d2021-06-02 21:22:21 -07001675 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001676
Florin Corasce17f462020-05-22 20:36:29 +00001677 vlsh = ldp_fd_to_vlsh (fd);
1678 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001679 {
Florin Corasce17f462020-05-22 20:36:29 +00001680 size = ldp_vls_recvfrom (vlsh, buf, n, flags, addr, addr_len);
Dave Wallace048b1d62018-01-03 22:24:41 -05001681 if (size < 0)
1682 {
1683 errno = -size;
1684 size = -1;
1685 }
1686 }
1687 else
1688 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001689 size = libc_recvfrom (fd, buf, n, flags, addr, addr_len);
1690 }
1691
Dave Wallace048b1d62018-01-03 22:24:41 -05001692 return size;
1693}
1694
Florin Coraseff5f7a2023-02-07 17:36:17 -08001695static int
1696ldp_parse_cmsg (vls_handle_t vlsh, const struct msghdr *msg,
1697 vppcom_endpt_tlv_t **app_tlvs)
1698{
1699 uint8_t *ad, *at = (uint8_t *) *app_tlvs;
1700 vppcom_endpt_tlv_t *adh;
1701 struct in_pktinfo *pi;
1702 struct cmsghdr *cmsg;
1703
1704 cmsg = CMSG_FIRSTHDR (msg);
1705
1706 while (cmsg != NULL)
1707 {
1708 switch (cmsg->cmsg_level)
1709 {
1710 case SOL_UDP:
1711 switch (cmsg->cmsg_type)
1712 {
1713 case UDP_SEGMENT:
1714 vec_add2 (at, adh, sizeof (*adh));
1715 adh->data_type = VCL_UDP_SEGMENT;
1716 adh->data_len = sizeof (uint16_t);
1717 vec_add2 (at, ad, sizeof (uint16_t));
1718 *(uint16_t *) ad = *(uint16_t *) CMSG_DATA (cmsg);
1719 break;
1720 default:
1721 LDBG (1, "SOL_UDP cmsg_type %u not supported", cmsg->cmsg_type);
1722 break;
1723 }
1724 break;
1725 case SOL_IP:
1726 switch (cmsg->cmsg_type)
1727 {
1728 case IP_PKTINFO:
1729 vec_add2 (at, adh, sizeof (*adh));
1730 adh->data_type = VCL_IP_PKTINFO;
1731 adh->data_len = sizeof (struct in_addr);
1732 vec_add2 (at, ad, sizeof (struct in_addr));
1733 pi = (void *) CMSG_DATA (cmsg);
1734 clib_memcpy_fast (ad, &pi->ipi_spec_dst,
1735 sizeof (struct in_addr));
1736 break;
1737 default:
1738 LDBG (1, "SOL_IP cmsg_type %u not supported", cmsg->cmsg_type);
1739 break;
1740 }
1741 break;
1742 default:
1743 LDBG (1, "cmsg_level %u not supported", cmsg->cmsg_level);
1744 break;
1745 }
1746 cmsg = CMSG_NXTHDR ((struct msghdr *) msg, cmsg);
1747 }
1748 *app_tlvs = (vppcom_endpt_tlv_t *) at;
1749 return 0;
1750}
1751
1752static int
1753ldp_make_cmsg (vls_handle_t vlsh, struct msghdr *msg)
1754{
1755 u32 optval, optlen = sizeof (optval);
1756 struct cmsghdr *cmsg;
1757
1758 cmsg = CMSG_FIRSTHDR (msg);
Steven Luong2da272e2023-07-18 23:25:15 -07001759 memset (cmsg, 0, sizeof (*cmsg));
Florin Coraseff5f7a2023-02-07 17:36:17 -08001760
1761 if (!vls_attr (vlsh, VPPCOM_ATTR_GET_IP_PKTINFO, (void *) &optval, &optlen))
1762 return 0;
1763
1764 if (optval)
1765 {
1766 vppcom_endpt_t ep;
1767 u8 addr_buf[sizeof (struct in_addr)];
1768 u32 size = sizeof (ep);
1769
1770 ep.ip = addr_buf;
1771
1772 if (!vls_attr (vlsh, VPPCOM_ATTR_GET_LCL_ADDR, &ep, &size))
1773 {
1774 struct in_pktinfo pi = {};
1775
1776 clib_memcpy (&pi.ipi_addr, ep.ip, sizeof (struct in_addr));
1777 cmsg->cmsg_level = SOL_IP;
1778 cmsg->cmsg_type = IP_PKTINFO;
1779 cmsg->cmsg_len = CMSG_LEN (sizeof (pi));
1780 clib_memcpy (CMSG_DATA (cmsg), &pi, sizeof (pi));
1781 }
1782 }
1783
1784 return 0;
1785}
1786
Dave Wallace048b1d62018-01-03 22:24:41 -05001787ssize_t
Florin Corasce17f462020-05-22 20:36:29 +00001788sendmsg (int fd, const struct msghdr * msg, int flags)
Dave Wallace048b1d62018-01-03 22:24:41 -05001789{
Florin Coras7baeb712019-01-04 17:05:43 -08001790 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001791 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001792
Florin Coras5f33d0d2021-06-02 21:22:21 -07001793 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001794
Florin Coras7baeb712019-01-04 17:05:43 -08001795 vlsh = ldp_fd_to_vlsh (fd);
1796 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001797 {
Florin Coraseff5f7a2023-02-07 17:36:17 -08001798 vppcom_endpt_tlv_t *app_tlvs = 0;
Florin Corasce17f462020-05-22 20:36:29 +00001799 struct iovec *iov = msg->msg_iov;
1800 ssize_t total = 0;
Florin Corascba1c222021-11-29 08:12:27 -08001801 int i, rv = 0;
Dou Chao243a0432022-11-29 19:41:34 +08001802
Florin Coraseff5f7a2023-02-07 17:36:17 -08001803 ldp_parse_cmsg (vlsh, msg, &app_tlvs);
Florin Corasce17f462020-05-22 20:36:29 +00001804
1805 for (i = 0; i < msg->msg_iovlen; ++i)
1806 {
Florin Coraseff5f7a2023-02-07 17:36:17 -08001807 rv = ldp_vls_sendo (vlsh, iov[i].iov_base, iov[i].iov_len, app_tlvs,
1808 flags, msg->msg_name, msg->msg_namelen);
Florin Corasce17f462020-05-22 20:36:29 +00001809 if (rv < 0)
1810 break;
1811 else
1812 {
1813 total += rv;
1814 if (rv < iov[i].iov_len)
1815 break;
1816 }
1817 }
1818
Florin Coraseff5f7a2023-02-07 17:36:17 -08001819 vec_free (app_tlvs);
1820
Florin Corasce17f462020-05-22 20:36:29 +00001821 if (rv < 0 && total == 0)
1822 {
1823 errno = -rv;
1824 size = -1;
1825 }
1826 else
1827 size = total;
Dave Wallace048b1d62018-01-03 22:24:41 -05001828 }
1829 else
1830 {
Florin Corasce17f462020-05-22 20:36:29 +00001831 size = libc_sendmsg (fd, msg, flags);
Dave Wallace048b1d62018-01-03 22:24:41 -05001832 }
1833
Dave Wallace048b1d62018-01-03 22:24:41 -05001834 return size;
1835}
1836
Florin Coras36847942023-02-02 12:56:16 -08001837#ifdef _GNU_SOURCE
Dave Wallace048b1d62018-01-03 22:24:41 -05001838int
1839sendmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags)
1840{
1841 ssize_t size;
1842 const char *func_str;
Florin Coras7baeb712019-01-04 17:05:43 -08001843 u32 sh = ldp_fd_to_vlsh (fd);
Dave Wallace048b1d62018-01-03 22:24:41 -05001844
Florin Coras5f33d0d2021-06-02 21:22:21 -07001845 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001846
wanghanlin97c6e0d2021-07-06 15:01:48 +08001847 if (sh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001848 {
1849 clib_warning ("LDP<%d>: LDP-TBD", getpid ());
1850 errno = ENOSYS;
1851 size = -1;
1852 }
1853 else
1854 {
1855 func_str = "libc_sendmmsg";
1856
Dave Wallace2a865272018-02-07 21:00:42 -05001857 if (LDP_DEBUG > 2)
Dave Wallace048b1d62018-01-03 22:24:41 -05001858 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1859 "vmessages %p, vlen %u, flags 0x%x",
1860 getpid (), fd, fd, func_str, vmessages, vlen, flags);
1861
1862 size = libc_sendmmsg (fd, vmessages, vlen, flags);
1863 }
1864
Dave Wallace2a865272018-02-07 21:00:42 -05001865 if (LDP_DEBUG > 2)
Dave Wallace048b1d62018-01-03 22:24:41 -05001866 {
1867 if (size < 0)
1868 {
1869 int errno_val = errno;
1870 perror (func_str);
1871 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1872 "rv %d, errno = %d", getpid (), fd, fd,
1873 func_str, size, errno_val);
1874 errno = errno_val;
1875 }
1876 else
1877 clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1878 getpid (), fd, fd, size, size);
1879 }
1880 return size;
1881}
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001882#endif
1883
Dave Wallace048b1d62018-01-03 22:24:41 -05001884ssize_t
Florin Corasce17f462020-05-22 20:36:29 +00001885recvmsg (int fd, struct msghdr * msg, int flags)
Dave Wallace048b1d62018-01-03 22:24:41 -05001886{
Florin Coras7baeb712019-01-04 17:05:43 -08001887 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001888 ssize_t size;
Dave Wallace048b1d62018-01-03 22:24:41 -05001889
Florin Coras5f33d0d2021-06-02 21:22:21 -07001890 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001891
Florin Coras7baeb712019-01-04 17:05:43 -08001892 vlsh = ldp_fd_to_vlsh (fd);
1893 if (vlsh != VLS_INVALID_HANDLE)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07001894 {
Florin Corasce17f462020-05-22 20:36:29 +00001895 struct iovec *iov = msg->msg_iov;
1896 ssize_t max_deq, total = 0;
1897 int i, rv;
1898
1899 max_deq = vls_attr (vlsh, VPPCOM_ATTR_GET_NREAD, 0, 0);
1900 if (!max_deq)
1901 return 0;
1902
1903 for (i = 0; i < msg->msg_iovlen; i++)
1904 {
1905 rv = ldp_vls_recvfrom (vlsh, iov[i].iov_base, iov[i].iov_len, flags,
1906 (i == 0 ? msg->msg_name : NULL),
1907 (i == 0 ? &msg->msg_namelen : NULL));
1908 if (rv <= 0)
1909 break;
1910 else
1911 {
1912 total += rv;
1913 if (rv < iov[i].iov_len)
1914 break;
1915 }
1916 if (total >= max_deq)
1917 break;
1918 }
1919
1920 if (rv < 0 && total == 0)
1921 {
1922 errno = -rv;
1923 size = -1;
1924 }
1925 else
Florin Coraseff5f7a2023-02-07 17:36:17 -08001926 {
1927 if (msg->msg_controllen)
1928 ldp_make_cmsg (vlsh, msg);
1929 size = total;
1930 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001931 }
1932 else
1933 {
Florin Corasce17f462020-05-22 20:36:29 +00001934 size = libc_recvmsg (fd, msg, flags);
Dave Wallace048b1d62018-01-03 22:24:41 -05001935 }
1936
Dave Wallace048b1d62018-01-03 22:24:41 -05001937 return size;
1938}
1939
Florin Coras36847942023-02-02 12:56:16 -08001940#ifdef _GNU_SOURCE
Dave Wallace048b1d62018-01-03 22:24:41 -05001941int
1942recvmmsg (int fd, struct mmsghdr *vmessages,
1943 unsigned int vlen, int flags, struct timespec *tmo)
1944{
Florin Corasf1a232f2023-02-02 22:56:03 -08001945 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
1946 u32 sh;
Dave Wallace048b1d62018-01-03 22:24:41 -05001947
Florin Coras5f33d0d2021-06-02 21:22:21 -07001948 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05001949
Florin Corasf1a232f2023-02-02 22:56:03 -08001950 sh = ldp_fd_to_vlsh (fd);
1951
wanghanlin97c6e0d2021-07-06 15:01:48 +08001952 if (sh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05001953 {
Florin Corasf1a232f2023-02-02 22:56:03 -08001954 struct mmsghdr *mh;
1955 ssize_t rv = 0;
1956 u32 nvecs = 0;
1957 f64 time_out;
1958
1959 if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
1960 clib_time_init (&ldpw->clib_time);
1961 if (tmo)
1962 {
1963 time_out = (f64) tmo->tv_sec + (f64) tmo->tv_nsec / (f64) 1e9;
1964 time_out += clib_time_now (&ldpw->clib_time);
1965 }
1966 else
1967 {
1968 time_out = (f64) ~0;
1969 }
1970
1971 while (nvecs < vlen)
1972 {
1973 mh = &vmessages[nvecs];
1974 rv = recvmsg (fd, &mh->msg_hdr, flags);
1975 if (rv > 0)
1976 {
1977 mh->msg_len = rv;
1978 nvecs += 1;
1979 continue;
1980 }
1981
1982 if (!time_out || clib_time_now (&ldpw->clib_time) >= time_out)
1983 break;
1984
1985 usleep (1);
1986 }
1987
1988 return nvecs > 0 ? nvecs : rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05001989 }
1990 else
1991 {
Florin Corasf1a232f2023-02-02 22:56:03 -08001992 return libc_recvmmsg (fd, vmessages, vlen, flags, tmo);
Dave Wallace048b1d62018-01-03 22:24:41 -05001993 }
Dave Wallace048b1d62018-01-03 22:24:41 -05001994}
1995#endif
1996
1997int
1998getsockopt (int fd, int level, int optname,
1999 void *__restrict optval, socklen_t * __restrict optlen)
2000{
Florin Coras7baeb712019-01-04 17:05:43 -08002001 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002002 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05002003
Florin Coras5f33d0d2021-06-02 21:22:21 -07002004 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05002005
Florin Coras7baeb712019-01-04 17:05:43 -08002006 vlsh = ldp_fd_to_vlsh (fd);
2007 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05002008 {
2009 rv = -EOPNOTSUPP;
2010
2011 switch (level)
2012 {
2013 case SOL_TCP:
2014 switch (optname)
2015 {
2016 case TCP_NODELAY:
Florin Coras7baeb712019-01-04 17:05:43 -08002017 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_NODELAY,
2018 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002019 break;
2020 case TCP_MAXSEG:
Florin Coras7baeb712019-01-04 17:05:43 -08002021 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_USER_MSS,
2022 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002023 break;
2024 case TCP_KEEPIDLE:
Florin Coras7baeb712019-01-04 17:05:43 -08002025 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_KEEPIDLE,
2026 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002027 break;
2028 case TCP_KEEPINTVL:
Florin Coras7baeb712019-01-04 17:05:43 -08002029 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TCP_KEEPINTVL,
2030 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002031 break;
2032 case TCP_INFO:
2033 if (optval && optlen && (*optlen == sizeof (struct tcp_info)))
2034 {
Florin Coras7baeb712019-01-04 17:05:43 -08002035 LDBG (1, "fd %d: vlsh %u SOL_TCP, TCP_INFO, optval %p, "
2036 "optlen %d: #LDP-NOP#", fd, vlsh, optval, *optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002037 memset (optval, 0, *optlen);
2038 rv = VPPCOM_OK;
2039 }
2040 else
2041 rv = -EFAULT;
2042 break;
Florin Coras0ed24e92019-01-21 09:03:10 -08002043 case TCP_CONGESTION:
Florin Coras0ed24e92019-01-21 09:03:10 -08002044 *optlen = strlen ("cubic");
Dave Barach02500902020-04-04 18:34:41 -04002045 strncpy (optval, "cubic", *optlen + 1);
Florin Coras0ed24e92019-01-21 09:03:10 -08002046 rv = 0;
2047 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05002048 default:
Florin Coras7baeb712019-01-04 17:05:43 -08002049 LDBG (0, "ERROR: fd %d: getsockopt SOL_TCP: sid %u, "
2050 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05002051 break;
2052 }
2053 break;
qinyangaf9b7152023-06-27 01:11:53 -07002054 case SOL_IP:
2055 switch (optname)
2056 {
2057 case SO_ORIGINAL_DST:
2058 rv =
2059 vls_attr (vlsh, VPPCOM_ATTR_GET_ORIGINAL_DST, optval, optlen);
2060 break;
2061 default:
2062 LDBG (0,
2063 "ERROR: fd %d: getsockopt SOL_IP: vlsh %u "
2064 "optname %d unsupported!",
2065 fd, vlsh, optname);
2066 break;
2067 }
2068 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05002069 case SOL_IPV6:
2070 switch (optname)
2071 {
2072 case IPV6_V6ONLY:
Florin Coras7baeb712019-01-04 17:05:43 -08002073 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_V6ONLY, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002074 break;
2075 default:
Florin Coras7baeb712019-01-04 17:05:43 -08002076 LDBG (0, "ERROR: fd %d: getsockopt SOL_IPV6: vlsh %u "
2077 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05002078 break;
2079 }
2080 break;
2081 case SOL_SOCKET:
2082 switch (optname)
2083 {
2084 case SO_ACCEPTCONN:
Florin Coras7baeb712019-01-04 17:05:43 -08002085 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_LISTEN, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002086 break;
2087 case SO_KEEPALIVE:
Florin Coras7baeb712019-01-04 17:05:43 -08002088 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_KEEPALIVE, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002089 break;
2090 case SO_PROTOCOL:
Florin Coras7baeb712019-01-04 17:05:43 -08002091 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_PROTOCOL, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002092 *(int *) optval = *(int *) optval ? SOCK_DGRAM : SOCK_STREAM;
2093 break;
2094 case SO_SNDBUF:
Florin Coras7baeb712019-01-04 17:05:43 -08002095 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_TX_FIFO_LEN,
2096 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002097 break;
2098 case SO_RCVBUF:
Florin Coras7baeb712019-01-04 17:05:43 -08002099 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_RX_FIFO_LEN,
2100 optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002101 break;
2102 case SO_REUSEADDR:
Florin Coras7baeb712019-01-04 17:05:43 -08002103 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_REUSEADDR, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002104 break;
wanghanlin0674f852021-02-22 10:38:36 +08002105 case SO_REUSEPORT:
2106 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_REUSEPORT, optval, optlen);
2107 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05002108 case SO_BROADCAST:
Florin Coras7baeb712019-01-04 17:05:43 -08002109 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_BROADCAST, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002110 break;
wanghanlin0674f852021-02-22 10:38:36 +08002111 case SO_DOMAIN:
2112 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_DOMAIN, optval, optlen);
2113 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05002114 case SO_ERROR:
Florin Coras7baeb712019-01-04 17:05:43 -08002115 rv = vls_attr (vlsh, VPPCOM_ATTR_GET_ERROR, optval, optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002116 break;
Florin Coras8eb8d502021-06-16 14:46:57 -07002117 case SO_BINDTODEVICE:
2118 rv = 0;
2119 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05002120 default:
Florin Coras7baeb712019-01-04 17:05:43 -08002121 LDBG (0, "ERROR: fd %d: getsockopt SOL_SOCKET: vlsh %u "
2122 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05002123 break;
2124 }
2125 break;
2126 default:
2127 break;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002128 }
2129
Dave Wallace048b1d62018-01-03 22:24:41 -05002130 if (rv != VPPCOM_OK)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002131 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002132 errno = -rv;
2133 rv = -1;
2134 }
2135 }
2136 else
2137 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002138 rv = libc_getsockopt (fd, level, optname, optval, optlen);
2139 }
2140
Dave Wallace048b1d62018-01-03 22:24:41 -05002141 return rv;
2142}
2143
2144int
2145setsockopt (int fd, int level, int optname,
2146 const void *optval, socklen_t optlen)
2147{
Florin Coras7baeb712019-01-04 17:05:43 -08002148 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002149 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05002150
Florin Coras5f33d0d2021-06-02 21:22:21 -07002151 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05002152
Florin Coras7baeb712019-01-04 17:05:43 -08002153 vlsh = ldp_fd_to_vlsh (fd);
2154 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05002155 {
2156 rv = -EOPNOTSUPP;
2157
2158 switch (level)
2159 {
2160 case SOL_TCP:
2161 switch (optname)
2162 {
2163 case TCP_NODELAY:
Florin Coras7baeb712019-01-04 17:05:43 -08002164 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_NODELAY,
2165 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002166 break;
2167 case TCP_MAXSEG:
Florin Coras7baeb712019-01-04 17:05:43 -08002168 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_USER_MSS,
2169 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002170 break;
2171 case TCP_KEEPIDLE:
Florin Coras7baeb712019-01-04 17:05:43 -08002172 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_KEEPIDLE,
2173 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002174 break;
2175 case TCP_KEEPINTVL:
Florin Coras7baeb712019-01-04 17:05:43 -08002176 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_TCP_KEEPINTVL,
2177 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002178 break;
Florin Coras0ed24e92019-01-21 09:03:10 -08002179 case TCP_CONGESTION:
Florin Coras8509aa22019-04-04 12:55:30 -07002180 case TCP_CORK:
Florin Coras0ed24e92019-01-21 09:03:10 -08002181 /* Ignore */
2182 rv = 0;
2183 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05002184 default:
Florin Coras7baeb712019-01-04 17:05:43 -08002185 LDBG (0, "ERROR: fd %d: setsockopt() SOL_TCP: vlsh %u"
2186 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05002187 break;
2188 }
2189 break;
2190 case SOL_IPV6:
2191 switch (optname)
2192 {
2193 case IPV6_V6ONLY:
Florin Coras7baeb712019-01-04 17:05:43 -08002194 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_V6ONLY,
2195 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002196 break;
2197 default:
Florin Coras7baeb712019-01-04 17:05:43 -08002198 LDBG (0, "ERROR: fd %d: setsockopt SOL_IPV6: vlsh %u"
2199 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05002200 break;
2201 }
2202 break;
2203 case SOL_SOCKET:
2204 switch (optname)
2205 {
2206 case SO_KEEPALIVE:
Florin Coras7baeb712019-01-04 17:05:43 -08002207 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_KEEPALIVE,
2208 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002209 break;
2210 case SO_REUSEADDR:
Florin Coras7baeb712019-01-04 17:05:43 -08002211 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_REUSEADDR,
2212 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002213 break;
wanghanlin0674f852021-02-22 10:38:36 +08002214 case SO_REUSEPORT:
2215 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_REUSEPORT, (void *) optval,
2216 &optlen);
2217 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05002218 case SO_BROADCAST:
Florin Coras7baeb712019-01-04 17:05:43 -08002219 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_BROADCAST,
2220 (void *) optval, &optlen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002221 break;
Florin Coras2f647902021-06-02 08:23:50 -07002222 case SO_LINGER:
2223 rv = 0;
2224 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05002225 default:
Florin Coras7baeb712019-01-04 17:05:43 -08002226 LDBG (0, "ERROR: fd %d: setsockopt SOL_SOCKET: vlsh %u "
2227 "optname %d unsupported!", fd, vlsh, optname);
Dave Wallace048b1d62018-01-03 22:24:41 -05002228 break;
2229 }
2230 break;
Florin Coraseff5f7a2023-02-07 17:36:17 -08002231 case SOL_IP:
2232 switch (optname)
2233 {
2234 case IP_PKTINFO:
2235 rv = vls_attr (vlsh, VPPCOM_ATTR_SET_IP_PKTINFO, (void *) optval,
2236 &optlen);
2237 break;
2238 default:
2239 LDBG (0,
2240 "ERROR: fd %d: setsockopt SOL_IP: vlsh %u optname %d"
2241 "unsupported!",
2242 fd, vlsh, optname);
2243 break;
2244 }
2245 break;
Dave Wallace048b1d62018-01-03 22:24:41 -05002246 default:
2247 break;
2248 }
2249
2250 if (rv != VPPCOM_OK)
2251 {
2252 errno = -rv;
2253 rv = -1;
2254 }
2255 }
2256 else
2257 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002258 rv = libc_setsockopt (fd, level, optname, optval, optlen);
2259 }
2260
Dave Wallace048b1d62018-01-03 22:24:41 -05002261 return rv;
2262}
2263
2264int
2265listen (int fd, int n)
2266{
Florin Coras7baeb712019-01-04 17:05:43 -08002267 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002268 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05002269
Florin Coras5f33d0d2021-06-02 21:22:21 -07002270 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05002271
Florin Coras7baeb712019-01-04 17:05:43 -08002272 vlsh = ldp_fd_to_vlsh (fd);
2273 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05002274 {
Florin Coras7baeb712019-01-04 17:05:43 -08002275 LDBG (0, "fd %d: calling vls_listen: vlsh %u, n %d", fd, vlsh, n);
Dave Wallace048b1d62018-01-03 22:24:41 -05002276
Florin Coras7baeb712019-01-04 17:05:43 -08002277 rv = vls_listen (vlsh, n);
Dave Wallace048b1d62018-01-03 22:24:41 -05002278 if (rv != VPPCOM_OK)
2279 {
2280 errno = -rv;
2281 rv = -1;
2282 }
2283 }
2284 else
2285 {
Florin Coras7baeb712019-01-04 17:05:43 -08002286 LDBG (0, "fd %d: calling libc_listen(): n %d", fd, n);
Dave Wallace048b1d62018-01-03 22:24:41 -05002287 rv = libc_listen (fd, n);
2288 }
2289
Florin Coras7baeb712019-01-04 17:05:43 -08002290 LDBG (1, "fd %d: returning %d", fd, rv);
Dave Wallace048b1d62018-01-03 22:24:41 -05002291 return rv;
2292}
2293
2294static inline int
Florin Coras36847942023-02-02 12:56:16 -08002295ldp_accept4 (int listen_fd, __SOCKADDR_ARG _addr,
2296 socklen_t *__restrict addr_len, int flags)
Dave Wallace048b1d62018-01-03 22:24:41 -05002297{
Florin Coras36847942023-02-02 12:56:16 -08002298 struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
Florin Coras7baeb712019-01-04 17:05:43 -08002299 vls_handle_t listen_vlsh, accept_vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002300 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05002301
Florin Coras5f33d0d2021-06-02 21:22:21 -07002302 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05002303
Florin Coras7baeb712019-01-04 17:05:43 -08002304 listen_vlsh = ldp_fd_to_vlsh (listen_fd);
2305 if (listen_vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05002306 {
2307 vppcom_endpt_t ep;
2308 u8 src_addr[sizeof (struct sockaddr_in6)];
Dave Wallace8aaba562018-01-18 17:21:19 -05002309 memset (&ep, 0, sizeof (ep));
Dave Wallace048b1d62018-01-03 22:24:41 -05002310 ep.ip = src_addr;
2311
Florin Coras7baeb712019-01-04 17:05:43 -08002312 LDBG (0, "listen fd %d: calling vppcom_session_accept: listen sid %u,"
Florin Coraseb801d02020-09-16 17:44:58 -07002313 " ep %p, flags 0x%x", listen_fd, listen_vlsh, &ep, flags);
Dave Wallace048b1d62018-01-03 22:24:41 -05002314
Florin Coras7baeb712019-01-04 17:05:43 -08002315 accept_vlsh = vls_accept (listen_vlsh, &ep, flags);
2316 if (accept_vlsh < 0)
Dave Wallace048b1d62018-01-03 22:24:41 -05002317 {
Florin Coras7baeb712019-01-04 17:05:43 -08002318 errno = -accept_vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002319 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002320 }
2321 else
2322 {
Dave Wallace2a865272018-02-07 21:00:42 -05002323 rv = ldp_copy_ep_to_sockaddr (addr, addr_len, &ep);
Dave Wallace048b1d62018-01-03 22:24:41 -05002324 if (rv != VPPCOM_OK)
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002325 {
Florin Coras7baeb712019-01-04 17:05:43 -08002326 (void) vls_close (accept_vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05002327 errno = -rv;
2328 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002329 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002330 else
2331 {
Florin Coras7baeb712019-01-04 17:05:43 -08002332 rv = ldp_vlsh_to_fd (accept_vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05002333 }
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002334 }
2335 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002336 else
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002337 {
Florin Coras7baeb712019-01-04 17:05:43 -08002338 LDBG (0, "listen fd %d: calling libc_accept4(): addr %p, addr_len %p,"
2339 " flags 0x%x", listen_fd, addr, addr_len, flags);
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002340
Dave Wallace048b1d62018-01-03 22:24:41 -05002341 rv = libc_accept4 (listen_fd, addr, addr_len, flags);
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002342 }
2343
Florin Coras7baeb712019-01-04 17:05:43 -08002344 LDBG (1, "listen fd %d: accept returning %d", listen_fd, rv);
Florin Coras05ecfcc2018-12-12 18:19:39 -08002345
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002346 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002347}
2348
Dave Wallace048b1d62018-01-03 22:24:41 -05002349int
2350accept4 (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len,
2351 int flags)
2352{
Dave Wallace2a865272018-02-07 21:00:42 -05002353 return ldp_accept4 (fd, addr, addr_len, flags);
Dave Wallace048b1d62018-01-03 22:24:41 -05002354}
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002355
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002356int
Dave Wallace048b1d62018-01-03 22:24:41 -05002357accept (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002358{
Dave Wallace2a865272018-02-07 21:00:42 -05002359 return ldp_accept4 (fd, addr, addr_len, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002360}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002361
Dave Wallace048b1d62018-01-03 22:24:41 -05002362int
2363shutdown (int fd, int how)
2364{
Florin Coras7baeb712019-01-04 17:05:43 -08002365 vls_handle_t vlsh;
liuyacan55c952e2021-06-13 14:54:55 +08002366 int rv = 0;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002367
Florin Coras5f33d0d2021-06-02 21:22:21 -07002368 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05002369
Florin Coras7baeb712019-01-04 17:05:43 -08002370 vlsh = ldp_fd_to_vlsh (fd);
2371 if (vlsh != VLS_INVALID_HANDLE)
Dave Wallace048b1d62018-01-03 22:24:41 -05002372 {
Florin Coras7baeb712019-01-04 17:05:43 -08002373 LDBG (0, "called shutdown: fd %u vlsh %u how %d", fd, vlsh, how);
liuyacan55c952e2021-06-13 14:54:55 +08002374 rv = vls_shutdown (vlsh, how);
Dave Wallace048b1d62018-01-03 22:24:41 -05002375 }
2376 else
2377 {
Florin Coras7baeb712019-01-04 17:05:43 -08002378 LDBG (0, "fd %d: calling libc_shutdown: how %d", fd, how);
Dave Wallace048b1d62018-01-03 22:24:41 -05002379 rv = libc_shutdown (fd, how);
2380 }
2381
Dave Wallace048b1d62018-01-03 22:24:41 -05002382 return rv;
2383}
2384
2385int
2386epoll_create1 (int flags)
2387{
Florin Corasdfe4cf42018-11-28 22:13:45 -08002388 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras7baeb712019-01-04 17:05:43 -08002389 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002390 int rv;
2391
Florin Coras5f33d0d2021-06-02 21:22:21 -07002392 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05002393
hanlina3a48962020-07-13 11:09:15 +08002394 if (ldp->vcl_needs_real_epoll || vls_use_real_epoll ())
Florin Coras99368312018-08-02 10:45:44 -07002395 {
Florin Coras2d9b4272019-03-11 10:14:37 -07002396 /* Make sure workers have been allocated */
2397 if (!ldp->workers)
2398 {
2399 ldp_alloc_workers ();
2400 ldpw = ldp_worker_get_current ();
2401 }
Florin Coras99368312018-08-02 10:45:44 -07002402 rv = libc_epoll_create1 (flags);
2403 ldp->vcl_needs_real_epoll = 0;
Florin Corasdfe4cf42018-11-28 22:13:45 -08002404 ldpw->vcl_mq_epfd = rv;
Florin Coras05ecfcc2018-12-12 18:19:39 -08002405 LDBG (0, "created vcl epfd %u", rv);
Florin Coras99368312018-08-02 10:45:44 -07002406 return rv;
2407 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002408
Florin Coras7baeb712019-01-04 17:05:43 -08002409 vlsh = vls_epoll_create ();
2410 if (PREDICT_FALSE (vlsh == VLS_INVALID_HANDLE))
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002411 {
Florin Coras7baeb712019-01-04 17:05:43 -08002412 errno = -vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002413 rv = -1;
shrinivasan ganapathy1d359632017-10-15 15:46:09 -07002414 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002415 else
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002416 {
Florin Coras7baeb712019-01-04 17:05:43 -08002417 rv = ldp_vlsh_to_fd (vlsh);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002418 }
Florin Coras7baeb712019-01-04 17:05:43 -08002419 LDBG (0, "epoll_create epfd %u vlsh %u", rv, vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05002420 return rv;
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002421}
2422
2423int
Dave Wallace048b1d62018-01-03 22:24:41 -05002424epoll_create (int size)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002425{
Dave Wallace048b1d62018-01-03 22:24:41 -05002426 return epoll_create1 (0);
2427}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002428
Dave Wallace048b1d62018-01-03 22:24:41 -05002429int
2430epoll_ctl (int epfd, int op, int fd, struct epoll_event *event)
2431{
Florin Coras7baeb712019-01-04 17:05:43 -08002432 vls_handle_t vep_vlsh, vlsh;
Florin Coras99368312018-08-02 10:45:44 -07002433 int rv;
Dave Wallace048b1d62018-01-03 22:24:41 -05002434
Florin Coras5f33d0d2021-06-02 21:22:21 -07002435 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05002436
Florin Coras7baeb712019-01-04 17:05:43 -08002437 vep_vlsh = ldp_fd_to_vlsh (epfd);
2438 if (PREDICT_FALSE (vep_vlsh == VLS_INVALID_HANDLE))
Dave Wallace048b1d62018-01-03 22:24:41 -05002439 {
Dave Wallace3ee1fe12018-02-23 01:09:11 -05002440 /* The LDP epoll_create1 always creates VCL epfd's.
2441 * The app should never have a kernel base epoll fd unless it
2442 * was acquired outside of the LD_PRELOAD process context.
2443 * In any case, if we get one, punt it to libc_epoll_ctl.
2444 */
Florin Corasc86662a2023-03-05 11:45:38 -08002445 LDBG (1,
2446 "epfd %d: calling libc_epoll_ctl: op %d, fd %d"
2447 " events 0x%x",
2448 epfd, op, fd, event ? event->events : 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002449
2450 rv = libc_epoll_ctl (epfd, op, fd, event);
Florin Coras99368312018-08-02 10:45:44 -07002451 goto done;
2452 }
2453
Florin Coras7baeb712019-01-04 17:05:43 -08002454 vlsh = ldp_fd_to_vlsh (fd);
Florin Coras99368312018-08-02 10:45:44 -07002455
Florin Coras7baeb712019-01-04 17:05:43 -08002456 LDBG (0, "epfd %d ep_vlsh %d, fd %u vlsh %d, op %u", epfd, vep_vlsh, fd,
2457 vlsh, op);
Florin Coras99368312018-08-02 10:45:44 -07002458
Florin Coras7baeb712019-01-04 17:05:43 -08002459 if (vlsh != VLS_INVALID_HANDLE)
Florin Coras99368312018-08-02 10:45:44 -07002460 {
Florin Corasc86662a2023-03-05 11:45:38 -08002461 LDBG (1,
2462 "epfd %d: calling vls_epoll_ctl: ep_vlsh %d op %d, vlsh %u,"
2463 " events 0x%x",
2464 epfd, vep_vlsh, op, vlsh, event ? event->events : 0);
Florin Coras99368312018-08-02 10:45:44 -07002465
Florin Coras7baeb712019-01-04 17:05:43 -08002466 rv = vls_epoll_ctl (vep_vlsh, op, vlsh, event);
Florin Coras99368312018-08-02 10:45:44 -07002467 if (rv != VPPCOM_OK)
2468 {
2469 errno = -rv;
2470 rv = -1;
2471 }
2472 }
2473 else
2474 {
2475 int libc_epfd;
2476 u32 size = sizeof (epfd);
2477
Florin Coras7baeb712019-01-04 17:05:43 -08002478 libc_epfd = vls_attr (vep_vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
Florin Coras99368312018-08-02 10:45:44 -07002479 if (!libc_epfd)
2480 {
Florin Coras7baeb712019-01-04 17:05:43 -08002481 LDBG (1, "epfd %d, vep_vlsh %d calling libc_epoll_create1: "
2482 "EPOLL_CLOEXEC", epfd, vep_vlsh);
Florin Coras99368312018-08-02 10:45:44 -07002483
2484 libc_epfd = libc_epoll_create1 (EPOLL_CLOEXEC);
2485 if (libc_epfd < 0)
2486 {
2487 rv = libc_epfd;
2488 goto done;
2489 }
2490
Florin Coras7baeb712019-01-04 17:05:43 -08002491 rv = vls_attr (vep_vlsh, VPPCOM_ATTR_SET_LIBC_EPFD, &libc_epfd,
2492 &size);
Florin Coras99368312018-08-02 10:45:44 -07002493 if (rv < 0)
2494 {
2495 errno = -rv;
2496 rv = -1;
2497 goto done;
2498 }
2499 }
2500 else if (PREDICT_FALSE (libc_epfd < 0))
2501 {
2502 errno = -epfd;
2503 rv = -1;
2504 goto done;
2505 }
2506
Florin Coras7baeb712019-01-04 17:05:43 -08002507 LDBG (1, "epfd %d: calling libc_epoll_ctl: libc_epfd %d, op %d, fd %d,"
2508 " event %p", epfd, libc_epfd, op, fd, event);
Florin Coras99368312018-08-02 10:45:44 -07002509
2510 rv = libc_epoll_ctl (libc_epfd, op, fd, event);
Dave Wallace048b1d62018-01-03 22:24:41 -05002511 }
2512
2513done:
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002514 return rv;
2515}
Dave Wallace048b1d62018-01-03 22:24:41 -05002516
2517static inline int
Florin Coras99368312018-08-02 10:45:44 -07002518ldp_epoll_pwait (int epfd, struct epoll_event *events, int maxevents,
2519 int timeout, const sigset_t * sigmask)
Dave Wallace048b1d62018-01-03 22:24:41 -05002520{
Liangxing Wang7c7231f2023-02-16 09:31:01 +00002521 ldp_worker_ctx_t *ldpw;
Florin Coras72f77822019-01-22 19:05:52 -08002522 double time_to_wait = (double) 0, max_time;
Florin Coras99368312018-08-02 10:45:44 -07002523 int libc_epfd, rv = 0;
Florin Coras7baeb712019-01-04 17:05:43 -08002524 vls_handle_t ep_vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002525
Florin Coras5f33d0d2021-06-02 21:22:21 -07002526 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05002527
2528 if (PREDICT_FALSE (!events || (timeout < -1)))
2529 {
2530 errno = EFAULT;
2531 return -1;
2532 }
2533
Liangxing Wang7c7231f2023-02-16 09:31:01 +00002534 if (PREDICT_FALSE (vppcom_worker_index () == ~0))
2535 vls_register_vcl_worker ();
2536
2537 ldpw = ldp_worker_get_current ();
Florin Corasdfe4cf42018-11-28 22:13:45 -08002538 if (epfd == ldpw->vcl_mq_epfd)
Florin Coras99368312018-08-02 10:45:44 -07002539 return libc_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
2540
Florin Coras7baeb712019-01-04 17:05:43 -08002541 ep_vlsh = ldp_fd_to_vlsh (epfd);
2542 if (PREDICT_FALSE (ep_vlsh == VLS_INVALID_HANDLE))
Dave Wallace048b1d62018-01-03 22:24:41 -05002543 {
Florin Coras7baeb712019-01-04 17:05:43 -08002544 LDBG (0, "epfd %d: bad ep_vlsh %d!", epfd, ep_vlsh);
Dave Wallace048b1d62018-01-03 22:24:41 -05002545 errno = EBADFD;
2546 return -1;
2547 }
2548
Florin Coras4dee8cd2019-01-29 21:28:16 -08002549 if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
2550 clib_time_init (&ldpw->clib_time);
Florin Corasb0f662f2018-12-27 14:51:46 -08002551 time_to_wait = ((timeout >= 0) ? (double) timeout / 1000 : 0);
Florin Coras72f77822019-01-22 19:05:52 -08002552 max_time = clib_time_now (&ldpw->clib_time) + time_to_wait;
Dave Wallace048b1d62018-01-03 22:24:41 -05002553
Florin Coras7baeb712019-01-04 17:05:43 -08002554 libc_epfd = vls_attr (ep_vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002555 if (PREDICT_FALSE (libc_epfd < 0))
2556 {
2557 errno = -libc_epfd;
2558 rv = -1;
2559 goto done;
2560 }
2561
Florin Coras7baeb712019-01-04 17:05:43 -08002562 LDBG (2, "epfd %d: vep_idx %d, libc_epfd %d, events %p, maxevents %d, "
2563 "timeout %d, sigmask %p: time_to_wait %.02f", epfd, ep_vlsh,
Florin Coras72f77822019-01-22 19:05:52 -08002564 libc_epfd, events, maxevents, timeout, sigmask, time_to_wait);
Dave Wallace048b1d62018-01-03 22:24:41 -05002565 do
2566 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002567 if (!ldpw->epoll_wait_vcl)
Dave Wallace048b1d62018-01-03 22:24:41 -05002568 {
Florin Coras7baeb712019-01-04 17:05:43 -08002569 rv = vls_epoll_wait (ep_vlsh, events, maxevents, 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002570 if (rv > 0)
2571 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002572 ldpw->epoll_wait_vcl = 1;
Dave Wallace048b1d62018-01-03 22:24:41 -05002573 goto done;
2574 }
2575 else if (rv < 0)
2576 {
2577 errno = -rv;
2578 rv = -1;
2579 goto done;
2580 }
2581 }
2582 else
Florin Corasdfe4cf42018-11-28 22:13:45 -08002583 ldpw->epoll_wait_vcl = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -05002584
2585 if (libc_epfd > 0)
2586 {
Florin Corasb0f662f2018-12-27 14:51:46 -08002587 rv = libc_epoll_pwait (libc_epfd, events, maxevents, 0, sigmask);
Dave Wallace048b1d62018-01-03 22:24:41 -05002588 if (rv != 0)
2589 goto done;
2590 }
Dave Wallace048b1d62018-01-03 22:24:41 -05002591 }
Florin Coras72f77822019-01-22 19:05:52 -08002592 while ((timeout == -1) || (clib_time_now (&ldpw->clib_time) < max_time));
Dave Wallace048b1d62018-01-03 22:24:41 -05002593
2594done:
Dave Wallace048b1d62018-01-03 22:24:41 -05002595 return rv;
2596}
2597
hanlin4266d4d2020-05-19 17:34:17 +08002598static inline int
2599ldp_epoll_pwait_eventfd (int epfd, struct epoll_event *events,
2600 int maxevents, int timeout, const sigset_t * sigmask)
2601{
Florin Corasc86662a2023-03-05 11:45:38 -08002602 int libc_epfd, rv = 0, num_ev, libc_num_ev, vcl_wups = 0;
2603 struct epoll_event *libc_evts;
hanlina3a48962020-07-13 11:09:15 +08002604 ldp_worker_ctx_t *ldpw;
hanlin4266d4d2020-05-19 17:34:17 +08002605 vls_handle_t ep_vlsh;
2606
Florin Coras5f33d0d2021-06-02 21:22:21 -07002607 ldp_init_check ();
hanlin4266d4d2020-05-19 17:34:17 +08002608
2609 if (PREDICT_FALSE (!events || (timeout < -1)))
2610 {
2611 errno = EFAULT;
2612 return -1;
2613 }
2614
Florin Corasff40d8f2020-08-11 22:05:28 -07002615 /* Make sure the vcl worker is valid. Could be that epoll fd was created on
2616 * one thread but it is now used on another */
2617 if (PREDICT_FALSE (vppcom_worker_index () == ~0))
2618 vls_register_vcl_worker ();
hanlina3a48962020-07-13 11:09:15 +08002619
2620 ldpw = ldp_worker_get_current ();
hanlin4266d4d2020-05-19 17:34:17 +08002621 if (epfd == ldpw->vcl_mq_epfd)
2622 return libc_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
2623
2624 ep_vlsh = ldp_fd_to_vlsh (epfd);
2625 if (PREDICT_FALSE (ep_vlsh == VLS_INVALID_HANDLE))
2626 {
2627 LDBG (0, "epfd %d: bad ep_vlsh %d!", epfd, ep_vlsh);
2628 errno = EBADFD;
2629 return -1;
2630 }
2631
2632 libc_epfd = vls_attr (ep_vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
2633 if (PREDICT_FALSE (!libc_epfd))
2634 {
2635 u32 size = sizeof (epfd);
2636
2637 LDBG (1, "epfd %d, vep_vlsh %d calling libc_epoll_create1: "
2638 "EPOLL_CLOEXEC", epfd, ep_vlsh);
2639 libc_epfd = libc_epoll_create1 (EPOLL_CLOEXEC);
2640 if (libc_epfd < 0)
2641 {
2642 rv = libc_epfd;
2643 goto done;
2644 }
2645
2646 rv = vls_attr (ep_vlsh, VPPCOM_ATTR_SET_LIBC_EPFD, &libc_epfd, &size);
2647 if (rv < 0)
2648 {
2649 errno = -rv;
2650 rv = -1;
2651 goto done;
2652 }
2653 }
2654 if (PREDICT_FALSE (libc_epfd <= 0))
2655 {
2656 errno = -libc_epfd;
2657 rv = -1;
2658 goto done;
2659 }
2660
2661 if (PREDICT_FALSE (!ldpw->mq_epfd_added))
2662 {
2663 struct epoll_event e = { 0 };
2664 e.events = EPOLLIN;
2665 e.data.fd = ldpw->vcl_mq_epfd;
2666 if (libc_epoll_ctl (libc_epfd, EPOLL_CTL_ADD, ldpw->vcl_mq_epfd, &e) <
2667 0)
2668 {
2669 LDBG (0, "epfd %d, add libc mq epoll fd %d to libc epoll fd %d",
2670 epfd, ldpw->vcl_mq_epfd, libc_epfd);
2671 rv = -1;
2672 goto done;
2673 }
2674 ldpw->mq_epfd_added = 1;
2675 }
2676
wanghanlin8919fec2021-03-18 20:00:41 +08002677 /* Request to only drain unhandled to prevent libc_epoll_wait starved */
2678 rv = vls_epoll_wait (ep_vlsh, events, maxevents, -2);
hanlin4266d4d2020-05-19 17:34:17 +08002679 if (rv > 0)
Florin Corasc86662a2023-03-05 11:45:38 -08002680 {
2681 timeout = 0;
2682 if (rv >= maxevents)
2683 goto done;
Florin Coras55c699e2023-08-15 12:11:50 -07002684 maxevents -= rv;
Florin Corasc86662a2023-03-05 11:45:38 -08002685 }
hanlina3a48962020-07-13 11:09:15 +08002686 else if (PREDICT_FALSE (rv < 0))
hanlin4266d4d2020-05-19 17:34:17 +08002687 {
2688 errno = -rv;
2689 rv = -1;
2690 goto done;
2691 }
2692
Florin Coras7a1e95a2023-03-01 00:45:31 -08002693epoll_again:
Florin Corasc86662a2023-03-05 11:45:38 -08002694
2695 libc_evts = &events[rv];
2696 libc_num_ev =
Florin Coras55c699e2023-08-15 12:11:50 -07002697 libc_epoll_pwait (libc_epfd, libc_evts, maxevents, timeout, sigmask);
Florin Corasc86662a2023-03-05 11:45:38 -08002698 if (libc_num_ev <= 0)
hanlin4266d4d2020-05-19 17:34:17 +08002699 {
Florin Corasc86662a2023-03-05 11:45:38 -08002700 rv = rv >= 0 ? rv : -1;
2701 goto done;
2702 }
2703
2704 for (int i = 0; i < libc_num_ev; i++)
2705 {
2706 if (libc_evts[i].data.fd == ldpw->vcl_mq_epfd)
hanlin4266d4d2020-05-19 17:34:17 +08002707 {
2708 /* We should remove mq epoll fd from events. */
Florin Corasc86662a2023-03-05 11:45:38 -08002709 libc_num_ev--;
2710 if (i != libc_num_ev)
hanlin4266d4d2020-05-19 17:34:17 +08002711 {
Florin Corasc86662a2023-03-05 11:45:38 -08002712 libc_evts[i].events = libc_evts[libc_num_ev].events;
2713 libc_evts[i].data.u64 = libc_evts[libc_num_ev].data.u64;
hanlin4266d4d2020-05-19 17:34:17 +08002714 }
Florin Corasc86662a2023-03-05 11:45:38 -08002715 num_ev = vls_epoll_wait (ep_vlsh, &libc_evts[libc_num_ev],
2716 maxevents - libc_num_ev, 0);
hanlin4266d4d2020-05-19 17:34:17 +08002717 if (PREDICT_TRUE (num_ev > 0))
2718 rv += num_ev;
Florin Coras7a1e95a2023-03-01 00:45:31 -08002719 /* Woken up by vcl but no events generated. Accept it once */
Florin Corasc86662a2023-03-05 11:45:38 -08002720 if (rv == 0 && libc_num_ev == 0 && timeout && vcl_wups++ < 1)
Florin Coras7a1e95a2023-03-01 00:45:31 -08002721 goto epoll_again;
hanlin4266d4d2020-05-19 17:34:17 +08002722 break;
2723 }
2724 }
2725
Florin Corasc86662a2023-03-05 11:45:38 -08002726 rv += libc_num_ev;
2727
hanlin4266d4d2020-05-19 17:34:17 +08002728done:
2729 return rv;
2730}
2731
Dave Wallace048b1d62018-01-03 22:24:41 -05002732int
2733epoll_pwait (int epfd, struct epoll_event *events,
2734 int maxevents, int timeout, const sigset_t * sigmask)
2735{
hanlin4266d4d2020-05-19 17:34:17 +08002736 if (vls_use_eventfd ())
2737 return ldp_epoll_pwait_eventfd (epfd, events, maxevents, timeout,
2738 sigmask);
2739 else
2740 return ldp_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
Dave Wallace048b1d62018-01-03 22:24:41 -05002741}
2742
2743int
2744epoll_wait (int epfd, struct epoll_event *events, int maxevents, int timeout)
2745{
hanlin4266d4d2020-05-19 17:34:17 +08002746 if (vls_use_eventfd ())
2747 return ldp_epoll_pwait_eventfd (epfd, events, maxevents, timeout, NULL);
2748 else
2749 return ldp_epoll_pwait (epfd, events, maxevents, timeout, NULL);
Dave Wallace048b1d62018-01-03 22:24:41 -05002750}
2751
2752int
2753poll (struct pollfd *fds, nfds_t nfds, int timeout)
2754{
Florin Corasdfe4cf42018-11-28 22:13:45 -08002755 ldp_worker_ctx_t *ldpw = ldp_worker_get_current ();
Florin Coras6917b942018-11-13 22:44:54 -08002756 int rv, i, n_revents = 0;
Florin Coras7baeb712019-01-04 17:05:43 -08002757 vls_handle_t vlsh;
Dave Wallace048b1d62018-01-03 22:24:41 -05002758 vcl_poll_t *vp;
Florin Coras4dee8cd2019-01-29 21:28:16 -08002759 double max_time;
Dave Wallace048b1d62018-01-03 22:24:41 -05002760
Florin Coraseb801d02020-09-16 17:44:58 -07002761 LDBG (3, "fds %p, nfds %ld, timeout %d", fds, nfds, timeout);
Dave Wallace048b1d62018-01-03 22:24:41 -05002762
Florin Coras4dee8cd2019-01-29 21:28:16 -08002763 if (PREDICT_FALSE (ldpw->clib_time.init_cpu_time == 0))
2764 clib_time_init (&ldpw->clib_time);
2765
2766 max_time = (timeout >= 0) ? (f64) timeout / 1000 : 0;
2767 max_time += clib_time_now (&ldpw->clib_time);
Dave Wallace048b1d62018-01-03 22:24:41 -05002768
Dave Wallace048b1d62018-01-03 22:24:41 -05002769 for (i = 0; i < nfds; i++)
2770 {
Florin Coras6917b942018-11-13 22:44:54 -08002771 if (fds[i].fd < 0)
2772 continue;
Dave Wallace048b1d62018-01-03 22:24:41 -05002773
Florin Coras7baeb712019-01-04 17:05:43 -08002774 vlsh = ldp_fd_to_vlsh (fds[i].fd);
2775 if (vlsh != VLS_INVALID_HANDLE)
Florin Coras6917b942018-11-13 22:44:54 -08002776 {
2777 fds[i].fd = -fds[i].fd;
Florin Corasdfe4cf42018-11-28 22:13:45 -08002778 vec_add2 (ldpw->vcl_poll, vp, 1);
Florin Coras6917b942018-11-13 22:44:54 -08002779 vp->fds_ndx = i;
Florin Coras7baeb712019-01-04 17:05:43 -08002780 vp->sh = vlsh_to_sh (vlsh);
Florin Coras6917b942018-11-13 22:44:54 -08002781 vp->events = fds[i].events;
Dave Wallace048b1d62018-01-03 22:24:41 -05002782#ifdef __USE_XOPEN2K
Florin Coras6917b942018-11-13 22:44:54 -08002783 if (fds[i].events & POLLRDNORM)
2784 vp->events |= POLLIN;
2785 if (fds[i].events & POLLWRNORM)
2786 vp->events |= POLLOUT;
Dave Wallace048b1d62018-01-03 22:24:41 -05002787#endif
Florin Coras6917b942018-11-13 22:44:54 -08002788 vp->revents = fds[i].revents;
2789 }
2790 else
2791 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002792 vec_add1 (ldpw->libc_poll, fds[i]);
2793 vec_add1 (ldpw->libc_poll_idxs, i);
Dave Wallace048b1d62018-01-03 22:24:41 -05002794 }
2795 }
2796
Dave Wallace048b1d62018-01-03 22:24:41 -05002797 do
2798 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002799 if (vec_len (ldpw->vcl_poll))
Dave Wallace048b1d62018-01-03 22:24:41 -05002800 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002801 rv = vppcom_poll (ldpw->vcl_poll, vec_len (ldpw->vcl_poll), 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002802 if (rv < 0)
2803 {
2804 errno = -rv;
2805 rv = -1;
2806 goto done;
2807 }
2808 else
2809 n_revents += rv;
2810 }
2811
Florin Corasdfe4cf42018-11-28 22:13:45 -08002812 if (vec_len (ldpw->libc_poll))
Dave Wallace048b1d62018-01-03 22:24:41 -05002813 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002814 rv = libc_poll (ldpw->libc_poll, vec_len (ldpw->libc_poll), 0);
Dave Wallace048b1d62018-01-03 22:24:41 -05002815 if (rv < 0)
2816 goto done;
2817 else
2818 n_revents += rv;
2819 }
2820
2821 if (n_revents)
2822 {
2823 rv = n_revents;
2824 goto done;
2825 }
2826 }
Florin Coras4dee8cd2019-01-29 21:28:16 -08002827 while ((timeout < 0) || (clib_time_now (&ldpw->clib_time) < max_time));
Dave Wallace048b1d62018-01-03 22:24:41 -05002828 rv = 0;
2829
2830done:
Florin Corasdfe4cf42018-11-28 22:13:45 -08002831 vec_foreach (vp, ldpw->vcl_poll)
Dave Wallace048b1d62018-01-03 22:24:41 -05002832 {
2833 fds[vp->fds_ndx].fd = -fds[vp->fds_ndx].fd;
Florin Coras6917b942018-11-13 22:44:54 -08002834 fds[vp->fds_ndx].revents = vp->revents;
Dave Wallace048b1d62018-01-03 22:24:41 -05002835#ifdef __USE_XOPEN2K
2836 if ((fds[vp->fds_ndx].revents & POLLIN) &&
2837 (fds[vp->fds_ndx].events & POLLRDNORM))
2838 fds[vp->fds_ndx].revents |= POLLRDNORM;
2839 if ((fds[vp->fds_ndx].revents & POLLOUT) &&
2840 (fds[vp->fds_ndx].events & POLLWRNORM))
2841 fds[vp->fds_ndx].revents |= POLLWRNORM;
2842#endif
2843 }
Florin Corasdfe4cf42018-11-28 22:13:45 -08002844 vec_reset_length (ldpw->vcl_poll);
Dave Wallace048b1d62018-01-03 22:24:41 -05002845
Florin Corasdfe4cf42018-11-28 22:13:45 -08002846 for (i = 0; i < vec_len (ldpw->libc_poll); i++)
Florin Coras6917b942018-11-13 22:44:54 -08002847 {
Florin Corasdfe4cf42018-11-28 22:13:45 -08002848 fds[ldpw->libc_poll_idxs[i]].revents = ldpw->libc_poll[i].revents;
Florin Coras6917b942018-11-13 22:44:54 -08002849 }
Florin Corasdfe4cf42018-11-28 22:13:45 -08002850 vec_reset_length (ldpw->libc_poll_idxs);
2851 vec_reset_length (ldpw->libc_poll);
Florin Coras6917b942018-11-13 22:44:54 -08002852
Dave Wallace048b1d62018-01-03 22:24:41 -05002853 return rv;
2854}
2855
Florin Coras36847942023-02-02 12:56:16 -08002856#ifdef _GNU_SOURCE
Dave Wallace048b1d62018-01-03 22:24:41 -05002857int
2858ppoll (struct pollfd *fds, nfds_t nfds,
2859 const struct timespec *timeout, const sigset_t * sigmask)
2860{
Florin Coras5f33d0d2021-06-02 21:22:21 -07002861 ldp_init_check ();
Dave Wallace048b1d62018-01-03 22:24:41 -05002862
2863 clib_warning ("LDP<%d>: LDP-TBD", getpid ());
2864 errno = ENOSYS;
2865
2866
2867 return -1;
2868}
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002869#endif
2870
Dave Wallace2a865272018-02-07 21:00:42 -05002871void CONSTRUCTOR_ATTRIBUTE ldp_constructor (void);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002872
Dave Wallace2a865272018-02-07 21:00:42 -05002873void DESTRUCTOR_ATTRIBUTE ldp_destructor (void);
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002874
Dave Wallace048b1d62018-01-03 22:24:41 -05002875/*
2876 * This function is called when the library is loaded
2877 */
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002878void
Dave Wallace2a865272018-02-07 21:00:42 -05002879ldp_constructor (void)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002880{
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002881 swrap_constructor ();
Dave Wallace2a865272018-02-07 21:00:42 -05002882 if (ldp_init () != 0)
Florin Corasd89411e2019-03-19 19:44:51 -07002883 {
2884 fprintf (stderr, "\nLDP<%d>: ERROR: ldp_constructor: failed!\n",
2885 getpid ());
2886 _exit (1);
2887 }
Dave Wallace69d01192018-02-22 16:22:09 -05002888 else if (LDP_DEBUG > 0)
Dave Wallace2a865272018-02-07 21:00:42 -05002889 clib_warning ("LDP<%d>: LDP constructor: done!\n", getpid ());
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002890}
2891
2892/*
2893 * This function is called when the library is unloaded
2894 */
2895void
Dave Wallace2a865272018-02-07 21:00:42 -05002896ldp_destructor (void)
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002897{
Florin Coras0ef8ef22019-01-18 08:37:13 -08002898 /*
2899 swrap_destructor ();
2900 if (ldp->init)
2901 ldp->init = 0;
2902 */
Dave Wallace048b1d62018-01-03 22:24:41 -05002903
2904 /* Don't use clib_warning() here because that calls writev()
Dave Wallace2a865272018-02-07 21:00:42 -05002905 * which will call ldp_init().
Dave Wallace048b1d62018-01-03 22:24:41 -05002906 */
Dave Wallace69d01192018-02-22 16:22:09 -05002907 if (LDP_DEBUG > 0)
Florin Coras0ef8ef22019-01-18 08:37:13 -08002908 fprintf (stderr, "%s:%d: LDP<%d>: LDP destructor: done!\n",
2909 __func__, __LINE__, getpid ());
Keith Burns (alagalah)b327c2b2017-10-09 08:52:59 -07002910}
2911
2912
2913/*
2914 * fd.io coding-style-patch-verification: ON
2915 *
2916 * Local Variables:
2917 * eval: (c-set-style "gnu")
2918 * End:
2919 */