]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | /* SPDX-License-Identifier: BSD-3-Clause |
2 | * Copyright(c) 2010-2014 Intel Corporation | |
7c673cae FG |
3 | */ |
4 | ||
5 | #include <stddef.h> | |
6 | ||
7 | #include <rte_debug.h> | |
8 | ||
9 | #include "ip_frag_common.h" | |
10 | ||
11 | /* | |
12 | * Reassemble fragments into one packet. | |
13 | */ | |
14 | struct rte_mbuf * | |
15 | ipv4_frag_reassemble(struct ip_frag_pkt *fp) | |
16 | { | |
17 | struct ipv4_hdr *ip_hdr; | |
18 | struct rte_mbuf *m, *prev; | |
19 | uint32_t i, n, ofs, first_len; | |
20 | uint32_t curr_idx = 0; | |
21 | ||
22 | first_len = fp->frags[IP_FIRST_FRAG_IDX].len; | |
23 | n = fp->last_idx - 1; | |
24 | ||
25 | /*start from the last fragment. */ | |
26 | m = fp->frags[IP_LAST_FRAG_IDX].mb; | |
27 | ofs = fp->frags[IP_LAST_FRAG_IDX].ofs; | |
28 | curr_idx = IP_LAST_FRAG_IDX; | |
29 | ||
30 | while (ofs != first_len) { | |
31 | ||
32 | prev = m; | |
33 | ||
34 | for (i = n; i != IP_FIRST_FRAG_IDX && ofs != first_len; i--) { | |
35 | ||
36 | /* previous fragment found. */ | |
37 | if(fp->frags[i].ofs + fp->frags[i].len == ofs) { | |
38 | ||
9f95a23c TL |
39 | RTE_ASSERT(curr_idx != i); |
40 | ||
7c673cae | 41 | /* adjust start of the last fragment data. */ |
9f95a23c TL |
42 | rte_pktmbuf_adj(m, |
43 | (uint16_t)(m->l2_len + m->l3_len)); | |
7c673cae FG |
44 | rte_pktmbuf_chain(fp->frags[i].mb, m); |
45 | ||
46 | /* this mbuf should not be accessed directly */ | |
47 | fp->frags[curr_idx].mb = NULL; | |
48 | curr_idx = i; | |
49 | ||
50 | /* update our last fragment and offset. */ | |
51 | m = fp->frags[i].mb; | |
52 | ofs = fp->frags[i].ofs; | |
53 | } | |
54 | } | |
55 | ||
56 | /* error - hole in the packet. */ | |
57 | if (m == prev) { | |
58 | return NULL; | |
59 | } | |
60 | } | |
61 | ||
62 | /* chain with the first fragment. */ | |
63 | rte_pktmbuf_adj(m, (uint16_t)(m->l2_len + m->l3_len)); | |
64 | rte_pktmbuf_chain(fp->frags[IP_FIRST_FRAG_IDX].mb, m); | |
11fdf7f2 | 65 | fp->frags[curr_idx].mb = NULL; |
7c673cae | 66 | m = fp->frags[IP_FIRST_FRAG_IDX].mb; |
11fdf7f2 | 67 | fp->frags[IP_FIRST_FRAG_IDX].mb = NULL; |
7c673cae FG |
68 | |
69 | /* update mbuf fields for reassembled packet. */ | |
70 | m->ol_flags |= PKT_TX_IP_CKSUM; | |
71 | ||
11fdf7f2 | 72 | /* update ipv4 header for the reassembled packet */ |
7c673cae FG |
73 | ip_hdr = rte_pktmbuf_mtod_offset(m, struct ipv4_hdr *, m->l2_len); |
74 | ||
75 | ip_hdr->total_length = rte_cpu_to_be_16((uint16_t)(fp->total_size + | |
76 | m->l3_len)); | |
77 | ip_hdr->fragment_offset = (uint16_t)(ip_hdr->fragment_offset & | |
78 | rte_cpu_to_be_16(IPV4_HDR_DF_FLAG)); | |
79 | ip_hdr->hdr_checksum = 0; | |
80 | ||
81 | return m; | |
82 | } | |
83 | ||
84 | /* | |
85 | * Process new mbuf with fragment of IPV4 packet. | |
86 | * Incoming mbuf should have it's l2_len/l3_len fields setuped correclty. | |
87 | * @param tbl | |
88 | * Table where to lookup/add the fragmented packet. | |
89 | * @param mb | |
90 | * Incoming mbuf with IPV4 fragment. | |
91 | * @param tms | |
92 | * Fragment arrival timestamp. | |
93 | * @param ip_hdr | |
94 | * Pointer to the IPV4 header inside the fragment. | |
95 | * @return | |
11fdf7f2 TL |
96 | * Pointer to mbuf for reassembled packet, or NULL if: |
97 | * - an error occurred. | |
7c673cae FG |
98 | * - not all fragments of the packet are collected yet. |
99 | */ | |
100 | struct rte_mbuf * | |
101 | rte_ipv4_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl, | |
9f95a23c TL |
102 | struct rte_ip_frag_death_row *dr, struct rte_mbuf *mb, uint64_t tms, |
103 | struct ipv4_hdr *ip_hdr) | |
7c673cae FG |
104 | { |
105 | struct ip_frag_pkt *fp; | |
106 | struct ip_frag_key key; | |
107 | const unaligned_uint64_t *psd; | |
7c673cae | 108 | uint16_t flag_offset, ip_ofs, ip_flag; |
9f95a23c | 109 | int32_t ip_len; |
7c673cae FG |
110 | |
111 | flag_offset = rte_be_to_cpu_16(ip_hdr->fragment_offset); | |
112 | ip_ofs = (uint16_t)(flag_offset & IPV4_HDR_OFFSET_MASK); | |
113 | ip_flag = (uint16_t)(flag_offset & IPV4_HDR_MF_FLAG); | |
114 | ||
115 | psd = (unaligned_uint64_t *)&ip_hdr->src_addr; | |
116 | /* use first 8 bytes only */ | |
117 | key.src_dst[0] = psd[0]; | |
118 | key.id = ip_hdr->packet_id; | |
119 | key.key_len = IPV4_KEYLEN; | |
120 | ||
121 | ip_ofs *= IPV4_HDR_OFFSET_UNITS; | |
9f95a23c | 122 | ip_len = rte_be_to_cpu_16(ip_hdr->total_length) - mb->l3_len; |
7c673cae FG |
123 | |
124 | IP_FRAG_LOG(DEBUG, "%s:%d:\n" | |
125 | "mbuf: %p, tms: %" PRIu64 | |
9f95a23c | 126 | ", key: <%" PRIx64 ", %#x>, ofs: %u, len: %d, flags: %#x\n" |
7c673cae FG |
127 | "tbl: %p, max_cycles: %" PRIu64 ", entry_mask: %#x, " |
128 | "max_entries: %u, use_entries: %u\n\n", | |
129 | __func__, __LINE__, | |
130 | mb, tms, key.src_dst[0], key.id, ip_ofs, ip_len, ip_flag, | |
131 | tbl, tbl->max_cycles, tbl->entry_mask, tbl->max_entries, | |
132 | tbl->use_entries); | |
133 | ||
9f95a23c TL |
134 | /* check that fragment length is greater then zero. */ |
135 | if (ip_len <= 0) { | |
136 | IP_FRAG_MBUF2DR(dr, mb); | |
137 | return NULL; | |
138 | } | |
139 | ||
7c673cae FG |
140 | /* try to find/add entry into the fragment's table. */ |
141 | if ((fp = ip_frag_find(tbl, dr, &key, tms)) == NULL) { | |
142 | IP_FRAG_MBUF2DR(dr, mb); | |
143 | return NULL; | |
144 | } | |
145 | ||
146 | IP_FRAG_LOG(DEBUG, "%s:%d:\n" | |
147 | "tbl: %p, max_entries: %u, use_entries: %u\n" | |
148 | "ipv4_frag_pkt: %p, key: <%" PRIx64 ", %#x>, start: %" PRIu64 | |
149 | ", total_size: %u, frag_size: %u, last_idx: %u\n\n", | |
150 | __func__, __LINE__, | |
151 | tbl, tbl->max_entries, tbl->use_entries, | |
152 | fp, fp->key.src_dst[0], fp->key.id, fp->start, | |
153 | fp->total_size, fp->frag_size, fp->last_idx); | |
154 | ||
155 | ||
156 | /* process the fragmented packet. */ | |
157 | mb = ip_frag_process(fp, dr, mb, ip_ofs, ip_len, ip_flag); | |
158 | ip_frag_inuse(tbl, fp); | |
159 | ||
160 | IP_FRAG_LOG(DEBUG, "%s:%d:\n" | |
161 | "mbuf: %p\n" | |
162 | "tbl: %p, max_entries: %u, use_entries: %u\n" | |
163 | "ipv4_frag_pkt: %p, key: <%" PRIx64 ", %#x>, start: %" PRIu64 | |
164 | ", total_size: %u, frag_size: %u, last_idx: %u\n\n", | |
165 | __func__, __LINE__, mb, | |
166 | tbl, tbl->max_entries, tbl->use_entries, | |
167 | fp, fp->key.src_dst[0], fp->key.id, fp->start, | |
168 | fp->total_size, fp->frag_size, fp->last_idx); | |
169 | ||
170 | return mb; | |
171 | } |