From c4c44906536c07fd3d684175db6a5dae05682947 Mon Sep 17 00:00:00 2001 From: Mohammad Abdul Awal Date: Fri, 3 Mar 2017 17:38:14 +0000 Subject: implement sw segmentation for tcp Change-Id: Ibe3ac4b401ea9c7680ab5d3e8c73557d95402ff2 Signed-off-by: Mohammad Abdul Awal --- lib/libtle_l4p/tcp_tx_seg.h | 114 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 lib/libtle_l4p/tcp_tx_seg.h (limited to 'lib/libtle_l4p/tcp_tx_seg.h') diff --git a/lib/libtle_l4p/tcp_tx_seg.h b/lib/libtle_l4p/tcp_tx_seg.h new file mode 100644 index 0000000..3a80fdd --- /dev/null +++ b/lib/libtle_l4p/tcp_tx_seg.h @@ -0,0 +1,114 @@ +/* + * 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_TX_SEG_H_ +#define _TCP_TX_SEG_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +static inline void +free_segments(struct rte_mbuf *mb[], uint32_t num) +{ + uint32_t i; + + for (i = 0; i != num; i++) + rte_pktmbuf_free(mb[i]); +} + +static inline int32_t +tcp_segmentation(struct rte_mbuf *mbin, struct rte_mbuf *mbout[], uint16_t num, + const struct tle_dest *dst, uint16_t mss) +{ + struct rte_mbuf *in_seg = NULL; + uint32_t nbseg, in_seg_data_pos; + uint32_t more_in_segs; + + in_seg = mbin; + in_seg_data_pos = 0; + nbseg = 0; + + /* Check that pkts_out is big enough to hold all fragments */ + if (mss * num < (uint16_t)mbin->pkt_len) + return -ENOSPC; + + more_in_segs = 1; + while (more_in_segs) { + struct rte_mbuf *out_pkt = NULL, *out_seg_prev = NULL; + uint32_t more_out_segs; + + /* Allocate direct buffer */ + out_pkt = rte_pktmbuf_alloc(dst->head_mp); + if (out_pkt == NULL) { + free_segments(mbout, nbseg); + return -ENOMEM; + } + + out_seg_prev = out_pkt; + more_out_segs = 1; + while (more_out_segs && more_in_segs) { + struct rte_mbuf *out_seg = NULL; + uint32_t len; + + /* Allocate indirect buffer */ + out_seg = rte_pktmbuf_alloc(dst->head_mp); + if (out_seg == NULL) { + rte_pktmbuf_free(out_pkt); + free_segments(mbout, nbseg); + return -ENOMEM; + } + out_seg_prev->next = out_seg; + out_seg_prev = out_seg; + + /* Prepare indirect buffer */ + rte_pktmbuf_attach(out_seg, in_seg); + len = mss; + if (len > (in_seg->data_len - in_seg_data_pos)) + len = in_seg->data_len - in_seg_data_pos; + + out_seg->data_off = in_seg->data_off + in_seg_data_pos; + out_seg->data_len = (uint16_t)len; + out_pkt->pkt_len = (uint16_t)(len + out_pkt->pkt_len); + out_pkt->nb_segs += 1; + in_seg_data_pos += len; + + /* Current output packet (i.e. fragment) done ? */ + if (out_pkt->pkt_len >= mss) + more_out_segs = 0; + + /* Current input segment done ? */ + if (in_seg_data_pos == in_seg->data_len) { + in_seg = in_seg->next; + in_seg_data_pos = 0; + + if (in_seg == NULL) + more_in_segs = 0; + } + } + + /* Write the segment to the output list */ + mbout[nbseg] = out_pkt; + nbseg++; + } + + return nbseg; +} + +#ifdef __cplusplus +} +#endif + +#endif /* _TCP_TX_SEG_H_ */ -- cgit 1.2.3-korg