⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dymoenginem.nc

📁 tinyos2.0版本驱动
💻 NC
字号:
/* * Copyright (c) 2007 Romain Thouvenin <romain.thouvenin@gmail.com> * Published under the terms of the GNU General Public License (GPLv2). */#include "routing.h"#include "routing_table.h"/** * DymoEngineM - Implements the algorithms to generate and process * DYMO messages. * * @author Romain Thouvenin */module DymoEngineM {  provides {    interface SplitControl;  }  uses {    interface DymoTable;    interface RoutingTable;    interface DymoPacket;    interface AMSend;    interface AMPacket;    interface Receive;        interface Mount;    interface ConfigStorage;  }#ifdef DYMO_MONITORING  provides interface DymoMonitor;  uses {    interface Timer<TMilli>;  }#endif}implementation {  message_t * avail_msg; //to be returned by receive  message_t buf_avail;   //first avail_msg  message_t buf_packet;  rt_info_t me;  rt_info_t buf_info;  addr_t ignoreNeeded;  bool busySend;  /* for processing */  bool busyProcess, busyIssue;  uint8_t cur_hopcnt;  uint8_t cur_info_pos;  rt_info_t buf_target;  addr_t fw_address; //set to 0 if the message must not be forwarded  message_t fw_msg;  bool sendRREP;#ifdef DYMO_MONITORING  uint32_t rreq_time;#endif  command error_t SplitControl.start(){    me.address = call AMPacket.address();    me.has_hopcnt = 1;    me.hopcnt = 0;    avail_msg = &buf_avail;    ignoreNeeded = 0;    sendRREP = FALSE;    busyProcess = FALSE;    busyIssue = FALSE;    busySend = FALSE;    buf_target.address = 0;    #ifdef DYMO_MONITORING    rreq_time = 0;#endif    return call Mount.mount();  }  void incr_seqnum(){    if(me.seqnum == 65535)      me.seqnum = 256;    else      me.seqnum++;    call ConfigStorage.write(0x0, &me.seqnum, sizeof(me.seqnum));  }  event void ConfigStorage.writeDone(storage_addr_t addr, void *buf,     storage_len_t len, error_t err) {    // Verify addr and len    if (err == SUCCESS) {      if (call ConfigStorage.commit() != SUCCESS) {        // Handle failure      }    }    else {      // Handle failure    }  }  event void Mount.mountDone(error_t error) {    if (error == SUCCESS) {      if (call ConfigStorage.valid() == TRUE) {        if (call ConfigStorage.read(0x0, &me.seqnum, sizeof(me.seqnum)) != SUCCESS) {          me.seqnum = 1;	  signal SplitControl.startDone(SUCCESS);	}      }      else {	// Invalid volume.  Commit to make valid.	if (call ConfigStorage.commit() == SUCCESS) {	  me.seqnum = 1;	}	else {	  signal SplitControl.startDone(FAIL);	}      }    }    else{      signal SplitControl.startDone(error);    }  }  event void ConfigStorage.commitDone(error_t err) {    if ((err != SUCCESS) && (me.seqnum == 1)) {      signal SplitControl.startDone(err);    } else if (me.seqnum == 1) {      signal SplitControl.startDone(SUCCESS);    }  }  event void ConfigStorage.readDone(storage_addr_t addr, void* buf,     storage_len_t len, error_t err) __attribute__((noinline)) {    if (err == SUCCESS) {      me.seqnum = *(seqnum_t *)buf;      signal SplitControl.startDone(SUCCESS);    } else {      signal SplitControl.startDone(err);    }  }  /* Send a RREQ for buf_info */  task void issueRREQ(){    atomic {      if(busySend)	post issueRREQ();      else {	busySend = TRUE;	incr_seqnum();	call DymoPacket.createRM(&buf_packet, DYMO_RREQ, &me, &buf_info);	call AMSend.send(AM_BROADCAST_ADDR, &buf_packet, call DymoPacket.getSize(&buf_packet));      }    }  }  /* Send a RREP to buf_info */  task void issueRREP(){    atomic {      if(busySend)	post issueRREP();      else {	busySend = TRUE;	call DymoPacket.createRM(&buf_packet, DYMO_RREP, &me, &buf_info);	if(buf_target.address)	  call DymoPacket.addInfo(&buf_packet, &buf_target);	call AMSend.send(buf_info.nexthop, &buf_packet, call DymoPacket.getSize(&buf_packet));	buf_target.address = 0;      }    }  }  /* Send a RERR with buf_info as unreachable */  task void issueRERR(){    atomic {      if(busySend)	post issueRERR();      else {	busySend = TRUE;	call DymoPacket.createRM(&buf_packet, DYMO_RERR, NULL, &buf_info);	call AMSend.send(AM_BROADCAST_ADDR, &buf_packet, call DymoPacket.getSize(&buf_packet));      }    }  }  /* Send current fw_msg to fw_address */  task void forward(){    atomic {      if(busySend)	post forward();      else {	busySend = TRUE;	call AMSend.send(fw_address, &fw_msg, call DymoPacket.getSize(&fw_msg));      }    }  }  event message_t* Receive.receive(message_t* msg, void* payload, uint8_t len){#ifdef DYMO_MONITORING    signal DymoMonitor.msgReceived(msg);#endif    dbg("de", "DE: Message (type %hhu) received.\n", call DymoPacket.getType(msg));    atomic {      if(busyProcess){	dbg("de", "DE: I'm busy, I can't handle this message, sorry.\n");	return msg; //we discard msg if a message is already being processed      } else {	busyProcess = TRUE;      }    }    cur_info_pos = 0;    fw_address = AM_BROADCAST_ADDR;    call DymoPacket.startProcessing(msg, &fw_msg);    return avail_msg;  }  event proc_action_t DymoPacket.hopsProcessed(message_t * msg, uint8_t hop_limit, uint8_t hop_count){    cur_hopcnt = hop_count; //TODO use this    if(hop_limit == 0){      fw_address = 0;      dbg("de", "DE: This message has reached its HL (%hhu hops) => discard.\n", hop_count);      return ACTION_DISCARD_MSG;    } else {      return ACTION_KEEP;    }  }  proc_action_t process_rm_info(message_t * msg, rt_info_t * info){    cur_info_pos++;    if(cur_info_pos == 1){ //target      if(info->address == me.address){	if(call DymoPacket.getType(msg) == DYMO_RREQ){	  dbg("de", "DE: This RREQ is for me => RREP.\n");	  if(info->seqnum < me.seqnum)	    incr_seqnum();	  sendRREP = TRUE; //to send a RREP when we receive the next event (= originator info)	} else {	  dbg("de", "DE: This RREP is for me, cool!\n");	}	fw_address = 0;	return ACTION_DISCARD_MSG;      } else { //not for me	info->nexthop = call AMPacket.source(msg);	if(call DymoPacket.getType(msg) == DYMO_RREQ){#if DYMO_INTER_RREP	  //if we know a route to the target, we send a intermediate RREP and don't forward the message	  ignoreNeeded = info->address;	  if (call RoutingTable.getRoute(info->address, &buf_info) == SUCCESS) {#if DYMO_FORCE_INTER_RREP	    if( !info->seqnum || !(call DymoTable.isSuperior(info, DYMO_RREQ)) ){#else	    if( info->seqnum && !(call DymoTable.isSuperior(info, DYMO_RREQ)) ){#endif	      dbg("de", "DE: This RREQ is for %u, but I know the route => RREP.\n", info->address);	      buf_target = buf_info;	      sendRREP = TRUE;	      fw_address = 0;	      return ACTION_DISCARD_MSG;	    }	  }#endif	  return ACTION_KEEP;	} else { //RREP	  ignoreNeeded = info->address;	  dbg("de", "DE: This RREP is for %u.\n", info->address);	  if(call RoutingTable.getForwardingRoute(info->address, &buf_info) == SUCCESS){	    fw_address = buf_info.nexthop;	    return ACTION_KEEP;	  } else {	    fw_address = 0;	    return ACTION_DISCARD_MSG;	  }	}//end RREP      }//end not for me    } else if((call DymoPacket.getType(msg) == DYMO_RREQ) //end if(info==target)	      && (cur_info_pos == 2)	      && (info->address == me.address)){      fw_address = 0;      sendRREP = FALSE;      return ACTION_DISCARD_MSG;    } else {      info->nexthop = call AMPacket.source(msg);      if(call DymoTable.update(info, call DymoPacket.getType(msg)) == EINVAL){	if(cur_info_pos == 2){ //origin	  dbg("de", "DE: I am discarding a msg with a bad origin (%u)\n", info->address);	  fw_address = 0;	  return ACTION_DISCARD_MSG;	} else {               //Additional info	  return ACTION_DISCARD;	}      } else {	if((cur_info_pos == 2) && sendRREP){	  buf_info = *info;	  atomic {	    if(!busyIssue){	      busyIssue = 1;	      post issueRREP();	    }	  }	  sendRREP = 0;	}#ifdef DYMO_MONITORING 	if( rreq_time    //TODO probably misses a test	    && (cur_info_pos == 2)	    && (call DymoPacket.getType(msg) == DYMO_RREP) ) {	  rreq_time = (call Timer.getNow()) - rreq_time;	  signal DymoMonitor.routeDiscovered(rreq_time, info->address);	  rreq_time = 0;	}#endif	return ACTION_KEEP;      }    } //end info!=target  }//end event  proc_action_t process_err_info(message_t * msg, rt_info_t * info){    info->nexthop = call AMPacket.source(msg);    if(call DymoTable.update(info, call DymoPacket.getType(msg)) == EINVAL){      return ACTION_DISCARD;           } else {      cur_info_pos++; //we only count kept pieces of info      return ACTION_KEEP;    }  }  event proc_action_t DymoPacket.infoProcessed(message_t * msg, rt_info_t * info){    if(call DymoPacket.getType(msg) == DYMO_RERR)      return process_err_info(msg, info);    else      return process_rm_info(msg, info);  }  event void DymoPacket.messageProcessed(message_t * msg){    avail_msg = msg;    if( (call DymoPacket.getType(msg) == DYMO_RERR) && cur_info_pos ){      post forward();    } else if( (call DymoPacket.getType(msg) != DYMO_RERR) && fw_address ){#if DYMO_APPEND_INFO      call DymoPacket.addInfo(&fw_msg, me);#endif      dbg("de", "DE: I'll forward this RM.\n");      post forward();    } else {      atomic {	busyProcess = 0;      }      dbg("de", "DE: I'm not busy anymore.\n");    }    dbg("de", "DE: Message (type %hhu) successfully processed.\n", call DymoPacket.getType(msg));  }  event void DymoTable.routeNeeded(addr_t destination){    if(ignoreNeeded == destination){      ignoreNeeded = 0;    } else {      buf_info.address = destination;      buf_info.seqnum = 0;      buf_info.has_hopcnt = FALSE;      atomic {	if(!busyIssue){	  busyIssue = TRUE;#ifdef DYMO_MONITORING	  rreq_time = call Timer.getNow();#endif	  post issueRREQ();	}      }    }  }    event void DymoTable.brokenRouteNeeded(const rt_info_t * route_info){    buf_info = *route_info;    buf_info.has_hopcnt = FALSE;    atomic {      if(!busyIssue){	busyIssue = TRUE;	post issueRERR();      }    }  }  event void RoutingTable.evicted(const rt_info_t * route_info, reason_t r){    if(r == REASON_UNREACHABLE){      buf_info = *route_info;      buf_info.has_hopcnt = FALSE;      atomic {	if(!busyIssue){	  busyIssue = TRUE;	  post issueRERR();	}      }    }  }  event void AMSend.sendDone(message_t *msg, error_t error){    atomic {      busySend = FALSE;    }    if(msg == &fw_msg){      atomic{	busyProcess = FALSE;      }    } else if(msg == &buf_packet) {      atomic {	busyIssue = FALSE;      }    }    if(error == SUCCESS){      if(msg == &fw_msg)	dbg("de", "DE: Message (type %hhu) forwarded.\n", call DymoPacket.getType(msg));      else	dbg("de", "DE: Message (type %hhu) sent.\n", call DymoPacket.getType(msg));    } else      dbg("de", "DE: Failed to send message (type %hhu).\n", call DymoPacket.getType(msg));#ifdef DYMO_MONITORING    if(error == SUCCESS)      signal DymoMonitor.msgSent(msg);#endif  }  command error_t SplitControl.stop(){ }#ifdef DYMO_MONITORING  event void Timer.fired(){} default event void DymoMonitor.msgReceived(message_t * msg){} default event void DymoMonitor.msgSent(message_t * msg){} default event void DymoMonitor.routeDiscovered(uint32_t delay, addr_t target){}#endif}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -