mirror of
https://github.com/cesanta/mongoose.git
synced 2025-01-16 12:12:59 +08:00
test for retransmitted segment
This commit is contained in:
parent
320da5e84c
commit
ac40673a9e
@ -8085,7 +8085,7 @@ static void read_conn(struct mg_connection *c, struct pkt *pkt) {
|
|||||||
MG_DEBUG(("%lu SEQ %x -> %x", c->id, mg_htonl(pkt->tcp->seq), s->ack));
|
MG_DEBUG(("%lu SEQ %x -> %x", c->id, mg_htonl(pkt->tcp->seq), s->ack));
|
||||||
// Advance ACK counter
|
// Advance ACK counter
|
||||||
s->ack = (uint32_t) (mg_htonl(pkt->tcp->seq) + pkt->pay.len);
|
s->ack = (uint32_t) (mg_htonl(pkt->tcp->seq) + pkt->pay.len);
|
||||||
#ifdef MIP_TEST
|
#if 0
|
||||||
// Send ACK immediately
|
// Send ACK immediately
|
||||||
uint32_t rem_ip;
|
uint32_t rem_ip;
|
||||||
memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t));
|
memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t));
|
||||||
|
@ -600,7 +600,7 @@ static void read_conn(struct mg_connection *c, struct pkt *pkt) {
|
|||||||
MG_DEBUG(("%lu SEQ %x -> %x", c->id, mg_htonl(pkt->tcp->seq), s->ack));
|
MG_DEBUG(("%lu SEQ %x -> %x", c->id, mg_htonl(pkt->tcp->seq), s->ack));
|
||||||
// Advance ACK counter
|
// Advance ACK counter
|
||||||
s->ack = (uint32_t) (mg_htonl(pkt->tcp->seq) + pkt->pay.len);
|
s->ack = (uint32_t) (mg_htonl(pkt->tcp->seq) + pkt->pay.len);
|
||||||
#ifdef MIP_TEST
|
#if 0
|
||||||
// Send ACK immediately
|
// Send ACK immediately
|
||||||
uint32_t rem_ip;
|
uint32_t rem_ip;
|
||||||
memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t));
|
memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t));
|
||||||
|
@ -3,8 +3,6 @@
|
|||||||
#define MG_ENABLE_TCPIP 1
|
#define MG_ENABLE_TCPIP 1
|
||||||
#define MG_ENABLE_PACKED_FS 0
|
#define MG_ENABLE_PACKED_FS 0
|
||||||
|
|
||||||
#define MIP_TEST
|
|
||||||
|
|
||||||
#include "mongoose.c"
|
#include "mongoose.c"
|
||||||
#include "driver_mock.c"
|
#include "driver_mock.c"
|
||||||
|
|
||||||
@ -55,6 +53,7 @@ static void test_poll(void) {
|
|||||||
struct driver_data {
|
struct driver_data {
|
||||||
char buf[DRIVER_BUF_SIZE];
|
char buf[DRIVER_BUF_SIZE];
|
||||||
size_t len;
|
size_t len;
|
||||||
|
bool tx_ready; // data can be read from tx
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct driver_data s_driver_data;
|
static struct driver_data s_driver_data;
|
||||||
@ -62,7 +61,9 @@ static struct driver_data s_driver_data;
|
|||||||
static size_t if_tx(const void *buf, size_t len, struct mg_tcpip_if *ifp) {
|
static size_t if_tx(const void *buf, size_t len, struct mg_tcpip_if *ifp) {
|
||||||
struct driver_data *driver_data = (struct driver_data *) ifp->driver_data;
|
struct driver_data *driver_data = (struct driver_data *) ifp->driver_data;
|
||||||
if (len > DRIVER_BUF_SIZE) len = DRIVER_BUF_SIZE;
|
if (len > DRIVER_BUF_SIZE) len = DRIVER_BUF_SIZE;
|
||||||
|
driver_data->len = len;
|
||||||
memcpy(driver_data->buf, buf, len);
|
memcpy(driver_data->buf, buf, len);
|
||||||
|
driver_data->tx_ready = true;
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,11 +73,19 @@ static bool if_up(struct mg_tcpip_if *ifp) {
|
|||||||
|
|
||||||
static size_t if_rx(void *buf, size_t len, struct mg_tcpip_if *ifp) {
|
static size_t if_rx(void *buf, size_t len, struct mg_tcpip_if *ifp) {
|
||||||
struct driver_data *driver_data = (struct driver_data *) ifp->driver_data;
|
struct driver_data *driver_data = (struct driver_data *) ifp->driver_data;
|
||||||
|
if (!driver_data->len) return 0;
|
||||||
if (len > driver_data->len) len = driver_data->len;
|
if (len > driver_data->len) len = driver_data->len;
|
||||||
memcpy(buf, driver_data->buf, len);
|
memcpy(buf, driver_data->buf, len);
|
||||||
|
driver_data->len = 0; // cleaning up the buffer
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool received_response(struct driver_data *driver) {
|
||||||
|
bool was_ready = driver->tx_ready;
|
||||||
|
driver->tx_ready = false;
|
||||||
|
return was_ready;
|
||||||
|
}
|
||||||
|
|
||||||
static void create_tcp_pkt(struct eth *e, struct ip *ip, uint32_t seq,
|
static void create_tcp_pkt(struct eth *e, struct ip *ip, uint32_t seq,
|
||||||
uint32_t ack, uint8_t flags, size_t payload_len) {
|
uint32_t ack, uint8_t flags, size_t payload_len) {
|
||||||
struct tcp t;
|
struct tcp t;
|
||||||
@ -88,8 +97,8 @@ static void create_tcp_pkt(struct eth *e, struct ip *ip, uint32_t seq,
|
|||||||
memcpy(s_driver_data.buf, e, sizeof(*e));
|
memcpy(s_driver_data.buf, e, sizeof(*e));
|
||||||
memcpy(s_driver_data.buf + sizeof(*e), ip, sizeof(*ip));
|
memcpy(s_driver_data.buf + sizeof(*e), ip, sizeof(*ip));
|
||||||
memcpy(s_driver_data.buf + sizeof(*e) + sizeof(*ip), &t, sizeof(struct tcp));
|
memcpy(s_driver_data.buf + sizeof(*e) + sizeof(*ip), &t, sizeof(struct tcp));
|
||||||
s_driver_data.len =
|
s_driver_data.len = sizeof(*e) + sizeof(*ip)
|
||||||
sizeof(*e) + sizeof(*ip) + sizeof(struct tcp) + payload_len;
|
+ sizeof(struct tcp) + payload_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_retransmit(void) {
|
static void test_retransmit(void) {
|
||||||
@ -97,6 +106,8 @@ static void test_retransmit(void) {
|
|||||||
struct eth e;
|
struct eth e;
|
||||||
struct ip ip;
|
struct ip ip;
|
||||||
struct tcp *t;
|
struct tcp *t;
|
||||||
|
uint64_t start, now;
|
||||||
|
bool response_recv = true;
|
||||||
struct mg_tcpip_driver driver;
|
struct mg_tcpip_driver driver;
|
||||||
struct mg_tcpip_if mif;
|
struct mg_tcpip_if mif;
|
||||||
struct mg_connection *c;
|
struct mg_connection *c;
|
||||||
@ -108,15 +119,17 @@ static void test_retransmit(void) {
|
|||||||
mif.driver = &driver;
|
mif.driver = &driver;
|
||||||
mif.driver_data = &s_driver_data;
|
mif.driver_data = &s_driver_data;
|
||||||
mg_tcpip_init(&mgr, &mif);
|
mg_tcpip_init(&mgr, &mif);
|
||||||
c = mg_alloc_conn(&mgr);
|
c = mg_alloc_conn(&mgr); // create dummy connection
|
||||||
LIST_ADD_HEAD(struct mg_connection, &mgr.conns, c);
|
LIST_ADD_HEAD(struct mg_connection, &mgr.conns, c);
|
||||||
c->is_listening = 1;
|
c->is_listening = 1;
|
||||||
mg_mgr_poll(&mgr, 0);
|
mg_mgr_poll(&mgr, 0);
|
||||||
|
|
||||||
|
// setting the Ethernet header
|
||||||
memset(&e, 0, sizeof(e));
|
memset(&e, 0, sizeof(e));
|
||||||
memcpy(e.dst, mif.mac, 6 * sizeof(uint8_t));
|
memcpy(e.dst, mif.mac, 6 * sizeof(uint8_t));
|
||||||
e.type = mg_htons(0x800);
|
e.type = mg_htons(0x800);
|
||||||
|
|
||||||
|
// setting the IP header
|
||||||
memset(&ip, 0, sizeof(ip));
|
memset(&ip, 0, sizeof(ip));
|
||||||
ip.ver = 4 << 4, ip.proto = 6;
|
ip.ver = 4 << 4, ip.proto = 6;
|
||||||
ip.len = mg_htons(sizeof(ip) + sizeof(struct tcp));
|
ip.len = mg_htons(sizeof(ip) + sizeof(struct tcp));
|
||||||
@ -126,6 +139,7 @@ static void test_retransmit(void) {
|
|||||||
mg_mgr_poll(&mgr, 0);
|
mg_mgr_poll(&mgr, 0);
|
||||||
|
|
||||||
// SYN-ACK
|
// SYN-ACK
|
||||||
|
while(!received_response(&s_driver_data)) mg_mgr_poll(&mgr, 0);
|
||||||
t = (struct tcp *) (s_driver_data.buf + sizeof(struct eth) +
|
t = (struct tcp *) (s_driver_data.buf + sizeof(struct eth) +
|
||||||
sizeof(struct ip));
|
sizeof(struct ip));
|
||||||
ASSERT((t->flags == (TH_SYN | TH_ACK)));
|
ASSERT((t->flags == (TH_SYN | TH_ACK)));
|
||||||
@ -140,26 +154,50 @@ static void test_retransmit(void) {
|
|||||||
mg_htons(sizeof(struct ip) + sizeof(struct tcp) + /* TCP Payload */ 1);
|
mg_htons(sizeof(struct ip) + sizeof(struct tcp) + /* TCP Payload */ 1);
|
||||||
create_tcp_pkt(&e, &ip, 1001, 1, TH_PUSH | TH_ACK, 1);
|
create_tcp_pkt(&e, &ip, 1001, 1, TH_PUSH | TH_ACK, 1);
|
||||||
mg_mgr_poll(&mgr, 0);
|
mg_mgr_poll(&mgr, 0);
|
||||||
|
while(!received_response(&s_driver_data)) mg_mgr_poll(&mgr, 0);
|
||||||
t = (struct tcp *) (s_driver_data.buf + sizeof(struct eth) +
|
t = (struct tcp *) (s_driver_data.buf + sizeof(struct eth) +
|
||||||
sizeof(struct ip));
|
sizeof(struct ip));
|
||||||
ASSERT((t->flags == TH_ACK));
|
ASSERT((t->flags == TH_ACK));
|
||||||
ASSERT((t->ack == mg_htonl(1002)));
|
ASSERT((t->ack == mg_htonl(1002))); // OK
|
||||||
|
|
||||||
// packet with seq_no = 1003
|
// resend packet with seq_no = 1001 (e.g.: MIP ACK lost)
|
||||||
|
create_tcp_pkt(&e, &ip, 1001, 1, TH_PUSH | TH_ACK, 1);
|
||||||
|
mg_mgr_poll(&mgr, 0);
|
||||||
|
start = mg_millis();
|
||||||
|
while(!received_response(&s_driver_data)) {
|
||||||
|
mg_mgr_poll(&mgr, 0);
|
||||||
|
now = mg_millis() - start;
|
||||||
|
// we wait enough time for a reply
|
||||||
|
if (now > 2 * MIP_TCP_ACK_MS) {
|
||||||
|
response_recv = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ASSERT((!response_recv)); // replies should not be sent for duplicate packets
|
||||||
|
|
||||||
|
// packet with seq_no = 1002 got lost/delayed, send seq_no = 1003
|
||||||
create_tcp_pkt(&e, &ip, 1003, 1, TH_PUSH | TH_ACK, 1);
|
create_tcp_pkt(&e, &ip, 1003, 1, TH_PUSH | TH_ACK, 1);
|
||||||
mg_mgr_poll(&mgr, 0);
|
mg_mgr_poll(&mgr, 0);
|
||||||
|
start = mg_millis();
|
||||||
|
while(!received_response(&s_driver_data)) {
|
||||||
|
mg_mgr_poll(&mgr, 0);
|
||||||
|
now = mg_millis() - start;
|
||||||
|
if (now > 2 * MIP_TCP_ACK_MS)
|
||||||
|
ASSERT(0); // response should have been received by now
|
||||||
|
}
|
||||||
t = (struct tcp *) (s_driver_data.buf + sizeof(struct eth) +
|
t = (struct tcp *) (s_driver_data.buf + sizeof(struct eth) +
|
||||||
sizeof(struct ip));
|
sizeof(struct ip));
|
||||||
ASSERT((t->flags == TH_ACK));
|
ASSERT((t->flags == TH_ACK));
|
||||||
ASSERT((t->ack == mg_htonl(1002)));
|
ASSERT((t->ack == mg_htonl(1002))); // dup ACK
|
||||||
|
|
||||||
// retransmitting packet with seq_no = 1002
|
// retransmitting packet with seq_no = 1002
|
||||||
create_tcp_pkt(&e, &ip, 1002, 1, TH_PUSH | TH_ACK, 1);
|
create_tcp_pkt(&e, &ip, 1002, 1, TH_PUSH | TH_ACK, 1);
|
||||||
mg_mgr_poll(&mgr, 0);
|
mg_mgr_poll(&mgr, 0);
|
||||||
|
while(!received_response(&s_driver_data)) mg_mgr_poll(&mgr, 0);
|
||||||
t = (struct tcp *) (s_driver_data.buf + sizeof(struct eth) +
|
t = (struct tcp *) (s_driver_data.buf + sizeof(struct eth) +
|
||||||
sizeof(struct ip));
|
sizeof(struct ip));
|
||||||
ASSERT((t->flags == TH_ACK));
|
ASSERT((t->flags == TH_ACK));
|
||||||
ASSERT((t->ack == mg_htonl(1003)));
|
ASSERT((t->ack == mg_htonl(1003))); // OK
|
||||||
|
|
||||||
s_driver_data.len = 0;
|
s_driver_data.len = 0;
|
||||||
mg_mgr_free(&mgr);
|
mg_mgr_free(&mgr);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user