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 |
|
---|
11 | struct test_udp_rxdata {
|
---|
12 | u32_t rx_cnt;
|
---|
13 | u32_t rx_bytes;
|
---|
14 | struct udp_pcb *pcb;
|
---|
15 | };
|
---|
16 |
|
---|
17 | static struct netif test_netif1, test_netif2;
|
---|
18 | static ip4_addr_t test_gw1, test_ipaddr1, test_netmask1;
|
---|
19 | static ip4_addr_t test_gw2, test_ipaddr2, test_netmask2;
|
---|
20 | static int output_ctr, linkoutput_ctr;
|
---|
21 |
|
---|
22 | /* Helper functions */
|
---|
23 | static void
|
---|
24 | udp_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 |
|
---|
37 | static err_t
|
---|
38 | default_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 |
|
---|
47 | static err_t
|
---|
48 | default_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 |
|
---|
56 | static err_t
|
---|
57 | default_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 |
|
---|
68 | static void
|
---|
69 | default_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 |
|
---|
100 | static void
|
---|
101 | default_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 |
|
---|
116 | static void
|
---|
117 | udp_setup(void)
|
---|
118 | {
|
---|
119 | udp_remove_all();
|
---|
120 | default_netif_add();
|
---|
121 | lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
|
---|
122 | }
|
---|
123 |
|
---|
124 | static void
|
---|
125 | udp_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 |
|
---|
135 | START_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 | }
|
---|
150 | END_TEST
|
---|
151 |
|
---|
152 | static 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 |
|
---|
171 | static struct pbuf *
|
---|
172 | test_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 */
|
---|
212 | START_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 | }
|
---|
336 | END_TEST
|
---|
337 |
|
---|
338 | /** Create the suite including all tests for this module */
|
---|
339 | Suite *
|
---|
340 | udp_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 | }
|
---|