2 * Copyright (c) 2016 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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
27 struct rte_mbuf **obj;
37 _ofodb_free(struct ofodb *db)
41 for (i = 0; i != db->nb_elem; i++)
42 rte_pktmbuf_free(db->obj[i]);
46 _ofo_remove(struct ofo *ofo, uint32_t pos, uint32_t num)
50 n = ofo->nb_elem - num - pos;
51 for (i = 0; i != n; i++)
52 ofo->db[pos + i] = ofo->db[pos + num + i];
57 tcp_ofo_reset(struct ofo *ofo)
61 for (i = 0; i != ofo->nb_elem; i++)
62 _ofodb_free(&ofo->db[i]);
64 _ofo_remove(ofo, 0, ofo->nb_elem);
67 static inline uint32_t
68 _ofo_insert_new(struct ofo *ofo, uint32_t pos, union seqlen *sl,
69 struct rte_mbuf *mb[], uint32_t num)
80 /* allocate new one */
84 /* insert into a proper position. */
85 for (i = n; i != pos; i--)
86 ofo->db[i] = ofo->db[i - 1];
89 n = RTE_MIN(db->nb_max, num);
90 for (i = 0; i != n; i++)
93 /* can't queue some packets. */
95 for (i = n; i != num; i++)
96 plen += mb[i]->pkt_len;
100 db->sl.len = sl->len - plen;
102 sl->seq += db->sl.len;
103 sl->len -= db->sl.len;
107 static inline uint32_t
108 _ofo_insert_right(struct ofo *ofo, uint32_t pos, union seqlen *sl,
109 struct rte_mbuf *mb[], uint32_t num)
112 uint32_t end, plen, skip;
116 end = db->sl.seq + db->sl.len;
118 skip = end - sl->seq;
120 /* skip overlapping packets */
121 for (i = 0, n = skip; i != num && n != 0; i++, n -= plen) {
123 plen = mb[i]->pkt_len;
125 /* adjust partially overlapped packet. */
126 rte_pktmbuf_adj(mb[i], plen - n);
131 /* free totally overlapped packets. */
132 for (j = 0; j != i; j++)
133 rte_pktmbuf_free(mb[j]);
135 /* copy non-overlapping mbufs */
137 n = RTE_MIN(db->nb_max - k, num - i);
140 for (j = 0; j != n; j++) {
141 db->obj[k + j] = mb[i + j];
142 plen += mb[i + j]->pkt_len;
154 static inline uint32_t
155 _ofo_step(struct ofo *ofo, union seqlen *sl, struct rte_mbuf *mb[],
158 uint32_t i, n, end, lo, ro;
162 end = sl->seq + sl->len;
166 * start from the right side, assume that after some gap,
167 * we keep receiving packets in order.
169 for (i = n; i-- != 0; ) {
171 if (tcp_seq_leq(db->sl.seq, sl->seq))
175 /* new db required */
176 if ((int32_t)i < 0 || tcp_seq_lt(db->sl.seq + db->sl.len, sl->seq))
177 return _ofo_insert_new(ofo, i + 1, sl, mb, num);
179 /* new one is right adjacent, or overlap */
181 ro = sl->seq - db->sl.seq;
182 lo = end - db->sl.seq;
184 /* new one is completely overlapped by old one */
185 if (lo <= db->sl.len)
188 /* either overlap OR (adjacent AND some free space remains) */
189 if (ro < db->sl.len || db->nb_elem != db->nb_max)
190 return _ofo_insert_right(ofo, i, sl, mb, num);
192 /* adjacent, no free space in current block */
193 return _ofo_insert_new(ofo, i + 1, sl, mb, num);
197 _ofo_compact(struct ofo *ofo)
199 uint32_t i, j, n, ro;
202 for (i = 0; i < ofo->nb_elem; i = j) {
204 for (j = i + 1; j != ofo->nb_elem; j++) {
206 /* no intersection */
207 ro = ofo->db[j].sl.seq - ofo->db[i].sl.seq;
208 if (ro > ofo->db[i].sl.len)
212 n = _ofo_insert_right(ofo, i, &db->sl, db->obj,
214 if (n < db->nb_elem) {
222 _ofo_remove(ofo, i + 1, n);
226 static inline uint32_t
227 _ofodb_enqueue(struct rte_ring *r, const struct ofodb *db, union seqlen *sl)
232 sl->raw = db->sl.raw;
233 n = _rte_ring_enqueue_burst(r, (void * const *)db->obj, num);
235 sl->len -= tcp_mbuf_seq_free(db->obj + n, num - n);
240 tcp_ofo_alloc(uint32_t nbufs, int32_t socket);
243 tcp_ofo_free(struct ofo *ofo);
249 #endif /* _TCP_OFO_H_ */