p802_15_4mac.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_4mac.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_4mac.cc,v 1.2 2005/01/25 23:29:16 haldar 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_4mac.h"
00055 #include "p802_15_4const.h"
00056 #include "p802_15_4csmaca.h"
00057 #include "p802_15_4sscs.h"
00058 #include "p802_15_4trace.h"
00059 #include "p802_15_4fail.h"
00060 #include "p802_15_4nam.h"
00061 
00062 bool Mac802_15_4::verbose = false;
00063 UINT_8 Mac802_15_4::txOption = 0x00;    //0x02=GTS; 0x04=Indirect; 0x00=Direct (only for 802.15.4-unaware upper layer app. packet)
00064 bool Mac802_15_4::ack4data = true;
00065 UINT_8 Mac802_15_4::callBack = 1;   //0=no call back; 1=call back for failures; 2=call back for failures and successes
00066 UINT_32 Mac802_15_4::DBG_UID = 0;
00067 
00068 static MAC_PIB MPIB =
00069 {
00070     def_macAckWaitDuration,     def_macAssociationPermit,
00071     def_macAutoRequest,     def_macBattLifeExt,
00072     def_macBattLifeExtPeriods,  def_macBeaconPayload,
00073     def_macBeaconPayloadLength, def_macBeaconOrder,
00074     def_macBeaconTxTime,        0/*def_macBSN*/,
00075     def_macCoordExtendedAddress,    def_macCoordShortAddress,
00076     0/*def_macDSN*/,        def_macGTSPermit,
00077     def_macMaxCSMABackoffs,     def_macMinBE,
00078     def_macPANId,           def_macPromiscuousMode,
00079     def_macRxOnWhenIdle,        def_macShortAddress,
00080     def_macSuperframeOrder,     def_macTransactionPersistenceTime,
00081     def_macACLEntryDescriptorSet,   def_macACLEntryDescriptorSetSize,
00082     def_macDefaultSecurity,     def_macACLDefaultSecurityMaterialLength,
00083     def_macDefaultSecurityMaterial, def_macDefaultSecuritySuite,
00084     def_macSecurityMode
00085 };
00086 
00087 void Mac802_15_4Handler::handle(Event* e)
00088 {
00089     nullEvent.uid_ = 0;
00090     if (type == macTxBcnCmdDataHType)
00091         mac->txBcnCmdDataHandler();
00092     else if (type == macIFSHType)
00093         mac->IFSHandler();
00094     else if (type == macBackoffBoundType)
00095         mac->backoffBoundHandler();
00096     else    
00097         assert(0);
00098 }
00099 
00100 int hdr_lrwpan::offset_;
00101 static class LRWPANHeaderClass : public PacketHeaderClass
00102 {
00103 public:
00104     LRWPANHeaderClass() : PacketHeaderClass("PacketHeader/LRWPAN",
00105                          sizeof(hdr_lrwpan))
00106     {
00107         bind_offset(&hdr_lrwpan::offset_);
00108     }
00109 } class_hdr_lrwpan;
00110 
00111 static class Mac802_15_4Class : public TclClass
00112 {
00113 public:
00114     Mac802_15_4Class() : TclClass("Mac/802_15_4") {}
00115     TclObject* create(int, const char*const*)
00116     {
00117         return (new Mac802_15_4(&MPIB));
00118     }
00119     virtual void bind(void);
00120     virtual int method(int argc, const char*const* argv);
00121 } class_mac802_15_4;
00122 
00123 void Mac802_15_4Class::bind(void)
00124 {
00125     TclClass::bind();
00126     add_method("wpanCmd");
00127     add_method("wpanNam");
00128 }
00129 
00130 int Mac802_15_4Class::method(int ac, const char*const* av)
00131 {
00132     //Available methods:
00133     //  ------------------------------------------------------------------------------------------
00134     //  bool Mac802_15_4::verbose; (Tcl command: Mac/802_15_4 wpanCmd verbose [on/off]
00135     //  UINT_8 Mac802_15_4::txOption; (Tcl command: Mac/802_15_4 wpanCmd txOption [2/4/0]
00136     //  bool Mac802_15_4::ack4data; (Tcl command: Mac/802_15_4 wpanCmd ack4data [on/off]
00137     //  UINT_8 Mac802_15_4::callBack; (Tcl command: Mac/802_15_4 wpanCmd callBack [0/1/2]
00138     //  link down; (Tcl command: Mac/802_15_4 wpanCmd link-down <src> <dst>
00139     //  link up; (Tcl command: Mac/802_15_4 wpanCmd link-up <src> <dst>
00140     //  ------------------------------------------------------------------------------------------
00141     //  bool Nam802_15_4::Nam_Status; (Tcl command: Mac/802_15_4 wpanNam namStatus [on/off]
00142     //  bool Nam802_15_4::emHandling; (Tcl command: Mac/802_15_4 wpanNam emHandling [on/off]
00143     //  char *Nam802_15_4::def_PANCoor_clr; (Tcl command: Mac/802_15_4 wpanNam PANCoorClr [clrName]
00144     //  char *Nam802_15_4::def_Coor_clr; (Tcl command: Mac/802_15_4 wpanNam CoorClr [clrName]
00145     //  char *Nam802_15_4::def_Dev_clr; (Tcl command: Mac/802_15_4 wpanNam DevClr [clrName]
00146     //  char *Nam802_15_4::def_ColFlash_clr; (Tcl command: Mac/802_15_4 wpanNam ColFlashClr [clrName]
00147     //  char *Nam802_15_4::def_NodeFail_clr; (Tcl command: Mac/802_15_4 wpanNam NodeFailClr [clrName]
00148     //  playback rate; (Tcl command: Mac/802_15_4 wpanNam PlaybackRate [step_in_ms]
00149     //  flow colors; (Tcl command: Mac/802_15_4 wpanNam FlowClr [-p <packet_type_name>] [-s <src>] [-d <dst>] [-c <clrName>]
00150     //  ------------------------------------------------------------------------------------------
00151 
00152     Tcl& tcl = Tcl::instance();
00153     int argc = ac - 2;
00154     const char*const* argv = av + 2;
00155 
00156     if (strcmp(argv[1], "wpanCmd") == 0)
00157     if (argc == 3)   
00158     {
00159         if (strcmp(argv[2], "verbose") == 0)
00160         {
00161             if (!Mac802_15_4::verbose)
00162                 tcl.result("off");
00163             else
00164                 tcl.result("on");
00165             return (TCL_OK);
00166         }
00167         else if (strcmp(argv[2], "txOption") == 0)
00168         {
00169             if (Mac802_15_4::txOption == 0x02)
00170                 tcl.result("GTS");
00171             else if (Mac802_15_4::txOption == 0x04)
00172                 tcl.result("Indirect");
00173             else
00174                 tcl.result("Direct");
00175             return (TCL_OK);
00176         }
00177         else if (strcmp(argv[2], "ack4data") == 0)
00178         {
00179             if (!Mac802_15_4::ack4data)
00180                 tcl.result("off");
00181             else
00182                 tcl.result("on");
00183             return (TCL_OK);
00184         }
00185         else if (strcmp(argv[2], "callBack") == 0)
00186         {
00187             tcl.resultf("%u",Mac802_15_4::callBack);
00188             return (TCL_OK);
00189         }
00190     }
00191     else if (argc == 4)
00192     {
00193         if (strcmp(argv[2], "verbose") == 0)
00194         {
00195             if (strcmp(argv[3], "on") == 0)
00196                 Mac802_15_4::verbose = true;
00197             else
00198                 Mac802_15_4::verbose = false;
00199             return (TCL_OK);
00200         }
00201         else if (strcmp(argv[2], "txOption") == 0)
00202         {
00203             Mac802_15_4::txOption = atoi(argv[3]);
00204             return (TCL_OK);
00205         }
00206         else if (strcmp(argv[2], "ack4data") == 0)
00207         {
00208             if (strcmp(argv[3], "on") == 0)
00209                 Mac802_15_4::ack4data = true;
00210             else
00211                 Mac802_15_4::ack4data = false;
00212             return (TCL_OK);
00213         }
00214         else if (strcmp(argv[2], "callBack") == 0)
00215         {
00216             Mac802_15_4::callBack = atoi(argv[3]);
00217             return (TCL_OK);
00218         }
00219     }
00220     else if  (argc == 5)
00221     {
00222         if (strcmp(argv[2], "link-down") == 0)
00223         {
00224             chkAddLFailLink(atoi(argv[3]),atoi(argv[4]));
00225             return (TCL_OK);
00226         }
00227         else if (strcmp(argv[2], "link-up") == 0)
00228         {
00229             updateLFailLink(fl_oper_del,atoi(argv[3]),atoi(argv[4]));
00230             return (TCL_OK);
00231         }
00232     }
00233 
00234     if (strcmp(argv[1], "wpanNam") == 0)
00235     if (strcmp(argv[2], "namStatus") == 0)
00236     {
00237         if (argc == 3)
00238         {
00239             if (!Nam802_15_4::Nam_Status)
00240                 tcl.result("off");
00241             else
00242                 tcl.result("on");
00243         }
00244         else if (argc == 4)
00245         {
00246             if (strcmp(argv[3], "on") == 0)
00247                 Nam802_15_4::Nam_Status = true;
00248             else
00249                 Nam802_15_4::Nam_Status = false;
00250         }
00251         return (TCL_OK);
00252     }
00253     else if (strcmp(argv[2], "emHandling") == 0)
00254     {
00255         if (argc == 3)
00256         {
00257             if (!Nam802_15_4::emHandling)
00258                 tcl.result("off");
00259             else
00260                 tcl.result("on");
00261         }
00262         else if (argc == 4)
00263         {
00264             if (strcmp(argv[3], "on") == 0)
00265                 Nam802_15_4::emHandling = true;
00266             else
00267                 Nam802_15_4::emHandling = false;
00268         }
00269         return (TCL_OK);
00270     }
00271     else if (strcmp(argv[2], "PANCoorClr") == 0)
00272     {
00273         if (argc == 3)
00274             tcl.result(Nam802_15_4::def_PANCoor_clr);
00275         else if (argc >= 4)
00276         {
00277             strncpy(Nam802_15_4::def_PANCoor_clr,argv[3],20);
00278             Nam802_15_4::def_PANCoor_clr[20] = 0;
00279         }
00280         return (TCL_OK);
00281     }
00282     else if (strcmp(argv[2], "CoorClr") == 0)
00283     {
00284         if (argc == 3)
00285             tcl.result(Nam802_15_4::def_Coor_clr);
00286         else if (argc >= 4)
00287         {
00288             strncpy(Nam802_15_4::def_Coor_clr,argv[3],20);
00289             Nam802_15_4::def_Coor_clr[20] = 0;
00290         }
00291         return (TCL_OK);
00292     }
00293     else if (strcmp(argv[2], "DevClr") == 0)
00294     {
00295         if (argc == 3)
00296             tcl.result(Nam802_15_4::def_Dev_clr);
00297         else if (argc >= 4)
00298         {
00299             strncpy(Nam802_15_4::def_Dev_clr,argv[3],20);
00300             Nam802_15_4::def_Dev_clr[20] = 0;
00301         }
00302         return (TCL_OK);
00303     }
00304     else if (strcmp(argv[2], "ColFlashClr") == 0)
00305     {
00306         if (argc == 3)
00307             tcl.result(Nam802_15_4::def_ColFlash_clr);
00308         else if (argc >= 4)
00309         {
00310             strncpy(Nam802_15_4::def_ColFlash_clr,argv[3],20);
00311             Nam802_15_4::def_ColFlash_clr[20] = 0;
00312         }
00313         return (TCL_OK);
00314     }
00315     else if (strcmp(argv[2], "NodeFailClr") == 0)
00316     {
00317         if (argc == 3)
00318             tcl.result(Nam802_15_4::def_NodeFail_clr);
00319         else if (argc >= 4)
00320         {
00321             strncpy(Nam802_15_4::def_NodeFail_clr,argv[3],20);
00322             Nam802_15_4::def_NodeFail_clr[20] = 0;
00323         }
00324         return (TCL_OK);
00325     }
00326     else if (strcmp(argv[2], "PlaybackRate") == 0)
00327     {
00328         if (argc == 3)
00329             tcl.result("??");
00330         else if (argc >= 4)
00331             Nam802_15_4::changePlaybackRate(CURRENT_TIME,argv[3]);
00332         return (TCL_OK);
00333     }
00334     else if (strcmp(argv[2], "FlowClr") == 0)
00335     {
00336         int i,lp,src,dst;
00337         char pName[21],cName[21];
00338         ATTRIBUTELINK *attr;
00339 
00340         src = -2;
00341         dst = -2;
00342         strcpy(pName,packet_info.name(PT_NTYPE));
00343         lp = (argc - 3) / 2;
00344         for (i=0;i<lp;i++)
00345         {
00346             if (strcmp(argv[i*2+3],"-p") == 0)
00347             {
00348                 strncpy(pName,argv[i*2+4],20);
00349                 pName[20] = 0;
00350             }
00351             else if (strcmp(argv[i*2+3],"-s") == 0)
00352                 src = atoi(argv[i*2+4]);
00353             else if (strcmp(argv[i*2+3],"-d") == 0)
00354                 dst = atoi(argv[i*2+4]);
00355             else if (strcmp(argv[i*2+3],"-c") == 0)
00356             {
00357                 strncpy(cName,argv[i*2+4],20);
00358                 cName[20] = 0;
00359             }
00360         }
00361         i = chkAddAttrLink(nam_pktName2Type(pName),cName,src,dst);
00362         if (i == 1)     //already exist
00363         {
00364             attr = findAttrLink(nam_pktName2Type(pName),src,dst);
00365             if (strcmp(attr->color,cName) != 0) //color changed
00366             {
00367                 strncpy(attr->color,cName,20);
00368                 attr->color[20] = 0;
00369                 Nam802_15_4::flowAttribute(attr->attribute,attr->color);
00370             }
00371             
00372         }
00373         else if (i == 0)    //added into the link
00374         {
00375             attr = findAttrLink(nam_pktName2Type(pName),src,dst);
00376             Nam802_15_4::flowAttribute(attr->attribute,attr->color);
00377         }
00378         return (TCL_OK);
00379     }
00380 
00381 
00382     return TclClass::method(ac, av);
00383 }
00384 
00385 Mac802_15_4::Mac802_15_4(MAC_PIB *mp) : Mac(),
00386 txCmdDataH(this,macTxBcnCmdDataHType),
00387 IFSH(this,macIFSHType),
00388 backoffBoundH(this,macBackoffBoundType)
00389 {
00390     capability.cap = 0xc1;      //alterPANCoor = true
00391                     //FFD = true
00392                     //mainsPower = false
00393                     //recvOnWhenIdle = false
00394                     //secuCapable = false
00395                     //alloShortAddr = true
00396     capability.parse();
00397     aExtendedAddress = index_;
00398     oneMoreBeacon = false;
00399     isPANCoor = false;
00400     inTransmission = false;
00401     mpib = *mp;
00402     mpib.macBSN = Random::random() % 0x100;
00403     mpib.macDSN = Random::random() % 0x100;
00404     macBeaconOrder2 = 15;
00405     macSuperframeOrder2 = def_macBeaconOrder;
00406     macBeaconOrder3 = 15;
00407     macSuperframeOrder3 = def_macBeaconOrder;
00408     if (mpib.macBeaconOrder == 15)      //non-beacon mode
00409         mpib.macRxOnWhenIdle = true;    //default is false, but should be true in non-beacon mode
00410     numLostBeacons = 0;
00411     phy = NULL;
00412     txOverT = new macTxOverTimer(this);
00413     assert(txOverT);
00414     txT = new macTxTimer(this);
00415     assert(txT);
00416     extractT = new macExtractTimer(this);
00417     assert(extractT);
00418     assoRspWaitT = new macAssoRspWaitTimer(this);
00419     assert(assoRspWaitT);
00420     dataWaitT = new macDataWaitTimer(this);
00421     assert(dataWaitT);
00422     rxEnableT = new macRxEnableTimer(this);
00423     assert(rxEnableT);
00424     scanT = new macScanTimer(this);
00425     assert(scanT);
00426     bcnTxT = new macBeaconTxTimer(this);
00427     assert(bcnTxT);
00428     bcnRxT = new macBeaconRxTimer(this);
00429     assert(bcnRxT);
00430     bcnSearchT = new macBeaconSearchTimer(this);
00431     assert(bcnSearchT);
00432     sscs = new SSCS802_15_4(this);
00433     assert(sscs);
00434     nam = new Nam802_15_4((isPANCoor)?Nam802_15_4::def_PANCoor_clr:"black","black",this);
00435     assert(nam);
00436 
00437     chkAddMacLink(index_,this);
00438 
00439     init();
00440 }
00441 
00442 Mac802_15_4::~Mac802_15_4()
00443 {
00444     /*for some reason,this function sometimes is called with <index_> beyond the scope (ns2 bug?)
00445     delete txOverT;
00446     delete txT;
00447     delete extractT;
00448     delete assoRspWaitT;
00449     delete dataWaitT;
00450     delete rxEnableT;
00451     delete scanT;
00452     delete bcnTxT;
00453     delete bcnRxT;
00454     delete bcnSearchT;
00455     delete csmaca;
00456     delete sscs;
00457     delete nam;
00458     */
00459 }
00460 
00461 void Mac802_15_4::init(bool reset)
00462 {
00463     secuBeacon = false;
00464     beaconWaiting = false;
00465     txBeacon = 0;
00466     txAck = 0;
00467     txBcnCmd = 0;
00468     txBcnCmd2 = 0;
00469     txData = 0;
00470     rxData = 0;
00471     rxCmd = 0;
00472 
00473     if (reset)
00474     {
00475         emptyHListLink(&hlistBLink1,&hlistBLink2);
00476         emptyHListLink(&hlistDLink1,&hlistDLink2);
00477         emptyDeviceLink(&deviceLink1,&deviceLink2);
00478         emptyTransacLink(&transacLink1,&transacLink2);
00479     }
00480     else
00481     {
00482         hlistBLink1 = NULL;
00483         hlistBLink2 = NULL;
00484         hlistDLink1 = NULL;
00485         hlistDLink2 = NULL;
00486         deviceLink1 = NULL;
00487         deviceLink2 = NULL;
00488         transacLink1 = NULL;
00489         transacLink2 = NULL;
00490     }
00491 
00492     taskP.init();
00493 }
00494 
00495 void Mac802_15_4::PD_DATA_confirm(PHYenum status)
00496 {
00497     inTransmission = false;
00498     if (txOverT->busy())
00499         txOverT->stop();
00500     if (backoffStatus == 1)
00501         backoffStatus = 0;      
00502     if (status == p_SUCCESS)
00503     {
00504         dispatch(status,__FUNCTION__);
00505     }
00506     else if (txPkt == txBeacon)
00507     {
00508         beaconWaiting = false;
00509         Packet::free(txBeacon);
00510         txBeacon = 0;
00511 
00512     }
00513     else if (txPkt == txAck)        
00514     {
00515         Packet::free(txAck);
00516         txAck = 0;
00517 
00518     }
00519     else    //RX_ON/TRX_OFF -- possible if the transmisstion is terminated by a FORCE_TRX_OFF or change of channel, or due to energy depletion
00520     {}  //nothing to do -- it is the process that terminated the transmisstion to provide a way to resume the transmission
00521 }
00522 
00523 void Mac802_15_4::PLME_CCA_confirm(PHYenum status)
00524 {
00525     if (taskP.taskStatus(TP_CCA_csmaca))
00526     {
00527         taskP.taskStatus(TP_CCA_csmaca) = false;
00528         csmaca->CCA_confirm(status);
00529     }
00530 }
00531 
00532 void Mac802_15_4::PLME_ED_confirm(PHYenum status,UINT_8 EnergyLevel)
00533 {
00534     energyLevel = EnergyLevel;
00535     dispatch(status,__FUNCTION__);
00536 }
00537 
00538 void Mac802_15_4::PLME_GET_confirm(PHYenum status,PPIBAenum PIBAttribute,PHY_PIB *PIBAttributeValue)
00539 {
00540     if (status == p_SUCCESS)
00541     switch(PIBAttribute)
00542     {
00543         case phyCurrentChannel:
00544             tmp_ppib.phyCurrentChannel = PIBAttributeValue->phyCurrentChannel;
00545             break;
00546         case phyChannelsSupported:
00547             tmp_ppib.phyChannelsSupported = PIBAttributeValue->phyChannelsSupported;
00548             break;
00549         case phyTransmitPower:
00550             tmp_ppib.phyTransmitPower = PIBAttributeValue->phyTransmitPower;
00551             break;
00552         case phyCCAMode:
00553             tmp_ppib.phyCCAMode = PIBAttributeValue->phyCCAMode;
00554             break;
00555         default:
00556             break;
00557     }
00558 }
00559 
00560 void Mac802_15_4::PLME_SET_TRX_STATE_confirm(PHYenum status)
00561 {
00562     //hdr_lrwpan *wph;
00563     //FrameCtrl frmCtrl;
00564     double delay;
00565 
00566     if (status == p_SUCCESS) status = trx_state_req;
00567 
00568     if (backoffStatus == 99)
00569     {
00570         if (trx_state_req == p_RX_ON)
00571         {
00572             if (taskP.taskStatus(TP_RX_ON_csmaca))
00573             {
00574                 taskP.taskStatus(TP_RX_ON_csmaca) = false;
00575                 csmaca->RX_ON_confirm(status);
00576             }
00577         }
00578     }
00579     else
00580         dispatch(status,__FUNCTION__,trx_state_req);
00581 
00582     if (status != p_TX_ON) return;
00583 
00584     //transmit the packet
00585     if (beaconWaiting)
00586     {
00587         /* to synchronize better, we don't transmit the beacon here
00588 #ifdef DEBUG802_15_4
00589         fprintf(stdout,"[%s::%s][%f](node %d) transmit BEACON to %d: SN = %d, uid = %d, mac_uid = %ld\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,p802_15_4macDA(txBeacon),HDR_LRWPAN(txBeacon)->MHR_BDSN,HDR_CMN(txBeacon)->uid(),HDR_LRWPAN(txBeacon)->uid);
00590 #endif
00591         if (!taskP.taskStatus(TP_mlme_start_request))   //not first beacon
00592             assert((!txAck)&&(!txCsmaca));      //all tasks should be done before next beacon
00593         txPkt = txBeacon;
00594         HDR_CMN(txBeacon)->direction() = hdr_cmn::DOWN;
00595         sendDown(txBeacon->refcopy(),this);
00596         */
00597     }
00598     else if (txAck)
00599     {
00600         //although no CSMA-CA required for the transmission of ack., 
00601         //but we still need to locate the backoff period boundary if beacon enabled
00602         //(refer to page 157, line 25-31)
00603         if ((mpib.macBeaconOrder == 15)&&(macBeaconOrder2 == 15))   //non-beacon enabled
00604             delay = 0.0;
00605         else                                //beacon enabled
00606             delay  = locateBoundary((p802_15_4macDA(txAck) == mpib.macCoordShortAddress),0.0);
00607         if (delay == 0.0)
00608             backoffBoundHandler();
00609         else
00610             Scheduler::instance().schedule(&backoffBoundH, &(backoffBoundH.nullEvent), delay);
00611     }
00612     else
00613         transmitCmdData();
00614 }
00615 
00616 void Mac802_15_4::PLME_SET_confirm(PHYenum status,PPIBAenum PIBAttribute)
00617 {
00618     if ((PIBAttribute == phyCurrentChannel)&&(status == p_SUCCESS))
00619         dispatch(status,__FUNCTION__);
00620 }
00621 
00622 void Mac802_15_4::MCPS_DATA_request(UINT_8 SrcAddrMode,UINT_16 SrcPANId,IE3ADDR SrcAddr,
00623                     UINT_8 DstAddrMode,UINT_16 DstPANId,IE3ADDR DstAddr,
00624                     UINT_8 msduLength,Packet *msdu,UINT_8 msduHandle,UINT_8 TxOptions)
00625 {
00626     mcps_data_request(SrcAddrMode,SrcPANId,SrcAddr,DstAddrMode,DstPANId,DstAddr,msduLength,msdu,msduHandle,TxOptions,true);
00627 }
00628 
00629 void Mac802_15_4::MCPS_DATA_indication(UINT_8 SrcAddrMode,UINT_16 SrcPANId,IE3ADDR SrcAddr,
00630                        UINT_8 DstAddrMode,UINT_16 DstPANId,IE3ADDR DstAddr,
00631                        UINT_8 msduLength,Packet *msdu,UINT_8 mpduLinkQuality,
00632                        bool SecurityUse,UINT_8 ACLEntry)
00633 {
00634     HDR_CMN(msdu)->num_forwards() += 1;
00635 
00636     if (HDR_LRWPAN(msdu)->msduHandle != 0)  //from peer SSCS
00637     {
00638         log(msdu->refcopy());
00639         sscs->MCPS_DATA_indication(SrcAddrMode,SrcPANId,SrcAddr,DstAddrMode,DstPANId,DstAddr,msduLength,msdu,mpduLinkQuality,SecurityUse,ACLEntry);
00640     }
00641     else
00642         uptarget_->recv(msdu,(Handler*) 0);
00643 }
00644 
00645 void Mac802_15_4::MCPS_PURGE_request(UINT_8 msduHandle)
00646 {
00647     
00648     int i;
00649     MACenum t_status;
00650 
00651     i = updateTransacLinkByPktOrHandle(tr_oper_del,&transacLink1,&transacLink2,NULL,msduHandle);
00652     t_status = (i == 0)?m_SUCCESS:m_INVALID_HANDLE;
00653     sscs->MCPS_PURGE_confirm(msduHandle,t_status);
00654 }
00655 
00656 void Mac802_15_4::MLME_ASSOCIATE_request(UINT_8 LogicalChannel,UINT_8 CoordAddrMode,UINT_16 CoordPANId,IE3ADDR CoordAddress,
00657                      UINT_8 CapabilityInformation,bool SecurityEnable)
00658 {
00659     mlme_associate_request(LogicalChannel,CoordAddrMode,CoordPANId,CoordAddress,CapabilityInformation,SecurityEnable,true);
00660 }
00661 
00662 void Mac802_15_4::MLME_ASSOCIATE_response(IE3ADDR DeviceAddress,UINT_16 AssocShortAddress,MACenum status,bool SecurityEnable)
00663 {
00664     mlme_associate_response(DeviceAddress,AssocShortAddress,status,SecurityEnable,true);
00665 }
00666 
00667 void Mac802_15_4::MLME_DISASSOCIATE_request(IE3ADDR DeviceAddress,UINT_8 DisassociateReason,bool SecurityEnable)
00668 {
00669     mlme_disassociate_request(DeviceAddress,DisassociateReason,SecurityEnable,true);
00670 }
00671 
00672 void Mac802_15_4::MLME_DISASSOCIATE_indication(IE3ADDR DeviceAddress,UINT_8 DisassociateReason,bool SecurityUse,UINT_8 ACLEntry)
00673 {
00674 }
00675 
00676 void Mac802_15_4::MLME_GET_request(MPIBAenum PIBAttribute)
00677 {
00678     MACenum t_status;
00679     
00680     switch(PIBAttribute)
00681     {
00682         case macAckWaitDuration:
00683         case macAssociationPermit:
00684         case macAutoRequest:
00685         case macBattLifeExt:
00686         case macBattLifeExtPeriods:
00687         case macBeaconPayload:
00688         case macBeaconPayloadLength:
00689         case macBeaconOrder:        
00690         case macBeaconTxTime:
00691         case macBSN:
00692         case macCoordExtendedAddress:
00693         case macCoordShortAddress:
00694         case macDSN:
00695         case macGTSPermit:
00696         case macMaxCSMABackoffs:
00697         case macMinBE:
00698         case macPANId:
00699         case macPromiscuousMode:
00700         case macRxOnWhenIdle:
00701         case macShortAddress:
00702         case macSuperframeOrder:
00703         case macTransactionPersistenceTime:
00704         case macACLEntryDescriptorSet:
00705         case macACLEntryDescriptorSetSize:
00706         case macDefaultSecurity:
00707         case macACLDefaultSecurityMaterialLength:
00708         case macDefaultSecurityMaterial:
00709         case macDefaultSecuritySuite:
00710         case macSecurityMode:
00711             t_status = m_SUCCESS;
00712             break;
00713         default:
00714             t_status = m_UNSUPPORTED_ATTRIBUTE;
00715             break;
00716     }
00717     sscs->MLME_GET_confirm(t_status,PIBAttribute,&mpib);
00718 }
00719 
00720 void Mac802_15_4::MLME_GTS_request(UINT_8 GTSCharacteristics,bool SecurityEnable)
00721 {
00722 }
00723 
00724 void Mac802_15_4::MLME_GTS_confirm(UINT_8 GTSCharacteristics,MACenum status)
00725 {
00726 }
00727 
00728 void Mac802_15_4::MLME_GTS_indication(UINT_16 DevAddress,UINT_8 GTSCharacteristics,
00729                       bool SecurityUse, UINT_8 ACLEntry)
00730 {
00731 }
00732 
00733 void Mac802_15_4::MLME_ORPHAN_response(IE3ADDR OrphanAddress,UINT_16 ShortAddress,bool AssociatedMember,bool SecurityEnable)
00734 {
00735     mlme_orphan_response(OrphanAddress,ShortAddress,AssociatedMember,SecurityEnable,true);
00736 }
00737 
00738 void Mac802_15_4::MLME_RESET_request(bool SetDefaultPIB)
00739 {
00740     mlme_reset_request(SetDefaultPIB,true);
00741 }
00742 
00743 void Mac802_15_4::MLME_RX_ENABLE_request(bool DeferPermit,UINT_32 RxOnTime,UINT_32 RxOnDuration)
00744 {
00745     mlme_rx_enable_request(DeferPermit,RxOnTime,RxOnDuration,true);
00746 }
00747 
00748 void Mac802_15_4::MLME_SCAN_request(UINT_8 ScanType,UINT_32 ScanChannels,UINT_8 ScanDuration)
00749 {
00750     mlme_scan_request(ScanType,ScanChannels,ScanDuration,true);
00751 }
00752 
00753 void Mac802_15_4::MLME_SET_request(MPIBAenum PIBAttribute,MAC_PIB *PIBAttributeValue)
00754 {
00755     PHYenum p_state;
00756     MACenum t_status;
00757 
00758     t_status = m_SUCCESS;
00759     switch(PIBAttribute)
00760     {
00761         case macAckWaitDuration:
00762             phy->PLME_GET_request(phyCurrentChannel);   //value will be returned in tmp_ppib
00763             if ((tmp_ppib.phyCurrentChannel <= 10)&&(PIBAttributeValue->macAckWaitDuration != 120)
00764              || (tmp_ppib.phyCurrentChannel > 10)&&(PIBAttributeValue->macAckWaitDuration != 54))
00765                 t_status = m_INVALID_PARAMETER;
00766             else
00767                 mpib.macAckWaitDuration = PIBAttributeValue->macAckWaitDuration;
00768             break;
00769         case macAssociationPermit:
00770                 mpib.macAssociationPermit = PIBAttributeValue->macAssociationPermit;
00771             break;
00772         case macAutoRequest:
00773                 mpib.macAutoRequest = PIBAttributeValue->macAutoRequest;
00774             break;
00775         case macBattLifeExt:
00776                 mpib.macBattLifeExt = PIBAttributeValue->macBattLifeExt;
00777             break;
00778         case macBattLifeExtPeriods:
00779             phy->PLME_GET_request(phyCurrentChannel);   //value will be returned in tmp_ppib
00780             if ((tmp_ppib.phyCurrentChannel <= 10)&&(PIBAttributeValue->macBattLifeExtPeriods != 8)
00781              || (tmp_ppib.phyCurrentChannel > 10)&&(PIBAttributeValue->macBattLifeExtPeriods != 6))
00782                 t_status = m_INVALID_PARAMETER;
00783             else
00784                 mpib.macBattLifeExtPeriods = PIBAttributeValue->macBattLifeExtPeriods;
00785             break;
00786         case macBeaconPayload:
00787                 //<macBeaconPayloadLength> should be set first
00788                 memcpy(mpib.macBeaconPayload,PIBAttributeValue->macBeaconPayload,mpib.macBeaconPayloadLength);
00789             break;
00790         case macBeaconPayloadLength:
00791             if (PIBAttributeValue->macBeaconPayloadLength > aMaxBeaconPayloadLength)
00792                 t_status = m_INVALID_PARAMETER;
00793             else
00794                 mpib.macBeaconPayloadLength = PIBAttributeValue->macBeaconPayloadLength;
00795             break;
00796         case macBeaconOrder:
00797             if (PIBAttributeValue->macBeaconOrder > 15)
00798                 t_status = m_INVALID_PARAMETER;
00799             else
00800                 mpib.macBeaconOrder = PIBAttributeValue->macBeaconOrder;
00801             break;
00802         case macBeaconTxTime:
00803             mpib.macBeaconTxTime = PIBAttributeValue->macBeaconTxTime;
00804             break;
00805         case macBSN:
00806             mpib.macBSN = PIBAttributeValue->macBSN;
00807             break;
00808         case macCoordExtendedAddress:
00809             mpib.macCoordExtendedAddress = PIBAttributeValue->macCoordExtendedAddress;
00810             break;
00811         case macCoordShortAddress:
00812             mpib.macCoordShortAddress = PIBAttributeValue->macCoordShortAddress;
00813             break;
00814         case macDSN:
00815             mpib.macDSN = PIBAttributeValue->macDSN;
00816             break;
00817         case macGTSPermit:
00818             mpib.macGTSPermit = PIBAttributeValue->macGTSPermit;
00819             break;
00820         case macMaxCSMABackoffs:
00821             if (PIBAttributeValue->macMaxCSMABackoffs > 5)
00822                 t_status = m_INVALID_PARAMETER;
00823             else
00824                 mpib.macMaxCSMABackoffs = PIBAttributeValue->macMaxCSMABackoffs;
00825             break;
00826         case macMinBE:
00827             if (PIBAttributeValue->macMinBE > 3)
00828                 t_status = m_INVALID_PARAMETER;
00829             else
00830                 mpib.macMinBE = PIBAttributeValue->macMinBE;
00831             break;
00832         case macPANId:
00833             mpib.macPANId = PIBAttributeValue->macPANId;
00834             break;
00835         case macPromiscuousMode:
00836             mpib.macPromiscuousMode = PIBAttributeValue->macPromiscuousMode;
00837             //some other operations (refer to sec. 7.5.6.6)
00838             mpib.macRxOnWhenIdle = PIBAttributeValue->macPromiscuousMode;
00839             p_state = mpib.macRxOnWhenIdle?p_RX_ON:p_TRX_OFF;
00840             phy->PLME_SET_TRX_STATE_request(p_state);
00841             break;
00842         case macRxOnWhenIdle:
00843             mpib.macRxOnWhenIdle = PIBAttributeValue->macRxOnWhenIdle;
00844             break;
00845         case macShortAddress:
00846             mpib.macShortAddress = PIBAttributeValue->macShortAddress;
00847             break;
00848         case macSuperframeOrder:
00849             if (PIBAttributeValue->macSuperframeOrder > 15)
00850                 t_status = m_INVALID_PARAMETER;
00851             else
00852                 mpib.macSuperframeOrder = PIBAttributeValue->macSuperframeOrder;
00853             break;
00854         case macTransactionPersistenceTime:
00855             mpib.macTransactionPersistenceTime = PIBAttributeValue->macTransactionPersistenceTime;
00856             break;
00857         case macACLEntryDescriptorSet:
00858         case macACLEntryDescriptorSetSize:
00859         case macDefaultSecurity:
00860         case macACLDefaultSecurityMaterialLength:
00861         case macDefaultSecurityMaterial:
00862         case macDefaultSecuritySuite:
00863         case macSecurityMode:
00864             break;      //currently security ignored in simulation
00865         default:
00866             t_status = m_UNSUPPORTED_ATTRIBUTE;
00867             break;
00868     }
00869     sscs->MLME_SET_confirm(t_status,PIBAttribute);
00870 }
00871 
00872 void Mac802_15_4::MLME_START_request(UINT_16 PANId,UINT_8 LogicalChannel,UINT_8 BeaconOrder,
00873                      UINT_8 SuperframeOrder,bool PANCoordinator,bool BatteryLifeExtension,
00874                      bool CoordRealignment,bool SecurityEnable)
00875 {
00876     mlme_start_request(PANId,LogicalChannel,BeaconOrder,SuperframeOrder,PANCoordinator,BatteryLifeExtension,CoordRealignment,SecurityEnable,true);
00877 }
00878 
00879 void Mac802_15_4::MLME_SYNC_request(UINT_8 LogicalChannel, bool TrackBeacon)
00880 {
00881     mlme_sync_request(LogicalChannel,TrackBeacon,true);
00882 }
00883 
00884 void Mac802_15_4::MLME_POLL_request(UINT_8 CoordAddrMode,UINT_16 CoordPANId,IE3ADDR CoordAddress,bool SecurityEnable)
00885 {
00886     mlme_poll_request(CoordAddrMode,CoordPANId,CoordAddress,SecurityEnable,false,true);
00887 }
00888 
00889 inline int Mac802_15_4::hdr_dst(char* hdr, int dst)
00890 {
00891     return p802_15_4hdr_dst(hdr,dst);
00892 }
00893 
00894 inline int Mac802_15_4::hdr_src(char* hdr, int src)
00895 {
00896     return p802_15_4hdr_src(hdr,src);
00897 }
00898 
00899 inline int Mac802_15_4::hdr_type(char* hdr, UINT_16 type)
00900 {
00901     return p802_15_4hdr_type(hdr,type);
00902 }
00903 
00904 void Mac802_15_4::recv(Packet *p, Handler *h)
00905 {
00906     hdr_lrwpan* wph = HDR_LRWPAN(p);
00907     hdr_cmn *ch = HDR_CMN(p);
00908     bool noAck;
00909     int i;
00910     UINT_8 txop;
00911     FrameCtrl frmCtrl;
00912     SuperframeSpec t_sfSpec;
00913 
00914     if (!Nam802_15_4::emStatus)
00915         Nam802_15_4::emStatus = (netif_->node()->energy_model()?true:false);    //is there a better place to do this?
00916 
00917     if(ch->direction() == hdr_cmn::DOWN)    //outgoing packet
00918     {
00919 #ifdef DEBUG802_15_4
00920         fprintf(stdout,"[%s::%s][%f](node %d) outgoing pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = ??, size = %d\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),ch->size());
00921 #endif
00922         //-- Notes for power-saving:
00923         //   It turns out to be very difficult to apply sleeping model in 802.15.4.
00924         //   First, a node shouldn't go to sleep if peer2peer transmission mode is
00925         //   used. Non-peer2peer means that a node only communicates with its parent 
00926         //   and/or children, which requests that pure tree routing be used.
00927         //   Second, even pure tree routing is used, a node can only go to sleep
00928         //   if it satisfies both the sleeping condition as a parent (to its children)
00929         //   and that as a child (to its parent) in a multi-hop environment. To 
00930         //   satisfy both conditions requires efficient scheduling scheme.
00931         //   Since ns2, by default, treats the power consumption in idle mode same 
00932         //   as that in sleeping mode, it makes no difference at this moment whether
00933         //   we set sleeping mode or not.
00934 
00935         //wake up the node if it is in sleep mode (only for legacy applications)
00936         EnergyModel *em = netif_->node()->energy_model();
00937         if (em)
00938         {
00939             if (em->energy() <= 0)
00940             {
00941                 drop(p,"ENE");
00942                 return;
00943             }
00944             if (em->sleep())
00945             {
00946                 em->set_node_sleep(0);
00947                 em->set_node_state(EnergyModel::INROUTE);
00948             }
00949         }
00950         /* SSCS should call MCPS_DATA_request() directly
00951         if (from SSCS)
00952         {
00953             MCPS_DATA_request(wph->SrcAddrMode,wph->SrcPANId,wph->SrcAddr,
00954                       wph->DstAddrMode,wph->DstPANId,wph->DstAddr,
00955                       ch->size(),p,wph->msduHandle,wph->TxOptions);
00956         }
00957         else    //802.15.4-unaware upper layer app. packet
00958         */
00959         {
00960             callback_ = h;
00961             if (p802_15_4macDA(p) == (nsaddr_t)MAC_BROADCAST)
00962                 txop = 0;
00963             else
00964             {
00965                 if (Mac802_15_4::ack4data)
00966                     txop = TxOp_Acked;
00967                 else
00968                     txop = 0;
00969                 txop |= Mac802_15_4::txOption;
00970             }
00971             wph->msduHandle = 0;
00972             MCPS_DATA_request(0,0,0,defFrmCtrl_AddrMode16,mpib.macPANId,p802_15_4macDA(p),ch->size(),p,0,txop); //direct transmission w/o security
00973         }
00974         return;
00975     }
00976     else    //incoming packet
00977     {
00978 #ifdef DEBUG802_15_4
00979         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());
00980 #endif
00981         resetCounter(p802_15_4macSA(p));
00982         //if during ED scan, discard all frames received over the PHY layer data service (sec. 7.5.2.1.1)
00983         //if during Active/Passive scan, discard all frames received over the PHY layer data service that are not beacon frames (sec. 7.5.2.1.2/7.5.2.1.3)
00984         //if during Orphan scan, discard all frames received over the PHY layer data service that are not coordinator realignment command frames (sec. 7.5.2.1.4)
00985         frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
00986         frmCtrl.parse();
00987         if (taskP.taskStatus(TP_mlme_scan_request))
00988         if (taskP.mlme_scan_request_ScanType == 0x00)       //ED scan
00989         {
00990 #ifdef DEBUG802_15_4
00991             fprintf(stdout,"[D][ED][%s::%s::%d][%f](node %d) dropping pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %d\n",__FILE__,__FUNCTION__,__LINE__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
00992 #endif
00993             drop(p,"ED");
00994             return;
00995         }
00996         else if (((taskP.mlme_scan_request_ScanType == 0x01)    //Active scan
00997                 ||(taskP.mlme_scan_request_ScanType == 0x02))   //Passive scan
00998              && (frmCtrl.frmType != defFrmCtrl_Type_Beacon))
00999         {
01000 #ifdef DEBUG802_15_4
01001             fprintf(stdout,"[D][APS][%s::%s::%d][%f](node %d) dropping pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %d\n",__FILE__,__FUNCTION__,__LINE__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
01002 #endif
01003             drop(p,"APS");
01004             return;
01005         }
01006         else if ((taskP.mlme_scan_request_ScanType == 0x03) //Orphan scan
01007              && ((frmCtrl.frmType != defFrmCtrl_Type_MacCmd)||(wph->MSDU_CmdType != 0x08)))
01008         {
01009 #ifdef DEBUG802_15_4
01010             fprintf(stdout,"[D][OPH][%s::%s::%d][%f](node %d) dropping pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %d\n",__FILE__,__FUNCTION__,__LINE__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
01011 #endif
01012             drop(p,"OPH");
01013             return;
01014         }
01015 
01016         //drop the packet if corrupted
01017         if (ch->error())
01018         {
01019 #ifdef DEBUG802_15_4
01020             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__,__LINE__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
01021 #endif
01022             drop(p,"ERR");
01023             return;
01024         }
01025         //drop the packet if the link quality is too bad (basically, collisions)
01026         if ((wph->rxTotPower-p->txinfo_.RxPr) > 0.0)
01027         if (p->txinfo_.RxPr/(wph->rxTotPower-p->txinfo_.RxPr) < p->txinfo_.CPThresh)
01028         {
01029 #ifdef DEBUG802_15_4
01030             fprintf(stdout,"[D][LQI][%s::%s::%d][%f](node %d) dropping pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %d\n",__FILE__,__FUNCTION__,__LINE__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
01031 #endif
01032             if (!wph->colFlag)  
01033                 nam->flashNodeColor(CURRENT_TIME);
01034             drop(p,"LQI");
01035             return;
01036         }
01037 
01038         if (frmCtrl.frmType == defFrmCtrl_Type_Beacon)
01039         {
01040             t_sfSpec.SuperSpec = wph->MSDU_SuperSpec;
01041             t_sfSpec.parse();
01042             if (t_sfSpec.BO != 15)
01043             {
01044                 //update superframe specification
01045                 sfSpec3 = t_sfSpec;
01046                 //calculate the time when we received the first bit of the beacon
01047                 macBcnOtherRxTime = (CURRENT_TIME - phy->trxTime(p)) * phy->getRate('s');
01048                 //update beacon order and superframe order
01049                 macBeaconOrder3 = sfSpec3.BO;
01050                 macSuperframeOrder3 = sfSpec3.SO;
01051             }
01052         }
01053 
01054         //---perform filtering (refer to sec. 7.5.6.2)---
01055         //drop the packet if FCS is not correct (ignored in simulation)
01056         if (ch->ptype() == PT_MAC)  //perform further filtering only if it is an 802.15.4 packet
01057         if (!mpib.macPromiscuousMode)   //perform further filtering only if the PAN is currently not in promiscuous mode
01058         {
01059             //check packet type
01060             if ((frmCtrl.frmType != defFrmCtrl_Type_Beacon)
01061               &&(frmCtrl.frmType != defFrmCtrl_Type_Data)
01062               &&(frmCtrl.frmType != defFrmCtrl_Type_Ack)
01063               &&(frmCtrl.frmType != defFrmCtrl_Type_MacCmd))
01064             {
01065 #ifdef DEBUG802_15_4
01066                 fprintf(stdout,"[D][TYPE][%s::%s::%d][%f](node %d) dropping pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %d\n",__FILE__,__FUNCTION__,__LINE__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
01067 #endif
01068                 drop(p,"TYPE");
01069                 return;
01070             }
01071             //check source PAN ID for beacon frame
01072             if ((frmCtrl.frmType == defFrmCtrl_Type_Beacon)
01073               &&(mpib.macPANId != 0xffff)
01074               &&(wph->MHR_SrcAddrInfo.panID != mpib.macPANId))
01075             {
01076 #ifdef DEBUG802_15_4
01077                 fprintf(stdout,"[D][PAN][%s::%s::%d][%f](node %d) dropping pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %d\n",__FILE__,__FUNCTION__,__LINE__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
01078 #endif
01079                 drop(p,"PAN");
01080                 return;
01081             }
01082             //check dest. PAN ID if it is included
01083             if ((frmCtrl.dstAddrMode == defFrmCtrl_AddrMode16)
01084               ||(frmCtrl.dstAddrMode == defFrmCtrl_AddrMode64))
01085             if ((wph->MHR_DstAddrInfo.panID != 0xffff)
01086               &&(wph->MHR_DstAddrInfo.panID != mpib.macPANId))
01087             {
01088 #ifdef DEBUG802_15_4
01089                 fprintf(stdout,"[D][PAN][%s::%s::%d][%f](node %d) dropping pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %d\n",__FILE__,__FUNCTION__,__LINE__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
01090 #endif
01091                 drop(p,"PAN");
01092                 return;
01093             }
01094             //check dest. address if it is included
01095             if (frmCtrl.dstAddrMode == defFrmCtrl_AddrMode16)
01096             {
01097                 if ((wph->MHR_DstAddrInfo.addr_16 != 0xffff)
01098                  && (wph->MHR_DstAddrInfo.addr_16 != mpib.macShortAddress))
01099                 {
01100 #ifdef DEBUG802_15_4
01101                     fprintf(stdout,"[D][ADR][%s::%s::%d][%f](node %d) dropping pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %d\n",__FILE__,__FUNCTION__,__LINE__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
01102 #endif
01103                     drop(p,"ADR");
01104                     return;
01105                 }
01106 
01107             }
01108             else if (frmCtrl.dstAddrMode == defFrmCtrl_AddrMode64)
01109             {
01110                 if (wph->MHR_DstAddrInfo.addr_64 != aExtendedAddress)
01111                 {
01112 #ifdef DEBUG802_15_4
01113                     fprintf(stdout,"[D][ADR][%s::%s::%d][%f](node %d) dropping pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %d\n",__FILE__,__FUNCTION__,__LINE__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
01114 #endif
01115                     drop(p,"ADR");
01116                     return;
01117                 }
01118             }
01119             //check for Data/MacCmd frame only w/ source address
01120             if ((frmCtrl.frmType == defFrmCtrl_Type_Data)
01121               ||(frmCtrl.frmType == defFrmCtrl_Type_MacCmd))
01122             if (frmCtrl.dstAddrMode == defFrmCtrl_AddrModeNone)
01123             {
01124                 if (((!capability.FFD)||(numberDeviceLink(&deviceLink1) == 0))  //I am not a coordinator
01125                   ||(wph->MHR_SrcAddrInfo.panID != mpib.macPANId))
01126                 {
01127 #ifdef DEBUG802_15_4
01128                     fprintf(stdout,"[D][PAN][%s::%s::%d][%f](node %d) dropping pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %d\n",__FILE__,__FUNCTION__,__LINE__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
01129 #endif
01130                     drop(p,"PAN");
01131                     return;
01132                 }
01133             }
01134             //we need to add one more filter for supporting multi-hop beacon enabled mode (not in the draft)
01135             if (frmCtrl.frmType == defFrmCtrl_Type_Beacon)
01136             if (wph->MHR_DstAddrInfo.panID != 0xffff)
01137             if ((mpib.macCoordExtendedAddress != wph->MHR_SrcAddrInfo.addr_64)  //ok even for short address (in simulation)
01138             &&  (mpib.macCoordExtendedAddress != def_macCoordExtendedAddress))
01139             {
01140 #ifdef DEBUG802_15_4
01141                 fprintf(stdout,"[D][COO][%s::%s::%d][%f](node %d) dropping pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %d\n",__FILE__,__FUNCTION__,__LINE__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
01142 #endif
01143                 drop(p,"COO");
01144                 return;
01145             }
01146         }   //---filtering done---
01147 
01148         //perform security task if required (ignored in simulation)
01149 
01150         //send an acknowledgement if needed (no matter this is a duplicated packet or not)
01151         if ((frmCtrl.frmType == defFrmCtrl_Type_Data)
01152           ||(frmCtrl.frmType == defFrmCtrl_Type_MacCmd))
01153         if (frmCtrl.ackReq) //acknowledgement required
01154         {
01155             //association request command will be ignored under following cases
01156             if ((frmCtrl.frmType == defFrmCtrl_Type_MacCmd)
01157              && (wph->MSDU_CmdType == 0x01))
01158             if ((!capability.FFD)           //not an FFD
01159              || (mpib.macShortAddress == 0xffff)    //not yet joined any PAN
01160              || (!macAssociationPermit))        //association not permitted
01161             {
01162                 Packet::free(p);
01163                 return;
01164             }
01165         
01166             noAck = false;
01167             if (frmCtrl.frmType == defFrmCtrl_Type_MacCmd)
01168             if ((rxCmd)||(txBcnCmd))
01169                 noAck = true;
01170             if (!noAck)
01171             {
01172                 constructACK(p);
01173                 //stop CSMA-CA if it is pending (it will be restored after the transmission of ACK)
01174                 if (backoffStatus == 99)
01175                 {
01176                     backoffStatus = 0;
01177                     csmaca->cancel();
01178                 }
01179                 plme_set_trx_state_request(p_TX_ON);
01180             }
01181         }
01182         else
01183             resetTRX();
01184 
01185         if (frmCtrl.frmType == defFrmCtrl_Type_MacCmd)
01186         if ((rxCmd)||(txBcnCmd))
01187         {
01188 #ifdef DEBUG802_15_4
01189             {
01190             fprintf(stdout,"[D][BSY][%s::%s::%d][%f](node %d) dropping pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %d\n",__FILE__,__FUNCTION__,__LINE__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
01191             if (rxCmd)
01192                 fprintf(stdout,"\trxCmd pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %d\n",wpan_pName(rxCmd),p802_15_4macSA(rxCmd),p802_15_4macDA(rxCmd),HDR_CMN(rxCmd)->uid(),HDR_LRWPAN(rxCmd)->uid,HDR_CMN(rxCmd)->size());
01193             if (txBcnCmd)
01194                 fprintf(stdout,"\ttxBcnCmd pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %d\n",wpan_pName(txBcnCmd),p802_15_4macSA(txBcnCmd),p802_15_4macDA(txBcnCmd),HDR_CMN(txBcnCmd)->uid(),HDR_LRWPAN(txBcnCmd)->uid,HDR_CMN(txBcnCmd)->size());
01195             }
01196 #endif
01197             drop(p,"BSY");
01198             return;
01199         }
01200 
01201         if (frmCtrl.frmType == defFrmCtrl_Type_Data)
01202         if (rxData)
01203         {
01204 #ifdef DEBUG802_15_4
01205             fprintf(stdout,"[D][BSY][%s::%s::%d][%f](node %d) dropping pkt: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %d\n",__FILE__,__FUNCTION__,__LINE__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),p802_15_4macDA(p),ch->uid(),wph->uid,ch->size());
01206 #endif
01207             drop(p,"BSY");
01208             return;
01209         }
01210 
01211         //check duplication -- must be performed AFTER all drop's
01212         if (frmCtrl.frmType == defFrmCtrl_Type_Beacon)
01213             i = chkAddUpdHListLink(&hlistBLink1,&hlistBLink2,p802_15_4macSA(p),wph->MHR_BDSN);
01214         else if (frmCtrl.frmType != defFrmCtrl_Type_Ack)
01215             i = chkAddUpdHListLink(&hlistDLink1,&hlistDLink2,p802_15_4macSA(p),wph->MHR_BDSN);
01216         else    //Acknowledgement
01217         {
01218             assert(txPkt);
01219                 if (wph->MHR_BDSN != HDR_LRWPAN(txPkt)->MHR_BDSN)
01220                 i = 2;
01221             else i = 0;
01222         }
01223         if (i == 2)
01224         {
01225 #ifdef DEBUG802_15_4
01226             fprintf(stdout,"[D][DUP][%s::%s][%f](node %d) dropping duplicated packet: type = %s, from = %d, uid = %d, mac_uid = %ld, size = %d, SN = %d\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),ch->uid(),wph->uid,ch->size(),wph->MHR_BDSN);
01227 #endif
01228             drop(p,"DUP");
01229             return;
01230         }
01231 
01232         //handle the beacon packet
01233         if (frmCtrl.frmType == defFrmCtrl_Type_Beacon)
01234             recvBeacon(p);
01235 
01236         //handle the ack. packet
01237         else if (frmCtrl.frmType == defFrmCtrl_Type_Ack)
01238             recvAck(p);
01239 
01240         //handle the command packet
01241         else if (frmCtrl.frmType == defFrmCtrl_Type_MacCmd)
01242             recvCommand(p);
01243         
01244         //handle the data packet
01245         else if (frmCtrl.frmType == defFrmCtrl_Type_Data)
01246         {
01247             recvData(p);
01248         }
01249     }
01250 }
01251 
01252 void Mac802_15_4::recvBeacon(Packet *p)
01253 {
01254     hdr_lrwpan* wph = HDR_LRWPAN(p);
01255     FrameCtrl frmCtrl;
01256     PendAddrSpec pendSpec;
01257     bool pending;
01258     double txtime;
01259     UINT_8 ifs;
01260     int i;
01261     //update superframe specification
01262     sfSpec2.SuperSpec = wph->MSDU_SuperSpec;
01263     sfSpec2.parse();
01264 #ifdef DEBUG802_15_4
01265     hdr_cmn* ch = HDR_CMN(p);
01266     fprintf(stdout,"[%s::%s][%f](node %d) M_BEACON [BO:%d][SO:%d] received: from = %d, uid = %d, mac_uid = %ld, size = %d, SN = %d\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,sfSpec2.BO,sfSpec2.SO,p802_15_4macSA(p),ch->uid(),wph->uid,ch->size(),wph->MHR_BDSN);
01267 #endif
01268     //calculate the time when we received the first bit of the beacon
01269     txtime = phy->trxTime(p);
01270 
01271     /* Linux floating number compatibility
01272     macBcnRxTime = (CURRENT_TIME - txtime) * phy->getRate('s');
01273     */
01274     {
01275     double tmpf;
01276     tmpf = CURRENT_TIME - txtime;
01277     macBcnRxTime = tmpf * phy->getRate('s');
01278     }
01279 
01280     //calculate <beaconPeriods2>
01281     if (HDR_CMN(p)->size() <= aMaxSIFSFrameSize)
01282         ifs = aMinSIFSPeriod;
01283     else
01284         ifs = aMinLIFSPeriod;
01285 
01286     /* Linux floating number compatibility
01287     beaconPeriods2 = (UINT_8)((txtime * phy->getRate('s') + ifs) / aUnitBackoffPeriod);
01288     */
01289     double tmpf;
01290     tmpf = txtime * phy->getRate('s');
01291     tmpf += ifs;
01292     beaconPeriods2 = (UINT_8)(tmpf / aUnitBackoffPeriod);
01293 
01294     /* Linux floating number compatibility
01295     if (fmod((txtime * phy->getRate('s')+ ifs) ,aUnitBackoffPeriod) > 0.0)
01296     */
01297     if (fmod(tmpf ,aUnitBackoffPeriod) > 0.0)
01298         beaconPeriods2++;
01299     //update PAN descriptor
01300     frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
01301     frmCtrl.parse();
01302     panDes2.CoordAddrMode = frmCtrl.srcAddrMode;
01303     panDes2.CoordPANId = wph->MHR_SrcAddrInfo.panID;
01304     panDes2.CoordAddress_64 = wph->MHR_SrcAddrInfo.addr_64;     //ok even it is a 16-bit address
01305     panDes2.LogicalChannel = wph->phyCurrentChannel;
01306     panDes2.SuperframeSpec = wph->MSDU_SuperSpec;
01307     gtsSpec2.fields = wph->MSDU_GTSFields;
01308     gtsSpec2.parse();
01309     panDes2.GTSPermit = gtsSpec2.permit;
01310     panDes2.LinkQuality = wph->ppduLinkQuality;
01311     panDes2.TimeStamp = (UINT_32)macBcnRxTime;
01312     panDes2.SecurityUse = wph->SecurityUse;
01313     panDes2.ACLEntry = wph->ACLEntry;
01314     panDes2.SecurityFailure = false;                //ignored in simulation
01315     panDes2.clusTreeDepth = wph->clusTreeDepth;
01316     //handle active and passive channel scans
01317     if ((taskP.taskStatus(TP_mlme_scan_request))
01318      || (taskP.taskStatus(TP_mlme_rx_enable_request)))
01319     {
01320         rxBeacon = p;
01321         dispatch(p_SUCCESS,__FUNCTION__);
01322     }
01323 
01324     if ((mpib.macPANId == 0xffff)
01325     || (mpib.macPANId != panDes2.CoordPANId)
01326     || (taskP.taskStatus(TP_mlme_associate_request)))
01327     {
01328         Packet::free(p);
01329         return;     
01330     }
01331     numLostBeacons = 0;
01332     nam->flashNodeMark(CURRENT_TIME);
01333     macBeaconOrder2 = sfSpec2.BO;
01334     macSuperframeOrder2 = sfSpec2.SO;
01335     //populate <macCoordShortAddress> if needed
01336     if (mpib.macCoordShortAddress == def_macCoordShortAddress)
01337     if (frmCtrl.srcAddrMode == defFrmCtrl_AddrMode16)
01338         mpib.macCoordShortAddress = wph->MHR_SrcAddrInfo.addr_16;
01339     dispatch(p_SUCCESS,__FUNCTION__);
01340     //resume extraction timer if needed
01341     extractT->resume();
01342     //CSMA-CA may be waiting for the new beacon
01343     if (wph->MHR_SrcAddrInfo.panID == mpib.macPANId)
01344     if (backoffStatus == 99)
01345         csmaca->newBeacon('r');
01346     
01347     //check if need to notify the upper layer
01348     if ((!mpib.macAutoRequest)||(wph->MSDU_PayloadLen > 0))
01349         sscs->MLME_BEACON_NOTIFY_indication(wph->MHR_BDSN,&panDes2,wph->MSDU_PendAddrFields.spec,wph->MSDU_PendAddrFields.addrList,wph->MSDU_PayloadLen,wph->MSDU_Payload);
01350     if (mpib.macAutoRequest)
01351     {
01352         //handle the pending packet
01353         pendSpec.fields = wph->MSDU_PendAddrFields;
01354         pendSpec.parse();
01355         pending = false;
01356         for (i=0;i<pendSpec.numShortAddr;i++)
01357         {
01358             if (pendSpec.fields.addrList[i] == mpib.macShortAddress)
01359             {
01360                 pending = true;
01361                 break;
01362             }
01363         }
01364         if (!pending)
01365         for (i=0;i<pendSpec.numExtendedAddr;i++)
01366         {
01367             if (pendSpec.fields.addrList[pendSpec.numShortAddr + i] == aExtendedAddress)
01368             {
01369                 pending = true;
01370                 break;
01371             }
01372         }
01373 
01374         if (pending)
01375         {
01376             //frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
01377             //frmCtrl.parse();
01378             mlme_poll_request(frmCtrl.srcAddrMode,wph->MHR_SrcAddrInfo.panID,wph->MHR_SrcAddrInfo.addr_64,capability.secuCapable,true,true);
01379         }
01380 
01381         log(p);
01382     }
01383 }
01384 
01385 void Mac802_15_4::recvAck(Packet *p)
01386 {
01387     hdr_lrwpan *wph;
01388     hdr_cmn *ch;
01389     FrameCtrl frmCtrl;
01390 
01391     wph = HDR_LRWPAN(p);
01392     ch = HDR_CMN(p);
01393 #ifdef DEBUG802_15_4
01394     fprintf(stdout,"[%s::%s][%f](node %d) M_ACK received: from = %d, SN = %d, uid = %d, mac_uid = %ld\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,p802_15_4macSA(p),wph->MHR_BDSN,ch->uid(),wph->uid);
01395 #endif
01396     if ((!txBcnCmd)&&(!txBcnCmd2)&&(!txData))
01397     {
01398         Packet::free(p);
01399         return;
01400     }
01401     
01402     //check the sequence number in the ack. to see if it matches that in the <txPkt>
01403     if (wph->MHR_BDSN != HDR_LRWPAN(txPkt)->MHR_BDSN)
01404     {
01405         Packet::free(p);
01406         return;
01407     }
01408 
01409     if (txT->busy())
01410         txT->stop();
01411     else    
01412     {
01413 #ifdef DEBUG802_15_4
01414         fprintf(stdout,"[%s::%s][%f](node %d) LATE ACK received: from = %d, SN = %d, uid = %d, mac_uid = %ld\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,p802_15_4macSA(p),wph->MHR_BDSN,ch->uid(),wph->uid);
01415 #endif
01416         //only handle late ack. for data packet
01417         if (txPkt != txData)
01418         {
01419             Packet::free(p);
01420             return;
01421         }
01422 
01423         if (backoffStatus == 99)
01424         {
01425             backoffStatus = 0;
01426             csmaca->cancel();
01427         }
01428     }
01429 
01430     //set pending flag for data polling
01431     if (txPkt == txBcnCmd2)
01432     if ((taskP.taskStatus(TP_mlme_poll_request))
01433      && (strcmp(taskP.taskFrFunc(TP_mlme_poll_request),__FUNCTION__) == 0))
01434     {
01435         frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
01436         frmCtrl.parse();
01437         taskP.mlme_poll_request_pending = frmCtrl.frmPending;
01438     }
01439     
01440     dispatch(p_SUCCESS,__FUNCTION__);
01441 
01442     log(p);
01443 }
01444 
01445 void Mac802_15_4::recvCommand(Packet *p)
01446 {
01447     hdr_lrwpan* wph;
01448     FrameCtrl frmCtrl;
01449     bool ackReq;
01450 
01451 #ifdef DEBUG802_15_4
01452     wph = HDR_LRWPAN(p);
01453     hdr_cmn* ch = HDR_CMN(p);
01454     fprintf(stdout,"[%s::%s][%f](node %d) %s received: from = %d, uid = %d, mac_uid = %ld, size = %d, SN = %d\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),ch->uid(),wph->uid,ch->size(),wph->MHR_BDSN);
01455 #endif
01456     ackReq = false;
01457     switch(HDR_LRWPAN(p)->MSDU_CmdType)
01458     {
01459         case 0x01:  //Association request
01460             //recv() is in charge of sending ack.
01461             //MLME-ASSOCIATE.indication() will be passed to upper layer after the transmission of ack.
01462             assert(rxCmd == 0);
01463             rxCmd = p;
01464             ackReq = true;
01465             break;
01466         case 0x02:  //Association response
01467             //recv() is in charge of sending ack.
01468             //MLME-ASSOCIATE.confirm will be passed to upper layer after the transmission of ack.
01469             assert(rxCmd == 0);
01470             rxCmd = p;
01471             ackReq = true;
01472             wph = HDR_LRWPAN(p);
01473             rt_myNodeID = *((UINT_16 *)wph->MSDU_Payload);
01474 #ifdef ZigBeeIF
01475             sscs->setGetClusTreePara('g',p);
01476 #endif
01477             break;
01478         case 0x03:  //Disassociation notification
01479             break;
01480         case 0x04:  //Data request
01481             //recv() is in charge of sending ack.
01482             //pending packet will be sent after the transmission of ack.
01483             assert(rxCmd == 0);
01484             rxCmd = p;
01485             ackReq = true;
01486             break;
01487         case 0x05:  //PAN ID conflict notification
01488             break;
01489         case 0x06:  //Orphan notification
01490             wph = HDR_LRWPAN(p);
01491             sscs->MLME_ORPHAN_indication(wph->MHR_SrcAddrInfo.addr_64,false,0);
01492             break;
01493         case 0x07:  //Beacon request
01494             if (capability.FFD                      //I am an FFD
01495              && (mpib.macAssociationPermit)                 //association permitted
01496              && (mpib.macShortAddress != 0xffff)                //allow to send beacons
01497              && (mpib.macBeaconOrder == 15))                //non-beacon enabled mode
01498             {
01499                 //send a beacon using unslotted CSMA-CA
01500 #ifdef DEBUG802_15_4
01501                 fprintf(stdout,"[%s::%s][%f](node %d) before alloc txBcnCmd:\n\t\ttxBeacon\t= %ld\n\t\ttxAck   \t= %ld\n\t\ttxBcnCmd\t= %ld\n\t\ttxBcnCmd2\t= %ld\n\t\ttxData  \t= %ld\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,txBeacon,txAck,txBcnCmd,txBcnCmd2,txData);
01502 #endif
01503                 assert(!txBcnCmd);
01504                 txBcnCmd = Packet::alloc();
01505                 if (!txBcnCmd) break;
01506                 wph = HDR_LRWPAN(txBcnCmd);
01507                 frmCtrl.FrmCtrl = 0;
01508                 frmCtrl.setFrmType(defFrmCtrl_Type_Beacon);
01509                 frmCtrl.setSecu(secuBeacon);
01510                 frmCtrl.setFrmPending(false);
01511                 frmCtrl.setAckReq(false);
01512                 frmCtrl.setDstAddrMode(defFrmCtrl_AddrModeNone);
01513                 if (mpib.macShortAddress == 0xfffe)
01514                 {
01515                     frmCtrl.setSrcAddrMode(defFrmCtrl_AddrMode64);
01516                     wph->MHR_SrcAddrInfo.panID = mpib.macPANId;
01517                     wph->MHR_SrcAddrInfo.addr_64 = aExtendedAddress;
01518                 }
01519                 else
01520                 {
01521                     frmCtrl.setSrcAddrMode(defFrmCtrl_AddrMode16);
01522                     wph->MHR_SrcAddrInfo.panID = mpib.macPANId;
01523                     wph->MHR_SrcAddrInfo.addr_16 = mpib.macShortAddress;
01524                 }
01525                 sfSpec.SuperSpec = 0;
01526                 sfSpec.setBO(15);
01527                 sfSpec.setBLE(mpib.macBattLifeExt);
01528                 sfSpec.setPANCoor(isPANCoor);
01529                 sfSpec.setAssoPmt(mpib.macAssociationPermit);
01530                 wph->MSDU_GTSFields.spec = 0;
01531                 wph->MSDU_PendAddrFields.spec = 0;
01532                 wph->MSDU_PayloadLen = 0;
01533 #ifdef ZigBeeIF
01534                 sscs->setGetClusTreePara('s',txBcnCmd);
01535 #endif
01536                 constructMPDU(4,txBcnCmd,frmCtrl.FrmCtrl,mpib.macBSN++,wph->MHR_DstAddrInfo,wph->MHR_SrcAddrInfo,sfSpec.SuperSpec,0,0);
01537                 hdr_dst((char *)HDR_MAC(txBcnCmd),p802_15_4macSA(p));
01538                 hdr_src((char *)HDR_MAC(txBcnCmd),index_);
01539                 HDR_CMN(txBcnCmd)->ptype() = PT_MAC;
01540                 //for trace
01541                 HDR_CMN(txBcnCmd)->next_hop_ = p802_15_4macDA(txBcnCmd);        //nam needs the nex_hop information
01542                 p802_15_4hdrBeacon(txBcnCmd);
01543                 csmacaBegin('c');
01544             }
01545             break;
01546         case 0x08:  //Coordinator realignment
01547             wph = HDR_LRWPAN(p);
01548             frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
01549             frmCtrl.parse();
01550             if (frmCtrl.dstAddrMode == defFrmCtrl_AddrMode64)       //directed to an orphan device
01551             {
01552                 //recv() is in charge of sending ack.
01553                 //further handling continues after the transmission of ack.
01554                 assert(rxCmd == 0);
01555                 rxCmd = p;
01556                 ackReq = true;
01557             }
01558             else                                //broadcasted realignment command
01559             if ((wph->MHR_SrcAddrInfo.addr_64 == macCoordExtendedAddress)
01560             && (wph->MHR_SrcAddrInfo.panID == mpib.macPANId))
01561             {
01562                 //no specification in the draft as how to handle this packet, so use our discretion
01563                 mpib.macPANId = *((UINT_16 *)wph->MSDU_Payload);
01564                 mpib.macCoordShortAddress = *((UINT_16 *)(wph->MSDU_Payload + 2));
01565                 tmp_ppib.phyCurrentChannel = wph->MSDU_Payload[4];
01566                 phy->PLME_SET_request(phyCurrentChannel,&tmp_ppib);
01567             }
01568             break;
01569         case 0x09:  //GTS request
01570             break;
01571         default:
01572             assert(0);
01573             break;
01574     }
01575 
01576     if (!ackReq)
01577         log(p);
01578     else    
01579         log(p->refcopy());
01580 }
01581 
01582 void Mac802_15_4::recvData(Packet *p)
01583 {
01584     hdr_lrwpan* wph;
01585     hdr_cmn* ch;
01586     FrameCtrl frmCtrl;
01587     UINT_8 ifs;
01588 
01589     //pass the data packet to upper layer
01590     //(we need some time to process the packet -- so delay SIFS/LIFS symbols from now or after finishing sending the ack.)
01591     //(refer to Figure 60 for details of SIFS/LIFS)
01592     assert(rxData == 0);
01593     rxData = p;
01594     wph = HDR_LRWPAN(p);
01595     ch = HDR_CMN(p);
01596 #ifdef DEBUG802_15_4
01597     fprintf(stdout,"[%s::%s][%f](node %d) DATA (%s) received: from = %d, uid = %d, mac_uid = %ld, size = %d, SN = %d\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(p),p802_15_4macSA(p),ch->uid(),wph->uid,ch->size(),wph->MHR_BDSN);
01598 #endif
01599     frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
01600     frmCtrl.parse();
01601     rxDataTime = CURRENT_TIME;
01602     if (!frmCtrl.ackReq)
01603     {
01604         if (ch->size() <= aMaxSIFSFrameSize)
01605             ifs = aMinSIFSPeriod;
01606         else
01607             ifs = aMinLIFSPeriod;
01608         Scheduler::instance().schedule(&IFSH, &(IFSH.nullEvent), ifs/phy->getRate('s'));
01609     }
01610     //else  //schedule and dispatch after finishing ack. transmission
01611 }
01612 
01613 bool Mac802_15_4::toParent(Packet *p)
01614 {
01615     hdr_lrwpan* wph = HDR_LRWPAN(p);
01616     FrameCtrl frmCtrl;
01617 
01618     frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
01619     frmCtrl.parse();
01620     if (((frmCtrl.dstAddrMode == defFrmCtrl_AddrMode16)&&(wph->MHR_DstAddrInfo.addr_16 == mpib.macCoordShortAddress))
01621     ||  ((frmCtrl.dstAddrMode == defFrmCtrl_AddrMode64)&&(wph->MHR_DstAddrInfo.addr_64 == mpib.macCoordExtendedAddress)))
01622         return true;
01623     else
01624         return false;
01625 }
01626 
01627 double Mac802_15_4::locateBoundary(bool parent,double wtime)
01628 {
01629     //In the case that a node acts as both a coordinator and a device, 
01630     //transmission of beacons is preferablly to be aligned with reception 
01631     //of beacons to achieve the best results -- but we cannot control this.
01632     //For example, the parent may originally work in non-beacon enabled mode
01633     //and later on begin to work in beacon enabled mode; the parent will
01634     //not align with the child since it is not supposed to handle the beacons
01635     //from the child.
01636     //So the alignment is specifically w.r.t. either transmission of beacons
01637     //(as a coordinator) or reception of beacons (as a device), but there is
01638     //no guarantee to satisfy both.
01639     
01640     int align;          
01641     double bcnTxRxTime,bPeriod;
01642     double newtime;
01643     
01644     if ((mpib.macBeaconOrder == 15)&&(macBeaconOrder2 == 15))
01645         return wtime;       
01646 
01647     if (parent)         
01648         align = (macBeaconOrder2 == 15)?1:2;
01649     else                
01650         align = (mpib.macBeaconOrder == 15)?2:1;
01651     
01652     bcnTxRxTime = (align == 1)?(macBcnTxTime / phy->getRate('s')):(macBcnRxTime / phy->getRate('s'));
01653     bPeriod = aUnitBackoffPeriod / phy->getRate('s');
01654 
01655     /* Linux floating number compatibility
01656     newtime = fmod(CURRENT_TIME + wtime - bcnTxRxTime, bPeriod);
01657     */
01658     {
01659     double tmpf;
01660     tmpf = CURRENT_TIME + wtime;
01661     tmpf -= bcnTxRxTime;
01662     newtime = fmod(tmpf, bPeriod);
01663     }
01664 
01665 #ifdef DEBUG802_15_4
01666     //fprintf(stdout,"[%s::%s][%f](node %d) delay = bPeriod - fmod = %f - %f = %f\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,bPeriod,newtime,bPeriod - newtime);
01667 #endif
01668     if(newtime > 0.0)
01669     {
01670         /* Linux floating number compatibility
01671         newtime = wtime + (bPeriod - newtime);
01672         */
01673         {
01674         double tmpf;
01675         tmpf = bPeriod - newtime;
01676         newtime = wtime + tmpf;
01677         }
01678     }
01679     else
01680         newtime = wtime;
01681 
01682     return newtime;
01683 }
01684 
01685 void Mac802_15_4::txOverHandler(void)
01686 {
01687     assert(txPkt);
01688     PD_DATA_confirm(p_UNDEFINED);
01689 }
01690 
01691 void Mac802_15_4::txHandler(void)
01692 {
01693     assert(txBcnCmd||txBcnCmd2||txData);
01694 
01695     Packet *p;
01696     hdr_lrwpan* wph;
01697     hdr_cmn* ch;
01698     UINT_8 t_numRetry;
01699 
01700     if (txBcnCmd) p = txBcnCmd;
01701     else if (txBcnCmd2) p = txBcnCmd2;
01702     else p = txData;
01703     wph = HDR_LRWPAN(p);
01704     ch = HDR_CMN(p);
01705 
01706     if (txBcnCmd) t_numRetry = numBcnCmdRetry;
01707     else if (txBcnCmd2) t_numRetry = numBcnCmdRetry2;
01708     else t_numRetry = numDataRetry;
01709     t_numRetry++;
01710 #ifdef DEBUG802_15_4
01711     if (t_numRetry <= aMaxFrameRetries)
01712         fprintf(stdout,"[%s::%s][%f](node %d) No ACK - retransmitting: 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());
01713     else
01714         fprintf(stdout,"[%s::%s][%f](node %d) No ACK - giving up: 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());
01715 #endif
01716     if (t_numRetry > aMaxFrameRetries)
01717         nam->flashLinkFail(CURRENT_TIME,p802_15_4macDA(p));
01718 
01719     dispatch(p_BUSY,__FUNCTION__);  //the status p_BUSY will be ignore
01720 }
01721 
01722 void Mac802_15_4::extractHandler(void)
01723 {
01724     if (taskP.taskStatus(TP_mlme_associate_request))
01725         strcpy(taskP.taskFrFunc(TP_mlme_associate_request),__FUNCTION__);
01726     dispatch(p_BUSY,__FUNCTION__);
01727 }
01728 
01729 void Mac802_15_4::assoRspWaitHandler(void)
01730 {
01731     dispatch(p_BUSY,__FUNCTION__);
01732 }
01733 
01734 void Mac802_15_4::dataWaitHandler(void)
01735 {
01736     dispatch(p_BUSY,__FUNCTION__);
01737 }
01738 
01739 void Mac802_15_4::rxEnableHandler(void)
01740 {
01741     dispatch(p_SUCCESS,__FUNCTION__);
01742 }
01743 
01744 void Mac802_15_4::scanHandler(void)
01745 {
01746     if (taskP.mlme_scan_request_ScanType == 0x01)
01747         taskP.taskStep(TP_mlme_scan_request)++;     
01748     dispatch(p_SUCCESS,__FUNCTION__);
01749 }
01750 
01751 void Mac802_15_4::beaconTxHandler(bool forTX)
01752 {
01753     hdr_lrwpan* wph;
01754     FrameCtrl frmCtrl;
01755     TRANSACLINK *tmp;
01756     int i;
01757 
01758     if ((mpib.macBeaconOrder != 15)     //beacon enabled
01759     || (oneMoreBeacon))
01760     if (forTX)
01761     {
01762         if (capability.FFD/*&&(numberDeviceLink(&deviceLink1) > 0)*/)
01763         {
01764             //enable the transmitter
01765             beaconWaiting = true;
01766             plme_set_trx_state_request(p_FORCE_TRX_OFF);    //finish your job before this!
01767             //assert(txAck == 0);   //It's not true, for the reason that packets can arrive 
01768                         //at any time if the source is in non-beacon mode.
01769                         //This could also happen if a device loses synchronization
01770                         //with its coordinator, or if a coordinator changes beacon
01771                         //order in the middle.
01772             if (txAck)
01773             {
01774 #ifdef DEBUG802_15_4
01775                 if (!updateDeviceLink(tr_oper_est, &deviceLink1, &deviceLink2, p802_15_4macDA(txAck)))  //this ACK is for my child
01776                     fprintf(stdout,"[%f](node %d) outgoing ACK truncated by beacon: src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %d\n", CURRENT_TIME,index_,p802_15_4macSA(txAck),p802_15_4macDA(txAck),HDR_CMN(txAck)->uid(),HDR_LRWPAN(txAck)->uid,HDR_CMN(txAck)->size());
01777 #endif
01778                 Packet::free(txAck);
01779                 txAck = 0;
01780             }
01781             plme_set_trx_state_request(p_TX_ON);
01782         }
01783         else
01784             assert(0);
01785     }
01786     else
01787     {
01788         if (capability.FFD/*&&(numberDeviceLink(&deviceLink1) > 0)*/)   //send a beacon here
01789         {
01790             //beaconWaiting = false;                
01791             if ((taskP.taskStatus(TP_mlme_start_request))       
01792             &&  (mpib.macBeaconOrder != 15))
01793             {
01794                 if (txAck||backoffStatus == 1)
01795                 {
01796                     beaconWaiting = false;
01797                     bcnTxT->start();
01798                     return;
01799                 }
01800             }
01801 #ifdef DEBUG802_15_4
01802             fprintf(stdout,"[%s::%s][%f](node %d) before alloc txBeacon:\n\t\ttxBeacon\t= %ld\n\t\ttxAck   \t= %ld\n\t\ttxBcnCmd\t= %ld\n\t\ttxBcnCmd2\t= %ld\n\t\ttxData  \t= %ld\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,txBeacon,txAck,txBcnCmd,txBcnCmd2,txData);
01803 #endif
01804             if (updateNFailLink(fl_oper_est,index_) == 0)
01805             {
01806                 if (txBeacon)
01807                 {
01808                     Packet::free(txBeacon);
01809                     txBeacon = 0;
01810                 }
01811                 beaconWaiting = false;
01812                 bcnTxT->start();
01813                 return;
01814             }
01815             assert(!txBeacon);
01816             txBeacon = Packet::alloc();
01817             if (!txBeacon)
01818             {
01819                 bcnTxT->start();        //try to restore the transmission of beacons next time
01820                 return;
01821             }
01822             wph = HDR_LRWPAN(txBeacon);
01823             frmCtrl.FrmCtrl = 0;
01824             frmCtrl.setFrmType(defFrmCtrl_Type_Beacon);
01825             frmCtrl.setSecu(secuBeacon);
01826             frmCtrl.setAckReq(false);
01827             frmCtrl.setDstAddrMode(defFrmCtrl_AddrModeNone);
01828             if (mpib.macShortAddress == 0xfffe)
01829             {
01830                 frmCtrl.setSrcAddrMode(defFrmCtrl_AddrMode64);
01831                 wph->MHR_SrcAddrInfo.panID = mpib.macPANId;
01832                 wph->MHR_SrcAddrInfo.addr_64 = aExtendedAddress;
01833             }
01834             else
01835             {
01836                 frmCtrl.setSrcAddrMode(defFrmCtrl_AddrMode16);
01837                 wph->MHR_SrcAddrInfo.panID = mpib.macPANId;
01838                 wph->MHR_SrcAddrInfo.addr_16 = mpib.macShortAddress;
01839             }
01840             sfSpec.SuperSpec = 0;
01841             sfSpec.setBO(mpib.macBeaconOrder);
01842             sfSpec.setSO(mpib.macSuperframeOrder);
01843             sfSpec.setFinCAP(aNumSuperframeSlots - 1);      //TBD: may be less than <aNumSuperframeSlots> when considering GTS
01844             sfSpec.setBLE(mpib.macBattLifeExt);
01845             sfSpec.setPANCoor(isPANCoor);
01846             sfSpec.setAssoPmt(mpib.macAssociationPermit);
01847             //populate the GTS fields -- more TBD when considering GTS
01848             gtsSpec.fields.spec = 0;
01849             gtsSpec.setPermit(mpib.macGTSPermit);
01850             wph->MSDU_GTSFields = gtsSpec.fields;
01851             //--- populate the pending address list ---
01852             pendAddrSpec.numShortAddr = 0;
01853             pendAddrSpec.numExtendedAddr = 0;
01854             purgeTransacLink(&transacLink1,&transacLink2);
01855             tmp = transacLink1;
01856             i = 0;
01857             while (tmp != NULL)
01858             {
01859                 if (tmp->pendAddrMode == defFrmCtrl_AddrMode16)
01860                 {
01861                     if (updateDeviceLink(tr_oper_est,&deviceLink1,&deviceLink2,tmp->pendAddr64) == 0)
01862                         i = pendAddrSpec.addShortAddr(tmp->pendAddr16);     //duplicated address filtered out
01863                 }
01864                 else
01865                 {
01866                     if (updateDeviceLink(tr_oper_est,&deviceLink1,&deviceLink2,tmp->pendAddr64) == 0)
01867                         i = pendAddrSpec.addExtendedAddr(tmp->pendAddr64);  //duplicated address filtered out
01868                 }
01869                 if (i >= 7) break;
01870                 tmp = tmp->next;
01871             }
01872             pendAddrSpec.format();
01873             wph->MSDU_PendAddrFields = pendAddrSpec.fields;
01874             frmCtrl.setFrmPending(i>0);
01875             //To populate the beacon payload field, <macBeaconPayloadLength> and <macBeaconPayload>
01876             //should be set first, in that order (use primitive MLME_SET_request).
01877             wph->MSDU_PayloadLen = mpib.macBeaconPayloadLength;
01878             memcpy(wph->MSDU_Payload,mpib.macBeaconPayload,mpib.macBeaconPayloadLength);
01879             //-----------------------------------------
01880 #ifdef ZigBeeIF
01881             sscs->setGetClusTreePara('s',txBeacon);
01882 #endif
01883             constructMPDU(2 + gtsSpec.size() + pendAddrSpec.size() + mpib.macBeaconPayloadLength,txBeacon,frmCtrl.FrmCtrl,mpib.macBSN++,wph->MHR_DstAddrInfo,wph->MHR_SrcAddrInfo,sfSpec.SuperSpec,0,0);
01884             hdr_src((char *)HDR_MAC(txBeacon),index_);
01885             hdr_dst((char *)HDR_MAC(txBeacon),MAC_BROADCAST);
01886             HDR_CMN(txBeacon)->ptype() = PT_MAC;
01887             HDR_CMN(txBeacon)->next_hop_ = p802_15_4macDA(txBeacon);        //nam needs the nex_hop information
01888             p802_15_4hdrBeacon(txBeacon);
01889 #ifdef DEBUG802_15_4
01890             fprintf(stdout,"[%s::%s][%f](node %d) transmit BEACON to %d: SN = %d, uid = %d, mac_uid = %ld\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,p802_15_4macDA(txBeacon),HDR_LRWPAN(txBeacon)->MHR_BDSN,HDR_CMN(txBeacon)->uid(),HDR_LRWPAN(txBeacon)->uid);
01891 #endif
01892             txPkt = txBeacon;
01893             HDR_CMN(txBeacon)->direction() = hdr_cmn::DOWN;
01894             //nam->flashNodeMark(CURRENT_TIME);
01895             sendDown(txBeacon->refcopy(), this);
01896             mpib.macBeaconTxTime = (UINT_32)(CURRENT_TIME * phy->getRate('s'));
01897             macBcnTxTime = CURRENT_TIME * phy->getRate('s');    //double used for accuracy
01898             oneMoreBeacon = false;
01899         }
01900         else
01901             assert(0);
01902     }
01903     bcnTxT->start();    //don't disable this even beacon not enabled (beacon may be temporarily disabled like in channel scan, but it will be enabled again)
01904 }
01905 
01906 void Mac802_15_4::beaconRxHandler(void)
01907 {
01908     if (macBeaconOrder2 != 15)      //beacon enabled (do nothing if beacon not enabled)
01909     {
01910         if (txAck)
01911         {
01912             Packet::free(txAck);
01913             txAck = 0;
01914         }
01915         //enable the receiver
01916         plme_set_trx_state_request(p_RX_ON);
01917         if (taskP.mlme_sync_request_tracking)   
01918         {
01919             //a better way is using another timer to detect <numLostBeacons> right after the header of superframe
01920             if (numLostBeacons > aMaxLostBeacons)
01921             {
01922                 char label[11];
01923                 //label[0] = 0;     
01924                 strcpy(label,"\" \"");
01925 #ifdef ZigBeeIF
01926                 if (sscs->t_isCT)
01927                     sprintf(label,"\"%s\"",(sscs->RNType())?"+":"-");
01928 #endif
01929                 nam->changeLabel(CURRENT_TIME,label);
01930                 changeNodeColor(CURRENT_TIME,Nam802_15_4::def_Node_clr);
01931                 sscs->MLME_SYNC_LOSS_indication(m_BEACON_LOSS);
01932                 numLostBeacons = 0;
01933             }
01934             else
01935             {
01936                 numLostBeacons++;
01937                 bcnRxT->start();
01938             }
01939         }
01940     }
01941 }
01942 
01943 void Mac802_15_4::beaconSearchHandler(void)
01944 {
01945     dispatch(p_BUSY,__FUNCTION__);
01946 }
01947 
01948 void Mac802_15_4::isPanCoor(bool isPC)
01949 {
01950     if (isPANCoor == isPC)
01951         return;
01952 
01953     if (isPC)
01954         changeNodeColor(CURRENT_TIME,Nam802_15_4::def_PANCoor_clr);
01955     else if (isPANCoor)
01956         changeNodeColor(CURRENT_TIME,
01957            (mpib.macPANId == 0xffff) ? Nam802_15_4::def_Node_clr :
01958            (mpib.macAssociationPermit) ? Nam802_15_4::def_Coor_clr : Nam802_15_4::def_Dev_clr);
01959     isPANCoor = isPC;
01960 }
01961 
01962 //-------------------------------------------------------------------------------------
01963 
01964 void Mac802_15_4::set_trx_state_request(PHYenum state,const char *frFile,const char *frFunc,int line)
01965 {
01966 #ifdef DEBUG802_15_4
01967     fprintf(stdout,"[%s::%s][%f](node %d): %s request from [%s:%s:%d]\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,
01968     (state == p_RX_ON)?"RX_ON":
01969     (state == p_TX_ON)?"TX_ON":
01970     (state == p_TRX_OFF)?"TRX_OFF":
01971     (state == p_FORCE_TRX_OFF)?"FORCE_TRX_OFF":"???",
01972     frFile,frFunc,line);
01973 #endif
01974     trx_state_req = state;
01975     phy->PLME_SET_TRX_STATE_request(state);
01976 }
01977 
01978 char *taskName[] = {"NONE",
01979             "MCPS-DATA.request",
01980             "MLME-ASSOCIATE.request",
01981             "MLME-ASSOCIATE.response",
01982             "MLME-DISASSOCIATE.request",
01983             "MLME-ORPHAN.response",
01984             "MLME-RESET.request",
01985             "MLME-RX-ENABLE.request",
01986             "MLME-SCAN.request",
01987             "MLME-START.request",
01988             "MLME-SYNC.request",
01989             "MLME-POLL.request",
01990             "CCA_csmaca",
01991             "RX_ON_csmaca"};
01992 void Mac802_15_4::checkTaskOverflow(UINT_8 task)
01993 {
01994     //Though we assume the upper layer should know what it is doing -- should send down requests one by one.
01995     //But we'd better check again (we have no control over upper layer and we don't know who is operating on the upper layer)
01996     if (taskP.taskStatus(task))
01997     {
01998         fprintf(stdout,"[%s::%s][%f](node %d) task overflow: %s\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,taskName[task]);
01999         exit(1);
02000     }
02001     else
02002     {
02003         taskP.taskStep(task) = 0;
02004         (taskP.taskFrFunc(task))[0] = 0;
02005     }
02006 }
02007 
02008 void Mac802_15_4::dispatch(PHYenum status,const char *frFunc,PHYenum req_state,MACenum mStatus)
02009 {
02010     hdr_lrwpan *wph;
02011     hdr_cmn *ch;
02012     FrameCtrl frmCtrl;
02013     UINT_8 ifs;
02014     //int i;
02015 
02016     if (strcmp(frFunc,"csmacaCallBack") == 0)
02017     {
02018         if (txCsmaca == txBcnCmd2)
02019         {
02020             if (taskP.taskStatus(TP_mlme_scan_request)
02021             && (strcmp(taskP.taskFrFunc(TP_mlme_scan_request),frFunc) == 0))
02022             {
02023                 if ((taskP.mlme_scan_request_ScanType == 0x01)  //active scan
02024                 ||  (taskP.mlme_scan_request_ScanType == 0x03)) //orphan scan
02025                     mlme_scan_request(taskP.mlme_scan_request_ScanType,taskP.mlme_scan_request_ScanChannels,taskP.mlme_scan_request_ScanDuration,false,status);
02026             }
02027             else if (taskP.taskStatus(TP_mlme_start_request)
02028             && (strcmp(taskP.taskFrFunc(TP_mlme_start_request),frFunc) == 0))
02029                 mlme_start_request(taskP.mlme_start_request_PANId,taskP.mlme_start_request_LogicalChannel,taskP.mlme_start_request_BeaconOrder,taskP.mlme_start_request_SuperframeOrder,taskP.mlme_start_request_PANCoordinator,taskP.mlme_start_request_BatteryLifeExtension,0,taskP.mlme_start_request_SecurityEnable,false,status);
02030             else if (taskP.taskStatus(TP_mlme_associate_request)
02031             && (strcmp(taskP.taskFrFunc(TP_mlme_associate_request),frFunc) == 0))
02032                 mlme_associate_request(0,0,0,0,0,taskP.mlme_associate_request_SecurityEnable,false,status);
02033             else if (taskP.taskStatus(TP_mlme_poll_request)
02034             && (strcmp(taskP.taskFrFunc(TP_mlme_poll_request),frFunc) == 0))
02035                 mlme_poll_request(taskP.mlme_poll_request_CoordAddrMode,taskP.mlme_poll_request_CoordPANId,taskP.mlme_poll_request_CoordAddress,taskP.mlme_poll_request_SecurityEnable,taskP.mlme_poll_request_autoRequest,false,status);
02036             else    //default handling for txBcnCmd2
02037             {
02038                 if (status == p_IDLE)
02039                     plme_set_trx_state_request(p_TX_ON);
02040                 else
02041                 {
02042                     freePkt(txBcnCmd2);
02043                     txBcnCmd2 = 0;
02044                     csmacaResume();     //other packet may be waiting
02045                 }
02046             }
02047         }
02048         else if (txCsmaca == txData)
02049         {
02050             assert(taskP.taskStatus(TP_mcps_data_request)
02051             && (strcmp(taskP.taskFrFunc(TP_mcps_data_request),frFunc) == 0));
02052 
02053             if (taskP.mcps_data_request_TxOptions & TxOp_GTS)       //GTS transmission
02054             {
02055                 ;   //TBD
02056             }
02057             else if ((taskP.mcps_data_request_TxOptions & TxOp_Indirect)    //indirect transmission
02058             && (capability.FFD&&(numberDeviceLink(&deviceLink1) > 0)))  //I am a coordinator
02059             {
02060                 if (status != p_IDLE)
02061                     mcps_data_request(0,0,0,0,0,0,0,0,0,taskP.mcps_data_request_TxOptions,false,p_BUSY,m_CHANNEL_ACCESS_FAILURE);
02062                 else
02063                 {
02064                     strcpy(taskP.taskFrFunc(TP_mcps_data_request),"PD_DATA_confirm");
02065                     plme_set_trx_state_request(p_TX_ON);
02066                 }
02067             }
02068             else        //direct transmission: in this case, let mcps_data_request() take care of everything
02069                 mcps_data_request(0,0,0,0,0,0,0,0,0,taskP.mcps_data_request_TxOptions,false,status);
02070         }
02071         else if (txCsmaca == txBcnCmd)  //default handling for txBcnCmd
02072         {
02073             wph = HDR_LRWPAN(txBcnCmd);
02074             frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
02075             frmCtrl.parse();
02076             if (status == p_IDLE)
02077             {
02078                 if ((frmCtrl.frmType == defFrmCtrl_Type_MacCmd)     //command packet
02079                 && (wph->MSDU_CmdType == 0x02))             //association response packet
02080                     strcpy(taskP.taskFrFunc(TP_mlme_associate_response),"PD_DATA_confirm");
02081                 else if ((frmCtrl.frmType == defFrmCtrl_Type_MacCmd)    //command packet
02082                 && (wph->MSDU_CmdType == 0x08))             //coordinator realignment response packet
02083                     strcpy(taskP.taskFrFunc(TP_mlme_orphan_response),"PD_DATA_confirm");
02084                 plme_set_trx_state_request(p_TX_ON);
02085             }
02086             else
02087             {
02088                 if ((frmCtrl.frmType == defFrmCtrl_Type_MacCmd)     //command packet
02089                 && (wph->MSDU_CmdType == 0x02))             //association response packet
02090                     mlme_associate_response(taskP.mlme_associate_response_DeviceAddress,0,m_CHANNEL_ACCESS_FAILURE,0,false,p_BUSY); //status returned in MACenum rather than in PHYenum
02091                 else if ((frmCtrl.frmType == defFrmCtrl_Type_MacCmd)    //command packet
02092                 && (wph->MSDU_CmdType == 0x08))             //coordinator realignment response packet
02093                     mlme_orphan_response(taskP.mlme_orphan_response_OrphanAddress,0,true,false,false,p_BUSY);
02094                 else
02095                 {
02096                     freePkt(txBcnCmd);
02097                     txBcnCmd = 0;
02098                     csmacaResume();     //other packets may be waiting
02099                 }
02100             }
02101         }
02102         //else      //may be purged from pending list
02103     }
02104     else if (strcmp(frFunc,"PD_DATA_confirm") == 0)
02105     {
02106         if (txPkt == txBeacon)
02107         {
02108             if (taskP.taskStatus(TP_mlme_start_request)
02109             && (strcmp(taskP.taskFrFunc(TP_mlme_start_request),frFunc) == 0))
02110                 mlme_start_request(taskP.mlme_start_request_PANId,taskP.mlme_start_request_LogicalChannel,taskP.mlme_start_request_BeaconOrder,taskP.mlme_start_request_SuperframeOrder,taskP.mlme_start_request_PANCoordinator,taskP.mlme_start_request_BatteryLifeExtension,0,taskP.mlme_start_request_SecurityEnable,false,status);
02111             else    //default handling
02112             {
02113                 resetTRX();
02114                 taskSuccess('b');
02115             }
02116         }
02117         else if (txPkt == txAck)
02118         {
02119             if (rxCmd)
02120             {
02121                 ch = HDR_CMN(rxCmd);
02122                 if (ch->size() <= aMaxSIFSFrameSize)
02123                     ifs = aMinSIFSPeriod;
02124                 else
02125                     ifs = aMinLIFSPeriod;
02126                 Scheduler::instance().schedule(&IFSH, &(IFSH.nullEvent), ifs/phy->getRate('s'));
02127                 resetTRX();
02128                 taskSuccess('a');
02129             }
02130             else if (rxData)    //default handling (virtually the only handling needed) for <rxData>
02131             {
02132                 ch = HDR_CMN(rxData);
02133                 if (ch->size() <= aMaxSIFSFrameSize)
02134                     ifs = aMinSIFSPeriod;
02135                 else
02136                     ifs = aMinLIFSPeriod;
02137                 Scheduler::instance().schedule(&IFSH, &(IFSH.nullEvent), ifs/phy->getRate('s'));
02138                 resetTRX();
02139                 taskSuccess('a');
02140             }
02141             else    //ack. for duplicated packet
02142             {
02143                 resetTRX();
02144                 taskSuccess('a');
02145             }
02146         }
02147         else if (txPkt == txBcnCmd)
02148         {
02149             //default handling -- should be replaced once a specific task will handle this
02150             wph = HDR_LRWPAN(txBcnCmd);
02151             ch = HDR_CMN(txBcnCmd);
02152             frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
02153             frmCtrl.parse();
02154             if (frmCtrl.ackReq) //ack. required
02155             {
02156                 //enable the receiver
02157                 plme_set_trx_state_request(p_RX_ON);
02158                 txT->start(mpib.macAckWaitDuration/phy->getRate('s'));
02159                 waitBcnCmdAck = true;
02160             }
02161             else        //assume success if ack. not required
02162             {
02163                 resetTRX();
02164                 taskSuccess('c');
02165             }
02166         }
02167         else if (txPkt == txBcnCmd2)
02168         {
02169             if (taskP.taskStatus(TP_mlme_scan_request)
02170             && ((taskP.mlme_scan_request_ScanType == 0x01)      //active scan
02171               ||(taskP.mlme_scan_request_ScanType == 0x03))     //orphan scan
02172             && (strcmp(taskP.taskFrFunc(TP_mlme_scan_request),frFunc) == 0))
02173                 mlme_scan_request(taskP.mlme_scan_request_ScanType,taskP.mlme_scan_request_ScanChannels,taskP.mlme_scan_request_ScanDuration,false,status);
02174             else if (taskP.taskStatus(TP_mlme_start_request)
02175             && (strcmp(taskP.taskFrFunc(TP_mlme_start_request),frFunc) == 0))
02176                 mlme_start_request(taskP.mlme_start_request_PANId,taskP.mlme_start_request_LogicalChannel,taskP.mlme_start_request_BeaconOrder,taskP.mlme_start_request_SuperframeOrder,taskP.mlme_start_request_PANCoordinator,taskP.mlme_start_request_BatteryLifeExtension,0,taskP.mlme_start_request_SecurityEnable,false,status);
02177             else if (taskP.taskStatus(TP_mlme_associate_request)
02178             && (strcmp(taskP.taskFrFunc(TP_mlme_associate_request),frFunc) == 0))
02179                 mlme_associate_request(0,0,0,0,0,taskP.mlme_associate_request_SecurityEnable,false,status);
02180             else if (taskP.taskStatus(TP_mlme_poll_request)
02181             && (strcmp(taskP.taskFrFunc(TP_mlme_poll_request),frFunc) == 0))
02182                 mlme_poll_request(taskP.mlme_poll_request_CoordAddrMode,taskP.mlme_poll_request_CoordPANId,taskP.mlme_poll_request_CoordAddress,taskP.mlme_poll_request_SecurityEnable,taskP.mlme_poll_request_autoRequest,false,status);
02183             else    //default handling
02184             {
02185                 wph = HDR_LRWPAN(txBcnCmd2);
02186                 ch = HDR_CMN(txBcnCmd2);
02187                 frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
02188                 frmCtrl.parse();
02189                 if (frmCtrl.ackReq) //ack. required
02190                 {
02191                     //enable the receiver
02192                     plme_set_trx_state_request(p_RX_ON);
02193                     txT->start(mpib.macAckWaitDuration/phy->getRate('s'));
02194                     waitBcnCmdAck2 = true;
02195                 }
02196                 else        //assume success if ack. not required
02197                 {
02198                     resetTRX();
02199                     taskSuccess('C');
02200                 }
02201             }
02202         }
02203         else if (txPkt == txData)
02204         {
02205             assert((taskP.taskStatus(TP_mcps_data_request))
02206             && (strcmp(taskP.taskFrFunc(TP_mcps_data_request),frFunc) == 0));
02207 
02208             wph = HDR_LRWPAN(txData);
02209             ch = HDR_CMN(txData);
02210             frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
02211             frmCtrl.parse();
02212             if (taskP.taskStatus(TP_mcps_data_request))
02213             {
02214                 if (taskP.mcps_data_request_TxOptions & TxOp_GTS)       //GTS transmission
02215                 {
02216                     ;   //TBD
02217                 }
02218                 else if ((taskP.mcps_data_request_TxOptions & TxOp_Indirect)    //indirect transmission
02219                 && (capability.FFD&&(numberDeviceLink(&deviceLink1) > 0)))  //I am a coordinator
02220                 {
02221                     if (!frmCtrl.ackReq)    //ack. not required
02222                         mcps_data_request(0,0,0,0,0,0,0,0,0,taskP.mcps_data_request_TxOptions,false,p_SUCCESS);
02223                     else
02224                     {
02225                         strcpy(taskP.taskFrFunc(TP_mcps_data_request),"recvAck");
02226                         //enable the receiver
02227                         plme_set_trx_state_request(p_RX_ON);
02228                         txT->start(mpib.macAckWaitDuration/phy->getRate('s'));
02229                         waitDataAck = true;
02230                     }
02231                 }
02232                 else        //direct transmission: in this case, let mcps_data_request() take care of everything
02233                     mcps_data_request(0,0,0,0,0,0,0,0,0,taskP.mcps_data_request_TxOptions,false,status);
02234             }
02235             else    //default handling (seems impossible)
02236             {
02237                 if (frmCtrl.ackReq) //ack. required
02238                 {
02239                     //enable the receiver
02240                     plme_set_trx_state_request(p_RX_ON);
02241                     txT->start(mpib.macAckWaitDuration/phy->getRate('s'));
02242                     waitDataAck = true;
02243                 }
02244                 else        //assume success if ack. not required
02245                 {
02246                     resetTRX();
02247                     taskSuccess('d');
02248                 }
02249             }
02250         }
02251         //else      //may be purged from pending list
02252     }
02253     else if (strcmp(frFunc,"recvAck") == 0)     //always check the task status if the dispatch comes from recvAck()
02254     {
02255         if (txPkt == txData)
02256         {
02257             if ((taskP.taskStatus(TP_mcps_data_request))
02258              && (strcmp(taskP.taskFrFunc(TP_mcps_data_request),frFunc) == 0))
02259                 mcps_data_request(0,0,0,0,0,0,0,0,0,taskP.mcps_data_request_TxOptions,false,p_SUCCESS);
02260             else    //default handling for <txData>
02261             {
02262                 if (taskP.taskStatus(TP_mcps_data_request)) //seems late ACK received
02263                     taskP.taskStatus(TP_mcps_data_request) = false;
02264                 resetTRX();
02265                 taskSuccess('d');
02266             }
02267         }
02268         else if (txPkt == txBcnCmd2)
02269         {
02270             if (taskP.taskStatus(TP_mlme_associate_request)
02271             && (strcmp(taskP.taskFrFunc(TP_mlme_associate_request),frFunc) == 0))
02272                 mlme_associate_request(0,0,0,0,0,taskP.mlme_associate_request_SecurityEnable,false,p_SUCCESS);
02273             else if (taskP.taskStatus(TP_mlme_poll_request)
02274             && (strcmp(taskP.taskFrFunc(TP_mlme_poll_request),frFunc) == 0))
02275                 mlme_poll_request(taskP.mlme_poll_request_CoordAddrMode,taskP.mlme_poll_request_CoordPANId,taskP.mlme_poll_request_CoordAddress,taskP.mlme_poll_request_SecurityEnable,taskP.mlme_poll_request_autoRequest,false,p_SUCCESS);
02276             else    //default handling for <txBcnCmd2>
02277                 taskSuccess('C');
02278         }
02279         else if (txPkt == txBcnCmd) //default handling for <txBcnCmd>
02280         {
02281             wph = HDR_LRWPAN(txBcnCmd);
02282             frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
02283             frmCtrl.parse();
02284             if ((frmCtrl.frmType == defFrmCtrl_Type_MacCmd)         //command packet
02285              && (wph->MSDU_CmdType == 0x02))                //association response packet
02286                 mlme_associate_response(taskP.mlme_associate_response_DeviceAddress,0,m_SUCCESS,0,false,p_SUCCESS);
02287             else if ((frmCtrl.frmType == defFrmCtrl_Type_MacCmd)        //command packet
02288             && (wph->MSDU_CmdType == 0x08))                 //coordinator realignment response packet
02289                 mlme_orphan_response(taskP.mlme_orphan_response_OrphanAddress,0,true,false,false);
02290             else
02291                 taskSuccess('c');
02292         }
02293         //else      //may be purged from pending list
02294     }
02295     else if (strcmp(frFunc,"txHandler") == 0)   //always check the task status if the dispatch comes from a timer
02296     {
02297         if (txPkt == txData)
02298         {
02299             if ((!taskP.taskStatus(TP_mcps_data_request))
02300              || (strcmp(taskP.taskFrFunc(TP_mcps_data_request),"recvAck") != 0))
02301                 return;
02302 
02303             if (taskP.taskStatus(TP_mcps_data_request))
02304             if (taskP.mcps_data_request_TxOptions & TxOp_GTS)       //GTS transmission
02305             {
02306                 ;   //TBD
02307             }
02308             else if ((taskP.mcps_data_request_TxOptions & TxOp_Indirect)    //indirect transmission
02309             && (capability.FFD&&(numberDeviceLink(&deviceLink1) > 0)))  //I am a coordinator
02310             {
02311                 /*
02312                 //there is contradiction in the draft:
02313                 //page 156, line 16: (for transaction, i.e., indirect transmission) "all subsequent retransmissions shall be transmitted using CSMA-CA"
02314                 //page 158, line 14-16:
02315                 //  "if a single transmission attempt has failed and the transmission was indirect, the coordinator shall not
02316                 //  retransmit the data or MAC command frame. Instead, the frame shall remain in the transaction queue of the
02317                 //  coordinator."
02318                 //the description on page 158 is more reasonable (though we already proceeded according to page 156)
02319                 // now follow page 158
02320                 numDataRetry++;
02321                 if (numDataRetry <= aMaxFrameRetries)
02322                 {
02323                 //no need to check if the packet has been purged -- if purged, then taskFailed() should have set txData = 0
02324                 wph = HDR_LRWPAN(txData);
02325                 frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
02326                 frmCtrl.parse();
02327                 i = updateTransacLinkByPktOrHandle(tr_oper_est,&transacLink1,&transacLink2,txData);
02328                 if (i != 0) //already purged from pending list
02329                 {
02330                 Packet::free(txData);
02331                 txData = 0;
02332                 return;
02333                 }
02334                 // -- don't end here, but afte 'else'
02335                 waitDataAck = false;
02336                 csmacaResume();
02337                 }
02338                 else
02339                 */
02340                 mcps_data_request(0,0,0,0,0,0,0,0,0,taskP.mcps_data_request_TxOptions,false,p_BUSY,m_NO_ACK);
02341             }
02342             else        //direct transmission: in this case, let mcps_data_request() take care of everything
02343                 mcps_data_request(0,0,0,0,0,0,0,0,0,taskP.mcps_data_request_TxOptions,false,p_BUSY);    //status can be anything but p_SUCCESS
02344         }
02345         else if (txPkt == txBcnCmd2)
02346         {
02347             if (taskP.taskStatus(TP_mlme_associate_request)
02348                 && (strcmp(taskP.taskFrFunc(TP_mlme_associate_request),"recvAck") == 0))
02349                 mlme_associate_request(0,0,0,0,0,taskP.mlme_associate_request_SecurityEnable,false,p_BUSY); //status can anything but p_SUCCESS
02350             else if (taskP.taskStatus(TP_mlme_poll_request)
02351             && (strcmp(taskP.taskFrFunc(TP_mlme_poll_request),"recvAck") == 0))
02352                 mlme_poll_request(taskP.mlme_poll_request_CoordAddrMode,taskP.mlme_poll_request_CoordPANId,taskP.mlme_poll_request_CoordAddress,taskP.mlme_poll_request_SecurityEnable,taskP.mlme_poll_request_autoRequest,false,p_BUSY);       //status can anything but p_SUCCESS
02353             else    //default handling for <txBcnCmd2>
02354             {
02355                 numBcnCmdRetry2++;
02356                 if (numBcnCmdRetry2 <= aMaxFrameRetries)
02357                     waitBcnCmdAck2 = false;
02358                 else
02359                 {
02360                     freePkt(txBcnCmd2);
02361                     txBcnCmd2 = 0;
02362                 }
02363                 csmacaResume();     //other packets may be waiting
02364             }
02365         }
02366         else if (txPkt == txBcnCmd)
02367         {
02368             wph = HDR_LRWPAN(txBcnCmd);
02369             frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
02370             frmCtrl.parse();
02371             if ((frmCtrl.frmType == defFrmCtrl_Type_MacCmd)     //command packet
02372              && (wph->MSDU_CmdType == 0x02))            //association response packet
02373             {
02374                 //different from data packet, association response packet
02375                 //should be retransmitted though it uses indirect transmission
02376                 //(refer to page 67, line 28-32)
02377                 numBcnCmdRetry++;
02378                 if (numBcnCmdRetry <= aMaxFrameRetries)
02379                 {
02380                     /* no need to check if the packet has been purged -- if purged, then taskFailed() should have set txBcnCmd = 0
02381                     if (wph->indirect)              //indirect transmission
02382                     {
02383                         frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
02384                         frmCtrl.parse();
02385                         i = updateTransacLinkByPktOrHandle(tr_oper_est,&transacLink1,&transacLink2,txBcnCmd);
02386                         if (i != 0) //already purged from pending list
02387                         {
02388                             Packet::free(txBcnCmd);
02389                             txBcnCmd = 0;
02390                             return;
02391                         }
02392                     }
02393                     */
02394                     strcpy(taskP.taskFrFunc(TP_mlme_associate_response),"csmacaCallBack");
02395                     waitBcnCmdAck = false;
02396                     csmacaResume();
02397                 }
02398                 else
02399                     mlme_associate_response(taskP.mlme_associate_response_DeviceAddress,0,m_NO_ACK,0,false,p_BUSY); //status returned in MACenum rather than in PHYenum
02400             }
02401             else if ((frmCtrl.frmType == defFrmCtrl_Type_MacCmd)        //command packet
02402             && (wph->MSDU_CmdType == 0x08))                 //coordinator realignment response packet
02403             {
02404                 numBcnCmdRetry++;
02405                 if (numBcnCmdRetry <= aMaxFrameRetries)
02406                 {
02407                     strcpy(taskP.taskFrFunc(TP_mlme_orphan_response),"csmacaCallBack");
02408                     waitBcnCmdAck = false;
02409                     csmacaResume();
02410                 }
02411                 else
02412                     mlme_orphan_response(taskP.mlme_orphan_response_OrphanAddress,0,true,false,p_BUSY);
02413             }
02414             else        //default handling for <txBcnCmd>
02415             {
02416                 freePkt(txBcnCmd);
02417                 txBcnCmd = 0;
02418                 csmacaResume();     //other packets may be waiting
02419             }
02420         }
02421         //else      //may be purged from the pending list
02422         
02423     }
02424     else if (strcmp(frFunc,"PLME_SET_TRX_STATE_confirm") == 0)
02425     {
02426         //handle TRX_OFF
02427         if (req_state == p_TRX_OFF)
02428         if (taskP.taskStatus(TP_mlme_reset_request)
02429         && (strcmp(taskP.taskFrFunc(TP_mlme_reset_request),frFunc) == 0))
02430             mlme_reset_request(taskP.mlme_reset_request_SetDefaultPIB,false,status);
02431         //handle RX_ON
02432         if (req_state == p_RX_ON)
02433         if (taskP.taskStatus(TP_mlme_scan_request)
02434         && (strcmp(taskP.taskFrFunc(TP_mlme_scan_request),frFunc) == 0))
02435             mlme_scan_request(taskP.mlme_scan_request_ScanType,taskP.mlme_scan_request_ScanChannels,taskP.mlme_scan_request_ScanDuration,false,status);
02436         else if (taskP.taskStatus(TP_mlme_rx_enable_request)
02437         && (strcmp(taskP.taskFrFunc(TP_mlme_rx_enable_request),frFunc) == 0))
02438             mlme_rx_enable_request(0,taskP.mlme_rx_enable_request_RxOnTime,taskP.mlme_rx_enable_request_RxOnDuration,false);
02439     }
02440     else if (strcmp(frFunc,"PLME_SET_confirm") == 0)
02441     {
02442         if (taskP.taskStatus(TP_mlme_scan_request)
02443         && (strcmp(taskP.taskFrFunc(TP_mlme_scan_request),frFunc) == 0))
02444             mlme_scan_request(taskP.mlme_scan_request_ScanType,taskP.mlme_scan_request_ScanChannels,taskP.mlme_scan_request_ScanDuration,false,status);
02445     }
02446     else if (strcmp(frFunc,"PLME_ED_confirm") == 0)
02447     {
02448         if (taskP.taskStatus(TP_mlme_scan_request)
02449         && (taskP.mlme_scan_request_ScanType == 0x00)       //ED scan
02450         && (strcmp(taskP.taskFrFunc(TP_mlme_scan_request),frFunc) == 0))
02451             mlme_scan_request(taskP.mlme_scan_request_ScanType,taskP.mlme_scan_request_ScanChannels,taskP.mlme_scan_request_ScanDuration,false,status);
02452     }
02453     else if (strcmp(frFunc,"recvBeacon") == 0)
02454     {
02455         if (taskP.taskStatus(TP_mlme_scan_request)
02456         && (strcmp(taskP.taskFrFunc(TP_mlme_scan_request),frFunc) == 0))
02457             mlme_scan_request(taskP.mlme_scan_request_ScanType,taskP.mlme_scan_request_ScanChannels,taskP.mlme_scan_request_ScanDuration,false,p_SUCCESS);
02458         else if (taskP.taskStatus(TP_mlme_rx_enable_request)
02459         && (strcmp(taskP.taskFrFunc(TP_mlme_rx_enable_request),frFunc) == 0))
02460             mlme_rx_enable_request(0,taskP.mlme_rx_enable_request_RxOnTime,taskP.mlme_rx_enable_request_RxOnDuration,false);
02461         else if (taskP.taskStatus(TP_mlme_sync_request)
02462         && (strcmp(taskP.taskFrFunc(TP_mlme_sync_request),frFunc) == 0))
02463             mlme_sync_request(0,taskP.mlme_sync_request_tracking,false,p_SUCCESS);
02464     }
02465     else if (strcmp(frFunc,"scanHandler") == 0) //always check the task status if the dispatch comes from a timer
02466     {
02467         if (taskP.taskStatus(TP_mlme_scan_request))
02468             mlme_scan_request(taskP.mlme_scan_request_ScanType,taskP.mlme_scan_request_ScanChannels,taskP.mlme_scan_request_ScanDuration,false,p_BUSY);
02469     }
02470     else if (strcmp(frFunc,"extractHandler") == 0)  //always check the task status if the dispatch comes from a timer
02471     {
02472         if (taskP.taskStatus(TP_mlme_associate_request)
02473         && (strcmp(taskP.taskFrFunc(TP_mlme_associate_request),frFunc) == 0))
02474         {
02475             mlme_associate_request(0,0,0,0,0,taskP.mlme_associate_request_SecurityEnable,false,p_BUSY); //status ignored in case 4, but should set to any value but p_SUCCESS in case 7 -- p_BUSY will be ok anyway
02476         }
02477         else if (taskP.taskStatus(TP_mlme_poll_request)
02478         && (strcmp(taskP.taskFrFunc(TP_mlme_poll_request),"IFSHandler") == 0))
02479             mlme_poll_request(taskP.mlme_poll_request_CoordAddrMode,taskP.mlme_poll_request_CoordPANId,taskP.mlme_poll_request_CoordAddress,taskP.mlme_poll_request_SecurityEnable,taskP.mlme_poll_request_autoRequest,false,p_BUSY);
02480     }
02481     else if (strcmp(frFunc,"assoRspWaitHandler") == 0)  //always check the task status if the dispatch comes from a timer
02482     {
02483         if (taskP.taskStatus(TP_mlme_associate_response))
02484         {
02485             taskP.taskStep(TP_mlme_associate_response) = 2;
02486             mlme_associate_response(taskP.mlme_associate_response_DeviceAddress,0,m_SUCCESS,0,false,p_BUSY);    //status ignored
02487         }
02488     }
02489     else if (strcmp(frFunc,"dataWaitHandler") == 0) //always check the task status if the dispatch comes from a timer
02490     {
02491         if (taskP.taskStatus(TP_mcps_data_request))
02492         {
02493             taskP.taskStep(TP_mcps_data_request) = 2;
02494             mcps_data_request(0,0,0,0,0,0,0,0,0,taskP.mcps_data_request_TxOptions,false,p_BUSY);    //status ignored
02495         }
02496     }
02497     else if (strcmp(frFunc,"IFSHandler") == 0)  //always check the task status if the dispatch comes from a timer
02498     {
02499         if (taskP.taskStatus(TP_mlme_associate_request)
02500         && (strcmp(taskP.taskFrFunc(TP_mlme_associate_request),frFunc) == 0))
02501             mlme_associate_request(0,0,0,0,0,taskP.mlme_associate_request_SecurityEnable,false,p_SUCCESS,mStatus);
02502         else if (taskP.taskStatus(TP_mlme_poll_request)
02503         && (strcmp(taskP.taskFrFunc(TP_mlme_poll_request),frFunc) == 0))
02504             mlme_poll_request(taskP.mlme_poll_request_CoordAddrMode,taskP.mlme_poll_request_CoordPANId,taskP.mlme_poll_request_CoordAddress,taskP.mlme_poll_request_SecurityEnable,taskP.mlme_poll_request_autoRequest,false,p_SUCCESS);
02505         else if (taskP.taskStatus(TP_mlme_scan_request)
02506         && (strcmp(taskP.taskFrFunc(TP_mlme_scan_request),frFunc) == 0))
02507             mlme_scan_request(taskP.mlme_scan_request_ScanType,taskP.mlme_scan_request_ScanChannels,taskP.mlme_scan_request_ScanDuration,false,p_SUCCESS);
02508     }
02509     else if (strcmp(frFunc,"rxEnableHandler") == 0)
02510     {
02511         //if (taskP.taskStatus(TP_mlme_rx_enable_request))  //we don't check the task status (it may be reset)
02512         if (strcmp(taskP.taskFrFunc(TP_mlme_rx_enable_request),frFunc) == 0)
02513             mlme_rx_enable_request(0,taskP.mlme_rx_enable_request_RxOnTime,taskP.mlme_rx_enable_request_RxOnDuration,false);
02514     }
02515     else if (strcmp(frFunc,"beaconSearchHandler") == 0) //always check the task status if the dispatch comes from a timer
02516     {
02517         if (taskP.taskStatus(TP_mlme_sync_request)
02518         && (strcmp(taskP.taskFrFunc(TP_mlme_sync_request),"recvBeacon") == 0))
02519             mlme_sync_request(0,taskP.mlme_sync_request_tracking,false,p_BUSY); //status can anything but p_SUCCESS
02520     }
02521 }
02522 
02523 void Mac802_15_4::sendDown(Packet *p,Handler* h)
02524 {
02525     if (updateNFailLink(fl_oper_est,index_) == 0)
02526     {
02527         if (txBeacon)
02528         {
02529             beaconWaiting = false;
02530             Packet::free(txBeacon);
02531             txBeacon = 0;
02532         }
02533         return;
02534     }
02535     else if (updateLFailLink(fl_oper_est,index_,p802_15_4macDA(p)) == 0)
02536     {
02537         dispatch(p_UNDEFINED,"PD_DATA_confirm");
02538         return;
02539     }
02540 
02541     inTransmission = true;
02542 
02543     //double trx_time = phy->trxTime(p,false);
02544     /* Linux floating number compatibility
02545     txOverT->start(trx_time + 1/phy->getRate('s'));
02546     */
02547     //{
02548     //double tmpf;
02549     //tmpf = 1/phy->getRate('s');       
02550     //txOverT->start(trx_time + tmpf);
02551     //}
02552     EnergyModel *em = netif_->node()->energy_model();
02553     if (em)
02554     if (em->energy() <= 0)
02555     {
02556         PD_DATA_confirm(p_UNDEFINED);
02557         return;
02558     }
02559 
02560     downtarget_->recv(p, h);
02561 }
02562 
02563 void Mac802_15_4::mcps_data_request(UINT_8 SrcAddrMode,UINT_16 SrcPANId,IE3ADDR SrcAddr,
02564                     UINT_8 DstAddrMode,UINT_16 DstPANId,IE3ADDR DstAddr,
02565                     UINT_8 msduLength,Packet *msdu,UINT_8 msduHandle,UINT_8 TxOptions,
02566                     bool frUpper,PHYenum status,MACenum mStatus)
02567 {
02568     UINT_8 step,task;
02569     hdr_lrwpan *wph;
02570     hdr_cmn *ch;
02571     FrameCtrl frmCtrl;
02572     double kpTime;
02573     int i;
02574 
02575     task = TP_mcps_data_request;
02576     if (frUpper) checkTaskOverflow(task);   
02577 
02578     step = taskP.taskStep(task);
02579     if (step == 0)
02580     {
02581         //check if parameters valid or not
02582         ch = HDR_CMN(msdu);
02583         if (ch->ptype() == PT_MAC)  //we only check for 802.15.4 packets (let other packets go through -- must be changed in implementation)
02584         if ((SrcAddrMode > 0x03)
02585         ||(DstAddrMode > 0x03)
02586         ||(msduLength > aMaxMACFrameSize)
02587         ||(TxOptions > 0x0f))
02588         {
02589             sscs->MCPS_DATA_confirm(msduHandle,m_INVALID_PARAMETER);
02590             return;
02591         }
02592 
02593         taskP.taskStatus(task) = true;
02594         taskP.mcps_data_request_TxOptions = TxOptions;
02595         //---construct a MPDU packet (not really a new packet in simulation, but still <msdu>)---
02596         frmCtrl.FrmCtrl = 0;
02597         frmCtrl.setFrmType(defFrmCtrl_Type_Data);   //data type
02598         if (TxOptions & TxOp_Acked)
02599             frmCtrl.setAckReq(true);
02600         if (SrcPANId == DstPANId)
02601             frmCtrl.setIntraPan(true);      //Intra PAN
02602         frmCtrl.setDstAddrMode(DstAddrMode);        //we reverse the bit order -- note to use the required order in implementation
02603         frmCtrl.setSrcAddrMode(SrcAddrMode);        //we reverse the bit order -- note to use the required order in implementation
02604         wph = HDR_LRWPAN(msdu);
02605         wph->MHR_DstAddrInfo.panID = DstPANId;
02606         wph->MHR_DstAddrInfo.addr_64 = DstAddr;     //it doesn't matter if this is actually a 16-bit address
02607         wph->MHR_SrcAddrInfo.panID = SrcPANId;
02608         wph->MHR_SrcAddrInfo.addr_64 = SrcAddr;     //it doesn't matter if this is actually a 16-bit address
02609         //ignore FCS in simulation
02610         constructMPDU(msduLength,msdu,frmCtrl.FrmCtrl,mpib.macDSN++,wph->MHR_DstAddrInfo,wph->MHR_SrcAddrInfo,0,0,0);
02611         //for trace
02612         p802_15_4hdrDATA(msdu);
02613         //---------------------------------------------------------------------------------------------------
02614 
02615         //perform security task if required (ignored in simulation)
02616     }
02617 
02618     if (TxOptions & TxOp_GTS)   //GTS transmission
02619     {
02620         switch(step)
02621         {
02622             //other cases: TBD
02623             default:
02624                 break;
02625         }
02626     }
02627     else if ((TxOptions & TxOp_Indirect)                //indirect transmission
02628     && (capability.FFD&&(numberDeviceLink(&deviceLink1) > 0)))  //I am a coordinator
02629     {
02630         switch(step)
02631         {
02632             case 0:
02633                 taskP.taskStep(task)++;
02634                 taskP.mcps_data_request_pendPkt = msdu;
02635                 if ((DstAddrMode == defFrmCtrl_AddrMode16)      //16-bit address available
02636                 || (DstAddrMode == defFrmCtrl_AddrMode64))      //64-bit address available
02637                 {
02638                     /* Linux floating number compatibility
02639                     kpTime = mpib.macTransactionPersistenceTime * (aBaseSuperframeDuration * (1 << mpib.macBeaconOrder) / phy->getRate('s'));
02640                     */
02641                     {
02642                     double tmpf;
02643                     tmpf = (aBaseSuperframeDuration * (1 << mpib.macBeaconOrder) / phy->getRate('s'));
02644                     kpTime = mpib.macTransactionPersistenceTime * tmpf;     
02645                     }
02646 
02647                     chkAddTransacLink(&transacLink1,&transacLink2,DstAddrMode,DstAddr,msdu,msduHandle,kpTime);
02648                 }
02649                 strcpy(taskP.taskFrFunc(task),"csmacaCallBack");
02650                 dataWaitT->start(kpTime);       
02651                 break;
02652             case 1:
02653                 if (!taskP.taskStatus(task))    
02654                     break;
02655                 if (status == p_SUCCESS)    //data packet transmitted and, if required, ack. received 
02656                 {
02657                     dataWaitT->stop();
02658                     taskP.taskStatus(task) = false;
02659                     resetTRX();
02660                     taskSuccess('d');
02661                 }
02662                 else                //data packet transmission failed
02663                 {
02664                     //leave the packet in the queue waiting for next polling
02665                     strcpy(taskP.taskFrFunc(task),"csmacaCallBack");    //wait for next polling
02666                     //status return in MACenum, either CHANNEL_ACCESS_FAILURE or NO_ACK
02667                     //taskP.taskStatus(task) = false;   
02668                     resetTRX();
02669                     taskFailed('d',mStatus);
02670                 }
02671                 break;
02672             case 2:
02673                 if (!taskP.taskStatus(task))        
02674                     break;
02675                 taskP.taskStatus(task) = false;
02676                 //check if the transaction still pending -- actually no need to check (it must be pending if case 1 didn't happen), but no harm
02677                 i = updateTransacLinkByPktOrHandle(tr_oper_est,&transacLink1,&transacLink2,taskP.mcps_data_request_pendPkt);    //don't use <txData>, since assignment 'txData = msdu' only happens if a data request command received
02678                 if (i == 0) //still pending
02679                 {
02680                     //get a copy of the packet for taskFailed()
02681                     if (!txData)
02682                         txData = taskP.mcps_data_request_pendPkt->copy();
02683                     //delete the packet from the transaction list immediately -- prevent the packet from being transmitted at the last moment
02684                     updateTransacLinkByPktOrHandle(tr_oper_del,&transacLink1,&transacLink2,taskP.mcps_data_request_pendPkt);
02685                     resetTRX();
02686                     taskFailed('d',m_TRANSACTION_EXPIRED);
02687                     return;
02688                 }
02689                 else    //being successfully extracted
02690                 {
02691                     resetTRX();
02692                     taskFailed('d',m_SUCCESS);
02693                     return;
02694                 }
02695                 break;
02696 
02697             default:
02698                 break;
02699         }
02700     }
02701     else                //direct transmission
02702     {
02703         switch(step)
02704         {
02705             case 0:
02706                 taskP.taskStep(task)++;
02707                 strcpy(taskP.taskFrFunc(task),"csmacaCallBack");
02708                 assert(!txData);
02709                 txData = msdu;
02710                 csmacaBegin('d');
02711                 break;
02712             case 1:
02713                 if (status == p_IDLE)
02714                 {
02715                     taskP.taskStep(task)++;
02716                     strcpy(taskP.taskFrFunc(task),"PD_DATA_confirm");
02717                     //enable the transmitter
02718                     plme_set_trx_state_request(p_TX_ON);
02719                 }
02720                 else
02721                 {
02722                     wph = HDR_LRWPAN(txData);
02723                     ch = HDR_CMN(txData);
02724                     if (wph->msduHandle)    //from SSCS
02725                     {
02726                         //let the upper layer handle the failure (no retry)
02727                         taskP.taskStatus(task) = false;
02728                         resetTRX();
02729                         taskFailed('d',m_CHANNEL_ACCESS_FAILURE);
02730                     }
02731                     else
02732                     {
02733                         csmacaResume();
02734                     }
02735                 }
02736                 break;
02737             case 2:
02738                 wph = HDR_LRWPAN(txData);
02739                 ch = HDR_CMN(txData);
02740                 frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
02741                 frmCtrl.parse();
02742                 if (frmCtrl.ackReq) //ack. required
02743                 {
02744                     taskP.taskStep(task)++;
02745                     strcpy(taskP.taskFrFunc(task),"recvAck");
02746                     //enable the receiver
02747                     plme_set_trx_state_request(p_RX_ON);
02748                     txT->start(mpib.macAckWaitDuration/phy->getRate('s'));
02749                     waitDataAck = true;
02750                 }
02751                 else        //assume success if ack. not required
02752                 {
02753                     taskP.taskStatus(task) = false;
02754                     resetTRX();
02755                     taskSuccess('d');
02756                 }
02757                 break;
02758             case 3:
02759                 if (status == p_SUCCESS)    //ack. received
02760                 {
02761                     taskP.taskStatus(task) = false;
02762                     resetTRX();
02763                     taskSuccess('d');
02764                 }
02765                 else                //time out when waiting for ack.
02766                 {
02767                     numDataRetry++;
02768                     if (numDataRetry <= aMaxFrameRetries)
02769                     {
02770                         taskP.taskStep(task) = 1;   //important
02771                         strcpy(taskP.taskFrFunc(task),"csmacaCallBack");
02772                         waitDataAck = false;
02773                         csmacaResume();
02774                     }
02775                     else
02776                     {
02777                         taskP.taskStatus(task) = false;
02778                         resetTRX();
02779                         taskFailed('d',m_NO_ACK);
02780                     }
02781                 }
02782                 break;
02783             default:
02784                 break;
02785         }
02786     }
02787 }
02788 
02789 void Mac802_15_4::mlme_associate_request(UINT_8 LogicalChannel,UINT_8 CoordAddrMode,UINT_16 CoordPANId,IE3ADDR CoordAddress,
02790                      UINT_8 CapabilityInformation,bool SecurityEnable,
02791                      bool frUpper,PHYenum status,MACenum mStatus)
02792 {
02793     //refer to Figure 25 for association details
02794     UINT_8 step,task;
02795     FrameCtrl frmCtrl;
02796     hdr_lrwpan* wph;
02797 
02798     task = TP_mlme_associate_request;
02799     if (frUpper) checkTaskOverflow(task);
02800 
02801     step = taskP.taskStep(task);
02802     switch(step)
02803     {
02804         case 0:
02805             //check if parameters valid or not
02806             if ((!phy->channelSupported(LogicalChannel))
02807             || ((CoordAddrMode != defFrmCtrl_AddrMode16)&&(CoordAddrMode != defFrmCtrl_AddrMode64)))
02808             {
02809                 sscs->MLME_ASSOCIATE_confirm(0,m_INVALID_PARAMETER);
02810                 return;
02811             }
02812 
02813             //assert(mpib.macShortAddress == 0xffff);       //not associated yet
02814 
02815             //we may optionally track beacons if beacon enabled (here we don't)
02816 
02817             tmp_ppib.phyCurrentChannel = LogicalChannel;
02818             phy->PLME_SET_request(phyCurrentChannel,&tmp_ppib);
02819             mpib.macPANId = CoordPANId;
02820             mpib.macCoordExtendedAddress = CoordAddress;
02821             taskP.taskStatus(task) = true;
02822             taskP.taskStep(task)++;
02823             strcpy(taskP.taskFrFunc(task),"csmacaCallBack");
02824             taskP.mlme_associate_request_CoordAddrMode = CoordAddrMode;
02825             taskP.mlme_associate_request_SecurityEnable = SecurityEnable;
02826             //--- send an association request command ---
02827 #ifdef DEBUG802_15_4
02828             fprintf(stdout,"[%s::%s][%f](node %d) before alloc txBcnCmd2:\n\t\ttxBeacon\t= %ld\n\t\ttxAck   \t= %ld\n\t\ttxBcnCmd\t= %ld\n\t\ttxBcnCmd2\t= %ld\n\t\ttxData  \t= %ld\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,txBeacon,txAck,txBcnCmd,txBcnCmd2,txData);
02829 #endif
02830             assert(!txBcnCmd2);
02831             txBcnCmd2 = Packet::alloc();
02832             assert(txBcnCmd2);
02833             wph = HDR_LRWPAN(txBcnCmd2);
02834             constructCommandHeader(txBcnCmd2,&frmCtrl,0x01,CoordAddrMode,CoordPANId,CoordAddress,defFrmCtrl_AddrMode64,0xffff,aExtendedAddress,SecurityEnable,false,true);
02835             wph->MSDU_Payload[0] = capability.cap;
02836             constructMPDU(2,txBcnCmd2,frmCtrl.FrmCtrl,mpib.macDSN++,wph->MHR_DstAddrInfo,wph->MHR_SrcAddrInfo,0,0x01,0);
02837             csmacaBegin('C');
02838             //------------------------------------
02839             break;
02840         case 1:
02841             if (status == p_IDLE)
02842             {
02843                 taskP.taskStep(task)++;
02844                 strcpy(taskP.taskFrFunc(task),"PD_DATA_confirm");
02845                 if (Mac802_15_4::verbose)
02846                     fprintf(stdout,"[%f](node %d) sending association request command ...\n",CURRENT_TIME,index_);
02847                 plme_set_trx_state_request(p_TX_ON);
02848                 break;
02849             }
02850             else
02851             {
02852                 taskP.taskStatus(task) = false;
02853                 freePkt(txBcnCmd2);
02854                 txBcnCmd2 = 0;
02855                 //restore default values
02856                 mpib.macPANId = def_macPANId;
02857                 mpib.macCoordExtendedAddress = def_macCoordExtendedAddress;
02858                 sscs->MLME_ASSOCIATE_confirm(0,m_CHANNEL_ACCESS_FAILURE);
02859                 csmacaResume();
02860                 return;
02861             }
02862             break;
02863         case 2:
02864             taskP.taskStep(task)++;
02865             strcpy(taskP.taskFrFunc(task),"recvAck");
02866             plme_set_trx_state_request(p_RX_ON);    //waiting for ack.
02867             txT->start(mpib.macAckWaitDuration/phy->getRate('s'));
02868             waitBcnCmdAck2 = true;
02869             break;
02870         case 3:
02871             if (status == p_SUCCESS)    //ack. received
02872             {
02873                 taskP.taskStep(task)++;
02874                 strcpy(taskP.taskFrFunc(task),"extractHandler");
02875                 plme_set_trx_state_request(p_TRX_OFF);      //we don't want to receive any packet at this moment
02876                 if (Mac802_15_4::verbose)
02877                     fprintf(stdout,"[%f](node %d) ack for association request command received\n",CURRENT_TIME,index_);
02878                 taskSuccess('C',false);
02879                 extractT->start(aResponseWaitTime/phy->getRate('s'),false);
02880             }
02881             else                //time out when waiting for ack.
02882             {
02883                 numBcnCmdRetry2++;
02884                 if (numBcnCmdRetry2 <= aMaxFrameRetries)
02885                 {
02886                     taskP.taskStep(task) = 1;   //important
02887                     strcpy(taskP.taskFrFunc(task),"csmacaCallBack");
02888                     waitBcnCmdAck2 = false;
02889                     csmacaResume();
02890                 }
02891                 else
02892                 {
02893                     taskP.taskStatus(task) = false;
02894                     resetTRX();
02895                     freePkt(txBcnCmd2);
02896                     txBcnCmd2 = 0;
02897                     //restore default values
02898                     mpib.macPANId = def_macPANId;
02899                     mpib.macCoordExtendedAddress = def_macCoordExtendedAddress;
02900                     sscs->MLME_ASSOCIATE_confirm(0,m_NO_ACK);
02901                     csmacaResume();
02902                     return;
02903                 }
02904             }
02905             break;
02906         case 4:
02907             taskP.taskStep(task)++;
02908             strcpy(taskP.taskFrFunc(task),"PD_DATA_confirm");
02909             //-- send a data request command to extract the response ---
02910 #ifdef DEBUG802_15_4
02911             fprintf(stdout,"[%s::%s][%f](node %d) before alloc txBcnCmd2:\n\t\ttxBeacon\t= %ld\n\t\ttxAck   \t= %ld\n\t\ttxBcnCmd\t= %ld\n\t\ttxBcnCmd2\t= %ld\n\t\ttxData  \t= %ld\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,txBeacon,txAck,txBcnCmd,txBcnCmd2,txData);
02912 #endif
02913             assert(!txBcnCmd2);
02914             txBcnCmd2 = Packet::alloc();
02915             assert(txBcnCmd2);
02916             wph = HDR_LRWPAN(txBcnCmd2);
02917             if ((mpib.macShortAddress == 0xfffe)||(mpib.macShortAddress == 0xffff))
02918             {
02919                 frmCtrl.setSrcAddrMode(defFrmCtrl_AddrMode64);
02920                 wph->MHR_SrcAddrInfo.addr_64 = aExtendedAddress;
02921             }
02922             else
02923             {
02924                 frmCtrl.setSrcAddrMode(defFrmCtrl_AddrMode16);
02925                 wph->MHR_SrcAddrInfo.addr_16 = mpib.macShortAddress;
02926             }
02927             constructCommandHeader(txBcnCmd2,&frmCtrl,0x04,taskP.mlme_associate_request_CoordAddrMode,mpib.macPANId,mpib.macCoordExtendedAddress,frmCtrl.srcAddrMode,mpib.macPANId,wph->MHR_SrcAddrInfo.addr_64,SecurityEnable,false,true);
02928             constructMPDU(1,txBcnCmd2,frmCtrl.FrmCtrl,mpib.macDSN++,wph->MHR_DstAddrInfo,wph->MHR_SrcAddrInfo,0,0x04,0);
02929             waitBcnCmdAck2 = false;     //command packet not yet transmitted
02930             numBcnCmdRetry2 = 0;
02931             if (Mac802_15_4::verbose)
02932                 fprintf(stdout,"[%f](node %d) sending data request command ...\n",CURRENT_TIME,index_);
02933             txCsmaca = txBcnCmd2;
02934             plme_set_trx_state_request(p_TX_ON);
02935             //------------------------------------
02936             break;
02937         case 5:
02938             taskP.taskStep(task)++;
02939             strcpy(taskP.taskFrFunc(task),"recvAck");
02940             //enable the receiver
02941             plme_set_trx_state_request(p_RX_ON);
02942             txT->start(mpib.macAckWaitDuration/phy->getRate('s'));
02943             waitBcnCmdAck2 = true;
02944             break;
02945         case 6:
02946             if (status == p_SUCCESS)    //ack. received
02947             {
02948                 taskP.taskStep(task)++;
02949                 strcpy(taskP.taskFrFunc(task),"IFSHandler");
02950                 plme_set_trx_state_request(p_RX_ON);        //wait for response
02951                 if (Mac802_15_4::verbose)
02952                     fprintf(stdout,"[%f](node %d) ack for data request command received\n",CURRENT_TIME,index_);
02953                 taskSuccess('C',false);
02954                 extractT->start(aResponseWaitTime/phy->getRate('s'),false); //compare: for normal data, wait for <aMaxFrameResponseTime> symbols (or CAP symbols if beacon enabled) (see page 156, line 1-3)
02955             }
02956             else                //time out when waiting for ack.
02957             {
02958                 //No retransmission required in general (just wait for next beacon and poll again, see page 156, line 20-24),
02959                 //but we need to retransmit here, since the node will not handle the pending list before it has associated
02960                 //with the coordinator.
02961                 numBcnCmdRetry2++;
02962                 if (numBcnCmdRetry2 <= aMaxFrameRetries)
02963                 {
02964                     taskP.taskStep(task) = 5;   //important
02965                     strcpy(taskP.taskFrFunc(task),"PD_DATA_confirm");
02966                     waitBcnCmdAck2 = false;
02967                     txCsmaca = txBcnCmd2;
02968                     plme_set_trx_state_request(p_TX_ON);
02969                 }
02970                 else
02971                 {
02972                     taskP.taskStatus(task) = false;
02973                     resetTRX();
02974                     freePkt(txBcnCmd2);
02975                     txBcnCmd2 = 0;
02976                     //restore default values
02977                     mpib.macPANId = def_macPANId;
02978                     mpib.macCoordExtendedAddress = def_macCoordExtendedAddress;
02979                     sscs->MLME_ASSOCIATE_confirm(0,m_NO_DATA);  //assume no DATA
02980                     csmacaResume();
02981                     return;
02982                 }
02983             }
02984             break;
02985         case 7:
02986             taskP.taskStatus(task) = false;
02987             resetTRX();
02988             if (status == p_SUCCESS)        //response received
02989             {
02990                 if (mStatus == m_SUCCESS)
02991                 {
02992                     changeNodeColor(CURRENT_TIME,(mpib.macAssociationPermit)?Nam802_15_4::def_Coor_clr:Nam802_15_4::def_Dev_clr);
02993                     char label[31];
02994                     sprintf(label,"[%d]",mpib.macCoordExtendedAddress);
02995 #ifdef ZigBeeIF
02996                     if (sscs->t_isCT)
02997                         sprintf(label,"\"%s%d (%d.%d)\"",(sscs->RNType())?"+":"-",rt_myNodeID,sscs->rt_myParentNodeID,sscs->rt_myDepth);
02998 #endif
02999                     nam->changeLabel(CURRENT_TIME,label);
03000                 }
03001                 else
03002                 {
03003                     //restore default values
03004                     mpib.macPANId = def_macPANId;
03005                     mpib.macCoordExtendedAddress = def_macCoordExtendedAddress;
03006                 }
03007                 //stop the timer
03008                 if (Mac802_15_4::verbose)
03009                     fprintf(stdout,"[%f](node %d) association response command received\n",CURRENT_TIME,index_);
03010                 extractT->stop();
03011                 sscs->MLME_ASSOCIATE_confirm(rt_myNodeID,mStatus);
03012             }
03013             else                    //time out when waiting for response
03014             {
03015                 //restore default values
03016                 mpib.macPANId = def_macPANId;
03017                 mpib.macCoordExtendedAddress = def_macCoordExtendedAddress;
03018                 sscs->MLME_ASSOCIATE_confirm(0,m_NO_DATA);
03019             }
03020             csmacaResume();
03021         default:
03022             break;
03023     }
03024 }
03025 
03026 void Mac802_15_4::mlme_associate_response(IE3ADDR DeviceAddress,UINT_16 AssocShortAddress,MACenum Status,bool SecurityEnable,
03027                       bool frUpper,PHYenum status)
03028 {
03029     FrameCtrl frmCtrl;
03030     hdr_lrwpan* wph;
03031     Packet *rspPkt;
03032     double kpTime;
03033     UINT_8 step,task;
03034     int i;
03035     task = TP_mlme_associate_response;
03036     //checkTaskOverflow(task);  
03037     if (frUpper)
03038     {
03039         if (taskP.taskStatus(task)) //overflow
03040         {
03041             sscs->MLME_COMM_STATUS_indication(mpib.macPANId,defFrmCtrl_AddrMode64,aExtendedAddress,defFrmCtrl_AddrMode64,DeviceAddress,m_TRANSACTION_OVERFLOW);
03042             return;
03043         }
03044         taskP.taskStep(task) = 0;
03045         (taskP.taskFrFunc(task))[0] = 0;
03046     }
03047     step = taskP.taskStep(task);
03048     switch(step)
03049     {
03050         case 0:
03051             //check if parameters valid or not
03052             if ((Status != m_SUCCESS)&&(Status != m_PAN_at_capacity)&&(Status != m_PAN_access_denied))
03053             {
03054                 sscs->MLME_COMM_STATUS_indication(mpib.macPANId,defFrmCtrl_AddrMode64,aExtendedAddress,defFrmCtrl_AddrMode64,DeviceAddress,m_INVALID_PARAMETER);
03055                 return;
03056             }
03057             taskP.taskStatus(task) = true;
03058             taskP.taskStep(task)++;
03059             strcpy(taskP.taskFrFunc(task),"csmacaCallBack");
03060             taskP.mlme_associate_response_DeviceAddress = DeviceAddress;
03061             //--- construct an association response command packet and put it in the pending list ---
03062             rspPkt = Packet::alloc();
03063             assert(rspPkt);
03064             wph = HDR_LRWPAN(rspPkt);
03065 #ifdef ZigBeeIF
03066             sscs->setGetClusTreePara('s',rspPkt);
03067 #endif
03068             constructCommandHeader(rspPkt,&frmCtrl,0x02,defFrmCtrl_AddrMode64,mpib.macPANId,DeviceAddress,defFrmCtrl_AddrMode64,mpib.macPANId,aExtendedAddress,SecurityEnable,false,true);
03069             *((UINT_16 *)wph->MSDU_Payload) = AssocShortAddress;
03070             *((MACenum *)(wph->MSDU_Payload + 2)) = Status;
03071             constructMPDU(4,rspPkt,frmCtrl.FrmCtrl,mpib.macDSN++,wph->MHR_DstAddrInfo,wph->MHR_SrcAddrInfo,0,0x02,0);
03072             kpTime = (2 * aResponseWaitTime) / phy->getRate('s');
03073             i = chkAddTransacLink(&transacLink1,&transacLink2,defFrmCtrl_AddrMode64,DeviceAddress,rspPkt,0,kpTime);
03074             if (i != 0) //overflow or failed
03075             {
03076 #ifdef DEBUG802_15_4
03077                 hdr_cmn *ch = HDR_CMN(rspPkt);
03078                 fprintf(stdout,"[%s::%s][%f](node %d) task overflow or failed: type = %s, src = %d, dst = %d, uid = %d, mac_uid = ??, size = %d\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(rspPkt),p802_15_4macSA(rspPkt),p802_15_4macDA(rspPkt),wph->uid,ch->size());
03079 #endif
03080                 taskP.taskStatus(task) = false;
03081                 Packet::free(rspPkt);
03082                 sscs->MLME_COMM_STATUS_indication(mpib.macPANId,defFrmCtrl_AddrMode64,aExtendedAddress,defFrmCtrl_AddrMode64,DeviceAddress,m_TRANSACTION_OVERFLOW);
03083                 return;
03084             }
03085             //----------------------------------------------------------------------
03086             assoRspWaitT->start(kpTime);
03087             taskP.mlme_associate_response_pendPkt = rspPkt;
03088             break;
03089         case 1:
03090             if (!taskP.taskStatus(task))    
03091                 break;
03092             taskP.taskStatus(task) = false;
03093             assoRspWaitT->stop();
03094             if (status == p_SUCCESS)    //response packet transmitted and ack. received
03095             {
03096                 sscs->MLME_COMM_STATUS_indication(mpib.macPANId,defFrmCtrl_AddrMode64,aExtendedAddress,defFrmCtrl_AddrMode64,DeviceAddress,m_SUCCESS);
03097                 taskSuccess('c');
03098             }
03099             else                //response packet transmission failed
03100             {
03101                 //be careful, we use MACenum to return the status, either CHANNEL_ACCESS_FAILURE or NO_ACK
03102                 sscs->MLME_COMM_STATUS_indication(mpib.macPANId,defFrmCtrl_AddrMode64,aExtendedAddress,defFrmCtrl_AddrMode64,DeviceAddress,Status);
03103                 freePkt(txBcnCmd);
03104                 txBcnCmd = 0;
03105             }
03106             break;
03107         case 2:
03108             if (!taskP.taskStatus(task))    
03109                 break;
03110             taskP.taskStatus(task) = false;
03111             //check if the transaction still pending -- actually no need to check (it must be pending if case 1 didn't happen), but no harm
03112             i = updateTransacLinkByPktOrHandle(tr_oper_est,&transacLink1,&transacLink2,taskP.mlme_associate_response_pendPkt);  //don't use <txBcnCmd>, since assignment 'txBcnCmd = rspPkt' only happens if a data request command received
03113             if (i == 0) //still pending
03114             {
03115                 //delete the packet from the transaction list immediately -- prevent the packet from being transmitted at the last moment
03116                 updateTransacLinkByPktOrHandle(tr_oper_del,&transacLink1,&transacLink2,taskP.mlme_associate_response_pendPkt);
03117                 sscs->MLME_COMM_STATUS_indication(mpib.macPANId,defFrmCtrl_AddrMode64,aExtendedAddress,defFrmCtrl_AddrMode64,DeviceAddress,m_TRANSACTION_EXPIRED);
03118                 return;
03119             }
03120             else    //being successfully extracted
03121             {
03122                 sscs->MLME_COMM_STATUS_indication(mpib.macPANId,defFrmCtrl_AddrMode64,aExtendedAddress,defFrmCtrl_AddrMode64,DeviceAddress,m_SUCCESS);
03123                 return;
03124             }
03125             break;
03126         default:
03127             break;
03128     }
03129 }
03130 
03131 void Mac802_15_4::mlme_disassociate_request(IE3ADDR DeviceAddress,UINT_8 DisassociateReason,bool SecurityEnable,bool frUpper,PHYenum status)
03132 {
03133     /*
03134     FrameCtrl frmCtrl;
03135     hdr_lrwpan* wph;
03136     double kpTime;
03137     UINT_8 step,task;
03138     int i;
03139 
03140     task = TP_mlme_disassociate_request;
03141     if (frUpper) checkTaskOverflow(task);
03142 
03143     step = taskP.taskStep(task);
03144     switch(step)
03145     {
03146         case 0:
03147             //check if parameters valid or not
03148             if (DeviceAddress != mpib.macCoordExtendedAddress)      //send to a device
03149             if ((!capability.FFD)||(numberDeviceLink(&deviceLink1) == 0))   //I am not a coordinator
03150 
03151             {
03152                 sscs->MLME_DISASSOCIATE_confirm(m_INVALID_PARAMETER);
03153                 return;
03154             }
03155             taskP.mlme_disassociate_request_toCoor = (DeviceAddress == mpib.macCoordExtendedAddress);
03156             //--- construct a disassociation notification command packet ---
03157 #ifdef DEBUG802_15_4
03158             fprintf(stdout,"[%s::%s][%f](node %d) before alloc txBcnCmd2:\n\t\ttxBeacon\t= %ld\n\t\ttxAck   \t= %ld\n\t\ttxBcnCmd\t= %ld\n\t\ttxBcnCmd2\t= %ld\n\t\ttxData  \t= %ld\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,txBeacon,txAck,txBcnCmd,txBcnCmd2,txData);
03159 #endif
03160             assert(!txBcnCmd2);
03161             txBcnCmd2 = Packet::alloc();
03162             assert(txBcnCmd2);
03163             wph = HDR_LRWPAN(txBcnCmd2);
03164             if (!taskP.mlme_disassociate_request_toCoor)
03165                 wph->MHR_DstAddrInfo.addr_64 = DeviceAddress;
03166             else
03167                 wph->MHR_DstAddrInfo.addr_64 = mpib.macCoordExtendedAddress;
03168             constructCommandHeader(txBcnCmd2,&frmCtrl,0x03,defFrmCtrl_AddrMode64,mpib.macPANId,wph->MHR_DstAddrInfo.addr_64,defFrmCtrl_AddrMode64,mpib.macPANId,aExtendedAddress,SecurityEnable,false,true);
03169             *((UINT_8 *)wph->MSDU_Payload) = (taskP.mlme_disassociate_request_toCoor)?0x02:0x01;
03170             constructMPDU(2,txBcnCmd2,frmCtrl.FrmCtrl,mpib.macDSN++,wph->MHR_DstAddrInfo,wph->MHR_SrcAddrInfo,0,0x03,0);
03171             //----------------------------------------------------------------------
03172             taskP.taskStatus(task) = true;
03173             taskP.taskStep(task)++;
03174             taskP.mlme_disassociate_request_pendPkt = txBcnCmd2;
03175             if (!taskP.mlme_disassociate_request_toCoor)        //indirect transmission should be used
03176             {
03177                 // Linux floating number compatibility
03178                 //kpTime = mpib.macTransactionPersistenceTime * (aBaseSuperframeDuration * (1 << mpib.macBeaconOrder) / phy->getRate('s'));
03179                 {
03180                 double tmpf;
03181                 tmpf = (aBaseSuperframeDuration * (1 << mpib.macBeaconOrder) / phy->getRate('s'));
03182                 kpTime = mpib.macTransactionPersistenceTime * tmpf;
03183                 }
03184 
03185                 i = chkAddTransacLink(&transacLink1,&transacLink2,defFrmCtrl_AddrMode64,wph->MHR_DstAddrInfo.addr_64,txBcnCmd2,0,kpTime);
03186                 if (i != 0) //overflow or failed
03187                 {
03188                     taskP.taskStatus(task) = false;
03189                     Packet::free(txBcnCmd2);
03190                     txBcnCmd2 = 0;
03191                     sscs->MLME_DISASSOCIATE_confirm(m_TRANSACTION_OVERFLOW);
03192                     return;
03193                 }
03194                 extractT->start(kpTime,false);
03195             }
03196             else
03197                 csmacaBegin('C');
03198             break;
03199         case 1:
03200             if (!taskP.mlme_disassociate_request_toCoor)        //indirect transmission
03201             {
03202                 //check if the transaction still pending
03203                 wph = HDR_LRWPAN(txBcnCmd2);
03204                 i = updateTransacLinkByPktOrHandle(tr_oper_est,&transacLink1,&transacLink2,taskP.mlme_disassociate_request_pendPkt);    //don't use <txBcnCmd2>, since it may be null if a data request command not received
03205                 if (i == 0) //still pending
03206                 {
03207                     //delete the packet from the transaction list immediately -- prevent the packet from being transmitted at the last moment
03208                     updateTransacLinkByPktOrHandle(tr_oper_del,&transacLink1,&transacLink2,taskP.mlme_disassociate_request_pendPkt);
03209                     taskP.taskStatus(task) = false;
03210                     sscs->MLME_DISASSOCIATE_confirm(m_TRANSACTION_EXPIRED);
03211                     return;
03212                 }
03213                 else    //being successfully extracted
03214                 {
03215                     taskP.taskStatus(task) = false;
03216                     sscs->MLME_COMM_STATUS_indication(mpib.macPANId,defFrmCtrl_AddrMode64,aExtendedAddress,defFrmCtrl_AddrMode64,DeviceAddress,m_SUCCESS);
03217                     return;
03218                 }
03219             }
03220             else
03221             {
03222             }
03223             break;
03224         default:
03225             break;
03226     }
03227     */
03228 }
03229 
03230 void Mac802_15_4::mlme_orphan_response(IE3ADDR OrphanAddress,UINT_16 ShortAddress,bool AssociatedMember,bool SecurityEnable,bool frUpper,PHYenum status)
03231 {
03232     hdr_lrwpan* wph;
03233     FrameCtrl frmCtrl;
03234     //UINT_8 step;
03235     UINT_8 task;
03236 
03237     task = TP_mlme_orphan_response;
03238     if (frUpper) checkTaskOverflow(task);
03239     
03240     switch(taskP.taskStep(task))
03241     {
03242         case 0:
03243             if (AssociatedMember)
03244             {
03245                 //send a coordinator realignment command
03246 #ifdef DEBUG802_15_4
03247                 fprintf(stdout,"[%s::%s][%f](node %d) before alloc txBcnCmd:\n\t\ttxBeacon\t= %ld\n\t\ttxAck   \t= %ld\n\t\ttxBcnCmd\t= %ld\n\t\ttxBcnCmd2\t= %ld\n\t\ttxData  \t= %ld\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,txBeacon,txAck,txBcnCmd,txBcnCmd2,txData);
03248 #endif
03249                 taskP.taskStatus(task) = true;
03250                 taskP.taskStep(task)++;
03251                 strcpy(taskP.taskFrFunc(task),"csmacaCallBack");
03252                 taskP.mlme_orphan_response_OrphanAddress = OrphanAddress;
03253                 assert(!txBcnCmd);
03254                 txBcnCmd = Packet::alloc();
03255                 assert(txBcnCmd);
03256                 wph = HDR_LRWPAN(txBcnCmd);
03257                 constructCommandHeader(txBcnCmd,&frmCtrl,0x08,defFrmCtrl_AddrMode64,0xffff,OrphanAddress,defFrmCtrl_AddrMode64,mpib.macPANId,aExtendedAddress,SecurityEnable,false,true);
03258                 *((UINT_16 *)wph->MSDU_Payload) = mpib.macPANId;
03259                 *((UINT_16 *)wph->MSDU_Payload + 2) = mpib.macShortAddress;
03260                 phy->PLME_GET_request(phyCurrentChannel);
03261                 *((UINT_8 *)wph->MSDU_Payload + 4) = tmp_ppib.phyCurrentChannel;
03262                 *((UINT_16 *)wph->MSDU_Payload + 5) = ShortAddress;
03263                 constructMPDU(8,txBcnCmd,frmCtrl.FrmCtrl,mpib.macDSN++,wph->MHR_DstAddrInfo,wph->MHR_SrcAddrInfo,0,0x08,0);
03264                 csmacaBegin('c');
03265             }
03266             break;
03267         case 1:
03268             taskP.taskStatus(task) = false;
03269             if (status == p_SUCCESS)    //response packet transmitted and ack. received
03270             {
03271                 sscs->MLME_COMM_STATUS_indication(mpib.macPANId,defFrmCtrl_AddrMode64,aExtendedAddress,defFrmCtrl_AddrMode64,OrphanAddress,m_SUCCESS);
03272                 taskSuccess('c');
03273             }
03274             else                //response packet transmission failed
03275             {
03276                 sscs->MLME_COMM_STATUS_indication(mpib.macPANId,defFrmCtrl_AddrMode64,aExtendedAddress,defFrmCtrl_AddrMode64,OrphanAddress,m_CHANNEL_ACCESS_FAILURE);
03277                 freePkt(txBcnCmd);
03278                 txBcnCmd = 0;
03279                 csmacaResume();     //other packets may be waiting
03280             }
03281             break;
03282         default:
03283             break;
03284     }
03285 }
03286 
03287 void Mac802_15_4::mlme_reset_request(bool SetDefaultPIB,bool frUpper,PHYenum status)
03288 {
03289     //UINT_8 step;
03290     UINT_8 task;
03291 
03292     task = TP_mlme_reset_request;
03293     if (frUpper) checkTaskOverflow(task);
03294 
03295     switch(taskP.taskStep(task))
03296     {
03297         case 0:
03298             taskP.taskStatus(task) = true;
03299             taskP.taskStep(task)++;
03300             strcpy(taskP.taskFrFunc(task),"PLME_SET_TRX_STATE_confirm");
03301             taskP.mlme_reset_request_SetDefaultPIB = SetDefaultPIB;
03302             plme_set_trx_state_request(p_TRX_OFF);
03303             break;
03304         case 1:
03305             taskP.taskStatus(task) = false;
03306             init(true);
03307             if (SetDefaultPIB)
03308                 mpib = MPIB;
03309             if (status == p_TRX_OFF)
03310                 sscs->MLME_RESET_confirm(m_SUCCESS);
03311             else
03312                 sscs->MLME_RESET_confirm(m_DISABLE_TRX_FAILURE);
03313             break;
03314         default:
03315             break;
03316     }
03317 }
03318 
03319 void Mac802_15_4::mlme_rx_enable_request(bool DeferPermit,UINT_32 RxOnTime,UINT_32 RxOnDuration,bool frUpper,PHYenum status)
03320 {
03321     UINT_8 step,task;
03322     UINT_32 t_CAP;
03323     double cutTime,tmpf;
03324 
03325     task = TP_mlme_rx_enable_request;
03326     if (frUpper) checkTaskOverflow(task);
03327 
03328     step = taskP.taskStep(task);
03329 
03330     if (step == 0)
03331     if (RxOnDuration == 0)
03332     {
03333         sscs->MLME_RX_ENABLE_confirm(m_SUCCESS);
03334         plme_set_trx_state_request(p_TRX_OFF);
03335         return;
03336     }
03337     
03338     if (macBeaconOrder2 != 15)      //beacon enabled
03339     {
03340         switch(step)
03341         {
03342             case 0:
03343                 taskP.mlme_rx_enable_request_RxOnTime = RxOnTime;
03344                 taskP.mlme_rx_enable_request_RxOnDuration = RxOnDuration;
03345                 if (RxOnTime + RxOnDuration >= sfSpec2.BI)
03346                 {
03347                     sscs->MLME_RX_ENABLE_confirm(m_INVALID_PARAMETER);
03348                     return;
03349                 }
03350                 t_CAP = (sfSpec2.FinCAP + 1) * sfSpec2.sd;
03351 
03352                 /* Linux floating number compatibility
03353                 */
03354                 tmpf = CURRENT_TIME * phy->getRate('s');
03355 
03356                 if ((RxOnTime - aTurnaroundTime) > t_CAP)
03357                 {
03358                     sscs->MLME_RX_ENABLE_confirm(m_OUT_OF_CAP);
03359                     return;
03360                 }
03361                 /* Linux floating number compatibility
03362                 else if ((CURRENT_TIME * phy->getRate('s') - macBcnRxTime) < (RxOnTime - aTurnaroundTime))
03363                 */
03364                 else if ((tmpf - macBcnRxTime) < (RxOnTime - aTurnaroundTime))
03365                 {
03366                     //can proceed in current superframe
03367                     taskP.taskStatus(task) = true;
03368                     taskP.taskStep(task)++;
03369                     //just fall through case 1
03370                 }
03371                 else if (DeferPermit)
03372                 {
03373                     //need to defer until next superframe
03374                     taskP.taskStatus(task) = true;
03375                     taskP.taskStep(task)++;
03376                     strcpy(taskP.taskFrFunc(task),"recvBeacon");
03377                     break;
03378                 }
03379                 else
03380                 {
03381                     sscs->MLME_RX_ENABLE_confirm(m_OUT_OF_CAP);
03382                     return;
03383                 }
03384             case 1:
03385                 taskP.taskStep(task)++;
03386                 strcpy(taskP.taskFrFunc(task),"rxEnableHandler");
03387                 /* Linux floating number compatibility
03388                 rxEnableT->start(RxOnTime / phy->getRate('s') - (CURRENT_TIME - macBcnRxTime / phy->getRate('s')));
03389                 */
03390                 {
03391                 double tmpf2;
03392                 tmpf = macBcnRxTime / phy->getRate('s');
03393                 tmpf = CURRENT_TIME - tmpf;
03394                 tmpf2 = RxOnTime / phy->getRate('s');
03395                 tmpf = tmpf2 - tmpf;
03396                 rxEnableT->start(tmpf);
03397                 }
03398                 break;
03399             case 2:
03400                 taskP.taskStep(task)++;
03401                 strcpy(taskP.taskFrFunc(task),"PLME_SET_TRX_STATE_confirm");
03402                 taskP.mlme_rx_enable_request_currentTime = CURRENT_TIME;
03403                 plme_set_trx_state_request(p_RX_ON);
03404                 break;
03405             case 3:
03406                 taskP.taskStatus(task) = false; 
03407                 strcpy(taskP.taskFrFunc(task),"rxEnableHandler");
03408                 taskP.taskStep(task)++;
03409                 if (status == p_TX_ON)
03410                     sscs->MLME_RX_ENABLE_confirm(m_TX_ACTIVE);
03411                 else
03412                     sscs->MLME_RX_ENABLE_confirm(m_SUCCESS);
03413                 //turn off the receiver before the CFP so as not to disturb it, and we see no reason to turn it on again after the CFP (i.e., inactive port of the superframe)
03414                 t_CAP = (sfSpec2.FinCAP + 1) * sfSpec2.sd;
03415                 cutTime = (RxOnTime + RxOnDuration - t_CAP) / phy->getRate('s');
03416 
03417                 /* Linux floating number compatibility
03418                 rxEnableT->start(RxOnDuration / phy->getRate('s') - (CURRENT_TIME - taskP.mlme_rx_enable_request_currentTime) - cutTime);
03419                 */
03420                 {
03421                 tmpf = RxOnDuration / phy->getRate('s');
03422                 tmpf -= CURRENT_TIME;
03423                 tmpf += taskP.mlme_rx_enable_request_currentTime;
03424                 tmpf -= cutTime;
03425                 rxEnableT->start(tmpf);
03426                 }
03427                 break;
03428             case 4:
03429                 strcpy(taskP.taskFrFunc(task),"");
03430                 plme_set_trx_state_request(p_TRX_OFF);
03431                 break;
03432             default:
03433                 break;
03434         }
03435     }
03436     else
03437     {
03438         switch(step)
03439         {
03440             case 0:
03441                 taskP.taskStatus(task) = true;
03442                 strcpy(taskP.taskFrFunc(task),"PLME_SET_TRX_STATE_confirm");
03443                 taskP.taskStep(task)++;
03444                 taskP.mlme_rx_enable_request_RxOnDuration = RxOnDuration;
03445                 taskP.mlme_rx_enable_request_currentTime = CURRENT_TIME;
03446                 plme_set_trx_state_request(p_RX_ON);
03447                 break;
03448             case 1:
03449                 taskP.taskStatus(task) = false; 
03450                 strcpy(taskP.taskFrFunc(task),"rxEnableHandler");
03451                 taskP.taskStep(task)++;
03452                 if (status == p_TX_ON)
03453                     sscs->MLME_RX_ENABLE_confirm(m_TX_ACTIVE);
03454                 else
03455                     sscs->MLME_RX_ENABLE_confirm(m_SUCCESS);
03456                 /* Linux floating number compatibility
03457                 rxEnableT->start(RxOnDuration / phy->getRate('s') - (CURRENT_TIME - taskP.mlme_rx_enable_request_currentTime));
03458                 */
03459                 {
03460                 tmpf = RxOnDuration / phy->getRate('s');
03461                 tmpf -= CURRENT_TIME;
03462                 tmpf += taskP.mlme_rx_enable_request_currentTime;
03463                 rxEnableT->start(tmpf);
03464                 }
03465                 break;
03466             case 2:
03467                 strcpy(taskP.taskFrFunc(task),"");
03468                 plme_set_trx_state_request(p_TRX_OFF);
03469                 break;
03470             default:
03471                 break;
03472         }
03473     }
03474 }
03475 
03476 void Mac802_15_4::mlme_scan_request(UINT_8 ScanType,UINT_32 ScanChannels,UINT_8 ScanDuration,bool frUpper,PHYenum status)
03477 {
03478     UINT_32 t_chanPos;
03479     UINT_8 step,task;
03480     FrameCtrl frmCtrl;
03481     hdr_lrwpan* wph;
03482     int i;
03483 
03484     task = TP_mlme_scan_request;
03485     if (frUpper) checkTaskOverflow(task);
03486 
03487     step = taskP.taskStep(task);
03488 
03489     if (step == 0)
03490     {
03491         if ((ScanType > 3)
03492         ||((ScanType != 3)&&(ScanDuration > 14)))
03493         {
03494             sscs->MLME_SCAN_confirm(m_INVALID_PARAMETER,ScanType,ScanChannels,0,NULL,NULL);
03495             return;
03496         }
03497         //disable the beacon
03498         taskP.mlme_scan_request_orig_macBeaconOrder = mpib.macBeaconOrder;
03499         taskP.mlme_scan_request_orig_macBeaconOrder2 = macBeaconOrder2;
03500         taskP.mlme_scan_request_orig_macBeaconOrder3 = macBeaconOrder3;
03501         mpib.macBeaconOrder = 15;
03502         macBeaconOrder2 = 15;
03503         macBeaconOrder3 = 15;
03504         //stop the CSMA-CA if it is running
03505         if (backoffStatus == 99)
03506         {
03507             backoffStatus = 0;
03508             csmaca->cancel();
03509         }
03510         taskP.mlme_scan_request_ScanType = ScanType;
03511     }
03512 
03513     if (ScanType == 0x00)       //ED scan
03514     switch (step)
03515     {
03516         case 0:
03517             phy->PLME_GET_request(phyChannelsSupported);    //value will be returned in tmp_ppib
03518             taskP.mlme_scan_request_ScanChannels = ScanChannels;
03519             if ((taskP.mlme_scan_request_ScanChannels & tmp_ppib.phyChannelsSupported) == 0)
03520             {
03521                 //restore the beacon order
03522                 mpib.macBeaconOrder = taskP.mlme_scan_request_orig_macBeaconOrder;
03523                 macBeaconOrder2 = taskP.mlme_scan_request_orig_macBeaconOrder2;
03524                 macBeaconOrder3 = taskP.mlme_scan_request_orig_macBeaconOrder3;
03525                 sscs->MLME_SCAN_confirm(m_SUCCESS,ScanType,ScanChannels,0,NULL,NULL);   //SUCCESS or INVALID_PARAMETER?
03526                 csmacaResume();
03527                 return;
03528             }
03529             taskP.taskStatus(task) = true;
03530             taskP.taskStep(task)++;
03531             strcpy(taskP.taskFrFunc(task),"PLME_SET_confirm");
03532             taskP.mlme_scan_request_CurrentChannel = 0;
03533             taskP.mlme_scan_request_ListNum = 0;
03534             t_chanPos = (1<<taskP.mlme_scan_request_CurrentChannel);
03535             while((t_chanPos & taskP.mlme_scan_request_ScanChannels) == 0
03536             ||(t_chanPos & tmp_ppib.phyChannelsSupported) == 0)
03537             {
03538                 taskP.mlme_scan_request_CurrentChannel++;
03539                 t_chanPos = (1<<taskP.mlme_scan_request_CurrentChannel);
03540             }
03541             tmp_ppib.phyCurrentChannel = taskP.mlme_scan_request_CurrentChannel;
03542             phy->PLME_SET_request(phyCurrentChannel,&tmp_ppib);
03543             break;
03544         case 1:
03545             taskP.taskStep(task)++;
03546             strcpy(taskP.taskFrFunc(task),"PLME_SET_TRX_STATE_confirm");
03547             plme_set_trx_state_request(p_RX_ON);
03548             break;
03549         case 2:
03550             if (status == p_RX_ON)
03551             {
03552                 taskP.taskStep(task)++;
03553                 strcpy(taskP.taskFrFunc(task),"PLME_ED_confirm");
03554                 phy->PLME_ED_request();
03555                 break;
03556             }
03557             //else  //fall through case 4
03558         case 3:
03559             if (step == 3)  //note that case 2 needs to fall through case 4 via here
03560             {
03561                 if (status == p_SUCCESS)
03562                 {
03563                     t_chanPos = (1<<taskP.mlme_scan_request_CurrentChannel);
03564                     taskP.mlme_scan_request_ScanChannels &= (t_chanPos^0xffffffff);
03565                     taskP.mlme_scan_request_EnergyDetectList[taskP.mlme_scan_request_ListNum] = energyLevel;
03566                     taskP.mlme_scan_request_ListNum++;
03567                 }
03568             }
03569             //fall through
03570         case 4:
03571             if ((taskP.mlme_scan_request_ScanChannels & tmp_ppib.phyChannelsSupported) == 0)
03572             {
03573                 //restore the beacon order
03574                 mpib.macBeaconOrder = taskP.mlme_scan_request_orig_macBeaconOrder;
03575                 macBeaconOrder2 = taskP.mlme_scan_request_orig_macBeaconOrder2;
03576                 macBeaconOrder3 = taskP.mlme_scan_request_orig_macBeaconOrder3;
03577                 taskP.taskStatus(task) = false;
03578                 sscs->MLME_SCAN_confirm(m_SUCCESS,ScanType,taskP.mlme_scan_request_ScanChannels,taskP.mlme_scan_request_ListNum,taskP.mlme_scan_request_EnergyDetectList,NULL);
03579                 csmacaResume();
03580                 return;
03581             }
03582             taskP.taskStep(task) = 1;   //important
03583             strcpy(taskP.taskFrFunc(task),"PLME_SET_confirm");
03584             taskP.mlme_scan_request_CurrentChannel++;
03585             t_chanPos = (1<<taskP.mlme_scan_request_CurrentChannel);
03586             while((t_chanPos & taskP.mlme_scan_request_ScanChannels) == 0
03587             ||(t_chanPos & tmp_ppib.phyChannelsSupported) == 0)
03588             {
03589                 taskP.mlme_scan_request_CurrentChannel++;
03590                 t_chanPos = (1<<taskP.mlme_scan_request_CurrentChannel);
03591             }
03592             tmp_ppib.phyCurrentChannel = taskP.mlme_scan_request_CurrentChannel;
03593             phy->PLME_SET_request(phyCurrentChannel,&tmp_ppib);
03594             break;
03595         default:
03596             break;
03597     }
03598 
03599     else if ((ScanType == 0x01) //active scan
03600     ||   (ScanType == 0x02))    //passive scan
03601     switch (step)
03602     {
03603         case 0:
03604             phy->PLME_GET_request(phyChannelsSupported);    //value will be returned in tmp_ppib
03605             taskP.mlme_scan_request_ScanChannels = ScanChannels;
03606             if ((taskP.mlme_scan_request_ScanChannels & tmp_ppib.phyChannelsSupported) == 0)
03607             {
03608                 mpib.macBeaconOrder = taskP.mlme_scan_request_orig_macBeaconOrder;
03609                 macBeaconOrder2 = taskP.mlme_scan_request_orig_macBeaconOrder2;
03610                 macBeaconOrder3 = taskP.mlme_scan_request_orig_macBeaconOrder3;
03611                 sscs->MLME_SCAN_confirm(m_SUCCESS,ScanType,ScanChannels,0,NULL,NULL);   //SUCCESS or INVALID_PARAMETER?
03612                 csmacaResume();
03613                 return;
03614             }
03615             taskP.taskStatus(task) = true;
03616             taskP.taskStep(task)++;
03617             strcpy(taskP.taskFrFunc(task),"PLME_SET_confirm");
03618             taskP.mlme_scan_request_orig_macPANId = mpib.macPANId;
03619             mpib.macPANId = 0xffff;
03620             taskP.mlme_scan_request_ScanDuration = ScanDuration;
03621             taskP.mlme_scan_request_CurrentChannel = 0;
03622             taskP.mlme_scan_request_ListNum = 0;
03623             t_chanPos = (1<<taskP.mlme_scan_request_CurrentChannel);
03624             while((t_chanPos & taskP.mlme_scan_request_ScanChannels) == 0
03625             ||(t_chanPos & tmp_ppib.phyChannelsSupported) == 0)
03626             {
03627                 taskP.mlme_scan_request_CurrentChannel++;
03628                 t_chanPos = (1<<taskP.mlme_scan_request_CurrentChannel);
03629             }
03630             tmp_ppib.phyCurrentChannel = taskP.mlme_scan_request_CurrentChannel;
03631             phy->PLME_SET_request(phyCurrentChannel,&tmp_ppib);
03632             break;
03633         case 1:
03634             if (Mac802_15_4::verbose)
03635                 fprintf(stdout,"[%f](node %d) scanning channel %d\n",CURRENT_TIME,index_,taskP.mlme_scan_request_CurrentChannel);
03636             if (ScanType == 0x01)       //active scan
03637             {
03638                 taskP.taskStep(task)++;
03639                 strcpy(taskP.taskFrFunc(task),"csmacaCallBack");
03640                 //--- send a beacon request command ---
03641 #ifdef DEBUG802_15_4
03642                 fprintf(stdout,"[%s::%s][%f](node %d) before alloc txBcnCmd2:\n\t\ttxBeacon\t= %ld\n\t\ttxAck   \t= %ld\n\t\ttxBcnCmd\t= %ld\n\t\ttxBcnCmd2\t= %ld\n\t\ttxData  \t= %ld\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,txBeacon,txAck,txBcnCmd,txBcnCmd2,txData);
03643 #endif
03644                 assert(!txBcnCmd2);
03645                 txBcnCmd2 = Packet::alloc();
03646                 assert(txBcnCmd2);
03647                 wph = HDR_LRWPAN(txBcnCmd2);
03648                 constructCommandHeader(txBcnCmd2,&frmCtrl,0x07,defFrmCtrl_AddrMode16,0xffff,0xffff,defFrmCtrl_AddrModeNone,0,0,false,false,false);
03649                 constructMPDU(1,txBcnCmd2,frmCtrl.FrmCtrl,mpib.macDSN++,wph->MHR_DstAddrInfo,wph->MHR_SrcAddrInfo,0,0x07,0);
03650                 csmacaBegin('C');
03651                 //------------------------------------
03652             }
03653             else
03654             {
03655                 taskP.taskStep(task) = 4;   //skip the steps only for active scan
03656                 strcpy(taskP.taskFrFunc(task),"PLME_SET_TRX_STATE_confirm");
03657                 plme_set_trx_state_request(p_RX_ON);
03658             }
03659             break;
03660         case 2:
03661             if (status == p_IDLE)
03662             {
03663                 taskP.taskStep(task)++;
03664                 strcpy(taskP.taskFrFunc(task),"PD_DATA_confirm");
03665                 plme_set_trx_state_request(p_TX_ON);
03666                 break;
03667             }
03668             else
03669             {
03670                 freePkt(txBcnCmd2); //actually we can keep <txBcnCmd2> for next channel
03671                 txBcnCmd2 = 0;
03672                 //fall through case 7
03673             }
03674         case 3:
03675             if (step == 3)
03676             {
03677                 taskP.taskStep(task)++;
03678                 strcpy(taskP.taskFrFunc(task),"PLME_SET_TRX_STATE_confirm");
03679                 taskSuccess('C',false);
03680                 plme_set_trx_state_request(p_RX_ON);
03681                 break;
03682             }
03683         case 4:
03684             if (step == 4)
03685             {
03686                 if (status == p_RX_ON)
03687                 {
03688                     taskP.taskStep(task)++;
03689                     strcpy(taskP.taskFrFunc(task),"recvBeacon");
03690                     //schedule for next channel
03691                     scanT->start((aBaseSuperframeDuration * ((1 << taskP.mlme_scan_request_ScanDuration) + 1)) / phy->getRate('s'));
03692                     break;
03693                 }
03694                 //else  //fall through case 7
03695             }
03696         case 5:
03697             if (step == 5)
03698             {
03699                 //beacon received
03700                 //record the PAN descriptor if it is a new one
03701                 assert(rxBeacon);
03702                 wph = HDR_LRWPAN(rxBeacon);
03703                 frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
03704                 frmCtrl.parse();
03705                 for (i=0;i<taskP.mlme_scan_request_ListNum;i++)
03706                 if ((taskP.mlme_scan_request_PANDescriptorList[i].LogicalChannel == taskP.mlme_scan_request_CurrentChannel)
03707                 && (taskP.mlme_scan_request_PANDescriptorList[i].CoordAddrMode == frmCtrl.srcAddrMode)
03708                 && (taskP.mlme_scan_request_PANDescriptorList[i].CoordPANId == wph->MHR_SrcAddrInfo.panID)      //but (page 146, line 4-5) implies not checking PAN ID
03709                 && (((frmCtrl.srcAddrMode == defFrmCtrl_AddrMode16)&&(taskP.mlme_scan_request_PANDescriptorList[i].CoordAddress_16 == (wph->MHR_SrcAddrInfo.addr_16))
03710                 ||((frmCtrl.srcAddrMode == defFrmCtrl_AddrMode64)&&(taskP.mlme_scan_request_PANDescriptorList[i].CoordAddress_64 == wph->MHR_SrcAddrInfo.addr_64)))))
03711                     break;
03712                 if (i >= taskP.mlme_scan_request_ListNum)   //unique beacon
03713                 {
03714                     taskP.mlme_scan_request_PANDescriptorList[taskP.mlme_scan_request_ListNum] = panDes2;
03715                     taskP.mlme_scan_request_ListNum++;
03716                     if (taskP.mlme_scan_request_ListNum >= 27)
03717                     {
03718                         //stop the timer
03719                         scanT->stop();
03720                         //fall through case 7
03721                     }
03722                     else
03723                         break;
03724                 }
03725                 else
03726                     break;
03727             }
03728         case 6:
03729             if (step == 6)
03730             {
03731                 t_chanPos = (1<<taskP.mlme_scan_request_CurrentChannel);
03732                 taskP.mlme_scan_request_ScanChannels &= (t_chanPos^0xffffffff);
03733                 //fall through case 7
03734             }
03735         case 7:
03736             if (((taskP.mlme_scan_request_ScanChannels & tmp_ppib.phyChannelsSupported) == 0)
03737                ||(taskP.mlme_scan_request_ListNum >= 27))
03738             {
03739                 mpib.macPANId = taskP.mlme_scan_request_orig_macPANId;
03740                 mpib.macBeaconOrder = taskP.mlme_scan_request_orig_macBeaconOrder;
03741                 macBeaconOrder2 = taskP.mlme_scan_request_orig_macBeaconOrder2;
03742                 macBeaconOrder3 = taskP.mlme_scan_request_orig_macBeaconOrder3;
03743                 taskP.taskStatus(task) = false;
03744                 sscs->MLME_SCAN_confirm(m_SUCCESS,ScanType,taskP.mlme_scan_request_ScanChannels,taskP.mlme_scan_request_ListNum,NULL,taskP.mlme_scan_request_PANDescriptorList);
03745                 csmacaResume();
03746                 return;
03747             }
03748             taskP.taskStep(task) = 1;   //important
03749             strcpy(taskP.taskFrFunc(task),"PLME_SET_confirm");
03750             taskP.mlme_scan_request_CurrentChannel++;
03751             t_chanPos = (1<<taskP.mlme_scan_request_CurrentChannel);
03752             while((t_chanPos & taskP.mlme_scan_request_ScanChannels) == 0
03753             ||(t_chanPos & tmp_ppib.phyChannelsSupported) == 0)
03754             {
03755                 taskP.mlme_scan_request_CurrentChannel++;
03756                 t_chanPos = (1<<taskP.mlme_scan_request_CurrentChannel);
03757             }
03758             tmp_ppib.phyCurrentChannel = taskP.mlme_scan_request_CurrentChannel;
03759             phy->PLME_SET_request(phyCurrentChannel,&tmp_ppib);
03760             break;
03761         default:
03762             break;
03763     }
03764 
03765     else //if (ScanType == 0x03)    //orphan scan
03766     switch (step)
03767     {
03768         case 0:
03769             phy->PLME_GET_request(phyChannelsSupported);    //value will be returned in tmp_ppib
03770             taskP.mlme_scan_request_ScanChannels = ScanChannels;
03771             if ((taskP.mlme_scan_request_ScanChannels & tmp_ppib.phyChannelsSupported) == 0)
03772             {
03773                 mpib.macBeaconOrder = taskP.mlme_scan_request_orig_macBeaconOrder;
03774                 //macBeaconOrder2 = taskP.mlme_scan_request_orig_macBeaconOrder2;
03775                 macBeaconOrder2 = 15;
03776                 macBeaconOrder3 = taskP.mlme_scan_request_orig_macBeaconOrder3;
03777                 sscs->MLME_SCAN_confirm(m_INVALID_PARAMETER,ScanType,ScanChannels,0,NULL,NULL);
03778                 csmacaResume();
03779                 return;
03780             }
03781             taskP.taskStatus(task) = true;
03782             taskP.taskStep(task)++;
03783             strcpy(taskP.taskFrFunc(task),"PLME_SET_confirm");
03784             taskP.mlme_scan_request_CurrentChannel = 0;
03785             t_chanPos = (1<<taskP.mlme_scan_request_CurrentChannel);
03786             while((t_chanPos & taskP.mlme_scan_request_ScanChannels) == 0
03787             ||(t_chanPos & tmp_ppib.phyChannelsSupported) == 0)
03788             {
03789                 taskP.mlme_scan_request_CurrentChannel++;
03790                 t_chanPos = (1<<taskP.mlme_scan_request_CurrentChannel);
03791             }
03792             tmp_ppib.phyCurrentChannel = taskP.mlme_scan_request_CurrentChannel;
03793             phy->PLME_SET_request(phyCurrentChannel,&tmp_ppib);
03794             break;
03795         case 1:
03796             if (Mac802_15_4::verbose)
03797                 fprintf(stdout,"[%f](node %d) orphan-scanning channel %d\n",CURRENT_TIME,index_,taskP.mlme_scan_request_CurrentChannel);
03798             taskP.taskStep(task)++;
03799             strcpy(taskP.taskFrFunc(task),"csmacaCallBack");
03800             //--- send an orphan notification command ---
03801 #ifdef DEBUG802_15_4
03802             fprintf(stdout,"[%s::%s][%f](node %d) before alloc txBcnCmd2:\n\t\ttxBeacon\t= %ld\n\t\ttxAck   \t= %ld\n\t\ttxBcnCmd\t= %ld\n\t\ttxBcnCmd2\t= %ld\n\t\ttxData  \t= %ld\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,txBeacon,txAck,txBcnCmd,txBcnCmd2,txData);
03803 #endif
03804             assert(!txBcnCmd2);
03805             txBcnCmd2 = Packet::alloc();
03806             assert(txBcnCmd2);
03807             wph = HDR_LRWPAN(txBcnCmd2);
03808             constructCommandHeader(txBcnCmd2,&frmCtrl,0x06,defFrmCtrl_AddrMode64,mpib.macPANId,mpib.macCoordExtendedAddress,defFrmCtrl_AddrMode64,mpib.macPANId,aExtendedAddress,false,false,false);
03809             constructMPDU(1,txBcnCmd2,frmCtrl.FrmCtrl,mpib.macDSN++,wph->MHR_DstAddrInfo,wph->MHR_SrcAddrInfo,0,0x06,0);
03810             csmacaBegin('C');
03811             //------------------------------------
03812             break;
03813         case 2:
03814             if (status == p_IDLE)
03815             {
03816                 taskP.taskStep(task)++;
03817                 strcpy(taskP.taskFrFunc(task),"PD_DATA_confirm");
03818                 plme_set_trx_state_request(p_TX_ON);
03819                 break;
03820             }
03821             else
03822             {
03823                 freePkt(txBcnCmd2);
03824                 txBcnCmd2 = 0;
03825                 //fall through case 6
03826             }
03827         case 3:
03828             if (step == 3)
03829             {
03830                 taskP.taskStep(task)++;
03831                 strcpy(taskP.taskFrFunc(task),"PLME_SET_TRX_STATE_confirm");
03832                 taskSuccess('C',false);
03833                 plme_set_trx_state_request(p_RX_ON);
03834                 break;
03835             }
03836         case 4:
03837             if (step == 4)
03838             {
03839                 if (status == p_RX_ON)
03840                 {
03841                     taskP.taskStep(task)++;
03842                     strcpy(taskP.taskFrFunc(task),"IFSHandler");
03843                     scanT->start(aResponseWaitTime / phy->getRate('s'));
03844                     break;
03845                 }
03846                 //else  //fall through case 6
03847             }
03848         case 5:
03849             if (step == 5)
03850             {
03851                 if (status == p_SUCCESS)    //coordinator realignment command received
03852                 {
03853                     scanT->stop();
03854                     mpib.macBeaconOrder = taskP.mlme_scan_request_orig_macBeaconOrder;
03855                     macBeaconOrder2 = taskP.mlme_scan_request_orig_macBeaconOrder2;
03856                     macBeaconOrder3 = taskP.mlme_scan_request_orig_macBeaconOrder3;
03857                     taskP.taskStatus(task) = false;
03858                     changeNodeColor(CURRENT_TIME,(mpib.macAssociationPermit)?Nam802_15_4::def_Coor_clr:Nam802_15_4::def_Dev_clr);
03859                     t_chanPos = (1<<taskP.mlme_scan_request_CurrentChannel);
03860                     taskP.mlme_scan_request_ScanChannels &= (t_chanPos^0xffffffff);
03861                     sscs->MLME_SCAN_confirm(m_SUCCESS,ScanType,taskP.mlme_scan_request_ScanChannels,0,NULL,NULL);
03862                     csmacaResume();
03863                     break;
03864                 }
03865                 else    //time out
03866                 {
03867                     t_chanPos = (1<<taskP.mlme_scan_request_CurrentChannel);
03868                     taskP.mlme_scan_request_ScanChannels &= (t_chanPos^0xffffffff);
03869                     //fall through case 6
03870                 }
03871             }
03872         case 6:
03873             if ((taskP.mlme_scan_request_ScanChannels & tmp_ppib.phyChannelsSupported) == 0)
03874             {
03875                 mpib.macBeaconOrder = taskP.mlme_scan_request_orig_macBeaconOrder;
03876                 //macBeaconOrder2 = taskP.mlme_scan_request_orig_macBeaconOrder2;
03877                 macBeaconOrder2 = 15;
03878                 macBeaconOrder3 = taskP.mlme_scan_request_orig_macBeaconOrder3;
03879                 taskP.taskStatus(task) = false;
03880                 sscs->MLME_SCAN_confirm(m_NO_BEACON,ScanType,taskP.mlme_scan_request_ScanChannels,0,NULL,NULL);
03881                 csmacaResume();
03882                 return;
03883             }
03884             taskP.taskStep(task) = 1;   //important
03885             strcpy(taskP.taskFrFunc(task),"PLME_SET_confirm");
03886             taskP.mlme_scan_request_CurrentChannel++;
03887             t_chanPos = (1<<taskP.mlme_scan_request_CurrentChannel);
03888             while((t_chanPos & taskP.mlme_scan_request_ScanChannels) == 0
03889             ||(t_chanPos & tmp_ppib.phyChannelsSupported) == 0)
03890             {
03891                 taskP.mlme_scan_request_CurrentChannel++;
03892                 t_chanPos = (1<<taskP.mlme_scan_request_CurrentChannel);
03893             }
03894             tmp_ppib.phyCurrentChannel = taskP.mlme_scan_request_CurrentChannel;
03895             phy->PLME_SET_request(phyCurrentChannel,&tmp_ppib);
03896             break;
03897         default:
03898             break;
03899     }
03900 }
03901 
03902 void Mac802_15_4::mlme_start_request(UINT_16 PANId,UINT_8 LogicalChannel,UINT_8 BeaconOrder,
03903                      UINT_8 SuperframeOrder,bool PANCoordinator,bool BatteryLifeExtension,
03904                      bool CoordRealignment,bool SecurityEnable,
03905                      bool frUpper,PHYenum status)
03906 {
03907     FrameCtrl frmCtrl;
03908     hdr_lrwpan* wph;
03909     UINT_8 origBeaconOrder;
03910     UINT_8 step,task;
03911 
03912     task = TP_mlme_start_request;
03913     if (frUpper) checkTaskOverflow(task);
03914 
03915     step = taskP.taskStep(task);
03916     switch (step)
03917     {
03918         case 0:
03919             if (mpib.macShortAddress == 0xffff)
03920             {
03921                 sscs->MLME_START_confirm(m_NO_SHORT_ADDRESS);
03922                 return;
03923             }
03924             else if ((!phy->channelSupported(LogicalChannel))
03925             || (BeaconOrder > 15)
03926             || ((SuperframeOrder > BeaconOrder)&&(SuperframeOrder != 15)))
03927             {
03928                 sscs->MLME_START_confirm(m_INVALID_PARAMETER);
03929                 return;
03930             }
03931             else if (!capability.FFD)
03932             {
03933                 sscs->MLME_START_confirm(m_UNDEFINED);
03934                 return;
03935             }
03936             taskP.taskStatus(task) = true;
03937             if (CoordRealignment)       //send a realignment command before changing configuration that affects the command
03938             {
03939                 taskP.taskStep(task)++;
03940                 strcpy(taskP.taskFrFunc(task),"csmacaCallBack");
03941                 //broadcast a realignment command
03942 #ifdef DEBUG802_15_4
03943                 fprintf(stdout,"[%s::%s][%f](node %d) before alloc txBcnCmd2:\n\t\ttxBeacon\t= %ld\n\t\ttxAck   \t= %ld\n\t\ttxBcnCmd\t= %ld\n\t\ttxBcnCmd2\t= %ld\n\t\ttxData  \t= %ld\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,txBeacon,txAck,txBcnCmd,txBcnCmd2,txData);
03944 #endif
03945                 assert(!txBcnCmd2);
03946                 txBcnCmd2 = Packet::alloc();
03947                 assert(txBcnCmd2);
03948                 wph = HDR_LRWPAN(txBcnCmd2);
03949                 constructCommandHeader(txBcnCmd2,&frmCtrl,0x08,defFrmCtrl_AddrMode16,0xffff,0xffff,defFrmCtrl_AddrMode64,mpib.macPANId,aExtendedAddress,false,false,false);
03950                 //--- payload (refer to Figure 56) ---
03951                 wph->MSDU_PayloadLen = 7;
03952                 *((UINT_16 *)wph->MSDU_Payload) = PANId;            //PAN identifier
03953                 *((UINT_16 *)(wph->MSDU_Payload + 2)) = mpib.macShortAddress;   //Coor. short address
03954                 wph->MSDU_Payload[4] = LogicalChannel;              //Logical channel
03955                 *((UINT_16 *)(wph->MSDU_Payload + 5)) = 0xffff;         //short address; be the assigned address if directed to an orphaned device
03956                 constructMPDU(8,txBcnCmd2,frmCtrl.FrmCtrl,mpib.macDSN++,wph->MHR_DstAddrInfo,wph->MHR_SrcAddrInfo,0,0x08,0);
03957                 csmacaBegin('C');
03958                 //------------------------------------
03959                 //change the configuration and begin to transmit beacons after the transmission of the realignment command
03960                 taskP.mlme_start_request_BeaconOrder = BeaconOrder;
03961                 taskP.mlme_start_request_SuperframeOrder = SuperframeOrder;
03962                 taskP.mlme_start_request_BatteryLifeExtension = BatteryLifeExtension;
03963                 taskP.mlme_start_request_SecurityEnable = SecurityEnable;
03964                 taskP.mlme_start_request_PANCoordinator = PANCoordinator;
03965                 taskP.mlme_start_request_PANId = PANId;
03966                 taskP.mlme_start_request_LogicalChannel = LogicalChannel;
03967                 break;
03968             }
03969             else
03970             {
03971                 taskP.taskStep(task) = 2;
03972                 step = 2;
03973                 //fall through case 2
03974             }
03975         case 1:
03976             if (step == 1)
03977             {
03978                 if (status == p_IDLE)
03979                 {
03980                     taskP.taskStep(task)++;
03981                     strcpy(taskP.taskFrFunc(task),"PD_DATA_confirm");
03982                     plme_set_trx_state_request(p_TX_ON);
03983                     break;
03984                 }
03985                 else
03986                 {
03987                     freePkt(txBcnCmd2); //actually we can keep <txBcnCmd2> for next channel
03988                     txBcnCmd2 = 0;
03989                     //fall through case case 2 -- ignore the failure and continue to transmit beacons
03990                     taskP.taskStep(task) = 2;
03991                 }
03992             }
03993         case 2:
03994             taskP.taskStep(task)++;
03995             strcpy(taskP.taskFrFunc(task),"PD_DATA_confirm");   //for beacon
03996             resetTRX();
03997             if (CoordRealignment)
03998                 taskSuccess('C',false);
03999             //change the configuration
04000             origBeaconOrder = mpib.macBeaconOrder;
04001             mpib.macBeaconOrder = BeaconOrder;
04002             if (BeaconOrder == 15)
04003                 mpib.macSuperframeOrder = 15;
04004             else
04005                 mpib.macSuperframeOrder = SuperframeOrder;
04006             mpib.macBattLifeExt = BatteryLifeExtension;
04007             secuBeacon = SecurityEnable;
04008             if (isPANCoor != PANCoordinator)
04009                 changeNodeColor(CURRENT_TIME,PANCoordinator?Nam802_15_4::def_PANCoor_clr:Nam802_15_4::def_Coor_clr);
04010             isPANCoor = PANCoordinator;
04011             if (PANCoordinator)
04012             {
04013                 mpib.macPANId = PANId;
04014                 mpib.macCoordExtendedAddress = aExtendedAddress;    //I'm the coordinator of myself
04015                 tmp_ppib.phyCurrentChannel = LogicalChannel;
04016                 phy->PLME_SET_request(phyCurrentChannel,&tmp_ppib);
04017             }
04018             if (origBeaconOrder == BeaconOrder)
04019             {
04020                 taskP.taskStatus(task) = false;
04021                 sscs->MLME_START_confirm(m_SUCCESS);
04022                 csmacaResume();
04023             }
04024             else if ((origBeaconOrder == 15)&&(BeaconOrder < 15))
04025             {
04026                 //transmit beacon immediately
04027                 if (bcnTxT->busy())     //the timer may still be looping there
04028                     bcnTxT->stop();
04029                 bcnTxT->start(true,true,0.0);
04030             }
04031             else if ((origBeaconOrder < 15)&&(BeaconOrder == 15))
04032                 oneMoreBeacon = true;
04033             break;
04034         case 3:
04035             taskP.taskStatus(task) = false;
04036             sscs->MLME_START_confirm(m_SUCCESS);
04037             taskSuccess('b');
04038             break;
04039         default:
04040             break;
04041     }
04042 }
04043 
04044 void Mac802_15_4::mlme_sync_request(UINT_8 LogicalChannel, bool TrackBeacon,bool frUpper,PHYenum status)
04045 {
04046     UINT_8 step,task,BO;
04047 
04048     task = TP_mlme_sync_request;
04049     if (frUpper)
04050     {
04051         //checkTaskOverflow(task);  //overlapping allowed
04052         //stop the beacon receiving timer if it is running
04053         if (bcnRxT->busy())
04054             bcnRxT->stop();
04055         taskP.taskStep(task) = 0;
04056         (taskP.taskFrFunc(task))[0] = 0;
04057     }
04058 
04059     step = taskP.taskStep(task);
04060     switch(step)
04061     {
04062         case 0:
04063             //no validation check required in the draft, but it's better to check it
04064             if ((!phy->channelSupported(LogicalChannel))    //channel not supported
04065              || (mpib.macPANId == 0xffff)           //broadcast PAN ID
04066              //|| (macBeaconOrder2 == 15)           //non-beacon mode or <macBeaconOrder2> not yet populated
04067              )
04068             {
04069                 sscs->MLME_SYNC_LOSS_indication(m_UNDEFINED);
04070                 return;
04071             }
04072             taskP.taskStatus(task) = true;
04073             taskP.taskStep(task)++;
04074             strcpy(taskP.taskFrFunc(task),"recvBeacon");
04075             taskP.mlme_sync_request_numSearchRetry = 0;
04076             taskP.mlme_sync_request_tracking = TrackBeacon;
04077             //set current channel
04078             tmp_ppib.phyCurrentChannel = LogicalChannel;
04079             phy->PLME_SET_request(phyCurrentChannel,&tmp_ppib);
04080             //enable the receiver
04081             plme_set_trx_state_request(p_RX_ON);
04082             BO = (macBeaconOrder2 == 15)?14:macBeaconOrder2;
04083             if (bcnSearchT->busy())
04084                 bcnSearchT->stop();
04085             bcnSearchT->start(aBaseSuperframeDuration*((1 << BO)+1) / phy->getRate('s'));
04086             break;
04087         case 1:
04088             if (status == p_SUCCESS)    //beacon received
04089             {
04090                 //no confirm primitive for the success - it's better to have one
04091                 taskP.taskStatus(task) = false;
04092                 //continue to track the beacon if required
04093                 if (TrackBeacon)
04094                 {
04095                     //reset <numSearchRetry> (so that tracking can work properly)
04096                     taskP.mlme_sync_request_numSearchRetry = 0;
04097                     if(!bcnRxT->busy())
04098                         bcnRxT->start();
04099                 }
04100                 csmacaResume();
04101             }
04102             else                //time out when waiting for beacon
04103             {
04104                 taskP.mlme_sync_request_numSearchRetry++;
04105                 if (taskP.mlme_sync_request_numSearchRetry <= aMaxLostBeacons)
04106                 {
04107                     plme_set_trx_state_request(p_RX_ON);
04108                     BO = (macBeaconOrder2 == 15)?14:macBeaconOrder2;
04109                     bcnSearchT->start(aBaseSuperframeDuration*((1 << BO)+1) / phy->getRate('s'));
04110                 }
04111                 else
04112                 {
04113                     taskP.taskStatus(task) = false;
04114                     changeNodeColor(CURRENT_TIME,Nam802_15_4::def_Node_clr);
04115                     sscs->MLME_SYNC_LOSS_indication(m_BEACON_LOSS);
04116                     /*If the initial beacon location fails, no need to track the beacon even it is required
04117                      *Note that not tracking does not mean the device will not be able to receive beacons --
04118                      *but the reception may be not so reliable since there is no synchronization.
04119                      */
04120                     taskP.mlme_sync_request_tracking = false;
04121                     csmacaResume();
04122                     return;
04123                 }
04124             }
04125             break;
04126         default:
04127             break;
04128     }
04129 }
04130 
04131 void Mac802_15_4::mlme_poll_request(UINT_8 CoordAddrMode,UINT_16 CoordPANId,IE3ADDR CoordAddress,bool SecurityEnable,
04132                     bool autoRequest,bool firstTime,PHYenum status)
04133 {
04134     UINT_8 step,task;
04135     FrameCtrl frmCtrl;
04136     hdr_lrwpan* wph;
04137 
04138     task = TP_mlme_poll_request;
04139     if (firstTime)
04140     {
04141         if (taskP.taskStatus(task))
04142             return;
04143         else
04144         {
04145             taskP.taskStep(task) = 0;
04146             (taskP.taskFrFunc(task))[0] = 0;
04147         }
04148     }
04149 
04150     step = taskP.taskStep(task);
04151     switch(step)
04152     {
04153         case 0:
04154             //check if parameters valid or not
04155             if (((CoordAddrMode != defFrmCtrl_AddrMode16)&&(CoordAddrMode != defFrmCtrl_AddrMode64))
04156              || (CoordPANId == 0xffff))
04157             {
04158                 if (!autoRequest)
04159                     sscs->MLME_POLL_confirm(m_INVALID_PARAMETER);
04160                 return;
04161             }
04162             taskP.taskStatus(task) = true;
04163             taskP.taskStep(task)++;
04164             strcpy(taskP.taskFrFunc(task),"csmacaCallBack");
04165             taskP.mlme_poll_request_CoordAddrMode = CoordAddrMode;
04166             taskP.mlme_poll_request_CoordPANId = CoordPANId;
04167             taskP.mlme_poll_request_CoordAddress = CoordAddress;
04168             taskP.mlme_poll_request_SecurityEnable = SecurityEnable;
04169             taskP.mlme_poll_request_autoRequest = autoRequest;
04170             //-- send a data request command ---
04171 #ifdef DEBUG802_15_4
04172             fprintf(stdout,"[%s::%s][%f](node %d) before alloc txBcnCmd2:\n\t\ttxBeacon\t= %ld\n\t\ttxAck   \t= %ld\n\t\ttxBcnCmd\t= %ld\n\t\ttxBcnCmd2\t= %ld\n\t\ttxData  \t= %ld\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,txBeacon,txAck,txBcnCmd,txBcnCmd2,txData);
04173 #endif
04174             assert(!txBcnCmd2);
04175             txBcnCmd2 = Packet::alloc();
04176             assert(txBcnCmd2);
04177             wph = HDR_LRWPAN(txBcnCmd2);
04178             if ((mpib.macShortAddress == 0xfffe)||(mpib.macShortAddress == 0xffff))
04179             {
04180                 frmCtrl.setSrcAddrMode(defFrmCtrl_AddrMode64);
04181                 wph->MHR_SrcAddrInfo.addr_64 = aExtendedAddress;
04182             }
04183             else
04184             {
04185                 frmCtrl.setSrcAddrMode(defFrmCtrl_AddrMode16);
04186                 wph->MHR_SrcAddrInfo.addr_16 = mpib.macShortAddress;
04187             }
04188             if (sfSpec2.PANCoor)
04189                 frmCtrl.setDstAddrMode(defFrmCtrl_AddrModeNone);
04190             else
04191                 frmCtrl.setDstAddrMode(CoordAddrMode);
04192             constructCommandHeader(txBcnCmd2,&frmCtrl,0x04,frmCtrl.dstAddrMode,CoordPANId,CoordAddress,frmCtrl.srcAddrMode,mpib.macPANId,wph->MHR_SrcAddrInfo.addr_64,SecurityEnable,false,true);
04193             constructMPDU(1,txBcnCmd2,frmCtrl.FrmCtrl,mpib.macDSN++,wph->MHR_DstAddrInfo,wph->MHR_SrcAddrInfo,0,0x04,0);
04194             csmacaBegin('C');
04195             //------------------------------------
04196             break;
04197         case 1:
04198             if (status == p_IDLE)
04199             {
04200                 taskP.taskStep(task)++;
04201                 strcpy(taskP.taskFrFunc(task),"PD_DATA_confirm");
04202                 plme_set_trx_state_request(p_TX_ON);
04203                 break;
04204             }
04205             else
04206             {
04207                 taskP.taskStatus(task) = false;
04208                 if (!autoRequest)
04209                     sscs->MLME_POLL_confirm(m_CHANNEL_ACCESS_FAILURE);
04210                 resetTRX();
04211                 taskFailed('C',m_CHANNEL_ACCESS_FAILURE);
04212                 return;
04213             }
04214             break;
04215         case 2:
04216             taskP.taskStep(task)++;
04217             strcpy(taskP.taskFrFunc(task),"recvAck");
04218             //enable the receiver
04219             plme_set_trx_state_request(p_RX_ON);
04220             txT->start(mpib.macAckWaitDuration/phy->getRate('s'));
04221             waitBcnCmdAck2 = true;
04222             break;
04223         case 3:
04224             if (status == p_SUCCESS)    //ack. received
04225             {
04226                 if (!taskP.mlme_poll_request_pending)
04227                 {
04228                     taskP.taskStatus(task) = false;
04229                     if (!autoRequest)
04230                         sscs->MLME_POLL_confirm(m_NO_DATA);
04231                     resetTRX();
04232                     taskSuccess('C');
04233                     return;
04234                 }
04235                 else
04236                 {
04237                     taskP.taskStep(task)++;
04238                     strcpy(taskP.taskFrFunc(task),"IFSHandler");
04239                     plme_set_trx_state_request(p_RX_ON);        //wait for data
04240                     taskSuccess('C',false);
04241                     extractT->start(aMaxFrameResponseTime/phy->getRate('s'),true);  //wait for <aMaxFrameResponseTime> symbols (or CAP symbols if beacon enabled) (see page 156, line 1-3)
04242                 }
04243             }
04244             else                //time out when waiting for ack.
04245             {
04246                 numBcnCmdRetry2++;
04247                 if (numBcnCmdRetry2 <= aMaxFrameRetries)
04248                 {
04249                     taskP.taskStep(task) = 1;   //important
04250                     strcpy(taskP.taskFrFunc(task),"csmacaCallBack");
04251                     waitBcnCmdAck2 = false;
04252                     csmacaResume();
04253                 }
04254                 else
04255                 {
04256                     taskP.taskStatus(task) = false;
04257                     if (!autoRequest)
04258                         sscs->MLME_POLL_confirm(m_NO_ACK);
04259                     resetTRX();
04260                     taskFailed('C',m_NO_ACK);
04261                     return;
04262                 }
04263             }
04264             break;
04265         case 4:
04266             taskP.taskStatus(task) = false;
04267             if (status == p_SUCCESS)        //data received
04268             {
04269                 //stop the timer
04270                 extractT->stop();
04271                 if (!autoRequest)
04272                     sscs->MLME_POLL_confirm(m_SUCCESS);
04273                 //another step is to issue DATA.indication() which has been done in IFSHandler()
04274 
04275                 //poll again to see if there are more packets pending -- note that, for each poll request, more than one confirm could be passed to upper layer
04276                 mlme_poll_request(CoordAddrMode,CoordPANId,CoordAddress,SecurityEnable,autoRequest,true);
04277             }
04278             else                    //time out when waiting for response
04279             {
04280                 if (!autoRequest)
04281                     sscs->MLME_POLL_confirm(m_NO_DATA);
04282                 resetTRX();
04283                 csmacaResume();
04284             }
04285             break;
04286         default:
04287             break;
04288     }
04289 }
04290 
04291 //-------------------------------------------------------------------------------------
04292 
04293 void Mac802_15_4::csmacaBegin(char pktType)
04294 {
04295     if (pktType == 'c')     //txBcnCmd
04296     {
04297         waitBcnCmdAck = false;          //beacon packet not yet transmitted
04298         numBcnCmdRetry = 0;
04299         if (backoffStatus == 99)        //backoffing for data packet
04300         {
04301             backoffStatus = 0;
04302             csmaca->cancel();
04303         }
04304         csmacaResume();
04305     }
04306     else if (pktType == 'C')    //txBcnCmd2
04307     {
04308         waitBcnCmdAck2 = false;         //command packet not yet transmitted
04309         numBcnCmdRetry2 = 0;
04310         if ((backoffStatus == 99)&&(txCsmaca != txBcnCmd))  //backoffing for data packet
04311         {
04312             backoffStatus = 0;
04313             csmaca->cancel();
04314         }
04315         csmacaResume();
04316 
04317     }
04318     else //if (pktType == 'd')  //txData
04319     {
04320         waitDataAck = false;            //data packet not yet transmitted
04321         numDataRetry = 0;
04322         csmacaResume();
04323     }
04324 }
04325 
04326 void Mac802_15_4::csmacaResume(void)
04327 {
04328     FrameCtrl frmCtrl;
04329 
04330     if ((backoffStatus != 99)           //not during backoff
04331     &&  (!inTransmission))              //not during transmission
04332     if ((txBcnCmd)&&(!waitBcnCmdAck))
04333     {
04334         backoffStatus = 99;
04335         frmCtrl.FrmCtrl = HDR_LRWPAN(txBcnCmd)->MHR_FrmCtrl;
04336         frmCtrl.parse();
04337         txCsmaca = txBcnCmd;
04338         csmaca->start(true,txBcnCmd,frmCtrl.ackReq);
04339     }
04340     else if ((txBcnCmd2)&&(!waitBcnCmdAck2))
04341     {
04342         backoffStatus = 99;
04343         frmCtrl.FrmCtrl = HDR_LRWPAN(txBcnCmd2)->MHR_FrmCtrl;
04344         frmCtrl.parse();
04345         txCsmaca = txBcnCmd2;
04346         csmaca->start(true,txBcnCmd2,frmCtrl.ackReq);
04347     }
04348     else if ((txData)&&(!waitDataAck))
04349     {
04350         strcpy(taskP.taskFrFunc(TP_mcps_data_request),"csmacaCallBack");    //the transmission may be interrupted and need to backoff again
04351         taskP.taskStep(TP_mcps_data_request) = 1;               //also set the step
04352         backoffStatus = 99;
04353         frmCtrl.FrmCtrl = HDR_LRWPAN(txData)->MHR_FrmCtrl;
04354         frmCtrl.parse();
04355         txCsmaca = txData;
04356         csmaca->start(true,txData,frmCtrl.ackReq);
04357     }
04358 }
04359 
04360 void Mac802_15_4::csmacaCallBack(PHYenum status)
04361 {
04362     if (((!txBcnCmd)||(waitBcnCmdAck))
04363       &&((!txBcnCmd2)||(waitBcnCmdAck2))
04364       &&((!txData)||(waitDataAck)))
04365         return;
04366 
04367     backoffStatus = (status == p_IDLE)?1:2;
04368 
04369 #ifdef DEBUG802_15_4
04370     hdr_cmn *ch = HDR_CMN(txCsmaca);
04371     if (status != p_IDLE)
04372         fprintf(stdout,"[%s::%s][%f](node %d) backoff failed: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %d\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(txCsmaca),p802_15_4macSA(txCsmaca),p802_15_4macDA(txCsmaca),ch->uid(),HDR_LRWPAN(txCsmaca)->uid,ch->size());
04373 #endif
04374     
04375     dispatch(status,__FUNCTION__);
04376 }
04377 
04378 int Mac802_15_4::getBattLifeExtSlotNum(void)
04379 {
04380     phy->PLME_GET_request(phyCurrentChannel);
04381     return (tmp_ppib.phyCurrentChannel<=10)?8:6;
04382 }
04383 
04384 double Mac802_15_4::getCAP(bool small)
04385 {
04386     double bcnTxTime,bcnRxTime,bcnOtherRxTime,bPeriod;
04387     double sSlotDuration,sSlotDuration2,sSlotDuration3,BI2,BI3,t_CAP,t_CAP2,t_CAP3;
04388     double now,oneDay,tmpf;
04389     
04390     now = CURRENT_TIME;
04391     oneDay = now + 24.0*3600;
04392 
04393     if ((mpib.macBeaconOrder == 15)&&(macBeaconOrder2 == 15)                //non-beacon enabled
04394     &&(macBeaconOrder3 == 15))                              //no beacons from outside PAN
04395         return oneDay;                                  //transmission can always go ahead
04396     
04397     bcnTxTime = macBcnTxTime / phy->getRate('s');
04398     bcnRxTime = macBcnRxTime / phy->getRate('s');
04399     bcnOtherRxTime = macBcnOtherRxTime / phy->getRate('s');
04400     bPeriod = aUnitBackoffPeriod / phy->getRate('s');
04401     sSlotDuration = sfSpec.sd / phy->getRate('s');
04402     sSlotDuration2 = sfSpec2.sd / phy->getRate('s');
04403     sSlotDuration3 = sfSpec3.sd / phy->getRate('s');
04404     BI2 = (sfSpec2.BI / phy->getRate('s'));
04405     BI3 = (sfSpec3.BI / phy->getRate('s'));
04406     if (mpib.macBeaconOrder != 15)
04407     {
04408         if (sfSpec.BLE)
04409         {
04410             /* Linux floating number compatibility
04411             t_CAP = (bcnTxTime + (beaconPeriods + getBattLifeExtSlotNum()) * aUnitBackoffPeriod);
04412             */
04413             {
04414             tmpf = (beaconPeriods + getBattLifeExtSlotNum()) * aUnitBackoffPeriod;
04415             t_CAP = bcnTxTime + tmpf;
04416             }
04417         }
04418         else
04419         {
04420             /* Linux floating number compatibility
04421             t_CAP = (bcnTxTime + (sfSpec.FinCAP + 1) * sSlotDuration);
04422             */
04423             {
04424             tmpf = (sfSpec.FinCAP + 1) * sSlotDuration;
04425             t_CAP = bcnTxTime + tmpf;
04426             }
04427         }
04428     }
04429     if (macBeaconOrder2 != 15)
04430     {
04431         if (sfSpec2.BLE)
04432         {
04433             /* Linux floating number compatibility
04434             t_CAP2 = (bcnRxTime + (beaconPeriods2 + getBattLifeExtSlotNum()) * aUnitBackoffPeriod);
04435             */
04436             {
04437             tmpf = (beaconPeriods2 + getBattLifeExtSlotNum()) * aUnitBackoffPeriod;
04438             t_CAP2 = bcnRxTime + tmpf;
04439             }
04440         }
04441         else
04442         {
04443             /* Linux floating number compatibility
04444             t_CAP2 = (bcnRxTime + (sfSpec2.FinCAP + 1) * sSlotDuration2);
04445             */
04446             {
04447             tmpf = (sfSpec2.FinCAP + 1) * sSlotDuration2;
04448             t_CAP2 = bcnRxTime + tmpf;
04449             }
04450         }
04451 
04452         /* Linux floating number compatibility
04453         if ((t_CAP2 < now)&&(t_CAP2 + aMaxLostBeacons * BI2 >= now))
04454         */
04455         tmpf = aMaxLostBeacons * BI2;
04456         if ((t_CAP2 < now)&&(t_CAP2 + tmpf >= now)) //no more than <aMaxLostBeacons> beacons missed
04457         while (t_CAP2 < now)
04458             t_CAP2 += BI2;
04459     }
04460     if (macBeaconOrder3 != 15)
04461     {
04462         //no need to handle option <macBattLifeExt> here
04463         /* Linux floating number compatibility
04464         t_CAP3 = (bcnOtherRxTime + (sfSpec3.FinCAP + 1) * sSlotDuration3);
04465         */
04466         {
04467         tmpf = (sfSpec3.FinCAP + 1) * sSlotDuration3;
04468         t_CAP3 = bcnOtherRxTime + tmpf;
04469         }
04470 
04471         /* Linux floating number compatibility
04472         if ((t_CAP3 < now)&&(t_CAP3 + aMaxLostBeacons * BI3 >= now))
04473         */
04474         tmpf = aMaxLostBeacons * BI3;
04475         if ((t_CAP3 < now)&&(t_CAP3 + tmpf >= now)) //no more than <aMaxLostBeacons> beacons missed
04476         while (t_CAP3 < now)
04477             t_CAP3 += BI3;
04478     }
04479 
04480     if ((mpib.macBeaconOrder == 15)&&(macBeaconOrder2 == 15))
04481     {
04482         if (t_CAP3 >= now)
04483             return t_CAP3;
04484         else
04485             return oneDay;
04486     }
04487     else if (mpib.macBeaconOrder == 15)
04488     {
04489         if (t_CAP2 >= now)
04490             return t_CAP2;
04491         else
04492             return oneDay;
04493     }
04494     else if (macBeaconOrder2 == 15)
04495     {
04496         if (t_CAP >= now)
04497             return t_CAP;
04498         else
04499             return oneDay;
04500     }
04501     else
04502     {
04503         if (t_CAP2 < now)
04504             return t_CAP;
04505 
04506         if ((small)
04507         &&  (t_CAP > t_CAP2))
04508             t_CAP = t_CAP2;
04509         if ((!small)
04510         &&  (t_CAP < t_CAP2))
04511             t_CAP = t_CAP2;
04512 
04513         return t_CAP;
04514     }
04515 }
04516 
04517 double Mac802_15_4::getCAPbyType(int type)
04518 {
04519     double bcnTxTime,bcnRxTime,bcnOtherRxTime,bPeriod;
04520     double sSlotDuration,sSlotDuration2,sSlotDuration3,BI2,BI3,t_CAP,t_CAP2,t_CAP3;
04521     double now,oneDay,tmpf;
04522     
04523     now = CURRENT_TIME;
04524     oneDay = now + 24.0*3600;
04525 
04526     if ((mpib.macBeaconOrder == 15)&&(macBeaconOrder2 == 15)                //non-beacon enabled
04527     &&(macBeaconOrder3 == 15))                              //no beacons from outside PAN
04528         return oneDay;                                  //transmission can always go ahead
04529     
04530     bcnTxTime = macBcnTxTime / phy->getRate('s');
04531     bcnRxTime = macBcnRxTime / phy->getRate('s');
04532     bcnOtherRxTime = macBcnOtherRxTime / phy->getRate('s');
04533     bPeriod = aUnitBackoffPeriod / phy->getRate('s');
04534     sSlotDuration = sfSpec.sd / phy->getRate('s');
04535     sSlotDuration2 = sfSpec2.sd / phy->getRate('s');
04536     sSlotDuration3 = sfSpec3.sd / phy->getRate('s');
04537     BI2 = (sfSpec2.BI / phy->getRate('s'));
04538     BI3 = (sfSpec3.BI / phy->getRate('s'));
04539 
04540     if (type == 1)
04541     if (mpib.macBeaconOrder != 15)
04542     {
04543         if (sfSpec.BLE)
04544         {
04545             /* Linux floating number compatibility
04546             t_CAP = (bcnTxTime + (beaconPeriods + getBattLifeExtSlotNum()) * aUnitBackoffPeriod);
04547             */
04548             {
04549             tmpf = (beaconPeriods + getBattLifeExtSlotNum()) * aUnitBackoffPeriod;
04550             t_CAP = bcnTxTime + tmpf;
04551             }
04552         }
04553         else
04554         {
04555             /* Linux floating number compatibility
04556             t_CAP = (bcnTxTime + (sfSpec.FinCAP + 1) * sSlotDuration);
04557             */
04558             {
04559             tmpf = (sfSpec.FinCAP + 1) * sSlotDuration;
04560             t_CAP = bcnTxTime + tmpf;
04561             }
04562         }
04563         return (t_CAP>=now)?t_CAP:oneDay;
04564     }
04565     else
04566         return oneDay;
04567 
04568     if (type == 2)
04569     if (macBeaconOrder2 != 15)
04570     {
04571         if (sfSpec2.BLE)
04572         {
04573             /* Linux floating number compatibility
04574             t_CAP2 = (bcnRxTime + (beaconPeriods2 + getBattLifeExtSlotNum()) * aUnitBackoffPeriod);
04575             */
04576             {
04577             tmpf = (beaconPeriods2 + getBattLifeExtSlotNum()) * aUnitBackoffPeriod;
04578             t_CAP2 = bcnRxTime + tmpf;
04579             }
04580         }
04581         else
04582         {
04583             /* Linux floating number compatibility
04584             t_CAP2 = (bcnRxTime + (sfSpec2.FinCAP + 1) * sSlotDuration2);
04585             */
04586             {
04587             tmpf = (sfSpec2.FinCAP + 1) * sSlotDuration2;
04588             t_CAP2 = bcnRxTime + tmpf;
04589             }
04590         }
04591 
04592         /* Linux floating number compatibility
04593         if ((t_CAP2 < now)&&(t_CAP2 + aMaxLostBeacons * BI2 >= now))
04594         */
04595         tmpf = aMaxLostBeacons * BI2;
04596         if ((t_CAP2 < now)&&(t_CAP2 + tmpf >= now)) //no more than <aMaxLostBeacons> beacons missed
04597         while (t_CAP2 < now)
04598             t_CAP2 += BI2;
04599         return (t_CAP2>=now)?t_CAP2:oneDay;
04600     }
04601     else
04602         return oneDay;
04603     
04604     if (type == 3)
04605     if (macBeaconOrder3 != 15)
04606     {
04607         //no need to handle option <macBattLifeExt> here
04608         /* Linux floating number compatibility
04609         t_CAP3 = (bcnOtherRxTime + (sfSpec3.FinCAP + 1) * sSlotDuration3);
04610         */
04611         {
04612         tmpf = (sfSpec3.FinCAP + 1) * sSlotDuration3;
04613         t_CAP3 = bcnOtherRxTime + tmpf;
04614         }
04615 
04616         /* Linux floating number compatibility
04617         if ((t_CAP3 < now)&&(t_CAP3 + aMaxLostBeacons * BI3 >= now))
04618         */
04619         tmpf = aMaxLostBeacons * BI3;
04620         if ((t_CAP3 < now)&&(t_CAP3 + tmpf >= now)) //no more than <aMaxLostBeacons> beacons missed
04621         while (t_CAP3 < now)
04622             t_CAP3 += BI3;
04623         return (t_CAP3>=now)?t_CAP3:oneDay;
04624     }
04625     else
04626         return oneDay;
04627 
04628     return oneDay;
04629 }
04630 
04631 bool Mac802_15_4::canProceedWOcsmaca(Packet *p)
04632 {
04633     //this function checks whether there is enough time in the CAP of current superframe to finish a transaction (transmit a pending packet to a device)
04634     //(in the case the node acts as both a coordinator and a device, both the superframes from and to this node should be taken into account)
04635     double wtime,t_IFS,t_transacTime,t_CAP,tmpf;
04636     FrameCtrl frmCtrl;
04637     //int type;
04638 
04639     if ((mpib.macBeaconOrder == 15)&&(macBeaconOrder2 == 15)                
04640     &&(macBeaconOrder3 == 15))                              
04641         return true;                                    
04642     else
04643     {
04644         frmCtrl.FrmCtrl = HDR_LRWPAN(p)->MHR_FrmCtrl;
04645         frmCtrl.parse();
04646         wtime = 0.0;
04647         //there is no need to consider <macBattLifeExt>, since the device polling the data 
04648         //should be waiting rather than go to sleep after the first 6 CAP backoff perios.
04649         if (HDR_CMN(p)->size() <= aMaxSIFSFrameSize)
04650             t_IFS = aMinSIFSPeriod;
04651         else
04652             t_IFS = aMinLIFSPeriod;
04653         t_IFS /= phy->getRate('s');
04654         t_transacTime  = locateBoundary(toParent(p),wtime) - wtime;         //boundary location time
04655         t_transacTime += phy->trxTime(p);                       //packet transmission time
04656         if (frmCtrl.ackReq)
04657         {
04658             t_transacTime += mpib.macAckWaitDuration/phy->getRate('s');     //ack. waiting time
04659             t_transacTime += 2*max_pDelay;                      //round trip propagation delay (802.15.4 ignores this, but it should be there even though it is very small)
04660             t_transacTime += t_IFS;                         //IFS time -- not only ensure that the sender can finish the transaction, but also the receiver
04661             t_CAP = getCAP(true);
04662 
04663             /* Linux floating number compatibility
04664             if (CURRENT_TIME + wtime + t_transacTime > t_CAP)
04665             */
04666             tmpf = CURRENT_TIME + wtime;
04667             tmpf += t_transacTime;
04668             if (tmpf > t_CAP)
04669                 return false;
04670             else
04671                 return true;
04672         }
04673         else
04674         {
04675             //in this case, we need to handle individual CAP 
04676             t_CAP = getCAPbyType(1);
04677 
04678             /* Linux floating number compatibility
04679             if (CURRENT_TIME + wtime + t_transacTime > t_CAP)
04680             */
04681             tmpf = CURRENT_TIME + wtime;
04682             tmpf += t_transacTime;
04683             if (tmpf > t_CAP)
04684                 return false;
04685             t_CAP = getCAPbyType(2);
04686             t_transacTime += max_pDelay;                        //one-way trip propagation delay (802.15.4 ignores this, but it should be there even though it is very small)
04687             t_transacTime += 12/phy->getRate('s');                  //transceiver turn-around time (receiver may need to do this to transmit next beacon)
04688             t_transacTime += t_IFS;                         //IFS time -- not only ensure that the sender can finish the transaction, but also the receiver
04689 
04690             /* Linux floating number compatibility
04691             if (CURRENT_TIME + wtime + t_transacTime > t_CAP)
04692             */
04693             tmpf = CURRENT_TIME + wtime;
04694             tmpf += t_transacTime;
04695             if (tmpf > t_CAP)
04696                 return false;
04697             t_CAP = getCAPbyType(3);
04698             t_transacTime -= t_IFS;                         //the third node does not need to handle the transaction
04699 
04700             /* Linux floating number compatibility
04701             if (CURRENT_TIME + wtime + t_transacTime > t_CAP)
04702             */
04703             tmpf = CURRENT_TIME + wtime;
04704             tmpf += t_transacTime;
04705             if (tmpf > t_CAP)
04706                 return false;
04707 
04708             return true;
04709         }
04710     }
04711 }
04712 
04713 void Mac802_15_4::transmitCmdData(void)
04714 {
04715     double delay;
04716 
04717     if ((mpib.macBeaconOrder != 15)||(macBeaconOrder2 != 15))   //beacon enabled -- slotted
04718     {
04719         delay =locateBoundary(toParent(txCsmaca),0.0);
04720         if(delay > 0.0)
04721         {
04722             Scheduler::instance().schedule(&txCmdDataH, &(txCmdDataH.nullEvent), delay);
04723             return;
04724         }
04725     }
04726 
04727     //transmit immediately
04728     txBcnCmdDataHandler();
04729 }
04730 
04731 void Mac802_15_4::reset_TRX(const char *frFile,const char *frFunc,int line)
04732 {
04733     double t_CAP;
04734     PHYenum t_state;
04735 
04736     if ((mpib.macBeaconOrder != 15)||(macBeaconOrder2 != 15))   //beacon enabled
04737     {
04738         //according to the draft, <macRxOnWhenIdle> only considered during idle periods of the CAP if beacon enabled
04739         t_CAP = getCAP(false);
04740         if (CURRENT_TIME < t_CAP)
04741             t_state = mpib.macRxOnWhenIdle?p_RX_ON:p_TRX_OFF;
04742         else
04743             t_state = p_RX_ON;  //(not considered ==> RX_ON)?
04744     }
04745     else
04746         t_state = mpib.macRxOnWhenIdle?p_RX_ON:p_TRX_OFF;
04747     
04748     set_trx_state_request(t_state,frFile,frFunc,line);
04749 }
04750 
04751 void Mac802_15_4::taskSuccess(char task,bool csmacaRes)
04752 {
04753     hdr_cmn* ch;
04754     hdr_lrwpan* wph;
04755     UINT_16 t_CAP;
04756     UINT_8 ifs;
04757     double tmpf;
04758 
04759 #ifdef DEBUG802_15_4
04760     fprintf(stdout,"[%s::%s][%f](node %d) task '%c' successful:\n\t\ttxBeacon\t= %ld\n\t\ttxAck   \t= %ld\n\t\ttxBcnCmd\t= %ld\n\t\ttxBcnCmd2\t= %ld\n\t\ttxData  \t= %ld\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,task,txBeacon,txAck,txBcnCmd,txBcnCmd2,txData);
04761 #endif
04762 
04763     if (task == 'b')    //beacon
04764     {
04765         if (!txBeacon)  
04766         {
04767             assert(txBcnCmd2);
04768             txBeacon = txBcnCmd2;
04769             txBcnCmd2 = 0;
04770         }
04771         //--- calculate CAP ---
04772         sfSpec.parse();     
04773         if (HDR_CMN(txBeacon)->size() <= aMaxSIFSFrameSize)
04774             ifs = aMinSIFSPeriod;
04775         else
04776             ifs = aMinLIFSPeriod;
04777 
04778         /* Linux floating number compatibility
04779         beaconPeriods = (UINT_8)((phy->trxTime(txBeacon) * phy->getRate('s') + ifs) / aUnitBackoffPeriod);
04780         */
04781         {
04782         tmpf = phy->trxTime(txBeacon) * phy->getRate('s');
04783         tmpf += ifs;
04784         beaconPeriods = (UINT_8)(tmpf / aUnitBackoffPeriod);
04785         }
04786 
04787         /* Linux floating number compatibility
04788         if (fmod((phy->trxTime(txBeacon) * phy->getRate('s')+ ifs) ,aUnitBackoffPeriod) > 0.0)
04789         */
04790         tmpf = phy->trxTime(txBeacon) * phy->getRate('s');
04791         tmpf += ifs;
04792         if (fmod(tmpf,aUnitBackoffPeriod) > 0.0)
04793             beaconPeriods++;
04794 
04795         t_CAP = (sfSpec.FinCAP + 1) * (sfSpec.sd / aUnitBackoffPeriod) - beaconPeriods;
04796 
04797         if (t_CAP == 0)
04798         {
04799             csmacaRes = false;
04800             plme_set_trx_state_request(p_TRX_OFF);
04801         }
04802         else
04803             plme_set_trx_state_request(p_RX_ON);
04804         //CSMA-CA may be waiting for the new beacon
04805         if (backoffStatus == 99)
04806             csmaca->newBeacon('t');
04807         //----------------------
04808         beaconWaiting = false;
04809         Packet::free(txBeacon);
04810         txBeacon = 0;
04811         /*
04812         //send out delayed ack.
04813         if (txAck)
04814         {
04815             csmacaRes = false;
04816             plme_set_trx_state_request(p_TX_ON);
04817         }
04818         */
04819     }
04820     else if (task == 'a')   //ack.
04821     {
04822         assert(txAck);
04823         Packet::free(txAck);
04824         txAck = 0;
04825     }
04826     else if (task == 'c')   //command
04827     {
04828         assert(txBcnCmd);
04829         //if it is a pending packet, delete it from the pending list
04830         updateTransacLinkByPktOrHandle(tr_oper_del,&transacLink1,&transacLink2,txBcnCmd);
04831         freePkt(txBcnCmd);
04832         txBcnCmd = 0;
04833     }
04834     else if (task == 'C')   //command
04835     {
04836         assert(txBcnCmd2);
04837         freePkt(txBcnCmd2);
04838         txBcnCmd2 = 0;
04839     }
04840     else if (task == 'd')   //data
04841     {
04842         assert(txData);
04843 
04844         ch = HDR_CMN(txData);
04845         wph = HDR_LRWPAN(txData);
04846 
04847         Packet *p = txData;
04848         txData = 0;
04849         if (ch->ptype() == PT_MAC)
04850         {
04851             assert(wph->msduHandle);
04852             sscs->MCPS_DATA_confirm(wph->msduHandle,m_SUCCESS);
04853         }
04854         else
04855         {
04856             if (Mac802_15_4::callBack == 2)
04857             if (ch->xmit_failure_)
04858                 if (p802_15_4macDA(p) != (nsaddr_t)MAC_BROADCAST)
04859             {
04860                 ch->size() -= macHeaderLen(wph->MHR_FrmCtrl);
04861                 ch->xmit_reason_ = 1;
04862                 ch->xmit_failure_(p->refcopy(),ch->xmit_failure_data_);
04863             }
04864             if (callback_)  
04865             {
04866                 Handler *h = callback_;
04867                 callback_ = 0;
04868                 h->handle((Event*) 0);
04869             }
04870         }
04871         //if it is a pending packet, delete it from the pending list
04872         updateTransacLinkByPktOrHandle(tr_oper_del,&transacLink1,&transacLink2,p);
04873         freePkt(p);
04874     }
04875     else
04876         assert(0);
04877 
04878     if (csmacaRes)
04879         csmacaResume();
04880 }
04881 
04882 void Mac802_15_4::taskFailed(char task,MACenum status,bool csmacaRes)
04883 {
04884     hdr_cmn* ch;
04885     hdr_lrwpan* wph;
04886 
04887 #ifdef DEBUG802_15_4
04888     fprintf(stdout,"[D][FAIL][%s::%s][%f](node %d) task '%c' failed:\n\t\ttxBeacon\t= %ld\n\t\ttxAck   \t= %ld\n\t\ttxBcnCmd\t= %ld\n\t\ttxBcnCmd2\t= %ld\n\t\ttxData  \t= %ld\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,task,txBeacon,txAck,txBcnCmd,txBcnCmd2,txData);
04889 #endif
04890 
04891     if ((task == 'b')   //beacon
04892     || (task == 'a')    //ack.
04893     || (task == 'c'))   //command
04894     {
04895         assert(0);  //we don't handle the above failures here
04896     }
04897     else if (task == 'C')   //command
04898     {
04899         freePkt(txBcnCmd2);
04900         txBcnCmd2 = 0;
04901     }
04902     else if (task == 'd')   //data
04903     {
04904         wph = HDR_LRWPAN(txData);
04905         ch = HDR_CMN(txData);
04906 #ifdef DEBUG802_15_4
04907         fprintf(stdout,"[D][FAIL][%s::%s::%d][%f](node %d) failure: type = %s, src = %d, dst = %d, uid = %d, mac_uid = %ld, size = %d\n",__FILE__,__FUNCTION__,__LINE__,CURRENT_TIME,index_,wpan_pName(txData),p802_15_4macSA(txData),p802_15_4macDA(txData),ch->uid(),wph->uid,ch->size());
04908 #endif
04909         Packet *p = txData;
04910         txData = 0;
04911         if (wph->msduHandle)    //from SSCS
04912             sscs->MCPS_DATA_confirm(wph->msduHandle,status);
04913         else
04914         {
04915             if (Mac802_15_4::callBack)
04916             if (ch->xmit_failure_)
04917             {
04918                 wph->setSN = true;      
04919                 ch->size() -= macHeaderLen(wph->MHR_FrmCtrl);
04920                 ch->xmit_reason_ = 0;
04921                 ch->xmit_failure_(p->refcopy(),ch->xmit_failure_data_);
04922             }
04923             if (callback_           
04924             && (!dataWaitT->busy()))    
04925             {
04926                 Handler *h = callback_;
04927                 callback_ = 0;
04928                 h->handle((Event*) 0);
04929             }
04930         }
04931         freePkt(p);
04932     }
04933     else
04934         assert(0);
04935 
04936     if (csmacaRes)
04937         csmacaResume();
04938 }
04939 
04940 void Mac802_15_4::freePkt(Packet *pkt)
04941 {
04942     /*
04943     if (HDR_LRWPAN(pkt)->indirect)
04944         return;         //the packet will be automatically deleted when expired
04945     else
04946         Packet::free(pkt);
04947     */
04948     Packet::free(pkt);      //now same operation for directly transmitted and indirectly transmitted packets
04949 }
04950 
04951 UINT_8 Mac802_15_4::macHeaderLen(UINT_16 FrmCtrl)
04952 {
04953     //calculate the MAC sublayer header (also including footer) length
04954     UINT_8 macHLen;
04955     FrameCtrl frmCtrl;
04956 
04957     frmCtrl.FrmCtrl = FrmCtrl;
04958     frmCtrl.parse();
04959     
04960     macHLen = 0;
04961     macHLen += 2        //FrmCtrl
04962           +1        //BSN/DSN
04963           +2;       //FCS
04964     if (frmCtrl.frmType == defFrmCtrl_Type_Beacon)      //Beacon
04965     {
04966         if (frmCtrl.srcAddrMode == defFrmCtrl_AddrMode16)
04967             macHLen += 2;
04968         else if (frmCtrl.srcAddrMode == defFrmCtrl_AddrMode64)
04969             macHLen += 8;
04970     }
04971     else if ((frmCtrl.frmType == defFrmCtrl_Type_Data)  //Data
04972         ||(frmCtrl.frmType == defFrmCtrl_Type_MacCmd))  //Mac Command
04973     {
04974         if (frmCtrl.dstAddrMode == defFrmCtrl_AddrMode16)
04975             macHLen += 2;
04976         else if (frmCtrl.dstAddrMode == defFrmCtrl_AddrMode64)
04977             macHLen += 8;
04978         if (frmCtrl.srcAddrMode == defFrmCtrl_AddrMode16)
04979             macHLen += 2;
04980         else if (frmCtrl.srcAddrMode == defFrmCtrl_AddrMode64)
04981             macHLen += 8;
04982     }
04983     else if (frmCtrl.frmType == defFrmCtrl_Type_Ack)    //Ack.
04984     {
04985         ;//nothing to do
04986     }
04987     else
04988         fprintf(stdout,"[%s][%f](node %d) Invalid frame type!\n",__FUNCTION__,CURRENT_TIME,index_);
04989 
04990     return macHLen;
04991 }
04992 
04993 void Mac802_15_4::constructACK(Packet *p)
04994 {
04995     bool intraPan;
04996     UINT_8 origFrmType;
04997     FrameCtrl frmCtrl;
04998     Packet *ack = Packet::alloc();
04999     hdr_lrwpan* wph1 = HDR_LRWPAN(p);
05000     hdr_lrwpan* wph2 = HDR_LRWPAN(ack);
05001     hdr_cmn* ch1 = HDR_CMN(p);
05002     hdr_cmn* ch2 = HDR_CMN(ack);
05003     int i;
05004     
05005     hdr_dst((char *)HDR_MAC(ack),p802_15_4macSA(p));
05006     hdr_src((char *)HDR_MAC(ack),index_);
05007     frmCtrl.FrmCtrl = wph1->MHR_FrmCtrl;
05008     frmCtrl.parse();
05009     intraPan = frmCtrl.intraPan;
05010     origFrmType = frmCtrl.frmType;
05011     frmCtrl.FrmCtrl = 0;
05012     frmCtrl.setFrmType(defFrmCtrl_Type_Ack);
05013     frmCtrl.setSecu(false);
05014     //if it is a data request command, then need to check if there is any packet pending.
05015     //In implementation, we may not have enough time to check if packets pending. If this is the case,
05016     //then the pending flag in the ack. should be set to 1, and then send a zero-length data packet
05017     //if later it turns out there is no packet actually pending.
05018     //In simulation, we assume having enough time to determine the pending status -- so zero-length packet will never be sent.
05019     //(refer to page 155, line 46-50)
05020     if ((origFrmType == defFrmCtrl_Type_MacCmd)     //command packet
05021     && (wph1->MSDU_CmdType == 0x04))            //data request command
05022     {
05023         i = updateTransacLink(tr_oper_est,&transacLink1,&transacLink2,frmCtrl.srcAddrMode,wph1->MHR_SrcAddrInfo.addr_64);
05024         frmCtrl.setFrmPending(i==0);
05025     }
05026     else
05027         frmCtrl.setFrmPending(false);
05028     frmCtrl.setAckReq(false);
05029     frmCtrl.setIntraPan(intraPan);
05030     frmCtrl.setDstAddrMode(defFrmCtrl_AddrModeNone);
05031     frmCtrl.setSrcAddrMode(defFrmCtrl_AddrModeNone);
05032     wph2->MHR_FrmCtrl = frmCtrl.FrmCtrl;
05033     wph2->MHR_BDSN = wph1->MHR_BDSN;    //copy the SN from Data/MacCmd packet
05034     wph2->uid = wph1->uid;          //for debug
05035     //wph2->MFR_FCS
05036 
05037     ch2->uid() = 0;
05038     ch2->ptype() = PT_MAC;
05039     ch2->iface() = -2;
05040     ch2->error() = 0;
05041     ch2->size() = 5;
05042     ch2->uid() = ch1->uid();        //copy the uid
05043 
05044     ch2->next_hop_ = p802_15_4macDA(ack);   //nam needs the nex_hop information
05045     p802_15_4hdrACK(ack);
05046 
05047 #ifdef DEBUG802_15_4
05048     fprintf(stdout,"[%s::%s][%f](node %d) before alloc txAck:\n\t\ttxBeacon\t= %ld\n\t\ttxAck   \t= %ld\n\t\ttxBcnCmd\t= %ld\n\t\ttxBcnCmd2\t= %ld\n\t\ttxData  \t= %ld\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,txBeacon,txAck,txBcnCmd,txBcnCmd2,txData);
05049 #endif
05050     assert(!txAck);     //it's impossilbe to receive the second packet before
05051                 //the Ack has been sent out.
05052     txAck = ack;
05053 }
05054 
05055 void Mac802_15_4::constructMPDU(UINT_8 msduLength,Packet *msdu, UINT_16 FrmCtrl,UINT_8 BDSN,panAddrInfo DstAddrInfo,
05056                  panAddrInfo  SrcAddrInfo,UINT_16 SuperSpec,UINT_8 CmdType,UINT_16 FCS)
05057 {
05058     hdr_lrwpan* wph = HDR_LRWPAN(msdu);
05059     hdr_cmn* ch = HDR_CMN(msdu);
05060     //FrameCtrl frmCtrl;
05061 
05062     //fill out fields
05063     wph->MHR_FrmCtrl = FrmCtrl;
05064     if (!wph->setSN)        
05065         wph->MHR_BDSN = BDSN;
05066     else
05067         wph->setSN = false; 
05068     if (!wph->uid)
05069         wph->uid = Mac802_15_4::DBG_UID++;
05070     wph->MHR_DstAddrInfo = DstAddrInfo;
05071     wph->MHR_SrcAddrInfo = SrcAddrInfo;
05072     wph->MSDU_SuperSpec = SuperSpec;
05073     wph->MSDU_CmdType = CmdType;
05074     wph->MFR_FCS = FCS;
05075 
05076     //update packet length
05077     ch->size() = msduLength + macHeaderLen(FrmCtrl);
05078 }
05079 
05080 void Mac802_15_4::constructCommandHeader(Packet *p,FrameCtrl *frmCtrl,UINT_8 CmdType,
05081                     UINT_8 dstAddrMode,UINT_16 dstPANId,IE3ADDR dstAddr,
05082                     UINT_8 srcAddrMode,UINT_16 srcPANId,IE3ADDR srcAddr,
05083                     bool secuEnable,bool pending,bool ackreq)
05084 {
05085     hdr_lrwpan *wph = HDR_LRWPAN(p);
05086 
05087     frmCtrl->FrmCtrl = 0;
05088     frmCtrl->setFrmType(defFrmCtrl_Type_MacCmd);
05089     frmCtrl->setDstAddrMode(dstAddrMode);
05090     wph->MHR_DstAddrInfo.panID = dstPANId;
05091     wph->MHR_DstAddrInfo.addr_64 = dstAddr;
05092     hdr_src((char *)HDR_MAC(p),index_);
05093     if (dstAddr == 0xffff)
05094         hdr_dst((char *)HDR_MAC(p),MAC_BROADCAST);
05095     else
05096         hdr_dst((char *)HDR_MAC(p),dstAddr);
05097     frmCtrl->setSrcAddrMode(srcAddrMode);
05098     wph->MHR_SrcAddrInfo.panID = srcPANId;
05099     wph->MHR_SrcAddrInfo.addr_64 = srcAddr;
05100     frmCtrl->setSecu(secuEnable);
05101     frmCtrl->setFrmPending(pending);
05102     frmCtrl->setAckReq(ackreq);
05103 
05104     HDR_CMN(p)->ptype() = PT_MAC;
05105 
05106     //for trace purpose
05107     HDR_CMN(p)->next_hop_ = p802_15_4macDA(p);      //nam needs the nex_hop information
05108     p802_15_4hdrCommand(p,CmdType);
05109 }
05110 
05111 void Mac802_15_4::log(Packet *p)
05112 {
05113     logtarget_->recv(p, (Handler*) 0);
05114 }
05115 
05116 void Mac802_15_4::resetCounter(int dst)
05117 {
05118     if (txBcnCmd)
05119     if (p802_15_4macDA(txBcnCmd) == dst)
05120         numBcnCmdRetry = 0;
05121 
05122     if (txBcnCmd2)
05123     if (p802_15_4macDA(txBcnCmd2) == dst)
05124         numBcnCmdRetry2 = 0;
05125 
05126     if (txData)
05127     if (p802_15_4macDA(txData) == dst)
05128         numDataRetry = 0;
05129 }
05130 
05131 int Mac802_15_4::command(int argc, const char*const* argv)
05132 {
05133     if (argc == 3)
05134     {
05135         if (strcmp(argv[1], "log-target") == 0)
05136         {
05137             logtarget_ = (NsObject*) TclObject::lookup(argv[2]);
05138             if(logtarget_ == 0)
05139                 return TCL_ERROR;
05140             return TCL_OK;
05141         }
05142     }
05143 
05144     if (strcmp(argv[1], "NodeClr") == 0)
05145     {
05146         changeNodeColor(CURRENT_TIME,argv[2]);
05147         return (TCL_OK);
05148     }
05149 
05150     if (strcmp(argv[1], "NodeLabel") == 0)
05151     {
05152         char label[81];
05153         int i;
05154         strcpy(label,"\"");
05155         strcat(label,argv[2]);
05156         i = 3;
05157         while (i < argc)
05158         {
05159             if (strlen(label) + strlen(argv[i]) < 78)
05160             {
05161                 strcat(label," ");
05162                 strcat(label,argv[i]);
05163             }
05164             else
05165                 break;
05166             i++;
05167         }
05168         strcat(label,"\"");
05169         nam->changeLabel(CURRENT_TIME,label);
05170         return (TCL_OK);
05171     }
05172 
05173     if (strcmp(argv[1], "node-down") == 0)
05174     {
05175         chkAddNFailLink(index_);
05176         changeNodeColor(CURRENT_TIME,Nam802_15_4::def_NodeFail_clr);
05177         if (txAck)
05178         {
05179             Packet::free(txAck);
05180             txAck = 0;
05181         }
05182         if (txBcnCmd)
05183         {
05184             freePkt(txBcnCmd);
05185             txBcnCmd = 0;
05186         }
05187         if (txBcnCmd2)
05188         {
05189             freePkt(txBcnCmd2);
05190             txBcnCmd2 = 0;
05191         }
05192         if (txData)
05193         {
05194             freePkt(txData);
05195             txData = 0;
05196         }
05197         if (phy->rxPacket())
05198             HDR_CMN(phy->rxPacket())->error() = 1;
05199         init(true);     //reset
05200         return (TCL_OK);
05201     }
05202     if (strcmp(argv[1], "node-up") == 0)
05203     {
05204         updateNFailLink(fl_oper_del,index_);
05205         nam->changeBackNodeColor(CURRENT_TIME);
05206         init(true);     //reset
05207         if (callback_)
05208         {
05209             Handler *h = callback_;
05210             callback_ = 0;
05211             h->handle((Event*) 0);
05212         }
05213         return (TCL_OK);
05214     }
05215 
05216     //check if this is actually a SSCS command
05217     if ((argc >= 3)&&(strcmp(argv[1],"sscs") == 0))
05218         return sscs->command(argc,argv);
05219 
05220     int rt = Mac::command(argc, argv);
05221     
05222     //check if Mac::command has already populated netif_
05223     if (netif_)
05224     if (phy == NULL)    //only execute once
05225     {
05226         phy = (Phy802_15_4 *)netif_;
05227         phy->macObj(this);
05228         csmaca = new CsmaCA802_15_4(phy,this);
05229         assert(csmaca);
05230     }
05231 
05232     return rt;
05233 }
05234 
05235 void Mac802_15_4::changeNodeColor(double atTime,const char *newColor,bool save)
05236 {
05237     nam->changeNodeColor(atTime,newColor,save);
05238     nam->changeNodeColor(atTime+0.030001,newColor,false);   
05239 }
05240 
05241 void Mac802_15_4::txBcnCmdDataHandler(void)
05242 {
05243     int i;
05244 
05245     if (taskP.taskStatus(TP_mlme_scan_request))
05246     if (txBcnCmd2 != txCsmaca)
05247         return;         //terminate all other transmissions (will resume afte channel scan)
05248 
05249     if (HDR_LRWPAN(txCsmaca)->indirect)
05250     {
05251         i = updateTransacLinkByPktOrHandle(tr_oper_est,&transacLink1,&transacLink2,txCsmaca);
05252         if (i != 0) //transaction expired
05253         {
05254             resetTRX();
05255             if (txBcnCmd == txCsmaca)
05256                 txBcnCmd = 0;
05257             else if (txBcnCmd2 == txCsmaca)
05258                 txBcnCmd2 = 0;
05259             else if (txData == txCsmaca)
05260                 txData = 0;
05261             //Packet::free(txCsmaca);   //don't do this, since the packet will be automatically deleted when expired
05262             csmacaResume();
05263             return;
05264         }
05265     }
05266 
05267     if (txBcnCmd == txCsmaca)
05268     {
05269 #ifdef DEBUG802_15_4
05270         FrameCtrl frmCtrl;
05271         frmCtrl.FrmCtrl = HDR_LRWPAN(txBcnCmd)->MHR_FrmCtrl;
05272         frmCtrl.parse();
05273         /*
05274         char frm_type[21];
05275         if (frmCtrl.frmType == defFrmCtrl_Type_Beacon)
05276             strcpy(frm_type,"BEACON");
05277         else
05278             sprintf(frm_type,"COMMAND_%d",HDR_LRWPAN(txBcnCmd)->MSDU_CmdType);
05279         */
05280         fprintf(stdout,"[%s::%s][%f](node %d) transmit %s to %d: SN = %d, uid = %d, mac_uid = %ld\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(txBcnCmd),p802_15_4macDA(txBcnCmd),HDR_LRWPAN(txBcnCmd)->MHR_BDSN,HDR_CMN(txBcnCmd)->uid(),HDR_LRWPAN(txBcnCmd)->uid);
05281 #endif
05282         txPkt = txBcnCmd;
05283         HDR_CMN(txBcnCmd)->direction() = hdr_cmn::DOWN;
05284         sendDown(txBcnCmd->copy(), this);       
05285     }
05286     else if (txBcnCmd2 == txCsmaca)
05287     {
05288 #ifdef DEBUG802_15_4
05289         FrameCtrl frmCtrl2;
05290         frmCtrl2.FrmCtrl = HDR_LRWPAN(txBcnCmd2)->MHR_FrmCtrl;
05291         frmCtrl2.parse();
05292         /*
05293         char frm_type2[21];
05294         if (frmCtrl2.frmType == defFrmCtrl_Type_Beacon)
05295             strcpy(frm_type2,"BEACON");
05296         else
05297             sprintf(frm_type2,"COMMAND_%d",HDR_LRWPAN(txBcnCmd2)->MSDU_CmdType);
05298         */
05299         fprintf(stdout,"[%s::%s][%f](node %d) transmit %s to %d: SN = %d, uid = %d, mac_uid = %ld\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(txBcnCmd2),p802_15_4macDA(txBcnCmd2),HDR_LRWPAN(txBcnCmd2)->MHR_BDSN,HDR_CMN(txBcnCmd2)->uid(),HDR_LRWPAN(txBcnCmd2)->uid);
05300 #endif
05301         txPkt = txBcnCmd2;
05302         HDR_CMN(txBcnCmd2)->direction() = hdr_cmn::DOWN;
05303         sendDown(txBcnCmd2->copy(), this);      
05304     }
05305     else if (txData == txCsmaca)
05306     {
05307 #ifdef DEBUG802_15_4
05308         fprintf(stdout,"[%s::%s][%f](node %d) transmit DATA (%s) to %d: SN = %d, uid = %d, mac_uid = %ld\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,wpan_pName(txData),p802_15_4macDA(txData),HDR_LRWPAN(txData)->MHR_BDSN,HDR_CMN(txData)->uid(),HDR_LRWPAN(txData)->uid);
05309 #endif
05310         txPkt = txData;
05311         HDR_CMN(txData)->direction() = hdr_cmn::DOWN;
05312         sendDown(txData->copy(), this);     
05313     }
05314 }
05315 
05316 void Mac802_15_4::IFSHandler(void)
05317 {
05318     hdr_lrwpan* wph;
05319     hdr_cmn* ch;
05320     FrameCtrl frmCtrl;
05321     Packet *pendPkt;
05322     MACenum status;
05323     int i;
05324 
05325     assert(rxData||rxCmd);
05326 
05327     if (rxCmd)
05328     {
05329         wph = HDR_LRWPAN(rxCmd);
05330         frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
05331         frmCtrl.parse();
05332 
05333         if (wph->MSDU_CmdType == 0x01)      //Association request
05334             sscs->MLME_ASSOCIATE_indication(wph->MHR_SrcAddrInfo.addr_64,wph->MSDU_Payload[0],frmCtrl.secu,0);  //ACL ignored in simulation
05335         else if (wph->MSDU_CmdType == 0x02) //Association response
05336         {
05337             status = (*(MACenum *)(wph->MSDU_Payload + 2));
05338             //save the short address (if association successful)
05339             if (status == m_SUCCESS)
05340                 mpib.macShortAddress = *((UINT_16 *)wph->MSDU_Payload);
05341             dispatch(p_SUCCESS,__FUNCTION__,p_SUCCESS,status);
05342         }
05343         else if (wph->MSDU_CmdType == 0x04) //Data request
05344         {
05345             //Continue to send pending packet (an ack. already sent).
05346             //In implementation, we may not have enough time to check if packets pending. If this is the case,
05347             //then the pending flag in the ack. should be set to 1, and then send a zero-length data packet
05348             //if later it turns out there is no packet actually pending.
05349             //In simulation, we assume having enough time to determine the pending status -- so zero-length packet will never be sent.
05350             //(refer to page 155, line 46-50)
05351             i = updateTransacLink(tr_oper_EST,&transacLink1,&transacLink2,frmCtrl.srcAddrMode,wph->MHR_SrcAddrInfo.addr_64);
05352             if (i != 0)
05353             {
05354                 i = updateTransacLink(tr_oper_est,&transacLink1,&transacLink2,frmCtrl.srcAddrMode,wph->MHR_SrcAddrInfo.addr_64);
05355                 i = (i == 0)?1:0;
05356             }
05357             else    //more than one packet pending
05358             {
05359                 i = 2;
05360             }
05361             if (i > 0)  //packet(s) pending
05362             {
05363                 pendPkt = getPktFrTransacLink(&transacLink1,frmCtrl.srcAddrMode,wph->MHR_SrcAddrInfo.addr_64);
05364                 wph = HDR_LRWPAN(pendPkt);
05365                 wph->indirect = true;
05366                 frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
05367                 frmCtrl.parse();
05368                 frmCtrl.setFrmPending(i>1);     //more packet pending?
05369                 wph->MHR_FrmCtrl = frmCtrl.FrmCtrl;
05370                 HDR_CMN(pendPkt)->direction() = hdr_cmn::DOWN;
05371                 if (frmCtrl.frmType == defFrmCtrl_Type_MacCmd)
05372                 {
05373                     if (txBcnCmd == pendPkt)    //it's being processed
05374                     {
05375                         Packet::free(rxCmd);    //we logged the command packet before, here just free it
05376                         rxCmd = 0;
05377                         return;
05378                     }
05379 #ifdef DEBUG802_15_4
05380                     fprintf(stdout,"[%s::%s][%f](node %d) before assign txBcnCmd:\n\t\ttxBeacon\t= %ld\n\t\ttxAck   \t= %ld\n\t\ttxBcnCmd\t= %ld\n\t\ttxBcnCmd2\t= %ld\n\t\ttxData  \t= %ld\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,txBeacon,txAck,txBcnCmd,txBcnCmd2,txData);
05381 #endif
05382                     assert(!txBcnCmd);      //we couldn't receive the data request command if we are processing txBcnCmd
05383                     txBcnCmd = pendPkt->refcopy();  
05384                     waitBcnCmdAck = false;
05385                     numBcnCmdRetry = 0;
05386 
05387                 }
05388                 else if (frmCtrl.frmType == defFrmCtrl_Type_Data)
05389                 {
05390                     if (txData == pendPkt)      //it's being processed
05391                     {
05392                         Packet::free(rxCmd);    //we logged the command packet before, here just free it
05393                         rxCmd = 0;
05394                         return;
05395                     }
05396 #ifdef DEBUG802_15_4
05397                     fprintf(stdout,"[%s::%s][%f](node %d) before assign txData:\n\t\ttxBeacon\t= %ld\n\t\ttxAck   \t= %ld\n\t\ttxBcnCmd\t= %ld\n\t\ttxBcnCmd2\t= %ld\n\t\ttxData  \t= %ld\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,txBeacon,txAck,txBcnCmd,txBcnCmd2,txData);
05398 #endif
05399                     assert(!txData);        //we couldn't receive the data request command if we are processing txData
05400                     txData = pendPkt->refcopy();    
05401                     waitDataAck = false;
05402                     numDataRetry = 0;
05403                 }
05404                 //there are two ways to transmit the pending packet for the first time (refer to page 156), w/o or w/ CSMA-CA,
05405                 if (canProceedWOcsmaca(pendPkt))
05406                 {
05407                     //change task field "frFunc"
05408                     if(taskP.taskStatus(TP_mcps_data_request))
05409                     {
05410                          if (strcmp(taskP.taskFrFunc(TP_mcps_data_request),"csmacaCallBack") == 0)
05411                             strcpy(taskP.taskFrFunc(TP_mcps_data_request),"PD_DATA_confirm");
05412                     }
05413                     else if (taskP.taskStatus(TP_mlme_associate_response))
05414                     {
05415                          if (strcmp(taskP.taskFrFunc(TP_mlme_associate_response),"csmacaCallBack") == 0)
05416                             strcpy(taskP.taskFrFunc(TP_mlme_associate_response),"PD_DATA_confirm");
05417                          //else     //other commands using indirect transmission (may  be none): TBD
05418                     }
05419                     txCsmaca = pendPkt;
05420                     plme_set_trx_state_request(p_TX_ON);
05421                 }
05422                 else
05423                 {
05424                     csmacaResume();
05425                 }
05426             }
05427             //else      //may need to send a zero-length packet in implementation
05428         }
05429         else if (wph->MSDU_CmdType == 0x08) //Coordinator realignment
05430         {
05431             mpib.macPANId = *((UINT_16 *)wph->MSDU_Payload);
05432             mpib.macCoordShortAddress = *((UINT_16 *)wph->MSDU_Payload + 2);
05433             tmp_ppib.phyCurrentChannel = wph->MSDU_Payload[4];
05434             phy->PLME_SET_request(phyCurrentChannel,&tmp_ppib);
05435             mpib.macShortAddress = *((UINT_16 *)wph->MSDU_Payload + 5);
05436             dispatch(p_SUCCESS,__FUNCTION__);
05437         }
05438         Packet::free(rxCmd);    //we logged the command packet before, here just free it
05439         rxCmd = 0;
05440     }
05441     else if (rxData)
05442     {
05443         wph = HDR_LRWPAN(rxData);
05444         ch = HDR_CMN(rxData);
05445         frmCtrl.FrmCtrl = wph->MHR_FrmCtrl;
05446         frmCtrl.parse();
05447 
05448         if (taskP.taskStatus(TP_mlme_poll_request))
05449             dispatch(p_SUCCESS,__FUNCTION__,p_SUCCESS,status);
05450         //else  //do nothing
05451         //the data waiting timer in data polling expired and the upper layer confirmed
05452         //with a status NO_DATA -- but we see no reason not to continue passing this data
05453         //packet to upper layer (note that the ack. has already been sent to data source -- 
05454         //we shouldn't drop the data packet here).
05455 
05456         //strip off the MAC sublayer header
05457         ch->size() -= macHeaderLen(wph->MHR_FrmCtrl);
05458         MCPS_DATA_indication(frmCtrl.srcAddrMode,wph->MHR_SrcAddrInfo.panID,wph->MHR_SrcAddrInfo.addr_64,
05459                     frmCtrl.dstAddrMode,wph->MHR_DstAddrInfo.panID,wph->MHR_DstAddrInfo.addr_64,
05460                     ch->size(),rxData,wph->ppduLinkQuality,
05461                     wph->SecurityUse,wph->ACLEntry);
05462         rxData = 0;
05463     }
05464 }
05465 
05466 void Mac802_15_4::backoffBoundHandler(void)
05467 {
05468     if (!beaconWaiting)
05469     if (txAck)      //<txAck> may have been cancelled by <macBeaconRxTimer>
05470     {
05471 #ifdef DEBUG802_15_4
05472         fprintf(stdout,"[%s::%s][%f](node %d) transmit M_ACK to %d: SN = %d, uid = %d, mac_uid = %ld\n",__FILE__,__FUNCTION__,CURRENT_TIME,index_,p802_15_4macDA(txAck),HDR_LRWPAN(txAck)->MHR_BDSN,HDR_CMN(txAck)->uid(),HDR_LRWPAN(txAck)->uid);
05473 #endif
05474         txPkt = txAck;
05475         HDR_CMN(txAck)->direction() = hdr_cmn::DOWN;
05476         sendDown(txAck->refcopy(), this);
05477     }
05478 }
05479 
05480 // End of file: p802_15_4mac.cc

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