1 /* This NetX test concentrates on the basic BSD RAW non-blocking bind to a specific address and connect + send operation. */
2
3
4 #include "tx_api.h"
5 #include "nx_api.h"
6 #if defined(__PRODUCT_NETXDUO__) && !defined(NX_DISABLE_IPV4)
7 #ifdef NX_BSD_ENABLE
8 #include "nxd_bsd.h"
9
10 #ifdef FEATURE_NX_IPV6
11 #include "nx_ipv6.h"
12 #endif
13 #include "nx_ipv4.h"
14 #ifdef __PRODUCT_NETXDUO__
15 #include "nx_icmpv6.h"
16 #endif
17 #define DEMO_STACK_SIZE 4096
18
19
20 /* Define the ThreadX and NetX object control blocks... */
21
22 static TX_THREAD ntest_0;
23 static TX_THREAD ntest_1;
24
25 static NX_PACKET_POOL pool_0;
26 static NX_IP ip_0;
27 static NX_IP ip_1;
28 static ULONG bsd_thread_area[DEMO_STACK_SIZE / sizeof(ULONG)];
29 #define BSD_THREAD_PRIORITY 2
30 #define NUM_CLIENTS 20
31 /* Define the counters used in the test application... */
32
33 static ULONG error_counter;
34
35
36 /* Define thread prototypes. */
37
38 static void ntest_0_entry(ULONG thread_input);
39 static void ntest_1_entry(ULONG thread_input);
40 extern void test_control_return(UINT status);
41 extern void _nx_ram_network_driver_256(struct NX_IP_DRIVER_STRUCT *driver_req);
42 static void validate_bsd_structure(void);
43 static TX_SEMAPHORE sema;
44 extern NX_BSD_SOCKET nx_bsd_socket_array[NX_BSD_MAX_SOCKETS];
45 extern TX_BLOCK_POOL nx_bsd_socket_block_pool;
46
47 #ifdef FEATURE_NX_IPV6
48 static NXD_ADDRESS ipv6_address_ip0[3][3];
49 static NXD_ADDRESS ipv6_address_ip1[3][3];
50 static char *bsd6_msg[3][3] = {{"BSD6_MSG IF0 LLA", "BSD6_MSG IF0 GA0", "MSD6_MSG IF0 GA1"},
51 {"BSD6_MSG IF1 LLA", "BSD6_MSG IF1 GA0", "MSD6_MSG IF1 GA1"},
52 {"BSD6_MSG IF2 LLA", "BSD6_MSG IF2 GA0", "MSD6_MSG IF2 GA1"}};
53 #endif /* FEATURE_NX_IPV6 */
54 static char *bsd4_msg[3] = {"BSD4_MSG 0", "BSD4_MSG 1", "MSD4_MSG 2"};
55
56 static void validate_bsd_structure(void);
57
58 #define IP0_IF0_V4_ADDR IP_ADDRESS(1,2,3,4)
59 #define IP0_IF1_V4_ADDR IP_ADDRESS(2,2,3,4)
60 #define IP0_IF2_V4_ADDR IP_ADDRESS(3,2,3,4)
61
62 #define IP1_IF0_V4_ADDR IP_ADDRESS(1,2,3,5)
63 #define IP1_IF1_V4_ADDR IP_ADDRESS(2,2,3,5)
64 #define IP1_IF2_V4_ADDR IP_ADDRESS(3,2,3,5)
65
66 #define ITERATIONS 100
67 static ULONG ip0_address[3] = {IP0_IF0_V4_ADDR, IP0_IF1_V4_ADDR, IP0_IF2_V4_ADDR};
68 static ULONG ip1_address[3] = {IP1_IF0_V4_ADDR, IP1_IF1_V4_ADDR, IP1_IF2_V4_ADDR};
69 /* Define what the initial system looks like. */
70
71 #ifdef CTEST
test_application_define(void * first_unused_memory)72 VOID test_application_define(void *first_unused_memory)
73 #else
74 void netx_bsd_raw_bind_connect_test_application_define(void *first_unused_memory)
75 #endif
76 {
77
78 CHAR *pointer;
79 UINT status;
80
81
82 /* Setup the working pointer. */
83 pointer = (CHAR *) first_unused_memory;
84
85 error_counter = 0;
86
87 /* Create the main thread. */
88 tx_thread_create(&ntest_0, "thread 0", ntest_0_entry, 0,
89 pointer, DEMO_STACK_SIZE,
90 3, 3, TX_NO_TIME_SLICE, TX_AUTO_START);
91
92 pointer = pointer + DEMO_STACK_SIZE;
93
94 /* Create the main thread. */
95 tx_thread_create(&ntest_1, "thread 1", ntest_1_entry, 0,
96 pointer, DEMO_STACK_SIZE,
97 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
98
99 pointer = pointer + DEMO_STACK_SIZE;
100
101
102 /* Initialize the NetX system. */
103 nx_system_initialize();
104
105 /* Create a packet pool. */
106 status = nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", 256, pointer, (256 + sizeof(NX_PACKET)) * (NUM_CLIENTS + 4) * 2);
107 pointer = pointer + (256 + sizeof(NX_PACKET)) * (NUM_CLIENTS + 4) * 2;
108
109 if (status)
110 error_counter++;
111
112 /* Create an IP instance. */
113 status = nx_ip_create(&ip_0, "NetX IP Instance 0", IP0_IF0_V4_ADDR, 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver_256,
114 pointer, 2048, 1);
115 pointer = pointer + 2048;
116
117 /* Attach a 2nd interface */
118 status += nx_ip_interface_attach(&ip_0, "ip_0_second", IP0_IF1_V4_ADDR, 0xFFFFFF00UL, _nx_ram_network_driver_256);
119 status += nx_ip_interface_attach(&ip_0, "ip_0_third", IP0_IF2_V4_ADDR, 0xFFFFFF00UL, _nx_ram_network_driver_256);
120
121 /* Create another IP instance. */
122 status += nx_ip_create(&ip_1, "NetX IP Instance 1", IP1_IF0_V4_ADDR, 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver_256,
123 pointer, 2048, 2);
124 pointer = pointer + 2048;
125
126 status += nx_ip_interface_attach(&ip_1, "ip_1_second", IP1_IF1_V4_ADDR, 0xFFFFFF00UL, _nx_ram_network_driver_256);
127 status += nx_ip_interface_attach(&ip_1, "ip_1_third", IP1_IF2_V4_ADDR, 0xFFFFFF00UL, _nx_ram_network_driver_256);
128 if (status)
129 error_counter++;
130
131 /* Enable ARP and supply ARP cache memory for IP Instance 0. */
132 status = nx_arp_enable(&ip_0, (void *) pointer, 1024);
133 pointer = pointer + 1024;
134 if (status)
135 error_counter++;
136
137 /* Enable ARP and supply ARP cache memory for IP Instance 1. */
138 status = nx_arp_enable(&ip_1, (void *) pointer, 1024);
139 pointer = pointer + 1024;
140 if (status)
141 error_counter++;
142
143 /* Enable RAW processing for both IP instances. */
144 status = nx_ip_raw_packet_enable(&ip_0);
145 status += nx_ip_raw_packet_enable(&ip_1);
146
147 /* Enable BSD */
148 status += bsd_initialize(&ip_0, &pool_0, (CHAR*)&bsd_thread_area[0], sizeof(bsd_thread_area), BSD_THREAD_PRIORITY);
149
150 /* Check RAW enable and BSD init status. */
151 if (status)
152 error_counter++;
153
154 status = tx_semaphore_create(&sema, "test done", 0);
155 if (status)
156 error_counter++;
157 }
158
159
160
161
162 #ifdef FEATURE_NX_IPV6
test_raw6_on_interface_address(int iface,int address)163 static void test_raw6_on_interface_address(int iface, int address)
164 {
165 int sockfd;
166 struct sockaddr_in6 remote_addr, local_addr;
167 int ret;
168
169
170 sockfd = socket(AF_INET6, SOCK_RAW, 100);
171 if(sockfd < 0)
172 error_counter++;
173
174 memset(&local_addr, 0, sizeof(local_addr));
175 local_addr.sin6_port = htons(100);
176 local_addr.sin6_family = AF_INET6;
177 if(iface != 3)
178 {
179 local_addr.sin6_addr._S6_un._S6_u32[0] = htonl(ipv6_address_ip0[iface][address].nxd_ip_address.v6[0]);
180 local_addr.sin6_addr._S6_un._S6_u32[1] = htonl(ipv6_address_ip0[iface][address].nxd_ip_address.v6[1]);
181 local_addr.sin6_addr._S6_un._S6_u32[2] = htonl(ipv6_address_ip0[iface][address].nxd_ip_address.v6[2]);
182 local_addr.sin6_addr._S6_un._S6_u32[3] = htonl(ipv6_address_ip0[iface][address].nxd_ip_address.v6[3]);
183 }
184
185
186 ret = bind(sockfd, (struct sockaddr*)&local_addr, sizeof(local_addr));
187 if(ret < 0)
188 error_counter++;
189
190 remote_addr.sin6_family = AF_INET6;
191 remote_addr.sin6_addr._S6_un._S6_u32[0] = htonl(ipv6_address_ip1[iface][address].nxd_ip_address.v6[0]);
192 remote_addr.sin6_addr._S6_un._S6_u32[1] = htonl(ipv6_address_ip1[iface][address].nxd_ip_address.v6[1]);
193 remote_addr.sin6_addr._S6_un._S6_u32[2] = htonl(ipv6_address_ip1[iface][address].nxd_ip_address.v6[2]);
194 remote_addr.sin6_addr._S6_un._S6_u32[3] = htonl(ipv6_address_ip1[iface][address].nxd_ip_address.v6[3]);
195
196 remote_addr.sin6_port = htons(100);
197
198 ret = connect(sockfd, (struct sockaddr*)&remote_addr, sizeof(remote_addr));
199 if(ret < 0)
200 error_counter++;
201
202
203 ret = send(sockfd, bsd6_msg[iface][address], strlen(bsd6_msg[iface][address]), 0);
204 if(ret != (INT)strlen(bsd6_msg[iface][address]))
205 error_counter++;
206
207 /* Close downt he socket. */
208 ret = soc_close(sockfd);
209 if(ret < 0)
210 error_counter++;
211
212 }
213
214
215 #endif /* FEATURE_NX_IPV6 */
216
test_raw4_on_interface(int i)217 static void test_raw4_on_interface(int i)
218 {
219
220 int sockfd;
221 struct sockaddr_in remote_addr, local_addr;
222 int ret;
223
224
225 sockfd = socket(AF_INET, SOCK_RAW, 100);
226 if(sockfd < 0)
227 error_counter++;
228
229 local_addr.sin_family = AF_INET;
230 local_addr.sin_port = htons(100);
231 local_addr.sin_addr.s_addr = htonl(ip0_address[i]);
232
233 ret = bind(sockfd, (struct sockaddr*)&local_addr, sizeof(local_addr));
234 if(ret < 0)
235 error_counter++;
236
237 remote_addr.sin_family = AF_INET;
238 remote_addr.sin_port = htons(100);
239 remote_addr.sin_addr.s_addr = htonl(ip1_address[i]);
240
241 ret = connect(sockfd, (struct sockaddr*)&remote_addr, sizeof(remote_addr));
242 if(ret < 0)
243 error_counter++;
244
245 ret = send(sockfd, bsd4_msg[i], strlen(bsd4_msg[i]), 0);
246 if(ret != (int)strlen(bsd4_msg[i]))
247 error_counter++;
248
249
250 /* Close downt he socket. */
251 ret = soc_close(sockfd);
252 if(ret < 0)
253 error_counter++;
254
255 }
256
257
258
259 /* Define the test threads. */
ntest_0_entry(ULONG thread_input)260 static void ntest_0_entry(ULONG thread_input)
261 {
262 #ifdef FEATURE_NX_IPV6
263 static char mac_ip0[6];
264 static char mac_ip1[6];
265 int j;
266 int addr_index;
267 UINT status;
268 int i;
269 #endif
270 int iface;
271
272
273 printf("NetX Test: Basic BSD RAW Bind Connect Send Test..........");
274
275 /* Check for earlier error. */
276 if (error_counter)
277 {
278
279 printf("ERROR!\n");
280 test_control_return(1);
281 }
282
283 #ifdef FEATURE_NX_IPV6
284
285 for(i = 0; i < 3; i++)
286 {
287 mac_ip0[0] = (char)(ip_0.nx_ip_interface[i].nx_interface_physical_address_msw >> 8);
288 mac_ip0[1] = ip_0.nx_ip_interface[i].nx_interface_physical_address_msw & 0xFF;
289 mac_ip0[2] = (ip_0.nx_ip_interface[i].nx_interface_physical_address_lsw >> 24) & 0xff;
290 mac_ip0[3] = (ip_0.nx_ip_interface[i].nx_interface_physical_address_lsw >> 16) & 0xff;
291 mac_ip0[4] = (ip_0.nx_ip_interface[i].nx_interface_physical_address_lsw >> 8) & 0xff;
292 mac_ip0[5] = ip_0.nx_ip_interface[i].nx_interface_physical_address_lsw & 0xff;
293
294 mac_ip1[0] = (char)(ip_1.nx_ip_interface[i].nx_interface_physical_address_msw >> 8);
295 mac_ip1[1] = ip_1.nx_ip_interface[i].nx_interface_physical_address_msw & 0xFF;
296 mac_ip1[2] = (ip_1.nx_ip_interface[i].nx_interface_physical_address_lsw >> 24) & 0xff;
297 mac_ip1[3] = (ip_1.nx_ip_interface[i].nx_interface_physical_address_lsw >> 16) & 0xff;
298 mac_ip1[4] = (ip_1.nx_ip_interface[i].nx_interface_physical_address_lsw >> 8) & 0xff;
299 mac_ip1[5] = ip_1.nx_ip_interface[i].nx_interface_physical_address_lsw & 0xff;
300
301 for(j = 0; j < 3; j ++)
302 {
303 if(j == 0)
304 {
305 /* First set up IPv6 linklocal addresses. */
306 ipv6_address_ip0[i][j].nxd_ip_version = NX_IP_VERSION_V6;
307 ipv6_address_ip0[i][j].nxd_ip_address.v6[0] = 0xfe800000;
308 ipv6_address_ip0[i][j].nxd_ip_address.v6[1] = 0x00000000;
309 ipv6_address_ip0[i][j].nxd_ip_address.v6[2] = ((mac_ip0[0] | 0x2) << 24) | (mac_ip0[1] << 16) | (mac_ip0[2] << 8) | 0xFF;
310 ipv6_address_ip0[i][j].nxd_ip_address.v6[3] = (0xFE << 24) | ((mac_ip0[3] | 0x2) << 16) | (mac_ip0[4] << 8) | mac_ip0[5];
311
312 ipv6_address_ip1[i][j].nxd_ip_version = NX_IP_VERSION_V6;
313 ipv6_address_ip1[i][j].nxd_ip_address.v6[0] = 0xfe800000;
314 ipv6_address_ip1[i][j].nxd_ip_address.v6[1] = 0x00000000;
315 ipv6_address_ip1[i][j].nxd_ip_address.v6[2] =
316 ((mac_ip1[0] | 0x2) << 24) | (mac_ip1[1] << 16) | (mac_ip1[2] << 8) | 0xFF;
317 ipv6_address_ip1[i][j].nxd_ip_address.v6[3] =
318 (0xFE << 24) | ((mac_ip1[3] | 0x2) << 16) | (mac_ip1[4] << 8) | mac_ip1[5];
319
320 status = nxd_ipv6_address_set(&ip_0, i, &ipv6_address_ip0[i][j], 10, NX_NULL);
321 status += nxd_ipv6_address_set(&ip_1, i, &ipv6_address_ip1[i][j], 10, NX_NULL);
322 }
323 else
324 {
325 /* Global Adddress */
326 ipv6_address_ip0[i][j].nxd_ip_version = NX_IP_VERSION_V6;
327 ipv6_address_ip0[i][j].nxd_ip_address.v6[0] = 0x20000000 + i;
328 ipv6_address_ip0[i][j].nxd_ip_address.v6[1] = j;
329 ipv6_address_ip0[i][j].nxd_ip_address.v6[2] = ipv6_address_ip0[i][0].nxd_ip_address.v6[2];
330 ipv6_address_ip0[i][j].nxd_ip_address.v6[3] = ipv6_address_ip0[i][0].nxd_ip_address.v6[3];
331
332 ipv6_address_ip1[i][j].nxd_ip_version = NX_IP_VERSION_V6;
333 ipv6_address_ip1[i][j].nxd_ip_address.v6[0] = 0x20000000 + i;
334 ipv6_address_ip1[i][j].nxd_ip_address.v6[1] = j;
335 ipv6_address_ip1[i][j].nxd_ip_address.v6[2] = ipv6_address_ip1[i][0].nxd_ip_address.v6[2];
336 ipv6_address_ip1[i][j].nxd_ip_address.v6[3] = ipv6_address_ip1[i][0].nxd_ip_address.v6[3];
337
338
339 status = nxd_ipv6_address_set(&ip_0, i, &ipv6_address_ip0[i][j], 64, NX_NULL);
340 status += nxd_ipv6_address_set(&ip_1, i, &ipv6_address_ip1[i][j], 64, NX_NULL);
341 }
342 status += nxd_nd_cache_entry_set(&ip_0, ipv6_address_ip1[i][j].nxd_ip_address.v6, 0, mac_ip1);
343 status += nxd_nd_cache_entry_set(&ip_1, ipv6_address_ip0[i][j].nxd_ip_address.v6, 0, mac_ip0);
344 }
345
346 }
347
348
349
350 status += nxd_ipv6_enable(&ip_0);
351 status += nxd_ipv6_enable(&ip_1);
352
353
354
355 if(status)
356 error_counter++;
357 #endif
358
359 /* Wait for the semaphore to signal the other party is ready. */
360 tx_semaphore_get(&sema, 2 * NX_IP_PERIODIC_RATE);
361
362 for(iface = 0; iface < 3; iface++)
363 {
364 test_raw4_on_interface(iface);
365
366 tx_semaphore_get(&sema, 2 * NX_IP_PERIODIC_RATE);
367
368 #ifdef FEATURE_NX_IPV6
369 for(addr_index = 1; addr_index < 3; addr_index++)
370 {
371
372 test_raw6_on_interface_address(iface, addr_index);
373
374 tx_semaphore_get(&sema, 2 * NX_IP_PERIODIC_RATE);
375 }
376
377 #endif
378 }
379
380
381 tx_semaphore_delete(&sema);
382
383 validate_bsd_structure();
384
385 if(error_counter)
386 printf("ERROR!\n");
387 else
388 printf("SUCCESS!\n");
389
390 if(error_counter)
391 test_control_return(1);
392
393 test_control_return(0);
394 }
395
ntest_1_entry(ULONG thread_input)396 static void ntest_1_entry(ULONG thread_input)
397 {
398 ULONG actual_status;
399 UINT status;
400 UINT iface;
401 NX_PACKET *packet_ptr;
402 NX_IPV4_HEADER *ipv4_header;
403 #ifdef FEATURE_NX_IPV6
404 NX_IPV6_HEADER *ipv6_header;
405 UINT addr_index;
406 #endif
407 /* Ensure the IP instance has been initialized. */
408 status = nx_ip_status_check(&ip_1, NX_IP_INITIALIZE_DONE, &actual_status, 1 * NX_IP_PERIODIC_RATE);
409
410 tx_semaphore_put(&sema);
411
412
413 for(iface = 0; iface < 3; iface++)
414 {
415
416 status = nx_ip_raw_packet_receive(&ip_1, &packet_ptr, 1 * NX_IP_PERIODIC_RATE);
417
418 /* Check status... */
419 if (status != NX_SUCCESS)
420 {
421 error_counter++;
422 continue;
423 }
424
425 ipv4_header = (NX_IPV4_HEADER*)packet_ptr -> nx_packet_ip_header;
426 if(ipv4_header -> nx_ip_header_source_ip != ip0_address[iface])
427 error_counter++;
428 if((ipv4_header -> nx_ip_header_word_2 & 0x00FF0000) != (100 << 16))
429 error_counter++;
430 if(ipv4_header -> nx_ip_header_destination_ip != ip1_address[iface])
431 error_counter++;
432 if((packet_ptr -> nx_packet_length != strlen(bsd4_msg[iface])) ||
433 (memcmp(packet_ptr -> nx_packet_prepend_ptr, bsd4_msg[iface], packet_ptr -> nx_packet_length)))
434 error_counter++;
435
436 nx_packet_release(packet_ptr);
437
438 tx_semaphore_put(&sema);
439
440 #ifdef FEATURE_NX_IPV6
441 for(addr_index = 1; addr_index < 3; addr_index++)
442 {
443 status = nx_ip_raw_packet_receive(&ip_1, &packet_ptr, 1 * NX_IP_PERIODIC_RATE);
444
445 if(status != NX_SUCCESS)
446 {
447 error_counter++;
448 continue;
449 }
450
451 ipv6_header = (NX_IPV6_HEADER*)packet_ptr -> nx_packet_ip_header;
452
453 if((ipv6_header -> nx_ip_header_source_ip[0] != ipv6_address_ip0[iface][addr_index].nxd_ip_address.v6[0]) ||
454 (ipv6_header -> nx_ip_header_source_ip[1] != ipv6_address_ip0[iface][addr_index].nxd_ip_address.v6[1]) ||
455 (ipv6_header -> nx_ip_header_source_ip[2] != ipv6_address_ip0[iface][addr_index].nxd_ip_address.v6[2]) ||
456 (ipv6_header -> nx_ip_header_source_ip[3] != ipv6_address_ip0[iface][addr_index].nxd_ip_address.v6[3]))
457 error_counter++;
458 if((ipv6_header -> nx_ip_header_destination_ip[0] != ipv6_address_ip1[iface][addr_index].nxd_ip_address.v6[0]) ||
459 (ipv6_header -> nx_ip_header_destination_ip[1] != ipv6_address_ip1[iface][addr_index].nxd_ip_address.v6[1]) ||
460 (ipv6_header -> nx_ip_header_destination_ip[2] != ipv6_address_ip1[iface][addr_index].nxd_ip_address.v6[2]) ||
461 (ipv6_header -> nx_ip_header_destination_ip[3] != ipv6_address_ip1[iface][addr_index].nxd_ip_address.v6[3]))
462 error_counter++;
463 if((ipv6_header -> nx_ip_header_word_1 & 0x0000FF00) != (100 << 8))
464 error_counter++;
465
466 if((packet_ptr -> nx_packet_length != strlen(bsd6_msg[iface][addr_index])) ||
467 (memcmp(packet_ptr -> nx_packet_prepend_ptr, bsd6_msg[iface][addr_index], packet_ptr -> nx_packet_length)))
468 error_counter++;
469
470 nx_packet_release(packet_ptr);
471
472 tx_semaphore_put(&sema);
473 }
474 #endif
475 }
476 }
477
validate_bsd_structure(void)478 static void validate_bsd_structure(void)
479 {
480 int i;
481 /* Make sure every BSD socket should be free by now. */
482
483 for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
484 {
485 if(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE)
486 {
487 error_counter++;
488 }
489
490 if(nx_bsd_socket_array[i].nx_bsd_socket_tcp_socket ||
491 nx_bsd_socket_array[i].nx_bsd_socket_udp_socket)
492 {
493 error_counter++;
494 }
495 }
496
497 /* Make sure all the NX SOCKET control blocks are released. */
498 if(nx_bsd_socket_block_pool.tx_block_pool_available !=
499 nx_bsd_socket_block_pool.tx_block_pool_total)
500 {
501 error_counter++;
502
503 }
504
505 /* Make sure all the sockets are released */
506 if(ip_0.nx_ip_tcp_created_sockets_ptr ||
507 ip_0.nx_ip_udp_created_sockets_ptr)
508 {
509 error_counter++;
510 return;
511 }
512 }
513
514 #endif /* NX_BSD_ENABLE */
515
516 #else /* __PRODUCT_NETXDUO__ */
517
518 extern void test_control_return(UINT status);
519 #ifdef CTEST
test_application_define(void * first_unused_memory)520 VOID test_application_define(void *first_unused_memory)
521 #else
522 void netx_bsd_raw_bind_connect_test_application_define(void *first_unused_memory)
523 #endif
524 {
525 printf("NetX Test: Basic BSD RAW Bind Connect Send Test..........N/A\n");
526 test_control_return(3);
527 }
528 #endif /* __PRODUCT_NETXDUO__ */
529
530