wireless-phy.cc
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:15k
- /* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*-
- *
- * Copyright (c) 1996 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 and the Daedalus
- * research group at UC Berkeley.
- * 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: /cvsroot/nsnam/ns-2/mac/wireless-phy.cc,v 1.28 2007/09/04 04:32:18 tom_henderson Exp $
- *
- * Ported from CMU/Monarch's code, nov'98 -Padma Haldar.
- * wireless-phy.cc
- */
- #include <math.h>
- #include <packet.h>
- #include <mobilenode.h>
- #include <phy.h>
- #include <propagation.h>
- #include <modulation.h>
- #include <omni-antenna.h>
- #include <wireless-phy.h>
- #include <packet.h>
- #include <ip.h>
- #include <agent.h>
- #include <trace.h>
- #include <sys/param.h> /* for MIN/MAX */
- #include "diffusion/diff_header.h"
- void Sleep_Timer::expire(Event *) {
- a_->UpdateSleepEnergy();
- }
- /* ======================================================================
- WirelessPhy Interface
- ====================================================================== */
- static class WirelessPhyClass: public TclClass {
- public:
- WirelessPhyClass() : TclClass("Phy/WirelessPhy") {}
- TclObject* create(int, const char*const*) {
- return (new WirelessPhy);
- }
- } class_WirelessPhy;
- WirelessPhy::WirelessPhy() : Phy(), sleep_timer_(this), status_(IDLE)
- {
- /*
- * It sounds like 10db should be the capture threshold.
- *
- * If a node is presently receiving a packet a a power level
- * Pa, and a packet at power level Pb arrives, the following
- * comparion must be made to determine whether or not capture
- * occurs:
- *
- * 10 * log(Pa) - 10 * log(Pb) > 10db
- *
- * OR equivalently
- *
- * Pa/Pb > 10.
- *
- */
- bind("CPThresh_", &CPThresh_);
- bind("CSThresh_", &CSThresh_);
- bind("RXThresh_", &RXThresh_);
- //bind("bandwidth_", &bandwidth_);
- bind("Pt_", &Pt_);
- bind("freq_", &freq_);
- bind("L_", &L_);
-
- lambda_ = SPEED_OF_LIGHT / freq_;
- node_ = 0;
- ant_ = 0;
- propagation_ = 0;
- modulation_ = 0;
- // Assume AT&T's Wavelan PCMCIA card -- Chalermek
- // Pt_ = 8.5872e-4; // For 40m transmission range.
- // Pt_ = 7.214e-3; // For 100m transmission range.
- // Pt_ = 0.2818; // For 250m transmission range.
- // Pt_ = pow(10, 2.45) * 1e-3; // 24.5 dbm, ~ 281.8mw
-
- Pt_consume_ = 0.660; // 1.6 W drained power for transmission
- Pr_consume_ = 0.395; // 1.2 W drained power for reception
- // P_idle_ = 0.035; // 1.15 W drained power for idle
- P_idle_ = 0.0;
- P_sleep_ = 0.00;
- T_sleep_ = 10000;
- P_transition_ = 0.00;
- T_transition_ = 0.00; // 2.31 change: Was not initialized earlier
- node_on_=1;
-
- channel_idle_time_ = NOW;
- update_energy_time_ = NOW;
- last_send_time_ = NOW;
-
- sleep_timer_.resched(1.0);
- }
- int
- WirelessPhy::command(int argc, const char*const* argv)
- {
- TclObject *obj;
- if (argc==2) {
- if (strcasecmp(argv[1], "NodeOn") == 0) {
- node_on();
- if (em() == NULL)
- return TCL_OK;
- if (NOW > update_energy_time_) {
- update_energy_time_ = NOW;
- }
- return TCL_OK;
- } else if (strcasecmp(argv[1], "NodeOff") == 0) {
- node_off();
- if (em() == NULL)
- return TCL_OK;
- if (NOW > update_energy_time_) {
- em()->DecrIdleEnergy(NOW-update_energy_time_,
- P_idle_);
- update_energy_time_ = NOW;
- }
- return TCL_OK;
- }
- } else if(argc == 3) {
- if (strcasecmp(argv[1], "setTxPower") == 0) {
- Pt_consume_ = atof(argv[2]);
- return TCL_OK;
- } else if (strcasecmp(argv[1], "setRxPower") == 0) {
- Pr_consume_ = atof(argv[2]);
- return TCL_OK;
- } else if (strcasecmp(argv[1], "setIdlePower") == 0) {
- P_idle_ = atof(argv[2]);
- return TCL_OK;
- }else if (strcasecmp(argv[1], "setSleepPower") == 0) {
- P_sleep_ = atof(argv[2]);
- return TCL_OK;
- }else if (strcasecmp(argv[1], "setSleepTime") == 0) {
- T_sleep_ = atof(argv[2]);
- return TCL_OK;
- } else if (strcasecmp(argv[1], "setTransitionPower") == 0) {
- P_transition_ = atof(argv[2]);
- return TCL_OK;
- } else if (strcasecmp(argv[1], "setTransitionTime") == 0) {
- T_transition_ = atof(argv[2]);
- return TCL_OK;
- }else if( (obj = TclObject::lookup(argv[2])) == 0) {
- fprintf(stderr,"WirelessPhy: %s lookup of %s failedn",
- argv[1], argv[2]);
- return TCL_ERROR;
- }else if (strcmp(argv[1], "propagation") == 0) {
- assert(propagation_ == 0);
- propagation_ = (Propagation*) obj;
- return TCL_OK;
- } else if (strcasecmp(argv[1], "antenna") == 0) {
- ant_ = (Antenna*) obj;
- return TCL_OK;
- } else if (strcasecmp(argv[1], "node") == 0) {
- assert(node_ == 0);
- node_ = (Node *)obj;
- return TCL_OK;
- }
- }
- return Phy::command(argc,argv);
- }
-
- void
- WirelessPhy::sendDown(Packet *p)
- {
- /*
- * Sanity Check
- */
- assert(initialized());
-
- if (em()) {
- //node is off here...
- if (Is_node_on() != true ) {
- Packet::free(p);
- return;
- }
- if(Is_node_on() == true && Is_sleeping() == true){
- em()-> DecrSleepEnergy(NOW-update_energy_time_,
- P_sleep_);
- update_energy_time_ = NOW;
- }
- }
- /*
- * Decrease node's energy
- */
- if(em()) {
- if (em()->energy() > 0) {
- double txtime = hdr_cmn::access(p)->txtime();
- double start_time = MAX(channel_idle_time_, NOW);
- double end_time = MAX(channel_idle_time_, NOW+txtime);
- double actual_txtime = end_time-start_time;
- if (start_time > update_energy_time_) {
- em()->DecrIdleEnergy(start_time -
- update_energy_time_, P_idle_);
- update_energy_time_ = start_time;
- }
- /* It turns out that MAC sends packet even though, it's
- receiving some packets.
-
- if (txtime-actual_txtime > 0.000001) {
- fprintf(stderr,"Something may be wrong at MACn");
- fprintf(stderr,"act_tx = %lf, tx = %lfn", actual_txtime, txtime);
- }
- */
- // Sanity check
- double temp = MAX(NOW,last_send_time_);
- /*
- if (NOW < last_send_time_) {
- fprintf(stderr,"Argggg !! Overlapping transmission. NOW %lf last %lf temp %lfn", NOW, last_send_time_, temp);
- }
- */
-
- double begin_adjust_time = MIN(channel_idle_time_, temp);
- double finish_adjust_time = MIN(channel_idle_time_, NOW+txtime);
- double gap_adjust_time = finish_adjust_time - begin_adjust_time;
- if (gap_adjust_time < 0.0) {
- fprintf(stderr,"What the heck ! negative gap time.n");
- }
- if ((gap_adjust_time > 0.0) && (status_ == RECV)) {
- em()->DecrTxEnergy(gap_adjust_time,
- Pt_consume_-Pr_consume_);
- }
- em()->DecrTxEnergy(actual_txtime,Pt_consume_);
- // if (end_time > channel_idle_time_) {
- // status_ = SEND;
- // }
- //
- status_ = IDLE;
- last_send_time_ = NOW+txtime;
- channel_idle_time_ = end_time;
- update_energy_time_ = end_time;
- if (em()->energy() <= 0) {
- em()->setenergy(0);
- ((MobileNode*)node())->log_energy(0);
- }
- } else {
- // log node energy
- if (em()->energy() > 0) {
- ((MobileNode *)node_)->log_energy(1);
- }
- //
- Packet::free(p);
- return;
- }
- }
- /*
- * Stamp the packet with the interface arguments
- */
- p->txinfo_.stamp((MobileNode*)node(), ant_->copy(), Pt_, lambda_);
-
- // Send the packet
- channel_->recv(p, this);
- }
- int
- WirelessPhy::sendUp(Packet *p)
- {
- /*
- * Sanity Check
- */
- assert(initialized());
- PacketStamp s;
- double Pr;
- int pkt_recvd = 0;
- Pr = p->txinfo_.getTxPr();
-
- // if the node is in sleeping mode, drop the packet simply
- if (em()) {
- if (Is_node_on()!= true){
- pkt_recvd = 0;
- goto DONE;
- }
- if (Is_sleeping()==true && (Is_node_on() == true)) {
- pkt_recvd = 0;
- goto DONE;
- }
-
- }
- // if the energy goes to ZERO, drop the packet simply
- if (em()) {
- if (em()->energy() <= 0) {
- pkt_recvd = 0;
- goto DONE;
- }
- }
- if(propagation_) {
- s.stamp((MobileNode*)node(), ant_, 0, lambda_);
- Pr = propagation_->Pr(&p->txinfo_, &s, this);
- if (Pr < CSThresh_) {
- pkt_recvd = 0;
- goto DONE;
- }
- if (Pr < RXThresh_) {
- /*
- * We can detect, but not successfully receive
- * this packet.
- */
- hdr_cmn *hdr = HDR_CMN(p);
- hdr->error() = 1;
- #if DEBUG > 3
- printf("SM %f.9 _%d_ drop pkt from %d low POWER %e/%en",
- Scheduler::instance().clock(), node()->index(),
- p->txinfo_.getNode()->index(),
- Pr,RXThresh);
- #endif
- }
- }
- if(modulation_) {
- hdr_cmn *hdr = HDR_CMN(p);
- hdr->error() = modulation_->BitError(Pr);
- }
-
- /*
- * The MAC layer must be notified of the packet reception
- * now - ie; when the first bit has been detected - so that
- * it can properly do Collision Avoidance / Detection.
- */
- pkt_recvd = 1;
- DONE:
- p->txinfo_.getAntenna()->release();
- /* WILD HACK: The following two variables are a wild hack.
- They will go away in the next release...
- They're used by the mac-802_11 object to determine
- capture. This will be moved into the net-if family of
- objects in the future. */
- p->txinfo_.RxPr = Pr;
- p->txinfo_.CPThresh = CPThresh_;
- /*
- * Decrease energy if packet successfully received
- */
- if(pkt_recvd && em()) {
- double rcvtime = hdr_cmn::access(p)->txtime();
- // no way to reach here if the energy level < 0
-
- double start_time = MAX(channel_idle_time_, NOW);
- double end_time = MAX(channel_idle_time_, NOW+rcvtime);
- double actual_rcvtime = end_time-start_time;
- if (start_time > update_energy_time_) {
- em()->DecrIdleEnergy(start_time-update_energy_time_,
- P_idle_);
- update_energy_time_ = start_time;
- }
-
- em()->DecrRcvEnergy(actual_rcvtime,Pr_consume_);
- /*
- if (end_time > channel_idle_time_) {
- status_ = RECV;
- }
- */
- channel_idle_time_ = end_time;
- update_energy_time_ = end_time;
- status_ = IDLE;
- /*
- hdr_diff *dfh = HDR_DIFF(p);
- printf("Node %d receives (%d, %d, %d) energy %lf.n",
- node()->address(), dfh->sender_id.addr_,
- dfh->sender_id.port_, dfh->pk_num, node()->energy());
- */
- // log node energy
- if (em()->energy() > 0) {
- ((MobileNode *)node_)->log_energy(1);
- }
- if (em()->energy() <= 0) {
- // saying node died
- em()->setenergy(0);
- ((MobileNode*)node())->log_energy(0);
- }
- }
-
- return pkt_recvd;
- }
- void
- WirelessPhy::node_on()
- {
- node_on_= TRUE;
- status_ = IDLE;
- if (em() == NULL)
- return;
- if (NOW > update_energy_time_) {
- update_energy_time_ = NOW;
- }
- }
- void
- WirelessPhy::node_off()
- {
- node_on_= FALSE;
- status_ = SLEEP;
- if (em() == NULL)
- return;
- if (NOW > update_energy_time_) {
- em()->DecrIdleEnergy(NOW-update_energy_time_,
- P_idle_);
- update_energy_time_ = NOW;
- }
- }
- void
- WirelessPhy::node_wakeup()
- {
- if (status_== IDLE)
- return;
- if (em() == NULL)
- return;
- if ( NOW > update_energy_time_ && (status_== SLEEP) ) {
- //the power consumption when radio goes from SLEEP mode to IDLE mode
- em()->DecrTransitionEnergy(T_transition_,P_transition_);
-
- em()->DecrSleepEnergy(NOW-update_energy_time_,
- P_sleep_);
- status_ = IDLE;
- update_energy_time_ = NOW;
-
- // log node energy
- if (em()->energy() > 0) {
- ((MobileNode *)node_)->log_energy(1);
- } else {
- ((MobileNode *)node_)->log_energy(0);
- }
- }
- }
- void
- WirelessPhy::node_sleep()
- {
- //
- // node_on_= FALSE;
- //
- if (status_== SLEEP)
- return;
- if (em() == NULL)
- return;
- if ( NOW > update_energy_time_ && (status_== IDLE) ) {
- //the power consumption when radio goes from IDLE mode to SLEEP mode
- em()->DecrTransitionEnergy(T_transition_,P_transition_);
- em()->DecrIdleEnergy(NOW-update_energy_time_,
- P_idle_);
- status_ = SLEEP;
- update_energy_time_ = NOW;
- // log node energy
- if (em()->energy() > 0) {
- ((MobileNode *)node_)->log_energy(1);
- } else {
- ((MobileNode *)node_)->log_energy(0);
- }
- }
- }
- //
- void
- WirelessPhy::dump(void) const
- {
- Phy::dump();
- fprintf(stdout,
- "tPt: %f, Gt: %f, Gr: %f, lambda: %f, L: %fn",
- Pt_, ant_->getTxGain(0,0,0,lambda_), ant_->getRxGain(0,0,0,lambda_), lambda_, L_);
- //fprintf(stdout, "tbandwidth: %fn", bandwidth_);
- fprintf(stdout, "--------------------------------------------------n");
- }
- void WirelessPhy::UpdateIdleEnergy()
- {
- if (em() == NULL) {
- return;
- }
- if (NOW > update_energy_time_ && (Is_node_on()==TRUE && status_ == IDLE ) ) {
- em()-> DecrIdleEnergy(NOW-update_energy_time_,
- P_idle_);
- update_energy_time_ = NOW;
- }
- // log node energy
- if (em()->energy() > 0) {
- ((MobileNode *)node_)->log_energy(1);
- } else {
- ((MobileNode *)node_)->log_energy(0);
- }
- // idle_timer_.resched(10.0);
- }
- double WirelessPhy::getDist(double Pr, double Pt, double Gt, double Gr,
- double hr, double ht, double L, double lambda)
- {
- if (propagation_) {
- return propagation_->getDist(Pr, Pt, Gt, Gr, hr, ht, L,
- lambda);
- }
- return 0;
- }
- //
- void WirelessPhy::UpdateSleepEnergy()
- {
- if (em() == NULL) {
- return;
- }
- if (NOW > update_energy_time_ && ( Is_node_on()==TRUE && Is_sleeping() == true) ) {
- em()-> DecrSleepEnergy(NOW-update_energy_time_,
- P_sleep_);
- update_energy_time_ = NOW;
- // log node energy
- if (em()->energy() > 0) {
- ((MobileNode *)node_)->log_energy(1);
- } else {
- ((MobileNode *)node_)->log_energy(0);
- }
- }
-
- //A hack to make states consistent with those of in Energy Model for AF
- int static s=em()->sleep();
- if(em()->sleep()!=s){
- s=em()->sleep();
- if(s==1)
- node_sleep();
- else
- node_wakeup();
- // printf("n AF hack %dn",em()->sleep());
- }
-
- sleep_timer_.resched(10.0);
- }