|
INET Framework for OMNeT++/OMNEST
|
00001 00002 #include "ansaSwitchCore.h" 00003 00004 Define_Module(ANSASwitchCore); 00005 00006 MACAddress ANSASwitchCore::getBridgeAddress() { 00007 Enter_Method_Silent(); 00008 return bridgeAddress; 00009 } 00010 00011 00012 void ANSASwitchCore::initialize(int stage) { 00013 00014 if (stage == 0) { 00015 portCount = gateSize("ifOut"); 00016 00017 /* because ASSERT in handleIncomingFrame() */ 00018 int i = 0; 00019 char msgname[16]; 00020 sprintf(msgname, "switchMsg %d", i); 00021 currentMsg = new cMessage(msgname, i); 00022 00023 cModule * tmp_macTable = getParentModule()->getSubmodule("MACTable"); 00024 addrTable = check_and_cast<MACTable *>(tmp_macTable); 00025 00026 cModule * tmp_vlanTable = getParentModule()->getSubmodule("VLANTable"); 00027 vlanTable = check_and_cast<VLANTable *>(tmp_vlanTable); 00028 00029 cModule * tmp_stp = getParentModule()->getSubmodule("stp"); 00030 spanningTree = check_and_cast<Stp *>(tmp_stp); 00031 00032 bridgeGroupAddress = MACAddress("01-80-C2-00-00-00"); 00033 bridgeAddress = MACAddress::generateAutoAddress(); 00034 00035 WATCH(bridgeAddress); 00036 } 00037 } 00038 00039 void ANSASwitchCore::handleMessage(cMessage *msg) { 00040 00041 if (!msg->isSelfMessage()) { 00042 tFrameDescriptor frame; 00043 00044 if (strcmp(msg->getArrivalGate()->getName(), "stpIn") == 0) { 00045 /* Messages from STP process */ 00046 dispatchBPDU(msg, msg->getArrivalGate()->getIndex()); 00047 return; 00048 00049 } else if (strcmp(msg->getArrivalGate()->getName(), "ifIn") == 0) { 00050 /* Messages from network */ 00051 if (reception(frame, msg) == true) { 00052 //EV << frame; 00053 //error("BLE BLE"); 00054 relay(frame); 00055 } 00056 delete frame.payload; 00057 } 00058 } else { 00059 // Self message signal used to indicate a frame has finished processing 00060 processFrame(msg); 00061 } 00062 delete msg; 00063 } 00064 00065 bool ANSASwitchCore::reception(ANSASwitchCore::tFrameDescriptor& frame, cMessage *msg) { 00066 /* ACTIVE TOPOLOGY ENFORCEMENT AFTER CLASSIFICATION AND INGRESS 00067 * because of learning state operation, MAC record can be learned 00068 * after classification and ingress, if learning is enabled on 00069 * that port. 00070 */ 00071 //CLASSIFICATION & INGRESS CALL 00072 int rPort = msg->getArrivalGate()->getIndex(); 00073 00074 cMessage * tmp = msg; 00075 ASSERT(tmp); 00076 00077 // Classify frame, and unpack to frame descriptor 00078 if (dynamic_cast<AnsaEtherFrame *>(tmp)){ 00079 AnsaEtherFrame * taggedFrame = (AnsaEtherFrame *) tmp; 00080 if (ingress(frame, taggedFrame, rPort) == false) { 00081 return false; 00082 } 00083 } else if (dynamic_cast<EthernetIIFrame *>(tmp)) { 00084 EthernetIIFrame * untaggedFrame = (EthernetIIFrame *) tmp; 00085 ingress(frame, untaggedFrame, rPort); // discarding forbidden PortVID is in relay 00086 } 00087 00088 return true; 00089 } 00090 00091 void ANSASwitchCore::relay(ANSASwitchCore::tFrameDescriptor& frame) { 00092 00093 // BPDU Handling 00094 if (frame.dest == bridgeGroupAddress) { 00095 deliverBPDU(frame); 00096 return; 00097 } 00098 00099 /* Dropping forbidden PortVID*/ 00100 if (frame.VID == 0) { 00101 return; 00102 } 00103 00104 // BROADCAST ?? 00105 if (frame.dest.isBroadcast()) { 00106 frame.portList = vlanTable->getPorts(frame.VID); 00107 if (frame.portList.size() == 0) { 00108 return; 00109 } 00110 00111 } else { 00112 VLANTable::tVIDPort tmpPort; 00113 tmpPort.action = VLANTable::REMOVE; 00114 00115 MACTable::tPortList tmpPortList = addrTable->getPorts(frame.dest); 00116 00117 if (tmpPortList.size() == 0) { // not known -> bcast 00118 frame.portList = vlanTable->getPorts(frame.VID); 00119 } else { 00120 for (unsigned int i = 0; i < tmpPortList.size(); i++) { 00121 tmpPort.port = tmpPortList.at(i); 00122 frame.portList.push_back(tmpPort); 00123 } 00124 } 00125 } 00126 00127 //EV << frame; 00128 //error("BLE BLE"); 00129 00130 00131 // LEARNING (explained in reception()) 00132 learn(frame); 00133 // ACTIVE TOPOLOGY ENFORCEMENT (explained in reception()) 00134 if (spanningTree->forwarding(frame.rPort, frame.VID) == true) { 00135 // EGRESS 00136 egress(frame); 00137 // SEND 00138 dispatch(frame); 00139 } 00140 } 00141 00142 bool ANSASwitchCore::ingress(ANSASwitchCore::tFrameDescriptor& tmp, EthernetIIFrame *frame, int rPort) { 00143 // Info from recepted frame 00144 tmp.payload = frame->decapsulate(); 00145 tmp.name.insert(0, frame->getName()); 00146 tmp.rPort = rPort; 00147 tmp.src = frame->getSrc(); 00148 tmp.dest = frame->getDest(); 00149 tmp.etherType = frame->getEtherType(); 00150 00151 // VLAN Assign 00152 tmp.VID = vlanTable->getVID(rPort); 00153 00154 if (tmp.VID == 0) { 00155 return false; 00156 } 00157 00158 00159 return true; 00160 } 00161 00162 bool ANSASwitchCore::ingress(ANSASwitchCore::tFrameDescriptor& tmp, AnsaEtherFrame *frame, int rPort) { 00163 // Info from recepted frame 00164 tmp.payload = frame->decapsulate(); 00165 tmp.name.insert(0, frame->getName()); 00166 tmp.rPort = rPort; 00167 tmp.VID = frame->getVlan(); 00168 tmp.src = frame->getSrc(); 00169 tmp.dest = frame->getDest(); 00170 tmp.etherType = frame->getEtherType(); 00171 00172 // VLAN Allowed 00173 if (vlanTable->isAllowed(frame->getVlan(), rPort) == false) { 00174 return false; 00175 } 00176 00177 return true; 00178 } 00179 00180 void ANSASwitchCore::egress(ANSASwitchCore::tFrameDescriptor& frame) { 00181 // MINIMIZE OUT PORTS 00182 // SET TAG ACTIONS 00183 00184 VLANTable::tVIDPortList tmp = frame.portList; 00185 frame.portList.clear(); 00186 00187 for (unsigned int i = 0; i < tmp.size(); i++) { 00188 if (vlanTable->isAllowed(frame.VID, tmp.at(i).port) == true && tmp.at(i).port != frame.rPort) { 00189 frame.portList.push_back(tmp.at(i)); 00190 } 00191 } 00192 00193 } 00194 00195 void ANSASwitchCore::dispatch(ANSASwitchCore::tFrameDescriptor& frame) { 00196 00197 EthernetIIFrame * untaggedFrame = new EthernetIIFrame(frame.name.c_str()); 00198 AnsaEtherFrame * taggedFrame = new AnsaEtherFrame(frame.name.c_str()); 00199 00200 taggedFrame->setKind(frame.payload->getKind()); 00201 taggedFrame->setSrc(frame.src); 00202 taggedFrame->setDest(frame.dest); 00203 taggedFrame->setByteLength(ETHER_MAC_FRAME_BYTES); 00204 taggedFrame->setVlan(frame.VID); 00205 taggedFrame->setEtherType(frame.etherType); 00206 00207 taggedFrame->encapsulate(frame.payload->dup()); 00208 if (taggedFrame->getByteLength() < MIN_ETHERNET_FRAME) { 00209 taggedFrame->setByteLength(MIN_ETHERNET_FRAME); // "padding" 00210 } 00211 00212 untaggedFrame->setKind(frame.payload->getKind()); 00213 untaggedFrame->setSrc(frame.src); 00214 untaggedFrame->setDest(frame.dest); 00215 untaggedFrame->setByteLength(ETHER_MAC_FRAME_BYTES); 00216 untaggedFrame->setEtherType(frame.etherType); 00217 00218 untaggedFrame->encapsulate(frame.payload->dup()); 00219 if (untaggedFrame->getByteLength() < MIN_ETHERNET_FRAME) { 00220 untaggedFrame->setByteLength(MIN_ETHERNET_FRAME); // "padding" 00221 } 00222 VLANTable::tVIDPortList::iterator it; 00223 for (it = frame.portList.begin(); it != frame.portList.end(); it++) { 00224 if (it->port >= portCount) { 00225 continue; 00226 } 00227 if (spanningTree->forwarding(it->port, frame.VID) == false) { 00228 continue; 00229 } 00230 if (it->action == VLANTable::INCLUDE) { 00231 send(taggedFrame->dup(), "ifOut", it->port); 00232 } else { 00233 send(untaggedFrame->dup(), "ifOut", it->port); 00234 } 00235 } 00236 00237 delete taggedFrame; 00238 delete untaggedFrame; 00239 return; 00240 } 00241 00242 00243 void ANSASwitchCore::learn(ANSASwitchCore::tFrameDescriptor& frame) { 00244 if (spanningTree->learning(frame.rPort, frame.VID) == true) { 00245 addrTable->update(frame.src, frame.rPort); 00246 } 00247 } 00248 00249 00250 00251 void ANSASwitchCore::handleIncomingFrame(EthernetIIFrame *frame) { 00252 // If buffer not full, insert payload frame into buffer and process the frame in parallel. 00253 cMessage *msg = this->currentMsg; 00254 ASSERT(msg->getContextPointer()==NULL); 00255 msg->setContextPointer(frame); 00256 scheduleAt(simTime(), msg); 00257 return; 00258 } 00259 00260 void ANSASwitchCore::processFrame(cMessage *msg) { 00261 EthernetIIFrame *frame = (EthernetIIFrame *) msg->getContextPointer(); 00262 ASSERT(frame); 00263 msg->setContextPointer(NULL); 00264 int inputport = frame->getArrivalGate()->getIndex(); 00265 00266 handleAndDispatchFrame(frame, inputport); 00267 return; 00268 } 00269 00270 void ANSASwitchCore::handleAndDispatchFrame(EthernetIIFrame *frame, int inputport) { 00271 this->addrTable->update(frame->getSrc(), inputport); 00272 00273 /* 00274 AnsaEtherFrame * tmp; 00275 tmp = this->tagMsg(frame, 1); 00276 newframe = this->untagMsg(tmp); 00277 */ 00278 00279 // handle broadcast frames first 00280 if (frame->getDest().isBroadcast()) { 00281 EV<< "Broadcasting broadcast frame " << frame << endl; 00282 broadcastFrame(frame, inputport); 00283 return; 00284 } 00285 00286 // Finds output port of destination address and sends to output port 00287 // if not found then broadcasts to all other ports instead 00288 MACTable::tPortList portList = addrTable->getPorts(frame->getDest()); 00289 00290 if (portList.size() == 0) { 00291 EV << "Dest address " << frame->getDest() << " unknown, broadcasting frame " << frame << endl; 00292 broadcastFrame(frame, inputport); 00293 } else { 00294 for (unsigned int i = 0; i < portList.size(); i++) { 00295 if (inputport != portList.at(i)) { 00296 EV << "Sending frame " << frame << " with dest address " << frame->getDest() << " to port " << portList.at(i) << endl; 00297 send(frame->dup(), "ifOut", portList.at(i)); 00298 } 00299 } 00300 delete frame; 00301 } 00302 00303 return; 00304 } 00305 00306 void ANSASwitchCore::broadcastFrame(EthernetIIFrame *frame, int inputport) { 00307 for (int i = 0; i < this->portCount; ++i) { 00308 if (i != inputport) { 00309 send((EthernetIIFrame*) frame->dup(), "ifOut", i); 00310 } 00311 } 00312 delete frame; 00313 00314 return; 00315 } 00316 00317 void ANSASwitchCore::sinkMsg(cMessage *msg) { 00318 send(msg, "toSink"); 00319 return; 00320 } 00321 00322 00323 void ANSASwitchCore::sinkDupMsg(cMessage *msg) { 00324 send(msg->dup(), "toSink"); 00325 return; 00326 } 00327 00328 void ANSASwitchCore::dispatchBPDU(cMessage *msg, int port) { 00329 if (port >= this->portCount || port < 0) { 00330 return; 00331 } 00332 00333 EthernetIIFrame * untaggedFrame = new EthernetIIFrame(msg->getName()); 00334 00335 untaggedFrame->setKind(msg->getKind()); 00336 untaggedFrame->setSrc(bridgeAddress); 00337 untaggedFrame->setDest(bridgeGroupAddress); 00338 untaggedFrame->setByteLength(ETHER_MAC_FRAME_BYTES); 00339 untaggedFrame->setEtherType(-1); 00340 00341 untaggedFrame->encapsulate((cPacket *)msg); 00342 if (untaggedFrame->getByteLength() < MIN_ETHERNET_FRAME) { 00343 untaggedFrame->setByteLength(MIN_ETHERNET_FRAME); // "padding" 00344 } 00345 00346 00347 send((EthernetIIFrame*) untaggedFrame, "ifOut", port); 00348 } 00349 00350 void ANSASwitchCore::deliverBPDU(ANSASwitchCore::tFrameDescriptor& frame) { 00351 send(frame.payload->dup(), "stpOut", frame.rPort); 00352 } 00353 00354 void ANSASwitchCore::finish() { 00355 cancelAndDelete(this->currentMsg); 00356 return; 00357 } 00358 00359 /* 00360 void ansaSwitchCore::tagMsg(int _vlan) { 00361 00362 EthernetIIFrame * tmp = check_and_cast<EthernetIIFrame *> (this->currentMsg); 00363 00364 cPacket * payload = tmp->decapsulate(); 00365 AnsaEtherFrame * frame = new AnsaEtherFrame(payload->getName()); 00366 00367 frame->setSrc(tmp->getSrc()); // if blank, will be filled in by MAC 00368 frame->setDest(tmp->getDest()); 00369 frame->setByteLength(ETHER_MAC_FRAME_BYTES); 00370 frame->setVlan(_vlan); 00371 00372 frame->encapsulate(tmp); 00373 if (frame->getByteLength() < MIN_ETHERNET_FRAME) { 00374 frame->setByteLength(MIN_ETHERNET_FRAME); // "padding" 00375 } 00376 this->currentMsg = frame; 00377 return; 00378 } 00379 */ 00380 00381 AnsaEtherFrame * ANSASwitchCore::tagMsg(EthernetIIFrame * _frame, int _vlan) { 00382 00383 EthernetIIFrame * tmp = _frame; 00384 00385 cPacket * payload = tmp->decapsulate(); 00386 AnsaEtherFrame * frame = new AnsaEtherFrame(payload->getName()); 00387 00388 frame->setSrc(tmp->getSrc()); 00389 frame->setDest(tmp->getDest()); 00390 frame->setByteLength(ETHER_MAC_FRAME_BYTES); 00391 frame->setVlan(_vlan); 00392 frame->setEtherType(tmp->getEtherType()); 00393 00394 frame->encapsulate(payload); 00395 if (frame->getByteLength() < MIN_ETHERNET_FRAME) { 00396 frame->setByteLength(MIN_ETHERNET_FRAME); // "padding" 00397 } 00398 00399 return frame; 00400 } 00401 00402 EthernetIIFrame * ANSASwitchCore::untagMsg(AnsaEtherFrame * _frame) { 00403 00404 AnsaEtherFrame * tmp = _frame; 00405 00406 cPacket * payload = tmp->decapsulate(); 00407 EthernetIIFrame * frame = new EthernetIIFrame(payload->getName()); 00408 00409 frame->setSrc(tmp->getSrc()); // if blank, will be filled in by MAC 00410 frame->setDest(tmp->getDest()); 00411 frame->setByteLength(ETHER_MAC_FRAME_BYTES); 00412 frame->setEtherType(tmp->getEtherType()); 00413 00414 frame->encapsulate(payload); 00415 if (frame->getByteLength() < MIN_ETHERNET_FRAME) { 00416 frame->setByteLength(MIN_ETHERNET_FRAME); // "padding" 00417 } 00418 return frame; 00419 } 00420 00421 /* 00422 void ansaSwitchCore::untagMsg() { 00423 00424 AnsaEtherFrame * tmp = check_and_cast<AnsaEtherFrame *> (this->currentMsg); 00425 00426 cPacket * payload = tmp->decapsulate(); 00427 EthernetIIFrame * frame = new EthernetIIFrame(payload->getName()); 00428 00429 frame->setSrc(tmp->getSrc()); // if blank, will be filled in by MAC 00430 frame->setDest(tmp->getDest()); 00431 frame->setByteLength(ETHER_MAC_FRAME_BYTES); 00432 00433 frame->encapsulate(tmp); 00434 if (frame->getByteLength() < MIN_ETHERNET_FRAME) { 00435 frame->setByteLength(MIN_ETHERNET_FRAME); // "padding" 00436 } 00437 this->currentMsg = frame; 00438 return; 00439 } 00440 */ 00441