Contiki 2.6
|
00001 /* 00002 * Copyright (c) 2007, Swedish Institute of Computer Science 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions 00007 * are met: 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the Institute nor the names of its contributors 00014 * may be used to endorse or promote products derived from this software 00015 * without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 00018 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 00021 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00022 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00023 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00024 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00025 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00026 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00027 * SUCH DAMAGE. 00028 * 00029 * This file is part of the Contiki operating system. 00030 * 00031 * @(#)$Id: radio-uip-uaodv.c,v 1.10 2010/10/19 18:29:05 adamdunkels Exp $ 00032 */ 00033 00034 #include "radio-uip-uaodv.h" 00035 #include "net/hc.h" 00036 #include "net/uip.h" 00037 #include "net/uaodv.h" 00038 #include "net/uaodv-rt.h" 00039 #include "net/uaodv-def.h" 00040 #include "lib/crc16.h" 00041 #include "list.h" 00042 #include <string.h> 00043 #include <stdio.h> 00044 00045 /* Packet buffer size and retransmission settings */ 00046 #define MAX_BUFFERED_PACKETS 10 00047 #define MAX_RETRANSMISSIONS_RREP 16 00048 #define MAX_RETRANSMISSIONS_UNICAST 16 00049 00050 /* Forward packet (header) */ 00051 #define FWD_ID "fWd:" 00052 #define FWD_ID_LENGTH 4 00053 #define FWD_NEXT_IP FWD_ID_LENGTH 00054 #define FWD_PACKET_LENGTH (FWD_NEXT_IP + 4) 00055 00056 /* Acknowledgement packet */ 00057 #define ACK_ID "aCk" 00058 #define ACK_ID_LENGTH 3 00059 #define ACK_CRC ACK_ID_LENGTH 00060 #define ACK_PACKET_LENGTH (ACK_ID_LENGTH + 2) 00061 #define ACK_TIMEOUT (CLOCK_SECOND / 50) * (random_rand() % 100) 00062 00063 enum { 00064 EVENT_SEND_ACK 00065 }; 00066 00067 struct buf_packet { 00068 struct buf_packet *next; 00069 uint8_t data[UIP_BUFSIZE]; 00070 int len; 00071 uint8_t resends; 00072 uint8_t acked; 00073 uint8_t want_ack; 00074 uint16_t crc; 00075 uip_ipaddr_t finaldest; 00076 struct etimer etimer; 00077 }; 00078 00079 LIST(buf_packet_list); 00080 MEMB(buf_packet_mem, struct buf_packet, MAX_BUFFERED_PACKETS); 00081 00082 PROCESS(radio_uip_process, "radio uIP uAODV process"); 00083 00084 static const struct radio_driver *radio; 00085 00086 00087 00088 /*---------------------------------------------------------------------------*/ 00089 static void receiver(const struct radio_driver *d); 00090 uint8_t radio_uip_uaodv_send(void); 00091 void radio_uip_uaodv_init(const struct radio_driver *d); 00092 int radio_uip_handle_ack(uint8_t *buf, int len); 00093 uint16_t radio_uip_calc_crc(uint8_t *buf, int len); 00094 int radio_uip_buffer_outgoing_packet(uint8_t *buf, int len, uip_ipaddr_t *dest, int max_sends); 00095 int radio_uip_is_ack(uint8_t *buf, int len); 00096 int radio_uip_uaodv_add_header(uint8_t *buf, int len, uip_ipaddr_t *addr); 00097 int radio_uip_uaodv_remove_header(uint8_t *buf, int len); 00098 void radio_uip_uaodv_change_header(uint8_t *buf, int len, uip_ipaddr_t *addr); 00099 int radio_uip_uaodv_header_exists(uint8_t *buf, int len); 00100 int radio_uip_uaodv_is_broadcast(uip_ipaddr_t *addr); 00101 int radio_uip_uaodv_fwd_is_broadcast(uint8_t *buf, int len); 00102 int radio_uip_uaodv_fwd_is_me(uint8_t *buf, int len); 00103 int radio_uip_uaodv_dest_is_me(uint8_t *buf, int len); 00104 int radio_uip_uaodv_dest_port(uint8_t *buf, int len); 00105 /*---------------------------------------------------------------------------*/ 00106 00107 /* Main process - handles (re)transmissions and acks */ 00108 PROCESS_THREAD(radio_uip_process, ev, data) 00109 { 00110 struct buf_packet *packet; 00111 00112 PROCESS_BEGIN(); 00113 00114 while(1) { 00115 PROCESS_YIELD(); 00116 00117 if(ev == EVENT_SEND_ACK) { 00118 00119 /* Prepare and send ack for given 16-bit CRC */ 00120 uint8_t ackPacket[ACK_PACKET_LENGTH]; 00121 memcpy(ackPacket, ACK_ID, ACK_ID_LENGTH); 00122 ackPacket[ACK_CRC] = ((uint16_t) data >> 8); 00123 ackPacket[ACK_CRC+1] = ((uint16_t) data & 0xff); 00124 radio->send(ackPacket, ACK_PACKET_LENGTH); 00125 00126 } else if(ev == PROCESS_EVENT_TIMER) { 00127 /* Locate which packet acknowledgement timed out */ 00128 for(packet = list_head(buf_packet_list); 00129 packet != NULL; 00130 packet = packet->next) { 00131 if (etimer_expired(&packet->etimer)) { 00132 00133 if (packet->acked) { 00134 /* Already acked packet, remove silently */ 00135 list_remove(buf_packet_list, packet); 00136 memb_free(&buf_packet_mem, packet); 00137 00138 } else if (packet->resends > 0) { 00139 /* Resend packet */ 00140 packet->resends--; 00141 etimer_set(&packet->etimer, ACK_TIMEOUT); 00142 00143 radio->send(packet->data, packet->len); 00144 00145 } else { 00146 /* Packet was resent maximum number of times */ 00147 00148 /* If an ack was expected, flag destination to bad */ 00149 if (packet->want_ack && !uip_ipaddr_cmp(&packet->finaldest, &uip_broadcast_addr)) { 00150 uaodv_bad_dest(&packet->finaldest); 00151 } 00152 00153 list_remove(buf_packet_list, packet); 00154 memb_free(&buf_packet_mem, packet); 00155 } 00156 } 00157 } 00158 } 00159 } 00160 PROCESS_END(); 00161 } 00162 /*---------------------------------------------------------------------------*/ 00163 static void 00164 receiver(const struct radio_driver *d) 00165 { 00166 uip_len = d->read(&uip_buf[UIP_LLH_LEN], UIP_BUFSIZE - UIP_LLH_LEN); 00167 if (uip_len <= 0) { 00168 return; 00169 } 00170 00171 /* Detect and handle acknowledgements */ 00172 if (radio_uip_is_ack(&uip_buf[UIP_LLH_LEN], uip_len)) { 00173 radio_uip_handle_ack(&uip_buf[UIP_LLH_LEN], uip_len); 00174 return; 00175 } 00176 00177 /* If no uAODV header, receive as usual */ 00178 if (!radio_uip_uaodv_header_exists(&uip_buf[UIP_LLH_LEN], uip_len)) { 00179 tcpip_input(); 00180 return; 00181 } 00182 00183 /* Drop packet unless we are the uAODV forwarder */ 00184 if (!radio_uip_uaodv_fwd_is_me(&uip_buf[UIP_LLH_LEN], uip_len)) { 00185 return; 00186 } 00187 00188 { 00189 /* Send ack as soon as possible */ 00190 uint16_t crc; 00191 crc = radio_uip_calc_crc(&uip_buf[UIP_LLH_LEN], uip_len); 00192 process_post(&radio_uip_process, EVENT_SEND_ACK, (void*) (uint32_t) crc); 00193 } 00194 00195 /* Strip header and receive packet */ 00196 uip_len = radio_uip_uaodv_remove_header(&uip_buf[UIP_LLH_LEN], uip_len); 00197 tcpip_input(); 00198 } 00199 /*---------------------------------------------------------------------------*/ 00200 uint8_t 00201 radio_uip_uaodv_send(void) 00202 { 00203 struct uaodv_rt_entry *route; 00204 00205 /* Transmit broadcast packets without header */ 00206 if (radio_uip_uaodv_is_broadcast(&((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])->destipaddr)) { 00207 return radio_uip_buffer_outgoing_packet(&uip_buf[UIP_LLH_LEN], uip_len, (void*) &uip_broadcast_addr, 1); 00208 } 00209 00210 /* Transmit uAODV packets with headers but without using route table */ 00211 if (((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])->proto == UIP_PROTO_UDP 00212 && radio_uip_uaodv_dest_port(&uip_buf[UIP_LLH_LEN], uip_len) == UIP_HTONS(UAODV_UDPPORT)) { 00213 uip_ipaddr_t nexthop; 00214 memcpy(&nexthop, &((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])->destipaddr, 4); 00215 00216 uip_len = radio_uip_uaodv_add_header( 00217 &uip_buf[UIP_LLH_LEN], 00218 uip_len, 00219 &nexthop 00220 ); 00221 00222 /* Buffer packet for persistent transmission */ 00223 return radio_uip_buffer_outgoing_packet( 00224 &uip_buf[UIP_LLH_LEN], 00225 uip_len, 00226 &((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN + FWD_PACKET_LENGTH])->destipaddr, 00227 MAX_RETRANSMISSIONS_RREP); 00228 } 00229 00230 /* Fetch already prepared uAODV route */ 00231 route = uaodv_rt_lookup_any((&((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])->destipaddr)); 00232 if (route == NULL || route->is_bad) { 00233 00234 /* If we are forwarding, notify origin of this bad route */ 00235 if (tcpip_is_forwarding) { 00236 uaodv_bad_dest((&((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])->destipaddr)); 00237 } 00238 00239 return UIP_FW_DROPPED; 00240 } 00241 00242 /* Add header and buffer packet for persistent transmission */ 00243 uip_len = radio_uip_uaodv_add_header(&uip_buf[UIP_LLH_LEN], uip_len, &route->nexthop); /* TODO Correct? */ 00244 return radio_uip_buffer_outgoing_packet( 00245 &uip_buf[UIP_LLH_LEN], 00246 uip_len, 00247 &route->dest, 00248 MAX_RETRANSMISSIONS_UNICAST); 00249 } 00250 /*---------------------------------------------------------------------------*/ 00251 void 00252 radio_uip_uaodv_init(const struct radio_driver *d) 00253 { 00254 /* Prepare buffers and start main process */ 00255 memb_init(&buf_packet_mem); 00256 list_init(buf_packet_list); 00257 process_start(&radio_uip_process, NULL); 00258 00259 radio = d; 00260 radio->set_receive_function(receiver); 00261 radio->on(); 00262 } 00263 /*---------------------------------------------------------------------------*/ 00264 uint16_t 00265 radio_uip_calc_crc(uint8_t *buf, int len) 00266 { 00267 uint16_t crcacc = 0xffff; 00268 int counter; 00269 00270 /* TODO Not effective */ 00271 for (counter = 0; counter < len; counter++) { 00272 crcacc = crc16_add(buf[counter], crcacc); 00273 } 00274 return crcacc; 00275 } 00276 /*---------------------------------------------------------------------------*/ 00277 int 00278 radio_uip_buffer_outgoing_packet(uint8_t *buf, int len, uip_ipaddr_t *dest, int max_sends) 00279 { 00280 struct buf_packet *packet; 00281 00282 uint16_t crc; 00283 00284 /* Calculate packet's unique CRC */ 00285 crc = radio_uip_calc_crc(&uip_buf[UIP_LLH_LEN], uip_len); 00286 00287 /* Check if this packet is already being transmitted */ 00288 for(packet = list_head(buf_packet_list); 00289 packet != NULL; 00290 packet = packet->next) { 00291 if (packet->crc == crc) { 00292 return UIP_FW_DROPPED; 00293 } 00294 } 00295 00296 /* Allocate storage memory */ 00297 packet = (struct buf_packet *)memb_alloc(&buf_packet_mem); 00298 if (packet == NULL) { 00299 return UIP_FW_DROPPED; 00300 } 00301 00302 /* Prepare packet buffer */ 00303 memcpy(packet->data, buf, len); 00304 packet->len = len; 00305 packet->resends = max_sends; 00306 packet->acked = 0; 00307 if (packet->resends > 1) 00308 packet->want_ack = 1; 00309 else 00310 packet->want_ack = 0; 00311 memcpy(&packet->finaldest, dest, 4); 00312 packet->crc = crc; 00313 00314 /* Set first transmission to as soon as possible */ 00315 PROCESS_CONTEXT_BEGIN(&radio_uip_process); 00316 etimer_set(&packet->etimer, 0); 00317 PROCESS_CONTEXT_END(&radio_uip_process); 00318 00319 /* Add to buffered packets list */ 00320 list_add(buf_packet_list, packet); 00321 00322 return UIP_FW_OK; 00323 } 00324 /*---------------------------------------------------------------------------*/ 00325 int 00326 radio_uip_is_ack(uint8_t *buf, int len) 00327 { 00328 if (len != ACK_PACKET_LENGTH) 00329 return 0; 00330 00331 return memcmp(buf, ACK_ID, ACK_ID_LENGTH) == 0; 00332 00333 } 00334 /*---------------------------------------------------------------------------*/ 00335 int 00336 radio_uip_handle_ack(uint8_t *buf, int len) 00337 { 00338 struct buf_packet *packet; 00339 uint16_t ackCRC; 00340 00341 ackCRC = (uint16_t) (buf[ACK_CRC] << 8) + (uint16_t) (0xff&buf[ACK_CRC+1]); 00342 00343 /* Locate which packet was acknowledged */ 00344 for(packet = list_head(buf_packet_list); 00345 packet != NULL; 00346 packet = packet->next) { 00347 if (packet->crc == ackCRC) { 00348 /* Signal packet has been acknowledged */ 00349 packet->acked = 1; 00350 return 0; 00351 } 00352 } 00353 00354 return 1; 00355 } 00356 /*---------------------------------------------------------------------------*/ 00357 int 00358 radio_uip_uaodv_add_header(uint8_t *buf, int len, uip_ipaddr_t *addr) 00359 { 00360 uint8_t tempbuf[len]; 00361 memcpy(tempbuf, buf, len); 00362 memcpy(&buf[FWD_PACKET_LENGTH], tempbuf, len); 00363 memcpy(buf, FWD_ID, FWD_ID_LENGTH); 00364 memcpy(&buf[FWD_NEXT_IP], (char*)addr, 4); 00365 return FWD_PACKET_LENGTH + len; 00366 } 00367 /*---------------------------------------------------------------------------*/ 00368 int 00369 radio_uip_uaodv_remove_header(uint8_t *buf, int len) 00370 { 00371 uint8_t tempbuf[len]; 00372 memcpy(tempbuf, &buf[FWD_PACKET_LENGTH], len); 00373 memcpy(buf, tempbuf, len); 00374 return len - FWD_PACKET_LENGTH; 00375 } 00376 /*---------------------------------------------------------------------------*/ 00377 void 00378 radio_uip_uaodv_change_header(uint8_t *buf, int len, uip_ipaddr_t *addr) 00379 { 00380 memcpy(&buf[FWD_NEXT_IP], addr, 4); 00381 } 00382 /*---------------------------------------------------------------------------*/ 00383 int 00384 radio_uip_uaodv_header_exists(uint8_t *buf, int len) 00385 { 00386 return !memcmp(buf, FWD_ID, FWD_ID_LENGTH); 00387 } 00388 /*---------------------------------------------------------------------------*/ 00389 int 00390 radio_uip_uaodv_is_broadcast(uip_ipaddr_t *addr) 00391 { 00392 return uip_ipaddr_cmp(addr, &uip_broadcast_addr); 00393 } 00394 /*---------------------------------------------------------------------------*/ 00395 int 00396 radio_uip_uaodv_fwd_is_broadcast(uint8_t *buf, int len) 00397 { 00398 return radio_uip_uaodv_is_broadcast((uip_ipaddr_t*) &buf[FWD_NEXT_IP]); 00399 } 00400 /*---------------------------------------------------------------------------*/ 00401 int 00402 radio_uip_uaodv_fwd_is_me(uint8_t *buf, int len) 00403 { 00404 return !memcmp(&buf[FWD_NEXT_IP], &uip_hostaddr, 4); 00405 } 00406 /*---------------------------------------------------------------------------*/ 00407 int 00408 radio_uip_uaodv_dest_is_me(uint8_t *buf, int len) 00409 { 00410 return !memcmp((&((struct uip_udpip_hdr *)buf)->destipaddr), &uip_hostaddr, 4); 00411 } 00412 /*---------------------------------------------------------------------------*/ 00413 int 00414 radio_uip_uaodv_dest_port(uint8_t *buf, int len) 00415 { 00416 if (len < sizeof(struct uip_udpip_hdr)) 00417 return -1; 00418 return (int) ((struct uip_udpip_hdr *)buf)->destport; 00419 } 00420 /*---------------------------------------------------------------------------*/