1 #include "test_etharp.h" 2 3 #include "lwip/udp.h" 4 #include "lwip/etharp.h" 5 #include "netif/ethernet.h" 6 #include "lwip/stats.h" 7 #include "lwip/prot/iana.h" 8 9 #if !LWIP_STATS || !UDP_STATS || !MEMP_STATS || !ETHARP_STATS 10 #error "This tests needs UDP-, MEMP- and ETHARP-statistics enabled" 11 #endif 12 #if !ETHARP_SUPPORT_STATIC_ENTRIES 13 #error "This test needs ETHARP_SUPPORT_STATIC_ENTRIES enabled" 14 #endif 15 16 static struct netif test_netif; 17 static ip4_addr_t test_ipaddr, test_netmask, test_gw; 18 struct eth_addr test_ethaddr = {{1,1,1,1,1,1}}; 19 struct eth_addr test_ethaddr2 = {{1,1,1,1,1,2}}; 20 struct eth_addr test_ethaddr3 = {{1,1,1,1,1,3}}; 21 struct eth_addr test_ethaddr4 = {{1,1,1,1,1,4}}; 22 static int linkoutput_ctr; 23 24 /* Helper functions */ 25 static void 26 etharp_remove_all(void) 27 { 28 int i; 29 /* call etharp_tmr often enough to have all entries cleaned */ 30 for(i = 0; i < 0xff; i++) { 31 etharp_tmr(); 32 } 33 } 34 35 static err_t 36 default_netif_linkoutput(struct netif *netif, struct pbuf *p) 37 { 38 fail_unless(netif == &test_netif); 39 fail_unless(p != NULL); 40 linkoutput_ctr++; 41 return ERR_OK; 42 } 43 44 static err_t 45 default_netif_init(struct netif *netif) 46 { 47 fail_unless(netif != NULL); 48 netif->linkoutput = default_netif_linkoutput; 49 netif->output = etharp_output; 50 netif->mtu = 1500; 51 netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; 52 netif->hwaddr_len = ETHARP_HWADDR_LEN; 53 return ERR_OK; 54 } 55 56 static void 57 default_netif_add(void) 58 { 59 IP4_ADDR(&test_gw, 192,168,0,1); 60 IP4_ADDR(&test_ipaddr, 192,168,0,1); 61 IP4_ADDR(&test_netmask, 255,255,0,0); 62 63 fail_unless(netif_default == NULL); 64 netif_set_default(netif_add(&test_netif, &test_ipaddr, &test_netmask, 65 &test_gw, NULL, default_netif_init, NULL)); 66 netif_set_up(&test_netif); 67 } 68 69 static void 70 default_netif_remove(void) 71 { 72 fail_unless(netif_default == &test_netif); 73 netif_remove(&test_netif); 74 } 75 76 static void 77 create_arp_response(ip4_addr_t *adr) 78 { 79 int k; 80 struct eth_hdr *ethhdr; 81 struct etharp_hdr *etharphdr; 82 struct pbuf *p = pbuf_alloc(PBUF_RAW, sizeof(struct eth_hdr) + sizeof(struct etharp_hdr), PBUF_RAM); 83 if(p == NULL) { 84 FAIL_RET(); 85 } 86 ethhdr = (struct eth_hdr*)p->payload; 87 etharphdr = (struct etharp_hdr*)(ethhdr + 1); 88 89 ethhdr->dest = test_ethaddr; 90 ethhdr->src = test_ethaddr2; 91 ethhdr->type = htons(ETHTYPE_ARP); 92 93 etharphdr->hwtype = htons(LWIP_IANA_HWTYPE_ETHERNET); 94 etharphdr->proto = htons(ETHTYPE_IP); 95 etharphdr->hwlen = ETHARP_HWADDR_LEN; 96 etharphdr->protolen = sizeof(ip4_addr_t); 97 etharphdr->opcode = htons(ARP_REPLY); 98 99 SMEMCPY(ðarphdr->sipaddr, adr, sizeof(ip4_addr_t)); 100 SMEMCPY(ðarphdr->dipaddr, &test_ipaddr, sizeof(ip4_addr_t)); 101 102 k = 6; 103 while(k > 0) { 104 k--; 105 /* Write the ARP MAC-Addresses */ 106 etharphdr->shwaddr.addr[k] = test_ethaddr2.addr[k]; 107 etharphdr->dhwaddr.addr[k] = test_ethaddr.addr[k]; 108 /* Write the Ethernet MAC-Addresses */ 109 ethhdr->dest.addr[k] = test_ethaddr.addr[k]; 110 ethhdr->src.addr[k] = test_ethaddr2.addr[k]; 111 } 112 113 ethernet_input(p, &test_netif); 114 } 115 116 /* Setups/teardown functions */ 117 118 static void 119 etharp_setup(void) 120 { 121 etharp_remove_all(); 122 default_netif_add(); 123 lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT)); 124 } 125 126 static void 127 etharp_teardown(void) 128 { 129 etharp_remove_all(); 130 default_netif_remove(); 131 lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT)); 132 } 133 134 135 /* Test functions */ 136 137 START_TEST(test_etharp_table) 138 { 139 #if ETHARP_SUPPORT_STATIC_ENTRIES 140 err_t err; 141 #endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ 142 ssize_t idx; 143 const ip4_addr_t *unused_ipaddr; 144 struct eth_addr *unused_ethaddr; 145 struct udp_pcb* pcb; 146 LWIP_UNUSED_ARG(_i); 147 148 if (netif_default != &test_netif) { 149 fail("This test needs a default netif"); 150 } 151 152 linkoutput_ctr = 0; 153 154 pcb = udp_new(); 155 fail_unless(pcb != NULL); 156 if (pcb != NULL) { 157 ip4_addr_t adrs[ARP_TABLE_SIZE + 2]; 158 int i; 159 for(i = 0; i < ARP_TABLE_SIZE + 2; i++) { 160 IP4_ADDR(&adrs[i], 192,168,0,i+2); 161 } 162 /* fill ARP-table with dynamic entries */ 163 for(i = 0; i < ARP_TABLE_SIZE; i++) { 164 struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, 10, PBUF_RAM); 165 fail_unless(p != NULL); 166 if (p != NULL) { 167 err_t err2; 168 ip_addr_t dst; 169 ip_addr_copy_from_ip4(dst, adrs[i]); 170 err2 = udp_sendto(pcb, p, &dst, 123); 171 fail_unless(err2 == ERR_OK); 172 /* etharp request sent? */ 173 fail_unless(linkoutput_ctr == (2*i) + 1); 174 pbuf_free(p); 175 176 /* create an ARP response */ 177 create_arp_response(&adrs[i]); 178 /* queued UDP packet sent? */ 179 fail_unless(linkoutput_ctr == (2*i) + 2); 180 181 idx = etharp_find_addr(NULL, &adrs[i], &unused_ethaddr, &unused_ipaddr); 182 fail_unless(idx == i); 183 etharp_tmr(); 184 } 185 } 186 linkoutput_ctr = 0; 187 #if ETHARP_SUPPORT_STATIC_ENTRIES 188 /* create one static entry */ 189 err = etharp_add_static_entry(&adrs[ARP_TABLE_SIZE], &test_ethaddr3); 190 fail_unless(err == ERR_OK); 191 idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE], &unused_ethaddr, &unused_ipaddr); 192 fail_unless(idx == 0); 193 fail_unless(linkoutput_ctr == 0); 194 #endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ 195 196 linkoutput_ctr = 0; 197 /* fill ARP-table with dynamic entries */ 198 for(i = 0; i < ARP_TABLE_SIZE; i++) { 199 struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, 10, PBUF_RAM); 200 fail_unless(p != NULL); 201 if (p != NULL) { 202 err_t err2; 203 ip_addr_t dst; 204 ip_addr_copy_from_ip4(dst, adrs[i]); 205 err2 = udp_sendto(pcb, p, &dst, 123); 206 fail_unless(err2 == ERR_OK); 207 /* etharp request sent? */ 208 fail_unless(linkoutput_ctr == (2*i) + 1); 209 pbuf_free(p); 210 211 /* create an ARP response */ 212 create_arp_response(&adrs[i]); 213 /* queued UDP packet sent? */ 214 fail_unless(linkoutput_ctr == (2*i) + 2); 215 216 idx = etharp_find_addr(NULL, &adrs[i], &unused_ethaddr, &unused_ipaddr); 217 if (i < ARP_TABLE_SIZE - 1) { 218 fail_unless(idx == i+1); 219 } else { 220 /* the last entry must not overwrite the static entry! */ 221 fail_unless(idx == 1); 222 } 223 etharp_tmr(); 224 } 225 } 226 #if ETHARP_SUPPORT_STATIC_ENTRIES 227 /* create a second static entry */ 228 err = etharp_add_static_entry(&adrs[ARP_TABLE_SIZE+1], &test_ethaddr4); 229 fail_unless(err == ERR_OK); 230 idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE], &unused_ethaddr, &unused_ipaddr); 231 fail_unless(idx == 0); 232 idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE+1], &unused_ethaddr, &unused_ipaddr); 233 fail_unless(idx == 2); 234 /* and remove it again */ 235 err = etharp_remove_static_entry(&adrs[ARP_TABLE_SIZE+1]); 236 fail_unless(err == ERR_OK); 237 idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE], &unused_ethaddr, &unused_ipaddr); 238 fail_unless(idx == 0); 239 idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE+1], &unused_ethaddr, &unused_ipaddr); 240 fail_unless(idx == -1); 241 #endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ 242 243 /* check that static entries don't time out */ 244 etharp_remove_all(); 245 idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE], &unused_ethaddr, &unused_ipaddr); 246 fail_unless(idx == 0); 247 248 #if ETHARP_SUPPORT_STATIC_ENTRIES 249 /* remove the first static entry */ 250 err = etharp_remove_static_entry(&adrs[ARP_TABLE_SIZE]); 251 fail_unless(err == ERR_OK); 252 idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE], &unused_ethaddr, &unused_ipaddr); 253 fail_unless(idx == -1); 254 idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE+1], &unused_ethaddr, &unused_ipaddr); 255 fail_unless(idx == -1); 256 #endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ 257 258 udp_remove(pcb); 259 } 260 } 261 END_TEST 262 263 264 /** Create the suite including all tests for this module */ 265 Suite * 266 etharp_suite(void) 267 { 268 testfunc tests[] = { 269 TESTFUNC(test_etharp_table) 270 }; 271 return create_suite("ETHARP", tests, sizeof(tests)/sizeof(testfunc), etharp_setup, etharp_teardown); 272 } 273