From 30216bf35c8cfe078ede4c4ad7f43544b469b7d3 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 25 Sep 2008 17:06:12 +0200 Subject: ftfw: fix race condition in the helloing routine This patch fixes a race condition that can prevent one node from sending the initial hello message required to reset the sequence tracking. node A node B | | start | | hello msg |----------------------->| stop | | start | | |<-----------------------| hello-back msg In the picture above, the node A never sends the hello messages. Thus, the node B drops the next messages as they are in the before boundary. This patch adds a new state to the the helloing state-machine to fix this problem. Signed-off-by: Pablo Neira Ayuso --- src/sync-ftfw.c | 44 ++++++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 14 deletions(-) (limited to 'src/sync-ftfw.c') diff --git a/src/sync-ftfw.c b/src/sync-ftfw.c index 8dd5554..11c0638 100644 --- a/src/sync-ftfw.c +++ b/src/sync-ftfw.c @@ -46,7 +46,14 @@ static uint32_t window; static uint32_t ack_from; static int ack_from_set = 0; static struct alarm_block alive_alarm; -static int hello_state = SAY_HELLO; + +enum { + HELLO_INIT, + HELLO_SAY, + HELLO_DONE, +}; +static int hello_state = HELLO_INIT; +static int say_hello_back; /* XXX: alive message expiration configurable */ #define ALIVE_INT 1 @@ -96,13 +103,17 @@ static void tx_queue_add_ctlmsg(uint32_t flags, uint32_t from, uint32_t to) }; switch(hello_state) { - case SAY_HELLO: + case HELLO_INIT: + hello_state = HELLO_SAY; + /* fall through */ + case HELLO_SAY: ack.flags |= NET_F_HELLO; break; - case HELLO_BACK: + } + + if (say_hello_back) { ack.flags |= NET_F_HELLO_BACK; - hello_state = HELLO_DONE; - break; + say_hello_back = 0; } queue_add(tx_queue, &ack, NETHDR_ACK_SIZ); @@ -335,12 +346,13 @@ static int digest_hello(const struct nethdr *net) int ret = 0; if (IS_HELLO(net)) { - dlog(LOG_NOTICE, "The other node says HELLO"); - hello_state = HELLO_BACK; + say_hello_back = 1; ret = 1; - } else if (IS_HELLO_BACK(net)) { - dlog(LOG_NOTICE, "The other node says HELLO BACK"); - hello_state = HELLO_DONE; + } + if (IS_HELLO_BACK(net)) { + /* this is a hello back for a requested hello */ + if (hello_state == HELLO_SAY) + hello_state = HELLO_DONE; } return ret; @@ -428,15 +440,19 @@ static void ftfw_send(struct nethdr *net, struct us_conntrack *u) } switch(hello_state) { - case SAY_HELLO: + case HELLO_INIT: + hello_state = HELLO_SAY; + /* fall through */ + case HELLO_SAY: net->flags = ntohs(net->flags) | NET_F_HELLO; net->flags = htons(net->flags); break; - case HELLO_BACK: + } + + if (say_hello_back) { net->flags = ntohs(net->flags) | NET_F_HELLO_BACK; net->flags = htons(net->flags); - hello_state = HELLO_DONE; - break; + say_hello_back = 0; } cn->seq = ntohl(net->seq); -- cgit v1.2.3