INET Framework for OMNeT++/OMNEST
stp.cc
Go to the documentation of this file.
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