📄 dymoenginem.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 + -