1 #include "tcp_helper.h"
4 #include "lwip/stats.h"
6 #include "lwip/inet_chksum.h"
8 #if !LWIP_STATS || !TCP_STATS || !MEMP_STATS
9 #error "This tests needs TCP- and MEMP-statistics enabled"
12 /** Remove all pcbs on the given list. */
14 tcp_remove(struct tcp_pcb
* pcb_list
)
16 struct tcp_pcb
*pcb
= pcb_list
;
26 /** Remove all pcbs on listen-, active- and time-wait-list (bound- isn't exported). */
30 //tcp_remove(tcp_bound_pcbs);
31 tcp_remove(tcp_listen_pcbs
.pcbs
);
32 tcp_remove(tcp_active_pcbs
);
33 tcp_remove(tcp_tw_pcbs
);
34 fail_unless(lwip_stats
.memp
[MEMP_TCP_PCB
].used
== 0);
35 fail_unless(lwip_stats
.memp
[MEMP_TCP_PCB_LISTEN
].used
== 0);
36 fail_unless(lwip_stats
.memp
[MEMP_TCP_SEG
].used
== 0);
37 fail_unless(lwip_stats
.memp
[MEMP_PBUF_POOL
].used
== 0);
40 /** Create a TCP segment usable for passing to tcp_input
41 * - IP-addresses, ports, seqno and ackno are taken from pcb
42 * - seqno and ackno can be altered with an offset
45 tcp_create_rx_segment(struct tcp_pcb
* pcb
, void* data
, size_t data_len
, u32_t seqno_offset
,
46 u32_t ackno_offset
, u8_t headerflags
)
48 return tcp_create_segment(&pcb
->remote_ip
, &pcb
->local_ip
, pcb
->remote_port
, pcb
->local_port
,
49 data
, data_len
, pcb
->rcv_nxt
+ seqno_offset
, pcb
->snd_nxt
+ ackno_offset
, headerflags
);
52 /** Create a TCP segment usable for passing to tcp_input */
54 tcp_create_segment(struct ip_addr
* src_ip
, struct ip_addr
* dst_ip
,
55 u16_t src_port
, u16_t dst_port
, void* data
, size_t data_len
,
56 u32_t seqno
, u32_t ackno
, u8_t headerflags
)
60 struct tcp_hdr
* tcphdr
;
61 u16_t pbuf_len
= sizeof(struct ip_hdr
) + sizeof(struct tcp_hdr
) + data_len
;
63 p
= pbuf_alloc(PBUF_RAW
, pbuf_len
, PBUF_POOL
);
64 EXPECT_RETNULL(p
!= NULL
);
65 EXPECT_RETNULL(p
->next
== NULL
);
67 memset(p
->payload
, 0, p
->len
);
71 iphdr
->dest
.addr
= dst_ip
->addr
;
72 iphdr
->src
.addr
= src_ip
->addr
;
73 IPH_VHLTOS_SET(iphdr
, 4, IP_HLEN
/ 4, 0);
74 IPH_LEN_SET(iphdr
, htons(p
->tot_len
));
75 IPH_CHKSUM_SET(iphdr
, inet_chksum(iphdr
, IP_HLEN
));
77 pbuf_header(p
, -(s16_t
)sizeof(struct ip_hdr
));
80 tcphdr
->src
= htons(src_port
);
81 tcphdr
->dest
= htons(dst_port
);
82 tcphdr
->seqno
= htonl(seqno
);
83 tcphdr
->ackno
= htonl(ackno
);
84 TCPH_HDRLEN_SET(tcphdr
, sizeof(struct tcp_hdr
)/4);
85 TCPH_FLAGS_SET(tcphdr
, headerflags
);
86 tcphdr
->wnd
= htonl(TCP_WND
);
89 memcpy((char*)tcphdr
+ sizeof(struct tcp_hdr
), data
, data_len
);
91 /* calculate checksum */
92 tcphdr
->chksum
= inet_chksum_pseudo(p
, &(iphdr
->src
), &(iphdr
->dest
),
93 IP_PROTO_TCP
, p
->tot_len
);
95 pbuf_header(p
, sizeof(struct ip_hdr
));
100 /** Safely bring a tcp_pcb into the requested state */
102 tcp_set_state(struct tcp_pcb
* pcb
, enum tcp_state state
, struct ip_addr
* local_ip
,
103 struct ip_addr
* remote_ip
, u16_t local_port
, u16_t remote_port
)
105 /* @todo: are these all states? */
106 /* @todo: remove from previous list */
108 if (state
== ESTABLISHED
) {
109 TCP_REG(&tcp_active_pcbs
, pcb
);
110 pcb
->local_ip
.addr
= local_ip
->addr
;
111 pcb
->local_port
= local_port
;
112 pcb
->remote_ip
.addr
= remote_ip
->addr
;
113 pcb
->remote_port
= remote_port
;
114 } else if(state
== LISTEN
) {
115 TCP_REG(&tcp_listen_pcbs
.pcbs
, pcb
);
116 pcb
->local_ip
.addr
= local_ip
->addr
;
117 pcb
->local_port
= local_port
;
118 } else if(state
== TIME_WAIT
) {
119 TCP_REG(&tcp_tw_pcbs
, pcb
);
120 pcb
->local_ip
.addr
= local_ip
->addr
;
121 pcb
->local_port
= local_port
;
122 pcb
->remote_ip
.addr
= remote_ip
->addr
;
123 pcb
->remote_port
= remote_port
;
130 test_tcp_counters_err(void* arg
, err_t err
)
132 struct test_tcp_counters
* counters
= arg
;
133 EXPECT_RET(arg
!= NULL
);
134 counters
->err_calls
++;
135 counters
->last_err
= err
;
139 test_tcp_counters_check_rxdata(struct test_tcp_counters
* counters
, struct pbuf
* p
)
143 if(counters
->expected_data
== NULL
) {
144 /* no data to compare */
147 EXPECT_RET(counters
->recved_bytes
+ p
->tot_len
<= counters
->expected_data_len
);
148 received
= counters
->recved_bytes
;
149 for(q
= p
; q
!= NULL
; q
= q
->next
) {
150 char *data
= q
->payload
;
151 for(i
= 0; i
< q
->len
; i
++) {
152 EXPECT_RET(data
[i
] == counters
->expected_data
[received
]);
156 EXPECT(received
== counters
->recved_bytes
+ p
->tot_len
);
160 test_tcp_counters_recv(void* arg
, struct tcp_pcb
* pcb
, struct pbuf
* p
, err_t err
)
162 struct test_tcp_counters
* counters
= arg
;
163 EXPECT_RETX(arg
!= NULL
, ERR_OK
);
164 EXPECT_RETX(pcb
!= NULL
, ERR_OK
);
165 EXPECT_RETX(err
== ERR_OK
, ERR_OK
);
168 if (counters
->close_calls
== 0) {
169 counters
->recv_calls
++;
170 test_tcp_counters_check_rxdata(counters
, p
);
171 counters
->recved_bytes
+= p
->tot_len
;
173 counters
->recv_calls_after_close
++;
174 counters
->recved_bytes_after_close
+= p
->tot_len
;
178 counters
->close_calls
++;
180 EXPECT(counters
->recv_calls_after_close
== 0 && counters
->recved_bytes_after_close
== 0);
184 /** Allocate a pcb and set up the test_tcp_counters_* callbacks */
186 test_tcp_new_counters_pcb(struct test_tcp_counters
* counters
)
188 struct tcp_pcb
* pcb
= tcp_new();
190 /* set up args and callbacks */
191 tcp_arg(pcb
, counters
);
192 tcp_recv(pcb
, test_tcp_counters_recv
);
193 tcp_err(pcb
, test_tcp_counters_err
);