aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/vcl/ldp.c127
-rw-r--r--src/vcl/vppcom.c6
-rw-r--r--src/vcl/vppcom.h1
3 files changed, 112 insertions, 22 deletions
diff --git a/src/vcl/ldp.c b/src/vcl/ldp.c
index beaa988185d..dfbb383f046 100644
--- a/src/vcl/ldp.c
+++ b/src/vcl/ldp.c
@@ -29,6 +29,9 @@
#include <vcl/vppcom.h>
#include <vppinfra/time.h>
#include <vppinfra/bitmap.h>
+#include <vppinfra/lock.h>
+#include <vppinfra/pool.h>
+#include <vppinfra/hash.h>
#define HAVE_CONSTRUCTOR_ATTRIBUTE
#ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
@@ -46,6 +49,13 @@
#define DESTRUCTOR_ATTRIBUTE
#endif
+typedef struct ldp_fd_entry_
+{
+ u32 sid;
+ u32 fd;
+ u32 fd_index;
+} ldp_fd_entry_t;
+
typedef struct
{
int init;
@@ -72,7 +82,9 @@ typedef struct
u8 vcl_needs_real_epoll; /*< vcl needs next epoll_create to
go to libc_epoll */
int vcl_mq_epfd;
-
+ ldp_fd_entry_t *fd_pool;
+ clib_rwlock_t fd_table_lock;
+ uword *sid_to_fd_table;
} ldp_main_t;
#define LDP_DEBUG ldp->debug
@@ -110,26 +122,94 @@ ldp_get_app_name ()
return ldp->app_name;
}
+static int
+ldp_fd_alloc (u32 sid)
+{
+ ldp_fd_entry_t *fde;
+
+ clib_rwlock_writer_lock (&ldp->fd_table_lock);
+ if (pool_elts (ldp->fd_pool) >= (1ULL << 32) - ldp->sid_bit_val)
+ {
+ clib_rwlock_writer_unlock (&ldp->fd_table_lock);
+ return -1;
+ }
+ pool_get (ldp->fd_pool, fde);
+ fde->sid = sid;
+ fde->fd_index = fde - ldp->fd_pool;
+ fde->fd = fde->fd_index + ldp->sid_bit_val;
+ hash_set (ldp->sid_to_fd_table, sid, fde->fd);
+ clib_rwlock_writer_unlock (&ldp->fd_table_lock);
+ return fde->fd;
+}
+
+static ldp_fd_entry_t *
+ldp_fd_entry_get_w_lock (u32 fd_index)
+{
+ clib_rwlock_reader_lock (&ldp->fd_table_lock);
+ if (pool_is_free_index (ldp->fd_pool, fd_index))
+ return 0;
+
+ return pool_elt_at_index (ldp->fd_pool, fd_index);
+}
+
static inline int
ldp_fd_from_sid (u32 sid)
{
- if (PREDICT_FALSE (sid >= ldp->sid_bit_val))
- return -EMFILE;
- else
- return (sid | ldp->sid_bit_val);
+ uword *fdp;
+ int fd;
+
+ clib_rwlock_reader_lock (&ldp->fd_table_lock);
+ fdp = hash_get (ldp->sid_to_fd_table, sid);
+ fd = fdp ? *fdp : -EMFILE;
+ clib_rwlock_reader_unlock (&ldp->fd_table_lock);
+
+ return fd;
}
static inline int
ldp_fd_is_sid (int fd)
{
- return ((u32) fd & ldp->sid_bit_val) ? 1 : 0;
+ return fd >= ldp->sid_bit_val;
}
static inline u32
ldp_sid_from_fd (int fd)
{
- return (ldp_fd_is_sid (fd) ? ((u32) fd & ldp->sid_bit_mask) :
- INVALID_SESSION_ID);
+ ldp_fd_entry_t *fde;
+ u32 fd_index, sid;
+
+ if (!ldp_fd_is_sid (fd))
+ return INVALID_SESSION_ID;
+
+ fd_index = fd - ldp->sid_bit_val;
+ fde = ldp_fd_entry_get_w_lock (fd_index);
+ sid = fde ? fde->sid : INVALID_SESSION_ID;
+ clib_rwlock_reader_unlock (&ldp->fd_table_lock);
+
+ /* Handle forks */
+ sid = vppcom_session_handle (vppcom_session_index (sid));
+ return sid;
+}
+
+static void
+ldp_fd_free_w_sid (u32 sid)
+{
+ ldp_fd_entry_t *fde;
+ u32 fd_index;
+ int fd;
+
+ fd = ldp_fd_from_sid (sid);
+ if (!fd)
+ return;
+
+ fd_index = fd - ldp->sid_bit_val;
+ fde = ldp_fd_entry_get_w_lock (fd_index);
+ if (fde)
+ {
+ hash_unset (ldp->sid_to_fd_table, fde->sid);
+ pool_put (ldp->fd_pool, fde);
+ }
+ clib_rwlock_writer_unlock (&ldp->fd_table_lock);
}
static inline int
@@ -222,6 +302,7 @@ ldp_init (void)
}
clib_time_init (&ldp->clib_time);
+ clib_rwlock_init (&ldp->fd_table_lock);
LDBG (0, "LDP<%d>: LDP initialization: done!", getpid ());
return 0;
@@ -272,6 +353,7 @@ close (int fd)
LDBG (0, "LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x)",
getpid (), fd, fd, func_str, sid, sid);
+ ldp_fd_free_w_sid (sid);
rv = vppcom_session_close (sid);
if (rv != VPPCOM_OK)
{
@@ -776,13 +858,11 @@ ldp_pselect (int nfds, fd_set * __restrict readfds,
const struct timespec *__restrict timeout,
const __sigset_t * __restrict sigmask)
{
- int rv;
+ uword sid_bits, sid_bits_set, libc_bits, libc_bits_set;
+ u32 minbits = clib_max (nfds, BITS (uword)), sid;
char *func_str = "##";
f64 time_out;
- int fd;
- uword sid_bits, sid_bits_set, libc_bits, libc_bits_set;
- u32 minbits = clib_max (nfds, BITS (uword));
- u32 sid;
+ int rv, fd;
if (nfds < 0)
{
@@ -860,7 +940,8 @@ ldp_pselect (int nfds, fd_set * __restrict readfds,
if (sid == INVALID_SESSION_ID)
clib_bitmap_set_no_check (ldp->libc_rd_bitmap, fd, 1);
else
- clib_bitmap_set_no_check (ldp->sid_rd_bitmap, sid, 1);
+ clib_bitmap_set_no_check (ldp->sid_rd_bitmap,
+ vppcom_session_index (sid), 1);
}));
/* *INDENT-ON* */
@@ -892,7 +973,8 @@ ldp_pselect (int nfds, fd_set * __restrict readfds,
if (sid == INVALID_SESSION_ID)
clib_bitmap_set_no_check (ldp->libc_wr_bitmap, fd, 1);
else
- clib_bitmap_set_no_check (ldp->sid_wr_bitmap, sid, 1);
+ clib_bitmap_set_no_check (ldp->sid_wr_bitmap,
+ vppcom_session_index (sid), 1);
}));
/* *INDENT-ON* */
@@ -924,7 +1006,8 @@ ldp_pselect (int nfds, fd_set * __restrict readfds,
if (sid == INVALID_SESSION_ID)
clib_bitmap_set_no_check (ldp->libc_ex_bitmap, fd, 1);
else
- clib_bitmap_set_no_check (ldp->sid_ex_bitmap, sid, 1);
+ clib_bitmap_set_no_check (ldp->sid_ex_bitmap,
+ vppcom_session_index (sid), 1);
}));
/* *INDENT-ON* */
@@ -983,7 +1066,7 @@ ldp_pselect (int nfds, fd_set * __restrict readfds,
/* *INDENT-OFF* */
clib_bitmap_foreach (sid, ldp->rd_bitmap,
({
- fd = ldp_fd_from_sid (sid);
+ fd = ldp_fd_from_sid (vppcom_session_handle (sid));
if (PREDICT_FALSE (fd < 0))
{
errno = EBADFD;
@@ -999,7 +1082,7 @@ ldp_pselect (int nfds, fd_set * __restrict readfds,
/* *INDENT-OFF* */
clib_bitmap_foreach (sid, ldp->wr_bitmap,
({
- fd = ldp_fd_from_sid (sid);
+ fd = ldp_fd_from_sid (vppcom_session_handle (sid));
if (PREDICT_FALSE (fd < 0))
{
errno = EBADFD;
@@ -1015,7 +1098,7 @@ ldp_pselect (int nfds, fd_set * __restrict readfds,
/* *INDENT-OFF* */
clib_bitmap_foreach (sid, ldp->ex_bitmap,
({
- fd = ldp_fd_from_sid (sid);
+ fd = ldp_fd_from_sid (vppcom_session_handle (sid));
if (PREDICT_FALSE (fd < 0))
{
errno = EBADFD;
@@ -1153,7 +1236,7 @@ socket (int domain, int type, int protocol)
else
{
func_str = "ldp_fd_from_sid";
- rv = ldp_fd_from_sid (sid);
+ rv = ldp_fd_alloc (sid);
if (rv < 0)
{
(void) vppcom_session_close (sid);
@@ -2838,7 +2921,7 @@ ldp_accept4 (int listen_fd, __SOCKADDR_ARG addr,
"accept sid %u (0x%x), ep %p, flags 0x%x",
getpid (), listen_fd, listen_fd,
func_str, accept_sid, accept_sid, ep, flags);
- rv = ldp_fd_from_sid ((u32) accept_sid);
+ rv = ldp_fd_alloc ((u32) accept_sid);
if (rv < 0)
{
(void) vppcom_session_close ((u32) accept_sid);
@@ -2965,7 +3048,7 @@ epoll_create1 (int flags)
rv = -1;
}
else
- rv = ldp_fd_from_sid ((u32) rv);
+ rv = ldp_fd_alloc ((u32) rv);
if (LDP_DEBUG > 1)
{
diff --git a/src/vcl/vppcom.c b/src/vcl/vppcom.c
index f20167226e8..b397058052c 100644
--- a/src/vcl/vppcom.c
+++ b/src/vcl/vppcom.c
@@ -3353,6 +3353,12 @@ vppcom_session_index (uint32_t session_handle)
}
int
+vppcom_session_handle (uint32_t session_index)
+{
+ return vcl_get_worker_index () << 24 | session_index;
+}
+
+int
vppcom_worker_register (void)
{
if (vcl_worker_alloc_and_init ())
diff --git a/src/vcl/vppcom.h b/src/vcl/vppcom.h
index 5f1992502ce..5085e950af4 100644
--- a/src/vcl/vppcom.h
+++ b/src/vcl/vppcom.h
@@ -262,6 +262,7 @@ extern int vppcom_poll (vcl_poll_t * vp, uint32_t n_sids,
double wait_for_time);
extern int vppcom_mq_epoll_fd (void);
extern int vppcom_session_index (uint32_t session_handle);
+extern int vppcom_session_handle (uint32_t session_index);
extern int vppcom_session_read_segments (uint32_t session_handle,
vppcom_data_segments_t ds);