energy-model.cc

Go to the documentation of this file.
00001 /* -*-  Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- 
00002  *
00003  * Copyright (c) 1997, 2000 Regents of the University of California.
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  * 3. All advertising materials mentioning features or use of this software
00015  *    must display the following acknowledgement:
00016  *  This product includes software developed by the Computer Systems
00017  *  Engineering Group at Lawrence Berkeley Laboratory.
00018  * 4. Neither the name of the University nor of the Laboratory may be used
00019  *    to endorse or promote products derived from this software without
00020  *    specific prior written permission.
00021  *
00022  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00023  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00024  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00025  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00026  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00027  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00028  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00029  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00031  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00032  * SUCH DAMAGE.
00033  *
00034  * $Header: /nfs/jade/vint/CVSROOT/ns-2/mobile/energy-model.cc,v 1.6 2005/06/13 17:50:41 haldar Exp $
00035  */
00036 
00037 // Contributed by Satish Kumar <kkumar@isi.edu>
00038 
00039 #include <stdarg.h>
00040 #include <float.h>
00041 
00042 #include "random.h"
00043 #include "energy-model.h"
00044 #include "mobilenode.h"
00045 #include "god.h"
00046 
00047 static class EnergyModelClass : public TclClass
00048 {
00049 public:
00050     EnergyModelClass ():TclClass ("EnergyModel") {}
00051     TclObject *create (int argc, const char *const *argv) {
00052         if (argc == 8) {
00053             MobileNode *n=(MobileNode*)TclObject::lookup(argv[4]);
00054             return (new EnergyModel(n, atof(argv[5]), 
00055                         atof(argv[6]), atof(argv[7])));
00056         } else {
00057             Tcl::instance().add_error("Wrong arguments to ErrorModel");
00058             return 0;
00059         }
00060     }
00061 } class_energy_model;
00062 
00063 void EnergyModel::DecrTxEnergy(double txtime, double P_tx) 
00064 {
00065     double dEng = P_tx * txtime;
00066     if (energy_ <= dEng)
00067         energy_ = 0.0;
00068     else
00069         energy_ = energy_ - dEng;
00070     if (energy_ <= 0.0)
00071         God::instance()->ComputeRoute();
00072 //
00073     // This variable keeps track of total energy consumption in Transmission..
00074     et_=et_+dEng;
00075 //
00076 }
00077 
00078 
00079 void EnergyModel::DecrRcvEnergy(double rcvtime, double P_rcv) 
00080 {
00081     double dEng = P_rcv * rcvtime;
00082     if (energy_ <= dEng)
00083         energy_ = 0.0;
00084     else
00085         energy_ = energy_ - dEng;
00086     if (energy_ <= 0.0)
00087         God::instance()->ComputeRoute();
00088 //
00089     // This variable keeps track of total energy consumption in RECV mode..
00090     er_=er_+dEng;
00091 //
00092 }
00093 
00094 void EnergyModel::DecrIdleEnergy(double idletime, double P_idle) 
00095 {
00096     double dEng = P_idle * idletime;
00097     if (energy_ <= dEng)
00098         energy_ = 0.0;
00099     else
00100         energy_ = energy_ - dEng;
00101     if (energy_ <= 0.0)
00102         God::instance()->ComputeRoute();
00103 //
00104     // This variable keeps track of total energy consumption in IDLE mode..
00105     ei_=ei_+dEng;
00106 //
00107 }
00108 
00109 //
00110 void EnergyModel::DecrSleepEnergy(double sleeptime, double P_sleep) 
00111 {
00112     double dEng = P_sleep * sleeptime;
00113     if (energy_ <= dEng)
00114         energy_ = 0.0;
00115     else
00116         energy_ = energy_ - dEng;
00117     if (energy_ <= 0.0)
00118         God::instance()->ComputeRoute();
00119 
00120     // This variable keeps track of total energy consumption in SLEEP mode..
00121     es_=es_+dEng;
00122 }
00123 
00124 void EnergyModel::DecrTransitionEnergy(double transitiontime, double P_transition) 
00125 {
00126     double dEng = P_transition * transitiontime;
00127     if (energy_ <= dEng)
00128         energy_ = 0.0;
00129     else
00130         energy_ = energy_ - dEng;
00131     if (energy_ <= 0.0)
00132         God::instance()->ComputeRoute();
00133 }
00134 //
00135 
00136 // XXX Moved from node.cc. These wireless stuff should NOT stay in the 
00137 // base node.
00138 void EnergyModel::start_powersaving()
00139 {
00140     snh_ = new SoftNeighborHandler(this);
00141     snh_->start();
00142     
00143     afe_ = new AdaptiveFidelityEntity(this);
00144     afe_->start();
00145 
00146     state_ = EnergyModel::POWERSAVING;
00147     state_start_time_ = Scheduler::instance().clock();
00148 }
00149 
00150 void EnergyModel::set_node_sleep(int status)
00151 {
00152     Tcl& tcl=Tcl::instance();
00153     //static float last_time_gosleep;
00154     // status = 1 to set node into sleep mode
00155     // status = 0 to put node back to idle mode.
00156     // time in the sleep mode should be used as credit to idle 
00157     // time energy consumption
00158     if (status) {
00159         last_time_gosleep = Scheduler::instance().clock();
00160         //printf("id=%d : put node into sleep at %f\n",
00161         // address_,last_time_gosleep);
00162         sleep_mode_ = status;
00163         if (node_->exist_namchan()) 
00164             tcl.evalf("%s add-mark m1 blue hexagon",node_->name());
00165     } else {
00166         sleep_mode_ = status;
00167         if (node_->exist_namchan()) 
00168             tcl.evalf("%s delete-mark m1", node_->name()); 
00169         //printf("id= %d last_time_sleep = %f\n",
00170         // address_, last_time_gosleep);
00171         if (last_time_gosleep) {
00172             total_sleeptime_ += Scheduler::instance().clock() -
00173                 last_time_gosleep;
00174             last_time_gosleep = 0;
00175         }
00176     }   
00177 }
00178 
00179 void EnergyModel::set_node_state(int state)
00180 {
00181     switch (state_) { 
00182     case POWERSAVING:
00183     case WAITING:
00184         state_ = state;
00185         state_start_time_ = Scheduler::instance().clock();
00186         break;
00187     case INROUTE:
00188         if (state == POWERSAVING) {
00189             state_ = state;
00190         } else if (state == INROUTE) {
00191             // a data packet is forwarded, needs to reset 
00192             // state_start_time_
00193             state_start_time_= Scheduler::instance().clock();
00194         }
00195         break;
00196     default:
00197         printf("Wrong state, quit...\n");
00198         abort();
00199     }
00200 }
00201 
00202 void EnergyModel::add_neighbor(u_int32_t nodeid)
00203 {
00204     neighbor_list_item *np;
00205     np = neighbor_list.head;
00206     for (; np; np = np->next) {
00207         if (np->id == nodeid) {
00208             np->ttl = maxttl_;
00209             break;
00210         }
00211     }
00212     if (!np) {      // insert this new entry
00213         np = new neighbor_list_item;
00214         np->id = nodeid;
00215         np->ttl = maxttl_;
00216         np->next = neighbor_list.head;
00217         neighbor_list.head = np;
00218         neighbor_list.neighbor_cnt_++;
00219     }
00220 }
00221 
00222 void EnergyModel::scan_neighbor()
00223 {
00224     neighbor_list_item *np, *lp;
00225     if (neighbor_list.neighbor_cnt_ > 0) {
00226         lp = neighbor_list.head;
00227         np = lp->next;
00228         for (; np; np = np->next) {
00229             np->ttl--;
00230             if (np->ttl <= 0){
00231                 lp->next = np->next;
00232                 delete np;
00233                 np = lp;
00234                 neighbor_list.neighbor_cnt_--;
00235             } 
00236             lp = np;
00237         }
00238         // process the first element
00239         np = neighbor_list.head;
00240         np->ttl--;
00241         if (np->ttl <= 0) {
00242             neighbor_list.head = np->next;
00243             delete np;
00244             neighbor_list.neighbor_cnt_--;
00245         }
00246     }
00247 }
00248 
00249 
00250 void SoftNeighborHandler::start()
00251 {
00252     Scheduler::instance().schedule(this, &intr, CHECKFREQ);
00253 }
00254 
00255 void SoftNeighborHandler::handle(Event *)
00256 {
00257     Scheduler &s = Scheduler::instance();
00258     nid_->scan_neighbor();
00259     s.schedule(this, &intr, CHECKFREQ);
00260 }
00261 
00262 void AdaptiveFidelityEntity::start()
00263 {
00264     sleep_time_ = 2;
00265     sleep_seed_ = 2;
00266     idle_time_ = 10;
00267     nid_->set_node_sleep(0);
00268     Scheduler::instance().schedule(this, &intr, 
00269                        Random::uniform(0, idle_time_));
00270 }
00271 
00272 void AdaptiveFidelityEntity::handle(Event *)
00273 {
00274     Scheduler &s = Scheduler::instance();
00275     int node_state = nid_->state();
00276     switch (node_state) {
00277     case EnergyModel::POWERSAVING:
00278         if (nid_->sleep()) {
00279             // node is in sleep mode, wake it up
00280             nid_->set_node_sleep(0);
00281             adapt_it();
00282             s.schedule(this, &intr, idle_time_);
00283         } else {
00284             // node is in idle mode, put it into sleep
00285             nid_->set_node_sleep(1);
00286             adapt_it();
00287             s.schedule(this, &intr, sleep_time_);
00288         }
00289         break;
00290     case EnergyModel::INROUTE:
00291         // 100s is the maximum INROUTE time.
00292         if (s.clock()-(nid_->state_start_time()) < 
00293             nid_->max_inroute_time()) {
00294             s.schedule(this, &intr, idle_time_);
00295         } else {
00296             nid_->set_node_state(EnergyModel::POWERSAVING);
00297             adapt_it();
00298             nid_->set_node_sleep(1);
00299             s.schedule(this, &intr, sleep_time_); 
00300         }
00301         break;
00302     case EnergyModel::WAITING:
00303         // 10s is the maximum WAITING time
00304         if (s.clock()-(nid_->state_start_time()) < MAX_WAITING_TIME) {
00305             s.schedule(this, &intr, idle_time_);
00306         } else {
00307             nid_->set_node_state(EnergyModel::POWERSAVING);
00308             adapt_it();
00309             nid_->set_node_sleep(1);
00310             s.schedule(this, &intr, sleep_time_); 
00311         }
00312         break;
00313     default:
00314         fprintf(stderr, "Illegal Node State!");
00315         abort();
00316     }
00317 }
00318 
00319 void AdaptiveFidelityEntity::adapt_it()
00320 {
00321     float delay;
00322     // use adaptive fidelity
00323     if (nid_->adaptivefidelity()) {
00324         int neighbors = nid_->getneighbors();
00325         if (!neighbors) 
00326             neighbors = 1;
00327         delay = sleep_seed_ * Random::uniform(1,neighbors); 
00328             set_sleeptime(delay);
00329     }
00330 }
00331 

Generated on Tue Mar 6 16:47:44 2007 for ns2 Network Simulator 2.29 by  doxygen 1.4.6