1#include "test_udp.h" 2 3#include "lwip/udp.h" 4#include "lwip/stats.h" 5#include "lwip/inet_chksum.h" 6 7#if !LWIP_STATS || !UDP_STATS || !MEMP_STATS 8#error "This tests needs UDP- and MEMP-statistics enabled" 9#endif 10 11struct test_udp_rxdata { 12 u32_t rx_cnt; 13 u32_t rx_bytes; 14 struct udp_pcb *pcb; 15}; 16 17static struct netif test_netif1, test_netif2; 18static ip4_addr_t test_gw1, test_ipaddr1, test_netmask1; 19static ip4_addr_t test_gw2, test_ipaddr2, test_netmask2; 20static int output_ctr, linkoutput_ctr; 21 22/* Helper functions */ 23static void 24udp_remove_all(void) 25{ 26 struct udp_pcb *pcb = udp_pcbs; 27 struct udp_pcb *pcb2; 28 29 while(pcb != NULL) { 30 pcb2 = pcb; 31 pcb = pcb->next; 32 udp_remove(pcb2); 33 } 34 fail_unless(MEMP_STATS_GET(used, MEMP_UDP_PCB) == 0); 35} 36 37static err_t 38default_netif_output(struct netif *netif, struct pbuf *p, const ip4_addr_t *ipaddr) 39{ 40 fail_unless((netif == &test_netif1) || (netif == &test_netif2)); 41 fail_unless(p != NULL); 42 fail_unless(ipaddr != NULL); 43 output_ctr++; 44 return ERR_OK; 45} 46 47static err_t 48default_netif_linkoutput(struct netif *netif, struct pbuf *p) 49{ 50 fail_unless((netif == &test_netif1) || (netif == &test_netif2)); 51 fail_unless(p != NULL); 52 linkoutput_ctr++; 53 return ERR_OK; 54} 55 56static err_t 57default_netif_init(struct netif *netif) 58{ 59 fail_unless(netif != NULL); 60 netif->output = default_netif_output; 61 netif->linkoutput = default_netif_linkoutput; 62 netif->mtu = 1500; 63 netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; 64 netif->hwaddr_len = 6; 65 return ERR_OK; 66} 67 68static void 69default_netif_add(void) 70{ 71 struct netif *n; 72 73#if LWIP_HAVE_LOOPIF 74 fail_unless(netif_list != NULL); /* the loopif */ 75 fail_unless(netif_list->next == NULL); 76#else 77 fail_unless(netif_list == NULL); 78#endif 79 fail_unless(netif_default == NULL); 80 81 IP4_ADDR(&test_ipaddr1, 192,168,0,1); 82 IP4_ADDR(&test_netmask1, 255,255,255,0); 83 IP4_ADDR(&test_gw1, 192,168,0,254); 84 n = netif_add(&test_netif1, &test_ipaddr1, &test_netmask1, 85 &test_gw1, NULL, default_netif_init, NULL); 86 fail_unless(n == &test_netif1); 87 88 IP4_ADDR(&test_ipaddr2, 192,168,1,1); 89 IP4_ADDR(&test_netmask2, 255,255,255,0); 90 IP4_ADDR(&test_gw2, 192,168,1,254); 91 n = netif_add(&test_netif2, &test_ipaddr2, &test_netmask2, 92 &test_gw2, NULL, default_netif_init, NULL); 93 fail_unless(n == &test_netif2); 94 95 netif_set_default(&test_netif1); 96 netif_set_up(&test_netif1); 97 netif_set_up(&test_netif2); 98} 99 100static void 101default_netif_remove(void) 102{ 103 fail_unless(netif_default == &test_netif1); 104 netif_remove(&test_netif1); 105 netif_remove(&test_netif2); 106 fail_unless(netif_default == NULL); 107#if LWIP_HAVE_LOOPIF 108 fail_unless(netif_list != NULL); /* the loopif */ 109 fail_unless(netif_list->next == NULL); 110#else 111 fail_unless(netif_list == NULL); 112#endif 113} 114/* Setups/teardown functions */ 115 116static void 117udp_setup(void) 118{ 119 udp_remove_all(); 120 default_netif_add(); 121 lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT)); 122} 123 124static void 125udp_teardown(void) 126{ 127 udp_remove_all(); 128 default_netif_remove(); 129 lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT)); 130} 131 132 133/* Test functions */ 134 135START_TEST(test_udp_new_remove) 136{ 137 struct udp_pcb* pcb; 138 LWIP_UNUSED_ARG(_i); 139 140 fail_unless(MEMP_STATS_GET(used, MEMP_UDP_PCB) == 0); 141 142 pcb = udp_new(); 143 fail_unless(pcb != NULL); 144 if (pcb != NULL) { 145 fail_unless(MEMP_STATS_GET(used, MEMP_UDP_PCB) == 1); 146 udp_remove(pcb); 147 fail_unless(MEMP_STATS_GET(used, MEMP_UDP_PCB) == 0); 148 } 149} 150END_TEST 151 152static void test_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, 153 const ip_addr_t *addr, u16_t port) 154{ 155 struct test_udp_rxdata *ctr = (struct test_udp_rxdata *)arg; 156 157 LWIP_UNUSED_ARG(addr); 158 LWIP_UNUSED_ARG(port); 159 160 fail_unless(arg != NULL); 161 fail_unless(ctr->pcb == pcb); 162 163 ctr->rx_cnt++; 164 ctr->rx_bytes += p->tot_len; 165 166 if (p != NULL) { 167 pbuf_free(p); 168 } 169} 170 171static struct pbuf * 172test_udp_create_test_packet(u16_t length, u16_t port, u32_t dst_addr) 173{ 174 err_t err; 175 u8_t ret; 176 struct udp_hdr *uh; 177 struct ip_hdr *ih; 178 struct pbuf *p; 179 const u8_t test_data[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}; 180 181 p = pbuf_alloc(PBUF_TRANSPORT, length, PBUF_POOL); 182 fail_unless(p != NULL); 183 if (p == NULL) { 184 return NULL; 185 } 186 fail_unless(p->next == NULL); 187 err = pbuf_take(p, test_data, length); 188 fail_unless(err == ERR_OK); 189 190 /* add UDP header */ 191 ret = pbuf_add_header(p, sizeof(struct udp_hdr)); 192 fail_unless(!ret); 193 uh = (struct udp_hdr *)p->payload; 194 uh->chksum = 0; 195 uh->dest = uh->src = lwip_htons(port); 196 uh->len = lwip_htons(p->tot_len); 197 /* add IPv4 header */ 198 ret = pbuf_add_header(p, sizeof(struct ip_hdr)); 199 fail_unless(!ret); 200 ih = (struct ip_hdr *)p->payload; 201 memset(ih, 0, sizeof(*ih)); 202 ih->dest.addr = dst_addr; 203 ih->_len = lwip_htons(p->tot_len); 204 ih->_ttl = 32; 205 ih->_proto = IP_PROTO_UDP; 206 IPH_VHL_SET(ih, 4, sizeof(struct ip_hdr) / 4); 207 IPH_CHKSUM_SET(ih, inet_chksum(ih, sizeof(struct ip_hdr))); 208 return p; 209} 210 211/* bind 2 pcbs to specific netif IP and test which one gets broadcasts */ 212START_TEST(test_udp_broadcast_rx_with_2_netifs) 213{ 214 err_t err; 215 struct udp_pcb *pcb1, *pcb2; 216 const u16_t port = 12345; 217 struct test_udp_rxdata ctr1, ctr2; 218 struct pbuf *p; 219#if SO_REUSE 220 struct udp_pcb *pcb_any; 221 struct test_udp_rxdata ctr_any; 222#endif 223 LWIP_UNUSED_ARG(_i); 224 225 pcb1 = udp_new(); 226 fail_unless(pcb1 != NULL); 227 pcb2 = udp_new(); 228 fail_unless(pcb2 != NULL); 229 230#if SO_REUSE 231 pcb_any = udp_new(); 232 fail_unless(pcb_any != NULL); 233 234 ip_set_option(pcb1, SOF_REUSEADDR); 235 ip_set_option(pcb2, SOF_REUSEADDR); 236 ip_set_option(pcb_any, SOF_REUSEADDR); 237 238 err = udp_bind(pcb_any, NULL, port); 239 fail_unless(err == ERR_OK); 240 memset(&ctr_any, 0, sizeof(ctr_any)); 241 ctr_any.pcb = pcb_any; 242 udp_recv(pcb_any, test_recv, &ctr_any); 243#endif 244 245 err = udp_bind(pcb1, &test_netif1.ip_addr, port); 246 fail_unless(err == ERR_OK); 247 err = udp_bind(pcb2, &test_netif2.ip_addr, port); 248 fail_unless(err == ERR_OK); 249 250 memset(&ctr1, 0, sizeof(ctr1)); 251 ctr1.pcb = pcb1; 252 memset(&ctr2, 0, sizeof(ctr2)); 253 ctr2.pcb = pcb2; 254 255 udp_recv(pcb1, test_recv, &ctr1); 256 udp_recv(pcb2, test_recv, &ctr2); 257 258 /* unicast to netif1 */ 259 p = test_udp_create_test_packet(16, port, test_ipaddr1.addr); 260 EXPECT_RET(p != NULL); 261 err = ip4_input(p, &test_netif1); 262 fail_unless(err == ERR_OK); 263 fail_unless(ctr1.rx_cnt == 1); 264 fail_unless(ctr1.rx_bytes == 16); 265 fail_unless(ctr2.rx_cnt == 0); 266#if SO_REUSE 267 fail_unless(ctr_any.rx_cnt == 0); 268#endif 269 ctr1.rx_cnt = ctr1.rx_bytes = 0; 270 271 /* unicast to netif2 */ 272 p = test_udp_create_test_packet(16, port, test_ipaddr2.addr); 273 EXPECT_RET(p != NULL); 274 err = ip4_input(p, &test_netif2); 275 fail_unless(err == ERR_OK); 276 fail_unless(ctr2.rx_cnt == 1); 277 fail_unless(ctr2.rx_bytes == 16); 278 fail_unless(ctr1.rx_cnt == 0); 279#if SO_REUSE 280 fail_unless(ctr_any.rx_cnt == 0); 281#endif 282 ctr2.rx_cnt = ctr2.rx_bytes = 0; 283 284 /* broadcast to netif1-broadcast, input to netif2 */ 285 p = test_udp_create_test_packet(16, port, test_ipaddr1.addr | ~test_netmask1.addr); 286 EXPECT_RET(p != NULL); 287 err = ip4_input(p, &test_netif2); 288 fail_unless(err == ERR_OK); 289 fail_unless(ctr1.rx_cnt == 1); 290 fail_unless(ctr1.rx_bytes == 16); 291 fail_unless(ctr2.rx_cnt == 0); 292#if SO_REUSE 293 fail_unless(ctr_any.rx_cnt == 0); 294#endif 295 ctr1.rx_cnt = ctr1.rx_bytes = 0; 296 297 /* broadcast to netif2-broadcast, input to netif1 */ 298 p = test_udp_create_test_packet(16, port, test_ipaddr2.addr | ~test_netmask2.addr); 299 EXPECT_RET(p != NULL); 300 err = ip4_input(p, &test_netif1); 301 fail_unless(err == ERR_OK); 302 fail_unless(ctr2.rx_cnt == 1); 303 fail_unless(ctr2.rx_bytes == 16); 304 fail_unless(ctr1.rx_cnt == 0); 305#if SO_REUSE 306 fail_unless(ctr_any.rx_cnt == 0); 307#endif 308 ctr2.rx_cnt = ctr2.rx_bytes = 0; 309 310 /* broadcast to global-broadcast, input to netif1 */ 311 p = test_udp_create_test_packet(16, port, 0xffffffff); 312 EXPECT_RET(p != NULL); 313 err = ip4_input(p, &test_netif1); 314 fail_unless(err == ERR_OK); 315 fail_unless(ctr1.rx_cnt == 1); 316 fail_unless(ctr1.rx_bytes == 16); 317 fail_unless(ctr2.rx_cnt == 0); 318#if SO_REUSE 319 fail_unless(ctr_any.rx_cnt == 0); 320#endif 321 ctr1.rx_cnt = ctr1.rx_bytes = 0; 322 323 /* broadcast to global-broadcast, input to netif2 */ 324 p = test_udp_create_test_packet(16, port, 0xffffffff); 325 EXPECT_RET(p != NULL); 326 err = ip4_input(p, &test_netif2); 327 fail_unless(err == ERR_OK); 328 fail_unless(ctr2.rx_cnt == 1); 329 fail_unless(ctr2.rx_bytes == 16); 330 fail_unless(ctr1.rx_cnt == 0); 331#if SO_REUSE 332 fail_unless(ctr_any.rx_cnt == 0); 333#endif 334 ctr2.rx_cnt = ctr2.rx_bytes = 0; 335} 336END_TEST 337 338/** Create the suite including all tests for this module */ 339Suite * 340udp_suite(void) 341{ 342 testfunc tests[] = { 343 TESTFUNC(test_udp_new_remove), 344 TESTFUNC(test_udp_broadcast_rx_with_2_netifs) 345 }; 346 return create_suite("UDP", tests, sizeof(tests)/sizeof(testfunc), udp_setup, udp_teardown); 347} 348