1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10 /**************************************************************************/
11 /**************************************************************************/
12 /** */
13 /** NetX Component */
14 /** */
15 /** Internet Protocol version 6 (IPv6) */
16 /** */
17 /**************************************************************************/
18 /**************************************************************************/
19 #define NX_SOURCE_CODE
20
21
22 /* Include necessary system files. */
23
24 #include "tx_api.h"
25 #include "nx_api.h"
26 #include "nx_ipv6.h"
27
28
29 #if defined(FEATURE_NX_IPV6) && !defined(NX_DISABLE_FRAGMENTATION)
30
31 /* Define the status 'bits' of the copy flag field. */
32 #define PACKET_MORE_TO_COPY 1
33 #define PACKET_ADD_BUFFER 2
34 #define PACKET_COPY_DONE 4
35 /**************************************************************************/
36 /* */
37 /* FUNCTION RELEASE */
38 /* */
39 /* _nx_ipv6_packet_copy PORTABLE C */
40 /* 6.1 */
41 /* AUTHOR */
42 /* */
43 /* Yuxin Zhou, Microsoft Corporation */
44 /* */
45 /* DESCRIPTION */
46 /* */
47 /* This internal function copies packet data between packets. */
48 /* */
49 /* INPUT */
50 /* */
51 /* source_pkt_head Pointer to source packet chain. */
52 /* dest_pkt_head Pointer to destination packet chain. */
53 /* size Number of bytes to copy. */
54 /* */
55 /* OUTPUT */
56 /* */
57 /* NX_SUCCESS Successful completion */
58 /* NX_NOT_SUCCESSFUL Error with packet copy */
59 /* */
60 /* CALLS */
61 /* */
62 /* None */
63 /* */
64 /* CALLED BY */
65 /* */
66 /* _nx_ipv6_fragment_process */
67 /* */
68 /* */
69 /* NOTE */
70 /* */
71 /* None */
72 /* */
73 /* RELEASE HISTORY */
74 /* */
75 /* DATE NAME DESCRIPTION */
76 /* */
77 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
78 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
79 /* resulting in version 6.1 */
80 /* */
81 /**************************************************************************/
_nx_ipv6_packet_copy(NX_PACKET * source_pkt_head,NX_PACKET * dest_pkt_head,UINT size)82 UINT _nx_ipv6_packet_copy(NX_PACKET *source_pkt_head, NX_PACKET *dest_pkt_head, UINT size)
83 {
84
85 UINT bytes_remaining;
86 NX_PACKET *source_pkt, *dest_pkt;
87 UINT bytes_to_copy;
88 ULONG *source_ptr, *dest_ptr;
89 UCHAR *source_byte, *dest_byte;
90 UINT flag;
91
92
93 /* Number of bytes to be copied. */
94 bytes_remaining = size;
95
96 /* Obtain points to the source and destination packets. */
97 source_pkt = source_pkt_head -> nx_packet_last;
98 dest_pkt = dest_pkt_head -> nx_packet_last;
99
100 while (bytes_remaining > 0)
101 {
102
103 /* Make sure source or destination packets are valid. */
104 if ((source_pkt == NX_NULL) || (dest_pkt == NX_NULL))
105 {
106 return(NX_NOT_SUCCESSFUL);
107 }
108
109 /*
110 figure out the amount of bytes we can copy in this iteration.
111 At the end of the interation, we shall be able to "close" either the
112 source packet or the destination packet.
113 */
114
115 bytes_to_copy = bytes_remaining;
116
117 flag = PACKET_COPY_DONE;
118
119 /* Check if the source packet is running out of data. */
120 /*lint -e{946} -e{947} suppress pointer subtraction, since it is necessary. */
121 if (bytes_to_copy > (UINT)(source_pkt -> nx_packet_append_ptr - source_pkt -> nx_packet_prepend_ptr))
122 {
123
124 /* It is. Set flag to PACKET_MORE_TO_COPY, indicating that there is more to be copied
125 from the following buffer. */
126 /*lint -e{946} -e{947} suppress pointer subtraction, since it is necessary. */
127 bytes_to_copy = (UINT)(source_pkt -> nx_packet_append_ptr - source_pkt -> nx_packet_prepend_ptr);
128 flag = PACKET_MORE_TO_COPY;
129 }
130
131 /* Check if the destination packet is running ouf of space. */
132 /*lint -e{946} -e{947} suppress pointer subtraction, since it is necessary. */
133 if (bytes_to_copy > (UINT)(dest_pkt -> nx_packet_data_end - dest_pkt -> nx_packet_append_ptr))
134 {
135
136 /* It is. Set the 2nd bit in the flag to indicate that at the the end of the
137 iteration we will need to chain another buffer on the destination packet.*/
138 /*lint -e{946} -e{947} suppress pointer subtraction, since it is necessary. */
139 bytes_to_copy = (UINT)(dest_pkt -> nx_packet_data_end - dest_pkt -> nx_packet_append_ptr);
140 flag = PACKET_ADD_BUFFER;
141 }
142
143 /* Adjust packet pointers. */
144 /*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary */
145 dest_ptr = (ULONG *)dest_pkt -> nx_packet_append_ptr;
146 dest_pkt -> nx_packet_append_ptr += bytes_to_copy;
147 dest_pkt -> nx_packet_length -= bytes_to_copy;
148
149 /*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary */
150 source_ptr = (ULONG *)source_pkt -> nx_packet_prepend_ptr;
151 source_pkt -> nx_packet_prepend_ptr += bytes_to_copy;
152
153 while (bytes_to_copy)
154 {
155 /* Loop unrolling: copy 32 bytes in one iteration. */
156 switch (bytes_to_copy >> 2)
157 {
158 default:
159 *dest_ptr++ = *source_ptr++;
160 /*lint -e{825} suppress fallthrough, since it is necessary. */ /* fallthrough */
161 case 7:
162 *dest_ptr++ = *source_ptr++;
163 /*lint -e{825} suppress fallthrough, since it is necessary. */ /* fallthrough */
164 case 6:
165 *dest_ptr++ = *source_ptr++;
166 /*lint -e{825} suppress fallthrough, since it is necessary. */ /* fallthrough */
167 case 5:
168 *dest_ptr++ = *source_ptr++;
169 /*lint -e{825} suppress fallthrough, since it is necessary. */ /* fallthrough */
170 case 4:
171 *dest_ptr++ = *source_ptr++;
172 /*lint -e{825} suppress fallthrough, since it is necessary. */ /* fallthrough */
173 case 3:
174 *dest_ptr++ = *source_ptr++;
175 /*lint -e{825} suppress fallthrough, since it is necessary. */ /* fallthrough */
176 case 2:
177 *dest_ptr++ = *source_ptr++;
178 /*lint -e{825} suppress fallthrough, since it is necessary. */ /* fallthrough */
179 case 1:
180 *dest_ptr++ = *source_ptr++;
181 }
182 if (bytes_to_copy >= 32)
183 {
184 bytes_to_copy -= 32;
185 bytes_remaining -= 32;
186 }
187 else
188 {
189
190 /* Copy bytes less than 4. */
191 /*lint --e{928} suppress cast from pointer to pointer, since it is necessary */
192 source_byte = (UCHAR *)source_ptr;
193 dest_byte = (UCHAR *)dest_ptr;
194 switch (bytes_to_copy & 3)
195 {
196 case 3:
197 *dest_byte++ = *source_byte++;
198 /*lint -e{825} suppress fallthrough, since it is necessary. */ /* fallthrough */
199 case 2:
200 *dest_byte++ = *source_byte++;
201 /*lint -e{825} suppress fallthrough, since it is necessary. */ /* fallthrough */
202 case 1:
203 *dest_byte++ = *source_byte++;
204 break;
205 default:
206 break;
207 }
208
209 bytes_remaining -= bytes_to_copy;
210 bytes_to_copy = 0;
211 }
212 }
213
214 /* Check if the flag has been set to more data to copy. */
215 if (flag & PACKET_MORE_TO_COPY)
216 {
217 source_pkt_head -> nx_packet_last = source_pkt -> nx_packet_next;
218 source_pkt = source_pkt_head -> nx_packet_last;
219 }
220
221 /* Check if we need to chain another buffer to the packet chain for more data copy. */
222 if (flag & PACKET_ADD_BUFFER)
223 {
224 dest_pkt_head -> nx_packet_last = dest_pkt -> nx_packet_next;
225 dest_pkt = dest_pkt -> nx_packet_next;
226 }
227
228 /* Check if we are done. */
229 if (flag & PACKET_COPY_DONE)
230 {
231
232 /* We are. */
233 break;
234 }
235 }
236
237 return(NX_SUCCESS);
238 }
239
240
241 #endif /* FEATURE_NX_IPV6 && NX_DISABLE_FRAGMENTATION*/
242
243