Contiki 2.6
|
00001 /** 00002 * \addtogroup rimerunicast 00003 * @{ 00004 */ 00005 00006 00007 /* 00008 * Copyright (c) 2006, Swedish Institute of Computer Science. 00009 * All rights reserved. 00010 * 00011 * Redistribution and use in source and binary forms, with or without 00012 * modification, are permitted provided that the following conditions 00013 * are met: 00014 * 1. Redistributions of source code must retain the above copyright 00015 * notice, this list of conditions and the following disclaimer. 00016 * 2. Redistributions in binary form must reproduce the above copyright 00017 * notice, this list of conditions and the following disclaimer in the 00018 * documentation and/or other materials provided with the distribution. 00019 * 3. Neither the name of the Institute nor the names of its contributors 00020 * may be used to endorse or promote products derived from this software 00021 * without specific prior written permission. 00022 * 00023 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 00024 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00025 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00026 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 00027 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00028 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00029 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00030 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00031 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00032 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00033 * SUCH DAMAGE. 00034 * 00035 * This file is part of the Contiki operating system. 00036 * 00037 * $Id: runicast.c,v 1.12 2010/03/26 12:29:29 nifi Exp $ 00038 */ 00039 00040 /** 00041 * \file 00042 * Reliable unicast 00043 * \author 00044 * Adam Dunkels <adam@sics.se> 00045 */ 00046 00047 #include "net/rime/runicast.h" 00048 #include "net/rime.h" 00049 #include <string.h> 00050 00051 00052 #ifdef RUNICAST_CONF_REXMIT_TIME 00053 #define REXMIT_TIME RUNICAST_CONF_REXMIT_TIME 00054 #else /* RUNICAST_CONF_REXMIT_TIME */ 00055 #define REXMIT_TIME CLOCK_SECOND 00056 #endif /* RUNICAST_CONF_REXMIT_TIME */ 00057 00058 static const struct packetbuf_attrlist attributes[] = 00059 { 00060 RUNICAST_ATTRIBUTES 00061 PACKETBUF_ATTR_LAST 00062 }; 00063 00064 #define DEBUG 0 00065 #if DEBUG 00066 #include <stdio.h> 00067 #define PRINTF(...) printf(__VA_ARGS__) 00068 #else 00069 #define PRINTF(...) 00070 #endif 00071 00072 /*---------------------------------------------------------------------------*/ 00073 static void 00074 sent_by_stunicast(struct stunicast_conn *stunicast, int status, int num_tx) 00075 { 00076 struct runicast_conn *c = (struct runicast_conn *)stunicast; 00077 00078 PRINTF("runicast: sent_by_stunicast c->rxmit %d num_tx %d\n", 00079 c->rxmit, num_tx); 00080 00081 /* Only process data packets, not ACKs. */ 00082 if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) == PACKETBUF_ATTR_PACKET_TYPE_DATA) { 00083 00084 c->rxmit += 1; 00085 00086 if(c->rxmit != 0) { 00087 RIMESTATS_ADD(rexmit); 00088 PRINTF("%d.%d: runicast: sent_by_stunicast packet %u (%u) resent %u\n", 00089 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], 00090 packetbuf_attr(PACKETBUF_ATTR_PACKET_ID), 00091 c->sndnxt, c->rxmit); 00092 } 00093 if(c->rxmit >= c->max_rxmit) { 00094 RIMESTATS_ADD(timedout); 00095 c->is_tx = 0; 00096 stunicast_cancel(&c->c); 00097 if(c->u->timedout) { 00098 c->u->timedout(c, stunicast_receiver(&c->c), c->rxmit); 00099 } 00100 c->rxmit = 0; 00101 PRINTF("%d.%d: runicast: packet %d timed out\n", 00102 rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1], 00103 c->sndnxt); 00104 c->sndnxt = (c->sndnxt + 1) % (1 << RUNICAST_PACKET_ID_BITS); 00105 } else { 00106 // int shift; 00107 00108 // shift = c->rxmit > 4? 4: c->rxmit; 00109 // stunicast_set_timer(&c->c, (REXMIT_TIME) << shift); 00110 } 00111 } 00112 } 00113 /*---------------------------------------------------------------------------*/ 00114 static void 00115 recv_from_stunicast(struct stunicast_conn *stunicast, const rimeaddr_t *from) 00116 { 00117 struct runicast_conn *c = (struct runicast_conn *)stunicast; 00118 /* struct runicast_hdr *hdr = packetbuf_dataptr();*/ 00119 00120 PRINTF("%d.%d: runicast: recv_from_stunicast from %d.%d type %d seqno %d\n", 00121 rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1], 00122 from->u8[0], from->u8[1], 00123 packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE), 00124 packetbuf_attr(PACKETBUF_ATTR_PACKET_ID)); 00125 00126 if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) == 00127 PACKETBUF_ATTR_PACKET_TYPE_ACK) { 00128 PRINTF("%d.%d: runicast: got ACK from %d.%d, seqno %d (%d)\n", 00129 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], 00130 from->u8[0], from->u8[1], 00131 packetbuf_attr(PACKETBUF_ATTR_PACKET_ID), 00132 c->sndnxt); 00133 if(packetbuf_attr(PACKETBUF_ATTR_PACKET_ID) == c->sndnxt) { 00134 RIMESTATS_ADD(ackrx); 00135 PRINTF("%d.%d: runicast: ACKed %d\n", 00136 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], 00137 packetbuf_attr(PACKETBUF_ATTR_PACKET_ID)); 00138 c->sndnxt = (c->sndnxt + 1) % (1 << RUNICAST_PACKET_ID_BITS); 00139 c->is_tx = 0; 00140 stunicast_cancel(&c->c); 00141 if(c->u->sent != NULL) { 00142 c->u->sent(c, stunicast_receiver(&c->c), c->rxmit); 00143 } 00144 } else { 00145 PRINTF("%d.%d: runicast: received bad ACK %d for %d\n", 00146 rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1], 00147 packetbuf_attr(PACKETBUF_ATTR_PACKET_ID), 00148 c->sndnxt); 00149 RIMESTATS_ADD(badackrx); 00150 } 00151 } else if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) == 00152 PACKETBUF_ATTR_PACKET_TYPE_DATA) { 00153 /* int send_ack = 1;*/ 00154 uint16_t packet_seqno; 00155 struct queuebuf *q; 00156 00157 RIMESTATS_ADD(reliablerx); 00158 00159 PRINTF("%d.%d: runicast: got packet %d\n", 00160 rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1], 00161 packetbuf_attr(PACKETBUF_ATTR_PACKET_ID)); 00162 00163 packet_seqno = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID); 00164 00165 /* packetbuf_hdrreduce(sizeof(struct runicast_hdr));*/ 00166 00167 q = queuebuf_new_from_packetbuf(); 00168 if(q != NULL) { 00169 PRINTF("%d.%d: runicast: Sending ACK to %d.%d for %d\n", 00170 rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1], 00171 from->u8[0], from->u8[1], 00172 packet_seqno); 00173 packetbuf_clear(); 00174 /* packetbuf_hdralloc(sizeof(struct runicast_hdr)); 00175 hdr = packetbuf_hdrptr(); 00176 hdr->type = TYPE_ACK; 00177 hdr->seqno = packet_seqno;*/ 00178 packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE, PACKETBUF_ATTR_PACKET_TYPE_ACK); 00179 packetbuf_set_attr(PACKETBUF_ATTR_PACKET_ID, packet_seqno); 00180 stunicast_send(&c->c, from); 00181 RIMESTATS_ADD(acktx); 00182 00183 queuebuf_to_packetbuf(q); 00184 queuebuf_free(q); 00185 } else { 00186 PRINTF("%d.%d: runicast: could not send ACK to %d.%d for %d: no queued buffers\n", 00187 rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1], 00188 from->u8[0], from->u8[1], 00189 packet_seqno); 00190 } 00191 if(c->u->recv != NULL) { 00192 c->u->recv(c, from, packet_seqno); 00193 } 00194 } 00195 } 00196 /*---------------------------------------------------------------------------*/ 00197 static const struct stunicast_callbacks runicast = {recv_from_stunicast, 00198 sent_by_stunicast}; 00199 /*---------------------------------------------------------------------------*/ 00200 void 00201 runicast_open(struct runicast_conn *c, uint16_t channel, 00202 const struct runicast_callbacks *u) 00203 { 00204 stunicast_open(&c->c, channel, &runicast); 00205 channel_set_attributes(channel, attributes); 00206 c->u = u; 00207 c->is_tx = 0; 00208 c->rxmit = 0; 00209 c->sndnxt = 0; 00210 } 00211 /*---------------------------------------------------------------------------*/ 00212 void 00213 runicast_close(struct runicast_conn *c) 00214 { 00215 stunicast_close(&c->c); 00216 } 00217 /*---------------------------------------------------------------------------*/ 00218 uint8_t 00219 runicast_is_transmitting(struct runicast_conn *c) 00220 { 00221 return c->is_tx; 00222 } 00223 /*---------------------------------------------------------------------------*/ 00224 int 00225 runicast_send(struct runicast_conn *c, const rimeaddr_t *receiver, 00226 uint8_t max_retransmissions) 00227 { 00228 int ret; 00229 if(runicast_is_transmitting(c)) { 00230 PRINTF("%d.%d: runicast: already transmitting\n", 00231 rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1]); 00232 return 0; 00233 } 00234 packetbuf_set_attr(PACKETBUF_ATTR_RELIABLE, 1); 00235 packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE, PACKETBUF_ATTR_PACKET_TYPE_DATA); 00236 packetbuf_set_attr(PACKETBUF_ATTR_PACKET_ID, c->sndnxt); 00237 packetbuf_set_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS, 3); 00238 c->max_rxmit = max_retransmissions; 00239 c->rxmit = 0; 00240 c->is_tx = 1; 00241 RIMESTATS_ADD(reliabletx); 00242 PRINTF("%d.%d: runicast: sending packet %d\n", 00243 rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1], 00244 c->sndnxt); 00245 ret = stunicast_send_stubborn(&c->c, receiver, REXMIT_TIME); 00246 if(!ret) { 00247 c->is_tx = 0; 00248 } 00249 return ret; 00250 } 00251 /*---------------------------------------------------------------------------*/ 00252 /** @} */