]>
git.proxmox.com Git - ceph.git/blob - ceph/src/seastar/dpdk/lib/librte_ip_frag/rte_ipv6_reassembly.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2014 Intel Corporation
7 #include <rte_memcpy.h>
9 #include "ip_frag_common.h"
15 * Implementation of IPv6 reassembly.
20 ip_frag_memmove(char *dst
, char *src
, int len
)
24 /* go backwards to make sure we don't overwrite anything important */
25 for (i
= len
- 1; i
>= 0; i
--)
30 * Reassemble fragments into one packet.
33 ipv6_frag_reassemble(struct ip_frag_pkt
*fp
)
35 struct ipv6_hdr
*ip_hdr
;
36 struct ipv6_extension_fragment
*frag_hdr
;
37 struct rte_mbuf
*m
, *prev
;
38 uint32_t i
, n
, ofs
, first_len
;
39 uint32_t last_len
, move_len
, payload_len
;
40 uint32_t curr_idx
= 0;
42 first_len
= fp
->frags
[IP_FIRST_FRAG_IDX
].len
;
45 /*start from the last fragment. */
46 m
= fp
->frags
[IP_LAST_FRAG_IDX
].mb
;
47 ofs
= fp
->frags
[IP_LAST_FRAG_IDX
].ofs
;
48 last_len
= fp
->frags
[IP_LAST_FRAG_IDX
].len
;
49 curr_idx
= IP_LAST_FRAG_IDX
;
51 payload_len
= ofs
+ last_len
;
53 while (ofs
!= first_len
) {
57 for (i
= n
; i
!= IP_FIRST_FRAG_IDX
&& ofs
!= first_len
; i
--) {
59 /* previous fragment found. */
60 if (fp
->frags
[i
].ofs
+ fp
->frags
[i
].len
== ofs
) {
62 RTE_ASSERT(curr_idx
!= i
);
64 /* adjust start of the last fragment data. */
66 (uint16_t)(m
->l2_len
+ m
->l3_len
));
67 rte_pktmbuf_chain(fp
->frags
[i
].mb
, m
);
69 /* this mbuf should not be accessed directly */
70 fp
->frags
[curr_idx
].mb
= NULL
;
73 /* update our last fragment and offset. */
75 ofs
= fp
->frags
[i
].ofs
;
79 /* error - hole in the packet. */
85 /* chain with the first fragment. */
86 rte_pktmbuf_adj(m
, (uint16_t)(m
->l2_len
+ m
->l3_len
));
87 rte_pktmbuf_chain(fp
->frags
[IP_FIRST_FRAG_IDX
].mb
, m
);
88 fp
->frags
[curr_idx
].mb
= NULL
;
89 m
= fp
->frags
[IP_FIRST_FRAG_IDX
].mb
;
90 fp
->frags
[IP_FIRST_FRAG_IDX
].mb
= NULL
;
92 /* update mbuf fields for reassembled packet. */
93 m
->ol_flags
|= PKT_TX_IP_CKSUM
;
95 /* update ipv6 header for the reassembled datagram */
96 ip_hdr
= rte_pktmbuf_mtod_offset(m
, struct ipv6_hdr
*, m
->l2_len
);
98 ip_hdr
->payload_len
= rte_cpu_to_be_16(payload_len
);
101 * remove fragmentation header. note that per RFC2460, we need to update
102 * the last non-fragmentable header with the "next header" field to contain
103 * type of the first fragmentable header, but we currently don't support
104 * other headers, so we assume there are no other headers and thus update
105 * the main IPv6 header instead.
107 move_len
= m
->l2_len
+ m
->l3_len
- sizeof(*frag_hdr
);
108 frag_hdr
= (struct ipv6_extension_fragment
*) (ip_hdr
+ 1);
109 ip_hdr
->proto
= frag_hdr
->next_header
;
111 ip_frag_memmove(rte_pktmbuf_mtod_offset(m
, char *, sizeof(*frag_hdr
)),
112 rte_pktmbuf_mtod(m
, char*), move_len
);
114 rte_pktmbuf_adj(m
, sizeof(*frag_hdr
));
120 * Process new mbuf with fragment of IPV6 datagram.
121 * Incoming mbuf should have its l2_len/l3_len fields setup correctly.
123 * Table where to lookup/add the fragmented packet.
125 * Incoming mbuf with IPV6 fragment.
127 * Fragment arrival timestamp.
129 * Pointer to the IPV6 header.
131 * Pointer to the IPV6 fragment extension header.
133 * Pointer to mbuf for reassembled packet, or NULL if:
134 * - an error occurred.
135 * - not all fragments of the packet are collected yet.
137 #define MORE_FRAGS(x) (((x) & 0x100) >> 8)
138 #define FRAG_OFFSET(x) (rte_cpu_to_be_16(x) >> 3)
140 rte_ipv6_frag_reassemble_packet(struct rte_ip_frag_tbl
*tbl
,
141 struct rte_ip_frag_death_row
*dr
, struct rte_mbuf
*mb
, uint64_t tms
,
142 struct ipv6_hdr
*ip_hdr
, struct ipv6_extension_fragment
*frag_hdr
)
144 struct ip_frag_pkt
*fp
;
145 struct ip_frag_key key
;
149 rte_memcpy(&key
.src_dst
[0], ip_hdr
->src_addr
, 16);
150 rte_memcpy(&key
.src_dst
[2], ip_hdr
->dst_addr
, 16);
152 key
.id
= frag_hdr
->id
;
153 key
.key_len
= IPV6_KEYLEN
;
155 ip_ofs
= FRAG_OFFSET(frag_hdr
->frag_data
) * 8;
158 * as per RFC2460, payload length contains all extension headers
160 * since we don't support anything but frag headers,
161 * this is what we remove from the payload len.
163 ip_len
= rte_be_to_cpu_16(ip_hdr
->payload_len
) - sizeof(*frag_hdr
);
165 IP_FRAG_LOG(DEBUG
, "%s:%d:\n"
166 "mbuf: %p, tms: %" PRIu64
167 ", key: <" IPv6_KEY_BYTES_FMT
", %#x>, "
168 "ofs: %u, len: %d, flags: %#x\n"
169 "tbl: %p, max_cycles: %" PRIu64
", entry_mask: %#x, "
170 "max_entries: %u, use_entries: %u\n\n",
172 mb
, tms
, IPv6_KEY_BYTES(key
.src_dst
), key
.id
, ip_ofs
, ip_len
,
173 RTE_IPV6_GET_MF(frag_hdr
->frag_data
),
174 tbl
, tbl
->max_cycles
, tbl
->entry_mask
, tbl
->max_entries
,
177 /* check that fragment length is greater then zero. */
179 IP_FRAG_MBUF2DR(dr
, mb
);
183 /* try to find/add entry into the fragment's table. */
184 fp
= ip_frag_find(tbl
, dr
, &key
, tms
);
186 IP_FRAG_MBUF2DR(dr
, mb
);
190 IP_FRAG_LOG(DEBUG
, "%s:%d:\n"
191 "tbl: %p, max_entries: %u, use_entries: %u\n"
192 "ipv6_frag_pkt: %p, key: <" IPv6_KEY_BYTES_FMT
", %#x>, start: %" PRIu64
193 ", total_size: %u, frag_size: %u, last_idx: %u\n\n",
195 tbl
, tbl
->max_entries
, tbl
->use_entries
,
196 fp
, IPv6_KEY_BYTES(fp
->key
.src_dst
), fp
->key
.id
, fp
->start
,
197 fp
->total_size
, fp
->frag_size
, fp
->last_idx
);
200 /* process the fragmented packet. */
201 mb
= ip_frag_process(fp
, dr
, mb
, ip_ofs
, ip_len
,
202 MORE_FRAGS(frag_hdr
->frag_data
));
203 ip_frag_inuse(tbl
, fp
);
205 IP_FRAG_LOG(DEBUG
, "%s:%d:\n"
207 "tbl: %p, max_entries: %u, use_entries: %u\n"
208 "ipv6_frag_pkt: %p, key: <" IPv6_KEY_BYTES_FMT
", %#x>, start: %" PRIu64
209 ", total_size: %u, frag_size: %u, last_idx: %u\n\n",
210 __func__
, __LINE__
, mb
,
211 tbl
, tbl
->max_entries
, tbl
->use_entries
,
212 fp
, IPv6_KEY_BYTES(fp
->key
.src_dst
), fp
->key
.id
, fp
->start
,
213 fp
->total_size
, fp
->frag_size
, fp
->last_idx
);