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