summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2012-10-21 05:32:43 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2012-10-21 05:32:43 +0200
commit758611ccd2a8ce105258cf766fc5aa7b0719ae95 (patch)
treefc5260a8fa2c2489e0b7234535e617e0554cf784
parentaa15b96d39dd0242c33b7a11c7c02ebdba50f150 (diff)
downloadffd-758611ccd2a8ce105258cf766fc5aa7b0719ae95.tar
ffd-758611ccd2a8ce105258cf766fc5aa7b0719ae95.zip
Use acked updates for seqno request replies
-rw-r--r--ffd/ack.c5
-rw-r--r--ffd/ffd.c4
-rw-r--r--ffd/ffd.h2
-rw-r--r--ffd/send.c17
-rw-r--r--ffd/send.h2
-rw-r--r--ffd/update.c38
6 files changed, 56 insertions, 12 deletions
diff --git a/ffd/ack.c b/ffd/ack.c
index 0dbb13c..cd21d0f 100644
--- a/ffd/ack.c
+++ b/ffd/ack.c
@@ -40,6 +40,7 @@ static uint16_t nonce = 0;
typedef struct _ack_arg_t {
void (*cb)(uint16_t nonce, void *arg);
+ void (*free)(uint16_t nonce, void *arg);
void *arg;
uint16_t nonce;
@@ -56,6 +57,7 @@ static void ack_resend(const struct timespec *timeout, void *argp) {
ack_arg_t *arg = argp;
if (GET_ACK(arg->nonce) || !(--arg->retries)) {
+ arg->free(arg->nonce, arg->arg);
free(arg);
return;
}
@@ -65,12 +67,13 @@ static void ack_resend(const struct timespec *timeout, void *argp) {
ffd_queue_put_delayed(&ack_requests, ack_resend, timeout, arg->interval, arg);
}
-void ffd_ack_request(void (*cb)(uint16_t nonce, void *arg), unsigned interval, unsigned retries, void *arg) {
+void ffd_ack_request(void (*cb)(uint16_t nonce, void *arg), void (*free_cb)(uint16_t nonce, void *arg), unsigned interval, unsigned retries, void *arg) {
UNSET_ACK(nonce);
cb(nonce, arg);
ack_arg_t *ack_arg = malloc(sizeof(ack_arg_t));
ack_arg->cb = cb;
+ ack_arg->free = free_cb;
ack_arg->arg = arg;
ack_arg->nonce = nonce++;
ack_arg->interval = interval;
diff --git a/ffd/ffd.c b/ffd/ffd.c
index 6b01cd3..0504085 100644
--- a/ffd/ffd.c
+++ b/ffd/ffd.c
@@ -407,14 +407,14 @@ static void handle_tlv_seqno_req(const ffd_tlv_seqno_req_t *tlv_req, size_t len,
if ((int16_t)(seqno-announce->selected->metric_seqno.seqno) <= 0) {
fprintf(stderr, "debug: received seqno request, seqno already ok\n");
- ffd_update_enqueue(&announce->node, announce->type, announce->key, neigh, false);
+ ffd_update_enqueue(&announce->node, announce->type, announce->key, neigh, true);
return;
}
if (!announce->selected->neigh) {
fprintf(stderr, "debug: received seqno request, incrementing seqno\n");
announce->selected->metric_seqno.seqno++;
- ffd_update_enqueue(&announce->node, announce->type, announce->key, neigh, false);
+ ffd_update_enqueue(&announce->node, announce->type, announce->key, neigh, true);
return;
}
diff --git a/ffd/ffd.h b/ffd/ffd.h
index b78f7af..2999be4 100644
--- a/ffd/ffd.h
+++ b/ffd/ffd.h
@@ -209,7 +209,7 @@ bool ffd_announce_seqno_request(ffd_announce_t *announce, ffd_neigh_t *neigh, ui
void ffd_announce_free(ffd_announce_t *announce);
void ffd_ack_handle(uint16_t n);
-void ffd_ack_request(void (*cb)(uint16_t nonce, void *arg), unsigned interval, unsigned retries, void *arg);
+void ffd_ack_request(void (*cb)(uint16_t nonce, void *arg), void (*free_cb)(uint16_t nonce, void *arg), unsigned interval, unsigned retries, void *arg);
int ffd_ack_timeout(void);
void ffd_ack_run(void);
diff --git a/ffd/send.c b/ffd/send.c
index dc6544b..2cd57bf 100644
--- a/ffd/send.c
+++ b/ffd/send.c
@@ -188,6 +188,18 @@ void ffd_send_hellos(void) {
}
}
+static bool add_ack_request(ffd_packet_t *packet, uint16_t nonce) {
+ ffd_tlv_ack_req_t *tlv = ffd_tlv_add(packet, FFD_PACKET_MAX, TLV_ACK_REQ, sizeof(ffd_tlv_ack_req_t));
+ if (!tlv)
+ return false;
+
+ tlv->reserved = 0;
+ tlv->nonce = htons(nonce);
+ tlv->interval = htons(FFD_ACK_INTERVAL);
+
+ return true;
+}
+
static bool add_node_id(ffd_packet_t *packet, size_t max_len, ffd_node_id_t node_id) {
ffd_tlv_node_id_t *tlv = ffd_tlv_add(packet, FFD_PACKET_MAX, TLV_NODE_ID, sizeof(ffd_tlv_node_id_t));
if (!tlv)
@@ -329,7 +341,7 @@ void ffd_send_retract(ffd_neigh_t *neigh, ffd_node_id_t node, uint16_t type, uin
send_neigh(neigh, packet);
}
-ffd_update_t* ffd_send_update_new(ffd_iface_t *iface, ffd_neigh_t *neigh) {
+ffd_update_t* ffd_send_update_new(ffd_iface_t *iface, ffd_neigh_t *neigh, const uint16_t *nonce) {
unsigned max_updates = (FFD_PACKET_MAX+sizeof(ffd_tlv_update_t)+1)/(sizeof(ffd_tlv_update_t)+2);
ffd_update_t *update = calloc(1, sizeof(ffd_update_t) + max_updates*sizeof(announce_info_t));
update->iface = iface;
@@ -340,6 +352,9 @@ ffd_update_t* ffd_send_update_new(ffd_iface_t *iface, ffd_neigh_t *neigh) {
update->packet->version_magic = htons(FFD_VERSION_MAGIC);
update->packet->len = 0;
+ if (nonce)
+ add_ack_request(update->packet, *nonce);
+
return update;
}
diff --git a/ffd/send.h b/ffd/send.h
index fbd9062..50a61e2 100644
--- a/ffd/send.h
+++ b/ffd/send.h
@@ -40,7 +40,7 @@ void ffd_send_retract(ffd_neigh_t *neigh, ffd_node_id_t node, uint16_t type, uin
void ffd_send_announce_request(ffd_iface_t *iface, ffd_neigh_t *neigh, ffd_node_id_t node, uint16_t type, uint16_t key, bool with_data);
void ffd_send_seqno_request(ffd_neigh_t *neigh, ffd_announce_t *announce, uint16_t seqno);
-ffd_update_t* ffd_send_update_new(ffd_iface_t *iface, ffd_neigh_t *neigh);
+ffd_update_t* ffd_send_update_new(ffd_iface_t *iface, ffd_neigh_t *neigh, const uint16_t *nonce);
bool ffd_send_update_add(ffd_update_t *update, ffd_announce_t *announce);
bool ffd_send_update_retract(ffd_update_t *update, ffd_node_id_t node, uint16_t type, uint16_t key);
void ffd_send_update_finish(ffd_update_t *update);
diff --git a/ffd/update.c b/ffd/update.c
index d273fec..77319bd 100644
--- a/ffd/update.c
+++ b/ffd/update.c
@@ -75,6 +75,27 @@ static inline void update_unref(update_arg_t *arg) {
}
}
+static void update_request_ack(uint16_t nonce, void *argp) {
+ update_arg_t *arg = argp;
+
+ fprintf(stderr, "debug: sending acked update with nonce %u.\n", nonce);
+
+ ffd_update_t *update = ffd_send_update_new(NULL, arg->neigh, &nonce);
+
+ ffd_announce_t *announce = ffd_announce_find(&arg->node, arg->type, arg->key);
+
+ if (announce)
+ ffd_send_update_add(update, announce);
+ else
+ ffd_send_update_retract(update, arg->node, arg->type, arg->key);
+
+ ffd_send_update_finish(update);
+}
+
+static void update_request_ack_free(uint16_t nonce, void *arg) {
+ update_unref(arg);
+}
+
void ffd_update_enqueue(const ffd_node_id_t *node, uint16_t type, uint16_t key, ffd_neigh_t *neigh, bool urgent) {
if (neigh)
ffd_neigh_ref(neigh);
@@ -82,11 +103,16 @@ void ffd_update_enqueue(const ffd_node_id_t *node, uint16_t type, uint16_t key,
update_arg_t *arg = update_new(node, type, key, neigh);
if (urgent) {
- ffd_queue_put_delayed(&pending_updates, NULL, &now, FFD_URGENT_DELAY, update_ref(arg));
- ffd_queue_put_delayed(&pending_updates, NULL, &now, 2*FFD_URGENT_DELAY, update_ref(arg));
- ffd_queue_put_delayed(&pending_updates, NULL, &now, 3*FFD_URGENT_DELAY, update_ref(arg));
- ffd_queue_put_delayed(&pending_updates, NULL, &now, 4*FFD_URGENT_DELAY, update_ref(arg));
- ffd_queue_put_delayed(&pending_updates, NULL, &now, 5*FFD_URGENT_DELAY, update_ref(arg));
+ if (neigh) {
+ ffd_ack_request(update_request_ack, update_request_ack_free, FFD_ACK_INTERVAL, 10, update_ref(arg));
+ }
+ else {
+ ffd_queue_put_delayed(&pending_updates, NULL, &now, FFD_URGENT_DELAY, update_ref(arg));
+ ffd_queue_put_delayed(&pending_updates, NULL, &now, 2*FFD_URGENT_DELAY, update_ref(arg));
+ ffd_queue_put_delayed(&pending_updates, NULL, &now, 3*FFD_URGENT_DELAY, update_ref(arg));
+ ffd_queue_put_delayed(&pending_updates, NULL, &now, 4*FFD_URGENT_DELAY, update_ref(arg));
+ ffd_queue_put_delayed(&pending_updates, NULL, &now, 5*FFD_URGENT_DELAY, update_ref(arg));
+ }
}
else {
ffd_queue_put_delayed(&pending_updates, NULL, &now, FFD_DELAY, update_ref(arg));
@@ -101,7 +127,7 @@ void ffd_update_run(void) {
while (!ffd_update_timeout()) {
ffd_neigh_t *neigh = ((update_arg_t*)pending_updates->arg)->neigh;
- ffd_update_t *update = ffd_send_update_new(NULL, neigh);
+ ffd_update_t *update = ffd_send_update_new(NULL, neigh, NULL);
fprintf(stderr, "debug: sending scheduled updates.\n");