📄 mac-timers_802_11e.cc
字号:
//* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- *//* * Copyright (c) 1997 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the Computer Systems * Engineering Group at Lawrence Berkeley Laboratory. * 4. Neither the name of the University nor of the Laboratory may be used * to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. *//* Ported from CMU/Monarch's code, nov'98 -Padma.*/#undef NDEBUG#include <assert.h>#include <delay.h>#include <connector.h>#include <packet.h>#include <random.h>#include <iostream.h>#define DEBUG_ 0#define BACKOFF_CHECK 0//#include <debug.h>#include <arp.h>#include <ll.h>#include <mac.h>#include <mac/802_11e/mac-timers_802_11e.h>#include <mac/802_11e/mac-802_11e.h> #define inf (1e12)#define round (1e-12)/* * Force timers to expire on slottime boundries. */// #define USE_SLOT_TIME#define ROUND_TIME() \ { \ assert(slottime); \ double rmd = remainder(s.clock() + rtime, slottime); \ if(rmd > 0.0) \ rtime += (slottime - rmd); \ else \ rtime += (-rmd); \ }/* ====================================================================== Timers ====================================================================== */voidMacTimer_802_11e::start(double time){ Scheduler &s = Scheduler::instance(); assert(busy_ == 0); busy_ = 1; paused_ = 0; stime = s.clock(); rtime = time; assert(rtime >= 0.0); s.schedule(this, &intr, rtime);}voidMacTimer_802_11e::stop(void){ Scheduler &s = Scheduler::instance(); assert(busy_); if(paused_ == 0) s.cancel(&intr); busy_ = 0; paused_ = 0; stime = 0.0; rtime = 0.0;}/* ====================================================================== Defer Timer ====================================================================== */voidDeferTimer_802_11e::start(int pri, double time){ Scheduler &s = Scheduler::instance(); int another = 0; assert(defer_[pri] == 0); for(int i = 0; i < MAX_PRI; i++ ){ if(defer_[i] && busy_) { another = 1; } } if(another){ pause(); } busy_ = 1; defer_[pri] = 1; stime_[pri] = s.clock(); rtime_[pri] = time; double delay = inf; int prio = MAX_PRI + 1; for(int pri = 0; pri < MAX_PRI; pri++){ if(defer_[pri]){ stime_[pri] = s.clock(); double delay_ = rtime_[pri]; if((delay_ < delay)) { delay = delay_; prio = pri; } } } if(prio < MAX_PRI + 1) { assert(rtime_[prio] >=0); s.schedule(this, &intr, rtime_[prio]); paused_ = 0; } else { exit(0); }}void DeferTimer_802_11e::stop(){ busy_ = 0; for(int pri = 0; pri < MAX_PRI;pri++){ if(defer_[pri]) mac->defer_stop(pri); defer_[pri] = 0; stime_[pri] = 0; rtime_[pri] = 0; } Scheduler &s = Scheduler::instance(); s.cancel(&intr);}voidDeferTimer_802_11e::pause(){ Scheduler &s = Scheduler::instance(); for(int pri = 0; pri < MAX_PRI; pri++ ){ if(defer_[pri] && busy_){ double st = s.clock(); //now double rt = stime_[pri]; // Start-Time of defer double sr = st - rt; assert(busy_ && ! paused_); if(rtime_[pri] - sr >= 0.0) { rtime_[pri] -= sr; assert(rtime_[pri] >= 0.0); } else{ if(rtime_[pri] + round - sr >= 0.0){ rtime_[pri] = 0; } else { cout<<"ERROR in DeferTimer::pause(), rtime_["<<pri<<"] is "<<rtime_[pri]<<", sr:"<<sr<<" \n"; exit(0); } } } } s.cancel(&intr); paused_ = 1;}void DeferTimer_802_11e::handle(Event *){ Scheduler &s = Scheduler::instance(); double delay = inf; int prio = MAX_PRI + 1; for( int pri = 0; pri < MAX_PRI; pri++) { if(rtime_[pri] >= 0 && defer_[pri]){ double delay_ = rtime_[pri]; if((delay_ < delay) && defer_[pri]) { delay = delay_; prio = pri; } } } if(prio < MAX_PRI + 1){ busy_ = 0; paused_ = 0; defer_[prio] = 0; stime_[prio] = 0.0; rtime_[prio] = 0.0; mac->deferHandler(prio); } else { cout<<"handling ERROR in DeferTimer::handler \n"; exit(0); } //check if there is another DeferTimer active for( int pri = 0; pri < MAX_PRI; pri++) { if(rtime_[pri] >= 0 && defer_[pri]){ rtime_[pri] = 0.0; stime_[pri] = 0.0; defer_[pri] = 0; mac->defer_stop(pri); } } }intDeferTimer_802_11e::defer(int pri) { return defer_[pri];}/* ====================================================================== NAV Timer ====================================================================== */void NavTimer_802_11e::handle(Event *){ busy_ = 0; paused_ = 0; stime = 0.0; rtime = 0.0; mac->navHandler();}/* ====================================================================== Receive Timer ====================================================================== */void RxTimer_802_11e::handle(Event *){ busy_ = 0; paused_ = 0; stime = 0.0; rtime = 0.0; mac->recvHandler();}/* ====================================================================== Send Timer ====================================================================== */void TxTimer_802_11e::handle(Event *){ busy_ = 0; paused_ = 0; stime = 0.0; rtime = 0.0; mac->sendHandler();}/* ====================================================================== Interface Timer ====================================================================== */voidIFTimer_802_11e::handle(Event *){ Scheduler &s = Scheduler::instance(); busy_ = 0; paused_ = 0; stime = 0.0; rtime = 0.0; mac->txHandler(); }/* ====================================================================== Defer Timer for SIFS ====================================================================== */voidSIFSTimer_802_11e::start(int pri, double time){ Scheduler &s = Scheduler::instance(); if(busy_ == 1){cout<<"Mac "<<mac->index_<<", ERROR in SIFSTimer!"; exit(0);} assert(sifs_[pri] == 0); busy_ = 1; sifs_[pri] = 1; stime_[pri] = s.clock(); rtime_[pri] = time; s.schedule(this, &intr, rtime_[pri]);}voidSIFSTimer_802_11e::handle(Event *){ Scheduler &s = Scheduler::instance(); busy_ = 0; prio = 0; for(int pri = 0; pri < MAX_PRI; pri++){ if(sifs_[pri]) { prio = pri; break; } } for(int i = 0; i < MAX_PRI; i++){ sifs_[i] = 0; stime_[i] = 0.0; rtime_[i] = 0.0; } mac->deferHandler(prio); }/* ====================================================================== Backoff Timer ====================================================================== */inline void BackoffTimer_802_11e::round_time(int pri){ double rmd = remainder(rtime_[pri], mac->phymib_->SlotTime); if(rmd<0){ rmd = 0; } assert(rmd>=0); if(rmd < (mac->phymib_->SlotTime /10)) if(rtime_[pri] -rmd >= 0) rtime_[pri] -= rmd; else rtime_[pri] = 0; else if(rmd > (mac->phymib_->SlotTime - (mac->phymib_->SlotTime /10))) rtime_[pri] += (mac->phymib_->SlotTime - rmd); else{ cout<<"ERROR in Backoff::round_time(): Mac "<<mac->index_<<" rtime_["<<pri<<"] is "<<rtime_[pri]<<", remainder: "<<rmd<<"\n"; exit(3); }}voidBackoffTimer_802_11e::handle(Event *){ Scheduler &s = Scheduler::instance(); paused_ = 0; double delay = inf; int prio = MAX_PRI + 1; for(int pri = 0; pri < MAX_PRI; pri++){ double delay_ = rtime_[pri] + AIFSwait_[pri]; if((delay_ < delay) && backoff_[pri]) { delay = delay_; prio = pri; } } if(prio < MAX_PRI + 1) { busy_ = 0; stime_[prio] = 0; rtime_[prio] = 0; backoff_[prio] = 0; AIFSwait_[prio] = 0.0; //mac->backoffHandler(prio); now done further down at the end of Handler! } else { cout<<"ERROR: wrong priority in BackoffTimer::handler()"; exit(0); } busy_ = 0; for(int pri = 0; pri < MAX_PRI; pri++){ if(backoff_[pri]) { //check if there is another backoff process busy_ = 1; if(rtime_[pri] + AIFSwait_[pri] == delay) { mac->inc_cw(pri); AIFSwait_[pri] = 0; stime_[pri] = s.clock(); //Start-Time rtime_[pri] = (Random::random() % (mac->getCW(pri) + 1)) * mac->phymib_->SlotTime; backoff_[pri] = 1; } } } if(busy_ && !paused_){ pause(); //pause + restart because the backoff could be a postbackoff! restart(); } mac->backoffHandler(prio); }voidBackoffTimer_802_11e::start(int pri, int cw, int idle){ Scheduler &s = Scheduler::instance(); if(busy_) { //already a backoff running! offset_[pri] = 0; stime_[pri] = s.clock(); //Start-Time rtime_[pri] = (Random::random() % (cw + 1)) * mac->phymib_->SlotTime; AIFSwait_[pri] = 0.0; backoff_[pri] = 1; if(idle == 0){ if(!paused_){ pause(); } } else { assert(rtime_[pri] >= 0.0); if(!paused_) { pause(); AIFSwait_[pri] = mac->getAIFS(pri); //cout<<"Mac "<<mac->index_<<": now: "<<Scheduler::instance().clock()<<"pause and restart for prio "<<pri<<"\n"; restart(); } } } else { backoff_[pri] = 1; busy_ = 1; offset_[pri] = 0; stime_[pri] = s.clock(); //Start-Time rtime_[pri] = (Random::random() % (cw + 1)) * mac->phymib_->SlotTime; AIFSwait_[pri] = mac->getAIFS(pri); if(idle == 0){ paused_ = 1; } else { assert(rtime_[pri] >= 0.0); s.schedule(this, &intr, rtime_[pri] + AIFSwait_[pri]); } }}voidBackoffTimer_802_11e::pause(){ Scheduler &s = Scheduler::instance(); //the caculation below make validation pass for linux though it // looks dummy for (int pri = 0; pri < MAX_PRI; pri++) { if(backoff_[pri]) { double st = s.clock(); //now double rt = stime_[pri] + AIFSwait_[pri]; // Start-Time des Backoffs + waiting time double sr = st - rt; double mst = (mac->phymib_->SlotTime); int slots = int (sr/mst); if(slots < 0) slots = 0; if(sr >= 0) offset_[pri] = sr - (slots * mst); assert(offset_[pri] >= 0); assert(busy_ && ! paused_); if(rtime_[pri] - (slots * mac->phymib_->SlotTime) >= 0.0) { rtime_[pri] -= (slots * mac->phymib_->SlotTime); assert(rtime_[pri] >= 0.0); } else{ if(rtime_[pri] + round - (slots * mac->phymib_->SlotTime) >= 0.0) { rtime_[pri] = 0; } else { cout<<"ERROR in BackoffTimer::pause(), rtime_["<<pri<<"] is "<<rtime_[pri]<<", slots: "<<slots<<", SlotTime: "<<mac->phymib_->SlotTime<<" \n"; exit(0); } } if(st - stime_[pri] >= mac->getAIFS(pri)) AIFSwait_[pri] = 0.0; else{ AIFSwait_[pri] -= st - stime_[pri]; if(AIFSwait_[pri] < 0) AIFSwait_[pri] = 0; //cout<<"Mac "<<mac->index_<<", now: "<<Scheduler::instance().clock()<<", setting AIFSwait_["<<pri<<"] to "<<AIFSwait_[pri]<<"\n"; } } } s.cancel(&intr); paused_ = 1;}voidBackoffTimer_802_11e::resume(){ double delay = inf; int prio = MAX_PRI + 1; Scheduler &s = Scheduler::instance(); for(int pri = 0; pri < MAX_PRI; pri++){ if(backoff_[pri]){ offset_[pri] = 0; round_time(pri); AIFSwait_[pri] = mac->getAIFS(pri); stime_[pri] = s.clock(); double delay_ = rtime_[pri] + AIFSwait_[pri]; if((delay_ < delay) && backoff_[pri]) { delay = delay_; prio = pri; } } } if(prio < MAX_PRI + 1) { assert(rtime_[prio] + AIFSwait_[prio] >=0); s.schedule(this, &intr, rtime_[prio] + AIFSwait_[prio]); paused_ = 0; } else { cout<<"ERROR: wrong priority in BackoffTimer::resume() \n"; exit(0); }}voidBackoffTimer_802_11e::restart(){ busy_ = 1; double delay = inf; int prio = MAX_PRI + 1; Scheduler &s = Scheduler::instance(); for(int pri = 0; pri < MAX_PRI; pri++){ if(backoff_[pri]) { if(rtime_[pri] > offset_[pri]) rtime_[pri] -= offset_[pri]; offset_[pri] = 0; round_time(pri); stime_[pri] = s.clock(); double delay_ = rtime_[pri] + AIFSwait_[pri]; if(delay_ < delay) { delay = delay_; prio = pri; } } } if(prio < MAX_PRI + 1) { assert(rtime_[prio] + AIFSwait_[prio] >=0); s.schedule(this, &intr, rtime_[prio] + AIFSwait_[prio]); paused_ = 0; } else { cout<<"ERROR: wrong priority in BackoffTimer::restart() \n"; exit(0); }}intBackoffTimer_802_11e::backoff(int pri){ return backoff_[pri];}/* * Timer for throughput measurement */ void AkaroaTimer::start(){ Scheduler &s = Scheduler::instance(); s.schedule(this, &intr,mac->interval_);}void AkaroaTimer::handle(Event *){ mac->calc_throughput();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -