- Properly sync to lwIP 1.4.0
- No code changes (except unit tests)

svn path=/trunk/; revision=54302
This commit is contained in:
Cameron Gutman 2011-11-05 18:54:49 +00:00
parent 64e1212557
commit 2506e5967c
12 changed files with 333 additions and 93 deletions

View file

@ -1,18 +1,29 @@
FUTURE
* TODO: The lwIP source code makes some invalid assumptions on processor
word-length, storage sizes and alignment. See the mailing lists for
problems with exoteric (/DSP) architectures showing these problems.
We still have to fix some of these issues neatly.
HISTORY HISTORY
(CVS HEAD) (CVS HEAD)
* [Enter new changes just after this line - do not remove this line] * [Enter new changes just after this line - do not remove this line]
++ New features:
++ Bugfixes:
(STABLE-1.4.0)
++ New features: ++ New features:
2011-03-27: Simon Goldschmidt
* tcp_impl.h, tcp_in.c, tcp_out.c: Removed 'dataptr' from 'struct tcp_seg' and
calculate it in tcp_zero_window_probe (the only place where it was used).
2010-11-21: Simon Goldschmidt
* dhcp.c/.h: Added a function to deallocate the struct dhcp from a netif
(fixes bug #31525).
2010-07-12: Simon Goldschmidt (patch by Stephane Lesage) 2010-07-12: Simon Goldschmidt (patch by Stephane Lesage)
* ip.c, udp.c/.h, pbuf.h, sockets.c: task #10495: Added support for * ip.c, udp.c/.h, pbuf.h, sockets.c: task #10495: Added support for
IP_MULTICAST_LOOP at socket- and raw-API level. IP_MULTICAST_LOOP at socket- and raw-API level.
@ -229,6 +240,137 @@ HISTORY
++ Bugfixes: ++ Bugfixes:
2011-04-20: Simon Goldschmidt
* sys_arch.txt: sys_arch_timeouts() is not needed any more.
2011-04-13: Simon Goldschmidt
* tcp.c, udp.c: Fixed bug #33048 (Bad range for IP source port numbers) by
using ports in the IANA private/dynamic range (49152 through 65535).
2011-03-29: Simon Goldschmidt, patch by Emil Lhungdahl:
* etharp.h/.c: Fixed broken VLAN support.
2011-03-27: Simon Goldschmidt
* tcp.c: Fixed bug #32926 (TCP_RMV(&tcp_bound_pcbs) is called on unbound tcp
pcbs) by checking if the pcb was bound (local_port != 0).
2011-03-27: Simon Goldschmidt
* ppp.c: Fixed bug #32280 (ppp: a pbuf is freed twice)
2011-03-27: Simon Goldschmidt
* sockets.c: Fixed bug #32906: lwip_connect+lwip_send did not work for udp and
raw pcbs with LWIP_TCPIP_CORE_LOCKING==1.
2011-03-27: Simon Goldschmidt
* tcp_out.c: Fixed bug #32820 (Outgoing TCP connections created before route
is present never times out) by starting retransmission timer before checking
route.
2011-03-22: Simon Goldschmidt
* ppp.c: Fixed bug #32648 (PPP code crashes when terminating a link) by only
calling sio_read_abort() if the file descriptor is valid.
2011-03-14: Simon Goldschmidt
* err.h/.c, sockets.c, api_msg.c: fixed bug #31748 (Calling non-blocking connect
more than once can render a socket useless) since it mainly involves changing
"FATAL" classification of error codes: ERR_USE and ERR_ISCONN just aren't fatal.
2011-03-13: Simon Goldschmidt
* sockets.c: fixed bug #32769 (ESHUTDOWN is linux-specific) by fixing
err_to_errno_table (ERR_CLSD: ENOTCONN instead of ESHUTDOWN), ERR_ISCONN:
use EALRADY instead of -1
2011-03-13: Simon Goldschmidt
* api_lib.c: netconn_accept: return ERR_ABRT instead of ERR_CLSD if the
connection has been aborted by err_tcp (since this is not a normal closing
procedure).
2011-03-13: Simon Goldschmidt
* tcp.c: tcp_bind: return ERR_VAL instead of ERR_ISCONN when trying to bind
with pcb->state != CLOSED
2011-02-17: Simon Goldschmidt
* rawapi.txt: Fixed bug #32561 tcp_poll argument definition out-of-order in
documentation
2011-02-17: Simon Goldschmidt
* many files: Added missing U/UL modifiers to fix 16-bit-arch portability.
2011-01-24: Simon Goldschmidt
* sockets.c: Fixed bug #31741: lwip_select seems to have threading problems
2010-12-02: Simon Goldschmidt
* err.h: Fixed ERR_IS_FATAL so that ERR_WOULDBLOCK is not fatal.
2010-11-23: Simon Goldschmidt
* api.h, api_lib.c, api_msg.c, sockets.c: netconn.recv_avail is only used for
LWIP_SO_RCVBUF and ioctl/FIONREAD.
2010-11-23: Simon Goldschmidt
* etharp.c: Fixed bug #31720: ARP-queueing: RFC 1122 recommends to queue at
least 1 packet -> ARP_QUEUEING==0 now queues the most recent packet.
2010-11-23: Simon Goldschmidt
* tcp_in.c: Fixed bug #30577: tcp_input: don't discard ACK-only packets after
refusing 'refused_data' again.
2010-11-22: Simon Goldschmidt
* sockets.c: Fixed bug #31590: getsockopt(... SO_ERROR ...) gives EINPROGRESS
after a successful nonblocking connection.
2010-11-22: Simon Goldschmidt
* etharp.c: Fixed bug #31722: IP packets sent with an AutoIP source addr
must be sent link-local
2010-11-22: Simon Goldschmidt
* timers.c: patch #7329: tcp_timer_needed prototype was ifdef'ed out for
LWIP_TIMERS==0
2010-11-20: Simon Goldschmidt
* sockets.c: Fixed bug #31170: lwip_setsockopt() does not set socket number
2010-11-20: Simon Goldschmidt
* sockets.h: Fixed bug #31304: Changed SHUT_RD, SHUT_WR and SHUT_RDWR to
resemble other stacks.
2010-11-20: Simon Goldschmidt
* dns.c: Fixed bug #31535: TCP_SND_QUEUELEN must be at least 2 or else
no-copy TCP writes will never succeed.
2010-11-20: Simon Goldschmidt
* dns.c: Fixed bug #31701: Error return value from dns_gethostbyname() does
not match documentation: return ERR_ARG instead of ERR_VAL if not
initialized or wrong argument.
2010-10-20: Simon Goldschmidt
* sockets.h: Fixed bug #31385: sizeof(struct sockaddr) is 30 but should be 16
2010-10-05: Simon Goldschmidt
* dhcp.c: Once again fixed #30038: DHCP/AutoIP cooperation failed when
replugging the network cable after an AutoIP address was assigned.
2010-08-10: Simon Goldschmidt
* tcp.c: Fixed bug #30728: tcp_new_port() did not check listen pcbs
2010-08-03: Simon Goldschmidt
* udp.c, raw.c: Don't chain empty pbufs when sending them (fixes bug #30625)
2010-08-01: Simon Goldschmidt (patch by Greg Renda)
* ppp.c: Applied patch #7264 (PPP protocols are rejected incorrectly on big
endian architectures)
2010-07-28: Simon Goldschmidt
* api_lib.c, api_msg.c, sockets.c, mib2.c: Fixed compilation with TCP or UDP
disabled.
2010-07-27: Simon Goldschmidt
* tcp.c: Fixed bug #30565 (tcp_connect() check bound list): that check did no
harm but never did anything
2010-07-21: Simon Goldschmidt
* ip.c: Fixed invalid fix for bug #30402 (CHECKSUM_GEN_IP_INLINE does not
add IP options)
2010-07-16: Kieran Mansley 2010-07-16: Kieran Mansley
* msg_in.c: Fixed SNMP ASN constant defines to not use ! operator * msg_in.c: Fixed SNMP ASN constant defines to not use ! operator

