?? smac.cc
字號:
/*
* smac.cc
* Copyright (C) 2000 by the University of Southern California
* $Id: smac.cc,v 1.18 2005/12/10 17:57:13 liyuan Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*
*
* The copyright of this module includes the following
* linking-with-specific-other-licenses addition:
*
* In addition, as a special exception, the copyright holders of
* this module give you permission to combine (via static or
* dynamic linking) this module with free software programs or
* libraries that are released under the GNU LGPL and with code
* included in the standard release of ns-2 under the Apache 2.0
* license or under otherwise-compatible licenses with advertising
* requirements (or modified versions of such code, with unchanged
* license). You may copy and distribute such a system following the
* terms of the GNU GPL for this module and the licenses of the
* other code concerned, provided that you include the source code of
* that other code when and as the GNU GPL requires distribution of
* source code.
*
* Note that people who make modified versions of this module
* are not obligated to grant this special exception for their
* modified versions; it is their choice whether to do so. The GNU
* General Public License gives permission to release a modified
* version without this exception; this exception also makes it
* possible to release a modified version which carries forward this
* exception.
*
*/
// smac is designed and developed by Wei Ye (SCADDS/ISI)
// and is re-written for ns by Padma Haldar (CONSER/ISI).
// Contributors: Yuan Li
// This module implements Sensor-MAC
// http://www.isi.edu/scadds/papers/smac_report.pdf
//
// It has the following functions.
// 1) Both virtual and physical carrier sense
// 2) RTS/CTS for hidden terminal problem
// 3) Backoff and retry
// 4) Broadcast packets are sent directly without using RTS/CTS/ACK.
// 5) A long unicast message is divided into multiple TOS_MSG (by upper
// layer). The RTS/CTS reserves the medium for the entire message.
// ACK is used for each TOS_MSG for immediate error recovery.
// 6) Node goes to sleep when its neighbor is communicating with another
// node.
// 7) Each node follows a periodic listen/sleep schedule
// 8.1) At bootup time each node listens for a fixed SYNCPERIOD and then
// tries to send out a sync packet. It suppresses sending out of sync pkt
// if it happens to receive a sync pkt from a neighbor and follows the
// neighbor's schedule.
// 8.2) Or a node can choose its own schecule instead of following others, the
// schedule start time is user configurable
// 9) Neighbor Discovery: in order to prevent that two neighbors can not
// find each other due to following complete different schedules, each
// node periodically listen for a whole period of the SYNCPERIOD
// 10) Duty cycle is user configurable
// New features including adaptive listen
// See http://www.isi.edu/~weiye/pub/smac_ton.pdf
#include "wireless-phy.h"
#include "smac.h"
static class MacSmacClass : public TclClass {
public:
MacSmacClass() : TclClass("Mac/SMAC") {}
TclObject* create(int, const char*const*) {
return (new SMAC());
}
} class_macSMAC;
// Timers call on expiration
int SmacTimer::busy()
{
if (status_ != TIMER_PENDING)
return 0;
else
return 1;
}
#ifdef JOURNAL_PAPER
void SmacUpdateNeighbTimer::expire(Event *e) {
a_->handleUpdateNeighbTimer();
}
void SmacAdaptiveListenTimer::expire(Event *e) {
a_->handleAdaptiveListenTimer();
}
#endif
void SmacGeneTimer::expire(Event *e) {
a_->handleGeneTimer();
}
void SmacRecvTimer::expire(Event *e) {
stime_ = rtime_ = 0;
a_->handleRecvTimer();
}
void SmacRecvTimer::sched(double time) {
TimerHandler::sched(time);
stime_ = Scheduler::instance().clock();
rtime_ = time;
}
void SmacRecvTimer::resched(double time) {
TimerHandler::resched(time);
stime_ = Scheduler::instance().clock();
rtime_ = time;
}
double SmacRecvTimer::timeToExpire() {
return ((stime_ + rtime_) - Scheduler::instance().clock());
}
void SmacSendTimer::expire(Event *e) {
a_->handleSendTimer();
}
void SmacNavTimer::expire(Event *e) {
a_->handleNavTimer();
}
void SmacNeighNavTimer::sched(double time) {
TimerHandler::sched(time);
stime_ = Scheduler::instance().clock();
rtime_ = time;
}
void SmacNeighNavTimer::expire(Event *e) {
stime_ = rtime_ = 0;
a_->handleNeighNavTimer();
}
double SmacNeighNavTimer::timeToExpire() {
return ((stime_ + rtime_) - Scheduler::instance().clock());
}
void SmacCsTimer::expire(Event *e) {
a_->handleCsTimer();
}
// if pending, cancel timer
void SmacCsTimer::checkToCancel() {
if (status_ == TIMER_PENDING)
cancel();
}
// void SmacChkSendTimer::expire(Event *e) {
// a_->handleChkSendTimer();
// }
void SmacCounterTimer::sched(double time) {
// the cycle timer assumes that all time shall be scheduled with time "left to sleep"
// and not the absolute time for a given state (sleep, sync or data). Thus in order
// to schedule for a sleep state, need to schedule with aggregate time CYCLETIME
// (sleeptime+synctime+dadatime).
// Similarly for sync state, schedule with listenTime_ (synctime+datattime)
// This is implemented to be in step with the counter used in actual smac.
tts_ = time; // time before it goes to sleep again
stime_ = Scheduler::instance().clock();
if (time <= CLKTICK2SEC(cycleTime_) && time > CLKTICK2SEC(listenTime_)) { // in sleep state
value_ = sleepTime_;
if (status_ == TIMER_IDLE)
TimerHandler::sched(time - CLKTICK2SEC(listenTime_));
else
TimerHandler::resched(time - CLKTICK2SEC(listenTime_));
} else if ( time <= CLKTICK2SEC(listenTime_) && time > CLKTICK2SEC(dataTime_)) { // in sync state
value_ = syncTime_;
if (status_ == TIMER_IDLE)
TimerHandler::sched(time - CLKTICK2SEC(dataTime_));
else
TimerHandler::resched(time - CLKTICK2SEC(dataTime_));
} else { // in data state
assert(time <= CLKTICK2SEC(dataTime_));
value_ = dataTime_;
if (status_ == TIMER_IDLE)
TimerHandler::sched(time);
else
TimerHandler::resched(time);
}
}
double SmacCounterTimer::timeToSleep() {
return ((stime_ + tts_) - Scheduler::instance().clock()) ;
}
void SmacCounterTimer::expire(Event *e) {
tts_ = stime_ = 0;
a_->handleCounterTimer(index_);
}
#ifdef JOURNAL_PAPER
SMAC::SMAC() : Mac(), mhUpdateNeighb_(this),mhNav_(this), mhNeighNav_(this), mhSend_(this), mhRecv_(this), mhGene_(this), mhCS_(this), mhAdap_(this), syncFlag_(0) {
int i;
#else
SMAC::SMAC() : Mac(), mhNav_(this), mhNeighNav_(this), mhSend_(this), mhRecv_(this), mhGene_(this), mhCS_(this), syncFlag_(0) {
#endif
state_ = IDLE;
radioState_ = RADIO_IDLE;
tx_active_ = 0;
mac_collision_ = 0;
sendAddr_ = -1;
recvAddr_ = -1;
nav_ = 0;
neighNav_ = 0;
numRetry_ = 0;
numExtend_ = 0;
lastRxFrag_ = -3; // since -1, -2 and 0 could be valid pkt uid's
//numFrags_ = 0;
//succFrags_ = 0;
#ifdef JOURNAL_PAPER
numFrags_ = 0;
succFrags_ = 0;
dataSched_ = 0;
syncSched_ = 0;
globalSchedule_ = 0; // Do not test global schedule
//globalSchedule_ = 1; // Test global schedule
updateNeighbList_ = 0;
sendSYNCFlag_ = 0;
sendAddr = -1;
adapSend_ = 0;
txRequest_ = 0;
adaptiveListen_ = 0;
#endif
dataPkt_ = 0;
pktRx_ = 0;
pktTx_ = 0;
/* setup internal mac and physical parameters
----------------------------------------------
byte_tx_time_: time to transmit a byte, in ms. Derived from bandwidth
slotTime_: time of each slot in contention window. It should be large
enough to receive the whole start symbol but cannot be smaller than clock
resolution. in msec
slotTime_sec_: slottime in sec
difs_: DCF interframe space (from 802.11), in ms. It is used at the beginning
of each contention window. It's the minmum time to wait to start a new
transmission.
sifs_: short interframe space (f
/rom 802.11), in ms. It is used before sending
an CTS or ACK packet. It takes care of the processing delay of each pkt.
eifs_: Entended interfrane space (from 802.11) in ms. Used for backing off
incase of a collision.
guardTime_: guard time at the end of each listen interval, in ms.
*/
byte_tx_time_ = 8.0 / BANDWIDTH;
double start_symbol = byte_tx_time_ * 2.5; // time to tx 20 bits
slotTime_ = CLOCKRES >= start_symbol ? CLOCKRES : start_symbol; // in msec
slotTime_sec_ = slotTime_ / 1.0e3; // in sec
difs_ = 10.0 * slotTime_;
sifs_ = 5.0 * slotTime_;
eifs_ = 50.0 * slotTime_;
guardTime_ = 4.0 * slotTime_;
// calculate packet duration. Following equations assume 4b/6b coding.
// All calculations yield in usec
//durSyncPkt_ = ((SIZEOF_SMAC_SYNCPKT) * 12 + 18) / 1.0e4 ;
durSyncPkt_ = (PRE_PKT_BYTES + (SIZEOF_SMAC_SYNCPKT * ENCODE_RATIO)) * byte_tx_time_ + 1;
durSyncPkt_ = CLKTICK2SEC(durSyncPkt_);
//durDataPkt_ = ((SIZEOF_SMAC_DATAPKT) * 12 + 18) / 1.0e4 ;
durDataPkt_ = (PRE_PKT_BYTES + (SIZEOF_SMAC_DATAPKT * ENCODE_RATIO)) * byte_tx_time_ + 1;
durDataPkt_ = CLKTICK2SEC(durDataPkt_);
//durCtrlPkt_ = ((SIZEOF_SMAC_CTRLPKT) * 12 + 18) / 1.0e4;
durCtrlPkt_ = (PRE_PKT_BYTES + (SIZEOF_SMAC_CTRLPKT * ENCODE_RATIO)) * byte_tx_time_ + 1;
durCtrlPkt_ = CLKTICK2SEC(durCtrlPkt_);
// time to wait for CTS or ACK
//timeWaitCtrl_ = durCtrlPkt_ + CLKTICK2SEC(4) ; // timeout time
double delay = 2 * PROC_DELAY + sifs_;
timeWaitCtrl_ = CLKTICK2SEC(delay) + durCtrlPkt_; // timeout time
numSched_ = 0;
numNeighb_ = 0;
numSync_ = 1; // perform neighbor discovery, do not go to sleep for the first SYNC period
schedListen_ = 1;
searchNeighb_ = 1;
#ifdef JOURNAL_PAPER
schedState_ = 1; // this is my first schedule
// initialize neighbour table
for (i = 0; i < SMAC_MAX_NUM_NEIGHBORS; i++) {
neighbList_[i].nodeId = 0;
neighbList_[i].schedId = 0;
neighbList_[i].active = 0;
neighbList_[i].state = 0;
}
// initialize schedule table
for (i = 0; i < SMAC_MAX_NUM_SCHEDULES; i++) {
schedTab_[i].numNodes = 0;
schedTab_[i].syncNode = 0;
}
schedTab_[0].numNodes = 1; // I'm the only one on this schedule
schedTab_[0].syncNode = index_; // I'm the schedule initializer
schedTab_[0].txData = 0;
schedTab_[0].txSync = 0;
schedTab_[0].chkSched = 0;
#endif
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -