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

📄 dymoenginem.nc

📁 tinyos-2.x.rar
💻 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. This the simultor version, without persistent
 * storage of the seqnum.
 *
 * @author Romain Thouvenin
 */

module DymoEngineM {
  provides {
    interface SplitControl;
  }
  uses {
    interface DymoTable;
    interface RoutingTable;
    interface DymoPacket;
    interface AMSend;
    interface AMPacket;
    interface Receive;
  }

#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


  task void startDoneTask() {
    signal SplitControl.startDone(SUCCESS);
  }

  command error_t SplitControl.start(){
    me.address = call AMPacket.address();
    me.seqnum = 1;
    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

    post startDoneTask();
    return SUCCESS;
  }

  void incr_seqnum(){
    if(me.seqnum == 65535)
      me.seqnum = 256;
    else
      me.seqnum++;
  }

  /* 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();
	  dbg("de", "DE: My seqnum for the RREP: %u.\n", me.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);
	      dbg("de", "DE: My seqnum for the RREP: %u.\n", me.seqnum);
	      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-%u-%hhu)\n", info->address, info->seqnum, info->hopcnt);
	  fw_address = 0;
	  return ACTION_DISCARD_MSG;
	} else {               //Additional info
	  dbg("de", "DE: I am discarding a bad piece of info (%u-%u-%hhu)\n", info->address, info->seqnum, info->hopcnt);
	  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 + -