vcl: improve shutdown()
This commit does following:
- Change the behavior of shutdown() with SHUT_RDWR flag.
- Check SHUT_RD flag when read()
- Change the errno when write() after SHUT_WR
- Remove unused code
All the above modification passed the packetdrill test.
Type: improvement
Signed-off-by: liuyacan <liuyacan@corp.netease.com>
Change-Id: I0c81f52e563562e58580d70976526b898e65e915
diff --git a/src/vcl/ldp.c b/src/vcl/ldp.c
index b51d2e0..54a8f66 100644
--- a/src/vcl/ldp.c
+++ b/src/vcl/ldp.c
@@ -2175,8 +2175,7 @@
shutdown (int fd, int how)
{
vls_handle_t vlsh;
- int rv = 0, flags;
- u32 flags_len = sizeof (flags);
+ int rv = 0;
ldp_init_check ();
@@ -2184,23 +2183,7 @@
if (vlsh != VLS_INVALID_HANDLE)
{
LDBG (0, "called shutdown: fd %u vlsh %u how %d", fd, vlsh, how);
-
- if (vls_attr (vlsh, VPPCOM_ATTR_SET_SHUT, &how, &flags_len))
- {
- close (fd);
- return -1;
- }
-
- if (vls_attr (vlsh, VPPCOM_ATTR_GET_SHUT, &flags, &flags_len))
- {
- close (fd);
- return -1;
- }
-
- if (flags == SHUT_RDWR)
- rv = close (fd);
- else if (flags == SHUT_WR)
- rv = vls_shutdown (vlsh);
+ rv = vls_shutdown (vlsh, how);
}
else
{
diff --git a/src/vcl/vcl_locked.c b/src/vcl/vcl_locked.c
index 69f492b..ea22bcd 100644
--- a/src/vcl/vcl_locked.c
+++ b/src/vcl/vcl_locked.c
@@ -1314,7 +1314,7 @@
}
int
-vls_shutdown (vls_handle_t vlsh)
+vls_shutdown (vls_handle_t vlsh, int how)
{
vcl_locked_session_t *vls;
int rv;
@@ -1324,7 +1324,7 @@
return VPPCOM_EBADFD;
vls_mt_guard (vls, VLS_MT_OP_SPOOL);
- rv = vppcom_session_shutdown (vls_to_sh (vls));
+ rv = vppcom_session_shutdown (vls_to_sh (vls), how);
vls_mt_unguard ();
vls_get_and_unlock (vlsh);
diff --git a/src/vcl/vcl_locked.h b/src/vcl/vcl_locked.h
index 3adcf62..fa3a273 100644
--- a/src/vcl/vcl_locked.h
+++ b/src/vcl/vcl_locked.h
@@ -26,7 +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_shutdown (vls_handle_t vlsh, int how);
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 628b731..5b19f94 100644
--- a/src/vcl/vcl_private.h
+++ b/src/vcl/vcl_private.h
@@ -126,8 +126,6 @@
VCL_SESS_ATTR_TCP_NODELAY, // SOL_TCP,TCP_NODELAY
VCL_SESS_ATTR_TCP_KEEPIDLE, // SOL_TCP,TCP_KEEPIDLE
VCL_SESS_ATTR_TCP_KEEPINTVL, // SOL_TCP,TCP_KEEPINTVL
- VCL_SESS_ATTR_SHUT_RD,
- VCL_SESS_ATTR_SHUT_WR,
VCL_SESS_ATTR_MAX
} vppcom_session_attr_t;
@@ -137,7 +135,8 @@
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,
+ VCL_SESSION_F_RD_SHUTDOWN = 1 << 4,
+ VCL_SESSION_F_WR_SHUTDOWN = 1 << 5,
} __clib_packed vcl_session_flags_t;
typedef struct vcl_session_
diff --git a/src/vcl/vppcom.c b/src/vcl/vppcom.c
index 330d590..d378f40 100644
--- a/src/vcl/vppcom.c
+++ b/src/vcl/vppcom.c
@@ -807,7 +807,7 @@
}
int
-vppcom_session_shutdown (uint32_t session_handle)
+vppcom_session_shutdown (uint32_t session_handle, int how)
{
vcl_worker_t *wrk = vcl_worker_get_current ();
vcl_session_t *session;
@@ -830,13 +830,20 @@
return VPPCOM_EBADFD;
}
+ if (how == SHUT_RD || how == SHUT_RDWR)
+ {
+ session->flags |= VCL_SESSION_F_RD_SHUTDOWN;
+ if (how == SHUT_RD)
+ return VPPCOM_OK;
+ }
+ session->flags |= VCL_SESSION_F_WR_SHUTDOWN;
+
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;
@@ -1948,6 +1955,18 @@
return vcl_session_closed_error (s);
}
+ if (PREDICT_FALSE (s->flags & VCL_SESSION_F_RD_SHUTDOWN))
+ {
+ /* Vpp would ack the incoming data and enqueue it for reading.
+ * So even if SHUT_RD is set, we can still read() the data if
+ * the session is ready.
+ */
+ if (!vcl_session_read_ready (s))
+ {
+ return 0;
+ }
+ }
+
is_nonblocking = vcl_session_has_attr (s, VCL_SESS_ATTR_NONBLOCK);
is_ct = vcl_session_is_ct (s);
mq = wrk->app_event_queue;
@@ -2166,8 +2185,7 @@
return VPPCOM_EBADFD;
}
- if (PREDICT_FALSE (!vcl_session_is_open (s) ||
- (s->flags & VCL_SESSION_F_SHUTDOWN)))
+ if (PREDICT_FALSE (!vcl_session_is_open (s)))
{
VDBG (1, "session %u [0x%llx]: is not open! state 0x%x (%s)",
s->session_index, s->vpp_handle, s->session_state,
@@ -2175,6 +2193,14 @@
return vcl_session_closed_error (s);;
}
+ if (PREDICT_FALSE (s->flags & VCL_SESSION_F_WR_SHUTDOWN))
+ {
+ VDBG (1, "session %u [0x%llx]: is shutdown! state 0x%x (%s)",
+ s->session_index, s->vpp_handle, s->session_state,
+ vppcom_session_state_str (s->session_state));
+ return VPPCOM_EPIPE;
+ }
+
is_ct = vcl_session_is_ct (s);
tx_fifo = is_ct ? s->ct_tx_fifo : s->tx_fifo;
is_nonblocking = vcl_session_has_attr (s, VCL_SESS_ATTR_NONBLOCK);
@@ -3209,7 +3235,7 @@
void *buffer, uint32_t * buflen)
{
vcl_worker_t *wrk = vcl_worker_get_current ();
- u32 *flags = buffer, tmp_flags = 0;
+ u32 *flags = buffer;
vppcom_endpt_t *ep = buffer;
transport_endpt_attr_t tea;
vcl_session_t *session;
@@ -3747,27 +3773,6 @@
*buflen);
break;
- case VPPCOM_ATTR_SET_SHUT:
- if (*flags == SHUT_RD || *flags == SHUT_RDWR)
- vcl_session_set_attr (session, VCL_SESS_ATTR_SHUT_RD);
- if (*flags == SHUT_WR || *flags == SHUT_RDWR)
- vcl_session_set_attr (session, VCL_SESS_ATTR_SHUT_WR);
- break;
-
- case VPPCOM_ATTR_GET_SHUT:
- if (vcl_session_has_attr (session, VCL_SESS_ATTR_SHUT_RD))
- tmp_flags = 1;
- if (vcl_session_has_attr (session, VCL_SESS_ATTR_SHUT_WR))
- tmp_flags |= 2;
- if (tmp_flags == 1)
- *(int *) buffer = SHUT_RD;
- else if (tmp_flags == 2)
- *(int *) buffer = SHUT_WR;
- else if (tmp_flags == 3)
- *(int *) buffer = SHUT_RDWR;
- *buflen = sizeof (int);
- break;
-
case VPPCOM_ATTR_SET_CONNECTED:
session->flags |= VCL_SESSION_F_CONNECTED;
break;
diff --git a/src/vcl/vppcom.h b/src/vcl/vppcom.h
index c2a625e..19a01c7 100644
--- a/src/vcl/vppcom.h
+++ b/src/vcl/vppcom.h
@@ -99,6 +99,7 @@
VPPCOM_ETIMEDOUT = -ETIMEDOUT,
VPPCOM_EEXIST = -EEXIST,
VPPCOM_ENOPROTOOPT = -ENOPROTOOPT,
+ VPPCOM_EPIPE = -EPIPE,
VPPCOM_ENOENT = -ENOENT,
} vppcom_error_t;
@@ -138,8 +139,6 @@
VPPCOM_ATTR_SET_TCP_KEEPINTVL,
VPPCOM_ATTR_GET_TCP_USER_MSS,
VPPCOM_ATTR_SET_TCP_USER_MSS,
- VPPCOM_ATTR_SET_SHUT,
- VPPCOM_ATTR_GET_SHUT,
VPPCOM_ATTR_SET_CONNECTED,
VPPCOM_ATTR_SET_CKPAIR,
VPPCOM_ATTR_SET_VRF,
@@ -174,7 +173,7 @@
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_shutdown (uint32_t session_handle, int how);
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);