From aa97dd1ce910b839fed46ad55d1e70e403f5a930 Mon Sep 17 00:00:00 2001 From: Konstantin Ananyev Date: Tue, 21 Feb 2017 18:12:20 +0000 Subject: Introduce first version of TCP code. Supported functionality: - open/close - listen/accept/connect - send/recv In order to achieve that libtle_udp library was reworked into libtle_l4p library that supports both TCP and UDP protocols. New libtle_timer library was introduced (thanks to Cisco guys and Dave Barach for sharing their timer code with us). Sample application was also reworked significantly to support both TCP and UDP traffic handling. New UT were introduced. Change-Id: I806b05011f521e89b58db403cfdd484a37beb775 Signed-off-by: Mohammad Abdul Awal Signed-off-by: Karol Latecki Signed-off-by: Daniel Mrzyglod Signed-off-by: Konstantin Ananyev --- lib/libtle_l4p/tcp_ofo.h | 249 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 249 insertions(+) create mode 100644 lib/libtle_l4p/tcp_ofo.h (limited to 'lib/libtle_l4p/tcp_ofo.h') diff --git a/lib/libtle_l4p/tcp_ofo.h b/lib/libtle_l4p/tcp_ofo.h new file mode 100644 index 0000000..4f3bdab --- /dev/null +++ b/lib/libtle_l4p/tcp_ofo.h @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2016 Intel Corporation. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _TCP_OFO_H_ +#define _TCP_OFO_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +struct ofodb { + uint32_t nb_elem; + uint32_t nb_max; + union seqlen sl; + struct rte_mbuf **obj; +}; + +struct ofo { + uint32_t nb_elem; + uint32_t nb_max; + struct ofodb db[]; +}; + +static inline void +_ofodb_free(struct ofodb *db) +{ + uint32_t i; + + for (i = 0; i != db->nb_elem; i++) + rte_pktmbuf_free(db->obj[i]); +} + +static inline void +_ofo_remove(struct ofo *ofo, uint32_t pos, uint32_t num) +{ + uint32_t i, n; + + n = ofo->nb_elem - num - pos; + for (i = 0; i != n; i++) + ofo->db[pos + i] = ofo->db[pos + num + i]; + ofo->nb_elem -= num; +} + +static inline void +tcp_ofo_reset(struct ofo *ofo) +{ + uint32_t i; + + for (i = 0; i != ofo->nb_elem; i++) + _ofodb_free(&ofo->db[i]); + + _ofo_remove(ofo, 0, ofo->nb_elem); +} + +static inline uint32_t +_ofo_insert_new(struct ofo *ofo, uint32_t pos, union seqlen *sl, + struct rte_mbuf *mb[], uint32_t num) +{ + uint32_t i, n, plen; + struct ofodb *db; + + n = ofo->nb_elem; + + /* out of space */ + if (n == ofo->nb_max) + return 0; + + /* allocate new one */ + db = ofo->db + n; + ofo->nb_elem = n + 1; + + /* insert into a proper position. */ + for (i = n; i != pos; i--) + ofo->db[i] = ofo->db[i - 1]; + + /* fill new block */ + n = RTE_MIN(db->nb_max, num); + for (i = 0; i != n; i++) + db->obj[i] = mb[i]; + + /* can't queue some packets. */ + plen = 0; + for (i = n; i != num; i++) + plen += mb[i]->pkt_len; + + db->nb_elem = n; + db->sl.seq = sl->seq; + db->sl.len = sl->len - plen; + + sl->seq += db->sl.len; + sl->len -= db->sl.len; + return n; +} + +static inline uint32_t +_ofo_insert_right(struct ofo *ofo, uint32_t pos, union seqlen *sl, + struct rte_mbuf *mb[], uint32_t num) +{ + uint32_t i, j, k, n; + uint32_t end, plen, skip; + struct ofodb *db; + + db = ofo->db + pos; + end = db->sl.seq + db->sl.len; + + skip = end - sl->seq; + + /* skip overlapping packets */ + for (i = 0, n = skip; i != num && n != 0; i++, n -= plen) { + + plen = mb[i]->pkt_len; + if (n < plen) { + /* adjust partially overlapped packet. */ + rte_pktmbuf_adj(mb[i], plen - n); + break; + } + } + + /* free totally overlapped packets. */ + for (j = 0; j != i; j++) + rte_pktmbuf_free(mb[j]); + + /* copy non-overlapping mbufs */ + k = db->nb_elem; + n = RTE_MIN(db->nb_max - k, num - i); + + plen = 0; + for (j = 0; j != n; j++) { + db->obj[k + j] = mb[i + j]; + plen += mb[i + j]->pkt_len; + } + + db->nb_elem += n; + db->sl.len += plen; + + plen += skip; + sl->len -= plen; + sl->seq += plen; + return n + i; +} + +static inline uint32_t +_ofo_step(struct ofo *ofo, union seqlen *sl, struct rte_mbuf *mb[], + uint32_t num) +{ + uint32_t i, n, end, lo, ro; + struct ofodb *db; + + db = NULL; + end = sl->seq + sl->len; + n = ofo->nb_elem; + + /* + * start from the right side, assume that after some gap, + * we keep receiving packets in order. + */ + for (i = n; i-- != 0; ) { + db = ofo->db + i; + if (tcp_seq_leq(db->sl.seq, sl->seq)) + break; + } + + /* new db required */ + if ((int32_t)i < 0 || tcp_seq_lt(db->sl.seq + db->sl.len, sl->seq)) + return _ofo_insert_new(ofo, i + 1, sl, mb, num); + + /* new one is right adjacent, or overlap */ + + ro = sl->seq - db->sl.seq; + lo = end - db->sl.seq; + + /* new one is completely overlapped by old one */ + if (lo <= db->sl.len) + return 0; + + /* either overlap OR (adjacent AND some free space remains) */ + if (ro < db->sl.len || db->nb_elem != db->nb_max) + return _ofo_insert_right(ofo, i, sl, mb, num); + + /* adjacent, no free space in current block */ + return _ofo_insert_new(ofo, i + 1, sl, mb, num); +} + +static inline void +_ofo_compact(struct ofo *ofo) +{ + uint32_t i, j, n, ro; + struct ofodb *db; + + for (i = 0; i < ofo->nb_elem; i = j) { + + for (j = i + 1; j != ofo->nb_elem; j++) { + + /* no intersection */ + ro = ofo->db[j].sl.seq - ofo->db[i].sl.seq; + if (ro > ofo->db[i].sl.len) + break; + + db = ofo->db + j; + n = _ofo_insert_right(ofo, i, &db->sl, db->obj, + db->nb_elem); + if (n < db->nb_elem) { + db->nb_elem -= n; + break; + } + } + + n = j - i - 1; + if (n != 0) + _ofo_remove(ofo, i + 1, n); + } +} + +static inline uint32_t +_ofodb_enqueue(struct rte_ring *r, const struct ofodb *db, union seqlen *sl) +{ + uint32_t n, num; + + num = db->nb_elem; + sl->raw = db->sl.raw; + n = rte_ring_enqueue_burst(r, (void * const *)db->obj, num); + + sl->len -= tcp_mbuf_seq_free(db->obj + n, num - n); + return num - n; +} + +struct ofo * +tcp_ofo_alloc(uint32_t nbufs, int32_t socket); + +void +tcp_ofo_free(struct ofo *ofo); + +#ifdef __cplusplus +} +#endif + +#endif /* _TCP_OFO_H_ */ -- cgit 1.2.3-korg