1 /* This NetX test concentrates on basic IPv6 fragmentation.  */
2 /* Test sequence:
3  * 1. ip_0 allocate one packets.
4  * 1. ip_0 add the Hop-by-Hop Option, 2 bytes(next header, option length) + 128 bytes(option length).
5  * 1. ip_0 append the data 1000 bytes.
6  * 2. ip_0 discard the packets excpet the header packet, packet length also is 2 + 128 + 1000.
7  * 3. ip_0 call nxd_ip_raw_packet_send to send the packet with Hop-by-Hop Option.
8  * 4. ip_0 call nx_ipv6_fragment_process to fragment packet and send the fragmentation packets.
9  * 5. check if the driver receive fragmentation packet form ip_0.
10  Test pointer:
11  * 1. in _nx_ipv6_packet_copy failure since the next packet of source packet is NX_NULL, cover the following code.
12         if ((source_pkt == NX_NULL) || (dest_pkt == NX_NULL))
13             return(NX_NOT_SUCCESSFUL);
14  * 2. in nx_ipv6_fragment_process failure since _nx_ipv6_packet_copy failure, cover the following code:
15         // For the first packet, the prepend pointer is already at the begining of the IP header.
16         if (_nx_ipv6_packet_copy(source_packet, first_fragment, fragment_size))
17             break;
18 */
19 
20 
21 #include   "tx_api.h"
22 #include   "nx_api.h"
23 #if !defined(NX_DISABLE_FRAGMENTATION) && defined(FEATURE_NX_IPV6)
24 #include   "nx_ipv6.h"
25 #define     DEMO_STACK_SIZE         2048
26 
27 
28 /* Define the ThreadX and NetX object control blocks...  */
29 
30 static TX_THREAD               thread_0;
31 
32 static NX_PACKET_POOL          pool_0;
33 static NX_IP                   ip_0;
34 static NX_IP                   ip_1;
35 
36 static NXD_ADDRESS             ipv6_address_0;
37 static NXD_ADDRESS             ipv6_address_1;
38 
39 
40 /* Define the counters used in the demo application...  */
41 
42 static ULONG                   error_counter;
43 static ULONG                   fragmentation_counter;
44 
45 /* Define thread prototypes.  */
46 
47 static void    thread_0_entry(ULONG thread_input);
48 extern void    test_control_return(UINT status);
49 extern void    _nx_ram_network_driver(struct NX_IP_DRIVER_STRUCT *driver_req);
50 extern UINT    (*advanced_packet_process_callback)(NX_IP *ip_ptr, NX_PACKET *packet_ptr, UINT *operation_ptr, UINT *delay_ptr);
51 static UINT    my_packet_process(NX_IP *ip_ptr, NX_PACKET *packet_ptr, UINT *operation_ptr, UINT *delay_ptr);
52 
53 static CHAR     msg[1500]={'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
54 
55 /* Define what the initial system looks like.  */
56 
57 #ifdef CTEST
test_application_define(void * first_unused_memory)58 VOID test_application_define(void *first_unused_memory)
59 #else
60 void  netx_ipv6_fragmentation_error_test2_application_define(void *first_unused_memory)
61 #endif
62 {
63 
64 CHAR    *pointer;
65 UINT    status;
66 
67 
68     /* Setup the working pointer.  */
69     pointer =  (CHAR *) first_unused_memory;
70 
71     error_counter =  0;
72     fragmentation_counter = 0;
73 
74     /* Create the main thread.  */
75     tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0,
76             pointer, DEMO_STACK_SIZE,
77             3, 3, TX_NO_TIME_SLICE, TX_AUTO_START);
78     pointer =  pointer + DEMO_STACK_SIZE;
79 
80     /* Initialize the NetX system.  */
81     nx_system_initialize();
82 
83     /* Create a packet pool.  */
84     status =  nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", 128, pointer, 128*60);
85     pointer = pointer + 128*60;
86 
87     /* Check for pool creation error.  */
88     if (status)
89         error_counter++;
90 
91     /* Create an IP instance.  */
92     status = nx_ip_create(&ip_0, "NetX IP Instance 0", IP_ADDRESS(1, 2, 3, 4), 0xFFFFF000UL, &pool_0, _nx_ram_network_driver,
93                     pointer, 2048, 1);
94     pointer =  pointer + 2048;
95 
96     /* Create another IP instance.  */
97     status += nx_ip_create(&ip_1, "NetX IP Instance 1", IP_ADDRESS(1, 2, 3, 5), 0xFFFFF000UL, &pool_0, _nx_ram_network_driver,
98                     pointer, 2048, 1);
99     pointer =  pointer + 2048;
100 
101     /* Check for IP create errors.  */
102     if (status)
103         error_counter++;
104 
105     status = nxd_ipv6_enable(&ip_0);
106     status += nxd_ipv6_enable(&ip_1);
107     if (status)
108         error_counter++;
109 
110     /* Enable IP fragmentation logic on both IP instances.  */
111     status =  nx_ip_fragment_enable(&ip_0);
112     status += nx_ip_fragment_enable(&ip_1);
113     if (status)
114         error_counter++;
115 
116     /* Enable IP raw feature on both IP instances.  */
117     status =  nx_ip_raw_packet_enable(&ip_0);
118     status += nx_ip_raw_packet_enable(&ip_1);
119     if (status)
120         error_counter++;
121 
122     status = nxd_icmp_enable(&ip_0);
123     status += nxd_icmp_enable(&ip_1);
124     if (status)
125         error_counter++;
126 
127     /* Set ipv6 version and address.  */
128     ipv6_address_0.nxd_ip_version = NX_IP_VERSION_V6;
129     ipv6_address_0.nxd_ip_address.v6[0] = 0x20010000;
130     ipv6_address_0.nxd_ip_address.v6[1] = 0x00000000;
131     ipv6_address_0.nxd_ip_address.v6[2] = 0x00000000;
132     ipv6_address_0.nxd_ip_address.v6[3] = 0x10000001;
133 
134     ipv6_address_1.nxd_ip_version = NX_IP_VERSION_V6;
135     ipv6_address_1.nxd_ip_address.v6[0] = 0x20010000;
136     ipv6_address_1.nxd_ip_address.v6[1] = 0x00000000;
137     ipv6_address_1.nxd_ip_address.v6[2] = 0x00000000;
138     ipv6_address_1.nxd_ip_address.v6[3] = 0x10000002;
139 
140     /* Set interfaces' address */
141     status += nxd_ipv6_address_set(&ip_0, 0, &ipv6_address_0, 64, NX_NULL);
142     status += nxd_ipv6_address_set(&ip_1, 0, &ipv6_address_1, 64, NX_NULL);
143 
144     if(status)
145         error_counter++;
146 
147 }
148 
149 
150 /* Define the test threads.  */
151 
thread_0_entry(ULONG thread_input)152 static void    thread_0_entry(ULONG thread_input)
153 {
154 
155 UINT        status;
156 UCHAR       data;
157 NX_PACKET   *my_packet;
158 
159 
160     /* Print out some test information banners.  */
161     printf("NetX Test:   IPv6 Fragmentation Error Test2............................");
162 
163     /* Check for earlier error.  */
164     if (error_counter)
165     {
166         printf("ERROR!\n");
167         test_control_return(1);
168     }
169 
170     /* DAD */
171     tx_thread_sleep(5 * NX_IP_PERIODIC_RATE);
172 
173     /* Set the callback function.  */
174     advanced_packet_process_callback = my_packet_process;
175 
176     /* Allocate a packet.  */
177     status =  nx_packet_allocate(&pool_0, &my_packet, NX_IPv6_PACKET, TX_WAIT_FOREVER);
178 
179     /* Check status.  */
180     if (status != NX_SUCCESS)
181     {
182         printf("ERROR!\n");
183         test_control_return(1);
184     }
185 
186     /* Added Hop-by-Hop Options header to let the unfragmentable size exceed one packet.  */
187 
188     /* Added the Next header.  */
189     data = 23;
190     status = nx_packet_data_append(my_packet, &data, 1, &pool_0, NX_IP_PERIODIC_RATE);
191 
192     /* Added the Hdr Ext Len.  */
193     data = 16;
194     status += nx_packet_data_append(my_packet, &data, 1, &pool_0, NX_IP_PERIODIC_RATE);
195 
196     /* Added the Options.  */
197     status += nx_packet_data_append(my_packet, msg, 16 * 8, &pool_0, NX_IP_PERIODIC_RATE);
198 
199     /* Check for error.  */
200     if(status)
201     {
202         printf("ERROR!\n");
203         test_control_return(1);
204     }
205 
206     /* Write ABCs into the packet payload!  */
207     status = nx_packet_data_append(my_packet, msg, 1000, &pool_0, NX_IP_PERIODIC_RATE);
208 
209     /* Check for error.  */
210     if(status)
211     {
212         printf("ERROR!\n");
213         test_control_return(1);
214     }
215 
216     /* Discard the packets except the header packet.  */
217     my_packet -> nx_packet_next = NX_NULL;
218     my_packet -> nx_packet_last = NX_NULL;
219 
220     /* Send the raw packet for Hop-by-Hop Option.  */
221     status = nxd_ip_raw_packet_send(&ip_0, my_packet, &ipv6_address_1, NX_PROTOCOL_NEXT_HEADER_HOP_BY_HOP, 255, NX_IP_NORMAL);
222 
223     /* Check for error.  */
224     if(status)
225     {
226         printf("ERROR!\n");
227         test_control_return(1);
228     }
229 
230     /* Check for error.  */
231     if((error_counter) || (fragmentation_counter))
232     {
233         printf("ERROR!\n");
234         test_control_return(1);
235     }
236     else
237     {
238 
239         printf("SUCCESS!\n");
240         test_control_return(0);
241     }
242 }
243 
my_packet_process(NX_IP * ip_ptr,NX_PACKET * packet_ptr,UINT * operation_ptr,UINT * delay_ptr)244 static UINT    my_packet_process(NX_IP *ip_ptr, NX_PACKET *packet_ptr, UINT *operation_ptr, UINT *delay_ptr)
245 {
246 
247     /* Check if receive IPv6 fragmentation packet from ip_0, except NA and NS(IPv6(40) + NS/NA(32)). */
248     if ((ip_ptr == &ip_0) && (packet_ptr -> nx_packet_length > 72))
249     {
250 
251         /* Updated the packet_counter.  */
252         fragmentation_counter ++;
253     }
254 
255     return NX_TRUE;
256 }
257 
258 #else
259 extern void    test_control_return(UINT status);
260 
261 #ifdef CTEST
test_application_define(void * first_unused_memory)262 VOID test_application_define(void *first_unused_memory)
263 #else
264 void netx_ipv6_fragmentation_error_test2_application_define(void *first_unused_memory)
265 #endif
266 {
267 
268     printf("NetX Test:   IPv6 Fragmentation Error Test2............................N/A\n");
269     test_control_return(3);
270 }
271 #endif /* NX_DISABLE_FRAGMENTATION  */
272