|
INET Framework for OMNeT++/OMNEST
|
00001 // 00002 // This program is free software: you can redistribute it and/or modify 00003 // it under the terms of the GNU Lesser General Public License as published by 00004 // the Free Software Foundation, either version 3 of the License, or 00005 // (at your option) any later version. 00006 // 00007 // This program is distributed in the hope that it will be useful, 00008 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00009 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00010 // GNU Lesser General Public License for more details. 00011 // 00012 // You should have received a copy of the GNU Lesser General Public License 00013 // along with this program. If not, see http://www.gnu.org/licenses/. 00014 // 00015 00016 #include "stp.h" 00017 #include "ansaSwitchCore.h" 00018 #include "vlanTable.h" 00019 #include "stpXMLparser.h" 00020 00021 Define_Module(Stp); 00022 00023 bool Stp::learning(unsigned int port, unsigned int vlan) { 00024 Enter_Method_Silent(); 00025 for (unsigned int i = 0; i < instReg.size(); i++) { 00026 if (instReg.at(i) == vlan) { 00027 return inst.at(i).learning(port); 00028 } 00029 } 00030 return false; 00031 } 00032 00033 bool Stp::forwarding(unsigned int port, unsigned int vlan) { 00034 Enter_Method_Silent(); 00035 for (unsigned int i = 0; i < instReg.size(); i++) { 00036 if (instReg.at(i) == vlan) { 00037 return inst.at(i).forwarding(port); 00038 } 00039 } 00040 return false; 00041 } 00042 00043 void Stp::dispatchALL() { 00044 for (unsigned int i = 0; i < inst.size(); i++) { 00045 dispatch(i); 00046 } 00047 } 00048 00049 void Stp::dispatch(unsigned int idx) { 00050 for (unsigned int i = 0; i < inst.at(idx).msgList.size(); i++) { 00051 send(inst.at(idx).msgList.at(i).msg, "out", inst.at(idx).msgList.at(i).port); 00052 } 00053 inst.at(idx).msgList.clear(); 00054 } 00055 00056 /* ---- FOR XML CONFIGURATOR ------*/ 00057 int Stp::getInstanceIndex(unsigned int _inst) { 00058 for (unsigned int i = 0; i < instReg.size(); i++) { 00059 if (instReg.at(i) == _inst) { 00060 return i; 00061 } 00062 } 00063 return -1; 00064 } 00065 00066 void Stp::setBridgePriority(unsigned int _inst, unsigned int _bridgePriority) { 00067 int idx = getInstanceIndex(_inst); 00068 if (idx == -1) { 00069 return; 00070 } 00071 00072 inst.at(idx).bridgePriority = _bridgePriority; 00073 00074 } 00075 00076 /* internal for XML configuration */ 00077 void Stp::setPortPriority(unsigned int _idx, unsigned int _port, unsigned int _priority) { 00078 inst.at(_idx).portTable.at(_port).priority = _priority; 00079 } 00080 void Stp::setLinkCost(unsigned int _idx, unsigned int _port, unsigned int _cost) { 00081 inst.at(_idx).portTable.at(_port).linkCost = _cost; 00082 } 00083 00084 00085 void Stp::setPortPriority(unsigned int _inst, std::vector<unsigned int>& _portList, std::vector<unsigned int>& _priList) { 00086 int idx = getInstanceIndex(_inst); 00087 if (idx == -1) { 00088 return; 00089 } 00090 00091 if (_portList.size() != _priList.size()) { 00092 return; 00093 } 00094 00095 for (unsigned int i = 0; i < _portList.size(); i++) { 00096 setPortPriority(idx, _portList.at(i), _priList.at(i)); 00097 } 00098 00099 } 00100 00101 void Stp::setLinkCost(unsigned int _inst, std::vector<unsigned int>& _portList, std::vector<unsigned int>& _costList) { 00102 int idx = getInstanceIndex(_inst); 00103 if (idx == -1) { 00104 return; 00105 } 00106 00107 if (_portList.size() != _costList.size()) { 00108 return; 00109 } 00110 00111 for (unsigned int i = 0; i < _portList.size(); i++) { 00112 setLinkCost(idx, _portList.at(i), _costList.at(i)); 00113 } 00114 00115 } 00116 00117 void Stp::setForwardDelay(unsigned int _inst, unsigned int _fwdDelay) { 00118 int idx = getInstanceIndex(_inst); 00119 if (idx == -1) { 00120 return; 00121 } 00122 inst.at(idx).fwdDelay = _fwdDelay; 00123 00124 } 00125 00126 void Stp::setMaxAge(unsigned int _inst, unsigned int _maxAge) { 00127 int idx = getInstanceIndex(_inst); 00128 if (idx == -1) { 00129 return; 00130 } 00131 inst.at(idx).maxAge = _maxAge; 00132 } 00133 00134 void Stp::setHelloTime(unsigned int _inst, unsigned int _helloTime){ 00135 int idx = getInstanceIndex(_inst); 00136 if (idx == -1) { 00137 return; 00138 } 00139 inst.at(idx).helloTime = _helloTime; 00140 } 00141 00142 00143 /* ---- END FOR XML CONFIGURATOR ------*/ 00144 00145 void Stp::initialize(int stage) 00146 { 00147 if (stage == 0) { 00148 00149 portCount = gateSize("out"); 00150 00151 tick = new cMessage("STP_TICK", 0); 00152 00153 /* connection to MAC Table for faster aging */ 00154 cModule * tmp_macTable = getParentModule()->getSubmodule("MACTable"); 00155 addrTable = check_and_cast<MACTable *>(tmp_macTable); 00156 00157 WATCH(bridgeAddress); 00158 } 00159 else if (stage == 1) { 00160 /* obtain a Bridge Address from Core and initialize instances*/ 00161 cModule * tmp_core = getParentModule()->getSubmodule("core"); 00162 ANSASwitchCore * core = check_and_cast<ANSASwitchCore *>(tmp_core); 00163 bridgeAddress = core->getBridgeAddress(); 00164 00165 /* obtain a VLAN list for STP instances creation */ 00166 cModule * tmp_vlantable = getParentModule()->getSubmodule("VLANTable"); 00167 VLANTable * vlantable = check_and_cast<VLANTable *>(tmp_vlantable); 00168 instReg = vlantable->getVLANList(); 00169 00170 00171 /* call init on all instances */ 00172 for (unsigned int i = 0; i < instReg.size(); i++) { 00173 stpi tmp(instReg.at(i), portCount, bridgeAddress, addrTable); 00174 inst.push_back(tmp); 00175 } 00176 00177 const char *filename = par("configFile"); 00178 const char *switchID = par("switchID"); 00179 00180 if (*filename == '\0' || *switchID == '\0') { 00181 EV << "Warning: " << this->getParentModule()->getName() << ": Could not config, config filename or switchID is not set, using Default." << std::endl; 00182 } else { 00183 stpXMLparser config(this); 00184 config.parse(filename, switchID); 00185 } 00186 00187 00188 00189 WATCH_VECTOR(inst); 00190 WATCH_VECTOR(instReg); 00191 00192 scheduleAt(simTime()+1, tick); 00193 } 00194 } 00195 00196 void Stp::handleMessage(cMessage *msg) 00197 { 00198 cMessage * tmp = msg; 00199 00200 if (!msg->isSelfMessage()) { 00201 if (dynamic_cast<STPBPDU *>(tmp)){ // Configuration BPDU 00202 STPBPDU * bpdu = (STPBPDU *) tmp; 00203 handleBPDU(bpdu); 00204 } else if (dynamic_cast<STPTCN *>(tmp)){ // Topology Change Notification 00205 STPTCN * tcn = (STPTCN *) tmp; 00206 handleTCN(tcn); 00207 } else { // Rubbish 00208 delete msg; 00209 } 00210 } else { 00211 handleSelfMessage(msg); 00212 } 00213 00214 00215 } 00216 00217 void Stp::finish() { 00218 cancelAndDelete(tick); 00219 } 00220 00221 void Stp::handleSelfMessage(cMessage * msg) { 00222 if (msg == tick) { 00223 for (unsigned int i = 0; i < inst.size(); i++) { 00224 inst.at(i).handleTick(); 00225 } 00226 scheduleAt(simTime()+1, tick); 00227 } else { 00228 delete msg; 00229 } 00230 dispatchALL(); 00231 } 00232 00233 void Stp::handleBPDU(STPBPDU * bpdu) { 00234 unsigned int _vlan = bpdu->getVlan(); 00235 00236 for (unsigned int i = 0; i < instReg.size(); i++) { 00237 if (instReg.at(i) == _vlan) { 00238 inst.at(i).handleBPDU(bpdu); 00239 dispatch(i); 00240 return; 00241 } 00242 } 00243 delete bpdu; 00244 00245 } 00246 00247 void Stp::handleTCN(STPTCN * tcn) { 00248 unsigned int _vlan = tcn->getVlan(); 00249 00250 for (unsigned int i = 0; i < instReg.size(); i++) { 00251 if (instReg.at(i) == _vlan) { 00252 inst.at(i).handleTCN(tcn); 00253 dispatch(i); 00254 return; 00255 } 00256 } 00257 delete tcn; 00258 } 00259 00260 00261 00262