|
INET Framework for OMNeT++/OMNEST
|
00001 /* 00002 * Copyright (C) 2003 Andras Varga; CTIE, Monash University, Australia 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU Lesser General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Lesser General Public License 00015 * along with this program; if not, see <http://www.gnu.org/licenses/>. 00016 */ 00017 00018 #include <stdio.h> 00019 #include "EtherEncap.h" 00020 #include "EtherFrame_m.h" 00021 #include "Ieee802Ctrl_m.h" 00022 #include "IInterfaceTable.h" 00023 #include "InterfaceTableAccess.h" 00024 #include "EtherMAC.h" 00025 00026 00027 Define_Module(EtherEncap); 00028 00029 void EtherEncap::initialize() 00030 { 00031 seqNum = 0; 00032 WATCH(seqNum); 00033 00034 totalFromHigherLayer = totalFromMAC = totalPauseSent = 0; 00035 WATCH(totalFromHigherLayer); 00036 WATCH(totalFromMAC); 00037 WATCH(totalPauseSent); 00038 } 00039 00040 void EtherEncap::handleMessage(cMessage *msg) 00041 { 00042 if (msg->arrivedOn("lowerLayerIn")) 00043 { 00044 processFrameFromMAC(check_and_cast<EtherFrame *>(msg)); 00045 } 00046 else 00047 { 00048 // from higher layer 00049 switch(msg->getKind()) 00050 { 00051 case IEEE802CTRL_DATA: 00052 case 0: // default message kind (0) is also accepted 00053 processPacketFromHigherLayer(PK(msg)); 00054 break; 00055 00056 case IEEE802CTRL_SENDPAUSE: 00057 // higher layer want MAC to send PAUSE frame 00058 handleSendPause(msg); 00059 break; 00060 00061 default: 00062 error("received message `%s' with unknown message kind %d", msg->getName(), msg->getKind()); 00063 } 00064 } 00065 00066 if (ev.isGUI()) 00067 updateDisplayString(); 00068 } 00069 00070 void EtherEncap::updateDisplayString() 00071 { 00072 char buf[80]; 00073 sprintf(buf, "passed up: %ld\nsent: %ld", totalFromMAC, totalFromHigherLayer); 00074 getDisplayString().setTagArg("t",0,buf); 00075 } 00076 00077 void EtherEncap::processPacketFromHigherLayer(cPacket *msg) 00078 { 00079 if (msg->getByteLength() > MAX_ETHERNET_DATA) 00080 error("packet from higher layer (%d bytes) exceeds maximum Ethernet payload length (%d)", (int)msg->getByteLength(), MAX_ETHERNET_DATA); 00081 00082 totalFromHigherLayer++; 00083 00084 // Creates MAC header information and encapsulates received higher layer data 00085 // with this information and transmits resultant frame to lower layer 00086 00087 // create Ethernet frame, fill it in from Ieee802Ctrl and encapsulate msg in it 00088 EV << "Encapsulating higher layer packet `" << msg->getName() <<"' for MAC\n"; 00089 00090 Ieee802Ctrl *etherctrl = check_and_cast<Ieee802Ctrl*>(msg->removeControlInfo()); 00091 EthernetIIFrame *frame = new EthernetIIFrame(msg->getName()); 00092 00093 frame->setSrc(etherctrl->getSrc()); // if blank, will be filled in by MAC 00094 frame->setDest(etherctrl->getDest()); 00095 frame->setEtherType(etherctrl->getEtherType()); 00096 frame->setByteLength(ETHER_MAC_FRAME_BYTES); 00097 delete etherctrl; 00098 00099 frame->encapsulate(msg); 00100 if (frame->getByteLength() < MIN_ETHERNET_FRAME) 00101 frame->setByteLength(MIN_ETHERNET_FRAME); // "padding" 00102 00103 send(frame, "lowerLayerOut"); 00104 } 00105 00106 void EtherEncap::processFrameFromMAC(EtherFrame *frame) 00107 { 00108 totalFromMAC++; 00109 00110 // decapsulate and attach control info 00111 cPacket *higherlayermsg = frame->decapsulate(); 00112 00113 // add Ieee802Ctrl to packet 00114 Ieee802Ctrl *etherctrl = new Ieee802Ctrl(); 00115 etherctrl->setSrc(frame->getSrc()); 00116 etherctrl->setDest(frame->getDest()); 00117 higherlayermsg->setControlInfo(etherctrl); 00118 00119 EV << "Decapsulating frame `" << frame->getName() <<"', passing up contained " 00120 "packet `" << higherlayermsg->getName() << "' to higher layer\n"; 00121 00122 // pass up to higher layers. 00123 send(higherlayermsg, "upperLayerOut"); 00124 delete frame; 00125 } 00126 00127 void EtherEncap::handleSendPause(cMessage *msg) 00128 { 00129 Ieee802Ctrl *etherctrl = dynamic_cast<Ieee802Ctrl*>(msg->removeControlInfo()); 00130 if (!etherctrl) 00131 error("PAUSE command `%s' from higher layer received without Ieee802Ctrl", msg->getName()); 00132 int pauseUnits = etherctrl->getPauseUnits(); 00133 delete etherctrl; 00134 00135 EV << "Creating and sending PAUSE frame, with duration=" << pauseUnits << " units\n"; 00136 00137 // create Ethernet frame 00138 char framename[30]; 00139 sprintf(framename, "pause-%d-%d", getId(), seqNum++); 00140 EtherPauseFrame *frame = new EtherPauseFrame(framename); 00141 frame->setPauseTime(pauseUnits); 00142 00143 frame->setByteLength(ETHER_MAC_FRAME_BYTES+ETHER_PAUSE_COMMAND_BYTES); 00144 if (frame->getByteLength() < MIN_ETHERNET_FRAME) 00145 frame->setByteLength(MIN_ETHERNET_FRAME); 00146 00147 send(frame, "lowerLayerOut"); 00148 delete msg; 00149 00150 totalPauseSent++; 00151 } 00152 00153 void EtherEncap::finish() 00154 { 00155 recordScalar("packets from higher layer", totalFromHigherLayer); 00156 recordScalar("frames from MAC", totalFromMAC); 00157 } 00158 00159