aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKonstantin Ananyev <konstantin.ananyev@intel.com>2021-07-06 15:08:48 +0000
committerKonstantin Ananyev <konstantin.ananyev@intel.com>2021-07-06 15:08:48 +0000
commitace4313dfd1f17eac022e497bb412e8e290c05e3 (patch)
tree0aa3f12476d3a615dd47489154074144966a1dc9
parenta32eaa3d00beef6bb81e2aadc2088e9a937d1fd0 (diff)
l4p/tcp: introduce tle_tcp_stream_get_state() API
tle_tcp_stream_get_state() allows user to query information regarding stream state, control ops and remote termination events. Signed-off-by: Konstantin Ananyev <konstantin.ananyev@intel.com> Change-Id: Ica22a5fe2e63fdece882935b76572142433a4ae1
-rw-r--r--lib/libtle_l4p/tcp_ctl.h9
-rw-r--r--lib/libtle_l4p/tcp_rxtx.c87
-rw-r--r--lib/libtle_l4p/tcp_stream.c48
-rw-r--r--lib/libtle_l4p/tcp_stream.h25
-rw-r--r--lib/libtle_l4p/tle_tcp.h61
5 files changed, 150 insertions, 80 deletions
diff --git a/lib/libtle_l4p/tcp_ctl.h b/lib/libtle_l4p/tcp_ctl.h
index 7dde8ff..57f3ffc 100644
--- a/lib/libtle_l4p/tcp_ctl.h
+++ b/lib/libtle_l4p/tcp_ctl.h
@@ -152,16 +152,19 @@ tcp_stream_reset(struct tle_ctx *ctx, struct tle_tcp_stream *s)
rte_atomic32_set(&s->tx.arm, 0);
/* reset TCB */
- uop = s->tcb.uop & ~TCP_OP_CLOSE;
+ uop = s->tcb.uop & ~TLE_TCP_OP_CLOSE;
memset(&s->tcb, 0, sizeof(s->tcb));
+ /* reset remote events */
+ s->err.rev = 0;
+
/* reset cached destination */
memset(&s->tx.dst, 0, sizeof(s->tx.dst));
- if (uop != TCP_OP_ACCEPT) {
+ if (uop != TLE_TCP_OP_ACCEPT) {
/* free stream's destination port */
stream_clear_ctx(ctx, &s->s);
- if (uop == TCP_OP_LISTEN)
+ if (uop == TLE_TCP_OP_LISTEN)
empty_lq(s);
}
diff --git a/lib/libtle_l4p/tcp_rxtx.c b/lib/libtle_l4p/tcp_rxtx.c
index 4f43557..03b6c63 100644
--- a/lib/libtle_l4p/tcp_rxtx.c
+++ b/lib/libtle_l4p/tcp_rxtx.c
@@ -63,7 +63,7 @@ rx_obtain_listen_stream(const struct tle_dev *dev, const union pkt_info *pi,
return NULL;
/* check that we have a proper stream. */
- if (s->tcb.state != TCP_ST_LISTEN) {
+ if (s->tcb.state != TLE_TCP_ST_LISTEN) {
tcp_stream_release(s);
s = NULL;
}
@@ -80,7 +80,7 @@ rx_acquire_stream(struct tle_stream *ts)
if (tcp_stream_acquire(s) < 0)
return NULL;
- else if (s->tcb.state == TCP_ST_CLOSED) {
+ else if (s->tcb.state == TLE_TCP_ST_CLOSED) {
tcp_stream_release(s);
return NULL;
}
@@ -104,7 +104,7 @@ rx_obtain_stream(const struct tle_dev *dev, struct stbl *st,
if (tcp_stream_acquire(s) < 0)
return NULL;
/* check that we have a proper stream. */
- else if (s->tcb.state == TCP_ST_CLOSED) {
+ else if (s->tcb.state == TLE_TCP_ST_CLOSED) {
tcp_stream_release(s);
s = NULL;
}
@@ -828,13 +828,13 @@ stream_term(struct tle_tcp_stream *s)
{
struct sdr *dr;
- s->tcb.state = TCP_ST_CLOSED;
+ s->tcb.state = TLE_TCP_ST_CLOSED;
rte_smp_wmb();
timer_stop(s);
/* close() was already invoked, schedule final cleanup */
- if ((s->tcb.uop & TCP_OP_CLOSE) != 0) {
+ if ((s->tcb.uop & TLE_TCP_OP_CLOSE) != 0) {
dr = CTX_TCP_SDR(s->s.ctx);
STAILQ_INSERT_TAIL(&dr->be, &s->s, link);
@@ -933,14 +933,14 @@ accept_prep_stream(struct tle_tcp_stream *ps, struct stbl *st,
cs->tcb.snd.ssthresh = cs->tcb.snd.wnd;
cs->tcb.snd.rto_tw = ps->tcb.snd.rto_tw;
- cs->tcb.state = TCP_ST_ESTABLISHED;
+ cs->tcb.state = TLE_TCP_ST_ESTABLISHED;
/* add stream to the table */
cs->ste = stbl_add_stream(st, pi, cs);
if (cs->ste == NULL)
return -ENOBUFS;
- cs->tcb.uop |= TCP_OP_ACCEPT;
+ cs->tcb.uop |= TLE_TCP_OP_ACCEPT;
tcp_stream_up(cs);
return 0;
}
@@ -1058,7 +1058,7 @@ static void
stream_timewait(struct tle_tcp_stream *s, uint32_t rto)
{
if (rto != 0) {
- s->tcb.state = TCP_ST_TIME_WAIT;
+ s->tcb.state = TLE_TCP_ST_TIME_WAIT;
s->tcb.snd.rto = rto;
timer_reset(s);
} else
@@ -1072,27 +1072,29 @@ rx_fin_state(struct tle_tcp_stream *s, struct resp_info *rsp)
int32_t ackfin;
s->tcb.rcv.nxt += 1;
+ s->err.rev |= TLE_TCP_REV_FIN;
ackfin = (s->tcb.snd.una == s->tcb.snd.fss);
state = s->tcb.state;
- if (state == TCP_ST_ESTABLISHED) {
- s->tcb.state = TCP_ST_CLOSE_WAIT;
+ if (state == TLE_TCP_ST_ESTABLISHED) {
+ s->tcb.state = TLE_TCP_ST_CLOSE_WAIT;
/* raise err.ev & err.cb */
if (s->err.ev != NULL)
tle_event_raise(s->err.ev);
else if (s->err.cb.func != NULL)
s->err.cb.func(s->err.cb.data, &s->s);
- } else if (state == TCP_ST_FIN_WAIT_1 || state == TCP_ST_CLOSING) {
+ } else if (state == TLE_TCP_ST_FIN_WAIT_1 ||
+ state == TLE_TCP_ST_CLOSING) {
rsp->flags |= TCP_FLAG_ACK;
if (ackfin != 0)
stream_timewait(s, s->tcb.snd.rto_tw);
else
- s->tcb.state = TCP_ST_CLOSING;
- } else if (state == TCP_ST_FIN_WAIT_2) {
+ s->tcb.state = TLE_TCP_ST_CLOSING;
+ } else if (state == TLE_TCP_ST_FIN_WAIT_2) {
rsp->flags |= TCP_FLAG_ACK;
stream_timewait(s, s->tcb.snd.rto_tw);
- } else if (state == TCP_ST_LAST_ACK && ackfin != 0) {
+ } else if (state == TLE_TCP_ST_LAST_ACK && ackfin != 0) {
stream_term(s);
}
}
@@ -1122,7 +1124,7 @@ rx_fin(struct tle_tcp_stream *s, uint32_t state,
if (ret != 0)
return ret;
- if (state < TCP_ST_ESTABLISHED)
+ if (state < TLE_TCP_ST_ESTABLISHED)
return -EINVAL;
if (plen != 0) {
@@ -1169,7 +1171,7 @@ rx_rst(struct tle_tcp_stream *s, uint32_t state, uint32_t flags,
* In the SYN-SENT state (a RST received in response to an initial SYN),
* the RST is acceptable if the ACK field acknowledges the SYN.
*/
- if (state == TCP_ST_SYN_SENT) {
+ if (state == TLE_TCP_ST_SYN_SENT) {
rc = ((flags & TCP_FLAG_ACK) == 0 ||
si->ack != s->tcb.snd.nxt) ?
-ERANGE : 0;
@@ -1178,8 +1180,10 @@ rx_rst(struct tle_tcp_stream *s, uint32_t state, uint32_t flags,
else
rc = check_seqn(&s->tcb, si->seq, 0);
- if (rc == 0)
+ if (rc == 0) {
+ s->err.rev |= TLE_TCP_REV_RST;
stream_term(s);
+ }
return rc;
}
@@ -1534,12 +1538,12 @@ rx_ackfin(struct tle_tcp_stream *s)
empty_tq(s);
state = s->tcb.state;
- if (state == TCP_ST_LAST_ACK)
+ if (state == TLE_TCP_ST_LAST_ACK)
stream_term(s);
- else if (state == TCP_ST_FIN_WAIT_1) {
+ else if (state == TLE_TCP_ST_FIN_WAIT_1) {
timer_stop(s);
- s->tcb.state = TCP_ST_FIN_WAIT_2;
- } else if (state == TCP_ST_CLOSING) {
+ s->tcb.state = TLE_TCP_ST_FIN_WAIT_2;
+ } else if (state == TLE_TCP_ST_CLOSING) {
stream_timewait(s, s->tcb.snd.rto_tw);
}
}
@@ -1581,7 +1585,7 @@ rx_synack(struct tle_tcp_stream *s, uint32_t ts, uint32_t state,
struct tle_tcp_syn_opts so;
struct rte_tcp_hdr *th;
- if (state != TCP_ST_SYN_SENT)
+ if (state != TLE_TCP_ST_SYN_SENT)
return -EINVAL;
/*
@@ -1628,7 +1632,7 @@ rx_synack(struct tle_tcp_stream *s, uint32_t ts, uint32_t state,
rsp->flags |= TCP_FLAG_ACK;
timer_stop(s);
- s->tcb.state = TCP_ST_ESTABLISHED;
+ s->tcb.state = TLE_TCP_ST_ESTABLISHED;
rte_smp_wmb();
if (s->tx.ev != NULL)
@@ -1704,7 +1708,8 @@ rx_stream(struct tle_tcp_stream *s, uint32_t ts,
i += (ret > 0);
/* normal data/ack packets */
- } else if (state >= TCP_ST_ESTABLISHED && state <= TCP_ST_LAST_ACK) {
+ } else if (state >= TLE_TCP_ST_ESTABLISHED &&
+ state <= TLE_TCP_ST_LAST_ACK) {
/* process incoming data packets. */
dack_info_init(&tack, &s->tcb);
@@ -1807,7 +1812,7 @@ rx_postsyn(struct tle_dev *dev, struct stbl *st, uint32_t type, uint32_t ts,
k = 0;
state = s->tcb.state;
- if (state == TCP_ST_LISTEN) {
+ if (state == TLE_TCP_ST_LISTEN) {
/* one connection per flow */
cs = NULL;
@@ -2222,8 +2227,8 @@ tle_tcp_stream_connect(struct tle_stream *ts, const struct sockaddr *addr)
return -EINVAL;
if (tcp_stream_try_acquire(s) > 0) {
- rc = rte_atomic16_cmpset(&s->tcb.state, TCP_ST_CLOSED,
- TCP_ST_SYN_SENT);
+ rc = rte_atomic16_cmpset(&s->tcb.state, TLE_TCP_ST_CLOSED,
+ TLE_TCP_ST_SYN_SENT);
rc = (rc == 0) ? -EDEADLK : 0;
} else
rc = -EINVAL;
@@ -2234,7 +2239,7 @@ tle_tcp_stream_connect(struct tle_stream *ts, const struct sockaddr *addr)
}
/* fill stream, prepare and transmit syn pkt */
- s->tcb.uop |= TCP_OP_CONNECT;
+ s->tcb.uop |= TLE_TCP_OP_CONNECT;
rc = tx_syn(s, addr);
tcp_stream_release(s);
@@ -2295,7 +2300,7 @@ tle_tcp_stream_establish(struct tle_ctx *ctx,
}
do {
- s->tcb.uop |= TCP_OP_ESTABLISH;
+ s->tcb.uop |= TLE_TCP_OP_ESTABLISH;
/* check and use stream addresses and parameters */
rc = tcp_stream_fill_prm(s, prm);
@@ -2317,7 +2322,7 @@ tle_tcp_stream_establish(struct tle_ctx *ctx,
/* fill TCB from user provided data */
tcb_establish(s, ci);
- s->tcb.state = TCP_ST_ESTABLISHED;
+ s->tcb.state = TLE_TCP_ST_ESTABLISHED;
tcp_stream_up(s);
} while (0);
@@ -2463,7 +2468,7 @@ tle_tcp_stream_send(struct tle_stream *ts, struct rte_mbuf *pkt[], uint16_t num)
}
state = s->tcb.state;
- if (state != TCP_ST_ESTABLISHED && state != TCP_ST_CLOSE_WAIT) {
+ if (state != TLE_TCP_ST_ESTABLISHED && state != TLE_TCP_ST_CLOSE_WAIT) {
rte_errno = ENOTCONN;
tcp_stream_release(s);
return 0;
@@ -2567,7 +2572,7 @@ tle_tcp_stream_writev(struct tle_stream *ts, struct rte_mempool *mp,
}
state = s->tcb.state;
- if (state != TCP_ST_ESTABLISHED && state != TCP_ST_CLOSE_WAIT) {
+ if (state != TLE_TCP_ST_ESTABLISHED && state != TLE_TCP_ST_CLOSE_WAIT) {
rte_errno = ENOTCONN;
tcp_stream_release(s);
return -1;
@@ -2663,8 +2668,8 @@ tx_data_fin(struct tle_tcp_stream *s, uint32_t tms, uint32_t state)
tx_nxt_data(s, tms);
/* we also have to send a FIN */
- if (state != TCP_ST_ESTABLISHED &&
- state != TCP_ST_CLOSE_WAIT &&
+ if (state != TLE_TCP_ST_ESTABLISHED &&
+ state != TLE_TCP_ST_CLOSE_WAIT &&
tcp_txq_nxt_cnt(s) == 0 &&
s->tcb.snd.fss != s->tcb.snd.nxt) {
s->tcb.snd.fss = ++s->tcb.snd.nxt;
@@ -2679,12 +2684,13 @@ tx_stream(struct tle_tcp_stream *s, uint32_t tms)
state = s->tcb.state;
- if (state == TCP_ST_SYN_SENT) {
+ if (state == TLE_TCP_ST_SYN_SENT) {
/* send the SYN, start the rto timer */
send_ack(s, tms, TCP_FLAG_SYN);
timer_start(s);
- } else if (state >= TCP_ST_ESTABLISHED && state <= TCP_ST_LAST_ACK) {
+ } else if (state >= TLE_TCP_ST_ESTABLISHED &&
+ state <= TLE_TCP_ST_LAST_ACK) {
tx_data_fin(s, tms, state);
@@ -2718,7 +2724,8 @@ rto_stream(struct tle_tcp_stream *s, uint32_t tms)
if (s->tcb.snd.nb_retx < s->tcb.snd.nb_retm) {
- if (state >= TCP_ST_ESTABLISHED && state <= TCP_ST_LAST_ACK) {
+ if (state >= TLE_TCP_ST_ESTABLISHED &&
+ state <= TLE_TCP_ST_LAST_ACK) {
/* update SND.CWD and SND.SSTHRESH */
rto_cwnd_update(&s->tcb);
@@ -2733,7 +2740,7 @@ rto_stream(struct tle_tcp_stream *s, uint32_t tms)
tx_data_fin(s, tms, state);
- } else if (state == TCP_ST_SYN_SENT) {
+ } else if (state == TLE_TCP_ST_SYN_SENT) {
/* resending SYN */
s->tcb.so.ts.val = tms;
@@ -2750,7 +2757,8 @@ rto_stream(struct tle_tcp_stream *s, uint32_t tms)
send_ack(s, tms, TCP_FLAG_SYN);
- } else if (state == TCP_ST_TIME_WAIT) {
+ } else if (state == TLE_TCP_ST_TIME_WAIT) {
+ s->err.rev |= TLE_TCP_REV_RTO;
stream_term(s);
}
@@ -2760,6 +2768,7 @@ rto_stream(struct tle_tcp_stream *s, uint32_t tms)
timer_restart(s);
} else {
+ s->err.rev |= TLE_TCP_REV_RTO;
send_rst(s, s->tcb.snd.nxt);
stream_term(s);
}
diff --git a/lib/libtle_l4p/tcp_stream.c b/lib/libtle_l4p/tcp_stream.c
index dbed84e..d97a6ce 100644
--- a/lib/libtle_l4p/tcp_stream.c
+++ b/lib/libtle_l4p/tcp_stream.c
@@ -514,11 +514,11 @@ stream_close(struct tle_ctx *ctx, struct tle_tcp_stream *s)
/* check was close() already invoked */
uop = s->tcb.uop;
- if ((uop & TCP_OP_CLOSE) != 0)
+ if ((uop & TLE_TCP_OP_CLOSE) != 0)
return -EDEADLK;
/* record that close() was already invoked */
- if (rte_atomic16_cmpset(&s->tcb.uop, uop, uop | TCP_OP_CLOSE) == 0)
+ if (rte_atomic16_cmpset(&s->tcb.uop, uop, uop | TLE_TCP_OP_CLOSE) == 0)
return -EDEADLK;
/* mark stream as unavaialbe for RX/TX. */
@@ -536,17 +536,17 @@ stream_close(struct tle_ctx *ctx, struct tle_tcp_stream *s)
state = s->tcb.state;
/* CLOSED, LISTEN, SYN_SENT - we can close the stream straighway */
- if (state <= TCP_ST_SYN_SENT) {
+ if (state <= TLE_TCP_ST_SYN_SENT) {
tcp_stream_reset(ctx, s);
return 0;
}
/* generate FIN and proceed with normal connection termination */
- if (state == TCP_ST_ESTABLISHED || state == TCP_ST_CLOSE_WAIT) {
+ if (state == TLE_TCP_ST_ESTABLISHED || state == TLE_TCP_ST_CLOSE_WAIT) {
/* change state */
- s->tcb.state = (state == TCP_ST_ESTABLISHED) ?
- TCP_ST_FIN_WAIT_1 : TCP_ST_LAST_ACK;
+ s->tcb.state = (state == TLE_TCP_ST_ESTABLISHED) ?
+ TLE_TCP_ST_FIN_WAIT_1 : TLE_TCP_ST_LAST_ACK;
/* mark stream as writable/readable again */
tcp_stream_up(s);
@@ -666,15 +666,15 @@ tle_tcp_stream_listen(struct tle_stream *ts)
/* app may listen for multiple times to change backlog,
* we will just return success for such cases.
*/
- if (s->tcb.state == TCP_ST_LISTEN)
+ if (s->tcb.state == TLE_TCP_ST_LISTEN)
return 0;
/* mark stream as not closable. */
if (tcp_stream_try_acquire(s) > 0) {
- rc = rte_atomic16_cmpset(&s->tcb.state, TCP_ST_CLOSED,
- TCP_ST_LISTEN);
+ rc = rte_atomic16_cmpset(&s->tcb.state, TLE_TCP_ST_CLOSED,
+ TLE_TCP_ST_LISTEN);
if (rc != 0) {
- s->tcb.uop |= TCP_OP_LISTEN;
+ s->tcb.uop |= TLE_TCP_OP_LISTEN;
s->tcb.rcv.wnd = calc_rx_wnd(s, TCP_WSCALE_DEFAULT);
rc = 0;
} else
@@ -696,7 +696,8 @@ stream_update_cfg(struct tle_stream *ts,struct tle_tcp_stream_cfg *prm)
s = TCP_STREAM(ts);
- if (tcp_stream_try_acquire(s) < 0 || (s->tcb.uop & TCP_OP_CLOSE) != 0) {
+ if (tcp_stream_try_acquire(s) < 0 ||
+ (s->tcb.uop & TLE_TCP_OP_CLOSE) != 0) {
tcp_stream_release(s);
return -EINVAL;
}
@@ -734,8 +735,8 @@ stream_update_cfg(struct tle_stream *ts,struct tle_tcp_stream_cfg *prm)
else if (s->tx.cb.func != NULL)
s->tx.cb.func(s->tx.cb.data, &s->s);
}
- if (s->tcb.state == TCP_ST_CLOSE_WAIT ||
- s->tcb.state == TCP_ST_CLOSED) {
+ if (s->tcb.state == TLE_TCP_ST_CLOSE_WAIT ||
+ s->tcb.state == TLE_TCP_ST_CLOSED) {
if (s->err.ev != NULL)
tle_event_raise(s->err.ev);
else if (s->err.cb.func != NULL)
@@ -769,9 +770,26 @@ tle_tcp_stream_get_mss(const struct tle_stream * ts)
{
struct tle_tcp_stream *s;
- if (ts == NULL)
+ s = TCP_STREAM(ts);
+ if (ts == NULL || s->s.type >= TLE_VNUM)
return -EINVAL;
- s = TCP_STREAM(ts);
return s->tcb.snd.mss;
}
+
+int
+tle_tcp_stream_get_state(const struct tle_stream * ts,
+ struct tle_tcp_stream_state *st)
+{
+ struct tle_tcp_stream *s;
+
+ s = TCP_STREAM(ts);
+ if (ts == NULL || s->s.type >= TLE_VNUM)
+ return -EINVAL;
+
+ st->state = s->tcb.state;
+ st->uop = s->tcb.uop;
+ st->rev = s->err.rev;
+
+ return 0;
+}
diff --git a/lib/libtle_l4p/tcp_stream.h b/lib/libtle_l4p/tcp_stream.h
index a36b5fe..f04052d 100644
--- a/lib/libtle_l4p/tcp_stream.h
+++ b/lib/libtle_l4p/tcp_stream.h
@@ -30,29 +30,6 @@
extern "C" {
#endif
-enum {
- TCP_ST_CLOSED,
- TCP_ST_LISTEN,
- TCP_ST_SYN_SENT,
- TCP_ST_SYN_RCVD,
- TCP_ST_ESTABLISHED,
- TCP_ST_FIN_WAIT_1,
- TCP_ST_FIN_WAIT_2,
- TCP_ST_CLOSE_WAIT,
- TCP_ST_CLOSING,
- TCP_ST_LAST_ACK,
- TCP_ST_TIME_WAIT,
- TCP_ST_NUM
-};
-
-enum {
- TCP_OP_LISTEN = 0x1,
- TCP_OP_ACCEPT = 0x2,
- TCP_OP_CONNECT = 0x4,
- TCP_OP_ESTABLISH = 0x8,
- TCP_OP_CLOSE = 0x10,
-};
-
struct tcb {
volatile uint16_t state;
volatile uint16_t uop; /* operations by user performed */
@@ -111,6 +88,8 @@ struct tle_tcp_stream {
struct {
struct tle_event *ev;
struct tle_stream_cb cb;
+ /*bitmask of remote events */
+ uint16_t rev;
} err;
struct {
diff --git a/lib/libtle_l4p/tle_tcp.h b/lib/libtle_l4p/tle_tcp.h
index 76f3476..df50a23 100644
--- a/lib/libtle_l4p/tle_tcp.h
+++ b/lib/libtle_l4p/tle_tcp.h
@@ -23,6 +23,44 @@ extern "C" {
#endif
/**
+ * TCP stream states
+ */
+enum {
+ TLE_TCP_ST_CLOSED,
+ TLE_TCP_ST_LISTEN,
+ TLE_TCP_ST_SYN_SENT,
+ TLE_TCP_ST_SYN_RCVD,
+ TLE_TCP_ST_ESTABLISHED,
+ TLE_TCP_ST_FIN_WAIT_1,
+ TLE_TCP_ST_FIN_WAIT_2,
+ TLE_TCP_ST_CLOSE_WAIT,
+ TLE_TCP_ST_CLOSING,
+ TLE_TCP_ST_LAST_ACK,
+ TLE_TCP_ST_TIME_WAIT,
+ TLE_TCP_ST_NUM
+};
+
+/**
+ * User control operations for TCP stream
+ */
+enum {
+ TLE_TCP_OP_LISTEN = 0x1,
+ TLE_TCP_OP_ACCEPT = 0x2,
+ TLE_TCP_OP_CONNECT = 0x4,
+ TLE_TCP_OP_ESTABLISH = 0x8,
+ TLE_TCP_OP_CLOSE = 0x10,
+};
+
+/**
+ * termination/error events from remote peer
+ */
+enum {
+ TLE_TCP_REV_FIN = 0x1, /** FIN received from peer*/
+ TLE_TCP_REV_RST = 0x2, /** RST received from peer */
+ TLE_TCP_REV_RTO = 0x4, /** receive timed-out */
+};
+
+/**
* TCP stream creation parameters.
*/
struct tle_tcp_stream_addr {
@@ -81,6 +119,18 @@ struct tle_tcp_conn_info {
};
/**
+ * TCP stream state information.
+ */
+struct tle_tcp_stream_state {
+ /** current TCP state (one of TLE_TCP_ST_*) */
+ uint16_t state;
+ /** bitmask of control ops performed by user (TLE_TCP_OP_*) */
+ uint16_t uop;
+ /** bitmask of remote termination events (TLE_TCP_REV_*) */
+ uint16_t rev;
+};
+
+/**
* create a new stream within given TCP context.
* @param ctx
* TCP context to create new stream within.
@@ -158,6 +208,17 @@ tle_tcp_stream_get_addr(const struct tle_stream *s,
*/
int tle_tcp_stream_get_mss(const struct tle_stream *ts);
+/**
+ * Get current TCP stream state
+ * @param ts
+ * Stream to retrieve state information from.
+ * @return
+ * zero on successful completion.
+ * - EINVAL - invalid parameter passed to function
+ */
+int tle_tcp_stream_get_state(const struct tle_stream *ts,
+ struct tle_tcp_stream_state *st);
+
struct tle_stream *
tle_tcp_stream_establish(struct tle_ctx *ctx,
const struct tle_tcp_stream_param *prm,