1 /*
2 demo_netx_nat.c
3
4 This is a small demo of NAT (Network Address Translation) on the high-performance
5 NetX TCP/IP stack. This demo relies on ThreadX, NetX and NAT APIs to perform network
6 address translation for IP packets traveling between private and external networks.
7 this demo concentrates on the ICMP ping operation.
8 */
9
10 #include "tx_api.h"
11 #include "nx_api.h"
12 #include "nx_nat.h"
13
14 extern void test_control_return(UINT status);
15 #if defined NX_NAT_ENABLE && defined __PRODUCT_NETXDUO__ && (NX_MAX_PHYSICAL_INTERFACES >= 2)
16
17 #define DEMO_STACK_SIZE 2048
18 #define DEMO_DATA "ABCDEFGHIJKLMNOPQRSTUVWXYZ "
19
20 /* Define the ThreadX and NetX object control blocks... */
21
22 static TX_THREAD ntest_0;
23
24 /* Set up the NAT components. */
25
26 /* Create a NAT instance, packet pool and translation table. */
27
28 NX_NAT_DEVICE nat_server;
29 NX_IP nat_ip;
30 NX_IP local_ip;
31 NX_IP external_ip;
32 NX_PACKET_POOL nat_packet_pool;
33 UINT error_counter = 0;
34
35
36 /* Configure the NAT network parameters. */
37
38 /* Set NetX IP packet pool packet size. This should be less than the Maximum Transmit Unit (MTU) of
39 the driver (allow enough room for the Ethernet header plus padding bytes for frame alignment). */
40 #define NX_NAT_PACKET_SIZE 1536
41
42
43 /* Set the size of the NAT IP packet pool. */
44 #define NX_NAT_PACKET_POOL_SIZE (NX_NAT_PACKET_SIZE * 10)
45
46 /* Set NetX IP helper thread stack size. */
47 #define NX_NAT_IP_THREAD_STACK_SIZE 2048
48
49 /* Set the server IP thread priority */
50 #define NX_NAT_IP_THREAD_PRIORITY 2
51
52 /* Set ARP cache size of a NAT ip instance. */
53 #define NX_NAT_ARP_CACHE_SIZE 1024
54
55 /* Set NAT entries memory size. */
56 #define NX_NAT_ENTRY_CACHE_SIZE 1024
57
58 /* Define NAT IP addresses, local host private IP addresses and external host IP address. */
59 #define NX_NAT_LOCAL_IPADR (IP_ADDRESS(192, 168, 2, 1))
60 #define NX_NAT_LOCAL_HOST1 (IP_ADDRESS(192, 168, 2, 3))
61 #define NX_NAT_LOCAL_HOST2 (IP_ADDRESS(192, 168, 2, 10))
62 #define NX_NAT_LOCAL_GATEWAY (IP_ADDRESS(192, 168, 2, 1))
63 #define NX_NAT_LOCAL_NETMASK (IP_ADDRESS(255, 255, 255, 0))
64 #define NX_NAT_EXTERNAL_IPADR (IP_ADDRESS(192, 168, 0, 10))
65 #define NX_NAT_EXTERNAL_HOST (IP_ADDRESS(192, 168, 0, 100))
66 #define NX_NAT_EXTERNAL_GATEWAY (IP_ADDRESS(192, 168, 0, 1))
67 #define NX_NAT_EXTERNAL_NETMASK (IP_ADDRESS(255, 255, 255, 0))
68
69 /* Create NAT structures for preloading NAT tables with static
70 entries for local server hosts. */
71 NX_NAT_TRANSLATION_ENTRY server_inbound_entry_icmp;
72
73 /* Define thread prototypes. */
74 static void ntest_0_entry(ULONG thread_input);
75 extern void _nx_ram_network_driver(struct NX_IP_DRIVER_STRUCT *driver_req);
76
77 /* Define main entry point. */
78
main()79 int main()
80 {
81
82 /* Enter the ThreadX kernel. */
83 tx_kernel_enter();
84 }
85
86
87 /* Define what the initial system looks like. */
88
tx_application_define(void * first_unused_memory)89 void tx_application_define(void *first_unused_memory)
90 {
91
92 UINT status;
93 UCHAR *pointer;
94
95 /* Initialize the NetX system. */
96 nx_system_initialize();
97
98 /* Setup the pointer to unallocated memory. */
99 pointer = (UCHAR *) first_unused_memory;
100
101 /* Create the main thread. */
102 tx_thread_create(&ntest_0, "thread 0", ntest_0_entry, 0,
103 pointer, DEMO_STACK_SIZE,
104 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
105 pointer = pointer + DEMO_STACK_SIZE;
106
107 /* Create NAT packet pool. */
108 status = nx_packet_pool_create(&nat_packet_pool, "NAT Packet Pool",
109 NX_NAT_PACKET_SIZE, pointer,
110 NX_NAT_PACKET_POOL_SIZE);
111
112 /* Update pointer to unallocated (free) memory. */
113 pointer = pointer + NX_NAT_PACKET_POOL_SIZE;
114
115 /* Check status. */
116 if (status)
117 return;
118
119 /* Create IP instances for NAT server (global network) */
120 status = nx_ip_create(&nat_ip, "NAT IP Instance", NX_NAT_EXTERNAL_IPADR, NX_NAT_EXTERNAL_NETMASK,
121 &nat_packet_pool, _nx_ram_network_driver, pointer,
122 NX_NAT_IP_THREAD_STACK_SIZE, NX_NAT_IP_THREAD_PRIORITY);
123
124 /* Update pointer to unallocated (free) memory. */
125 pointer = pointer + NX_NAT_IP_THREAD_STACK_SIZE;
126
127 /* Check status. */
128 if (status)
129 {
130 error_counter++;
131 return;
132 }
133
134 /* Set the private interface(private network). */
135 status += nx_ip_interface_attach(&nat_ip, "Private Interface", NX_NAT_LOCAL_IPADR, NX_NAT_LOCAL_NETMASK, _nx_ram_network_driver);
136
137 /* Check status. */
138 if (status)
139 {
140 error_counter++;
141 return;
142 }
143
144 /* Create IP instances for Local network IP instance */
145 status = nx_ip_create(&local_ip, "Local IP Instance", NX_NAT_LOCAL_HOST1, NX_NAT_LOCAL_NETMASK,
146 &nat_packet_pool, _nx_ram_network_driver, pointer,
147 NX_NAT_IP_THREAD_STACK_SIZE, NX_NAT_IP_THREAD_PRIORITY);
148
149 /* Update pointer to unallocated (free) memory. */
150 pointer = pointer + NX_NAT_IP_THREAD_STACK_SIZE;
151
152 /* Check status. */
153 if (status)
154 {
155 error_counter++;
156 return;
157 }
158
159 /* Create IP instances for external network IP instance */
160 status = nx_ip_create(&external_ip, "External IP Instance", NX_NAT_EXTERNAL_HOST, NX_NAT_EXTERNAL_NETMASK,
161 &nat_packet_pool, _nx_ram_network_driver, pointer,
162 NX_NAT_IP_THREAD_STACK_SIZE, NX_NAT_IP_THREAD_PRIORITY);
163
164 /* Update pointer to unallocated (free) memory. */
165 pointer = pointer + NX_NAT_IP_THREAD_STACK_SIZE;
166
167 /* Check status. */
168 if (status)
169 {
170 error_counter++;
171 return;
172 }
173
174 /* Set the global network gateway for NAT IP instance. */
175 status = nx_ip_gateway_address_set(&nat_ip, NX_NAT_EXTERNAL_GATEWAY);
176
177 /* Check status. */
178 if (status)
179 {
180 error_counter++;
181 return;
182 }
183
184 /* Set the global network gateway for Local IP instance. */
185 status = nx_ip_gateway_address_set(&local_ip, NX_NAT_LOCAL_GATEWAY);
186
187 /* Check status. */
188 if (status)
189 {
190 error_counter++;
191 return;
192 }
193
194 /* Set the global network gateway for External IP instance. */
195 status = nx_ip_gateway_address_set(&external_ip, NX_NAT_EXTERNAL_GATEWAY);
196
197 /* Check status. */
198 if (status)
199 {
200 error_counter++;
201 return;
202 }
203
204
205 /* Enable ARP and supply ARP cache memory for NAT IP isntance. */
206 status = nx_arp_enable(&nat_ip, (void **) pointer,
207 NX_NAT_ARP_CACHE_SIZE);
208
209 /* Check status. */
210 if (status)
211 {
212 error_counter++;
213 return;
214 }
215
216 /* Update pointer to unallocated (free) memory. */
217 pointer = pointer + NX_NAT_ARP_CACHE_SIZE;
218
219 /* Enable ARP and supply ARP cache memory for Local IP isntance. */
220 status = nx_arp_enable(&local_ip, (void **) pointer,
221 NX_NAT_ARP_CACHE_SIZE);
222
223 /* Check status. */
224 if (status)
225 {
226 error_counter++;
227 return;
228 }
229
230 /* Update pointer to unallocated (free) memory. */
231 pointer = pointer + NX_NAT_ARP_CACHE_SIZE;
232
233 /* Enable ARP and supply ARP cache memory for External IP isntance. */
234 status = nx_arp_enable(&external_ip, (void **) pointer,
235 NX_NAT_ARP_CACHE_SIZE);
236
237 /* Check status. */
238 if (status)
239 {
240 error_counter++;
241 return;
242 }
243
244 /* Update pointer to unallocated (free) memory. */
245 pointer = pointer + NX_NAT_ARP_CACHE_SIZE;
246
247 /* Enable ICMP. */
248 nx_icmp_enable(&nat_ip);
249 nx_icmp_enable(&local_ip);
250 nx_icmp_enable(&external_ip);
251
252 /* Create a NetX NAT server and cache with a global interface index. */
253 status = nx_nat_create(&nat_server, &nat_ip, 0, pointer, NX_NAT_ENTRY_CACHE_SIZE);
254
255 /* Check status. */
256 if (status)
257 {
258 error_counter++;
259 return;
260 }
261
262 /* Update pointer to unallocated (free) memory. */
263 pointer = pointer + NX_NAT_ENTRY_CACHE_SIZE;
264 }
265
266 /* Define the test threads. */
267
ntest_0_entry(ULONG thread_input)268 static void ntest_0_entry(ULONG thread_input)
269 {
270
271 UINT status;
272 NX_PACKET *my_packet;
273
274 NX_PARAMETER_NOT_USED(thread_input);
275
276 /***********************************/
277 /* Disable NAT feature */
278 /***********************************/
279 /* Local Host ping External Host address. */
280 status = nx_icmp_ping(&local_ip, NX_NAT_EXTERNAL_HOST, DEMO_DATA, sizeof(DEMO_DATA), &my_packet, NX_IP_PERIODIC_RATE);
281
282 /* Check status. */
283 if (status == NX_SUCCESS)
284 {
285 error_counter++;
286 return;
287 }
288
289 /* Check the NAT forwarded count. */
290 #ifndef NX_DISABLE_NAT_INFO
291 if ((nat_server.forwarded_packets_received != 0) || (nat_server.forwarded_packets_sent != 0) ||(nat_server.forwarded_packets_dropped != 0))
292 {
293 error_counter++;
294 return;
295 }
296 #endif
297
298 /* External Host ping NAT External address, NAT IP instance will response the requet. */
299 status = nx_icmp_ping(&external_ip, NX_NAT_EXTERNAL_IPADR, DEMO_DATA, sizeof(DEMO_DATA), &my_packet, NX_IP_PERIODIC_RATE);
300
301 /* Check status. */
302 if ((status != NX_SUCCESS) || (my_packet == NX_NULL) || (my_packet -> nx_packet_length != 28))
303 {
304 error_counter++;
305 return;
306 }
307
308 /* Check the NAT forwarded count. */
309 #ifndef NX_DISABLE_NAT_INFO
310 if ((nat_server.forwarded_packets_received != 0) || (nat_server.forwarded_packets_sent != 0) ||(nat_server.forwarded_packets_dropped != 0))
311 {
312 error_counter++;
313 return;
314 }
315 #endif
316
317 /***********************************/
318 /* Enable NAT feature */
319 /***********************************/
320
321 /* Enable the NAT service. */
322 nx_nat_enable(&nat_server);
323
324 /* Local Host ping External Host address. */
325 status = nx_icmp_ping(&local_ip, NX_NAT_EXTERNAL_HOST, DEMO_DATA, sizeof(DEMO_DATA), &my_packet, NX_IP_PERIODIC_RATE);
326
327 if ((status != NX_SUCCESS) || (my_packet == NX_NULL) || (my_packet -> nx_packet_length != 28))
328 {
329 error_counter++;
330 return;
331 }
332
333 /* Check the NAT forwarded count. */
334 #ifndef NX_DISABLE_NAT_INFO
335 if ((nat_server.forwarded_packets_received != 2) || (nat_server.forwarded_packets_sent != 2) ||(nat_server.forwarded_packets_dropped != 0))
336 {
337 error_counter++;
338 return;
339 }
340 #endif
341
342 /* External Host ping NAT External address, NAT IP instance will response the requet. */
343 status = nx_icmp_ping(&external_ip, NX_NAT_EXTERNAL_IPADR, DEMO_DATA, sizeof(DEMO_DATA), &my_packet, NX_IP_PERIODIC_RATE);
344
345 if ((status != NX_SUCCESS) || (my_packet == NX_NULL) || (my_packet -> nx_packet_length != 28))
346 {
347 error_counter++;
348 return;
349 }
350
351 /* Check the NAT forwarded count. NAT receive the ping request, but can not forward this packet to local network. discard it. */
352 #ifndef NX_DISABLE_NAT_INFO
353 if ((nat_server.forwarded_packets_received != 3) || (nat_server.forwarded_packets_sent != 2) ||(nat_server.forwarded_packets_dropped != 1))
354 {
355 error_counter++;
356 return;
357 }
358 #endif
359
360 /**********************************************/
361 /* Preload a inbound entry for ICMP */
362 /**********************************************/
363
364 /* Calling NAT API to create a inbound entry. */
365 status = nx_nat_inbound_entry_create(&nat_server, &server_inbound_entry_icmp, NX_NAT_LOCAL_HOST1, 0, 0, NX_PROTOCOL_ICMP);
366
367 if (status != NX_SUCCESS)
368 {
369 error_counter++;
370 return;
371 }
372
373 /* External Host ping NAT External address, LOCAL HOST1 will response all inbound icmp request from external network. */
374 status = nx_icmp_ping(&external_ip, NX_NAT_EXTERNAL_IPADR, DEMO_DATA, sizeof(DEMO_DATA), &my_packet, NX_IP_PERIODIC_RATE);
375
376 if ((status != NX_SUCCESS) || (my_packet == NX_NULL) || (my_packet -> nx_packet_length != 28))
377 {
378 error_counter++;
379 return;
380 }
381
382 /* Check the NAT forwarded count. */
383 #ifndef NX_DISABLE_NAT_INFO
384 if ((nat_server.forwarded_packets_received != 5) || (nat_server.forwarded_packets_sent != 4) ||(nat_server.forwarded_packets_dropped != 1))
385 {
386 error_counter++;
387 return;
388 }
389 #endif
390 }
391 #endif
392