Contiki 2.6
|
00001 /** 00002 * \addtogroup trickle 00003 * @{ 00004 */ 00005 00006 /* 00007 * Copyright (c) 2007, Swedish Institute of Computer Science. 00008 * All rights reserved. 00009 * 00010 * Redistribution and use in source and binary forms, with or without 00011 * modification, are permitted provided that the following conditions 00012 * are met: 00013 * 1. Redistributions of source code must retain the above copyright 00014 * notice, this list of conditions and the following disclaimer. 00015 * 2. Redistributions in binary form must reproduce the above copyright 00016 * notice, this list of conditions and the following disclaimer in the 00017 * documentation and/or other materials provided with the distribution. 00018 * 3. Neither the name of the Institute nor the names of its contributors 00019 * may be used to endorse or promote products derived from this software 00020 * without specific prior written permission. 00021 * 00022 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 00023 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00024 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00025 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 00026 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00027 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00028 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00029 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00030 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00031 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00032 * SUCH DAMAGE. 00033 * 00034 * This file is part of the Contiki operating system. 00035 * 00036 * $Id: trickle.c,v 1.18 2009/11/08 19:40:18 adamdunkels Exp $ 00037 */ 00038 00039 /** 00040 * \file 00041 * Trickle (reliable single source flooding) for Rime 00042 * \author 00043 * Adam Dunkels <adam@sics.se> 00044 */ 00045 00046 #include "net/rime/trickle.h" 00047 #include "lib/random.h" 00048 00049 #if CONTIKI_TARGET_NETSIM 00050 #include "ether.h" 00051 #endif 00052 00053 #define INTERVAL_MIN 1 00054 #define INTERVAL_MAX 4 00055 00056 #define DUPLICATE_THRESHOLD 1 00057 00058 #define SEQNO_LT(a, b) ((signed char)((a) - (b)) < 0) 00059 00060 static const struct packetbuf_attrlist attributes[] = 00061 { 00062 TRICKLE_ATTRIBUTES PACKETBUF_ATTR_LAST 00063 }; 00064 00065 00066 #define DEBUG 0 00067 #if DEBUG 00068 #include <stdio.h> 00069 #define PRINTF(...) printf(__VA_ARGS__) 00070 #else 00071 #define PRINTF(...) 00072 #endif 00073 00074 static int run_trickle(struct trickle_conn *c); 00075 /*---------------------------------------------------------------------------*/ 00076 static void 00077 send(void *ptr) 00078 { 00079 struct trickle_conn *c = ptr; 00080 00081 if(c->q != NULL) { 00082 queuebuf_to_packetbuf(c->q); 00083 broadcast_send(&c->c); 00084 } else { 00085 PRINTF("%d.%d: trickle send but c->q == NULL\n", 00086 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1]); 00087 } 00088 } 00089 /*---------------------------------------------------------------------------*/ 00090 static void 00091 timer_callback(void *ptr) 00092 { 00093 struct trickle_conn *c = ptr; 00094 run_trickle(c); 00095 } 00096 /*---------------------------------------------------------------------------*/ 00097 static void 00098 reset_interval(struct trickle_conn *c) 00099 { 00100 PT_INIT(&c->pt); 00101 run_trickle(c); 00102 } 00103 /*---------------------------------------------------------------------------*/ 00104 static void 00105 set_timer(struct trickle_conn *c, struct ctimer *t, clock_time_t i) 00106 { 00107 ctimer_set(t, i, timer_callback, c); 00108 } 00109 /*---------------------------------------------------------------------------*/ 00110 static int 00111 run_trickle(struct trickle_conn *c) 00112 { 00113 clock_time_t interval; 00114 PT_BEGIN(&c->pt); 00115 00116 while(1) { 00117 interval = c->interval << c->interval_scaling; 00118 set_timer(c, &c->interval_timer, interval); 00119 set_timer(c, &c->t, interval / 2 + (random_rand() % (interval / 2))); 00120 00121 c->duplicates = 0; 00122 PT_YIELD(&c->pt); /* Wait until listen timeout */ 00123 if(c->duplicates < DUPLICATE_THRESHOLD) { 00124 send(c); 00125 } 00126 PT_YIELD(&c->pt); /* Wait until interval timer expired. */ 00127 if(c->interval_scaling < INTERVAL_MAX) { 00128 c->interval_scaling++; 00129 } 00130 } 00131 00132 PT_END(&c->pt); 00133 } 00134 /*---------------------------------------------------------------------------*/ 00135 static void 00136 recv(struct broadcast_conn *bc, const rimeaddr_t *from) 00137 { 00138 struct trickle_conn *c = (struct trickle_conn *)bc; 00139 uint16_t seqno = packetbuf_attr(PACKETBUF_ATTR_EPACKET_ID); 00140 00141 PRINTF("%d.%d: trickle recv seqno %d from %d.%d our %d data len %d channel %d\n", 00142 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], 00143 seqno, 00144 from->u8[0], from->u8[1], 00145 c->seqno, 00146 packetbuf_datalen(), 00147 packetbuf_attr(PACKETBUF_ATTR_CHANNEL)); 00148 00149 if(seqno == c->seqno) { 00150 /* c->cb->recv(c);*/ 00151 ++c->duplicates; 00152 } else if(SEQNO_LT(seqno, c->seqno)) { 00153 c->interval_scaling = 0; 00154 send(c); 00155 } else { /* hdr->seqno > c->seqno */ 00156 #if CONTIKI_TARGET_NETSIM 00157 /* ether_set_line(from->u8[0], from->u8[1]);*/ 00158 #endif /* CONTIKI_TARGET_NETSIM */ 00159 c->seqno = seqno; 00160 /* Store the incoming data in the queuebuf */ 00161 if(c->q != NULL) { 00162 queuebuf_free(c->q); 00163 } 00164 c->q = queuebuf_new_from_packetbuf(); 00165 c->interval_scaling = 0; 00166 reset_interval(c); 00167 ctimer_set(&c->first_transmission_timer, random_rand() % c->interval, 00168 send, c); 00169 c->cb->recv(c); 00170 } 00171 } 00172 /*---------------------------------------------------------------------------*/ 00173 static CC_CONST_FUNCTION struct broadcast_callbacks bc = { recv }; 00174 /*---------------------------------------------------------------------------*/ 00175 void 00176 trickle_open(struct trickle_conn *c, clock_time_t interval, 00177 uint16_t channel, const struct trickle_callbacks *cb) 00178 { 00179 broadcast_open(&c->c, channel, &bc); 00180 c->cb = cb; 00181 c->q = NULL; 00182 c->interval = interval; 00183 c->interval_scaling = 0; 00184 channel_set_attributes(channel, attributes); 00185 } 00186 /*---------------------------------------------------------------------------*/ 00187 void 00188 trickle_close(struct trickle_conn *c) 00189 { 00190 broadcast_close(&c->c); 00191 ctimer_stop(&c->t); 00192 ctimer_stop(&c->interval_timer); 00193 } 00194 /*---------------------------------------------------------------------------*/ 00195 void 00196 trickle_send(struct trickle_conn *c) 00197 { 00198 if(c->q != NULL) { 00199 queuebuf_free(c->q); 00200 } 00201 c->seqno++; 00202 packetbuf_set_attr(PACKETBUF_ATTR_EPACKET_ID, c->seqno); 00203 c->q = queuebuf_new_from_packetbuf(); 00204 PRINTF("%d.%d: trickle send seqno %d\n", 00205 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], 00206 c->seqno); 00207 reset_interval(c); 00208 send(c); 00209 } 00210 /*---------------------------------------------------------------------------*/ 00211 /** @} */