You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
269 lines
7.6 KiB
269 lines
7.6 KiB
#include "test_etharp.h" |
|
|
|
#include "lwip/udp.h" |
|
#include "lwip/etharp.h" |
|
#include "netif/ethernet.h" |
|
#include "lwip/stats.h" |
|
|
|
#if !LWIP_STATS || !UDP_STATS || !MEMP_STATS || !ETHARP_STATS |
|
#error "This tests needs UDP-, MEMP- and ETHARP-statistics enabled" |
|
#endif |
|
#if !ETHARP_SUPPORT_STATIC_ENTRIES |
|
#error "This test needs ETHARP_SUPPORT_STATIC_ENTRIES enabled" |
|
#endif |
|
|
|
static struct netif test_netif; |
|
static ip4_addr_t test_ipaddr, test_netmask, test_gw; |
|
struct eth_addr test_ethaddr = {{1,1,1,1,1,1}}; |
|
struct eth_addr test_ethaddr2 = {{1,1,1,1,1,2}}; |
|
struct eth_addr test_ethaddr3 = {{1,1,1,1,1,3}}; |
|
struct eth_addr test_ethaddr4 = {{1,1,1,1,1,4}}; |
|
static int linkoutput_ctr; |
|
|
|
/* Helper functions */ |
|
static void |
|
etharp_remove_all(void) |
|
{ |
|
int i; |
|
/* call etharp_tmr often enough to have all entries cleaned */ |
|
for(i = 0; i < 0xff; i++) { |
|
etharp_tmr(); |
|
} |
|
} |
|
|
|
static err_t |
|
default_netif_linkoutput(struct netif *netif, struct pbuf *p) |
|
{ |
|
fail_unless(netif == &test_netif); |
|
fail_unless(p != NULL); |
|
linkoutput_ctr++; |
|
return ERR_OK; |
|
} |
|
|
|
static err_t |
|
default_netif_init(struct netif *netif) |
|
{ |
|
fail_unless(netif != NULL); |
|
netif->linkoutput = default_netif_linkoutput; |
|
netif->output = etharp_output; |
|
netif->mtu = 1500; |
|
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; |
|
netif->hwaddr_len = ETHARP_HWADDR_LEN; |
|
return ERR_OK; |
|
} |
|
|
|
static void |
|
default_netif_add(void) |
|
{ |
|
IP4_ADDR(&test_gw, 192,168,0,1); |
|
IP4_ADDR(&test_ipaddr, 192,168,0,1); |
|
IP4_ADDR(&test_netmask, 255,255,0,0); |
|
|
|
fail_unless(netif_default == NULL); |
|
netif_set_default(netif_add(&test_netif, &test_ipaddr, &test_netmask, |
|
&test_gw, NULL, default_netif_init, NULL)); |
|
netif_set_up(&test_netif); |
|
} |
|
|
|
static void |
|
default_netif_remove(void) |
|
{ |
|
fail_unless(netif_default == &test_netif); |
|
netif_remove(&test_netif); |
|
} |
|
|
|
static void |
|
create_arp_response(ip4_addr_t *adr) |
|
{ |
|
int k; |
|
struct eth_hdr *ethhdr; |
|
struct etharp_hdr *etharphdr; |
|
struct pbuf *p = pbuf_alloc(PBUF_RAW, sizeof(struct eth_hdr) + sizeof(struct etharp_hdr), PBUF_RAM); |
|
if(p == NULL) { |
|
FAIL_RET(); |
|
} |
|
ethhdr = (struct eth_hdr*)p->payload; |
|
etharphdr = (struct etharp_hdr*)(ethhdr + 1); |
|
|
|
ethhdr->dest = test_ethaddr; |
|
ethhdr->src = test_ethaddr2; |
|
ethhdr->type = htons(ETHTYPE_ARP); |
|
|
|
etharphdr->hwtype = htons(/*HWTYPE_ETHERNET*/ 1); |
|
etharphdr->proto = htons(ETHTYPE_IP); |
|
etharphdr->hwlen = ETHARP_HWADDR_LEN; |
|
etharphdr->protolen = sizeof(ip4_addr_t); |
|
etharphdr->opcode = htons(ARP_REPLY); |
|
|
|
SMEMCPY(ðarphdr->sipaddr, adr, sizeof(ip4_addr_t)); |
|
SMEMCPY(ðarphdr->dipaddr, &test_ipaddr, sizeof(ip4_addr_t)); |
|
|
|
k = 6; |
|
while(k > 0) { |
|
k--; |
|
/* Write the ARP MAC-Addresses */ |
|
etharphdr->shwaddr.addr[k] = test_ethaddr2.addr[k]; |
|
etharphdr->dhwaddr.addr[k] = test_ethaddr.addr[k]; |
|
/* Write the Ethernet MAC-Addresses */ |
|
ethhdr->dest.addr[k] = test_ethaddr.addr[k]; |
|
ethhdr->src.addr[k] = test_ethaddr2.addr[k]; |
|
} |
|
|
|
ethernet_input(p, &test_netif); |
|
} |
|
|
|
/* Setups/teardown functions */ |
|
|
|
static void |
|
etharp_setup(void) |
|
{ |
|
etharp_remove_all(); |
|
default_netif_add(); |
|
} |
|
|
|
static void |
|
etharp_teardown(void) |
|
{ |
|
etharp_remove_all(); |
|
default_netif_remove(); |
|
} |
|
|
|
|
|
/* Test functions */ |
|
|
|
START_TEST(test_etharp_table) |
|
{ |
|
#if ETHARP_SUPPORT_STATIC_ENTRIES |
|
err_t err; |
|
#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ |
|
s8_t idx; |
|
const ip4_addr_t *unused_ipaddr; |
|
struct eth_addr *unused_ethaddr; |
|
struct udp_pcb* pcb; |
|
LWIP_UNUSED_ARG(_i); |
|
|
|
if (netif_default != &test_netif) { |
|
fail("This test needs a default netif"); |
|
} |
|
|
|
linkoutput_ctr = 0; |
|
|
|
pcb = udp_new(); |
|
fail_unless(pcb != NULL); |
|
if (pcb != NULL) { |
|
ip4_addr_t adrs[ARP_TABLE_SIZE + 2]; |
|
int i; |
|
for(i = 0; i < ARP_TABLE_SIZE + 2; i++) { |
|
IP4_ADDR(&adrs[i], 192,168,0,i+2); |
|
} |
|
/* fill ARP-table with dynamic entries */ |
|
for(i = 0; i < ARP_TABLE_SIZE; i++) { |
|
struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, 10, PBUF_RAM); |
|
fail_unless(p != NULL); |
|
if (p != NULL) { |
|
err_t err2; |
|
ip_addr_t dst; |
|
ip_addr_copy_from_ip4(dst, adrs[i]); |
|
err2 = udp_sendto(pcb, p, &dst, 123); |
|
fail_unless(err2 == ERR_OK); |
|
/* etharp request sent? */ |
|
fail_unless(linkoutput_ctr == (2*i) + 1); |
|
pbuf_free(p); |
|
|
|
/* create an ARP response */ |
|
create_arp_response(&adrs[i]); |
|
/* queued UDP packet sent? */ |
|
fail_unless(linkoutput_ctr == (2*i) + 2); |
|
|
|
idx = etharp_find_addr(NULL, &adrs[i], &unused_ethaddr, &unused_ipaddr); |
|
fail_unless(idx == i); |
|
etharp_tmr(); |
|
} |
|
} |
|
linkoutput_ctr = 0; |
|
#if ETHARP_SUPPORT_STATIC_ENTRIES |
|
/* create one static entry */ |
|
err = etharp_add_static_entry(&adrs[ARP_TABLE_SIZE], &test_ethaddr3); |
|
fail_unless(err == ERR_OK); |
|
idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE], &unused_ethaddr, &unused_ipaddr); |
|
fail_unless(idx == 0); |
|
fail_unless(linkoutput_ctr == 0); |
|
#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ |
|
|
|
linkoutput_ctr = 0; |
|
/* fill ARP-table with dynamic entries */ |
|
for(i = 0; i < ARP_TABLE_SIZE; i++) { |
|
struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, 10, PBUF_RAM); |
|
fail_unless(p != NULL); |
|
if (p != NULL) { |
|
err_t err2; |
|
ip_addr_t dst; |
|
ip_addr_copy_from_ip4(dst, adrs[i]); |
|
err2 = udp_sendto(pcb, p, &dst, 123); |
|
fail_unless(err2 == ERR_OK); |
|
/* etharp request sent? */ |
|
fail_unless(linkoutput_ctr == (2*i) + 1); |
|
pbuf_free(p); |
|
|
|
/* create an ARP response */ |
|
create_arp_response(&adrs[i]); |
|
/* queued UDP packet sent? */ |
|
fail_unless(linkoutput_ctr == (2*i) + 2); |
|
|
|
idx = etharp_find_addr(NULL, &adrs[i], &unused_ethaddr, &unused_ipaddr); |
|
if (i < ARP_TABLE_SIZE - 1) { |
|
fail_unless(idx == i+1); |
|
} else { |
|
/* the last entry must not overwrite the static entry! */ |
|
fail_unless(idx == 1); |
|
} |
|
etharp_tmr(); |
|
} |
|
} |
|
#if ETHARP_SUPPORT_STATIC_ENTRIES |
|
/* create a second static entry */ |
|
err = etharp_add_static_entry(&adrs[ARP_TABLE_SIZE+1], &test_ethaddr4); |
|
fail_unless(err == ERR_OK); |
|
idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE], &unused_ethaddr, &unused_ipaddr); |
|
fail_unless(idx == 0); |
|
idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE+1], &unused_ethaddr, &unused_ipaddr); |
|
fail_unless(idx == 2); |
|
/* and remove it again */ |
|
err = etharp_remove_static_entry(&adrs[ARP_TABLE_SIZE+1]); |
|
fail_unless(err == ERR_OK); |
|
idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE], &unused_ethaddr, &unused_ipaddr); |
|
fail_unless(idx == 0); |
|
idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE+1], &unused_ethaddr, &unused_ipaddr); |
|
fail_unless(idx == -1); |
|
#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ |
|
|
|
/* check that static entries don't time out */ |
|
etharp_remove_all(); |
|
idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE], &unused_ethaddr, &unused_ipaddr); |
|
fail_unless(idx == 0); |
|
|
|
#if ETHARP_SUPPORT_STATIC_ENTRIES |
|
/* remove the first static entry */ |
|
err = etharp_remove_static_entry(&adrs[ARP_TABLE_SIZE]); |
|
fail_unless(err == ERR_OK); |
|
idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE], &unused_ethaddr, &unused_ipaddr); |
|
fail_unless(idx == -1); |
|
idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE+1], &unused_ethaddr, &unused_ipaddr); |
|
fail_unless(idx == -1); |
|
#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ |
|
|
|
udp_remove(pcb); |
|
} |
|
} |
|
END_TEST |
|
|
|
|
|
/** Create the suite including all tests for this module */ |
|
Suite * |
|
etharp_suite(void) |
|
{ |
|
testfunc tests[] = { |
|
TESTFUNC(test_etharp_table) |
|
}; |
|
return create_suite("ETHARP", tests, sizeof(tests)/sizeof(testfunc), etharp_setup, etharp_teardown); |
|
}
|
|
|