]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | /* SPDX-License-Identifier: BSD-3-Clause |
2 | * Copyright(c) 2017 Intel Corporation | |
3 | */ | |
4 | ||
5 | #include "gso_common.h" | |
6 | #include "gso_tcp4.h" | |
7 | ||
8 | static void | |
9 | update_ipv4_tcp_headers(struct rte_mbuf *pkt, uint8_t ipid_delta, | |
10 | struct rte_mbuf **segs, uint16_t nb_segs) | |
11 | { | |
f67539c2 TL |
12 | struct rte_ipv4_hdr *ipv4_hdr; |
13 | struct rte_tcp_hdr *tcp_hdr; | |
11fdf7f2 TL |
14 | uint32_t sent_seq; |
15 | uint16_t id, tail_idx, i; | |
16 | uint16_t l3_offset = pkt->l2_len; | |
17 | uint16_t l4_offset = l3_offset + pkt->l3_len; | |
18 | ||
f67539c2 | 19 | ipv4_hdr = (struct rte_ipv4_hdr *)(rte_pktmbuf_mtod(pkt, char*) + |
11fdf7f2 | 20 | l3_offset); |
f67539c2 | 21 | tcp_hdr = (struct rte_tcp_hdr *)((char *)ipv4_hdr + pkt->l3_len); |
11fdf7f2 TL |
22 | id = rte_be_to_cpu_16(ipv4_hdr->packet_id); |
23 | sent_seq = rte_be_to_cpu_32(tcp_hdr->sent_seq); | |
24 | tail_idx = nb_segs - 1; | |
25 | ||
26 | for (i = 0; i < nb_segs; i++) { | |
27 | update_ipv4_header(segs[i], l3_offset, id); | |
28 | update_tcp_header(segs[i], l4_offset, sent_seq, i < tail_idx); | |
29 | id += ipid_delta; | |
30 | sent_seq += (segs[i]->pkt_len - segs[i]->data_len); | |
31 | } | |
32 | } | |
33 | ||
34 | int | |
35 | gso_tcp4_segment(struct rte_mbuf *pkt, | |
36 | uint16_t gso_size, | |
37 | uint8_t ipid_delta, | |
38 | struct rte_mempool *direct_pool, | |
39 | struct rte_mempool *indirect_pool, | |
40 | struct rte_mbuf **pkts_out, | |
41 | uint16_t nb_pkts_out) | |
42 | { | |
f67539c2 | 43 | struct rte_ipv4_hdr *ipv4_hdr; |
11fdf7f2 TL |
44 | uint16_t pyld_unit_size, hdr_offset; |
45 | uint16_t frag_off; | |
46 | int ret; | |
47 | ||
48 | /* Don't process the fragmented packet */ | |
f67539c2 | 49 | ipv4_hdr = (struct rte_ipv4_hdr *)(rte_pktmbuf_mtod(pkt, char *) + |
11fdf7f2 TL |
50 | pkt->l2_len); |
51 | frag_off = rte_be_to_cpu_16(ipv4_hdr->fragment_offset); | |
52 | if (unlikely(IS_FRAGMENTED(frag_off))) { | |
53 | pkts_out[0] = pkt; | |
54 | return 1; | |
55 | } | |
56 | ||
57 | /* Don't process the packet without data */ | |
58 | hdr_offset = pkt->l2_len + pkt->l3_len + pkt->l4_len; | |
59 | if (unlikely(hdr_offset >= pkt->pkt_len)) { | |
60 | pkts_out[0] = pkt; | |
61 | return 1; | |
62 | } | |
63 | ||
64 | pyld_unit_size = gso_size - hdr_offset; | |
65 | ||
66 | /* Segment the payload */ | |
67 | ret = gso_do_segment(pkt, hdr_offset, pyld_unit_size, direct_pool, | |
68 | indirect_pool, pkts_out, nb_pkts_out); | |
69 | if (ret > 1) | |
70 | update_ipv4_tcp_headers(pkt, ipid_delta, pkts_out, ret); | |
71 | ||
72 | return ret; | |
73 | } |