diff options
author | Florin Coras <fcoras@cisco.com> | 2018-08-02 10:45:44 -0700 |
---|---|---|
committer | Dave Barach <openvpp@barachs.net> | 2018-08-10 20:26:24 +0000 |
commit | 993683150202254c6ba8dd43e087a7229edd5d4c (patch) | |
tree | 141ce2cdfe546bfe2ad46e66ac9569a33a895072 /src/vcl/ldp.c | |
parent | f46663c65b0238311af93fcfa3030eefdb56e299 (diff) |
vcl: support for eventfd mq signaling
- support eventfd based mq signaling. Based on configuration, vcl
epoll/select can use either condvars or epoll on mq eventfds.
- add vcl support for memfd segments
- vpp explicitly registers cut-through segments with apps/vcl
- if using eventfd, make ldp allow one call to libc_epoll_create. Needed
for the message queue epfd
- update svm_queue_t to allow blocking calls with eventfd signaling.
Change-Id: I064151ac370bbe29bb16c968bf4e3659c8286bea
Signed-off-by: Florin Coras <fcoras@cisco.com>
Diffstat (limited to 'src/vcl/ldp.c')
-rw-r--r-- | src/vcl/ldp.c | 418 |
1 files changed, 197 insertions, 221 deletions
diff --git a/src/vcl/ldp.c b/src/vcl/ldp.c index c26c460bec8..b7b6b3c26b1 100644 --- a/src/vcl/ldp.c +++ b/src/vcl/ldp.c @@ -67,9 +67,17 @@ typedef struct vcl_poll_t *vcl_poll; u8 select_vcl; u8 epoll_wait_vcl; + u8 vcl_needs_real_epoll; /*< vcl needs next epoll_create to + go to libc_epoll */ + int vcl_mq_epfd; + } ldp_main_t; #define LDP_DEBUG ldp->debug +#define LDBG(_lvl, _fmt, _args...) \ + if (ldp->debug > _lvl) \ + clib_warning (_fmt, ##_args) + static ldp_main_t ldp_main = { .sid_bit_val = (1 << LDP_SID_BIT_MIN), .sid_bit_mask = (1 << LDP_SID_BIT_MIN) - 1, @@ -125,107 +133,96 @@ ldp_sid_from_fd (int fd) static inline int ldp_init (void) { - int rv = 0; + int rv; + + if (PREDICT_TRUE (ldp->init)) + return 0; + + ldp->init = 1; + ldp->vcl_needs_real_epoll = 1; + rv = vppcom_app_create (ldp_get_app_name ()); + if (rv != VPPCOM_OK) + { + fprintf (stderr, "\nLDP<%d>: ERROR: ldp_init: vppcom_app_create()" + " failed! rv = %d (%s)\n", + getpid (), rv, vppcom_retval_str (rv)); + ldp->init = 0; + return rv; + } + ldp->vcl_needs_real_epoll = 0; - if (PREDICT_FALSE (!ldp->init)) + char *env_var_str = getenv (LDP_ENV_DEBUG); + if (env_var_str) { - ldp->init = 1; - rv = vppcom_app_create (ldp_get_app_name ()); - if (rv == VPPCOM_OK) + u32 tmp; + if (sscanf (env_var_str, "%u", &tmp) != 1) + clib_warning ("LDP<%d>: WARNING: Invalid LDP debug level specified in" + " the env var " LDP_ENV_DEBUG " (%s)!", getpid (), + env_var_str); + else { - char *env_var_str = getenv (LDP_ENV_DEBUG); - if (env_var_str) - { - u32 tmp; - if (sscanf (env_var_str, "%u", &tmp) != 1) - clib_warning ("LDP<%d>: WARNING: Invalid LDP debug level " - "specified in the env var " LDP_ENV_DEBUG - " (%s)!", getpid (), env_var_str); - else - { - ldp->debug = tmp; - if (LDP_DEBUG > 0) - clib_warning ("LDP<%d>: configured LDP debug level (%u) " - "from the env var " LDP_ENV_DEBUG "!", - getpid (), ldp->debug); - } - } + ldp->debug = tmp; + LDBG (0, "LDP<%d>: configured LDP debug level (%u) from env var " + LDP_ENV_DEBUG "!", getpid (), ldp->debug); + } + } - env_var_str = getenv (LDP_ENV_APP_NAME); - if (env_var_str) - { - ldp_set_app_name (env_var_str); - if (LDP_DEBUG > 0) - clib_warning ("LDP<%d>: configured LDP app name (%s) " - "from the env var " LDP_ENV_APP_NAME "!", - getpid (), ldp->app_name); - } + env_var_str = getenv (LDP_ENV_APP_NAME); + if (env_var_str) + { + ldp_set_app_name (env_var_str); + LDBG (0, "LDP<%d>: configured LDP app name (%s) from the env var " + LDP_ENV_APP_NAME "!", getpid (), ldp->app_name); + } - env_var_str = getenv (LDP_ENV_SID_BIT); - if (env_var_str) - { - u32 sb; - if (sscanf (env_var_str, "%u", &sb) != 1) - { - clib_warning ("LDP<%d>: WARNING: Invalid LDP sid bit " - "specified in the env var " - LDP_ENV_SID_BIT " (%s)!" - "sid bit value %d (0x%x)", - getpid (), env_var_str, - ldp->sid_bit_val, ldp->sid_bit_val); - } - else if (sb < LDP_SID_BIT_MIN) - { - ldp->sid_bit_val = (1 << LDP_SID_BIT_MIN); - ldp->sid_bit_mask = ldp->sid_bit_val - 1; - - clib_warning ("LDP<%d>: WARNING: LDP sid bit (%u) " - "specified in the env var " - LDP_ENV_SID_BIT " (%s) is too small. " - "Using LDP_SID_BIT_MIN (%d)! " - "sid bit value %d (0x%x)", - getpid (), sb, env_var_str, LDP_SID_BIT_MIN, - ldp->sid_bit_val, ldp->sid_bit_val); - } - else if (sb > LDP_SID_BIT_MAX) - { - ldp->sid_bit_val = (1 << LDP_SID_BIT_MAX); - ldp->sid_bit_mask = ldp->sid_bit_val - 1; - - clib_warning ("LDP<%d>: WARNING: LDP sid bit (%u) " - "specified in the env var " - LDP_ENV_SID_BIT " (%s) is too big. " - "Using LDP_SID_BIT_MAX (%d)! " - "sid bit value %d (0x%x)", - getpid (), sb, env_var_str, LDP_SID_BIT_MAX, - ldp->sid_bit_val, ldp->sid_bit_val); - } - else - { - ldp->sid_bit_val = (1 << sb); - ldp->sid_bit_mask = ldp->sid_bit_val - 1; - - if (LDP_DEBUG > 0) - clib_warning ("LDP<%d>: configured LDP sid bit (%u) " - "from " LDP_ENV_SID_BIT - "! sid bit value %d (0x%x)", getpid (), - sb, ldp->sid_bit_val, ldp->sid_bit_val); - } - } + env_var_str = getenv (LDP_ENV_SID_BIT); + if (env_var_str) + { + u32 sb; + if (sscanf (env_var_str, "%u", &sb) != 1) + { + clib_warning ("LDP<%d>: WARNING: Invalid LDP sid bit specified in" + " the env var " LDP_ENV_SID_BIT " (%s)! sid bit " + "value %d (0x%x)", getpid (), env_var_str, + ldp->sid_bit_val, ldp->sid_bit_val); + } + else if (sb < LDP_SID_BIT_MIN) + { + ldp->sid_bit_val = (1 << LDP_SID_BIT_MIN); + ldp->sid_bit_mask = ldp->sid_bit_val - 1; - clib_time_init (&ldp->clib_time); - if (LDP_DEBUG > 0) - clib_warning ("LDP<%d>: LDP initialization: done!", getpid ()); + clib_warning ("LDP<%d>: WARNING: LDP sid bit (%u) specified in the" + " env var " LDP_ENV_SID_BIT " (%s) is too small. " + "Using LDP_SID_BIT_MIN (%d)! sid bit value %d (0x%x)", + getpid (), sb, env_var_str, LDP_SID_BIT_MIN, + ldp->sid_bit_val, ldp->sid_bit_val); + } + else if (sb > LDP_SID_BIT_MAX) + { + ldp->sid_bit_val = (1 << LDP_SID_BIT_MAX); + ldp->sid_bit_mask = ldp->sid_bit_val - 1; + + clib_warning ("LDP<%d>: WARNING: LDP sid bit (%u) specified in the" + " env var " LDP_ENV_SID_BIT " (%s) is too big. Using" + " LDP_SID_BIT_MAX (%d)! sid bit value %d (0x%x)", + getpid (), sb, env_var_str, LDP_SID_BIT_MAX, + ldp->sid_bit_val, ldp->sid_bit_val); } else { - fprintf (stderr, "\nLDP<%d>: ERROR: ldp_init: vppcom_app_create()" - " failed! rv = %d (%s)\n", - getpid (), rv, vppcom_retval_str (rv)); - ldp->init = 0; + ldp->sid_bit_val = (1 << sb); + ldp->sid_bit_mask = ldp->sid_bit_val - 1; + + LDBG (0, "LDP<%d>: configured LDP sid bit (%u) from " + LDP_ENV_SID_BIT "! sid bit value %d (0x%x)", getpid (), sb, + ldp->sid_bit_val, ldp->sid_bit_val); } } - return rv; + + clib_time_init (&ldp->clib_time); + LDBG (0, "LDP<%d>: LDP initialization: done!", getpid ()); + + return 0; } int @@ -1151,11 +1148,9 @@ socket (int domain, int type, int protocol) func_str = "vppcom_session_create"; - if (LDP_DEBUG > 0) - clib_warning ("LDP<%d>: : calling %s(): " - "proto %u (%s), is_nonblocking %u", - getpid (), func_str, proto, - vppcom_proto_str (proto), is_nonblocking); + LDBG (0, "LDP<%d>: : calling %s(): proto %u (%s), is_nonblocking %u", + getpid (), func_str, proto, vppcom_proto_str (proto), + is_nonblocking); sid = vppcom_session_create (proto, is_nonblocking); if (sid < 0) @@ -1179,8 +1174,7 @@ socket (int domain, int type, int protocol) { func_str = "libc_socket"; - if (LDP_DEBUG > 0) - clib_warning ("LDP<%d>: : calling %s()", getpid (), func_str); + LDBG (0, "LDP<%d>: : calling %s()", getpid (), func_str); rv = libc_socket (domain, type, protocol); } @@ -2765,10 +2759,8 @@ listen (int fd, int n) { func_str = "vppcom_session_listen"; - if (LDP_DEBUG > 0) - clib_warning - ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), n %d", - getpid (), fd, fd, func_str, sid, sid, n); + LDBG (0, "LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), n %d", + getpid (), fd, fd, func_str, sid, sid, n); rv = vppcom_session_listen (sid, n); if (rv != VPPCOM_OK) @@ -2781,9 +2773,8 @@ listen (int fd, int n) { func_str = "libc_listen"; - if (LDP_DEBUG > 0) - clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): n %d", - getpid (), fd, fd, func_str, n); + LDBG (0, "LDP<%d>: fd %d (0x%x): calling %s(): n %d", getpid (), fd, + fd, func_str, n); rv = libc_listen (fd, n); } @@ -2966,10 +2957,17 @@ epoll_create1 (int flags) if ((errno = -ldp_init ())) return -1; + if (ldp->vcl_needs_real_epoll) + { + rv = libc_epoll_create1 (flags); + ldp->vcl_needs_real_epoll = 0; + ldp->vcl_mq_epfd = rv; + LDBG (0, "LDP<%d>: created vcl epfd %u", getpid (), rv); + return rv; + } func_str = "vppcom_epoll_create"; - if (LDP_DEBUG > 1) - clib_warning ("LDP<%d>: calling %s()", getpid (), func_str); + LDBG (1, "LDP<%d>: calling %s()", getpid (), func_str); rv = vppcom_epoll_create (); @@ -3007,121 +3005,105 @@ epoll_create (int size) int epoll_ctl (int epfd, int op, int fd, struct epoll_event *event) { - int rv; + u32 vep_idx = ldp_sid_from_fd (epfd), sid; const char *func_str; - u32 vep_idx = ldp_sid_from_fd (epfd); + int rv; if ((errno = -ldp_init ())) return -1; - if (PREDICT_TRUE (vep_idx != INVALID_SESSION_ID)) + if (PREDICT_FALSE (vep_idx == INVALID_SESSION_ID)) { - u32 sid = ldp_sid_from_fd (fd); + /* The LDP epoll_create1 always creates VCL epfd's. + * The app should never have a kernel base epoll fd unless it + * was acquired outside of the LD_PRELOAD process context. + * In any case, if we get one, punt it to libc_epoll_ctl. + */ + func_str = "libc_epoll_ctl"; - if (LDP_DEBUG > 1) - clib_warning ("LDP<%d>: epfd %d (0x%x), vep_idx %d (0x%x), " - "sid %d (0x%x)", getpid (), epfd, epfd, - vep_idx, vep_idx, sid, sid); + LDBG (1, "LDP<%d>: epfd %d (0x%x): calling %s(): op %d, fd %d (0x%x)," + " event %p", getpid (), epfd, epfd, func_str, op, fd, fd, event); - if (sid != INVALID_SESSION_ID) - { - func_str = "vppcom_epoll_ctl"; + rv = libc_epoll_ctl (epfd, op, fd, event); + goto done; + } - if (LDP_DEBUG > 1) - clib_warning ("LDP<%d>: epfd %d (0x%x): calling %s(): " - "vep_idx %d (0x%x), op %d, sid %u (0x%x), event %p", - getpid (), epfd, epfd, func_str, vep_idx, vep_idx, - sid, sid, event); + sid = ldp_sid_from_fd (fd); - rv = vppcom_epoll_ctl (vep_idx, op, sid, event); - if (rv != VPPCOM_OK) - { - errno = -rv; - rv = -1; - } + LDBG (0, "LDP<%d>: epfd %d (0x%x), vep_idx %d (0x%x), sid %d (0x%x)", + getpid (), epfd, epfd, vep_idx, vep_idx, sid, sid); + + if (sid != INVALID_SESSION_ID) + { + func_str = "vppcom_epoll_ctl"; + + LDBG (1, "LDP<%d>: epfd %d (0x%x): calling %s(): vep_idx %d (0x%x)," + " op %d, sid %u (0x%x), event %p", getpid (), epfd, epfd, + func_str, vep_idx, vep_idx, sid, sid, event); + + rv = vppcom_epoll_ctl (vep_idx, op, sid, event); + if (rv != VPPCOM_OK) + { + errno = -rv; + rv = -1; } - else + } + else + { + int libc_epfd; + u32 size = sizeof (epfd); + + func_str = "vppcom_session_attr[GET_LIBC_EPFD]"; + libc_epfd = vppcom_session_attr (vep_idx, VPPCOM_ATTR_GET_LIBC_EPFD, 0, + 0); + LDBG (1, "LDP<%d>: epfd %d (0x%x), vep_idx %d (0x%x): %s() " + "returned libc_epfd %d (0x%x)", getpid (), epfd, epfd, + vep_idx, vep_idx, func_str, libc_epfd, libc_epfd); + + if (!libc_epfd) { - int libc_epfd; - u32 size = sizeof (epfd); + func_str = "libc_epoll_create1"; - func_str = "vppcom_session_attr[GET_LIBC_EPFD]"; - libc_epfd = vppcom_session_attr (vep_idx, - VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0); - if (LDP_DEBUG > 1) - clib_warning ("LDP<%d>: epfd %d (0x%x), vep_idx %d (0x%x): " - "%s() returned libc_epfd %d (0x%x)", - getpid (), epfd, epfd, vep_idx, vep_idx, - func_str, libc_epfd, libc_epfd); + LDBG (1, "LDP<%d>: epfd %d (0x%x), vep_idx %d (0x%x): " + "calling %s(): EPOLL_CLOEXEC", getpid (), epfd, epfd, + vep_idx, vep_idx, func_str); - if (!libc_epfd) + libc_epfd = libc_epoll_create1 (EPOLL_CLOEXEC); + if (libc_epfd < 0) { - func_str = "libc_epoll_create1"; - - if (LDP_DEBUG > 1) - clib_warning ("LDP<%d>: epfd %d (0x%x), vep_idx %d (0x%x): " - "calling %s(): EPOLL_CLOEXEC", - getpid (), epfd, epfd, vep_idx, vep_idx, - func_str); + rv = libc_epfd; + goto done; + } - libc_epfd = libc_epoll_create1 (EPOLL_CLOEXEC); - if (libc_epfd < 0) - { - rv = libc_epfd; - goto done; - } + func_str = "vppcom_session_attr[SET_LIBC_EPFD]"; + LDBG (1, "LDP<%d>: epfd %d (0x%x): calling %s(): vep_idx %d (0x%x)," + " VPPCOM_ATTR_SET_LIBC_EPFD, libc_epfd %d (0x%x), size %d", + getpid (), epfd, epfd, func_str, vep_idx, vep_idx, libc_epfd, + libc_epfd, size); - func_str = "vppcom_session_attr[SET_LIBC_EPFD]"; - if (LDP_DEBUG > 1) - clib_warning ("LDP<%d>: epfd %d (0x%x): calling %s(): " - "vep_idx %d (0x%x), VPPCOM_ATTR_SET_LIBC_EPFD, " - "libc_epfd %d (0x%x), size %d", - getpid (), epfd, epfd, func_str, - vep_idx, vep_idx, libc_epfd, libc_epfd, size); - - rv = vppcom_session_attr (vep_idx, VPPCOM_ATTR_SET_LIBC_EPFD, - &libc_epfd, &size); - if (rv < 0) - { - errno = -rv; - rv = -1; - goto done; - } - } - else if (PREDICT_FALSE (libc_epfd < 0)) + rv = vppcom_session_attr (vep_idx, VPPCOM_ATTR_SET_LIBC_EPFD, + &libc_epfd, &size); + if (rv < 0) { - errno = -epfd; + errno = -rv; rv = -1; goto done; } - - func_str = "libc_epoll_ctl"; - - if (LDP_DEBUG > 1) - clib_warning ("LDP<%d>: epfd %d (0x%x): calling %s(): " - "libc_epfd %d (0x%x), op %d, " - "fd %d (0x%x), event %p", - getpid (), epfd, epfd, func_str, - libc_epfd, libc_epfd, op, fd, fd, event); - - rv = libc_epoll_ctl (libc_epfd, op, fd, event); } - } - else - { - /* The LDP epoll_create1 always creates VCL epfd's. - * The app should never have a kernel base epoll fd unless it - * was acquired outside of the LD_PRELOAD process context. - * In any case, if we get one, punt it to libc_epoll_ctl. - */ + else if (PREDICT_FALSE (libc_epfd < 0)) + { + errno = -epfd; + rv = -1; + goto done; + } + func_str = "libc_epoll_ctl"; - if (LDP_DEBUG > 1) - clib_warning ("LDP<%d>: epfd %d (0x%x): calling %s(): " - "op %d, fd %d (0x%x), event %p", - getpid (), epfd, epfd, func_str, op, fd, fd, event); + LDBG (1, "LDP<%d>: epfd %d (0x%x): calling %s(): libc_epfd %d (0x%x), " + "op %d, fd %d (0x%x), event %p", getpid (), epfd, epfd, func_str, + libc_epfd, libc_epfd, op, fd, fd, event); - rv = libc_epoll_ctl (epfd, op, fd, event); + rv = libc_epoll_ctl (libc_epfd, op, fd, event); } done: @@ -3144,15 +3126,13 @@ done: } static inline int -ldp_epoll_pwait (int epfd, struct epoll_event *events, - int maxevents, int timeout, const sigset_t * sigmask) +ldp_epoll_pwait (int epfd, struct epoll_event *events, int maxevents, + int timeout, const sigset_t * sigmask) { - const char *func_str; - int rv = 0; - double time_to_wait = (double) 0; - double time_out, now = 0; + double time_to_wait = (double) 0, time_out, now = 0; u32 vep_idx = ldp_sid_from_fd (epfd); - int libc_epfd; + int libc_epfd, rv = 0; + const char *func_str; if ((errno = -ldp_init ())) return -1; @@ -3163,6 +3143,9 @@ ldp_epoll_pwait (int epfd, struct epoll_event *events, return -1; } + if (epfd == ldp->vcl_mq_epfd) + return libc_epoll_pwait (epfd, events, maxevents, timeout, sigmask); + if (PREDICT_FALSE (vep_idx == INVALID_SESSION_ID)) { clib_warning ("LDP<%d>: ERROR: epfd %d (0x%x): bad vep_idx %d (0x%x)!", @@ -3183,24 +3166,19 @@ ldp_epoll_pwait (int epfd, struct epoll_event *events, goto done; } - if (LDP_DEBUG > 2) - clib_warning ("LDP<%d>: epfd %d (0x%x): vep_idx %d (0x%x), " - "libc_epfd %d (0x%x), events %p, maxevents %d, " - "timeout %d, sigmask %p: time_to_wait %.02f", - getpid (), epfd, epfd, vep_idx, vep_idx, - libc_epfd, libc_epfd, events, maxevents, timeout, - sigmask, time_to_wait, time_out); + LDBG (2, "LDP<%d>: epfd %d (0x%x): vep_idx %d (0x%x), libc_epfd %d (0x%x), " + "events %p, maxevents %d, timeout %d, sigmask %p: time_to_wait %.02f", + getpid (), epfd, epfd, vep_idx, vep_idx, libc_epfd, libc_epfd, events, + maxevents, timeout, sigmask, time_to_wait, time_out); do { if (!ldp->epoll_wait_vcl) { func_str = "vppcom_epoll_wait"; - if (LDP_DEBUG > 3) - clib_warning ("LDP<%d>: epfd %d (0x%x): calling %s(): " - "vep_idx %d (0x%x), events %p, maxevents %d", - getpid (), epfd, epfd, func_str, - vep_idx, vep_idx, events, maxevents); + LDBG (3, "LDP<%d>: epfd %d (0x%x): calling %s(): vep_idx %d (0x%x)," + " events %p, maxevents %d", getpid (), epfd, epfd, func_str, + vep_idx, vep_idx, events, maxevents); rv = vppcom_epoll_wait (vep_idx, events, maxevents, 0); if (rv > 0) @@ -3222,12 +3200,10 @@ ldp_epoll_pwait (int epfd, struct epoll_event *events, { func_str = "libc_epoll_pwait"; - if (LDP_DEBUG > 3) - clib_warning ("LDP<%d>: epfd %d (0x%x): calling %s(): " - "libc_epfd %d (0x%x), events %p, " - "maxevents %d, sigmask %p", - getpid (), epfd, epfd, func_str, - libc_epfd, libc_epfd, events, maxevents, sigmask); + LDBG (3, "LDP<%d>: epfd %d (0x%x): calling %s(): libc_epfd %d " + "(0x%x), events %p, maxevents %d, sigmask %p", getpid (), + epfd, epfd, func_str, libc_epfd, libc_epfd, events, + maxevents, sigmask); rv = libc_epoll_pwait (libc_epfd, events, maxevents, 1, sigmask); if (rv != 0) |