View file

@ -111,11 +111,16 @@ with newer versions.
* Added const char* name to mem- and memp-stats for easier debugging. * Added const char* name to mem- and memp-stats for easier debugging.
* Calculate the TCP/UDP checksum while copying to only fetch data once: * Calculate the TCP/UDP checksum while copying to only fetch data once:
Define LWIP_CHKSUM_COPY to a memcpy-like function that returns the checksum Define LWIP_CHKSUM_COPY to a memcpy-like function that returns the checksum
* Added SO_REUSE_RXTOALL to pass received UDP broadcast/multicast packets to * Added SO_REUSE_RXTOALL to pass received UDP broadcast/multicast packets to
more than one pcb. more than one pcb.
* Changed the semantics of ARP_QUEUEING==0: ARP_QUEUEING now cannot be turned
off any more, if this is set to 0, only one packet (the most recent one) is
queued (like demanded by RFC 1122).
++ Major bugfixes/improvements ++ Major bugfixes/improvements
* Implemented tcp_shutdown() to only shut down one end of a connection * Implemented tcp_shutdown() to only shut down one end of a connection

View file

@ -251,8 +251,9 @@ if a call to tcp_write() has failed because memory wasn't available,
the application may use the polling functionality to call tcp_write() the application may use the polling functionality to call tcp_write()
again when the connection has been idle for a while. again when the connection has been idle for a while.
- void tcp_poll(struct tcp_pcb *pcb, u8_t interval, - void tcp_poll(struct tcp_pcb *pcb,
err_t (* poll)(void *arg, struct tcp_pcb *tpcb)) err_t (* poll)(void *arg, struct tcp_pcb *tpcb),
u8_t interval)
Specifies the polling interval and the callback function that should Specifies the polling interval and the callback function that should
be called to poll the application. The interval is specified in be called to poll the application. The interval is specified in

View file

