runicast.c

Go to the documentation of this file.
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     } else {
00105       int shift;
00106       
00107       shift = c->rxmit > 4? 4: c->rxmit;
00108       stunicast_set_timer(&c->c, (REXMIT_TIME) << shift);
00109     }
00110   }
00111 }
00112 /*---------------------------------------------------------------------------*/
00113 static void
00114 recv_from_stunicast(struct stunicast_conn *stunicast, const rimeaddr_t *from)
00115 {
00116   struct runicast_conn *c = (struct runicast_conn *)stunicast;
00117   /*  struct runicast_hdr *hdr = packetbuf_dataptr();*/
00118 
00119   PRINTF("%d.%d: runicast: recv_from_stunicast from %d.%d type %d seqno %d\n",
00120          rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1],
00121          from->u8[0], from->u8[1],
00122          packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE),
00123          packetbuf_attr(PACKETBUF_ATTR_PACKET_ID));
00124 
00125   if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
00126      PACKETBUF_ATTR_PACKET_TYPE_ACK) {
00127       PRINTF("%d.%d: runicast: got ACK from %d.%d, seqno %d (%d)\n",
00128              rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
00129              from->u8[0], from->u8[1],
00130              packetbuf_attr(PACKETBUF_ATTR_PACKET_ID),
00131              c->sndnxt);
00132     if(packetbuf_attr(PACKETBUF_ATTR_PACKET_ID) == c->sndnxt) {
00133       RIMESTATS_ADD(ackrx);
00134       PRINTF("%d.%d: runicast: ACKed %d\n",
00135              rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
00136              packetbuf_attr(PACKETBUF_ATTR_PACKET_ID));
00137       c->sndnxt = (c->sndnxt + 1) % (1 << RUNICAST_PACKET_ID_BITS);
00138       c->is_tx = 0;
00139       stunicast_cancel(&c->c);
00140       if(c->u->sent != NULL) {
00141         c->u->sent(c, stunicast_receiver(&c->c), c->rxmit);
00142       }
00143     } else {
00144       PRINTF("%d.%d: runicast: received bad ACK %d for %d\n",
00145              rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1],
00146              packetbuf_attr(PACKETBUF_ATTR_PACKET_ID),
00147              c->sndnxt);
00148       RIMESTATS_ADD(badackrx);
00149     }
00150   } else if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
00151             PACKETBUF_ATTR_PACKET_TYPE_DATA) {
00152     /*    int send_ack = 1;*/
00153     uint16_t packet_seqno;
00154     struct queuebuf *q;
00155 
00156     RIMESTATS_ADD(reliablerx);
00157 
00158     PRINTF("%d.%d: runicast: got packet %d\n",
00159            rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1],
00160            packetbuf_attr(PACKETBUF_ATTR_PACKET_ID));
00161 
00162     packet_seqno = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID);
00163 
00164     /*    packetbuf_hdrreduce(sizeof(struct runicast_hdr));*/
00165 
00166     q = queuebuf_new_from_packetbuf();
00167     if(q != NULL) {
00168       PRINTF("%d.%d: runicast: Sending ACK to %d.%d for %d\n",
00169              rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1],
00170              from->u8[0], from->u8[1],
00171              packet_seqno);
00172       packetbuf_clear();
00173       /*    packetbuf_hdralloc(sizeof(struct runicast_hdr));
00174             hdr = packetbuf_hdrptr();
00175             hdr->type = TYPE_ACK;
00176             hdr->seqno = packet_seqno;*/
00177       packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE, PACKETBUF_ATTR_PACKET_TYPE_ACK);
00178       packetbuf_set_attr(PACKETBUF_ATTR_PACKET_ID, packet_seqno);
00179       stunicast_send(&c->c, from);
00180       RIMESTATS_ADD(acktx);
00181 
00182       queuebuf_to_packetbuf(q);
00183       queuebuf_free(q);
00184     } else {
00185       PRINTF("%d.%d: runicast: could not send ACK to %d.%d for %d: no queued buffers\n",
00186              rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1],
00187              from->u8[0], from->u8[1],
00188              packet_seqno);
00189     }
00190     if(c->u->recv != NULL) {
00191       c->u->recv(c, from, packet_seqno);
00192     }
00193   }
00194 }
00195 /*---------------------------------------------------------------------------*/
00196 static const struct stunicast_callbacks runicast = {recv_from_stunicast,
00197                                                     sent_by_stunicast};
00198 /*---------------------------------------------------------------------------*/
00199 void
00200 runicast_open(struct runicast_conn *c, uint16_t channel,
00201           const struct runicast_callbacks *u)
00202 {
00203   stunicast_open(&c->c, channel, &runicast);
00204   channel_set_attributes(channel, attributes);
00205   c->u = u;
00206   c->is_tx = 0;
00207   c->rxmit = 0;
00208   c->sndnxt = 0;
00209 }
00210 /*---------------------------------------------------------------------------*/
00211 void
00212 runicast_close(struct runicast_conn *c)
00213 {
00214   stunicast_close(&c->c);
00215 }
00216 /*---------------------------------------------------------------------------*/
00217 uint8_t
00218 runicast_is_transmitting(struct runicast_conn *c)
00219 {
00220   return c->is_tx;
00221 }
00222 /*---------------------------------------------------------------------------*/
00223 int
00224 runicast_send(struct runicast_conn *c, const rimeaddr_t *receiver,
00225               uint8_t max_retransmissions)
00226 {
00227   int ret;
00228   if(runicast_is_transmitting(c)) {
00229     PRINTF("%d.%d: runicast: already transmitting\n",
00230         rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1]);
00231     return 0;
00232   }
00233   packetbuf_set_attr(PACKETBUF_ATTR_RELIABLE, 1);
00234   packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE, PACKETBUF_ATTR_PACKET_TYPE_DATA);
00235   packetbuf_set_attr(PACKETBUF_ATTR_PACKET_ID, c->sndnxt);
00236   packetbuf_set_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS, 3);
00237   c->max_rxmit = max_retransmissions;
00238   c->rxmit = 0;
00239   c->is_tx = 1;
00240   RIMESTATS_ADD(reliabletx);
00241   PRINTF("%d.%d: runicast: sending packet %d\n",
00242          rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1],
00243          c->sndnxt);
00244   ret = stunicast_send_stubborn(&c->c, receiver, REXMIT_TIME);
00245   if(!ret) {
00246     c->is_tx = 0;
00247   }
00248   return ret;
00249 }
00250 /*---------------------------------------------------------------------------*/
00251 /** @} */

Generated on Mon Apr 11 14:23:31 2011 for Contiki 2.5 by  doxygen 1.6.1