/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- * * Copyright (c) 1997, 2000 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the Computer Systems * Engineering Group at Lawrence Berkeley Laboratory. * 4. Neither the name of the University nor of the Laboratory may be used * to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Header: /nfs/jade/vint/CVSROOT/ns-2/mobile/energy-model.cc,v 1.5 2000/08/31 20:11:49 haoboy Exp $ */ // Contributed by Satish Kumar #include #include #include "random.h" #include "energy-model.h" #include "mobilenode.h" #include "god.h" static class EnergyModelClass : public TclClass { public: EnergyModelClass ():TclClass ("EnergyModel") {} TclObject *create (int argc, const char *const *argv) { if (argc == 8) { MobileNode *n=(MobileNode*)TclObject::lookup(argv[4]); return (new EnergyModel(n, atof(argv[5]), atof(argv[6]), atof(argv[7]))); } else { Tcl::instance().add_error("Wrong arguments to ErrorModel"); return 0; } } } class_energy_model; void EnergyModel::DecrTxEnergy(double txtime, double P_tx) { double dEng = P_tx * txtime; if (energy_ <= dEng) energy_ = 0.0; else energy_ = energy_ - dEng; if (energy_ <= 0.0) God::instance()->ComputeRoute(); } void EnergyModel::DecrRcvEnergy(double rcvtime, double P_rcv) { double dEng = P_rcv * rcvtime; if (energy_ <= dEng) energy_ = 0.0; else energy_ = energy_ - dEng; if (energy_ <= 0.0) God::instance()->ComputeRoute(); } void EnergyModel::DecrIdleEnergy(double idletime, double P_idle) { double dEng = P_idle * idletime; if (energy_ <= dEng) energy_ = 0.0; else energy_ = energy_ - dEng; if (energy_ <= 0.0) God::instance()->ComputeRoute(); } //Iyappan added this function void EnergyModel::DecrSleepEnergy(double sleeptime, double P_sleep) { double dEng = P_sleep * sleeptime; if (energy_ <= dEng) energy_ = 0.0; else energy_ = energy_ - dEng; if (energy_ <= 0.0) God::instance()->ComputeRoute(); } // XXX Moved from node.cc. These wireless stuff should NOT stay in the // base node. void EnergyModel::start_powersaving() { snh_ = new SoftNeighborHandler(this); snh_->start(); afe_ = new AdaptiveFidelityEntity(this); afe_->start(); state_ = EnergyModel::POWERSAVING; state_start_time_ = Scheduler::instance().clock(); } void EnergyModel::set_node_sleep(int status) { Tcl& tcl=Tcl::instance(); //static float last_time_gosleep; // status = 1 to set node into sleep mode // status = 0 to put node back to idle mode. // time in the sleep mode should be used as credit to idle // time energy consumption if (status) { last_time_gosleep = Scheduler::instance().clock(); //printf("id=%d : put node into sleep at %f\n", // address_,last_time_gosleep); sleep_mode_ = status; if (node_->exist_namchan()) tcl.evalf("%s add-mark m1 blue hexagon",node_->name()); } else { sleep_mode_ = status; if (node_->exist_namchan()) tcl.evalf("%s delete-mark m1", node_->name()); //printf("id= %d last_time_sleep = %f\n", // address_, last_time_gosleep); if (last_time_gosleep) { total_sleeptime_ += Scheduler::instance().clock() - last_time_gosleep; last_time_gosleep = 0; } } } void EnergyModel::set_node_state(int state) { switch (state_) { case POWERSAVING: case WAITING: state_ = state; state_start_time_ = Scheduler::instance().clock(); break; case INROUTE: if (state == POWERSAVING) { state_ = state; } else if (state == INROUTE) { // a data packet is forwarded, needs to reset // state_start_time_ state_start_time_= Scheduler::instance().clock(); } break; default: printf("Wrong state, quit...\n"); abort(); } } void EnergyModel::add_neighbor(u_int32_t nodeid) { neighbor_list_item *np; np = neighbor_list.head; for (; np; np = np->next) { if (np->id == nodeid) { np->ttl = maxttl_; break; } } if (!np) { // insert this new entry np = new neighbor_list_item; np->id = nodeid; np->ttl = maxttl_; np->next = neighbor_list.head; neighbor_list.head = np; neighbor_list.neighbor_cnt_++; } } void EnergyModel::scan_neighbor() { neighbor_list_item *np, *lp; if (neighbor_list.neighbor_cnt_ > 0) { lp = neighbor_list.head; np = lp->next; for (; np; np = np->next) { np->ttl--; if (np->ttl <= 0){ lp->next = np->next; delete np; np = lp; neighbor_list.neighbor_cnt_--; } lp = np; } // process the first element np = neighbor_list.head; np->ttl--; if (np->ttl <= 0) { neighbor_list.head = np->next; delete np; neighbor_list.neighbor_cnt_--; } } } void SoftNeighborHandler::start() { Scheduler::instance().schedule(this, &intr, CHECKFREQ); } void SoftNeighborHandler::handle(Event *) { Scheduler &s = Scheduler::instance(); nid_->scan_neighbor(); s.schedule(this, &intr, CHECKFREQ); } void AdaptiveFidelityEntity::start() { sleep_time_ = 2; sleep_seed_ = 2; idle_time_ = 10; nid_->set_node_sleep(0); Scheduler::instance().schedule(this, &intr, Random::uniform(0, idle_time_)); } void AdaptiveFidelityEntity::handle(Event *) { Scheduler &s = Scheduler::instance(); int node_state = nid_->state(); switch (node_state) { case EnergyModel::POWERSAVING: if (nid_->sleep()) { // node is in sleep mode, wake it up nid_->set_node_sleep(0); adapt_it(); s.schedule(this, &intr, idle_time_); } else { // node is in idle mode, put it into sleep nid_->set_node_sleep(1); adapt_it(); s.schedule(this, &intr, sleep_time_); } break; case EnergyModel::INROUTE: // 100s is the maximum INROUTE time. if (s.clock()-(nid_->state_start_time()) < nid_->max_inroute_time()) { s.schedule(this, &intr, idle_time_); } else { nid_->set_node_state(EnergyModel::POWERSAVING); adapt_it(); nid_->set_node_sleep(1); s.schedule(this, &intr, sleep_time_); } break; case EnergyModel::WAITING: // 10s is the maximum WAITING time if (s.clock()-(nid_->state_start_time()) < MAX_WAITING_TIME) { s.schedule(this, &intr, idle_time_); } else { nid_->set_node_state(EnergyModel::POWERSAVING); adapt_it(); nid_->set_node_sleep(1); s.schedule(this, &intr, sleep_time_); } break; default: fprintf(stderr, "Illegal Node State!"); abort(); } } void AdaptiveFidelityEntity::adapt_it() { float delay; // use adaptive fidelity if (nid_->adaptivefidelity()) { int neighbors = nid_->getneighbors(); if (!neighbors) neighbors = 1; delay = sleep_seed_ * Random::uniform(1,neighbors); set_sleeptime(delay); } }