📄 ls.cc
字号:
// Copyright (c) 2000 by the University of Southern California// All rights reserved.//// Permission to use, copy, modify, and distribute this software and its// documentation in source and binary forms for non-commercial purposes// and without fee is hereby granted, provided that the above copyright// notice appear in all copies and that both the copyright notice and// this permission notice appear in supporting documentation. and that// any documentation, advertising materials, and other materials related// to such distribution and use acknowledge that the software was// developed by the University of Southern California, Information// Sciences Institute. The name of the University may not be used to// endorse or promote products derived from this software without// specific prior written permission.//// THE UNIVERSITY OF SOUTHERN CALIFORNIA makes no representations about// the suitability of this software for any purpose. THIS SOFTWARE IS// PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,// INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.//// Other copyrights might apply to parts of this software and are so// noted when applicable.//// Copyright (C) 1998 by Mingzhou Sun. All rights reserved.// This software is developed at Rensselaer Polytechnic Institute under // DARPA grant No. F30602-97-C-0274// Redistribution and use in source and binary forms are permitted// provided that the above copyright notice and this paragraph are// duplicated in all such forms and that any documentation, advertising// materials, and other materials related to such distribution and use// acknowledge that the software was developed by Mingzhou Sun at the// Rensselaer Polytechnic Institute. The name of the University may not // be used to endorse or promote products derived from this software // without specific prior written permission.//// $Header: /nfs/jade/vint/CVSROOT/ns-2/linkstate/ls.cc,v 1.1 2000/07/27 01:29:16 haoboy Exp $#include "ls.h"// a global variableLsMessageCenter messageCenter;int LsRouting::msgSizes[LS_MESSAGE_TYPES];class initRouting {public: initRouting() { LsRouting::msgSizes[LS_MSG_LSA] = LS_LSA_MESSAGE_SIZE; LsRouting::msgSizes[LS_MSG_TPM] = LS_TOPO_MESSAGE_SIZE; LsRouting::msgSizes[LS_MSG_LSAACK] = LS_ACK_MESSAGE_SIZE; LsRouting::msgSizes[LS_MSG_TPMACK] = LS_ACK_MESSAGE_SIZE; }} lsRoutingInitializer;void ls_error(char* msg) { fprintf(stderr, "%s\n", msg); abort();}/* LsNodeIdList methods*/int LsNodeIdList::appendUnique (const LsNodeIdList & x) { int newHopCount = 0; for (LsNodeIdList::const_iterator itr1 = x.begin(); itr1 != x.end(); itr1++) { LsNodeIdList::iterator itr2; for (itr2 = begin(); itr2 != end(); itr2++) // check for duplicate if ((*itr1) == (*itr2)) break; if (itr2 == end()) { // no duplicate, insert it push_back(*itr1); newHopCount++; // forgot what newHopCount is used for } } return newHopCount;}/* LsTopoMap methods*/LsLinkStateList * LsTopoMap::insertLinkState (int nodeId, const LsLinkState& linkState){ LsLinkStateList* lsp = LsLinkStateListMap::findPtr(nodeId); if (lsp != NULL) { // there's a node with other linkState, not checking if there's // duplicate lsp->push_back(linkState); return lsp; } // else new node LsLinkStateList lsl; // an empty one iterator itr = insert(nodeId, lsl); if (itr !=end()){ // successful (*itr).second.push_back(linkState); return &((*itr).second); } // else something is wrong ls_error("LsTopoMap::insertLinkState failed\n"); // debug return (LsLinkStateList *) NULL;}// -- update --, return true if anything's changed bool LsTopoMap::update(int nodeId, const LsLinkStateList& linkStateList){ LsLinkStateList * LSLptr = findPtr (nodeId); if (LSLptr == NULL) { insert(nodeId, linkStateList); return true; } bool retCode = false; LsLinkStateList::iterator itrOld; for (LsLinkStateList::const_iterator itrNew = linkStateList.begin(); itrNew != linkStateList.end(); itrNew++ ) { for (itrOld = LSLptr->begin(); itrOld != LSLptr->end(); itrOld++) { if ((*itrNew).neighborId_ == (*itrOld).neighborId_) { // old link state found if (nodeId != myNodeId_) // update the sequence number, if // it's not my own link state (*itrOld).sequenceNumber_ = (*itrNew).sequenceNumber_; if ((*itrNew).status_ != (*itrOld).status_) { (*itrOld).status_ = (*itrNew).status_; retCode = true; } if ((*itrNew).cost_ != (*itrOld).cost_) { (*itrOld).cost_ = (*itrNew).cost_; retCode = true; } break; // no need to search for more old link state; } // end if old link state found } // end for old link states if (itrOld == LSLptr->end()) { // no old link found LSLptr->push_back(*itrNew); retCode = true; } }// end for new link states return retCode;}/* LsPaths methods*/// insertPath(), returns end() if error, else return iterator LsPaths::iterator LsPaths::insertPath(int destId, int cost, int nextHop) { iterator itr = LsEqualPathsMap::find(destId); // if new path, insert it and return iterator if (itr == end()) return insertPathNoChecking(destId, cost, nextHop); LsEqualPaths * ptrEP = &(*itr).second; // if the old path is better, ignore it, return end() // to flag the error if (ptrEP->cost < cost) return end(); // else if the new path is better, erase the old ones and save the new one LsNodeIdList & nhList = ptrEP->nextHopList; if (ptrEP->cost > cost) { ptrEP->cost = cost; nhList.erase(nhList.begin(), nhList.end()); nhList.push_back(nextHop); return itr; } // else the old path is the same cost, check for duplicate for (LsNodeIdList::iterator itrList = nhList.begin(); itrList != nhList.end(); itrList++) // if duplicate found, return 0 to flag the error if ((*itrList) == nextHop) return end(); // else, the new path is installed indeed, the total number of nextHops // is returned. nhList.push_back(nextHop); return itr;}LsPaths::iterator LsPaths::insertNextHopList(int destId, int cost, const LsNodeIdList& nextHopList) { iterator itr = LsEqualPathsMap::find(destId); // if new path, insert it and return iterator if (itr == end()) { LsEqualPaths ep(cost, nextHopList); itr = insert(destId, ep); return itr; } // else get the old ep LsEqualPaths* ptrOldEp = &(*itr).second; // if the old path is better, ignore it, return end() to flag error if (ptrOldEp->cost < cost) return end(); // else if the new path is better, replace the old one with the new one if (ptrOldEp->cost > cost) { ptrOldEp->cost = cost; ptrOldEp->nextHopList = nextHopList ; // copy return itr; } // equal cost: append the new next hops with checking for duplicates ptrOldEp->appendNextHopList(nextHopList); return itr;}/* LsPathsTentative methods*/LsPath LsPathsTentative::popShortestPath() { findMinEqualPaths(); LsPath path; if (empty() || (minCostIterator == end())) return path; // an invalid one LsNodeIdList& nhList = (*minCostIterator).second.nextHopList; if (nhList.empty() && (findMinEqualPaths() == end())) return path; path.destination = (*minCostIterator).first; path.cost=(*minCostIterator).second.cost; // the first 'nextHop' path.nextHop = nhList.front(); nhList.pop_front(); // if this pops out the last nextHop in the EqualPaths, find a new one. if (nhList.empty()) { erase(minCostIterator); findMinEqualPaths(); } return path;}LsPathsTentative::iterator LsPathsTentative::findMinEqualPaths(){ minCost = LS_MAX_COST + 1; minCostIterator = end(); for (iterator itr = begin(); itr != end(); itr++){ if ((minCost > (*itr).second.cost) && !(*itr).second.nextHopList.empty()) { minCost = (*itr).second.cost; minCostIterator = itr; } } return minCostIterator;}/* LsMessageCenter methods*/LsMessage* LsMessageCenter::newMessage(int nodeId, ls_message_type_t type) { // check if max_message_number is invalid, call init () if (max_size == 0) init(); // if max_size reached, recycle message_storage* storagePtr; u_int32_t currentId; // current_lsa_id and current_other_id are odd and even, respectively if ((type == LS_MSG_LSA) || (type == LS_MSG_TPM)) { storagePtr = & lsa_messages; currentId = current_lsa_id; if ((current_lsa_id += 2) == LS_INVALID_MESSAGE_ID) current_lsa_id += 2; } else { storagePtr = &other_messages; currentId = current_other_id; if ((current_other_id += 2) == LS_INVALID_MESSAGE_ID) current_other_id +=2; } if (storagePtr->size() >= max_size) storagePtr->erase(storagePtr->begin()); LsMessage* msgPtr = (LsMessage *)NULL; message_storage::iterator itr = storagePtr->insert(currentId, LsMessage(currentId, nodeId, type)); if (itr == storagePtr->end()) ls_error("Can't insert new message in " "LsMessageCenter::newMessage.\n"); else msgPtr = &((*itr).second); return msgPtr;}bool LsMessageCenter::deleteMessage(u_int32_t msgId){ message_storage::iterator itr = other_messages.find (msgId); if (itr == other_messages.end()) return false; other_messages.erase(itr); return true;}// init()void LsMessageCenter::init() { // only when nothing is provided by tcl code max_size = 300;}/* LsMessageHistory methods */// TODO, rewrite this method for topo messagebool LsMessageHistory::isNewMessage ( const LsMessage& msg ) { iterator itr = find(msg.originNodeId_); if (itr != end()) { if (((*itr).second < msg.sequenceNumber_) || ((*itr).second - msg.sequenceNumber_ > LS_WRAPAROUND_THRESHOLD)) { // The new message is more up-to-date than the old one (*itr).second = msg.sequenceNumber_; return true; } else { // We had a more up-to-date or same message from // this node before return false; } } else { // We never received message from this node before insert(msg.originNodeId_, msg.sequenceNumber_); return true; } }/* LsRetransmissionManager Methods */void LsRetransmissionManager::initTimeout(LsDelayMap * delayMapPtr) { if (delayMapPtr == NULL) return; for (LsDelayMap::iterator itr = delayMapPtr->begin(); itr != delayMapPtr->end(); itr++) // timeout is LS_TIMEOUT_FACTOR*one-way-delay estimate insert((*itr).first, LsUnackPeer(this, (*itr).first, LS_TIMEOUT_FACTOR*(*itr).second));}void LsRetransmissionManager::cancelTimer (int nbrId) { LsUnackPeer* peerPtr = findPtr(nbrId); if (peerPtr == NULL) return; peerPtr->tpmSeq_ = LS_INVALID_MESSAGE_ID; peerPtr->lsaMap_.eraseAll(); peerPtr->timer_.force_cancel();}// Called by LsRouting when a message is sent outint LsRetransmissionManager::messageOut(int peerId, const LsMessage& msg){ LsUnackPeer* peerPtr = findPtr(peerId); if (peerPtr == NULL) { iterator itr = insert(peerId, LsUnackPeer(this, peerId)); if (itr == end()) { ls_error ("Can't insert."); } peerPtr = &((*itr).second); } LsIdSeq* idSeqPtr; switch (msg.type_) { case LS_MSG_TPM: peerPtr->tpmSeq_ = msg.sequenceNumber_; break; case LS_MSG_LSA: idSeqPtr = peerPtr->lsaMap_.findPtr(msg.originNodeId_); if (idSeqPtr == NULL) peerPtr->lsaMap_.insert(msg.originNodeId_, LsIdSeq(msg.messageId_, msg.sequenceNumber_)); else { idSeqPtr->msgId_ = msg.messageId_; idSeqPtr->seq_ = msg.sequenceNumber_; } break; case LS_MSG_TPMACK: case LS_MSG_LSAACK: case LS_MSG_LSM: default: // nothing, just to avoid compiler warning break; } // reschedule timer to allow account for this latest message peerPtr->timer_.resched(peerPtr->rtxTimeout_); return 0;} // Called by LsRouting, when an ack is received// Or by messageIn, some the message can serve as ackint LsRetransmissionManager::ackIn(int peerId, const LsMessage& msg){ LsUnackPeer* peerPtr = findPtr(peerId); if ((peerPtr == NULL) || (peerPtr->tpmSeq_ == LS_INVALID_MESSAGE_ID) && peerPtr->lsaMap_.empty()) // no pending ack for this neighbor return 0; LsMap<int, LsIdSeq>::iterator itr; switch (msg.type_) { case LS_MSG_TPMACK: if (peerPtr->tpmSeq_ == msg.sequenceNumber_) // We've got the right ack, so erase the unack record peerPtr->tpmSeq_ = LS_INVALID_MESSAGE_ID; break; case LS_MSG_LSAACK: itr = peerPtr->lsaMap_.find(msg.originNodeId_); if ((itr != peerPtr->lsaMap_.end()) && ((*itr).second.seq_ == msg.sequenceNumber_)) // We've got the right ack, so erase the unack record peerPtr->lsaMap_.erase(itr); break; case LS_MSG_TPM: case LS_MSG_LSA: case LS_MSG_LSM: default: break; } if ((peerPtr->tpmSeq_ == LS_INVALID_MESSAGE_ID) && (peerPtr->lsaMap_.empty())) // No more pending ack, cancel timer peerPtr->timer_.cancel(); // ack deleted in calling function LsRouting::receiveMessage return 0;}// resendMessage
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -