summaryrefslogtreecommitdiffstats
path: root/src/vcl
diff options
context:
space:
mode:
authorliuyacan <liuyacan@corp.netease.com>2021-05-09 03:50:40 +0000
committerFlorin Coras <florin.coras@gmail.com>2021-05-12 04:45:07 +0000
commit534468e9f768ae7465ef722520dadfd916cdc9fb (patch)
tree7433d66e807340a2b5e0abbe152b6b944f32675d /src/vcl
parent7b2917fbe2a9ec17f69ca94fcbae534927915834 (diff)
session: support half-close connection
Some app(e.g. Envoy) may call shutdown() instead of close() when draining connection. Type: improvement Signed-off-by: liuyacan <liuyacan@corp.netease.com> Change-Id: I9543b9ca3caa87b10b134fd1fc4019124e41e4d2
Diffstat (limited to 'src/vcl')
-rw-r--r--src/vcl/ldp.c2
-rw-r--r--src/vcl/vcl_locked.c18
-rw-r--r--src/vcl/vcl_locked.h1
-rw-r--r--src/vcl/vcl_private.h1
-rw-r--r--src/vcl/vppcom.c56
-rw-r--r--src/vcl/vppcom.h1
6 files changed, 78 insertions, 1 deletions
diff --git a/src/vcl/ldp.c b/src/vcl/ldp.c
index 64a4e7c77db..f27f6ba8e97 100644
--- a/src/vcl/ldp.c
+++ b/src/vcl/ldp.c
@@ -2219,6 +2219,8 @@ shutdown (int fd, int how)
if (flags == SHUT_RDWR)
rv = close (fd);
+ else if (flags == SHUT_WR)
+ rv = vls_shutdown (vlsh);
}
else
{
diff --git a/src/vcl/vcl_locked.c b/src/vcl/vcl_locked.c
index 757c0fc45a7..69f492b8694 100644
--- a/src/vcl/vcl_locked.c
+++ b/src/vcl/vcl_locked.c
@@ -1313,6 +1313,24 @@ vls_close (vls_handle_t vlsh)
return rv;
}
+int
+vls_shutdown (vls_handle_t vlsh)
+{
+ vcl_locked_session_t *vls;
+ int rv;
+
+ vls_mt_detect ();
+ if (!(vls = vls_get_w_dlock (vlsh)))
+ return VPPCOM_EBADFD;
+
+ vls_mt_guard (vls, VLS_MT_OP_SPOOL);
+ rv = vppcom_session_shutdown (vls_to_sh (vls));
+ vls_mt_unguard ();
+ vls_get_and_unlock (vlsh);
+
+ return rv;
+}
+
vls_handle_t
vls_epoll_create (void)
{
diff --git a/src/vcl/vcl_locked.h b/src/vcl/vcl_locked.h
index 11b71eee4af..3adcf62bc77 100644
--- a/src/vcl/vcl_locked.h
+++ b/src/vcl/vcl_locked.h
@@ -26,6 +26,7 @@
typedef int vls_handle_t;
vls_handle_t vls_create (uint8_t proto, uint8_t is_nonblocking);
+int vls_shutdown (vls_handle_t vlsh);
int vls_close (vls_handle_t vlsh);
int vls_bind (vls_handle_t vlsh, vppcom_endpt_t * ep);
int vls_listen (vls_handle_t vlsh, int q_len);
diff --git a/src/vcl/vcl_private.h b/src/vcl/vcl_private.h
index 6060ef82357..956f077b880 100644
--- a/src/vcl/vcl_private.h
+++ b/src/vcl/vcl_private.h
@@ -137,6 +137,7 @@ typedef enum vcl_session_flags_
VCL_SESSION_F_IS_VEP = 1 << 1,
VCL_SESSION_F_IS_VEP_SESSION = 1 << 2,
VCL_SESSION_F_HAS_RX_EVT = 1 << 3,
+ VCL_SESSION_F_SHUTDOWN = 1 << 4,
} __clib_packed vcl_session_flags_t;
typedef struct vcl_session_
diff --git a/src/vcl/vppcom.c b/src/vcl/vppcom.c
index 96a207b741f..0713a7b2d33 100644
--- a/src/vcl/vppcom.c
+++ b/src/vcl/vppcom.c
@@ -260,6 +260,23 @@ vcl_send_session_unlisten (vcl_worker_t * wrk, vcl_session_t * s)
}
static void
+vcl_send_session_shutdown (vcl_worker_t *wrk, vcl_session_t *s)
+{
+ app_session_evt_t _app_evt, *app_evt = &_app_evt;
+ session_shutdown_msg_t *mp;
+ svm_msg_q_t *mq;
+
+ /* Send to thread that owns the session */
+ mq = s->vpp_evt_q;
+ app_alloc_ctrl_evt_to_vpp (mq, app_evt, SESSION_CTRL_EVT_SHUTDOWN);
+ mp = (session_shutdown_msg_t *) app_evt->evt->data;
+ memset (mp, 0, sizeof (*mp));
+ mp->client_index = wrk->api_client_handle;
+ mp->handle = s->vpp_handle;
+ app_send_ctrl_evt_to_vpp (mq, app_evt);
+}
+
+static void
vcl_send_session_disconnect (vcl_worker_t * wrk, vcl_session_t * s)
{
app_session_evt_t _app_evt, *app_evt = &_app_evt;
@@ -789,6 +806,42 @@ vcl_session_disconnected_handler (vcl_worker_t * wrk,
return session;
}
+int
+vppcom_session_shutdown (uint32_t session_handle)
+{
+ vcl_worker_t *wrk = vcl_worker_get_current ();
+ vcl_session_t *session;
+ vcl_session_state_t state;
+ u64 vpp_handle;
+
+ session = vcl_session_get_w_handle (wrk, session_handle);
+ if (PREDICT_FALSE (!session))
+ return VPPCOM_EBADFD;
+
+ vpp_handle = session->vpp_handle;
+ state = session->session_state;
+
+ VDBG (1, "session %u [0x%llx] state 0x%x (%s)", session->session_index,
+ vpp_handle, state, vppcom_session_state_str (state));
+
+ if (PREDICT_FALSE (state == VCL_STATE_LISTEN))
+ {
+ VDBG (0, "ERROR: Cannot shutdown a listen socket!");
+ return VPPCOM_EBADFD;
+ }
+
+ if (PREDICT_TRUE (state == VCL_STATE_READY))
+ {
+ VDBG (1, "session %u [0x%llx]: sending shutdown...",
+ session->session_index, vpp_handle);
+
+ vcl_send_session_shutdown (wrk, session);
+ session->flags |= VCL_SESSION_F_SHUTDOWN;
+ }
+
+ return VPPCOM_OK;
+}
+
static int
vppcom_session_disconnect (u32 session_handle)
{
@@ -2101,7 +2154,8 @@ vppcom_session_write_inline (vcl_worker_t * wrk, vcl_session_t * s, void *buf,
return VPPCOM_EBADFD;
}
- if (PREDICT_FALSE (!vcl_session_is_open (s)))
+ if (PREDICT_FALSE (!vcl_session_is_open (s) ||
+ s->flags & VCL_SESSION_F_SHUTDOWN))
{
VDBG (1, "session %u [0x%llx]: is not open! state 0x%x (%s)",
s->session_index, s->vpp_handle, s->session_state,
diff --git a/src/vcl/vppcom.h b/src/vcl/vppcom.h
index ae4888566c7..72e5d46bc8f 100644
--- a/src/vcl/vppcom.h
+++ b/src/vcl/vppcom.h
@@ -172,6 +172,7 @@ extern int vppcom_app_create (const char *app_name);
extern void vppcom_app_destroy (void);
extern int vppcom_session_create (uint8_t proto, uint8_t is_nonblocking);
+extern int vppcom_session_shutdown (uint32_t session_handle);
extern int vppcom_session_close (uint32_t session_handle);
extern int vppcom_session_bind (uint32_t session_handle, vppcom_endpt_t * ep);
extern int vppcom_session_listen (uint32_t session_handle, uint32_t q_len);