Contiki 3.x
runicast.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2006, Swedish Institute of Computer Science.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  *
31  */
32 
33 /**
34  * \file
35  * Reliable unicast
36  * \author
37  * Adam Dunkels <adam@sics.se>
38  */
39 
40 /**
41  * \addtogroup rimerunicast
42  * @{
43  */
44 
45 #include "net/rime/runicast.h"
46 #include "net/rime/rime.h"
47 #include <string.h>
48 
49 
50 #ifdef RUNICAST_CONF_REXMIT_TIME
51 #define REXMIT_TIME RUNICAST_CONF_REXMIT_TIME
52 #else /* RUNICAST_CONF_REXMIT_TIME */
53 #define REXMIT_TIME CLOCK_SECOND
54 #endif /* RUNICAST_CONF_REXMIT_TIME */
55 
56 static const struct packetbuf_attrlist attributes[] =
57  {
58  RUNICAST_ATTRIBUTES
59  PACKETBUF_ATTR_LAST
60  };
61 
62 #define DEBUG 0
63 #if DEBUG
64 #include <stdio.h>
65 #define PRINTF(...) printf(__VA_ARGS__)
66 #else
67 #define PRINTF(...)
68 #endif
69 
70 /*---------------------------------------------------------------------------*/
71 static void
72 sent_by_stunicast(struct stunicast_conn *stunicast, int status, int num_tx)
73 {
74  struct runicast_conn *c = (struct runicast_conn *)stunicast;
75 
76  PRINTF("runicast: sent_by_stunicast c->rxmit %d num_tx %d\n",
77  c->rxmit, num_tx);
78 
79  /* Only process data packets, not ACKs. */
80  if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) == PACKETBUF_ATTR_PACKET_TYPE_DATA) {
81 
82  c->rxmit += 1;
83 
84  if(c->rxmit != 0) {
85  RIMESTATS_ADD(rexmit);
86  PRINTF("%d.%d: runicast: sent_by_stunicast packet %u (%u) resent %u\n",
88  packetbuf_attr(PACKETBUF_ATTR_PACKET_ID),
89  c->sndnxt, c->rxmit);
90  }
91  if(c->rxmit >= c->max_rxmit) {
92  RIMESTATS_ADD(timedout);
93  c->is_tx = 0;
94  stunicast_cancel(&c->c);
95  if(c->u->timedout) {
96  c->u->timedout(c, stunicast_receiver(&c->c), c->rxmit);
97  }
98  c->rxmit = 0;
99  PRINTF("%d.%d: runicast: packet %d timed out\n",
101  c->sndnxt);
102  c->sndnxt = (c->sndnxt + 1) % (1 << RUNICAST_PACKET_ID_BITS);
103  } else {
104 // int shift;
105 
106 // shift = c->rxmit > 4? 4: c->rxmit;
107 // stunicast_set_timer(&c->c, (REXMIT_TIME) << shift);
108  }
109  }
110 }
111 /*---------------------------------------------------------------------------*/
112 static void
113 recv_from_stunicast(struct stunicast_conn *stunicast, const linkaddr_t *from)
114 {
115  struct runicast_conn *c = (struct runicast_conn *)stunicast;
116  /* struct runicast_hdr *hdr = packetbuf_dataptr();*/
117 
118  PRINTF("%d.%d: runicast: recv_from_stunicast from %d.%d type %d seqno %d\n",
120  from->u8[0], from->u8[1],
121  packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE),
122  packetbuf_attr(PACKETBUF_ATTR_PACKET_ID));
123 
124  if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
125  PACKETBUF_ATTR_PACKET_TYPE_ACK) {
126  PRINTF("%d.%d: runicast: got ACK from %d.%d, seqno %d (%d)\n",
128  from->u8[0], from->u8[1],
129  packetbuf_attr(PACKETBUF_ATTR_PACKET_ID),
130  c->sndnxt);
131  if(packetbuf_attr(PACKETBUF_ATTR_PACKET_ID) == c->sndnxt) {
132  RIMESTATS_ADD(ackrx);
133  PRINTF("%d.%d: runicast: ACKed %d\n",
135  packetbuf_attr(PACKETBUF_ATTR_PACKET_ID));
136  c->sndnxt = (c->sndnxt + 1) % (1 << RUNICAST_PACKET_ID_BITS);
137  c->is_tx = 0;
138  stunicast_cancel(&c->c);
139  if(c->u->sent != NULL) {
140  c->u->sent(c, stunicast_receiver(&c->c), c->rxmit);
141  }
142  } else {
143  PRINTF("%d.%d: runicast: received bad ACK %d for %d\n",
145  packetbuf_attr(PACKETBUF_ATTR_PACKET_ID),
146  c->sndnxt);
147  RIMESTATS_ADD(badackrx);
148  }
149  } else if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
150  PACKETBUF_ATTR_PACKET_TYPE_DATA) {
151  /* int send_ack = 1;*/
152  uint16_t packet_seqno;
153  struct queuebuf *q;
154 
155  RIMESTATS_ADD(reliablerx);
156 
157  PRINTF("%d.%d: runicast: got packet %d\n",
159  packetbuf_attr(PACKETBUF_ATTR_PACKET_ID));
160 
161  packet_seqno = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID);
162 
163  /* packetbuf_hdrreduce(sizeof(struct runicast_hdr));*/
164 
165  q = queuebuf_new_from_packetbuf();
166  if(q != NULL) {
167  PRINTF("%d.%d: runicast: Sending ACK to %d.%d for %d\n",
169  from->u8[0], from->u8[1],
170  packet_seqno);
171  packetbuf_clear();
172  /* packetbuf_hdralloc(sizeof(struct runicast_hdr));
173  hdr = packetbuf_hdrptr();
174  hdr->type = TYPE_ACK;
175  hdr->seqno = packet_seqno;*/
176  packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE, PACKETBUF_ATTR_PACKET_TYPE_ACK);
177  packetbuf_set_attr(PACKETBUF_ATTR_PACKET_ID, packet_seqno);
178  stunicast_send(&c->c, from);
179  RIMESTATS_ADD(acktx);
180 
181  queuebuf_to_packetbuf(q);
182  queuebuf_free(q);
183  } else {
184  PRINTF("%d.%d: runicast: could not send ACK to %d.%d for %d: no queued buffers\n",
186  from->u8[0], from->u8[1],
187  packet_seqno);
188  }
189  if(c->u->recv != NULL) {
190  c->u->recv(c, from, packet_seqno);
191  }
192  }
193 }
194 /*---------------------------------------------------------------------------*/
195 static const struct stunicast_callbacks runicast = {recv_from_stunicast,
196  sent_by_stunicast};
197 /*---------------------------------------------------------------------------*/
198 void
199 runicast_open(struct runicast_conn *c, uint16_t channel,
200  const struct runicast_callbacks *u)
201 {
202  stunicast_open(&c->c, channel, &runicast);
203  channel_set_attributes(channel, attributes);
204  c->u = u;
205  c->is_tx = 0;
206  c->rxmit = 0;
207  c->sndnxt = 0;
208 }
209 /*---------------------------------------------------------------------------*/
210 void
211 runicast_close(struct runicast_conn *c)
212 {
213  stunicast_close(&c->c);
214 }
215 /*---------------------------------------------------------------------------*/
216 uint8_t
217 runicast_is_transmitting(struct runicast_conn *c)
218 {
219  return c->is_tx;
220 }
221 /*---------------------------------------------------------------------------*/
222 int
223 runicast_send(struct runicast_conn *c, const linkaddr_t *receiver,
224  uint8_t max_retransmissions)
225 {
226  int ret;
227  if(runicast_is_transmitting(c)) {
228  PRINTF("%d.%d: runicast: already transmitting\n",
230  return 0;
231  }
232  packetbuf_set_attr(PACKETBUF_ATTR_RELIABLE, 1);
233  packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE, PACKETBUF_ATTR_PACKET_TYPE_DATA);
234  packetbuf_set_attr(PACKETBUF_ATTR_PACKET_ID, c->sndnxt);
235  packetbuf_set_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS, 3);
236  c->max_rxmit = max_retransmissions;
237  c->rxmit = 0;
238  c->is_tx = 1;
239  RIMESTATS_ADD(reliabletx);
240  PRINTF("%d.%d: runicast: sending packet %d\n",
242  c->sndnxt);
243  ret = stunicast_send_stubborn(&c->c, receiver, REXMIT_TIME);
244  if(!ret) {
245  c->is_tx = 0;
246  }
247  return ret;
248 }
249 /*---------------------------------------------------------------------------*/
250 /** @} */
linkaddr_t linkaddr_node_addr
The Rime address of the node.
Definition: linkaddr.c:48
#define NULL
The null pointer.
Header file for the Rime stack
Reliable unicast header file
void packetbuf_clear(void)
Clear and reset the packetbuf.
Definition: packetbuf.c:77