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