@ -123,18 +123,6 @@ The following functions must be implemented by the sys_arch:
sys_arch_mbox_fetch(mbox,msg,1) sys_arch_mbox_fetch(mbox,msg,1)
although this would introduce unnecessary delays. although this would introduce unnecessary delays.
- struct sys_timeouts *sys_arch_timeouts(void)
Returns a pointer to the per-thread sys_timeouts structure. In lwIP,
each thread has a list of timeouts which is repressented as a linked
list of sys_timeout structures. The sys_timeouts structure holds a
pointer to a linked list of timeouts. This function is called by
the lwIP timeout scheduler and must not return a NULL value.
In a single thread sys_arch implementation, this function will
simply return a pointer to a global sys_timeouts variable stored in
the sys_arch module.
If threads are supported by the underlying operating system and if If threads are supported by the underlying operating system and if
such functionality is needed in lwIP, the following function will have such functionality is needed in lwIP, the following function will have
to be implemented as well: to be implemented as well:

View file

@ -79,20 +79,6 @@ static void tcp_parseopt(struct tcp_pcb *pcb);
static err_t tcp_listen_input(struct tcp_pcb_listen *pcb); static err_t tcp_listen_input(struct tcp_pcb_listen *pcb);
static err_t tcp_timewait_input(struct tcp_pcb *pcb); static err_t tcp_timewait_input(struct tcp_pcb *pcb);
static const char * const tcp_state_str[] = {
"CLOSED",
"LISTEN",
"SYN_SENT",
"SYN_RCVD",
"ESTABLISHED",
"FIN_WAIT_1",
"FIN_WAIT_2",
"CLOSE_WAIT",
"CLOSING",
"LAST_ACK",
"TIME_WAIT"
};
/** /**
* The initial input processing of TCP. It verifies the TCP header, demultiplexes * The initial input processing of TCP. It verifies the TCP header, demultiplexes
* the segment between the PCBs and passes it on to tcp_process(), which implements * the segment between the PCBs and passes it on to tcp_process(), which implements

View file

@ -23,7 +23,7 @@ static Suite* create_suite(const char* name, TFun *tests, size_t num_tests, SFun
Suite *s = suite_create(name); Suite *s = suite_create(name);
for(i = 0; i < num_tests; i++) { for(i = 0; i < num_tests; i++) {
// Core test case /* Core test case */
TCase *tc_core = tcase_create("Core"); TCase *tc_core = tcase_create("Core");
if ((setup != NULL) || (teardown != NULL)) { if ((setup != NULL) || (teardown != NULL)) {
tcase_add_checked_fixture(tc_core, setup, teardown); tcase_add_checked_fixture(tc_core, setup, teardown);

View file

@ -3,6 +3,8 @@
#include "udp/test_udp.h" #include "udp/test_udp.h"
#include "tcp/test_tcp.h" #include "tcp/test_tcp.h"
#include "tcp/test_tcp_oos.h" #include "tcp/test_tcp_oos.h"
#include "core/test_mem.h"
#include "etharp/test_etharp.h"
#include "lwip/init.h" #include "lwip/init.h"
@ -16,6 +18,8 @@ int main()
udp_suite, udp_suite,
tcp_suite, tcp_suite,
tcp_oos_suite, tcp_oos_suite,
mem_suite,
etharp_suite,
}; };
size_t num = sizeof(suites)/sizeof(void*); size_t num = sizeof(suites)/sizeof(void*);
LWIP_ASSERT("No suites defined", num > 0); LWIP_ASSERT("No suites defined", num > 0);

View file

