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