Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

EtherEncap.cc

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2003 CTIE, Monash University
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU 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 General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017 */
00018 
00019 #ifdef _MSC_VER
00020 #pragma warning(disable:4786)
00021 #endif
00022 
00023 #include <stdio.h>
00024 #include <omnetpp.h>
00025 
00026 #include "Ethernet.h"
00027 #include "EtherFrame_m.h"
00028 #include "EtherCtrl_m.h"
00029 #include "utils.h"
00030 
00031 
00035 class EtherEncap : public cSimpleModule
00036 {
00037   protected:
00038     int seqNum;
00039 
00040     // statistics
00041     long totalFromHigherLayer;  // total number of packets received from higher layer
00042     long totalFromMAC;          // total number of frames received from MAC
00043     long totalPauseSent;        // total number of PAUSE frames sent
00044 
00045   public:
00046     Module_Class_Members(EtherEncap,cSimpleModule,0);
00047 
00048     virtual void initialize();
00049     virtual void handleMessage(cMessage *msg);
00050     virtual void finish();
00051 
00052     virtual void processPacketFromHigherLayer(cMessage *msg);
00053     virtual void processFrameFromMAC(EtherFrame *msg);
00054     virtual void handleSendPause(cMessage *msg);
00055 
00056 };
00057 
00058 Define_Module(EtherEncap);
00059 
00060 void EtherEncap::initialize()
00061 {
00062     seqNum = 0;
00063     WATCH(seqNum);
00064 
00065     totalFromHigherLayer = totalFromMAC = totalPauseSent = 0;
00066     WATCH(totalFromHigherLayer);
00067     WATCH(totalFromMAC);
00068     WATCH(totalPauseSent);
00069 }
00070 
00071 void EtherEncap::handleMessage(cMessage *msg)
00072 {
00073     if (msg->arrivedOn("lowerLayerIn"))
00074     {
00075         processFrameFromMAC(check_and_cast<EtherFrame *>(msg));
00076     }
00077     else
00078     {
00079         // from higher layer
00080         switch(msg->kind())
00081         {
00082             case 0:  //FIXME
00083             case ETHCTRL_DATA:
00084               processPacketFromHigherLayer(msg);
00085               break;
00086 
00087             case ETHCTRL_SENDPAUSE:
00088               // higher layer want MAC to send PAUSE frame
00089               handleSendPause(msg);
00090               break;
00091 
00092             default:
00093               error("received message `%s' with unknown message kind %d", msg->name(), msg->kind());
00094         }
00095     }
00096 }
00097 
00098 void EtherEncap::processPacketFromHigherLayer(cMessage *msg)
00099 {
00100     if (msg->length()>8*MAX_ETHERNET_DATA)
00101         error("packet from higher layer (%d bytes) exceeds maximum Ethernet payload length (%d)", msg->length()/8, MAX_ETHERNET_DATA);
00102 
00103     totalFromHigherLayer++;
00104 
00105     // Creates MAC header information and encapsulates received higher layer data
00106     // with this information and transmits resultant frame to lower layer
00107 
00108     // create Ethernet frame, fill it in from EtherCtrl and encapsulate msg in it
00109     EV << "Encapsulating higher layer packet `" << msg->name() <<"' for MAC\n";
00110     EV << "Sent from " << simulation.module(msg->senderModuleId())->fullPath() << " at " << msg->sendingTime() << " and was created " << msg->creationTime() <<  "\n";
00111 
00112     EtherCtrl *etherctrl = check_and_cast<EtherCtrl*>(M30(msg)->removeControlInfo());
00113     EthernetIIFrame *frame = new EthernetIIFrame(msg->name(), ETH_FRAME);
00114 
00115     frame->setSrc(etherctrl->getSrc());  // if blank, will be filled in by MAC
00116     frame->setDest(etherctrl->getDest());
00117     frame->setEtherType(etherctrl->getEtherType());
00118     frame->setLength(8*ETHER_MAC_FRAME_BYTES);
00119     delete etherctrl;
00120 
00121     frame->encapsulate(msg);
00122     if (frame->length() < 8*MIN_ETHERNET_FRAME)
00123         frame->setLength(8*MIN_ETHERNET_FRAME);  // "padding"
00124 
00125     send(frame, "lowerLayerOut");
00126 }
00127 
00128 void EtherEncap::processFrameFromMAC(EtherFrame *frame)
00129 {
00130     totalFromMAC++;
00131 
00132     // decapsulate and attach control info
00133     cMessage *higherlayermsg = frame->decapsulate();
00134 
00135     // add EtherCtrl to packet
00136     EtherCtrl *etherctrl = new EtherCtrl();
00137     etherctrl->setSrc(frame->getSrc());
00138     etherctrl->setDest(frame->getDest());
00139     M30(higherlayermsg)->setControlInfo(etherctrl);
00140 
00141     EV << "Decapsulating frame `" << frame->name() <<"', passing up contained "
00142           "packet `" << higherlayermsg->name() << "' to higher layer\n";
00143 
00144     // pass up to higher layers.
00145     send(higherlayermsg, "upperLayerOut");
00146     delete frame;
00147 }
00148 
00149 void EtherEncap::handleSendPause(cMessage *msg)
00150 {
00151     EtherCtrl *etherctrl = check_and_cast<EtherCtrl*>(M30(msg)->removeControlInfo());
00152     int pauseUnits = etherctrl->getPauseUnits();
00153     delete etherctrl;
00154 
00155     EV << "Creating and sending PAUSE frame, with duration=" << pauseUnits << " units\n";
00156 
00157     // create Ethernet frame
00158     char framename[30];
00159     sprintf(framename, "pause-%d-%d", id(), seqNum++);
00160     EtherPauseFrame *frame = new EtherPauseFrame(framename, ETH_PAUSE);
00161     frame->setPauseTime(pauseUnits);
00162 
00163     frame->setLength(8*(ETHER_MAC_FRAME_BYTES+ETHER_PAUSE_COMMAND_BYTES));
00164     if (frame->length() < 8*MIN_ETHERNET_FRAME)
00165         frame->setLength(8*MIN_ETHERNET_FRAME);
00166 
00167     send(frame, "lowerLayerOut");
00168     delete msg;
00169 
00170     totalPauseSent++;
00171 }
00172 
00173 void EtherEncap::finish()
00174 {
00175     if (par("writeScalars").boolValue())
00176     {
00177         recordScalar("packets from higher layer", totalFromHigherLayer);
00178         recordScalar("frames from MAC", totalFromMAC);
00179     }
00180 }
00181 

Generated on Sat May 15 20:30:42 2004 for Ethernet by doxygen1.2.17