57f3ffcbedbf74838aff87f18894e7b0ebbce66a
[tldk.git] / lib / libtle_l4p / tcp_ctl.h
1 /*
2  * Copyright (c) 2016-2017  Intel Corporation.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 /*
17  * Some helper stream control functions definitions.
18  */
19
20 #ifndef _TCP_CTL_H_
21 #define _TCP_CTL_H_
22
23 #include "tcp_stream.h"
24 #include "tcp_ofo.h"
25
26 #ifdef __cplusplus
27 extern "C" {
28 #endif
29
30 static inline void
31 tcp_stream_down(struct tle_tcp_stream *s)
32 {
33         if ((s->flags & TLE_CTX_FLAG_ST) == 0)
34                 rwl_down(&s->use);
35         else
36                 rte_atomic32_set(&s->use, INT32_MIN);
37 }
38
39 static inline void
40 tcp_stream_up(struct tle_tcp_stream *s)
41 {
42         int32_t v;
43
44         if ((s->flags & TLE_CTX_FLAG_ST) == 0)
45                 rwl_up(&s->use);
46         else {
47                 v = rte_atomic32_read(&s->use) - INT32_MIN;
48                 rte_atomic32_set(&s->use, v);
49         }
50 }
51
52 static inline int
53 tcp_stream_try_acquire(struct tle_tcp_stream *s)
54 {
55         int32_t v;
56
57         if ((s->flags & TLE_CTX_FLAG_ST) == 0)
58                 return rwl_try_acquire(&s->use);
59
60         v = rte_atomic32_read(&s->use) + 1;
61         rte_atomic32_set(&s->use, v);
62         return v;
63 }
64
65 static inline void
66 tcp_stream_release(struct tle_tcp_stream *s)
67 {
68         int32_t v;
69
70         if ((s->flags & TLE_CTX_FLAG_ST) == 0)
71                 rwl_release(&s->use);
72         else {
73                 v = rte_atomic32_read(&s->use) - 1;
74                 rte_atomic32_set(&s->use, v);
75         }
76 }
77
78 static inline int
79 tcp_stream_acquire(struct tle_tcp_stream *s)
80 {
81         int32_t v;
82
83         if ((s->flags & TLE_CTX_FLAG_ST) == 0)
84                 return rwl_acquire(&s->use);
85
86         v = rte_atomic32_read(&s->use) + 1;
87         if (v > 0)
88                 rte_atomic32_set(&s->use, v);
89         return v;
90 }
91
92 /* calculate RCV.WND value based on size of stream receive buffer */
93 static inline uint32_t
94 calc_rx_wnd(const struct tle_tcp_stream *s, uint32_t scale)
95 {
96         uint32_t wnd;
97
98         /* peer doesn't support WSCALE option, wnd size is limited to 64K */
99         if (scale == TCP_WSCALE_NONE) {
100                 wnd = _rte_ring_get_mask(s->rx.q) << TCP_WSCALE_DEFAULT;
101                 return RTE_MIN(wnd, (uint32_t)UINT16_MAX);
102         } else
103                 return  _rte_ring_get_mask(s->rx.q) << scale;
104 }
105
106 /* empty stream's send queue */
107 static inline void
108 empty_tq(struct tle_tcp_stream *s)
109 {
110         s->tx.q->cons.head = s->tx.q->cons.tail;
111         empty_mbuf_ring(s->tx.q);
112 }
113
114 /* empty stream's receive queue */
115 static inline void
116 empty_rq(struct tle_tcp_stream *s)
117 {
118         uint32_t n;
119         struct rte_mbuf *mb[MAX_PKT_BURST];
120
121         do {
122                 n = _rte_ring_mcs_dequeue_burst(s->rx.q, (void **)mb,
123                         RTE_DIM(mb));
124                 free_mbufs(mb, n);
125         } while (n != 0);
126
127         tcp_ofo_reset(s->rx.ofo);
128 }
129
130 /* empty stream's listen queue */
131 static inline void
132 empty_lq(struct tle_tcp_stream *s)
133 {
134         uint32_t n;
135         struct tle_stream *ts[MAX_PKT_BURST];
136
137         do {
138                 n = _rte_ring_dequeue_burst(s->rx.q, (void **)ts, RTE_DIM(ts));
139                 tle_tcp_stream_close_bulk(ts, n);
140         } while (n != 0);
141 }
142
143 static inline void
144 tcp_stream_reset(struct tle_ctx *ctx, struct tle_tcp_stream *s)
145 {
146         uint16_t uop;
147         struct tcp_streams *ts;
148
149         ts = CTX_TCP_STREAMS(ctx);
150
151         /* reset TX armed */
152         rte_atomic32_set(&s->tx.arm, 0);
153
154         /* reset TCB */
155         uop = s->tcb.uop & ~TLE_TCP_OP_CLOSE;
156         memset(&s->tcb, 0, sizeof(s->tcb));
157
158         /* reset remote events */
159         s->err.rev = 0;
160
161         /* reset cached destination */
162         memset(&s->tx.dst, 0, sizeof(s->tx.dst));
163
164         if (uop != TLE_TCP_OP_ACCEPT) {
165                 /* free stream's destination port */
166                 stream_clear_ctx(ctx, &s->s);
167                 if (uop == TLE_TCP_OP_LISTEN)
168                         empty_lq(s);
169         }
170
171         if (s->ste != NULL) {
172                 /* remove entry from RX streams table */
173                 stbl_del_stream(&ts->st, s->ste, s,
174                         (s->flags & TLE_CTX_FLAG_ST) == 0);
175                 s->ste = NULL;
176                 empty_rq(s);
177         }
178
179         /* empty TX queue */
180         empty_tq(s);
181
182         /*
183          * mark the stream as free again.
184          * if there still are pkts queued for TX,
185          * then put this stream to the tail of free list.
186          */
187         if (TCP_STREAM_TX_PENDING(s)) 
188                 put_stream(ctx, &s->s, 0);
189         else {
190                 s->s.type = TLE_VNUM;
191                 tle_memtank_free(ts->mts, (void **)&s, 1, 0);
192         }
193 }
194
195 static inline struct tle_tcp_stream *
196 tcp_stream_get(struct tle_ctx *ctx, uint32_t flag)
197 {
198         struct tle_stream *s;
199         struct tle_tcp_stream *cs;
200         struct tcp_streams *ts;
201
202         ts = CTX_TCP_STREAMS(ctx);
203         
204         /* check TX pending list */
205         s = get_stream(ctx);
206         cs = TCP_STREAM(s);
207         if (s != NULL) {
208                 if (TCP_STREAM_TX_FINISHED(cs))
209                         return cs;
210                 put_stream(ctx, &cs->s, 0);
211         }
212
213         if (tle_memtank_alloc(ts->mts, (void **)&cs, 1, flag) != 1)
214                 return NULL;
215
216         return cs;
217 }
218
219 #ifdef __cplusplus
220 }
221 #endif
222
223 #endif /* _TCP_CTL_H_ */