1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
/*
* Copyright (c) 2016-2017 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 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;
uint16_t bytes_left;
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_mbufs(mbout, nbseg);
return -ENOMEM;
}
bytes_left = mss;
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_mbufs(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 = bytes_left;
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;
bytes_left -= len;
/* Current output packet (i.e. fragment) done ? */
if (bytes_left == 0)
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_ */
|