p802_15_4phy.cc

Go to the documentation of this file.
00001 /********************************************/
00002 /*     NS2 Simulator for IEEE 802.15.4      */
00003 /*           (per P802.15.4/D18)            */
00004 /*------------------------------------------*/
00005 /* by:        Jianliang Zheng               */
00006 /*        (zheng@ee.ccny.cuny.edu)          */
00007 /*              Myung J. Lee                */
00008 /*          (lee@ccny.cuny.edu)             */
00009 /*        ~~~~~~~~~~~~~~~~~~~~~~~~~         */
00010 /*           SAIT-CUNY Joint Lab            */
00011 /********************************************/
00012 
00013 // File:  p802_15_4phy.cc
00014 // Mode:  C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t
00015 
00016 // $Header: /nfs/jade/vint/CVSROOT/ns-2/wpan/p802_15_4phy.cc,v 1.3 2005/07/27 01:13:46 tomh Exp $
00017 
00018 /*
00019  * Copyright (c) 2003-2004 Samsung Advanced Institute of Technology and
00020  * The City University of New York. All rights reserved.
00021  *
00022  * Redistribution and use in source and binary forms, with or without
00023  * modification, are permitted provided that the following conditions
00024  * are met:
00025  * 1. Redistributions of source code must retain the above copyright
00026  *    notice, this list of conditions and the following disclaimer.
00027  * 2. Redistributions in binary form must reproduce the above copyright
00028  *    notice, this list of conditions and the following disclaimer in the
00029  *    documentation and/or other materials provided with the distribution.
00030  * 3. All advertising materials mentioning features or use of this software
00031  *    must display the following acknowledgement:
00032  *  This product includes software developed by the Joint Lab of Samsung 
00033  *      Advanced Institute of Technology and The City University of New York.
00034  * 4. Neither the name of Samsung Advanced Institute of Technology nor of 
00035  *    The City University of New York may be used to endorse or promote 
00036  *    products derived from this software without specific prior written 
00037  *    permission.
00038  *
00039  * THIS SOFTWARE IS PROVIDED BY THE JOINT LAB OF SAMSUNG ADVANCED INSTITUTE
00040  * OF TECHNOLOGY AND THE CITY UNIVERSITY OF NEW YORK ``AS IS'' AND ANY EXPRESS 
00041  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
00042  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 
00043  * NO EVENT SHALL SAMSUNG ADVANCED INSTITUTE OR THE CITY UNIVERSITY OF NEW YORK 
00044  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
00045  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 
00046  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
00047  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
00048  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 
00049  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00050  */
00051 
00052 
00053 #include "p802_15_4pkt.h"
00054 #include "p802_15_4phy.h"
00055 #include "p802_15_4mac.h"
00056 #include "p802_15_4sscs.h"
00057 #include "p802_15_4const.h"
00058 #include "p802_15_4timer.h"
00059 #include "p802_15_4trace.h"
00060 #include "p802_15_4fail.h"
00061 #include "p802_15_4nam.h"
00062 
00063 
00064 PHY_PIB Phy802_15_4::PPIB =
00065 {
00066     def_phyCurrentChannel,
00067     def_phyChannelsSupported,
00068     def_phyTransmitPower,
00069     def_phyCCAMode
00070 };
00071 
00072 void Phy802_15_4Timer::start(double wtime)
00073 {
00074     active = true;
00075     nullEvent.uid_ = 0;
00076     Scheduler::instance().schedule(this,&nullEvent,wtime);
00077 }
00078 
00079 void Phy802_15_4Timer::cancel(void)
00080 {
00081     active = false;
00082     Scheduler::instance().cancel(&nullEvent);
00083 }
00084 
00085 void Phy802_15_4Timer::handle(Event* e)
00086 {
00087     active = false;
00088     if (type == phyCCAHType)
00089         phy->CCAHandler();
00090     else if(type == phyEDHType)
00091         phy->EDHandler();
00092     else if(type == phyTRXHType)
00093         phy->TRXHandler();
00094     else if(type == phyRecvOverHType)
00095         phy->recvOverHandler((Packet *)e);
00096     else if(type == phySendOverHType)
00097         phy->sendOverHandler();
00098     else    
00099         assert(0);
00100 }
00101 
00102 static class Phy802_15_4Class : public TclClass {
00103 public:
00104     Phy802_15_4Class() : TclClass("Phy/WirelessPhy/802_15_4") {}
00105     TclObject* create(int, const char*const*) {
00106         return (new Phy802_15_4(&(Phy802_15_4::PPIB)));
00107     }
00108 } class_Phy802_15_4;
00109 
00110 Phy802_15_4::Phy802_15_4(PHY_PIB *pp)
00111 : WirelessPhy(),
00112   CCAH(this, phyCCAHType),
00113   EDH(this, phyEDHType),
00114   TRXH(this, phyTRXHType),
00115   recvOverH(this, phyRecvOverHType),
00116   sendOverH(this, phySendOverHType)
00117 {
00118     int i;
00119     ppib = *pp;
00120     trx_state = p_RX_ON;
00121     trx_state_defer_set = p_IDLE;
00122     tx_state = p_IDLE;
00123     rxPkt = 0;
00124     for (i=0;i<27;i++)
00125     {
00126         rxTotPower[i] = 0.0;
00127         rxTotNum[i] = 0;
00128         rxThisTotNum[i] = 0;
00129     }
00130     mac = 0;
00131 }
00132 
00133 void Phy802_15_4::macObj(Mac802_15_4 *m)
00134 {
00135     mac = m;
00136 }
00137 
00138 bool Phy802_15_4::channelSupported(UINT_8 channel)
00139 {
00140     return ((ppib.phyChannelsSupported & (1 << channel)) != 0);
00141 }
00142 
00143 double Phy802_15_4::getRate(char dataOrSymbol)
00144 {
00145     double rate;
00146     
00147     if (ppib.phyCurrentChannel == 0)
00148     {
00149         if (dataOrSymbol == 'd')
00150             rate = BR_868M;
00151         else
00152             rate = SR_868M;
00153     }
00154     else if (ppib.phyCurrentChannel <= 10)
00155     {
00156         if (dataOrSymbol == 'd')
00157             rate = BR_915M;
00158         else
00159             rate = SR_915M;
00160     }
00161     else
00162     {
00163         if (dataOrSymbol == 'd')
00164             rate = BR_2_4G;
00165         else
00166             rate = SR_2_4G;
00167     }
00168     return (rate*1000);
00169 }
00170 
00171 double Phy802_15_4::trxTime(Packet *p,bool phyPkt)
00172 {
00173     int phyHeaderLen;
00174     double trx;
00175     hdr_cmn* ch = HDR_CMN(p);
00176     
00177     phyHeaderLen = (phyPkt)?0:defPHY_HEADER_LEN;
00178     trx = ((ch->size() + phyHeaderLen)*8/getRate('d'));
00179     return trx;
00180 }
00181 
00182 void Phy802_15_4::construct_PPDU(UINT_8 psduLength,Packet *psdu)
00183 {
00184     //not really a new packet in simulation, but just update some packet header fields.
00185     hdr_lrwpan* wph = HDR_LRWPAN(psdu);
00186     hdr_cmn* ch = HDR_CMN(psdu);
00187     
00188     wph->SHR_PreSeq = defSHR_PreSeq;
00189     wph->SHR_SFD = defSHR_SFD;
00190     wph->PHR_FrmLen = psduLength;
00191     //also set channel (for filtering in simulation)
00192     wph->phyCurrentChannel = ppib.phyCurrentChannel;
00193     ch->size() = psduLength + defPHY_HEADER_LEN;
00194     ch->txtime() = trxTime(psdu,true);  
00195 }
00196 
00197 void Phy802_15_4::PD_DATA_request(UINT_8 psduLength,Packet *psdu)
00198 {
00199     hdr_cmn* ch = HDR_CMN(psdu);
00200 
00201     //check packet length
00202     if (psduLength > aMaxPHYPacketSize)
00203     {
00204         fprintf(stdout,"[%s::%s][%f](node %d) Invalid PSDU/MPDU length: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %u, size = %d\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(psdu),p802_15_4macSA(psdu),p802_15_4macDA(psdu),ch->uid(),HDR_LRWPAN(psdu)->uid,ch->size());
00205         Packet::free(psdu);
00206         mac->PD_DATA_confirm(p_UNDEFINED);
00207         return;
00208     }
00209     
00210     if (trx_state == p_TX_ON)
00211     {
00212         if (tx_state == p_IDLE)
00213         {
00214 #ifdef DEBUG802_15_4
00215             fprintf(stdout,"[%s::%s][%f](node %d) sending pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %d\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(psdu),p802_15_4macSA(psdu),p802_15_4macDA(psdu),ch->uid(),HDR_LRWPAN(psdu)->uid,ch->size());
00216 #endif
00217             //construct a PPDU packet (not really a new packet in simulation, but still <psdu>)
00218             construct_PPDU(psduLength,psdu);
00219             //somehow the packet size is set to 0 after sendDown() -- ok, the packet is out and anything can happen (we shouldn't care once it's out)
00220             //so we have to calculate the transmission time before sendDown()
00221             double trx_time = trxTime(psdu,true);
00222             //send the packet to Radio (channel target) for transmission
00223             txPkt = psdu;
00224             txPktCopy = psdu->copy();   //for debug purpose, we still want to access the packet after transmission is done
00225             sendDown(psdu);         //WirelessPhy::sendDown()
00226             tx_state = p_BUSY;      //for carrier sense
00227             sendOverH.start(trx_time);
00228         }
00229         else    //impossible
00230             assert(0);
00231     }
00232     else
00233     {
00234 #ifdef DEBUG802_15_4
00235         fprintf(stdout,"[D][TRX][%s::%s][%f](node %d) dropping pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %d\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(psdu),p802_15_4macSA(psdu),p802_15_4macDA(psdu),ch->uid(),HDR_LRWPAN(psdu)->uid,ch->size());
00236 #endif
00237         Packet::free(psdu);
00238         mac->PD_DATA_confirm(trx_state);
00239     }
00240 }
00241 
00242 void Phy802_15_4::PD_DATA_indication(UINT_8 psduLength,Packet *psdu,UINT_8 ppduLinkQuality)
00243 {
00244     //refer to sec 6.7.8 for LQI details
00245     hdr_lrwpan* wph = HDR_LRWPAN(psdu);
00246 
00247     wph->ppduLinkQuality = ppduLinkQuality;
00248 
00249     if (sendUp(psdu) == 0)
00250         Packet::free(psdu);
00251     else
00252         uptarget_->recv(psdu, (Handler*) 0);
00253 }
00254 
00255 void Phy802_15_4::PLME_CCA_request()
00256 {
00257     if (trx_state == p_RX_ON)
00258     {
00259         //perform CCA
00260         //refer to sec 6.7.9 for CCA details
00261         //we need to delay 8 symbols
00262         CCAH.start(8/getRate('s'));
00263 
00264     }
00265     else
00266         mac->PLME_CCA_confirm(trx_state);
00267 }
00268 
00269 void Phy802_15_4::PLME_ED_request()
00270 {
00271     if (trx_state == p_RX_ON)
00272     {
00273         //perform ED
00274         //refer to sec 6.7.7 for ED implementation details
00275         //we need to delay 8 symbols
00276         rxEDPeakPower = rxTotPower[ppib.phyCurrentChannel];
00277         EDH.start(8/getRate('s'));
00278     }
00279     else
00280         mac->PLME_ED_confirm(trx_state,0);
00281 }
00282 
00283 void Phy802_15_4::PLME_GET_request(PPIBAenum PIBAttribute)
00284 {
00285     PHYenum t_status;
00286     
00287     switch(PIBAttribute)
00288     {
00289         case phyCurrentChannel:
00290         case phyChannelsSupported:
00291         case phyTransmitPower:
00292         case phyCCAMode:
00293             t_status = p_SUCCESS;
00294             break;
00295         default:
00296             t_status = p_UNSUPPORT_ATTRIBUTE;
00297             break;
00298     }
00299     mac->PLME_GET_confirm(t_status,PIBAttribute,&ppib);
00300 }
00301 
00302 void Phy802_15_4::PLME_SET_TRX_STATE_request(PHYenum state)
00303 {
00304     bool delay;
00305     PHYenum t_status;
00306     
00307     //ignore any pending request
00308     if (trx_state_defer_set != p_IDLE)
00309         trx_state_defer_set = p_IDLE;
00310     else if (TRXH.active)
00311     {
00312         TRXH.cancel();
00313     }
00314 
00315     t_status = trx_state;
00316     if (state != trx_state)
00317     {
00318         delay = false;
00319         if (((state == p_RX_ON)||(state == p_TRX_OFF))&&(tx_state == p_BUSY))
00320         {
00321             t_status = p_BUSY_TX;
00322             trx_state_defer_set = state;
00323         }
00324         else if (((state == p_TX_ON)||(state == p_TRX_OFF))
00325                 &&(rxPkt)&&(!HDR_CMN(rxPkt)->error()))          //if after received a valid SFD
00326         {
00327             t_status = p_BUSY_RX;
00328             trx_state_defer_set = state;
00329         }
00330         else if (state == p_FORCE_TRX_OFF)
00331         {
00332             t_status = (trx_state == p_TRX_OFF)?p_TRX_OFF:p_SUCCESS;
00333             trx_state = p_TRX_OFF;
00334             //terminate reception if needed
00335             if (rxPkt)
00336             {
00337 #ifdef DEBUG802_15_4
00338                 hdr_cmn *ch = HDR_CMN(rxPkt);
00339                 hdr_lrwpan *wph = HDR_LRWPAN(rxPkt);
00340                 fprintf(stdout,"[%s::%s][%f](node %d) FORCE_TRX_OFF sets error bit for incoming pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %d\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(rxPkt),p802_15_4macSA(rxPkt),p802_15_4macDA(rxPkt),ch->uid(),wph->uid,ch->size());
00341 #endif
00342                 HDR_CMN(rxPkt)->error() = 1;    //incomplete reception -- force packet discard
00343             }
00344             //terminate transmission if needed
00345             if (tx_state == p_BUSY)
00346             {
00347 #ifdef DEBUG802_15_4
00348                 hdr_cmn *ch = HDR_CMN(txPkt);
00349                 hdr_lrwpan *wph = HDR_LRWPAN(txPkt);
00350                 fprintf(stdout,"[%s::%s][%f](node %d) FORCE_TRX_OFF sets error bit for outgoing pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %d\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(txPkt),p802_15_4macSA(txPkt),p802_15_4macDA(txPkt),ch->uid(),wph->uid,ch->size());
00351 #endif
00352                 HDR_CMN(txPkt)->error() = 1;
00353                 sendOverH.cancel();
00354                 Packet::free(txPktCopy);
00355                 tx_state = p_IDLE;
00356                 mac->PD_DATA_confirm(p_TRX_OFF);
00357                 if (trx_state_defer_set != p_IDLE)
00358                     trx_state_defer_set = p_IDLE;
00359             }
00360         }
00361         else
00362         {
00363             t_status = p_SUCCESS;
00364             if (((state == p_RX_ON)&&(trx_state == p_TX_ON))
00365               ||((state == p_TX_ON)&&(trx_state == p_RX_ON)))
00366             {
00367                 trx_state_turnaround = state;
00368                 delay = true;
00369             }
00370             else
00371                 trx_state = state;
00372         }
00373         //we need to delay <aTurnaroundTime> symbols if Tx2Rx or Rx2Tx
00374         if (delay)
00375         {
00376             trx_state = p_TRX_OFF;  //should be disabled immediately (further transmission/reception will not succeed)
00377             TRXH.start(aTurnaroundTime/getRate('s'));
00378         }
00379         else
00380             mac->PLME_SET_TRX_STATE_confirm(t_status);
00381     }
00382     else
00383         mac->PLME_SET_TRX_STATE_confirm(t_status);
00384 #ifdef DEBUG802_15_4
00385         fprintf(stdout,"[%s::%s][%f](node %d) SET TRX: old = %s req = %s ret = %s\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,
00386             (trx_state == p_RX_ON)?"RX_ON":
00387             (trx_state == p_TX_ON)?"TX_ON":
00388             (trx_state == p_TRX_OFF)?"TRX_OFF":"???",
00389             (state == p_RX_ON)?"RX_ON":
00390             (state == p_TX_ON)?"TX_ON":
00391             (state == p_TRX_OFF)?"TRX_OFF":
00392             (state == p_FORCE_TRX_OFF)?"FORCE_TRX_OFF":"???",
00393             (t_status == p_RX_ON)?"RX_ON":
00394             (t_status == p_TX_ON)?"TX_ON":
00395             (t_status == p_TRX_OFF)?"TRX_OFF":
00396             (t_status == p_BUSY_TX)?"BUSY_TX":
00397             (t_status == p_BUSY_RX)?"BUSY_RX":
00398             (t_status == p_SUCCESS)?"SUCCESS":"???");
00399 #endif
00400 }
00401 
00402 void Phy802_15_4::PLME_SET_request(PPIBAenum PIBAttribute,PHY_PIB *PIBAttributeValue)
00403 {
00404     PHYenum t_status;
00405     
00406     t_status = p_SUCCESS;
00407     switch(PIBAttribute)
00408     {
00409         case phyCurrentChannel:
00410             if (!channelSupported(PIBAttributeValue->phyCurrentChannel))
00411                 t_status = p_INVALID_PARAMETER;
00412             if (ppib.phyCurrentChannel != PIBAttributeValue->phyCurrentChannel)
00413             {
00414                 //any packet in transmission or reception will be corrupted
00415                 if (rxPkt)
00416                 {
00417 #ifdef DEBUG802_15_4
00418                     hdr_cmn *ch = HDR_CMN(rxPkt);
00419                     hdr_lrwpan *wph = HDR_LRWPAN(rxPkt);
00420                     fprintf(stdout,"[%s::%s][%f](node %d) SET phy channel sets error bit for incoming pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %d\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(rxPkt),p802_15_4macSA(rxPkt),p802_15_4macDA(rxPkt),ch->uid(),wph->uid,ch->size());
00421 #endif
00422                     HDR_CMN(rxPkt)->error() = 1;
00423                 }
00424                 if (tx_state == p_BUSY)
00425                 {
00426 #ifdef DEBUG802_15_4
00427                     hdr_cmn *ch = HDR_CMN(txPkt);
00428                     hdr_lrwpan *wph = HDR_LRWPAN(txPkt);
00429                     fprintf(stdout,"[%s::%s][%f](node %d) SET phy channel sets error bit for outgoing pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %d\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(txPkt),p802_15_4macSA(txPkt),p802_15_4macDA(txPkt),ch->uid(),wph->uid,ch->size());
00430 #endif
00431                     HDR_CMN(txPkt)->error() = 1;
00432                     sendOverH.cancel();
00433                     Packet::free(txPktCopy);
00434                     tx_state = p_IDLE;
00435                     mac->PD_DATA_confirm(p_TRX_OFF);
00436                     if (trx_state_defer_set != p_IDLE)
00437                         trx_state_defer_set = p_IDLE;
00438                 }
00439                 ppib.phyCurrentChannel = PIBAttributeValue->phyCurrentChannel;
00440             }
00441             break;
00442         case phyChannelsSupported:
00443             if ((PIBAttributeValue->phyChannelsSupported&0xf8000000) != 0)  //5 MSBs reserved
00444                 t_status = p_INVALID_PARAMETER;
00445             else
00446                 ppib.phyChannelsSupported = PIBAttributeValue->phyChannelsSupported;
00447             break;
00448         case phyTransmitPower:
00449             if (PIBAttributeValue->phyTransmitPower > 0xbf)
00450                 t_status = p_INVALID_PARAMETER;
00451             else
00452                 ppib.phyTransmitPower = PIBAttributeValue->phyTransmitPower;
00453             break;
00454         case phyCCAMode:
00455             if ((PIBAttributeValue->phyCCAMode < 1)
00456              || (PIBAttributeValue->phyCCAMode > 3))
00457                 t_status = p_INVALID_PARAMETER;
00458             else
00459                 ppib.phyCCAMode = PIBAttributeValue->phyCCAMode;
00460             break;
00461         default:
00462             t_status = p_UNSUPPORT_ATTRIBUTE;
00463             break;
00464     }
00465     mac->PLME_SET_confirm(t_status,PIBAttribute);
00466 }
00467 
00468 UINT_8 Phy802_15_4::measureLinkQ(Packet *p)
00469 {
00470     //Link quality measurement is somewhat simulation/implementation specific;
00471     //here's our way:
00472     int lq,lq2;
00473 
00474     //consider energy
00475     /* Linux floating number compatibility
00476     lq = (int)((p->txinfo_.RxPr/RXThresh_)*128);
00477     */
00478     {
00479     double tmpf;
00480     tmpf = p->txinfo_.RxPr/RXThresh_;
00481     lq = (int)(tmpf * 128);
00482     }
00483     if (lq > 255) lq = 255;
00484 
00485     //consider signal-to-noise
00486     /* Linux floating number compatibility
00487     lq2 = (int)((p->txinfo_.RxPr/HDR_LRWPAN(p)->rxTotPower)*255);
00488     */
00489     {
00490     double tmpf;
00491     tmpf = p->txinfo_.RxPr/HDR_LRWPAN(p)->rxTotPower;
00492     lq2 = (int)(tmpf * 255);
00493     }
00494     
00495     if (lq > lq2) lq = lq2;     //use worst value
00496         
00497     return (UINT_8) lq;
00498 }
00499 
00500 void Phy802_15_4::recv(Packet *p, Handler *h)
00501 {
00502     hdr_lrwpan* wph = HDR_LRWPAN(p);
00503     hdr_cmn *ch = HDR_CMN(p);
00504         FrameCtrl frmCtrl;
00505 
00506     switch(ch->direction())
00507     {
00508     case hdr_cmn::DOWN:
00509 #ifdef DEBUG802_15_4
00510         fprintf(stdout,"[%s::%s][%f](node %d) outgoing pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %d\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
00511 #endif
00512         PD_DATA_request((UINT_8) ch->size(),p);
00513         break;
00514     case hdr_cmn::UP:
00515     default:
00516         if (sendUp(p) == 0) 
00517         {
00518             Packet::free(p);
00519             return;
00520         }
00521 
00522         if (updateNFailLink(fl_oper_est,index_) == 0)
00523         {
00524             Packet::free(p);
00525             return;
00526         }
00527 
00528                 if (updateLFailLink(fl_oper_est,p802_15_4macSA(p),index_) == 0) //broadcast packets can still reach here
00529                 {
00530                         Packet::free(p);
00531                         return;
00532                 }
00533 
00534                 frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
00535                 frmCtrl.parse();
00536         //tap out
00537         if (mac->tap() && frmCtrl.frmType == defFrmCtrl_Type_Data)
00538             mac->tap()->tap(p);
00539 
00540         if (node()->energy_model() && node()->energy_model()->adaptivefidelity())
00541             node()->energy_model()->add_neighbor(p802_15_4macSA(p));
00542 
00543         //Under whatever condition, we should mark the media as busy.
00544         // --no matter the packet(s) is for this node or not, no matter
00545         //   what state the transceiver is in, RX_ON,TX_ON or TRX_OFF, and
00546         //   no matter which channel is being used.
00547         //Note that current WirelessPhy->sendUp() prevents packets with (Pr < CSThresh_)
00548         //from reaching here --. need to modify.WirelessPhy->sendUp() if we want to see
00549         //all the packets here (but seems no reason to do that).
00550         //  in dB as can be seen from following:
00551         //  not very clear (now CPThresh_ is just a ratio, not in dB?)
00552         rxTotPower[wph->phyCurrentChannel] += p->txinfo_.RxPr;
00553         rxTotNum[wph->phyCurrentChannel]++;
00554         if (EDH.active)
00555         if(rxEDPeakPower < rxTotPower[ppib.phyCurrentChannel])
00556             rxEDPeakPower = rxTotPower[ppib.phyCurrentChannel];
00557         
00558         if ((p802_15_4macDA(p) == index_)           //packet for this node
00559           ||(p802_15_4macDA(p) == ((int)MAC_BROADCAST)))        //broadcast packet
00560             rxThisTotNum[wph->phyCurrentChannel]++;
00561 
00562         if (trx_state == p_RX_ON)
00563         if (wph->phyCurrentChannel == ppib.phyCurrentChannel)   //current channel
00564         if ((p802_15_4macDA(p) == index_)           //packet for this node
00565           ||(p802_15_4macDA(p) == ((int)MAC_BROADCAST)))        //broadcast packet
00566         if (wph->SHR_SFD == defSHR_SFD)             //valid SFD
00567         {
00568 #ifdef DEBUG802_15_4
00569             fprintf(stdout,"[%s::%s][%f](node %d) incoming pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %d\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
00570 #endif
00571             wph->colFlag = false;
00572             if (rxPkt == 0)
00573             {
00574                 rxPkt = p;
00575                 HDR_LRWPAN(rxPkt)->rxTotPower = rxTotPower[wph->phyCurrentChannel];
00576             }
00577             else
00578             {
00579 #ifdef DEBUG802_15_4
00580                 fprintf(stdout,"[D][COL][%s::%s][%f](node %d) COLLISION:\n\t First (power:%f): type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %d\n\tSecond (power:%f): type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %d\n",
00581                     __FILE__,__FUNCTION__,CURRENT_TIME,index_,
00582                     rxPkt->txinfo_.RxPr,wpan_pName(rxPkt),p802_15_4macSA(rxPkt),p802_15_4macDA(rxPkt),HDR_CMN(rxPkt)->uid(),HDR_LRWPAN(rxPkt)->uid,HDR_CMN(rxPkt)->size(),
00583                     p->txinfo_.RxPr,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
00584 #endif
00585                 wph->colFlag = true;
00586                 HDR_LRWPAN(rxPkt)->colFlag = true;
00587                 mac->nam->flashNodeColor(CURRENT_TIME);
00588                 if (p->txinfo_.RxPr > rxPkt->txinfo_.RxPr)
00589                 {
00590                     //What should we do if there is a transceiver state set pending?
00591                     //  1. continue defering (could be unbounded delay)
00592                     //..2. set transceiver state now (the incoming packet ignored)
00593                     //We select choice 1, as the traffic rate is supposed to be low.
00594                     rxPkt = p;
00595                     HDR_LRWPAN(rxPkt)->rxTotPower = rxTotPower[wph->phyCurrentChannel];
00596                 }
00597             }
00598 
00599         }
00600         if (rxPkt)
00601         if (HDR_LRWPAN(rxPkt)->rxTotPower < rxTotPower[HDR_LRWPAN(rxPkt)->phyCurrentChannel])
00602             HDR_LRWPAN(rxPkt)->rxTotPower = rxTotPower[HDR_LRWPAN(rxPkt)->phyCurrentChannel];
00603         assert(ch->size() > 0);
00604         if (ch->direction() != hdr_cmn::UP)
00605         {
00606             printf("Packet-flow direction not specified: sending up the stack on default.\n\n");
00607             ch->direction() = hdr_cmn::UP;  //we don't want MAC to handle the same problem
00608         }
00609         Scheduler::instance().schedule(&recvOverH, (Event *)p, trxTime(p,true));
00610         break;
00611     }
00612 }
00613 
00614 void Phy802_15_4::CCAHandler(void)
00615 {
00616     PHYenum t_status;
00617 
00618     //refer to sec 6.7.9 for CCA details
00619     //  1. CCA will be affected by outgoing packets,
00620     //     incoming packets (both destined for this device 
00621     //     and not destined for this device) and other
00622     //     interferences.
00623     //  2. In implementation, we don't care about the details 
00624     //     and just need to perform an actual measurement.
00625     if ((tx_state == p_BUSY)||(rxTotNum[ppib.phyCurrentChannel] > 0))
00626     {
00627         t_status = p_BUSY;
00628     }
00629     else if (ppib.phyCCAMode == 1)  //ED detection
00630     {
00631         //sec 6.5.3.3 and 6.6.3.4
00632         // -- receiver sensitivity: -85 dBm or better for 2.4G
00633         // -- receiver sensitivity: -92 dBm or better for 868M/915M
00634         //sec 6.7.9
00635         // -- ED threshold at most 10 dB above receiver sensitivity.
00636         //For simulations, we simply compare with CSThresh_
00637         t_status = (rxTotPower[ppib.phyCurrentChannel] >= CSThresh_)?p_BUSY:p_IDLE;
00638     }
00639     else if (ppib.phyCCAMode == 2)  //carrier sense only
00640     {
00641         t_status = (rxTotNum[ppib.phyCurrentChannel] > 0)?p_BUSY:p_IDLE;
00642     }
00643     else //if (ppib.phyCCAMode == 3)    //both
00644     {
00645         t_status = ((rxTotPower[ppib.phyCurrentChannel] >= CSThresh_)&&(rxTotNum[ppib.phyCurrentChannel] > 0))?p_BUSY:p_IDLE;
00646     }
00647     mac->PLME_CCA_confirm(t_status);
00648 }
00649 
00650 void Phy802_15_4::EDHandler(void)
00651 {
00652     int energy;
00653     UINT_8 t_EnergyLevel;
00654 
00655     //refer to sec 6.7.7 for ED implementation details
00656     //ED is somewhat simulation/implementation specific; here's our way:
00657 
00658     /* Linux floating number compatibility
00659     energy = (int)((rxEDPeakPower/RXThresh_)*128);
00660     */
00661     {
00662     double tmpf;
00663     tmpf = rxEDPeakPower/RXThresh_;
00664     energy = (int)(tmpf * 128);
00665     }
00666     t_EnergyLevel = (energy > 255)?255:energy;
00667     mac->PLME_ED_confirm(p_SUCCESS,t_EnergyLevel);
00668 }
00669 
00670 void Phy802_15_4::TRXHandler(void)
00671 {
00672     trx_state = trx_state_turnaround;
00673     //send a confirm
00674     mac->PLME_SET_TRX_STATE_confirm(trx_state);
00675 }
00676 
00677 void Phy802_15_4::recvOverHandler(Packet *p)
00678 {
00679     UINT_8 lq;
00680     hdr_lrwpan* wph = HDR_LRWPAN(p);
00681     hdr_cmn *ch = HDR_CMN(p);
00682     
00683     rxTotPower[wph->phyCurrentChannel] -= p->txinfo_.RxPr;
00684     rxTotNum[wph->phyCurrentChannel]--;
00685     
00686     if (rxTotNum[wph->phyCurrentChannel] == 0)
00687         rxTotPower[wph->phyCurrentChannel] = 0.0;
00688 
00689     if ((p802_15_4macDA(p) != index_)
00690       &&(p802_15_4macDA(p) != ((int)MAC_BROADCAST)))    //packet not for this node (interference)
00691         Packet::free(p);
00692     else if (p != rxPkt)                //packet corrupted (not the strongest one) or un-detectable
00693     {
00694 #ifdef DEBUG802_15_4
00695         fprintf(stdout,"[D][%s][%s::%s::%d][%f](node %d) dropping pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %d\n",(wph->phyCurrentChannel != ppib.phyCurrentChannel)?"CHN":"NOT",__FILE__,__FUNCTION__,__LINE__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
00696 #endif
00697         rxThisTotNum[wph->phyCurrentChannel]--;
00698         drop(p,(wph->phyCurrentChannel != ppib.phyCurrentChannel)?"CHN":"NOT");
00699     }
00700     else
00701     {
00702         rxThisTotNum[wph->phyCurrentChannel]--;
00703         //measure (here calculate) the link quality
00704         lq = measureLinkQ(p);
00705         ch->size() -= defPHY_HEADER_LEN;
00706         rxPkt = 0;
00707         if ((ch->size() <= 0) 
00708             ||(ch->size() > aMaxPHYPacketSize)
00709             ||ch->error())      //incomplete reception (due to FORCE_TRX_OFF),data packet received during ED or other errors
00710         {
00711 #ifdef DEBUG802_15_4
00712             fprintf(stdout,"[D][ERR][%s::%s::%d][%f](node %d) dropping pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %d\n",__FILE__,__FUNCTION__,CURRENT_TIME,__LINE__,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
00713 #endif
00714             drop(p,"ERR");
00715         }
00716         else
00717         {
00718 
00719 #ifdef DEBUG802_15_4
00720             fprintf(stdout,"[%s::%s][%f](node %d) incoming pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %d --> PD_DATA_indication()\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
00721 #endif
00722             PD_DATA_indication(ch->size(),p,lq);    //MAC sublayer need to further check if the packet
00723                                 //is really received successfully or not.
00724         }
00725         if (trx_state_defer_set != p_IDLE)
00726         {
00727             trx_state_turnaround = trx_state_defer_set;
00728             trx_state_defer_set = p_IDLE;
00729             if (trx_state_turnaround == p_TRX_OFF)
00730             {
00731                 trx_state = trx_state_turnaround;
00732                 mac->PLME_SET_TRX_STATE_confirm(trx_state);
00733             }
00734             else
00735             {
00736                 //we need to delay <aTurnaroundTime> symbols for Rx2Tx
00737                 trx_state = p_TRX_OFF;  //should be disabled immediately (further reception will not succeed)
00738                 TRXH.start(aTurnaroundTime/getRate('s'));
00739             }
00740         }
00741     }
00742 }
00743 
00744 void Phy802_15_4::sendOverHandler(void)
00745 {
00746 #ifdef DEBUG802_15_4
00747     fprintf(stdout,"[%s::%s][%f](node %d) sending over: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %d\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(txPktCopy),p802_15_4macSA(txPktCopy),p802_15_4macDA(txPktCopy),HDR_CMN(txPktCopy)->uid(),HDR_LRWPAN(txPktCopy)->uid,HDR_CMN(txPktCopy)->size());
00748 #endif
00749     assert(tx_state == p_BUSY);
00750     assert(txPktCopy);
00751     Packet::free(txPktCopy);
00752     tx_state = p_IDLE;
00753     mac->PD_DATA_confirm(p_SUCCESS);
00754     if (trx_state_defer_set != p_IDLE)
00755     {
00756         trx_state_turnaround = trx_state_defer_set;
00757         trx_state_defer_set = p_IDLE;
00758         if (trx_state_turnaround == p_TRX_OFF)
00759         {
00760             trx_state = trx_state_turnaround;
00761             mac->PLME_SET_TRX_STATE_confirm(trx_state);
00762         }
00763         else
00764         {
00765             //we need to delay <aTurnaroundTime> symbols for Rx2Tx
00766             trx_state = p_TRX_OFF;  //should be disabled immediately (further transmission will not succeed)
00767             TRXH.start(aTurnaroundTime/getRate('s'));
00768         }
00769     }
00770 }
00771 
00772 // End of file: p802_15_4phy.cc

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