⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smac.cc

📁 网络仿真模拟工具NS2下实现的支持传感器网络的MAC协议SMAC
💻 CC
📖 第 1 页 / 共 5 页
字号:
// Copyright (c) 2000 by the University of Southern California// All rights reserved.//// Permission to use, copy, modify, and distribute this software and its// documentation in source and binary forms for non-commercial purposes// and without fee is hereby granted, provided that the above copyright// notice appear in all copies and that both the copyright notice and// this permission notice appear in supporting documentation. and that// any documentation, advertising materials, and other materials related// to such distribution and use acknowledge that the software was// developed by the University of Southern California, Information// Sciences Institute.  The name of the University may not be used to// endorse or promote products derived from this software without// specific prior written permission.//// THE UNIVERSITY OF SOUTHERN CALIFORNIA makes no representations about// the suitability of this software for any purpose.  THIS SOFTWARE IS// PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,// INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.//// Other copyrights might apply to parts of this software and are so// noted when applicable.// 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 "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 expirationint SmacTimer::busy(){	if (status_ != TIMER_PENDING)		return 0;	else		return 1;}#ifdef JOURNAL_PAPERvoid SmacUpdateNeighbTimer::expire(Event *e) {        a_->handleUpdateNeighbTimer();}                                                                                                                                                            void SmacAdaptiveListenTimer::expire(Event *e) {        a_->handleAdaptiveListenTimer();}#endifvoid 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 timervoid 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_PAPERSMAC::SMAC() : Mac(), mhUpdateNeighb_(this),mhNav_(this), mhNeighNav_(this), mhSend_(this), mhRecv_(this), mhGene_(this), mhCS_(this), mhAdap_(this), syncFlag_(0) {        int i;#elseSMAC::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=%f\n", 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=%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());

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -