wireless-phymr.cc
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:17k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- 
  2.  *
  3.  * Copyright (c) 1996 Regents of the University of California.
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  * 1. Redistributions of source code must retain the above copyright
  10.  *    notice, this list of conditions and the following disclaimer.
  11.  * 2. Redistributions in binary form must reproduce the above copyright
  12.  *    notice, this list of conditions and the following disclaimer in the
  13.  *    documentation and/or other materials provided with the distribution.
  14.  * 3. All advertising materials mentioning features or use of this software
  15.  *    must display the following acknowledgement:
  16.  * This product includes software developed by the Computer Systems
  17.  * Engineering Group at Lawrence Berkeley Laboratory and the Daedalus
  18.  * research group at UC Berkeley.
  19.  * 4. Neither the name of the University nor of the Laboratory may be used
  20.  *    to endorse or promote products derived from this software without
  21.  *    specific prior written permission.
  22.  *
  23.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  24.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  25.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  26.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  27.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  28.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  29.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  30.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  31.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  32.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  33.  * SUCH DAMAGE.
  34.  *
  35.  * $Header: /nfs/jade/vint/CVSROOT/ns-2/mac/wireless-phy.cc,v 1.25 2005/08/22 05:08:33 tomh Exp $
  36.  *
  37.  * Ported from CMU/Monarch's code, nov'98 -Padma Haldar.
  38.  * wireless-phy.cc
  39.  *
  40.  * Ported 2006 from ns-2.29 
  41.  * by Federico Maguolo, Nicola Baldo and Simone Merlin 
  42.  * (SIGNET lab, University of Padova, Department of Information Engineering)
  43.  *
  44.  */
  45. #include <math.h>
  46. #include <packet.h>
  47. #include <mobilenode.h>
  48. #include <phy.h>
  49. #include <propagation.h>
  50. #include <modulation.h>
  51. #include <omni-antenna.h>
  52. #include "wireless-phymr.h"
  53. #include <packet.h>
  54. #include <ip.h>
  55. #include <agent.h>
  56. #include <trace.h>
  57. #include "diffusion/diff_header.h"
  58. #include "papropagation.h"
  59. #ifndef MAX
  60. #define MAX(a,b) (((a)<(b))?(b):(a))
  61. #endif
  62. #ifndef MIN
  63. #define MIN(a,b) (((a)<(b))?(a):(b))
  64. #endif
  65. void PASleep_Timer::expire(Event *) {
  66. a_->UpdateSleepEnergy();
  67. }
  68. /*
  69. PowerChangeTimer
  70. */
  71. PowerChangeTimer::PowerChangeTimer(PAWirelessPhy *phy) : phy_(phy), eventList_(0)
  72. {
  73. }
  74. void PowerChangeTimer::addEvent(double instant, double increasePower)
  75. {
  76. PowerChangeEvent *pe = new PowerChangeEvent;
  77. pe->instant = instant;
  78. pe->increasePower = increasePower;
  79. PowerChangeEvent *prev = 0;
  80. for(PowerChangeEvent *cur = eventList_; cur; cur = cur->next)
  81. {
  82. if(cur->instant >= instant)
  83. {
  84. pe->next = cur;
  85. if(prev)
  86. prev->next = pe;
  87. else
  88. eventList_ = pe;
  89. resched(eventList_->instant - Scheduler::instance().clock());
  90. return;
  91. }
  92. if(cur)
  93. prev = cur;
  94. }
  95. if(prev)
  96. prev->next = pe;
  97. else
  98. eventList_ = pe;
  99. pe->next = 0;
  100. resched(eventList_->instant - Scheduler::instance().clock());
  101. }
  102. void PowerChangeTimer::expire(Event *e)
  103. {
  104. assert(eventList_);
  105. PowerChangeEvent *pe = eventList_;
  106. eventList_ = eventList_->next;
  107. phy_->increasePower(pe->increasePower);
  108. delete pe;
  109. if(eventList_)
  110. resched(eventList_->instant - Scheduler::instance().clock());
  111. }
  112. /* ======================================================================
  113.    PAWirelessPhy Interface
  114.    ====================================================================== */
  115. static class PAWirelessPhyClass: public TclClass {
  116. public:
  117.         PAWirelessPhyClass() : TclClass("Phy/WirelessPhy/PowerAware") {}
  118.         TclObject* create(int, const char*const*) {
  119.                 return (new PAWirelessPhy);
  120.         }
  121. } class_PAWirelessPhy;
  122. PAWirelessPhy::PAWirelessPhy() : Phy(), sleep_timer_(this), status_(IDLE), powerTimer_(this), profile_(0)
  123. {
  124. bind("CSThresh_", &CSThresh_);
  125. bind("Pt_", &Pt_);
  126. bind("freq_", &freq_);
  127. bind("L_", &L_);
  128. lambda_ = SPEED_OF_LIGHT / freq_;
  129. node_ = 0;
  130. ant_ = 0;
  131. propagation_ = 0;
  132. //[Nicola] modulation was removed
  133. //modulation_ = 0;
  134. // Assume AT&T's Wavelan PCMCIA card -- Chalermek
  135.         // Pt_ = 8.5872e-4; // For 40m transmission range.
  136. //      Pt_ = 7.214e-3;  // For 100m transmission range.
  137. //      Pt_ = 0.2818; // For 250m transmission range.
  138. // Pt_ = pow(10, 2.45) * 1e-3;         // 24.5 dbm, ~ 281.8mw
  139. Pt_consume_ = 0.660;  // 1.6 W drained power for transmission
  140. Pr_consume_ = 0.395;  // 1.2 W drained power for reception
  141. // P_idle_ = 0.035; // 1.15 W drained power for idle
  142. P_idle_ = 0.0;
  143. P_sleep_ = 0.00;
  144. P_transition_ = 0.00;
  145. node_on_=1;
  146. channel_idle_time_ = NOW;
  147. update_energy_time_ = NOW;
  148. last_send_time_ = NOW;
  149. sleep_timer_.resched(1.0);
  150. }
  151. int
  152. PAWirelessPhy::command(int argc, const char*const* argv)
  153. {
  154. TclObject *obj; 
  155. if (argc==2) {
  156. if (strcasecmp(argv[1], "NodeOn") == 0) {
  157. node_on();
  158. if (em() == NULL) 
  159. return TCL_OK;
  160. if (NOW > update_energy_time_) {
  161. update_energy_time_ = NOW;
  162. }
  163. return TCL_OK;
  164. } else if (strcasecmp(argv[1], "NodeOff") == 0) {
  165. node_off();
  166. if (em() == NULL) 
  167. return TCL_OK;
  168. if (NOW > update_energy_time_) {
  169. em()->DecrIdleEnergy(NOW-update_energy_time_,
  170.      P_idle_);
  171. update_energy_time_ = NOW;
  172. }
  173. return TCL_OK;
  174. }
  175. } else if(argc == 3) {
  176. if (strcasecmp(argv[1], "setTxPower") == 0) {
  177. Pt_consume_ = atof(argv[2]);
  178. return TCL_OK;
  179. } else if (strcasecmp(argv[1], "setRxPower") == 0) {
  180. Pr_consume_ = atof(argv[2]);
  181. return TCL_OK;
  182. } else if (strcasecmp(argv[1], "setIdlePower") == 0) {
  183. P_idle_ = atof(argv[2]);
  184. return TCL_OK;
  185. }else if (strcasecmp(argv[1], "setSleepPower") == 0) {
  186. P_sleep_ = atof(argv[2]);
  187. return TCL_OK;
  188. } else if (strcasecmp(argv[1], "setTransitionPower") == 0) {
  189. P_transition_ = atof(argv[2]);
  190. return TCL_OK;
  191. } else if (strcasecmp(argv[1], "setTransitionTime") == 0) {
  192. T_transition_ = atof(argv[2]);
  193. return TCL_OK;
  194. }else if( (obj = TclObject::lookup(argv[2])) == 0) {
  195. fprintf(stderr,"PAWirelessPhy: %s lookup of %s failedn", 
  196. argv[1], argv[2]);
  197. return TCL_ERROR;
  198. }else if (strcmp(argv[1], "propagation") == 0) {
  199. assert(propagation_ == 0);
  200. propagation_ = (PAFreeSpace*) obj;
  201. return TCL_OK;
  202. } else if (strcasecmp(argv[1], "antenna") == 0) {
  203. ant_ = (Antenna*) obj;
  204. return TCL_OK;
  205. } else if (strcasecmp(argv[1], "node") == 0) {
  206. assert(node_ == 0);
  207. node_ = (Node *)obj;
  208. return TCL_OK;
  209. } else  if (strcmp(argv[1], "powerProfile") == 0) {
  210. profile_ = (PowerProfile *) TclObject::lookup(argv[2]);
  211. if (profile_ == 0)
  212. return TCL_ERROR;
  213. return TCL_OK;
  214. }
  215. }
  216. return Phy::command(argc,argv);
  217. }
  218.  
  219. void 
  220. PAWirelessPhy::sendDown(Packet *p)
  221. {
  222. /*
  223.  * Sanity Check
  224.  */
  225. assert(initialized());
  226. if (em()) {
  227. if (Is_node_on() != true ) {
  228. //node is off here...
  229. Packet::free(p);
  230. return;
  231. }
  232. if(Is_node_on() == true && Is_sleeping() == true){
  233. em()-> DecrSleepEnergy(NOW-update_energy_time_,
  234.        P_sleep_);
  235. update_energy_time_ = NOW;
  236. }
  237. }
  238. /*
  239.  * Decrease node's energy
  240.  */
  241. if(em()) {
  242. if (em()->energy() > 0) {
  243.     double txtime = hdr_cmn::access(p)->txtime();
  244.     double start_time = MAX(channel_idle_time_, NOW);
  245.     double end_time = MAX(channel_idle_time_, NOW+txtime);
  246.     double actual_txtime = end_time-start_time;
  247.     if (start_time > update_energy_time_) {
  248.     em()->DecrIdleEnergy(start_time - 
  249.  update_energy_time_, P_idle_);
  250.     update_energy_time_ = start_time;
  251.     }
  252.     /* It turns out that MAC sends packet even though, it's
  253.        receiving some packets.
  254.     
  255.     if (txtime-actual_txtime > 0.000001) {
  256.     fprintf(stderr,"Something may be wrong at MACn");
  257.     fprintf(stderr,"act_tx = %lf, tx = %lfn", actual_txtime, txtime);
  258.     }
  259.     */
  260.    // Sanity check
  261.    double temp = MAX(NOW,last_send_time_);
  262.    /*
  263.    if (NOW < last_send_time_) {
  264.    fprintf(stderr,"Argggg !! Overlapping transmission. NOW %lf last %lf temp %lfn", NOW, last_send_time_, temp);
  265.    }
  266.    */
  267.    
  268.    double begin_adjust_time = MIN(channel_idle_time_, temp);
  269.    double finish_adjust_time = MIN(channel_idle_time_, NOW+txtime);
  270.    double gap_adjust_time = finish_adjust_time - begin_adjust_time;
  271.    if (gap_adjust_time < 0.0) {
  272.    fprintf(stderr,"What the heck ! negative gap time.n");
  273.    }
  274.    if ((gap_adjust_time > 0.0) && (status_ == RECV)) {
  275.    em()->DecrTxEnergy(gap_adjust_time,
  276.       Pt_consume_-Pr_consume_);
  277.    }
  278.    em()->DecrTxEnergy(actual_txtime,Pt_consume_);
  279. //    if (end_time > channel_idle_time_) {
  280. //    status_ = SEND;
  281. //    }
  282. //
  283.    status_ = IDLE;
  284.    last_send_time_ = NOW+txtime;
  285.    channel_idle_time_ = end_time;
  286.    update_energy_time_ = end_time;
  287.    if (em()->energy() <= 0) {
  288.    em()->setenergy(0);
  289.    ((MobileNode*)node())->log_energy(0);
  290.    }
  291. } else {
  292. // log node energy
  293. if (em()->energy() > 0) {
  294. ((MobileNode *)node_)->log_energy(1);
  295. //
  296. Packet::free(p);
  297. return;
  298. }
  299. }
  300. /*
  301.  *  Stamp the packet with the interface arguments
  302.  */
  303. p->txinfo_.stamp((MobileNode*)node(), ant_->copy(), Pt_, lambda_);
  304. // Send the packet
  305. channel_->recv(p, this);
  306. }
  307. int 
  308. PAWirelessPhy::sendUp(Packet *p)
  309. {
  310. /*
  311.  * Sanity Check
  312.  */
  313. assert(initialized());
  314. PacketStamp s;
  315. double Pr;
  316. int pkt_recvd = 1; // [Nicola] Changed default value, removed spaghetti code below
  317. Pr = p->txinfo_.getTxPr();
  318. if (em()) {
  319. // Drop the packet if the node is either OFF, SLEEPING, 
  320. // or if it has ZERO ENERGY
  321. if ((Is_node_on()== false) || (Is_sleeping()==true) || (em()->energy() <= 0)) {
  322. pkt_recvd = 0;
  323. }
  324. }
  325. if(propagation_) {
  326. s.stamp((MobileNode*)node(), ant_, 0, lambda_);
  327. Pr = propagation_->Pr(p, &p->txinfo_, &s, getL(), getLambda());
  328. if (Pr < CSThresh_) {
  329. pkt_recvd = 0;
  330. }
  331. // ---------------------------------------------
  332. // [Nicola] Removed because we're dealing with 
  333. //     RX success somewhere else
  334. // --------------------------------------------
  335. //  if (Pr < RXThresh_) {
  336. //  /*
  337. //   * We can detect, but not successfully receive
  338. //   * this packet.
  339. //   */
  340. //  hdr_cmn *hdr = HDR_CMN(p);
  341. //  hdr->error() = 1;
  342. // #if DEBUG > 3
  343. //  printf("SM %f.9 _%d_ drop pkt from %d low POWER %e/%en",
  344. //         Scheduler::instance().clock(), node()->index(),
  345. //         p->txinfo_.getNode()->index(),
  346. //         Pr,RXThresh);
  347. // #endif
  348. //  }
  349. }
  350. // ---------------------
  351. // [Nicola] Removed because:
  352. //  1) the only available modulation module implementation is almost fake
  353. //  2) errors will be handled somewhere else through SNIR
  354. //  if(modulation_) {
  355. //  hdr_cmn *hdr = HDR_CMN(p);
  356. //  hdr->error() = modulation_->BitError(Pr);
  357. //  }
  358. // ---------------------
  359. /*
  360.  * The MAC layer must be notified of the packet reception
  361.  * now - ie; when the first bit has been detected - so that
  362.  * it can properly do Collision Avoidance / Detection.
  363.  */
  364.  
  365. /*
  366. Federico  27/04/2006 - I need to gnerate an event when the trasmission ends, in order to decrease the instant power
  367. */
  368. if(debug_>1) printf("%f - WirelessPhy.sendUp - receivePower=%-2.20fn", Scheduler::instance().clock(),Pr);
  369. increasePower(Pr);
  370. powerTimer_.addEvent(Scheduler::instance().clock() + hdr_cmn::access(p)->txtime(), -Pr);
  371. p->txinfo_.getAntenna()->release();
  372. /* WILD HACK: The following two variables are a wild hack.
  373.    They will go away in the next release...
  374.    They're used by the mac-802_11 object to determine
  375.    capture.  This will be moved into the net-if family of 
  376.    objects in the future. */
  377. p->txinfo_.RxPr = Pr;
  378. // [Nicola] CTPhresh was part of the WILD HACK above, we don't need it any more...
  379. // p->txinfo_.CPThresh = CPThresh_;
  380. /*
  381.  * Decrease energy if packet successfully received
  382.  */
  383. if(pkt_recvd && em()) {
  384. double rcvtime = hdr_cmn::access(p)->txtime();
  385. // no way to reach here if the energy level < 0
  386. double start_time = MAX(channel_idle_time_, NOW);
  387. double end_time = MAX(channel_idle_time_, NOW+rcvtime);
  388. double actual_rcvtime = end_time-start_time;
  389. if (start_time > update_energy_time_) {
  390. em()->DecrIdleEnergy(start_time-update_energy_time_,
  391.      P_idle_);
  392. update_energy_time_ = start_time;
  393. }
  394. em()->DecrRcvEnergy(actual_rcvtime,Pr_consume_);
  395. /*
  396.   if (end_time > channel_idle_time_) {
  397.   status_ = RECV;
  398.   }
  399. */
  400. channel_idle_time_ = end_time;
  401. update_energy_time_ = end_time;
  402. status_ = IDLE;
  403. /*
  404.   hdr_diff *dfh = HDR_DIFF(p);
  405.   printf("Node %d receives (%d, %d, %d) energy %lf.n",
  406.   node()->address(), dfh->sender_id.addr_, 
  407.   dfh->sender_id.port_, dfh->pk_num, node()->energy());
  408. */
  409. // log node energy
  410. if (em()->energy() > 0) {
  411. ((MobileNode *)node_)->log_energy(1);
  412.          } 
  413. if (em()->energy() <= 0) {  
  414. // saying node died
  415. em()->setenergy(0);
  416. ((MobileNode*)node())->log_energy(0);
  417. }
  418. }
  419. return pkt_recvd;
  420. }
  421. void
  422. PAWirelessPhy::node_on()
  423. {
  424.         node_on_= TRUE;
  425. status_ = IDLE;
  426.        if (em() == NULL)
  427.       return;
  428.     if (NOW > update_energy_time_) {
  429.            update_energy_time_ = NOW;
  430.     }
  431. }
  432. void 
  433. PAWirelessPhy::node_off()
  434. {
  435.         node_on_= FALSE;
  436. status_ = SLEEP;
  437. if (em() == NULL)
  438.             return;
  439.         if (NOW > update_energy_time_) {
  440.             em()->DecrIdleEnergy(NOW-update_energy_time_,
  441.                                 P_idle_);
  442.             update_energy_time_ = NOW;
  443. }
  444. }
  445. void 
  446. PAWirelessPhy::node_wakeup()
  447. {
  448. if (status_== IDLE)
  449. return;
  450. if (em() == NULL)
  451.             return;
  452.         if ( NOW > update_energy_time_ && (status_== SLEEP) ) {
  453. //the power consumption when radio goes from SLEEP mode to IDLE mode
  454. em()->DecrTransitionEnergy(T_transition_,P_transition_);
  455. em()->DecrSleepEnergy(NOW-update_energy_time_,
  456.       P_sleep_);
  457. status_ = IDLE;
  458.         update_energy_time_ = NOW;
  459. // log node energy
  460. if (em()->energy() > 0) {
  461. ((MobileNode *)node_)->log_energy(1);
  462.         } else {
  463. ((MobileNode *)node_)->log_energy(0);   
  464.         }
  465. }
  466. }
  467. void 
  468. PAWirelessPhy::node_sleep()
  469. {
  470. //
  471. //        node_on_= FALSE;
  472. //
  473. if (status_== SLEEP)
  474. return;
  475. if (em() == NULL)
  476.             return;
  477.         if ( NOW > update_energy_time_ && (status_== IDLE) ) {
  478. //the power consumption when radio goes from IDLE mode to SLEEP mode
  479.     em()->DecrTransitionEnergy(T_transition_,P_transition_);
  480.             em()->DecrIdleEnergy(NOW-update_energy_time_,
  481.                                 P_idle_);
  482. status_ = SLEEP;
  483.         update_energy_time_ = NOW;
  484. // log node energy
  485. if (em()->energy() > 0) {
  486. ((MobileNode *)node_)->log_energy(1);
  487.         } else {
  488. ((MobileNode *)node_)->log_energy(0);   
  489.         }
  490. }
  491. }
  492. //
  493. void
  494. PAWirelessPhy::dump(void) const
  495. {
  496. Phy::dump();
  497. fprintf(stdout,
  498. "tPt: %f, Gt: %f, Gr: %f, lambda: %f, L: %fn",
  499. Pt_, ant_->getTxGain(0,0,0,lambda_), ant_->getRxGain(0,0,0,lambda_), lambda_, L_);
  500. //fprintf(stdout, "tbandwidth: %fn", bandwidth_);
  501. fprintf(stdout, "--------------------------------------------------n");
  502. }
  503. void PAWirelessPhy::UpdateIdleEnergy()
  504. {
  505. if (em() == NULL) {
  506. return;
  507. }
  508. if (NOW > update_energy_time_ && (Is_node_on()==TRUE && status_ == IDLE ) ) {
  509.   em()-> DecrIdleEnergy(NOW-update_energy_time_,
  510. P_idle_);
  511.   update_energy_time_ = NOW;
  512. }
  513. // log node energy
  514. if (em()->energy() > 0) {
  515. ((MobileNode *)node_)->log_energy(1);
  516.         } else {
  517. ((MobileNode *)node_)->log_energy(0);   
  518.         }
  519. // idle_timer_.resched(10.0);
  520. }
  521. double PAWirelessPhy::getDist(double Pr, double Pt, double Gt, double Gr,
  522.     double hr, double ht, double L, double lambda)
  523. {
  524. if (propagation_) {
  525. return propagation_->getDist(Pr, Pt, Gt, Gr, hr, ht, L,
  526.      lambda);
  527. }
  528. return 0;
  529. }
  530. //
  531. void PAWirelessPhy::UpdateSleepEnergy()
  532. {
  533. if (em() == NULL) {
  534. return;
  535. }
  536. if (NOW > update_energy_time_ && ( Is_node_on()==TRUE  && Is_sleeping() == true) ) {
  537.   em()-> DecrSleepEnergy(NOW-update_energy_time_,
  538. P_sleep_);
  539.   update_energy_time_ = NOW;
  540. // log node energy
  541. if (em()->energy() > 0) {
  542. ((MobileNode *)node_)->log_energy(1);
  543.          } else {
  544. ((MobileNode *)node_)->log_energy(0);   
  545.          }
  546. }
  547. //A hack to make states consistent with those of in Energy Model for AF
  548. int static s=em()->sleep();
  549. if(em()->sleep()!=s){
  550. s=em()->sleep();
  551. if(s==1)
  552. node_sleep();
  553. else
  554. node_wakeup();
  555. printf("n AF hack %dn",em()->sleep());
  556. }
  557. sleep_timer_.resched(10.0);
  558. }
  559. void PAWirelessPhy::increasePower(double power)
  560. {
  561. if(profile_)
  562. {
  563. PowerElement el;
  564. el.power = power;
  565. el.time = Scheduler::instance().clock();
  566. if(debug_) printf("%f - WirelessPhy.increasePower - Power=%-2.20fn", Scheduler::instance().clock(),power);
  567. profile_->addElement(el);
  568. }
  569. }