tc_netdev.c 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144
  1. /*
  2. * Copyright (c) 2006-2025, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2025-09-12 Rbb666 the first version
  9. */
  10. #include <rtthread.h>
  11. #include "utest.h"
  12. #include <sys/socket.h>
  13. #include <arpa/inet.h>
  14. #include <dfs_net.h>
  15. #include <netdev.h>
  16. #include <netdev_ipaddr.h>
  17. #include <sal_low_lvl.h>
  18. #include <stdio.h>
  19. #include <math.h>
  20. #include <string.h>
  21. /* Callback event synchronization timeout (milliseconds) */
  22. #define CALLBACK_EVENT_TIMEOUT 1000
  23. /** @brief Save original default network device pointer for restoration after testing */
  24. static struct netdev *netdev_default_old = RT_NULL;
  25. /* Save initial network configuration for network state restoration after testing */
  26. static ip_addr_t initial_ip_addr; /**< Initial IP address */
  27. static ip_addr_t initial_netmask; /**< Initial subnet mask */
  28. static ip_addr_t initial_gw; /**< Initial gateway address */
  29. static ip_addr_t initial_dns0; /**< Initial primary DNS server */
  30. static ip_addr_t initial_dns1; /**< Initial secondary DNS server */
  31. static rt_bool_t initial_dhcp_enabled; /**< Initial DHCP enable status */
  32. /**
  33. * @brief Execute multiple ping tests and calculate success rate
  34. *
  35. * This function performs multiple ping operations to a specified host and determines
  36. * test results based on success rate. The test passes if success rate exceeds 80%.
  37. *
  38. * @param netdev Network device pointer
  39. * @param host Target host address (IP address or domain name)
  40. * @param n Number of ping test attempts
  41. * @return rt_err_t RT_EOK-test passed (success rate>=80%), -RT_ERROR-test failed
  42. *
  43. * @note This function uses 32-byte data packets with a 5-second timeout
  44. */
  45. rt_err_t multiple_ping_test(struct netdev *netdev, const char *host, rt_uint32_t n)
  46. {
  47. #define UTEST_PING_DATA_LEN 32 /* Ping data packet size */
  48. #define UTEST_PING_TIMEOUT (5 * RT_TICK_PER_SECOND) /* Ping timeout: 5 seconds */
  49. rt_uint32_t success_num = 0, i;
  50. rt_err_t res = RT_EOK;
  51. struct netdev_ping_resp ping_resp;
  52. /* Execute ping operations n times */
  53. for (i = 0; i < n; i++)
  54. {
  55. res = netdev->ops->ping(netdev, host, UTEST_PING_DATA_LEN, UTEST_PING_TIMEOUT, &ping_resp, RT_FALSE);
  56. if (res == RT_EOK)
  57. {
  58. success_num++;
  59. }
  60. }
  61. /* Test passes if success rate is more than 80 percent */
  62. if (success_num >= ceil(0.8 * n))
  63. return RT_EOK;
  64. else
  65. return -RT_ERROR;
  66. }
  67. /**
  68. * @brief Test network connectivity using ping operations
  69. *
  70. * This function tests network connectivity by pinging various targets:
  71. * - Gateway address (should succeed)
  72. * - Invalid internal IP address (should fail)
  73. * - External IP address (should succeed)
  74. * - Invalid external IP address (should fail)
  75. * - External URL (should succeed)
  76. * - Invalid external URL (should fail)
  77. *
  78. * @note This test verifies both successful and failed ping scenarios
  79. */
  80. static void test_netdev_ping(void)
  81. {
  82. #define UTEST_INTRANET_WRONG_IP_ADDR "192.256.0.321" /* Invalid IP format */
  83. #define UTEST_EXTERNAL_IP_ADDR "8.8.8.8" /* Valid external IP */
  84. #define UTEST_EXTERNAL_WRONG_IP_ADDR "123.456.789.012" /* Invalid IP format */
  85. #define UTEST_EXTERNAL_URL "www.baidu.com" /* Valid external URL */
  86. #define UTEST_EXTERNAL_WRONG_URL "www.abcsdd.com" /* Non-existent URL */
  87. rt_err_t res = RT_EOK;
  88. /* Test ping to gateway address - should succeed */
  89. res = multiple_ping_test(netdev_default, inet_ntoa(netdev_default->gw), 10);
  90. uassert_true(res == RT_EOK);
  91. /* Test ping to invalid internal IP - should fail */
  92. res = multiple_ping_test(netdev_default, UTEST_INTRANET_WRONG_IP_ADDR, 1);
  93. uassert_false(res == RT_EOK);
  94. /* Test ping to external IP address - should succeed */
  95. res = multiple_ping_test(netdev_default, UTEST_EXTERNAL_IP_ADDR, 10);
  96. uassert_true(res == RT_EOK);
  97. /* Test ping to invalid external IP - should fail */
  98. res = multiple_ping_test(netdev_default, UTEST_EXTERNAL_WRONG_IP_ADDR, 1);
  99. uassert_false(res == RT_EOK);
  100. /* Test ping to external URL - should succeed */
  101. res = multiple_ping_test(netdev_default, UTEST_EXTERNAL_URL, 10);
  102. uassert_true(res == RT_EOK);
  103. /* Test ping to invalid external URL - should fail */
  104. res = multiple_ping_test(netdev_default, UTEST_EXTERNAL_WRONG_URL, 1);
  105. uassert_false(res == RT_EOK);
  106. }
  107. /**
  108. * @brief Test network interface configuration and status
  109. *
  110. * This function tests:
  111. * - Network interface status (up/link up)
  112. * - IP address configuration validity
  113. * - Gateway configuration validity
  114. * - Subnet mask configuration validity
  115. * - DNS server configuration validity
  116. *
  117. * @note Validates that the network interface is properly configured and operational
  118. */
  119. static void test_netdev_ifconfig(void)
  120. {
  121. /* Perform network interface status validation */
  122. uassert_true(netdev_is_up(netdev_default) && netdev_is_link_up(netdev_default)); /* Interface should be up and linked */
  123. uassert_false(ip_addr_isany(&netdev_default->ip_addr)); /* IP address should be assigned */
  124. uassert_false(ip_addr_isany(&netdev_default->gw)); /* Gateway should be configured */
  125. uassert_false(ip_addr_isany(&netdev_default->netmask)); /* Subnet mask should be configured */
  126. uassert_false(ip_addr_isany(&netdev_default->dns_servers[0])); /* Primary DNS should be configured */
  127. }
  128. /**
  129. * @brief Test network statistics functionality
  130. *
  131. * This function tests the netstat operation capability of the network device.
  132. * It verifies that the netstat function can be called without crashing.
  133. *
  134. * @note This is a basic functionality test to ensure netstat operation is available
  135. */
  136. static void test_netdev_netstat(void)
  137. {
  138. /* Simply test that netstat function can be called without crashing */
  139. if (netdev_default->ops->netstat)
  140. {
  141. netdev_default->ops->netstat(netdev_default);
  142. uassert_true(RT_TRUE); /* If we reach here, the function call succeeded */
  143. }
  144. else
  145. {
  146. uassert_true(RT_FALSE); /* netstat function not available */
  147. }
  148. }
  149. /**
  150. * @brief Test DNS server configuration and hostname resolution
  151. *
  152. * This function tests:
  153. * - Setting incorrect DNS server and verifying hostname resolution fails
  154. * - Setting correct DNS server and verifying hostname resolution succeeds
  155. * - DNS server configuration operations
  156. *
  157. * @note DNS configuration will be restored in utest_tc_cleanup
  158. */
  159. static void test_netdev_dns(void)
  160. {
  161. #define UTEST_DNS "114.114.114.114" /* Valid DNS server */
  162. #define UTEST_WRONG_DNS "13.19.123.143" /* Invalid DNS server */
  163. #define UTEST_WRONG_HOST_NAME "www.abcde.com" /* Test hostname */
  164. #define UTEST_HOST_ADDR "www.rt-thread.org" /* RT-Thread official website */
  165. ip_addr_t ipaddr = {0};
  166. struct hostent *res = RT_NULL;
  167. struct sal_proto_family *netdev_inet = RT_NULL;
  168. /* Get SAL protocol family for DNS operations */
  169. netdev_inet = netdev_default->sal_user_data;
  170. if (netdev_inet == RT_NULL)
  171. {
  172. rt_kprintf("get sal proto family fail!");
  173. uassert_true(RT_FALSE);
  174. return;
  175. }
  176. /* Test with wrong DNS server - hostname resolution should fail */
  177. inet_aton(UTEST_WRONG_DNS, &ipaddr);
  178. netdev_default->ops->set_dns_server(netdev_default, 0, &ipaddr);
  179. netdev_default->ops->set_dns_server(netdev_default, 1, &ipaddr);
  180. res = netdev_inet->netdb_ops->gethostbyname(UTEST_WRONG_HOST_NAME);
  181. if (res == RT_NULL)
  182. {
  183. uassert_true(RT_TRUE); /* Expected failure */
  184. }
  185. else
  186. {
  187. uassert_true(RT_FALSE); /* Unexpected success */
  188. }
  189. /* Test with correct DNS server - hostname resolution should succeed */
  190. inet_aton(UTEST_DNS, &ipaddr);
  191. netdev_default->ops->set_dns_server(netdev_default, 0, &ipaddr);
  192. netdev_default->ops->set_dns_server(netdev_default, 1, &ipaddr);
  193. res = netdev_inet->netdb_ops->gethostbyname(UTEST_HOST_ADDR);
  194. uassert_true(res != RT_NULL);
  195. /* DNS will be restored in utest_tc_cleanup */
  196. }
  197. /**
  198. * @brief Test DHCP functionality
  199. *
  200. * This function tests:
  201. * - DHCP disable operation
  202. * - DHCP state verification
  203. * - DHCP state restoration
  204. * - Network configuration stability after DHCP operations
  205. *
  206. * @note Includes retry mechanism to wait for network configuration restoration
  207. * to prevent interference with subsequent ping tests
  208. */
  209. static void test_netdev_dhcp(void)
  210. {
  211. rt_err_t res;
  212. rt_bool_t initial_state;
  213. ip_addr_t initial_ip, initial_gw;
  214. int retry_count = 0;
  215. const int max_retries = 10;
  216. /* Save initial network configuration for restoration */
  217. initial_state = netdev_is_dhcp_enabled(netdev_default);
  218. initial_ip = netdev_default->ip_addr;
  219. initial_gw = netdev_default->gw;
  220. rt_kprintf("Initial DHCP state: %s\n", initial_state ? "enabled" : "disabled");
  221. rt_kprintf("Initial IP: %s, Gateway: %s\n", inet_ntoa(initial_ip), inet_ntoa(initial_gw));
  222. /* Test DHCP disable operation */
  223. res = netdev_dhcp_enabled(netdev_default, RT_FALSE);
  224. if (res == RT_EOK)
  225. {
  226. uassert_false(netdev_is_dhcp_enabled(netdev_default));
  227. rt_kprintf("DHCP successfully disabled\n");
  228. }
  229. else
  230. {
  231. rt_kprintf("Failed to disable DHCP: error code %d\n", res);
  232. uassert_true(RT_FALSE);
  233. return;
  234. }
  235. /* Restore initial DHCP state */
  236. res = netdev_dhcp_enabled(netdev_default, initial_state);
  237. uassert_true(res == RT_EOK);
  238. /* Wait for network configuration to stabilize after DHCP restoration */
  239. if (initial_state)
  240. {
  241. rt_kprintf("Waiting for DHCP to restore network configuration...\n");
  242. while (retry_count < max_retries)
  243. {
  244. rt_thread_mdelay(1000); /* Wait 1000ms between checks */
  245. /* Check if IP and gateway are properly restored */
  246. if (!ip_addr_isany(&netdev_default->ip_addr) &&
  247. !ip_addr_isany(&netdev_default->gw))
  248. {
  249. rt_kprintf("Network configuration restored after %d retries\n", retry_count);
  250. rt_kprintf("Current IP: %s, Gateway: %s\n",
  251. inet_ntoa(netdev_default->ip_addr),
  252. inet_ntoa(netdev_default->gw));
  253. break;
  254. }
  255. retry_count++;
  256. }
  257. /* Fail the test if network configuration is not restored within timeout */
  258. if (retry_count >= max_retries)
  259. {
  260. rt_kprintf("Failed: Network configuration not fully restored within timeout\n");
  261. uassert_true(RT_FALSE);
  262. }
  263. }
  264. }
  265. /**
  266. * @brief Test setting network interface configuration parameters
  267. *
  268. * This function tests:
  269. * - IP address setting and verification
  270. * - Gateway address setting and verification
  271. * - Network configuration restoration
  272. * - DHCP disable/enable during configuration changes
  273. *
  274. * @note DHCP will be restored in utest_tc_cleanup
  275. */
  276. static void test_netdev_ifconfig_set(void)
  277. {
  278. #define UTEST_WRONG_IP_ADDR "192.1.4.125" /* Test IP address */
  279. #define UTEST_HOST_ADDR "www.rt-thread.org" /* Test hostname */
  280. #define UTEST_WRONG_GW_IP_ADDR "192.168.99.1" /* Test gateway address */
  281. ip_addr_t ipaddr, true_ipaddr;
  282. rt_err_t res = RT_EOK;
  283. /* Save original IP address for restoration */
  284. true_ipaddr = netdev_default->ip_addr;
  285. /* Disable DHCP before manual configuration */
  286. res = netdev_dhcp_enabled(netdev_default, RT_FALSE);
  287. if (res != RT_EOK)
  288. {
  289. rt_kprintf("Failed to disable DHCP: %d\n", res);
  290. uassert_true(RT_FALSE);
  291. }
  292. /* Test setting a different valid IP address */
  293. inet_aton(UTEST_WRONG_IP_ADDR, &ipaddr);
  294. res = netdev_set_ipaddr(netdev_default, &ipaddr);
  295. if (res != RT_EOK)
  296. {
  297. rt_kprintf("Failed to set IP address: %d\n", res);
  298. uassert_true(RT_FALSE);
  299. }
  300. /* Verify IP address was set correctly */
  301. uassert_true(ip_addr_cmp(&netdev_default->ip_addr, &ipaddr));
  302. /* Test ping with new IP configuration (may fail due to network setup) */
  303. res = multiple_ping_test(netdev_default, UTEST_HOST_ADDR, 1);
  304. /* Don't assert on ping result as it depends on network setup */
  305. /* Restore original IP address */
  306. res = netdev_set_ipaddr(netdev_default, &true_ipaddr);
  307. if (res != RT_EOK)
  308. {
  309. rt_kprintf("Failed to restore IP address: %d\n", res);
  310. uassert_true(RT_FALSE);
  311. }
  312. /* Verify IP address was restored */
  313. uassert_true(ip_addr_cmp(&netdev_default->ip_addr, &true_ipaddr));
  314. /* Test gateway setting */
  315. ip_addr_t original_gw = netdev_default->gw;
  316. inet_aton(UTEST_WRONG_GW_IP_ADDR, &ipaddr);
  317. res = netdev_set_gw(netdev_default, &ipaddr);
  318. if (res != RT_EOK)
  319. {
  320. rt_kprintf("Failed to set gateway: %d\n", res);
  321. uassert_true(RT_FALSE);
  322. }
  323. /* Verify gateway was set correctly */
  324. uassert_true(ip_addr_cmp(&netdev_default->gw, &ipaddr));
  325. /* Restore original gateway */
  326. res = netdev_set_gw(netdev_default, &original_gw);
  327. if (res != RT_EOK)
  328. {
  329. rt_kprintf("Failed to restore gateway: %d\n", res);
  330. uassert_true(RT_FALSE);
  331. }
  332. /* Verify gateway was restored */
  333. uassert_true(ip_addr_cmp(&netdev_default->gw, &original_gw));
  334. /* DHCP will be restored in utest_tc_cleanup */
  335. }
  336. /**
  337. * @brief Test setting the default network device
  338. *
  339. * This function tests the ability to set a network device as the default
  340. * network interface for the system.
  341. */
  342. static void test_netdev_set_default_netdev(void)
  343. {
  344. netdev_set_default(netdev_get_by_name(RT_UTEST_DEFAULT_NETDEV_NAME));
  345. uassert_true(RT_TRUE);
  346. }
  347. /**
  348. * @brief Test IP address conversion functions
  349. *
  350. * This function tests various IP address conversion utilities:
  351. * - IPv4 string to binary conversion (aton)
  352. * - IPv4 binary to string conversion (ntoa)
  353. * - IPv4 binary to string conversion with buffer (ntoa_r)
  354. * - IPv4 address parsing and validation
  355. * - inet_pton and inet_ntop functions
  356. *
  357. * @note Tests both valid and invalid IP address formats
  358. */
  359. static void test_netdev_ipaddr_conversion(void)
  360. {
  361. #define UTEST_IP4_ADDR_STR "192.168.1.1" /* Valid IPv4 address */
  362. #define UTEST_IP4_ADDR_STR2 "10.0.0.1" /* Another valid IPv4 address */
  363. #define UTEST_INVALID_IP_STR "999.999.999.999" /* Invalid IPv4 address */
  364. ip4_addr_t ip4_addr;
  365. char buf[16]; /* Maximum length for IPv4 string representation */
  366. int res;
  367. /* Test IPv4 string to binary conversion (aton) */
  368. res = netdev_ip4addr_aton(UTEST_IP4_ADDR_STR, &ip4_addr);
  369. uassert_true(res == 1); /* Should succeed */
  370. uassert_true(ip4_addr_get_u32(&ip4_addr) == inet_addr(UTEST_IP4_ADDR_STR));
  371. /* Test invalid IP address conversion */
  372. res = netdev_ip4addr_aton(UTEST_INVALID_IP_STR, &ip4_addr);
  373. uassert_true(res == 0); /* Should fail */
  374. /* Test IPv4 binary to string conversion with buffer (ntoa_r) */
  375. ip4_addr_set_u32(&ip4_addr, inet_addr(UTEST_IP4_ADDR_STR));
  376. netdev_ip4addr_ntoa_r(&ip4_addr, buf, sizeof(buf));
  377. uassert_str_equal(buf, UTEST_IP4_ADDR_STR);
  378. /* Test IPv4 binary to string conversion (ntoa) */
  379. const char *ntoa_result = netdev_ip4addr_ntoa(&ip4_addr);
  380. uassert_str_equal(ntoa_result, UTEST_IP4_ADDR_STR);
  381. /* Test IP address string to binary conversion (ipaddr_addr) */
  382. in_addr_t addr = netdev_ipaddr_addr(UTEST_IP4_ADDR_STR);
  383. uassert_true(addr == inet_addr(UTEST_IP4_ADDR_STR));
  384. /* Test invalid IP address should return INADDR_NONE */
  385. addr = netdev_ipaddr_addr(UTEST_INVALID_IP_STR);
  386. uassert_true(addr == INADDR_NONE);
  387. /* Test inet_pton and inet_ntop for IPv4 */
  388. struct in_addr in_addr;
  389. res = netdev_inet_pton(AF_INET, UTEST_IP4_ADDR_STR, &in_addr);
  390. uassert_true(res == 1); /* Should succeed */
  391. uassert_true(in_addr.s_addr == inet_addr(UTEST_IP4_ADDR_STR));
  392. const char *ntop_result = netdev_inet_ntop(AF_INET, &in_addr, buf, sizeof(buf));
  393. uassert_true(ntop_result != NULL);
  394. uassert_str_equal(buf, UTEST_IP4_ADDR_STR);
  395. /* Test invalid IP format should fail */
  396. res = netdev_inet_pton(AF_INET, UTEST_INVALID_IP_STR, &in_addr);
  397. uassert_true(res == 0); /* Should fail */
  398. }
  399. /**
  400. * @brief Test network device retrieval functions
  401. *
  402. * This function tests various methods to retrieve network devices:
  403. * - Get device by name (valid and invalid names)
  404. * - Get device by IP address (valid and invalid addresses)
  405. * - Get device by interface index (valid and invalid indices)
  406. * - Get first device by flags
  407. * - Get device by protocol family (if SAL is enabled)
  408. *
  409. * @note Tests both successful and failed retrieval scenarios
  410. */
  411. static void test_netdev_get_functions(void)
  412. {
  413. struct netdev *netdev_found;
  414. /* Test get_by_name */
  415. netdev_found = netdev_get_by_name(netdev_default->name);
  416. uassert_true(netdev_found == netdev_default);
  417. netdev_found = netdev_get_by_name("nonexistent");
  418. uassert_true(netdev_found == RT_NULL);
  419. /* Test get_by_ipaddr */
  420. netdev_found = netdev_get_by_ipaddr(&netdev_default->ip_addr);
  421. uassert_true(netdev_found == netdev_default);
  422. ip_addr_t invalid_ip;
  423. ip_addr_set_zero(&invalid_ip);
  424. netdev_found = netdev_get_by_ipaddr(&invalid_ip);
  425. uassert_true(netdev_found == RT_NULL);
  426. /* Test get_by_ifindex */
  427. netdev_found = netdev_get_by_ifindex(netdev_default->ifindex);
  428. uassert_true(netdev_found == netdev_default);
  429. netdev_found = netdev_get_by_ifindex(-1);
  430. uassert_true(netdev_found == RT_NULL);
  431. /* Test get_first_by_flags */
  432. netdev_found = netdev_get_first_by_flags(NETDEV_FLAG_UP);
  433. uassert_true(netdev_found != RT_NULL);
  434. netdev_found = netdev_get_first_by_flags(NETDEV_FLAG_UP | NETDEV_FLAG_LINK_UP);
  435. uassert_true(netdev_found != RT_NULL);
  436. #ifdef RT_USING_SAL
  437. /* Test get_by_family */
  438. netdev_found = netdev_get_by_family(AF_INET);
  439. uassert_true(netdev_found != RT_NULL);
  440. /* Test family_get */
  441. int family = netdev_family_get(netdev_default);
  442. uassert_true(family == AF_INET);
  443. #endif
  444. }
  445. /**
  446. * @brief Test network device status setting operations
  447. *
  448. * This function tests:
  449. * - Network interface up/down operations
  450. * - Link status setting and verification
  451. * - Status operation error handling
  452. * - Status restoration
  453. *
  454. * @note Carefully avoids disrupting network connectivity during testing
  455. */
  456. static void test_netdev_status_set(void)
  457. {
  458. rt_err_t res;
  459. rt_bool_t original_link_up;
  460. /* Test set_up and set_down - be careful not to disrupt network */
  461. rt_bool_t was_up = netdev_is_up(netdev_default);
  462. if (!was_up)
  463. {
  464. res = netdev_set_up(netdev_default);
  465. uassert_true(res == RT_EOK);
  466. uassert_true(netdev_is_up(netdev_default));
  467. }
  468. uassert_true(netdev_is_up(netdev_default));
  469. uassert_true(netdev_default->ops->set_up != RT_NULL);
  470. uassert_true(netdev_default->ops->set_down != RT_NULL);
  471. /* Test set_down and set_up cycle */
  472. res = netdev_set_down(netdev_default);
  473. if (res == RT_EOK)
  474. {
  475. uassert_false(netdev_is_up(netdev_default));
  476. res = netdev_set_up(netdev_default);
  477. uassert_true(res == RT_EOK);
  478. uassert_true(netdev_is_up(netdev_default));
  479. }
  480. else
  481. {
  482. uassert_true(netdev_is_up(netdev_default));
  483. }
  484. /* Test link status */
  485. original_link_up = netdev_is_link_up(netdev_default);
  486. netdev_low_level_set_link_status(netdev_default, RT_FALSE);
  487. uassert_false(netdev_is_link_up(netdev_default));
  488. netdev_low_level_set_link_status(netdev_default, RT_TRUE);
  489. uassert_true(netdev_is_link_up(netdev_default));
  490. /* Restore original link status */
  491. netdev_low_level_set_link_status(netdev_default, original_link_up);
  492. }
  493. /**
  494. * @brief Test network device configuration setting operations
  495. *
  496. * This function tests:
  497. * - Subnet mask setting and verification
  498. * - DNS server setting and verification
  499. * - Network interface parameter setting (set_if)
  500. * - Configuration restoration
  501. * - DHCP interaction with manual configuration
  502. *
  503. * @note Includes proper configuration backup and restoration
  504. */
  505. static void test_netdev_config_set(void)
  506. {
  507. ip_addr_t original_netmask = netdev_default->netmask;
  508. ip_addr_t original_dns0 = netdev_default->dns_servers[0];
  509. ip_addr_t original_dns1 = netdev_default->dns_servers[1];
  510. ip_addr_t test_netmask = {0}, test_dns = {0};
  511. rt_err_t res;
  512. /* Test set_netmask */
  513. if (netdev_is_dhcp_enabled(netdev_default))
  514. {
  515. res = netdev_dhcp_enabled(netdev_default, RT_FALSE);
  516. if (res != RT_EOK)
  517. {
  518. goto skip_netmask_test;
  519. }
  520. }
  521. inet_aton("255.255.255.0", &test_netmask);
  522. res = netdev_set_netmask(netdev_default, &test_netmask);
  523. if (res == RT_EOK)
  524. {
  525. uassert_true(ip_addr_cmp(&netdev_default->netmask, &test_netmask));
  526. }
  527. /* Restore netmask */
  528. res = netdev_set_netmask(netdev_default, &original_netmask);
  529. uassert_true(res == RT_EOK);
  530. skip_netmask_test:
  531. /* Test set_dns_server */
  532. inet_aton("8.8.8.8", &test_dns);
  533. res = netdev_set_dns_server(netdev_default, 0, &test_dns);
  534. uassert_true(res == RT_EOK);
  535. uassert_true(ip_addr_cmp(&netdev_default->dns_servers[0], &test_dns));
  536. inet_aton("8.8.4.4", &test_dns);
  537. res = netdev_set_dns_server(netdev_default, 1, &test_dns);
  538. uassert_true(res == RT_EOK);
  539. uassert_true(ip_addr_cmp(&netdev_default->dns_servers[1], &test_dns));
  540. /* Restore DNS servers */
  541. res = netdev_set_dns_server(netdev_default, 0, &original_dns0);
  542. uassert_true(res == RT_EOK);
  543. res = netdev_set_dns_server(netdev_default, 1, &original_dns1);
  544. uassert_true(res == RT_EOK);
  545. /* Test set_if */
  546. ip_addr_t test_ip, test_gw, test_nm;
  547. ip_addr_t original_ip, original_gw, original_nm;
  548. original_ip = netdev_default->ip_addr;
  549. original_gw = netdev_default->gw;
  550. original_nm = netdev_default->netmask;
  551. inet_aton("192.168.2.100", &test_ip);
  552. inet_aton("192.168.2.1", &test_gw);
  553. inet_aton("255.255.255.0", &test_nm);
  554. netdev_set_if(netdev_default->name, inet_ntoa(test_ip), inet_ntoa(test_gw), inet_ntoa(test_nm));
  555. uassert_true(RT_TRUE);
  556. /* Restore original network configuration */
  557. netdev_set_ipaddr(netdev_default, &original_ip);
  558. netdev_set_gw(netdev_default, &original_gw);
  559. netdev_set_netmask(netdev_default, &original_nm);
  560. }
  561. /* Network device callback test variables */
  562. static rt_bool_t callback_called = RT_FALSE; /**< General callback called flag */
  563. static enum netdev_cb_type last_callback_type = NETDEV_CB_ADDR_IP; /**< Last callback type received */
  564. static rt_bool_t ip_callback_called = RT_FALSE; /**< IP address callback flag */
  565. static rt_bool_t gw_callback_called = RT_FALSE; /**< Gateway callback flag */
  566. static rt_bool_t dhcp_callback_called = RT_FALSE; /**< DHCP callback flag */
  567. /* Event for synchronizing callback tests */
  568. static rt_event_t callback_event;
  569. /**
  570. * @brief Helper function for testing callback operations
  571. *
  572. * This function performs a network operation and waits for the corresponding
  573. * callback to be triggered within a specified timeout.
  574. *
  575. * @param operation Function pointer to the operation to perform
  576. * @param param Parameter to pass to the operation
  577. * @param event_mask Event mask to wait for
  578. * @param callback_flag Pointer to callback flag to check
  579. * @param test_name Name of the test for logging purposes
  580. */
  581. static void test_callback_operation(rt_err_t (*operation)(struct netdev *, void *),
  582. void *param,
  583. rt_uint32_t event_mask,
  584. rt_bool_t *callback_flag,
  585. const char *test_name)
  586. {
  587. rt_err_t res;
  588. rt_uint32_t recved;
  589. /* Reset callback flag */
  590. *callback_flag = RT_FALSE;
  591. /* Perform operation */
  592. res = operation(netdev_default, param);
  593. if (res == RT_EOK)
  594. {
  595. /* Wait for callback event */
  596. rt_err_t event_res = rt_event_recv(callback_event, event_mask,
  597. RT_EVENT_FLAG_AND | RT_EVENT_FLAG_CLEAR,
  598. CALLBACK_EVENT_TIMEOUT, &recved);
  599. if (event_res == RT_EOK && *callback_flag)
  600. {
  601. rt_kprintf("%s test passed\n", test_name);
  602. uassert_true(RT_TRUE);
  603. }
  604. else
  605. {
  606. rt_kprintf("%s test failed - event_res=%d, callback_called=%d\n",
  607. test_name, event_res, *callback_flag);
  608. uassert_true(RT_FALSE);
  609. }
  610. }
  611. else
  612. {
  613. rt_kprintf("Failed to perform %s: %d\n", test_name, res);
  614. uassert_true(RT_FALSE);
  615. }
  616. }
  617. /* Wrapper functions for callback testing */
  618. static rt_err_t set_ipaddr_wrapper(struct netdev *netdev, void *param)
  619. {
  620. return netdev_set_ipaddr(netdev, (ip_addr_t *)param);
  621. }
  622. static rt_err_t set_gw_wrapper(struct netdev *netdev, void *param)
  623. {
  624. return netdev_set_gw(netdev, (ip_addr_t *)param);
  625. }
  626. static rt_err_t dhcp_enable_wrapper(struct netdev *netdev, void *param)
  627. {
  628. return netdev_dhcp_enabled(netdev, *(rt_bool_t *)param);
  629. }
  630. static void test_callback(struct netdev *netdev, enum netdev_cb_type type)
  631. {
  632. callback_called = RT_TRUE;
  633. last_callback_type = type;
  634. rt_kprintf("Callback called: type=%d, netdev=%s\n", type, netdev->name);
  635. /* Track specific callback types */
  636. switch (type)
  637. {
  638. case NETDEV_CB_ADDR_IP:
  639. ip_callback_called = RT_TRUE;
  640. break;
  641. case NETDEV_CB_ADDR_GATEWAY:
  642. gw_callback_called = RT_TRUE;
  643. break;
  644. case NETDEV_CB_STATUS_DHCP_ENABLE:
  645. dhcp_callback_called = RT_TRUE;
  646. break;
  647. default:
  648. break;
  649. }
  650. /* Send event to synchronize */
  651. if (callback_event)
  652. {
  653. rt_event_send(callback_event, 1 << type);
  654. }
  655. }
  656. static void empty_callback(struct netdev *netdev, enum netdev_cb_type type)
  657. {
  658. /* Empty callback function for clearing */
  659. }
  660. /**
  661. * @brief Test network device callback mechanism
  662. *
  663. * This function tests the callback functionality for network events:
  664. * - Setting status and address callbacks
  665. * - IP address change callbacks
  666. * - Gateway change callbacks
  667. * - DHCP enable callbacks
  668. * - Callback synchronization using events
  669. * - Callback cleanup
  670. *
  671. * @note Uses event synchronization to verify callbacks are properly triggered
  672. */
  673. static void test_netdev_callbacks(void)
  674. {
  675. ip_addr_t test_ip, test_gw;
  676. rt_bool_t dhcp_enable = RT_TRUE;
  677. /* Reset callback test variables */
  678. callback_called = RT_FALSE;
  679. last_callback_type = NETDEV_CB_ADDR_IP;
  680. ip_callback_called = RT_FALSE;
  681. gw_callback_called = RT_FALSE;
  682. dhcp_callback_called = RT_FALSE;
  683. /* Set status callback */
  684. netdev_set_status_callback(netdev_default, test_callback);
  685. /* Set address callback */
  686. netdev_set_addr_callback(netdev_default, test_callback);
  687. /* Test IP address change callback */
  688. inet_aton("192.168.1.100", &test_ip);
  689. test_callback_operation(set_ipaddr_wrapper, &test_ip,
  690. 1 << NETDEV_CB_ADDR_IP, &ip_callback_called, "IP address");
  691. /* Reset callback flags */
  692. ip_callback_called = RT_FALSE;
  693. gw_callback_called = RT_FALSE;
  694. /* Test gateway change callback */
  695. inet_aton("192.168.1.1", &test_gw);
  696. test_callback_operation(set_gw_wrapper, &test_gw,
  697. 1 << NETDEV_CB_ADDR_GATEWAY, &gw_callback_called, "Gateway");
  698. /* Reset callback flags */
  699. dhcp_callback_called = RT_FALSE;
  700. /* Test DHCP enable callback */
  701. test_callback_operation(dhcp_enable_wrapper, &dhcp_enable,
  702. 1 << NETDEV_CB_STATUS_DHCP_ENABLE, &dhcp_callback_called, "DHCP enable");
  703. /* Clear callbacks */
  704. netdev_set_status_callback(netdev_default, empty_callback);
  705. netdev_set_addr_callback(netdev_default, empty_callback);
  706. }
  707. /**
  708. * @brief Test multiple network interfaces functionality
  709. *
  710. * This function tests:
  711. * - Creating and registering a new network device
  712. * - Network device search and verification
  713. * - Default network device switching
  714. * - Interface index assignment and lookup
  715. * - Network device list management
  716. * - Network device unregistration and cleanup
  717. *
  718. * @note Creates a temporary test network device for comprehensive testing
  719. */
  720. static void test_netdev_multiple_interfaces(void)
  721. {
  722. /* Test network device name */
  723. #define TEST_NETDEV_NAME "fake-e0"
  724. struct netdev *test_netdev = RT_NULL;
  725. struct netdev *found_netdev = RT_NULL;
  726. struct netdev *original_default = netdev_default;
  727. ip_addr_t test_ip;
  728. int result;
  729. rt_slist_t *node = RT_NULL;
  730. struct netdev *current_netdev;
  731. int netdev_count = 0;
  732. rt_bool_t found_original = RT_FALSE;
  733. rt_bool_t found_test = RT_FALSE;
  734. /* Allocate memory for test netdev */
  735. test_netdev = rt_malloc(sizeof(struct netdev));
  736. if (test_netdev == RT_NULL)
  737. {
  738. rt_kprintf("Failed to allocate memory for test netdev\n");
  739. uassert_true(RT_FALSE);
  740. return;
  741. }
  742. /* Initialize test netdev structure */
  743. rt_memset(test_netdev, 0, sizeof(struct netdev));
  744. /* Set basic properties */
  745. test_netdev->hwaddr_len = 6;
  746. test_netdev->hwaddr[0] = 0x01;
  747. test_netdev->hwaddr[1] = 0x02;
  748. test_netdev->hwaddr[2] = 0x03;
  749. test_netdev->hwaddr[3] = 0x04;
  750. test_netdev->hwaddr[4] = 0x05;
  751. test_netdev->hwaddr[5] = 0x06;
  752. test_netdev->mtu = 1500;
  753. test_netdev->flags = NETDEV_FLAG_UP | NETDEV_FLAG_LINK_UP;
  754. /* Set IP address */
  755. inet_aton("192.168.2.100", &test_ip);
  756. ip_addr_copy(test_netdev->ip_addr, test_ip);
  757. inet_aton("255.255.255.0", &test_ip);
  758. ip_addr_copy(test_netdev->netmask, test_ip);
  759. inet_aton("192.168.2.1", &test_ip);
  760. ip_addr_copy(test_netdev->gw, test_ip);
  761. /* Register the test netdev */
  762. result = netdev_register(test_netdev, TEST_NETDEV_NAME, RT_NULL);
  763. if (result != RT_EOK)
  764. {
  765. rt_kprintf("Failed to register test netdev: %d\n", result);
  766. rt_free(test_netdev);
  767. uassert_true(RT_FALSE);
  768. return;
  769. }
  770. rt_kprintf("Successfully registered test netdev '%s'\n", TEST_NETDEV_NAME);
  771. /* Verify the test netdev can be found by name */
  772. found_netdev = netdev_get_by_name(TEST_NETDEV_NAME);
  773. uassert_true(found_netdev == test_netdev);
  774. /* Verify the test netdev can be found by IP address */
  775. found_netdev = netdev_get_by_ipaddr(&test_netdev->ip_addr);
  776. uassert_true(found_netdev == test_netdev);
  777. /* Test default netdev switching */
  778. netdev_set_default(test_netdev);
  779. uassert_true(netdev_default == test_netdev);
  780. /* Switch back to original default */
  781. netdev_set_default(original_default);
  782. uassert_true(netdev_default == original_default);
  783. /* Test netdev ifindex */
  784. uassert_true(test_netdev->ifindex > 0);
  785. found_netdev = netdev_get_by_ifindex(test_netdev->ifindex);
  786. uassert_true(found_netdev == test_netdev);
  787. if (netdev_list == RT_NULL)
  788. {
  789. rt_kprintf("Netdev list is empty\n");
  790. uassert_true(RT_FALSE);
  791. return;
  792. }
  793. for (node = &(netdev_list->list); node; node = rt_slist_next(node))
  794. {
  795. current_netdev = rt_list_entry(node, struct netdev, list);
  796. netdev_count++;
  797. if (rt_strcmp(current_netdev->name, original_default->name) == 0)
  798. {
  799. found_original = RT_TRUE;
  800. }
  801. if (rt_strcmp(current_netdev->name, TEST_NETDEV_NAME) == 0)
  802. {
  803. found_test = RT_TRUE;
  804. }
  805. }
  806. uassert_true(netdev_count >= 2); /* At least original + test */
  807. uassert_true(found_original);
  808. uassert_true(found_test);
  809. /* Cleanup: Unregister the test netdev */
  810. result = netdev_unregister(test_netdev);
  811. if (result == RT_EOK)
  812. {
  813. test_netdev = RT_NULL;
  814. rt_free(test_netdev);
  815. }
  816. else
  817. {
  818. rt_kprintf("Failed to unregister test netdev: %d\n", result);
  819. /* Manual cleanup if unregister failed */
  820. if (test_netdev != RT_NULL)
  821. {
  822. rt_free(test_netdev);
  823. test_netdev = RT_NULL;
  824. }
  825. }
  826. /* Verify test netdev is no longer accessible */
  827. found_netdev = netdev_get_by_name(TEST_NETDEV_NAME);
  828. uassert_true(found_netdev == RT_NULL);
  829. }
  830. /**
  831. * @brief Unit test initialization function
  832. *
  833. * This function performs setup operations before running tests:
  834. * - Creates callback synchronization event
  835. * - Locates and configures the test network device
  836. * - Saves initial network configuration for restoration
  837. * - Waits for network connectivity to be established
  838. * - Sets the test network device as default
  839. *
  840. * @return rt_err_t RT_EOK on success, -RT_ERROR on failure
  841. */
  842. static rt_err_t utest_tc_init(void)
  843. {
  844. struct netdev *netdev_lwip = RT_NULL;
  845. /* Create event for callback synchronization */
  846. callback_event = rt_event_create("callback_event", RT_IPC_FLAG_FIFO);
  847. if (callback_event == RT_NULL)
  848. {
  849. rt_kprintf("Failed to create callback event\n");
  850. return -RT_ERROR;
  851. }
  852. netdev_lwip = netdev_get_by_name(RT_UTEST_DEFAULT_NETDEV_NAME);
  853. if (netdev_lwip == RT_NULL)
  854. {
  855. rt_kprintf("Network interface device not found!\n");
  856. return -RT_ERROR;
  857. }
  858. /* Save initial network configuration */
  859. initial_ip_addr = netdev_lwip->ip_addr;
  860. initial_netmask = netdev_lwip->netmask;
  861. initial_gw = netdev_lwip->gw;
  862. initial_dns0 = netdev_lwip->dns_servers[0];
  863. initial_dns1 = netdev_lwip->dns_servers[1];
  864. initial_dhcp_enabled = netdev_is_dhcp_enabled(netdev_lwip);
  865. rt_kprintf("Saved initial network config - IP: %s, DHCP: %s\n",
  866. inet_ntoa(initial_ip_addr),
  867. initial_dhcp_enabled ? "enabled" : "disabled");
  868. /* Wait for network connect successful */
  869. while (1)
  870. {
  871. if (!ip_addr_isany(&netdev_lwip->ip_addr))
  872. {
  873. rt_kprintf("IP address assigned: %s\n", inet_ntoa(netdev_lwip->ip_addr));
  874. break;
  875. }
  876. rt_thread_mdelay(500);
  877. }
  878. /* Save the old netdev */
  879. netdev_default_old = netdev_default;
  880. netdev_set_default(netdev_lwip);
  881. if (netdev_default == RT_NULL)
  882. {
  883. rt_kprintf("No default network interface!\n");
  884. return -RT_ERROR;
  885. }
  886. return RT_EOK;
  887. }
  888. /**
  889. * @brief Unit test cleanup function
  890. *
  891. * This function performs cleanup operations after running tests:
  892. * - Deletes callback synchronization event
  893. * - Restores original network configuration
  894. * - Restores original DHCP settings
  895. * - Restores original default network device
  896. *
  897. * @return rt_err_t RT_EOK on success
  898. */
  899. static rt_err_t utest_tc_cleanup(void)
  900. {
  901. rt_err_t res;
  902. /* Delete callback event */
  903. if (callback_event)
  904. {
  905. rt_event_delete(callback_event);
  906. callback_event = RT_NULL;
  907. }
  908. /* Restore initial network configuration */
  909. if (netdev_default != RT_NULL)
  910. {
  911. rt_kprintf("Restoring initial network configuration...\n");
  912. /* First disable DHCP if it's enabled */
  913. if (netdev_is_dhcp_enabled(netdev_default))
  914. {
  915. res = netdev_dhcp_enabled(netdev_default, RT_FALSE);
  916. if (res != RT_EOK)
  917. {
  918. rt_kprintf("Warning: Failed to disable DHCP: %d\n", res);
  919. }
  920. }
  921. /* Restore network configuration */
  922. res = netdev_set_ipaddr(netdev_default, &initial_ip_addr);
  923. if (res != RT_EOK) rt_kprintf("Warning: Failed to restore IP address: %d\n", res);
  924. res = netdev_set_netmask(netdev_default, &initial_netmask);
  925. if (res != RT_EOK) rt_kprintf("Warning: Failed to restore netmask: %d\n", res);
  926. res = netdev_set_gw(netdev_default, &initial_gw);
  927. if (res != RT_EOK) rt_kprintf("Warning: Failed to restore gateway: %d\n", res);
  928. res = netdev_set_dns_server(netdev_default, 0, &initial_dns0);
  929. if (res != RT_EOK) rt_kprintf("Warning: Failed to restore DNS0: %d\n", res);
  930. res = netdev_set_dns_server(netdev_default, 1, &initial_dns1);
  931. if (res != RT_EOK) rt_kprintf("Warning: Failed to restore DNS1: %d\n", res);
  932. /* Restore DHCP state */
  933. if (initial_dhcp_enabled)
  934. {
  935. rt_kprintf("Restoring DHCP...\n");
  936. res = netdev_dhcp_enabled(netdev_default, RT_TRUE);
  937. if (res != RT_EOK)
  938. {
  939. rt_kprintf("Warning: Failed to restore DHCP: %d\n", res);
  940. }
  941. else
  942. {
  943. rt_kprintf("DHCP restored, waiting for IP address...\n");
  944. }
  945. }
  946. rt_kprintf("Network configuration restoration completed\n");
  947. }
  948. netdev_set_default(netdev_default_old);
  949. return RT_EOK;
  950. }
  951. static void testcase(void)
  952. {
  953. /* Test DHCP functionality */
  954. UTEST_UNIT_RUN(test_netdev_dhcp);
  955. /* Test network connectivity using ping operations */
  956. UTEST_UNIT_RUN(test_netdev_ping);
  957. /* Test network interface configuration and status */
  958. UTEST_UNIT_RUN(test_netdev_ifconfig);
  959. /* Test network statistics functionality */
  960. UTEST_UNIT_RUN(test_netdev_netstat);
  961. /* Test DNS server configuration and hostname resolution */
  962. UTEST_UNIT_RUN(test_netdev_dns);
  963. /* Test setting network interface configuration parameters */
  964. UTEST_UNIT_RUN(test_netdev_ifconfig_set);
  965. /* Test setting the default network device */
  966. UTEST_UNIT_RUN(test_netdev_set_default_netdev);
  967. /* Test IP address conversion functions */
  968. UTEST_UNIT_RUN(test_netdev_ipaddr_conversion);
  969. /* Test network device retrieval functions */
  970. UTEST_UNIT_RUN(test_netdev_get_functions);
  971. /* Test network device status setting operations */
  972. UTEST_UNIT_RUN(test_netdev_status_set);
  973. /* Test network device configuration setting operations */
  974. UTEST_UNIT_RUN(test_netdev_config_set);
  975. /* Test network device callback mechanisms */
  976. UTEST_UNIT_RUN(test_netdev_callbacks);
  977. /* Test multiple network interfaces functionality */
  978. UTEST_UNIT_RUN(test_netdev_multiple_interfaces);
  979. }
  980. UTEST_TC_EXPORT(testcase, "components.net.tc_netdev", utest_tc_init, utest_tc_cleanup, 1000);