@ -1,6 +1,6 @@
#include "tcp_helper.h" #include "tcp_helper.h"
#include "lwip/tcp.h" #include "lwip/tcp_impl.h"
#include "lwip/stats.h" #include "lwip/stats.h"
#include "lwip/pbuf.h" #include "lwip/pbuf.h"
#include "lwip/inet_chksum.h" #include "lwip/inet_chksum.h"
@ -27,7 +27,6 @@ tcp_remove(struct tcp_pcb* pcb_list)
void void
tcp_remove_all(void) tcp_remove_all(void)
{ {
//tcp_remove(tcp_bound_pcbs);
tcp_remove(tcp_listen_pcbs.pcbs); tcp_remove(tcp_listen_pcbs.pcbs);
tcp_remove(tcp_active_pcbs); tcp_remove(tcp_active_pcbs);
tcp_remove(tcp_tw_pcbs); tcp_remove(tcp_tw_pcbs);
@ -51,14 +50,14 @@ tcp_create_rx_segment(struct tcp_pcb* pcb, void* data, size_t data_len, u32_t se
/** Create a TCP segment usable for passing to tcp_input */ /** Create a TCP segment usable for passing to tcp_input */
struct pbuf* struct pbuf*
tcp_create_segment(struct ip_addr* src_ip, struct ip_addr* dst_ip, tcp_create_segment(ip_addr_t* src_ip, ip_addr_t* dst_ip,
u16_t src_port, u16_t dst_port, void* data, size_t data_len, u16_t src_port, u16_t dst_port, void* data, size_t data_len,
u32_t seqno, u32_t ackno, u8_t headerflags) u32_t seqno, u32_t ackno, u8_t headerflags)
{ {
struct pbuf* p; struct pbuf* p;
struct ip_hdr* iphdr; struct ip_hdr* iphdr;
struct tcp_hdr* tcphdr; struct tcp_hdr* tcphdr;
u16_t pbuf_len = sizeof(struct ip_hdr) + sizeof(struct tcp_hdr) + data_len; u16_t pbuf_len = (u16_t)(sizeof(struct ip_hdr) + sizeof(struct tcp_hdr) + data_len);
p = pbuf_alloc(PBUF_RAW, pbuf_len, PBUF_POOL); p = pbuf_alloc(PBUF_RAW, pbuf_len, PBUF_POOL);
EXPECT_RETNULL(p != NULL); EXPECT_RETNULL(p != NULL);
@ -83,13 +82,14 @@ tcp_create_segment(struct ip_addr* src_ip, struct ip_addr* dst_ip,
tcphdr->ackno = htonl(ackno); tcphdr->ackno = htonl(ackno);
TCPH_HDRLEN_SET(tcphdr, sizeof(struct tcp_hdr)/4); TCPH_HDRLEN_SET(tcphdr, sizeof(struct tcp_hdr)/4);
TCPH_FLAGS_SET(tcphdr, headerflags); TCPH_FLAGS_SET(tcphdr, headerflags);
tcphdr->wnd = htonl(TCP_WND); tcphdr->wnd = htons(TCP_WND);
/* copy data */ /* copy data */
memcpy((char*)tcphdr + sizeof(struct tcp_hdr), data, data_len); memcpy((char*)tcphdr + sizeof(struct tcp_hdr), data, data_len);
/* calculate checksum */ /* calculate checksum */
tcphdr->chksum = inet_chksum_pseudo(p, &(iphdr->src), &(iphdr->dest),
tcphdr->chksum = inet_chksum_pseudo(p, src_ip, dst_ip,
IP_PROTO_TCP, p->tot_len); IP_PROTO_TCP, p->tot_len);
pbuf_header(p, sizeof(struct ip_hdr)); pbuf_header(p, sizeof(struct ip_hdr));
@ -99,8 +99,8 @@ tcp_create_segment(struct ip_addr* src_ip, struct ip_addr* dst_ip,
/** Safely bring a tcp_pcb into the requested state */ /** Safely bring a tcp_pcb into the requested state */
void void
tcp_set_state(struct tcp_pcb* pcb, enum tcp_state state, struct ip_addr* local_ip, tcp_set_state(struct tcp_pcb* pcb, enum tcp_state state, ip_addr_t* local_ip,
struct ip_addr* remote_ip, u16_t local_port, u16_t remote_port) ip_addr_t* remote_ip, u16_t local_port, u16_t remote_port)
{ {
/* @todo: are these all states? */ /* @todo: are these all states? */
/* @todo: remove from previous list */ /* @todo: remove from previous list */
@ -194,3 +194,20 @@ test_tcp_new_counters_pcb(struct test_tcp_counters* counters)
} }
return pcb; return pcb;
} }
/** Calls tcp_input() after adjusting current_iphdr_dest */
void test_tcp_input(struct pbuf *p, struct netif *inp)
{
struct ip_hdr *iphdr = (struct ip_hdr*)p->payload;
ip_addr_copy(current_iphdr_dest, iphdr->dest);
ip_addr_copy(current_iphdr_src, iphdr->src);
current_netif = inp;
current_header = iphdr;
tcp_input(p, inp);
current_iphdr_dest.addr = 0;
current_iphdr_src.addr = 0;
current_netif = NULL;
current_header = NULL;
}

View file

@ -21,16 +21,18 @@ struct test_tcp_counters {
/* Helper functions */ /* Helper functions */
void tcp_remove_all(void); void tcp_remove_all(void);
struct pbuf* tcp_create_segment(struct ip_addr* src_ip, struct ip_addr* dst_ip, struct pbuf* tcp_create_segment(ip_addr_t* src_ip, ip_addr_t* dst_ip,
u16_t src_port, u16_t dst_port, void* data, size_t data_len, u16_t src_port, u16_t dst_port, void* data, size_t data_len,
u32_t seqno, u32_t ackno, u8_t headerflags); u32_t seqno, u32_t ackno, u8_t headerflags);
struct pbuf* tcp_create_rx_segment(struct tcp_pcb* pcb, void* data, size_t data_len, struct pbuf* tcp_create_rx_segment(struct tcp_pcb* pcb, void* data, size_t data_len,
u32_t seqno_offset, u32_t ackno_offset, u8_t headerflags); u32_t seqno_offset, u32_t ackno_offset, u8_t headerflags);
void tcp_set_state(struct tcp_pcb* pcb, enum tcp_state state, struct ip_addr* local_ip, void tcp_set_state(struct tcp_pcb* pcb, enum tcp_state state, ip_addr_t* local_ip,
struct ip_addr* remote_ip, u16_t local_port, u16_t remote_port); ip_addr_t* remote_ip, u16_t local_port, u16_t remote_port);
void test_tcp_counters_err(void* arg, err_t err); void test_tcp_counters_err(void* arg, err_t err);
err_t test_tcp_counters_recv(void* arg, struct tcp_pcb* pcb, struct pbuf* p, err_t err); err_t test_tcp_counters_recv(void* arg, struct tcp_pcb* pcb, struct pbuf* p, err_t err);
struct tcp_pcb* test_tcp_new_counters_pcb(struct test_tcp_counters* counters); struct tcp_pcb* test_tcp_new_counters_pcb(struct test_tcp_counters* counters);
void test_tcp_input(struct pbuf *p, struct netif *inp);
#endif #endif

View file

@ -1,6 +1,6 @@
#include "test_tcp.h" #include "test_tcp.h"
#include "lwip/tcp.h" #include "lwip/tcp_impl.h"
#include "lwip/stats.h" #include "lwip/stats.h"
#include "tcp_helper.h" #include "tcp_helper.h"
@ -50,7 +50,7 @@ START_TEST(test_tcp_recv_inseq)
struct tcp_pcb* pcb; struct tcp_pcb* pcb;
struct pbuf* p; struct pbuf* p;
char data[] = {1, 2, 3, 4}; char data[] = {1, 2, 3, 4};
struct ip_addr remote_ip, local_ip; ip_addr_t remote_ip, local_ip;
u16_t data_len; u16_t data_len;
u16_t remote_port = 0x100, local_port = 0x101; u16_t remote_port = 0x100, local_port = 0x101;
struct netif netif; struct netif netif;
@ -76,7 +76,7 @@ START_TEST(test_tcp_recv_inseq)
EXPECT(p != NULL); EXPECT(p != NULL);
if (p != NULL) { if (p != NULL) {
/* pass the segment to tcp_input */ /* pass the segment to tcp_input */
tcp_input(p, &netif); test_tcp_input(p, &netif);
/* check if counters are as expected */ /* check if counters are as expected */
EXPECT(counters.close_calls == 0); EXPECT(counters.close_calls == 0);
EXPECT(counters.recv_calls == 1); EXPECT(counters.recv_calls == 1);

View file

@ -1,6 +1,6 @@
#include "test_tcp_oos.h" #include "test_tcp_oos.h"
#include "lwip/tcp.h" #include "lwip/tcp_impl.h"
#include "lwip/stats.h" #include "lwip/stats.h"
#include "tcp_helper.h" #include "tcp_helper.h"
@ -60,7 +60,7 @@ tcp_oos_seg_seqno(struct tcp_pcb* pcb, int seg_index)
return 0; return 0;
} }
/** Get the tcplen of a segment (by index) on the ooseq list /** Get the tcplen (datalen + SYN/FIN) of a segment (by index) on the ooseq list
* *
* @param pcb the pcb to check for ooseq segments * @param pcb the pcb to check for ooseq segments
* @param seg_index index of the segment on the ooseq list * @param seg_index index of the segment on the ooseq list
@ -84,6 +84,25 @@ tcp_oos_seg_tcplen(struct tcp_pcb* pcb, int seg_index)
return -1; return -1;
} }
/** Get the tcplen (datalen + SYN/FIN) of all segments on the ooseq list
*
* @param pcb the pcb to check for ooseq segments
* @return tcplen of all segment
*/
static int
tcp_oos_tcplen(struct tcp_pcb* pcb)
{
int len = 0;
struct tcp_seg* seg = pcb->ooseq;
/* then check the actual segment */
while(seg != NULL) {
len += TCP_TCPLEN(seg);
seg = seg->next;
}
return len;
}
/* Setup/teardown functions */ /* Setup/teardown functions */
static void static void
@ -115,7 +134,7 @@ START_TEST(test_tcp_recv_ooseq_FIN_OOSEQ)
5, 6, 7, 8, 5, 6, 7, 8,
9, 10, 11, 12, 9, 10, 11, 12,
13, 14, 15, 16}; 13, 14, 15, 16};
struct ip_addr remote_ip, local_ip; ip_addr_t remote_ip, local_ip;
u16_t data_len; u16_t data_len;
u16_t remote_port = 0x100, local_port = 0x101; u16_t remote_port = 0x100, local_port = 0x101;
struct netif netif; struct netif netif;
@ -161,7 +180,7 @@ START_TEST(test_tcp_recv_ooseq_FIN_OOSEQ)
EXPECT(p_fin != NULL); EXPECT(p_fin != NULL);
if ((pinseq != NULL) && (p_8_9 != NULL) && (p_4_8 != NULL) && (p_4_10 != NULL) && (p_2_14 != NULL) && (p_fin != NULL)) { if ((pinseq != NULL) && (p_8_9 != NULL) && (p_4_8 != NULL) && (p_4_10 != NULL) && (p_2_14 != NULL) && (p_fin != NULL)) {
/* pass the segment to tcp_input */ /* pass the segment to tcp_input */
tcp_input(p_8_9, &netif); test_tcp_input(p_8_9, &netif);
/* check if counters are as expected */ /* check if counters are as expected */
EXPECT(counters.close_calls == 0); EXPECT(counters.close_calls == 0);
EXPECT(counters.recv_calls == 0); EXPECT(counters.recv_calls == 0);
@ -173,7 +192,7 @@ START_TEST(test_tcp_recv_ooseq_FIN_OOSEQ)
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 9); /* includes FIN */ EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 9); /* includes FIN */
/* pass the segment to tcp_input */ /* pass the segment to tcp_input */
tcp_input(p_4_8, &netif); test_tcp_input(p_4_8, &netif);
/* check if counters are as expected */ /* check if counters are as expected */
EXPECT(counters.close_calls == 0); EXPECT(counters.close_calls == 0);
EXPECT(counters.recv_calls == 0); EXPECT(counters.recv_calls == 0);
@ -187,7 +206,7 @@ START_TEST(test_tcp_recv_ooseq_FIN_OOSEQ)
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 9); /* includes FIN */ EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 9); /* includes FIN */
/* pass the segment to tcp_input */ /* pass the segment to tcp_input */
tcp_input(p_4_10, &netif); test_tcp_input(p_4_10, &netif);
/* check if counters are as expected */ /* check if counters are as expected */
EXPECT(counters.close_calls == 0); EXPECT(counters.close_calls == 0);
EXPECT(counters.recv_calls == 0); EXPECT(counters.recv_calls == 0);
@ -201,35 +220,31 @@ START_TEST(test_tcp_recv_ooseq_FIN_OOSEQ)
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 9); /* includes FIN */ EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 9); /* includes FIN */
/* pass the segment to tcp_input */ /* pass the segment to tcp_input */
tcp_input(p_2_14, &netif); test_tcp_input(p_2_14, &netif);
/* check if counters are as expected */ /* check if counters are as expected */
EXPECT(counters.close_calls == 0); EXPECT(counters.close_calls == 0);
EXPECT(counters.recv_calls == 0); EXPECT(counters.recv_calls == 0);
EXPECT(counters.recved_bytes == 0); EXPECT(counters.recved_bytes == 0);
EXPECT(counters.err_calls == 0); EXPECT(counters.err_calls == 0);
/* check ooseq queue */ /* check ooseq queue */
EXPECT_OOSEQ(tcp_oos_count(pcb) == 2); EXPECT_OOSEQ(tcp_oos_count(pcb) == 1);
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 2); EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 2);
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 6); EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 15); /* includes FIN */
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 8);
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 9); /* includes FIN */
/* pass the segment to tcp_input */ /* pass the segment to tcp_input */
tcp_input(p_fin, &netif); test_tcp_input(p_fin, &netif);
/* check if counters are as expected */ /* check if counters are as expected */
EXPECT(counters.close_calls == 0); EXPECT(counters.close_calls == 0);
EXPECT(counters.recv_calls == 0); EXPECT(counters.recv_calls == 0);
EXPECT(counters.recved_bytes == 0); EXPECT(counters.recved_bytes == 0);
EXPECT(counters.err_calls == 0); EXPECT(counters.err_calls == 0);
/* ooseq queue: unchanged */ /* ooseq queue: unchanged */
EXPECT_OOSEQ(tcp_oos_count(pcb) == 2); EXPECT_OOSEQ(tcp_oos_count(pcb) == 1);
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 2); EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 2);
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 6); EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 15); /* includes FIN */
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 8);
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 9); /* includes FIN */
/* pass the segment to tcp_input */ /* pass the segment to tcp_input */
tcp_input(pinseq, &netif); test_tcp_input(pinseq, &netif);
/* check if counters are as expected */ /* check if counters are as expected */
EXPECT(counters.close_calls == 1); EXPECT(counters.close_calls == 1);
EXPECT(counters.recv_calls == 1); EXPECT(counters.recv_calls == 1);
@ -259,7 +274,7 @@ START_TEST(test_tcp_recv_ooseq_FIN_INSEQ)
5, 6, 7, 8, 5, 6, 7, 8,
9, 10, 11, 12, 9, 10, 11, 12,
13, 14, 15, 16}; 13, 14, 15, 16};
struct ip_addr remote_ip, local_ip; ip_addr_t remote_ip, local_ip;
u16_t data_len; u16_t data_len;
u16_t remote_port = 0x100, local_port = 0x101; u16_t remote_port = 0x100, local_port = 0x101;
struct netif netif; struct netif netif;
@ -315,7 +330,7 @@ START_TEST(test_tcp_recv_ooseq_FIN_INSEQ)
if ((pinseq != NULL) && (p_1_2 != NULL) && (p_4_8 != NULL) && (p_3_11 != NULL) && (p_2_12 != NULL) if ((pinseq != NULL) && (p_1_2 != NULL) && (p_4_8 != NULL) && (p_3_11 != NULL) && (p_2_12 != NULL)
&& (p_15_1 != NULL) && (p_15_1a != NULL) && (pinseqFIN != NULL)) { && (p_15_1 != NULL) && (p_15_1a != NULL) && (pinseqFIN != NULL)) {
/* pass the segment to tcp_input */ /* pass the segment to tcp_input */
tcp_input(p_1_2, &netif); test_tcp_input(p_1_2, &netif);
/* check if counters are as expected */ /* check if counters are as expected */
EXPECT(counters.close_calls == 0); EXPECT(counters.close_calls == 0);
EXPECT(counters.recv_calls == 0); EXPECT(counters.recv_calls == 0);
@ -327,7 +342,7 @@ START_TEST(test_tcp_recv_ooseq_FIN_INSEQ)
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 2); EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 2);
/* pass the segment to tcp_input */ /* pass the segment to tcp_input */
tcp_input(p_4_8, &netif); test_tcp_input(p_4_8, &netif);
/* check if counters are as expected */ /* check if counters are as expected */
EXPECT(counters.close_calls == 0); EXPECT(counters.close_calls == 0);
EXPECT(counters.recv_calls == 0); EXPECT(counters.recv_calls == 0);
@ -341,7 +356,7 @@ START_TEST(test_tcp_recv_ooseq_FIN_INSEQ)
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 8); EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 8);
/* pass the segment to tcp_input */ /* pass the segment to tcp_input */
tcp_input(p_3_11, &netif); test_tcp_input(p_3_11, &netif);
/* check if counters are as expected */ /* check if counters are as expected */
EXPECT(counters.close_calls == 0); EXPECT(counters.close_calls == 0);
EXPECT(counters.recv_calls == 0); EXPECT(counters.recv_calls == 0);
@ -356,23 +371,21 @@ START_TEST(test_tcp_recv_ooseq_FIN_INSEQ)
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 11); EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 11);
/* pass the segment to tcp_input */ /* pass the segment to tcp_input */
tcp_input(p_2_12, &netif); test_tcp_input(p_2_12, &netif);
/* check if counters are as expected */ /* check if counters are as expected */
EXPECT(counters.close_calls == 0); EXPECT(counters.close_calls == 0);
EXPECT(counters.recv_calls == 0); EXPECT(counters.recv_calls == 0);
EXPECT(counters.recved_bytes == 0); EXPECT(counters.recved_bytes == 0);
EXPECT(counters.err_calls == 0); EXPECT(counters.err_calls == 0);
/* check ooseq queue */ /* check ooseq queue */
EXPECT_OOSEQ(tcp_oos_count(pcb) == 3); EXPECT_OOSEQ(tcp_oos_count(pcb) == 2);
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1); EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1);
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 1); EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 1);
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 2); EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 2);
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 1); EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 12);
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 2) == 3);
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 2) == 11);
/* pass the segment to tcp_input */ /* pass the segment to tcp_input */
tcp_input(pinseq, &netif); test_tcp_input(pinseq, &netif);
/* check if counters are as expected */ /* check if counters are as expected */
EXPECT(counters.close_calls == 0); EXPECT(counters.close_calls == 0);
EXPECT(counters.recv_calls == 1); EXPECT(counters.recv_calls == 1);
@ -381,7 +394,7 @@ START_TEST(test_tcp_recv_ooseq_FIN_INSEQ)
EXPECT(pcb->ooseq == NULL); EXPECT(pcb->ooseq == NULL);
/* pass the segment to tcp_input */ /* pass the segment to tcp_input */
tcp_input(p_15_1, &netif); test_tcp_input(p_15_1, &netif);
/* check if counters are as expected */ /* check if counters are as expected */
EXPECT(counters.close_calls == 0); EXPECT(counters.close_calls == 0);
EXPECT(counters.recv_calls == 1); EXPECT(counters.recv_calls == 1);
@ -393,7 +406,7 @@ START_TEST(test_tcp_recv_ooseq_FIN_INSEQ)
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 1); EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 1);
/* pass the segment to tcp_input */ /* pass the segment to tcp_input */
tcp_input(p_15_1a, &netif); test_tcp_input(p_15_1a, &netif);
/* check if counters are as expected */ /* check if counters are as expected */
EXPECT(counters.close_calls == 0); EXPECT(counters.close_calls == 0);
EXPECT(counters.recv_calls == 1); EXPECT(counters.recv_calls == 1);
@ -405,7 +418,7 @@ START_TEST(test_tcp_recv_ooseq_FIN_INSEQ)
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 1); EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 1);
/* pass the segment to tcp_input */ /* pass the segment to tcp_input */
tcp_input(pinseqFIN, &netif); test_tcp_input(pinseqFIN, &netif);
/* check if counters are as expected */ /* check if counters are as expected */
EXPECT(counters.close_calls == 1); EXPECT(counters.close_calls == 1);
EXPECT(counters.recv_calls == 2); EXPECT(counters.recv_calls == 2);
@ -421,6 +434,99 @@ START_TEST(test_tcp_recv_ooseq_FIN_INSEQ)
} }
END_TEST END_TEST
static char data_full_wnd[TCP_WND];
/** create multiple segments and pass them to tcp_input with the first segment missing
* to simulate overruning the rxwin with ooseq queueing enabled */
START_TEST(test_tcp_recv_ooseq_overrun_rxwin)
{
int i, k;
struct test_tcp_counters counters;
struct tcp_pcb* pcb;
struct pbuf *pinseq, *p_ovr;
ip_addr_t remote_ip, local_ip;
u16_t remote_port = 0x100, local_port = 0x101;
struct netif netif;
int datalen = 0;
int datalen2;
LWIP_UNUSED_ARG(_i);
for(i = 0; i < sizeof(data_full_wnd); i++) {
data_full_wnd[i] = (char)i;
}
/* initialize local vars */
memset(&netif, 0, sizeof(netif));
IP4_ADDR(&local_ip, 192, 168, 1, 1);
IP4_ADDR(&remote_ip, 192, 168, 1, 2);
/* initialize counter struct */
memset(&counters, 0, sizeof(counters));
counters.expected_data_len = TCP_WND;
counters.expected_data = data_full_wnd;
/* create and initialize the pcb */
pcb = test_tcp_new_counters_pcb(&counters);
EXPECT_RET(pcb != NULL);
tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port);
pcb->rcv_nxt = 0x8000;
/* create segments */
/* pinseq is sent as last segment! */
pinseq = tcp_create_rx_segment(pcb, &data_full_wnd[0], TCP_MSS, 0, 0, TCP_ACK);
for(i = TCP_MSS, k = 0; i < TCP_WND; i += TCP_MSS, k++) {
int count, expected_datalen;
struct pbuf *p = tcp_create_rx_segment(pcb, &data_full_wnd[TCP_MSS*(k+1)],
TCP_MSS, TCP_MSS*(k+1), 0, TCP_ACK);
EXPECT(p != NULL);
/* pass the segment to tcp_input */
test_tcp_input(p, &netif);
/* check if counters are as expected */
EXPECT(counters.close_calls == 0);
EXPECT(counters.recv_calls == 0);
EXPECT(counters.recved_bytes == 0);
EXPECT(counters.err_calls == 0);
/* check ooseq queue */
count = tcp_oos_count(pcb);
EXPECT_OOSEQ(count == k+1);
datalen = tcp_oos_tcplen(pcb);
if (i + TCP_MSS < TCP_WND) {
expected_datalen = (k+1)*TCP_MSS;
} else {
expected_datalen = TCP_WND - TCP_MSS;
}
if (datalen != expected_datalen) {
EXPECT_OOSEQ(datalen == expected_datalen);
}
}
/* pass in one more segment, cleary overrunning the rxwin */
p_ovr = tcp_create_rx_segment(pcb, &data_full_wnd[TCP_MSS*(k+1)], TCP_MSS, TCP_MSS*(k+1), 0, TCP_ACK);
EXPECT(p_ovr != NULL);
/* pass the segment to tcp_input */
test_tcp_input(p_ovr, &netif);
/* check if counters are as expected */
EXPECT(counters.close_calls == 0);
EXPECT(counters.recv_calls == 0);
EXPECT(counters.recved_bytes == 0);
EXPECT(counters.err_calls == 0);
/* check ooseq queue */
EXPECT_OOSEQ(tcp_oos_count(pcb) == k);
datalen2 = tcp_oos_tcplen(pcb);
EXPECT_OOSEQ(datalen == datalen2);
/* now pass inseq */
test_tcp_input(pinseq, &netif);
EXPECT(pcb->ooseq == NULL);
/* make sure the pcb is freed */
EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 1);
tcp_abort(pcb);
EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
}
END_TEST
/** Create the suite including all tests for this module */ /** Create the suite including all tests for this module */
Suite * Suite *
tcp_oos_suite(void) tcp_oos_suite(void)
@ -428,6 +534,7 @@ tcp_oos_suite(void)
TFun tests[] = { TFun tests[] = {
test_tcp_recv_ooseq_FIN_OOSEQ, test_tcp_recv_ooseq_FIN_OOSEQ,
test_tcp_recv_ooseq_FIN_INSEQ, test_tcp_recv_ooseq_FIN_INSEQ,
test_tcp_recv_ooseq_overrun_rxwin,
}; };
return create_suite("TCP_OOS", tests, sizeof(tests)/sizeof(TFun), tcp_oos_setup, tcp_oos_teardown); return create_suite("TCP_OOS", tests, sizeof(tests)/sizeof(TFun), tcp_oos_setup, tcp_oos_teardown);
} }

View file

@ -56,17 +56,6 @@ START_TEST(test_udp_new_remove)
} }
END_TEST END_TEST
START_TEST(test_udp_remove)
{
struct udp_pcb* pcb;
LWIP_UNUSED_ARG(_i);
pcb = NULL;
//pcb = udp_new();
//fail_unless(pcb != NULL);
}
END_TEST
/** Create the suite including all tests for this module */ /** Create the suite including all tests for this module */
Suite * Suite *
@ -74,7 +63,6 @@ udp_suite(void)
{ {
TFun tests[] = { TFun tests[] = {
test_udp_new_remove, test_udp_new_remove,
test_udp_remove
}; };
return create_suite("UDP", tests, sizeof(tests)/sizeof(TFun), udp_setup, udp_teardown); return create_suite("UDP", tests, sizeof(tests)/sizeof(TFun), udp_setup, udp_teardown);
} }