diff --git a/core/net/rime/trickle.c b/core/net/rime/trickle.c index 126a76ae3..4296520e3 100644 --- a/core/net/rime/trickle.c +++ b/core/net/rime/trickle.c @@ -33,7 +33,7 @@ * * This file is part of the Contiki operating system. * - * $Id: trickle.c,v 1.9 2008/07/03 22:02:10 adamdunkels Exp $ + * $Id: trickle.c,v 1.10 2008/07/07 23:29:30 adamdunkels Exp $ */ /** @@ -44,6 +44,7 @@ */ #include "net/rime/trickle.h" +#include "lib/random.h" #if NETSIM #include "ether.h" @@ -52,8 +53,16 @@ #define INTERVAL_MIN 1 #define INTERVAL_MAX 4 +#define DUPLICATE_THRESHOLD 1 + #define SEQNO_LT(a, b) ((signed char)((a) - (b)) < 0) +static const struct rimebuf_attrlist attributes[] = + { + TRICKLE_ATTRIBUTES RIMEBUF_ATTR_LAST + }; + + #define DEBUG 0 #if DEBUG #include @@ -62,7 +71,7 @@ #define PRINTF(...) #endif - +static int run_trickle(struct trickle_conn *c); /*---------------------------------------------------------------------------*/ static void send(void *ptr) @@ -71,20 +80,63 @@ send(void *ptr) if(c->q != NULL) { queuebuf_to_rimebuf(c->q); - netflood_send(&c->c, c->seqno); - ctimer_set(&c->t, c->interval << c->interval_scaling, - send, c); + broadcast_send(&c->c); } else { PRINTF("%d.%d: trickle send but c->q == NULL\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1]); } } /*---------------------------------------------------------------------------*/ -static int -recv(struct netflood_conn *nf, rimeaddr_t *from, - rimeaddr_t *originator, uint8_t seqno, uint8_t hops) +static void +timer_callback(void *ptr) { - struct trickle_conn *c = (struct trickle_conn *)nf; + struct trickle_conn *c = ptr; + run_trickle(c); +} +/*---------------------------------------------------------------------------*/ +static void +reset_interval(struct trickle_conn *c) +{ + PT_INIT(&c->pt); + run_trickle(c); +} +/*---------------------------------------------------------------------------*/ +static void +set_timer(struct trickle_conn *c, struct ctimer *t, clock_time_t i) +{ + ctimer_set(t, i, timer_callback, c); +} +/*---------------------------------------------------------------------------*/ +static int +run_trickle(struct trickle_conn *c) +{ + clock_time_t interval; + PT_BEGIN(&c->pt); + + while(1) { + interval = c->interval << c->interval_scaling; + set_timer(c, &c->interval_timer, interval); + set_timer(c, &c->t, interval / 2 + (random_rand() % (interval / 2))); + + c->duplicates = 0; + PT_YIELD(&c->pt); /* Wait until listen timeout */ + if(c->duplicates < DUPLICATE_THRESHOLD) { + send(c); + } + PT_YIELD(&c->pt); /* Wait until interval timer expired. */ + if(c->interval_scaling < INTERVAL_MAX) { + c->interval_scaling++; + } + } + + PT_END(&c->pt); +} +/*---------------------------------------------------------------------------*/ +static int +recv(struct broadcast_conn *bc, rimeaddr_t *from) +{ + struct trickle_conn *c = (struct trickle_conn *)bc; + uint16_t seqno = rimebuf_attr(RIMEBUF_ATTR_EPACKET_ID); PRINTF("%d.%d: trickle recv seqno %d our %d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], @@ -92,6 +144,7 @@ recv(struct netflood_conn *nf, rimeaddr_t *from, if(seqno == c->seqno) { /* c->cb->recv(c);*/ + ++c->duplicates; } else if(SEQNO_LT(seqno, c->seqno)) { c->interval_scaling = 0; send(c); @@ -106,42 +159,33 @@ recv(struct netflood_conn *nf, rimeaddr_t *from, } c->q = queuebuf_new_from_rimebuf(); c->interval_scaling = 0; + reset_interval(c); send(c); c->cb->recv(c); } return 0; } /*---------------------------------------------------------------------------*/ -static void -sent_or_dropped(struct netflood_conn *nf) -{ - struct trickle_conn *c = (struct trickle_conn *)nf; - - c->interval_scaling++; - if(c->interval_scaling > INTERVAL_MAX) { - c->interval_scaling = INTERVAL_MAX; - } -} -/*---------------------------------------------------------------------------*/ -static const struct netflood_callbacks nf = {recv, - sent_or_dropped, - sent_or_dropped}; +static CC_CONST_FUNCTION struct broadcast_callbacks bc = { recv }; /*---------------------------------------------------------------------------*/ void trickle_open(struct trickle_conn *c, clock_time_t interval, uint16_t channel, const struct trickle_callbacks *cb) { - netflood_open(&c->c, interval, channel, &nf); + broadcast_open(&c->c, channel, &bc); c->cb = cb; c->q = NULL; c->interval = interval; + c->interval_scaling = 0; + channel_set_attributes(channel, attributes); } /*---------------------------------------------------------------------------*/ void trickle_close(struct trickle_conn *c) { - netflood_close(&c->c); + broadcast_close(&c->c); ctimer_stop(&c->t); + ctimer_stop(&c->interval_timer); } /*---------------------------------------------------------------------------*/ void @@ -150,11 +194,13 @@ trickle_send(struct trickle_conn *c) if(c->q != NULL) { queuebuf_free(c->q); } - c->q = queuebuf_new_from_rimebuf(); c->seqno++; + rimebuf_set_attr(RIMEBUF_ATTR_EPACKET_ID, c->seqno); + c->q = queuebuf_new_from_rimebuf(); PRINTF("%d.%d: trickle send seqno %d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], c->seqno); + reset_interval(c); send(c); } /*---------------------------------------------------------------------------*/ diff --git a/core/net/rime/trickle.h b/core/net/rime/trickle.h index 22af0ff60..41e752a38 100644 --- a/core/net/rime/trickle.h +++ b/core/net/rime/trickle.h @@ -45,7 +45,7 @@ * * This file is part of the Contiki operating system. * - * $Id: trickle.h,v 1.8 2008/07/03 22:02:10 adamdunkels Exp $ + * $Id: trickle.h,v 1.9 2008/07/07 23:29:30 adamdunkels Exp $ */ /** @@ -58,7 +58,12 @@ #ifndef __TRICKLE_H__ #define __TRICKLE_H__ -#include "net/rime/netflood.h" +#include "net/rime/broadcast.h" +#include "net/rime/ctimer.h" +#include "net/rime/queuebuf.h" + +#define TRICKLE_ATTRIBUTES { RIMEBUF_ATTR_EPACKET_ID, RIMEBUF_ATTR_BIT * 8 },\ + BROADCAST_ATTRIBUTES struct trickle_conn; @@ -67,13 +72,15 @@ struct trickle_callbacks { }; struct trickle_conn { - struct netflood_conn c; + struct broadcast_conn c; const struct trickle_callbacks *cb; - struct ctimer t; + struct ctimer t, interval_timer; + struct pt pt; struct queuebuf *q; clock_time_t interval; uint8_t seqno; uint8_t interval_scaling; + uint8_t duplicates; }; void trickle_open(struct trickle_conn *c, clock_time_t interval,