ac2b13bbce004792660a18c4662d326c25bdb900
[tldk.git] / lib / libtle_l4p / tcp_tx_seg.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 #ifndef _TCP_TX_SEG_H_
17 #define _TCP_TX_SEG_H_
18
19 #ifdef __cplusplus
20 extern "C" {
21 #endif
22
23 static inline int32_t
24 tcp_segmentation(struct rte_mbuf *mbin, struct rte_mbuf *mbout[], uint16_t num,
25         const struct tle_dest *dst, uint16_t mss)
26 {
27         struct rte_mbuf *in_seg = NULL;
28         uint32_t nbseg, in_seg_data_pos;
29         uint32_t more_in_segs;
30         uint16_t bytes_left;
31
32         in_seg = mbin;
33         in_seg_data_pos = 0;
34         nbseg = 0;
35
36         /* Check that pkts_out is big enough to hold all fragments */
37         if (mss * num < (uint16_t)mbin->pkt_len)
38                 return -ENOSPC;
39
40         more_in_segs = 1;
41         while (more_in_segs) {
42                 struct rte_mbuf *out_pkt = NULL, *out_seg_prev = NULL;
43                 uint32_t more_out_segs;
44
45                 /* Allocate direct buffer */
46                 out_pkt = rte_pktmbuf_alloc(dst->head_mp);
47                 if (out_pkt == NULL) {
48                         free_mbufs(mbout, nbseg);
49                         return -ENOMEM;
50                 }
51
52                 bytes_left = mss;
53                 out_seg_prev = out_pkt;
54                 more_out_segs = 1;
55                 while (more_out_segs && more_in_segs) {
56                         struct rte_mbuf *out_seg = NULL;
57                         uint32_t len;
58
59                         /* Allocate indirect buffer */
60                         out_seg = rte_pktmbuf_alloc(dst->head_mp);
61                         if (out_seg == NULL) {
62                                 rte_pktmbuf_free(out_pkt);
63                                 free_mbufs(mbout, nbseg);
64                                 return -ENOMEM;
65                         }
66                         out_seg_prev->next = out_seg;
67                         out_seg_prev = out_seg;
68
69                         /* Prepare indirect buffer */
70                         rte_pktmbuf_attach(out_seg, in_seg);
71                         len = bytes_left;
72                         if (len > (in_seg->data_len - in_seg_data_pos))
73                                 len = in_seg->data_len - in_seg_data_pos;
74
75                         out_seg->data_off = in_seg->data_off + in_seg_data_pos;
76                         out_seg->data_len = (uint16_t)len;
77                         out_pkt->pkt_len = (uint16_t)(len + out_pkt->pkt_len);
78                         out_pkt->nb_segs += 1;
79                         in_seg_data_pos += len;
80                         bytes_left -= len;
81
82                         /* Current output packet (i.e. fragment) done ? */
83                         if (bytes_left == 0)
84                                 more_out_segs = 0;
85
86                         /* Current input segment done ? */
87                         if (in_seg_data_pos == in_seg->data_len) {
88                                 in_seg = in_seg->next;
89                                 in_seg_data_pos = 0;
90
91                                 if (in_seg == NULL)
92                                         more_in_segs = 0;
93                         }
94                 }
95
96                 /* Write the segment to the output list */
97                 mbout[nbseg] = out_pkt;
98                 nbseg++;
99         }
100
101         return nbseg;
102 }
103
104 #ifdef __cplusplus
105 }
106 #endif
107
108 #endif /* _TCP_TX_SEG_H_ */