?? router.cc
字號:
// -*- C++ -*-
// Copyright (C) 2003 Leherstuh f黵 Betrieb System/ Verteilte System,
// Universitaet Dortmund
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
// Author: Muddassar Farooq
// Informatik III, Universitaet Dortmund
// Germany
//-------------------------------------------------------------
// file: router.cpp
// (part of AntNet Routing Simulation)
//-------------------------------------------------------------
#include "router.h"
Define_Module( Router );
Router::Router(const char *name, cModule *parentmodule,unsigned stacksize)
:cSimpleModule(name, parentmodule, stacksize)
{
qBuffer = new map<int, Buffer*>();
neighborPortID = new map<int,pair<int,int>*>();
msgServiced = new map<int,cMessage*>();
sendControlOrDataPacket = new map<int,cMessage*>();
bandWidthPdelay = new map<int,pair<double,double>*>();
IPAddress = -1;
contextSwitchTime = 0;
numNeighbors = 0;
}
Router::~Router()
{
map<int,pair<int,int>*>::const_iterator P;
for( P = (*neighborPortID).begin(); P != (*neighborPortID).end(); P++)
{
delete (*P).second;
}
delete neighborPortID;
map<int,Buffer*>::const_iterator I;
for( I = (*qBuffer).begin(); I != (*qBuffer).end(); I++)
{
delete (*I).second;
}
delete qBuffer;
delete msgServiced;
delete sendControlOrDataPacket;
map<int,pair<double,double>*>::const_iterator N;
for( N = (*bandWidthPdelay).begin(); N != (*bandWidthPdelay).end(); N++)
{
delete (*N).second;
}
delete bandWidthPdelay;
delete rTable;
delete neighborAtIndex;
}
void Router::initialize()
{
dataRate = par("dataRate");
IPAddress = par("address");
queueSize= static_cast<int> ( par("queueSize") );
numNodes = par("numStations");
startTime = static_cast<double> ( par("startTime") );
endTime = static_cast<double> ( par("endTime") );
qWeightFactor = static_cast<double> ( par("qWeightFactor") );
debug = false;
logResults = par("logResults");
const char *statModulePath = par("statModulePath");
cModule *tmp1 = simulation.moduleByPath(statModulePath);
sPtr= check_and_cast<statistics *> (tmp1);
converganceTime = (double) par("converganceTime");
probabilisticRouting = par("probabilisticRouting");
fsm.setName("fsm");
dataPacketLength = static_cast<int> (gate("fromDataGen")->fromGate()->ownerModule()->par("messageLength"));
resendAttempts = static_cast<int> ( par("resendAttempts") );
agentProcTime = static_cast<bool> (par("agentProcTime"));
contextSwitchTime = static_cast<double>(par("contextSwitchTime"));
numNeighbors = 0;
routerDown = false;
tcb.state = INIT_S;
buildGateIDToNeighborMap();
//allocate buffers for each neighbor
map<int,pair<int,int>*>::const_iterator I;
numNeighbors = (*neighborPortID).size();
neighborAtIndex = new int[numNeighbors];
int i = 0;
for( I = (*neighborPortID).begin(); I != (*neighborPortID).end(); I++)
{
int port = (*I).first;
neighborAtIndex[i] = (*((*I).second)).second;
Buffer *tmp = new Buffer(port, queueSize);
(*qBuffer)[port] = tmp;
(*sendControlOrDataPacket)[port] = new cMessage("sendControlorDataPacket");
(*sendControlOrDataPacket)[port]->setKind(TRANSMIT_PACKET + port);
(*msgServiced)[port] = NULL;
i++;
}
rTable = new routingTable();
bHelloSize = originalHelloSize * BYTE;
hopsLimit = static_cast<int> (hopsLimitFactor * numNodes);
startUpMessage = new cMessage("StartUpMessage",START_UP_MESSAGE);
scheduleAt(0.0 , startUpMessage);
}
void Router::handleMessage(cMessage *msg)
{
simtime_t time = simTime();
if( time >= startTime && time < endTime )
{
if( !routerDown )
{
routerDown = true;
clearAllBuffersOfRouter();
}
if(dynamic_cast<samplePacket *> (msg) != NULL)
{
samplePacket *dPacket = (samplePacket*) msg;
int destination = dPacket->getDestAddress();
if(destination == IPAddress)
{
sPtr->incrTotalBitsUndeliverable();
}
else
{
int id = msg->arrivalGateId();
if( id != 1)
{
sPtr->incrTotalBitsLost();
}
else
{
sPtr->incrTotalDownBitsGenerated();
}
}
delete dPacket;
}
else if(dynamic_cast<Ant *> (msg) != NULL)
{
sPtr->incrTotalAntsDeleted();
delete msg;
}
else if( dynamic_cast<helloPacket*> (msg) != NULL)
{
delete msg;
}
}
else
{
routerDown = false;
FSM_Switch( fsm )
{
case FSM_Exit(INIT):
// switch to send Hello Packet State
analyzeEvent(msg);
performExitInitActions(msg);
break;
case FSM_Exit(NORMAL):
analyzeEvent(msg);
performActionsInNormalState(msg);
break;
}
}
}
void Router::analyzeEvent(cMessage *msg)
{
switch(msg->kind())
{
case START_UP_MESSAGE:
tcb.event = START_UP_MESSAGE_EVENT;
break;
case NETLAYER_HELLO_PACKET:
tcb.event = NETLAYER_HELLO_PACKET_EVENT;
break;
case NETLAYER_HELLO_REPLY_PACKET:
tcb.event = NETLAYER_HELLO_REPLY_PACKET_EVENT;
break;
case NETLAYER_DATA_PACKET:
tcb.event = NETLAYER_DATA_PACKET_EVENT;
break;
case NETLAYER_BACKWARD_ANT:
tcb.event = NETLAYER_BACKWARD_ANT_EVENT;
break;
case NETLAYER_FORWARD_ANT:
tcb.event = NETLAYER_FORWARD_ANT_EVENT;
break;
default:
if( msg->kind() >= TRANSMIT_PACKET)
{
tcb.event = TRANSMIT_PACKET_EVENT;
}
else
{
throw new cException("Unknown event %s %d in AnyalyzeEvent:", msg->name, msg->kind());
}
break;
}
}
void Router::performExitInitActions(cMessage *msg)
{
switch(tcb.event)
{
case START_UP_MESSAGE_EVENT:
enqueHelloPacketInBuffers();
tcb.state = NORMAL_S;
FSM_Goto(fsm,NORMAL);
break;
default:
if(debug)
{
ev << "In INIT state received: " << tcb.event << endl;
ev << "Ignoring case: not handeled in switch(INIT)";
}
break;
}
}
void Router::performActionsInNormalState(cMessage *msg)
{
switch(tcb.event)
{
case NETLAYER_HELLO_PACKET_EVENT:
processHelloPacket(dynamic_cast<helloPacket*>(msg));
break;
case NETLAYER_HELLO_REPLY_PACKET_EVENT:
processHelloReplyPacket(dynamic_cast<helloPacket*>(msg));
delete msg;
break;
case NETLAYER_DATA_PACKET_EVENT:
processDataPacket(dynamic_cast<samplePacket*>(msg));
break;
case NETLAYER_FORWARD_ANT_EVENT:
processForwardAnt((Ant *) msg);
break;
case NETLAYER_BACKWARD_ANT_EVENT:
processBackwardAnt((Ant *) msg);
break;
case TRANSMIT_PACKET_EVENT:
processTransmitPacket(msg);
break;
default:
ev << "In Normal State received: " << tcb.event << endl;
throw new cException("Unexpected Event: Case Not Handeled");
break;
}
}
void Router::enqueHelloPacketInBuffers()
{
char msgname[70];
// We need to find out which ports are connected to another Routers
// and then send hello message on all of these ports
map<int,pair<int,int>*>::const_iterator I;
for( I = (*neighborPortID).begin(); I != (*neighborPortID).end(); I++)
{
int port = (*I).first;
pair<int,int>& thePair = *((*I).second);
int neighborAddress = thePair.second;
sprintf(msgname, "Hello Packet Source%d-Destination %d", IPAddress, neighborAddress);
helloPacket *hPacket = new helloPacket(msgname);
hPacket->setSourceAddress(IPAddress);
hPacket->setLength(bHelloSize);
hPacket->setKind(static_cast<int> (NETLAYER_HELLO_PACKET) );
hPacket->setTimestamp(simTime());
queueManagementForMessage(hPacket,port);
}
}
void Router::processHelloPacket(helloPacket* msg)
{
// Find out the port from where this hello packet arrived
int port = msg->arrivalGateId();
int sourceAddress = msg->getSourceAddress();
msg->setNeighborAddress(IPAddress);
msg->setKind(NETLAYER_HELLO_REPLY_PACKET);
msg->setTimestamp( simTime() );
queueManagementForMessage(msg,port);
}
void Router::processHelloReplyPacket(helloPacket* msg)
{
simtime_t rxTime = simTime();
simtime_t txTime = msg->getTxTime();
simtime_t qTime = msg->getQDelayAtNeighbor();
int messageID = msg->getMessageID();
int port = msg->arrivalGateId();
map<int,pair<double,double>*>::const_iterator J = (*bandWidthPdelay).find(port);
if( J != (*bandWidthPdelay).end() )
{
pair<double,double>& thePair = *((*J).second);
simtime_t transmitTime = static_cast<double> ( msg->length() / thePair.first );
// Estimate the propagation delay
double pDelay = ( rxTime - txTime - qTime) / 2.0 - transmitTime;
(*((*bandWidthPdelay)[port])).second = pDelay;
if(debug)
{
ev<<"Propagation Delay between node: " << IPAddress << "and node: " << msg->getNeighborAddress() <<" "<<
pDelay<<endl;
}
}
else
{
throw new cException("Received reply from Neighbor: %d(Unknown) ", (*((*neighborPortID)[port])).second);
}
}
void Router::processForwardAnt(Ant *msg)
{
findSourceForAnt( msg );
if( tcb.source == ROUTER)
{
send( msg, "toAntNest");
}
else if( tcb.source == ANT_NEST)
{
// now do the recording keep values by pushing the
// entrance time and nodeID onto the stack.
// for quick checking of cycles, we keep another
// array for the nodes being visited by the ant.
int neighbor = msg->getNeighborChosen();
double estimatedEntryTimeToThisNode = msg->getTimeAtNextHop();
double delay = estimateTimeToNextNode(neighbor);
msg->setTimeAtNextHop( estimatedEntryTimeToThisNode + delay);
int index = findInputGateIDForNeighbor(neighbor);
queueManagementForMessage(msg, index);
}
else
{
throw new cException("Unknown source for Ant in Router %d",IPAddress);
}
}
void Router::processBackwardAnt(Ant* msg)
{
findSourceForAnt( msg );
if( tcb.source == ROUTER)
{
send( msg, "toAntNest");
}
else if( tcb.source == ANT_NEST)
{
int neighbor = msg->getNeighborChosen();
int index = findInputGateIDForNeighbor(neighbor);
queueManagementForMessage(msg, index);
}
else
{
throw new cException("Unknown source for Ant in Router %d",IPAddress);
}
}
void Router::processDataPacket(samplePacket *msg)
{
int hops = msg->getHops();
double life = simTime() - msg->creationTime();
if( hops >= hopsLimit || life>= lifeLimit)
{
sPtr->incrTotalBitsLost();
delete msg;
}
else
{
int destination = msg->getDestAddress();
if(destination == IPAddress)
{
send(msg, "toDataSink");
}
else
{
int inputPortIndex = msg->arrivalGateId();
int nextPortIndex = chooseNextHop(msg);
// Increase the Number of Hops First
if( nextPortIndex == -1)
{
char msg1[100];
sprintf(msg1,"No OutPort Available for %d in %d", destination, IPAddress);
perror(msg1);
exit(-1);
}
msg->setHops( msg->getHops() + 1);
msg->setTimestamp( simTime() );
queueManagementForMessage(msg,nextPortIndex);
}
}
}
int Router::chooseNextHop(samplePacket *msg)
{
int sourceNode = msg->getSourceAddress();
int destination = msg->getDestAddress();
int enterPort = -1;
int port = -2;
// Find out from which neighbor this packet arrived
// and in this case we only need to modify just ack
// and send flags of the message already in the table
map<int,pair<int,int>*>::const_iterator J = (*neighborPortID).begin();
if (sourceNode != IPAddress)
{
enterPort = msg->arrivalGateId();
}
if(probabilisticRouting)
{
if( numNeighbors == 1)
{
return (*J).first;
}
else
{
// We implemented the routing mechanism as suggested in the paper by combinig
// the queue length and the probabiltiy. However, the performance somehow thisway
// is poorer as doing a simple stochastis spread.
/* double ln= 1.0;
int qSum = totalQueueLength();
double probSum = 0.0;
map<int,double> refineProb;
for( J = (*neighborPortID).begin(); J != (*neighborPortID).end(); J++)
{
port = (*J).first;
Buffer *sBuff = getBufferForThisPort(port);
int qn = sBuff->getNormalQueueCapacity() + sBuff->getQuickQueueCapacity();
int neighbor = (*((*neighborPortID)[port])).second;
if (qSum != 0)
{
ln = 1 - (double) qn/qSum;
}
else
{
ln = 1;
}
double Pnd = getProb(destination, neighbor);
double PndFinal = Pnd + qWeightFactor * ln;
probSum += PndFinal;
}
for( J = (*neighborPortID).begin(); J != (*neighborPortID).end(); J++)
{
port = (*J).first;
Buffer *sBuff = getBufferForThisPort(port);
int qn = sBuff->getNormalQueueCapacity() + sBuff->getQuickQueueCapacity();
int neighbor = (*((*neighborPortID)[port])).second;
if (qSum != 0)
{
ln = 1 - (double) qn/qSum;
}
else
{
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -