123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472 |
- #include "test_udp.h"
- #include "lwip/udp.h"
- #include "lwip/stats.h"
- #include "lwip/inet_chksum.h"
- #if !LWIP_STATS || !UDP_STATS || !MEMP_STATS
- #error "This tests needs UDP- and MEMP-statistics enabled"
- #endif
- struct test_udp_rxdata {
- u32_t rx_cnt;
- u32_t rx_bytes;
- struct udp_pcb *pcb;
- };
- static struct netif test_netif1, test_netif2;
- static ip4_addr_t test_gw1, test_ipaddr1, test_netmask1;
- static ip4_addr_t test_gw2, test_ipaddr2, test_netmask2;
- static int output_ctr, linkoutput_ctr;
- /* Helper functions */
- static void
- udp_remove_all(void)
- {
- struct udp_pcb *pcb = udp_pcbs;
- struct udp_pcb *pcb2;
- while(pcb != NULL) {
- pcb2 = pcb;
- pcb = pcb->next;
- udp_remove(pcb2);
- }
- fail_unless(MEMP_STATS_GET(used, MEMP_UDP_PCB) == 0);
- }
- static err_t
- default_netif_output(struct netif *netif, struct pbuf *p, const ip4_addr_t *ipaddr)
- {
- fail_unless((netif == &test_netif1) || (netif == &test_netif2));
- fail_unless(p != NULL);
- fail_unless(ipaddr != NULL);
- output_ctr++;
- return ERR_OK;
- }
- static err_t
- default_netif_linkoutput(struct netif *netif, struct pbuf *p)
- {
- fail_unless((netif == &test_netif1) || (netif == &test_netif2));
- fail_unless(p != NULL);
- linkoutput_ctr++;
- return ERR_OK;
- }
- static err_t
- default_netif_init(struct netif *netif)
- {
- fail_unless(netif != NULL);
- netif->output = default_netif_output;
- netif->linkoutput = default_netif_linkoutput;
- netif->mtu = 1500;
- netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
- netif->hwaddr_len = 6;
- return ERR_OK;
- }
- static void
- default_netif_add(void)
- {
- struct netif *n;
- #if LWIP_HAVE_LOOPIF
- fail_unless(netif_list != NULL); /* the loopif */
- fail_unless(netif_list->next == NULL);
- #else
- fail_unless(netif_list == NULL);
- #endif
- fail_unless(netif_default == NULL);
- IP4_ADDR(&test_ipaddr1, 192,168,0,1);
- IP4_ADDR(&test_netmask1, 255,255,255,0);
- IP4_ADDR(&test_gw1, 192,168,0,254);
- n = netif_add(&test_netif1, &test_ipaddr1, &test_netmask1,
- &test_gw1, NULL, default_netif_init, NULL);
- fail_unless(n == &test_netif1);
- IP4_ADDR(&test_ipaddr2, 192,168,1,1);
- IP4_ADDR(&test_netmask2, 255,255,255,0);
- IP4_ADDR(&test_gw2, 192,168,1,254);
- n = netif_add(&test_netif2, &test_ipaddr2, &test_netmask2,
- &test_gw2, NULL, default_netif_init, NULL);
- fail_unless(n == &test_netif2);
- netif_set_default(&test_netif1);
- netif_set_up(&test_netif1);
- netif_set_up(&test_netif2);
- }
- static void
- default_netif_remove(void)
- {
- fail_unless(netif_default == &test_netif1);
- netif_remove(&test_netif1);
- netif_remove(&test_netif2);
- fail_unless(netif_default == NULL);
- #if LWIP_HAVE_LOOPIF
- fail_unless(netif_list != NULL); /* the loopif */
- fail_unless(netif_list->next == NULL);
- #else
- fail_unless(netif_list == NULL);
- #endif
- }
- /* Setups/teardown functions */
- static void
- udp_setup(void)
- {
- udp_remove_all();
- default_netif_add();
- lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
- }
- static void
- udp_teardown(void)
- {
- udp_remove_all();
- default_netif_remove();
- lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
- }
- /* Test functions */
- START_TEST(test_udp_new_remove)
- {
- struct udp_pcb* pcb;
- LWIP_UNUSED_ARG(_i);
- fail_unless(MEMP_STATS_GET(used, MEMP_UDP_PCB) == 0);
- pcb = udp_new();
- fail_unless(pcb != NULL);
- if (pcb != NULL) {
- fail_unless(MEMP_STATS_GET(used, MEMP_UDP_PCB) == 1);
- udp_remove(pcb);
- fail_unless(MEMP_STATS_GET(used, MEMP_UDP_PCB) == 0);
- }
- }
- END_TEST
- static void test_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p,
- const ip_addr_t *addr, u16_t port)
- {
- struct test_udp_rxdata *ctr = (struct test_udp_rxdata *)arg;
- LWIP_UNUSED_ARG(addr);
- LWIP_UNUSED_ARG(port);
- fail_unless(arg != NULL);
- fail_unless(ctr->pcb == pcb);
- ctr->rx_cnt++;
- ctr->rx_bytes += p->tot_len;
- if (p != NULL) {
- pbuf_free(p);
- }
- }
- static struct pbuf *
- test_udp_create_test_packet(u16_t length, u16_t port, u32_t dst_addr)
- {
- err_t err;
- u8_t ret;
- struct udp_hdr *uh;
- struct ip_hdr *ih;
- struct pbuf *p;
- const u8_t test_data[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf};
- p = pbuf_alloc(PBUF_TRANSPORT, length, PBUF_POOL);
- fail_unless(p != NULL);
- if (p == NULL) {
- return NULL;
- }
- fail_unless(p->next == NULL);
- err = pbuf_take(p, test_data, length);
- fail_unless(err == ERR_OK);
- /* add UDP header */
- ret = pbuf_add_header(p, sizeof(struct udp_hdr));
- fail_unless(!ret);
- uh = (struct udp_hdr *)p->payload;
- uh->chksum = 0;
- uh->dest = uh->src = lwip_htons(port);
- uh->len = lwip_htons(p->tot_len);
- /* add IPv4 header */
- ret = pbuf_add_header(p, sizeof(struct ip_hdr));
- fail_unless(!ret);
- ih = (struct ip_hdr *)p->payload;
- memset(ih, 0, sizeof(*ih));
- ih->dest.addr = dst_addr;
- ih->_len = lwip_htons(p->tot_len);
- ih->_ttl = 32;
- ih->_proto = IP_PROTO_UDP;
- IPH_VHL_SET(ih, 4, sizeof(struct ip_hdr) / 4);
- IPH_CHKSUM_SET(ih, inet_chksum(ih, sizeof(struct ip_hdr)));
- return p;
- }
- /* bind 2 pcbs to specific netif IP and test which one gets broadcasts */
- START_TEST(test_udp_broadcast_rx_with_2_netifs)
- {
- err_t err;
- struct udp_pcb *pcb1, *pcb2;
- const u16_t port = 12345;
- struct test_udp_rxdata ctr1, ctr2;
- struct pbuf *p;
- #if SO_REUSE
- struct udp_pcb *pcb_any;
- struct test_udp_rxdata ctr_any;
- #endif
- LWIP_UNUSED_ARG(_i);
- pcb1 = udp_new();
- fail_unless(pcb1 != NULL);
- pcb2 = udp_new();
- fail_unless(pcb2 != NULL);
- #if SO_REUSE
- pcb_any = udp_new();
- fail_unless(pcb_any != NULL);
- ip_set_option(pcb1, SOF_REUSEADDR);
- ip_set_option(pcb2, SOF_REUSEADDR);
- ip_set_option(pcb_any, SOF_REUSEADDR);
- err = udp_bind(pcb_any, NULL, port);
- fail_unless(err == ERR_OK);
- memset(&ctr_any, 0, sizeof(ctr_any));
- ctr_any.pcb = pcb_any;
- udp_recv(pcb_any, test_recv, &ctr_any);
- #endif
- err = udp_bind(pcb1, &test_netif1.ip_addr, port);
- fail_unless(err == ERR_OK);
- err = udp_bind(pcb2, &test_netif2.ip_addr, port);
- fail_unless(err == ERR_OK);
- memset(&ctr1, 0, sizeof(ctr1));
- ctr1.pcb = pcb1;
- memset(&ctr2, 0, sizeof(ctr2));
- ctr2.pcb = pcb2;
- udp_recv(pcb1, test_recv, &ctr1);
- udp_recv(pcb2, test_recv, &ctr2);
- /* unicast to netif1 */
- p = test_udp_create_test_packet(16, port, test_ipaddr1.addr);
- EXPECT_RET(p != NULL);
- err = ip4_input(p, &test_netif1);
- fail_unless(err == ERR_OK);
- fail_unless(ctr1.rx_cnt == 1);
- fail_unless(ctr1.rx_bytes == 16);
- fail_unless(ctr2.rx_cnt == 0);
- #if SO_REUSE
- fail_unless(ctr_any.rx_cnt == 0);
- #endif
- ctr1.rx_cnt = ctr1.rx_bytes = 0;
- /* unicast to netif2 */
- p = test_udp_create_test_packet(16, port, test_ipaddr2.addr);
- EXPECT_RET(p != NULL);
- err = ip4_input(p, &test_netif2);
- fail_unless(err == ERR_OK);
- fail_unless(ctr2.rx_cnt == 1);
- fail_unless(ctr2.rx_bytes == 16);
- fail_unless(ctr1.rx_cnt == 0);
- #if SO_REUSE
- fail_unless(ctr_any.rx_cnt == 0);
- #endif
- ctr2.rx_cnt = ctr2.rx_bytes = 0;
- /* broadcast to netif1-broadcast, input to netif2 */
- p = test_udp_create_test_packet(16, port, test_ipaddr1.addr | ~test_netmask1.addr);
- EXPECT_RET(p != NULL);
- err = ip4_input(p, &test_netif2);
- fail_unless(err == ERR_OK);
- fail_unless(ctr1.rx_cnt == 1);
- fail_unless(ctr1.rx_bytes == 16);
- fail_unless(ctr2.rx_cnt == 0);
- #if SO_REUSE
- fail_unless(ctr_any.rx_cnt == 0);
- #endif
- ctr1.rx_cnt = ctr1.rx_bytes = 0;
- /* broadcast to netif2-broadcast, input to netif1 */
- p = test_udp_create_test_packet(16, port, test_ipaddr2.addr | ~test_netmask2.addr);
- EXPECT_RET(p != NULL);
- err = ip4_input(p, &test_netif1);
- fail_unless(err == ERR_OK);
- fail_unless(ctr2.rx_cnt == 1);
- fail_unless(ctr2.rx_bytes == 16);
- fail_unless(ctr1.rx_cnt == 0);
- #if SO_REUSE
- fail_unless(ctr_any.rx_cnt == 0);
- #endif
- ctr2.rx_cnt = ctr2.rx_bytes = 0;
- /* broadcast to global-broadcast, input to netif1 */
- p = test_udp_create_test_packet(16, port, 0xffffffff);
- EXPECT_RET(p != NULL);
- err = ip4_input(p, &test_netif1);
- fail_unless(err == ERR_OK);
- fail_unless(ctr1.rx_cnt == 1);
- fail_unless(ctr1.rx_bytes == 16);
- fail_unless(ctr2.rx_cnt == 0);
- #if SO_REUSE
- fail_unless(ctr_any.rx_cnt == 0);
- #endif
- ctr1.rx_cnt = ctr1.rx_bytes = 0;
- /* broadcast to global-broadcast, input to netif2 */
- p = test_udp_create_test_packet(16, port, 0xffffffff);
- EXPECT_RET(p != NULL);
- err = ip4_input(p, &test_netif2);
- fail_unless(err == ERR_OK);
- fail_unless(ctr2.rx_cnt == 1);
- fail_unless(ctr2.rx_bytes == 16);
- fail_unless(ctr1.rx_cnt == 0);
- #if SO_REUSE
- fail_unless(ctr_any.rx_cnt == 0);
- #endif
- ctr2.rx_cnt = ctr2.rx_bytes = 0;
- }
- END_TEST
- START_TEST(test_udp_bind)
- {
- struct udp_pcb* pcb1;
- struct udp_pcb* pcb2;
- ip_addr_t ip1;
- ip_addr_t ip2;
- err_t err1;
- err_t err2;
- LWIP_UNUSED_ARG(_i);
- /* bind on same port using different IP address types */
- ip_addr_set_any_val(0, ip1);
- ip_addr_set_any_val(1, ip2);
- pcb1 = udp_new_ip_type(IPADDR_TYPE_V4);
- pcb2 = udp_new_ip_type(IPADDR_TYPE_V6);
- err1 = udp_bind(pcb1, &ip1, 2105);
- err2 = udp_bind(pcb2, &ip2, 2105);
- fail_unless(err1 == ERR_OK);
- fail_unless(err2 == ERR_OK);
- udp_remove(pcb1);
- udp_remove(pcb2);
- /* bind on same port using SAME IPv4 address type */
- ip_addr_set_any_val(0, ip1);
- ip_addr_set_any_val(0, ip2);
- pcb1 = udp_new_ip_type(IPADDR_TYPE_V4);
- pcb2 = udp_new_ip_type(IPADDR_TYPE_V4);
- err1 = udp_bind(pcb1, &ip1, 2105);
- err2 = udp_bind(pcb2, &ip2, 2105);
- fail_unless(err1 == ERR_OK);
- fail_unless(err2 == ERR_USE);
- udp_remove(pcb1);
- udp_remove(pcb2);
- /* bind on same port using SAME IPv6 address type */
- ip_addr_set_any_val(1, ip1);
- ip_addr_set_any_val(1, ip2);
- pcb1 = udp_new_ip_type(IPADDR_TYPE_V6);
- pcb2 = udp_new_ip_type(IPADDR_TYPE_V6);
- err1 = udp_bind(pcb1, &ip1, 2105);
- err2 = udp_bind(pcb2, &ip2, 2105);
- fail_unless(err1 == ERR_OK);
- fail_unless(err2 == ERR_USE);
- udp_remove(pcb1);
- udp_remove(pcb2);
- /* Bind with different IP address type */
- ip_addr_set_any_val(0, ip1);
- ip_addr_set_any_val(1, ip2);
- pcb1 = udp_new_ip_type(IPADDR_TYPE_V6);
- pcb2 = udp_new_ip_type(IPADDR_TYPE_V4);
- err1 = udp_bind(pcb1, &ip1, 2105);
- err2 = udp_bind(pcb2, &ip2, 2105);
- fail_unless(err1 == ERR_OK);
- fail_unless(err2 == ERR_OK);
- udp_remove(pcb1);
- udp_remove(pcb2);
- /* Bind with different IP numbers */
- IP_ADDR4(&ip1, 1, 2, 3, 4);
- IP_ADDR4(&ip2, 4, 3, 2, 1);
- pcb1 = udp_new_ip_type(IPADDR_TYPE_V6);
- pcb2 = udp_new_ip_type(IPADDR_TYPE_V4);
- err1 = udp_bind(pcb1, &ip1, 2105);
- err2 = udp_bind(pcb2, &ip2, 2105);
- fail_unless(err1 == ERR_OK);
- fail_unless(err2 == ERR_OK);
- udp_remove(pcb1);
- udp_remove(pcb2);
- /* Bind with same IP numbers */
- IP_ADDR4(&ip1, 1, 2, 3, 4);
- IP_ADDR4(&ip2, 1, 2, 3, 4);
- pcb1 = udp_new_ip_type(IPADDR_TYPE_V6);
- pcb2 = udp_new_ip_type(IPADDR_TYPE_V4);
- err1 = udp_bind(pcb1, &ip1, 2105);
- err2 = udp_bind(pcb2, &ip2, 2105);
- fail_unless(err1 == ERR_OK);
- fail_unless(err2 == ERR_USE);
- udp_remove(pcb1);
- udp_remove(pcb2);
- /* bind on same port using ANY + IPv4 */
- ip1 = *IP_ANY_TYPE;
- IP_ADDR4(&ip2, 1, 2, 3, 4);
- pcb1 = udp_new_ip_type(IPADDR_TYPE_ANY);
- pcb2 = udp_new_ip_type(IPADDR_TYPE_V4);
- err1 = udp_bind(pcb1, &ip1, 2105);
- err2 = udp_bind(pcb2, &ip2, 2105);
- fail_unless(err1 == ERR_OK);
- fail_unless(err2 == ERR_USE);
- udp_remove(pcb1);
- udp_remove(pcb2);
- }
- END_TEST
- /** Create the suite including all tests for this module */
- Suite *
- udp_suite(void)
- {
- testfunc tests[] = {
- TESTFUNC(test_udp_new_remove),
- TESTFUNC(test_udp_broadcast_rx_with_2_netifs),
- TESTFUNC(test_udp_bind)
- };
- return create_suite("UDP", tests, sizeof(tests)/sizeof(testfunc), udp_setup, udp_teardown);
- }
|