?? smac.cc
字號:
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=%f\n", dutyCycle_);
}
else {
dutyCycle_ = SMAC_DUTY_CYCLE;
printf("dutyCyle=%f\n", dutyCycle_);
}
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=%d\n", 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= %d\n", 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 %.6f\n", 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, %d\n", 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, %d\n", 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
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -