1195972f6Sopenharmony_ci#include "test_etharp.h" 2195972f6Sopenharmony_ci 3195972f6Sopenharmony_ci#include "lwip/udp.h" 4195972f6Sopenharmony_ci#include "lwip/etharp.h" 5195972f6Sopenharmony_ci#include "netif/ethernet.h" 6195972f6Sopenharmony_ci#include "lwip/stats.h" 7195972f6Sopenharmony_ci#include "lwip/prot/iana.h" 8195972f6Sopenharmony_ci 9195972f6Sopenharmony_ci#if !LWIP_STATS || !UDP_STATS || !MEMP_STATS || !ETHARP_STATS 10195972f6Sopenharmony_ci#error "This tests needs UDP-, MEMP- and ETHARP-statistics enabled" 11195972f6Sopenharmony_ci#endif 12195972f6Sopenharmony_ci#if !ETHARP_SUPPORT_STATIC_ENTRIES 13195972f6Sopenharmony_ci#error "This test needs ETHARP_SUPPORT_STATIC_ENTRIES enabled" 14195972f6Sopenharmony_ci#endif 15195972f6Sopenharmony_ci 16195972f6Sopenharmony_cistatic struct netif test_netif; 17195972f6Sopenharmony_cistatic ip4_addr_t test_ipaddr, test_netmask, test_gw; 18195972f6Sopenharmony_cistruct eth_addr test_ethaddr = {{1,1,1,1,1,1}}; 19195972f6Sopenharmony_cistruct eth_addr test_ethaddr2 = {{1,1,1,1,1,2}}; 20195972f6Sopenharmony_cistruct eth_addr test_ethaddr3 = {{1,1,1,1,1,3}}; 21195972f6Sopenharmony_cistruct eth_addr test_ethaddr4 = {{1,1,1,1,1,4}}; 22195972f6Sopenharmony_cistatic int linkoutput_ctr; 23195972f6Sopenharmony_ci 24195972f6Sopenharmony_ci/* Helper functions */ 25195972f6Sopenharmony_cistatic void 26195972f6Sopenharmony_cietharp_remove_all(void) 27195972f6Sopenharmony_ci{ 28195972f6Sopenharmony_ci int i; 29195972f6Sopenharmony_ci /* call etharp_tmr often enough to have all entries cleaned */ 30195972f6Sopenharmony_ci for(i = 0; i < 0xff; i++) { 31195972f6Sopenharmony_ci etharp_tmr(); 32195972f6Sopenharmony_ci } 33195972f6Sopenharmony_ci} 34195972f6Sopenharmony_ci 35195972f6Sopenharmony_cistatic err_t 36195972f6Sopenharmony_cidefault_netif_linkoutput(struct netif *netif, struct pbuf *p) 37195972f6Sopenharmony_ci{ 38195972f6Sopenharmony_ci fail_unless(netif == &test_netif); 39195972f6Sopenharmony_ci fail_unless(p != NULL); 40195972f6Sopenharmony_ci linkoutput_ctr++; 41195972f6Sopenharmony_ci return ERR_OK; 42195972f6Sopenharmony_ci} 43195972f6Sopenharmony_ci 44195972f6Sopenharmony_cistatic err_t 45195972f6Sopenharmony_cidefault_netif_init(struct netif *netif) 46195972f6Sopenharmony_ci{ 47195972f6Sopenharmony_ci fail_unless(netif != NULL); 48195972f6Sopenharmony_ci netif->linkoutput = default_netif_linkoutput; 49195972f6Sopenharmony_ci netif->output = etharp_output; 50195972f6Sopenharmony_ci netif->mtu = 1500; 51195972f6Sopenharmony_ci netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; 52195972f6Sopenharmony_ci netif->hwaddr_len = ETHARP_HWADDR_LEN; 53195972f6Sopenharmony_ci return ERR_OK; 54195972f6Sopenharmony_ci} 55195972f6Sopenharmony_ci 56195972f6Sopenharmony_cistatic void 57195972f6Sopenharmony_cidefault_netif_add(void) 58195972f6Sopenharmony_ci{ 59195972f6Sopenharmony_ci IP4_ADDR(&test_gw, 192,168,0,1); 60195972f6Sopenharmony_ci IP4_ADDR(&test_ipaddr, 192,168,0,1); 61195972f6Sopenharmony_ci IP4_ADDR(&test_netmask, 255,255,0,0); 62195972f6Sopenharmony_ci 63195972f6Sopenharmony_ci fail_unless(netif_default == NULL); 64195972f6Sopenharmony_ci netif_set_default(netif_add(&test_netif, &test_ipaddr, &test_netmask, 65195972f6Sopenharmony_ci &test_gw, NULL, default_netif_init, NULL)); 66195972f6Sopenharmony_ci netif_set_up(&test_netif); 67195972f6Sopenharmony_ci} 68195972f6Sopenharmony_ci 69195972f6Sopenharmony_cistatic void 70195972f6Sopenharmony_cidefault_netif_remove(void) 71195972f6Sopenharmony_ci{ 72195972f6Sopenharmony_ci fail_unless(netif_default == &test_netif); 73195972f6Sopenharmony_ci netif_remove(&test_netif); 74195972f6Sopenharmony_ci} 75195972f6Sopenharmony_ci 76195972f6Sopenharmony_cistatic void 77195972f6Sopenharmony_cicreate_arp_response(ip4_addr_t *adr) 78195972f6Sopenharmony_ci{ 79195972f6Sopenharmony_ci int k; 80195972f6Sopenharmony_ci struct eth_hdr *ethhdr; 81195972f6Sopenharmony_ci struct etharp_hdr *etharphdr; 82195972f6Sopenharmony_ci struct pbuf *p = pbuf_alloc(PBUF_RAW, sizeof(struct eth_hdr) + sizeof(struct etharp_hdr), PBUF_RAM); 83195972f6Sopenharmony_ci if(p == NULL) { 84195972f6Sopenharmony_ci FAIL_RET(); 85195972f6Sopenharmony_ci } 86195972f6Sopenharmony_ci ethhdr = (struct eth_hdr*)p->payload; 87195972f6Sopenharmony_ci etharphdr = (struct etharp_hdr*)(ethhdr + 1); 88195972f6Sopenharmony_ci 89195972f6Sopenharmony_ci ethhdr->dest = test_ethaddr; 90195972f6Sopenharmony_ci ethhdr->src = test_ethaddr2; 91195972f6Sopenharmony_ci ethhdr->type = htons(ETHTYPE_ARP); 92195972f6Sopenharmony_ci 93195972f6Sopenharmony_ci etharphdr->hwtype = htons(LWIP_IANA_HWTYPE_ETHERNET); 94195972f6Sopenharmony_ci etharphdr->proto = htons(ETHTYPE_IP); 95195972f6Sopenharmony_ci etharphdr->hwlen = ETHARP_HWADDR_LEN; 96195972f6Sopenharmony_ci etharphdr->protolen = sizeof(ip4_addr_t); 97195972f6Sopenharmony_ci etharphdr->opcode = htons(ARP_REPLY); 98195972f6Sopenharmony_ci 99195972f6Sopenharmony_ci SMEMCPY(ðarphdr->sipaddr, adr, sizeof(ip4_addr_t)); 100195972f6Sopenharmony_ci SMEMCPY(ðarphdr->dipaddr, &test_ipaddr, sizeof(ip4_addr_t)); 101195972f6Sopenharmony_ci 102195972f6Sopenharmony_ci k = 6; 103195972f6Sopenharmony_ci while(k > 0) { 104195972f6Sopenharmony_ci k--; 105195972f6Sopenharmony_ci /* Write the ARP MAC-Addresses */ 106195972f6Sopenharmony_ci etharphdr->shwaddr.addr[k] = test_ethaddr2.addr[k]; 107195972f6Sopenharmony_ci etharphdr->dhwaddr.addr[k] = test_ethaddr.addr[k]; 108195972f6Sopenharmony_ci /* Write the Ethernet MAC-Addresses */ 109195972f6Sopenharmony_ci ethhdr->dest.addr[k] = test_ethaddr.addr[k]; 110195972f6Sopenharmony_ci ethhdr->src.addr[k] = test_ethaddr2.addr[k]; 111195972f6Sopenharmony_ci } 112195972f6Sopenharmony_ci 113195972f6Sopenharmony_ci ethernet_input(p, &test_netif); 114195972f6Sopenharmony_ci} 115195972f6Sopenharmony_ci 116195972f6Sopenharmony_ci/* Setups/teardown functions */ 117195972f6Sopenharmony_ci 118195972f6Sopenharmony_cistatic void 119195972f6Sopenharmony_cietharp_setup(void) 120195972f6Sopenharmony_ci{ 121195972f6Sopenharmony_ci etharp_remove_all(); 122195972f6Sopenharmony_ci default_netif_add(); 123195972f6Sopenharmony_ci lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT)); 124195972f6Sopenharmony_ci} 125195972f6Sopenharmony_ci 126195972f6Sopenharmony_cistatic void 127195972f6Sopenharmony_cietharp_teardown(void) 128195972f6Sopenharmony_ci{ 129195972f6Sopenharmony_ci etharp_remove_all(); 130195972f6Sopenharmony_ci default_netif_remove(); 131195972f6Sopenharmony_ci lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT)); 132195972f6Sopenharmony_ci} 133195972f6Sopenharmony_ci 134195972f6Sopenharmony_ci 135195972f6Sopenharmony_ci/* Test functions */ 136195972f6Sopenharmony_ci 137195972f6Sopenharmony_ciSTART_TEST(test_etharp_table) 138195972f6Sopenharmony_ci{ 139195972f6Sopenharmony_ci#if ETHARP_SUPPORT_STATIC_ENTRIES 140195972f6Sopenharmony_ci err_t err; 141195972f6Sopenharmony_ci#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ 142195972f6Sopenharmony_ci ssize_t idx; 143195972f6Sopenharmony_ci const ip4_addr_t *unused_ipaddr; 144195972f6Sopenharmony_ci struct eth_addr *unused_ethaddr; 145195972f6Sopenharmony_ci struct udp_pcb* pcb; 146195972f6Sopenharmony_ci LWIP_UNUSED_ARG(_i); 147195972f6Sopenharmony_ci 148195972f6Sopenharmony_ci if (netif_default != &test_netif) { 149195972f6Sopenharmony_ci fail("This test needs a default netif"); 150195972f6Sopenharmony_ci } 151195972f6Sopenharmony_ci 152195972f6Sopenharmony_ci linkoutput_ctr = 0; 153195972f6Sopenharmony_ci 154195972f6Sopenharmony_ci pcb = udp_new(); 155195972f6Sopenharmony_ci fail_unless(pcb != NULL); 156195972f6Sopenharmony_ci if (pcb != NULL) { 157195972f6Sopenharmony_ci ip4_addr_t adrs[ARP_TABLE_SIZE + 2]; 158195972f6Sopenharmony_ci int i; 159195972f6Sopenharmony_ci for(i = 0; i < ARP_TABLE_SIZE + 2; i++) { 160195972f6Sopenharmony_ci IP4_ADDR(&adrs[i], 192,168,0,i+2); 161195972f6Sopenharmony_ci } 162195972f6Sopenharmony_ci /* fill ARP-table with dynamic entries */ 163195972f6Sopenharmony_ci for(i = 0; i < ARP_TABLE_SIZE; i++) { 164195972f6Sopenharmony_ci struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, 10, PBUF_RAM); 165195972f6Sopenharmony_ci fail_unless(p != NULL); 166195972f6Sopenharmony_ci if (p != NULL) { 167195972f6Sopenharmony_ci err_t err2; 168195972f6Sopenharmony_ci ip_addr_t dst; 169195972f6Sopenharmony_ci ip_addr_copy_from_ip4(dst, adrs[i]); 170195972f6Sopenharmony_ci err2 = udp_sendto(pcb, p, &dst, 123); 171195972f6Sopenharmony_ci fail_unless(err2 == ERR_OK); 172195972f6Sopenharmony_ci /* etharp request sent? */ 173195972f6Sopenharmony_ci fail_unless(linkoutput_ctr == (2*i) + 1); 174195972f6Sopenharmony_ci pbuf_free(p); 175195972f6Sopenharmony_ci 176195972f6Sopenharmony_ci /* create an ARP response */ 177195972f6Sopenharmony_ci create_arp_response(&adrs[i]); 178195972f6Sopenharmony_ci /* queued UDP packet sent? */ 179195972f6Sopenharmony_ci fail_unless(linkoutput_ctr == (2*i) + 2); 180195972f6Sopenharmony_ci 181195972f6Sopenharmony_ci idx = etharp_find_addr(NULL, &adrs[i], &unused_ethaddr, &unused_ipaddr); 182195972f6Sopenharmony_ci fail_unless(idx == i); 183195972f6Sopenharmony_ci etharp_tmr(); 184195972f6Sopenharmony_ci } 185195972f6Sopenharmony_ci } 186195972f6Sopenharmony_ci linkoutput_ctr = 0; 187195972f6Sopenharmony_ci#if ETHARP_SUPPORT_STATIC_ENTRIES 188195972f6Sopenharmony_ci /* create one static entry */ 189195972f6Sopenharmony_ci err = etharp_add_static_entry(&adrs[ARP_TABLE_SIZE], &test_ethaddr3); 190195972f6Sopenharmony_ci fail_unless(err == ERR_OK); 191195972f6Sopenharmony_ci idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE], &unused_ethaddr, &unused_ipaddr); 192195972f6Sopenharmony_ci fail_unless(idx == 0); 193195972f6Sopenharmony_ci fail_unless(linkoutput_ctr == 0); 194195972f6Sopenharmony_ci#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ 195195972f6Sopenharmony_ci 196195972f6Sopenharmony_ci linkoutput_ctr = 0; 197195972f6Sopenharmony_ci /* fill ARP-table with dynamic entries */ 198195972f6Sopenharmony_ci for(i = 0; i < ARP_TABLE_SIZE; i++) { 199195972f6Sopenharmony_ci struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, 10, PBUF_RAM); 200195972f6Sopenharmony_ci fail_unless(p != NULL); 201195972f6Sopenharmony_ci if (p != NULL) { 202195972f6Sopenharmony_ci err_t err2; 203195972f6Sopenharmony_ci ip_addr_t dst; 204195972f6Sopenharmony_ci ip_addr_copy_from_ip4(dst, adrs[i]); 205195972f6Sopenharmony_ci err2 = udp_sendto(pcb, p, &dst, 123); 206195972f6Sopenharmony_ci fail_unless(err2 == ERR_OK); 207195972f6Sopenharmony_ci /* etharp request sent? */ 208195972f6Sopenharmony_ci fail_unless(linkoutput_ctr == (2*i) + 1); 209195972f6Sopenharmony_ci pbuf_free(p); 210195972f6Sopenharmony_ci 211195972f6Sopenharmony_ci /* create an ARP response */ 212195972f6Sopenharmony_ci create_arp_response(&adrs[i]); 213195972f6Sopenharmony_ci /* queued UDP packet sent? */ 214195972f6Sopenharmony_ci fail_unless(linkoutput_ctr == (2*i) + 2); 215195972f6Sopenharmony_ci 216195972f6Sopenharmony_ci idx = etharp_find_addr(NULL, &adrs[i], &unused_ethaddr, &unused_ipaddr); 217195972f6Sopenharmony_ci if (i < ARP_TABLE_SIZE - 1) { 218195972f6Sopenharmony_ci fail_unless(idx == i+1); 219195972f6Sopenharmony_ci } else { 220195972f6Sopenharmony_ci /* the last entry must not overwrite the static entry! */ 221195972f6Sopenharmony_ci fail_unless(idx == 1); 222195972f6Sopenharmony_ci } 223195972f6Sopenharmony_ci etharp_tmr(); 224195972f6Sopenharmony_ci } 225195972f6Sopenharmony_ci } 226195972f6Sopenharmony_ci#if ETHARP_SUPPORT_STATIC_ENTRIES 227195972f6Sopenharmony_ci /* create a second static entry */ 228195972f6Sopenharmony_ci err = etharp_add_static_entry(&adrs[ARP_TABLE_SIZE+1], &test_ethaddr4); 229195972f6Sopenharmony_ci fail_unless(err == ERR_OK); 230195972f6Sopenharmony_ci idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE], &unused_ethaddr, &unused_ipaddr); 231195972f6Sopenharmony_ci fail_unless(idx == 0); 232195972f6Sopenharmony_ci idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE+1], &unused_ethaddr, &unused_ipaddr); 233195972f6Sopenharmony_ci fail_unless(idx == 2); 234195972f6Sopenharmony_ci /* and remove it again */ 235195972f6Sopenharmony_ci err = etharp_remove_static_entry(&adrs[ARP_TABLE_SIZE+1]); 236195972f6Sopenharmony_ci fail_unless(err == ERR_OK); 237195972f6Sopenharmony_ci idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE], &unused_ethaddr, &unused_ipaddr); 238195972f6Sopenharmony_ci fail_unless(idx == 0); 239195972f6Sopenharmony_ci idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE+1], &unused_ethaddr, &unused_ipaddr); 240195972f6Sopenharmony_ci fail_unless(idx == -1); 241195972f6Sopenharmony_ci#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ 242195972f6Sopenharmony_ci 243195972f6Sopenharmony_ci /* check that static entries don't time out */ 244195972f6Sopenharmony_ci etharp_remove_all(); 245195972f6Sopenharmony_ci idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE], &unused_ethaddr, &unused_ipaddr); 246195972f6Sopenharmony_ci fail_unless(idx == 0); 247195972f6Sopenharmony_ci 248195972f6Sopenharmony_ci#if ETHARP_SUPPORT_STATIC_ENTRIES 249195972f6Sopenharmony_ci /* remove the first static entry */ 250195972f6Sopenharmony_ci err = etharp_remove_static_entry(&adrs[ARP_TABLE_SIZE]); 251195972f6Sopenharmony_ci fail_unless(err == ERR_OK); 252195972f6Sopenharmony_ci idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE], &unused_ethaddr, &unused_ipaddr); 253195972f6Sopenharmony_ci fail_unless(idx == -1); 254195972f6Sopenharmony_ci idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE+1], &unused_ethaddr, &unused_ipaddr); 255195972f6Sopenharmony_ci fail_unless(idx == -1); 256195972f6Sopenharmony_ci#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ 257195972f6Sopenharmony_ci 258195972f6Sopenharmony_ci udp_remove(pcb); 259195972f6Sopenharmony_ci } 260195972f6Sopenharmony_ci} 261195972f6Sopenharmony_ciEND_TEST 262195972f6Sopenharmony_ci 263195972f6Sopenharmony_ci 264195972f6Sopenharmony_ci/** Create the suite including all tests for this module */ 265195972f6Sopenharmony_ciSuite * 266195972f6Sopenharmony_cietharp_suite(void) 267195972f6Sopenharmony_ci{ 268195972f6Sopenharmony_ci testfunc tests[] = { 269195972f6Sopenharmony_ci TESTFUNC(test_etharp_table) 270195972f6Sopenharmony_ci }; 271195972f6Sopenharmony_ci return create_suite("ETHARP", tests, sizeof(tests)/sizeof(testfunc), etharp_setup, etharp_teardown); 272195972f6Sopenharmony_ci} 273