00001
00002
00003 #include "CSMAMacLayer.h"
00004 #include "FWMath.h"
00005 #include "MacToPhyControlInfo.h"
00006 #include <BaseArp.h>
00007 #include <BaseConnectionManager.h>
00008
00009 Define_Module( CSMAMacLayer )
00010
00011
00015 void CSMAMacLayer::initialize(int stage)
00016 {
00017 BaseMacLayer::initialize(stage);
00018
00019 if (stage == 0) {
00020
00021 queueLength = hasPar("queueLength") ? par("queueLength").longValue() : 10;
00022
00023 slotDuration = hasPar("slotDuration") ? par("slotDuration").doubleValue() : 0.1;
00024 difs = hasPar("difs") ? par("difs").doubleValue() : 0.001;
00025 maxTxAttempts = hasPar("maxTxAttempts") ? par("maxTxAttempts").longValue() : 7;
00026 bitrate = hasPar("bitrate") ? par("bitrate").doubleValue() : 10000;
00027 txPower = hasPar("txPower") ? par("txPower").doubleValue() : 50;
00028 initialCW = hasPar("contentionWindow") ? par("contentionWindow").longValue(): 31;
00029
00030 macState = RX;
00031
00032
00033
00034
00035
00036
00037 backoffTimer = new cMessage("backoff");
00038 minorMsg = new cMessage("minClear");
00039
00040 nbBackoffs = 0;
00041 backoffValues = 0;
00042 nbTxFrames = 0;
00043
00044 txAttempts = 0;
00045 }
00046 else if(stage == 1) {
00047 BaseConnectionManager* cc = getConnectionManager();
00048
00049 if(cc->hasPar("pMax") && txPower > cc->par("pMax").doubleValue())
00050 opp_error("TranmitterPower can't be bigger than pMax in ConnectionManager! "
00051 "Please adjust your omnetpp.ini file accordingly.");
00052
00053 if(phy->getRadioState() != Radio::RX) {
00054 opp_error("Initial radio state isn't RX but CSMAMacLayer"
00055 " assumes that the NIC starts in RX state.");
00056 }
00057
00058 debugEV << "queueLength = " << queueLength
00059
00060 << " slotDuration = " << slotDuration
00061 << " difs = " << difs
00062 << " maxTxAttempts = " << maxTxAttempts
00063 << " bitrate = " << bitrate
00064 << " contentionWindow = " << initialCW << endl;
00065
00066
00067 }
00068 }
00069
00070 CSMAMacLayer::~CSMAMacLayer() {
00071 cancelAndDelete(backoffTimer);
00072 cancelAndDelete(minorMsg);
00073
00074 for(MacQueue::iterator it = macQueue.begin();
00075 it != macQueue.end(); ++it)
00076 {
00077 delete (*it);
00078 }
00079 macQueue.clear();
00080 }
00081
00082 void CSMAMacLayer::finish() {
00083 recordScalar("nbBackoffs", nbBackoffs);
00084 recordScalar("backoffDurations", backoffValues);
00085 recordScalar("nbTxFrames", nbTxFrames);
00086
00087
00088 }
00089
00103 void CSMAMacLayer::handleUpperMsg(cMessage *msg)
00104 {
00105 cPacket* pkt = static_cast<cPacket*>(msg);
00106
00107
00108
00109
00110
00111
00112 if (macQueue.size() <= queueLength)
00113 {
00114 macQueue.push_back(pkt);
00115 debugEV << "packet putt in queue\n queue size:" << macQueue.size() << " macState:" << macState
00116 << " (RX=" << RX << ") is scheduled:" << backoffTimer->isScheduled() << endl;;
00117
00118 if((macQueue.size() == 1) && (macState == RX) && !backoffTimer->isScheduled()) {
00119 scheduleBackoff();
00120 }
00121 }
00122 else {
00123
00124 EV << "New packet arrived, but queue is FULL, so new packet is deleted\n";
00125 MacPkt* mac = encapsMsg(pkt);
00126 mac->setName("MAC ERROR");
00127 mac->setKind(PACKET_DROPPED);
00128 sendControlUp(mac);
00129
00130
00131
00132
00133 }
00134 }
00135
00140 void CSMAMacLayer::handleSelfMsg(cMessage *msg)
00141 {
00142 if(msg == backoffTimer) {
00143 debugEV << "backoffTimer ";
00144
00145 if(macState == RX) {
00146 debugEV << " RX ";
00147
00148 if(macQueue.size() != 0) {
00149 macState = CCA;
00150
00151 if(phy->getRadioState() == Radio::RX) {
00152
00153 if(phy->getChannelState().isIdle()) {
00154 debugEV << " idle ";
00155 scheduleAt(simTime()+difs, minorMsg);
00156 }
00157 else{
00158 macState = RX;
00159 debugEV << " busy ";
00160 scheduleBackoff();
00161 }
00162 }
00163 }
00164 }
00165 else {
00166 debugEV << "" << endl;
00167 debugEV << "state=" << macState << "(TX="<<TX<<", CCA="<<CCA<<")\n";
00168 error("backoffTimer expired, MAC in wrong state");
00169 }
00170 }
00171 else if(msg == minorMsg) {
00172 debugEV << " minorMsg ";
00173
00174
00175 if((macState == CCA) && (phy->getRadioState() == Radio::RX)) {
00176
00177 if(phy->getChannelState().isIdle()) {
00178 debugEV << " idle -> to send ";
00179 macState = TX;
00180 phy->setRadioState(Radio::TX);
00181 }
00182 else {
00183 debugEV << " busy -> backoff ";
00184 macState = RX;
00185 if(!backoffTimer->isScheduled())
00186 scheduleBackoff();
00187 }
00188 }
00189 else {
00190 error("minClearTimer fired -- channel or mac in wrong state");
00191 }
00192 }
00193 debugEV << endl;
00194 }
00195
00196
00202 void CSMAMacLayer::handleLowerMsg(cMessage *msg)
00203 {
00204 MacPkt *mac = static_cast<MacPkt *>(msg);
00205 int dest = mac->getDestAddr();
00206
00207 if(dest == myMacAddr || dest == L2BROADCAST)
00208 {
00209 debugEV << "sending pkt to upper...\n";
00210 sendUp(decapsMsg(mac));
00211 }
00212 else {
00213 debugEV << "packet not for me, deleting...\n";
00214 delete mac;
00215 }
00216
00217 if(!backoffTimer->isScheduled()) scheduleBackoff();
00218 }
00219
00220 void CSMAMacLayer::handleLowerControl(cMessage *msg)
00221 {
00222 if(msg->getKind() == MacToPhyInterface::TX_OVER) {
00223 debugEV << " transmission over" << endl;
00224 macState = RX;
00225 phy->setRadioState(Radio::RX);
00226 txAttempts = 0;
00227 if(!backoffTimer->isScheduled()) scheduleBackoff();
00228 }
00229 else if(msg->getKind() == MacToPhyInterface::RADIO_SWITCHING_OVER) {
00230 if((macState == TX) && (phy->getRadioState() == Radio::TX)) {
00231 debugEV << " radio switched to tx, sendDown packet" << endl;
00232 nbTxFrames++;
00233 sendDown(encapsMsg(macQueue.front()));
00234 macQueue.pop_front();
00235 }
00236 }
00237 else {
00238 EV << "control message with wrong kind -- deleting\n";
00239 }
00240 delete msg;
00241 }
00242
00243 void CSMAMacLayer::scheduleBackoff()
00244 {
00245 if(backoffTimer->isScheduled()) {
00246 std::cerr << " is scheduled: MAC state "
00247 << macState << " radio state : " << phy->getRadioState() << endl;
00248 }
00249
00250 if(minorMsg->isScheduled()){
00251 cancelEvent( minorMsg );
00252 macState=RX;
00253 }
00254
00255 if(txAttempts > maxTxAttempts) {
00256 debugEV << " drop packet " << endl;
00257
00258 cMessage *mac = encapsMsg(macQueue.front());
00259 mac->setName("MAC ERROR");
00260 mac->setKind(PACKET_DROPPED);
00261 txAttempts = 0;
00262 macQueue.pop_front();
00263 sendControlUp(mac);
00264
00265
00266
00267
00268 }
00269
00270 if(macQueue.size() != 0) {
00271 debugEV << " schedule backoff " << endl;
00272
00273 double slots = intrand(initialCW + txAttempts) + 1.0 + dblrand();
00274 double time = slots * slotDuration;
00275
00276 txAttempts++;
00277 debugEV << " attempts so far: " << txAttempts << " " << endl;
00278
00279 nbBackoffs = nbBackoffs + 1;
00280 backoffValues = backoffValues + time;
00281
00282 scheduleAt(simTime() + time, backoffTimer);
00283 }
00284
00285 }
00286
00287 MacPkt* CSMAMacLayer::encapsMsg(cPacket *pkt)
00288 {
00289 MacPkt* macPkt = BaseMacLayer::encapsMsg(pkt);
00290
00291
00292 simtime_t duration = macPkt->getBitLength() / bitrate;
00293
00294 if(duration > slotDuration) {
00295 EV << "Warning: Sending packet " << pkt
00296 << " - duration (" << duration
00297 << " ) is bigger than the slot duration (" << slotDuration
00298 <<")." << endl;
00299 }
00300
00301
00302 Signal* s = createSignal(simTime(), duration, txPower, bitrate);
00303
00304
00305 MacToPhyControlInfo* ctrl = new MacToPhyControlInfo(s);
00306
00307 macPkt->setControlInfo(ctrl);
00308
00309 return macPkt;
00310 }
00311
00312
00313