From 5a82ac6d6a3c245a468e6dc2c63a8f5fe6179aca Mon Sep 17 00:00:00 2001 From: Konstantin Ananyev Date: Tue, 3 Aug 2021 16:17:10 +0000 Subject: l4p/tcp: introduce tle_tcp_stream_shutdown() API Introduce ability ot perform half-close for TCP connection. Signed-off-by: Konstantin Ananyev Change-Id: I468ed84b5f42ae1e5c35f08871f7dd775e3d888a --- lib/libtle_l4p/tcp_stream.c | 79 ++++++++++++++++++++++++++++++++++----------- lib/libtle_l4p/tle_tcp.h | 20 ++++++++++-- 2 files changed, 79 insertions(+), 20 deletions(-) diff --git a/lib/libtle_l4p/tcp_stream.c b/lib/libtle_l4p/tcp_stream.c index 59299f7..59d94a4 100644 --- a/lib/libtle_l4p/tcp_stream.c +++ b/lib/libtle_l4p/tcp_stream.c @@ -502,6 +502,26 @@ tle_tcp_stream_open(struct tle_ctx *ctx, return &s->s; } +/* + * Helper function, used by close()/shutdown API + * Check stream state, if FIN was not generatedi yet, then + * change stream state and queue it for TX. + */ +static inline int +stream_finalize(struct tle_ctx *ctx, struct tle_tcp_stream *s, uint32_t state) +{ + if (state != TLE_TCP_ST_ESTABLISHED && state != TLE_TCP_ST_CLOSE_WAIT) + return -EINVAL; + + /* change state */ + s->tcb.state = (state == TLE_TCP_ST_ESTABLISHED) ? + TLE_TCP_ST_FIN_WAIT_1 : TLE_TCP_ST_LAST_ACK; + + /* queue stream into to-send queue */ + txs_enqueue(ctx, s); + return 0; +} + /* * Helper function, used by close API. */ @@ -515,26 +535,12 @@ stream_close(struct tle_ctx *ctx, struct tle_tcp_stream *s) return rc; /* generate FIN and proceed with normal connection termination */ - if (rc == TLE_TCP_ST_ESTABLISHED || rc == TLE_TCP_ST_CLOSE_WAIT) { - - /* change state */ - s->tcb.state = (rc == TLE_TCP_ST_ESTABLISHED) ? - TLE_TCP_ST_FIN_WAIT_1 : TLE_TCP_ST_LAST_ACK; + stream_finalize(ctx, s, rc); - /* mark stream as writable/readable again */ - tcp_stream_up(s); - - /* queue stream into to-send queue */ - txs_enqueue(ctx, s); - return 0; - } + /* mark stream as writable/readable again */ + tcp_stream_up(s); - /* - * accroding to the state, close() was already invoked, - * should never that point. - */ - RTE_ASSERT(0); - return -EINVAL; + return 0; } uint32_t @@ -628,6 +634,43 @@ tle_tcp_stream_abort(struct tle_stream *ts) return rc; } +int +tle_tcp_stream_shutdown(struct tle_stream *ts) +{ + int32_t rc; + uint16_t uop; + struct tle_ctx *ctx; + struct tle_tcp_stream *s; + + const uint16_t nop = TLE_TCP_OP_SHUTDOWN; + + s = TCP_STREAM(ts); + if (ts == NULL || s->s.type >= TLE_VNUM) + return -EINVAL; + + ctx = s->s.ctx; + + /* check was shutdown() or close() already invoked */ + uop = s->tcb.uop; + if ((uop & (TLE_TCP_OP_CLOSE | nop)) != 0) + return -EDEADLK; + + /* record that shutdown was invoked */ + if (rte_atomic16_cmpset(&s->tcb.uop, uop, uop | nop) == 0) + return -EDEADLK; + + /* mark stream as unavaialbe for RX/TX. */ + tcp_stream_down(s); + + /* change state, generate FIN */ + rc = stream_finalize(ctx, s, s->tcb.state); + + /* mark stream as writable/readable again */ + tcp_stream_up(s); + + return rc; +} + int tle_tcp_stream_get_addr(const struct tle_stream *ts, struct tle_tcp_stream_addr *addr) diff --git a/lib/libtle_l4p/tle_tcp.h b/lib/libtle_l4p/tle_tcp.h index 289683f..8a42f75 100644 --- a/lib/libtle_l4p/tle_tcp.h +++ b/lib/libtle_l4p/tle_tcp.h @@ -48,8 +48,9 @@ enum { TLE_TCP_OP_ACCEPT = 0x2, TLE_TCP_OP_CONNECT = 0x4, TLE_TCP_OP_ESTABLISH = 0x8, - TLE_TCP_OP_CLOSE = 0x10, - TLE_TCP_OP_ABORT = 0x20, + TLE_TCP_OP_SHUTDOWN = 0x10, + TLE_TCP_OP_CLOSE = 0x20, + TLE_TCP_OP_ABORT = 0x40, }; #define TLE_TCP_OP_CLOSE_ABORT (TLE_TCP_OP_CLOSE | TLE_TCP_OP_ABORT) @@ -167,6 +168,21 @@ tle_tcp_stream_open(struct tle_ctx *ctx, */ int tle_tcp_stream_close(struct tle_stream *s); +/** + * half-close for open stream. + * if the stream is in connected or close-wait state, then: + * - FIN packet will be generated and stream state will be changed accordingly. + * Note that stream will remain open till user will call actual close() + * for that stream (even if actual connection was already terminated). + * @param s + * Pointer to the stream to close. + * @return + * zero on successful completion. + * - -EINVAL - invalid parameter passed to function + * - -EDEADLK - shutdown/close was already invoked on that stream + */ +int tle_tcp_stream_shutdown(struct tle_stream *s); + /** * abnormal stream termination. * if the stream is in connected state, then: -- cgit 1.2.3-korg