diff options
Diffstat (limited to 'lib/libtle_l4p/tcp_stream.c')
-rw-r--r-- | lib/libtle_l4p/tcp_stream.c | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/lib/libtle_l4p/tcp_stream.c b/lib/libtle_l4p/tcp_stream.c index 67ed66b..f06b2ed 100644 --- a/lib/libtle_l4p/tcp_stream.c +++ b/lib/libtle_l4p/tcp_stream.c @@ -511,6 +511,7 @@ tle_tcp_stream_listen(struct tle_stream *ts) TCP_ST_LISTEN); if (rc != 0) { s->tcb.uop |= TCP_OP_LISTEN; + s->tcb.rcv.wnd = calc_rx_wnd(s, TCP_WSCALE_DEFAULT); rc = 0; } else rc = -EDEADLK; @@ -520,3 +521,87 @@ tle_tcp_stream_listen(struct tle_stream *ts) rwl_release(&s->rx.use); return rc; } + +/* + * helper function, updates stream config + */ +static inline int +stream_update_cfg(struct tle_stream *ts,struct tle_tcp_stream_cfg *prm) +{ + int32_t rc1, rc2; + struct tle_tcp_stream *s; + + s = TCP_STREAM(ts); + + rc1 = rwl_try_acquire(&s->rx.use); + rc2 = rwl_try_acquire(&s->tx.use); + + if (rc1 < 0 || rc2 < 0 || (s->tcb.uop & TCP_OP_CLOSE) != 0) { + rwl_release(&s->tx.use); + rwl_release(&s->rx.use); + return -EINVAL; + } + + /* setup stream notification menchanism */ + s->rx.ev = prm->recv_ev; + s->tx.ev = prm->send_ev; + s->err.ev = prm->err_ev; + + s->rx.cb.data = prm->recv_cb.data; + s->tx.cb.data = prm->send_cb.data; + s->err.cb.data = prm->err_cb.data; + + rte_smp_wmb(); + + s->rx.cb.func = prm->recv_cb.func; + s->tx.cb.func = prm->send_cb.func; + s->err.cb.func = prm->err_cb.func; + + /* store other params */ + s->tcb.snd.nb_retm = (prm->nb_retries != 0) ? prm->nb_retries : + TLE_TCP_DEFAULT_RETRIES; + + /* invoke async notifications, if any */ + if (rte_ring_count(s->rx.q) != 0) { + if (s->rx.ev != NULL) + tle_event_raise(s->rx.ev); + else if (s->rx.cb.func != NULL) + s->rx.cb.func(s->rx.cb.data, &s->s); + } + if (rte_ring_free_count(s->tx.q) != 0) { + if (s->tx.ev != NULL) + tle_event_raise(s->tx.ev); + 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->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); + } + + rwl_release(&s->tx.use); + rwl_release(&s->rx.use); + + return 0; +} + +uint32_t +tle_tcp_stream_update_cfg(struct tle_stream *ts[], + struct tle_tcp_stream_cfg prm[], uint32_t num) +{ + int32_t rc; + uint32_t i; + + for (i = 0; i != num; i++) { + rc = stream_update_cfg(ts[i], &prm[i]); + if (rc != 0) { + rte_errno = -rc; + break; + } + } + + return i; +} |