00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
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
00055 #define REXMIT_TIME CLOCK_SECOND
00056 #endif
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
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
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
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
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
00174
00175
00176
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