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