smac.cc
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:78k
- /*
- * 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 inorder
- // 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
-
- Tcl& tcl = Tcl::instance();
- tcl.evalf("Mac/SMAC set syncFlag_");
- if (strcmp(tcl.result(), "0") != 0)
- syncFlag_ = 1; // syncflag is set; use sleep-wakeup cycle
- tcl.evalf("Mac/SMAC set selfConfigFlag_");
- if (strcmp(tcl.result(), "0") != 0)
- selfConfigFlag_ = 1; // autoflag is set; user can not configure the schedule start time
-
- // User can specify the duty cycle
- tcl.evalf("Mac/SMAC set dutyCycle_");
- if (strcmp(tcl.result(), "0") != 0){
- bind_bw("dutyCycle_", &dutyCycle_);
- //printf("dutyCyle=%fn", dutyCycle_);
-
- }
- else {
- // dutyCycle_ = SMAC_DUTY_CYCLE;
- }
- if (!syncFlag_)
- txData_ = 0;
-
- else {
- // Calculate sync/data/sleeptime based on duty cycle
- // all time in ms
- syncTime_ = difs_ + slotTime_ * SYNC_CW + SEC2CLKTICK(durSyncPkt_) + guardTime_;
- #ifdef JOURNAL_PAPER
- // added time for overhearing CTS so that can do adaptive listen
- dataTime_ = difs_ + slotTime_ * DATA_CW + SEC2CLKTICK(durCtrlPkt_) + PROC_DELAY + sifs_ + SEC2CLKTICK(durCtrlPkt_) + guardTime_;
- #else
- dataTime_ = difs_ + slotTime_ * DATA_CW + SEC2CLKTICK(durCtrlPkt_) + guardTime_;
- #endif
- listenTime_ = syncTime_ + dataTime_;
- cycleTime_ = listenTime_ * 100 / dutyCycle_ + 1;
- sleepTime_ = cycleTime_ - listenTime_;
-
- //printf("cycletime=%d, sleeptime=%d, listentime=%dn", cycleTime_, sleepTime_, listenTime_);
- for (int i=0; i< SMAC_MAX_NUM_SCHEDULES; i++) {
- mhCounter_[i] = new SmacCounterTimer(this, i);
- mhCounter_[i]->syncTime_ = syncTime_;
- mhCounter_[i]->dataTime_ = dataTime_;
- mhCounter_[i]->listenTime_ = listenTime_;
- mhCounter_[i]->sleepTime_ = sleepTime_;
- mhCounter_[i]->cycleTime_ = cycleTime_;
- }
- // printf("syncTime= %d, dataTime= %d, listentime = %d, sleepTime= %d, cycletime= %dn", syncTime_, dataTime_, listenTime_, sleepTime_, cycleTime_);
- // listen for a whole period to choose a schedule first
- //double cw = (Random::random() % SYNC_CW) * slotTime_sec_ ;
-
- // The foll (higher) CW value allows neigh nodes to follow a single schedule
- // double w = (Random::random() % (SYNC_CW)) ;
- // double cw = w/10.0;
- double c = CLKTICK2SEC(listenTime_) + CLKTICK2SEC(sleepTime_);
- double s = SYNCPERIOD + 1;
- double t = c * s ;
- //mhGene_.sched(t + cw);
- if ( selfConfigFlag_ == 1) {
- #ifdef JOURNAL_PAPER
- adapTime_ = dataTime_;
- mhGene_.sched(t);
-
- //start setting timer for update neighbor list
- //printf("SMAC_UPDATE_NEIGHB_PERIOD: ............node %d %d at %.6fn", index_, SMAC_UPDATE_NEIGHB_PERIOD, Scheduler::instance().clock());
- mhUpdateNeighb_.sched(SMAC_UPDATE_NEIGHB_PERIOD);
- //dump();
- #else
- mhGene_.sched(t);
- #endif
- }
- }
- }
- void SMAC::setMySched(Packet *pkt)
- {
- // set my schedule and put it into the first entry of schedule table
- state_ = IDLE;
- numSched_ = 1;
- schedTab_[0].numPeriods = 0;
- schedTab_[0].txData = 0;
- schedTab_[0].txSync = 1; // need to brdcast my schedule
-
- if (pkt == 0) { // freely choose my schedule
- #ifdef JOURNAL_PAPER
- //printf("#############################################################n");
- //printf(" %d is choosing its own shedule %d n", index_, index_);
- //printf("#############################################################n");
- schedState_++;
- mhCounter_[0]->sched(CLKTICK2SEC(listenTime_+index_*10));
- schedTab_[0].syncNode = index_;
- #else
- mhCounter_[0]->sched(CLKTICK2SEC(listenTime_));
- #endif
- mySyncNode_ = index_; // myself
- currSched_ = 0;
- //sendSYNC();
-
- } else { // follow schedule in syncpkt
-
- struct smac_sync_frame *pf = (struct smac_sync_frame *)pkt->access(hdr_mac::offset_);
- mhCounter_[0]->sched(pf->sleepTime);
- #ifdef JOURNAL_PAPER
- mySyncNode_ = pf->syncNode;
- //printf("#############################################################n");
- //printf("%d receives SYNC packet from %d and starts following shedule %d n", index_, pf->srcAddr, pf->syncNode);
- //printf("#############################################################n");
- schedTab_[0].numNodes++; // 2 nodes on this schedule now
- schedTab_[0].syncNode = pf->syncNode;
- schedState_++;
-
- //add node in my neighbor list
- neighbList_[0].nodeId = pf->srcAddr;
- neighbList_[0].schedId = 0;
- neighbList_[0].active = 1;
- neighbList_[0].state = pf->state;
- #else
- mySyncNode_ = pf->srcAddr;
- //add node in my neighbor list
- neighbList_[0].nodeId = mySyncNode_;
- neighbList_[0].schedId = 0;
- #endif
- numNeighb_ = 1;
- }
- }
- int SMAC::command(int argc, const char*const* argv)
- {
- if (argc == 3) {
- if (strcmp(argv[1], "log-target") == 0) {
- logtarget_ = (NsObject*) TclObject::lookup(argv[2]);
- if(logtarget_ == 0)
- return TCL_ERROR;
- return TCL_OK;
- }
- else if ( selfConfigFlag_ != 1) {
- if (strcmp(argv[1], "schedule-start-time") == 0) {
- startTime_ = strtod(argv[2],NULL);
- // set up schedule
- state_ = IDLE;
- numSched_ = 1;
- schedTab_[0].numPeriods = SYNCPERIOD;
- schedTab_[0].txData = 0;
- schedTab_[0].txSync = 1; // need to brdcast my schedule
- // schedule starts up with listen time (sync+data)
- // need to caculate time to sleep
- startTime_ = startTime_ + listenTime_;
- if ( startTime_ >= cycleTime_ )
- startTime_ = startTime_ - cycleTime_;
- mhCounter_[0]->sched(CLKTICK2SEC(startTime_));
- mySyncNode_ = index_; // myself
- currSched_ = 0;
- return TCL_OK;
-
- }
- }
- }
- return Mac::command(argc, argv);
- }
- #ifdef JOURNAL_PAPER
- void SMAC::adaptiveListen()
- {
- // adaptively wake-up at the end of current transmission. Will try to
- // send only if the buffered packet is unicast. Since my next-hop
- // neighbor may not be aware of the Tx of my previous-hop neighbor,
- // broadcast now is unreliable
- //printf("adaptiveListen set AdaptiveTimer: node %d scheduletime: %f adapTime_: %d time:%.9f n", index_, mhCounter_[0]->value_, adapTime_, Scheduler::instance().clock());
- mhAdap_.resched(CLKTICK2SEC(adapTime_)); // set timer to bring me back to sleep
- adaptiveListen_ = 1;
- if (state_ == SLEEP) {
- //printf("adaptiveListen wakeup: node %d scheduletime: %f time:%.9f n", index_, mhCounter_[0]->value_, Scheduler::instance().clock());
- wakeup();
- }
- else {
- }
-
- if ( schedTab_[0].txData == 1 && sendAddr == UNICAST_ADDR){
- adapSend_ = 1;
- checkToSend();
- }
- }
- #endif
- // XXXX smac handler functions
- void SMAC::handleSendTimer() {
- assert(pktTx_);
-
- struct hdr_smac *sh = HDR_SMAC(pktTx_);
-
- // Packet tx is done so radio should go back to idle
- radioState_ = RADIO_IDLE;
- tx_active_ = 0;
-
- switch(sh->type) {
-
- case RTS_PKT:
- sentRTS(pktTx_);
- break;
- case CTS_PKT:
- sentCTS(pktTx_);
- break;
-
- case DATA_PKT:
- sentDATA(pktTx_);
- break;
-
- case ACK_PKT:
- sentACK(pktTx_);
- break;
- case SYNC_PKT:
- sentSYNC(pktTx_);
- break;
- default:
- fprintf(stderr, "unknown mac pkt type, %dn", sh->type);
- break;
- }
-
- pktTx_ = 0;
- }
- void SMAC::handleRecvTimer() {
- assert(pktRx_);
-
- struct hdr_cmn *ch = HDR_CMN(pktRx_);
- struct hdr_smac *sh = HDR_SMAC(pktRx_);
- if (state_ == SLEEP) {
- // Bug fixed here. a collision might happen just now, need to clear the mac_collision_ flag, otherwise the node won't receive any following packet
- if (mac_collision_) {
- discard(pktRx_, DROP_MAC_COLLISION);
- mac_collision_ = 0;
- updateNav(CLKTICK2SEC(eifs_));
- if (state_ == CR_SENSE)
- sleep(); // have to wait until next wakeup time
- else
- radioState_ = RADIO_IDLE;
- goto done;
- }
- discard(pktRx_, DROP_MAC_SLEEP);
- radioState_ = RADIO_SLP;
- goto done;
- }
-
- // if the radio interface is tx'ing when this packet arrives
- // I would never have seen it and should do a silent discard
-
- if (radioState_ == RADIO_TX) {
- Packet::free(pktRx_);
- goto done;
- }
-
- if (mac_collision_) {
- discard(pktRx_, DROP_MAC_COLLISION);
- mac_collision_ = 0;
- updateNav(CLKTICK2SEC(eifs_));
-
- if (state_ == CR_SENSE)
- sleep(); // have to wait until next wakeup time
- else
- radioState_ = RADIO_IDLE;
-
- goto done;
- }
-
- if (ch->error()) {
- Packet::free(pktRx_);
- updateNav(CLKTICK2SEC(eifs_));
- if (state_ == CR_SENSE)
- sleep();
- else
- radioState_ = RADIO_IDLE;
-
- goto done;
- }
-
- // set radio from rx to idle again
- radioState_ = RADIO_IDLE;
- switch (sh->type) {
- case DATA_PKT:
- handleDATA(pktRx_);
- break;
- case RTS_PKT:
- handleRTS(pktRx_);
- Packet::free(pktRx_);
- break;
- case CTS_PKT:
- handleCTS(pktRx_);
- Packet::free(pktRx_);
- break;
- case ACK_PKT:
- handleACK(pktRx_);
- Packet::free(pktRx_);
- break;
- case SYNC_PKT:
- handleSYNC(pktRx_);
- Packet::free(pktRx_);
- break;
- default:
- fprintf(stderr, "Unknown smac pkt type, %dn", sh->type);
- break;
- }
-
- done:
- pktRx_ = 0;
-
- }
- void SMAC::handleGeneTimer()
- {
-
- if (syncFlag_) {
- // still in choose-schedule state
- if (numSched_ == 0) {
- setMySched(0); // I'm the primary synchroniser
- return;
- }
- }
- if (state_ == WAIT_CTS) { // CTS timeout
- if (numRetry_ < SMAC_RETRY_LIMIT) {
- numRetry_++;
- // wait until receiver's next wakeup
- state_ = IDLE;
- #ifdef JOURNAL_PAPER
- //node tries to go to sleep if it needs to resend
- if( mhCounter_[0]->value_ == sleepTime_ )
- sleep();
- #endif
-
- if (!syncFlag_)
- checkToSend();
-
- } else {
- state_ = IDLE;
- Packet::free(dataPkt_);
- dataPkt_ = 0;
- numRetry_ = 0;
- //numFrags_ = 0;
- // signal upper layer about failure of tx
- // txMsgFailed();
- txMsgDone();
-
- }
-
- } else if (state_ == WAIT_ACK) { // ack timeout
-
- if (numExtend_ < SMAC_EXTEND_LIMIT) { // extend time
- printf("SMAC %d: no ACK received. Extend Tx time.n", index_);
- numExtend_++;
-
- updateNeighNav(durDataPkt_ + durCtrlPkt_);
- //neighNav_ = (durDataPkt_ + durCtrlPkt_);
-
- } else { // reached extension limit, can't extend time
- //numFrags_--;
-
- }
- if (neighNav_ < (durDataPkt_ + durCtrlPkt_)) {
-
- // used up reserved time, stop tx
-
- discard(dataPkt_, DROP_MAC_RETRY_COUNT_EXCEEDED);
- dataPkt_ = 0;
- pktTx_ = 0;
- state_ = IDLE;
-
- // signal upper layer the number of transmitted frags
- //txMsgFailed(succFrags); -> no frag for now
-
- txMsgDone();
-
- } else { // still have time
- // keep sending until use up remaining time
- sendDATA();
- }
- #ifdef JOURNAL_PAPER
- } else if (state_ == DATA_SENSE1) {
- state_ = DATA_SENSE2;
- mhGene_.resched(timeWaitCtrl_);
-
- } else if (state_ == DATA_SENSE2) {
- state_ = IDLE;
- //node tries to go to sleep if it does not hear CTS or DATA for others' connection
- if( mhCounter_[0]->value_ == sleepTime_ )
- sleep();
- #endif
- }
- }
- void SMAC::handleNavTimer() {
- // medium is now free
- nav_ = 0; // why have this variable?? probably not required use the timer instead
-
- if (!syncFlag_) {
- if (state_ == SLEEP)
- wakeup();
- // try to send waiting data, if any
- checkToSend();
- }
- #ifdef JOURNAL_PAPER
- adaptiveListen();
- #endif
- }
- int SMAC::checkToSend() {
- #ifdef JOURNAL_PAPER
- if (txRequest_ == 1 || syncFlag_) {
- #else
- if (txData_ == 1) {
- #endif
- assert(dataPkt_);
- struct hdr_smac *mh = HDR_SMAC(dataPkt_);
-
- if (radioState_ != RADIO_SLP && radioState_ != RADIO_IDLE)
- goto done; // cannot send if radio is sending or recving
-
- if (state_ != SLEEP && state_ != IDLE && state_ != WAIT_DATA )
- goto done; // cannot send if not in any of these states
-
- if (!(mhNav_.busy()) && !(mhNeighNav_.busy()) &&
- (state_ == SLEEP || state_ == IDLE)) {
-
- if (state_ == SLEEP) wakeup();
-
- if ((u_int32_t)mh->dstAddr == MAC_BROADCAST)
- howToSend_ = BCASTDATA;
- else
- howToSend_ = UNICAST;
-
- state_ = CR_SENSE;
- #ifdef JOURNAL_PAPER
- adapSend_ = 0;
- //printf("adaptiveListen sendData: node %d scheduletime: %f time:%.9f n", index_, mhCounter_[0]->value_, Scheduler::instance().clock());
- #endif
-
- // start cstimer
- double cw = (Random::random() % DATA_CW) * slotTime_sec_;
- mhCS_.sched(CLKTICK2SEC(difs_) + cw);
-
- return 1;
-
- } else {
- return 0;
- }
-
- done:
- return 0;
-
- } else {
- return 0;
- }
- }
- void SMAC::handleNeighNavTimer() {
-
- // Timer to track my neighbor's NAV
- neighNav_ = 0; // probably don't need to use this variable
-
- if (state_ == WAIT_DATA) { // data timeout
- state_ = IDLE;
-
- // signal upper layer that rx msg is done
- // didnot get any/all data
- rxMsgDone(0);
- } else {
- if (!syncFlag_)
- checkToSend();
- }
- #ifdef JOURNAL_PAPER
- adaptiveListen();
- #endif
- }
- void SMAC::handleCsTimer() {
-
- // carrier sense successful
-
- #ifdef MAC_DEBUG
- if (howToSend_ != BCASTSYNC && dataPkt_ == 0)
- numCSError++;
- #endif // MAC_DEBUG
-
- switch(howToSend_) {
- case BCASTSYNC:
- if (sendSYNC())
- state_ = IDLE;
- break;
-
- case BCASTDATA:
- startBcast();
- break;
-
- case UNICAST:
- startUcast();
- break;
- }
- }
- void SMAC::handleCounterTimer(int id) {
-
- //printf("MAC:%d,id:%d - time:%.9fn", index_,id,Scheduler::instance().clock());
- #ifdef JOURNAL_PAPER
- if (schedTab_[id].numNodes > 0) {
- #endif
- if (mhCounter_[id]->value_ == sleepTime_) { //woken up from sleep
- // listentime starts now
- if (radioState_ != RADIO_SLP && radioState_ != RADIO_IDLE)
- goto sched_1; // cannot send if radio is sending or recving
-
- if (state_ != SLEEP && state_ != IDLE && state_ != WAIT_DATA )
- goto sched_1;; // cannot send if not in any of these states
-
- if (!(mhNav_.busy()) && !(mhNeighNav_.busy()) &&
- (state_ == SLEEP || state_ == IDLE)) {
-
- if (state_ == SLEEP &&
- (id == 0 || schedTab_[id].txSync == 1)) {
-
- wakeup();
- }
- if (schedTab_[id].txSync == 1) {
- // start carrier sense for sending sync
- howToSend_ = BCASTSYNC;
- #ifdef JOURNAL_PAPER
- syncSched_ = id;
- #else
- currSched_ = id;
- #endif
- state_ = CR_SENSE;
- double cw = (Random::random() % SYNC_CW) * slotTime_sec_;
- mhCS_.sched(CLKTICK2SEC(difs_) + cw);
- }
- }
- // start to listen now
- sched_1:
- mhCounter_[id]->sched(CLKTICK2SEC(listenTime_));
-
- } else if (mhCounter_[id]->value_ == syncTime_) { //synctime over
- // can start datatime now
-
- if (radioState_ != RADIO_SLP && radioState_ != RADIO_IDLE)
- goto sched_2; // cannot send if radio is sending or recving
-
- if (state_ != SLEEP && state_ != IDLE && state_ != WAIT_DATA )
- goto sched_2; // cannot send if not in any of these states
-
- if (schedTab_[id].txData == 1 &&
- (!(mhNav_.busy()) && !(mhNeighNav_.busy())) &&
- (state_ == SLEEP || state_ == IDLE)) {
- // schedule sending data
-
- if (state_ == SLEEP)
- wakeup();
-
- struct hdr_smac *mh = (struct hdr_smac *)dataPkt_->access(hdr_mac::offset_);
- if ((u_int32_t)mh->dstAddr == MAC_BROADCAST)
- howToSend_ = BCASTDATA;
- else
- howToSend_ = UNICAST;
- #ifdef JOURNAL_PAPER
- dataSched_ = id;
- #else
- currSched_ = id;
- #endif
- state_ = CR_SENSE;
- // start cstimer
- double cw = (Random::random() % DATA_CW) * slotTime_sec_;
- mhCS_.sched(CLKTICK2SEC(difs_) + cw);
- }
- sched_2:
- mhCounter_[id]->sched(CLKTICK2SEC(dataTime_));
-
- } else if (mhCounter_[id]->value_ == dataTime_) { //datatime over
- // check if in the middle of recving a pkt
- if (radioState_ == RADIO_RX)
- goto sched_3;
- #ifdef JOURNAL_PAPER
- if (id == 0 && state_ == IDLE && searchNeighb_ ==0 && adaptiveListen_ ==0 )
- #else
- if (id == 0 && state_ == IDLE && searchNeighb_ ==0 )
- #endif
- sleep();
- sched_3:
- // now time to go to sleep
- mhCounter_[id]->sched(CLKTICK2SEC(cycleTime_));
-
- // check if ready to send out sync
- if (schedTab_[id].numPeriods > 0) {
- schedTab_[id].numPeriods--;
- if (schedTab_[id].numPeriods == 0) {
-
- schedTab_[id].txSync = 1;
- // neighbor discovery
- if ( id == 0 ) {
- numSync_--;
- // printf("numSync_ %d: ............node %d at %.6fn", numSync_, index_,Scheduler::instance().clock());
- if ( numSync_ == 1 ) {
- searchNeighb_ = 1; // node will go to neighbor discovery period starting from the next frame
- //printf("Start Neighbor Discovery: ............node %d at %.6fn", index_, Scheduler::instance().clock());
- }
- else if ( numSync_ == 0 ) {
- searchNeighb_ = 0; // neighbor discovery period lasts exactly one SYNC period
- //printf("Ending Neighbor Discovery: ............node %d at %.6fn", index_, Scheduler::instance().clock());
- if ( numNeighb_ == 0 ) {
- numSync_ = SRCH_CYCLES_SHORT;
- }
- else {
- numSync_ = SRCH_CYCLES_LONG;
- }
- }
- }
- }
- }
- }
- #ifdef JOURNAL_PAPER
- }
- #endif
- }
- #ifdef JOURNAL_PAPER
- void SMAC::handleUpdateNeighbTimer() {
- //printf("SMAC::handleUpdateNeighbTimer: ............node %d at %.6fn", index_, Scheduler::instance().clock());
- if (txRequest_ == 0) { // No data waiting to be transmitted
- txRequest_ = 1; // temporarily disable tx when updating
- update_myNeighbList();
- } else {
- updateNeighbList_ = 1; // set flag to update when tx done
- }
- }
-
- void SMAC::handleAdaptiveListenTimer() {
- //node tries to go to sleep after adaptive listen times out
- adaptiveListen_ = 0;
- if (state_ == IDLE && state_ != TX_PKT && mhCounter_[0]->value_ == sleepTime_)
- sleep();
- }
- #endif
- // recv function for mac layer
- void SMAC::recv(Packet *p, Handler *h) {
-
- struct hdr_cmn *ch = HDR_CMN(p);
- assert(initialized());
- // handle outgoing pkt
- if ( ch->direction() == hdr_cmn::DOWN) {
- sendMsg(p, h);
- return;
- }
- // handle incoming pkt
- // we have just recvd the first bit of a pkt on the network interface
-
- // if the interface is in tx mode it probably would not see this pkt
- if (radioState_ == RADIO_TX && ch->error() == 0) {
- assert(tx_active_);
- ch->error() = 1;
- pktRx_ = p;
- mhRecv_.resched(txtime(p));
- return;
- }
-
- // cancel carrier sense timer and wait for entire pkt
- if (state_ == CR_SENSE) {
- //printf("Cancelling CS- node %dn", index_);
- // cancels only if timer is pending; smac could be in CR_SENSE with timer cancelled
- // incase it has already received a pkt and receiving again
- mhCS_.checkToCancel();
- }
-
- // if the interface is already in process of recv'ing pkt
- if (radioState_ == RADIO_RX) {
- assert(pktRx_);
- assert(mhRecv_.busy());
-
- // if power of the incoming pkt is smaller than the power
- // of the pkt currently being recvd by atleast the capture
- // threshold then we ignore the new pkt.
-
- if (pktRx_->txinfo_.RxPr / p->txinfo_.RxPr >= p->txinfo_.CPThresh)
- capture(p);
- else
- collision(p);
- }
-
- else {
- if (mhRecv_.busy()) { // and radiostate != RADIO_RX
- assert(radioState_ == RADIO_SLP);
- // The radio interface was recv'ing a pkt when it went to sleep
- // should it postpone sleep till it finishes recving the pkt???
- mhRecv_.resched(txtime(p));
- } else
- mhRecv_.sched(txtime(p));
-
- radioState_ = RADIO_RX;
- pktRx_ = p;
- }
- }
- void SMAC::capture(Packet *p) {
- // we update NAV for this pkt txtime
- updateNav(CLKTICK2SEC(eifs_) + txtime(p));
- Packet::free(p);
- }
- void SMAC::collision(Packet *p) {
- if (!mac_collision_)
- mac_collision_ = 1;
-
- // since a collision has occured figure out which packet that caused
- // the collision will "last" longer. Make this pkt pktRx_ and reset the
- // recv timer.
- if (txtime(p) > mhRecv_.timeToExpire()) {
- mhRecv_.resched(txtime(p));
- discard(pktRx_, DROP_MAC_COLLISION);
- // shouldn't we free pkt here ???
- pktRx_ = p;
- }
- else
- discard(p, DROP_MAC_COLLISION);
- // shouldn't we free pkt here ???
- }
- void SMAC::discard(Packet *p, const char* why)
- {
- hdr_cmn *ch = HDR_CMN(p);
- hdr_smac *sh = HDR_SMAC(p);
-
- /* if the rcvd pkt contains errors, a real MAC layer couldn't
- necessarily read any data from it, so we just toss it now */
- if(ch->error() != 0) {
- Packet::free(p);
- //p = 0;
- return;
- }
- switch(sh->type) {
-
- case RTS_PKT:
- if (drop_RTS(p, why))
- return;
- break;
-
- case CTS_PKT:
- case ACK_PKT:
- if (drop_CTS(p, why))
- return;
- break;
-
- case DATA_PKT:
- if (drop_DATA(p, why))
- return;
- break;
- case SYNC_PKT:
- if(drop_SYNC(p, why))
- return;
- break;
- default:
- fprintf(stderr, "invalid MAC type (%x)n", sh->type);
- //trace_pkt(p);
- exit(1);
- }
- Packet::free(p);
- }
- int SMAC::drop_RTS(Packet *p, const char* why)
- {
- struct smac_control_frame *cf = (smac_control_frame *)p->access(hdr_mac::offset_);
-
- if (cf->srcAddr == index_) {
- drop(p, why);
- return 1;
- }
- return 0;
- }
- int SMAC::drop_CTS(Packet *p, const char* why)
- {
- struct smac_control_frame *cf = (smac_control_frame *)p->access(hdr_mac::offset_);
- if (cf->dstAddr == index_) {
- drop(p, why);
- return 1;
- }
- return 0;
- }
- int SMAC::drop_DATA(Packet *p, const char* why)
- {
- hdr_smac *sh = HDR_SMAC(p);
- if ( (sh->dstAddr == index_) ||
- (sh->srcAddr == index_) ||
- ((u_int32_t)sh->dstAddr == MAC_BROADCAST)) {
- drop(p, why);
- return 1;
- }
- return 0;
- }
- int SMAC::drop_SYNC(Packet *p, const char* why)
- {
- drop(p, why);
- return 1;
- }
- #ifdef JOURNAL_PAPER
- void SMAC::checkMySched()
- {
- // check if I am the only one on schedTab[0]
- // if yes, should switch and follow the next available schedule
- // happens when an old node switches to a new schedule
- // and when I drop some inactive nodes from neighbor list(updating)
- int i, schedId;
- schedId = 0;
- if (schedTab_[0].numNodes == 1 && numSched_ > 1 && numNeighb_ > 0) {
- for (i = 1; i < SMAC_MAX_NUM_SCHEDULES; i++) {
- if (schedTab_[i].numNodes > 0) { // switch to next available schedule
- //schedTab_[0].counter = schedTab[i].counter;
- schedTab_[0].numPeriods = 0;
- schedTab_[0].txSync = 1;
- schedTab_[0].txData = schedTab_[i].txData;
- schedTab_[0].syncNode = schedTab_[i].syncNode;
- schedTab_[0].numNodes = schedTab_[i].numNodes + 1;
- // delete this schedule
- schedTab_[i].numNodes = 0;
- numSched_--;
- schedId = i;
- break;
- }
- }
- if (schedId > 0){
- schedState_++;
- // update my neighbor list which relative to this schedId
- for (i = 0; i < SMAC_MAX_NUM_NEIGHBORS; i++) {
- if (neighbList_[i].state > 0 )
- if (neighbList_[i].schedId == schedId)
- neighbList_[i].schedId = 0;
- }
- }
- }
- }
- // update_schedTab_neighbList() is executed whenever the transmission is done
- void SMAC::update_schedTab_neighbList()
- {
- //update schedTab and neighbList if flag is set
- //we should update the schedTab[].numNodes before we call checkMySched()
- //to ensure the next available schedule is correct
- check_schedFlag();
- if (updateNeighbList_ == 1) {
- update_neighbList();
- updateNeighbList_ = 0;
- schedTab_[0].chkSched = 0; //we already did checkMySched() in update_neighbList()
- } else if (schedTab_[0].chkSched == 1) {
- checkMySched();
- schedTab_[0].chkSched = 0;
- }
- }
-
- //update_myNeighbList() is executed whenever the UpdateNeighb timer timesout
- void SMAC::update_myNeighbList()
- {
- //we should update the schedTab[].numNodes before we call checkMySched()
- //to ensure the next available schedule is correct
- check_schedFlag();
- update_neighbList();
- updateNeighbList_ = 0;
- schedTab_[0].chkSched = 0; //we already did checkMySched() in update_neighbList()
- txRequest_ = 0;
- }
-
- void SMAC::update_neighbList()
- {
- // update neighbor list,
- // if the node is not active (moved away or died) for a certain time,
- // need to drop it from neighbor list
-
- //printf("nupdate_neighbList:node %d at %.6f n", index_, Scheduler::instance().clock());
- int i, schedId;
- //dump();
- for (i = 0; i < SMAC_MAX_NUM_NEIGHBORS; i++) {
- if (neighbList_[i].state > 0 ){
- if (neighbList_[i].active != 1){ // this node is not active recently
- //printf("node %d lost a neighbor of node %d: ............at %.6fn", index_, neighbList_[i].nodeId, Scheduler::instance().clock());
- schedId = neighbList_[i].schedId;
- schedTab_[schedId].numNodes--;
- if (schedTab_[schedId].numNodes == 0)
- numSched_--;
- neighbList_[i].state = 0;
- numNeighb_--;
- } else
- //printf("node %d has a neighbor of node %d: ............at %.6fn", index_, neighbList_[i].nodeId, Scheduler::instance().clock());
- neighbList_[i].active = 0;
- }
- }
- //printf("#####################################################n");
-
- // maybe the inactive nodes were dropped from schedTab[0]
- // check if I am the only one on schedTab[0]
- // if yes, I should follow the next available schedule
- checkMySched();
- mhUpdateNeighb_.resched(SMAC_UPDATE_NEIGHB_PERIOD);
- }
- void SMAC::check_schedFlag()
- {
- int i;
- // decrease the numNodes in the old schedule first
- for (i = 1; i < SMAC_MAX_NUM_SCHEDULES; i++) {
- if (schedTab_[i].numNodes > 0 && schedTab_[i].chkSched == 1){
- schedTab_[i].chkSched = 0;
- schedTab_[i].numNodes--;
- if (schedTab_[i].numNodes == 0)
- numSched_--;
- }
- }
- }
- #endif
- void SMAC::handleRTS(Packet *p) {
- // internal handler for RTS
- struct smac_control_frame *cf = (smac_control_frame *)p->access(hdr_mac::offset_);
-
- if(cf->dstAddr == index_) {
- if((state_ == IDLE || state_ == CR_SENSE) && nav_ == 0) {
- recvAddr_ = cf->srcAddr; // remember sender's addr
- #ifdef JOURNAL_PAPER
- updateNeighNav(cf->duration);
- #endif
- if(sendCTS(cf->duration)) {
- state_ = WAIT_DATA;
- lastRxFrag_ = -3; //reset frag no
- }
- }
- } else {
- // pkt destined to another node
- // don't go to sleep unless hear first data fragment
- // so I know how long to sleep
- if (state_ == CR_SENSE)
- state_ = IDLE;
- #ifdef JOURNAL_PAPER
- updateNav(cf->duration);
- state_ = DATA_SENSE1;
- mhGene_.sched(timeWaitCtrl_);
- #else
- updateNav(durCtrlPkt_ + durDataPkt_);
- #endif
- }
- }
- void SMAC::handleCTS(Packet *p) {
- // internal handler for CTS
- struct smac_control_frame *cf = (smac_control_frame *)p->access(hdr_mac::offset_);
- if(cf->dstAddr == index_) { // for me
- if(state_ == WAIT_CTS && cf->srcAddr == sendAddr_) {
- // cancel CTS timer
- mhGene_.cancel();
- if(sendDATA()) {
- state_ = WAIT_ACK;
- #ifndef JORNAL_PAPER
- if (!syncFlag_)
- txData_ = 0;
- else
- schedTab_[currSched_].txData = 0;
- #endif
- }
- }
- } else { // for others
- updateNav(cf->duration);
- #ifdef JOURNAL_PAPER
- if(state_ == DATA_SENSE1 || state_ == DATA_SENSE2) { mhGene_.cancel();}
- if(state_ == IDLE || state_ == CR_SENSE || state_ == DATA_SENSE1 || state_ == DATA_SENSE2)
- sleep();
- #else
- if(state_ == IDLE || state_ == CR_SENSE)
- sleep();
- #endif
- }
- }
- void SMAC::handleDATA(Packet *p) {
- // internal handler for DATA packet
- struct hdr_cmn *ch = HDR_CMN(p);
- struct hdr_smac * sh = HDR_SMAC(p);
-
- if((u_int32_t)sh->dstAddr == MAC_BROADCAST) { // brdcast pkt
- state_ = IDLE;
- // hand pkt over to higher layer
- rxMsgDone(p);
-
- } else if (sh->dstAddr == index_) { // unicast pkt
- if(state_ == WAIT_DATA && sh->srcAddr == recvAddr_) {
- // Should track neighbors' NAV, in case tx extended
- updateNeighNav(sh->duration);
- sendACK(sh->duration);
- #ifdef JOURNAL_PAPER
- if (sh->duration > durCtrlPkt_) { // wait for more frag
- rxFragDone(p); //no frag for now
- state_ = WAIT_DATA;
- } else { // no more fragments
- state_ = IDLE;
- rxMsgDone(p);
- }
- #else
-
- //if (sh->duration > durCtrlPkt_) { // wait for more frag
- //rxFragDone(p); no frag for now
- //state_ = IDLE;
- //} else { // no more fragments
-
- state_ = IDLE;
- if(lastRxFrag_ != ch->uid()) {
- lastRxFrag_ = ch->uid();
- rxMsgDone(p);
- }
- else {
- printf("Recd duplicate data pkt at %d from %d! free pktn",index_,sh->srcAddr);
- Packet::free(p);
- if (!syncFlag_)
- checkToSend();
- }
- #endif
- } else if (state_ == IDLE || state_ == CR_SENSE ) {
- printf("got data pkt in %d state XXX %dn", state_, index_);
- //updateNav(sh->duration + 0.00001); // incase I have a pkt to send
- sendACK(sh->duration);
- state_ = IDLE;
- if(lastRxFrag_ != ch->uid()) {
- lastRxFrag_ = ch->uid();
- rxMsgDone(p);
- }
- else {
- printf("Recd duplicate data pkt! free pktn");
- Packet::free(p);
- if (!syncFlag_)
- checkToSend();
- }
- } else { // some other state
- // not sure we can handle this
- // so drop pkt
- printf("Got data pkt in !WAIT_DATA/!CR_SENSE/!IDLE state(%d) XXX %dn", state_, index_);
- printf("Dropping data pktn");
- Packet::free(p);
- }
- } else { // unicast pkt destined to other node
- updateNav(sh->duration);
- Packet::free(p);
- #ifdef JOURNAL_PAPER
- if (state_ == DATA_SENSE2) { mhGene_.cancel();}
- if (state_ == IDLE || state_ == CR_SENSE || state_ == DATA_SENSE2)
- sleep();
- #else
- if (state_ == IDLE || state_ == CR_SENSE)
- sleep();
- #endif
- }
- }
- void SMAC::handleACK(Packet *p) {
- // internal handler for ack
- struct smac_control_frame *cf = (smac_control_frame *)p->access(hdr_mac::offset_);
-
- if (cf->dstAddr == index_) {
- if (state_ == WAIT_ACK && cf->srcAddr == sendAddr_) {
- // cancel ACK timer
- mhGene_.cancel();
- #ifdef JOURNAL_PAPER
- numFrags_--;
- succFrags_++;
- if (numFrags_ > 0) { //need to send more frags
- state_ = TX_NEXT_FRAG;
- txFragDone();
- } else {
- state_ = IDLE;
- txMsgDone();
- }
- #else
- Packet::free(dataPkt_);
- dataPkt_ = 0;
- //numFrags_--;
- //succFrags_++;
-
- // if (numFrags_ > 0) { //need to send more frags
- // if (neighNav__ < (durDataPkt_ + durCtrlPkt_)) {
- // // used up reserved time, have to stop
- // state_ = IDLE;
- // // txMsgFailed(succFrags_);
- // txMsgDone();
- // } else { // continue on next fragment
- // state_ = WAIT_NEXTFRAG;
- // txFragDone(dataPkt_);
- // }
- // } else {
- state_ = IDLE;
- txMsgDone();
- //}
- #endif
- }
-
- } else { // destined to another node
- if (cf->duration > 0) {
- updateNav(cf->duration);
- if (state_ == IDLE || state_ == CR_SENSE)
- sleep();
- }
- }
- }
- #ifdef JOURNAL_PAPER
- void SMAC::handleSYNC(Packet *p)
- {
- struct smac_sync_frame *sf = (struct smac_sync_frame *)p->access(hdr_mac::offset_);
- int i, j,nodeId, schedId, flag;
- struct SchedTable tempSched;
- int foundNeighb = 0;
- if (index_ == 5){
- double t = Scheduler::instance().clock();
- //printf("Recvd SYNC (not/f) at %d from %d.....at %.6fn", index_, sf->srcAddr, t);
- }
- if (numSched_ == 0) { // in choose_sched state
- mhGene_.cancel();
- setMySched(p);
- return;
- }
- if (numNeighb_ == 0 && globalSchedule_ == 1) {
- // follow this schedule if having no other neighbor and if this schedule has smaller ID
- if (schedTab_[0].syncNode > sf->syncNode || !sendSYNCFlag_ ) {
- setMySched(p);
- return;
- }
- }
- else if (numNeighb_ == 0) { // getting first sync pkt
- // follow this sched as have no other neighbor
- setMySched(p);
- return;
- }
- state_ = IDLE;
- // check if sender is on my neighbor list
- nodeId = SMAC_MAX_NUM_NEIGHBORS;
- schedId = SMAC_MAX_NUM_SCHEDULES;
- for (i = 0; i < SMAC_MAX_NUM_NEIGHBORS; i++) {
- if (neighbList_[i].state > 0 && neighbList_[i].nodeId == sf->srcAddr) {
- nodeId = i;
- schedId = neighbList_[i].schedId; // a known neighbor
- break;
- }
- }
- if (nodeId < SMAC_MAX_NUM_NEIGHBORS) {
- if (neighbList_[nodeId].state == sf->state) {
- // update the existing schedule
- mhCounter_[schedId]->sched(sf->sleepTime);
- neighbList_[nodeId].active = 1;
- if (globalSchedule_ == 1 && schedTab_[0].syncNode > sf->syncNode ){
- // change state
- schedState_++;
- //printf("#############################################################n");
- //printf("node %d hears SYNC from node %d and changes schedule from %d to schedule %d : ............at %.6fn", index_, sf->srcAddr, schedTab_[0].syncNode, sf->syncNode, Scheduler::instance().clock());
- //printf("#############################################################n");
- tempSched.syncNode = schedTab_[schedId].syncNode;
- tempSched.txSync = schedTab_[schedId].txSync; // need send sync
- tempSched.txData = schedTab_[schedId].txData;
- tempSched.numPeriods = schedTab_[schedId].numPeriods;
- tempSched.numNodes = schedTab_[schedId].numNodes ; //
- tempSched.chkSched = schedTab_[schedId].chkSched;
- if (schedTab_[0].numNodes == 1) {
- numSched_--;
- }
- mhCounter_[schedId]->sched(mhCounter_[0]->timeToSleep());
- schedTab_[schedId].syncNode = schedTab_[0].syncNode;
- schedTab_[schedId].txSync = schedTab_[0].txSync; // need send sync
- schedTab_[schedId].txData = schedTab_[0].txData;
- schedTab_[schedId].numPeriods = schedTab_[0].numPeriods;
- schedTab_[schedId].numNodes = schedTab_[0].numNodes - 1; // I switch schedule
- schedTab_[schedId].chkSched = schedTab_[0].chkSched;
- // new schedule is schedule 0 now
- mhCounter_[0]->sched(sf->sleepTime);
- schedTab_[0].syncNode = sf->syncNode;
- schedTab_[0].txSync = 1;
- schedTab_[0].txData = tempSched.txData;
- schedTab_[0].numPeriods = 0;
- schedTab_[0].numNodes = tempSched.numNodes + 1; // I are following this sched
- schedTab_[0].chkSched = tempSched.chkSched;
- // change all the neighbor who was following shedule 0
- for (j = 0; j < SMAC_MAX_NUM_NEIGHBORS; j++) {
- if (neighbList_[j].schedId == 0) { // found an empty entry
- neighbList_[j].schedId = schedId;
- }
- else if (neighbList_[j].schedId == schedId) { // found an empty entry
- neighbList_[j].schedId = 0;
- }
- }
- }
- return;
- } else {
- // decrement number of nodes on old schedule
- if (schedTab_[schedId].numNodes ==1 && txRequest_ == 1) {
- //set flag to decrement numNodes after tx pkt is done
- schedTab_[schedId].chkSched = 1;
- }
- else
- {
- schedTab_[schedId].numNodes--;
- if (schedTab_[schedId].numNodes == 0){
- numSched_--;
- }
- }
- }
- }
- // now it's either a new node or an old node switching to a new schedule
- // it is also possible that a node switches to an existing schedule
- // check if its schedule is a known one to me
- schedId = SMAC_MAX_NUM_SCHEDULES;
- for (i = 0; i < SMAC_MAX_NUM_SCHEDULES; i++) {
- if (schedTab_[i].numNodes > 0) {
-
- double t = mhCounter_[i]->timeToSleep();
- double st = sf->sleepTime;
- double timeDiff = st - t;
- if ( timeDiff > -GUARDTIME && timeDiff < GUARDTIME) {
- mhCounter_[i]->sched(sf->sleepTime);
- schedTab_[i].numNodes++; // it will follow this schedule
- schedId = i;
- break;
- }
- }
- }
- if (schedId == SMAC_MAX_NUM_SCHEDULES) { // unknow schedule
- flag =1;
- // add an entry to the schedule table
- if (numSched_ < SMAC_MAX_NUM_SCHEDULES){
- for (i = 0; i < SMAC_MAX_NUM_SCHEDULES; i++) {
- if (schedTab_[i].numNodes == 0) { // found an empty entry
- // check if I need to switch
- if (globalSchedule_ == 1 && schedTab_[0].syncNode > sf->syncNode ){
- // change state
- schedState_++;
- //printf("#############################################################n");
- //printf("node %d hears SYNC from node %d and changes schedule from %d to schedule %d : ............at %.6fn", index_, sf->srcAddr, schedTab_[0].syncNode, sf->syncNode, Scheduler::instance().clock());
- //printf("#############################################################n");
- if (schedTab_[0].numNodes >= 2) { // need to move old schedule 0 to schedule i
- mhCounter_[i]->sched(mhCounter_[0]->timeToSleep());
- schedTab_[i].syncNode = schedTab_[0].syncNode;
- schedTab_[i].txSync = schedTab_[0].txSync; // need send sync
- schedTab_[i].txData = schedTab_[0].txData;
- schedTab_[i].numPeriods = schedTab_[0].numPeriods;
- schedTab_[i].numNodes = schedTab_[0].numNodes - 1; // I switch schedule
- schedTab_[i].chkSched = schedTab_[0].chkSched;
- numSched_++; // increment number of schedules
- // change all the neighbor who was following shedule 0
- for (j = 0; j < SMAC_MAX_NUM_NEIGHBORS; j++) {
- if (neighbList_[j].schedId == 0) { // found an empty entry
- neighbList_[j].schedId = i;
- }
- }
- }
- // new schedule is schedule 0 now
- mhCounter_[0]->sched(sf->sleepTime);
- schedTab_[0].syncNode = sf->syncNode;
- schedTab_[0].txSync = 1; // need send sync
- schedTab_[0].txData = 0;
- schedTab_[0].numPeriods = 0;
- schedTab_[0].numNodes = 2; // 1st node + I are following this sched
- schedTab_[0].chkSched = 0;
- schedId = 0;
- }
- else { // fill new schedule in schedule i
- mhCounter_[i]->sched(sf->sleepTime);
- schedTab_[i].syncNode = sf->syncNode;
- schedTab_[i].txSync = 1; // need send sync
- schedTab_[i].txData = 0;
- schedTab_[i].numPeriods = 0;
- schedTab_[i].numNodes = 1; // 1st node following this sched
- schedTab_[i].chkSched = 0;
- schedId = i;
- numSched_++; // increment number of schedules
- }
- break;
- }
- }
- }
- }
- if (nodeId == SMAC_MAX_NUM_NEIGHBORS) { // a new node
- // didn't find an empty entry in schedule table, just drop the new node
- if (schedId == SMAC_MAX_NUM_SCHEDULES) return;
- // add it to my neighbor list
- if (numNeighb_ < SMAC_MAX_NUM_NEIGHBORS){
- for (i = 0; i < SMAC_MAX_NUM_NEIGHBORS; i++) {
- if (neighbList_[i].state == 0) { // found an empty entry
- neighbList_[i].state = sf->state;
- neighbList_[i].nodeId = sf->srcAddr;
- neighbList_[i].schedId = schedId;
- neighbList_[i].active = 1;
- numNeighb_++; // increment number of neighbors
- return;
- }
- }
- }
- // didn't find an empty entry in neighb list, just drop the new node
- schedTab_[schedId].numNodes--;
- if (schedTab_[schedId].numNodes == 0)
- numSched_--;
- } else if (flag == 1) { // old node switches to a new schedule
- // didn't find an empty entry in schedule table, delete the old node
- if (schedId == SMAC_MAX_NUM_SCHEDULES) {
- neighbList_[nodeId].state = 0;
- numNeighb_--; // decrement number of neighbors
- } else {
- neighbList_[nodeId].state = sf->state;
- neighbList_[nodeId].schedId = schedId;
- neighbList_[nodeId].active = 1;
- }
- // maybe the old node switches from schedTab_[0]
- // check if I am the only one on schedTab_[0] now
- // if yes, I should follow the next available schedule
- if (txRequest_ == 0) {
- checkMySched();
- } else {
- // set flag to call checkMySched() when txRequest_ becomes 0
- schedTab_[0].chkSched = 1;
- }
- } else { // old node switches to old schedule
- neighbList_[nodeId].state = sf->state;
- neighbList_[nodeId].schedId = schedId;
- neighbList_[nodeId].active = 1;
- if (globalSchedule_ == 1 && schedTab_[0].syncNode > sf->syncNode ){
- //printf("#############################################################n");
- //printf("node %d hears SYNC from node %d and changes schedule from %d to schedule %d : ............at %.6fn", index_, sf->srcAddr, schedTab_[0].syncNode, sf->syncNode, Scheduler::instance().clock());
- //printf("#############################################################n");
- // change state
- schedState_++;
- tempSched.syncNode = schedTab_[schedId].syncNode;
- tempSched.txSync = schedTab_[schedId].txSync; // need send sync
- tempSched.txData = schedTab_[schedId].txData;
- tempSched.numPeriods = schedTab_[schedId].numPeriods;
- tempSched.numNodes = schedTab_[schedId].numNodes ; //
- tempSched.chkSched = schedTab_[schedId].chkSched;
- if (schedTab_[0].numNodes == 1) {
- numSched_--;
- }
- mhCounter_[schedId]->sched(mhCounter_[0]->timeToSleep());
- schedTab_[schedId].syncNode = schedTab_[0].syncNode;
- schedTab_[schedId].txSync = schedTab_[0].txSync; // need send sync
- schedTab_[schedId].txData = schedTab_[0].txData;
- schedTab_[schedId].numPeriods = schedTab_[0].numPeriods;
- schedTab_[schedId].numNodes = schedTab_[0].numNodes - 1; // I switch schedule
- schedTab_[schedId].chkSched = schedTab_[0].chkSched;
- /// new schedule is schedule 0 now
- mhCounter_[0]->sched(sf->sleepTime);
- schedTab_[0].syncNode = sf->syncNode;
- schedTab_[0].txSync = 1;
- schedTab_[0].txData = tempSched.txData;
- schedTab_[0].numPeriods = 0;
- schedTab_[0].numNodes = tempSched.numNodes + 1; // I are following this sched
- schedTab_[0].chkSched = tempSched.chkSched;
- // change all the neighbor who was following shedule 0
- for (j = 0; j < SMAC_MAX_NUM_NEIGHBORS; j++) {
- if (neighbList_[j].schedId == 0) { // found an empty entry
- neighbList_[j].schedId = schedId;
- }
- else if (neighbList_[j].schedId == schedId) { // found an empty entry
- neighbList_[j].schedId = 0;
- }
- }
- }
- return;
- }
- }
- #else
- void SMAC::handleSYNC(Packet *p)
- {
- //printf("node: %d ..............data sent............n",index_);
- if ( selfConfigFlag_ == 1) {
- if(numSched_ == 0) { // in choose_sched state
- mhGene_.cancel();
- //double t = Scheduler::instance().clock();
- //struct smac_sync_frame *sf = (struct smac_sync_frame *)p->access(hdr_mac::offset_);
- //printf("Recvd SYNC (follow) at %d from %d.....at %.6fn", index_, sf->srcAddr, t);
- setMySched(p);
- return;
- }
- if (numNeighb_ == 0) { // getting first sync pkt
- // follow this sched as have no other neighbor
- //double t = Scheduler::instance().clock();
- //struct smac_sync_frame *sf = (struct smac_sync_frame *)p->access(hdr_mac::offset_);
- //printf("Recvd SYNC (follow) at %d from %d.....at %.6fn", index_, sf->srcAddr, t);
- setMySched(p);
- return;
- }
- }
- state_ = IDLE;
- // check if sender is on my neighbor list
- struct smac_sync_frame *sf = (struct smac_sync_frame *)p->access(hdr_mac::offset_);
- int i, j;
- int foundNeighb = 0;
- int schedId = SMAC_MAX_NUM_SCHEDULES;
- //double t = Scheduler::instance().clock();
- //printf("Recvd SYNC (not/f) at %d from %d.....at %.6fn", index_, sf->srcAddr, t);
-
- for(i = 0; i < numNeighb_; i++) {
- if (neighbList_[i].nodeId == sf->srcAddr) {
- foundNeighb = 1;
- schedId = neighbList_[i].schedId; // a known neighbor
- mhCounter_[schedId]->sched(sf->sleepTime);
- break;
- }
- if (neighbList_[i].nodeId == sf->syncNode)
- // // found its synchronizer, remember it schedule id
- schedId = neighbList_[i].schedId;
- }
- if (!foundNeighb) { // unknown node, add it onto neighbor list
- neighbList_[numNeighb_].nodeId = sf->srcAddr;
- if (schedId < SMAC_MAX_NUM_SCHEDULES) {
- // found its synchronizer
- neighbList_[numNeighb_].schedId = schedId;
- } else if (sf->syncNode == index_) { // this node follows my schedule
- neighbList_[numNeighb_].schedId = 0;
- } else { // its synchronizer is unknown
- // check if its schedule equals to an existing one
- int foundSched = 0;
- for (j = 0; j < numSched_; j++) {
- double t = mhCounter_[j]->timeToSleep();
- double st = sf->sleepTime;
- if (t == st || (t + CLKTICK2SEC(1)) == st || t == (st + CLKTICK2SEC(1))) {
- neighbList_[numNeighb_].schedId = j;
- foundSched = 1;
- break;
- }
- }
- if (!foundSched) { // this is unknown schedule
- schedTab_[numSched_].txSync = 1;
- schedTab_[numSched_].txData = 0;
- schedTab_[numSched_].numPeriods = 0;
- neighbList_[numNeighb_].schedId = numSched_;
- mhCounter_[numSched_]->sched(sf->sleepTime);
- numSched_++;
- }
- }
- numNeighb_++; // increment number of neighbors
- }
- }
- #endif
- void SMAC::rxMsgDone(Packet *p) {
- // no more fragments
- // defragment all pkts and send them up
- // fragmentation/de-frag to be implemented
-
- if (p)
- uptarget_->recv(p, (Handler*)0);
-
- if (!syncFlag_)
- // check if any pkt waiting to get tx'ed
- checkToSend();
- #ifdef JOURNAL_PAPER
- //node tries to go to sleep after receiving the message
- //we temperarily disable sleep() here, because in the testcases where ARP messages exist, more than one message need to be transmitted in one round
- else {
- // if( mhCounter_[0]->value_ == sleepTime_ )
- // sleep();
- }
- #endif
- }
- #ifdef JOURNAL_PAPER
- void SMAC::rxFragDone(Packet *p) {
- // more fragments to come
- }
- #endif
- //void SMAC::rxFragDone(Packet *p) {
- // more fragments to come
- //}
- // mac transmission functions
- void SMAC::transmit(Packet *p) {
-
- radioState_ = RADIO_TX;
- tx_active_ = 1;
- pktTx_ = p;
- double transTime = txtime(p);
- hdr_cmn *ch = hdr_cmn::access(p);
- ch->txtime() = transTime;
- // printf("%d MAC sending at %fn",index_,NOW);
- downtarget_->recv(p->copy(), this);
- //Scheduler::instance().schedule(downtarget_, p, 0.000001);
- mhSend_.sched(txtime(p));
- }
- bool SMAC::chkRadio() {
- // check radiostate
- if (radioState_ == RADIO_IDLE || radioState_ == RADIO_SLP)
- return (1);
- return (0); // phy interface is ready to tx
- }
- int SMAC::startBcast()
- {
- // broadcast data directly; don't use RTS/CTS
- hdr_smac *mh = HDR_SMAC(dataPkt_);
-
- mh->duration = 0;
- if(chkRadio()) {
- transmit(dataPkt_);
- return 1;
- }
-
- return 0;
- }
- int SMAC::startUcast()
- {
- printf("node: %d ..............data sent Uni............n",index_);
- // start unicast data; send RTS first
- hdr_smac *mh = HDR_SMAC(dataPkt_);
-
- sendAddr_ = mh->dstAddr;
- numRetry_ = 0;
- //succFrags_ = 0;
- #ifdef JOURNAL_PAPER
- succFrags_ = 0;
- #endif
- numExtend_ = 0;
- if(sendRTS()) {
- state_ = WAIT_CTS;
- return 1;
- }
-
- return 0;
- }
- void SMAC::txMsgDone()
- {
- #ifdef JOURNAL_PAPER
- // update schedTab and neighbList if flags are set when txRequest_=1
- update_schedTab_neighbList();
- txRequest_ = 0;
- #endif
- if (!syncFlag_) {
- #ifdef JOURNAL_PAPER
- txData_ = 0;
- #endif
- // check if any data is waiting to get tx'ed
- if(checkToSend())
- return;
- else if (callback_) { // signal upper layer
- Handler *h = callback_;
- callback_ = 0;
- h->handle((Event*) 0);
- }
- } else {
- #ifdef JOURNAL_PAPER
- schedTab_[dataSched_].txData = 0;
- #endif
- if (callback_) { // signal upper layer
- Handler *h = callback_;
- callback_ = 0;
- h->handle((Event*) 0);
- }
- #ifdef JOURNAL_PAPER
- //node tries to go to sleep after transmission is done (both unicast and broadcast)
- if( mhCounter_[0]->value_ == sleepTime_ )
- sleep();
- #endif
- }
-
- }
- // void SMAC::txFragDone()
- // {
- // // send next fragment
- // }
- #ifdef JOURNAL_PAPER
- void SMAC::txFragDone()
- {
- // send next fragment
- txNextFrag(&dataPkt_);
- }
-
- bool SMAC::txNextFrag(void* data)
- {
- // Send subsequent fragments
-
- if (state_ != TX_NEXT_FRAG || data == 0) return 0;
- // dataPkt = (MACHeader*)data;
- // fill in MAC header fields except duration
- // dataPkt->type = DATA_PKT; // data pkt
- // dataPkt->toAddr = sendAddr;
- // dataPkt->fromAddr = TOS_LOCAL_ADDRESS;
- // dataPkt->fragNo = txFragCount;
- // if (neighbNav >= (SIFS + durDataPkt + timeWaitCtrl)) {
- // schedule to send this fragment, no need for carrier sense
- // state = TX_PKT;
- if(sendDATA()) {
- state_ = WAIT_ACK;
- if (!syncFlag_)
- txData_ = 0;
- else
- schedTab_[dataSched_].txData = 0;
- //schedTab_[currSched_].txData = 0;
- }
-
- // } // else will retry when neighbNav timeout
- return 1;
- }
- #endif
- bool SMAC::sendMsg(Packet *pkt, Handler *h) {
- struct hdr_smac *mh = HDR_SMAC(pkt);
- #ifdef JOURNAL_PAPER
- struct hdr_cmn *ch = HDR_CMN(pkt);
- #endif
- callback_ = h;
- if ((u_int32_t)mh->dstAddr == MAC_BROADCAST) {
- return (bcastMsg(pkt));
- } else {
- #ifdef JOURNAL_PAPER
- //printf("message length: %dn",ch->size_);
- // need upper level support here
- int fragNum = ch->size_ / SIZEOF_SMAC_DATAPKT ;
- if (fragNum == 0) fragNum = 1;
- //printf("message length:%dn",fragNum);
- return unicastMsg(fragNum, pkt); // for now no fragmentation
- #else
- return (unicastMsg(1, pkt)); // for now no fragmentation
- #endif
- // fragmentation limit is 40 bytes per pkt.
- // max_msg_size is tentatively 1000 bytes; weiye will confirm this
- }
- }
- bool SMAC::bcastMsg(Packet *p) {
- //if (dataPkt_ != 0 || p == 0)
- //return 0;
- assert(p);
-
- //if (state_ != IDLE && state_ != SLEEP && state_!= WAIT_DATA)
- //return 0;
- //char * mh = (char *)p->access(hdr_mac::offset_);
- //int dst = hdr_dst(mh);
- //int src = hdr_src(mh);
-
- struct hdr_smac *sh = HDR_SMAC(p);
-
- sh->type = DATA_PKT;
- sh->length = SIZEOF_SMAC_DATAPKT;
- //sh->srcAddr = src;
- //sh->dstAddr = dst;
- dataPkt_ = p;
- #ifdef JOURNAL_PAPER
- // Don't accept Tx request if I have already accepted a request
- if (txRequest_ == 0) {
- txRequest_ = 1;
- }
- else {
- return 0;
- }
-
- for (int i = 0; i < SMAC_MAX_NUM_SCHEDULES; i++) {
- if (schedTab_[i].numNodes > 0) {
- //printf("txData[%d] = 1: ............node %d at %.6fn", i, index_, Scheduler::instance().clock());
- schedTab_[i].txData = 1;
- }
- }
- #else
- for(int i=0; i < numSched_; i++) {
- schedTab_[i].txData = 1;
- }
- #endif
- if (!syncFlag_) {
- txData_ = 1;
- // check if can send now
- if (checkToSend())
- return 1;
- else
- return 0;
-
- } else {
- numBcast_ = numSched_;
- return 1;
- }
- }
- bool SMAC::unicastMsg(int numfrags, Packet *p) {
- // if (dataPkt != 0 || p == 0)
- //return 0;
- assert(p);
- //if (state_ != IDLE && state_ != SLEEP && state_!= WAIT_DATA)
- //return 0;
-
- char * mh = (char *)p->access(hdr_mac::offset_);
- int dst = hdr_dst(mh);
- int src = hdr_src(mh);
- // search for schedule of dest node
- struct hdr_smac *sh = HDR_SMAC(p);
- //int dst = sh->dstAddr;
- if (syncFlag_) {
- int found = 0;
- for (int i=0; i < numNeighb_; i++) {
- if (neighbList_[i].nodeId == dst) {
- found = 1;
- #ifdef JOURNAL_PAPER
- sendAddr = UNICAST_ADDR;
- dataSched_ = neighbList_[i].schedId;
- #endif
- schedTab_[neighbList_[i].schedId].txData = 1;
- break;
- }
- }
- if (found == 0) {
- printf("Neighbor unknown; cannot send pktn");
- return 0; // unknown neighbor
- }
- }
- #ifdef JOURNAL_PAPER
- // Don't accept Tx request if I have already accepted a request
- if (txRequest_ == 0) {
- txRequest_ = 1;
- }
- else {
- return 0;
- }
- numFrags_ = numfrags;
- #endif
- sh->type = DATA_PKT;
- sh->length = SIZEOF_SMAC_DATAPKT;
- sh->dstAddr = dst;
- sh->srcAddr = src;
- //numFrags_ = numfrags;
- dataPkt_ = p;
- if (!syncFlag_) {
- txData_ = 1;
-
- // check if can send now
- if (checkToSend())
- return 1;
- else
- return 0;
-
- } else
- return 1;
- }
- bool SMAC::sendRTS() {
- //printf("node: %d ..............data sent............n",index_);
- // construct RTS pkt
- Packet *p = Packet::alloc();
- struct smac_control_frame *cf = (struct smac_control_frame *)p->access(hdr_mac::offset_);
- struct hdr_cmn *ch = HDR_CMN(p);
- ch->uid() = 0;
- ch->ptype() = PT_SMAC;
- ch->size() = SIZEOF_SMAC_CTRLPKT;
- ch->iface() = UNKN_IFACE.value();
- ch->direction() = hdr_cmn::DOWN;
- ch->error() = 0; /* pkt not corrupt to start with */
-
- bzero(cf, MAC_HDR_LEN);
-
- cf->length = SIZEOF_SMAC_CTRLPKT;
- cf->type = RTS_PKT;
-
- cf->srcAddr = index_; // mac_id
- cf->dstAddr = sendAddr_;
- // reserved time for CTS + all fragments + all acks
- //cf->duration = (numFrags_ + 1) * durCtrlPkt_ + numFrags_ * durDataPkt_;
- #ifdef JOURNAL_PAPER
- cf->duration = (numFrags_ + 1) * durCtrlPkt_ + numFrags_ * durDataPkt_;
- #else
- cf->duration = (2 * durCtrlPkt_ + durDataPkt_ + 0.001 );
- #endif
- cf->crc = 0;
-
- // send RTS
- if (chkRadio()) {
- transmit(p);
- return 1;
-
- } else
- return 0;
- }
- bool SMAC::sendCTS(double duration) {
-
- // construct CTS
- Packet *p = Packet::alloc();
- struct smac_control_frame *cf = (struct smac_control_frame *)p->access(hdr_mac::offset_);
- struct hdr_cmn *ch = HDR_CMN(p);
- ch->uid() = 0;
- ch->ptype() = PT_SMAC;
- ch->size() = SIZEOF_SMAC_CTRLPKT;
- ch->iface() = UNKN_IFACE.value();
- ch->direction() = hdr_cmn::DOWN;
- ch->error() = 0; /* pkt not corrupt to start with */
- bzero(cf, MAC_HDR_LEN);
-
- cf->length = SIZEOF_SMAC_CTRLPKT;
- cf->type = CTS_PKT;
-
- cf->srcAddr = index_;
- cf->dstAddr = recvAddr_;
- // input duration is the duration field from received RTS pkt
- cf->duration = duration - durCtrlPkt_ ;
- cf->crc = 0;
- // send CTS
- if (chkRadio()) {
- transmit(p);
- return 1;
- } else
- return 0;
- }
- bool SMAC::sendDATA() {
- // assuming data pkt is already constructed
- struct hdr_smac * sh = HDR_SMAC(dataPkt_);
-
- //sh->duration = numFrags_ * durCtrlPkt_ + (numFrags_ - 1) * durDataPkt_;
- #ifdef JOURNAL_PAPER
- sh->duration = numFrags_ * durCtrlPkt_ + (numFrags_ - 1) * durDataPkt_;
- #else
- sh->duration = durCtrlPkt_;
- #endif
- // send DATA
- if (chkRadio()) {
- transmit(dataPkt_);
-
- return 1;
- } else
- return 0;
- }
- bool SMAC::sendACK(double duration) {
- // construct ACK pkt
- Packet *p = Packet::alloc();
- struct smac_control_frame *cf = (struct smac_control_frame *)p->access(hdr_mac::offset_);
- struct hdr_cmn *ch = HDR_CMN(p);
- ch->uid() = 0;
- ch->ptype() = PT_SMAC;
- ch->size() = SIZEOF_SMAC_CTRLPKT;
- ch->iface() = UNKN_IFACE.value();
- ch->direction() = hdr_cmn::DOWN;
- ch->error() = 0; /* pkt not corrupt to start with */
-
- bzero(cf, MAC_HDR_LEN);
-
- cf->length = SIZEOF_SMAC_CTRLPKT;
- cf->type = ACK_PKT;
-
- cf->srcAddr = index_;
- cf->dstAddr = recvAddr_;
-
- // input duration is the duration field from recvd data pkt
- // stick to neighbNav -- should update it when rx data packet
- cf->duration = duration - durCtrlPkt_;
- //cf->duration = mhNeighNav_.timeToExpire() - durCtrlPkt_;
-
- // send ACK
- if (chkRadio()) {
- transmit(p);
- return 1;
- } else
- return 0;
- }
- bool SMAC::sendSYNC()
- {
- // construct and send SYNC pkt
- Packet *p = Packet::alloc();
- struct smac_sync_frame *cf = (struct smac_sync_frame *)p->access(hdr_mac::offset_);
- struct hdr_cmn *ch = HDR_CMN(p);
- ch->uid() = 0;
- ch->ptype() = PT_SMAC;
- ch->size() = SIZEOF_SMAC_SYNCPKT;
- ch->iface() = UNKN_IFACE.value();
- ch->direction() = hdr_cmn::DOWN;
- ch->error() = 0; /* pkt not corrupt to start with */
-
- cf->length = SIZEOF_SMAC_SYNCPKT;
- cf->type = SYNC_PKT;
-
- cf->srcAddr = index_;
- #ifdef JOURNAL_PAPER
- cf->syncNode = schedTab_[0].syncNode;
- cf->state = schedState_;
- #else
- cf->syncNode = mySyncNode_;
- #endif
- // shld change SYNCPKTTIME to match with the configures durSyncPkt_
- cf->sleepTime = mhCounter_[0]->timeToSleep() - CLKTICK2SEC(SYNCPKTTIME);
- if (cf->sleepTime < 0)
- cf->sleepTime += CLKTICK2SEC(cycleTime_);
-
- // send SYNC
- if (chkRadio()) {
- // if(index_==0)
- // printf("%d Sent SYNC at %.6fn", index_,Scheduler::instance().clock());
- transmit(p);
- //double t = Scheduler::instance().clock();
- //printf("Sent SYNC from %d.....at %.6fn", cf->srcAddr, t);
- return 1;
-
- } else
- return 0;
- }
- void SMAC::sentRTS(Packet *p)
- {
- // just sent RTS, set timer for CTS timeout
- mhGene_.sched(timeWaitCtrl_);
- Packet::free(p);
-
- }
- void SMAC::sentCTS(Packet *p)
- {
- // just sent CTS, track my neighbors' NAV
- // they update NAV and go to sleep after recv CTS
- // no data timeout, just use neighbors' NAV
- // since they went to sleep, just wait data for the entire time
- struct smac_control_frame *cf = (struct smac_control_frame *)p->access(hdr_mac::offset_);
-
- updateNeighNav(cf->duration);
- Packet::free(p);
- }
- void SMAC::sentDATA(Packet *p)
- {
- struct hdr_smac *mh = HDR_SMAC(p);
-
- if (howToSend_ == BCASTDATA) { // if data was brdcast
- state_ = IDLE;
- if (!syncFlag_) {
- txData_ = 0;
- dataPkt_ = 0;
- Packet::free(p);
-
- // signal upper layer
- txMsgDone();
-
- } else {
- #ifdef JOURNAL_PAPER
- schedTab_[dataSched_].txData = 0;
- #else
- schedTab_[currSched_].txData = 0;
- #endif
- numBcast_--;
- if (numBcast_ == 0) {
- dataPkt_ = 0;
- Packet::free(p);
- #ifdef JOURNAL_PAPER
- txRequest_ = 0;
- #endif
- // signal upper layer
- txMsgDone();
- }
- #ifdef JOURNAL_PAPER
- //when broadcast data is done for one schedule, sender needs to sleep
- if( mhCounter_[0]->value_ == sleepTime_ )
- sleep();
- #endif
- }
-
- } else {
-
- // unicast is done; track my neighbors' NAV
- // they update NAV and go to sleep after recv first data fragment
- #ifdef JOURNAL_PAPER
- sendAddr = -1;
- txRequest_ = 0;
- #endif
- updateNeighNav(mh->duration);
-
- //waiting for ACK, set timer for ACK timeout
- mhGene_.sched(timeWaitCtrl_);
- }
- }
- void SMAC::sentACK(Packet *p)
- {
- struct smac_control_frame *cf = (struct smac_control_frame *)p->access(hdr_mac::offset_);
-
- updateNeighNav(cf->duration);
- Packet::free(p);
- }
- void SMAC::sentSYNC(Packet *p)
- {
- #ifdef JOURNAL_PAPER
- schedTab_[syncSched_].txSync = 0;
- schedTab_[syncSched_].numPeriods = SYNCPERIOD;
- #else
- schedTab_[currSched_].txSync = 0;
- schedTab_[currSched_].numPeriods = SYNCPERIOD;
- #endif
- Packet::free(p);
- }
- void SMAC::sleep()
- {
- // go to sleep, turn off radio
- state_ = SLEEP;
- radioState_ = RADIO_SLP;
- #ifdef JOURNAL_PAPER
- //printf("SLEEP: ............node %d at %.6fn", index_, Scheduler::instance().clock());
- #endif
- // printf("SLEEP: ............node %d at %.6fn", index_, Scheduler::instance().clock());
- //printf("%d SMAC SLEEP: at %.6fn", index_,Scheduler::instance().clock());
- // set node state
- Phy *p;
- p=netif_;
- ((WirelessPhy *)p)->node_sleep();
- // printf("nnetifn %d", ((WirelessPhy *)p)->testfun(34));
- //
- }
- void SMAC::wakeup()
- {
- //wakeup from sleep. turn on radio
- state_ = IDLE;
-
- // since radio can start to recv while in sleep
- // it might be in RX state
- // and eventually the pkt will not be recvd if in sleep state
- // so careful not to change state of radio unless it is really sleeping
- if (radioState_ == RADIO_SLP)
- radioState_ = RADIO_IDLE;
- #ifdef JOURNAL_PAPER
- //printf("WAKEUP: ............node %d at %.6fn", index_, Scheduler::instance().clock());
- #endif
- // printf("WAKEUP: ............node %d at %.6fn", index_, Scheduler::instance().clock());
- Phy *p;
- p=netif_;
- ((WirelessPhy *)p)->node_wakeup();
- //printf("WAKEUP: ............node %d at %.6fn", index_, Scheduler::instance().clock());
- }
- void SMAC::updateNav(double d ) {
- double now = Scheduler::instance().clock();
- // already in sec
- // double d = duration * 1.0e-6; // convert to sec
- if ((now + d) > nav_) {
- nav_ = now + d;
-
- mhNav_.resched(d);
-
- }
- }
-
- void SMAC::updateNeighNav(double d ) {
- double now = Scheduler::instance().clock();
- //double d = duration * 1.0e-6; // convert to sec
- if ((now + d) > neighNav_) {
- neighNav_ = now + d;
- mhNeighNav_.resched(d);
-
- }
- }
- double SMAC::txtime(Packet *p)
- {
- struct hdr_smac *sh = HDR_SMAC(p);
- switch(sh->type) {
-
- case DATA_PKT:
- return durDataPkt_;
-
- case RTS_PKT:
- case CTS_PKT:
- case ACK_PKT:
- return durCtrlPkt_;
- case SYNC_PKT:
- return CLKTICK2SEC(SYNCPKTTIME);
- default:
- fprintf(stderr, "invalid smac pkt type %dn", sh->type);
- exit(1);
- }
-
- }
- #ifdef JOURNAL_PAPER
- void SMAC::dump(){
- int i;
- for (i = 0; i < 5; i++) {
-
- printf(" neighbor: %d schedule: %d state: %d active: %d n", neighbList_[i].nodeId, neighbList_[i].schedId, neighbList_[i].state, neighbList_[i].active);
- }
-
- for (i = 0; i < 4; i++) {
- printf(" schedule: %d numNodes: %d n",schedTab_[i].syncNode, schedTab_[i].numNodes);
- }
- }
- #endif