📄 router.cc
字号:
//get the gate of networkNode to which this gate is connected
cGate *networkNodeGate = outRouterGate->toGate();
// Determine if this gate is connected to the network or not
// if yes then send on it hello packet
if(networkNodeGate->isConnected())
{
cModule *neighborNetworkNode = networkNodeGate->toGate()->ownerModule();
int neighborAddress = neighborNetworkNode->par("address");
// just for debugging purposed otherwise neighbor address will
// come in hello message from neighbor or Hello message from
// send to neighbor by this router
sprintf(msgname, "Hello Packet Source%d-Destination %d", myAddress, neighborAddress);
helloAndReplyMessage *helloPacket = new helloAndReplyMessage(msgname);
helloPacket->setSourceAddress(myAddress);
helloPacket->setLength(BYTE * 68);
helloPacket->setKind((int) NETLAYER_HELLO_PACKET);
helloPacket->setTimestamp(simTime());
int messageAndTimerID = (timerID++) % 10000;
// set the message ID to the output gate
// this ensures that if ack for this
// gate is not forthcoming then we would
// simply retransmit
helloPacket->setMessageID(messageAndTimerID);
helloAndReplyMessage *sendHelloCopy =
(helloAndReplyMessage*) helloPacket->dup();
simtime_t helloTxTime = helloPacket->length() / (double) dataRate;
send(sendHelloCopy, gateIDtoNode);
if(debug)
{
ev << "Router : " << myAddress << "Sending Hello Packet to "<<
neighborAddress << endl;
}
// we will just schedule one time out message, once this timer goes off
// we will scan the queue of unacknowledged messages and then simply
// resend all of them that are still in the queue
// Prepare timer for important identities so that it becomes
// easier for us to identify which timer has gone or to
// cancel which timer in case an acknowledgement comes back
cMessage *helloTimer = new cMessage("helloTimer",HELLO_RESEND_TIMER);
timerContextInfo *timerContext = new timerContextInfo();
timerContext->setGateID(gateIDtoNode);
timerContext->setTimerType((int) HELLO_RESEND_TIMER);
timerContext->setTimerID(messageAndTimerID);
timerContext->setNeighbor(neighborAddress); // debugging purpose
timerContext->setResendAttempt(0);
timerContext->setMsg(helloPacket);
helloTimer->setContextPointer( (void *) timerContext);
timerQueue.takeOwnership(false);
timerQueue.insert(helloTimer);
scheduleAt(simTime() + timeValues.helloTimeOutValue, helloTimer);
delete helloPacket;
}
}
}
}
void Router::sendHelloPacket(int neighbor)
{
char msgname[70];
helloAndReplyMessage *helloPacket;
sprintf(msgname, "Hello Packet Source%d-Destination %d", myAddress, neighbor);
helloPacket = new helloAndReplyMessage(msgname);
helloPacket->setSourceAddress(myAddress);
helloPacket->setNeighborAddress(neighbor);
helloPacket->setLength(BYTE * 68);
helloPacket->setTimestamp();
helloPacket->setKind((int) NETLAYER_HELLO_PACKET);
int messageAndTimerID = (timerID++) % 10000;
helloPacket->setMessageID(messageAndTimerID);
helloAndReplyMessage *sendHelloCopy =
(helloAndReplyMessage *) helloPacket->dup();
// find out transmission time
int gateID = getOutGateID(neighbor);
simtime_t helloTxTime = helloPacket->length() / (double) dataRate;
send(sendHelloCopy, gateID);
// we will just schedule one time out message, once this timer goes off
// we will scan the queue of unacknowledged messages and then simply
// resend all of them that are still in the queue
// Prepare timer for important identities so that it becomes
// easier for us to identify which timer has gone or to
// cancel which timer in case an acknowledgement comes back
cMessage *helloTimer = new cMessage("helloTimer",HELLO_RESEND_TIMER);
timerContextInfo *timerContext = new timerContextInfo();
timerContext->setGateID(gateID);
timerContext->setTimerType((int) HELLO_RESEND_TIMER);
timerContext->setTimerID(messageAndTimerID);
timerContext->setNeighbor(neighbor); // debugging purpose
timerContext->setResendAttempt(0);
timerContext->setMsg(helloPacket);
helloTimer->setContextPointer( (void *) timerContext);
timerQueue.takeOwnership(false);
timerQueue.insert(helloTimer);
scheduleAt(simTime() + timeValues.helloTimeOutValue, helloTimer);
delete helloPacket;
}
void Router::retransmitHelloMessageForThisTimerMessage(cMessage *pMsg)
{
timerContextInfo *timerContext = (timerContextInfo *) pMsg->contextPointer();
if(timerContext->getResendAttempt() < resendAttempts)
{
int outGateID = timerContext->getGateID();
int neighborAddress = timerContext->getNeighbor();
helloAndReplyMessage *tempHelloMsg =
(helloAndReplyMessage *) timerContext->getMsg();
int messageAndTimerID = (timerID++) % 10000;
tempHelloMsg->setMessageID(messageAndTimerID);
helloAndReplyMessage *sendHelloCopy = (helloAndReplyMessage*) tempHelloMsg->dup();
simtime_t helloTxTime = tempHelloMsg->length() / (double) dataRate;
send(sendHelloCopy, outGateID);
// we will just schedule one time out message, once this timer goes off
// we will scan the queue of unacknowledged messages and then simply
// resend all of them that are still in the queue
// Prepare timer for important identities so that it becomes
// easier for us to identify which timer has gone or to
// cancel which timer in case an acknowledgement comes back
cMessage *helloTimer = new cMessage("helloTimer",HELLO_RESEND_TIMER);
timerContext->setTimerID(messageAndTimerID);
timerContext->setMsg(tempHelloMsg);
int attempts = timerContext->getResendAttempt();
attempts++;
timerContext->setResendAttempt(attempts);
helloTimer->setContextPointer((void*) timerContext);
timerQueue.takeOwnership(false);
timerQueue.insert(helloTimer);
scheduleAt(simTime() + timeValues.helloTimeOutValue, helloTimer);
delete tempHelloMsg;
}
else
{
// it means that either this neighbor or link is down, we will
// assume that link is down and in this way all neighbors will
// remove link from this node and hence it will be imperative
// that in this way dwon nod is out of topology
// delete this timer and associated messages
// helloAndReplyMessage *thisMessage =
// (helloAndReplyMessage*) timerContext->msg;
int neighborAddress = timerContext->getNeighbor();
deleteNeighbor(neighborAddress);
delete timerContext;
}
}
int Router::processHelloAndReplyMessage(helloAndReplyMessage *helloOrReplyPacket)
{
// Find out whether this is a hello message or
// reply to the hello message
if( helloOrReplyPacket->kind() == (int) NETLAYER_HELLO_PACKET) //this is helloMessage
{
// This means that this router has received a hello message,
// hence router simply send an acknowledgement and provides
// its own address in it.
int neighborAddress = helloOrReplyPacket->getSourceAddress();
int outGateID = getOutGateID(neighborAddress);
helloOrReplyPacket->setNeighborAddress(myAddress);
helloOrReplyPacket->setKind((int) NETLAYER_HELLO_REPLY_PACKET);
simtime_t replyTxTime = helloOrReplyPacket->length() / (double) dataRate;
send(helloOrReplyPacket, outGateID);
// The idea here is maintain a pair of source address
// to port/gate so that in future we could just traverse
// this small vector to find out the source is connected
// to which gate/(port) of the router
if( !existsNeighborGatePair(neighborAddress))
{
pairNumber *dPair = new pairNumber;
dPair->first = neighborAddress;
dPair->second = outGateID;
destGate.push_back(dPair);
}
// now we know the address of one of the neighbors,
// hence we use it add it in the topology graph
// addRouter node ensures that we do not add
// multiple nodes
if( !neighborExists( neighborAddress ))
{
topology.push_back(neighborAddress);
}
if(debug)
{
ev << "Hello Packet Received at Router: " << myAddress << endl;
ev << "Hello Packet receievd from Router: "
<< helloOrReplyPacket->getSourceAddress() << endl;
}
return neighborAddress;
}
// this is the reply message of my hello message
else if( helloOrReplyPacket->kind() == (int) NETLAYER_HELLO_REPLY_PACKET)
{
int sourceAddress = helloOrReplyPacket->getSourceAddress();
// This Packet will provide us with the address of one of the
// neighbors, hence we extract its address and add its
// identity to the graph data structure
int messageID = helloOrReplyPacket->getMessageID();
// now we must delete this timer message from the queue of timer
// messages
deleteHelloTimerMessage(messageID);
// now we know the address of one of the neighbors,
// hence we use it add it in the topology graph
// addRouter node ensures that we do not add
// multiple nodes
int neighborAddress = helloOrReplyPacket->getNeighborAddress();
int gateID = getOutGateID(neighborAddress);
if( !existsNeighborGatePair(neighborAddress))
{
pairNumber *dPair = new pairNumber;
dPair->first = neighborAddress;
dPair->second = gateID;
destGate.push_back(dPair);
}
if( !neighborExists( neighborAddress ))
{
topology.push_back(neighborAddress);
}
// this packet is no more needed, hence freeing memory.
delete helloOrReplyPacket;
if(debug)
{
ev << "Reply of Hello Packet Received at Router: " << myAddress
<< "from Router " << neighborAddress << endl;
}
return neighborAddress;
}
else
{
throw new cException("Error: Expecting Hello or Reply Message");
}
}
void Router::deleteHelloTimerMessage(int hID)
{
cMessage *tMsg = NULL;
for(cQueueIterator iter(timerQueue,1); !iter.end(); iter++)
{
cMessage *hMsg = (cMessage *) iter();
timerContextInfo *timerContext= (timerContextInfo *) hMsg->contextPointer();
if( hMsg->kind() == (int) HELLO_RESEND_TIMER
&& timerContext->getTimerID() == hID)
{
tMsg = hMsg;
break;
}
}
if(tMsg != NULL)
{
cMessage *temp = (cMessage *) timerQueue.remove(tMsg);
timerContextInfo *timerContext= (timerContextInfo *) tMsg->contextPointer();
delete timerContext;
if( temp->isScheduled())
{
delete cancelEvent(temp);
}
else
{
delete temp;
}
}
}
void Router::handleForwardAnt(Ant *msg)
{
findSourceForAnt( msg );
if( tcb.source == ROUTER)
{
send( msg, "toAntNest");
}
else if( tcb.source == ANT_NEST)
{
int neighbor = msg->getNeighborChosen();
int index = findIndexForNeighbor(neighbor);
handleMessageQueue(msg, index);
}
else
{
throw new cException("Unknown source for Ant in Router %d",myAddress);
}
}
void Router::handleMessageQueue(cMessage *msg, int index)
{
if(msg == sendNormalAndForwardAnt[index])
{
if( sendNormalQueue[index].empty() )
{
msgServiced[index] = NULL;
}
else
{
msgServiced[index] = (cMessage *) sendNormalQueue[index].getTail();
simtime_t txTime = sendPacketInQueue(msgServiced[index], index);
sendNormalAndForwardAnt[index]->setKind( SEND_NORMAL_PACKET_COM + index);
scheduleAt(simTime() + txTime, sendNormalAndForwardAnt[index]);
}
}
else if( !msgServiced[index])
{
msgServiced[index] = msg;
simtime_t txTime = processMessageWhenQueueIsEmpty(msg, index);
sendNormalAndForwardAnt[index]->setKind( SEND_NORMAL_PACKET_COM + index);
scheduleAt(simTime() + txTime, sendNormalAndForwardAnt[index]);
}
else
{
int type = msg->kind();
if(type == NETLAYER_FORWARD_ANT)
{
receiveProcessStorePacket( (Ant *) msg,index);
}
else if(type == NETLAYER_DATA_PACKET)
{
processNormalDataPackets((samplePacket *) msg,index);
}
else
{
throw new cException("Unknown Message in handleQueueMessage%d", type);
}
}
}
simtime_t Router::processMessageWhenQueueIsEmpty(cMessage *msg, int index)
{
int kind = msg->kind();
simtime_t txTime = 0.0;
if ( kind == NETLAYER_DATA_PACKET)
{
samplePacket *packet = (samplePacket *) msg;
// if this node is the destination then give
// packet to the sink
int destination = packet->getDestAddress();
if( destination == myAddress)
{
send(packet, "toDataSink");
txTime = 0.0000001;
return txTime;
}
else
{
simtime_t txTime = sendPacketInQueue(msg,index);
return txTime;
}
}
else if ( kind == NETLAYER_FORWARD_ANT)
{
Ant *forwardAnt = (Ant *) msg;
simtime_t txTime = sendPacketInQueue(msg,index);
return txTime;
}
else
{
throw new cException("Unknown Message in handleQueueMessage%d", kind);
}
}
void Router::processNormalDataPackets(samplePacket *packet, int i)
{
// if routing table is yet not constructed then simply
// ignore the packet
if(topologyDiscovered)
{
receiveProcessStorePacket( packet,i );
}
else
{
delete packet;
}
}
void Router::receiveProcessStorePacket(cMessage *packet, int i)
{
int type = packet->kind();
if(debug)
{
ev << "Ant Received at Router: " << myAddress << packet->name() << endl;
ev << "Message Kind is: " << type << endl;
}
// increment the counter
numPacketsToSend[i]++;
//if send queue is already full then we need to drop the packet
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -